commit 42bb2a655fe8b1a894bc658dfd173b25ef80b866 Author: Vehicle Researcher Date: Sun Oct 5 09:02:49 2025 +0000 openpilot v0.10.1 release date: 2025-10-05T09:02:48 master commit: 31801a73121b729d11a7dd4a7ccd9698f4d8fc92 diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..631ea04840 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +**/.git +.DS_Store +*.dylib +*.DSYM +*.d +*.pyc +*.pyo +.*.swp +.*.swo +.*.un~ +*.tmp +*.o +*.o-* +*.os +*.os-* + +venv/ +.venv/ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..d506433ece --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,pyx,pxd}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..47eb6c216f --- /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/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..6efdc059a5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: Car bug report + url: https://github.com/commaai/opendbc/issues/new + about: For issues with a particular car make or model + - name: Join the Discord + url: https://discord.comma.ai + about: The community Discord is for both openpilot development and experience discussion + - name: Report driving behavior feedback + url: https://discord.com/channels/469524606043160576/1254834193066623017 + about: Feedback for the driving and driver monitoring models goes in the #driving-feedback in Discord + - name: Community Wiki + url: https://github.com/commaai/openpilot/wiki + about: Check out our community wiki diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 0000000000..330b9b1101 --- /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 0000000000..761c8b1a0a --- /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 24.04 + validations: + required: true + + - type: input + id: version + attributes: + label: openpilot version or commit + placeholder: bd36f2ec8d3559909678eff2690c10a520938367 + validations: + required: false + + - type: textarea + attributes: + label: Additional info + diff --git a/.github/labeler.yaml b/.github/labeler.yaml new file mode 100644 index 0000000000..127a04e9e4 --- /dev/null +++ b/.github/labeler.yaml @@ -0,0 +1,27 @@ +CI / testing: + - changed-files: + - any-glob-to-all-files: "{.github/**,**/test_*,**/test/**,Jenkinsfile}" + +car: + - changed-files: + - any-glob-to-all-files: '{selfdrive/car/**,opendbc_repo}' + +simulation: + - changed-files: + - any-glob-to-all-files: 'tools/sim/**' + +ui: + - changed-files: + - any-glob-to-all-files: '{selfdrive/ui/**,system/ui/**}' + +tools: + - changed-files: + - any-glob-to-all-files: 'tools/**' + +multilanguage: + - changed-files: + - any-glob-to-all-files: 'selfdrive/ui/translations/**' + +autonomy: + - changed-files: + - any-glob-to-all-files: "{selfdrive/modeld/models/**,selfdrive/test/process_replay/model_replay_ref_commit}" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..2b4a5ed48f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,68 @@ + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..0832b3964e --- /dev/null +++ b/.gitignore @@ -0,0 +1,96 @@ +venv/ +.venv/ +.ci_cache +.env +.clang-format +.DS_Store +.tags +.ipynb_checkpoints +.idea +.overlay_init +.overlay_consistent +.sconsign.dblite +a.out +.hypothesis +.cache/ + +/docs_site/ + +*.mp4 +*.dylib +*.DSYM +*.d +*.pyc +*.pyo +.*.swp +.*.swo +.*.un~ +*.tmp +*.o +*.o-* +*.os +*.os-* +*.so +*.a +*.clb +*.class +*.pyxbldc +*.vcd +*.qm +*_pyx.cpp +config.json +clcache +compile_commands.json +compare_runtime*.html + +selfdrive/pandad/pandad +cereal/services.h +cereal/gen +cereal/messaging/bridge +selfdrive/ui/translations/tmp +selfdrive/car/tests/cars_dump +system/camerad/camerad +system/camerad/test/ae_gray_test + +.coverage* +coverage.xml +htmlcov +pandaextra + +.mypy_cache/ +flycheck_* + +cppcheck_report.txt +comma*.sh + +selfdrive/modeld/models/*.pkl + +# openpilot log files +*.bz2 +*.zst + +build/ + +!**/.gitkeep + +poetry.toml +Pipfile + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..458312fc88 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "ms-python.python", + "ms-vscode.cpptools", + "elagil.pre-commit-helper", + "charliermarsh.ruff", + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000000..f090061c42 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,85 @@ +{ + "version": "0.2.0", + "inputs": [ + { + "id": "python_process", + "type": "pickString", + "description": "Select the process to debug", + "options": [ + "selfdrive/controls/controlsd.py", + "system/timed/timed.py", + "tools/sim/run_bridge.py" + ] + }, + { + "id": "cpp_process", + "type": "pickString", + "description": "Select the process to debug", + "options": [ + "selfdrive/ui/ui" + ] + }, + { + "id": "args", + "description": "Arguments to pass to the process", + "type": "promptString" + }, + { + "id": "replayArg", + "type": "promptString", + "description": "Enter route or segment to replay." + } + ], + "configurations": [ + { + "name": "Python: openpilot Process", + "type": "debugpy", + "request": "launch", + "program": "${input:python_process}", + "console": "integratedTerminal", + "justMyCode": true, + "args": "${input:args}" + }, + { + "name": "C++: openpilot Process", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/${input:cpp_process}", + "cwd": "${workspaceFolder}" + }, + { + "name": "Attach LLDB to Replay drive", + "type": "lldb", + "request": "attach", + "pid": "${command:pickMyProcess}", + "initCommands": [ + "script import time; time.sleep(3)" + ] + }, + { + "name": "Replay drive", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/opendbc/safety/tests/safety_replay/replay_drive.py", + "args": [ + "${input:replayArg}" + ], + "console": "integratedTerminal", + "justMyCode": false, + "env": { + "PYTHONPATH": "${workspaceFolder}" + }, + "subProcess": true, + "stopOnEntry": false + } + ], + "compounds": [ + { + "name": "Replay drive + Safety LLDB", + "configurations": [ + "Replay drive", + "Attach LLDB to Replay drive" + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..f0731c362d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,27 @@ +{ + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.renderWhitespace": "trailing", + "files.trimTrailingWhitespace": true, + "search.exclude": { + "**/.git": true, + "**/.venv": true, + "**/__pycache__": true + }, + "files.exclude": { + "**/.git": true, + "**/.venv": true, + "**/__pycache__": true + }, + "python.analysis.exclude": [ + "**/.git", + "**/.venv", + "**/__pycache__", + // exclude directories that should be using the symlinked version + "common/**", + "selfdrive/**", + "system/**", + "third_party/**", + "tools/**", + ] +} diff --git a/Dockerfile.openpilot b/Dockerfile.openpilot new file mode 100644 index 0000000000..106a06e3a2 --- /dev/null +++ b/Dockerfile.openpilot @@ -0,0 +1,14 @@ +FROM ghcr.io/commaai/openpilot-base:latest + +ENV PYTHONUNBUFFERED=1 + +ENV OPENPILOT_PATH=/home/batman/openpilot + +RUN mkdir -p ${OPENPILOT_PATH} +WORKDIR ${OPENPILOT_PATH} + +COPY . ${OPENPILOT_PATH}/ + +ENV UV_BIN="/home/batman/.local/bin/" +ENV PATH="$UV_BIN:$PATH" +RUN UV_PROJECT_ENVIRONMENT=$VIRTUAL_ENV uv run scons --cache-readonly -j$(nproc) diff --git a/Dockerfile.openpilot_base b/Dockerfile.openpilot_base new file mode 100644 index 0000000000..44d8d95e95 --- /dev/null +++ b/Dockerfile.openpilot_base @@ -0,0 +1,81 @@ +FROM ubuntu:24.04 + +ENV PYTHONUNBUFFERED=1 + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && \ + apt-get install -y --no-install-recommends sudo tzdata locales ssh pulseaudio xvfb x11-xserver-utils gnome-screenshot python3-tk python3-dev && \ + rm -rf /var/lib/apt/lists/* + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG=en_US.UTF-8 +ENV LANGUAGE=en_US:en +ENV LC_ALL=en_US.UTF-8 + +COPY tools/install_ubuntu_dependencies.sh /tmp/tools/ +RUN /tmp/tools/install_ubuntu_dependencies.sh && \ + rm -rf /var/lib/apt/lists/* /tmp/* && \ + cd /usr/lib/gcc/arm-none-eabi/* && \ + rm -rf arm/ thumb/nofp thumb/v6* thumb/v8* thumb/v7+fp thumb/v7-r+fp.sp + +# Add OpenCL +RUN apt-get update && apt-get install -y --no-install-recommends \ + apt-utils \ + alien \ + unzip \ + tar \ + curl \ + xz-utils \ + dbus \ + gcc-arm-none-eabi \ + tmux \ + vim \ + libx11-6 \ + wget \ + && rm -rf /var/lib/apt/lists/* + +RUN mkdir -p /tmp/opencl-driver-intel && \ + cd /tmp/opencl-driver-intel && \ + wget https://github.com/intel/llvm/releases/download/2024-WW14/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \ + wget https://github.com/oneapi-src/oneTBB/releases/download/v2021.12.0/oneapi-tbb-2021.12.0-lin.tgz && \ + mkdir -p /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \ + cd /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \ + tar -zxvf /tmp/opencl-driver-intel/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \ + mkdir -p /etc/OpenCL/vendors && \ + echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64/libintelocl.so > /etc/OpenCL/vendors/intel_expcpu.icd && \ + cd /opt/intel && \ + tar -zxvf /tmp/opencl-driver-intel/oneapi-tbb-2021.12.0-lin.tgz && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so.12 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so.2 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \ + mkdir -p /etc/ld.so.conf.d && \ + echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 > /etc/ld.so.conf.d/libintelopenclexp.conf && \ + ldconfig -f /etc/ld.so.conf.d/libintelopenclexp.conf && \ + cd / && \ + rm -rf /tmp/opencl-driver-intel + +ENV NVIDIA_VISIBLE_DEVICES=all +ENV NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute +ENV QTWEBENGINE_DISABLE_SANDBOX=1 + +RUN dbus-uuidgen > /etc/machine-id + +ARG USER=batman +ARG USER_UID=1001 +RUN useradd -m -s /bin/bash -u $USER_UID $USER +RUN usermod -aG sudo $USER +RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers +USER $USER + +COPY --chown=$USER pyproject.toml uv.lock /home/$USER +COPY --chown=$USER tools/install_python_dependencies.sh /home/$USER/tools/ + +ENV VIRTUAL_ENV=/home/$USER/.venv +ENV PATH="$VIRTUAL_ENV/bin:$PATH" +RUN cd /home/$USER && \ + tools/install_python_dependencies.sh && \ + rm -rf tools/ pyproject.toml uv.lock .cache + +USER root +RUN sudo git config --global --add safe.directory /tmp/openpilot diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..ad8e85136b --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,269 @@ +def retryWithDelay(int maxRetries, int delay, Closure body) { + for (int i = 0; i < maxRetries; i++) { + try { + return body() + } catch (Exception e) { + sleep(delay) + } + } + throw Exception("Failed after ${maxRetries} retries") +} + +def device(String ip, String step_label, String cmd) { + withCredentials([file(credentialsId: 'id_rsa', variable: 'key_file')]) { + def ssh_cmd = """ +ssh -o ConnectTimeout=5 -o ServerAliveInterval=5 -o ServerAliveCountMax=2 -o BatchMode=yes -o StrictHostKeyChecking=no -i ${key_file} 'comma@${ip}' exec /usr/bin/bash <<'END' + +set -e + +export TERM=xterm-256color + +shopt -s huponexit # kill all child processes when the shell exits + +export CI=1 +export PYTHONWARNINGS=error +export LOGPRINT=debug +export TEST_DIR=${env.TEST_DIR} +export SOURCE_DIR=${env.SOURCE_DIR} +export GIT_BRANCH=${env.GIT_BRANCH} +export GIT_COMMIT=${env.GIT_COMMIT} +export CI_ARTIFACTS_TOKEN=${env.CI_ARTIFACTS_TOKEN} +export GITHUB_COMMENTS_TOKEN=${env.GITHUB_COMMENTS_TOKEN} +export AZURE_TOKEN='${env.AZURE_TOKEN}' +# only use 1 thread for tici tests since most require HIL +export PYTEST_ADDOPTS="-n0 -s" + + +export GIT_SSH_COMMAND="ssh -i /data/gitkey" + +source ~/.bash_profile +if [ -f /TICI ]; then + source /etc/profile + + rm -rf /tmp/tmp* + rm -rf ~/.commacache + rm -rf /dev/shm/* + rm -rf /dev/tmp/tmp* + + if ! systemctl is-active --quiet systemd-resolved; then + echo "restarting resolved" + sudo systemctl start systemd-resolved + sleep 3 + fi + + # restart aux USB + if [ -e /sys/bus/usb/drivers/hub/3-0:1.0 ]; then + echo "restarting aux usb" + echo "3-0:1.0" | sudo tee /sys/bus/usb/drivers/hub/unbind + sleep 0.5 + echo "3-0:1.0" | sudo tee /sys/bus/usb/drivers/hub/bind + fi +fi +if [ -f /data/openpilot/launch_env.sh ]; then + source /data/openpilot/launch_env.sh +fi + +ln -snf ${env.TEST_DIR} /data/pythonpath + +cd ${env.TEST_DIR} || true +time ${cmd} +END""" + + sh script: ssh_cmd, label: step_label + } +} + +def deviceStage(String stageName, String deviceType, List extra_env, def steps) { + stage(stageName) { + if (currentBuild.result != null) { + return + } + + if (isReplay()) { + error("REPLAYING TESTS IS NOT ALLOWED. FIX THEM INSTEAD.") + } + + def extra = extra_env.collect { "export ${it}" }.join('\n'); + def branch = env.BRANCH_NAME ?: 'master'; + def gitDiff = sh returnStdout: true, script: 'curl -s -H "Authorization: Bearer ${GITHUB_COMMENTS_TOKEN}" https://api.github.com/repos/commaai/openpilot/compare/master...${GIT_BRANCH} | jq .files[].filename || echo "/"', label: 'Getting changes' + + lock(resource: "", label: deviceType, inversePrecedence: true, variable: 'device_ip', quantity: 1, resourceSelectStrategy: 'random') { + docker.image('ghcr.io/commaai/alpine-ssh').inside('--user=root') { + timeout(time: 35, unit: 'MINUTES') { + retry (3) { + def date = sh(script: 'date', returnStdout: true).trim(); + device(device_ip, "set time", "date -s '" + date + "'") + device(device_ip, "git checkout", extra + "\n" + readFile("selfdrive/test/setup_device_ci.sh")) + } + steps.each { item -> + def name = item[0] + def cmd = item[1] + + def args = item[2] + def diffPaths = args.diffPaths ?: [] + def cmdTimeout = args.timeout ?: 9999 + + if (branch != "master" && !branch.contains("__jenkins_loop_") && diffPaths && !hasPathChanged(gitDiff, diffPaths)) { + println "Skipping ${name}: no changes in ${diffPaths}." + return + } else { + timeout(time: cmdTimeout, unit: 'SECONDS') { + device(device_ip, name, cmd) + } + } + } + } + } + } + } +} + +def hasPathChanged(String gitDiff, List paths) { + for (path in paths) { + if (gitDiff.contains(path)) { + return true + } + } + return false +} + +def isReplay() { + def replayClass = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause" + return currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replayClass) } +} + +def setupCredentials() { + withCredentials([ + string(credentialsId: 'azure_token', variable: 'AZURE_TOKEN'), + ]) { + env.AZURE_TOKEN = "${AZURE_TOKEN}" + } + + withCredentials([ + string(credentialsId: 'ci_artifacts_pat', variable: 'CI_ARTIFACTS_TOKEN'), + ]) { + env.CI_ARTIFACTS_TOKEN = "${CI_ARTIFACTS_TOKEN}" + } + + withCredentials([ + string(credentialsId: 'post_comments_github_pat', variable: 'GITHUB_COMMENTS_TOKEN'), + ]) { + env.GITHUB_COMMENTS_TOKEN = "${GITHUB_COMMENTS_TOKEN}" + } +} + +def step(String name, String cmd, Map args = [:]) { + return [name, cmd, args] +} + +node { + env.CI = "1" + env.PYTHONWARNINGS = "error" + env.TEST_DIR = "/data/openpilot" + env.SOURCE_DIR = "/data/openpilot_source/" + setupCredentials() + + env.GIT_BRANCH = checkout(scm).GIT_BRANCH + env.GIT_COMMIT = checkout(scm).GIT_COMMIT + + def excludeBranches = ['__nightly', 'devel', 'devel-staging', 'release3', 'release3-staging', + 'release-tici', 'release-tizi', 'testing-closet*', 'hotfix-*'] + def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*') + + if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) { + properties([ + disableConcurrentBuilds(abortPrevious: true) + ]) + } + + try { + if (env.BRANCH_NAME == 'devel-staging') { + deviceStage("build release3-staging", "tizi-needs-can", [], [ + step("build release3-staging", "RELEASE_BRANCH=release3-staging $SOURCE_DIR/release/build_release.sh"), + ]) + } + + if (env.BRANCH_NAME == '__nightly') { + parallel ( + 'nightly': { + deviceStage("build nightly", "tizi-needs-can", [], [ + step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"), + ]) + }, + 'nightly-dev': { + deviceStage("build nightly-dev", "tizi-needs-can", [], [ + step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"), + ]) + }, + ) + } + + if (!env.BRANCH_NAME.matches(excludeRegex)) { + parallel ( + 'onroad tests': { + deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [ + step("build openpilot", "cd system/manager && ./build.py"), + step("check dirty", "release/check-dirty.sh"), + step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]), + ]) + }, + 'HW + Unit Tests': { + deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [ + step("build", "cd system/manager && ./build.py"), + step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]), + step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"), + step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]), + step("test manager", "pytest system/manager/test/test_manager.py"), + ]) + }, + 'loopback': { + deviceStage("loopback", "tizi-loopback", ["UNSAFE=1"], [ + step("build openpilot", "cd system/manager && ./build.py"), + step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"), + ]) + }, + 'camerad OX03C10': { + deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [ + step("build", "cd system/manager && ./build.py"), + step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]), + step("test exposure", "pytest system/camerad/test/test_exposure.py"), + ]) + }, + 'camerad OS04C10': { + deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [ + step("build", "cd system/manager && ./build.py"), + step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]), + step("test exposure", "pytest system/camerad/test/test_exposure.py"), + ]) + }, + 'sensord': { + deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [ + step("build", "cd system/manager && ./build.py"), + step("test sensord", "pytest system/sensord/tests/test_sensord.py"), + ]) + }, + 'replay': { + deviceStage("model-replay", "tizi-replay", ["UNSAFE=1"], [ + step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]), + step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]), + ]) + }, + 'tizi': { + deviceStage("tizi", "tizi", ["UNSAFE=1"], [ + step("build openpilot", "cd system/manager && ./build.py"), + step("test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"), + step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"), + step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"), + // TODO: enable once new AGNOS is available + // step("test esim", "pytest system/hardware/tici/tests/test_esim.py"), + step("test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py", [diffPaths: ["system/qcomgpsd/"]]), + ]) + }, + + ) + } + } catch (Exception e) { + currentBuild.result = 'FAILED' + throw e + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..7dafa9443b --- /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 0000000000..9f1819afbf --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +
+ +

openpilot

+ +

+ openpilot is an operating system for robotics. +
+ Currently, it upgrades the driver assistance system in 300+ supported cars. +

+ +

+ Docs + · + Roadmap + · + Contribute + · + Community + · + Try it on a comma 3X +

+ +Quick start: `bash <(curl -fsSL openpilot.comma.ai)` + +[![openpilot tests](https://github.com/commaai/openpilot/actions/workflows/selfdrive_tests.yaml/badge.svg)](https://github.com/commaai/openpilot/actions/workflows/selfdrive_tests.yaml) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +[![X Follow](https://img.shields.io/twitter/follow/comma_ai)](https://x.com/comma_ai) +[![Discord](https://img.shields.io/discord/469524606043160576)](https://discord.comma.ai) + +
+ + + + + + + +
+ + +Using openpilot in a car +------ + +To use openpilot in a car, you need four things: +1. **Supported Device:** a comma 3X, available at [comma.ai/shop](https://comma.ai/shop/comma-3x). +2. **Software:** The setup procedure for the comma 3X allows users to enter a URL for custom software. Use the URL `openpilot.comma.ai` to install the release version. +3. **Supported Car:** Ensure that you have one of [the 275+ supported cars](docs/CARS.md). +4. **Car Harness:** You will also need a [car harness](https://comma.ai/shop/car-harness) to connect your comma 3X to your car. + +We have detailed instructions for [how to install the harness and device in a car](https://comma.ai/setup). Note that it's possible to run openpilot on [other hardware](https://blog.comma.ai/self-driving-car-for-free/), although it's not plug-and-play. + +### Branches +| branch | URL | description | +|------------------|----------------------------------------|-------------------------------------------------------------------------------------| +| `release3` | openpilot.comma.ai | This is openpilot's release branch. | +| `release3-staging` | openpilot-test.comma.ai | This is the staging branch for releases. Use it to get new releases slightly early. | +| `nightly` | openpilot-nightly.comma.ai | This is the bleeding edge development branch. Do not expect this to be stable. | +| `nightly-dev` | installer.comma.ai/commaai/nightly-dev | Same as nightly, but includes experimental development features for some cars. | + +To start developing openpilot +------ + +openpilot is developed by [comma](https://comma.ai/) and by users like you. We welcome both pull requests and issues on [GitHub](http://github.com/commaai/openpilot). + +* Join the [community Discord](https://discord.comma.ai) +* Check out [the contributing docs](docs/CONTRIBUTING.md) +* Check out the [openpilot tools](tools/) +* Code documentation lives at https://docs.comma.ai +* Information about running openpilot lives on the [community wiki](https://github.com/commaai/openpilot/wiki) + +Want to get paid to work on openpilot? [comma is hiring](https://comma.ai/jobs#open-positions) and offers lots of [bounties](https://comma.ai/bounties) for external contributors. + +Safety and Testing +---- + +* openpilot observes [ISO26262](https://en.wikipedia.org/wiki/ISO_26262) guidelines, see [SAFETY.md](docs/SAFETY.md) for more details. +* openpilot has software-in-the-loop [tests](.github/workflows/selfdrive_tests.yaml) that run on every commit. +* The code enforcing the safety model lives in panda and is written in C, see [code rigor](https://github.com/commaai/panda#code-rigor) for more details. +* panda has software-in-the-loop [safety tests](https://github.com/commaai/panda/tree/master/tests/safety). +* Internally, we have a hardware-in-the-loop Jenkins test suite that builds and unit tests the various processes. +* panda has additional hardware-in-the-loop [tests](https://github.com/commaai/panda/blob/master/Jenkinsfile). +* We run the latest openpilot in a testing closet containing 10 comma devices continuously replaying routes. + +
+MIT Licensed + +openpilot is released under the MIT license. Some parts of the software are released under other licenses as specified. + +Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys’ fees and costs) which arise out of, relate to or result from any use of this software by user. + +**THIS IS ALPHA QUALITY SOFTWARE FOR RESEARCH PURPOSES ONLY. THIS IS NOT A PRODUCT. +YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS. +NO WARRANTY EXPRESSED OR IMPLIED.** +
+ +
+User Data and comma Account + +By default, openpilot uploads the driving data to our servers. You can also access your data through [comma connect](https://connect.comma.ai/). We use your data to train better models and improve openpilot for everyone. + +openpilot is open source software: the user is free to disable data collection if they wish to do so. + +openpilot logs the road-facing cameras, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs. +The driver-facing camera and microphone are only logged if you explicitly opt-in in settings. + +By using openpilot, you agree to [our Privacy Policy](https://comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data. +
diff --git a/RELEASES.md b/RELEASES.md new file mode 100644 index 0000000000..568be6c353 --- /dev/null +++ b/RELEASES.md @@ -0,0 +1,1088 @@ +Version 0.10.1 (2025-09-08) +======================== +* New driving model #36114 + * World Model: removed global localization inputs + * World Model: 2x the number of parameters + * World Model: trained on 4x the number of segments + * VAE Compression Model: new architecture and training objective + * Driving Vision Model: trained on 4x the number of segments +* New Driver Monitoring model #36198 +* Acura TLX 2021 support thanks to MVL! +* Honda City 2023 support thanks to vanillagorillaa and drFritz! +* Honda N-Box 2018 support thanks to miettal! +* Honda Odyssey 2021-25 support thanks to csouers and MVL! +* Honda Passport 2026 support thanks to vanillagorillaa and MVL! + +Version 0.10.0 (2025-08-05) +======================== +* New driving model + * New training architecture + * Described in our CVPR paper: "Learning to Drive from a World Model" + * Longitudinal MPC replaced by E2E planning from World Model in Experimental Mode + * Action from lateral MPC as training objective replaced by E2E planning from World Model + * Low-speed lead car ground-truth fixes +* Enable live-learned steering actuation delay +* Opt-in audio recording for dashcam video +* Acura MDX 2025 support thanks to vanillagorillaa and MVL! +* Honda Accord 2023-25 support thanks to vanillagorillaa and MVL! +* Honda CR-V 2023-25 support thanks to vanillagorillaa and MVL! +* Honda Pilot 2023-25 support thanks to vanillagorillaa and MVL! + +Version 0.9.9 (2025-05-23) +======================== +* New driving model + * New training architecture using parts from MLSIM +* Steering actuation delay is now learned online +* Ford Escape 2023-24 support thanks to incognitojam! +* Ford Kuga 2024 support thanks to incognitojam! +* Hyundai Nexo 2021 support thanks to sunnyhaibin! +* Tesla Model 3 and Y support thanks to lukasloetkolben! +* Lexus RC 2023 support thanks to nelsonjchen! + +Version 0.9.8 (2025-02-28) +======================== +* New driving model + * Model now gates applying positive acceleration in Chill mode +* New driver monitoring model + * Reduced false positives related to passengers +* Image processing pipeline moved to the ISP + * More GPU time for bigger driving models + * Power draw reduced 0.5W, which means your device runs cooler +* Added toggle to enable driver monitoring even when openpilot is not engaged +* Localizer rewritten to remove GPS dependency at runtime +* Firehose Mode for maximizing your training data uploads +* Enable openpilot longitudinal control for Ford Q3 vehicles +* New Toyota TSS2 longitudinal tune +* Rivian R1S and R1T support thanks to lukasloetkolben! +* Ford F-150, F-150 Hybrid, Mach-E, and Ranger support + +Version 0.9.7 (2024-06-13) +======================== +* New driving model + * Inputs the past curvature for smoother and more accurate lateral control + * Simplified neural network architecture in the model's last layers + * Minor fixes to desire augmentation and weight decay +* New driver monitoring model + * Improved end-to-end bit for phone detection +* Adjust driving personality with the follow distance button +* Support for hybrid variants of supported Ford models +* Fingerprinting without the OBD-II port on all cars +* Improved fuzzy fingerprinting for Ford and Volkswagen + +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 +* Model path UI + * Shows where driving model wants to be + * Shows what model is seeing more clearly, but more jittery +* 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 pandad 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 pandad + * 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 pandad 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 0000000000..80273db106 --- /dev/null +++ b/SConstruct @@ -0,0 +1,273 @@ +import os +import subprocess +import sys +import sysconfig +import platform +import shlex +import numpy as np + +import SCons.Errors + +SCons.Warnings.warningAsException(True) + +Decider('MD5-timestamp') + +SetOption('num_jobs', max(1, int(os.cpu_count()/2))) + +AddOption('--kaitai', action='store_true', help='Regenerate kaitai struct parsers') +AddOption('--asan', action='store_true', help='turn on ASAN') +AddOption('--ubsan', action='store_true', help='turn on UBSan') +AddOption('--mutation', action='store_true', help='generate mutation-ready code') +AddOption('--ccflags', action='store', type='string', default='', help='pass arbitrary flags over the command line') +AddOption('--minimal', + action='store_false', + dest='extras', + default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS) + help='the minimum build to run openpilot. no tests, tools, etc.') + +# Detect platform +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 os.path.isfile('/TICI'): + arch = "larch64" +assert arch in [ + "larch64", # linux tici arm64 + "aarch64", # linux pc arm64 + "x86_64", # linux pc x64 + "Darwin", # macOS arm64 (x86 not supported) +] + +env = Environment( + ENV={ + "PATH": os.environ['PATH'], + "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" + }, + CC='clang', + CXX='clang++', + CCFLAGS=[ + "-g", + "-fPIC", + "-O2", + "-Wunused", + "-Werror", + "-Wshadow", + "-Wno-unknown-warning-option", + "-Wno-inconsistent-missing-override", + "-Wno-c99-designator", + "-Wno-reorder-init-list", + "-Wno-vla-cxx-extension", + ], + CFLAGS=["-std=gnu11"], + CXXFLAGS=["-std=c++1z"], + CPPPATH=[ + "#", + "#msgq", + "#third_party", + "#third_party/json11", + "#third_party/linux/include", + "#third_party/acados/include", + "#third_party/acados/include/blasfeo/include", + "#third_party/acados/include/hpipm/include", + "#third_party/catch2/include", + "#third_party/libyuv/include", + ], + LIBPATH=[ + "#common", + "#msgq_repo", + "#third_party", + "#selfdrive/pandad", + "#rednose/helpers", + f"#third_party/libyuv/{arch}/lib", + f"#third_party/acados/{arch}/lib", + ], + RPATH=[], + CYTHONCFILESUFFIX=".cpp", + COMPILATIONDB_USE_ABSPATH=True, + REDNOSE_ROOT="#", + tools=["default", "cython", "compilation_db", "rednose_filter"], + toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"], +) + +# Arch-specific flags and paths +if arch == "larch64": + env.Append(CPPPATH=["#third_party/opencl/include"]) + env.Append(LIBPATH=[ + "/usr/local/lib", + "/system/vendor/lib64", + "/usr/lib/aarch64-linux-gnu", + ]) + arch_flags = ["-D__TICI__", "-mcpu=cortex-a57"] + env.Append(CCFLAGS=arch_flags) + env.Append(CXXFLAGS=arch_flags) +elif arch == "Darwin": + env.Append(LIBPATH=[ + f"{brew_prefix}/lib", + f"{brew_prefix}/opt/openssl@3.0/lib", + f"{brew_prefix}/opt/llvm/lib/c++", + "/System/Library/Frameworks/OpenGL.framework/Libraries", + ]) + env.Append(CCFLAGS=["-DGL_SILENCE_DEPRECATION"]) + env.Append(CXXFLAGS=["-DGL_SILENCE_DEPRECATION"]) + env.Append(CPPPATH=[ + f"{brew_prefix}/include", + f"{brew_prefix}/opt/openssl@3.0/include", + ]) +else: + env.Append(LIBPATH=[ + "/usr/lib", + "/usr/local/lib", + ]) + +# Sanitizers and extra CCFLAGS from CLI +if GetOption('asan'): + env.Append(CCFLAGS=["-fsanitize=address", "-fno-omit-frame-pointer"]) + env.Append(LINKFLAGS=["-fsanitize=address"]) +elif GetOption('ubsan'): + env.Append(CCFLAGS=["-fsanitize=undefined"]) + env.Append(LINKFLAGS=["-fsanitize=undefined"]) + +_extra_cc = shlex.split(GetOption('ccflags') or '') +if _extra_cc: + env.Append(CCFLAGS=_extra_cc) + +# no --as-needed on mac linker +if arch != "Darwin": + env.Append(LINKFLAGS=["-Wl,--as-needed", "-Wl,--no-undefined"]) + +# progress output +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"] = env["LINKFLAGS"] + ["-bundle", "-undefined", "dynamic_lookup"] +else: + envCython["LINKFLAGS"] = ["-pthread", "-shared"] + +np_version = SCons.Script.Value(np.__version__) +Export('envCython', 'np_version') + +# ********** Qt build environment ********** +qt_env = env.Clone() +qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "DBus", "Xml"] + +qt_libs = [] +if arch == "Darwin": + qt_env['QTDIR'] = f"{brew_prefix}/opt/qt@5" + qt_dirs = [ + os.path.join(qt_env['QTDIR'], "include"), + ] + qt_dirs += [f"{qt_env['QTDIR']}/include/Qt{m}" for m in qt_modules] + qt_env["LINKFLAGS"] += ["-F" + os.path.join(qt_env['QTDIR'], "lib")] + qt_env["FRAMEWORKS"] += [f"Qt{m}" for m in qt_modules] + ["OpenGL"] + qt_env.AppendENVPath('PATH', os.path.join(qt_env['QTDIR'], "bin")) +else: + 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'] +qt_env.Tool('qt3') + +qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"] +qt_flags = [ + "-D_REENTRANT", + "-DQT_NO_DEBUG", + "-DQT_WIDGETS_LIB", + "-DQT_GUI_LIB", + "-DQT_CORE_LIB", + "-DQT_MESSAGELOGCONTEXT", +] +qt_env['CXXFLAGS'] += qt_flags +qt_env['LIBPATH'] += ['#selfdrive/ui', ] +qt_env['LIBS'] = qt_libs + +Export('env', 'qt_env', 'arch') + +# Setup cache dir +cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache' +CacheDir(cache_dir) +Clean(["."], cache_dir) + +# ********** start building stuff ********** + +# Build common module +SConscript(['common/SConscript']) +Import('_common') +common = [_common, 'json11', 'zmq'] +Export('common') + +# Build messaging (cereal + msgq + socketmaster + their dependencies) +# Enable swaglog include in submodules +env_swaglog = env.Clone() +env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""') +SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog}) +SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog}) + +SConscript(['cereal/SConscript']) + +Import('socketmaster', 'msgq') +messaging = [socketmaster, msgq, 'capnp', 'kj',] +Export('messaging') + + +# Build other submodules +SConscript(['panda/SConscript']) + +# Build rednose library +SConscript(['rednose/SConscript']) + +# Build system services +SConscript([ + 'system/ubloxd/SConscript', + 'system/loggerd/SConscript', +]) + +if arch == "larch64": + SConscript(['system/camerad/SConscript']) + +# Build openpilot +SConscript(['third_party/SConscript']) + +SConscript(['selfdrive/SConscript']) + +if Dir('#tools/cabana/').exists() and GetOption('extras'): + SConscript(['tools/replay/SConscript']) + if arch != "larch64": + SConscript(['tools/cabana/SConscript']) + + +env.CompilationDatabase('compile_commands.json') diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..8b66082bf2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Suspected vulnerabilities can be reported to both `adeeb@comma.ai` and `security@comma.ai`. diff --git a/cereal/README.md b/cereal/README.md new file mode 100644 index 0000000000..45e859c09c --- /dev/null +++ b/cereal/README.md @@ -0,0 +1,95 @@ +# What is cereal? + +cereal is the messaging system for openpilot. It uses [msgq](https://github.com/commaai/msgq) as a pub/sub backend, and [Cap'n proto](https://capnproto.org/capnp-tool.html) for serialization of the structs. + + +## Messaging Spec + +You'll find the message types in [log.capnp](log.capnp). It uses [Cap'n proto](https://capnproto.org/capnp-tool.html) and defines one struct called `Event`. + +All `Events` have a `logMonoTime` and a `valid`. Then a big union defines the packet type. + +### Best Practices + +- **All fields must describe quantities in SI units**, unless otherwise specified in the field name. +- In the context of the message they are in, field names should be completely unambiguous. +- All values should be easy to plot and be human-readable with minimal parsing. + +### Maintaining backwards-compatibility + +When making changes to the messaging spec you want to maintain backwards-compatibility, such that old logs can +be parsed with a new version of cereal. Adding structs and adding members to structs is generally safe, most other +things are not. Read more details [here](https://capnproto.org/language.html). + +### Custom forks + +Forks of [openpilot](https://github.com/commaai/openpilot) might want to add things to the messaging +spec, however this could conflict with future changes made in mainline cereal/openpilot. Rebasing against mainline openpilot +then means breaking backwards-compatibility with all old logs of your fork. So we added reserved events in +[custom.capnp](custom.capnp) that we will leave empty in mainline cereal/openpilot. **If you only modify those, you can ensure your +fork will remain backwards-compatible with all versions of mainline openpilot and your fork.** + +An example of compatible changes: +```diff +diff --git a/cereal/custom.capnp b/cereal/custom.capnp +index 3348e859e..3365c7b98 100644 +--- a/cereal/custom.capnp ++++ b/cereal/custom.capnp +@@ -10,7 +10,11 @@ $Cxx.namespace("cereal"); + # DO rename the structs + # DON'T change the identifier (e.g. @0x81c2f05a394cf4af) + +-struct CustomReserved0 @0x81c2f05a394cf4af { ++struct SteeringInfo @0x81c2f05a394cf4af { ++ active @0 :Bool; ++ steeringAngleDeg @1 :Float32; ++ steeringRateDeg @2 :Float32; ++ steeringAccelDeg @3 :Float32; + } + + struct CustomReserved1 @0xaedffd8f31e7b55d { +diff --git a/cereal/log.capnp b/cereal/log.capnp +index 1209f3fd9..b189f58b6 100644 +--- a/cereal/log.capnp ++++ b/cereal/log.capnp +@@ -2558,14 +2558,14 @@ struct Event { + + # DO change the name of the field + # DON'T change anything after the "@" +- customReservedRawData0 @124 :Data; ++ rawCanData @124 :Data; + customReservedRawData1 @125 :Data; + customReservedRawData2 @126 :Data; + + # DO change the name of the field and struct + # DON'T change the ID (e.g. @107) + # DON'T change which struct it points to +- customReserved0 @107 :Custom.CustomReserved0; ++ steeringInfo @107 :Custom.SteeringInfo; + customReserved1 @108 :Custom.CustomReserved1; + customReserved2 @109 :Custom.CustomReserved2; + customReserved3 @110 :Custom.CustomReserved3; +``` + +--- + +Example +--- +```python +import cereal.messaging as messaging + +# in subscriber +sm = messaging.SubMaster(['sensorEvents']) +while 1: + sm.update() + print(sm['sensorEvents']) + +``` + +```python +# in publisher +pm = messaging.PubMaster(['sensorEvents']) +dat = messaging.new_message('sensorEvents', size=1) +dat.sensorEvents[0] = {"gyro": {"v": [0.1, -0.1, 0.1]}} +pm.send('sensorEvents', dat) +``` diff --git a/cereal/SConscript b/cereal/SConscript new file mode 100644 index 0000000000..a58a9490ce --- /dev/null +++ b/cereal/SConscript @@ -0,0 +1,20 @@ +Import('env', 'common', 'msgq') + +cereal_dir = Dir('.') +gen_dir = Dir('gen') + +# Build cereal +schema_files = ['log.capnp', 'car.capnp', 'legacy.capnp', 'custom.capnp'] +env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files], + schema_files, + f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/") + +cereal = env.Library('cereal', [f'gen/cpp/{s}.c++' for s in schema_files]) + +# Build messaging +services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET') +env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc'], LIBS=[msgq, common, 'pthread']) + +socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc']) + +Export('cereal', 'socketmaster') diff --git a/cereal/__init__.py b/cereal/__init__.py new file mode 100644 index 0000000000..93f4d77227 --- /dev/null +++ b/cereal/__init__.py @@ -0,0 +1,11 @@ +import os +import capnp +from importlib.resources import as_file, files + +capnp.remove_import_hook() + +with as_file(files("cereal")) as fspath: + CEREAL_PATH = fspath.as_posix() + log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp")) + car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp")) + custom = capnp.load(os.path.join(CEREAL_PATH, "custom.capnp")) diff --git a/cereal/car.capnp b/cereal/car.capnp new file mode 120000 index 0000000000..4bc7f89b1f --- /dev/null +++ b/cereal/car.capnp @@ -0,0 +1 @@ +../opendbc_repo/opendbc/car/car.capnp \ No newline at end of file diff --git a/cereal/custom.capnp b/cereal/custom.capnp new file mode 100644 index 0000000000..3348e859ef --- /dev/null +++ b/cereal/custom.capnp @@ -0,0 +1,71 @@ +using Cxx = import "./include/c++.capnp"; +$Cxx.namespace("cereal"); + +@0xb526ba661d550a59; + +# custom.capnp: a home for empty structs reserved for custom forks +# These structs are guaranteed to remain reserved and empty in mainline +# cereal, so use these if you want custom events in your fork. + +# DO rename the structs +# DON'T change the identifier (e.g. @0x81c2f05a394cf4af) + +struct CustomReserved0 @0x81c2f05a394cf4af { +} + +struct CustomReserved1 @0xaedffd8f31e7b55d { +} + +struct CustomReserved2 @0xf35cc4560bbf6ec2 { +} + +struct CustomReserved3 @0xda96579883444c35 { +} + +struct CustomReserved4 @0x80ae746ee2596b11 { +} + +struct CustomReserved5 @0xa5cd762cd951a455 { +} + +struct CustomReserved6 @0xf98d843bfd7004a3 { +} + +struct CustomReserved7 @0xb86e6369214c01c8 { +} + +struct CustomReserved8 @0xf416ec09499d9d19 { +} + +struct CustomReserved9 @0xa1680744031fdb2d { +} + +struct CustomReserved10 @0xcb9fd56c7057593a { +} + +struct CustomReserved11 @0xc2243c65e0340384 { +} + +struct CustomReserved12 @0x9ccdc8676701b412 { +} + +struct CustomReserved13 @0xcd96dafb67a082d0 { +} + +struct CustomReserved14 @0xb057204d7deadf3f { +} + +struct CustomReserved15 @0xbd443b539493bc68 { +} + +struct CustomReserved16 @0xfc6241ed8877b611 { +} + +struct CustomReserved17 @0xa30662f84033036c { +} + +struct CustomReserved18 @0xc86a3d38d13eb3ef { +} + +struct CustomReserved19 @0xa4f1eb3323f5f582 { +} diff --git a/cereal/include/c++.capnp b/cereal/include/c++.capnp new file mode 100644 index 0000000000..2bda547179 --- /dev/null +++ b/cereal/include/c++.capnp @@ -0,0 +1,26 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# 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. + +@0xbdf87d7bb8304e81; +$namespace("capnp::annotations"); + +annotation namespace(file): Text; +annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text; diff --git a/cereal/legacy.capnp b/cereal/legacy.capnp new file mode 100644 index 0000000000..a8fa5e4a1f --- /dev/null +++ b/cereal/legacy.capnp @@ -0,0 +1,574 @@ +using Cxx = import "./include/c++.capnp"; +$Cxx.namespace("cereal"); + +@0x80ef1ec4889c2a63; + +# legacy.capnp: a home for deprecated structs + +struct LogRotate @0x9811e1f38f62f2d1 { + segmentNum @0 :Int32; + path @1 :Text; +} + +struct LiveUI @0xc08240f996aefced { + rearViewCam @0 :Bool; + alertText1 @1 :Text; + alertText2 @2 :Text; + awarenessStatus @3 :Float32; +} + +struct UiLayoutState @0x88dcce08ad29dda0 { + activeApp @0 :App; + sidebarCollapsed @1 :Bool; + mapEnabled @2 :Bool; + mockEngaged @3 :Bool; + + enum App @0x9917470acf94d285 { + home @0; + music @1; + nav @2; + settings @3; + none @4; + } +} + +struct OrbslamCorrection @0x8afd33dc9b35e1aa { + correctionMonoTime @0 :UInt64; + prePositionECEF @1 :List(Float64); + postPositionECEF @2 :List(Float64); + prePoseQuatECEF @3 :List(Float32); + postPoseQuatECEF @4 :List(Float32); + numInliers @5 :UInt32; +} + +struct EthernetPacket @0xa99a9d5b33cf5859 { + pkt @0 :Data; + ts @1 :Float32; +} + +struct CellInfo @0xcff7566681c277ce { + timestamp @0 :UInt64; + repr @1 :Text; # android toString() for now +} + +struct WifiScan @0xd4df5a192382ba0b { + bssid @0 :Text; + ssid @1 :Text; + capabilities @2 :Text; + frequency @3 :Int32; + level @4 :Int32; + timestamp @5 :Int64; + + centerFreq0 @6 :Int32; + centerFreq1 @7 :Int32; + channelWidth @8 :ChannelWidth; + operatorFriendlyName @9 :Text; + venueName @10 :Text; + is80211mcResponder @11 :Bool; + passpoint @12 :Bool; + + distanceCm @13 :Int32; + distanceSdCm @14 :Int32; + + enum ChannelWidth @0xcb6a279f015f6b51 { + w20Mhz @0; + w40Mhz @1; + w80Mhz @2; + w160Mhz @3; + w80Plus80Mhz @4; + } +} + +struct LiveEventData @0x94b7baa90c5c321e { + name @0 :Text; + value @1 :Int32; +} + +struct ModelData @0xb8aad62cffef28a9 { + frameId @0 :UInt32; + frameAge @12 :UInt32; + frameDropPerc @13 :Float32; + timestampEof @9 :UInt64; + modelExecutionTime @14 :Float32; + gpuExecutionTime @16 :Float32; + rawPred @15 :Data; + + path @1 :PathData; + leftLane @2 :PathData; + rightLane @3 :PathData; + lead @4 :LeadData; + freePath @6 :List(Float32); + + settings @5 :ModelSettings; + leadFuture @7 :LeadData; + speed @8 :List(Float32); + meta @10 :MetaData; + longitudinal @11 :LongitudinalData; + + struct PathData @0x8817eeea389e9f08 { + points @0 :List(Float32); + prob @1 :Float32; + std @2 :Float32; + stds @3 :List(Float32); + poly @4 :List(Float32); + validLen @5 :Float32; + } + + struct LeadData @0xd1c9bef96d26fa91 { + dist @0 :Float32; + prob @1 :Float32; + std @2 :Float32; + relVel @3 :Float32; + relVelStd @4 :Float32; + relY @5 :Float32; + relYStd @6 :Float32; + relA @7 :Float32; + relAStd @8 :Float32; + } + + struct ModelSettings @0xa26e3710efd3e914 { + bigBoxX @0 :UInt16; + bigBoxY @1 :UInt16; + bigBoxWidth @2 :UInt16; + bigBoxHeight @3 :UInt16; + boxProjection @4 :List(Float32); + yuvCorrection @5 :List(Float32); + inputTransform @6 :List(Float32); + } + + struct MetaData @0x9744f25fb60f2bf8 { + engagedProb @0 :Float32; + desirePrediction @1 :List(Float32); + brakeDisengageProb @2 :Float32; + gasDisengageProb @3 :Float32; + steerOverrideProb @4 :Float32; + desireState @5 :List(Float32); + } + + struct LongitudinalData @0xf98f999c6a071122 { + distances @2 :List(Float32); + speeds @0 :List(Float32); + accelerations @1 :List(Float32); + } +} + +struct ECEFPoint @0xc25bbbd524983447 { + x @0 :Float64; + y @1 :Float64; + z @2 :Float64; +} + +struct ECEFPointDEPRECATED @0xe10e21168db0c7f7 { + x @0 :Float32; + y @1 :Float32; + z @2 :Float32; +} + +struct GPSPlannerPoints @0xab54c59699f8f9f3 { + curPosDEPRECATED @0 :ECEFPointDEPRECATED; + pointsDEPRECATED @1 :List(ECEFPointDEPRECATED); + curPos @6 :ECEFPoint; + points @7 :List(ECEFPoint); + valid @2 :Bool; + trackName @3 :Text; + speedLimit @4 :Float32; + accelTarget @5 :Float32; +} + +struct GPSPlannerPlan @0xf5ad1d90cdc1dd6b { + valid @0 :Bool; + poly @1 :List(Float32); + trackName @2 :Text; + speed @3 :Float32; + acceleration @4 :Float32; + pointsDEPRECATED @5 :List(ECEFPointDEPRECATED); + points @6 :List(ECEFPoint); + xLookahead @7 :Float32; +} + +struct UiNavigationEvent @0x90c8426c3eaddd3b { + type @0: Type; + status @1: Status; + distanceTo @2: Float32; + endRoadPointDEPRECATED @3: ECEFPointDEPRECATED; + endRoadPoint @4: ECEFPoint; + + enum Type @0xe8db07dcf8fcea05 { + none @0; + laneChangeLeft @1; + laneChangeRight @2; + mergeLeft @3; + mergeRight @4; + turnLeft @5; + turnRight @6; + } + + enum Status @0xb9aa88c75ef99a1f { + none @0; + passive @1; + approaching @2; + active @3; + } +} + +struct LiveLocationData @0xb99b2bc7a57e8128 { + status @0 :UInt8; + + # 3D fix + lat @1 :Float64; + lon @2 :Float64; + alt @3 :Float32; # m + + # speed + speed @4 :Float32; # m/s + + # NED velocity components + vNED @5 :List(Float32); + + # roll, pitch, heading (x,y,z) + roll @6 :Float32; # WRT to center of earth? + pitch @7 :Float32; # WRT to center of earth? + heading @8 :Float32; # WRT to north? + + # what are these? + wanderAngle @9 :Float32; + trackAngle @10 :Float32; + + # car frame -- https://upload.wikimedia.org/wikipedia/commons/f/f5/RPY_angles_of_cars.png + + # gyro, in car frame, deg/s + gyro @11 :List(Float32); + + # accel, in car frame, m/s^2 + accel @12 :List(Float32); + + accuracy @13 :Accuracy; + + source @14 :SensorSource; + # if we are fixing a location in the past + fixMonoTime @15 :UInt64; + + gpsWeek @16 :Int32; + timeOfWeek @17 :Float64; + + positionECEF @18 :List(Float64); + poseQuatECEF @19 :List(Float32); + pitchCalibration @20 :Float32; + yawCalibration @21 :Float32; + imuFrame @22 :List(Float32); + + struct Accuracy @0x943dc4625473b03f { + pNEDError @0 :List(Float32); + vNEDError @1 :List(Float32); + rollError @2 :Float32; + pitchError @3 :Float32; + headingError @4 :Float32; + ellipsoidSemiMajorError @5 :Float32; + ellipsoidSemiMinorError @6 :Float32; + ellipsoidOrientationError @7 :Float32; + } + + enum SensorSource @0xc871d3cc252af657 { + applanix @0; + kalman @1; + orbslam @2; + timing @3; + dummy @4; + } +} + +struct OrbOdometry @0xd7700859ed1f5b76 { + # timing first + startMonoTime @0 :UInt64; + endMonoTime @1 :UInt64; + + # fundamental matrix and error + f @2: List(Float64); + err @3: Float64; + + # number of inlier points + inliers @4: Int32; + + # for debug only + # indexed by endMonoTime features + # value is startMonoTime feature match + # -1 if no match + matches @5: List(Int16); +} + +struct OrbFeatures @0xcd60164a8a0159ef { + timestampEof @0 :UInt64; + # transposed arrays of normalized image coordinates + # len(xs) == len(ys) == len(descriptors) * 32 + xs @1 :List(Float32); + ys @2 :List(Float32); + descriptors @3 :Data; + octaves @4 :List(Int8); + + # match index to last OrbFeatures + # -1 if no match + timestampLastEof @5 :UInt64; + matches @6: List(Int16); +} + +struct OrbFeaturesSummary @0xd500d30c5803fa4f { + timestampEof @0 :UInt64; + timestampLastEof @1 :UInt64; + + featureCount @2 :UInt16; + matchCount @3 :UInt16; + computeNs @4 :UInt64; +} + +struct OrbKeyFrame @0xc8233c0345e27e24 { + # this is a globally unique id for the KeyFrame + id @0: UInt64; + + # this is the location of the KeyFrame + pos @1: ECEFPoint; + + # these are the features in the world + # len(dpos) == len(descriptors) * 32 + dpos @2 :List(ECEFPoint); + descriptors @3 :Data; +} + +struct KalmanOdometry @0x92e21bb7ea38793a { + trans @0 :List(Float32); # m/s in device frame + rot @1 :List(Float32); # rad/s in device frame + transStd @2 :List(Float32); # std m/s in device frame + rotStd @3 :List(Float32); # std rad/s in device frame +} + +struct OrbObservation @0x9b326d4e436afec7 { + observationMonoTime @0 :UInt64; + normalizedCoordinates @1 :List(Float32); + locationECEF @2 :List(Float64); + matchDistance @3: UInt32; +} + +struct CalibrationFeatures @0x8fdfadb254ea867a { + frameId @0 :UInt32; + + p0 @1 :List(Float32); + p1 @2 :List(Float32); + status @3 :List(Int8); +} + +struct NavStatus @0xbd8822120928120c { + isNavigating @0 :Bool; + currentAddress @1 :Address; + + struct Address @0xce7cd672cacc7814 { + title @0 :Text; + lat @1 :Float64; + lng @2 :Float64; + house @3 :Text; + address @4 :Text; + street @5 :Text; + city @6 :Text; + state @7 :Text; + country @8 :Text; + } +} + +struct NavUpdate @0xdb98be6565516acb { + isNavigating @0 :Bool; + curSegment @1 :Int32; + segments @2 :List(Segment); + + struct LatLng @0x9eaef9187cadbb9b { + lat @0 :Float64; + lng @1 :Float64; + } + + struct Segment @0xa5b39b4fc4d7da3f { + from @0 :LatLng; + to @1 :LatLng; + updateTime @2 :Int32; + distance @3 :Int32; + crossTime @4 :Int32; + exitNo @5 :Int32; + instruction @6 :Instruction; + + parts @7 :List(LatLng); + + enum Instruction @0xc5417a637451246f { + turnLeft @0; + turnRight @1; + keepLeft @2; + keepRight @3; + straight @4; + roundaboutExitNumber @5; + roundaboutExit @6; + roundaboutTurnLeft @7; + unkn8 @8; + roundaboutStraight @9; + unkn10 @10; + roundaboutTurnRight @11; + unkn12 @12; + roundaboutUturn @13; + unkn14 @14; + arrive @15; + exitLeft @16; + exitRight @17; + unkn18 @18; + uturn @19; + # ... + } + } +} + +struct TrafficEvent @0xacfa74a094e62626 { + type @0 :Type; + distance @1 :Float32; + action @2 :Action; + resuming @3 :Bool; + + enum Type @0xd85d75253435bf4b { + stopSign @0; + lightRed @1; + lightYellow @2; + lightGreen @3; + stopLight @4; + } + + enum Action @0xa6f6ce72165ccb49 { + none @0; + yield @1; + stop @2; + resumeReady @3; + } + +} + + +struct AndroidGnss @0xdfdf30d03fc485bd { + union { + measurements @0 :Measurements; + navigationMessage @1 :NavigationMessage; + } + + struct Measurements @0xa20710d4f428d6cd { + clock @0 :Clock; + measurements @1 :List(Measurement); + + struct Clock @0xa0e27b453a38f450 { + timeNanos @0 :Int64; + hardwareClockDiscontinuityCount @1 :Int32; + + hasTimeUncertaintyNanos @2 :Bool; + timeUncertaintyNanos @3 :Float64; + + hasLeapSecond @4 :Bool; + leapSecond @5 :Int32; + + hasFullBiasNanos @6 :Bool; + fullBiasNanos @7 :Int64; + + hasBiasNanos @8 :Bool; + biasNanos @9 :Float64; + + hasBiasUncertaintyNanos @10 :Bool; + biasUncertaintyNanos @11 :Float64; + + hasDriftNanosPerSecond @12 :Bool; + driftNanosPerSecond @13 :Float64; + + hasDriftUncertaintyNanosPerSecond @14 :Bool; + driftUncertaintyNanosPerSecond @15 :Float64; + } + + struct Measurement @0xd949bf717d77614d { + svId @0 :Int32; + constellation @1 :Constellation; + + timeOffsetNanos @2 :Float64; + state @3 :Int32; + receivedSvTimeNanos @4 :Int64; + receivedSvTimeUncertaintyNanos @5 :Int64; + cn0DbHz @6 :Float64; + pseudorangeRateMetersPerSecond @7 :Float64; + pseudorangeRateUncertaintyMetersPerSecond @8 :Float64; + accumulatedDeltaRangeState @9 :Int32; + accumulatedDeltaRangeMeters @10 :Float64; + accumulatedDeltaRangeUncertaintyMeters @11 :Float64; + + hasCarrierFrequencyHz @12 :Bool; + carrierFrequencyHz @13 :Float32; + hasCarrierCycles @14 :Bool; + carrierCycles @15 :Int64; + hasCarrierPhase @16 :Bool; + carrierPhase @17 :Float64; + hasCarrierPhaseUncertainty @18 :Bool; + carrierPhaseUncertainty @19 :Float64; + hasSnrInDb @20 :Bool; + snrInDb @21 :Float64; + + multipathIndicator @22 :MultipathIndicator; + + enum Constellation @0x9ef1f3ff0deb5ffb { + unknown @0; + gps @1; + sbas @2; + glonass @3; + qzss @4; + beidou @5; + galileo @6; + } + + enum State @0xcbb9490adce12d72 { + unknown @0; + codeLock @1; + bitSync @2; + subframeSync @3; + towDecoded @4; + msecAmbiguous @5; + symbolSync @6; + gloStringSync @7; + gloTodDecoded @8; + bdsD2BitSync @9; + bdsD2SubframeSync @10; + galE1bcCodeLock @11; + galE1c2ndCodeLock @12; + galE1bPageSync @13; + sbasSync @14; + } + + enum MultipathIndicator @0xc04e7b6231d4caa8 { + unknown @0; + detected @1; + notDetected @2; + } + } + } + + struct NavigationMessage @0xe2517b083095fd4e { + type @0 :Int32; + svId @1 :Int32; + messageId @2 :Int32; + submessageId @3 :Int32; + data @4 :Data; + status @5 :Status; + + enum Status @0xec1ff7996b35366f { + unknown @0; + parityPassed @1; + parityRebuilt @2; + } + } +} + +struct LidarPts @0xe3d6685d4e9d8f7a { + r @0 :List(UInt16); # uint16 m*500.0 + theta @1 :List(UInt16); # uint16 deg*100.0 + reflect @2 :List(UInt8); # uint8 0-255 + + # For storing out of file. + idx @3 :UInt64; + + # For storing in file + pkt @4 :Data; +} + + diff --git a/cereal/log.capnp b/cereal/log.capnp new file mode 100644 index 0000000000..019fbbe10b --- /dev/null +++ b/cereal/log.capnp @@ -0,0 +1,2691 @@ +using Cxx = import "./include/c++.capnp"; +$Cxx.namespace("cereal"); + +using Car = import "car.capnp"; +using Legacy = import "legacy.capnp"; +using Custom = import "custom.capnp"; + +@0xf3b1f17e25a4285b; + +const logVersion :Int32 = 1; + +struct Map(Key, Value) { + entries @0 :List(Entry); + struct Entry { + key @0 :Key; + value @1 :Value; + } +} + +struct OnroadEvent @0xc4fa6047f024e718 { + name @0 :EventName; + + # event types + enable @1 :Bool; + noEntry @2 :Bool; + warning @3 :Bool; # alerts presented only when enabled or soft disabling + userDisable @4 :Bool; + softDisable @5 :Bool; + immediateDisable @6 :Bool; + preEnable @7 :Bool; + permanent @8 :Bool; # alerts presented regardless of openpilot state + overrideLateral @10 :Bool; + overrideLongitudinal @9 :Bool; + + enum EventName @0x91f1992a1f77fb03 { + canError @0; + steerUnavailable @1; + wrongGear @2; + doorOpen @3; + seatbeltNotLatched @4; + espDisabled @5; + wrongCarMode @6; + steerTempUnavailable @7; + reverseGear @8; + buttonCancel @9; + buttonEnable @10; + pedalPressed @11; # exits active state + preEnableStandstill @12; # added during pre-enable state with brake + gasPressedOverride @13; # added when user is pressing gas with no disengage on gas + steerOverride @14; + steerDisengage @94; # exits active state + cruiseDisabled @15; + speedTooLow @16; + outOfSpace @17; + overheat @18; + calibrationIncomplete @19; + calibrationInvalid @20; + calibrationRecalibrating @21; + controlsMismatch @22; + pcmEnable @23; + pcmDisable @24; + radarFault @25; + radarTempUnavailable @93; + brakeHold @26; + parkBrake @27; + manualRestart @28; + joystickDebug @29; + longitudinalManeuver @30; + steerTempUnavailableSilent @31; + resumeRequired @32; + preDriverDistracted @33; + promptDriverDistracted @34; + driverDistracted @35; + preDriverUnresponsive @36; + promptDriverUnresponsive @37; + driverUnresponsive @38; + belowSteerSpeed @39; + lowBattery @40; + accFaulted @41; + sensorDataInvalid @42; + commIssue @43; + commIssueAvgFreq @44; + tooDistracted @45; + posenetInvalid @46; + preLaneChangeLeft @48; + preLaneChangeRight @49; + laneChange @50; + lowMemory @51; + stockAeb @52; + ldw @53; + carUnrecognized @54; + invalidLkasSetting @55; + speedTooHigh @56; + laneChangeBlocked @57; + relayMalfunction @58; + stockFcw @59; + startup @60; + startupNoCar @61; + startupNoControl @62; + startupNoSecOcKey @63; + startupMaster @64; + fcw @65; + steerSaturated @66; + belowEngageSpeed @67; + noGps @68; + wrongCruiseMode @69; + modeldLagging @70; + deviceFalling @71; + fanMalfunction @72; + cameraMalfunction @73; + cameraFrameRate @74; + processNotRunning @75; + dashcamMode @76; + selfdriveInitializing @77; + usbError @78; + cruiseMismatch @79; + canBusMissing @80; + selfdrivedLagging @81; + resumeBlocked @82; + steerTimeLimit @83; + vehicleSensorsInvalid @84; + locationdTemporaryError @85; + locationdPermanentError @86; + paramsdTemporaryError @87; + paramsdPermanentError @88; + actuatorsApiUnavailable @89; + espActive @90; + personalityChanged @91; + aeb @92; + userBookmark @95; + excessiveActuation @96; + audioFeedback @97; + + soundsUnavailableDEPRECATED @47; + } +} + +enum LongitudinalPersonality { + aggressive @0; + standard @1; + relaxed @2; +} + +struct InitData { + kernelArgs @0 :List(Text); + kernelVersion @15 :Text; + osVersion @18 :Text; + + dongleId @2 :Text; + bootlogId @22 :Text; + + deviceType @3 :DeviceType; + version @4 :Text; + gitCommit @10 :Text; + gitCommitDate @21 :Text; + gitBranch @11 :Text; + gitRemote @13 :Text; + + # this is source commit for prebuilt branches + gitSrcCommit @23 :Text; + gitSrcCommitDate @24 :Text; + + androidProperties @16 :Map(Text, Text); + + pandaInfo @8 :PandaInfo; + + dirty @9 :Bool; + passive @12 :Bool; + params @17 :Map(Text, Data); + + commands @19 :Map(Text, Data); + + wallTimeNanos @20 :UInt64; + + enum DeviceType { + unknown @0; + neo @1; + chffrAndroid @2; + chffrIos @3; + tici @4; + pc @5; + tizi @6; + mici @7; + } + + struct PandaInfo { + hasPanda @0 :Bool; + dongleId @1 :Text; + stVersion @2 :Text; + espVersion @3 :Text; + } + + # ***** deprecated stuff ***** + gctxDEPRECATED @1 :Text; + androidBuildInfo @5 :AndroidBuildInfo; + androidSensorsDEPRECATED @6 :List(AndroidSensor); + chffrAndroidExtraDEPRECATED @7 :ChffrAndroidExtra; + iosBuildInfoDEPRECATED @14 :IosBuildInfo; + + struct AndroidBuildInfo { + board @0 :Text; + bootloader @1 :Text; + brand @2 :Text; + device @3 :Text; + display @4 :Text; + fingerprint @5 :Text; + hardware @6 :Text; + host @7 :Text; + id @8 :Text; + manufacturer @9 :Text; + model @10 :Text; + product @11 :Text; + radioVersion @12 :Text; + serial @13 :Text; + supportedAbis @14 :List(Text); + tags @15 :Text; + time @16 :Int64; + type @17 :Text; + user @18 :Text; + + versionCodename @19 :Text; + versionRelease @20 :Text; + versionSdk @21 :Int32; + versionSecurityPatch @22 :Text; + } + + struct AndroidSensor { + id @0 :Int32; + name @1 :Text; + vendor @2 :Text; + version @3 :Int32; + handle @4 :Int32; + type @5 :Int32; + maxRange @6 :Float32; + resolution @7 :Float32; + power @8 :Float32; + minDelay @9 :Int32; + fifoReservedEventCount @10 :UInt32; + fifoMaxEventCount @11 :UInt32; + stringType @12 :Text; + maxDelay @13 :Int32; + } + + struct ChffrAndroidExtra { + allCameraCharacteristics @0 :Map(Text, Text); + } + + struct IosBuildInfo { + appVersion @0 :Text; + appBuild @1 :UInt32; + osVersion @2 :Text; + deviceModel @3 :Text; + } +} + +struct FrameData { + frameId @0 :UInt32; + frameIdSensor @25 :UInt32; + requestId @28 :UInt32; + encodeId @1 :UInt32; + + # Timestamps + timestampEof @2 :UInt64; + timestampSof @8 :UInt64; + processingTime @23 :Float32; + + # Exposure + integLines @4 :Int32; + highConversionGain @20 :Bool; + gain @15 :Float32; # This includes highConversionGain if enabled + measuredGreyFraction @21 :Float32; + targetGreyFraction @22 :Float32; + exposureValPercent @27 :Float32; + + transform @10 :List(Float32); + + image @6 :Data; + + temperaturesC @24 :List(Float32); + + enum FrameTypeDEPRECATED { + unknown @0; + neo @1; + chffrAndroid @2; + front @3; + } + + sensor @26 :ImageSensor; + enum ImageSensor { + unknown @0; + ar0231 @1; + ox03c10 @2; + os04c10 @3; + } + + frameLengthDEPRECATED @3 :Int32; + globalGainDEPRECATED @5 :Int32; + frameTypeDEPRECATED @7 :FrameTypeDEPRECATED; + androidCaptureResultDEPRECATED @9 :AndroidCaptureResult; + lensPosDEPRECATED @11 :Int32; + lensSagDEPRECATED @12 :Float32; + lensErrDEPRECATED @13 :Float32; + lensTruePosDEPRECATED @14 :Float32; + focusValDEPRECATED @16 :List(Int16); + focusConfDEPRECATED @17 :List(UInt8); + sharpnessScoreDEPRECATED @18 :List(UInt16); + recoverStateDEPRECATED @19 :Int32; + struct AndroidCaptureResult { + sensitivity @0 :Int32; + frameDuration @1 :Int64; + exposureTime @2 :Int64; + rollingShutterSkew @3 :UInt64; + colorCorrectionTransform @4 :List(Int32); + colorCorrectionGains @5 :List(Float32); + displayRotation @6 :Int8; + } +} + +struct Thumbnail { + frameId @0 :UInt32; + timestampEof @1 :UInt64; + thumbnail @2 :Data; + encoding @3 :Encoding; + + enum Encoding { + unknown @0; + jpeg @1; + keyframe @2; + } +} + +struct GPSNMEAData { + timestamp @0 :Int64; + localWallTime @1 :UInt64; + nmea @2 :Text; +} + +# android sensor_event_t +struct SensorEventData { + version @0 :Int32; + sensor @1 :Int32; + type @2 :Int32; + timestamp @3 :Int64; + uncalibratedDEPRECATED @10 :Bool; + + union { + acceleration @4 :SensorVec; + magnetic @5 :SensorVec; + orientation @6 :SensorVec; + gyro @7 :SensorVec; + pressure @9 :SensorVec; + magneticUncalibrated @11 :SensorVec; + gyroUncalibrated @12 :SensorVec; + proximity @13: Float32; + light @14: Float32; + temperature @15: Float32; + } + source @8 :SensorSource; + + struct SensorVec { + v @0 :List(Float32); + status @1 :Int8; + } + + enum SensorSource { + android @0; + iOS @1; + fiber @2; + velodyne @3; # Velodyne IMU + bno055 @4; # Bosch accelerometer + lsm6ds3 @5; # includes LSM6DS3 and LSM6DS3TR, TR = tape reel + bmp280 @6; # barometer + mmc3416x @7; # magnetometer + bmx055 @8; + rpr0521 @9; + lsm6ds3trc @10; + mmc5603nj @11; + } +} + +# android struct GpsLocation +struct GpsLocationData { + # Contains module-specific flags. + flags @0 :UInt16; + + # Represents latitude in degrees. + latitude @1 :Float64; + + # Represents longitude in degrees. + longitude @2 :Float64; + + # Represents altitude in meters above the WGS 84 reference ellipsoid. + altitude @3 :Float64; + + # Represents speed in meters per second. + speed @4 :Float32; + + # Represents heading in degrees. + bearingDeg @5 :Float32; + + # Represents expected horizontal accuracy in meters. + horizontalAccuracy @6 :Float32; + + unixTimestampMillis @7 :Int64; + + source @8 :SensorSource; + + # Represents NED velocity in m/s. + vNED @9 :List(Float32); + + # Represents expected vertical accuracy in meters. (presumably 1 sigma?) + verticalAccuracy @10 :Float32; + + # Represents bearing accuracy in degrees. (presumably 1 sigma?) + bearingAccuracyDeg @11 :Float32; + + # Represents velocity accuracy in m/s. (presumably 1 sigma?) + speedAccuracy @12 :Float32; + + hasFix @13 :Bool; + satelliteCount @14 :Int8; + + enum SensorSource { + android @0; + iOS @1; + car @2; + velodyne @3; # Velodyne IMU + fusion @4; + external @5; + ublox @6; + trimble @7; + qcomdiag @8; + unicore @9; + } +} + +enum Desire { + none @0; + turnLeft @1; + turnRight @2; + laneChangeLeft @3; + laneChangeRight @4; + keepLeft @5; + keepRight @6; +} + +enum LaneChangeState { + off @0; + preLaneChange @1; + laneChangeStarting @2; + laneChangeFinishing @3; +} + +enum LaneChangeDirection { + none @0; + left @1; + right @2; +} + +struct CanData { + address @0 :UInt32; + dat @2 :Data; + src @3 :UInt8; + busTimeDEPRECATED @1 :UInt16; +} + +struct DeviceState @0xa4d8b5af2aa492eb { + deviceType @45 :InitData.DeviceType; + + networkType @22 :NetworkType; + networkInfo @31 :NetworkInfo; + networkStrength @24 :NetworkStrength; + networkStats @43 :NetworkStats; + networkMetered @41 :Bool; + lastAthenaPingTime @32 :UInt64; + + started @11 :Bool; + startedMonoTime @13 :UInt64; + + # system utilization + freeSpacePercent @7 :Float32; + memoryUsagePercent @19 :Int8; + gpuUsagePercent @33 :Int8; + cpuUsagePercent @34 :List(Int8); # per-core cpu usage + + # power + offroadPowerUsageUwh @23 :UInt32; + carBatteryCapacityUwh @25 :UInt32; + powerDrawW @40 :Float32; + somPowerDrawW @42 :Float32; + + # device thermals + cpuTempC @26 :List(Float32); + gpuTempC @27 :List(Float32); + dspTempC @49 :Float32; + memoryTempC @28 :Float32; + modemTempC @36 :List(Float32); + pmicTempC @39 :List(Float32); + intakeTempC @46 :Float32; + exhaustTempC @47 :Float32; + caseTempC @48 :Float32; + maxTempC @44 :Float32; # max of other temps, used to control fan + thermalZones @38 :List(ThermalZone); + thermalStatus @14 :ThermalStatus; + + fanSpeedPercentDesired @10 :UInt16; + screenBrightnessPercent @37 :Int8; + + struct ThermalZone { + name @0 :Text; + temp @1 :Float32; + } + + enum ThermalStatus { + green @0; + yellow @1; + red @2; + danger @3; + } + + enum NetworkType { + none @0; + wifi @1; + cell2G @2; + cell3G @3; + cell4G @4; + cell5G @5; + ethernet @6; + } + + enum NetworkStrength { + unknown @0; + poor @1; + moderate @2; + good @3; + great @4; + } + + struct NetworkInfo { + technology @0 :Text; + operator @1 :Text; + band @2 :Text; + channel @3 :UInt16; + extra @4 :Text; + state @5 :Text; + } + + struct NetworkStats { + wwanTx @0 :Int64; + wwanRx @1 :Int64; + } + + # deprecated + cpu0DEPRECATED @0 :UInt16; + cpu1DEPRECATED @1 :UInt16; + cpu2DEPRECATED @2 :UInt16; + cpu3DEPRECATED @3 :UInt16; + memDEPRECATED @4 :UInt16; + gpuDEPRECATED @5 :UInt16; + batDEPRECATED @6 :UInt32; + pa0DEPRECATED @21 :UInt16; + cpuUsagePercentDEPRECATED @20 :Int8; + batteryStatusDEPRECATED @9 :Text; + batteryVoltageDEPRECATED @16 :Int32; + batteryTempCDEPRECATED @29 :Float32; + batteryPercentDEPRECATED @8 :Int16; + batteryCurrentDEPRECATED @15 :Int32; + chargingErrorDEPRECATED @17 :Bool; + chargingDisabledDEPRECATED @18 :Bool; + usbOnlineDEPRECATED @12 :Bool; + ambientTempCDEPRECATED @30 :Float32; + nvmeTempCDEPRECATED @35 :List(Float32); +} + +struct PandaState @0xa7649e2575e4591e { + ignitionLine @2 :Bool; + rxBufferOverflow @7 :UInt32; + txBufferOverflow @8 :UInt32; + pandaType @10 :PandaType; + ignitionCan @13 :Bool; + faultStatus @15 :FaultStatus; + powerSaveEnabled @16 :Bool; + uptime @17 :UInt32; + faults @18 :List(FaultType); + heartbeatLost @22 :Bool; + interruptLoad @25 :Float32; + fanPower @28 :UInt8; + + spiErrorCount @33 :UInt16; + + harnessStatus @21 :HarnessStatus; + sbu1Voltage @35 :Float32; + sbu2Voltage @36 :Float32; + + # can health + canState0 @29 :PandaCanState; + canState1 @30 :PandaCanState; + canState2 @31 :PandaCanState; + + # safety stuff + controlsAllowed @3 :Bool; + safetyRxInvalid @19 :UInt32; + safetyTxBlocked @24 :UInt32; + safetyModel @14 :Car.CarParams.SafetyModel; + safetyParam @27 :UInt16; + alternativeExperience @23 :Int16; + safetyRxChecksInvalid @32 :Bool; + + voltage @0 :UInt32; + current @1 :UInt32; + + enum FaultStatus { + none @0; + faultTemp @1; + faultPerm @2; + } + + enum FaultType { + relayMalfunction @0; + unusedInterruptHandled @1; + interruptRateCan1 @2; + interruptRateCan2 @3; + interruptRateCan3 @4; + interruptRateTach @5; + interruptRateGmlanDEPRECATED @6; + interruptRateInterrupts @7; + interruptRateSpiDma @8; + interruptRateSpiCs @9; + interruptRateUart1 @10; + interruptRateUart2 @11; + interruptRateUart3 @12; + interruptRateUart5 @13; + interruptRateUartDma @14; + interruptRateUsb @15; + interruptRateTim1 @16; + interruptRateTim3 @17; + registerDivergent @18; + interruptRateKlineInit @19; + interruptRateClockSource @20; + interruptRateTick @21; + interruptRateExti @22; + interruptRateSpi @23; + interruptRateUart7 @24; + sirenMalfunction @25; + heartbeatLoopWatchdog @26; + # Update max fault type in boardd when adding faults + } + + enum PandaType @0x8a58adf93e5b3751 { + unknown @0; + whitePanda @1; + greyPanda @2; + blackPanda @3; + pedal @4; + uno @5; + dos @6; + redPanda @7; + redPandaV2 @8; + tres @9; + cuatro @10; + } + + enum HarnessStatus { + notConnected @0; + normal @1; + flipped @2; + } + + struct PandaCanState { + busOff @0 :Bool; + busOffCnt @1 :UInt32; + errorWarning @2 :Bool; + errorPassive @3 :Bool; + lastError @4 :LecErrorCode; + lastStoredError @5 :LecErrorCode; + lastDataError @6 :LecErrorCode; + lastDataStoredError @7 :LecErrorCode; + receiveErrorCnt @8 :UInt8; + transmitErrorCnt @9 :UInt8; + totalErrorCnt @10 :UInt32; + totalTxLostCnt @11 :UInt32; + totalRxLostCnt @12 :UInt32; + totalTxCnt @13 :UInt32; + totalRxCnt @14 :UInt32; + totalFwdCnt @15 :UInt32; + canSpeed @16 :UInt16; + canDataSpeed @17 :UInt16; + canfdEnabled @18 :Bool; + brsEnabled @19 :Bool; + canfdNonIso @20 :Bool; + irq0CallRate @21 :UInt32; + irq1CallRate @22 :UInt32; + irq2CallRate @23 :UInt32; + canCoreResetCnt @24 :UInt32; + + enum LecErrorCode { + noError @0; + stuffError @1; + formError @2; + ackError @3; + bit1Error @4; + bit0Error @5; + crcError @6; + noChange @7; + } + } + + gasInterceptorDetectedDEPRECATED @4 :Bool; + startedSignalDetectedDEPRECATED @5 :Bool; + hasGpsDEPRECATED @6 :Bool; + gmlanSendErrsDEPRECATED @9 :UInt32; + fanSpeedRpmDEPRECATED @11 :UInt16; + usbPowerModeDEPRECATED @12 :PeripheralState.UsbPowerModeDEPRECATED; + safetyParamDEPRECATED @20 :Int16; + safetyParam2DEPRECATED @26 :UInt32; + fanStallCountDEPRECATED @34 :UInt8; +} + +struct PeripheralState { + pandaType @0 :PandaState.PandaType; + voltage @1 :UInt32; + current @2 :UInt32; + fanSpeedRpm @3 :UInt16; + + usbPowerModeDEPRECATED @4 :UsbPowerModeDEPRECATED; + enum UsbPowerModeDEPRECATED @0xa8883583b32c9877 { + none @0; + client @1; + cdp @2; + dcp @3; + } +} + +struct RadarState @0x9a185389d6fdd05f { + mdMonoTime @6 :UInt64; + carStateMonoTime @11 :UInt64; + radarErrors @13 :Car.RadarData.Error; + + leadOne @3 :LeadData; + leadTwo @4 :LeadData; + + struct LeadData { + dRel @0 :Float32; + yRel @1 :Float32; + vRel @2 :Float32; + aRel @3 :Float32; + vLead @4 :Float32; + dPath @6 :Float32; + vLat @7 :Float32; + vLeadK @8 :Float32; + aLeadK @9 :Float32; + fcw @10 :Bool; + status @11 :Bool; + aLeadTau @12 :Float32; + modelProb @13 :Float32; + radar @14 :Bool; + radarTrackId @15 :Int32 = -1; + + aLeadDEPRECATED @5 :Float32; + } + + # deprecated + ftMonoTimeDEPRECATED @7 :UInt64; + warpMatrixDEPRECATED @0 :List(Float32); + angleOffsetDEPRECATED @1 :Float32; + calStatusDEPRECATED @2 :Int8; + calCycleDEPRECATED @8 :Int32; + calPercDEPRECATED @9 :Int8; + canMonoTimesDEPRECATED @10 :List(UInt64); + cumLagMsDEPRECATED @5 :Float32; + radarErrorsDEPRECATED @12 :List(Car.RadarData.ErrorDEPRECATED); +} + +struct LiveCalibrationData { + calStatus @11 :Status; + calCycle @2 :Int32; + calPerc @3 :Int8; + validBlocks @9 :Int32; + + # view_frame_from_road_frame + # ui's is inversed needs new + extrinsicMatrix @4 :List(Float32); + # the direction of travel vector in device frame + rpyCalib @7 :List(Float32); + rpyCalibSpread @8 :List(Float32); + wideFromDeviceEuler @10 :List(Float32); + height @12 :List(Float32); + + warpMatrixDEPRECATED @0 :List(Float32); + calStatusDEPRECATED @1 :Int8; + warpMatrix2DEPRECATED @5 :List(Float32); + warpMatrixBigDEPRECATED @6 :List(Float32); + + enum Status { + uncalibrated @0; + calibrated @1; + invalid @2; + recalibrating @3; + } +} + +struct LiveTracksDEPRECATED { + trackId @0 :Int32; + dRel @1 :Float32; + yRel @2 :Float32; + vRel @3 :Float32; + aRel @4 :Float32; + timeStamp @5 :Float32; + status @6 :Float32; + currentTime @7 :Float32; + stationary @8 :Bool; + oncoming @9 :Bool; +} + +struct SelfdriveState { + # high level system state + state @0 :OpenpilotState; + enabled @1 :Bool; + active @2 :Bool; + engageable @9 :Bool; # can OP be engaged? + + # UI alerts + alertText1 @3 :Text; + alertText2 @4 :Text; + alertStatus @5 :AlertStatus; + alertSize @6 :AlertSize; + alertType @7 :Text; + alertSound @8 :Car.CarControl.HUDControl.AudibleAlert; + alertHudVisual @12 :Car.CarControl.HUDControl.VisualAlert; + + # configurable driving settings + experimentalMode @10 :Bool; + personality @11 :LongitudinalPersonality; + + enum OpenpilotState @0xdbe58b96d2d1ac61 { + disabled @0; + preEnabled @1; + enabled @2; + softDisabling @3; + overriding @4; # superset of overriding with steering or accelerator + } + + enum AlertStatus @0xa0d0dcd113193c62 { + normal @0; + userPrompt @1; + critical @2; + } + + enum AlertSize @0xe98bb99d6e985f64 { + none @0; + small @1; + mid @2; + full @3; + } +} + +struct ControlsState @0x97ff69c53601abf1 { + longitudinalPlanMonoTime @28 :UInt64; + lateralPlanMonoTime @50 :UInt64; + + longControlState @30 :Car.CarControl.Actuators.LongControlState; + upAccelCmd @4 :Float32; + uiAccelCmd @5 :Float32; + ufAccelCmd @33 :Float32; + curvature @37 :Float32; # path curvature from vehicle model + desiredCurvature @61 :Float32; # lag adjusted curvatures used by lateral controllers + forceDecel @51 :Bool; + + lateralControlState :union { + pidState @53 :LateralPIDState; + angleState @58 :LateralAngleState; + debugState @59 :LateralDebugState; + torqueState @60 :LateralTorqueState; + + curvatureStateDEPRECATED @65 :LateralCurvatureState; + lqrStateDEPRECATED @55 :LateralLQRState; + indiStateDEPRECATED @52 :LateralINDIState; + } + + struct LateralINDIState { + active @0 :Bool; + steeringAngleDeg @1 :Float32; + steeringRateDeg @2 :Float32; + steeringAccelDeg @3 :Float32; + rateSetPoint @4 :Float32; + accelSetPoint @5 :Float32; + accelError @6 :Float32; + delayedOutput @7 :Float32; + delta @8 :Float32; + output @9 :Float32; + saturated @10 :Bool; + steeringAngleDesiredDeg @11 :Float32; + steeringRateDesiredDeg @12 :Float32; + } + + struct LateralPIDState { + active @0 :Bool; + steeringAngleDeg @1 :Float32; + steeringRateDeg @2 :Float32; + angleError @3 :Float32; + p @4 :Float32; + i @5 :Float32; + f @6 :Float32; + output @7 :Float32; + saturated @8 :Bool; + steeringAngleDesiredDeg @9 :Float32; + } + + struct LateralTorqueState { + active @0 :Bool; + error @1 :Float32; + errorRate @8 :Float32; + p @2 :Float32; + i @3 :Float32; + d @4 :Float32; + f @5 :Float32; + output @6 :Float32; + saturated @7 :Bool; + actualLateralAccel @9 :Float32; + desiredLateralAccel @10 :Float32; + } + + struct LateralLQRState { + active @0 :Bool; + steeringAngleDeg @1 :Float32; + i @2 :Float32; + output @3 :Float32; + lqrOutput @4 :Float32; + saturated @5 :Bool; + steeringAngleDesiredDeg @6 :Float32; + } + + struct LateralAngleState { + active @0 :Bool; + steeringAngleDeg @1 :Float32; + output @2 :Float32; + saturated @3 :Bool; + steeringAngleDesiredDeg @4 :Float32; + } + + struct LateralCurvatureState { + active @0 :Bool; + actualCurvature @1 :Float32; + desiredCurvature @2 :Float32; + error @3 :Float32; + p @4 :Float32; + i @5 :Float32; + f @6 :Float32; + output @7 :Float32; + saturated @8 :Bool; + } + + struct LateralDebugState { + active @0 :Bool; + steeringAngleDeg @1 :Float32; + output @2 :Float32; + saturated @3 :Bool; + } + + # deprecated + vEgoDEPRECATED @0 :Float32; + vEgoRawDEPRECATED @32 :Float32; + aEgoDEPRECATED @1 :Float32; + canMonoTimeDEPRECATED @16 :UInt64; + radarStateMonoTimeDEPRECATED @17 :UInt64; + mdMonoTimeDEPRECATED @18 :UInt64; + yActualDEPRECATED @6 :Float32; + yDesDEPRECATED @7 :Float32; + upSteerDEPRECATED @8 :Float32; + uiSteerDEPRECATED @9 :Float32; + ufSteerDEPRECATED @34 :Float32; + aTargetMinDEPRECATED @10 :Float32; + aTargetMaxDEPRECATED @11 :Float32; + rearViewCamDEPRECATED @23 :Bool; + driverMonitoringOnDEPRECATED @43 :Bool; + hudLeadDEPRECATED @14 :Int32; + alertSoundDEPRECATED @45 :Text; + angleModelBiasDEPRECATED @27 :Float32; + gpsPlannerActiveDEPRECATED @40 :Bool; + decelForTurnDEPRECATED @47 :Bool; + decelForModelDEPRECATED @54 :Bool; + awarenessStatusDEPRECATED @26 :Float32; + angleSteersDEPRECATED @13 :Float32; + vCurvatureDEPRECATED @46 :Float32; + mapValidDEPRECATED @49 :Bool; + jerkFactorDEPRECATED @12 :Float32; + steerOverrideDEPRECATED @20 :Bool; + steeringAngleDesiredDegDEPRECATED @29 :Float32; + canMonoTimesDEPRECATED @21 :List(UInt64); + desiredCurvatureRateDEPRECATED @62 :Float32; + canErrorCounterDEPRECATED @57 :UInt32; + vPidDEPRECATED @2 :Float32; + alertBlinkingRateDEPRECATED @42 :Float32; + alertText1DEPRECATED @24 :Text; + alertText2DEPRECATED @25 :Text; + alertStatusDEPRECATED @38 :SelfdriveState.AlertStatus; + alertSizeDEPRECATED @39 :SelfdriveState.AlertSize; + alertTypeDEPRECATED @44 :Text; + alertSound2DEPRECATED @56 :Car.CarControl.HUDControl.AudibleAlert; + engageableDEPRECATED @41 :Bool; # can OP be engaged? + stateDEPRECATED @31 :SelfdriveState.OpenpilotState; + enabledDEPRECATED @19 :Bool; + activeDEPRECATED @36 :Bool; + experimentalModeDEPRECATED @64 :Bool; + personalityDEPRECATED @66 :LongitudinalPersonality; + vCruiseDEPRECATED @22 :Float32; # actual set speed + vCruiseClusterDEPRECATED @63 :Float32; # set speed to display in the UI + startMonoTimeDEPRECATED @48 :UInt64; + cumLagMsDEPRECATED @15 :Float32; + aTargetDEPRECATED @35 :Float32; + vTargetLeadDEPRECATED @3 :Float32; +} + +struct DrivingModelData { + frameId @0 :UInt32; + frameIdExtra @1 :UInt32; + frameDropPerc @6 :Float32; + modelExecutionTime @7 :Float32; + + action @2 :ModelDataV2.Action; + + laneLineMeta @3 :LaneLineMeta; + meta @4 :MetaData; + + path @5 :PolyPath; + + struct PolyPath { + xCoefficients @0 :List(Float32); + yCoefficients @1 :List(Float32); + zCoefficients @2 :List(Float32); + } + + struct LaneLineMeta { + leftY @0 :Float32; + rightY @1 :Float32; + leftProb @2 :Float32; + rightProb @3 :Float32; + } + + struct MetaData { + laneChangeState @0 :LaneChangeState; + laneChangeDirection @1 :LaneChangeDirection; + } +} + +# All SI units and in device frame +struct XYZTData @0xc3cbae1fd505ae80 { + x @0 :List(Float32); + y @1 :List(Float32); + z @2 :List(Float32); + t @3 :List(Float32); + xStd @4 :List(Float32); + yStd @5 :List(Float32); + zStd @6 :List(Float32); +} + +struct ModelDataV2 { + frameId @0 :UInt32; + frameIdExtra @20 :UInt32; + frameAge @1 :UInt32; + frameDropPerc @2 :Float32; + timestampEof @3 :UInt64; + modelExecutionTime @15 :Float32; + rawPredictions @16 :Data; + + # predicted future position, orientation, etc.. + position @4 :XYZTData; + orientation @5 :XYZTData; + velocity @6 :XYZTData; + orientationRate @7 :XYZTData; + acceleration @19 :XYZTData; + + # prediction lanelines and road edges + laneLines @8 :List(XYZTData); + laneLineProbs @9 :List(Float32); + laneLineStds @13 :List(Float32); + roadEdges @10 :List(XYZTData); + roadEdgeStds @14 :List(Float32); + + # predicted lead cars + leads @11 :List(LeadDataV2); + leadsV3 @18 :List(LeadDataV3); + + meta @12 :MetaData; + confidence @23: ConfidenceClass; + + # Model perceived motion + temporalPoseDEPRECATED @21 :Pose; + + # e2e lateral planner + action @26: Action; + + gpuExecutionTimeDEPRECATED @17 :Float32; + navEnabledDEPRECATED @22 :Bool; + locationMonoTimeDEPRECATED @24 :UInt64; + lateralPlannerSolutionDEPRECATED @25: LateralPlannerSolution; + + struct LeadDataV2 { + prob @0 :Float32; # probability that car is your lead at time t + t @1 :Float32; + + # x and y are relative position in device frame + # v is norm relative speed + # a is norm relative acceleration + xyva @2 :List(Float32); + xyvaStd @3 :List(Float32); + } + + struct LeadDataV3 { + prob @0 :Float32; # probability that car is your lead at time t + probTime @1 :Float32; + t @2 :List(Float32); + + # x and y are relative position in device frame + # v absolute norm speed + # a is derivative of v + x @3 :List(Float32); + xStd @4 :List(Float32); + y @5 :List(Float32); + yStd @6 :List(Float32); + v @7 :List(Float32); + vStd @8 :List(Float32); + a @9 :List(Float32); + aStd @10 :List(Float32); + } + + + struct MetaData { + engagedProb @0 :Float32; + desirePrediction @1 :List(Float32); + desireState @5 :List(Float32); + disengagePredictions @6 :DisengagePredictions; + hardBrakePredicted @7 :Bool; + laneChangeState @8 :LaneChangeState; + laneChangeDirection @9 :LaneChangeDirection; + + + # deprecated + brakeDisengageProbDEPRECATED @2 :Float32; + gasDisengageProbDEPRECATED @3 :Float32; + steerOverrideProbDEPRECATED @4 :Float32; + } + + enum ConfidenceClass { + red @0; + yellow @1; + green @2; + } + + struct DisengagePredictions { + t @0 :List(Float32); + brakeDisengageProbs @1 :List(Float32); + gasDisengageProbs @2 :List(Float32); + steerOverrideProbs @3 :List(Float32); + brake3MetersPerSecondSquaredProbs @4 :List(Float32); + brake4MetersPerSecondSquaredProbs @5 :List(Float32); + brake5MetersPerSecondSquaredProbs @6 :List(Float32); + gasPressProbs @7 :List(Float32); + brakePressProbs @8 :List(Float32); + } + + struct Pose { + trans @0 :List(Float32); # m/s in device frame + rot @1 :List(Float32); # rad/s in device frame + transStd @2 :List(Float32); # std m/s in device frame + rotStd @3 :List(Float32); # std rad/s in device frame + } + + struct LateralPlannerSolution { + x @0 :List(Float32); + y @1 :List(Float32); + yaw @2 :List(Float32); + yawRate @3 :List(Float32); + xStd @4 :List(Float32); + yStd @5 :List(Float32); + yawStd @6 :List(Float32); + yawRateStd @7 :List(Float32); + } + + struct Action { + desiredCurvature @0 :Float32; + desiredAcceleration @1 :Float32; + shouldStop @2 :Bool; + } +} + +struct EncodeIndex { + # picture from camera + frameId @0 :UInt32; + type @1 :Type; + # index of encoder from start of route + encodeId @2 :UInt32; + # minute long segment this frame is in + segmentNum @3 :Int32; + # index into camera file in segment in presentation order + segmentId @4 :UInt32; + # index into camera file in segment in encode order + segmentIdEncode @5 :UInt32; + timestampSof @6 :UInt64; + timestampEof @7 :UInt64; + + # encoder metadata + flags @8 :UInt32; + len @9 :UInt32; + + enum Type { + bigBoxLossless @0; + fullHEVC @1; + qcameraH264 @6; + livestreamH264 @7; + + # deprecated + bigBoxHEVCDEPRECATED @2; + chffrAndroidH264DEPRECATED @3; + fullLosslessClipDEPRECATED @4; + frontDEPRECATED @5; + + } +} + +struct AndroidLogEntry { + id @0 :UInt8; + ts @1 :UInt64; + priority @2 :UInt8; + pid @3 :Int32; + tid @4 :Int32; + tag @5 :Text; + message @6 :Text; +} + +struct DriverAssistance { + # Lane Departure Warnings + leftLaneDeparture @0 :Bool; + rightLaneDeparture @1 :Bool; + + # FCW, AEB, etc. will go here +} + +struct LongitudinalPlan @0xe00b5b3eba12876c { + modelMonoTime @9 :UInt64; + hasLead @7 :Bool; + fcw @8 :Bool; + longitudinalPlanSource @15 :LongitudinalPlanSource; + processingDelay @29 :Float32; + + # desired speed/accel/jerk over next 2.5s + accels @32 :List(Float32); + speeds @33 :List(Float32); + jerks @34 :List(Float32); + aTarget @18 :Float32; + shouldStop @37: Bool; + allowThrottle @38: Bool; + allowBrake @39: Bool; + + + solverExecutionTime @35 :Float32; + + enum LongitudinalPlanSource { + cruise @0; + lead0 @1; + lead1 @2; + lead2 @3; + e2e @4; + } + + # deprecated + vCruiseDEPRECATED @16 :Float32; + aCruiseDEPRECATED @17 :Float32; + vTargetDEPRECATED @3 :Float32; + vTargetFutureDEPRECATED @14 :Float32; + vStartDEPRECATED @26 :Float32; + aStartDEPRECATED @27 :Float32; + vMaxDEPRECATED @20 :Float32; + radarStateMonoTimeDEPRECATED @10 :UInt64; + jerkFactorDEPRECATED @6 :Float32; + hasLeftLaneDEPRECATED @23 :Bool; + hasRightLaneDEPRECATED @24 :Bool; + aTargetMinDEPRECATED @4 :Float32; + aTargetMaxDEPRECATED @5 :Float32; + lateralValidDEPRECATED @0 :Bool; + longitudinalValidDEPRECATED @2 :Bool; + dPolyDEPRECATED @1 :List(Float32); + laneWidthDEPRECATED @11 :Float32; + vCurvatureDEPRECATED @21 :Float32; + decelForTurnDEPRECATED @22 :Bool; + mapValidDEPRECATED @25 :Bool; + radarValidDEPRECATED @28 :Bool; + radarCanErrorDEPRECATED @30 :Bool; + commIssueDEPRECATED @31 :Bool; + eventsDEPRECATED @13 :List(Car.OnroadEventDEPRECATED); + gpsTrajectoryDEPRECATED @12 :GpsTrajectory; + gpsPlannerActiveDEPRECATED @19 :Bool; + personalityDEPRECATED @36 :LongitudinalPersonality; + + struct GpsTrajectory { + x @0 :List(Float32); + y @1 :List(Float32); + } +} +struct UiPlan { + frameId @2 :UInt32; + position @0 :XYZTData; + accel @1 :List(Float32); +} + +struct LateralPlan @0xe1e9318e2ae8b51e { + modelMonoTime @31 :UInt64; + laneWidthDEPRECATED @0 :Float32; + lProbDEPRECATED @5 :Float32; + rProbDEPRECATED @7 :Float32; + dPathPoints @20 :List(Float32); + dProbDEPRECATED @21 :Float32; + + mpcSolutionValid @9 :Bool; + desire @17 :Desire; + laneChangeState @18 :LaneChangeState; + laneChangeDirection @19 :LaneChangeDirection; + useLaneLines @29 :Bool; + + # desired curvatures over next 2.5s in rad/m + psis @26 :List(Float32); + curvatures @27 :List(Float32); + curvatureRates @28 :List(Float32); + + solverExecutionTime @30 :Float32; + solverCost @32 :Float32; + solverState @33 :SolverState; + + struct SolverState { + x @0 :List(List(Float32)); + u @1 :List(Float32); + } + + # deprecated + curvatureDEPRECATED @22 :Float32; + curvatureRateDEPRECATED @23 :Float32; + rawCurvatureDEPRECATED @24 :Float32; + rawCurvatureRateDEPRECATED @25 :Float32; + cProbDEPRECATED @3 :Float32; + dPolyDEPRECATED @1 :List(Float32); + cPolyDEPRECATED @2 :List(Float32); + lPolyDEPRECATED @4 :List(Float32); + rPolyDEPRECATED @6 :List(Float32); + modelValidDEPRECATED @12 :Bool; + commIssueDEPRECATED @15 :Bool; + posenetValidDEPRECATED @16 :Bool; + sensorValidDEPRECATED @14 :Bool; + paramsValidDEPRECATED @10 :Bool; + steeringAngleDegDEPRECATED @8 :Float32; # deg + steeringRateDegDEPRECATED @13 :Float32; # deg/s + angleOffsetDegDEPRECATED @11 :Float32; +} + +struct LiveLocationKalman { + + # More info on reference frames: + # https://github.com/commaai/openpilot/tree/master/common/transformations + + positionECEF @0 : Measurement; + positionGeodetic @1 : Measurement; + velocityECEF @2 : Measurement; + velocityNED @3 : Measurement; + velocityDevice @4 : Measurement; + accelerationDevice @5: Measurement; + + + # These angles are all eulers and roll, pitch, yaw + # orientationECEF transforms to rot matrix: ecef_from_device + orientationECEF @6 : Measurement; + calibratedOrientationECEF @20 : Measurement; + orientationNED @7 : Measurement; + angularVelocityDevice @8 : Measurement; + + # orientationNEDCalibrated transforms to rot matrix: NED_from_calibrated + calibratedOrientationNED @9 : Measurement; + + # Calibrated frame is simply device frame + # aligned with the vehicle + velocityCalibrated @10 : Measurement; + accelerationCalibrated @11 : Measurement; + angularVelocityCalibrated @12 : Measurement; + + gpsWeek @13 :Int32; + gpsTimeOfWeek @14 :Float64; + status @15 :Status; + unixTimestampMillis @16 :Int64; + inputsOK @17 :Bool = true; + posenetOK @18 :Bool = true; + gpsOK @19 :Bool = true; + sensorsOK @21 :Bool = true; + deviceStable @22 :Bool = true; + timeSinceReset @23 :Float64; + excessiveResets @24 :Bool; + timeToFirstFix @25 :Float32; + + filterState @26 : Measurement; + + enum Status { + uninitialized @0; + uncalibrated @1; + valid @2; + } + + struct Measurement { + value @0 : List(Float64); + std @1 : List(Float64); + valid @2 : Bool; + } +} + + +struct LivePose { + # More info on reference frames: + # https://github.com/commaai/openpilot/tree/master/common/transformations + orientationNED @0 :XYZMeasurement; + velocityDevice @1 :XYZMeasurement; + accelerationDevice @2 :XYZMeasurement; + angularVelocityDevice @3 :XYZMeasurement; + + inputsOK @4 :Bool = false; + posenetOK @5 :Bool = false; + sensorsOK @6 :Bool = false; + + debugFilterState @7 :FilterState; + + struct XYZMeasurement { + x @0 :Float32; + y @1 :Float32; + z @2 :Float32; + xStd @3 :Float32; + yStd @4 :Float32; + zStd @5 :Float32; + valid @6 :Bool; + } + + struct FilterState { + value @0 : List(Float64); + std @1 : List(Float64); + valid @2 : Bool; + + observations @3 :List(Observation); + + struct Observation { + kind @0 :Int32; + value @1 :List(Float32); + error @2 :List(Float32); + } + } +} + +struct ProcLog { + cpuTimes @0 :List(CPUTimes); + mem @1 :Mem; + procs @2 :List(Process); + + struct Process { + pid @0 :Int32; + name @1 :Text; + state @2 :UInt8; + ppid @3 :Int32; + + cpuUser @4 :Float32; + cpuSystem @5 :Float32; + cpuChildrenUser @6 :Float32; + cpuChildrenSystem @7 :Float32; + priority @8 :Int64; + nice @9 :Int32; + numThreads @10 :Int32; + startTime @11 :Float64; + + memVms @12 :UInt64; + memRss @13 :UInt64; + + processor @14 :Int32; + + cmdline @15 :List(Text); + exe @16 :Text; + } + + struct CPUTimes { + cpuNum @0 :Int64; + user @1 :Float32; + nice @2 :Float32; + system @3 :Float32; + idle @4 :Float32; + iowait @5 :Float32; + irq @6 :Float32; + softirq @7 :Float32; + } + + struct Mem { + total @0 :UInt64; + free @1 :UInt64; + available @2 :UInt64; + buffers @3 :UInt64; + cached @4 :UInt64; + active @5 :UInt64; + inactive @6 :UInt64; + shared @7 :UInt64; + } +} + +struct GnssMeasurements { + measTime @0 :UInt64; + gpsWeek @1 :Int16; + gpsTimeOfWeek @2 :Float64; + + correctedMeasurements @3 :List(CorrectedMeasurement); + ephemerisStatuses @9 :List(EphemerisStatus); + + kalmanPositionECEF @4 :LiveLocationKalman.Measurement; + kalmanVelocityECEF @5 :LiveLocationKalman.Measurement; + positionECEF @6 :LiveLocationKalman.Measurement; + velocityECEF @7 :LiveLocationKalman.Measurement; + timeToFirstFix @8 :Float32; + # Todo sync this with timing pulse of ublox + + struct EphemerisStatus { + constellationId @0 :ConstellationId; + svId @1 :UInt8; + type @2 :EphemerisType; + source @3 :EphemerisSource; + gpsWeek @4 : UInt16; + tow @5 :Float64; + } + + struct CorrectedMeasurement { + constellationId @0 :ConstellationId; + svId @1 :UInt8; + # Is 0 when not Glonass constellation. + glonassFrequency @2 :Int8; + pseudorange @3 :Float64; + pseudorangeStd @4 :Float64; + pseudorangeRate @5 :Float64; + pseudorangeRateStd @6 :Float64; + # Satellite position and velocity [x,y,z] + satPos @7 :List(Float64); + satVel @8 :List(Float64); + ephemerisSourceDEPRECATED @9 :EphemerisSourceDEPRECATED; + } + + struct EphemerisSourceDEPRECATED { + type @0 :EphemerisType; + # first epoch in file: + gpsWeek @1 :Int16; # -1 if Nav + gpsTimeOfWeek @2 :Int32; # -1 if Nav. Integer for seconds is good enough for logs. + } + + enum ConstellationId { + # Satellite Constellation using the Ublox gnssid as index + gps @0; + sbas @1; + galileo @2; + beidou @3; + imes @4; + qznss @5; + glonass @6; + } + + enum EphemerisType { + nav @0; + # Different ultra-rapid files: + nasaUltraRapid @1; + glonassIacUltraRapid @2; + qcom @3; + } + + enum EphemerisSource { + gnssChip @0; + internet @1; + cache @2; + unknown @3; + } +} + +struct UbloxGnss { + union { + measurementReport @0 :MeasurementReport; + ephemeris @1 :Ephemeris; + ionoData @2 :IonoData; + hwStatus @3 :HwStatus; + hwStatus2 @4 :HwStatus2; + glonassEphemeris @5 :GlonassEphemeris; + satReport @6 :SatReport; + } + + struct SatReport { + #received time of week in gps time in seconds and gps week + iTow @0 :UInt32; + svs @1 :List(SatInfo); + + struct SatInfo { + svId @0 :UInt8; + gnssId @1 :UInt8; + flagsBitfield @2 :UInt32; + cno @3 :UInt8; + elevationDeg @4 :Int8; + azimuthDeg @5 :Int16; + pseudorangeResidual @6 :Float32; + } + } + + struct MeasurementReport { + #received time of week in gps time in seconds and gps week + rcvTow @0 :Float64; + gpsWeek @1 :UInt16; + # leap seconds in seconds + leapSeconds @2 :UInt16; + # receiver status + receiverStatus @3 :ReceiverStatus; + # num of measurements to follow + numMeas @4 :UInt8; + measurements @5 :List(Measurement); + + struct ReceiverStatus { + # leap seconds have been determined + leapSecValid @0 :Bool; + # Clock reset applied + clkReset @1 :Bool; + } + + struct Measurement { + svId @0 :UInt8; + trackingStatus @1 :TrackingStatus; + # pseudorange in meters + pseudorange @2 :Float64; + # carrier phase measurement in cycles + carrierCycles @3 :Float64; + # doppler measurement in Hz + doppler @4 :Float32; + # GNSS id, 0 is gps + gnssId @5 :UInt8; + glonassFrequencyIndex @6 :UInt8; + # carrier phase locktime counter in ms + locktime @7 :UInt16; + # Carrier-to-noise density ratio (signal strength) in dBHz + cno @8 :UInt8; + # pseudorange standard deviation in meters + pseudorangeStdev @9 :Float32; + # carrier phase standard deviation in cycles + carrierPhaseStdev @10 :Float32; + # doppler standard deviation in Hz + dopplerStdev @11 :Float32; + sigId @12 :UInt8; + + struct TrackingStatus { + # pseudorange valid + pseudorangeValid @0 :Bool; + # carrier phase valid + carrierPhaseValid @1 :Bool; + # half cycle valid + halfCycleValid @2 :Bool; + # half cycle subtracted from phase + halfCycleSubtracted @3 :Bool; + } + } + } + + struct Ephemeris { + # This is according to the rinex (2?) format + svId @0 :UInt16; + year @1 :UInt16; + month @2 :UInt16; + day @3 :UInt16; + hour @4 :UInt16; + minute @5 :UInt16; + second @6 :Float32; + af0 @7 :Float64; + af1 @8 :Float64; + af2 @9 :Float64; + + iode @10 :Float64; + crs @11 :Float64; + deltaN @12 :Float64; + m0 @13 :Float64; + + cuc @14 :Float64; + ecc @15 :Float64; + cus @16 :Float64; + a @17 :Float64; # note that this is not the root!! + + toe @18 :Float64; + cic @19 :Float64; + omega0 @20 :Float64; + cis @21 :Float64; + + i0 @22 :Float64; + crc @23 :Float64; + omega @24 :Float64; + omegaDot @25 :Float64; + + iDot @26 :Float64; + codesL2 @27 :Float64; + gpsWeekDEPRECATED @28 :Float64; + l2 @29 :Float64; + + svAcc @30 :Float64; + svHealth @31 :Float64; + tgd @32 :Float64; + iodc @33 :Float64; + + transmissionTime @34 :Float64; + fitInterval @35 :Float64; + + toc @36 :Float64; + + ionoCoeffsValid @37 :Bool; + ionoAlpha @38 :List(Float64); + ionoBeta @39 :List(Float64); + + towCount @40 :UInt32; + toeWeek @41 :UInt16; + tocWeek @42 :UInt16; + } + + struct IonoData { + svHealth @0 :UInt32; + tow @1 :Float64; + gpsWeek @2 :Float64; + + ionoAlpha @3 :List(Float64); + ionoBeta @4 :List(Float64); + + healthValid @5 :Bool; + ionoCoeffsValid @6 :Bool; + } + + struct HwStatus { + noisePerMS @0 :UInt16; + agcCnt @1 :UInt16; + aStatus @2 :AntennaSupervisorState; + aPower @3 :AntennaPowerStatus; + jamInd @4 :UInt8; + flags @5 :UInt8; + + enum AntennaSupervisorState { + init @0; + dontknow @1; + ok @2; + short @3; + open @4; + } + + enum AntennaPowerStatus { + off @0; + on @1; + dontknow @2; + } + } + + struct HwStatus2 { + ofsI @0 :Int8; + magI @1 :UInt8; + ofsQ @2 :Int8; + magQ @3 :UInt8; + cfgSource @4 :ConfigSource; + lowLevCfg @5 :UInt32; + postStatus @6 :UInt32; + + enum ConfigSource { + undefined @0; + rom @1; + otp @2; + configpins @3; + flash @4; + } + } + + struct GlonassEphemeris { + svId @0 :UInt16; + year @1 :UInt16; + dayInYear @2 :UInt16; + hour @3 :UInt16; + minute @4 :UInt16; + second @5 :Float32; + + x @6 :Float64; + xVel @7 :Float64; + xAccel @8 :Float64; + y @9 :Float64; + yVel @10 :Float64; + yAccel @11 :Float64; + z @12 :Float64; + zVel @13 :Float64; + zAccel @14 :Float64; + + svType @15 :UInt8; + svURA @16 :Float32; + age @17 :UInt8; + + svHealth @18 :UInt8; + tkDEPRECATED @19 :UInt16; + tb @20 :UInt16; + + tauN @21 :Float64; + deltaTauN @22 :Float64; + gammaN @23 :Float64; + + p1 @24 :UInt8; + p2 @25 :UInt8; + p3 @26 :UInt8; + p4 @27 :UInt8; + + freqNumDEPRECATED @28 :UInt32; + + n4 @29 :UInt8; + nt @30 :UInt16; + freqNum @31 :Int16; + tkSeconds @32 :UInt32; + } +} + +struct QcomGnss @0xde94674b07ae51c1 { + logTs @0 :UInt64; + union { + measurementReport @1 :MeasurementReport; + clockReport @2 :ClockReport; + drMeasurementReport @3 :DrMeasurementReport; + drSvPoly @4 :DrSvPolyReport; + rawLog @5 :Data; + } + + enum MeasurementSource @0xd71a12b6faada7ee { + gps @0; + glonass @1; + beidou @2; + unknown3 @3; + unknown4 @4; + unknown5 @5; + sbas @6; + } + + enum SVObservationState @0xe81e829a0d6c83e9 { + idle @0; + search @1; + searchVerify @2; + bitEdge @3; + trackVerify @4; + track @5; + restart @6; + dpo @7; + glo10msBe @8; + glo10msAt @9; + } + + struct MeasurementStatus @0xe501010e1bcae83b { + subMillisecondIsValid @0 :Bool; + subBitTimeIsKnown @1 :Bool; + satelliteTimeIsKnown @2 :Bool; + bitEdgeConfirmedFromSignal @3 :Bool; + measuredVelocity @4 :Bool; + fineOrCoarseVelocity @5 :Bool; + lockPointValid @6 :Bool; + lockPointPositive @7 :Bool; + lastUpdateFromDifference @8 :Bool; + lastUpdateFromVelocityDifference @9 :Bool; + strongIndicationOfCrossCorelation @10 :Bool; + tentativeMeasurement @11 :Bool; + measurementNotUsable @12 :Bool; + sirCheckIsNeeded @13 :Bool; + probationMode @14 :Bool; + + glonassMeanderBitEdgeValid @15 :Bool; + glonassTimeMarkValid @16 :Bool; + + gpsRoundRobinRxDiversity @17 :Bool; + gpsRxDiversity @18 :Bool; + gpsLowBandwidthRxDiversityCombined @19 :Bool; + gpsHighBandwidthNu4 @20 :Bool; + gpsHighBandwidthNu8 @21 :Bool; + gpsHighBandwidthUniform @22 :Bool; + multipathIndicator @23 :Bool; + + imdJammingIndicator @24 :Bool; + lteB13TxJammingIndicator @25 :Bool; + freshMeasurementIndicator @26 :Bool; + + multipathEstimateIsValid @27 :Bool; + directionIsValid @28 :Bool; + } + + struct MeasurementReport @0xf580d7d86b7b8692 { + source @0 :MeasurementSource; + + fCount @1 :UInt32; + + gpsWeek @2 :UInt16; + glonassCycleNumber @3 :UInt8; + glonassNumberOfDays @4 :UInt16; + + milliseconds @5 :UInt32; + timeBias @6 :Float32; + clockTimeUncertainty @7 :Float32; + clockFrequencyBias @8 :Float32; + clockFrequencyUncertainty @9 :Float32; + + sv @10 :List(SV); + + struct SV @0xf10c595ae7bb2c27 { + svId @0 :UInt8; + observationState @2 :SVObservationState; + observations @3 :UInt8; + goodObservations @4 :UInt8; + gpsParityErrorCount @5 :UInt16; + glonassFrequencyIndex @1 :Int8; + glonassHemmingErrorCount @6 :UInt8; + filterStages @7 :UInt8; + carrierNoise @8 :UInt16; + latency @9 :Int16; + predetectInterval @10 :UInt8; + postdetections @11 :UInt16; + + unfilteredMeasurementIntegral @12 :UInt32; + unfilteredMeasurementFraction @13 :Float32; + unfilteredTimeUncertainty @14 :Float32; + unfilteredSpeed @15 :Float32; + unfilteredSpeedUncertainty @16 :Float32; + measurementStatus @17 :MeasurementStatus; + multipathEstimate @18 :UInt32; + azimuth @19 :Float32; + elevation @20 :Float32; + carrierPhaseCyclesIntegral @21 :Int32; + carrierPhaseCyclesFraction @22 :UInt16; + fineSpeed @23 :Float32; + fineSpeedUncertainty @24 :Float32; + cycleSlipCount @25 :UInt8; + } + + } + + struct ClockReport @0xca965e4add8f4f0b { + hasFCount @0 :Bool; + fCount @1 :UInt32; + + hasGpsWeek @2 :Bool; + gpsWeek @3 :UInt16; + hasGpsMilliseconds @4 :Bool; + gpsMilliseconds @5 :UInt32; + gpsTimeBias @6 :Float32; + gpsClockTimeUncertainty @7 :Float32; + gpsClockSource @8 :UInt8; + + hasGlonassYear @9 :Bool; + glonassYear @10 :UInt8; + hasGlonassDay @11 :Bool; + glonassDay @12 :UInt16; + hasGlonassMilliseconds @13 :Bool; + glonassMilliseconds @14 :UInt32; + glonassTimeBias @15 :Float32; + glonassClockTimeUncertainty @16 :Float32; + glonassClockSource @17 :UInt8; + + bdsWeek @18 :UInt16; + bdsMilliseconds @19 :UInt32; + bdsTimeBias @20 :Float32; + bdsClockTimeUncertainty @21 :Float32; + bdsClockSource @22 :UInt8; + + galWeek @23 :UInt16; + galMilliseconds @24 :UInt32; + galTimeBias @25 :Float32; + galClockTimeUncertainty @26 :Float32; + galClockSource @27 :UInt8; + + clockFrequencyBias @28 :Float32; + clockFrequencyUncertainty @29 :Float32; + frequencySource @30 :UInt8; + gpsLeapSeconds @31 :UInt8; + gpsLeapSecondsUncertainty @32 :UInt8; + gpsLeapSecondsSource @33 :UInt8; + + gpsToGlonassTimeBiasMilliseconds @34 :Float32; + gpsToGlonassTimeBiasMillisecondsUncertainty @35 :Float32; + gpsToBdsTimeBiasMilliseconds @36 :Float32; + gpsToBdsTimeBiasMillisecondsUncertainty @37 :Float32; + bdsToGloTimeBiasMilliseconds @38 :Float32; + bdsToGloTimeBiasMillisecondsUncertainty @39 :Float32; + gpsToGalTimeBiasMilliseconds @40 :Float32; + gpsToGalTimeBiasMillisecondsUncertainty @41 :Float32; + galToGloTimeBiasMilliseconds @42 :Float32; + galToGloTimeBiasMillisecondsUncertainty @43 :Float32; + galToBdsTimeBiasMilliseconds @44 :Float32; + galToBdsTimeBiasMillisecondsUncertainty @45 :Float32; + + hasRtcTime @46 :Bool; + systemRtcTime @47 :UInt32; + fCountOffset @48 :UInt32; + lpmRtcCount @49 :UInt32; + clockResets @50 :UInt32; + } + + struct DrMeasurementReport @0x8053c39445c6c75c { + + reason @0 :UInt8; + seqNum @1 :UInt8; + seqMax @2 :UInt8; + rfLoss @3 :UInt16; + + systemRtcValid @4 :Bool; + fCount @5 :UInt32; + clockResets @6 :UInt32; + systemRtcTime @7 :UInt64; + + gpsLeapSeconds @8 :UInt8; + gpsLeapSecondsUncertainty @9 :UInt8; + gpsToGlonassTimeBiasMilliseconds @10 :Float32; + gpsToGlonassTimeBiasMillisecondsUncertainty @11 :Float32; + + gpsWeek @12 :UInt16; + gpsMilliseconds @13 :UInt32; + gpsTimeBiasMs @14 :UInt32; + gpsClockTimeUncertaintyMs @15 :UInt32; + gpsClockSource @16 :UInt8; + + glonassClockSource @17 :UInt8; + glonassYear @18 :UInt8; + glonassDay @19 :UInt16; + glonassMilliseconds @20 :UInt32; + glonassTimeBias @21 :Float32; + glonassClockTimeUncertainty @22 :Float32; + + clockFrequencyBias @23 :Float32; + clockFrequencyUncertainty @24 :Float32; + frequencySource @25 :UInt8; + + source @26 :MeasurementSource; + + sv @27 :List(SV); + + struct SV @0xf08b81df8cbf459c { + svId @0 :UInt8; + glonassFrequencyIndex @1 :Int8; + observationState @2 :SVObservationState; + observations @3 :UInt8; + goodObservations @4 :UInt8; + filterStages @5 :UInt8; + predetectInterval @6 :UInt8; + cycleSlipCount @7 :UInt8; + postdetections @8 :UInt16; + + measurementStatus @9 :MeasurementStatus; + + carrierNoise @10 :UInt16; + rfLoss @11 :UInt16; + latency @12 :Int16; + + filteredMeasurementFraction @13 :Float32; + filteredMeasurementIntegral @14 :UInt32; + filteredTimeUncertainty @15 :Float32; + filteredSpeed @16 :Float32; + filteredSpeedUncertainty @17 :Float32; + + unfilteredMeasurementFraction @18 :Float32; + unfilteredMeasurementIntegral @19 :UInt32; + unfilteredTimeUncertainty @20 :Float32; + unfilteredSpeed @21 :Float32; + unfilteredSpeedUncertainty @22 :Float32; + + multipathEstimate @23 :UInt32; + azimuth @24 :Float32; + elevation @25 :Float32; + dopplerAcceleration @26 :Float32; + fineSpeed @27 :Float32; + fineSpeedUncertainty @28 :Float32; + + carrierPhase @29 :Float64; + fCount @30 :UInt32; + + parityErrorCount @31 :UInt16; + goodParity @32 :Bool; + } + } + + struct DrSvPolyReport @0xb1fb80811a673270 { + svId @0 :UInt16; + frequencyIndex @1 :Int8; + + hasPosition @2 :Bool; + hasIono @3 :Bool; + hasTropo @4 :Bool; + hasElevation @5 :Bool; + polyFromXtra @6 :Bool; + hasSbasIono @7 :Bool; + + iode @8 :UInt16; + t0 @9 :Float64; + xyz0 @10 :List(Float64); + xyzN @11 :List(Float64); + other @12 :List(Float32); + + positionUncertainty @13 :Float32; + ionoDelay @14 :Float32; + ionoDot @15 :Float32; + sbasIonoDelay @16 :Float32; + sbasIonoDot @17 :Float32; + tropoDelay @18 :Float32; + elevation @19 :Float32; + elevationDot @20 :Float32; + elevationUncertainty @21 :Float32; + velocityCoeff @22 :List(Float64); + + gpsWeek @23 :UInt16; + gpsTow @24 :Float64; + } +} + +struct Clocks { + wallTimeNanos @3 :UInt64; # unix epoch time + + bootTimeNanosDEPRECATED @0 :UInt64; + monotonicNanosDEPRECATED @1 :UInt64; + monotonicRawNanosDEPRECATD @2 :UInt64; + modemUptimeMillisDEPRECATED @4 :UInt64; +} + +struct LiveMpcData { + x @0 :List(Float32); + y @1 :List(Float32); + psi @2 :List(Float32); + curvature @3 :List(Float32); + qpIterations @4 :UInt32; + calculationTime @5 :UInt64; + cost @6 :Float64; +} + +struct LiveLongitudinalMpcData { + xEgo @0 :List(Float32); + vEgo @1 :List(Float32); + aEgo @2 :List(Float32); + xLead @3 :List(Float32); + vLead @4 :List(Float32); + aLead @5 :List(Float32); + aLeadTau @6 :Float32; # lead accel time constant + qpIterations @7 :UInt32; + mpcId @8 :UInt32; + calculationTime @9 :UInt64; + cost @10 :Float64; +} + +struct Joystick { + # convenient for debug and live tuning + axes @0: List(Float32); + buttons @1: List(Bool); +} + +struct DriverStateV2 { + frameId @0 :UInt32; + modelExecutionTime @1 :Float32; + gpuExecutionTime @8 :Float32; + rawPredictions @3 :Data; + + wheelOnRightProb @5 :Float32; + leftDriverData @6 :DriverData; + rightDriverData @7 :DriverData; + + struct DriverData { + faceOrientation @0 :List(Float32); + faceOrientationStd @1 :List(Float32); + facePosition @2 :List(Float32); + facePositionStd @3 :List(Float32); + faceProb @4 :Float32; + leftEyeProb @5 :Float32; + rightEyeProb @6 :Float32; + leftBlinkProb @7 :Float32; + rightBlinkProb @8 :Float32; + sunglassesProb @9 :Float32; + notReadyProb @12 :List(Float32); + occludedProbDEPRECATED @10 :Float32; + readyProbDEPRECATED @11 :List(Float32); + } + + dspExecutionTimeDEPRECATED @2 :Float32; + poorVisionProbDEPRECATED @4 :Float32; +} + +struct DriverStateDEPRECATED @0xb83c6cc593ed0a00 { + frameId @0 :UInt32; + modelExecutionTime @14 :Float32; + dspExecutionTime @16 :Float32; + rawPredictions @15 :Data; + + faceOrientation @3 :List(Float32); + facePosition @4 :List(Float32); + faceProb @5 :Float32; + leftEyeProb @6 :Float32; + rightEyeProb @7 :Float32; + leftBlinkProb @8 :Float32; + rightBlinkProb @9 :Float32; + faceOrientationStd @11 :List(Float32); + facePositionStd @12 :List(Float32); + sunglassesProb @13 :Float32; + poorVision @17 :Float32; + partialFace @18 :Float32; + distractedPose @19 :Float32; + distractedEyes @20 :Float32; + eyesOnRoad @21 :Float32; + phoneUse @22 :Float32; + occludedProb @23 :Float32; + + readyProb @24 :List(Float32); + notReadyProb @25 :List(Float32); + + irPwrDEPRECATED @10 :Float32; + descriptorDEPRECATED @1 :List(Float32); + stdDEPRECATED @2 :Float32; +} + +struct DriverMonitoringState @0xb83cda094a1da284 { + events @18 :List(OnroadEvent); + faceDetected @1 :Bool; + isDistracted @2 :Bool; + distractedType @17 :UInt32; + awarenessStatus @3 :Float32; + posePitchOffset @6 :Float32; + posePitchValidCount @7 :UInt32; + poseYawOffset @8 :Float32; + poseYawValidCount @9 :UInt32; + stepChange @10 :Float32; + awarenessActive @11 :Float32; + awarenessPassive @12 :Float32; + isLowStd @13 :Bool; + hiStdCount @14 :UInt32; + isActiveMode @16 :Bool; + isRHD @4 :Bool; + + isPreviewDEPRECATED @15 :Bool; + rhdCheckedDEPRECATED @5 :Bool; + eventsDEPRECATED @0 :List(Car.OnroadEventDEPRECATED); +} + +struct Boot { + wallTimeNanos @0 :UInt64; + pstore @4 :Map(Text, Data); + commands @5 :Map(Text, Data); + launchLog @3 :Text; + + lastKmsgDEPRECATED @1 :Data; + lastPmsgDEPRECATED @2 :Data; +} + +struct LiveParametersData { + valid @0 :Bool; + gyroBias @1 :Float32; + angleOffsetDeg @2 :Float32; + angleOffsetAverageDeg @3 :Float32; + stiffnessFactor @4 :Float32; + steerRatio @5 :Float32; + sensorValid @6 :Bool; + posenetSpeed @8 :Float32; + posenetValid @9 :Bool; + angleOffsetFastStd @10 :Float32; + angleOffsetAverageStd @11 :Float32; + stiffnessFactorStd @12 :Float32; + steerRatioStd @13 :Float32; + roll @14 :Float32; + debugFilterState @16 :FilterState; + + angleOffsetValid @17 :Bool = true; + angleOffsetAverageValid @18 :Bool = true; + steerRatioValid @19 :Bool = true; + stiffnessFactorValid @20 :Bool = true; + + yawRateDEPRECATED @7 :Float32; + filterStateDEPRECATED @15 :LiveLocationKalman.Measurement; + + struct FilterState { + value @0 : List(Float64); + std @1 : List(Float64); + } +} + +struct LiveTorqueParametersData { + liveValid @0 :Bool; + latAccelFactorRaw @1 :Float32; + latAccelOffsetRaw @2 :Float32; + frictionCoefficientRaw @3 :Float32; + latAccelFactorFiltered @4 :Float32; + latAccelOffsetFiltered @5 :Float32; + frictionCoefficientFiltered @6 :Float32; + totalBucketPoints @7 :Float32; + decay @8 :Float32; + maxResets @9 :Float32; + points @10 :List(List(Float32)); + version @11 :Int32; + useParams @12 :Bool; + calPerc @13 :Int8; +} + +struct LiveDelayData { + lateralDelay @0 :Float32; + validBlocks @1 :Int32; + status @2 :Status; + + lateralDelayEstimate @3 :Float32; + lateralDelayEstimateStd @5 :Float32; + points @4 :List(Float32); + calPerc @6 :Int8; + + enum Status { + unestimated @0; + estimated @1; + invalid @2; + } +} + +struct LiveMapDataDEPRECATED { + speedLimitValid @0 :Bool; + speedLimit @1 :Float32; + speedAdvisoryValid @12 :Bool; + speedAdvisory @13 :Float32; + speedLimitAheadValid @14 :Bool; + speedLimitAhead @15 :Float32; + speedLimitAheadDistance @16 :Float32; + curvatureValid @2 :Bool; + curvature @3 :Float32; + wayId @4 :UInt64; + roadX @5 :List(Float32); + roadY @6 :List(Float32); + lastGps @7: GpsLocationData; + roadCurvatureX @8 :List(Float32); + roadCurvature @9 :List(Float32); + distToTurn @10 :Float32; + mapValid @11 :Bool; +} + +struct CameraOdometry { + frameId @4 :UInt32; + timestampEof @5 :UInt64; + trans @0 :List(Float32); # m/s in device frame + rot @1 :List(Float32); # rad/s in device frame + transStd @2 :List(Float32); # std m/s in device frame + rotStd @3 :List(Float32); # std rad/s in device frame + wideFromDeviceEuler @6 :List(Float32); + wideFromDeviceEulerStd @7 :List(Float32); + roadTransformTrans @8 :List(Float32); + roadTransformTransStd @9 :List(Float32); +} + +struct Sentinel { + enum SentinelType { + endOfSegment @0; + endOfRoute @1; + startOfSegment @2; + startOfRoute @3; + } + type @0 :SentinelType; + signal @1 :Int32; +} + +struct UIDebug { + drawTimeMillis @0 :Float32; +} + +struct ManagerState { + processes @0 :List(ProcessState); + + struct ProcessState { + name @0 :Text; + pid @1 :Int32; + running @2 :Bool; + shouldBeRunning @4 :Bool; + exitCode @3 :Int32; + } +} + +struct UploaderState { + immediateQueueSize @0 :UInt32; + immediateQueueCount @1 :UInt32; + rawQueueSize @2 :UInt32; + rawQueueCount @3 :UInt32; + + # stats for last successfully uploaded file + lastTime @4 :Float32; # s + lastSpeed @5 :Float32; # MB/s + lastFilename @6 :Text; +} + +struct NavInstruction { + maneuverPrimaryText @0 :Text; + maneuverSecondaryText @1 :Text; + maneuverDistance @2 :Float32; # m + maneuverType @3 :Text; # TODO: Make Enum + maneuverModifier @4 :Text; # TODO: Make Enum + + distanceRemaining @5 :Float32; # m + timeRemaining @6 :Float32; # s + timeRemainingTypical @7 :Float32; # s + + lanes @8 :List(Lane); + showFull @9 :Bool; + + speedLimit @10 :Float32; # m/s + speedLimitSign @11 :SpeedLimitSign; + + allManeuvers @12 :List(Maneuver); + + struct Lane { + directions @0 :List(Direction); + active @1 :Bool; + activeDirection @2 :Direction; + } + + enum Direction { + none @0; + left @1; + right @2; + straight @3; + slightLeft @4; + slightRight @5; + } + + enum SpeedLimitSign { + mutcd @0; # US Style + vienna @1; # EU Style + } + + struct Maneuver { + distance @0 :Float32; + type @1 :Text; + modifier @2 :Text; + } +} + +struct NavRoute { + coordinates @0 :List(Coordinate); + + struct Coordinate { + latitude @0 :Float32; + longitude @1 :Float32; + } +} + +struct MapRenderState { + locationMonoTime @0 :UInt64; + renderTime @1 :Float32; + frameId @2: UInt32; +} + +struct NavModelData { + frameId @0 :UInt32; + locationMonoTime @6 :UInt64; + modelExecutionTime @1 :Float32; + dspExecutionTime @2 :Float32; + features @3 :List(Float32); + # predicted future position + position @4 :XYData; + desirePrediction @5 :List(Float32); + + # All SI units and in device frame + struct XYData { + x @0 :List(Float32); + y @1 :List(Float32); + xStd @2 :List(Float32); + yStd @3 :List(Float32); + } +} + +struct EncodeData { + idx @0 :EncodeIndex; + data @1 :Data; + header @2 :Data; + unixTimestampNanos @3 :UInt64; + width @4 :UInt32; + height @5 :UInt32; +} + +struct DebugAlert { + alertText1 @0 :Text; + alertText2 @1 :Text; +} + +struct UserBookmark @0xfe346a9de48d9b50 { +} + +struct SoundPressure @0xdc24138990726023 { + soundPressure @0 :Float32; + + # uncalibrated, A-weighted + soundPressureWeighted @3 :Float32; + soundPressureWeightedDb @1 :Float32; + + filteredSoundPressureWeightedDbDEPRECATED @2 :Float32; +} + +struct AudioData { + data @0 :Data; + sampleRate @1 :UInt32; +} + +struct AudioFeedback { + audio @0 :AudioData; + blockNum @1 :UInt16; +} + +struct Touch { + sec @0 :Int64; + usec @1 :Int64; + type @2 :UInt8; + code @3 :Int32; + value @4 :Int32; +} + +struct Event { + logMonoTime @0 :UInt64; # nanoseconds + valid @67 :Bool = true; + + union { + # *********** log metadata *********** + initData @1 :InitData; + sentinel @73 :Sentinel; + + # *********** bootlog *********** + boot @60 :Boot; + + # ********** openpilot daemon msgs ********** + gpsNMEA @3 :GPSNMEAData; + can @5 :List(CanData); + controlsState @7 :ControlsState; + selfdriveState @130 :SelfdriveState; + gyroscope @99 :SensorEventData; + gyroscope2 @100 :SensorEventData; + accelerometer @98 :SensorEventData; + accelerometer2 @101 :SensorEventData; + magnetometer @95 :SensorEventData; + lightSensor @96 :SensorEventData; + temperatureSensor @97 :SensorEventData; + temperatureSensor2 @123 :SensorEventData; + pandaStates @81 :List(PandaState); + peripheralState @80 :PeripheralState; + radarState @13 :RadarState; + liveTracks @131 :Car.RadarData; + sendcan @17 :List(CanData); + liveCalibration @19 :LiveCalibrationData; + carState @22 :Car.CarState; + carControl @23 :Car.CarControl; + carOutput @127 :Car.CarOutput; + longitudinalPlan @24 :LongitudinalPlan; + driverAssistance @132 :DriverAssistance; + ubloxGnss @34 :UbloxGnss; + ubloxRaw @39 :Data; + qcomGnss @31 :QcomGnss; + gpsLocationExternal @48 :GpsLocationData; + gpsLocation @21 :GpsLocationData; + gnssMeasurements @91 :GnssMeasurements; + liveParameters @61 :LiveParametersData; + liveTorqueParameters @94 :LiveTorqueParametersData; + liveDelay @146 : LiveDelayData; + cameraOdometry @63 :CameraOdometry; + thumbnail @66: Thumbnail; + onroadEvents @134: List(OnroadEvent); + carParams @69: Car.CarParams; + driverMonitoringState @71: DriverMonitoringState; + livePose @129 :LivePose; + modelV2 @75 :ModelDataV2; + drivingModelData @128 :DrivingModelData; + driverStateV2 @92 :DriverStateV2; + + # camera stuff, each camera state has a matching encode idx + roadCameraState @2 :FrameData; + driverCameraState @70: FrameData; + wideRoadCameraState @74: FrameData; + roadEncodeIdx @15 :EncodeIndex; + driverEncodeIdx @76 :EncodeIndex; + wideRoadEncodeIdx @77 :EncodeIndex; + qRoadEncodeIdx @90 :EncodeIndex; + + livestreamRoadEncodeIdx @117 :EncodeIndex; + livestreamWideRoadEncodeIdx @118 :EncodeIndex; + livestreamDriverEncodeIdx @119 :EncodeIndex; + + # microphone data + soundPressure @103 :SoundPressure; + rawAudioData @147 :AudioData; + + # systems stuff + androidLog @20 :AndroidLogEntry; + managerState @78 :ManagerState; + uploaderState @79 :UploaderState; + procLog @33 :ProcLog; + clocks @35 :Clocks; + deviceState @6 :DeviceState; + logMessage @18 :Text; + errorLogMessage @85 :Text; + + # touch frame + touch @135 :List(Touch); + + # navigation + navInstruction @82 :NavInstruction; + navRoute @83 :NavRoute; + navThumbnail @84: Thumbnail; + mapRenderState @105: MapRenderState; + + # UI services + uiDebug @102 :UIDebug; + + # driving feedback + userBookmark @93 :UserBookmark; + bookmarkButton @148 :UserBookmark; + audioFeedback @149 :AudioFeedback; + + # *********** debug *********** + testJoystick @52 :Joystick; + roadEncodeData @86 :EncodeData; + driverEncodeData @87 :EncodeData; + wideRoadEncodeData @88 :EncodeData; + qRoadEncodeData @89 :EncodeData; + alertDebug @133 :DebugAlert; + + livestreamRoadEncodeData @120 :EncodeData; + livestreamWideRoadEncodeData @121 :EncodeData; + livestreamDriverEncodeData @122 :EncodeData; + + # *********** Custom: reserved for forks *********** + + # DO change the name of the field + # DON'T change anything after the "@" + customReservedRawData0 @124 :Data; + customReservedRawData1 @125 :Data; + customReservedRawData2 @126 :Data; + + # DO change the name of the field and struct + # DON'T change the ID (e.g. @107) + # DON'T change which struct it points to + customReserved0 @107 :Custom.CustomReserved0; + customReserved1 @108 :Custom.CustomReserved1; + customReserved2 @109 :Custom.CustomReserved2; + customReserved3 @110 :Custom.CustomReserved3; + customReserved4 @111 :Custom.CustomReserved4; + customReserved5 @112 :Custom.CustomReserved5; + customReserved6 @113 :Custom.CustomReserved6; + customReserved7 @114 :Custom.CustomReserved7; + customReserved8 @115 :Custom.CustomReserved8; + customReserved9 @116 :Custom.CustomReserved9; + customReserved10 @136 :Custom.CustomReserved10; + customReserved11 @137 :Custom.CustomReserved11; + customReserved12 @138 :Custom.CustomReserved12; + customReserved13 @139 :Custom.CustomReserved13; + customReserved14 @140 :Custom.CustomReserved14; + customReserved15 @141 :Custom.CustomReserved15; + customReserved16 @142 :Custom.CustomReserved16; + customReserved17 @143 :Custom.CustomReserved17; + customReserved18 @144 :Custom.CustomReserved18; + customReserved19 @145 :Custom.CustomReserved19; + + # *********** legacy + deprecated *********** + model @9 :Legacy.ModelData; # TODO: rename modelV2 and mark this as deprecated + liveMpcDEPRECATED @36 :LiveMpcData; + liveLongitudinalMpcDEPRECATED @37 :LiveLongitudinalMpcData; + liveLocationKalmanLegacyDEPRECATED @51 :Legacy.LiveLocationData; + orbslamCorrectionDEPRECATED @45 :Legacy.OrbslamCorrection; + liveUIDEPRECATED @14 :Legacy.LiveUI; + sensorEventDEPRECATED @4 :SensorEventData; + liveEventDEPRECATED @8 :List(Legacy.LiveEventData); + liveLocationDEPRECATED @25 :Legacy.LiveLocationData; + ethernetDataDEPRECATED @26 :List(Legacy.EthernetPacket); + cellInfoDEPRECATED @28 :List(Legacy.CellInfo); + wifiScanDEPRECATED @29 :List(Legacy.WifiScan); + uiNavigationEventDEPRECATED @50 :Legacy.UiNavigationEvent; + liveMapDataDEPRECATED @62 :LiveMapDataDEPRECATED; + gpsPlannerPointsDEPRECATED @40 :Legacy.GPSPlannerPoints; + gpsPlannerPlanDEPRECATED @41 :Legacy.GPSPlannerPlan; + applanixRawDEPRECATED @42 :Data; + androidGnssDEPRECATED @30 :Legacy.AndroidGnss; + lidarPtsDEPRECATED @32 :Legacy.LidarPts; + navStatusDEPRECATED @38 :Legacy.NavStatus; + trafficEventsDEPRECATED @43 :List(Legacy.TrafficEvent); + liveLocationTimingDEPRECATED @44 :Legacy.LiveLocationData; + liveLocationCorrectedDEPRECATED @46 :Legacy.LiveLocationData; + navUpdateDEPRECATED @27 :Legacy.NavUpdate; + orbObservationDEPRECATED @47 :List(Legacy.OrbObservation); + locationDEPRECATED @49 :Legacy.LiveLocationData; + orbOdometryDEPRECATED @53 :Legacy.OrbOdometry; + orbFeaturesDEPRECATED @54 :Legacy.OrbFeatures; + applanixLocationDEPRECATED @55 :Legacy.LiveLocationData; + orbKeyFrameDEPRECATED @56 :Legacy.OrbKeyFrame; + orbFeaturesSummaryDEPRECATED @58 :Legacy.OrbFeaturesSummary; + featuresDEPRECATED @10 :Legacy.CalibrationFeatures; + kalmanOdometryDEPRECATED @65 :Legacy.KalmanOdometry; + uiLayoutStateDEPRECATED @57 :Legacy.UiLayoutState; + pandaStateDEPRECATED @12 :PandaState; + driverStateDEPRECATED @59 :DriverStateDEPRECATED; + sensorEventsDEPRECATED @11 :List(SensorEventData); + lateralPlanDEPRECATED @64 :LateralPlan; + navModelDEPRECATED @104 :NavModelData; + uiPlanDEPRECATED @106 :UiPlan; + liveLocationKalmanDEPRECATED @72 :LiveLocationKalman; + liveTracksDEPRECATED @16 :List(LiveTracksDEPRECATED); + onroadEventsDEPRECATED @68: List(Car.OnroadEventDEPRECATED); + } +} diff --git a/cereal/messaging/__init__.py b/cereal/messaging/__init__.py new file mode 100644 index 0000000000..b03285f80a --- /dev/null +++ b/cereal/messaging/__init__.py @@ -0,0 +1,257 @@ +# must be built with scons +from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \ + set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event +from msgq.ipc_pyx import MultiplePublishersError, IpcError +from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw +import msgq + +import os +import capnp +import time + +from typing import Optional, List, Union, Dict + +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.common.util import MovingAverage + +NO_TRAVERSAL_LIMIT = 2**64-1 + + +def reset_context(): + msgq.context = Context() + + +def log_from_bytes(dat: bytes, struct: capnp.lib.capnp._StructModule = log.Event) -> capnp.lib.capnp._DynamicStructReader: + with struct.from_bytes(dat, traversal_limit_in_words=NO_TRAVERSAL_LIMIT) as msg: + return msg + + +def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder: + args = { + 'valid': False, + 'logMonoTime': int(time.monotonic() * 1e9), + **kwargs + } + dat = log.Event.new_message(**args) + if service is not None: + if size is None: + dat.init(service) + else: + dat.init(service, size) + return dat + + +def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]: + """Receive all message currently available on the queue""" + msgs = drain_sock_raw(sock, wait_for_one=wait_for_one) + return [log_from_bytes(m) for m in msgs] + + +# TODO: print when we drop packets? +def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]: + """Same as drain sock, but only returns latest message. Consider using conflate instead.""" + dat = None + + while 1: + if wait and dat is None: + recv = sock.receive() + else: + recv = sock.receive(non_blocking=True) + + if recv is None: # Timeout hit + break + + dat = recv + + if dat is not None: + dat = log_from_bytes(dat) + + return dat + + +def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]: + dat = sock.receive() + if dat is not None: + dat = log_from_bytes(dat) + return dat + + +def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]: + dat = sock.receive(non_blocking=True) + if dat is not None: + dat = log_from_bytes(dat) + return dat + + +def recv_one_retry(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader: + """Keep receiving until we get a message""" + while True: + dat = sock.receive() + if dat is not None: + return log_from_bytes(dat) + + +class FrequencyTracker: + def __init__(self, service_freq: float, update_freq: float, is_poll: bool): + freq = max(min(service_freq, update_freq), 1.) + if is_poll: + min_freq = max_freq = freq + else: + max_freq = min(freq, update_freq) + if service_freq >= 2 * update_freq: + min_freq = update_freq + elif update_freq >= 2* service_freq: + min_freq = freq + else: + min_freq = min(freq, freq / 2.) + + self.min_freq = min_freq * 0.8 + self.max_freq = max_freq * 1.2 + self.avg_dt = MovingAverage(int(10 * freq)) + self.recent_avg_dt = MovingAverage(int(freq)) + self.prev_time = 0.0 + + def record_recv_time(self, cur_time: float) -> None: + # TODO: Handle case where cur_time is less than prev_time + if self.prev_time > 1e-5: + dt = cur_time - self.prev_time + + self.avg_dt.add_value(dt) + self.recent_avg_dt.add_value(dt) + + self.prev_time = cur_time + + @property + def valid(self) -> bool: + if self.avg_dt.count == 0: + return False + + avg_freq = 1.0 / self.avg_dt.get_average() + if self.min_freq <= avg_freq <= self.max_freq: + return True + + avg_freq_recent = 1.0 / self.recent_avg_dt.get_average() + return self.min_freq <= avg_freq_recent <= self.max_freq + + +class SubMaster: + def __init__(self, services: List[str], poll: Optional[str] = None, + ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None, + ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None): + self.frame = -1 + self.services = services + self.seen = {s: False for s in services} + self.updated = {s: False for s in services} + self.recv_time = {s: 0. for s in services} + self.recv_frame = {s: 0 for s in services} + self.sock = {} + self.data = {} + self.logMonoTime = {s: 0 for s in services} + + # zero-frequency / on-demand services are always alive and presumed valid; all others must pass checks + on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in services} + self.static_freq_services = set(s for s in services if not on_demand[s]) + self.alive = {s: on_demand[s] for s in services} + self.freq_ok = {s: on_demand[s] for s in services} + self.valid = {s: on_demand[s] for s in services} + + self.freq_tracker: Dict[str, FrequencyTracker] = {} + self.poller = Poller() + polled_services = set([poll, ] if poll is not None else services) + self.non_polled_services = set(services) - polled_services + + self.ignore_average_freq = [] if ignore_avg_freq is None else ignore_avg_freq + self.ignore_alive = [] if ignore_alive is None else ignore_alive + self.ignore_valid = [] if ignore_valid is None else ignore_valid + + self.simulation = bool(int(os.getenv("SIMULATION", "0"))) + + # if freq and poll aren't specified, assume the max to be conservative + assert frequency is None or poll is None, "Do not specify 'frequency' - frequency of the polled service will be used." + self.update_freq = frequency or max([SERVICE_LIST[s].frequency for s in polled_services]) + + for s in services: + p = self.poller if s not in self.non_polled_services else None + self.sock[s] = sub_sock(s, poller=p, addr=addr, conflate=True) + + try: + data = new_message(s) + except capnp.lib.capnp.KjException: + data = new_message(s, 0) # lists + + self.data[s] = getattr(data.as_reader(), s) + self.freq_tracker[s] = FrequencyTracker(SERVICE_LIST[s].frequency, self.update_freq, s == poll) + + def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader: + return self.data[s] + + def _check_avg_freq(self, s: str) -> bool: + return SERVICE_LIST[s].frequency > 0.99 and (s not in self.ignore_average_freq) and (s not in self.ignore_alive) + + def update(self, timeout: int = 100) -> None: + msgs = [] + for sock in self.poller.poll(timeout): + msgs.append(recv_one_or_none(sock)) + + # non-blocking receive for non-polled sockets + for s in self.non_polled_services: + msgs.append(recv_one_or_none(self.sock[s])) + self.update_msgs(time.monotonic(), msgs) + + def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None: + self.frame += 1 + self.updated = dict.fromkeys(self.services, False) + for msg in msgs: + if msg is None: + continue + + s = msg.which() + self.seen[s] = True + self.updated[s] = True + + self.freq_tracker[s].record_recv_time(cur_time) + self.recv_time[s] = cur_time + self.recv_frame[s] = self.frame + self.data[s] = getattr(msg, s) + self.logMonoTime[s] = msg.logMonoTime + self.valid[s] = msg.valid + + for s in self.static_freq_services: + # alive if delay is within 10x the expected frequency; checks relaxed in simulator + self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency) or (self.seen[s] and self.simulation) + self.freq_ok[s] = self.freq_tracker[s].valid or self.simulation + + def all_alive(self, service_list: Optional[List[str]] = None) -> bool: + return all(self.alive[s] for s in (service_list or self.services) if s not in self.ignore_alive) + + def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool: + return all(self.freq_ok[s] for s in (service_list or self.services) if self._check_avg_freq(s)) + + def all_valid(self, service_list: Optional[List[str]] = None) -> bool: + return all(self.valid[s] for s in (service_list or self.services) if s not in self.ignore_valid) + + def all_checks(self, service_list: Optional[List[str]] = None) -> bool: + return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list) + + +class PubMaster: + def __init__(self, services: List[str]): + self.sock = {} + for s in services: + self.sock[s] = pub_sock(s) + + def send(self, s: str, dat: Union[bytes, capnp.lib.capnp._DynamicStructBuilder]) -> None: + if not isinstance(dat, bytes): + dat = dat.to_bytes() + self.sock[s].send(dat) + + def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool: + for _ in range(int(timeout*(1./dt))): + if self.sock[s].all_readers_updated(): + return True + time.sleep(dt) + return False + + def all_readers_updated(self, s: str) -> bool: + return self.sock[s].all_readers_updated() # type: ignore diff --git a/cereal/messaging/bridge.cc b/cereal/messaging/bridge.cc new file mode 100644 index 0000000000..69ecd188e1 --- /dev/null +++ b/cereal/messaging/bridge.cc @@ -0,0 +1,71 @@ +#include + +#include "cereal/messaging/msgq_to_zmq.h" +#include "cereal/services.h" +#include "common/util.h" + +ExitHandler do_exit; + +static std::vector get_services(const std::string &whitelist_str, bool zmq_to_msgq) { + std::vector service_list; + for (const auto& it : services) { + std::string name = it.second.name; + bool in_whitelist = whitelist_str.find(name) != std::string::npos; + if (zmq_to_msgq && !in_whitelist) { + continue; + } + service_list.push_back(name); + } + return service_list; +} + +void msgq_to_zmq(const std::vector &endpoints, const std::string &ip) { + MsgqToZmq bridge; + bridge.run(endpoints, ip); +} + +void zmq_to_msgq(const std::vector &endpoints, const std::string &ip) { + auto poller = std::make_unique(); + auto pub_context = std::make_unique(); + auto sub_context = std::make_unique(); + std::map sub2pub; + + for (auto endpoint : endpoints) { + auto pub_sock = new MSGQPubSocket(); + auto sub_sock = new ZMQSubSocket(); + pub_sock->connect(pub_context.get(), endpoint); + sub_sock->connect(sub_context.get(), endpoint, ip, false); + + poller->registerSocket(sub_sock); + sub2pub[sub_sock] = pub_sock; + } + + while (!do_exit) { + for (auto sub_sock : poller->poll(100)) { + std::unique_ptr msg(sub_sock->receive(true)); + if (msg) { + sub2pub[sub_sock]->sendMessage(msg.get()); + } + } + } + + // Clean up allocated sockets + for (auto &[sub_sock, pub_sock] : sub2pub) { + delete sub_sock; + delete pub_sock; + } +} + +int main(int argc, char **argv) { + bool is_zmq_to_msgq = argc > 2; + std::string ip = is_zmq_to_msgq ? argv[1] : "127.0.0.1"; + std::string whitelist_str = is_zmq_to_msgq ? std::string(argv[2]) : ""; + std::vector endpoints = get_services(whitelist_str, is_zmq_to_msgq); + + if (is_zmq_to_msgq) { + zmq_to_msgq(endpoints, ip); + } else { + msgq_to_zmq(endpoints, ip); + } + return 0; +} diff --git a/cereal/messaging/messaging.h b/cereal/messaging/messaging.h new file mode 100644 index 0000000000..fb9c261f2b --- /dev/null +++ b/cereal/messaging/messaging.h @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include "cereal/gen/cpp/log.capnp.h" +#include "common/timing.h" +#include "msgq/ipc.h" + +class SubMaster { +public: + SubMaster(const std::vector &service_list, const std::vector &poll = {}, + const char *address = nullptr, const std::vector &ignore_alive = {}); + void update(int timeout = 1000); + void update_msgs(uint64_t current_time, const std::vector> &messages); + inline bool allAlive(const std::vector &service_list = {}) { return all_(service_list, false, true); } + inline bool allValid(const std::vector &service_list = {}) { return all_(service_list, true, false); } + inline bool allAliveAndValid(const std::vector &service_list = {}) { return all_(service_list, true, true); } + void drain(); + ~SubMaster(); + + uint64_t frame = 0; + bool updated(const char *name) const; + bool alive(const char *name) const; + bool valid(const char *name) const; + uint64_t rcv_frame(const char *name) const; + uint64_t rcv_time(const char *name) const; + cereal::Event::Reader &operator[](const char *name) const; + +private: + bool all_(const std::vector &service_list, bool valid, bool alive); + Poller *poller_ = nullptr; + struct SubMessage; + std::map messages_; + std::map services_; +}; + +class MessageBuilder : public capnp::MallocMessageBuilder { +public: + MessageBuilder() = default; + + cereal::Event::Builder initEvent(bool valid = true) { + cereal::Event::Builder event = initRoot(); + event.setLogMonoTime(nanos_since_boot()); + event.setValid(valid); + return event; + } + + kj::ArrayPtr toBytes() { + heapArray_ = capnp::messageToFlatArray(*this); + return heapArray_.asBytes(); + } + + size_t getSerializedSize() { + return capnp::computeSerializedSizeInWords(*this) * sizeof(capnp::word); + } + + int serializeToBuffer(unsigned char *buffer, size_t buffer_size) { + size_t serialized_size = getSerializedSize(); + if (serialized_size > buffer_size) { return -1; } + kj::ArrayOutputStream out(kj::ArrayPtr(buffer, buffer_size)); + capnp::writeMessage(out, *this); + return serialized_size; + } + +private: + kj::Array heapArray_; +}; + +class PubMaster { +public: + PubMaster(const std::vector &service_list); + inline int send(const char *name, capnp::byte *data, size_t size) { return sockets_.at(name)->send((char *)data, size); } + int send(const char *name, MessageBuilder &msg); + ~PubMaster(); + +private: + std::map sockets_; +}; + +class AlignedBuffer { +public: + kj::ArrayPtr align(const char *data, const size_t size) { + words_size = size / sizeof(capnp::word) + 1; + if (aligned_buf.size() < words_size) { + aligned_buf = kj::heapArray(words_size < 512 ? 512 : words_size); + } + memcpy(aligned_buf.begin(), data, size); + return aligned_buf.slice(0, words_size); + } + inline kj::ArrayPtr align(Message *m) { + return align(m->getData(), m->getSize()); + } +private: + kj::Array aligned_buf; + size_t words_size; +}; diff --git a/cereal/messaging/msgq_to_zmq.cc b/cereal/messaging/msgq_to_zmq.cc new file mode 100644 index 0000000000..ce626f2aad --- /dev/null +++ b/cereal/messaging/msgq_to_zmq.cc @@ -0,0 +1,144 @@ +#include "cereal/messaging/msgq_to_zmq.h" + +#include + +#include "common/util.h" + +extern ExitHandler do_exit; + +// Max messages to process per socket per poll +constexpr int MAX_MESSAGES_PER_SOCKET = 50; + +static std::string recv_zmq_msg(void *sock) { + zmq_msg_t msg; + zmq_msg_init(&msg); + std::string ret; + if (zmq_msg_recv(&msg, sock, 0) > 0) { + ret.assign((char *)zmq_msg_data(&msg), zmq_msg_size(&msg)); + } + zmq_msg_close(&msg); + return ret; +} + +void MsgqToZmq::run(const std::vector &endpoints, const std::string &ip) { + zmq_context = std::make_unique(); + msgq_context = std::make_unique(); + + // Create ZMQPubSockets for each endpoint + for (const auto &endpoint : endpoints) { + auto &socket_pair = socket_pairs.emplace_back(); + socket_pair.endpoint = endpoint; + socket_pair.pub_sock = std::make_unique(); + int ret = socket_pair.pub_sock->connect(zmq_context.get(), endpoint); + if (ret != 0) { + printf("Failed to create ZMQ publisher for [%s]: %s\n", endpoint.c_str(), zmq_strerror(zmq_errno())); + return; + } + } + + // Start ZMQ monitoring thread to monitor socket events + std::thread thread(&MsgqToZmq::zmqMonitorThread, this); + + // Main loop for processing messages + while (!do_exit) { + { + std::unique_lock lk(mutex); + cv.wait(lk, [this]() { return do_exit || !sub2pub.empty(); }); + if (do_exit) break; + + for (auto sub_sock : msgq_poller->poll(100)) { + // Process messages for each socket + ZMQPubSocket *pub_sock = sub2pub.at(sub_sock); + for (int i = 0; i < MAX_MESSAGES_PER_SOCKET; ++i) { + auto msg = std::unique_ptr(sub_sock->receive(true)); + if (!msg) break; + + while (pub_sock->sendMessage(msg.get()) == -1) { + if (errno != EINTR) break; + } + } + } + } + util::sleep_for(1); // Give zmqMonitorThread a chance to acquire the mutex + } + + thread.join(); +} + +void MsgqToZmq::zmqMonitorThread() { + std::vector pollitems; + + // Set up ZMQ monitor for each pub socket + for (int i = 0; i < socket_pairs.size(); ++i) { + std::string addr = "inproc://op-bridge-monitor-" + std::to_string(i); + zmq_socket_monitor(socket_pairs[i].pub_sock->sock, addr.c_str(), ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED); + + void *monitor_socket = zmq_socket(zmq_context->getRawContext(), ZMQ_PAIR); + zmq_connect(monitor_socket, addr.c_str()); + pollitems.emplace_back(zmq_pollitem_t{.socket = monitor_socket, .events = ZMQ_POLLIN}); + } + + while (!do_exit) { + int ret = zmq_poll(pollitems.data(), pollitems.size(), 1000); + if (ret < 0) { + if (errno == EINTR) { + // Due to frequent EINTR signals from msgq, introduce a brief delay (200 ms) + // to reduce CPU usage during retry attempts. + util::sleep_for(200); + } + continue; + } + + for (int i = 0; i < pollitems.size(); ++i) { + if (pollitems[i].revents & ZMQ_POLLIN) { + // First frame in message contains event number and value + std::string frame = recv_zmq_msg(pollitems[i].socket); + if (frame.empty()) continue; + + uint16_t event_type = *(uint16_t *)(frame.data()); + + // Second frame in message contains event address + frame = recv_zmq_msg(pollitems[i].socket); + if (frame.empty()) continue; + + std::unique_lock lk(mutex); + auto &pair = socket_pairs[i]; + if (event_type & ZMQ_EVENT_ACCEPTED) { + printf("socket [%s] connected\n", pair.endpoint.c_str()); + if (++pair.connected_clients == 1) { + // Create new MSGQ subscriber socket and map to ZMQ publisher + pair.sub_sock = std::make_unique(); + pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1"); + sub2pub[pair.sub_sock.get()] = pair.pub_sock.get(); + registerSockets(); + } + } else if (event_type & ZMQ_EVENT_DISCONNECTED) { + printf("socket [%s] disconnected\n", pair.endpoint.c_str()); + if (pair.connected_clients == 0 || --pair.connected_clients == 0) { + // Remove MSGQ subscriber socket from mapping and reset it + sub2pub.erase(pair.sub_sock.get()); + pair.sub_sock.reset(nullptr); + registerSockets(); + } + } + cv.notify_one(); + } + } + } + + // Clean up monitor sockets + for (int i = 0; i < pollitems.size(); ++i) { + zmq_socket_monitor(socket_pairs[i].pub_sock->sock, nullptr, 0); + zmq_close(pollitems[i].socket); + } + cv.notify_one(); +} + +void MsgqToZmq::registerSockets() { + msgq_poller = std::make_unique(); + for (const auto &socket_pair : socket_pairs) { + if (socket_pair.sub_sock) { + msgq_poller->registerSocket(socket_pair.sub_sock.get()); + } + } +} diff --git a/cereal/messaging/msgq_to_zmq.h b/cereal/messaging/msgq_to_zmq.h new file mode 100644 index 0000000000..ebdbe5df69 --- /dev/null +++ b/cereal/messaging/msgq_to_zmq.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#define private public +#include "msgq/impl_msgq.h" +#include "msgq/impl_zmq.h" + +class MsgqToZmq { +public: + MsgqToZmq() {} + void run(const std::vector &endpoints, const std::string &ip); + +protected: + void registerSockets(); + void zmqMonitorThread(); + + struct SocketPair { + std::string endpoint; + std::unique_ptr pub_sock; + std::unique_ptr sub_sock; + int connected_clients = 0; + }; + + std::unique_ptr msgq_context; + std::unique_ptr zmq_context; + std::mutex mutex; + std::condition_variable cv; + std::unique_ptr msgq_poller; + std::map sub2pub; + std::vector socket_pairs; +}; diff --git a/cereal/messaging/socketmaster.cc b/cereal/messaging/socketmaster.cc new file mode 100644 index 0000000000..7f7e2795c4 --- /dev/null +++ b/cereal/messaging/socketmaster.cc @@ -0,0 +1,203 @@ +#include +#include +#include +#include + +#include "cereal/services.h" +#include "cereal/messaging/messaging.h" + +const bool SIMULATION = (getenv("SIMULATION") != nullptr) && (std::string(getenv("SIMULATION")) == "1"); + +static inline bool inList(const std::vector &list, const char *value) { + for (auto &v : list) { + if (strcmp(value, v) == 0) return true; + } + return false; +} + +class MessageContext { +public: + MessageContext() : ctx_(nullptr) {} + ~MessageContext() { delete ctx_; } + inline Context *context() { + std::call_once(init_flag, [=]() { ctx_ = Context::create(); }); + return ctx_; + } +private: + Context *ctx_; + std::once_flag init_flag; +}; + +MessageContext message_context; + +struct SubMaster::SubMessage { + std::string name; + SubSocket *socket = nullptr; + float freq = 0.0f; + bool updated = false, alive = false, valid = false, ignore_alive; + uint64_t rcv_time = 0, rcv_frame = 0; + void *allocated_msg_reader = nullptr; + bool is_polled = false; + capnp::FlatArrayMessageReader *msg_reader = nullptr; + AlignedBuffer aligned_buf; + cereal::Event::Reader event; +}; + +SubMaster::SubMaster(const std::vector &service_list, const std::vector &poll, + const char *address, const std::vector &ignore_alive) { + poller_ = Poller::create(); + for (auto name : service_list) { + assert(services.count(std::string(name)) > 0); + + service serv = services.at(std::string(name)); + SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true); + assert(socket != 0); + bool is_polled = inList(poll, name) || poll.empty(); + if (is_polled) poller_->registerSocket(socket); + SubMessage *m = new SubMessage{ + .name = name, + .socket = socket, + .freq = serv.frequency, + .ignore_alive = inList(ignore_alive, name), + .allocated_msg_reader = malloc(sizeof(capnp::FlatArrayMessageReader)), + .is_polled = is_polled}; + m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader({}); + messages_[socket] = m; + services_[name] = m; + } +} + +void SubMaster::update(int timeout) { + for (auto &kv : messages_) kv.second->updated = false; + + auto sockets = poller_->poll(timeout); + + // add non-polled sockets for non-blocking receive + for (auto &kv : messages_) { + SubMessage *m = kv.second; + SubSocket *s = kv.first; + if (!m->is_polled) sockets.push_back(s); + } + + uint64_t current_time = nanos_since_boot(); + + std::vector> messages; + + for (auto s : sockets) { + Message *msg = s->receive(true); + if (msg == nullptr) continue; + + SubMessage *m = messages_.at(s); + + m->msg_reader->~FlatArrayMessageReader(); + capnp::ReaderOptions options; + options.traversalLimitInWords = kj::maxValue; // Don't limit + m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader(m->aligned_buf.align(msg), options); + delete msg; + messages.push_back({m->name, m->msg_reader->getRoot()}); + } + + update_msgs(current_time, messages); +} + +void SubMaster::update_msgs(uint64_t current_time, const std::vector> &messages){ + if (++frame == UINT64_MAX) frame = 1; + + for (auto &kv : messages) { + auto m_find = services_.find(kv.first); + if (m_find == services_.end()){ + continue; + } + SubMessage *m = m_find->second; + m->event = kv.second; + m->updated = true; + m->rcv_time = current_time; + m->rcv_frame = frame; + m->valid = m->event.getValid(); + if (SIMULATION) m->alive = true; + } + + if (!SIMULATION) { + for (auto &kv : messages_) { + SubMessage *m = kv.second; + m->alive = (m->freq <= (1e-5) || ((current_time - m->rcv_time) * (1e-9)) < (10.0 / m->freq)); + } + } +} + +bool SubMaster::all_(const std::vector &service_list, bool valid, bool alive) { + int found = 0; + for (auto &kv : messages_) { + SubMessage *m = kv.second; + if (service_list.size() == 0 || inList(service_list, m->name.c_str())) { + found += (!valid || m->valid) && (!alive || (m->alive || m->ignore_alive)); + } + } + return service_list.size() == 0 ? found == messages_.size() : found == service_list.size(); +} + +void SubMaster::drain() { + while (true) { + auto polls = poller_->poll(0); + if (polls.size() == 0) + break; + + for (auto sock : polls) { + Message *msg = sock->receive(true); + delete msg; + } + } +} + +bool SubMaster::updated(const char *name) const { + return services_.at(name)->updated; +} + +bool SubMaster::alive(const char *name) const { + return services_.at(name)->alive; +} + +bool SubMaster::valid(const char *name) const { + return services_.at(name)->valid; +} + +uint64_t SubMaster::rcv_frame(const char *name) const { + return services_.at(name)->rcv_frame; +} + +uint64_t SubMaster::rcv_time(const char *name) const { + return services_.at(name)->rcv_time; +} + +cereal::Event::Reader &SubMaster::operator[](const char *name) const { + return services_.at(name)->event; +} + +SubMaster::~SubMaster() { + delete poller_; + for (auto &kv : messages_) { + SubMessage *m = kv.second; + m->msg_reader->~FlatArrayMessageReader(); + free(m->allocated_msg_reader); + delete m->socket; + delete m; + } +} + +PubMaster::PubMaster(const std::vector &service_list) { + for (auto name : service_list) { + assert(services.count(name) > 0); + PubSocket *socket = PubSocket::create(message_context.context(), name); + assert(socket); + sockets_[name] = socket; + } +} + +int PubMaster::send(const char *name, MessageBuilder &msg) { + auto bytes = msg.toBytes(); + return send(name, bytes.begin(), bytes.size()); +} + +PubMaster::~PubMaster() { + for (auto s : sockets_) delete s.second; +} diff --git a/cereal/messaging/tests/__init__.py b/cereal/messaging/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cereal/messaging/tests/test_messaging.py b/cereal/messaging/tests/test_messaging.py new file mode 100644 index 0000000000..583eb8b0d8 --- /dev/null +++ b/cereal/messaging/tests/test_messaging.py @@ -0,0 +1,185 @@ +import os +import capnp +import multiprocessing +import numbers +import random +import threading +import time +from parameterized import parameterized +import pytest + +from cereal import log, car +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST + +events = [evt for evt in log.Event.schema.union_fields if evt in SERVICE_LIST.keys()] + +def random_sock(): + return random.choice(events) + +def random_socks(num_socks=10): + return list({random_sock() for _ in range(num_socks)}) + +def random_bytes(length=1000): + return bytes([random.randrange(0xFF) for _ in range(length)]) + +def zmq_sleep(t=1): + if "ZMQ" in os.environ: + time.sleep(t) + + +# TODO: this should take any capnp struct and returrn a msg with random populated data +def random_carstate(): + fields = ["vEgo", "aEgo", "brake", "steeringAngleDeg"] + msg = messaging.new_message("carState") + cs = msg.carState + for f in fields: + setattr(cs, f, random.random() * 10) + return msg + +# TODO: this should compare any capnp structs +def assert_carstate(cs1, cs2): + for f in car.CarState.schema.non_union_fields: + # TODO: check all types + val1, val2 = getattr(cs1, f), getattr(cs2, f) + if isinstance(val1, numbers.Number): + assert val1 == val2, f"{f}: sent '{val1}' vs recvd '{val2}'" + +def delayed_send(delay, sock, dat): + def send_func(): + sock.send(dat) + threading.Timer(delay, send_func).start() + + +class TestMessaging: + def setUp(self): + # TODO: ZMQ tests are too slow; all sleeps will need to be + # replaced with logic to block on the necessary condition + if "ZMQ" in os.environ: + pytest.skip() + + # ZMQ pub socket takes too long to die + # sleep to prevent multiple publishers error between tests + zmq_sleep() + + @parameterized.expand(events) + def test_new_message(self, evt): + try: + msg = messaging.new_message(evt) + except capnp.lib.capnp.KjException: + msg = messaging.new_message(evt, random.randrange(200)) + assert (time.monotonic() - msg.logMonoTime) < 0.1 + assert not msg.valid + assert evt == msg.which() + + @parameterized.expand(events) + def test_pub_sock(self, evt): + messaging.pub_sock(evt) + + @parameterized.expand(events) + def test_sub_sock(self, evt): + messaging.sub_sock(evt) + + @parameterized.expand([ + (messaging.drain_sock, capnp._DynamicStructReader), + (messaging.drain_sock_raw, bytes), + ]) + def test_drain_sock(self, func, expected_type): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sub_sock = messaging.sub_sock(sock, timeout=1000) + zmq_sleep() + + # no wait and no msgs in queue + msgs = func(sub_sock) + assert isinstance(msgs, list) + assert len(msgs) == 0 + + # no wait but msgs are queued up + num_msgs = random.randrange(3, 10) + for _ in range(num_msgs): + pub_sock.send(messaging.new_message(sock).to_bytes()) + time.sleep(0.1) + msgs = func(sub_sock) + assert isinstance(msgs, list) + assert all(isinstance(msg, expected_type) for msg in msgs) + assert len(msgs) == num_msgs + + def test_recv_sock(self): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sub_sock = messaging.sub_sock(sock, timeout=100) + zmq_sleep() + + # no wait and no msg in queue, socket should timeout + recvd = messaging.recv_sock(sub_sock) + assert recvd is None + + # no wait and one msg in queue + msg = random_carstate() + pub_sock.send(msg.to_bytes()) + time.sleep(0.01) + recvd = messaging.recv_sock(sub_sock) + assert isinstance(recvd, capnp._DynamicStructReader) + # https://github.com/python/mypy/issues/13038 + assert_carstate(msg.carState, recvd.carState) + + def test_recv_one(self): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sub_sock = messaging.sub_sock(sock, timeout=1000) + zmq_sleep() + + # no msg in queue, socket should timeout + recvd = messaging.recv_one(sub_sock) + assert recvd is None + + # one msg in queue + msg = random_carstate() + pub_sock.send(msg.to_bytes()) + recvd = messaging.recv_one(sub_sock) + assert isinstance(recvd, capnp._DynamicStructReader) + assert_carstate(msg.carState, recvd.carState) + + @pytest.mark.xfail(condition="ZMQ" in os.environ, reason='ZMQ detected') + def test_recv_one_or_none(self): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sub_sock = messaging.sub_sock(sock) + zmq_sleep() + + # no msg in queue, socket shouldn't block + recvd = messaging.recv_one_or_none(sub_sock) + assert recvd is None + + # one msg in queue + msg = random_carstate() + pub_sock.send(msg.to_bytes()) + recvd = messaging.recv_one_or_none(sub_sock) + assert isinstance(recvd, capnp._DynamicStructReader) + assert_carstate(msg.carState, recvd.carState) + + def test_recv_one_retry(self): + sock = "carState" + sock_timeout = 0.1 + pub_sock = messaging.pub_sock(sock) + sub_sock = messaging.sub_sock(sock, timeout=round(sock_timeout*1000)) + zmq_sleep() + + # this test doesn't work with ZMQ since multiprocessing interrupts it + if "ZMQ" not in os.environ: + # wait 5 socket timeouts and make sure it's still retrying + p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,)) + p.start() + time.sleep(sock_timeout*5) + assert p.is_alive() + p.terminate() + + # wait 5 socket timeouts before sending + msg = random_carstate() + start_time = time.monotonic() + delayed_send(sock_timeout*5, pub_sock, msg.to_bytes()) + recvd = messaging.recv_one_retry(sub_sock) + assert (time.monotonic() - start_time) >= sock_timeout*5 + assert isinstance(recvd, capnp._DynamicStructReader) + assert_carstate(msg.carState, recvd.carState) diff --git a/cereal/messaging/tests/test_pub_sub_master.py b/cereal/messaging/tests/test_pub_sub_master.py new file mode 100644 index 0000000000..5e26b49701 --- /dev/null +++ b/cereal/messaging/tests/test_pub_sub_master.py @@ -0,0 +1,160 @@ +import random +import time +from typing import Sized, cast + +import cereal.messaging as messaging +from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \ + random_bytes, random_carstate, assert_carstate, \ + zmq_sleep +from cereal.services import SERVICE_LIST + + +class TestSubMaster: + + def setup_method(self): + # ZMQ pub socket takes too long to die + # sleep to prevent multiple publishers error between tests + zmq_sleep(3) + + def test_init(self): + sm = messaging.SubMaster(events) + for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive, + sm.sock, sm.data, sm.logMonoTime, sm.valid]: + assert len(cast(Sized, p)) == len(events) + + def test_init_state(self): + socks = random_socks() + sm = messaging.SubMaster(socks) + assert sm.frame == -1 + assert not any(sm.updated.values()) + assert not any(sm.seen.values()) + on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in sm.services} + assert all(sm.alive[s] == sm.valid[s] == sm.freq_ok[s] == on_demand[s] for s in sm.services) + assert all(t == 0. for t in sm.recv_time.values()) + assert all(f == 0 for f in sm.recv_frame.values()) + assert all(t == 0 for t in sm.logMonoTime.values()) + + for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive, + sm.sock, sm.data, sm.logMonoTime, sm.valid]: + assert len(cast(Sized, p)) == len(socks) + + def test_getitem(self): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sm = messaging.SubMaster([sock,]) + zmq_sleep() + + msg = random_carstate() + pub_sock.send(msg.to_bytes()) + sm.update(1000) + assert_carstate(msg.carState, sm[sock]) + + # TODO: break this test up to individually test SubMaster.update and SubMaster.update_msgs + def test_update(self): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sm = messaging.SubMaster([sock,]) + zmq_sleep() + + for i in range(10): + msg = messaging.new_message(sock) + pub_sock.send(msg.to_bytes()) + sm.update(1000) + assert sm.frame == i + assert all(sm.updated.values()) + + def test_update_timeout(self): + sock = random_sock() + sm = messaging.SubMaster([sock,]) + timeout = random.randrange(1000, 3000) + start_time = time.monotonic() + sm.update(timeout) + t = time.monotonic() - start_time + assert t >= timeout/1000. + assert t < 3 + assert not any(sm.updated.values()) + + def test_avg_frequency_checks(self): + for poll in (True, False): + sm = messaging.SubMaster(["modelV2", "carParams", "carState", "cameraOdometry", "liveCalibration"], + poll=("modelV2" if poll else None), + frequency=(20. if not poll else None)) + + checks = { + "carState": (20, 20), + "modelV2": (20, 20 if poll else 10), + "cameraOdometry": (20, 10), + "liveCalibration": (4, 4), + "carParams": (None, None), + "userBookmark": (None, None), + } + + for service, (max_freq, min_freq) in checks.items(): + if max_freq is not None: + assert sm._check_avg_freq(service) + assert sm.freq_tracker[service].max_freq == max_freq*1.2 + assert sm.freq_tracker[service].min_freq == min_freq*0.8 + else: + assert not sm._check_avg_freq(service) + + def test_alive(self): + pass + + def test_ignore_alive(self): + pass + + def test_valid(self): + pass + + # SubMaster should always conflate + def test_conflate(self): + sock = "carState" + pub_sock = messaging.pub_sock(sock) + sm = messaging.SubMaster([sock,]) + + n = 10 + for i in range(n+1): + msg = messaging.new_message(sock) + msg.carState.vEgo = i + pub_sock.send(msg.to_bytes()) + time.sleep(0.01) + sm.update(1000) + assert sm[sock].vEgo == n + + +class TestPubMaster: + + def setup_method(self): + # ZMQ pub socket takes too long to die + # sleep to prevent multiple publishers error between tests + zmq_sleep(3) + + def test_init(self): + messaging.PubMaster(events) + + def test_send(self): + socks = random_socks() + pm = messaging.PubMaster(socks) + sub_socks = {s: messaging.sub_sock(s, conflate=True, timeout=1000) for s in socks} + zmq_sleep() + + # PubMaster accepts either a capnp msg builder or bytes + for capnp in [True, False]: + for i in range(100): + sock = socks[i % len(socks)] + + if capnp: + try: + msg = messaging.new_message(sock) + except Exception: + msg = messaging.new_message(sock, random.randrange(50)) + else: + msg = random_bytes() + + pm.send(sock, msg) + recvd = sub_socks[sock].receive() + + if capnp: + msg.clear_write_flag() + msg = msg.to_bytes() + assert msg == recvd, i diff --git a/cereal/messaging/tests/test_services.py b/cereal/messaging/tests/test_services.py new file mode 100644 index 0000000000..8bfd2ea978 --- /dev/null +++ b/cereal/messaging/tests/test_services.py @@ -0,0 +1,21 @@ +import os +import tempfile +from typing import Dict +from parameterized import parameterized + +import cereal.services as services +from cereal.services import SERVICE_LIST + + +class TestServices: + + @parameterized.expand(SERVICE_LIST.keys()) + def test_services(self, s): + service = SERVICE_LIST[s] + assert service.frequency <= 104 + assert service.decimation != 0 + + def test_generated_header(self): + with tempfile.NamedTemporaryFile(suffix=".h") as f: + ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name} -std=c++11") + assert ret == 0, "generated services header is not valid C" diff --git a/cereal/services.py b/cereal/services.py new file mode 100755 index 0000000000..edeca412ce --- /dev/null +++ b/cereal/services.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +from typing import Optional + + +class Service: + def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None): + self.should_log = should_log + self.frequency = frequency + self.decimation = decimation + + +_services: dict[str, tuple] = { + # service: (should_log, frequency, qlog decimation (optional)) + # note: the "EncodeIdx" packets will still be in the log + "gyroscope": (True, 104., 104), + "gyroscope2": (True, 100., 100), + "accelerometer": (True, 104., 104), + "accelerometer2": (True, 100., 100), + "magnetometer": (True, 25.), + "lightSensor": (True, 100., 100), + "temperatureSensor": (True, 2., 200), + "temperatureSensor2": (True, 2., 200), + "gpsNMEA": (True, 9.), + "deviceState": (True, 2., 1), + "touch": (True, 20., 1), + "can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment + "controlsState": (True, 100., 10), + "selfdriveState": (True, 100., 10), + "pandaStates": (True, 10., 1), + "peripheralState": (True, 2., 1), + "radarState": (True, 20., 5), + "roadEncodeIdx": (False, 20., 1), + "liveTracks": (True, 20.), + "sendcan": (True, 100., 139), + "logMessage": (True, 0.), + "errorLogMessage": (True, 0., 1), + "liveCalibration": (True, 4., 4), + "liveTorqueParameters": (True, 4., 1), + "liveDelay": (True, 4., 1), + "androidLog": (True, 0.), + "carState": (True, 100., 10), + "carControl": (True, 100., 10), + "carOutput": (True, 100., 10), + "longitudinalPlan": (True, 20., 10), + "driverAssistance": (True, 20., 20), + "procLog": (True, 0.5, 15), + "gpsLocationExternal": (True, 10., 10), + "gpsLocation": (True, 1., 1), + "ubloxGnss": (True, 10.), + "qcomGnss": (True, 2.), + "gnssMeasurements": (True, 10., 10), + "clocks": (True, 0.1, 1), + "ubloxRaw": (True, 20.), + "livePose": (True, 20., 4), + "liveParameters": (True, 20., 5), + "cameraOdometry": (True, 20., 10), + "thumbnail": (True, 1 / 60., 1), + "onroadEvents": (True, 1., 1), + "carParams": (True, 0.02, 1), + "roadCameraState": (True, 20., 20), + "driverCameraState": (True, 20., 20), + "driverEncodeIdx": (False, 20., 1), + "driverStateV2": (True, 20., 10), + "driverMonitoringState": (True, 20., 10), + "wideRoadEncodeIdx": (False, 20., 1), + "wideRoadCameraState": (True, 20., 20), + "drivingModelData": (True, 20., 10), + "modelV2": (True, 20.), + "managerState": (True, 2., 1), + "uploaderState": (True, 0., 1), + "navInstruction": (True, 1., 10), + "navRoute": (True, 0.), + "navThumbnail": (True, 0.), + "qRoadEncodeIdx": (False, 20.), + "userBookmark": (True, 0., 1), + "soundPressure": (True, 10., 10), + "rawAudioData": (False, 20.), + "bookmarkButton": (True, 0., 1), + "audioFeedback": (True, 0., 1), + + # debug + "uiDebug": (True, 0., 1), + "testJoystick": (True, 0.), + "alertDebug": (True, 20., 5), + "roadEncodeData": (False, 20.), + "driverEncodeData": (False, 20.), + "wideRoadEncodeData": (False, 20.), + "qRoadEncodeData": (False, 20.), + "livestreamWideRoadEncodeIdx": (False, 20.), + "livestreamRoadEncodeIdx": (False, 20.), + "livestreamDriverEncodeIdx": (False, 20.), + "livestreamWideRoadEncodeData": (False, 20.), + "livestreamRoadEncodeData": (False, 20.), + "livestreamDriverEncodeData": (False, 20.), + "customReservedRawData0": (True, 0.), + "customReservedRawData1": (True, 0.), + "customReservedRawData2": (True, 0.), +} +SERVICE_LIST = {name: Service(*vals) for + idx, (name, vals) in enumerate(_services.items())} + + +def build_header(): + h = "" + h += "/* THIS IS AN AUTOGENERATED FILE, PLEASE EDIT services.py */\n" + h += "#ifndef __SERVICES_H\n" + h += "#define __SERVICES_H\n" + + h += "#include \n" + h += "#include \n" + + h += "struct service { std::string name; bool should_log; float frequency; int decimation; };\n" + h += "static std::map services = {\n" + for k, v in SERVICE_LIST.items(): + should_log = "true" if v.should_log else "false" + decimation = -1 if v.decimation is None else v.decimation + h += ' { "%s", {"%s", %s, %f, %d}},\n' % \ + (k, k, should_log, v.frequency, decimation) + h += "};\n" + + h += "#endif\n" + return h + + +if __name__ == "__main__": + print(build_header()) diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000000..ce1da4c53c --- /dev/null +++ b/common/.gitignore @@ -0,0 +1 @@ +*.cpp diff --git a/common/SConscript b/common/SConscript new file mode 100644 index 0000000000..0891b79039 --- /dev/null +++ b/common/SConscript @@ -0,0 +1,30 @@ +Import('env', 'envCython', 'arch') + +common_libs = [ + 'params.cc', + 'swaglog.cc', + 'util.cc', + 'watchdog.cc', + 'ratekeeper.cc', + 'clutil.cc', +] + +_common = env.Library('common', common_libs, LIBS="json11") +Export('_common') + +if GetOption('extras'): + env.Program('tests/test_common', + ['tests/test_runner.cc', 'tests/test_params.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'], + LIBS=[_common, 'json11', 'zmq', 'pthread']) + +# Cython bindings +params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11']) + +SConscript([ + 'transformations/SConscript', +]) + +Import('transformations_python') +common_python = [params_python, transformations_python] + +Export('common_python') diff --git a/common/__init__.py b/common/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/api.py b/common/api.py new file mode 100644 index 0000000000..005655b21d --- /dev/null +++ b/common/api.py @@ -0,0 +1,48 @@ +import jwt +import os +import requests +from datetime import datetime, timedelta, UTC +from openpilot.system.hardware.hw import Paths +from openpilot.system.version import get_version + +API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com') + +class Api: + def __init__(self, dongle_id): + self.dongle_id = dongle_id + with open(Paths.persist_root()+'/comma/id_rsa') as f: + self.private_key = f.read() + + def get(self, *args, **kwargs): + return self.request('GET', *args, **kwargs) + + def post(self, *args, **kwargs): + return self.request('POST', *args, **kwargs) + + def request(self, method, endpoint, timeout=None, access_token=None, **params): + return api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params) + + def get_token(self, payload_extra=None, expiry_hours=1): + now = datetime.now(UTC).replace(tzinfo=None) + payload = { + 'identity': self.dongle_id, + 'nbf': now, + 'iat': now, + 'exp': now + timedelta(hours=expiry_hours) + } + if payload_extra is not None: + payload.update(payload_extra) + token = jwt.encode(payload, self.private_key, algorithm='RS256') + if isinstance(token, bytes): + token = token.decode('utf8') + return token + + +def api_get(endpoint, method='GET', timeout=None, access_token=None, **params): + headers = {} + if access_token is not None: + headers['Authorization'] = "JWT " + access_token + + headers['User-Agent'] = "openpilot-" + get_version() + + return requests.request(method, API_HOST + "/" + endpoint, timeout=timeout, headers=headers, params=params) diff --git a/common/basedir.py b/common/basedir.py new file mode 100644 index 0000000000..6b4811e53c --- /dev/null +++ b/common/basedir.py @@ -0,0 +1,4 @@ +import os + + +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")) diff --git a/common/clutil.cc b/common/clutil.cc new file mode 100644 index 0000000000..f8381a7e09 --- /dev/null +++ b/common/clutil.cc @@ -0,0 +1,98 @@ +#include "common/clutil.h" + +#include +#include +#include + +#include "common/util.h" +#include "common/swaglog.h" + +namespace { // helper functions + +template +std::string get_info(Func get_info_func, Id id, Name param_name) { + size_t size = 0; + CL_CHECK(get_info_func(id, param_name, 0, NULL, &size)); + std::string info(size, '\0'); + CL_CHECK(get_info_func(id, param_name, size, info.data(), NULL)); + return info; +} +inline std::string get_platform_info(cl_platform_id id, cl_platform_info name) { return get_info(&clGetPlatformInfo, id, name); } +inline std::string get_device_info(cl_device_id id, cl_device_info name) { return get_info(&clGetDeviceInfo, id, name); } + +void cl_print_info(cl_platform_id platform, cl_device_id device) { + size_t work_group_size = 0; + cl_device_type device_type = 0; + clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(work_group_size), &work_group_size, NULL); + clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(device_type), &device_type, NULL); + const char *type_str = "Other..."; + switch (device_type) { + case CL_DEVICE_TYPE_CPU: type_str ="CL_DEVICE_TYPE_CPU"; break; + case CL_DEVICE_TYPE_GPU: type_str = "CL_DEVICE_TYPE_GPU"; break; + case CL_DEVICE_TYPE_ACCELERATOR: type_str = "CL_DEVICE_TYPE_ACCELERATOR"; break; + } + + LOGD("vendor: %s", get_platform_info(platform, CL_PLATFORM_VENDOR).c_str()); + LOGD("platform version: %s", get_platform_info(platform, CL_PLATFORM_VERSION).c_str()); + LOGD("profile: %s", get_platform_info(platform, CL_PLATFORM_PROFILE).c_str()); + LOGD("extensions: %s", get_platform_info(platform, CL_PLATFORM_EXTENSIONS).c_str()); + LOGD("name: %s", get_device_info(device, CL_DEVICE_NAME).c_str()); + LOGD("device version: %s", get_device_info(device, CL_DEVICE_VERSION).c_str()); + LOGD("max work group size: %zu", work_group_size); + LOGD("type = %d, %s", (int)device_type, type_str); +} + +void cl_print_build_errors(cl_program program, cl_device_id device) { + cl_build_status status; + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS, sizeof(status), &status, NULL); + size_t log_size; + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); + std::string log(log_size, '\0'); + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, &log[0], NULL); + + LOGE("build failed; status=%d, log: %s", status, log.c_str()); +} + +} // namespace + +cl_device_id cl_get_device_id(cl_device_type device_type) { + cl_uint num_platforms = 0; + CL_CHECK(clGetPlatformIDs(0, NULL, &num_platforms)); + std::unique_ptr platform_ids = std::make_unique(num_platforms); + CL_CHECK(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL)); + + for (size_t i = 0; i < num_platforms; ++i) { + LOGD("platform[%zu] CL_PLATFORM_NAME: %s", i, get_platform_info(platform_ids[i], CL_PLATFORM_NAME).c_str()); + + // Get first device + if (cl_device_id device_id = NULL; clGetDeviceIDs(platform_ids[i], device_type, 1, &device_id, NULL) == 0 && device_id) { + cl_print_info(platform_ids[i], device_id); + return device_id; + } + } + LOGE("No valid openCL platform found"); + assert(0); + return nullptr; +} + +cl_context cl_create_context(cl_device_id device_id) { + return CL_CHECK_ERR(clCreateContext(NULL, 1, &device_id, NULL, NULL, &err)); +} + +void cl_release_context(cl_context context) { + clReleaseContext(context); +} + +cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args) { + return cl_program_from_source(ctx, device_id, util::read_file(path), args); +} + +cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args) { + const char *csrc = src.c_str(); + cl_program prg = CL_CHECK_ERR(clCreateProgramWithSource(ctx, 1, &csrc, NULL, &err)); + if (int err = clBuildProgram(prg, 1, &device_id, args, NULL, NULL); err != 0) { + cl_print_build_errors(prg, device_id); + assert(0); + } + return prg; +} diff --git a/common/clutil.h b/common/clutil.h new file mode 100644 index 0000000000..b364e79d45 --- /dev/null +++ b/common/clutil.h @@ -0,0 +1,28 @@ +#pragma once + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include + +#define CL_CHECK(_expr) \ + do { \ + assert(CL_SUCCESS == (_expr)); \ + } while (0) + +#define CL_CHECK_ERR(_expr) \ + ({ \ + cl_int err = CL_INVALID_VALUE; \ + __typeof__(_expr) _ret = _expr; \ + assert(_ret&& err == CL_SUCCESS); \ + _ret; \ + }) + +cl_device_id cl_get_device_id(cl_device_type device_type); +cl_context cl_create_context(cl_device_id device_id); +void cl_release_context(cl_context context); +cl_program cl_program_from_source(cl_context ctx, cl_device_id device_id, const std::string& src, const char* args = nullptr); +cl_program cl_program_from_file(cl_context ctx, cl_device_id device_id, const char* path, const char* args); diff --git a/common/constants.py b/common/constants.py new file mode 100644 index 0000000000..7ca425c4b2 --- /dev/null +++ b/common/constants.py @@ -0,0 +1,23 @@ +import numpy as np + +# conversions +class CV: + # Speed + MPH_TO_KPH = 1.609344 + KPH_TO_MPH = 1. / MPH_TO_KPH + MS_TO_KPH = 3.6 + KPH_TO_MS = 1. / MS_TO_KPH + MS_TO_MPH = MS_TO_KPH * KPH_TO_MPH + MPH_TO_MS = MPH_TO_KPH * KPH_TO_MS + MS_TO_KNOTS = 1.9438 + KNOTS_TO_MS = 1. / MS_TO_KNOTS + + # Angle + DEG_TO_RAD = np.pi / 180. + RAD_TO_DEG = 1. / DEG_TO_RAD + + # Mass + LB_TO_KG = 0.453592 + + +ACCELERATION_DUE_TO_GRAVITY = 9.81 # m/s^2 diff --git a/common/dict_helpers.py b/common/dict_helpers.py new file mode 100644 index 0000000000..62cff63b58 --- /dev/null +++ b/common/dict_helpers.py @@ -0,0 +1,9 @@ +# remove all keys that end in DEPRECATED +def strip_deprecated_keys(d): + for k in list(d.keys()): + if isinstance(k, str): + if k.endswith('DEPRECATED'): + d.pop(k) + elif isinstance(d[k], dict): + strip_deprecated_keys(d[k]) + return d diff --git a/common/file_helpers.py b/common/file_helpers.py new file mode 100644 index 0000000000..b0d889f163 --- /dev/null +++ b/common/file_helpers.py @@ -0,0 +1,58 @@ +import io +import os +import tempfile +import contextlib +import zstandard as zstd + +LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change + + +class CallbackReader: + """Wraps a file, but overrides the read method to also + call a callback function with the number of bytes read so far.""" + def __init__(self, f, callback, *args): + self.f = f + self.callback = callback + self.cb_args = args + self.total_read = 0 + + def __getattr__(self, attr): + return getattr(self.f, attr) + + def read(self, *args, **kwargs): + chunk = self.f.read(*args, **kwargs) + self.total_read += len(chunk) + self.callback(*self.cb_args, self.total_read) + return chunk + + +@contextlib.contextmanager +def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str = None, newline: str = None, + overwrite: bool = False): + """Write to a file atomically using a temporary file in the same directory as the destination file.""" + dir_name = os.path.dirname(path) + + if not overwrite and os.path.exists(path): + raise FileExistsError(f"File '{path}' already exists. To overwrite it, set 'overwrite' to True.") + + with tempfile.NamedTemporaryFile(mode=mode, buffering=buffering, encoding=encoding, newline=newline, dir=dir_name, delete=False) as tmp_file: + yield tmp_file + tmp_file_name = tmp_file.name + os.replace(tmp_file_name, path) + + +def get_upload_stream(filepath: str, should_compress: bool) -> tuple[io.BufferedIOBase, int]: + if not should_compress: + file_size = os.path.getsize(filepath) + file_stream = open(filepath, "rb") + return file_stream, file_size + + # Compress the file on the fly + compressed_stream = io.BytesIO() + compressor = zstd.ZstdCompressor(level=LOG_COMPRESSION_LEVEL) + + with open(filepath, "rb") as f: + compressor.copy_stream(f, compressed_stream) + compressed_size = compressed_stream.tell() + compressed_stream.seek(0) + return compressed_stream, compressed_size diff --git a/common/filter_simple.py b/common/filter_simple.py new file mode 100644 index 0000000000..9ea6fe3070 --- /dev/null +++ b/common/filter_simple.py @@ -0,0 +1,17 @@ +class FirstOrderFilter: + def __init__(self, x0, rc, dt, initialized=True): + self.x = x0 + self.dt = dt + self.update_alpha(rc) + self.initialized = initialized + + def update_alpha(self, rc): + self.alpha = self.dt / (rc + self.dt) + + def update(self, x): + if self.initialized: + self.x = (1. - self.alpha) * self.x + self.alpha * x + else: + self.initialized = True + self.x = x + return self.x diff --git a/common/git.py b/common/git.py new file mode 100644 index 0000000000..4406bf96b1 --- /dev/null +++ b/common/git.py @@ -0,0 +1,42 @@ +from functools import cache +import subprocess +from openpilot.common.run import run_cmd, run_cmd_default + + +@cache +def get_commit(cwd: str = None, branch: str = "HEAD") -> str: + return run_cmd_default(["git", "rev-parse", branch], cwd=cwd) + + +@cache +def get_commit_date(cwd: str = None, commit: str = "HEAD") -> str: + return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit], cwd=cwd) + + +@cache +def get_short_branch(cwd: str = None) -> str: + return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd) + + +@cache +def get_branch(cwd: str = None) -> str: + return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=cwd) + + +@cache +def get_origin(cwd: str = None) -> str: + try: + local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"], cwd=cwd) + tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"], cwd=cwd) + return run_cmd(["git", "config", "remote." + tracking_remote + ".url"], cwd=cwd) + except subprocess.CalledProcessError: # Not on a branch, fallback + return run_cmd_default(["git", "config", "--get", "remote.origin.url"], cwd=cwd) + + +@cache +def get_normalized_origin(cwd: str = None) -> str: + return get_origin(cwd) \ + .replace("git@", "", 1) \ + .replace(".git", "", 1) \ + .replace("https://", "", 1) \ + .replace(":", "/", 1) diff --git a/common/gpio.py b/common/gpio.py new file mode 100644 index 0000000000..8f025a2daf --- /dev/null +++ b/common/gpio.py @@ -0,0 +1,89 @@ +import os +import fcntl +import ctypes +from functools import cache + +def gpio_init(pin: int, output: bool) -> None: + try: + with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f: + f.write(b"out" if output else b"in") + except Exception as e: + print(f"Failed to set gpio {pin} direction: {e}") + +def gpio_set(pin: int, high: bool) -> None: + try: + with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f: + f.write(b"1" if high else b"0") + except Exception as e: + print(f"Failed to set gpio {pin} value: {e}") + +def gpio_read(pin: int) -> bool | None: + val = None + try: + with open(f"/sys/class/gpio/gpio{pin}/value", 'rb') as f: + val = bool(int(f.read().strip())) + except Exception as e: + print(f"Failed to set gpio {pin} value: {e}") + + return val + +def gpio_export(pin: int) -> None: + if os.path.isdir(f"/sys/class/gpio/gpio{pin}"): + return + + try: + with open("/sys/class/gpio/export", 'w') as f: + f.write(str(pin)) + except Exception: + print(f"Failed to export gpio {pin}") + +@cache +def get_irq_action(irq: int) -> list[str]: + try: + with open(f"/sys/kernel/irq/{irq}/actions") as f: + actions = f.read().strip().split(',') + return actions + except FileNotFoundError: + return [] + +def get_irqs_for_action(action: str) -> list[str]: + ret = [] + with open("/proc/interrupts") as f: + for l in f.readlines(): + irq = l.split(':')[0].strip() + if irq.isdigit() and action in get_irq_action(irq): + ret.append(irq) + return ret + +# *** gpiochip *** + +class gpioevent_data(ctypes.Structure): + _fields_ = [ + ("timestamp", ctypes.c_uint64), + ("id", ctypes.c_uint32), + ] + +class gpioevent_request(ctypes.Structure): + _fields_ = [ + ("lineoffset", ctypes.c_uint32), + ("handleflags", ctypes.c_uint32), + ("eventflags", ctypes.c_uint32), + ("label", ctypes.c_char * 32), + ("fd", ctypes.c_int) + ] + +def gpiochip_get_ro_value_fd(label: str, gpiochip_id: int, pin: int) -> int: + GPIOEVENT_REQUEST_BOTH_EDGES = 0x3 + GPIOHANDLE_REQUEST_INPUT = 0x1 + GPIO_GET_LINEEVENT_IOCTL = 0xc030b404 + + rq = gpioevent_request() + rq.lineoffset = pin + rq.handleflags = GPIOHANDLE_REQUEST_INPUT + rq.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES + rq.label = label.encode('utf-8')[:31] + b'\0' + + fd = os.open(f"/dev/gpiochip{gpiochip_id}", os.O_RDONLY) + fcntl.ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, rq) + os.close(fd) + return int(rq.fd) diff --git a/common/gps.py b/common/gps.py new file mode 100644 index 0000000000..6f96d72e99 --- /dev/null +++ b/common/gps.py @@ -0,0 +1,8 @@ +from openpilot.common.params import Params + + +def get_gps_location_service(params: Params) -> str: + if params.get_bool("UbloxAvailable"): + return "gpsLocationExternal" + else: + return "gpsLocation" diff --git a/common/logging_extra.py b/common/logging_extra.py new file mode 100644 index 0000000000..ceaf083cd5 --- /dev/null +++ b/common/logging_extra.py @@ -0,0 +1,249 @@ +import io +import os +import sys +import copy +import json +import time +import uuid +import socket +import logging +import traceback +import numpy as np +from threading import local +from collections import OrderedDict +from contextlib import contextmanager + +LOG_TIMESTAMPS = "LOG_TIMESTAMPS" in os.environ + +def json_handler(obj): + if isinstance(obj, np.bool_): + return bool(obj) + # if isinstance(obj, (datetime.date, datetime.time)): + # return obj.isoformat() + return repr(obj) + +def json_robust_dumps(obj): + return json.dumps(obj, default=json_handler) + +class NiceOrderedDict(OrderedDict): + def __str__(self): + return json_robust_dumps(self) + +class SwagFormatter(logging.Formatter): + def __init__(self, swaglogger): + logging.Formatter.__init__(self, None, '%a %b %d %H:%M:%S %Z %Y') + + self.swaglogger = swaglogger + self.host = socket.gethostname() + + def format_dict(self, record): + record_dict = NiceOrderedDict() + + if isinstance(record.msg, dict): + record_dict['msg'] = record.msg + else: + try: + record_dict['msg'] = record.getMessage() + except (ValueError, TypeError): + record_dict['msg'] = [record.msg]+record.args + + record_dict['ctx'] = self.swaglogger.get_ctx() + + if record.exc_info: + record_dict['exc_info'] = self.formatException(record.exc_info) + + record_dict['level'] = record.levelname + record_dict['levelnum'] = record.levelno + record_dict['name'] = record.name + record_dict['filename'] = record.filename + record_dict['lineno'] = record.lineno + record_dict['pathname'] = record.pathname + record_dict['module'] = record.module + record_dict['funcName'] = record.funcName + record_dict['host'] = self.host + record_dict['process'] = record.process + record_dict['thread'] = record.thread + record_dict['threadName'] = record.threadName + record_dict['created'] = record.created + + return record_dict + + def format(self, record): + if self.swaglogger is None: + raise Exception("must set swaglogger before calling format()") + return json_robust_dumps(self.format_dict(record)) + +class SwagLogFileFormatter(SwagFormatter): + def fix_kv(self, k, v): + # append type to names to preserve legacy naming in logs + # avoids overlapping key namespaces with different types + # e.g. log.info() creates 'msg' -> 'msg$s' + # log.event() creates 'msg.health.logMonoTime' -> 'msg.health.logMonoTime$i' + # because overlapping namespace 'msg' caused problems + if isinstance(v, (str, bytes)): + k += "$s" + elif isinstance(v, float): + k += "$f" + elif isinstance(v, bool): + k += "$b" + elif isinstance(v, int): + k += "$i" + elif isinstance(v, dict): + nv = {} + for ik, iv in v.items(): + ik, iv = self.fix_kv(ik, iv) + nv[ik] = iv + v = nv + elif isinstance(v, list): + k += "$a" + return k, v + + def format(self, record): + if isinstance(record, str): + v = json.loads(record) + else: + v = self.format_dict(record) + + mk, mv = self.fix_kv('msg', v['msg']) + del v['msg'] + v[mk] = mv + v['id'] = uuid.uuid4().hex + + return json_robust_dumps(v) + +class SwagErrorFilter(logging.Filter): + def filter(self, record): + return record.levelno < logging.ERROR + +def _tmpfunc(): + return 0 + +def _srcfile(): + return os.path.normcase(_tmpfunc.__code__.co_filename) + +class SwagLogger(logging.Logger): + def __init__(self): + logging.Logger.__init__(self, "swaglog") + + self.global_ctx = {} + + self.log_local = local() + self.log_local.ctx = {} + + def local_ctx(self): + try: + return self.log_local.ctx + except AttributeError: + self.log_local.ctx = {} + return self.log_local.ctx + + def get_ctx(self): + return dict(self.local_ctx(), **self.global_ctx) + + @contextmanager + def ctx(self, **kwargs): + old_ctx = self.local_ctx() + self.log_local.ctx = copy.copy(old_ctx) or {} + self.log_local.ctx.update(kwargs) + try: + yield + finally: + self.log_local.ctx = old_ctx + + def bind(self, **kwargs): + self.local_ctx().update(kwargs) + + def bind_global(self, **kwargs): + self.global_ctx.update(kwargs) + + def event(self, event, *args, **kwargs): + evt = NiceOrderedDict() + evt['event'] = event + if args: + evt['args'] = args + evt.update(kwargs) + if 'error' in kwargs: + self.error(evt) + elif 'debug' in kwargs: + self.debug(evt) + else: + self.info(evt) + + def timestamp(self, event_name): + if LOG_TIMESTAMPS: + t = time.monotonic() + tstp = NiceOrderedDict() + tstp['timestamp'] = NiceOrderedDict() + tstp['timestamp']["event"] = event_name + tstp['timestamp']["time"] = t*1e9 + self.debug(tstp) + + def findCaller(self, stack_info=False, stacklevel=1): + """ + Find the stack frame of the caller so that we can note the source + file name, line number and function name. + """ + f = sys._getframe(3) + #On some versions of IronPython, currentframe() returns None if + #IronPython isn't run with -X:Frames. + if f is not None: + f = f.f_back + orig_f = f + while f and stacklevel > 1: + f = f.f_back + stacklevel -= 1 + if not f: + f = orig_f + rv = "(unknown file)", 0, "(unknown function)", None + while hasattr(f, "f_code"): + co = f.f_code + filename = os.path.normcase(co.co_filename) + + if filename == _srcfile: + f = f.f_back + continue + sinfo = None + if stack_info: + sio = io.StringIO() + sio.write('Stack (most recent call last):\n') + traceback.print_stack(f, file=sio) + sinfo = sio.getvalue() + if sinfo[-1] == '\n': + sinfo = sinfo[:-1] + sio.close() + rv = (co.co_filename, f.f_lineno, co.co_name, sinfo) + break + return rv + +if __name__ == "__main__": + log = SwagLogger() + + stdout_handler = logging.StreamHandler(sys.stdout) + stdout_handler.setLevel(logging.INFO) + stdout_handler.addFilter(SwagErrorFilter()) + log.addHandler(stdout_handler) + + stderr_handler = logging.StreamHandler(sys.stderr) + stderr_handler.setLevel(logging.ERROR) + log.addHandler(stderr_handler) + + log.info("asdasd %s", "a") + log.info({'wut': 1}) + log.warning("warning") + log.error("error") + log.critical("critical") + log.event("test", x="y") + + with log.ctx(): + stdout_handler.setFormatter(SwagFormatter(log)) + stderr_handler.setFormatter(SwagFormatter(log)) + log.bind(user="some user") + log.info("in req") + print("") + log.warning("warning") + print("") + log.error("error") + print("") + log.critical("critical") + print("") + log.event("do_req", a=1, b="c") diff --git a/common/markdown.py b/common/markdown.py new file mode 100644 index 0000000000..f0f056d963 --- /dev/null +++ b/common/markdown.py @@ -0,0 +1,45 @@ +HTML_REPLACEMENTS = [ + (r'&', r'&'), + (r'"', r'"'), +] + +def parse_markdown(text: str, tab_length: int = 2) -> str: + lines = text.split("\n") + output: list[str] = [] + list_level = 0 + + def end_outstanding_lists(level: int, end_level: int) -> int: + while level > end_level: + level -= 1 + output.append("") + if level > 0: + output.append("") + return end_level + + for i, line in enumerate(lines): + if i + 1 < len(lines) and lines[i + 1].startswith("==="): # heading + output.append(f"

{line}

") + elif line.startswith("==="): + pass + elif line.lstrip().startswith("* "): # list + line_level = 1 + line.count(" " * tab_length, 0, line.index("*")) + if list_level >= line_level: + list_level = end_outstanding_lists(list_level, line_level) + else: + list_level += 1 + if list_level > 1: + output[-1] = output[-1].replace("", "") + output.append("
    ") + output.append(f"
  • {line.replace('*', '', 1).lstrip()}
  • ") + else: + list_level = end_outstanding_lists(list_level, 0) + if len(line) > 0: + output.append(line) + + end_outstanding_lists(list_level, 0) + output_str = "\n".join(output) + "\n" + + for (fr, to) in HTML_REPLACEMENTS: + output_str = output_str.replace(fr, to) + + return output_str diff --git a/common/mat.h b/common/mat.h new file mode 100644 index 0000000000..8e10d61971 --- /dev/null +++ b/common/mat.h @@ -0,0 +1,85 @@ +#pragma once + +typedef struct vec3 { + float v[3]; +} vec3; + +typedef struct vec4 { + float v[4]; +} vec4; + +typedef struct mat3 { + float v[3*3]; +} mat3; + +typedef struct mat4 { + float v[4*4]; +} mat4; + +static inline mat3 matmul3(const mat3 &a, const mat3 &b) { + mat3 ret = {{0.0}}; + for (int r=0; r<3; r++) { + for (int c=0; c<3; c++) { + float v = 0.0; + for (int k=0; k<3; k++) { + v += a.v[r*3+k] * b.v[k*3+c]; + } + ret.v[r*3+c] = v; + } + } + return ret; +} + +static inline vec3 matvecmul3(const mat3 &a, const vec3 &b) { + vec3 ret = {{0.0}}; + for (int r=0; r<3; r++) { + for (int c=0; c<3; c++) { + ret.v[r] += a.v[r*3+c] * b.v[c]; + } + } + return ret; +} + +static inline mat4 matmul(const mat4 &a, const mat4 &b) { + mat4 ret = {{0.0}}; + for (int r=0; r<4; r++) { + for (int c=0; c<4; c++) { + float v = 0.0; + for (int k=0; k<4; k++) { + v += a.v[r*4+k] * b.v[k*4+c]; + } + ret.v[r*4+c] = v; + } + } + return ret; +} + +static inline vec4 matvecmul(const mat4 &a, const vec4 &b) { + vec4 ret = {{0.0}}; + for (int r=0; r<4; r++) { + for (int c=0; c<4; c++) { + ret.v[r] += a.v[r*4+c] * b.v[c]; + } + } + return ret; +} + +// scales the input and output space of a transformation matrix +// that assumes pixel-center origin. +static inline mat3 transform_scale_buffer(const mat3 &in, float s) { + // in_pt = ( transform(out_pt/s + 0.5) - 0.5) * s + + mat3 transform_out = {{ + 1.0f/s, 0.0f, 0.5f, + 0.0f, 1.0f/s, 0.5f, + 0.0f, 0.0f, 1.0f, + }}; + + mat3 transform_in = {{ + s, 0.0f, -0.5f*s, + 0.0f, s, -0.5f*s, + 0.0f, 0.0f, 1.0f, + }}; + + return matmul3(transform_in, matmul3(in, transform_out)); +} diff --git a/common/mock/__init__.py b/common/mock/__init__.py new file mode 100644 index 0000000000..4b01dfe841 --- /dev/null +++ b/common/mock/__init__.py @@ -0,0 +1,50 @@ +""" +Utilities for generating mock messages for testing. +example in common/tests/test_mock.py +""" + + +import functools +import threading +from cereal.messaging import PubMaster +from cereal.services import SERVICE_LIST +from openpilot.common.mock.generators import generate_livePose +from openpilot.common.realtime import Ratekeeper + + +MOCK_GENERATOR = { + "livePose": generate_livePose +} + + +def generate_messages_loop(services: list[str], done: threading.Event): + pm = PubMaster(services) + rk = Ratekeeper(100) + i = 0 + while not done.is_set(): + for s in services: + should_send = i % (100/SERVICE_LIST[s].frequency) == 0 + if should_send: + message = MOCK_GENERATOR[s]() + pm.send(s, message) + i += 1 + rk.keep_time() + + +def mock_messages(services: list[str] | str): + if isinstance(services, str): + services = [services] + + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + done = threading.Event() + t = threading.Thread(target=generate_messages_loop, args=(services, done)) + t.start() + try: + return func(*args, **kwargs) + finally: + done.set() + t.join() + return wrapper + return decorator diff --git a/common/mock/generators.py b/common/mock/generators.py new file mode 100644 index 0000000000..5cd9c88a56 --- /dev/null +++ b/common/mock/generators.py @@ -0,0 +1,14 @@ +from cereal import messaging + + +def generate_livePose(): + msg = messaging.new_message('livePose') + meas = {'x': 0.0, 'y': 0.0, 'z': 0.0, 'xStd': 0.0, 'yStd': 0.0, 'zStd': 0.0, 'valid': True} + msg.livePose.orientationNED = meas + msg.livePose.velocityDevice = meas + msg.livePose.angularVelocityDevice = meas + msg.livePose.accelerationDevice = meas + msg.livePose.inputsOK = True + msg.livePose.posenetOK = True + msg.livePose.sensorsOK = True + return msg diff --git a/common/params.cc b/common/params.cc new file mode 100644 index 0000000000..6af00fe95c --- /dev/null +++ b/common/params.cc @@ -0,0 +1,242 @@ +#include "common/params.h" + +#include +#include + +#include +#include +#include +#include + +#include "common/params_keys.h" +#include "common/queue.h" +#include "common/swaglog.h" +#include "common/util.h" +#include "system/hardware/hw.h" + +namespace { + +volatile sig_atomic_t params_do_exit = 0; +void params_sig_handler(int signal) { + params_do_exit = 1; +} + +int fsync_dir(const std::string &path) { + int result = -1; + int fd = HANDLE_EINTR(open(path.c_str(), O_RDONLY, 0755)); + if (fd >= 0) { + result = HANDLE_EINTR(fsync(fd)); + HANDLE_EINTR(close(fd)); + } + return result; +} + +bool create_params_path(const std::string ¶m_path, const std::string &key_path) { + // Make sure params path exists + if (!util::file_exists(param_path) && !util::create_directories(param_path, 0775)) { + return false; + } + + // See if the symlink exists, otherwise create it + if (!util::file_exists(key_path)) { + // 1) Create temp folder + // 2) Symlink it to temp link + // 3) Move symlink to /d + + std::string tmp_path = param_path + "/.tmp_XXXXXX"; + // this should be OK since mkdtemp just replaces characters in place + char *tmp_dir = mkdtemp((char *)tmp_path.c_str()); + if (tmp_dir == NULL) { + return false; + } + + std::string link_path = std::string(tmp_dir) + ".link"; + if (symlink(tmp_dir, link_path.c_str()) != 0) { + return false; + } + + // don't return false if it has been created by other + if (rename(link_path.c_str(), key_path.c_str()) != 0 && errno != EEXIST) { + return false; + } + } + + return true; +} + +std::string ensure_params_path(const std::string &prefix, const std::string &path = {}) { + std::string params_path = path.empty() ? Path::params() : path; + if (!create_params_path(params_path, params_path + prefix)) { + throw std::runtime_error(util::string_format( + "Failed to ensure params path, errno=%d, path=%s, param_prefix=%s", + errno, params_path.c_str(), prefix.c_str())); + } + return params_path; +} + +class FileLock { +public: + FileLock(const std::string &fn) { + fd_ = HANDLE_EINTR(open(fn.c_str(), O_CREAT, 0775)); + if (fd_ < 0 || HANDLE_EINTR(flock(fd_, LOCK_EX)) < 0) { + LOGE("Failed to lock file %s, errno=%d", fn.c_str(), errno); + } + } + ~FileLock() { close(fd_); } + +private: + int fd_ = -1; +}; + +} // namespace + + +Params::Params(const std::string &path) { + params_prefix = "/" + util::getenv("OPENPILOT_PREFIX", "d"); + params_path = ensure_params_path(params_prefix, path); +} + +Params::~Params() { + if (future.valid()) { + future.wait(); + } + assert(queue.empty()); +} + +std::vector Params::allKeys() const { + std::vector ret; + for (auto &p : keys) { + ret.push_back(p.first); + } + return ret; +} + +bool Params::checkKey(const std::string &key) { + return keys.find(key) != keys.end(); +} + +ParamKeyFlag Params::getKeyFlag(const std::string &key) { + return static_cast(keys[key].flags); +} + +ParamKeyType Params::getKeyType(const std::string &key) { + return keys[key].type; +} + +std::optional Params::getKeyDefaultValue(const std::string &key) { + return keys[key].default_value; +} + +int Params::put(const char* key, const char* value, size_t value_size) { + // Information about safely and atomically writing a file: https://lwn.net/Articles/457667/ + // 1) Create temp file + // 2) Write data to temp file + // 3) fsync() the temp file + // 4) rename the temp file to the real name + // 5) fsync() the containing directory + std::string tmp_path = params_path + "/.tmp_value_XXXXXX"; + int tmp_fd = mkstemp((char*)tmp_path.c_str()); + if (tmp_fd < 0) return -1; + + int result = -1; + do { + // Write value to temp. + ssize_t bytes_written = HANDLE_EINTR(write(tmp_fd, value, value_size)); + if (bytes_written < 0 || (size_t)bytes_written != value_size) { + result = -20; + break; + } + + // fsync to force persist the changes. + if ((result = HANDLE_EINTR(fsync(tmp_fd))) < 0) break; + + FileLock file_lock(params_path + "/.lock"); + + // Move temp into place. + if ((result = rename(tmp_path.c_str(), getParamPath(key).c_str())) < 0) break; + + // fsync parent directory + result = fsync_dir(getParamPath()); + } while (false); + + close(tmp_fd); + if (result != 0) { + ::unlink(tmp_path.c_str()); + } + return result; +} + +int Params::remove(const std::string &key) { + FileLock file_lock(params_path + "/.lock"); + int result = unlink(getParamPath(key).c_str()); + if (result != 0) { + return result; + } + return fsync_dir(getParamPath()); +} + +std::string Params::get(const std::string &key, bool block) { + if (!block) { + return util::read_file(getParamPath(key)); + } else { + // blocking read until successful + params_do_exit = 0; + void (*prev_handler_sigint)(int) = std::signal(SIGINT, params_sig_handler); + void (*prev_handler_sigterm)(int) = std::signal(SIGTERM, params_sig_handler); + + std::string value; + while (!params_do_exit) { + if (value = util::read_file(getParamPath(key)); !value.empty()) { + break; + } + util::sleep_for(100); // 0.1 s + } + + std::signal(SIGINT, prev_handler_sigint); + std::signal(SIGTERM, prev_handler_sigterm); + return value; + } +} + +std::map Params::readAll() { + FileLock file_lock(params_path + "/.lock"); + return util::read_files_in_dir(getParamPath()); +} + +void Params::clearAll(ParamKeyFlag key_flag) { + FileLock file_lock(params_path + "/.lock"); + + // 1) delete params of key_flag + // 2) delete files that are not defined in the keys. + if (DIR *d = opendir(getParamPath().c_str())) { + struct dirent *de = NULL; + while ((de = readdir(d))) { + if (de->d_type != DT_DIR) { + auto it = keys.find(de->d_name); + if (it == keys.end() || (it->second.flags & key_flag)) { + unlink(getParamPath(de->d_name).c_str()); + } + } + } + closedir(d); + } + + fsync_dir(getParamPath()); +} + +void Params::putNonBlocking(const std::string &key, const std::string &val) { + queue.push(std::make_pair(key, val)); + // start thread on demand + if (!future.valid() || future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) { + future = std::async(std::launch::async, &Params::asyncWriteThread, this); + } +} + +void Params::asyncWriteThread() { + // TODO: write the latest one if a key has multiple values in the queue. + std::pair p; + while (queue.try_pop(p, 0)) { + // Params::put is Thread-Safe + put(p.first, p.second); + } +} diff --git a/common/params.h b/common/params.h new file mode 100644 index 0000000000..8169063ac0 --- /dev/null +++ b/common/params.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "common/queue.h" + +enum ParamKeyFlag { + PERSISTENT = 0x02, + CLEAR_ON_MANAGER_START = 0x04, + CLEAR_ON_ONROAD_TRANSITION = 0x08, + CLEAR_ON_OFFROAD_TRANSITION = 0x10, + DONT_LOG = 0x20, + DEVELOPMENT_ONLY = 0x40, + CLEAR_ON_IGNITION_ON = 0x80, + ALL = 0xFFFFFFFF +}; + +enum ParamKeyType { + STRING = 0, // must be utf-8 decodable + BOOL = 1, + INT = 2, + FLOAT = 3, + TIME = 4, // ISO 8601 + JSON = 5, + BYTES = 6 +}; + +struct ParamKeyAttributes { + uint32_t flags; + ParamKeyType type; + std::optional default_value = std::nullopt; +}; + +class Params { +public: + explicit Params(const std::string &path = {}); + ~Params(); + // Not copyable. + Params(const Params&) = delete; + Params& operator=(const Params&) = delete; + + std::vector allKeys() const; + bool checkKey(const std::string &key); + ParamKeyFlag getKeyFlag(const std::string &key); + ParamKeyType getKeyType(const std::string &key); + std::optional getKeyDefaultValue(const std::string &key); + inline std::string getParamPath(const std::string &key = {}) { + return params_path + params_prefix + (key.empty() ? "" : "/" + key); + } + + // Delete a value + int remove(const std::string &key); + void clearAll(ParamKeyFlag flag); + + // helpers for reading values + std::string get(const std::string &key, bool block = false); + inline bool getBool(const std::string &key, bool block = false) { + return get(key, block) == "1"; + } + std::map readAll(); + + // helpers for writing values + int put(const char *key, const char *val, size_t value_size); + inline int put(const std::string &key, const std::string &val) { + return put(key.c_str(), val.data(), val.size()); + } + inline int putBool(const std::string &key, bool val) { + return put(key.c_str(), val ? "1" : "0", 1); + } + void putNonBlocking(const std::string &key, const std::string &val); + inline void putBoolNonBlocking(const std::string &key, bool val) { + putNonBlocking(key, val ? "1" : "0"); + } + +private: + void asyncWriteThread(); + + std::string params_path; + std::string params_prefix; + + // for nonblocking write + std::future future; + SafeQueue> queue; +}; diff --git a/common/params.py b/common/params.py new file mode 100644 index 0000000000..494617200f --- /dev/null +++ b/common/params.py @@ -0,0 +1,19 @@ +from openpilot.common.params_pyx import Params, ParamKeyFlag, ParamKeyType, UnknownKeyName +assert Params +assert ParamKeyFlag +assert ParamKeyType +assert UnknownKeyName + +if __name__ == "__main__": + import sys + + params = Params() + key = sys.argv[1] + assert params.check_key(key), f"unknown param: {key}" + + if len(sys.argv) == 3: + val = sys.argv[2] + print(f"SET: {key} = {val}") + params.put(key, val) + elif len(sys.argv) == 2: + print(f"GET: {key} = {params.get(key)}") diff --git a/common/params_keys.h b/common/params_keys.h new file mode 100644 index 0000000000..211b4d550b --- /dev/null +++ b/common/params_keys.h @@ -0,0 +1,131 @@ +#pragma once + +#include +#include + +#include "cereal/gen/cpp/log.capnp.h" + +inline static std::unordered_map keys = { + {"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}}, + {"AdbEnabled", {PERSISTENT, BOOL}}, + {"AlwaysOnDM", {PERSISTENT, BOOL}}, + {"ApiCache_Device", {PERSISTENT, STRING}}, + {"ApiCache_FirehoseStats", {PERSISTENT, JSON}}, + {"AssistNowToken", {PERSISTENT, STRING}}, + {"AthenadPid", {PERSISTENT, INT}}, + {"AthenadUploadQueue", {PERSISTENT, JSON}}, + {"AthenadRecentlyViewedRoutes", {PERSISTENT, STRING}}, + {"BootCount", {PERSISTENT, INT}}, + {"CalibrationParams", {PERSISTENT, BYTES}}, + {"CameraDebugExpGain", {CLEAR_ON_MANAGER_START, STRING}}, + {"CameraDebugExpTime", {CLEAR_ON_MANAGER_START, STRING}}, + {"CarBatteryCapacity", {PERSISTENT, INT}}, + {"CarParams", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}}, + {"CarParamsCache", {CLEAR_ON_MANAGER_START, BYTES}}, + {"CarParamsPersistent", {PERSISTENT, BYTES}}, + {"CarParamsPrevRoute", {PERSISTENT, BYTES}}, + {"CompletedTrainingVersion", {PERSISTENT, STRING, "0"}}, + {"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"CurrentBootlog", {PERSISTENT, STRING}}, + {"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}}, + {"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"DisablePowerDown", {PERSISTENT, BOOL}}, + {"DisableUpdates", {PERSISTENT, BOOL}}, + {"DisengageOnAccelerator", {PERSISTENT, BOOL, "0"}}, + {"DongleId", {PERSISTENT, STRING}}, + {"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}}, + {"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}}, + {"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}}, + {"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}}, + {"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY, BOOL}}, + {"ExperimentalMode", {PERSISTENT, BOOL}}, + {"ExperimentalModeConfirmed", {PERSISTENT, BOOL}}, + {"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"ForcePowerDown", {PERSISTENT, BOOL}}, + {"GitBranch", {PERSISTENT, STRING}}, + {"GitCommit", {PERSISTENT, STRING}}, + {"GitCommitDate", {PERSISTENT, STRING}}, + {"GitDiff", {PERSISTENT, STRING}}, + {"GithubSshKeys", {PERSISTENT, STRING}}, + {"GithubUsername", {PERSISTENT, STRING}}, + {"GitRemote", {PERSISTENT, STRING}}, + {"GsmApn", {PERSISTENT, STRING}}, + {"GsmMetered", {PERSISTENT, BOOL, "1"}}, + {"GsmRoaming", {PERSISTENT, BOOL}}, + {"HardwareSerial", {PERSISTENT, STRING}}, + {"HasAcceptedTerms", {PERSISTENT, STRING, "0"}}, + {"InstallDate", {PERSISTENT, TIME}}, + {"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}}, + {"IsEngaged", {PERSISTENT, BOOL}}, + {"IsLdwEnabled", {PERSISTENT, BOOL}}, + {"IsMetric", {PERSISTENT, BOOL}}, + {"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}}, + {"IsOnroad", {PERSISTENT, BOOL}}, + {"IsRhdDetected", {PERSISTENT, BOOL}}, + {"IsReleaseBranch", {CLEAR_ON_MANAGER_START, BOOL}}, + {"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}}, + {"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}}, + {"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}}, + {"LanguageSetting", {PERSISTENT, STRING, "main_en"}}, + {"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}}, + {"LastGPSPosition", {PERSISTENT, STRING}}, + {"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}}, + {"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}}, + {"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}}, + {"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}}, + {"LastUpdateRouteCount", {PERSISTENT, INT, "0"}}, + {"LastUpdateTime", {PERSISTENT, TIME}}, + {"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}}, + {"LiveDelay", {PERSISTENT, BYTES}}, + {"LiveParameters", {PERSISTENT, JSON}}, + {"LiveParametersV2", {PERSISTENT, BYTES}}, + {"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}}, + {"LocationFilterInitialState", {PERSISTENT, BYTES}}, + {"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}}, + {"LongitudinalPersonality", {PERSISTENT, INT, std::to_string(static_cast(cereal::LongitudinalPersonality::STANDARD))}}, + {"NetworkMetered", {PERSISTENT, BOOL}}, + {"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"ObdMultiplexingEnabled", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"Offroad_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}}, + {"Offroad_ConnectivityNeeded", {CLEAR_ON_MANAGER_START, JSON}}, + {"Offroad_ConnectivityNeededPrompt", {CLEAR_ON_MANAGER_START, JSON}}, + {"Offroad_ExcessiveActuation", {PERSISTENT, JSON}}, + {"Offroad_IsTakingSnapshot", {CLEAR_ON_MANAGER_START, JSON}}, + {"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}}, + {"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}}, + {"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}}, + {"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}}, + {"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}}, + {"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}}, + {"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}}, + {"OpenpilotEnabledToggle", {PERSISTENT, BOOL, "1"}}, + {"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}}, + {"PandaSomResetTriggered", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}}, + {"PandaSignatures", {CLEAR_ON_MANAGER_START, BYTES}}, + {"PrimeType", {PERSISTENT, INT}}, + {"RecordAudio", {PERSISTENT, BOOL}}, + {"RecordAudioFeedback", {PERSISTENT, BOOL, "0"}}, + {"RecordFront", {PERSISTENT, BOOL}}, + {"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet + {"SecOCKey", {PERSISTENT | DONT_LOG, STRING}}, + {"RouteCount", {PERSISTENT, INT, "0"}}, + {"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}}, + {"SshEnabled", {PERSISTENT, BOOL}}, + {"TermsVersion", {PERSISTENT, STRING}}, + {"TrainingVersion", {PERSISTENT, STRING}}, + {"UbloxAvailable", {PERSISTENT, BOOL}}, + {"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}}, + {"UpdateFailedCount", {CLEAR_ON_MANAGER_START, INT}}, + {"UpdaterAvailableBranches", {PERSISTENT, STRING}}, + {"UpdaterCurrentDescription", {CLEAR_ON_MANAGER_START, STRING}}, + {"UpdaterCurrentReleaseNotes", {CLEAR_ON_MANAGER_START, BYTES}}, + {"UpdaterFetchAvailable", {CLEAR_ON_MANAGER_START, BOOL}}, + {"UpdaterNewDescription", {CLEAR_ON_MANAGER_START, STRING}}, + {"UpdaterNewReleaseNotes", {CLEAR_ON_MANAGER_START, BYTES}}, + {"UpdaterState", {CLEAR_ON_MANAGER_START, STRING}}, + {"UpdaterTargetBranch", {CLEAR_ON_MANAGER_START, STRING}}, + {"UpdaterLastFetchTime", {PERSISTENT, TIME}}, + {"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}}, + {"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}}, + {"Version", {PERSISTENT, STRING}}, +}; diff --git a/common/params_pyx.pyx b/common/params_pyx.pyx new file mode 100644 index 0000000000..93c550f22a --- /dev/null +++ b/common/params_pyx.pyx @@ -0,0 +1,196 @@ +# distutils: language = c++ +# cython: language_level = 3 +import builtins +import datetime +import json +from libcpp cimport bool +from libcpp.string cimport string +from libcpp.vector cimport vector +from libcpp.optional cimport optional + +from openpilot.common.swaglog import cloudlog + +cdef extern from "common/params.h": + cpdef enum ParamKeyFlag: + PERSISTENT + CLEAR_ON_MANAGER_START + CLEAR_ON_ONROAD_TRANSITION + CLEAR_ON_OFFROAD_TRANSITION + DEVELOPMENT_ONLY + CLEAR_ON_IGNITION_ON + ALL + + cpdef enum ParamKeyType: + STRING + BOOL + INT + FLOAT + TIME + JSON + BYTES + + cdef cppclass c_Params "Params": + c_Params(string) except + nogil + string get(string, bool) nogil + bool getBool(string, bool) nogil + int remove(string) nogil + int put(string, string) nogil + void putNonBlocking(string, string) nogil + void putBoolNonBlocking(string, bool) nogil + int putBool(string, bool) nogil + bool checkKey(string) nogil + ParamKeyType getKeyType(string) nogil + optional[string] getKeyDefaultValue(string) nogil + string getParamPath(string) nogil + void clearAll(ParamKeyFlag) + vector[string] allKeys() + +PYTHON_2_CPP = { + (str, STRING): lambda v: v, + (builtins.bool, BOOL): lambda v: "1" if v else "0", + (int, INT): str, + (float, FLOAT): str, + (datetime.datetime, TIME): lambda v: v.isoformat(), + (dict, JSON): json.dumps, + (list, JSON): json.dumps, + (bytes, BYTES): lambda v: v, +} +CPP_2_PYTHON = { + STRING: lambda v: v.decode("utf-8"), + BOOL: lambda v: v == b"1", + INT: int, + FLOAT: float, + TIME: lambda v: datetime.datetime.fromisoformat(v.decode("utf-8")), + JSON: json.loads, + BYTES: lambda v: v, +} + +def ensure_bytes(v): + return v.encode() if isinstance(v, str) else v + +class UnknownKeyName(Exception): + pass + +cdef class Params: + cdef c_Params* p + cdef str d + + def __cinit__(self, d=""): + cdef string path = d.encode() + with nogil: + self.p = new c_Params(path) + self.d = d + + def __reduce__(self): + return (type(self), (self.d,)) + + def __dealloc__(self): + del self.p + + def clear_all(self, tx_flag=ParamKeyFlag.ALL): + self.p.clearAll(tx_flag) + + def check_key(self, key): + key = ensure_bytes(key) + if not self.p.checkKey(key): + raise UnknownKeyName(key) + return key + + def python2cpp(self, proposed_type, expected_type, value, key): + cast = PYTHON_2_CPP.get((proposed_type, expected_type)) + if cast: + return cast(value) + raise TypeError(f"Type mismatch while writing param {key}: {proposed_type=} {expected_type=} {value=}") + + def _cpp2python(self, t, value, default, key): + if value is None: + return None + try: + return CPP_2_PYTHON[t](value) + except (KeyError, TypeError, ValueError): + cloudlog.warning(f"Failed to cast param {key} with {value=} from type {t=}") + return self._cpp2python(t, default, None, key) + + def get(self, key, bool block=False, bool return_default=False): + cdef string k = self.check_key(key) + cdef ParamKeyType t = self.p.getKeyType(k) + cdef optional[string] default = self.p.getKeyDefaultValue(k) + cdef string val + with nogil: + val = self.p.get(k, block) + + default_val = (default.value() if default.has_value() else None) if return_default else None + if val == b"": + if block: + # If we got no value while running in blocked mode + # it means we got an interrupt while waiting + raise KeyboardInterrupt + else: + return self._cpp2python(t, default_val, None, key) + return self._cpp2python(t, val, default_val, key) + + def get_bool(self, key, bool block=False): + cdef string k = self.check_key(key) + cdef bool r + with nogil: + r = self.p.getBool(k, block) + return r + + def _put_cast(self, key, dat): + cdef string k = self.check_key(key) + cdef ParamKeyType t = self.p.getKeyType(k) + return ensure_bytes(self.python2cpp(type(dat), t, dat, key)) + + def put(self, key, dat): + """ + Warning: This function blocks until the param is written to disk! + In very rare cases this can take over a second, and your code will hang. + Use the put_nonblocking, put_bool_nonblocking in time sensitive code, but + in general try to avoid writing params as much as possible. + """ + cdef string k = self.check_key(key) + cdef string dat_bytes = self._put_cast(key, dat) + with nogil: + self.p.put(k, dat_bytes) + + def put_bool(self, key, bool val): + cdef string k = self.check_key(key) + with nogil: + self.p.putBool(k, val) + + def put_nonblocking(self, key, dat): + cdef string k = self.check_key(key) + cdef string dat_bytes = self._put_cast(key, dat) + with nogil: + self.p.putNonBlocking(k, dat_bytes) + + def put_bool_nonblocking(self, key, bool val): + cdef string k = self.check_key(key) + with nogil: + self.p.putBoolNonBlocking(k, val) + + def remove(self, key): + cdef string k = self.check_key(key) + with nogil: + self.p.remove(k) + + def get_param_path(self, key=""): + cdef string key_bytes = ensure_bytes(key) + return self.p.getParamPath(key_bytes).decode("utf-8") + + def get_type(self, key): + return self.p.getKeyType(self.check_key(key)) + + def all_keys(self): + return self.p.allKeys() + + def get_default_value(self, key): + cdef string k = self.check_key(key) + cdef ParamKeyType t = self.p.getKeyType(k) + cdef optional[string] default = self.p.getKeyDefaultValue(k) + return self._cpp2python(t, default.value(), None, key) if default.has_value() else None + + def cpp2python(self, key, value): + cdef string k = self.check_key(key) + cdef ParamKeyType t = self.p.getKeyType(k) + return self._cpp2python(t, value, None, key) diff --git a/common/pid.py b/common/pid.py new file mode 100644 index 0000000000..99142280ca --- /dev/null +++ b/common/pid.py @@ -0,0 +1,64 @@ +import numpy as np +from numbers import Number + +class PIDController: + def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100): + self._k_p = k_p + self._k_i = k_i + self._k_d = k_d + self.k_f = k_f # feedforward gain + if isinstance(self._k_p, Number): + self._k_p = [[0], [self._k_p]] + if isinstance(self._k_i, Number): + self._k_i = [[0], [self._k_i]] + if isinstance(self._k_d, Number): + self._k_d = [[0], [self._k_d]] + + self.set_limits(pos_limit, neg_limit) + + self.i_rate = 1.0 / rate + self.speed = 0.0 + + self.reset() + + @property + def k_p(self): + return np.interp(self.speed, self._k_p[0], self._k_p[1]) + + @property + def k_i(self): + return np.interp(self.speed, self._k_i[0], self._k_i[1]) + + @property + def k_d(self): + return np.interp(self.speed, self._k_d[0], self._k_d[1]) + + def reset(self): + self.p = 0.0 + self.i = 0.0 + self.d = 0.0 + self.f = 0.0 + self.control = 0 + + def set_limits(self, pos_limit, neg_limit): + self.pos_limit = pos_limit + self.neg_limit = neg_limit + + def update(self, error, error_rate=0.0, speed=0.0, feedforward=0., freeze_integrator=False): + self.speed = speed + self.p = float(error) * self.k_p + self.f = feedforward * self.k_f + self.d = error_rate * self.k_d + + if not freeze_integrator: + i = self.i + error * self.k_i * self.i_rate + + # Don't allow windup if already clipping + test_control = self.p + i + self.d + self.f + i_upperbound = self.i if test_control > self.pos_limit else self.pos_limit + i_lowerbound = self.i if test_control < self.neg_limit else self.neg_limit + self.i = np.clip(i, i_lowerbound, i_upperbound) + + control = self.p + self.i + self.d + self.f + self.control = np.clip(control, self.neg_limit, self.pos_limit) + return self.control diff --git a/common/prefix.h b/common/prefix.h new file mode 100644 index 0000000000..2612c05d4f --- /dev/null +++ b/common/prefix.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include "common/params.h" +#include "common/util.h" +#include "system/hardware/hw.h" + +class OpenpilotPrefix { +public: + OpenpilotPrefix(std::string prefix = {}) { + if (prefix.empty()) { + prefix = util::random_string(15); + } + msgq_path = Path::shm_path() + "/" + prefix; + bool ret = util::create_directories(msgq_path, 0777); + assert(ret); + setenv("OPENPILOT_PREFIX", prefix.c_str(), 1); + } + + ~OpenpilotPrefix() { + auto param_path = Params().getParamPath(); + if (util::file_exists(param_path)) { + std::string real_path = util::readlink(param_path); + system(util::string_format("rm %s -rf", real_path.c_str()).c_str()); + unlink(param_path.c_str()); + } + if (getenv("COMMA_CACHE") == nullptr) { + system(util::string_format("rm %s -rf", Path::download_cache_root().c_str()).c_str()); + } + system(util::string_format("rm %s -rf", Path::comma_home().c_str()).c_str()); + system(util::string_format("rm %s -rf", msgq_path.c_str()).c_str()); + unsetenv("OPENPILOT_PREFIX"); + } + +private: + std::string msgq_path; +}; diff --git a/common/prefix.py b/common/prefix.py new file mode 100644 index 0000000000..207f8477d7 --- /dev/null +++ b/common/prefix.py @@ -0,0 +1,59 @@ +import os +import shutil +import uuid + + +from openpilot.common.params import Params +from openpilot.system.hardware import PC +from openpilot.system.hardware.hw import Paths +from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT + +class OpenpilotPrefix: + def __init__(self, prefix: str = None, create_dirs_on_enter: bool = True, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False): + self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15]) + self.msgq_path = os.path.join(Paths.shm_path(), self.prefix) + self.create_dirs_on_enter = create_dirs_on_enter + self.clean_dirs_on_exit = clean_dirs_on_exit + self.shared_download_cache = shared_download_cache + + def __enter__(self): + self.original_prefix = os.environ.get('OPENPILOT_PREFIX', None) + os.environ['OPENPILOT_PREFIX'] = self.prefix + + if self.create_dirs_on_enter: + self.create_dirs() + + if self.shared_download_cache: + os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT + + return self + + def __exit__(self, exc_type, exc_obj, exc_tb): + if self.clean_dirs_on_exit: + self.clean_dirs() + try: + del os.environ['OPENPILOT_PREFIX'] + if self.original_prefix is not None: + os.environ['OPENPILOT_PREFIX'] = self.original_prefix + except KeyError: + pass + return False + + def create_dirs(self): + try: + os.mkdir(self.msgq_path) + except FileExistsError: + pass + os.makedirs(Paths.log_root(), exist_ok=True) + + def clean_dirs(self): + symlink_path = Params().get_param_path() + if os.path.exists(symlink_path): + shutil.rmtree(os.path.realpath(symlink_path), ignore_errors=True) + os.remove(symlink_path) + shutil.rmtree(self.msgq_path, ignore_errors=True) + if PC: + shutil.rmtree(Paths.log_root(), ignore_errors=True) + if not os.environ.get("COMMA_CACHE", False): + shutil.rmtree(Paths.download_cache_root(), ignore_errors=True) + shutil.rmtree(Paths.comma_home(), ignore_errors=True) diff --git a/common/queue.h b/common/queue.h new file mode 100644 index 0000000000..b3558b11a4 --- /dev/null +++ b/common/queue.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include + +template +class SafeQueue { +public: + SafeQueue() = default; + + void push(const T& v) { + { + std::unique_lock lk(m); + q.push(v); + } + cv.notify_one(); + } + + T pop() { + std::unique_lock lk(m); + cv.wait(lk, [this] { return !q.empty(); }); + T v = q.front(); + q.pop(); + return v; + } + + bool try_pop(T& v, int timeout_ms = 0) { + std::unique_lock lk(m); + if (!cv.wait_for(lk, std::chrono::milliseconds(timeout_ms), [this] { return !q.empty(); })) { + return false; + } + v = q.front(); + q.pop(); + return true; + } + + bool empty() const { + std::scoped_lock lk(m); + return q.empty(); + } + + size_t size() const { + std::scoped_lock lk(m); + return q.size(); + } + +private: + mutable std::mutex m; + std::condition_variable cv; + std::queue q; +}; diff --git a/common/ratekeeper.cc b/common/ratekeeper.cc new file mode 100644 index 0000000000..7e63815168 --- /dev/null +++ b/common/ratekeeper.cc @@ -0,0 +1,40 @@ +#include "common/ratekeeper.h" + +#include + +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" + +RateKeeper::RateKeeper(const std::string &name, float rate, float print_delay_threshold) + : name(name), + print_delay_threshold(std::max(0.f, print_delay_threshold)) { + interval = 1 / rate; + last_monitor_time = seconds_since_boot(); + next_frame_time = last_monitor_time + interval; +} + +bool RateKeeper::keepTime() { + bool lagged = monitorTime(); + if (remaining_ > 0) { + util::sleep_for(remaining_ * 1000); + } + return lagged; +} + +bool RateKeeper::monitorTime() { + ++frame_; + last_monitor_time = seconds_since_boot(); + remaining_ = next_frame_time - last_monitor_time; + + bool lagged = remaining_ < 0; + if (lagged) { + if (print_delay_threshold > 0 && remaining_ < -print_delay_threshold) { + LOGW("%s lagging by %.2f ms", name.c_str(), -remaining_ * 1000); + } + next_frame_time = last_monitor_time + interval; + } else { + next_frame_time += interval; + } + return lagged; +} diff --git a/common/ratekeeper.h b/common/ratekeeper.h new file mode 100644 index 0000000000..e7323c6ec3 --- /dev/null +++ b/common/ratekeeper.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +class RateKeeper { +public: + RateKeeper(const std::string &name, float rate, float print_delay_threshold = 0); + ~RateKeeper() {} + bool keepTime(); + bool monitorTime(); + inline uint64_t frame() const { return frame_; } + inline double remaining() const { return remaining_; } + +private: + double interval; + double next_frame_time; + double last_monitor_time; + double remaining_ = 0; + float print_delay_threshold = 0; + uint64_t frame_ = 0; + std::string name; +}; diff --git a/common/realtime.py b/common/realtime.py new file mode 100644 index 0000000000..57926b4c4f --- /dev/null +++ b/common/realtime.py @@ -0,0 +1,96 @@ +"""Utilities for reading real time clocks and keeping soft real time constraints.""" +import gc +import os +import sys +import time + +from setproctitle import getproctitle + +from openpilot.common.util import MovingAverage +from openpilot.system.hardware import PC + + +# time step for each process +DT_CTRL = 0.01 # controlsd +DT_MDL = 0.05 # model +DT_HW = 0.5 # hardwared and manager +DT_DMON = 0.05 # driver monitoring + + +class Priority: + # CORE 2 + # - modeld = 55 + # - camerad = 54 + CTRL_LOW = 51 # plannerd & radard + + # CORE 3 + # - pandad = 55 + CTRL_HIGH = 53 + + +def set_core_affinity(cores: list[int]) -> None: + if sys.platform == 'linux' and not PC: + os.sched_setaffinity(0, cores) + + +def config_realtime_process(cores: int | list[int], priority: int) -> None: + gc.disable() + if sys.platform == 'linux' and not PC: + os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(priority)) + c = cores if isinstance(cores, list) else [cores, ] + set_core_affinity(c) + + +class Ratekeeper: + def __init__(self, rate: float, print_delay_threshold: float | None = 0.0) -> None: + """Rate in Hz for ratekeeping. print_delay_threshold must be nonnegative.""" + self._interval = 1. / rate + self._print_delay_threshold = print_delay_threshold + self._frame = 0 + self._remaining = 0.0 + self._process_name = getproctitle() + self._last_monitor_time = -1. + self._next_frame_time = -1. + + self.avg_dt = MovingAverage(100) + self.avg_dt.add_value(self._interval) + + @property + def frame(self) -> int: + return self._frame + + @property + def remaining(self) -> float: + return self._remaining + + @property + def lagging(self) -> bool: + expected_dt = self._interval * (1 / 0.9) + return self.avg_dt.get_average() > expected_dt + + # Maintain loop rate by calling this at the end of each loop + def keep_time(self) -> bool: + lagged = self.monitor_time() + if self._remaining > 0: + time.sleep(self._remaining) + return lagged + + # Monitors the cumulative lag, but does not enforce a rate + def monitor_time(self) -> bool: + if self._last_monitor_time < 0: + self._next_frame_time = time.monotonic() + self._interval + self._last_monitor_time = time.monotonic() + + prev = self._last_monitor_time + self._last_monitor_time = time.monotonic() + self.avg_dt.add_value(self._last_monitor_time - prev) + + lagged = False + remaining = self._next_frame_time - time.monotonic() + self._next_frame_time += self._interval + if self._print_delay_threshold is not None and remaining < -self._print_delay_threshold: + print(f"{self._process_name} lagging by {-remaining * 1000:.2f} ms") + lagged = True + self._frame += 1 + self._remaining = remaining + return lagged diff --git a/common/retry.py b/common/retry.py new file mode 100644 index 0000000000..9bd4ac9522 --- /dev/null +++ b/common/retry.py @@ -0,0 +1,30 @@ +import time +import functools + +from openpilot.common.swaglog import cloudlog + + +def retry(attempts=3, delay=1.0, ignore_failure=False): + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + for _ in range(attempts): + try: + return func(*args, **kwargs) + except Exception: + cloudlog.exception(f"{func.__name__} failed, trying again") + time.sleep(delay) + + if ignore_failure: + cloudlog.error(f"{func.__name__} failed after retry") + else: + raise Exception(f"{func.__name__} failed after retry") + return wrapper + return decorator + + +if __name__ == "__main__": + @retry(attempts=10) + def abc(): + raise ValueError("abc failed :(") + abc() diff --git a/common/run.py b/common/run.py new file mode 100644 index 0000000000..75395ead1f --- /dev/null +++ b/common/run.py @@ -0,0 +1,28 @@ +import subprocess +from contextlib import contextmanager +from subprocess import Popen, PIPE, TimeoutExpired + + +def run_cmd(cmd: list[str], cwd=None, env=None) -> str: + return subprocess.check_output(cmd, encoding='utf8', cwd=cwd, env=env).strip() + + +def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> str: + try: + return run_cmd(cmd, cwd=cwd, env=env) + except subprocess.CalledProcessError: + return default + + +@contextmanager +def managed_proc(cmd: list[str], env: dict[str, str]): + proc = Popen(cmd, env=env, stdout=PIPE, stderr=PIPE) + try: + yield proc + finally: + if proc.poll() is None: + proc.terminate() + try: + proc.wait(timeout=5) + except TimeoutExpired: + proc.kill() diff --git a/common/simple_kalman.py b/common/simple_kalman.py new file mode 100644 index 0000000000..194b27204b --- /dev/null +++ b/common/simple_kalman.py @@ -0,0 +1,54 @@ +import numpy as np + + +def get_kalman_gain(dt, A, C, Q, R, iterations=100): + P = np.zeros_like(Q) + for _ in range(iterations): + P = A.dot(P).dot(A.T) + dt * Q + S = C.dot(P).dot(C.T) + R + K = P.dot(C.T).dot(np.linalg.inv(S)) + P = (np.eye(len(P)) - K.dot(C)).dot(P) + return K + + +class KF1D: + # this EKF assumes constant covariance matrix, so calculations are much simpler + # the Kalman gain also needs to be precomputed using the control module + + def __init__(self, x0, A, C, K): + self.x0_0 = x0[0][0] + self.x1_0 = x0[1][0] + self.A0_0 = A[0][0] + self.A0_1 = A[0][1] + self.A1_0 = A[1][0] + self.A1_1 = A[1][1] + self.C0_0 = C[0] + self.C0_1 = C[1] + self.K0_0 = K[0][0] + self.K1_0 = K[1][0] + + self.A_K_0 = self.A0_0 - self.K0_0 * self.C0_0 + self.A_K_1 = self.A0_1 - self.K0_0 * self.C0_1 + self.A_K_2 = self.A1_0 - self.K1_0 * self.C0_0 + self.A_K_3 = self.A1_1 - self.K1_0 * self.C0_1 + + # K matrix needs to be pre-computed as follow: + # import control + # (x, l, K) = control.dare(np.transpose(self.A), np.transpose(self.C), Q, R) + # self.K = np.transpose(K) + + def update(self, meas): + #self.x = np.dot(self.A_K, self.x) + np.dot(self.K, meas) + x0_0 = self.A_K_0 * self.x0_0 + self.A_K_1 * self.x1_0 + self.K0_0 * meas + x1_0 = self.A_K_2 * self.x0_0 + self.A_K_3 * self.x1_0 + self.K1_0 * meas + self.x0_0 = x0_0 + self.x1_0 = x1_0 + return [self.x0_0, self.x1_0] + + @property + def x(self): + return [[self.x0_0], [self.x1_0]] + + def set_x(self, x): + self.x0_0 = x[0][0] + self.x1_0 = x[1][0] diff --git a/common/spinner.py b/common/spinner.py new file mode 100755 index 0000000000..12a816eaf8 --- /dev/null +++ b/common/spinner.py @@ -0,0 +1,52 @@ +import os +import subprocess +from openpilot.common.basedir import BASEDIR + + +class Spinner: + def __init__(self): + try: + self.spinner_proc = subprocess.Popen(["./spinner.py"], + stdin=subprocess.PIPE, + cwd=os.path.join(BASEDIR, "system", "ui"), + close_fds=True) + except OSError: + self.spinner_proc = None + + def __enter__(self): + return self + + def update(self, spinner_text: str): + if self.spinner_proc is not None: + self.spinner_proc.stdin.write(spinner_text.encode('utf8') + b"\n") + try: + self.spinner_proc.stdin.flush() + except BrokenPipeError: + pass + + def update_progress(self, cur: float, total: float): + self.update(str(round(100 * cur / total))) + + def close(self): + if self.spinner_proc is not None: + self.spinner_proc.kill() + try: + self.spinner_proc.communicate(timeout=2.) + except subprocess.TimeoutExpired: + print("WARNING: failed to kill spinner") + self.spinner_proc = None + + def __del__(self): + self.close() + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + +if __name__ == "__main__": + import time + with Spinner() as s: + s.update("Spinner text") + time.sleep(5.0) + print("gone") + time.sleep(5.0) diff --git a/common/stat_live.py b/common/stat_live.py new file mode 100644 index 0000000000..3901c448d8 --- /dev/null +++ b/common/stat_live.py @@ -0,0 +1,73 @@ +import numpy as np + +class RunningStat: + # tracks realtime mean and standard deviation without storing any data + def __init__(self, priors=None, max_trackable=-1): + self.max_trackable = max_trackable + if priors is not None: + # initialize from history + self.M = priors[0] + self.S = priors[1] + self.n = priors[2] + self.M_last = self.M + self.S_last = self.S + + else: + self.reset() + + def reset(self): + self.M = 0. + self.S = 0. + self.M_last = 0. + self.S_last = 0. + self.n = 0 + + def push_data(self, new_data): + # short term memory hack + if self.max_trackable < 0 or self.n < self.max_trackable: + self.n += 1 + if self.n == 0: + self.M_last = new_data + self.M = self.M_last + self.S_last = 0. + else: + self.M = self.M_last + (new_data - self.M_last) / self.n + self.S = self.S_last + (new_data - self.M_last) * (new_data - self.M) + self.M_last = self.M + self.S_last = self.S + + def mean(self): + return self.M + + def variance(self): + if self.n >= 2: + return self.S / (self.n - 1.) + else: + return 0 + + def std(self): + return np.sqrt(self.variance()) + + def params_to_save(self): + return [self.M, self.S, self.n] + +class RunningStatFilter: + def __init__(self, raw_priors=None, filtered_priors=None, max_trackable=-1): + self.raw_stat = RunningStat(raw_priors, -1) + self.filtered_stat = RunningStat(filtered_priors, max_trackable) + + def reset(self): + self.raw_stat.reset() + self.filtered_stat.reset() + + def push_and_update(self, new_data): + _std_last = self.raw_stat.std() + self.raw_stat.push_data(new_data) + _delta_std = self.raw_stat.std() - _std_last + if _delta_std <= 0: + self.filtered_stat.push_data(new_data) + else: + pass + # self.filtered_stat.push_data(self.filtered_stat.mean()) + +# class SequentialBayesian(): diff --git a/common/swaglog.cc b/common/swaglog.cc new file mode 100644 index 0000000000..62a405a2b6 --- /dev/null +++ b/common/swaglog.cc @@ -0,0 +1,155 @@ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "common/swaglog.h" + +#include +#include +#include +#include + +#include +#include +#include "third_party/json11/json11.hpp" +#include "common/version.h" +#include "system/hardware/hw.h" + +class SwaglogState { +public: + SwaglogState() { + zctx = zmq_ctx_new(); + sock = zmq_socket(zctx, ZMQ_PUSH); + + // Timeout on shutdown for messages to be received by the logging process + int timeout = 100; + zmq_setsockopt(sock, ZMQ_LINGER, &timeout, sizeof(timeout)); + zmq_connect(sock, Path::swaglog_ipc().c_str()); + + // workaround for https://github.com/dropbox/json11/issues/38 + setlocale(LC_NUMERIC, "C"); + + print_level = CLOUDLOG_WARNING; + if (const char* print_lvl = getenv("LOGPRINT")) { + if (strcmp(print_lvl, "debug") == 0) { + print_level = CLOUDLOG_DEBUG; + } else if (strcmp(print_lvl, "info") == 0) { + print_level = CLOUDLOG_INFO; + } else if (strcmp(print_lvl, "warning") == 0) { + print_level = CLOUDLOG_WARNING; + } + } + + ctx_j = json11::Json::object{}; + if (char* dongle_id = getenv("DONGLE_ID")) { + ctx_j["dongle_id"] = dongle_id; + } + if (char* git_origin = getenv("GIT_ORIGIN")) { + ctx_j["origin"] = git_origin; + } + if (char* git_branch = getenv("GIT_BRANCH")) { + ctx_j["branch"] = git_branch; + } + if (char* git_commit = getenv("GIT_COMMIT")) { + ctx_j["commit"] = git_commit; + } + if (char* daemon_name = getenv("MANAGER_DAEMON")) { + ctx_j["daemon"] = daemon_name; + } + ctx_j["version"] = COMMA_VERSION; + ctx_j["dirty"] = !getenv("CLEAN"); + ctx_j["device"] = Hardware::get_name(); + } + + ~SwaglogState() { + zmq_close(sock); + zmq_ctx_destroy(zctx); + } + + void log(int levelnum, const char* filename, int lineno, const char* func, const char* msg, const std::string& log_s) { + std::lock_guard lk(lock); + if (levelnum >= print_level) { + printf("%s: %s\n", filename, msg); + } + zmq_send(sock, log_s.data(), log_s.length(), ZMQ_NOBLOCK); + } + + std::mutex lock; + void* zctx = nullptr; + void* sock = nullptr; + int print_level; + json11::Json::object ctx_j; +}; + +bool LOG_TIMESTAMPS = getenv("LOG_TIMESTAMPS"); +uint32_t NO_FRAME_ID = std::numeric_limits::max(); + +static void cloudlog_common(int levelnum, const char* filename, int lineno, const char* func, + char* msg_buf, const json11::Json::object &msg_j={}) { + static SwaglogState s; + + json11::Json::object log_j = json11::Json::object { + {"ctx", s.ctx_j}, + {"levelnum", levelnum}, + {"filename", filename}, + {"lineno", lineno}, + {"funcname", func}, + {"created", seconds_since_epoch()} + }; + if (msg_j.empty()) { + log_j["msg"] = msg_buf; + } else { + log_j["msg"] = msg_j; + } + + std::string log_s; + log_s += (char)levelnum; + ((json11::Json)log_j).dump(log_s); + s.log(levelnum, filename, lineno, func, msg_buf, log_s); + + free(msg_buf); +} + +void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func, + const char* fmt, ...) { + va_list args; + va_start(args, fmt); + char* msg_buf = nullptr; + int ret = vasprintf(&msg_buf, fmt, args); + va_end(args); + if (ret <= 0 || !msg_buf) return; + cloudlog_common(levelnum, filename, lineno, func, msg_buf); +} + +void cloudlog_t_common(int levelnum, const char* filename, int lineno, const char* func, + uint32_t frame_id, const char* fmt, va_list args) { + if (!LOG_TIMESTAMPS) return; + char* msg_buf = nullptr; + int ret = vasprintf(&msg_buf, fmt, args); + if (ret <= 0 || !msg_buf) return; + json11::Json::object tspt_j = json11::Json::object{ + {"event", msg_buf}, + {"time", std::to_string(nanos_since_boot())} + }; + if (frame_id < NO_FRAME_ID) { + tspt_j["frame_id"] = std::to_string(frame_id); + } + tspt_j = json11::Json::object{{"timestamp", tspt_j}}; + cloudlog_common(levelnum, filename, lineno, func, msg_buf, tspt_j); +} + + +void cloudlog_te(int levelnum, const char* filename, int lineno, const char* func, + const char* fmt, ...) { + va_list args; + va_start(args, fmt); + cloudlog_t_common(levelnum, filename, lineno, func, NO_FRAME_ID, fmt, args); + va_end(args); +} +void cloudlog_te(int levelnum, const char* filename, int lineno, const char* func, + uint32_t frame_id, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + cloudlog_t_common(levelnum, filename, lineno, func, frame_id, fmt, args); + va_end(args); +} diff --git a/common/swaglog.h b/common/swaglog.h new file mode 100644 index 0000000000..06d45b1d98 --- /dev/null +++ b/common/swaglog.h @@ -0,0 +1,76 @@ +#pragma once + +#include "common/timing.h" + +#define CLOUDLOG_DEBUG 10 +#define CLOUDLOG_INFO 20 +#define CLOUDLOG_WARNING 30 +#define CLOUDLOG_ERROR 40 +#define CLOUDLOG_CRITICAL 50 + + +#ifdef __GNUC__ +#define SWAG_LOG_CHECK_FMT(a, b) __attribute__ ((format (printf, a, b))) +#else +#define SWAG_LOG_CHECK_FMT(a, b) +#endif + +void cloudlog_e(int levelnum, const char* filename, int lineno, const char* func, + const char* fmt, ...) SWAG_LOG_CHECK_FMT(5, 6); + +void cloudlog_te(int levelnum, const char* filename, int lineno, const char* func, + const char* fmt, ...) SWAG_LOG_CHECK_FMT(5, 6); + +void cloudlog_te(int levelnum, const char* filename, int lineno, const char* func, + uint32_t frame_id, const char* fmt, ...) SWAG_LOG_CHECK_FMT(6, 7); + + +#define cloudlog(lvl, fmt, ...) cloudlog_e(lvl, __FILE__, __LINE__, \ + __func__, \ + fmt, ## __VA_ARGS__) + +#define cloudlog_t(lvl, ...) cloudlog_te(lvl, __FILE__, __LINE__, \ + __func__, \ + __VA_ARGS__) + + +#define cloudlog_rl(burst, millis, lvl, fmt, ...) \ +{ \ + static uint64_t __begin = 0; \ + static int __printed = 0; \ + static int __missed = 0; \ + \ + int __burst = (burst); \ + int __millis = (millis); \ + uint64_t __ts = nanos_since_boot(); \ + \ + if (!__begin) { __begin = __ts; } \ + \ + if (__begin + __millis*1000000ULL < __ts) { \ + if (__missed) { \ + cloudlog(CLOUDLOG_WARNING, "cloudlog: %d messages suppressed", __missed); \ + } \ + __begin = 0; \ + __printed = 0; \ + __missed = 0; \ + } \ + \ + if (__printed < __burst) { \ + cloudlog(lvl, fmt, ## __VA_ARGS__); \ + __printed++; \ + } else { \ + __missed++; \ + } \ +} + + +#define LOGT(...) cloudlog_t(CLOUDLOG_DEBUG, __VA_ARGS__) +#define LOGD(fmt, ...) cloudlog(CLOUDLOG_DEBUG, fmt, ## __VA_ARGS__) +#define LOG(fmt, ...) cloudlog(CLOUDLOG_INFO, fmt, ## __VA_ARGS__) +#define LOGW(fmt, ...) cloudlog(CLOUDLOG_WARNING, fmt, ## __VA_ARGS__) +#define LOGE(fmt, ...) cloudlog(CLOUDLOG_ERROR, fmt, ## __VA_ARGS__) + +#define LOGD_100(fmt, ...) cloudlog_rl(2, 100, CLOUDLOG_DEBUG, fmt, ## __VA_ARGS__) +#define LOG_100(fmt, ...) cloudlog_rl(2, 100, CLOUDLOG_INFO, fmt, ## __VA_ARGS__) +#define LOGW_100(fmt, ...) cloudlog_rl(2, 100, CLOUDLOG_WARNING, fmt, ## __VA_ARGS__) +#define LOGE_100(fmt, ...) cloudlog_rl(2, 100, CLOUDLOG_ERROR, fmt, ## __VA_ARGS__) diff --git a/common/swaglog.py b/common/swaglog.py new file mode 100644 index 0000000000..d009f00e76 --- /dev/null +++ b/common/swaglog.py @@ -0,0 +1,144 @@ +import logging +import os +import time +import warnings +from pathlib import Path +from logging.handlers import BaseRotatingHandler + +import zmq + +from openpilot.common.logging_extra import SwagLogger, SwagFormatter, SwagLogFileFormatter +from openpilot.system.hardware.hw import Paths + + +def get_file_handler(): + Path(Paths.swaglog_root()).mkdir(parents=True, exist_ok=True) + base_filename = os.path.join(Paths.swaglog_root(), "swaglog") + handler = SwaglogRotatingFileHandler(base_filename) + return handler + +class SwaglogRotatingFileHandler(BaseRotatingHandler): + def __init__(self, base_filename, interval=60, max_bytes=1024*256, backup_count=2500, encoding=None): + super().__init__(base_filename, mode="a", encoding=encoding, delay=True) + self.base_filename = base_filename + self.interval = interval # seconds + self.max_bytes = max_bytes + self.backup_count = backup_count + self.log_files = self.get_existing_logfiles() + log_indexes = [f.split(".")[-1] for f in self.log_files] + self.last_file_idx = max([int(i) for i in log_indexes if i.isdigit()] or [-1]) + self.last_rollover = None + self.doRollover() + + def _open(self): + self.last_rollover = time.monotonic() + self.last_file_idx += 1 + next_filename = f"{self.base_filename}.{self.last_file_idx:010}" + stream = open(next_filename, self.mode, encoding=self.encoding) + self.log_files.insert(0, next_filename) + return stream + + def get_existing_logfiles(self): + log_files = list() + base_dir = os.path.dirname(self.base_filename) + for fn in os.listdir(base_dir): + fp = os.path.join(base_dir, fn) + if fp.startswith(self.base_filename) and os.path.isfile(fp): + log_files.append(fp) + return sorted(log_files) + + def shouldRollover(self, record): + size_exceeded = self.max_bytes > 0 and self.stream.tell() >= self.max_bytes + time_exceeded = self.interval > 0 and self.last_rollover + self.interval <= time.monotonic() + return size_exceeded or time_exceeded + + def doRollover(self): + if self.stream: + self.stream.close() + self.stream = self._open() + + if self.backup_count > 0: + while len(self.log_files) > self.backup_count: + to_delete = self.log_files.pop() + if os.path.exists(to_delete): # just being safe, should always exist + os.remove(to_delete) + +class UnixDomainSocketHandler(logging.Handler): + def __init__(self, formatter): + logging.Handler.__init__(self) + self.setFormatter(formatter) + self.pid = None + + self.zctx = None + self.sock = None + + def __del__(self): + self.close() + + def close(self): + if self.sock is not None: + self.sock.close() + if self.zctx is not None: + self.zctx.term() + + def connect(self): + self.zctx = zmq.Context() + self.sock = self.zctx.socket(zmq.PUSH) + self.sock.setsockopt(zmq.LINGER, 10) + self.sock.connect(Paths.swaglog_ipc()) + self.pid = os.getpid() + + def emit(self, record): + if os.getpid() != self.pid: + # TODO suppresses warning about forking proc with zmq socket, fix root cause + warnings.filterwarnings("ignore", category=ResourceWarning, message="unclosed.*") + self.connect() + + msg = self.format(record).rstrip('\n') + # print("SEND".format(repr(msg))) + try: + s = chr(record.levelno)+msg + self.sock.send(s.encode('utf8'), zmq.NOBLOCK) + except zmq.error.Again: + # drop :/ + pass + + +class ForwardingHandler(logging.Handler): + def __init__(self, target_logger): + super().__init__() + self.target_logger = target_logger + + def emit(self, record): + self.target_logger.handle(record) + + +def add_file_handler(log): + """ + Function to add the file log handler to swaglog. + This can be used to store logs when logmessaged is not running. + """ + handler = get_file_handler() + handler.setFormatter(SwagLogFileFormatter(log)) + log.addHandler(handler) + + +cloudlog = log = SwagLogger() +log.setLevel(logging.DEBUG) + + +outhandler = logging.StreamHandler() + +print_level = os.environ.get('LOGPRINT', 'warning') +if print_level == 'debug': + outhandler.setLevel(logging.DEBUG) +elif print_level == 'info': + outhandler.setLevel(logging.INFO) +elif print_level == 'warning': + outhandler.setLevel(logging.WARNING) + +ipchandler = UnixDomainSocketHandler(SwagFormatter(log)) + +log.addHandler(outhandler) +# logs are sent through IPC before writing to disk to prevent disk I/O blocking +log.addHandler(ipchandler) diff --git a/common/tests/.gitignore b/common/tests/.gitignore new file mode 100644 index 0000000000..6cddfc7bdf --- /dev/null +++ b/common/tests/.gitignore @@ -0,0 +1 @@ +test_common diff --git a/common/tests/__init__.py b/common/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/tests/test_file_helpers.py b/common/tests/test_file_helpers.py new file mode 100644 index 0000000000..a9977c2362 --- /dev/null +++ b/common/tests/test_file_helpers.py @@ -0,0 +1,19 @@ +import os +from uuid import uuid4 + +from openpilot.common.file_helpers import atomic_write_in_dir + + +class TestFileHelpers: + def run_atomic_write_func(self, atomic_write_func): + path = f"/tmp/tmp{uuid4()}" + with atomic_write_func(path) as f: + f.write("test") + assert not os.path.exists(path) + + with open(path) as f: + assert f.read() == "test" + os.remove(path) + + def test_atomic_write_in_dir(self): + self.run_atomic_write_func(atomic_write_in_dir) diff --git a/common/tests/test_markdown.py b/common/tests/test_markdown.py new file mode 100644 index 0000000000..d3c7e02c69 --- /dev/null +++ b/common/tests/test_markdown.py @@ -0,0 +1,15 @@ +import os + +from openpilot.common.basedir import BASEDIR +from openpilot.common.markdown import parse_markdown + + +class TestMarkdown: + def test_all_release_notes(self): + with open(os.path.join(BASEDIR, "RELEASES.md")) as f: + release_notes = f.read().split("\n\n") + assert len(release_notes) > 10 + + for rn in release_notes: + md = parse_markdown(rn) + assert len(md) > 0 diff --git a/common/tests/test_params.cc b/common/tests/test_params.cc new file mode 100644 index 0000000000..f8d6c79f55 --- /dev/null +++ b/common/tests/test_params.cc @@ -0,0 +1,27 @@ +#include "catch2/catch.hpp" +#define private public +#include "common/params.h" +#include "common/util.h" + +TEST_CASE("params_nonblocking_put") { + char tmp_path[] = "/tmp/asyncWriter_XXXXXX"; + const std::string param_path = mkdtemp(tmp_path); + auto param_names = {"CarParams", "IsMetric"}; + { + Params params(param_path); + for (const auto &name : param_names) { + params.putNonBlocking(name, "1"); + // param is empty + REQUIRE(params.get(name).empty()); + } + + // check if thread is running + REQUIRE(params.future.valid()); + REQUIRE(params.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout); + } + // check results + Params p(param_path); + for (const auto &name : param_names) { + REQUIRE(p.get(name) == "1"); + } +} diff --git a/common/tests/test_params.py b/common/tests/test_params.py new file mode 100644 index 0000000000..592bf2c4b2 --- /dev/null +++ b/common/tests/test_params.py @@ -0,0 +1,141 @@ +import pytest +import datetime +import os +import threading +import time +import uuid + +from openpilot.common.params import Params, ParamKeyFlag, UnknownKeyName + +class TestParams: + def setup_method(self): + self.params = Params() + + def test_params_put_and_get(self): + self.params.put("DongleId", "cb38263377b873ee") + assert self.params.get("DongleId") == "cb38263377b873ee" + + def test_params_non_ascii(self): + st = b"\xe1\x90\xff" + self.params.put("CarParams", st) + assert self.params.get("CarParams") == st + + def test_params_get_cleared_manager_start(self): + self.params.put("CarParams", b"test") + self.params.put("DongleId", "cb38263377b873ee") + assert self.params.get("CarParams") == b"test" + + undefined_param = self.params.get_param_path(uuid.uuid4().hex) + with open(undefined_param, "w") as f: + f.write("test") + assert os.path.isfile(undefined_param) + + self.params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START) + assert self.params.get("CarParams") is None + assert self.params.get("DongleId") is not None + assert not os.path.isfile(undefined_param) + + def test_params_two_things(self): + self.params.put("DongleId", "bob") + self.params.put("AthenadPid", 123) + assert self.params.get("DongleId") == "bob" + assert self.params.get("AthenadPid") == 123 + + def test_params_get_block(self): + def _delayed_writer(): + time.sleep(0.1) + self.params.put("CarParams", b"test") + threading.Thread(target=_delayed_writer).start() + assert self.params.get("CarParams") is None + assert self.params.get("CarParams", block=True) == b"test" + + def test_params_unknown_key_fails(self): + with pytest.raises(UnknownKeyName): + self.params.get("swag") + + with pytest.raises(UnknownKeyName): + self.params.get_bool("swag") + + with pytest.raises(UnknownKeyName): + self.params.put("swag", "abc") + + with pytest.raises(UnknownKeyName): + self.params.put_bool("swag", True) + + def test_remove_not_there(self): + assert self.params.get("CarParams") is None + self.params.remove("CarParams") + assert self.params.get("CarParams") is None + + def test_get_bool(self): + self.params.remove("IsMetric") + assert not self.params.get_bool("IsMetric") + + self.params.put_bool("IsMetric", True) + assert self.params.get_bool("IsMetric") + + self.params.put_bool("IsMetric", False) + assert not self.params.get_bool("IsMetric") + + self.params.put("IsMetric", True) + assert self.params.get_bool("IsMetric") + + self.params.put("IsMetric", False) + assert not self.params.get_bool("IsMetric") + + def test_put_non_blocking_with_get_block(self): + q = Params() + def _delayed_writer(): + time.sleep(0.1) + Params().put_nonblocking("CarParams", b"test") + threading.Thread(target=_delayed_writer).start() + assert q.get("CarParams") is None + assert q.get("CarParams", True) == b"test" + + def test_put_bool_non_blocking_with_get_block(self): + q = Params() + def _delayed_writer(): + time.sleep(0.1) + Params().put_bool_nonblocking("CarParams", True) + threading.Thread(target=_delayed_writer).start() + assert q.get("CarParams") is None + assert q.get("CarParams", True) == b"1" + + def test_params_all_keys(self): + keys = Params().all_keys() + + # sanity checks + assert len(keys) > 20 + assert len(keys) == len(set(keys)) + assert b"CarParams" in keys + + def test_params_default_value(self): + self.params.remove("LanguageSetting") + self.params.remove("LongitudinalPersonality") + self.params.remove("LiveParameters") + + assert self.params.get("LanguageSetting") is None + assert self.params.get("LanguageSetting", return_default=False) is None + assert isinstance(self.params.get("LanguageSetting", return_default=True), str) + assert isinstance(self.params.get("LongitudinalPersonality", return_default=True), int) + assert self.params.get("LiveParameters") is None + assert self.params.get("LiveParameters", return_default=True) is None + + def test_params_get_type(self): + # json + self.params.put("ApiCache_FirehoseStats", {"a": 0}) + assert self.params.get("ApiCache_FirehoseStats") == {"a": 0} + + # int + self.params.put("BootCount", 1441) + assert self.params.get("BootCount") == 1441 + + # bool + self.params.put("AdbEnabled", True) + assert self.params.get("AdbEnabled") + assert isinstance(self.params.get("AdbEnabled"), bool) + + # time + now = datetime.datetime.now(datetime.UTC) + self.params.put("InstallDate", now) + assert self.params.get("InstallDate") == now diff --git a/common/tests/test_runner.cc b/common/tests/test_runner.cc new file mode 100644 index 0000000000..62bf7476a1 --- /dev/null +++ b/common/tests/test_runner.cc @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/common/tests/test_simple_kalman.py b/common/tests/test_simple_kalman.py new file mode 100644 index 0000000000..e44ac2cc57 --- /dev/null +++ b/common/tests/test_simple_kalman.py @@ -0,0 +1,29 @@ +from openpilot.common.simple_kalman import KF1D + + +class TestSimpleKalman: + def setup_method(self): + dt = 0.01 + x0_0 = 0.0 + x1_0 = 0.0 + A0_0 = 1.0 + A0_1 = dt + A1_0 = 0.0 + A1_1 = 1.0 + C0_0 = 1.0 + C0_1 = 0.0 + K0_0 = 0.12287673 + K1_0 = 0.29666309 + + self.kf = KF1D(x0=[[x0_0], [x1_0]], + A=[[A0_0, A0_1], [A1_0, A1_1]], + C=[C0_0, C0_1], + K=[[K0_0], [K1_0]]) + + def test_getter_setter(self): + self.kf.set_x([[1.0], [1.0]]) + assert self.kf.x == [[1.0], [1.0]] + + def test_update_returns_state(self): + x = self.kf.update(100) + assert x == [i[0] for i in self.kf.x] diff --git a/common/tests/test_swaglog.cc b/common/tests/test_swaglog.cc new file mode 100644 index 0000000000..09bc4c3795 --- /dev/null +++ b/common/tests/test_swaglog.cc @@ -0,0 +1,88 @@ +#include + +#include + +#include "catch2/catch.hpp" +#include "common/swaglog.h" +#include "common/util.h" +#include "common/version.h" +#include "system/hardware/hw.h" +#include "third_party/json11/json11.hpp" + +std::string daemon_name = "testy"; +std::string dongle_id = "test_dongle_id"; +int LINE_NO = 0; + +void log_thread(int thread_id, int msg_cnt) { + for (int i = 0; i < msg_cnt; ++i) { + LOGD("%d", thread_id); + LINE_NO = __LINE__ - 1; + usleep(1); + } +} + +void recv_log(int thread_cnt, int thread_msg_cnt) { + void *zctx = zmq_ctx_new(); + void *sock = zmq_socket(zctx, ZMQ_PULL); + zmq_bind(sock, Path::swaglog_ipc().c_str()); + std::vector thread_msgs(thread_cnt); + int total_count = 0; + + for (auto start = std::chrono::steady_clock::now(), now = start; + now < start + std::chrono::seconds{1} && total_count < (thread_cnt * thread_msg_cnt); + now = std::chrono::steady_clock::now()) { + char buf[4096] = {}; + if (zmq_recv(sock, buf, sizeof(buf), ZMQ_DONTWAIT) <= 0) { + if (errno == EAGAIN || errno == EINTR || errno == EFSM) continue; + break; + } + + REQUIRE(buf[0] == CLOUDLOG_DEBUG); + std::string err; + auto msg = json11::Json::parse(buf + 1, err); + REQUIRE(!msg.is_null()); + + REQUIRE(msg["levelnum"].int_value() == CLOUDLOG_DEBUG); + REQUIRE_THAT(msg["filename"].string_value(), Catch::Contains("test_swaglog.cc")); + REQUIRE(msg["funcname"].string_value() == "log_thread"); + REQUIRE(msg["lineno"].int_value() == LINE_NO); + + auto ctx = msg["ctx"]; + + REQUIRE(ctx["daemon"].string_value() == daemon_name); + REQUIRE(ctx["dongle_id"].string_value() == dongle_id); + REQUIRE(ctx["dirty"].bool_value() == true); + + REQUIRE(ctx["version"].string_value() == COMMA_VERSION); + + std::string device = Hardware::get_name(); + REQUIRE(ctx["device"].string_value() == device); + + int thread_id = atoi(msg["msg"].string_value().c_str()); + REQUIRE((thread_id >= 0 && thread_id < thread_cnt)); + thread_msgs[thread_id]++; + total_count++; + } + for (int i = 0; i < thread_cnt; ++i) { + INFO("thread :" << i); + REQUIRE(thread_msgs[i] == thread_msg_cnt); + } + zmq_close(sock); + zmq_ctx_destroy(zctx); +} + +TEST_CASE("swaglog") { + setenv("MANAGER_DAEMON", daemon_name.c_str(), 1); + setenv("DONGLE_ID", dongle_id.c_str(), 1); + setenv("dirty", "1", 1); + const int thread_cnt = 5; + const int thread_msg_cnt = 100; + + std::vector log_threads; + for (int i = 0; i < thread_cnt; ++i) { + log_threads.push_back(std::thread(log_thread, i, thread_msg_cnt)); + } + for (auto &t : log_threads) t.join(); + + recv_log(thread_cnt, thread_msg_cnt); +} diff --git a/common/tests/test_util.cc b/common/tests/test_util.cc new file mode 100644 index 0000000000..de87fa3e06 --- /dev/null +++ b/common/tests/test_util.cc @@ -0,0 +1,147 @@ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "catch2/catch.hpp" +#include "common/util.h" + +std::string random_bytes(int size) { + std::random_device rd; + std::independent_bits_engine rbe(rd()); + std::string bytes(size + 1, '\0'); + std::generate(bytes.begin(), bytes.end(), std::ref(rbe)); + return bytes; +} + +TEST_CASE("util::read_file") { + SECTION("read /proc/version") { + std::string ret = util::read_file("/proc/version"); + REQUIRE(ret.find("Linux version") != std::string::npos); + } + SECTION("read from sysfs") { + std::string ret = util::read_file("/sys/power/wakeup_count"); + REQUIRE(!ret.empty()); + } + SECTION("read file") { + char filename[] = "/tmp/test_read_XXXXXX"; + int fd = mkstemp(filename); + + REQUIRE(util::read_file(filename).empty()); + + std::string content = random_bytes(64 * 1024); + write(fd, content.c_str(), content.size()); + std::string ret = util::read_file(filename); + bool equal = (ret == content); + REQUIRE(equal); + close(fd); + } + SECTION("read directory") { + REQUIRE(util::read_file(".").empty()); + } + SECTION("read non-existent file") { + std::string ret = util::read_file("does_not_exist"); + REQUIRE(ret.empty()); + } + SECTION("read non-permission") { + REQUIRE(util::read_file("/proc/kmsg").empty()); + } +} + +TEST_CASE("util::file_exists") { + char filename[] = "/tmp/test_file_exists_XXXXXX"; + int fd = mkstemp(filename); + REQUIRE(fd != -1); + close(fd); + + SECTION("existent file") { + REQUIRE(util::file_exists(filename)); + REQUIRE(util::file_exists("/tmp")); + } + SECTION("nonexistent file") { + std::string fn = filename; + REQUIRE(!util::file_exists(fn + "/nonexistent")); + } + SECTION("file has no access permissions") { + std::string fn = "/proc/kmsg"; + std::ifstream f(fn); + REQUIRE(f.good() == false); + REQUIRE(util::file_exists(fn)); + } + ::remove(filename); +} + +TEST_CASE("util::read_files_in_dir") { + char tmp_path[] = "/tmp/test_XXXXXX"; + const std::string test_path = mkdtemp(tmp_path); + const std::string files[] = {".test1", "'test2'", "test3"}; + for (auto fn : files) { + std::ofstream{test_path + "/" + fn} << fn; + } + mkdir((test_path + "/dir").c_str(), 0777); + + std::map result = util::read_files_in_dir(test_path); + REQUIRE(result.find("dir") == result.end()); + REQUIRE(result.size() == std::size(files)); + for (auto& [k, v] : result) { + REQUIRE(k == v); + } +} + + +TEST_CASE("util::safe_fwrite") { + char filename[] = "/tmp/XXXXXX"; + int fd = mkstemp(filename); + close(fd); + std::string dat = random_bytes(1024 * 1024); + + FILE *f = util::safe_fopen(filename, "wb"); + REQUIRE(f != nullptr); + size_t size = util::safe_fwrite(dat.data(), 1, dat.size(), f); + REQUIRE(size == dat.size()); + int ret = util::safe_fflush(f); + REQUIRE(ret == 0); + ret = fclose(f); + REQUIRE(ret == 0); + bool equal = (dat == util::read_file(filename)); + REQUIRE(equal); +} + +TEST_CASE("util::create_directories") { + system("rm /tmp/test_create_directories -rf"); + std::string dir = "/tmp/test_create_directories/a/b/c/d/e/f"; + + auto check_dir_permissions = [](const std::string &dir, mode_t mode) -> bool { + struct stat st = {}; + return stat(dir.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR && (st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)) == mode; + }; + + SECTION("create_directories") { + REQUIRE(util::create_directories(dir, 0755)); + REQUIRE(check_dir_permissions(dir, 0755)); + } + SECTION("dir already exists") { + REQUIRE(util::create_directories(dir, 0755)); + REQUIRE(util::create_directories(dir, 0755)); + } + SECTION("a file exists with the same name") { + REQUIRE(util::create_directories(dir, 0755)); + int f = open((dir + "/file").c_str(), O_RDWR | O_CREAT); + REQUIRE(f != -1); + close(f); + REQUIRE(util::create_directories(dir + "/file", 0755) == false); + REQUIRE(util::create_directories(dir + "/file/1/2/3", 0755) == false); + } + SECTION("end with slashes") { + REQUIRE(util::create_directories(dir + "/", 0755)); + } + SECTION("empty") { + REQUIRE(util::create_directories("", 0755) == false); + } +} diff --git a/common/text_window.py b/common/text_window.py new file mode 100755 index 0000000000..358243d1f1 --- /dev/null +++ b/common/text_window.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +import os +import time +import subprocess +from openpilot.common.basedir import BASEDIR + + +class TextWindow: + def __init__(self, text): + try: + self.text_proc = subprocess.Popen(["./text.py", text], + stdin=subprocess.PIPE, + cwd=os.path.join(BASEDIR, "system", "ui"), + close_fds=True) + except OSError: + self.text_proc = None + + def get_status(self): + if self.text_proc is not None: + self.text_proc.poll() + return self.text_proc.returncode + return None + + def __enter__(self): + return self + + def close(self): + if self.text_proc is not None: + self.text_proc.terminate() + self.text_proc = None + + def wait_for_exit(self): + if self.text_proc is not None: + while True: + if self.get_status() == 1: + return + time.sleep(0.1) + + def __del__(self): + self.close() + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + +if __name__ == "__main__": + text = """Traceback (most recent call last): + File "./controlsd.py", line 608, in + main() + File "./controlsd.py", line 604, in main + controlsd_thread(sm, pm, logcan) + File "./controlsd.py", line 455, in controlsd_thread + 1/0 +ZeroDivisionError: division by zero""" + print(text) + + with TextWindow(text) as s: + for _ in range(100): + if s.get_status() == 1: + print("Got exit button") + break + time.sleep(0.1) + print("gone") diff --git a/common/time_helpers.py b/common/time_helpers.py new file mode 100644 index 0000000000..8564e270c2 --- /dev/null +++ b/common/time_helpers.py @@ -0,0 +1,15 @@ +import datetime +from pathlib import Path + +MIN_DATE = datetime.datetime(year=2025, month=2, day=21) + +def min_date(): + # on systemd systems, the default time is the systemd build time + systemd_path = Path("/lib/systemd/systemd") + if systemd_path.exists(): + d = datetime.datetime.fromtimestamp(systemd_path.stat().st_mtime) + return max(MIN_DATE, d + datetime.timedelta(days=1)) + return MIN_DATE + +def system_time_valid(): + return datetime.datetime.now() > min_date() diff --git a/common/timeout.py b/common/timeout.py new file mode 100644 index 0000000000..d0b0ce0630 --- /dev/null +++ b/common/timeout.py @@ -0,0 +1,27 @@ +import signal + +class TimeoutException(Exception): + pass + +class Timeout: + """ + Timeout context manager. + For example this code will raise a TimeoutException: + with Timeout(seconds=5, error_msg="Sleep was too long"): + time.sleep(10) + """ + def __init__(self, seconds, error_msg=None): + if error_msg is None: + error_msg = f'Timed out after {seconds} seconds' + self.seconds = seconds + self.error_msg = error_msg + + def handle_timeout(self, signume, frame): + raise TimeoutException(self.error_msg) + + def __enter__(self): + signal.signal(signal.SIGALRM, self.handle_timeout) + signal.alarm(self.seconds) + + def __exit__(self, exc_type, exc_val, exc_tb): + signal.alarm(0) diff --git a/common/timing.h b/common/timing.h new file mode 100644 index 0000000000..83f55e0c40 --- /dev/null +++ b/common/timing.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#ifdef __APPLE__ +#define CLOCK_BOOTTIME CLOCK_MONOTONIC +#endif + +static inline uint64_t nanos_since_boot() { + struct timespec t; + clock_gettime(CLOCK_BOOTTIME, &t); + return t.tv_sec * 1000000000ULL + t.tv_nsec; +} + +static inline double millis_since_boot() { + struct timespec t; + clock_gettime(CLOCK_BOOTTIME, &t); + return t.tv_sec * 1000.0 + t.tv_nsec * 1e-6; +} + +static inline double seconds_since_boot() { + struct timespec t; + clock_gettime(CLOCK_BOOTTIME, &t); + return (double)t.tv_sec + t.tv_nsec * 1e-9; +} + +static inline uint64_t nanos_since_epoch() { + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return t.tv_sec * 1000000000ULL + t.tv_nsec; +} + +static inline double seconds_since_epoch() { + struct timespec t; + clock_gettime(CLOCK_REALTIME, &t); + return (double)t.tv_sec + t.tv_nsec * 1e-9; +} + +// you probably should use nanos_since_boot instead +static inline uint64_t nanos_monotonic() { + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return t.tv_sec * 1000000000ULL + t.tv_nsec; +} + +static inline uint64_t nanos_monotonic_raw() { + struct timespec t; + clock_gettime(CLOCK_MONOTONIC_RAW, &t); + return t.tv_sec * 1000000000ULL + t.tv_nsec; +} diff --git a/common/transformations/.gitignore b/common/transformations/.gitignore new file mode 100644 index 0000000000..a67290f09a --- /dev/null +++ b/common/transformations/.gitignore @@ -0,0 +1,2 @@ +transformations +transformations.cpp diff --git a/common/transformations/README.md b/common/transformations/README.md new file mode 100644 index 0000000000..42a060da80 --- /dev/null +++ b/common/transformations/README.md @@ -0,0 +1,70 @@ + +Reference Frames +------ +Many reference frames are used throughout. This +folder contains all helper functions needed to +transform between them. Generally this is done +by generating a rotation matrix and multiplying. + + +| Name | [x, y, z] | Units | Notes | +| :-------------: |:-------------:| :-----:| :----: | +| Geodetic | [Latitude, Longitude, Altitude] | geodetic coordinates | Sometimes used as [lon, lat, alt], avoid this frame. | +| ECEF | [x, y, z] | meters | We use **ITRF14 (IGS14)**, NOT NAD83.
    This is the global Mesh3D frame. | +| NED | [North, East, Down] | meters | Relative to earth's surface, useful for visualizing. | +| Device | [Forward, Right, Down] | meters | This is the Mesh3D local frame.
    Relative to camera, **not imu.**
    ![img](http://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/RPY_angles_of_airplanes.png/440px-RPY_angles_of_airplanes.png)| +| Calibrated | [Forward, Right, Down] | meters | This is the frame the model outputs are in.
    More details below.
    | +| Car | [Forward, Right, Down] | meters | This is useful for estimating position of points on the road.
    More details below.
    | +| View | [Right, Down, Forward] | meters | Like device frame, but according to camera conventions. | +| Camera | [u, v, focal] | pixels | Like view frame, but 2d on the camera image.| +| Normalized Camera | [u / focal, v / focal, 1] | / | | +| Model | [u, v, focal] | pixels | The sampled rectangle of the full camera frame the model uses. | +| Normalized Model | [u / focal, v / focal, 1] | / | | + + + + +Orientation Conventions +------ +Quaternions, rotation matrices and euler angles are three +equivalent representations of orientation and all three are +used throughout the code base. + +For euler angles the preferred convention is [roll, pitch, yaw] +which corresponds to rotations around the [x, y, z] axes. All +euler angles should always be in radians or radians/s unless +for plotting or display purposes. For quaternions the hamilton +notations is preferred which is [qw, qx, qy, qz]. All quaternions +should always be normalized with a strictly positive qw. **These +quaternions are a unique representation of orientation whereas euler angles +or rotation matrices are not.** + +To rotate from one frame into another with euler angles the +convention is to rotate around roll, then pitch and then yaw, +while rotating around the rotated axes, not the original axes. + + +Car frame +------ +Device frame is aligned with the road-facing camera used by openpilot. However, when controlling the vehicle it is helpful to think in a reference frame aligned with the vehicle. These two reference frames can be different. + +The orientation of car frame is defined to be aligned with the car's direction of travel and the road plane when the vehicle is driving on a flat road and not turning. The origin of car frame is defined to be directly below device frame (in car frame), such that it is on the road plane. The position and orientation of this frame is not necessarily always aligned with the direction of travel or the road plane due to suspension movements and other effects. + + +Calibrated frame +------ +It is helpful for openpilot's driving model to take in images that look similar when mounted differently in different cars. To achieve this we "calibrate" the images by transforming it into calibrated frame. Calibrated frame is defined to be aligned with car frame in pitch and yaw, and aligned with device frame in roll. It also has the same origin as device frame. + + +Example +------ +To transform global Mesh3D positions and orientations (positions_ecef, quats_ecef) into the local frame described by the +first position and orientation from Mesh3D one would do: +``` +ecef_from_local = rot_from_quat(quats_ecef[0]) +local_from_ecef = ecef_from_local.T +positions_local = np.einsum('ij,kj->ki', local_from_ecef, postions_ecef - positions_ecef[0]) +rotations_global = rot_from_quat(quats_ecef) +rotations_local = np.einsum('ij,kjl->kil', local_from_ecef, rotations_global) +eulers_local = euler_from_rot(rotations_local) +``` diff --git a/common/transformations/SConscript b/common/transformations/SConscript new file mode 100644 index 0000000000..4ac73a165e --- /dev/null +++ b/common/transformations/SConscript @@ -0,0 +1,5 @@ +Import('env', 'envCython') + +transformations = env.Library('transformations', ['orientation.cc', 'coordinates.cc']) +transformations_python = envCython.Program('transformations.so', 'transformations.pyx') +Export('transformations', 'transformations_python') diff --git a/common/transformations/__init__.py b/common/transformations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/transformations/camera.py b/common/transformations/camera.py new file mode 100644 index 0000000000..2e68b5e37c --- /dev/null +++ b/common/transformations/camera.py @@ -0,0 +1,179 @@ +import itertools +import numpy as np +from dataclasses import dataclass + +import openpilot.common.transformations.orientation as orient + +## -- hardcoded hardware params -- +@dataclass(frozen=True) +class CameraConfig: + width: int + height: int + focal_length: float + + @property + def size(self): + return (self.width, self.height) + + @property + def intrinsics(self): + # aka 'K' aka camera_frame_from_view_frame + return np.array([ + [self.focal_length, 0.0, float(self.width)/2], + [0.0, self.focal_length, float(self.height)/2], + [0.0, 0.0, 1.0] + ]) + + @property + def intrinsics_inv(self): + # aka 'K_inv' aka view_frame_from_camera_frame + return np.linalg.inv(self.intrinsics) + +@dataclass(frozen=True) +class _NoneCameraConfig(CameraConfig): + width: int = 0 + height: int = 0 + focal_length: float = 0 + +@dataclass(frozen=True) +class DeviceCameraConfig: + fcam: CameraConfig + dcam: CameraConfig + ecam: CameraConfig + + def all_cams(self): + for cam in ['fcam', 'dcam', 'ecam']: + if not isinstance(getattr(self, cam), _NoneCameraConfig): + yield cam, getattr(self, cam) + +_ar_ox_fisheye = CameraConfig(1928, 1208, 567.0) # focal length probably wrong? magnification is not consistent across frame +_os_fisheye = CameraConfig(2688 // 2, 1520 // 2, 567.0 / 4 * 3) +_ar_ox_config = DeviceCameraConfig(CameraConfig(1928, 1208, 2648.0), _ar_ox_fisheye, _ar_ox_fisheye) +_os_config = DeviceCameraConfig(CameraConfig(2688 // 2, 1520 // 2, 1522.0 * 3 / 4), _os_fisheye, _os_fisheye) +_neo_config = DeviceCameraConfig(CameraConfig(1164, 874, 910.0), CameraConfig(816, 612, 650.0), _NoneCameraConfig()) + +DEVICE_CAMERAS = { + # A "device camera" is defined by a device type and sensor + + # sensor type was never set on eon/neo/two + ("neo", "unknown"): _neo_config, + # unknown here is AR0231, field was added with OX03C10 support + ("tici", "unknown"): _ar_ox_config, + + # before deviceState.deviceType was set, assume tici AR config + ("unknown", "ar0231"): _ar_ox_config, + ("unknown", "ox03c10"): _ar_ox_config, + + # simulator (emulates a tici) + ("pc", "unknown"): _ar_ox_config, +} +prods = itertools.product(('tici', 'tizi', 'mici'), (('ar0231', _ar_ox_config), ('ox03c10', _ar_ox_config), ('os04c10', _os_config))) +DEVICE_CAMERAS.update({(d, c[0]): c[1] for d, c in prods}) + +# device/mesh : x->forward, y-> right, z->down +# view : x->right, y->down, z->forward +device_frame_from_view_frame = np.array([ + [ 0., 0., 1.], + [ 1., 0., 0.], + [ 0., 1., 0.] +]) +view_frame_from_device_frame = device_frame_from_view_frame.T + + +# aka 'extrinsic_matrix' +# road : x->forward, y -> left, z->up +def get_view_frame_from_road_frame(roll, pitch, yaw, height): + device_from_road = orient.rot_from_euler([roll, pitch, yaw]).dot(np.diag([1, -1, -1])) + view_from_road = view_frame_from_device_frame.dot(device_from_road) + return np.hstack((view_from_road, [[0], [height], [0]])) + + + +# aka 'extrinsic_matrix' +def get_view_frame_from_calib_frame(roll, pitch, yaw, height): + device_from_calib= orient.rot_from_euler([roll, pitch, yaw]) + view_from_calib = view_frame_from_device_frame.dot(device_from_calib) + return np.hstack((view_from_calib, [[0], [height], [0]])) + + +def vp_from_ke(m): + """ + Computes the vanishing point from the product of the intrinsic and extrinsic + matrices C = KE. + + The vanishing point is defined as lim x->infinity C (x, 0, 0, 1).T + """ + return (m[0, 0]/m[2, 0], m[1, 0]/m[2, 0]) + + +def roll_from_ke(m): + # note: different from calibration.h/RollAnglefromKE: i think that one's just wrong + return np.arctan2(-(m[1, 0] - m[1, 1] * m[2, 0] / m[2, 1]), + -(m[0, 0] - m[0, 1] * m[2, 0] / m[2, 1])) + + +def normalize(img_pts, intrinsics): + # normalizes image coordinates + # accepts single pt or array of pts + intrinsics_inv = np.linalg.inv(intrinsics) + img_pts = np.array(img_pts) + input_shape = img_pts.shape + img_pts = np.atleast_2d(img_pts) + img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0], 1)))) + img_pts_normalized = img_pts.dot(intrinsics_inv.T) + img_pts_normalized[(img_pts < 0).any(axis=1)] = np.nan + return img_pts_normalized[:, :2].reshape(input_shape) + + +def denormalize(img_pts, intrinsics, width=np.inf, height=np.inf): + # denormalizes image coordinates + # accepts single pt or array of pts + img_pts = np.array(img_pts) + input_shape = img_pts.shape + img_pts = np.atleast_2d(img_pts) + img_pts = np.hstack((img_pts, np.ones((img_pts.shape[0], 1), dtype=img_pts.dtype))) + img_pts_denormalized = img_pts.dot(intrinsics.T) + if np.isfinite(width): + img_pts_denormalized[img_pts_denormalized[:, 0] > width] = np.nan + img_pts_denormalized[img_pts_denormalized[:, 0] < 0] = np.nan + if np.isfinite(height): + img_pts_denormalized[img_pts_denormalized[:, 1] > height] = np.nan + img_pts_denormalized[img_pts_denormalized[:, 1] < 0] = np.nan + return img_pts_denormalized[:, :2].reshape(input_shape) + + +def get_calib_from_vp(vp, intrinsics): + vp_norm = normalize(vp, intrinsics) + yaw_calib = np.arctan(vp_norm[0]) + pitch_calib = -np.arctan(vp_norm[1]*np.cos(yaw_calib)) + roll_calib = 0 + return roll_calib, pitch_calib, yaw_calib + + +def device_from_ecef(pos_ecef, orientation_ecef, pt_ecef): + # device from ecef frame + # device frame is x -> forward, y-> right, z -> down + # accepts single pt or array of pts + input_shape = pt_ecef.shape + pt_ecef = np.atleast_2d(pt_ecef) + ecef_from_device_rot = orient.rotations_from_quats(orientation_ecef) + device_from_ecef_rot = ecef_from_device_rot.T + pt_ecef_rel = pt_ecef - pos_ecef + pt_device = np.einsum('jk,ik->ij', device_from_ecef_rot, pt_ecef_rel) + return pt_device.reshape(input_shape) + + +def img_from_device(pt_device): + # img coordinates from pts in device frame + # first transforms to view frame, then to img coords + # accepts single pt or array of pts + input_shape = pt_device.shape + pt_device = np.atleast_2d(pt_device) + pt_view = np.einsum('jk,ik->ij', view_frame_from_device_frame, pt_device) + + # This function should never return negative depths + pt_view[pt_view[:, 2] < 0] = np.nan + + pt_img = pt_view/pt_view[:, 2:3] + return pt_img.reshape(input_shape)[:, :2] + diff --git a/common/transformations/coordinates.cc b/common/transformations/coordinates.cc new file mode 100644 index 0000000000..f3f10e547f --- /dev/null +++ b/common/transformations/coordinates.cc @@ -0,0 +1,100 @@ +#define _USE_MATH_DEFINES + +#include "common/transformations/coordinates.hpp" + +#include +#include +#include + +double a = 6378137; // lgtm [cpp/short-global-name] +double b = 6356752.3142; // lgtm [cpp/short-global-name] +double esq = 6.69437999014 * 0.001; // lgtm [cpp/short-global-name] +double e1sq = 6.73949674228 * 0.001; + + +static Geodetic to_degrees(Geodetic geodetic){ + geodetic.lat = RAD2DEG(geodetic.lat); + geodetic.lon = RAD2DEG(geodetic.lon); + return geodetic; +} + +static Geodetic to_radians(Geodetic geodetic){ + geodetic.lat = DEG2RAD(geodetic.lat); + geodetic.lon = DEG2RAD(geodetic.lon); + return geodetic; +} + + +ECEF geodetic2ecef(const Geodetic &geodetic) { + auto g = to_radians(geodetic); + double xi = sqrt(1.0 - esq * pow(sin(g.lat), 2)); + double x = (a / xi + g.alt) * cos(g.lat) * cos(g.lon); + double y = (a / xi + g.alt) * cos(g.lat) * sin(g.lon); + double z = (a / xi * (1.0 - esq) + g.alt) * sin(g.lat); + return {x, y, z}; +} + +Geodetic ecef2geodetic(const ECEF &e) { + // Convert from ECEF to geodetic using Ferrari's methods + // https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#Ferrari.27s_solution + double x = e.x; + double y = e.y; + double z = e.z; + + double r = sqrt(x * x + y * y); + double Esq = a * a - b * b; + double F = 54 * b * b * z * z; + double G = r * r + (1 - esq) * z * z - esq * Esq; + double C = (esq * esq * F * r * r) / (pow(G, 3)); + double S = cbrt(1 + C + sqrt(C * C + 2 * C)); + double P = F / (3 * pow((S + 1 / S + 1), 2) * G * G); + double Q = sqrt(1 + 2 * esq * esq * P); + double r_0 = -(P * esq * r) / (1 + Q) + sqrt(0.5 * a * a*(1 + 1.0 / Q) - P * (1 - esq) * z * z / (Q * (1 + Q)) - 0.5 * P * r * r); + double U = sqrt(pow((r - esq * r_0), 2) + z * z); + double V = sqrt(pow((r - esq * r_0), 2) + (1 - esq) * z * z); + double Z_0 = b * b * z / (a * V); + double h = U * (1 - b * b / (a * V)); + + double lat = atan((z + e1sq * Z_0) / r); + double lon = atan2(y, x); + + return to_degrees({lat, lon, h}); +} + +LocalCoord::LocalCoord(const Geodetic &geodetic, const ECEF &e) { + init_ecef << e.x, e.y, e.z; + + auto g = to_radians(geodetic); + + ned2ecef_matrix << + -sin(g.lat)*cos(g.lon), -sin(g.lon), -cos(g.lat)*cos(g.lon), + -sin(g.lat)*sin(g.lon), cos(g.lon), -cos(g.lat)*sin(g.lon), + cos(g.lat), 0, -sin(g.lat); + ecef2ned_matrix = ned2ecef_matrix.transpose(); +} + +NED LocalCoord::ecef2ned(const ECEF &e) { + Eigen::Vector3d ecef; + ecef << e.x, e.y, e.z; + + Eigen::Vector3d ned = (ecef2ned_matrix * (ecef - init_ecef)); + return {ned[0], ned[1], ned[2]}; +} + +ECEF LocalCoord::ned2ecef(const NED &n) { + Eigen::Vector3d ned; + ned << n.n, n.e, n.d; + + Eigen::Vector3d ecef = (ned2ecef_matrix * ned) + init_ecef; + return {ecef[0], ecef[1], ecef[2]}; +} + +NED LocalCoord::geodetic2ned(const Geodetic &g) { + ECEF e = ::geodetic2ecef(g); + return ecef2ned(e); +} + +Geodetic LocalCoord::ned2geodetic(const NED &n) { + ECEF e = ned2ecef(n); + return ::ecef2geodetic(e); +} diff --git a/common/transformations/coordinates.hpp b/common/transformations/coordinates.hpp new file mode 100644 index 0000000000..dc8ff7a4b6 --- /dev/null +++ b/common/transformations/coordinates.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#define DEG2RAD(x) ((x) * M_PI / 180.0) +#define RAD2DEG(x) ((x) * 180.0 / M_PI) + +struct ECEF { + double x, y, z; + Eigen::Vector3d to_vector() const { + return Eigen::Vector3d(x, y, z); + } +}; + +struct NED { + double n, e, d; + Eigen::Vector3d to_vector() const { + return Eigen::Vector3d(n, e, d); + } +}; + +struct Geodetic { + double lat, lon, alt; + bool radians=false; +}; + +ECEF geodetic2ecef(const Geodetic &g); +Geodetic ecef2geodetic(const ECEF &e); + +class LocalCoord { +public: + Eigen::Matrix3d ned2ecef_matrix; + Eigen::Matrix3d ecef2ned_matrix; + Eigen::Vector3d init_ecef; + LocalCoord(const Geodetic &g, const ECEF &e); + LocalCoord(const Geodetic &g) : LocalCoord(g, ::geodetic2ecef(g)) {} + LocalCoord(const ECEF &e) : LocalCoord(::ecef2geodetic(e), e) {} + + NED ecef2ned(const ECEF &e); + ECEF ned2ecef(const NED &n); + NED geodetic2ned(const Geodetic &g); + Geodetic ned2geodetic(const NED &n); +}; diff --git a/common/transformations/coordinates.py b/common/transformations/coordinates.py new file mode 100644 index 0000000000..696e7de2e5 --- /dev/null +++ b/common/transformations/coordinates.py @@ -0,0 +1,18 @@ +from openpilot.common.transformations.orientation import numpy_wrap +from openpilot.common.transformations.transformations import (ecef2geodetic_single, + geodetic2ecef_single) +from openpilot.common.transformations.transformations import LocalCoord as LocalCoord_single + + +class LocalCoord(LocalCoord_single): + ecef2ned = numpy_wrap(LocalCoord_single.ecef2ned_single, (3,), (3,)) + ned2ecef = numpy_wrap(LocalCoord_single.ned2ecef_single, (3,), (3,)) + geodetic2ned = numpy_wrap(LocalCoord_single.geodetic2ned_single, (3,), (3,)) + ned2geodetic = numpy_wrap(LocalCoord_single.ned2geodetic_single, (3,), (3,)) + + +geodetic2ecef = numpy_wrap(geodetic2ecef_single, (3,), (3,)) +ecef2geodetic = numpy_wrap(ecef2geodetic_single, (3,), (3,)) + +geodetic_from_ecef = ecef2geodetic +ecef_from_geodetic = geodetic2ecef diff --git a/common/transformations/model.py b/common/transformations/model.py new file mode 100644 index 0000000000..ea1dff30e8 --- /dev/null +++ b/common/transformations/model.py @@ -0,0 +1,70 @@ +import numpy as np + +from openpilot.common.transformations.orientation import rot_from_euler +from openpilot.common.transformations.camera import get_view_frame_from_calib_frame, view_frame_from_device_frame, _ar_ox_fisheye + +# segnet +SEGNET_SIZE = (512, 384) + +# MED model +MEDMODEL_INPUT_SIZE = (512, 256) +MEDMODEL_YUV_SIZE = (MEDMODEL_INPUT_SIZE[0], MEDMODEL_INPUT_SIZE[1] * 3 // 2) +MEDMODEL_CY = 47.6 + +medmodel_fl = 910.0 +medmodel_intrinsics = np.array([ + [medmodel_fl, 0.0, 0.5 * MEDMODEL_INPUT_SIZE[0]], + [0.0, medmodel_fl, MEDMODEL_CY], + [0.0, 0.0, 1.0]]) + + +# BIG model +BIGMODEL_INPUT_SIZE = (1024, 512) +BIGMODEL_YUV_SIZE = (BIGMODEL_INPUT_SIZE[0], BIGMODEL_INPUT_SIZE[1] * 3 // 2) + +bigmodel_fl = 910.0 +bigmodel_intrinsics = np.array([ + [bigmodel_fl, 0.0, 0.5 * BIGMODEL_INPUT_SIZE[0]], + [0.0, bigmodel_fl, 256 + MEDMODEL_CY], + [0.0, 0.0, 1.0]]) + + +# SBIG model (big model with the size of small model) +SBIGMODEL_INPUT_SIZE = (512, 256) +SBIGMODEL_YUV_SIZE = (SBIGMODEL_INPUT_SIZE[0], SBIGMODEL_INPUT_SIZE[1] * 3 // 2) + +sbigmodel_fl = 455.0 +sbigmodel_intrinsics = np.array([ + [sbigmodel_fl, 0.0, 0.5 * SBIGMODEL_INPUT_SIZE[0]], + [0.0, sbigmodel_fl, 0.5 * (256 + MEDMODEL_CY)], + [0.0, 0.0, 1.0]]) + +DM_INPUT_SIZE = (1440, 960) +dmonitoringmodel_fl = _ar_ox_fisheye.focal_length +dmonitoringmodel_intrinsics = np.array([ + [dmonitoringmodel_fl, 0.0, DM_INPUT_SIZE[0]/2], + [0.0, dmonitoringmodel_fl, DM_INPUT_SIZE[1]/2 - (_ar_ox_fisheye.height - DM_INPUT_SIZE[1])/2], + [0.0, 0.0, 1.0]]) + +bigmodel_frame_from_calib_frame = np.dot(bigmodel_intrinsics, + get_view_frame_from_calib_frame(0, 0, 0, 0)) + + +sbigmodel_frame_from_calib_frame = np.dot(sbigmodel_intrinsics, + get_view_frame_from_calib_frame(0, 0, 0, 0)) + +medmodel_frame_from_calib_frame = np.dot(medmodel_intrinsics, + get_view_frame_from_calib_frame(0, 0, 0, 0)) + +medmodel_frame_from_bigmodel_frame = np.dot(medmodel_intrinsics, np.linalg.inv(bigmodel_intrinsics)) + +calib_from_medmodel = np.linalg.inv(medmodel_frame_from_calib_frame[:, :3]) +calib_from_sbigmodel = np.linalg.inv(sbigmodel_frame_from_calib_frame[:, :3]) + +# This function is verified to give similar results to xx.uncommon.utils.transform_img +def get_warp_matrix(device_from_calib_euler: np.ndarray, intrinsics: np.ndarray, bigmodel_frame: bool = False) -> np.ndarray: + calib_from_model = calib_from_sbigmodel if bigmodel_frame else calib_from_medmodel + device_from_calib = rot_from_euler(device_from_calib_euler) + camera_from_calib = intrinsics @ view_frame_from_device_frame @ device_from_calib + warp_matrix: np.ndarray = camera_from_calib @ calib_from_model + return warp_matrix diff --git a/common/transformations/orientation.cc b/common/transformations/orientation.cc new file mode 100644 index 0000000000..fb5e47a86a --- /dev/null +++ b/common/transformations/orientation.cc @@ -0,0 +1,144 @@ +#define _USE_MATH_DEFINES + +#include +#include +#include + +#include "common/transformations/orientation.hpp" +#include "common/transformations/coordinates.hpp" + +Eigen::Quaterniond ensure_unique(const Eigen::Quaterniond &quat) { + if (quat.w() > 0){ + return quat; + } else { + return Eigen::Quaterniond(-quat.w(), -quat.x(), -quat.y(), -quat.z()); + } +} + +Eigen::Quaterniond euler2quat(const Eigen::Vector3d &euler) { + Eigen::Quaterniond q; + + q = Eigen::AngleAxisd(euler(2), Eigen::Vector3d::UnitZ()) + * Eigen::AngleAxisd(euler(1), Eigen::Vector3d::UnitY()) + * Eigen::AngleAxisd(euler(0), Eigen::Vector3d::UnitX()); + return ensure_unique(q); +} + + +Eigen::Vector3d quat2euler(const Eigen::Quaterniond &quat) { + // TODO: switch to eigen implementation if the range of the Euler angles doesn't matter anymore + // Eigen::Vector3d euler = quat.toRotationMatrix().eulerAngles(2, 1, 0); + // return {euler(2), euler(1), euler(0)}; + double gamma = atan2(2 * (quat.w() * quat.x() + quat.y() * quat.z()), 1 - 2 * (quat.x()*quat.x() + quat.y()*quat.y())); + double asin_arg_clipped = std::clamp(2 * (quat.w() * quat.y() - quat.z() * quat.x()), -1.0, 1.0); + double theta = asin(asin_arg_clipped); + double psi = atan2(2 * (quat.w() * quat.z() + quat.x() * quat.y()), 1 - 2 * (quat.y()*quat.y() + quat.z()*quat.z())); + return {gamma, theta, psi}; +} + +Eigen::Matrix3d quat2rot(const Eigen::Quaterniond &quat) { + return quat.toRotationMatrix(); +} + +Eigen::Quaterniond rot2quat(const Eigen::Matrix3d &rot) { + return ensure_unique(Eigen::Quaterniond(rot)); +} + +Eigen::Matrix3d euler2rot(const Eigen::Vector3d &euler) { + return quat2rot(euler2quat(euler)); +} + +Eigen::Vector3d rot2euler(const Eigen::Matrix3d &rot) { + return quat2euler(rot2quat(rot)); +} + +Eigen::Matrix3d rot_matrix(double roll, double pitch, double yaw) { + return euler2rot({roll, pitch, yaw}); +} + +Eigen::Matrix3d rot(const Eigen::Vector3d &axis, double angle) { + Eigen::Quaterniond q; + q = Eigen::AngleAxisd(angle, axis); + return q.toRotationMatrix(); +} + + +Eigen::Vector3d ecef_euler_from_ned(const ECEF &ecef_init, const Eigen::Vector3d &ned_pose) { + /* + Using Rotations to Build Aerospace Coordinate Systems + Don Koks + https://apps.dtic.mil/dtic/tr/fulltext/u2/a484864.pdf + */ + LocalCoord converter = LocalCoord(ecef_init); + Eigen::Vector3d zero = ecef_init.to_vector(); + + Eigen::Vector3d x0 = converter.ned2ecef({1, 0, 0}).to_vector() - zero; + Eigen::Vector3d y0 = converter.ned2ecef({0, 1, 0}).to_vector() - zero; + Eigen::Vector3d z0 = converter.ned2ecef({0, 0, 1}).to_vector() - zero; + + Eigen::Vector3d x1 = rot(z0, ned_pose(2)) * x0; + Eigen::Vector3d y1 = rot(z0, ned_pose(2)) * y0; + Eigen::Vector3d z1 = rot(z0, ned_pose(2)) * z0; + + Eigen::Vector3d x2 = rot(y1, ned_pose(1)) * x1; + Eigen::Vector3d y2 = rot(y1, ned_pose(1)) * y1; + Eigen::Vector3d z2 = rot(y1, ned_pose(1)) * z1; + + Eigen::Vector3d x3 = rot(x2, ned_pose(0)) * x2; + Eigen::Vector3d y3 = rot(x2, ned_pose(0)) * y2; + + + x0 = Eigen::Vector3d(1, 0, 0); + y0 = Eigen::Vector3d(0, 1, 0); + z0 = Eigen::Vector3d(0, 0, 1); + + double psi = atan2(x3.dot(y0), x3.dot(x0)); + double theta = atan2(-x3.dot(z0), sqrt(pow(x3.dot(x0), 2) + pow(x3.dot(y0), 2))); + + y2 = rot(z0, psi) * y0; + z2 = rot(y2, theta) * z0; + + double phi = atan2(y3.dot(z2), y3.dot(y2)); + + return {phi, theta, psi}; +} + +Eigen::Vector3d ned_euler_from_ecef(const ECEF &ecef_init, const Eigen::Vector3d &ecef_pose) { + /* + Using Rotations to Build Aerospace Coordinate Systems + Don Koks + https://apps.dtic.mil/dtic/tr/fulltext/u2/a484864.pdf + */ + LocalCoord converter = LocalCoord(ecef_init); + + Eigen::Vector3d x0 = Eigen::Vector3d(1, 0, 0); + Eigen::Vector3d y0 = Eigen::Vector3d(0, 1, 0); + Eigen::Vector3d z0 = Eigen::Vector3d(0, 0, 1); + + Eigen::Vector3d x1 = rot(z0, ecef_pose(2)) * x0; + Eigen::Vector3d y1 = rot(z0, ecef_pose(2)) * y0; + Eigen::Vector3d z1 = rot(z0, ecef_pose(2)) * z0; + + Eigen::Vector3d x2 = rot(y1, ecef_pose(1)) * x1; + Eigen::Vector3d y2 = rot(y1, ecef_pose(1)) * y1; + Eigen::Vector3d z2 = rot(y1, ecef_pose(1)) * z1; + + Eigen::Vector3d x3 = rot(x2, ecef_pose(0)) * x2; + Eigen::Vector3d y3 = rot(x2, ecef_pose(0)) * y2; + + Eigen::Vector3d zero = ecef_init.to_vector(); + x0 = converter.ned2ecef({1, 0, 0}).to_vector() - zero; + y0 = converter.ned2ecef({0, 1, 0}).to_vector() - zero; + z0 = converter.ned2ecef({0, 0, 1}).to_vector() - zero; + + double psi = atan2(x3.dot(y0), x3.dot(x0)); + double theta = atan2(-x3.dot(z0), sqrt(pow(x3.dot(x0), 2) + pow(x3.dot(y0), 2))); + + y2 = rot(z0, psi) * y0; + z2 = rot(y2, theta) * z0; + + double phi = atan2(y3.dot(z2), y3.dot(y2)); + + return {phi, theta, psi}; +} + diff --git a/common/transformations/orientation.hpp b/common/transformations/orientation.hpp new file mode 100644 index 0000000000..0874a0a814 --- /dev/null +++ b/common/transformations/orientation.hpp @@ -0,0 +1,17 @@ +#pragma once +#include +#include "common/transformations/coordinates.hpp" + + +Eigen::Quaterniond ensure_unique(const Eigen::Quaterniond &quat); + +Eigen::Quaterniond euler2quat(const Eigen::Vector3d &euler); +Eigen::Vector3d quat2euler(const Eigen::Quaterniond &quat); +Eigen::Matrix3d quat2rot(const Eigen::Quaterniond &quat); +Eigen::Quaterniond rot2quat(const Eigen::Matrix3d &rot); +Eigen::Matrix3d euler2rot(const Eigen::Vector3d &euler); +Eigen::Vector3d rot2euler(const Eigen::Matrix3d &rot); +Eigen::Matrix3d rot_matrix(double roll, double pitch, double yaw); +Eigen::Matrix3d rot(const Eigen::Vector3d &axis, double angle); +Eigen::Vector3d ecef_euler_from_ned(const ECEF &ecef_init, const Eigen::Vector3d &ned_pose); +Eigen::Vector3d ned_euler_from_ecef(const ECEF &ecef_init, const Eigen::Vector3d &ecef_pose); diff --git a/common/transformations/orientation.py b/common/transformations/orientation.py new file mode 100644 index 0000000000..86e6a6c347 --- /dev/null +++ b/common/transformations/orientation.py @@ -0,0 +1,52 @@ +import numpy as np +from collections.abc import Callable + +from openpilot.common.transformations.transformations import (ecef_euler_from_ned_single, + euler2quat_single, + euler2rot_single, + ned_euler_from_ecef_single, + quat2euler_single, + quat2rot_single, + rot2euler_single, + rot2quat_single) + + +def numpy_wrap(function, input_shape, output_shape) -> Callable[..., np.ndarray]: + """Wrap a function to take either an input or list of inputs and return the correct shape""" + def f(*inps): + *args, inp = inps + inp = np.array(inp) + shape = inp.shape + + if len(shape) == len(input_shape): + out_shape = output_shape + else: + out_shape = (shape[0],) + output_shape + + # Add empty dimension if inputs is not a list + if len(shape) == len(input_shape): + inp.shape = (1, ) + inp.shape + + result = np.asarray([function(*args, i) for i in inp]) + result.shape = out_shape + return result + return f + + +euler2quat = numpy_wrap(euler2quat_single, (3,), (4,)) +quat2euler = numpy_wrap(quat2euler_single, (4,), (3,)) +quat2rot = numpy_wrap(quat2rot_single, (4,), (3, 3)) +rot2quat = numpy_wrap(rot2quat_single, (3, 3), (4,)) +euler2rot = numpy_wrap(euler2rot_single, (3,), (3, 3)) +rot2euler = numpy_wrap(rot2euler_single, (3, 3), (3,)) +ecef_euler_from_ned = numpy_wrap(ecef_euler_from_ned_single, (3,), (3,)) +ned_euler_from_ecef = numpy_wrap(ned_euler_from_ecef_single, (3,), (3,)) + +quats_from_rotations = rot2quat +quat_from_rot = rot2quat +rotations_from_quats = quat2rot +rot_from_quat = quat2rot +euler_from_rot = rot2euler +euler_from_quat = quat2euler +rot_from_euler = euler2rot +quat_from_euler = euler2quat diff --git a/common/transformations/tests/__init__.py b/common/transformations/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/transformations/tests/test_coordinates.py b/common/transformations/tests/test_coordinates.py new file mode 100644 index 0000000000..11a6bf70ee --- /dev/null +++ b/common/transformations/tests/test_coordinates.py @@ -0,0 +1,104 @@ +import numpy as np + +import openpilot.common.transformations.coordinates as coord + +geodetic_positions = np.array([[37.7610403, -122.4778699, 115], + [27.4840915, -68.5867592, 2380], + [32.4916858, -113.652821, -6], + [15.1392514, 103.6976037, 24], + [24.2302229, 44.2835412, 1650]]) + +ecef_positions = np.array([[-2711076.55270557, -4259167.14692758, 3884579.87669935], + [ 2068042.69652729, -5273435.40316622, 2927004.89190746], + [-2160412.60461669, -4932588.89873832, 3406542.29652851], + [-1458247.92550567, 5983060.87496612, 1654984.6099885 ], + [ 4167239.10867871, 4064301.90363223, 2602234.6065749 ]]) + +ecef_positions_offset = np.array([[-2711004.46961115, -4259099.33540613, 3884605.16002147], + [ 2068074.30639499, -5273413.78835412, 2927012.48741131], + [-2160344.53748176, -4932586.20092211, 3406636.2962545 ], + [-1458211.98517094, 5983151.11161276, 1655077.02698447], + [ 4167271.20055269, 4064398.22619263, 2602238.95265847]]) + + +ned_offsets = np.array([[78.722153649976391, 24.396208657446344, 60.343017506838436], + [10.699003365155221, 37.319278617604269, 4.1084100025050407], + [95.282646251726959, 61.266689955574428, -25.376506058505054], + [68.535769283630003, -56.285970011848889, -100.54840137956515], + [-33.066609321880179, 46.549821994306861, -84.062540548335591]]) + +ecef_init_batch = np.array([2068042.69652729, -5273435.40316622, 2927004.89190746]) +ecef_positions_offset_batch = np.array([[ 2068089.41454771, -5273434.46829148, 2927074.04783672], + [ 2068103.31628647, -5273393.92275431, 2927102.08725987], + [ 2068108.49939636, -5273359.27047121, 2927045.07091581], + [ 2068075.12395611, -5273381.69432566, 2927041.08207992], + [ 2068060.72033399, -5273430.6061505, 2927094.54928305]]) + +ned_offsets_batch = np.array([[ 53.88103168, 43.83445935, -46.27488057], + [ 93.83378995, 71.57943024, -30.23113187], + [ 57.26725796, 89.05602684, 23.02265814], + [ 49.71775195, 49.79767572, 17.15351015], + [ 78.56272609, 18.53100158, -43.25290759]]) + + +class TestNED: + def test_small_distances(self): + start_geodetic = np.array([33.8042184, -117.888593, 0.0]) + local_coord = coord.LocalCoord.from_geodetic(start_geodetic) + + start_ned = local_coord.geodetic2ned(start_geodetic) + np.testing.assert_array_equal(start_ned, np.zeros(3,)) + + west_geodetic = start_geodetic + [0, -0.0005, 0] + west_ned = local_coord.geodetic2ned(west_geodetic) + assert np.abs(west_ned[0]) < 1e-3 + assert west_ned[1] < 0 + + southwest_geodetic = start_geodetic + [-0.0005, -0.002, 0] + southwest_ned = local_coord.geodetic2ned(southwest_geodetic) + assert southwest_ned[0] < 0 + assert southwest_ned[1] < 0 + + def test_ecef_geodetic(self): + # testing single + np.testing.assert_allclose(ecef_positions[0], coord.geodetic2ecef(geodetic_positions[0]), rtol=1e-9) + np.testing.assert_allclose(geodetic_positions[0, :2], coord.ecef2geodetic(ecef_positions[0])[:2], rtol=1e-9) + np.testing.assert_allclose(geodetic_positions[0, 2], coord.ecef2geodetic(ecef_positions[0])[2], rtol=1e-9, atol=1e-4) + + np.testing.assert_allclose(geodetic_positions[:, :2], coord.ecef2geodetic(ecef_positions)[:, :2], rtol=1e-9) + np.testing.assert_allclose(geodetic_positions[:, 2], coord.ecef2geodetic(ecef_positions)[:, 2], rtol=1e-9, atol=1e-4) + np.testing.assert_allclose(ecef_positions, coord.geodetic2ecef(geodetic_positions), rtol=1e-9) + + + def test_ned(self): + for ecef_pos in ecef_positions: + converter = coord.LocalCoord.from_ecef(ecef_pos) + ecef_pos_moved = ecef_pos + [25, -25, 25] + ecef_pos_moved_double_converted = converter.ned2ecef(converter.ecef2ned(ecef_pos_moved)) + np.testing.assert_allclose(ecef_pos_moved, ecef_pos_moved_double_converted, rtol=1e-9) + + for geo_pos in geodetic_positions: + converter = coord.LocalCoord.from_geodetic(geo_pos) + geo_pos_moved = geo_pos + np.array([0, 0, 10]) + geo_pos_double_converted_moved = converter.ned2geodetic(converter.geodetic2ned(geo_pos) + np.array([0, 0, -10])) + np.testing.assert_allclose(geo_pos_moved[:2], geo_pos_double_converted_moved[:2], rtol=1e-9, atol=1e-6) + np.testing.assert_allclose(geo_pos_moved[2], geo_pos_double_converted_moved[2], rtol=1e-9, atol=1e-4) + + def test_ned_saved_results(self): + for i, ecef_pos in enumerate(ecef_positions): + converter = coord.LocalCoord.from_ecef(ecef_pos) + np.testing.assert_allclose(converter.ned2ecef(ned_offsets[i]), + ecef_positions_offset[i], + rtol=1e-9, atol=1e-4) + np.testing.assert_allclose(converter.ecef2ned(ecef_positions_offset[i]), + ned_offsets[i], + rtol=1e-9, atol=1e-4) + + def test_ned_batch(self): + converter = coord.LocalCoord.from_ecef(ecef_init_batch) + np.testing.assert_allclose(converter.ecef2ned(ecef_positions_offset_batch), + ned_offsets_batch, + rtol=1e-9, atol=1e-7) + np.testing.assert_allclose(converter.ned2ecef(ned_offsets_batch), + ecef_positions_offset_batch, + rtol=1e-9, atol=1e-7) diff --git a/common/transformations/tests/test_orientation.py b/common/transformations/tests/test_orientation.py new file mode 100644 index 0000000000..55fbc6581e --- /dev/null +++ b/common/transformations/tests/test_orientation.py @@ -0,0 +1,61 @@ +import numpy as np + +from openpilot.common.transformations.orientation import euler2quat, quat2euler, euler2rot, rot2euler, \ + rot2quat, quat2rot, \ + ned_euler_from_ecef + +eulers = np.array([[ 1.46520501, 2.78688383, 2.92780854], + [ 4.86909526, 3.60618161, 4.30648981], + [ 3.72175965, 2.68763705, 5.43895988], + [ 5.92306687, 5.69573614, 0.81100357], + [ 0.67838374, 5.02402037, 2.47106426]]) + +quats = np.array([[ 0.66855182, -0.71500939, 0.19539353, 0.06017818], + [ 0.43163717, 0.70013301, 0.28209145, 0.49389021], + [ 0.44121991, -0.08252646, 0.34257534, 0.82532207], + [ 0.88578382, -0.04515356, -0.32936046, 0.32383617], + [ 0.06578165, 0.61282835, 0.07126891, 0.78424163]]) + +ecef_positions = np.array([[-2711076.55270557, -4259167.14692758, 3884579.87669935], + [ 2068042.69652729, -5273435.40316622, 2927004.89190746], + [-2160412.60461669, -4932588.89873832, 3406542.29652851], + [-1458247.92550567, 5983060.87496612, 1654984.6099885 ], + [ 4167239.10867871, 4064301.90363223, 2602234.6065749 ]]) + +ned_eulers = np.array([[ 0.46806039, -0.4881889 , 1.65697808], + [-2.14525969, -0.36533066, 0.73813479], + [-1.39523364, -0.58540761, -1.77376356], + [-1.84220435, 0.61828016, -1.03310421], + [ 2.50450101, 0.36304151, 0.33136365]]) + + +class TestOrientation: + def test_quat_euler(self): + for i, eul in enumerate(eulers): + np.testing.assert_allclose(quats[i], euler2quat(eul), rtol=1e-7) + np.testing.assert_allclose(quats[i], euler2quat(quat2euler(quats[i])), rtol=1e-6) + for i, eul in enumerate(eulers): + np.testing.assert_allclose(quats[i], euler2quat(list(eul)), rtol=1e-7) + np.testing.assert_allclose(quats[i], euler2quat(quat2euler(list(quats[i]))), rtol=1e-6) + np.testing.assert_allclose(quats, euler2quat(eulers), rtol=1e-7) + np.testing.assert_allclose(quats, euler2quat(quat2euler(quats)), rtol=1e-6) + + def test_rot_euler(self): + for eul in eulers: + np.testing.assert_allclose(euler2quat(eul), euler2quat(rot2euler(euler2rot(eul))), rtol=1e-7) + for eul in eulers: + np.testing.assert_allclose(euler2quat(eul), euler2quat(rot2euler(euler2rot(list(eul)))), rtol=1e-7) + np.testing.assert_allclose(euler2quat(eulers), euler2quat(rot2euler(euler2rot(eulers))), rtol=1e-7) + + def test_rot_quat(self): + for quat in quats: + np.testing.assert_allclose(quat, rot2quat(quat2rot(quat)), rtol=1e-7) + for quat in quats: + np.testing.assert_allclose(quat, rot2quat(quat2rot(list(quat))), rtol=1e-7) + np.testing.assert_allclose(quats, rot2quat(quat2rot(quats)), rtol=1e-7) + + def test_euler_ned(self): + for i in range(len(eulers)): + np.testing.assert_allclose(ned_eulers[i], ned_euler_from_ecef(ecef_positions[i], eulers[i]), rtol=1e-7) + #np.testing.assert_allclose(eulers[i], ecef_euler_from_ned(ecef_positions[i], ned_eulers[i]), rtol=1e-7) + # np.testing.assert_allclose(ned_eulers, ned_euler_from_ecef(ecef_positions, eulers), rtol=1e-7) diff --git a/common/transformations/transformations.pxd b/common/transformations/transformations.pxd new file mode 100644 index 0000000000..fe32e18dea --- /dev/null +++ b/common/transformations/transformations.pxd @@ -0,0 +1,72 @@ +# cython: language_level=3 +from libcpp cimport bool + +cdef extern from "orientation.cc": + pass + +cdef extern from "orientation.hpp": + cdef cppclass Quaternion "Eigen::Quaterniond": + Quaternion() + Quaternion(double, double, double, double) + double w() + double x() + double y() + double z() + + cdef cppclass Vector3 "Eigen::Vector3d": + Vector3() + Vector3(double, double, double) + double operator()(int) + + cdef cppclass Matrix3 "Eigen::Matrix3d": + Matrix3() + Matrix3(double*) + + double operator()(int, int) + + Quaternion euler2quat(const Vector3 &) + Vector3 quat2euler(const Quaternion &) + Matrix3 quat2rot(const Quaternion &) + Quaternion rot2quat(const Matrix3 &) + Vector3 rot2euler(const Matrix3 &) + Matrix3 euler2rot(const Vector3 &) + Matrix3 rot_matrix(double, double, double) + Vector3 ecef_euler_from_ned(const ECEF &, const Vector3 &) + Vector3 ned_euler_from_ecef(const ECEF &, const Vector3 &) + + +cdef extern from "coordinates.cc": + cdef struct ECEF: + double x + double y + double z + + cdef struct NED: + double n + double e + double d + + cdef struct Geodetic: + double lat + double lon + double alt + bool radians + + ECEF geodetic2ecef(const Geodetic &) + Geodetic ecef2geodetic(const ECEF &) + + cdef cppclass LocalCoord_c "LocalCoord": + Matrix3 ned2ecef_matrix + Matrix3 ecef2ned_matrix + + LocalCoord_c(const Geodetic &, const ECEF &) + LocalCoord_c(const Geodetic &) + LocalCoord_c(const ECEF &) + + NED ecef2ned(const ECEF &) + ECEF ned2ecef(const NED &) + NED geodetic2ned(const Geodetic &) + Geodetic ned2geodetic(const NED &) + +cdef extern from "coordinates.hpp": + pass diff --git a/common/transformations/transformations.pyx b/common/transformations/transformations.pyx new file mode 100644 index 0000000000..ae045c369d --- /dev/null +++ b/common/transformations/transformations.pyx @@ -0,0 +1,173 @@ +# distutils: language = c++ +# cython: language_level = 3 +from openpilot.common.transformations.transformations cimport Matrix3, Vector3, Quaternion +from openpilot.common.transformations.transformations cimport ECEF, NED, Geodetic + +from openpilot.common.transformations.transformations cimport euler2quat as euler2quat_c +from openpilot.common.transformations.transformations cimport quat2euler as quat2euler_c +from openpilot.common.transformations.transformations cimport quat2rot as quat2rot_c +from openpilot.common.transformations.transformations cimport rot2quat as rot2quat_c +from openpilot.common.transformations.transformations cimport euler2rot as euler2rot_c +from openpilot.common.transformations.transformations cimport rot2euler as rot2euler_c +from openpilot.common.transformations.transformations cimport rot_matrix as rot_matrix_c +from openpilot.common.transformations.transformations cimport ecef_euler_from_ned as ecef_euler_from_ned_c +from openpilot.common.transformations.transformations cimport ned_euler_from_ecef as ned_euler_from_ecef_c +from openpilot.common.transformations.transformations cimport geodetic2ecef as geodetic2ecef_c +from openpilot.common.transformations.transformations cimport ecef2geodetic as ecef2geodetic_c +from openpilot.common.transformations.transformations cimport LocalCoord_c + + +import numpy as np +cimport numpy as np + +cdef np.ndarray[double, ndim=2] matrix2numpy(Matrix3 m): + return np.array([ + [m(0, 0), m(0, 1), m(0, 2)], + [m(1, 0), m(1, 1), m(1, 2)], + [m(2, 0), m(2, 1), m(2, 2)], + ]) + +cdef Matrix3 numpy2matrix(np.ndarray[double, ndim=2, mode="fortran"] m): + assert m.shape[0] == 3 + assert m.shape[1] == 3 + return Matrix3(m.data) + +cdef ECEF list2ecef(ecef): + cdef ECEF e + e.x = ecef[0] + e.y = ecef[1] + e.z = ecef[2] + return e + +cdef NED list2ned(ned): + cdef NED n + n.n = ned[0] + n.e = ned[1] + n.d = ned[2] + return n + +cdef Geodetic list2geodetic(geodetic): + cdef Geodetic g + g.lat = geodetic[0] + g.lon = geodetic[1] + g.alt = geodetic[2] + return g + +def euler2quat_single(euler): + cdef Vector3 e = Vector3(euler[0], euler[1], euler[2]) + cdef Quaternion q = euler2quat_c(e) + return [q.w(), q.x(), q.y(), q.z()] + +def quat2euler_single(quat): + cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3]) + cdef Vector3 e = quat2euler_c(q) + return [e(0), e(1), e(2)] + +def quat2rot_single(quat): + cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3]) + cdef Matrix3 r = quat2rot_c(q) + return matrix2numpy(r) + +def rot2quat_single(rot): + cdef Matrix3 r = numpy2matrix(np.asfortranarray(rot, dtype=np.double)) + cdef Quaternion q = rot2quat_c(r) + return [q.w(), q.x(), q.y(), q.z()] + +def euler2rot_single(euler): + cdef Vector3 e = Vector3(euler[0], euler[1], euler[2]) + cdef Matrix3 r = euler2rot_c(e) + return matrix2numpy(r) + +def rot2euler_single(rot): + cdef Matrix3 r = numpy2matrix(np.asfortranarray(rot, dtype=np.double)) + cdef Vector3 e = rot2euler_c(r) + return [e(0), e(1), e(2)] + +def rot_matrix(roll, pitch, yaw): + return matrix2numpy(rot_matrix_c(roll, pitch, yaw)) + +def ecef_euler_from_ned_single(ecef_init, ned_pose): + cdef ECEF init = list2ecef(ecef_init) + cdef Vector3 pose = Vector3(ned_pose[0], ned_pose[1], ned_pose[2]) + + cdef Vector3 e = ecef_euler_from_ned_c(init, pose) + return [e(0), e(1), e(2)] + +def ned_euler_from_ecef_single(ecef_init, ecef_pose): + cdef ECEF init = list2ecef(ecef_init) + cdef Vector3 pose = Vector3(ecef_pose[0], ecef_pose[1], ecef_pose[2]) + + cdef Vector3 e = ned_euler_from_ecef_c(init, pose) + return [e(0), e(1), e(2)] + +def geodetic2ecef_single(geodetic): + cdef Geodetic g = list2geodetic(geodetic) + cdef ECEF e = geodetic2ecef_c(g) + return [e.x, e.y, e.z] + +def ecef2geodetic_single(ecef): + cdef ECEF e = list2ecef(ecef) + cdef Geodetic g = ecef2geodetic_c(e) + return [g.lat, g.lon, g.alt] + + +cdef class LocalCoord: + cdef LocalCoord_c * lc + + def __init__(self, geodetic=None, ecef=None): + assert (geodetic is not None) or (ecef is not None) + if geodetic is not None: + self.lc = new LocalCoord_c(list2geodetic(geodetic)) + elif ecef is not None: + self.lc = new LocalCoord_c(list2ecef(ecef)) + + @property + def ned2ecef_matrix(self): + return matrix2numpy(self.lc.ned2ecef_matrix) + + @property + def ecef2ned_matrix(self): + return matrix2numpy(self.lc.ecef2ned_matrix) + + @property + def ned_from_ecef_matrix(self): + return self.ecef2ned_matrix + + @property + def ecef_from_ned_matrix(self): + return self.ned2ecef_matrix + + @classmethod + def from_geodetic(cls, geodetic): + return cls(geodetic=geodetic) + + @classmethod + def from_ecef(cls, ecef): + return cls(ecef=ecef) + + def ecef2ned_single(self, ecef): + assert self.lc + cdef ECEF e = list2ecef(ecef) + cdef NED n = self.lc.ecef2ned(e) + return [n.n, n.e, n.d] + + def ned2ecef_single(self, ned): + assert self.lc + cdef NED n = list2ned(ned) + cdef ECEF e = self.lc.ned2ecef(n) + return [e.x, e.y, e.z] + + def geodetic2ned_single(self, geodetic): + assert self.lc + cdef Geodetic g = list2geodetic(geodetic) + cdef NED n = self.lc.geodetic2ned(g) + return [n.n, n.e, n.d] + + def ned2geodetic_single(self, ned): + assert self.lc + cdef NED n = list2ned(ned) + cdef Geodetic g = self.lc.ned2geodetic(n) + return [g.lat, g.lon, g.alt] + + def __dealloc__(self): + del self.lc diff --git a/common/util.cc b/common/util.cc new file mode 100644 index 0000000000..26a2bd60bc --- /dev/null +++ b/common/util.cc @@ -0,0 +1,317 @@ +#include "common/util.h" +#include "common/swaglog.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __linux__ +#include +#include +#ifndef __USE_GNU +#define __USE_GNU +#endif +#include +#endif // __linux__ + +namespace util { + +void set_thread_name(const char* name) { +#ifdef __linux__ + // pthread_setname_np is dumb (fails instead of truncates) + prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); +#endif +} + +int set_realtime_priority(int level) { +#ifdef __linux__ + long tid = syscall(SYS_gettid); + + // should match python using chrt + struct sched_param sa; + memset(&sa, 0, sizeof(sa)); + sa.sched_priority = level; + return sched_setscheduler(tid, SCHED_FIFO, &sa); +#else + return -1; +#endif +} + +int set_core_affinity(std::vector cores) { +#ifdef __linux__ + long tid = syscall(SYS_gettid); + cpu_set_t cpu; + + CPU_ZERO(&cpu); + for (const int n : cores) { + CPU_SET(n, &cpu); + } + return sched_setaffinity(tid, sizeof(cpu), &cpu); +#else + return -1; +#endif +} + +int set_file_descriptor_limit(uint64_t limit_val) { + struct rlimit limit; + int status; + + if ((status = getrlimit(RLIMIT_NOFILE, &limit)) < 0) + return status; + + limit.rlim_cur = limit_val; + if ((status = setrlimit(RLIMIT_NOFILE, &limit)) < 0) + return status; + + return 0; +} + +std::string read_file(const std::string& fn) { + std::ifstream f(fn, std::ios::binary | std::ios::in); + if (f.is_open()) { + f.seekg(0, std::ios::end); + std::streamsize size = f.tellg(); + // seekg and tellg on a directory doesn't return pos_type(-1) but max(streamsize) + if (f.good() && size > 0 && size < std::numeric_limits::max()) { + std::string result(size, '\0'); + f.seekg(0, std::ios::beg); + f.read(result.data(), size); + // return either good() or has reached end-of-file (e.g. /sys/power/wakeup_count) + if (f.good() || f.eof()) { + result.resize(f.gcount()); + return result; + } + } + // fallback for files created on read, e.g. procfs + std::stringstream buffer; + buffer << f.rdbuf(); + return buffer.str(); + } + return std::string(); +} + +std::map read_files_in_dir(const std::string &path) { + std::map ret; + DIR *d = opendir(path.c_str()); + if (!d) return ret; + + struct dirent *de = NULL; + while ((de = readdir(d))) { + if (de->d_type != DT_DIR) { + ret[de->d_name] = util::read_file(path + "/" + de->d_name); + } + } + + closedir(d); + return ret; +} + +int write_file(const char* path, const void* data, size_t size, int flags, mode_t mode) { + int fd = HANDLE_EINTR(open(path, flags, mode)); + if (fd == -1) { + return -1; + } + ssize_t n = HANDLE_EINTR(write(fd, data, size)); + close(fd); + return (n >= 0 && (size_t)n == size) ? 0 : -1; +} + +FILE* safe_fopen(const char* filename, const char* mode) { + FILE* fp = NULL; + do { + fp = fopen(filename, mode); + } while ((nullptr == fp) && (errno == EINTR)); + return fp; +} + +size_t safe_fwrite(const void* ptr, size_t size, size_t count, FILE* stream) { + size_t written = 0; + do { + size_t ret = ::fwrite((void*)((char *)ptr + written * size), size, count - written, stream); + if (ret == 0 && errno != EINTR) break; + written += ret; + } while (written != count); + return written; +} + +int safe_fflush(FILE *stream) { + int ret = EOF; + do { + ret = fflush(stream); + } while ((EOF == ret) && (errno == EINTR)); + return ret; +} + +int safe_ioctl(int fd, unsigned long request, void *argp, const char* exception_msg) { + int ret; + do { + ret = ioctl(fd, request, argp); + } while ((ret == -1) && (errno == EINTR)); + + if (ret == -1 && exception_msg) { + LOGE("safe_ioctl error: %s %s(%d) (fd: %d request: %lx argp: %p)", exception_msg, strerror(errno), errno, fd, request, argp); + throw std::runtime_error(exception_msg); + } + return ret; +} + +std::string readlink(const std::string &path) { + char buff[4096]; + ssize_t len = ::readlink(path.c_str(), buff, sizeof(buff)-1); + if (len != -1) { + buff[len] = '\0'; + return std::string(buff); + } + return ""; +} + +bool file_exists(const std::string& fn) { + struct stat st = {}; + return stat(fn.c_str(), &st) != -1; +} + +static bool createDirectory(std::string dir, mode_t mode) { + auto verify_dir = [](const std::string& dir) -> bool { + struct stat st = {}; + return (stat(dir.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR); + }; + // remove trailing /'s + while (dir.size() > 1 && dir.back() == '/') { + dir.pop_back(); + } + // try to mkdir this directory + if (mkdir(dir.c_str(), mode) == 0) return true; + if (errno == EEXIST) return verify_dir(dir); + if (errno != ENOENT) return false; + + // mkdir failed because the parent dir doesn't exist, so try to create it + size_t slash = dir.rfind('/'); + if ((slash == std::string::npos || slash < 1) || + !createDirectory(dir.substr(0, slash), mode)) { + return false; + } + + // try again + if (mkdir(dir.c_str(), mode) == 0) return true; + return errno == EEXIST && verify_dir(dir); +} + +bool create_directories(const std::string& dir, mode_t mode) { + if (dir.empty()) return false; + return createDirectory(dir, mode); +} + +std::string getenv(const char* key, std::string default_val) { + const char* val = ::getenv(key); + return val ? val : default_val; +} + +int getenv(const char* key, int default_val) { + const char* val = ::getenv(key); + return val ? atoi(val) : default_val; +} + +float getenv(const char* key, float default_val) { + const char* val = ::getenv(key); + return val ? atof(val) : default_val; +} + +std::string hexdump(const uint8_t* in, const size_t size) { + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (size_t i = 0; i < size; i++) { + ss << std::setw(2) << static_cast(in[i]); + } + return ss.str(); +} + +int random_int(int min, int max) { + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_int_distribution dist(min, max); + return dist(rng); +} + +std::string random_string(std::string::size_type length) { + const std::string chrs = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + std::mt19937 rg{std::random_device{}()}; + std::uniform_int_distribution pick(0, chrs.length() - 1); + std::string s; + s.reserve(length); + while (length--) { + s += chrs[pick(rg)]; + } + return s; +} + +bool starts_with(const std::string &s1, const std::string &s2) { + return strncmp(s1.c_str(), s2.c_str(), s2.size()) == 0; +} + +bool ends_with(const std::string& s, const std::string& suffix) { + return s.size() >= suffix.size() && + strcmp(s.c_str() + (s.size() - suffix.size()), suffix.c_str()) == 0; +} + +std::string strip(const std::string &str) { + auto should_trim = [](unsigned char ch) { + return std::isspace(ch) || ch == '\0'; + }; + + size_t start = 0; + while (start < str.size() && should_trim(static_cast(str[start]))) { + start++; + } + + if (start == str.size()) { + return ""; + } + + size_t end = str.size() - 1; + while (end > 0 && should_trim(static_cast(str[end]))) { + end--; + } + + return str.substr(start, end - start + 1); +} + +std::string check_output(const std::string& command) { + char buffer[128]; + std::string result; + std::unique_ptr pipe(popen(command.c_str(), "r"), pclose); + + if (!pipe) { + return ""; + } + + while (fgets(buffer, std::size(buffer), pipe.get()) != nullptr) { + result += std::string(buffer); + } + + return result; +} + +bool system_time_valid() { + // Default to August 26, 2024 + tm min_tm = {.tm_year = 2024 - 1900, .tm_mon = 7, .tm_mday = 26}; + time_t min_date = mktime(&min_tm); + + struct stat st; + if (stat("/lib/systemd/systemd", &st) == 0) { + min_date = std::max(min_date, st.st_mtime + 86400); // Add 1 day (86400 seconds) + } + + return time(nullptr) > min_date; +} + +} // namespace util diff --git a/common/util.h b/common/util.h new file mode 100644 index 0000000000..f46db4d9fa --- /dev/null +++ b/common/util.h @@ -0,0 +1,187 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// keep trying if x gets interrupted by a signal +#define HANDLE_EINTR(x) \ + ({ \ + decltype(x) ret_; \ + int try_cnt = 0; \ + do { \ + ret_ = (x); \ + } while (ret_ == -1 && errno == EINTR && try_cnt++ < 100); \ + ret_; \ + }) + +#ifndef sighandler_t +typedef void (*sighandler_t)(int sig); +#endif + +const double MILE_TO_KM = 1.609344; +const double KM_TO_MILE = 1. / MILE_TO_KM; +const double MS_TO_KPH = 3.6; +const double MS_TO_MPH = MS_TO_KPH * KM_TO_MILE; +const double METER_TO_MILE = KM_TO_MILE / 1000.0; +const double METER_TO_FOOT = 3.28084; + +#define ALIGNED_SIZE(x, align) (((x) + (align)-1) & ~((align)-1)) + +namespace util { + +void set_thread_name(const char* name); +int set_realtime_priority(int level); +int set_core_affinity(std::vector cores); +int set_file_descriptor_limit(uint64_t limit); + +// ***** math helpers ***** + +// map x from [a1, a2] to [b1, b2] +template +T map_val(T x, T a1, T a2, T b1, T b2) { + x = std::clamp(x, a1, a2); + T ra = a2 - a1; + T rb = b2 - b1; + return (x - a1) * rb / ra + b1; +} + +// ***** string helpers ***** + +template +std::string string_format(const std::string& format, Args... args) { + size_t size = snprintf(nullptr, 0, format.c_str(), args...) + 1; + std::unique_ptr buf(new char[size]); + snprintf(buf.get(), size, format.c_str(), args...); + return std::string(buf.get(), buf.get() + size - 1); +} + +std::string getenv(const char* key, std::string default_val = ""); +int getenv(const char* key, int default_val); +float getenv(const char* key, float default_val); + +std::string hexdump(const uint8_t* in, const size_t size); +bool starts_with(const std::string &s1, const std::string &s2); +bool ends_with(const std::string &s, const std::string &suffix); +std::string strip(const std::string &str); + +// ***** random helpers ***** +int random_int(int min, int max); +std::string random_string(std::string::size_type length); + +// **** file helpers ***** +std::string read_file(const std::string& fn); +std::map read_files_in_dir(const std::string& path); +int write_file(const char* path, const void* data, size_t size, int flags = O_WRONLY, mode_t mode = 0664); + +FILE* safe_fopen(const char* filename, const char* mode); +size_t safe_fwrite(const void * ptr, size_t size, size_t count, FILE * stream); +int safe_fflush(FILE *stream); +int safe_ioctl(int fd, unsigned long request, void *argp, const char* exception_msg = nullptr); + +std::string readlink(const std::string& path); +bool file_exists(const std::string& fn); +bool create_directories(const std::string &dir, mode_t mode); + +std::string check_output(const std::string& command); + +bool system_time_valid(); + +inline void sleep_for(const int milliseconds) { + if (milliseconds > 0) { + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); + } +} + +} // namespace util + +class ExitHandler { +public: + ExitHandler() { + std::signal(SIGINT, (sighandler_t)set_do_exit); + std::signal(SIGTERM, (sighandler_t)set_do_exit); + +#ifndef __APPLE__ + std::signal(SIGPWR, (sighandler_t)set_do_exit); +#endif + } + inline static std::atomic power_failure = false; + inline static std::atomic signal = 0; + inline operator bool() { return do_exit; } + inline ExitHandler& operator=(bool v) { + signal = 0; + do_exit = v; + return *this; + } +private: + static void set_do_exit(int sig) { +#ifndef __APPLE__ + power_failure = (sig == SIGPWR); +#endif + signal = sig; + do_exit = true; + } + inline static std::atomic do_exit = false; +}; + +struct unique_fd { + unique_fd(int fd = -1) : fd_(fd) {} + unique_fd& operator=(unique_fd&& uf) { + fd_ = uf.fd_; + uf.fd_ = -1; + return *this; + } + ~unique_fd() { + if (fd_ != -1) close(fd_); + } + operator int() const { return fd_; } + int fd_; +}; + +class FirstOrderFilter { +public: + FirstOrderFilter(float x0, float ts, float dt, bool initialized = true) { + k_ = (dt / ts) / (1.0 + dt / ts); + x_ = x0; + initialized_ = initialized; + } + inline float update(float x) { + if (initialized_) { + x_ = (1. - k_) * x_ + k_ * x; + } else { + initialized_ = true; + x_ = x; + } + return x_; + } + inline void reset(float x) { x_ = x; } + inline float x(){ return x_; } + +private: + float x_, k_; + bool initialized_; +}; + +template +void update_max_atomic(std::atomic& max, T const& value) { + T prev = max; + while (prev < value && !max.compare_exchange_weak(prev, value)) {} +} + +typedef struct Rect { + int x; + int y; + int w; + int h; +} Rect; diff --git a/common/util.py b/common/util.py new file mode 100644 index 0000000000..e6ddb46e7b --- /dev/null +++ b/common/util.py @@ -0,0 +1,46 @@ +import os +import subprocess + +def sudo_write(val: str, path: str) -> None: + try: + with open(path, 'w') as f: + f.write(str(val)) + except PermissionError: + os.system(f"sudo chmod a+w {path}") + try: + with open(path, 'w') as f: + f.write(str(val)) + except PermissionError: + # fallback for debugfs files + os.system(f"sudo su -c 'echo {val} > {path}'") + +def sudo_read(path: str) -> str: + try: + return subprocess.check_output(f"sudo cat {path}", shell=True, encoding='utf8').strip() + except Exception: + return "" + +class MovingAverage: + def __init__(self, window_size: int): + self.window_size: int = window_size + self.buffer: list[float] = [0.0] * window_size + self.index: int = 0 + self.count: int = 0 + self.sum: float = 0.0 + + def add_value(self, new_value: float): + # Update the sum: subtract the value being replaced and add the new value + self.sum -= self.buffer[self.index] + self.buffer[self.index] = new_value + self.sum += new_value + + # Update the index in a circular manner + self.index = (self.index + 1) % self.window_size + + # Track the number of added values (for partial windows) + self.count = min(self.count + 1, self.window_size) + + def get_average(self) -> float: + if self.count == 0: + return float('nan') + return self.sum / self.count diff --git a/common/version.h b/common/version.h new file mode 100644 index 0000000000..669f303211 --- /dev/null +++ b/common/version.h @@ -0,0 +1 @@ +#define COMMA_VERSION "0.10.1" diff --git a/common/watchdog.cc b/common/watchdog.cc new file mode 100644 index 0000000000..44e8c83e6d --- /dev/null +++ b/common/watchdog.cc @@ -0,0 +1,12 @@ +#include + +#include "common/watchdog.h" +#include "common/util.h" +#include "system/hardware/hw.h" + +const std::string watchdog_fn_prefix = Path::shm_path() + "/wd_"; // + + +bool watchdog_kick(uint64_t ts) { + static std::string fn = watchdog_fn_prefix + std::to_string(getpid()); + return util::write_file(fn.c_str(), &ts, sizeof(ts), O_WRONLY | O_CREAT) > 0; +} diff --git a/common/watchdog.h b/common/watchdog.h new file mode 100644 index 0000000000..12dd2ca035 --- /dev/null +++ b/common/watchdog.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool watchdog_kick(uint64_t ts); diff --git a/common/watchdog.py b/common/watchdog.py new file mode 100644 index 0000000000..ddb6f744e9 --- /dev/null +++ b/common/watchdog.py @@ -0,0 +1,22 @@ +import os +import time +import struct +from openpilot.system.hardware.hw import Paths + +WATCHDOG_FN = f"{Paths.shm_path()}/wd_" +_LAST_KICK = 0.0 + +def kick_watchdog(): + global _LAST_KICK + current_time = time.monotonic() + + if current_time - _LAST_KICK < 1.0: + return + + try: + with open(f"{WATCHDOG_FN}{os.getpid()}", 'wb') as f: + f.write(struct.pack(' + +# Supported Cars + +A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified. + +# 325 Supported Cars + +|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Hardware Needed
     |Video|Setup Video| +|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:| +|Acura|ILX 2016-18|Technology Plus Package or AcuraWatch Plus|openpilot|26 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Acura|ILX 2019|All|openpilot|26 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Acura|MDX 2025|All except Type S|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Acura|RDX 2019-21|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Acura|TLX 2021|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Audi|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 GM connector
    - 1 comma 3X
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 GM connector
    - 1 comma 3X
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 GM connector
    - 1 comma 3X
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chevrolet|Silverado 1500 2020-21|Safety Package II|openpilot available[1](#footnotes)|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 GM connector
    - 1 comma 3X
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chevrolet|Trailblazer 2021-22|Adaptive Cruise Control (ACC)|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 GM connector
    - 1 comma 3X
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Chrysler|Pacifica Hybrid 2019-25|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|comma|body|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|None||| +|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Escape 2023-24|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Escape Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Escape Plug-in Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Expedition 2022-24|Co-Pilot360 Assist 2.0|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Explorer 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|F-150 2021-23|Co-Pilot360 Assist 2.0|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|F-150 Hybrid 2021-23|Co-Pilot360 Assist 2.0|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Focus 2018[3](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Focus Hybrid 2018[3](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Kuga 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Kuga Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Kuga Hybrid 2024|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Kuga Plug-in Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Kuga Plug-in Hybrid 2024|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Maverick 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Maverick 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Maverick Hybrid 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Maverick Hybrid 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Mustang Mach-E 2021-24|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ford|Ranger 2024|Adaptive Cruise Control with Lane Centering|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q4 connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G70 2018|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai F connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G70 2019-21|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai F connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G70 2022-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G80 2017|All|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai J connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G80 2018-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G80 (2.5T Advanced Trim, with HDA II) 2024[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai P connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|G90 2017-20|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV60 (Advanced Trim) 2023[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV60 (Performance Trim) 2022-23[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV70 (2.5T Trim, without HDA II) 2022-24[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV70 (3.5T Trim, without HDA II) 2022-23[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai M connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV70 Electrified (Australia Only) 2022[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai Q connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV70 Electrified (with HDA II) 2023-24[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai Q connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Genesis|GV80 2023[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai M connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|GMC|Sierra 1500 2020-21|Driver Alert Package II|openpilot available[1](#footnotes)|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 GM connector
    - 1 comma 3X
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Accord 2018-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Accord 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Accord Hybrid 2018-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Accord Hybrid 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|City (Brazil only) 2023|All|openpilot available[1](#footnotes)|0 mph|14 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic 2019-21|All|openpilot available[1](#footnotes)|0 mph|2 mph[5](#footnotes)|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic 2022-24|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic Hatchback 2019-21|All|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic Hatchback 2022-24|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic Hatchback Hybrid 2025-26|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Civic Hybrid 2025|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|CR-V 2015-16|Touring Trim|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|CR-V 2017-22|Honda Sensing|openpilot available[1](#footnotes)|0 mph|15 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|CR-V 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|CR-V Hybrid 2017-22|Honda Sensing|openpilot available[1](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|CR-V Hybrid 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|e 2020|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Fit 2018-20|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Freed 2020|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|HR-V 2019-22|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|HR-V 2023-25|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Insight 2019-22|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Inspire 2018|All|openpilot available[1](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|N-Box 2018|All|openpilot available[1](#footnotes)|0 mph|11 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Odyssey 2021-25|All|openpilot available[1](#footnotes)|0 mph|43 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Passport 2026|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Pilot 2023-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Honda Bosch C connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Honda|Ridgeline 2017-25|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Honda Nidec connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Azera 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Azera Hybrid 2019|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Azera Hybrid 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Custin 2023|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai G connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai J connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai Q connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq 5 (with HDA II) 2022-24[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai Q connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq 5 (without HDA II) 2022-24[6](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq 6 (with HDA II) 2023-24[6](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai P connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq Electric 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq Hybrid 2020-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Ioniq Plug-in Hybrid 2020-22|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Kona 2020|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|6 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai G connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai O connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Kona Electric (with HDA II, Korea only) 2023[6](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai R connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai I connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Nexo 2021|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Palisade 2020-22|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Santa Cruz 2022-24[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Santa Fe 2019-20|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai D connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Santa Fe 2021-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Santa Fe Hybrid 2022-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Santa Fe Plug-in Hybrid 2022-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Sonata 2020-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Sonata Hybrid 2020-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Staria 2023[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Tucson 2022[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Tucson 2023-24[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Tucson Hybrid 2022-24[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Tucson Plug-in Hybrid 2024[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 FCA connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Carnival 2022-24[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Carnival (China only) 2023[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|EV6 (Southeast Asia only) 2022-24[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai P connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|EV6 (with HDA II) 2022-24[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai P connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|EV6 (without HDA II) 2022-24[6](#footnotes)|Highway Driving Assist|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai L connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|6 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai G connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Forte 2022-23|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|K5 2021-24|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|K8 Hybrid (with HDA II) 2023[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai Q connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro EV 2019|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro EV 2020|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai F connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro EV 2021|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro EV 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro EV (with HDA II) 2025[6](#footnotes)|Highway Driving Assist II|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai R connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro EV (without HDA II) 2023-25[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Hybrid 2018|Smart Cruise Control (SCC)|Stock|10 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai D connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai F connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Hybrid 2023[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Plug-in Hybrid 2020|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai D connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Plug-in Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai D connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Niro Plug-in Hybrid 2022|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai F connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Optima 2017|Advanced Smart Cruise Control|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai G connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Seltos 2021|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sorento 2018|Advanced Smart Cruise Control & LKAS|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai E connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sorento 2021-23[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sorento Hybrid 2021-23[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sorento Plug-in Hybrid 2022-23[6](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sportage 2023-24[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Sportage Hybrid 2023[6](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai N connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai C connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Stinger 2022-23|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai K connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Kia|Telluride 2020-22|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Hyundai H connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|ES 2017-18|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|ES 2019-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|ES Hybrid 2017-18|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|ES Hybrid 2019-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|IS 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|LC 2024-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|NX 2018-19|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|NX 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|NX Hybrid 2018-19|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|NX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RC 2018-20|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RC 2023|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RX 2016|Lexus Safety System+|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RX 2017-19|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RX 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RX Hybrid 2016|Lexus Safety System+|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RX Hybrid 2017-19|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lexus|UX Hybrid 2019-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ford Q3 connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Mazda|CX-5 2022-25|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Mazda connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Mazda connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Nissan[7](#footnotes)|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Nissan B connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Nissan[7](#footnotes)|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Nissan A connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Nissan[7](#footnotes)|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Nissan A connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Nissan[7](#footnotes)|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Nissan A connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Ram connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Rivian|R1S 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Rivian A connector
    - 1 USB-C coupler
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Rivian|R1T 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Rivian A connector
    - 1 USB-C coupler
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Subaru|Ascent 2019-21|All[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Forester 2019-21|All[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Impreza 2017-19|EyeSight Driver Assistance[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Impreza 2020-22|EyeSight Driver Assistance[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Legacy 2020-22|All[8](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|Outback 2020-22|All[8](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru B connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|XV 2018-19|EyeSight Driver Assistance[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Subaru|XV 2020-21|EyeSight Driver Assistance[8](#footnotes)|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Subaru A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    Tools- 1 Pry Tool
    - 1 Socket Wrench 8mm or 5/16" (deep)
    ||| +|Škoda|Fabia 2022-23[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    [17](#footnotes)||| +|Škoda|Kamiq 2021-23[13,15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    [17](#footnotes)||| +|Škoda|Karoq 2019-23[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Škoda|Kodiaq 2017-23[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Škoda|Octavia 2015-19[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Škoda|Octavia RS 2016[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Škoda|Octavia Scout 2017-19[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Škoda|Scala 2020-23[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    [17](#footnotes)||| +|Škoda|Superb 2015-22[15](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Tesla[11](#footnotes)|Model 3 (with HW3) 2019-23[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Tesla A connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Tesla[11](#footnotes)|Model 3 (with HW4) 2024-25[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Tesla B connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Tesla[11](#footnotes)|Model Y (with HW3) 2020-23[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Tesla A connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Tesla[11](#footnotes)|Model Y (with HW4) 2024-25[10](#footnotes)|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Tesla B connector
    - 1 USB-C coupler
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Avalon 2017-18|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Avalon 2019-21|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Avalon 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Avalon Hybrid 2019-21|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Avalon Hybrid 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|C-HR 2017-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|C-HR 2021|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|C-HR Hybrid 2021-22|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Camry 2018-20|All|Stock|0 mph[12](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Camry 2021-24|All|openpilot|0 mph[12](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla 2017-19|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Highlander 2017-19|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Highlander Hybrid 2017-19|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Highlander Hybrid 2020-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Prius 2016|Toyota Safety Sense P|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Prius 2017-20|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Prius Prime 2017-20|All|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Prius v 2017|Toyota Safety Sense P|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 2016|Toyota Safety Sense P|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 2017-18|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 2023-25|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 Hybrid 2017-18|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 Hybrid 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|RAV4 Hybrid 2023-25|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Toyota|Sienna 2018-20|All|openpilot available[2](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 Toyota A connector
    - 1 comma 3X
    - 1 comma power v3
    - 1 harness box
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 angled mount (8 degrees)
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Jetta 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Passat 2015-22[14](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    [17](#footnotes)||| +|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    [17](#footnotes)||| +|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    [17](#footnotes)||| +|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| +|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,16](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|
    Parts- 1 USB-C coupler
    - 1 VW J533 connector
    - 1 comma 3X
    - 1 harness box
    - 1 long OBD-C cable (9.5 ft)
    - 1 mount
    - 1 right angle OBD-C cable (1.5 ft)
    Buy Here
    ||| + +### Footnotes +1openpilot Longitudinal Control (Alpha) is available behind a toggle; the toggle is only available in non-release branches such as `devel` or `nightly-dev`.
    +2By default, this car will use the stock Adaptive Cruise Control (ACC) for longitudinal control. If the Driver Support Unit (DSU) is disconnected, openpilot ACC will replace stock ACC. NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).
    +3Refers only to the Focus Mk4 (C519) available in Europe/China/Taiwan/Australasia, not the Focus Mk3 (C346) in North and South America/Southeast Asia.
    +4See more setup details for GM.
    +52019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.
    +6Requires a CAN FD panda kit if not using comma 3X for this CAN FD car.
    +7See more setup details for Nissan.
    +8In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance.
    +9Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB.
    +10Some 2023 model years have HW4. To check which hardware type your vehicle has, look for Autopilot computer under Software -> Additional Vehicle Information on your vehicle's touchscreen. See this page for more information.
    +11See more setup details for Tesla.
    +12openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.
    +13Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform.
    +14Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets.
    +15Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma 3X functionality.
    +16Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC.
    +17Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store.
    + +## Community Maintained Cars +Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/). + +# Don't see your car here? + +**openpilot can support many more cars than it currently does.** There are a few reasons your car may not be supported. +If your car doesn't fit into any of the incompatibility criteria here, then there's a good chance it can be supported! We're adding support for new cars all the time. **We don't have a roadmap for car support**, and in fact, most car support comes from users like you! + +### Which cars are able to be supported? + +openpilot uses the existing steering, gas, and brake interfaces in your car. If your car lacks any one of these interfaces, openpilot will not be able to control the car. If your car has [ACC](https://en.wikipedia.org/wiki/Adaptive_cruise_control) and any form of [LKAS](https://en.wikipedia.org/wiki/Automated_Lane_Keeping_Systems)/[LCA](https://en.wikipedia.org/wiki/Lane_centering), then it almost certainly has these interfaces. These features generally started shipping on cars around 2016. Note that manufacturers will often make their own [marketing terms](https://en.wikipedia.org/wiki/Adaptive_cruise_control#Vehicle_models_supporting_adaptive_cruise_control) for these features, such as Hyundai's "Smart Cruise Control" branding of Adaptive Cruise Control. + +If your car has the following packages or features, then it's a good candidate for support. + +| Make | Required Package/Features | +| ---- | ------------------------- | +| Acura | Any car with AcuraWatch Plus will work. AcuraWatch Plus comes standard on many newer models. | +| Ford | Any car with Lane Centering will likely work. | +| Honda | Any car with Honda Sensing will work. Honda Sensing comes standard on many newer models. | +| Subaru | Any car with EyeSight will work. EyeSight comes standard on many newer models. | +| Nissan | Any car with ProPILOT will likely work. | +| Toyota & Lexus | Any car that has Toyota/Lexus Safety Sense with "Lane Departure Alert with Steering Assist (LDA w/SA)" and/or "Lane Tracing Assist (LTA)" will work. Note that LDA without Steering Assist will not work. These features come standard on most newer models. | +| Hyundai, Kia, & Genesis | Any car with Smart Cruise Control (SCC) and Lane Following Assist (LFA) or Lane Keeping Assist (LKAS) will work. LKAS/LFA comes standard on most newer models. Any form of SCC will work, such as NSCC. | +| Chrysler, Jeep, & Ram | Any car with LaneSense and Adaptive Cruise Control will likely work. These come standard on many newer models. | + +### FlexRay + +All the cars that openpilot supports use a [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) for communication between all the car's computers, however a CAN bus isn't the only way that the computers in your car can communicate. Most, if not all, vehicles from the following manufacturers use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) instead of a CAN bus: **BMW, Mercedes, Audi, Land Rover, and some Volvo**. These cars may one day be supported, but we have no immediate plans to support FlexRay. + +### Toyota Security + +openpilot does not yet support these Toyota models due to a new message authentication method. +[Vote](https://comma.ai/shop#toyota-security) if you'd like to see openpilot support on these models. + +* Toyota RAV4 Prime 2021+ +* Toyota Sienna 2021+ +* Toyota Venza 2021+ +* Toyota Sequoia 2023+ +* Toyota Tundra 2022+ +* Toyota Highlander 2024+ +* Toyota Corolla Cross 2022+ (only US model) +* Toyota Camry 2025+ +* Lexus NX 2022+ +* Toyota bZ4x 2023+ +* Subaru Solterra 2023+ diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000000..7583095eaf --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,73 @@ +# How to contribute + +Our software is open source so you can solve your own problems without needing help from others. And if you solve a problem and are so kind, you can upstream it for the rest of the world to use. Check out our [post about externalization](https://blog.comma.ai/a-2020-theme-externalization/). + +Development is coordinated through [Discord](https://discord.comma.ai) and GitHub. + +### Getting Started + +* Set up your [development environment](/tools/) +* Join our [Discord](https://discord.comma.ai) +* Docs are at https://docs.comma.ai and https://blog.comma.ai + +## What contributions are we looking for? + +**openpilot's priorities are [safety](SAFETY.md), stability, quality, and features, in that order.** +openpilot is part of comma's mission to *solve self-driving cars while delivering shippable intermediaries*, and all development is towards that goal. + +### What gets merged? + +The probability of a pull request being merged is a function of its value to the project and the effort it will take us to get it merged. +If a PR offers *some* value but will take lots of time to get merged, it will be closed. +Simple, well-tested bug fixes are the easiest to merge, and new features are the hardest to get merged. + +All of these are examples of good PRs: +* typo fix: https://github.com/commaai/openpilot/pull/30678 +* removing unused code: https://github.com/commaai/openpilot/pull/30573 +* simple car model port: https://github.com/commaai/openpilot/pull/30245 +* car brand port: https://github.com/commaai/openpilot/pull/23331 + +### What doesn't get merged? + +* **style changes**: code is art, and it's up to the author to make it beautiful +* **500+ line PRs**: clean it up, break it up into smaller PRs, or both +* **PRs without a clear goal**: every PR must have a singular and clear goal +* **UI design**: we do not have a good review process for this yet +* **New features**: We believe openpilot is mostly feature-complete, and the rest is a matter of refinement and fixing bugs. As a result of this, most feature PRs will be immediately closed, however the beauty of open source is that forks can and do offer features that upstream openpilot doesn't. +* **Negative expected value**: This a class of PRs that makes an improvement, but the risk or validation costs more than the improvement. The risk can be mitigated by first getting a failing test merged. + +### First contribution + +[Projects / openpilot bounties](https://github.com/orgs/commaai/projects/26/views/1?pane=info) is the best place to get started and goes in-depth on what's expected when working on a bounty. +There's lot of bounties that don't require a comma 3X or a car. + +## Pull Requests + +Pull requests should be against the master branch. + +A good pull request has all of the following: +* a clearly stated purpose +* every line changed directly contributes to the stated purpose +* verification, i.e. how did you test your PR? +* justification + * if you've optimized something, post benchmarks to prove it's better + * if you've improved your car's tuning, post before and after plots +* passes the CI tests + +## Contributing without Code + +* Report bugs in GitHub issues. +* Report driving issues in the `#driving-feedback` Discord channel. +* Consider opting into driver camera uploads to improve the driver monitoring model. +* Connect your device to Wi-Fi regularly, so that we can pull data for training better driving models. +* Run the `nightly` branch and report issues. This branch is like `master` but it's built just like a release. +* Annotate images in the [comma10k dataset](https://github.com/commaai/comma10k). + +## Contributing Training Data + +### A guide for forks + +In order for your fork's data to be eligible for the training set: +* **Your cereal messaging structs must be [compatible](../cereal#custom-forks)** +* **The definitions of all the stock messaging structs must not change**: Do not change how any of the fields are set, including everything from `selfdriveState.enabled` to `carState.steeringAngleDeg`. Instead, create your own structs and set them however you'd like. +* **Do not include cars that are not supported in upstream platforms**: Instead, create new opendbc platforms for cars that you'd like to support outside of upstream, even if it's just a trim-level difference. diff --git a/docs/DEBUGGING_SAFETY.md b/docs/DEBUGGING_SAFETY.md new file mode 100644 index 0000000000..cd0a46b446 --- /dev/null +++ b/docs/DEBUGGING_SAFETY.md @@ -0,0 +1,30 @@ +# Debugging Panda Safety with Replay Drive + LLDB + +## 1. Start the debugger in VS Code + +* Select **Replay drive + Safety LLDB**. +* Enter the route or segment when prompted. +[](https://github.com/user-attachments/assets/b0cc320a-083e-46a7-a9f8-ca775bbe5604) + +## 2. Attach LLDB + +* When prompted, pick the running **`replay_drive` process**. +* ⚠️ Attach quickly, or `replay_drive` will start consuming messages. + +> [!TIP] +> Add a Python breakpoint at the start of `replay_drive.py` to pause execution and give yourself time to attach LLDB. + +## 3. Set breakpoints in VS Code +Breakpoints can be set directly in `modes/xxx.h` (or any C file). +No extra LLDB commands are required — just place breakpoints in the editor. + +## 4. Resume execution +Once attached, you can step through both Python (on the replay) and C safety code as CAN logs are replayed. + +> [!NOTE] +> * Use short routes for quicker iteration. +> * Pause `replay_drive` early to avoid wasting log messages. + +## Video + +View a demo of this workflow on the PR that added it: https://github.com/commaai/openpilot/pull/36055#issue-3352911578 \ No newline at end of file diff --git a/docs/INTEGRATION.md b/docs/INTEGRATION.md new file mode 100644 index 0000000000..ba6291c1e3 --- /dev/null +++ b/docs/INTEGRATION.md @@ -0,0 +1,11 @@ +# Integration with Stock Features + +In all supported cars: +* Stock Lane Keep Assist (LKA) and stock ALC are replaced by openpilot ALC, which only functions when openpilot is engaged by the user. +* Stock LDW is replaced by openpilot LDW. + +Additionally, on specific supported cars (see ACC column in [supported cars](CARS.md)): +* Stock ACC is replaced by openpilot ACC. +* openpilot FCW operates in addition to stock FCW. + +openpilot should preserve all other vehicle's stock features, including, but not limited to: FCW, Automatic Emergency Braking (AEB), auto high-beam, blind spot warning, and side collision warning. diff --git a/docs/LIMITATIONS.md b/docs/LIMITATIONS.md new file mode 100644 index 0000000000..8c112659c2 --- /dev/null +++ b/docs/LIMITATIONS.md @@ -0,0 +1,58 @@ +# Limitations +## Limitations of openpilot ALC and LDW + +openpilot ALC and openpilot LDW do not automatically drive the vehicle or reduce the amount of attention that must be paid to operate your vehicle. The driver must always keep control of the steering wheel and be ready to correct the openpilot ALC action at all times. + +While changing lanes, openpilot is not capable of looking next to you or checking your blind spot. Only nudge the wheel to initiate a lane change after you have confirmed it's safe to do so. + +Many factors can impact the performance of openpilot ALC and openpilot LDW, causing them to be unable to function as intended. These include, but are not limited to: + +* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation. +* The road facing camera is obstructed, covered or damaged by mud, ice, snow, etc. +* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle. +* The device is mounted incorrectly. +* When in sharp curves, like on-off ramps, intersections etc...; openpilot is designed to be limited in the amount of steering torque it can produce. +* In the presence of restricted lanes or construction zones. +* When driving on highly banked roads or in presence of strong cross-wind. +* Extremely hot or cold temperatures. +* Bright light (due to oncoming headlights, direct sunlight, etc.). +* Driving on hills, narrow, or winding roads. + +The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times. + +## Limitations of openpilot ACC and FCW + +openpilot ACC and openpilot FCW are not systems that allow careless or inattentive driving. It is still necessary for the driver to pay close attention to the vehicle’s surroundings and to be ready to re-take control of the gas and the brake at all times. + +Many factors can impact the performance of openpilot ACC and openpilot FCW, causing them to be unable to function as intended. These include, but are not limited to: + +* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation. +* The road facing camera or radar are obstructed, covered, or damaged by mud, ice, snow, etc. +* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle. +* The device is mounted incorrectly. +* Approaching a toll booth, a bridge or a large metal plate. +* When driving on roads with pedestrians, cyclists, etc... +* In presence of traffic signs or stop lights, which are not detected by openpilot at this time. +* When the posted speed limit is below the user selected set speed. openpilot does not detect speed limits at this time. +* In presence of vehicles in the same lane that are not moving. +* When abrupt braking maneuvers are required. openpilot is designed to be limited in the amount of deceleration and acceleration that it can produce. +* When surrounding vehicles perform close cut-ins from neighbor lanes. +* Driving on hills, narrow, or winding roads. +* Extremely hot or cold temperatures. +* Bright light (due to oncoming headlights, direct sunlight, etc.). +* Interference from other equipment that generates radar waves. + +The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times. + +## Limitations of openpilot DM + +openpilot DM should not be considered an exact measurement of the alertness of the driver. + +Many factors can impact the performance of openpilot DM, causing it to be unable to function as intended. These include, but are not limited to: + +* Low light conditions, such as driving at night or in dark tunnels. +* Bright light (due to oncoming headlights, direct sunlight, etc.). +* The driver's face is partially or completely outside field of view of the driver facing camera. +* The driver facing camera is obstructed, covered, or damaged. + +The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. A driver should not rely on openpilot DM to assess their level of attention. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..08dd4fa8bc --- /dev/null +++ b/docs/README.md @@ -0,0 +1,26 @@ +# openpilot docs + +This is the source for [docs.comma.ai](https://docs.comma.ai). +The site is updated on pushes to master by this [workflow](../.github/workflows/docs.yaml). + +## Development +NOTE: Those commands must be run in the root directory of openpilot, **not /docs** + +**1. Install the docs dependencies** +``` bash +pip install .[docs] +``` + +**2. Build the new site** +``` bash +mkdocs build +``` + +**3. Run the new site locally** +``` bash +mkdocs serve +``` + +References: +* https://www.mkdocs.org/getting-started/ +* https://github.com/ntno/mkdocs-terminal diff --git a/docs/SAFETY.md b/docs/SAFETY.md new file mode 100644 index 0000000000..25815e3372 --- /dev/null +++ b/docs/SAFETY.md @@ -0,0 +1,46 @@ +# Safety + +openpilot is an Adaptive Cruise Control (ACC) and Automated Lane Centering (ALC) system. +Like other ACC and ALC systems, openpilot is a failsafe passive system and it requires the +driver to be alert and to pay attention at all times. + +In order to enforce driver alertness, openpilot includes a driver monitoring feature +that alerts the driver when distracted. + +However, even with an attentive driver, we must make further efforts for the system to be +safe. We repeat, **driver alertness is necessary, but not sufficient, for openpilot to be +used safely** and openpilot is provided with no warranty of fitness for any purpose. + +openpilot is developed in good faith to be compliant with FMVSS requirements and to follow +industry standards of safety for Level 2 Driver Assistance Systems. In particular, we observe +ISO26262 guidelines, including those from [pertinent documents](https://www.nhtsa.gov/sites/nhtsa.dot.gov/files/documents/13498a_812_573_alcsystemreport.pdf) +released by NHTSA. In addition, we impose strict coding guidelines (like [MISRA C : 2012](https://www.misra.org.uk/what-is-misra/)) +on parts of openpilot that are safety relevant. We also perform software-in-the-loop, +hardware-in-the-loop, and in-vehicle tests before each software release. + +Following Hazard and Risk Analysis and FMEA, at a very high level, we have designed openpilot +ensuring two main safety requirements. + +1. The driver must always be capable to immediately retake manual control of the vehicle, + by stepping on the brake pedal or by pressing the cancel button. +2. The vehicle must not alter its trajectory too quickly for the driver to safely + react. This means that while the system is engaged, the actuators are constrained + to operate within reasonable limits[^1]. + +For additional safety implementation details, refer to [panda safety model](https://github.com/commaai/panda#safety-model). For vehicle specific implementation of the safety concept, refer to [opendbc/safety/safety](https://github.com/commaai/opendbc/tree/master/opendbc/safety/safety). + +[^1]: For these actuator limits we observe ISO11270 and ISO15622. Lateral limits described there translate to 0.9 seconds of maximum actuation to achieve a 1m lateral deviation. + +--- + +### Forks of openpilot + +* Do not disable or nerf [driver monitoring](https://github.com/commaai/openpilot/tree/master/selfdrive/monitoring) +* Do not disable or nerf [excessive actuation checks](https://github.com/commaai/openpilot/tree/master/selfdrive/selfdrived/helpers.py) +* If your fork modifies any of the code in `opendbc/safety/`: + * your fork cannot use the openpilot trademark + * your fork must preserve the full [safety test suite](https://github.com/commaai/opendbc/tree/master/opendbc/safety/tests) and all tests must pass, including any new coverage required by the fork's changes + +Failure to comply with these standards will get you and your users banned from comma.ai servers. + +**comma.ai strongly discourages the use of openpilot forks with safety code either missing or not fully meeting the above requirements.** diff --git a/docs/assets/icon-star-empty.svg b/docs/assets/icon-star-empty.svg new file mode 100644 index 0000000000..5d3c32d671 --- /dev/null +++ b/docs/assets/icon-star-empty.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/docs/assets/icon-star-full.svg b/docs/assets/icon-star-full.svg new file mode 100644 index 0000000000..294db2b7f2 --- /dev/null +++ b/docs/assets/icon-star-full.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/docs/assets/icon-star-half.svg b/docs/assets/icon-star-half.svg new file mode 100644 index 0000000000..ab905fddcb --- /dev/null +++ b/docs/assets/icon-star-half.svg @@ -0,0 +1,66 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/docs/assets/icon-youtube.svg b/docs/assets/icon-youtube.svg new file mode 100644 index 0000000000..4e2c9fdfa9 --- /dev/null +++ b/docs/assets/icon-youtube.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/three-back.svg b/docs/assets/three-back.svg new file mode 100644 index 0000000000..e5e8f9c1fc --- /dev/null +++ b/docs/assets/three-back.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/car-porting/brand-port.md b/docs/car-porting/brand-port.md new file mode 100644 index 0000000000..a3daa7a848 --- /dev/null +++ b/docs/car-porting/brand-port.md @@ -0,0 +1,5 @@ +# Developing a car brand port + +A brand port is a port of openpilot to a substantially new car brand or platform within a brand. + +Here's an example of one: https://github.com/commaai/openpilot/pull/23331. diff --git a/docs/car-porting/model-port.md b/docs/car-porting/model-port.md new file mode 100644 index 0000000000..e148a40ecb --- /dev/null +++ b/docs/car-porting/model-port.md @@ -0,0 +1,5 @@ +# Developing a car model port + +A model port is a port of openpilot to a new car model within an already supported brand. Model ports are easier than brand ports because the car's existing APIs are already known. + +Here's an example of one: https://github.com/commaai/openpilot/pull/30672/. diff --git a/docs/car-porting/what-is-a-car-port.md b/docs/car-porting/what-is-a-car-port.md new file mode 100644 index 0000000000..55cce94da1 --- /dev/null +++ b/docs/car-porting/what-is-a-car-port.md @@ -0,0 +1,39 @@ +# What is a car port? + +A car port enables openpilot support on a particular car. Each car model openpilot supports needs to be individually ported. The complexity of a car port varies depending on many factors including: + +* existing openpilot support for similar cars +* architecture and APIs available in the car + + +# Structure of a car port + +Virtually all car-specific code is contained in two other repositories: [opendbc](https://github.com/commaai/opendbc) and [panda](https://github.com/commaai/panda). + +## opendbc + +Each car brand is supported by a standard interface structure in `opendbc/car/[brand]`: + +* `interface.py`: Interface for the car, defines the CarInterface class +* `carstate.py`: Reads CAN messages from the car and builds openpilot CarState messages +* `carcontroller.py`: Control logic for executing openpilot CarControl actions on the car +* `[brand]can.py`: Composes CAN messages for carcontroller to send +* `values.py`: Limits for actuation, general constants for cars, and supported car documentation +* `radar_interface.py`: Interface for parsing radar points from the car, if applicable + +## panda + +* `board/safety/safety_[brand].h`: Brand-specific safety logic +* `tests/safety/test_[brand].py`: Brand-specific safety CI tests + +## openpilot + +For historical reasons, openpilot still contains a small amount of car-specific logic. This will eventually be migrated to opendbc or otherwise removed. + +* `selfdrive/car/car_specific.py`: Brand-specific event logic + +# Overview + +[Jason Young](https://github.com/jyoung8607) gave a talk at COMMA_CON with an overview of the car porting process. The talk is available on YouTube: + +https://www.youtube.com/watch?v=XxPS5TpTUnI diff --git a/docs/concepts/glossary.md b/docs/concepts/glossary.md new file mode 100644 index 0000000000..a09b0f0785 --- /dev/null +++ b/docs/concepts/glossary.md @@ -0,0 +1,9 @@ +# openpilot glossary + +* **onroad**: openpilot's system state while ignition is on +* **offroad**: openpilot's system state while ignition is off +* **route**: a route is a recording of an onroad session +* **segment**: routes are split into one minute chunks called segments. +* **comma connect**: the web viewer for all your routes; check it out at [connect.comma.ai](https://connect.comma.ai). +* **panda**: this is the secondary processor on the device that implements the functional safety and directly talks to the car over CAN. See the [panda repo](https://github.com/commaai/panda). +* **comma 3X**: the latest hardware by comma.ai for running openpilot. more info at [comma.ai/shop](https://comma.ai/shop). diff --git a/docs/concepts/logs.md b/docs/concepts/logs.md new file mode 100644 index 0000000000..46ab2897df --- /dev/null +++ b/docs/concepts/logs.md @@ -0,0 +1,29 @@ +# Logging + +openpilot records routes in one minute chunks called segments. A route starts on the rising edge of ignition and ends on the falling edge. + +Check out our [Python library](https://github.com/commaai/openpilot/blob/master/tools/lib/logreader.py) for reading openpilot logs. Also checkout our [tools](https://github.com/commaai/openpilot/tree/master/tools) to replay and view your data. These are the same tools we use to debug and develop openpilot. + +For each segment, openpilot records the following log types: + +## rlog.bz2 + +rlogs contain all the messages passed amongst openpilot's processes. See [cereal/services.py](https://github.com/commaai/cereal/blob/master/services.py) for a list of all the logged services. They're a bzip2 archive of the serialized capnproto messages. + +## {f,e,d}camera.hevc + +Each camera stream is H.265 encoded and written to its respective file. + +* `fcamera.hevc` is the road camera +* `ecamera.hevc` is the wide road camera +* `dcamera.hevc` is the driver camera + +## qlog.bz2 & qcamera.ts + +qlogs are a decimated subset of the rlogs. Check out [cereal/services.py](https://github.com/commaai/cereal/blob/master/services.py) for the decimation. + + +qcameras are H.264 encoded, lower res versions of the fcamera.hevc. The video shown in [comma connect](https://connect.comma.ai/) is from the qcameras. + + +qlogs and qcameras are designed to be small enough to upload instantly on slow internet and store forever, yet useful enough for most analysis and debugging. diff --git a/docs/concepts/safety.md b/docs/concepts/safety.md new file mode 120000 index 0000000000..f286ad4b15 --- /dev/null +++ b/docs/concepts/safety.md @@ -0,0 +1 @@ +../SAFETY.md \ No newline at end of file diff --git a/docs/contributing/architecture.md b/docs/contributing/architecture.md new file mode 100644 index 0000000000..c79bec1ac6 --- /dev/null +++ b/docs/contributing/architecture.md @@ -0,0 +1 @@ +# Architecture diff --git a/docs/contributing/roadmap.md b/docs/contributing/roadmap.md new file mode 100644 index 0000000000..1262017a0b --- /dev/null +++ b/docs/contributing/roadmap.md @@ -0,0 +1,31 @@ +# Roadmap + +This is the roadmap for the next major openpilot releases. Also check out + +* [Milestones](https://github.com/commaai/openpilot/milestones) for minor releases +* [Projects](https://github.com/commaai/openpilot/projects?query=is%3Aopen) for shorter-term projects not tied to releases +* [Bounties](https://comma.ai/bounties) for paid individual issues +* [#current-projects](https://discord.com/channels/469524606043160576/1249579909739708446) in Discord for discussion on work-in-progress projects + +## openpilot 0.10 + +openpilot 0.10 will be the first release with a driving policy trained in +a [learned simulator](https://youtu.be/EqQNZXqzFSI). + +* Driving model trained in a learned simulator +* Always-on driver monitoring (behind a toggle) +* GPS removed from the driving stack +* 100KB qlogs +* `nightly` pushed after 1000 hours of hardware-in-the-loop testing +* Car interface code moved into [opendbc](https://github.com/commaai/opendbc) +* openpilot on PC for Linux x86, Linux arm64, and Mac (Apple Silicon) + +## openpilot 1.0 + +openpilot 1.0 will feature a fully end-to-end driving policy. + +* End-to-end longitudinal control in Chill mode +* Automatic Emergency Braking (AEB) +* Driver monitoring with sleep detection +* Rolling updates/releases pushed out by CI +* [panda safety 1.0](https://github.com/orgs/commaai/projects/27) diff --git a/docs/css/tooltip.css b/docs/css/tooltip.css new file mode 100644 index 0000000000..b9a54f793f --- /dev/null +++ b/docs/css/tooltip.css @@ -0,0 +1,44 @@ +[data-tooltip] { + position: relative; + display: inline-block; + border-bottom: 1px dotted black; +} + +[data-tooltip] .tooltip-content { + width: max-content; + max-width: 25em; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + background-color: white; + color: #404040; + box-shadow: 0 4px 14px 0 rgba(0,0,0,.2), 0 0 0 1px rgba(0,0,0,.05); + padding: 10px; + font: 14px/1.5 Lato, proxima-nova, Helvetica Neue, Arial, sans-serif; + text-decoration: none; + opacity: 0; + visibility: hidden; + transition: opacity 0.1s, visibility 0s; + z-index: 1000; + pointer-events: none; /* Prevent accidental interaction */ +} + +[data-tooltip]:hover .tooltip-content { + opacity: 1; + visibility: visible; + pointer-events: auto; /* Allow interaction when visible */ +} + +.tooltip-content .tooltip-glossary-link { + display: inline-block; + margin-top: 8px; + font-size: 12px; + color: #007bff; + text-decoration: none; +} + +.tooltip-content .tooltip-glossary-link:hover { + color: #0056b3; + text-decoration: underline; +} diff --git a/docs/getting-started/what-is-openpilot.md b/docs/getting-started/what-is-openpilot.md new file mode 100644 index 0000000000..b3c56c8410 --- /dev/null +++ b/docs/getting-started/what-is-openpilot.md @@ -0,0 +1,12 @@ +# What is openpilot? + +[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](https://github.com/commaai/openpilot/blob/master/docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](https://github.com/commaai/openpilot/blob/master/docs/INTEGRATION.md) and [limitations](https://github.com/commaai/openpilot/blob/master/docs/LIMITATIONS.md). + + +## How do I use it? + +openpilot is designed to be used on the comma 3X. + +## How does it work? + +In short, openpilot uses the car's existing APIs for the built-in [ADAS](https://en.wikipedia.org/wiki/Advanced_driver-assistance_system) system and simply provides better acceleration, braking, and steering inputs than the stock system. diff --git a/docs/glossary.toml b/docs/glossary.toml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/hooks/glossary.py b/docs/hooks/glossary.py new file mode 100644 index 0000000000..e2fa3d51e0 --- /dev/null +++ b/docs/hooks/glossary.py @@ -0,0 +1,68 @@ +import re +import tomllib + +def load_glossary(file_path="docs/glossary.toml"): + with open(file_path, "rb") as f: + glossary_data = tomllib.load(f) + return glossary_data.get("glossary", {}) + +def generate_anchor_id(name): + return name.replace(" ", "-").replace("_", "-").lower() + +def format_markdown_term(name, definition): + anchor_id = generate_anchor_id(name) + markdown = f"* [**{name.replace('_', ' ').title()}**](#{anchor_id})" + if definition.get("abbreviation"): + markdown += f" *({definition['abbreviation']})*" + if definition.get("description"): + markdown += f": {definition['description']}\n" + return markdown + +def glossary_markdown(vocabulary): + markdown = "" + for category, terms in vocabulary.items(): + markdown += f"## {category.replace('_', ' ').title()}\n\n" + for name, definition in terms.items(): + markdown += format_markdown_term(name, definition) + return markdown + +def format_tooltip_html(term_key, definition, html): + display_term = term_key.replace("_", " ").title() + clean_description = re.sub(r"\[(.+)]\(.+\)", r"\1", definition["description"]) + glossary_link = ( + f"Glossary🔗" + ) + return re.sub( + re.escape(display_term), + lambda + match: f"{match.group(0)}{clean_description} {glossary_link}", + html, + flags=re.IGNORECASE, + ) + +def apply_tooltip(_term_key, _definition, pattern, html): + return re.sub( + pattern, + lambda match: format_tooltip_html(_term_key, _definition, match.group(0)), + html, + flags=re.IGNORECASE, + ) + +def tooltip_html(vocabulary, html): + for _category, terms in vocabulary.items(): + for term_key, definition in terms.items(): + if definition.get("description"): + pattern = rf"(?)(?!\([^)]*\))" + html = apply_tooltip(term_key, definition, pattern, html) + return html + +# Page Hooks +def on_page_markdown(markdown, **kwargs): + glossary = load_glossary() + return markdown.replace("{{GLOSSARY_DEFINITIONS}}", glossary_markdown(glossary)) + +def on_page_content(html, **kwargs): + if kwargs.get("page").title == "Glossary": + return html + glossary = load_glossary() + return tooltip_html(glossary, html) diff --git a/docs/how-to/connect-to-comma.md b/docs/how-to/connect-to-comma.md new file mode 100644 index 0000000000..5f02e11599 --- /dev/null +++ b/docs/how-to/connect-to-comma.md @@ -0,0 +1,99 @@ +# connect to a comma 3X + +A comma 3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console). + +## Serial Console + +On both the comma three and 3X, the serial console is accessible from the main OBD-C port. +Connect the comma 3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power. + +On the comma three, the serial console is exposed through a UART-to-USB chip, and `tools/scripts/serial.sh` can be used to connect. + +On the comma 3X, the serial console is accessible through the [panda](https://github.com/commaai/panda) using the `panda/tests/som_debug.sh` script. + + * Username: `comma` + * Password: `comma` + +## SSH + +In order to SSH into your device, you'll need a GitHub account with SSH keys. See this [GitHub article](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) for getting your account setup with SSH keys. + +* Enable SSH in your device's settings +* Enter your GitHub username in the device's settings +* Connect to your device + * Username: `comma` + * Port: `22` + +Here's an example command for connecting to your device using its tethered connection:
    +`ssh comma@192.168.43.1` + +For doing development work on device, it's recommended to use [SSH agent forwarding](https://docs.github.com/en/developers/overview/using-ssh-agent-forwarding). + + +## ADB + +In order to use ADB on your device, you'll need to perform the following steps using the image below for reference: + +![comma 3/3x back](../assets/three-back.svg) + +* Plug your device into constant power using port 2, letting the device boot up +* Enable ADB in your device's settings +* Plug in your device to your PC using port 1 +* Connect to your device + * `adb shell` over USB + * `adb connect` over WiFi + * Here's an example command for connecting to your device using its tethered connection: `adb connect 192.168.43.1:5555` + +> [!NOTE] +> The default port for ADB is 5555 on the comma 3X. + +For more info on ADB, see the [Android Debug Bridge (ADB) documentation](https://developer.android.com/tools/adb). + +### Notes + +The public keys are only fetched from your GitHub account once. In order to update your device's authorized keys, you'll need to re-enter your GitHub username. + +The `id_rsa` key in this directory only works while your device is in the setup state with no software installed. After installation, that default key will be removed. + +#### ssh.comma.ai proxy + +With a [comma prime subscription](https://comma.ai/connect), you can SSH into your comma device from anywhere. + +With the below SSH configuration, you can type `ssh comma-{dongleid}` to connect to your device through `ssh.comma.ai`. + +``` +Host comma-* + Port 22 + User comma + IdentityFile ~/.ssh/my_github_key + ProxyCommand ssh %h@ssh.comma.ai -W %h:%p + +Host ssh.comma.ai + Hostname ssh.comma.ai + Port 22 + IdentityFile ~/.ssh/my_github_key +``` + +### One-off connection + +``` +ssh -i ~/.ssh/my_github_key -o ProxyCommand="ssh -i ~/.ssh/my_github_key -W %h:%p -p %p %h@ssh.comma.ai" comma@ffffffffffffffff +``` +(Replace `ffffffffffffffff` with your dongle_id) + +### ssh.comma.ai host key fingerprint + +``` +Host key fingerprint is SHA256:X22GOmfjGb9J04IA2+egtdaJ7vW9Fbtmpz9/x8/W1X4 ++---[RSA 4096]----+ +| | +| | +| . | +| + o | +| S = + +..| +| + @ = .=| +| . B @ ++=| +| o * B XE| +| .o o OB/| ++----[SHA256]-----+ +``` diff --git a/docs/how-to/replay-a-drive.md b/docs/how-to/replay-a-drive.md new file mode 100644 index 0000000000..b0db36a46f --- /dev/null +++ b/docs/how-to/replay-a-drive.md @@ -0,0 +1,14 @@ +# Replay + +Replaying is a critical tool for openpilot development and debugging. + +## Replaying a route +*Hardware required: none* + +Just run `tools/replay/replay --demo`. + +## Replaying CAN data +*Hardware required: jungle and comma 3X* + +1. Connect your PC to a jungle. +2. diff --git a/docs/how-to/turn-the-speed-blue.md b/docs/how-to/turn-the-speed-blue.md new file mode 100644 index 0000000000..eb6e75afa2 --- /dev/null +++ b/docs/how-to/turn-the-speed-blue.md @@ -0,0 +1,114 @@ +# Turn the speed blue +*A getting started guide for openpilot development* + +In 30 minutes, we'll get an openpilot development environment set up on your computer and make some changes to openpilot's UI. + +And if you have a comma 3X, we'll deploy the change to your device for testing. + +## 1. Set up your development environment + +Run this to clone openpilot and install all the dependencies: +```bash +bash <(curl -fsSL openpilot.comma.ai) +``` + +Navigate to openpilot folder & activate a Python virtual environment +```bash +cd openpilot +source .venv/bin/activate +``` + +Then, compile openpilot: +```bash +scons -j$(nproc) +``` + +## 2. Run replay + +We'll run the `replay` tool with the demo route to get data streaming for testing our UI changes. +```bash +# in terminal 1 +tools/replay/replay --demo + +# in terminal 2 +selfdrive/ui/ui +``` + +The openpilot UI should launch and show a replay of the demo route. + +If you have your own comma device, you can replace `--demo` with one of your own routes from comma connect. + + +## 3. Make the speed blue + +Now let’s update the speed display color in the UI. + +Search for the function responsible for rendering UI text: +```bash +git grep "drawText" selfdrive/ui/qt/onroad/hud.cc +``` + +You’ll find the relevant code inside `selfdrive/ui/qt/onroad/hud.cc`, in this function: + +```cpp +void HudRenderer::drawText(QPainter &p, int x, int y, const QString &text, int alpha) { + QRect real_rect = p.fontMetrics().boundingRect(text); + real_rect.moveCenter({x, y - real_rect.height() / 2}); + + p.setPen(QColor(0xff, 0xff, 0xff, alpha)); // <- this sets the speed text color + p.drawText(real_rect.x(), real_rect.bottom(), text); +} +``` + +Change the `QColor(...)` line to make it **blue** instead of white. A nice soft blue is `#8080FF`, which translates to: + +```diff +- p.setPen(QColor(0xff, 0xff, 0xff, alpha)); ++ p.setPen(QColor(0x80, 0x80, 0xFF, alpha)); +``` + +This change will tint all speed-related UI text to blue with the same transparency (`alpha`). + +--- + +## 4. Rebuild the UI + +After making changes, rebuild Openpilot so your new UI is compiled: +```bash +scons -j$(nproc) && selfdrive/ui/ui +``` +![](https://blog.comma.ai/img/blue_speed_ui.png) + +You should now see the speed displayed in a nice blue shade during the demo replay. + +--- + +## 5. Push your fork to GitHub + +Click **"Fork"** on the [Openpilot GitHub repo](https://github.com/commaai/openpilot). Then push with: +```bash +git remote rm origin +git remote add origin git@github.com:/openpilot.git +git add . +git commit -m "Make the speed display blue" +git push --set-upstream origin master +``` + +--- + +## 6. Run your fork on your comma device + +Uninstall Openpilot through the settings on your device. + +Then reinstall using your own GitHub-hosted fork: +``` +installer.comma.ai//master +``` + +--- + +## 7. Admire your work IRL 🚗💨 + +You’ve now successfully modified Openpilot’s UI and deployed it to your own car! + +![](https://blog.comma.ai/img/c3_blue_ui.jpg) diff --git a/docs/index.md b/docs/index.md new file mode 120000 index 0000000000..74ea27aeeb --- /dev/null +++ b/docs/index.md @@ -0,0 +1 @@ +getting-started/what-is-openpilot.md \ No newline at end of file diff --git a/git_src_commit b/git_src_commit new file mode 100644 index 0000000000..8508037585 --- /dev/null +++ b/git_src_commit @@ -0,0 +1 @@ +31801a73121b729d11a7dd4a7ccd9698f4d8fc92 \ No newline at end of file diff --git a/git_src_commit_date b/git_src_commit_date new file mode 100644 index 0000000000..12cfb8a2e4 --- /dev/null +++ b/git_src_commit_date @@ -0,0 +1 @@ +1759571245 2025-10-04 02:47:25 -0700 \ No newline at end of file diff --git a/launch_chffrplus.sh b/launch_chffrplus.sh new file mode 100755 index 0000000000..d4689aae53 --- /dev/null +++ b/launch_chffrplus.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +source "$DIR/launch_env.sh" + +function agnos_init { + # TODO: move this to agnos + sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta + + # set success flag for current boot slot + sudo abctl --set_success + + # TODO: do this without udev in AGNOS + # udev does this, but sometimes we startup faster + sudo chgrp gpu /dev/adsprpc-smd /dev/ion /dev/kgsl-3d0 + sudo chmod 660 /dev/adsprpc-smd /dev/ion /dev/kgsl-3d0 + + # Check if AGNOS update is required + if [ $(< /VERSION) != "$AGNOS_VERSION" ]; then + AGNOS_PY="$DIR/system/hardware/tici/agnos.py" + MANIFEST="$DIR/system/hardware/tici/agnos.json" + if $AGNOS_PY --verify $MANIFEST; then + sudo reboot + fi + $DIR/system/hardware/tici/updater $AGNOS_PY $MANIFEST + fi +} + +function launch { + # Remove orphaned git lock if it exists on boot + [ -f "$DIR/.git/index.lock" ] && rm -f $DIR/.git/index.lock + + # Check to see if there's a valid overlay-based update available. Conditions + # are as follows: + # + # 1. The DIR init file has to exist, with a newer modtime than anything in + # the DIR Git repo. This checks for local development work or the user + # switching branches/forks, which should not be overwritten. + # 2. The FINALIZED consistent file has to exist, indicating there's an update + # that completed successfully and synced to disk. + + if [ -f "${DIR}/.overlay_init" ]; then + find ${DIR}/.git -newer ${DIR}/.overlay_init | grep -q '.' 2> /dev/null + if [ $? -eq 0 ]; then + echo "${DIR} has been modified, skipping overlay update installation" + else + if [ -f "${STAGING_ROOT}/finalized/.overlay_consistent" ]; then + if [ ! -d /data/safe_staging/old_openpilot ]; then + echo "Valid overlay update found, installing" + LAUNCHER_LOCATION="${BASH_SOURCE[0]}" + + mv $DIR /data/safe_staging/old_openpilot + mv "${STAGING_ROOT}/finalized" $DIR + cd $DIR + + echo "Restarting launch script ${LAUNCHER_LOCATION}" + unset AGNOS_VERSION + exec "${LAUNCHER_LOCATION}" + else + echo "openpilot backup found, not updating" + # TODO: restore backup? This means the updater didn't start after swapping + fi + fi + fi + fi + + # handle pythonpath + ln -sfn $(pwd) /data/pythonpath + export PYTHONPATH="$PWD" + + # hardware specific init + if [ -f /AGNOS ]; then + agnos_init + fi + + # write tmux scrollback to a file + tmux capture-pane -pq -S-1000 > /tmp/launch_log + + # start manager + cd system/manager + if [ ! -f $DIR/prebuilt ]; then + ./build.py + fi + ./manager.py + + # if broken, keep on screen error + while true; do sleep 1; done +} + +launch diff --git a/launch_env.sh b/launch_env.sh new file mode 100755 index 0000000000..67dd5ee795 --- /dev/null +++ b/launch_env.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +export OMP_NUM_THREADS=1 +export MKL_NUM_THREADS=1 +export NUMEXPR_NUM_THREADS=1 +export OPENBLAS_NUM_THREADS=1 +export VECLIB_MAXIMUM_THREADS=1 + +if [ -z "$AGNOS_VERSION" ]; then + export AGNOS_VERSION="13.1" +fi + +export STAGING_ROOT="/data/safe_staging" diff --git a/launch_openpilot.sh b/launch_openpilot.sh new file mode 100755 index 0000000000..d6e3424c34 --- /dev/null +++ b/launch_openpilot.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +exec ./launch_chffrplus.sh diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000000..550f807aca --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,44 @@ +site_name: openpilot docs +repo_url: https://github.com/commaai/openpilot/ +site_url: https://docs.comma.ai + +exclude_docs: README.md + +strict: true +docs_dir: docs +site_dir: docs_site/ + +hooks: + - docs/hooks/glossary.py +extra_css: + - css/tooltip.css +theme: + name: readthedocs + navigation_depth: 3 + +nav: + - Getting Started: + - What is openpilot?: getting-started/what-is-openpilot.md + - How-to: + - Turn the speed blue: how-to/turn-the-speed-blue.md + - Connect to a comma 3X: how-to/connect-to-comma.md + # - Make your first pull request: how-to/make-first-pr.md + #- Replay a drive: how-to/replay-a-drive.md + - Concepts: + - Logs: concepts/logs.md + - Safety: concepts/safety.md + - Glossary: concepts/glossary.md + - Car Porting: + - What is a car port?: car-porting/what-is-a-car-port.md + - Porting a car brand: car-porting/brand-port.md + - Porting a car model: car-porting/model-port.md + - Contributing: + - Roadmap: contributing/roadmap.md + #- Architecture: contributing/architecture.md + - Contributing Guide →: https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md + - Links: + - Blog →: https://blog.comma.ai + - Bounties →: https://comma.ai/bounties + - GitHub →: https://github.com/commaai + - Discord →: https://discord.comma.ai + - X →: https://x.com/comma_ai diff --git a/msgq b/msgq new file mode 120000 index 0000000000..df09146f62 --- /dev/null +++ b/msgq @@ -0,0 +1 @@ +msgq_repo/msgq \ No newline at end of file diff --git a/msgq_repo/.gitignore b/msgq_repo/.gitignore new file mode 100644 index 0000000000..324effb5b6 --- /dev/null +++ b/msgq_repo/.gitignore @@ -0,0 +1,19 @@ +/gen/ +*.tmp +*.pyc +__pycache__ +.*.swp +.*.swo +*.os +*.so +*.o +*.a +uv.lock +catch2/ + +test_runner + +libmessaging.* +libmessaging_shared.* +.sconsign.dblite +.mypy_cache/ \ No newline at end of file diff --git a/msgq_repo/.pre-commit-config.yaml b/msgq_repo/.pre-commit-config.yaml new file mode 100644 index 0000000000..60271fafe6 --- /dev/null +++ b/msgq_repo/.pre-commit-config.yaml @@ -0,0 +1,49 @@ +files: ^msgq/ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-ast + - id: check-yaml + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.17.1 + hooks: + - id: mypy +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.12 + hooks: + - id: ruff +- repo: local + hooks: + - id: cppcheck + name: cppcheck + entry: cppcheck + language: system + types: [c++] + exclude: '^(msgq/msgq_tests.cc|msgq/test_runner.cc)' + args: + - --error-exitcode=1 + - --inline-suppr + - --language=c++ + - --force + - --quiet + - -j4 + - --check-level=exhaustive +- repo: https://github.com/cpplint/cpplint + rev: 2.0.2 + hooks: + - id: cpplint + args: + - --quiet + - --counting=detailed + - --linelength=240 + - --filter=-build,-legal,-readability,-runtime,-whitespace,+build/include_subdir,+build/forward_decl,+build/include_what_you_use,+build/deprecated,+whitespace/comma,+whitespace/line_length,+whitespace/empty_if_body,+whitespace/empty_loop_body,+whitespace/empty_conditional_body,+whitespace/forcolon,+whitespace/parens,+whitespace/semicolon,+whitespace/tab,+readability/braces +- repo: https://github.com/codespell-project/codespell + rev: v2.4.1 + hooks: + - id: codespell + args: + - -L ned + - --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US diff --git a/msgq_repo/README.md b/msgq_repo/README.md new file mode 100644 index 0000000000..dc10530e0a --- /dev/null +++ b/msgq_repo/README.md @@ -0,0 +1,54 @@ +# MSGQ: A lock free single producer multi consumer message queue + +## What is this library? +MSGQ is a generic high performance IPC pub sub system with a single publisher and multiple subscribers. MSGQ is designed to be a high performance replacement for ZMQ-like SUB/PUB patterns. It uses a ring buffer in shared memory to efficiently read and write data. Each read requires a copy. Writing can be done without a copy, as long as the size of the data is known in advance. While MSGQ is the core of this library, this library also allows replacing the MSGQ backend with ZMQ or a spoofed implementation that can be used for deterministic testing. This library also contains visionipc, an IPC system specifically for large contiguous buffers (like images/video). + +## Storage +The storage for the queue consists of an area of metadata, and the actual buffer. The metadata contains: + +1. A counter to the number of readers that are active +2. A pointer to the head of the queue for writing. From now on referred to as *write pointer* +3. A cycle counter for the writer. This counter is incremented when the writer wraps around +4. N pointers, pointing to the current read position for all the readers. From now on referred to as *read pointer* +5. N counters, counting the number of cycles for all the readers +6. N booleans, indicating validity for all the readers. From now on referred to as *validity flag* + +The counter and the pointer are both 32 bit values, packed into 64 bit so they can be read and written atomically. + +The data buffer is a ring buffer. All messages are prefixed by an 8 byte size field, followed by the data. A size of -1 indicates a wrap-around, and means the next message is stored at the beginning of the buffer. + + +## Writing +Writing involves the following steps: + +1. Check if the area that is to be written overlaps with any of the read pointers, mark those readers as invalid by clearing the validity flag. +2. Write the message +3. Increase the write pointer by the size of the message + +In case there is not enough space at the end of the buffer, a special empty message with a prefix of -1 is written. The cycle counter is incremented by one. In this case step 1 will check there are no read pointers pointing to the remainder of the buffer. Then another write cycle will start with the actual message. + +There always needs to be 8 bytes of empty space at the end of the buffer. By doing this there is always space to write the -1. + +## Reset reader +When the reader is lagging too much behind the read pointer becomes invalid and no longer points to the beginning of a valid message. To reset a reader to the current write pointer, the following steps are performed: + +1. Set valid flag +2. Set read cycle counter to that of the writer +3. Set read pointer to write pointer + +## Reading +Reading involves the following steps: + +1. Read the size field at the current read pointer +2. Read the validity flag +3. Copy the data out of the buffer +4. Increase the read pointer by the size of the message +5. Check the validity flag again + +Before starting the copy, the valid flag is checked. This is to prevent a race condition where the size prefix was invalid, and the read could read outside of the buffer. Make sure that step 1 and 2 are not reordered by your compiler or CPU. + +If a writer overwrites the data while it's being copied out, the data will be invalid. Therefore the validity flag is also checked after reading it. The order of step 4 and 5 does not matter. + +If at steps 2 or 5 the validity flag is not set, the reader is reset. Any data that was already read is discarded. After the reader is reset, the reading starts from the beginning. + +If a message with size -1 is encountered, step 3 and 4 are replaced by increasing the cycle counter and setting the read pointer to the beginning of the buffer. After that another read is performed. diff --git a/msgq_repo/SConscript b/msgq_repo/SConscript new file mode 100644 index 0000000000..147eb30425 --- /dev/null +++ b/msgq_repo/SConscript @@ -0,0 +1,48 @@ +Import('env', 'envCython', 'arch', 'common') + + +visionipc_dir = Dir('msgq/visionipc') +gen_dir = Dir('gen') + + +# Build msgq +msgq_objects = env.SharedObject([ + 'msgq/ipc.cc', + 'msgq/event.cc', + 'msgq/impl_zmq.cc', + 'msgq/impl_msgq.cc', + 'msgq/impl_fake.cc', + 'msgq/msgq.cc', +]) +msgq = env.Library('msgq', msgq_objects) +msgq_python = envCython.Program('msgq/ipc_pyx.so', 'msgq/ipc_pyx.pyx', LIBS=envCython["LIBS"]+[msgq, "zmq", common]) + +# Build Vision IPC +vipc_files = ['visionipc.cc', 'visionipc_server.cc', 'visionipc_client.cc', 'visionbuf.cc'] +vipc_sources = [f'{visionipc_dir.abspath}/{f}' for f in vipc_files] + +if arch == "larch64": + vipc_sources += [f'{visionipc_dir.abspath}/visionbuf_ion.cc'] +else: + vipc_sources += [f'{visionipc_dir.abspath}/visionbuf_cl.cc'] + +vipc_objects = env.SharedObject(vipc_sources) +visionipc = env.Library('visionipc', vipc_objects) + + +vipc_frameworks = [] +vipc_libs = envCython["LIBS"] + [visionipc, msgq, common, "zmq"] +if arch == "Darwin": + vipc_frameworks.append('OpenCL') +else: + vipc_libs.append('OpenCL') +envCython.Program(f'{visionipc_dir.abspath}/visionipc_pyx.so', f'{visionipc_dir.abspath}/visionipc_pyx.pyx', + LIBS=vipc_libs, FRAMEWORKS=vipc_frameworks) + +if GetOption('extras'): + env.Program('msgq/test_runner', ['msgq/test_runner.cc', 'msgq/msgq_tests.cc'], LIBS=[msgq, common]) + env.Program(f'{visionipc_dir.abspath}/test_runner', + [f'{visionipc_dir.abspath}/test_runner.cc', f'{visionipc_dir.abspath}/visionipc_tests.cc'], + LIBS=['pthread'] + vipc_libs, FRAMEWORKS=vipc_frameworks) + +Export('visionipc', 'msgq', 'msgq_python') diff --git a/msgq_repo/SConstruct b/msgq_repo/SConstruct new file mode 100644 index 0000000000..476672be5c --- /dev/null +++ b/msgq_repo/SConstruct @@ -0,0 +1,91 @@ +import os +import platform +import subprocess +import sysconfig +import numpy as np + +arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() +if platform.system() == "Darwin": + arch = "Darwin" + +common = '' + +cpppath = [ + f"#/", + '#msgq/', + '/usr/lib/include', + '/opt/homebrew/include', + sysconfig.get_paths()['include'], +] + +libpath = [ + '/opt/homebrew/lib', +] + +AddOption('--minimal', + action='store_false', + dest='extras', + default=True, + help='the minimum build. no tests, tools, etc.') + +AddOption('--asan', + action='store_true', + help='turn on ASAN') + +AddOption('--ubsan', + action='store_true', + help='turn on UBSan') + +ccflags = [] +ldflags = [] +if GetOption('ubsan'): + flags = [ + "-fsanitize=undefined", + "-fno-sanitize-recover=undefined", + ] + ccflags += flags + ldflags += flags +elif GetOption('asan'): + ccflags += ["-fsanitize=address", "-fno-omit-frame-pointer"] + ldflags += ["-fsanitize=address"] + +env = Environment( + ENV=os.environ, + CC='clang', + CXX='clang++', + CCFLAGS=[ + "-g", + "-fPIC", + "-O2", + "-Wunused", + "-Werror", + "-Wshadow", + "-Wno-vla-cxx-extension", + "-Wno-unknown-warning-option", + ] + ccflags, + LDFLAGS=ldflags, + LINKFLAGS=ldflags, + + CFLAGS="-std=gnu11", + CXXFLAGS="-std=c++1z", + CPPPATH=cpppath, + LIBPATH=libpath, + CYTHONCFILESUFFIX=".cpp", + tools=["default", "cython"] +) + +Export('env', 'arch', 'common') + +envCython = env.Clone(LIBS=[]) +envCython["CPPPATH"] += [np.get_include()] +envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-shadow", "-Wno-deprecated-declarations"] +envCython["CCFLAGS"].remove('-Werror') +if arch == "Darwin": + envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] +else: + envCython["LINKFLAGS"] = ["-pthread", "-shared"] + +Export('envCython') + + +SConscript(['SConscript']) diff --git a/msgq_repo/codecov.yml b/msgq_repo/codecov.yml new file mode 100644 index 0000000000..83427c3ee8 --- /dev/null +++ b/msgq_repo/codecov.yml @@ -0,0 +1,8 @@ +comment: false +coverage: + status: + project: + default: + informational: true + patch: off + diff --git a/msgq_repo/msgq/.gitignore b/msgq_repo/msgq/.gitignore new file mode 100644 index 0000000000..6bd751773b --- /dev/null +++ b/msgq_repo/msgq/.gitignore @@ -0,0 +1 @@ +ipc_pyx.cpp diff --git a/msgq_repo/msgq/__init__.py b/msgq_repo/msgq/__init__.py new file mode 100644 index 0000000000..340a1254e3 --- /dev/null +++ b/msgq_repo/msgq/__init__.py @@ -0,0 +1,61 @@ +# must be built with scons +from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \ + set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event +from msgq.ipc_pyx import MultiplePublishersError, IpcError + +from typing import Optional, List + +assert MultiplePublishersError +assert IpcError +assert toggle_fake_events +assert set_fake_prefix +assert get_fake_prefix +assert delete_fake_prefix +assert wait_for_one_event + +NO_TRAVERSAL_LIMIT = 2**64-1 + +context = Context() + + +def fake_event_handle(endpoint: str, identifier: Optional[str] = None, override: bool = True, enable: bool = False) -> SocketEventHandle: + identifier = identifier or get_fake_prefix() + handle = SocketEventHandle(endpoint, identifier, override) + if override: + handle.enabled = enable + + return handle + +def pub_sock(endpoint: str) -> PubSocket: + sock = PubSocket() + sock.connect(context, endpoint) + return sock + + +def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1", + conflate: bool = False, timeout: Optional[int] = None) -> SubSocket: + sock = SubSocket() + sock.connect(context, endpoint, addr.encode('utf8'), conflate) + + if timeout is not None: + sock.setTimeout(timeout) + + if poller is not None: + poller.registerSocket(sock) + return sock + +def drain_sock_raw(sock: SubSocket, wait_for_one: bool = False) -> List[bytes]: + """Receive all message currently available on the queue""" + ret: List[bytes] = [] + while 1: + if wait_for_one and len(ret) == 0: + dat = sock.receive() + else: + dat = sock.receive(non_blocking=True) + + if dat is None: + break + + ret.append(dat) + + return ret diff --git a/msgq_repo/msgq/event.cc b/msgq_repo/msgq/event.cc new file mode 100644 index 0000000000..7f1625a334 --- /dev/null +++ b/msgq_repo/msgq/event.cc @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "msgq/event.h" + +#ifndef __APPLE__ +#include + +void event_state_shm_mmap(std::string endpoint, std::string identifier, char **shm_mem, std::string *shm_path) { + const char* op_prefix = std::getenv("OPENPILOT_PREFIX"); + + std::string full_path = "/dev/shm/"; + if (op_prefix) { + full_path += std::string(op_prefix) + "/"; + } + full_path += CEREAL_EVENTS_PREFIX + "/"; + if (identifier.size() > 0) { + full_path += identifier + "/"; + } + std::filesystem::create_directories(full_path); + full_path += endpoint; + + int shm_fd = open(full_path.c_str(), O_RDWR | O_CREAT, 0664); + if (shm_fd < 0) { + throw std::runtime_error("Could not open shared memory file."); + } + + int rc = ftruncate(shm_fd, sizeof(EventState)); + if (rc < 0){ + close(shm_fd); + throw std::runtime_error("Could not truncate shared memory file."); + } + + char * mem = (char*)mmap(NULL, sizeof(EventState), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + close(shm_fd); + if (mem == nullptr) { + throw std::runtime_error("Could not map shared memory file."); + } + + if (shm_mem != nullptr) + *shm_mem = mem; + if (shm_path != nullptr) + *shm_path = full_path; +} + +SocketEventHandle::SocketEventHandle(std::string endpoint, std::string identifier, bool override) { + char *mem; + event_state_shm_mmap(endpoint, identifier, &mem, &this->shm_path); + + this->state = (EventState*)mem; + if (override) { + this->state->fds[0] = eventfd(0, EFD_NONBLOCK); + this->state->fds[1] = eventfd(0, EFD_NONBLOCK); + } +} + +SocketEventHandle::~SocketEventHandle() { + close(this->state->fds[0]); + close(this->state->fds[1]); + munmap(this->state, sizeof(EventState)); + unlink(this->shm_path.c_str()); +} + +bool SocketEventHandle::is_enabled() { + return this->state->enabled; +} + +void SocketEventHandle::set_enabled(bool enabled) { + this->state->enabled = enabled; +} + +Event SocketEventHandle::recv_called() { + return Event(this->state->fds[0]); +} + +Event SocketEventHandle::recv_ready() { + return Event(this->state->fds[1]); +} + +void SocketEventHandle::toggle_fake_events(bool enabled) { + if (enabled) + setenv("CEREAL_FAKE", "1", true); + else + unsetenv("CEREAL_FAKE"); +} + +void SocketEventHandle::set_fake_prefix(std::string prefix) { + if (prefix.size() == 0) { + unsetenv("CEREAL_FAKE_PREFIX"); + } else { + setenv("CEREAL_FAKE_PREFIX", prefix.c_str(), true); + } +} + +std::string SocketEventHandle::fake_prefix() { + const char* prefix = std::getenv("CEREAL_FAKE_PREFIX"); + if (prefix == nullptr) { + return ""; + } else { + return std::string(prefix); + } +} + +Event::Event(int fd): event_fd(fd) {} + +void Event::set() const { + throw_if_invalid(); + + uint64_t val = 1; + size_t count = write(this->event_fd, &val, sizeof(uint64_t)); + assert(count == sizeof(uint64_t)); +} + +int Event::clear() const { + throw_if_invalid(); + + uint64_t val = 0; + // read the eventfd to clear it + read(this->event_fd, &val, sizeof(uint64_t)); + + return val; +} + +void Event::wait(int timeout_sec) const { + throw_if_invalid(); + + int event_count; + struct pollfd fds = { this->event_fd, POLLIN, 0 }; + struct timespec timeout = { timeout_sec, 0 };; + + sigset_t signals; + sigfillset(&signals); + sigdelset(&signals, SIGALRM); + sigdelset(&signals, SIGINT); + sigdelset(&signals, SIGTERM); + sigdelset(&signals, SIGQUIT); + + event_count = ppoll(&fds, 1, timeout_sec < 0 ? nullptr : &timeout, &signals); + + if (event_count == 0) { + throw std::runtime_error("Event timed out pid: " + std::to_string(getpid())); + } else if (event_count < 0) { + throw std::runtime_error("Event poll failed, errno: " + std::to_string(errno) + " pid: " + std::to_string(getpid())); + } +} + +bool Event::peek() const { + throw_if_invalid(); + + int event_count; + + struct pollfd fds = { this->event_fd, POLLIN, 0 }; + + // poll with timeout zero to return status immediately + event_count = poll(&fds, 1, 0); + + return event_count != 0; +} + +bool Event::is_valid() const { + return event_fd != -1; +} + +int Event::fd() const { + return event_fd; +} + +int Event::wait_for_one(const std::vector& events, int timeout_sec) { + struct pollfd fds[events.size()]; + for (size_t i = 0; i < events.size(); i++) { + fds[i] = { events[i].fd(), POLLIN, 0 }; + } + + struct timespec timeout = { timeout_sec, 0 }; + + sigset_t signals; + sigfillset(&signals); + sigdelset(&signals, SIGALRM); + sigdelset(&signals, SIGINT); + sigdelset(&signals, SIGTERM); + sigdelset(&signals, SIGQUIT); + + int event_count = ppoll(fds, events.size(), timeout_sec < 0 ? nullptr : &timeout, &signals); + + if (event_count == 0) { + throw std::runtime_error("Event timed out pid: " + std::to_string(getpid())); + } else if (event_count < 0) { + throw std::runtime_error("Event poll failed, errno: " + std::to_string(errno) + " pid: " + std::to_string(getpid())); + } + + for (size_t i = 0; i < events.size(); i++) { + if (fds[i].revents & POLLIN) { + return i; + } + } + + throw std::runtime_error("Event poll failed, no events ready"); +} +#else +// Stub implementation for Darwin, which does not support eventfd +void event_state_shm_mmap(std::string endpoint, std::string identifier, char **shm_mem, std::string *shm_path) {} + +SocketEventHandle::SocketEventHandle(std::string endpoint, std::string identifier, bool override) { + std::cerr << "SocketEventHandle not supported on macOS" << std::endl; + assert(false); +} +SocketEventHandle::~SocketEventHandle() {} +bool SocketEventHandle::is_enabled() { return this->state->enabled; } +void SocketEventHandle::set_enabled(bool enabled) {} +Event SocketEventHandle::recv_called() { return Event(); } +Event SocketEventHandle::recv_ready() { return Event(); } +void SocketEventHandle::toggle_fake_events(bool enabled) {} +void SocketEventHandle::set_fake_prefix(std::string prefix) {} +std::string SocketEventHandle::fake_prefix() { return ""; } + +Event::Event(int fd): event_fd(fd) {} +void Event::set() const {} +int Event::clear() const { return 0; } +void Event::wait(int timeout_sec) const {} +bool Event::peek() const { return false; } +bool Event::is_valid() const { return false; } +int Event::fd() const { return this->event_fd; } +int Event::wait_for_one(const std::vector& events, int timeout_sec) { return -1; } +#endif diff --git a/msgq_repo/msgq/event.h b/msgq_repo/msgq/event.h new file mode 100644 index 0000000000..c638b6b4ea --- /dev/null +++ b/msgq_repo/msgq/event.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include + +#define CEREAL_EVENTS_PREFIX std::string("cereal_events") + +void event_state_shm_mmap(std::string endpoint, std::string identifier, char **shm_mem, std::string *shm_path); + +enum EventPurpose { + RECV_CALLED, + RECV_READY +}; + +struct EventState { + int fds[2]; + bool enabled; +}; + +class Event { +private: + int event_fd = -1; + + inline void throw_if_invalid() const { + if (!this->is_valid()) { + throw std::runtime_error("Event does not have valid file descriptor."); + } + } +public: + Event(int fd = -1); + + void set() const; + int clear() const; + void wait(int timeout_sec = -1) const; + bool peek() const; + bool is_valid() const; + int fd() const; + + static int wait_for_one(const std::vector& events, int timeout_sec = -1); +}; + +class SocketEventHandle { +private: + std::string shm_path; + EventState* state; +public: + SocketEventHandle(std::string endpoint, std::string identifier = "", bool override = true); + ~SocketEventHandle(); + + bool is_enabled(); + void set_enabled(bool enabled); + Event recv_called(); + Event recv_ready(); + + static void toggle_fake_events(bool enabled); + static void set_fake_prefix(std::string prefix); + static std::string fake_prefix(); +}; diff --git a/msgq_repo/msgq/impl_fake.cc b/msgq_repo/msgq/impl_fake.cc new file mode 100644 index 0000000000..6829901093 --- /dev/null +++ b/msgq_repo/msgq/impl_fake.cc @@ -0,0 +1,10 @@ +#include +#include "msgq/impl_fake.h" + +void FakePoller::registerSocket(SubSocket *socket) { + this->sockets.push_back(socket); +} + +std::vector FakePoller::poll(int timeout) { + return this->sockets; +} diff --git a/msgq_repo/msgq/impl_fake.h b/msgq_repo/msgq/impl_fake.h new file mode 100644 index 0000000000..2c3b74dc9a --- /dev/null +++ b/msgq_repo/msgq/impl_fake.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "msgq/ipc.h" +#include "msgq/event.h" + +template +class FakeSubSocket: public TSubSocket { +private: + Event *recv_called = nullptr; + Event *recv_ready = nullptr; + EventState *state = nullptr; + +public: + FakeSubSocket(): TSubSocket() {} + ~FakeSubSocket() { + delete recv_called; + delete recv_ready; + if (state != nullptr) { + munmap(state, sizeof(EventState)); + } + } + + int connect(Context *context, std::string endpoint, std::string address, bool conflate=false, bool check_endpoint=true) override { + const char* cereal_prefix = std::getenv("CEREAL_FAKE_PREFIX"); + + char* mem; + std::string identifier = cereal_prefix != nullptr ? std::string(cereal_prefix) : ""; + event_state_shm_mmap(endpoint, identifier, &mem, nullptr); + + this->state = (EventState*)mem; + this->recv_called = new Event(state->fds[EventPurpose::RECV_CALLED]); + this->recv_ready = new Event(state->fds[EventPurpose::RECV_READY]); + + return TSubSocket::connect(context, endpoint, address, conflate, check_endpoint); + } + + Message *receive(bool non_blocking=false) override { + if (this->state->enabled) { + this->recv_called->set(); + this->recv_ready->wait(); + this->recv_ready->clear(); + } + + return TSubSocket::receive(non_blocking); + } +}; + +class FakePoller: public Poller { +private: + std::vector sockets; + +public: + void registerSocket(SubSocket *socket) override; + std::vector poll(int timeout) override; + ~FakePoller() {} +}; diff --git a/msgq_repo/msgq/impl_msgq.cc b/msgq_repo/msgq/impl_msgq.cc new file mode 100644 index 0000000000..12725e52f9 --- /dev/null +++ b/msgq_repo/msgq/impl_msgq.cc @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "msgq/impl_msgq.h" + +MSGQContext::MSGQContext() { +} + +MSGQContext::~MSGQContext() { +} + +void MSGQMessage::init(size_t sz) { + size = sz; + data = new char[size]; +} + +void MSGQMessage::init(char * d, size_t sz) { + size = sz; + data = new char[size]; + memcpy(data, d, size); +} + +void MSGQMessage::takeOwnership(char * d, size_t sz) { + size = sz; + data = d; +} + +void MSGQMessage::close() { + if (size > 0){ + delete[] data; + } + size = 0; +} + +MSGQMessage::~MSGQMessage() { + this->close(); +} + +int MSGQSubSocket::connect(Context *context, std::string endpoint, std::string address, bool conflate, bool check_endpoint){ + assert(context); + assert(address == "127.0.0.1"); + + q = new msgq_queue_t; + int r = msgq_new_queue(q, endpoint.c_str(), DEFAULT_SEGMENT_SIZE); + if (r != 0){ + return r; + } + + msgq_init_subscriber(q); + + if (conflate){ + q->read_conflate = true; + } + + timeout = -1; + + return 0; +} + + +Message * MSGQSubSocket::receive(bool non_blocking){ + msgq_msg_t msg; + + MSGQMessage *r = NULL; + + int rc = msgq_msg_recv(&msg, q); + + // Hack to implement blocking read with a poller. Don't use this + while (!non_blocking && rc == 0){ + msgq_pollitem_t items[1]; + items[0].q = q; + + int t = (timeout != -1) ? timeout : 100; + + int n = msgq_poll(items, 1, t); + rc = msgq_msg_recv(&msg, q); + + // The poll indicated a message was ready, but the receive failed. Try again + if (n == 1 && rc == 0){ + continue; + } + + if (timeout != -1){ + break; + } + } + + if (rc > 0){ + r = new MSGQMessage; + r->takeOwnership(msg.data, msg.size); + } + + return (Message*)r; +} + +void MSGQSubSocket::setTimeout(int t){ + timeout = t; +} + +MSGQSubSocket::~MSGQSubSocket(){ + if (q != NULL){ + msgq_close_queue(q); + delete q; + } +} + +int MSGQPubSocket::connect(Context *context, std::string endpoint, bool check_endpoint){ + assert(context); + + // TODO + //if (check_endpoint && !service_exists(std::string(endpoint))){ + // std::cout << "Warning, " << std::string(endpoint) << " is not in service list." << std::endl; + //} + + q = new msgq_queue_t; + int r = msgq_new_queue(q, endpoint.c_str(), DEFAULT_SEGMENT_SIZE); + if (r != 0){ + return r; + } + + msgq_init_publisher(q); + + return 0; +} + +int MSGQPubSocket::sendMessage(Message *message){ + msgq_msg_t msg; + msg.data = message->getData(); + msg.size = message->getSize(); + + return msgq_msg_send(&msg, q); +} + +int MSGQPubSocket::send(char *data, size_t size){ + msgq_msg_t msg; + msg.data = data; + msg.size = size; + + return msgq_msg_send(&msg, q); +} + +bool MSGQPubSocket::all_readers_updated() { + return msgq_all_readers_updated(q); +} + +MSGQPubSocket::~MSGQPubSocket(){ + if (q != NULL){ + msgq_close_queue(q); + delete q; + } +} + + +void MSGQPoller::registerSocket(SubSocket * socket){ + assert(num_polls + 1 < MAX_POLLERS); + polls[num_polls].q = (msgq_queue_t*)socket->getRawSocket(); + + sockets.push_back(socket); + num_polls++; +} + +std::vector MSGQPoller::poll(int timeout){ + std::vector r; + + msgq_poll(polls, num_polls, timeout); + for (size_t i = 0; i < num_polls; i++){ + if (polls[i].revents){ + r.push_back(sockets[i]); + } + } + + return r; +} diff --git a/msgq_repo/msgq/impl_msgq.h b/msgq_repo/msgq/impl_msgq.h new file mode 100644 index 0000000000..4d9db1850f --- /dev/null +++ b/msgq_repo/msgq/impl_msgq.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +#include "msgq/ipc.h" +#include "msgq/msgq.h" + +#define MAX_POLLERS 128 + +class MSGQContext : public Context { +private: + void * context = NULL; +public: + MSGQContext(); + void * getRawContext() {return context;} + ~MSGQContext(); +}; + +class MSGQMessage : public Message { +private: + char * data; + size_t size; +public: + void init(size_t size); + void init(char *data, size_t size); + void takeOwnership(char *data, size_t size); + size_t getSize(){return size;} + char * getData(){return data;} + void close(); + ~MSGQMessage(); +}; + +class MSGQSubSocket : public SubSocket { +private: + msgq_queue_t * q = NULL; + int timeout; +public: + int connect(Context *context, std::string endpoint, std::string address, bool conflate=false, bool check_endpoint=true); + void setTimeout(int timeout); + void * getRawSocket() {return (void*)q;} + Message *receive(bool non_blocking=false); + ~MSGQSubSocket(); +}; + +class MSGQPubSocket : public PubSocket { +private: + msgq_queue_t * q = NULL; +public: + int connect(Context *context, std::string endpoint, bool check_endpoint=true); + int sendMessage(Message *message); + int send(char *data, size_t size); + bool all_readers_updated(); + ~MSGQPubSocket(); +}; + +class MSGQPoller : public Poller { +private: + std::vector sockets; + msgq_pollitem_t polls[MAX_POLLERS]; + size_t num_polls = 0; + +public: + void registerSocket(SubSocket *socket); + std::vector poll(int timeout); + ~MSGQPoller(){} +}; diff --git a/msgq_repo/msgq/impl_zmq.cc b/msgq_repo/msgq/impl_zmq.cc new file mode 100644 index 0000000000..1518be750f --- /dev/null +++ b/msgq_repo/msgq/impl_zmq.cc @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "msgq/impl_zmq.h" + +static size_t fnv1a_hash(const std::string &str) { + const size_t fnv_prime = 0x100000001b3; + size_t hash_value = 0xcbf29ce484222325; + for (char c : str) { + hash_value ^= (unsigned char)c; + hash_value *= fnv_prime; + } + return hash_value; +} + +//FIXME: This is a hack to get the port number from the socket name, might have collisions +static int get_port(std::string endpoint) { + size_t hash_value = fnv1a_hash(endpoint); + int start_port = 8023; + int max_port = 65535; + int port = start_port + (hash_value % (max_port - start_port)); + return port; +} + +ZMQContext::ZMQContext() { + context = zmq_ctx_new(); +} + +ZMQContext::~ZMQContext() { + zmq_ctx_term(context); +} + +void ZMQMessage::init(size_t sz) { + size = sz; + data = new char[size]; +} + +void ZMQMessage::init(char * d, size_t sz) { + size = sz; + data = new char[size]; + memcpy(data, d, size); +} + +void ZMQMessage::close() { + if (size > 0){ + delete[] data; + } + size = 0; +} + +ZMQMessage::~ZMQMessage() { + this->close(); +} + + +int ZMQSubSocket::connect(Context *context, std::string endpoint, std::string address, bool conflate, bool check_endpoint){ + sock = zmq_socket(context->getRawContext(), ZMQ_SUB); + if (sock == NULL){ + return -1; + } + + zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0); + + if (conflate){ + int arg = 1; + zmq_setsockopt(sock, ZMQ_CONFLATE, &arg, sizeof(int)); + } + + int reconnect_ivl = 500; + zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &reconnect_ivl, sizeof(reconnect_ivl)); + + + full_endpoint = "tcp://" + address + ":"; + if (check_endpoint){ + full_endpoint += std::to_string(get_port(endpoint)); + } else { + full_endpoint += endpoint; + } + + return zmq_connect(sock, full_endpoint.c_str()); +} + + +Message * ZMQSubSocket::receive(bool non_blocking){ + zmq_msg_t msg; + assert(zmq_msg_init(&msg) == 0); + + int flags = non_blocking ? ZMQ_DONTWAIT : 0; + int rc = zmq_msg_recv(&msg, sock, flags); + Message *r = NULL; + + if (rc >= 0){ + // Make a copy to ensure the data is aligned + r = new ZMQMessage; + r->init((char*)zmq_msg_data(&msg), zmq_msg_size(&msg)); + } + + zmq_msg_close(&msg); + return r; +} + +void ZMQSubSocket::setTimeout(int timeout){ + zmq_setsockopt(sock, ZMQ_RCVTIMEO, &timeout, sizeof(int)); +} + +ZMQSubSocket::~ZMQSubSocket(){ + zmq_close(sock); +} + +int ZMQPubSocket::connect(Context *context, std::string endpoint, bool check_endpoint){ + sock = zmq_socket(context->getRawContext(), ZMQ_PUB); + if (sock == NULL){ + return -1; + } + + full_endpoint = "tcp://*:"; + if (check_endpoint){ + full_endpoint += std::to_string(get_port(endpoint)); + } else { + full_endpoint += endpoint; + } + + // ZMQ pub sockets cannot be shared between processes, so we need to ensure pid stays the same + pid = getpid(); + + return zmq_bind(sock, full_endpoint.c_str()); +} + +int ZMQPubSocket::sendMessage(Message *message) { + assert(pid == getpid()); + return zmq_send(sock, message->getData(), message->getSize(), ZMQ_DONTWAIT); +} + +int ZMQPubSocket::send(char *data, size_t size) { + assert(pid == getpid()); + return zmq_send(sock, data, size, ZMQ_DONTWAIT); +} + +bool ZMQPubSocket::all_readers_updated() { + assert(false); // TODO not implemented + return false; +} + +ZMQPubSocket::~ZMQPubSocket(){ + zmq_close(sock); +} + + +void ZMQPoller::registerSocket(SubSocket * socket){ + assert(num_polls + 1 < MAX_POLLERS); + polls[num_polls].socket = socket->getRawSocket(); + polls[num_polls].events = ZMQ_POLLIN; + + sockets.push_back(socket); + num_polls++; +} + +std::vector ZMQPoller::poll(int timeout){ + std::vector r; + + int rc = zmq_poll(polls, num_polls, timeout); + if (rc < 0){ + return r; + } + + for (size_t i = 0; i < num_polls; i++){ + if (polls[i].revents){ + r.push_back(sockets[i]); + } + } + + return r; +} diff --git a/msgq_repo/msgq/impl_zmq.h b/msgq_repo/msgq/impl_zmq.h new file mode 100644 index 0000000000..718196e306 --- /dev/null +++ b/msgq_repo/msgq/impl_zmq.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include + +#include "msgq/ipc.h" + +#define MAX_POLLERS 128 + +class ZMQContext : public Context { +private: + void * context = NULL; +public: + ZMQContext(); + void * getRawContext() {return context;} + ~ZMQContext(); +}; + +class ZMQMessage : public Message { +private: + char * data; + size_t size; +public: + void init(size_t size); + void init(char *data, size_t size); + size_t getSize(){return size;} + char * getData(){return data;} + void close(); + ~ZMQMessage(); +}; + +class ZMQSubSocket : public SubSocket { +private: + void * sock; + std::string full_endpoint; +public: + int connect(Context *context, std::string endpoint, std::string address, bool conflate=false, bool check_endpoint=true); + void setTimeout(int timeout); + void * getRawSocket() {return sock;} + Message *receive(bool non_blocking=false); + ~ZMQSubSocket(); +}; + +class ZMQPubSocket : public PubSocket { +private: + void * sock; + std::string full_endpoint; + int pid = -1; +public: + int connect(Context *context, std::string endpoint, bool check_endpoint=true); + int sendMessage(Message *message); + int send(char *data, size_t size); + bool all_readers_updated(); + ~ZMQPubSocket(); +}; + +class ZMQPoller : public Poller { +private: + std::vector sockets; + zmq_pollitem_t polls[MAX_POLLERS]; + size_t num_polls = 0; + +public: + void registerSocket(SubSocket *socket); + std::vector poll(int timeout); + ~ZMQPoller(){} +}; diff --git a/msgq_repo/msgq/ipc.cc b/msgq_repo/msgq/ipc.cc new file mode 100644 index 0000000000..e96f4076c1 --- /dev/null +++ b/msgq_repo/msgq/ipc.cc @@ -0,0 +1,121 @@ +#include +#include +#include + +#include "msgq/ipc.h" +#include "msgq/impl_zmq.h" +#include "msgq/impl_msgq.h" +#include "msgq/impl_fake.h" + +#ifdef __APPLE__ +const bool MUST_USE_ZMQ = true; +#else +const bool MUST_USE_ZMQ = false; +#endif + +bool messaging_use_zmq(){ + if (std::getenv("ZMQ") || MUST_USE_ZMQ) { + if (std::getenv("OPENPILOT_PREFIX")) { + std::cerr << "OPENPILOT_PREFIX not supported with ZMQ backend\n"; + assert(false); + } + return true; + } + return false; +} + +bool messaging_use_fake(){ + char* fake_enabled = std::getenv("CEREAL_FAKE"); + return fake_enabled != NULL; +} + +Context * Context::create(){ + Context * c; + if (messaging_use_zmq()){ + c = new ZMQContext(); + } else { + c = new MSGQContext(); + } + return c; +} + +SubSocket * SubSocket::create(){ + SubSocket * s; + if (messaging_use_fake()) { + if (messaging_use_zmq()) { + s = new FakeSubSocket(); + } else { + s = new FakeSubSocket(); + } + } else { + if (messaging_use_zmq()){ + s = new ZMQSubSocket(); + } else { + s = new MSGQSubSocket(); + } + } + + return s; +} + +SubSocket * SubSocket::create(Context * context, std::string endpoint, std::string address, bool conflate, bool check_endpoint){ + SubSocket *s = SubSocket::create(); + int r = s->connect(context, endpoint, address, conflate, check_endpoint); + + if (r == 0) { + return s; + } else { + std::cerr << "Error, failed to connect SubSocket to " << endpoint << ": " << strerror(errno) << std::endl; + + delete s; + return nullptr; + } +} + +PubSocket * PubSocket::create(){ + PubSocket * s; + if (messaging_use_zmq()){ + s = new ZMQPubSocket(); + } else { + s = new MSGQPubSocket(); + } + + return s; +} + +PubSocket * PubSocket::create(Context * context, std::string endpoint, bool check_endpoint){ + PubSocket *s = PubSocket::create(); + int r = s->connect(context, endpoint, check_endpoint); + + if (r == 0) { + return s; + } else { + std::cerr << "Error, failed to bind PubSocket to " << endpoint << ": " << strerror(errno) << std::endl; + + delete s; + return nullptr; + } +} + +Poller * Poller::create(){ + Poller * p; + if (messaging_use_fake()) { + p = new FakePoller(); + } else { + if (messaging_use_zmq()){ + p = new ZMQPoller(); + } else { + p = new MSGQPoller(); + } + } + return p; +} + +Poller * Poller::create(std::vector sockets){ + Poller * p = Poller::create(); + + for (auto s : sockets){ + p->registerSocket(s); + } + return p; +} diff --git a/msgq_repo/msgq/ipc.h b/msgq_repo/msgq/ipc.h new file mode 100644 index 0000000000..1f0e3e06b5 --- /dev/null +++ b/msgq_repo/msgq/ipc.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + + +#ifdef __APPLE__ +#define CLOCK_BOOTTIME CLOCK_MONOTONIC +#endif + +#define MSG_MULTIPLE_PUBLISHERS 100 + +bool messaging_use_zmq(); + +class Context { +public: + virtual void * getRawContext() = 0; + static Context * create(); + virtual ~Context(){} +}; + +class Message { +public: + virtual void init(size_t size) = 0; + virtual void init(char * data, size_t size) = 0; + virtual void close() = 0; + virtual size_t getSize() = 0; + virtual char * getData() = 0; + virtual ~Message(){} +}; + + +class SubSocket { +public: + virtual int connect(Context *context, std::string endpoint, std::string address, bool conflate=false, bool check_endpoint=true) = 0; + virtual void setTimeout(int timeout) = 0; + virtual Message *receive(bool non_blocking=false) = 0; + virtual void * getRawSocket() = 0; + static SubSocket * create(); + static SubSocket * create(Context * context, std::string endpoint, std::string address="127.0.0.1", bool conflate=false, bool check_endpoint=true); + virtual ~SubSocket(){} +}; + +class PubSocket { +public: + virtual int connect(Context *context, std::string endpoint, bool check_endpoint=true) = 0; + virtual int sendMessage(Message *message) = 0; + virtual int send(char *data, size_t size) = 0; + virtual bool all_readers_updated() = 0; + static PubSocket * create(); + static PubSocket * create(Context * context, std::string endpoint, bool check_endpoint=true); + static PubSocket * create(Context * context, std::string endpoint, int port, bool check_endpoint=true); + virtual ~PubSocket(){} +}; + +class Poller { +public: + virtual void registerSocket(SubSocket *socket) = 0; + virtual std::vector poll(int timeout) = 0; + static Poller * create(); + static Poller * create(std::vector sockets); + virtual ~Poller(){} +}; \ No newline at end of file diff --git a/msgq_repo/msgq/ipc.pxd b/msgq_repo/msgq/ipc.pxd new file mode 100644 index 0000000000..6a049708f7 --- /dev/null +++ b/msgq_repo/msgq/ipc.pxd @@ -0,0 +1,68 @@ +# distutils: language = c++ +#cython: language_level=3 + +from libcpp.string cimport string +from libcpp.vector cimport vector +from libcpp cimport bool + + +cdef extern from "msgq/impl_fake.h": + cdef cppclass Event: + @staticmethod + int wait_for_one(vector[Event], int) except + + + Event() + Event(int) + void set() + int clear() + void wait(int) except + + bool peek() + int fd() + + cdef cppclass SocketEventHandle: + @staticmethod + void toggle_fake_events(bool) + @staticmethod + void set_fake_prefix(string) + @staticmethod + string fake_prefix() + + SocketEventHandle(string, string, bool) + bool is_enabled() + void set_enabled(bool) + Event recv_called() + Event recv_ready() + + +cdef extern from "msgq/ipc.h": + cdef cppclass Context: + @staticmethod + Context * create() + + cdef cppclass Message: + void init(size_t) + void init(char *, size_t) + void close() + size_t getSize() + char *getData() + + cdef cppclass SubSocket: + @staticmethod + SubSocket * create() nogil + int connect(Context *, string, string, bool) nogil + Message * receive(bool) nogil + void setTimeout(int) nogil + + cdef cppclass PubSocket: + @staticmethod + PubSocket * create() + int connect(Context *, string) + int sendMessage(Message *) + int send(char *, size_t) + bool all_readers_updated() + + cdef cppclass Poller: + @staticmethod + Poller * create() + void registerSocket(SubSocket *) + vector[SubSocket*] poll(int) nogil diff --git a/msgq_repo/msgq/ipc_pyx.pyx b/msgq_repo/msgq/ipc_pyx.pyx new file mode 100644 index 0000000000..41fd20aa81 --- /dev/null +++ b/msgq_repo/msgq/ipc_pyx.pyx @@ -0,0 +1,251 @@ +# distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + +import sys +from libcpp.string cimport string +from libcpp.vector cimport vector +from libcpp cimport bool +from libc cimport errno +from libc.string cimport strerror +from cython.operator import dereference + + +from .ipc cimport Context as cppContext +from .ipc cimport SubSocket as cppSubSocket +from .ipc cimport PubSocket as cppPubSocket +from .ipc cimport Poller as cppPoller +from .ipc cimport Message as cppMessage +from .ipc cimport Event as cppEvent, SocketEventHandle as cppSocketEventHandle + + +class IpcError(Exception): + def __init__(self, endpoint=None): + suffix = f"with {endpoint.decode('utf-8')}" if endpoint else "" + message = f"Messaging failure {suffix}: {strerror(errno.errno).decode('utf-8')}" + super().__init__(message) + + +class MultiplePublishersError(IpcError): + pass + + +def toggle_fake_events(bool enabled): + cppSocketEventHandle.toggle_fake_events(enabled) + + +def set_fake_prefix(string prefix): + cppSocketEventHandle.set_fake_prefix(prefix) + + +def get_fake_prefix(): + return cppSocketEventHandle.fake_prefix() + + +def delete_fake_prefix(): + cppSocketEventHandle.set_fake_prefix(b"") + + +def wait_for_one_event(list events, int timeout=-1): + cdef vector[cppEvent] items + for event in events: + items.push_back(dereference(event.ptr)) + return cppEvent.wait_for_one(items, timeout) + + +cdef class Event: + cdef cppEvent event; + + def __cinit__(self): + pass + + cdef setEvent(self, cppEvent event): + self.event = event + + def set(self): + self.event.set() + + def clear(self): + return self.event.clear() + + def wait(self, int timeout=-1): + self.event.wait(timeout) + + def peek(self): + return self.event.peek() + + @property + def fd(self): + return self.event.fd() + + @property + def ptr(self): + return &self.event + + +cdef class SocketEventHandle: + cdef cppSocketEventHandle * handle; + + def __cinit__(self, string endpoint, string identifier, bool override): + self.handle = new cppSocketEventHandle(endpoint, identifier, override) + + def __dealloc__(self): + del self.handle + + @property + def enabled(self): + return self.handle.is_enabled() + + @enabled.setter + def enabled(self, bool value): + self.handle.set_enabled(value) + + @property + def recv_called_event(self): + e = Event() + e.setEvent(self.handle.recv_called()) + + return e + + @property + def recv_ready_event(self): + e = Event() + e.setEvent(self.handle.recv_ready()) + + return e + + +cdef class Context: + cdef cppContext * context + + def __cinit__(self): + self.context = cppContext.create() + + def term(self): + del self.context + self.context = NULL + + def __dealloc__(self): + pass + # Deleting the context will hang if sockets are still active + # TODO: Figure out a way to make sure the context is closed last + # del self.context + + +cdef class Poller: + cdef cppPoller * poller + cdef list sub_sockets + + def __cinit__(self): + self.sub_sockets = [] + self.poller = cppPoller.create() + + def __dealloc__(self): + del self.poller + + def registerSocket(self, SubSocket socket): + self.sub_sockets.append(socket) + self.poller.registerSocket(socket.socket) + + def poll(self, timeout): + sockets = [] + cdef int t = timeout + + with nogil: + result = self.poller.poll(t) + + for s in result: + socket = SubSocket() + socket.setPtr(s) + sockets.append(socket) + + return sockets + + +cdef class SubSocket: + cdef cppSubSocket * socket + cdef bool is_owner + + def __cinit__(self): + with nogil: + self.socket = cppSubSocket.create() + + self.is_owner = True + if self.socket == NULL: + raise IpcError + + def __dealloc__(self): + if self.is_owner: + with nogil: + del self.socket + + cdef setPtr(self, cppSubSocket * ptr): + if self.is_owner: + with nogil: + del self.socket + + self.is_owner = False + self.socket = ptr + + def connect(self, Context context, string endpoint, string address=b"127.0.0.1", bool conflate=False): + cdef int r + with nogil: + r = self.socket.connect(context.context, endpoint, address, conflate) + + if r != 0: + if errno.errno == errno.EADDRINUSE: + raise MultiplePublishersError(endpoint) + else: + raise IpcError(endpoint) + + def setTimeout(self, int timeout): + with nogil: + self.socket.setTimeout(timeout) + + def receive(self, bool non_blocking=False): + cdef cppMessage *msg + with nogil: + msg = self.socket.receive(non_blocking) + + if msg == NULL: + return None + else: + sz = msg.getSize() + m = msg.getData()[:sz] + with nogil: + del msg + + return m + + +cdef class PubSocket: + cdef cppPubSocket * socket + + def __cinit__(self): + self.socket = cppPubSocket.create() + if self.socket == NULL: + raise IpcError + + def __dealloc__(self): + del self.socket + + def connect(self, Context context, string endpoint): + r = self.socket.connect(context.context, endpoint) + + if r != 0: + if errno.errno == errno.EADDRINUSE: + raise MultiplePublishersError(endpoint) + else: + raise IpcError(endpoint) + + def send(self, bytes data): + length = len(data) + r = self.socket.send(data, length) + + if r != length: + if errno.errno == errno.EADDRINUSE: + raise MultiplePublishersError + else: + raise IpcError + + def all_readers_updated(self): + return self.socket.all_readers_updated() diff --git a/msgq_repo/msgq/logger/logger.h b/msgq_repo/msgq/logger/logger.h new file mode 100644 index 0000000000..03336f8fff --- /dev/null +++ b/msgq_repo/msgq/logger/logger.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef SWAGLOG +// cppcheck-suppress preprocessorErrorDirective +#include SWAGLOG +#else + +#define CLOUDLOG_DEBUG 10 +#define CLOUDLOG_INFO 20 +#define CLOUDLOG_WARNING 30 +#define CLOUDLOG_ERROR 40 +#define CLOUDLOG_CRITICAL 50 + +#define cloudlog(lvl, fmt, ...) printf(fmt "\n", ## __VA_ARGS__) + +#define LOGD(fmt, ...) cloudlog(CLOUDLOG_DEBUG, fmt, ## __VA_ARGS__) +#define LOG(fmt, ...) cloudlog(CLOUDLOG_INFO, fmt, ## __VA_ARGS__) +#define LOGW(fmt, ...) cloudlog(CLOUDLOG_WARNING, fmt, ## __VA_ARGS__) +#define LOGE(fmt, ...) cloudlog(CLOUDLOG_ERROR, fmt, ## __VA_ARGS__) + +#endif diff --git a/msgq_repo/msgq/msgq.cc b/msgq_repo/msgq/msgq.cc new file mode 100644 index 0000000000..5ce25a3bc2 --- /dev/null +++ b/msgq_repo/msgq/msgq.cc @@ -0,0 +1,468 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "msgq/msgq.h" + +void sigusr2_handler(int signal) { + assert(signal == SIGUSR2); +} + +uint64_t msgq_get_uid(void){ + std::random_device rd("/dev/urandom"); + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + + #ifdef __APPLE__ + // TODO: this doesn't work + uint64_t uid = distribution(rd) << 32 | getpid(); + #else + uint64_t uid = distribution(rd) << 32 | syscall(SYS_gettid); + #endif + + return uid; +} + +int msgq_msg_init_size(msgq_msg_t * msg, size_t size){ + msg->size = size; + msg->data = new(std::nothrow) char[size]; + + return (msg->data == NULL) ? -1 : 0; +} + + +int msgq_msg_init_data(msgq_msg_t * msg, char * data, size_t size) { + int r = msgq_msg_init_size(msg, size); + + if (r == 0) + memcpy(msg->data, data, size); + + return r; +} + +int msgq_msg_close(msgq_msg_t * msg){ + if (msg->size > 0) + delete[] msg->data; + + msg->size = 0; + + return 0; +} + +void msgq_reset_reader(msgq_queue_t * q){ + int id = q->reader_id; + q->read_valids[id]->store(true); + q->read_pointers[id]->store(*q->write_pointer); +} + +void msgq_wait_for_subscriber(msgq_queue_t *q){ + while (*q->num_readers == 0){ + // wait for subscriber + } + + return; +} + +int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size){ + assert(size < 0xFFFFFFFF); // Buffer must be smaller than 2^32 bytes + std::signal(SIGUSR2, sigusr2_handler); + + std::string full_path = "/dev/shm/"; + const char* prefix = std::getenv("OPENPILOT_PREFIX"); + if (prefix) { + full_path += std::string(prefix) + "/"; + } + full_path += path; + + auto fd = open(full_path.c_str(), O_RDWR | O_CREAT, 0664); + if (fd < 0) { + std::cout << "Warning, could not open: " << full_path << std::endl; + return -1; + } + + int rc = ftruncate(fd, size + sizeof(msgq_header_t)); + if (rc < 0){ + close(fd); + return -1; + } + char * mem = (char*)mmap(NULL, size + sizeof(msgq_header_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + close(fd); + + if (mem == MAP_FAILED){ + return -1; + } + q->mmap_p = mem; + + msgq_header_t *header = (msgq_header_t *)mem; + + // Setup pointers to header segment + q->num_readers = reinterpret_cast*>(&header->num_readers); + q->write_pointer = reinterpret_cast*>(&header->write_pointer); + q->write_uid = reinterpret_cast*>(&header->write_uid); + + for (size_t i = 0; i < NUM_READERS; i++){ + q->read_pointers[i] = reinterpret_cast*>(&header->read_pointers[i]); + q->read_valids[i] = reinterpret_cast*>(&header->read_valids[i]); + q->read_uids[i] = reinterpret_cast*>(&header->read_uids[i]); + } + + q->data = mem + sizeof(msgq_header_t); + q->size = size; + q->reader_id = -1; + + q->endpoint = path; + q->read_conflate = false; + + return 0; +} + +void msgq_close_queue(msgq_queue_t *q){ + if (q->mmap_p != NULL){ + munmap(q->mmap_p, q->size + sizeof(msgq_header_t)); + } +} + + +void msgq_init_publisher(msgq_queue_t * q) { + //std::cout << "Starting publisher" << std::endl; + uint64_t uid = msgq_get_uid(); + + *q->write_uid = uid; + *q->num_readers = 0; + + for (size_t i = 0; i < NUM_READERS; i++){ + *q->read_valids[i] = false; + *q->read_uids[i] = 0; + } + + q->write_uid_local = uid; +} + +static void thread_signal(uint32_t tid) { + #ifndef SYS_tkill + // TODO: this won't work for multithreaded programs + kill(tid, SIGUSR2); + #else + syscall(SYS_tkill, tid, SIGUSR2); + #endif +} + +void msgq_init_subscriber(msgq_queue_t * q) { + assert(q != NULL); + assert(q->num_readers != NULL); + + uint64_t uid = msgq_get_uid(); + + // Get reader id + while (true){ + uint64_t cur_num_readers = *q->num_readers; + uint64_t new_num_readers = cur_num_readers + 1; + + // No more slots available. Reset all subscribers to kick out inactive ones + if (new_num_readers > NUM_READERS){ + //std::cout << "Warning, evicting all subscribers!" << std::endl; + *q->num_readers = 0; + + for (size_t i = 0; i < NUM_READERS; i++){ + *q->read_valids[i] = false; + + uint64_t old_uid = *q->read_uids[i]; + *q->read_uids[i] = 0; + + // Wake up reader in case they are in a poll + thread_signal(old_uid & 0xFFFFFFFF); + } + + continue; + } + + // Use atomic compare and swap to handle race condition + // where two subscribers start at the same time + if (std::atomic_compare_exchange_strong(q->num_readers, + &cur_num_readers, + new_num_readers)){ + q->reader_id = cur_num_readers; + q->read_uid_local = uid; + + // We start with read_valid = false, + // on the first read the read pointer will be synchronized with the write pointer + *q->read_valids[cur_num_readers] = false; + *q->read_pointers[cur_num_readers] = 0; + *q->read_uids[cur_num_readers] = uid; + break; + } + } + + //std::cout << "New subscriber id: " << q->reader_id << " uid: " << q->read_uid_local << " " << q->endpoint << std::endl; + msgq_reset_reader(q); +} + +int msgq_msg_send(msgq_msg_t * msg, msgq_queue_t *q){ + // Die if we are no longer the active publisher + if (q->write_uid_local != *q->write_uid){ + std::cout << "Killing old publisher: " << q->endpoint << std::endl; + errno = EADDRINUSE; + return -1; + } + + uint64_t total_msg_size = ALIGN(msg->size + sizeof(int64_t)); + + // We need to fit at least three messages in the queue, + // then we can always safely access the last message + assert(3 * total_msg_size <= q->size); + + uint64_t num_readers = *q->num_readers; + + uint32_t write_cycles, write_pointer; + UNPACK64(write_cycles, write_pointer, *q->write_pointer); + + char *p = q->data + write_pointer; // add base offset + + // Check remaining space + // Always leave space for a wraparound tag for the next message, including alignment + int64_t remaining_space = q->size - write_pointer - total_msg_size - sizeof(int64_t); + if (remaining_space <= 0){ + // Write -1 size tag indicating wraparound + *(int64_t*)p = -1; + + // Invalidate all readers that are beyond the write pointer + // TODO: should we handle the case where a new reader shows up while this is running? + for (uint64_t i = 0; i < num_readers; i++){ + uint64_t read_pointer = *q->read_pointers[i]; + uint64_t read_cycles = read_pointer >> 32; + read_pointer &= 0xFFFFFFFF; + + if ((read_pointer > write_pointer) && (read_cycles != write_cycles)) { + *q->read_valids[i] = false; + } + } + + // Update global and local copies of write pointer and write_cycles + write_pointer = 0; + write_cycles = write_cycles + 1; + PACK64(*q->write_pointer, write_cycles, write_pointer); + + // Set actual pointer to the beginning of the data segment + p = q->data; + } + + // Invalidate readers that are in the area that will be written + uint64_t start = write_pointer; + uint64_t end = ALIGN(start + sizeof(int64_t) + msg->size); + + for (uint64_t i = 0; i < num_readers; i++){ + uint32_t read_cycles, read_pointer; + UNPACK64(read_cycles, read_pointer, *q->read_pointers[i]); + + if ((read_pointer >= start) && (read_pointer < end) && (read_cycles != write_cycles)) { + *q->read_valids[i] = false; + } + } + + + // Write size tag + std::atomic *size_p = reinterpret_cast*>(p); + *size_p = msg->size; + + // Copy data + memcpy(p + sizeof(int64_t), msg->data, msg->size); + __sync_synchronize(); + + // Update write pointer + uint32_t new_ptr = ALIGN(write_pointer + msg->size + sizeof(int64_t)); + PACK64(*q->write_pointer, write_cycles, new_ptr); + + // Notify readers + for (uint64_t i = 0; i < num_readers; i++){ + uint64_t reader_uid = *q->read_uids[i]; + thread_signal(reader_uid & 0xFFFFFFFF); + } + + return msg->size; +} + + +int msgq_msg_ready(msgq_queue_t * q){ + start: + int id = q->reader_id; + assert(id >= 0); // Make sure subscriber is initialized + + if (q->read_uid_local != *q->read_uids[id]){ + //std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl; + msgq_init_subscriber(q); + goto start; + } + + // Check valid + if (!*q->read_valids[id]){ + msgq_reset_reader(q); + goto start; + } + + uint32_t read_cycles, read_pointer; + UNPACK64(read_cycles, read_pointer, *q->read_pointers[id]); + UNUSED(read_cycles); + + uint32_t write_cycles, write_pointer; + UNPACK64(write_cycles, write_pointer, *q->write_pointer); + UNUSED(write_cycles); + + // Check if new message is available + return (read_pointer != write_pointer); +} + +int msgq_msg_recv(msgq_msg_t * msg, msgq_queue_t * q){ + start: + int id = q->reader_id; + assert(id >= 0); // Make sure subscriber is initialized + + if (q->read_uid_local != *q->read_uids[id]){ + //std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl; + msgq_init_subscriber(q); + goto start; + } + + // Check valid + if (!*q->read_valids[id]){ + msgq_reset_reader(q); + goto start; + } + + uint32_t read_cycles, read_pointer; + UNPACK64(read_cycles, read_pointer, *q->read_pointers[id]); + + uint32_t write_cycles, write_pointer; + UNPACK64(write_cycles, write_pointer, *q->write_pointer); + UNUSED(write_cycles); + + char * p = q->data + read_pointer; + + // Check if new message is available + if (read_pointer == write_pointer) { + msg->size = 0; + return 0; + } + + // Read potential message size + std::atomic *size_p = reinterpret_cast*>(p); + std::int64_t size = *size_p; + + // Check if the size that was read is valid + if (!*q->read_valids[id]){ + msgq_reset_reader(q); + goto start; + } + + // If size is -1 the buffer was full, and we need to wrap around + if (size == -1){ + read_cycles++; + PACK64(*q->read_pointers[id], read_cycles, 0); + goto start; + } + + // crashing is better than passing garbage data to the consumer + // the size will have weird value if it was overwritten by data accidentally + assert((uint64_t)size < q->size); + assert(size > 0); + + uint32_t new_read_pointer = ALIGN(read_pointer + sizeof(std::int64_t) + size); + + // If conflate is true, check if this is the latest message, else start over + if (q->read_conflate){ + if (new_read_pointer != write_pointer){ + // Update read pointer + PACK64(*q->read_pointers[id], read_cycles, new_read_pointer); + goto start; + } + } + + // Copy message + if (msgq_msg_init_size(msg, size) < 0) + return -1; + + __sync_synchronize(); + memcpy(msg->data, p + sizeof(int64_t), size); + __sync_synchronize(); + + // Update read pointer + PACK64(*q->read_pointers[id], read_cycles, new_read_pointer); + + // Check if the actual data that was copied is valid + if (!*q->read_valids[id]){ + msgq_msg_close(msg); + msgq_reset_reader(q); + goto start; + } + + + return msg->size; +} + + + +int msgq_poll(msgq_pollitem_t * items, size_t nitems, int timeout){ + int num = 0; + + // Check if messages ready + for (size_t i = 0; i < nitems; i++) { + items[i].revents = msgq_msg_ready(items[i].q); + if (items[i].revents) num++; + } + + int ms = (timeout == -1) ? 100 : timeout; + struct timespec ts; + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000 * 1000; + + + while (num == 0) { + int ret; + + ret = nanosleep(&ts, &ts); + + // Check if messages ready + for (size_t i = 0; i < nitems; i++) { + if (items[i].revents == 0 && msgq_msg_ready(items[i].q)){ + num += 1; + items[i].revents = 1; + } + } + + // exit if we had a timeout and the sleep finished + if (timeout != -1 && ret == 0){ + break; + } + } + + return num; +} + +bool msgq_all_readers_updated(msgq_queue_t *q) { + uint64_t num_readers = *q->num_readers; + for (uint64_t i = 0; i < num_readers; i++) { + if (*q->read_valids[i] && *q->write_pointer != *q->read_pointers[i]) { + return false; + } + } + return num_readers > 0; +} diff --git a/msgq_repo/msgq/msgq.h b/msgq_repo/msgq/msgq.h new file mode 100644 index 0000000000..94e1849442 --- /dev/null +++ b/msgq_repo/msgq/msgq.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include +#include + +#define DEFAULT_SEGMENT_SIZE (10 * 1024 * 1024) +#define NUM_READERS 15 +#define ALIGN(n) ((n + (8 - 1)) & -8) + +#define UNUSED(x) (void)x +#define UNPACK64(higher, lower, input) do {uint64_t tmp = input; higher = tmp >> 32; lower = tmp & 0xFFFFFFFF;} while (0) +#define PACK64(output, higher, lower) output = ((uint64_t)higher << 32) | ((uint64_t)lower & 0xFFFFFFFF) + +struct msgq_header_t { + uint64_t num_readers; + uint64_t write_pointer; + uint64_t write_uid; + uint64_t read_pointers[NUM_READERS]; + uint64_t read_valids[NUM_READERS]; + uint64_t read_uids[NUM_READERS]; +}; + +struct msgq_queue_t { + std::atomic *num_readers; + std::atomic *write_pointer; + std::atomic *write_uid; + std::atomic *read_pointers[NUM_READERS]; + std::atomic *read_valids[NUM_READERS]; + std::atomic *read_uids[NUM_READERS]; + char * mmap_p; + char * data; + size_t size; + int reader_id; + uint64_t read_uid_local; + uint64_t write_uid_local; + + bool read_conflate; + std::string endpoint; +}; + +struct msgq_msg_t { + size_t size; + char * data; +}; + +struct msgq_pollitem_t { + msgq_queue_t *q; + int revents; +}; + +void msgq_wait_for_subscriber(msgq_queue_t *q); +void msgq_reset_reader(msgq_queue_t *q); + +int msgq_msg_init_size(msgq_msg_t *msg, size_t size); +int msgq_msg_init_data(msgq_msg_t *msg, char * data, size_t size); +int msgq_msg_close(msgq_msg_t *msg); + +int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size); +void msgq_close_queue(msgq_queue_t *q); +void msgq_init_publisher(msgq_queue_t * q); +void msgq_init_subscriber(msgq_queue_t * q); + +int msgq_msg_send(msgq_msg_t *msg, msgq_queue_t *q); +int msgq_msg_recv(msgq_msg_t *msg, msgq_queue_t *q); +int msgq_msg_ready(msgq_queue_t * q); +int msgq_poll(msgq_pollitem_t * items, size_t nitems, int timeout); + +bool msgq_all_readers_updated(msgq_queue_t *q); diff --git a/msgq_repo/msgq/msgq_tests.cc b/msgq_repo/msgq/msgq_tests.cc new file mode 100644 index 0000000000..02f17917a5 --- /dev/null +++ b/msgq_repo/msgq/msgq_tests.cc @@ -0,0 +1,424 @@ +#include "catch2/catch.hpp" +#include "msgq/msgq.h" + +TEST_CASE("ALIGN") +{ + REQUIRE(ALIGN(0) == 0); + REQUIRE(ALIGN(1) == 8); + REQUIRE(ALIGN(7) == 8); + REQUIRE(ALIGN(8) == 8); + REQUIRE(ALIGN(99999) == 100000); +} + +TEST_CASE("msgq_msg_init_size") +{ + const size_t msg_size = 30; + msgq_msg_t msg; + + msgq_msg_init_size(&msg, msg_size); + REQUIRE(msg.size == msg_size); + + msgq_msg_close(&msg); +} + +TEST_CASE("msgq_msg_init_data") +{ + const size_t msg_size = 30; + char *data = new char[msg_size]; + + for (size_t i = 0; i < msg_size; i++) + { + data[i] = i; + } + + msgq_msg_t msg; + msgq_msg_init_data(&msg, data, msg_size); + + REQUIRE(msg.size == msg_size); + REQUIRE(memcmp(msg.data, data, msg_size) == 0); + + delete[] data; + msgq_msg_close(&msg); +} + +TEST_CASE("msgq_init_subscriber") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t q; + msgq_new_queue(&q, "test_queue", 1024); + REQUIRE(*q.num_readers == 0); + + q.reader_id = 1; + *q.read_valids[0] = false; + *q.read_pointers[0] = ((uint64_t)1 << 32); + + *q.write_pointer = 255; + + msgq_init_subscriber(&q); + REQUIRE(q.read_conflate == false); + REQUIRE(*q.read_valids[0] == true); + REQUIRE((*q.read_pointers[0] >> 32) == 0); + REQUIRE((*q.read_pointers[0] & 0xFFFFFFFF) == 255); +} + +TEST_CASE("msgq_msg_send first message") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t q; + msgq_new_queue(&q, "test_queue", 1024); + msgq_init_publisher(&q); + + REQUIRE(*q.write_pointer == 0); + + size_t msg_size = 128; + + SECTION("Aligned message size") + { + } + SECTION("Unaligned message size") + { + msg_size--; + } + char *data = new char[msg_size]; + + for (size_t i = 0; i < msg_size; i++) + { + data[i] = i; + } + + msgq_msg_t msg; + msgq_msg_init_data(&msg, data, msg_size); + + msgq_msg_send(&msg, &q); + REQUIRE(*(int64_t *)q.data == msg_size); // Check size tag + REQUIRE(*q.write_pointer == 128 + sizeof(int64_t)); + REQUIRE(memcmp(q.data + sizeof(int64_t), data, msg_size) == 0); + + delete[] data; + msgq_msg_close(&msg); +} + +TEST_CASE("msgq_msg_send test wraparound") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t q; + msgq_new_queue(&q, "test_queue", 1024); + msgq_init_publisher(&q); + + REQUIRE((*q.write_pointer & 0xFFFFFFFF) == 0); + REQUIRE((*q.write_pointer >> 32) == 0); + + const size_t msg_size = 120; + msgq_msg_t msg; + msgq_msg_init_size(&msg, msg_size); + + for (int i = 0; i < 8; i++) + { + msgq_msg_send(&msg, &q); + } + // Check 8th message was written at the beginning + REQUIRE((*q.write_pointer & 0xFFFFFFFF) == msg_size + sizeof(int64_t)); + + // Check cycle count + REQUIRE((*q.write_pointer >> 32) == 1); + + // Check wraparound tag + char *tag_location = q.data; + tag_location += 7 * (msg_size + sizeof(int64_t)); + REQUIRE(*(int64_t *)tag_location == -1); + + msgq_msg_close(&msg); +} + +TEST_CASE("msgq_msg_recv test wraparound") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t q_pub, q_sub; + msgq_new_queue(&q_pub, "test_queue", 1024); + msgq_new_queue(&q_sub, "test_queue", 1024); + + msgq_init_publisher(&q_pub); + msgq_init_subscriber(&q_sub); + + REQUIRE((*q_pub.write_pointer >> 32) == 0); + REQUIRE((*q_sub.read_pointers[0] >> 32) == 0); + + const size_t msg_size = 120; + msgq_msg_t msg1; + msgq_msg_init_size(&msg1, msg_size); + + SECTION("Check cycle counter after reset") + { + for (int i = 0; i < 8; i++) + { + msgq_msg_send(&msg1, &q_pub); + } + + msgq_msg_t msg2; + msgq_msg_recv(&msg2, &q_sub); + REQUIRE(msg2.size == 0); // Reader had to reset + msgq_msg_close(&msg2); + } + SECTION("Check cycle counter while keeping up with writer") + { + for (int i = 0; i < 8; i++) + { + msgq_msg_send(&msg1, &q_pub); + + msgq_msg_t msg2; + msgq_msg_recv(&msg2, &q_sub); + REQUIRE(msg2.size > 0); + msgq_msg_close(&msg2); + } + } + + REQUIRE((*q_sub.read_pointers[0] >> 32) == 1); + msgq_msg_close(&msg1); +} + +TEST_CASE("msgq_msg_send test invalidation") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t q_pub, q_sub; + msgq_new_queue(&q_pub, "test_queue", 1024); + msgq_new_queue(&q_sub, "test_queue", 1024); + + msgq_init_publisher(&q_pub); + msgq_init_subscriber(&q_sub); + *q_sub.write_pointer = (uint64_t)1 << 32; + + REQUIRE(*q_sub.read_valids[0] == true); + + SECTION("read pointer in tag") + { + *q_sub.read_pointers[0] = 0; + } + SECTION("read pointer in data section") + { + *q_sub.read_pointers[0] = 64; + } + SECTION("read pointer in wraparound section") + { + *q_pub.write_pointer = ((uint64_t)1 << 32) | 1000; // Writer is one cycle ahead + *q_sub.read_pointers[0] = 1020; + } + + msgq_msg_t msg; + msgq_msg_init_size(&msg, 128); + msgq_msg_send(&msg, &q_pub); + + REQUIRE(*q_sub.read_valids[0] == false); + + msgq_msg_close(&msg); +} + +TEST_CASE("msgq_init_subscriber init 2 subscribers") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t q1, q2; + msgq_new_queue(&q1, "test_queue", 1024); + msgq_new_queue(&q2, "test_queue", 1024); + + *q1.num_readers = 0; + + REQUIRE(*q1.num_readers == 0); + REQUIRE(*q2.num_readers == 0); + + msgq_init_subscriber(&q1); + REQUIRE(*q1.num_readers == 1); + REQUIRE(*q2.num_readers == 1); + REQUIRE(q1.reader_id == 0); + + msgq_init_subscriber(&q2); + REQUIRE(*q1.num_readers == 2); + REQUIRE(*q2.num_readers == 2); + REQUIRE(q2.reader_id == 1); +} + +TEST_CASE("Write 1 msg, read 1 msg", "[integration]") +{ + remove("/dev/shm/test_queue"); + const size_t msg_size = 128; + msgq_queue_t writer, reader; + + msgq_new_queue(&writer, "test_queue", 1024); + msgq_new_queue(&reader, "test_queue", 1024); + + msgq_init_publisher(&writer); + msgq_init_subscriber(&reader); + + // Build 128 byte message + msgq_msg_t outgoing_msg; + msgq_msg_init_size(&outgoing_msg, msg_size); + + for (size_t i = 0; i < msg_size; i++) + { + outgoing_msg.data[i] = i; + } + + REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size); + + msgq_msg_t incoming_msg1; + REQUIRE(msgq_msg_recv(&incoming_msg1, &reader) == msg_size); + REQUIRE(memcmp(incoming_msg1.data, outgoing_msg.data, msg_size) == 0); + + // Verify that there are no more messages + msgq_msg_t incoming_msg2; + REQUIRE(msgq_msg_recv(&incoming_msg2, &reader) == 0); + + msgq_msg_close(&outgoing_msg); + msgq_msg_close(&incoming_msg1); + msgq_msg_close(&incoming_msg2); +} + +TEST_CASE("Write 2 msg, read 2 msg - conflate = false", "[integration]") +{ + remove("/dev/shm/test_queue"); + const size_t msg_size = 128; + msgq_queue_t writer, reader; + + msgq_new_queue(&writer, "test_queue", 1024); + msgq_new_queue(&reader, "test_queue", 1024); + + msgq_init_publisher(&writer); + msgq_init_subscriber(&reader); + + // Build 128 byte message + msgq_msg_t outgoing_msg; + msgq_msg_init_size(&outgoing_msg, msg_size); + + for (size_t i = 0; i < msg_size; i++) + { + outgoing_msg.data[i] = i; + } + + REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size); + REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size); + + msgq_msg_t incoming_msg1; + REQUIRE(msgq_msg_recv(&incoming_msg1, &reader) == msg_size); + REQUIRE(memcmp(incoming_msg1.data, outgoing_msg.data, msg_size) == 0); + + msgq_msg_t incoming_msg2; + REQUIRE(msgq_msg_recv(&incoming_msg2, &reader) == msg_size); + REQUIRE(memcmp(incoming_msg2.data, outgoing_msg.data, msg_size) == 0); + + msgq_msg_close(&outgoing_msg); + msgq_msg_close(&incoming_msg1); + msgq_msg_close(&incoming_msg2); +} + +TEST_CASE("Write 2 msg, read 2 msg - conflate = true", "[integration]") +{ + remove("/dev/shm/test_queue"); + const size_t msg_size = 128; + msgq_queue_t writer, reader; + + msgq_new_queue(&writer, "test_queue", 1024); + msgq_new_queue(&reader, "test_queue", 1024); + + msgq_init_publisher(&writer); + msgq_init_subscriber(&reader); + reader.read_conflate = true; + + // Build 128 byte message + msgq_msg_t outgoing_msg; + msgq_msg_init_size(&outgoing_msg, msg_size); + + for (size_t i = 0; i < msg_size; i++) + { + outgoing_msg.data[i] = i; + } + + REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size); + REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size); + + msgq_msg_t incoming_msg1; + REQUIRE(msgq_msg_recv(&incoming_msg1, &reader) == msg_size); + REQUIRE(memcmp(incoming_msg1.data, outgoing_msg.data, msg_size) == 0); + + // Verify that there are no more messages + msgq_msg_t incoming_msg2; + REQUIRE(msgq_msg_recv(&incoming_msg2, &reader) == 0); + + msgq_msg_close(&outgoing_msg); + msgq_msg_close(&incoming_msg1); + msgq_msg_close(&incoming_msg2); +} + +TEST_CASE("1 publisher, 1 slow subscriber", "[integration]") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t writer, reader; + + msgq_new_queue(&writer, "test_queue", 1024); + msgq_new_queue(&reader, "test_queue", 1024); + + msgq_init_publisher(&writer); + msgq_init_subscriber(&reader); + + int n_received = 0; + int n_skipped = 0; + + for (uint64_t i = 0; i < 1e5; i++) + { + msgq_msg_t outgoing_msg; + msgq_msg_init_data(&outgoing_msg, (char *)&i, sizeof(uint64_t)); + msgq_msg_send(&outgoing_msg, &writer); + msgq_msg_close(&outgoing_msg); + + if (i % 10 == 0) + { + msgq_msg_t msg1; + msgq_msg_recv(&msg1, &reader); + + if (msg1.size == 0) + { + n_skipped++; + } + else + { + n_received++; + } + msgq_msg_close(&msg1); + } + } + + // TODO: verify these numbers by hand + REQUIRE(n_received == 8572); + REQUIRE(n_skipped == 1428); +} + +TEST_CASE("1 publisher, 2 subscribers", "[integration]") +{ + remove("/dev/shm/test_queue"); + msgq_queue_t writer, reader1, reader2; + + msgq_new_queue(&writer, "test_queue", 1024); + msgq_new_queue(&reader1, "test_queue", 1024); + msgq_new_queue(&reader2, "test_queue", 1024); + + msgq_init_publisher(&writer); + msgq_init_subscriber(&reader1); + msgq_init_subscriber(&reader2); + + for (uint64_t i = 0; i < 1024 * 3; i++) + { + msgq_msg_t outgoing_msg; + msgq_msg_init_data(&outgoing_msg, (char *)&i, sizeof(uint64_t)); + msgq_msg_send(&outgoing_msg, &writer); + + msgq_msg_t msg1, msg2; + msgq_msg_recv(&msg1, &reader1); + msgq_msg_recv(&msg2, &reader2); + + REQUIRE(msg1.size == sizeof(uint64_t)); + REQUIRE(msg2.size == sizeof(uint64_t)); + REQUIRE(*(uint64_t *)msg1.data == i); + REQUIRE(*(uint64_t *)msg2.data == i); + + msgq_msg_close(&outgoing_msg); + msgq_msg_close(&msg1); + msgq_msg_close(&msg2); + } +} diff --git a/msgq_repo/msgq/test_runner.cc b/msgq_repo/msgq/test_runner.cc new file mode 100644 index 0000000000..62bf7476a1 --- /dev/null +++ b/msgq_repo/msgq/test_runner.cc @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/msgq_repo/msgq/tests/__init__.py b/msgq_repo/msgq/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/msgq_repo/msgq/tests/test_fake.py b/msgq_repo/msgq/tests/test_fake.py new file mode 100644 index 0000000000..d2c51313cc --- /dev/null +++ b/msgq_repo/msgq/tests/test_fake.py @@ -0,0 +1,188 @@ +import pytest +import os +import multiprocessing +import platform +import msgq +from parameterized import parameterized_class +from typing import Optional + +WAIT_TIMEOUT = 5 + + +@pytest.mark.skipif(condition=platform.system() == "Darwin", reason="Events not supported on macOS") +class TestEvents: + + def test_mutation(self): + handle = msgq.fake_event_handle("carState") + event = handle.recv_called_event + + assert not event.peek() + event.set() + assert event.peek() + event.clear() + assert not event.peek() + + del event + + def test_wait(self): + handle = msgq.fake_event_handle("carState") + event = handle.recv_called_event + + event.set() + try: + event.wait(WAIT_TIMEOUT) + assert event.peek() + except RuntimeError: + pytest.fail("event.wait() timed out") + + def test_wait_multiprocess(self): + handle = msgq.fake_event_handle("carState") + event = handle.recv_called_event + + def set_event_run(): + event.set() + + try: + p = multiprocessing.Process(target=set_event_run) + p.start() + event.wait(WAIT_TIMEOUT) + assert event.peek() + except RuntimeError: + pytest.fail("event.wait() timed out") + + p.kill() + + def test_wait_zero_timeout(self): + handle = msgq.fake_event_handle("carState") + event = handle.recv_called_event + + try: + event.wait(0) + pytest.fail("event.wait() did not time out") + except RuntimeError: + assert not event.peek() + + +@pytest.mark.skipif(condition=platform.system() == "Darwin", reason="FakeSockets not supported on macOS") +@pytest.mark.skipif(condition="ZMQ" in os.environ, reason="FakeSockets not supported on ZMQ") +@parameterized_class([{"prefix": None}, {"prefix": "test"}]) +class TestFakeSockets: + prefix: Optional[str] = None + + def setup_method(self): + msgq.toggle_fake_events(True) + if self.prefix is not None: + msgq.set_fake_prefix(self.prefix) + else: + msgq.delete_fake_prefix() + + def teardown_method(self): + msgq.toggle_fake_events(False) + msgq.delete_fake_prefix() + + def test_event_handle_init(self): + handle = msgq.fake_event_handle("controlsState", override=True) + + assert not handle.enabled + assert handle.recv_called_event.fd >= 0 + assert handle.recv_ready_event.fd >= 0 + + def test_non_managed_socket_state(self): + # non managed socket should have zero state + _ = msgq.pub_sock("ubloxGnss") + + handle = msgq.fake_event_handle("ubloxGnss", override=False) + + assert not handle.enabled + assert handle.recv_called_event.fd == 0 + assert handle.recv_ready_event.fd == 0 + + def test_managed_socket_state(self): + # managed socket should not change anything about the state + handle = msgq.fake_event_handle("ubloxGnss") + handle.enabled = True + + expected_enabled = handle.enabled + expected_recv_called_fd = handle.recv_called_event.fd + expected_recv_ready_fd = handle.recv_ready_event.fd + + _ = msgq.pub_sock("ubloxGnss") + + assert handle.enabled == expected_enabled + assert handle.recv_called_event.fd == expected_recv_called_fd + assert handle.recv_ready_event.fd == expected_recv_ready_fd + + def test_sockets_enable_disable(self): + carState_handle = msgq.fake_event_handle("ubloxGnss", enable=True) + recv_called = carState_handle.recv_called_event + recv_ready = carState_handle.recv_ready_event + + pub_sock = msgq.pub_sock("ubloxGnss") + sub_sock = msgq.sub_sock("ubloxGnss") + + try: + carState_handle.enabled = True + recv_ready.set() + pub_sock.send(b"test") + _ = sub_sock.receive() + assert recv_called.peek() + recv_called.clear() + + carState_handle.enabled = False + recv_ready.set() + pub_sock.send(b"test") + _ = sub_sock.receive() + assert not recv_called.peek() + except RuntimeError: + pytest.fail("event.wait() timed out") + + def test_synced_pub_sub(self): + def daemon_repub_process_run(): + pub_sock = msgq.pub_sock("ubloxGnss") + sub_sock = msgq.sub_sock("carState") + + frame = -1 + while True: + frame += 1 + msg = sub_sock.receive(non_blocking=True) + if msg is None: + print("none received") + continue + + bts = frame.to_bytes(8, 'little') + pub_sock.send(bts) + + carState_handle = msgq.fake_event_handle("carState", enable=True) + recv_called = carState_handle.recv_called_event + recv_ready = carState_handle.recv_ready_event + + p = multiprocessing.Process(target=daemon_repub_process_run) + p.start() + + pub_sock = msgq.pub_sock("carState") + sub_sock = msgq.sub_sock("ubloxGnss") + + try: + for i in range(10): + recv_called.wait(WAIT_TIMEOUT) + recv_called.clear() + + if i == 0: + sub_sock.receive(non_blocking=True) + + bts = i.to_bytes(8, 'little') + pub_sock.send(bts) + + recv_ready.set() + recv_called.wait(WAIT_TIMEOUT) + + msg = sub_sock.receive(non_blocking=True) + assert msg is not None + assert len(msg) == 8 + + frame = int.from_bytes(msg, 'little') + assert frame == i + except RuntimeError: + pytest.fail("event.wait() timed out") + finally: + p.kill() diff --git a/msgq_repo/msgq/tests/test_messaging.py b/msgq_repo/msgq/tests/test_messaging.py new file mode 100644 index 0000000000..b3fee36d85 --- /dev/null +++ b/msgq_repo/msgq/tests/test_messaging.py @@ -0,0 +1,71 @@ +import os +import random +import time +import string +import msgq + + +def random_sock(): + return ''.join(random.choices(string.ascii_uppercase + string.digits, k=10)) + +def random_bytes(length=1000): + return bytes([random.randrange(0xFF) for _ in range(length)]) + +def zmq_sleep(t=1): + if "ZMQ" in os.environ: + time.sleep(t) + +class TestPubSubSockets: + + def setup_method(self): + # ZMQ pub socket takes too long to die + # sleep to prevent multiple publishers error between tests + zmq_sleep() + + def test_pub_sub(self): + sock = random_sock() + pub_sock = msgq.pub_sock(sock) + sub_sock = msgq.sub_sock(sock, conflate=False, timeout=None) + zmq_sleep(3) + + for _ in range(1000): + msg = random_bytes() + pub_sock.send(msg) + recvd = sub_sock.receive() + assert msg == recvd + + def test_conflate(self): + sock = random_sock() + pub_sock = msgq.pub_sock(sock) + for conflate in [True, False]: + for _ in range(10): + num_msgs = random.randint(3, 10) + sub_sock = msgq.sub_sock(sock, conflate=conflate, timeout=None) + zmq_sleep() + + sent_msgs = [] + for __ in range(num_msgs): + msg = random_bytes() + pub_sock.send(msg) + sent_msgs.append(msg) + time.sleep(0.1) + recvd_msgs = msgq.drain_sock_raw(sub_sock) + if conflate: + assert len(recvd_msgs) == 1 + assert recvd_msgs[0] == sent_msgs[-1] + else: + assert len(recvd_msgs) == len(sent_msgs) + for rec_msg, sent_msg in zip(recvd_msgs, sent_msgs): + assert rec_msg == sent_msg + + def test_receive_timeout(self): + sock = random_sock() + for _ in range(10): + timeout = random.randrange(200) + sub_sock = msgq.sub_sock(sock, timeout=timeout) + zmq_sleep() + + start_time = time.monotonic() + recvd = sub_sock.receive() + assert (time.monotonic() - start_time) < 0.2 + assert recvd is None diff --git a/msgq_repo/msgq/tests/test_poller.py b/msgq_repo/msgq/tests/test_poller.py new file mode 100644 index 0000000000..6ef2c0423e --- /dev/null +++ b/msgq_repo/msgq/tests/test_poller.py @@ -0,0 +1,138 @@ +import pytest +import time +import msgq +import concurrent.futures + +SERVICE_NAME = 'myService' + +def poller(): + context = msgq.Context() + + p = msgq.Poller() + + sub = msgq.SubSocket() + sub.connect(context, SERVICE_NAME) + p.registerSocket(sub) + + socks = p.poll(10000) + r = [s.receive(non_blocking=True) for s in socks] + + return r + + +class TestPoller: + def test_poll_once(self): + context = msgq.Context() + + pub = msgq.PubSocket() + pub.connect(context, SERVICE_NAME) + + with concurrent.futures.ThreadPoolExecutor() as e: + poll = e.submit(poller) + + time.sleep(0.1) # Slow joiner syndrome + + # Send message + pub.send(b"a") + + # Wait for poll result + result = poll.result() + + del pub + context.term() + + assert result == [b"a"] + + def test_poll_and_create_many_subscribers(self): + context = msgq.Context() + + pub = msgq.PubSocket() + pub.connect(context, SERVICE_NAME) + + with concurrent.futures.ThreadPoolExecutor() as e: + poll = e.submit(poller) + + time.sleep(0.1) # Slow joiner syndrome + c = msgq.Context() + for _ in range(10): + msgq.SubSocket().connect(c, SERVICE_NAME) + + time.sleep(0.1) + + # Send message + pub.send(b"a") + + # Wait for poll result + result = poll.result() + + del pub + context.term() + + assert result == [b"a"] + + def test_multiple_publishers_exception(self): + context = msgq.Context() + + with pytest.raises(msgq.MultiplePublishersError): + pub1 = msgq.PubSocket() + pub1.connect(context, SERVICE_NAME) + + pub2 = msgq.PubSocket() + pub2.connect(context, SERVICE_NAME) + + pub1.send(b"a") + + del pub1 + del pub2 + context.term() + + def test_multiple_messages(self): + context = msgq.Context() + + pub = msgq.PubSocket() + pub.connect(context, SERVICE_NAME) + + sub = msgq.SubSocket() + sub.connect(context, SERVICE_NAME) + + time.sleep(0.1) # Slow joiner + + for i in range(1, 100): + pub.send(b'a'*i) + + msg_seen = False + i = 1 + while True: + r = sub.receive(non_blocking=True) + + if r is not None: + assert b'a'*i == r + + msg_seen = True + i += 1 + + if r is None and msg_seen: # ZMQ sometimes receives nothing on the first receive + break + + del pub + del sub + context.term() + + def test_conflate(self): + context = msgq.Context() + + pub = msgq.PubSocket() + pub.connect(context, SERVICE_NAME) + + sub = msgq.SubSocket() + sub.connect(context, SERVICE_NAME, conflate=True) + + time.sleep(0.1) # Slow joiner + pub.send(b'a') + pub.send(b'b') + + assert b'b' == sub.receive() + + del pub + del sub + context.term() diff --git a/msgq_repo/msgq/visionipc/.gitignore b/msgq_repo/msgq/visionipc/.gitignore new file mode 100644 index 0000000000..fa5a2b9f38 --- /dev/null +++ b/msgq_repo/msgq/visionipc/.gitignore @@ -0,0 +1,2 @@ +visionipc_pyx.cpp +*.so diff --git a/msgq_repo/msgq/visionipc/__init__.py b/msgq_repo/msgq/visionipc/__init__.py new file mode 100644 index 0000000000..57011537e4 --- /dev/null +++ b/msgq_repo/msgq/visionipc/__init__.py @@ -0,0 +1,6 @@ +from msgq.visionipc.visionipc_pyx import VisionBuf, VisionIpcClient, VisionIpcServer, VisionStreamType, get_endpoint_name +assert VisionBuf +assert VisionIpcClient +assert VisionIpcServer +assert VisionStreamType +assert get_endpoint_name diff --git a/msgq_repo/msgq/visionipc/test_runner.cc b/msgq_repo/msgq/visionipc/test_runner.cc new file mode 100644 index 0000000000..62bf7476a1 --- /dev/null +++ b/msgq_repo/msgq/visionipc/test_runner.cc @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/msgq_repo/msgq/visionipc/tests/__init__.py b/msgq_repo/msgq/visionipc/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/msgq_repo/msgq/visionipc/tests/test_visionipc.py b/msgq_repo/msgq/visionipc/tests/test_visionipc.py new file mode 100644 index 0000000000..077a9aead4 --- /dev/null +++ b/msgq_repo/msgq/visionipc/tests/test_visionipc.py @@ -0,0 +1,99 @@ +import os +import time +import random +import numpy as np +from msgq.visionipc import VisionIpcServer, VisionIpcClient, VisionStreamType + +def zmq_sleep(t=1): + if "ZMQ" in os.environ: + time.sleep(t) + + +class TestVisionIpc: + + def setup_vipc(self, name, *stream_types, num_buffers=1, width=100, height=100, conflate=False): + self.server = VisionIpcServer(name) + for stream_type in stream_types: + self.server.create_buffers(stream_type, num_buffers, width, height) + self.server.start_listener() + + if len(stream_types): + self.client = VisionIpcClient(name, stream_types[0], conflate) + assert self.client.connect(True) + else: + self.client = None + + zmq_sleep() + return self.server, self.client + + def test_connect(self): + self.setup_vipc("camerad", VisionStreamType.VISION_STREAM_ROAD) + assert self.client.is_connected + del self.client + del self.server + + def test_available_streams(self): + for k in range(4): + stream_types = set(random.choices([x.value for x in VisionStreamType], k=k)) + self.setup_vipc("camerad", *stream_types) + available_streams = VisionIpcClient.available_streams("camerad", True) + assert available_streams == stream_types + del self.client + del self.server + + def test_buffers(self): + width, height, num_buffers = 100, 200, 5 + self.setup_vipc("camerad", VisionStreamType.VISION_STREAM_ROAD, num_buffers=num_buffers, width=width, height=height) + assert self.client.width == width + assert self.client.height == height + assert self.client.buffer_len > 0 + assert self.client.num_buffers == num_buffers + del self.client + del self.server + + def test_send_single_buffer(self): + self.setup_vipc("camerad", VisionStreamType.VISION_STREAM_ROAD) + + buf = np.zeros(self.client.buffer_len, dtype=np.uint8) + buf.view('width = init_width; + this->height = init_height; + this->stride = init_stride; + this->uv_offset = init_uv_offset; + + this->y = (uint8_t *)this->addr; + this->uv = this->y + this->uv_offset; +} + + +uint64_t VisionBuf::get_frame_id() { + return *frame_id; +} + +void VisionBuf::set_frame_id(uint64_t id) { + *frame_id = id; +} diff --git a/msgq_repo/msgq/visionipc/visionbuf.h b/msgq_repo/msgq/visionipc/visionbuf.h new file mode 100644 index 0000000000..52345ba08a --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionbuf.h @@ -0,0 +1,62 @@ +#pragma once + +#include "msgq/visionipc/visionipc.h" + +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#define VISIONBUF_SYNC_FROM_DEVICE 0 +#define VISIONBUF_SYNC_TO_DEVICE 1 + +enum VisionStreamType { + VISION_STREAM_ROAD, + VISION_STREAM_DRIVER, + VISION_STREAM_WIDE_ROAD, + + VISION_STREAM_MAP, + VISION_STREAM_MAX, +}; + +class VisionBuf { + public: + size_t len = 0; + size_t mmap_len = 0; + void * addr = nullptr; + uint64_t *frame_id; + int fd = 0; + + size_t width = 0; + size_t height = 0; + size_t stride = 0; + size_t uv_offset = 0; + + // YUV + uint8_t * y = nullptr; + uint8_t * uv = nullptr; + + // Visionipc + uint64_t server_id = 0; + size_t idx = 0; + VisionStreamType type; + + // OpenCL + cl_mem buf_cl = nullptr; + cl_command_queue copy_q = nullptr; + + // ion + int handle = 0; + + void allocate(size_t len); + void import(); + void init_cl(cl_device_id device_id, cl_context ctx); + void init_yuv(size_t width, size_t height, size_t stride, size_t uv_offset); + int sync(int dir); + int free(); + + void set_frame_id(uint64_t id); + uint64_t get_frame_id(); +}; diff --git a/msgq_repo/msgq/visionipc/visionbuf_cl.cc b/msgq_repo/msgq/visionipc/visionbuf_cl.cc new file mode 100644 index 0000000000..db1ca03347 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionbuf_cl.cc @@ -0,0 +1,94 @@ +#include "msgq/visionipc/visionbuf.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +std::atomic offset = 0; + +static void *malloc_with_fd(size_t len, int *fd) { + char full_path[0x100]; + +#ifdef __APPLE__ + snprintf(full_path, sizeof(full_path)-1, "/tmp/visionbuf_%d_%d", getpid(), offset++); +#else + snprintf(full_path, sizeof(full_path)-1, "/dev/shm/visionbuf_%d_%d", getpid(), offset++); +#endif + + *fd = open(full_path, O_RDWR | O_CREAT, 0664); + assert(*fd >= 0); + + unlink(full_path); + + ftruncate(*fd, len); + void *addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); + assert(addr != MAP_FAILED); + + return addr; +} + +void VisionBuf::allocate(size_t length) { + this->len = length; + this->mmap_len = this->len + sizeof(uint64_t); + this->addr = malloc_with_fd(this->mmap_len, &this->fd); + this->frame_id = (uint64_t*)((uint8_t*)this->addr + this->len); +} + +void VisionBuf::init_cl(cl_device_id device_id, cl_context ctx){ + int err; + + this->copy_q = clCreateCommandQueue(ctx, device_id, 0, &err); + assert(err == 0); + + this->buf_cl = clCreateBuffer(ctx, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, this->len, this->addr, &err); + assert(err == 0); +} + + +void VisionBuf::import(){ + assert(this->fd >= 0); + this->addr = mmap(NULL, this->mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, 0); + assert(this->addr != MAP_FAILED); + + this->frame_id = (uint64_t*)((uint8_t*)this->addr + this->len); +} + + +int VisionBuf::sync(int dir) { + int err = 0; + if (!this->buf_cl) return 0; + + if (dir == VISIONBUF_SYNC_FROM_DEVICE) { + err = clEnqueueReadBuffer(this->copy_q, this->buf_cl, CL_FALSE, 0, this->len, this->addr, 0, NULL, NULL); + } else { + err = clEnqueueWriteBuffer(this->copy_q, this->buf_cl, CL_FALSE, 0, this->len, this->addr, 0, NULL, NULL); + } + + if (err == 0){ + err = clFinish(this->copy_q); + } + + return err; +} + +int VisionBuf::free() { + int err = 0; + if (this->buf_cl){ + err = clReleaseMemObject(this->buf_cl); + if (err != 0) return err; + + err = clReleaseCommandQueue(this->copy_q); + if (err != 0) return err; + } + + err = munmap(this->addr, this->mmap_len); + if (err != 0) return err; + + err = close(this->fd); + return err; +} diff --git a/msgq_repo/msgq/visionipc/visionbuf_ion.cc b/msgq_repo/msgq/visionipc/visionbuf_ion.cc new file mode 100644 index 0000000000..13be154914 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionbuf_ion.cc @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "msgq/visionipc/visionbuf.h" + +// keep trying if x gets interrupted by a signal +#define HANDLE_EINTR(x) \ + ({ \ + decltype(x) ret; \ + int try_cnt = 0; \ + do { \ + ret = (x); \ + } while (ret == -1 && errno == EINTR && try_cnt++ < 100); \ + ret; \ + }) + +// just hard-code these for convenience +// size_t device_page_size = 0; +// clGetDeviceInfo(device_id, CL_DEVICE_PAGE_SIZE_QCOM, +// sizeof(device_page_size), &device_page_size, +// NULL); + +// size_t padding_cl = 0; +// clGetDeviceInfo(device_id, CL_DEVICE_EXT_MEM_PADDING_IN_BYTES_QCOM, +// sizeof(padding_cl), &padding_cl, +// NULL); +#define DEVICE_PAGE_SIZE_CL 4096 +#define PADDING_CL 0 + +struct IonFileHandle { + IonFileHandle() { + fd = open("/dev/ion", O_RDWR | O_NONBLOCK); + assert(fd >= 0); + } + ~IonFileHandle() { + close(fd); + } + int fd = -1; +}; + +int ion_fd() { + static IonFileHandle fh; + return fh.fd; +} + +void VisionBuf::allocate(size_t length) { + struct ion_allocation_data ion_alloc = {0}; + ion_alloc.len = length + PADDING_CL + sizeof(uint64_t); + ion_alloc.align = 4096; + ion_alloc.heap_id_mask = 1 << ION_IOMMU_HEAP_ID; + ion_alloc.flags = ION_FLAG_CACHED; + + int err = HANDLE_EINTR(ioctl(ion_fd(), ION_IOC_ALLOC, &ion_alloc)); + assert(err == 0); + + struct ion_fd_data ion_fd_data = {0}; + ion_fd_data.handle = ion_alloc.handle; + err = HANDLE_EINTR(ioctl(ion_fd(), ION_IOC_SHARE, &ion_fd_data)); + assert(err == 0); + + void *mmap_addr = mmap(NULL, ion_alloc.len, + PROT_READ | PROT_WRITE, + MAP_SHARED, ion_fd_data.fd, 0); + assert(mmap_addr != MAP_FAILED); + + memset(mmap_addr, 0, ion_alloc.len); + + this->len = length; + this->mmap_len = ion_alloc.len; + this->addr = mmap_addr; + this->handle = ion_alloc.handle; + this->fd = ion_fd_data.fd; + this->frame_id = (uint64_t*)((uint8_t*)this->addr + this->len + PADDING_CL); +} + +void VisionBuf::import(){ + int err; + assert(this->fd >= 0); + + // Get handle + struct ion_fd_data fd_data = {0}; + fd_data.fd = this->fd; + err = HANDLE_EINTR(ioctl(ion_fd(), ION_IOC_IMPORT, &fd_data)); + assert(err == 0); + + this->handle = fd_data.handle; + this->addr = mmap(NULL, this->mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED, this->fd, 0); + assert(this->addr != MAP_FAILED); + + this->frame_id = (uint64_t*)((uint8_t*)this->addr + this->len + PADDING_CL); +} + +void VisionBuf::init_cl(cl_device_id device_id, cl_context ctx) { + int err; + + assert(((uintptr_t)this->addr % DEVICE_PAGE_SIZE_CL) == 0); + + cl_mem_ion_host_ptr ion_cl = {0}; + ion_cl.ext_host_ptr.allocation_type = CL_MEM_ION_HOST_PTR_QCOM; + ion_cl.ext_host_ptr.host_cache_policy = CL_MEM_HOST_UNCACHED_QCOM; + ion_cl.ion_filedesc = this->fd; + ion_cl.ion_hostptr = this->addr; + + this->buf_cl = clCreateBuffer(ctx, + CL_MEM_USE_HOST_PTR | CL_MEM_EXT_HOST_PTR_QCOM, + this->len, &ion_cl, &err); + assert(err == 0); +} + + +int VisionBuf::sync(int dir) { + struct ion_flush_data flush_data = {0}; + flush_data.handle = this->handle; + flush_data.vaddr = this->addr; + flush_data.offset = 0; + flush_data.length = this->len; + + // ION_IOC_INV_CACHES ~= DMA_FROM_DEVICE + // ION_IOC_CLEAN_CACHES ~= DMA_TO_DEVICE + // ION_IOC_CLEAN_INV_CACHES ~= DMA_BIDIRECTIONAL + + struct ion_custom_data custom_data = {0}; + + assert(dir == VISIONBUF_SYNC_FROM_DEVICE || dir == VISIONBUF_SYNC_TO_DEVICE); + custom_data.cmd = (dir == VISIONBUF_SYNC_FROM_DEVICE) ? + ION_IOC_INV_CACHES : ION_IOC_CLEAN_CACHES; + + custom_data.arg = (unsigned long)&flush_data; + return HANDLE_EINTR(ioctl(ion_fd(), ION_IOC_CUSTOM, &custom_data)); +} + +int VisionBuf::free() { + int err = 0; + + if (this->buf_cl){ + err = clReleaseMemObject(this->buf_cl); + if (err != 0) return err; + } + + err = munmap(this->addr, this->mmap_len); + if (err != 0) return err; + + err = close(this->fd); + if (err != 0) return err; + + struct ion_handle_data handle_data = {.handle = this->handle}; + return HANDLE_EINTR(ioctl(ion_fd(), ION_IOC_FREE, &handle_data)); +} diff --git a/msgq_repo/msgq/visionipc/visionipc.cc b/msgq_repo/msgq/visionipc/visionipc.cc new file mode 100644 index 0000000000..48e13c27d9 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc.cc @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __APPLE__ +#define getsocket() socket(AF_UNIX, SOCK_STREAM, 0) +#else +#define getsocket() socket(AF_UNIX, SOCK_SEQPACKET, 0) +#endif + +#include "msgq/visionipc/visionipc.h" + +int ipc_connect(const char* socket_path) { + int err; + + int sock = getsocket(); + + if (sock < 0) return -1; + struct sockaddr_un addr = { + .sun_family = AF_UNIX, + }; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path); + err = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); + if (err != 0) { + close(sock); + return -1; + } + + return sock; +} + +int ipc_bind(const char* socket_path) { + int err; + + unlink(socket_path); + + int sock = getsocket(); + + struct sockaddr_un addr = { + .sun_family = AF_UNIX, + }; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socket_path); + err = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); + assert(err == 0); + + err = listen(sock, 3); + assert(err == 0); + + return sock; +} + + +int ipc_sendrecv_with_fds(bool send, int fd, void *buf, size_t buf_size, int* fds, int num_fds, + int *out_num_fds) { + char control_buf[CMSG_SPACE(sizeof(int) * num_fds)]; + memset(control_buf, 0, CMSG_SPACE(sizeof(int) * num_fds)); + + struct iovec iov = { + .iov_base = buf, + .iov_len = buf_size, + }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + }; + + if (num_fds > 0) { + assert(fds); + + msg.msg_control = control_buf; + msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds); + } + + if (send) { + if (num_fds) { + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + assert(cmsg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); + memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * num_fds); + } + return sendmsg(fd, &msg, 0); + } else { + int r = recvmsg(fd, &msg, 0); + if (r < 0) return r; + + int recv_fds = 0; + if (msg.msg_controllen > 0) { + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + assert(cmsg); + assert(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS); + recv_fds = (cmsg->cmsg_len - CMSG_LEN(0)); + assert(recv_fds > 0 && (recv_fds % sizeof(int)) == 0); + recv_fds /= sizeof(int); + + assert(fds && recv_fds <= num_fds); + memcpy(fds, CMSG_DATA(cmsg), sizeof(int) * recv_fds); + } + + if (msg.msg_flags) { + for (int i=0; i +#include + + +int ipc_connect(const char* socket_path); +int ipc_bind(const char* socket_path); +int ipc_sendrecv_with_fds(bool send, int fd, void *buf, size_t buf_size, int* fds, int num_fds, + int *out_num_fds); + +constexpr int VISIONIPC_MAX_FDS = 128; + +struct VisionIpcBufExtra { + uint32_t frame_id; + uint64_t timestamp_sof; + uint64_t timestamp_eof; + bool valid; +}; + +struct VisionIpcPacket { + uint64_t server_id; + size_t idx; + struct VisionIpcBufExtra extra; +}; diff --git a/msgq_repo/msgq/visionipc/visionipc.pxd b/msgq_repo/msgq/visionipc/visionipc.pxd new file mode 100644 index 0000000000..cce6ee5049 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc.pxd @@ -0,0 +1,61 @@ +# distutils: language = c++ +#cython: language_level=3 + +from libcpp.string cimport string +from libcpp.vector cimport vector +from libcpp.set cimport set +from libc.stdint cimport uint32_t, uint64_t +from libcpp cimport bool, int + +cdef extern from "msgq/visionipc/visionbuf.h": + struct _cl_device_id + struct _cl_context + struct _cl_mem + + ctypedef _cl_device_id * cl_device_id + ctypedef _cl_context * cl_context + ctypedef _cl_mem * cl_mem + + cdef enum VisionStreamType: + pass + + cdef cppclass VisionBuf: + void * addr + int fd + size_t len + size_t width + size_t height + size_t stride + size_t uv_offset + size_t idx + cl_mem buf_cl + void set_frame_id(uint64_t id) + +cdef extern from "msgq/visionipc/visionipc.h": + struct VisionIpcBufExtra: + uint32_t frame_id + uint64_t timestamp_sof + uint64_t timestamp_eof + bool valid + +cdef extern from "msgq/visionipc/visionipc_server.h": + string get_endpoint_name(string, VisionStreamType) + + cdef cppclass VisionIpcServer: + VisionIpcServer(string, void*, void*) + void create_buffers(VisionStreamType, size_t, size_t, size_t) + void create_buffers_with_sizes(VisionStreamType, size_t, size_t, size_t, size_t, size_t, size_t) + VisionBuf * get_buffer(VisionStreamType) + void send(VisionBuf *, VisionIpcBufExtra *, bool) + void start_listener() + +cdef extern from "msgq/visionipc/visionipc_client.h": + cdef cppclass VisionIpcClient: + int num_buffers + VisionBuf buffers[1] + VisionIpcClient(string, VisionStreamType, bool, void*, void*) + VisionBuf * recv(VisionIpcBufExtra *, int) + bool connect(bool) + bool is_connected() + @staticmethod + set[VisionStreamType] getAvailableStreams(string, bool) diff --git a/msgq_repo/msgq/visionipc/visionipc_client.cc b/msgq_repo/msgq/visionipc/visionipc_client.cc new file mode 100644 index 0000000000..3601119fbf --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_client.cc @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "msgq/visionipc/visionipc.h" +#include "msgq/visionipc/visionipc_client.h" +#include "msgq/visionipc/visionipc_server.h" +#include "msgq/logger/logger.h" + +static int connect_to_vipc_server(const std::string &name, bool blocking) { + const std::string ipc_path = get_ipc_path(name); + int socket_fd = ipc_connect(ipc_path.c_str()); + while (socket_fd < 0 && blocking) { + std::cout << "VisionIpcClient connecting" << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + socket_fd = ipc_connect(ipc_path.c_str()); + } + return socket_fd; +} + +VisionIpcClient::VisionIpcClient(std::string name, VisionStreamType type, bool conflate, cl_device_id device_id, cl_context ctx) : name(name), type(type), device_id(device_id), ctx(ctx) { + msg_ctx = Context::create(); + sock = SubSocket::create(msg_ctx, get_endpoint_name(name, type), "127.0.0.1", conflate, false); + + poller = Poller::create(); + poller->registerSocket(sock); +} + +// Connect is not thread safe. Do not use the buffers while calling connect +bool VisionIpcClient::connect(bool blocking){ + connected = false; + + // Cleanup old buffers on reconnect + for (size_t i = 0; i < num_buffers; i++){ + if (buffers[i].free() != 0) { + LOGE("Failed to free buffer %zu", i); + } + } + + num_buffers = 0; + + int socket_fd = connect_to_vipc_server(name, blocking); + if (socket_fd < 0) { + return false; + } + // Send stream type to server to request FDs + int r = ipc_sendrecv_with_fds(true, socket_fd, &type, sizeof(type), nullptr, 0, nullptr); + assert(r == sizeof(type)); + + // Get FDs + int fds[VISIONIPC_MAX_FDS]; + VisionBuf bufs[VISIONIPC_MAX_FDS]; + r = ipc_sendrecv_with_fds(false, socket_fd, &bufs, sizeof(bufs), fds, VISIONIPC_MAX_FDS, &num_buffers); + if (r < 0) { + // only expected error is server shutting down + assert(errno == ECONNRESET); + close(socket_fd); + return false; + } + + assert(num_buffers >= 0); + assert(r == sizeof(VisionBuf) * num_buffers); + + // Import buffers + for (size_t i = 0; i < num_buffers; i++){ + buffers[i] = bufs[i]; + buffers[i].fd = fds[i]; + buffers[i].import(); + buffers[i].init_yuv(buffers[i].width, buffers[i].height, buffers[i].stride, buffers[i].uv_offset); + + if (device_id) buffers[i].init_cl(device_id, ctx); + } + + close(socket_fd); + connected = true; + return true; +} + +VisionBuf * VisionIpcClient::recv(VisionIpcBufExtra * extra, const int timeout_ms){ + auto p = poller->poll(timeout_ms); + + if (!p.size()){ + return nullptr; + } + + Message * r = sock->receive(true); + if (r == nullptr){ + return nullptr; + } + + // Get buffer + assert(r->getSize() == sizeof(VisionIpcPacket)); + VisionIpcPacket *packet = (VisionIpcPacket*)r->getData(); + + assert(packet->idx < num_buffers); + VisionBuf * buf = &buffers[packet->idx]; + + if (buf->server_id != packet->server_id){ + connected = false; + delete r; + return nullptr; + } + + if (extra) { + *extra = packet->extra; + } + + if (buf->sync(VISIONBUF_SYNC_TO_DEVICE) != 0) { + LOGE("Failed to sync buffer"); + } + + delete r; + return buf; +} + +std::set VisionIpcClient::getAvailableStreams(const std::string &name, bool blocking) { + int socket_fd = connect_to_vipc_server(name, blocking); + if (socket_fd < 0) { + return {}; + } + // Send VISION_STREAM_MAX to server to request available streams + int request = VISION_STREAM_MAX; + int r = ipc_sendrecv_with_fds(true, socket_fd, &request, sizeof(request), nullptr, 0, nullptr); + assert(r == sizeof(request)); + + VisionStreamType available_streams[VISION_STREAM_MAX] = {}; + r = ipc_sendrecv_with_fds(false, socket_fd, &available_streams, sizeof(available_streams), nullptr, 0, nullptr); + if (r < 0) { + // only expected error is server shutting down + assert(errno == ECONNRESET); + close(socket_fd); + return {}; + } + + assert(r % sizeof(VisionStreamType) == 0); + close(socket_fd); + return std::set(available_streams, available_streams + r / sizeof(VisionStreamType)); +} + +VisionIpcClient::~VisionIpcClient(){ + for (size_t i = 0; i < num_buffers; i++){ + if (buffers[i].free() != 0) { + LOGE("Failed to free buffer %zu", i); + } + } + + delete sock; + delete poller; + delete msg_ctx; +} diff --git a/msgq_repo/msgq/visionipc/visionipc_client.h b/msgq_repo/msgq/visionipc/visionipc_client.h new file mode 100644 index 0000000000..e4abdc5de3 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_client.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "msgq/ipc.h" +#include "msgq/visionipc/visionbuf.h" + + +class VisionIpcClient { +private: + std::string name; + Context * msg_ctx; + SubSocket * sock; + Poller * poller; + + cl_device_id device_id = nullptr; + cl_context ctx = nullptr; + +public: + bool connected = false; + VisionStreamType type; + int num_buffers = 0; + VisionBuf buffers[VISIONIPC_MAX_FDS]; + VisionIpcClient(std::string name, VisionStreamType type, bool conflate, cl_device_id device_id=nullptr, cl_context ctx=nullptr); + ~VisionIpcClient(); + VisionBuf * recv(VisionIpcBufExtra * extra=nullptr, const int timeout_ms=100); + bool connect(bool blocking=true); + bool is_connected() { return connected; } + static std::set getAvailableStreams(const std::string &name, bool blocking = true); +}; diff --git a/msgq_repo/msgq/visionipc/visionipc_pyx.pxd b/msgq_repo/msgq/visionipc/visionipc_pyx.pxd new file mode 100644 index 0000000000..ec431ceecd --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_pyx.pxd @@ -0,0 +1,15 @@ +# distutils: language = c++ +#cython: language_level=3 + +from .visionipc cimport VisionBuf as cppVisionBuf +from .visionipc cimport cl_device_id, cl_context + +cdef class CLContext: + cdef cl_device_id device_id + cdef cl_context context + +cdef class VisionBuf: + cdef cppVisionBuf * buf + + @staticmethod + cdef create(cppVisionBuf*) diff --git a/msgq_repo/msgq/visionipc/visionipc_pyx.pyx b/msgq_repo/msgq/visionipc/visionipc_pyx.pyx new file mode 100644 index 0000000000..7f4d2209a0 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_pyx.pyx @@ -0,0 +1,168 @@ +# distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + +import sys +import numpy as np +cimport numpy as cnp +from cython.view cimport array +from libc.string cimport memcpy +from libc.stdint cimport uint32_t, uint64_t +from libcpp cimport bool +from libcpp.string cimport string + +from .visionipc cimport VisionIpcServer as cppVisionIpcServer +from .visionipc cimport VisionIpcClient as cppVisionIpcClient +from .visionipc cimport VisionBuf as cppVisionBuf +from .visionipc cimport VisionIpcBufExtra +from .visionipc cimport get_endpoint_name as cpp_get_endpoint_name + + +def get_endpoint_name(string name, VisionStreamType stream): + return cpp_get_endpoint_name(name, stream).decode('utf-8') + + +cpdef enum VisionStreamType: + VISION_STREAM_ROAD + VISION_STREAM_DRIVER + VISION_STREAM_WIDE_ROAD + VISION_STREAM_MAP + + +cdef class VisionBuf: + @staticmethod + cdef create(cppVisionBuf * cbuf): + buf = VisionBuf() + buf.buf = cbuf + return buf + + @property + def data(self): + return np.asarray( self.buf.addr) + + @property + def width(self): + return self.buf.width + + @property + def height(self): + return self.buf.height + + @property + def stride(self): + return self.buf.stride + + @property + def uv_offset(self): + return self.buf.uv_offset + + @property + def idx(self): + return self.buf.idx + + @property + def fd(self): + return self.buf.fd + + +cdef class VisionIpcServer: + cdef cppVisionIpcServer * server + + def __init__(self, string name): + self.server = new cppVisionIpcServer(name, NULL, NULL) + + def create_buffers(self, VisionStreamType tp, size_t num_buffers, size_t width, size_t height): + self.server.create_buffers(tp, num_buffers, width, height) + + def create_buffers_with_sizes(self, VisionStreamType tp, size_t num_buffers, size_t width, size_t height, size_t size, size_t stride, size_t uv_offset): + self.server.create_buffers_with_sizes(tp, num_buffers, width, height, size, stride, uv_offset) + + def send(self, VisionStreamType tp, const unsigned char[:] data, uint32_t frame_id=0, uint64_t timestamp_sof=0, uint64_t timestamp_eof=0): + cdef cppVisionBuf * buf = self.server.get_buffer(tp) + + # Populate buffer + assert buf.len == len(data) + memcpy(buf.addr, &data[0], len(data)) + buf.set_frame_id(frame_id) + + cdef VisionIpcBufExtra extra + extra.frame_id = frame_id + extra.timestamp_sof = timestamp_sof + extra.timestamp_eof = timestamp_eof + + self.server.send(buf, &extra, False) + + def start_listener(self): + self.server.start_listener() + + def __dealloc__(self): + del self.server + + +cdef class VisionIpcClient: + cdef cppVisionIpcClient * client + cdef VisionIpcBufExtra extra + + def __cinit__(self, string name, VisionStreamType stream, bool conflate, CLContext context = None): + if context: + self.client = new cppVisionIpcClient(name, stream, conflate, context.device_id, context.context) + else: + self.client = new cppVisionIpcClient(name, stream, conflate, NULL, NULL) + + def __dealloc__(self): + del self.client + + @property + def width(self): + return self.client.buffers[0].width if self.client.num_buffers else None + + @property + def height(self): + return self.client.buffers[0].height if self.client.num_buffers else None + + @property + def stride(self): + return self.client.buffers[0].stride if self.client.num_buffers else None + + @property + def uv_offset(self): + return self.client.buffers[0].uv_offset if self.client.num_buffers else None + + @property + def buffer_len(self): + return self.client.buffers[0].len if self.client.num_buffers else None + + @property + def num_buffers(self): + return self.client.num_buffers + + @property + def frame_id(self): + return self.extra.frame_id + + @property + def timestamp_sof(self): + return self.extra.timestamp_sof + + @property + def timestamp_eof(self): + return self.extra.timestamp_eof + + @property + def valid(self): + return self.extra.valid + + def recv(self, int timeout_ms=100): + buf = self.client.recv(&self.extra, timeout_ms) + if not buf: + return None + return VisionBuf.create(buf) + + def connect(self, bool blocking): + return self.client.connect(blocking) + + def is_connected(self): + return self.client.is_connected() + + @staticmethod + def available_streams(string name, bool block): + return cppVisionIpcClient.getAvailableStreams(name, block) diff --git a/msgq_repo/msgq/visionipc/visionipc_server.cc b/msgq_repo/msgq/visionipc/visionipc_server.cc new file mode 100644 index 0000000000..0b8579c875 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_server.cc @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "msgq/ipc.h" +#include "msgq/visionipc/visionipc.h" +#include "msgq/visionipc/visionipc_server.h" +#include "msgq/logger/logger.h" + +std::string get_endpoint_name(std::string name, VisionStreamType type){ + if (messaging_use_zmq()){ + assert(name == "camerad" || name == "navd"); + return std::to_string(9000 + static_cast(type)); + } else { + return "visionipc_" + name + "_" + std::to_string(type); + } +} + +std::string get_ipc_path(const std::string& name) { + std::string path = "/tmp/"; + if (char* prefix = std::getenv("OPENPILOT_PREFIX")) { + path += std::string(prefix) + "_"; + } + return path + "visionipc_" + name; +} + +VisionIpcServer::VisionIpcServer(std::string name, cl_device_id device_id, cl_context ctx) : name(name), device_id(device_id), ctx(ctx) { + msg_ctx = Context::create(); + + std::random_device rd("/dev/urandom"); + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + server_id = distribution(rd); +} + +void VisionIpcServer::create_buffers(VisionStreamType type, size_t num_buffers, size_t width, size_t height){ + // TODO: assert that this type is not created yet + assert(num_buffers < VISIONIPC_MAX_FDS); + + size_t size = 0; + size_t stride = 0; + size_t uv_offset = 0; + + size = width * height * 3 / 2; + stride = width; + uv_offset = width * height; + + create_buffers_with_sizes(type, num_buffers, width, height, size, stride, uv_offset); +} + +void VisionIpcServer::create_buffers_with_sizes(VisionStreamType type, size_t num_buffers, size_t width, size_t height, size_t size, size_t stride, size_t uv_offset) { + // Create map + alloc requested buffers + for (size_t i = 0; i < num_buffers; i++){ + VisionBuf* buf = new VisionBuf(); + buf->allocate(size); + buf->idx = i; + buf->type = type; + + if (device_id) buf->init_cl(device_id, ctx); + + buf->init_yuv(width, height, stride, uv_offset); + + buffers[type].push_back(buf); + } + + cur_idx[type] = 0; + + // Create msgq publisher for each of the `name` + type combos + // TODO: compute port number directly if using zmq + sockets[type] = PubSocket::create(msg_ctx, get_endpoint_name(name, type), false); +} + + +void VisionIpcServer::start_listener(){ + listener_thread = std::thread(&VisionIpcServer::listener, this); +} + + +void VisionIpcServer::listener(){ + std::cout << "Starting listener for: " << name << std::endl; + + const std::string ipc_path = get_ipc_path(name); + int sock = ipc_bind(ipc_path.c_str()); + assert(sock >= 0); + + while (!should_exit){ + // Wait for incoming connection + struct pollfd polls[1] = {{0}}; + polls[0].fd = sock; + polls[0].events = POLLIN; + + int ret = poll(polls, 1, 100); + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN) continue; + std::cout << "poll failed, stopping listener" << std::endl; + break; + } + + if (should_exit) break; + if (!polls[0].revents) { + continue; + } + + // Handle incoming request + int fd = accept(sock, NULL, NULL); + assert(fd >= 0); + + VisionStreamType type = VisionStreamType::VISION_STREAM_MAX; + int r = ipc_sendrecv_with_fds(false, fd, &type, sizeof(type), nullptr, 0, nullptr); + assert(r == sizeof(type)); + + // send available stream types + if (type == VisionStreamType::VISION_STREAM_MAX) { + std::vector available_stream_types; + for (auto& [stream_type, _] : buffers) { + available_stream_types.push_back(stream_type); + } + r = ipc_sendrecv_with_fds(true, fd, available_stream_types.data(), available_stream_types.size() * sizeof(VisionStreamType), nullptr, 0, nullptr); + assert(r == available_stream_types.size() * sizeof(VisionStreamType)); + close(fd); + continue; + } + + if (buffers.count(type) <= 0) { + std::cout << "got request for invalid buffer type: " << type << std::endl; + close(fd); + continue; + } + + int fds[VISIONIPC_MAX_FDS]; + int num_fds = buffers[type].size(); + VisionBuf bufs[VISIONIPC_MAX_FDS]; + + for (int i = 0; i < num_fds; i++){ + fds[i] = buffers[type][i]->fd; + bufs[i] = *buffers[type][i]; + + // Remove some private openCL/ion metadata + bufs[i].buf_cl = 0; + bufs[i].copy_q = 0; + bufs[i].handle = 0; + + bufs[i].server_id = server_id; + } + + r = ipc_sendrecv_with_fds(true, fd, &bufs, sizeof(VisionBuf) * num_fds, fds, num_fds, nullptr); + + close(fd); + } + + std::cout << "Stopping listener for: " << name << std::endl; + close(sock); + unlink(ipc_path.c_str()); +} + + + +VisionBuf * VisionIpcServer::get_buffer(VisionStreamType type, int idx){ + // Do we want to keep track if the buffer has been sent out yet and warn user? + assert(buffers.count(type)); + auto b = buffers[type]; + if (idx < 0) { + idx = cur_idx[type]++ % b.size(); + } else { + assert(idx < b.size() && idx >= 0); + cur_idx[type] = idx; + } + return b[idx]; +} + +void VisionIpcServer::send(VisionBuf * buf, VisionIpcBufExtra * extra, bool sync){ + if (sync) { + if (buf->sync(VISIONBUF_SYNC_FROM_DEVICE) != 0) { + LOGE("Failed to sync buffer"); + } + } + assert(buffers.count(buf->type)); + assert(buf->idx < buffers[buf->type].size()); + + // Send over correct msgq socket + VisionIpcPacket packet = {0}; + packet.server_id = server_id; + packet.idx = buf->idx; + packet.extra = *extra; + + sockets[buf->type]->send((char*)&packet, sizeof(packet)); +} + +VisionIpcServer::~VisionIpcServer(){ + should_exit = true; + listener_thread.join(); + + // VisionBuf cleanup + for (auto const& [type, buf] : buffers) { + for (VisionBuf* b : buf){ + if (b->free() != 0) { + LOGE("Failed to free buffer"); + } + delete b; + } + } + + // Messaging cleanup + for (auto const& [type, sock] : sockets) { + delete sock; + } + delete msg_ctx; +} diff --git a/msgq_repo/msgq/visionipc/visionipc_server.h b/msgq_repo/msgq/visionipc/visionipc_server.h new file mode 100644 index 0000000000..b96f498485 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_server.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include +#include +#include +#include + +#include "msgq/ipc.h" +#include "msgq/visionipc/visionbuf.h" + +std::string get_endpoint_name(std::string name, VisionStreamType type); +std::string get_ipc_path(const std::string &name); + +class VisionIpcServer { + private: + cl_device_id device_id = nullptr; + cl_context ctx = nullptr; + uint64_t server_id; + + std::atomic should_exit = false; + std::string name; + std::thread listener_thread; + + std::map > cur_idx; + std::map > buffers; + + Context * msg_ctx; + std::map sockets; + + void listener(void); + + public: + VisionIpcServer(std::string name, cl_device_id device_id=nullptr, cl_context ctx=nullptr); + ~VisionIpcServer(); + + VisionBuf * get_buffer(VisionStreamType type, int idx = -1); + + void create_buffers(VisionStreamType type, size_t num_buffers, size_t width, size_t height); + void create_buffers_with_sizes(VisionStreamType type, size_t num_buffers, size_t width, size_t height, size_t size, size_t stride, size_t uv_offset); + void send(VisionBuf * buf, VisionIpcBufExtra * extra, bool sync=true); + void start_listener(); +}; diff --git a/msgq_repo/msgq/visionipc/visionipc_tests.cc b/msgq_repo/msgq/visionipc/visionipc_tests.cc new file mode 100644 index 0000000000..ddf790df76 --- /dev/null +++ b/msgq_repo/msgq/visionipc/visionipc_tests.cc @@ -0,0 +1,135 @@ +#include +#include + +#include "catch2/catch.hpp" + +#include "msgq/visionipc/visionipc_server.h" +#include "msgq/visionipc/visionipc_client.h" + + +static void zmq_sleep(int milliseconds=1000){ + if (messaging_use_zmq()){ + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); + } +} + +TEST_CASE("Connecting"){ + VisionIpcServer server("camerad"); + server.create_buffers(VISION_STREAM_ROAD, 1, 100, 100); + server.start_listener(); + + VisionIpcClient client = VisionIpcClient("camerad", VISION_STREAM_ROAD, false); + REQUIRE(client.connect()); + + REQUIRE(client.connected); +} + +TEST_CASE("getAvailableStreams"){ + VisionIpcServer server("camerad"); + server.create_buffers(VISION_STREAM_ROAD, 1, 100, 100); + server.create_buffers(VISION_STREAM_WIDE_ROAD, 1, 100, 100); + server.start_listener(); + auto available_streams = VisionIpcClient::getAvailableStreams("camerad"); + REQUIRE(available_streams.size() == 2); + REQUIRE(available_streams.count(VISION_STREAM_ROAD) == 1); + REQUIRE(available_streams.count(VISION_STREAM_WIDE_ROAD) == 1); +} + +TEST_CASE("Check buffers"){ + size_t width = 100, height = 200, num_buffers = 5; + VisionIpcServer server("camerad"); + server.create_buffers(VISION_STREAM_ROAD, num_buffers, width, height); + server.start_listener(); + + VisionIpcClient client = VisionIpcClient("camerad", VISION_STREAM_ROAD, false); + REQUIRE(client.connect()); + + REQUIRE(client.buffers[0].width == width); + REQUIRE(client.buffers[0].height == height); + REQUIRE(client.buffers[0].len); + REQUIRE(client.num_buffers == num_buffers); +} + +TEST_CASE("Send single buffer"){ + VisionIpcServer server("camerad"); + server.create_buffers(VISION_STREAM_ROAD, 1, 100, 100); + server.start_listener(); + + VisionIpcClient client = VisionIpcClient("camerad", VISION_STREAM_ROAD, false); + REQUIRE(client.connect()); + zmq_sleep(); + + VisionBuf * buf = server.get_buffer(VISION_STREAM_ROAD); + REQUIRE(buf != nullptr); + + *((uint64_t*)buf->addr) = 1234; + + VisionIpcBufExtra extra = {0}; + extra.frame_id = 1337; + buf->set_frame_id(extra.frame_id); + + server.send(buf, &extra); + + VisionIpcBufExtra extra_recv = {0}; + VisionBuf * recv_buf = client.recv(&extra_recv); + REQUIRE(recv_buf != nullptr); + REQUIRE(*(uint64_t*)recv_buf->addr == 1234); + REQUIRE(extra_recv.frame_id == extra.frame_id); + REQUIRE(recv_buf->get_frame_id() == extra.frame_id); +} + + +TEST_CASE("Test no conflate"){ + VisionIpcServer server("camerad"); + server.create_buffers(VISION_STREAM_ROAD, 1, 100, 100); + server.start_listener(); + + VisionIpcClient client = VisionIpcClient("camerad", VISION_STREAM_ROAD, false); + REQUIRE(client.connect()); + zmq_sleep(); + + VisionBuf * buf = server.get_buffer(VISION_STREAM_ROAD); + REQUIRE(buf != nullptr); + + VisionIpcBufExtra extra = {0}; + extra.frame_id = 1; + server.send(buf, &extra); + extra.frame_id = 2; + server.send(buf, &extra); + + VisionIpcBufExtra extra_recv = {0}; + VisionBuf * recv_buf = client.recv(&extra_recv); + REQUIRE(recv_buf != nullptr); + REQUIRE(extra_recv.frame_id == 1); + + recv_buf = client.recv(&extra_recv); + REQUIRE(recv_buf != nullptr); + REQUIRE(extra_recv.frame_id == 2); +} + +TEST_CASE("Test conflate"){ + VisionIpcServer server("camerad"); + server.create_buffers(VISION_STREAM_ROAD, 1, 100, 100); + server.start_listener(); + + VisionIpcClient client = VisionIpcClient("camerad", VISION_STREAM_ROAD, true); + REQUIRE(client.connect()); + zmq_sleep(); + + VisionBuf * buf = server.get_buffer(VISION_STREAM_ROAD); + REQUIRE(buf != nullptr); + + VisionIpcBufExtra extra = {0}; + extra.frame_id = 1; + server.send(buf, &extra); + extra.frame_id = 2; + server.send(buf, &extra); + + VisionIpcBufExtra extra_recv = {0}; + VisionBuf * recv_buf = client.recv(&extra_recv); + REQUIRE(recv_buf != nullptr); + REQUIRE(extra_recv.frame_id == 2); + + recv_buf = client.recv(&extra_recv); + REQUIRE(recv_buf == nullptr); +} diff --git a/msgq_repo/pyproject.toml b/msgq_repo/pyproject.toml new file mode 100644 index 0000000000..d7c4e336b3 --- /dev/null +++ b/msgq_repo/pyproject.toml @@ -0,0 +1,58 @@ +[project] +name = "msgq" +version = "0.0.1" +description = "Code powering the comma.ai panda" +readme = "README.md" +requires-python = ">=3.11,<3.13" +license = {text = "MIT"} +authors = [{name = "comma.ai"}] +classifiers = [ + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Topic :: System :: Hardware", +] +dependencies = [ + "setuptools", # for distutils + "Cython", + "scons", + "pre-commit", + "ruff", + "parameterized", + "coverage", + "numpy", + "pytest", + "cppcheck", +] + +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +lint.select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF100", "A"] +lint.ignore = ["W292", "E741", "E402", "C408", "ISC003"] +lint.flake8-implicit-str-concat.allow-multiline=false + +line-length = 160 +target-version="py311" + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" +"unittest".msg = "Use pytest" + +[tool.mypy] +# third-party packages +ignore_missing_imports=true + +# helpful warnings +warn_redundant_casts=true +warn_unreachable=true +warn_unused_ignores=true + +# restrict dynamic typing +warn_return_any=true +check_untyped_defs=true + +[tool.pytest.ini_options] +addopts = "--durations=10" +testpaths = [ + "msgq/tests", + "msgq/visionipc/tests", +] diff --git a/msgq_repo/setup.sh b/msgq_repo/setup.sh new file mode 100755 index 0000000000..8d06116288 --- /dev/null +++ b/msgq_repo/setup.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +PLATFORM=$(uname -s) + +echo "installing dependencies" +if [[ $PLATFORM == "Darwin" ]]; then + export ZMQ=1 + + export HOMEBREW_NO_AUTO_UPDATE=1 + brew install python3 zeromq +elif [[ $PLATFORM == "Linux" ]]; then + # for AGNOS since we clear the apt lists + if [[ ! -d /"var/lib/apt/" ]]; then + sudo apt update + fi + + sudo apt-get install -y --no-install-recommends \ + curl ca-certificates \ + libzmq3-dev \ + ocl-icd-opencl-dev opencl-headers \ + python3-dev python3-pip python3-venv +else + echo "WARNING: unsupported platform. skipping apt/brew install." +fi + +# catch2 +if [ ! -d $DIR/msgq/catch2/ ]; then + rm -rf /tmp/catch2/ $DIR/msgq/catch2/ + git clone -b v2.x --depth 1 https://github.com/catchorg/Catch2.git /tmp/catch2 + pushd /tmp/catch2 + mv single_include/* $DIR/msgq/ + popd +fi + +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh + + # doesn't require sourcing on all platforms + set +e + source $HOME/.local/bin/env + set -e +fi + +export UV_PROJECT_ENVIRONMENT="$DIR/.venv" +uv sync --all-extras +source "$DIR/.venv/bin/activate" diff --git a/msgq_repo/site_scons/site_tools/cython.py b/msgq_repo/site_scons/site_tools/cython.py new file mode 100644 index 0000000000..c291475533 --- /dev/null +++ b/msgq_repo/site_scons/site_tools/cython.py @@ -0,0 +1,72 @@ +import re +import SCons +from SCons.Action import Action +from SCons.Scanner import Scanner + +pyx_from_import_re = re.compile(r'^from\s+(\S+)\s+cimport', re.M) +pyx_import_re = re.compile(r'^cimport\s+(\S+)', re.M) +cdef_import_re = re.compile(r'^cdef extern from\s+.(\S+).:', re.M) + + +def pyx_scan(node, env, path, arg=None): + contents = node.get_text_contents() + + # from cimport ... + matches = pyx_from_import_re.findall(contents) + # cimport + matches += pyx_import_re.findall(contents) + + # Modules can be either .pxd or .pyx files + files = [m.replace('.', '/') + '.pxd' for m in matches] + files += [m.replace('.', '/') + '.pyx' for m in matches] + + # cdef extern from + files += cdef_import_re.findall(contents) + + # Handle relative imports + cur_dir = str(node.get_dir()) + files = [cur_dir + f if f.startswith('/') else f for f in files] + + # Filter out non-existing files (probably system imports) + files = [f for f in files if env.File(f).exists()] + return env.File(files) + + +pyxscanner = Scanner(function=pyx_scan, skeys=['.pyx', '.pxd'], recursive=True) +cythonAction = Action("$CYTHONCOM") + + +def create_builder(env): + try: + cython = env['BUILDERS']['Cython'] + except KeyError: + cython = SCons.Builder.Builder( + action=cythonAction, + emitter={}, + suffix=cython_suffix_emitter, + single_source=1 + ) + env.Append(SCANNERS=pyxscanner) + env['BUILDERS']['Cython'] = cython + return cython + +def cython_suffix_emitter(env, source): + return "$CYTHONCFILESUFFIX" + +def generate(env): + env["CYTHON"] = "cythonize" + env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS $SOURCE" + env["CYTHONCFILESUFFIX"] = ".cpp" + + c_file, _ = SCons.Tool.createCFileBuilders(env) + + c_file.suffix['.pyx'] = cython_suffix_emitter + c_file.add_action('.pyx', cythonAction) + + c_file.suffix['.py'] = cython_suffix_emitter + c_file.add_action('.py', cythonAction) + + create_builder(env) + +def exists(env): + return True diff --git a/msgq_repo/test.sh b/msgq_repo/test.sh new file mode 100755 index 0000000000..e0cfe7c2ae --- /dev/null +++ b/msgq_repo/test.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +# *** env setup *** +source ./setup.sh + +# *** build *** +scons -j8 + +# *** lint *** +#ruff check . +#mypy python/ +pre-commit run --all-files + +# *** test *** +pytest diff --git a/opendbc b/opendbc new file mode 120000 index 0000000000..7cd9a5bd1e --- /dev/null +++ b/opendbc @@ -0,0 +1 @@ +opendbc_repo/opendbc \ No newline at end of file diff --git a/opendbc_repo/.github/labeler.yaml b/opendbc_repo/.github/labeler.yaml new file mode 100644 index 0000000000..520e2d12a5 --- /dev/null +++ b/opendbc_repo/.github/labeler.yaml @@ -0,0 +1,76 @@ +CI / testing: + - changed-files: + - any-glob-to-any-file: '.github/**' + +car: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/**' + +car safety: + - changed-files: + - any-glob-to-any-file: 'opendbc/safety/**' + +can: + - changed-files: + - any-glob-to-any-file: 'opendbc/can/**' + +DBC signals: + - changed-files: + - any-glob-to-any-file: 'opendbc/dbc/**' + + +body: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/body/**' + +chrysler: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/chrysler/**' + +ford: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/ford/**' + +gm: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/gm/**' + +honda: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/honda/**' + +hyundai: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/hyundai/**' + +mazda: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/mazda/**' + +nissan: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/nissan/**' + +rivian: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/rivian/**' + +subaru: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/subaru/**' + +tesla: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/tesla/**' + +toyota: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/toyota/**' + +volkswagen: + - changed-files: + - any-glob-to-any-file: 'opendbc/car/volkswagen/**' + +fingerprint: + - changed-files: + - any-glob-to-all-files: 'opendbc/car/*/fingerprints.py' diff --git a/opendbc_repo/.github/pull_request_template.md b/opendbc_repo/.github/pull_request_template.md new file mode 100644 index 0000000000..39601109dc --- /dev/null +++ b/opendbc_repo/.github/pull_request_template.md @@ -0,0 +1,9 @@ + +Validation +* Dongle ID: +* Route: diff --git a/opendbc_repo/.gitignore b/opendbc_repo/.gitignore new file mode 100644 index 0000000000..5a595d00af --- /dev/null +++ b/opendbc_repo/.gitignore @@ -0,0 +1,35 @@ +.cache/ +/build/ +.mypy_cache/ +*.pyc +*.os +*.o +*.so +*.a +*.tmp +*.dylib +.*.swp +.DS_Store +.sconsign.dblite +.hypothesis +*.egg-info/ +*.html +*.gcda +*.gcno +*.dump +*.gcov +uv.lock +/dist/ +.vscode/ +__pycache__/ +mull.yml +*.profraw + +opendbc/can/build/ +opendbc/can/obj/ +opendbc/dbc/*_generated.dbc + +cppcheck-addon-ctu-file-list +opendbc/safety/tests/coverage-out + +compile_commands.json diff --git a/opendbc_repo/LICENSE b/opendbc_repo/LICENSE new file mode 100644 index 0000000000..f1fd199c63 --- /dev/null +++ b/opendbc_repo/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2020, 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/opendbc_repo/MANIFEST.in b/opendbc_repo/MANIFEST.in new file mode 100644 index 0000000000..a8583dc97b --- /dev/null +++ b/opendbc_repo/MANIFEST.in @@ -0,0 +1,3 @@ +include opendbc/car/car.capnp +include opendbc/car/include/c++.capnp +recursive-include opendbc/safety *.h diff --git a/opendbc_repo/README.md b/opendbc_repo/README.md new file mode 100644 index 0000000000..1149cd208c --- /dev/null +++ b/opendbc_repo/README.md @@ -0,0 +1,196 @@ +
    + +

    opendbc

    +

    + opendbc is a Python API for your car. +
    + Control the gas, brake, steering, and more. Read the speed, steering angle, and more. +

    + +

    + Docs + · + Contribute + · + Discord +

    + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +[![X Follow](https://img.shields.io/twitter/follow/comma_ai)](https://x.com/comma_ai) +[![Discord](https://img.shields.io/discord/469524606043160576)](https://discord.comma.ai) + +
    + +--- + +Most cars since 2016 have electronically-actuatable steering, gas, and brakes thanks to [LKAS](https://en.wikipedia.org/wiki/Lane_departure_warning_system#Lane_keeping_and_next_technologies) and [ACC](https://en.wikipedia.org/wiki/Adaptive_cruise_control). +The goal of this project is to support controlling the steering, gas, and brakes on every single one of those cars. + +While the primary focus is on supporting ADAS interfaces for [openpilot](https://github.com/commaai/openpilot), we're also interested in reading and writing as many things as we can (EV charge status, lock/unlocking doors, etc) such that we can build the best vehicle management app ever. + +--- + +This README and the [supported cars list](docs/CARS.md) are all the docs for the opendbc project. +Everything you need to know to use, contribute, and extend opendbc are in these docs. + +## Quick start + +```bash +git clone https://github.com/commaai/opendbc.git +cd opendbc + +# you probably just want to use this. it's an all-in-one for dependency +# installation, compiling, linting, and tests. it's also what runs in CI +./test.sh + +# here are the individual commands it runs +pip3 install -e .[testing,docs] # install dependencies +scons -j8 # build with 8 cores +pytest . # run the tests +lefthook run lint # run the linter +``` + +[`examples/`](examples/) contains small example programs that can read state from the car and control the steering, gas, and brakes. +[`examples/joystick.py`](examples/joystick.py) allows you to control a car with a joystick. + +### Project Structure +* [`opendbc/dbc/`](opendbc/dbc/) is a repository of [DBC](https://en.wikipedia.org/wiki/CAN_bus#DBC_(CAN_Database_Files)) files +* [`opendbc/can/`](opendbc/can/) is a library for parsing and building CAN messages from DBC files +* [`opendbc/car/`](opendbc/car/) is a high-level library for interfacing with cars using Python +* [`opendbc/safety/`](opendbc/safety/) is the functional safety for all the cars supported by `opendbc/car/` + +## How to Port a Car + +This guide covers everything from adding support to a new car all the way to improving existing cars (e.g. adding longitudinal control or radar parsing). If similar cars to yours are already compatible, most of this work is likely already done for you. + +At its most basic, a car port will control the steering on a car. A "complete" car port will have all of: lateral control, longitudinal control, good tuning for both lateral and longitudinal, radar parsing (if equipped), fuzzy fingerprinting, and more. The new car support docs will clearly communicate each car's support level. + +### Connect to the Car + +The first step is to get connected to the car with a comma 3X and a car harness. +The car harness gets you connected to two different CAN buses and splits one of those buses to send our own actuation messages. + +If you're lucky, a harness compatible with your car will already be designed and sold on comma.ai/shop. +If you're not so lucky, start with a "developer harness" from comma.ai/shop and crimp on whatever connector you need. + +### Structure of a port + +Depending on the brand, most of this basic structure will already be in place. + +The entirety of a car port lives in `opendbc/car//`: +* `carstate.py`: parses out the relevant information from the CAN stream using the car's DBC file +* `carcontroller.py`: outputs CAN messages to control the car +* `can.py`: thin Python helpers around the DBC file to build CAN messages +* `fingerprints.py`: database of ECU firmware versions for identifying car models +* `interface.py`: high level class for interfacing with the car +* `radar_interface.py`: parses out the radar +* `values.py`: enumerates the brand's supported cars + +### Reverse Engineer CAN messages + +Start off by recording a route with lots of interesting events: enable LKAS and ACC, turn the steering wheel both extremes, etc. Then, load up that route in [cabana](https://github.com/commaai/openpilot/tree/master/tools/cabana). + +### Tuning + +#### Longitudinal + +Use the [longitudinal maneuvers](https://github.com/commaai/openpilot/tree/master/tools/longitudinal_maneuvers) report to evaluate your car's longitudinal control and tune it. + +## Contributing + +All opendbc development is coordinated on GitHub and [Discord](https://discord.comma.ai). Check out the `#dev-opendbc-cars` channel and `Vehicle Specific` section. + +### Roadmap + +Short term +- [ ] `pip install opendbc` +- [ ] 100% type coverage +- [ ] 100% line coverage +- [ ] Make car ports easier: refactors, tools, tests, and docs +- [ ] Expose the state of all supported cars better: https://github.com/commaai/opendbc/issues/1144 + +Longer term +- [ ] Extend support to every car with LKAS + ACC interfaces +- [ ] Automatic lateral and longitudinal control/tuning evaluation +- [ ] Auto-tuning for [lateral](https://blog.comma.ai/090release/#torqued-an-auto-tuner-for-lateral-control) and longitudinal control +- [ ] [Automatic Emergency Braking](https://en.wikipedia.org/wiki/Automated_emergency_braking_system) + +Contributions towards anything here are welcome. + +## Safety Model + +When a [panda](https://comma.ai/shop/panda) powers up with [opendbc safety firmware](opendbc/safety), by default it's in `SAFETY_SILENT` mode. While in `SAFETY_SILENT` mode, the CAN buses are forced to be silent. In order to send messages, you have to select a safety mode. Some of safety modes (for example `SAFETY_ALLOUTPUT`) are disabled in release firmwares. In order to use them, compile and flash your own build. + +Safety modes optionally support `controls_allowed`, which allows or blocks a subset of messages based on a customizable state in the board. + +## Code Rigor + +The opendbc safety firmware is written for its use in conjunction with [openpilot](https://github.com/commaai/openpilot) and [panda](https://github.com/commaai/panda). The safety firmware, through its safety model, provides and enforces the +[openpilot safety](https://github.com/commaai/openpilot/blob/master/docs/SAFETY.md). Due to its critical function, it's important that the application code rigor within the `safety` folder is held to high standards. + +These are the [CI regression tests](https://github.com/commaai/opendbc/actions) we have in place: +* A generic static code analysis is performed by [cppcheck](https://github.com/danmar/cppcheck/). +* In addition, [cppcheck](https://github.com/danmar/cppcheck/) has a specific addon to check for [MISRA C:2012](https://misra.org.uk/) violations. See [current coverage](opendbc/safety/tests/misra/coverage_table). +* Compiler options are relatively strict: the flags `-Wall -Wextra -Wstrict-prototypes -Werror` are enforced. +* The [safety logic](opendbc/safety) is tested and verified by [unit tests](opendbc/safety/tests) for each supported car variant. + +The above tests are themselves tested by: +* a [mutation test](opendbc/safety/tests/misra/test_mutation.py) on the MISRA coverage +* 100% line coverage enforced on the safety unit tests + +In addition, we run the [ruff linter](https://github.com/astral-sh/ruff) and [mypy](https://mypy-lang.org/) on the car interface library. + +### Bounties + +Every car port is eligible for a bounty: +* $2000 - [Any car brand / platform port](https://github.com/orgs/commaai/projects/26/views/1?pane=issue&itemId=47913774) +* $250 - [Any car model port](https://github.com/orgs/commaai/projects/26/views/1?pane=issue&itemId=47913790) +* $300 - [Reverse Engineering a new Actuation Message](https://github.com/orgs/commaai/projects/26/views/1?pane=issue&itemId=73445563) + +In addition to the standard bounties, we also offer higher value bounties for more popular cars. See those at [comma.ai/bounties](comma.ai/bounties). + +## FAQ + +***How do I use this?*** A [comma 3X](https://comma.ai/shop/comma-3x) is custom-designed to be the best way to run and develop opendbc and openpilot. + +***Which cars are supported?*** See the [supported cars list](docs/CARS.md). + +***Can I add support for my car?*** Yes, most car support comes from the community. Read the guide [here](https://github.com/commaai/opendbc/blob/docs/README.md#how-to-port-a-car). + +***Which cars can be supported?*** Any car with LKAS and ACC. More info [here](https://github.com/commaai/openpilot/blob/master/docs/CARS.md#dont-see-your-car-here). + +***How does this work?*** In short, we designed hardware to replace your car's built-in lane keep and adaptive cruise features. See [this talk](https://www.youtube.com/watch?v=FL8CxUSfipM) for an in-depth explanation. + +***Is there a timeline or roadmap for adding car support?*** No, most car support comes from the community, with comma doing final safety and quality validation. The more complete the community car port is and the more popular the car is, the more likely we are to pick it up as the next one to validate. + +### Terms + +* **port**: refers to the integration and support of a specific car +* **lateral control**: aka steering control +* **longitudinal control**: aka gas/brakes control +* **fingerprinting**: automatic process for identifying the car +* **[LKAS](https://en.wikipedia.org/wiki/Lane_departure_warning_system)**: lane keeping assist +* **[ACC](https://en.wikipedia.org/wiki/Adaptive_cruise_control)**: adaptive cruise control +* **[harness](https://comma.ai/shop/car-harness)**: car-specific hardware to attach to the car and intercept the ADAS messages +* **[panda](https://github.com/commaai/panda)**: hardware used to get on a car's CAN bus +* **[ECU](https://en.wikipedia.org/wiki/Electronic_control_unit)**: computers or control modules inside the car +* **[CAN bus](https://en.wikipedia.org/wiki/CAN_bus)**: a bus that connects the ECUs in a car +* **[cabana](https://github.com/commaai/openpilot/tree/master/tools/cabana#readme)**: our tool for reverse engineering CAN messages +* **[DBC file](https://en.wikipedia.org/wiki/CAN_bus#DBC)**: contains definitions for messages on a CAN bus +* **[openpilot](https://github.com/commaai/openpilot)**: an ADAS system for cars supported by opendbc +* **[comma](https://github.com/commaai)**: the company behind opendbc +* **[comma 3X](https://comma.ai/shop/comma-3x)**: the hardware used to run openpilot + +### More resources + +* [*How Do We Control The Car?*](https://www.youtube.com/watch?v=nNU6ipme878&pp=ygUoY29tbWEgY29uIDIwMjEgaG93IGRvIHdlIGNvbnRyb2wgdGhlIGNhcg%3D%3D) by [@robbederks](https://github.com/robbederks) from COMMA_CON 2021 +* [*How to Port a Car*](https://www.youtube.com/watch?v=XxPS5TpTUnI&t=142s&pp=ygUPamFzb24gY29tbWEgY29u) by [@jyoung8607](https://github.com/jyoung8607) from COMMA_CON 2023 +* [commaCarSegments](https://huggingface.co/datasets/commaai/commaCarSegments): a massive dataset of CAN data from 300 different car models +* [cabana](https://github.com/commaai/openpilot/tree/master/tools/cabana#readme): our tool for reverse engineering CAN messages +* [can_print_changes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/debug/can_print_changes.py): diff the whole CAN bus across two drives, such as one without any LKAS and one with LKAS +* [longitudinal maneuvers](https://github.com/commaai/openpilot/tree/master/tools/longitudinal_maneuvers): a tool for evaluating and tuning longitudinal control +* [opendbc data](https://commaai.github.io/opendbc-data/): a repository of longitudinal maneuver evaluations + +## Come work with us -- [comma.ai/jobs](https://comma.ai/jobs) + +comma is hiring engineers to work on opendbc and [openpilot](https://github.com/commaai/openpilot). We love hiring contributors. diff --git a/opendbc_repo/RELEASES.md b/opendbc_repo/RELEASES.md new file mode 100644 index 0000000000..2eab19fe84 --- /dev/null +++ b/opendbc_repo/RELEASES.md @@ -0,0 +1,13 @@ +Version 0.2.1 (2025-02-10) +======================== +* Fix missing files making car/ package not importable + +Version 0.2.0 (2025-02-10) +======================== +* Moved car/ directory from openpilot to opendbc. It comprises the APIs necessary to communicate with 275+ car models + * opendbc is moving towards being a complete self-contained car API package + * Soon all opendbc-related tests from openpilot will be migrated as well + +Version 0.1.0 (2024-08-01) +======================== +* Initial pre-release package with can/ and dbc/ directories diff --git a/opendbc_repo/SConscript b/opendbc_repo/SConscript new file mode 100644 index 0000000000..6e191d710c --- /dev/null +++ b/opendbc_repo/SConscript @@ -0,0 +1,5 @@ +SConscript(['opendbc/dbc/SConscript']) + +# test files +if GetOption('extras'): + SConscript('opendbc/safety/tests/libsafety/SConscript') diff --git a/opendbc_repo/SConstruct b/opendbc_repo/SConstruct new file mode 100644 index 0000000000..897ae18e1d --- /dev/null +++ b/opendbc_repo/SConstruct @@ -0,0 +1,11 @@ +AddOption('--minimal', + action='store_false', + dest='extras', + default=True, + help='the minimum build. no tests, tools, etc.') + +AddOption('--ubsan', + action='store_true', + help='turn on UBSan') + +SConscript(['SConscript']) diff --git a/opendbc_repo/conftest.py b/opendbc_repo/conftest.py new file mode 100644 index 0000000000..952972531b --- /dev/null +++ b/opendbc_repo/conftest.py @@ -0,0 +1,5 @@ +# pytest attempts to execute shell scripts while collecting +collect_ignore_glob = [ + "opendbc/safety/tests/misra/*.sh", + "opendbc/safety/tests/misra/cppcheck/", +] diff --git a/opendbc_repo/docs/CARS.md b/opendbc_repo/docs/CARS.md new file mode 100644 index 0000000000..4a159ddff1 --- /dev/null +++ b/opendbc_repo/docs/CARS.md @@ -0,0 +1,446 @@ + + +# Support Information for 383 Known Cars + +|Make|Model|Package|Support Level| +|---|---|---|:---:| +|Acura|ILX 2016-18|Technology Plus Package or AcuraWatch Plus|[Upstream](#upstream)| +|Acura|ILX 2019|All|[Upstream](#upstream)| +|Acura|Integra 2023-25|All|[Community](#community)| +|Acura|MDX 2015-16|Advance Package|[Community](#community)| +|Acura|MDX 2017-20|All|[Community](#community)| +|Acura|MDX 2022-24|All|[Community](#community)| +|Acura|MDX 2025|All except Type S|[Upstream](#upstream)| +|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|[Upstream](#upstream)| +|Acura|RDX 2019-21|All|[Upstream](#upstream)| +|Acura|RDX 2022-25|All|[Community](#community)| +|Acura|RLX 2017|Advance Package or Technology Package|[Community](#community)| +|Acura|TLX 2015-17|Advance Package|[Community](#community)| +|Acura|TLX 2018-20|All|[Community](#community)| +|Acura|TLX 2021|All|[Upstream](#upstream)| +|Acura|TLX 2022-23|All|[Community](#community)| +|Acura|ZDX 2024|All|[Not compatible](#can-bus-security)| +|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Audi|A4 2016-24|All|[Not compatible](#flexray)| +|Audi|A5 2016-24|All|[Not compatible](#flexray)| +|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Audi|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Audi|Q5 2017-24|All|[Not compatible](#flexray)| +|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|[Upstream](#upstream)| +|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|[Upstream](#upstream)| +|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Chevrolet|Silverado 1500 2020-21|Safety Package II|[Upstream](#upstream)| +|Chevrolet|Trailblazer 2021-22|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Chrysler|Pacifica 2021-23|All|[Upstream](#upstream)| +|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Chrysler|Pacifica Hybrid 2019-25|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|comma|body|All|[Upstream](#upstream)| +|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Escape 2020-22|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Escape 2023-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Escape Hybrid 2023-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Escape Plug-in Hybrid 2023-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Expedition 2022-24|Co-Pilot360 Assist 2.0|[Upstream](#upstream)| +|Ford|Explorer 2020-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|F-150 2021-23|Co-Pilot360 Assist 2.0|[Upstream](#upstream)| +|Ford|F-150 Hybrid 2021-23|Co-Pilot360 Assist 2.0|[Upstream](#upstream)| +|Ford|Focus 2018|Adaptive Cruise Control with Lane Centering|[Upstream](#upstream)| +|Ford|Focus Hybrid 2018|Adaptive Cruise Control with Lane Centering|[Upstream](#upstream)| +|Ford|Kuga 2020-23|Adaptive Cruise Control with Lane Centering|[Upstream](#upstream)| +|Ford|Kuga Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|[Upstream](#upstream)| +|Ford|Kuga Hybrid 2024|All|[Upstream](#upstream)| +|Ford|Kuga Plug-in Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|[Upstream](#upstream)| +|Ford|Kuga Plug-in Hybrid 2024|All|[Upstream](#upstream)| +|Ford|Maverick 2022|LARIAT Luxury|[Upstream](#upstream)| +|Ford|Maverick 2023-24|Co-Pilot360 Assist|[Upstream](#upstream)| +|Ford|Maverick Hybrid 2022|LARIAT Luxury|[Upstream](#upstream)| +|Ford|Maverick Hybrid 2023-24|Co-Pilot360 Assist|[Upstream](#upstream)| +|Ford|Mustang Mach-E 2021-24|All|[Upstream](#upstream)| +|Ford|Ranger 2024|Adaptive Cruise Control with Lane Centering|[Upstream](#upstream)| +|Genesis|G70 2018|All|[Upstream](#upstream)| +|Genesis|G70 2019-21|All|[Upstream](#upstream)| +|Genesis|G70 2022-23|All|[Upstream](#upstream)| +|Genesis|G80 2017|All|[Upstream](#upstream)| +|Genesis|G80 2018-19|All|[Upstream](#upstream)| +|Genesis|G80 (2.5T Advanced Trim, with HDA II) 2024|Highway Driving Assist II|[Upstream](#upstream)| +|Genesis|G90 2017-20|All|[Upstream](#upstream)| +|Genesis|GV60 (Advanced Trim) 2023|All|[Upstream](#upstream)| +|Genesis|GV60 (Performance Trim) 2022-23|All|[Upstream](#upstream)| +|Genesis|GV70 (2.5T Trim, without HDA II) 2022-24|All|[Upstream](#upstream)| +|Genesis|GV70 (3.5T Trim, without HDA II) 2022-23|All|[Upstream](#upstream)| +|Genesis|GV70 Electrified (Australia Only) 2022|All|[Upstream](#upstream)| +|Genesis|GV70 Electrified (with HDA II) 2023-24|Highway Driving Assist II|[Upstream](#upstream)| +|Genesis|GV80 2023|All|[Upstream](#upstream)| +|GMC|Sierra 1500 2020-21|Driver Alert Package II|[Upstream](#upstream)| +|GMC|Yukon 2019-20|Adaptive Cruise Control (ACC) & LKAS|[Dashcam mode](#dashcam)| +|Honda|Accord 2016-17|Honda Sensing|[Community](#community)| +|Honda|Accord 2018-22|All|[Upstream](#upstream)| +|Honda|Accord 2023-25|All|[Upstream](#upstream)| +|Honda|Accord Hybrid 2018-22|All|[Upstream](#upstream)| +|Honda|Accord Hybrid 2023-25|All|[Upstream](#upstream)| +|Honda|City (Brazil only) 2023|All|[Upstream](#upstream)| +|Honda|Civic 2016-18|Honda Sensing|[Upstream](#upstream)| +|Honda|Civic 2019-21|All|[Upstream](#upstream)| +|Honda|Civic 2022-24|All|[Upstream](#upstream)| +|Honda|Civic Hatchback 2017-18|Honda Sensing|[Upstream](#upstream)| +|Honda|Civic Hatchback 2019-21|All|[Upstream](#upstream)| +|Honda|Civic Hatchback 2022-24|All|[Upstream](#upstream)| +|Honda|Civic Hatchback Hybrid 2025-26|All|[Upstream](#upstream)| +|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|[Upstream](#upstream)| +|Honda|Civic Hybrid 2025|All|[Upstream](#upstream)| +|Honda|Clarity 2018-21|All|[Community](#community)| +|Honda|CR-V 2015-16|Touring Trim|[Upstream](#upstream)| +|Honda|CR-V 2017-22|Honda Sensing|[Upstream](#upstream)| +|Honda|CR-V 2023-25|All|[Upstream](#upstream)| +|Honda|CR-V Hybrid 2017-22|Honda Sensing|[Upstream](#upstream)| +|Honda|CR-V Hybrid 2023-25|All|[Upstream](#upstream)| +|Honda|e 2020|All|[Upstream](#upstream)| +|Honda|Fit 2018-20|Honda Sensing|[Upstream](#upstream)| +|Honda|Freed 2020|Honda Sensing|[Upstream](#upstream)| +|Honda|HR-V 2019-22|Honda Sensing|[Upstream](#upstream)| +|Honda|HR-V 2023-25|All|[Upstream](#upstream)| +|Honda|Insight 2019-22|All|[Upstream](#upstream)| +|Honda|Inspire 2018|All|[Upstream](#upstream)| +|Honda|N-Box 2018|All|[Upstream](#upstream)| +|Honda|Odyssey 2018-20|Honda Sensing|[Upstream](#upstream)| +|Honda|Odyssey 2021-25|All|[Upstream](#upstream)| +|Honda|Passport 2019-25|All|[Upstream](#upstream)| +|Honda|Passport 2026|All|[Upstream](#upstream)| +|Honda|Pilot 2016-22|Honda Sensing|[Upstream](#upstream)| +|Honda|Pilot 2023-25|All|[Upstream](#upstream)| +|Honda|Prologue 2024-25|All|[Not compatible](#can-bus-security)| +|Honda|Ridgeline 2017-25|Honda Sensing|[Upstream](#upstream)| +|Hyundai|Azera 2022|All|[Upstream](#upstream)| +|Hyundai|Azera Hybrid 2019|All|[Upstream](#upstream)| +|Hyundai|Azera Hybrid 2020|All|[Upstream](#upstream)| +|Hyundai|Custin 2023|All|[Upstream](#upstream)| +|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24|All|[Upstream](#upstream)| +|Hyundai|Ioniq 5 (with HDA II) 2022-24|Highway Driving Assist II|[Upstream](#upstream)| +|Hyundai|Ioniq 5 (without HDA II) 2022-24|Highway Driving Assist|[Upstream](#upstream)| +|Hyundai|Ioniq 6 (with HDA II) 2023-24|Highway Driving Assist II|[Upstream](#upstream)| +|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Ioniq Electric 2020|All|[Upstream](#upstream)| +|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Ioniq Hybrid 2020-22|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Ioniq Plug-in Hybrid 2020-22|All|[Upstream](#upstream)| +|Hyundai|Kona 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|[Dashcam mode](#dashcam)| +|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Kona Electric (with HDA II, Korea only) 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Nexo 2021|All|[Upstream](#upstream)| +|Hyundai|Palisade 2020-22|All|[Upstream](#upstream)| +|Hyundai|Palisade 2023-24|HDA2|[Community](#community)| +|Hyundai|Santa Cruz 2022-24|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Santa Fe 2019-20|All|[Upstream](#upstream)| +|Hyundai|Santa Fe 2021-23|All|[Upstream](#upstream)| +|Hyundai|Santa Fe Hybrid 2022-23|All|[Upstream](#upstream)| +|Hyundai|Santa Fe Plug-in Hybrid 2022-23|All|[Upstream](#upstream)| +|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Sonata 2020-23|All|[Upstream](#upstream)| +|Hyundai|Sonata Hybrid 2020-23|All|[Upstream](#upstream)| +|Hyundai|Staria 2023|All|[Upstream](#upstream)| +|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Tucson 2022|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Tucson 2023-24|All|[Upstream](#upstream)| +|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Hyundai|Tucson Hybrid 2022-24|All|[Upstream](#upstream)| +|Hyundai|Tucson Plug-in Hybrid 2024|All|[Upstream](#upstream)| +|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Kia|Carnival 2022-24|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Carnival (China only) 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|EV6 (Southeast Asia only) 2022-24|All|[Upstream](#upstream)| +|Kia|EV6 (with HDA II) 2022-24|Highway Driving Assist II|[Upstream](#upstream)| +|Kia|EV6 (without HDA II) 2022-24|Highway Driving Assist|[Upstream](#upstream)| +|Kia|Forte 2019-21|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Forte 2022-23|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|K5 2021-24|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|K8 Hybrid (with HDA II) 2023|Highway Driving Assist II|[Upstream](#upstream)| +|Kia|Niro EV 2019|All|[Upstream](#upstream)| +|Kia|Niro EV 2020|All|[Upstream](#upstream)| +|Kia|Niro EV 2021|All|[Upstream](#upstream)| +|Kia|Niro EV 2022|All|[Upstream](#upstream)| +|Kia|Niro EV (with HDA II) 2025|Highway Driving Assist II|[Upstream](#upstream)| +|Kia|Niro EV (without HDA II) 2023-25|All|[Upstream](#upstream)| +|Kia|Niro Hybrid 2018|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Niro Hybrid 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Niro Plug-in Hybrid 2018-19|All|[Upstream](#upstream)| +|Kia|Niro Plug-in Hybrid 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Niro Plug-in Hybrid 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Niro Plug-in Hybrid 2022|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Optima 2017|Advanced Smart Cruise Control|[Upstream](#upstream)| +|Kia|Optima 2019-20|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Optima Hybrid 2017|Advanced Smart Cruise Control|[Dashcam mode](#dashcam)| +|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Seltos 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Sorento 2018|Advanced Smart Cruise Control & LKAS|[Upstream](#upstream)| +|Kia|Sorento 2019|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Sorento 2021-23|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Sorento Hybrid 2021-23|All|[Upstream](#upstream)| +|Kia|Sorento Plug-in Hybrid 2022-23|All|[Upstream](#upstream)| +|Kia|Sportage 2023-24|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Sportage Hybrid 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|[Upstream](#upstream)| +|Kia|Stinger 2022-23|All|[Upstream](#upstream)| +|Kia|Telluride 2020-22|All|[Upstream](#upstream)| +|Kia|Telluride 2023-24|HDA2|[Community](#community)| +|Lexus|CT Hybrid 2017-18|Lexus Safety System+|[Upstream](#upstream)| +|Lexus|ES 2017-18|All|[Upstream](#upstream)| +|Lexus|ES 2019-25|All|[Upstream](#upstream)| +|Lexus|ES Hybrid 2017-18|All|[Upstream](#upstream)| +|Lexus|ES Hybrid 2019-25|All|[Upstream](#upstream)| +|Lexus|GS F 2016|All|[Upstream](#upstream)| +|Lexus|IS 2017-19|All|[Upstream](#upstream)| +|Lexus|IS 2022-24|All|[Upstream](#upstream)| +|Lexus|LC 2024-25|All|[Upstream](#upstream)| +|Lexus|NS 2022-25|Any|[Not compatible](#can-bus-security)| +|Lexus|NX 2018-19|All|[Upstream](#upstream)| +|Lexus|NX 2020-21|All|[Upstream](#upstream)| +|Lexus|NX Hybrid 2018-19|All|[Upstream](#upstream)| +|Lexus|NX Hybrid 2020-21|All|[Upstream](#upstream)| +|Lexus|RC 2018-20|All|[Upstream](#upstream)| +|Lexus|RC 2023|All|[Upstream](#upstream)| +|Lexus|RX 2016|Lexus Safety System+|[Upstream](#upstream)| +|Lexus|RX 2017-19|All|[Upstream](#upstream)| +|Lexus|RX 2020-22|All|[Upstream](#upstream)| +|Lexus|RX Hybrid 2016|Lexus Safety System+|[Upstream](#upstream)| +|Lexus|RX Hybrid 2017-19|All|[Upstream](#upstream)| +|Lexus|RX Hybrid 2020-22|All|[Upstream](#upstream)| +|Lexus|UX Hybrid 2019-24|All|[Upstream](#upstream)| +|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|[Upstream](#upstream)| +|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|[Upstream](#upstream)| +|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Mazda|3 2017-18|All|[Dashcam mode](#dashcam)| +|Mazda|6 2017-20|All|[Dashcam mode](#dashcam)| +|Mazda|CX-5 2017-21|All|[Dashcam mode](#dashcam)| +|Mazda|CX-5 2022-25|All|[Upstream](#upstream)| +|Mazda|CX-9 2016-20|All|[Dashcam mode](#dashcam)| +|Mazda|CX-9 2021-23|All|[Upstream](#upstream)| +|Nissan|Altima 2019-20|ProPILOT Assist|[Upstream](#upstream)| +|Nissan|Leaf 2018-23|ProPILOT Assist|[Upstream](#upstream)| +|Nissan|Rogue 2018-20|ProPILOT Assist|[Upstream](#upstream)| +|Nissan|X-Trail 2017|ProPILOT Assist|[Upstream](#upstream)| +|Peugeot|208 2019-25|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| +|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)| +|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)| +|Rivian|R1S 2022-24|All|[Upstream](#upstream)| +|Rivian|R1T 2022-24|All|[Upstream](#upstream)| +|SEAT|Alhambra 2018-20|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Subaru|Ascent 2019-21|All|[Upstream](#upstream)| +|Subaru|Ascent 2023|All|[Dashcam mode](#dashcam)| +|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance|[Upstream](#upstream)| +|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance|[Upstream](#upstream)| +|Subaru|Crosstrek Hybrid 2020|EyeSight Driver Assistance|[Dashcam mode](#dashcam)| +|Subaru|Forester 2017-18|EyeSight Driver Assistance|[Dashcam mode](#dashcam)| +|Subaru|Forester 2019-21|All|[Upstream](#upstream)| +|Subaru|Forester 2022-24|All|[Dashcam mode](#dashcam)| +|Subaru|Forester Hybrid 2020|EyeSight Driver Assistance|[Dashcam mode](#dashcam)| +|Subaru|Impreza 2017-19|EyeSight Driver Assistance|[Upstream](#upstream)| +|Subaru|Impreza 2020-22|EyeSight Driver Assistance|[Upstream](#upstream)| +|Subaru|Legacy 2015-18|EyeSight Driver Assistance|[Dashcam mode](#dashcam)| +|Subaru|Legacy 2020-22|All|[Upstream](#upstream)| +|Subaru|Outback 2015-17|EyeSight Driver Assistance|[Dashcam mode](#dashcam)| +|Subaru|Outback 2018-19|EyeSight Driver Assistance|[Dashcam mode](#dashcam)| +|Subaru|Outback 2020-22|All|[Upstream](#upstream)| +|Subaru|Outback 2023|All|[Dashcam mode](#dashcam)| +|Subaru|Solterra 2023-25|Any|[Not compatible](#can-bus-security)| +|Subaru|XV 2018-19|EyeSight Driver Assistance|[Upstream](#upstream)| +|Subaru|XV 2020-21|EyeSight Driver Assistance|[Upstream](#upstream)| +|Škoda|Fabia 2022-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Kamiq 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Karoq 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Kodiaq 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Octavia 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Octavia RS 2016|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Octavia Scout 2017-19|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Scala 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Škoda|Superb 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Tesla|Model 3 (with HW3) 2019-23|All|[Upstream](#upstream)| +|Tesla|Model 3 (with HW4) 2024-25|All|[Upstream](#upstream)| +|Tesla|Model X (with HW4) 2024|All|[Dashcam mode](#dashcam)| +|Tesla|Model Y (with HW3) 2020-23|All|[Upstream](#upstream)| +|Tesla|Model Y (with HW4) 2024-25|All|[Upstream](#upstream)| +|Toyota|Alphard 2019-20|All|[Upstream](#upstream)| +|Toyota|Alphard Hybrid 2021|All|[Upstream](#upstream)| +|Toyota|Avalon 2016|Toyota Safety Sense P|[Upstream](#upstream)| +|Toyota|Avalon 2017-18|All|[Upstream](#upstream)| +|Toyota|Avalon 2019-21|All|[Upstream](#upstream)| +|Toyota|Avalon 2022|All|[Upstream](#upstream)| +|Toyota|Avalon Hybrid 2019-21|All|[Upstream](#upstream)| +|Toyota|Avalon Hybrid 2022|All|[Upstream](#upstream)| +|Toyota|bZ4x 2023-25|Any|[Not compatible](#can-bus-security)| +|Toyota|C-HR 2017-20|All|[Upstream](#upstream)| +|Toyota|C-HR 2021|All|[Upstream](#upstream)| +|Toyota|C-HR Hybrid 2017-20|All|[Upstream](#upstream)| +|Toyota|C-HR Hybrid 2021-22|All|[Upstream](#upstream)| +|Toyota|Camry 2018-20|All|[Upstream](#upstream)| +|Toyota|Camry 2021-24|All|[Upstream](#upstream)| +|Toyota|Camry 2025|Any|[Not compatible](#can-bus-security)| +|Toyota|Camry Hybrid 2018-20|All|[Upstream](#upstream)| +|Toyota|Camry Hybrid 2021-24|All|[Upstream](#upstream)| +|Toyota|Corolla 2017-19|All|[Upstream](#upstream)| +|Toyota|Corolla 2020-22|All|[Upstream](#upstream)| +|Toyota|Corolla Cross 2022-25|Any|[Not compatible](#can-bus-security)| +|Toyota|Corolla Cross (Non-US only) 2020-23|All|[Upstream](#upstream)| +|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|[Upstream](#upstream)| +|Toyota|Corolla Hatchback 2019-22|All|[Upstream](#upstream)| +|Toyota|Corolla Hybrid 2020-22|All|[Upstream](#upstream)| +|Toyota|Corolla Hybrid (South America only) 2020-23|All|[Upstream](#upstream)| +|Toyota|Highlander 2017-19|All|[Upstream](#upstream)| +|Toyota|Highlander 2020-23|All|[Upstream](#upstream)| +|Toyota|Highlander 2025|Any|[Not compatible](#can-bus-security)| +|Toyota|Highlander Hybrid 2017-19|All|[Upstream](#upstream)| +|Toyota|Highlander Hybrid 2020-23|All|[Upstream](#upstream)| +|Toyota|Mirai 2021|All|[Upstream](#upstream)| +|Toyota|Prius 2016|Toyota Safety Sense P|[Upstream](#upstream)| +|Toyota|Prius 2017-20|All|[Upstream](#upstream)| +|Toyota|Prius 2021-22|All|[Upstream](#upstream)| +|Toyota|Prius Prime 2017-20|All|[Upstream](#upstream)| +|Toyota|Prius Prime 2021-22|All|[Upstream](#upstream)| +|Toyota|Prius v 2017|Toyota Safety Sense P|[Upstream](#upstream)| +|Toyota|RAV4 2016|Toyota Safety Sense P|[Upstream](#upstream)| +|Toyota|RAV4 2017-18|All|[Upstream](#upstream)| +|Toyota|RAV4 2019-21|All|[Upstream](#upstream)| +|Toyota|RAV4 2022|All|[Upstream](#upstream)| +|Toyota|RAV4 2023-25|All|[Upstream](#upstream)| +|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|[Upstream](#upstream)| +|Toyota|RAV4 Hybrid 2017-18|All|[Upstream](#upstream)| +|Toyota|RAV4 Hybrid 2019-21|All|[Upstream](#upstream)| +|Toyota|RAV4 Hybrid 2022|All|[Upstream](#upstream)| +|Toyota|RAV4 Hybrid 2023-25|All|[Upstream](#upstream)| +|Toyota|RAV4 Prime 2021-23|All|[Community](#community)| +|Toyota|RAV4 Prime 2024-25|Any|[Not compatible](#can-bus-security)| +|Toyota|Sequoia 2023-25|Any|[Not compatible](#can-bus-security)| +|Toyota|Sienna 2018-20|All|[Upstream](#upstream)| +|Toyota|Sienna 2021-23|All|[Community](#community)| +|Toyota|Sienna 2024-25|Any|[Not compatible](#can-bus-security)| +|Toyota|Tundra 2022-25|Any|[Not compatible](#can-bus-security)| +|Toyota|Venza 2021-25|Any|[Not compatible](#can-bus-security)| +|Toyota|Yaris (Non-US only) 2020, 2023|All|[Community](#community)| +|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Caddy 2019|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|Volkswagen|Caddy Maxi 2019|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Jetta 2015-18|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|Volkswagen|Jetta 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Passat 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Passat NMS 2017-22|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Sharan 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)| +|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| +|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| + +# Types of Support + +**opendbc can support many more cars than it currently does.** There are a few reasons your car may not be supported. +If your car doesn't fit into any of the incompatibility criteria here, then there's a good chance it can be supported! +We're adding support for new cars all the time. **We don't have a roadmap for car support**, and in fact, most car +support comes from users like you! + +## Upstream + +A supported vehicle is one that just works when you install a comma device. All supported cars provide a better +experience than any stock system. Supported vehicles reference the US market unless otherwise specified. + +## Under Review + +A vehicle under review is one for which software support has been merged into upstream openpilot, but hasn't yet been +tested for drive quality and conformance with [comma safety guidelines](https://github.com/commaai/openpilot/blob/master/docs/SAFETY.md). +This is a normal part of the development and quality assurance process. This vehicle will not work when upstream +openpilot is installed, but custom forks may allow their use. + +## Custom + +Vehicles in this category are not considered plug-and-play. Software support is included in upstream openpilot, but +these vehicles might not have a harness in the comma store, or the physical install might be at an unusual or cumbersome +location, or they might need unusual configuration after install. + +## Dashcam + +Dashcam vehicles have software support in upstream openpilot, but will go into "dashcam mode" at startup and will not +engage. This may be due to known issues with driving safety or quality, or it may be a work in progress that isn't yet +ready for safety and quality review. + +## Community + +Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community +Supported Models' section of each make [on our wiki](https://wiki.comma.ai/). + +Some notable works-in-progress: +* Honda + * 2022-24 Acura RDX, commaai/opendbc#1967 + * Camera ACC stability improvements, commaai/opendbc#2192 + * Alpha longitudinal stability improvements, commaai/opendbc#2347 and commaai/opendbc#2165 + +## Incompatible + +### CAN Bus Security + +Vehicles with CAN security measures, such as AUTOSAR Secure Onboard Communication (SecOC) are not usable with openpilot +unless the owner can recover the message signing key and implement CAN message signing. Examples include certain newer +Toyota, and the GM Global B platform. + +### FlexRay + +All the cars that openpilot supports use a [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) for communication between all the car's computers, however a +CAN bus isn't the only way that the computers in your car can communicate. Most, if not all, vehicles from the following +manufacturers use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) instead of a CAN bus: **BMW, Mercedes, Audi, Land Rover, and some Volvo**. These cars +may one day be supported, but we have no immediate plans to support FlexRay. \ No newline at end of file diff --git a/opendbc_repo/examples/joystick.py b/opendbc_repo/examples/joystick.py new file mode 100755 index 0000000000..2b80b342bb --- /dev/null +++ b/opendbc_repo/examples/joystick.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +import time +import threading +import argparse +import numpy as np +from pprint import pprint +from inputs import get_gamepad + +from kbhit import KBHit + +from opendbc.car.structs import CarControl +from opendbc.car.panda_runner import PandaRunner + + +class Keyboard: + def __init__(self): + self.kb = KBHit() + self.axis_increment = 0.05 # 5% of full actuation each key press + self.axes_map = {'w': 'gb', 's': 'gb', + 'a': 'steer', 'd': 'steer'} + self.axes_values = {'gb': 0., 'steer': 0.} + self.axes_order = ['gb', 'steer'] + self.cancel = False + + def update(self): + key = self.kb.getch().lower() + print(key) + self.cancel = False + if key == 'r': + self.axes_values = {ax: 0. for ax in self.axes_values} + elif key == 'c': + self.cancel = True + elif key in self.axes_map: + axis = self.axes_map[key] + incr = self.axis_increment if key in ['w', 'a'] else -self.axis_increment + self.axes_values[axis] = float(np.clip(self.axes_values[axis] + incr, -1, 1)) + else: + return False + return True + + +class Joystick: + def __init__(self, gamepad=False): + # TODO: find a way to get this from API, perhaps "inputs" doesn't support it + if gamepad: + self.cancel_button = 'BTN_NORTH' # (BTN_NORTH=X, ABS_RZ=Right Trigger) + accel_axis = 'ABS_Y' + steer_axis = 'ABS_RX' + else: + self.cancel_button = 'BTN_TRIGGER' + accel_axis = 'ABS_Y' + steer_axis = 'ABS_RX' + self.min_axis_value = {accel_axis: 0., steer_axis: 0.} + self.max_axis_value = {accel_axis: 255., steer_axis: 255.} + self.axes_values = {accel_axis: 0., steer_axis: 0.} + self.axes_order = [accel_axis, steer_axis] + self.cancel = False + + def update(self): + joystick_event = get_gamepad()[0] + event = (joystick_event.code, joystick_event.state) + if event[0] == self.cancel_button: + if event[1] == 1: + self.cancel = True + elif event[1] == 0: # state 0 is falling edge + self.cancel = False + elif event[0] in self.axes_values: + self.max_axis_value[event[0]] = max(event[1], self.max_axis_value[event[0]]) + self.min_axis_value[event[0]] = min(event[1], self.min_axis_value[event[0]]) + + norm = -float(np.interp(event[1], [self.min_axis_value[event[0]], self.max_axis_value[event[0]]], [-1., 1.])) + self.axes_values[event[0]] = norm if abs(norm) > 0.05 else 0. # center can be noisy, deadzone of 5% + else: + return False + return True + + +def joystick_thread(joystick): + while True: + joystick.update() + + +def main(joystick): + threading.Thread(target=joystick_thread, args=(joystick,), daemon=True).start() + with PandaRunner() as p: + CC = CarControl(enabled=False) + while True: + CC.actuators.accel = float(4.0*np.clip(joystick.axes_values['gb'], -1, 1)) + CC.actuators.torque = float(np.clip(joystick.axes_values['steer'], -1, 1)) + pprint(CC) + + p.read() + p.write(CC) + + # 100Hz + time.sleep(0.01) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Test the car interface with a joystick. Uses keyboard by default.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument('--mode', choices=['keyboard', 'gamepad', 'joystick'], default='keyboard') + args = parser.parse_args() + + print() + joystick: Keyboard | Joystick + if args.mode == 'keyboard': + print('Gas/brake control: `W` and `S` keys') + print('Steering control: `A` and `D` keys') + print('Buttons') + print('- `R`: Resets axes') + print('- `C`: Cancel cruise control') + joystick = Keyboard() + else: + joystick = Joystick(gamepad=(args.mode == 'gamepad')) + main(joystick) diff --git a/opendbc_repo/examples/kbhit.py b/opendbc_repo/examples/kbhit.py new file mode 100755 index 0000000000..58fde349f4 --- /dev/null +++ b/opendbc_repo/examples/kbhit.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +import sys +import termios +import atexit +from select import select + +STDIN_FD = sys.stdin.fileno() + + +class KBHit: + def __init__(self) -> None: + self.set_kbhit_terminal() + + def set_kbhit_terminal(self) -> None: + # Save the terminal settings + self.old_term = termios.tcgetattr(STDIN_FD) + self.new_term = self.old_term.copy() + + # New terminal setting unbuffered + self.new_term[3] &= ~(termios.ICANON | termios.ECHO) + termios.tcsetattr(STDIN_FD, termios.TCSAFLUSH, self.new_term) + + # Support normal-terminal reset at exit + atexit.register(self.set_normal_term) + + def set_normal_term(self) -> None: + termios.tcsetattr(STDIN_FD, termios.TCSAFLUSH, self.old_term) + + @staticmethod + def getch() -> str: + return sys.stdin.read(1) + + @staticmethod + def getarrow() -> int: + c = sys.stdin.read(3)[2] + vals = [65, 67, 66, 68] + return vals.index(ord(c)) + + @staticmethod + def kbhit(): + ''' Returns True if keyboard character was hit, False otherwise. + ''' + return select([sys.stdin], [], [], 0)[0] != [] + + +if __name__ == "__main__": + + kb = KBHit() + + print('Hit any key, or ESC to exit') + + while True: + + if kb.kbhit(): + c = kb.getch() + if c == '\x1b': # ESC + break + print(c) + + kb.set_normal_term() diff --git a/opendbc_repo/lefthook.yml b/opendbc_repo/lefthook.yml new file mode 100644 index 0000000000..91d1378433 --- /dev/null +++ b/opendbc_repo/lefthook.yml @@ -0,0 +1,28 @@ +output: + - meta # Print lefthook version + - summary # Print summary block (successful and failed steps) + - empty_summary # Print summary heading when there are no steps to run + - success # Print successful steps + - failure # Print failed steps printing + - execution # Print any execution logs + #- execution_out # Print execution output + #- execution_info # Print `EXECUTE > ...` logging + - skips # Print "skip" (i.e. no files matched) + +test: + parallel: true + commands: + # *** static analysis + ruff: + run: ruff check . + codespell: + run: codespell {files} -L tge,stdio -S *.dbc + files: git ls-tree -r HEAD --name-only + cpplint: + run: cpplint --exclude=opendbc/safety/tests/misra/cppcheck/ --exclude=opendbc/can/*_pyx.cpp --recursive --quiet --counting=detailed --linelength=240 --filter=-build,-legal,-readability,-runtime,-whitespace,+build/include_subdir,+build/forward_decl,+build/include_what_you_use,+build/deprecated,+whitespace/comma,+whitespace/line_length,+whitespace/empty_if_body,+whitespace/empty_loop_body,+whitespace/empty_conditional_body,+whitespace/forcolon,+whitespace/parens,+whitespace/semicolon,+whitespace/tab,+readability/braces opendbc/ + misra: + run: opendbc/safety/tests/misra/test_misra.sh + + # *** tests *** + pytest: + run: pytest -n8 diff --git a/opendbc_repo/opendbc/__init__.py b/opendbc_repo/opendbc/__init__.py new file mode 100644 index 0000000000..9f4ee6588b --- /dev/null +++ b/opendbc_repo/opendbc/__init__.py @@ -0,0 +1,6 @@ +import os + +DBC_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'dbc') + +# -I include path for e.g. "#include " +INCLUDE_PATH = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")) diff --git a/opendbc_repo/opendbc/can/__init__.py b/opendbc_repo/opendbc/can/__init__.py new file mode 100644 index 0000000000..d9979457e4 --- /dev/null +++ b/opendbc_repo/opendbc/can/__init__.py @@ -0,0 +1,8 @@ +from opendbc.can.packer import CANPacker +from opendbc.can.parser import CANParser, CANDefine + +__all__ = [ + "CANDefine", + "CANParser", + "CANPacker", +] diff --git a/opendbc_repo/opendbc/can/dbc.py b/opendbc_repo/opendbc/can/dbc.py new file mode 100644 index 0000000000..658bbdab38 --- /dev/null +++ b/opendbc_repo/opendbc/can/dbc.py @@ -0,0 +1,215 @@ +import re +import os +from dataclasses import dataclass +from collections.abc import Callable + +from opendbc import DBC_PATH + +# TODO: these should just be passed in along with the DBC file +from opendbc.car.honda.hondacan import honda_checksum +from opendbc.car.toyota.toyotacan import toyota_checksum +from opendbc.car.subaru.subarucan import subaru_checksum +from opendbc.car.chrysler.chryslercan import chrysler_checksum, fca_giorgio_checksum +from opendbc.car.hyundai.hyundaicanfd import hkg_can_fd_checksum +from opendbc.car.volkswagen.mqbcan import volkswagen_mqb_meb_checksum, xor_checksum +from opendbc.car.tesla.teslacan import tesla_checksum +from opendbc.car.body.bodycan import body_checksum +from opendbc.car.psa.psacan import psa_checksum + + +class SignalType: + DEFAULT = 0 + COUNTER = 1 + HONDA_CHECKSUM = 2 + TOYOTA_CHECKSUM = 3 + BODY_CHECKSUM = 4 + VOLKSWAGEN_MQB_MEB_CHECKSUM = 5 + XOR_CHECKSUM = 6 + SUBARU_CHECKSUM = 7 + CHRYSLER_CHECKSUM = 8 + HKG_CAN_FD_CHECKSUM = 9 + FCA_GIORGIO_CHECKSUM = 10 + TESLA_CHECKSUM = 11 + PSA_CHECKSUM = 12 + + +@dataclass +class Signal: + name: str + start_bit: int + msb: int + lsb: int + size: int + is_signed: bool + factor: float + offset: float + is_little_endian: bool + type: int = SignalType.DEFAULT + calc_checksum: 'Callable[[int, Signal, bytearray], int] | None' = None + + +@dataclass +class Msg: + name: str + address: int + size: int + sigs: dict[str, Signal] + + +@dataclass +class Val: + name: str + address: int + def_val: str + sigs: dict[str, Signal] | None = None + + +BO_RE = re.compile(r"^BO_ (\w+) (\w+) *: (\w+) (\w+)") +SG_RE = re.compile(r"^SG_ (\w+) : (\d+)\|(\d+)@(\d)([+-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[[0-9.+\-eE]+\|[0-9.+\-eE]+\] \".*\" .*") +SGM_RE = re.compile(r"^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d)([+-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[[0-9.+\-eE]+\|[0-9.+\-eE]+\] \".*\" .*") +VAL_RE = re.compile(r"^VAL_ (\w+) (\w+) (.*);") +VAL_SPLIT_RE = re.compile(r'["]+') + + +@dataclass +class DBC: + name: str + msgs: dict[int, Msg] + addr_to_msg: dict[int, Msg] + name_to_msg: dict[str, Msg] + vals: list[Val] + + def __init__(self, name: str): + dbc_path = name + if not os.path.exists(dbc_path): + dbc_path = os.path.join(DBC_PATH, name + ".dbc") + + self._parse(dbc_path) + + def _parse(self, path: str): + self.name = os.path.basename(path).replace(".dbc", "") + with open(path) as f: + lines = f.readlines() + + checksum_state = get_checksum_state(self.name) + be_bits = [j + i * 8 for i in range(64) for j in range(7, -1, -1)] + self.msgs: dict[int, Msg] = {} + self.addr_to_msg: dict[int, Msg] = {} + self.name_to_msg: dict[str, Msg] = {} + self.vals: list[Val] = [] + address = 0 + signals_temp: dict[int, dict[str, Signal]] = {} + for line_num, line in enumerate(lines, 1): + line = line.strip() + if line.startswith("BO_ "): + m = BO_RE.match(line) + if not m: + continue + address = int(m.group(1), 0) + msg_name = m.group(2) + size = int(m.group(3), 0) + sigs = {} + self.msgs[address] = Msg(msg_name, address, size, sigs) + self.addr_to_msg[address] = self.msgs[address] + self.name_to_msg[msg_name] = self.msgs[address] + signals_temp[address] = sigs + elif line.startswith("SG_ "): + m = SG_RE.search(line) + offset = 0 + if not m: + m = SGM_RE.search(line) + if not m: + continue + offset = 1 + sig_name = m.group(1) + start_bit = int(m.group(2 + offset)) + size = int(m.group(3 + offset)) + is_little_endian = m.group(4 + offset) == "1" + is_signed = m.group(5 + offset) == "-" + factor = float(m.group(6 + offset)) + offset_val = float(m.group(7 + offset)) + + if is_little_endian: + lsb = start_bit + msb = start_bit + size - 1 + else: + idx = be_bits.index(start_bit) + lsb = be_bits[idx + size - 1] + msb = start_bit + + sig = Signal(sig_name, start_bit, msb, lsb, size, is_signed, factor, offset_val, is_little_endian) + set_signal_type(sig, checksum_state, self.name, line_num) + signals_temp[address][sig_name] = sig + elif line.startswith("VAL_ "): + m = VAL_RE.search(line) + if not m: + continue + val_addr = int(m.group(1), 0) + sgname = m.group(2) + defs = m.group(3) + words = [w.strip() for w in VAL_SPLIT_RE.split(defs) if w.strip()] + words = [w.upper().replace(" ", "_") for w in words] + val_def = " ".join(words).strip() + self.vals.append(Val(sgname, val_addr, val_def)) + for addr, sigs in signals_temp.items(): + self.msgs[addr].sigs = sigs + + +# ***** checksum functions ***** + +def tesla_setup_signal(sig: Signal, dbc_name: str, line_num: int) -> None: + if sig.name.endswith("Counter"): + sig.type = SignalType.COUNTER + elif sig.name.endswith("Checksum"): + sig.type = SignalType.TESLA_CHECKSUM + sig.calc_checksum = tesla_checksum + + +@dataclass +class ChecksumState: + checksum_size: int + counter_size: int + checksum_start_bit: int + counter_start_bit: int + little_endian: bool + checksum_type: int + calc_checksum: Callable[[int, Signal, bytearray], int] | None + setup_signal: Callable[[Signal, str, int], None] | None = None + + +def get_checksum_state(dbc_name: str) -> ChecksumState | None: + if dbc_name.startswith(("honda_", "acura_")): + return ChecksumState(4, 2, 3, 5, False, SignalType.HONDA_CHECKSUM, honda_checksum) + elif dbc_name.startswith(("toyota_", "lexus_")): + return ChecksumState(8, -1, 7, -1, False, SignalType.TOYOTA_CHECKSUM, toyota_checksum) + elif dbc_name.startswith("hyundai_canfd_generated"): + return ChecksumState(16, -1, 0, -1, True, SignalType.HKG_CAN_FD_CHECKSUM, hkg_can_fd_checksum) + elif dbc_name.startswith(("vw_mqb", "vw_mqbevo", "vw_meb")): + return ChecksumState(8, 4, 0, 0, True, SignalType.VOLKSWAGEN_MQB_MEB_CHECKSUM, volkswagen_mqb_meb_checksum) + elif dbc_name.startswith("vw_pq"): + return ChecksumState(8, 4, 0, -1, True, SignalType.XOR_CHECKSUM, xor_checksum) + elif dbc_name.startswith("subaru_global_"): + return ChecksumState(8, -1, 0, -1, True, SignalType.SUBARU_CHECKSUM, subaru_checksum) + elif dbc_name.startswith("chrysler_"): + return ChecksumState(8, -1, 7, -1, False, SignalType.CHRYSLER_CHECKSUM, chrysler_checksum) + elif dbc_name.startswith("fca_giorgio"): + return ChecksumState(8, -1, 7, -1, False, SignalType.FCA_GIORGIO_CHECKSUM, fca_giorgio_checksum) + elif dbc_name.startswith("comma_body"): + return ChecksumState(8, 4, 7, 3, False, SignalType.BODY_CHECKSUM, body_checksum) + elif dbc_name.startswith("tesla_model3_party"): + return ChecksumState(8, -1, 0, -1, True, SignalType.TESLA_CHECKSUM, tesla_checksum, tesla_setup_signal) + elif dbc_name.startswith("psa_"): + return ChecksumState(4, 4, 7, 3, False, SignalType.PSA_CHECKSUM, psa_checksum) + return None + + +def set_signal_type(sig: Signal, chk: ChecksumState | None, dbc_name: str, line_num: int) -> None: + sig.calc_checksum = None + if chk: + if chk.setup_signal: + chk.setup_signal(sig, dbc_name, line_num) + if sig.name == "CHECKSUM": + sig.type = chk.checksum_type + sig.calc_checksum = chk.calc_checksum + elif sig.name == "COUNTER": + sig.type = SignalType.COUNTER diff --git a/opendbc_repo/opendbc/can/packer.py b/opendbc_repo/opendbc/can/packer.py new file mode 100644 index 0000000000..efc1c81763 --- /dev/null +++ b/opendbc_repo/opendbc/can/packer.py @@ -0,0 +1,71 @@ +import math + +from opendbc.car.carlog import carlog +from opendbc.can.dbc import DBC, Signal, SignalType + + +class CANPacker: + def __init__(self, dbc_name: str): + self.dbc = DBC(dbc_name) + self.counters: dict[int, int] = {} + + def pack(self, address: int, values: dict[str, float]) -> bytearray: + msg = self.dbc.addr_to_msg.get(address) + if msg is None: + carlog.error(f"msg not found for {address=}") + return bytearray() + dat = bytearray(msg.size) + counter_set = False + for name, value in values.items(): + sig = msg.sigs.get(name) + if sig is None: + carlog.error(f"unknown signal {name=} in {msg.name}") + continue + ival = int(math.floor((value - sig.offset) / sig.factor + 0.5)) + if ival < 0: + ival = (1 << sig.size) + ival + set_value(dat, sig, ival) + if sig.type == SignalType.COUNTER or sig.name == "COUNTER": + self.counters[address] = int(value) + counter_set = True + sig_counter = next((s for s in msg.sigs.values() if s.type == SignalType.COUNTER or s.name == "COUNTER"), None) + if sig_counter and not counter_set: + if address not in self.counters: + self.counters[address] = 0 + set_value(dat, sig_counter, self.counters[address]) + self.counters[address] = (self.counters[address] + 1) % (1 << sig_counter.size) + sig_checksum = next((s for s in msg.sigs.values() if s.type > SignalType.COUNTER), None) + if sig_checksum and sig_checksum.calc_checksum: + checksum = sig_checksum.calc_checksum(address, sig_checksum, dat) + set_value(dat, sig_checksum, checksum) + return dat + + def make_can_msg(self, name_or_addr, bus: int, values: dict[str, float]): + if isinstance(name_or_addr, int): + addr = name_or_addr + else: + msg = self.dbc.name_to_msg.get(name_or_addr) + if msg is None: + carlog.error(f"msg not found for {name_or_addr=}") + return 0, b'', bus + addr = msg.address + dat = self.pack(addr, values) + if len(dat) == 0: + return 0, b'', bus + return addr, bytes(dat), bus + + +def set_value(msg: bytearray, sig: Signal, ival: int) -> None: + i = sig.lsb // 8 + bits = sig.size + if sig.size < 64: + ival &= (1 << sig.size) - 1 + while 0 <= i < len(msg) and bits > 0: + shift = sig.lsb % 8 if (sig.lsb // 8) == i else 0 + size = min(bits, 8 - shift) + mask = ((1 << size) - 1) << shift + msg[i] &= ~mask + msg[i] |= (ival & ((1 << size) - 1)) << shift + bits -= size + ival >>= size + i = i + 1 if sig.is_little_endian else i - 1 diff --git a/opendbc_repo/opendbc/can/parser.py b/opendbc_repo/opendbc/can/parser.py new file mode 100644 index 0000000000..ffcb4a37fb --- /dev/null +++ b/opendbc_repo/opendbc/can/parser.py @@ -0,0 +1,274 @@ +import math +import numbers +from collections import defaultdict, deque +from dataclasses import dataclass, field + +from opendbc.car.carlog import carlog +from opendbc.can.dbc import DBC, Signal + + +MAX_BAD_COUNTER = 5 +CAN_INVALID_CNT = 5 + + +def get_raw_value(dat: bytes | bytearray, sig: Signal) -> int: + ret = 0 + i = sig.msb // 8 + bits = sig.size + while 0 <= i < len(dat) and bits > 0: + lsb = sig.lsb if (sig.lsb // 8) == i else i * 8 + msb = sig.msb if (sig.msb // 8) == i else (i + 1) * 8 - 1 + size = msb - lsb + 1 + d = (dat[i] >> (lsb - (i * 8))) & ((1 << size) - 1) + ret |= d << (bits - size) + bits -= size + i = i - 1 if sig.is_little_endian else i + 1 + return ret + + +@dataclass +class MessageState: + address: int + name: str + size: int + signals: list[Signal] + ignore_alive: bool = False + ignore_checksum: bool = False + ignore_counter: bool = False + frequency: float = 0.0 + timeout_threshold: float = 1e5 # default to 1Hz threshold + vals: list[float] = field(default_factory=list) + all_vals: list[list[float]] = field(default_factory=list) + timestamps: deque[int] = field(default_factory=lambda: deque(maxlen=500)) + counter: int = 0 + counter_fail: int = 0 + first_seen_nanos: int = 0 + last_warning_log_nanos: int = 0 + + def rate_limited_log(self, last_update_nanos: int, msg: str) -> None: + if (last_update_nanos - self.last_warning_log_nanos) >= 1_000_000_000: + carlog.warning(f"CANParser: {hex(self.address)} {self.name} {msg}") + self.last_warning_log_nanos = last_update_nanos + + def parse(self, nanos: int, dat: bytes) -> bool: + tmp_vals: list[float] = [0.0] * len(self.signals) + checksum_failed = False + counter_failed = False + + if self.first_seen_nanos == 0: + self.first_seen_nanos = nanos + + for i, sig in enumerate(self.signals): + tmp = get_raw_value(dat, sig) + if sig.is_signed: + tmp -= ((tmp >> (sig.size - 1)) & 0x1) * (1 << sig.size) + + if not self.ignore_checksum and sig.calc_checksum is not None: + expected_checksum = sig.calc_checksum(self.address, sig, bytearray(dat)) + if tmp != expected_checksum: + checksum_failed = True + self.rate_limited_log(nanos, f"checksum failed: received {hex(tmp)}, calculated {hex(expected_checksum)}") + + if not self.ignore_counter and sig.type == 1: # COUNTER + if not self.update_counter(tmp, sig.size): + counter_failed = True + + tmp_vals[i] = tmp * sig.factor + sig.offset + + # must have good counter and checksum to update data + if checksum_failed or counter_failed: + return False + + if not self.vals: + self.vals = [0.0] * len(self.signals) + self.all_vals = [[] for _ in self.signals] + + for i, v in enumerate(tmp_vals): + self.vals[i] = v + self.all_vals[i].append(v) + + self.timestamps.append(nanos) + + if self.frequency < 1e-5 and len(self.timestamps) >= 3: + dt = (self.timestamps[-1] - self.timestamps[0]) * 1e-9 + if (dt > 1.0 or len(self.timestamps) >= self.timestamps.maxlen) and dt != 0: + self.frequency = min(len(self.timestamps) / dt, 100.0) + self.timeout_threshold = (1_000_000_000 / self.frequency) * 10 + return True + + def update_counter(self, cur_count: int, cnt_size: int) -> bool: + if ((self.counter + 1) & ((1 << cnt_size) - 1)) != cur_count: + self.counter_fail = min(self.counter_fail + 1, MAX_BAD_COUNTER) + elif self.counter_fail > 0: + self.counter_fail -= 1 + self.counter = cur_count + return self.counter_fail < MAX_BAD_COUNTER + + def valid(self, current_nanos: int, bus_timeout: bool) -> bool: + if self.ignore_alive: + return True + if not self.timestamps: + return False + if (current_nanos - self.timestamps[-1]) > self.timeout_threshold: + return False + return True + + +class VLDict(dict): + def __init__(self, parser): + super().__init__() + self.parser = parser + + def __getitem__(self, key): + if key not in self: + self.parser._add_message(key) + return super().__getitem__(key) + + +class CANParser: + def __init__(self, dbc_name: str, messages: list[tuple[str | int, int]], bus: int): + self.dbc_name: str = dbc_name + self.bus: int = bus + self.dbc: DBC = DBC(dbc_name) + + self.vl: dict[int | str, dict[str, float]] = VLDict(self) + self.vl_all: dict[int | str, dict[str, list[float]]] = {} + self.ts_nanos: dict[int | str, dict[str, int]] = {} + self.addresses: set[int] = set() + self.message_states: dict[int, MessageState] = {} + + for name_or_addr, freq in messages: + if isinstance(name_or_addr, numbers.Number): + msg = self.dbc.addr_to_msg.get(int(name_or_addr)) + else: + msg = self.dbc.name_to_msg.get(name_or_addr) + if msg is None: + raise RuntimeError(f"could not find message {name_or_addr!r} in DBC {dbc_name}") + if msg.address in self.addresses: + raise RuntimeError("Duplicate Message Check: %d" % msg.address) + + self._add_message(name_or_addr, freq) + + self.can_invalid_cnt: int = CAN_INVALID_CNT + self.last_nonempty_nanos: int = 0 + self._last_update_nanos: int = 0 + + def _add_message(self, name_or_addr: str | int, freq: int = None) -> None: + if isinstance(name_or_addr, numbers.Number): + msg = self.dbc.addr_to_msg.get(int(name_or_addr)) + else: + msg = self.dbc.name_to_msg.get(name_or_addr) + assert msg is not None + assert msg.address not in self.addresses + + self.addresses.add(msg.address) + signal_names = list(msg.sigs.keys()) + signals_dict = {s: 0.0 for s in signal_names} + dict.__setitem__(self.vl, msg.address, signals_dict) + dict.__setitem__(self.vl, msg.name, signals_dict) + self.vl_all[msg.address] = defaultdict(list) + self.vl_all[msg.name] = self.vl_all[msg.address] + self.ts_nanos[msg.address] = {s: 0 for s in signal_names} + self.ts_nanos[msg.name] = self.ts_nanos[msg.address] + + state = MessageState( + address=msg.address, + name=msg.name, + size=msg.size, + signals=list(msg.sigs.values()), + ignore_alive=freq is not None and math.isnan(freq), + ) + if freq is not None and freq > 0: + state.frequency = freq + else: + # if frequency not specified, assume 1Hz until we learn it + freq = 1 + state.timeout_threshold = (1_000_000_000 / freq) * 10 + + self.message_states[msg.address] = state + + @property + def bus_timeout(self) -> bool: + ignore_alive = all(s.ignore_alive for s in self.message_states.values()) + bus_timeout_threshold = 500 * 1_000_000 + for st in self.message_states.values(): + if st.timeout_threshold > 0: + bus_timeout_threshold = min(bus_timeout_threshold, st.timeout_threshold) + return ((self._last_update_nanos - self.last_nonempty_nanos) > bus_timeout_threshold) and not ignore_alive + + @property + def can_valid(self) -> bool: + valid = True + counters_valid = True + bus_timeout = self.bus_timeout + for state in self.message_states.values(): + if state.counter_fail >= MAX_BAD_COUNTER: + counters_valid = False + state.rate_limited_log(self._last_update_nanos, f"counter invalid, {state.counter_fail=} {MAX_BAD_COUNTER=}") + if not state.valid(self._last_update_nanos, bus_timeout): + valid = False + state.rate_limited_log(self._last_update_nanos, "not valid (timeout or missing)") + + # TODO: probably only want to increment this once per update() call + self.can_invalid_cnt = 0 if valid else min(self.can_invalid_cnt + 1, CAN_INVALID_CNT) + return self.can_invalid_cnt < CAN_INVALID_CNT and counters_valid + + def update(self, strings, sendcan: bool = False): + if strings and not isinstance(strings[0], list | tuple): + strings = [strings] + + for addr in self.addresses: + for k in self.vl_all[addr]: + self.vl_all[addr][k].clear() + + updated_addrs: set[int] = set() + for entry in strings: + t = entry[0] + frames = entry[1] + bus_empty = True + for address, dat, src in frames: + if src != self.bus: + continue + bus_empty = False + state = self.message_states.get(address) + if state is None or len(dat) > 64: + continue + if state.parse(t, dat): + updated_addrs.add(address) + + vl_addr = self.vl[address] + vl_all_addr = self.vl_all[address] + ts_addr = self.ts_nanos[address] + + for i, sig in enumerate(state.signals): + vl_addr[sig.name] = state.vals[i] + vl_all_addr[sig.name] = state.all_vals[i] + ts_addr[sig.name] = state.timestamps[-1] + + if not bus_empty: + self.last_nonempty_nanos = t + + self._last_update_nanos = t + + return updated_addrs + + +class CANDefine: + def __init__(self, dbc_name: str): + dbc = DBC(dbc_name) + + dv = defaultdict(dict) + for val in dbc.vals: + sgname = val.name + address = val.address + msg = dbc.addr_to_msg.get(address) + if msg is None: + raise KeyError(address) + msgname = msg.name + parts = val.def_val.split() + values = [int(v) for v in parts[::2]] + defs = parts[1::2] + dv[address][sgname] = dict(zip(values, defs, strict=True)) + dv[msgname][sgname] = dv[address][sgname] + + self.dv = dict(dv) diff --git a/opendbc_repo/opendbc/can/tests/.gitignore b/opendbc_repo/opendbc/can/tests/.gitignore new file mode 100644 index 0000000000..192fb0945e --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/.gitignore @@ -0,0 +1 @@ +*.bz2 diff --git a/opendbc_repo/opendbc/can/tests/__init__.py b/opendbc_repo/opendbc/can/tests/__init__.py new file mode 100644 index 0000000000..3bf02fdae0 --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/__init__.py @@ -0,0 +1,8 @@ +import glob +import os + +from opendbc import DBC_PATH + +ALL_DBCS = [os.path.basename(dbc).split('.')[0] for dbc in + glob.glob(f"{DBC_PATH}/*.dbc")] +TEST_DBC = os.path.abspath(os.path.join(os.path.dirname(__file__), "test.dbc")) diff --git a/opendbc_repo/opendbc/can/tests/benchmark.py b/opendbc_repo/opendbc/can/tests/benchmark.py new file mode 100755 index 0000000000..6652f44da0 --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/benchmark.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import time +from opendbc.can import CANPacker, CANParser + + +def _benchmark(checks, n): + parser = CANParser('toyota_new_mc_pt_generated', checks, 0) + packer = CANPacker('toyota_new_mc_pt_generated') + + t1 = time.process_time_ns() + can_msgs = [] + for i in range(10000): + values = {"ACC_CONTROL": {"ACC_TYPE": 1, "ALLOW_LONG_PRESS": 3}} + msgs = [packer.make_can_msg(k, 0, v) for k, v in values.items()] + can_msgs.append([int(0.01 * i * 1e9), msgs]) + t2 = time.process_time_ns() + pack_dt = t2 - t1 + + ets = [] + for _ in range(25): + if n > 1: + strings = [] + for i in range(0, len(can_msgs), n): + strings.append(can_msgs[i:i + n]) + t1 = time.process_time_ns() + for m in strings: + parser.update(m) + t2 = time.process_time_ns() + else: + t1 = time.process_time_ns() + for m in can_msgs: + parser.update([m]) + t2 = time.process_time_ns() + + ets.append(t2 - t1) + + et = sum(ets) / len(ets) + avg_nanos = et / len(can_msgs) + print('[%d] %.1fms to pack, %.1fms to parse %s messages, avg: %dns' % (n, pack_dt/1e6, et/1e6, len(can_msgs), avg_nanos)) + + +if __name__ == "__main__": + # python -m cProfile -s cumulative benchmark.py + _benchmark([('ACC_CONTROL', 10)], 1) + _benchmark([('ACC_CONTROL', 10)], 5) + _benchmark([('ACC_CONTROL', 10)], 10) diff --git a/opendbc_repo/opendbc/can/tests/test.dbc b/opendbc_repo/opendbc/can/tests/test.dbc new file mode 100644 index 0000000000..05104fb068 --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/test.dbc @@ -0,0 +1,27 @@ +CM_ "This DBC is used for the CAN parser and packer tests."; + +BO_ 228 STEERING_CONTROL: 5 EON + SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS + SG_ SET_ME_X00 : 22|7@0+ (1,0) [0|127] "" EPS + SG_ SET_ME_X00_2 : 31|8@0+ (1,0) [0|0] "" EPS + SG_ STEER_TORQUE : 7|16@0- (1,0) [-4096|4096] "" EPS + SG_ STEER_DOWN_TO_ZERO : 38|1@0+ (1,0) [0|1] "" EPS + SG_ COUNTER : 37|2@0+ (1,0) [0|3] "" EPS + SG_ CHECKSUM : 35|4@0+ (1,0) [0|15] "" EPS + +BO_ 316 Brake_Status: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|46@1+ (1,0) [0|1] "" XXX + SG_ ES_Brake : 58|1@1+ (1,0) [0|1] "" XXX + SG_ Signal2 : 59|3@1+ (1,0) [0|1] "" XXX + SG_ Brake : 62|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 245 CAN_FD_MESSAGE: 32 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|1] "" XXX + SG_ SIGNED : 22|16@0- (1,0) [0|1] "" XXX + SG_ 64_BIT_LE : 159|64@1+ (1,0) [0|1] "" XXX + SG_ 64_BIT_BE : 80|64@0+ (1,0) [0|1] "" XXX + +VAL_ 80 NON_EXISTENT_ADDR 0 "test"; diff --git a/opendbc_repo/opendbc/can/tests/test_checksums.py b/opendbc_repo/opendbc/can/tests/test_checksums.py new file mode 100644 index 0000000000..a357819a04 --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/test_checksums.py @@ -0,0 +1,556 @@ +import copy +from opendbc.can import CANPacker, CANParser + + +class TestCanChecksums: + + def verify_checksum(self, subtests, dbc_file: str, msg_name: str, msg_addr: int, test_messages: list[bytes], + checksum_field: str = 'CHECKSUM', counter_field = 'COUNTER'): + """ + Verify that opendbc calculates payload CRCs/checksums matching those received in known-good sample messages + Depends on all non-zero bits in the sample message having a corresponding DBC signal, add UNKNOWN signals if needed + """ + parser = CANParser(dbc_file, [(msg_name, 0)], 0) + packer = CANPacker(dbc_file) + + for data in test_messages: + expected_msg = (msg_addr, data, 0) + parser.update([0, [expected_msg]]) + expected = copy.deepcopy(parser.vl[msg_name]) + + modified = copy.deepcopy(expected) + modified.pop(checksum_field, None) + modified_msg = packer.make_can_msg(msg_name, 0, modified) + + parser.update([0, [modified_msg]]) + tested = parser.vl[msg_name] + with subtests.test(counter=expected[counter_field]): + assert tested[checksum_field] == expected[checksum_field] + + def verify_fca_giorgio_crc(self, subtests, msg_name: str, msg_addr: int, test_messages: list[bytes]): + """Test modified SAE J1850 CRCs, with special final XOR cases for EPS messages""" + assert len(test_messages) == 3 + self.verify_checksum(subtests, "fca_giorgio", msg_name, msg_addr, test_messages) + + def test_fca_giorgio_eps_1(self, subtests): + self.verify_fca_giorgio_crc(subtests, "EPS_1", 0xDE, [ + b'\x17\x51\x97\xcc\x00\xdf', + b'\x17\x51\x97\xc9\x01\xa3', + b'\x17\x51\x97\xcc\x02\xe5', + ]) + + def test_fca_giorgio_eps_2(self, subtests): + self.verify_fca_giorgio_crc(subtests, "EPS_2", 0x106, [ + b'\x7c\x43\x57\x60\x00\x00\xa1', + b'\x7c\x63\x58\xe0\x00\x01\xd5', + b'\x7c\x63\x58\xe0\x00\x02\xf2', + ]) + + def test_fca_giorgio_eps_3(self, subtests): + self.verify_fca_giorgio_crc(subtests, "EPS_3", 0x122, [ + b'\x7b\x30\x00\xf8', + b'\x7b\x10\x01\x90', + b'\x7b\xf0\x02\x6e', + ]) + + def test_fca_giorgio_abs_2(self, subtests): + self.verify_fca_giorgio_crc(subtests, "ABS_2", 0xFE, [ + b'\x7e\x38\x00\x7d\x10\x31\x80\x32', + b'\x7e\x38\x00\x7d\x10\x31\x81\x2f', + b'\x7e\x38\x00\x7d\x20\x31\x82\x20', + ]) + + def test_honda_checksum(self): + """Test checksums for Honda standard and extended CAN ids""" + # TODO: refactor to use self.verify_checksum() + dbc_file = "honda_civic_hatchback_ex_2017_can_generated" + msgs = [("LKAS_HUD", 0), ("LKAS_HUD_A", 0)] + parser = CANParser(dbc_file, msgs, 0) + packer = CANPacker(dbc_file) + + values = { + 'LKAS_READY': 1, + 'LKAS_STATE_CHANGE': 1, + 'STEERING_REQUIRED': 1, + 'SOLID_LANES': 1, + 'BEEP': 0, + } + + # known correct checksums according to the above values + checksum_std = [11, 10, 9, 8] + checksum_ext = [4, 3, 2, 1] + + for std, ext in zip(checksum_std, checksum_ext, strict=True): + msgs = [ + packer.make_can_msg("LKAS_HUD", 0, values), + packer.make_can_msg("LKAS_HUD_A", 0, values), + ] + parser.update([0, msgs]) + + assert parser.vl['LKAS_HUD']['CHECKSUM'] == std + assert parser.vl['LKAS_HUD_A']['CHECKSUM'] == ext + + def verify_volkswagen_mqb_crc(self, subtests, msg_name: str, msg_addr: int, test_messages: list[bytes], counter_field: str = 'COUNTER'): + """Test AUTOSAR E2E Profile 2 CRCs""" + assert len(test_messages) == 16 # All counter values must be tested + self.verify_checksum(subtests, "vw_mqb", msg_name, msg_addr, test_messages, counter_field=counter_field) + + def test_volkswagen_mqb_crc_lwi_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "LWI_01", 0x86, [ + b'\x6b\x00\xbd\x00\x00\x00\x00\x00', + b'\xee\x01\x0a\x00\x00\x00\x00\x00', + b'\xd8\x02\xa9\x00\x00\x00\x00\x00', + b'\x03\x03\xbe\xa2\x12\x00\x00\x00', + b'\x7b\x04\x31\x20\x03\x00\x00\x00', + b'\x8b\x05\xe2\x85\x09\x00\x00\x00', + b'\x63\x06\x13\x21\x00\x00\x00\x00', + b'\x66\x07\x05\x00\x00\x00\x00\x00', + b'\x49\x08\x0d\x00\x00\x00\x00\x00', + b'\x5f\x09\x7e\x60\x01\x00\x00\x00', + b'\xaf\x0a\x72\x20\x00\x00\x00\x00', + b'\x59\x0b\x1b\x00\x00\x00\x00\x00', + b'\xa8\x0c\x06\x00\x00\x00\x00\x00', + b'\xbc\x0d\x72\x20\x00\x00\x00\x00', + b'\xf9\x0e\x0f\x00\x00\x00\x00\x00', + b'\x60\x0f\x62\xc0\x00\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_airbag_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "Airbag_01", 0x40, [ + b'\xaf\x00\x00\x80\xc0\x00\x20\x3e', + b'\x54\x01\x00\x80\xc0\x00\x20\x1a', + b'\x54\x02\x00\x80\xc0\x00\x60\x00', + b'\x31\x03\x00\x80\xc0\x00\x60\xf2', + b'\xe0\x04\x00\x80\xc0\x00\x60\xcc', + b'\xb3\x05\x00\x80\xc0\x00\x40\xde', + b'\xa4\x06\x00\x80\xc0\x00\x40\x18', + b'\x94\x07\x00\x80\xc0\x00\x20\x38', + b'\x2d\x08\x00\x80\xc0\x00\x60\xae', + b'\xc2\x09\x00\x80\xc0\x00\x00\x1c', + b'\x1f\x0a\x00\x80\xc0\x00\x60\x2c', + b'\x7f\x0b\x00\x80\xc0\x00\x00\x00', + b'\x03\x0c\x00\x80\xc0\x00\x40\xd6', + b'\x56\x0d\x00\x80\xc0\x00\x20\x50', + b'\x4a\x0e\x00\x80\xc0\x00\x20\xf2', + b'\xe5\x0f\x00\x80\xc0\x00\x40\xf6', + ]) + + def test_volkswagen_mqb_crc_lh_eps_03(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "LH_EPS_03", 0x9F, [ + b'\x11\x30\x2e\x00\x05\x1c\x80\x30', + b'\x5b\x31\x8e\x03\x05\x53\x00\x30', + b'\xcb\x32\xd3\x06\x05\x73\x00\x30', + b'\xf2\x33\x28\x00\x05\x26\x00\x30', + b'\x0b\x34\x44\x00\x05\x5b\x80\x30', + b'\xed\x35\x80\x00\x03\x34\x00\x30', + b'\xf0\x36\x88\x00\x05\x3d\x80\x30', + b'\x9e\x37\x44\x03\x05\x41\x00\x30', + b'\x68\x38\x06\x01\x05\x18\x80\x30', + b'\x87\x39\x51\x00\x05\x11\x80\x30', + b'\x8c\x3a\x29\x00\x05\xac\x00\x30', + b'\x08\x3b\xbd\x00\x05\x8e\x00\x30', + b'\xd4\x3c\x19\x00\x05\x05\x80\x30', + b'\x29\x3d\x54\x00\x05\x5b\x00\x30', + b'\xa1\x3e\x49\x01\x03\x04\x80\x30', + b'\xe2\x3f\x05\x00\x05\x0a\x00\x30', + ]) + + def test_volkswagen_mqb_crc_getriebe_11(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "Getriebe_11", 0xAD, [ + b'\xf8\xe0\xbf\xff\x5f\x20\x20\x20', + b'\xb0\xe1\xbf\xff\xc6\x98\x21\x80', + b'\xd2\xe2\xbf\xff\x5f\x20\x20\x20', + b'\x00\xe3\xbf\xff\xaa\x20\x20\x10', + b'\xf1\xe4\xbf\xff\x5f\x20\x20\x20', + b'\xc4\xe5\xbf\xff\x5f\x20\x20\x20', + b'\xda\xe6\xbf\xff\x5f\x20\x20\x20', + b'\x85\xe7\xbf\xff\x5f\x20\x20\x20', + b'\x12\xe8\xbf\xff\x5f\x20\x20\x20', + b'\x45\xe9\xbf\xff\xaa\x20\x20\x10', + b'\x03\xea\xbf\xff\xcc\x20\x20\x10', + b'\xfc\xeb\xbf\xff\x5f\x20\x21\x20', + b'\xfe\xec\xbf\xff\xad\x20\x20\x10', + b'\xbd\xed\xbf\xff\xaa\x20\x20\x10', + b'\x67\xee\xbf\xff\xaa\x20\x20\x10', + b'\x36\xef\xbf\xff\xaa\x20\x20\x10', + ], counter_field="COUNTER_DISABLED") # see opendbc#1235 + + def test_volkswagen_mqb_crc_esp_21(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ESP_21", 0xFD, [ + b'\x66\xd0\x1f\x80\x45\x05\x00\x00', + b'\x87\xd1\x1f\x80\x52\x05\x00\x00', + b'\xcd\xd2\x1f\x80\x50\x06\x00\x00', + b'\xfd\xd3\x1f\x80\x35\x02\x00\x00', + b'\xfa\xd4\x1f\x80\x22\x05\x00\x00', + b'\xfd\xd5\x1f\x80\x84\x04\x00\x00', + b'\x2e\xd6\x1f\x80\xf0\x03\x00\x00', + b'\x9f\xd7\x1f\x80\x00\x00\x00\x00', + b'\x1e\xd8\x1f\x80\xb3\x03\x00\x00', + b'\x61\xd9\x1f\x80\x6d\x05\x00\x00', + b'\x44\xda\x1f\x80\x47\x02\x00\x00', + b'\x86\xdb\x1f\x80\x3a\x02\x00\x00', + b'\x39\xdc\x1f\x80\xcb\x01\x00\x00', + b'\x19\xdd\x1f\x80\x00\x00\x00\x00', + b'\x8c\xde\x1f\x80\xba\x04\x00\x00', + b'\xfb\xdf\x1f\x80\x46\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_esp_02(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ESP_02", 0x101, [ + b'\xf2\x00\x7e\xff\xa1\x2a\x40\x00', + b'\xd3\x01\x7d\x00\xa2\x0c\x02\x00', + b'\x03\x02\x7a\x06\xa2\x49\x42\x00', + b'\xfd\x03\x70\xfb\xa1\xde\x00\x00', + b'\x8e\x04\x7b\xf7\xa1\xd2\x01\x00', + b'\x0f\x05\x7d\xfd\xa1\x31\x40\x00', + b'\xb6\x06\x7d\x01\xa2\x0a\x40\x00', + b'\xe8\x07\x7e\xfd\xa1\x12\x40\x00', + b'\x74\x08\x7a\x01\xa2\x40\x01\x00', + b'\xe3\x09\x81\x00\xa2\xb5\x01\x00', + b'\xab\x0a\x74\x09\xa2\x9f\x42\x00', + b'\xf3\x0b\x80\x12\xa2\x94\x00\x00', + b'\x88\x0c\x7f\x07\xa2\x46\x00\x00', + b'\x6f\x0d\x7f\xff\xa1\x53\x40\x00', + b'\x38\x0e\x73\xd6\xa1\x6a\x40\x00', + b'\x49\x0f\x85\x12\xa2\xf6\x01\x00', + ]) + + def test_volkswagen_mqb_crc_esp_05(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ESP_05", 0x106, [ + b'\x90\x80\x64\x00\x00\x00\xe7\x10', + b'\xf4\x81\x64\x00\x00\x00\xe7\x10', + b'\x90\x82\x63\x00\x00\x00\xe8\x10', + b'\xa0\x83\x63\x00\x00\x00\xe6\x10', + b'\xe7\x84\x63\x00\x00\x00\xe8\x10', + b'\x2e\x85\x78\x04\x00\x00\xea\x30', + b'\x7b\x86\x63\x00\x00\x00\xe6\x10', + b'\x71\x87\x79\x04\x00\x00\xd0\x30', + b'\x50\x88\x79\x04\x00\x00\xea\x30', + b'\x81\x89\x64\x00\x00\x00\xe1\x10', + b'\x6a\x8a\x68\x00\x00\x04\xd0\x10', + b'\x17\x8b\x6a\x04\x00\x00\xe6\x10', + b'\xc7\x8c\x63\x00\x00\x00\xd1\x10', + b'\x53\x8d\x64\x04\x00\x00\xe2\x10', + b'\x24\x8e\x63\x00\x00\x00\xe7\x10', + b'\x3f\x8f\x82\x04\x00\x00\xe6\x30', + ]) + + def test_volkswagen_mqb_crc_esp_10(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ESP_10", 0x116, [ + b'\x2d\x00\xd5\x98\x9f\x26\x25\x0f', + b'\x24\x01\x60\x63\x2c\x5e\x3b\x0f', + b'\x08\x02\xb2\x2f\xee\x9a\x29\x0f', + b'\x7c\x03\x17\x07\x1d\xe5\x8c\x0f', + b'\xaa\x04\xd6\xe3\xeb\x98\xe8\x0f', + b'\x4e\x05\xbb\xd9\x65\x43\xca\x0f', + b'\x59\x06\x78\xbd\x25\xc6\xf2\xff', + b'\xaf\x07\x42\x85\x53\xbe\xbe\x0f', + b'\x2a\x08\xa6\xcd\x95\x8c\x12\x0f', + b'\xce\x09\x6e\x17\x6d\x1b\x2f\x0f', + b'\x60\x0a\xd3\xe6\x3a\x8d\xf0\x0f', + b'\xc5\x0b\xfc\x69\x57\x50\x21\x0f', + b'\x70\x0c\xde\xf3\x9d\xe9\x6b\xff', + b'\x62\x0d\xc4\x1a\xdb\x61\x7a\x0f', + b'\x76\x0e\x79\x69\xe3\x32\x67\x0f', + b'\x15\x0f\x51\x59\x56\x35\xb1\x0f', + ]) + + def test_volkswagen_mqb_crc_acc_10(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ACC_10", 0x117, [ + b'\x9b\x00\x00\x40\x68\x00\x00\xff', + b'\xff\x01\x00\x40\x68\x00\x00\xff', + b'\x53\x02\x00\x40\x68\x00\x00\xff', + b'\x37\x03\x00\x40\x68\x00\x00\xff', + b'\x24\x04\x00\x40\x68\x00\x00\xff', + b'\x40\x05\x00\x40\x68\x00\x00\xff', + b'\xec\x06\x00\x40\x68\x00\x00\xff', + b'\x88\x07\x00\x40\x68\x00\x00\xff', + b'\xca\x08\x00\x40\x68\x00\x00\xff', + b'\xae\x09\x00\x40\x68\x00\x00\xff', + b'\x02\x0a\x00\x40\x68\x00\x00\xff', + b'\x66\x0b\x00\x40\x68\x00\x00\xff', + b'\x75\x0c\x00\x40\x68\x00\x00\xff', + b'\x11\x0d\x00\x40\x68\x00\x00\xff', + b'\xbd\x0e\x00\x40\x68\x00\x00\xff', + b'\xd9\x0f\x00\x40\x68\x00\x00\xff', + ]) + + def test_volkswagen_mqb_crc_tsk_06(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "TSK_06", 0x120, [ + b'\xc1\x00\x00\x02\x00\x08\xff\x21', + b'\x34\x01\x00\x02\x00\x08\xff\x21', + b'\xcc\x02\x00\x02\x00\x08\xff\x21', + b'\x1e\x03\x00\x02\x00\x08\xff\x21', + b'\x48\x04\x00\x02\x00\x08\xff\x21', + b'\x4a\x05\x00\x02\x00\x08\xff\x21', + b'\xa5\x06\x00\x02\x00\x08\xff\x21', + b'\xa7\x07\x00\x02\x00\x08\xff\x21', + b'\xfe\x08\x00\x02\x00\x08\xff\x21', + b'\xa8\x09\x00\x02\x00\x08\xff\x21', + b'\x73\x0a\x00\x02\x00\x08\xff\x21', + b'\xdf\x0b\x00\x02\x00\x08\xff\x21', + b'\x05\x0c\x00\x02\x00\x08\xff\x21', + b'\xb5\x0d\x00\x02\x00\x08\xff\x21', + b'\xde\x0e\x00\x02\x00\x08\xff\x21', + b'\x0b\x0f\x00\x02\x00\x08\xff\x21', + ]) + + def test_volkswagen_mqb_crc_motor_20(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "Motor_20", 0x121, [ + b'\xb9\x00\x00\xc0\x39\x46\x7e\xfe', + b'\x85\x31\x20\x00\x1a\x46\x7e\xfe', + b'\xc7\x12\x00\x40\x1a\x46\x7e\xfe', + b'\x53\x93\x00\x00\x19\x46\x7e\xfe', + b'\xa4\x34\x00\x80\x1a\x46\x7e\xfe', + b'\x0e\x55\x20\x60\x18\x46\x7e\xfe', + b'\x3f\x06\x00\xc0\x37\x4c\x7e\xfe', + b'\x0c\x07\x00\x40\x39\x46\x7e\xfe', + b'\x2a\x08\x00\x00\x3a\x46\x7e\xfe', + b'\x7f\x49\x20\x80\x1a\x46\x7e\xfe', + b'\x2f\x0a\x00\xc0\x39\x46\x7e\xfe', + b'\x70\xbb\x00\x00\x17\x46\x7e\xfe', + b'\x06\x0c\x00\x00\x39\x46\x7e\xfe', + b'\x4b\x9d\x20\xe0\x16\x4c\x7e\xfe', + b'\x73\xfe\x00\x40\x16\x46\x7e\xfe', + b'\xaf\x0f\x20\x80\x39\x4c\x7e\xfe', + ]) + + def test_volkswagen_mqb_crc_acc_06(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ACC_06", 0x122, [ + b'\x14\x80\x00\xfe\x07\x00\x00\x18', + b'\x9f\x81\x00\xfe\x07\x00\x00\x18', + b'\x0a\x82\x00\xfe\x07\x00\x00\x28', + b'\x40\x83\x00\xfe\x07\x00\x00\x18', + b'\x2d\x84\x00\xfe\x07\x00\x00\x28', + b'\xdb\x85\x00\xfe\x07\x00\x00\x18', + b'\x4d\x86\x00\xfe\x07\x00\x00\x28', + b'\x35\x87\x00\xfe\x07\x00\x00\x18', + b'\x23\x88\x00\xfe\x07\x00\x00\x28', + b'\x4a\x89\x00\xfe\x07\x00\x00\x28', + b'\xe1\x8a\x00\xfe\x07\x00\x00\x28', + b'\x30\x8b\x00\xfe\x07\x00\x00\x28', + b'\x60\x8c\x00\xfe\x07\x00\x00\x28', + b'\x0d\x8d\x00\xfe\x07\x00\x00\x18', + b'\x8c\x8e\x00\xfe\x07\x00\x00\x18', + b'\x6f\x8f\x00\xfe\x07\x00\x00\x28', + ]) + + def test_volkswagen_mqb_crc_hca_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "HCA_01", 0x126, [ + b'\x00\x30\x0d\xc0\x05\xfe\x07\x00', + b'\x3e\x31\x54\xc0\x05\xfe\x07\x00', + b'\xa7\x32\xbb\x40\x05\xfe\x07\x00', + b'\x96\x33\x29\xc0\x05\xfe\x07\x00', + b'\x5f\x34\x00\x00\x03\xfe\x07\x00', + b'\x3b\x35\xae\x40\x05\xfe\x07\x00', + b'\xc7\x36\x7a\x40\x05\xfe\x07\x00', + b'\x6f\x37\x76\x40\x05\xfe\x07\x00', + b'\xb1\x38\x00\x00\x03\xfe\x07\x00', + b'\xd5\x39\x00\x00\x03\xfe\x07\x00', + b'\xba\x3a\x69\xc0\x05\xfe\x07\x00', + b'\x65\x3b\x10\x40\x05\xfe\x07\x00', + b'\x49\x3c\x72\xc0\x05\xfe\x07\x00', + b'\xc6\x3d\xdf\x40\x05\xfe\x07\x00', + b'\x1d\x3e\x2c\xc1\x05\xfe\x07\x00', + b'\x9b\x3f\x20\x40\x05\xfe\x07\x00', + ]) + + def test_volkswagen_mqb_crc_gra_acc_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "GRA_ACC_01", 0x12B, [ + b'\x86\x40\x80\x2a\x00\x00\x00\x00', + b'\xf4\x41\x80\x2a\x00\x00\x00\x00', + b'\x50\x42\x80\x2a\x00\x00\x00\x00', + b'\x08\x43\x80\x2a\x00\x00\x00\x00', + b'\x88\x44\x80\x2a\x00\x00\x00\x00', + b'\x2d\x45\x80\x2a\x00\x00\x00\x00', + b'\x34\x46\x80\x2a\x00\x00\x00\x00', + b'\x11\x47\x80\x2a\x00\x00\x00\x00', + b'\xc4\x48\x80\x2a\x00\x00\x00\x00', + b'\xcc\x49\x80\x2a\x00\x00\x00\x00', + b'\xdc\x4a\x80\x2a\x00\x00\x00\x00', + b'\x79\x4b\x80\x2a\x00\x00\x00\x00', + b'\x3c\x4c\x80\x2a\x00\x00\x00\x00', + b'\x68\x4d\x80\x2a\x00\x00\x00\x00', + b'\x27\x4e\x80\x2a\x00\x00\x00\x00', + b'\x0d\x4f\x80\x2a\x00\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_acc_07(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ACC_07", 0x12E, [ + b'\xac\xe0\x7f\x00\xfe\x00\xc0\xff', + b'\xa2\xe1\x7f\x00\xfe\x00\xc0\xff', + b'\x6b\xe2\x7f\x00\xfe\x00\xc0\xff', + b'\xf2\xe3\x7f\x00\xfe\x00\xc0\xff', + b'\xd5\xe4\x7f\x00\xfe\x00\xc0\xff', + b'\x35\xe5\x7f\x00\xfe\x00\xc0\xff', + b'\x7f\xe6\x7f\x00\xfe\x00\xc0\xff', + b'\x6c\xe7\x7f\x00\xfe\x00\xc0\xff', + b'\x05\xe8\x7f\x00\xfe\x00\xc0\xff', + b'\x79\xe9\x7f\x00\xfe\x00\xc0\xff', + b'\x25\xea\x7f\x00\xfe\x00\xc0\xff', + b'\xd1\xeb\x7f\x00\xfe\x00\xc0\xff', + b'\x72\xec\x7f\x00\xfe\x00\xc0\xff', + b'\x58\xed\x7f\x00\xfe\x00\xc0\xff', + b'\x82\xee\x7f\x00\xfe\x00\xc0\xff', + b'\x85\xef\x7f\x00\xfe\x00\xc0\xff', + ]) + + def test_volkswagen_mqb_crc_motor_ev_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "Motor_EV_01", 0x187, [ + b'\x70\x80\x15\x00\x00\x00\x00\xF0', + b'\x07\x81\x15\x00\x00\x00\x00\xF0', + b'\x7A\x82\x15\x00\x00\x00\x00\xF0', + b'\x26\x83\x15\x00\x00\x00\x00\xF0', + b'\xBE\x84\x15\x00\x00\x00\x00\xF0', + b'\x5A\x85\x15\x00\x00\x00\x00\xF0', + b'\xFC\x86\x15\x00\x00\x00\x00\xF0', + b'\x9E\x87\x15\x00\x00\x00\x00\xF0', + b'\xAF\x88\x15\x00\x00\x00\x00\xF0', + b'\x35\x89\x15\x00\x00\x00\x00\xF0', + b'\xC5\x8A\x15\x00\x00\x00\x00\xF0', + b'\x11\x8B\x15\x00\x00\x00\x00\xF0', + b'\xD0\x8C\x15\x00\x00\x00\x00\xF0', + b'\xE8\x8D\x15\x00\x00\x00\x00\xF0', + b'\xF5\x8E\x15\x00\x00\x00\x00\xF0', + b'\x00\x8F\x15\x00\x00\x00\x00\xF0', + ]) + + def test_volkswagen_mqb_crc_esp_33(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ESP_33", 0x1AB, [ + b'\x64\x00\x80\x02\x00\x00\x00\x00', + b'\x19\x01\x00\x00\x00\x00\x00\x00', + b'\xfc\x02\x00\x10\x01\x00\x00\x00', + b'\x8b\x03\x80\x02\x00\x00\x00\x00', + b'\xa4\x04\x00\x10\x01\x00\x00\x00', + b'\x97\x05\x00\x02\x00\x00\x01\x00', + b'\xd5\x06\x80\x02\x00\x00\x01\x00', + b'\xa0\x07\x80\x02\x00\x00\x01\x00', + b'\x89\x08\x00\x00\x00\x00\x00\x00', + b'\xe3\x09\x00\x00\x00\x00\x00\x00', + b'\x0e\x0a\x00\x00\x00\x00\x00\x00', + b'\x90\x0b\x00\x00\x00\x00\x00\x00', + b'\x32\x0c\x00\x10\x01\x00\x00\x00', + b'\x30\x0d\x00\x00\x00\x00\x00\x00', + b'\xc2\x0e\x00\x10\x01\x00\x00\x00', + b'\x68\x0f\x80\x02\x00\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_acc_02(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ACC_02", 0x30C, [ + b'\x82\xf0\x3f\x00\x40\x30\x00\x40', + b'\xe6\xf1\x3f\x00\x40\x30\x00\x40', + b'\x4a\xf2\x3f\x00\x40\x30\x00\x40', + b'\x2e\xf3\x3f\x00\x40\x30\x00\x40', + b'\x3d\xf4\x3f\x00\x40\x30\x00\x40', + b'\x59\xf5\x3f\x00\x40\x30\x00\x40', + b'\xf5\xf6\x3f\x00\x40\x30\x00\x40', + b'\x91\xf7\x3f\x00\x40\x30\x00\x40', + b'\xd3\xf8\x3f\x00\x40\x30\x00\x40', + b'\xb7\xf9\x3f\x00\x40\x30\x00\x40', + b'\x1b\xfa\x3f\x00\x40\x30\x00\x40', + b'\x7f\xfb\x3f\x00\x40\x30\x00\x40', + b'\x6c\xfc\x3f\x00\x40\x30\x00\x40', + b'\x08\xfd\x3f\x00\x40\x30\x00\x40', + b'\xa4\xfe\x3f\x00\x40\x30\x00\x40', + b'\xc0\xff\x3f\x00\x40\x30\x00\x40', + ]) + + def test_volkswagen_mqb_crc_swa_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "SWA_01", 0x30F, [ + b'\x10\x00\x10\x00\x00\x00\x00\x00', + b'\x74\x01\x10\x00\x00\x00\x00\x00', + b'\xD8\x02\x10\x00\x00\x00\x00\x00', + b'\xBC\x03\x10\x00\x00\x00\x00\x00', + b'\xAF\x04\x10\x00\x00\x00\x00\x00', + b'\xCB\x05\x10\x00\x00\x00\x00\x00', + b'\x67\x06\x10\x00\x00\x00\x00\x00', + b'\x03\x07\x10\x00\x00\x00\x00\x00', + b'\x41\x08\x10\x00\x00\x00\x00\x00', + b'\x25\x09\x10\x00\x00\x00\x00\x00', + b'\x89\x0A\x10\x00\x00\x00\x00\x00', + b'\xED\x0B\x10\x00\x00\x00\x00\x00', + b'\xFE\x0C\x10\x00\x00\x00\x00\x00', + b'\x9A\x0D\x10\x00\x00\x00\x00\x00', + b'\x36\x0E\x10\x00\x00\x00\x00\x00', + b'\x52\x0F\x10\x00\x00\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_acc_04(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ACC_04", 0x324, [ + b'\xba\x00\x00\x00\x00\x00\x00\x10', + b'\xde\x01\x00\x00\x00\x00\x00\x10', + b'\x72\x02\x00\x00\x00\x00\x00\x10', + b'\x16\x03\x00\x00\x00\x00\x00\x10', + b'\x05\x04\x00\x00\x00\x00\x00\x10', + b'\x44\x05\x00\x00\x00\x00\x00\x00', + b'\xe8\x06\x00\x00\x00\x00\x00\x00', + b'\xa9\x07\x00\x00\x00\x00\x00\x10', + b'\xeb\x08\x00\x00\x00\x00\x00\x10', + b'\x8f\x09\x00\x00\x00\x00\x00\x10', + b'\x06\x0a\x00\x00\x00\x00\x00\x00', + b'\x47\x0b\x00\x00\x00\x00\x00\x10', + b'\x71\x0c\x00\x00\x00\x00\x00\x00', + b'\x15\x0d\x00\x00\x00\x00\x00\x00', + b'\xb9\x0e\x00\x00\x00\x00\x00\x00', + b'\xdd\x0f\x00\x00\x00\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_klemmen_status_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "Klemmen_Status_01", 0x3C0, [ + b'\x74\x00\x03\x00', + b'\xc1\x01\x03\x00', + b'\x31\x02\x03\x00', + b'\x84\x03\x03\x00', + b'\xfe\x04\x03\x00', + b'\x4b\x05\x03\x00', + b'\xbb\x06\x03\x00', + b'\x0e\x07\x03\x00', + b'\x4f\x08\x03\x00', + b'\xfa\x09\x03\x00', + b'\x0a\x0a\x03\x00', + b'\xbf\x0b\x03\x00', + b'\xc5\x0c\x03\x00', + b'\x70\x0d\x03\x00', + b'\x80\x0e\x03\x00', + b'\x35\x0f\x03\x00', + ]) + + def test_volkswagen_mqb_crc_licht_anf_01(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "Licht_Anf_01", 0x3D5, [ + b'\xc8\x00\x00\x04\x00\x00\x00\x00', + b'\x9f\x01\x00\x04\x00\x00\x00\x00', + b'\x5e\x02\x00\x04\x00\x00\x00\x00', + b'\x52\x03\x00\x04\x00\x00\x00\x00', + b'\xf2\x04\x00\x04\x00\x00\x00\x00', + b'\x79\x05\x00\x04\x00\x00\x00\x00', + b'\xe6\x06\x00\x04\x00\x00\x00\x00', + b'\xfd\x07\x00\x04\x00\x00\x00\x00', + b'\xf8\x08\x00\x04\x00\x00\x00\x00', + b'\xc6\x09\x00\x04\x00\x00\x00\x00', + b'\xf5\x0a\x00\x04\x00\x00\x00\x00', + b'\x1a\x0b\x00\x04\x00\x00\x00\x00', + b'\x65\x0c\x00\x04\x00\x00\x00\x00', + b'\x41\x0d\x00\x04\x00\x00\x00\x00', + b'\x7f\x0e\x00\x04\x00\x00\x00\x00', + b'\x98\x0f\x00\x04\x00\x00\x00\x00', + ]) + + def test_volkswagen_mqb_crc_esp_20(self, subtests): + self.verify_volkswagen_mqb_crc(subtests, "ESP_20", 0x65D, [ + b'\x98\x30\x2b\x10\x00\x00\x22\x81', + b'\xc8\x31\x2b\x10\x00\x00\x22\x81', + b'\x9d\x32\x2b\x10\x00\x00\x22\x81', + b'\x1f\x33\x2b\x10\x00\x00\x22\x81', + b'\x6e\x34\x2b\x10\x00\x00\x22\x81', + b'\x61\x35\x2b\x10\x00\x00\x22\x81', + b'\x6f\x36\x2b\x10\x00\x00\x22\x81', + b'\xe5\x37\x2b\x10\x00\x00\x22\x81', + b'\xf8\x38\x2b\x10\x00\x00\x22\x81', + b'\xe1\x39\x2b\x10\x00\x00\x22\x81', + b'\xaa\x3a\x2b\x10\x00\x00\x22\x81', + b'\xe6\x3b\x2b\x10\x00\x00\x22\x81', + b'\xef\x3c\x2b\x10\x00\x00\x22\x81', + b'\xbb\x3d\x2b\x10\x00\x00\x22\x81', + b'\x9b\x3e\x2b\x10\x00\x00\x22\x81', + b'\x72\x3f\x2b\x10\x00\x00\x22\x81', + ]) diff --git a/opendbc_repo/opendbc/can/tests/test_dbc_exceptions.py b/opendbc_repo/opendbc/can/tests/test_dbc_exceptions.py new file mode 100644 index 0000000000..858a643720 --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/test_dbc_exceptions.py @@ -0,0 +1,29 @@ +import pytest + +from opendbc.can import CANDefine, CANPacker, CANParser +from opendbc.can.tests import TEST_DBC + + +class TestCanParserPackerExceptions: + def test_civic_exceptions(self): + dbc_file = "honda_civic_touring_2016_can_generated" + dbc_invalid = dbc_file + "abcdef" + msgs = [("STEERING_CONTROL", 50)] + with pytest.raises(FileNotFoundError): + CANParser(dbc_invalid, msgs, 0) + with pytest.raises(FileNotFoundError): + CANPacker(dbc_invalid) + with pytest.raises(FileNotFoundError): + CANDefine(dbc_invalid) + with pytest.raises(KeyError): + CANDefine(TEST_DBC) + + parser = CANParser(dbc_file, msgs, 0) + with pytest.raises(IndexError): + parser.update([b'']) + + # Everything is supposed to work below + CANParser(dbc_file, msgs, 0) + CANParser(dbc_file, [], 0) + CANPacker(dbc_file) + CANDefine(dbc_file) diff --git a/opendbc_repo/opendbc/can/tests/test_dbc_parser.py b/opendbc_repo/opendbc/can/tests/test_dbc_parser.py new file mode 100644 index 0000000000..508b80b95e --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/test_dbc_parser.py @@ -0,0 +1,21 @@ +from opendbc.can import CANParser +from opendbc.can.tests import ALL_DBCS + + +class TestDBCParser: + def test_enough_dbcs(self): + # sanity check that we're running on the real DBCs + assert len(ALL_DBCS) > 20 + + def test_parse_all_dbcs(self, subtests): + """ + Dynamic DBC parser checks: + - Checksum and counter length, start bit, endianness + - Duplicate message addresses and names + - Signal out of bounds + - All BO_, SG_, VAL_ lines for syntax errors + """ + + for dbc in ALL_DBCS: + with subtests.test(dbc=dbc): + CANParser(dbc, [], 0) diff --git a/opendbc_repo/opendbc/can/tests/test_define.py b/opendbc_repo/opendbc/can/tests/test_define.py new file mode 100644 index 0000000000..41cfa7899b --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/test_define.py @@ -0,0 +1,27 @@ +from opendbc.can import CANDefine +from opendbc.can.tests import ALL_DBCS + + +class TestCANDefine: + def test_civic(self): + + dbc_file = "honda_civic_touring_2016_can_generated" + defs = CANDefine(dbc_file) + + assert defs.dv[399] == defs.dv['STEER_STATUS'] + assert defs.dv[399] == {'STEER_STATUS': + {7: 'PERMANENT_FAULT', + 6: 'TMP_FAULT', + 5: 'FAULT_1', + 4: 'NO_TORQUE_ALERT_2', + 3: 'LOW_SPEED_LOCKOUT', + 2: 'NO_TORQUE_ALERT_1', + 1: 'DRIVER_STEERING', + 0: 'NORMAL'} + } + + def test_all_dbcs(self, subtests): + # Asserts no exceptions on all DBCs + for dbc in ALL_DBCS: + with subtests.test(dbc=dbc): + CANDefine(dbc) diff --git a/opendbc_repo/opendbc/can/tests/test_packer_parser.py b/opendbc_repo/opendbc/can/tests/test_packer_parser.py new file mode 100644 index 0000000000..51aa527f55 --- /dev/null +++ b/opendbc_repo/opendbc/can/tests/test_packer_parser.py @@ -0,0 +1,368 @@ +import pytest +import random + +from opendbc.can import CANPacker, CANParser +from opendbc.can.tests import TEST_DBC + +MAX_BAD_COUNTER = 5 + + +class TestCanParserPacker: + def test_packer(self): + packer = CANPacker(TEST_DBC) + + for b in range(6): + for i in range(256): + values = {"COUNTER": i} + addr, dat, bus = packer.make_can_msg("CAN_FD_MESSAGE", b, values) + assert addr == 245 + assert bus == b + assert dat[0] == i + + def test_packer_counter(self): + msgs = [("CAN_FD_MESSAGE", 0), ] + packer = CANPacker(TEST_DBC) + parser = CANParser(TEST_DBC, msgs, 0) + + # packer should increment the counter + for i in range(1000): + msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {}) + parser.update([0, [msg]]) + assert parser.vl["CAN_FD_MESSAGE"]["COUNTER"] == (i % 256) + + # setting COUNTER should override + for _ in range(100): + cnt = random.randint(0, 255) + msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, { + "COUNTER": cnt, + "SIGNED": 0 + }) + parser.update([0, [msg]]) + assert parser.vl["CAN_FD_MESSAGE"]["COUNTER"] == cnt + + # then, should resume counting from the override value + cnt = parser.vl["CAN_FD_MESSAGE"]["COUNTER"] + for i in range(100): + msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {}) + parser.update([0, [msg]]) + assert parser.vl["CAN_FD_MESSAGE"]["COUNTER"] == ((cnt + i) % 256) + + def test_parser_can_valid(self): + msgs = [("CAN_FD_MESSAGE", 10), ] + packer = CANPacker(TEST_DBC) + parser = CANParser(TEST_DBC, msgs, 0) + + # shouldn't be valid initially + assert not parser.can_valid + + # not valid until the message is seen + for _ in range(100): + parser.update([0, []]) + assert not parser.can_valid + + # valid once seen + for i in range(1, 100): + t = int(0.01 * i * 1e9) + msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {}) + parser.update([t, [msg]]) + assert parser.can_valid + + def test_parser_updated_list(self): + msgs = [("CAN_FD_MESSAGE", 10), ] + parser = CANParser(TEST_DBC, msgs, 0) + packer = CANPacker(TEST_DBC) + + msg = packer.make_can_msg("CAN_FD_MESSAGE", 0, {}) + ret = parser.update([0, [msg]]) + assert ret == {245} + + ret = parser.update([]) + assert len(ret) == 0 + + def test_parser_counter_can_valid(self): + """ + Tests number of allowed bad counters + ensures CAN stays invalid + while receiving invalid messages + that we can recover + """ + msgs = [ + ("STEERING_CONTROL", 0), + ] + packer = CANPacker("honda_civic_touring_2016_can_generated") + parser = CANParser("honda_civic_touring_2016_can_generated", msgs, 0) + + msg = packer.make_can_msg("STEERING_CONTROL", 0, {"COUNTER": 0}) + + # bad static counter, invalid once it's seen MAX_BAD_COUNTER messages + for idx in range(0x1000): + parser.update([0, [msg]]) + assert ((idx + 1) < MAX_BAD_COUNTER) == parser.can_valid + + # one to recover + msg = packer.make_can_msg("STEERING_CONTROL", 0, {"COUNTER": 1}) + parser.update([0, [msg]]) + assert parser.can_valid + + def test_parser_no_partial_update(self): + """ + Ensure that the CANParser doesn't partially update messages with invalid signals (COUNTER/CHECKSUM). + Previously, the signal update loop would only break once it got to one of these invalid signals, + after already updating most/all of the signals. + """ + msgs = [ + ("STEERING_CONTROL", 0), + ] + packer = CANPacker("honda_civic_touring_2016_can_generated") + parser = CANParser("honda_civic_touring_2016_can_generated", msgs, 0) + + def rx_steering_msg(values, bad_checksum=False): + msg = packer.make_can_msg("STEERING_CONTROL", 0, values) + if bad_checksum: + # add 1 to checksum + dat = bytearray(msg[1]) + dat[4] = (dat[4] & 0xF0) | ((dat[4] & 0x0F) + 1) + msg = (msg[0], bytes(dat), msg[2]) + + parser.update([0, [msg]]) + + rx_steering_msg({"STEER_TORQUE": 100}, bad_checksum=False) + assert parser.vl["STEERING_CONTROL"]["STEER_TORQUE"] == 100 + assert parser.vl_all["STEERING_CONTROL"]["STEER_TORQUE"] == [100] + + for _ in range(5): + rx_steering_msg({"STEER_TORQUE": 200}, bad_checksum=True) + assert parser.vl["STEERING_CONTROL"]["STEER_TORQUE"] == 100 + assert parser.vl_all["STEERING_CONTROL"]["STEER_TORQUE"] == [] + + # Even if CANParser doesn't update instantaneous vl, make sure it didn't add invalid values to vl_all + rx_steering_msg({"STEER_TORQUE": 300}, bad_checksum=False) + assert parser.vl["STEERING_CONTROL"]["STEER_TORQUE"] == 300 + assert parser.vl_all["STEERING_CONTROL"]["STEER_TORQUE"] == [300] + + def test_packer_parser(self): + msgs = [ + ("Brake_Status", 0), + ("CAN_FD_MESSAGE", 0), + ("STEERING_CONTROL", 0), + ] + packer = CANPacker(TEST_DBC) + parser = CANParser(TEST_DBC, msgs, 0) + + for steer in range(-256, 255): + for active in (1, 0): + values = { + "STEERING_CONTROL": { + "STEER_TORQUE": steer, + "STEER_TORQUE_REQUEST": active, + }, + "Brake_Status": { + "Signal1": 61042322657536.0, + }, + "CAN_FD_MESSAGE": { + "SIGNED": steer, + "64_BIT_LE": random.randint(0, 100), + "64_BIT_BE": random.randint(0, 100), + }, + } + + msgs = [packer.make_can_msg(k, 0, v) for k, v in values.items()] + parser.update([0, msgs]) + + for k, v in values.items(): + for key, val in v.items(): + assert parser.vl[k][key] == pytest.approx(val) + + # also check address + for sig in ("STEER_TORQUE", "STEER_TORQUE_REQUEST", "COUNTER", "CHECKSUM"): + assert parser.vl["STEERING_CONTROL"][sig] == parser.vl[228][sig] + + def test_scale_offset(self): + """Test that both scale and offset are correctly preserved""" + dbc_file = "honda_civic_touring_2016_can_generated" + msgs = [("VSA_STATUS", 50)] + parser = CANParser(dbc_file, msgs, 0) + packer = CANPacker(dbc_file) + + for brake in range(100): + values = {"USER_BRAKE": brake} + msgs = packer.make_can_msg("VSA_STATUS", 0, values) + parser.update([0, [msgs]]) + + assert parser.vl["VSA_STATUS"]["USER_BRAKE"] == pytest.approx(brake) + + def test_subaru(self): + # Subaru is little endian + + dbc_file = "subaru_global_2017_generated" + + msgs = [("ES_LKAS", 50)] + + parser = CANParser(dbc_file, msgs, 0) + packer = CANPacker(dbc_file) + + idx = 0 + for steer in range(-256, 255): + for active in [1, 0]: + values = { + "LKAS_Output": steer, + "LKAS_Request": active, + "SET_1": 1 + } + + msgs = packer.make_can_msg("ES_LKAS", 0, values) + parser.update([0, [msgs]]) + + assert parser.vl["ES_LKAS"]["LKAS_Output"] == pytest.approx(steer) + assert parser.vl["ES_LKAS"]["LKAS_Request"] == pytest.approx(active) + assert parser.vl["ES_LKAS"]["SET_1"] == pytest.approx(1) + assert parser.vl["ES_LKAS"]["COUNTER"] == pytest.approx(idx % 16) + idx += 1 + + def test_bus_timeout(self): + """Test CAN bus timeout detection""" + dbc_file = "honda_civic_touring_2016_can_generated" + + freq = 100 + msgs = [("VSA_STATUS", freq), ("STEER_MOTOR_TORQUE", freq/2)] + + parser = CANParser(dbc_file, msgs, 0) + packer = CANPacker(dbc_file) + + i = 0 + + def send_msg(blank=False): + nonlocal i + i += 1 + t = i*((1 / freq) * 1e9) + + if blank: + msgs = [] + else: + msgs = [packer.make_can_msg("VSA_STATUS", 0, {}), ] + + parser.update([t, msgs]) + + # all good, no timeout + for _ in range(1000): + send_msg() + assert not parser.bus_timeout, str(_) + + # timeout after 10 blank msgs + for n in range(200): + send_msg(blank=True) + assert (n >= 10) == parser.bus_timeout + + # no timeout immediately after seen again + send_msg() + assert not parser.bus_timeout + + def test_updated(self): + """Test updated value dict""" + dbc_file = "honda_civic_touring_2016_can_generated" + msgs = [("VSA_STATUS", 50)] + parser = CANParser(dbc_file, msgs, 0) + packer = CANPacker(dbc_file) + + # Make sure nothing is updated + assert len(parser.vl_all["VSA_STATUS"]["USER_BRAKE"]) == 0 + + idx = 0 + for _ in range(10): + # Ensure CANParser holds the values of any duplicate messages over multiple frames + user_brake_vals = [random.randrange(100) for _ in range(random.randrange(5, 10))] + half_idx = len(user_brake_vals) // 2 + can_msgs = [[], []] + for frame, brake_vals in enumerate((user_brake_vals[:half_idx], user_brake_vals[half_idx:])): + for user_brake in brake_vals: + values = {"USER_BRAKE": user_brake} + can_msgs[frame].append(packer.make_can_msg("VSA_STATUS", 0, values)) + idx += 1 + + parser.update([[0, m] for m in can_msgs]) + vl_all = parser.vl_all["VSA_STATUS"]["USER_BRAKE"] + + assert vl_all == user_brake_vals + if len(user_brake_vals): + assert vl_all[-1] == parser.vl["VSA_STATUS"]["USER_BRAKE"] + + def test_timestamp_nanos(self): + """Test message timestamp dict""" + dbc_file = "honda_civic_touring_2016_can_generated" + + msgs = [ + ("VSA_STATUS", 50), + ("POWERTRAIN_DATA", 100), + ] + + parser = CANParser(dbc_file, msgs, 0) + packer = CANPacker(dbc_file) + + # Check the default timestamp is zero + for msg in ("VSA_STATUS", "POWERTRAIN_DATA"): + ts_nanos = parser.ts_nanos[msg].values() + assert set(ts_nanos) == {0} + + # Check: + # - timestamp is only updated for correct messages + # - timestamp is correct for multiple runs + # - timestamp is from the latest message if updating multiple strings + for _ in range(10): + can_strings = [] + log_mono_time = 0 + for i in range(10): + log_mono_time = int(0.01 * i * 1e+9) + can_msg = packer.make_can_msg("VSA_STATUS", 0, {}) + can_strings.append((log_mono_time, [can_msg])) + parser.update(can_strings) + + ts_nanos = parser.ts_nanos["VSA_STATUS"].values() + assert set(ts_nanos) == {log_mono_time} + ts_nanos = parser.ts_nanos["POWERTRAIN_DATA"].values() + assert set(ts_nanos) == {0} + + def test_nonexistent_messages(self): + # Ensure we don't allow messages not in the DBC + existing_messages = ("STEERING_CONTROL", 228, "CAN_FD_MESSAGE", 245) + + for msg in existing_messages: + CANParser(TEST_DBC, [(msg, 0)], 0) + with pytest.raises(RuntimeError): + new_msg = msg + "1" if isinstance(msg, str) else msg + 1 + CANParser(TEST_DBC, [(new_msg, 0)], 0) + + def test_track_all_signals(self): + parser = CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 0)], 0) + assert parser.vl["ACC_CONTROL"] == { + "ACCEL_CMD": 0, + "ALLOW_LONG_PRESS": 0, + "ACC_MALFUNCTION": 0, + "RADAR_DIRTY": 0, + "DISTANCE": 0, + "MINI_CAR": 0, + "ACC_TYPE": 0, + "CANCEL_REQ": 0, + "ACC_CUT_IN": 0, + "LEAD_VEHICLE_STOPPED": 0, + "PERMIT_BRAKING": 0, + "RELEASE_STANDSTILL": 0, + "ITS_CONNECT_LEAD": 0, + "ACCEL_CMD_ALT": 0, + "CHECKSUM": 0, + } + + def test_disallow_duplicate_messages(self): + CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 5)], 0) + + with pytest.raises(RuntimeError): + CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 5), ("ACC_CONTROL", 10)], 0) + + with pytest.raises(RuntimeError): + CANParser("toyota_nodsu_pt_generated", [("ACC_CONTROL", 10), ("ACC_CONTROL", 10)], 0) + + def test_allow_undefined_msgs(self): + # TODO: we should throw an exception for these, but we need good + # discovery tests in openpilot first + packer = CANPacker("toyota_nodsu_pt_generated") + + assert packer.make_can_msg("ACC_CONTROL", 0, {"UNKNOWN_SIGNAL": 0}) == (835, b'\x00\x00\x00\x00\x00\x00\x00N', 0) + assert packer.make_can_msg("UNKNOWN_MESSAGE", 0, {"UNKNOWN_SIGNAL": 0}) == (0, b'', 0) + assert packer.make_can_msg(0, 0, {"UNKNOWN_SIGNAL": 0}) == (0, b'', 0) diff --git a/opendbc_repo/opendbc/car/CARS_template.md b/opendbc_repo/opendbc/car/CARS_template.md new file mode 100644 index 0000000000..9d71ad0a8b --- /dev/null +++ b/opendbc_repo/opendbc/car/CARS_template.md @@ -0,0 +1,67 @@ + + +# Support Information for {{all_car_docs | length}} Known Cars + +|{{ExtraCarsColumn | map(attribute='value') | join('|') | replace(hardware_col_name, wide_hardware_col_name)}}| +|---|---|---|{% for _ in range((ExtraCarsColumn | length) - 3) %}{{':---:|'}}{% endfor +%} +{% for car_docs in all_car_docs %} +|{% for column in ExtraCarsColumn %}{{car_docs.get_extra_cars_column(column)}}|{% endfor %} + +{% endfor %} + +# Types of Support + +**opendbc can support many more cars than it currently does.** There are a few reasons your car may not be supported. +If your car doesn't fit into any of the incompatibility criteria here, then there's a good chance it can be supported! +We're adding support for new cars all the time. **We don't have a roadmap for car support**, and in fact, most car +support comes from users like you! + +## Upstream + +A supported vehicle is one that just works when you install a comma device. All supported cars provide a better +experience than any stock system. Supported vehicles reference the US market unless otherwise specified. + +## Under Review + +A vehicle under review is one for which software support has been merged into upstream openpilot, but hasn't yet been +tested for drive quality and conformance with [comma safety guidelines](https://github.com/commaai/openpilot/blob/master/docs/SAFETY.md). +This is a normal part of the development and quality assurance process. This vehicle will not work when upstream +openpilot is installed, but custom forks may allow their use. + +## Custom + +Vehicles in this category are not considered plug-and-play. Software support is included in upstream openpilot, but +these vehicles might not have a harness in the comma store, or the physical install might be at an unusual or cumbersome +location, or they might need unusual configuration after install. + +## Dashcam + +Dashcam vehicles have software support in upstream openpilot, but will go into "dashcam mode" at startup and will not +engage. This may be due to known issues with driving safety or quality, or it may be a work in progress that isn't yet +ready for safety and quality review. + +## Community + +Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community +Supported Models' section of each make [on our wiki](https://wiki.comma.ai/). + +Some notable works-in-progress: +* Honda + * 2022-24 Acura RDX, commaai/opendbc#1967 + * Camera ACC stability improvements, commaai/opendbc#2192 + * Alpha longitudinal stability improvements, commaai/opendbc#2347 and commaai/opendbc#2165 + +## Incompatible + +### CAN Bus Security + +Vehicles with CAN security measures, such as AUTOSAR Secure Onboard Communication (SecOC) are not usable with openpilot +unless the owner can recover the message signing key and implement CAN message signing. Examples include certain newer +Toyota, and the GM Global B platform. + +### FlexRay + +All the cars that openpilot supports use a [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) for communication between all the car's computers, however a +CAN bus isn't the only way that the computers in your car can communicate. Most, if not all, vehicles from the following +manufacturers use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) instead of a CAN bus: **BMW, Mercedes, Audi, Land Rover, and some Volvo**. These cars +may one day be supported, but we have no immediate plans to support FlexRay. diff --git a/opendbc_repo/opendbc/car/__init__.py b/opendbc_repo/opendbc/car/__init__.py new file mode 100644 index 0000000000..79fb455375 --- /dev/null +++ b/opendbc_repo/opendbc/car/__init__.py @@ -0,0 +1,242 @@ +# functions common among cars +import numpy as np +from dataclasses import dataclass, field +from enum import IntFlag, ReprEnum, StrEnum, EnumType, auto +from dataclasses import replace + +from opendbc.car import structs, uds +from opendbc.car.can_definitions import CanData +from opendbc.car.docs_definitions import CarDocs, ExtraCarDocs + +DT_CTRL = 0.01 # car state and control loop timestep (s) + +# kg of standard extra cargo to count for drive, gas, etc... +STD_CARGO_KG = 136. + +ACCELERATION_DUE_TO_GRAVITY = 9.81 # m/s^2 + +ButtonType = structs.CarState.ButtonEvent.Type + + +def apply_hysteresis(val: float, val_steady: float, hyst_gap: float) -> float: + if val > val_steady + hyst_gap: + val_steady = val - hyst_gap + elif val < val_steady - hyst_gap: + val_steady = val + hyst_gap + return val_steady + + +def create_button_events(cur_btn: int, prev_btn: int, buttons_dict: dict[int, structs.CarState.ButtonEvent.Type], + unpressed_btn: int = 0) -> list[structs.CarState.ButtonEvent]: + events: list[structs.CarState.ButtonEvent] = [] + + if cur_btn == prev_btn: + return events + + # Add events for button presses, multiple when a button switches without going to unpressed + for pressed, btn in ((False, prev_btn), (True, cur_btn)): + if btn != unpressed_btn: + events.append(structs.CarState.ButtonEvent(pressed=pressed, + type=buttons_dict.get(btn, ButtonType.unknown))) + return events + + +def gen_empty_fingerprint(): + return {i: {} for i in range(8)} + + +# these params were derived for the Civic and used to calculate params for other cars +class VehicleDynamicsParams: + MASS = 1326. + STD_CARGO_KG + WHEELBASE = 2.70 + CENTER_TO_FRONT = WHEELBASE * 0.4 + CENTER_TO_REAR = WHEELBASE - CENTER_TO_FRONT + ROTATIONAL_INERTIA = 2500 + TIRE_STIFFNESS_FRONT = 192150 + TIRE_STIFFNESS_REAR = 202500 + + +# TODO: get actual value, for now starting with reasonable value for +# civic and scaling by mass and wheelbase +def scale_rot_inertia(mass, wheelbase): + return VehicleDynamicsParams.ROTATIONAL_INERTIA * mass * wheelbase ** 2 / (VehicleDynamicsParams.MASS * VehicleDynamicsParams.WHEELBASE ** 2) + + +# TODO: start from empirically derived lateral slip stiffness for the civic and scale by +# mass and CG position, so all cars will have approximately similar dyn behaviors +def scale_tire_stiffness(mass, wheelbase, center_to_front, tire_stiffness_factor): + center_to_rear = wheelbase - center_to_front + tire_stiffness_front = (VehicleDynamicsParams.TIRE_STIFFNESS_FRONT * tire_stiffness_factor) * mass / VehicleDynamicsParams.MASS * \ + (center_to_rear / wheelbase) / (VehicleDynamicsParams.CENTER_TO_REAR / VehicleDynamicsParams.WHEELBASE) + + tire_stiffness_rear = (VehicleDynamicsParams.TIRE_STIFFNESS_REAR * tire_stiffness_factor) * mass / VehicleDynamicsParams.MASS * \ + (center_to_front / wheelbase) / (VehicleDynamicsParams.CENTER_TO_FRONT / VehicleDynamicsParams.WHEELBASE) + + return tire_stiffness_front, tire_stiffness_rear + + +DbcDict = dict[StrEnum, str] + + +class Bus(StrEnum): + pt = auto() + cam = auto() + radar = auto() + adas = auto() + alt = auto() + body = auto() + chassis = auto() + loopback = auto() + main = auto() + party = auto() + ap_party = auto() + + +def rate_limit(new_value, last_value, dw_step, up_step): + return float(np.clip(new_value, last_value + dw_step, last_value + up_step)) + + +def make_tester_present_msg(addr, bus, subaddr=None, suppress_response=False): + dat = [0x02, uds.SERVICE_TYPE.TESTER_PRESENT] + if subaddr is not None: + dat.insert(0, subaddr) + dat.append(0x80 if suppress_response else 0x0) # sub-function + + dat.extend([0x0] * (8 - len(dat))) + return CanData(addr, bytes(dat), bus) + + +def get_safety_config(safety_model: structs.CarParams.SafetyModel, safety_param: int = None) -> structs.CarParams.SafetyConfig: + ret = structs.CarParams.SafetyConfig() + ret.safetyModel = safety_model + if safety_param is not None: + ret.safetyParam = safety_param + return ret + + +class CanBusBase: + offset: int + + def __init__(self, CP, fingerprint: dict[int, dict[int, int]] | None) -> None: + if CP is None: + assert fingerprint is not None + num = max([k for k, v in fingerprint.items() if len(v)], default=0) // 4 + 1 + else: + num = len(CP.safetyConfigs) + self.offset = 4 * (num - 1) + + +class CanSignalRateCalculator: + """ + Calculates the instantaneous rate of a CAN signal by using the counter + variable and the known frequency of the CAN message that contains it. + """ + def __init__(self, frequency): + self.frequency = frequency + self.previous_counter = 0 + self.previous_value = 0 + self.rate = 0 + + def update(self, current_value, current_counter): + if current_counter != self.previous_counter: + self.rate = (current_value - self.previous_value) * self.frequency + + self.previous_counter = current_counter + self.previous_value = current_value + + return self.rate + + +@dataclass(frozen=True, kw_only=True) +class CarSpecs: + mass: float # kg, curb weight + wheelbase: float # meters + steerRatio: float + centerToFrontRatio: float = 0.5 + minSteerSpeed: float = 0.0 # m/s + minEnableSpeed: float = -1.0 # m/s + tireStiffnessFactor: float = 1.0 + + def override(self, **kwargs): + return replace(self, **kwargs) + + +class Freezable: + _frozen: bool = False + + def freeze(self): + if not self._frozen: + self._frozen = True + + def __setattr__(self, *args, **kwargs): + if self._frozen: + raise Exception("cannot modify frozen object") + super().__setattr__(*args, **kwargs) + + +@dataclass(order=True) +class PlatformConfigBase(Freezable): + car_docs: list[CarDocs] | list[ExtraCarDocs] + specs: CarSpecs + + dbc_dict: DbcDict + + flags: int = 0 + + platform_str: str | None = None + + def __hash__(self) -> int: + return hash(self.platform_str) + + def override(self, **kwargs): + return replace(self, **kwargs) + + def init(self): + pass + + def __post_init__(self): + self.init() + + +@dataclass(order=True) +class PlatformConfig(PlatformConfigBase): + car_docs: list[CarDocs] + specs: CarSpecs + dbc_dict: DbcDict + + +@dataclass(order=True) +class ExtraPlatformConfig(PlatformConfigBase): + car_docs: list[ExtraCarDocs] + specs: CarSpecs = CarSpecs(mass=0., wheelbase=0., steerRatio=0.) + dbc_dict: DbcDict = field(default_factory=lambda: dict()) + + +class PlatformsType(EnumType): + def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **kwds): + for key in classdict._member_names.keys(): + cfg: PlatformConfig = classdict[key] + cfg.platform_str = key + cfg.freeze() + return super().__new__(metacls, cls, bases, classdict, boundary=boundary, _simple=_simple, **kwds) + + +class Platforms(str, ReprEnum, metaclass=PlatformsType): + config: PlatformConfigBase + + def __new__(cls, platform_config: PlatformConfig): + member = str.__new__(cls, platform_config.platform_str) + member.config = platform_config + member._value_ = platform_config.platform_str + return member + + def __repr__(self): + return f"<{self.__class__.__name__}.{self.name}>" + + @classmethod + def create_dbc_map(cls) -> dict[str, DbcDict]: + return {p: p.config.dbc_dict for p in cls} + + @classmethod + def with_flags(cls, flags: IntFlag) -> set['Platforms']: + return {p for p in cls if p.config.flags & flags} diff --git a/opendbc_repo/opendbc/car/body/__init__.py b/opendbc_repo/opendbc/car/body/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/body/bodycan.py b/opendbc_repo/opendbc/car/body/bodycan.py new file mode 100644 index 0000000000..201bfe718f --- /dev/null +++ b/opendbc_repo/opendbc/car/body/bodycan.py @@ -0,0 +1,20 @@ +def create_control(packer, torque_l, torque_r): + values = { + "TORQUE_L": torque_l, + "TORQUE_R": torque_r, + } + + return packer.make_can_msg("TORQUE_CMD", 0, values) + + +def body_checksum(address: int, sig, d: bytearray) -> int: + crc = 0xFF + poly = 0xD5 + for i in range(len(d) - 2, -1, -1): + crc ^= d[i] + for _ in range(8): + if crc & 0x80: + crc = ((crc << 1) ^ poly) & 0xFF + else: + crc = (crc << 1) & 0xFF + return crc diff --git a/opendbc_repo/opendbc/car/body/carcontroller.py b/opendbc_repo/opendbc/car/body/carcontroller.py new file mode 100644 index 0000000000..3739af24f2 --- /dev/null +++ b/opendbc_repo/opendbc/car/body/carcontroller.py @@ -0,0 +1,82 @@ +import numpy as np + +from opendbc.can import CANPacker +from opendbc.car import Bus, DT_CTRL +from opendbc.car.common.pid import PIDController +from opendbc.car.body import bodycan +from opendbc.car.body.values import SPEED_FROM_RPM +from opendbc.car.interfaces import CarControllerBase + +MAX_TORQUE = 500 +MAX_TORQUE_RATE = 50 +MAX_ANGLE_ERROR = np.radians(7) +MAX_POS_INTEGRATOR = 0.2 # meters +MAX_TURN_INTEGRATOR = 0.1 # meters + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.packer = CANPacker(dbc_names[Bus.main]) + + # PIDs + self.turn_pid = PIDController(110, k_i=11.5, rate=1 / DT_CTRL) + self.wheeled_speed_pid = PIDController(110, k_i=11.5, rate=1 / DT_CTRL) + + self.torque_r_filtered = 0. + self.torque_l_filtered = 0. + + @staticmethod + def deadband_filter(torque, deadband): + if torque > 0: + torque += deadband + else: + torque -= deadband + return torque + + def update(self, CC, CS, now_nanos): + + torque_l = 0 + torque_r = 0 + + if CC.enabled: + # Read these from the joystick + # TODO: this isn't acceleration, okay? + speed_desired = CC.actuators.accel / 5. + speed_diff_desired = -CC.actuators.torque / 2. + + speed_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr) / 2. + speed_error = speed_desired - speed_measured + + torque = self.wheeled_speed_pid.update(speed_error, freeze_integrator=False) + + speed_diff_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl - CS.out.wheelSpeeds.fr) + turn_error = speed_diff_measured - speed_diff_desired + freeze_integrator = ((turn_error < 0 and self.turn_pid.error_integral <= -MAX_TURN_INTEGRATOR) or + (turn_error > 0 and self.turn_pid.error_integral >= MAX_TURN_INTEGRATOR)) + torque_diff = self.turn_pid.update(turn_error, freeze_integrator=freeze_integrator) + + # Combine 2 PIDs outputs + torque_r = torque + torque_diff + torque_l = torque - torque_diff + + # Torque rate limits + self.torque_r_filtered = np.clip(self.deadband_filter(torque_r, 10), + self.torque_r_filtered - MAX_TORQUE_RATE, + self.torque_r_filtered + MAX_TORQUE_RATE) + self.torque_l_filtered = np.clip(self.deadband_filter(torque_l, 10), + self.torque_l_filtered - MAX_TORQUE_RATE, + self.torque_l_filtered + MAX_TORQUE_RATE) + torque_r = int(np.clip(self.torque_r_filtered, -MAX_TORQUE, MAX_TORQUE)) + torque_l = int(np.clip(self.torque_l_filtered, -MAX_TORQUE, MAX_TORQUE)) + + can_sends = [] + can_sends.append(bodycan.create_control(self.packer, torque_l, torque_r)) + + new_actuators = CC.actuators.as_builder() + new_actuators.accel = torque_l + new_actuators.torque = torque_r + new_actuators.torqueOutputCan = torque_r + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/body/carstate.py b/opendbc_repo/opendbc/car/body/carstate.py new file mode 100644 index 0000000000..b346a3df01 --- /dev/null +++ b/opendbc_repo/opendbc/car/body/carstate.py @@ -0,0 +1,35 @@ +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import CarStateBase +from opendbc.car.body.values import DBC + + +class CarState(CarStateBase): + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.main] + ret = structs.CarState() + + ret.wheelSpeeds.fl = cp.vl['MOTORS_DATA']['SPEED_L'] + ret.wheelSpeeds.fr = cp.vl['MOTORS_DATA']['SPEED_R'] + + ret.vEgoRaw = ((ret.wheelSpeeds.fl + ret.wheelSpeeds.fr) / 2.) * self.CP.wheelSpeedFactor + + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.standstill = False + + ret.steerFaultPermanent = any([cp.vl['VAR_VALUES']['MOTOR_ERR_L'], cp.vl['VAR_VALUES']['MOTOR_ERR_R'], + cp.vl['VAR_VALUES']['FAULT']]) + + ret.charging = cp.vl["BODY_DATA"]["CHARGER_CONNECTED"] == 1 + ret.fuelGauge = cp.vl["BODY_DATA"]["BATT_PERCENTAGE"] / 100 + + # irrelevant for non-car + ret.gearShifter = structs.CarState.GearShifter.drive + ret.cruiseState.enabled = True + ret.cruiseState.available = True + + return ret + + @staticmethod + def get_can_parsers(CP): + return {Bus.main: CANParser(DBC[CP.carFingerprint][Bus.main], [], 0)} diff --git a/opendbc_repo/opendbc/car/body/fingerprints.py b/opendbc_repo/opendbc/car/body/fingerprints.py new file mode 100644 index 0000000000..5806112fb1 --- /dev/null +++ b/opendbc_repo/opendbc/car/body/fingerprints.py @@ -0,0 +1,28 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.body.values import CAR + +Ecu = CarParams.Ecu + +# debug ecu fw version is the git hash of the firmware + + +FINGERPRINTS = { + CAR.COMMA_BODY: [{ + 513: 8, 516: 8, 514: 3, 515: 4 + }], +} + +FW_VERSIONS = { + CAR.COMMA_BODY: { + (Ecu.engine, 0x720, None): [ + b'0.0.01', + b'0.3.00a', + b'02/27/2022', + ], + (Ecu.debug, 0x721, None): [ + b'166bd860', + b'dc780f85', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/body/interface.py b/opendbc_repo/opendbc/car/body/interface.py new file mode 100644 index 0000000000..24e571ee95 --- /dev/null +++ b/opendbc_repo/opendbc/car/body/interface.py @@ -0,0 +1,30 @@ +import math +from opendbc.car import get_safety_config, structs +from opendbc.car.body.carcontroller import CarController +from opendbc.car.body.carstate import CarState +from opendbc.car.body.values import SPEED_FROM_RPM +from opendbc.car.interfaces import CarInterfaceBase + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.notCar = True + ret.brand = "body" + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.body)] + + ret.minSteerSpeed = -math.inf + ret.maxLateralAccel = math.inf # TODO: set to a reasonable value + ret.steerLimitTimer = 1.0 + ret.steerActuatorDelay = 0. + + ret.wheelSpeedFactor = SPEED_FROM_RPM + + ret.radarUnavailable = True + ret.openpilotLongitudinalControl = True + ret.steerControlType = structs.CarParams.SteerControlType.angle + + return ret diff --git a/opendbc_repo/opendbc/car/body/values.py b/opendbc_repo/opendbc/car/body/values.py new file mode 100644 index 0000000000..27490aba4f --- /dev/null +++ b/opendbc_repo/opendbc/car/body/values.py @@ -0,0 +1,40 @@ +from opendbc.car import Bus, CarSpecs, PlatformConfig, Platforms +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarDocs +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu + +SPEED_FROM_RPM = 0.008587 + + +class CarControllerParams: + ANGLE_DELTA_BP = [0., 5., 15.] + ANGLE_DELTA_V = [5., .8, .15] # windup limit + ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit + LKAS_MAX_TORQUE = 1 # A value of 1 is easy to overpower + STEER_THRESHOLD = 1.0 + + def __init__(self, CP): + pass + + +class CAR(Platforms): + COMMA_BODY = PlatformConfig( + [CarDocs("comma body", package="All", video="https://youtu.be/VT-i3yRsX2s?t=2736")], + CarSpecs(mass=9, wheelbase=0.406, steerRatio=0.5, centerToFrontRatio=0.44), + {Bus.main: 'comma_body'}, + ) + + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.UDS_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.UDS_VERSION_RESPONSE], + bus=0, + ), + ], +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/can_definitions.py b/opendbc_repo/opendbc/car/can_definitions.py new file mode 100644 index 0000000000..2dba7f26a8 --- /dev/null +++ b/opendbc_repo/opendbc/car/can_definitions.py @@ -0,0 +1,15 @@ +from collections.abc import Callable +from typing import NamedTuple, Protocol + + +class CanData(NamedTuple): + address: int + dat: bytes + src: int + + +CanSendCallable = Callable[[list[CanData]], None] + + +class CanRecvCallable(Protocol): + def __call__(self, wait_for_one: bool = False) -> list[list[CanData]]: ... diff --git a/opendbc_repo/opendbc/car/car.capnp b/opendbc_repo/opendbc/car/car.capnp new file mode 100644 index 0000000000..d237e353d5 --- /dev/null +++ b/opendbc_repo/opendbc/car/car.capnp @@ -0,0 +1,735 @@ +using Cxx = import "./include/c++.capnp"; +$Cxx.namespace("cereal"); + +@0x8e2af1e708af8b8d; + +# ******* events causing controls state machine transition ******* + +# IMPORTANT: This struct is to not be modified so old logs can be parsed +struct OnroadEventDEPRECATED @0x9b1657f34caf3ad3 { + name @0 :EventName; + + # event types + enable @1 :Bool; + noEntry @2 :Bool; + warning @3 :Bool; # alerts presented only when enabled or soft disabling + userDisable @4 :Bool; + softDisable @5 :Bool; + immediateDisable @6 :Bool; + preEnable @7 :Bool; + permanent @8 :Bool; # alerts presented regardless of openpilot state + overrideLateral @10 :Bool; + overrideLongitudinal @9 :Bool; + + enum EventName @0xbaa8c5d505f727de { + canError @0; + steerUnavailable @1; + wrongGear @4; + doorOpen @5; + seatbeltNotLatched @6; + espDisabled @7; + wrongCarMode @8; + steerTempUnavailable @9; + reverseGear @10; + buttonCancel @11; + buttonEnable @12; + pedalPressed @13; # exits active state + preEnableStandstill @73; # added during pre-enable state with brake + gasPressedOverride @108; # added when user is pressing gas with no disengage on gas + steerOverride @114; + cruiseDisabled @14; + speedTooLow @17; + outOfSpace @18; + overheat @19; + calibrationIncomplete @20; + calibrationInvalid @21; + calibrationRecalibrating @117; + controlsMismatch @22; + pcmEnable @23; + pcmDisable @24; + radarFault @26; + brakeHold @28; + parkBrake @29; + manualRestart @30; + joystickDebug @34; + longitudinalManeuver @124; + steerTempUnavailableSilent @35; + resumeRequired @36; + preDriverDistracted @37; + promptDriverDistracted @38; + driverDistracted @39; + preDriverUnresponsive @43; + promptDriverUnresponsive @44; + driverUnresponsive @45; + belowSteerSpeed @46; + lowBattery @48; + accFaulted @51; + sensorDataInvalid @52; + commIssue @53; + commIssueAvgFreq @109; + tooDistracted @54; + posenetInvalid @55; + preLaneChangeLeft @57; + preLaneChangeRight @58; + laneChange @59; + lowMemory @63; + stockAeb @64; + ldw @65; + carUnrecognized @66; + invalidLkasSetting @69; + speedTooHigh @70; + laneChangeBlocked @71; + relayMalfunction @72; + stockFcw @74; + startup @75; + startupNoCar @76; + startupNoControl @77; + startupNoSecOcKey @125; + startupMaster @78; + fcw @79; + steerSaturated @80; + belowEngageSpeed @84; + noGps @85; + wrongCruiseMode @87; + modeldLagging @89; + deviceFalling @90; + fanMalfunction @91; + cameraMalfunction @92; + cameraFrameRate @110; + processNotRunning @95; + dashcamMode @96; + selfdriveInitializing @98; + usbError @99; + cruiseMismatch @106; + canBusMissing @111; + selfdrivedLagging @112; + resumeBlocked @113; + steerTimeLimit @115; + vehicleSensorsInvalid @116; + locationdTemporaryError @103; + locationdPermanentError @118; + paramsdTemporaryError @50; + paramsdPermanentError @119; + actuatorsApiUnavailable @120; + espActive @121; + personalityChanged @122; + aeb @123; + + radarCanErrorDEPRECATED @15; + communityFeatureDisallowedDEPRECATED @62; + radarCommIssueDEPRECATED @67; + driverMonitorLowAccDEPRECATED @68; + gasUnavailableDEPRECATED @3; + dataNeededDEPRECATED @16; + modelCommIssueDEPRECATED @27; + ipasOverrideDEPRECATED @33; + geofenceDEPRECATED @40; + driverMonitorOnDEPRECATED @41; + driverMonitorOffDEPRECATED @42; + calibrationProgressDEPRECATED @47; + invalidGiraffeHondaDEPRECATED @49; + invalidGiraffeToyotaDEPRECATED @60; + internetConnectivityNeededDEPRECATED @61; + whitePandaUnsupportedDEPRECATED @81; + commIssueWarningDEPRECATED @83; + focusRecoverActiveDEPRECATED @86; + neosUpdateRequiredDEPRECATED @88; + modelLagWarningDEPRECATED @93; + startupOneplusDEPRECATED @82; + startupFuzzyFingerprintDEPRECATED @97; + noTargetDEPRECATED @25; + brakeUnavailableDEPRECATED @2; + plannerErrorDEPRECATED @32; + gpsMalfunctionDEPRECATED @94; + roadCameraErrorDEPRECATED @100; + driverCameraErrorDEPRECATED @101; + wideRoadCameraErrorDEPRECATED @102; + highCpuUsageDEPRECATED @105; + startupNoFwDEPRECATED @104; + lowSpeedLockoutDEPRECATED @31; + lkasDisabledDEPRECATED @107; + soundsUnavailableDEPRECATED @56; + } +} + +struct CarState { + # CAN health + canValid @26 :Bool; # invalid counter/checksums + canTimeout @40 :Bool; # CAN bus dropped out + canErrorCounter @48 :UInt32; + + # process meta + cumLagMs @50 :Float32; + + # car speed + vEgo @1 :Float32; # best estimate of speed + aEgo @16 :Float32; # best estimate of aCAN cceleration + vEgoRaw @17 :Float32; # unfiltered speed from wheel speed sensors + vEgoCluster @44 :Float32; # best estimate of speed shown on car's instrument cluster, used for UI + + vCruise @53 :Float32; # actual set speed + vCruiseCluster @54 :Float32; # set speed to display in the UI + + yawRate @22 :Float32; # best estimate of yaw rate + standstill @18 :Bool; + wheelSpeeds @2 :WheelSpeeds; + + gasPressed @4 :Bool; # this is user pedal only + + # brake pedal, 0.0-1.0 + brake @5 :Float32; # this is user pedal only + brakePressed @6 :Bool; # this is user pedal only + regenBraking @45 :Bool; # this is user pedal only + parkingBrake @39 :Bool; + brakeHoldActive @38 :Bool; + + # steering wheel + steeringAngleDeg @7 :Float32; + steeringAngleOffsetDeg @37 :Float32; # Offset between sensors in case there multiple + steeringRateDeg @15 :Float32; # optional + steeringTorque @8 :Float32; # Native CAN units, only needed on cars where it's used for control + steeringTorqueEps @27 :Float32; # Native CAN units, only needed on cars where it's used for control + steeringPressed @9 :Bool; # is the user overring the steering wheel? + steeringDisengage @58 :Bool; # more force than steeringPressed, disengages for applicable brands + steerFaultTemporary @35 :Bool; + steerFaultPermanent @36 :Bool; + + invalidLkasSetting @55 :Bool; # stock LKAS is incorrectly configured (i.e. on or off) + stockAeb @30 :Bool; + stockLkas @59 :Bool; + stockFcw @31 :Bool; + espDisabled @32 :Bool; + accFaulted @42 :Bool; + carFaultedNonCritical @47 :Bool; # some ECU is faulted, but car remains controllable + espActive @51 :Bool; + vehicleSensorsInvalid @52 :Bool; # invalid steering angle readings, etc. + lowSpeedAlert @56 :Bool; # lost steering control due to a dynamic min steering speed + blockPcmEnable @60 :Bool; # whether to allow PCM to enable this frame + + # cruise state + cruiseState @10 :CruiseState; + + # gear + gearShifter @14 :GearShifter; + + # button presses + buttonEvents @11 :List(ButtonEvent); + buttonEnable @57 :Bool; # user is requesting enable, usually one frame. set if pcmCruise=False + leftBlinker @20 :Bool; + rightBlinker @21 :Bool; + genericToggle @23 :Bool; + + # lock info + doorOpen @24 :Bool; # ideally includes all doors + seatbeltUnlatched @25 :Bool; # driver seatbelt + + # blindspot sensors + leftBlindspot @33 :Bool; # Is there something blocking the left lane change + rightBlindspot @34 :Bool; # Is there something blocking the right lane change + + fuelGauge @41 :Float32; # battery or fuel tank level from [0.0, 1.0] + charging @43 :Bool; + + struct WheelSpeeds { + # optional wheel speeds + fl @0 :Float32; + fr @1 :Float32; + rl @2 :Float32; + rr @3 :Float32; + } + + struct CruiseState { + enabled @0 :Bool; + speed @1 :Float32; + speedCluster @6 :Float32; # Set speed as shown on instrument cluster + available @2 :Bool; + standstill @4 :Bool; + nonAdaptive @5 :Bool; + + speedOffsetDEPRECATED @3 :Float32; + } + + enum GearShifter { + unknown @0; + park @1; + drive @2; + neutral @3; + reverse @4; + sport @5; + low @6; + brake @7; + eco @8; + manumatic @9; + } + + # send on change + struct ButtonEvent { + pressed @0 :Bool; + type @1 :Type; + + enum Type { + unknown @0; + leftBlinker @1; + rightBlinker @2; + accelCruise @3; + decelCruise @4; + cancel @5; + lkas @6; + altButton2 @7; + mainCruise @8; + setCruise @9; + resumeCruise @10; + gapAdjustCruise @11; + } + } + + # deprecated + errorsDEPRECATED @0 :List(OnroadEventDEPRECATED.EventName); + gasDEPRECATED @3 :Float32; # this is user pedal only + brakeLightsDEPRECATED @19 :Bool; + steeringRateLimitedDEPRECATED @29 :Bool; + canMonoTimesDEPRECATED @12: List(UInt64); + canRcvTimeoutDEPRECATED @49 :Bool; + eventsDEPRECATED @13 :List(OnroadEventDEPRECATED); + clutchPressedDEPRECATED @28 :Bool; + engineRpmDEPRECATED @46 :Float32; +} + +# ******* radar state @ 20hz ******* + +struct RadarData @0x888ad6581cf0aacb { + errors @3 :Error; + points @1 :List(RadarPoint); + + struct Error { + canError @0 :Bool; + radarFault @1 :Bool; + wrongConfig @2 :Bool; + radarUnavailableTemporary @3 :Bool; # radar data is temporarily unavailable due to conditions the car sets + } + + # similar to LiveTracks + # is one timestamp valid for all? I think so + struct RadarPoint { + trackId @0 :UInt64; # no trackId reuse + + # these 3 are the minimum required + dRel @1 :Float32; # m from the front bumper of the car + yRel @2 :Float32; # m + vRel @3 :Float32; # m/s + + # these are optional and valid if they are not NaN + aRel @4 :Float32; # m/s^2 + yvRel @5 :Float32; # m/s + + # some radars flag measurements VS estimates + measured @6 :Bool; + } + + enum ErrorDEPRECATED { + canError @0; + fault @1; + wrongConfig @2; + } + + # deprecated + canMonoTimesDEPRECATED @2 :List(UInt64); + errorsDEPRECATED @0 :List(ErrorDEPRECATED); +} + +# ******* car controls @ 100hz ******* + +struct CarControl { + # must be true for any actuator commands to work + enabled @0 :Bool; + latActive @11: Bool; + longActive @12: Bool; + + # Final actuator commands + actuators @6 :Actuators; + + # Blinker controls + leftBlinker @15: Bool; + rightBlinker @16: Bool; + + orientationNED @13 :List(Float32); + angularVelocity @14 :List(Float32); + currentCurvature @17 :Float32; # From vehicle model + + cruiseControl @4 :CruiseControl; + hudControl @5 :HUDControl; + + struct Actuators { + # lateral commands, mutually exclusive + torque @2: Float32; # [0.0, 1.0] + steeringAngleDeg @3: Float32; + curvature @7: Float32; + + # longitudinal commands + accel @4: Float32; # m/s^2 + longControlState @5: LongControlState; + + # these are only for logging the actual values sent to the car over CAN + gas @0: Float32; # [0.0, 1.0] + brake @1: Float32; # [0.0, 1.0] + torqueOutputCan @8: Float32; # value sent over can to the car + speed @6: Float32; # m/s + + enum LongControlState @0xe40f3a917d908282{ + off @0; + pid @1; + stopping @2; + starting @3; + } + } + + struct CruiseControl { + cancel @0: Bool; + resume @1: Bool; + override @4: Bool; + speedOverrideDEPRECATED @2: Float32; + accelOverrideDEPRECATED @3: Float32; + } + + struct HUDControl { + speedVisible @0: Bool; + setSpeed @1: Float32; + lanesVisible @2: Bool; + leadVisible @3: Bool; + visualAlert @4: VisualAlert; + rightLaneVisible @6: Bool; + leftLaneVisible @7: Bool; + rightLaneDepart @8: Bool; + leftLaneDepart @9: Bool; + leadDistanceBars @10: Int8; # 1-3: 1 is closest, 3 is farthest. some ports may utilize 2-4 bars instead + + # not used with the dash, TODO: separate structs for dash UI and device UI + audibleAlert @5: AudibleAlert; + + enum VisualAlert { + # these are the choices from the Honda + # map as good as you can for your car + none @0; + fcw @1; + steerRequired @2; + brakePressed @3; + wrongGear @4; + seatbeltUnbuckled @5; + speedTooHigh @6; + ldw @7; + } + + enum AudibleAlert { + none @0; + + engage @1; + disengage @2; + refuse @3; + + warningSoft @4; + warningImmediate @5; + + prompt @6; + promptRepeat @7; + promptDistracted @8; + } + } + + gasDEPRECATED @1 :Float32; + brakeDEPRECATED @2 :Float32; + steeringTorqueDEPRECATED @3 :Float32; + activeDEPRECATED @7 :Bool; + rollDEPRECATED @8 :Float32; + pitchDEPRECATED @9 :Float32; + actuatorsOutputDEPRECATED @10 :Actuators; +} + +struct CarOutput { + # Any car specific rate limits or quirks applied by + # the CarController are reflected in actuatorsOutput + # and matches what is sent to the car + actuatorsOutput @0 :CarControl.Actuators; +} + +# ****** car param ****** + +struct CarParams { + brand @0 :Text; # Designates which group a platform falls under. Each folder in opendbc/car is assigned one brand string + carFingerprint @1 :Text; + fuzzyFingerprint @55 :Bool; + + notCar @66 :Bool; # flag for non-car robotics platforms + + pcmCruise @3 :Bool; # is openpilot's state tied to the PCM's cruise state? + enableDsu @5 :Bool; # driving support unit + enableBsm @56 :Bool; # blind spot monitoring + flags @64 :UInt32; # flags for car specific quirks + alphaLongitudinalAvailable @71 :Bool; + + minEnableSpeed @7 :Float32; + minSteerSpeed @8 :Float32; + steerAtStandstill @77 :Bool; # is steering available at standstill? just check if it faults + safetyConfigs @62 :List(SafetyConfig); + alternativeExperience @65 :Int16; # panda flag for features like no disengage on gas + + # Car docs fields, not used for control + maxLateralAccel @68 :Float32; + autoResumeSng @69 :Bool; # describes whether car can resume from a stop automatically + + # things about the car in the manual + mass @17 :Float32; # [kg] curb weight: all fluids no cargo + wheelbase @18 :Float32; # [m] distance from rear axle to front axle + centerToFront @19 :Float32; # [m] distance from center of mass to front axle + steerRatio @20 :Float32; # [] ratio of steering wheel angle to front wheel angle + steerRatioRear @21 :Float32; # [] ratio of steering wheel angle to rear wheel angle (usually 0) + + # things we can derive + rotationalInertia @22 :Float32; # [kg*m2] body rotational inertia + tireStiffnessFactor @72 :Float32; # scaling factor used in calculating tireStiffness[Front,Rear] + tireStiffnessFront @23 :Float32; # [N/rad] front tire coeff of stiff + tireStiffnessRear @24 :Float32; # [N/rad] rear tire coeff of stiff + + longitudinalTuning @25 :LongitudinalPIDTuning; + lateralParams @48 :LateralParams; + lateralTuning :union { + pid @26 :LateralPIDTuning; + indiDEPRECATED @27 :LateralINDITuning; + lqrDEPRECATED @40 :LateralLQRTuning; + torque @67 :LateralTorqueTuning; + } + + steerLimitAlert @28 :Bool; + steerLimitTimer @47 :Float32; # time before steerLimitAlert is issued + + vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state + vEgoStarting @59 :Float32; # Speed at which the car goes into starting state + steerControlType @34 :SteerControlType; + radarUnavailable @35 :Bool; # True when radar objects aren't visible on CAN or aren't parsed out + stopAccel @60 :Float32; # Required acceleration to keep vehicle stationary + stoppingDecelRate @52 :Float32; # m/s^2/s while trying to stop + startAccel @32 :Float32; # Required acceleration to get car moving + startingState @70 :Bool; # Does this car make use of special starting state + + steerActuatorDelay @36 :Float32; # Steering wheel actuator delay in seconds + longitudinalActuatorDelay @58 :Float32; # Gas/Brake actuator delay in seconds + openpilotLongitudinalControl @37 :Bool; # is openpilot doing the longitudinal control? + carVin @38 :Text; # VIN number queried during fingerprinting + dashcamOnly @41: Bool; + passive @73: Bool; # is openpilot in control? + transmissionType @43 :TransmissionType; + carFw @44 :List(CarFw); + + radarDelay @74 :Float32; + fingerprintSource @49: FingerprintSource; + networkLocation @50 :NetworkLocation; # Where Panda/C2 is integrated into the car's CAN network + + wheelSpeedFactor @63 :Float32; # Multiplier on wheels speeds to computer actual speeds + + secOcRequired @75 :Bool; # Car requires SecOC message authentication to operate + secOcKeyAvailable @76 :Bool; # Stored SecOC key loaded from params + + struct SafetyConfig { + safetyModel @0 :SafetyModel; + safetyParam @3 :UInt16; + safetyParamDEPRECATED @1 :Int16; + safetyParam2DEPRECATED @2 :UInt32; + } + + struct LateralParams { + torqueBP @0 :List(Int32); + torqueV @1 :List(Int32); + } + + struct LateralPIDTuning { + kpBP @0 :List(Float32); + kpV @1 :List(Float32); + kiBP @2 :List(Float32); + kiV @3 :List(Float32); + kf @4 :Float32; + } + + struct LateralTorqueTuning { + kp @1 :Float32; + ki @2 :Float32; + friction @3 :Float32; + kf @4 :Float32; + steeringAngleDeadzoneDeg @5 :Float32; + latAccelFactor @6 :Float32; + latAccelOffset @7 :Float32; + useSteeringAngleDEPRECATED @0 :Bool; + } + + struct LongitudinalPIDTuning { + kpBP @0 :List(Float32); + kpV @1 :List(Float32); + kiBP @2 :List(Float32); + kiV @3 :List(Float32); + kf @6 :Float32; + deadzoneBPDEPRECATED @4 :List(Float32); + deadzoneVDEPRECATED @5 :List(Float32); + } + + struct LateralINDITuning { + outerLoopGainBP @4 :List(Float32); + outerLoopGainV @5 :List(Float32); + innerLoopGainBP @6 :List(Float32); + innerLoopGainV @7 :List(Float32); + timeConstantBP @8 :List(Float32); + timeConstantV @9 :List(Float32); + actuatorEffectivenessBP @10 :List(Float32); + actuatorEffectivenessV @11 :List(Float32); + + outerLoopGainDEPRECATED @0 :Float32; + innerLoopGainDEPRECATED @1 :Float32; + timeConstantDEPRECATED @2 :Float32; + actuatorEffectivenessDEPRECATED @3 :Float32; + } + + struct LateralLQRTuning { + scale @0 :Float32; + ki @1 :Float32; + dcGain @2 :Float32; + + # State space system + a @3 :List(Float32); + b @4 :List(Float32); + c @5 :List(Float32); + + k @6 :List(Float32); # LQR gain + l @7 :List(Float32); # Kalman gain + } + + enum SafetyModel { + silent @0; + hondaNidec @1; + toyota @2; + elm327 @3; + gm @4; + hondaBoschGiraffe @5; + ford @6; + cadillac @7; + hyundai @8; + chrysler @9; + tesla @10; + subaru @11; + gmPassive @12; + mazda @13; + nissan @14; + volkswagen @15; + toyotaIpas @16; + allOutput @17; + gmAscm @18; + noOutput @19; # like silent but without silent CAN TXs + hondaBosch @20; + volkswagenPq @21; + subaruPreglobal @22; # pre-Global platform + hyundaiLegacy @23; + hyundaiCommunity @24; + volkswagenMlb @25; + hongqi @26; + body @27; + hyundaiCanfd @28; + volkswagenMqbEvo @29; + chryslerCusw @30; + psa @31; + fcaGiorgio @32; + rivian @33; + volkswagenMeb @34; + } + + enum SteerControlType { + torque @0; + angle @1; + + curvatureDEPRECATED @2; + } + + enum TransmissionType { + unknown @0; + automatic @1; # Traditional auto, including DSG + manual @2; # True "stick shift" only + direct @3; # Electric vehicle or other direct drive + cvt @4; + } + + struct CarFw { + ecu @0 :Ecu; + fwVersion @1 :Data; + address @2 :UInt32; + subAddress @3 :UInt8; + responseAddress @4 :UInt32; + request @5 :List(Data); + brand @6 :Text; + bus @7 :UInt8; + logging @8 :Bool; + obdMultiplexing @9 :Bool; + } + + enum Ecu { + eps @0; + abs @1; + fwdRadar @2; + fwdCamera @3; + engine @4; + unknown @5; + transmission @8; # Transmission Control Module + hybrid @18; # hybrid control unit, e.g. Chrysler's HCP, Honda's IMA Control Unit, Toyota's hybrid control computer + srs @9; # airbag + gateway @10; # can gateway + hud @11; # heads up display + combinationMeter @12; # instrument cluster + electricBrakeBooster @15; + shiftByWire @16; + adas @19; + cornerRadar @21; + hvac @20; + parkingAdas @7; # parking assist system ECU, e.g. Toyota's IPAS, Hyundai's RSPA, etc. + epb @22; # electronic parking brake + telematics @23; + body @24; # body control module + + # Toyota only + dsu @6; + + # Honda only + vsa @13; # Vehicle Stability Assist + programmedFuelInjection @14; + + debug @17; + } + + enum FingerprintSource { + can @0; + fw @1; + fixed @2; + } + + enum NetworkLocation { + fwdCamera @0; # Standard/default integration at LKAS camera + gateway @1; # Integration at vehicle's CAN gateway + } + + enableGasInterceptorDEPRECATED @2 :Bool; + enableCameraDEPRECATED @4 :Bool; + enableApgsDEPRECATED @6 :Bool; + steerRateCostDEPRECATED @33 :Float32; + isPandaBlackDEPRECATED @39 :Bool; + hasStockCameraDEPRECATED @57 :Bool; + safetyParamDEPRECATED @10 :Int16; + safetyModelDEPRECATED @9 :SafetyModel; + safetyModelPassiveDEPRECATED @42 :SafetyModel = silent; + minSpeedCanDEPRECATED @51 :Float32; + communityFeatureDEPRECATED @46: Bool; + startingAccelRateDEPRECATED @53 :Float32; + steerMaxBPDEPRECATED @11 :List(Float32); + steerMaxVDEPRECATED @12 :List(Float32); + gasMaxBPDEPRECATED @13 :List(Float32); + gasMaxVDEPRECATED @14 :List(Float32); + brakeMaxBPDEPRECATED @15 :List(Float32); + brakeMaxVDEPRECATED @16 :List(Float32); + directAccelControlDEPRECATED @30 :Bool; + maxSteeringAngleDegDEPRECATED @54 :Float32; + longitudinalActuatorDelayLowerBoundDEPRECATED @61 :Float32; + stoppingControlDEPRECATED @31 :Bool; # Does the car allow full control even at lows speeds when stopping + radarTimeStepDEPRECATED @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard +} diff --git a/opendbc_repo/opendbc/car/car_helpers.py b/opendbc_repo/opendbc/car/car_helpers.py new file mode 100644 index 0000000000..dfda015525 --- /dev/null +++ b/opendbc_repo/opendbc/car/car_helpers.py @@ -0,0 +1,173 @@ +import os +import time + +from opendbc.car import gen_empty_fingerprint +from opendbc.car.can_definitions import CanRecvCallable, CanSendCallable +from opendbc.car.carlog import carlog +from opendbc.car.structs import CarParams, CarParamsT +from opendbc.car.fingerprints import eliminate_incompatible_cars, all_legacy_fingerprint_cars +from opendbc.car.fw_versions import ObdCallback, get_fw_versions_ordered, get_present_ecus, match_fw_to_car +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.values import BRANDS +from opendbc.car.vin import get_vin, is_valid_vin, VIN_UNKNOWN + +FRAME_FINGERPRINT = 100 # 1s + + +def load_interfaces(brand_names): + ret = {} + for brand_name in brand_names: + path = f'opendbc.car.{brand_name}' + CarInterface = __import__(path + '.interface', fromlist=['CarInterface']).CarInterface + for model_name in brand_names[brand_name]: + ret[model_name] = CarInterface + return ret + + +def _get_interface_names() -> dict[str, list[str]]: + # returns a dict of brand name and its respective models + brand_names = {} + for brand in BRANDS: + brand_name = brand.__module__.split('.')[-2] + brand_names[brand_name] = [model.value for model in brand] + + return brand_names + + +# imports from directory opendbc/car// +interface_names = _get_interface_names() +interfaces = load_interfaces(interface_names) + + +def can_fingerprint(can_recv: CanRecvCallable) -> tuple[str | None, dict[int, dict]]: + finger = gen_empty_fingerprint() + candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1 + frame = 0 + car_fingerprint = None + done = False + + while not done: + # can_recv(wait_for_one=True) may return zero or multiple packets, so we increment frame for each one we receive + can_packets = can_recv(wait_for_one=True) + for can_packet in can_packets: + for can in can_packet: + # The fingerprint dict is generated for all buses, this way the car interface + # can use it to detect a (valid) multipanda setup and initialize accordingly + if can.src < 128: + if can.src not in finger: + finger[can.src] = {} + finger[can.src][can.address] = len(can.dat) + + for b in candidate_cars: + # Ignore extended messages and VIN query response. + if can.src == b and can.address < 0x800 and can.address not in (0x7df, 0x7e0, 0x7e8): + candidate_cars[b] = eliminate_incompatible_cars(can, candidate_cars[b]) + + # if we only have one car choice and the time since we got our first + # message has elapsed, exit + for b in candidate_cars: + if len(candidate_cars[b]) == 1 and frame > FRAME_FINGERPRINT: + # fingerprint done + car_fingerprint = candidate_cars[b][0] + + # bail if no cars left or we've been waiting for more than 2s + failed = (all(len(cc) == 0 for cc in candidate_cars.values()) and frame > FRAME_FINGERPRINT) or frame > 200 + succeeded = car_fingerprint is not None + done = failed or succeeded + + frame += 1 + + return car_fingerprint, finger + + +# **** for use live only **** +def fingerprint(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, num_pandas: int, + cached_params: CarParamsT | None) -> tuple[str | None, dict, str, list[CarParams.CarFw], CarParams.FingerprintSource, bool]: + fixed_fingerprint = os.environ.get('FINGERPRINT', "") + skip_fw_query = os.environ.get('SKIP_FW_QUERY', False) + disable_fw_cache = os.environ.get('DISABLE_FW_CACHE', False) + ecu_rx_addrs = set() + + start_time = time.monotonic() + if not skip_fw_query: + if cached_params is not None and cached_params.brand != "mock" and len(cached_params.carFw) > 0 and \ + cached_params.carVin is not VIN_UNKNOWN and not disable_fw_cache: + carlog.warning("Using cached CarParams") + vin_rx_addr, vin_rx_bus, vin = -1, -1, cached_params.carVin + car_fw = list(cached_params.carFw) + cached = True + else: + carlog.warning("Getting VIN & FW versions") + # enable OBD multiplexing for VIN query + # NOTE: this takes ~0.1s and is relied on to allow sendcan subscriber to connect in time + set_obd_multiplexing(True) + # VIN query only reliably works through OBDII + vin_rx_addr, vin_rx_bus, vin = get_vin(can_recv, can_send, (0, 1)) + ecu_rx_addrs = get_present_ecus(can_recv, can_send, set_obd_multiplexing, num_pandas=num_pandas) + car_fw = get_fw_versions_ordered(can_recv, can_send, set_obd_multiplexing, vin, ecu_rx_addrs, num_pandas=num_pandas) + cached = False + + exact_fw_match, fw_candidates = match_fw_to_car(car_fw, vin) + else: + vin_rx_addr, vin_rx_bus, vin = -1, -1, VIN_UNKNOWN + exact_fw_match, fw_candidates, car_fw = True, set(), [] + cached = False + + if not is_valid_vin(vin): + carlog.error({"event": "Malformed VIN", "vin": vin}) + vin = VIN_UNKNOWN + carlog.warning("VIN %s", vin) + + # disable OBD multiplexing for CAN fingerprinting and potential ECU knockouts + set_obd_multiplexing(False) + + fw_query_time = time.monotonic() - start_time + + # CAN fingerprint + # drain CAN socket so we get the latest messages + can_recv() + car_fingerprint, finger = can_fingerprint(can_recv) + + exact_match = True + source = CarParams.FingerprintSource.can + + # If FW query returns exactly 1 candidate, use it + if len(fw_candidates) == 1: + car_fingerprint = list(fw_candidates)[0] + source = CarParams.FingerprintSource.fw + exact_match = exact_fw_match + + if fixed_fingerprint: + car_fingerprint = fixed_fingerprint + source = CarParams.FingerprintSource.fixed + + carlog.error({"event": "fingerprinted", "car_fingerprint": str(car_fingerprint), "source": source, "fuzzy": not exact_match, + "cached": cached, "fw_count": len(car_fw), "ecu_responses": list(ecu_rx_addrs), "vin_rx_addr": vin_rx_addr, + "vin_rx_bus": vin_rx_bus, "fingerprints": repr(finger), "fw_query_time": fw_query_time}) + + return car_fingerprint, finger, vin, car_fw, source, exact_match + + +def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, alpha_long_allowed: bool, + is_release: bool, num_pandas: int = 1, cached_params: CarParamsT | None = None): + candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params) + + if candidate is None: + carlog.error({"event": "car doesn't match any fingerprints", "fingerprints": repr(fingerprints)}) + candidate = "MOCK" + + CarInterface = interfaces[candidate] + CP: CarParams = CarInterface.get_params(candidate, fingerprints, car_fw, alpha_long_allowed, is_release, docs=False) + CP.carVin = vin + CP.carFw = car_fw + CP.fingerprintSource = source + CP.fuzzyFingerprint = not exact_match + + return interfaces[CP.carFingerprint](CP) + + +def get_demo_car_params(): + platform = MOCK.MOCK + CarInterface = interfaces[platform] + CP = CarInterface.get_non_essential_params(platform) + return CP diff --git a/opendbc_repo/opendbc/car/carlog.py b/opendbc_repo/opendbc/car/carlog.py new file mode 100644 index 0000000000..5683d2a394 --- /dev/null +++ b/opendbc_repo/opendbc/car/carlog.py @@ -0,0 +1,12 @@ +import os +import logging + +# set up logging +LOGPRINT = os.environ.get('LOGPRINT', 'INFO').upper() +carlog = logging.getLogger('carlog') +carlog.setLevel(LOGPRINT) +carlog.propagate = False + +handler = logging.StreamHandler() +handler.setFormatter(logging.Formatter('%(message)s')) +carlog.addHandler(handler) diff --git a/opendbc_repo/opendbc/car/ccp.py b/opendbc_repo/opendbc/car/ccp.py new file mode 100644 index 0000000000..c94acb802b --- /dev/null +++ b/opendbc_repo/opendbc/car/ccp.py @@ -0,0 +1,385 @@ +import sys +import time +import struct +from enum import IntEnum, Enum +from dataclasses import dataclass + + +@dataclass +class ExchangeStationIdsReturn: + id_length: int + data_type: int + available: int + protected: int + + +@dataclass +class GetDaqListSizeReturn: + list_size: int + first_pid: int + + +@dataclass +class GetSessionStatusReturn: + status: int + info: int | None + + +@dataclass +class DiagnosticServiceReturn: + length: int + type: int + + +@dataclass +class ActionServiceReturn: + length: int + type: int + + +class COMMAND_CODE(IntEnum): + CONNECT = 0x01 + SET_MTA = 0x02 + DNLOAD = 0x03 + UPLOAD = 0x04 + TEST = 0x05 + START_STOP = 0x06 + DISCONNECT = 0x07 + START_STOP_ALL = 0x08 + GET_ACTIVE_CAL_PAGE = 0x09 + SET_S_STATUS = 0x0C + GET_S_STATUS = 0x0D + BUILD_CHKSUM = 0x0E + SHORT_UP = 0x0F + CLEAR_MEMORY = 0x10 + SELECT_CAL_PAGE = 0x11 + GET_SEED = 0x12 + UNLOCK = 0x13 + GET_DAQ_SIZE = 0x14 + SET_DAQ_PTR = 0x15 + WRITE_DAQ = 0x16 + EXCHANGE_ID = 0x17 + PROGRAM = 0x18 + MOVE = 0x19 + GET_CCP_VERSION = 0x1B + DIAG_SERVICE = 0x20 + ACTION_SERVICE = 0x21 + PROGRAM_6 = 0x22 + DNLOAD_6 = 0x23 + + +COMMAND_RETURN_CODES = { + 0x00: "acknowledge / no error", + 0x01: "DAQ processor overload", + 0x10: "command processor busy", + 0x11: "DAQ processor busy", + 0x12: "internal timeout", + 0x18: "key request", + 0x19: "session status request", + 0x20: "cold start request", + 0x21: "cal. data init. request", + 0x22: "DAQ list init. request", + 0x23: "code update request", + 0x30: "unknown command", + 0x31: "command syntax", + 0x32: "parameter(s) out of range", + 0x33: "access denied", + 0x34: "overload", + 0x35: "access locked", + 0x36: "resource/function not available", +} + + +class BYTE_ORDER(Enum): + LITTLE_ENDIAN = '<' + BIG_ENDIAN = '>' + + +class CommandTimeoutError(Exception): + pass + + +class CommandCounterError(Exception): + pass + + +class CommandResponseError(Exception): + def __init__(self, message, return_code): + super().__init__() + self.message = message + self.return_code = return_code + + def __str__(self): + return self.message + + +class CcpClient: + def __init__(self, panda, tx_addr: int, rx_addr: int, bus: int=0, byte_order: BYTE_ORDER=BYTE_ORDER.BIG_ENDIAN, debug=False): + self.tx_addr = tx_addr + self.rx_addr = rx_addr + self.can_bus = bus + self.byte_order = byte_order + self.debug = debug + self._panda = panda + self._command_counter = -1 + + def _send_cro(self, cmd: int, dat: bytes = b"") -> None: + self._command_counter = (self._command_counter + 1) & 0xFF + tx_data = (bytes([cmd, self._command_counter]) + dat).ljust(8, b"\x00") + if self.debug: + print(f"CAN-TX: {hex(self.tx_addr)} - 0x{bytes.hex(tx_data)}") + assert len(tx_data) == 8, "data is not 8 bytes" + self._panda.can_clear(self.can_bus) + self._panda.can_clear(0xFFFF) + self._panda.can_send(self.tx_addr, tx_data, self.can_bus) + + def _recv_dto(self, timeout: float) -> bytes: + start_time = time.time() + while time.time() - start_time < timeout: + msgs = self._panda.can_recv() or [] + if len(msgs) >= 256: + print("CAN RX buffer overflow!!!", file=sys.stderr) + for rx_addr, rx_data_bytearray, rx_bus in msgs: + if rx_bus == self.can_bus and rx_addr == self.rx_addr: + rx_data = bytes(rx_data_bytearray) + if self.debug: + print(f"CAN-RX: {hex(rx_addr)} - 0x{bytes.hex(rx_data)}") + assert len(rx_data) == 8, f"message length not 8: {len(rx_data)}" + + pid = rx_data[0] + if pid == 0xFF or pid == 0xFE: + err = rx_data[1] + err_desc = COMMAND_RETURN_CODES.get(err, "unknown error") + ctr = rx_data[2] + dat = rx_data[3:] + + if pid == 0xFF and self._command_counter != ctr: + raise CommandCounterError(f"counter invalid: {ctr} != {self._command_counter}") + + if err >= 0x10 and err <= 0x12: + if self.debug: + print(f"CCP-WAIT: {hex(err)} - {err_desc}") + start_time = time.time() + continue + + if err >= 0x30: + raise CommandResponseError(f"{hex(err)} - {err_desc}", err) + else: + dat = rx_data[1:] + + return dat + time.sleep(0.001) + + raise CommandTimeoutError("timeout waiting for response") + + # commands + def connect(self, station_addr: int) -> None: + if station_addr > 65535: + raise ValueError("station address must be less than 65536") + # NOTE: station address is always little endian + self._send_cro(COMMAND_CODE.CONNECT, struct.pack(" ExchangeStationIdsReturn: + self._send_cro(COMMAND_CODE.EXCHANGE_ID, device_id_info) + resp = self._recv_dto(0.025) + return ExchangeStationIdsReturn(id_length=resp[0], data_type=resp[1], available=resp[2], protected=resp[3]) + + def get_seed(self, resource_mask: int) -> bytes: + if resource_mask > 255: + raise ValueError("resource mask must be less than 256") + self._send_cro(COMMAND_CODE.GET_SEED, bytes([resource_mask])) + resp = self._recv_dto(0.025) + # protected = resp[0] == 0 + seed = resp[1:] + return seed + + def unlock(self, key: bytes) -> int: + if len(key) > 6: + raise ValueError("max key size is 6 bytes") + self._send_cro(COMMAND_CODE.UNLOCK, key) + resp = self._recv_dto(0.025) + status = resp[0] + return status + + def set_memory_transfer_address(self, mta_num: int, addr_ext: int, addr: int) -> None: + if mta_num > 255: + raise ValueError("MTA number must be less than 256") + if addr_ext > 255: + raise ValueError("address extension must be less than 256") + self._send_cro(COMMAND_CODE.SET_MTA, bytes([mta_num, addr_ext]) + struct.pack(f"{self.byte_order.value}I", addr)) + self._recv_dto(0.025) + + def download(self, data: bytes) -> int: + if len(data) > 5: + raise ValueError("max data size is 5 bytes") + self._send_cro(COMMAND_CODE.DNLOAD, bytes([len(data)]) + data) + resp = self._recv_dto(0.025) + # mta_addr_ext = resp[0] + mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0] + return mta_addr # type: ignore + + def download_6_bytes(self, data: bytes) -> int: + if len(data) != 6: + raise ValueError("data size must be 6 bytes") + self._send_cro(COMMAND_CODE.DNLOAD_6, data) + resp = self._recv_dto(0.025) + # mta_addr_ext = resp[0] + mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0] + return mta_addr # type: ignore + + def upload(self, size: int) -> bytes: + if size > 5: + raise ValueError("size must be less than 6") + self._send_cro(COMMAND_CODE.UPLOAD, bytes([size])) + return self._recv_dto(0.025)[:size] + + def short_upload(self, size: int, addr_ext: int, addr: int) -> bytes: + if size > 5: + raise ValueError("size must be less than 6") + if addr_ext > 255: + raise ValueError("address extension must be less than 256") + self._send_cro(COMMAND_CODE.SHORT_UP, bytes([size, addr_ext]) + struct.pack(f"{self.byte_order.value}I", addr)) + return self._recv_dto(0.025)[:size] + + def select_calibration_page(self) -> None: + self._send_cro(COMMAND_CODE.SELECT_CAL_PAGE) + self._recv_dto(0.025) + + def get_daq_list_size(self, list_num: int, can_id: int = 0) -> GetDaqListSizeReturn: + if list_num > 255: + raise ValueError("list number must be less than 256") + self._send_cro(COMMAND_CODE.GET_DAQ_SIZE, bytes([list_num, 0]) + struct.pack(f"{self.byte_order.value}I", can_id)) + resp = self._recv_dto(0.025) + return GetDaqListSizeReturn(list_size=resp[0], first_pid=resp[1]) + + def set_daq_list_pointer(self, list_num: int, odt_num: int, element_num: int) -> None: + if list_num > 255: + raise ValueError("list number must be less than 256") + if odt_num > 255: + raise ValueError("ODT number must be less than 256") + if element_num > 255: + raise ValueError("element number must be less than 256") + self._send_cro(COMMAND_CODE.SET_DAQ_PTR, bytes([list_num, odt_num, element_num])) + self._recv_dto(0.025) + + def write_daq_list_entry(self, size: int, addr_ext: int, addr: int) -> None: + if size > 255: + raise ValueError("size must be less than 256") + if addr_ext > 255: + raise ValueError("address extension must be less than 256") + self._send_cro(COMMAND_CODE.WRITE_DAQ, bytes([size, addr_ext]) + struct.pack(f"{self.byte_order.value}I", addr)) + self._recv_dto(0.025) + + def start_stop_transmission(self, mode: int, list_num: int, odt_num: int, channel_num: int, rate_prescaler: int = 0) -> None: + if mode > 255: + raise ValueError("mode must be less than 256") + if list_num > 255: + raise ValueError("list number must be less than 256") + if odt_num > 255: + raise ValueError("ODT number must be less than 256") + if channel_num > 255: + raise ValueError("channel number must be less than 256") + if rate_prescaler > 65535: + raise ValueError("rate prescaler must be less than 65536") + self._send_cro(COMMAND_CODE.START_STOP, bytes([mode, list_num, odt_num, channel_num]) + struct.pack(f"{self.byte_order.value}H", rate_prescaler)) + self._recv_dto(0.025) + + def disconnect(self, station_addr: int, temporary: bool = False) -> None: + if station_addr > 65535: + raise ValueError("station address must be less than 65536") + # NOTE: station address is always little endian + self._send_cro(COMMAND_CODE.DISCONNECT, bytes([int(not temporary), 0x00]) + struct.pack(" None: + if status > 255: + raise ValueError("status must be less than 256") + self._send_cro(COMMAND_CODE.SET_S_STATUS, bytes([status])) + self._recv_dto(0.025) + + def get_session_status(self) -> GetSessionStatusReturn: + self._send_cro(COMMAND_CODE.GET_S_STATUS) + resp = self._recv_dto(0.025) + info = resp[2] if resp[1] else None + return GetSessionStatusReturn(status=resp[0], info=info) + + def build_checksum(self, size: int) -> bytes: + self._send_cro(COMMAND_CODE.BUILD_CHKSUM, struct.pack(f"{self.byte_order.value}I", size)) + resp = self._recv_dto(30.0) + chksum_size = resp[0] + assert chksum_size <= 4, "checksum more than 4 bytes" + chksum = resp[1:1+chksum_size] + return chksum + + def clear_memory(self, size: int) -> None: + self._send_cro(COMMAND_CODE.CLEAR_MEMORY, struct.pack(f"{self.byte_order.value}I", size)) + self._recv_dto(30.0) + + def program(self, size: int, data: bytes) -> int: + if size > 5: + raise ValueError("size must be less than 6") + if len(data) > 5: + raise ValueError("max data size is 5 bytes") + self._send_cro(COMMAND_CODE.PROGRAM, bytes([size]) + data) + resp = self._recv_dto(0.1) + # mta_addr_ext = resp[0] + mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0] + return mta_addr # type: ignore + + def program_6_bytes(self, data: bytes) -> int: + if len(data) != 6: + raise ValueError("data size must be 6 bytes") + self._send_cro(COMMAND_CODE.PROGRAM_6, data) + resp = self._recv_dto(0.1) + # mta_addr_ext = resp[0] + mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0] + return mta_addr # type: ignore + + def move_memory_block(self, size: int) -> None: + self._send_cro(COMMAND_CODE.MOVE, struct.pack(f"{self.byte_order.value}I", size)) + self._recv_dto(0.025) + + def diagnostic_service(self, service_num: int, data: bytes = b"") -> DiagnosticServiceReturn: + if service_num > 65535: + raise ValueError("service number must be less than 65536") + if len(data) > 4: + raise ValueError("max data size is 4 bytes") + self._send_cro(COMMAND_CODE.DIAG_SERVICE, struct.pack(f"{self.byte_order.value}H", service_num) + data) + resp = self._recv_dto(0.025) + return DiagnosticServiceReturn(length=resp[0], type=resp[1]) + + def action_service(self, service_num: int, data: bytes = b"") -> ActionServiceReturn: + if service_num > 65535: + raise ValueError("service number must be less than 65536") + if len(data) > 4: + raise ValueError("max data size is 4 bytes") + self._send_cro(COMMAND_CODE.ACTION_SERVICE, struct.pack(f"{self.byte_order.value}H", service_num) + data) + resp = self._recv_dto(0.025) + return ActionServiceReturn(length=resp[0], type=resp[1]) + + def test_availability(self, station_addr: int) -> None: + if station_addr > 65535: + raise ValueError("station address must be less than 65536") + # NOTE: station address is always little endian + self._send_cro(COMMAND_CODE.TEST, struct.pack(" None: + if mode > 255: + raise ValueError("mode must be less than 256") + self._send_cro(COMMAND_CODE.START_STOP_ALL, bytes([mode])) + self._recv_dto(0.025) + + def get_active_calibration_page(self): + self._send_cro(COMMAND_CODE.GET_ACTIVE_CAL_PAGE) + resp = self._recv_dto(0.025) + # cal_addr_ext = resp[0] + cal_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0] + return cal_addr + + def get_version(self, desired_version: float = 2.1) -> float: + major, minor = map(int, str(desired_version).split(".")) + self._send_cro(COMMAND_CODE.GET_CCP_VERSION, bytes([major, minor])) + resp = self._recv_dto(0.025) + return float(f"{resp[0]}.{resp[1]}") diff --git a/opendbc_repo/opendbc/car/chrysler/__init__.py b/opendbc_repo/opendbc/car/chrysler/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/chrysler/carcontroller.py b/opendbc_repo/opendbc/car/chrysler/carcontroller.py new file mode 100644 index 0000000000..8a2e9582ca --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/carcontroller.py @@ -0,0 +1,84 @@ +from opendbc.can import CANPacker +from opendbc.car import Bus, DT_CTRL +from opendbc.car.lateral import apply_meas_steer_torque_limits +from opendbc.car.chrysler import chryslercan +from opendbc.car.chrysler.values import RAM_CARS, CarControllerParams, ChryslerFlags +from opendbc.car.interfaces import CarControllerBase + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.apply_torque_last = 0 + + self.hud_count = 0 + self.last_lkas_falling_edge = 0 + self.lkas_control_bit_prev = False + self.last_button_frame = 0 + + self.packer = CANPacker(dbc_names[Bus.pt]) + self.params = CarControllerParams(CP) + + def update(self, CC, CS, now_nanos): + can_sends = [] + + lkas_active = CC.latActive and self.lkas_control_bit_prev + + # cruise buttons + if (self.frame - self.last_button_frame) * DT_CTRL > 0.05: + das_bus = 2 if self.CP.carFingerprint in RAM_CARS else 0 + + # ACC cancellation + if CC.cruiseControl.cancel: + self.last_button_frame = self.frame + can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter + 1, das_bus, cancel=True)) + + # ACC resume from standstill + elif CC.cruiseControl.resume: + self.last_button_frame = self.frame + can_sends.append(chryslercan.create_cruise_buttons(self.packer, CS.button_counter + 1, das_bus, resume=True)) + + # HUD alerts + if self.frame % 25 == 0: + if CS.lkas_car_model != -1: + can_sends.append(chryslercan.create_lkas_hud(self.packer, self.CP, lkas_active, CC.hudControl.visualAlert, + self.hud_count, CS.lkas_car_model, CS.auto_high_beam)) + self.hud_count += 1 + + # steering + if self.frame % self.params.STEER_STEP == 0: + + # TODO: can we make this more sane? why is it different for all the cars? + lkas_control_bit = self.lkas_control_bit_prev + if CS.out.vEgo > self.CP.minSteerSpeed: + lkas_control_bit = True + elif self.CP.flags & ChryslerFlags.HIGHER_MIN_STEERING_SPEED: + if CS.out.vEgo < (self.CP.minSteerSpeed - 3.0): + lkas_control_bit = False + elif self.CP.carFingerprint in RAM_CARS: + if CS.out.vEgo < (self.CP.minSteerSpeed - 0.5): + lkas_control_bit = False + + # EPS faults if LKAS re-enables too quickly + lkas_control_bit = lkas_control_bit and (self.frame - self.last_lkas_falling_edge > 200) + + if not lkas_control_bit and self.lkas_control_bit_prev: + self.last_lkas_falling_edge = self.frame + self.lkas_control_bit_prev = lkas_control_bit + + # steer torque + new_torque = int(round(CC.actuators.torque * self.params.STEER_MAX)) + apply_torque = apply_meas_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorqueEps, self.params) + if not lkas_active or not lkas_control_bit: + apply_torque = 0 + self.apply_torque_last = apply_torque + + can_sends.append(chryslercan.create_lkas_command(self.packer, self.CP, int(apply_torque), lkas_control_bit)) + + self.frame += 1 + + new_actuators = CC.actuators.as_builder() + new_actuators.torque = self.apply_torque_last / self.params.STEER_MAX + new_actuators.torqueOutputCan = self.apply_torque_last + + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/chrysler/carstate.py b/opendbc_repo/opendbc/car/chrysler/carstate.py new file mode 100644 index 0000000000..2eed3db9ee --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/carstate.py @@ -0,0 +1,107 @@ +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.chrysler.values import DBC, STEER_THRESHOLD, RAM_CARS +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarStateBase + +ButtonType = structs.CarState.ButtonEvent.Type + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + self.CP = CP + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + + self.auto_high_beam = 0 + self.button_counter = 0 + self.lkas_car_model = -1 + + if CP.carFingerprint in RAM_CARS: + self.shifter_values = can_define.dv["Transmission_Status"]["Gear_State"] + else: + self.shifter_values = can_define.dv["GEAR"]["PRNDL"] + + self.distance_button = 0 + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + + ret = structs.CarState() + + prev_distance_button = self.distance_button + self.distance_button = cp.vl["CRUISE_BUTTONS"]["ACC_Distance_Dec"] + + # lock info + ret.doorOpen = any([cp.vl["BCM_1"]["DOOR_OPEN_FL"], + cp.vl["BCM_1"]["DOOR_OPEN_FR"], + cp.vl["BCM_1"]["DOOR_OPEN_RL"], + cp.vl["BCM_1"]["DOOR_OPEN_RR"]]) + ret.seatbeltUnlatched = cp.vl["ORC_1"]["SEATBELT_DRIVER_UNLATCHED"] == 1 + + # brake pedal + ret.brake = 0 + ret.brakePressed = cp.vl["ESP_1"]['Brake_Pedal_State'] == 1 # Physical brake pedal switch + + # gas pedal + ret.gasPressed = cp.vl["ECM_5"]["Accelerator_Position"] > 1e-5 + + # car speed + if self.CP.carFingerprint in RAM_CARS: + ret.vEgoRaw = cp.vl["ESP_8"]["Vehicle_Speed"] * CV.KPH_TO_MS + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(cp.vl["Transmission_Status"]["Gear_State"], None)) + else: + ret.vEgoRaw = (cp.vl["SPEED_1"]["SPEED_LEFT"] + cp.vl["SPEED_1"]["SPEED_RIGHT"]) / 2. + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(cp.vl["GEAR"]["PRNDL"], None)) + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.standstill = not ret.vEgoRaw > 0.001 + + # button presses + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_stalk(200, cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 1, + cp.vl["STEERING_LEVERS"]["TURN_SIGNALS"] == 2) + ret.genericToggle = cp.vl["STEERING_LEVERS"]["HIGH_BEAM_PRESSED"] == 1 + + # steering wheel + ret.steeringAngleDeg = cp.vl["STEERING"]["STEERING_ANGLE"] + cp.vl["STEERING"]["STEERING_ANGLE_HP"] + ret.steeringRateDeg = cp.vl["STEERING"]["STEERING_RATE"] + ret.steeringTorque = cp.vl["EPS_2"]["COLUMN_TORQUE"] + ret.steeringTorqueEps = cp.vl["EPS_2"]["EPS_TORQUE_MOTOR"] + ret.steeringPressed = abs(ret.steeringTorque) > STEER_THRESHOLD + + # cruise state + cp_cruise = cp_cam if self.CP.carFingerprint in RAM_CARS else cp + + ret.cruiseState.available = cp_cruise.vl["DAS_3"]["ACC_AVAILABLE"] == 1 + ret.cruiseState.enabled = cp_cruise.vl["DAS_3"]["ACC_ACTIVE"] == 1 + ret.cruiseState.speed = cp_cruise.vl["DAS_4"]["ACC_SET_SPEED_KPH"] * CV.KPH_TO_MS + ret.cruiseState.nonAdaptive = cp_cruise.vl["DAS_4"]["ACC_STATE"] in (1, 2) # 1 NormalCCOn and 2 NormalCCSet + ret.cruiseState.standstill = cp_cruise.vl["DAS_3"]["ACC_STANDSTILL"] == 1 + ret.accFaulted = cp_cruise.vl["DAS_3"]["ACC_FAULTED"] != 0 + + if self.CP.carFingerprint in RAM_CARS: + # Auto High Beam isn't Located in this message on chrysler or jeep currently located in 729 message + self.auto_high_beam = cp_cam.vl["DAS_6"]['AUTO_HIGH_BEAM_ON'] + ret.steerFaultTemporary = cp.vl["EPS_3"]["DASM_FAULT"] == 1 + else: + ret.steerFaultTemporary = cp.vl["EPS_2"]["LKAS_TEMPORARY_FAULT"] == 1 + ret.steerFaultPermanent = cp.vl["EPS_2"]["LKAS_STATE"] == 4 + + # blindspot sensors + if self.CP.enableBsm: + ret.leftBlindspot = cp.vl["BSM_1"]["LEFT_STATUS"] == 1 + ret.rightBlindspot = cp.vl["BSM_1"]["RIGHT_STATUS"] == 1 + + self.lkas_car_model = cp_cam.vl["DAS_6"]["CAR_MODEL"] + self.button_counter = cp.vl["CRUISE_BUTTONS"]["COUNTER"] + + ret.buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/chrysler/chryslercan.py b/opendbc_repo/opendbc/car/chrysler/chryslercan.py new file mode 100644 index 0000000000..677582ef40 --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/chryslercan.py @@ -0,0 +1,113 @@ +from opendbc.car import structs +from opendbc.car.crc import CRC8J1850 +from opendbc.car.chrysler.values import RAM_CARS + +GearShifter = structs.CarState.GearShifter +VisualAlert = structs.CarControl.HUDControl.VisualAlert + + +def create_lkas_hud(packer, CP, lkas_active, hud_alert, hud_count, car_model, auto_high_beam): + # LKAS_HUD - Controls what lane-keeping icon is displayed + + # == Color == + # 0 hidden? + # 1 white + # 2 green + # 3 ldw + + # == Lines == + # 03 white Lines + # 04 grey lines + # 09 left lane close + # 0A right lane close + # 0B left Lane very close + # 0C right Lane very close + # 0D left cross cross + # 0E right lane cross + + # == Alerts == + # 7 Normal + # 6 lane departure place hands on wheel + + color = 2 if lkas_active else 1 + lines = 3 if lkas_active else 0 + alerts = 7 if lkas_active else 0 + + if hud_count < (1 * 4): # first 3 seconds, 4Hz + alerts = 1 + + if hud_alert in (VisualAlert.ldw, VisualAlert.steerRequired): + color = 4 + lines = 0 + alerts = 6 + + values = { + "LKAS_ICON_COLOR": color, + "CAR_MODEL": car_model, + "LKAS_LANE_LINES": lines, + "LKAS_ALERTS": alerts, + } + + if CP.carFingerprint in RAM_CARS: + values['AUTO_HIGH_BEAM_ON'] = auto_high_beam + + return packer.make_can_msg("DAS_6", 0, values) + + +def create_lkas_command(packer, CP, apply_torque, lkas_control_bit): + # LKAS_COMMAND Lane-keeping signal to turn the wheel + enabled_val = 2 if CP.carFingerprint in RAM_CARS else 1 + values = { + "STEERING_TORQUE": apply_torque, + "LKAS_CONTROL_BIT": enabled_val if lkas_control_bit else 0, + } + return packer.make_can_msg("LKAS_COMMAND", 0, values) + + +def create_cruise_buttons(packer, frame, bus, cancel=False, resume=False): + values = { + "ACC_Cancel": cancel, + "ACC_Resume": resume, + "COUNTER": frame % 0x10, + } + return packer.make_can_msg("CRUISE_BUTTONS", bus, values) + + +def chrysler_checksum(address: int, sig, d: bytearray) -> int: + checksum = 0xFF + for j in range(len(d) - 1): + curr = d[j] + shift = 0x80 + for _ in range(8): + bit_sum = curr & shift + temp_chk = checksum & 0x80 + if bit_sum: + bit_sum = 0x1C + if temp_chk: + bit_sum = 1 + checksum = (checksum << 1) & 0xFF + temp_chk = checksum | 1 + bit_sum ^= temp_chk + else: + if temp_chk: + bit_sum = 0x1D + checksum = (checksum << 1) & 0xFF + bit_sum ^= checksum + checksum = bit_sum & 0xFF + shift >>= 1 + return (~checksum) & 0xFF + + +def fca_giorgio_checksum(address: int, sig, d: bytearray) -> int: + crc = 0 + for i in range(len(d) - 1): + crc ^= d[i] + crc = CRC8J1850[crc] + if address == 0xDE: + return crc ^ 0x10 + elif address == 0x106: + return crc ^ 0xF6 + elif address == 0x122: + return crc ^ 0xF1 + else: + return crc ^ 0x0A diff --git a/opendbc_repo/opendbc/car/chrysler/fingerprints.py b/opendbc_repo/opendbc/car/chrysler/fingerprints.py new file mode 100644 index 0000000000..7cd90dcb13 --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/fingerprints.py @@ -0,0 +1,783 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.chrysler.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.CHRYSLER_PACIFICA_2018: { + (Ecu.combinationMeter, 0x742, None): [ + b'68227902AF', + b'68227902AG', + b'68227902AH', + b'68227905AG', + b'68360252AC', + ], + (Ecu.srs, 0x744, None): [ + b'68211617AF', + b'68211617AG', + b'68358974AC', + b'68405937AA', + ], + (Ecu.abs, 0x747, None): [ + b'68222747AG', + b'68330876AA', + b'68330876AB', + b'68352227AA', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672758AA', + b'04672758AB', + b'68226356AF', + b'68226356AH', + b'68226356AI', + ], + (Ecu.eps, 0x75a, None): [ + b'68288891AE', + b'68378884AA', + b'68525338AA', + b'68525338AB', + ], + (Ecu.engine, 0x7e0, None): [ + b'68267018AO ', + b'68267020AJ ', + b'68303534AG ', + b'68303534AJ ', + b'68340762AD ', + b'68340764AD ', + b'68352652AE ', + b'68352654AE ', + b'68366851AH ', + b'68366853AE ', + b'68366853AG ', + b'68372861AF ', + ], + (Ecu.transmission, 0x7e1, None): [ + b'68277370AJ', + b'68277370AM', + b'68277372AD', + b'68277372AE', + b'68277372AN', + b'68277374AA', + b'68277374AB', + b'68277374AD', + b'68277374AN', + b'68367471AC', + b'68367471AD', + b'68380571AB', + ], + }, + CAR.CHRYSLER_PACIFICA_2020: { + (Ecu.combinationMeter, 0x742, None): [ + b'68405327AC', + b'68436233AB', + b'68436233AC', + b'68436234AB', + b'68436250AE', + b'68529067AA', + b'68594993AB', + b'68594994AB', + ], + (Ecu.srs, 0x744, None): [ + b'68405565AB', + b'68405565AC', + b'68444299AC', + b'68480707AC', + b'68480708AC', + b'68526663AB', + ], + (Ecu.abs, 0x747, None): [ + b'68397394AA', + b'68433480AB', + b'68453575AF', + b'68577676AA', + b'68593395AA', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672758AA', + b'04672758AB', + b'68417813AF', + b'68540436AA', + b'68540436AB', + b'68540436AC', + b'68540436AD', + b'68598670AB', + b'68598670AC', + ], + (Ecu.eps, 0x75a, None): [ + b'68416742AA', + b'68460393AA', + b'68460393AB', + b'68494461AB', + b'68494461AC', + b'68524936AA', + b'68524936AB', + b'68525338AB', + b'68594337AB', + b'68594340AB', + ], + (Ecu.engine, 0x7e0, None): [ + b'68413871AD ', + b'68413871AE ', + b'68413871AH ', + b'68413871AI ', + b'68413871AJ ', + b'68413873AH ', + b'68413873AI ', + b'68443120AE ', + b'68443123AC ', + b'68443125AC ', + b'68496647AI ', + b'68496647AJ ', + b'68496650AH ', + b'68496650AI ', + b'68496650AL ', + b'68496652AH ', + b'68526752AD ', + b'68526752AE ', + b'68526754AD ', + b'68526754AE ', + b'68536264AE ', + b'68700304AB ', + b'68700306AB ', + ], + (Ecu.transmission, 0x7e1, None): [ + b'68414271AC', + b'68414271AD', + b'68414275AC', + b'68414275AD', + b'68443154AB', + b'68443154AC', + b'68443155AC', + b'68443158AB', + b'68501050AD', + b'68501051AD', + b'68501055AD', + b'68527221AB', + b'68527223AB', + b'68586231AD', + b'68586233AD', + ], + }, + CAR.CHRYSLER_PACIFICA_2018_HYBRID: { + (Ecu.combinationMeter, 0x742, None): [ + b'68239262AH', + b'68239262AI', + b'68239262AJ', + b'68239263AH', + b'68239263AJ', + b'68358439AE', + b'68358439AG', + ], + (Ecu.srs, 0x744, None): [ + b'68238840AH', + b'68358990AC', + b'68405939AA', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672758AA', + b'68226356AI', + ], + (Ecu.eps, 0x75a, None): [ + b'68288309AC', + b'68288309AD', + b'68525339AA', + ], + (Ecu.engine, 0x7e0, None): [ + b'68277480AV ', + b'68277480AX ', + b'68277480AZ ', + b'68366580AI ', + b'68366580AK ', + b'68366580AM ', + ], + (Ecu.hybrid, 0x7e2, None): [ + b'05190175BF', + b'05190175BH', + b'05190226AI', + b'05190226AK', + b'05190226AM', + ], + }, + CAR.CHRYSLER_PACIFICA_2019_HYBRID: { + (Ecu.combinationMeter, 0x742, None): [ + b'68405292AC', + b'68434956AC', + b'68434956AD', + b'68434960AE', + b'68434960AF', + b'68529064AB', + b'68594990AB', + b'68594990AD', + b'68594990AE', + b'68594991AB', + ], + (Ecu.srs, 0x744, None): [ + b'68405567AB', + b'68405567AC', + b'68453076AD', + b'68480710AC', + b'68526665AB', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672758AB', + b'68417813AF', + b'68540436AA', + b'68540436AB', + b'68540436AC', + b'68540436AD', + b'68598670AB', + b'68598670AC', + b'68645752AA', + ], + (Ecu.eps, 0x75a, None): [ + b'68416741AA', + b'68460392AA', + b'68525339AA', + b'68525339AB', + b'68594341AB', + b'68594341AC', + ], + (Ecu.engine, 0x7e0, None): [ + b'05190392AB ', + b'68416680AD ', + b'68416680AE ', + b'68416680AF ', + b'68416680AG ', + b'68444228AC ', + b'68444228AD ', + b'68444228AE ', + b'68444228AF ', + b'68499122AD ', + b'68499122AE ', + b'68499122AF ', + b'68526772AD ', + b'68526772AH ', + b'68599493AC ', + b'68657433AA ', + b'68700317AC ', + ], + (Ecu.hybrid, 0x7e2, None): [ + b'05185116AF', + b'05185116AJ', + b'05185116AK', + b'05185116AL', + b'05190240AP', + b'05190240AQ', + b'05190240AR', + b'05190265AG', + b'05190265AH', + b'05190289AE', + b'68540977AH', + b'68540977AK', + b'68540977AL', + b'68597647AE', + b'68597647AF', + b'68632416AB', + b'68632416AC', + b'68676877AB', + ], + }, + CAR.JEEP_GRAND_CHEROKEE: { + (Ecu.combinationMeter, 0x742, None): [ + b'68243549AG', + b'68302211AC', + b'68302212AD', + b'68302214AC', + b'68302223AC', + b'68302246AC', + b'68331511AC', + b'68331574AC', + b'68331687AC', + b'68331690AC', + b'68340272AD', + ], + (Ecu.srs, 0x744, None): [ + b'68309533AA', + b'68316742AB', + b'68355363AB', + ], + (Ecu.abs, 0x747, None): [ + b'68252642AG', + b'68306178AD', + b'68336275AB', + b'68336276AB', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672627AB', + b'68251506AF', + b'68332015AB', + ], + (Ecu.eps, 0x75a, None): [ + b'68276201AG', + b'68321644AB', + b'68321644AC', + b'68321646AC', + b'68321648AC', + b'68321650AC', + ], + (Ecu.engine, 0x7e0, None): [ + b'05035920AE ', + b'68252272AG ', + b'68284455AI ', + b'68284456AI ', + b'68284456AJ ', + b'68284477AF ', + b'68325564AH ', + b'68325564AI ', + b'68325565AH ', + b'68325565AI ', + b'68325565AJ ', + b'68325618AD ', + ], + (Ecu.transmission, 0x7e1, None): [ + b'05035517AH', + b'68253222AF', + b'68311218AC', + b'68311218AD', + b'68311223AF', + b'68311223AG', + b'68361911AE', + b'68361911AF', + b'68361911AH', + b'68361914AE', + b'68361916AD', + ], + }, + CAR.JEEP_GRAND_CHEROKEE_2019: { + (Ecu.combinationMeter, 0x742, None): [ + b'68402703AB', + b'68402704AB', + b'68402707AB', + b'68402708AB', + b'68402714AB', + b'68402971AD', + b'68454144AD', + b'68454145AB', + b'68454152AB', + b'68454156AB', + b'68516650AB', + b'68516651AB', + b'68516669AB', + b'68516671AB', + b'68516683AB', + ], + (Ecu.srs, 0x744, None): [ + b'68355363AB', + b'68355364AB', + ], + (Ecu.abs, 0x747, None): [ + b'68408639AC', + b'68408639AD', + b'68499978AB', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672788AA', + b'68456722AC', + ], + (Ecu.eps, 0x75a, None): [ + b'68417279AA', + b'68417280AA', + b'68417281AA', + b'68453431AA', + b'68453433AA', + b'68453435AA', + b'68499171AA', + b'68499171AB', + b'68501183AA', + b'68501186AA', + ], + (Ecu.engine, 0x7e0, None): [ + b'05035674AB ', + b'68412635AE ', + b'68412635AG ', + b'68412660AD ', + b'68412660AF ', + b'68422860AB', + b'68449435AE ', + b'68496223AA ', + b'68504959AD ', + b'68504959AE ', + b'68504960AD ', + b'68504993AC ', + ], + (Ecu.transmission, 0x7e1, None): [ + b'05035707AA', + b'68419672AC', + b'68419678AB', + b'68423905AB', + b'68449258AC', + b'68495807AA', + b'68495807AB', + b'68503641AC', + b'68503644AC', + b'68503664AC', + ], + }, + CAR.RAM_1500_5TH_GEN: { + (Ecu.combinationMeter, 0x742, None): [ + b'68294051AG', + b'68294051AI', + b'68294052AG', + b'68294052AH', + b'68294059AI', + b'68294063AG', + b'68294063AH', + b'68294063AI', + b'68434846AC', + b'68434847AC', + b'68434849AC', + b'68434850AC', + b'68434855AC', + b'68434856AC', + b'68434858AC', + b'68434859AC', + b'68434860AC', + b'68453471AD', + b'68453483AC', + b'68453483AD', + b'68453487AD', + b'68453491AC', + b'68453491AD', + b'68453499AD', + b'68453502AC', + b'68453503AC', + b'68453503AD', + b'68453505AC', + b'68453505AD', + b'68453511AC', + b'68453513AC', + b'68453513AD', + b'68453514AD', + b'68505633AB', + b'68510277AG', + b'68510277AH', + b'68510280AG', + b'68510280AH', + b'68510282AG', + b'68510282AH', + b'68510283AG', + b'68527346AE', + b'68527361AD', + b'68527375AD', + b'68527381AD', + b'68527381AE', + b'68527382AE', + b'68527383AD', + b'68527383AE', + b'68527387AE', + b'68527397AD', + b'68527403AC', + b'68527403AD', + b'68527404AD', + b'68546047AF', + b'68631938AA', + b'68631939AA', + b'68631940AA', + b'68631940AB', + b'68631941AB', + b'68631942AA', + b'68631943AB', + ], + (Ecu.srs, 0x744, None): [ + b'68428609AB', + b'68441329AA', + b'68441329AB', + b'68473844AB', + b'68490898AA', + b'68500728AA', + b'68615033AA', + b'68615034AA', + ], + (Ecu.abs, 0x747, None): [ + b'68292406AG', + b'68292406AH', + b'68432418AB', + b'68432418AC', + b'68432418AD', + b'68436004AD', + b'68436004AE', + b'68438454AC', + b'68438454AD', + b'68438456AE', + b'68438456AF', + b'68535469AB', + b'68535470AC', + b'68548900AB', + b'68548900AC', + b'68586307AB', + b'68586307AC', + b'68728724AA', + b'68728727AA', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672892AB', + b'04672932AB', + b'04672932AC', + b'22DTRHD_AA', + b'68320950AH', + b'68320950AI', + b'68320950AJ', + b'68320950AL', + b'68320950AM', + b'68454268AB', + b'68454268AC', + b'68475160AE', + b'68475160AF', + b'68475160AG', + ], + (Ecu.eps, 0x75a, None): [ + b'21590101AA', + b'21590101AB', + b'22490101AB', + b'68273275AF', + b'68273275AG', + b'68273275AH', + b'68312176AE', + b'68312176AF', + b'68312176AG', + b'68440789AC', + b'68466110AA', + b'68466110AB', + b'68466113AA', + b'68466116AA', + b'68469901AA', + b'68469904AA', + b'68469907AA', + b'68522583AA', + b'68522583AB', + b'68522584AA', + b'68522585AB', + b'68552788AA', + b'68552789AA', + b'68552790AA', + b'68552791AB', + b'68552794AA', + b'68552794AD', + b'68585106AB', + b'68585107AB', + b'68585108AB', + b'68585109AB', + b'68585112AB', + ], + (Ecu.engine, 0x7e0, None): [ + b'05035699AG ', + b'05035841AC ', + b'05035841AD ', + b'05036026AB ', + b'05036030AC ', + b'05036065AE ', + b'05036066AE ', + b'05036067AE ', + b'05036193AA ', + b'05149368AA ', + b'05149374AA ', + b'05149591AD ', + b'05149591AE ', + b'05149592AE ', + b'05149599AE ', + b'05149600AD ', + b'05149600AE ', + b'05149605AE ', + b'05149846AA ', + b'05149848AA ', + b'05149848AC ', + b'05190341AD', + b'05190346AD', + b'68378695AI ', + b'68378695AJ ', + b'68378695AK ', + b'68378696AJ ', + b'68378696AK ', + b'68378701AI ', + b'68378702AI ', + b'68378710AL ', + b'68378742AI ', + b'68378742AK ', + b'68378743AI ', + b'68378743AM ', + b'68378748AL ', + b'68378758AM ', + b'68378759AM ', + b'68448163AJ', + b'68448163AK', + b'68448163AL', + b'68448165AG', + b'68448165AK', + b'68455111AC ', + b'68455119AC ', + b'68455137AC ', + b'68455142AC ', + b'68455142AE ', + b'68455145AC ', + b'68455145AE ', + b'68455146AC ', + b'68460927AA ', + b'68467909AB ', + b'68467909AC ', + b'68467915AC ', + b'68467916AC ', + b'68467936AC ', + b'68500630AD', + b'68500630AE', + b'68500630AF', + b'68500631AE', + b'68502719AC ', + b'68502722AC ', + b'68502733AC ', + b'68502734AF ', + b'68502737AF ', + b'68502740AF ', + b'68502741AF ', + b'68502742AC ', + b'68502742AF ', + b'68539650AD', + b'68539650AF', + b'68539651AD', + b'68586101AA ', + b'68586102AA ', + b'68586105AB ', + b'68629917AC ', + b'68629919AC ', + b'68629919AD ', + b'68629922AC ', + b'68629925AC ', + b'68629926AC ', + ], + (Ecu.transmission, 0x7e1, None): [ + b'05035706AD', + b'05035842AB', + b'05036069AA', + b'05036181AA', + b'05149536AC', + b'05149537AC', + b'05149543AC', + b'68360078AL', + b'68360080AL', + b'68360080AM', + b'68360081AM', + b'68360081AN', + b'68360085AH', + b'68360085AJ', + b'68360085AK', + b'68360085AL', + b'68360085AO', + b'68360086AH', + b'68360086AK', + b'68360086AN', + b'68384328AD', + b'68384332AD', + b'68445531AC', + b'68445532AB', + b'68445533AB', + b'68445536AB', + b'68445537AB', + b'68466081AB', + b'68466086AB', + b'68466087AB', + b'68484466AC', + b'68484467AC', + b'68484471AC', + b'68502994AC', + b'68502994AD', + b'68502996AD', + b'68520867AE', + b'68520867AF', + b'68520870AC', + b'68520871AC', + b'68528325AE', + b'68540431AB', + b'68540433AB', + b'68551676AA', + b'68629935AB', + b'68629936AC', + ], + }, + CAR.RAM_HD_5TH_GEN: { + (Ecu.combinationMeter, 0x742, None): [ + b'68361606AH', + b'68437735AC', + b'68492693AD', + b'68525485AB', + b'68525487AB', + b'68525498AB', + b'68528791AF', + b'68628474AB', + ], + (Ecu.srs, 0x744, None): [ + b'68399794AC', + b'68428503AA', + b'68428505AA', + b'68428507AA', + ], + (Ecu.abs, 0x747, None): [ + b'68334977AH', + b'68455481AC', + b'68504022AA', + b'68504022AB', + b'68504022AC', + b'68530686AB', + b'68530686AC', + b'68544596AC', + b'68641704AA', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'04672895AB', + b'04672934AB', + b'56029827AG', + b'56029827AH', + b'68462657AE', + b'68484694AD', + b'68484694AE', + b'68615489AB', + ], + (Ecu.eps, 0x761, None): [ + b'68421036AC', + b'68507906AB', + b'68534023AC', + ], + (Ecu.engine, 0x7e0, None): [ + b'52370131AF', + b'52370231AF', + b'52370231AG', + b'52370491AA', + b'52370931CT', + b'52401032AE', + b'52421132AF', + b'52421332AF', + b'68527616AD ', + b'M2370131MB', + b'M2421132MB', + ], + }, + CAR.DODGE_DURANGO: { + (Ecu.combinationMeter, 0x742, None): [ + b'68454261AD', + b'68471535AE', + ], + (Ecu.srs, 0x744, None): [ + b'68355362AB', + b'68492238AD', + ], + (Ecu.abs, 0x747, None): [ + b'68408639AD', + b'68499978AB', + ], + (Ecu.fwdRadar, 0x753, None): [ + b'68440581AE', + b'68456722AC', + ], + (Ecu.eps, 0x75a, None): [ + b'68453435AA', + b'68498477AA', + ], + (Ecu.engine, 0x7e0, None): [ + b'05035786AE ', + b'68449476AE ', + ], + (Ecu.transmission, 0x7e1, None): [ + b'05035826AC', + b'68449265AC', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/chrysler/interface.py b/opendbc_repo/opendbc/car/chrysler/interface.py new file mode 100755 index 0000000000..0be2ccacb0 --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/interface.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +from opendbc.car import get_safety_config, structs +from opendbc.car.chrysler.carcontroller import CarController +from opendbc.car.chrysler.carstate import CarState +from opendbc.car.chrysler.radar_interface import RadarInterface +from opendbc.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags, ChryslerSafetyFlags +from opendbc.car.interfaces import CarInterfaceBase + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "chrysler" + ret.dashcamOnly = candidate in RAM_HD + + # radar parsing needs some work, see https://github.com/commaai/openpilot/issues/26842 + ret.radarUnavailable = True # Bus.radar not in DBC[candidate][Bus.radar] + ret.steerActuatorDelay = 0.1 + ret.steerLimitTimer = 0.4 + + # safety config + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.chrysler)] + if candidate in RAM_HD: + ret.safetyConfigs[0].safetyParam |= ChryslerSafetyFlags.RAM_HD.value + elif candidate in RAM_DT: + ret.safetyConfigs[0].safetyParam |= ChryslerSafetyFlags.RAM_DT.value + + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + if candidate not in RAM_CARS: + # Newer FW versions standard on the following platforms, or flashed by a dealer onto older platforms have a higher minimum steering speed. + new_eps_platform = candidate in (CAR.CHRYSLER_PACIFICA_2019_HYBRID, CAR.CHRYSLER_PACIFICA_2020, CAR.JEEP_GRAND_CHEROKEE_2019, CAR.DODGE_DURANGO) + new_eps_firmware = any(fw.ecu == 'eps' and fw.fwVersion[:4] >= b"6841" for fw in car_fw) + if new_eps_platform or new_eps_firmware: + ret.flags |= ChryslerFlags.HIGHER_MIN_STEERING_SPEED.value + + # Chrysler + if candidate in (CAR.CHRYSLER_PACIFICA_2018, CAR.CHRYSLER_PACIFICA_2018_HYBRID, CAR.CHRYSLER_PACIFICA_2019_HYBRID, + CAR.CHRYSLER_PACIFICA_2020, CAR.DODGE_DURANGO): + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] + ret.lateralTuning.pid.kf = 0.00006 + + # Jeep + elif candidate in (CAR.JEEP_GRAND_CHEROKEE, CAR.JEEP_GRAND_CHEROKEE_2019): + ret.steerActuatorDelay = 0.2 + + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] + ret.lateralTuning.pid.kf = 0.00006 + + # Ram + elif candidate == CAR.RAM_1500_5TH_GEN: + ret.steerActuatorDelay = 0.2 + ret.wheelbase = 3.88 + # Older EPS FW allow steer to zero + if any(fw.ecu == 'eps' and b"68" < fw.fwVersion[:4] <= b"6831" for fw in car_fw): + ret.minSteerSpeed = 0. + + elif candidate == CAR.RAM_HD_5TH_GEN: + ret.steerActuatorDelay = 0.2 + + else: + raise ValueError(f"Unsupported car: {candidate}") + + if ret.flags & ChryslerFlags.HIGHER_MIN_STEERING_SPEED: + # TODO: allow these cars to steer down to 13 m/s if already engaged. + # TODO: Durango 2020 may be able to steer to zero once above 38 kph + ret.minSteerSpeed = 17.5 # m/s 17 on the way up, 13 on the way down once engaged. + + ret.centerToFront = ret.wheelbase * 0.44 + ret.enableBsm = 720 in fingerprint[0] + + return ret diff --git a/opendbc_repo/opendbc/car/chrysler/radar_interface.py b/opendbc_repo/opendbc/car/chrysler/radar_interface.py new file mode 100755 index 0000000000..4ad4afa1d0 --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/radar_interface.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import RadarInterfaceBase +from opendbc.car.chrysler.values import DBC + +RADAR_MSGS_C = list(range(0x2c2, 0x2d4+2, 2)) # c_ messages 706,...,724 +RADAR_MSGS_D = list(range(0x2a2, 0x2b4+2, 2)) # d_ messages +LAST_MSG = max(RADAR_MSGS_C + RADAR_MSGS_D) +NUMBER_MSGS = len(RADAR_MSGS_C) + len(RADAR_MSGS_D) + + +def _create_radar_can_parser(car_fingerprint): + if Bus.radar not in DBC[car_fingerprint]: + return None + + msg_n = len(RADAR_MSGS_C) + # list of [(signal name, message name or number), (...)] + # [('RADAR_STATE', 1024), + # ('LONG_DIST', 1072), + # ('LONG_DIST', 1073), + # ('LONG_DIST', 1074), + # ('LONG_DIST', 1075), + + messages = list(zip(RADAR_MSGS_C + + RADAR_MSGS_D, + [20] * msg_n + # 20Hz (0.05s) + [20] * msg_n, strict=True)) # 20Hz (0.05s) + + return CANParser(DBC[car_fingerprint][Bus.radar], messages, 1) + + +def _address_to_track(address): + if address in RADAR_MSGS_C: + return (address - RADAR_MSGS_C[0]) // 2 + if address in RADAR_MSGS_D: + return (address - RADAR_MSGS_D[0]) // 2 + raise ValueError("radar received unexpected address %d" % address) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + self.rcp = _create_radar_can_parser(CP.carFingerprint) + self.updated_messages = set() + self.trigger_msg = LAST_MSG + + def update(self, can_strings): + if self.rcp is None or self.CP.radarUnavailable: + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + + ret = structs.RadarData() + if not self.rcp.can_valid: + ret.errors.canError = True + + for ii in self.updated_messages: # ii should be the message ID as a number + cpt = self.rcp.vl[ii] + trackId = _address_to_track(ii) + + if trackId not in self.pts: + self.pts[trackId] = structs.RadarData.RadarPoint() + self.pts[trackId].trackId = trackId + self.pts[trackId].aRel = float('nan') + self.pts[trackId].yvRel = float('nan') + self.pts[trackId].measured = True + + if 'LONG_DIST' in cpt: # c_* message + self.pts[trackId].dRel = cpt['LONG_DIST'] # from front of car + # our lat_dist is positive to the right in car's frame. + # TODO what does yRel want? + self.pts[trackId].yRel = cpt['LAT_DIST'] # in car frame's y axis, left is positive + else: # d_* message + self.pts[trackId].vRel = cpt['REL_SPEED'] + + # We want a list, not a dictionary. Filter out LONG_DIST==0 because that means it's not valid. + ret.points = [x for x in self.pts.values() if x.dRel != 0] + + self.updated_messages.clear() + return ret diff --git a/opendbc_repo/opendbc/car/chrysler/values.py b/opendbc_repo/opendbc/car/chrysler/values.py new file mode 100644 index 0000000000..232e5712e3 --- /dev/null +++ b/opendbc_repo/opendbc/car/chrysler/values.py @@ -0,0 +1,160 @@ +from enum import IntFlag +from dataclasses import dataclass, field + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarHarness, CarDocs, CarParts +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, p16 + +Ecu = CarParams.Ecu + + +class ChryslerSafetyFlags(IntFlag): + RAM_DT = 1 + RAM_HD = 2 + + +class ChryslerFlags(IntFlag): + # Detected flags + HIGHER_MIN_STEERING_SPEED = 1 + + +@dataclass +class ChryslerCarDocs(CarDocs): + package: str = "Adaptive Cruise Control (ACC)" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) + + +@dataclass +class ChryslerPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: { + Bus.pt: 'chrysler_pacifica_2017_hybrid_generated', + Bus.radar: 'chrysler_pacifica_2017_hybrid_private_fusion', + }) + + +@dataclass(frozen=True) +class ChryslerCarSpecs(CarSpecs): + minSteerSpeed: float = 3.8 # m/s + + +class CAR(Platforms): + # Chrysler + CHRYSLER_PACIFICA_2018_HYBRID = ChryslerPlatformConfig( + [ChryslerCarDocs("Chrysler Pacifica Hybrid 2017-18")], + ChryslerCarSpecs(mass=2242., wheelbase=3.089, steerRatio=16.2), + ) + CHRYSLER_PACIFICA_2019_HYBRID = ChryslerPlatformConfig( + [ChryslerCarDocs("Chrysler Pacifica Hybrid 2019-25")], + CHRYSLER_PACIFICA_2018_HYBRID.specs, + ) + CHRYSLER_PACIFICA_2018 = ChryslerPlatformConfig( + [ChryslerCarDocs("Chrysler Pacifica 2017-18")], + CHRYSLER_PACIFICA_2018_HYBRID.specs, + ) + CHRYSLER_PACIFICA_2020 = ChryslerPlatformConfig( + [ + ChryslerCarDocs("Chrysler Pacifica 2019-20"), + ChryslerCarDocs("Chrysler Pacifica 2021-23", package="All"), + ], + CHRYSLER_PACIFICA_2018_HYBRID.specs, + ) + + # Dodge + DODGE_DURANGO = ChryslerPlatformConfig( + [ChryslerCarDocs("Dodge Durango 2020-21")], + CHRYSLER_PACIFICA_2018_HYBRID.specs, + ) + + # Jeep + JEEP_GRAND_CHEROKEE = ChryslerPlatformConfig( # includes 2017 Trailhawk + [ChryslerCarDocs("Jeep Grand Cherokee 2016-18", video="https://www.youtube.com/watch?v=eLR9o2JkuRk")], + ChryslerCarSpecs(mass=1778., wheelbase=2.71, steerRatio=16.7), + ) + + JEEP_GRAND_CHEROKEE_2019 = ChryslerPlatformConfig( # includes 2020 Trailhawk + [ChryslerCarDocs("Jeep Grand Cherokee 2019-21", video="https://www.youtube.com/watch?v=jBe4lWnRSu4")], + JEEP_GRAND_CHEROKEE.specs, + ) + + # Ram + RAM_1500_5TH_GEN = ChryslerPlatformConfig( + [ChryslerCarDocs("Ram 1500 2019-24", car_parts=CarParts.common([CarHarness.ram]))], + ChryslerCarSpecs(mass=2493., wheelbase=3.88, steerRatio=16.3, minSteerSpeed=14.5), + {Bus.pt: 'chrysler_ram_dt_generated'}, + ) + RAM_HD_5TH_GEN = ChryslerPlatformConfig( + [ + ChryslerCarDocs("Ram 2500 2020-24", car_parts=CarParts.common([CarHarness.ram])), + ChryslerCarDocs("Ram 3500 2019-22", car_parts=CarParts.common([CarHarness.ram])), + ], + ChryslerCarSpecs(mass=3405., wheelbase=3.785, steerRatio=15.61, minSteerSpeed=16.), + {Bus.pt: 'chrysler_ram_hd_generated'}, + ) + + +class CarControllerParams: + def __init__(self, CP): + self.STEER_STEP = 2 # 50 Hz + self.STEER_ERROR_MAX = 80 + if CP.carFingerprint in RAM_HD: + self.STEER_DELTA_UP = 14 + self.STEER_DELTA_DOWN = 14 + self.STEER_MAX = 361 # higher than this faults the EPS + elif CP.carFingerprint in RAM_DT: + self.STEER_DELTA_UP = 6 + self.STEER_DELTA_DOWN = 6 + self.STEER_MAX = 261 # EPS allows more, up to 350? + else: + self.STEER_DELTA_UP = 3 + self.STEER_DELTA_DOWN = 3 + self.STEER_MAX = 261 # higher than this faults the EPS + + +STEER_THRESHOLD = 120 + +RAM_DT = {CAR.RAM_1500_5TH_GEN, } +RAM_HD = {CAR.RAM_HD_5TH_GEN, } +RAM_CARS = RAM_DT | RAM_HD + + +CHRYSLER_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(0xf132) +CHRYSLER_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(0xf132) + +CHRYSLER_SOFTWARE_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.SYSTEM_SUPPLIER_ECU_SOFTWARE_NUMBER) +CHRYSLER_SOFTWARE_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.SYSTEM_SUPPLIER_ECU_SOFTWARE_NUMBER) + +CHRYSLER_RX_OFFSET = -0x280 + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + Request( + [CHRYSLER_VERSION_REQUEST], + [CHRYSLER_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.eps, Ecu.srs, Ecu.fwdRadar, Ecu.combinationMeter], + rx_offset=CHRYSLER_RX_OFFSET, + bus=0, + ), + Request( + [CHRYSLER_VERSION_REQUEST], + [CHRYSLER_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.hybrid, Ecu.engine, Ecu.transmission], + bus=0, + ), + Request( + [CHRYSLER_SOFTWARE_VERSION_REQUEST], + [CHRYSLER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.engine, Ecu.transmission], + bus=0, + ), + ], + extra_ecus=[ + (Ecu.abs, 0x7e4, None), # alt address for abs on hybrids, NOTE: not on all hybrid platforms + ], +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/common/__init__.py b/opendbc_repo/opendbc/car/common/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/common/basedir.py b/opendbc_repo/opendbc/car/common/basedir.py new file mode 100644 index 0000000000..6b4811e53c --- /dev/null +++ b/opendbc_repo/opendbc/car/common/basedir.py @@ -0,0 +1,4 @@ +import os + + +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")) diff --git a/opendbc_repo/opendbc/car/common/conversions.py b/opendbc_repo/opendbc/car/common/conversions.py new file mode 100644 index 0000000000..111c928842 --- /dev/null +++ b/opendbc_repo/opendbc/car/common/conversions.py @@ -0,0 +1,20 @@ +import numpy as np + + +class Conversions: + # Speed + MPH_TO_KPH = 1.609344 + KPH_TO_MPH = 1. / MPH_TO_KPH + MS_TO_KPH = 3.6 + KPH_TO_MS = 1. / MS_TO_KPH + MS_TO_MPH = MS_TO_KPH * KPH_TO_MPH + MPH_TO_MS = MPH_TO_KPH * KPH_TO_MS + MS_TO_KNOTS = 1.9438 + KNOTS_TO_MS = 1. / MS_TO_KNOTS + + # Angle + DEG_TO_RAD = np.pi / 180. + RAD_TO_DEG = 1. / DEG_TO_RAD + + # Mass + LB_TO_KG = 0.453592 diff --git a/opendbc_repo/opendbc/car/common/filter_simple.py b/opendbc_repo/opendbc/car/common/filter_simple.py new file mode 100644 index 0000000000..0ec7a51562 --- /dev/null +++ b/opendbc_repo/opendbc/car/common/filter_simple.py @@ -0,0 +1,18 @@ +class FirstOrderFilter: + # first order filter + def __init__(self, x0, rc, dt, initialized=True): + self.x = x0 + self.dt = dt + self.update_alpha(rc) + self.initialized = initialized + + def update_alpha(self, rc): + self.alpha = self.dt / (rc + self.dt) + + def update(self, x): + if self.initialized: + self.x = (1. - self.alpha) * self.x + self.alpha * x + else: + self.initialized = True + self.x = x + return self.x diff --git a/opendbc_repo/opendbc/car/common/pid.py b/opendbc_repo/opendbc/car/common/pid.py new file mode 100644 index 0000000000..e9b5bb9815 --- /dev/null +++ b/opendbc_repo/opendbc/car/common/pid.py @@ -0,0 +1,71 @@ +import numpy as np +from numbers import Number + + +class PIDController: + def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100): + self._k_p = k_p + self._k_i = k_i + self._k_d = k_d + self.k_f = k_f # feedforward gain + if isinstance(self._k_p, Number): + self._k_p = [[0], [self._k_p]] + if isinstance(self._k_i, Number): + self._k_i = [[0], [self._k_i]] + if isinstance(self._k_d, Number): + self._k_d = [[0], [self._k_d]] + + self.pos_limit = pos_limit + self.neg_limit = neg_limit + + self.i_unwind_rate = 0.3 / rate + self.i_rate = 1.0 / rate + self.speed = 0.0 + + self.reset() + + @property + def k_p(self): + return np.interp(self.speed, self._k_p[0], self._k_p[1]) + + @property + def k_i(self): + return np.interp(self.speed, self._k_i[0], self._k_i[1]) + + @property + def k_d(self): + return np.interp(self.speed, self._k_d[0], self._k_d[1]) + + @property + def error_integral(self): + return self.i/self.k_i + + def reset(self): + self.p = 0.0 + self.i = 0.0 + self.d = 0.0 + self.f = 0.0 + self.control = 0 + + def update(self, error, error_rate=0.0, speed=0.0, override=False, feedforward=0., freeze_integrator=False): + self.speed = speed + + self.p = float(error) * self.k_p + self.f = feedforward * self.k_f + self.d = error_rate * self.k_d + + if override: + self.i -= self.i_unwind_rate * float(np.sign(self.i)) + else: + if not freeze_integrator: + self.i = self.i + error * self.k_i * self.i_rate + + # Clip i to prevent exceeding control limits + control_no_i = self.p + self.d + self.f + control_no_i = np.clip(control_no_i, self.neg_limit, self.pos_limit) + self.i = np.clip(self.i, self.neg_limit - control_no_i, self.pos_limit - control_no_i) + + control = self.p + self.i + self.d + self.f + + self.control = np.clip(control, self.neg_limit, self.pos_limit) + return self.control diff --git a/opendbc_repo/opendbc/car/common/simple_kalman.py b/opendbc_repo/opendbc/car/common/simple_kalman.py new file mode 100644 index 0000000000..194b27204b --- /dev/null +++ b/opendbc_repo/opendbc/car/common/simple_kalman.py @@ -0,0 +1,54 @@ +import numpy as np + + +def get_kalman_gain(dt, A, C, Q, R, iterations=100): + P = np.zeros_like(Q) + for _ in range(iterations): + P = A.dot(P).dot(A.T) + dt * Q + S = C.dot(P).dot(C.T) + R + K = P.dot(C.T).dot(np.linalg.inv(S)) + P = (np.eye(len(P)) - K.dot(C)).dot(P) + return K + + +class KF1D: + # this EKF assumes constant covariance matrix, so calculations are much simpler + # the Kalman gain also needs to be precomputed using the control module + + def __init__(self, x0, A, C, K): + self.x0_0 = x0[0][0] + self.x1_0 = x0[1][0] + self.A0_0 = A[0][0] + self.A0_1 = A[0][1] + self.A1_0 = A[1][0] + self.A1_1 = A[1][1] + self.C0_0 = C[0] + self.C0_1 = C[1] + self.K0_0 = K[0][0] + self.K1_0 = K[1][0] + + self.A_K_0 = self.A0_0 - self.K0_0 * self.C0_0 + self.A_K_1 = self.A0_1 - self.K0_0 * self.C0_1 + self.A_K_2 = self.A1_0 - self.K1_0 * self.C0_0 + self.A_K_3 = self.A1_1 - self.K1_0 * self.C0_1 + + # K matrix needs to be pre-computed as follow: + # import control + # (x, l, K) = control.dare(np.transpose(self.A), np.transpose(self.C), Q, R) + # self.K = np.transpose(K) + + def update(self, meas): + #self.x = np.dot(self.A_K, self.x) + np.dot(self.K, meas) + x0_0 = self.A_K_0 * self.x0_0 + self.A_K_1 * self.x1_0 + self.K0_0 * meas + x1_0 = self.A_K_2 * self.x0_0 + self.A_K_3 * self.x1_0 + self.K1_0 * meas + self.x0_0 = x0_0 + self.x1_0 = x1_0 + return [self.x0_0, self.x1_0] + + @property + def x(self): + return [[self.x0_0], [self.x1_0]] + + def set_x(self, x): + self.x0_0 = x[0][0] + self.x1_0 = x[1][0] diff --git a/opendbc_repo/opendbc/car/crc.py b/opendbc_repo/opendbc/car/crc.py new file mode 100644 index 0000000000..2518286d8f --- /dev/null +++ b/opendbc_repo/opendbc/car/crc.py @@ -0,0 +1,30 @@ + +def _gen_crc8_table(poly: int) -> list[int]: + table = [] + for i in range(256): + crc = i + for _ in range(8): + if crc & 0x80: + crc = ((crc << 1) ^ poly) & 0xFF + else: + crc = (crc << 1) & 0xFF + table.append(crc) + return table + + +def _gen_crc16_table(poly: int) -> list[int]: + table = [] + for i in range(256): + crc = i << 8 + for _ in range(8): + if crc & 0x8000: + crc = ((crc << 1) ^ poly) & 0xFFFF + else: + crc = (crc << 1) & 0xFFFF + table.append(crc) + return table + + +CRC8H2F = _gen_crc8_table(0x2F) +CRC8J1850 = _gen_crc8_table(0x1D) +CRC16_XMODEM = _gen_crc16_table(0x1021) diff --git a/opendbc_repo/opendbc/car/debug/format_fingerprints.py b/opendbc_repo/opendbc/car/debug/format_fingerprints.py new file mode 100755 index 0000000000..43b59bf2e0 --- /dev/null +++ b/opendbc_repo/opendbc/car/debug/format_fingerprints.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +import jinja2 +import os + +from opendbc.car.common.basedir import BASEDIR +from opendbc.car.interfaces import get_interface_attr +from opendbc.car.structs import CarParams + +Ecu = CarParams.Ecu + +CARS = get_interface_attr('CAR') +FW_VERSIONS = get_interface_attr('FW_VERSIONS') +FINGERPRINTS = get_interface_attr('FINGERPRINTS') +ECU_NAME = {v: k for k, v in Ecu.schema.enumerants.items()} + +FINGERPRINTS_PY_TEMPLATE = jinja2.Template(""" +{%- if FINGERPRINTS[brand] and brand != 'body' %} +# ruff: noqa: E501 +{% endif %} +\"\"\" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.\"\"\" +{% if FW_VERSIONS[brand] %} +from opendbc.car.structs import CarParams +{% endif %} +from opendbc.car.{{brand}}.values import CAR +{% if FW_VERSIONS[brand] %} + +Ecu = CarParams.Ecu +{% endif %} +{% if comments +%} +{{ comments | join() }} +{% endif %} +{% if FINGERPRINTS[brand] %} + +FINGERPRINTS = { +{% for car, fingerprints in FINGERPRINTS[brand].items() %} + CAR.{{car.name}}: [{ +{% for fingerprint in fingerprints %} +{% if not loop.first %} + {{ "{" }} +{% endif %} + {% for key, value in fingerprint.items() %}{{key}}: {{value}}{% if not loop.last %}, {% endif %}{% endfor %} + + }{% if loop.last %}]{% endif %}, +{% endfor %} +{% endfor %} +} +{% endif %} + +FW_VERSIONS{% if not FW_VERSIONS[brand] %}: dict[str, dict[tuple, list[bytes]]]{% endif %} = { +{% for car, _ in FW_VERSIONS[brand].items() %} + CAR.{{car.name}}: { +{% for key, fw_versions in FW_VERSIONS[brand][car].items() %} + (Ecu.{{ECU_NAME[key[0]]}}, 0x{{"%0x" | format(key[1] | int)}}, \ +{% if key[2] %}0x{{"%0x" | format(key[2] | int)}}{% else %}{{key[2]}}{% endif %}): [ + {% for fw_version in (fw_versions + extra_fw_versions.get(car, {}).get(key, [])) | unique | sort %} + {{fw_version}}, + {% endfor %} + ], +{% endfor %} + }, +{% endfor %} +} + +""", trim_blocks=True) + + +def format_brand_fw_versions(brand, extra_fw_versions: None | dict[str, dict[tuple, list[bytes]]] = None): + extra_fw_versions = extra_fw_versions or {} + + fingerprints_file = os.path.join(BASEDIR, f"{brand}/fingerprints.py") + with open(fingerprints_file) as f: + comments = [line for line in f.readlines() if line.startswith("#") and "noqa" not in line] + + with open(fingerprints_file, "w") as f: + f.write(FINGERPRINTS_PY_TEMPLATE.render(brand=brand, comments=comments, ECU_NAME=ECU_NAME, + FINGERPRINTS=FINGERPRINTS, FW_VERSIONS=FW_VERSIONS, + extra_fw_versions=extra_fw_versions)) + + +if __name__ == "__main__": + for brand in FW_VERSIONS.keys(): + format_brand_fw_versions(brand) diff --git a/opendbc_repo/opendbc/car/disable_ecu.py b/opendbc_repo/opendbc/car/disable_ecu.py new file mode 100644 index 0000000000..797b40649f --- /dev/null +++ b/opendbc_repo/opendbc/car/disable_ecu.py @@ -0,0 +1,36 @@ +from opendbc.car.carlog import carlog +from opendbc.car.isotp_parallel_query import IsoTpParallelQuery + +EXT_DIAG_REQUEST = b'\x10\x03' +EXT_DIAG_RESPONSE = b'\x50\x03' + +COM_CONT_RESPONSE = b'' + + +def disable_ecu(can_recv, can_send, bus=0, addr=0x7d0, sub_addr=None, com_cont_req=b'\x28\x83\x01', timeout=0.1, retry=10): + """Silence an ECU by disabling sending and receiving messages using UDS 0x28. + The ECU will stay silent as long as openpilot keeps sending Tester Present. + + This is used to disable the radar in some cars. Openpilot will emulate the radar. + WARNING: THIS DISABLES AEB!""" + carlog.warning(f"ecu disable {hex(addr), sub_addr} ...") + + for i in range(retry): + try: + query = IsoTpParallelQuery(can_send, can_recv, bus, [(addr, sub_addr)], [EXT_DIAG_REQUEST], [EXT_DIAG_RESPONSE]) + + for _, _ in query.get_data(timeout).items(): + carlog.warning("communication control disable tx/rx ...") + + query = IsoTpParallelQuery(can_send, can_recv, bus, [(addr, sub_addr)], [com_cont_req], [COM_CONT_RESPONSE]) + query.get_data(0) + + carlog.warning("ecu disabled") + return True + + except Exception: + carlog.exception("ecu disable exception") + + carlog.error(f"ecu disable retry ({i + 1}) ...") + carlog.error("ecu disable failed") + return False diff --git a/opendbc_repo/opendbc/car/docs.py b/opendbc_repo/opendbc/car/docs.py new file mode 100755 index 0000000000..901b889d50 --- /dev/null +++ b/opendbc_repo/opendbc/car/docs.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +import argparse +import os +from typing import get_args + +from collections import defaultdict +import jinja2 +from enum import Enum +from natsort import natsorted + +from opendbc.car.common.basedir import BASEDIR +from opendbc.car import gen_empty_fingerprint +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import BaseCarHarness, CarDocs, Device, ExtraCarDocs, Column, ExtraCarsColumn, CommonFootnote, PartType, SupportType +from opendbc.car.car_helpers import interfaces +from opendbc.car.interfaces import get_interface_attr +from opendbc.car.values import Platform +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.extra_cars import CAR as EXTRA + + +EXTRA_CARS_MD_OUT = os.path.join(BASEDIR, "../", "../", "docs", "CARS.md") +EXTRA_CARS_MD_TEMPLATE = os.path.join(BASEDIR, "CARS_template.md") + +# TODO: merge these platforms into normal car ports with SupportType flag +ExtraPlatform = Platform | EXTRA +EXTRA_BRANDS = get_args(ExtraPlatform) +EXTRA_PLATFORMS: dict[str, ExtraPlatform] = {str(platform): platform for brand in EXTRA_BRANDS for platform in brand} + + +def get_params_for_docs(platform) -> CarParams: + cp_platform = platform if platform in interfaces else MOCK.MOCK + CP: CarParams = interfaces[cp_platform].get_params(cp_platform, fingerprint=gen_empty_fingerprint(), + car_fw=[CarParams.CarFw(ecu=CarParams.Ecu.unknown)], + alpha_long=True, is_release=False, docs=True) + return CP + + +def get_all_footnotes() -> dict[Enum, int]: + all_footnotes = list(CommonFootnote) + for footnotes in get_interface_attr("Footnote", ignore_none=True).values(): + all_footnotes.extend(footnotes) + return {fn: idx + 1 for idx, fn in enumerate(all_footnotes)} + + +def build_sorted_car_docs_list(platforms, footnotes=None): + collected_car_docs: list[CarDocs | ExtraCarDocs] = [] + for platform in platforms.values(): + car_docs = platform.config.car_docs + CP = get_params_for_docs(platform) + + if not len(car_docs): + continue + + # A platform can include multiple car models + for _car_docs in car_docs: + if not hasattr(_car_docs, "row"): + _car_docs.init_make(CP) + _car_docs.init(CP, footnotes) + collected_car_docs.append(_car_docs) + + # Sort cars by make and model + year + sorted_cars = natsorted(collected_car_docs, key=lambda car: car.name.lower()) + return sorted_cars + + +# CAUTION: This function is imported by shop.comma.ai and comma.ai/vehicles, test changes carefully +def get_all_car_docs() -> list[CarDocs]: + collected_footnotes = get_all_footnotes() + sorted_list: list[CarDocs] = build_sorted_car_docs_list(EXTRA_PLATFORMS, footnotes=collected_footnotes) + return sorted_list + + +def group_by_make(all_car_docs: list[CarDocs]) -> dict[str, list[CarDocs]]: + sorted_car_docs = defaultdict(list) + for car_docs in all_car_docs: + sorted_car_docs[car_docs.make].append(car_docs) + return dict(sorted_car_docs) + + +# CAUTION: This function is imported by shop.comma.ai and comma.ai/vehicles, test changes carefully +def generate_cars_md(all_car_docs: list[CarDocs], template_fn: str, **kwargs) -> str: + with open(template_fn) as f: + template = jinja2.Template(f.read(), trim_blocks=True, lstrip_blocks=True) + + footnotes = [fn.value.text for fn in get_all_footnotes()] + cars_md: str = template.render(all_car_docs=all_car_docs, PartType=PartType, + group_by_make=group_by_make, footnotes=footnotes, + Device=Device, Column=Column, ExtraCarsColumn=ExtraCarsColumn, + BaseCarHarness=BaseCarHarness, SupportType=SupportType, + **kwargs) + return cars_md + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Auto generates supportability info docs for all known cars", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("--template", default=EXTRA_CARS_MD_TEMPLATE, help="Override default template filename") + parser.add_argument("--out", default=EXTRA_CARS_MD_OUT, help="Override default generated filename") + args = parser.parse_args() + + with open(args.out, 'w') as f: + f.write(generate_cars_md(get_all_car_docs(), args.template)) + print(f"Generated and written to {args.out}") diff --git a/opendbc_repo/opendbc/car/docs_definitions.py b/opendbc_repo/opendbc/car/docs_definitions.py new file mode 100644 index 0000000000..744d47580b --- /dev/null +++ b/opendbc_repo/opendbc/car/docs_definitions.py @@ -0,0 +1,420 @@ +import re +from collections import namedtuple +import copy +from dataclasses import dataclass, field +from enum import Enum + +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.structs import CarParams + +GOOD_TORQUE_THRESHOLD = 1.0 # m/s^2 +MODEL_YEARS_RE = r"(?<= )((\d{4}-\d{2})|(\d{4}))(,|$)" + + +class Column(Enum): + MAKE = "Make" + MODEL = "Model" + PACKAGE = "Supported Package" + LONGITUDINAL = "ACC" + FSR_LONGITUDINAL = "No ACC accel below" + FSR_STEERING = "No ALC below" + STEERING_TORQUE = "Steering Torque" + AUTO_RESUME = "Resume from stop" + HARDWARE = "Hardware Needed" + VIDEO = "Video" + SETUP_VIDEO = "Setup Video" + + +class ExtraCarsColumn(Enum): + MAKE = "Make" + MODEL = "Model" + PACKAGE = "Package" + SUPPORT = "Support Level" + + +class SupportType(Enum): + UPSTREAM = "Upstream" # Actively maintained by comma, plug-and-play in release versions of openpilot + REVIEW = "Under review" # Dashcam, but planned for official support after safety validation + DASHCAM = "Dashcam mode" # Dashcam, but may be drivable in a community fork + COMMUNITY = "Community" # Not upstream, but available in a custom community fork, not validated by comma + CUSTOM = "Custom" # Upstream, but don't have a harness available or need an unusual custom install + INCOMPATIBLE = "Not compatible" # Known fundamental incompatibility such as Flexray or hydraulic power steering + + +class Star(Enum): + FULL = "full" + HALF = "half" + EMPTY = "empty" + + +# A part + its comprised parts +@dataclass +class BasePart: + name: str + parts: list[Enum] = field(default_factory=list) + + def all_parts(self): + # Recursively get all parts + _parts = 'parts' + parts = [] + parts.extend(getattr(self, _parts)) + for part in getattr(self, _parts): + parts.extend(part.value.all_parts()) + + return parts + + +class EnumBase(Enum): + @property + def part_type(self): + return PartType(self.__class__) + + +class Mount(EnumBase): + mount = BasePart("mount") + angled_mount_8_degrees = BasePart("angled mount (8 degrees)") + + +class Cable(EnumBase): + long_obdc_cable = BasePart("long OBD-C cable (9.5 ft)") + usb_a_2_a_cable = BasePart("USB A-A cable") + usbc_otg_cable = BasePart("USB C OTG cable") + usbc_coupler = BasePart("USB-C coupler") + obd_c_cable_1_5ft = BasePart("OBD-C cable (1.5 ft)") + right_angle_obd_c_cable_1_5ft = BasePart("right angle OBD-C cable (1.5 ft)") + + +class Accessory(EnumBase): + harness_box = BasePart("harness box") + comma_power = BasePart("comma power v3") + + +class Tool(EnumBase): + socket_8mm_deep = BasePart("Socket Wrench 8mm or 5/16\" (deep)") + pry_tool = BasePart("Pry Tool") + + +@dataclass +class BaseCarHarness(BasePart): + parts: list[Enum] = field(default_factory=lambda: [Accessory.harness_box, Accessory.comma_power]) + has_connector: bool = True # without are hidden on the harness connector page + + +class CarHarness(EnumBase): + nidec = BaseCarHarness("Honda Nidec connector") + bosch_a = BaseCarHarness("Honda Bosch A connector") + bosch_b = BaseCarHarness("Honda Bosch B connector") + bosch_c = BaseCarHarness("Honda Bosch C connector") + toyota_a = BaseCarHarness("Toyota A connector") + toyota_b = BaseCarHarness("Toyota B connector") + subaru_a = BaseCarHarness("Subaru A connector", parts=[Accessory.harness_box, Accessory.comma_power, Tool.socket_8mm_deep, Tool.pry_tool]) + subaru_b = BaseCarHarness("Subaru B connector", parts=[Accessory.harness_box, Accessory.comma_power, Tool.socket_8mm_deep, Tool.pry_tool]) + subaru_c = BaseCarHarness("Subaru C connector", parts=[Accessory.harness_box, Accessory.comma_power, Tool.socket_8mm_deep, Tool.pry_tool]) + subaru_d = BaseCarHarness("Subaru D connector", parts=[Accessory.harness_box, Accessory.comma_power, Tool.socket_8mm_deep, Tool.pry_tool]) + fca = BaseCarHarness("FCA connector") + ram = BaseCarHarness("Ram connector") + vw_a = BaseCarHarness("VW A connector") + vw_j533 = BaseCarHarness("VW J533 connector", parts=[Accessory.harness_box, Cable.long_obdc_cable, Cable.usbc_coupler]) + hyundai_a = BaseCarHarness("Hyundai A connector") + hyundai_b = BaseCarHarness("Hyundai B connector") + hyundai_c = BaseCarHarness("Hyundai C connector") + hyundai_d = BaseCarHarness("Hyundai D connector") + hyundai_e = BaseCarHarness("Hyundai E connector") + hyundai_f = BaseCarHarness("Hyundai F connector") + hyundai_g = BaseCarHarness("Hyundai G connector") + hyundai_h = BaseCarHarness("Hyundai H connector") + hyundai_i = BaseCarHarness("Hyundai I connector") + hyundai_j = BaseCarHarness("Hyundai J connector") + hyundai_k = BaseCarHarness("Hyundai K connector") + hyundai_l = BaseCarHarness("Hyundai L connector") + hyundai_m = BaseCarHarness("Hyundai M connector") + hyundai_n = BaseCarHarness("Hyundai N connector") + hyundai_o = BaseCarHarness("Hyundai O connector") + hyundai_p = BaseCarHarness("Hyundai P connector") + hyundai_q = BaseCarHarness("Hyundai Q connector") + hyundai_r = BaseCarHarness("Hyundai R connector") + custom = BaseCarHarness("Developer connector") + obd_ii = BaseCarHarness("OBD-II connector", parts=[Cable.long_obdc_cable, Cable.usbc_coupler], has_connector=False) + gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box]) + gmsdgm = BaseCarHarness("GM SDGM connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler]) + nissan_a = BaseCarHarness("Nissan A connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler]) + nissan_b = BaseCarHarness("Nissan B connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler]) + mazda = BaseCarHarness("Mazda connector") + ford_q3 = BaseCarHarness("Ford Q3 connector") + ford_q4 = BaseCarHarness("Ford Q4 connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler]) + rivian = BaseCarHarness("Rivian A connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable, Cable.usbc_coupler]) + tesla_a = BaseCarHarness("Tesla A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable, Cable.usbc_coupler]) + tesla_b = BaseCarHarness("Tesla B connector", parts=[Accessory.harness_box, Cable.long_obdc_cable, Cable.usbc_coupler]) + psa_a = BaseCarHarness("PSA A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable, Cable.usbc_coupler]) + + +class Device(EnumBase): + threex = BasePart("comma 3X", parts=[Mount.mount, Cable.right_angle_obd_c_cable_1_5ft]) + # variant of comma 3X with angled mounts + threex_angled_mount = BasePart("comma 3X", parts=[Mount.angled_mount_8_degrees, Cable.right_angle_obd_c_cable_1_5ft]) + red_panda = BasePart("red panda") + + +class Kit(EnumBase): + red_panda_kit = BasePart("CAN FD panda kit", parts=[Device.red_panda, Accessory.harness_box, + Cable.usb_a_2_a_cable, Cable.usbc_otg_cable, Cable.obd_c_cable_1_5ft]) + + +class PartType(Enum): + accessory = Accessory + cable = Cable + connector = CarHarness + device = Device + kit = Kit + mount = Mount + tool = Tool + + +DEFAULT_CAR_PARTS: list[EnumBase] = [Device.threex] + + +@dataclass +class CarParts: + parts: list[EnumBase] = field(default_factory=list) + + def __call__(self): + return copy.deepcopy(self) + + @classmethod + def common(cls, add: list[EnumBase] = None, remove: list[EnumBase] = None): + p = [part for part in (add or []) + DEFAULT_CAR_PARTS if part not in (remove or [])] + return cls(p) + + def all_parts(self): + parts = [] + for part in self.parts: + parts.extend(part.value.all_parts()) + return self.parts + parts + + +CarFootnote = namedtuple("CarFootnote", ["text", "column", "docs_only", "setup_note"], defaults=(False, False)) + + +class CommonFootnote(Enum): + EXP_LONG_AVAIL = CarFootnote( + "openpilot Longitudinal Control (Alpha) is available behind a toggle; " + + "the toggle is only available in non-release branches such as `devel` or `nightly-dev`.", + Column.LONGITUDINAL, docs_only=True) + EXP_LONG_DSU = CarFootnote( + "By default, this car will use the stock Adaptive Cruise Control (ACC) for longitudinal control. " + + "If the Driver Support Unit (DSU) is disconnected, openpilot ACC will replace " + + "stock ACC. NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).", + Column.LONGITUDINAL) + + +def get_footnotes(footnotes: list[Enum], column: Column) -> list[Enum]: + # Returns applicable footnotes given current column + return [fn for fn in footnotes if fn.value.column == column] + + +# TODO: store years as a list +def get_year_list(years): + years_list = [] + if len(years) == 0: + return years_list + + for year in years.split(','): + year = year.strip() + if len(year) == 4: + years_list.append(str(year)) + elif "-" in year and len(year) == 7: + start, end = year.split("-") + years_list.extend(map(str, range(int(start), int(f"20{end}") + 1))) + else: + raise Exception(f"Malformed year string: {years}") + return years_list + + +def split_name(name: str) -> tuple[str, str, str]: + make, model = name.split(" ", 1) + years = "" + match = re.search(MODEL_YEARS_RE, model) + if match is not None: + years = model[match.start():] + model = model[:match.start() - 1] + return make, model, years + + +@dataclass +class CarDocs: + # make + model + model years + name: str + + # the simplest description of the requirements for the US market + package: str + + video: str | None = None + setup_video: str | None = None + footnotes: list[Enum] = field(default_factory=list) + min_steer_speed: float | None = None + min_enable_speed: float | None = None + auto_resume: bool | None = None + + # all the parts needed for the supported car + car_parts: CarParts = field(default_factory=CarParts) + + merged: bool = True + support_type: SupportType = SupportType.UPSTREAM + support_link: str | None = "#upstream" + + def __post_init__(self): + self.make, self.model, self.years = split_name(self.name) + self.year_list = get_year_list(self.years) + + def init(self, CP: CarParams, all_footnotes=None): + self.brand = CP.brand + self.car_fingerprint = CP.carFingerprint + + if self.merged and CP.dashcamOnly: + if self.support_type != SupportType.REVIEW: + self.support_type = SupportType.DASHCAM + self.support_link = "#dashcam" + else: + self.support_link = "#under-review" + + # longitudinal column + op_long = "Stock" + if CP.alphaLongitudinalAvailable or CP.enableDsu: + op_long = "openpilot available" + if CP.enableDsu: + self.footnotes.append(CommonFootnote.EXP_LONG_DSU) + else: + self.footnotes.append(CommonFootnote.EXP_LONG_AVAIL) + elif CP.openpilotLongitudinalControl and not CP.enableDsu: + op_long = "openpilot" + + # min steer & enable speed columns + # TODO: set all the min steer speeds in carParams and remove this + if self.min_steer_speed is not None: + assert CP.minSteerSpeed < 0.5, f"{CP.carFingerprint}: Minimum steer speed set in both CarDocs and CarParams" + else: + self.min_steer_speed = CP.minSteerSpeed + + # TODO: set all the min enable speeds in carParams correctly and remove this + if self.min_enable_speed is None: + self.min_enable_speed = CP.minEnableSpeed + + if self.auto_resume is None: + self.auto_resume = CP.autoResumeSng and self.min_enable_speed <= 0 + + # hardware column + hardware_col = "None" + if self.car_parts.parts: + buy_link = f'Buy Here' + + tools_docs = [part for part in self.car_parts.all_parts() if isinstance(part, Tool)] + parts_docs = [part for part in self.car_parts.all_parts() if not isinstance(part, Tool)] + + def display_func(parts): + return '
    '.join([f"- {parts.count(part)} {part.value.name}" for part in sorted(set(parts), key=lambda part: str(part.value.name))]) + + hardware_col = f'
    Parts{display_func(parts_docs)}
    {buy_link}
    ' + if len(tools_docs): + hardware_col += f'
    Tools{display_func(tools_docs)}
    ' + + self.row: dict[Enum, str | Star] = { + Column.MAKE: self.make, + Column.MODEL: self.model, + Column.PACKAGE: self.package, + Column.LONGITUDINAL: op_long, + Column.FSR_LONGITUDINAL: f"{max(self.min_enable_speed * CV.MS_TO_MPH, 0):.0f} mph", + Column.FSR_STEERING: f"{max(self.min_steer_speed * CV.MS_TO_MPH, 0):.0f} mph", + Column.STEERING_TORQUE: Star.EMPTY, + Column.AUTO_RESUME: Star.FULL if self.auto_resume else Star.EMPTY, + Column.HARDWARE: hardware_col, + Column.VIDEO: self.video or "", # replaced with an image and link from template in get_column + Column.SETUP_VIDEO: self.setup_video or "", # replaced with an image and link from template in get_column + } + + if self.support_link is not None: + support_info = f"[{self.support_type.value}]({self.support_link})" + else: + support_info = self.support_type.value + + self.extra_cars_row: dict[Enum, str] = { + ExtraCarsColumn.MAKE: self.make, + ExtraCarsColumn.MODEL: self.model, + ExtraCarsColumn.PACKAGE: self.package, + ExtraCarsColumn.SUPPORT: support_info, + } + + # Set steering torque star from max lateral acceleration + assert CP.maxLateralAccel > 0.1 + if CP.maxLateralAccel >= GOOD_TORQUE_THRESHOLD: + self.row[Column.STEERING_TORQUE] = Star.FULL + + self.all_footnotes = all_footnotes + self.detail_sentence = self.get_detail_sentence(CP) + + return self + + def init_make(self, CP: CarParams): + """CarDocs subclasses can add make-specific logic for harness selection, footnotes, etc.""" + + def get_detail_sentence(self, CP): + if not CP.notCar: + sentence_builder = "openpilot upgrades your {car_model} with automated lane centering{alc} and adaptive cruise control{acc}." + + if self.min_steer_speed > self.min_enable_speed: + alc = f" above {self.min_steer_speed * CV.MS_TO_MPH:.0f} mph," if self.min_steer_speed > 0 else " at all speeds," + else: + alc = "" + + # Exception for cars which do not auto-resume yet + acc = "" + if self.min_enable_speed > 0: + acc = f" while driving above {self.min_enable_speed * CV.MS_TO_MPH:.0f} mph" + elif self.auto_resume: + acc = " that automatically resumes from a stop" + + if self.row[Column.STEERING_TORQUE] != Star.FULL: + sentence_builder += " This car may not be able to take tight turns on its own." + + # experimental mode + exp_link = "Experimental mode" + if CP.openpilotLongitudinalControl and not CP.alphaLongitudinalAvailable: + sentence_builder += f" Traffic light and stop sign handling is also available in {exp_link}." + + return sentence_builder.format(car_model=f"{self.make} {self.model}", alc=alc, acc=acc) + + else: + if CP.carFingerprint == "COMMA_BODY": + return "The body is a robotics dev kit that can run openpilot. Learn more." + else: + raise Exception(f"This notCar does not have a detail sentence: {CP.carFingerprint}") + + def get_column(self, column: Column, star_icon: str, video_icon: str, footnote_tag: str) -> str: + item: str | Star = self.row[column] + if isinstance(item, Star): + item = star_icon.format(item.value) + elif column == Column.MODEL and len(self.years): + item += f" {self.years}" + elif column in (Column.VIDEO, Column.SETUP_VIDEO) and len(item) > 0: + item = video_icon.format(item) + + footnotes = get_footnotes(self.footnotes, column) + if len(footnotes): + sups = sorted([self.all_footnotes[fn] for fn in footnotes]) + item += footnote_tag.format(f'{",".join(map(str, sups))}') + + return item + + def get_extra_cars_column(self, column: ExtraCarsColumn) -> str: + item: str = self.extra_cars_row[column] + if column == ExtraCarsColumn.MODEL and len(self.years): + item += f" {self.years}" + + return item + + +@dataclass +class ExtraCarDocs(CarDocs): + package: str = "Any" + merged: bool = False + support_type: SupportType = SupportType.INCOMPATIBLE + support_link: str | None = "#incompatible" diff --git a/opendbc_repo/opendbc/car/ecu_addrs.py b/opendbc_repo/opendbc/car/ecu_addrs.py new file mode 100644 index 0000000000..c607e2c640 --- /dev/null +++ b/opendbc_repo/opendbc/car/ecu_addrs.py @@ -0,0 +1,56 @@ +import time + +from opendbc.car import make_tester_present_msg, uds +from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable +from opendbc.car.carlog import carlog +from opendbc.car.fw_query_definitions import EcuAddrBusType + + +def _is_tester_present_response(msg: CanData, subaddr: int = None) -> bool: + # ISO-TP messages may use CAN frame optimization (not always 8 bytes) + # tester present response is always a single frame + dat_offset = 1 if subaddr is not None else 0 + min_length = 4 if subaddr is not None else 3 # bytes: frame len, (pos/neg) sid, (optional negative sid)/0x00 sub-function + if min_length <= len(msg.dat) <= 8 and 1 <= msg.dat[dat_offset] <= 7: + # success response + if msg.dat[dat_offset + 1] == (uds.SERVICE_TYPE.TESTER_PRESENT + 0x40): + return True + # error response + if msg.dat[dat_offset + 1] == 0x7F and msg.dat[dat_offset + 2] == uds.SERVICE_TYPE.TESTER_PRESENT: + return True + return False + + +def get_all_ecu_addrs(can_recv: CanRecvCallable, can_send: CanSendCallable, bus: int, timeout: float = 1) -> set[EcuAddrBusType]: + addr_list = [0x700 + i for i in range(256)] + [0x18da00f1 + (i << 8) for i in range(256)] + queries: set[EcuAddrBusType] = {(addr, None, bus) for addr in addr_list} + responses = queries + return get_ecu_addrs(can_recv, can_send, queries, responses, timeout=timeout) + + +def get_ecu_addrs(can_recv: CanRecvCallable, can_send: CanSendCallable, queries: set[EcuAddrBusType], + responses: set[EcuAddrBusType], timeout: float = 1) -> set[EcuAddrBusType]: + ecu_responses: set[EcuAddrBusType] = set() # set((addr, subaddr, bus),) + try: + msgs = [make_tester_present_msg(addr, bus, subaddr) for addr, subaddr, bus in queries] + + can_recv() + can_send(msgs) + start_time = time.monotonic() + while time.monotonic() - start_time < timeout: + can_packets = can_recv(wait_for_one=True) + for packet in can_packets: + for msg in packet: + if not len(msg.dat): + carlog.warning("ECU addr scan: skipping empty remote frame") + continue + + subaddr = None if (msg.address, None, msg.src) in responses else msg.dat[0] + if (msg.address, subaddr, msg.src) in responses and _is_tester_present_response(msg, subaddr): + carlog.debug(f"CAN-RX: {hex(msg.address)} - 0x{bytes.hex(msg.dat)}") + if (msg.address, subaddr, msg.src) in ecu_responses: + carlog.debug(f"Duplicate ECU address: {hex(msg.address)}") + ecu_responses.add((msg.address, subaddr, msg.src)) + except Exception: + carlog.exception("ECU addr scan exception") + return ecu_responses diff --git a/opendbc_repo/opendbc/car/extra_cars.py b/opendbc_repo/opendbc/car/extra_cars.py new file mode 100644 index 0000000000..5ffa42bf4a --- /dev/null +++ b/opendbc_repo/opendbc/car/extra_cars.py @@ -0,0 +1,85 @@ +from dataclasses import dataclass + +from opendbc.car import structs, Platforms, ExtraPlatformConfig +from opendbc.car.docs_definitions import ExtraCarDocs, SupportType + + +@dataclass +class CommunityCarDocs(ExtraCarDocs): + def init_make(self, CP: structs.CarParams): + self.support_type = SupportType.COMMUNITY + self.support_link = "#community" + + +@dataclass +class ToyotaSecurityCarDocs(ExtraCarDocs): + def init_make(self, CP: structs.CarParams): + self.support_type = SupportType.INCOMPATIBLE + self.support_link = "#can-bus-security" + + +@dataclass +class GMSecurityCarDocs(ExtraCarDocs): + def init_make(self, CP: structs.CarParams): + self.support_type = SupportType.INCOMPATIBLE + self.support_link = "#can-bus-security" + + +@dataclass +class FlexRayCarDocs(ExtraCarDocs): + def init_make(self, CP: structs.CarParams): + self.support_type = SupportType.INCOMPATIBLE + self.support_link = "#flexray" + + +class CAR(Platforms): + config: ExtraPlatformConfig + + EXTRA_HONDA = ExtraPlatformConfig( + [ + CommunityCarDocs("Acura Integra 2023-25", "All"), + CommunityCarDocs("Acura MDX 2015-16", "Advance Package"), + CommunityCarDocs("Acura MDX 2017-20", "All"), + CommunityCarDocs("Acura MDX 2022-24", "All"), + CommunityCarDocs("Acura RDX 2022-25", "All"), + CommunityCarDocs("Acura RLX 2017", "Advance Package or Technology Package"), + CommunityCarDocs("Acura TLX 2015-17", "Advance Package"), + CommunityCarDocs("Acura TLX 2018-20", "All"), + CommunityCarDocs("Acura TLX 2022-23", "All"), + GMSecurityCarDocs("Acura ZDX 2024", "All"), + CommunityCarDocs("Honda Accord 2016-17", "Honda Sensing"), + CommunityCarDocs("Honda Clarity 2018-21", "All"), + GMSecurityCarDocs("Honda Prologue 2024-25", "All"), + ], + ) + + EXTRA_HYUNDAI = ExtraPlatformConfig( + [ + CommunityCarDocs("Hyundai Palisade 2023-24", package="HDA2"), + CommunityCarDocs("Kia Telluride 2023-24", package="HDA2"), + ], + ) + + EXTRA_TOYOTA = ExtraPlatformConfig( + [ + ToyotaSecurityCarDocs("Subaru Solterra 2023-25"), + ToyotaSecurityCarDocs("Lexus NS 2022-25"), + ToyotaSecurityCarDocs("Toyota bZ4x 2023-25"), + ToyotaSecurityCarDocs("Toyota Camry 2025"), + ToyotaSecurityCarDocs("Toyota Corolla Cross 2022-25"), + ToyotaSecurityCarDocs("Toyota Highlander 2025"), + ToyotaSecurityCarDocs("Toyota RAV4 Prime 2024-25"), + ToyotaSecurityCarDocs("Toyota Sequoia 2023-25"), + ToyotaSecurityCarDocs("Toyota Sienna 2024-25"), + ToyotaSecurityCarDocs("Toyota Tundra 2022-25"), + ToyotaSecurityCarDocs("Toyota Venza 2021-25"), + ], + ) + + EXTRA_VOLKSWAGEN = ExtraPlatformConfig( + [ + FlexRayCarDocs("Audi A4 2016-24", package="All"), + FlexRayCarDocs("Audi A5 2016-24", package="All"), + FlexRayCarDocs("Audi Q5 2017-24", package="All"), + ], + ) diff --git a/opendbc_repo/opendbc/car/fingerprints.py b/opendbc_repo/opendbc/car/fingerprints.py new file mode 100644 index 0000000000..206177f8ce --- /dev/null +++ b/opendbc_repo/opendbc/car/fingerprints.py @@ -0,0 +1,338 @@ +from opendbc.car.interfaces import get_interface_attr +from opendbc.car.body.values import CAR as BODY +from opendbc.car.chrysler.values import CAR as CHRYSLER +from opendbc.car.ford.values import CAR as FORD +from opendbc.car.gm.values import CAR as GM +from opendbc.car.honda.values import CAR as HONDA +from opendbc.car.hyundai.values import CAR as HYUNDAI +from opendbc.car.mazda.values import CAR as MAZDA +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.nissan.values import CAR as NISSAN +from opendbc.car.subaru.values import CAR as SUBARU +from opendbc.car.toyota.values import CAR as TOYOTA +from opendbc.car.volkswagen.values import CAR as VW + +FW_VERSIONS = get_interface_attr('FW_VERSIONS', combine_brands=True, ignore_none=True) +_FINGERPRINTS = get_interface_attr('FINGERPRINTS', combine_brands=True, ignore_none=True) + +_DEBUG_ADDRESS = {1880: 8} # reserved for debug purposes + + +def is_valid_for_fingerprint(msg, car_fingerprint: dict[int, int]): + adr = msg.address + # ignore addresses that are more than 11 bits + return (adr in car_fingerprint and car_fingerprint[adr] == len(msg.dat)) or adr >= 0x800 + + +def eliminate_incompatible_cars(msg, candidate_cars): + """Removes cars that could not have sent msg. + + Inputs: + msg: A cereal/log CanData message from the car. + candidate_cars: A list of cars to consider. + + Returns: + A list containing the subset of candidate_cars that could have sent msg. + """ + compatible_cars = [] + + for car_name in candidate_cars: + car_fingerprints = _FINGERPRINTS[car_name] + + for fingerprint in car_fingerprints: + # add alien debug address + if is_valid_for_fingerprint(msg, fingerprint | _DEBUG_ADDRESS): + compatible_cars.append(car_name) + break + + return compatible_cars + + +def all_legacy_fingerprint_cars(): + """Returns a list of all known car strings, FPv1 only.""" + return list(_FINGERPRINTS.keys()) + + +# A dict that maps old platform strings to their latest representations +MIGRATION = { + "ACURA ILX 2016 ACURAWATCH PLUS": HONDA.ACURA_ILX, + "ACURA RDX 2018 ACURAWATCH PLUS": HONDA.ACURA_RDX, + "ACURA RDX 2020 TECH": HONDA.ACURA_RDX_3G, + "AUDI A3": VW.AUDI_A3_MK3, + "HONDA ACCORD 2018 HYBRID TOURING": HONDA.HONDA_ACCORD, + "HONDA ACCORD 1.5T 2018": HONDA.HONDA_ACCORD, + "HONDA ACCORD 2018 LX 1.5T": HONDA.HONDA_ACCORD, + "HONDA ACCORD 2018 SPORT 2T": HONDA.HONDA_ACCORD, + "HONDA ACCORD 2T 2018": HONDA.HONDA_ACCORD, + "HONDA ACCORD HYBRID 2018": HONDA.HONDA_ACCORD, + "HONDA CIVIC 2016 TOURING": HONDA.HONDA_CIVIC, + "HONDA CIVIC HATCHBACK 2017 SEDAN/COUPE 2019": HONDA.HONDA_CIVIC_BOSCH, + "HONDA CIVIC SEDAN 1.6 DIESEL": HONDA.HONDA_CIVIC_BOSCH_DIESEL, + "HONDA CR-V 2016 EXECUTIVE": HONDA.HONDA_CRV_EU, + "HONDA CR-V 2016 TOURING": HONDA.HONDA_CRV, + "HONDA CR-V 2017 EX": HONDA.HONDA_CRV_5G, + "HONDA CR-V 2019 HYBRID": HONDA.HONDA_CRV_HYBRID, + "HONDA FIT 2018 EX": HONDA.HONDA_FIT, + "HONDA HRV 2019 TOURING": HONDA.HONDA_HRV, + "HONDA INSIGHT 2019 TOURING": HONDA.HONDA_INSIGHT, + "HONDA ODYSSEY 2018 EX-L": HONDA.HONDA_ODYSSEY, + "HONDA PILOT 2017 TOURING": HONDA.HONDA_PILOT, + "HONDA PILOT 2019 ELITE": HONDA.HONDA_PILOT, + "HONDA PILOT 2019": HONDA.HONDA_PILOT, + "HONDA PASSPORT 2021": HONDA.HONDA_PILOT, + "HONDA RIDGELINE 2017 BLACK EDITION": HONDA.HONDA_RIDGELINE, + "HYUNDAI ELANTRA LIMITED ULTIMATE 2017": HYUNDAI.HYUNDAI_ELANTRA, + "HYUNDAI SANTA FE LIMITED 2019": HYUNDAI.HYUNDAI_SANTA_FE, + "HYUNDAI TUCSON DIESEL 2019": HYUNDAI.HYUNDAI_TUCSON, + "KIA OPTIMA 2016": HYUNDAI.KIA_OPTIMA_G4, + "KIA OPTIMA 2019": HYUNDAI.KIA_OPTIMA_G4_FL, + "KIA OPTIMA SX 2019 & 2016": HYUNDAI.KIA_OPTIMA_G4_FL, + "LEXUS CT 200H 2018": TOYOTA.LEXUS_CTH, + "LEXUS ES 300H 2018": TOYOTA.LEXUS_ES, + "LEXUS ES 300H 2019": TOYOTA.LEXUS_ES_TSS2, + "LEXUS IS300 2018": TOYOTA.LEXUS_IS, + "LEXUS NX300 2018": TOYOTA.LEXUS_NX, + "LEXUS NX300H 2018": TOYOTA.LEXUS_NX, + "LEXUS RX 350 2016": TOYOTA.LEXUS_RX, + "LEXUS RX350 2020": TOYOTA.LEXUS_RX_TSS2, + "LEXUS RX450 HYBRID 2020": TOYOTA.LEXUS_RX_TSS2, + "TOYOTA SIENNA XLE 2018": TOYOTA.TOYOTA_SIENNA, + "TOYOTA C-HR HYBRID 2018": TOYOTA.TOYOTA_CHR, + "TOYOTA COROLLA HYBRID TSS2 2019": TOYOTA.TOYOTA_COROLLA_TSS2, + "TOYOTA RAV4 HYBRID 2019": TOYOTA.TOYOTA_RAV4_TSS2, + "LEXUS ES HYBRID 2019": TOYOTA.LEXUS_ES_TSS2, + "LEXUS NX HYBRID 2018": TOYOTA.LEXUS_NX, + "LEXUS NX HYBRID 2020": TOYOTA.LEXUS_NX_TSS2, + "LEXUS RX HYBRID 2020": TOYOTA.LEXUS_RX_TSS2, + "TOYOTA ALPHARD HYBRID 2021": TOYOTA.TOYOTA_ALPHARD_TSS2, + "TOYOTA AVALON HYBRID 2019": TOYOTA.TOYOTA_AVALON_2019, + "TOYOTA AVALON HYBRID 2022": TOYOTA.TOYOTA_AVALON_TSS2, + "TOYOTA CAMRY HYBRID 2018": TOYOTA.TOYOTA_CAMRY, + "TOYOTA CAMRY HYBRID 2021": TOYOTA.TOYOTA_CAMRY_TSS2, + "TOYOTA C-HR HYBRID 2022": TOYOTA.TOYOTA_CHR_TSS2, + "TOYOTA HIGHLANDER HYBRID 2020": TOYOTA.TOYOTA_HIGHLANDER_TSS2, + "TOYOTA RAV4 HYBRID 2022": TOYOTA.TOYOTA_RAV4_TSS2_2022, + "TOYOTA RAV4 HYBRID 2023": TOYOTA.TOYOTA_RAV4_TSS2_2023, + "TOYOTA HIGHLANDER HYBRID 2018": TOYOTA.TOYOTA_HIGHLANDER, + "LEXUS ES HYBRID 2018": TOYOTA.LEXUS_ES, + "LEXUS RX HYBRID 2017": TOYOTA.LEXUS_RX, + "HYUNDAI TUCSON HYBRID 4TH GEN": HYUNDAI.HYUNDAI_TUCSON_4TH_GEN, + "KIA SPORTAGE HYBRID 5TH GEN": HYUNDAI.KIA_SPORTAGE_5TH_GEN, + "KIA SORENTO PLUG-IN HYBRID 4TH GEN": HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, + "CADILLAC ESCALADE ESV PLATINUM 2019": GM.CADILLAC_ESCALADE_ESV_2019, + + # Removal of platform_str, see https://github.com/commaai/openpilot/pull/31868/ + "COMMA BODY": BODY.COMMA_BODY, + "CHRYSLER PACIFICA HYBRID 2017": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID, + "CHRYSLER_PACIFICA_2017_HYBRID": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID, + "CHRYSLER PACIFICA HYBRID 2018": CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID, + "CHRYSLER PACIFICA HYBRID 2019": CHRYSLER.CHRYSLER_PACIFICA_2019_HYBRID, + "CHRYSLER PACIFICA 2018": CHRYSLER.CHRYSLER_PACIFICA_2018, + "CHRYSLER PACIFICA 2020": CHRYSLER.CHRYSLER_PACIFICA_2020, + "DODGE DURANGO 2021": CHRYSLER.DODGE_DURANGO, + "JEEP GRAND CHEROKEE V6 2018": CHRYSLER.JEEP_GRAND_CHEROKEE, + "JEEP GRAND CHEROKEE 2019": CHRYSLER.JEEP_GRAND_CHEROKEE_2019, + "RAM 1500 5TH GEN": CHRYSLER.RAM_1500_5TH_GEN, + "RAM HD 5TH GEN": CHRYSLER.RAM_HD_5TH_GEN, + "FORD BRONCO SPORT 1ST GEN": FORD.FORD_BRONCO_SPORT_MK1, + "FORD ESCAPE 4TH GEN": FORD.FORD_ESCAPE_MK4, + "FORD EXPLORER 6TH GEN": FORD.FORD_EXPLORER_MK6, + "FORD F-150 14TH GEN": FORD.FORD_F_150_MK14, + "FORD F-150 LIGHTNING 1ST GEN": FORD.FORD_F_150_LIGHTNING_MK1, + "FORD FOCUS 4TH GEN": FORD.FORD_FOCUS_MK4, + "FORD MAVERICK 1ST GEN": FORD.FORD_MAVERICK_MK1, + "FORD MUSTANG MACH-E 1ST GEN": FORD.FORD_MUSTANG_MACH_E_MK1, + "HOLDEN ASTRA RS-V BK 2017": GM.HOLDEN_ASTRA, + "CHEVROLET VOLT PREMIER 2017": GM.CHEVROLET_VOLT, + "CADILLAC ATS Premium Performance 2018": GM.CADILLAC_ATS, + "CHEVROLET MALIBU PREMIER 2017": GM.CHEVROLET_MALIBU, + "GMC ACADIA DENALI 2018": GM.GMC_ACADIA, + "BUICK LACROSSE 2017": GM.BUICK_LACROSSE, + "BUICK REGAL ESSENCE 2018": GM.BUICK_REGAL, + "CADILLAC ESCALADE 2017": GM.CADILLAC_ESCALADE, + "CADILLAC ESCALADE ESV 2016": GM.CADILLAC_ESCALADE_ESV, + "CADILLAC ESCALADE ESV 2019": GM.CADILLAC_ESCALADE_ESV_2019, + "CHEVROLET BOLT EUV 2022": GM.CHEVROLET_BOLT_EUV, + "CHEVROLET SILVERADO 1500 2020": GM.CHEVROLET_SILVERADO, + "CHEVROLET EQUINOX 2019": GM.CHEVROLET_EQUINOX, + "CHEVROLET TRAILBLAZER 2021": GM.CHEVROLET_TRAILBLAZER, + "HONDA ACCORD 2018": HONDA.HONDA_ACCORD, + "HONDA CIVIC (BOSCH) 2019": HONDA.HONDA_CIVIC_BOSCH, + "HONDA CIVIC SEDAN 1.6 DIESEL 2019": HONDA.HONDA_CIVIC_BOSCH_DIESEL, + "HONDA CIVIC 2022": HONDA.HONDA_CIVIC_2022, + "HONDA CR-V 2017": HONDA.HONDA_CRV_5G, + "HONDA CR-V HYBRID 2019": HONDA.HONDA_CRV_HYBRID, + "HONDA HR-V 2023": HONDA.HONDA_HRV_3G, + "ACURA RDX 2020": HONDA.ACURA_RDX_3G, + "HONDA INSIGHT 2019": HONDA.HONDA_INSIGHT, + "HONDA E 2020": HONDA.HONDA_E, + "ACURA ILX 2016": HONDA.ACURA_ILX, + "HONDA CR-V 2016": HONDA.HONDA_CRV, + "HONDA CR-V EU 2016": HONDA.HONDA_CRV_EU, + "HONDA FIT 2018": HONDA.HONDA_FIT, + "HONDA FREED 2020": HONDA.HONDA_FREED, + "HONDA HRV 2019": HONDA.HONDA_HRV, + "HONDA ODYSSEY 2018": HONDA.HONDA_ODYSSEY, + "ACURA RDX 2018": HONDA.ACURA_RDX, + "HONDA PILOT 2017": HONDA.HONDA_PILOT, + "HONDA RIDGELINE 2017": HONDA.HONDA_RIDGELINE, + "HONDA CIVIC 2016": HONDA.HONDA_CIVIC, + "HYUNDAI AZERA 6TH GEN": HYUNDAI.HYUNDAI_AZERA_6TH_GEN, + "HYUNDAI AZERA HYBRID 6TH GEN": HYUNDAI.HYUNDAI_AZERA_HEV_6TH_GEN, + "HYUNDAI ELANTRA 2017": HYUNDAI.HYUNDAI_ELANTRA, + "HYUNDAI I30 N LINE 2019 & GT 2018 DCT": HYUNDAI.HYUNDAI_ELANTRA_GT_I30, + "HYUNDAI ELANTRA 2021": HYUNDAI.HYUNDAI_ELANTRA_2021, + "HYUNDAI ELANTRA HYBRID 2021": HYUNDAI.HYUNDAI_ELANTRA_HEV_2021, + "HYUNDAI GENESIS 2015-2016": HYUNDAI.HYUNDAI_GENESIS, + "HYUNDAI IONIQ HYBRID 2017-2019": HYUNDAI.HYUNDAI_IONIQ, + "HYUNDAI IONIQ HYBRID 2020-2022": HYUNDAI.HYUNDAI_IONIQ_HEV_2022, + "HYUNDAI IONIQ ELECTRIC LIMITED 2019": HYUNDAI.HYUNDAI_IONIQ_EV_LTD, + "HYUNDAI IONIQ ELECTRIC 2020": HYUNDAI.HYUNDAI_IONIQ_EV_2020, + "HYUNDAI IONIQ PLUG-IN HYBRID 2019": HYUNDAI.HYUNDAI_IONIQ_PHEV_2019, + "HYUNDAI IONIQ PHEV 2020": HYUNDAI.HYUNDAI_IONIQ_PHEV, + "HYUNDAI KONA 2020": HYUNDAI.HYUNDAI_KONA, + "HYUNDAI KONA ELECTRIC 2019": HYUNDAI.HYUNDAI_KONA_EV, + "HYUNDAI KONA ELECTRIC 2022": HYUNDAI.HYUNDAI_KONA_EV_2022, + "HYUNDAI KONA ELECTRIC 2ND GEN": HYUNDAI.HYUNDAI_KONA_EV_2ND_GEN, + "HYUNDAI KONA HYBRID 2020": HYUNDAI.HYUNDAI_KONA_HEV, + "HYUNDAI SANTA FE 2019": HYUNDAI.HYUNDAI_SANTA_FE, + "HYUNDAI SANTA FE 2022": HYUNDAI.HYUNDAI_SANTA_FE_2022, + "HYUNDAI SANTA FE HYBRID 2022": HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022, + "HYUNDAI SANTA FE PlUG-IN HYBRID 2022": HYUNDAI.HYUNDAI_SANTA_FE_PHEV_2022, + "HYUNDAI SONATA 2020": HYUNDAI.HYUNDAI_SONATA, + "HYUNDAI SONATA 2019": HYUNDAI.HYUNDAI_SONATA_LF, + "HYUNDAI STARIA 4TH GEN": HYUNDAI.HYUNDAI_STARIA_4TH_GEN, + "HYUNDAI TUCSON 2019": HYUNDAI.HYUNDAI_TUCSON, + "HYUNDAI PALISADE 2020": HYUNDAI.HYUNDAI_PALISADE, + "HYUNDAI VELOSTER 2019": HYUNDAI.HYUNDAI_VELOSTER, + "HYUNDAI SONATA HYBRID 2021": HYUNDAI.HYUNDAI_SONATA_HYBRID, + "HYUNDAI IONIQ 5 2022": HYUNDAI.HYUNDAI_IONIQ_5, + "HYUNDAI IONIQ 6 2023": HYUNDAI.HYUNDAI_IONIQ_6, + "HYUNDAI TUCSON 4TH GEN": HYUNDAI.HYUNDAI_TUCSON_4TH_GEN, + "HYUNDAI SANTA CRUZ 1ST GEN": HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN, + "HYUNDAI CUSTIN 1ST GEN": HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN, + "KIA FORTE E 2018 & GT 2021": HYUNDAI.KIA_FORTE, + "KIA K5 2021": HYUNDAI.KIA_K5_2021, + "KIA K5 HYBRID 2020": HYUNDAI.KIA_K5_HEV_2020, + "KIA K8 HYBRID 1ST GEN": HYUNDAI.KIA_K8_HEV_1ST_GEN, + "KIA NIRO EV 2020": HYUNDAI.KIA_NIRO_EV, + "KIA NIRO EV 2ND GEN": HYUNDAI.KIA_NIRO_EV_2ND_GEN, + "KIA NIRO HYBRID 2019": HYUNDAI.KIA_NIRO_PHEV, + "KIA NIRO PLUG-IN HYBRID 2022": HYUNDAI.KIA_NIRO_PHEV_2022, + "KIA NIRO HYBRID 2021": HYUNDAI.KIA_NIRO_HEV_2021, + "KIA NIRO HYBRID 2ND GEN": HYUNDAI.KIA_NIRO_HEV_2ND_GEN, + "KIA OPTIMA 4TH GEN": HYUNDAI.KIA_OPTIMA_G4, + "KIA OPTIMA 4TH GEN FACELIFT": HYUNDAI.KIA_OPTIMA_G4_FL, + "KIA OPTIMA HYBRID 2017 & SPORTS 2019": HYUNDAI.KIA_OPTIMA_H, + "KIA OPTIMA HYBRID 4TH GEN FACELIFT": HYUNDAI.KIA_OPTIMA_H_G4_FL, + "KIA SELTOS 2021": HYUNDAI.KIA_SELTOS, + "KIA SPORTAGE 5TH GEN": HYUNDAI.KIA_SPORTAGE_5TH_GEN, + "KIA SORENTO GT LINE 2018": HYUNDAI.KIA_SORENTO, + "KIA SORENTO 4TH GEN": HYUNDAI.KIA_SORENTO_4TH_GEN, + "KIA SORENTO HYBRID 4TH GEN": HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, + "KIA STINGER GT2 2018": HYUNDAI.KIA_STINGER, + "KIA STINGER 2022": HYUNDAI.KIA_STINGER_2022, + "KIA CEED INTRO ED 2019": HYUNDAI.KIA_CEED, + "KIA EV6 2022": HYUNDAI.KIA_EV6, + "KIA CARNIVAL 4TH GEN": HYUNDAI.KIA_CARNIVAL_4TH_GEN, + "GENESIS GV60 ELECTRIC 1ST GEN": HYUNDAI.GENESIS_GV60_EV_1ST_GEN, + "GENESIS G70 2018": HYUNDAI.GENESIS_G70, + "GENESIS G70 2020": HYUNDAI.GENESIS_G70_2020, + "GENESIS GV70 1ST GEN": HYUNDAI.GENESIS_GV70_1ST_GEN, + "GENESIS G80 2017": HYUNDAI.GENESIS_G80, + "GENESIS G90 2017": HYUNDAI.GENESIS_G90, + "GENESIS GV80 2023": HYUNDAI.GENESIS_GV80, + "MAZDA CX-5": MAZDA.MAZDA_CX5, + "MAZDA CX-9": MAZDA.MAZDA_CX9, + "MAZDA 3": MAZDA.MAZDA_3, + "MAZDA 6": MAZDA.MAZDA_6, + "MAZDA CX-9 2021": MAZDA.MAZDA_CX9_2021, + "MAZDA CX-5 2022": MAZDA.MAZDA_CX5_2022, + "NISSAN X-TRAIL 2017": NISSAN.NISSAN_XTRAIL, + "NISSAN LEAF 2018": NISSAN.NISSAN_LEAF, + "NISSAN LEAF 2018 Instrument Cluster": NISSAN.NISSAN_LEAF_IC, + "NISSAN ROGUE 2019": NISSAN.NISSAN_ROGUE, + "NISSAN ALTIMA 2020": NISSAN.NISSAN_ALTIMA, + "SUBARU ASCENT LIMITED 2019": SUBARU.SUBARU_ASCENT, + "SUBARU OUTBACK 6TH GEN": SUBARU.SUBARU_OUTBACK, + "SUBARU LEGACY 7TH GEN": SUBARU.SUBARU_LEGACY, + "SUBARU IMPREZA LIMITED 2019": SUBARU.SUBARU_IMPREZA, + "SUBARU IMPREZA SPORT 2020": SUBARU.SUBARU_IMPREZA_2020, + "SUBARU CROSSTREK HYBRID 2020": SUBARU.SUBARU_CROSSTREK_HYBRID, + "SUBARU FORESTER 2019": SUBARU.SUBARU_FORESTER, + "SUBARU FORESTER HYBRID 2020": SUBARU.SUBARU_FORESTER_HYBRID, + "SUBARU FORESTER 2017 - 2018": SUBARU.SUBARU_FORESTER_PREGLOBAL, + "SUBARU LEGACY 2015 - 2018": SUBARU.SUBARU_LEGACY_PREGLOBAL, + "SUBARU OUTBACK 2015 - 2017": SUBARU.SUBARU_OUTBACK_PREGLOBAL, + "SUBARU OUTBACK 2018 - 2019": SUBARU.SUBARU_OUTBACK_PREGLOBAL_2018, + "SUBARU FORESTER 2022": SUBARU.SUBARU_FORESTER_2022, + "SUBARU OUTBACK 7TH GEN": SUBARU.SUBARU_OUTBACK_2023, + "SUBARU ASCENT 2023": SUBARU.SUBARU_ASCENT_2023, + "TOYOTA ALPHARD 2020": TOYOTA.TOYOTA_ALPHARD_TSS2, + "TOYOTA AVALON 2016": TOYOTA.TOYOTA_AVALON, + "TOYOTA AVALON 2019": TOYOTA.TOYOTA_AVALON_2019, + "TOYOTA AVALON 2022": TOYOTA.TOYOTA_AVALON_TSS2, + "TOYOTA CAMRY 2018": TOYOTA.TOYOTA_CAMRY, + "TOYOTA CAMRY 2021": TOYOTA.TOYOTA_CAMRY_TSS2, + "TOYOTA C-HR 2018": TOYOTA.TOYOTA_CHR, + "TOYOTA C-HR 2021": TOYOTA.TOYOTA_CHR_TSS2, + "TOYOTA COROLLA 2017": TOYOTA.TOYOTA_COROLLA, + "TOYOTA COROLLA TSS2 2019": TOYOTA.TOYOTA_COROLLA_TSS2, + "TOYOTA HIGHLANDER 2017": TOYOTA.TOYOTA_HIGHLANDER, + "TOYOTA HIGHLANDER 2020": TOYOTA.TOYOTA_HIGHLANDER_TSS2, + "TOYOTA PRIUS 2017": TOYOTA.TOYOTA_PRIUS, + "TOYOTA PRIUS v 2017": TOYOTA.TOYOTA_PRIUS_V, + "TOYOTA PRIUS TSS2 2021": TOYOTA.TOYOTA_PRIUS_TSS2, + "TOYOTA RAV4 2017": TOYOTA.TOYOTA_RAV4, + "TOYOTA RAV4 HYBRID 2017": TOYOTA.TOYOTA_RAV4H, + "TOYOTA RAV4 2019": TOYOTA.TOYOTA_RAV4_TSS2, + "TOYOTA RAV4 2022": TOYOTA.TOYOTA_RAV4_TSS2_2022, + "TOYOTA RAV4 2023": TOYOTA.TOYOTA_RAV4_TSS2_2023, + "TOYOTA MIRAI 2021": TOYOTA.TOYOTA_MIRAI, + "TOYOTA SIENNA 2018": TOYOTA.TOYOTA_SIENNA, + "LEXUS CT HYBRID 2018": TOYOTA.LEXUS_CTH, + "LEXUS ES 2018": TOYOTA.LEXUS_ES, + "LEXUS ES 2019": TOYOTA.LEXUS_ES_TSS2, + "LEXUS IS 2018": TOYOTA.LEXUS_IS, + "LEXUS IS 2023": TOYOTA.LEXUS_IS_TSS2, + "LEXUS NX 2018": TOYOTA.LEXUS_NX, + "LEXUS NX 2020": TOYOTA.LEXUS_NX_TSS2, + "LEXUS LC 2024": TOYOTA.LEXUS_LC_TSS2, + "LEXUS RC 2020": TOYOTA.LEXUS_RC, + "LEXUS RX 2016": TOYOTA.LEXUS_RX, + "LEXUS RX 2020": TOYOTA.LEXUS_RX_TSS2, + "LEXUS GS F 2016": TOYOTA.LEXUS_GS_F, + "VOLKSWAGEN ARTEON 1ST GEN": VW.VOLKSWAGEN_ARTEON_MK1, + "VOLKSWAGEN ATLAS 1ST GEN": VW.VOLKSWAGEN_ATLAS_MK1, + "VOLKSWAGEN CADDY 3RD GEN": VW.VOLKSWAGEN_CADDY_MK3, + "VOLKSWAGEN CRAFTER 2ND GEN": VW.VOLKSWAGEN_CRAFTER_MK2, + "VOLKSWAGEN GOLF 7TH GEN": VW.VOLKSWAGEN_GOLF_MK7, + "VOLKSWAGEN JETTA 6TH GEN": VW.VOLKSWAGEN_JETTA_MK6, + "VOLKSWAGEN JETTA 7TH GEN": VW.VOLKSWAGEN_JETTA_MK7, + "VOLKSWAGEN PASSAT 8TH GEN": VW.VOLKSWAGEN_PASSAT_MK8, + "VOLKSWAGEN PASSAT NMS": VW.VOLKSWAGEN_PASSAT_NMS, + "VOLKSWAGEN POLO 6TH GEN": VW.VOLKSWAGEN_POLO_MK6, + "VOLKSWAGEN SHARAN 2ND GEN": VW.VOLKSWAGEN_SHARAN_MK2, + "VOLKSWAGEN TAOS 1ST GEN": VW.VOLKSWAGEN_TAOS_MK1, + "VOLKSWAGEN T-CROSS 1ST GEN": VW.VOLKSWAGEN_TCROSS_MK1, + "VOLKSWAGEN TIGUAN 2ND GEN": VW.VOLKSWAGEN_TIGUAN_MK2, + "VOLKSWAGEN TOURAN 2ND GEN": VW.VOLKSWAGEN_TOURAN_MK2, + "VOLKSWAGEN TRANSPORTER T6.1": VW.VOLKSWAGEN_TRANSPORTER_T61, + "VOLKSWAGEN T-ROC 1ST GEN": VW.VOLKSWAGEN_TROC_MK1, + "AUDI A3 3RD GEN": VW.AUDI_A3_MK3, + "AUDI Q2 1ST GEN": VW.AUDI_Q2_MK1, + "AUDI Q3 2ND GEN": VW.AUDI_Q3_MK2, + "SEAT ATECA 1ST GEN": VW.SEAT_ATECA_MK1, + "SEAT LEON 3RD GEN": VW.SEAT_ATECA_MK1, + "SEAT_LEON_MK3": VW.SEAT_ATECA_MK1, + "SKODA FABIA 4TH GEN": VW.SKODA_FABIA_MK4, + "SKODA KAMIQ 1ST GEN": VW.SKODA_KAMIQ_MK1, + "SKODA KAROQ 1ST GEN": VW.SKODA_KAROQ_MK1, + "SKODA KODIAQ 1ST GEN": VW.SKODA_KODIAQ_MK1, + "SKODA OCTAVIA 3RD GEN": VW.SKODA_OCTAVIA_MK3, + "SKODA SCALA 1ST GEN": VW.SKODA_KAMIQ_MK1, + "SKODA_SCALA_MK1": VW.SKODA_KAMIQ_MK1, + "SKODA SUPERB 3RD GEN": VW.SKODA_SUPERB_MK3, + + "mock": MOCK.MOCK, +} diff --git a/opendbc_repo/opendbc/car/ford/__init__.py b/opendbc_repo/opendbc/car/ford/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/ford/carcontroller.py b/opendbc_repo/opendbc/car/ford/carcontroller.py new file mode 100644 index 0000000000..914668256c --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/carcontroller.py @@ -0,0 +1,203 @@ +import math +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY, Bus, DT_CTRL, apply_hysteresis, structs +from opendbc.car.lateral import ISO_LATERAL_ACCEL, apply_std_steer_angle_limits +from opendbc.car.ford import fordcan +from opendbc.car.ford.values import CarControllerParams, FordFlags, CAR +from opendbc.car.interfaces import CarControllerBase, V_CRUISE_MAX + +LongCtrlState = structs.CarControl.Actuators.LongControlState +VisualAlert = structs.CarControl.HUDControl.VisualAlert + +# CAN FD limits: +# Limit to average banked road since safety doesn't have the roll +AVERAGE_ROAD_ROLL = 0.06 # ~3.4 degrees, 6% superelevation. higher actual roll raises lateral acceleration +MAX_LATERAL_ACCEL = ISO_LATERAL_ACCEL - (ACCELERATION_DUE_TO_GRAVITY * AVERAGE_ROAD_ROLL) # ~2.4 m/s^2 + + +def anti_overshoot(apply_curvature, apply_curvature_last, v_ego): + diff = 0.1 + tau = 5 # 5s smooths over the overshoot + dt = DT_CTRL * CarControllerParams.STEER_STEP + alpha = 1 - np.exp(-dt / tau) + + lataccel = apply_curvature * (v_ego ** 2) + last_lataccel = apply_curvature_last * (v_ego ** 2) + last_lataccel = apply_hysteresis(lataccel, last_lataccel, diff) + last_lataccel = alpha * lataccel + (1 - alpha) * last_lataccel + + output_curvature = last_lataccel / (max(v_ego, 1) ** 2) + + return float(np.interp(v_ego, [5, 10], [apply_curvature, output_curvature])) + + +def apply_ford_curvature_limits(apply_curvature, apply_curvature_last, current_curvature, v_ego_raw, steering_angle, lat_active, CP): + # No blending at low speed due to lack of torque wind-up and inaccurate current curvature + if v_ego_raw > 9: + apply_curvature = np.clip(apply_curvature, current_curvature - CarControllerParams.CURVATURE_ERROR, + current_curvature + CarControllerParams.CURVATURE_ERROR) + + # Curvature rate limit after driver torque limit + apply_curvature = apply_std_steer_angle_limits(apply_curvature, apply_curvature_last, v_ego_raw, steering_angle, lat_active, CarControllerParams.ANGLE_LIMITS) + + # Ford Q4/CAN FD has more torque available compared to Q3/CAN so we limit it based on lateral acceleration. + # Safety is not aware of the road roll so we subtract a conservative amount at all times + if CP.flags & FordFlags.CANFD: + # Limit curvature to conservative max lateral acceleration + curvature_accel_limit = MAX_LATERAL_ACCEL / (max(v_ego_raw, 1) ** 2) + apply_curvature = float(np.clip(apply_curvature, -curvature_accel_limit, curvature_accel_limit)) + + return apply_curvature + + +def apply_creep_compensation(accel: float, v_ego: float) -> float: + creep_accel = np.interp(v_ego, [1., 3.], [0.6, 0.]) + creep_accel = np.interp(accel, [0., 0.2], [creep_accel, 0.]) + accel -= creep_accel + return float(accel) + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.packer = CANPacker(dbc_names[Bus.pt]) + self.CAN = fordcan.CanBus(CP) + + self.apply_curvature_last = 0 + self.anti_overshoot_curvature_last = 0 + self.accel = 0.0 + self.gas = 0.0 + self.brake_request = False + self.main_on_last = False + self.lkas_enabled_last = False + self.steer_alert_last = False + self.lead_distance_bars_last = None + self.distance_bar_frame = 0 + + def update(self, CC, CS, now_nanos): + can_sends = [] + + actuators = CC.actuators + hud_control = CC.hudControl + + main_on = CS.out.cruiseState.available + steer_alert = hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw) + fcw_alert = hud_control.visualAlert == VisualAlert.fcw + + ### acc buttons ### + if CC.cruiseControl.cancel: + can_sends.append(fordcan.create_button_msg(self.packer, self.CAN.camera, CS.buttons_stock_values, cancel=True)) + can_sends.append(fordcan.create_button_msg(self.packer, self.CAN.main, CS.buttons_stock_values, cancel=True)) + elif CC.cruiseControl.resume and (self.frame % CarControllerParams.BUTTONS_STEP) == 0: + can_sends.append(fordcan.create_button_msg(self.packer, self.CAN.camera, CS.buttons_stock_values, resume=True)) + can_sends.append(fordcan.create_button_msg(self.packer, self.CAN.main, CS.buttons_stock_values, resume=True)) + # if stock lane centering isn't off, send a button press to toggle it off + # the stock system checks for steering pressed, and eventually disengages cruise control + elif CS.acc_tja_status_stock_values["Tja_D_Stat"] != 0 and (self.frame % CarControllerParams.ACC_UI_STEP) == 0: + can_sends.append(fordcan.create_button_msg(self.packer, self.CAN.camera, CS.buttons_stock_values, tja_toggle=True)) + + ### lateral control ### + # send steer msg at 20Hz + if (self.frame % CarControllerParams.STEER_STEP) == 0: + # Bronco and some other cars consistently overshoot curv requests + # Apply some deadzone + smoothing convergence to avoid oscillations + if self.CP.carFingerprint in (CAR.FORD_BRONCO_SPORT_MK1, CAR.FORD_F_150_MK14): + self.anti_overshoot_curvature_last = anti_overshoot(actuators.curvature, self.anti_overshoot_curvature_last, CS.out.vEgoRaw) + apply_curvature = self.anti_overshoot_curvature_last + else: + apply_curvature = actuators.curvature + + # apply rate limits, curvature error limit, and clip to signal range + current_curvature = -CS.out.yawRate / max(CS.out.vEgoRaw, 0.1) + + self.apply_curvature_last = apply_ford_curvature_limits(apply_curvature, self.apply_curvature_last, current_curvature, + CS.out.vEgoRaw, 0., CC.latActive, self.CP) + + if self.CP.flags & FordFlags.CANFD: + # TODO: extended mode + # Ford uses four individual signals to dictate how to drive to the car. Curvature alone (limited to 0.02m/s^2) + # can actuate the steering for a large portion of any lateral movements. However, in order to get further control on + # steer actuation, the other three signals are necessary. Ford controls vehicles differently than most other makes. + # A detailed explanation on ford control can be found here: + # https://www.f150gen14.com/forum/threads/introducing-bluepilot-a-ford-specific-fork-for-comma3x-openpilot.24241/#post-457706 + mode = 1 if CC.latActive else 0 + counter = (self.frame // CarControllerParams.STEER_STEP) % 0x10 + can_sends.append(fordcan.create_lat_ctl2_msg(self.packer, self.CAN, mode, 0., 0., -self.apply_curvature_last, 0., counter)) + else: + can_sends.append(fordcan.create_lat_ctl_msg(self.packer, self.CAN, CC.latActive, 0., 0., -self.apply_curvature_last, 0.)) + + # send lka msg at 33Hz + if (self.frame % CarControllerParams.LKA_STEP) == 0: + can_sends.append(fordcan.create_lka_msg(self.packer, self.CAN)) + + ### longitudinal control ### + # send acc msg at 50Hz + if self.CP.openpilotLongitudinalControl and (self.frame % CarControllerParams.ACC_CONTROL_STEP) == 0: + accel = actuators.accel + gas = accel + + if CC.longActive: + # Compensate for engine creep at low speed. + # Either the ABS does not account for engine creep, or the correction is very slow + # TODO: verify this applies to EV/hybrid + accel = apply_creep_compensation(accel, CS.out.vEgo) + + # The stock system has been seen rate limiting the brake accel to 5 m/s^3, + # however even 3.5 m/s^3 causes some overshoot with a step response. + accel = max(accel, self.accel - (3.5 * CarControllerParams.ACC_CONTROL_STEP * DT_CTRL)) + + accel = float(np.clip(accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)) + gas = float(np.clip(gas, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)) + + # Both gas and accel are in m/s^2, accel is used solely for braking + if not CC.longActive or gas < CarControllerParams.MIN_GAS: + gas = CarControllerParams.INACTIVE_GAS + + # PCM applies pitch compensation to gas/accel, but we need to compensate for the brake/pre-charge bits + accel_due_to_pitch = 0.0 + if len(CC.orientationNED) == 3: + accel_due_to_pitch = math.sin(CC.orientationNED[1]) * ACCELERATION_DUE_TO_GRAVITY + + accel_pitch_compensated = accel + accel_due_to_pitch + if accel_pitch_compensated > 0.3 or not CC.longActive: + self.brake_request = False + elif accel_pitch_compensated < 0.0: + self.brake_request = True + + stopping = CC.actuators.longControlState == LongCtrlState.stopping + # TODO: look into using the actuators packet to send the desired speed + can_sends.append(fordcan.create_acc_msg(self.packer, self.CAN, CC.longActive, gas, accel, stopping, self.brake_request, v_ego_kph=V_CRUISE_MAX)) + + self.accel = accel + self.gas = gas + + ### ui ### + send_ui = (self.main_on_last != main_on) or (self.lkas_enabled_last != CC.latActive) or (self.steer_alert_last != steer_alert) + # send lkas ui msg at 1Hz or if ui state changes + if (self.frame % CarControllerParams.LKAS_UI_STEP) == 0 or send_ui: + can_sends.append(fordcan.create_lkas_ui_msg(self.packer, self.CAN, main_on, CC.latActive, steer_alert, hud_control, CS.lkas_status_stock_values)) + + # send acc ui msg at 5Hz or if ui state changes + if hud_control.leadDistanceBars != self.lead_distance_bars_last: + send_ui = True + self.distance_bar_frame = self.frame + + if (self.frame % CarControllerParams.ACC_UI_STEP) == 0 or send_ui: + show_distance_bars = self.frame - self.distance_bar_frame < 400 + can_sends.append(fordcan.create_acc_ui_msg(self.packer, self.CAN, self.CP, main_on, CC.latActive, + fcw_alert, CS.out.cruiseState.standstill, show_distance_bars, + hud_control, CS.acc_tja_status_stock_values)) + + self.main_on_last = main_on + self.lkas_enabled_last = CC.latActive + self.steer_alert_last = steer_alert + self.lead_distance_bars_last = hud_control.leadDistanceBars + + new_actuators = actuators.as_builder() + new_actuators.curvature = self.apply_curvature_last + new_actuators.accel = self.accel + new_actuators.gas = self.gas + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/ford/carstate.py b/opendbc_repo/opendbc/car/ford/carstate.py new file mode 100644 index 0000000000..d0d45f7076 --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/carstate.py @@ -0,0 +1,123 @@ +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.ford.fordcan import CanBus +from opendbc.car.ford.values import DBC, CarControllerParams, FordFlags +from opendbc.car.interfaces import CarStateBase + +ButtonType = structs.CarState.ButtonEvent.Type +GearShifter = structs.CarState.GearShifter +TransmissionType = structs.CarParams.TransmissionType + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + if CP.transmissionType == TransmissionType.automatic: + self.shifter_values = can_define.dv["PowertrainData_10"]["TrnRng_D_Rq"] + + self.distance_button = 0 + self.lc_button = 0 + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + + ret = structs.CarState() + + # Occasionally on startup, the ABS module recalibrates the steering pinion offset, so we need to block engagement + # The vehicle usually recovers out of this state within a minute of normal driving + ret.vehicleSensorsInvalid = cp.vl["SteeringPinion_Data"]["StePinCompAnEst_D_Qf"] != 3 + + # car speed + ret.vEgoRaw = cp.vl["BrakeSysFeatures"]["Veh_V_ActlBrk"] * CV.KPH_TO_MS + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.yawRate = cp.vl["Yaw_Data_FD1"]["VehYaw_W_Actl"] + ret.standstill = cp.vl["DesiredTorqBrk"]["VehStop_D_Stat"] == 1 + + # gas pedal + ret.gasPressed = cp.vl["EngVehicleSpThrottle"]["ApedPos_Pc_ActlArb"] / 100. > 1e-6 + + # brake pedal + ret.brake = cp.vl["BrakeSnData_4"]["BrkTot_Tq_Actl"] / 32756. # torque in Nm + ret.brakePressed = cp.vl["EngBrakeData"]["BpedDrvAppl_D_Actl"] == 2 + ret.parkingBrake = cp.vl["DesiredTorqBrk"]["PrkBrkStatus"] in (1, 2) + + # steering wheel + ret.steeringAngleDeg = cp.vl["SteeringPinion_Data"]["StePinComp_An_Est"] + ret.steeringTorque = cp.vl["EPAS_INFO"]["SteeringColumnTorque"] + ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > CarControllerParams.STEER_DRIVER_ALLOWANCE, 5) + ret.steerFaultTemporary = cp.vl["EPAS_INFO"]["EPAS_Failure"] == 1 + ret.steerFaultPermanent = cp.vl["EPAS_INFO"]["EPAS_Failure"] in (2, 3) + ret.espDisabled = cp.vl["Cluster_Info1_FD1"]["DrvSlipCtlMde_D_Rq"] != 0 # 0 is default mode + + if self.CP.flags & FordFlags.CANFD: + # this signal is always 0 on non-CAN FD cars + ret.steerFaultTemporary |= cp.vl["Lane_Assist_Data3_FD1"]["LatCtlSte_D_Stat"] not in (1, 2, 3) + + # cruise state + is_metric = cp.vl["INSTRUMENT_PANEL"]["METRIC_UNITS"] == 1 if not self.CP.flags & FordFlags.CANFD else False + ret.cruiseState.speed = cp.vl["EngBrakeData"]["Veh_V_DsplyCcSet"] * (CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS) + ret.cruiseState.enabled = cp.vl["EngBrakeData"]["CcStat_D_Actl"] in (4, 5) + ret.cruiseState.available = cp.vl["EngBrakeData"]["CcStat_D_Actl"] in (3, 4, 5) + ret.cruiseState.nonAdaptive = cp.vl["Cluster_Info1_FD1"]["AccEnbl_B_RqDrv"] == 0 + ret.cruiseState.standstill = cp.vl["EngBrakeData"]["AccStopMde_D_Rq"] == 3 + ret.accFaulted = cp.vl["EngBrakeData"]["CcStat_D_Actl"] in (1, 2) + if not self.CP.openpilotLongitudinalControl: + ret.accFaulted = ret.accFaulted or cp_cam.vl["ACCDATA"]["CmbbDeny_B_Actl"] == 1 + + # gear + if self.CP.transmissionType == TransmissionType.automatic: + gear = self.shifter_values.get(cp.vl["PowertrainData_10"]["TrnRng_D_Rq"]) + ret.gearShifter = self.parse_gear_shifter(gear) + elif self.CP.transmissionType == TransmissionType.manual: + if bool(cp.vl["BCM_Lamp_Stat_FD1"]["RvrseLghtOn_B_Stat"]): + ret.gearShifter = GearShifter.reverse + else: + ret.gearShifter = GearShifter.drive + + # safety + ret.stockFcw = bool(cp_cam.vl["ACCDATA_3"]["FcwVisblWarn_B_Rq"]) + ret.stockAeb = bool(cp_cam.vl["ACCDATA_2"]["CmbbBrkDecel_B_Rq"]) + + # button presses + ret.leftBlinker = cp.vl["Steering_Data_FD1"]["TurnLghtSwtch_D_Stat"] == 1 + ret.rightBlinker = cp.vl["Steering_Data_FD1"]["TurnLghtSwtch_D_Stat"] == 2 + # TODO: block this going to the camera otherwise it will enable stock TJA + ret.genericToggle = bool(cp.vl["Steering_Data_FD1"]["TjaButtnOnOffPress"]) + prev_distance_button = self.distance_button + prev_lc_button = self.lc_button + self.distance_button = cp.vl["Steering_Data_FD1"]["AccButtnGapTogglePress"] + self.lc_button = bool(cp.vl["Steering_Data_FD1"]["TjaButtnOnOffPress"]) + + # lock info + ret.doorOpen = any([cp.vl["BodyInfo_3_FD1"]["DrStatDrv_B_Actl"], cp.vl["BodyInfo_3_FD1"]["DrStatPsngr_B_Actl"], + cp.vl["BodyInfo_3_FD1"]["DrStatRl_B_Actl"], cp.vl["BodyInfo_3_FD1"]["DrStatRr_B_Actl"]]) + ret.seatbeltUnlatched = cp.vl["RCMStatusMessage2_FD1"]["FirstRowBuckleDriver"] == 2 + + # blindspot sensors + if self.CP.enableBsm: + cp_bsm = cp_cam if self.CP.flags & FordFlags.CANFD else cp + ret.leftBlindspot = cp_bsm.vl["Side_Detect_L_Stat"]["SodDetctLeft_D_Stat"] != 0 + ret.rightBlindspot = cp_bsm.vl["Side_Detect_R_Stat"]["SodDetctRight_D_Stat"] != 0 + + # Stock steering buttons so that we can passthru blinkers etc. + self.buttons_stock_values = cp.vl["Steering_Data_FD1"] + # Stock values from IPMA so that we can retain some stock functionality + self.acc_tja_status_stock_values = cp_cam.vl["ACCDATA_3"] + self.lkas_status_stock_values = cp_cam.vl["IPMA_Data"] + + ret.buttonEvents = [ + *create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}), + *create_button_events(self.lc_button, prev_lc_button, {1: ButtonType.lkas}), + ] + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).main), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).camera), + } diff --git a/opendbc_repo/opendbc/car/ford/fingerprints.py b/opendbc_repo/opendbc/car/ford/fingerprints.py new file mode 100644 index 0000000000..6b3e33701f --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/fingerprints.py @@ -0,0 +1,223 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.ford.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.FORD_BRONCO_SPORT_MK1: { + (Ecu.eps, 0x730, None): [ + b'LX6C-14D003-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-14D003-AK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'LX6C-2D053-RD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-2D053-RE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-2D053-RF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'M1PT-14F397-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'M1PT-14F397-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_ESCAPE_MK4: { + (Ecu.eps, 0x730, None): [ + b'LX6C-14D003-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-14D003-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-14D003-AK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'LX6C-2D053-NS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-2D053-NT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-2D053-NY\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-2D053-SA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-2D053-SD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'LJ6T-14F397-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LJ6T-14F397-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LV4T-14F397-GG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_ESCAPE_MK4_5: { + (Ecu.eps, 0x730, None): [ + b'PZ11-14D003-EA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'PZ1C-2D053-EJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'ML3T-14D049-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'PJ6T-14H102-ABL\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_EXPLORER_MK6: { + (Ecu.eps, 0x730, None): [ + b'L1MC-14D003-AJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-14D003-AK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'M1MC-14D003-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'M1MC-14D003-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'P1MC-14D003-AA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'L1MC-2D053-AJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-2D053-BA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-2D053-BB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-2D053-BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-2D053-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-2D053-BJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'L1MC-2D053-KB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'LB5T-14F397-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LB5T-14F397-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LB5T-14F397-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LC5T-14F397-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LC5T-14F397-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_EXPEDITION_MK4: { + (Ecu.eps, 0x730, None): [ + b'NL14-14D003-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'RL14-2D053-AA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'ML3T-14D049-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'ML3T-14H102-ABT\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_F_150_MK14: { + (Ecu.eps, 0x730, None): [ + b'ML3V-14D003-BC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'ML3V-14D003-BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'NL34-2D053-CA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PL34-2D053-CA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PL34-2D053-CC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PL3V-2D053-BA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PL3V-2D053-BB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'ML3T-14D049-AK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'ML3T-14D049-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'ML3T-14H102-ABR\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'ML3T-14H102-ABS\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'ML3T-14H102-ABT\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PJ6T-14H102-ABJ\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PJ6T-14H102-ABS\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RJ6T-14H102-ACJ\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RJ6T-14H102-BBC\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_F_150_LIGHTNING_MK1: { + (Ecu.abs, 0x760, None): [ + b'PL38-2D053-AA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RL38-2D053-BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'ML3T-14H102-ABT\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RJ6T-14H102-ACJ\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RJ6T-14H102-BBC\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'ML3T-14D049-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x730, None): [ + b'RL38-14D003-AA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_MUSTANG_MACH_E_MK1: { + (Ecu.eps, 0x730, None): [ + b'LJ9C-14D003-AM\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LJ9C-14D003-CC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LJ9C-14D003-FA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LJ9C-14D003-GA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LJ9C-14D003-HA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'LK9C-2D053-CK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LK9C-2D053-CN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'ML3T-14D049-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'ML3T-14H102-ABS\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RJ6T-14H102-BAE\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_FOCUS_MK4: { + (Ecu.eps, 0x730, None): [ + b'JX6C-14D003-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'JX61-2D053-CJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'JX7T-14D049-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'JX7T-14F397-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_MAVERICK_MK1: { + (Ecu.eps, 0x730, None): [ + b'NZ6C-14D003-AK\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'NZ6C-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'NZ6C-2D053-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'NZ6C-2D053-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'NZ6C-2D053-AG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PZ6C-2D053-ED\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PZ6C-2D053-EE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PZ6C-2D053-EF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'NZ6T-14D049-AA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'NZ6T-14F397-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.FORD_RANGER_MK2: { + (Ecu.eps, 0x730, None): [ + b'NB3C-14D003-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'NL14-14D003-AE\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RB3C-14D003-AA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'PB3C-2D053-ZD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PB3C-2D053-ZG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PB3C-2D053-ZJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'ML3T-14D049-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'PJ6T-14H102-ABJ\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'RJ6T-14H102-BBB\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/ford/fordcan.py b/opendbc_repo/opendbc/car/ford/fordcan.py new file mode 100644 index 0000000000..2ac68c4427 --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/fordcan.py @@ -0,0 +1,342 @@ +from opendbc.car import CanBusBase, structs + +HUDControl = structs.CarControl.HUDControl + + +class CanBus(CanBusBase): + def __init__(self, CP=None, fingerprint=None) -> None: + super().__init__(CP, fingerprint) + + @property + def main(self) -> int: + return self.offset + + @property + def radar(self) -> int: + return self.offset + 1 + + @property + def camera(self) -> int: + return self.offset + 2 + + +def calculate_lat_ctl2_checksum(mode: int, counter: int, dat: bytearray) -> int: + curvature = (dat[2] << 3) | ((dat[3]) >> 5) + curvature_rate = (dat[6] << 3) | ((dat[7]) >> 5) + path_angle = ((dat[3] & 0x1F) << 6) | ((dat[4]) >> 2) + path_offset = ((dat[4] & 0x3) << 8) | dat[5] + + checksum = mode + counter + for sig_val in (curvature, curvature_rate, path_angle, path_offset): + checksum += sig_val + (sig_val >> 8) + + return 0xFF - (checksum & 0xFF) + + +def create_lka_msg(packer, CAN: CanBus): + """ + Creates an empty CAN message for the Ford LKA Command. + + This command can apply "Lane Keeping Aid" maneuvers, which are subject to the PSCM lockout. + + Frequency is 33Hz. + """ + + return packer.make_can_msg("Lane_Assist_Data1", CAN.main, {}) + + +def create_lat_ctl_msg(packer, CAN: CanBus, lat_active: bool, path_offset: float, path_angle: float, curvature: float, + curvature_rate: float): + """ + Creates a CAN message for the Ford TJA/LCA Command. + + This command can apply "Lane Centering" maneuvers: continuous lane centering for traffic jam assist and highway + driving. It is not subject to the PSCM lockout. + + Ford lane centering command uses a third order polynomial to describe the road centerline. The polynomial is defined + by the following coefficients: + c0: lateral offset between the vehicle and the centerline (positive is right) + c1: heading angle between the vehicle and the centerline (positive is right) + c2: curvature of the centerline (positive is left) + c3: rate of change of curvature of the centerline + As the PSCM combines this information with other sensor data, such as the vehicle's yaw rate and speed, the steering + angle cannot be easily controlled. + + The PSCM should be configured to accept TJA/LCA commands before these commands will be processed. This can be done + using tools such as Forscan. + + Frequency is 20Hz. + """ + + values = { + "LatCtlRng_L_Max": 0, # Unknown [0|126] meter + "HandsOffCnfm_B_Rq": 0, # Unknown: 0=Inactive, 1=Active [0|1] + "LatCtl_D_Rq": 1 if lat_active else 0, # Mode: 0=None, 1=ContinuousPathFollowing, 2=InterventionLeft, + # 3=InterventionRight, 4-7=NotUsed [0|7] + "LatCtlRampType_D_Rq": 0, # Ramp speed: 0=Slow, 1=Medium, 2=Fast, 3=Immediate [0|3] + # Makes no difference with curvature control + "LatCtlPrecision_D_Rq": 1, # Precision: 0=Comfortable, 1=Precise, 2/3=NotUsed [0|3] + # The stock system always uses comfortable + "LatCtlPathOffst_L_Actl": path_offset, # Path offset [-5.12|5.11] meter + "LatCtlPath_An_Actl": path_angle, # Path angle [-0.5|0.5235] radians + "LatCtlCurv_NoRate_Actl": curvature_rate, # Curvature rate [-0.001024|0.00102375] 1/meter^2 + "LatCtlCurv_No_Actl": curvature, # Curvature [-0.02|0.02094] 1/meter + } + return packer.make_can_msg("LateralMotionControl", CAN.main, values) + + +def create_lat_ctl2_msg(packer, CAN: CanBus, mode: int, path_offset: float, path_angle: float, curvature: float, + curvature_rate: float, counter: int): + """ + Create a CAN message for the new Ford Lane Centering command. + + This message is used on the CAN FD platform and replaces the old LateralMotionControl message. It is similar but has + additional signals for a counter and checksum. + + Frequency is 20Hz. + """ + + values = { + "LatCtl_D2_Rq": mode, # Mode: 0=None, 1=PathFollowingLimitedMode, 2=PathFollowingExtendedMode, + # 3=SafeRampOut, 4-7=NotUsed [0|7] + "LatCtlRampType_D_Rq": 0, # 0=Slow, 1=Medium, 2=Fast, 3=Immediate [0|3] + "LatCtlPrecision_D_Rq": 1, # 0=Comfortable, 1=Precise, 2/3=NotUsed [0|3] + "LatCtlPathOffst_L_Actl": path_offset, # [-5.12|5.11] meter + "LatCtlPath_An_Actl": path_angle, # [-0.5|0.5235] radians + "LatCtlCurv_No_Actl": curvature, # [-0.02|0.02094] 1/meter + "LatCtlCrv_NoRate2_Actl": curvature_rate, # [-0.001024|0.001023] 1/meter^2 + "HandsOffCnfm_B_Rq": 0, # 0=Inactive, 1=Active [0|1] + "LatCtlPath_No_Cnt": counter, # [0|15] + "LatCtlPath_No_Cs": 0, # [0|255] + } + + # calculate checksum + dat = packer.make_can_msg("LateralMotionControl2", 0, values)[1] + values["LatCtlPath_No_Cs"] = calculate_lat_ctl2_checksum(mode, counter, dat) + + return packer.make_can_msg("LateralMotionControl2", CAN.main, values) + + +def create_acc_msg(packer, CAN: CanBus, long_active: bool, gas: float, accel: float, stopping: bool, brake_request, v_ego_kph: float): + """ + Creates a CAN message for the Ford ACC Command. + + This command can be used to enable ACC, to set the ACC gas/brake/decel values + and to disable ACC. + + Frequency is 50Hz. + """ + values = { + "AccBrkTot_A_Rq": accel, # Brake total accel request: [-20|11.9449] m/s^2 + "Cmbb_B_Enbl": 1 if long_active else 0, # Enabled: 0=No, 1=Yes + "AccPrpl_A_Rq": gas, # Acceleration request: [-5|5.23] m/s^2 + # No observed acceleration seen from this signal alone. During stock system operation, it appears to + # be the raw acceleration request (AccPrpl_A_Rq when positive, AccBrkTot_A_Rq when negative) + "AccPrpl_A_Pred": -5.0, # Acceleration request: [-5|5.23] m/s^2 + "AccResumEnbl_B_Rq": 1 if long_active else 0, + # No observed acceleration seen from this signal alone + "AccVeh_V_Trg": v_ego_kph, # Target speed: [0|255] km/h + # TODO: we may be able to improve braking response by utilizing pre-charging better + # When setting these two bits without AccBrkTot_A_Rq, an initial jerk is observed and car may be able to brake temporarily with AccPrpl_A_Rq + "AccBrkPrchg_B_Rq": 1 if brake_request else 0, # Pre-charge brake request: 0=No, 1=Yes + "AccBrkDecel_B_Rq": 1 if brake_request else 0, # Deceleration request: 0=Inactive, 1=Active + "AccStopStat_B_Rq": 1 if stopping else 0, + } + return packer.make_can_msg("ACCDATA", CAN.main, values) + + +def create_acc_ui_msg(packer, CAN: CanBus, CP, main_on: bool, enabled: bool, fcw_alert: bool, standstill: bool, + show_distance_bars: bool, hud_control, stock_values: dict): + """ + Creates a CAN message for the Ford IPC adaptive cruise, forward collision warning and traffic jam + assist status. + + Stock functionality is maintained by passing through unmodified signals. + + Frequency is 5Hz. + """ + + # Tja_D_Stat + if enabled: + if hud_control.leftLaneDepart: + status = 3 # ActiveInterventionLeft + elif hud_control.rightLaneDepart: + status = 4 # ActiveInterventionRight + else: + status = 2 # Active + elif main_on: + if hud_control.leftLaneDepart: + status = 5 # ActiveWarningLeft + elif hud_control.rightLaneDepart: + status = 6 # ActiveWarningRight + else: + status = 1 # Standby + else: + status = 0 # Off + + values = {s: stock_values[s] for s in [ + "HaDsply_No_Cs", + "HaDsply_No_Cnt", + "AccStopStat_D_Dsply", # ACC stopped status message + "AccTrgDist2_D_Dsply", # ACC target distance + "AccStopRes_B_Dsply", + "TjaWarn_D_Rq", # TJA warning + "TjaMsgTxt_D_Dsply", # TJA text + "IaccLamp_D_Rq", # iACC status icon + "AccMsgTxt_D2_Rq", # ACC text + "FcwDeny_B_Dsply", # FCW disabled + "FcwMemStat_B_Actl", # FCW enabled setting + "AccTGap_B_Dsply", # ACC time gap display setting + "CadsAlignIncplt_B_Actl", + "AccFllwMde_B_Dsply", # ACC follow mode display setting + "CadsRadrBlck_B_Actl", + "CmbbPostEvnt_B_Dsply", # AEB event status + "AccStopMde_B_Dsply", # ACC stop mode display setting + "FcwMemSens_D_Actl", # FCW sensitivity setting + "FcwMsgTxt_D_Rq", # FCW text + "AccWarn_D_Dsply", # ACC warning + "FcwVisblWarn_B_Rq", # FCW visible alert + "FcwAudioWarn_B_Rq", # FCW audio alert + "AccTGap_D_Dsply", # ACC time gap + "AccMemEnbl_B_RqDrv", # ACC adaptive/normal setting + "FdaMem_B_Stat", # FDA enabled setting + ]} + + values.update({ + "Tja_D_Stat": status, # TJA status + }) + + if CP.openpilotLongitudinalControl: + values.update({ + "AccStopStat_D_Dsply": 2 if standstill else 0, # Stopping status text + "AccMsgTxt_D2_Rq": 0, # ACC text + "AccTGap_B_Dsply": 1 if show_distance_bars else 0, # Show time gap control UI + "AccFllwMde_B_Dsply": 1 if hud_control.leadVisible else 0, # Lead indicator + "AccStopMde_B_Dsply": 1 if standstill else 0, + "AccWarn_D_Dsply": 0, # ACC warning + "AccTGap_D_Dsply": hud_control.leadDistanceBars, # Time gap + }) + + # Forwards FCW alert from IPMA + if fcw_alert: + values["FcwVisblWarn_B_Rq"] = 1 # FCW visible alert + + return packer.make_can_msg("ACCDATA_3", CAN.main, values) + + +def create_lkas_ui_msg(packer, CAN: CanBus, main_on: bool, enabled: bool, steer_alert: bool, hud_control, + stock_values: dict): + """ + Creates a CAN message for the Ford IPC IPMA/LKAS status. + + Show the LKAS status with the "driver assist" lines in the IPC. + + Stock functionality is maintained by passing through unmodified signals. + + Frequency is 1Hz. + """ + + # LaActvStats_D_Dsply + # R Intvn Warn Supprs Avail No + # L + # Intvn 24 19 14 9 4 + # Warn 23 18 13 8 3 + # Supprs 22 17 12 7 2 + # Avail 21 16 11 6 1 + # No 20 15 10 5 0 + # + # TODO: test suppress state + if enabled: + lines = 0 # NoLeft_NoRight + if hud_control.leftLaneDepart: + lines += 4 + elif hud_control.leftLaneVisible: + lines += 1 + if hud_control.rightLaneDepart: + lines += 20 + elif hud_control.rightLaneVisible: + lines += 5 + elif main_on: + lines = 0 + else: + if hud_control.leftLaneDepart: + lines = 3 # WarnLeft_NoRight + elif hud_control.rightLaneDepart: + lines = 15 # NoLeft_WarnRight + else: + lines = 30 # LA_Off + + hands_on_wheel_dsply = 1 if steer_alert else 0 + + values = {s: stock_values[s] for s in [ + "FeatConfigIpmaActl", + "FeatNoIpmaActl", + "PersIndexIpma_D_Actl", + "AhbcRampingV_D_Rq", # AHB ramping + "LaDenyStats_B_Dsply", # LKAS error + "CamraDefog_B_Req", # Windshield heater? + "CamraStats_D_Dsply", # Camera status + "DasAlrtLvl_D_Dsply", # DAS alert level + "DasStats_D_Dsply", # DAS status + "DasWarn_D_Dsply", # DAS warning + "AhbHiBeam_D_Rq", # AHB status + "Passthru_63", + "Passthru_48", + ]} + + values.update({ + "LaActvStats_D_Dsply": lines, # LKAS status (lines) [0|31] + "LaHandsOff_D_Dsply": hands_on_wheel_dsply, # 0=HandsOn, 1=Level1 (w/o chime), 2=Level2 (w/ chime), 3=Suppressed + }) + return packer.make_can_msg("IPMA_Data", CAN.main, values) + + +def create_button_msg(packer, bus: int, stock_values: dict, cancel=False, resume=False, tja_toggle=False): + """ + Creates a CAN message for the Ford SCCM buttons/switches. + + Includes cruise control buttons, turn lights and more. + + Frequency is 10Hz. + """ + + values = {s: stock_values[s] for s in [ + "HeadLghtHiFlash_D_Stat", # SCCM Passthrough the remaining buttons + "TurnLghtSwtch_D_Stat", # SCCM Turn signal switch + "WiprFront_D_Stat", + "LghtAmb_D_Sns", + "AccButtnGapDecPress", + "AccButtnGapIncPress", + "AslButtnOnOffCnclPress", + "AslButtnOnOffPress", + "LaSwtchPos_D_Stat", + "CcAslButtnCnclResPress", + "CcAslButtnDeny_B_Actl", + "CcAslButtnIndxDecPress", + "CcAslButtnIndxIncPress", + "CcAslButtnOffCnclPress", + "CcAslButtnOnOffCncl", + "CcAslButtnOnPress", + "CcAslButtnResDecPress", + "CcAslButtnResIncPress", + "CcAslButtnSetDecPress", + "CcAslButtnSetIncPress", + "CcAslButtnSetPress", + "CcButtnOffPress", + "CcButtnOnOffCnclPress", + "CcButtnOnOffPress", + "CcButtnOnPress", + "HeadLghtHiFlash_D_Actl", + "HeadLghtHiOn_B_StatAhb", + "AhbStat_B_Dsply", + "AccButtnGapTogglePress", + "WiprFrontSwtch_D_Stat", + "HeadLghtHiCtrl_D_RqAhb", + ]} + + values.update({ + "CcAslButtnCnclPress": 1 if cancel else 0, # CC cancel button + "CcAsllButtnResPress": 1 if resume else 0, # CC resume button + "TjaButtnOnOffPress": 1 if tja_toggle else 0, # LCA/TJA toggle button + }) + return packer.make_can_msg("Steering_Data_FD1", bus, values) diff --git a/opendbc_repo/opendbc/car/ford/interface.py b/opendbc_repo/opendbc/car/ford/interface.py new file mode 100644 index 0000000000..97685df58c --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/interface.py @@ -0,0 +1,98 @@ +import numpy as np +from opendbc.car import Bus, get_safety_config, structs +from opendbc.car.carlog import carlog +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.ford.carcontroller import CarController +from opendbc.car.ford.carstate import CarState +from opendbc.car.ford.fordcan import CanBus +from opendbc.car.ford.radar_interface import RadarInterface +from opendbc.car.ford.values import CarControllerParams, DBC, Ecu, FordFlags, RADAR, FordSafetyFlags +from opendbc.car.interfaces import CarInterfaceBase + +TransmissionType = structs.CarParams.TransmissionType + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def get_pid_accel_limits(CP, current_speed, cruise_speed): + # PCM doesn't allow acceleration near cruise_speed, + # so limit limits of pid to prevent windup + ACCEL_MAX_VALS = [CarControllerParams.ACCEL_MAX, 0.2] + ACCEL_MAX_BP = [cruise_speed - 2., cruise_speed - .4] + return CarControllerParams.ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS) + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "ford" + + ret.radarUnavailable = Bus.radar not in DBC[candidate] + ret.steerControlType = structs.CarParams.SteerControlType.angle + ret.steerActuatorDelay = 0.2 + ret.steerLimitTimer = 1.0 + ret.steerAtStandstill = True + + ret.longitudinalTuning.kiBP = [0.] + ret.longitudinalTuning.kiV = [0.5] + + if not ret.radarUnavailable and DBC[candidate][Bus.radar] == RADAR.DELPHI_MRR: + # average of 33.3 Hz radar timestep / 4 scan modes = 60 ms + # MRR_Header_Timestamps->CAN_DET_TIME_SINCE_MEAS reports 61.3 ms + ret.radarDelay = 0.06 + + CAN = CanBus(fingerprint=fingerprint) + cfgs = [get_safety_config(structs.CarParams.SafetyModel.ford)] + if CAN.main >= 4: + cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput)) + ret.safetyConfigs = cfgs + + ret.alphaLongitudinalAvailable = ret.radarUnavailable + if alpha_long or not ret.radarUnavailable: + ret.safetyConfigs[-1].safetyParam |= FordSafetyFlags.LONG_CONTROL.value + ret.openpilotLongitudinalControl = True + + if ret.flags & FordFlags.CANFD: + ret.safetyConfigs[-1].safetyParam |= FordSafetyFlags.CANFD.value + + # TRON (SecOC) platforms are not supported + # LateralMotionControl2, ACCDATA are 16 bytes on these platforms + if len(fingerprint[CAN.camera]): + if fingerprint[CAN.camera].get(0x3d6) != 8 or fingerprint[CAN.camera].get(0x186) != 8: + carlog.error('dashcamOnly: SecOC is unsupported') + ret.dashcamOnly = True + else: + # Lock out if the car does not have needed lateral and longitudinal control APIs. + # Note that we also check CAN for adaptive cruise, but no known signal for LCA exists + pscm_config = next((fw for fw in car_fw if fw.ecu == Ecu.eps and b'\x22\xDE\x01' in fw.request), None) + if pscm_config: + if len(pscm_config.fwVersion) != 24: + carlog.error('dashcamOnly: Invalid EPS FW version') + ret.dashcamOnly = True + else: + config_tja = pscm_config.fwVersion[7] # Traffic Jam Assist + config_lca = pscm_config.fwVersion[8] # Lane Centering Assist + if config_tja != 0xFF or config_lca != 0xFF: + carlog.error('dashcamOnly: Car lacks required lateral control APIs') + ret.dashcamOnly = True + + # Auto Transmission: 0x732 ECU or Gear_Shift_by_Wire_FD1 + found_ecus = [fw.ecu for fw in car_fw] + if Ecu.shiftByWire in found_ecus or 0x5A in fingerprint[CAN.main] or docs: + ret.transmissionType = TransmissionType.automatic + else: + ret.transmissionType = TransmissionType.manual + ret.minEnableSpeed = 20.0 * CV.MPH_TO_MS + + # BSM: Side_Detect_L_Stat, Side_Detect_R_Stat + # TODO: detect bsm in car_fw? + ret.enableBsm = 0x3A6 in fingerprint[CAN.main] and 0x3A7 in fingerprint[CAN.main] + + # LCA can steer down to zero + ret.minSteerSpeed = 0. + + ret.autoResumeSng = ret.minEnableSpeed == -1. + ret.centerToFront = ret.wheelbase * 0.44 + return ret diff --git a/opendbc_repo/opendbc/car/ford/radar_interface.py b/opendbc_repo/opendbc/car/ford/radar_interface.py new file mode 100644 index 0000000000..87a8f23440 --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/radar_interface.py @@ -0,0 +1,272 @@ +import numpy as np +from typing import cast +from collections import defaultdict +from math import cos, sin +from dataclasses import dataclass +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.ford.fordcan import CanBus +from opendbc.car.ford.values import DBC, RADAR +from opendbc.car.interfaces import RadarInterfaceBase + +DELPHI_ESR_RADAR_MSGS = list(range(0x500, 0x540)) + +DELPHI_MRR_RADAR_START_ADDR = 0x120 +DELPHI_MRR_RADAR_HEADER_ADDR = 0x174 # MRR_Header_SensorCoverage +DELPHI_MRR_RADAR_MSG_COUNT = 64 + +DELPHI_MRR_RADAR_RANGE_COVERAGE = {0: 42, 1: 164, 2: 45, 3: 175} # scan index to detection range (m) +DELPHI_MRR_MIN_LONG_RANGE_DIST = 30 # meters +DELPHI_MRR_CLUSTER_THRESHOLD = 5 # meters, lateral distance and relative velocity are weighted + + +@dataclass +class Cluster: + dRel: float = 0.0 + yRel: float = 0.0 + vRel: float = 0.0 + trackId: int = 0 + + +def cluster_points(pts_l: list[list[float]], pts2_l: list[list[float]], max_dist: float) -> list[int]: + """ + Clusters a collection of points based on another collection of points. This is useful for correlating clusters through time. + Points in pts2 not close enough to any point in pts are assigned -1. + Args: + pts_l: List of points to base the new clusters on + pts2_l: List of points to cluster using pts + max_dist: Max distance from cluster center to candidate point + + Returns: + List of cluster indices for pts2 that correspond to pts + """ + + if not len(pts2_l): + return [] + + if not len(pts_l): + return [-1] * len(pts2_l) + + max_dist_sq = max_dist ** 2 + pts = np.array(pts_l) + pts2 = np.array(pts2_l) + + # Compute squared norms + pts_norm_sq = np.sum(pts ** 2, axis=1) + pts2_norm_sq = np.sum(pts2 ** 2, axis=1) + + # Compute squared Euclidean distances using the identity + # dist_sq[i, j] = ||pts2[i]||^2 + ||pts[j]||^2 - 2 * pts2[i] . pts[j] + dist_sq = pts2_norm_sq[:, np.newaxis] + pts_norm_sq[np.newaxis, :] - 2 * np.dot(pts2, pts.T) + dist_sq = np.maximum(dist_sq, 0.0) + + # Find the closest cluster for each point and assign its index + closest_clusters = np.argmin(dist_sq, axis=1) + closest_dist_sq = dist_sq[np.arange(len(pts2)), closest_clusters] + cluster_idxs = np.where(closest_dist_sq < max_dist_sq, closest_clusters, -1) + + return cast(list[int], cluster_idxs.tolist()) + + +def _create_delphi_esr_radar_can_parser(CP) -> CANParser: + msg_n = len(DELPHI_ESR_RADAR_MSGS) + messages = list(zip(DELPHI_ESR_RADAR_MSGS, [20] * msg_n, strict=True)) + + return CANParser(RADAR.DELPHI_ESR, messages, CanBus(CP).radar) + + +def _create_delphi_mrr_radar_can_parser(CP) -> CANParser: + messages = [ + ("MRR_Header_InformationDetections", 33), + ("MRR_Header_SensorCoverage", 33), + ] + + for i in range(1, DELPHI_MRR_RADAR_MSG_COUNT + 1): + msg = f"MRR_Detection_{i:03d}" + messages += [(msg, 33)] + + return CANParser(RADAR.DELPHI_MRR, messages, CanBus(CP).radar) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + + self.points: list[list[float]] = [] + self.clusters: list[Cluster] = [] + + self.updated_messages = set() + self.track_id = 0 + self.radar = DBC[CP.carFingerprint].get(Bus.radar) + self.scan_index_invalid_cnt = 0 + self.radar_unavailable_cnt = 0 + self.prev_headerScanIndex = 0 + if CP.radarUnavailable: + self.rcp = None + elif self.radar == RADAR.DELPHI_ESR: + self.rcp = _create_delphi_esr_radar_can_parser(CP) + self.trigger_msg = DELPHI_ESR_RADAR_MSGS[-1] + self.valid_cnt = {key: 0 for key in DELPHI_ESR_RADAR_MSGS} + elif self.radar == RADAR.DELPHI_MRR: + self.rcp = _create_delphi_mrr_radar_can_parser(CP) + self.trigger_msg = DELPHI_MRR_RADAR_HEADER_ADDR + else: + raise ValueError(f"Unsupported radar: {self.radar}") + + def update(self, can_strings): + if self.rcp is None: + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + self.updated_messages.clear() + + ret = structs.RadarData() + if not self.rcp.can_valid: + ret.errors.canError = True + + if self.radar == RADAR.DELPHI_ESR: + self._update_delphi_esr() + elif self.radar == RADAR.DELPHI_MRR: + _update = self._update_delphi_mrr(ret) + if not _update: + return None + + ret.points = list(self.pts.values()) + return ret + + def _update_delphi_esr(self): + for ii in sorted(self.updated_messages): + cpt = self.rcp.vl[ii] + + if cpt['X_Rel'] > 0.00001: + self.valid_cnt[ii] = 0 # reset counter + + if cpt['X_Rel'] > 0.00001: + self.valid_cnt[ii] += 1 + else: + self.valid_cnt[ii] = max(self.valid_cnt[ii] - 1, 0) + #print ii, self.valid_cnt[ii], cpt['VALID'], cpt['X_Rel'], cpt['Angle'] + + # radar point only valid if there have been enough valid measurements + if self.valid_cnt[ii] > 0: + if ii not in self.pts: + self.pts[ii] = structs.RadarData.RadarPoint() + self.pts[ii].trackId = self.track_id + self.track_id += 1 + self.pts[ii].dRel = cpt['X_Rel'] # from front of car + self.pts[ii].yRel = cpt['X_Rel'] * cpt['Angle'] * CV.DEG_TO_RAD # in car frame's y axis, left is positive + self.pts[ii].vRel = cpt['V_Rel'] + self.pts[ii].aRel = float('nan') + self.pts[ii].yvRel = float('nan') + self.pts[ii].measured = True + else: + if ii in self.pts: + del self.pts[ii] + + def _update_delphi_mrr(self, ret: structs.RadarData): + headerScanIndex = int(self.rcp.vl["MRR_Header_InformationDetections"]['CAN_SCAN_INDEX']) & 0b11 + + # In reverse, the radar continually sends the last messages. Mark this as invalid + if (self.prev_headerScanIndex + 1) % 4 != headerScanIndex: + self.radar_unavailable_cnt += 1 + else: + self.radar_unavailable_cnt = 0 + self.prev_headerScanIndex = headerScanIndex + + if self.radar_unavailable_cnt >= 5: + self.pts.clear() + self.points.clear() + self.clusters.clear() + ret.errors.radarUnavailableTemporary = True + return True + + # Use points with Doppler coverage of +-60 m/s, reduces similar points + if headerScanIndex not in (2, 3): + return False + + if DELPHI_MRR_RADAR_RANGE_COVERAGE[headerScanIndex] != int(self.rcp.vl["MRR_Header_SensorCoverage"]["CAN_RANGE_COVERAGE"]): + self.scan_index_invalid_cnt += 1 + else: + self.scan_index_invalid_cnt = 0 + + # Rarely MRR_Header_InformationDetections can fail to send a message. The scan index is skipped in this case + if self.scan_index_invalid_cnt >= 5: + ret.errors.wrongConfig = True + + for ii in range(1, DELPHI_MRR_RADAR_MSG_COUNT + 1): + msg = self.rcp.vl[f"MRR_Detection_{ii:03d}"] + + # SCAN_INDEX rotates through 0..3 on each message for different measurement modes + # Indexes 0 and 2 have a max range of ~40m, 1 and 3 are ~170m (MRR_Header_SensorCoverage->CAN_RANGE_COVERAGE) + # Indexes 0 and 1 have a Doppler coverage of +-71 m/s, 2 and 3 have +-60 m/s + scanIndex = msg[f"CAN_SCAN_INDEX_2LSB_{ii:02d}"] + + # Throw out old measurements. Very unlikely to happen, but is proper behavior + if scanIndex != headerScanIndex: + continue + + valid = bool(msg[f"CAN_DET_VALID_LEVEL_{ii:02d}"]) + + # Long range measurement mode is more sensitive and can detect the road surface + dist = msg[f"CAN_DET_RANGE_{ii:02d}"] # m [0|255.984] + if scanIndex in (1, 3) and dist < DELPHI_MRR_MIN_LONG_RANGE_DIST: + valid = False + + if valid: + azimuth = msg[f"CAN_DET_AZIMUTH_{ii:02d}"] # rad [-3.1416|3.13964] + distRate = msg[f"CAN_DET_RANGE_RATE_{ii:02d}"] # m/s [-128|127.984] + dRel = cos(azimuth) * dist # m from front of car + yRel = -sin(azimuth) * dist # in car frame's y axis, left is positive + + self.points.append([dRel, yRel * 2, distRate * 2]) + + # Cluster and publish using stored points once we've cycled through all 4 scan modes + if headerScanIndex != 3: + return False + + # Cluster points from this cycle against the centroids from the previous cycle + prev_keys = [[p.dRel, p.yRel * 2, p.vRel * 2] for p in self.clusters] + labels = cluster_points(prev_keys, self.points, DELPHI_MRR_CLUSTER_THRESHOLD) + + points_by_track_id = defaultdict(list) + for idx, label in enumerate(labels): + if label != -1: + points_by_track_id[self.clusters[label].trackId].append(self.points[idx]) + else: + points_by_track_id[self.track_id].append(self.points[idx]) + self.track_id += 1 + + self.clusters = [] + for idx, (track_id, pts) in enumerate(points_by_track_id.items()): + dRel = [p[0] for p in pts] + min_dRel = min(dRel) + dRel = sum(dRel) / len(dRel) + + yRel = [p[1] for p in pts] + yRel = sum(yRel) / len(yRel) / 2 + + vRel = [p[2] for p in pts] + vRel = sum(vRel) / len(vRel) / 2 + + # FIXME: creating capnp RadarPoint and accessing attributes are both expensive, so we store a dataclass and reuse the RadarPoint + self.clusters.append(Cluster(dRel=dRel, yRel=yRel, vRel=vRel, trackId=track_id)) + + if idx not in self.pts: + self.pts[idx] = structs.RadarData.RadarPoint(measured=True, aRel=float('nan'), yvRel=float('nan')) + + self.pts[idx].dRel = min_dRel + self.pts[idx].yRel = yRel + self.pts[idx].vRel = vRel + self.pts[idx].trackId = track_id + + for idx in range(len(points_by_track_id), len(self.pts)): + del self.pts[idx] + + self.points = [] + + return True diff --git a/opendbc_repo/opendbc/car/ford/tests/__init__.py b/opendbc_repo/opendbc/car/ford/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/ford/tests/print_platform_codes.py b/opendbc_repo/opendbc/car/ford/tests/print_platform_codes.py new file mode 100755 index 0000000000..dfb93c06fd --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/tests/print_platform_codes.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +from collections import defaultdict + +from opendbc.car.structs import CarParams +from opendbc.car.ford.values import get_platform_codes +from opendbc.car.ford.fingerprints import FW_VERSIONS + +Ecu = CarParams.Ecu + +if __name__ == "__main__": + cars_for_code: defaultdict = defaultdict(lambda: defaultdict(set)) + + for car_model, ecus in FW_VERSIONS.items(): + print(car_model) + for ecu in sorted(ecus): + platform_codes = get_platform_codes(ecus[ecu]) + for code in platform_codes: + cars_for_code[ecu][code].add(car_model) + + print(f' (Ecu.{ecu[0]}, {hex(ecu[1])}, {ecu[2]}):') + print(f' Codes: {sorted(platform_codes)}') + print() + + print('\nCar models vs. platform codes:') + for ecu, codes in cars_for_code.items(): + print(f' (Ecu.{ecu[0]}, {hex(ecu[1])}, {ecu[2]}):') + for code, cars in codes.items(): + print(f' {code!r}: {sorted(map(str, cars))}') diff --git a/opendbc_repo/opendbc/car/ford/tests/test_ford.py b/opendbc_repo/opendbc/car/ford/tests/test_ford.py new file mode 100644 index 0000000000..5e3cc420b4 --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/tests/test_ford.py @@ -0,0 +1,142 @@ +import random +from collections.abc import Iterable + +from hypothesis import settings, given, strategies as st +from parameterized import parameterized + +from opendbc.car.structs import CarParams +from opendbc.car.fw_versions import build_fw_dict +from opendbc.car.ford.values import CAR, FW_QUERY_CONFIG, FW_PATTERN, get_platform_codes +from opendbc.car.ford.fingerprints import FW_VERSIONS + +Ecu = CarParams.Ecu + + +ECU_ADDRESSES = { + Ecu.eps: 0x730, # Power Steering Control Module (PSCM) + Ecu.abs: 0x760, # Anti-Lock Brake System (ABS) + Ecu.fwdRadar: 0x764, # Cruise Control Module (CCM) + Ecu.fwdCamera: 0x706, # Image Processing Module A (IPMA) + Ecu.engine: 0x7E0, # Powertrain Control Module (PCM) + Ecu.shiftByWire: 0x732, # Gear Shift Module (GSM) + Ecu.debug: 0x7D0, # Accessory Protocol Interface Module (APIM) +} + + +ECU_PART_NUMBER = { + Ecu.eps: [ + b"14D003", + ], + Ecu.abs: [ + b"2D053", + ], + Ecu.fwdRadar: [ + b"14D049", + ], + Ecu.fwdCamera: [ + b"14F397", # Ford Q3 + b"14H102", # Ford Q4 + ], +} + + +class TestFordFW: + def test_fw_query_config(self): + for (ecu, addr, subaddr) in FW_QUERY_CONFIG.extra_ecus: + assert ecu in ECU_ADDRESSES, "Unknown ECU" + assert addr == ECU_ADDRESSES[ecu], "ECU address mismatch" + assert subaddr is None, "Unexpected ECU subaddress" + + @parameterized.expand(FW_VERSIONS.items()) + def test_fw_versions(self, car_model: str, fw_versions: dict[tuple[int, int, int | None], Iterable[bytes]]): + for (ecu, addr, subaddr), fws in fw_versions.items(): + assert ecu in ECU_PART_NUMBER, "Unexpected ECU" + assert addr == ECU_ADDRESSES[ecu], "ECU address mismatch" + assert subaddr is None, "Unexpected ECU subaddress" + + for fw in fws: + assert len(fw) == 24, "Expected ECU response to be 24 bytes" + + match = FW_PATTERN.match(fw) + assert match is not None, f"Unable to parse FW: {fw!r}" + if match: + part_number = match.group("part_number") + assert part_number in ECU_PART_NUMBER[ecu], f"Unexpected part number for {fw!r}" + + codes = get_platform_codes([fw]) + assert 1 == len(codes), f"Unable to parse FW: {fw!r}" + + @settings(max_examples=100) + @given(data=st.data()) + def test_platform_codes_fuzzy_fw(self, data): + """Ensure function doesn't raise an exception""" + fw_strategy = st.lists(st.binary()) + fws = data.draw(fw_strategy) + get_platform_codes(fws) + + def test_platform_codes_spot_check(self): + # Asserts basic platform code parsing behavior for a few cases + results = get_platform_codes([ + b"JX6A-14C204-BPL\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"NZ6T-14F397-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"PJ6T-14H102-ABJ\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"LB5A-14C204-EAC\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ]) + assert results == {(b"X6A", b"J"), (b"Z6T", b"N"), (b"J6T", b"P"), (b"B5A", b"L")} + + def test_fuzzy_match(self): + for platform, fw_by_addr in FW_VERSIONS.items(): + # Ensure there's no overlaps in platform codes + for _ in range(20): + car_fw = [] + for ecu, fw_versions in fw_by_addr.items(): + ecu_name, addr, sub_addr = ecu + fw = random.choice(fw_versions) + car_fw.append(CarParams.CarFw(ecu=ecu_name, fwVersion=fw, address=addr, + subAddress=0 if sub_addr is None else sub_addr)) + + CP = CarParams(carFw=car_fw) + matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw), CP.carVin, FW_VERSIONS) + assert matches == {platform} + + def test_match_fw_fuzzy(self): + offline_fw = { + (Ecu.eps, 0x730, None): [ + b"L1MC-14D003-AJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"L1MC-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ], + (Ecu.abs, 0x760, None): [ + b"L1MC-2D053-BA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"L1MC-2D053-BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ], + (Ecu.fwdRadar, 0x764, None): [ + b"LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"LB5T-14D049-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ], + # We consider all model year hints for ECU, even with different platform codes + (Ecu.fwdCamera, 0x706, None): [ + b"LB5T-14F397-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + b"NC5T-14F397-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + ], + } + expected_fingerprint = CAR.FORD_EXPLORER_MK6 + + # ensure that we fuzzy match on all non-exact FW with changed revisions + live_fw = { + (0x730, None): {b"L1MC-14D003-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + (0x760, None): {b"L1MC-2D053-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + (0x764, None): {b"LB5T-14D049-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + (0x706, None): {b"LB5T-14F397-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, + } + candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw}) + assert candidates == {expected_fingerprint} + + # model year hint in between the range should match + live_fw[(0x706, None)] = {b"MB5T-14F397-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"} + candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw,}) + assert candidates == {expected_fingerprint} + + # unseen model year hint should not match + live_fw[(0x760, None)] = {b"M1MC-2D053-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"} + candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw}) + assert len(candidates) == 0, "Should not match new model year hint" diff --git a/opendbc_repo/opendbc/car/ford/values.py b/opendbc_repo/opendbc/car/ford/values.py new file mode 100644 index 0000000000..2bda03b8d8 --- /dev/null +++ b/opendbc_repo/opendbc/car/ford/values.py @@ -0,0 +1,319 @@ +import copy +import re +from dataclasses import dataclass, field, replace +from enum import Enum, IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds +from opendbc.car.lateral import AngleSteeringLimits +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column, \ + Device +from opendbc.car.fw_query_definitions import FwQueryConfig, LiveFwVersions, OfflineFwVersions, Request, StdQueries, p16 + +Ecu = CarParams.Ecu + + +class CarControllerParams: + STEER_STEP = 5 # LateralMotionControl, 20Hz + LKA_STEP = 3 # Lane_Assist_Data1, 33Hz + ACC_CONTROL_STEP = 2 # ACCDATA, 50Hz + LKAS_UI_STEP = 100 # IPMA_Data, 1Hz + ACC_UI_STEP = 20 # ACCDATA_3, 5Hz + BUTTONS_STEP = 5 # Steering_Data_FD1, 10Hz, but send twice as fast + + STEER_DRIVER_ALLOWANCE = 1.0 # Driver intervention threshold, Nm + + ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits( + 0.02, # Max curvature for steering command, m^-1 + # Curvature rate limits + # Max curvature is limited by the EPS to an equivalent of ~2.0 m/s^2 at all speeds, + # however max curvature rate linearly decreases as speed increases: + # ~0.009 m^-1/sec at 7 m/s, ~0.002 m^-1/sec at 35 m/s + # Limit to ~2 m/s^3 up, ~3.3 m/s^3 down at 75 mph and match EPS limit at low speed + ([5, 25], [0.00045, 0.0001]), + ([5, 25], [0.00045, 0.00015]) + ) + CURVATURE_ERROR = 0.002 # ~6 degrees at 10 m/s, ~10 degrees at 35 m/s + + ACCEL_MAX = 2.0 # m/s^2 max acceleration + ACCEL_MIN = -3.5 # m/s^2 max deceleration + MIN_GAS = -0.5 + INACTIVE_GAS = -5.0 + + def __init__(self, CP): + pass + + +class FordSafetyFlags(IntFlag): + LONG_CONTROL = 1 + CANFD = 2 + + +class FordFlags(IntFlag): + # Static flags + CANFD = 1 + + +class RADAR: + DELPHI_ESR = 'ford_fusion_2018_adas' + DELPHI_MRR = 'FORD_CADS' + + +class Footnote(Enum): + FOCUS = CarFootnote( + "Refers only to the Focus Mk4 (C519) available in Europe/China/Taiwan/Australasia, not the Focus Mk3 (C346) in " + + "North and South America/Southeast Asia.", + Column.MODEL, + ) + + +@dataclass +class FordCarDocs(CarDocs): + package: str = "Co-Pilot360 Assist+" + hybrid: bool = False + plug_in_hybrid: bool = False + + def init_make(self, CP: CarParams): + harness = CarHarness.ford_q4 if CP.flags & FordFlags.CANFD else CarHarness.ford_q3 + if CP.carFingerprint in (CAR.FORD_BRONCO_SPORT_MK1, CAR.FORD_MAVERICK_MK1, CAR.FORD_F_150_MK14, CAR.FORD_F_150_LIGHTNING_MK1): + self.car_parts = CarParts([Device.threex_angled_mount, harness]) + else: + self.car_parts = CarParts([Device.threex, harness]) + + if harness == CarHarness.ford_q4: + self.setup_video = "https://www.youtube.com/watch?v=uUGkH6C_EQU" + + if CP.carFingerprint in (CAR.FORD_F_150_MK14, CAR.FORD_F_150_LIGHTNING_MK1, CAR.FORD_EXPEDITION_MK4): + self.setup_video = "https://www.youtube.com/watch?v=MewJc9LYp9M" + + +@dataclass +class FordPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: { + Bus.pt: 'ford_lincoln_base_pt', + Bus.radar: RADAR.DELPHI_MRR, + }) + + def init(self): + for car_docs in list(self.car_docs): + if car_docs.hybrid: + name = f"{car_docs.make} {car_docs.model} Hybrid {car_docs.years}" + self.car_docs.append(replace(copy.deepcopy(car_docs), name=name)) + if car_docs.plug_in_hybrid: + name = f"{car_docs.make} {car_docs.model} Plug-in Hybrid {car_docs.years}" + self.car_docs.append(replace(copy.deepcopy(car_docs), name=name)) + + +@dataclass +class FordCANFDPlatformConfig(FordPlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: { + Bus.pt: 'ford_lincoln_base_pt', + }) + + def init(self): + super().init() + self.flags |= FordFlags.CANFD + + +@dataclass +class FordF150LightningPlatform(FordCANFDPlatformConfig): + def init(self): + super().init() + + # Don't show in docs until this issue is resolved. See https://github.com/commaai/openpilot/issues/30302 + self.car_docs = [] + + +class CAR(Platforms): + FORD_BRONCO_SPORT_MK1 = FordPlatformConfig( + [FordCarDocs("Ford Bronco Sport 2021-24")], + CarSpecs(mass=1625, wheelbase=2.67, steerRatio=17.7), + ) + FORD_ESCAPE_MK4 = FordPlatformConfig( + [ + FordCarDocs("Ford Escape 2020-22", hybrid=True, plug_in_hybrid=True), + FordCarDocs("Ford Kuga 2020-23", "Adaptive Cruise Control with Lane Centering", hybrid=True, plug_in_hybrid=True), + ], + CarSpecs(mass=1750, wheelbase=2.71, steerRatio=16.7), + ) + FORD_ESCAPE_MK4_5 = FordCANFDPlatformConfig( + [ + FordCarDocs("Ford Escape 2023-24", hybrid=True, plug_in_hybrid=True, setup_video="https://www.youtube.com/watch?v=M6uXf4b2SHM"), + FordCarDocs("Ford Kuga Hybrid 2024", "All"), + FordCarDocs("Ford Kuga Plug-in Hybrid 2024", "All"), + ], + CarSpecs(mass=1750, wheelbase=2.71, steerRatio=16.7), + ) + FORD_EXPLORER_MK6 = FordPlatformConfig( + [ + FordCarDocs("Ford Explorer 2020-24", hybrid=True), # Hybrid: Limited and Platinum only + FordCarDocs("Lincoln Aviator 2020-24", "Co-Pilot360 Plus", plug_in_hybrid=True), # Hybrid: Grand Touring only + ], + CarSpecs(mass=2050, wheelbase=3.025, steerRatio=16.8), + ) + FORD_EXPEDITION_MK4 = FordCANFDPlatformConfig( + [FordCarDocs("Ford Expedition 2022-24", "Co-Pilot360 Assist 2.0", hybrid=False)], + CarSpecs(mass=2000, wheelbase=3.69, steerRatio=17.0), + ) + FORD_F_150_MK14 = FordCANFDPlatformConfig( + [FordCarDocs("Ford F-150 2021-23", "Co-Pilot360 Assist 2.0", hybrid=True)], + CarSpecs(mass=2000, wheelbase=3.69, steerRatio=17.0), + ) + FORD_F_150_LIGHTNING_MK1 = FordF150LightningPlatform( + [FordCarDocs("Ford F-150 Lightning 2022-23", "Co-Pilot360 Assist 2.0")], + CarSpecs(mass=2948, wheelbase=3.70, steerRatio=16.9), + ) + FORD_FOCUS_MK4 = FordPlatformConfig( + [FordCarDocs("Ford Focus 2018", "Adaptive Cruise Control with Lane Centering", footnotes=[Footnote.FOCUS], hybrid=True)], # mHEV only + CarSpecs(mass=1350, wheelbase=2.7, steerRatio=15.0), + ) + FORD_MAVERICK_MK1 = FordPlatformConfig( + [ + FordCarDocs("Ford Maverick 2022", "LARIAT Luxury", hybrid=True), + FordCarDocs("Ford Maverick 2023-24", "Co-Pilot360 Assist", hybrid=True), + ], + CarSpecs(mass=1650, wheelbase=3.076, steerRatio=17.0), + ) + FORD_MUSTANG_MACH_E_MK1 = FordCANFDPlatformConfig( + [FordCarDocs("Ford Mustang Mach-E 2021-24", "All", setup_video="https://www.youtube.com/watch?v=AR4_eTF3b_A")], + CarSpecs(mass=2200, wheelbase=2.984, steerRatio=17.0), # TODO: check steer ratio + ) + FORD_RANGER_MK2 = FordCANFDPlatformConfig( + [FordCarDocs("Ford Ranger 2024", "Adaptive Cruise Control with Lane Centering", setup_video="https://www.youtube.com/watch?v=2oJlXCKYOy0")], + CarSpecs(mass=2000, wheelbase=3.27, steerRatio=17.0), + ) + + +# FW response contains a combined software and part number +# A-Z except no I, O or W +# e.g. NZ6A-14C204-AAA +# 1222-333333-444 +# 1 = Model year hint (approximates model year/generation) +# 2 = Platform hint +# 3 = Part number +# 4 = Software version +FW_ALPHABET = b'A-HJ-NP-VX-Z' +FW_PATTERN = re.compile(b'^(?P[' + FW_ALPHABET + b'])' + + b'(?P[0-9' + FW_ALPHABET + b']{3})-' + + b'(?P[0-9' + FW_ALPHABET + b']{5,6})-' + + b'(?P[' + FW_ALPHABET + b']{2,})\x00*$') + + +def get_platform_codes(fw_versions: list[bytes] | set[bytes]) -> set[tuple[bytes, bytes]]: + codes = set() + for fw in fw_versions: + match = FW_PATTERN.match(fw) + if match is not None: + codes.add((match.group('platform_hint'), match.group('model_year_hint'))) + + return codes + + +def match_fw_to_car_fuzzy(live_fw_versions: LiveFwVersions, vin: str, offline_fw_versions: OfflineFwVersions) -> set[str]: + candidates: set[str] = set() + + for candidate, fws in offline_fw_versions.items(): + # Keep track of ECUs which pass all checks (platform hint, within model year hint range) + valid_found_ecus = set() + valid_expected_ecus = {ecu[1:] for ecu in fws if ecu[0] in PLATFORM_CODE_ECUS} + for ecu, expected_versions in fws.items(): + addr = ecu[1:] + # Only check ECUs expected to have platform codes + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + # Expected platform codes & model year hints + codes = get_platform_codes(expected_versions) + expected_platform_codes = {code for code, _ in codes} + expected_model_year_hints = {model_year_hint for _, model_year_hint in codes} + + # Found platform codes & model year hints + codes = get_platform_codes(live_fw_versions.get(addr, set())) + found_platform_codes = {code for code, _ in codes} + found_model_year_hints = {model_year_hint for _, model_year_hint in codes} + + # Check platform code matches for any found versions + if not any(found_platform_code in expected_platform_codes for found_platform_code in found_platform_codes): + break + + # Check any model year hint within range in the database. Note that some models have more than one + # platform code per ECU which we don't consider as separate ranges + if not any(min(expected_model_year_hints) <= found_model_year_hint <= max(expected_model_year_hints) for + found_model_year_hint in found_model_year_hints): + break + + valid_found_ecus.add(addr) + + # If all live ECUs pass all checks for candidate, add it as a match + if valid_expected_ecus.issubset(valid_found_ecus): + candidates.add(candidate) + + return candidates + + +# All of these ECUs must be present and are expected to have platform codes we can match +PLATFORM_CODE_ECUS = (Ecu.abs, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.eps) + +DATA_IDENTIFIER_FORD_ASBUILT = 0xDE00 + +ASBUILT_BLOCKS: list[tuple[int, list]] = [ + (1, [Ecu.debug, Ecu.fwdCamera, Ecu.eps]), + (2, [Ecu.abs, Ecu.debug, Ecu.eps]), + (3, [Ecu.abs, Ecu.debug, Ecu.eps]), + (4, [Ecu.debug, Ecu.fwdCamera]), + (5, [Ecu.debug]), + (6, [Ecu.debug]), + (7, [Ecu.debug]), + (8, [Ecu.debug]), + (9, [Ecu.debug]), + (16, [Ecu.debug, Ecu.fwdCamera]), + (18, [Ecu.fwdCamera]), + (20, [Ecu.fwdCamera]), + (21, [Ecu.fwdCamera]), +] + + +def ford_asbuilt_block_request(block_id: int): + return bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + p16(DATA_IDENTIFIER_FORD_ASBUILT + block_id - 1) + + +def ford_asbuilt_block_response(block_id: int): + return bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + p16(DATA_IDENTIFIER_FORD_ASBUILT + block_id - 1) + + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + # CAN and CAN FD queries are combined. + # FIXME: For CAN FD, ECUs respond with frames larger than 8 bytes on the powertrain bus + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.debug, Ecu.engine, Ecu.eps, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.shiftByWire], + logging=True, + ), + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.debug, Ecu.engine, Ecu.eps, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.shiftByWire], + bus=0, + auxiliary=True, + ), + *[Request( + [StdQueries.TESTER_PRESENT_REQUEST, ford_asbuilt_block_request(block_id)], + [StdQueries.TESTER_PRESENT_RESPONSE, ford_asbuilt_block_response(block_id)], + whitelist_ecus=ecus, + bus=0, + logging=True, + ) for block_id, ecus in ASBUILT_BLOCKS], + ], + extra_ecus=[ + (Ecu.engine, 0x7e0, None), # Powertrain Control Module + # Note: We are unlikely to get a response from behind the gateway + (Ecu.shiftByWire, 0x732, None), # Gear Shift Module + (Ecu.debug, 0x7d0, None), # Accessory Protocol Interface Module + ], + # Custom fuzzy fingerprinting function using platform and model year hints + match_fw_to_car_fuzzy=match_fw_to_car_fuzzy, +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/fw_query_definitions.py b/opendbc_repo/opendbc/car/fw_query_definitions.py new file mode 100644 index 0000000000..5c48fed6a1 --- /dev/null +++ b/opendbc_repo/opendbc/car/fw_query_definitions.py @@ -0,0 +1,152 @@ +import copy +from dataclasses import dataclass, field +import struct +from collections.abc import Callable + +from opendbc.car import uds +from opendbc.car.structs import CarParams + +Ecu = CarParams.Ecu + +AddrType = tuple[int, int | None] +EcuAddrBusType = tuple[int, int | None, int] +EcuAddrSubAddr = tuple[Ecu, int, int | None] + +LiveFwVersions = dict[AddrType, set[bytes]] +OfflineFwVersions = dict[str, dict[EcuAddrSubAddr, list[bytes]]] + +# A global list of addresses we will only ever consider for VIN responses +# engine, hybrid controller, Ford abs, Hyundai CAN FD cluster, 29-bit engine, PGM-FI +# TODO: move these to each brand's FW query config +STANDARD_VIN_ADDRS = [0x7e0, 0x7e2, 0x760, 0x7c6, 0x18da10f1, 0x18da0ef1] + +ESSENTIAL_ECUS = [Ecu.engine, Ecu.eps, Ecu.abs, Ecu.fwdRadar, Ecu.fwdCamera, Ecu.vsa] +ECU_NAME = {v: k for k, v in Ecu.schema.enumerants.items()} + + +def p16(val): + return struct.pack("!H", val) + + +class StdQueries: + # FW queries + TESTER_PRESENT_REQUEST = bytes([uds.SERVICE_TYPE.TESTER_PRESENT, 0x0]) + TESTER_PRESENT_RESPONSE = bytes([uds.SERVICE_TYPE.TESTER_PRESENT + 0x40, 0x0]) + + SHORT_TESTER_PRESENT_REQUEST = bytes([uds.SERVICE_TYPE.TESTER_PRESENT]) + SHORT_TESTER_PRESENT_RESPONSE = bytes([uds.SERVICE_TYPE.TESTER_PRESENT + 0x40]) + + DEFAULT_DIAGNOSTIC_REQUEST = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, + uds.SESSION_TYPE.DEFAULT]) + DEFAULT_DIAGNOSTIC_RESPONSE = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL + 0x40, + uds.SESSION_TYPE.DEFAULT, 0x0, 0x32, 0x1, 0xf4]) + + EXTENDED_DIAGNOSTIC_REQUEST = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, + uds.SESSION_TYPE.EXTENDED_DIAGNOSTIC]) + EXTENDED_DIAGNOSTIC_RESPONSE = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL + 0x40, + uds.SESSION_TYPE.EXTENDED_DIAGNOSTIC, 0x0, 0x32, 0x1, 0xf4]) + + MANUFACTURER_SOFTWARE_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_SOFTWARE_NUMBER) + MANUFACTURER_SOFTWARE_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_SOFTWARE_NUMBER) + + SUPPLIER_SOFTWARE_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.SYSTEM_SUPPLIER_ECU_SOFTWARE_VERSION_NUMBER) + SUPPLIER_SOFTWARE_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.SYSTEM_SUPPLIER_ECU_SOFTWARE_VERSION_NUMBER) + + MANUFACTURER_ECU_HARDWARE_NUMBER_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_HARDWARE_NUMBER) + MANUFACTURER_ECU_HARDWARE_NUMBER_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_HARDWARE_NUMBER) + + UDS_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_SOFTWARE_IDENTIFICATION) + UDS_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_SOFTWARE_IDENTIFICATION) + + OBD_VERSION_REQUEST = b'\x09\x04' + OBD_VERSION_RESPONSE = b'\x49\x04' + + # VIN queries + OBD_VIN_REQUEST = b'\x09\x02' + OBD_VIN_RESPONSE = b'\x49\x02\x01' + + UDS_VIN_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + p16(uds.DATA_IDENTIFIER_TYPE.VIN) + UDS_VIN_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + p16(uds.DATA_IDENTIFIER_TYPE.VIN) + + GM_VIN_REQUEST = b'\x1a\x90' + GM_VIN_RESPONSE = b'\x5a\x90' + + KWP_VIN_REQUEST = b'\x21\x81' + KWP_VIN_RESPONSE = b'\x61\x81' + + +@dataclass +class Request: + request: list[bytes] + response: list[bytes] + whitelist_ecus: list[Ecu] = field(default_factory=list) + rx_offset: int = 0x8 + bus: int = 1 + # Whether this query should be run on the first auxiliary panda (CAN FD cars for example) + auxiliary: bool = False + # FW responses from these queries will not be used for fingerprinting + logging: bool = False + # pandad toggles OBD multiplexing on/off as needed + obd_multiplexing: bool = True + + +@dataclass +class FwQueryConfig: + requests: list[Request] + # TODO: make this automatic and remove hardcoded lists, or do fingerprinting with ecus + # Overrides and removes from essential ecus for specific models and ecus (exact matching) + non_essential_ecus: dict[Ecu, list[str]] = field(default_factory=dict) + # Ecus added for data collection, not to be fingerprinted on + extra_ecus: list[tuple[Ecu, int, int | None]] = field(default_factory=list) + # Function a brand can implement to provide better fuzzy matching. Takes in FW versions and VIN, + # returns set of candidates. Only will match if one candidate is returned + match_fw_to_car_fuzzy: Callable[[LiveFwVersions, str, OfflineFwVersions], set[str]] | None = None + + def __post_init__(self): + # Asserts that a request exists if extra ecus are used + if len(self.extra_ecus): + assert len(self.requests), "Must define a request with extra ecus" + + # All extra ecus should be used in a request + for ecu, _, _ in self.extra_ecus: + assert (any(ecu in request.whitelist_ecus for request in self.requests) or + any(not request.whitelist_ecus for request in self.requests)), f"Ecu.{ECU_NAME[ecu]} not in any request" + + # These ECUs are already not in ESSENTIAL_ECUS which the fingerprint functions give a pass if missing + unnecessary_non_essential_ecus = set(self.non_essential_ecus) - set(ESSENTIAL_ECUS) + assert unnecessary_non_essential_ecus == set(), ("Declaring non-essential ECUs non-essential is not required: " + + f"{', '.join([f'Ecu.{ECU_NAME[ecu]}' for ecu in unnecessary_non_essential_ecus])}") + + # Asserts equal length request and response lists + for request_obj in self.requests: + assert len(request_obj.request) == len(request_obj.response), ("Request and response lengths do not match: " + + f"{request_obj.request} vs. {request_obj.response}") + + # No request on the OBD port (bus 1, multiplexed) should be run on an aux panda + assert not (request_obj.auxiliary and request_obj.bus == 1 and request_obj.obd_multiplexing), ("OBD multiplexed request should not " + + f"be marked auxiliary: {request_obj}") + + # Add aux requests (second panda) for all requests that are marked as auxiliary + for i in range(len(self.requests)): + if self.requests[i].auxiliary: + new_request = copy.deepcopy(self.requests[i]) + new_request.bus += 4 + self.requests.append(new_request) + + def get_all_ecus(self, offline_fw_versions: OfflineFwVersions, + include_extra_ecus: bool = True) -> set[EcuAddrSubAddr]: + # Add ecus in database + extra ecus + brand_ecus = {ecu for ecus in offline_fw_versions.values() for ecu in ecus} + + if include_extra_ecus: + brand_ecus |= set(self.extra_ecus) + + return brand_ecus diff --git a/opendbc_repo/opendbc/car/fw_versions.py b/opendbc_repo/opendbc/car/fw_versions.py new file mode 100644 index 0000000000..09d83b5276 --- /dev/null +++ b/opendbc_repo/opendbc/car/fw_versions.py @@ -0,0 +1,327 @@ +from collections import defaultdict +from collections.abc import Callable, Iterator +from typing import Protocol, TypeVar + +from tqdm import tqdm + +from opendbc.car import uds +from opendbc.car.can_definitions import CanRecvCallable, CanSendCallable +from opendbc.car.carlog import carlog +from opendbc.car.structs import CarParams +from opendbc.car.ecu_addrs import get_ecu_addrs +from opendbc.car.fingerprints import FW_VERSIONS +from opendbc.car.fw_query_definitions import ESSENTIAL_ECUS, AddrType, EcuAddrBusType, FwQueryConfig, LiveFwVersions, OfflineFwVersions +from opendbc.car.interfaces import get_interface_attr +from opendbc.car.isotp_parallel_query import IsoTpParallelQuery + +Ecu = CarParams.Ecu +FUZZY_EXCLUDE_ECUS = [Ecu.fwdCamera, Ecu.fwdRadar, Ecu.eps, Ecu.debug] + +FW_QUERY_CONFIGS: dict[str, FwQueryConfig] = get_interface_attr('FW_QUERY_CONFIG', ignore_none=True) +VERSIONS = get_interface_attr('FW_VERSIONS', ignore_none=True) + +MODEL_TO_BRAND = {c: b for b, e in VERSIONS.items() for c in e} +REQUESTS = [(brand, config, r) for brand, config in FW_QUERY_CONFIGS.items() for r in config.requests] + +T = TypeVar('T') +ObdCallback = Callable[[bool], None] + + +def chunks(l: list[T], n: int = 128) -> Iterator[list[T]]: + for i in range(0, len(l), n): + yield l[i:i + n] + + +def is_brand(brand: str, filter_brand: str | None) -> bool: + """Returns if brand matches filter_brand or no brand filter is specified""" + return filter_brand is None or brand == filter_brand + + +def build_fw_dict(fw_versions: list[CarParams.CarFw], filter_brand: str = None) -> dict[AddrType, set[bytes]]: + fw_versions_dict: defaultdict[AddrType, set[bytes]] = defaultdict(set) + for fw in fw_versions: + if is_brand(fw.brand, filter_brand) and not fw.logging: + sub_addr = fw.subAddress if fw.subAddress != 0 else None + fw_versions_dict[(fw.address, sub_addr)].add(fw.fwVersion) + return dict(fw_versions_dict) + + +class MatchFwToCar(Protocol): + def __call__(self, live_fw_versions: LiveFwVersions, match_brand: str = None, log: bool = True) -> set[str]: + ... + + +def match_fw_to_car_fuzzy(live_fw_versions: LiveFwVersions, match_brand: str = None, log: bool = True, exclude: str = None) -> set[str]: + """Do a fuzzy FW match. This function will return a match, and the number of firmware version + that were matched uniquely to that specific car. If multiple ECUs uniquely match to different cars + the match is rejected.""" + + # Build lookup table from (addr, sub_addr, fw) to list of candidate cars + all_fw_versions = defaultdict(list) + for candidate, fw_by_addr in FW_VERSIONS.items(): + if not is_brand(MODEL_TO_BRAND[candidate], match_brand): + continue + + if candidate == exclude: + continue + + for addr, fws in fw_by_addr.items(): + # These ECUs are known to be shared between models (EPS only between hybrid/ICE version) + # Getting this exactly right isn't crucial, but excluding camera and radar makes it almost + # impossible to get 3 matching versions, even if two models with shared parts are released at the same + # time and only one is in our database. + if addr[0] in FUZZY_EXCLUDE_ECUS: + continue + for f in fws: + all_fw_versions[(addr[1], addr[2], f)].append(candidate) + + matched_ecus = set() + match: str | None = None + for addr, versions in live_fw_versions.items(): + ecu_key = (addr[0], addr[1]) + for version in versions: + # All cars that have this FW response on the specified address + candidates = all_fw_versions[(*ecu_key, version)] + + if len(candidates) == 1: + matched_ecus.add(ecu_key) + if match is None: + match = candidates[0] + # We uniquely matched two different cars. No fuzzy match possible + elif match != candidates[0]: + return set() + + # Note that it is possible to match to a candidate without all its ECUs being present + # if there are enough matches. FIXME: parameterize this or require all ECUs to exist like exact matching + if match and len(matched_ecus) >= 2: + if log: + carlog.error(f"Fingerprinted {match} using fuzzy match. {len(matched_ecus)} matching ECUs") + return {match} + else: + return set() + + +def match_fw_to_car_exact(live_fw_versions: LiveFwVersions, match_brand: str = None, log: bool = True, extra_fw_versions: dict = None) -> set[str]: + """Do an exact FW match. Returns all cars that match the given + FW versions for a list of "essential" ECUs. If an ECU is not considered + essential the FW version can be missing to get a fingerprint, but if it's present it + needs to match the database.""" + if extra_fw_versions is None: + extra_fw_versions = {} + + invalid = set() + candidates = {c: f for c, f in FW_VERSIONS.items() if + is_brand(MODEL_TO_BRAND[c], match_brand)} + + for candidate, fws in candidates.items(): + config = FW_QUERY_CONFIGS[MODEL_TO_BRAND[candidate]] + for ecu, expected_versions in fws.items(): + expected_versions = expected_versions + extra_fw_versions.get(candidate, {}).get(ecu, []) + ecu_type = ecu[0] + addr = ecu[1:] + + found_versions = live_fw_versions.get(addr, set()) + if not len(found_versions): + # Some models can sometimes miss an ecu, or show on two different addresses + # FIXME: this logic can be improved to be more specific, should require one of the two addresses + if candidate in config.non_essential_ecus.get(ecu_type, []): + continue + + # Ignore non essential ecus + if ecu_type not in ESSENTIAL_ECUS: + continue + + # Virtual debug ecu doesn't need to match the database + if ecu_type == Ecu.debug: + continue + + if not any(found_version in expected_versions for found_version in found_versions): + invalid.add(candidate) + break + + return set(candidates.keys()) - invalid + + +def match_fw_to_car(fw_versions: list[CarParams.CarFw], vin: str, allow_exact: bool = True, + allow_fuzzy: bool = True, log: bool = True) -> tuple[bool, set[str]]: + # Try exact matching first + exact_matches: list[tuple[bool, MatchFwToCar]] = [] + if allow_exact: + exact_matches = [(True, match_fw_to_car_exact)] + if allow_fuzzy: + exact_matches.append((False, match_fw_to_car_fuzzy)) + + for exact_match, match_func in exact_matches: + # For each brand, attempt to fingerprint using all FW returned from its queries + matches: set[str] = set() + for brand in VERSIONS.keys(): + fw_versions_dict = build_fw_dict(fw_versions, filter_brand=brand) + matches |= match_func(fw_versions_dict, match_brand=brand, log=log) + + # If specified and no matches so far, fall back to brand's fuzzy fingerprinting function + config = FW_QUERY_CONFIGS[brand] + if not exact_match and not len(matches) and config.match_fw_to_car_fuzzy is not None: + matches |= config.match_fw_to_car_fuzzy(fw_versions_dict, vin, VERSIONS[brand]) + + if len(matches): + return exact_match, matches + + return True, set() + + +def get_present_ecus(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, num_pandas: int = 1) -> set[EcuAddrBusType]: + # queries are split by OBD multiplexing mode + queries: dict[bool, list[list[EcuAddrBusType]]] = {True: [], False: []} + parallel_queries: dict[bool, list[EcuAddrBusType]] = {True: [], False: []} + responses: set[EcuAddrBusType] = set() + + for brand, config, r in REQUESTS: + # Skip query if no panda available + if r.bus > num_pandas * 4 - 1: + continue + + for ecu_type, addr, sub_addr in config.get_all_ecus(VERSIONS[brand]): + # Only query ecus in whitelist if whitelist is not empty + if len(r.whitelist_ecus) == 0 or ecu_type in r.whitelist_ecus: + a = (addr, sub_addr, r.bus) + # Build set of queries + if sub_addr is None: + if a not in parallel_queries[r.obd_multiplexing]: + parallel_queries[r.obd_multiplexing].append(a) + else: # subaddresses must be queried one by one + if [a] not in queries[r.obd_multiplexing]: + queries[r.obd_multiplexing].append([a]) + + # Build set of expected responses to filter + response_addr = uds.get_rx_addr_for_tx_addr(addr, r.rx_offset) + responses.add((response_addr, sub_addr, r.bus)) + + for obd_multiplexing in queries: + queries[obd_multiplexing].insert(0, parallel_queries[obd_multiplexing]) + + ecu_responses = set() + for obd_multiplexing in queries: + set_obd_multiplexing(obd_multiplexing) + for query in queries[obd_multiplexing]: + ecu_responses.update(get_ecu_addrs(can_recv, can_send, set(query), responses, timeout=0.1)) + return ecu_responses + + +def get_brand_ecu_matches(ecu_rx_addrs: set[EcuAddrBusType]) -> dict[str, list[bool]]: + """Returns dictionary of brands and matches with ECUs in their FW versions""" + + brand_rx_addrs = {brand: set() for brand in FW_QUERY_CONFIGS} + brand_matches = {brand: [] for brand, _, _ in REQUESTS} + + # Since we can't know what request an ecu responded to, add matches for all possible rx offsets + for brand, config, r in REQUESTS: + for ecu in config.get_all_ecus(VERSIONS[brand]): + if len(r.whitelist_ecus) == 0 or ecu[0] in r.whitelist_ecus: + brand_rx_addrs[brand].add((uds.get_rx_addr_for_tx_addr(ecu[1], r.rx_offset), ecu[2])) + + for brand, addrs in brand_rx_addrs.items(): + for addr in addrs: + # TODO: check bus from request as well + brand_matches[brand].append(addr in [addr[:2] for addr in ecu_rx_addrs]) + + return brand_matches + + +def get_fw_versions_ordered(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, vin: str, + ecu_rx_addrs: set[EcuAddrBusType], timeout: float = 0.1, num_pandas: int = 1, progress: bool = False) -> list[CarParams.CarFw]: + """Queries for FW versions ordering brands by likelihood, breaks when exact match is found""" + + all_car_fw = [] + brand_matches = get_brand_ecu_matches(ecu_rx_addrs) + + # Sort brands by number of matching ECUs first, then percentage of matching ECUs in the database + # This allows brands with only one ECU to be queried first (e.g. Tesla) + for brand in sorted(brand_matches, key=lambda b: (brand_matches[b].count(True), brand_matches[b].count(True) / len(brand_matches[b])), reverse=True): + # Skip this brand if there are no matching present ECUs + if True not in brand_matches[brand]: + continue + + car_fw = get_fw_versions(can_recv, can_send, set_obd_multiplexing, query_brand=brand, timeout=timeout, num_pandas=num_pandas, progress=progress) + all_car_fw.extend(car_fw) + + # If there is a match using this brand's FW alone, finish querying early + _, matches = match_fw_to_car(car_fw, vin, log=False) + if len(matches) == 1: + break + + return all_car_fw + + +def get_fw_versions(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multiplexing: ObdCallback, query_brand: str = None, + extra: OfflineFwVersions = None, timeout: float = 0.1, num_pandas: int = 1, progress: bool = False) -> list[CarParams.CarFw]: + versions = VERSIONS.copy() + + if query_brand is not None: + versions = {query_brand: versions[query_brand]} + + if extra is not None: + versions.update(extra) + + # Extract ECU addresses to query from fingerprints + # ECUs using a subaddress need be queried one by one, the rest can be done in parallel + addrs = [] + parallel_addrs = [] + ecu_types = {} + + for brand, brand_versions in versions.items(): + config = FW_QUERY_CONFIGS[brand] + for ecu_type, addr, sub_addr in config.get_all_ecus(brand_versions): + a = (brand, addr, sub_addr) + if a not in ecu_types: + ecu_types[a] = ecu_type + + if sub_addr is None: + if a not in parallel_addrs: + parallel_addrs.append(a) + else: + if [a] not in addrs: + addrs.append([a]) + + addrs.insert(0, parallel_addrs) + + # Get versions and build capnp list to put into CarParams + car_fw = [] + requests = [(brand, config, r) for brand, config, r in REQUESTS if is_brand(brand, query_brand)] + for addr_group in tqdm(addrs, disable=not progress): # split by subaddr, if any + for addr_chunk in chunks(addr_group): + for brand, config, r in requests: + # Skip query if no panda available + if r.bus > num_pandas * 4 - 1: + continue + + # Toggle OBD multiplexing for each request + if r.bus % 4 == 1: + set_obd_multiplexing(r.obd_multiplexing) + + try: + query_addrs = [(a, s) for (b, a, s) in addr_chunk if b in (brand, 'any') and + (len(r.whitelist_ecus) == 0 or ecu_types[(b, a, s)] in r.whitelist_ecus)] + + if query_addrs: + query = IsoTpParallelQuery(can_send, can_recv, r.bus, query_addrs, r.request, r.response, r.rx_offset) + for (tx_addr, sub_addr), version in query.get_data(timeout).items(): + f = CarParams.CarFw() + + f.ecu = ecu_types.get((brand, tx_addr, sub_addr), Ecu.unknown) + f.fwVersion = version + f.address = tx_addr + f.responseAddress = uds.get_rx_addr_for_tx_addr(tx_addr, r.rx_offset) + f.request = r.request + f.brand = brand + f.bus = r.bus + f.logging = r.logging or (f.ecu, tx_addr, sub_addr) in config.extra_ecus + f.obdMultiplexing = r.obd_multiplexing + + if sub_addr is not None: + f.subAddress = sub_addr + + car_fw.append(f) + except Exception: + carlog.exception("FW query exception") + + return car_fw diff --git a/opendbc_repo/opendbc/car/gm/__init__.py b/opendbc_repo/opendbc/car/gm/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/gm/carcontroller.py b/opendbc_repo/opendbc/car/gm/carcontroller.py new file mode 100644 index 0000000000..9f462004c6 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/carcontroller.py @@ -0,0 +1,163 @@ +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import Bus, DT_CTRL, structs +from opendbc.car.lateral import apply_driver_steer_torque_limits +from opendbc.car.gm import gmcan +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.gm.values import DBC, CanBus, CarControllerParams, CruiseButtons +from opendbc.car.interfaces import CarControllerBase + +VisualAlert = structs.CarControl.HUDControl.VisualAlert +NetworkLocation = structs.CarParams.NetworkLocation +LongCtrlState = structs.CarControl.Actuators.LongControlState + +# Camera cancels up to 0.1s after brake is pressed, ECM allows 0.5s +CAMERA_CANCEL_DELAY_FRAMES = 10 +# Enforce a minimum interval between steering messages to avoid a fault +MIN_STEER_MSG_INTERVAL_MS = 15 + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.start_time = 0. + self.apply_torque_last = 0 + self.apply_gas = 0 + self.apply_brake = 0 + self.last_steer_frame = 0 + self.last_button_frame = 0 + self.cancel_counter = 0 + + self.lka_steering_cmd_counter = 0 + self.lka_icon_status_last = (False, False) + + self.params = CarControllerParams(self.CP) + + self.packer_pt = CANPacker(DBC[self.CP.carFingerprint][Bus.pt]) + self.packer_obj = CANPacker(DBC[self.CP.carFingerprint][Bus.radar]) + self.packer_ch = CANPacker(DBC[self.CP.carFingerprint][Bus.chassis]) + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + hud_control = CC.hudControl + hud_alert = hud_control.visualAlert + hud_v_cruise = hud_control.setSpeed + if hud_v_cruise > 70: + hud_v_cruise = 0 + + # Send CAN commands. + can_sends = [] + + # Steering (Active: 50Hz, inactive: 10Hz) + steer_step = self.params.STEER_STEP if CC.latActive else self.params.INACTIVE_STEER_STEP + + if self.CP.networkLocation == NetworkLocation.fwdCamera: + # Also send at 50Hz: + # - on startup, first few msgs are blocked + # - until we're in sync with camera so counters align when relay closes, preventing a fault. + # openpilot can subtly drift, so this is activated throughout a drive to stay synced + out_of_sync = self.lka_steering_cmd_counter % 4 != (CS.cam_lka_steering_cmd_counter + 1) % 4 + if CS.loopback_lka_steering_cmd_ts_nanos == 0 or out_of_sync: + steer_step = self.params.STEER_STEP + + self.lka_steering_cmd_counter += 1 if CS.loopback_lka_steering_cmd_updated else 0 + + # Avoid GM EPS faults when transmitting messages too close together: skip this transmit if we + # received the ASCMLKASteeringCmd loopback confirmation too recently + last_lka_steer_msg_ms = (now_nanos - CS.loopback_lka_steering_cmd_ts_nanos) * 1e-6 + if (self.frame - self.last_steer_frame) >= steer_step and last_lka_steer_msg_ms > MIN_STEER_MSG_INTERVAL_MS: + # Initialize ASCMLKASteeringCmd counter using the camera until we get a msg on the bus + if CS.loopback_lka_steering_cmd_ts_nanos == 0: + self.lka_steering_cmd_counter = CS.pt_lka_steering_cmd_counter + 1 + + if CC.latActive: + new_torque = int(round(actuators.torque * self.params.STEER_MAX)) + apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params) + else: + apply_torque = 0 + + self.last_steer_frame = self.frame + self.apply_torque_last = apply_torque + idx = self.lka_steering_cmd_counter % 4 + can_sends.append(gmcan.create_steering_control(self.packer_pt, CanBus.POWERTRAIN, apply_torque, idx, CC.latActive)) + + if self.CP.openpilotLongitudinalControl: + # Gas/regen, brakes, and UI commands - all at 25Hz + if self.frame % 4 == 0: + stopping = actuators.longControlState == LongCtrlState.stopping + if not CC.longActive: + # ASCM sends max regen when not enabled + self.apply_gas = self.params.INACTIVE_REGEN + self.apply_brake = 0 + else: + self.apply_gas = float(np.interp(actuators.accel, self.params.GAS_LOOKUP_BP, self.params.GAS_LOOKUP_V)) + self.apply_brake = int(round(np.interp(actuators.accel, self.params.BRAKE_LOOKUP_BP, self.params.BRAKE_LOOKUP_V))) + # Don't allow any gas above inactive regen while stopping + # FIXME: brakes aren't applied immediately when enabling at a stop + if stopping: + self.apply_gas = self.params.INACTIVE_REGEN + + idx = (self.frame // 4) % 4 + + at_full_stop = CC.longActive and CS.out.standstill + near_stop = CC.longActive and (abs(CS.out.vEgo) < self.params.NEAR_STOP_BRAKE_PHASE) + friction_brake_bus = CanBus.CHASSIS + # GM Camera exceptions + # TODO: can we always check the longControlState? + if self.CP.networkLocation == NetworkLocation.fwdCamera: + at_full_stop = at_full_stop and stopping + friction_brake_bus = CanBus.POWERTRAIN + + # GasRegenCmdActive needs to be 1 to avoid cruise faults. It describes the ACC state, not actuation + can_sends.append(gmcan.create_gas_regen_command(self.packer_pt, CanBus.POWERTRAIN, self.apply_gas, idx, CC.enabled, at_full_stop)) + can_sends.append(gmcan.create_friction_brake_command(self.packer_ch, friction_brake_bus, self.apply_brake, + idx, CC.enabled, near_stop, at_full_stop, self.CP)) + + # Send dashboard UI commands (ACC status) + send_fcw = hud_alert == VisualAlert.fcw + can_sends.append(gmcan.create_acc_dashboard_command(self.packer_pt, CanBus.POWERTRAIN, CC.enabled, + hud_v_cruise * CV.MS_TO_KPH, hud_control, send_fcw)) + + # Radar needs to know current speed and yaw rate (50hz), + # and that ADAS is alive (10hz) + if not self.CP.radarUnavailable: + tt = self.frame * DT_CTRL + time_and_headlights_step = 10 + if self.frame % time_and_headlights_step == 0: + idx = (self.frame // time_and_headlights_step) % 4 + can_sends.append(gmcan.create_adas_time_status(CanBus.OBSTACLE, int((tt - self.start_time) * 60), idx)) + can_sends.append(gmcan.create_adas_headlights_status(self.packer_obj, CanBus.OBSTACLE)) + + speed_and_accelerometer_step = 2 + if self.frame % speed_and_accelerometer_step == 0: + idx = (self.frame // speed_and_accelerometer_step) % 4 + can_sends.append(gmcan.create_adas_steering_status(CanBus.OBSTACLE, idx)) + can_sends.append(gmcan.create_adas_accelerometer_speed_status(CanBus.OBSTACLE, abs(CS.out.vEgo), idx)) + + if self.CP.networkLocation == NetworkLocation.gateway and self.frame % self.params.ADAS_KEEPALIVE_STEP == 0: + can_sends += gmcan.create_adas_keepalive(CanBus.POWERTRAIN) + + else: + # While car is braking, cancel button causes ECM to enter a soft disable state with a fault status. + # A delayed cancellation allows camera to cancel and avoids a fault when user depresses brake quickly + self.cancel_counter = self.cancel_counter + 1 if CC.cruiseControl.cancel else 0 + + # Stock longitudinal, integrated at camera + if (self.frame - self.last_button_frame) * DT_CTRL > 0.04: + if self.cancel_counter > CAMERA_CANCEL_DELAY_FRAMES: + self.last_button_frame = self.frame + can_sends.append(gmcan.create_buttons(self.packer_pt, CanBus.CAMERA, CS.buttons_counter, CruiseButtons.CANCEL)) + + if self.CP.networkLocation == NetworkLocation.fwdCamera: + # Silence "Take Steering" alert sent by camera, forward PSCMStatus with HandsOffSWlDetectionStatus=1 + if self.frame % 10 == 0: + can_sends.append(gmcan.create_pscm_status(self.packer_pt, CanBus.CAMERA, CS.pscm_status)) + + new_actuators = actuators.as_builder() + new_actuators.torque = self.apply_torque_last / self.params.STEER_MAX + new_actuators.torqueOutputCan = self.apply_torque_last + new_actuators.gas = self.apply_gas + new_actuators.brake = self.apply_brake + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/gm/carstate.py b/opendbc_repo/opendbc/car/gm/carstate.py new file mode 100644 index 0000000000..f4a62a3015 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/carstate.py @@ -0,0 +1,179 @@ +import copy +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarStateBase +from opendbc.car.gm.values import DBC, AccState, CruiseButtons, STEER_THRESHOLD, SDGM_CAR, ALT_ACCS + +ButtonType = structs.CarState.ButtonEvent.Type +TransmissionType = structs.CarParams.TransmissionType +NetworkLocation = structs.CarParams.NetworkLocation + +STANDSTILL_THRESHOLD = 10 * 0.0311 + +BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.DECEL_SET: ButtonType.decelCruise, + CruiseButtons.MAIN: ButtonType.mainCruise, CruiseButtons.CANCEL: ButtonType.cancel} + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + self.shifter_values = can_define.dv["ECMPRDNL2"]["PRNDL2"] + self.cluster_speed_hyst_gap = CV.KPH_TO_MS / 2. + self.cluster_min_speed = CV.KPH_TO_MS / 2. + + self.loopback_lka_steering_cmd_updated = False + self.loopback_lka_steering_cmd_ts_nanos = 0 + self.pt_lka_steering_cmd_counter = 0 + self.cam_lka_steering_cmd_counter = 0 + self.buttons_counter = 0 + + self.distance_button = 0 + + def update_button_enable(self, buttonEvents: list[structs.CarState.ButtonEvent]): + if not self.CP.pcmCruise: + for b in buttonEvents: + # The ECM allows enabling on falling edge of set, but only rising edge of resume + if (b.type == ButtonType.accelCruise and b.pressed) or \ + (b.type == ButtonType.decelCruise and not b.pressed): + return True + return False + + def update(self, can_parsers) -> structs.CarState: + pt_cp = can_parsers[Bus.pt] + cam_cp = can_parsers[Bus.cam] + loopback_cp = can_parsers[Bus.loopback] + + ret = structs.CarState() + + prev_cruise_buttons = self.cruise_buttons + prev_distance_button = self.distance_button + self.cruise_buttons = pt_cp.vl["ASCMSteeringButton"]["ACCButtons"] + self.distance_button = pt_cp.vl["ASCMSteeringButton"]["DistanceButton"] + self.buttons_counter = pt_cp.vl["ASCMSteeringButton"]["RollingCounter"] + self.pscm_status = copy.copy(pt_cp.vl["PSCMStatus"]) + + # Variables used for avoiding LKAS faults + self.loopback_lka_steering_cmd_updated = len(loopback_cp.vl_all["ASCMLKASteeringCmd"]["RollingCounter"]) > 0 + if self.loopback_lka_steering_cmd_updated: + self.loopback_lka_steering_cmd_ts_nanos = loopback_cp.ts_nanos["ASCMLKASteeringCmd"]["RollingCounter"] + if self.CP.networkLocation == NetworkLocation.fwdCamera: + self.pt_lka_steering_cmd_counter = pt_cp.vl["ASCMLKASteeringCmd"]["RollingCounter"] + self.cam_lka_steering_cmd_counter = cam_cp.vl["ASCMLKASteeringCmd"]["RollingCounter"] + + # This is to avoid a fault where you engage while still moving backwards after shifting to D. + # An Equinox has been seen with an unsupported status (3), so only check if either wheel is in reverse (2) + left_whl_sign = -1 if pt_cp.vl["EBCMWheelSpdRear"]["RLWheelDir"] == 2 else 1 + right_whl_sign = -1 if pt_cp.vl["EBCMWheelSpdRear"]["RRWheelDir"] == 2 else 1 + self.parse_wheel_speeds(ret, + left_whl_sign * pt_cp.vl["EBCMWheelSpdFront"]["FLWheelSpd"], + right_whl_sign * pt_cp.vl["EBCMWheelSpdFront"]["FRWheelSpd"], + left_whl_sign * pt_cp.vl["EBCMWheelSpdRear"]["RLWheelSpd"], + right_whl_sign * pt_cp.vl["EBCMWheelSpdRear"]["RRWheelSpd"], + ) + # sample rear wheel speeds to match the safety which only uses the rear CAN message + # standstill=True if ECM allows engagement with brake + ret.standstill = abs(pt_cp.vl["EBCMWheelSpdRear"]["RLWheelSpd"]) <= STANDSTILL_THRESHOLD and \ + abs(pt_cp.vl["EBCMWheelSpdRear"]["RRWheelSpd"]) <= STANDSTILL_THRESHOLD + + if pt_cp.vl["ECMPRDNL2"]["ManualMode"] == 1: + ret.gearShifter = self.parse_gear_shifter("T") + else: + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(pt_cp.vl["ECMPRDNL2"]["PRNDL2"], None)) + + ret.brake = pt_cp.vl["ECMAcceleratorPos"]["BrakePedalPos"] + if self.CP.networkLocation == NetworkLocation.fwdCamera: + ret.brakePressed = pt_cp.vl["ECMEngineStatus"]["BrakePressed"] != 0 + else: + # Some Volt 2016-17 have loose brake pedal push rod retainers which causes the ECM to believe + # that the brake is being intermittently pressed without user interaction. + # To avoid a cruise fault we need to use a conservative brake position threshold + # https://static.nhtsa.gov/odi/tsbs/2017/MC-10137629-9999.pdf + ret.brakePressed = ret.brake >= 8 + + # Regen braking is braking + if self.CP.transmissionType == TransmissionType.direct: + ret.regenBraking = pt_cp.vl["EBCMRegenPaddle"]["RegenPaddle"] != 0 + + ret.gasPressed = pt_cp.vl["AcceleratorPedal2"]["AcceleratorPedal2"] / 254. > 1e-5 + + ret.steeringAngleDeg = pt_cp.vl["PSCMSteeringAngle"]["SteeringWheelAngle"] + ret.steeringRateDeg = pt_cp.vl["PSCMSteeringAngle"]["SteeringWheelRate"] + ret.steeringTorque = pt_cp.vl["PSCMStatus"]["LKADriverAppldTrq"] + ret.steeringTorqueEps = pt_cp.vl["PSCMStatus"]["LKATorqueDelivered"] + ret.steeringPressed = abs(ret.steeringTorque) > STEER_THRESHOLD + + # 0 inactive, 1 active, 2 temporarily limited, 3 failed + self.lkas_status = pt_cp.vl["PSCMStatus"]["LKATorqueDeliveredStatus"] + ret.steerFaultTemporary = self.lkas_status == 2 + ret.steerFaultPermanent = self.lkas_status == 3 + + # 1 - open, 0 - closed + ret.doorOpen = (pt_cp.vl["BCMDoorBeltStatus"]["FrontLeftDoor"] == 1 or + pt_cp.vl["BCMDoorBeltStatus"]["FrontRightDoor"] == 1 or + pt_cp.vl["BCMDoorBeltStatus"]["RearLeftDoor"] == 1 or + pt_cp.vl["BCMDoorBeltStatus"]["RearRightDoor"] == 1) + + # 1 - latched + ret.seatbeltUnlatched = pt_cp.vl["BCMDoorBeltStatus"]["LeftSeatBelt"] == 0 + ret.leftBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 1 + ret.rightBlinker = pt_cp.vl["BCMTurnSignals"]["TurnSignals"] == 2 + + ret.parkingBrake = pt_cp.vl["BCMGeneralPlatformStatus"]["ParkBrakeSwActive"] == 1 + ret.cruiseState.available = pt_cp.vl["ECMEngineStatus"]["CruiseMainOn"] != 0 + ret.espDisabled = pt_cp.vl["ESPStatus"]["TractionControlOn"] != 1 + ret.accFaulted = (pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.FAULTED or + pt_cp.vl["EBCMFrictionBrakeStatus"]["FrictionBrakeUnavailable"] == 1) + + ret.cruiseState.enabled = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] != AccState.OFF + ret.cruiseState.standstill = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.STANDSTILL + if self.CP.networkLocation == NetworkLocation.fwdCamera: + if self.CP.carFingerprint not in ALT_ACCS: + ret.cruiseState.speed = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCSpeedSetpoint"] * CV.KPH_TO_MS + # This FCW signal only works for SDGM cars. CAM cars send FCW on GMLAN but this bit is always 0 for them + ret.stockFcw = cam_cp.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"] != 0 + if self.CP.pcmCruise: + # openpilot controls nonAdaptive when not pcmCruise + ret.cruiseState.nonAdaptive = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCCruiseState"] not in (2, 3) + else: + ret.cruiseState.speed = pt_cp.vl["ECMCruiseControl"]["CruiseSetSpeed"] * CV.KPH_TO_MS + + if self.CP.carFingerprint not in SDGM_CAR: + ret.stockAeb = cam_cp.vl["AEBCmd"]["AEBCmdActive"] != 0 + + if self.CP.enableBsm: + ret.leftBlindspot = pt_cp.vl["BCMBlindSpotMonitor"]["LeftBSM"] == 1 + ret.rightBlindspot = pt_cp.vl["BCMBlindSpotMonitor"]["RightBSM"] == 1 + + # Don't add event if transitioning from INIT, unless it's to an actual button + if self.cruise_buttons != CruiseButtons.UNPRESS or prev_cruise_buttons != CruiseButtons.INIT: + ret.buttonEvents = [ + *create_button_events(self.cruise_buttons, prev_cruise_buttons, BUTTONS_DICT, + unpressed_btn=CruiseButtons.UNPRESS), + *create_button_events(self.distance_button, prev_distance_button, + {1: ButtonType.gapAdjustCruise}) + ] + + if ret.vEgo < self.CP.minSteerSpeed: + ret.lowSpeedAlert = True + + return ret + + @staticmethod + def get_can_parsers(CP): + pt_messages = [] + if CP.networkLocation == NetworkLocation.fwdCamera: + pt_messages += [ + ("ASCMLKASteeringCmd", float('nan')), + ] + + loopback_messages = [ + ("ASCMLKASteeringCmd", float('nan')), + ] + + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], pt_messages, 0), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + Bus.loopback: CANParser(DBC[CP.carFingerprint][Bus.pt], loopback_messages, 128), + } diff --git a/opendbc_repo/opendbc/car/gm/fingerprints.py b/opendbc_repo/opendbc/car/gm/fingerprints.py new file mode 100644 index 0000000000..2758e7980c --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/fingerprints.py @@ -0,0 +1,76 @@ +# ruff: noqa: E501 +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.gm.values import CAR + +# Trailblazer also matches as a SILVERADO, TODO: split with fw versions +# FIXME: There are Equinox users with different message lengths, specifically 304 and 320 + + +FINGERPRINTS = { + CAR.HOLDEN_ASTRA: [{ + 190: 8, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 8, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 8, 398: 8, 401: 8, 413: 8, 417: 8, 419: 8, 422: 1, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 8, 455: 7, 456: 8, 458: 5, 479: 8, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 8, 501: 8, 508: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 647: 5, 707: 8, 715: 8, 723: 8, 753: 5, 761: 7, 806: 1, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1009: 8, 1011: 6, 1017: 8, 1019: 3, 1020: 8, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 8, 1280: 4, 1300: 8, 1328: 4, 1417: 8, 1906: 7, 1907: 7, 1908: 7, 1912: 7, 1919: 7 + }], + CAR.CHEVROLET_VOLT: [{ + 170: 8, 171: 8, 189: 7, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 289: 8, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 528: 4, 532: 6, 546: 7, 550: 8, 554: 3, 558: 8, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 566: 5, 567: 3, 568: 1, 573: 1, 577: 8, 647: 3, 707: 8, 711: 6, 715: 8, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 961: 8, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1928: 7, 2016: 8, 2020: 8, 2024: 8, 2028: 8 + }, + { + 170: 8, 171: 8, 189: 7, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 528: 4, 532: 6, 546: 7, 550: 8, 554: 3, 558: 8, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 566: 5, 567: 3, 568: 1, 573: 1, 577: 8, 578: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 3, 707: 8, 711: 6, 715: 8, 717: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 967: 4, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1516: 8, 1601: 8, 1618: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1930: 7, 2016: 8, 2018: 8, 2020: 8, 2024: 8, 2028: 8 + }, + { + 170: 8, 171: 8, 189: 7, 190: 6, 192: 5, 193: 8, 197: 8, 199: 4, 201: 6, 209: 7, 211: 2, 241: 6, 288: 5, 289: 1, 290: 1, 298: 2, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 368: 8, 381: 2, 384: 8, 386: 5, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 458: 8, 479: 3, 481: 7, 485: 8, 489: 5, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 3, 508: 8, 512: 3, 528: 4, 530: 8, 532: 6, 537: 5, 539: 8, 542: 7, 546: 7, 550: 8, 554: 3, 558: 8, 560: 6, 562: 4, 563: 5, 564: 5, 565: 5, 566: 5, 567: 3, 568: 1, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 3, 707: 8, 711: 6, 761: 7, 810: 8, 821: 4, 823: 7, 832: 8, 840: 5, 842: 5, 844: 8, 853: 8, 866: 4, 961: 8, 967: 4, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 5, 1003: 5, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7 + }], + CAR.BUICK_LACROSSE: [{ + 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 322: 7, 328: 1, 352: 5, 353: 3, 381: 6, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 456: 8, 463: 3, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 503: 1, 508: 8, 510: 8, 528: 5, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 5, 707: 8, 753: 5, 761: 7, 801: 8, 804: 3, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 872: 1, 882: 8, 890: 1, 892: 2, 893: 1, 894: 1, 961: 8, 967: 4, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 3, 1017: 8, 1019: 2, 1020: 8, 1022: 1, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1243: 3, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1280: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1609: 8, 1613: 8, 1649: 8, 1792: 8, 1798: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1858: 8, 1860: 8, 1863: 8, 1872: 8, 1875: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1904: 7, 1906: 7, 1907: 7, 1912: 7, 1913: 7, 1914: 7, 1916: 7, 1918: 7, 1919: 7, 1937: 8, 1953: 8, 1968: 8, 2001: 8, 2017: 8, 2018: 8, 2020: 8, 2026: 8 + }], + CAR.BUICK_REGAL: [{ + 190: 8, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 8, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 322: 7, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 8, 419: 8, 422: 4, 426: 8, 431: 8, 442: 8, 451: 8, 452: 8, 453: 8, 455: 7, 456: 8, 463: 3, 479: 8, 481: 7, 485: 8, 487: 8, 489: 8, 495: 8, 497: 8, 499: 3, 500: 8, 501: 8, 508: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 569: 3, 573: 1, 577: 8, 578: 8, 579: 8, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 3, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 882: 8, 884: 8, 890: 1, 892: 2, 893: 2, 894: 1, 961: 8, 967: 8, 969: 8, 977: 8, 979: 8, 985: 8, 1001: 8, 1005: 6, 1009: 8, 1011: 8, 1013: 3, 1017: 8, 1020: 8, 1024: 8, 1025: 8, 1026: 8, 1027: 8, 1028: 8, 1029: 8, 1030: 8, 1031: 8, 1032: 2, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 8, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 8, 1263: 8, 1265: 8, 1267: 8, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1601: 8, 1602: 8, 1603: 7, 1611: 8, 1618: 8, 1906: 8, 1907: 7, 1912: 7, 1914: 7, 1916: 7, 1919: 7, 1930: 7, 2016: 8, 2018: 8, 2019: 8, 2024: 8, 2026: 8 + }], + CAR.CADILLAC_ATS: [{ + 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 322: 7, 328: 1, 352: 5, 368: 3, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 401: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 456: 8, 462: 4, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 491: 2, 493: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 528: 5, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 719: 5, 723: 2, 753: 5, 761: 7, 801: 8, 804: 3, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 882: 8, 890: 1, 892: 2, 893: 2, 894: 1, 961: 8, 967: 4, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 3, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1233: 8, 1241: 3, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1904: 7, 1906: 7, 1907: 7, 1912: 7, 1916: 7, 1917: 7, 1918: 7, 1919: 7, 1920: 7, 1930: 7, 2016: 8, 2024: 8 + }], + CAR.CHEVROLET_MALIBU: [{ + 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 456: 8, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1013: 3, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1930: 7, 2016: 8, 2024: 8 + }], + CAR.GMC_ACADIA: [{ + 190: 6, 192: 5, 193: 8, 197: 8, 199: 4, 201: 6, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 1, 290: 1, 298: 8, 304: 8, 309: 8, 313: 8, 320: 8, 322: 7, 328: 1, 352: 7, 368: 8, 381: 8, 384: 8, 386: 8, 388: 8, 393: 8, 398: 8, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 458: 8, 460: 4, 462: 4, 463: 3, 479: 3, 481: 7, 485: 8, 489: 5, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 512: 3, 530: 8, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 567: 5, 568: 2, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 789: 5, 800: 6, 801: 8, 803: 8, 804: 3, 805: 8, 832: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1003: 5, 1005: 6, 1009: 8, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1906: 7, 1907: 7, 1912: 7, 1914: 7, 1918: 7, 1919: 7, 1920: 7, 1930: 7 + }, + { + 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 8, 298: 8, 304: 1, 309: 8, 313: 8, 320: 3, 322: 7, 328: 1, 338: 6, 340: 6, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 393: 8, 398: 8, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 462: 4, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1601: 8, 1906: 7, 1907: 7, 1912: 7, 1914: 7, 1919: 7, 1920: 7, 1930: 7, 2016: 8, 2024: 8 + }], + CAR.CADILLAC_ESCALADE: [{ + 170: 8, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 322: 7, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 4, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 460: 5, 462: 4, 463: 3, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 719: 5, 761: 7, 801: 8, 804: 3, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 967: 4, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1609: 8, 1613: 8, 1649: 8, 1792: 8, 1798: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1858: 8, 1860: 8, 1863: 8, 1872: 8, 1875: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1906: 7, 1907: 7, 1912: 7, 1914: 7, 1917: 7, 1918: 7, 1919: 7, 1920: 7, 1930: 7, 1937: 8, 1953: 8, 1968: 8, 2001: 8, 2017: 8, 2018: 8, 2020: 8, 2026: 8 + }], + CAR.CADILLAC_ESCALADE_ESV: [{ + 309: 1, 848: 8, 849: 8, 850: 8, 851: 8, 852: 8, 853: 8, 854: 3, 1056: 6, 1057: 8, 1058: 8, 1059: 8, 1060: 8, 1061: 8, 1062: 8, 1063: 8, 1064: 8, 1065: 8, 1066: 8, 1067: 8, 1068: 8, 1120: 8, 1121: 8, 1122: 8, 1123: 8, 1124: 8, 1125: 8, 1126: 8, 1127: 8, 1128: 8, 1129: 8, 1130: 8, 1131: 8, 1132: 8, 1133: 8, 1134: 8, 1135: 8, 1136: 8, 1137: 8, 1138: 8, 1139: 8, 1140: 8, 1141: 8, 1142: 8, 1143: 8, 1146: 8, 1147: 8, 1148: 8, 1149: 8, 1150: 8, 1151: 8, 1216: 8, 1217: 8, 1218: 8, 1219: 8, 1220: 8, 1221: 8, 1222: 8, 1223: 8, 1224: 8, 1225: 8, 1226: 8, 1232: 8, 1233: 8, 1234: 8, 1235: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1240: 8, 1241: 8, 1242: 8, 1787: 8, 1788: 8 + }], + CAR.CADILLAC_ESCALADE_ESV_2019: [{ + 715: 8, 840: 5, 717: 5, 869: 4, 880: 6, 289: 8, 454: 8, 842: 5, 460: 5, 463: 3, 801: 8, 170: 8, 190: 6, 241: 6, 201: 8, 417: 7, 211: 2, 419: 1, 398: 8, 426: 7, 487: 8, 442: 8, 451: 8, 452: 8, 453: 6, 479: 3, 311: 8, 500: 6, 647: 6, 193: 8, 707: 8, 197: 8, 209: 7, 199: 4, 455: 7, 313: 8, 481: 7, 485: 8, 489: 8, 249: 8, 393: 7, 407: 7, 413: 8, 422: 4, 431: 8, 501: 8, 499: 3, 810: 8, 508: 8, 381: 8, 462: 4, 532: 6, 562: 8, 386: 8, 761: 7, 573: 1, 554: 3, 719: 5, 560: 8, 1279: 4, 388: 8, 288: 5, 1005: 6, 497: 8, 844: 8, 961: 8, 967: 4, 977: 8, 979: 8, 985: 5, 1001: 8, 1017: 8, 1019: 2, 1020: 8, 1217: 8, 510: 8, 866: 4, 304: 1, 969: 8, 384: 4, 1033: 7, 1009: 8, 1034: 7, 1296: 4, 1930: 7, 1105: 5, 1013: 5, 1225: 7, 1919: 7, 320: 3, 534: 2, 352: 5, 298: 8, 1223: 2, 1233: 8, 608: 8, 1265: 8, 609: 6, 1267: 1, 1417: 8, 610: 6, 1906: 7, 611: 6, 612: 8, 613: 8, 208: 8, 564: 5, 309: 8, 1221: 5, 1280: 4, 1249: 8, 1907: 7, 1257: 6, 1300: 8, 1920: 7, 563: 5, 1322: 6, 1323: 4, 1328: 4, 1917: 7, 328: 1, 1912: 7, 1914: 7, 804: 3, 1918: 7 + }], + CAR.CHEVROLET_BOLT_EUV: [{ + 189: 7, 190: 7, 193: 8, 197: 8, 201: 8, 209: 7, 211: 3, 241: 6, 257: 8, 288: 5, 289: 8, 298: 8, 304: 3, 309: 8, 311: 8, 313: 8, 320: 4, 322: 7, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 451: 8, 452: 8, 453: 6, 458: 5, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 528: 5, 532: 6, 560: 8, 562: 8, 563: 5, 565: 5, 566: 8, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 789: 5, 800: 6, 810: 8, 840: 5, 842: 5, 844: 8, 848: 4, 869: 4, 880: 6, 977: 8, 1001: 8, 1017: 8, 1020: 8, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1265: 8, 1280: 4, 1296: 4, 1300: 8, 1611: 8, 1930: 7 + }], + CAR.CHEVROLET_SILVERADO: [{ + 190: 6, 193: 8, 197: 8, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 298: 8, 304: 3, 309: 8, 311: 8, 313: 8, 320: 4, 322: 7, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 460: 5, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 528: 5, 532: 6, 534: 2, 560: 8, 562: 8, 563: 5, 565: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 715: 8, 717: 5, 761: 7, 789: 5, 800: 6, 801: 8, 810: 8, 840: 5, 842: 5, 844: 8, 848: 4, 869: 4, 880: 6, 977: 8, 1001: 8, 1011: 6, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1611: 8, 1930: 7 + }], + CAR.CHEVROLET_EQUINOX: [{ + 190: 6, 193: 8, 197: 8, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 510: 8, 528: 5, 532: 6, 560: 8, 562: 8, 563: 5, 565: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 789: 5, 800: 6, 810: 8, 840: 5, 842: 5, 844: 8, 869: 4, 880: 6, 977: 8, 1001: 8, 1011: 6, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1611: 8, 1930: 7 + }, + { + 190: 6, 201: 8, 211: 2, 717: 5, 241: 6, 451: 8, 298: 8, 452: 8, 453: 6, 479: 3, 485: 8, 249: 8, 500: 6, 587: 8, 1611: 8, 289: 8, 481: 7, 193: 8, 197: 8, 209: 7, 455: 7, 489: 8, 309: 8, 413: 8, 501: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 311: 8, 510: 8, 528: 5, 532: 6, 715: 8, 560: 8, 562: 8, 707: 8, 789: 5, 869: 4, 880: 6, 761: 7, 840: 5, 842: 5, 844: 8, 313: 8, 381: 8, 386: 8, 810: 8, 322: 7, 384: 4, 800: 6, 1033: 7, 1034: 7, 1296: 4, 753: 5, 388: 8, 288: 5, 497: 8, 463: 3, 304: 3, 977: 8, 1001: 8, 1280: 4, 320: 4, 352: 5, 563: 5, 565: 5, 1221: 5, 1011: 6, 1017: 8, 1020: 8, 1249: 8, 1300: 8, 328: 1, 1217: 8, 1233: 8, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1930: 7, 1271: 8 + }], + CAR.CADILLAC_XT4: [{ + 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 292: 2, 298: 8, 304: 3, 309: 8, 313: 8, 320: 4, 322: 7, 328: 1, 331: 3, 352: 5, 353: 3, 368: 3, 381: 8, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 401: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 503: 2, 508: 8, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 719: 5, 761: 7, 806: 1, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 872: 1, 880: 6, 961: 8, 969: 8, 975: 2, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 5, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1037: 5, 1105: 5, 1187: 5, 1195: 3, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1236: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1268: 2, 1271: 8, 1273: 3, 1276: 2, 1277: 7, 1278: 4, 1279: 4, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1345: 8, 1417: 8, 1512: 8, 1517: 8, 1601: 8, 1609: 8, 1613: 8, 1649: 8, 1792: 8, 1793: 8, 1798: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1858: 8, 1860: 8, 1863: 8, 1872: 8, 1875: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1920: 8, 1924: 8, 1930: 7, 1937: 8, 1953: 8, 1968: 8, 1969: 8, 1971: 8, 1975: 8, 1984: 8, 1988: 8, 2000: 8, 2001: 8, 2002: 8, 2016: 8, 2017: 8, 2018: 8, 2020: 8, 2021: 8, 2024: 8, 2026: 8 + }], + CAR.CHEVROLET_VOLT_2019: [{ + 170: 8, 189: 7, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 257: 8, 288: 5, 289: 8, 292: 2, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 331: 3, 352: 5, 368: 3, 381: 8, 384: 4, 386: 8, 388: 8, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 528: 5, 532: 6, 546: 7, 550: 8, 554: 3, 558: 8, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 566: 7, 567: 5, 573: 1, 577: 8, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 3, 707: 8, 711: 6, 715: 8, 717: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 967: 4, 969: 8, 975: 2, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 5, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1236: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1268: 2, 1273: 3, 1275: 3, 1279: 4, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1345: 8, 1417: 8, 1512: 8, 1513: 8, 1516: 8, 1517: 8, 1601: 8, 1609: 8, 1611: 8, 1618: 8, 1613: 8, 1649: 8, 1792: 8, 1793: 8, 1798: 8, 1799: 8, 1810: 8, 1813: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1856: 8, 1858: 8, 1859: 8, 1860: 8, 1862: 8, 1863: 8, 1871: 8, 1872: 8, 1875: 8, 1879: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1905: 7, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1920: 8, 1922: 7, 1927: 7, 1930: 7, 1937: 8, 1953: 8, 1954: 8, 1955: 8, 1968: 8, 1969: 8, 1971: 8, 1975: 8, 1988: 8, 1990: 8, 2000: 8, 2001: 8, 2004: 8, 2017: 8, 2018: 8, 2020: 8, 2021: 8, 2023: 8, 2025: 8, 2028: 8, 2031: 8 + }], + CAR.CHEVROLET_TRAVERSE: [{ + 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 292: 2, 298: 8, 304: 3, 309: 8, 313: 8, 320: 4, 322: 7, 328: 1, 331: 3, 352: 5, 368: 3, 381: 8, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 401: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 567: 5, 573: 1, 577: 8, 578: 8, 579: 8, 587: 8, 603: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 723: 4, 730: 4, 753: 5, 761: 7, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 975: 2, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 5, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1105: 5, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1233: 8, 1236: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1268: 2, 1271: 8, 1279: 4, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1345: 8, 1346: 8, 1347: 8, 1355: 8, 1362: 8, 1417: 8, 1512: 8, 1514: 8, 1601: 8, 1602: 8, 1603: 7, 1609: 8, 1611: 8, 1613: 8, 1618: 8, 1649: 8, 1792: 8, 1793: 8, 1798: 8, 1799: 8, 1810: 8, 1813: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1856: 8, 1858: 8, 1859: 8, 1860: 8, 1862: 8, 1863: 8, 1871: 8, 1872: 8, 1875: 8, 1879: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1920: 7, 1927: 8, 1930: 7, 1937: 8, 1953: 8, 1954: 8, 1955: 8, 1968: 8, 1969: 8, 1971: 8, 1975: 8, 1988: 8, 1990: 8, 2000: 8, 2001: 8, 2004: 8, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2024: 8, 2026: 8 + }], + CAR.GMC_YUKON: [{ + 190: 6, 193: 8, 197: 8, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 8, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 460: 5, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 510: 8, 528: 5, 532: 6, 534: 2, 562: 8, 563: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 761: 7, 800: 6, 801: 8, 810: 8, 840: 5, 842: 5, 844: 8, 848: 4, 977: 8, 1001: 8, 1017: 8, 1020: 8, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1265: 8, 1267: 1, 1280: 4, 1300: 8, 1355: 8, 1611: 8 + }], +} + +FW_VERSIONS: dict[str, dict[tuple, list[bytes]]] = { +} diff --git a/opendbc_repo/opendbc/car/gm/gmcan.py b/opendbc_repo/opendbc/car/gm/gmcan.py new file mode 100644 index 0000000000..cb74b609e4 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/gmcan.py @@ -0,0 +1,171 @@ +from opendbc.car.can_definitions import CanData +from opendbc.car.gm.values import CAR + + +def create_buttons(packer, bus, idx, button): + values = { + "ACCButtons": button, + "RollingCounter": idx, + "ACCAlwaysOne": 1, + "DistanceButton": 0, + } + + checksum = 240 + int(values["ACCAlwaysOne"] * 0xf) + checksum += values["RollingCounter"] * (0x4ef if values["ACCAlwaysOne"] != 0 else 0x3f0) + checksum -= int(values["ACCButtons"] - 1) << 4 # not correct if value is 0 + checksum -= 2 * values["DistanceButton"] + + values["SteeringButtonChecksum"] = checksum + return packer.make_can_msg("ASCMSteeringButton", bus, values) + + +def create_pscm_status(packer, bus, pscm_status): + values = {s: pscm_status[s] for s in [ + "HandsOffSWDetectionMode", + "HandsOffSWlDetectionStatus", + "LKATorqueDeliveredStatus", + "LKADriverAppldTrq", + "LKATorqueDelivered", + "LKATotalTorqueDelivered", + "RollingCounter", + "PSCMStatusChecksum", + ]} + checksum_mod = int(1 - values["HandsOffSWlDetectionStatus"]) << 5 + values["HandsOffSWlDetectionStatus"] = 1 + values["PSCMStatusChecksum"] += checksum_mod + return packer.make_can_msg("PSCMStatus", bus, values) + + +def create_steering_control(packer, bus, apply_torque, idx, lkas_active): + values = { + "LKASteeringCmdActive": lkas_active, + "LKASteeringCmd": apply_torque, + "RollingCounter": idx, + "LKASteeringCmdChecksum": 0x1000 - (lkas_active << 11) - (apply_torque & 0x7ff) - idx + } + + return packer.make_can_msg("ASCMLKASteeringCmd", bus, values) + + +def create_adas_keepalive(bus): + dat = b"\x00\x00\x00\x00\x00\x00\x00" + return [CanData(0x409, dat, bus), CanData(0x40a, dat, bus)] + + +def create_gas_regen_command(packer, bus, throttle, idx, enabled, at_full_stop): + values = { + "GasRegenCmdActive": enabled, + "RollingCounter": idx, + "GasRegenCmd": throttle, + "GasRegenFullStopActive": at_full_stop, + "GasRegenAccType": 1, + } + + dat = packer.make_can_msg("ASCMGasRegenCmd", bus, values)[1] + values["GasRegenChecksum"] = ((1 - enabled) << 24) | \ + (((0xff - dat[1]) & 0xff) << 16) | \ + (((0xff - dat[2]) & 0xff) << 8) | \ + ((0x100 - dat[3] - idx) & 0xff) + + return packer.make_can_msg("ASCMGasRegenCmd", bus, values) + + +def create_friction_brake_command(packer, bus, apply_brake, idx, enabled, near_stop, at_full_stop, CP): + mode = 0x1 + + # TODO: Understand this better. Volts and ICE Camera ACC cars are 0x1 when enabled with no brake + if enabled and CP.carFingerprint in (CAR.CHEVROLET_BOLT_EUV,): + mode = 0x9 + + if apply_brake > 0: + mode = 0xa + if at_full_stop: + mode = 0xd + + # TODO: this is to have GM bringing the car to complete stop, + # but currently it conflicts with OP controls, so turned off. Not set by all cars + #elif near_stop: + # mode = 0xb + + brake = (0x1000 - apply_brake) & 0xfff + checksum = (0x10000 - (mode << 12) - brake - idx) & 0xffff + + values = { + "RollingCounter": idx, + "FrictionBrakeMode": mode, + "FrictionBrakeChecksum": checksum, + "FrictionBrakeCmd": -apply_brake + } + + return packer.make_can_msg("EBCMFrictionBrakeCmd", bus, values) + + +def create_acc_dashboard_command(packer, bus, enabled, target_speed_kph, hud_control, fcw): + target_speed = min(target_speed_kph, 255) + + values = { + "ACCAlwaysOne": 1, + "ACCResumeButton": 0, + "ACCSpeedSetpoint": target_speed, + "ACCGapLevel": hud_control.leadDistanceBars * enabled, # 3 "far", 0 "inactive" + "ACCCmdActive": enabled, + "ACCAlwaysOne2": 1, + "ACCLeadCar": hud_control.leadVisible, + "FCWAlert": 0x3 if fcw else 0 + } + + return packer.make_can_msg("ASCMActiveCruiseControlStatus", bus, values) + + +def create_adas_time_status(bus, tt, idx): + dat = [(tt >> 20) & 0xff, (tt >> 12) & 0xff, (tt >> 4) & 0xff, + ((tt & 0xf) << 4) + (idx << 2)] + chksum = 0x1000 - dat[0] - dat[1] - dat[2] - dat[3] + chksum = chksum & 0xfff + dat += [0x40 + (chksum >> 8), chksum & 0xff, 0x12] + return CanData(0xa1, bytes(dat), bus) + + +def create_adas_steering_status(bus, idx): + dat = [idx << 6, 0xf0, 0x20, 0, 0, 0] + chksum = 0x60 + sum(dat) + dat += [chksum >> 8, chksum & 0xff] + return CanData(0x306, bytes(dat), bus) + + +def create_adas_accelerometer_speed_status(bus, speed_ms, idx): + spd = int(speed_ms * 16) & 0xfff + accel = 0 & 0xfff + # 0 if in park/neutral, 0x10 if in reverse, 0x08 for D/L + #stick = 0x08 + near_range_cutoff = 0x27 + near_range_mode = 1 if spd <= near_range_cutoff else 0 + far_range_mode = 1 - near_range_mode + dat = [0x08, spd >> 4, ((spd & 0xf) << 4) | (accel >> 8), accel & 0xff, 0] + chksum = 0x62 + far_range_mode + (idx << 2) + dat[0] + dat[1] + dat[2] + dat[3] + dat[4] + dat += [(idx << 5) + (far_range_mode << 4) + (near_range_mode << 3) + (chksum >> 8), chksum & 0xff] + return CanData(0x308, bytes(dat), bus) + + +def create_adas_headlights_status(packer, bus): + values = { + "Always42": 0x42, + "Always4": 0x4, + } + return packer.make_can_msg("ASCMHeadlight", bus, values) + + +def create_lka_icon_command(bus, active, critical, steer): + if active and steer == 1: + if critical: + dat = b"\x50\xc0\x14" + else: + dat = b"\x50\x40\x18" + elif active: + if critical: + dat = b"\x40\xc0\x14" + else: + dat = b"\x40\x40\x18" + else: + dat = b"\x00\x00\x00" + return CanData(0x104c006c, dat, bus) diff --git a/opendbc_repo/opendbc/car/gm/interface.py b/opendbc_repo/opendbc/car/gm/interface.py new file mode 100755 index 0000000000..38adf80d62 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/interface.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +from math import fabs, exp +import numpy as np + +from opendbc.car import get_safety_config, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.gm.carcontroller import CarController +from opendbc.car.gm.carstate import CarState +from opendbc.car.gm.radar_interface import RadarInterface, RADAR_HEADER_MSG, CAMERA_DATA_HEADER_MSG +from opendbc.car.gm.values import CAR, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, ALT_ACCS, CanBus, GMSafetyFlags +from opendbc.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, LateralAccelFromTorqueCallbackType + +TransmissionType = structs.CarParams.TransmissionType +NetworkLocation = structs.CarParams.NetworkLocation + +NON_LINEAR_TORQUE_PARAMS = { + CAR.CHEVROLET_BOLT_EUV: [2.6531724862969748, 1.0, 0.1919764879840985, 0.009054123646805178], + CAR.GMC_ACADIA: [4.78003305, 1.0, 0.3122, 0.05591772], + CAR.CHEVROLET_SILVERADO: [3.29974374, 1.0, 0.25571356, 0.0465122] +} + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def get_pid_accel_limits(CP, current_speed, cruise_speed): + return CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX + + # Determined by iteratively plotting and minimizing error for f(angle, speed) = steer. + @staticmethod + def get_steer_feedforward_volt(desired_angle, v_ego): + desired_angle *= 0.02904609 + sigmoid = desired_angle / (1 + fabs(desired_angle)) + return 0.10006696 * sigmoid * (v_ego + 3.12485927) + + def get_steer_feedforward_function(self): + if self.CP.carFingerprint == CAR.CHEVROLET_VOLT: + return self.get_steer_feedforward_volt + else: + return CarInterfaceBase.get_steer_feedforward_default + + def get_lataccel_torque_siglin(self) -> float: + + def torque_from_lateral_accel_siglin_func(lateral_acceleration: float) -> float: + # The "lat_accel vs torque" relationship is assumed to be the sum of "sigmoid + linear" curves + # An important thing to consider is that the slope at 0 should be > 0 (ideally >1) + # This has big effect on the stability about 0 (noise when going straight) + non_linear_torque_params = NON_LINEAR_TORQUE_PARAMS.get(self.CP.carFingerprint) + assert non_linear_torque_params, "The params are not defined" + a, b, c, _ = non_linear_torque_params + sig_input = a * lateral_acceleration + sig = np.sign(sig_input) * (1 / (1 + exp(-fabs(sig_input))) - 0.5) + steer_torque = (sig * b) + (lateral_acceleration * c) + return float(steer_torque) + + lataccel_values = np.arange(-5.0, 5.0, 0.01) + torque_values = [torque_from_lateral_accel_siglin_func(x) for x in lataccel_values] + assert min(torque_values) < -1 and max(torque_values) > 1, "The torque values should cover the range [-1, 1]" + return torque_values, lataccel_values + + def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType: + if self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS: + torque_values, lataccel_values = self.get_lataccel_torque_siglin() + + def torque_from_lateral_accel_siglin(lateral_acceleration: float, torque_params: structs.CarParams.LateralTorqueTuning): + return np.interp(lateral_acceleration, lataccel_values, torque_values) + return torque_from_lateral_accel_siglin + else: + return self.torque_from_lateral_accel_linear + + def lateral_accel_from_torque(self) -> LateralAccelFromTorqueCallbackType: + if self.CP.carFingerprint in NON_LINEAR_TORQUE_PARAMS: + torque_values, lataccel_values = self.get_lataccel_torque_siglin() + + def lateral_accel_from_torque_siglin(torque: float, torque_params: structs.CarParams.LateralTorqueTuning): + return np.interp(torque, torque_values, lataccel_values) + return lateral_accel_from_torque_siglin + else: + return self.lateral_accel_from_torque_linear + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "gm" + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.gm)] + ret.autoResumeSng = False + ret.enableBsm = 0x142 in fingerprint[CanBus.POWERTRAIN] + + if candidate in EV_CAR: + ret.transmissionType = TransmissionType.direct + ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.EV.value + else: + ret.transmissionType = TransmissionType.automatic + + ret.longitudinalTuning.kiBP = [5., 35.] + + if candidate in (CAMERA_ACC_CAR | SDGM_CAR): + ret.alphaLongitudinalAvailable = candidate not in SDGM_CAR + ret.networkLocation = NetworkLocation.fwdCamera + ret.radarUnavailable = True # no radar + ret.pcmCruise = True + ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.HW_CAM.value + ret.minEnableSpeed = -1 if candidate in SDGM_CAR else 5 * CV.KPH_TO_MS + ret.minSteerSpeed = 10 * CV.KPH_TO_MS + + # Tuning for experimental long + ret.longitudinalTuning.kiV = [2.0, 1.5] + ret.stoppingDecelRate = 2.0 # reach brake quickly after enabling + ret.vEgoStopping = 0.25 + ret.vEgoStarting = 0.25 + + if alpha_long: + ret.pcmCruise = False + ret.openpilotLongitudinalControl = True + ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.HW_CAM_LONG.value + + if candidate in ALT_ACCS: + ret.alphaLongitudinalAvailable = False + ret.openpilotLongitudinalControl = False + ret.minEnableSpeed = -1. # engage speed is decided by PCM + + else: # ASCM, OBD-II harness + ret.openpilotLongitudinalControl = True + ret.networkLocation = NetworkLocation.gateway + # LRR messages can take up to a few seconds to start sending after ignition, check camera data as well which starts earlier + ret.radarUnavailable = RADAR_HEADER_MSG not in fingerprint[CanBus.OBSTACLE] and CAMERA_DATA_HEADER_MSG not in fingerprint[CanBus.OBSTACLE] and not docs + ret.pcmCruise = False # stock non-adaptive cruise control is kept off + # supports stop and go, but initial engage must (conservatively) be above 18mph + ret.minEnableSpeed = 18 * CV.MPH_TO_MS + ret.minSteerSpeed = 7 * CV.MPH_TO_MS + + # Tuning + ret.longitudinalTuning.kiV = [2.4, 1.5] + + # These cars have been put into dashcam only due to both a lack of users and test coverage. + # These cars likely still work fine. Once a user confirms each car works and a test route is + # added to opendbc/car/tests/routes.py, we can remove it from this list. + ret.dashcamOnly = candidate in {CAR.CADILLAC_ATS, CAR.HOLDEN_ASTRA, CAR.CHEVROLET_MALIBU, CAR.BUICK_REGAL} or \ + (ret.networkLocation == NetworkLocation.gateway and ret.radarUnavailable) + + # Start with a baseline tuning for all GM vehicles. Override tuning as needed in each model section below. + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.00]] + ret.lateralTuning.pid.kf = 0.00004 # full torque for 20 deg at 80mph means 0.00007818594 + ret.steerActuatorDelay = 0.1 # Default delay, not measured yet + + ret.steerLimitTimer = 0.4 + ret.longitudinalActuatorDelay = 0.5 # large delay to initially start braking + + if candidate == CAR.CHEVROLET_VOLT: + ret.lateralTuning.pid.kpBP = [0., 40.] + ret.lateralTuning.pid.kpV = [0., 0.17] + ret.lateralTuning.pid.kiBP = [0.] + ret.lateralTuning.pid.kiV = [0.] + ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt() + ret.steerActuatorDelay = 0.2 + + elif candidate == CAR.GMC_ACADIA: + ret.minEnableSpeed = -1. # engage speed is decided by pcm + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.BUICK_LACROSSE: + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CADILLAC_ESCALADE: + ret.minEnableSpeed = -1. # engage speed is decided by pcm + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate in (CAR.CADILLAC_ESCALADE_ESV, CAR.CADILLAC_ESCALADE_ESV_2019): + ret.minEnableSpeed = -1. # engage speed is decided by pcm + + if candidate == CAR.CADILLAC_ESCALADE_ESV: + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[10., 41.0], [10., 41.0]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.13, 0.24], [0.01, 0.02]] + ret.lateralTuning.pid.kf = 0.000045 + else: + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CHEVROLET_BOLT_EUV: + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CHEVROLET_SILVERADO: + # On the Bolt, the ECM and camera independently check that you are either above 5 kph or at a stop + # with foot on brake to allow engagement, but this platform only has that check in the camera. + # TODO: check if this is split by EV/ICE with more platforms in the future + if ret.openpilotLongitudinalControl: + ret.minEnableSpeed = -1. + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CHEVROLET_EQUINOX: + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CHEVROLET_TRAILBLAZER: + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CADILLAC_XT4: + ret.steerActuatorDelay = 0.2 + ret.minSteerSpeed = 30 * CV.MPH_TO_MS + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CHEVROLET_VOLT_2019: + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.CHEVROLET_TRAVERSE: + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + elif candidate == CAR.GMC_YUKON: + ret.steerActuatorDelay = 0.5 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + ret.dashcamOnly = True # Needs steerRatio, tireStiffness, and lat accel factor tuning + + return ret diff --git a/opendbc_repo/opendbc/car/gm/radar_interface.py b/opendbc_repo/opendbc/car/gm/radar_interface.py new file mode 100755 index 0000000000..c7b70007e2 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/radar_interface.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +import math +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.gm.values import DBC, CanBus +from opendbc.car.interfaces import RadarInterfaceBase + +RADAR_HEADER_MSG = 1120 # F_LRR_Obj_Header +CAMERA_DATA_HEADER_MSG = 1056 # F_Vision_Obj_Header +SLOT_1_MSG = RADAR_HEADER_MSG + 1 +NUM_SLOTS = 20 + +# Actually it's 0x47f, but can parser only reports +# messages that are present in DBC +LAST_RADAR_MSG = RADAR_HEADER_MSG + NUM_SLOTS + + +def create_radar_can_parser(car_fingerprint): + # C1A-ARS3-A by Continental + radar_targets = list(range(SLOT_1_MSG, SLOT_1_MSG + NUM_SLOTS)) + signals = list(zip(['FLRRNumValidTargets', + 'FLRRSnsrBlckd', 'FLRRYawRtPlsblityFlt', + 'FLRRHWFltPrsntInt', 'FLRRAntTngFltPrsnt', + 'FLRRAlgnFltPrsnt', 'FLRRSnstvFltPrsntInt'] + + ['TrkRange'] * NUM_SLOTS + ['TrkRangeRate'] * NUM_SLOTS + + ['TrkRangeAccel'] * NUM_SLOTS + ['TrkAzimuth'] * NUM_SLOTS + + ['TrkWidth'] * NUM_SLOTS + ['TrkObjectID'] * NUM_SLOTS, + [RADAR_HEADER_MSG] * 7 + radar_targets * 6, strict=True)) + + messages = list({(s[1], 14) for s in signals}) + + return CANParser(DBC[car_fingerprint][Bus.radar], messages, CanBus.OBSTACLE) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + + self.rcp = None if CP.radarUnavailable else create_radar_can_parser(CP.carFingerprint) + + self.trigger_msg = LAST_RADAR_MSG + self.updated_messages = set() + + def update(self, can_strings): + if self.rcp is None: + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + + ret = structs.RadarData() + header = self.rcp.vl[RADAR_HEADER_MSG] + fault = header['FLRRSnsrBlckd'] or header['FLRRSnstvFltPrsntInt'] or \ + header['FLRRYawRtPlsblityFlt'] or header['FLRRHWFltPrsntInt'] or \ + header['FLRRAntTngFltPrsnt'] or header['FLRRAlgnFltPrsnt'] + if not self.rcp.can_valid: + ret.errors.canError = True + if fault: + ret.errors.radarFault = True + + currentTargets = set() + num_targets = header['FLRRNumValidTargets'] + + # Not all radar messages describe targets, + # no need to monitor all of the self.rcp.msgs_upd + for ii in self.updated_messages: + if ii == RADAR_HEADER_MSG: + continue + + if num_targets == 0: + break + + cpt = self.rcp.vl[ii] + # Zero distance means it's an empty target slot + if cpt['TrkRange'] > 0.0: + targetId = cpt['TrkObjectID'] + currentTargets.add(targetId) + if targetId not in self.pts: + self.pts[targetId] = structs.RadarData.RadarPoint() + self.pts[targetId].trackId = targetId + distance = cpt['TrkRange'] + self.pts[targetId].dRel = distance # from front of car + # From driver's pov, left is positive + self.pts[targetId].yRel = math.sin(cpt['TrkAzimuth'] * CV.DEG_TO_RAD) * distance + self.pts[targetId].vRel = cpt['TrkRangeRate'] + self.pts[targetId].aRel = float('nan') + self.pts[targetId].yvRel = float('nan') + + for oldTarget in list(self.pts.keys()): + if oldTarget not in currentTargets: + del self.pts[oldTarget] + + ret.points = list(self.pts.values()) + self.updated_messages.clear() + return ret diff --git a/opendbc_repo/opendbc/car/gm/tests/__init__.py b/opendbc_repo/opendbc/car/gm/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/gm/tests/test_gm.py b/opendbc_repo/opendbc/car/gm/tests/test_gm.py new file mode 100644 index 0000000000..c14b9bd243 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/tests/test_gm.py @@ -0,0 +1,20 @@ +from parameterized import parameterized + +from opendbc.car.gm.fingerprints import FINGERPRINTS +from opendbc.car.gm.values import CAMERA_ACC_CAR, GM_RX_OFFSET + +CAMERA_DIAGNOSTIC_ADDRESS = 0x24b + + +class TestGMFingerprint: + @parameterized.expand(FINGERPRINTS.items()) + def test_can_fingerprints(self, car_model, fingerprints): + assert len(fingerprints) > 0 + + assert all(len(finger) for finger in fingerprints) + + # The camera can sometimes be communicating on startup + if car_model in CAMERA_ACC_CAR: + for finger in fingerprints: + for required_addr in (CAMERA_DIAGNOSTIC_ADDRESS, CAMERA_DIAGNOSTIC_ADDRESS + GM_RX_OFFSET): + assert finger.get(required_addr) == 8, required_addr diff --git a/opendbc_repo/opendbc/car/gm/values.py b/opendbc_repo/opendbc/car/gm/values.py new file mode 100644 index 0000000000..13793537b5 --- /dev/null +++ b/opendbc_repo/opendbc/car/gm/values.py @@ -0,0 +1,286 @@ +from dataclasses import dataclass, field +from enum import Enum, IntFlag + +from opendbc.car import Bus, PlatformConfig, DbcDict, Platforms, CarSpecs +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarDocs, CarFootnote, CarHarness, CarParts, Column +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu + + +class CarControllerParams: + STEER_MAX = 300 # GM limit is 3Nm. Used by carcontroller to generate LKA output + STEER_STEP = 3 # Active control frames per command (~33hz) + INACTIVE_STEER_STEP = 10 # Inactive control frames per command (10hz) + STEER_DELTA_UP = 10 # Delta rates require review due to observed EPS weakness + STEER_DELTA_DOWN = 15 + STEER_DRIVER_ALLOWANCE = 65 + STEER_DRIVER_MULTIPLIER = 4 + STEER_DRIVER_FACTOR = 100 + NEAR_STOP_BRAKE_PHASE = 0.5 # m/s + + # Heartbeat for dash "Service Adaptive Cruise" and "Service Front Camera" + ADAS_KEEPALIVE_STEP = 100 + CAMERA_KEEPALIVE_STEP = 100 + + # Allow small margin below -3.5 m/s^2 from ISO 15622:2018 since we + # perform the closed loop control, and might need some + # to apply some more braking if we're on a downhill slope. + # Our controller should still keep the 2 second average above + # -3.5 m/s^2 as per planner limits + ACCEL_MAX = 2. # m/s^2 + ACCEL_MIN = -4. # m/s^2 + + def __init__(self, CP): + # Gas/brake lookups + self.MAX_BRAKE = 400 # ~ -4.0 m/s^2 with regen + + if CP.carFingerprint in (CAMERA_ACC_CAR | SDGM_CAR): + self.MAX_GAS = 1346.0 + self.MAX_ACC_REGEN = -540.0 + self.INACTIVE_REGEN = -500.0 + # Camera ACC vehicles have no regen while enabled. + # Camera transitions to MAX_ACC_REGEN from zero gas and uses friction brakes instantly + max_regen_acceleration = 0. + + else: + self.MAX_GAS = 1018.0 # Safety limit, not ACC max. Stock ACC >2042 from standstill. + self.MAX_ACC_REGEN = -650.0 # Max ACC regen is slightly less than max paddle regen + self.INACTIVE_REGEN = -650.0 + # ICE has much less engine braking force compared to regen in EVs, + # lower threshold removes some braking deadzone + max_regen_acceleration = -1. if CP.carFingerprint in EV_CAR else -0.1 + + self.GAS_LOOKUP_BP = [max_regen_acceleration, 0., self.ACCEL_MAX] + self.GAS_LOOKUP_V = [self.MAX_ACC_REGEN, 0., self.MAX_GAS] + + self.BRAKE_LOOKUP_BP = [self.ACCEL_MIN, max_regen_acceleration] + self.BRAKE_LOOKUP_V = [self.MAX_BRAKE, 0.] + + +class GMSafetyFlags(IntFlag): + HW_CAM = 1 + HW_CAM_LONG = 2 + EV = 4 + + +class Footnote(Enum): + SETUP = CarFootnote( + "See more setup details for GM.", + Column.MAKE, setup_note=True) + + +@dataclass +class GMCarDocs(CarDocs): + package: str = "Adaptive Cruise Control (ACC)" + + def init_make(self, CP: CarParams): + if CP.networkLocation == CarParams.NetworkLocation.fwdCamera: + if CP.carFingerprint in SDGM_CAR: + self.car_parts = CarParts.common([CarHarness.gmsdgm]) + else: + self.car_parts = CarParts.common([CarHarness.gm]) + else: + self.footnotes.insert(0, Footnote.SETUP) + self.car_parts = CarParts.common([CarHarness.obd_ii]) + + +@dataclass(frozen=True, kw_only=True) +class GMCarSpecs(CarSpecs): + tireStiffnessFactor: float = 0.444 # not optimized yet + + +@dataclass +class GMPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: { + Bus.pt: 'gm_global_a_powertrain_generated', + Bus.radar: 'gm_global_a_object', + Bus.chassis: 'gm_global_a_chassis', + }) + + +@dataclass +class GMASCMPlatformConfig(GMPlatformConfig): + def init(self): + # ASCM is supported, but due to a janky install and hardware configuration, we are not showing in the car docs + self.car_docs = [] + + +@dataclass +class GMSDGMPlatformConfig(GMPlatformConfig): + def init(self): + # Don't show in docs until the harness is sold. See https://github.com/commaai/openpilot/issues/32471 + self.car_docs = [] + + +class CAR(Platforms): + HOLDEN_ASTRA = GMASCMPlatformConfig( + [GMCarDocs("Holden Astra 2017")], + GMCarSpecs(mass=1363, wheelbase=2.662, steerRatio=15.7, centerToFrontRatio=0.4), + ) + CHEVROLET_VOLT = GMASCMPlatformConfig( + [GMCarDocs("Chevrolet Volt 2017-18", min_enable_speed=0, video="https://youtu.be/QeMCN_4TFfQ")], + GMCarSpecs(mass=1607, wheelbase=2.69, steerRatio=17.7, centerToFrontRatio=0.45, tireStiffnessFactor=0.469), + ) + CADILLAC_ATS = GMASCMPlatformConfig( + [GMCarDocs("Cadillac ATS Premium Performance 2018")], + GMCarSpecs(mass=1601, wheelbase=2.78, steerRatio=15.3), + ) + CHEVROLET_MALIBU = GMASCMPlatformConfig( + [GMCarDocs("Chevrolet Malibu Premier 2017")], + GMCarSpecs(mass=1496, wheelbase=2.83, steerRatio=15.8, centerToFrontRatio=0.4), + ) + GMC_ACADIA = GMASCMPlatformConfig( + [GMCarDocs("GMC Acadia 2018", video="https://www.youtube.com/watch?v=0ZN6DdsBUZo")], + GMCarSpecs(mass=1975, wheelbase=2.86, steerRatio=14.4, centerToFrontRatio=0.4), + ) + BUICK_LACROSSE = GMASCMPlatformConfig( + [GMCarDocs("Buick LaCrosse 2017-19", "Driver Confidence Package 2")], + GMCarSpecs(mass=1712, wheelbase=2.91, steerRatio=15.8, centerToFrontRatio=0.4), + ) + BUICK_REGAL = GMASCMPlatformConfig( + [GMCarDocs("Buick Regal Essence 2018")], + GMCarSpecs(mass=1714, wheelbase=2.83, steerRatio=14.4, centerToFrontRatio=0.4), + ) + CADILLAC_ESCALADE = GMASCMPlatformConfig( + [GMCarDocs("Cadillac Escalade 2017", "Driver Assist Package")], + GMCarSpecs(mass=2564, wheelbase=2.95, steerRatio=17.3), + ) + CADILLAC_ESCALADE_ESV = GMASCMPlatformConfig( + [GMCarDocs("Cadillac Escalade ESV 2016", "Adaptive Cruise Control (ACC) & LKAS")], + GMCarSpecs(mass=2739, wheelbase=3.302, steerRatio=17.3, tireStiffnessFactor=1.0), + ) + CADILLAC_ESCALADE_ESV_2019 = GMASCMPlatformConfig( + [GMCarDocs("Cadillac Escalade ESV 2019", "Adaptive Cruise Control (ACC) & LKAS")], + CADILLAC_ESCALADE_ESV.specs, + ) + CHEVROLET_BOLT_EUV = GMPlatformConfig( + [ + GMCarDocs("Chevrolet Bolt EUV 2022-23", "Premier or Premier Redline Trim without Super Cruise Package", video="https://youtu.be/xvwzGMUA210"), + GMCarDocs("Chevrolet Bolt EV 2022-23", "2LT Trim with Adaptive Cruise Control Package"), + ], + GMCarSpecs(mass=1669, wheelbase=2.63779, steerRatio=16.8, centerToFrontRatio=0.4, tireStiffnessFactor=1.0), + ) + CHEVROLET_SILVERADO = GMPlatformConfig( + [ + GMCarDocs("Chevrolet Silverado 1500 2020-21", "Safety Package II"), + GMCarDocs("GMC Sierra 1500 2020-21", "Driver Alert Package II", video="https://youtu.be/5HbNoBLzRwE"), + ], + GMCarSpecs(mass=2450, wheelbase=3.75, steerRatio=16.3, tireStiffnessFactor=1.0), + ) + CHEVROLET_EQUINOX = GMPlatformConfig( + [GMCarDocs("Chevrolet Equinox 2019-22")], + GMCarSpecs(mass=1588, wheelbase=2.72, steerRatio=14.4, centerToFrontRatio=0.4), + ) + CHEVROLET_TRAILBLAZER = GMPlatformConfig( + [GMCarDocs("Chevrolet Trailblazer 2021-22")], + GMCarSpecs(mass=1345, wheelbase=2.64, steerRatio=16.8, centerToFrontRatio=0.4, tireStiffnessFactor=1.0), + ) + CADILLAC_XT4 = GMSDGMPlatformConfig( + [GMCarDocs("Cadillac XT4 2023", "Driver Assist Package")], + GMCarSpecs(mass=1660, wheelbase=2.78, steerRatio=14.4, centerToFrontRatio=0.4), + ) + CHEVROLET_VOLT_2019 = GMSDGMPlatformConfig( + [GMCarDocs("Chevrolet Volt 2019", "Adaptive Cruise Control (ACC) & LKAS")], + GMCarSpecs(mass=1607, wheelbase=2.69, steerRatio=15.7, centerToFrontRatio=0.45), + ) + CHEVROLET_TRAVERSE = GMSDGMPlatformConfig( + [GMCarDocs("Chevrolet Traverse 2022-23", "RS, Premier, or High Country Trim")], + GMCarSpecs(mass=1955, wheelbase=3.07, steerRatio=17.9, centerToFrontRatio=0.4), + ) + GMC_YUKON = GMPlatformConfig( + [GMCarDocs("GMC Yukon 2019-20", "Adaptive Cruise Control (ACC) & LKAS")], + GMCarSpecs(mass=2490, wheelbase=2.94, steerRatio=17.3, centerToFrontRatio=0.5, tireStiffnessFactor=1.0), + ) + + +class CruiseButtons: + INIT = 0 + UNPRESS = 1 + RES_ACCEL = 2 + DECEL_SET = 3 + MAIN = 5 + CANCEL = 6 + + +class AccState: + OFF = 0 + ACTIVE = 1 + FAULTED = 3 + STANDSTILL = 4 + + +class CanBus: + POWERTRAIN = 0 + OBSTACLE = 1 + CAMERA = 2 + CHASSIS = 2 + LOOPBACK = 128 + DROPPED = 192 + + +# In a Data Module, an identifier is a string used to recognize an object, +# either by itself or together with the identifiers of parent objects. +# Each returns a 4 byte hex representation of the decimal part number. `b"\x02\x8c\xf0'"` -> 42790951 +GM_BOOT_SOFTWARE_PART_NUMER_REQUEST = b'\x1a\xc0' # likely does not contain anything useful +GM_SOFTWARE_MODULE_1_REQUEST = b'\x1a\xc1' +GM_SOFTWARE_MODULE_2_REQUEST = b'\x1a\xc2' +GM_SOFTWARE_MODULE_3_REQUEST = b'\x1a\xc3' + +# Part number of XML data file that is used to configure ECU +GM_XML_DATA_FILE_PART_NUMBER = b'\x1a\x9c' +GM_XML_CONFIG_COMPAT_ID = b'\x1a\x9b' # used to know if XML file is compatible with the ECU software/hardware + +# This DID is for identifying the part number that reflects the mix of hardware, +# software, and calibrations in the ECU when it first arrives at the vehicle assembly plant. +# If there's an Alpha Code, it's associated with this part number and stored in the DID $DB. +GM_END_MODEL_PART_NUMBER_REQUEST = b'\x1a\xcb' +GM_END_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST = b'\x1a\xdb' +GM_BASE_MODEL_PART_NUMBER_REQUEST = b'\x1a\xcc' +GM_BASE_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST = b'\x1a\xdc' +GM_FW_RESPONSE = b'\x5a' + +GM_FW_REQUESTS = [ + GM_BOOT_SOFTWARE_PART_NUMER_REQUEST, + GM_SOFTWARE_MODULE_1_REQUEST, + GM_SOFTWARE_MODULE_2_REQUEST, + GM_SOFTWARE_MODULE_3_REQUEST, + GM_XML_DATA_FILE_PART_NUMBER, + GM_XML_CONFIG_COMPAT_ID, + GM_END_MODEL_PART_NUMBER_REQUEST, + GM_END_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST, + GM_BASE_MODEL_PART_NUMBER_REQUEST, + GM_BASE_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST, +] + +GM_RX_OFFSET = 0x400 + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[request for req in GM_FW_REQUESTS for request in [ + Request( + [StdQueries.SHORT_TESTER_PRESENT_REQUEST, req], + [StdQueries.SHORT_TESTER_PRESENT_RESPONSE, GM_FW_RESPONSE + bytes([req[-1]])], + rx_offset=GM_RX_OFFSET, + bus=0, + logging=True, + ), + ]], + extra_ecus=[(Ecu.fwdCamera, 0x24b, None)], +) + +# TODO: detect most of these sets live +EV_CAR = {CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_BOLT_EUV} + +# We're integrated at the camera with VOACC on these cars (instead of ASCM w/ OBD-II harness) +CAMERA_ACC_CAR = {CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_SILVERADO, CAR.CHEVROLET_EQUINOX, CAR.CHEVROLET_TRAILBLAZER, CAR.GMC_YUKON} + +# Alt ASCMActiveCruiseControlStatus +ALT_ACCS = {CAR.GMC_YUKON} + +# We're integrated at the Safety Data Gateway Module on these cars +SDGM_CAR = {CAR.CADILLAC_XT4, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_TRAVERSE} + +STEER_THRESHOLD = 1.0 + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/honda/__init__.py b/opendbc_repo/opendbc/car/honda/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/honda/carcontroller.py b/opendbc_repo/opendbc/car/honda/carcontroller.py new file mode 100644 index 0000000000..e442230781 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/carcontroller.py @@ -0,0 +1,250 @@ +import numpy as np + +from opendbc.can import CANPacker +from opendbc.car import Bus, DT_CTRL, rate_limit, make_tester_present_msg, structs +from opendbc.car.honda import hondacan +from opendbc.car.honda.values import CAR, CruiseButtons, HONDA_BOSCH, HONDA_BOSCH_CANFD, HONDA_BOSCH_RADARLESS, \ + HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams +from opendbc.car.interfaces import CarControllerBase + +VisualAlert = structs.CarControl.HUDControl.VisualAlert +LongCtrlState = structs.CarControl.Actuators.LongControlState + + +def compute_gb_honda_bosch(accel, speed): + # TODO returns 0s, is unused + return 0.0, 0.0 + + +def compute_gb_honda_nidec(accel, speed): + creep_brake = 0.0 + creep_speed = 2.3 + creep_brake_value = 0.15 + if speed < creep_speed: + creep_brake = (creep_speed - speed) / creep_speed * creep_brake_value + gb = float(accel) / 4.8 - creep_brake + return np.clip(gb, 0.0, 1.0), np.clip(-gb, 0.0, 1.0) + + +def compute_gas_brake(accel, speed, fingerprint): + if fingerprint in HONDA_BOSCH: + return compute_gb_honda_bosch(accel, speed) + else: + return compute_gb_honda_nidec(accel, speed) + + +# TODO not clear this does anything useful +def actuator_hysteresis(brake, braking, brake_steady, v_ego, car_fingerprint): + # hyst params + brake_hyst_on = 0.02 # to activate brakes exceed this value + brake_hyst_off = 0.005 # to deactivate brakes below this value + brake_hyst_gap = 0.01 # don't change brake command for small oscillations within this value + + # *** hysteresis logic to avoid brake blinking. go above 0.1 to trigger + if (brake < brake_hyst_on and not braking) or brake < brake_hyst_off: + brake = 0. + braking = brake > 0. + + # for small brake oscillations within brake_hyst_gap, don't change the brake command + if brake == 0.: + brake_steady = 0. + elif brake > brake_steady + brake_hyst_gap: + brake_steady = brake - brake_hyst_gap + elif brake < brake_steady - brake_hyst_gap: + brake_steady = brake + brake_hyst_gap + brake = brake_steady + + return brake, braking, brake_steady + + +def brake_pump_hysteresis(apply_brake, apply_brake_last, last_pump_ts, ts): + pump_on = False + + # reset pump timer if: + # - there is an increment in brake request + # - we are applying steady state brakes and we haven't been running the pump + # for more than 20s (to prevent pressure bleeding) + if apply_brake > apply_brake_last or (ts - last_pump_ts > 20. and apply_brake > 0): + last_pump_ts = ts + + # once the pump is on, run it for at least 0.2s + if ts - last_pump_ts < 0.2 and apply_brake > 0: + pump_on = True + + return pump_on, last_pump_ts + + +def process_hud_alert(hud_alert): + alert_fcw = False + alert_steer_required = False + + # Make sure FCW is prioritized over steering required + # TODO: implement separate available LDW alert + if hud_alert == VisualAlert.fcw: + alert_fcw = True + elif hud_alert in (VisualAlert.steerRequired, VisualAlert.ldw): + alert_steer_required = True + + return alert_fcw, alert_steer_required + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.packer = CANPacker(dbc_names[Bus.pt]) + self.params = CarControllerParams(CP) + self.CAN = hondacan.CanBus(CP) + + self.braking = False + self.brake_steady = 0. + self.brake_last = 0. + self.apply_brake_last = 0 + self.last_pump_ts = 0. + self.stopping_counter = 0 + + self.accel = 0.0 + self.speed = 0.0 + self.gas = 0.0 + self.brake = 0.0 + self.last_torque = 0.0 + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + hud_control = CC.hudControl + hud_v_cruise = hud_control.setSpeed / CS.v_cruise_factor if hud_control.speedVisible else 255 + pcm_cancel_cmd = CC.cruiseControl.cancel + + if CC.longActive: + accel = actuators.accel + gas, brake = compute_gas_brake(actuators.accel, CS.out.vEgo, self.CP.carFingerprint) + else: + accel = 0.0 + gas, brake = 0.0, 0.0 + + # *** rate limit steer *** + limited_torque = rate_limit(actuators.torque, self.last_torque, -self.params.STEER_DELTA_DOWN * DT_CTRL, + self.params.STEER_DELTA_UP * DT_CTRL) + self.last_torque = limited_torque + + # *** apply brake hysteresis *** + pre_limit_brake, self.braking, self.brake_steady = actuator_hysteresis(brake, self.braking, self.brake_steady, + CS.out.vEgo, self.CP.carFingerprint) + + # *** rate limit after the enable check *** + self.brake_last = rate_limit(pre_limit_brake, self.brake_last, -2., DT_CTRL) + + # vehicle hud display, wait for one update from 10Hz 0x304 msg + alert_fcw, alert_steer_required = process_hud_alert(hud_control.visualAlert) + + # **** process the car messages **** + + # steer torque is converted back to CAN reference (positive when steering right) + apply_torque = int(np.interp(-limited_torque * self.params.STEER_MAX, + self.params.STEER_LOOKUP_BP, self.params.STEER_LOOKUP_V)) + + # Send CAN commands + can_sends = [] + + # tester present - w/ no response (keeps radar disabled) + if self.CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and self.CP.openpilotLongitudinalControl: + if self.frame % 10 == 0: + can_sends.append(make_tester_present_msg(0x18DAB0F1, 1, suppress_response=True)) + + # Send steering command. + can_sends.append(hondacan.create_steering_control(self.packer, self.CAN, apply_torque, CC.latActive)) + + # wind brake from air resistance decel at high speed + wind_brake = np.interp(CS.out.vEgo, [0.0, 2.3, 35.0], [0.001, 0.002, 0.15]) + # all of this is only relevant for HONDA NIDEC + max_accel = np.interp(CS.out.vEgo, self.params.NIDEC_MAX_ACCEL_BP, self.params.NIDEC_MAX_ACCEL_V) + # TODO this 1.44 is just to maintain previous behavior + pcm_speed_BP = [-wind_brake, + -wind_brake * (3 / 4), + 0.0, + 0.5] + # The Honda ODYSSEY seems to have different PCM_ACCEL + # msgs, is it other cars too? + if not CC.longActive: + pcm_speed = 0.0 + pcm_accel = int(0.0) + elif self.CP.carFingerprint in HONDA_NIDEC_ALT_PCM_ACCEL: + pcm_speed_V = [0.0, + np.clip(CS.out.vEgo - 3.0, 0.0, 100.0), + np.clip(CS.out.vEgo + 0.0, 0.0, 100.0), + np.clip(CS.out.vEgo + 5.0, 0.0, 100.0)] + pcm_speed = float(np.interp(gas - brake, pcm_speed_BP, pcm_speed_V)) + pcm_accel = int(1.0 * self.params.NIDEC_GAS_MAX) + else: + pcm_speed_V = [0.0, + np.clip(CS.out.vEgo - 2.0, 0.0, 100.0), + np.clip(CS.out.vEgo + 2.0, 0.0, 100.0), + np.clip(CS.out.vEgo + 5.0, 0.0, 100.0)] + pcm_speed = float(np.interp(gas - brake, pcm_speed_BP, pcm_speed_V)) + pcm_accel = int(np.clip((accel / 1.44) / max_accel, 0.0, 1.0) * self.params.NIDEC_GAS_MAX) + + if not self.CP.openpilotLongitudinalControl: + if self.frame % 2 == 0 and self.CP.carFingerprint not in HONDA_BOSCH_RADARLESS | HONDA_BOSCH_CANFD: + can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, self.CAN)) + # If using stock ACC, spam cancel command to kill gas when OP disengages. + if pcm_cancel_cmd: + can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, CruiseButtons.CANCEL, self.CP.carFingerprint)) + elif CC.cruiseControl.resume: + can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, CruiseButtons.RES_ACCEL, self.CP.carFingerprint)) + + else: + # Send gas and brake commands. + if self.frame % 2 == 0: + ts = self.frame * DT_CTRL + + if self.CP.carFingerprint in HONDA_BOSCH: + self.accel = float(np.clip(accel, self.params.BOSCH_ACCEL_MIN, self.params.BOSCH_ACCEL_MAX)) + self.gas = float(np.interp(accel, self.params.BOSCH_GAS_LOOKUP_BP, self.params.BOSCH_GAS_LOOKUP_V)) + + stopping = actuators.longControlState == LongCtrlState.stopping + self.stopping_counter = self.stopping_counter + 1 if stopping else 0 + can_sends.extend(hondacan.create_acc_commands(self.packer, self.CAN, CC.enabled, CC.longActive, self.accel, self.gas, + self.stopping_counter, self.CP.carFingerprint)) + else: + apply_brake = np.clip(self.brake_last - wind_brake, 0.0, 1.0) + apply_brake = int(np.clip(apply_brake * self.params.NIDEC_BRAKE_MAX, 0, self.params.NIDEC_BRAKE_MAX - 1)) + pump_on, self.last_pump_ts = brake_pump_hysteresis(apply_brake, self.apply_brake_last, self.last_pump_ts, ts) + + pcm_override = True + can_sends.append(hondacan.create_brake_command(self.packer, self.CAN, apply_brake, pump_on, + pcm_override, pcm_cancel_cmd, alert_fcw, + self.CP.carFingerprint, CS.stock_brake)) + self.apply_brake_last = apply_brake + self.brake = apply_brake / self.params.NIDEC_BRAKE_MAX + + # Send dashboard UI commands. + if self.frame % 10 == 0: + if self.CP.openpilotLongitudinalControl: + # On Nidec, this also controls longitudinal positive acceleration + can_sends.append(hondacan.create_acc_hud(self.packer, self.CAN.pt, self.CP, CC.enabled, pcm_speed, pcm_accel, + hud_control, hud_v_cruise, CS.is_metric, CS.acc_hud)) + + steering_available = CS.out.cruiseState.available and CS.out.vEgo > self.CP.minSteerSpeed + reduced_steering = CS.out.steeringPressed + can_sends.extend(hondacan.create_lkas_hud(self.packer, self.CAN.lkas, self.CP, hud_control, CC.latActive, + steering_available, reduced_steering, alert_steer_required, CS.lkas_hud)) + + if self.CP.openpilotLongitudinalControl: + # TODO: combining with create_acc_hud block above will change message order and will need replay logs regenerated + if self.CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS): + can_sends.append(hondacan.create_radar_hud(self.packer, self.CAN.pt)) + if self.CP.carFingerprint == CAR.HONDA_CIVIC_BOSCH: + can_sends.append(hondacan.create_legacy_brake_command(self.packer, self.CAN.pt)) + if self.CP.carFingerprint not in HONDA_BOSCH: + self.speed = pcm_speed + self.gas = pcm_accel / self.params.NIDEC_GAS_MAX + + new_actuators = actuators.as_builder() + new_actuators.speed = self.speed + new_actuators.accel = self.accel + new_actuators.gas = self.gas + new_actuators.brake = self.brake + new_actuators.torque = self.last_torque + new_actuators.torqueOutputCan = apply_torque + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/honda/carstate.py b/opendbc_repo/opendbc/car/honda/carstate.py new file mode 100644 index 0000000000..334491968f --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/carstate.py @@ -0,0 +1,232 @@ +import numpy as np +from collections import defaultdict + +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.honda.hondacan import CanBus +from opendbc.car.honda.values import CAR, DBC, STEER_THRESHOLD, HONDA_BOSCH, HONDA_BOSCH_ALT_RADAR, HONDA_BOSCH_CANFD, \ + HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_RADARLESS, \ + HondaFlags, CruiseButtons, CruiseSettings, GearShifter, CarControllerParams +from opendbc.car.interfaces import CarStateBase + +TransmissionType = structs.CarParams.TransmissionType +ButtonType = structs.CarState.ButtonEvent.Type + +BUTTONS_DICT = {CruiseButtons.RES_ACCEL: ButtonType.accelCruise, CruiseButtons.DECEL_SET: ButtonType.decelCruise, + CruiseButtons.MAIN: ButtonType.mainCruise, CruiseButtons.CANCEL: ButtonType.cancel} +SETTINGS_BUTTONS_DICT = {CruiseSettings.DISTANCE: ButtonType.gapAdjustCruise, CruiseSettings.LKAS: ButtonType.lkas} + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + + if CP.transmissionType != TransmissionType.manual: + self.gearbox_msg = "GEARBOX_AUTO" + if CP.transmissionType == TransmissionType.cvt: + self.gearbox_msg = "GEARBOX_CVT" + self.shifter_values = can_define.dv[self.gearbox_msg]["GEAR_SHIFTER"] + + self.car_state_scm_msg = "SCM_FEEDBACK" + if CP.carFingerprint in HONDA_NIDEC_ALT_SCM_MESSAGES: + self.car_state_scm_msg = "SCM_BUTTONS" + + self.brake_error_msg = "HYBRID_BRAKE_ERROR" if CP.flags & HondaFlags.HYBRID else "STANDSTILL" + + self.steer_status_values = defaultdict(lambda: "UNKNOWN", can_define.dv["STEER_STATUS"]["STEER_STATUS"]) + + self.brake_switch_prev = False + self.brake_switch_active = False + self.low_speed_alert = False + + self.dynamic_v_cruise_units = self.CP.carFingerprint in (HONDA_BOSCH_RADARLESS | HONDA_BOSCH_ALT_RADAR | HONDA_BOSCH_CANFD) + self.cruise_setting = 0 + self.v_cruise_pcm_prev = 0 + + # When available we use cp.vl["CAR_SPEED"]["ROUGH_CAR_SPEED_2"] to populate vEgoCluster + # However, on cars without a digital speedometer this is not always present (HRV, FIT, CRV 2016, ILX and RDX) + self.dash_speed_seen = False + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + if self.CP.enableBsm: + cp_body = can_parsers[Bus.body] + + ret = structs.CarState() + + # car params + v_weight_v = [0., 1.] # don't trust smooth speed at low values to avoid premature zero snapping + v_weight_bp = [1., 6.] # smooth blending, below ~0.6m/s the smooth speed snaps to zero + + # update prevs, update must run once per loop + prev_cruise_buttons = self.cruise_buttons + prev_cruise_setting = self.cruise_setting + self.cruise_setting = cp.vl["SCM_BUTTONS"]["CRUISE_SETTING"] + self.cruise_buttons = cp.vl["SCM_BUTTONS"]["CRUISE_BUTTONS"] + + # used for car hud message + self.is_metric = not cp.vl["CAR_SPEED"]["IMPERIAL_UNIT"] + self.v_cruise_factor = CV.MPH_TO_MS if self.dynamic_v_cruise_units and not self.is_metric else CV.KPH_TO_MS + + # ******************* parse out can ******************* + + # blend in transmission speed at low speed, since it has more low speed accuracy + # STANDSTILL->WHEELS_MOVING bit can be noisy around zero, so use XMISSION_SPEED + v_wheel = sum([cp.vl["WHEEL_SPEEDS"][f"WHEEL_SPEED_{s}"] for s in ("FL", "FR", "RL", "RR")]) / 4.0 * CV.KPH_TO_MS + v_weight = float(np.interp(v_wheel, v_weight_bp, v_weight_v)) + ret.vEgoRaw = (1. - v_weight) * cp.vl["ENGINE_DATA"]["XMISSION_SPEED"] * CV.KPH_TO_MS * self.CP.wheelSpeedFactor + v_weight * v_wheel + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.standstill = cp.vl["ENGINE_DATA"]["XMISSION_SPEED"] < 1e-5 + + # doorOpen is true if we can find any door open, but signal locations vary, and we may only see the driver's door + # TODO: Test the eight Nidec cars without SCM signals for driver's door state, may be able to consolidate further + if self.CP.flags & HondaFlags.HAS_ALL_DOOR_STATES: + ret.doorOpen = any([cp.vl["DOORS_STATUS"]["DOOR_OPEN_FL"], cp.vl["DOORS_STATUS"]["DOOR_OPEN_FR"], + cp.vl["DOORS_STATUS"]["DOOR_OPEN_RL"], cp.vl["DOORS_STATUS"]["DOOR_OPEN_RR"]]) + elif "DRIVERS_DOOR_OPEN" in cp.vl["SCM_BUTTONS"]: + ret.doorOpen = bool(cp.vl["SCM_BUTTONS"]["DRIVERS_DOOR_OPEN"]) + else: + ret.doorOpen = bool(cp.vl["SCM_FEEDBACK"]["DRIVERS_DOOR_OPEN"]) + + ret.seatbeltUnlatched = bool(cp.vl["SEATBELT_STATUS"]["SEATBELT_DRIVER_LAMP"] or not cp.vl["SEATBELT_STATUS"]["SEATBELT_DRIVER_LATCHED"]) + + steer_status = self.steer_status_values[cp.vl["STEER_STATUS"]["STEER_STATUS"]] + ret.steerFaultPermanent = steer_status not in ("NORMAL", "NO_TORQUE_ALERT_1", "NO_TORQUE_ALERT_2", "LOW_SPEED_LOCKOUT", "TMP_FAULT") + if self.CP.carFingerprint in HONDA_BOSCH_ALT_RADAR: + # TODO: See if this logic works for all other Honda + min_steer_speed = max(CarControllerParams.STEER_GLOBAL_MIN_SPEED, self.CP.minSteerSpeed) + expected_low_speed_lockout = steer_status == "LOW_SPEED_LOCKOUT" and ret.vEgo < min_steer_speed + ret.steerFaultTemporary = steer_status != "NORMAL" and not expected_low_speed_lockout + else: + # LOW_SPEED_LOCKOUT is not worth a warning + # NO_TORQUE_ALERT_2 can be caused by bump or steering nudge from driver + # FIXME: the stock camera stops steering on NO_TORQUE_ALERT_1 + ret.steerFaultTemporary = steer_status not in ("NORMAL", "LOW_SPEED_LOCKOUT", "NO_TORQUE_ALERT_2") + + # All Honda EPS cut off slightly above standstill, some much higher + # Don't alert in the near-standstill range, but alert for per-vehicle configured minimums above that + if CarControllerParams.STEER_GLOBAL_MIN_SPEED < ret.vEgo < (self.CP.minSteerSpeed + 0.5): + self.low_speed_alert = True + elif ret.vEgo > (self.CP.minSteerSpeed + 1.): + # TODO: better handle delayed steering enablement on ALT_RADAR cars + self.low_speed_alert = False + ret.lowSpeedAlert = self.low_speed_alert + + if self.CP.carFingerprint in HONDA_BOSCH_RADARLESS: + ret.accFaulted = bool(cp.vl["CRUISE_FAULT_STATUS"]["CRUISE_FAULT"]) + else: + if self.CP.openpilotLongitudinalControl: + ret.accFaulted = bool(cp.vl[self.brake_error_msg]["BRAKE_ERROR_1"] or cp.vl[self.brake_error_msg]["BRAKE_ERROR_2"]) + + # Log non-critical stock ACC/LKAS faults if Nidec (camera) + if self.CP.carFingerprint not in HONDA_BOSCH: + ret.carFaultedNonCritical = bool(cp_cam.vl["ACC_HUD"]["ACC_PROBLEM"] or cp_cam.vl["LKAS_HUD"]["LKAS_PROBLEM"]) + + ret.espDisabled = cp.vl["VSA_STATUS"]["ESP_DISABLED"] != 0 + + self.dash_speed_seen = self.dash_speed_seen or cp.vl["CAR_SPEED"]["ROUGH_CAR_SPEED_2"] > 1e-3 + if self.dash_speed_seen: + conversion = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS + ret.vEgoCluster = cp.vl["CAR_SPEED"]["ROUGH_CAR_SPEED_2"] * conversion + + ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEER_ANGLE"] + ret.steeringRateDeg = cp.vl["STEERING_SENSORS"]["STEER_ANGLE_RATE"] + + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_stalk( + 250, cp.vl["SCM_FEEDBACK"]["LEFT_BLINKER"], cp.vl["SCM_FEEDBACK"]["RIGHT_BLINKER"]) + ret.brakeHoldActive = cp.vl["VSA_STATUS"]["BRAKE_HOLD_ACTIVE"] == 1 + ret.parkingBrake = bool(cp.vl[self.car_state_scm_msg]["PARKING_BRAKE_ON"]) + + if self.CP.transmissionType == TransmissionType.manual: + ret.gearShifter = GearShifter.reverse if bool(cp.vl["SCM_FEEDBACK"]["REVERSE_LIGHT"]) else GearShifter.drive + else: + gear_position = self.shifter_values.get(cp.vl[self.gearbox_msg]["GEAR_SHIFTER"], None) + ret.gearShifter = self.parse_gear_shifter(gear_position) + + ret.gasPressed = cp.vl["POWERTRAIN_DATA"]["PEDAL_GAS"] > 1e-5 + + ret.steeringTorque = cp.vl["STEER_STATUS"]["STEER_TORQUE_SENSOR"] + ret.steeringPressed = abs(ret.steeringTorque) > STEER_THRESHOLD.get(self.CP.carFingerprint, 1200) + + if self.CP.carFingerprint in HONDA_BOSCH: + # The PCM always manages its own cruise control state, but doesn't publish it + if self.CP.carFingerprint in HONDA_BOSCH_RADARLESS: + ret.cruiseState.nonAdaptive = cp_cam.vl["ACC_HUD"]["CRUISE_CONTROL_LABEL"] != 0 + + if not self.CP.openpilotLongitudinalControl: + # ACC_HUD is on camera bus on radarless cars + acc_hud = cp_cam.vl["ACC_HUD"] if self.CP.carFingerprint in HONDA_BOSCH_RADARLESS else cp.vl["ACC_HUD"] + ret.cruiseState.nonAdaptive = acc_hud["CRUISE_CONTROL_LABEL"] != 0 + ret.cruiseState.standstill = acc_hud["CRUISE_SPEED"] == 252. + + # On set, cruise set speed pulses between 254~255 and the set speed prev is set to avoid this. + ret.cruiseState.speed = self.v_cruise_pcm_prev if acc_hud["CRUISE_SPEED"] > 160.0 else acc_hud["CRUISE_SPEED"] * self.v_cruise_factor + self.v_cruise_pcm_prev = ret.cruiseState.speed + else: + ret.cruiseState.speed = cp.vl["CRUISE"]["CRUISE_SPEED_PCM"] * CV.KPH_TO_MS + + if self.CP.flags & HondaFlags.BOSCH_ALT_BRAKE: + ret.brakePressed = cp.vl["BRAKE_MODULE"]["BRAKE_PRESSED"] != 0 + else: + # brake switch has shown some single time step noise, so only considered when + # switch is on for at least 2 consecutive CAN samples + # brake switch rises earlier than brake pressed but is never 1 when in park + brake_switch_vals = cp.vl_all["POWERTRAIN_DATA"]["BRAKE_SWITCH"] + if len(brake_switch_vals): + brake_switch = cp.vl["POWERTRAIN_DATA"]["BRAKE_SWITCH"] != 0 + if len(brake_switch_vals) > 1: + self.brake_switch_prev = brake_switch_vals[-2] != 0 + self.brake_switch_active = brake_switch and self.brake_switch_prev + self.brake_switch_prev = brake_switch + ret.brakePressed = (cp.vl["POWERTRAIN_DATA"]["BRAKE_PRESSED"] != 0) or self.brake_switch_active + + ret.brake = cp.vl["VSA_STATUS"]["USER_BRAKE"] + ret.cruiseState.enabled = cp.vl["POWERTRAIN_DATA"]["ACC_STATUS"] != 0 + ret.cruiseState.available = bool(cp.vl[self.car_state_scm_msg]["MAIN_ON"]) + + # Gets rid of Pedal Grinding noise when brake is pressed at slow speeds for some models + if self.CP.carFingerprint in (CAR.HONDA_PILOT, CAR.HONDA_RIDGELINE): + if ret.brake > 0.1: + ret.brakePressed = True + + if self.CP.carFingerprint in HONDA_BOSCH: + # TODO: find the radarless AEB_STATUS bit and make sure ACCEL_COMMAND is correct to enable AEB alerts + if self.CP.carFingerprint not in HONDA_BOSCH_RADARLESS: + ret.stockAeb = (not self.CP.openpilotLongitudinalControl) and bool(cp.vl["ACC_CONTROL"]["AEB_STATUS"] and cp.vl["ACC_CONTROL"]["ACCEL_COMMAND"] < -1e-5) + else: + ret.stockAeb = bool(cp_cam.vl["BRAKE_COMMAND"]["AEB_REQ_1"] and cp_cam.vl["BRAKE_COMMAND"]["COMPUTER_BRAKE"] > 1e-5) + + self.acc_hud = False + self.lkas_hud = False + if self.CP.carFingerprint not in HONDA_BOSCH: + ret.stockFcw = cp_cam.vl["BRAKE_COMMAND"]["FCW"] != 0 + self.acc_hud = cp_cam.vl["ACC_HUD"] + self.stock_brake = cp_cam.vl["BRAKE_COMMAND"] + if self.CP.carFingerprint in HONDA_BOSCH_RADARLESS: + self.lkas_hud = cp_cam.vl["LKAS_HUD"] + + if self.CP.enableBsm: + # BSM messages are on B-CAN, requires a panda forwarding B-CAN messages to CAN 0 + # more info here: https://github.com/commaai/openpilot/pull/1867 + ret.leftBlindspot = cp_body.vl["BSM_STATUS_LEFT"]["BSM_ALERT"] == 1 + ret.rightBlindspot = cp_body.vl["BSM_STATUS_RIGHT"]["BSM_ALERT"] == 1 + + ret.buttonEvents = [ + *create_button_events(self.cruise_buttons, prev_cruise_buttons, BUTTONS_DICT), + *create_button_events(self.cruise_setting, prev_cruise_setting, SETTINGS_BUTTONS_DICT), + ] + + return ret + + def get_can_parsers(self, CP): + parsers = { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).pt), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).camera), + } + if CP.enableBsm: + parsers[Bus.body] = CANParser(DBC[CP.carFingerprint][Bus.body], [], CanBus(CP).radar) + + return parsers diff --git a/opendbc_repo/opendbc/car/honda/fingerprints.py b/opendbc_repo/opendbc/car/honda/fingerprints.py new file mode 100644 index 0000000000..8f84811926 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/fingerprints.py @@ -0,0 +1,1062 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.honda.values import CAR + +Ecu = CarParams.Ecu + +# Modified FW can be identified by the second dash being replaced by a comma +# For example: `b'39990-TVA,A150\x00\x00'` +# +# TODO: vsa is "essential" for fpv2 but doesn't appear on some CAR.FREED models + + +FW_VERSIONS = { + CAR.HONDA_NBOX_2G: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TTA-J030\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TTA-J040\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TTA-N930\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TTA-J070\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'38897-TTA-J010\x00\x00', + ] + }, + CAR.HONDA_ACCORD: { + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TVC-A910\x00\x00', + b'54008-TWA-A910\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-6A7-A220\x00\x00', + b'28101-6A7-A230\x00\x00', + b'28101-6A7-A320\x00\x00', + b'28101-6A7-A330\x00\x00', + b'28101-6A7-A410\x00\x00', + b'28101-6A7-A510\x00\x00', + b'28101-6A7-A610\x00\x00', + b'28101-6A7-A710\x00\x00', + b'28101-6A9-H140\x00\x00', + b'28101-6A9-H420\x00\x00', + b'28102-6B8-A560\x00\x00', + b'28102-6B8-A570\x00\x00', + b'28102-6B8-A700\x00\x00', + b'28102-6B8-A800\x00\x00', + b'28102-6B8-C560\x00\x00', + b'28102-6B8-C570\x00\x00', + b'28102-6B8-M520\x00\x00', + b'28102-6B8-R700\x00\x00', + ], + (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ + b'46114-TVA-A050\x00\x00', + b'46114-TVA-A060\x00\x00', + b'46114-TVA-A080\x00\x00', + b'46114-TVA-A120\x00\x00', + b'46114-TVA-A320\x00\x00', + b'46114-TVA-A410\x00\x00', + b'46114-TVE-H550\x00\x00', + b'46114-TVE-H560\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TVA-B040\x00\x00', + b'57114-TVA-B050\x00\x00', + b'57114-TVA-B060\x00\x00', + b'57114-TVA-B530\x00\x00', + b'57114-TVA-C040\x00\x00', + b'57114-TVA-C050\x00\x00', + b'57114-TVA-C060\x00\x00', + b'57114-TVA-C530\x00\x00', + b'57114-TVA-D520\x00\x00', + b'57114-TVA-E520\x00\x00', + b'57114-TVE-H250\x00\x00', + b'57114-TWA-A040\x00\x00', + b'57114-TWA-A050\x00\x00', + b'57114-TWA-A530\x00\x00', + b'57114-TWA-B520\x00\x00', + b'57114-TWA-C510\x00\x00', + b'57114-TWB-H030\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TBX-H120\x00\x00', + b'39990-TVA-A140\x00\x00', + b'39990-TVA-A150\x00\x00', + b'39990-TVA-A160\x00\x00', + b'39990-TVA-A340\x00\x00', + b'39990-TVA-X030\x00\x00', + b'39990-TVA-X040\x00\x00', + b'39990-TVE-H130\x00\x00', + b'39990-TWB-H120\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TBX-H230\x00\x00', + b'77959-TVA-A460\x00\x00', + b'77959-TVA-F330\x00\x00', + b'77959-TVA-H230\x00\x00', + b'77959-TVA-L420\x00\x00', + b'77959-TVA-X330\x00\x00', + b'77959-TWA-A440\x00\x00', + b'77959-TWA-L420\x00\x00', + b'77959-TWB-H220\x00\x00', + ], + (Ecu.hud, 0x18da61f1, None): [ + b'78209-TVA-A010\x00\x00', + b'78209-TVA-A110\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TBX-H140\x00\x00', + b'36802-TVA-A150\x00\x00', + b'36802-TVA-A160\x00\x00', + b'36802-TVA-A170\x00\x00', + b'36802-TVA-A180\x00\x00', + b'36802-TVA-A330\x00\x00', + b'36802-TVC-A330\x00\x00', + b'36802-TVE-H070\x00\x00', + b'36802-TWA-A070\x00\x00', + b'36802-TWA-A080\x00\x00', + b'36802-TWA-A210\x00\x00', + b'36802-TWA-A330\x00\x00', + b'36802-TWB-H060\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TBX-H130\x00\x00', + b'36161-TVA-A060\x00\x00', + b'36161-TVA-A330\x00\x00', + b'36161-TVC-A330\x00\x00', + b'36161-TVE-H050\x00\x00', + b'36161-TWA-A070\x00\x00', + b'36161-TWA-A330\x00\x00', + b'36161-TWB-H040\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TVA-A010\x00\x00', + b'38897-TVA-A020\x00\x00', + b'38897-TVA-A230\x00\x00', + b'38897-TVA-A240\x00\x00', + b'38897-TWA-A120\x00\x00', + b'38897-TWD-J020\x00\x00', + ], + }, + CAR.HONDA_CIVIC: { + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-5CG-A040\x00\x00', + b'28101-5CG-A050\x00\x00', + b'28101-5CG-A070\x00\x00', + b'28101-5CG-A080\x00\x00', + b'28101-5CG-A320\x00\x00', + b'28101-5CG-A810\x00\x00', + b'28101-5CG-A820\x00\x00', + b'28101-5DJ-A040\x00\x00', + b'28101-5DJ-A060\x00\x00', + b'28101-5DJ-A510\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TBA-A540\x00\x00', + b'57114-TBA-A550\x00\x00', + b'57114-TBA-A560\x00\x00', + b'57114-TBA-A570\x00\x00', + b'57114-TEA-Q220\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TBA-A030\x00\x00', + b'39990-TBG-A030\x00\x00', + b'39990-TEA-T020\x00\x00', + b'39990-TEG-A010\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TBA-A030\x00\x00', + b'77959-TBA-A040\x00\x00', + b'77959-TBG-A020\x00\x00', + b'77959-TBG-A030\x00\x00', + b'77959-TEA-Q820\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-TBA-A020\x00\x00', + b'36161-TBA-A030\x00\x00', + b'36161-TBA-A040\x00\x00', + b'36161-TBC-A020\x00\x00', + b'36161-TBC-A030\x00\x00', + b'36161-TED-Q320\x00\x00', + b'36161-TEG-A010\x00\x00', + b'36161-TEG-A020\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TBA-A010\x00\x00', + b'38897-TBA-A020\x00\x00', + ], + }, + CAR.HONDA_CIVIC_BOSCH: { + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-5CG-A920\x00\x00', + b'28101-5CG-AB10\x00\x00', + b'28101-5CG-C110\x00\x00', + b'28101-5CG-C220\x00\x00', + b'28101-5CG-C320\x00\x00', + b'28101-5CG-G020\x00\x00', + b'28101-5CG-L020\x00\x00', + b'28101-5CK-A130\x00\x00', + b'28101-5CK-A140\x00\x00', + b'28101-5CK-A150\x00\x00', + b'28101-5CK-C130\x00\x00', + b'28101-5CK-C140\x00\x00', + b'28101-5CK-C150\x00\x00', + b'28101-5CK-G210\x00\x00', + b'28101-5CK-J710\x00\x00', + b'28101-5CK-Q110\x00\x00', + b'28101-5CK-Q610\x00\x00', + b'28101-5DJ-A610\x00\x00', + b'28101-5DJ-A710\x00\x00', + b'28101-5DV-E330\x00\x00', + b'28101-5DV-E610\x00\x00', + b'28101-5DV-E820\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TBG-A330\x00\x00', + b'57114-TBG-A340\x00\x00', + b'57114-TBG-A350\x00\x00', + b'57114-TGG-A340\x00\x00', + b'57114-TGG-C320\x00\x00', + b'57114-TGG-G320\x00\x00', + b'57114-TGG-L320\x00\x00', + b'57114-TGG-L330\x00\x00', + b'57114-TGH-L130\x00\x00', + b'57114-TGJ-Q330\x00\x00', + b'57114-TGK-T320\x00\x00', + b'57114-TGL-G330\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TBA-C020\x00\x00', + b'39990-TBA-C120\x00\x00', + b'39990-TEA-T330\x00\x00', + b'39990-TEA-T820\x00\x00', + b'39990-TEZ-T020\x00\x00', + b'39990-TGG-A020\x00\x00', + b'39990-TGG-A120\x00\x00', + b'39990-TGG-J510\x00\x00', + b'39990-TGH-J530\x00\x00', + b'39990-TGL-E130\x00\x00', + b'39990-TGN-E120\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TBA-A060\x00\x00', + b'77959-TBG-A050\x00\x00', + b'77959-TEA-G020\x00\x00', + b'77959-TGG-A020\x00\x00', + b'77959-TGG-A030\x00\x00', + b'77959-TGG-E010\x00\x00', + b'77959-TGG-G010\x00\x00', + b'77959-TGG-G110\x00\x00', + b'77959-TGG-J320\x00\x00', + b'77959-TGG-Q810\x00\x00', + b'77959-TGG-Z820\x00\x00', + b'77959-TGH-J110\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TBA-A150\x00\x00', + b'36802-TBA-A160\x00\x00', + b'36802-TFJ-G060\x00\x00', + b'36802-TGG-A050\x00\x00', + b'36802-TGG-A060\x00\x00', + b'36802-TGG-A070\x00\x00', + b'36802-TGG-A130\x00\x00', + b'36802-TGG-G040\x00\x00', + b'36802-TGG-G130\x00\x00', + b'36802-TGH-A140\x00\x00', + b'36802-TGK-Q030\x00\x00', + b'36802-TGK-Q120\x00\x00', + b'36802-TGL-G040\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TBA-A130\x00\x00', + b'36161-TBA-A140\x00\x00', + b'36161-TFJ-G070\x00\x00', + b'36161-TGG-A060\x00\x00', + b'36161-TGG-A080\x00\x00', + b'36161-TGG-A120\x00\x00', + b'36161-TGG-G050\x00\x00', + b'36161-TGG-G070\x00\x00', + b'36161-TGG-G130\x00\x00', + b'36161-TGG-G140\x00\x00', + b'36161-TGH-A140\x00\x00', + b'36161-TGK-Q040\x00\x00', + b'36161-TGK-Q120\x00\x00', + b'36161-TGL-G050\x00\x00', + b'36161-TGL-G070\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TBA-A020\x00\x00', + b'38897-TBA-A110\x00\x00', + b'38897-TGH-A010\x00\x00', + ], + (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ + b'39494-TGL-G030\x00\x00', + ], + }, + CAR.HONDA_CIVIC_BOSCH_DIESEL: { + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-59Y-G220\x00\x00', + b'28101-59Y-G620\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TGN-E320\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TFK-G020\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TFK-G210\x00\x00', + b'77959-TGN-G220\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TFK-G130\x00\x00', + b'36802-TGN-G130\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TGN-E010\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TFK-G130\x00\x00', + b'36161-TGN-G130\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TBA-A020\x00\x00', + ], + }, + CAR.HONDA_CRV: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-T1W-A230\x00\x00', + b'57114-T1W-A240\x00\x00', + b'57114-TFF-A940\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T0A-A230\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T1W-A830\x00\x00', + b'36161-T1W-C830\x00\x00', + b'36161-T1X-A830\x00\x00', + ], + }, + CAR.HONDA_CRV_5G: { + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-5RG-A020\x00\x00', + b'28101-5RG-A030\x00\x00', + b'28101-5RG-A040\x00\x00', + b'28101-5RG-A120\x00\x00', + b'28101-5RG-A220\x00\x00', + b'28101-5RH-A020\x00\x00', + b'28101-5RH-A030\x00\x00', + b'28101-5RH-A040\x00\x00', + b'28101-5RH-A120\x00\x00', + b'28101-5RH-A220\x00\x00', + b'28101-5RL-Q010\x00\x00', + b'28101-5RM-F010\x00\x00', + b'28101-5RM-K010\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TLA-A040\x00\x00', + b'57114-TLA-A050\x00\x00', + b'57114-TLA-A060\x00\x00', + b'57114-TLB-A830\x00\x00', + b'57114-TMC-Z040\x00\x00', + b'57114-TMC-Z050\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TLA-A040\x00\x00', + b'39990-TLA-A110\x00\x00', + b'39990-TLA-A220\x00\x00', + b'39990-TME-T030\x00\x00', + b'39990-TME-T120\x00\x00', + b'39990-TMT-T010\x00\x00', + ], + (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ + b'46114-TLA-A040\x00\x00', + b'46114-TLA-A050\x00\x00', + b'46114-TLA-A930\x00\x00', + b'46114-TMC-U020\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TLA-A010\x00\x00', + b'38897-TLA-A110\x00\x00', + b'38897-TNY-G010\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TLA-A040\x00\x00', + b'36802-TLA-A050\x00\x00', + b'36802-TLA-A060\x00\x00', + b'36802-TLA-A070\x00\x00', + b'36802-TMC-Q040\x00\x00', + b'36802-TMC-Q070\x00\x00', + b'36802-TNY-A030\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TLA-A060\x00\x00', + b'36161-TLA-A070\x00\x00', + b'36161-TLA-A080\x00\x00', + b'36161-TMC-Q020\x00\x00', + b'36161-TMC-Q030\x00\x00', + b'36161-TMC-Q040\x00\x00', + b'36161-TNY-A020\x00\x00', + b'36161-TNY-A030\x00\x00', + b'36161-TNY-A040\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TLA-A240\x00\x00', + b'77959-TLA-A250\x00\x00', + b'77959-TLA-A320\x00\x00', + b'77959-TLA-A410\x00\x00', + b'77959-TLA-A420\x00\x00', + b'77959-TLA-Q040\x00\x00', + b'77959-TLA-Z040\x00\x00', + b'77959-TMM-F040\x00\x00', + ], + }, + CAR.HONDA_CRV_EU: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-T1V-G920\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T1V-G520\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-T1V-G010\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-5LH-E120\x00\x00', + b'28103-5LH-E100\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T1G-G940\x00\x00', + ], + }, + CAR.HONDA_CRV_HYBRID: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TMB-H030\x00\x00', + b'57114-TPA-G020\x00\x00', + b'57114-TPG-A020\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TMA-H020\x00\x00', + b'39990-TPA-G030\x00\x00', + b'39990-TPG-A020\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TMA-H110\x00\x00', + b'38897-TPG-A110\x00\x00', + b'38897-TPG-A210\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TMB-H510\x00\x00', + b'54008-TMB-H610\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TMB-H040\x00\x00', + b'36161-TPA-E050\x00\x00', + b'36161-TPA-E070\x00\x00', + b'36161-TPG-A030\x00\x00', + b'36161-TPG-A040\x00\x00', + b'36161-TPG-A050\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TMB-H040\x00\x00', + b'36802-TPA-E040\x00\x00', + b'36802-TPG-A020\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TLA-C320\x00\x00', + b'77959-TLA-C410\x00\x00', + b'77959-TLA-C420\x00\x00', + b'77959-TLA-G220\x00\x00', + b'77959-TLA-H240\x00\x00', + ], + }, + CAR.HONDA_FIT: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-T5R-L020\x00\x00', + b'57114-T5R-L220\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-T5R-C020\x00\x00', + b'39990-T5R-C030\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-T5A-J010\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T5R-A040\x00\x00', + b'36161-T5R-A240\x00\x00', + b'36161-T5R-A520\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T5R-A230\x00\x00', + ], + }, + CAR.HONDA_FREED: { + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TDK-J010\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TDK-J050\x00\x00', + b'39990-TDK-N020\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TDK-J120\x00\x00', + b'57114-TDK-J330\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-TDK-J070\x00\x00', + b'36161-TDK-J080\x00\x00', + b'36161-TDK-J530\x00\x00', + ], + }, + CAR.ACURA_MDX_4G_MMR: { + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'8S102-TYA-A020\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'8S302-TYA-A020\x00\x00', + ], + }, + CAR.HONDA_ODYSSEY: { + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-THR-A010\x00\x00', + b'38897-THR-A020\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-THR-A020\x00\x00', + b'39990-THR-A030\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-THR-A010\x00\x00', + b'77959-THR-A110\x00\x00', + b'77959-THR-X010\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-THR-A020\x00\x00', + b'36161-THR-A030\x00\x00', + b'36161-THR-A110\x00\x00', + b'36161-THR-A720\x00\x00', + b'36161-THR-A730\x00\x00', + b'36161-THR-A810\x00\x00', + b'36161-THR-A910\x00\x00', + b'36161-THR-C010\x00\x00', + b'36161-THR-D110\x00\x00', + b'36161-THR-K020\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-5NZ-A110\x00\x00', + b'28101-5NZ-A310\x00\x00', + b'28101-5NZ-C310\x00\x00', + b'28102-5MX-A001\x00\x00', + b'28102-5MX-A600\x00\x00', + b'28102-5MX-A610\x00\x00', + b'28102-5MX-A700\x00\x00', + b'28102-5MX-A710\x00\x00', + b'28102-5MX-A900\x00\x00', + b'28102-5MX-A910\x00\x00', + b'28102-5MX-C001\x00\x00', + b'28102-5MX-C610\x00\x00', + b'28102-5MX-C910\x00\x00', + b'28102-5MX-D001\x00\x00', + b'28102-5MX-D710\x00\x00', + b'28102-5MX-K610\x00\x00', + b'28103-5NZ-A100\x00\x00', + b'28103-5NZ-A300\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-THR-A040\x00\x00', + b'57114-THR-A110\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-THR-A020\x00\x00', + ], + }, + CAR.HONDA_ODYSSEY_5G_MMR: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-THR-A240\x00\x00', + b'57114-THR-A520\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-THR-A220\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-THR-A220\x00\x00', + b'36161-THR-A230\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-THR-A310\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28102-5MX-A100\x00\x00', + b'28102-5MX-A200\x00\x00', + b'28102-5MX-A410\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-THR-A220\x00\x00', + b'77959-THR-A230\x00\x00', + b'77959-THR-A320\x00\x00', + ], + (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ + b'46114-THR-A530\x00\x00', + b'46114-THR-A540\x00\x00', + b'46114-THR-A720\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-THR-A130\x00\x00', + b'38897-THR-A320\x00\x00', + b'38897-THR-A410\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-THR-A050\x00\x00', + b'39990-THR-A110\x00\x00', + ], + }, + CAR.HONDA_PILOT: { + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TG7-A520\x00\x00', + b'54008-TG7-A530\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-5EY-A040\x00\x00', + b'28101-5EY-A050\x00\x00', + b'28101-5EY-A100\x00\x00', + b'28101-5EY-A330\x00\x00', + b'28101-5EY-A430\x00\x00', + b'28101-5EY-A500\x00\x00', + b'28101-5EZ-A050\x00\x00', + b'28101-5EZ-A060\x00\x00', + b'28101-5EZ-A100\x00\x00', + b'28101-5EZ-A210\x00\x00', + b'28101-5EZ-A330\x00\x00', + b'28101-5EZ-A430\x00\x00', + b'28101-5EZ-A500\x00\x00', + b'28101-5EZ-A600\x00\x00', + b'28101-5EZ-A700\x00\x00', + b'28103-5EY-A110\x00\x00', + b'28103-5EZ-A010\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TG7-A030\x00\x00', + b'38897-TG7-A040\x00\x00', + b'38897-TG7-A110\x00\x00', + b'38897-TG7-A210\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TG7-A030\x00\x00', + b'39990-TG7-A040\x00\x00', + b'39990-TG7-A060\x00\x00', + b'39990-TG7-A070\x00\x00', + b'39990-TGS-A230\x00\x00', + b'39990-TGS-A320\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-TG7-A310\x00\x00', + b'36161-TG7-A520\x00\x00', + b'36161-TG7-A630\x00\x00', + b'36161-TG7-A720\x00\x00', + b'36161-TG7-A820\x00\x00', + b'36161-TG7-A930\x00\x00', + b'36161-TG7-C520\x00\x00', + b'36161-TG7-D520\x00\x00', + b'36161-TG7-D630\x00\x00', + b'36161-TG7-Y630\x00\x00', + b'36161-TG8-A410\x00\x00', + b'36161-TG8-A520\x00\x00', + b'36161-TG8-A630\x00\x00', + b'36161-TG8-A720\x00\x00', + b'36161-TG8-A830\x00\x00', + b'36161-TGS-A030\x00\x00', + b'36161-TGS-A130\x00\x00', + b'36161-TGS-A220\x00\x00', + b'36161-TGS-A320\x00\x00', + b'36161-TGT-A030\x00\x00', + b'36161-TGT-A130\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TG7-A020\x00\x00', + b'77959-TG7-A110\x00\x00', + b'77959-TG7-A210\x00\x00', + b'77959-TG7-Y210\x00\x00', + b'77959-TGS-A010\x00\x00', + b'77959-TGS-A110\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TG7-A130\x00\x00', + b'57114-TG7-A140\x00\x00', + b'57114-TG7-A230\x00\x00', + b'57114-TG7-A240\x00\x00', + b'57114-TG7-A630\x00\x00', + b'57114-TG7-A730\x00\x00', + b'57114-TG8-A140\x00\x00', + b'57114-TG8-A230\x00\x00', + b'57114-TG8-A240\x00\x00', + b'57114-TG8-A630\x00\x00', + b'57114-TG8-A730\x00\x00', + b'57114-TGS-A530\x00\x00', + b'57114-TGT-A530\x00\x00', + ], + }, + CAR.ACURA_RDX: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TX4-A220\x00\x00', + b'57114-TX5-A220\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-TX4-A030\x00\x00', + b'36161-TX5-A030\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TX4-B010\x00\x00', + b'77959-TX4-C010\x00\x00', + b'77959-TX4-C020\x00\x00', + ], + }, + CAR.ACURA_RDX_3G: { + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TJB-A030\x00\x00', + b'57114-TJB-A040\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TJB-A040\x00\x00', + b'36802-TJB-A050\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TJB-A040\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TJB-A520\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28102-5YK-A610\x00\x00', + b'28102-5YK-A620\x00\x00', + b'28102-5YK-A630\x00\x00', + b'28102-5YK-A700\x00\x00', + b'28102-5YK-A711\x00\x00', + b'28102-5YL-A620\x00\x00', + b'28102-5YL-A700\x00\x00', + b'28102-5YL-A711\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TJB-A040\x00\x00', + b'77959-TJB-A210\x00\x00', + ], + (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ + b'46114-TJB-A040\x00\x00', + b'46114-TJB-A050\x00\x00', + b'46114-TJB-A060\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TJB-A040\x00\x00', + b'38897-TJB-A110\x00\x00', + b'38897-TJB-A120\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TJB-A030\x00\x00', + b'39990-TJB-A040\x00\x00', + b'39990-TJB-A130\x00\x00', + ], + }, + CAR.HONDA_RIDGELINE: { + (Ecu.eps, 0x18da30f1, None): [ + b'39990-T6Z-A020\x00\x00', + b'39990-T6Z-A030\x00\x00', + b'39990-T6Z-A050\x00\x00', + b'39990-T6Z-A110\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T6Z-A020\x00\x00', + b'36161-T6Z-A310\x00\x00', + b'36161-T6Z-A420\x00\x00', + b'36161-T6Z-A520\x00\x00', + b'36161-T6Z-A620\x00\x00', + b'36161-T6Z-A720\x00\x00', + b'36161-TJZ-A120\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-T6Z-A010\x00\x00', + b'38897-T6Z-A110\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T6Z-A020\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-T6Z-A120\x00\x00', + b'57114-T6Z-A130\x00\x00', + b'57114-T6Z-A520\x00\x00', + b'57114-T6Z-A610\x00\x00', + b'57114-TJZ-A520\x00\x00', + ], + }, + CAR.HONDA_INSIGHT: { + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TXM-A040\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TXM-A070\x00\x00', + b'36802-TXM-A080\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TXM-A050\x00\x00', + b'36161-TXM-A060\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TXM-A230\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TXM-A030\x00\x00', + b'57114-TXM-A040\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TWA-A910\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TXM-A020\x00\x00', + ], + }, + CAR.HONDA_HRV: { + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-T7A-A010\x00\x00', + b'38897-T7A-A110\x00\x00', + ], + (Ecu.eps, 0x18da30f1, None): [ + b'39990-THX-A020\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T7A-A040\x00\x00', + b'36161-T7A-A140\x00\x00', + b'36161-T7A-A240\x00\x00', + b'36161-T7A-C440\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T7A-A230\x00\x00', + ], + }, + CAR.HONDA_HRV_3G: { + (Ecu.eps, 0x18da30f1, None): [ + b'39990-3M0-G110\x00\x00', + b'39990-3M0-J030\x00\x00', + b'39990-3W0-A030\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-3M0-M110\x00\x00', + b'38897-3M0-Z010\x00\x00', + b'38897-3W1-A010\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-3M0-K840\x00\x00', + b'77959-3N1-Z840\x00\x00', + b'77959-3V0-A820\x00\x00', + b'77959-3V0-A910\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'8S102-3M3-T050\x00\x00', + b'8S102-3M6-P030\x00\x00', + b'8S102-3M6-PA20\x00\x00', + b'8S102-3W0-A060\x00\x00', + b'8S102-3W0-AB10\x00\x00', + b'8S102-3W0-AB20\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-3M6-M010\x00\x00', + b'57114-3N1-T020\x00\x00', + b'57114-3W0-A040\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-6EH-A010\x00\x00', + b'28101-6EH-A110\x00\x00', + b'28101-6JC-M310\x00\x00', + ], + (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ + b'46114-3W0-A020\x00\x00', + b'46114-3W0-A050\x00\x00', + ], + }, + CAR.ACURA_ILX: { + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TX6-A010\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-TV9-A140\x00\x00', + b'36161-TV9-C140\x00\x00', + b'36161-TX6-A030\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TX6-A230\x00\x00', + b'77959-TX6-C210\x00\x00', + ], + }, + CAR.HONDA_E: { + (Ecu.eps, 0x18da30f1, None): [ + b'39990-TYF-N030\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-TYF-E140\x00\x00', + ], + (Ecu.shiftByWire, 0x18da0bf1, None): [ + b'54008-TYF-E010\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-TYF-G430\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TYF-E030\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TYF-E020\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-TYF-E030\x00\x00', + ], + }, + CAR.HONDA_CIVIC_2022: { + (Ecu.eps, 0x18da30f1, None): [ + b'39990-T24-T120\x00\x00', + b'39990-T38-A040\x00\x00', + b'39990-T39-A130\x00\x00', + b'39990-T43-J020\x00\x00', + b'39990-T43-J030\x00\x00', + b'39990-T50-J030\x00\x00', + b'39990-T50-J110\x00\x00', + b'39990-T56-A040\x00\x00', + b'39990-T60-J030\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-T20-A020\x00\x00', + b'38897-T20-A210\x00\x00', + b'38897-T20-A310\x00\x00', + b'38897-T20-A510\x00\x00', + b'38897-T21-A010\x00\x00', + b'38897-T22-A110\x00\x00', + b'38897-T24-Z120\x00\x00', + b'38897-T47-AA20\x00\x00', + b'38897-T50-E310\x00\x00', + b'38897-T50-EA10\x00\x00', + b'38897-T60-A110\x00\x00', + b'38897-T61-A320\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T20-A970\x00\x00', + b'77959-T20-A980\x00\x00', + b'77959-T20-M820\x00\x00', + b'77959-T39-A910\x00\x00', + b'77959-T47-A940\x00\x00', + b'77959-T47-A950\x00\x00', + b'77959-T50-G010\x00\x00', + b'77959-T50-G930\x00\x00', + b'77959-T60-A920\x00\x00', + b'77959-T61-A920\x00\x00', + b'77959-T65-A920\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T20-A060\x00\x00', + b'36161-T20-A070\x00\x00', + b'36161-T20-A080\x00\x00', + b'36161-T24-T070\x00\x00', + b'36161-T38-A060\x00\x00', + b'36161-T47-A050\x00\x00', + b'36161-T47-A060\x00\x00', + b'36161-T47-A070\x00\x00', + b'8S102-T20-AA10\x00\x00', + b'8S102-T43-J540\x00\x00', + b'8S102-T47-AA10\x00\x00', + b'8S102-T47-AA20\x00\x00', + b'8S102-T50-EA10\x00\x00', + b'8S102-T56-A060\x00\x00', + b'8S102-T60-AA10\x00\x00', + b'8S102-T64-A040\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-T20-AB40\x00\x00', + b'57114-T24-TB30\x00\x00', + b'57114-T38-AA20\x00\x00', + b'57114-T43-JA30\x00\x00', + b'57114-T43-JB30\x00\x00', + b'57114-T50-JC20\x00\x00', + b'57114-T60-AA20\x00\x00', + b'57114-T61-AJ30\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-65D-A020\x00\x00', + b'28101-65D-A120\x00\x00', + b'28101-65H-A020\x00\x00', + b'28101-65H-A120\x00\x00', + b'28101-65J-N010\x00\x00', + ], + }, + CAR.HONDA_PILOT_4G: { + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'8S102-T90-A050\x00\x00', + b'8S102-T90-A060\x00\x00', + b'8S102-T90-A070\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'8S302-T90-A040\x00\x00', + ], + }, + CAR.HONDA_ACCORD_11G: { + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'8S302-30A-A040\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'8S102-30A-A050\x00\x00', + b'8S102-30A-A060\x00\x00', + ], + }, + CAR.HONDA_CRV_6G: { + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'8S302-3A0-A060\x00\x00', + b'8S302-3C0-Q050\x00\x00', + b'8S302-3D4-A050\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'8S102-3A0-A090\x00\x00', + b'8S102-3A0-A110\x00\x00', + b'8S102-3C0-Q060\x00\x00', + b'8S102-3D4-A060\x00\x00', + b'8S102-3D4-A070\x00\x00', + b'8S102-3D4-A080\x00\x00', + b'8S102-3D4-A090\x00\x00', + ], + }, + CAR.HONDA_CITY_7G: { + (Ecu.eps, 0x18da30f1, None): [ + b'39990-T14-B030\x00\x00', + ], + (Ecu.gateway, 0x18daeff1, None): [ + b'38897-T14-M110\x00\x00', + ], + (Ecu.srs, 0x18da53f1, None): [ + b'77959-T00-B830\x00\x00', + ], + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36161-T14-P050\x00\x00', + ], + (Ecu.vsa, 0x18da28f1, None): [ + b'57114-T14-B030\x00\x00', + ], + (Ecu.transmission, 0x18da1ef1, None): [ + b'28101-63B-M420\x00\x00', + ], + }, + CAR.HONDA_PASSPORT_4G: { + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'8S302-3BM-A020\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'8S102-3BM-A020\x00\x00', + ], + }, + CAR.ACURA_TLX_2G: { + (Ecu.fwdRadar, 0x18dab0f1, None): [ + b'36802-TGV-A060\x00\x00', + ], + (Ecu.fwdCamera, 0x18dab5f1, None): [ + b'36161-TGV-A030\x00\x00', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/honda/hondacan.py b/opendbc_repo/opendbc/car/honda/hondacan.py new file mode 100644 index 0000000000..317cadc656 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/hondacan.py @@ -0,0 +1,242 @@ +from opendbc.car import CanBusBase +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.honda.values import (HondaFlags, HONDA_BOSCH, HONDA_BOSCH_ALT_RADAR, HONDA_BOSCH_RADARLESS, + HONDA_BOSCH_CANFD, CarControllerParams) + +# CAN bus layout with relay +# 0 = ACC-CAN - radar side +# 1 = F-CAN B - powertrain +# 2 = ACC-CAN - camera side +# 3 = F-CAN A - OBDII port + + +class CanBus(CanBusBase): + def __init__(self, CP=None, fingerprint=None) -> None: + # use fingerprint if specified + super().__init__(CP if fingerprint is None else None, fingerprint) + + # powertrain bus is split instead of radar on radarless and CAN FD Bosch + if CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS - HONDA_BOSCH_CANFD): + self._pt, self._radar = self.offset + 1, self.offset + # normally steering commands are sent to radar, which forwards them to powertrain bus + # when radar is disabled, steering commands are sent directly to powertrain bus + self._lkas = self._pt if CP.openpilotLongitudinalControl else self._radar + else: + self._pt, self._radar, self._lkas = self.offset, self.offset + 1, self.offset + + @property + def pt(self) -> int: + return self._pt + + @property + def radar(self) -> int: + return self._radar + + @property + def camera(self) -> int: + return self.offset + 2 + + @property + def lkas(self) -> int: + return self._lkas + + # B-CAN is forwarded to ACC-CAN radar side (CAN 0 on fake ethernet port) + @property + def body(self) -> int: + return self.offset + + +def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, car_fingerprint, stock_brake): + # TODO: do we loose pressure if we keep pump off for long? + brakelights = apply_brake > 0 + brake_rq = apply_brake > 0 + pcm_fault_cmd = False + + values = { + "COMPUTER_BRAKE": apply_brake, + "BRAKE_PUMP_REQUEST": pump_on, + "CRUISE_OVERRIDE": pcm_override, + "CRUISE_FAULT_CMD": pcm_fault_cmd, + "CRUISE_CANCEL_CMD": pcm_cancel_cmd, + "COMPUTER_BRAKE_REQUEST": brake_rq, + "SET_ME_1": 1, + "BRAKE_LIGHTS": brakelights, + "CHIME": stock_brake["CHIME"] if fcw else 0, # send the chime for stock fcw + "FCW": fcw << 1, # TODO: Why are there two bits for fcw? + "AEB_REQ_1": 0, + "AEB_REQ_2": 0, + "AEB_STATUS": 0, + } + return packer.make_can_msg("BRAKE_COMMAND", CAN.pt, values) + + +def create_acc_commands(packer, CAN, enabled, active, accel, gas, stopping_counter, car_fingerprint): + commands = [] + min_gas_accel = CarControllerParams.BOSCH_GAS_LOOKUP_BP[0] + + control_on = 5 if enabled else 0 + gas_command = gas if active and accel > min_gas_accel else -30000 + accel_command = accel if active else 0 + braking = 1 if active and accel < min_gas_accel else 0 + standstill = 1 if active and stopping_counter > 0 else 0 + standstill_release = 1 if active and stopping_counter == 0 else 0 + + # common ACC_CONTROL values + acc_control_values = { + 'ACCEL_COMMAND': accel_command, + 'STANDSTILL': standstill, + } + + if car_fingerprint in HONDA_BOSCH_RADARLESS: + acc_control_values.update({ + "CONTROL_ON": enabled, + "IDLESTOP_ALLOW": stopping_counter > 200, # allow idle stop after 4 seconds (50 Hz) + }) + else: + acc_control_values.update({ + # setting CONTROL_ON causes car to set POWERTRAIN_DATA->ACC_STATUS = 1 + "CONTROL_ON": control_on, + "GAS_COMMAND": gas_command, # used for gas + "BRAKE_LIGHTS": braking, + "BRAKE_REQUEST": braking, + "STANDSTILL_RELEASE": standstill_release, + }) + acc_control_on_values = { + "SET_TO_3": 0x03, + "CONTROL_ON": enabled, + "SET_TO_FF": 0xff, + "SET_TO_75": 0x75, + "SET_TO_30": 0x30, + } + commands.append(packer.make_can_msg("ACC_CONTROL_ON", CAN.pt, acc_control_on_values)) + + commands.append(packer.make_can_msg("ACC_CONTROL", CAN.pt, acc_control_values)) + return commands + + +def create_steering_control(packer, CAN, apply_torque, lkas_active): + values = { + "STEER_TORQUE": apply_torque if lkas_active else 0, + "STEER_TORQUE_REQUEST": lkas_active, + } + return packer.make_can_msg("STEERING_CONTROL", CAN.lkas, values) + + +def create_bosch_supplemental_1(packer, CAN): + # non-active params + values = { + "SET_ME_X04": 0x04, + "SET_ME_X80": 0x80, + "SET_ME_X10": 0x10, + } + return packer.make_can_msg("BOSCH_SUPPLEMENTAL_1", CAN.lkas, values) + + +def create_acc_hud(packer, bus, CP, enabled, pcm_speed, pcm_accel, hud_control, hud_v_cruise, is_metric, acc_hud): + acc_hud_values = { + 'CRUISE_SPEED': hud_v_cruise, + 'ENABLE_MINI_CAR': 1 if enabled else 0, + # only moves the lead car without ACC_ON + 'HUD_DISTANCE': hud_control.leadDistanceBars, # wraps to 0 at 4 bars + 'IMPERIAL_UNIT': int(not is_metric), + 'HUD_LEAD': 2 if enabled and hud_control.leadVisible else 1 if enabled else 0, + 'SET_ME_X01_2': 1, + } + + if CP.carFingerprint in HONDA_BOSCH: + acc_hud_values['ACC_ON'] = int(enabled) + acc_hud_values['FCM_OFF'] = 1 + acc_hud_values['FCM_OFF_2'] = 1 + else: + # Shows the distance bars, TODO: stock camera shows updates temporarily while disabled + acc_hud_values['ACC_ON'] = int(enabled) + acc_hud_values['PCM_SPEED'] = pcm_speed * CV.MS_TO_KPH + acc_hud_values['PCM_GAS'] = pcm_accel + acc_hud_values['SET_ME_X01'] = 1 + acc_hud_values['FCM_OFF'] = acc_hud['FCM_OFF'] + acc_hud_values['FCM_OFF_2'] = acc_hud['FCM_OFF_2'] + acc_hud_values['FCM_PROBLEM'] = acc_hud['FCM_PROBLEM'] + acc_hud_values['ICONS'] = acc_hud['ICONS'] + + return packer.make_can_msg("ACC_HUD", bus, acc_hud_values) + + +def create_lkas_hud(packer, bus, CP, hud_control, lat_active, steering_available, reduced_steering, alert_steer_required, lkas_hud): + commands = [] + + lkas_hud_values = { + 'LKAS_READY': 1, + 'LKAS_STATE_CHANGE': 1, + 'STEERING_REQUIRED': alert_steer_required, + 'SOLID_LANES': hud_control.lanesVisible, + 'BEEP': 0, + } + + if CP.carFingerprint in (HONDA_BOSCH_RADARLESS | HONDA_BOSCH_CANFD): + lkas_hud_values['LANE_LINES'] = 3 + lkas_hud_values['DASHED_LANES'] = hud_control.lanesVisible + + # car likely needs to see LKAS_PROBLEM fall within a specific time frame, so forward from camera + # TODO: needed for Bosch CAN FD? + if CP.carFingerprint in HONDA_BOSCH_RADARLESS: + lkas_hud_values['LKAS_PROBLEM'] = lkas_hud['LKAS_PROBLEM'] + + if not (CP.flags & HondaFlags.BOSCH_EXT_HUD): + lkas_hud_values['RDM_OFF'] = 1 + lkas_hud_values['LANE_ASSIST_BEEP_OFF'] = 1 + + # New HUD concept for selected Bosch cars, overwrites some of the above + # TODO: make global across all Honda if feedback is favorable + if CP.carFingerprint in HONDA_BOSCH_ALT_RADAR: + lkas_hud_values['DASHED_LANES'] = steering_available + lkas_hud_values['SOLID_LANES'] = lat_active + lkas_hud_values['LKAS_PROBLEM'] = lat_active and reduced_steering + + if CP.flags & HondaFlags.BOSCH_EXT_HUD and not CP.openpilotLongitudinalControl: + commands.append(packer.make_can_msg('LKAS_HUD_A', bus, lkas_hud_values)) + commands.append(packer.make_can_msg('LKAS_HUD_B', bus, lkas_hud_values)) + else: + commands.append(packer.make_can_msg('LKAS_HUD', bus, lkas_hud_values)) + + return commands + + +def create_radar_hud(packer, bus): + radar_hud_values = { + 'CMBS_OFF': 0x01, + 'SET_TO_1': 0x01, + } + + return packer.make_can_msg('RADAR_HUD', bus, radar_hud_values) + + +def create_legacy_brake_command(packer, bus): + return packer.make_can_msg("LEGACY_BRAKE_COMMAND", bus, {}) + + +def spam_buttons_command(packer, CAN, button_val, car_fingerprint): + values = { + 'CRUISE_BUTTONS': button_val, + 'CRUISE_SETTING': 0, + } + # send buttons to camera on radarless (camera does ACC) cars + bus = CAN.camera if car_fingerprint in HONDA_BOSCH_RADARLESS else CAN.pt + return packer.make_can_msg("SCM_BUTTONS", bus, values) + + +def honda_checksum(address: int, sig, d: bytearray) -> int: + s = 0 + extended = address > 0x7FF + addr = address + while addr: + s += addr & 0xF + addr >>= 4 + for i in range(len(d)): + x = d[i] + if i == len(d) - 1: + x >>= 4 + s += (x & 0xF) + (x >> 4) + s = 8 - s + if extended: + s += 3 + return s & 0xF diff --git a/opendbc_repo/opendbc/car/honda/interface.py b/opendbc_repo/opendbc/car/honda/interface.py new file mode 100755 index 0000000000..4b1c680cf7 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/interface.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python3 +import numpy as np +from opendbc.car import get_safety_config, structs, uds +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.disable_ecu import disable_ecu +from opendbc.car.honda.hondacan import CanBus +from opendbc.car.honda.values import CarControllerParams, HondaFlags, CAR, HONDA_BOSCH, HONDA_BOSCH_CANFD, \ + HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_RADARLESS, HondaSafetyFlags +from opendbc.car.honda.carcontroller import CarController +from opendbc.car.honda.carstate import CarState +from opendbc.car.honda.radar_interface import RadarInterface +from opendbc.car.interfaces import CarInterfaceBase + +TransmissionType = structs.CarParams.TransmissionType + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def get_pid_accel_limits(CP, current_speed, cruise_speed): + if CP.carFingerprint in HONDA_BOSCH: + return CarControllerParams.BOSCH_ACCEL_MIN, CarControllerParams.BOSCH_ACCEL_MAX + else: + # NIDECs don't allow acceleration near cruise_speed, + # so limit limits of pid to prevent windup + ACCEL_MAX_VALS = [CarControllerParams.NIDEC_ACCEL_MAX, 0.2] + ACCEL_MAX_BP = [cruise_speed - 2., cruise_speed - .2] + return CarControllerParams.NIDEC_ACCEL_MIN, np.interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS) + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "honda" + + CAN = CanBus(ret, fingerprint) + + if candidate in HONDA_BOSCH: + cfgs = [get_safety_config(structs.CarParams.SafetyModel.hondaBosch)] + if candidate in HONDA_BOSCH_CANFD and CAN.pt >= 4: + cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput)) + ret.safetyConfigs = cfgs + + ret.radarUnavailable = True + # Disable the radar and let openpilot control longitudinal + # WARNING: THIS DISABLES AEB! + # If Bosch radarless, this blocks ACC messages from the camera + # TODO: get radar disable working on Bosch CANFD + ret.alphaLongitudinalAvailable = candidate not in HONDA_BOSCH_CANFD + ret.openpilotLongitudinalControl = alpha_long + ret.pcmCruise = not ret.openpilotLongitudinalControl + else: + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hondaNidec)] + ret.openpilotLongitudinalControl = True + + ret.pcmCruise = True + + if candidate == CAR.HONDA_CRV_5G: + ret.enableBsm = 0x12f8bfa7 in fingerprint[CAN.radar] + + # Detect Bosch cars with new HUD msgs + if any(0x33DA in f for f in fingerprint.values()): + ret.flags |= HondaFlags.BOSCH_EXT_HUD.value + + if 0x184 in fingerprint[CAN.pt]: + ret.flags |= HondaFlags.HYBRID.value + + if ret.flags & HondaFlags.ALLOW_MANUAL_TRANS and all(msg not in fingerprint[CAN.pt] for msg in (0x191, 0x1A3)): + # Manual transmission support for allowlisted cars only, to prevent silent fall-through on auto-detection failures + ret.transmissionType = TransmissionType.manual + elif 0x191 in fingerprint[CAN.pt] and candidate != CAR.ACURA_RDX: + # Traditional CVTs, gearshift position in GEARBOX_CVT + ret.transmissionType = TransmissionType.cvt + else: + # Traditional autos, direct-drive EVs and eCVTs, gearshift position in GEARBOX_AUTO + ret.transmissionType = TransmissionType.automatic + + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0], [0]] + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]] + ret.lateralTuning.pid.kf = 0.00006 # conservative feed-forward + ret.steerActuatorDelay = 0.1 + + if candidate in HONDA_BOSCH: + ret.longitudinalActuatorDelay = 0.5 # s + if candidate in HONDA_BOSCH_RADARLESS: + ret.stopAccel = CarControllerParams.BOSCH_ACCEL_MIN # stock uses -4.0 m/s^2 once stopped but limited by safety model + else: + # default longitudinal tuning for all hondas + ret.longitudinalTuning.kiBP = [0., 5., 35.] + ret.longitudinalTuning.kiV = [1.2, 0.8, 0.5] + + # Disable control if EPS mod detected + for fw in car_fw: + if fw.ecu == "eps" and b"," in fw.fwVersion: + ret.dashcamOnly = True + + if candidate == CAR.HONDA_CIVIC: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[1.1], [0.33]] + + elif candidate in (CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_BOSCH_DIESEL): + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + if candidate == CAR.HONDA_CIVIC_BOSCH: + CarControllerParams.BOSCH_GAS_LOOKUP_V = [0, 750] + + elif candidate == CAR.HONDA_CIVIC_2022: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kpV = [[0, 10], [0.05, 0.5]] + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kiV = [[0, 10], [0.0125, 0.125]] + + elif candidate == CAR.HONDA_ACCORD: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] + + elif candidate == CAR.ACURA_ILX: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + + elif candidate in (CAR.HONDA_CRV, CAR.HONDA_CRV_EU): + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + ret.wheelSpeedFactor = 1.025 + + elif candidate == CAR.HONDA_CRV_5G: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.64], [0.192]] + ret.wheelSpeedFactor = 1.025 + + elif candidate == CAR.HONDA_CRV_HYBRID: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] + ret.wheelSpeedFactor = 1.025 + + elif candidate == CAR.HONDA_FIT: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.05]] + + elif candidate == CAR.HONDA_FREED: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.05]] + + elif candidate in (CAR.HONDA_HRV, CAR.HONDA_HRV_3G): + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] + if candidate == CAR.HONDA_HRV: + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.025]] + ret.wheelSpeedFactor = 1.025 + else: + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] # TODO: can probably use some tuning + + elif candidate == CAR.ACURA_RDX: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + + elif candidate == CAR.ACURA_RDX_3G: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.06]] + + elif candidate == CAR.HONDA_ODYSSEY: + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]] + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + + elif candidate == CAR.HONDA_PILOT: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.38], [0.11]] + + elif candidate == CAR.HONDA_RIDGELINE: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.38], [0.11]] + + elif candidate in (CAR.HONDA_INSIGHT, CAR.HONDA_NBOX_2G): + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] + + elif candidate == CAR.HONDA_E: + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] # TODO: can probably use some tuning + + elif candidate == CAR.HONDA_ODYSSEY_5G_MMR: + # Stock camera sends up to 2560 during LKA operation and up to 3840 during RDM operation + # Steer motor torque does rise a little above 2560, but not linearly, RDM also applies one-sided brake drag + #ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560, 3072], [0, 2560, 3840]] + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]] + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + ret.steerActuatorDelay = 0.15 + CarControllerParams.BOSCH_GAS_LOOKUP_V = [0, 2000] + if not ret.openpilotLongitudinalControl: + # When using stock ACC, the radar intercepts and filters steering commands the EPS would otherwise accept + ret.minSteerSpeed = 70. * CV.KPH_TO_MS + + else: + ret.steerActuatorDelay = 0.15 + ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]] + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + # These cars use alternate user brake msg (0x1BE) + if 0x1BE in fingerprint[CAN.pt] and candidate in (CAR.HONDA_ACCORD, CAR.HONDA_HRV_3G, *HONDA_BOSCH_CANFD): + ret.flags |= HondaFlags.BOSCH_ALT_BRAKE.value + + if ret.flags & HondaFlags.BOSCH_ALT_BRAKE: + ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.ALT_BRAKE.value + if candidate in HONDA_NIDEC_ALT_SCM_MESSAGES: + ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.NIDEC_ALT.value + if ret.openpilotLongitudinalControl and candidate in HONDA_BOSCH: + ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.BOSCH_LONG.value + if candidate in HONDA_BOSCH_RADARLESS: + ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.RADARLESS.value + if candidate in HONDA_BOSCH_CANFD: + ret.safetyConfigs[-1].safetyParam |= HondaSafetyFlags.BOSCH_CANFD.value + + # min speed to enable ACC. if car can do stop and go, then set enabling speed + # to a negative value, so it won't matter. Otherwise, add 0.5 mph margin to not + # conflict with PCM acc + ret.autoResumeSng = candidate in (HONDA_BOSCH | {CAR.HONDA_CIVIC}) + ret.minEnableSpeed = -1. if ret.autoResumeSng else 25.51 * CV.MPH_TO_MS + + ret.steerLimitTimer = 0.8 + ret.radarDelay = 0.1 + + return ret + + @staticmethod + def init(CP, can_recv, can_send, communication_control=None): + if CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and CP.openpilotLongitudinalControl: + # 0x80 silences response + if communication_control is None: + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.DISABLE_RX_DISABLE_TX, + uds.MESSAGE_TYPE.NORMAL_AND_NETWORK_MANAGEMENT]) + disable_ecu(can_recv, can_send, bus=CanBus(CP).pt, addr=0x18DAB0F1, com_cont_req=communication_control) + + @staticmethod + def deinit(CP, can_recv, can_send): + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX, + uds.MESSAGE_TYPE.NORMAL_AND_NETWORK_MANAGEMENT]) + CarInterface.init(CP, can_recv, can_send, communication_control) diff --git a/opendbc_repo/opendbc/car/honda/radar_interface.py b/opendbc_repo/opendbc/car/honda/radar_interface.py new file mode 100755 index 0000000000..34a743d196 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/radar_interface.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import RadarInterfaceBase +from opendbc.car.honda.values import DBC + + +def _create_nidec_can_parser(car_fingerprint): + radar_messages = [0x400] + list(range(0x430, 0x43A)) + list(range(0x440, 0x446)) + messages = [(m, 20) for m in radar_messages] + return CANParser(DBC[car_fingerprint][Bus.radar], messages, 1) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + self.track_id = 0 + self.radar_fault = False + self.radar_wrong_config = False + self.radar_off_can = CP.radarUnavailable + + # Nidec + if self.radar_off_can: + self.rcp = None + else: + self.rcp = _create_nidec_can_parser(CP.carFingerprint) + self.trigger_msg = 0x445 + self.updated_messages = set() + + def update(self, can_strings): + # in Bosch radar and we are only steering for now, so sleep 0.05s to keep + # radard at 20Hz and return no points + if self.radar_off_can: + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + + rr = self._update(self.updated_messages) + self.updated_messages.clear() + return rr + + def _update(self, updated_messages): + ret = structs.RadarData() + + for ii in sorted(updated_messages): + cpt = self.rcp.vl[ii] + if ii == 0x400: + # check for radar faults + self.radar_fault = cpt['RADAR_STATE'] != 0x79 + self.radar_wrong_config = cpt['RADAR_STATE'] == 0x69 + elif cpt['LONG_DIST'] < 255: + if ii not in self.pts or cpt['NEW_TRACK']: + self.pts[ii] = structs.RadarData.RadarPoint() + self.pts[ii].trackId = self.track_id + self.track_id += 1 + self.pts[ii].dRel = cpt['LONG_DIST'] # from front of car + self.pts[ii].yRel = -cpt['LAT_DIST'] # in car frame's y axis, left is positive + self.pts[ii].vRel = cpt['REL_SPEED'] + self.pts[ii].aRel = float('nan') + self.pts[ii].yvRel = float('nan') + self.pts[ii].measured = True + else: + if ii in self.pts: + del self.pts[ii] + + if not self.rcp.can_valid: + ret.errors.canError = True + if self.radar_fault: + ret.errors.radarFault = True + if self.radar_wrong_config: + ret.errors.wrongConfig = True + + ret.points = list(self.pts.values()) + + return ret diff --git a/opendbc_repo/opendbc/car/honda/tests/__init__.py b/opendbc_repo/opendbc/car/honda/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/honda/tests/test_honda.py b/opendbc_repo/opendbc/car/honda/tests/test_honda.py new file mode 100644 index 0000000000..946f496d10 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/tests/test_honda.py @@ -0,0 +1,14 @@ +import re + +from opendbc.car.honda.fingerprints import FW_VERSIONS + +HONDA_FW_VERSION_RE = br"[A-Z0-9]{5}-[A-Z0-9]{3}(-|,)[A-Z0-9]{4}(\x00){2}$" + + +class TestHondaFingerprint: + def test_fw_version_format(self): + # Asserts all FW versions follow an expected format + for fw_by_ecu in FW_VERSIONS.values(): + for fws in fw_by_ecu.values(): + for fw in fws: + assert re.match(HONDA_FW_VERSION_RE, fw) is not None, fw diff --git a/opendbc_repo/opendbc/car/honda/values.py b/opendbc_repo/opendbc/car/honda/values.py new file mode 100644 index 0000000000..2e6513911b --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/values.py @@ -0,0 +1,436 @@ +from dataclasses import dataclass, field +from enum import Enum, IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, structs, uds +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column, Device +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 + +Ecu = structs.CarParams.Ecu +VisualAlert = structs.CarControl.HUDControl.VisualAlert +GearShifter = structs.CarState.GearShifter + + +class CarControllerParams: + # Allow small margin below -3.5 m/s^2 from ISO 15622:2018 since we + # perform the closed loop control, and might need some + # to apply some more braking if we're on a downhill slope. + # Our controller should still keep the 2 second average above + # -3.5 m/s^2 as per planner limits + NIDEC_ACCEL_MIN = -4.0 # m/s^2 + NIDEC_ACCEL_MAX = 1.6 # m/s^2, lower than 2.0 m/s^2 for tuning reasons + + NIDEC_ACCEL_LOOKUP_BP = [-1., 0., .6] + NIDEC_ACCEL_LOOKUP_V = [-4.8, 0., 2.0] + + NIDEC_MAX_ACCEL_V = [0.5, 2.4, 1.4, 0.6] + NIDEC_MAX_ACCEL_BP = [0.0, 4.0, 10., 20.] + + NIDEC_GAS_MAX = 198 # 0xc6 + NIDEC_BRAKE_MAX = 1024 // 4 + + BOSCH_ACCEL_MIN = -3.5 # m/s^2 + BOSCH_ACCEL_MAX = 2.0 # m/s^2 + + BOSCH_GAS_LOOKUP_BP = [-0.2, 2.0] # 2m/s^2 + BOSCH_GAS_LOOKUP_V = [0, 1600] + + STEER_STEP = 1 # 100 Hz + STEER_DELTA_UP = 3 # min/max in 0.33s for all Honda + STEER_DELTA_DOWN = 3 + STEER_GLOBAL_MIN_SPEED = 3 * CV.MPH_TO_MS + + def __init__(self, CP): + self.STEER_MAX = CP.lateralParams.torqueBP[-1] + # mirror of list (assuming first item is zero) for interp of signed request + # values and verify that both arrays begin at zero + assert CP.lateralParams.torqueBP[0] == 0 + assert CP.lateralParams.torqueV[0] == 0 + self.STEER_LOOKUP_BP = [v * -1 for v in CP.lateralParams.torqueBP][1:][::-1] + list(CP.lateralParams.torqueBP) + self.STEER_LOOKUP_V = [v * -1 for v in CP.lateralParams.torqueV][1:][::-1] + list(CP.lateralParams.torqueV) + + +class HondaSafetyFlags(IntFlag): + ALT_BRAKE = 1 + BOSCH_LONG = 2 + NIDEC_ALT = 4 + RADARLESS = 8 + BOSCH_CANFD = 16 + + +class HondaFlags(IntFlag): + # Detected flags + # Bosch models with alternate set of LKAS_HUD messages + BOSCH_EXT_HUD = 1 + BOSCH_ALT_BRAKE = 2 + + # Static flags + BOSCH = 4 + BOSCH_RADARLESS = 8 + + NIDEC = 16 + NIDEC_ALT_PCM_ACCEL = 32 + NIDEC_ALT_SCM_MESSAGES = 64 + + BOSCH_CANFD = 128 + + HAS_ALL_DOOR_STATES = 256 # Some Hondas have all door states, others only driver door + BOSCH_ALT_RADAR = 512 + ALLOW_MANUAL_TRANS = 1024 + HYBRID = 2048 + + +# Car button codes +class CruiseButtons: + RES_ACCEL = 4 + DECEL_SET = 3 + CANCEL = 2 + MAIN = 1 + + +class CruiseSettings: + DISTANCE = 3 + LKAS = 1 + + +@dataclass +class HondaCarDocs(CarDocs): + package: str = "Honda Sensing" + + def init_make(self, CP: structs.CarParams): + if CP.flags & HondaFlags.BOSCH: + if CP.flags & HondaFlags.BOSCH_CANFD: + harness = CarHarness.bosch_c + elif CP.flags & HondaFlags.BOSCH_RADARLESS: + harness = CarHarness.bosch_b + else: + harness = CarHarness.bosch_a + else: + harness = CarHarness.nidec + + if CP.carFingerprint in (CAR.HONDA_PILOT_4G,): + self.car_parts = CarParts([Device.threex_angled_mount, harness]) + else: + self.car_parts = CarParts.common([harness]) + + +class Footnote(Enum): + CIVIC_DIESEL = CarFootnote( + "2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph.", + Column.FSR_STEERING) + + +@dataclass +class HondaBoschPlatformConfig(PlatformConfig): + def init(self): + self.flags |= HondaFlags.BOSCH + + +@dataclass +class HondaBoschCANFDPlatformConfig(HondaBoschPlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'honda_common_canfd_generated'}) + + def init(self): + super().init() + self.flags |= HondaFlags.BOSCH_CANFD + + +@dataclass +class HondaNidecPlatformConfig(PlatformConfig): + def init(self): + self.flags |= HondaFlags.NIDEC + + +def radar_dbc_dict(pt_dict): + return {Bus.pt: pt_dict, Bus.radar: 'acura_ilx_2016_nidec'} + + +# Certain Hondas have an extra steering sensor at the bottom of the steering rack, +# which improves controls quality as it removes the steering column torsion from feedback. +# Tire stiffness factor fictitiously lower if it includes the steering column torsion effect. +# For modeling details, see p.198-200 in "The Science of Vehicle Dynamics (2014), M. Guiggiani" + + +class CAR(Platforms): + # Bosch Cars + HONDA_NBOX_2G = HondaBoschPlatformConfig( + [ + HondaCarDocs("Honda N-Box 2018", "All", min_steer_speed=5.), + ], + CarSpecs(mass=890., wheelbase=2.520, steerRatio=18.64), + {Bus.pt: 'acura_rdx_2020_can_generated'}, + ) + HONDA_ACCORD = HondaBoschPlatformConfig( + [ + HondaCarDocs("Honda Accord 2018-22", "All", video="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS), + HondaCarDocs("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS), + HondaCarDocs("Honda Accord Hybrid 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS), + ], + # steerRatio: 11.82 is spec end-to-end + CarSpecs(mass=3279 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=16.33, centerToFrontRatio=0.39, tireStiffnessFactor=0.8467), + {Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated'}, + ) + HONDA_ACCORD_11G = HondaBoschCANFDPlatformConfig( + [ + HondaCarDocs("Honda Accord 2023-25", "All"), + HondaCarDocs("Honda Accord Hybrid 2023-25", "All"), + ], + CarSpecs(mass=3477 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=16.0, centerToFrontRatio=0.39), + ) + HONDA_CIVIC_BOSCH = HondaBoschPlatformConfig( + [ + HondaCarDocs("Honda Civic 2019-21", "All", video="https://www.youtube.com/watch?v=4Iz1Mz5LGF8", + footnotes=[Footnote.CIVIC_DIESEL], min_steer_speed=2. * CV.MPH_TO_MS), + HondaCarDocs("Honda Civic Hatchback 2017-18", min_steer_speed=12. * CV.MPH_TO_MS), + HondaCarDocs("Honda Civic Hatchback 2019-21", "All", min_steer_speed=12. * CV.MPH_TO_MS), + ], + CarSpecs(mass=1326, wheelbase=2.7, steerRatio=15.38, centerToFrontRatio=0.4), # steerRatio: 10.93 is end-to-end spec + {Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated'}, + ) + HONDA_CIVIC_BOSCH_DIESEL = HondaBoschPlatformConfig( + [], # don't show in docs + HONDA_CIVIC_BOSCH.specs, + {Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated'}, + ) + HONDA_CIVIC_2022 = HondaBoschPlatformConfig( + [ + HondaCarDocs("Honda Civic 2022-24", "All", video="https://youtu.be/ytiOT5lcp6Q"), + HondaCarDocs("Honda Civic Hybrid 2025", "All"), + HondaCarDocs("Honda Civic Hatchback 2022-24", "All", video="https://youtu.be/ytiOT5lcp6Q"), + HondaCarDocs("Honda Civic Hatchback Hybrid (Europe only) 2023", "All"), + # TODO: Confirm 2024 + HondaCarDocs("Honda Civic Hatchback Hybrid 2025-26", "All"), + ], + HONDA_CIVIC_BOSCH.specs, + {Bus.pt: 'honda_bosch_radarless_generated'}, + flags=HondaFlags.BOSCH_RADARLESS | HondaFlags.ALLOW_MANUAL_TRANS + ) + HONDA_CRV_5G = HondaBoschPlatformConfig( + [HondaCarDocs("Honda CR-V 2017-22", min_steer_speed=15. * CV.MPH_TO_MS)], + # steerRatio: 12.3 is spec end-to-end + CarSpecs(mass=3410 * CV.LB_TO_KG, wheelbase=2.66, steerRatio=16.0, centerToFrontRatio=0.41, tireStiffnessFactor=0.677), + {Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated', Bus.body: 'honda_crv_ex_2017_body_generated'}, + flags=HondaFlags.BOSCH_ALT_BRAKE, + ) + HONDA_CRV_6G = HondaBoschCANFDPlatformConfig( + [ + HondaCarDocs("Honda CR-V 2023-25", "All"), + HondaCarDocs("Honda CR-V Hybrid 2023-25", "All"), + ], + CarSpecs(mass=1703, wheelbase=2.7, steerRatio=16.2, centerToFrontRatio=0.42), + ) + HONDA_CRV_HYBRID = HondaBoschPlatformConfig( + [HondaCarDocs("Honda CR-V Hybrid 2017-22", min_steer_speed=12. * CV.MPH_TO_MS)], + # mass: mean of 4 models in kg, steerRatio: 12.3 is spec end-to-end + CarSpecs(mass=1667, wheelbase=2.66, steerRatio=16, centerToFrontRatio=0.41, tireStiffnessFactor=0.677), + {Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated'}, + ) + HONDA_HRV_3G = HondaBoschPlatformConfig( + [HondaCarDocs("Honda HR-V 2023-25", "All")], + CarSpecs(mass=3125 * CV.LB_TO_KG, wheelbase=2.61, steerRatio=15.2, centerToFrontRatio=0.41, tireStiffnessFactor=0.5), + {Bus.pt: 'honda_bosch_radarless_generated'}, + flags=HondaFlags.BOSCH_RADARLESS, + ) + HONDA_CITY_7G = HondaBoschPlatformConfig( + [HondaCarDocs("Honda City (Brazil only) 2023", "All")], + CarSpecs(mass=3125 * CV.LB_TO_KG, wheelbase=2.6, steerRatio=19.0, centerToFrontRatio=0.41, minSteerSpeed=23. * CV.KPH_TO_MS), + {Bus.pt: 'honda_bosch_radarless_generated'}, + flags=HondaFlags.BOSCH_RADARLESS, + ) + ACURA_RDX_3G = HondaBoschPlatformConfig( + [HondaCarDocs("Acura RDX 2019-21", "All", min_steer_speed=3. * CV.MPH_TO_MS)], + CarSpecs(mass=4068 * CV.LB_TO_KG, wheelbase=2.75, steerRatio=11.95, centerToFrontRatio=0.41, tireStiffnessFactor=0.677), # as spec + {Bus.pt: 'acura_rdx_2020_can_generated'}, + flags=HondaFlags.BOSCH_ALT_BRAKE, + ) + HONDA_INSIGHT = HondaBoschPlatformConfig( + [HondaCarDocs("Honda Insight 2019-22", "All", min_steer_speed=3. * CV.MPH_TO_MS)], + CarSpecs(mass=2987 * CV.LB_TO_KG, wheelbase=2.7, steerRatio=15.0, centerToFrontRatio=0.39, tireStiffnessFactor=0.82), # as spec + {Bus.pt: 'honda_insight_ex_2019_can_generated'}, + ) + HONDA_E = HondaBoschPlatformConfig( + [HondaCarDocs("Honda e 2020", "All", min_steer_speed=3. * CV.MPH_TO_MS)], + CarSpecs(mass=3338.8 * CV.LB_TO_KG, wheelbase=2.5, centerToFrontRatio=0.5, steerRatio=16.71, tireStiffnessFactor=0.82), + {Bus.pt: 'acura_rdx_2020_can_generated'}, + ) + HONDA_PILOT_4G = HondaBoschCANFDPlatformConfig( + [HondaCarDocs("Honda Pilot 2023-25", "All")], + CarSpecs(mass=4660 * CV.LB_TO_KG, wheelbase=2.89, centerToFrontRatio=0.442, steerRatio=17.5), + ) + HONDA_PASSPORT_4G = HondaBoschCANFDPlatformConfig( + [HondaCarDocs("Honda Passport 2026", "All")], + CarSpecs(mass=4620 * CV.LB_TO_KG, wheelbase=2.89, centerToFrontRatio=0.442, steerRatio=18.5), + ) + # mid-model refresh + ACURA_MDX_4G_MMR = HondaBoschCANFDPlatformConfig( + [HondaCarDocs("Acura MDX 2025", "All except Type S")], + CarSpecs(mass=4544 * CV.LB_TO_KG, wheelbase=2.89, centerToFrontRatio=0.428, steerRatio=16.2), + ) + HONDA_ODYSSEY_5G_MMR = HondaBoschPlatformConfig( + [HondaCarDocs("Honda Odyssey 2021-25", "All", min_steer_speed=70. * CV.KPH_TO_MS)], + CarSpecs(mass=4590 * CV.LB_TO_KG, wheelbase=3.00, steerRatio=19.4, centerToFrontRatio=0.41), + {Bus.pt: 'acura_rdx_2020_can_generated'}, + flags=HondaFlags.BOSCH_ALT_BRAKE | HondaFlags.BOSCH_ALT_RADAR, + ) + ACURA_TLX_2G = HondaBoschPlatformConfig( + [HondaCarDocs("Acura TLX 2021", "All")], + CarSpecs(mass=3982 * CV.LB_TO_KG, wheelbase=2.87, steerRatio=14.0, centerToFrontRatio=0.43), + {Bus.pt: 'honda_civic_hatchback_ex_2017_can_generated'}, + flags=HondaFlags.BOSCH_ALT_RADAR, + ) + + # Nidec Cars + ACURA_ILX = HondaNidecPlatformConfig( + [ + HondaCarDocs("Acura ILX 2016-18", "Technology Plus Package or AcuraWatch Plus", min_steer_speed=25. * CV.MPH_TO_MS), + HondaCarDocs("Acura ILX 2019", "All", min_steer_speed=25. * CV.MPH_TO_MS), + ], + CarSpecs(mass=3095 * CV.LB_TO_KG, wheelbase=2.67, steerRatio=18.61, centerToFrontRatio=0.37, tireStiffnessFactor=0.72), # 15.3 is spec end-to-end + radar_dbc_dict('acura_ilx_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES | HondaFlags.HAS_ALL_DOOR_STATES, + ) + HONDA_CRV = HondaNidecPlatformConfig( + [HondaCarDocs("Honda CR-V 2015-16", "Touring Trim", min_steer_speed=12. * CV.MPH_TO_MS)], + CarSpecs(mass=3572 * CV.LB_TO_KG, wheelbase=2.62, steerRatio=16.89, centerToFrontRatio=0.41, tireStiffnessFactor=0.444), # as spec + radar_dbc_dict('honda_crv_touring_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES | HondaFlags.HAS_ALL_DOOR_STATES, + ) + HONDA_CRV_EU = HondaNidecPlatformConfig( + [], # Euro version of CRV Touring, don't show in docs + HONDA_CRV.specs, + radar_dbc_dict('honda_crv_touring_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES | HondaFlags.HAS_ALL_DOOR_STATES, + ) + HONDA_FIT = HondaNidecPlatformConfig( + [HondaCarDocs("Honda Fit 2018-20", min_steer_speed=12. * CV.MPH_TO_MS)], + CarSpecs(mass=2644 * CV.LB_TO_KG, wheelbase=2.53, steerRatio=13.06, centerToFrontRatio=0.39, tireStiffnessFactor=0.75), + radar_dbc_dict('acura_ilx_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES, + ) + HONDA_FREED = HondaNidecPlatformConfig( + [HondaCarDocs("Honda Freed 2020", min_steer_speed=12. * CV.MPH_TO_MS)], + CarSpecs(mass=3086. * CV.LB_TO_KG, wheelbase=2.74, steerRatio=13.06, centerToFrontRatio=0.39, tireStiffnessFactor=0.75), # mostly copied from FIT + radar_dbc_dict('acura_ilx_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES, + ) + HONDA_HRV = HondaNidecPlatformConfig( + [HondaCarDocs("Honda HR-V 2019-22", min_steer_speed=12. * CV.MPH_TO_MS)], + HONDA_HRV_3G.specs, + radar_dbc_dict('acura_ilx_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES, + ) + HONDA_ODYSSEY = HondaNidecPlatformConfig( + [HondaCarDocs("Honda Odyssey 2018-20")], + CarSpecs(mass=1900, wheelbase=3.0, steerRatio=14.35, centerToFrontRatio=0.41, tireStiffnessFactor=0.82), + radar_dbc_dict('honda_odyssey_exl_2018_generated'), + flags=HondaFlags.NIDEC_ALT_PCM_ACCEL | HondaFlags.HAS_ALL_DOOR_STATES, + ) + ACURA_RDX = HondaNidecPlatformConfig( + [HondaCarDocs("Acura RDX 2016-18", "AcuraWatch Plus or Advance Package", min_steer_speed=12. * CV.MPH_TO_MS)], + CarSpecs(mass=3925 * CV.LB_TO_KG, wheelbase=2.68, steerRatio=15.0, centerToFrontRatio=0.38, tireStiffnessFactor=0.444), # as spec + radar_dbc_dict('acura_rdx_2018_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES | HondaFlags.HAS_ALL_DOOR_STATES, + ) + HONDA_PILOT = HondaNidecPlatformConfig( + [ + HondaCarDocs("Honda Pilot 2016-22", min_steer_speed=12. * CV.MPH_TO_MS), + HondaCarDocs("Honda Passport 2019-25", "All", min_steer_speed=12. * CV.MPH_TO_MS), + ], + HONDA_PILOT_4G.specs, + radar_dbc_dict('acura_ilx_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES | HondaFlags.HAS_ALL_DOOR_STATES, + ) + HONDA_RIDGELINE = HondaNidecPlatformConfig( + [HondaCarDocs("Honda Ridgeline 2017-25", min_steer_speed=12. * CV.MPH_TO_MS)], + CarSpecs(mass=4515 * CV.LB_TO_KG, wheelbase=3.18, centerToFrontRatio=0.41, steerRatio=15.59, tireStiffnessFactor=0.444), # as spec + radar_dbc_dict('acura_ilx_2016_can_generated'), + flags=HondaFlags.NIDEC_ALT_SCM_MESSAGES | HondaFlags.HAS_ALL_DOOR_STATES, + ) + HONDA_CIVIC = HondaNidecPlatformConfig( + [HondaCarDocs("Honda Civic 2016-18", min_steer_speed=12. * CV.MPH_TO_MS, video="https://youtu.be/-IkImTe1NYE")], + CarSpecs(mass=1326, wheelbase=2.70, centerToFrontRatio=0.4, steerRatio=15.38), # 10.93 is end-to-end spec + radar_dbc_dict('honda_civic_touring_2016_can_generated'), + flags=HondaFlags.HAS_ALL_DOOR_STATES + ) + + +HONDA_NIDEC_ALT_PCM_ACCEL = CAR.with_flags(HondaFlags.NIDEC_ALT_PCM_ACCEL) +HONDA_NIDEC_ALT_SCM_MESSAGES = CAR.with_flags(HondaFlags.NIDEC_ALT_SCM_MESSAGES) +HONDA_BOSCH = CAR.with_flags(HondaFlags.BOSCH) +HONDA_BOSCH_RADARLESS = CAR.with_flags(HondaFlags.BOSCH_RADARLESS) +HONDA_BOSCH_CANFD = CAR.with_flags(HondaFlags.BOSCH_CANFD) +HONDA_BOSCH_ALT_RADAR = CAR.with_flags(HondaFlags.BOSCH_ALT_RADAR) + + +DBC = CAR.create_dbc_map() + + +STEER_THRESHOLD = { + # default is 1200, overrides go here + CAR.ACURA_RDX: 400, + CAR.HONDA_CRV_EU: 400, + CAR.HONDA_ACCORD_11G: 600, + CAR.HONDA_PILOT_4G: 600, + CAR.HONDA_PASSPORT_4G: 600, + CAR.ACURA_MDX_4G_MMR: 600, + CAR.HONDA_CRV_6G: 600, + CAR.HONDA_CITY_7G: 600, + CAR.HONDA_NBOX_2G: 600, +} + + +HONDA_ALT_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(0xF112) +HONDA_ALT_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(0xF112) + + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + # Currently used to fingerprint + Request( + [StdQueries.UDS_VERSION_REQUEST], + [StdQueries.UDS_VERSION_RESPONSE], + bus=1, + ), + + # Data collection requests: + # Log manufacturer-specific identifier for current ECUs + Request( + [HONDA_ALT_VERSION_REQUEST], + [HONDA_ALT_VERSION_RESPONSE], + bus=1, + logging=True, + ), + # Nidec PT bus + Request( + [StdQueries.UDS_VERSION_REQUEST], + [StdQueries.UDS_VERSION_RESPONSE], + bus=0, + ), + # Bosch PT bus + Request( + [StdQueries.UDS_VERSION_REQUEST], + [StdQueries.UDS_VERSION_RESPONSE], + bus=1, + obd_multiplexing=False, + ), + ], + # We lose these ECUs without the comma power on these cars. + # Note that we still attempt to match with them when they are present + # This is or'd with (ALL_ECUS - ESSENTIAL_ECUS) from fw_versions.py + non_essential_ecus={ + Ecu.eps: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_E, *HONDA_BOSCH_ALT_RADAR, *HONDA_BOSCH_RADARLESS, *HONDA_BOSCH_CANFD], + Ecu.vsa: [CAR.ACURA_RDX_3G, CAR.HONDA_ACCORD, CAR.HONDA_CIVIC, CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CRV_5G, CAR.HONDA_CRV_HYBRID, + CAR.HONDA_E, CAR.HONDA_INSIGHT, CAR.HONDA_NBOX_2G, *HONDA_BOSCH_ALT_RADAR, *HONDA_BOSCH_RADARLESS, *HONDA_BOSCH_CANFD], + }, + extra_ecus=[ + (Ecu.combinationMeter, 0x18da60f1, None), + (Ecu.programmedFuelInjection, 0x18da10f1, None), + # The only other ECU on PT bus accessible by camera on radarless Civic + # This is likely a manufacturer-specific sub-address implementation: the camera responds to this and 0x18dab0f1 + # Unclear what the part number refers to: 8S103 is 'Camera Set Mono', while 36160 is 'Camera Monocular - Honda' + # TODO: add query back, camera does not support querying both in parallel and 0x18dab0f1 often fails to respond + # (Ecu.unknown, 0x18DAB3F1, None), + ], +) diff --git a/opendbc_repo/opendbc/car/hyundai/__init__.py b/opendbc_repo/opendbc/car/hyundai/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py new file mode 100644 index 0000000000..6d6aa8ad94 --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -0,0 +1,217 @@ +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import Bus, DT_CTRL, make_tester_present_msg, structs +from opendbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.hyundai import hyundaicanfd, hyundaican +from opendbc.car.hyundai.hyundaicanfd import CanBus +from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR +from opendbc.car.interfaces import CarControllerBase + +VisualAlert = structs.CarControl.HUDControl.VisualAlert +LongCtrlState = structs.CarControl.Actuators.LongControlState + +# EPS faults if you apply torque while the steering angle is above 90 degrees for more than 1 second +# All slightly below EPS thresholds to avoid fault +MAX_ANGLE = 85 +MAX_ANGLE_FRAMES = 89 +MAX_ANGLE_CONSECUTIVE_FRAMES = 2 + + +def process_hud_alert(enabled, fingerprint, hud_control): + sys_warning = (hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw)) + + # initialize to no line visible + # TODO: this is not accurate for all cars + sys_state = 1 + if hud_control.leftLaneVisible and hud_control.rightLaneVisible or sys_warning: # HUD alert only display when LKAS status is active + sys_state = 3 if enabled or sys_warning else 4 + elif hud_control.leftLaneVisible: + sys_state = 5 + elif hud_control.rightLaneVisible: + sys_state = 6 + + # initialize to no warnings + left_lane_warning = 0 + right_lane_warning = 0 + if hud_control.leftLaneDepart: + left_lane_warning = 1 if fingerprint in (CAR.GENESIS_G90, CAR.GENESIS_G80) else 2 + if hud_control.rightLaneDepart: + right_lane_warning = 1 if fingerprint in (CAR.GENESIS_G90, CAR.GENESIS_G80) else 2 + + return sys_warning, sys_state, left_lane_warning, right_lane_warning + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.CAN = CanBus(CP) + self.params = CarControllerParams(CP) + self.packer = CANPacker(dbc_names[Bus.pt]) + self.angle_limit_counter = 0 + + self.accel_last = 0 + self.apply_torque_last = 0 + self.car_fingerprint = CP.carFingerprint + self.last_button_frame = 0 + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + hud_control = CC.hudControl + + # steering torque + new_torque = int(round(actuators.torque * self.params.STEER_MAX)) + apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params) + + # >90 degree steering fault prevention + self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive, + self.angle_limit_counter, MAX_ANGLE_FRAMES, + MAX_ANGLE_CONSECUTIVE_FRAMES) + + if not CC.latActive: + apply_torque = 0 + + # Hold torque with induced temporary fault when cutting the actuation bit + # FIXME: we don't use this with CAN FD? + torque_fault = CC.latActive and not apply_steer_req + + self.apply_torque_last = apply_torque + + # accel + longitudinal + accel = float(np.clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)) + stopping = actuators.longControlState == LongCtrlState.stopping + set_speed_in_units = hud_control.setSpeed * (CV.MS_TO_KPH if CS.is_metric else CV.MS_TO_MPH) + + can_sends = [] + + # *** common hyundai stuff *** + + # tester present - w/ no response (keeps relevant ECU disabled) + if self.frame % 100 == 0 and not (self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) and self.CP.openpilotLongitudinalControl: + # for longitudinal control, either radar or ADAS driving ECU + addr, bus = 0x7d0, self.CAN.ECAN if self.CP.flags & HyundaiFlags.CANFD else 0 + if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value: + addr, bus = 0x730, self.CAN.ECAN + can_sends.append(make_tester_present_msg(addr, bus, suppress_response=True)) + + # for blinkers + if self.CP.flags & HyundaiFlags.ENABLE_BLINKERS: + can_sends.append(make_tester_present_msg(0x7b1, self.CAN.ECAN, suppress_response=True)) + + # *** CAN/CAN FD specific *** + if self.CP.flags & HyundaiFlags.CANFD: + can_sends.extend(self.create_canfd_msgs(apply_steer_req, apply_torque, set_speed_in_units, accel, + stopping, hud_control, CS, CC)) + else: + can_sends.extend(self.create_can_msgs(apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel, + stopping, hud_control, actuators, CS, CC)) + + new_actuators = actuators.as_builder() + new_actuators.torque = apply_torque / self.params.STEER_MAX + new_actuators.torqueOutputCan = apply_torque + new_actuators.accel = accel + + self.frame += 1 + return new_actuators, can_sends + + def create_can_msgs(self, apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel, stopping, hud_control, actuators, CS, CC): + can_sends = [] + + # HUD messages + sys_warning, sys_state, left_lane_warning, right_lane_warning = process_hud_alert(CC.enabled, self.car_fingerprint, + hud_control) + + can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_torque, apply_steer_req, + torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled, + hud_control.leftLaneVisible, hud_control.rightLaneVisible, + left_lane_warning, right_lane_warning)) + + # Button messages + if not self.CP.openpilotLongitudinalControl: + if CC.cruiseControl.cancel: + can_sends.append(hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.CANCEL, self.CP)) + elif CC.cruiseControl.resume: + # send resume at a max freq of 10Hz + if (self.frame - self.last_button_frame) * DT_CTRL > 0.1: + # send 25 messages at a time to increases the likelihood of resume being accepted + can_sends.extend([hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.RES_ACCEL, self.CP)] * 25) + if (self.frame - self.last_button_frame) * DT_CTRL >= 0.15: + self.last_button_frame = self.frame + + if self.frame % 2 == 0 and self.CP.openpilotLongitudinalControl: + # TODO: unclear if this is needed + jerk = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0 + use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value + can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled, accel, jerk, int(self.frame / 2), + hud_control, set_speed_in_units, stopping, + CC.cruiseControl.override, use_fca, self.CP)) + + # 20 Hz LFA MFA message + if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value: + can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled)) + + # 5 Hz ACC options + if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl: + can_sends.extend(hyundaican.create_acc_opt(self.packer, self.CP)) + + # 2 Hz front radar options + if self.frame % 50 == 0 and self.CP.openpilotLongitudinalControl: + can_sends.append(hyundaican.create_frt_radar_opt(self.packer)) + + return can_sends + + def create_canfd_msgs(self, apply_steer_req, apply_torque, set_speed_in_units, accel, stopping, hud_control, CS, CC): + can_sends = [] + + lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING + lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl + + # steering control + can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque)) + + # prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU + if self.frame % 5 == 0 and lka_steering: + can_sends.append(hyundaicanfd.create_suppress_lfa(self.packer, self.CAN, CS.lfa_block_msg, + self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT)) + + # LFA and HDA icons + if self.frame % 5 == 0 and (not lka_steering or lka_steering_long): + can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled)) + + # blinkers + if lka_steering and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS: + can_sends.extend(hyundaicanfd.create_spas_messages(self.packer, self.CAN, CC.leftBlinker, CC.rightBlinker)) + + if self.CP.openpilotLongitudinalControl: + if lka_steering: + can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame)) + else: + can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame)) + if self.frame % 2 == 0: + can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override, + set_speed_in_units, hud_control)) + self.accel_last = accel + else: + # button presses + if (self.frame - self.last_button_frame) * DT_CTRL > 0.25: + # cruise cancel + if CC.cruiseControl.cancel: + if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS: + can_sends.append(hyundaicanfd.create_acc_cancel(self.packer, self.CP, self.CAN, CS.cruise_info)) + self.last_button_frame = self.frame + else: + for _ in range(20): + can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter + 1, Buttons.CANCEL)) + self.last_button_frame = self.frame + + # cruise standstill resume + elif CC.cruiseControl.resume: + if self.CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS: + # TODO: resume for alt button cars + pass + else: + for _ in range(20): + can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, CS.buttons_counter + 1, Buttons.RES_ACCEL)) + self.last_button_frame = self.frame + + return can_sends diff --git a/opendbc_repo/opendbc/car/hyundai/carstate.py b/opendbc_repo/opendbc/car/hyundai/carstate.py new file mode 100644 index 0000000000..60978970ab --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/carstate.py @@ -0,0 +1,318 @@ +from collections import deque +import copy +import math + +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.hyundai.hyundaicanfd import CanBus +from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, Buttons, CarControllerParams +from opendbc.car.interfaces import CarStateBase + +ButtonType = structs.CarState.ButtonEvent.Type + +PREV_BUTTON_SAMPLES = 8 +CLUSTER_SAMPLE_RATE = 20 # frames +STANDSTILL_THRESHOLD = 12 * 0.03125 + +# Cancel button can sometimes be ACC pause/resume button, main button can also enable on some cars +ENABLE_BUTTONS = (Buttons.RES_ACCEL, Buttons.SET_DECEL, Buttons.CANCEL) +BUTTONS_DICT = {Buttons.RES_ACCEL: ButtonType.accelCruise, Buttons.SET_DECEL: ButtonType.decelCruise, + Buttons.GAP_DIST: ButtonType.gapAdjustCruise, Buttons.CANCEL: ButtonType.cancel} + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + + self.cruise_buttons: deque = deque([Buttons.NONE] * PREV_BUTTON_SAMPLES, maxlen=PREV_BUTTON_SAMPLES) + self.main_buttons: deque = deque([Buttons.NONE] * PREV_BUTTON_SAMPLES, maxlen=PREV_BUTTON_SAMPLES) + self.lda_button = 0 + + self.gear_msg_canfd = "ACCELERATOR" if CP.flags & HyundaiFlags.EV else \ + "GEAR_ALT" if CP.flags & HyundaiFlags.CANFD_ALT_GEARS else \ + "GEAR_ALT_2" if CP.flags & HyundaiFlags.CANFD_ALT_GEARS_2 else \ + "GEAR_SHIFTER" + if CP.flags & HyundaiFlags.CANFD: + self.shifter_values = can_define.dv[self.gear_msg_canfd]["GEAR"] + elif CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV): + self.shifter_values = can_define.dv["ELECT_GEAR"]["Elect_Gear_Shifter"] + elif self.CP.flags & HyundaiFlags.CLUSTER_GEARS: + self.shifter_values = can_define.dv["CLU15"]["CF_Clu_Gear"] + elif self.CP.flags & HyundaiFlags.TCU_GEARS: + self.shifter_values = can_define.dv["TCU12"]["CUR_GR"] + elif CP.flags & HyundaiFlags.FCEV: + self.shifter_values = can_define.dv["EMS20"]["HYDROGEN_GEAR_SHIFTER"] + else: + self.shifter_values = can_define.dv["LVR12"]["CF_Lvr_Gear"] + + self.accelerator_msg_canfd = "ACCELERATOR" if CP.flags & HyundaiFlags.EV else \ + "ACCELERATOR_ALT" if CP.flags & HyundaiFlags.HYBRID else \ + "ACCELERATOR_BRAKE_ALT" + self.cruise_btns_msg_canfd = "CRUISE_BUTTONS_ALT" if CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS else \ + "CRUISE_BUTTONS" + self.is_metric = False + self.buttons_counter = 0 + + self.cruise_info = {} + + # On some cars, CLU15->CF_Clu_VehicleSpeed can oscillate faster than the dash updates. Sample at 5 Hz + self.cluster_speed = 0 + self.cluster_speed_counter = CLUSTER_SAMPLE_RATE + + self.params = CarControllerParams(CP) + + def recent_button_interaction(self) -> bool: + # On some newer model years, the CANCEL button acts as a pause/resume button based on the PCM state + # To avoid re-engaging when openpilot cancels, check user engagement intention via buttons + # Main button also can trigger an engagement on these cars + return any(btn in ENABLE_BUTTONS for btn in self.cruise_buttons) or any(self.main_buttons) + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + + if self.CP.flags & HyundaiFlags.CANFD: + return self.update_canfd(can_parsers) + + ret = structs.CarState() + cp_cruise = cp_cam if self.CP.flags & HyundaiFlags.CAMERA_SCC else cp + self.is_metric = cp.vl["CLU11"]["CF_Clu_SPEED_UNIT"] == 0 + speed_conv = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS + + ret.doorOpen = any([cp.vl["CGW1"]["CF_Gway_DrvDrSw"], cp.vl["CGW1"]["CF_Gway_AstDrSw"], + cp.vl["CGW2"]["CF_Gway_RLDrSw"], cp.vl["CGW2"]["CF_Gway_RRDrSw"]]) + + ret.seatbeltUnlatched = cp.vl["CGW1"]["CF_Gway_DrvSeatBeltSw"] == 0 + + self.parse_wheel_speeds(ret, + cp.vl["WHL_SPD11"]["WHL_SPD_FL"], + cp.vl["WHL_SPD11"]["WHL_SPD_FR"], + cp.vl["WHL_SPD11"]["WHL_SPD_RL"], + cp.vl["WHL_SPD11"]["WHL_SPD_RR"], + ) + ret.standstill = cp.vl["WHL_SPD11"]["WHL_SPD_FL"] <= STANDSTILL_THRESHOLD and cp.vl["WHL_SPD11"]["WHL_SPD_RR"] <= STANDSTILL_THRESHOLD + + self.cluster_speed_counter += 1 + if self.cluster_speed_counter > CLUSTER_SAMPLE_RATE: + self.cluster_speed = cp.vl["CLU15"]["CF_Clu_VehicleSpeed"] + self.cluster_speed_counter = 0 + + # Mimic how dash converts to imperial. + # Sorento is the only platform where CF_Clu_VehicleSpeed is already imperial when not is_metric + # TODO: CGW_USM1->CF_Gway_DrLockSoundRValue may describe this + if not self.is_metric and self.CP.carFingerprint not in (CAR.KIA_SORENTO,): + self.cluster_speed = math.floor(self.cluster_speed * CV.KPH_TO_MPH + CV.KPH_TO_MPH) + + ret.vEgoCluster = self.cluster_speed * speed_conv + + ret.steeringAngleDeg = cp.vl["SAS11"]["SAS_Angle"] + ret.steeringRateDeg = cp.vl["SAS11"]["SAS_Speed"] + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp( + 50, cp.vl["CGW1"]["CF_Gway_TurnSigLh"], cp.vl["CGW1"]["CF_Gway_TurnSigRh"]) + ret.steeringTorque = cp.vl["MDPS12"]["CR_Mdps_StrColTq"] + ret.steeringTorqueEps = cp.vl["MDPS12"]["CR_Mdps_OutTq"] + ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5) + ret.steerFaultTemporary = cp.vl["MDPS12"]["CF_Mdps_ToiUnavail"] != 0 or cp.vl["MDPS12"]["CF_Mdps_ToiFlt"] != 0 + + # 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 + ret.cruiseState.enabled = cp.vl["TCS13"]["ACC_REQ"] == 1 + ret.cruiseState.standstill = False + ret.cruiseState.nonAdaptive = False + else: + ret.cruiseState.available = cp_cruise.vl["SCC11"]["MainMode_ACC"] == 1 + ret.cruiseState.enabled = cp_cruise.vl["SCC12"]["ACCMode"] != 0 + ret.cruiseState.standstill = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 4. + ret.cruiseState.nonAdaptive = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 2. # Shows 'Cruise Control' on dash + ret.cruiseState.speed = cp_cruise.vl["SCC11"]["VSetDis"] * speed_conv + + # TODO: Find brake pressure + ret.brake = 0 + ret.brakePressed = cp.vl["TCS13"]["DriverOverride"] == 2 # 2 includes regen braking by user on HEV/EV + ret.brakeHoldActive = cp.vl["TCS15"]["AVH_LAMP"] == 2 # 0 OFF, 1 ERROR, 2 ACTIVE, 3 READY + ret.parkingBrake = cp.vl["TCS13"]["PBRAKE_ACT"] == 1 + ret.espDisabled = cp.vl["TCS11"]["TCS_PAS"] == 1 + ret.espActive = cp.vl["TCS11"]["ABS_ACT"] == 1 + ret.accFaulted = cp.vl["TCS13"]["ACCEnable"] != 0 # 0 ACC CONTROL ENABLED, 1-3 ACC CONTROL DISABLED + + if self.CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV | HyundaiFlags.FCEV): + if self.CP.flags & HyundaiFlags.FCEV: + ret.gasPressed = cp.vl["FCEV_ACCELERATOR"]["ACCELERATOR_PEDAL"] > 0 + elif self.CP.flags & HyundaiFlags.HYBRID: + ret.gasPressed = cp.vl["E_EMS11"]["CR_Vcu_AccPedDep_Pos"] > 0 + else: + ret.gasPressed = cp.vl["E_EMS11"]["Accel_Pedal_Pos"] > 0 + else: + ret.gasPressed = bool(cp.vl["EMS16"]["CF_Ems_AclAct"]) + + # Gear Selection via Cluster - For those Kia/Hyundai which are not fully discovered, we can use the Cluster Indicator for Gear Selection, + # as this seems to be standard over all cars, but is not the preferred method. + if self.CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV): + gear = cp.vl["ELECT_GEAR"]["Elect_Gear_Shifter"] + elif self.CP.flags & HyundaiFlags.FCEV: + gear = cp.vl["EMS20"]["HYDROGEN_GEAR_SHIFTER"] + elif self.CP.flags & HyundaiFlags.CLUSTER_GEARS: + gear = cp.vl["CLU15"]["CF_Clu_Gear"] + elif self.CP.flags & HyundaiFlags.TCU_GEARS: + gear = cp.vl["TCU12"]["CUR_GR"] + else: + gear = cp.vl["LVR12"]["CF_Lvr_Gear"] + + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear)) + + if not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC: + aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12" + aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct" + aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0 + scc_warning = cp_cruise.vl["SCC12"]["TakeOverReq"] == 1 # sometimes only SCC system shows an FCW + aeb_braking = cp_cruise.vl[aeb_src]["CF_VSM_DecCmdAct"] != 0 or cp_cruise.vl[aeb_src][aeb_sig] != 0 + ret.stockFcw = (aeb_warning or scc_warning) and not aeb_braking + ret.stockAeb = aeb_warning and aeb_braking + + if self.CP.enableBsm: + ret.leftBlindspot = cp.vl["LCA11"]["CF_Lca_IndLeft"] != 0 + ret.rightBlindspot = cp.vl["LCA11"]["CF_Lca_IndRight"] != 0 + + # save the entire LKAS11 and CLU11 + self.lkas11 = copy.copy(cp_cam.vl["LKAS11"]) + self.clu11 = copy.copy(cp.vl["CLU11"]) + self.steer_state = cp.vl["MDPS12"]["CF_Mdps_ToiActive"] # 0 NOT ACTIVE, 1 ACTIVE + prev_cruise_buttons = self.cruise_buttons[-1] + prev_main_buttons = self.main_buttons[-1] + prev_lda_button = self.lda_button + 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.flags & HyundaiFlags.HAS_LDA_BUTTON: + self.lda_button = cp.vl["BCM_PO_11"]["LDA_BTN"] + + ret.buttonEvents = [*create_button_events(self.cruise_buttons[-1], prev_cruise_buttons, BUTTONS_DICT), + *create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise}), + *create_button_events(self.lda_button, prev_lda_button, {1: ButtonType.lkas})] + + ret.blockPcmEnable = not self.recent_button_interaction() + + # low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s) + if ret.vEgo < (self.CP.minSteerSpeed + 2.) and self.CP.minSteerSpeed > 10.: + self.low_speed_alert = True + if ret.vEgo > (self.CP.minSteerSpeed + 4.): + self.low_speed_alert = False + ret.lowSpeedAlert = self.low_speed_alert + + return ret + + def update_canfd(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + + ret = structs.CarState() + + self.is_metric = cp.vl["CRUISE_BUTTONS_ALT"]["DISTANCE_UNIT"] != 1 + speed_factor = CV.KPH_TO_MS if self.is_metric else CV.MPH_TO_MS + + if self.CP.flags & (HyundaiFlags.EV | HyundaiFlags.HYBRID): + ret.gasPressed = cp.vl[self.accelerator_msg_canfd]["ACCELERATOR_PEDAL"] > 1e-5 + else: + ret.gasPressed = bool(cp.vl[self.accelerator_msg_canfd]["ACCELERATOR_PEDAL_PRESSED"]) + + ret.brakePressed = cp.vl["TCS"]["DriverBraking"] == 1 + + ret.doorOpen = cp.vl["DOORS_SEATBELTS"]["DRIVER_DOOR"] == 1 + ret.seatbeltUnlatched = cp.vl["DOORS_SEATBELTS"]["DRIVER_SEATBELT"] == 0 + + gear = cp.vl[self.gear_msg_canfd]["GEAR"] + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear)) + + # TODO: figure out positions + self.parse_wheel_speeds(ret, + cp.vl["WHEEL_SPEEDS"]["WHL_SpdFLVal"], + cp.vl["WHEEL_SPEEDS"]["WHL_SpdFRVal"], + cp.vl["WHEEL_SPEEDS"]["WHL_SpdRLVal"], + cp.vl["WHEEL_SPEEDS"]["WHL_SpdRRVal"], + ) + ret.standstill = cp.vl["WHEEL_SPEEDS"]["WHL_SpdFLVal"] <= STANDSTILL_THRESHOLD and cp.vl["WHEEL_SPEEDS"]["WHL_SpdFRVal"] <= STANDSTILL_THRESHOLD and \ + cp.vl["WHEEL_SPEEDS"]["WHL_SpdRLVal"] <= STANDSTILL_THRESHOLD and cp.vl["WHEEL_SPEEDS"]["WHL_SpdRRVal"] <= STANDSTILL_THRESHOLD + + ret.steeringRateDeg = cp.vl["STEERING_SENSORS"]["STEERING_RATE"] + ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"] + ret.steeringTorque = cp.vl["MDPS"]["STEERING_COL_TORQUE"] + ret.steeringTorqueEps = cp.vl["MDPS"]["STEERING_OUT_TORQUE"] + ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5) + ret.steerFaultTemporary = cp.vl["MDPS"]["LKA_FAULT"] != 0 + + # TODO: alt signal usage may be described by cp.vl['BLINKERS']['USE_ALT_LAMP'] + left_blinker_sig, right_blinker_sig = "LEFT_LAMP", "RIGHT_LAMP" + if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN: + left_blinker_sig, right_blinker_sig = "LEFT_LAMP_ALT", "RIGHT_LAMP_ALT" + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig], + cp.vl["BLINKERS"][right_blinker_sig]) + if self.CP.enableBsm: + ret.leftBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FL_INDICATOR"] != 0 + ret.rightBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FR_INDICATOR"] != 0 + + # cruise state + # CAN FD cars enable on main button press, set available if no TCS faults preventing engagement + ret.cruiseState.available = cp.vl["TCS"]["ACCEnable"] == 0 + if self.CP.openpilotLongitudinalControl: + # These are not used for engage/disengage since openpilot keeps track of state using the buttons + ret.cruiseState.enabled = cp.vl["TCS"]["ACC_REQ"] == 1 + ret.cruiseState.standstill = False + else: + cp_cruise_info = cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp + 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 + self.cruise_info = copy.copy(cp_cruise_info.vl["SCC_CONTROL"]) + + # Manual Speed Limit Assist is a feature that replaces non-adaptive cruise control on EV CAN FD platforms. + # It limits the vehicle speed, overridable by pressing the accelerator past a certain point. + # The car will brake, but does not respect positive acceleration commands in this mode + # TODO: find this message on ICE & HYBRID cars + cruise control signals (if exists) + if self.CP.flags & HyundaiFlags.EV: + ret.cruiseState.nonAdaptive = cp.vl["MANUAL_SPEED_LIMIT_ASSIST"]["MSLA_ENABLED"] == 1 + + prev_cruise_buttons = self.cruise_buttons[-1] + prev_main_buttons = self.main_buttons[-1] + prev_lda_button = self.lda_button + 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"]) + self.lda_button = cp.vl[self.cruise_btns_msg_canfd]["LDA_BTN"] + self.buttons_counter = cp.vl[self.cruise_btns_msg_canfd]["COUNTER"] + ret.accFaulted = cp.vl["TCS"]["ACCEnable"] != 0 # 0 ACC CONTROL ENABLED, 1-3 ACC CONTROL DISABLED + + if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING: + self.lfa_block_msg = copy.copy(cp_cam.vl["CAM_0x362"] if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT + else cp_cam.vl["CAM_0x2a4"]) + + ret.buttonEvents = [*create_button_events(self.cruise_buttons[-1], prev_cruise_buttons, BUTTONS_DICT), + *create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise}), + *create_button_events(self.lda_button, prev_lda_button, {1: ButtonType.lkas})] + + ret.blockPcmEnable = not self.recent_button_interaction() + + return ret + + def get_can_parsers_canfd(self, CP): + msgs = [] + if not (CP.flags & HyundaiFlags.CANFD_ALT_BUTTONS): + # TODO: this can be removed once we add dynamic support to vl_all + msgs += [ + # this message is 50Hz but the ECU frequently stops transmitting for ~0.5s + ("CRUISE_BUTTONS", 1) + ] + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], msgs, CanBus(CP).ECAN), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).CAM), + } + + def get_can_parsers(self, CP): + if CP.flags & HyundaiFlags.CANFD: + return self.get_can_parsers_canfd(CP) + + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/hyundai/fingerprints.py b/opendbc_repo/opendbc/car/hyundai/fingerprints.py new file mode 100644 index 0000000000..4c59f92ebc --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/fingerprints.py @@ -0,0 +1,1275 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.hyundai.values import CAR + +Ecu = CarParams.Ecu + +# The existence of SCC or RDR in the fwdRadar FW usually determines the radar's function, +# i.e. if it sends the SCC messages or if another ECU like the camera or ADAS Driving ECU does + + +FW_VERSIONS = { + CAR.HYUNDAI_AZERA_6TH_GEN: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00IG__ SCC F-CU- 1.00 1.00 99110-G8100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00IG MDPS C 1.00 1.02 56310G8510\x00 4IGSC103', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00IG MFC AT MES LHD 1.00 1.04 99211-G8100 200511', + b'\xf1\x00IG MFC AT MES LHD 1.00 1.05 99211-G8100 210409', + ], + }, + CAR.HYUNDAI_AZERA_HEV_6TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00IGH MFC AT KOR LHD 1.00 1.00 99211-G8000 180903', + b'\xf1\x00IGH MFC AT KOR LHD 1.00 1.01 99211-G8000 181109', + b'\xf1\x00IGH MFC AT KOR LHD 1.00 1.02 99211-G8100 191029', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00IG MDPS C 1.00 1.00 56310M9600\x00 4IHSC100', + b'\xf1\x00IG MDPS C 1.00 1.01 56310M9350\x00 4IH8C101', + b'\xf1\x00IG MDPS C 1.00 1.02 56310M9350\x00 4IH8C102', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00IGhe SCC FHCUP 1.00 1.00 99110-M9100 ', + b'\xf1\x00IGhe SCC FHCUP 1.00 1.01 99110-M9000 ', + b'\xf1\x00IGhe SCC FHCUP 1.00 1.02 99110-M9000 ', + ], + }, + CAR.HYUNDAI_GENESIS: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DH LKAS 1.1 -150210', + b'\xf1\x00DH LKAS 1.4 -140110', + b'\xf1\x00DH LKAS 1.5 -140425', + ], + }, + CAR.HYUNDAI_IONIQ: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 ', + b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00AE MDPS C 1.00 1.03 56310/G2300 4AEHC103', + b'\xf1\x00AE MDPS C 1.00 1.03 56310G2300\x00 4AEHC103', + b'\xf1\x00AE MDPS C 1.00 1.04 56310G2550\x00 4AEHC104', + b'\xf1\x00AE MDPS C 1.00 1.05 56310/G2500 4AEHC105', + b'\xf1\x00AE MDPS C 1.00 1.05 56310/G2501 4AEHC105', + b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2301 4AEHC107', + b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2501 4AEHC107', + b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2551 4AEHC107', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AEH MFC AT EUR LHD 1.00 1.00 95740-G2400 180222', + b'\xf1\x00AEH MFC AT EUR LHD 1.00 1.00 95740-G7200 160418', + b'\xf1\x00AEH MFC AT EUR RHD 1.00 1.00 95740-G2200 161014', + b'\xf1\x00AEH MFC AT EUR RHD 1.00 1.00 95740-G2400 180222', + b'\xf1\x00AEH MFC AT USA LHD 1.00 1.00 95740-G2300 170703', + b'\xf1\x00AEH MFC AT USA LHD 1.00 1.00 95740-G2400 180222', + ], + }, + CAR.HYUNDAI_IONIQ_PHEV_2019: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 ', + b'\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2501 4AEHC107', + b'\xf1\x00AE MDPS C 1.00 1.07 56310/G2551 4AEHC107', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AEP MFC AT AUS RHD 1.00 1.00 95740-G2400 180222', + b'\xf1\x00AEP MFC AT USA LHD 1.00 1.00 95740-G2400 180222', + ], + }, + CAR.HYUNDAI_IONIQ_PHEV: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AEhe SCC F-CUP 1.00 1.00 99110-G2200 ', + b'\xf1\x00AEhe SCC F-CUP 1.00 1.00 99110-G2600 ', + b'\xf1\x00AEhe SCC F-CUP 1.00 1.02 99110-G2100 ', + b'\xf1\x00AEhe SCC FHCUP 1.00 1.00 99110-G2600 ', + b'\xf1\x00AEhe SCC FHCUP 1.00 1.02 99110-G2100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G2210 4APHC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G2310 4APHC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G2510 4APHC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G2560 4APHC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310G2510\x00 4APHC101', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AEP MFC AT EUR LHD 1.00 1.01 95740-G2600 190819', + b'\xf1\x00AEP MFC AT EUR RHD 1.00 1.01 95740-G2600 190819', + b'\xf1\x00AEP MFC AT USA LHD 1.00 1.00 95740-G2700 201027', + b'\xf1\x00AEP MFC AT USA LHD 1.00 1.01 95740-G2600 190819', + ], + }, + CAR.HYUNDAI_IONIQ_EV_2020: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AEev SCC F-CUP 1.00 1.00 99110-G7200 ', + b'\xf1\x00AEev SCC F-CUP 1.00 1.00 99110-G7500 ', + b'\xf1\x00AEev SCC F-CUP 1.00 1.01 99110-G7000 ', + b'\xf1\x00AEev SCC F-CUP 1.00 1.01 99110-G7100 ', + b'\xf1\x00AEev SCC FHCUP 1.00 1.01 99110-G7100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G7310 4APEC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G7510 4APEC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G7560 4APEC101', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.00 95740-G2600 190730', + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.00 95740-G2700 201027', + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.01 95740-G2600 190819', + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.03 95740-G2500 190516', + b'\xf1\x00AEE MFC AT EUR RHD 1.00 1.01 95740-G2600 190819', + b'\xf1\x00AEE MFC AT USA LHD 1.00 1.01 95740-G2600 190819', + ], + }, + CAR.HYUNDAI_IONIQ_EV_LTD: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AEev SCC F-CUP 1.00 1.00 96400-G7000 ', + b'\xf1\x00AEev SCC F-CUP 1.00 1.00 96400-G7100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00AE MDPS C 1.00 1.02 56310G7300\x00 4AEEC102', + b'\xf1\x00AE MDPS C 1.00 1.03 56310/G7300 4AEEC103', + b'\xf1\x00AE MDPS C 1.00 1.03 56310G7300\x00 4AEEC103', + b'\xf1\x00AE MDPS C 1.00 1.04 56310/G7301 4AEEC104', + b'\xf1\x00AE MDPS C 1.00 1.04 56310/G7501 4AEEC104', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.00 95740-G2300 170703', + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.00 95740-G2400 180222', + b'\xf1\x00AEE MFC AT EUR LHD 1.00 1.00 95740-G7200 160418', + b'\xf1\x00AEE MFC AT USA LHD 1.00 1.00 95740-G2400 180222', + ], + }, + CAR.HYUNDAI_IONIQ_HEV_2022: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AEhe SCC F-CUP 1.00 1.00 99110-G2600 ', + b'\xf1\x00AEhe SCC F-CUP 1.00 1.02 99110-G2100 ', + b'\xf1\x00AEhe SCC FHCUP 1.00 1.00 99110-G2600 ', + b'\xf1\x00AEhe SCC FHCUP 1.00 1.02 99110-G2100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00AE MDPS C 1.00 1.01 56310/G2510 4APHC101', + b'\xf1\x00AE MDPS C 1.00 1.01 56310G2510\x00 4APHC101', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AEH MFC AT USA LHD 1.00 1.00 95740-G2700 201027', + b'\xf1\x00AEH MFC AT USA LHD 1.00 1.01 95740-G2600 190819', + ], + }, + CAR.HYUNDAI_SONATA: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DN8_ SCC F-CU- 1.00 1.00 99110-L0000 ', + b'\xf1\x00DN8_ SCC F-CUP 1.00 1.00 99110-L0000 ', + b'\xf1\x00DN8_ SCC F-CUP 1.00 1.02 99110-L1000 ', + b'\xf1\x00DN8_ SCC FHCU- 1.00 1.00 99110-L0000 ', + b'\xf1\x00DN8_ SCC FHCUP 1.00 1.00 99110-L0000 ', + b'\xf1\x00DN8_ SCC FHCUP 1.00 1.01 99110-L1000 ', + b'\xf1\x00DN8_ SCC FHCUP 1.00 1.02 99110-L1000 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00DN ESC \x01 102\x19\x04\x13 58910-L1300', + b'\xf1\x00DN ESC \x03 100 \x08\x01 58910-L0300', + b'\xf1\x00DN ESC \x06 104\x19\x08\x01 58910-L0100', + b'\xf1\x00DN ESC \x06 106 \x07\x01 58910-L0100', + b'\xf1\x00DN ESC \x06 107 \x07\x03 58910-L1300', + b'\xf1\x00DN ESC \x06 107"\x08\x07 58910-L0100', + b'\xf1\x00DN ESC \x07 104\x19\x08\x01 58910-L0100', + b'\xf1\x00DN ESC \x07 106 \x07\x01 58910-L0100', + b'\xf1\x00DN ESC \x07 107"\x08\x07 58910-L0100', + b'\xf1\x00DN ESC \x08 103\x19\x06\x01 58910-L1300', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DN8 MDPS C 1,00 1,01 56310L0010\x00 4DNAC101', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0010 4DNAC101', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0200 4DNAC101', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0200 4DNAC102', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0210 4DNAC101', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L0210 4DNAC102', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310L0010\x00 4DNAC101', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310L0200\x00 4DNAC102', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310L0210\x00 4DNAC101', + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310L0210\x00 4DNAC102', + b'\xf1\x00DN8 MDPS C 1.00 1.03 56310-L1010 4DNDC103', + b'\xf1\x00DN8 MDPS C 1.00 1.03 56310-L1030 4DNDC103', + b'\xf1\x00DN8 MDPS R 1.00 1.00 57700-L0000 4DNAP100', + b'\xf1\x00DN8 MDPS R 1.00 1.00 57700-L0000 4DNAP101', + b'\xf1\x00DN8 MDPS R 1.00 1.02 57700-L1000 4DNDP105', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.02 99211-L1000 190422', + b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.04 99211-L1000 191016', + b'\xf1\x00DN8 MFC AT RUS LHD 1.00 1.03 99211-L1000 190705', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.00 99211-L0000 190716', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.01 99211-L0000 191016', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.03 99211-L0000 210603', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.05 99211-L1000 201109', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.06 99211-L1000 210325', + b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.07 99211-L1000 211223', + ], + }, + CAR.HYUNDAI_SONATA_LF: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00LF__ SCC F-CUP 1.00 1.00 96401-C2200 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00LF ESC \t 11 \x17\x01\x13 58920-C2610', + b'\xf1\x00LF ESC \x0c 11 \x17\x01\x13 58920-C2610', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00LFF LKAS AT USA LHD 1.00 1.01 95740-C1000 E51', + b'\xf1\x00LFF LKAS AT USA LHD 1.01 1.02 95740-C1000 E52', + ], + }, + CAR.HYUNDAI_TUCSON: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00TL__ FCA F-CUP 1.00 1.01 99110-D3500 ', + b'\xf1\x00TL__ FCA F-CUP 1.00 1.02 99110-D3510 ', + b'\xf1\x00TL__ FCA FHCUP 1.00 1.02 99110-D3500 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00TL MFC AT KOR LHD 1.00 1.02 95895-D3800 180719', + b'\xf1\x00TL MFC AT KOR LHD 1.00 1.06 95895-D3800 190107', + b'\xf1\x00TL MFC AT USA LHD 1.00 1.06 95895-D3800 190107', + ], + }, + CAR.HYUNDAI_SANTA_FE: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00TM__ SCC F-CUP 1.00 1.00 99110-S1210 ', + b'\xf1\x00TM__ SCC F-CUP 1.00 1.01 99110-S2000 ', + b'\xf1\x00TM__ SCC F-CUP 1.00 1.02 99110-S2000 ', + b'\xf1\x00TM__ SCC F-CUP 1.00 1.03 99110-S2000 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00TM ESC \x02 100\x18\x030 58910-S2600', + b'\xf1\x00TM ESC \x02 102\x18\x07\x01 58910-S2600', + b'\xf1\x00TM ESC \x02 103\x18\x11\x05 58910-S2500', + b'\xf1\x00TM ESC \x02 103\x18\x11\x07 58910-S2600', + b'\xf1\x00TM ESC \x02 104\x19\x07\x07 58910-S2600', + b'\xf1\x00TM ESC \x03 103\x18\x11\x07 58910-S2600', + b'\xf1\x00TM ESC \x0c 103\x18\x11\x08 58910-S2650', + b'\xf1\x00TM ESC \r 100\x18\x031 58910-S2650', + b'\xf1\x00TM ESC \r 103\x18\x11\x08 58910-S2650', + b'\xf1\x00TM ESC \r 104\x19\x07\x08 58910-S2650', + b'\xf1\x00TM ESC \r 105\x19\x05# 58910-S1500', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8409', + b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8A12', + b'\xf1\x00TM MDPS C 1.00 1.01 56340-S2000 9129', + b'\xf1\x00TM MDPS R 1.00 1.02 57700-S1100 4TMDP102', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00TM MFC AT EUR LHD 1.00 1.01 99211-S1010 181207', + b'\xf1\x00TM MFC AT USA LHD 1.00 1.00 99211-S2000 180409', + ], + }, + CAR.HYUNDAI_SANTA_FE_2022: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00TM__ SCC F-CUP 1.00 1.00 99110-S1500 ', + b'\xf1\x00TM__ SCC F-CUP 1.00 1.01 99110-S1500 ', + b'\xf1\x00TM__ SCC FHCUP 1.00 1.00 99110-S1500 ', + b'\xf1\x00TM__ SCC FHCUP 1.00 1.01 99110-S1500 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00TM ESC \x01 102!\x04\x03 58910-S2DA0', + b'\xf1\x00TM ESC \x01 104"\x10\x07 58910-S2DA0', + b'\xf1\x00TM ESC \x02 101 \x08\x04 58910-S2GA0', + b'\xf1\x00TM ESC \x02 103"\x07\x08 58910-S2GA0', + b'\xf1\x00TM ESC \x03 101 \x08\x02 58910-S2DA0', + b'\xf1\x00TM ESC \x03 102!\x04\x03 58910-S2DA0', + b'\xf1\x00TM ESC \x03 103"\x07\x06 58910-S2DA0', + b'\xf1\x00TM ESC \x04 101 \x08\x04 58910-S2GA0', + b'\xf1\x00TM ESC \x04 102!\x04\x05 58910-S2GA0', + b'\xf1\x00TM ESC \x04 103"\x07\x08 58910-S2GA0', + b'\xf1\x00TM ESC \x1b 102 \x08\x08 58910-S1DA0', + b'\xf1\x00TM ESC \x1e 102 \x08\x08 58910-S1DA0', + b'\xf1\x00TM ESC 103!\x030 58910-S1MA0', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00TM MDPS C 1.00 1.01 56310-S1AB0 4TSDC101', + b'\xf1\x00TM MDPS C 1.00 1.01 56310-S1EB0 4TSDC101', + b'\xf1\x00TM MDPS C 1.00 1.02 56370-S2AA0 0B19', + b'\xf1\x00TM MDPS R 1.00 1.05 57700-S1500 4TSDP105', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00TM MFC AT EUR LHD 1.00 1.03 99211-S1500 210224', + b'\xf1\x00TM MFC AT MES LHD 1.00 1.05 99211-S1500 220126', + b'\xf1\x00TMA MFC AT MEX LHD 1.00 1.01 99211-S2500 210205', + b'\xf1\x00TMA MFC AT USA LHD 1.00 1.00 99211-S2500 200720', + b'\xf1\x00TMA MFC AT USA LHD 1.00 1.01 99211-S2500 210205', + b'\xf1\x00TMA MFC AT USA LHD 1.00 1.03 99211-S2500 220414', + ], + }, + CAR.HYUNDAI_SANTA_FE_HEV_2022: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00TMhe SCC FHCUP 1.00 1.00 99110-CL500 ', + b'\xf1\x00TMhe SCC FHCUP 1.00 1.01 99110-CL500 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLAC0 4TSHC102', + b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLEC0 4TSHC102', + b'\xf1\x00TM MDPS C 1.00 1.02 56310-GA000 4TSHA100', + b'\xf1\x00TM MDPS C 1.00 1.02 56310GA000\x00 4TSHA100', + b'\xf1\x00TM MDPS R 1.00 1.05 57700-CL000 4TSHP105', + b'\xf1\x00TM MDPS R 1.00 1.06 57700-CL000 4TSHP106', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00TMA MFC AT USA LHD 1.00 1.03 99211-S2500 220414', + b'\xf1\x00TMH MFC AT EUR LHD 1.00 1.06 99211-S1500 220727', + b'\xf1\x00TMH MFC AT KOR LHD 1.00 1.06 99211-S1500 220727', + b'\xf1\x00TMH MFC AT USA LHD 1.00 1.03 99211-S1500 210224', + b'\xf1\x00TMH MFC AT USA LHD 1.00 1.05 99211-S1500 220126', + b'\xf1\x00TMH MFC AT USA LHD 1.00 1.06 99211-S1500 220727', + ], + }, + CAR.HYUNDAI_SANTA_FE_PHEV_2022: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00TMhe SCC F-CUP 1.00 1.00 99110-CL500 ', + b'\xf1\x00TMhe SCC FHCUP 1.00 1.00 99110-CL500 ', + b'\xf1\x00TMhe SCC FHCUP 1.00 1.01 99110-CL500 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLAC0 4TSHC102', + b'\xf1\x00TM MDPS C 1.00 1.02 56310-CLEC0 4TSHC102', + b'\xf1\x00TM MDPS C 1.00 1.02 56310CLEC0\x00 4TSHC102', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00TMP MFC AT USA LHD 1.00 1.03 99211-S1500 210224', + b'\xf1\x00TMP MFC AT USA LHD 1.00 1.05 99211-S1500 220126', + b'\xf1\x00TMP MFC AT USA LHD 1.00 1.06 99211-S1500 220727', + ], + }, + CAR.HYUNDAI_CUSTIN_1ST_GEN: { + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00KU ESC \x01 101!\x02\x03 58910-O3200', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00KU__ SCC F-CUP 1.00 1.01 99110-O3000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00KU MDPS C 1.00 1.01 56310/O3100 4KUCC101', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00KU2 MFC AT CHN LHD 1.00 1.02 99211-O3000 220923', + ], + }, + CAR.KIA_STINGER: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CK__ SCC FHCUP 1.00 1.02 96400-J5000 ', + b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5000 ', + b'\xf1\x00CK__ SCC F_CUP 1.00 1.01 96400-J5100 ', + b'\xf1\x00CK__ SCC F_CUP 1.00 1.02 96400-J5100 ', + b'\xf1\x00CK__ SCC F_CUP 1.00 1.03 96400-J5100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00CK MDPS R 1.00 1.04 57700-J5200 4C2CL104', + b'\xf1\x00CK MDPS R 1.00 1.04 57700-J5220 4C2VL104', + b'\xf1\x00CK MDPS R 1.00 1.04 57700-J5420 4C4VL104', + b'\xf1\x00CK MDPS R 1.00 1.06 57700-J5220 4C2VL106', + b'\xf1\x00CK MDPS R 1.00 1.06 57700-J5420 4C4VL106', + b'\xf1\x00CK MDPS R 1.00 1.07 57700-J5220 4C2VL107', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CK MFC AT EUR LHD 1.00 1.03 95740-J5000 170822', + b'\xf1\x00CK MFC AT KOR LHD 1.00 1.04 95740-J5000 180504', + b'\xf1\x00CK MFC AT USA LHD 1.00 1.03 95740-J5000 170822', + b'\xf1\x00CK MFC AT USA LHD 1.00 1.04 95740-J5000 180504', + ], + }, + CAR.KIA_STINGER_2022: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CK__ SCC F-CUP 1.00 1.00 99110-J5500 ', + b'\xf1\x00CK__ SCC FHCUP 1.00 1.00 99110-J5500 ', + b'\xf1\x00CK__ SCC FHCUP 1.00 1.00 99110-J5600 ', + b'\xf1\x00CK__ SCC FHCUP 1.00 1.01 99110-J5100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5300 4C2CL503', + b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5320 4C2VL503', + b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5380 4C2VR503', + b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5520 4C4VL503', + b'\xf1\x00CK MDPS R 1.00 5.04 57700-J5320 4C2VL504', + b'\xf1\x00CK MDPS R 1.00 5.04 57700-J5520 4C4VL504', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CK MFC AT AUS RHD 1.00 1.00 99211-J5500 210622', + b'\xf1\x00CK MFC AT KOR LHD 1.00 1.00 99211-J5500 210622', + b'\xf1\x00CK MFC AT USA LHD 1.00 1.00 99211-J5500 210622', + b'\xf1\x00CK MFC AT USA LHD 1.00 1.03 99211-J5000 201209', + ], + }, + CAR.HYUNDAI_PALISADE: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00LX2 SCC FHCUP 1.00 1.04 99110-S8100 ', + b'\xf1\x00LX2_ SCC F-CU- 1.00 1.05 99110-S8100 ', + b'\xf1\x00LX2_ SCC F-CUP 1.00 1.00 99110-S8110 ', + b'\xf1\x00LX2_ SCC F-CUP 1.00 1.04 99110-S8100 ', + b'\xf1\x00LX2_ SCC F-CUP 1.00 1.05 99110-S8100 ', + b'\xf1\x00LX2_ SCC FHCU- 1.00 1.05 99110-S8100 ', + b'\xf1\x00LX2_ SCC FHCUP 1.00 1.00 99110-S8110 ', + b'\xf1\x00LX2_ SCC FHCUP 1.00 1.03 99110-S8100 ', + b'\xf1\x00LX2_ SCC FHCUP 1.00 1.04 99110-S8100 ', + b'\xf1\x00LX2_ SCC FHCUP 1.00 1.05 99110-S8100 ', + b'\xf1\x00ON__ FCA FHCU- 1.00 1.00 99110-S9110 ', + b'\xf1\x00ON__ FCA FHCUP 1.00 1.00 99110-S9110 ', + b'\xf1\x00ON__ FCA FHCUP 1.00 1.01 99110-S9110 ', + b'\xf1\x00ON__ FCA FHCUP 1.00 1.02 99110-S9100 ', + b'\xf1\x00ON__ FCA FHCUP 1.00 1.03 99110-S9100 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00LX ESC \x01 103\x19\t\x10 58910-S8360', + b'\xf1\x00LX ESC \x01 1031\t\x10 58910-S8360', + b'\xf1\x00LX ESC \x01 104 \x10\x15 58910-S8350', + b'\xf1\x00LX ESC \x01 104 \x10\x16 58910-S8360', + b'\xf1\x00LX ESC \x0b 101\x19\x03\x17 58910-S8330', + b'\xf1\x00LX ESC \x0b 101\x19\x03 58910-S8360', + b'\xf1\x00LX ESC \x0b 102\x19\x05\x07 58910-S8330', + b'\xf1\x00LX ESC \x0b 103\x19\t\x07 58910-S8330', + b'\xf1\x00LX ESC \x0b 103\x19\t\t 58910-S8350', + b'\xf1\x00LX ESC \x0b 103\x19\t\x10 58910-S8360', + b'\xf1\x00LX ESC \x0b 104 \x10\x13 58910-S8330', + b'\xf1\x00LX ESC \x0b 104 \x10\x16 58910-S8360', + b'\xf1\x00ON ESC \x01 101\x19\t\x08 58910-S9360', + b'\xf1\x00ON ESC \x01 103$\x04\x08 58910-S9360', + b'\xf1\x00ON ESC \x0b 100\x18\x12\x18 58910-S9360', + b'\xf1\x00ON ESC \x0b 101\x19\t\x05 58910-S9320', + b'\xf1\x00ON ESC \x0b 101\x19\t\x08 58910-S9360', + b'\xf1\x00ON ESC \x0b 103$\x04\x08 58910-S9360', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00LX2 MDPS C 1,00 1,03 56310-S8020 4LXDC103', + b'\xf1\x00LX2 MDPS C 1.00 1.03 56310-S8000 4LXDC103', + b'\xf1\x00LX2 MDPS C 1.00 1.03 56310-S8020 4LXDC103', + b'\xf1\x00LX2 MDPS C 1.00 1.03 56310-XX000 4LXDC103', + b'\xf1\x00LX2 MDPS C 1.00 1.04 56310-S8000 4LXDC104', + b'\xf1\x00LX2 MDPS C 1.00 1.04 56310-S8020 4LXDC104', + b'\xf1\x00LX2 MDPS C 1.00 1.04 56310-S8420 4LXDC104', + b'\xf1\x00LX2 MDPS R 1.00 1.02 56370-S8300 9318', + b'\xf1\x00ON MDPS C 1.00 1.00 56340-S9000 8B13', + b'\xf1\x00ON MDPS C 1.00 1.01 56340-S9000 9201', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00LX2 MFC AT KOR LHD 1.00 1.08 99211-S8100 200903', + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.00 99211-S8110 210226', + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.03 99211-S8100 190125', + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.05 99211-S8100 190909', + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.07 99211-S8100 200422', + b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.08 99211-S8100 200903', + b'\xf1\x00ON MFC AT USA LHD 1.00 1.01 99211-S9100 181105', + b'\xf1\x00ON MFC AT USA LHD 1.00 1.03 99211-S9100 200720', + b'\xf1\x00ON MFC AT USA LHD 1.00 1.04 99211-S9100 211227', + ], + }, + CAR.HYUNDAI_VELOSTER: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JS__ SCC H-CUP 1.00 1.02 95650-J3200 ', + b'\xf1\x00JS__ SCC HNCUP 1.00 1.02 95650-J3100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00JSL MDPS C 1.00 1.03 56340-J3000 8308', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JS LKAS AT KOR LHD 1.00 1.03 95740-J3000 K33', + b'\xf1\x00JS LKAS AT USA LHD 1.00 1.02 95740-J3000 K32', + ], + }, + CAR.GENESIS_G70: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00IK__ SCC F-CUP 1.00 1.01 96400-G9100 ', + b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00IK MDPS R 1.00 1.06 57700-G9420 4I4VL106', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00IK MFC AT USA LHD 1.00 1.01 95740-G9000 170920', + ], + }, + CAR.GENESIS_G70_2020: { + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00IK MDPS R 1.00 1.06 57700-G9220 4I2VL106', + b'\xf1\x00IK MDPS R 1.00 1.07 57700-G9220 4I2VL107', + b'\xf1\x00IK MDPS R 1.00 1.07 57700-G9420 4I4VL107', + b'\xf1\x00IK MDPS R 1.00 1.08 57700-G9200 4I2CL108', + b'\xf1\x00IK MDPS R 1.00 1.08 57700-G9420 4I4VL108', + b'\xf1\x00IK MDPS R 1.00 5.09 57700-G9520 4I4VL509', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00IK__ SCC F-CUP 1.00 1.01 96400-G9100 ', + b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 ', + b'\xf1\x00IK__ SCC F-CUP 1.00 1.02 96400-G9100 \xf1\xa01.02', + b'\xf1\x00IK__ SCC FHCUP 1.00 1.00 99110-G9300 ', + b'\xf1\x00IK__ SCC FHCUP 1.00 1.02 96400-G9000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00IK MFC AT KOR LHD 1.00 1.01 95740-G9000 170920', + b'\xf1\x00IK MFC AT USA LHD 1.00 1.01 95740-G9000 170920', + b'\xf1\x00IK MFC AT USA LHD 1.00 1.04 99211-G9000 220401', + ], + }, + CAR.GENESIS_G80: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DH__ SCC F-CU- 1.00 1.01 96400-B1110 ', + b'\xf1\x00DH__ SCC F-CUP 1.00 1.01 96400-B1120 ', + b'\xf1\x00DH__ SCC F-CUP 1.00 1.02 96400-B1120 ', + b'\xf1\x00DH__ SCC FHCUP 1.00 1.01 96400-B1110 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DH LKAS AT EUR LHD 1.01 1.01 95895-B1500 161014', + b'\xf1\x00DH LKAS AT KOR LHD 1.01 1.01 95895-B1500 161014', + b'\xf1\x00DH LKAS AT KOR LHD 1.01 1.02 95895-B1500 170810', + b'\xf1\x00DH LKAS AT USA LHD 1.01 1.01 95895-B1500 161014', + b'\xf1\x00DH LKAS AT USA LHD 1.01 1.02 95895-B1500 170810', + b'\xf1\x00DH LKAS AT USA LHD 1.01 1.03 95895-B1500 180713', + b'\xf1\x00DH LKAS AT USA LHD 1.01 1.04 95895-B1500 181213', + ], + }, + CAR.GENESIS_G80_2ND_GEN_FL: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00RG3_ SCC ----- 1.00 1.02 99110-T1120 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00RG3 MFC AT USA LHD 1.00 1.01 99211-T1200 230607', + ], + }, + CAR.GENESIS_G90: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00HI__ SCC F-CUP 1.00 1.01 96400-D2100 ', + b'\xf1\x00HI__ SCC FHCUP 1.00 1.02 99110-D2100 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00HI LKAS AT USA LHD 1.00 1.00 95895-D2020 160302', + b'\xf1\x00HI LKAS AT USA LHD 1.00 1.00 95895-D2030 170208', + b'\xf1\x00HI LKAS AT USA LHD 1.00 1.01 95895-D2030 170811', + b'\xf1\x00HI MFC AT USA LHD 1.00 1.03 99211-D2000 190831', + ], + }, + CAR.HYUNDAI_KONA: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00OS__ SCC F-CUP 1.00 1.00 95655-J9200 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00OS MDPS C 1.00 1.05 56310J9030\x00 4OSDC105', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00OS9 LKAS AT USA LHD 1.00 1.00 95740-J9300 g21', + ], + }, + CAR.KIA_CEED: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CD__ SCC F-CUP 1.00 1.00 99110-J7500 ', + b'\xf1\x00CD__ SCC F-CUP 1.00 1.02 99110-J7000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00CD MDPS C 1.00 1.06 56310-XX000 4CDEC106', + b'\xf1\x00CDT MDPS C 1.00 1.00 56310-XX000 4CDTC100', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CD LKAS AT EUR LHD 1.00 1.01 99211-J7000 B40', + b'\xf1\x00CDT LKAS AT EUR LHD 1.00 1.01 99211-J7210 521', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00CD ESC \x03 102\x18\x08\x05 58920-J7350', + b'\xf1\x00CD ESC \x0b 101 \x10\x03 58910-J7AC0', + ], + }, + CAR.KIA_FORTE: { + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00BD MDPS C 1.00 1.02 56310-XX000 4BD2C102', + b'\xf1\x00BD MDPS C 1.00 1.08 56310/M6300 4BDDC108', + b'\xf1\x00BD MDPS C 1.00 1.08 56310M6300\x00 4BDDC108', + b'\xf1\x00BDm MDPS C A.01 1.01 56310M7800\x00 4BPMC101', + b'\xf1\x00BDm MDPS C A.01 1.03 56310M7800\x00 4BPMC103', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00BD LKAS AT USA LHD 1.00 1.04 95740-M6000 J33', + b'\xf1\x00BDP LKAS AT USA LHD 1.00 1.05 99211-M6500 744', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00BDPE_SCC FHCUPC 1.00 1.04 99110-M6500\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'\xf1\x00BD__ SCC H-CUP 1.00 1.02 99110-M6000 ', + ], + }, + CAR.KIA_K5_2021: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DL3_ SCC F-CUP 1.00 1.03 99110-L2100 ', + b'\xf1\x00DL3_ SCC FHCUP 1.00 1.03 99110-L2000 ', + b'\xf1\x00DL3_ SCC FHCUP 1.00 1.03 99110-L2100 ', + b'\xf1\x00DL3_ SCC FHCUP 1.00 1.04 99110-L2100 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3110 4DLAC101', + b'\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3220 4DLAC101', + b'\xf1\x00DL3 MDPS C 1.00 1.01 56310L3220\x00 4DLAC101', + b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L2220 4DLDC102', + b'\xf1\x00DL3 MDPS C 1.00 1.02 56310L3220\x00 4DLAC102', + b'\xf1\x00DL3 MDPS R 1.00 1.02 57700-L3000 4DLAP102', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DL3 MFC AT KOR LHD 1.00 1.04 99210-L2000 210527', + b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.03 99210-L3000 200915', + b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.04 99210-L3000 210208', + b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.05 99210-L3000 211222', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00DL ESC \x01 104 \x07\x12 58910-L2200', + b'\xf1\x00DL ESC \x03 100 \x08\x02 58910-L3600', + b'\xf1\x00DL ESC \x06 101 \x04\x02 58910-L3200', + b'\xf1\x00DL ESC \x06 102 \x07\x02 58910-L3200', + b'\xf1\x00DL ESC \x06 103"\x08\x06 58910-L3200', + b'\xf1\x00DL ESC \t 100 \x06\x02 58910-L3800', + b'\xf1\x00DL ESC \t 101 \x07\x02 58910-L3800', + b'\xf1\x00DL ESC \t 102"\x08\x10 58910-L3800', + ], + }, + CAR.KIA_K5_HEV_2020: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DLhe SCC FHCUP 1.00 1.02 99110-L7000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L7000 4DLHC102', + b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L7220 4DLHC102', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.01 99210-L2000 191022', + b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.02 99210-L2000 200309', + b'\xf1\x00DL3HMFC AT KOR LHD 1.00 1.04 99210-L2000 210527', + ], + }, + CAR.HYUNDAI_KONA_EV: { + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00OS IEB \x01 212 \x11\x13 58520-K4000', + b'\xf1\x00OS IEB \x02 210 \x02\x14 58520-K4000', + b'\xf1\x00OS IEB \x02 212 \x11\x13 58520-K4000', + b'\xf1\x00OS IEB \x03 210 \x02\x14 58520-K4000', + b'\xf1\x00OS IEB \x03 211 \x04\x02 58520-K4000', + b'\xf1\x00OS IEB \x03 212 \x11\x13 58520-K4000', + b'\xf1\x00OS IEB \x04 212 \x11\x13 58520-K4000', + b'\xf1\x00OS IEB \r 105\x18\t\x18 58520-K4000', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00OE2 LKAS AT EUR LHD 1.00 1.00 95740-K4200 200', + b'\xf1\x00OSE LKAS AT AUS RHD 1.00 1.00 95740-K4300 W50', + b'\xf1\x00OSE LKAS AT EUR LHD 1.00 1.00 95740-K4100 W40', + b'\xf1\x00OSE LKAS AT EUR RHD 1.00 1.00 95740-K4100 W40', + b'\xf1\x00OSE LKAS AT KOR LHD 1.00 1.00 95740-K4100 W40', + b'\xf1\x00OSE LKAS AT KOR LHD 1.00 1.00 95740-K4300 W50', + b'\xf1\x00OSE LKAS AT USA LHD 1.00 1.00 95740-K4100 W40', + b'\xf1\x00OSE LKAS AT USA LHD 1.00 1.00 95740-K4300 W50', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00OS MDPS C 1.00 1.03 56310/K4550 4OEDC103', + b'\xf1\x00OS MDPS C 1.00 1.04 56310-XX000 4OEDC104', + b'\xf1\x00OS MDPS C 1.00 1.04 56310/K4550 4OEDC104', + b'\xf1\x00OS MDPS C 1.00 1.04 56310K4000\x00 4OEDC104', + b'\xf1\x00OS MDPS C 1.00 1.04 56310K4050\x00 4OEDC104', + b'\xf1\x00OS MDPS C 1.00 1.05 56310K4000\x00 4OEDC105', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00OSev SCC F-CUP 1.00 1.00 99110-K4000 ', + b'\xf1\x00OSev SCC F-CUP 1.00 1.00 99110-K4100 ', + b'\xf1\x00OSev SCC F-CUP 1.00 1.01 99110-K4000 ', + b'\xf1\x00OSev SCC FNCUP 1.00 1.01 99110-K4000 ', + ], + }, + CAR.HYUNDAI_KONA_EV_2022: { + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00OS IEB \x02 102"\x05\x16 58520-K4010', + b'\xf1\x00OS IEB \x03 101 \x11\x13 58520-K4010', + b'\xf1\x00OS IEB \x03 102"\x05\x16 58520-K4010', + b'\xf1\x00OS IEB \r 102"\x05\x16 58520-K4010', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00OSP LKA AT AUS RHD 1.00 1.04 99211-J9200 904', + b'\xf1\x00OSP LKA AT CND LHD 1.00 1.02 99211-J9110 802', + b'\xf1\x00OSP LKA AT EUR LHD 1.00 1.04 99211-J9200 904', + b'\xf1\x00OSP LKA AT EUR RHD 1.00 1.02 99211-J9110 802', + b'\xf1\x00OSP LKA AT EUR RHD 1.00 1.04 99211-J9200 904', + b'\xf1\x00OSP LKA AT USA LHD 1.00 1.04 99211-J9200 904', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00OSP MDPS C 1.00 1.02 56310-K4271 4OEPC102', + b'\xf1\x00OSP MDPS C 1.00 1.02 56310/K4271 4OEPC102', + b'\xf1\x00OSP MDPS C 1.00 1.02 56310/K4970 4OEPC102', + b'\xf1\x00OSP MDPS C 1.00 1.02 56310K4260\x00 4OEPC102', + b'\xf1\x00OSP MDPS C 1.00 1.02 56310K4261\x00 4OEPC102', + b'\xf1\x00OSP MDPS C 1.00 1.02 56310K4971\x00 4OEPC102', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00YB__ FCA ----- 1.00 1.01 99110-K4500 \x00\x00\x00', + ], + }, + CAR.HYUNDAI_KONA_EV_2ND_GEN: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00SXev RDR ----- 1.00 1.00 99110-BF000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410', + ], + }, + CAR.KIA_NIRO_EV: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4000 ', + b'\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4100 ', + b'\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4500 ', + b'\xf1\x00DEev SCC F-CUP 1.00 1.00 99110-Q4600 ', + b'\xf1\x00DEev SCC F-CUP 1.00 1.02 96400-Q4000 ', + b'\xf1\x00DEev SCC F-CUP 1.00 1.02 96400-Q4100 ', + b'\xf1\x00DEev SCC F-CUP 1.00 1.03 96400-Q4100 ', + b'\xf1\x00DEev SCC FHCUP 1.00 1.00 99110-Q4600 ', + b'\xf1\x00DEev SCC FHCUP 1.00 1.03 96400-Q4000 ', + b'\xf1\x00DEev SCC FNCUP 1.00 1.00 99110-Q4600 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DE MDPS C 1.00 1.04 56310Q4100\x00 4DEEC104', + b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4000\x00 4DEEC105', + b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4100\x00 4DEEC105', + b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4150\x00 4DEEC105', + b'\xf1\x00DE MDPS C 1.00 1.05 56310Q4200\x00 4DEEC105', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.00 99211-Q4000 191211', + b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.00 99211-Q4100 200706', + b'\xf1\x00DEE MFC AT EUR LHD 1.00 1.03 95740-Q4000 180821', + b'\xf1\x00DEE MFC AT EUR RHD 1.00 1.00 99211-Q4000 191211', + b'\xf1\x00DEE MFC AT KOR LHD 1.00 1.02 95740-Q4000 180705', + b'\xf1\x00DEE MFC AT KOR LHD 1.00 1.03 95740-Q4000 180821', + b'\xf1\x00DEE MFC AT USA LHD 1.00 1.00 99211-Q4000 191211', + b'\xf1\x00DEE MFC AT USA LHD 1.00 1.01 99211-Q4500 210428', + b'\xf1\x00DEE MFC AT USA LHD 1.00 1.02 99211-Q4100 201218', + b'\xf1\x00DEE MFC AT USA LHD 1.00 1.03 95740-Q4000 180821', + ], + }, + CAR.KIA_NIRO_EV_2ND_GEN: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00SG2_ RDR ----- 1.00 1.01 99110-AT000 ', + b'\xf1\x00SG__ RDR ----- 1.00 1.00 99110-AT200 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00SG2EMFC AT EUR LHD 1.00 1.00 99211-AT200 240315', + b'\xf1\x00SG2EMFC AT EUR LHD 1.01 1.09 99211-AT000 220801', + b'\xf1\x00SG2EMFC AT USA LHD 1.00 1.00 99211-AT100 230216', + b'\xf1\x00SG2EMFC AT USA LHD 1.00 1.00 99211-AT200 240401', + b'\xf1\x00SG2EMFC AT USA LHD 1.01 1.09 99211-AT000 220801', + ], + }, + CAR.KIA_NIRO_PHEV: { + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DE MDPS C 1.00 1.01 56310G5520\x00 4DEPC101', + b'\xf1\x00DE MDPS C 1.00 1.09 56310G5301\x00 4DEHC109', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DEH MFC AT USA LHD 1.00 1.00 95740-G5010 170117', + b'\xf1\x00DEP MFC AT USA LHD 1.00 1.00 95740-G5010 170117', + b'\xf1\x00DEP MFC AT USA LHD 1.00 1.01 95740-G5010 170424', + b'\xf1\x00DEP MFC AT USA LHD 1.00 1.05 99211-G5000 190826', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DEhe SCC F-CUP 1.00 1.02 99110-G5100 ', + b'\xf1\x00DEhe SCC FHCUP 1.00 1.02 99110-G5100 ', + b'\xf1\x00DEhe SCC H-CUP 1.01 1.02 96400-G5100 ', + ], + }, + CAR.KIA_NIRO_PHEV_2022: { + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DE MDPS C 1.00 1.01 56310G5520\x00 4DEPC101', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DEP MFC AT USA LHD 1.00 1.00 99211-G5500 210428', + b'\xf1\x00DEP MFC AT USA LHD 1.00 1.06 99211-G5000 201028', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DEhe SCC F-CUP 1.00 1.00 99110-G5600 ', + b'\xf1\x00DEhe SCC FHCUP 1.00 1.00 99110-G5600 ', + ], + }, + CAR.KIA_NIRO_HEV_2021: { + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DE MDPS C 1.00 1.01 56310G5520\x00 4DEPC101', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DEH MFC AT KOR LHD 1.00 1.04 99211-G5000 190516', + b'\xf1\x00DEH MFC AT USA LHD 1.00 1.00 99211-G5500 210428', + b'\xf1\x00DEH MFC AT USA LHD 1.00 1.06 99211-G5000 201028', + b'\xf1\x00DEH MFC AT USA LHD 1.00 1.07 99211-G5000 201221', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DEhe SCC FHCUP 1.00 1.00 99110-G5600 ', + b'\xf1\x00DEhe SCC FHCUP 1.00 1.01 99110-G5000 ', + ], + }, + CAR.KIA_SELTOS: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00SP2_ SCC FHCUP 1.01 1.05 99110-Q5100 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00SP ESC \x07 101\x19\t\x05 58910-Q5450', + b'\xf1\x00SP ESC \t 101\x19\t\x05 58910-Q5450', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00SP2 MDPS C 1.00 1.04 56300Q5200 ', + b'\xf1\x00SP2 MDPS C 1.01 1.05 56300Q5200 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00SP2 MFC AT USA LHD 1.00 1.04 99210-Q5000 191114', + b'\xf1\x00SP2 MFC AT USA LHD 1.00 1.05 99210-Q5000 201012', + ], + }, + CAR.KIA_OPTIMA_G4: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JF__ SCC F-CUP 1.00 1.00 96400-D4100 ', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00JF ESC \t 17 \x16\x06# 58920-D4180', + b'\xf1\x00JF ESC \x0f 16 \x16\x06\x17 58920-D5080', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JFWGN LDWS AT USA LHD 1.00 1.02 95895-D4100 G21', + b'\xf1\x00JFWGN LKAS AT EUR LHD 1.00 1.01 95895-D4100 G20', + ], + }, + CAR.KIA_OPTIMA_G4_FL: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JF__ SCC F-CUP 1.00 1.00 96400-D4110 ', + ], + (Ecu.abs, 0x7d1, None): [ + b"\xf1\x00JF ESC \t 11 \x18\x03' 58920-D5260", + b'\xf1\x00JF ESC \x0b 11 \x18\x030 58920-D5180', + b'\xf1\x00JF ESC \x0c 11 \x18\x030 58920-D5180', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JFA LKAS AT USA LHD 1.00 1.00 95895-D5001 h32', + b'\xf1\x00JFA LKAS AT USA LHD 1.00 1.00 95895-D5100 h32', + ], + }, + CAR.KIA_OPTIMA_H: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JFhe SCC FNCUP 1.00 1.00 96400-A8000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JFP LKAS AT EUR LHD 1.00 1.03 95895-A8100 160711', + ], + }, + CAR.KIA_OPTIMA_H_G4_FL: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JFhe SCC FHCUP 1.00 1.01 99110-A8500 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JFH MFC AT KOR LHD 1.00 1.01 95895-A8200 180323', + ], + }, + CAR.HYUNDAI_ELANTRA: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00AD LKAS AT USA LHD 1.01 1.01 95895-F2000 251', + b'\xf1\x00ADP LKAS AT USA LHD 1.00 1.03 99211-F2000 X31', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00AD ESC \x11 11 \x18\x05\x06 58910-F2840', + b'\xf1\x00AD ESC \x11 12 \x15\t\t 58920-F2810', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00AD__ SCC H-CUP 1.00 1.00 99110-F2100 ', + b'\xf1\x00AD__ SCC H-CUP 1.00 1.01 96400-F2100 ', + ], + }, + CAR.HYUNDAI_ELANTRA_GT_I30: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00PD LKAS AT KOR LHD 1.00 1.02 95740-G3000 A51', + b'\xf1\x00PD LKAS AT USA LHD 1.00 1.02 95740-G3000 A51', + b'\xf1\x00PD LKAS AT USA LHD 1.01 1.01 95740-G3100 A54', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00PD MDPS C 1.00 1.00 56310G3300\x00 4PDDC100', + b'\xf1\x00PD MDPS C 1.00 1.03 56310/G3300 4PDDC103', + b'\xf1\x00PD MDPS C 1.00 1.04 56310/G3300 4PDDC104', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00PD ESC \t 104\x18\t\x03 58920-G3350', + b'\xf1\x00PD ESC \x0b 103\x17\x110 58920-G3350', + b'\xf1\x00PD ESC \x0b 104\x18\t\x03 58920-G3350', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00PD__ SCC F-CUP 1.00 1.00 96400-G3300 ', + b'\xf1\x00PD__ SCC F-CUP 1.01 1.00 96400-G3100 ', + b'\xf1\x00PD__ SCC FNCUP 1.01 1.00 96400-G3000 ', + ], + }, + CAR.HYUNDAI_ELANTRA_2021: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CN7_ SCC F-CUP 1.00 1.01 99110-AA000 ', + b'\xf1\x00CN7_ SCC FHCUP 1.00 1.01 99110-AA000 ', + b'\xf1\x00CN7_ SCC FNCUP 1.00 1.01 99110-AA000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00CN7 MDPS C 1.00 1.06 56310/AA050 4CNDC106', + b'\xf1\x00CN7 MDPS C 1.00 1.06 56310/AA070 4CNDC106', + b'\xf1\x00CN7 MDPS C 1.00 1.06 56310AA050\x00 4CNDC106', + b'\xf1\x00CN7 MDPS C 1.00 1.07 56310AA050\x00 4CNDC107', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.00 99210-AB000 200819', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.01 99210-AB000 210205', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.02 99210-AB000 220111', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.03 99210-AA000 200819', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.03 99210-AB000 220426', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.06 99210-AA000 220111', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.07 99210-AA000 220426', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.08 99210-AA000 220728', + b'\xf1\x00CN7 MFC AT USA LHD 1.00 1.09 99210-AA000 221108', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00CN ESC \t 101 \x10\x03 58910-AB800', + b'\xf1\x00CN ESC \t 104 \x08\x03 58910-AA800', + b'\xf1\x00CN ESC \t 105 \x10\x03 58910-AA800', + ], + }, + CAR.HYUNDAI_ELANTRA_HEV_2021: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CN7HMFC AT USA LHD 1.00 1.03 99210-AA000 200819', + b'\xf1\x00CN7HMFC AT USA LHD 1.00 1.05 99210-AA000 210930', + b'\xf1\x00CN7HMFC AT USA LHD 1.00 1.07 99210-AA000 220426', + b'\xf1\x00CN7HMFC AT USA LHD 1.00 1.08 99210-AA000 220728', + b'\xf1\x00CN7HMFC AT USA LHD 1.00 1.09 99210-AA000 221108', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CNhe SCC FHCUP 1.00 1.01 99110-BY000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00CN7 MDPS C 1.00 1.02 56310/BY050 4CNHC102', + b'\xf1\x00CN7 MDPS C 1.00 1.03 56310/BY050 4CNHC103', + b'\xf1\x00CN7 MDPS C 1.00 1.03 56310BY050\x00 4CNHC103', + b'\xf1\x00CN7 MDPS C 1.00 1.03 56310BY0500 4CNHC103', + b'\xf1\x00CN7 MDPS C 1.00 1.04 56310BY050\x00 4CNHC104', + ], + }, + CAR.HYUNDAI_KONA_HEV: { + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00OS IEB \x01 104 \x11 58520-CM000', + b'\xf1\x00OS IEB \x03 104 \x11 58520-CM000', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00OShe SCC F-CUP 1.00 1.01 99110-CM000 ', + b'\xf1\x00OShe SCC FNCUP 1.00 1.01 99110-CM000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00OS MDPS C 1.00 1.00 56310CM020\x00 4OHDC100', + b'\xf1\x00OS MDPS C 1.00 1.00 56310CM030\x00 4OHDC100', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00OSH LKAS AT EUR LHD 1.00 1.01 95740-CM000 l31', + b'\xf1\x00OSH LKAS AT KOR LHD 1.00 1.01 95740-CM000 l31', + ], + }, + CAR.HYUNDAI_SONATA_HYBRID: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00DNhe SCC F-CUP 1.00 1.02 99110-L5000 ', + b'\xf1\x00DNhe SCC FHCUP 1.00 1.00 99110-L5000 ', + b'\xf1\x00DNhe SCC FHCUP 1.00 1.02 99110-L5000 ', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00DN8 MDPS C 1.00 1.01 56310-L5000 4DNHC101', + b'\xf1\x00DN8 MDPS C 1.00 1.02 56310-L5450 4DNHC102', + b'\xf1\x00DN8 MDPS C 1.00 1.02 56310-L5500 4DNHC102', + b'\xf1\x00DN8 MDPS C 1.00 1.03 56310-L5450 4DNHC103', + b'\xf1\x00DN8 MDPS C 1.00 1.03 56310L5450\x00 4DNHC104', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00DN8HMFC AT KOR LHD 1.00 1.03 99211-L1000 190705', + b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.04 99211-L1000 191016', + b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.05 99211-L1000 201109', + b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.06 99211-L1000 210325', + b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.07 99211-L1000 211223', + ], + }, + CAR.KIA_SORENTO: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00UMP LKAS AT AUS RHD 1.00 1.00 96400-C6550 S30', + b'\xf1\x00UMP LKAS AT KOR LHD 1.00 1.00 95740-C5550 S30', + b'\xf1\x00UMP LKAS AT USA LHD 1.00 1.00 95740-C6550 d00', + b'\xf1\x00UMP LKAS AT USA LHD 1.01 1.01 95740-C6550 d01', + ], + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00UM ESC \x02 12 \x18\x05\x05 58910-C6300', + b'\xf1\x00UM ESC \x0c 12 \x18\x05\x06 58910-C6330', + b'\xf1\x00UM ESC \x13 12 \x17\x07\x05 58910-C5320', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00UM__ SCC F-CUP 1.00 1.00 96400-C5500 ', + b'\xf1\x00UM__ SCC F-CUP 1.00 1.00 96400-C6500 ', + ], + }, + CAR.KIA_EV6: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CV1 MFC AT EUR LHD 1.00 1.05 99210-CV000 211027', + b'\xf1\x00CV1 MFC AT EUR LHD 1.00 1.06 99210-CV000 220328', + b'\xf1\x00CV1 MFC AT EUR RHD 1.00 1.00 99210-CV100 220630', + b'\xf1\x00CV1 MFC AT KOR LHD 1.00 1.00 99210-CV100 220630', + b'\xf1\x00CV1 MFC AT KOR LHD 1.00 1.00 99210-CV200 230510', + b'\xf1\x00CV1 MFC AT KOR LHD 1.00 1.04 99210-CV000 210823', + b'\xf1\x00CV1 MFC AT KOR LHD 1.00 1.05 99210-CV000 211027', + b'\xf1\x00CV1 MFC AT KOR LHD 1.00 1.06 99210-CV000 220328', + b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.00 99210-CV100 220630', + b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.00 99210-CV200 230510', + b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.05 99210-CV000 211027', + b'\xf1\x00CV1 MFC AT USA LHD 1.00 1.06 99210-CV000 220328', + ], + }, + CAR.HYUNDAI_IONIQ_5: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NE1_ RDR ----- 1.00 1.00 99110-GI000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NE1 MFC AT CAN LHD 1.00 1.01 99211-GI010 211007', + b'\xf1\x00NE1 MFC AT CAN LHD 1.00 1.05 99211-GI010 220614', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.00 99211-GI100 230915', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.01 99211-GI010 211007', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.01 99211-GI100 240110', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.02 99211-GI010 211206', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.03 99211-GI010 220401', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.06 99211-GI000 210813', + b'\xf1\x00NE1 MFC AT EUR LHD 1.00 1.06 99211-GI010 230110', + b'\xf1\x00NE1 MFC AT EUR RHD 1.00 1.01 99211-GI010 211007', + b'\xf1\x00NE1 MFC AT EUR RHD 1.00 1.01 99211-GI100 240110', + b'\xf1\x00NE1 MFC AT EUR RHD 1.00 1.02 99211-GI010 211206', + b'\xf1\x00NE1 MFC AT IND RHD 1.00 1.07 99211-GI010 230620', + b'\xf1\x00NE1 MFC AT KOR LHD 1.00 1.00 99211-GI020 230719', + b'\xf1\x00NE1 MFC AT KOR LHD 1.00 1.01 99211-GI010 211007', + b'\xf1\x00NE1 MFC AT KOR LHD 1.00 1.05 99211-GI010 220614', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI020 230719', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.00 99211-GI100 230915', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.01 99211-GI010 211007', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.01 99211-GI100 240110', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.02 99211-GI010 211206', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.03 99211-GI010 220401', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.05 99211-GI010 220614', + b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110', + ], + }, + CAR.HYUNDAI_IONIQ_6: { + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ', + b'\xf1\x00CE__ RDR ----- 1.00 1.02 99110-KL000 ', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00CE MFC AT CAN LHD 1.00 1.04 99211-KL000 221213', + b'\xf1\x00CE MFC AT EUR LHD 1.00 1.03 99211-KL000 221011', + b'\xf1\x00CE MFC AT EUR LHD 1.00 1.04 99211-KL000 221213', + b'\xf1\x00CE MFC AT USA LHD 1.00 1.04 99211-KL000 221213', + b'\xf1\x00CE MFC AT USA LHD 1.00 1.06 99211-KL000 230915', + ], + }, + CAR.HYUNDAI_TUCSON_4TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N9220 14K', + b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N9260 14Y', + b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.01 99211-N9100 14A', + b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N9220 14K', + b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 2.02 99211-N9000 14E', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9210 14G', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9220 14K', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9240 14Q', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9250 14W', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N9260 14Y', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N9100 14A', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N9240 14T', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NX4__ 1.00 1.00 99110-N9100 ', + b'\xf1\x00NX4__ 1.00 1.01 99110-N9000 ', + b'\xf1\x00NX4__ 1.00 1.02 99110-N9000 ', + b'\xf1\x00NX4__ 1.01 1.00 99110-N9100 ', + ], + }, + CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW000 14M', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW010 14X', + b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW020 14Z', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NX4__ 1.00 1.00 99110-K5000 ', + b'\xf1\x00NX4__ 1.01 1.00 99110-K5000 ', + ], + }, + CAR.KIA_SPORTAGE_5TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00NQ5 FR_CMR AT AUS RHD 1.00 1.00 99211-P1040 663', + b'\xf1\x00NQ5 FR_CMR AT EUR LHD 1.00 1.00 99211-P1040 663', + b'\xf1\x00NQ5 FR_CMR AT GEN LHD 1.00 1.00 99211-P1040 663', + b'\xf1\x00NQ5 FR_CMR AT GEN LHD 1.00 1.00 99211-P1060 665', + b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1030 662', + b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1040 663', + b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1060 665', + b'\xf1\x00NQ5 FR_CMR AT USA LHD 1.00 1.00 99211-P1070 690', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00NQ5__ 1.00 1.02 99110-P1000 ', + b'\xf1\x00NQ5__ 1.00 1.03 99110-CH000 ', + b'\xf1\x00NQ5__ 1.00 1.03 99110-P1000 ', + b'\xf1\x00NQ5__ 1.01 1.03 99110-CH000 ', + b'\xf1\x00NQ5__ 1.01 1.03 99110-P1000 ', + ], + }, + CAR.GENESIS_GV70_1ST_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.02 99211-IY000 230627', + b'\xf1\x00JK1 MFC AT CAN LHD 1.00 1.04 99211-AR100 210204', + b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.01 99211-AR200 220125', + b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.01 99211-AR300 220125', + b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.02 99211-IY000 230627', + b'\xf1\x00JK1 MFC AT USA LHD 1.00 1.04 99211-AR000 210204', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JK1_ SCC ----- 1.00 1.02 99110-AR100 ', + b'\xf1\x00JK1_ SCC FHCUP 1.00 1.00 99110-AR200 ', + b'\xf1\x00JK1_ SCC FHCUP 1.00 1.00 99110-AR300 ', + b'\xf1\x00JK1_ SCC FHCUP 1.00 1.00 99110-IY000 ', + b'\xf1\x00JK1_ SCC FHCUP 1.00 1.02 99110-AR000 ', + ], + }, + CAR.GENESIS_GV70_ELECTRIFIED_1ST_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JK1EMFC AT AUS RHD 1.00 1.01 99211-DS100 220125', + b'\xf1\x00JK1EMFC AT USA LHD 1.00 1.00 99211-IT100 220919', + b'\xf1\x00JK1EMFC AT USA LHD 1.00 1.01 99211-IT100 230628', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JKev SCC ----- 1.00 1.01 99110-DS000 ', + ], + }, + CAR.GENESIS_GV60_EV_1ST_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JW1 MFC AT AUS RHD 1.00 1.03 99211-CU100 221118', + b'\xf1\x00JW1 MFC AT USA LHD 1.00 1.02 99211-CU000 211215', + b'\xf1\x00JW1 MFC AT USA LHD 1.00 1.02 99211-CU100 211215', + b'\xf1\x00JW1 MFC AT USA LHD 1.00 1.03 99211-CU000 221118', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JW1_ RDR ----- 1.00 1.00 99110-CU000 ', + ], + }, + CAR.KIA_SORENTO_4TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00MQ4 MFC AT USA LHD 1.00 1.00 99210-R5100 221019', + b'\xf1\x00MQ4 MFC AT USA LHD 1.00 1.03 99210-R5000 200903', + b'\xf1\x00MQ4 MFC AT USA LHD 1.00 1.05 99210-R5000 210623', + b'\xf1\x00MQ4 MFC AT USA LHD 1.00 1.06 99210-R5000 211216', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MQ4_ SCC F-CUP 1.00 1.06 99110-P2000 ', + b'\xf1\x00MQ4_ SCC FHCUP 1.00 1.00 99110-R5000 ', + b'\xf1\x00MQ4_ SCC FHCUP 1.00 1.06 99110-P2000 ', + b'\xf1\x00MQ4_ SCC FHCUP 1.00 1.08 99110-P2000 ', + ], + }, + CAR.KIA_SORENTO_HEV_4TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00MQ4HMFC AT KOR LHD 1.00 1.04 99210-P2000 200330', + b'\xf1\x00MQ4HMFC AT KOR LHD 1.00 1.12 99210-P2000 230331', + b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.10 99210-P2000 210406', + b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.11 99210-P2000 211217', + b'\xf1\x00MQ4HMFC AT USA LHD 1.00 1.12 99210-P2000 230331', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00MQhe SCC FHCUP 1.00 1.04 99110-P4000 ', + b'\xf1\x00MQhe SCC FHCUP 1.00 1.06 99110-P4000 ', + b'\xf1\x00MQhe SCC FHCUP 1.00 1.07 99110-P4000 ', + ], + }, + CAR.KIA_NIRO_HEV_2ND_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00SG2HMFC AT USA LHD 1.01 1.08 99211-AT000 220531', + b'\xf1\x00SG2HMFC AT USA LHD 1.01 1.09 99211-AT000 220801', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00SG2_ RDR ----- 1.00 1.01 99110-AT000 ', + ], + }, + CAR.GENESIS_GV80: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00JX1 MFC AT USA LHD 1.00 1.02 99211-T6110 220513', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00JX1_ SCC FHCUP 1.00 1.01 99110-T6100 ', + ], + }, + CAR.KIA_CARNIVAL_4TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00KA4 MFC AT EUR LHD 1.00 1.06 99210-R0000 220221', + b'\xf1\x00KA4 MFC AT KOR LHD 1.00 1.05 99210-R0000 201221', + b'\xf1\x00KA4 MFC AT KOR LHD 1.00 1.06 99210-R0000 220221', + b'\xf1\x00KA4 MFC AT USA LHD 1.00 1.00 99210-R0100 230105', + b'\xf1\x00KA4 MFC AT USA LHD 1.00 1.01 99210-R0100 230710', + b'\xf1\x00KA4 MFC AT USA LHD 1.00 1.05 99210-R0000 201221', + b'\xf1\x00KA4 MFC AT USA LHD 1.00 1.06 99210-R0000 220221', + b'\xf1\x00KA4CMFC AT CHN LHD 1.00 1.01 99211-I4000 210525', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00KA4_ SCC F-CUP 1.00 1.03 99110-R0000 ', + b'\xf1\x00KA4_ SCC FHCUP 1.00 1.00 99110-R0100 ', + b'\xf1\x00KA4_ SCC FHCUP 1.00 1.02 99110-R0000 ', + b'\xf1\x00KA4_ SCC FHCUP 1.00 1.03 99110-R0000 ', + b'\xf1\x00KA4c SCC FHCUP 1.00 1.01 99110-I4000 ', + ], + }, + CAR.KIA_K8_HEV_1ST_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00GL3HMFC AT KOR LHD 1.00 1.03 99211-L8000 210907', + b'\xf1\x00GL3HMFC AT KOR LHD 1.00 1.04 99211-L8000 230207', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00GL3_ RDR ----- 1.00 1.02 99110-L8000 ', + ], + }, + CAR.HYUNDAI_STARIA_4TH_GEN: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00US4 MFC AT KOR LHD 1.00 1.06 99211-CG000 230524', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00US4_ RDR ----- 1.00 1.00 99110-CG000 ', + ], + }, + CAR.HYUNDAI_NEXO_1ST_GEN: { + (Ecu.abs, 0x7d1, None): [ + b'\xf1\x00FE IEB \x01 312 \x11\x13 58520-M5000', + ], + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00FE MFC AT KOR LHD 1.00 1.00 99211-M5100 201218', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00FE MDPS C 1.00 1.05 56340-M5000 9903', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00FE__ SCC FHCUP 1.00 1.05 99110-M5000 ', + ], + }, + CAR.HYUNDAI_KONA_2022: { + (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00OSP LKA AT CND LHD 1.00 1.04 99211-J9200 904', + b'\xf1\x00OSP LKA AT USA LHD 1.00 1.04 99211-J9200 904', + ], + (Ecu.eps, 0x7d4, None): [ + b'\xf1\x00OSP MDPS C 1.00 1.04 56310/J9290 4OPCC104', + b'\xf1\x00OSP MDPS C 1.00 1.04 56310/J9291 4OPCC104', + b'\xf1\x00OSP MDPS C 1.00 1.04 56310J9291\x00 4OPCC104', + ], + (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00YB__ FCA ----- 1.00 1.01 99110-J9000 \x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x00HT6WA280BLHT6VA650A1COS4N20NS1\x00\x00\x00\x00\x00\x00\x15\xf5\x87~', + b'\xf1\x00T01960BL T01E60A1 DOS2T16X4XE60NS4N\x90\xe6\xcb', + b'\xf1\x00T01G00BL T01I00A1 DOS2T16X2XI00NS0\x8c`\xff\xe7', + b'\xf1\x00T01G00BL T01I00A1 DOS2T16X4XI00NS0\x99L\xeeq', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaican.py b/opendbc_repo/opendbc/car/hyundai/hyundaican.py new file mode 100644 index 0000000000..8f3a049cd2 --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/hyundaican.py @@ -0,0 +1,217 @@ +import crcmod +from opendbc.car.hyundai.values import CAR, HyundaiFlags + +hyundai_checksum = crcmod.mkCrcFun(0x11D, initCrc=0xFD, rev=False, xorOut=0xdf) + + +def create_lkas11(packer, frame, CP, apply_torque, steer_req, + torque_fault, lkas11, sys_warning, sys_state, enabled, + left_lane, right_lane, + left_lane_depart, right_lane_depart): + values = {s: lkas11[s] for s in [ + "CF_Lkas_LdwsActivemode", + "CF_Lkas_LdwsSysState", + "CF_Lkas_SysWarning", + "CF_Lkas_LdwsLHWarning", + "CF_Lkas_LdwsRHWarning", + "CF_Lkas_HbaLamp", + "CF_Lkas_FcwBasReq", + "CF_Lkas_HbaSysState", + "CF_Lkas_FcwOpt", + "CF_Lkas_HbaOpt", + "CF_Lkas_FcwSysState", + "CF_Lkas_FcwCollisionWarning", + "CF_Lkas_FusionState", + "CF_Lkas_FcwOpt_USM", + "CF_Lkas_LdwsOpt_USM", + ]} + values["CF_Lkas_LdwsSysState"] = sys_state + values["CF_Lkas_SysWarning"] = 3 if sys_warning else 0 + values["CF_Lkas_LdwsLHWarning"] = left_lane_depart + values["CF_Lkas_LdwsRHWarning"] = right_lane_depart + values["CR_Lkas_StrToqReq"] = apply_torque + values["CF_Lkas_ActToi"] = steer_req + values["CF_Lkas_ToiFlt"] = torque_fault # seems to allow actuation on CR_Lkas_StrToqReq + values["CF_Lkas_MsgCount"] = frame % 0x10 + + if CP.carFingerprint in (CAR.HYUNDAI_SONATA, CAR.HYUNDAI_PALISADE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_NIRO_PHEV_2022, CAR.HYUNDAI_SANTA_FE, + CAR.HYUNDAI_IONIQ_EV_2020, CAR.HYUNDAI_IONIQ_PHEV, CAR.KIA_SELTOS, CAR.HYUNDAI_ELANTRA_2021, CAR.GENESIS_G70_2020, + CAR.HYUNDAI_ELANTRA_HEV_2021, CAR.HYUNDAI_SONATA_HYBRID, CAR.HYUNDAI_KONA_EV, CAR.HYUNDAI_KONA_HEV, CAR.HYUNDAI_KONA_EV_2022, + CAR.HYUNDAI_SANTA_FE_2022, CAR.KIA_K5_2021, CAR.HYUNDAI_IONIQ_HEV_2022, CAR.HYUNDAI_SANTA_FE_HEV_2022, + CAR.HYUNDAI_SANTA_FE_PHEV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_CEED, + CAR.HYUNDAI_AZERA_6TH_GEN, CAR.HYUNDAI_AZERA_HEV_6TH_GEN, CAR.HYUNDAI_CUSTIN_1ST_GEN, CAR.HYUNDAI_KONA_2022): + values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1) + values["CF_Lkas_LdwsOpt_USM"] = 2 + + # FcwOpt_USM 5 = Orange blinking car + lanes + # FcwOpt_USM 4 = Orange car + lanes + # FcwOpt_USM 3 = Green blinking car + lanes + # FcwOpt_USM 2 = Green car + lanes + # FcwOpt_USM 1 = White car + lanes + # FcwOpt_USM 0 = No car + lanes + values["CF_Lkas_FcwOpt_USM"] = 2 if enabled else 1 + + # SysWarning 4 = keep hands on wheel + # SysWarning 5 = keep hands on wheel (red) + # SysWarning 6 = keep hands on wheel (red) + beep + # Note: the warning is hidden while the blinkers are on + values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0 + + # Likely cars lacking the ability to show individual lane lines in the dash + elif CP.carFingerprint in (CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL): + # SysWarning 4 = keep hands on wheel + beep + values["CF_Lkas_SysWarning"] = 4 if sys_warning else 0 + + # SysState 0 = no icons + # SysState 1-2 = white car + lanes + # SysState 3 = green car + lanes, green steering wheel + # SysState 4 = green car + lanes + values["CF_Lkas_LdwsSysState"] = 3 if enabled else 1 + values["CF_Lkas_LdwsOpt_USM"] = 2 # non-2 changes above SysState definition + + # these have no effect + values["CF_Lkas_LdwsActivemode"] = 0 + values["CF_Lkas_FcwOpt_USM"] = 0 + + elif CP.carFingerprint == CAR.HYUNDAI_GENESIS: + # This field is actually LdwsActivemode + # Genesis and Optima fault when forwarding while engaged + values["CF_Lkas_LdwsActivemode"] = 2 + + dat = packer.make_can_msg("LKAS11", 0, values)[1] + + if CP.flags & HyundaiFlags.CHECKSUM_CRC8: + # CRC Checksum as seen on 2019 Hyundai Santa Fe + dat = dat[:6] + dat[7:8] + checksum = hyundai_checksum(dat) + elif CP.flags & HyundaiFlags.CHECKSUM_6B: + # Checksum of first 6 Bytes, as seen on 2018 Kia Sorento + checksum = sum(dat[:6]) % 256 + else: + # Checksum of first 6 Bytes and last Byte as seen on 2018 Kia Stinger + checksum = (sum(dat[:6]) + dat[7]) % 256 + + values["CF_Lkas_Chksum"] = checksum + + return packer.make_can_msg("LKAS11", 0, values) + + +def create_clu11(packer, frame, clu11, button, CP): + values = {s: clu11[s] for s in [ + "CF_Clu_CruiseSwState", + "CF_Clu_CruiseSwMain", + "CF_Clu_SldMainSW", + "CF_Clu_ParityBit1", + "CF_Clu_VanzDecimal", + "CF_Clu_Vanz", + "CF_Clu_SPEED_UNIT", + "CF_Clu_DetentOut", + "CF_Clu_RheostatLevel", + "CF_Clu_CluInfo", + "CF_Clu_AmpInfo", + "CF_Clu_AliveCnt1", + ]} + values["CF_Clu_CruiseSwState"] = button + values["CF_Clu_AliveCnt1"] = frame % 0x10 + # send buttons to camera on camera-scc based cars + bus = 2 if CP.flags & HyundaiFlags.CAMERA_SCC else 0 + return packer.make_can_msg("CLU11", bus, values) + + +def create_lfahda_mfc(packer, enabled): + values = { + "LFA_Icon_State": 2 if enabled else 0, + } + return packer.make_can_msg("LFAHDA_MFC", 0, values) + + +def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, CP): + commands = [] + + scc11_values = { + "MainMode_ACC": 1, + "TauGapSet": hud_control.leadDistanceBars, + "VSetDis": set_speed if enabled else 0, + "AliveCounterACC": idx % 0x10, + "ObjValid": 1, # close lead makes controls tighter + "ACC_ObjStatus": 1, # close lead makes controls tighter + "ACC_ObjLatPos": 0, + "ACC_ObjRelSpd": 0, + "ACC_ObjDist": 1, # close lead makes controls tighter + } + commands.append(packer.make_can_msg("SCC11", 0, scc11_values)) + + scc12_values = { + "ACCMode": 2 if enabled and long_override else 1 if enabled else 0, + "StopReq": 1 if stopping else 0, + "aReqRaw": accel, + "aReqValue": accel, # stock ramps up and down respecting jerk limit until it reaches aReqRaw + "CR_VSM_Alive": idx % 0xF, + } + + # show AEB disabled indicator on dash with SCC12 if not sending FCA messages. + # these signals also prevent a TCS fault on non-FCA cars with alpha longitudinal + if not use_fca: + scc12_values["CF_VSM_ConfMode"] = 1 + scc12_values["AEB_Status"] = 1 # AEB disabled + + scc12_dat = packer.make_can_msg("SCC12", 0, scc12_values)[1] + scc12_values["CR_VSM_ChkSum"] = 0x10 - sum(sum(divmod(i, 16)) for i in scc12_dat) % 0x10 + + commands.append(packer.make_can_msg("SCC12", 0, scc12_values)) + + scc14_values = { + "ComfortBandUpper": 0.0, # stock usually is 0 but sometimes uses higher values + "ComfortBandLower": 0.0, # stock usually is 0 but sometimes uses higher values + "JerkUpperLimit": upper_jerk, # stock usually is 1.0 but sometimes uses higher values + "JerkLowerLimit": 5.0, # stock usually is 0.5 but sometimes uses higher values + "ACCMode": 2 if enabled and long_override else 1 if enabled else 4, # stock will always be 4 instead of 0 after first disengage + "ObjGap": 2 if hud_control.leadVisible else 0, # 5: >30, m, 4: 25-30 m, 3: 20-25 m, 2: < 20 m, 0: no lead + } + commands.append(packer.make_can_msg("SCC14", 0, scc14_values)) + + # Only send FCA11 on cars where it exists on the bus + # On Camera SCC cars, FCA11 is not disabled, so we forward stock FCA11 back to the car forward hooks + if use_fca and not (CP.flags & HyundaiFlags.CAMERA_SCC): + # note that some vehicles most likely have an alternate checksum/counter definition + # https://github.com/commaai/opendbc/commit/9ddcdb22c4929baf310295e832668e6e7fcfa602 + fca11_values = { + "CR_FCA_Alive": idx % 0xF, + "PAINT1_Status": 1, + "FCA_DrvSetStatus": 1, + "FCA_Status": 1, # AEB disabled + } + fca11_dat = packer.make_can_msg("FCA11", 0, fca11_values)[1] + fca11_values["CR_FCA_ChkSum"] = hyundai_checksum(fca11_dat[:7]) + commands.append(packer.make_can_msg("FCA11", 0, fca11_values)) + + return commands + + +def create_acc_opt(packer, CP): + commands = [] + + scc13_values = { + "SCCDrvModeRValue": 2, + "SCC_Equip": 1, + "Lead_Veh_Dep_Alert_USM": 2, + } + commands.append(packer.make_can_msg("SCC13", 0, scc13_values)) + + # TODO: this needs to be detected and conditionally sent on unsupported long cars + # On Camera SCC cars, FCA12 is not disabled, so we forward stock FCA12 back to the car forward hooks + if not (CP.flags & HyundaiFlags.CAMERA_SCC): + fca12_values = { + "FCA_DrvSetState": 2, + "FCA_USM": 1, # AEB disabled + } + commands.append(packer.make_can_msg("FCA12", 0, fca12_values)) + + return commands + + +def create_frt_radar_opt(packer): + frt_radar11_values = { + "CF_FCA_Equip_Front_Radar": 1, + } + return packer.make_can_msg("FRT_RADAR11", 0, frt_radar11_values) diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py new file mode 100644 index 0000000000..1537bb4fdc --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py @@ -0,0 +1,256 @@ +import copy +import numpy as np +from opendbc.car import CanBusBase +from opendbc.car.crc import CRC16_XMODEM +from opendbc.car.hyundai.values import HyundaiFlags + + +class CanBus(CanBusBase): + def __init__(self, CP, fingerprint=None, lka_steering=None) -> None: + super().__init__(CP, fingerprint) + + if lka_steering is None: + lka_steering = CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value if CP is not None else False + + # On the CAN-FD platforms, the LKAS camera is on both A-CAN and E-CAN. LKA steering cars + # have a different harness than the LFA steering variants in order to split + # a different bus, since the steering is done by different ECUs. + self._a, self._e = 1, 0 + if lka_steering: + self._a, self._e = 0, 1 + + self._a += self.offset + self._e += self.offset + self._cam = 2 + self.offset + + @property + def ECAN(self): + return self._e + + @property + def ACAN(self): + return self._a + + @property + def CAM(self): + return self._cam + + +def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque): + common_values = { + "LKA_MODE": 2, + "LKA_ICON": 2 if enabled else 1, + "TORQUE_REQUEST": apply_torque, + "LKA_ASSIST": 0, + "STEER_REQ": 1 if lat_active else 0, + "STEER_MODE": 0, + "HAS_LANE_SAFETY": 0, # hide LKAS settings + "NEW_SIGNAL_2": 0, + "DAMP_FACTOR": 100, # can potentially tuned for better perf [3, 200] + } + + lkas_values = copy.copy(common_values) + lkas_values["LKA_AVAILABLE"] = 0 + + lfa_values = copy.copy(common_values) + lfa_values["NEW_SIGNAL_1"] = 0 + + ret = [] + if CP.flags & HyundaiFlags.CANFD_LKA_STEERING: + lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT else "LKAS" + if CP.openpilotLongitudinalControl: + ret.append(packer.make_can_msg("LFA", CAN.ECAN, lfa_values)) + ret.append(packer.make_can_msg(lkas_msg, CAN.ACAN, lkas_values)) + else: + ret.append(packer.make_can_msg("LFA", CAN.ECAN, lfa_values)) + + return ret + + +def create_suppress_lfa(packer, CAN, lfa_block_msg, lka_steering_alt): + suppress_msg = "CAM_0x362" if lka_steering_alt else "CAM_0x2a4" + msg_bytes = 32 if lka_steering_alt else 24 + + values = {f"BYTE{i}": lfa_block_msg[f"BYTE{i}"] for i in range(3, msg_bytes) if i != 7} + values["COUNTER"] = lfa_block_msg["COUNTER"] + values["SET_ME_0"] = 0 + values["SET_ME_0_2"] = 0 + values["LEFT_LANE_LINE"] = 0 + values["RIGHT_LANE_LINE"] = 0 + return packer.make_can_msg(suppress_msg, CAN.ACAN, values) + + +def create_buttons(packer, CP, CAN, cnt, btn): + values = { + "COUNTER": cnt, + "SET_ME_1": 1, + "CRUISE_BUTTONS": btn, + } + + bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_LKA_STEERING else CAN.CAM + return packer.make_can_msg("CRUISE_BUTTONS", bus, values) + + +def create_acc_cancel(packer, CP, CAN, cruise_info_copy): + # TODO: why do we copy different values here? + if CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value: + values = {s: cruise_info_copy[s] for s in [ + "COUNTER", + "CHECKSUM", + "NEW_SIGNAL_1", + "MainMode_ACC", + "ACCMode", + "ZEROS_9", + "CRUISE_STANDSTILL", + "ZEROS_5", + "DISTANCE_SETTING", + "VSetDis", + ]} + else: + values = {s: cruise_info_copy[s] for s in [ + "COUNTER", + "CHECKSUM", + "ACCMode", + "VSetDis", + "CRUISE_STANDSTILL", + ]} + values.update({ + "ACCMode": 4, + "aReqRaw": 0.0, + "aReqValue": 0.0, + }) + return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values) + + +def create_lfahda_cluster(packer, CAN, enabled): + values = { + "HDA_ICON": 1 if enabled else 0, + "LFA_ICON": 2 if enabled else 0, + } + 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): + jerk = 5 + jn = jerk / 50 + if not enabled or gas_override: + a_val, a_raw = 0, 0 + else: + a_raw = accel + a_val = np.clip(accel, accel_last - jn, accel_last + jn) + + values = { + "ACCMode": 0 if not enabled else (2 if gas_override else 1), + "MainMode_ACC": 1, + "StopReq": 1 if stopping else 0, + "aReqValue": a_val, + "aReqRaw": a_raw, + "VSetDis": set_speed, + "JerkLowerLimit": jerk if enabled else 1, + "JerkUpperLimit": 3.0, + + "ACC_ObjDist": 1, + "ObjValid": 0, + "OBJ_STATUS": 2, + "SET_ME_2": 0x4, + "SET_ME_3": 0x3, + "SET_ME_TMP_64": 0x64, + "DISTANCE_SETTING": hud_control.leadDistanceBars, + } + + return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values) + + +def create_spas_messages(packer, CAN, left_blink, right_blink): + ret = [] + + values = { + } + ret.append(packer.make_can_msg("SPAS1", CAN.ECAN, values)) + + blink = 0 + if left_blink: + blink = 3 + elif right_blink: + blink = 4 + values = { + "BLINKER_CONTROL": blink, + } + ret.append(packer.make_can_msg("SPAS2", CAN.ECAN, values)) + + return ret + + +def create_fca_warning_light(packer, CAN, frame): + ret = [] + + if frame % 2 == 0: + values = { + 'AEB_SETTING': 0x1, # show AEB disabled icon + 'SET_ME_2': 0x2, + 'SET_ME_FF': 0xff, + 'SET_ME_FC': 0xfc, + 'SET_ME_9': 0x9, + } + ret.append(packer.make_can_msg("ADRV_0x160", CAN.ECAN, values)) + return ret + + +def create_adrv_messages(packer, CAN, frame): + # messages needed to car happy after disabling + # the ADAS Driving ECU to do longitudinal control + + ret = [] + + values = { + } + ret.append(packer.make_can_msg("ADRV_0x51", CAN.ACAN, values)) + + ret.extend(create_fca_warning_light(packer, CAN, frame)) + + if frame % 5 == 0: + values = { + 'SET_ME_1C': 0x1c, + 'SET_ME_FF': 0xff, + 'SET_ME_TMP_F': 0xf, + 'SET_ME_TMP_F_2': 0xf, + } + ret.append(packer.make_can_msg("ADRV_0x1ea", CAN.ECAN, values)) + + values = { + 'SET_ME_E1': 0xe1, + 'SET_ME_3A': 0x3a, + } + ret.append(packer.make_can_msg("ADRV_0x200", CAN.ECAN, values)) + + if frame % 20 == 0: + values = { + 'SET_ME_15': 0x15, + } + ret.append(packer.make_can_msg("ADRV_0x345", CAN.ECAN, values)) + + if frame % 100 == 0: + values = { + 'SET_ME_22': 0x22, + 'SET_ME_41': 0x41, + } + ret.append(packer.make_can_msg("ADRV_0x1da", CAN.ECAN, values)) + + return ret + + +def hkg_can_fd_checksum(address: int, sig, d: bytearray) -> int: + crc = 0 + for i in range(2, len(d)): + crc = ((crc << 8) ^ CRC16_XMODEM[(crc >> 8) ^ d[i]]) & 0xFFFF + crc = ((crc << 8) ^ CRC16_XMODEM[(crc >> 8) ^ ((address >> 0) & 0xFF)]) & 0xFFFF + crc = ((crc << 8) ^ CRC16_XMODEM[(crc >> 8) ^ ((address >> 8) & 0xFF)]) & 0xFFFF + if len(d) == 8: + crc ^= 0x5F29 + elif len(d) == 16: + crc ^= 0x041D + elif len(d) == 24: + crc ^= 0x819D + elif len(d) == 32: + crc ^= 0x9F5B + return crc diff --git a/opendbc_repo/opendbc/car/hyundai/interface.py b/opendbc_repo/opendbc/car/hyundai/interface.py new file mode 100644 index 0000000000..1e058c4fce --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/interface.py @@ -0,0 +1,176 @@ +from opendbc.car import Bus, get_safety_config, structs, uds +from opendbc.car.hyundai.hyundaicanfd import CanBus +from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, \ + CANFD_UNSUPPORTED_LONGITUDINAL_CAR, \ + UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags +from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.disable_ecu import disable_ecu +from opendbc.car.hyundai.carcontroller import CarController +from opendbc.car.hyundai.carstate import CarState +from opendbc.car.hyundai.radar_interface import RadarInterface + +ButtonType = structs.CarState.ButtonEvent.Type +Ecu = structs.CarParams.Ecu + +# Cancel button can sometimes be ACC pause/resume button, main button can also enable on some cars +ENABLE_BUTTONS = (ButtonType.accelCruise, ButtonType.decelCruise, ButtonType.cancel, ButtonType.mainCruise) + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "hyundai" + + # "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera. + # Generally means our LKAS message is forwarded to another ECU (commonly ADAS ECU) + # that finally retransmits our steering command in LFA or LFA_ALT to the MDPS. + # "LFA steering" if camera directly sends LFA to the MDPS + cam_can = CanBus(None, fingerprint).CAM + lka_steering = 0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can] + CAN = CanBus(None, fingerprint, lka_steering) + + if ret.flags & HyundaiFlags.CANFD: + # Shared configuration for CAN-FD cars + ret.alphaLongitudinalAvailable = candidate not in CANFD_UNSUPPORTED_LONGITUDINAL_CAR + if lka_steering and Ecu.adas not in [fw.ecu for fw in car_fw]: + # this needs to be figured out for cars without an ADAS ECU + ret.alphaLongitudinalAvailable = False + + ret.enableBsm = 0x1e5 in fingerprint[CAN.ECAN] + + # Check if the car is hybrid. Only HEV/PHEV cars have 0xFA on E-CAN. + if 0xFA in fingerprint[CAN.ECAN]: + ret.flags |= HyundaiFlags.HYBRID.value + + if lka_steering: + # detect LKA steering + ret.flags |= HyundaiFlags.CANFD_LKA_STEERING.value + if 0x110 in fingerprint[CAN.CAM]: + ret.flags |= HyundaiFlags.CANFD_LKA_STEERING_ALT.value + else: + # no LKA steering + if 0x1cf not in fingerprint[CAN.ECAN]: + ret.flags |= HyundaiFlags.CANFD_ALT_BUTTONS.value + if not ret.flags & HyundaiFlags.RADAR_SCC: + ret.flags |= HyundaiFlags.CANFD_CAMERA_SCC.value + + # Some LKA steering cars have alternative messages for gear checks + # ICE cars do not have 0x130; GEARS message on 0x40 or 0x70 instead + if 0x130 not in fingerprint[CAN.ECAN]: + if 0x40 not in fingerprint[CAN.ECAN]: + ret.flags |= HyundaiFlags.CANFD_ALT_GEARS_2.value + else: + ret.flags |= HyundaiFlags.CANFD_ALT_GEARS.value + + cfgs = [get_safety_config(structs.CarParams.SafetyModel.hyundaiCanfd), ] + if CAN.ECAN >= 4: + cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput)) + ret.safetyConfigs = cfgs + + if ret.flags & HyundaiFlags.CANFD_LKA_STEERING: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEERING.value + if ret.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT.value + if ret.flags & HyundaiFlags.CANFD_ALT_BUTTONS: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value + if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value + + else: + # Shared configuration for non CAN-FD cars + ret.alphaLongitudinalAvailable = candidate not in UNSUPPORTED_LONGITUDINAL_CAR + ret.enableBsm = 0x58b in fingerprint[0] + + # Send LFA message on cars with HDA + if 0x485 in fingerprint[2]: + ret.flags |= HyundaiFlags.SEND_LFA.value + + # These cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 + if 0x38d in fingerprint[0] or 0x38d in fingerprint[2]: + ret.flags |= HyundaiFlags.USE_FCA.value + + if ret.flags & HyundaiFlags.LEGACY: + # these cars require a special panda safety mode due to missing counters and checksums in the messages + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hyundaiLegacy)] + else: + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hyundai, 0)] + + if ret.flags & HyundaiFlags.CAMERA_SCC: + ret.safetyConfigs[0].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value + + # These cars have the LFA button on the steering wheel + if 0x391 in fingerprint[0]: + ret.flags |= HyundaiFlags.HAS_LDA_BUTTON.value + + # Common lateral control setup + + ret.centerToFront = ret.wheelbase * 0.4 + ret.steerActuatorDelay = 0.1 + ret.steerLimitTimer = 0.4 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + if ret.flags & HyundaiFlags.ALT_LIMITS: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.ALT_LIMITS.value + + if ret.flags & HyundaiFlags.ALT_LIMITS_2: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.ALT_LIMITS_2.value + + # see https://github.com/commaai/opendbc/pull/1137/ + ret.dashcamOnly = True + + # Common longitudinal control setup + + ret.radarUnavailable = RADAR_START_ADDR not in fingerprint[1] or Bus.radar not in DBC[ret.carFingerprint] + ret.openpilotLongitudinalControl = alpha_long and ret.alphaLongitudinalAvailable + ret.pcmCruise = not ret.openpilotLongitudinalControl + ret.startingState = True + ret.vEgoStarting = 0.1 + ret.startAccel = 1.0 + ret.longitudinalActuatorDelay = 0.5 + + if ret.openpilotLongitudinalControl: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.LONG.value + if ret.flags & HyundaiFlags.HYBRID: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.HYBRID_GAS.value + elif ret.flags & HyundaiFlags.EV: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.EV_GAS.value + elif ret.flags & HyundaiFlags.FCEV: + ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.FCEV_GAS.value + + # Car specific configuration overrides + + if candidate == CAR.KIA_OPTIMA_G4_FL: + ret.steerActuatorDelay = 0.2 + + # Dashcam cars are missing a test route, or otherwise need validation + # TODO: Optima Hybrid 2017 uses a different SCC12 checksum + if candidate in (CAR.KIA_OPTIMA_H,): + ret.dashcamOnly = True + + return ret + + @staticmethod + def init(CP, can_recv, can_send, communication_control=None): + # 0x80 silences response + if communication_control is None: + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.DISABLE_RX_DISABLE_TX, uds.MESSAGE_TYPE.NORMAL]) + + if CP.openpilotLongitudinalControl and not (CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)): + addr, bus = 0x7d0, CanBus(CP).ECAN if CP.flags & HyundaiFlags.CANFD else 0 + if CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value: + addr, bus = 0x730, CanBus(CP).ECAN + disable_ecu(can_recv, can_send, bus=bus, addr=addr, com_cont_req=communication_control) + + # for blinkers + if CP.flags & HyundaiFlags.ENABLE_BLINKERS: + disable_ecu(can_recv, can_send, bus=CanBus(CP).ECAN, addr=0x7B1, com_cont_req=communication_control) + + @staticmethod + def deinit(CP, can_recv, can_send): + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, 0x80 | uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX, uds.MESSAGE_TYPE.NORMAL]) + CarInterface.init(CP, can_recv, can_send, communication_control) diff --git a/opendbc_repo/opendbc/car/hyundai/radar_interface.py b/opendbc_repo/opendbc/car/hyundai/radar_interface.py new file mode 100644 index 0000000000..3cabb95176 --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/radar_interface.py @@ -0,0 +1,77 @@ +import math + +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import RadarInterfaceBase +from opendbc.car.hyundai.values import DBC + +RADAR_START_ADDR = 0x500 +RADAR_MSG_COUNT = 32 + +# POC for parsing corner radars: https://github.com/commaai/openpilot/pull/24221/ + + +def get_radar_can_parser(CP): + if Bus.radar not in DBC[CP.carFingerprint]: + return None + + messages = [(f"RADAR_TRACK_{addr:x}", 50) for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT)] + return CANParser(DBC[CP.carFingerprint][Bus.radar], messages, 1) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + self.updated_messages = set() + self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1 + self.track_id = 0 + + self.radar_off_can = CP.radarUnavailable + self.rcp = get_radar_can_parser(CP) + + def update(self, can_strings): + if self.radar_off_can or (self.rcp is None): + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + + rr = self._update(self.updated_messages) + self.updated_messages.clear() + + return rr + + def _update(self, updated_messages): + ret = structs.RadarData() + if self.rcp is None: + return ret + + if not self.rcp.can_valid: + ret.errors.canError = True + + for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT): + msg = self.rcp.vl[f"RADAR_TRACK_{addr:x}"] + + if addr not in self.pts: + self.pts[addr] = structs.RadarData.RadarPoint() + self.pts[addr].trackId = self.track_id + self.track_id += 1 + + valid = msg['STATE'] in (3, 4) + if valid: + azimuth = math.radians(msg['AZIMUTH']) + self.pts[addr].measured = True + self.pts[addr].dRel = math.cos(azimuth) * msg['LONG_DIST'] + self.pts[addr].yRel = 0.5 * -math.sin(azimuth) * msg['LONG_DIST'] + self.pts[addr].vRel = msg['REL_SPEED'] + self.pts[addr].aRel = msg['REL_ACCEL'] + self.pts[addr].yvRel = float('nan') + + else: + del self.pts[addr] + + ret.points = list(self.pts.values()) + return ret diff --git a/opendbc_repo/opendbc/car/hyundai/tests/__init__.py b/opendbc_repo/opendbc/car/hyundai/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/hyundai/tests/print_platform_codes.py b/opendbc_repo/opendbc/car/hyundai/tests/print_platform_codes.py new file mode 100755 index 0000000000..325b020f9b --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/tests/print_platform_codes.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +from opendbc.car.structs import CarParams +from opendbc.car.hyundai.values import PLATFORM_CODE_ECUS, get_platform_codes +from opendbc.car.hyundai.fingerprints import FW_VERSIONS + +Ecu = CarParams.Ecu + +if __name__ == "__main__": + for car_model, ecus in FW_VERSIONS.items(): + print() + print(car_model) + for ecu in sorted(ecus): + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + platform_codes = get_platform_codes(ecus[ecu]) + codes = {code for code, _ in platform_codes} + dates = {date for _, date in platform_codes if date is not None} + print(f' (Ecu.{ecu[0]}, {hex(ecu[1])}, {ecu[2]}):') + print(f' Codes: {codes}') + print(f' Dates: {dates}') diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py new file mode 100644 index 0000000000..b798acaa1d --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -0,0 +1,247 @@ +from hypothesis import settings, given, strategies as st + +import pytest + +from opendbc.car import gen_empty_fingerprint +from opendbc.car.structs import CarParams +from opendbc.car.fw_versions import build_fw_dict +from opendbc.car.hyundai.interface import CarInterface +from opendbc.car.hyundai.hyundaicanfd import CanBus +from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR +from opendbc.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, DATE_FW_ECUS, \ + HYBRID_CAR, EV_CAR, FW_QUERY_CONFIG, LEGACY_SAFETY_MODE_CAR, CANFD_FUZZY_WHITELIST, \ + UNSUPPORTED_LONGITUDINAL_CAR, PLATFORM_CODE_ECUS, HYUNDAI_VERSION_REQUEST_LONG, \ + HyundaiFlags, get_platform_codes, HyundaiSafetyFlags +from opendbc.car.hyundai.fingerprints import FW_VERSIONS + +Ecu = CarParams.Ecu + +# Some platforms have date codes in a different format we don't yet parse (or are missing). +# For now, assert list of expected missing date cars +NO_DATES_PLATFORMS = { + # CAN FD + CAR.KIA_SPORTAGE_5TH_GEN, + CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN, + CAR.HYUNDAI_TUCSON_4TH_GEN, + # CAN + CAR.HYUNDAI_ELANTRA, + CAR.HYUNDAI_ELANTRA_GT_I30, + CAR.KIA_CEED, + CAR.KIA_FORTE, + CAR.KIA_OPTIMA_G4, + CAR.KIA_OPTIMA_G4_FL, + CAR.KIA_SORENTO, + CAR.HYUNDAI_KONA, + CAR.HYUNDAI_KONA_EV, + CAR.HYUNDAI_KONA_EV_2022, + CAR.HYUNDAI_KONA_HEV, + CAR.HYUNDAI_SONATA_LF, + CAR.HYUNDAI_VELOSTER, + CAR.HYUNDAI_KONA_2022, +} + +CANFD_EXPECTED_ECUS = {Ecu.fwdCamera, Ecu.fwdRadar} + + +class TestHyundaiFingerprint: + def test_feature_detection(self): + # LKA steering + for lka_steering in (True, False): + fingerprint = gen_empty_fingerprint() + if lka_steering: + cam_can = CanBus(None, fingerprint).CAM + fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages + CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False) + assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering + + # radar available + for radar in (True, False): + fingerprint = gen_empty_fingerprint() + if radar: + fingerprint[1][RADAR_START_ADDR] = 8 + CP = CarInterface.get_params(CAR.HYUNDAI_SONATA, fingerprint, [], False, False, False) + assert CP.radarUnavailable != radar + + def test_alternate_limits(self): + # Alternate lateral control limits, for high torque cars, verify Panda safety mode flag is set + fingerprint = gen_empty_fingerprint() + for car_model in CAR: + CP = CarInterface.get_params(car_model, fingerprint, [], False, False, False) + assert bool(CP.flags & HyundaiFlags.ALT_LIMITS) == bool(CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.ALT_LIMITS) + + def test_can_features(self): + # Test no EV/HEV in any gear lists (should all use ELECT_GEAR) + assert set.union(*CAN_GEARS.values()) & (HYBRID_CAR | EV_CAR) == set() + + # Test CAN FD car not in CAN feature lists + can_specific_feature_list = set.union(*CAN_GEARS.values(), *CHECKSUM.values(), LEGACY_SAFETY_MODE_CAR, UNSUPPORTED_LONGITUDINAL_CAR, CAMERA_SCC_CAR) + for car_model in CANFD_CAR: + assert car_model not in can_specific_feature_list, "CAN FD car unexpectedly found in a CAN feature list" + + def test_hybrid_ev_sets(self): + assert HYBRID_CAR & EV_CAR == set(), "Shared cars between hybrid and EV" + assert CANFD_CAR & HYBRID_CAR == set(), "Hard coding CAN FD cars as hybrid is no longer supported" + + def test_canfd_ecu_whitelist(self): + # Asserts only expected Ecus can exist in database for CAN-FD cars + for car_model in CANFD_CAR: + ecus = {fw[0] for fw in FW_VERSIONS[car_model].keys()} + ecus_not_in_whitelist = ecus - CANFD_EXPECTED_ECUS + ecu_strings = ", ".join([f"Ecu.{ecu}" for ecu in ecus_not_in_whitelist]) + assert len(ecus_not_in_whitelist) == 0, \ + f"{car_model}: Car model has unexpected ECUs: {ecu_strings}" + + def test_blacklisted_parts(self, subtests): + # Asserts no ECUs known to be shared across platforms exist in the database. + # Tucson having Santa Cruz camera and EPS for example + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + if car_model == CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN: + pytest.skip("Skip checking Santa Cruz for its parts") + + for code, _ in get_platform_codes(ecus[(Ecu.fwdCamera, 0x7c4, None)]): + if b"-" not in code: + continue + part = code.split(b"-")[1] + assert not part.startswith(b'CW'), "Car has bad part number" + + def test_correct_ecu_response_database(self, subtests): + """ + Assert standard responses for certain ECUs, since they can + respond to multiple queries with different data + """ + expected_fw_prefix = HYUNDAI_VERSION_REQUEST_LONG[1:] + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for ecu, fws in ecus.items(): + assert all(fw.startswith(expected_fw_prefix) for fw in fws), \ + f"FW from unexpected request in database: {(ecu, fws)}" + + @settings(max_examples=100) + @given(data=st.data()) + def test_platform_codes_fuzzy_fw(self, data): + """Ensure function doesn't raise an exception""" + fw_strategy = st.lists(st.binary()) + fws = data.draw(fw_strategy) + get_platform_codes(fws) + + def test_expected_platform_codes(self, subtests): + # Ensures we don't accidentally add multiple platform codes for a car unless it is intentional + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for ecu, fws in ecus.items(): + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + # Third and fourth character are usually EV/hybrid identifiers + codes = {code.split(b"-")[0][:2] for code, _ in get_platform_codes(fws)} + if car_model == CAR.HYUNDAI_PALISADE: + assert codes == {b"LX", b"ON"}, f"Car has unexpected platform codes: {car_model} {codes}" + elif car_model == CAR.HYUNDAI_KONA_EV and ecu[0] == Ecu.fwdCamera: + assert codes == {b"OE", b"OS"}, f"Car has unexpected platform codes: {car_model} {codes}" + else: + assert len(codes) == 1, f"Car has multiple platform codes: {car_model} {codes}" + + # Tests for platform codes, part numbers, and FW dates which Hyundai will use to fuzzy + # fingerprint in the absence of full FW matches: + def test_platform_code_ecus_available(self, subtests): + # TODO: add queries for these non-CAN FD cars to get EPS + no_eps_platforms = CANFD_CAR | {CAR.KIA_SORENTO, CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.KIA_OPTIMA_H, + CAR.KIA_OPTIMA_H_G4_FL, CAR.HYUNDAI_SONATA_LF, CAR.HYUNDAI_TUCSON, CAR.GENESIS_G90, CAR.GENESIS_G80, CAR.HYUNDAI_ELANTRA} + + # Asserts ECU keys essential for fuzzy fingerprinting are available on all platforms + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for platform_code_ecu in PLATFORM_CODE_ECUS: + if platform_code_ecu in (Ecu.fwdRadar, Ecu.eps) and car_model == CAR.HYUNDAI_GENESIS: + continue + if platform_code_ecu == Ecu.eps and car_model in no_eps_platforms: + continue + assert platform_code_ecu in [e[0] for e in ecus] + + def test_fw_format(self, subtests): + # Asserts: + # - every supported ECU FW version returns one platform code + # - every supported ECU FW version has a part number + # - expected parsing of ECU FW dates + + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for ecu, fws in ecus.items(): + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + codes = set() + for fw in fws: + result = get_platform_codes([fw]) + assert 1 == len(result), f"Unable to parse FW: {fw}" + codes |= result + + if ecu[0] not in DATE_FW_ECUS or car_model in NO_DATES_PLATFORMS: + assert all(date is None for _, date in codes) + else: + assert all(date is not None for _, date in codes) + + if car_model == CAR.HYUNDAI_GENESIS: + pytest.skip("No part numbers for car model") + + # Hyundai places the ECU part number in their FW versions, assert all parsable + # Some examples of valid formats: b"56310-L0010", b"56310L0010", b"56310/M6300" + assert all(b"-" in code for code, _ in codes), \ + f"FW does not have part number: {fw}" + + def test_platform_codes_spot_check(self): + # Asserts basic platform code parsing behavior for a few cases + results = get_platform_codes([b"\xf1\x00DH LKAS 1.1 -150210"]) + assert results == {(b"DH", b"150210")} + + # Some cameras and all radars do not have dates + results = get_platform_codes([b"\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 "]) + assert results == {(b"AEhe-G2000", None)} + + results = get_platform_codes([b"\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 "]) + assert results == {(b"CV1-CV000", None)} + + results = get_platform_codes([ + b"\xf1\x00DH LKAS 1.1 -150210", + b"\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 ", + b"\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 ", + ]) + assert results == {(b"DH", b"150210"), (b"AEhe-G2000", None), (b"CV1-CV000", None)} + + results = get_platform_codes([ + b"\xf1\x00LX2 MFC AT USA LHD 1.00 1.07 99211-S8100 220222", + b"\xf1\x00LX2 MFC AT USA LHD 1.00 1.08 99211-S8100 211103", + b"\xf1\x00ON MFC AT USA LHD 1.00 1.01 99211-S9100 190405", + b"\xf1\x00ON MFC AT USA LHD 1.00 1.03 99211-S9100 190720", + ]) + assert results == {(b"LX2-S8100", b"220222"), (b"LX2-S8100", b"211103"), + (b"ON-S9100", b"190405"), (b"ON-S9100", b"190720")} + + def test_fuzzy_excluded_platforms(self): + # Asserts a list of platforms that will not fuzzy fingerprint with platform codes due to them being shared. + # This list can be shrunk as we combine platforms and detect features + excluded_platforms = { + CAR.GENESIS_G70, # shared platform code, part number, and date + CAR.GENESIS_G70_2020, + } + excluded_platforms |= CANFD_CAR - EV_CAR - CANFD_FUZZY_WHITELIST # shared platform codes + excluded_platforms |= NO_DATES_PLATFORMS # date codes are required to match + + platforms_with_shared_codes = set() + for platform, fw_by_addr in FW_VERSIONS.items(): + car_fw = [] + for ecu, fw_versions in fw_by_addr.items(): + ecu_name, addr, sub_addr = ecu + for fw in fw_versions: + car_fw.append(CarParams.CarFw(ecu=ecu_name, fwVersion=fw, address=addr, + subAddress=0 if sub_addr is None else sub_addr)) + + CP = CarParams(carFw=car_fw) + matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw), CP.carVin, FW_VERSIONS) + if len(matches) == 1: + assert list(matches)[0] == platform + else: + platforms_with_shared_codes.add(platform) + + assert platforms_with_shared_codes == excluded_platforms diff --git a/opendbc_repo/opendbc/car/hyundai/values.py b/opendbc_repo/opendbc/car/hyundai/values.py new file mode 100644 index 0000000000..d7b1733b19 --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/values.py @@ -0,0 +1,806 @@ +import re +from dataclasses import dataclass, field +from enum import Enum, IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column, Device +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, p16 + +Ecu = CarParams.Ecu + + +class CarControllerParams: + ACCEL_MIN = -3.5 # m/s + ACCEL_MAX = 2.0 # m/s + + def __init__(self, CP): + self.STEER_DELTA_UP = 3 + self.STEER_DELTA_DOWN = 7 + self.STEER_DRIVER_ALLOWANCE = 50 + self.STEER_DRIVER_MULTIPLIER = 2 + self.STEER_DRIVER_FACTOR = 1 + self.STEER_THRESHOLD = 150 + self.STEER_STEP = 1 # 100 Hz + + if CP.flags & HyundaiFlags.CANFD: + self.STEER_MAX = 270 + self.STEER_DRIVER_ALLOWANCE = 250 + self.STEER_DRIVER_MULTIPLIER = 2 + self.STEER_THRESHOLD = 250 + self.STEER_DELTA_UP = 2 + self.STEER_DELTA_DOWN = 3 + + # To determine the limit for your car, find the maximum value that the stock LKAS will request. + # If the max stock LKAS request is <384, add your car to this list. + elif CP.carFingerprint in (CAR.GENESIS_G80, CAR.HYUNDAI_ELANTRA, CAR.HYUNDAI_ELANTRA_GT_I30, CAR.HYUNDAI_IONIQ, + CAR.HYUNDAI_IONIQ_EV_LTD, CAR.HYUNDAI_SANTA_FE_PHEV_2022, CAR.HYUNDAI_SONATA_LF, CAR.KIA_FORTE, CAR.KIA_NIRO_PHEV, + CAR.KIA_OPTIMA_H, CAR.KIA_OPTIMA_H_G4_FL, CAR.KIA_SORENTO): + self.STEER_MAX = 255 + + # these cars have significantly more torque than most HKG; limit to 70% of max + elif CP.flags & HyundaiFlags.ALT_LIMITS: + self.STEER_MAX = 270 + self.STEER_DELTA_UP = 2 + self.STEER_DELTA_DOWN = 3 + + elif CP.flags & HyundaiFlags.ALT_LIMITS_2: + self.STEER_MAX = 170 + self.STEER_DELTA_UP = 2 + self.STEER_DELTA_DOWN = 3 + + # Default for most HKG + else: + self.STEER_MAX = 384 + + +class HyundaiSafetyFlags(IntFlag): + EV_GAS = 1 + HYBRID_GAS = 2 + LONG = 4 + CAMERA_SCC = 8 + CANFD_LKA_STEERING = 16 + CANFD_ALT_BUTTONS = 32 + ALT_LIMITS = 64 + CANFD_LKA_STEERING_ALT = 128 + FCEV_GAS = 256 + ALT_LIMITS_2 = 512 + + +class HyundaiFlags(IntFlag): + # Dynamic Flags + + # Default assumption: all cars use LFA (ADAS) steering from the camera. + # CANFD_LKA_STEERING/CANFD_LKA_STEERING_ALT cars typically have both LKA (camera) and LFA (ADAS) steering messages, + # with LKA commands forwarded to the ADAS DRV ECU. + # Most HDA2 trims are assumed to be equipped with the ADAS DRV ECU, though some variants may not be equipped with one. + CANFD_LKA_STEERING = 1 + CANFD_ALT_BUTTONS = 2 + CANFD_ALT_GEARS = 2 ** 2 + CANFD_CAMERA_SCC = 2 ** 3 + + ALT_LIMITS = 2 ** 4 + ENABLE_BLINKERS = 2 ** 5 + CANFD_ALT_GEARS_2 = 2 ** 6 + SEND_LFA = 2 ** 7 + USE_FCA = 2 ** 8 + CANFD_LKA_STEERING_ALT = 2 ** 9 + + # these cars use a different gas signal + HYBRID = 2 ** 10 + EV = 2 ** 11 + + # Static flags + + # If 0x500 is present on bus 1 it probably has a Mando radar outputting radar points. + # If no points are outputted by default it might be possible to turn it on using selfdrive/debug/hyundai_enable_radar_points.py + MANDO_RADAR = 2 ** 12 + CANFD = 2 ** 13 + + # The radar does SCC on these cars when HDA I, rather than the camera + RADAR_SCC = 2 ** 14 + # The camera does SCC on these cars, rather than the radar + CAMERA_SCC = 2 ** 15 + CHECKSUM_CRC8 = 2 ** 16 + CHECKSUM_6B = 2 ** 17 + + # these cars require a special panda safety mode due to missing counters and checksums in the messages + LEGACY = 2 ** 18 + + # these cars have not been verified to work with longitudinal yet - radar disable, sending correct messages, etc. + UNSUPPORTED_LONGITUDINAL = 2 ** 19 + + # These CAN FD cars do not accept communication control to disable the ADAS ECU, + # responds with 0x7F2822 - 'conditions not correct' + CANFD_NO_RADAR_DISABLE = 2 ** 20 + + CLUSTER_GEARS = 2 ** 21 + TCU_GEARS = 2 ** 22 + + MIN_STEER_32_MPH = 2 ** 23 + + HAS_LDA_BUTTON = 2 ** 24 + + FCEV = 2 ** 25 + + ALT_LIMITS_2 = 2 ** 26 + + +class Footnote(Enum): + CANFD = CarFootnote( + "Requires a CAN FD panda kit if not using " + + "comma 3X for this CAN FD car.", + Column.MODEL) + + +@dataclass +class HyundaiCarDocs(CarDocs): + package: str = "Smart Cruise Control (SCC)" + + def init_make(self, CP: CarParams): + if CP.flags & HyundaiFlags.CANFD: + self.footnotes.insert(0, Footnote.CANFD) + + +@dataclass +class HyundaiPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "hyundai_kia_generic"}) + + def init(self): + if self.flags & HyundaiFlags.MANDO_RADAR: + self.dbc_dict = {Bus.pt: "hyundai_kia_generic", Bus.radar: 'hyundai_kia_mando_front_radar_generated'} + + if self.flags & HyundaiFlags.MIN_STEER_32_MPH: + self.specs = self.specs.override(minSteerSpeed=32 * CV.MPH_TO_MS) + + +@dataclass +class HyundaiCanFDPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: "hyundai_canfd_generated"}) + + def init(self): + self.flags |= HyundaiFlags.CANFD + + +class CAR(Platforms): + # Hyundai + HYUNDAI_AZERA_6TH_GEN = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Azera 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))], + CarSpecs(mass=1600, wheelbase=2.885, steerRatio=14.5), + ) + HYUNDAI_AZERA_HEV_6TH_GEN = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Hyundai Azera Hybrid 2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c])), + HyundaiCarDocs("Hyundai Azera Hybrid 2020", "All", car_parts=CarParts.common([CarHarness.hyundai_k])), + ], + CarSpecs(mass=1675, wheelbase=2.885, steerRatio=14.5), + flags=HyundaiFlags.HYBRID, + ) + HYUNDAI_ELANTRA = HyundaiPlatformConfig( + [ + # TODO: 2017-18 could be Hyundai G + HyundaiCarDocs("Hyundai Elantra 2017-18", min_enable_speed=19 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_b])), + HyundaiCarDocs("Hyundai Elantra 2019", min_enable_speed=19 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_g])), + ], + # steerRatio: 14 is Stock | Settled Params Learner values are steerRatio: 15.401566348670535, stiffnessFactor settled on 1.0081302973865127 + CarSpecs(mass=1275, wheelbase=2.7, steerRatio=15.4, tireStiffnessFactor=0.385), + flags=HyundaiFlags.LEGACY | HyundaiFlags.CLUSTER_GEARS | HyundaiFlags.MIN_STEER_32_MPH, + ) + HYUNDAI_ELANTRA_GT_I30 = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Hyundai Elantra GT 2017-20", car_parts=CarParts.common([CarHarness.hyundai_e])), + HyundaiCarDocs("Hyundai i30 2017-19", car_parts=CarParts.common([CarHarness.hyundai_e])), + ], + HYUNDAI_ELANTRA.specs, + flags=HyundaiFlags.LEGACY | HyundaiFlags.CLUSTER_GEARS | HyundaiFlags.MIN_STEER_32_MPH, + ) + HYUNDAI_ELANTRA_2021 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Elantra 2021-23", video="https://youtu.be/_EdYQtV52-c", car_parts=CarParts.common([CarHarness.hyundai_k]))], + CarSpecs(mass=2800 * CV.LB_TO_KG, wheelbase=2.72, steerRatio=12.9, tireStiffnessFactor=0.65), + flags=HyundaiFlags.CHECKSUM_CRC8, + ) + HYUNDAI_ELANTRA_HEV_2021 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Elantra Hybrid 2021-23", video="https://youtu.be/_EdYQtV52-c", + car_parts=CarParts.common([CarHarness.hyundai_k]))], + CarSpecs(mass=3017 * CV.LB_TO_KG, wheelbase=2.72, steerRatio=12.9, tireStiffnessFactor=0.65), + flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, + ) + HYUNDAI_GENESIS = HyundaiPlatformConfig( + [ + # TODO: check 2015 packages + HyundaiCarDocs("Hyundai Genesis 2015-16", min_enable_speed=19 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_j])), + HyundaiCarDocs("Genesis G80 2017", "All", min_enable_speed=19 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_j])), + ], + CarSpecs(mass=2060, wheelbase=3.01, steerRatio=16.5, minSteerSpeed=60 * CV.KPH_TO_MS), + flags=HyundaiFlags.CHECKSUM_6B | HyundaiFlags.LEGACY, + ) + HYUNDAI_IONIQ = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq Hybrid 2017-19", car_parts=CarParts.common([CarHarness.hyundai_c]))], + CarSpecs(mass=1490, wheelbase=2.7, steerRatio=13.73, tireStiffnessFactor=0.385), + flags=HyundaiFlags.HYBRID | HyundaiFlags.MIN_STEER_32_MPH, + ) + HYUNDAI_IONIQ_HEV_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_h]))], + CarSpecs(mass=1490, wheelbase=2.7, steerRatio=13.73, tireStiffnessFactor=0.385), + flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY, + ) + HYUNDAI_IONIQ_EV_LTD = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq Electric 2019", car_parts=CarParts.common([CarHarness.hyundai_c]))], + CarSpecs(mass=1490, wheelbase=2.7, steerRatio=13.73, tireStiffnessFactor=0.385), + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.EV | HyundaiFlags.LEGACY | HyundaiFlags.MIN_STEER_32_MPH, + ) + HYUNDAI_IONIQ_EV_2020 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq Electric 2020", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))], + CarSpecs(mass=1490, wheelbase=2.7, steerRatio=13.73, tireStiffnessFactor=0.385), + flags=HyundaiFlags.EV, + ) + HYUNDAI_IONIQ_PHEV_2019 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq Plug-in Hybrid 2019", car_parts=CarParts.common([CarHarness.hyundai_c]))], + CarSpecs(mass=1490, wheelbase=2.7, steerRatio=13.73, tireStiffnessFactor=0.385), + flags=HyundaiFlags.HYBRID | HyundaiFlags.MIN_STEER_32_MPH, + ) + HYUNDAI_IONIQ_PHEV = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq Plug-in Hybrid 2020-22", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))], + CarSpecs(mass=1490, wheelbase=2.7, steerRatio=13.73, tireStiffnessFactor=0.385), + flags=HyundaiFlags.HYBRID, + ) + HYUNDAI_KONA = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Kona 2020", min_enable_speed=6 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_b]))], + CarSpecs(mass=1275, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CLUSTER_GEARS | HyundaiFlags.ALT_LIMITS, + ) + HYUNDAI_KONA_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Kona 2022-23", car_parts=CarParts.common([CarHarness.hyundai_o]))], + CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2, + ) + HYUNDAI_KONA_EV = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))], + CarSpecs(mass=1685, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), + flags=HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS, + ) + HYUNDAI_KONA_EV_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Kona Electric 2022-23", car_parts=CarParts.common([CarHarness.hyundai_o]))], + CarSpecs(mass=1743, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), + flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS, + ) + HYUNDAI_KONA_EV_2ND_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw", + car_parts=CarParts.common([CarHarness.hyundai_r]))], + CarSpecs(mass=1740, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385), + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE, + ) + HYUNDAI_KONA_HEV = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Kona Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_i]))], # TODO: check packages, + CarSpecs(mass=1425, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385), + flags=HyundaiFlags.HYBRID | HyundaiFlags.ALT_LIMITS, + ) + HYUNDAI_NEXO_1ST_GEN = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Nexo 2021", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))], + CarSpecs(mass=3990 * CV.LB_TO_KG, wheelbase=2.79, steerRatio=14.19), # https://www.hyundainews.com/assets/documents/original/42768-2021NEXOProductGuideSpecs.pdf + flags=HyundaiFlags.FCEV, + ) + HYUNDAI_SANTA_FE = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Santa Fe 2019-20", "All", video="https://youtu.be/bjDR0YjM__s", + car_parts=CarParts.common([CarHarness.hyundai_d]))], + CarSpecs(mass=3982 * CV.LB_TO_KG, wheelbase=2.766, steerRatio=16.55, tireStiffnessFactor=0.82), + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8, + ) + HYUNDAI_SANTA_FE_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Santa Fe 2021-23", "All", video="https://youtu.be/VnHzSTygTS4", + car_parts=CarParts.common([CarHarness.hyundai_l]))], + HYUNDAI_SANTA_FE.specs, + flags=HyundaiFlags.CHECKSUM_CRC8, + ) + HYUNDAI_SANTA_FE_HEV_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Santa Fe Hybrid 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_l]))], + HYUNDAI_SANTA_FE.specs, + flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, + ) + HYUNDAI_SANTA_FE_PHEV_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Santa Fe Plug-in Hybrid 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_l]))], + HYUNDAI_SANTA_FE.specs, + flags=HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, + ) + HYUNDAI_SONATA = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Sonata 2020-23", "All", video="https://www.youtube.com/watch?v=ix63r9kE3Fw", + car_parts=CarParts.common([CarHarness.hyundai_a]))], + CarSpecs(mass=1513, wheelbase=2.84, steerRatio=13.27 * 1.15, tireStiffnessFactor=0.65), # 15% higher at the center seems reasonable + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8, + ) + HYUNDAI_SONATA_LF = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Sonata 2018-19", car_parts=CarParts.common([CarHarness.hyundai_e]))], + CarSpecs(mass=1536, wheelbase=2.804, steerRatio=13.27 * 1.15), # 15% higher at the center seems reasonable + flags=HyundaiFlags.UNSUPPORTED_LONGITUDINAL | HyundaiFlags.TCU_GEARS, + ) + HYUNDAI_STARIA_4TH_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Staria 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))], + CarSpecs(mass=2205, wheelbase=3.273, steerRatio=11.94), # https://www.hyundai.com/content/dam/hyundai/au/en/models/staria-load/premium-pip-update-2023/spec-sheet/STARIA_Load_Spec-Table_March_2023_v3.1.pdf + ) + HYUNDAI_TUCSON = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Hyundai Tucson 2021", min_enable_speed=19 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_l])), + HyundaiCarDocs("Hyundai Tucson Diesel 2019", car_parts=CarParts.common([CarHarness.hyundai_l])), + ], + CarSpecs(mass=3520 * CV.LB_TO_KG, wheelbase=2.67, steerRatio=16.1, tireStiffnessFactor=0.385), + flags=HyundaiFlags.TCU_GEARS, + ) + HYUNDAI_PALISADE = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Hyundai Palisade 2020-22", "All", video="https://youtu.be/TAnDqjF4fDY?t=456", car_parts=CarParts.common([CarHarness.hyundai_h])), + HyundaiCarDocs("Kia Telluride 2020-22", "All", car_parts=CarParts([Device.threex_angled_mount, CarHarness.hyundai_h])), + ], + CarSpecs(mass=1999, wheelbase=2.9, steerRatio=15.6 * 1.15, tireStiffnessFactor=0.63), + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8, + ) + HYUNDAI_VELOSTER = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Veloster 2019-20", min_enable_speed=5. * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_e]))], + CarSpecs(mass=2917 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75 * 1.15, tireStiffnessFactor=0.5), + flags=HyundaiFlags.LEGACY | HyundaiFlags.TCU_GEARS, + ) + HYUNDAI_SONATA_HYBRID = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Sonata Hybrid 2020-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a]))], + HYUNDAI_SONATA.specs, + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, + ) + HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), + HyundaiCarDocs("Hyundai Ioniq 5 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_k])), + HyundaiCarDocs("Hyundai Ioniq 5 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), + ], + CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65), + flags=HyundaiFlags.EV, + ) + HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Ioniq 6 (with HDA II) 2023-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))], + HYUNDAI_IONIQ_5.specs, + flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE, + ) + HYUNDAI_TUCSON_4TH_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Hyundai Tucson 2022", car_parts=CarParts.common([CarHarness.hyundai_n])), + HyundaiCarDocs("Hyundai Tucson 2023-24", "All", car_parts=CarParts.common([CarHarness.hyundai_n])), + HyundaiCarDocs("Hyundai Tucson Hybrid 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_n])), + HyundaiCarDocs("Hyundai Tucson Plug-in Hybrid 2024", "All", car_parts=CarParts.common([CarHarness.hyundai_n])), + ], + CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385), + ) + HYUNDAI_SANTA_CRUZ_1ST_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Hyundai Santa Cruz 2022-24", car_parts=CarParts.common([CarHarness.hyundai_n]))], + # weight from Limited trim - the only supported trim, steering ratio according to Hyundai News https://www.hyundainews.com/assets/documents/original/48035-2022SantaCruzProductGuideSpecsv2081521.pdf + CarSpecs(mass=1870, wheelbase=3, steerRatio=14.2), + ) + HYUNDAI_CUSTIN_1ST_GEN = HyundaiPlatformConfig( + [HyundaiCarDocs("Hyundai Custin 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))], + CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner + flags=HyundaiFlags.CHECKSUM_CRC8, + ) + + # Kia + KIA_FORTE = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Kia Forte 2019-21", min_enable_speed=6 * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_g])), + HyundaiCarDocs("Kia Forte 2022-23", car_parts=CarParts.common([CarHarness.hyundai_e])), + ], + CarSpecs(mass=2878 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5) + ) + KIA_K5_2021 = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia K5 2021-24", car_parts=CarParts.common([CarHarness.hyundai_a]))], + CarSpecs(mass=3381 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5), # 2021 Kia K5 Steering Ratio (all trims) + flags=HyundaiFlags.CHECKSUM_CRC8, + ) + KIA_K5_HEV_2020 = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a]))], + KIA_K5_2021.specs, + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID, + ) + KIA_K8_HEV_1ST_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Kia K8 Hybrid (with HDA II) 2023", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q]))], + # mass: https://carprices.ae/brands/kia/2023/k8/1.6-turbo-hybrid, steerRatio: guesstimate from K5 platform + CarSpecs(mass=1630, wheelbase=2.895, steerRatio=13.27) + ) + KIA_NIRO_EV = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Kia Niro EV 2019", "All", video="https://www.youtube.com/watch?v=lT7zcG6ZpGo", car_parts=CarParts.common([CarHarness.hyundai_h])), + HyundaiCarDocs("Kia Niro EV 2020", "All", video="https://www.youtube.com/watch?v=lT7zcG6ZpGo", car_parts=CarParts.common([CarHarness.hyundai_f])), + HyundaiCarDocs("Kia Niro EV 2021", "All", video="https://www.youtube.com/watch?v=lT7zcG6ZpGo", car_parts=CarParts.common([CarHarness.hyundai_c])), + HyundaiCarDocs("Kia Niro EV 2022", "All", video="https://www.youtube.com/watch?v=lT7zcG6ZpGo", car_parts=CarParts.common([CarHarness.hyundai_h])), + ], + CarSpecs(mass=3543 * CV.LB_TO_KG, wheelbase=2.7, steerRatio=13.6, tireStiffnessFactor=0.385), # average of all the cars + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.EV, + ) + KIA_NIRO_EV_2ND_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia Niro EV (without HDA II) 2023-25", "All", car_parts=CarParts.common([CarHarness.hyundai_a])), + HyundaiCarDocs("Kia Niro EV (with HDA II) 2025", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_r])), + ], + KIA_NIRO_EV.specs, + flags=HyundaiFlags.EV, + ) + KIA_NIRO_PHEV = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Kia Niro Hybrid 2018", min_enable_speed=10. * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_c])), + HyundaiCarDocs("Kia Niro Plug-in Hybrid 2018-19", "All", min_enable_speed=10. * CV.MPH_TO_MS, car_parts=CarParts.common([CarHarness.hyundai_c])), + HyundaiCarDocs("Kia Niro Plug-in Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_d])), + ], + KIA_NIRO_EV.specs, + flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.HYBRID | HyundaiFlags.UNSUPPORTED_LONGITUDINAL | HyundaiFlags.MIN_STEER_32_MPH, + ) + KIA_NIRO_PHEV_2022 = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Kia Niro Plug-in Hybrid 2021", car_parts=CarParts.common([CarHarness.hyundai_d])), + HyundaiCarDocs("Kia Niro Plug-in Hybrid 2022", car_parts=CarParts.common([CarHarness.hyundai_f])), + ], + KIA_NIRO_EV.specs, + flags=HyundaiFlags.HYBRID | HyundaiFlags.MANDO_RADAR, + ) + KIA_NIRO_HEV_2021 = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Kia Niro Hybrid 2021", car_parts=CarParts.common([CarHarness.hyundai_d])), + HyundaiCarDocs("Kia Niro Hybrid 2022", car_parts=CarParts.common([CarHarness.hyundai_f])), + ], + KIA_NIRO_EV.specs, + flags=HyundaiFlags.HYBRID, + ) + KIA_NIRO_HEV_2ND_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Kia Niro Hybrid 2023", car_parts=CarParts.common([CarHarness.hyundai_a]))], + KIA_NIRO_EV.specs, + ) + KIA_OPTIMA_G4 = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Optima 2017", "Advanced Smart Cruise Control", + car_parts=CarParts.common([CarHarness.hyundai_b]))], # TODO: may support 2016, 2018 + CarSpecs(mass=3558 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5), + flags=HyundaiFlags.LEGACY | HyundaiFlags.TCU_GEARS | HyundaiFlags.MIN_STEER_32_MPH, + ) + KIA_OPTIMA_G4_FL = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Optima 2019-20", car_parts=CarParts.common([CarHarness.hyundai_g]))], + CarSpecs(mass=3558 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5), + flags=HyundaiFlags.UNSUPPORTED_LONGITUDINAL | HyundaiFlags.TCU_GEARS, + ) + # TODO: may support adjacent years. may have a non-zero minimum steering speed + KIA_OPTIMA_H = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Optima Hybrid 2017", "Advanced Smart Cruise Control", car_parts=CarParts.common([CarHarness.hyundai_c]))], + CarSpecs(mass=3558 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5), + flags=HyundaiFlags.HYBRID | HyundaiFlags.LEGACY, + ) + KIA_OPTIMA_H_G4_FL = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Optima Hybrid 2019", car_parts=CarParts.common([CarHarness.hyundai_h]))], + CarSpecs(mass=3558 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5), + flags=HyundaiFlags.HYBRID | HyundaiFlags.UNSUPPORTED_LONGITUDINAL, + ) + KIA_SELTOS = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Seltos 2021", car_parts=CarParts.common([CarHarness.hyundai_a]))], + CarSpecs(mass=1337, wheelbase=2.63, steerRatio=14.56), + flags=HyundaiFlags.CHECKSUM_CRC8, + ) + KIA_SPORTAGE_5TH_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia Sportage 2023-24", car_parts=CarParts.common([CarHarness.hyundai_n])), + HyundaiCarDocs("Kia Sportage Hybrid 2023", car_parts=CarParts.common([CarHarness.hyundai_n])), + ], + # weight from SX and above trims, average of FWD and AWD version, steering ratio according to Kia News https://www.kiamedia.com/us/en/models/sportage/2023/specifications + CarSpecs(mass=1725, wheelbase=2.756, steerRatio=13.6), + ) + KIA_SORENTO = HyundaiPlatformConfig( + [ + HyundaiCarDocs("Kia Sorento 2018", "Advanced Smart Cruise Control & LKAS", video="https://www.youtube.com/watch?v=Fkh3s6WHJz8", + car_parts=CarParts.common([CarHarness.hyundai_e])), + HyundaiCarDocs("Kia Sorento 2019", video="https://www.youtube.com/watch?v=Fkh3s6WHJz8", car_parts=CarParts.common([CarHarness.hyundai_e])), + ], + CarSpecs(mass=1985, wheelbase=2.78, steerRatio=14.4 * 1.1), # 10% higher at the center seems reasonable + flags=HyundaiFlags.CHECKSUM_6B | HyundaiFlags.UNSUPPORTED_LONGITUDINAL, + ) + KIA_SORENTO_4TH_GEN = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Kia Sorento 2021-23", car_parts=CarParts.common([CarHarness.hyundai_k]))], + CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms + flags=HyundaiFlags.RADAR_SCC, + ) + KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia Sorento Hybrid 2021-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])), + HyundaiCarDocs("Kia Sorento Plug-in Hybrid 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])), + ], + CarSpecs(mass=4395 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms + flags=HyundaiFlags.RADAR_SCC, + ) + KIA_STINGER = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Stinger 2018-20", video="https://www.youtube.com/watch?v=MJ94qoofYw0", + car_parts=CarParts.common([CarHarness.hyundai_c]))], + CarSpecs(mass=1825, wheelbase=2.78, steerRatio=14.4 * 1.15) # 15% higher at the center seems reasonable + ) + KIA_STINGER_2022 = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Stinger 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))], + KIA_STINGER.specs, + ) + KIA_CEED = HyundaiPlatformConfig( + [HyundaiCarDocs("Kia Ceed 2019-21", car_parts=CarParts.common([CarHarness.hyundai_e]))], + CarSpecs(mass=1450, wheelbase=2.65, steerRatio=13.75, tireStiffnessFactor=0.5), + flags=HyundaiFlags.LEGACY, + ) + KIA_EV6 = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia EV6 (Southeast Asia only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_p])), + HyundaiCarDocs("Kia EV6 (without HDA II) 2022-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])), + HyundaiCarDocs("Kia EV6 (with HDA II) 2022-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p])) + ], + CarSpecs(mass=2055, wheelbase=2.9, steerRatio=16, tireStiffnessFactor=0.65), + flags=HyundaiFlags.EV, + ) + KIA_CARNIVAL_4TH_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Kia Carnival 2022-24", car_parts=CarParts.common([CarHarness.hyundai_a])), + HyundaiCarDocs("Kia Carnival (China only) 2023", car_parts=CarParts.common([CarHarness.hyundai_k])) + ], + CarSpecs(mass=2087, wheelbase=3.09, steerRatio=14.23), + flags=HyundaiFlags.RADAR_SCC, + ) + + # Genesis + GENESIS_GV60_EV_1ST_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Genesis GV60 (Advanced Trim) 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_a])), + HyundaiCarDocs("Genesis GV60 (Performance Trim) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_k])), + ], + CarSpecs(mass=2205, wheelbase=2.9, steerRatio=17.6), + flags=HyundaiFlags.EV, + ) + GENESIS_G70 = HyundaiPlatformConfig( + [HyundaiCarDocs("Genesis G70 2018", "All", car_parts=CarParts.common([CarHarness.hyundai_f]))], + CarSpecs(mass=1640, wheelbase=2.84, steerRatio=13.56), + flags=HyundaiFlags.LEGACY, + ) + GENESIS_G70_2020 = HyundaiPlatformConfig( + [ + # TODO: 2021 MY harness is unknown + HyundaiCarDocs("Genesis G70 2019-21", "All", car_parts=CarParts.common([CarHarness.hyundai_f])), + # TODO: From 3.3T Sport Advanced 2022 & Prestige 2023 Trim, 2.0T is unknown + HyundaiCarDocs("Genesis G70 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_l])), + ], + GENESIS_G70.specs, + flags=HyundaiFlags.MANDO_RADAR, + ) + GENESIS_GV70_1ST_GEN = HyundaiCanFDPlatformConfig( + [ + # TODO: Hyundai P is likely the correct harness for HDA II for 2.5T (unsupported due to missing ADAS ECU, is that the radar?) + HyundaiCarDocs("Genesis GV70 (2.5T Trim, without HDA II) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_l])), + HyundaiCarDocs("Genesis GV70 (3.5T Trim, without HDA II) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_m])), + ], + CarSpecs(mass=1950, wheelbase=2.87, steerRatio=14.6), + flags=HyundaiFlags.RADAR_SCC, + ) + GENESIS_GV70_ELECTRIFIED_1ST_GEN = HyundaiCanFDPlatformConfig( + [ + HyundaiCarDocs("Genesis GV70 Electrified (Australia Only) 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_q])), + HyundaiCarDocs("Genesis GV70 Electrified (with HDA II) 2023-24", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_q])), + ], + CarSpecs(mass=2260, wheelbase=2.87, steerRatio=17.1), + flags=HyundaiFlags.EV, + ) + GENESIS_G80 = HyundaiPlatformConfig( + [HyundaiCarDocs("Genesis G80 2018-19", "All", car_parts=CarParts.common([CarHarness.hyundai_h]))], + CarSpecs(mass=2060, wheelbase=3.01, steerRatio=16.5), + flags=HyundaiFlags.LEGACY, + ) + GENESIS_G80_2ND_GEN_FL = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Genesis G80 (2.5T Advanced Trim, with HDA II) 2024", "Highway Driving Assist II", car_parts=CarParts.common([CarHarness.hyundai_p]))], + CarSpecs(mass=2060, wheelbase=3.00, steerRatio=14.0), + ) + GENESIS_G90 = HyundaiPlatformConfig( + [HyundaiCarDocs("Genesis G90 2017-20", "All", car_parts=CarParts.common([CarHarness.hyundai_c]))], + CarSpecs(mass=2200, wheelbase=3.15, steerRatio=12.069), + ) + GENESIS_GV80 = HyundaiCanFDPlatformConfig( + [HyundaiCarDocs("Genesis GV80 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_m]))], + CarSpecs(mass=2258, wheelbase=2.95, steerRatio=14.14), + flags=HyundaiFlags.RADAR_SCC, + ) + + +class Buttons: + NONE = 0 + RES_ACCEL = 1 + SET_DECEL = 2 + GAP_DIST = 3 + CANCEL = 4 # on newer models, this is a pause/resume button + + +def get_platform_codes(fw_versions: list[bytes]) -> set[tuple[bytes, bytes | None]]: + # Returns unique, platform-specific identification codes for a set of versions + codes = set() # (code-Optional[part], date) + for fw in fw_versions: + code_match = PLATFORM_CODE_FW_PATTERN.search(fw) + part_match = PART_NUMBER_FW_PATTERN.search(fw) + date_match = DATE_FW_PATTERN.search(fw) + if code_match is not None: + code: bytes = code_match.group() + part = part_match.group() if part_match else None + date = date_match.group() if date_match else None + if part is not None: + # part number starts with generic ECU part type, add what is specific to platform + code += b"-" + part[-5:] + + codes.add((code, date)) + return codes + + +def match_fw_to_car_fuzzy(live_fw_versions, vin, offline_fw_versions) -> set[str]: + # Non-electric CAN FD platforms often do not have platform code specifiers needed + # to distinguish between hybrid and ICE. All EVs so far are either exclusively + # electric or specify electric in the platform code. + fuzzy_platform_blacklist = {str(c) for c in (CANFD_CAR - EV_CAR - CANFD_FUZZY_WHITELIST)} + candidates: set[str] = set() + + for candidate, fws in offline_fw_versions.items(): + # Keep track of ECUs which pass all checks (platform codes, within date range) + valid_found_ecus = set() + valid_expected_ecus = {ecu[1:] for ecu in fws if ecu[0] in PLATFORM_CODE_ECUS} + for ecu, expected_versions in fws.items(): + addr = ecu[1:] + # Only check ECUs expected to have platform codes + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + # Expected platform codes & dates + codes = get_platform_codes(expected_versions) + expected_platform_codes = {code for code, _ in codes} + expected_dates = {date for _, date in codes if date is not None} + + # Found platform codes & dates + codes = get_platform_codes(live_fw_versions.get(addr, set())) + found_platform_codes = {code for code, _ in codes} + found_dates = {date for _, date in codes if date is not None} + + # Check platform code + part number matches for any found versions + if not any(found_platform_code in expected_platform_codes for found_platform_code in found_platform_codes): + break + + if ecu[0] in DATE_FW_ECUS: + # If ECU can have a FW date, require it to exist + # (this excludes candidates in the database without dates) + if not len(expected_dates) or not len(found_dates): + break + + # Check any date within range in the database, format is %y%m%d + if not any(min(expected_dates) <= found_date <= max(expected_dates) for found_date in found_dates): + break + + valid_found_ecus.add(addr) + + # If all live ECUs pass all checks for candidate, add it as a match + if valid_expected_ecus.issubset(valid_found_ecus): + candidates.add(candidate) + + return candidates - fuzzy_platform_blacklist + + +HYUNDAI_VERSION_REQUEST_LONG = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(0xf100) # Long description + +HYUNDAI_VERSION_REQUEST_ALT = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(0xf110) # Alt long description + +HYUNDAI_ECU_MANUFACTURING_DATE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.ECU_MANUFACTURING_DATE) + +HYUNDAI_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + +# Regex patterns for parsing platform code, FW date, and part number from FW versions +PLATFORM_CODE_FW_PATTERN = re.compile(b'((?<=' + HYUNDAI_VERSION_REQUEST_LONG[1:] + + b')[A-Z]{2}[A-Za-z0-9]{0,2})') +DATE_FW_PATTERN = re.compile(b'(?<=[ -])([0-9]{6}$)') +PART_NUMBER_FW_PATTERN = re.compile(b'(?<=[0-9][.,][0-9]{2} )([0-9]{5}[-/]?[A-Z][A-Z0-9]{3}[0-9])') + +# We've seen both ICE and hybrid for these platforms, and they have hybrid descriptors (e.g. MQ4 vs MQ4H) +CANFD_FUZZY_WHITELIST = {CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_SORENTO_HEV_4TH_GEN, CAR.KIA_K8_HEV_1ST_GEN, + # TODO: the hybrid variant is not out yet + CAR.KIA_CARNIVAL_4TH_GEN} + +# List of ECUs expected to have platform codes, camera and radar should exist on all cars +# TODO: use abs, it has the platform code and part number on many platforms +PLATFORM_CODE_ECUS = [Ecu.fwdRadar, Ecu.fwdCamera, Ecu.eps] +# So far we've only seen dates in fwdCamera +# TODO: there are date codes in the ABS firmware versions in hex +DATE_FW_ECUS = [Ecu.fwdCamera] + +# Note: an ECU on CAN FD cars may sometimes send 0x30080aaaaaaaaaaa (flow control continue) while we +# are attempting to query ECUs. This currently does not seem to affect fingerprinting from the camera +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + # TODO: add back whitelists + # CAN queries (OBD-II port) + Request( + [HYUNDAI_VERSION_REQUEST_LONG], + [HYUNDAI_VERSION_RESPONSE], + ), + + # CAN & CAN-FD queries (from camera) + Request( + [HYUNDAI_VERSION_REQUEST_LONG], + [HYUNDAI_VERSION_RESPONSE], + bus=0, + auxiliary=True, + ), + Request( + [HYUNDAI_VERSION_REQUEST_LONG], + [HYUNDAI_VERSION_RESPONSE], + bus=1, + auxiliary=True, + obd_multiplexing=False, + ), + + # CAN & CAN FD query to understand the three digit date code + # LKA steering cars usually use 6 digit date codes, so skip bus 1 + Request( + [HYUNDAI_ECU_MANUFACTURING_DATE], + [HYUNDAI_VERSION_RESPONSE], + bus=0, + auxiliary=True, + logging=True, + ), + + # CAN-FD alt request logging queries for hvac and parkingAdas + Request( + [HYUNDAI_VERSION_REQUEST_ALT], + [HYUNDAI_VERSION_RESPONSE], + bus=0, + auxiliary=True, + logging=True, + ), + Request( + [HYUNDAI_VERSION_REQUEST_ALT], + [HYUNDAI_VERSION_RESPONSE], + bus=1, + auxiliary=True, + logging=True, + obd_multiplexing=False, + ), + ], + # We lose these ECUs without the comma power on these cars. + # Note that we still attempt to match with them when they are present + non_essential_ecus={ + Ecu.abs: [CAR.HYUNDAI_PALISADE, CAR.HYUNDAI_SONATA, CAR.HYUNDAI_SANTA_FE_2022, CAR.KIA_K5_2021, CAR.HYUNDAI_ELANTRA_2021, + CAR.HYUNDAI_SANTA_FE, CAR.HYUNDAI_KONA_EV_2022, CAR.HYUNDAI_KONA_EV, CAR.HYUNDAI_CUSTIN_1ST_GEN, CAR.KIA_SORENTO, + CAR.KIA_CEED, CAR.KIA_SELTOS], + }, + extra_ecus=[ + (Ecu.adas, 0x730, None), # ADAS Driving ECU on platforms with LKA steering + (Ecu.parkingAdas, 0x7b1, None), # ADAS Parking ECU (may exist on all platforms) + (Ecu.hvac, 0x7b3, None), # HVAC Control Assembly + (Ecu.cornerRadar, 0x7b7, None), + (Ecu.combinationMeter, 0x7c6, None), # CAN FD Instrument cluster + ], + # Custom fuzzy fingerprinting function using platform codes, part numbers + FW dates: + match_fw_to_car_fuzzy=match_fw_to_car_fuzzy, +) + +CHECKSUM = { + "crc8": CAR.with_flags(HyundaiFlags.CHECKSUM_CRC8), + "6B": CAR.with_flags(HyundaiFlags.CHECKSUM_6B), +} + +CAN_GEARS = { + # which message has the gear. hybrid and EV use ELECT_GEAR + "use_cluster_gears": CAR.with_flags(HyundaiFlags.CLUSTER_GEARS), + "use_tcu_gears": CAR.with_flags(HyundaiFlags.TCU_GEARS), +} + +CANFD_CAR = CAR.with_flags(HyundaiFlags.CANFD) +CANFD_RADAR_SCC_CAR = CAR.with_flags(HyundaiFlags.RADAR_SCC) # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR + +CANFD_UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.CANFD_NO_RADAR_DISABLE) # TODO: merge with UNSUPPORTED_LONGITUDINAL_CAR + +CAMERA_SCC_CAR = CAR.with_flags(HyundaiFlags.CAMERA_SCC) + +HYBRID_CAR = CAR.with_flags(HyundaiFlags.HYBRID) + +EV_CAR = CAR.with_flags(HyundaiFlags.EV) + +LEGACY_SAFETY_MODE_CAR = CAR.with_flags(HyundaiFlags.LEGACY) + +# TODO: another PR with (HyundaiFlags.LEGACY | HyundaiFlags.UNSUPPORTED_LONGITUDINAL | HyundaiFlags.CAMERA_SCC | +# HyundaiFlags.CANFD_RADAR_SCC | HyundaiFlags.CANFD_NO_RADAR_DISABLE | ) +UNSUPPORTED_LONGITUDINAL_CAR = CAR.with_flags(HyundaiFlags.LEGACY) | CAR.with_flags(HyundaiFlags.UNSUPPORTED_LONGITUDINAL) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/include/c++.capnp b/opendbc_repo/opendbc/car/include/c++.capnp new file mode 100644 index 0000000000..2bda547179 --- /dev/null +++ b/opendbc_repo/opendbc/car/include/c++.capnp @@ -0,0 +1,26 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# 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. + +@0xbdf87d7bb8304e81; +$namespace("capnp::annotations"); + +annotation namespace(file): Text; +annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text; diff --git a/opendbc_repo/opendbc/car/interfaces.py b/opendbc_repo/opendbc/car/interfaces.py new file mode 100644 index 0000000000..088c3470b7 --- /dev/null +++ b/opendbc_repo/opendbc/car/interfaces.py @@ -0,0 +1,407 @@ +import os +import numpy as np +import time +import tomllib +from abc import abstractmethod, ABC +from enum import StrEnum +from typing import Any +from collections.abc import Callable +from functools import cache + +from opendbc.car import DT_CTRL, apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness, STD_CARGO_KG +from opendbc.car import structs +from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable +from opendbc.car.common.basedir import BASEDIR +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.common.simple_kalman import KF1D, get_kalman_gain +from opendbc.car.values import PLATFORMS +from opendbc.can import CANParser + +GearShifter = structs.CarState.GearShifter +ButtonType = structs.CarState.ButtonEvent.Type + +V_CRUISE_MAX = 145 +MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS +ACCEL_MAX = 2.0 +ACCEL_MIN = -3.5 + +TORQUE_PARAMS_PATH = os.path.join(BASEDIR, 'torque_data/params.toml') +TORQUE_OVERRIDE_PATH = os.path.join(BASEDIR, 'torque_data/override.toml') +TORQUE_SUBSTITUTE_PATH = os.path.join(BASEDIR, 'torque_data/substitute.toml') + +GEAR_SHIFTER_MAP: dict[str, structs.CarState.GearShifter] = { + 'P': GearShifter.park, 'PARK': GearShifter.park, + 'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse, + 'N': GearShifter.neutral, 'NEUTRAL': GearShifter.neutral, + 'E': GearShifter.eco, 'ECO': GearShifter.eco, + 'T': GearShifter.manumatic, 'MANUAL': GearShifter.manumatic, + 'D': GearShifter.drive, 'DRIVE': GearShifter.drive, + 'S': GearShifter.sport, 'SPORT': GearShifter.sport, + 'L': GearShifter.low, 'LOW': GearShifter.low, + 'B': GearShifter.brake, 'BRAKE': GearShifter.brake, +} + +TorqueFromLateralAccelCallbackType = Callable[[float, structs.CarParams.LateralTorqueTuning, bool], float] +LateralAccelFromTorqueCallbackType = Callable[[float, structs.CarParams.LateralTorqueTuning, bool], float] + + +@cache +def get_torque_params(): + with open(TORQUE_SUBSTITUTE_PATH, 'rb') as f: + sub = tomllib.load(f) + with open(TORQUE_PARAMS_PATH, 'rb') as f: + params = tomllib.load(f) + with open(TORQUE_OVERRIDE_PATH, 'rb') as f: + override = tomllib.load(f) + + torque_params = {} + for candidate in (sub.keys() | params.keys() | override.keys()) - {'legend'}: + if sum([candidate in x for x in [sub, params, override]]) > 1: + raise RuntimeError(f'{candidate} is defined twice in torque config') + + sub_candidate = sub.get(candidate, candidate) + + if sub_candidate in override: + out = override[sub_candidate] + elif sub_candidate in params: + out = params[sub_candidate] + else: + raise NotImplementedError(f"Did not find torque params for {sub_candidate}") + + torque_params[sub_candidate] = {key: out[i] for i, key in enumerate(params['legend'])} + if candidate in sub: + torque_params[candidate] = torque_params[sub_candidate] + + return torque_params + +# generic car and radar interfaces + + +class RadarInterfaceBase(ABC): + def __init__(self, CP: structs.CarParams): + self.CP = CP + self.rcp = None + self.pts: dict[int, structs.RadarData.RadarPoint] = {} + self.frame = 0 + + def update(self, can_packets: list[tuple[int, list[CanData]]]) -> structs.RadarDataT | None: + self.frame += 1 + if (self.frame % 5) == 0: # 20 Hz is very standard + return structs.RadarData() + return None + + +class CarInterfaceBase(ABC): + CarState: 'CarStateBase' + CarController: 'CarControllerBase' + RadarInterface: 'RadarInterfaceBase' = RadarInterfaceBase + + def __init__(self, CP: structs.CarParams): + self.CP = CP + + self.frame = 0 + self.v_ego_cluster_seen = False + + self.CS: CarStateBase = self.CarState(CP) + self.can_parsers: dict[StrEnum, CANParser] = self.CS.get_can_parsers(CP) + + dbc_names = {bus: cp.dbc_name for bus, cp in self.can_parsers.items()} + self.CC: CarControllerBase = self.CarController(dbc_names, CP) + + def apply(self, c: structs.CarControl, now_nanos: int | None = None) -> tuple[structs.CarControl.Actuators, list[CanData]]: + if now_nanos is None: + now_nanos = int(time.monotonic() * 1e9) + return self.CC.update(c, self.CS, now_nanos) + + @staticmethod + def get_pid_accel_limits(CP, current_speed, cruise_speed): + return ACCEL_MIN, ACCEL_MAX + + @classmethod + def get_non_essential_params(cls, candidate: str) -> structs.CarParams: + """ + Parameters essential to controlling the car may be incomplete or wrong without FW versions or fingerprints. + """ + return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False, False) + + @classmethod + def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[structs.CarParams.CarFw], + alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams: + ret = CarInterfaceBase.get_std_params(candidate) + + platform = PLATFORMS[candidate] + ret.mass = platform.config.specs.mass + ret.wheelbase = platform.config.specs.wheelbase + ret.steerRatio = platform.config.specs.steerRatio + ret.centerToFront = ret.wheelbase * platform.config.specs.centerToFrontRatio + ret.minEnableSpeed = platform.config.specs.minEnableSpeed + ret.minSteerSpeed = platform.config.specs.minSteerSpeed + ret.tireStiffnessFactor = platform.config.specs.tireStiffnessFactor + ret.flags |= int(platform.config.flags) + + ret = cls._get_params(ret, candidate, fingerprint, car_fw, alpha_long, is_release, docs) + + # Vehicle mass is published curb weight plus assumed payload such as a human driver; notCars have no assumed payload + if not ret.notCar: + ret.mass = ret.mass + STD_CARGO_KG + + # Set params dependent on values set by the car interface + ret.rotationalInertia = scale_rot_inertia(ret.mass, ret.wheelbase) + ret.tireStiffnessFront, ret.tireStiffnessRear = scale_tire_stiffness(ret.mass, ret.wheelbase, ret.centerToFront, ret.tireStiffnessFactor) + + return ret + + @staticmethod + @abstractmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint: dict[int, dict[int, int]], + car_fw: list[structs.CarParams.CarFw], alpha_long: bool, is_release: bool, docs: bool) -> structs.CarParams: + raise NotImplementedError + + @staticmethod + def init(CP: structs.CarParams, can_recv: CanRecvCallable, can_send: CanSendCallable): + """Used to disable longitudinal ECUs as needed""" + + @staticmethod + def deinit(CP: structs.CarParams, can_recv: CanRecvCallable, can_send: CanSendCallable): + """Used to re-enable longitudinal ECUs as needed""" + + @staticmethod + def get_steer_feedforward_default(desired_angle, v_ego): + # Proportional to realigning tire momentum: lateral acceleration. + return desired_angle * (v_ego**2) + + def get_steer_feedforward_function(self): + return self.get_steer_feedforward_default + + def torque_from_lateral_accel_linear(self, lateral_acceleration: float, torque_params: structs.CarParams.LateralTorqueTuning) -> float: + # The default is a linear relationship between torque and lateral acceleration (accounting for road roll and steering friction) + return lateral_acceleration / float(torque_params.latAccelFactor) + + def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType: + return self.torque_from_lateral_accel_linear + + def lateral_accel_from_torque_linear(self, torque: float, torque_params: structs.CarParams.LateralTorqueTuning) -> float: + return torque * float(torque_params.latAccelFactor) + + def lateral_accel_from_torque(self) -> LateralAccelFromTorqueCallbackType: + return self.lateral_accel_from_torque_linear + + # returns a set of default params to avoid repetition in car specific params + @staticmethod + def get_std_params(candidate: str) -> structs.CarParams: + ret = structs.CarParams() + ret.carFingerprint = candidate + + # Car docs fields + ret.maxLateralAccel = get_torque_params()[candidate]['MAX_LAT_ACCEL_MEASURED'] + ret.autoResumeSng = True # describes whether car can resume from a stop automatically + + # standard ALC params + ret.tireStiffnessFactor = 1.0 + ret.steerControlType = structs.CarParams.SteerControlType.torque + ret.minSteerSpeed = 0. + ret.wheelSpeedFactor = 1.0 + + ret.pcmCruise = True # openpilot's state is tied to the PCM's cruise state on most cars + ret.minEnableSpeed = -1. # enable is done by stock ACC, so ignore this + ret.steerRatioRear = 0. # no rear steering, at least on the listed cars aboveA + ret.openpilotLongitudinalControl = False + ret.stopAccel = -2.0 + ret.stoppingDecelRate = 0.8 # brake_travel/s while trying to stop + ret.vEgoStopping = 0.5 + ret.vEgoStarting = 0.5 + ret.longitudinalTuning.kf = 1. + ret.longitudinalTuning.kpBP = [0.] + ret.longitudinalTuning.kpV = [0.] + ret.longitudinalTuning.kiBP = [0.] + ret.longitudinalTuning.kiV = [0.] + # TODO estimate car specific lag, use .15s for now + ret.longitudinalActuatorDelay = 0.15 + ret.steerLimitTimer = 1.0 + return ret + + @staticmethod + def configure_torque_tune(candidate: str, tune: structs.CarParams.LateralTuning, steering_angle_deadzone_deg: float = 0.0): + params = get_torque_params()[candidate] + + tune.init('torque') + tune.torque.kf = 1.0 + tune.torque.kp = 1.0 + tune.torque.ki = 0.3 + tune.torque.friction = params['FRICTION'] + tune.torque.latAccelFactor = params['LAT_ACCEL_FACTOR'] + tune.torque.latAccelOffset = 0.0 + tune.torque.steeringAngleDeadzoneDeg = steering_angle_deadzone_deg + + def update(self, can_packets: list[tuple[int, list[CanData]]]) -> structs.CarState: + # parse can + for cp in self.can_parsers.values(): + if cp is not None: + cp.update(can_packets) + + # get CarState + ret = self.CS.update(self.can_parsers) + + ret.canValid = all(cp.can_valid for cp in self.can_parsers.values()) + ret.canTimeout = any(cp.bus_timeout for cp in self.can_parsers.values()) + + if ret.vEgoCluster == 0.0 and not self.v_ego_cluster_seen: + ret.vEgoCluster = ret.vEgo + else: + self.v_ego_cluster_seen = True + + # Many cars apply hysteresis to the ego dash speed + ret.vEgoCluster = apply_hysteresis(ret.vEgoCluster, self.CS.out.vEgoCluster, self.CS.cluster_speed_hyst_gap) + if abs(ret.vEgo) < self.CS.cluster_min_speed: + ret.vEgoCluster = 0.0 + + if ret.cruiseState.speedCluster == 0: + ret.cruiseState.speedCluster = ret.cruiseState.speed + + ret.buttonEnable = self.CS.update_button_enable(ret.buttonEvents) + + # save for next iteration + self.CS.out = ret + + return ret + + +class CarStateBase(ABC): + def __init__(self, CP: structs.CarParams): + self.CP = CP + self.car_fingerprint = CP.carFingerprint + self.out = structs.CarState() + + self.cruise_buttons = 0 + self.left_blinker_cnt = 0 + self.right_blinker_cnt = 0 + self.steering_pressed_cnt = 0 + self.left_blinker_prev = False + self.right_blinker_prev = False + self.low_speed_alert = False + self.cluster_speed_hyst_gap = 0.0 + self.cluster_min_speed = 0.0 # min speed before dropping to 0 + self.secoc_key: bytes = b"00" * 16 + + Q = [[0.0, 0.0], [0.0, 100.0]] + R = 0.3 + A = [[1.0, DT_CTRL], [0.0, 1.0]] + C = [[1.0, 0.0]] + x0=[[0.0], [0.0]] + K = get_kalman_gain(DT_CTRL, np.array(A), np.array(C), np.array(Q), R) + self.v_ego_kf = KF1D(x0=x0, A=A, C=C[0], K=K) + + @abstractmethod + def update(self, can_parsers) -> structs.CarState: + pass + + def parse_wheel_speeds(self, cs, fl, fr, rl, rr, unit=CV.KPH_TO_MS): + cs.vEgoRaw = sum((fl, fr, rl, rr)) / 4 * unit * self.CP.wheelSpeedFactor + cs.vEgo, cs.aEgo = self.update_speed_kf(cs.vEgoRaw) + + def update_speed_kf(self, v_ego_raw): + if abs(v_ego_raw - self.v_ego_kf.x[0][0]) > 2.0: # Prevent large accelerations when car starts at non zero speed + self.v_ego_kf.set_x([[v_ego_raw], [0.0]]) + + v_ego_x = self.v_ego_kf.update(v_ego_raw) + return float(v_ego_x[0]), float(v_ego_x[1]) + + def update_blinker_from_lamp(self, blinker_time: int, left_blinker_lamp: bool, right_blinker_lamp: bool): + """Update blinkers from lights. Enable output when light was seen within the last `blinker_time` + iterations""" + # TODO: Handle case when switching direction. Now both blinkers can be on at the same time + self.left_blinker_cnt = blinker_time if left_blinker_lamp else max(self.left_blinker_cnt - 1, 0) + self.right_blinker_cnt = blinker_time if right_blinker_lamp else max(self.right_blinker_cnt - 1, 0) + return self.left_blinker_cnt > 0, self.right_blinker_cnt > 0 + + def update_steering_pressed(self, steering_pressed, steering_pressed_min_count): + """Applies filtering on steering pressed for noisy driver torque signals.""" + self.steering_pressed_cnt += 1 if steering_pressed else -1 + self.steering_pressed_cnt = int(np.clip(self.steering_pressed_cnt, 0, steering_pressed_min_count * 2 + 1)) + return self.steering_pressed_cnt > steering_pressed_min_count + + def update_blinker_from_stalk(self, blinker_time: int, left_blinker_stalk: bool, right_blinker_stalk: bool): + """Update blinkers from stalk position. When stalk is seen the blinker will be on for at least blinker_time, + or until the stalk is turned off, whichever is longer. If the opposite stalk direction is seen the blinker + is forced to the other side. On a rising edge of the stalk the timeout is reset.""" + + if left_blinker_stalk: + self.right_blinker_cnt = 0 + if not self.left_blinker_prev: + self.left_blinker_cnt = blinker_time + + if right_blinker_stalk: + self.left_blinker_cnt = 0 + if not self.right_blinker_prev: + self.right_blinker_cnt = blinker_time + + self.left_blinker_cnt = max(self.left_blinker_cnt - 1, 0) + self.right_blinker_cnt = max(self.right_blinker_cnt - 1, 0) + + self.left_blinker_prev = left_blinker_stalk + self.right_blinker_prev = right_blinker_stalk + + return bool(left_blinker_stalk or self.left_blinker_cnt > 0), bool(right_blinker_stalk or self.right_blinker_cnt > 0) + + def update_button_enable(self, buttonEvents: list[structs.CarState.ButtonEvent]): + if not self.CP.pcmCruise: + for b in buttonEvents: + # Enable OP long on falling edge of enable buttons + if b.type in (ButtonType.accelCruise, ButtonType.decelCruise) and not b.pressed: + return True + return False + + @staticmethod + def parse_gear_shifter(gear: str | None) -> structs.CarState.GearShifter: + if gear is None: + return GearShifter.unknown + return GEAR_SHIFTER_MAP.get(gear.upper(), GearShifter.unknown) + + @staticmethod + def get_can_parsers(CP) -> dict[StrEnum, CANParser]: + return {} + + +class CarControllerBase(ABC): + def __init__(self, dbc_names: dict[StrEnum, str], CP: structs.CarParams): + self.CP = CP + self.frame = 0 + self.secoc_key: bytes = b"00" * 16 + + @abstractmethod + def update(self, CC: structs.CarControl, CS: CarStateBase, now_nanos: int) -> tuple[structs.CarControl.Actuators, list[CanData]]: + pass + + +INTERFACE_ATTR_FILE = { + "FINGERPRINTS": "fingerprints", + "FW_VERSIONS": "fingerprints", +} + +# interface-specific helpers + + +def get_interface_attr(attr: str, combine_brands: bool = False, ignore_none: bool = False) -> dict[str | StrEnum, Any]: + # read all the folders in opendbc/car and return a dict where: + # - keys are all the car models or brand names + # - values are attr values from all car folders + result = {} + for car_folder in sorted([x[0] for x in os.walk(BASEDIR)]): + try: + brand_name = car_folder.split('/')[-1] + brand_values = __import__(f'opendbc.car.{brand_name}.{INTERFACE_ATTR_FILE.get(attr, "values")}', fromlist=[attr]) + if hasattr(brand_values, attr) or not ignore_none: + attr_data = getattr(brand_values, attr, None) + else: + continue + + if combine_brands: + if isinstance(attr_data, dict): + for f, v in attr_data.items(): + result[f] = v + else: + result[brand_name] = attr_data + except (ImportError, OSError): + pass + + return result diff --git a/opendbc_repo/opendbc/car/isotp.py b/opendbc_repo/opendbc/car/isotp.py new file mode 100644 index 0000000000..8ead67e6f2 --- /dev/null +++ b/opendbc_repo/opendbc/car/isotp.py @@ -0,0 +1,147 @@ +import binascii +import time + +DEBUG = False + + +def msg(x): + if DEBUG: + print("S:", binascii.hexlify(x)) + assert len(x) <= 7 + ret = bytes([len(x)]) + x + return ret.ljust(8, b"\x00") + + +kmsgs = [] + + +def recv(panda, cnt, addr, nbus): + global kmsgs + ret = [] + + while len(ret) < cnt: + kmsgs += panda.can_recv() + nmsgs = [] + for ids, dat, bus in kmsgs: + if ids == addr and bus == nbus and len(ret) < cnt: + ret.append(dat) + else: + # leave around + nmsgs.append((ids, dat, bus)) + kmsgs = nmsgs[-256:] + return ret + + +def isotp_recv_subaddr(panda, addr, bus, sendaddr, subaddr): + msg = recv(panda, 1, addr, bus)[0] + + # TODO: handle other subaddr also communicating + assert msg[0] == subaddr + + if msg[1] & 0xf0 == 0x10: + # first + tlen = ((msg[1] & 0xf) << 8) | msg[2] + dat = msg[3:] + + # 0 block size? + CONTINUE = bytes([subaddr]) + b"\x30" + b"\x00" * 6 + panda.can_send(sendaddr, CONTINUE, bus) + + idx = 1 + for mm in recv(panda, (tlen - len(dat) + 5) // 6, addr, bus): + assert mm[0] == subaddr + assert mm[1] == (0x20 | (idx & 0xF)) + dat += mm[2:] + idx += 1 + elif msg[1] & 0xf0 == 0x00: + # single + tlen = msg[1] & 0xf + dat = msg[2:] + else: + print(binascii.hexlify(msg)) + raise AssertionError + + return dat[0:tlen] + +# **** import below this line **** + + +def isotp_send(panda, x, addr, bus=0, recvaddr=None, subaddr=None, rate=None): + if recvaddr is None: + recvaddr = addr + 8 + + if len(x) <= 7 and subaddr is None: + panda.can_send(addr, msg(x), bus) + elif len(x) <= 6 and subaddr is not None: + panda.can_send(addr, bytes([subaddr]) + msg(x)[0:7], bus) + else: + if subaddr: + ss = bytes([subaddr, 0x10 + (len(x) >> 8), len(x) & 0xFF]) + x[0:5] + x = x[5:] + else: + ss = bytes([0x10 + (len(x) >> 8), len(x) & 0xFF]) + x[0:6] + x = x[6:] + idx = 1 + sends = [] + while len(x) > 0: + if subaddr: + sends.append((bytes([subaddr, 0x20 + (idx & 0xF)]) + x[0:6]).ljust(8, b"\x00")) + x = x[6:] + else: + sends.append((bytes([0x20 + (idx & 0xF)]) + x[0:7]).ljust(8, b"\x00")) + x = x[7:] + idx += 1 + + # actually send + panda.can_send(addr, ss, bus) + rr = recv(panda, 1, recvaddr, bus)[0] + if rr.find(b"\x30\x01") != -1: + for s in sends[:-1]: + panda.can_send(addr, s, 0) + rr = recv(panda, 1, recvaddr, bus)[0] + panda.can_send(addr, sends[-1], 0) + else: + if rate is None: + panda.can_send_many([(addr, s, bus) for s in sends]) + else: + for dat in sends: + panda.can_send(addr, dat, bus) + time.sleep(rate) + + +def isotp_recv(panda, addr, bus=0, sendaddr=None, subaddr=None): + if sendaddr is None: + sendaddr = addr - 8 + + if subaddr is not None: + dat = isotp_recv_subaddr(panda, addr, bus, sendaddr, subaddr) + else: + msg = recv(panda, 1, addr, bus)[0] + + if msg[0] & 0xf0 == 0x10: + # first + tlen = ((msg[0] & 0xf) << 8) | msg[1] + dat = msg[2:] + + # 0 block size? + CONTINUE = b"\x30" + b"\x00" * 7 + + panda.can_send(sendaddr, CONTINUE, bus) + + idx = 1 + for mm in recv(panda, (tlen - len(dat) + 6) // 7, addr, bus): + assert mm[0] == (0x20 | (idx & 0xF)) + dat += mm[1:] + idx += 1 + elif msg[0] & 0xf0 == 0x00: + # single + tlen = msg[0] & 0xf + dat = msg[1:] + else: + raise AssertionError + dat = dat[0:tlen] + + if DEBUG: + print("R:", binascii.hexlify(dat)) + + return dat diff --git a/opendbc_repo/opendbc/car/isotp_parallel_query.py b/opendbc_repo/opendbc/car/isotp_parallel_query.py new file mode 100644 index 0000000000..57925e4239 --- /dev/null +++ b/opendbc_repo/opendbc/car/isotp_parallel_query.py @@ -0,0 +1,170 @@ +import time +from collections import defaultdict +from functools import partial + +from opendbc.car import uds +from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable +from opendbc.car.carlog import carlog +from opendbc.car.fw_query_definitions import AddrType + + +class IsoTpParallelQuery: + def __init__(self, can_send: CanSendCallable, can_recv: CanRecvCallable, bus: int, addrs: list[int] | list[AddrType], + request: list[bytes], response: list[bytes], response_offset: int = 0x8, + functional_addrs: list[int] = None, response_pending_timeout: float = 10) -> None: + self.can_send = can_send + self.can_recv = can_recv + self.bus = bus + self.request = request + self.response = response + self.functional_addrs = functional_addrs or [] + self.response_pending_timeout = response_pending_timeout + + real_addrs = [a if isinstance(a, tuple) else (a, None) for a in addrs] + for tx_addr, _ in real_addrs: + assert tx_addr not in uds.FUNCTIONAL_ADDRS, f"Functional address should be defined in functional_addrs: {hex(tx_addr)}" + + self.msg_addrs = {tx_addr: uds.get_rx_addr_for_tx_addr(tx_addr[0], rx_offset=response_offset) for tx_addr in real_addrs} + self.msg_buffer: dict[int, list[CanData]] = defaultdict(list) + + def rx(self) -> None: + """Drain can socket and sort messages into buffers based on address""" + can_packets = self.can_recv(wait_for_one=True) + + for packet in can_packets: + for msg in packet: + if msg.src == self.bus and msg.address in self.msg_addrs.values(): + self.msg_buffer[msg.address].append(CanData(msg.address, msg.dat, msg.src)) + + def _can_tx(self, tx_addr: int, dat: bytes, bus: int): + """Helper function to send single message""" + msg = CanData(tx_addr, dat, bus) + self.can_send([msg]) + + def _can_rx(self, addr, sub_addr=None): + """Helper function to retrieve message with specified address and subaddress from buffer""" + keep_msgs = [] + + if sub_addr is None: + msgs = self.msg_buffer[addr] + else: + # Filter based on subaddress + msgs = [] + for m in self.msg_buffer[addr]: + first_byte = m[1][0] + if first_byte == sub_addr: + msgs.append(m) + else: + keep_msgs.append(m) + + self.msg_buffer[addr] = keep_msgs + return msgs + + def _drain_rx(self) -> None: + self.can_recv() + self.msg_buffer = defaultdict(list) + + def _create_isotp_msg(self, tx_addr: int, sub_addr: int | None, rx_addr: int): + can_client = uds.CanClient(self._can_tx, partial(self._can_rx, rx_addr, sub_addr=sub_addr), tx_addr, rx_addr, + self.bus, sub_addr=sub_addr) + + # uses iso-tp frame separation time of 10 ms + # TODO: use single_frame_mode so ECUs can send as fast as they want, + # as well as reduces chances we process messages from previous queries + return uds.IsoTpMessage(can_client, timeout=0, separation_time=0.01) + + def get_data(self, timeout: float, total_timeout: float = 60.) -> dict[AddrType, bytes]: + self._drain_rx() + + # Create message objects + msgs = {} + request_counter = {} + request_done = {} + for tx_addr, rx_addr in self.msg_addrs.items(): + msgs[tx_addr] = self._create_isotp_msg(*tx_addr, rx_addr) + request_counter[tx_addr] = 0 + request_done[tx_addr] = False + + # Send first request to functional addrs, subsequent responses are handled on physical addrs + if len(self.functional_addrs): + for addr in self.functional_addrs: + self._create_isotp_msg(addr, None, -1).send(self.request[0]) + + # Send first frame (single or first) to all addresses and receive asynchronously in the loop below. + # If querying functional addrs, only set up physical IsoTpMessages to send consecutive frames + for msg in msgs.values(): + msg.send(self.request[0], setup_only=len(self.functional_addrs) > 0) + + results = {} + start_time = time.monotonic() + addrs_responded = set() # track addresses that have ever sent a valid iso-tp frame for timeout logging + response_timeouts = {tx_addr: start_time + timeout for tx_addr in self.msg_addrs} + while True: + self.rx() + + for tx_addr, msg in msgs.items(): + try: + dat, rx_in_progress = msg.recv() + except Exception: + carlog.exception(f"Error processing UDS response: {tx_addr}") + request_done[tx_addr] = True + continue + + # Extend timeout for each consecutive ISO-TP frame to avoid timing out on long responses + if rx_in_progress: + addrs_responded.add(tx_addr) + response_timeouts[tx_addr] = time.monotonic() + timeout + + if dat is None: + continue + + # Log unexpected empty responses + if len(dat) == 0: + carlog.error(f"iso-tp query empty response: {tx_addr}") + request_done[tx_addr] = True + continue + + counter = request_counter[tx_addr] + expected_response = self.response[counter] + response_valid = dat.startswith(expected_response) + + if response_valid: + if counter + 1 < len(self.request): + response_timeouts[tx_addr] = time.monotonic() + timeout + msg.send(self.request[counter + 1]) + request_counter[tx_addr] += 1 + else: + results[tx_addr] = dat[len(expected_response):] + request_done[tx_addr] = True + else: + error_code = dat[2] if len(dat) > 2 else -1 + if error_code == 0x78: + response_timeouts[tx_addr] = time.monotonic() + self.response_pending_timeout + carlog.error(f"iso-tp query response pending: {tx_addr}") + else: + request_done[tx_addr] = True + carlog.error(f"iso-tp query bad response: {tx_addr} - 0x{dat.hex()}") + + # Mark request done if address timed out + cur_time = time.monotonic() + for tx_addr in response_timeouts: + if cur_time - response_timeouts[tx_addr] > 0: + if not request_done[tx_addr]: + if request_counter[tx_addr] > 0: + carlog.error(f"iso-tp query timeout after receiving partial response: {tx_addr}") + elif tx_addr in addrs_responded: + carlog.error(f"iso-tp query timeout while receiving response: {tx_addr}") + # TODO: handle functional addresses + # else: + # carlog.error(f"iso-tp query timeout with no response: {tx_addr}") + request_done[tx_addr] = True + + # Break if all requests are done (finished or timed out) + if all(request_done.values()): + break + + if cur_time - start_time > total_timeout: + carlog.error("iso-tp query timeout while receiving data") + break + + return results diff --git a/opendbc_repo/opendbc/car/lateral.py b/opendbc_repo/opendbc/car/lateral.py new file mode 100644 index 0000000000..9d120e308b --- /dev/null +++ b/opendbc_repo/opendbc/car/lateral.py @@ -0,0 +1,169 @@ +import math +import numpy as np +from dataclasses import dataclass +from opendbc.car import structs, rate_limit, DT_CTRL +from opendbc.car.vehicle_model import VehicleModel + +FRICTION_THRESHOLD = 0.3 + +# ISO 11270 +ISO_LATERAL_ACCEL = 3.0 # m/s^2 +ISO_LATERAL_JERK = 5.0 # m/s^3 + + +@dataclass +class AngleSteeringLimits: + # v1 limits (using apply_std_steer_angle_limits) + STEER_ANGLE_MAX: float + ANGLE_RATE_LIMIT_UP: tuple[list[float], list[float]] + ANGLE_RATE_LIMIT_DOWN: tuple[list[float], list[float]] + + # v2 vehicle model limits (using apply_steer_angle_limits_vm) + MAX_LATERAL_ACCEL: float = 0 + MAX_LATERAL_JERK: float = 0 + MAX_ANGLE_RATE: float = math.inf + + +def apply_driver_steer_torque_limits(apply_torque: int, apply_torque_last: int, driver_torque: float, LIMITS, steer_max: int = None): + # some safety modes utilize a dynamic max steer + if steer_max is None: + steer_max = LIMITS.STEER_MAX + + # limits due to driver torque + driver_max_torque = steer_max + (LIMITS.STEER_DRIVER_ALLOWANCE + driver_torque * LIMITS.STEER_DRIVER_FACTOR) * LIMITS.STEER_DRIVER_MULTIPLIER + driver_min_torque = -steer_max + (-LIMITS.STEER_DRIVER_ALLOWANCE + driver_torque * LIMITS.STEER_DRIVER_FACTOR) * LIMITS.STEER_DRIVER_MULTIPLIER + max_steer_allowed = max(min(steer_max, driver_max_torque), 0) + min_steer_allowed = min(max(-steer_max, driver_min_torque), 0) + apply_torque = np.clip(apply_torque, min_steer_allowed, max_steer_allowed) + + # slow rate if steer torque increases in magnitude + if apply_torque_last > 0: + apply_torque = np.clip(apply_torque, max(apply_torque_last - LIMITS.STEER_DELTA_DOWN, -LIMITS.STEER_DELTA_UP), + apply_torque_last + LIMITS.STEER_DELTA_UP) + else: + apply_torque = np.clip(apply_torque, apply_torque_last - LIMITS.STEER_DELTA_UP, + min(apply_torque_last + LIMITS.STEER_DELTA_DOWN, LIMITS.STEER_DELTA_UP)) + + return int(round(float(apply_torque))) + + +def apply_dist_to_meas_limits(val, val_last, val_meas, + STEER_DELTA_UP, STEER_DELTA_DOWN, + STEER_ERROR_MAX, STEER_MAX): + # limits due to comparison of commanded val VS measured val (torque/angle/curvature) + max_lim = min(max(val_meas + STEER_ERROR_MAX, STEER_ERROR_MAX), STEER_MAX) + min_lim = max(min(val_meas - STEER_ERROR_MAX, -STEER_ERROR_MAX), -STEER_MAX) + + val = np.clip(val, min_lim, max_lim) + + # slow rate if val increases in magnitude + if val_last > 0: + val = np.clip(val, + max(val_last - STEER_DELTA_DOWN, -STEER_DELTA_UP), + val_last + STEER_DELTA_UP) + else: + val = np.clip(val, + val_last - STEER_DELTA_UP, + min(val_last + STEER_DELTA_DOWN, STEER_DELTA_UP)) + + return float(val) + + +def apply_meas_steer_torque_limits(apply_torque, apply_torque_last, motor_torque, LIMITS): + return int(round(apply_dist_to_meas_limits(apply_torque, apply_torque_last, motor_torque, + LIMITS.STEER_DELTA_UP, LIMITS.STEER_DELTA_DOWN, + LIMITS.STEER_ERROR_MAX, LIMITS.STEER_MAX))) + + +def apply_std_steer_angle_limits(apply_angle: float, apply_angle_last: float, v_ego: float, steering_angle: float, + lat_active: bool, limits: AngleSteeringLimits) -> float: + # pick angle rate limits based on wind up/down + steer_up = apply_angle_last * apply_angle >= 0. and abs(apply_angle) > abs(apply_angle_last) + rate_limits = limits.ANGLE_RATE_LIMIT_UP if steer_up else limits.ANGLE_RATE_LIMIT_DOWN + + angle_rate_lim = np.interp(v_ego, rate_limits[0], rate_limits[1]) + new_apply_angle = np.clip(apply_angle, apply_angle_last - angle_rate_lim, apply_angle_last + angle_rate_lim) + + # angle is current steering wheel angle when inactive on all angle cars + if not lat_active: + new_apply_angle = steering_angle + + return float(np.clip(new_apply_angle, -limits.STEER_ANGLE_MAX, limits.STEER_ANGLE_MAX)) + + +def get_max_angle_delta_vm(v_ego_raw: float, VM: VehicleModel, limits): + """Calculate the maximum steering angle rate based on lateral jerk limits.""" + max_curvature_rate_sec = limits.ANGLE_LIMITS.MAX_LATERAL_JERK / (v_ego_raw ** 2) # (1/m)/s + max_angle_rate_sec = math.degrees(VM.get_steer_from_curvature(max_curvature_rate_sec, v_ego_raw, 0)) # deg/s + return max_angle_rate_sec * (DT_CTRL * limits.STEER_STEP) + + +def get_max_angle_vm(v_ego_raw: float, VM: VehicleModel, limits): + """Calculate the maximum steering angle based on lateral acceleration limits.""" + max_curvature = limits.ANGLE_LIMITS.MAX_LATERAL_ACCEL / (v_ego_raw ** 2) # 1/m + return math.degrees(VM.get_steer_from_curvature(max_curvature, v_ego_raw, 0)) # deg + + +def apply_steer_angle_limits_vm(apply_angle: float, apply_angle_last: float, v_ego_raw: float, steering_angle: float, + lat_active: bool, limits, VM: VehicleModel) -> float: + """Apply jerk, accel, and safety limit constraints to steering angle.""" + v_ego_raw = max(v_ego_raw, 1) + + # *** max lateral jerk limit *** + max_angle_delta = get_max_angle_delta_vm(v_ego_raw, VM, limits) + + # prevent fault/low speed comfort + max_angle_delta = min(max_angle_delta, limits.ANGLE_LIMITS.MAX_ANGLE_RATE) + new_apply_angle = rate_limit(apply_angle, apply_angle_last, -max_angle_delta, max_angle_delta) + + # *** max lateral accel limit *** + max_angle = get_max_angle_vm(v_ego_raw, VM, limits) + new_apply_angle = np.clip(new_apply_angle, -max_angle, max_angle) + + # angle is current angle when inactive + if not lat_active: + new_apply_angle = steering_angle + + # prevent fault + return float(np.clip(new_apply_angle, -limits.ANGLE_LIMITS.STEER_ANGLE_MAX, limits.ANGLE_LIMITS.STEER_ANGLE_MAX)) + + +def common_fault_avoidance(fault_condition: bool, request: bool, above_limit_frames: int, + max_above_limit_frames: int, max_mismatching_frames: int = 1): + """ + Several cars have the ability to work around their EPS limits by cutting the + request bit of their LKAS message after a certain number of frames above the limit. + """ + + # Count up to max_above_limit_frames, at which point we need to cut the request for above_limit_frames to avoid a fault + if request and fault_condition: + above_limit_frames += 1 + else: + above_limit_frames = 0 + + # Once we cut the request bit, count additionally to max_mismatching_frames before setting the request bit high again. + # Some brands do not respect our workaround without multiple messages on the bus, for example + if above_limit_frames > max_above_limit_frames: + request = False + + if above_limit_frames >= max_above_limit_frames + max_mismatching_frames: + above_limit_frames = 0 + + return above_limit_frames, request + + +def apply_center_deadzone(error, deadzone): + if (error > - deadzone) and (error < deadzone): + error = 0. + return error + + +def get_friction(lateral_accel_error: float, lateral_accel_deadzone: float, friction_threshold: float, + torque_params: structs.CarParams.LateralTorqueTuning) -> float: + # TODO torque params' friction should be in lataxel space, not torque space + friction_interp = np.interp( + apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone), + [-friction_threshold, friction_threshold], + [-torque_params.friction * torque_params.latAccelFactor, torque_params.friction * torque_params.latAccelFactor] + ) + return float(friction_interp) diff --git a/opendbc_repo/opendbc/car/mazda/__init__.py b/opendbc_repo/opendbc/car/mazda/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/mazda/carcontroller.py b/opendbc_repo/opendbc/car/mazda/carcontroller.py new file mode 100644 index 0000000000..453f3ee200 --- /dev/null +++ b/opendbc_repo/opendbc/car/mazda/carcontroller.py @@ -0,0 +1,65 @@ +from opendbc.can import CANPacker +from opendbc.car import Bus, structs +from opendbc.car.lateral import apply_driver_steer_torque_limits +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.mazda import mazdacan +from opendbc.car.mazda.values import CarControllerParams, Buttons + +VisualAlert = structs.CarControl.HUDControl.VisualAlert + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.apply_torque_last = 0 + self.packer = CANPacker(dbc_names[Bus.pt]) + self.brake_counter = 0 + + def update(self, CC, CS, now_nanos): + can_sends = [] + + apply_torque = 0 + + if CC.latActive: + # calculate steer and also set limits due to driver torque + new_torque = int(round(CC.actuators.torque * CarControllerParams.STEER_MAX)) + apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, + CS.out.steeringTorque, CarControllerParams) + + if CC.cruiseControl.cancel: + # If brake is pressed, let us wait >70ms before trying to disable crz to avoid + # a race condition with the stock system, where the second cancel from openpilot + # will disable the crz 'main on'. crz ctrl msg runs at 50hz. 70ms allows us to + # read 3 messages and most likely sync state before we attempt cancel. + self.brake_counter = self.brake_counter + 1 + if self.frame % 10 == 0 and not (CS.out.brakePressed and self.brake_counter < 7): + # Cancel Stock ACC if it's enabled while OP is disengaged + # Send at a rate of 10hz until we sync with stock ACC state + can_sends.append(mazdacan.create_button_cmd(self.packer, self.CP, CS.crz_btns_counter, Buttons.CANCEL)) + else: + self.brake_counter = 0 + if CC.cruiseControl.resume and self.frame % 5 == 0: + # Mazda Stop and Go requires a RES button (or gas) press if the car stops more than 3 seconds + # Send Resume button when planner wants car to move + can_sends.append(mazdacan.create_button_cmd(self.packer, self.CP, CS.crz_btns_counter, Buttons.RESUME)) + + self.apply_torque_last = apply_torque + + # send HUD alerts + if self.frame % 50 == 0: + ldw = CC.hudControl.visualAlert == VisualAlert.ldw + steer_required = CC.hudControl.visualAlert == VisualAlert.steerRequired + # TODO: find a way to silence audible warnings so we can add more hud alerts + steer_required = steer_required and CS.lkas_allowed_speed + can_sends.append(mazdacan.create_alert_command(self.packer, CS.cam_laneinfo, ldw, steer_required)) + + # send steering command + can_sends.append(mazdacan.create_steering_control(self.packer, self.CP, + self.frame, apply_torque, CS.cam_lkas)) + + new_actuators = CC.actuators.as_builder() + new_actuators.torque = apply_torque / CarControllerParams.STEER_MAX + new_actuators.torqueOutputCan = apply_torque + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/mazda/carstate.py b/opendbc_repo/opendbc/car/mazda/carstate.py new file mode 100644 index 0000000000..074a13c26e --- /dev/null +++ b/opendbc_repo/opendbc/car/mazda/carstate.py @@ -0,0 +1,125 @@ +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarStateBase +from opendbc.car.mazda.values import DBC, LKAS_LIMITS + +ButtonType = structs.CarState.ButtonEvent.Type + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + self.shifter_values = can_define.dv["GEAR"]["GEAR"] + + self.crz_btns_counter = 0 + self.acc_active_last = False + self.lkas_allowed_speed = False + + self.distance_button = 0 + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + + ret = structs.CarState() + + prev_distance_button = self.distance_button + self.distance_button = cp.vl["CRZ_BTNS"]["DISTANCE_LESS"] + + self.parse_wheel_speeds(ret, + cp.vl["WHEEL_SPEEDS"]["FL"], + cp.vl["WHEEL_SPEEDS"]["FR"], + cp.vl["WHEEL_SPEEDS"]["RL"], + cp.vl["WHEEL_SPEEDS"]["RR"], + ) + + # Match panda speed reading + speed_kph = cp.vl["ENGINE_DATA"]["SPEED"] + ret.standstill = speed_kph <= .1 + + can_gear = int(cp.vl["GEAR"]["GEAR"]) + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None)) + + ret.genericToggle = bool(cp.vl["BLINK_INFO"]["HIGH_BEAMS"]) + ret.leftBlindspot = cp.vl["BSM"]["LEFT_BS_STATUS"] != 0 + ret.rightBlindspot = cp.vl["BSM"]["RIGHT_BS_STATUS"] != 0 + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(40, cp.vl["BLINK_INFO"]["LEFT_BLINK"] == 1, + cp.vl["BLINK_INFO"]["RIGHT_BLINK"] == 1) + + ret.steeringAngleDeg = cp.vl["STEER"]["STEER_ANGLE"] + ret.steeringTorque = cp.vl["STEER_TORQUE"]["STEER_TORQUE_SENSOR"] + ret.steeringPressed = abs(ret.steeringTorque) > LKAS_LIMITS.STEER_THRESHOLD + + ret.steeringTorqueEps = cp.vl["STEER_TORQUE"]["STEER_TORQUE_MOTOR"] + ret.steeringRateDeg = cp.vl["STEER_RATE"]["STEER_ANGLE_RATE"] + + # TODO: this should be from 0 - 1. + ret.brakePressed = cp.vl["PEDALS"]["BRAKE_ON"] == 1 + ret.brake = cp.vl["BRAKE"]["BRAKE_PRESSURE"] + + ret.seatbeltUnlatched = cp.vl["SEATBELT"]["DRIVER_SEATBELT"] == 0 + ret.doorOpen = any([cp.vl["DOORS"]["FL"], cp.vl["DOORS"]["FR"], + cp.vl["DOORS"]["BL"], cp.vl["DOORS"]["BR"]]) + + # TODO: this should be from 0 - 1. + ret.gasPressed = cp.vl["ENGINE_DATA"]["PEDAL_GAS"] > 0 + + # Either due to low speed or hands off + lkas_blocked = cp.vl["STEER_RATE"]["LKAS_BLOCK"] == 1 + + if self.CP.minSteerSpeed > 0: + # LKAS is enabled at 52kph going up and disabled at 45kph going down + # wait for LKAS_BLOCK signal to clear when going up since it lags behind the speed sometimes + if speed_kph > LKAS_LIMITS.ENABLE_SPEED and not lkas_blocked: + self.lkas_allowed_speed = True + elif speed_kph < LKAS_LIMITS.DISABLE_SPEED: + self.lkas_allowed_speed = False + else: + self.lkas_allowed_speed = True + + # TODO: the signal used for available seems to be the adaptive cruise signal, instead of the main on + # it should be used for carState.cruiseState.nonAdaptive instead + ret.cruiseState.available = cp.vl["CRZ_CTRL"]["CRZ_AVAILABLE"] == 1 + ret.cruiseState.enabled = cp.vl["CRZ_CTRL"]["CRZ_ACTIVE"] == 1 + ret.cruiseState.standstill = cp.vl["PEDALS"]["STANDSTILL"] == 1 + ret.cruiseState.speed = cp.vl["CRZ_EVENTS"]["CRZ_SPEED"] * CV.KPH_TO_MS + + # stock lkas should be on + # TODO: is this needed? + ret.invalidLkasSetting = cp_cam.vl["CAM_LANEINFO"]["LANE_LINES"] == 0 + + if ret.cruiseState.enabled: + if not self.lkas_allowed_speed and self.acc_active_last: + self.low_speed_alert = True + else: + self.low_speed_alert = False + ret.lowSpeedAlert = self.low_speed_alert + + # Check if LKAS is disabled due to lack of driver torque when all other states indicate + # it should be enabled (steer lockout). Don't warn until we actually get lkas active + # and lose it again, i.e, after initial lkas activation + ret.steerFaultTemporary = self.lkas_allowed_speed and lkas_blocked + + self.acc_active_last = ret.cruiseState.enabled + + self.crz_btns_counter = cp.vl["CRZ_BTNS"]["CTR"] + + # camera signals + self.cam_lkas = cp_cam.vl["CAM_LKAS"] + self.cam_laneinfo = cp_cam.vl["CAM_LANEINFO"] + ret.steerFaultPermanent = cp_cam.vl["CAM_LKAS"]["ERR_BIT_1"] == 1 + + # TODO: add button types for inc and dec + ret.buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/mazda/fingerprints.py b/opendbc_repo/opendbc/car/mazda/fingerprints.py new file mode 100644 index 0000000000..5569e28c7f --- /dev/null +++ b/opendbc_repo/opendbc/car/mazda/fingerprints.py @@ -0,0 +1,283 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.mazda.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.MAZDA_CX5_2022: { + (Ecu.eps, 0x730, None): [ + b'KBST-3210X-A-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KSD5-3210X-C-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'PEW5-188K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PGK4-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PW67-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PW67-188K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PW8F-188K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PW8G-188K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2C-188K2-G\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2D-188K2-G\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2D-188K2-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2G-188K2-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2H-188K2-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2H-188K2-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX85-188K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXFG-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXFG-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXGC-188K2-\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PY40-188K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'SH54-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'K131-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'KBSV-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KGWD-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KSD5-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'GSH7-67XK2-S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'PG69-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PG69-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PW66-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PW66-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXDL-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXFG-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXFG-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXGG-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYA4-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYJ3-21PS1-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYJ3-21PS1-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'SH51-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.MAZDA_CX5: { + (Ecu.eps, 0x730, None): [ + b'K319-3210X-A-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KCB8-3210X-B-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KJ01-3210X-G-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KJ01-3210X-J-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KJ01-3210X-M-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'PA53-188K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PAR4-188K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2E-188K2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2F-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2G-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2H-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2H-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2H-188K2-G\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX2K-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX38-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX42-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX68-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFA-188K2-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFC-188K2-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFD-188K2-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYNF-188K2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'SHKT-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'K123-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'K123-437K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KBJ5-437K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KL2K-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KN0W-437K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'B61L-67XK2-R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-V\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-M\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-N\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-R\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'PA66-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PA66-21PS1-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX39-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX39-21PS1-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX68-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB1-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB1-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB1-21PS1-G\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-G\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYB2-21PS1-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYNC-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'SH9T-21PS1-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.MAZDA_CX9: { + (Ecu.eps, 0x730, None): [ + b'K070-3210X-C-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KJ01-3210X-G-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KJ01-3210X-L-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'PX23-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX24-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM4-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXN8-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXN8-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYD7-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYD8-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFM-188K2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFM-188K2-H\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'K123-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TK80-67XK2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TK80-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'TA0B-437K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TK79-437K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TK79-437K2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TM53-437K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TN40-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'B61L-67XK2-P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-V\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-J\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-K\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'TK80-67XK2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'PXM4-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM7-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM7-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYD5-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYD5-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYD6-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYD6-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFM-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYFM-21PS1-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.MAZDA_3: { + (Ecu.eps, 0x730, None): [ + b'BHN1-3210X-J-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K070-3210X-C-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'KR11-3210X-K-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'P5JD-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PY2P-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYJW-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYKC-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYKE-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'B63C-67XK2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GHP9-67Y10---41\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'B45A-437AS-0-08\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'B61L-67XK2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-Q\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'P52G-21PS1-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PY2S-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYKA-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYKE-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYKE-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.MAZDA_6: { + (Ecu.eps, 0x730, None): [ + b'GBEF-3210X-B-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GBEF-3210X-C-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GFBC-3210X-A-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'PA34-188K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PX4F-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYH7-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYH7-188K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'K131-67XK2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'GBVH-437K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GBVH-437K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GDDM-437K2-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'B61L-67XK2-S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'B61L-67XK2-T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'PA28-21PS1-A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYH3-21PS1-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PYH7-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, + CAR.MAZDA_CX9_2021: { + (Ecu.eps, 0x730, None): [ + b'TC3M-3210X-A-00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'PXGW-188K2-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXGW-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM4-188K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM4-188K2-D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM6-188K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM7-188K2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x764, None): [ + b'K131-67XK2-E\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'K131-67XK2-F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x760, None): [ + b'TA0B-437K2-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x706, None): [ + b'GSH7-67XK2-M\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-N\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-S\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'GSH7-67XK2-U\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.transmission, 0x7e1, None): [ + b'PXM4-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM6-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM7-21PS1-B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PXM7-21PS1-C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/mazda/interface.py b/opendbc_repo/opendbc/car/mazda/interface.py new file mode 100755 index 0000000000..814846e852 --- /dev/null +++ b/opendbc_repo/opendbc/car/mazda/interface.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +from opendbc.car import get_safety_config, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.mazda.carcontroller import CarController +from opendbc.car.mazda.carstate import CarState +from opendbc.car.mazda.values import CAR, LKAS_LIMITS + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "mazda" + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.mazda)] + ret.radarUnavailable = True + + ret.dashcamOnly = candidate not in (CAR.MAZDA_CX5_2022, CAR.MAZDA_CX9_2021) + + ret.steerActuatorDelay = 0.1 + ret.steerLimitTimer = 0.8 + + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + if candidate not in (CAR.MAZDA_CX5_2022,): + ret.minSteerSpeed = LKAS_LIMITS.DISABLE_SPEED * CV.KPH_TO_MS + + ret.centerToFront = ret.wheelbase * 0.41 + + return ret diff --git a/opendbc_repo/opendbc/car/mazda/mazdacan.py b/opendbc_repo/opendbc/car/mazda/mazdacan.py new file mode 100644 index 0000000000..adccdd6428 --- /dev/null +++ b/opendbc_repo/opendbc/car/mazda/mazdacan.py @@ -0,0 +1,128 @@ +from opendbc.car.mazda.values import Buttons, MazdaFlags + + +def create_steering_control(packer, CP, frame, apply_torque, lkas): + + tmp = apply_torque + 2048 + + lo = tmp & 0xFF + hi = tmp >> 8 + + # copy values from camera + b1 = int(lkas["BIT_1"]) + er1 = int(lkas["ERR_BIT_1"]) + lnv = 0 + ldw = 0 + er2 = int(lkas["ERR_BIT_2"]) + + # Some older models do have these, newer models don't. + # Either way, they all work just fine if set to zero. + steering_angle = 0 + b2 = 0 + + tmp = steering_angle + 2048 + ahi = tmp >> 10 + amd = (tmp & 0x3FF) >> 2 + amd = (amd >> 4) | ((amd & 0xF) << 4) + alo = (tmp & 0x3) << 2 + + ctr = frame % 16 + # bytes: [ 1 ] [ 2 ] [ 3 ] [ 4 ] + csum = 249 - ctr - hi - lo - (lnv << 3) - er1 - (ldw << 7) - (er2 << 4) - (b1 << 5) + + # bytes [ 5 ] [ 6 ] [ 7 ] + csum = csum - ahi - amd - alo - b2 + + if ahi == 1: + csum = csum + 15 + + if csum < 0: + if csum < -256: + csum = csum + 512 + else: + csum = csum + 256 + + csum = csum % 256 + + values = {} + if CP.flags & MazdaFlags.GEN1: + values = { + "LKAS_REQUEST": apply_torque, + "CTR": ctr, + "ERR_BIT_1": er1, + "LINE_NOT_VISIBLE": lnv, + "LDW": ldw, + "BIT_1": b1, + "ERR_BIT_2": er2, + "STEERING_ANGLE": steering_angle, + "ANGLE_ENABLED": b2, + "CHKSUM": csum + } + + return packer.make_can_msg("CAM_LKAS", 0, values) + + +def create_alert_command(packer, cam_msg: dict, ldw: bool, steer_required: bool): + values = {s: cam_msg[s] for s in [ + "LINE_VISIBLE", + "LINE_NOT_VISIBLE", + "LANE_LINES", + "BIT1", + "BIT2", + "BIT3", + "NO_ERR_BIT", + "S1", + "S1_HBEAM", + ]} + values.update({ + # TODO: what's the difference between all these? do we need to send all? + "HANDS_WARN_3_BITS": 0b111 if steer_required else 0, + "HANDS_ON_STEER_WARN": steer_required, + "HANDS_ON_STEER_WARN_2": steer_required, + + # TODO: right lane works, left doesn't + # TODO: need to do something about L/R + "LDW_WARN_LL": 0, + "LDW_WARN_RL": 0, + }) + return packer.make_can_msg("CAM_LANEINFO", 0, values) + + +def create_button_cmd(packer, CP, counter, button): + + can = int(button == Buttons.CANCEL) + res = int(button == Buttons.RESUME) + + if CP.flags & MazdaFlags.GEN1: + values = { + "CAN_OFF": can, + "CAN_OFF_INV": (can + 1) % 2, + + "SET_P": 0, + "SET_P_INV": 1, + + "RES": res, + "RES_INV": (res + 1) % 2, + + "SET_M": 0, + "SET_M_INV": 1, + + "DISTANCE_LESS": 0, + "DISTANCE_LESS_INV": 1, + + "DISTANCE_MORE": 0, + "DISTANCE_MORE_INV": 1, + + "MODE_X": 0, + "MODE_X_INV": 1, + + "MODE_Y": 0, + "MODE_Y_INV": 1, + + "BIT1": 1, + "BIT2": 1, + "BIT3": 1, + "CTR": (counter + 1) % 16, + } + + return packer.make_can_msg("CRZ_BTNS", 0, values) diff --git a/opendbc_repo/opendbc/car/mazda/values.py b/opendbc_repo/opendbc/car/mazda/values.py new file mode 100644 index 0000000000..e85b352b85 --- /dev/null +++ b/opendbc_repo/opendbc/car/mazda/values.py @@ -0,0 +1,104 @@ +from dataclasses import dataclass, field +from enum import IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarHarness, CarDocs, CarParts +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu + + +# Steer torque limits + +class CarControllerParams: + STEER_MAX = 800 # theoretical max_steer 2047 + STEER_DELTA_UP = 10 # torque increase per refresh + STEER_DELTA_DOWN = 25 # torque decrease per refresh + STEER_DRIVER_ALLOWANCE = 15 # allowed driver torque before start limiting + STEER_DRIVER_MULTIPLIER = 1 # weight driver torque + STEER_DRIVER_FACTOR = 1 # from dbc + STEER_ERROR_MAX = 350 # max delta between torque cmd and torque motor + STEER_STEP = 1 # 100 Hz + + def __init__(self, CP): + pass + + +@dataclass +class MazdaCarDocs(CarDocs): + package: str = "All" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.mazda])) + + +@dataclass(frozen=True, kw_only=True) +class MazdaCarSpecs(CarSpecs): + tireStiffnessFactor: float = 0.7 # not optimized yet + + +class MazdaFlags(IntFlag): + # Static flags + # Gen 1 hardware: same CAN messages and same camera + GEN1 = 1 + + +@dataclass +class MazdaPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'mazda_2017'}) + flags: int = MazdaFlags.GEN1 + + +class CAR(Platforms): + MAZDA_CX5 = MazdaPlatformConfig( + [MazdaCarDocs("Mazda CX-5 2017-21")], + MazdaCarSpecs(mass=3655 * CV.LB_TO_KG, wheelbase=2.7, steerRatio=15.5) + ) + MAZDA_CX9 = MazdaPlatformConfig( + [MazdaCarDocs("Mazda CX-9 2016-20")], + MazdaCarSpecs(mass=4217 * CV.LB_TO_KG, wheelbase=3.1, steerRatio=17.6) + ) + MAZDA_3 = MazdaPlatformConfig( + [MazdaCarDocs("Mazda 3 2017-18")], + MazdaCarSpecs(mass=2875 * CV.LB_TO_KG, wheelbase=2.7, steerRatio=14.0) + ) + MAZDA_6 = MazdaPlatformConfig( + [MazdaCarDocs("Mazda 6 2017-20")], + MazdaCarSpecs(mass=3443 * CV.LB_TO_KG, wheelbase=2.83, steerRatio=15.5) + ) + MAZDA_CX9_2021 = MazdaPlatformConfig( + [MazdaCarDocs("Mazda CX-9 2021-23", video="https://youtu.be/dA3duO4a0O4")], + MAZDA_CX9.specs + ) + MAZDA_CX5_2022 = MazdaPlatformConfig( + [MazdaCarDocs("Mazda CX-5 2022-25")], + MAZDA_CX5.specs, + ) + + +class LKAS_LIMITS: + STEER_THRESHOLD = 15 + DISABLE_SPEED = 45 # kph + ENABLE_SPEED = 52 # kph + + +class Buttons: + NONE = 0 + SET_PLUS = 1 + SET_MINUS = 2 + RESUME = 3 + CANCEL = 4 + + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + # TODO: check data to ensure ABS does not skip ISO-TP frames on bus 0 + Request( + [StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], + [StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + bus=0, + ), + ], +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/mock/__init__.py b/opendbc_repo/opendbc/car/mock/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/mock/carcontroller.py b/opendbc_repo/opendbc/car/mock/carcontroller.py new file mode 100644 index 0000000000..6336dcfcbe --- /dev/null +++ b/opendbc_repo/opendbc/car/mock/carcontroller.py @@ -0,0 +1,6 @@ +from opendbc.car.interfaces import CarControllerBase + + +class CarController(CarControllerBase): + def update(self, CC, CS, now_nanos): + return CC.actuators.as_builder(), [] diff --git a/opendbc_repo/opendbc/car/mock/carstate.py b/opendbc_repo/opendbc/car/mock/carstate.py new file mode 100644 index 0000000000..9cbdf99e91 --- /dev/null +++ b/opendbc_repo/opendbc/car/mock/carstate.py @@ -0,0 +1,7 @@ +from opendbc.car import structs +from opendbc.car.interfaces import CarStateBase + + +class CarState(CarStateBase): + def update(self, *_) -> structs.CarState: + return structs.CarState() diff --git a/opendbc_repo/opendbc/car/mock/interface.py b/opendbc_repo/opendbc/car/mock/interface.py new file mode 100755 index 0000000000..3bcc2f8f11 --- /dev/null +++ b/opendbc_repo/opendbc/car/mock/interface.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +from opendbc.car import structs +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.mock.carcontroller import CarController +from opendbc.car.mock.carstate import CarState + + +# mocked car interface for dashcam mode +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "mock" + ret.mass = 1700. + ret.wheelbase = 2.70 + ret.centerToFront = ret.wheelbase * 0.5 + ret.steerRatio = 13. + ret.dashcamOnly = True + return ret diff --git a/opendbc_repo/opendbc/car/mock/values.py b/opendbc_repo/opendbc/car/mock/values.py new file mode 100644 index 0000000000..aa844de4c5 --- /dev/null +++ b/opendbc_repo/opendbc/car/mock/values.py @@ -0,0 +1,9 @@ +from opendbc.car import CarSpecs, PlatformConfig, Platforms + + +class CAR(Platforms): + MOCK = PlatformConfig( + [], + CarSpecs(mass=1700, wheelbase=2.7, steerRatio=13), + {} + ) diff --git a/opendbc_repo/opendbc/car/nissan/__init__.py b/opendbc_repo/opendbc/car/nissan/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/nissan/carcontroller.py b/opendbc_repo/opendbc/car/nissan/carcontroller.py new file mode 100644 index 0000000000..16f990a824 --- /dev/null +++ b/opendbc_repo/opendbc/car/nissan/carcontroller.py @@ -0,0 +1,76 @@ +from opendbc.can import CANPacker +from opendbc.car import Bus, structs +from opendbc.car.lateral import apply_std_steer_angle_limits +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.nissan import nissancan +from opendbc.car.nissan.values import CAR, CarControllerParams + +VisualAlert = structs.CarControl.HUDControl.VisualAlert + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.car_fingerprint = CP.carFingerprint + + self.apply_angle_last = 0 + + self.packer = CANPacker(dbc_names[Bus.pt]) + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + hud_control = CC.hudControl + pcm_cancel_cmd = CC.cruiseControl.cancel + + can_sends = [] + + ### STEER ### + steer_hud_alert = 1 if hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw) else 0 + + # windup slower + self.apply_angle_last = apply_std_steer_angle_limits(actuators.steeringAngleDeg, self.apply_angle_last, CS.out.vEgoRaw, + CS.out.steeringAngleDeg, CC.latActive, CarControllerParams.ANGLE_LIMITS) + + lkas_max_torque = 0 + if CC.latActive: + # Max torque from driver before EPS will give up and not apply torque + if not bool(CS.out.steeringPressed): + lkas_max_torque = CarControllerParams.LKAS_MAX_TORQUE + else: + # Scale max torque based on how much torque the driver is applying to the wheel + lkas_max_torque = max( + # Scale max torque down to half LKAX_MAX_TORQUE as a minimum + CarControllerParams.LKAS_MAX_TORQUE * 0.5, + # Start scaling torque at STEER_THRESHOLD + CarControllerParams.LKAS_MAX_TORQUE - 0.6 * max(0, abs(CS.out.steeringTorque) - CarControllerParams.STEER_THRESHOLD) + ) + + if self.CP.carFingerprint in (CAR.NISSAN_ROGUE, CAR.NISSAN_XTRAIL, CAR.NISSAN_ALTIMA) and pcm_cancel_cmd: + can_sends.append(nissancan.create_acc_cancel_cmd(self.packer, self.car_fingerprint, CS.cruise_throttle_msg)) + + # TODO: Find better way to cancel! + # For some reason spamming the cancel button is unreliable on the Leaf + # We now cancel by making propilot think the seatbelt is unlatched, + # this generates a beep and a warning message every time you disengage + if self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC) and self.frame % 2 == 0: + can_sends.append(nissancan.create_cancel_msg(self.packer, CS.cancel_msg, pcm_cancel_cmd)) + + can_sends.append(nissancan.create_steering_control( + self.packer, self.apply_angle_last, self.frame, CC.latActive, lkas_max_torque)) + + # Below are the HUD messages. We copy the stock message and modify + if self.CP.carFingerprint != CAR.NISSAN_ALTIMA: + if self.frame % 2 == 0: + can_sends.append(nissancan.create_lkas_hud_msg(self.packer, CS.lkas_hud_msg, CC.enabled, hud_control.leftLaneVisible, hud_control.rightLaneVisible, + hud_control.leftLaneDepart, hud_control.rightLaneDepart)) + + if self.frame % 50 == 0: + can_sends.append(nissancan.create_lkas_hud_info_msg( + self.packer, CS.lkas_hud_info_msg, steer_hud_alert + )) + + new_actuators = actuators.as_builder() + new_actuators.steeringAngleDeg = self.apply_angle_last + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/nissan/carstate.py b/opendbc_repo/opendbc/car/nissan/carstate.py new file mode 100644 index 0000000000..8f38590ad5 --- /dev/null +++ b/opendbc_repo/opendbc/car/nissan/carstate.py @@ -0,0 +1,139 @@ +import copy +from collections import deque +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarStateBase +from opendbc.car.nissan.values import CAR, DBC, CarControllerParams + +ButtonType = structs.CarState.ButtonEvent.Type + +TORQUE_SAMPLES = 12 + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + + self.lkas_hud_msg = {} + self.lkas_hud_info_msg = {} + + self.steeringTorqueSamples = deque(TORQUE_SAMPLES*[0], TORQUE_SAMPLES) + self.shifter_values = can_define.dv["GEARBOX"]["GEAR_SHIFTER"] + + self.distance_button = 0 + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + cp_adas = can_parsers[Bus.adas] + + ret = structs.CarState() + + prev_distance_button = self.distance_button + self.distance_button = cp.vl["CRUISE_THROTTLE"]["FOLLOW_DISTANCE_BUTTON"] + + if self.CP.carFingerprint in (CAR.NISSAN_ROGUE, CAR.NISSAN_XTRAIL, CAR.NISSAN_ALTIMA): + ret.gasPressed = bool(cp.vl["GAS_PEDAL"]["GAS_PEDAL"] > 3) + elif self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC): + ret.gasPressed = bool(cp.vl["CRUISE_THROTTLE"]["GAS_PEDAL"] > 3) + + if self.CP.carFingerprint in (CAR.NISSAN_ROGUE, CAR.NISSAN_XTRAIL, CAR.NISSAN_ALTIMA): + ret.brakePressed = bool(cp.vl["DOORS_LIGHTS"]["USER_BRAKE_PRESSED"]) + elif self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC): + ret.brakePressed = bool(cp.vl["CRUISE_THROTTLE"]["USER_BRAKE_PRESSED"]) + + fl = cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FL"] * CV.KPH_TO_MS + fr = cp.vl["WHEEL_SPEEDS_FRONT"]["WHEEL_SPEED_FR"] * CV.KPH_TO_MS + rl = cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RL"] * CV.KPH_TO_MS + rr = cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RR"] * CV.KPH_TO_MS + # safety uses the rear wheel speeds for the speed measurement and angle limiting + ret.vEgoRaw = (rl + rr) / 2.0 + + v_ego_raw_full = (fl + fr + rl + rr) / 4.0 + ret.vEgo, ret.aEgo = self.update_speed_kf(v_ego_raw_full) + ret.standstill = cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RL"] == 0.0 and cp.vl["WHEEL_SPEEDS_REAR"]["WHEEL_SPEED_RR"] == 0.0 + + if self.CP.carFingerprint == CAR.NISSAN_ALTIMA: + ret.cruiseState.enabled = bool(cp.vl["CRUISE_STATE"]["CRUISE_ENABLED"]) + else: + ret.cruiseState.enabled = bool(cp_adas.vl["CRUISE_STATE"]["CRUISE_ENABLED"]) + + if self.CP.carFingerprint in (CAR.NISSAN_ROGUE, CAR.NISSAN_XTRAIL): + ret.seatbeltUnlatched = cp.vl["HUD"]["SEATBELT_DRIVER_LATCHED"] == 0 + ret.cruiseState.available = bool(cp_cam.vl["PRO_PILOT"]["CRUISE_ON"]) + elif self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC): + if self.CP.carFingerprint == CAR.NISSAN_LEAF: + ret.seatbeltUnlatched = cp.vl["SEATBELT"]["SEATBELT_DRIVER_LATCHED"] == 0 + elif self.CP.carFingerprint == CAR.NISSAN_LEAF_IC: + ret.seatbeltUnlatched = cp.vl["CANCEL_MSG"]["CANCEL_SEATBELT"] == 1 + ret.cruiseState.available = bool(cp.vl["CRUISE_THROTTLE"]["CRUISE_AVAILABLE"]) + elif self.CP.carFingerprint == CAR.NISSAN_ALTIMA: + ret.seatbeltUnlatched = cp.vl["HUD"]["SEATBELT_DRIVER_LATCHED"] == 0 + ret.cruiseState.available = bool(cp_adas.vl["PRO_PILOT"]["CRUISE_ON"]) + + if self.CP.carFingerprint == CAR.NISSAN_ALTIMA: + speed = cp.vl["PROPILOT_HUD"]["SET_SPEED"] + else: + speed = cp_adas.vl["PROPILOT_HUD"]["SET_SPEED"] + + if speed != 255: + if self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC): + conversion = CV.MPH_TO_MS if cp.vl["HUD_SETTINGS"]["SPEED_MPH"] else CV.KPH_TO_MS + else: + conversion = CV.MPH_TO_MS if cp.vl["HUD"]["SPEED_MPH"] else CV.KPH_TO_MS + ret.cruiseState.speed = speed * conversion + ret.cruiseState.speedCluster = (speed - 1) * conversion # Speed on HUD is always 1 lower than actually sent on can bus + + if self.CP.carFingerprint == CAR.NISSAN_ALTIMA: + ret.steeringTorque = cp_cam.vl["STEER_TORQUE_SENSOR"]["STEER_TORQUE_DRIVER"] + else: + ret.steeringTorque = cp.vl["STEER_TORQUE_SENSOR"]["STEER_TORQUE_DRIVER"] + + self.steeringTorqueSamples.append(ret.steeringTorque) + # Filtering driver torque to prevent steeringPressed false positives + ret.steeringPressed = bool(abs(sum(self.steeringTorqueSamples) / TORQUE_SAMPLES) > CarControllerParams.STEER_THRESHOLD) + + ret.steeringAngleDeg = cp.vl["STEER_ANGLE_SENSOR"]["STEER_ANGLE"] + + ret.leftBlinker = bool(cp.vl["LIGHTS"]["LEFT_BLINKER"]) + ret.rightBlinker = bool(cp.vl["LIGHTS"]["RIGHT_BLINKER"]) + + ret.doorOpen = any([cp.vl["DOORS_LIGHTS"]["DOOR_OPEN_RR"], + cp.vl["DOORS_LIGHTS"]["DOOR_OPEN_RL"], + cp.vl["DOORS_LIGHTS"]["DOOR_OPEN_FR"], + cp.vl["DOORS_LIGHTS"]["DOOR_OPEN_FL"]]) + + ret.espDisabled = bool(cp.vl["ESP"]["ESP_DISABLED"]) + + can_gear = int(cp.vl["GEARBOX"]["GEAR_SHIFTER"]) + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None)) + + # stock lkas should be off + # TODO: is this needed? + if self.CP.carFingerprint == CAR.NISSAN_ALTIMA: + ret.invalidLkasSetting = bool(cp.vl["LKAS_SETTINGS"]["LKAS_ENABLED"]) + else: + ret.invalidLkasSetting = bool(cp_adas.vl["LKAS_SETTINGS"]["LKAS_ENABLED"]) + + self.cruise_throttle_msg = copy.copy(cp.vl["CRUISE_THROTTLE"]) + + if self.CP.carFingerprint in (CAR.NISSAN_LEAF, CAR.NISSAN_LEAF_IC): + self.cancel_msg = copy.copy(cp.vl["CANCEL_MSG"]) + + if self.CP.carFingerprint != CAR.NISSAN_ALTIMA: + self.lkas_hud_msg = copy.copy(cp_adas.vl["PROPILOT_HUD"]) + self.lkas_hud_info_msg = copy.copy(cp_adas.vl["PROPILOT_HUD_INFO_MSG"]) + + ret.buttonEvents = create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 1 if CP.carFingerprint == CAR.NISSAN_ALTIMA else 0), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0 if CP.carFingerprint == CAR.NISSAN_ALTIMA else 1), + Bus.adas: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/nissan/fingerprints.py b/opendbc_repo/opendbc/car/nissan/fingerprints.py new file mode 100644 index 0000000000..4db2fe7c48 --- /dev/null +++ b/opendbc_repo/opendbc/car/nissan/fingerprints.py @@ -0,0 +1,100 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.nissan.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.NISSAN_ALTIMA: { + (Ecu.fwdCamera, 0x707, None): [ + b'284N86CA1D', + ], + (Ecu.eps, 0x742, None): [ + b'6CA2B\xa9A\x02\x02G8A89P90D6A\x00\x00\x01\x80', + ], + (Ecu.engine, 0x7e0, None): [ + b'237109HE2B', + ], + (Ecu.gateway, 0x18dad0f1, None): [ + b'284U29HE0A', + ], + }, + CAR.NISSAN_LEAF: { + (Ecu.abs, 0x740, None): [ + b'476605SA1C', + b'476605SA7D', + b'476605SC2D', + b'476606WK7B', + b'476606WK9B', + ], + (Ecu.eps, 0x742, None): [ + b'5SA2A\x99A\x05\x02N123F\x15b\x00\x00\x00\x00\x00\x00\x00\x80', + b'5SA2A\xb7A\x05\x02N123F\x15\xa2\x00\x00\x00\x00\x00\x00\x00\x80', + b'5SN2A\xb7A\x05\x02N123F\x15\xa2\x00\x00\x00\x00\x00\x00\x00\x80', + b'5SN2A\xb7A\x05\x02N126F\x15\xb2\x00\x00\x00\x00\x00\x00\x00\x80', + ], + (Ecu.fwdCamera, 0x707, None): [ + b'5SA0ADB\x04\x18\x00\x00\x00\x00\x00_*6\x04\x94a\x00\x00\x00\x80', + b'5SA2ADB\x04\x18\x00\x00\x00\x00\x00_*6\x04\x94a\x00\x00\x00\x80', + b'6WK2ADB\x04\x18\x00\x00\x00\x00\x00R;1\x18\x99\x10\x00\x00\x00\x80', + b'6WK2BDB\x04\x18\x00\x00\x00\x00\x00R;1\x18\x99\x10\x00\x00\x00\x80', + b'6WK2CDB\x04\x18\x00\x00\x00\x00\x00R=1\x18\x99\x10\x00\x00\x00\x80', + ], + (Ecu.gateway, 0x18dad0f1, None): [ + b'284U25SA3C', + b'284U25SP0C', + b'284U25SP1C', + b'284U26WK0A', + b'284U26WK0C', + ], + }, + CAR.NISSAN_LEAF_IC: { + (Ecu.fwdCamera, 0x707, None): [ + b'5SH1BDB\x04\x18\x00\x00\x00\x00\x00_-?\x04\x91\xf2\x00\x00\x00\x80', + b'5SH3BDB\x04\x18\x00\x00\x00\x00\x00_-?\x04\x91\xf2\x00\x00\x00\x80', + b'5SH4BDB\x04\x18\x00\x00\x00\x00\x00_-?\x04\x91\xf2\x00\x00\x00\x80', + b'5SK0ADB\x04\x18\x00\x00\x00\x00\x00_(5\x07\x9aQ\x00\x00\x00\x80', + ], + (Ecu.abs, 0x740, None): [ + b'476605SD2E', + b'476605SH1D', + b'476605SH7D', + b'476605SH7E', + b'476605SK2A', + ], + (Ecu.eps, 0x742, None): [ + b'5SH2A\x99A\x05\x02N123F\x15\x81\x00\x00\x00\x00\x00\x00\x00\x80', + b'5SH2A\xb7A\x05\x02N123F\x15\xa3\x00\x00\x00\x00\x00\x00\x00\x80', + b'5SH2C\xb7A\x05\x02N123F\x15\xa3\x00\x00\x00\x00\x00\x00\x00\x80', + b'5SK3A\x99A\x05\x02N123F\x15u\x00\x00\x00\x00\x00\x00\x00\x80', + ], + (Ecu.gateway, 0x18dad0f1, None): [ + b'284U25SF0C', + b'284U25SH3A', + b'284U25SK2D', + b'284U25SR0B', + ], + }, + CAR.NISSAN_XTRAIL: { + (Ecu.fwdCamera, 0x707, None): [ + b'284N86FR2A', + ], + (Ecu.abs, 0x740, None): [ + b'6FU0AD\x11\x02\x00\x02e\x95e\x80iQ#\x01\x00\x00\x00\x00\x00\x80', + b'6FU1BD\x11\x02\x00\x02e\x95e\x80iX#\x01\x00\x00\x00\x00\x00\x80', + ], + (Ecu.eps, 0x742, None): [ + b'6FP2A\x99A\x05\x02N123F\x18\x02\x00\x00\x00\x00\x00\x00\x00\x80', + ], + (Ecu.combinationMeter, 0x743, None): [ + b'6FR2A\x18B\x05\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80', + ], + (Ecu.engine, 0x7e0, None): [ + b'6FR9A\xa0A\x06\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80', + b'6FU9B\xa0A\x06\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80', + ], + (Ecu.gateway, 0x18dad0f1, None): [ + b'284U26FR0E', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/nissan/interface.py b/opendbc_repo/opendbc/car/nissan/interface.py new file mode 100644 index 0000000000..bac7b3f1af --- /dev/null +++ b/opendbc_repo/opendbc/car/nissan/interface.py @@ -0,0 +1,29 @@ +from opendbc.car import get_safety_config, structs +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.nissan.carcontroller import CarController +from opendbc.car.nissan.carstate import CarState +from opendbc.car.nissan.values import CAR, NissanSafetyFlags + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "nissan" + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.nissan)] + ret.autoResumeSng = False + + ret.steerLimitTimer = 1.0 + + ret.steerActuatorDelay = 0.1 + + ret.steerControlType = structs.CarParams.SteerControlType.angle + ret.radarUnavailable = True + + if candidate == CAR.NISSAN_ALTIMA: + # Altima has EPS on C-CAN unlike the others that have it on V-CAN + ret.safetyConfigs[0].safetyParam |= NissanSafetyFlags.ALT_EPS_BUS.value + + return ret diff --git a/opendbc_repo/opendbc/car/nissan/nissancan.py b/opendbc_repo/opendbc/car/nissan/nissancan.py new file mode 100644 index 0000000000..0c95ad1854 --- /dev/null +++ b/opendbc_repo/opendbc/car/nissan/nissancan.py @@ -0,0 +1,154 @@ +import crcmod +from opendbc.car.nissan.values import CAR + +# TODO: add this checksum to the CANPacker +nissan_checksum = crcmod.mkCrcFun(0x11d, initCrc=0x00, rev=False, xorOut=0xff) + + +def create_steering_control(packer, apply_torque, frame, steer_on, lkas_max_torque): + values = { + "COUNTER": frame % 0x10, + "DESIRED_ANGLE": apply_torque, + "SET_0x80_2": 0x80, + "SET_0x80": 0x80, + "MAX_TORQUE": lkas_max_torque if steer_on else 0, + "LKA_ACTIVE": steer_on, + } + + dat = packer.make_can_msg("LKAS", 0, values)[1] + + values["CHECKSUM"] = nissan_checksum(dat[:7]) + return packer.make_can_msg("LKAS", 0, values) + + +def create_acc_cancel_cmd(packer, car_fingerprint, cruise_throttle_msg): + values = {s: cruise_throttle_msg[s] for s in [ + "COUNTER", + "PROPILOT_BUTTON", + "CANCEL_BUTTON", + "GAS_PEDAL_INVERTED", + "SET_BUTTON", + "RES_BUTTON", + "FOLLOW_DISTANCE_BUTTON", + "NO_BUTTON_PRESSED", + "GAS_PEDAL", + "USER_BRAKE_PRESSED", + "NEW_SIGNAL_2", + "GAS_PRESSED_INVERTED", + "unsure1", + "unsure2", + "unsure3", + ]} + can_bus = 1 if car_fingerprint == CAR.NISSAN_ALTIMA else 2 + + values["CANCEL_BUTTON"] = 1 + values["NO_BUTTON_PRESSED"] = 0 + values["PROPILOT_BUTTON"] = 0 + values["SET_BUTTON"] = 0 + values["RES_BUTTON"] = 0 + values["FOLLOW_DISTANCE_BUTTON"] = 0 + + return packer.make_can_msg("CRUISE_THROTTLE", can_bus, values) + + +def create_cancel_msg(packer, cancel_msg, cruise_cancel): + values = {s: cancel_msg[s] for s in [ + "CANCEL_SEATBELT", + "NEW_SIGNAL_1", + "NEW_SIGNAL_2", + "NEW_SIGNAL_3", + ]} + + if cruise_cancel: + values["CANCEL_SEATBELT"] = 1 + + return packer.make_can_msg("CANCEL_MSG", 2, values) + + +def create_lkas_hud_msg(packer, lkas_hud_msg, enabled, left_line, right_line, left_lane_depart, right_lane_depart): + values = {s: lkas_hud_msg[s] for s in [ + "LARGE_WARNING_FLASHING", + "SIDE_RADAR_ERROR_FLASHING1", + "SIDE_RADAR_ERROR_FLASHING2", + "LEAD_CAR", + "LEAD_CAR_ERROR", + "FRONT_RADAR_ERROR", + "FRONT_RADAR_ERROR_FLASHING", + "SIDE_RADAR_ERROR_FLASHING3", + "LKAS_ERROR_FLASHING", + "SAFETY_SHIELD_ACTIVE", + "RIGHT_LANE_GREEN_FLASH", + "LEFT_LANE_GREEN_FLASH", + "FOLLOW_DISTANCE", + "AUDIBLE_TONE", + "SPEED_SET_ICON", + "SMALL_STEERING_WHEEL_ICON", + "unknown59", + "unknown55", + "unknown26", + "unknown28", + "unknown31", + "SET_SPEED", + "unknown43", + "unknown08", + "unknown05", + "unknown02", + ]} + + values["RIGHT_LANE_YELLOW_FLASH"] = 1 if right_lane_depart else 0 + values["LEFT_LANE_YELLOW_FLASH"] = 1 if left_lane_depart else 0 + + values["LARGE_STEERING_WHEEL_ICON"] = 2 if enabled else 0 + values["RIGHT_LANE_GREEN"] = 1 if right_line and enabled else 0 + values["LEFT_LANE_GREEN"] = 1 if left_line and enabled else 0 + + return packer.make_can_msg("PROPILOT_HUD", 0, values) + + +def create_lkas_hud_info_msg(packer, lkas_hud_info_msg, steer_hud_alert): + values = {s: lkas_hud_info_msg[s] for s in [ + "NA_HIGH_ACCEL_TEMP", + "SIDE_RADAR_NA_HIGH_CABIN_TEMP", + "SIDE_RADAR_MALFUNCTION", + "LKAS_MALFUNCTION", + "FRONT_RADAR_MALFUNCTION", + "SIDE_RADAR_NA_CLEAN_REAR_CAMERA", + "NA_POOR_ROAD_CONDITIONS", + "CURRENTLY_UNAVAILABLE", + "SAFETY_SHIELD_OFF", + "FRONT_COLLISION_NA_FRONT_RADAR_OBSTRUCTION", + "PEDAL_MISSAPPLICATION_SYSTEM_ACTIVATED", + "SIDE_IMPACT_NA_RADAR_OBSTRUCTION", + "WARNING_DO_NOT_ENTER", + "SIDE_IMPACT_SYSTEM_OFF", + "SIDE_IMPACT_MALFUNCTION", + "FRONT_COLLISION_MALFUNCTION", + "SIDE_RADAR_MALFUNCTION2", + "LKAS_MALFUNCTION2", + "FRONT_RADAR_MALFUNCTION2", + "PROPILOT_NA_MSGS", + "BOTTOM_MSG", + "HANDS_ON_WHEEL_WARNING", + "WARNING_STEP_ON_BRAKE_NOW", + "PROPILOT_NA_FRONT_CAMERA_OBSTRUCTED", + "PROPILOT_NA_HIGH_CABIN_TEMP", + "WARNING_PROPILOT_MALFUNCTION", + "ACC_UNAVAILABLE_HIGH_CABIN_TEMP", + "ACC_NA_FRONT_CAMERA_IMPARED", + "unknown07", + "unknown10", + "unknown15", + "unknown23", + "unknown19", + "unknown31", + "unknown32", + "unknown46", + "unknown61", + "unknown55", + "unknown50", + ]} + + if steer_hud_alert: + values["HANDS_ON_WHEEL_WARNING"] = 1 + + return packer.make_can_msg("PROPILOT_HUD_INFO_MSG", 0, values) diff --git a/opendbc_repo/opendbc/car/nissan/values.py b/opendbc_repo/opendbc/car/nissan/values.py new file mode 100644 index 0000000000..ee00cf423f --- /dev/null +++ b/opendbc_repo/opendbc/car/nissan/values.py @@ -0,0 +1,125 @@ +from dataclasses import dataclass, field +from enum import Enum, IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds +from opendbc.car.lateral import AngleSteeringLimits +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarDocs, CarFootnote, CarHarness, CarParts, Column +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu + + +class CarControllerParams: + ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits( + # When output steering Angle not within range -1311 and 1310, + # CANPacker packs wrong angle output to be decoded by panda + 600, # deg, reasonable limit + ([0., 5., 15.], [5., .8, .15]), + ([0., 5., 15.], [5., 3.5, 0.4]), + ) + + LKAS_MAX_TORQUE = 1 # A value of 1 is easy to overpower + STEER_THRESHOLD = 1.0 + + def __init__(self, CP): + pass + + +class NissanSafetyFlags(IntFlag): + ALT_EPS_BUS = 1 + + +class Footnote(Enum): + SETUP = CarFootnote( + "See more setup details for Nissan.", + Column.MAKE, setup_note=True) + + +@dataclass +class NissanCarDocs(CarDocs): + package: str = "ProPILOT Assist" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.nissan_a])) + footnotes: list[Enum] = field(default_factory=lambda: [Footnote.SETUP]) + + +@dataclass(frozen=True) +class NissanCarSpecs(CarSpecs): + centerToFrontRatio: float = 0.44 + steerRatio: float = 17. + + +@dataclass +class NissanPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'nissan_x_trail_2017_generated'}) + + +class CAR(Platforms): + NISSAN_XTRAIL = NissanPlatformConfig( + [NissanCarDocs("Nissan X-Trail 2017")], + NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + NISSAN_LEAF = NissanPlatformConfig( + [NissanCarDocs("Nissan Leaf 2018-23", video="https://youtu.be/vaMbtAh_0cY")], + NissanCarSpecs(mass=1610, wheelbase=2.705), + {Bus.pt: 'nissan_leaf_2018_generated'}, + ) + # Leaf with ADAS ECU found behind instrument cluster instead of glovebox + # Currently the only known difference between them is the inverted seatbelt signal. + NISSAN_LEAF_IC = NISSAN_LEAF.override(car_docs=[]) + NISSAN_ROGUE = NissanPlatformConfig( + [NissanCarDocs("Nissan Rogue 2018-20")], + NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + NISSAN_ALTIMA = NissanPlatformConfig( + [NissanCarDocs("Nissan Altima 2019-20", car_parts=CarParts.common([CarHarness.nissan_b]))], + NissanCarSpecs(mass=1492, wheelbase=2.824) + ) + + +DBC = CAR.create_dbc_map() + +# Default diagnostic session +NISSAN_DIAGNOSTIC_REQUEST_KWP = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, 0x81]) +NISSAN_DIAGNOSTIC_RESPONSE_KWP = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL + 0x40, 0x81]) + +# Manufacturer specific +NISSAN_DIAGNOSTIC_REQUEST_KWP_2 = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, 0xda]) +NISSAN_DIAGNOSTIC_RESPONSE_KWP_2 = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL + 0x40, 0xda]) + +NISSAN_VERSION_REQUEST_KWP = b'\x21\x83' +NISSAN_VERSION_RESPONSE_KWP = b'\x61\x83' + +NISSAN_RX_OFFSET = 0x20 + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[request for bus, logging in ((0, False), (1, True)) for request in [ + Request( + [NISSAN_DIAGNOSTIC_REQUEST_KWP, NISSAN_VERSION_REQUEST_KWP], + [NISSAN_DIAGNOSTIC_RESPONSE_KWP, NISSAN_VERSION_RESPONSE_KWP], + bus=bus, + logging=logging, + ), + Request( + [NISSAN_DIAGNOSTIC_REQUEST_KWP, NISSAN_VERSION_REQUEST_KWP], + [NISSAN_DIAGNOSTIC_RESPONSE_KWP, NISSAN_VERSION_RESPONSE_KWP], + rx_offset=NISSAN_RX_OFFSET, + bus=bus, + logging=logging, + ), + # Rogue's engine solely responds to this + Request( + [NISSAN_DIAGNOSTIC_REQUEST_KWP_2, NISSAN_VERSION_REQUEST_KWP], + [NISSAN_DIAGNOSTIC_RESPONSE_KWP_2, NISSAN_VERSION_RESPONSE_KWP], + bus=bus, + logging=logging, + ), + Request( + [StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], + [StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + rx_offset=NISSAN_RX_OFFSET, + bus=bus, + logging=logging, + ), + ]], +) diff --git a/opendbc_repo/opendbc/car/panda_runner.py b/opendbc_repo/opendbc/car/panda_runner.py new file mode 100644 index 0000000000..3c811750ee --- /dev/null +++ b/opendbc_repo/opendbc/car/panda_runner.py @@ -0,0 +1,59 @@ +import time +from contextlib import AbstractContextManager + +from panda import Panda +from opendbc.car.car_helpers import get_car +from opendbc.car.can_definitions import CanData +from opendbc.car.structs import CarParams, CarControl + + +class PandaRunner(AbstractContextManager): + def __enter__(self): + self.p = Panda() + self.p.reset() + + # setup + fingerprinting + self.p.set_safety_mode(CarParams.SafetyModel.elm327, 1) + self.CI = get_car(self._can_recv, self.p.can_send_many, self.p.set_obd, True, False) + assert self.CI.CP.carFingerprint.lower() != "mock", "Unable to identify car. Check connections and ensure car is supported." + + safety_model = self.CI.CP.safetyConfigs[0].safetyModel + self.p.set_safety_mode(CarParams.SafetyModel.elm327, 1) + self.CI.init(self.CI.CP, self._can_recv, self.p.can_send_many) + self.p.set_safety_mode(safety_model, self.CI.CP.safetyConfigs[0].safetyParam) + + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.p.set_safety_mode(CarParams.SafetyModel.noOutput) + self.p.reset() # avoid siren + return super().__exit__(exc_type, exc_value, traceback) + + @property + def panda(self) -> Panda: + return self.p + + def _can_recv(self, wait_for_one: bool = False) -> list[list[CanData]]: + recv = self.p.can_recv() + while len(recv) == 0 and wait_for_one: + recv = self.p.can_recv() + return [[CanData(addr, dat, bus) for addr, dat, bus in recv], ] + + def read(self, strict: bool = True): + cs = self.CI.update([int(time.monotonic()*1e9), self._can_recv()[0]]) + if strict: + assert cs.canValid, "CAN went invalid, check connections" + return cs + + def write(self, cc: CarControl) -> None: + if cc.enabled and not self.p.health()['controls_allowed']: + # prevent the car from faulting. print a warning? + cc = CarControl(enabled=False) + _, can_sends = self.CI.apply(cc) + self.p.can_send_many(can_sends, timeout=25) + self.p.send_heartbeat() + + +if __name__ == "__main__": + with PandaRunner() as p: + print(p.read()) diff --git a/opendbc_repo/opendbc/car/psa/__init__.py b/opendbc_repo/opendbc/car/psa/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/psa/carcontroller.py b/opendbc_repo/opendbc/car/psa/carcontroller.py new file mode 100644 index 0000000000..792deccee9 --- /dev/null +++ b/opendbc_repo/opendbc/car/psa/carcontroller.py @@ -0,0 +1,41 @@ +from opendbc.can.packer import CANPacker +from opendbc.car import Bus +from opendbc.car.lateral import apply_std_steer_angle_limits +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.psa.psacan import create_lka_steering +from opendbc.car.psa.values import CarControllerParams + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.packer = CANPacker(dbc_names[Bus.main]) + self.apply_angle_last = 0 + self.status = 2 + + def update(self, CC, CS, now_nanos): + can_sends = [] + actuators = CC.actuators + + # lateral control + if self.frame % 5 == 0: + apply_angle = apply_std_steer_angle_limits(actuators.steeringAngleDeg, self.apply_angle_last, CS.out.vEgoRaw, + CS.out.steeringAngleDeg, CC.latActive, CarControllerParams.ANGLE_LIMITS) + + # EPS disengages on steering override, activation sequence 2->3->4 to re-engage + # STATUS - 0: UNAVAILABLE, 1: UNSELECTED, 2: READY, 3: AUTHORIZED, 4: ACTIVE + if not CC.latActive: + self.status = 2 + elif not CS.eps_active and not CS.out.steeringPressed: + self.status = 2 if self.status == 4 else self.status + 1 + else: + self.status = 4 + + can_sends.append(create_lka_steering(self.packer, CC.latActive, apply_angle, self.status)) + + self.apply_angle_last = apply_angle + + new_actuators = actuators.as_builder() + new_actuators.steeringAngleDeg = self.apply_angle_last + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/psa/carstate.py b/opendbc_repo/opendbc/car/psa/carstate.py new file mode 100644 index 0000000000..81335ef598 --- /dev/null +++ b/opendbc_repo/opendbc/car/psa/carstate.py @@ -0,0 +1,73 @@ +from opendbc.car import structs, Bus +from opendbc.can.parser import CANParser +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.psa.values import DBC, CarControllerParams +from opendbc.car.interfaces import CarStateBase + +GearShifter = structs.CarState.GearShifter +TransmissionType = structs.CarParams.TransmissionType + + +class CarState(CarStateBase): + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.main] + cp_adas = can_parsers[Bus.adas] + cp_cam = can_parsers[Bus.cam] + ret = structs.CarState() + + # car speed + self.parse_wheel_speeds(ret, + cp.vl['Dyn4_FRE']['P263_VehV_VPsvValWhlFrtL'], + cp.vl['Dyn4_FRE']['P264_VehV_VPsvValWhlFrtR'], + cp.vl['Dyn4_FRE']['P265_VehV_VPsvValWhlBckL'], + cp.vl['Dyn4_FRE']['P266_VehV_VPsvValWhlBckR'], + ) + ret.yawRate = cp_adas.vl['HS2_DYN_UCF_MDD_32D']['VITESSE_LACET_BRUTE'] * CV.DEG_TO_RAD + ret.standstill = bool(cp_adas.vl['HS2_DYN_UCF_MDD_32D']['VEHICLE_STANDSTILL']) + + # gas + ret.gasPressed = cp.vl['Dyn_CMM']['P002_Com_rAPP'] > 0 + + # brake + ret.brakePressed = bool(cp_cam.vl['Dat_BSI']['P013_MainBrake']) + ret.parkingBrake = cp.vl['Dyn_EasyMove']['P337_Com_stPrkBrk'] == 1 # 0: disengaged, 1: engaged, 3: brake actuator moving + + # steering wheel + ret.steeringAngleDeg = cp.vl['STEERING_ALT']['ANGLE'] # EPS + ret.steeringRateDeg = cp.vl['STEERING_ALT']['RATE'] * (2 * cp.vl['STEERING_ALT']['RATE_SIGN'] - 1) # convert [0,1] to [-1,1] EPS: rot. speed * rot. sign + ret.steeringTorque = cp.vl['STEERING']['DRIVER_TORQUE'] + ret.steeringTorqueEps = cp.vl['IS_DAT_DIRA']['EPS_TORQUE'] + ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > CarControllerParams.STEER_DRIVER_ALLOWANCE, 5) + self.eps_active = cp.vl['IS_DAT_DIRA']['EPS_STATE_LKA'] == 3 # 0: Unauthorized, 1: Authorized, 2: Available, 3: Active, 4: Defect + + # cruise + ret.cruiseState.speed = cp_adas.vl['HS2_DAT_MDD_CMD_452']['SPEED_SETPOINT'] * CV.KPH_TO_MS # set to 255 when ACC is off, -2 kph offset from dash speed + ret.cruiseState.enabled = cp_adas.vl['HS2_DAT_MDD_CMD_452']['RVV_ACC_ACTIVATION_REQ'] == 1 + ret.cruiseState.available = cp_adas.vl['HS2_DYN1_MDD_ETAT_2B6']['ACC_STATUS'] > 2 + ret.cruiseState.nonAdaptive = cp_adas.vl['HS2_DAT_MDD_CMD_452']['LONGITUDINAL_REGULATION_TYPE'] != 3 # 0: None, 1: CC, 2: Limiter, 3: ACC + ret.cruiseState.standstill = bool(cp_adas.vl['HS2_DYN_UCF_MDD_32D']['VEHICLE_STANDSTILL']) + ret.accFaulted = cp_adas.vl['HS2_DYN_UCF_MDD_32D']['ACC_ETAT_DECEL_OR_ESP_STATUS'] == 3 # 0: Inhibited, 1: Waiting, 2: Active, 3: Fault + + # gear + if bool(cp_cam.vl['Dat_BSI']['P103_Com_bRevGear']): + ret.gearShifter = GearShifter.reverse + else: + ret.gearShifter = GearShifter.drive + + # blinkers + blinker = cp_cam.vl['HS2_DAT7_BSI_612']['CDE_CLG_ET_HDC'] + ret.leftBlinker = blinker == 1 + ret.rightBlinker = blinker == 2 + + # lock info + ret.doorOpen = any((cp_cam.vl['Dat_BSI']['DRIVER_DOOR'], cp_cam.vl['Dat_BSI']['PASSENGER_DOOR'])) + ret.seatbeltUnlatched = cp_cam.vl['RESTRAINTS']['DRIVER_SEATBELT'] != 2 + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.main: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0), + Bus.adas: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 1), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/psa/fingerprints.py b/opendbc_repo/opendbc/car/psa/fingerprints.py new file mode 100644 index 0000000000..497f8bb134 --- /dev/null +++ b/opendbc_repo/opendbc/car/psa/fingerprints.py @@ -0,0 +1,13 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.psa.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.PSA_PEUGEOT_208: { + (Ecu.fwdRadar, 0x6b6, None): [ + b'212053276', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/psa/interface.py b/opendbc_repo/opendbc/car/psa/interface.py new file mode 100644 index 0000000000..f719a3d6aa --- /dev/null +++ b/opendbc_repo/opendbc/car/psa/interface.py @@ -0,0 +1,30 @@ +from opendbc.car import structs, get_safety_config +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.psa.carcontroller import CarController +from opendbc.car.psa.carstate import CarState + +TransmissionType = structs.CarParams.TransmissionType + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = 'psa' + + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.psa)] + + ret.dashcamOnly = True + + ret.steerActuatorDelay = 0.3 + ret.steerLimitTimer = 0.1 + ret.steerAtStandstill = True + + ret.steerControlType = structs.CarParams.SteerControlType.angle + ret.radarUnavailable = True + + ret.alphaLongitudinalAvailable = False + + return ret \ No newline at end of file diff --git a/opendbc_repo/opendbc/car/psa/psacan.py b/opendbc_repo/opendbc/car/psa/psacan.py new file mode 100644 index 0000000000..a039e752a0 --- /dev/null +++ b/opendbc_repo/opendbc/car/psa/psacan.py @@ -0,0 +1,18 @@ +def psa_checksum(address: int, sig, d: bytearray) -> int: + chk_ini = {0x452: 0x4, 0x38D: 0x7, 0x42D: 0xC}.get(address, 0xB) + byte = sig.start_bit // 8 + d[byte] &= 0x0F if sig.start_bit % 8 >= 4 else 0xF0 + checksum = sum((b >> 4) + (b & 0xF) for b in d) + return (chk_ini - checksum) & 0xF + + +def create_lka_steering(packer, lat_active: bool, apply_angle: float, status: int): + values = { + 'DRIVE': 1, + 'STATUS': status, + 'LXA_ACTIVATION': 1, + 'TORQUE_FACTOR': lat_active * 100, + 'SET_ANGLE': apply_angle, + } + + return packer.make_can_msg('LANE_KEEP_ASSIST', 0, values) diff --git a/opendbc_repo/opendbc/car/psa/values.py b/opendbc_repo/opendbc/car/psa/values.py new file mode 100644 index 0000000000..5bd2a589c2 --- /dev/null +++ b/opendbc_repo/opendbc/car/psa/values.py @@ -0,0 +1,54 @@ +from dataclasses import dataclass, field + +from opendbc.car.structs import CarParams +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms +from opendbc.car.lateral import AngleSteeringLimits +from opendbc.car.docs_definitions import CarDocs, CarHarness, CarParts +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu + + +class CarControllerParams: + STEER_STEP = 1 + + ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits( + 390, # deg + ([0., 5., 25.], [2.5, 1.5, .2]), + ([0., 5., 25.], [5., 2., .3]), + ) + STEER_DRIVER_ALLOWANCE = 5 # Driver intervention threshold, 0.5 Nm + + +@dataclass +class PSACarDocs(CarDocs): + package: str = "Adaptive Cruise Control (ACC) & Lane Assist" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.psa_a])) + + +@dataclass +class PSAPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: { + Bus.pt: 'psa_aee2010_r3', + }) + + +class CAR(Platforms): + PSA_PEUGEOT_208 = PSAPlatformConfig( + [PSACarDocs("Peugeot 208 2019-25")], + CarSpecs(mass=1530, wheelbase=2.54, steerRatio=17.6), + ) + + +# Placeholder, FW Query will be added in separate PR +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.UDS_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.UDS_VERSION_RESPONSE], + bus=0, + ), + ], +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/rivian/__init__.py b/opendbc_repo/opendbc/car/rivian/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/rivian/carcontroller.py b/opendbc_repo/opendbc/car/rivian/carcontroller.py new file mode 100644 index 0000000000..6e7c3a12ff --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/carcontroller.py @@ -0,0 +1,58 @@ +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import Bus +from opendbc.car.lateral import apply_driver_steer_torque_limits +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.rivian.riviancan import create_lka_steering, create_longitudinal, create_wheel_touch, create_adas_status +from opendbc.car.rivian.values import CarControllerParams + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.apply_torque_last = 0 + self.packer = CANPacker(dbc_names[Bus.pt]) + + self.cancel_frames = 0 + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + can_sends = [] + + apply_torque = 0 + steer_max = round(float(np.interp(CS.out.vEgoRaw, CarControllerParams.STEER_MAX_LOOKUP[0], + CarControllerParams.STEER_MAX_LOOKUP[1]))) + if CC.latActive: + new_torque = int(round(CC.actuators.torque * steer_max)) + apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, + CS.out.steeringTorque, CarControllerParams, steer_max) + + # send steering command + self.apply_torque_last = apply_torque + can_sends.append(create_lka_steering(self.packer, self.frame, CS.acm_lka_hba_cmd, apply_torque, CC.enabled, CC.latActive)) + + if self.frame % 5 == 0: + can_sends.append(create_wheel_touch(self.packer, CS.sccm_wheel_touch, CC.enabled)) + + # Longitudinal control + if self.CP.openpilotLongitudinalControl: + accel = float(np.clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)) + can_sends.append(create_longitudinal(self.packer, self.frame, accel, CC.enabled)) + else: + interface_status = None + if CC.cruiseControl.cancel: + # if there is a noEntry, we need to send a status of "available" before the ACM will accept "unavailable" + # send "available" right away as the VDM itself takes a few frames to acknowledge + interface_status = 1 if self.cancel_frames < 5 else 0 + self.cancel_frames += 1 + else: + self.cancel_frames = 0 + + can_sends.append(create_adas_status(self.packer, CS.vdm_adas_status, interface_status)) + + new_actuators = actuators.as_builder() + new_actuators.torque = apply_torque / steer_max + new_actuators.torqueOutputCan = apply_torque + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/rivian/carstate.py b/opendbc_repo/opendbc/car/rivian/carstate.py new file mode 100644 index 0000000000..001d705ef0 --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/carstate.py @@ -0,0 +1,103 @@ +import copy +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import CarStateBase +from opendbc.car.rivian.values import DBC, GEAR_MAP +from opendbc.car.common.conversions import Conversions as CV + +GearShifter = structs.CarState.GearShifter + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + self.last_speed = 30 + + self.acm_lka_hba_cmd = None + self.sccm_wheel_touch = None + self.vdm_adas_status = None + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + cp_adas = can_parsers[Bus.adas] + ret = structs.CarState() + + # Vehicle speed + ret.vEgoRaw = cp.vl["ESP_Status"]["ESP_Vehicle_Speed"] * CV.KPH_TO_MS + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.standstill = abs(ret.vEgoRaw) < 0.01 + conversion = CV.KPH_TO_MS if cp_adas.vl["Cluster"]["Cluster_Unit"] == 0 else CV.MPH_TO_MS + ret.vEgoCluster = cp_adas.vl["Cluster"]["Cluster_VehicleSpeed"] * conversion + + # Gas pedal + ret.gasPressed = cp.vl["VDM_PropStatus"]["VDM_AcceleratorPedalPosition"] > 0 + + # Brake pedal + ret.brake = cp.vl["ESPiB3"]["ESPiB3_pMC1"] / 250.0 # pressure in Bar + ret.brakePressed = cp.vl["iBESP2"]["iBESP2_BrakePedalApplied"] == 1 + + # Steering wheel + ret.steeringAngleDeg = cp.vl["EPAS_AdasStatus"]["EPAS_InternalSas"] + ret.steeringRateDeg = cp.vl["EPAS_AdasStatus"]["EPAS_SteeringAngleSpeed"] + ret.steeringTorque = cp.vl["EPAS_SystemStatus"]["EPAS_TorsionBarTorque"] + ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > 1.0, 5) + + ret.steerFaultTemporary = cp.vl["EPAS_AdasStatus"]["EPAS_EacErrorCode"] != 0 + + # Cruise state + speed = min(int(cp_adas.vl["ACM_tsrCmd"]["ACM_tsrSpdDisClsMain"]), 85) + self.last_speed = speed if speed != 0 else self.last_speed + ret.cruiseState.enabled = cp_cam.vl["ACM_Status"]["ACM_FeatureStatus"] == 1 + # TODO: find cruise set speed on CAN + ret.cruiseState.speed = self.last_speed * CV.MPH_TO_MS # detected speed limit + if not self.CP.openpilotLongitudinalControl: + ret.cruiseState.speed = -1 + ret.cruiseState.available = True # cp.vl["VDM_AdasSts"]["VDM_AdasInterfaceStatus"] == 1 + ret.cruiseState.standstill = cp.vl["VDM_AdasSts"]["VDM_AdasVehicleHoldStatus"] == 1 + + # ACM_Status->ACM_FaultSupervisorState normally 1, appears to go to 3 when either: + # 1. car in park/not in drive (normal) + # 2. something (message from another ECU) ACM relies on is faulty + # * ACM_FaultStatus will stay 0 since ACM itself isn't faulted + # TODO: ACM_FaultStatus hasn't been seen high yet, but log anyway + ret.accFaulted = (cp_cam.vl["ACM_Status"]["ACM_FaultStatus"] == 1 or + # VDM_AdasFaultStatus=Brk_Intv is the default for some reason + # VDM_AdasFaultStatus=Cntr_Fault isn't fully understood, but we've seen it in the wild + # VDM_AdasFaultStatus=Imps_Cmd was seen when sending it rapidly changing ACC enable commands, or when ACC command drops out + cp.vl["VDM_AdasSts"]["VDM_AdasFaultStatus"] in (2, 3)) # 2=Cntr_Fault, 3=Imps_Cmd + + # Gear + ret.gearShifter = GEAR_MAP.get(int(cp.vl["VDM_PropStatus"]["VDM_Prndl_Status"]), GearShifter.unknown) + + # Doors + ret.doorOpen = any(cp_adas.vl["IndicatorLights"][door] != 2 for door in ("RearDriverDoor", "FrontPassengerDoor", "DriverDoor", "RearPassengerDoor")) + + # Blinkers + ret.leftBlinker = cp_adas.vl["IndicatorLights"]["TurnLightLeft"] in (1, 2) + ret.rightBlinker = cp_adas.vl["IndicatorLights"]["TurnLightRight"] in (1, 2) + + # Seatbelt + ret.seatbeltUnlatched = cp.vl["RCM_Status"]["RCM_Status_IND_WARN_BELT_DRIVER"] != 0 + + # Blindspot + # ret.leftBlindspot = False + # ret.rightBlindspot = False + + # AEB + ret.stockAeb = cp_cam.vl["ACM_AebRequest"]["ACM_EnableRequest"] != 0 + + # Messages needed by carcontroller + self.acm_lka_hba_cmd = copy.copy(cp_cam.vl["ACM_lkaHbaCmd"]) + self.sccm_wheel_touch = copy.copy(cp.vl["SCCM_WheelTouch"]) + self.vdm_adas_status = copy.copy(cp.vl["VDM_AdasSts"]) + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 0), + Bus.adas: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 1), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/rivian/fingerprints.py b/opendbc_repo/opendbc/car/rivian/fingerprints.py new file mode 100644 index 0000000000..bc58d97150 --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/fingerprints.py @@ -0,0 +1,14 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.rivian.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.RIVIAN_R1_GEN1: { + (Ecu.eps, 0x733, None): [ + b'R1TS_v3.4.1(51),3.4.1\x00', + b'R1TS_v4.4.1(63),4.4.1\x00', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/rivian/interface.py b/opendbc_repo/opendbc/car/rivian/interface.py new file mode 100644 index 0000000000..f1108e0811 --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/interface.py @@ -0,0 +1,37 @@ +from opendbc.car import get_safety_config, structs +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.rivian.carcontroller import CarController +from opendbc.car.rivian.carstate import CarState +from opendbc.car.rivian.radar_interface import RadarInterface +from opendbc.car.rivian.values import RivianSafetyFlags + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "rivian" + + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.rivian)] + + ret.steerActuatorDelay = 0.15 + ret.steerLimitTimer = 0.4 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + ret.steerControlType = structs.CarParams.SteerControlType.torque + ret.radarUnavailable = True + + # TODO: pending finding/handling missing set speed and fixing up radar parser + ret.alphaLongitudinalAvailable = False + if alpha_long: + ret.openpilotLongitudinalControl = True + ret.safetyConfigs[0].safetyParam |= RivianSafetyFlags.LONG_CONTROL.value + + ret.longitudinalActuatorDelay = 0.35 + ret.vEgoStopping = 0.25 + ret.stopAccel = 0 + + return ret diff --git a/opendbc_repo/opendbc/car/rivian/radar_interface.py b/opendbc_repo/opendbc/car/rivian/radar_interface.py new file mode 100644 index 0000000000..f74acafe9f --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/radar_interface.py @@ -0,0 +1,72 @@ +import math + +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import RadarInterfaceBase +from opendbc.car.rivian.values import DBC + +RADAR_START_ADDR = 0x500 +RADAR_MSG_COUNT = 32 + + +def get_radar_can_parser(CP): + messages = [(f"RADAR_TRACK_{addr:x}", 20) for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT)] + return CANParser(DBC[CP.carFingerprint][Bus.radar], messages, 1) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + self.updated_messages = set() + self.trigger_msg = RADAR_START_ADDR + RADAR_MSG_COUNT - 1 + self.track_id = 0 + + self.radar_off_can = CP.radarUnavailable + self.rcp = get_radar_can_parser(CP) + + def update(self, can_strings): + if self.radar_off_can or (self.rcp is None): + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + + rr = self._update(self.updated_messages) + self.updated_messages.clear() + + return rr + + def _update(self, updated_messages): + ret = structs.RadarData() + if self.rcp is None: + return ret + + if not self.rcp.can_valid: + ret.errors.canError = True + + for addr in range(RADAR_START_ADDR, RADAR_START_ADDR + RADAR_MSG_COUNT): + msg = self.rcp.vl[f"RADAR_TRACK_{addr:x}"] + + if addr not in self.pts: + self.pts[addr] = structs.RadarData.RadarPoint() + self.pts[addr].trackId = self.track_id + self.track_id += 1 + + valid = msg['STATE'] in (3, 4) and msg['STATE_2'] == 1 + if valid: + azimuth = math.radians(msg['AZIMUTH']) + self.pts[addr].measured = True + self.pts[addr].dRel = math.cos(azimuth) * msg['LONG_DIST'] + self.pts[addr].yRel = 0.5 * -math.sin(azimuth) * msg['LONG_DIST'] + self.pts[addr].vRel = msg['REL_SPEED'] + self.pts[addr].aRel = float('nan') + self.pts[addr].yvRel = float('nan') + + else: + del self.pts[addr] + + ret.points = list(self.pts.values()) + return ret diff --git a/opendbc_repo/opendbc/car/rivian/riviancan.py b/opendbc_repo/opendbc/car/rivian/riviancan.py new file mode 100644 index 0000000000..bbe679c20a --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/riviancan.py @@ -0,0 +1,99 @@ +def checksum(data, poly, xor_output): + crc = 0 + for byte in data: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = (crc << 1) ^ poly + else: + crc <<= 1 + crc &= 0xFF + return crc ^ xor_output + + +def create_lka_steering(packer, frame, acm_lka_hba_cmd, apply_torque, enabled, active): + # forward auto high beam and speed limit status and nothing else + values = {s: acm_lka_hba_cmd[s] for s in ( + "ACM_hbaSysState", + "ACM_hbaLamp", + "ACM_hbaOnOffState", + "ACM_slifOnOffState", + )} + + values |= { + "ACM_lkaHbaCmd_Counter": frame % 15, + "ACM_lkaStrToqReq": apply_torque, + "ACM_lkaActToi": active, + + "ACM_lkaLaneRecogState": 3 if enabled else 0, + "ACM_lkaSymbolState": 3 if enabled else 0, + + # static values + "ACM_lkaElkRequest": 0, + "ACM_ldwlkaOnOffState": 2, # 2=LKAS+LDW on + "ACM_elkOnOffState": 1, # 1=LKAS on + # TODO: what are these used for? + "ACM_ldwWarnTypeState": 2, # always 2 + "ACM_ldwWarnTimingState": 1, # always 1 + #"ACM_lkaHandsoffDisplayWarning": 1, # TODO: we can send this when openpilot wants you to pay attention + } + + data = packer.make_can_msg("ACM_lkaHbaCmd", 0, values)[1] + values["ACM_lkaHbaCmd_Checksum"] = checksum(data[1:], 0x1D, 0x63) + return packer.make_can_msg("ACM_lkaHbaCmd", 0, values) + + +def create_wheel_touch(packer, sccm_wheel_touch, enabled): + values = {s: sccm_wheel_touch[s] for s in ( + "SCCM_WheelTouch_Counter", + "SCCM_WheelTouch_HandsOn", + "SCCM_WheelTouch_CapacitiveValue", + "SETME_X52", + )} + + # When only using ACC without lateral, the ACM warns the driver to hold the steering wheel on engagement + # Tell the ACM that the user is holding the wheel to avoid this warning + if enabled: + values["SCCM_WheelTouch_HandsOn"] = 1 + values["SCCM_WheelTouch_CapacitiveValue"] = 100 # only need to send this value, but both are set for consistency + + data = packer.make_can_msg("SCCM_WheelTouch", 2, values)[1] + values["SCCM_WheelTouch_Checksum"] = checksum(data[1:], 0x1D, 0x97) + return packer.make_can_msg("SCCM_WheelTouch", 2, values) + + +def create_longitudinal(packer, frame, accel, enabled): + values = { + "ACM_longitudinalRequest_Counter": frame % 15, + "ACM_AccelerationRequest": accel, + "ACM_PrndRequest": 0, + "ACM_longInterfaceEnable": 1 if enabled else 0, + "ACM_VehicleHoldRequest": 0, + } + + data = packer.make_can_msg("ACM_longitudinalRequest", 0, values)[1] + values["ACM_longitudinalRequest_Checksum"] = checksum(data[1:], 0x1D, 0x12) + return packer.make_can_msg("ACM_longitudinalRequest", 0, values) + + +def create_adas_status(packer, vdm_adas_status, interface_status): + values = {s: vdm_adas_status[s] for s in ( + "VDM_AdasStatus_Checksum", + "VDM_AdasStatus_Counter", + "VDM_AdasDecelLimit", + "VDM_AdasDriverAccelPriorityStatus", + "VDM_AdasFaultStatus", + "VDM_AdasAccelLimit", + "VDM_AdasDriverModeStatus", + "VDM_AdasUnkown1", + "VDM_AdasInterfaceStatus", + "VDM_AdasVehicleHoldStatus", + "VDM_UserAdasRequest", + )} + + if interface_status is not None: + values["VDM_AdasInterfaceStatus"] = interface_status + + data = packer.make_can_msg("VDM_AdasSts", 2, values)[1] + values["VDM_AdasStatus_Checksum"] = checksum(data[1:], 0x1D, 0xD1) + return packer.make_can_msg("VDM_AdasSts", 2, values) diff --git a/opendbc_repo/opendbc/car/rivian/tests/__init__.py b/opendbc_repo/opendbc/car/rivian/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/rivian/tests/test_rivian.py b/opendbc_repo/opendbc/car/rivian/tests/test_rivian.py new file mode 100644 index 0000000000..90dcfcd5dd --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/tests/test_rivian.py @@ -0,0 +1,23 @@ +from opendbc.car.rivian.fingerprints import FW_VERSIONS +from opendbc.car.rivian.values import CAR, FW_QUERY_CONFIG, WMI, ModelLine, ModelYear + + +class TestRivian: + def test_custom_fuzzy_fingerprinting(self, subtests): + for platform in CAR: + with subtests.test(platform=platform.name): + for wmi in WMI: + for line in ModelLine: + for year in ModelYear: + for bad in (True, False): + vin = ["0"] * 17 + vin[:3] = wmi + vin[3] = line.value + vin[9] = year.value + if bad: + vin[3] = "Z" + vin = "".join(vin) + + matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy({}, vin, FW_VERSIONS) + should_match = year != ModelYear.S_2025 and not bad + assert (matches == {platform}) == should_match, "Bad match" diff --git a/opendbc_repo/opendbc/car/rivian/values.py b/opendbc_repo/opendbc/car/rivian/values.py new file mode 100644 index 0000000000..bd50e622e8 --- /dev/null +++ b/opendbc_repo/opendbc/car/rivian/values.py @@ -0,0 +1,138 @@ +from dataclasses import dataclass, field +from enum import StrEnum, IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, structs, uds +from opendbc.car.docs_definitions import CarHarness, CarDocs, CarParts, Device +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 +from opendbc.car.vin import Vin + + +class WMI(StrEnum): + RIVIAN_TRUCK = "7FC" + RIVIAN_MPV = "7PD" + + +class ModelLine(StrEnum): + R1T = "T" # R1T 4-door Pickup Truck + R1S = "S" # R1S 4-door MPV + + +class ModelYear(StrEnum): + N_2022 = "N" + P_2023 = "P" + R_2024 = "R" + S_2025 = "S" + + +@dataclass +class RivianCarDocs(CarDocs): + package: str = "All" + car_parts: CarParts = field(default_factory=CarParts([Device.threex_angled_mount, CarHarness.rivian])) + setup_video: str = "https://youtu.be/uaISd1j7Z4U" + + +@dataclass +class RivianPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'rivian_primary_actuator', Bus.radar: 'rivian_mando_front_radar_generated'}) + wmis: set[WMI] = field(default_factory=set) + lines: set[ModelLine] = field(default_factory=set) + years: set[ModelYear] = field(default_factory=set) + + +class CAR(Platforms): + RIVIAN_R1_GEN1 = RivianPlatformConfig( + # TODO: verify this + [ + RivianCarDocs("Rivian R1S 2022-24"), + RivianCarDocs("Rivian R1T 2022-24"), + ], + CarSpecs(mass=3206., wheelbase=3.08, steerRatio=15.2), + wmis={WMI.RIVIAN_TRUCK, WMI.RIVIAN_MPV}, + lines={ModelLine.R1T, ModelLine.R1S}, + years={ModelYear.N_2022, ModelYear.P_2023, ModelYear.R_2024}, + ) + + +def match_fw_to_car_fuzzy(live_fw_versions, vin, offline_fw_versions) -> set[str]: + # Rivian VIN reference: https://www.rivianforums.com/forum/threads/rivian-vin-decoder.1546 + vin_obj = Vin(vin) + line = vin_obj.vds[:1] + year = vin_obj.vis[:1] + + candidates = set() + for platform in CAR: + if vin_obj.wmi in platform.config.wmis and line in platform.config.lines and year in platform.config.years: + candidates.add(platform) + + return {str(c) for c in candidates} + + +RIVIAN_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(0xf1a0) +RIVIAN_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.SUPPLIER_SOFTWARE_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.SUPPLIER_SOFTWARE_VERSION_RESPONSE], + rx_offset=0x40, + bus=0, + ), + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_ECU_HARDWARE_NUMBER_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_ECU_HARDWARE_NUMBER_RESPONSE], + rx_offset=0x40, + bus=0, + logging=True, + ), + Request( + [StdQueries.TESTER_PRESENT_REQUEST, RIVIAN_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, RIVIAN_VERSION_RESPONSE], + rx_offset=0x40, + bus=0, + logging=True, + ), + ], + match_fw_to_car_fuzzy=match_fw_to_car_fuzzy, +) + +GEAR_MAP = { + 0: structs.CarState.GearShifter.unknown, + 1: structs.CarState.GearShifter.park, + 2: structs.CarState.GearShifter.reverse, + 3: structs.CarState.GearShifter.neutral, + 4: structs.CarState.GearShifter.drive, +} + + +class CarControllerParams: + # The R1T 2023 and R1S 2023 we tested on achieves slightly more lateral acceleration going left vs. right + # and lateral acceleration falls linearly as speed decreases from 38 mph to 20 mph. These values are set + # conservatively to reach a maximum of 3.0 m/s^2 turning left at 80 mph + + # These refer to turning left: + # 250 is ~2.8 m/s^2 above 17 m/s, then linearly ramps to ~1.6 m/s^2 from 17 m/s to 9 m/s + # TODO: it is theorized older models have different steering racks and achieve down to half the + # lateral acceleration referenced here at all speeds. detect this and ship a torque increase for those models + STEER_MAX = 250 # 350 is intended to maintain lateral accel, not increase it + STEER_MAX_LOOKUP = [9, 17], [350, 250] + STEER_STEP = 1 + STEER_DELTA_UP = 3 # torque increase per refresh + STEER_DELTA_DOWN = 5 # torque decrease per refresh + STEER_DRIVER_ALLOWANCE = 100 # allowed driver torque before start limiting + STEER_DRIVER_MULTIPLIER = 2 # weight driver torque + STEER_DRIVER_FACTOR = 100 + + ACCEL_MIN = -3.5 # m/s^2 + ACCEL_MAX = 2.0 # m/s^2 + + def __init__(self, CP): + pass + + +class RivianSafetyFlags(IntFlag): + LONG_CONTROL = 1 + + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/secoc.py b/opendbc_repo/opendbc/car/secoc.py new file mode 100644 index 0000000000..c61f4ca14a --- /dev/null +++ b/opendbc_repo/opendbc/car/secoc.py @@ -0,0 +1,49 @@ +import struct + +from Crypto.Hash import CMAC +from Crypto.Cipher import AES + + +def add_mac(key, trip_cnt, reset_cnt, msg_cnt, msg): + # TODO: clean up conversion to and from hex + + addr, payload, bus = msg + reset_flag = reset_cnt & 0b11 + msg_cnt_flag = msg_cnt & 0b11 + payload = payload[:4] + + # Step 1: Build Freshness Value (48 bits) + # [Trip Counter (16 bit)][[Reset Counter (20 bit)][Message Counter (8 bit)][Reset Flag (2 bit)][Padding (2 bit)] + freshness_value = struct.pack('>HI', trip_cnt, (reset_cnt << 12) | ((msg_cnt & 0xff) << 4) | (reset_flag << 2)) + + # Step 2: Build data to authenticate (96 bits) + # [Message ID (16 bits)][Payload (32 bits)][Freshness Value (48 bits)] + to_auth = struct.pack('>H', addr) + payload + freshness_value + + # Step 3: Calculate CMAC (28 bit) + cmac = CMAC.new(key, ciphermod=AES) + cmac.update(to_auth) + mac = cmac.digest().hex()[:7] # truncated MAC + + # Step 4: Build message + # [Payload (32 bit)][Message Counter Flag (2 bit)][Reset Flag (2 bit)][Authenticator (28 bit)] + msg_cnt_rst_flag = struct.pack('>B', (msg_cnt_flag << 2) | reset_flag).hex()[1] + msg = payload.hex() + msg_cnt_rst_flag + mac + payload = bytes.fromhex(msg) + + return (addr, payload, bus) + + +def build_sync_mac(key, trip_cnt, reset_cnt, id_=0xf): + id_ = struct.pack('>H', id_) # 16 + trip_cnt = struct.pack('>H', trip_cnt) # 16 + reset_cnt = struct.pack('>I', reset_cnt << 12)[:-1] # 20 + 4 padding + + to_auth = id_ + trip_cnt + reset_cnt # SecOC 11.4.1.1 page 138 + + cmac = CMAC.new(key, ciphermod=AES) + cmac.update(to_auth) + + msg = "0" + cmac.digest().hex()[:7] + msg = bytes.fromhex(msg) + return struct.unpack('>I', msg)[0] diff --git a/opendbc_repo/opendbc/car/structs.py b/opendbc_repo/opendbc/car/structs.py new file mode 100644 index 0000000000..a5628c7e00 --- /dev/null +++ b/opendbc_repo/opendbc/car/structs.py @@ -0,0 +1,20 @@ +import os +import capnp +from opendbc.car.common.basedir import BASEDIR + +# TODO: remove car from cereal/__init__.py and always import from opendbc +try: + from cereal import car +except ImportError: + capnp.remove_import_hook() + car = capnp.load(os.path.join(BASEDIR, "car.capnp")) + +CarState = car.CarState +RadarData = car.RadarData +CarControl = car.CarControl +CarParams = car.CarParams + +CarStateT = capnp.lib.capnp._StructModule +RadarDataT = capnp.lib.capnp._StructModule +CarControlT = capnp.lib.capnp._StructModule +CarParamsT = capnp.lib.capnp._StructModule diff --git a/opendbc_repo/opendbc/car/subaru/__init__.py b/opendbc_repo/opendbc/car/subaru/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/subaru/carcontroller.py b/opendbc_repo/opendbc/car/subaru/carcontroller.py new file mode 100644 index 0000000000..3b9abf5917 --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/carcontroller.py @@ -0,0 +1,144 @@ +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import Bus, make_tester_present_msg +from opendbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.subaru import subarucan +from opendbc.car.subaru.values import DBC, GLOBAL_ES_ADDR, CanBus, CarControllerParams, SubaruFlags + +# FIXME: These limits aren't exact. The real limit is more than likely over a larger time period and +# involves the total steering angle change rather than rate, but these limits work well for now +MAX_STEER_RATE = 25 # deg/s +MAX_STEER_RATE_FRAMES = 7 # tx control frames needed before torque can be cut + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.apply_torque_last = 0 + + self.cruise_button_prev = 0 + self.steer_rate_counter = 0 + + self.p = CarControllerParams(CP) + self.packer = CANPacker(DBC[CP.carFingerprint][Bus.pt]) + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + hud_control = CC.hudControl + pcm_cancel_cmd = CC.cruiseControl.cancel + + can_sends = [] + + # *** steering *** + if (self.frame % self.p.STEER_STEP) == 0: + apply_torque = int(round(actuators.torque * self.p.STEER_MAX)) + + # limits due to driver torque + + new_torque = int(round(apply_torque)) + apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.p) + + if not CC.latActive: + apply_torque = 0 + + if self.CP.flags & SubaruFlags.PREGLOBAL: + can_sends.append(subarucan.create_preglobal_steering_control(self.packer, self.frame // self.p.STEER_STEP, apply_torque, CC.latActive)) + else: + apply_steer_req = CC.latActive + + if self.CP.flags & SubaruFlags.STEER_RATE_LIMITED: + # Steering rate fault prevention + self.steer_rate_counter, apply_steer_req = \ + common_fault_avoidance(abs(CS.out.steeringRateDeg) > MAX_STEER_RATE, apply_steer_req, + self.steer_rate_counter, MAX_STEER_RATE_FRAMES) + + can_sends.append(subarucan.create_steering_control(self.packer, apply_torque, apply_steer_req)) + + self.apply_torque_last = apply_torque + + # *** longitudinal *** + + if CC.longActive: + apply_throttle = int(round(np.interp(actuators.accel, CarControllerParams.THROTTLE_LOOKUP_BP, CarControllerParams.THROTTLE_LOOKUP_V))) + apply_rpm = int(round(np.interp(actuators.accel, CarControllerParams.RPM_LOOKUP_BP, CarControllerParams.RPM_LOOKUP_V))) + apply_brake = int(round(np.interp(actuators.accel, CarControllerParams.BRAKE_LOOKUP_BP, CarControllerParams.BRAKE_LOOKUP_V))) + + # limit min and max values + cruise_throttle = np.clip(apply_throttle, CarControllerParams.THROTTLE_MIN, CarControllerParams.THROTTLE_MAX) + cruise_rpm = np.clip(apply_rpm, CarControllerParams.RPM_MIN, CarControllerParams.RPM_MAX) + cruise_brake = np.clip(apply_brake, CarControllerParams.BRAKE_MIN, CarControllerParams.BRAKE_MAX) + else: + cruise_throttle = CarControllerParams.THROTTLE_INACTIVE + cruise_rpm = CarControllerParams.RPM_MIN + cruise_brake = CarControllerParams.BRAKE_MIN + + # *** alerts and pcm cancel *** + if self.CP.flags & SubaruFlags.PREGLOBAL: + if self.frame % 5 == 0: + # 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep + # disengage ACC when OP is disengaged + if pcm_cancel_cmd: + cruise_button = 1 + # turn main on if off and past start-up state + elif not CS.out.cruiseState.available and CS.ready: + cruise_button = 1 + else: + cruise_button = CS.cruise_button + + # unstick previous mocked button press + if cruise_button == 1 and self.cruise_button_prev == 1: + cruise_button = 0 + self.cruise_button_prev = cruise_button + + can_sends.append(subarucan.create_preglobal_es_distance(self.packer, cruise_button, CS.es_distance_msg)) + + else: + if self.frame % 10 == 0: + can_sends.append(subarucan.create_es_dashstatus(self.packer, self.frame // 10, CS.es_dashstatus_msg, CC.enabled, + self.CP.openpilotLongitudinalControl, CC.longActive, hud_control.leadVisible)) + + can_sends.append(subarucan.create_es_lkas_state(self.packer, self.frame // 10, CS.es_lkas_state_msg, CC.enabled, hud_control.visualAlert, + hud_control.leftLaneVisible, hud_control.rightLaneVisible, + hud_control.leftLaneDepart, hud_control.rightLaneDepart)) + + if self.CP.flags & SubaruFlags.SEND_INFOTAINMENT: + can_sends.append(subarucan.create_es_infotainment(self.packer, self.frame // 10, CS.es_infotainment_msg, hud_control.visualAlert)) + + if self.CP.openpilotLongitudinalControl: + if self.frame % 5 == 0: + can_sends.append(subarucan.create_es_status(self.packer, self.frame // 5, CS.es_status_msg, + self.CP.openpilotLongitudinalControl, CC.longActive, cruise_rpm)) + + can_sends.append(subarucan.create_es_brake(self.packer, self.frame // 5, CS.es_brake_msg, + self.CP.openpilotLongitudinalControl, CC.longActive, cruise_brake)) + + can_sends.append(subarucan.create_es_distance(self.packer, self.frame // 5, CS.es_distance_msg, 0, pcm_cancel_cmd, + self.CP.openpilotLongitudinalControl, cruise_brake > 0, cruise_throttle)) + else: + if pcm_cancel_cmd: + if not (self.CP.flags & SubaruFlags.HYBRID): + bus = CanBus.alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else CanBus.main + can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg["COUNTER"] + 1, CS.es_distance_msg, bus, pcm_cancel_cmd)) + + if self.CP.flags & SubaruFlags.DISABLE_EYESIGHT: + # Tester present (keeps eyesight disabled) + if self.frame % 100 == 0: + can_sends.append(make_tester_present_msg(GLOBAL_ES_ADDR, CanBus.camera, suppress_response=True)) + + # Create all of the other eyesight messages to keep the rest of the car happy when eyesight is disabled + if self.frame % 5 == 0: + can_sends.append(subarucan.create_es_highbeamassist(self.packer)) + + if self.frame % 10 == 0: + can_sends.append(subarucan.create_es_static_1(self.packer)) + + if self.frame % 2 == 0: + can_sends.append(subarucan.create_es_static_2(self.packer)) + + new_actuators = actuators.as_builder() + new_actuators.torque = self.apply_torque_last / self.p.STEER_MAX + new_actuators.torqueOutputCan = self.apply_torque_last + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/subaru/carstate.py b/opendbc_repo/opendbc/car/subaru/carstate.py new file mode 100644 index 0000000000..76bc4ff8f7 --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/carstate.py @@ -0,0 +1,134 @@ +import copy +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarStateBase +from opendbc.car.subaru.values import DBC, CanBus, SubaruFlags +from opendbc.car import CanSignalRateCalculator + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + self.shifter_values = can_define.dv["Transmission"]["Gear"] + + self.angle_rate_calulator = CanSignalRateCalculator(50) + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + cp_alt = can_parsers[Bus.alt] + ret = structs.CarState() + + throttle_msg = cp.vl["Throttle"] if not (self.CP.flags & SubaruFlags.HYBRID) else cp_alt.vl["Throttle_Hybrid"] + ret.gasPressed = throttle_msg["Throttle_Pedal"] > 1e-5 + if self.CP.flags & SubaruFlags.PREGLOBAL: + ret.brakePressed = cp.vl["Brake_Pedal"]["Brake_Pedal"] > 0 + else: + cp_brakes = cp_alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp + ret.brakePressed = cp_brakes.vl["Brake_Status"]["Brake"] == 1 + + cp_es_distance = cp_alt if self.CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID) else cp_cam + if not (self.CP.flags & SubaruFlags.HYBRID): + eyesight_fault = bool(cp_es_distance.vl["ES_Distance"]["Cruise_Fault"]) + + # if openpilot is controlling long, an eyesight fault is a non-critical fault. otherwise it's an ACC fault + if self.CP.openpilotLongitudinalControl: + ret.carFaultedNonCritical = eyesight_fault + else: + ret.accFaulted = eyesight_fault + + cp_wheels = cp_alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp + self.parse_wheel_speeds(ret, + cp_wheels.vl["Wheel_Speeds"]["FL"], + cp_wheels.vl["Wheel_Speeds"]["FR"], + cp_wheels.vl["Wheel_Speeds"]["RL"], + cp_wheels.vl["Wheel_Speeds"]["RR"], + ) + ret.standstill = ret.vEgoRaw == 0 + + # continuous blinker signals for assisted lane change + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["Dashlights"]["LEFT_BLINKER"], + cp.vl["Dashlights"]["RIGHT_BLINKER"]) + + if self.CP.enableBsm: + ret.leftBlindspot = (cp.vl["BSD_RCTA"]["L_ADJACENT"] == 1) or (cp.vl["BSD_RCTA"]["L_APPROACHING"] == 1) + ret.rightBlindspot = (cp.vl["BSD_RCTA"]["R_ADJACENT"] == 1) or (cp.vl["BSD_RCTA"]["R_APPROACHING"] == 1) + + cp_transmission = cp_alt if self.CP.flags & SubaruFlags.HYBRID else cp + can_gear = int(cp_transmission.vl["Transmission"]["Gear"]) + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None)) + + ret.steeringAngleDeg = cp.vl["Steering_Torque"]["Steering_Angle"] + + if not (self.CP.flags & SubaruFlags.PREGLOBAL): + # ideally we get this from the car, but unclear if it exists. diagnostic software doesn't even have it + ret.steeringRateDeg = self.angle_rate_calulator.update(ret.steeringAngleDeg, cp.vl["Steering_Torque"]["COUNTER"]) + + ret.steeringTorque = cp.vl["Steering_Torque"]["Steer_Torque_Sensor"] + ret.steeringTorqueEps = cp.vl["Steering_Torque"]["Steer_Torque_Output"] + + steer_threshold = 75 if self.CP.flags & SubaruFlags.PREGLOBAL else 80 + ret.steeringPressed = abs(ret.steeringTorque) > steer_threshold + + cp_cruise = cp_alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp + if self.CP.flags & SubaruFlags.HYBRID: + ret.cruiseState.enabled = cp_cam.vl["ES_DashStatus"]['Cruise_Activated'] != 0 + ret.cruiseState.available = cp_cam.vl["ES_DashStatus"]['Cruise_On'] != 0 + else: + ret.cruiseState.enabled = cp_cruise.vl["CruiseControl"]["Cruise_Activated"] != 0 + ret.cruiseState.available = cp_cruise.vl["CruiseControl"]["Cruise_On"] != 0 + ret.cruiseState.speed = cp_cam.vl["ES_DashStatus"]["Cruise_Set_Speed"] * CV.KPH_TO_MS + + if (self.CP.flags & SubaruFlags.PREGLOBAL and cp.vl["Dash_State2"]["UNITS"] == 1) or \ + (not (self.CP.flags & SubaruFlags.PREGLOBAL) and cp.vl["Dashlights"]["UNITS"] == 1): + ret.cruiseState.speed *= CV.MPH_TO_KPH + + ret.seatbeltUnlatched = cp.vl["Dashlights"]["SEATBELT_FL"] == 1 + ret.doorOpen = any([cp.vl["BodyInfo"]["DOOR_OPEN_RR"], + cp.vl["BodyInfo"]["DOOR_OPEN_RL"], + cp.vl["BodyInfo"]["DOOR_OPEN_FR"], + cp.vl["BodyInfo"]["DOOR_OPEN_FL"]]) + ret.steerFaultPermanent = cp.vl["Steering_Torque"]["Steer_Error_1"] == 1 + + if self.CP.flags & SubaruFlags.PREGLOBAL: + self.cruise_button = cp_cam.vl["ES_Distance"]["Cruise_Button"] + self.ready = not cp_cam.vl["ES_DashStatus"]["Not_Ready_Startup"] + else: + ret.steerFaultTemporary = cp.vl["Steering_Torque"]["Steer_Warning"] == 1 + ret.cruiseState.nonAdaptive = cp_cam.vl["ES_DashStatus"]["Conventional_Cruise"] == 1 + ret.cruiseState.standstill = cp_cam.vl["ES_DashStatus"]["Cruise_State"] == 3 + ret.stockFcw = (cp_cam.vl["ES_LKAS_State"]["LKAS_Alert"] == 1) or \ + (cp_cam.vl["ES_LKAS_State"]["LKAS_Alert"] == 2) + + self.es_lkas_state_msg = copy.copy(cp_cam.vl["ES_LKAS_State"]) + cp_es_brake = cp_alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp_cam + self.es_brake_msg = copy.copy(cp_es_brake.vl["ES_Brake"]) + cp_es_status = cp_alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp_cam + + # TODO: Hybrid cars don't have ES_Distance, need a replacement + if not (self.CP.flags & SubaruFlags.HYBRID): + # 8 is known AEB, there are a few other values related to AEB we ignore + ret.stockAeb = (cp_es_distance.vl["ES_Brake"]["AEB_Status"] == 8) and \ + (cp_es_distance.vl["ES_Brake"]["Brake_Pressure"] != 0) + + self.es_status_msg = copy.copy(cp_es_status.vl["ES_Status"]) + self.cruise_control_msg = copy.copy(cp_cruise.vl["CruiseControl"]) + + if not (self.CP.flags & SubaruFlags.HYBRID): + self.es_distance_msg = copy.copy(cp_es_distance.vl["ES_Distance"]) + + self.es_dashstatus_msg = copy.copy(cp_cam.vl["ES_DashStatus"]) + if self.CP.flags & SubaruFlags.SEND_INFOTAINMENT: + self.es_infotainment_msg = copy.copy(cp_cam.vl["ES_Infotainment"]) + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.main), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.camera), + Bus.alt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.alt) + } diff --git a/opendbc_repo/opendbc/car/subaru/fingerprints.py b/opendbc_repo/opendbc/car/subaru/fingerprints.py new file mode 100644 index 0000000000..64158446bd --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/fingerprints.py @@ -0,0 +1,580 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.subaru.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.SUBARU_ASCENT: { + (Ecu.abs, 0x7b0, None): [ + b'\xa5 \x19\x02\x00', + b'\xa5 !\x02\x00', + ], + (Ecu.eps, 0x746, None): [ + b'\x05\xc0\xd0\x00', + b'\x85\xc0\xd0\x00', + b'\x95\xc0\xd0\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00d\xb9\x00\x00\x00\x00', + b'\x00\x00d\xb9\x1f@ \x10', + b'\x00\x00e@\x00\x00\x00\x00', + b'\x00\x00e@\x1f@ $', + b"\x00\x00e~\x1f@ '", + ], + (Ecu.engine, 0x7e0, None): [ + b'\xbb,\xa0t\x07', + b'\xd1,\xa0q\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\x00>\xf0\x00\x00', + b'\x00\xfe\xf7\x00\x00', + b'\x01\xfe\xf7\x00\x00', + b'\x01\xfe\xf9\x00\x00', + b'\x01\xfe\xfa\x00\x00', + ], + }, + CAR.SUBARU_ASCENT_2023: { + (Ecu.abs, 0x7b0, None): [ + b'\xa5 #\x03\x00', + ], + (Ecu.eps, 0x746, None): [ + b'%\xc0\xd0\x11', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x05!\x08\x1dK\x05!\x08\x01/', + ], + (Ecu.engine, 0x7a2, None): [ + b'\xe5,\xa0P\x07', + ], + (Ecu.transmission, 0x7a3, None): [ + b'\x04\xfe\xf3\x00\x00', + ], + }, + CAR.SUBARU_LEGACY: { + (Ecu.abs, 0x7b0, None): [ + b'\xa1 \x02\x01', + b'\xa1 \x02\x02', + b'\xa1 \x03\x02', + b'\xa1 \x03\x03', + b'\xa1 \x04\x01', + b'\xa1 \x04\x02', + ], + (Ecu.eps, 0x746, None): [ + b'\x9b\xc0\x11\x00', + b'\x9b\xc0\x11\x02', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00e\x80\x00\x1f@ \x19\x00', + b'\x00\x00e\x9a\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xde"a0\x07', + b'\xde,\xa0@\x07', + b'\xe2"a0\x07', + b'\xe2"ap\x07', + b'\xe2"aq\x07', + b'\xe2,\xa0@\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xa5\xf6\x05@\x00', + b'\xa5\xfe\xc7@\x00', + b'\xa7\xf6\x04@\x00', + b'\xa7\xfe\xc4@\x00', + ], + }, + CAR.SUBARU_IMPREZA: { + (Ecu.abs, 0x7b0, None): [ + b'z\x84\x19\x90\x00', + b'z\x94\x08\x90\x00', + b'z\x94\x08\x90\x01', + b'z\x94\x0c\x90\x00', + b'z\x94\x0c\x90\x01', + b'z\x94.\x90\x00', + b'z\x94?\x90\x00', + b'z\x9c\x19\x80\x01', + b'\xa2 \x185\x00', + b'\xa2 \x193\x00', + b'\xa2 \x194\x00', + b'\xa2 \x19`\x00', + ], + (Ecu.eps, 0x746, None): [ + b'z\xc0\x00\x00', + b'z\xc0\x04\x00', + b'z\xc0\x08\x00', + b'z\xc0\n\x00', + b'z\xc0\x0c\x00', + b'\x8a\xc0\x00\x00', + b'\x8a\xc0\x10\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00c\xf4\x00\x00\x00\x00', + b'\x00\x00c\xf4\x1f@ \x07', + b'\x00\x00d)\x00\x00\x00\x00', + b'\x00\x00d)\x1f@ \x07', + b'\x00\x00dd\x00\x00\x00\x00', + b'\x00\x00dd\x1f@ \x0e', + b'\x00\x00d\xb5\x1f@ \x0e', + b'\x00\x00d\xdc\x00\x00\x00\x00', + b'\x00\x00d\xdc\x1f@ \x0e', + b'\x00\x00e\x02\x1f@ \x14', + b'\x00\x00e\x1c\x00\x00\x00\x00', + b'\x00\x00e\x1c\x1f@ \x14', + b'\x00\x00e+\x00\x00\x00\x00', + b'\x00\x00e+\x1f@ \x14', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xaa\x00Bu\x07', + b'\xaa\x01bt\x07', + b'\xaa\x01fr\x07', + b'\xaa!`u\x07', + b'\xaa!au\x07', + b'\xaa!av\x07', + b'\xaa!aw\x07', + b'\xaa!dq\x07', + b'\xaa!ds\x07', + b'\xaa!dt\x07', + b'\xaaafs\x07', + b'\xbe!as\x07', + b'\xbe!at\x07', + b'\xbeacr\x07', + b'\xc5!`r\x07', + b'\xc5!`s\x07', + b'\xc5!ap\x07', + b'\xc5!ar\x07', + b'\xc5!as\x07', + b'\xc5!dr\x07', + b'\xc5!ds\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xe3\xd0\x081\x00', + b'\xe3\xd5\x161\x00', + b'\xe3\xd5F1\x00', + b'\xe3\xe5F1\x00', + b'\xe3\xf5\x06\x00\x00', + b'\xe3\xf5\x07\x00\x00', + b'\xe3\xf5C\x00\x00', + b'\xe3\xf5F\x00\x00', + b'\xe3\xf5G\x00\x00', + b'\xe4\xe5\x021\x00', + b'\xe4\xe5\x061\x00', + b'\xe4\xf5\x02\x00\x00', + b'\xe4\xf5\x07\x00\x00', + b'\xe5\xf5\x04\x00\x00', + b'\xe5\xf5$\x00\x00', + b'\xe5\xf5B\x00\x00', + ], + }, + CAR.SUBARU_IMPREZA_2020: { + (Ecu.abs, 0x7b0, None): [ + b'\xa2 \x193\x00', + b'\xa2 \x194\x00', + b'\xa2 `\x00', + b'\xa2 !3\x00', + b'\xa2 !6\x00', + b'\xa2 !`\x00', + b'\xa2 !i\x00', + ], + (Ecu.eps, 0x746, None): [ + b'\n\xc0\x04\x00', + b'\n\xc0\x04\x01', + b'\x9a\xc0\x00\x00', + b'\x9a\xc0\x04\x00', + b'\x9a\xc0\n\x01', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00eb\x1f@ "', + b'\x00\x00eq\x00\x00\x00\x00', + b'\x00\x00eq\x1f@ "', + b'\x00\x00e\x8f\x00\x00\x00\x00', + b'\x00\x00e\x8f\x1f@ )', + b'\x00\x00e\x92\x00\x00\x00\x00', + b'\x00\x00e\xa4\x00\x00\x00\x00', + b'\x00\x00e\xa4\x1f@ (', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xca!`0\x07', + b'\xca!`p\x07', + b'\xca!`t\x07', + b'\xca!a0\x07', + b'\xca!ap\x07', + b'\xca!f@\x07', + b'\xca!fp\x07', + b'\xcaacp\x07', + b'\xcc!`p\x07', + b'\xcc!fp\x07', + b'\xcc"f0\x07', + b'\xe6!`@\x07', + b'\xe6!fp\x07', + b'\xe6"f0\x07', + b'\xe6"fp\x07', + b'\xf3"f@\x07', + b'\xf3"fp\x07', + b'\xf3"fr\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xe6\x15\x042\x00', + b'\xe6\xf5\x04\x00\x00', + b'\xe6\xf5$\x00\x00', + b'\xe6\xf5D0\x00', + b'\xe7\xf5\x04\x00\x00', + b'\xe7\xf5D0\x00', + b'\xe7\xf6B0\x00', + b'\xe9\xf5"\x00\x00', + b'\xe9\xf5B0\x00', + b'\xe9\xf6B0\x00', + b'\xe9\xf6F0\x00', + ], + }, + CAR.SUBARU_CROSSTREK_HYBRID: { + (Ecu.abs, 0x7b0, None): [ + b'\xa2 \x19e\x01', + b'\xa2 !e\x01', + ], + (Ecu.eps, 0x746, None): [ + b'\n\xc2\x01\x00', + b'\x9a\xc2\x01\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00el\x1f@ #', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xd7!`@\x07', + b'\xd7!`p\x07', + b'\xf4!`0\x07', + ], + }, + CAR.SUBARU_FORESTER: { + (Ecu.abs, 0x7b0, None): [ + b'\xa3 \x18\x14\x00', + b'\xa3 \x18&\x00', + b'\xa3 \x19\x14\x00', + b'\xa3 \x19&\x00', + b'\xa3 \x19h\x00', + b'\xa3 \x14\x00', + b'\xa3 \x14\x01', + ], + (Ecu.eps, 0x746, None): [ + b'\x8d\xc0\x00\x00', + b'\x8d\xc0\x04\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00e!\x00\x00\x00\x00', + b'\x00\x00e!\x1f@ \x11', + b'\x00\x00e^\x00\x00\x00\x00', + b'\x00\x00e^\x1f@ !', + b'\x00\x00e`\x00\x00\x00\x00', + b'\x00\x00e`\x1f@ ', + b'\x00\x00e\x97\x00\x00\x00\x00', + b'\x00\x00e\x97\x1f@ 0', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xb6"`A\x07', + b'\xb6\xa2`A\x07', + b'\xcb"`@\x07', + b'\xcb"`p\x07', + b'\xcf"`0\x07', + b'\xcf"`p\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\x1a\xe6B1\x00', + b'\x1a\xe6F1\x00', + b'\x1a\xf6B0\x00', + b'\x1a\xf6B`\x00', + b'\x1a\xf6F`\x00', + b'\x1a\xf6b0\x00', + b'\x1a\xf6b`\x00', + b'\x1a\xf6f`\x00', + ], + }, + CAR.SUBARU_FORESTER_HYBRID: { + (Ecu.abs, 0x7b0, None): [ + b'\xa3 \x19T\x00', + ], + (Ecu.eps, 0x746, None): [ + b'\x8d\xc2\x00\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00eY\x1f@ !', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xd2\xa1`r\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\x1b\xa7@a\x00', + ], + }, + CAR.SUBARU_FORESTER_PREGLOBAL: { + (Ecu.abs, 0x7b0, None): [ + b'm\x97\x14@', + b'}\x97\x14@', + ], + (Ecu.eps, 0x746, None): [ + b'm\xc0\x10\x00', + b'}\xc0\x10\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00c\xe9\x00\x00\x00\x00', + b'\x00\x00c\xe9\x1f@ \x03', + b'\x00\x00d5\x1f@ \t', + b'\x00\x00d\xd3\x1f@ \t', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xa7"@0\x07', + b'\xa7"@p\x07', + b'\xa7)\xa0q\x07', + b'\xba"@@\x07', + b'\xba"@p\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\x1a\xf6F`\x00', + b'\xda\xf2`p\x00', + b'\xda\xf2`\x80\x00', + b'\xda\xfd\xe0\x80\x00', + b'\xdc\xf2@`\x00', + b'\xdc\xf2``\x00', + b'\xdc\xf2`\x80\x00', + b'\xdc\xf2`\x81\x00', + ], + }, + CAR.SUBARU_LEGACY_PREGLOBAL: { + (Ecu.abs, 0x7b0, None): [ + b'[\x97D\x00', + b'[\xba\xc4\x03', + b'k\x97D\x00', + b'k\x9aD\x00', + b'{\x97D\x00', + ], + (Ecu.eps, 0x746, None): [ + b'K\xb0\x00\x01', + b'[\xb0\x00\x01', + b'k\xb0\x00\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00c\x94\x1f@\x10\x08', + b'\x00\x00c\xb7\x1f@\x10\x16', + b'\x00\x00c\xec\x1f@ \x04', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xa0"@q\x07', + b'\xa0+@p\x07', + b'\xab*@r\x07', + b'\xab+@p\x07', + b'\xb4"@0\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xbd\xf2\x00`\x00', + b'\xbe\xf2\x00p\x00', + b'\xbe\xfb\xc0p\x00', + b'\xbf\xf2\x00\x80\x00', + b'\xbf\xfb\xc0\x80\x00', + ], + }, + CAR.SUBARU_OUTBACK_PREGLOBAL: { + (Ecu.abs, 0x7b0, None): [ + b'[\xba\xac\x03', + b'[\xf7\xac\x00', + b'[\xf7\xac\x03', + b'[\xf7\xbc\x03', + b'k\x97\xac\x00', + b'k\x9a\xac\x00', + b'{\x97\xac\x00', + b'{\x9a\xac\x00', + ], + (Ecu.eps, 0x746, None): [ + b'K\xb0\x00\x00', + b'K\xb0\x00\x02', + b'[\xb0\x00\x00', + b'k\xb0\x00\x00', + b'{\xb0\x00\x01', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00c\x90\x1f@\x10\x0e', + b'\x00\x00c\x94\x00\x00\x00\x00', + b'\x00\x00c\x94\x1f@\x10\x08', + b'\x00\x00c\xb7\x1f@\x10\x16', + b'\x00\x00c\xd1\x1f@\x10\x17', + b'\x00\x00c\xec\x1f@ \x04', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xa0"@\x80\x07', + b'\xa0*@q\x07', + b'\xa0*@u\x07', + b'\xa0+@@\x07', + b'\xa0bAq\x07', + b'\xab"@@\x07', + b'\xab"@s\x07', + b'\xab*@@\x07', + b'\xab+@@\x07', + b'\xb4"@0\x07', + b'\xb4"@p\x07', + b'\xb4"@r\x07', + b'\xb4+@p\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xbd\xf2@`\x00', + b'\xbd\xf2@\x81\x00', + b'\xbd\xfb\xe0\x80\x00', + b'\xbe\xf2@p\x00', + b'\xbe\xf2@\x80\x00', + b'\xbe\xfb\xe0p\x00', + b'\xbf\xe2@\x80\x00', + b'\xbf\xf2@\x80\x00', + b'\xbf\xfb\xe0b\x00', + ], + }, + CAR.SUBARU_OUTBACK_PREGLOBAL_2018: { + (Ecu.abs, 0x7b0, None): [ + b'\x8b\x97\xac\x00', + b'\x8b\x97\xbc\x00', + b'\x8b\x99\xac\x00', + b'\x8b\x9a\xac\x00', + b'\x9b\x97\xac\x00', + b'\x9b\x97\xbe\x10', + b'\x9b\x9a\xac\x00', + ], + (Ecu.eps, 0x746, None): [ + b'{\xb0\x00\x00', + b'{\xb0\x00\x01', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00df\x1f@ \n', + b'\x00\x00d\x95\x00\x00\x00\x00', + b'\x00\x00d\x95\x1f@ \x0f', + b'\x00\x00d\xfe\x00\x00\x00\x00', + b'\x00\x00d\xfe\x1f@ \x15', + b'\x00\x00e\x19\x1f@ \x15', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xb5"@P\x07', + b'\xb5"@p\x07', + b'\xb5+@@\x07', + b'\xb5b@1\x07', + b'\xb5q\xe0@\x07', + b'\xc4"@0\x07', + b'\xc4+@0\x07', + b'\xc4b@p\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xbb\xf2@`\x00', + b'\xbb\xfb\xe0`\x00', + b'\xbc\xaf\xe0`\x00', + b'\xbc\xe2@\x80\x00', + b'\xbc\xf2@\x80\x00', + b'\xbc\xf2@\x81\x00', + b'\xbc\xfb\xe0`\x00', + b'\xbc\xfb\xe0\x80\x00', + ], + }, + CAR.SUBARU_OUTBACK: { + (Ecu.abs, 0x7b0, None): [ + b'\xa1 \x06\x00', + b'\xa1 \x06\x01', + b'\xa1 \x06\x02', + b'\xa1 \x06\x03', + b'\xa1 \x07\x00', + b'\xa1 \x07\x01', + b'\xa1 \x07\x02', + b'\xa1 \x07\x03', + b'\xa1 \x08\x00', + b'\xa1 \x08\x01', + b'\xa1 \x08\x02', + b'\xa1 "\t\x00', + b'\xa1 "\t\x01', + ], + (Ecu.eps, 0x746, None): [ + b'\x1b\xc0\x10\x00', + b'\x9b\xc0\x10\x00', + b'\x9b\xc0\x10\x02', + b'\x9b\xc0 \x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x00\x00eJ\x00\x00\x00\x00\x00\x00', + b'\x00\x00eJ\x00\x1f@ \x19\x00', + b'\x00\x00e\x80\x00\x1f@ \x19\x00', + b'\x00\x00e\x9a\x00\x00\x00\x00\x00\x00', + b'\x00\x00e\x9a\x00\x1f@ 1\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xbc"`@\x07', + b'\xbc"`q\x07', + b'\xbc,\xa0q\x07', + b'\xbc,\xa0u\x07', + b'\xde"`0\x07', + b'\xde,\xa0@\x07', + b'\xe2"`0\x07', + b'\xe2"`p\x07', + b'\xe2"`q\x07', + b'\xe2"`t\x07', + b'\xe2,\xa0p\x07', + b'\xe3,\xa0@\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xa5\xf6D@\x00', + b'\xa5\xfe\xf6@\x00', + b'\xa5\xfe\xf7@\x00', + b'\xa5\xfe\xf8@\x00', + b'\xa7\x8e\xf40\x00', + b'\xa7\xf6D@\x00', + b'\xa7\xfe\xf4@\x00', + b'\xa7\xfe\xf6@\x00', + ], + }, + CAR.SUBARU_FORESTER_2022: { + (Ecu.abs, 0x7b0, None): [ + b'\xa3 !v\x00', + b'\xa3 !x\x00', + b'\xa3 "v\x00', + b'\xa3 "x\x00', + ], + (Ecu.eps, 0x746, None): [ + b'-\xc0\x040', + b'-\xc0%0', + b'=\xc0%\x02', + b'=\xc04\x02', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\x04!\x01\x1eD\x07!\x00\x04,', + b'\x04!\x08\x01.\x07!\x08\x022', + b'\r!\x08\x017\x00\x00\x00\x00\x00', + b'\r!\x08\x017\n!\x08\x003', + ], + (Ecu.engine, 0x7e0, None): [ + b'\xd5"`0\x07', + b'\xd5"a0\x07', + b'\xf1"`q\x07', + b'\xf1"aq\x07', + b'\xfa"`p\x07', + b'\xfa"ap\x07', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\x1d\x86B0\x00', + b'\x1d\xf6B0\x00', + b'\x1e\x86B0\x00', + b'\x1e\x86F0\x00', + b'\x1e\xf6D0\x00', + b'\x1f\xf6B1\x00', + ], + }, + CAR.SUBARU_OUTBACK_2023: { + (Ecu.abs, 0x7b0, None): [ + b'\xa1 #\x14\x00', + b'\xa1 #\x17\x00', + ], + (Ecu.eps, 0x746, None): [ + b'+\xc0\x10\x11\x00', + b'+\xc0\x12\x11\x00', + ], + (Ecu.fwdCamera, 0x787, None): [ + b'\t!\x08\x046\x05!\x08\x01/', + ], + (Ecu.engine, 0x7a2, None): [ + b'\xed,\xa0q\x07', + b'\xed,\xa2q\x07', + ], + (Ecu.transmission, 0x7a3, None): [ + b'\xa8\x8e\xf41\x00', + b'\xa8\xfe\xf41\x00', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/subaru/interface.py b/opendbc_repo/opendbc/car/subaru/interface.py new file mode 100644 index 0000000000..b11a987d55 --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/interface.py @@ -0,0 +1,111 @@ +from opendbc.car import get_safety_config, structs, uds +from opendbc.car.disable_ecu import disable_ecu +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.subaru.carcontroller import CarController +from opendbc.car.subaru.carstate import CarState +from opendbc.car.subaru.values import CAR, GLOBAL_ES_ADDR, SubaruFlags, SubaruSafetyFlags + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "subaru" + ret.radarUnavailable = True + # for HYBRID CARS to be upstreamed, we need: + # - replacement for ES_Distance so we can cancel the cruise control + # - to find the Cruise_Activated bit from the car + # - proper panda safety setup (use the correct cruise_activated bit, throttle from Throttle_Hybrid, etc) + ret.dashcamOnly = bool(ret.flags & (SubaruFlags.PREGLOBAL | SubaruFlags.LKAS_ANGLE | SubaruFlags.HYBRID)) + ret.autoResumeSng = False + + # Detect infotainment message sent from the camera + if not (ret.flags & SubaruFlags.PREGLOBAL) and 0x323 in fingerprint[2]: + ret.flags |= SubaruFlags.SEND_INFOTAINMENT.value + + if ret.flags & SubaruFlags.PREGLOBAL: + ret.enableBsm = 0x25c in fingerprint[0] + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.subaruPreglobal)] + else: + ret.enableBsm = 0x228 in fingerprint[0] + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.subaru)] + if ret.flags & SubaruFlags.GLOBAL_GEN2: + ret.safetyConfigs[0].safetyParam |= SubaruSafetyFlags.GEN2.value + + ret.steerLimitTimer = 0.4 + ret.steerActuatorDelay = 0.1 + + if ret.flags & SubaruFlags.LKAS_ANGLE: + ret.steerControlType = structs.CarParams.SteerControlType.angle + else: + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + if candidate in (CAR.SUBARU_ASCENT, CAR.SUBARU_ASCENT_2023): + ret.steerActuatorDelay = 0.3 # end-to-end angle controller + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kf = 0.00003 + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 20.], [0., 20.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.0025, 0.1], [0.00025, 0.01]] + + elif candidate == CAR.SUBARU_IMPREZA: + ret.steerActuatorDelay = 0.4 # end-to-end angle controller + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kf = 0.00005 + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 20.], [0., 20.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2, 0.3], [0.02, 0.03]] + + elif candidate == CAR.SUBARU_IMPREZA_2020: + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kf = 0.00005 + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 14., 23.], [0., 14., 23.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.045, 0.042, 0.20], [0.04, 0.035, 0.045]] + + elif candidate == CAR.SUBARU_CROSSTREK_HYBRID: + ret.steerActuatorDelay = 0.1 + + elif candidate in (CAR.SUBARU_FORESTER, CAR.SUBARU_FORESTER_2022, CAR.SUBARU_FORESTER_HYBRID): + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kf = 0.000038 + ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0., 14., 23.], [0., 14., 23.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.01, 0.065, 0.2], [0.001, 0.015, 0.025]] + + elif candidate in (CAR.SUBARU_OUTBACK, CAR.SUBARU_LEGACY, CAR.SUBARU_OUTBACK_2023): + ret.steerActuatorDelay = 0.1 + + elif candidate in (CAR.SUBARU_FORESTER_PREGLOBAL, CAR.SUBARU_OUTBACK_PREGLOBAL_2018): + # Outback 2018-2019 and Forester have reversed driver torque signal + ret.safetyConfigs[0].safetyParam = SubaruSafetyFlags.PREGLOBAL_REVERSED_DRIVER_TORQUE.value + + elif candidate == CAR.SUBARU_LEGACY_PREGLOBAL: + ret.steerActuatorDelay = 0.15 + + elif candidate == CAR.SUBARU_OUTBACK_PREGLOBAL: + pass + else: + raise ValueError(f"unknown car: {candidate}") + + ret.alphaLongitudinalAvailable = not (ret.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.PREGLOBAL | + SubaruFlags.LKAS_ANGLE | SubaruFlags.HYBRID)) + ret.openpilotLongitudinalControl = alpha_long and ret.alphaLongitudinalAvailable + + if ret.flags & SubaruFlags.GLOBAL_GEN2 and ret.openpilotLongitudinalControl: + ret.flags |= SubaruFlags.DISABLE_EYESIGHT.value + + if ret.openpilotLongitudinalControl: + ret.safetyConfigs[0].safetyParam |= SubaruSafetyFlags.LONG.value + + return ret + + @staticmethod + def init(CP, can_recv, can_send, communication_control=None): + if CP.flags & SubaruFlags.DISABLE_EYESIGHT: + if communication_control is None: + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, uds.CONTROL_TYPE.DISABLE_RX_DISABLE_TX, uds.MESSAGE_TYPE.NORMAL]) + disable_ecu(can_recv, can_send, bus=2, addr=GLOBAL_ES_ADDR, com_cont_req=communication_control) + + @staticmethod + def deinit(CP, can_recv, can_send): + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX, uds.MESSAGE_TYPE.NORMAL]) + CarInterface.init(CP, can_recv, can_send, communication_control) diff --git a/opendbc_repo/opendbc/car/subaru/subarucan.py b/opendbc_repo/opendbc/car/subaru/subarucan.py new file mode 100644 index 0000000000..64cab421ce --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/subarucan.py @@ -0,0 +1,336 @@ +from opendbc.car import structs +from opendbc.car.subaru.values import CanBus + +VisualAlert = structs.CarControl.HUDControl.VisualAlert + + +def create_steering_control(packer, apply_torque, steer_req): + values = { + "LKAS_Output": apply_torque, + "LKAS_Request": steer_req, + "SET_1": 1 + } + return packer.make_can_msg("ES_LKAS", 0, values) + + +def create_steering_control_angle(packer, apply_torque, steer_req): + values = { + "LKAS_Output": apply_torque, + "LKAS_Request": steer_req, + "SET_3": 3 + } + return packer.make_can_msg("ES_LKAS_ANGLE", 0, values) + + +def create_steering_status(packer): + return packer.make_can_msg("ES_LKAS_State", 0, {}) + + +def create_es_distance(packer, frame, es_distance_msg, bus, pcm_cancel_cmd, long_enabled = False, brake_cmd = False, cruise_throttle = 0): + values = {s: es_distance_msg[s] for s in [ + "CHECKSUM", + "Signal1", + "Cruise_Fault", + "Cruise_Throttle", + "Signal2", + "Car_Follow", + "Low_Speed_Follow", + "Cruise_Soft_Disable", + "Signal7", + "Cruise_Brake_Active", + "Distance_Swap", + "Cruise_EPB", + "Signal4", + "Close_Distance", + "Signal5", + "Cruise_Cancel", + "Cruise_Set", + "Cruise_Resume", + "Signal6", + ]} + + values["COUNTER"] = frame % 0x10 + + if long_enabled: + values["Cruise_Throttle"] = cruise_throttle + + # Do not disable openpilot on Eyesight Soft Disable, if openpilot is controlling long + values["Cruise_Soft_Disable"] = 0 + values["Cruise_Fault"] = 0 + + values["Cruise_Brake_Active"] = brake_cmd + + if pcm_cancel_cmd: + values["Cruise_Cancel"] = 1 + values["Cruise_Throttle"] = 1818 # inactive throttle + + return packer.make_can_msg("ES_Distance", bus, values) + + +def create_es_lkas_state(packer, frame, es_lkas_state_msg, enabled, visual_alert, left_line, right_line, left_lane_depart, right_lane_depart): + values = {s: es_lkas_state_msg[s] for s in [ + "CHECKSUM", + "LKAS_Alert_Msg", + "Signal1", + "LKAS_ACTIVE", + "LKAS_Dash_State", + "Signal2", + "Backward_Speed_Limit_Menu", + "LKAS_Left_Line_Enable", + "LKAS_Left_Line_Light_Blink", + "LKAS_Right_Line_Enable", + "LKAS_Right_Line_Light_Blink", + "LKAS_Left_Line_Visible", + "LKAS_Right_Line_Visible", + "LKAS_Alert", + "Signal3", + ]} + + values["COUNTER"] = frame % 0x10 + + # Filter the stock LKAS "Keep hands on wheel" alert + if values["LKAS_Alert_Msg"] == 1: + values["LKAS_Alert_Msg"] = 0 + + # Filter the stock LKAS sending an audible alert when it turns off LKAS + if values["LKAS_Alert"] == 27: + values["LKAS_Alert"] = 0 + + # Filter the stock LKAS sending an audible alert when "Keep hands on wheel" alert is active (2020+ models) + if values["LKAS_Alert"] == 28 and values["LKAS_Alert_Msg"] == 7: + values["LKAS_Alert"] = 0 + + # Filter the stock LKAS sending an audible alert when "Keep hands on wheel OFF" alert is active (2020+ models) + if values["LKAS_Alert"] == 30: + values["LKAS_Alert"] = 0 + + # Filter the stock LKAS sending "Keep hands on wheel OFF" alert (2020+ models) + if values["LKAS_Alert_Msg"] == 7: + values["LKAS_Alert_Msg"] = 0 + + # Show Keep hands on wheel alert for openpilot steerRequired alert + if visual_alert == VisualAlert.steerRequired: + values["LKAS_Alert_Msg"] = 1 + + # Ensure we don't overwrite potentially more important alerts from stock (e.g. FCW) + if visual_alert == VisualAlert.ldw and values["LKAS_Alert"] == 0: + if left_lane_depart: + values["LKAS_Alert"] = 12 # Left lane departure dash alert + elif right_lane_depart: + values["LKAS_Alert"] = 11 # Right lane departure dash alert + + if enabled: + values["LKAS_ACTIVE"] = 1 # Show LKAS lane lines + values["LKAS_Dash_State"] = 2 # Green enabled indicator + else: + values["LKAS_Dash_State"] = 0 # LKAS Not enabled + + values["LKAS_Left_Line_Visible"] = int(left_line) + values["LKAS_Right_Line_Visible"] = int(right_line) + + return packer.make_can_msg("ES_LKAS_State", CanBus.main, values) + + +def create_es_dashstatus(packer, frame, dashstatus_msg, enabled, long_enabled, long_active, lead_visible): + values = {s: dashstatus_msg[s] for s in [ + "CHECKSUM", + "PCB_Off", + "LDW_Off", + "Signal1", + "Cruise_State_Msg", + "LKAS_State_Msg", + "Signal2", + "Cruise_Soft_Disable", + "Cruise_Status_Msg", + "Signal3", + "Cruise_Distance", + "Signal4", + "Conventional_Cruise", + "Signal5", + "Cruise_Disengaged", + "Cruise_Activated", + "Signal6", + "Cruise_Set_Speed", + "Cruise_Fault", + "Cruise_On", + "Display_Own_Car", + "Brake_Lights", + "Car_Follow", + "Signal7", + "Far_Distance", + "Cruise_State", + ]} + + values["COUNTER"] = frame % 0x10 + + if long_enabled: + values["Cruise_State"] = 0 + values["Cruise_Activated"] = enabled + values["Cruise_Disengaged"] = 0 + values["Car_Follow"] = int(lead_visible) + + values["PCB_Off"] = 1 # AEB is not presevered, so show the PCB_Off on dash + values["LDW_Off"] = 0 + values["Cruise_Fault"] = 0 + + # Filter stock LKAS disabled and Keep hands on steering wheel OFF alerts + if values["LKAS_State_Msg"] in (2, 3): + values["LKAS_State_Msg"] = 0 + + return packer.make_can_msg("ES_DashStatus", CanBus.main, values) + + +def create_es_brake(packer, frame, es_brake_msg, long_enabled, long_active, brake_value): + values = {s: es_brake_msg[s] for s in [ + "CHECKSUM", + "Signal1", + "Brake_Pressure", + "AEB_Status", + "Cruise_Brake_Lights", + "Cruise_Brake_Fault", + "Cruise_Brake_Active", + "Cruise_Activated", + "Signal3", + ]} + + values["COUNTER"] = frame % 0x10 + + if long_enabled: + values["Cruise_Brake_Fault"] = 0 + values["Cruise_Activated"] = long_active + + values["Brake_Pressure"] = brake_value + + values["Cruise_Brake_Active"] = brake_value > 0 + values["Cruise_Brake_Lights"] = brake_value >= 70 + + return packer.make_can_msg("ES_Brake", CanBus.main, values) + + +def create_es_status(packer, frame, es_status_msg, long_enabled, long_active, cruise_rpm): + values = {s: es_status_msg[s] for s in [ + "CHECKSUM", + "Signal1", + "Cruise_Fault", + "Cruise_RPM", + "Cruise_Activated", + "Brake_Lights", + "Cruise_Hold", + "Signal3", + ]} + + values["COUNTER"] = frame % 0x10 + + if long_enabled: + values["Cruise_RPM"] = cruise_rpm + values["Cruise_Fault"] = 0 + + values["Cruise_Activated"] = long_active + + return packer.make_can_msg("ES_Status", CanBus.main, values) + + +def create_es_infotainment(packer, frame, es_infotainment_msg, visual_alert): + # Filter stock LKAS disabled and Keep hands on steering wheel OFF alerts + values = {s: es_infotainment_msg[s] for s in [ + "CHECKSUM", + "LKAS_State_Infotainment", + "LKAS_Blue_Lines", + "Signal1", + "Signal2", + ]} + + values["COUNTER"] = frame % 0x10 + + if values["LKAS_State_Infotainment"] in (3, 4): + values["LKAS_State_Infotainment"] = 0 + + # Show Keep hands on wheel alert for openpilot steerRequired alert + if visual_alert == VisualAlert.steerRequired: + values["LKAS_State_Infotainment"] = 3 + + # Show Obstacle Detected for fcw + if visual_alert == VisualAlert.fcw: + values["LKAS_State_Infotainment"] = 2 + + return packer.make_can_msg("ES_Infotainment", CanBus.main, values) + + +def create_es_highbeamassist(packer): + values = { + "HBA_Available": False, + } + + return packer.make_can_msg("ES_HighBeamAssist", CanBus.main, values) + + +def create_es_static_1(packer): + values = { + "SET_3": 3, + } + + return packer.make_can_msg("ES_STATIC_1", CanBus.main, values) + + +def create_es_static_2(packer): + values = { + "SET_3": 3, + } + + return packer.make_can_msg("ES_STATIC_2", CanBus.main, values) + + +# *** Subaru Pre-global *** + +def subaru_preglobal_checksum(packer, values, addr, checksum_byte=7): + dat = packer.make_can_msg(addr, 0, values)[1] + return (sum(dat[:checksum_byte]) + sum(dat[checksum_byte+1:])) % 256 + + +def create_preglobal_steering_control(packer, frame, apply_torque, steer_req): + values = { + "COUNTER": frame % 0x08, + "LKAS_Command": apply_torque, + "LKAS_Active": steer_req, + } + values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_LKAS") + + return packer.make_can_msg("ES_LKAS", CanBus.main, values) + + +def create_preglobal_es_distance(packer, cruise_button, es_distance_msg): + values = {s: es_distance_msg[s] for s in [ + "Cruise_Throttle", + "Signal1", + "Car_Follow", + "Signal2", + "Cruise_Brake_Active", + "Distance_Swap", + "Standstill", + "Signal3", + "Close_Distance", + "Signal4", + "Standstill_2", + "Cruise_Fault", + "Signal5", + "COUNTER", + "Signal6", + "Cruise_Button", + "Signal7", + ]} + + values["Cruise_Button"] = cruise_button + values["Checksum"] = subaru_preglobal_checksum(packer, values, "ES_Distance") + + return packer.make_can_msg("ES_Distance", CanBus.main, values) + + +def subaru_checksum(address: int, sig, d: bytearray) -> int: + s = 0 + addr = address + while addr: + s += addr & 0xFF + addr >>= 8 + for i in range(1, len(d)): + s += d[i] + return s & 0xFF diff --git a/opendbc_repo/opendbc/car/subaru/tests/__init__.py b/opendbc_repo/opendbc/car/subaru/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/subaru/tests/test_subaru.py b/opendbc_repo/opendbc/car/subaru/tests/test_subaru.py new file mode 100644 index 0000000000..7f3d9bb3c5 --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/tests/test_subaru.py @@ -0,0 +1,10 @@ +from opendbc.car.subaru.fingerprints import FW_VERSIONS + + +class TestSubaruFingerprint: + def test_fw_version_format(self): + for platform, fws_per_ecu in FW_VERSIONS.items(): + for (ecu, _, _), fws in fws_per_ecu.items(): + fw_size = len(fws[0]) + for fw in fws: + assert len(fw) == fw_size, f"{platform} {ecu}: {len(fw)} {fw_size}" diff --git a/opendbc_repo/opendbc/car/subaru/values.py b/opendbc_repo/opendbc/car/subaru/values.py new file mode 100644 index 0000000000..a702d39430 --- /dev/null +++ b/opendbc_repo/opendbc/car/subaru/values.py @@ -0,0 +1,280 @@ +from dataclasses import dataclass, field +from enum import Enum, IntFlag + +from opendbc.car import Bus, CarSpecs, DbcDict, PlatformConfig, Platforms, uds +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 + +Ecu = CarParams.Ecu + + +class CarControllerParams: + def __init__(self, CP): + self.STEER_STEP = 2 # how often we update the steer cmd + self.STEER_DELTA_UP = 50 # torque increase per refresh, 0.8s to max + self.STEER_DELTA_DOWN = 70 # torque decrease per refresh + self.STEER_DRIVER_ALLOWANCE = 60 # allowed driver torque before start limiting + self.STEER_DRIVER_MULTIPLIER = 50 # weight driver torque heavily + self.STEER_DRIVER_FACTOR = 1 # from dbc + + if CP.flags & SubaruFlags.GLOBAL_GEN2: + # TODO: lower rate limits, this reaches min/max in 0.5s which negatively affects tuning + self.STEER_MAX = 1000 + self.STEER_DELTA_UP = 40 + self.STEER_DELTA_DOWN = 40 + elif CP.carFingerprint == CAR.SUBARU_IMPREZA_2020: + self.STEER_DELTA_UP = 35 + self.STEER_MAX = 1439 + else: + self.STEER_MAX = 2047 + + THROTTLE_MIN = 808 + THROTTLE_MAX = 3400 + + THROTTLE_INACTIVE = 1818 # corresponds to zero acceleration + THROTTLE_ENGINE_BRAKE = 808 # while braking, eyesight sets throttle to this, probably for engine braking + + BRAKE_MIN = 0 + BRAKE_MAX = 600 # about -3.5m/s2 from testing + + RPM_MIN = 0 + RPM_MAX = 3600 + + RPM_INACTIVE = 600 # a good base rpm for zero acceleration + + THROTTLE_LOOKUP_BP = [0, 2] + THROTTLE_LOOKUP_V = [THROTTLE_INACTIVE, THROTTLE_MAX] + + RPM_LOOKUP_BP = [0, 2] + RPM_LOOKUP_V = [RPM_INACTIVE, RPM_MAX] + + BRAKE_LOOKUP_BP = [-3.5, 0] + BRAKE_LOOKUP_V = [BRAKE_MAX, BRAKE_MIN] + + +class SubaruSafetyFlags(IntFlag): + GEN2 = 1 + LONG = 2 + PREGLOBAL_REVERSED_DRIVER_TORQUE = 4 + + +class SubaruFlags(IntFlag): + # Detected flags + SEND_INFOTAINMENT = 1 + DISABLE_EYESIGHT = 2 + + # Static flags + GLOBAL_GEN2 = 4 + + # Cars that temporarily fault when steering angle rate is greater than some threshold. + # Appears to be all torque-based cars produced around 2019 - present + STEER_RATE_LIMITED = 8 + PREGLOBAL = 16 + HYBRID = 32 + LKAS_ANGLE = 64 + + +GLOBAL_ES_ADDR = 0x787 +GEN2_ES_BUTTONS_DID = b'\x11\x30' + + +class CanBus: + main = 0 + alt = 1 + camera = 2 + + +class Footnote(Enum): + GLOBAL = CarFootnote( + "In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance.", + Column.PACKAGE) + EXP_LONG = CarFootnote( + "Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB.", + Column.LONGITUDINAL) + + +@dataclass +class SubaruCarDocs(CarDocs): + package: str = "EyeSight Driver Assistance" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.subaru_a])) + footnotes: list[Enum] = field(default_factory=lambda: [Footnote.GLOBAL]) + + def init_make(self, CP: CarParams): + if CP.alphaLongitudinalAvailable: + self.footnotes.append(Footnote.EXP_LONG) + + +@dataclass +class SubaruPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'subaru_global_2017_generated'}) + + def init(self): + if self.flags & SubaruFlags.HYBRID: + self.dbc_dict = {Bus.pt: 'subaru_global_2020_hybrid_generated'} + + +@dataclass +class SubaruGen2PlatformConfig(SubaruPlatformConfig): + def init(self): + super().init() + self.flags |= SubaruFlags.GLOBAL_GEN2 + if not (self.flags & SubaruFlags.LKAS_ANGLE): + self.flags |= SubaruFlags.STEER_RATE_LIMITED + + +class CAR(Platforms): + # Global platform + SUBARU_ASCENT = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Ascent 2019-21", "All")], + CarSpecs(mass=2031, wheelbase=2.89, steerRatio=13.5), + ) + SUBARU_OUTBACK = SubaruGen2PlatformConfig( + [SubaruCarDocs("Subaru Outback 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b]))], + CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17), + ) + SUBARU_LEGACY = SubaruGen2PlatformConfig( + [SubaruCarDocs("Subaru Legacy 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b]))], + SUBARU_OUTBACK.specs, + ) + SUBARU_IMPREZA = SubaruPlatformConfig( + [ + SubaruCarDocs("Subaru Impreza 2017-19"), + SubaruCarDocs("Subaru Crosstrek 2018-19", video="https://youtu.be/Agww7oE1k-s?t=26"), + SubaruCarDocs("Subaru XV 2018-19", video="https://youtu.be/Agww7oE1k-s?t=26"), + ], + CarSpecs(mass=1568, wheelbase=2.67, steerRatio=15), + ) + SUBARU_IMPREZA_2020 = SubaruPlatformConfig( + [ + SubaruCarDocs("Subaru Impreza 2020-22"), + SubaruCarDocs("Subaru Crosstrek 2020-23"), + SubaruCarDocs("Subaru XV 2020-21"), + ], + CarSpecs(mass=1480, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.STEER_RATE_LIMITED, + ) + # TODO: is there an XV and Impreza too? + SUBARU_CROSSTREK_HYBRID = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Crosstrek Hybrid 2020", car_parts=CarParts.common([CarHarness.subaru_b]))], + CarSpecs(mass=1668, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.HYBRID, + ) + SUBARU_FORESTER = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Forester 2019-21", "All")], + CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.STEER_RATE_LIMITED, + ) + SUBARU_FORESTER_HYBRID = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Forester Hybrid 2020")], + SUBARU_FORESTER.specs, + flags=SubaruFlags.HYBRID, + ) + # Pre-global + SUBARU_FORESTER_PREGLOBAL = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Forester 2017-18")], + CarSpecs(mass=1568, wheelbase=2.67, steerRatio=20), + {Bus.pt: 'subaru_forester_2017_generated'}, + flags=SubaruFlags.PREGLOBAL, + ) + SUBARU_LEGACY_PREGLOBAL = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Legacy 2015-18")], + CarSpecs(mass=1568, wheelbase=2.67, steerRatio=12.5), + {Bus.pt: 'subaru_outback_2015_generated'}, + flags=SubaruFlags.PREGLOBAL, + ) + SUBARU_OUTBACK_PREGLOBAL = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Outback 2015-17")], + SUBARU_FORESTER_PREGLOBAL.specs, + {Bus.pt: 'subaru_outback_2015_generated'}, + flags=SubaruFlags.PREGLOBAL, + ) + SUBARU_OUTBACK_PREGLOBAL_2018 = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Outback 2018-19")], + SUBARU_FORESTER_PREGLOBAL.specs, + {Bus.pt: 'subaru_outback_2019_generated'}, + flags=SubaruFlags.PREGLOBAL, + ) + # Angle LKAS + SUBARU_FORESTER_2022 = SubaruPlatformConfig( + [SubaruCarDocs("Subaru Forester 2022-24", "All", car_parts=CarParts.common([CarHarness.subaru_c]))], + SUBARU_FORESTER.specs, + flags=SubaruFlags.LKAS_ANGLE, + ) + SUBARU_OUTBACK_2023 = SubaruGen2PlatformConfig( + [SubaruCarDocs("Subaru Outback 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d]))], + SUBARU_OUTBACK.specs, + flags=SubaruFlags.LKAS_ANGLE, + ) + SUBARU_ASCENT_2023 = SubaruGen2PlatformConfig( + [SubaruCarDocs("Subaru Ascent 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d]))], + SUBARU_ASCENT.specs, + flags=SubaruFlags.LKAS_ANGLE, + ) + + +SUBARU_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION) +SUBARU_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION) + +# The EyeSight ECU takes 10s to respond to SUBARU_VERSION_REQUEST properly, +# log this alternate manufacturer-specific query +SUBARU_ALT_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(0xf100) +SUBARU_ALT_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ + p16(0xf100) + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + Request( + [StdQueries.TESTER_PRESENT_REQUEST, SUBARU_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, SUBARU_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.eps, Ecu.fwdCamera, Ecu.engine, Ecu.transmission], + logging=True, + ), + # Non-OBD requests + # Some Eyesight modules fail on TESTER_PRESENT_REQUEST + # TODO: check if this resolves the fingerprinting issue for the 2023 Ascent and other new Subaru cars + Request( + [SUBARU_VERSION_REQUEST], + [SUBARU_VERSION_RESPONSE], + whitelist_ecus=[Ecu.fwdCamera], + bus=0, + ), + Request( + [SUBARU_ALT_VERSION_REQUEST], + [SUBARU_ALT_VERSION_RESPONSE], + whitelist_ecus=[Ecu.fwdCamera], + bus=0, + logging=True, + ), + Request( + [StdQueries.DEFAULT_DIAGNOSTIC_REQUEST, StdQueries.TESTER_PRESENT_REQUEST, SUBARU_VERSION_REQUEST], + [StdQueries.DEFAULT_DIAGNOSTIC_RESPONSE, StdQueries.TESTER_PRESENT_RESPONSE, SUBARU_VERSION_RESPONSE], + whitelist_ecus=[Ecu.fwdCamera], + bus=0, + logging=True, + ), + Request( + [StdQueries.TESTER_PRESENT_REQUEST, SUBARU_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, SUBARU_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.eps, Ecu.fwdCamera, Ecu.engine, Ecu.transmission], + bus=0, + ), + # GEN2 powertrain bus query + Request( + [StdQueries.TESTER_PRESENT_REQUEST, SUBARU_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, SUBARU_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.eps, Ecu.fwdCamera, Ecu.engine, Ecu.transmission], + bus=1, + obd_multiplexing=False, + ), + ], + # We don't get the EPS from non-OBD queries on GEN2 cars. Note that we still attempt to match when it exists + non_essential_ecus={ + Ecu.eps: list(CAR.with_flags(SubaruFlags.GLOBAL_GEN2)), + } +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/tesla/__init__.py b/opendbc_repo/opendbc/car/tesla/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/tesla/carcontroller.py b/opendbc_repo/opendbc/car/tesla/carcontroller.py new file mode 100644 index 0000000000..986897f849 --- /dev/null +++ b/opendbc_repo/opendbc/car/tesla/carcontroller.py @@ -0,0 +1,66 @@ +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import Bus +from opendbc.car.lateral import apply_steer_angle_limits_vm +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.tesla.teslacan import TeslaCAN +from opendbc.car.tesla.values import CarControllerParams +from opendbc.car.vehicle_model import VehicleModel + + +def get_safety_CP(): + # We use the TESLA_MODEL_Y platform for lateral limiting to match safety + # A Model 3 at 40 m/s using the Model Y limits sees a <0.3% difference in max angle (from curvature factor) + from opendbc.car.tesla.interface import CarInterface + return CarInterface.get_non_essential_params("TESLA_MODEL_Y") + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.apply_angle_last = 0 + self.packer = CANPacker(dbc_names[Bus.party]) + self.tesla_can = TeslaCAN(self.packer) + + # Vehicle model used for lateral limiting + self.VM = VehicleModel(get_safety_CP()) + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + can_sends = [] + + # Tesla EPS enforces disabling steering on heavy lateral override force. + # When enabling in a tight curve, we wait until user reduces steering force to start steering. + # Canceling is done on rising edge and is handled generically with CC.cruiseControl.cancel + lat_active = CC.latActive and CS.hands_on_level < 3 + + if self.frame % 2 == 0: + # Angular rate limit based on speed + self.apply_angle_last = apply_steer_angle_limits_vm(actuators.steeringAngleDeg, self.apply_angle_last, CS.out.vEgoRaw, CS.out.steeringAngleDeg, + lat_active, CarControllerParams, self.VM) + + can_sends.append(self.tesla_can.create_steering_control(self.apply_angle_last, lat_active)) + + if self.frame % 10 == 0: + can_sends.append(self.tesla_can.create_steering_allowed()) + + # Longitudinal control + if self.CP.openpilotLongitudinalControl: + if self.frame % 4 == 0: + state = 13 if CC.cruiseControl.cancel else 4 # 4=ACC_ON, 13=ACC_CANCEL_GENERIC_SILENT + accel = float(np.clip(actuators.accel, CarControllerParams.ACCEL_MIN, CarControllerParams.ACCEL_MAX)) + cntr = (self.frame // 4) % 8 + can_sends.append(self.tesla_can.create_longitudinal_command(state, accel, cntr, CS.out.vEgo, CC.longActive)) + + else: + # Increment counter so cancel is prioritized even without openpilot longitudinal + if CC.cruiseControl.cancel: + cntr = (CS.das_control["DAS_controlCounter"] + 1) % 8 + can_sends.append(self.tesla_can.create_longitudinal_command(13, 0, cntr, CS.out.vEgo, False)) + + # TODO: HUD control + new_actuators = actuators.as_builder() + new_actuators.steeringAngleDeg = self.apply_angle_last + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/tesla/carstate.py b/opendbc_repo/opendbc/car/tesla/carstate.py new file mode 100644 index 0000000000..fa16116b3b --- /dev/null +++ b/opendbc_repo/opendbc/car/tesla/carstate.py @@ -0,0 +1,127 @@ +import copy +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarStateBase +from opendbc.car.tesla.values import DBC, CANBUS, GEAR_MAP, STEER_THRESHOLD, CAR + +ButtonType = structs.CarState.ButtonEvent.Type + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + self.can_define = CANDefine(DBC[CP.carFingerprint][Bus.party]) + self.shifter_values = self.can_define.dv["DI_systemStatus"]["DI_gear"] + + self.autopark = False + self.autopark_prev = False + self.cruise_enabled_prev = False + + self.hands_on_level = 0 + self.das_control = None + + def update_autopark_state(self, autopark_state: str, cruise_enabled: bool): + autopark_now = autopark_state in ("ACTIVE", "COMPLETE", "SELFPARK_STARTED") + if autopark_now and not self.autopark_prev and not self.cruise_enabled_prev: + self.autopark = True + if not autopark_now: + self.autopark = False + self.autopark_prev = autopark_now + self.cruise_enabled_prev = cruise_enabled + + def update(self, can_parsers) -> structs.CarState: + cp_party = can_parsers[Bus.party] + cp_ap_party = can_parsers[Bus.ap_party] + ret = structs.CarState() + + # Vehicle speed + ret.vEgoRaw = cp_party.vl["DI_speed"]["DI_vehicleSpeed"] * CV.KPH_TO_MS + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + + # Gas pedal + ret.gasPressed = cp_party.vl["DI_systemStatus"]["DI_accelPedalPos"] > 0 + + # Brake pedal + ret.brake = 0 + ret.brakePressed = cp_party.vl["IBST_status"]["IBST_driverBrakeApply"] == 2 + + # Steering wheel + epas_status = cp_party.vl["EPAS3S_sysStatus"] + self.hands_on_level = epas_status["EPAS3S_handsOnLevel"] + ret.steeringAngleDeg = -epas_status["EPAS3S_internalSAS"] + ret.steeringRateDeg = -cp_ap_party.vl["SCCM_steeringAngleSensor"]["SCCM_steeringAngleSpeed"] + ret.steeringTorque = -epas_status["EPAS3S_torsionBarTorque"] + + # stock handsOnLevel uses >0.5 for 0.25s, but is too slow + ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > STEER_THRESHOLD, 5) + + eac_status = self.can_define.dv["EPAS3S_sysStatus"]["EPAS3S_eacStatus"].get(int(epas_status["EPAS3S_eacStatus"]), None) + ret.steerFaultPermanent = eac_status == "EAC_FAULT" + ret.steerFaultTemporary = eac_status == "EAC_INHIBITED" + + # FSD disengages using union of handsOnLevel (slow overrides) and high angle rate faults (fast overrides, high speed) + eac_error_code = self.can_define.dv["EPAS3S_sysStatus"]["EPAS3S_eacErrorCode"].get(int(epas_status["EPAS3S_eacErrorCode"]), None) + ret.steeringDisengage = self.hands_on_level >= 3 or (eac_status == "EAC_INHIBITED" and + eac_error_code == "EAC_ERROR_HIGH_ANGLE_RATE_SAFETY") + + # Cruise state + cruise_state = self.can_define.dv["DI_state"]["DI_cruiseState"].get(int(cp_party.vl["DI_state"]["DI_cruiseState"]), None) + speed_units = self.can_define.dv["DI_state"]["DI_speedUnits"].get(int(cp_party.vl["DI_state"]["DI_speedUnits"]), None) + + autopark_state = self.can_define.dv["DI_state"]["DI_autoparkState"].get(int(cp_party.vl["DI_state"]["DI_autoparkState"]), None) + cruise_enabled = cruise_state in ("ENABLED", "STANDSTILL", "OVERRIDE", "PRE_FAULT", "PRE_CANCEL") + self.update_autopark_state(autopark_state, cruise_enabled) + + # Match panda safety cruise engaged logic + ret.cruiseState.enabled = cruise_enabled and not self.autopark + if speed_units == "KPH": + ret.cruiseState.speed = max(cp_party.vl["DI_state"]["DI_digitalSpeed"] * CV.KPH_TO_MS, 1e-3) + elif speed_units == "MPH": + ret.cruiseState.speed = max(cp_party.vl["DI_state"]["DI_digitalSpeed"] * CV.MPH_TO_MS, 1e-3) + ret.cruiseState.available = cruise_state == "STANDBY" or ret.cruiseState.enabled + ret.cruiseState.standstill = False # This needs to be false, since we can resume from stop without sending anything special + ret.standstill = cp_party.vl["ESP_B"]["ESP_vehicleStandstillSts"] == 1 + ret.accFaulted = cruise_state == "FAULT" + + # Gear + ret.gearShifter = GEAR_MAP[self.can_define.dv["DI_systemStatus"]["DI_gear"].get(int(cp_party.vl["DI_systemStatus"]["DI_gear"]), "DI_GEAR_INVALID")] + + # Doors + ret.doorOpen = cp_party.vl["UI_warning"]["anyDoorOpen"] == 1 + + # Blinkers + ret.leftBlinker = cp_party.vl["UI_warning"]["leftBlinkerBlinking"] in (1, 2) + ret.rightBlinker = cp_party.vl["UI_warning"]["rightBlinkerBlinking"] in (1, 2) + + # Seatbelt + ret.seatbeltUnlatched = cp_party.vl["UI_warning"]["buckleStatus"] != 1 + + # Blindspot + ret.leftBlindspot = cp_ap_party.vl["DAS_status"]["DAS_blindSpotRearLeft"] != 0 + ret.rightBlindspot = cp_ap_party.vl["DAS_status"]["DAS_blindSpotRearRight"] != 0 + + # AEB + ret.stockAeb = cp_ap_party.vl["DAS_control"]["DAS_aebEvent"] == 1 + + # LKAS + ret.stockLkas = cp_ap_party.vl["DAS_steeringControl"]["DAS_steeringControlType"] == 2 # LANE_KEEP_ASSIST + + # Stock Autosteer should be off (includes FSD) + if self.CP.carFingerprint in (CAR.TESLA_MODEL_3, CAR.TESLA_MODEL_Y): + ret.invalidLkasSetting = cp_ap_party.vl["DAS_settings"]["DAS_autosteerEnabled"] != 0 + else: + pass + # Buttons # ToDo: add Gap adjust button + + # Messages needed by carcontroller + self.das_control = copy.copy(cp_ap_party.vl["DAS_control"]) + + return ret + + @staticmethod + def get_can_parsers(CP): + return { + Bus.party: CANParser(DBC[CP.carFingerprint][Bus.party], [], CANBUS.party), + Bus.ap_party: CANParser(DBC[CP.carFingerprint][Bus.party], [], CANBUS.autopilot_party) + } diff --git a/opendbc_repo/opendbc/car/tesla/fingerprints.py b/opendbc_repo/opendbc/car/tesla/fingerprints.py new file mode 100644 index 0000000000..54705385a6 --- /dev/null +++ b/opendbc_repo/opendbc/car/tesla/fingerprints.py @@ -0,0 +1,47 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.tesla.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.TESLA_MODEL_3: { + (Ecu.eps, 0x730, None): [ + b'TeM3_E014p10_0.0.0 (16),E014.17.00', + b'TeM3_E014p10_0.0.0 (16),EL014.17.00', + b'TeM3_ES014p11_0.0.0 (25),ES014.19.0', + b'TeMYG4_DCS_Update_0.0.0 (13),E4014.28.1', + b'TeMYG4_DCS_Update_0.0.0 (9),E4014.26.0', + b'TeMYG4_Legacy3Y_0.0.0 (2),E4015.02.0', + b'TeMYG4_Legacy3Y_0.0.0 (5),E4015.03.2', + b'TeMYG4_Legacy3Y_0.0.0 (5),E4L015.03.2', + b'TeMYG4_Main_0.0.0 (59),E4H014.29.0', + b'TeMYG4_Main_0.0.0 (65),E4H015.01.0', + b'TeMYG4_Main_0.0.0 (67),E4H015.02.1', + b'TeMYG4_SingleECU_0.0.0 (33),E4S014.27', + ], + }, + CAR.TESLA_MODEL_Y: { + (Ecu.eps, 0x730, None): [ + b'TeM3_E014p10_0.0.0 (16),Y002.18.00', + b'TeM3_E014p10_0.0.0 (16),YP002.18.00', + b'TeM3_ES014p11_0.0.0 (16),YS002.17', + b'TeM3_ES014p11_0.0.0 (25),YS002.19.0', + b'TeMYG4_DCS_Update_0.0.0 (13),Y4002.27.1', + b'TeMYG4_DCS_Update_0.0.0 (13),Y4P002.27.1', + b'TeMYG4_DCS_Update_0.0.0 (9),Y4P002.25.0', + b'TeMYG4_Legacy3Y_0.0.0 (2),Y4003.02.0', + b'TeMYG4_Legacy3Y_0.0.0 (2),Y4P003.02.0', + b'TeMYG4_Legacy3Y_0.0.0 (5),Y4003.03.2', + b'TeMYG4_Legacy3Y_0.0.0 (5),Y4P003.03.2', + b'TeMYG4_SingleECU_0.0.0 (28),Y4S002.23.0', + b'TeMYG4_SingleECU_0.0.0 (33),Y4S002.26', + ], + }, + CAR.TESLA_MODEL_X: { + (Ecu.eps, 0x730, None): [ + b'TeM3_SP_XP002p2_0.0.0 (23),XPR003.6.0', + b'TeM3_SP_XP002p2_0.0.0 (36),XPR003.10.0', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/tesla/interface.py b/opendbc_repo/opendbc/car/tesla/interface.py new file mode 100644 index 0000000000..baf1593238 --- /dev/null +++ b/opendbc_repo/opendbc/car/tesla/interface.py @@ -0,0 +1,36 @@ +from opendbc.car import get_safety_config, structs +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.tesla.carcontroller import CarController +from opendbc.car.tesla.carstate import CarState +from opendbc.car.tesla.values import TeslaSafetyFlags, CAR + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "tesla" + + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.tesla)] + + ret.steerLimitTimer = 0.4 + ret.steerActuatorDelay = 0.1 + ret.steerAtStandstill = True + + ret.steerControlType = structs.CarParams.SteerControlType.angle + ret.radarUnavailable = True + + ret.alphaLongitudinalAvailable = True + if alpha_long: + ret.openpilotLongitudinalControl = True + ret.safetyConfigs[0].safetyParam |= TeslaSafetyFlags.LONG_CONTROL.value + + ret.vEgoStopping = 0.1 + ret.vEgoStarting = 0.1 + ret.stoppingDecelRate = 0.3 + + ret.dashcamOnly = candidate in (CAR.TESLA_MODEL_X) # dashcam only, pending find invalidLkasSetting signal + + return ret diff --git a/opendbc_repo/opendbc/car/tesla/teslacan.py b/opendbc_repo/opendbc/car/tesla/teslacan.py new file mode 100644 index 0000000000..4bfc67a4e3 --- /dev/null +++ b/opendbc_repo/opendbc/car/tesla/teslacan.py @@ -0,0 +1,52 @@ +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.tesla.values import CANBUS, CarControllerParams + + +class TeslaCAN: + def __init__(self, packer): + self.packer = packer + + def create_steering_control(self, angle, enabled): + values = { + "DAS_steeringAngleRequest": -angle, + "DAS_steeringHapticRequest": 0, + "DAS_steeringControlType": 1 if enabled else 0, + } + + return self.packer.make_can_msg("DAS_steeringControl", CANBUS.party, values) + + def create_longitudinal_command(self, acc_state, accel, counter, v_ego, active): + from opendbc.car.interfaces import V_CRUISE_MAX + + set_speed = max(v_ego * CV.MS_TO_KPH, 0) + if active: + # TODO: this causes jerking after gas override when above set speed + set_speed = 0 if accel < 0 else V_CRUISE_MAX + + values = { + "DAS_setSpeed": set_speed, + "DAS_accState": acc_state, + "DAS_aebEvent": 0, + "DAS_jerkMin": CarControllerParams.JERK_LIMIT_MIN, + "DAS_jerkMax": CarControllerParams.JERK_LIMIT_MAX, + "DAS_accelMin": accel, + "DAS_accelMax": max(accel, 0), + "DAS_controlCounter": counter, + } + return self.packer.make_can_msg("DAS_control", CANBUS.party, values) + + def create_steering_allowed(self): + values = { + "APS_eacAllow": 1, + } + + return self.packer.make_can_msg("APS_eacMonitor", CANBUS.party, values) + + +def tesla_checksum(address: int, sig, d: bytearray) -> int: + checksum = (address & 0xFF) + ((address >> 8) & 0xFF) + checksum_byte = sig.start_bit // 8 + for i in range(len(d)): + if i != checksum_byte: + checksum += d[i] + return checksum & 0xFF diff --git a/opendbc_repo/opendbc/car/tesla/values.py b/opendbc_repo/opendbc/car/tesla/values.py new file mode 100644 index 0000000000..6fedfaac02 --- /dev/null +++ b/opendbc_repo/opendbc/car/tesla/values.py @@ -0,0 +1,130 @@ +from dataclasses import dataclass, field +from enum import Enum, IntFlag +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY, Bus, CarSpecs, DbcDict, PlatformConfig, Platforms +from opendbc.car.lateral import AngleSteeringLimits, ISO_LATERAL_ACCEL +from opendbc.car.structs import CarParams, CarState +from opendbc.car.docs_definitions import CarDocs, CarFootnote, CarHarness, CarParts, Column +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu + + +class Footnote(Enum): + HW_TYPE = CarFootnote( + "Some 2023 model years have HW4. To check which hardware type your vehicle has, look for " + + "Autopilot computer under Software -> Additional Vehicle Information on your vehicle's touchscreen.

    " + + "See this page for more information.", + Column.MODEL) + + SETUP = CarFootnote( + "See more setup details for Tesla.", + Column.MAKE, setup_note=True) + + +@dataclass +class TeslaCarDocsHW3(CarDocs): + package: str = "All" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.tesla_a])) + footnotes: list[Enum] = field(default_factory=lambda: [Footnote.HW_TYPE, Footnote.SETUP]) + + +@dataclass +class TeslaCarDocsHW4(CarDocs): + package: str = "All" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.tesla_b])) + footnotes: list[Enum] = field(default_factory=lambda: [Footnote.HW_TYPE, Footnote.SETUP]) + + +@dataclass +class TeslaPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.party: 'tesla_model3_party'}) + + +class CAR(Platforms): + TESLA_MODEL_3 = TeslaPlatformConfig( + [ + # TODO: do we support 2017? It's HW3 + TeslaCarDocsHW3("Tesla Model 3 (with HW3) 2019-23"), + TeslaCarDocsHW4("Tesla Model 3 (with HW4) 2024-25"), + ], + CarSpecs(mass=1899., wheelbase=2.875, steerRatio=12.0), + ) + TESLA_MODEL_Y = TeslaPlatformConfig( + [ + TeslaCarDocsHW3("Tesla Model Y (with HW3) 2020-23"), + TeslaCarDocsHW4("Tesla Model Y (with HW4) 2024-25"), + ], + CarSpecs(mass=2072., wheelbase=2.890, steerRatio=12.0), + ) + TESLA_MODEL_X = TeslaPlatformConfig( + [TeslaCarDocsHW4("Tesla Model X (with HW4) 2024")], + CarSpecs(mass=2495., wheelbase=2.960, steerRatio=12.0), + ) + + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[ + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.SUPPLIER_SOFTWARE_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.SUPPLIER_SOFTWARE_VERSION_RESPONSE], + bus=0, + ) + ] +) + + +class CANBUS: + party = 0 + vehicle = 1 + autopilot_party = 2 + + +GEAR_MAP = { + "DI_GEAR_INVALID": CarState.GearShifter.unknown, + "DI_GEAR_P": CarState.GearShifter.park, + "DI_GEAR_R": CarState.GearShifter.reverse, + "DI_GEAR_N": CarState.GearShifter.neutral, + "DI_GEAR_D": CarState.GearShifter.drive, + "DI_GEAR_SNA": CarState.GearShifter.unknown, +} + + +# Add extra tolerance for average banked road since safety doesn't have the roll +AVERAGE_ROAD_ROLL = 0.06 # ~3.4 degrees, 6% superelevation. higher actual roll lowers lateral acceleration + + +class CarControllerParams: + ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits( + # EPAS faults above this angle + 360, # deg + # Tesla uses a vehicle model instead, check carcontroller.py for details + ([], []), + ([], []), + + # Vehicle model angle limits + # Add extra tolerance for average banked road since safety doesn't have the roll + MAX_LATERAL_ACCEL=ISO_LATERAL_ACCEL + (ACCELERATION_DUE_TO_GRAVITY * AVERAGE_ROAD_ROLL), # ~3.6 m/s^2 + MAX_LATERAL_JERK=3.0 + (ACCELERATION_DUE_TO_GRAVITY * AVERAGE_ROAD_ROLL), # ~3.6 m/s^3 + + # limit angle rate to both prevent a fault and for low speed comfort (~12 mph rate down to 0 mph) + MAX_ANGLE_RATE=5, # deg/20ms frame, EPS faults at 12 at a standstill + ) + + STEER_STEP = 2 # Angle command is sent at 50 Hz + ACCEL_MAX = 2.0 # m/s^2 + ACCEL_MIN = -3.48 # m/s^2 + JERK_LIMIT_MAX = 4.9 # m/s^3, ACC faults at 5.0 + JERK_LIMIT_MIN = -4.9 # m/s^3, ACC faults at 5.0 + + +class TeslaSafetyFlags(IntFlag): + LONG_CONTROL = 1 + + +class TeslaFlags(IntFlag): + LONG_CONTROL = 1 + + +DBC = CAR.create_dbc_map() + +STEER_THRESHOLD = 1 diff --git a/opendbc_repo/opendbc/car/tests/__init__.py b/opendbc_repo/opendbc/car/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/tests/routes.py b/opendbc_repo/opendbc/car/tests/routes.py new file mode 100644 index 0000000000..02d2550a05 --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/routes.py @@ -0,0 +1,335 @@ +from typing import NamedTuple + +from opendbc.car.chrysler.values import CAR as CHRYSLER +from opendbc.car.gm.values import CAR as GM +from opendbc.car.ford.values import CAR as FORD +from opendbc.car.honda.values import CAR as HONDA +from opendbc.car.hyundai.values import CAR as HYUNDAI +from opendbc.car.nissan.values import CAR as NISSAN +from opendbc.car.mazda.values import CAR as MAZDA +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.rivian.values import CAR as RIVIAN +from opendbc.car.subaru.values import CAR as SUBARU +from opendbc.car.tesla.values import CAR as TESLA +from opendbc.car.toyota.values import CAR as TOYOTA +from opendbc.car.values import Platform +from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN +from opendbc.car.body.values import CAR as COMMA +from opendbc.car.psa.values import CAR as PSA + +# FIXME: add routes for these cars +non_tested_cars = [ + MOCK.MOCK, + GM.CADILLAC_ATS, + GM.HOLDEN_ASTRA, + GM.CHEVROLET_MALIBU, + HYUNDAI.GENESIS_G90, + VOLKSWAGEN.VOLKSWAGEN_CRAFTER_MK2, # need a route from an ACC-equipped Crafter + SUBARU.SUBARU_FORESTER_HYBRID, +] + + +class CarTestRoute(NamedTuple): + route: str + car_model: Platform | None + segment: int | None = None + + +routes = [ + CarTestRoute("efdf9af95e71cd84/2022-05-13--19-03-31", COMMA.COMMA_BODY), + + CarTestRoute("0c94aa1e1296d7c6/2021-05-05--19-48-37", CHRYSLER.JEEP_GRAND_CHEROKEE), + CarTestRoute("91dfedae61d7bd75/2021-05-22--20-07-52", CHRYSLER.JEEP_GRAND_CHEROKEE_2019), + CarTestRoute("420a8e183f1aed48/2020-03-05--07-15-29", CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID), # 2017 + CarTestRoute("43a685a66291579b/2021-05-27--19-47-29", CHRYSLER.CHRYSLER_PACIFICA_2018), + CarTestRoute("378472f830ee7395/2021-05-28--07-38-43", CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID), + CarTestRoute("8190c7275a24557b/2020-01-29--08-33-58", CHRYSLER.CHRYSLER_PACIFICA_2019_HYBRID), + CarTestRoute("3d84727705fecd04/2021-05-25--08-38-56", CHRYSLER.CHRYSLER_PACIFICA_2020), + CarTestRoute("221c253375af4ee9/2022-06-15--18-38-24", CHRYSLER.RAM_1500_5TH_GEN), + CarTestRoute("8fb5eabf914632ae/2022-08-04--17-28-53", CHRYSLER.RAM_HD_5TH_GEN, segment=6), + CarTestRoute("3379c85aeedc8285/2023-12-07--17-49-39", CHRYSLER.DODGE_DURANGO), + + CarTestRoute("54827bf84c38b14f/2023-01-25--14-14-11", FORD.FORD_BRONCO_SPORT_MK1), + CarTestRoute("f8eaaccd2a90aef8/2023-05-04--15-10-09", FORD.FORD_ESCAPE_MK4), + CarTestRoute("56574443e0c3783c/00000002--c00bd0fe69", FORD.FORD_ESCAPE_MK4_5), + CarTestRoute("62241b0c7fea4589/2022-09-01--15-32-49", FORD.FORD_EXPLORER_MK6), + CarTestRoute("e886087f430e7fe7/2023-06-16--23-06-36", FORD.FORD_FOCUS_MK4), + CarTestRoute("bd37e43731e5964b/2023-04-30--10-42-26", FORD.FORD_MAVERICK_MK1), + CarTestRoute("112e4d6e0cad05e1/2023-11-14--08-21-43", FORD.FORD_F_150_LIGHTNING_MK1), + CarTestRoute("e36b272d5679115f/00000369--a3e8499a85", FORD.FORD_F_150_MK14), + CarTestRoute("83a4e056c7072678/2023-11-13--16-51-33", FORD.FORD_MUSTANG_MACH_E_MK1), + CarTestRoute("37998aa0fade36ab/00000000--48f927c4f5", FORD.FORD_RANGER_MK2), + CarTestRoute("61a1b9e7a4eae0f6/00000000--79d85d1315", FORD.FORD_EXPEDITION_MK4), + #TestRoute("f1b4c567731f4a1b/2018-04-30--10-15-35", FORD.FUSION), + + CarTestRoute("7cc2a8365b4dd8a9/2018-12-02--12-10-44", GM.GMC_ACADIA), + CarTestRoute("aa20e335f61ba898/2019-02-05--16-59-04", GM.BUICK_REGAL), + CarTestRoute("75a6bcb9b8b40373/2023-03-11--22-47-33", GM.BUICK_LACROSSE), + CarTestRoute("e746f59bc96fd789/2024-01-31--22-25-58", GM.CHEVROLET_EQUINOX), + CarTestRoute("ef8f2185104d862e/2023-02-09--18-37-13", GM.CADILLAC_ESCALADE), + CarTestRoute("46460f0da08e621e/2021-10-26--07-21-46", GM.CADILLAC_ESCALADE_ESV), + CarTestRoute("168f8b3be57f66ae/2023-09-12--21-44-42", GM.CADILLAC_ESCALADE_ESV_2019), + CarTestRoute("c950e28c26b5b168/2018-05-30--22-03-41", GM.CHEVROLET_VOLT), + CarTestRoute("f08912a233c1584f/2022-08-11--18-02-41", GM.CHEVROLET_BOLT_EUV, segment=1), + CarTestRoute("555d4087cf86aa91/2022-12-02--12-15-07", GM.CHEVROLET_BOLT_EUV, segment=14), # Bolt EV + CarTestRoute("38aa7da107d5d252/2022-08-15--16-01-12", GM.CHEVROLET_SILVERADO), + CarTestRoute("5085c761395d1fe6/2023-04-07--18-20-06", GM.CHEVROLET_TRAILBLAZER), + CarTestRoute("162796f1469f2f1b/00000005--6f334eda14", GM.CADILLAC_XT4), + CarTestRoute("477dd485611d1e6e/00000009--85fc06e10a", GM.CHEVROLET_VOLT_2019), + CarTestRoute("a40976dc9f28ba62/0000001f--160e210119", GM.CHEVROLET_TRAVERSE), + CarTestRoute("36c62b5da6f08154/00000052--983c17c5b2", GM.GMC_YUKON), + + CarTestRoute("0e7a2ba168465df5/2020-10-18--14-14-22", HONDA.ACURA_RDX_3G), + CarTestRoute("a74b011b32b51b56/2020-07-26--17-09-36", HONDA.HONDA_CIVIC), + CarTestRoute("a859a044a447c2b0/2020-03-03--18-42-45", HONDA.HONDA_CRV_EU), + CarTestRoute("68aac44ad69f838e/2021-05-18--20-40-52", HONDA.HONDA_CRV), + CarTestRoute("14fed2e5fa0aa1a5/2021-05-25--14-59-42", HONDA.HONDA_CRV_HYBRID), + CarTestRoute("52f3e9ae60c0d886/2021-05-23--15-59-43", HONDA.HONDA_FIT), + CarTestRoute("2c4292a5cd10536c/2021-08-19--21-32-15", HONDA.HONDA_FREED), + CarTestRoute("03be5f2fd5c508d1/2020-04-19--18-44-15", HONDA.HONDA_HRV), + CarTestRoute("320098ff6c5e4730/2023-04-13--17-47-46", HONDA.HONDA_HRV_3G), + CarTestRoute("147613502316e718/00000001--dd141a3140", HONDA.HONDA_HRV_3G), # Brazilian model + CarTestRoute("1e4baee1aa2687a0/00000001--74c4cc0b23", HONDA.HONDA_HRV_3G), # Thailand model use ALT_GEAR + CarTestRoute("414af83891dbf72c/00000006--51fa6d99cd", HONDA.HONDA_NBOX_2G), + CarTestRoute("917b074700869333/2021-05-24--20-40-20", HONDA.ACURA_ILX), + CarTestRoute("08a3deb07573f157/2020-03-06--16-11-19", HONDA.HONDA_ACCORD), # 1.5T + CarTestRoute("1da5847ac2488106/2021-05-24--19-31-50", HONDA.HONDA_ACCORD), # 2.0T + CarTestRoute("085ac1d942c35910/2021-03-25--20-11-15", HONDA.HONDA_ACCORD), # 2021 with new style HUD msgs + CarTestRoute("07585b0da3c88459/2021-05-26--18-52-04", HONDA.HONDA_ACCORD), # hybrid + CarTestRoute("f29e2b57a55e7ad5/2021-03-24--20-52-38", HONDA.HONDA_ACCORD), # hybrid, 2021 with new style HUD msgs + CarTestRoute("1ad763dd22ef1a0e/2020-02-29--18-37-03", HONDA.HONDA_CRV_5G), + CarTestRoute("0a96f86fcfe35964/2020-02-05--07-25-51", HONDA.HONDA_ODYSSEY), + CarTestRoute("d7233a428eb7d0b5/00000001--9b99b04d43", HONDA.HONDA_ODYSSEY_5G_MMR), + CarTestRoute("d83f36766f8012a5/2020-02-05--18-42-21", HONDA.HONDA_CIVIC_BOSCH_DIESEL), + CarTestRoute("f0890d16a07a236b/2021-05-25--17-27-22", HONDA.HONDA_INSIGHT), + CarTestRoute("07d37d27996096b6/2020-03-04--21-57-27", HONDA.HONDA_PILOT), + CarTestRoute("684e8f96bd491a0e/2021-11-03--11-08-42", HONDA.HONDA_PILOT), # Passport + CarTestRoute("0a78dfbacc8504ef/2020-03-04--13-29-55", HONDA.HONDA_CIVIC_BOSCH), + CarTestRoute("f34a60d68d83b1e5/2020-10-06--14-35-55", HONDA.ACURA_RDX), + CarTestRoute("54fd8451b3974762/2021-04-01--14-50-10", HONDA.HONDA_RIDGELINE), + CarTestRoute("2d5808fae0b38ac6/2021-09-01--17-14-11", HONDA.HONDA_E), + CarTestRoute("f44aa96ace22f34a/2021-12-22--06-22-31", HONDA.HONDA_CIVIC_2022), + CarTestRoute("1f032f5173c8ad99/00000006--573b3fcaf5", HONDA.HONDA_CIVIC_2022), # Civic Type R with manual transmission + CarTestRoute("b1c832ad56b6bc9d/00000010--debfcf5867", HONDA.HONDA_CIVIC_2022), # 2025 Civic Hatch Hybrid with new eCVT transmission + CarTestRoute("f9c43864cf057d05/2024-01-15--23-01-20", HONDA.HONDA_PILOT_4G), # TODO: Replace with a newer route + CarTestRoute("f39cf149898833ff/0000002b--54f3fae045", HONDA.HONDA_ACCORD_11G), + CarTestRoute("ad9840558640c31d/0000001a--d6cd4871c2", HONDA.ACURA_MDX_4G_MMR), # 2025 MDX + CarTestRoute("56b2cf1dacdcd033/00000017--d24ffdb376", HONDA.HONDA_CITY_7G), # Brazilian model + CarTestRoute("2dc4489d7e1410ca/00000001--bbec3f5117", HONDA.HONDA_CRV_6G), + CarTestRoute("a703d058f4e05aeb/00000008--f169423024", HONDA.HONDA_PASSPORT_4G), + CarTestRoute("58c4a49c7e193080/00000008--aed64b5ba8", HONDA.ACURA_TLX_2G), + + CarTestRoute("87d7f06ade479c2e/2023-09-11--23-30-11", HYUNDAI.HYUNDAI_AZERA_6TH_GEN), + CarTestRoute("66189dd8ec7b50e6/2023-09-20--07-02-12", HYUNDAI.HYUNDAI_AZERA_HEV_6TH_GEN), + CarTestRoute("6fe86b4e410e4c37/2020-07-22--16-27-13", HYUNDAI.HYUNDAI_GENESIS), + CarTestRoute("b5d6dc830ad63071/2022-12-12--21-28-25", HYUNDAI.GENESIS_GV60_EV_1ST_GEN, segment=12), + CarTestRoute("70c5bec28ec8e345/2020-08-08--12-22-23", HYUNDAI.GENESIS_G70), + CarTestRoute("ca4de5b12321bd98/2022-10-18--21-15-59", HYUNDAI.GENESIS_GV70_1ST_GEN), + CarTestRoute("afe09b9f5d3f3548/00000011--15fefe1c50", HYUNDAI.GENESIS_GV70_ELECTRIFIED_1ST_GEN), + CarTestRoute("afe09b9f5d3f3548/0000001b--a1129a4a15", HYUNDAI.GENESIS_GV70_ELECTRIFIED_1ST_GEN), # openpilot longitudinal enabled + CarTestRoute("6b301bf83f10aa90/2020-11-22--16-45-07", HYUNDAI.GENESIS_G80), + CarTestRoute("66eaa6c3b6b2afc6/00000009--3a5199aabe", HYUNDAI.GENESIS_G80_2ND_GEN_FL), # LKA steering + CarTestRoute("0bbe367c98fa1538/2023-09-16--00-16-49", HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN), + CarTestRoute("f0709d2bc6ca451f/2022-10-15--08-13-54", HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN), + CarTestRoute("4dbd55df87507948/2022-03-01--09-45-38", HYUNDAI.HYUNDAI_SANTA_FE), + CarTestRoute("bf43d9df2b660eb0/2021-09-23--14-16-37", HYUNDAI.HYUNDAI_SANTA_FE_2022), + CarTestRoute("37398f32561a23ad/2021-11-18--00-11-35", HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022), + CarTestRoute("656ac0d830792fcc/2021-12-28--14-45-56", HYUNDAI.HYUNDAI_SANTA_FE_PHEV_2022, segment=1), + CarTestRoute("de59124955b921d8/2023-06-24--00-12-50", HYUNDAI.KIA_CARNIVAL_4TH_GEN), + CarTestRoute("409c9409979a8abc/2023-07-11--09-06-44", HYUNDAI.KIA_CARNIVAL_4TH_GEN), # Chinese model + CarTestRoute("e0e98335f3ebc58f/2021-03-07--16-38-29", HYUNDAI.KIA_CEED), + CarTestRoute("7653b2bce7bcfdaa/2020-03-04--15-34-32", HYUNDAI.KIA_OPTIMA_G4), + CarTestRoute("018654717bc93d7d/2022-09-19--23-11-10", HYUNDAI.KIA_OPTIMA_G4_FL, segment=0), + CarTestRoute("f9716670b2481438/2023-08-23--14-49-50", HYUNDAI.KIA_OPTIMA_H), + CarTestRoute("6a42c1197b2a8179/2023-09-21--10-23-44", HYUNDAI.KIA_OPTIMA_H_G4_FL), + CarTestRoute("c75a59efa0ecd502/2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS), + CarTestRoute("5b7c365c50084530/2020-04-15--16-13-24", HYUNDAI.HYUNDAI_SONATA), + CarTestRoute("b2a38c712dcf90bd/2020-05-18--18-12-48", HYUNDAI.HYUNDAI_SONATA_LF), + CarTestRoute("c344fd2492c7a9d2/2023-12-11--09-03-23", HYUNDAI.HYUNDAI_STARIA_4TH_GEN), + CarTestRoute("fb3fd42f0baaa2f8/2022-03-30--15-25-05", HYUNDAI.HYUNDAI_TUCSON), + CarTestRoute("db68bbe12250812c/2022-12-05--00-54-12", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # 2023 + CarTestRoute("36e10531feea61a4/2022-07-25--13-37-42", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # hybrid + CarTestRoute("5875672fc1d4bf57/2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO), + CarTestRoute("1d0d000db3370fd0/2023-01-04--22-28-42", HYUNDAI.KIA_SORENTO_4TH_GEN, segment=5), + CarTestRoute("fc19648042eb6896/2023-08-16--11-43-27", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, segment=14), + CarTestRoute("628935d7d3e5f4f7/2022-11-30--01-12-46", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN), # plug-in hybrid + CarTestRoute("9c917ba0d42ffe78/2020-04-17--12-43-19", HYUNDAI.HYUNDAI_PALISADE), + CarTestRoute("05a8f0197fdac372/2022-10-19--14-14-09", HYUNDAI.HYUNDAI_IONIQ_5), # LKA steering + CarTestRoute("eb4eae1476647463/2023-08-26--18-07-04", HYUNDAI.HYUNDAI_IONIQ_6, segment=6), # LKA steering + CarTestRoute("3f29334d6134fcd4/2022-03-30--22-00-50", HYUNDAI.HYUNDAI_IONIQ_PHEV_2019), + CarTestRoute("fa8db5869167f821/2021-06-10--22-50-10", HYUNDAI.HYUNDAI_IONIQ_PHEV), + CarTestRoute("e1107f9d04dfb1e2/2023-09-05--22-32-12", HYUNDAI.HYUNDAI_IONIQ_PHEV), # openpilot longitudinal enabled + CarTestRoute("2c5cf2dd6102e5da/2020-12-17--16-06-44", HYUNDAI.HYUNDAI_IONIQ_EV_2020), + CarTestRoute("610ebb9faaad6b43/2020-06-13--15-28-36", HYUNDAI.HYUNDAI_IONIQ_EV_LTD), + CarTestRoute("2c5cf2dd6102e5da/2020-06-26--16-00-08", HYUNDAI.HYUNDAI_IONIQ), + CarTestRoute("012c95f06918eca4/2023-01-15--11-19-36", HYUNDAI.HYUNDAI_IONIQ), # openpilot longitudinal enabled + CarTestRoute("ab59fe909f626921/2021-10-18--18-34-28", HYUNDAI.HYUNDAI_IONIQ_HEV_2022), + CarTestRoute("22d955b2cd499c22/2020-08-10--19-58-21", HYUNDAI.HYUNDAI_KONA), + CarTestRoute("0099bdb24d82951b/00000005--c38d940b04", HYUNDAI.HYUNDAI_KONA_2022), + CarTestRoute("efc48acf44b1e64d/2021-05-28--21-05-04", HYUNDAI.HYUNDAI_KONA_EV), + CarTestRoute("f90d3cd06caeb6fa/2023-09-06--17-15-47", HYUNDAI.HYUNDAI_KONA_EV), # openpilot longitudinal enabled + CarTestRoute("ff973b941a69366f/2022-07-28--22-01-19", HYUNDAI.HYUNDAI_KONA_EV_2022, segment=11), + CarTestRoute("1618132d68afc876/2023-08-27--09-32-14", HYUNDAI.HYUNDAI_KONA_EV_2ND_GEN, segment=13), + CarTestRoute("49f3c13141b6bc87/2021-07-28--08-05-13", HYUNDAI.HYUNDAI_KONA_HEV), + CarTestRoute("a74afe0cf708748f/0000000e--a2885a9a71", HYUNDAI.HYUNDAI_NEXO_1ST_GEN), + CarTestRoute("a74afe0cf708748f/0000000c--b476a8fd00", HYUNDAI.HYUNDAI_NEXO_1ST_GEN), # openpilot longitudinal enabled + CarTestRoute("5dddcbca6eb66c62/2020-07-26--13-24-19", HYUNDAI.KIA_STINGER), + CarTestRoute("5b50b883a4259afb/2022-11-09--15-00-42", HYUNDAI.KIA_STINGER_2022), + CarTestRoute("d624b3d19adce635/2020-08-01--14-59-12", HYUNDAI.HYUNDAI_VELOSTER), + CarTestRoute("d545129f3ca90f28/2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # LKA steering + CarTestRoute("68d6a96e703c00c9/2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # LFA steering + CarTestRoute("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6), + CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021), + CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020), + CarTestRoute("78ad5150de133637/2023-09-13--16-15-57", HYUNDAI.KIA_K8_HEV_1ST_GEN), + CarTestRoute("50c6c9b85fd1ff03/2020-10-26--17-56-06", HYUNDAI.KIA_NIRO_EV), + CarTestRoute("b153671049a867b3/2023-04-05--10-00-30", HYUNDAI.KIA_NIRO_EV_2ND_GEN), + CarTestRoute("173219cf50acdd7b/2021-07-05--10-27-41", HYUNDAI.KIA_NIRO_PHEV), + CarTestRoute("23349923ba5c4e3b/2023-12-02--08-51-54", HYUNDAI.KIA_NIRO_PHEV_2022), + CarTestRoute("34a875f29f69841a/2021-07-29--13-02-09", HYUNDAI.KIA_NIRO_HEV_2021), + CarTestRoute("db04d2c63990e3ba/2023-02-08--16-52-39", HYUNDAI.KIA_NIRO_HEV_2ND_GEN), + CarTestRoute("50a2212c41f65c7b/2021-05-24--16-22-06", HYUNDAI.KIA_FORTE), + CarTestRoute("192283cdbb7a58c2/2022-10-15--01-43-18", HYUNDAI.KIA_SPORTAGE_5TH_GEN), + CarTestRoute("09559f1fcaed4704/2023-11-16--02-24-57", HYUNDAI.KIA_SPORTAGE_5TH_GEN, segment=0), # openpilot longitudinal + CarTestRoute("b3537035ffe6a7d6/2022-10-17--15-23-49", HYUNDAI.KIA_SPORTAGE_5TH_GEN), # hybrid + CarTestRoute("c5ac319aa9583f83/2021-06-01--18-18-31", HYUNDAI.HYUNDAI_ELANTRA), + CarTestRoute("734ef96182ddf940/2022-10-02--16-41-44", HYUNDAI.HYUNDAI_ELANTRA_GT_I30), + CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021), + CarTestRoute("715ac05b594e9c59/2021-06-20--16-21-07", HYUNDAI.HYUNDAI_ELANTRA_HEV_2021), + CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID), + CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020), + CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80), + + CarTestRoute("00c829b1b7613dea/2021-06-24--09-10-10", TOYOTA.TOYOTA_ALPHARD_TSS2), + CarTestRoute("912119ebd02c7a42/2022-03-19--07-24-50", TOYOTA.TOYOTA_ALPHARD_TSS2), # hybrid + CarTestRoute("000cf3730200c71c/2021-05-24--10-42-05", TOYOTA.TOYOTA_AVALON), + CarTestRoute("0bb588106852abb7/2021-05-26--12-22-01", TOYOTA.TOYOTA_AVALON_2019), + CarTestRoute("87bef2930af86592/2021-05-30--09-40-54", TOYOTA.TOYOTA_AVALON_2019), # hybrid + CarTestRoute("e9966711cfb04ce3/2022-01-11--07-59-43", TOYOTA.TOYOTA_AVALON_TSS2), + CarTestRoute("eca1080a91720a54/2022-03-17--13-32-29", TOYOTA.TOYOTA_AVALON_TSS2), # hybrid + CarTestRoute("6cdecc4728d4af37/2020-02-23--15-44-18", TOYOTA.TOYOTA_CAMRY), + CarTestRoute("2f37c007683e85ba/2023-09-02--14-39-44", TOYOTA.TOYOTA_CAMRY), # openpilot longitudinal, with radar CAN filter + CarTestRoute("54034823d30962f5/2021-05-24--06-37-34", TOYOTA.TOYOTA_CAMRY), # hybrid + CarTestRoute("3456ad0cd7281b24/2020-12-13--17-45-56", TOYOTA.TOYOTA_CAMRY_TSS2), + CarTestRoute("ffccc77938ddbc44/2021-01-04--16-55-41", TOYOTA.TOYOTA_CAMRY_TSS2), # hybrid + CarTestRoute("4e45c89c38e8ec4d/2021-05-02--02-49-28", TOYOTA.TOYOTA_COROLLA), + CarTestRoute("5f5afb36036506e4/2019-05-14--02-09-54", TOYOTA.TOYOTA_COROLLA_TSS2), + CarTestRoute("5ceff72287a5c86c/2019-10-19--10-59-02", TOYOTA.TOYOTA_COROLLA_TSS2), # hybrid + CarTestRoute("d2525c22173da58b/2021-04-25--16-47-04", TOYOTA.TOYOTA_PRIUS), + CarTestRoute("b14c5b4742e6fc85/2020-07-28--19-50-11", TOYOTA.TOYOTA_RAV4), + CarTestRoute("32a7df20486b0f70/2020-02-06--16-06-50", TOYOTA.TOYOTA_RAV4H), + CarTestRoute("cdf2f7de565d40ae/2019-04-25--03-53-41", TOYOTA.TOYOTA_RAV4_TSS2), + CarTestRoute("a5c341bb250ca2f0/2022-05-18--16-05-17", TOYOTA.TOYOTA_RAV4_TSS2_2022), + CarTestRoute("ad5a3fa719bc2f83/2023-10-17--19-48-42", TOYOTA.TOYOTA_RAV4_TSS2_2023), + CarTestRoute("7e34a988419b5307/2019-12-18--19-13-30", TOYOTA.TOYOTA_RAV4_TSS2), # hybrid + CarTestRoute("2475fb3eb2ffcc2e/2022-04-29--12-46-23", TOYOTA.TOYOTA_RAV4_TSS2_2022), # hybrid + CarTestRoute("20ba9ade056a8c7b/2021-02-08--21-57-35", TOYOTA.TOYOTA_RAV4_PRIME), # SecOC + CarTestRoute("8bfb000e03b2a257/00000004--f9eee5f52e", TOYOTA.TOYOTA_SIENNA_4TH_GEN), # SecOC + CarTestRoute("0b54d0594d924cd9/00000057--b6206a3205", TOYOTA.TOYOTA_YARIS), # SecOC + CarTestRoute("7a31f030957b9c85/2023-04-01--14-12-51", TOYOTA.LEXUS_ES), + CarTestRoute("37041c500fd30100/2020-12-30--12-17-24", TOYOTA.LEXUS_ES), # hybrid + CarTestRoute("e6a24be49a6cd46e/2019-10-29--10-52-42", TOYOTA.LEXUS_ES_TSS2), + CarTestRoute("f49e8041283f2939/2019-05-30--11-51-51", TOYOTA.LEXUS_ES_TSS2), # hybrid + CarTestRoute("da23c367491f53e2/2021-05-21--09-09-11", TOYOTA.LEXUS_CTH, segment=3), + CarTestRoute("32696cea52831b02/2021-11-19--18-13-30", TOYOTA.LEXUS_RC), + CarTestRoute("7f8f479cfa6f392a/00000001--9a84b69c9d", TOYOTA.LEXUS_RC_TSS2), + CarTestRoute("ab9b64a5e5960cba/2023-10-24--17-32-08", TOYOTA.LEXUS_GS_F), + CarTestRoute("886fcd8408d570e9/2020-01-29--02-18-55", TOYOTA.LEXUS_RX), + CarTestRoute("d27ad752e9b08d4f/2021-05-26--19-39-51", TOYOTA.LEXUS_RX), # hybrid + CarTestRoute("01b22eb2ed121565/2020-02-02--11-25-51", TOYOTA.LEXUS_RX_TSS2), + CarTestRoute("b74758c690a49668/2020-05-20--15-58-57", TOYOTA.LEXUS_RX_TSS2), # hybrid + CarTestRoute("964c09eb11ca8089/2020-11-03--22-04-00", TOYOTA.LEXUS_NX), + CarTestRoute("ec429c0f37564e3c/2020-02-01--17-28-12", TOYOTA.LEXUS_NX), # hybrid + CarTestRoute("3fd5305f8b6ca765/2021-04-28--19-26-49", TOYOTA.LEXUS_NX_TSS2), + CarTestRoute("09ae96064ed85a14/2022-06-09--12-22-31", TOYOTA.LEXUS_NX_TSS2), # hybrid + CarTestRoute("4765fbbf59e3cd88/2024-02-06--17-45-32", TOYOTA.LEXUS_LC_TSS2), + CarTestRoute("0a302ffddbb3e3d3/2020-02-08--16-19-08", TOYOTA.TOYOTA_HIGHLANDER_TSS2), + CarTestRoute("437e4d2402abf524/2021-05-25--07-58-50", TOYOTA.TOYOTA_HIGHLANDER_TSS2), # hybrid + CarTestRoute("3183cd9b021e89ce/2021-05-25--10-34-44", TOYOTA.TOYOTA_HIGHLANDER), + CarTestRoute("80d16a262e33d57f/2021-05-23--20-01-43", TOYOTA.TOYOTA_HIGHLANDER), # hybrid + CarTestRoute("eb6acd681135480d/2019-06-20--20-00-00", TOYOTA.TOYOTA_SIENNA), + CarTestRoute("2e07163a1ba9a780/2019-08-25--13-15-13", TOYOTA.LEXUS_IS), + CarTestRoute("649bf2997ada6e3a/2023-08-08--18-04-22", TOYOTA.LEXUS_IS_TSS2), + CarTestRoute("0a0de17a1e6a2d15/2020-09-21--21-24-41", TOYOTA.TOYOTA_PRIUS_TSS2), + CarTestRoute("9b36accae406390e/2021-03-30--10-41-38", TOYOTA.TOYOTA_MIRAI), + CarTestRoute("cd9cff4b0b26c435/2021-05-13--15-12-39", TOYOTA.TOYOTA_CHR), + CarTestRoute("57858ede0369a261/2021-05-18--20-34-20", TOYOTA.TOYOTA_CHR), # hybrid + CarTestRoute("ea8fbe72b96a185c/2023-02-08--15-11-46", TOYOTA.TOYOTA_CHR_TSS2), + CarTestRoute("6719965b0e1d1737/2023-02-09--22-44-05", TOYOTA.TOYOTA_CHR_TSS2), # hybrid + CarTestRoute("6719965b0e1d1737/2023-08-29--06-40-05", TOYOTA.TOYOTA_CHR_TSS2), # hybrid, openpilot longitudinal, radar disabled + CarTestRoute("14623aae37e549f3/2021-10-24--01-20-49", TOYOTA.TOYOTA_PRIUS_V), + + CarTestRoute("202c40641158a6e5/2021-09-21--09-43-24", VOLKSWAGEN.VOLKSWAGEN_ARTEON_MK1), + CarTestRoute("2c68dda277d887ac/2021-05-11--15-22-20", VOLKSWAGEN.VOLKSWAGEN_ATLAS_MK1), + CarTestRoute("ffcd23abbbd02219/2024-02-28--14-59-38", VOLKSWAGEN.VOLKSWAGEN_CADDY_MK3), + CarTestRoute("cae14e88932eb364/2021-03-26--14-43-28", VOLKSWAGEN.VOLKSWAGEN_GOLF_MK7), # Stock ACC + CarTestRoute("3cfdec54aa035f3f/2022-10-13--14-58-58", VOLKSWAGEN.VOLKSWAGEN_GOLF_MK7), # openpilot longitudinal + CarTestRoute("578742b26807f756|00000010--41ee3e5bec", VOLKSWAGEN.VOLKSWAGEN_JETTA_MK6), + CarTestRoute("58a7d3b707987d65/2021-03-25--17-26-37", VOLKSWAGEN.VOLKSWAGEN_JETTA_MK7), + CarTestRoute("4d134e099430fba2/2021-03-26--00-26-06", VOLKSWAGEN.VOLKSWAGEN_PASSAT_MK8), + CarTestRoute("3cfdec54aa035f3f/2022-07-19--23-45-10", VOLKSWAGEN.VOLKSWAGEN_PASSAT_NMS), + CarTestRoute("0cd0b7f7e31a3853/2021-11-03--19-30-22", VOLKSWAGEN.VOLKSWAGEN_POLO_MK6), + CarTestRoute("064d1816e448f8eb/2022-09-29--15-32-34", VOLKSWAGEN.VOLKSWAGEN_SHARAN_MK2), + CarTestRoute("7d82b2f3a9115f1f/2021-10-21--15-39-42", VOLKSWAGEN.VOLKSWAGEN_TAOS_MK1), + CarTestRoute("2744c89a8dda9a51/2021-07-24--21-28-06", VOLKSWAGEN.VOLKSWAGEN_TCROSS_MK1), + CarTestRoute("2cef8a0b898f331a/2021-03-25--20-13-57", VOLKSWAGEN.VOLKSWAGEN_TIGUAN_MK2), + CarTestRoute("a589dcc642fdb10a/2021-06-14--20-54-26", VOLKSWAGEN.VOLKSWAGEN_TOURAN_MK2), + CarTestRoute("a459f4556782eba1/2021-09-19--09-48-00", VOLKSWAGEN.VOLKSWAGEN_TRANSPORTER_T61), + CarTestRoute("0cd0b7f7e31a3853/2021-11-18--00-38-32", VOLKSWAGEN.VOLKSWAGEN_TROC_MK1), + CarTestRoute("07667b885add75fd/2021-01-23--19-48-42", VOLKSWAGEN.AUDI_A3_MK3), + CarTestRoute("6c6b466346192818/2021-06-06--14-17-47", VOLKSWAGEN.AUDI_Q2_MK1), + CarTestRoute("0cd0b7f7e31a3853/2021-12-03--03-12-05", VOLKSWAGEN.AUDI_Q3_MK2), + CarTestRoute("8f205bdd11bcbb65/2021-03-26--01-00-17", VOLKSWAGEN.SEAT_ATECA_MK1), + CarTestRoute("fc6b6c9a3471c846/2021-05-27--13-39-56", VOLKSWAGEN.SEAT_ATECA_MK1), # Leon + CarTestRoute("0bbe367c98fa1538/2023-03-04--17-46-11", VOLKSWAGEN.SKODA_FABIA_MK4), + CarTestRoute("12d6ae3057c04b0d/2021-09-15--00-04-07", VOLKSWAGEN.SKODA_KAMIQ_MK1), + CarTestRoute("12d6ae3057c04b0d/2021-09-04--21-21-21", VOLKSWAGEN.SKODA_KAROQ_MK1), + CarTestRoute("90434ff5d7c8d603/2021-03-15--12-07-31", VOLKSWAGEN.SKODA_KODIAQ_MK1), + CarTestRoute("66e5edc3a16459c5/2021-05-25--19-00-29", VOLKSWAGEN.SKODA_OCTAVIA_MK3), + CarTestRoute("026b6d18fba6417f/2021-03-26--09-17-04", VOLKSWAGEN.SKODA_KAMIQ_MK1), # Scala + CarTestRoute("b2e9858e29db492b/2021-03-26--16-58-42", VOLKSWAGEN.SKODA_SUPERB_MK3), + + CarTestRoute("3c8f0c502e119c1c/2020-06-30--12-58-02", SUBARU.SUBARU_ASCENT), + CarTestRoute("c321c6b697c5a5ff/2020-06-23--11-04-33", SUBARU.SUBARU_FORESTER), + CarTestRoute("791340bc01ed993d/2019-03-10--16-28-08", SUBARU.SUBARU_IMPREZA), + CarTestRoute("8bf7e79a3ce64055/2021-05-24--09-36-27", SUBARU.SUBARU_IMPREZA_2020), + CarTestRoute("8de015561e1ea4a0/2023-08-29--17-08-31", SUBARU.SUBARU_IMPREZA), # openpilot longitudinal + # CarTestRoute("c3d1ccb52f5f9d65/2023-07-22--01-23-20", SUBARU.OUTBACK, segment=9), # gen2 longitudinal, eyesight disabled + CarTestRoute("1bbe6bf2d62f58a8/2022-07-14--17-11-43", SUBARU.SUBARU_OUTBACK, segment=10), + CarTestRoute("c56e69bbc74b8fad/2022-08-18--09-43-51", SUBARU.SUBARU_LEGACY, segment=3), + CarTestRoute("f4e3a0c511a076f4/2022-08-04--16-16-48", SUBARU.SUBARU_CROSSTREK_HYBRID, segment=2), + CarTestRoute("7fd1e4f3a33c1673/2022-12-04--15-09-53", SUBARU.SUBARU_FORESTER_2022, segment=4), + CarTestRoute("f3b34c0d2632aa83/2023-07-23--20-43-25", SUBARU.SUBARU_OUTBACK_2023, segment=7), + CarTestRoute("99437cef6d5ff2ee/2023-03-13--21-21-38", SUBARU.SUBARU_ASCENT_2023, segment=7), + # Pre-global, dashcam + CarTestRoute("95441c38ae8c130e/2020-06-08--12-10-17", SUBARU.SUBARU_FORESTER_PREGLOBAL), + CarTestRoute("df5ca7660000fba8/2020-06-16--17-37-19", SUBARU.SUBARU_LEGACY_PREGLOBAL), + CarTestRoute("5ab784f361e19b78/2020-06-08--16-30-41", SUBARU.SUBARU_OUTBACK_PREGLOBAL), + CarTestRoute("e19eb5d5353b1ac1/2020-08-09--14-37-56", SUBARU.SUBARU_OUTBACK_PREGLOBAL_2018), + + CarTestRoute("fbbfa6af821552b9/2020-03-03--08-09-43", NISSAN.NISSAN_XTRAIL), + CarTestRoute("5b7c365c50084530/2020-03-25--22-10-13", NISSAN.NISSAN_LEAF), + CarTestRoute("22c3dcce2dd627eb/2020-12-30--16-38-48", NISSAN.NISSAN_LEAF_IC), + CarTestRoute("059ab9162e23198e/2020-05-30--09-41-01", NISSAN.NISSAN_ROGUE), + CarTestRoute("b72d3ec617c0a90f/2020-12-11--15-38-17", NISSAN.NISSAN_ALTIMA), + + CarTestRoute("32a319f057902bb3/2020-04-27--15-18-58", MAZDA.MAZDA_CX5), + CarTestRoute("10b5a4b380434151/2020-08-26--17-11-45", MAZDA.MAZDA_CX9), + CarTestRoute("74f1038827005090/2020-08-26--20-05-50", MAZDA.MAZDA_3), + CarTestRoute("fb53c640f499b73d/2021-06-01--04-17-56", MAZDA.MAZDA_6), + CarTestRoute("f6d5b1a9d7a1c92e/2021-07-08--06-56-59", MAZDA.MAZDA_CX9_2021), + CarTestRoute("a4af1602d8e668ac/2022-02-03--12-17-07", MAZDA.MAZDA_CX5_2022), + + CarTestRoute("6a7075a4fdd765ee/0000004e--1f612006dd", PSA.PSA_PEUGEOT_208), + + CarTestRoute("bc095dc92e101734/000000db--ee9fe46e57", RIVIAN.RIVIAN_R1_GEN1), + + CarTestRoute("7dc058789994da80/00000112--adb970f6a8", TESLA.TESLA_MODEL_3), + CarTestRoute("c8a98e58647765ad/00000002--84e4746136", TESLA.TESLA_MODEL_Y), + CarTestRoute("2c912ca5de3b1ee9/0000025d--6eb6bcbca4", TESLA.TESLA_MODEL_Y, segment=4), + CarTestRoute("bdda168c0c35fad7/00000001--5c5a36ec06", TESLA.TESLA_MODEL_X), # openpilot longitudinal + + # Segments that test specific issues + # Controls mismatch due to standstill threshold + CarTestRoute("bec2dcfde6a64235/2022-04-08--14-21-32", HONDA.HONDA_CRV_HYBRID, segment=22), +] diff --git a/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py b/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py new file mode 100644 index 0000000000..30dba60008 --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py @@ -0,0 +1,55 @@ +import pytest +from opendbc.car.can_definitions import CanData +from opendbc.car.car_helpers import FRAME_FINGERPRINT, can_fingerprint +from opendbc.car.fingerprints import _FINGERPRINTS as FINGERPRINTS + + +class TestCanFingerprint: + @pytest.mark.parametrize("car_model, fingerprints", FINGERPRINTS.items()) + def test_can_fingerprint(self, car_model, fingerprints): + """Tests online fingerprinting function on offline fingerprints""" + + for fingerprint in fingerprints: # can have multiple fingerprints for each platform + can = [CanData(address=address, dat=b'\x00' * length, src=src) + for address, length in fingerprint.items() for src in (0, 1)] + + fingerprint_iter = iter([can]) + car_fingerprint, finger = can_fingerprint(lambda **kwargs: [next(fingerprint_iter, [])]) # noqa: B023 + + assert car_fingerprint == car_model + assert finger[0] == fingerprint + assert finger[1] == fingerprint + assert finger[2] == {} + + def test_timing(self, subtests): + # just pick any CAN fingerprinting car + car_model = "CHEVROLET_BOLT_EUV" + fingerprint = FINGERPRINTS[car_model][0] + + cases = [] + + # case 1 - one match, make sure we keep going for 100 frames + can = [CanData(address=address, dat=b'\x00' * length, src=src) + for address, length in fingerprint.items() for src in (0, 1)] + cases.append((FRAME_FINGERPRINT, car_model, can)) + + # case 2 - no matches, make sure we keep going for 100 frames + can = [CanData(address=1, dat=b'\x00' * 1, src=src) for src in (0, 1)] # uncommon address + cases.append((FRAME_FINGERPRINT, None, can)) + + # case 3 - multiple matches, make sure we keep going for 200 frames to try to eliminate some + can = [CanData(address=2016, dat=b'\x00' * 8, src=src) for src in (0, 1)] # common address + cases.append((FRAME_FINGERPRINT * 2, None, can)) + + for expected_frames, car_model, can in cases: + with subtests.test(expected_frames=expected_frames, car_model=car_model): + frames = 0 + + def can_recv(**kwargs): + nonlocal frames + frames += 1 + return [can] # noqa: B023 + + car_fingerprint, _ = can_fingerprint(can_recv) + assert car_fingerprint == car_model + assert frames == expected_frames + 2 # TODO: fix extra frames diff --git a/opendbc_repo/opendbc/car/tests/test_car_interfaces.py b/opendbc_repo/opendbc/car/tests/test_car_interfaces.py new file mode 100644 index 0000000000..63bedf0bb5 --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_car_interfaces.py @@ -0,0 +1,151 @@ +import os +import math +import hypothesis.strategies as st +import pytest +from hypothesis import Phase, given, settings +from collections.abc import Callable +from typing import Any + +from opendbc.car import DT_CTRL, CanData, structs +from opendbc.car.car_helpers import interfaces +from opendbc.car.fingerprints import FW_VERSIONS +from opendbc.car.fw_versions import FW_QUERY_CONFIGS +from opendbc.car.interfaces import CarInterfaceBase, get_interface_attr +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.values import PLATFORMS + +DrawType = Callable[[st.SearchStrategy], Any] + +ALL_ECUS = {ecu for ecus in FW_VERSIONS.values() for ecu in ecus.keys()} +ALL_ECUS |= {ecu for config in FW_QUERY_CONFIGS.values() for ecu in config.extra_ecus} + +ALL_REQUESTS = {tuple(r.request) for config in FW_QUERY_CONFIGS.values() for r in config.requests} + +# From panda/python/__init__.py +DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64] + +MAX_EXAMPLES = int(os.environ.get('MAX_EXAMPLES', '15')) + + +def get_fuzzy_car_interface(car_name: str, draw: DrawType) -> CarInterfaceBase: + # Fuzzy CAN fingerprints and FW versions to test more states of the CarInterface + fingerprint_strategy = st.fixed_dictionaries({0: st.dictionaries(st.integers(min_value=0, max_value=0x800), + st.sampled_from(DLC_TO_LEN))}) + + # only pick from possible ecus to reduce search space + car_fw_strategy = st.lists(st.builds( + lambda fw, req: structs.CarParams.CarFw(ecu=fw[0], address=fw[1], subAddress=fw[2] or 0, request=req), + st.sampled_from(sorted(ALL_ECUS)), + st.sampled_from(sorted(ALL_REQUESTS)), + )) + + params_strategy = st.fixed_dictionaries({ + 'fingerprints': fingerprint_strategy, + 'car_fw': car_fw_strategy, + 'alpha_long': st.booleans(), + }) + + params: dict = draw(params_strategy) + # reduce search space by duplicating CAN fingerprints across all buses + params['fingerprints'] |= {key + 1: params['fingerprints'][0] for key in range(6)} + + # initialize car interface + CarInterface = interfaces[car_name] + car_params = CarInterface.get_params(car_name, params['fingerprints'], params['car_fw'], + alpha_long=params['alpha_long'], is_release=False, docs=False) + return CarInterface(car_params) + + +class TestCarInterfaces: + # FIXME: Due to the lists used in carParams, Phase.target is very slow and will cause + # many generated examples to overrun when max_examples > ~20, don't use it + @pytest.mark.parametrize("car_name", sorted(PLATFORMS)) + @settings(max_examples=MAX_EXAMPLES, deadline=None, + phases=(Phase.reuse, Phase.generate, Phase.shrink)) + @given(data=st.data()) + def test_car_interfaces(self, car_name, data): + car_interface = get_fuzzy_car_interface(car_name, data.draw) + car_params = car_interface.CP.as_reader() + + assert car_params.mass > 1 + assert car_params.wheelbase > 0 + # centerToFront is center of gravity to front wheels, assert a reasonable range + assert car_params.wheelbase * 0.3 < car_params.centerToFront < car_params.wheelbase * 0.7 + assert car_params.maxLateralAccel > 0 + + # Longitudinal sanity checks + assert len(car_params.longitudinalTuning.kpV) == len(car_params.longitudinalTuning.kpBP) + assert len(car_params.longitudinalTuning.kiV) == len(car_params.longitudinalTuning.kiBP) + + # Lateral sanity checks + if car_params.steerControlType != structs.CarParams.SteerControlType.angle: + tune = car_params.lateralTuning + if tune.which() == 'pid': + if car_name != MOCK.MOCK: + assert not math.isnan(tune.pid.kf) and tune.pid.kf > 0 + assert len(tune.pid.kpV) > 0 and len(tune.pid.kpV) == len(tune.pid.kpBP) + assert len(tune.pid.kiV) > 0 and len(tune.pid.kiV) == len(tune.pid.kiBP) + + elif tune.which() == 'torque': + assert not math.isnan(tune.torque.kf) and tune.torque.kf > 0 + assert not math.isnan(tune.torque.friction) and tune.torque.friction > 0 + + # Run car interface + # TODO: use hypothesis to generate random messages + now_nanos = 0 + CC = structs.CarControl().as_reader() + for _ in range(10): + car_interface.update([]) + car_interface.apply(CC, now_nanos) + now_nanos += DT_CTRL * 1e9 # 10 ms + + CC = structs.CarControl() + CC.enabled = True + CC.latActive = True + CC.longActive = True + CC = CC.as_reader() + for _ in range(10): + car_interface.update([]) + car_interface.apply(CC, now_nanos) + now_nanos += DT_CTRL * 1e9 # 10ms + + # Test radar interface + radar_interface = car_interface.RadarInterface(car_params) + assert radar_interface + + # Run radar interface once + radar_interface.update([]) + if not car_params.radarUnavailable and radar_interface.rcp is not None and \ + hasattr(radar_interface, '_update') and hasattr(radar_interface, 'trigger_msg'): + radar_interface._update([radar_interface.trigger_msg]) + + # Test radar fault + if not car_params.radarUnavailable and radar_interface.rcp is not None: + cans = [(0, [CanData(0, b'', 0) for _ in range(5)])] + rr = radar_interface.update(cans) + assert rr is None or len(rr.errors) > 0 + + def test_interface_attrs(self): + """Asserts basic behavior of interface attribute getter""" + num_brands = len(get_interface_attr('CAR')) + assert num_brands >= 12 + + # Should return value for all brands when not combining, even if attribute doesn't exist + ret = get_interface_attr('FAKE_ATTR') + assert len(ret) == num_brands + + # Make sure we can combine dicts + ret = get_interface_attr('DBC', combine_brands=True) + assert len(ret) >= 160 + + # We don't support combining non-dicts + ret = get_interface_attr('CAR', combine_brands=True) + assert len(ret) == 0 + + # If brand has None value, it shouldn't return when ignore_none=True is specified + none_brands = {b for b, v in get_interface_attr('FINGERPRINTS').items() if v is None} + assert len(none_brands) >= 1 + + ret = get_interface_attr('FINGERPRINTS', ignore_none=True) + none_brands_in_ret = none_brands.intersection(ret) + assert len(none_brands_in_ret) == 0, f'Brands with None values in ignore_none=True result: {none_brands_in_ret}' diff --git a/opendbc_repo/opendbc/car/tests/test_docs.py b/opendbc_repo/opendbc/car/tests/test_docs.py new file mode 100644 index 0000000000..8a4ae09b5a --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_docs.py @@ -0,0 +1,79 @@ +from collections import defaultdict +import pytest + +from opendbc.car.car_helpers import interfaces +from opendbc.car.docs import get_all_car_docs +from opendbc.car.docs_definitions import Cable, Column, PartType, Star, SupportType +from opendbc.car.honda.values import CAR as HONDA +from opendbc.car.values import PLATFORMS + + +class TestCarDocs: + @classmethod + def setup_class(cls): + cls.all_cars = get_all_car_docs() + + def test_duplicate_years(self, subtests): + make_model_years = defaultdict(list) + for car in self.all_cars: + with subtests.test(car_docs_name=car.name): + if car.support_type != SupportType.UPSTREAM: + pytest.skip() + + make_model = (car.make, car.model) + for year in car.year_list: + assert year not in make_model_years[make_model], f"{car.name}: Duplicate model year" + make_model_years[make_model].append(year) + + def test_missing_car_docs(self, subtests): + all_car_docs_platforms = [name for name, config in PLATFORMS.items()] + for platform in sorted(interfaces.keys()): + with subtests.test(platform=platform): + assert platform in all_car_docs_platforms, f"Platform: {platform} doesn't have a CarDocs entry" + + def test_naming_conventions(self, subtests): + # Asserts market-standard car naming conventions by brand + for car in self.all_cars: + with subtests.test(car=car.name): + tokens = car.model.lower().split(" ") + if car.brand == "hyundai": + assert "phev" not in tokens, "Use `Plug-in Hybrid`" + assert "hev" not in tokens, "Use `Hybrid`" + if "plug-in hybrid" in car.model.lower(): + assert "Plug-in Hybrid" in car.model, "Use correct capitalization" + if car.make != "Kia": + assert "ev" not in tokens, "Use `Electric`" + elif car.brand == "toyota": + if "rav4" in tokens: + assert "RAV4" in car.model, "Use correct capitalization" + + def test_torque_star(self, subtests): + # Asserts brand-specific assumptions around steering torque star + for car in self.all_cars: + with subtests.test(car=car.name): + # honda sanity check, it's the definition of a no torque star + if car.car_fingerprint in (HONDA.HONDA_ACCORD, HONDA.HONDA_CIVIC, HONDA.HONDA_CRV, HONDA.HONDA_ODYSSEY, HONDA.HONDA_PILOT): + assert car.row[Column.STEERING_TORQUE] == Star.EMPTY, f"{car.name} has full torque star" + elif car.brand in ("toyota", "hyundai"): + assert car.row[Column.STEERING_TORQUE] != Star.EMPTY, f"{car.name} has no torque star" + + def test_year_format(self, subtests): + for car in self.all_cars: + with subtests.test(car=car.name): + if car.name == "comma body": + pytest.skip() + + assert car.years and car.year_list, f"Format years correctly: {car.name}" + + def test_harnesses(self, subtests): + for car in self.all_cars: + with subtests.test(car=car.name): + if car.name == "comma body" or car.support_type != SupportType.UPSTREAM: + pytest.skip() + + car_part_type = [p.part_type for p in car.car_parts.all_parts()] + car_parts = list(car.car_parts.all_parts()) + assert len(car_parts) > 0, f"Need to specify car parts: {car.name}" + assert car_part_type.count(PartType.connector) == 1, f"Need to specify one harness connector: {car.name}" + assert car_part_type.count(PartType.mount) == 1, f"Need to specify one mount: {car.name}" + assert Cable.right_angle_obd_c_cable_1_5ft in car_parts, f"Need to specify a right angle OBD-C cable (1.5ft): {car.name}" diff --git a/opendbc_repo/opendbc/car/tests/test_fw_fingerprint.py b/opendbc_repo/opendbc/car/tests/test_fw_fingerprint.py new file mode 100644 index 0000000000..08e8cf8544 --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_fw_fingerprint.py @@ -0,0 +1,328 @@ +import pytest +import random +import time +from collections import defaultdict + +from opendbc.car.can_definitions import CanData +from opendbc.car.car_helpers import interfaces +from opendbc.car.structs import CarParams +from opendbc.car.fingerprints import FW_VERSIONS +from opendbc.car.fw_versions import FW_QUERY_CONFIGS, FUZZY_EXCLUDE_ECUS, VERSIONS, build_fw_dict, \ + match_fw_to_car, get_brand_ecu_matches, get_fw_versions, get_present_ecus +from opendbc.car.vin import get_vin + +CarFw = CarParams.CarFw +Ecu = CarParams.Ecu + +ECU_NAME = {v: k for k, v in Ecu.schema.enumerants.items()} + + +class TestFwFingerprint: + def assertFingerprints(self, candidates, expected): + candidates = list(candidates) + assert len(candidates) == 1, f"got more than one candidate: {candidates}" + assert candidates[0] == expected + + @pytest.mark.parametrize("brand, car_model, ecus, test_non_essential", + [(b, c, e[c], n) for b, e in VERSIONS.items() for c in e for n in (True, False)]) + def test_exact_match(self, brand, car_model, ecus, test_non_essential): + config = FW_QUERY_CONFIGS[brand] + CP = CarParams() + for _ in range(20): + fw = [] + for ecu, fw_versions in ecus.items(): + # Assume non-essential ECUs apply to all cars, so we catch cases where Car A with + # missing ECUs won't match to Car B where only Car B has labeled non-essential ECUs + if ecu[0] in config.non_essential_ecus and test_non_essential: + continue + + ecu_name, addr, sub_addr = ecu + fw.append(CarFw(ecu=ecu_name, fwVersion=random.choice(fw_versions), brand=brand, + address=addr, subAddress=0 if sub_addr is None else sub_addr)) + CP.carFw = fw + _, matches = match_fw_to_car(CP.carFw, CP.carVin, allow_fuzzy=False) + if not test_non_essential: + self.assertFingerprints(matches, car_model) + else: + # if we're removing ECUs we expect some match loss, but it shouldn't mismatch + if len(matches) != 0: + self.assertFingerprints(matches, car_model) + + @pytest.mark.parametrize("brand, car_model, ecus", [(b, c, e[c]) for b, e in VERSIONS.items() for c in e]) + def test_custom_fuzzy_match(self, brand, car_model, ecus): + # Assert brand-specific fuzzy fingerprinting function doesn't disagree with standard fuzzy function + config = FW_QUERY_CONFIGS[brand] + if config.match_fw_to_car_fuzzy is None: + pytest.skip("Brand does not implement custom fuzzy fingerprinting function") + + CP = CarParams() + for _ in range(5): + fw = [] + for ecu, fw_versions in ecus.items(): + ecu_name, addr, sub_addr = ecu + fw.append(CarFw(ecu=ecu_name, fwVersion=random.choice(fw_versions), brand=brand, + address=addr, subAddress=0 if sub_addr is None else sub_addr)) + CP.carFw = fw + _, matches = match_fw_to_car(CP.carFw, CP.carVin, allow_exact=False, log=False) + brand_matches = config.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw), CP.carVin, VERSIONS[brand]) + + # If both have matches, they must agree + if len(matches) == 1 and len(brand_matches) == 1: + assert matches == brand_matches + + @pytest.mark.parametrize("brand, car_model, ecus", [(b, c, e[c]) for b, e in VERSIONS.items() for c in e]) + def test_fuzzy_match_ecu_count(self, brand, car_model, ecus): + # Asserts that fuzzy matching does not count matching FW, but ECU address keys + valid_ecus = [e for e in ecus if e[0] not in FUZZY_EXCLUDE_ECUS] + if not len(valid_ecus): + pytest.skip("Car model has no compatible ECUs for fuzzy matching") + + fw = [] + for ecu in valid_ecus: + ecu_name, addr, sub_addr = ecu + for _ in range(5): + # Add multiple FW versions to simulate ECU returning to multiple queries in a brand + fw.append(CarFw(ecu=ecu_name, fwVersion=random.choice(ecus[ecu]), brand=brand, + address=addr, subAddress=0 if sub_addr is None else sub_addr)) + CP = CarParams(carFw=fw) + _, matches = match_fw_to_car(CP.carFw, CP.carVin, allow_exact=False, log=False) + + # Assert no match if there are not enough unique ECUs + unique_ecus = {(f.address, f.subAddress) for f in fw} + if len(unique_ecus) < 2: + assert len(matches) == 0, car_model + # There won't always be a match due to shared FW, but if there is it should be correct + elif len(matches): + self.assertFingerprints(matches, car_model) + + def test_fw_version_lists(self, subtests): + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for ecu, ecu_fw in ecus.items(): + with subtests.test(ecu): + duplicates = {fw for fw in ecu_fw if ecu_fw.count(fw) > 1} + assert not len(duplicates), f'{car_model}: Duplicate FW versions: Ecu.{ecu[0]}, {duplicates}' + assert len(ecu_fw) > 0, f'{car_model}: No FW versions: Ecu.{ecu[0]}' + + def test_all_addrs_map_to_one_ecu(self): + for brand, cars in VERSIONS.items(): + addr_to_ecu = defaultdict(set) + for ecus in cars.values(): + for ecu_type, addr, sub_addr in ecus.keys(): + addr_to_ecu[(addr, sub_addr)].add(ecu_type) + ecus_for_addr = addr_to_ecu[(addr, sub_addr)] + ecu_strings = ", ".join([f'Ecu.{ecu}' for ecu in ecus_for_addr]) + assert len(ecus_for_addr) <= 1, f"{brand} has multiple ECUs that map to one address: {ecu_strings} -> ({hex(addr)}, {sub_addr})" + + def test_data_collection_ecus(self, subtests): + # Asserts no extra ECUs are in the fingerprinting database + for brand, config in FW_QUERY_CONFIGS.items(): + for car_model, ecus in VERSIONS[brand].items(): + bad_ecus = set(ecus).intersection(config.extra_ecus) + with subtests.test(car_model=car_model.value): + assert not len(bad_ecus), f'{car_model}: Fingerprints contain ECUs added for data collection: {bad_ecus}' + + def test_blacklisted_ecus(self, subtests): + blacklisted_addrs = (0x7c4, 0x7d0) # includes A/C ecu and an unknown ecu + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + CP = interfaces[car_model].get_non_essential_params(car_model) + if CP.brand == 'subaru': + for ecu in ecus.keys(): + assert ecu[1] not in blacklisted_addrs, f'{car_model}: Blacklisted ecu: (Ecu.{ecu[0]}, {hex(ecu[1])})' + + elif CP.brand == "chrysler": + # Some HD trucks have a combined TCM and ECM + if CP.carFingerprint.startswith("RAM_HD"): + for ecu in ecus.keys(): + assert ecu[0] != Ecu.transmission, f"{car_model}: Blacklisted ecu: (Ecu.{ecu[0]}, {hex(ecu[1])})" + + def test_missing_versions_and_configs(self, subtests): + brand_versions = set(VERSIONS.keys()) + brand_configs = set(FW_QUERY_CONFIGS.keys()) + if len(brand_configs - brand_versions): + with subtests.test(): + pytest.fail(f"Brands do not implement FW_VERSIONS: {brand_configs - brand_versions}") + + if len(brand_versions - brand_configs): + with subtests.test(): + pytest.fail(f"Brands do not implement FW_QUERY_CONFIG: {brand_versions - brand_configs}") + + # Ensure each brand has at least 1 ECU to query, and extra ECU retrieval + for brand, config in FW_QUERY_CONFIGS.items(): + assert len(config.get_all_ecus({}, include_extra_ecus=False)) == 0 + assert config.get_all_ecus({}) == set(config.extra_ecus) + if len(VERSIONS[brand]) > 0: + assert len(config.get_all_ecus(VERSIONS[brand])) > 0 + + def test_fw_request_ecu_whitelist(self, subtests): + for brand, config in FW_QUERY_CONFIGS.items(): + with subtests.test(brand=brand): + whitelisted_ecus = {ecu for r in config.requests for ecu in r.whitelist_ecus} + brand_ecus = {fw[0] for car_fw in VERSIONS[brand].values() for fw in car_fw} + brand_ecus |= {ecu[0] for ecu in config.extra_ecus} + + # each ecu in brand's fw versions + extra ecus needs to be whitelisted at least once + ecus_not_whitelisted = brand_ecus - whitelisted_ecus + + ecu_strings = ", ".join([f'Ecu.{ecu}' for ecu in ecus_not_whitelisted]) + assert not (len(whitelisted_ecus) and len(ecus_not_whitelisted)), \ + f'{brand.title()}: ECUs not in any FW query whitelists: {ecu_strings}' + + def test_request_ecus_in_versions(self): + # All ECUs in requests should be in the brand's FW versions + for brand, config in FW_QUERY_CONFIGS.items(): + request_ecus = {ecu for r in config.requests for ecu in r.whitelist_ecus} - {ecu[0] for ecu in config.extra_ecus} + print(brand, request_ecus) + version_ecus = config.get_all_ecus(VERSIONS[brand], include_extra_ecus=False) + for request_ecu in request_ecus: + assert request_ecu in {e for e, _, _ in version_ecus}, f"Ecu.{ECU_NAME[request_ecu]} not in {brand} FW versions" + + def test_brand_ecu_matches(self): + brand_matches = get_brand_ecu_matches(set()) + assert len(brand_matches) > 0 + assert all(len(e) and not any(e) for e in brand_matches.values()) + + # we ignore bus + brand_matches = get_brand_ecu_matches({(0x758, 0xf, 99)}) + assert True in brand_matches['toyota'] + assert not any(any(e) for b, e in brand_matches.items() if b != 'toyota') + + +class TestFwFingerprintTiming: + N: int = 5 + TOL: float = 0.05 + + # for patched functions + current_obd_multiplexing: bool + total_time: float + + @staticmethod + def fake_can_send(msgs): + pass + + @staticmethod + def fake_can_recv(wait_for_one: bool = False) -> list[list[CanData]]: + return ([[CanData(random.randint(0x600, 0x800), b'\x00' * 8, 0)]] + if random.uniform(0, 1) > 0.5 else []) + + def fake_set_obd_multiplexing(self, obd_multiplexing): + """The 10Hz blocking params loop adds on average 50ms to the query time for each OBD multiplexing change""" + if obd_multiplexing != self.current_obd_multiplexing: + self.current_obd_multiplexing = obd_multiplexing + self.total_time += 0.1 / 2 + + def fake_get_data(self, timeout): + self.total_time += timeout + return {} + + def _benchmark_brand(self, brand, num_pandas, mocker): + self.total_time = 0 + mocker.patch("opendbc.car.isotp_parallel_query.IsoTpParallelQuery.get_data", self.fake_get_data) + for _ in range(self.N): + # Treat each brand as the most likely (aka, the first) brand with OBD multiplexing initially on + self.current_obd_multiplexing = True + + t = time.perf_counter() + get_fw_versions(self.fake_can_recv, self.fake_can_send, self.fake_set_obd_multiplexing, brand, num_pandas=num_pandas) + self.total_time += time.perf_counter() - t + + return self.total_time / self.N + + def _assert_timing(self, avg_time, ref_time): + assert avg_time < ref_time + self.TOL + assert avg_time > ref_time - self.TOL, "Performance seems to have improved, update test refs." + + def test_startup_timing(self, subtests, mocker): + # Tests worse-case VIN query time and typical present ECU query time + vin_ref_times = {'worst': 1.6, 'best': 0.8} # best assumes we go through all queries to get a match + present_ecu_ref_time = 0.45 + + def fake_get_ecu_addrs(*_, timeout): + self.total_time += timeout + return set() + + self.total_time = 0.0 + mocker.patch("opendbc.car.fw_versions.get_ecu_addrs", fake_get_ecu_addrs) + for _ in range(self.N): + self.current_obd_multiplexing = True + get_present_ecus(self.fake_can_recv, self.fake_can_send, self.fake_set_obd_multiplexing, num_pandas=2) + self._assert_timing(self.total_time / self.N, present_ecu_ref_time) + print(f'get_present_ecus, query time={self.total_time / self.N} seconds') + + for name, args in (('worst', {}), ('best', {'retry': 1})): + with subtests.test(name=name): + self.total_time = 0.0 + mocker.patch("opendbc.car.isotp_parallel_query.IsoTpParallelQuery.get_data", self.fake_get_data) + for _ in range(self.N): + get_vin(self.fake_can_recv, self.fake_can_send, (0, 1), **args) + self._assert_timing(self.total_time / self.N, vin_ref_times[name]) + print(f'get_vin {name} case, query time={self.total_time / self.N} seconds') + + def test_fw_query_timing(self, subtests, mocker): + total_ref_time = {1: 7.4, 2: 8.0} + brand_ref_times = { + 1: { + 'gm': 1.0, + 'body': 0.1, + 'chrysler': 0.3, + 'ford': 1.5, + 'honda': 0.45, + 'hyundai': 0.65, + 'mazda': 0.1, + 'nissan': 0.8, + 'subaru': 0.65, + 'tesla': 0.1, + 'toyota': 0.7, + 'volkswagen': 0.65, + 'rivian': 0.3, + 'psa': 0.1, + }, + 2: { + 'ford': 1.6, + 'hyundai': 1.15, + } + } + + total_times = {1: 0.0, 2: 0.0} + for num_pandas in (1, 2): + for brand, config in FW_QUERY_CONFIGS.items(): + with subtests.test(brand=brand, num_pandas=num_pandas): + avg_time = self._benchmark_brand(brand, num_pandas, mocker) + total_times[num_pandas] += avg_time + avg_time = round(avg_time, 2) + + ref_time = brand_ref_times[num_pandas].get(brand) + if ref_time is None: + # ref time should be same as 1 panda if no aux queries + ref_time = brand_ref_times[num_pandas - 1][brand] + + self._assert_timing(avg_time, ref_time) + print(f'{brand=}, {num_pandas=}, {len(config.requests)=}, avg FW query time={avg_time} seconds') + + for num_pandas in (1, 2): + with subtests.test(brand='all_brands', num_pandas=num_pandas): + total_time = round(total_times[num_pandas], 2) + self._assert_timing(total_time, total_ref_time[num_pandas]) + print(f'all brands, total FW query time={total_time} seconds') + + def test_get_fw_versions(self, subtests, mocker): + # some coverage on IsoTpParallelQuery and panda UDS library + # TODO: replace this with full fingerprint simulation testing + # https://github.com/commaai/panda/pull/1329 + + def fake_carlog_exception(*args, **kwargs): + raise + + t = 0 + + def fake_monotonic(): + nonlocal t + t += 0.0001 + return t + + mocker.patch("opendbc.car.carlog.carlog.exception", fake_carlog_exception) + mocker.patch("time.monotonic", fake_monotonic) + for brand in FW_QUERY_CONFIGS.keys(): + with subtests.test(brand=brand): + get_fw_versions(self.fake_can_recv, self.fake_can_send, lambda obd: None, brand) diff --git a/opendbc_repo/opendbc/car/tests/test_lateral_limits.py b/opendbc_repo/opendbc/car/tests/test_lateral_limits.py new file mode 100755 index 0000000000..070da5d742 --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_lateral_limits.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +from collections import defaultdict +import importlib +from parameterized import parameterized_class +import pytest +import sys + +from opendbc.car import DT_CTRL +from opendbc.car.car_helpers import interfaces +from opendbc.car.interfaces import get_torque_params +from opendbc.car.lateral import ISO_LATERAL_ACCEL +from opendbc.car.values import PLATFORMS + +# ISO 11270 - allowed up jerk is strictly lower than recommended limits +MAX_LAT_JERK_UP = 2.5 # m/s^3 +MAX_LAT_JERK_DOWN = 5.0 # m/s^3 +MAX_LAT_JERK_UP_TOLERANCE = 0.5 # m/s^3 + +# jerk is measured over half a second +JERK_MEAS_T = 0.5 + + +@parameterized_class('car_model', [(c,) for c in sorted(PLATFORMS)]) +class TestLateralLimits: + car_model: str + + @classmethod + def setup_class(cls): + CarInterface = interfaces[cls.car_model] + CP = CarInterface.get_non_essential_params(cls.car_model) + + if cls.car_model == 'MOCK': + pytest.skip('Mock car') + + # TODO: test all platforms + if CP.steerControlType != 'torque': + pytest.skip() + + if CP.notCar: + pytest.skip() + + CarControllerParams = importlib.import_module(f'opendbc.car.{CP.brand}.values').CarControllerParams + cls.control_params = CarControllerParams(CP) + cls.torque_params = get_torque_params()[cls.car_model] + + @staticmethod + def calculate_0_5s_jerk(control_params, torque_params): + steer_step = control_params.STEER_STEP + max_lat_accel = torque_params['MAX_LAT_ACCEL_MEASURED'] + + # Steer up/down delta per 10ms frame, in percentage of max torque + steer_up_per_frame = control_params.STEER_DELTA_UP / control_params.STEER_MAX / steer_step + steer_down_per_frame = control_params.STEER_DELTA_DOWN / control_params.STEER_MAX / steer_step + + # Lateral acceleration reached in 0.5 seconds, clipping to max torque + accel_up_0_5_sec = min(steer_up_per_frame * JERK_MEAS_T / DT_CTRL, 1.0) * max_lat_accel + accel_down_0_5_sec = min(steer_down_per_frame * JERK_MEAS_T / DT_CTRL, 1.0) * max_lat_accel + + # Convert to m/s^3 + return accel_up_0_5_sec / JERK_MEAS_T, accel_down_0_5_sec / JERK_MEAS_T + + def test_jerk_limits(self): + up_jerk, down_jerk = self.calculate_0_5s_jerk(self.control_params, self.torque_params) + assert up_jerk <= MAX_LAT_JERK_UP + MAX_LAT_JERK_UP_TOLERANCE + assert down_jerk <= MAX_LAT_JERK_DOWN + + def test_max_lateral_accel(self): + assert self.torque_params["MAX_LAT_ACCEL_MEASURED"] <= ISO_LATERAL_ACCEL + + +class LatAccelReport: + car_model_jerks: defaultdict[str, dict[str, float]] = defaultdict(dict) + + def pytest_sessionfinish(self): + print(f"\n\n---- Lateral limit report ({len(PLATFORMS)} cars) ----\n") + + max_car_model_len = max([len(car_model) for car_model in self.car_model_jerks]) + for car_model, _jerks in sorted(self.car_model_jerks.items(), key=lambda i: i[1]['up_jerk'], reverse=True): + violation = _jerks["up_jerk"] > MAX_LAT_JERK_UP + MAX_LAT_JERK_UP_TOLERANCE or \ + _jerks["down_jerk"] > MAX_LAT_JERK_DOWN + violation_str = " - VIOLATION" if violation else "" + + print(f"{car_model:{max_car_model_len}} - up jerk: {round(_jerks['up_jerk'], 2):5} " + + f"m/s^3, down jerk: {round(_jerks['down_jerk'], 2):5} m/s^3{violation_str}") + + @pytest.fixture(scope="class", autouse=True) + def class_setup(self, request): + yield + cls = request.cls + if hasattr(cls, "control_params"): + up_jerk, down_jerk = TestLateralLimits.calculate_0_5s_jerk(cls.control_params, cls.torque_params) + self.car_model_jerks[cls.car_model] = {"up_jerk": up_jerk, "down_jerk": down_jerk} + + +if __name__ == '__main__': + sys.exit(pytest.main([__file__, '-n0', '--no-summary'], plugins=[LatAccelReport()])) # noqa: TID251 diff --git a/opendbc_repo/opendbc/car/tests/test_platform_configs.py b/opendbc_repo/opendbc/car/tests/test_platform_configs.py new file mode 100644 index 0000000000..1704621ddd --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_platform_configs.py @@ -0,0 +1,17 @@ +from opendbc.car.values import PLATFORMS + + +class TestPlatformConfigs: + def test_configs(self, subtests): + + for name, platform in PLATFORMS.items(): + with subtests.test(platform=str(platform)): + assert platform.config._frozen + + if platform != "MOCK": + assert len(platform.config.dbc_dict) > 0 + assert len(platform.config.platform_str) > 0 + + assert name == platform.config.platform_str + + assert platform.config.specs is not None diff --git a/opendbc_repo/opendbc/car/tests/test_routes.py b/opendbc_repo/opendbc/car/tests/test_routes.py new file mode 100644 index 0000000000..92176909db --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_routes.py @@ -0,0 +1,11 @@ +import pytest + +from opendbc.car.values import PLATFORMS +from opendbc.car.tests.routes import non_tested_cars, routes + + +@pytest.mark.parametrize("platform", PLATFORMS.keys()) +def test_test_route_present(platform): + tested_platforms = [r.car_model for r in routes] + assert platform in set(tested_platforms) | set(non_tested_cars), \ + f"Missing test route for {platform}. Add a route to opendbc/car/tests/routes.py" diff --git a/opendbc_repo/opendbc/car/tests/test_vehicle_model.py b/opendbc_repo/opendbc/car/tests/test_vehicle_model.py new file mode 100644 index 0000000000..b88a8dab4e --- /dev/null +++ b/opendbc_repo/opendbc/car/tests/test_vehicle_model.py @@ -0,0 +1,67 @@ +import pytest +import math + +import numpy as np + +from opendbc.car.honda.interface import CarInterface +from opendbc.car.honda.values import CAR +from opendbc.car.vehicle_model import VehicleModel, dyn_ss_sol, create_dyn_state_matrices + + +class TestVehicleModel: + def setup_method(self): + CP = CarInterface.get_non_essential_params(CAR.HONDA_CIVIC) + self.VM = VehicleModel(CP) + + def test_round_trip_yaw_rate(self): + # TODO: fix VM to work at zero speed + for u in np.linspace(1, 30, num=10): + for roll in np.linspace(math.radians(-20), math.radians(20), num=11): + for sa in np.linspace(math.radians(-20), math.radians(20), num=11): + yr = self.VM.yaw_rate(sa, u, roll) + new_sa = self.VM.get_steer_from_yaw_rate(yr, u, roll) + + assert sa == pytest.approx(new_sa) + + def test_dyn_ss_sol_against_yaw_rate(self): + """Verify that the yaw_rate helper function matches the results + from the state space model.""" + + for roll in np.linspace(math.radians(-20), math.radians(20), num=11): + for u in np.linspace(1, 30, num=10): + for sa in np.linspace(math.radians(-20), math.radians(20), num=11): + + # Compute yaw rate based on state space model + _, yr1 = dyn_ss_sol(sa, u, roll, self.VM) + + # Compute yaw rate using direct computations + yr2 = self.VM.yaw_rate(sa, u, roll) + assert float(yr1[0]) == pytest.approx(yr2) + + def test_syn_ss_sol_simulate(self): + """Verifies that dyn_ss_sol matches a simulation""" + + for roll in np.linspace(math.radians(-20), math.radians(20), num=11): + for u in np.linspace(1, 30, num=10): + A, B = create_dyn_state_matrices(u, self.VM) + + # Convert to discrete time system + dt = 0.01 + top = np.hstack((A, B)) + full = np.vstack((top, np.zeros_like(top))) * dt + Md = sum([np.linalg.matrix_power(full, k) / math.factorial(k) for k in range(25)]) + Ad = Md[:A.shape[0], :A.shape[1]] + Bd = Md[:A.shape[0], A.shape[1]:] + + for sa in np.linspace(math.radians(-20), math.radians(20), num=11): + inp = np.array([[sa], [roll]]) + + # Simulate for 1 second + x1 = np.zeros((2, 1)) + for _ in range(100): + x1 = Ad @ x1 + Bd @ inp + + # Compute steady state solution directly + x2 = dyn_ss_sol(sa, u, roll, self.VM) + + np.testing.assert_almost_equal(x1, x2, decimal=3) diff --git a/opendbc_repo/opendbc/car/torque_data/override.toml b/opendbc_repo/opendbc/car/torque_data/override.toml new file mode 100644 index 0000000000..bcd99a23a5 --- /dev/null +++ b/opendbc_repo/opendbc/car/torque_data/override.toml @@ -0,0 +1,100 @@ +legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] +### angle control +# Nissan appears to have torque +"NISSAN_XTRAIL" = [nan, 1.5, nan] +"NISSAN_ALTIMA" = [nan, 1.5, nan] +"NISSAN_LEAF_IC" = [nan, 1.5, nan] +"NISSAN_LEAF" = [nan, 1.5, nan] +"NISSAN_ROGUE" = [nan, 1.5, nan] + +# PSA angle based controllers +"PSA_PEUGEOT_208" = [nan, 2.0, nan] + +# New subarus angle based controllers +"SUBARU_FORESTER_2022" = [nan, 3.0, nan] +"SUBARU_OUTBACK_2023" = [nan, 3.0, nan] +"SUBARU_ASCENT_2023" = [nan, 3.0, nan] + +# Toyota LTA also has torque +"TOYOTA_RAV4_TSS2_2023" = [nan, 3.0, nan] + +# Tesla angle based controllers +"TESLA_MODEL_3" = [nan, 2.5, nan] +"TESLA_MODEL_Y" = [nan, 2.5, nan] +"TESLA_MODEL_X" = [nan, 2.5, nan] + +# Guess +"FORD_BRONCO_SPORT_MK1" = [nan, 1.5, nan] +"FORD_ESCAPE_MK4" = [nan, 1.5, nan] +"FORD_ESCAPE_MK4_5" = [nan, 1.5, nan] +"FORD_EXPLORER_MK6" = [nan, 1.5, nan] +"FORD_EXPEDITION_MK4" = [nan, 1.5, nan] +"FORD_F_150_MK14" = [nan, 1.5, nan] +"FORD_FOCUS_MK4" = [nan, 1.5, nan] +"FORD_MAVERICK_MK1" = [nan, 1.5, nan] +"FORD_F_150_LIGHTNING_MK1" = [nan, 1.5, nan] +"FORD_MUSTANG_MACH_E_MK1" = [nan, 1.5, nan] +"FORD_RANGER_MK2" = [nan, 1.5, nan] +### + +# No steering wheel +"COMMA_BODY" = [nan, 1000, nan] + +# Totally new cars +"RAM_1500_5TH_GEN" = [2.0, 2.0, 0.05] +"RAM_HD_5TH_GEN" = [1.4, 1.4, 0.05] +"SUBARU_OUTBACK" = [2.0, 1.5, 0.2] +"CADILLAC_ESCALADE" = [1.899999976158142, 1.842270016670227, 0.1120000034570694] +"CADILLAC_ESCALADE_ESV_2019" = [1.15, 1.3, 0.2] +"CADILLAC_XT4" = [1.45, 1.6, 0.2] +"CHEVROLET_BOLT_EUV" = [1.0, 2.0, 0.175] +"CHEVROLET_SILVERADO" = [1.9, 1.9, 0.112] +"CHEVROLET_TRAILBLAZER" = [1.33, 1.9, 0.16] +"CHEVROLET_TRAVERSE" = [1.33, 1.33, 0.18] +"CHEVROLET_EQUINOX" = [2.5, 2.5, 0.05] +"CHEVROLET_VOLT_2019" = [1.4, 1.4, 0.16] +"VOLKSWAGEN_CADDY_MK3" = [1.2, 1.2, 0.1] +"VOLKSWAGEN_PASSAT_NMS" = [2.5, 2.5, 0.1] +"VOLKSWAGEN_SHARAN_MK2" = [2.5, 2.5, 0.1] +"HYUNDAI_SANTA_CRUZ_1ST_GEN" = [2.7, 2.7, 0.1] +"KIA_SPORTAGE_5TH_GEN" = [2.6, 2.6, 0.1] +"GENESIS_GV70_1ST_GEN" = [2.42, 2.42, 0.1] +"GENESIS_GV60_EV_1ST_GEN" = [2.5, 2.5, 0.1] +"GMC_YUKON" = [1.2, 2.5, 0.26] +"KIA_SORENTO_4TH_GEN" = [2.5, 2.5, 0.1] +"KIA_SORENTO_HEV_4TH_GEN" = [2.5, 2.5, 0.1] +"KIA_NIRO_HEV_2ND_GEN" = [2.42, 2.5, 0.12] +"KIA_NIRO_EV_2ND_GEN" = [2.05, 2.5, 0.14] +"GENESIS_GV80" = [2.5, 2.5, 0.1] +"KIA_CARNIVAL_4TH_GEN" = [1.75, 1.75, 0.15] +"GMC_ACADIA" = [1.6, 1.6, 0.2] +"LEXUS_IS_TSS2" = [2.0, 2.0, 0.1] +"HYUNDAI_KONA_EV_2ND_GEN" = [2.5, 2.5, 0.1] +"HYUNDAI_IONIQ_6" = [2.5, 2.5, 0.005] +"HYUNDAI_AZERA_6TH_GEN" = [1.8, 1.8, 0.1] +"HYUNDAI_AZERA_HEV_6TH_GEN" = [1.8, 1.8, 0.1] +"KIA_K8_HEV_1ST_GEN" = [2.5, 2.5, 0.1] +"HYUNDAI_CUSTIN_1ST_GEN" = [2.5, 2.5, 0.1] +"LEXUS_GS_F" = [2.5, 2.5, 0.08] +"HYUNDAI_STARIA_4TH_GEN" = [1.8, 2.0, 0.15] +"GENESIS_GV70_ELECTRIFIED_1ST_GEN" = [1.9, 1.9, 0.09] +"GENESIS_G80_2ND_GEN_FL" = [2.5819356441497803, 2.5, 0.11244568973779678] +# Note that some Rivians achieve significantly less lateral acceleration than this +"RIVIAN_R1_GEN1" = [2.8, 2.5, 0.07] +"HYUNDAI_NEXO_1ST_GEN" = [2.5, 2.5, 0.1] +"HONDA_ACCORD_11G" = [1.35, 1.35, 0.17] +"HONDA_PILOT_4G" = [1.25, 1.25, 0.21] +"HONDA_PASSPORT_4G" = [1.2, 1.2, 0.16] +"ACURA_MDX_4G_MMR" = [1.25, 1.25, 0.15] +"HONDA_CRV_6G" = [1.3, 1.3, 0.2] +"HONDA_CITY_7G" = [1.2, 1.2, 0.23] +"HONDA_ODYSSEY_5G_MMR" = [0.9, 0.9, 0.2] +"HONDA_NBOX_2G" = [1.2, 1.2, 0.2] +"ACURA_TLX_2G" = [1.2, 1.2, 0.15] + +# Dashcam or fallback configured as ideal car +"MOCK" = [10.0, 10, 0.0] + +# Manually checked +"HONDA_CIVIC_2022" = [2.5, 1.2, 0.15] +"HONDA_HRV_3G" = [2.5, 1.2, 0.2] diff --git a/opendbc_repo/opendbc/car/torque_data/params.toml b/opendbc_repo/opendbc/car/torque_data/params.toml new file mode 100644 index 0000000000..fde2ca221d --- /dev/null +++ b/opendbc_repo/opendbc/car/torque_data/params.toml @@ -0,0 +1,82 @@ +legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] +"ACURA_ILX" = [1.524988973896102, 0.519011053086259, 0.34236219253028] +"ACURA_RDX" = [0.9987728568686902, 0.5323765166196301, 0.303218805715844] +"ACURA_RDX_3G" = [1.4314459806646749, 0.33874701282109954, 0.18048847083897598] +"AUDI_A3_MK3" = [1.5122414863077502, 1.7443517531719404, 0.15194151892450905] +"AUDI_Q3_MK2" = [1.4439223359448605, 1.2254955789112076, 0.1413798895978097] +"CHEVROLET_VOLT" = [1.5961527626411784, 1.8422651988094612, 0.1572393918005158] +"CHRYSLER_PACIFICA_2018" = [2.07140, 1.3366521181047952, 0.13776367250652022] +"CHRYSLER_PACIFICA_2020" = [1.86206, 1.509076559398423, 0.14328246159386085] +"CHRYSLER_PACIFICA_2018_HYBRID" = [2.08887, 1.2943025830995154, 0.114818] +"CHRYSLER_PACIFICA_2019_HYBRID" = [1.90120, 1.1958788168371808, 0.131520] +"GENESIS_G70" = [3.8520195946707947, 2.354697063349854, 0.06830285485626221] +"HONDA_ACCORD" = [1.6893333799149202, 0.3246749081720698, 0.2120497022936265] +"HONDA_CIVIC_BOSCH" = [1.691708637466905, 0.40132900729454185, 0.25460295304024094] +"HONDA_CIVIC" = [1.6528895627785531, 0.4018518740819229, 0.25458812851328544] +"HONDA_CRV" = [0.7667141440182675, 0.5927571534745969, 0.40909087636157127] +"HONDA_CRV_5G" = [2.01323205142022, 0.2700612209345081, 0.2238412881331528] +"HONDA_CRV_HYBRID" = [2.072034634644233, 0.7152085160516978, 0.20237105008376083] +"HONDA_FIT" = [1.5719981427109775, 0.5712761407108976, 0.110773383324281] +"HONDA_HRV" = [2.0661212805710205, 0.7521343418694775, 0.17760375789242094] +"HONDA_INSIGHT" = [1.5201671214069354, 0.5660229120683284, 0.25808042580281876] +"HONDA_ODYSSEY" = [1.8774809275211801, 0.8394431662987996, 0.2096978613792822] +"HONDA_PILOT" = [1.7262026201812795, 0.9470005614967523, 0.21351430733218763] +"HONDA_RIDGELINE" = [1.4146525028237624, 0.7356572861629564, 0.23307177552211328] +"HYUNDAI_ELANTRA_2021" = [3.169, 2.1259108157250735, 0.0819] +"HYUNDAI_GENESIS" = [2.7807965280270794, 2.325, 0.0984484465421171] +"HYUNDAI_IONIQ_5" = [3.172929, 2.713050, 0.096019] +"HYUNDAI_IONIQ_EV_LTD" = [1.7662975472852054, 1.613755614526594, 0.17087579756306276] +"HYUNDAI_IONIQ_PHEV" = [3.2928700076638537, 2.1193482926455656, 0.12463700961468778] +"HYUNDAI_IONIQ_PHEV_2019" = [2.970807902012267, 1.6312321830002083, 0.1088964990357482] +"HYUNDAI_KONA_EV" = [3.078814714619148, 2.307336938253934, 0.12359762054065548] +"HYUNDAI_PALISADE" = [2.544642494803999, 1.8721703683337008, 0.1301424599248651] +"HYUNDAI_SANTA_FE" = [3.0787027729757632, 2.6173437483495565, 0.1207019341823945] +"HYUNDAI_SANTA_FE_HEV_2022" = [3.501877602644835, 2.729064118456137, 0.10384068104538963] +"HYUNDAI_SANTA_FE_PHEV_2022" = [1.6953050513611045, 1.5837614296206861, 0.12672855941458458] +"HYUNDAI_SONATA_LF" = [2.2200457811703953, 1.2967330275895228, 0.14039920986586393] +"HYUNDAI_SONATA" = [2.9638737459977467, 2.1259108157250735, 0.07813665616927593] +"HYUNDAI_SONATA_HYBRID" = [2.8990264092395734, 2.061410192222139, 0.0899805488717382] +"HYUNDAI_TUCSON_4TH_GEN" = [2.960174, 2.860284, 0.108745] +"JEEP_GRAND_CHEROKEE_2019" = [2.30972, 1.289689569171081, 0.117048] +"JEEP_GRAND_CHEROKEE" = [2.27116, 1.4057367824262523, 0.11725947414922003] +"KIA_EV6" = [3.2, 2.093457, 0.005] +"KIA_K5_2021" = [2.405339728085138, 1.460032270828705, 0.11650989850813716] +"KIA_NIRO_EV" = [2.9215954981365337, 2.1500583840260044, 0.09236802474810267] +"KIA_SORENTO" = [2.464854685101844, 1.5335274218367956, 0.12056170567599558] +"KIA_STINGER" = [2.7499043387418967, 1.849652021986449, 0.12048334239559202] +"LEXUS_ES_TSS2" = [2.0357564999999997, 1.999082295195227, 0.101533] +"LEXUS_NX" = [2.3525924753753613, 1.9731412277641067, 0.15168101064205927] +"LEXUS_NX_TSS2" = [2.4331999786982936, 2.1045680431705414, 0.14099899317761067] +"LEXUS_RX" = [1.6430539050086406, 1.181960058934143, 0.19768806040843034] +"LEXUS_RX_TSS2" = [1.5375561442049257, 1.343166476215164, 0.1931062001527557] +"MAZDA_CX9_2021" = [1.7601682915983443, 1.0889677335154337, 0.17713792194297195] +"SKODA_SUPERB_MK3" = [1.166437404652981, 1.1686163012668165, 0.12194533036948708] +"SUBARU_FORESTER" = [3.6617001649776793, 2.342197172531713, 0.11075960785398745] +"SUBARU_IMPREZA" = [1.0670704910352047, 0.8234374840709592, 0.20986563268614938] +"SUBARU_IMPREZA_2020" = [2.6068223389108303, 2.134872342760203, 0.15261513193561627] +"TOYOTA_AVALON" = [2.5185770183845646, 1.7153346784214922, 0.10603968787111022] +"TOYOTA_AVALON_2019" = [1.7036141952825095, 1.239619084240008, 0.08459830394899492] +"TOYOTA_AVALON_TSS2" = [2.3154403649717357, 2.7777922854327124, 0.11453999639164605] +"TOYOTA_CHR" = [1.5591084333664578, 1.271271459066948, 0.20259087058453193] +"TOYOTA_CHR_TSS2" = [1.7678810166088303, 1.3742176337919942, 0.2319674583741509] +"TOYOTA_CAMRY" = [2.0568162685952505, 1.7576185169559122, 0.108878753] +"TOYOTA_CAMRY_TSS2" = [2.3548324999999997, 2.368900128946771, 0.118436] +"TOYOTA_COROLLA" = [3.117154369115421, 1.8438132575043773, 0.12289685869250652] +"TOYOTA_COROLLA_TSS2" = [1.991132339206426, 1.868866242720403, 0.19570063298031432] +"TOYOTA_HIGHLANDER" = [1.8108348718624456, 1.6348421600679828, 0.15972686105120398] +"TOYOTA_HIGHLANDER_TSS2" = [1.9617570834136164, 1.8611643317268927, 0.14519673256119725] +"TOYOTA_MIRAI" = [2.506899832157829, 1.7417213930750164, 0.20182618449440565] +"TOYOTA_PRIUS" = [1.60, 1.5023147650693636, 0.151515] +"TOYOTA_PRIUS_TSS2" = [1.972600, 1.9104337425537743, 0.170968] +"TOYOTA_RAV4" = [2.085695074355425, 2.2142832316984733, 0.13339165270103975] +"TOYOTA_RAV4_TSS2" = [2.279239424615458, 2.087101966779332, 0.13682208413446817] +"TOYOTA_RAV4H" = [1.9796257271652042, 1.7503987331707576, 0.14628860048885406] +"TOYOTA_RAV4_TSS2_2022" = [2.241883248393209, 1.9304407208090029, 0.112174] +"TOYOTA_SIENNA" = [1.689726, 1.3208264576110418, 0.140456] +"TOYOTA_YARIS" = [2.22984, 1.86145, 0.168189] +"VOLKSWAGEN_ARTEON_MK1" = [1.45136518053819, 1.3639364049316804, 0.23806361745695032] +"VOLKSWAGEN_ATLAS_MK1" = [1.4677006726964945, 1.6733266634075656, 0.12959584092073367] +"VOLKSWAGEN_GOLF_MK7" = [1.3750394140491293, 1.5814743077200641, 0.2018321939386586] +"VOLKSWAGEN_JETTA_MK7" = [1.2271623034089392, 1.216955117387, 0.19437384688370712] +"VOLKSWAGEN_PASSAT_MK8" = [1.3432120736752917, 1.7087275587362314, 0.19444383787326647] +"VOLKSWAGEN_TIGUAN_MK2" = [0.9711965500094828, 1.0001565939459098, 0.1465626137072916] diff --git a/opendbc_repo/opendbc/car/torque_data/substitute.toml b/opendbc_repo/opendbc/car/torque_data/substitute.toml new file mode 100644 index 0000000000..db26c1a01d --- /dev/null +++ b/opendbc_repo/opendbc/car/torque_data/substitute.toml @@ -0,0 +1,87 @@ +legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] +"MAZDA_3" = "MAZDA_CX9_2021" +"MAZDA_6" = "MAZDA_CX9_2021" +"MAZDA_CX5" = "MAZDA_CX9_2021" +"MAZDA_CX5_2022" = "MAZDA_CX9_2021" +"MAZDA_CX9" = "MAZDA_CX9_2021" + +"DODGE_DURANGO" = "CHRYSLER_PACIFICA_2020" + +"TOYOTA_ALPHARD_TSS2" = "TOYOTA_SIENNA" +"TOYOTA_PRIUS_V" = "TOYOTA_PRIUS" +"TOYOTA_RAV4_PRIME" = "TOYOTA_RAV4_TSS2" +"TOYOTA_SIENNA_4TH_GEN" = "TOYOTA_RAV4_TSS2" +"LEXUS_IS" = "LEXUS_NX" +"LEXUS_CTH" = "LEXUS_NX" +"LEXUS_ES" = "TOYOTA_CAMRY" +"LEXUS_RC" = "LEXUS_NX_TSS2" +"LEXUS_RC_TSS2" = "LEXUS_NX_TSS2" +"LEXUS_LC_TSS2" = "LEXUS_NX_TSS2" + +"KIA_OPTIMA_G4" = "HYUNDAI_SONATA" +"KIA_OPTIMA_G4_FL" = "HYUNDAI_SONATA" +"KIA_OPTIMA_H" = "HYUNDAI_SONATA" +"KIA_OPTIMA_H_G4_FL" = "HYUNDAI_SONATA" +"KIA_FORTE" = "HYUNDAI_SONATA" +"KIA_CEED" = "HYUNDAI_SONATA" +"KIA_SELTOS" = "HYUNDAI_SONATA" +"KIA_NIRO_PHEV" = "KIA_NIRO_EV" +"KIA_NIRO_PHEV_2022" = "KIA_NIRO_EV" +"KIA_NIRO_HEV_2021" = "KIA_NIRO_EV" +"HYUNDAI_VELOSTER" = "HYUNDAI_SONATA_LF" +"HYUNDAI_KONA" = "HYUNDAI_KONA_EV" +"HYUNDAI_KONA_2022" = "HYUNDAI_KONA_EV" +"HYUNDAI_KONA_HEV" = "HYUNDAI_KONA_EV" +"HYUNDAI_KONA_EV_2022" = "HYUNDAI_KONA_EV" +"HYUNDAI_IONIQ" = "HYUNDAI_IONIQ_PHEV_2019" +"HYUNDAI_IONIQ_HEV_2022" = "HYUNDAI_IONIQ_PHEV_2019" +"HYUNDAI_IONIQ_EV_2020" = "HYUNDAI_IONIQ_PHEV_2019" +"HYUNDAI_ELANTRA" = "HYUNDAI_SONATA_LF" +"HYUNDAI_ELANTRA_GT_I30" = "HYUNDAI_SONATA_LF" +"HYUNDAI_ELANTRA_HEV_2021" = "HYUNDAI_SONATA" +"HYUNDAI_TUCSON" = "HYUNDAI_SANTA_FE" +"HYUNDAI_SANTA_FE_2022" = "HYUNDAI_SANTA_FE_HEV_2022" +"KIA_K5_HEV_2020" = "KIA_K5_2021" +"KIA_STINGER_2022" = "KIA_STINGER" +"GENESIS_G90" = "GENESIS_G70" +"GENESIS_G80" = "GENESIS_G70" +"GENESIS_G70_2020" = "HYUNDAI_SONATA" + +"HONDA_FREED" = "HONDA_ODYSSEY" +"HONDA_CRV_EU" = "HONDA_CRV" +"HONDA_CIVIC_BOSCH_DIESEL" = "HONDA_CIVIC_BOSCH" +"HONDA_E" = "HONDA_CIVIC_BOSCH" + +"BUICK_LACROSSE" = "CHEVROLET_VOLT" +"BUICK_REGAL" = "CHEVROLET_VOLT" +"CADILLAC_ESCALADE_ESV" = "CHEVROLET_VOLT" +"CADILLAC_ATS" = "CHEVROLET_VOLT" +"CHEVROLET_MALIBU" = "CHEVROLET_VOLT" +"HOLDEN_ASTRA" = "CHEVROLET_VOLT" + +"SKODA_FABIA_MK4" = "VOLKSWAGEN_GOLF_MK7" +"SKODA_OCTAVIA_MK3" = "SKODA_SUPERB_MK3" +"SKODA_KODIAQ_MK1" = "SKODA_SUPERB_MK3" +"SKODA_KAROQ_MK1" = "SKODA_SUPERB_MK3" +"SKODA_KAMIQ_MK1" = "SKODA_SUPERB_MK3" +"VOLKSWAGEN_CRAFTER_MK2" = "VOLKSWAGEN_TIGUAN_MK2" +"VOLKSWAGEN_TROC_MK1" = "VOLKSWAGEN_TIGUAN_MK2" +"VOLKSWAGEN_TCROSS_MK1" = "VOLKSWAGEN_TIGUAN_MK2" +"VOLKSWAGEN_TOURAN_MK2" = "VOLKSWAGEN_TIGUAN_MK2" +"VOLKSWAGEN_TRANSPORTER_T61" = "VOLKSWAGEN_TIGUAN_MK2" +"AUDI_Q2_MK1" = "VOLKSWAGEN_TIGUAN_MK2" +"VOLKSWAGEN_TAOS_MK1" = "VOLKSWAGEN_TIGUAN_MK2" +"VOLKSWAGEN_POLO_MK6" = "VOLKSWAGEN_GOLF_MK7" +"SEAT_ATECA_MK1" = "VOLKSWAGEN_GOLF_MK7" +"VOLKSWAGEN_JETTA_MK6" = "VOLKSWAGEN_PASSAT_NMS" + +"SUBARU_CROSSTREK_HYBRID" = "SUBARU_IMPREZA_2020" +"SUBARU_FORESTER_HYBRID" = "SUBARU_IMPREZA_2020" +"SUBARU_LEGACY" = "SUBARU_OUTBACK" + +# Old subarus don't have much data guessing it's like low torque impreza" +"SUBARU_OUTBACK_PREGLOBAL_2018" = "SUBARU_IMPREZA" +"SUBARU_OUTBACK_PREGLOBAL" = "SUBARU_IMPREZA" +"SUBARU_FORESTER_PREGLOBAL" = "SUBARU_IMPREZA" +"SUBARU_LEGACY_PREGLOBAL" = "SUBARU_IMPREZA" +"SUBARU_ASCENT" = "SUBARU_FORESTER" diff --git a/opendbc_repo/opendbc/car/toyota/__init__.py b/opendbc_repo/opendbc/car/toyota/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/toyota/carcontroller.py b/opendbc_repo/opendbc/car/toyota/carcontroller.py new file mode 100644 index 0000000000..34156976fc --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/carcontroller.py @@ -0,0 +1,304 @@ +import math +import numpy as np +from opendbc.car import Bus, make_tester_present_msg, rate_limit, structs, ACCELERATION_DUE_TO_GRAVITY, DT_CTRL +from opendbc.car.lateral import apply_meas_steer_torque_limits, apply_std_steer_angle_limits, common_fault_avoidance +from opendbc.car.can_definitions import CanData +from opendbc.car.carlog import carlog +from opendbc.car.common.filter_simple import FirstOrderFilter +from opendbc.car.common.pid import PIDController +from opendbc.car.secoc import add_mac, build_sync_mac +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.toyota import toyotacan +from opendbc.car.toyota.values import CAR, STATIC_DSU_MSGS, NO_STOP_TIMER_CAR, TSS2_CAR, \ + CarControllerParams, ToyotaFlags, \ + UNSUPPORTED_DSU_CAR +from opendbc.can import CANPacker + +Ecu = structs.CarParams.Ecu +LongCtrlState = structs.CarControl.Actuators.LongControlState +SteerControlType = structs.CarParams.SteerControlType +VisualAlert = structs.CarControl.HUDControl.VisualAlert + +# The up limit allows the brakes/gas to unwind quickly leaving a stop, +# the down limit roughly matches the rate of ACCEL_NET, reducing PCM compensation windup +ACCEL_WINDUP_LIMIT = 4.0 * DT_CTRL * 3 # m/s^2 / frame +ACCEL_WINDDOWN_LIMIT = -4.0 * DT_CTRL * 3 # m/s^2 / frame +ACCEL_PID_UNWIND = 0.03 * DT_CTRL * 3 # m/s^2 / frame + +MAX_PITCH_COMPENSATION = 1.5 # m/s^2 + +# LKA limits +# EPS faults if you apply torque while the steering rate is above 100 deg/s for too long +MAX_STEER_RATE = 100 # deg/s +MAX_STEER_RATE_FRAMES = 18 # tx control frames needed before torque can be cut + +# EPS allows user torque above threshold for 50 frames before permanently faulting +MAX_USER_TORQUE = 500 + + +def get_long_tune(CP, params): + if CP.carFingerprint in TSS2_CAR: + kiBP = [2., 5.] + kiV = [0.5, 0.25] + else: + kiBP = [0., 5., 35.] + kiV = [3.6, 2.4, 1.5] + + return PIDController(0.0, (kiBP, kiV), k_f=1.0, + pos_limit=params.ACCEL_MAX, neg_limit=params.ACCEL_MIN, + rate=1 / (DT_CTRL * 3)) + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.params = CarControllerParams(self.CP) + self.last_torque = 0 + self.last_angle = 0 + self.alert_active = False + self.last_standstill = False + self.standstill_req = False + self.permit_braking = True + self.steer_rate_counter = 0 + self.distance_button = 0 + + # *** start long control state *** + self.long_pid = get_long_tune(self.CP, self.params) + self.aego = FirstOrderFilter(0.0, 0.25, DT_CTRL * 3) + self.pitch = FirstOrderFilter(0, 0.25, DT_CTRL) + self.pitch_slow = FirstOrderFilter(0, 1.5, DT_CTRL) + + self.accel = 0 + self.prev_accel = 0 + # *** end long control state *** + + self.packer = CANPacker(dbc_names[Bus.pt]) + + self.secoc_lka_message_counter = 0 + self.secoc_lta_message_counter = 0 + self.secoc_prev_reset_counter = 0 + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + stopping = actuators.longControlState == LongCtrlState.stopping + hud_control = CC.hudControl + pcm_cancel_cmd = CC.cruiseControl.cancel + lat_active = CC.latActive and abs(CS.out.steeringTorque) < MAX_USER_TORQUE + + if len(CC.orientationNED) == 3: + self.pitch.update(CC.orientationNED[1]) + self.pitch_slow.update(CC.orientationNED[1]) + + # *** control msgs *** + can_sends = [] + + # *** handle secoc reset counter increase *** + if self.CP.flags & ToyotaFlags.SECOC.value: + if CS.secoc_synchronization['RESET_CNT'] != self.secoc_prev_reset_counter: + self.secoc_lka_message_counter = 0 + self.secoc_lta_message_counter = 0 + self.secoc_prev_reset_counter = CS.secoc_synchronization['RESET_CNT'] + + expected_mac = build_sync_mac(self.secoc_key, int(CS.secoc_synchronization['TRIP_CNT']), int(CS.secoc_synchronization['RESET_CNT'])) + if int(CS.secoc_synchronization['AUTHENTICATOR']) != expected_mac: + carlog.error("SecOC synchronization MAC mismatch, wrong key?") + + # *** steer torque *** + new_torque = int(round(actuators.torque * self.params.STEER_MAX)) + apply_torque = apply_meas_steer_torque_limits(new_torque, self.last_torque, CS.out.steeringTorqueEps, self.params) + + # >100 degree/sec steering fault prevention + self.steer_rate_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringRateDeg) >= MAX_STEER_RATE, lat_active, + self.steer_rate_counter, MAX_STEER_RATE_FRAMES) + + if not lat_active: + apply_torque = 0 + + # *** steer angle *** + if self.CP.steerControlType == SteerControlType.angle: + # If using LTA control, disable LKA and set steering angle command + apply_torque = 0 + apply_steer_req = False + if self.frame % 2 == 0: + # EPS uses the torque sensor angle to control with, offset to compensate + apply_angle = actuators.steeringAngleDeg + CS.out.steeringAngleOffsetDeg + + # Angular rate limit based on speed + self.last_angle = apply_std_steer_angle_limits(apply_angle, self.last_angle, CS.out.vEgoRaw, + CS.out.steeringAngleDeg + CS.out.steeringAngleOffsetDeg, + CC.latActive, self.params.ANGLE_LIMITS) + + self.last_torque = apply_torque + + # toyota can trace shows STEERING_LKA at 42Hz, with counter adding alternatively 1 and 2; + # sending it at 100Hz seem to allow a higher rate limit, as the rate limit seems imposed + # on consecutive messages + steer_command = toyotacan.create_steer_command(self.packer, apply_torque, apply_steer_req) + if self.CP.flags & ToyotaFlags.SECOC.value: + # TODO: check if this slow and needs to be done by the CANPacker + steer_command = add_mac(self.secoc_key, + int(CS.secoc_synchronization['TRIP_CNT']), + int(CS.secoc_synchronization['RESET_CNT']), + self.secoc_lka_message_counter, + steer_command) + self.secoc_lka_message_counter += 1 + can_sends.append(steer_command) + + # STEERING_LTA does not seem to allow more rate by sending faster, and may wind up easier + if self.frame % 2 == 0 and self.CP.carFingerprint in TSS2_CAR: + lta_active = lat_active and self.CP.steerControlType == SteerControlType.angle + # cut steering torque with TORQUE_WIND_DOWN when either EPS torque or driver torque is above + # the threshold, to limit max lateral acceleration and for driver torque blending respectively. + full_torque_condition = (abs(CS.out.steeringTorqueEps) < self.params.STEER_MAX and + abs(CS.out.steeringTorque) < self.params.MAX_LTA_DRIVER_TORQUE_ALLOWANCE) + + # TORQUE_WIND_DOWN at 0 ramps down torque at roughly the max down rate of 1500 units/sec + torque_wind_down = 100 if lta_active and full_torque_condition else 0 + can_sends.append(toyotacan.create_lta_steer_command(self.packer, self.CP.steerControlType, self.last_angle, + lta_active, self.frame // 2, torque_wind_down)) + + if self.CP.flags & ToyotaFlags.SECOC.value: + lta_steer_2 = toyotacan.create_lta_steer_command_2(self.packer, self.frame // 2) + lta_steer_2 = add_mac(self.secoc_key, + int(CS.secoc_synchronization['TRIP_CNT']), + int(CS.secoc_synchronization['RESET_CNT']), + self.secoc_lta_message_counter, + lta_steer_2) + self.secoc_lta_message_counter += 1 + can_sends.append(lta_steer_2) + + # *** gas and brake *** + + # 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): + self.standstill_req = True + if CS.pcm_acc_status != 8: + # pcm entered standstill or it's disabled + self.standstill_req = False + + self.last_standstill = CS.out.standstill + + # handle UI messages + fcw_alert = hud_control.visualAlert == VisualAlert.fcw + steer_alert = hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw) + lead = hud_control.leadVisible or CS.out.vEgo < 12. # at low speed we always assume the lead is present so ACC can be engaged + + if self.CP.openpilotLongitudinalControl: + if self.frame % 3 == 0: + # 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: + desired_distance = 4 - hud_control.leadDistanceBars + if CS.out.cruiseState.enabled and CS.pcm_follow_distance != desired_distance: + self.distance_button = not self.distance_button + else: + self.distance_button = 0 + + # internal PCM gas command can get stuck unwinding from negative accel so we apply a generous rate limit + pcm_accel_cmd = actuators.accel + if CC.longActive: + pcm_accel_cmd = rate_limit(pcm_accel_cmd, self.prev_accel, ACCEL_WINDDOWN_LIMIT, ACCEL_WINDUP_LIMIT) + self.prev_accel = pcm_accel_cmd + + # calculate amount of acceleration PCM should apply to reach target, given pitch. + # clipped to only include downhill angles, avoids erroneously unsetting PERMIT_BRAKING when stopping on uphills + accel_due_to_pitch = math.sin(min(self.pitch.x, 0.0)) * ACCELERATION_DUE_TO_GRAVITY + # TODO: on uphills this sometimes sets PERMIT_BRAKING low not considering the creep force + net_acceleration_request = pcm_accel_cmd + accel_due_to_pitch + + # GVC does not overshoot ego acceleration when starting from stop, but still has a similar delay + if not self.CP.flags & ToyotaFlags.SECOC.value: + a_ego_blended = float(np.interp(CS.out.vEgo, [1.0, 2.0], [CS.gvc, CS.out.aEgo])) + else: + a_ego_blended = CS.out.aEgo + + # wind down integral when approaching target for step changes and smooth ramps to reduce overshoot + prev_aego = self.aego.x + self.aego.update(a_ego_blended) + j_ego = (self.aego.x - prev_aego) / (DT_CTRL * 3) + + future_t = float(np.interp(CS.out.vEgo, [2., 5.], [0.25, 0.5])) + a_ego_future = a_ego_blended + j_ego * future_t + + if CC.longActive: + # constantly slowly unwind integral to recover from large temporary errors + self.long_pid.i -= ACCEL_PID_UNWIND * float(np.sign(self.long_pid.i)) + + error_future = pcm_accel_cmd - a_ego_future + + if not stopping: + # Toyota's PCM slowly responds to changes in pitch. On change, we amplify our + # acceleration request to compensate for the undershoot and following overshoot + high_pass_pitch = self.pitch.x - self.pitch_slow.x + pitch_compensation = float(np.clip(math.sin(high_pass_pitch) * ACCELERATION_DUE_TO_GRAVITY, + -MAX_PITCH_COMPENSATION, MAX_PITCH_COMPENSATION)) + pcm_accel_cmd += pitch_compensation + + pcm_accel_cmd = self.long_pid.update(error_future, + speed=CS.out.vEgo, + feedforward=pcm_accel_cmd, + freeze_integrator=actuators.longControlState != LongCtrlState.pid) + else: + self.long_pid.reset() + + # Along with rate limiting positive jerk above, this greatly improves gas response time + # Consider the net acceleration request that the PCM should be applying (pitch included) + net_acceleration_request_min = min(actuators.accel + accel_due_to_pitch, net_acceleration_request) + if net_acceleration_request_min < 0.2 or stopping or not CC.longActive: + self.permit_braking = True + elif net_acceleration_request_min > 0.3: + self.permit_braking = False + + pcm_accel_cmd = float(np.clip(pcm_accel_cmd, self.params.ACCEL_MIN, self.params.ACCEL_MAX)) + + can_sends.append(toyotacan.create_accel_command(self.packer, pcm_accel_cmd, pcm_cancel_cmd, self.permit_braking, self.standstill_req, lead, + CS.acc_type, fcw_alert, self.distance_button)) + self.accel = pcm_accel_cmd + + else: + # we can spam can to cancel the system even if we are using lat only control + if pcm_cancel_cmd: + if self.CP.carFingerprint in UNSUPPORTED_DSU_CAR: + can_sends.append(toyotacan.create_acc_cancel_command(self.packer)) + else: + can_sends.append(toyotacan.create_accel_command(self.packer, 0, pcm_cancel_cmd, True, False, lead, CS.acc_type, False, self.distance_button)) + + # *** hud ui *** + if self.CP.carFingerprint != CAR.TOYOTA_PRIUS_V: + # ui mesg is at 1Hz but we send asap if: + # - there is something to display + # - there is something to stop displaying + send_ui = False + if ((fcw_alert or steer_alert) and not self.alert_active) or \ + (not (fcw_alert or steer_alert) and self.alert_active): + send_ui = True + self.alert_active = not self.alert_active + elif pcm_cancel_cmd: + # forcing the pcm to disengage causes a bad fault sound so play a good sound instead + send_ui = True + + if self.frame % 20 == 0 or send_ui: + can_sends.append(toyotacan.create_ui_command(self.packer, steer_alert, pcm_cancel_cmd, hud_control.leftLaneVisible, + hud_control.rightLaneVisible, hud_control.leftLaneDepart, + hud_control.rightLaneDepart, CC.enabled, CS.lkas_hud)) + + if (self.frame % 100 == 0 or send_ui) and (self.CP.enableDsu or self.CP.flags & ToyotaFlags.DISABLE_RADAR.value): + can_sends.append(toyotacan.create_fcw_command(self.packer, fcw_alert)) + + # *** static msgs *** + if self.CP.enableDsu: + for addr, cars, bus, fr_step, vl in STATIC_DSU_MSGS: + if self.frame % fr_step == 0 and self.CP.carFingerprint in cars: + can_sends.append(CanData(addr, vl, bus)) + + # keep radar disabled + if self.frame % 20 == 0 and self.CP.flags & ToyotaFlags.DISABLE_RADAR.value: + can_sends.append(make_tester_present_msg(0x750, 0, 0xF)) + + new_actuators = actuators.as_builder() + new_actuators.torque = apply_torque / self.params.STEER_MAX + new_actuators.torqueOutputCan = apply_torque + new_actuators.steeringAngleDeg = self.last_angle + new_actuators.accel = self.accel + + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/toyota/carstate.py b/opendbc_repo/opendbc/car/toyota/carstate.py new file mode 100644 index 0000000000..6c996def41 --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/carstate.py @@ -0,0 +1,212 @@ +import copy + +from opendbc.can import CANDefine, CANParser +from opendbc.car import Bus, DT_CTRL, create_button_events, structs +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.common.filter_simple import FirstOrderFilter +from opendbc.car.interfaces import CarStateBase +from opendbc.car.toyota.values import ToyotaFlags, CAR, DBC, STEER_THRESHOLD, NO_STOP_TIMER_CAR, \ + TSS2_CAR, RADAR_ACC_CAR, EPS_SCALE, UNSUPPORTED_DSU_CAR + +ButtonType = structs.CarState.ButtonEvent.Type +SteerControlType = structs.CarParams.SteerControlType + +# These steering fault definitions seem to be common across LKA (torque) and LTA (angle): +# - high steer rate fault: goes to 21 or 25 for 1 frame, then 9 for 2 seconds +# - lka/lta msg drop out: goes to 9 then 11 for a combined total of 2 seconds, then 3. +# if using the other control command, goes directly to 3 after 1.5 seconds +# - initializing: LTA can report 0 as long as STEER_TORQUE_SENSOR->STEER_ANGLE_INITIALIZING is 1, +# and is a catch-all for LKA +TEMP_STEER_FAULTS = (0, 9, 11, 21, 25) +# - lka/lta msg drop out: 3 (recoverable) +# - prolonged high driver torque: 17 (permanent) +PERM_STEER_FAULTS = (3, 17) + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + self.eps_torque_scale = EPS_SCALE[CP.carFingerprint] / 100. + self.cluster_speed_hyst_gap = CV.KPH_TO_MS / 2. + self.cluster_min_speed = CV.KPH_TO_MS / 2. + + if CP.flags & ToyotaFlags.SECOC.value: + self.shifter_values = can_define.dv["GEAR_PACKET_HYBRID"]["GEAR"] + else: + self.shifter_values = can_define.dv["GEAR_PACKET"]["GEAR"] + + # On cars with cp.vl["STEER_TORQUE_SENSOR"]["STEER_ANGLE"] + # the signal is zeroed to where the steering angle is at start. + # Need to apply an offset as soon as the steering angle measurements are both received + self.accurate_steer_angle_seen = False + self.angle_offset = FirstOrderFilter(None, 60.0, DT_CTRL, initialized=False) + + self.lkas_button = 0 + self.distance_button = 0 + + self.pcm_follow_distance = 0 + + self.acc_type = 1 + self.lkas_hud = {} + self.gvc = 0.0 + self.secoc_synchronization = None + + def update(self, can_parsers) -> structs.CarState: + cp = can_parsers[Bus.pt] + cp_cam = can_parsers[Bus.cam] + + ret = structs.CarState() + cp_acc = cp_cam if self.CP.carFingerprint in (TSS2_CAR - RADAR_ACC_CAR) else cp + + if not self.CP.flags & ToyotaFlags.SECOC.value: + self.gvc = cp.vl["VSC1S07"]["GVC"] + + ret.doorOpen = any([cp.vl["BODY_CONTROL_STATE"]["DOOR_OPEN_FL"], cp.vl["BODY_CONTROL_STATE"]["DOOR_OPEN_FR"], + cp.vl["BODY_CONTROL_STATE"]["DOOR_OPEN_RL"], cp.vl["BODY_CONTROL_STATE"]["DOOR_OPEN_RR"]]) + ret.seatbeltUnlatched = cp.vl["BODY_CONTROL_STATE"]["SEATBELT_DRIVER_UNLATCHED"] != 0 + ret.parkingBrake = cp.vl["BODY_CONTROL_STATE"]["PARKING_BRAKE"] == 1 + + ret.brakePressed = cp.vl["BRAKE_MODULE"]["BRAKE_PRESSED"] != 0 + ret.brakeHoldActive = cp.vl["ESP_CONTROL"]["BRAKE_HOLD_ACTIVE"] == 1 + + if self.CP.flags & ToyotaFlags.SECOC.value: + self.secoc_synchronization = copy.copy(cp.vl["SECOC_SYNCHRONIZATION"]) + ret.gasPressed = cp.vl["GAS_PEDAL"]["GAS_PEDAL_USER"] > 0 + can_gear = int(cp.vl["GEAR_PACKET_HYBRID"]["GEAR"]) + else: + ret.gasPressed = cp.vl["PCM_CRUISE"]["GAS_RELEASED"] == 0 # TODO: these also have GAS_PEDAL, come back and unify + can_gear = int(cp.vl["GEAR_PACKET"]["GEAR"]) + if not self.CP.enableDsu and not self.CP.flags & ToyotaFlags.DISABLE_RADAR.value: + ret.stockAeb = bool(cp_acc.vl["PRE_COLLISION"]["PRECOLLISION_ACTIVE"] and cp_acc.vl["PRE_COLLISION"]["FORCE"] < -1e-5) + + self.parse_wheel_speeds(ret, + cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FL"], + cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_FR"], + cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RL"], + cp.vl["WHEEL_SPEEDS"]["WHEEL_SPEED_RR"], + ) + ret.vEgoCluster = ret.vEgo * 1.015 # minimum of all the cars + + ret.standstill = abs(ret.vEgoRaw) < 1e-3 + + ret.steeringAngleDeg = cp.vl["STEER_ANGLE_SENSOR"]["STEER_ANGLE"] + cp.vl["STEER_ANGLE_SENSOR"]["STEER_FRACTION"] + ret.steeringRateDeg = cp.vl["STEER_ANGLE_SENSOR"]["STEER_RATE"] + torque_sensor_angle_deg = cp.vl["STEER_TORQUE_SENSOR"]["STEER_ANGLE"] + + # On some cars, the angle measurement is non-zero while initializing + if abs(torque_sensor_angle_deg) > 1e-3 and not bool(cp.vl["STEER_TORQUE_SENSOR"]["STEER_ANGLE_INITIALIZING"]): + self.accurate_steer_angle_seen = True + + if self.accurate_steer_angle_seen: + # Offset seems to be invalid for large steering angles and high angle rates + if abs(ret.steeringAngleDeg) < 90 and abs(ret.steeringRateDeg) < 100 and cp.can_valid: + self.angle_offset.update(torque_sensor_angle_deg - ret.steeringAngleDeg) + + if self.angle_offset.initialized: + ret.steeringAngleOffsetDeg = self.angle_offset.x + ret.steeringAngleDeg = torque_sensor_angle_deg - self.angle_offset.x + + ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None)) + ret.leftBlinker = cp.vl["BLINKERS_STATE"]["TURN_SIGNALS"] == 1 + ret.rightBlinker = cp.vl["BLINKERS_STATE"]["TURN_SIGNALS"] == 2 + + ret.steeringTorque = cp.vl["STEER_TORQUE_SENSOR"]["STEER_TORQUE_DRIVER"] + ret.steeringTorqueEps = cp.vl["STEER_TORQUE_SENSOR"]["STEER_TORQUE_EPS"] * self.eps_torque_scale + # we could use the override bit from dbc, but it's triggered at too high torque values + ret.steeringPressed = abs(ret.steeringTorque) > STEER_THRESHOLD + + # Check EPS LKA/LTA fault status + ret.steerFaultTemporary = cp.vl["EPS_STATUS"]["LKA_STATE"] in TEMP_STEER_FAULTS + ret.steerFaultPermanent = cp.vl["EPS_STATUS"]["LKA_STATE"] in PERM_STEER_FAULTS + + if self.CP.steerControlType == SteerControlType.angle: + ret.steerFaultTemporary = ret.steerFaultTemporary or cp.vl["EPS_STATUS"]["LTA_STATE"] in TEMP_STEER_FAULTS + ret.steerFaultPermanent = ret.steerFaultPermanent or cp.vl["EPS_STATUS"]["LTA_STATE"] in PERM_STEER_FAULTS + + # Lane Tracing Assist control is unavailable (EPS_STATUS->LTA_STATE=0) until + # the more accurate angle sensor signal is initialized + ret.vehicleSensorsInvalid = not self.accurate_steer_angle_seen + + if self.CP.carFingerprint in UNSUPPORTED_DSU_CAR: + # TODO: find the bit likely in DSU_CRUISE that describes an ACC fault. one may also exist in CLUTCH + ret.cruiseState.available = cp.vl["DSU_CRUISE"]["MAIN_ON"] != 0 + ret.cruiseState.speed = cp.vl["DSU_CRUISE"]["SET_SPEED"] * CV.KPH_TO_MS + cluster_set_speed = cp.vl["PCM_CRUISE_ALT"]["UI_SET_SPEED"] + else: + ret.accFaulted = cp.vl["PCM_CRUISE_2"]["ACC_FAULTED"] != 0 + ret.carFaultedNonCritical = cp.vl["PCM_CRUISE_SM"]["TEMP_ACC_FAULTED"] != 0 + ret.cruiseState.available = cp.vl["PCM_CRUISE_2"]["MAIN_ON"] != 0 + ret.cruiseState.speed = cp.vl["PCM_CRUISE_2"]["SET_SPEED"] * CV.KPH_TO_MS + cluster_set_speed = cp.vl["PCM_CRUISE_SM"]["UI_SET_SPEED"] + + # UI_SET_SPEED is always non-zero when main is on, hide until first enable + is_metric = cp.vl["BODY_CONTROL_STATE_2"]["UNITS"] in (1, 2) + if ret.cruiseState.speed != 0: + conversion_factor = CV.KPH_TO_MS if is_metric else CV.MPH_TO_MS + ret.cruiseState.speedCluster = cluster_set_speed * conversion_factor + + if self.CP.carFingerprint in TSS2_CAR and not self.CP.flags & ToyotaFlags.DISABLE_RADAR.value: + self.acc_type = cp_acc.vl["ACC_CONTROL"]["ACC_TYPE"] + ret.stockFcw = bool(cp_acc.vl["PCS_HUD"]["FCW"]) + + # some TSS2 cars have low speed lockout permanently set, so ignore on those cars + # these cars are identified by an ACC_TYPE value of 2. + # TODO: it is possible to avoid the lockout and gain stop and go if you + # send your own ACC_CONTROL msg on startup with ACC_TYPE set to 1 + if (self.CP.carFingerprint not in TSS2_CAR and self.CP.carFingerprint not in UNSUPPORTED_DSU_CAR) or \ + (self.CP.carFingerprint in TSS2_CAR and self.acc_type == 1): + if self.CP.openpilotLongitudinalControl: + ret.accFaulted = ret.accFaulted or cp.vl["PCM_CRUISE_2"]["LOW_SPEED_LOCKOUT"] == 2 + + self.pcm_acc_status = cp.vl["PCM_CRUISE"]["CRUISE_STATE"] + if self.CP.carFingerprint not in (NO_STOP_TIMER_CAR - TSS2_CAR): + # ignore standstill state in certain vehicles, since pcm allows to restart with just an acceleration request + ret.cruiseState.standstill = self.pcm_acc_status == 7 + ret.cruiseState.enabled = bool(cp.vl["PCM_CRUISE"]["CRUISE_ACTIVE"]) + ret.cruiseState.nonAdaptive = self.pcm_acc_status in (1, 2, 3, 4, 5, 6) + + ret.genericToggle = bool(cp.vl["LIGHT_STALK"]["AUTO_HIGH_BEAM"]) + ret.espDisabled = cp.vl["ESP_CONTROL"]["TC_DISABLED"] != 0 + + if self.CP.enableBsm: + ret.leftBlindspot = (cp.vl["BSM"]["L_ADJACENT"] == 1) or (cp.vl["BSM"]["L_APPROACHING"] == 1) + ret.rightBlindspot = (cp.vl["BSM"]["R_ADJACENT"] == 1) or (cp.vl["BSM"]["R_APPROACHING"] == 1) + + if self.CP.carFingerprint != CAR.TOYOTA_PRIUS_V: + self.lkas_hud = copy.copy(cp_cam.vl["LKAS_HUD"]) + + if self.CP.carFingerprint not in UNSUPPORTED_DSU_CAR: + self.pcm_follow_distance = cp.vl["PCM_CRUISE_2"]["PCM_FOLLOW_DISTANCE"] + + buttonEvents = [] + if self.CP.carFingerprint in TSS2_CAR: + # lkas button is wired to the camera + prev_lkas_button = self.lkas_button + self.lkas_button = cp_cam.vl["LKAS_HUD"]["LDA_ON_MESSAGE"] + + # Cycles between 1 and 2 when pressing the button, then rests back at 0 after ~3s + if self.lkas_button != 0 and self.lkas_button != prev_lkas_button: + buttonEvents.extend(create_button_events(1, 0, {1: ButtonType.lkas}) + + create_button_events(0, 1, {1: ButtonType.lkas})) + + if self.CP.carFingerprint not in RADAR_ACC_CAR: + # distance button is wired to the ACC module (camera or radar) + prev_distance_button = self.distance_button + self.distance_button = cp_acc.vl["ACC_CONTROL"]["DISTANCE"] + + buttonEvents += create_button_events(self.distance_button, prev_distance_button, {1: ButtonType.gapAdjustCruise}) + ret.buttonEvents = buttonEvents + + return ret + + @staticmethod + def get_can_parsers(CP): + pt_messages = [ + ("BLINKERS_STATE", float('nan')), + ] + + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], pt_messages, 0), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], 2), + } diff --git a/opendbc_repo/opendbc/car/toyota/fingerprints.py b/opendbc_repo/opendbc/car/toyota/fingerprints.py new file mode 100644 index 0000000000..f320e40e8a --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/fingerprints.py @@ -0,0 +1,1861 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.toyota.values import CAR + +Ecu = CarParams.Ecu + +FW_VERSIONS = { + CAR.TOYOTA_AVALON: { + (Ecu.abs, 0x7b0, None): [ + b'F152607060\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881510701300\x00\x00\x00\x00', + b'881510705100\x00\x00\x00\x00', + b'881510705200\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B41051\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0230721100\x00\x00\x00\x00\x00\x00\x00\x00A0C01000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230721200\x00\x00\x00\x00\x00\x00\x00\x00A0C01000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702000\x00\x00\x00\x00', + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F0701100\x00\x00\x00\x00', + b'8646F0703000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_AVALON_2019: { + (Ecu.abs, 0x7b0, None): [ + b'F152607110\x00\x00\x00\x00\x00\x00', + b'F152607140\x00\x00\x00\x00\x00\x00', + b'F152607171\x00\x00\x00\x00\x00\x00', + b'F152607180\x00\x00\x00\x00\x00\x00', + b'F152641040\x00\x00\x00\x00\x00\x00', + b'F152641050\x00\x00\x00\x00\x00\x00', + b'F152641060\x00\x00\x00\x00\x00\x00', + b'F152641061\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881510703200\x00\x00\x00\x00', + b'881510704200\x00\x00\x00\x00', + b'881514107100\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B07010\x00\x00\x00\x00\x00\x00', + b'8965B41070\x00\x00\x00\x00\x00\x00', + b'8965B41080\x00\x00\x00\x00\x00\x00', + b'8965B41090\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x01896630725100\x00\x00\x00\x00', + b'\x01896630725200\x00\x00\x00\x00', + b'\x01896630725300\x00\x00\x00\x00', + b'\x01896630725400\x00\x00\x00\x00', + b'\x01896630735100\x00\x00\x00\x00', + b'\x01896630738000\x00\x00\x00\x00', + b'\x02896630724000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x02896630728000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x02896630734000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x02896630737000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F0702100\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_AVALON_TSS2: { + (Ecu.abs, 0x7b0, None): [ + b'\x01F152607240\x00\x00\x00\x00\x00\x00', + b'\x01F152607250\x00\x00\x00\x00\x00\x00', + b'\x01F152607280\x00\x00\x00\x00\x00\x00', + b'F152641080\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B41110\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x018966306Q6000\x00\x00\x00\x00', + b'\x01896630742000\x00\x00\x00\x00', + b'\x01896630743000\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F6201200\x00\x00\x00\x00', + b'\x018821F6201300\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F4104100\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F4104100\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_CAMRY: { + (Ecu.engine, 0x700, None): [ + b'\x018966306L3100\x00\x00\x00\x00', + b'\x018966306L4200\x00\x00\x00\x00', + b'\x018966306L5200\x00\x00\x00\x00', + b'\x018966306L9000\x00\x00\x00\x00', + b'\x018966306P8000\x00\x00\x00\x00', + b'\x018966306Q3100\x00\x00\x00\x00', + b'\x018966306Q4000\x00\x00\x00\x00', + b'\x018966306Q4100\x00\x00\x00\x00', + b'\x018966306Q4200\x00\x00\x00\x00', + b'\x018966306Q6000\x00\x00\x00\x00', + b'\x018966333N1100\x00\x00\x00\x00', + b'\x018966333N4300\x00\x00\x00\x00', + b'\x018966333P3000\x00\x00\x00\x00', + b'\x018966333P3100\x00\x00\x00\x00', + b'\x018966333P3200\x00\x00\x00\x00', + b'\x018966333P4200\x00\x00\x00\x00', + b'\x018966333P4300\x00\x00\x00\x00', + b'\x018966333P4400\x00\x00\x00\x00', + b'\x018966333P4500\x00\x00\x00\x00', + b'\x018966333P4700\x00\x00\x00\x00', + b'\x018966333P4900\x00\x00\x00\x00', + b'\x018966333Q6000\x00\x00\x00\x00', + b'\x018966333Q6200\x00\x00\x00\x00', + b'\x018966333Q6300\x00\x00\x00\x00', + b'\x018966333Q6500\x00\x00\x00\x00', + b'\x018966333Q9200\x00\x00\x00\x00', + b'\x018966333W6000\x00\x00\x00\x00', + b'\x018966333X0000\x00\x00\x00\x00', + b'\x018966333X4000\x00\x00\x00\x00', + b'\x01896633T16000\x00\x00\x00\x00', + b'\x01896633TA2000\x00\x00\x00\x00', + b'\x028966306B2100\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306B2300\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306B2500\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306N8100\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306N8200\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306N8300\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306N8400\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306R5000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306R5000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966306R6000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966306R6000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966306S0000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966306S0100\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966306S1100\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x02333P1100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'8821F0601200 ', + b'8821F0601300 ', + b'8821F0601400 ', + b'8821F0601500 ', + b'8821F0601600 ', + b'8821F0602000 ', + b'8821F0603300 ', + b'8821F0603400 ', + b'8821F0604000 ', + b'8821F0604100 ', + b'8821F0604200 ', + b'8821F0605200 ', + b'8821F0606200 ', + b'8821F0607200 ', + b'8821F0607300 ', + b'8821F0608000 ', + b'8821F0608200 ', + b'8821F0608300 ', + b'8821F0609000 ', + b'8821F0609100 ', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152606210\x00\x00\x00\x00\x00\x00', + b'F152606230\x00\x00\x00\x00\x00\x00', + b'F152606260\x00\x00\x00\x00\x00\x00', + b'F152606270\x00\x00\x00\x00\x00\x00', + b'F152606290\x00\x00\x00\x00\x00\x00', + b'F152606410\x00\x00\x00\x00\x00\x00', + b'F152633214\x00\x00\x00\x00\x00\x00', + b'F152633540\x00\x00\x00\x00\x00\x00', + b'F152633660\x00\x00\x00\x00\x00\x00', + b'F152633712\x00\x00\x00\x00\x00\x00', + b'F152633713\x00\x00\x00\x00\x00\x00', + b'F152633A10\x00\x00\x00\x00\x00\x00', + b'F152633A20\x00\x00\x00\x00\x00\x00', + b'F152633B51\x00\x00\x00\x00\x00\x00', + b'F152633B60\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B33540\x00\x00\x00\x00\x00\x00', + b'8965B33542\x00\x00\x00\x00\x00\x00', + b'8965B33550\x00\x00\x00\x00\x00\x00', + b'8965B33551\x00\x00\x00\x00\x00\x00', + b'8965B33580\x00\x00\x00\x00\x00\x00', + b'8965B33581\x00\x00\x00\x00\x00\x00', + b'8965B33611\x00\x00\x00\x00\x00\x00', + b'8965B33621\x00\x00\x00\x00\x00\x00', + b'8965B33630\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F0601200 ', + b'8821F0601300 ', + b'8821F0601400 ', + b'8821F0601500 ', + b'8821F0601600 ', + b'8821F0602000 ', + b'8821F0603300 ', + b'8821F0603400 ', + b'8821F0604000 ', + b'8821F0604100 ', + b'8821F0604200 ', + b'8821F0605200 ', + b'8821F0606200 ', + b'8821F0607200 ', + b'8821F0607300 ', + b'8821F0608000 ', + b'8821F0608200 ', + b'8821F0608300 ', + b'8821F0609000 ', + b'8821F0609100 ', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F0601200 ', + b'8646F0601300 ', + b'8646F0601400 ', + b'8646F0603400 ', + b'8646F0603500 ', + b'8646F0604000 ', + b'8646F0604100 ', + b'8646F0605000 ', + b'8646F0606000 ', + b'8646F0606100 ', + b'8646F0607000 ', + b'8646F0607100 ', + ], + }, + CAR.TOYOTA_CAMRY_TSS2: { + (Ecu.eps, 0x7a1, None): [ + b'8965B33630\x00\x00\x00\x00\x00\x00', + b'8965B33640\x00\x00\x00\x00\x00\x00', + b'8965B33650\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F152606370\x00\x00\x00\x00\x00\x00', + b'\x01F152606390\x00\x00\x00\x00\x00\x00', + b'\x01F152606400\x00\x00\x00\x00\x00\x00', + b'\x01F152606431\x00\x00\x00\x00\x00\x00', + b'\x01F152633E11\x00\x00\x00\x00\x00\x00', + b'F152633310\x00\x00\x00\x00\x00\x00', + b'F152633D00\x00\x00\x00\x00\x00\x00', + b'F152633D60\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x018966306Q5000\x00\x00\x00\x00', + b'\x018966306Q6000\x00\x00\x00\x00', + b'\x018966306Q7000\x00\x00\x00\x00', + b'\x018966306Q9000\x00\x00\x00\x00', + b'\x018966306R3000\x00\x00\x00\x00', + b'\x018966306R8000\x00\x00\x00\x00', + b'\x018966306T0000\x00\x00\x00\x00', + b'\x018966306T3100\x00\x00\x00\x00', + b'\x018966306T3200\x00\x00\x00\x00', + b'\x018966306T4000\x00\x00\x00\x00', + b'\x018966306T4100\x00\x00\x00\x00', + b'\x018966306V1000\x00\x00\x00\x00', + b'\x018966333Z1000\x00\x00\x00\x00', + b'\x018966333Z9000\x00\x00\x00\x00', + b'\x01896633T20000\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F6201200\x00\x00\x00\x00', + b'\x018821F6201300\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0602100\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F0602200\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F0602300\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F3305200\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F3305200\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F3305300\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F3305300\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F3305400\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F3305500\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_CHR: { + (Ecu.engine, 0x700, None): [ + b'\x01896631017100\x00\x00\x00\x00', + b'\x01896631017200\x00\x00\x00\x00', + b'\x01896631021100\x00\x00\x00\x00', + b'\x0189663F413100\x00\x00\x00\x00', + b'\x0189663F414100\x00\x00\x00\x00', + b'\x0189663F438000\x00\x00\x00\x00', + b'\x02896631013200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x0289663F405000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x0289663F405100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x0289663F418000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x0289663F423000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x0289663F431000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'8821F0W01000 ', + b'8821F0W01100 ', + b'8821FF401600 ', + b'8821FF401800 ', + b'8821FF402300 ', + b'8821FF402400 ', + b'8821FF404000 ', + b'8821FF404100 ', + b'8821FF405000 ', + b'8821FF405100 ', + b'8821FF406000 ', + b'8821FF407100 ', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152610012\x00\x00\x00\x00\x00\x00', + b'F152610013\x00\x00\x00\x00\x00\x00', + b'F152610014\x00\x00\x00\x00\x00\x00', + b'F152610020\x00\x00\x00\x00\x00\x00', + b'F152610040\x00\x00\x00\x00\x00\x00', + b'F152610153\x00\x00\x00\x00\x00\x00', + b'F152610190\x00\x00\x00\x00\x00\x00', + b'F152610200\x00\x00\x00\x00\x00\x00', + b'F152610210\x00\x00\x00\x00\x00\x00', + b'F152610220\x00\x00\x00\x00\x00\x00', + b'F152610230\x00\x00\x00\x00\x00\x00', + b'F1526F4034\x00\x00\x00\x00\x00\x00', + b'F1526F4044\x00\x00\x00\x00\x00\x00', + b'F1526F4073\x00\x00\x00\x00\x00\x00', + b'F1526F4121\x00\x00\x00\x00\x00\x00', + b'F1526F4122\x00\x00\x00\x00\x00\x00', + b'F1526F4190\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B10011\x00\x00\x00\x00\x00\x00', + b'8965B10020\x00\x00\x00\x00\x00\x00', + b'8965B10040\x00\x00\x00\x00\x00\x00', + b'8965B10050\x00\x00\x00\x00\x00\x00', + b'8965B10070\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0331024000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00', + b'\x0331024000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + b'\x0331036000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + b'\x033F401100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203102\x00\x00\x00\x00', + b'\x033F401200\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00', + b'\x033F424000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00', + b'\x033F424000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + b'\x033F435000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F0W01000 ', + b'8821F0W01100 ', + b'8821FF401600 ', + b'8821FF401800 ', + b'8821FF402300 ', + b'8821FF402400 ', + b'8821FF404000 ', + b'8821FF404100 ', + b'8821FF405000 ', + b'8821FF405100 ', + b'8821FF406000 ', + b'8821FF407100 ', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646FF401700 ', + b'8646FF401800 ', + b'8646FF402100 ', + b'8646FF404000 ', + b'8646FF406000 ', + b'8646FF407000 ', + b'8646FF407100 ', + ], + }, + CAR.TOYOTA_CHR_TSS2: { + (Ecu.abs, 0x7b0, None): [ + b'F152610041\x00\x00\x00\x00\x00\x00', + b'F152610260\x00\x00\x00\x00\x00\x00', + b'F1526F4270\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B10091\x00\x00\x00\x00\x00\x00', + b'8965B10092\x00\x00\x00\x00\x00\x00', + b'8965B10110\x00\x00\x00\x00\x00\x00', + b'8965B10111\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x0189663F438000\x00\x00\x00\x00', + b'\x0189663F459000\x00\x00\x00\x00', + b'\x02896631025000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x0289663F453000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0331014000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821FF410200\x00\x00\x00\x00', + b'\x018821FF410300\x00\x00\x00\x00', + b'\x018821FF410400\x00\x00\x00\x00', + b'\x018821FF410500\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646FF410200\x00\x00\x00\x008646GF408200\x00\x00\x00\x00', + b'\x028646FF411100\x00\x00\x00\x008646GF409000\x00\x00\x00\x00', + b'\x028646FF413000\x00\x00\x00\x008646GF411000\x00\x00\x00\x00', + b'\x028646FF413100\x00\x00\x00\x008646GF411100\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_COROLLA: { + (Ecu.engine, 0x7e0, None): [ + b'\x0230ZC2000\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC2100\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC2200\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC2300\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC3000\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC3100\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC3200\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZC3300\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0330ZC1200\x00\x00\x00\x00\x00\x00\x00\x0050212000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881510201100\x00\x00\x00\x00', + b'881510201200\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152602190\x00\x00\x00\x00\x00\x00', + b'F152602191\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B02181\x00\x00\x00\x00\x00\x00', + b'8965B02191\x00\x00\x00\x00\x00\x00', + b'8965B48150\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F0201101\x00\x00\x00\x00', + b'8646F0201200\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_COROLLA_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x01896630A22000\x00\x00\x00\x00', + b'\x01896630A42000\x00\x00\x00\x00', + b'\x01896630ZG2000\x00\x00\x00\x00', + b'\x01896630ZG5000\x00\x00\x00\x00', + b'\x01896630ZG5100\x00\x00\x00\x00', + b'\x01896630ZG5200\x00\x00\x00\x00', + b'\x01896630ZG5300\x00\x00\x00\x00', + b'\x01896630ZJ1000\x00\x00\x00\x00', + b'\x01896630ZP1000\x00\x00\x00\x00', + b'\x01896630ZP2000\x00\x00\x00\x00', + b'\x01896630ZQ5000\x00\x00\x00\x00', + b'\x01896630ZU8000\x00\x00\x00\x00', + b'\x01896630ZU9000\x00\x00\x00\x00', + b'\x01896630ZX4000\x00\x00\x00\x00', + b'\x01896630ZX7100\x00\x00\x00\x00', + b'\x018966312L8000\x00\x00\x00\x00', + b'\x018966312M0000\x00\x00\x00\x00', + b'\x018966312M9000\x00\x00\x00\x00', + b'\x018966312P9000\x00\x00\x00\x00', + b'\x018966312P9100\x00\x00\x00\x00', + b'\x018966312P9200\x00\x00\x00\x00', + b'\x018966312P9300\x00\x00\x00\x00', + b'\x018966312Q2300\x00\x00\x00\x00', + b'\x018966312Q8000\x00\x00\x00\x00', + b'\x018966312R0000\x00\x00\x00\x00', + b'\x018966312R0100\x00\x00\x00\x00', + b'\x018966312R0200\x00\x00\x00\x00', + b'\x018966312R1000\x00\x00\x00\x00', + b'\x018966312R1100\x00\x00\x00\x00', + b'\x018966312R3100\x00\x00\x00\x00', + b'\x018966312S5000\x00\x00\x00\x00', + b'\x018966312S7000\x00\x00\x00\x00', + b'\x018966312W3000\x00\x00\x00\x00', + b'\x018966312W9000\x00\x00\x00\x00', + b'\x01896637621000\x00\x00\x00\x00', + b'\x01896637623000\x00\x00\x00\x00', + b'\x01896637624000\x00\x00\x00\x00', + b'\x01896637625000\x00\x00\x00\x00', + b'\x01896637626000\x00\x00\x00\x00', + b'\x01896637639000\x00\x00\x00\x00', + b'\x01896637643000\x00\x00\x00\x00', + b'\x01896637644000\x00\x00\x00\x00', + b'\x01896637648000\x00\x00\x00\x00', + b'\x01896637649000\x00\x00\x00\x00', + b'\x02896630A07000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630A21000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZJ5000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZK8000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZN8000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZQ3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZR2000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZT8000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZT9000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896630ZZ0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966312K6000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966312L0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966312L0100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966312Q3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966312Q3100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966312Q4000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x038966312L7000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF1205001\x00\x00\x00\x00', + b'\x038966312N1000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x038966312T3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF1205001\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0230A10000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230A11000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZN4000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230ZN5000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02312K4000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02312U5000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x03312K7000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', + b'\x03312M3000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', + b'\x03312N6000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00', + b'\x03312N6000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + b'\x03312N6000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', + b'\x03312N6100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + b'\x03312N6100\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', + b'\x03312N6200\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203202\x00\x00\x00\x00', + b'\x03312N6200\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203302\x00\x00\x00\x00', + b'\x03312N6200\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00895231203402\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x018965B12350\x00\x00\x00\x00\x00\x00', + b'\x018965B12470\x00\x00\x00\x00\x00\x00', + b'\x018965B12490\x00\x00\x00\x00\x00\x00', + b'\x018965B12500\x00\x00\x00\x00\x00\x00', + b'\x018965B12510\x00\x00\x00\x00\x00\x00', + b'\x018965B12520\x00\x00\x00\x00\x00\x00', + b'\x018965B12530\x00\x00\x00\x00\x00\x00', + b'\x018965B1254000\x00\x00\x00\x00', + b'\x018965B1255000\x00\x00\x00\x00', + b'\x018965B1256000\x00\x00\x00\x00', + b'\x018965B1270000\x00\x00\x00\x00', + b'8965B12361\x00\x00\x00\x00\x00\x00', + b'8965B12451\x00\x00\x00\x00\x00\x00', + b'8965B16011\x00\x00\x00\x00\x00\x00', + b'8965B16101\x00\x00\x00\x00\x00\x00', + b'8965B16170\x00\x00\x00\x00\x00\x00', + b'8965B16260\x00\x00\x00\x00\x00\x00', + b'8965B76012\x00\x00\x00\x00\x00\x00', + b'8965B76050\x00\x00\x00\x00\x00\x00', + b'8965B76091\x00\x00\x00\x00\x00\x00', + b'8965B76101\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F152602280\x00\x00\x00\x00\x00\x00', + b'\x01F152602281\x00\x00\x00\x00\x00\x00', + b'\x01F152602470\x00\x00\x00\x00\x00\x00', + b'\x01F152602560\x00\x00\x00\x00\x00\x00', + b'\x01F152602590\x00\x00\x00\x00\x00\x00', + b'\x01F152602650\x00\x00\x00\x00\x00\x00', + b'\x01F15260A010\x00\x00\x00\x00\x00\x00', + b'\x01F15260A050\x00\x00\x00\x00\x00\x00', + b'\x01F15260A070\x00\x00\x00\x00\x00\x00', + b'\x01F15260A33000\x00\x00\x00\x00', + b'\x01F152612641\x00\x00\x00\x00\x00\x00', + b'\x01F152612651\x00\x00\x00\x00\x00\x00', + b'\x01F152612862\x00\x00\x00\x00\x00\x00', + b'\x01F152612B10\x00\x00\x00\x00\x00\x00', + b'\x01F152612B51\x00\x00\x00\x00\x00\x00', + b'\x01F152612B60\x00\x00\x00\x00\x00\x00', + b'\x01F152612B61\x00\x00\x00\x00\x00\x00', + b'\x01F152612B62\x00\x00\x00\x00\x00\x00', + b'\x01F152612B70\x00\x00\x00\x00\x00\x00', + b'\x01F152612B71\x00\x00\x00\x00\x00\x00', + b'\x01F152612B81\x00\x00\x00\x00\x00\x00', + b'\x01F152612B90\x00\x00\x00\x00\x00\x00', + b'\x01F152612B91\x00\x00\x00\x00\x00\x00', + b'\x01F152612C00\x00\x00\x00\x00\x00\x00', + b'\x01F152676250\x00\x00\x00\x00\x00\x00', + b'\x01F152676350\x00\x00\x00\x00\x00\x00', + b'F152612590\x00\x00\x00\x00\x00\x00', + b'F152612691\x00\x00\x00\x00\x00\x00', + b'F152612692\x00\x00\x00\x00\x00\x00', + b'F152612700\x00\x00\x00\x00\x00\x00', + b'F152612710\x00\x00\x00\x00\x00\x00', + b'F152612790\x00\x00\x00\x00\x00\x00', + b'F152612800\x00\x00\x00\x00\x00\x00', + b'F152612820\x00\x00\x00\x00\x00\x00', + b'F152612840\x00\x00\x00\x00\x00\x00', + b'F152612842\x00\x00\x00\x00\x00\x00', + b'F152612890\x00\x00\x00\x00\x00\x00', + b'F152612A00\x00\x00\x00\x00\x00\x00', + b'F152612A10\x00\x00\x00\x00\x00\x00', + b'F152612D00\x00\x00\x00\x00\x00\x00', + b'F152616011\x00\x00\x00\x00\x00\x00', + b'F152616030\x00\x00\x00\x00\x00\x00', + b'F152616060\x00\x00\x00\x00\x00\x00', + b'F152642540\x00\x00\x00\x00\x00\x00', + b'F152676293\x00\x00\x00\x00\x00\x00', + b'F152676303\x00\x00\x00\x00\x00\x00', + b'F152676304\x00\x00\x00\x00\x00\x00', + b'F152676311\x00\x00\x00\x00\x00\x00', + b'F152676371\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301100\x00\x00\x00\x00', + b'\x018821F3301200\x00\x00\x00\x00', + b'\x018821F3301300\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F12010C0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F12010D0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F1201100\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F1201200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F1201300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F1201400\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + b'\x028646F1202000\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F1202100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F1202200\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + b'\x028646F1206000\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + b'\x028646F1601100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F1601200\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F1601300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F1601500\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F4203400\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F76020C0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F7603100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F7603200\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F7603300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F7605100\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_HIGHLANDER: { + (Ecu.engine, 0x700, None): [ + b'\x01896630E09000\x00\x00\x00\x00', + b'\x01896630E43000\x00\x00\x00\x00', + b'\x01896630E43100\x00\x00\x00\x00', + b'\x01896630E43200\x00\x00\x00\x00', + b'\x01896630E43500\x00\x00\x00\x00', + b'\x01896630E44200\x00\x00\x00\x00', + b'\x01896630E44400\x00\x00\x00\x00', + b'\x01896630E45000\x00\x00\x00\x00', + b'\x01896630E45100\x00\x00\x00\x00', + b'\x01896630E45200\x00\x00\x00\x00', + b'\x01896630E46000\x00\x00\x00\x00', + b'\x01896630E46200\x00\x00\x00\x00', + b'\x01896630E48200\x00\x00\x00\x00', + b'\x01896630E74000\x00\x00\x00\x00', + b'\x01896630E75000\x00\x00\x00\x00', + b'\x01896630E76000\x00\x00\x00\x00', + b'\x01896630E77000\x00\x00\x00\x00', + b'\x01896630E83000\x00\x00\x00\x00', + b'\x01896630E84000\x00\x00\x00\x00', + b'\x01896630E85000\x00\x00\x00\x00', + b'\x01896630E86000\x00\x00\x00\x00', + b'\x01896630E88000\x00\x00\x00\x00', + b'\x01896630EA0000\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0230E40000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230E40100\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230E51000\x00\x00\x00\x00\x00\x00\x00\x0050E17000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230EA2000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0230EA2100\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B48140\x00\x00\x00\x00\x00\x00', + b'8965B48150\x00\x00\x00\x00\x00\x00', + b'8965B48160\x00\x00\x00\x00\x00\x00', + b'8965B48210\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F15260E011\x00\x00\x00\x00\x00\x00', + b'F152648541\x00\x00\x00\x00\x00\x00', + b'F152648542\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881510E01100\x00\x00\x00\x00', + b'881510E01200\x00\x00\x00\x00', + b'881510E02100\x00\x00\x00\x00', + b'881510E02200\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F0E01200\x00\x00\x00\x00', + b'8646F0E01300\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_HIGHLANDER_TSS2: { + (Ecu.eps, 0x7a1, None): [ + b'8965B48241\x00\x00\x00\x00\x00\x00', + b'8965B48310\x00\x00\x00\x00\x00\x00', + b'8965B48320\x00\x00\x00\x00\x00\x00', + b'8965B48400\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15260E051\x00\x00\x00\x00\x00\x00', + b'\x01F15260E05300\x00\x00\x00\x00', + b'\x01F15260E061\x00\x00\x00\x00\x00\x00', + b'\x01F15260E110\x00\x00\x00\x00\x00\x00', + b'\x01F15260E170\x00\x00\x00\x00\x00\x00', + b'\x01F15264872300\x00\x00\x00\x00', + b'\x01F15264872400\x00\x00\x00\x00', + b'\x01F15264872500\x00\x00\x00\x00', + b'\x01F15264872600\x00\x00\x00\x00', + b'\x01F15264872700\x00\x00\x00\x00', + b'\x01F15264873500\x00\x00\x00\x00', + b'\x01F152648C6300\x00\x00\x00\x00', + b'\x01F152648J4000\x00\x00\x00\x00', + b'\x01F152648J5000\x00\x00\x00\x00', + b'\x01F152648J6000\x00\x00\x00\x00', + b'\x01F152648J7000\x00\x00\x00\x00', + b'\x01F152648L5000\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x01896630E62100\x00\x00\x00\x00', + b'\x01896630E62200\x00\x00\x00\x00', + b'\x01896630E64100\x00\x00\x00\x00', + b'\x01896630E64200\x00\x00\x00\x00', + b'\x01896630E64400\x00\x00\x00\x00', + b'\x01896630E67000\x00\x00\x00\x00', + b'\x01896630EA1000\x00\x00\x00\x00', + b'\x01896630EB1000\x00\x00\x00\x00', + b'\x01896630EB1100\x00\x00\x00\x00', + b'\x01896630EB1200\x00\x00\x00\x00', + b'\x01896630EB1300\x00\x00\x00\x00', + b'\x01896630EB2000\x00\x00\x00\x00', + b'\x01896630EB2100\x00\x00\x00\x00', + b'\x01896630EB2200\x00\x00\x00\x00', + b'\x01896630EC4000\x00\x00\x00\x00', + b'\x01896630ED9000\x00\x00\x00\x00', + b'\x01896630ED9100\x00\x00\x00\x00', + b'\x01896630EE1000\x00\x00\x00\x00', + b'\x01896630EE1100\x00\x00\x00\x00', + b'\x01896630EE4000\x00\x00\x00\x00', + b'\x01896630EE4100\x00\x00\x00\x00', + b'\x01896630EE5000\x00\x00\x00\x00', + b'\x01896630EE6000\x00\x00\x00\x00', + b'\x01896630EE7000\x00\x00\x00\x00', + b'\x01896630EF8000\x00\x00\x00\x00', + b'\x01896630EG3000\x00\x00\x00\x00', + b'\x01896630EG3100\x00\x00\x00\x00', + b'\x01896630EG5000\x00\x00\x00\x00', + b'\x01896630EG5100\x00\x00\x00\x00', + b'\x02896630E66000\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896630E66100\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896630EB3000\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896630EB3100\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896630EB3200\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301400\x00\x00\x00\x00', + b'\x018821F6201200\x00\x00\x00\x00', + b'\x018821F6201300\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0E02100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F4803000\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F4803000\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F4803200\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_IS: { + (Ecu.engine, 0x700, None): [ + b'\x018966353M7000\x00\x00\x00\x00', + b'\x018966353M7100\x00\x00\x00\x00', + b'\x018966353Q2000\x00\x00\x00\x00', + b'\x018966353Q2100\x00\x00\x00\x00', + b'\x018966353Q2300\x00\x00\x00\x00', + b'\x018966353Q4000\x00\x00\x00\x00', + b'\x018966353R1100\x00\x00\x00\x00', + b'\x018966353R5000\x00\x00\x00\x00', + b'\x018966353R7000\x00\x00\x00\x00', + b'\x018966353R7100\x00\x00\x00\x00', + b'\x018966353R8000\x00\x00\x00\x00', + b'\x018966353R8100\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0232480000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02353N5100\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02353P7000\x00\x00\x00\x00\x00\x00\x00\x00530J5000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02353P9000\x00\x00\x00\x00\x00\x00\x00\x00553C1000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152653300\x00\x00\x00\x00\x00\x00', + b'F152653301\x00\x00\x00\x00\x00\x00', + b'F152653310\x00\x00\x00\x00\x00\x00', + b'F152653330\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881515306200\x00\x00\x00\x00', + b'881515306400\x00\x00\x00\x00', + b'881515306500\x00\x00\x00\x00', + b'881515307400\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B53270\x00\x00\x00\x00\x00\x00', + b'8965B53271\x00\x00\x00\x00\x00\x00', + b'8965B53280\x00\x00\x00\x00\x00\x00', + b'8965B53281\x00\x00\x00\x00\x00\x00', + b'8965B53310\x00\x00\x00\x00\x00\x00', + b'8965B53311\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F5301101\x00\x00\x00\x00', + b'8646F5301200\x00\x00\x00\x00', + b'8646F5301300\x00\x00\x00\x00', + b'8646F5301400\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_IS_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x018966353S1000\x00\x00\x00\x00', + b'\x018966353S2000\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x02353U0000\x00\x00\x00\x00\x00\x00\x00\x0052422000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15265337200\x00\x00\x00\x00', + b'\x01F15265342000\x00\x00\x00\x00', + b'\x01F15265343000\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B53450\x00\x00\x00\x00\x00\x00', + b'8965B53800\x00\x00\x00\x00\x00\x00', + b'8965B53801\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F6201200\x00\x00\x00\x00', + b'\x018821F6201300\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F5303300\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F5303300\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F5303400\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_PRIUS: { + (Ecu.engine, 0x700, None): [ + b'\x02896634761000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634761100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634761200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634762000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634762100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634763000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634763100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634765000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634765100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634769000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634769100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634769200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634770000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634770100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634774000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634774100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634774200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634782000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x02896634784000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347A0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347A1000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347A5000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347A8000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347B0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x03896634759100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x03896634759200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x03896634759200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00', + b'\x03896634759300\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x03896634759300\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00', + b'\x03896634760000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701002\x00\x00\x00\x00', + b'\x03896634760000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x03896634760000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00', + b'\x03896634760100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x03896634760200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x03896634760200\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00', + b'\x03896634760300\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701004\x00\x00\x00\x00', + b'\x03896634768000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703001\x00\x00\x00\x00', + b'\x03896634768000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703002\x00\x00\x00\x00', + b'\x03896634768100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703002\x00\x00\x00\x00', + b'\x03896634785000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4705001\x00\x00\x00\x00', + b'\x03896634785000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00', + b'\x03896634786000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4705001\x00\x00\x00\x00', + b'\x03896634786000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00', + b'\x03896634789000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4703002\x00\x00\x00\x00', + b'\x038966347A3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4701003\x00\x00\x00\x00', + b'\x038966347A3000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4707001\x00\x00\x00\x00', + b'\x038966347B6000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00', + b'\x038966347B7000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x038966347B7000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710001\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B47021\x00\x00\x00\x00\x00\x00', + b'8965B47022\x00\x00\x00\x00\x00\x00', + b'8965B47023\x00\x00\x00\x00\x00\x00', + b'8965B47050\x00\x00\x00\x00\x00\x00', + b'8965B47060\x00\x00\x00\x00\x00\x00', + b'8965B47070\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152647290\x00\x00\x00\x00\x00\x00', + b'F152647300\x00\x00\x00\x00\x00\x00', + b'F152647310\x00\x00\x00\x00\x00\x00', + b'F152647414\x00\x00\x00\x00\x00\x00', + b'F152647415\x00\x00\x00\x00\x00\x00', + b'F152647416\x00\x00\x00\x00\x00\x00', + b'F152647417\x00\x00\x00\x00\x00\x00', + b'F152647470\x00\x00\x00\x00\x00\x00', + b'F152647490\x00\x00\x00\x00\x00\x00', + b'F152647682\x00\x00\x00\x00\x00\x00', + b'F152647683\x00\x00\x00\x00\x00\x00', + b'F152647684\x00\x00\x00\x00\x00\x00', + b'F152647862\x00\x00\x00\x00\x00\x00', + b'F152647863\x00\x00\x00\x00\x00\x00', + b'F152647864\x00\x00\x00\x00\x00\x00', + b'F152647865\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881514702300\x00\x00\x00\x00', + b'881514702400\x00\x00\x00\x00', + b'881514703100\x00\x00\x00\x00', + b'881514704100\x00\x00\x00\x00', + b'881514706000\x00\x00\x00\x00', + b'881514706100\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702000\x00\x00\x00\x00', + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F4701300\x00\x00\x00\x00', + b'8646F4702001\x00\x00\x00\x00', + b'8646F4702100\x00\x00\x00\x00', + b'8646F4702200\x00\x00\x00\x00', + b'8646F4705000\x00\x00\x00\x00', + b'8646F4705200\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_PRIUS_V: { + (Ecu.abs, 0x7b0, None): [ + b'F152647280\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0234781000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881514705100\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F4703300\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_RAV4: { + (Ecu.engine, 0x7e0, None): [ + b'\x02342Q1000\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q1100\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q1200\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q1300\x00\x00\x00\x00\x00\x00\x00\x0054212000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q2000\x00\x00\x00\x00\x00\x00\x00\x0054213000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q2100\x00\x00\x00\x00\x00\x00\x00\x0054213000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q2200\x00\x00\x00\x00\x00\x00\x00\x0054213000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q3000\x00\x00\x00\x00\x00\x00\x00\x0054214000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342Q4000\x00\x00\x00\x00\x00\x00\x00\x0054215000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B42063\x00\x00\x00\x00\x00\x00', + b'8965B42073\x00\x00\x00\x00\x00\x00', + b'8965B42082\x00\x00\x00\x00\x00\x00', + b'8965B42083\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F15260R102\x00\x00\x00\x00\x00\x00', + b'F15260R103\x00\x00\x00\x00\x00\x00', + b'F152642492\x00\x00\x00\x00\x00\x00', + b'F152642493\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881514201200\x00\x00\x00\x00', + b'881514201300\x00\x00\x00\x00', + b'881514201400\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702000\x00\x00\x00\x00', + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F4201100\x00\x00\x00\x00', + b'8646F4201200\x00\x00\x00\x00', + b'8646F4202001\x00\x00\x00\x00', + b'8646F4202100\x00\x00\x00\x00', + b'8646F4204000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_RAV4H: { + (Ecu.engine, 0x7e0, None): [ + b'\x02342N9000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342N9100\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02342P0000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B42102\x00\x00\x00\x00\x00\x00', + b'8965B42103\x00\x00\x00\x00\x00\x00', + b'8965B42112\x00\x00\x00\x00\x00\x00', + b'8965B42162\x00\x00\x00\x00\x00\x00', + b'8965B42163\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152642090\x00\x00\x00\x00\x00\x00', + b'F152642110\x00\x00\x00\x00\x00\x00', + b'F152642120\x00\x00\x00\x00\x00\x00', + b'F152642400\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881514202200\x00\x00\x00\x00', + b'881514202300\x00\x00\x00\x00', + b'881514202400\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702000\x00\x00\x00\x00', + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F4201100\x00\x00\x00\x00', + b'8646F4201200\x00\x00\x00\x00', + b'8646F4202001\x00\x00\x00\x00', + b'8646F4202100\x00\x00\x00\x00', + b'8646F4204000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_RAV4_PRIME: { + (Ecu.engine, 0x700, None): [ + b'\x018966342S7000\x00\x00\x00\x00', + b'\x018966342Z1000\x00\x00\x00\x00', + b'\x018966342Z1100\x00\x00\x00\x00', + b'\x01896634AJ7000\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15264228300\x00\x00\x00\x00', + b'\x01F15264228500\x00\x00\x00\x00', + b'\x01F15264284100\x00\x00\x00\x00', + b'\x01F152642F3000\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x018965B4209000\x00\x00\x00\x00', + b'\x018965B4233100\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301400\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F4205200\x00\x00\x00\x008646G4202000\x00\x00\x00\x00', + b'\x028646F4205300\x00\x00\x00\x008646G4202100\x00\x00\x00\x00', + b'\x028646F4210100\x00\x00\x00\x008646G3305000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_RAV4_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x01896630R58000\x00\x00\x00\x00', + b'\x01896630R58100\x00\x00\x00\x00', + b'\x018966342E2000\x00\x00\x00\x00', + b'\x018966342M5000\x00\x00\x00\x00', + b'\x018966342M8000\x00\x00\x00\x00', + b'\x018966342S9000\x00\x00\x00\x00', + b'\x018966342T1000\x00\x00\x00\x00', + b'\x018966342T6000\x00\x00\x00\x00', + b'\x018966342T9000\x00\x00\x00\x00', + b'\x018966342U4000\x00\x00\x00\x00', + b'\x018966342U4100\x00\x00\x00\x00', + b'\x018966342U5100\x00\x00\x00\x00', + b'\x018966342V0000\x00\x00\x00\x00', + b'\x018966342V3000\x00\x00\x00\x00', + b'\x018966342V3100\x00\x00\x00\x00', + b'\x018966342V3200\x00\x00\x00\x00', + b'\x018966342W5000\x00\x00\x00\x00', + b'\x018966342W7000\x00\x00\x00\x00', + b'\x018966342W8000\x00\x00\x00\x00', + b'\x018966342W9000\x00\x00\x00\x00', + b'\x018966342X5000\x00\x00\x00\x00', + b'\x018966342X6000\x00\x00\x00\x00', + b'\x01896634A05000\x00\x00\x00\x00', + b'\x01896634A15000\x00\x00\x00\x00', + b'\x01896634A19000\x00\x00\x00\x00', + b'\x01896634A19100\x00\x00\x00\x00', + b'\x01896634A20000\x00\x00\x00\x00', + b'\x01896634A20100\x00\x00\x00\x00', + b'\x01896634A22000\x00\x00\x00\x00', + b'\x01896634A22100\x00\x00\x00\x00', + b'\x01896634A25000\x00\x00\x00\x00', + b'\x01896634A30000\x00\x00\x00\x00', + b'\x01896634A44000\x00\x00\x00\x00', + b'\x01896634A45000\x00\x00\x00\x00', + b'\x01896634A46000\x00\x00\x00\x00', + b'\x028966342M7000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00', + b'\x028966342T0000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00', + b'\x028966342V1000\x00\x00\x00\x00897CF1202001\x00\x00\x00\x00', + b'\x028966342W4001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x028966342Y8000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00', + b'\x028966342Z8000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00', + b'\x02896634A13000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02896634A13001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A13101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A13201\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A14001\x00\x00\x00\x00897CF0R01000\x00\x00\x00\x00', + b'\x02896634A14001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x02896634A14001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A14101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A18000\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00', + b'\x02896634A18100\x00\x00\x00\x00897CF1201001\x00\x00\x00\x00', + b'\x02896634A23000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02896634A23001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x02896634A23101\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', + b'\x02896634A43000\x00\x00\x00\x00897CF4201001\x00\x00\x00\x00', + b'\x02896634A47000\x00\x00\x00\x00897CF4201001\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15260R210\x00\x00\x00\x00\x00\x00', + b'\x01F15260R220\x00\x00\x00\x00\x00\x00', + b'\x01F15260R290\x00\x00\x00\x00\x00\x00', + b'\x01F15260R292\x00\x00\x00\x00\x00\x00', + b'\x01F15260R300\x00\x00\x00\x00\x00\x00', + b'\x01F15260R302\x00\x00\x00\x00\x00\x00', + b'\x01F152642551\x00\x00\x00\x00\x00\x00', + b'\x01F152642561\x00\x00\x00\x00\x00\x00', + b'\x01F152642601\x00\x00\x00\x00\x00\x00', + b'\x01F152642700\x00\x00\x00\x00\x00\x00', + b'\x01F152642701\x00\x00\x00\x00\x00\x00', + b'\x01F152642710\x00\x00\x00\x00\x00\x00', + b'\x01F152642711\x00\x00\x00\x00\x00\x00', + b'\x01F152642750\x00\x00\x00\x00\x00\x00', + b'\x01F152642751\x00\x00\x00\x00\x00\x00', + b'F152642290\x00\x00\x00\x00\x00\x00', + b'F152642291\x00\x00\x00\x00\x00\x00', + b'F152642322\x00\x00\x00\x00\x00\x00', + b'F152642330\x00\x00\x00\x00\x00\x00', + b'F152642331\x00\x00\x00\x00\x00\x00', + b'F152642520\x00\x00\x00\x00\x00\x00', + b'F152642521\x00\x00\x00\x00\x00\x00', + b'F152642531\x00\x00\x00\x00\x00\x00', + b'F152642532\x00\x00\x00\x00\x00\x00', + b'F152642540\x00\x00\x00\x00\x00\x00', + b'F152642541\x00\x00\x00\x00\x00\x00', + b'F152642542\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x028965B0R01200\x00\x00\x00\x008965B0R02200\x00\x00\x00\x00', + b'\x028965B0R01300\x00\x00\x00\x008965B0R02300\x00\x00\x00\x00', + b'\x028965B0R01400\x00\x00\x00\x008965B0R02400\x00\x00\x00\x00', + b'8965B42170\x00\x00\x00\x00\x00\x00', + b'8965B42171\x00\x00\x00\x00\x00\x00', + b'8965B42180\x00\x00\x00\x00\x00\x00', + b'8965B42181\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301100\x00\x00\x00\x00', + b'\x018821F3301200\x00\x00\x00\x00', + b'\x018821F3301300\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F4203200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F4203300\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F4203400\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F4203500\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F4203700\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F4203800\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_RAV4_TSS2_2022: { + (Ecu.abs, 0x7b0, None): [ + b'\x01F15260R350\x00\x00\x00\x00\x00\x00', + b'\x01F15260R361\x00\x00\x00\x00\x00\x00', + b'\x01F15264283100\x00\x00\x00\x00', + b'\x01F15264283200\x00\x00\x00\x00', + b'\x01F15264286100\x00\x00\x00\x00', + b'\x01F15264286200\x00\x00\x00\x00', + b'\x01F152642870\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x028965B0R01500\x00\x00\x00\x008965B0R02500\x00\x00\x00\x00', + b'8965B42172\x00\x00\x00\x00\x00\x00', + b'8965B42182\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x01896634A02001\x00\x00\x00\x00', + b'\x01896634A02101\x00\x00\x00\x00', + b'\x01896634A03000\x00\x00\x00\x00', + b'\x01896634A08000\x00\x00\x00\x00', + b'\x01896634A59000\x00\x00\x00\x00', + b'\x01896634A61000\x00\x00\x00\x00', + b'\x01896634A62000\x00\x00\x00\x00', + b'\x01896634A62100\x00\x00\x00\x00', + b'\x01896634A63000\x00\x00\x00\x00', + b'\x01896634A88000\x00\x00\x00\x00', + b'\x01896634A89000\x00\x00\x00\x00', + b'\x01896634A89100\x00\x00\x00\x00', + b'\x01896634AA0000\x00\x00\x00\x00', + b'\x01896634AA0100\x00\x00\x00\x00', + b'\x01896634AA1000\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F0R01100\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0R02100\x00\x00\x00\x008646G0R01100\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_RAV4_TSS2_2023: { + (Ecu.abs, 0x7b0, None): [ + b'\x01F15260R440\x00\x00\x00\x00\x00\x00', + b'\x01F15260R450\x00\x00\x00\x00\x00\x00', + b'\x01F15260R50000\x00\x00\x00\x00', + b'\x01F15260R51000\x00\x00\x00\x00', + b'\x01F15264283200\x00\x00\x00\x00', + b'\x01F15264283300\x00\x00\x00\x00', + b'\x01F152642F1000\x00\x00\x00\x00', + b'\x01F152642F8000\x00\x00\x00\x00', + b'\x01F152642F8100\x00\x00\x00\x00', + b'\x01F152642F9000\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x028965B0R11000\x00\x00\x00\x008965B0R12000\x00\x00\x00\x00', + b'8965B42371\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x700, None): [ + b'\x01896634A61000\x00\x00\x00\x00', + b'\x01896634A88100\x00\x00\x00\x00', + b'\x01896634A89100\x00\x00\x00\x00', + b'\x01896634AD7000\x00\x00\x00\x00', + b'\x01896634AE1001\x00\x00\x00\x00', + b'\x01896634AF0000\x00\x00\x00\x00', + b'\x01896634AJ2000\x00\x00\x00\x00', + b'\x01896634AJ3000\x00\x00\x00\x00', + b'\x01896634AL5000\x00\x00\x00\x00', + b'\x01896634AL6000\x00\x00\x00\x00', + b'\x01896634AL8000\x00\x00\x00\x00', + b'\x01896634AS8001\x00\x00\x00\x00', + b'\x01896634AS9000\x00\x00\x00\x00', + b'\x01896634AT7000\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F0R03100\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0R05100\x00\x00\x00\x008646G0R02100\x00\x00\x00\x00', + b'\x028646F0R05200\x00\x00\x00\x008646G0R02200\x00\x00\x00\x00', + b'\x028646F0R05300\x00\x00\x00\x008646G0R02300\x00\x00\x00\x00', + b'\x028646F0R11000\x00\x00\x00\x008646G0R04000\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_SIENNA: { + (Ecu.engine, 0x700, None): [ + b'\x01896630832100\x00\x00\x00\x00', + b'\x01896630832200\x00\x00\x00\x00', + b'\x01896630838000\x00\x00\x00\x00', + b'\x01896630838100\x00\x00\x00\x00', + b'\x01896630842000\x00\x00\x00\x00', + b'\x01896630843000\x00\x00\x00\x00', + b'\x01896630851000\x00\x00\x00\x00', + b'\x01896630851100\x00\x00\x00\x00', + b'\x01896630851200\x00\x00\x00\x00', + b'\x01896630852000\x00\x00\x00\x00', + b'\x01896630852100\x00\x00\x00\x00', + b'\x01896630852200\x00\x00\x00\x00', + b'\x01896630859000\x00\x00\x00\x00', + b'\x01896630860000\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B45070\x00\x00\x00\x00\x00\x00', + b'8965B45080\x00\x00\x00\x00\x00\x00', + b'8965B45082\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152608130\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881510801100\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702200\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F0801100\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_SIENNA_4TH_GEN: { + (Ecu.engine, 0x700, None): [ + b'\x01896630841000\x00\x00\x00\x00', + b'\x01896630857101\x00\x00\x00\x00', + b'\x01896630864000\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15260815100\x00\x00\x00\x00', + b'\x01F15260815300\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x018965B4509100\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301500\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0802200\x00\x00\x00\x008646G4202100\x00\x00\x00\x00', + b'\x028646F0802300\x00\x00\x00\x008646G4202100\x00\x00\x00\x00', + b'\x028646F0802400\x00\x00\x00\x008646G4202100\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_CTH: { + (Ecu.dsu, 0x791, None): [ + b'881517601100\x00\x00\x00\x00', + b'881517602000\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152676144\x00\x00\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0237635000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0237641000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F7601100\x00\x00\x00\x00', + b'8646F7601200\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_ES_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x018966306U6000\x00\x00\x00\x00', + b'\x018966306V5000\x00\x00\x00\x00', + b'\x018966306W6000\x00\x00\x00\x00', + b'\x018966333T5000\x00\x00\x00\x00', + b'\x018966333T5100\x00\x00\x00\x00', + b'\x018966333X6000\x00\x00\x00\x00', + b'\x01896633T07000\x00\x00\x00\x00', + b'\x01896633T38000\x00\x00\x00\x00', + b'\x01896633T58000\x00\x00\x00\x00', + b'\x01896633T63000\x00\x00\x00\x00', + b'\x028966333S8000\x00\x00\x00\x00897CF3302002\x00\x00\x00\x00', + b'\x028966333S8000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966333T0100\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966333V4000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966333W1000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x02896633T09000\x00\x00\x00\x00897CF3307001\x00\x00\x00\x00', + b'\x02896633T10000\x00\x00\x00\x00897CF3307001\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F152606281\x00\x00\x00\x00\x00\x00', + b'\x01F152606340\x00\x00\x00\x00\x00\x00', + b'\x01F152606461\x00\x00\x00\x00\x00\x00', + b'\x01F15260646200\x00\x00\x00\x00', + b'\x01F152633A71\x00\x00\x00\x00\x00\x00', + b'F152633423\x00\x00\x00\x00\x00\x00', + b'F152633680\x00\x00\x00\x00\x00\x00', + b'F152633681\x00\x00\x00\x00\x00\x00', + b'F152633F50\x00\x00\x00\x00\x00\x00', + b'F152633F51\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B33252\x00\x00\x00\x00\x00\x00', + b'8965B33590\x00\x00\x00\x00\x00\x00', + b'8965B33690\x00\x00\x00\x00\x00\x00', + b'8965B33702\x00\x00\x00\x00\x00\x00', + b'8965B33721\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301100\x00\x00\x00\x00', + b'\x018821F3301200\x00\x00\x00\x00', + b'\x018821F3301300\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + b'\x018821F6201200\x00\x00\x00\x00', + b'\x018821F6201300\x00\x00\x00\x00', + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0610000\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F0610100\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F33030D0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F3303100\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F3303200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F3304100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F3304200\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F3304300\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + b'\x028646F3309100\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F3309100\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + b'\x028646F3309400\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_ES: { + (Ecu.engine, 0x7e0, None): [ + b'\x02333M4100\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02333M4200\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02333R0000\x00\x00\x00\x00\x00\x00\x00\x00A0C01000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152606201\x00\x00\x00\x00\x00\x00', + b'F152606202\x00\x00\x00\x00\x00\x00', + b'F152633171\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881513309400\x00\x00\x00\x00', + b'881513309500\x00\x00\x00\x00', + b'881513310400\x00\x00\x00\x00', + b'881513310500\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B33502\x00\x00\x00\x00\x00\x00', + b'8965B33512\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4701100\x00\x00\x00\x00', + b'8821F4701200\x00\x00\x00\x00', + b'8821F4701300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F3302001\x00\x00\x00\x00', + b'8646F3302100\x00\x00\x00\x00', + b'8646F3302200\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_GS_F: { + (Ecu.engine, 0x7e0, None): [ + b'\x0233075200\x00\x00\x00\x00\x00\x00\x00\x00530B9000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152630700\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881513016200\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B30551\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702000\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F3002100\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_NX: { + (Ecu.engine, 0x700, None): [ + b'\x01896637850000\x00\x00\x00\x00', + b'\x01896637851000\x00\x00\x00\x00', + b'\x01896637852000\x00\x00\x00\x00', + b'\x01896637854000\x00\x00\x00\x00', + b'\x01896637873000\x00\x00\x00\x00', + b'\x01896637878000\x00\x00\x00\x00', + b'\x01896637878100\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0237841000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0237842000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0237880000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0237882000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0237886000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152678130\x00\x00\x00\x00\x00\x00', + b'F152678140\x00\x00\x00\x00\x00\x00', + b'F152678160\x00\x00\x00\x00\x00\x00', + b'F152678170\x00\x00\x00\x00\x00\x00', + b'F152678171\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881517803100\x00\x00\x00\x00', + b'881517803300\x00\x00\x00\x00', + b'881517804100\x00\x00\x00\x00', + b'881517804300\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B78060\x00\x00\x00\x00\x00\x00', + b'8965B78080\x00\x00\x00\x00\x00\x00', + b'8965B78100\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702100\x00\x00\x00\x00', + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F7801100\x00\x00\x00\x00', + b'8646F7801300\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_NX_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x018966378B2000\x00\x00\x00\x00', + b'\x018966378B2100\x00\x00\x00\x00', + b'\x018966378B3000\x00\x00\x00\x00', + b'\x018966378B3100\x00\x00\x00\x00', + b'\x018966378B4100\x00\x00\x00\x00', + b'\x018966378G2000\x00\x00\x00\x00', + b'\x018966378G3000\x00\x00\x00\x00', + b'\x018966378G4000\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0237881000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0237887000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02378A0000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02378F4000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F152678221\x00\x00\x00\x00\x00\x00', + b'F152678200\x00\x00\x00\x00\x00\x00', + b'F152678210\x00\x00\x00\x00\x00\x00', + b'F152678211\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B78110\x00\x00\x00\x00\x00\x00', + b'8965B78120\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301200\x00\x00\x00\x00', + b'\x018821F3301300\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F78030A0\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F7803100\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_LC_TSS2: { + (Ecu.engine, 0x7e0, None): [ + b'\x0131126000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0131130000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152611390\x00\x00\x00\x00\x00\x00', + b'F152611430\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B11091\x00\x00\x00\x00\x00\x00', + b'8965B11120\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F1104200\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F1105200\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_RC: { + (Ecu.engine, 0x700, None): [ + b'\x01896632461100\x00\x00\x00\x00', + b'\x01896632478100\x00\x00\x00\x00', + b'\x01896632478200\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x0232480000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0232484000\x00\x00\x00\x00\x00\x00\x00\x0052422000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152624150\x00\x00\x00\x00\x00\x00', + b'F152624171\x00\x00\x00\x00\x00\x00', + b'F152624221\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881512404100\x00\x00\x00\x00', + b'881512405100\x00\x00\x00\x00', + b'881512407000\x00\x00\x00\x00', + b'881512409100\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B24081\x00\x00\x00\x00\x00\x00', + b'8965B24240\x00\x00\x00\x00\x00\x00', + b'8965B24260\x00\x00\x00\x00\x00\x00', + b'8965B24320\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4702300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F2401100\x00\x00\x00\x00', + b'8646F2401200\x00\x00\x00\x00', + b'8646F2402200\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_RC_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x018966324C8000\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15262426000\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B24481\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F6201400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F2403100\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_RX: { + (Ecu.engine, 0x700, None): [ + b'\x01896630E36100\x00\x00\x00\x00', + b'\x01896630E36200\x00\x00\x00\x00', + b'\x01896630E36300\x00\x00\x00\x00', + b'\x01896630E36600\x00\x00\x00\x00', + b'\x01896630E37100\x00\x00\x00\x00', + b'\x01896630E37200\x00\x00\x00\x00', + b'\x01896630E37300\x00\x00\x00\x00', + b'\x01896630E41000\x00\x00\x00\x00', + b'\x01896630E41100\x00\x00\x00\x00', + b'\x01896630E41200\x00\x00\x00\x00', + b'\x01896630E41500\x00\x00\x00\x00', + b'\x01896630EA3100\x00\x00\x00\x00', + b'\x01896630EA3300\x00\x00\x00\x00', + b'\x01896630EA3400\x00\x00\x00\x00', + b'\x01896630EA4100\x00\x00\x00\x00', + b'\x01896630EA4200\x00\x00\x00\x00', + b'\x01896630EA4300\x00\x00\x00\x00', + b'\x01896630EA4400\x00\x00\x00\x00', + b'\x01896630EA6300\x00\x00\x00\x00', + b'\x018966348R1300\x00\x00\x00\x00', + b'\x018966348R8500\x00\x00\x00\x00', + b'\x018966348R9300\x00\x00\x00\x00', + b'\x018966348W1300\x00\x00\x00\x00', + b'\x018966348W2300\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x02348J7000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348N0000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348Q4000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348Q4100\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348T1000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348T1100\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348T1200\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348T3000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348V6000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348Z3000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152648361\x00\x00\x00\x00\x00\x00', + b'F152648472\x00\x00\x00\x00\x00\x00', + b'F152648473\x00\x00\x00\x00\x00\x00', + b'F152648474\x00\x00\x00\x00\x00\x00', + b'F152648492\x00\x00\x00\x00\x00\x00', + b'F152648493\x00\x00\x00\x00\x00\x00', + b'F152648494\x00\x00\x00\x00\x00\x00', + b'F152648501\x00\x00\x00\x00\x00\x00', + b'F152648502\x00\x00\x00\x00\x00\x00', + b'F152648504\x00\x00\x00\x00\x00\x00', + b'F152648630\x00\x00\x00\x00\x00\x00', + b'F152648740\x00\x00\x00\x00\x00\x00', + b'F152648A30\x00\x00\x00\x00\x00\x00', + ], + (Ecu.dsu, 0x791, None): [ + b'881514810300\x00\x00\x00\x00', + b'881514810500\x00\x00\x00\x00', + b'881514810700\x00\x00\x00\x00', + b'881514811300\x00\x00\x00\x00', + b'881514811500\x00\x00\x00\x00', + b'881514811700\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B0E011\x00\x00\x00\x00\x00\x00', + b'8965B0E012\x00\x00\x00\x00\x00\x00', + b'8965B48102\x00\x00\x00\x00\x00\x00', + b'8965B48111\x00\x00\x00\x00\x00\x00', + b'8965B48112\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'8821F4701000\x00\x00\x00\x00', + b'8821F4701100\x00\x00\x00\x00', + b'8821F4701200\x00\x00\x00\x00', + b'8821F4701300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'8646F4801100\x00\x00\x00\x00', + b'8646F4801200\x00\x00\x00\x00', + b'8646F4802001\x00\x00\x00\x00', + b'8646F4802100\x00\x00\x00\x00', + b'8646F4802200\x00\x00\x00\x00', + b'8646F4809000\x00\x00\x00\x00', + ], + }, + CAR.LEXUS_RX_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x01896630EA9000\x00\x00\x00\x00', + b'\x01896630EB0000\x00\x00\x00\x00', + b'\x01896630EC9000\x00\x00\x00\x00', + b'\x01896630EC9100\x00\x00\x00\x00', + b'\x01896630ED0000\x00\x00\x00\x00', + b'\x01896630ED0100\x00\x00\x00\x00', + b'\x01896630ED5000\x00\x00\x00\x00', + b'\x01896630ED6000\x00\x00\x00\x00', + b'\x018966348R9200\x00\x00\x00\x00', + b'\x018966348T8000\x00\x00\x00\x00', + b'\x018966348W5100\x00\x00\x00\x00', + b'\x018966348W9000\x00\x00\x00\x00', + b'\x018966348X0000\x00\x00\x00\x00', + b'\x01896634D11000\x00\x00\x00\x00', + b'\x01896634D12000\x00\x00\x00\x00', + b'\x01896634D12100\x00\x00\x00\x00', + b'\x01896634D43000\x00\x00\x00\x00', + b'\x01896634D44000\x00\x00\x00\x00', + ], + (Ecu.engine, 0x7e0, None): [ + b'\x02348U2000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348X4000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348X5000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348X6000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348X8000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x02348Y3000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0234D14000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0234D15000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0234D16000\x00\x00\x00\x00\x00\x00\x00\x00A4802000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15260E031\x00\x00\x00\x00\x00\x00', + b'\x01F15260E041\x00\x00\x00\x00\x00\x00', + b'\x01F152648781\x00\x00\x00\x00\x00\x00', + b'\x01F152648801\x00\x00\x00\x00\x00\x00', + b'F152648493\x00\x00\x00\x00\x00\x00', + b'F152648811\x00\x00\x00\x00\x00\x00', + b'F152648831\x00\x00\x00\x00\x00\x00', + b'F152648891\x00\x00\x00\x00\x00\x00', + b'F152648C80\x00\x00\x00\x00\x00\x00', + b'F152648D00\x00\x00\x00\x00\x00\x00', + b'F152648D60\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B48261\x00\x00\x00\x00\x00\x00', + b'8965B48271\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301100\x00\x00\x00\x00', + b'\x018821F3301300\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F4810100\x00\x00\x00\x008646G2601200\x00\x00\x00\x00', + b'\x028646F4810200\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F4810300\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F4810400\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_PRIUS_TSS2: { + (Ecu.engine, 0x700, None): [ + b'\x028966347B1000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347C4000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347C6000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347C7000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x028966347C8000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00', + b'\x038966347C0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710101\x00\x00\x00\x00', + b'\x038966347C0000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710102\x00\x00\x00\x00', + b'\x038966347C1000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4710101\x00\x00\x00\x00', + b'\x038966347C5000\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4707101\x00\x00\x00\x00', + b'\x038966347C5100\x00\x00\x00\x008966A4703000\x00\x00\x00\x00897CF4707101\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152647500\x00\x00\x00\x00\x00\x00', + b'F152647510\x00\x00\x00\x00\x00\x00', + b'F152647520\x00\x00\x00\x00\x00\x00', + b'F152647521\x00\x00\x00\x00\x00\x00', + b'F152647531\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B47070\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301300\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F4707000\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646F4710000\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + b'\x028646F4712000\x00\x00\x00\x008646G2601500\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_MIRAI: { + (Ecu.abs, 0x7d1, None): [ + b'\x01898A36203000\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F15266203200\x00\x00\x00\x00', + b'\x01F15266203500\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x028965B6204100\x00\x00\x00\x008965B6203100\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F6201200\x00\x00\x00\x00', + b'\x018821F6201300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F6201400\x00\x00\x00\x008646G3304000\x00\x00\x00\x00', + b'\x028646F6201400\x00\x00\x00\x008646G5301200\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_ALPHARD_TSS2: { + (Ecu.engine, 0x7e0, None): [ + b'\x0235852100\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0235870000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0235879000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00', + b'\x0235883000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'8965B58040\x00\x00\x00\x00\x00\x00', + b'8965B58052\x00\x00\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'F152658160\x00\x00\x00\x00\x00\x00', + b'F152658320\x00\x00\x00\x00\x00\x00', + b'F152658341\x00\x00\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F3301000\x00\x00\x00\x00', + b'\x018821F3301200\x00\x00\x00\x00', + b'\x018821F3301400\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F58010B0\x00\x00\x00\x008646G2601003\x00\x00\x00\x00', + b'\x028646F58010C0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', + b'\x028646F5803200\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + b'\x028646FV201000\x00\x00\x00\x008646G2601400\x00\x00\x00\x00', + ], + }, + CAR.TOYOTA_YARIS: { + (Ecu.engine, 0x700, None): [ + b'\x0189663K015300\x00\x00\x00\x00', + b'\x0189663K023000\x00\x00\x00\x00', + ], + (Ecu.eps, 0x7a1, None): [ + b'\x018965BK002100\x00\x00\x00\x00', + b'\x018965BK003200\x00\x00\x00\x00', + ], + (Ecu.abs, 0x7b0, None): [ + b'\x01F1526K005600\x00\x00\x00\x00', + b'\x01F1526K007500\x00\x00\x00\x00', + ], + (Ecu.fwdRadar, 0x750, 0xf): [ + b'\x018821F0D04100\x00\x00\x00\x00', + b'\x018821F0D05300\x00\x00\x00\x00', + ], + (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F0W04100\x00\x00\x00\x008646G0W04100\x00\x00\x00\x00', + b'\x028646F5205200\x00\x00\x00\x008646G5202200\x00\x00\x00\x00', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/toyota/interface.py b/opendbc_repo/opendbc/car/toyota/interface.py new file mode 100644 index 0000000000..b8ee8c946b --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/interface.py @@ -0,0 +1,168 @@ +from opendbc.car import Bus, structs, get_safety_config, uds +from opendbc.car.toyota.carstate import CarState +from opendbc.car.toyota.carcontroller import CarController +from opendbc.car.toyota.radar_interface import RadarInterface +from opendbc.car.toyota.values import Ecu, CAR, DBC, ToyotaFlags, CarControllerParams, TSS2_CAR, RADAR_ACC_CAR, NO_DSU_CAR, \ + MIN_ACC_SPEED, EPS_SCALE, UNSUPPORTED_DSU_CAR, NO_STOP_TIMER_CAR, ANGLE_CONTROL_CAR, \ + ToyotaSafetyFlags +from opendbc.car.disable_ecu import disable_ecu +from opendbc.car.interfaces import CarInterfaceBase + +SteerControlType = structs.CarParams.SteerControlType + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + RadarInterface = RadarInterface + + @staticmethod + def get_pid_accel_limits(CP, current_speed, cruise_speed): + return CarControllerParams(CP).ACCEL_MIN, CarControllerParams(CP).ACCEL_MAX + + @staticmethod + def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "toyota" + ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.toyota)] + ret.safetyConfigs[0].safetyParam = EPS_SCALE[candidate] + + # BRAKE_MODULE is on a different address for these cars + if DBC[candidate][Bus.pt] == "toyota_new_mc_pt_generated": + ret.safetyConfigs[0].safetyParam |= ToyotaSafetyFlags.ALT_BRAKE.value + + if ret.flags & ToyotaFlags.SECOC.value: + ret.secOcRequired = True + ret.safetyConfigs[0].safetyParam |= ToyotaSafetyFlags.SECOC.value + ret.dashcamOnly = is_release + + if candidate in ANGLE_CONTROL_CAR: + ret.steerControlType = SteerControlType.angle + ret.safetyConfigs[0].safetyParam |= ToyotaSafetyFlags.LTA.value + + # LTA control can be more delayed and winds up more often + ret.steerActuatorDelay = 0.18 + ret.steerLimitTimer = 0.8 + else: + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + + ret.steerActuatorDelay = 0.12 # Default delay, Prius has larger delay + ret.steerLimitTimer = 0.4 + + stop_and_go = candidate in TSS2_CAR + + # In TSS2 cars, the camera does long control + found_ecus = [fw.ecu for fw in car_fw] + ret.enableDsu = len(found_ecus) > 0 and Ecu.dsu not in found_ecus and candidate not in (NO_DSU_CAR | UNSUPPORTED_DSU_CAR) + + if Ecu.hybrid in found_ecus: + ret.flags |= ToyotaFlags.HYBRID.value + + if candidate == CAR.TOYOTA_PRIUS: + stop_and_go = True + # Only give steer angle deadzone to for bad angle sensor prius + for fw in car_fw: + if fw.ecu == "eps" and not fw.fwVersion == b'8965B47060\x00\x00\x00\x00\x00\x00': + ret.steerActuatorDelay = 0.25 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, steering_angle_deadzone_deg=0.2) + + elif candidate in (CAR.LEXUS_RX, CAR.LEXUS_RX_TSS2): + stop_and_go = True + ret.wheelSpeedFactor = 1.035 + + elif candidate in (CAR.TOYOTA_AVALON, CAR.TOYOTA_AVALON_2019, CAR.TOYOTA_AVALON_TSS2): + # starting from 2019, all Avalon variants have stop and go + # https://engage.toyota.com/static/images/toyota_safety_sense/TSS_Applicability_Chart.pdf + stop_and_go = candidate != CAR.TOYOTA_AVALON + + elif candidate in (CAR.TOYOTA_RAV4_TSS2, CAR.TOYOTA_RAV4_TSS2_2022, CAR.TOYOTA_RAV4_TSS2_2023, CAR.TOYOTA_RAV4_PRIME, CAR.TOYOTA_SIENNA_4TH_GEN): + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kiBP = [0.0] + ret.lateralTuning.pid.kpBP = [0.0] + ret.lateralTuning.pid.kpV = [0.6] + ret.lateralTuning.pid.kiV = [0.1] + ret.lateralTuning.pid.kf = 0.00007818594 + + # 2019+ RAV4 TSS2 uses two different steering racks and specific tuning seems to be necessary. + # See https://github.com/commaai/openpilot/pull/21429#issuecomment-873652891 + for fw in car_fw: + if fw.ecu == "eps" and (fw.fwVersion.startswith(b'\x02') or fw.fwVersion in [b'8965B42181\x00\x00\x00\x00\x00\x00']): + ret.lateralTuning.pid.kpV = [0.15] + ret.lateralTuning.pid.kiV = [0.05] + ret.lateralTuning.pid.kf = 0.00004 + break + + elif candidate in (CAR.TOYOTA_CHR, CAR.TOYOTA_CAMRY, CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_NX): + # TODO: Some of these platforms are not advertised to have full range ACC, are they similar to SNG_WITHOUT_DSU cars? + stop_and_go = True + + # TODO: these models can do stop and go, but unclear if it requires sDSU or unplugging DSU. + # For now, don't list stop and go functionality in the docs + if ret.flags & ToyotaFlags.SNG_WITHOUT_DSU: + stop_and_go = stop_and_go or (ret.enableDsu and not docs) + + ret.centerToFront = ret.wheelbase * 0.44 + + # TODO: Some TSS-P platforms have BSM, but are flipped based on region or driving direction. + # Detect flipped signals and enable for C-HR and others + ret.enableBsm = 0x3F6 in fingerprint[0] and candidate in TSS2_CAR + + # No radar dbc for cars without DSU which are not TSS 2.0 + # TODO: make an adas dbc file for dsu-less models + ret.radarUnavailable = Bus.radar not in DBC[candidate] or candidate in (NO_DSU_CAR - TSS2_CAR) + + # since we don't yet parse radar on TSS2/TSS-P radar-based ACC cars, gate longitudinal behind experimental toggle + if candidate in (RADAR_ACC_CAR | NO_DSU_CAR): + ret.alphaLongitudinalAvailable = candidate in RADAR_ACC_CAR + + # Disabling radar is only supported on TSS2 radar-ACC cars + if alpha_long and candidate in RADAR_ACC_CAR: + ret.flags |= ToyotaFlags.DISABLE_RADAR.value + + # openpilot longitudinal enabled by default: + # - cars w/ DSU disconnected + # - TSS2 cars with camera sending ACC_CONTROL where we can block it + # openpilot longitudinal behind experimental long toggle: + # - TSS2 radar ACC cars (disables radar) + + if ret.flags & ToyotaFlags.SECOC.value: + ret.openpilotLongitudinalControl = False + else: + ret.openpilotLongitudinalControl = ret.enableDsu or \ + candidate in (TSS2_CAR - RADAR_ACC_CAR) or \ + bool(ret.flags & ToyotaFlags.DISABLE_RADAR.value) + + ret.autoResumeSng = ret.openpilotLongitudinalControl and candidate in NO_STOP_TIMER_CAR + + if not ret.openpilotLongitudinalControl: + ret.safetyConfigs[0].safetyParam |= ToyotaSafetyFlags.STOCK_LONGITUDINAL.value + + # min speed to enable ACC. if car can do stop and go, then set enabling speed + # to a negative value, so it won't matter. + ret.minEnableSpeed = -1. if stop_and_go else MIN_ACC_SPEED + + if candidate in TSS2_CAR: + ret.flags |= ToyotaFlags.RAISED_ACCEL_LIMIT.value + + ret.vEgoStopping = 0.25 + ret.vEgoStarting = 0.25 + ret.stoppingDecelRate = 0.3 # reach stopping target smoothly + + # Hybrids have much quicker longitudinal actuator response + if ret.flags & ToyotaFlags.HYBRID.value: + ret.longitudinalActuatorDelay = 0.05 + + return ret + + @staticmethod + def init(CP, can_recv, can_send, communication_control=None): + # disable radar if alpha longitudinal toggled on radar-ACC car + if CP.flags & ToyotaFlags.DISABLE_RADAR.value: + if communication_control is None: + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, uds.CONTROL_TYPE.ENABLE_RX_DISABLE_TX, uds.MESSAGE_TYPE.NORMAL]) + disable_ecu(can_recv, can_send, bus=0, addr=0x750, sub_addr=0xf, com_cont_req=communication_control) + + @staticmethod + def deinit(CP, can_recv, can_send): + # re-enable radar if alpha longitudinal toggled on radar-ACC car + communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL, uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX, uds.MESSAGE_TYPE.NORMAL]) + CarInterface.init(CP, can_recv, can_send, communication_control) diff --git a/opendbc_repo/opendbc/car/toyota/radar_interface.py b/opendbc_repo/opendbc/car/toyota/radar_interface.py new file mode 100755 index 0000000000..2c166ff5b1 --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/radar_interface.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 +from opendbc.can import CANParser +from opendbc.car import Bus +from opendbc.car.structs import RadarData +from opendbc.car.toyota.values import DBC, TSS2_CAR +from opendbc.car.interfaces import RadarInterfaceBase + + +def _create_radar_can_parser(car_fingerprint): + if car_fingerprint in TSS2_CAR: + RADAR_A_MSGS = list(range(0x180, 0x190)) + RADAR_B_MSGS = list(range(0x190, 0x1a0)) + else: + RADAR_A_MSGS = list(range(0x210, 0x220)) + RADAR_B_MSGS = list(range(0x220, 0x230)) + + msg_a_n = len(RADAR_A_MSGS) + msg_b_n = len(RADAR_B_MSGS) + messages = list(zip(RADAR_A_MSGS + RADAR_B_MSGS, [20] * (msg_a_n + msg_b_n), strict=True)) + + return CANParser(DBC[car_fingerprint][Bus.radar], messages, 1) + + +class RadarInterface(RadarInterfaceBase): + def __init__(self, CP): + super().__init__(CP) + self.track_id = 0 + + if CP.carFingerprint in TSS2_CAR: + self.RADAR_A_MSGS = list(range(0x180, 0x190)) + self.RADAR_B_MSGS = list(range(0x190, 0x1a0)) + else: + self.RADAR_A_MSGS = list(range(0x210, 0x220)) + self.RADAR_B_MSGS = list(range(0x220, 0x230)) + + self.valid_cnt = {key: 0 for key in self.RADAR_A_MSGS} + + self.rcp = None if CP.radarUnavailable else _create_radar_can_parser(CP.carFingerprint) + self.trigger_msg = self.RADAR_B_MSGS[-1] + self.updated_messages = set() + + def update(self, can_strings): + if self.rcp is None: + return super().update(None) + + vls = self.rcp.update(can_strings) + self.updated_messages.update(vls) + + if self.trigger_msg not in self.updated_messages: + return None + + rr = self._update(self.updated_messages) + self.updated_messages.clear() + + return rr + + def _update(self, updated_messages): + ret = RadarData() + if not self.rcp.can_valid: + ret.errors.canError = True + + for ii in sorted(updated_messages): + if ii in self.RADAR_A_MSGS: + cpt = self.rcp.vl[ii] + + if cpt['LONG_DIST'] >= 255 or cpt['NEW_TRACK']: + self.valid_cnt[ii] = 0 # reset counter + if cpt['VALID'] and cpt['LONG_DIST'] < 255: + self.valid_cnt[ii] += 1 + else: + self.valid_cnt[ii] = max(self.valid_cnt[ii] - 1, 0) + + score = self.rcp.vl[ii+16]['SCORE'] + # print ii, self.valid_cnt[ii], score, cpt['VALID'], cpt['LONG_DIST'], cpt['LAT_DIST'] + + # radar point only valid if it's a valid measurement and score is above 50 + if cpt['VALID'] or (score > 50 and cpt['LONG_DIST'] < 255 and self.valid_cnt[ii] > 0): + if ii not in self.pts or cpt['NEW_TRACK']: + self.pts[ii] = RadarData.RadarPoint() + self.pts[ii].trackId = self.track_id + self.track_id += 1 + self.pts[ii].dRel = cpt['LONG_DIST'] # from front of car + self.pts[ii].yRel = -cpt['LAT_DIST'] # in car frame's y axis, left is positive + self.pts[ii].vRel = cpt['REL_SPEED'] + self.pts[ii].aRel = float('nan') + self.pts[ii].yvRel = float('nan') + self.pts[ii].measured = bool(cpt['VALID']) + else: + if ii in self.pts: + del self.pts[ii] + + ret.points = list(self.pts.values()) + return ret diff --git a/opendbc_repo/opendbc/car/toyota/tests/__init__.py b/opendbc_repo/opendbc/car/toyota/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/toyota/tests/print_platform_codes.py b/opendbc_repo/opendbc/car/toyota/tests/print_platform_codes.py new file mode 100755 index 0000000000..333e7dca26 --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/tests/print_platform_codes.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +from collections import defaultdict +from opendbc.car.toyota.values import PLATFORM_CODE_ECUS, get_platform_codes +from opendbc.car.toyota.fingerprints import FW_VERSIONS + +if __name__ == "__main__": + parts_for_ecu: dict = defaultdict(set) + cars_for_code: dict = defaultdict(lambda: defaultdict(set)) + for car_model, ecus in FW_VERSIONS.items(): + print() + print(car_model) + for ecu in sorted(ecus): + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + platform_codes = get_platform_codes(ecus[ecu]) + parts_for_ecu[ecu] |= {code.split(b'-')[0] for code in platform_codes if code.count(b'-') > 1} + for code in platform_codes: + cars_for_code[ecu][b'-'.join(code.split(b'-')[:2])] |= {car_model} + print(f' (Ecu.{ecu[0]}, {hex(ecu[1])}, {ecu[2]}):') + print(f' Codes: {platform_codes}') + + print('\nECU parts:') + for ecu, parts in parts_for_ecu.items(): + print(f' (Ecu.{ecu[0]}, {hex(ecu[1])}, {ecu[2]}): {parts}') + + print('\nCar models vs. platform codes (no major versions):') + for ecu, codes in cars_for_code.items(): + print(f' (Ecu.{ecu[0]}, {hex(ecu[1])}, {ecu[2]}):') + for code, cars in codes.items(): + print(f' {code!r}: {sorted(cars)}') diff --git a/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py b/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py new file mode 100644 index 0000000000..5ab47f3565 --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/tests/test_toyota.py @@ -0,0 +1,167 @@ +from hypothesis import given, settings, strategies as st + +from opendbc.car import Bus +from opendbc.car.structs import CarParams +from opendbc.car.fw_versions import build_fw_dict +from opendbc.car.toyota.fingerprints import FW_VERSIONS +from opendbc.car.toyota.values import CAR, DBC, TSS2_CAR, ANGLE_CONTROL_CAR, RADAR_ACC_CAR, SECOC_CAR, \ + FW_QUERY_CONFIG, PLATFORM_CODE_ECUS, FUZZY_EXCLUDED_PLATFORMS, \ + get_platform_codes + +Ecu = CarParams.Ecu + + +def check_fw_version(fw_version: bytes) -> bool: + # TODO: just use the FW patterns, need to support all chunks + return b'?' not in fw_version and b'!' not in fw_version + + +class TestToyotaInterfaces: + def test_car_sets(self): + assert len(ANGLE_CONTROL_CAR - TSS2_CAR) == 0 + assert len(RADAR_ACC_CAR - TSS2_CAR) == 0 + + def test_lta_platforms(self): + # At this time, only RAV4 2023 is expected to use LTA/angle control + assert ANGLE_CONTROL_CAR == {CAR.TOYOTA_RAV4_TSS2_2023} + + def test_tss2_dbc(self): + # We make some assumptions about TSS2 platforms, + # like looking up certain signals only in this DBC + for car_model, dbc in DBC.items(): + if car_model in TSS2_CAR and car_model not in SECOC_CAR: + assert dbc[Bus.pt] == "toyota_nodsu_pt_generated" + + def test_essential_ecus(self, subtests): + # Asserts standard ECUs exist for each platform + common_ecus = {Ecu.fwdRadar, Ecu.fwdCamera} + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + present_ecus = {ecu[0] for ecu in ecus} + missing_ecus = common_ecus - present_ecus + assert len(missing_ecus) == 0 + + # Some exceptions for other common ECUs + if car_model not in (CAR.TOYOTA_ALPHARD_TSS2,): + assert Ecu.abs in present_ecus + + if car_model not in (CAR.TOYOTA_MIRAI,): + assert Ecu.engine in present_ecus + + if car_model not in (CAR.TOYOTA_PRIUS_V, CAR.LEXUS_CTH): + assert Ecu.eps in present_ecus + + +class TestToyotaFingerprint: + def test_non_essential_ecus(self, subtests): + # Ensures only the cars that have multiple engine ECUs are in the engine non-essential ECU list + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + engine_ecus = {ecu for ecu in ecus if ecu[0] == Ecu.engine} + assert (len(engine_ecus) > 1) == (car_model in FW_QUERY_CONFIG.non_essential_ecus[Ecu.engine]), \ + f"Car model unexpectedly {'not ' if len(engine_ecus) > 1 else ''}in non-essential list" + + def test_valid_fw_versions(self, subtests): + # Asserts all FW versions are valid + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for fws in ecus.values(): + for fw in fws: + assert check_fw_version(fw), fw + + # Tests for part numbers, platform codes, and sub-versions which Toyota will use to fuzzy + # fingerprint in the absence of full FW matches: + @settings(max_examples=100) + @given(data=st.data()) + def test_platform_codes_fuzzy_fw(self, data): + fw_strategy = st.lists(st.binary()) + fws = data.draw(fw_strategy) + get_platform_codes(fws) + + def test_platform_code_ecus_available(self, subtests): + # Asserts ECU keys essential for fuzzy fingerprinting are available on all platforms + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for platform_code_ecu in PLATFORM_CODE_ECUS: + if platform_code_ecu == Ecu.eps and car_model in (CAR.TOYOTA_PRIUS_V, CAR.LEXUS_CTH,): + continue + if platform_code_ecu == Ecu.abs and car_model in (CAR.TOYOTA_ALPHARD_TSS2,): + continue + assert platform_code_ecu in [e[0] for e in ecus] + + def test_fw_format(self, subtests): + # Asserts: + # - every supported ECU FW version returns one platform code + # - every supported ECU FW version has a part number + # - expected parsing of ECU sub-versions + + for car_model, ecus in FW_VERSIONS.items(): + with subtests.test(car_model=car_model.value): + for ecu, fws in ecus.items(): + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + codes = dict() + for fw in fws: + result = get_platform_codes([fw]) + # Check only one platform code and sub-version + assert 1 == len(result), f"Unable to parse FW: {fw}" + assert 1 == len(list(result.values())[0]), f"Unable to parse FW: {fw}" + codes |= result + + # Toyota places the ECU part number in their FW versions, assert all parsable + # Note that there is only one unique part number per ECU across the fleet, so this + # is not important for identification, just a sanity check. + assert all(code.count(b"-") > 1 for code in codes), f"FW does not have part number: {fw} {codes}" + + def test_platform_codes_spot_check(self): + # Asserts basic platform code parsing behavior for a few cases + results = get_platform_codes([ + b"F152607140\x00\x00\x00\x00\x00\x00", + b"F152607171\x00\x00\x00\x00\x00\x00", + b"F152607110\x00\x00\x00\x00\x00\x00", + b"F152607180\x00\x00\x00\x00\x00\x00", + ]) + assert results == {b"F1526-07-1": {b"10", b"40", b"71", b"80"}} + + results = get_platform_codes([ + b"\x028646F4104100\x00\x00\x00\x008646G5301200\x00\x00\x00\x00", + b"\x028646F4104100\x00\x00\x00\x008646G3304000\x00\x00\x00\x00", + ]) + assert results == {b"8646F-41-04": {b"100"}} + + # Short version has no part number + results = get_platform_codes([ + b"\x0235870000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00", + b"\x0235883000\x00\x00\x00\x00\x00\x00\x00\x00A0202000\x00\x00\x00\x00\x00\x00\x00\x00", + ]) + assert results == {b"58-70": {b"000"}, b"58-83": {b"000"}} + + results = get_platform_codes([ + b"F152607110\x00\x00\x00\x00\x00\x00", + b"F152607140\x00\x00\x00\x00\x00\x00", + b"\x028646F4104100\x00\x00\x00\x008646G5301200\x00\x00\x00\x00", + b"\x0235879000\x00\x00\x00\x00\x00\x00\x00\x00A4701000\x00\x00\x00\x00\x00\x00\x00\x00", + ]) + assert results == {b"F1526-07-1": {b"10", b"40"}, b"8646F-41-04": {b"100"}, b"58-79": {b"000"}} + + def test_fuzzy_excluded_platforms(self): + # Asserts a list of platforms that will not fuzzy fingerprint with platform codes due to them being shared. + platforms_with_shared_codes = set() + for platform, fw_by_addr in FW_VERSIONS.items(): + car_fw = [] + for ecu, fw_versions in fw_by_addr.items(): + ecu_name, addr, sub_addr = ecu + for fw in fw_versions: + car_fw.append(CarParams.CarFw(ecu=ecu_name, fwVersion=fw, address=addr, + subAddress=0 if sub_addr is None else sub_addr)) + + CP = CarParams(carFw=car_fw) + matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw), CP.carVin, FW_VERSIONS) + if len(matches) == 1: + assert list(matches)[0] == platform + else: + # If a platform has multiple matches, add it and its matches + platforms_with_shared_codes |= {str(platform), *matches} + + assert platforms_with_shared_codes == FUZZY_EXCLUDED_PLATFORMS, (len(platforms_with_shared_codes), len(FW_VERSIONS)) diff --git a/opendbc_repo/opendbc/car/toyota/toyotacan.py b/opendbc_repo/opendbc/car/toyota/toyotacan.py new file mode 100644 index 0000000000..1ca3ca5ef6 --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/toyotacan.py @@ -0,0 +1,159 @@ +from opendbc.car.structs import CarParams + +SteerControlType = CarParams.SteerControlType + + +def create_steer_command(packer, steer, steer_req): + """Creates a CAN message for the Toyota Steer Command.""" + + values = { + "STEER_REQUEST": steer_req, + "STEER_TORQUE_CMD": steer, + "SET_ME_1": 1, + } + return packer.make_can_msg("STEERING_LKA", 0, values) + + +def create_lta_steer_command(packer, steer_control_type, steer_angle, steer_req, frame, torque_wind_down): + """Creates a CAN message for the Toyota LTA Steer Command.""" + + values = { + "COUNTER": frame + 128, + "SETME_X1": 1, # suspected LTA feature availability + # 1 for TSS 2.5 cars, 3 for TSS 2.0. Send based on whether we're using LTA for lateral control + "SETME_X3": 1 if steer_control_type == SteerControlType.angle else 3, + "PERCENTAGE": 100, + "TORQUE_WIND_DOWN": torque_wind_down, + "ANGLE": 0, + "STEER_ANGLE_CMD": steer_angle, + "STEER_REQUEST": steer_req, + "STEER_REQUEST_2": steer_req, + "CLEAR_HOLD_STEERING_ALERT": 0, + } + return packer.make_can_msg("STEERING_LTA", 0, values) + + +def create_lta_steer_command_2(packer, frame): + values = { + "COUNTER": frame + 128, + } + return packer.make_can_msg("STEERING_LTA_2", 0, values) + + +def create_accel_command(packer, accel, pcm_cancel, permit_braking, standstill_req, lead, acc_type, fcw_alert, distance): + # TODO: find the exact canceling bit that does not create a chime + values = { + "ACCEL_CMD": accel, + "ACC_TYPE": acc_type, + "DISTANCE": distance, + "MINI_CAR": lead, + "PERMIT_BRAKING": permit_braking, + "RELEASE_STANDSTILL": not standstill_req, + "CANCEL_REQ": pcm_cancel, + "ALLOW_LONG_PRESS": 1, + "ACC_CUT_IN": fcw_alert, # only shown when ACC enabled + } + return packer.make_can_msg("ACC_CONTROL", 0, values) + + +def create_pcs_commands(packer, accel, active, mass): + values1 = { + "COUNTER": 0, + "FORCE": round(min(accel, 0) * mass * 2), + "STATE": 3 if active else 0, + "BRAKE_STATUS": 0, + "PRECOLLISION_ACTIVE": 1 if active else 0, + } + msg1 = packer.make_can_msg("PRE_COLLISION", 0, values1) + + values2 = { + "DSS1GDRV": min(accel, 0), # accel + "PCSALM": 1 if active else 0, # goes high same time as PRECOLLISION_ACTIVE + "IBTRGR": 1 if active else 0, # unknown + "PBATRGR": 1 if active else 0, # noisy actuation bit? + "PREFILL": 1 if active else 0, # goes on and off before DSS1GDRV + "AVSTRGR": 1 if active else 0, + } + msg2 = packer.make_can_msg("PRE_COLLISION_2", 0, values2) + + return [msg1, msg2] + + +def create_acc_cancel_command(packer): + values = { + "GAS_RELEASED": 0, + "CRUISE_ACTIVE": 0, + "ACC_BRAKING": 0, + "ACCEL_NET": 0, + "CRUISE_STATE": 0, + "CANCEL_REQ": 1, + } + return packer.make_can_msg("PCM_CRUISE", 0, values) + + +def create_fcw_command(packer, fcw): + values = { + "PCS_INDICATOR": 1, # PCS turned off + "FCW": fcw, + "SET_ME_X20": 0x20, + "SET_ME_X10": 0x10, + "PCS_OFF": 1, + "PCS_SENSITIVITY": 0, + } + return packer.make_can_msg("PCS_HUD", 0, values) + + +def create_ui_command(packer, steer, chime, left_line, right_line, left_lane_depart, right_lane_depart, enabled, stock_lkas_hud): + values = { + "TWO_BEEPS": chime, + "LDA_ALERT": steer, + "RIGHT_LINE": 3 if right_lane_depart else 1 if right_line else 2, + "LEFT_LINE": 3 if left_lane_depart else 1 if left_line else 2, + "BARRIERS": 1 if enabled else 0, + + # static signals + "SET_ME_X02": 2, + "SET_ME_X01": 1, + "LKAS_STATUS": 1, + "REPEATED_BEEPS": 0, + "LANE_SWAY_FLD": 7, + "LANE_SWAY_BUZZER": 0, + "LANE_SWAY_WARNING": 0, + "LDA_FRONT_CAMERA_BLOCKED": 0, + "TAKE_CONTROL": 0, + "LANE_SWAY_SENSITIVITY": 2, + "LANE_SWAY_TOGGLE": 1, + "LDA_ON_MESSAGE": 0, + "LDA_MESSAGES": 0, + "LDA_SA_TOGGLE": 1, + "LDA_SENSITIVITY": 2, + "LDA_UNAVAILABLE": 0, + "LDA_MALFUNCTION": 0, + "LDA_UNAVAILABLE_QUIET": 0, + "ADJUSTING_CAMERA": 0, + "LDW_EXIST": 1, + } + + # lane sway functionality + # not all cars have LKAS_HUD — update with camera values if available + if len(stock_lkas_hud): + values.update({s: stock_lkas_hud[s] for s in [ + "LANE_SWAY_FLD", + "LANE_SWAY_BUZZER", + "LANE_SWAY_WARNING", + "LANE_SWAY_SENSITIVITY", + "LANE_SWAY_TOGGLE", + ]}) + + return packer.make_can_msg("LKAS_HUD", 0, values) + + +def toyota_checksum(address: int, sig, d: bytearray) -> int: + s = len(d) + addr = address + while addr: + s += addr & 0xFF + addr >>= 8 + for i in range(len(d) - 1): + s += d[i] + return s & 0xFF diff --git a/opendbc_repo/opendbc/car/toyota/values.py b/opendbc_repo/opendbc/car/toyota/values.py new file mode 100644 index 0000000000..fa6f96e73f --- /dev/null +++ b/opendbc_repo/opendbc/car/toyota/values.py @@ -0,0 +1,635 @@ +import re +from collections import defaultdict +from dataclasses import dataclass, field +from enum import Enum, IntFlag + +from opendbc.car import Bus, CarSpecs, PlatformConfig, Platforms +from opendbc.car.lateral import AngleSteeringLimits +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.structs import CarParams +from opendbc.car.docs_definitions import CarFootnote, CarDocs, Column, CarParts, CarHarness, SupportType +from opendbc.car.fw_query_definitions import FwQueryConfig, Request, StdQueries + +Ecu = CarParams.Ecu +MIN_ACC_SPEED = 19. * CV.MPH_TO_MS +PEDAL_TRANSITION = 10. * CV.MPH_TO_MS + + +class CarControllerParams: + STEER_STEP = 1 + STEER_MAX = 1500 + STEER_ERROR_MAX = 350 # max delta between torque cmd and torque motor + + # Lane Tracing Assist (LTA) control limits + ANGLE_LIMITS: AngleSteeringLimits = AngleSteeringLimits( + # EPS ignores commands above this angle and causes PCS to fault + 94.9461, # deg + # Assuming a steering ratio of 13.7: + # Limit to ~2.0 m/s^3 up (7.5 deg/s), ~3.5 m/s^3 down (13 deg/s) at 75 mph + # Worst case, the low speed limits will allow ~4.0 m/s^3 up (15 deg/s) and ~4.9 m/s^3 down (18 deg/s) at 75 mph, + # however the EPS has its own internal limits at all speeds which are less than that: + # Observed internal torque rate limit on TSS 2.5 Camry and RAV4 is ~1500 units/sec up and down when using LTA + ([5, 25], [0.3, 0.15]), + ([5, 25], [0.36, 0.26]), + ) + + MAX_LTA_DRIVER_TORQUE_ALLOWANCE = 150 # slightly above steering pressed allows some resistance when changing lanes + + def __init__(self, CP): + if CP.flags & ToyotaFlags.RAISED_ACCEL_LIMIT: + self.ACCEL_MAX = 2.0 + else: + self.ACCEL_MAX = 1.5 # m/s2, lower than allowed 2.0 m/s^2 for tuning reasons + self.ACCEL_MIN = -3.5 # m/s2 + + if CP.lateralTuning.which() == 'torque': + self.STEER_DELTA_UP = 15 # 1.0s time to peak torque + self.STEER_DELTA_DOWN = 25 # always lower than 45 otherwise the Rav4 faults (Prius seems ok with 50) + else: + self.STEER_DELTA_UP = 10 # 1.5s time to peak torque + self.STEER_DELTA_DOWN = 25 # always lower than 45 otherwise the Rav4 faults (Prius seems ok with 50) + + +class ToyotaSafetyFlags(IntFlag): + # first byte is for EPS scaling factor + ALT_BRAKE = (1 << 8) + STOCK_LONGITUDINAL = (2 << 8) + LTA = (4 << 8) + SECOC = (8 << 8) + + +class ToyotaFlags(IntFlag): + # Detected flags + HYBRID = 1 + DISABLE_RADAR = 4 + + # Static flags + TSS2 = 8 + NO_DSU = 16 + UNSUPPORTED_DSU = 32 + RADAR_ACC = 64 + # these cars use the Lane Tracing Assist (LTA) message for lateral control + ANGLE_CONTROL = 128 + NO_STOP_TIMER = 256 + # these cars are speculated to allow stop and go when the DSU is unplugged + SNG_WITHOUT_DSU = 512 + # these cars can utilize 2.0 m/s^2 + RAISED_ACCEL_LIMIT = 1024 + SECOC = 2048 + + +def dbc_dict(pt, radar): + return {Bus.pt: pt, Bus.radar: radar} + + +class Footnote(Enum): + CAMRY = CarFootnote( + "openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control.", + Column.FSR_LONGITUDINAL) + + +@dataclass +class ToyotaCarDocs(CarDocs): + package: str = "All" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.toyota_a])) + + +@dataclass +class ToyotaCommunityCarDocs(ToyotaCarDocs): + support_type: SupportType = SupportType.COMMUNITY + support_link: str = "#community" + + +@dataclass +class ToyotaTSS2PlatformConfig(PlatformConfig): + dbc_dict: dict = field(default_factory=lambda: dbc_dict('toyota_nodsu_pt_generated', 'toyota_tss2_adas')) + + def init(self): + self.flags |= ToyotaFlags.TSS2 | ToyotaFlags.NO_STOP_TIMER | ToyotaFlags.NO_DSU + + if self.flags & ToyotaFlags.RADAR_ACC: + self.dbc_dict = {Bus.pt: 'toyota_nodsu_pt_generated'} + + +@dataclass +class ToyotaSecOCPlatformConfig(PlatformConfig): + dbc_dict: dict = field(default_factory=lambda: dbc_dict('toyota_secoc_pt_generated', 'toyota_tss2_adas')) + + def init(self): + self.flags |= ToyotaFlags.TSS2 | ToyotaFlags.NO_STOP_TIMER | ToyotaFlags.NO_DSU | ToyotaFlags.SECOC + + if self.flags & ToyotaFlags.RADAR_ACC: + self.dbc_dict = {Bus.pt: 'toyota_secoc_pt_generated'} + + +class CAR(Platforms): + # Toyota + TOYOTA_ALPHARD_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota Alphard 2019-20"), + ToyotaCarDocs("Toyota Alphard Hybrid 2021"), + ], + CarSpecs(mass=4305. * CV.LB_TO_KG, wheelbase=3.0, steerRatio=14.2, tireStiffnessFactor=0.444), + ) + TOYOTA_AVALON = PlatformConfig( + [ + ToyotaCarDocs("Toyota Avalon 2016", "Toyota Safety Sense P"), + ToyotaCarDocs("Toyota Avalon 2017-18"), + ], + CarSpecs(mass=3505. * CV.LB_TO_KG, wheelbase=2.82, steerRatio=14.8, tireStiffnessFactor=0.7983), + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + ) + TOYOTA_AVALON_2019 = PlatformConfig( + [ + ToyotaCarDocs("Toyota Avalon 2019-21"), + ToyotaCarDocs("Toyota Avalon Hybrid 2019-21"), + ], + TOYOTA_AVALON.specs, + dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'), + ) + TOYOTA_AVALON_TSS2 = ToyotaTSS2PlatformConfig( # TSS 2.5 + [ + ToyotaCarDocs("Toyota Avalon 2022"), + ToyotaCarDocs("Toyota Avalon Hybrid 2022"), + ], + TOYOTA_AVALON.specs, + ) + TOYOTA_CAMRY = PlatformConfig( + [ + ToyotaCarDocs("Toyota Camry 2018-20", video="https://www.youtube.com/watch?v=fkcjviZY9CM", footnotes=[Footnote.CAMRY]), + ToyotaCarDocs("Toyota Camry Hybrid 2018-20", video="https://www.youtube.com/watch?v=Q2DYY0AWKgk"), + ], + CarSpecs(mass=3400. * CV.LB_TO_KG, wheelbase=2.82448, steerRatio=13.7, tireStiffnessFactor=0.7933), + dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.NO_DSU, + ) + TOYOTA_CAMRY_TSS2 = ToyotaTSS2PlatformConfig( # TSS 2.5 + [ + ToyotaCarDocs("Toyota Camry 2021-24", footnotes=[Footnote.CAMRY]), + ToyotaCarDocs("Toyota Camry Hybrid 2021-24"), + ], + TOYOTA_CAMRY.specs, + ) + TOYOTA_CHR = PlatformConfig( + [ + ToyotaCarDocs("Toyota C-HR 2017-20"), + ToyotaCarDocs("Toyota C-HR Hybrid 2017-20"), + ], + CarSpecs(mass=3300. * CV.LB_TO_KG, wheelbase=2.63906, steerRatio=13.6, tireStiffnessFactor=0.7933), + dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.NO_DSU, + ) + TOYOTA_CHR_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota C-HR 2021"), + ToyotaCarDocs("Toyota C-HR Hybrid 2021-22"), + ], + TOYOTA_CHR.specs, + flags=ToyotaFlags.RADAR_ACC, + ) + TOYOTA_COROLLA = PlatformConfig( + [ToyotaCarDocs("Toyota Corolla 2017-19")], + CarSpecs(mass=2860. * CV.LB_TO_KG, wheelbase=2.7, steerRatio=18.27, tireStiffnessFactor=0.444), + dbc_dict('toyota_new_mc_pt_generated', 'toyota_adas'), + ) + # LSS2 Lexus UX Hybrid is same as a TSS2 Corolla Hybrid + TOYOTA_COROLLA_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota Corolla 2020-22", video="https://www.youtube.com/watch?v=_66pXk0CBYA"), + ToyotaCarDocs("Toyota Corolla Cross (Non-US only) 2020-23", min_enable_speed=7.5), + ToyotaCarDocs("Toyota Corolla Hatchback 2019-22", video="https://www.youtube.com/watch?v=_66pXk0CBYA"), + # Hybrid platforms + ToyotaCarDocs("Toyota Corolla Hybrid 2020-22"), + ToyotaCarDocs("Toyota Corolla Hybrid (South America only) 2020-23", min_enable_speed=7.5), + ToyotaCarDocs("Toyota Corolla Cross Hybrid (Non-US only) 2020-22", min_enable_speed=7.5), + ToyotaCarDocs("Lexus UX Hybrid 2019-24"), + ], + CarSpecs(mass=3060. * CV.LB_TO_KG, wheelbase=2.67, steerRatio=13.9, tireStiffnessFactor=0.444), + ) + TOYOTA_HIGHLANDER = PlatformConfig( + [ + ToyotaCarDocs("Toyota Highlander 2017-19", video="https://www.youtube.com/watch?v=0wS0wXSLzoo"), + ToyotaCarDocs("Toyota Highlander Hybrid 2017-19"), + ], + CarSpecs(mass=4516. * CV.LB_TO_KG, wheelbase=2.8194, steerRatio=16.0, tireStiffnessFactor=0.8), + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.NO_STOP_TIMER | ToyotaFlags.SNG_WITHOUT_DSU, + ) + TOYOTA_HIGHLANDER_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota Highlander 2020-23"), + ToyotaCarDocs("Toyota Highlander Hybrid 2020-23"), + ], + TOYOTA_HIGHLANDER.specs, + ) + TOYOTA_PRIUS = PlatformConfig( + [ + ToyotaCarDocs("Toyota Prius 2016", "Toyota Safety Sense P", video="https://www.youtube.com/watch?v=8zopPJI8XQ0"), + ToyotaCarDocs("Toyota Prius 2017-20", video="https://www.youtube.com/watch?v=8zopPJI8XQ0"), + ToyotaCarDocs("Toyota Prius Prime 2017-20", video="https://www.youtube.com/watch?v=8zopPJI8XQ0"), + ], + CarSpecs(mass=3045. * CV.LB_TO_KG, wheelbase=2.7, steerRatio=15.74, tireStiffnessFactor=0.6371), + dbc_dict('toyota_nodsu_pt_generated', 'toyota_adas'), + ) + TOYOTA_PRIUS_V = PlatformConfig( + [ToyotaCarDocs("Toyota Prius v 2017", "Toyota Safety Sense P", min_enable_speed=MIN_ACC_SPEED)], + CarSpecs(mass=3340. * CV.LB_TO_KG, wheelbase=2.78, steerRatio=17.4, tireStiffnessFactor=0.5533), + dbc_dict('toyota_new_mc_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.NO_STOP_TIMER | ToyotaFlags.SNG_WITHOUT_DSU, + ) + TOYOTA_PRIUS_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota Prius 2021-22", video="https://www.youtube.com/watch?v=J58TvCpUd4U"), + ToyotaCarDocs("Toyota Prius Prime 2021-22", video="https://www.youtube.com/watch?v=J58TvCpUd4U"), + ], + CarSpecs(mass=3115. * CV.LB_TO_KG, wheelbase=2.70002, steerRatio=13.4, tireStiffnessFactor=0.6371), + ) + TOYOTA_RAV4 = PlatformConfig( + [ + ToyotaCarDocs("Toyota RAV4 2016", "Toyota Safety Sense P"), + ToyotaCarDocs("Toyota RAV4 2017-18") + ], + CarSpecs(mass=3650. * CV.LB_TO_KG, wheelbase=2.65, steerRatio=16.88, tireStiffnessFactor=0.5533), + dbc_dict('toyota_new_mc_pt_generated', 'toyota_adas'), + ) + TOYOTA_RAV4H = PlatformConfig( + [ + ToyotaCarDocs("Toyota RAV4 Hybrid 2016", "Toyota Safety Sense P", video="https://youtu.be/LhT5VzJVfNI?t=26"), + ToyotaCarDocs("Toyota RAV4 Hybrid 2017-18", video="https://youtu.be/LhT5VzJVfNI?t=26") + ], + TOYOTA_RAV4.specs, + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + # Note that the ICE RAV4 does not respect positive acceleration commands under 19 mph + flags=ToyotaFlags.NO_STOP_TIMER | ToyotaFlags.SNG_WITHOUT_DSU, + ) + TOYOTA_RAV4_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota RAV4 2019-21", video="https://www.youtube.com/watch?v=wJxjDd42gGA"), + ToyotaCarDocs("Toyota RAV4 Hybrid 2019-21"), + ], + CarSpecs(mass=3585. * CV.LB_TO_KG, wheelbase=2.68986, steerRatio=14.3, tireStiffnessFactor=0.7933), + ) + TOYOTA_RAV4_TSS2_2022 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota RAV4 2022"), + ToyotaCarDocs("Toyota RAV4 Hybrid 2022", video="https://youtu.be/U0nH9cnrFB0"), + ], + TOYOTA_RAV4_TSS2.specs, + flags=ToyotaFlags.RADAR_ACC, + ) + TOYOTA_RAV4_TSS2_2023 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Toyota RAV4 2023-25"), + ToyotaCarDocs("Toyota RAV4 Hybrid 2023-25", video="https://youtu.be/4eIsEq4L4Ng"), + ], + TOYOTA_RAV4_TSS2.specs, + flags=ToyotaFlags.RADAR_ACC | ToyotaFlags.ANGLE_CONTROL, + ) + TOYOTA_RAV4_PRIME = ToyotaSecOCPlatformConfig( + [ToyotaCommunityCarDocs("Toyota RAV4 Prime 2021-23", min_enable_speed=MIN_ACC_SPEED)], + CarSpecs(mass=4372. * CV.LB_TO_KG, wheelbase=2.68, steerRatio=16.88, tireStiffnessFactor=0.5533), + ) + TOYOTA_YARIS = ToyotaSecOCPlatformConfig( + [ToyotaCommunityCarDocs("Toyota Yaris (Non-US only) 2020, 2023", min_enable_speed=MIN_ACC_SPEED)], + CarSpecs(mass=1170, wheelbase=2.55, steerRatio=14.80, tireStiffnessFactor=0.5533), + flags=ToyotaFlags.RADAR_ACC, + ) + TOYOTA_MIRAI = ToyotaTSS2PlatformConfig( # TSS 2.5 + [ToyotaCarDocs("Toyota Mirai 2021")], + CarSpecs(mass=4300. * CV.LB_TO_KG, wheelbase=2.91, steerRatio=14.8, tireStiffnessFactor=0.8), + ) + TOYOTA_SIENNA = PlatformConfig( + [ToyotaCarDocs("Toyota Sienna 2018-20", video="https://www.youtube.com/watch?v=q1UPOo4Sh68", min_enable_speed=MIN_ACC_SPEED)], + CarSpecs(mass=4590. * CV.LB_TO_KG, wheelbase=3.03, steerRatio=15.5, tireStiffnessFactor=0.444), + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.NO_STOP_TIMER, + ) + TOYOTA_SIENNA_4TH_GEN = ToyotaSecOCPlatformConfig( + [ToyotaCommunityCarDocs("Toyota Sienna 2021-23", min_enable_speed=MIN_ACC_SPEED)], + CarSpecs(mass=4625. * CV.LB_TO_KG, wheelbase=3.06, steerRatio=17.8, tireStiffnessFactor=0.444), + ) + + # Lexus + LEXUS_CTH = PlatformConfig( + [ToyotaCarDocs("Lexus CT Hybrid 2017-18", "Lexus Safety System+")], + CarSpecs(mass=3108. * CV.LB_TO_KG, wheelbase=2.6, steerRatio=18.6, tireStiffnessFactor=0.517), + dbc_dict('toyota_new_mc_pt_generated', 'toyota_adas'), + ) + LEXUS_ES = PlatformConfig( + [ + ToyotaCarDocs("Lexus ES 2017-18"), + ToyotaCarDocs("Lexus ES Hybrid 2017-18"), + ], + CarSpecs(mass=3677. * CV.LB_TO_KG, wheelbase=2.8702, steerRatio=16.0, tireStiffnessFactor=0.444), + dbc_dict('toyota_new_mc_pt_generated', 'toyota_adas'), + ) + LEXUS_ES_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Lexus ES 2019-25"), + ToyotaCarDocs("Lexus ES Hybrid 2019-25", video="https://youtu.be/BZ29osRVJeg?t=12"), + ], + LEXUS_ES.specs, + ) + LEXUS_IS = PlatformConfig( + [ToyotaCarDocs("Lexus IS 2017-19")], + CarSpecs(mass=3736.8 * CV.LB_TO_KG, wheelbase=2.79908, steerRatio=13.3, tireStiffnessFactor=0.444), + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.UNSUPPORTED_DSU, + ) + LEXUS_IS_TSS2 = ToyotaTSS2PlatformConfig( + [ToyotaCarDocs("Lexus IS 2022-24")], + LEXUS_IS.specs, + ) + LEXUS_NX = PlatformConfig( + [ + ToyotaCarDocs("Lexus NX 2018-19"), + ToyotaCarDocs("Lexus NX Hybrid 2018-19"), + ], + CarSpecs(mass=4070. * CV.LB_TO_KG, wheelbase=2.66, steerRatio=14.7, tireStiffnessFactor=0.444), + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + ) + LEXUS_NX_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Lexus NX 2020-21"), + ToyotaCarDocs("Lexus NX Hybrid 2020-21"), + ], + LEXUS_NX.specs, + ) + LEXUS_LC_TSS2 = ToyotaTSS2PlatformConfig( + [ToyotaCarDocs("Lexus LC 2024-25")], + CarSpecs(mass=4500. * CV.LB_TO_KG, wheelbase=2.87, steerRatio=13.0, tireStiffnessFactor=0.444), + ) + LEXUS_RC = PlatformConfig( + [ToyotaCarDocs("Lexus RC 2018-20")], + LEXUS_IS.specs, + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.UNSUPPORTED_DSU, + ) + LEXUS_RC_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Lexus RC 2023"), + ], + CarSpecs(mass=3986. * CV.LB_TO_KG, wheelbase=2.73, steerRatio=13.9, tireStiffnessFactor=0.444), + ) + LEXUS_RX = PlatformConfig( + [ + ToyotaCarDocs("Lexus RX 2016", "Lexus Safety System+"), + ToyotaCarDocs("Lexus RX 2017-19"), + # Hybrid platforms + ToyotaCarDocs("Lexus RX Hybrid 2016", "Lexus Safety System+"), + ToyotaCarDocs("Lexus RX Hybrid 2017-19"), + ], + CarSpecs(mass=4481. * CV.LB_TO_KG, wheelbase=2.79, steerRatio=16., tireStiffnessFactor=0.5533), + dbc_dict('toyota_tnga_k_pt_generated', 'toyota_adas'), + ) + LEXUS_RX_TSS2 = ToyotaTSS2PlatformConfig( + [ + ToyotaCarDocs("Lexus RX 2020-22"), + ToyotaCarDocs("Lexus RX Hybrid 2020-22"), + ], + LEXUS_RX.specs, + ) + LEXUS_GS_F = PlatformConfig( + [ToyotaCarDocs("Lexus GS F 2016")], + CarSpecs(mass=4034. * CV.LB_TO_KG, wheelbase=2.84988, steerRatio=13.3, tireStiffnessFactor=0.444), + dbc_dict('toyota_new_mc_pt_generated', 'toyota_adas'), + flags=ToyotaFlags.UNSUPPORTED_DSU, + ) + + +# (addr, cars, bus, 1/freq*100, vl) +STATIC_DSU_MSGS = [ + (0x128, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_AVALON), + 1, 3, b'\xf4\x01\x90\x83\x00\x37'), + (0x128, (CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES), 1, 3, b'\x03\x00\x20\x00\x00\x52'), + (0x141, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON, + CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), 1, 2, b'\x00\x00\x00\x46'), + (0x160, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON, + CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), 1, 7, b'\x00\x00\x08\x12\x01\x31\x9c\x51'), + (0x161, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_AVALON, CAR.TOYOTA_PRIUS_V), + 1, 7, b'\x00\x1e\x00\x00\x00\x80\x07'), + (0X161, (CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES), 1, 7, b'\x00\x1e\x00\xd4\x00\x00\x5b'), + (0x283, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON, + CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), 0, 3, b'\x00\x00\x00\x00\x00\x00\x8c'), + (0x2E6, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX), 0, 3, b'\xff\xf8\x00\x08\x7f\xe0\x00\x4e'), + (0x2E7, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX), 0, 3, b'\xa8\x9c\x31\x9c\x00\x00\x00\x02'), + (0x33E, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX), 0, 20, b'\x0f\xff\x26\x40\x00\x1f\x00'), + (0x344, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON, + CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), 0, 5, b'\x00\x00\x01\x00\x00\x00\x00\x50'), + (0x365, (CAR.TOYOTA_PRIUS, CAR.LEXUS_NX, CAR.TOYOTA_HIGHLANDER), 0, 20, b'\x00\x00\x00\x80\x03\x00\x08'), + (0x365, (CAR.TOYOTA_RAV4, CAR.TOYOTA_RAV4H, CAR.TOYOTA_COROLLA, CAR.TOYOTA_AVALON, CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.LEXUS_RX, + CAR.TOYOTA_PRIUS_V), 0, 20, b'\x00\x00\x00\x80\xfc\x00\x08'), + (0x366, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_HIGHLANDER), 0, 20, b'\x00\x00\x4d\x82\x40\x02\x00'), + (0x366, (CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_AVALON, CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), + 0, 20, b'\x00\x72\x07\xff\x09\xfe\x00'), + (0x470, (CAR.TOYOTA_PRIUS, CAR.LEXUS_RX), 1, 100, b'\x00\x00\x02\x7a'), + (0x470, (CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_RAV4H, CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), 1, 100, b'\x00\x00\x01\x79'), + (0x4CB, (CAR.TOYOTA_PRIUS, CAR.TOYOTA_RAV4H, CAR.LEXUS_RX, CAR.LEXUS_NX, CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON, + CAR.TOYOTA_SIENNA, CAR.LEXUS_CTH, CAR.LEXUS_ES, CAR.TOYOTA_PRIUS_V), 0, 100, b'\x0c\x00\x00\x00\x00\x00\x00\x00'), +] + + +def get_platform_codes(fw_versions: list[bytes]) -> dict[bytes, set[bytes]]: + # Returns sub versions in a dict so comparisons can be made within part-platform-major_version combos + codes = defaultdict(set) # Optional[part]-platform-major_version: set of sub_version + for fw in fw_versions: + # FW versions returned from UDS queries can return multiple fields/chunks of data (different ECU calibrations, different data?) + # and are prefixed with a byte that describes how many chunks of data there are. + # But FW returned from KWP requires querying of each sub-data id and does not have a length prefix. + + length_code = 1 + length_code_match = FW_LEN_CODE.search(fw) + if length_code_match is not None: + length_code = length_code_match.group()[0] + fw = fw[1:] + + # fw length should be multiple of 16 bytes (per chunk, even if no length code), skip parsing if unexpected length + if length_code * FW_CHUNK_LEN != len(fw): + continue + + chunks = [fw[FW_CHUNK_LEN * i:FW_CHUNK_LEN * i + FW_CHUNK_LEN].strip(b'\x00 ') for i in range(length_code)] + + # only first is considered for now since second is commonly shared (TODO: understand that) + first_chunk = chunks[0] + if len(first_chunk) == 8: + # TODO: no part number, but some short chunks have it in subsequent chunks + fw_match = SHORT_FW_PATTERN.search(first_chunk) + if fw_match is not None: + platform, major_version, sub_version = fw_match.groups() + codes[b'-'.join((platform, major_version))].add(sub_version) + + elif len(first_chunk) == 10: + fw_match = MEDIUM_FW_PATTERN.search(first_chunk) + if fw_match is not None: + part, platform, major_version, sub_version = fw_match.groups() + codes[b'-'.join((part, platform, major_version))].add(sub_version) + + elif len(first_chunk) == 12: + fw_match = LONG_FW_PATTERN.search(first_chunk) + if fw_match is not None: + part, platform, major_version, sub_version = fw_match.groups() + codes[b'-'.join((part, platform, major_version))].add(sub_version) + + return dict(codes) + + +def match_fw_to_car_fuzzy(live_fw_versions, vin, offline_fw_versions) -> set[str]: + candidates = set() + + for candidate, fws in offline_fw_versions.items(): + # Keep track of ECUs which pass all checks (platform codes, within sub-version range) + valid_found_ecus = set() + valid_expected_ecus = {ecu[1:] for ecu in fws if ecu[0] in PLATFORM_CODE_ECUS} + for ecu, expected_versions in fws.items(): + addr = ecu[1:] + # Only check ECUs expected to have platform codes + if ecu[0] not in PLATFORM_CODE_ECUS: + continue + + # Expected platform codes & versions + expected_platform_codes = get_platform_codes(expected_versions) + + # Found platform codes & versions + found_platform_codes = get_platform_codes(live_fw_versions.get(addr, set())) + + # Check part number + platform code + major version matches for any found versions + # Platform codes and major versions change for different physical parts, generation, API, etc. + # Sub-versions are incremented for minor recalls, do not need to be checked. + if not any(found_platform_code in expected_platform_codes for found_platform_code in found_platform_codes): + break + + valid_found_ecus.add(addr) + + # If all live ECUs pass all checks for candidate, add it as a match + if valid_expected_ecus.issubset(valid_found_ecus): + candidates.add(candidate) + + return {str(c) for c in (candidates - FUZZY_EXCLUDED_PLATFORMS)} + + +# Regex patterns for parsing more general platform-specific identifiers from FW versions. +# - Part number: Toyota part number (usually last character needs to be ignored to find a match). +# Each ECU address has just one part number. +# - Platform: usually multiple codes per an openpilot platform, however this is the least variable and +# is usually shared across ECUs and model years signifying this describes something about the specific platform. +# This describes more generational changes (TSS-P vs TSS2), or manufacture region. +# - Major version: second least variable part of the FW version. Seen splitting cars by model year/API such as +# RAV4 2022/2023 and Avalon. Used to differentiate cars where API has changed slightly, but is not a generational change. +# It is important to note that these aren't always consecutive, for example: +# Avalon 2016-18's fwdCamera has these major versions: 01, 03 while 2019 has: 02 +# - Sub version: exclusive to major version, but shared with other cars. Should only be used for further filtering. +# Seen bumped in TSB FW updates, and describes other minor differences. +SHORT_FW_PATTERN = re.compile(b'[A-Z0-9](?P[A-Z0-9]{2})(?P[A-Z0-9]{2})(?P[A-Z0-9]{3})') +MEDIUM_FW_PATTERN = re.compile(b'(?P[A-Z0-9]{5})(?P[A-Z0-9]{2})(?P[A-Z0-9]{1})(?P[A-Z0-9]{2})') +LONG_FW_PATTERN = re.compile(b'(?P[A-Z0-9]{5})(?P[A-Z0-9]{2})(?P[A-Z0-9]{2})(?P[A-Z0-9]{3})') +FW_LEN_CODE = re.compile(b'^[\x01-\x03]') # highest seen is 3 chunks, 16 bytes each +FW_CHUNK_LEN = 16 + +# List of ECUs that are most unique across openpilot platforms +# - fwdCamera: describes actual features related to ADAS. For example, on the Avalon it describes +# when TSS-P became standard, whether the car supports stop and go, and whether it's TSS2. +# On the RAV4, it describes the move to the radar doing ACC, and the use of LTA for lane keeping. +# Note that the platform codes & major versions do not describe features in plain text, only with +# matching against other seen FW versions in the database they can describe features. +# - fwdRadar: sanity check against fwdCamera, commonly shares a platform code. +# For example the RAV4 2022's new radar architecture is shown for both with platform code. +# - abs: differentiates hybrid/ICE on most cars (Corolla TSS2 is an exception, not used due to hybrid platform combination) +# - eps: describes lateral API changes for the EPS, such as using LTA for lane keeping and rejecting LKA messages +PLATFORM_CODE_ECUS = (Ecu.fwdCamera, Ecu.fwdRadar, Ecu.eps) + +# These platforms have at least one platform code for all ECUs shared with another platform. +FUZZY_EXCLUDED_PLATFORMS: set[CAR] = set() + +# Some ECUs that use KWP2000 have their FW versions on non-standard data identifiers. +# Toyota diagnostic software first gets the supported data ids, then queries them one by one. +# For example, sends: 0x1a8800, receives: 0x1a8800010203, queries: 0x1a8801, 0x1a8802, 0x1a8803 +TOYOTA_VERSION_REQUEST_KWP = b'\x1a\x88\x01' +TOYOTA_VERSION_RESPONSE_KWP = b'\x5a\x88\x01' + +FW_QUERY_CONFIG = FwQueryConfig( + # TODO: look at data to whitelist new ECUs effectively + requests=[ + Request( + [StdQueries.SHORT_TESTER_PRESENT_REQUEST, TOYOTA_VERSION_REQUEST_KWP], + [StdQueries.SHORT_TESTER_PRESENT_RESPONSE, TOYOTA_VERSION_RESPONSE_KWP], + whitelist_ecus=[Ecu.fwdCamera, Ecu.fwdRadar, Ecu.dsu, Ecu.abs, Ecu.eps, Ecu.srs, Ecu.transmission, Ecu.hvac], + bus=0, + ), + Request( + [StdQueries.SHORT_TESTER_PRESENT_REQUEST, StdQueries.OBD_VERSION_REQUEST], + [StdQueries.SHORT_TESTER_PRESENT_RESPONSE, StdQueries.OBD_VERSION_RESPONSE], + whitelist_ecus=[Ecu.engine, Ecu.hybrid, Ecu.srs, Ecu.transmission, Ecu.hvac], + bus=0, + ), + Request( + [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.DEFAULT_DIAGNOSTIC_REQUEST, StdQueries.EXTENDED_DIAGNOSTIC_REQUEST, StdQueries.UDS_VERSION_REQUEST], + [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.DEFAULT_DIAGNOSTIC_RESPONSE, StdQueries.EXTENDED_DIAGNOSTIC_RESPONSE, StdQueries.UDS_VERSION_RESPONSE], + whitelist_ecus=[Ecu.engine, Ecu.fwdRadar, Ecu.fwdCamera, Ecu.abs, Ecu.eps, + Ecu.hybrid, Ecu.srs, Ecu.transmission, Ecu.hvac], + bus=0, + ), + ], + non_essential_ecus={ + # FIXME: On some models, abs can sometimes be missing + Ecu.abs: [CAR.TOYOTA_RAV4, CAR.TOYOTA_COROLLA, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_SIENNA, CAR.LEXUS_IS, CAR.TOYOTA_ALPHARD_TSS2], + # On some models, the engine can show on two different addresses + Ecu.engine: [CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_CAMRY, CAR.TOYOTA_COROLLA_TSS2, CAR.TOYOTA_CHR, CAR.TOYOTA_CHR_TSS2, CAR.LEXUS_IS, + CAR.LEXUS_IS_TSS2, CAR.LEXUS_RC, CAR.LEXUS_NX, CAR.LEXUS_NX_TSS2, CAR.LEXUS_RX, CAR.LEXUS_RX_TSS2], + }, + extra_ecus=[ + # All known ECUs on a late-model Toyota vehicle not queried here: + # Responds to UDS: + # - Combination Meter (0x7c0) + # - HV Battery (0x713, 0x747) + # - Motor Generator (0x716, 0x724) + # - 2nd ABS "Brake/EPB" (0x730) + # - Electronic Parking Brake ((0x750, 0x2c)) + # - Telematics ((0x750, 0xc7)) + # Responds to KWP (0x1a8801): + # - Steering Angle Sensor (0x7b3) + # - EPS/EMPS (0x7a0, 0x7a1) + # - 2nd SRS Airbag (0x784) + # - Central Gateway ((0x750, 0x5f)) + # - Telematics ((0x750, 0xc7)) + # Responds to KWP (0x1a8881): + # - Body Control Module ((0x750, 0x40)) + # - Telematics ((0x750, 0xc7)) + + # Hybrid control computer can be on 0x7e2 (KWP) or 0x7d2 (UDS) depending on platform + (Ecu.hybrid, 0x7e2, None), # Hybrid Control Assembly & Computer + (Ecu.hybrid, 0x7d2, None), # Hybrid Control Assembly & Computer + (Ecu.srs, 0x780, None), # SRS Airbag + # Transmission is combined with engine on some platforms, such as TSS-P RAV4 + (Ecu.transmission, 0x701, None), + # A few platforms have a tester present response on this address, add to log + (Ecu.transmission, 0x7e1, None), + (Ecu.hvac, 0x7c4, None), + ], + match_fw_to_car_fuzzy=match_fw_to_car_fuzzy, +) + +STEER_THRESHOLD = 100 + +# These cars have non-standard EPS torque scale factors. All others are 73 +EPS_SCALE = defaultdict(lambda: 73, + {CAR.TOYOTA_PRIUS: 66, CAR.TOYOTA_COROLLA: 88, CAR.LEXUS_IS: 77, CAR.LEXUS_RC: 77, CAR.LEXUS_CTH: 100, CAR.TOYOTA_PRIUS_V: 100}) + +# Toyota/Lexus Safety Sense 2.0 and 2.5 +TSS2_CAR = CAR.with_flags(ToyotaFlags.TSS2) + +NO_DSU_CAR = CAR.with_flags(ToyotaFlags.NO_DSU) + +# the DSU uses the AEB message for longitudinal on these cars +UNSUPPORTED_DSU_CAR = CAR.with_flags(ToyotaFlags.UNSUPPORTED_DSU) + +# these cars have a radar which sends ACC messages instead of the camera +RADAR_ACC_CAR = CAR.with_flags(ToyotaFlags.RADAR_ACC) + +ANGLE_CONTROL_CAR = CAR.with_flags(ToyotaFlags.ANGLE_CONTROL) + +SECOC_CAR = CAR.with_flags(ToyotaFlags.SECOC) + +# no resume button press required +NO_STOP_TIMER_CAR = CAR.with_flags(ToyotaFlags.NO_STOP_TIMER) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/uds.py b/opendbc_repo/opendbc/car/uds.py new file mode 100644 index 0000000000..0ae06be70f --- /dev/null +++ b/opendbc_repo/opendbc/car/uds.py @@ -0,0 +1,973 @@ +import time +import struct +from collections import deque +from typing import NamedTuple, cast +from collections.abc import Callable, Generator +from enum import IntEnum +from functools import partial + +from opendbc.car.carlog import carlog + + +class SERVICE_TYPE(IntEnum): + DIAGNOSTIC_SESSION_CONTROL = 0x10 + ECU_RESET = 0x11 + SECURITY_ACCESS = 0x27 + COMMUNICATION_CONTROL = 0x28 + TESTER_PRESENT = 0x3E + ACCESS_TIMING_PARAMETER = 0x83 + SECURED_DATA_TRANSMISSION = 0x84 + CONTROL_DTC_SETTING = 0x85 + RESPONSE_ON_EVENT = 0x86 + LINK_CONTROL = 0x87 + READ_DATA_BY_IDENTIFIER = 0x22 + READ_MEMORY_BY_ADDRESS = 0x23 + READ_SCALING_DATA_BY_IDENTIFIER = 0x24 + READ_DATA_BY_PERIODIC_IDENTIFIER = 0x2A + DYNAMICALLY_DEFINE_DATA_IDENTIFIER = 0x2C + WRITE_DATA_BY_IDENTIFIER = 0x2E + WRITE_MEMORY_BY_ADDRESS = 0x3D + CLEAR_DIAGNOSTIC_INFORMATION = 0x14 + READ_DTC_INFORMATION = 0x19 + INPUT_OUTPUT_CONTROL_BY_IDENTIFIER = 0x2F + ROUTINE_CONTROL = 0x31 + REQUEST_DOWNLOAD = 0x34 + REQUEST_UPLOAD = 0x35 + TRANSFER_DATA = 0x36 + REQUEST_TRANSFER_EXIT = 0x37 + + +class SESSION_TYPE(IntEnum): + DEFAULT = 1 + PROGRAMMING = 2 + EXTENDED_DIAGNOSTIC = 3 + SAFETY_SYSTEM_DIAGNOSTIC = 4 + + +class RESET_TYPE(IntEnum): + HARD = 1 + KEY_OFF_ON = 2 + SOFT = 3 + ENABLE_RAPID_POWER_SHUTDOWN = 4 + DISABLE_RAPID_POWER_SHUTDOWN = 5 + + +class ACCESS_TYPE(IntEnum): + REQUEST_SEED = 1 + SEND_KEY = 2 + + +class CONTROL_TYPE(IntEnum): + ENABLE_RX_ENABLE_TX = 0 + ENABLE_RX_DISABLE_TX = 1 + DISABLE_RX_ENABLE_TX = 2 + DISABLE_RX_DISABLE_TX = 3 + + +class MESSAGE_TYPE(IntEnum): + NORMAL = 1 + NETWORK_MANAGEMENT = 2 + NORMAL_AND_NETWORK_MANAGEMENT = 3 + + +class TIMING_PARAMETER_TYPE(IntEnum): + READ_EXTENDED_SET = 1 + SET_TO_DEFAULT_VALUES = 2 + READ_CURRENTLY_ACTIVE = 3 + SET_TO_GIVEN_VALUES = 4 + + +class DTC_SETTING_TYPE(IntEnum): + ON = 1 + OFF = 2 + + +class RESPONSE_EVENT_TYPE(IntEnum): + STOP_RESPONSE_ON_EVENT = 0 + ON_DTC_STATUS_CHANGE = 1 + ON_TIMER_INTERRUPT = 2 + ON_CHANGE_OF_DATA_IDENTIFIER = 3 + REPORT_ACTIVATED_EVENTS = 4 + START_RESPONSE_ON_EVENT = 5 + CLEAR_RESPONSE_ON_EVENT = 6 + ON_COMPARISON_OF_VALUES = 7 + + +class LINK_CONTROL_TYPE(IntEnum): + VERIFY_BAUDRATE_TRANSITION_WITH_FIXED_BAUDRATE = 1 + VERIFY_BAUDRATE_TRANSITION_WITH_SPECIFIC_BAUDRATE = 2 + TRANSITION_BAUDRATE = 3 + + +class BAUD_RATE_TYPE(IntEnum): + PC9600 = 1 + PC19200 = 2 + PC38400 = 3 + PC57600 = 4 + PC115200 = 5 + CAN125000 = 16 + CAN250000 = 17 + CAN500000 = 18 + CAN1000000 = 19 + + +class DATA_IDENTIFIER_TYPE(IntEnum): + BOOT_SOFTWARE_IDENTIFICATION = 0xF180 + APPLICATION_SOFTWARE_IDENTIFICATION = 0xF181 + APPLICATION_DATA_IDENTIFICATION = 0xF182 + BOOT_SOFTWARE_FINGERPRINT = 0xF183 + APPLICATION_SOFTWARE_FINGERPRINT = 0xF184 + APPLICATION_DATA_FINGERPRINT = 0xF185 + ACTIVE_DIAGNOSTIC_SESSION = 0xF186 + VEHICLE_MANUFACTURER_SPARE_PART_NUMBER = 0xF187 + VEHICLE_MANUFACTURER_ECU_SOFTWARE_NUMBER = 0xF188 + VEHICLE_MANUFACTURER_ECU_SOFTWARE_VERSION_NUMBER = 0xF189 + SYSTEM_SUPPLIER_IDENTIFIER = 0xF18A + ECU_MANUFACTURING_DATE = 0xF18B + ECU_SERIAL_NUMBER = 0xF18C + SUPPORTED_FUNCTIONAL_UNITS = 0xF18D + VEHICLE_MANUFACTURER_KIT_ASSEMBLY_PART_NUMBER = 0xF18E + VIN = 0xF190 + VEHICLE_MANUFACTURER_ECU_HARDWARE_NUMBER = 0xF191 + SYSTEM_SUPPLIER_ECU_HARDWARE_NUMBER = 0xF192 + SYSTEM_SUPPLIER_ECU_HARDWARE_VERSION_NUMBER = 0xF193 + SYSTEM_SUPPLIER_ECU_SOFTWARE_NUMBER = 0xF194 + SYSTEM_SUPPLIER_ECU_SOFTWARE_VERSION_NUMBER = 0xF195 + EXHAUST_REGULATION_OR_TYPE_APPROVAL_NUMBER = 0xF196 + SYSTEM_NAME_OR_ENGINE_TYPE = 0xF197 + REPAIR_SHOP_CODE_OR_TESTER_SERIAL_NUMBER = 0xF198 + PROGRAMMING_DATE = 0xF199 + CALIBRATION_REPAIR_SHOP_CODE_OR_CALIBRATION_EQUIPMENT_SERIAL_NUMBER = 0xF19A + CALIBRATION_DATE = 0xF19B + CALIBRATION_EQUIPMENT_SOFTWARE_NUMBER = 0xF19C + ECU_INSTALLATION_DATE = 0xF19D + ODX_FILE = 0xF19E + ENTITY = 0xF19F + + +class TRANSMISSION_MODE_TYPE(IntEnum): + SEND_AT_SLOW_RATE = 1 + SEND_AT_MEDIUM_RATE = 2 + SEND_AT_FAST_RATE = 3 + STOP_SENDING = 4 + + +class DYNAMIC_DEFINITION_TYPE(IntEnum): + DEFINE_BY_IDENTIFIER = 1 + DEFINE_BY_MEMORY_ADDRESS = 2 + CLEAR_DYNAMICALLY_DEFINED_DATA_IDENTIFIER = 3 + + +class ISOTP_FRAME_TYPE(IntEnum): + SINGLE = 0 + FIRST = 1 + CONSECUTIVE = 2 + FLOW = 3 + + +class DynamicSourceDefinition(NamedTuple): + data_identifier: int + position: int + memory_size: int + memory_address: int + + +class DTC_GROUP_TYPE(IntEnum): + EMISSIONS = 0x000000 + ALL = 0xFFFFFF + + +class DTC_REPORT_TYPE(IntEnum): + NUMBER_OF_DTC_BY_STATUS_MASK = 0x01 + DTC_BY_STATUS_MASK = 0x02 + DTC_SNAPSHOT_IDENTIFICATION = 0x03 + DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER = 0x04 + DTC_SNAPSHOT_RECORD_BY_RECORD_NUMBER = 0x05 + DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER = 0x06 + NUMBER_OF_DTC_BY_SEVERITY_MASK_RECORD = 0x07 + DTC_BY_SEVERITY_MASK_RECORD = 0x08 + SEVERITY_INFORMATION_OF_DTC = 0x09 + SUPPORTED_DTC = 0x0A + FIRST_TEST_FAILED_DTC = 0x0B + FIRST_CONFIRMED_DTC = 0x0C + MOST_RECENT_TEST_FAILED_DTC = 0x0D + MOST_RECENT_CONFIRMED_DTC = 0x0E + MIRROR_MEMORY_DTC_BY_STATUS_MASK = 0x0F + MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER = 0x10 + NUMBER_OF_MIRROR_MEMORY_DTC_BY_STATUS_MASK = 0x11 + NUMBER_OF_EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK = 0x12 + EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK = 0x13 + DTC_FAULT_DETECTION_COUNTER = 0x14 + DTC_WITH_PERMANENT_STATUS = 0x15 + + +class DTC_STATUS_MASK_TYPE(IntEnum): + TEST_FAILED = 0x01 + TEST_FAILED_THIS_OPERATION_CYCLE = 0x02 + PENDING_DTC = 0x04 + CONFIRMED_DTC = 0x08 + TEST_NOT_COMPLETED_SINCE_LAST_CLEAR = 0x10 + TEST_FAILED_SINCE_LAST_CLEAR = 0x20 + TEST_NOT_COMPLETED_THIS_OPERATION_CYCLE = 0x40 + WARNING_INDICATOR_REQUESTED = 0x80 + ALL = 0xFF + + +class DTC_SEVERITY_MASK_TYPE(IntEnum): + MAINTENANCE_ONLY = 0x20 + CHECK_AT_NEXT_HALT = 0x40 + CHECK_IMMEDIATELY = 0x80 + ALL = 0xE0 + + +class CONTROL_PARAMETER_TYPE(IntEnum): + RETURN_CONTROL_TO_ECU = 0 + RESET_TO_DEFAULT = 1 + FREEZE_CURRENT_STATE = 2 + SHORT_TERM_ADJUSTMENT = 3 + + +class ROUTINE_CONTROL_TYPE(IntEnum): + START = 1 + STOP = 2 + REQUEST_RESULTS = 3 + + +class ROUTINE_IDENTIFIER_TYPE(IntEnum): + ERASE_MEMORY = 0xFF00 + CHECK_PROGRAMMING_DEPENDENCIES = 0xFF01 + ERASE_MIRROR_MEMORY_DTCS = 0xFF02 + + +class MessageTimeoutError(Exception): + pass + + +class NegativeResponseError(Exception): + def __init__(self, message, service_id, error_code): + super().__init__() + self.message = message + self.service_id = service_id + self.error_code = error_code + + def __str__(self): + return self.message + + +class InvalidServiceIdError(Exception): + pass + + +class InvalidSubFunctionError(Exception): + pass + + +class InvalidSubAddressError(Exception): + pass + + +_negative_response_codes = { + 0x00: 'positive response', + 0x10: 'general reject', + 0x11: 'service not supported', + 0x12: 'sub-function not supported', + 0x13: 'incorrect message length or invalid format', + 0x14: 'response too long', + 0x21: 'busy repeat request', + 0x22: 'conditions not correct', + 0x24: 'request sequence error', + 0x25: 'no response from subnet component', + 0x26: 'failure prevents execution of requested action', + 0x31: 'request out of range', + 0x33: 'security access denied', + 0x35: 'invalid key', + 0x36: 'exceed number of attempts', + 0x37: 'required time delay not expired', + 0x70: 'upload download not accepted', + 0x71: 'transfer data suspended', + 0x72: 'general programming failure', + 0x73: 'wrong block sequence counter', + 0x78: 'request correctly received - response pending', + 0x7e: 'sub-function not supported in active session', + 0x7f: 'service not supported in active session', + 0x81: 'rpm too high', + 0x82: 'rpm too low', + 0x83: 'engine is running', + 0x84: 'engine is not running', + 0x85: 'engine run time too low', + 0x86: 'temperature too high', + 0x87: 'temperature too low', + 0x88: 'vehicle speed too high', + 0x89: 'vehicle speed too low', + 0x8a: 'throttle/pedal too high', + 0x8b: 'throttle/pedal too low', + 0x8c: 'transmission not in neutral', + 0x8d: 'transmission not in gear', + 0x8f: 'brake switch(es) not closed', + 0x90: 'shifter lever not in park', + 0x91: 'torque converter clutch locked', + 0x92: 'voltage too high', + 0x93: 'voltage too low', +} + + +def get_dtc_num_as_str(dtc_num_bytes): + # ISO 15031-6 + designator = { + 0b00: "P", + 0b01: "C", + 0b10: "B", + 0b11: "U", + } + d = designator[dtc_num_bytes[0] >> 6] + n = bytes([dtc_num_bytes[0] & 0x3F]) + dtc_num_bytes[1:] + return d + n.hex() + + +def get_dtc_status_names(status): + result = list() + for m in DTC_STATUS_MASK_TYPE: + if m == DTC_STATUS_MASK_TYPE.ALL: + continue + if status & m.value: + result.append(m.name) + return result + + +class CanClient: + def __init__(self, can_send: Callable[[int, bytes, int], None], can_recv: Callable[[], list[tuple[int, bytes, int]]], + tx_addr: int, rx_addr: int, bus: int, sub_addr: int | None = None, rx_sub_addr: int | None = None): + self.tx = can_send + self.rx = can_recv + self.tx_addr = tx_addr + self.rx_addr = rx_addr + self.rx_buff: deque[bytes] = deque() + self.sub_addr = sub_addr + self.rx_sub_addr = rx_sub_addr if rx_sub_addr is not None else sub_addr + self.bus = bus + + def _recv_filter(self, bus: int, addr: int) -> bool: + # handle functional addresses (switch to first addr to respond) + if self.tx_addr == 0x7DF: + is_response = addr >= 0x7E8 and addr <= 0x7EF + if is_response: + carlog.debug(f"switch to physical addr {hex(addr)}") + self.tx_addr = addr - 8 + self.rx_addr = addr + return is_response + if self.tx_addr == 0x18DB33F1: + is_response = addr >= 0x18DAF100 and addr <= 0x18DAF1FF + if is_response: + carlog.debug(f"switch to physical addr {hex(addr)}") + self.tx_addr = 0x18DA00F1 + (addr << 8 & 0xFF00) + self.rx_addr = addr + return bus == self.bus and addr == self.rx_addr + + def _recv_buffer(self, drain: bool = False) -> None: + while True: + msgs = self.rx() + if drain: + carlog.debug(f"CAN-RX: drain - {len(msgs)}") + self.rx_buff.clear() + else: + for rx_addr, rx_data, rx_bus in msgs or []: + if self._recv_filter(rx_bus, rx_addr) and len(rx_data) > 0: + rx_data = bytes(rx_data) # convert bytearray to bytes + + carlog.debug(f"CAN-RX: {hex(rx_addr)} - 0x{bytes.hex(rx_data)}") + + # Cut off sub addr in first byte + if self.rx_sub_addr is not None: + if rx_data[0] != self.rx_sub_addr: + raise InvalidSubAddressError(f"isotp - rx: invalid sub-address: {rx_data[0]}, expected: {self.rx_sub_addr}") + rx_data = rx_data[1:] + + self.rx_buff.append(rx_data) + # break when non-full buffer is processed + if len(msgs) < 254: + return + + def recv(self, drain: bool = False) -> Generator[bytes, None, None]: + # buffer rx messages in case two response messages are received at once + # (e.g. response pending and success/failure response) + self._recv_buffer(drain) + try: + while True: + yield self.rx_buff.popleft() + except IndexError: + pass # empty + + def send(self, msgs: list[bytes], delay: float = 0) -> None: + for i, msg in enumerate(msgs): + if delay and i != 0: + carlog.debug(f"CAN-TX: delay - {delay}") + time.sleep(delay) + + if self.sub_addr is not None: + msg = bytes([self.sub_addr]) + msg + + carlog.debug(f"CAN-TX: {hex(self.tx_addr)} - 0x{bytes.hex(msg)}") + assert len(msg) <= 8 + + self.tx(self.tx_addr, msg, self.bus) + # prevent rx buffer from overflowing on large tx + if i % 10 == 9: + self._recv_buffer() + + +class IsoTpMessage: + def __init__(self, can_client: CanClient, timeout: float = 1, single_frame_mode: bool = False, separation_time: float = 0): + self._can_client = can_client + self.timeout = timeout + self.single_frame_mode = single_frame_mode + self.max_len = 8 if self._can_client.sub_addr is None else 7 + + # <= 127, separation time in milliseconds + # 0xF1 to 0xF9 UF, 100 to 900 microseconds + if 1e-4 <= separation_time <= 9e-4: + offset = int(round(separation_time, 4) * 1e4) - 1 + separation_time = 0xF1 + offset + elif 0 <= separation_time <= 0.127: + separation_time = round(separation_time * 1000) + else: + raise Exception("Separation time not in range") + + self.flow_control_msg = bytes([ + 0x30, # flow control + 0x01 if self.single_frame_mode else 0x00, # block size + separation_time, + ]).ljust(self.max_len, b"\x00") + + def send(self, dat: bytes, setup_only: bool = False) -> None: + # throw away any stale data + self._can_client.recv(drain=True) + + self.tx_dat = dat + self.tx_len = len(dat) + self.tx_idx = 0 + self.tx_done = False + + self.rx_dat = b"" + self.rx_len = 0 + self.rx_idx = 0 + self.rx_done = False + + if not setup_only: + carlog.debug(f"ISO-TP: REQUEST - {hex(self._can_client.tx_addr)} 0x{bytes.hex(self.tx_dat)}") + self._tx_first_frame(setup_only=setup_only) + + def _tx_first_frame(self, setup_only: bool = False) -> None: + if self.tx_len < self.max_len: + # single frame (send all bytes) + if not setup_only: + carlog.debug(f"ISO-TP: TX - single frame - {hex(self._can_client.tx_addr)}") + msg = (bytes([self.tx_len]) + self.tx_dat).ljust(self.max_len, b"\x00") + self.tx_done = True + else: + # first frame (send first 6 bytes) + if not setup_only: + carlog.debug(f"ISO-TP: TX - first frame - {hex(self._can_client.tx_addr)}") + msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:self.max_len - 2]).ljust(self.max_len - 2, b"\x00") + if not setup_only: + self._can_client.send([msg]) + + def recv(self, timeout=None) -> tuple[bytes | None, bool]: + if timeout is None: + timeout = self.timeout + + start_time = time.monotonic() + rx_in_progress = False + try: + while True: + for msg in self._can_client.recv(): + frame_type = self._isotp_rx_next(msg) + start_time = time.monotonic() + # Anything that signifies we're building a response + rx_in_progress = frame_type in (ISOTP_FRAME_TYPE.FIRST, ISOTP_FRAME_TYPE.CONSECUTIVE) + if self.tx_done and self.rx_done: + return self.rx_dat, False + # no timeout indicates non-blocking + if timeout == 0: + return None, rx_in_progress + if time.monotonic() - start_time > timeout: + raise MessageTimeoutError("timeout waiting for response") + finally: + if self.rx_dat: + carlog.debug(f"ISO-TP: RESPONSE - {hex(self._can_client.rx_addr)} 0x{bytes.hex(self.rx_dat)}") + + def _isotp_rx_next(self, rx_data: bytes) -> ISOTP_FRAME_TYPE: + # TODO: Handle CAN frame data optimization, which is allowed with some frame types + # # ISO 15765-2 specifies an eight byte CAN frame for ISO-TP communication + # assert len(rx_data) == self.max_len, f"isotp - rx: invalid CAN frame length: {len(rx_data)}" + + if rx_data[0] >> 4 == ISOTP_FRAME_TYPE.SINGLE: + assert self.rx_dat == b"" or self.rx_done, "isotp - rx: single frame with active frame" + + # "if the first byte is 0x00, then it's a CAN-FD SF, and the second byte specifies the size of the data." + # - https://en.wikipedia.org/wiki/CAN_FD + if rx_data[0] & 0x0F == 0 and len(rx_data) > 8: + self.rx_len = rx_data[1] + offset = 2 + # TODO: update self.max_len for CAN FD + max_len = 62 if self._can_client.sub_addr is None else 61 + assert self.rx_len <= max_len, f"isotp - rx: invalid single frame length: {self.rx_len}" + else: + self.rx_len = rx_data[0] & 0x0F + offset = 1 + assert self.rx_len < self.max_len, f"isotp - rx: invalid single frame length: {self.rx_len}" + + self.rx_dat = rx_data[offset:offset + self.rx_len] + self.rx_idx = 0 + self.rx_done = True + carlog.debug(f"ISO-TP: RX - single frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}") + return ISOTP_FRAME_TYPE.SINGLE + + elif rx_data[0] >> 4 == ISOTP_FRAME_TYPE.FIRST: + # TODO: support CAN FD first frames + # Once a first frame is received, further frames must be consecutive + assert self.rx_dat == b"" or self.rx_done, "isotp - rx: first frame with active frame" + self.rx_len = ((rx_data[0] & 0x0F) << 8) + rx_data[1] + assert self.rx_len >= self.max_len, f"isotp - rx: invalid first frame length: {self.rx_len}" + assert len(rx_data) == self.max_len, f"isotp - rx: invalid CAN frame length: {len(rx_data)}" + self.rx_dat = rx_data[2:] + self.rx_idx = 0 + self.rx_done = False + carlog.debug(f"ISO-TP: RX - first frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}") + carlog.debug(f"ISO-TP: TX - flow control continue - {hex(self._can_client.tx_addr)}") + # send flow control message + self._can_client.send([self.flow_control_msg]) + return ISOTP_FRAME_TYPE.FIRST + + elif rx_data[0] >> 4 == ISOTP_FRAME_TYPE.CONSECUTIVE: + assert not self.rx_done, "isotp - rx: consecutive frame with no active frame" + self.rx_idx += 1 + assert self.rx_idx & 0xF == rx_data[0] & 0xF, "isotp - rx: invalid consecutive frame index" + rx_size = self.rx_len - len(self.rx_dat) + self.rx_dat += rx_data[1:1 + rx_size] + if self.rx_len == len(self.rx_dat): + self.rx_done = True + elif self.single_frame_mode: + # notify ECU to send next frame + self._can_client.send([self.flow_control_msg]) + carlog.debug(f"ISO-TP: RX - consecutive frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}") + return ISOTP_FRAME_TYPE.CONSECUTIVE + + elif rx_data[0] >> 4 == ISOTP_FRAME_TYPE.FLOW: + assert not self.tx_done, "isotp - rx: flow control with no active frame" + assert rx_data[0] != 0x32, "isotp - rx: flow-control overflow/abort" + assert rx_data[0] == 0x30 or rx_data[0] == 0x31, "isotp - rx: flow-control transfer state indicator invalid" + if rx_data[0] == 0x30: + carlog.debug(f"ISO-TP: RX - flow control continue - {hex(self._can_client.tx_addr)}") + delay_ts = rx_data[2] & 0x7F + # scale is 1 milliseconds if first bit == 0, 100 micro seconds if first bit == 1 + delay_div = 1000. if rx_data[2] & 0x80 == 0 else 10000. + delay_sec = delay_ts / delay_div + + # first frame = 6 bytes, each consecutive frame = 7 bytes + num_bytes = self.max_len - 1 + start = self.max_len - 2 + self.tx_idx * num_bytes + count = rx_data[1] + end = start + count * num_bytes if count > 0 else self.tx_len + tx_msgs = [] + for i in range(start, end, num_bytes): + self.tx_idx += 1 + # consecutive tx messages + msg = (bytes([0x20 | (self.tx_idx & 0xF)]) + self.tx_dat[i:i + num_bytes]).ljust(self.max_len, b"\x00") + tx_msgs.append(msg) + # send consecutive tx messages + self._can_client.send(tx_msgs, delay=delay_sec) + if end >= self.tx_len: + self.tx_done = True + carlog.debug(f"ISO-TP: TX - consecutive frame - {hex(self._can_client.tx_addr)} idx={self.tx_idx} done={self.tx_done}") + elif rx_data[0] == 0x31: + # wait (do nothing until next flow control message) + carlog.debug(f"ISO-TP: TX - flow control wait - {hex(self._can_client.tx_addr)}") + return ISOTP_FRAME_TYPE.FLOW + + # 4-15 - reserved + else: + raise Exception(f"isotp - rx: invalid frame type: {rx_data[0] >> 4}") + + +FUNCTIONAL_ADDRS = [0x7DF, 0x18DB33F1] + + +def get_rx_addr_for_tx_addr(tx_addr, rx_offset=0x8): + if tx_addr in FUNCTIONAL_ADDRS: + return None + + if tx_addr < 0xFFF8: + # pseudo-standard 11 bit response addr (add 8) works for most manufacturers + # allow override; some manufacturers use other offsets for non-OBD2 access + return tx_addr + rx_offset + + if tx_addr > 0x10000000 and tx_addr < 0xFFFFFFFF: + # standard 29 bit response addr (flip last two bytes) + return (tx_addr & 0xFFFF0000) + (tx_addr << 8 & 0xFF00) + (tx_addr >> 8 & 0xFF) + + raise ValueError(f"invalid tx_addr: {tx_addr}") + + +class UdsClient: + def __init__(self, panda, tx_addr: int, rx_addr: int | None = None, bus: int = 0, sub_addr: int | None = None, rx_sub_addr: int | None = None, + timeout: float = 1, tx_timeout: float = 1, response_pending_timeout: float = 10): + self.bus = bus + self.tx_addr = tx_addr + self.rx_addr = rx_addr if rx_addr is not None else get_rx_addr_for_tx_addr(tx_addr) + self.sub_addr = sub_addr + self.timeout = timeout + can_send_with_timeout = partial(panda.can_send, timeout=int(tx_timeout*1000)) + self._can_client = CanClient(can_send_with_timeout, panda.can_recv, self.tx_addr, self.rx_addr, self.bus, self.sub_addr, rx_sub_addr) + self.response_pending_timeout = response_pending_timeout + + # generic uds request + def _uds_request(self, service_type: SERVICE_TYPE, subfunction: int | None = None, data: bytes | None = None) -> bytes: + req = bytes([service_type]) + if subfunction is not None: + req += bytes([subfunction]) + if data is not None: + req += data + + # send request, wait for response + isotp_msg = IsoTpMessage(self._can_client, timeout=self.timeout) + isotp_msg.send(req) + response_pending = False + while True: + timeout = self.response_pending_timeout if response_pending else self.timeout + resp, _ = isotp_msg.recv(timeout) + + if resp is None: + continue + + response_pending = False + resp_sid = resp[0] if len(resp) > 0 else None + + # negative response + if resp_sid == 0x7F: + service_id = resp[1] if len(resp) > 1 else -1 + try: + service_desc = SERVICE_TYPE(service_id).name + except BaseException: + service_desc = 'NON_STANDARD_SERVICE' + error_code = resp[2] if len(resp) > 2 else -1 + try: + error_desc = _negative_response_codes[error_code] + except BaseException: + error_desc = resp[3:].hex() + # wait for another message if response pending + if error_code == 0x78: + response_pending = True + carlog.debug("UDS-RX: response pending") + continue + raise NegativeResponseError(f'{service_desc} - {error_desc}', service_id, error_code) + + # positive response + if service_type + 0x40 != resp_sid: + resp_sid_hex = hex(resp_sid) if resp_sid is not None else None + raise InvalidServiceIdError(f'invalid response service id: {resp_sid_hex}') + + if subfunction is not None: + resp_sfn = resp[1] if len(resp) > 1 else None + if subfunction != resp_sfn: + resp_sfn_hex = hex(resp_sfn) if resp_sfn is not None else None + raise InvalidSubFunctionError(f'invalid response subfunction: {resp_sfn_hex}') + + # return data (exclude service id and sub-function id) + return resp[(1 if subfunction is None else 2):] + + # services + def diagnostic_session_control(self, session_type: SESSION_TYPE): + self._uds_request(SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, subfunction=session_type) + + def ecu_reset(self, reset_type: RESET_TYPE): + resp = self._uds_request(SERVICE_TYPE.ECU_RESET, subfunction=reset_type) + power_down_time = None + if reset_type == RESET_TYPE.ENABLE_RAPID_POWER_SHUTDOWN: + power_down_time = resp[0] + return power_down_time + + def security_access(self, access_type: ACCESS_TYPE, security_key: bytes = b'', data_record: bytes = b''): + request_seed = access_type % 2 != 0 + if request_seed and len(security_key) != 0: + raise ValueError('security_key not allowed') + if not request_seed and len(security_key) == 0: + raise ValueError('security_key is missing') + if not request_seed and len(data_record) != 0: + raise ValueError('data_record not allowed') + data = security_key + data_record + resp = self._uds_request(SERVICE_TYPE.SECURITY_ACCESS, subfunction=access_type, data=data) + if request_seed: + security_seed = resp + return security_seed + + def communication_control(self, control_type: CONTROL_TYPE, message_type: MESSAGE_TYPE): + data = bytes([message_type]) + self._uds_request(SERVICE_TYPE.COMMUNICATION_CONTROL, subfunction=control_type, data=data) + + def tester_present(self, ): + self._uds_request(SERVICE_TYPE.TESTER_PRESENT, subfunction=0x00) + + def access_timing_parameter(self, timing_parameter_type: TIMING_PARAMETER_TYPE, parameter_values: bytes | None = None): + write_custom_values = timing_parameter_type == TIMING_PARAMETER_TYPE.SET_TO_GIVEN_VALUES + read_values = (timing_parameter_type == TIMING_PARAMETER_TYPE.READ_CURRENTLY_ACTIVE or + timing_parameter_type == TIMING_PARAMETER_TYPE.READ_EXTENDED_SET) + if not write_custom_values and parameter_values is not None: + raise ValueError('parameter_values not allowed') + if write_custom_values and parameter_values is None: + raise ValueError('parameter_values is missing') + resp = self._uds_request(SERVICE_TYPE.ACCESS_TIMING_PARAMETER, subfunction=timing_parameter_type, data=parameter_values) + if read_values: + # TODO: parse response into values? + parameter_values = resp + return parameter_values + + def secured_data_transmission(self, data: bytes): + # TODO: split data into multiple input parameters? + resp = self._uds_request(SERVICE_TYPE.SECURED_DATA_TRANSMISSION, subfunction=None, data=data) + # TODO: parse response into multiple output values? + return resp + + def control_dtc_setting(self, dtc_setting_type: DTC_SETTING_TYPE): + self._uds_request(SERVICE_TYPE.CONTROL_DTC_SETTING, subfunction=dtc_setting_type) + + def response_on_event(self, response_event_type: RESPONSE_EVENT_TYPE, store_event: bool, window_time: int, + event_type_record: int, service_response_record: int): + if store_event: + response_event_type |= 0x20 # type: ignore + # TODO: split record parameters into arrays + data = bytes([window_time, event_type_record, service_response_record]) + resp = self._uds_request(SERVICE_TYPE.RESPONSE_ON_EVENT, subfunction=response_event_type, data=data) + + if response_event_type == RESPONSE_EVENT_TYPE.REPORT_ACTIVATED_EVENTS: + return { + "num_of_activated_events": resp[0], + "data": resp[1:], # TODO: parse the reset of response + } + + return { + "num_of_identified_events": resp[0], + "event_window_time": resp[1], + "data": resp[2:], # TODO: parse the reset of response + } + + def link_control(self, link_control_type: LINK_CONTROL_TYPE, baud_rate_type: BAUD_RATE_TYPE | None = None): + data: bytes | None + + if link_control_type == LINK_CONTROL_TYPE.VERIFY_BAUDRATE_TRANSITION_WITH_FIXED_BAUDRATE: + # baud_rate_type = BAUD_RATE_TYPE + data = bytes([cast(int, baud_rate_type)]) + elif link_control_type == LINK_CONTROL_TYPE.VERIFY_BAUDRATE_TRANSITION_WITH_SPECIFIC_BAUDRATE: + # baud_rate_type = custom value (3 bytes big-endian) + data = struct.pack('!I', baud_rate_type)[1:] + else: + data = None + self._uds_request(SERVICE_TYPE.LINK_CONTROL, subfunction=link_control_type, data=data) + + def read_data_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE): + # TODO: support list of identifiers + data = struct.pack('!H', data_identifier_type) + resp = self._uds_request(SERVICE_TYPE.READ_DATA_BY_IDENTIFIER, subfunction=None, data=data) + resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None + if resp_id != data_identifier_type: + raise ValueError(f'invalid response data identifier: {hex(resp_id)} expected: {hex(data_identifier_type)}') + return resp[2:] + + def read_memory_by_address(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 1): + if memory_address_bytes < 1 or memory_address_bytes > 4: + raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') + if memory_size_bytes < 1 or memory_size_bytes > 4: + raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') + data = bytes([memory_size_bytes << 4 | memory_address_bytes]) + + if memory_address >= 1 << (memory_address_bytes * 8): + raise ValueError(f'invalid memory_address: {memory_address}') + data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] + if memory_size >= 1 << (memory_size_bytes * 8): + raise ValueError(f'invalid memory_size: {memory_size}') + data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] + + resp = self._uds_request(SERVICE_TYPE.READ_MEMORY_BY_ADDRESS, subfunction=None, data=data) + return resp + + def read_scaling_data_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE): + data = struct.pack('!H', data_identifier_type) + resp = self._uds_request(SERVICE_TYPE.READ_SCALING_DATA_BY_IDENTIFIER, subfunction=None, data=data) + resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None + if resp_id != data_identifier_type: + raise ValueError(f'invalid response data identifier: {hex(resp_id)}') + return resp[2:] # TODO: parse the response + + def read_data_by_periodic_identifier(self, transmission_mode_type: TRANSMISSION_MODE_TYPE, periodic_data_identifier: int): + # TODO: support list of identifiers + data = bytes([transmission_mode_type, periodic_data_identifier]) + self._uds_request(SERVICE_TYPE.READ_DATA_BY_PERIODIC_IDENTIFIER, subfunction=None, data=data) + + def dynamically_define_data_identifier(self, dynamic_definition_type: DYNAMIC_DEFINITION_TYPE, dynamic_data_identifier: int, + source_definitions: list[DynamicSourceDefinition], memory_address_bytes: int = 4, memory_size_bytes: int = 1): + if memory_address_bytes < 1 or memory_address_bytes > 4: + raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') + if memory_size_bytes < 1 or memory_size_bytes > 4: + raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') + + data = struct.pack('!H', dynamic_data_identifier) + if dynamic_definition_type == DYNAMIC_DEFINITION_TYPE.DEFINE_BY_IDENTIFIER: + for s in source_definitions: + data += struct.pack('!H', s.data_identifier) + bytes([s.position, s.memory_size]) + elif dynamic_definition_type == DYNAMIC_DEFINITION_TYPE.DEFINE_BY_MEMORY_ADDRESS: + data += bytes([memory_size_bytes << 4 | memory_address_bytes]) + for s in source_definitions: + if s.memory_address >= 1 << (memory_address_bytes * 8): + raise ValueError(f'invalid memory_address: {s.memory_address}') + data += struct.pack('!I', s.memory_address)[4 - memory_address_bytes:] + if s.memory_size >= 1 << (memory_size_bytes * 8): + raise ValueError(f'invalid memory_size: {s.memory_size}') + data += struct.pack('!I', s.memory_size)[4 - memory_size_bytes:] + elif dynamic_definition_type == DYNAMIC_DEFINITION_TYPE.CLEAR_DYNAMICALLY_DEFINED_DATA_IDENTIFIER: + pass + else: + raise ValueError(f'invalid dynamic identifier type: {hex(dynamic_definition_type)}') + self._uds_request(SERVICE_TYPE.DYNAMICALLY_DEFINE_DATA_IDENTIFIER, subfunction=dynamic_definition_type, data=data) + + def write_data_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE, data_record: bytes): + data = struct.pack('!H', data_identifier_type) + data_record + resp = self._uds_request(SERVICE_TYPE.WRITE_DATA_BY_IDENTIFIER, subfunction=None, data=data) + resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None + if resp_id != data_identifier_type: + raise ValueError(f'invalid response data identifier: {hex(resp_id)}') + + def write_memory_by_address(self, memory_address: int, memory_size: int, data_record: bytes, memory_address_bytes: int = 4, memory_size_bytes: int = 1): + if memory_address_bytes < 1 or memory_address_bytes > 4: + raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') + if memory_size_bytes < 1 or memory_size_bytes > 4: + raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') + data = bytes([memory_size_bytes << 4 | memory_address_bytes]) + + if memory_address >= 1 << (memory_address_bytes * 8): + raise ValueError(f'invalid memory_address: {memory_address}') + data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] + if memory_size >= 1 << (memory_size_bytes * 8): + raise ValueError(f'invalid memory_size: {memory_size}') + data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] + + data += data_record + self._uds_request(SERVICE_TYPE.WRITE_MEMORY_BY_ADDRESS, subfunction=None, data=data) + + def clear_diagnostic_information(self, dtc_group_type: DTC_GROUP_TYPE): + data = struct.pack('!I', dtc_group_type)[1:] # 3 bytes + self._uds_request(SERVICE_TYPE.CLEAR_DIAGNOSTIC_INFORMATION, subfunction=None, data=data) + + def read_dtc_information(self, dtc_report_type: DTC_REPORT_TYPE, dtc_status_mask_type: DTC_STATUS_MASK_TYPE = DTC_STATUS_MASK_TYPE.ALL, + dtc_severity_mask_type: DTC_SEVERITY_MASK_TYPE = DTC_SEVERITY_MASK_TYPE.ALL, dtc_mask_record: int = 0xFFFFFF, + dtc_snapshot_record_num: int = 0xFF, dtc_extended_record_num: int = 0xFF): + data = b'' + # dtc_status_mask_type + if dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_DTC_BY_STATUS_MASK or \ + dtc_report_type == DTC_REPORT_TYPE.DTC_BY_STATUS_MASK or \ + dtc_report_type == DTC_REPORT_TYPE.MIRROR_MEMORY_DTC_BY_STATUS_MASK or \ + dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_MIRROR_MEMORY_DTC_BY_STATUS_MASK or \ + dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK or \ + dtc_report_type == DTC_REPORT_TYPE.EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK: + data += bytes([dtc_status_mask_type]) + # dtc_mask_record + if dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_IDENTIFICATION or \ + dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER or \ + dtc_report_type == DTC_REPORT_TYPE.DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \ + dtc_report_type == DTC_REPORT_TYPE.MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \ + dtc_report_type == DTC_REPORT_TYPE.SEVERITY_INFORMATION_OF_DTC: + data += struct.pack('!I', dtc_mask_record)[1:] # 3 bytes + # dtc_snapshot_record_num + if dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_IDENTIFICATION or \ + dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER or \ + dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_RECORD_BY_RECORD_NUMBER: + data += bytes([dtc_snapshot_record_num]) + # dtc_extended_record_num + if dtc_report_type == DTC_REPORT_TYPE.DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \ + dtc_report_type == DTC_REPORT_TYPE.MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER: + data += bytes([dtc_extended_record_num]) + # dtc_severity_mask_type + if dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_DTC_BY_SEVERITY_MASK_RECORD or \ + dtc_report_type == DTC_REPORT_TYPE.DTC_BY_SEVERITY_MASK_RECORD: + data += bytes([dtc_severity_mask_type, dtc_status_mask_type]) + + resp = self._uds_request(SERVICE_TYPE.READ_DTC_INFORMATION, subfunction=dtc_report_type, data=data) + + # TODO: parse response + return resp + + def input_output_control_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE, control_parameter_type: CONTROL_PARAMETER_TYPE, + control_option_record: bytes = b'', control_enable_mask_record: bytes = b''): + data = struct.pack('!H', data_identifier_type) + bytes([control_parameter_type]) + control_option_record + control_enable_mask_record + resp = self._uds_request(SERVICE_TYPE.INPUT_OUTPUT_CONTROL_BY_IDENTIFIER, subfunction=None, data=data) + resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None + if resp_id != data_identifier_type: + raise ValueError(f'invalid response data identifier: {hex(resp_id)}') + return resp[2:] + + def routine_control(self, routine_control_type: ROUTINE_CONTROL_TYPE, routine_identifier_type: ROUTINE_IDENTIFIER_TYPE, routine_option_record: bytes = b''): + data = struct.pack('!H', routine_identifier_type) + routine_option_record + resp = self._uds_request(SERVICE_TYPE.ROUTINE_CONTROL, subfunction=routine_control_type, data=data) + resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None + if resp_id != routine_identifier_type: + raise ValueError(f'invalid response routine identifier: {hex(resp_id)}') + return resp[2:] + + def request_download(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 4, data_format: int = 0x00): + data = bytes([data_format]) + + if memory_address_bytes < 1 or memory_address_bytes > 4: + raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') + if memory_size_bytes < 1 or memory_size_bytes > 4: + raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') + data += bytes([memory_size_bytes << 4 | memory_address_bytes]) + + if memory_address >= 1 << (memory_address_bytes * 8): + raise ValueError(f'invalid memory_address: {memory_address}') + data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] + if memory_size >= 1 << (memory_size_bytes * 8): + raise ValueError(f'invalid memory_size: {memory_size}') + data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] + + resp = self._uds_request(SERVICE_TYPE.REQUEST_DOWNLOAD, subfunction=None, data=data) + max_num_bytes_len = resp[0] >> 4 if len(resp) > 0 else 0 + if max_num_bytes_len >= 1 and max_num_bytes_len <= 4: + max_num_bytes = struct.unpack('!I', (b"\x00" * (4 - max_num_bytes_len)) + resp[1:max_num_bytes_len + 1])[0] + else: + raise ValueError(f'invalid max_num_bytes_len: {max_num_bytes_len}') + + return max_num_bytes # max number of bytes per transfer data request + + def request_upload(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 4, data_format: int = 0x00): + data = bytes([data_format]) + + if memory_address_bytes < 1 or memory_address_bytes > 4: + raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') + if memory_size_bytes < 1 or memory_size_bytes > 4: + raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') + data += bytes([memory_size_bytes << 4 | memory_address_bytes]) + + if memory_address >= 1 << (memory_address_bytes * 8): + raise ValueError(f'invalid memory_address: {memory_address}') + data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] + if memory_size >= 1 << (memory_size_bytes * 8): + raise ValueError(f'invalid memory_size: {memory_size}') + data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] + + resp = self._uds_request(SERVICE_TYPE.REQUEST_UPLOAD, subfunction=None, data=data) + max_num_bytes_len = resp[0] >> 4 if len(resp) > 0 else 0 + if max_num_bytes_len >= 1 and max_num_bytes_len <= 4: + max_num_bytes = struct.unpack('!I', (b"\x00" * (4 - max_num_bytes_len)) + resp[1:max_num_bytes_len + 1])[0] + else: + raise ValueError(f'invalid max_num_bytes_len: {max_num_bytes_len}') + + return max_num_bytes # max number of bytes per transfer data request + + def transfer_data(self, block_sequence_count: int, data: bytes = b''): + data = bytes([block_sequence_count]) + data + resp = self._uds_request(SERVICE_TYPE.TRANSFER_DATA, subfunction=None, data=data) + resp_id = resp[0] if len(resp) > 0 else None + if resp_id != block_sequence_count: + raise ValueError(f'invalid block_sequence_count: {resp_id}') + return resp[1:] + + def request_transfer_exit(self): + self._uds_request(SERVICE_TYPE.REQUEST_TRANSFER_EXIT, subfunction=None) diff --git a/opendbc_repo/opendbc/car/values.py b/opendbc_repo/opendbc/car/values.py new file mode 100644 index 0000000000..f606249a4e --- /dev/null +++ b/opendbc_repo/opendbc/car/values.py @@ -0,0 +1,21 @@ +from typing import get_args +from opendbc.car.body.values import CAR as BODY +from opendbc.car.chrysler.values import CAR as CHRYSLER +from opendbc.car.ford.values import CAR as FORD +from opendbc.car.gm.values import CAR as GM +from opendbc.car.honda.values import CAR as HONDA +from opendbc.car.hyundai.values import CAR as HYUNDAI +from opendbc.car.mazda.values import CAR as MAZDA +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.nissan.values import CAR as NISSAN +from opendbc.car.psa.values import CAR as PSA +from opendbc.car.rivian.values import CAR as RIVIAN +from opendbc.car.subaru.values import CAR as SUBARU +from opendbc.car.tesla.values import CAR as TESLA +from opendbc.car.toyota.values import CAR as TOYOTA +from opendbc.car.volkswagen.values import CAR as VOLKSWAGEN + +Platform = BODY | CHRYSLER | FORD | GM | HONDA | HYUNDAI | MAZDA | MOCK | NISSAN | PSA | RIVIAN | SUBARU | TESLA | TOYOTA | VOLKSWAGEN +BRANDS = get_args(Platform) + +PLATFORMS: dict[str, Platform] = {str(platform): platform for brand in BRANDS for platform in brand} diff --git a/opendbc_repo/opendbc/car/vehicle_model.py b/opendbc_repo/opendbc/car/vehicle_model.py new file mode 100755 index 0000000000..bc87503a07 --- /dev/null +++ b/opendbc_repo/opendbc/car/vehicle_model.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +""" +Dynamic bicycle model from "The Science of Vehicle Dynamics (2014), M. Guiggiani" + +The state is x = [v, r]^T +with v lateral speed [m/s], and r rotational speed [rad/s] + +The input u is the steering angle [rad], and roll [rad] + +The system is defined by +x_dot = A*x + B*u + +A depends on longitudinal speed, u [m/s], and vehicle parameters CP +""" + +import numpy as np +from numpy.linalg import solve + +from opendbc.car.structs import CarParams +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY + + +class VehicleModel: + def __init__(self, CP: CarParams): + """ + Args: + CP: Car Parameters + """ + # for math readability, convert long names car params into short names + self.m: float = CP.mass + self.j: float = CP.rotationalInertia + self.l: float = CP.wheelbase + self.aF: float = CP.centerToFront + self.aR: float = CP.wheelbase - CP.centerToFront + self.chi: float = CP.steerRatioRear + + self.cF_orig: float = CP.tireStiffnessFront + self.cR_orig: float = CP.tireStiffnessRear + self.update_params(1.0, CP.steerRatio) + + def update_params(self, stiffness_factor: float, steer_ratio: float) -> None: + """Update the vehicle model with a new stiffness factor and steer ratio""" + self.cF: float = stiffness_factor * self.cF_orig + self.cR: float = stiffness_factor * self.cR_orig + self.sR: float = steer_ratio + + def steady_state_sol(self, sa: float, u: float, roll: float) -> np.ndarray: + """Returns the steady state solution. + + If the speed is too low we can't use the dynamic model (tire slip is undefined), + we then have to use the kinematic model + + Args: + sa: Steering wheel angle [rad] + u: Speed [m/s] + roll: Road Roll [rad] + + Returns: + 2x1 matrix with steady state solution (lateral speed, rotational speed) + """ + if u > 0.1: + return dyn_ss_sol(sa, u, roll, self) + else: + return kin_ss_sol(sa, u, self) + + def calc_curvature(self, sa: float, u: float, roll: float) -> float: + """Returns the curvature. Multiplied by the speed this will give the yaw rate. + + Args: + sa: Steering wheel angle [rad] + u: Speed [m/s] + roll: Road Roll [rad] + + Returns: + Curvature factor [1/m] + """ + return (self.curvature_factor(u) * sa / self.sR) + self.roll_compensation(roll, u) + + def curvature_factor(self, u: float) -> float: + """Returns the curvature factor. + Multiplied by wheel angle (not steering wheel angle) this will give the curvature. + + Args: + u: Speed [m/s] + + Returns: + Curvature factor [1/m] + """ + sf = calc_slip_factor(self) + return (1. - self.chi) / (1. - sf * u**2) / self.l + + def get_steer_from_curvature(self, curv: float, u: float, roll: float) -> float: + """Calculates the required steering wheel angle for a given curvature + + Args: + curv: Desired curvature [1/m] + u: Speed [m/s] + roll: Road Roll [rad] + + Returns: + Steering wheel angle [rad] + """ + + return (curv - self.roll_compensation(roll, u)) * self.sR * 1.0 / self.curvature_factor(u) + + def roll_compensation(self, roll: float, u: float) -> float: + """Calculates the roll-compensation to curvature + + Args: + roll: Road Roll [rad] + u: Speed [m/s] + + Returns: + Roll compensation curvature [rad] + """ + sf = calc_slip_factor(self) + + if abs(sf) < 1e-6: + return 0 + else: + return (ACCELERATION_DUE_TO_GRAVITY * roll) / ((1 / sf) - u**2) + + def get_steer_from_yaw_rate(self, yaw_rate: float, u: float, roll: float) -> float: + """Calculates the required steering wheel angle for a given yaw_rate + + Args: + yaw_rate: Desired yaw rate [rad/s] + u: Speed [m/s] + roll: Road Roll [rad] + + Returns: + Steering wheel angle [rad] + """ + curv = yaw_rate / u + return self.get_steer_from_curvature(curv, u, roll) + + def yaw_rate(self, sa: float, u: float, roll: float) -> float: + """Calculate yaw rate + + Args: + sa: Steering wheel angle [rad] + u: Speed [m/s] + roll: Road Roll [rad] + + Returns: + Yaw rate [rad/s] + """ + return self.calc_curvature(sa, u, roll) * u + + +def kin_ss_sol(sa: float, u: float, VM: VehicleModel) -> np.ndarray: + """Calculate the steady state solution at low speeds + At low speeds the tire slip is undefined, so a kinematic + model is used. + + Args: + sa: Steering angle [rad] + u: Speed [m/s] + VM: Vehicle model + + Returns: + 2x1 matrix with steady state solution + """ + K = np.zeros((2, 1)) + K[0, 0] = VM.aR / VM.sR / VM.l * u + K[1, 0] = 1. / VM.sR / VM.l * u + return K * sa + + +def create_dyn_state_matrices(u: float, VM: VehicleModel) -> tuple[np.ndarray, np.ndarray]: + """Returns the A and B matrix for the dynamics system + + Args: + u: Vehicle speed [m/s] + VM: Vehicle model + + Returns: + A tuple with the 2x2 A matrix, and 2x2 B matrix + + Parameters in the vehicle model: + cF: Tire stiffness Front [N/rad] + cR: Tire stiffness Rear [N/rad] + aF: Distance from CG to front wheels [m] + aR: Distance from CG to rear wheels [m] + m: Mass [kg] + j: Rotational inertia [kg m^2] + sR: Steering ratio [-] + chi: Steer ratio rear [-] + """ + A = np.zeros((2, 2)) + B = np.zeros((2, 2)) + A[0, 0] = - (VM.cF + VM.cR) / (VM.m * u) + A[0, 1] = - (VM.cF * VM.aF - VM.cR * VM.aR) / (VM.m * u) - u + A[1, 0] = - (VM.cF * VM.aF - VM.cR * VM.aR) / (VM.j * u) + A[1, 1] = - (VM.cF * VM.aF**2 + VM.cR * VM.aR**2) / (VM.j * u) + + # Steering input + B[0, 0] = (VM.cF + VM.chi * VM.cR) / VM.m / VM.sR + B[1, 0] = (VM.cF * VM.aF - VM.chi * VM.cR * VM.aR) / VM.j / VM.sR + + # Roll input + B[0, 1] = -ACCELERATION_DUE_TO_GRAVITY + + return A, B + + +def dyn_ss_sol(sa: float, u: float, roll: float, VM: VehicleModel) -> np.ndarray: + """Calculate the steady state solution when x_dot = 0, + Ax + Bu = 0 => x = -A^{-1} B u + + Args: + sa: Steering angle [rad] + u: Speed [m/s] + roll: Road Roll [rad] + VM: Vehicle model + + Returns: + 2x1 matrix with steady state solution + """ + A, B = create_dyn_state_matrices(u, VM) + inp = np.array([[sa], [roll]]) + return -solve(A, B) @ inp # type: ignore + + +def calc_slip_factor(VM: VehicleModel) -> float: + """The slip factor is a measure of how the curvature changes with speed + it's positive for Oversteering vehicle, negative (usual case) otherwise. + """ + return VM.m * (VM.cF * VM.aF - VM.cR * VM.aR) / (VM.l**2 * VM.cF * VM.cR) diff --git a/opendbc_repo/opendbc/car/vin.py b/opendbc_repo/opendbc/car/vin.py new file mode 100644 index 0000000000..e373c76665 --- /dev/null +++ b/opendbc_repo/opendbc/car/vin.py @@ -0,0 +1,75 @@ +import re +from dataclasses import dataclass, field + +from opendbc.car import uds +from opendbc.car.carlog import carlog +from opendbc.car.isotp_parallel_query import IsoTpParallelQuery +from opendbc.car.fw_query_definitions import STANDARD_VIN_ADDRS, StdQueries + +VIN_UNKNOWN = "0" * 17 +VIN_RE = "[A-HJ-NPR-Z0-9]{17}" + + +@dataclass +class Vin: + vin: str + wmi: str = field(init=False) + vds: str = field(init=False) + vis: str = field(init=False) + + def __post_init__(self): + # parses VIN in accordance with North America standard >2000 vehicles: + # https://en.wikipedia.org/wiki/Vehicle_identification_number#Components + self.wmi = self.vin[:3] # World Manufacturer Identifier + self.vds = self.vin[3:9] # Vehicle Descriptor Section + self.vis = self.vin[9:17] # Vehicle Identifier Section + + +def is_valid_vin(vin: str): + return re.fullmatch(VIN_RE, vin) is not None + + +def get_vin(can_recv, can_send, buses, timeout=0.1, retry=2): + for i in range(retry): + for bus in buses: + for request, response, valid_buses, vin_addrs, functional_addrs, rx_offset in ( + (StdQueries.UDS_VIN_REQUEST, StdQueries.UDS_VIN_RESPONSE, (0, 1), STANDARD_VIN_ADDRS, uds.FUNCTIONAL_ADDRS, 0x8), + (StdQueries.OBD_VIN_REQUEST, StdQueries.OBD_VIN_RESPONSE, (0, 1), STANDARD_VIN_ADDRS, uds.FUNCTIONAL_ADDRS, 0x8), + (StdQueries.GM_VIN_REQUEST, StdQueries.GM_VIN_RESPONSE, (0,), [0x24b], None, 0x400), # Bolt fwdCamera + (StdQueries.KWP_VIN_REQUEST, StdQueries.KWP_VIN_RESPONSE, (0,), [0x797], None, 0x3), # Nissan Leaf VCM + (StdQueries.UDS_VIN_REQUEST, StdQueries.UDS_VIN_RESPONSE, (0,), [0x74f], None, 0x6a), # Volkswagen fwdCamera + (StdQueries.UDS_VIN_REQUEST, StdQueries.UDS_VIN_RESPONSE, (0,), [0x733], None, 0x40), # Rivian EPAS + ): + if bus not in valid_buses: + continue + + # When querying functional addresses, ideally we respond to everything that sends a first frame to avoid leaving the + # ECU in a temporary bad state. Note that we may not cover all ECUs and response offsets. TODO: query physical addrs + tx_addrs = vin_addrs + if functional_addrs is not None: + tx_addrs = [a for a in range(0x700, 0x800) if a != 0x7DF] + list(range(0x18DA00F1, 0x18DB00F1, 0x100)) + + try: + query = IsoTpParallelQuery(can_send, can_recv, bus, tx_addrs, [request, ], [response, ], response_offset=rx_offset, + functional_addrs=functional_addrs) + results = query.get_data(timeout) + + for addr in vin_addrs: + vin = results.get((addr, None)) + if vin is not None: + # Ford and Nissan pads with null bytes + if len(vin) in (19, 24): + vin = re.sub(b'\x00*$', b'', vin) + + # Honda Bosch response starts with a length, trim to correct length + if vin.startswith(b'\x11'): + vin = vin[1:18] + + carlog.error(f"got vin with {request=}") + return uds.get_rx_addr_for_tx_addr(addr, rx_offset=rx_offset), bus, vin.decode() + except Exception: + carlog.exception("VIN query exception") + + carlog.error(f"vin query retry ({i+1}) ...") + + return -1, -1, VIN_UNKNOWN diff --git a/opendbc_repo/opendbc/car/volkswagen/__init__.py b/opendbc_repo/opendbc/car/volkswagen/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/volkswagen/carcontroller.py b/opendbc_repo/opendbc/car/volkswagen/carcontroller.py new file mode 100644 index 0000000000..a42ddf2cbc --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/carcontroller.py @@ -0,0 +1,128 @@ +import numpy as np +from opendbc.can import CANPacker +from opendbc.car import Bus, DT_CTRL, structs +from opendbc.car.lateral import apply_driver_steer_torque_limits +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.interfaces import CarControllerBase +from opendbc.car.volkswagen import mqbcan, pqcan +from opendbc.car.volkswagen.values import CanBus, CarControllerParams, VolkswagenFlags + +VisualAlert = structs.CarControl.HUDControl.VisualAlert +LongCtrlState = structs.CarControl.Actuators.LongControlState + + +class CarController(CarControllerBase): + def __init__(self, dbc_names, CP): + super().__init__(dbc_names, CP) + self.CCP = CarControllerParams(CP) + self.CAN = CanBus(CP) + self.CCS = pqcan if CP.flags & VolkswagenFlags.PQ else mqbcan + self.packer_pt = CANPacker(dbc_names[Bus.pt]) + self.aeb_available = not CP.flags & VolkswagenFlags.PQ + + self.apply_torque_last = 0 + self.gra_acc_counter_last = None + self.eps_timer_soft_disable_alert = False + self.hca_frame_timer_running = 0 + self.hca_frame_same_torque = 0 + + def update(self, CC, CS, now_nanos): + actuators = CC.actuators + hud_control = CC.hudControl + can_sends = [] + + # **** Steering Controls ************************************************ # + + if self.frame % self.CCP.STEER_STEP == 0: + # Logic to avoid HCA state 4 "refused": + # * Don't steer unless HCA is in state 3 "ready" or 5 "active" + # * Don't steer at standstill + # * Don't send > 3.00 Newton-meters torque + # * Don't send the same torque for > 6 seconds + # * Don't send uninterrupted steering for > 360 seconds + # MQB racks reset the uninterrupted steering timer after a single frame + # of HCA disabled; this is done whenever output happens to be zero. + + if CC.latActive: + new_torque = int(round(actuators.torque * self.CCP.STEER_MAX)) + apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.CCP) + self.hca_frame_timer_running += self.CCP.STEER_STEP + if self.apply_torque_last == apply_torque: + self.hca_frame_same_torque += self.CCP.STEER_STEP + if self.hca_frame_same_torque > self.CCP.STEER_TIME_STUCK_TORQUE / DT_CTRL: + apply_torque -= (1, -1)[apply_torque < 0] + self.hca_frame_same_torque = 0 + else: + self.hca_frame_same_torque = 0 + hca_enabled = abs(apply_torque) > 0 + else: + hca_enabled = False + apply_torque = 0 + + if not hca_enabled: + self.hca_frame_timer_running = 0 + + self.eps_timer_soft_disable_alert = self.hca_frame_timer_running > self.CCP.STEER_TIME_ALERT / DT_CTRL + self.apply_torque_last = apply_torque + can_sends.append(self.CCS.create_steering_control(self.packer_pt, self.CAN.pt, apply_torque, hca_enabled)) + + if self.CP.flags & VolkswagenFlags.STOCK_HCA_PRESENT: + # Pacify VW Emergency Assist driver inactivity detection by changing its view of driver steering input torque + # to the greatest of actual driver input or 2x openpilot's output (1x openpilot output is not enough to + # consistently reset inactivity detection on straight level roads). See commaai/openpilot#23274 for background. + ea_simulated_torque = float(np.clip(apply_torque * 2, -self.CCP.STEER_MAX, self.CCP.STEER_MAX)) + if abs(CS.out.steeringTorque) > abs(ea_simulated_torque): + ea_simulated_torque = CS.out.steeringTorque + can_sends.append(self.CCS.create_eps_update(self.packer_pt, self.CAN.cam, CS.eps_stock_values, ea_simulated_torque)) + + # **** Acceleration Controls ******************************************** # + + if self.CP.openpilotLongitudinalControl: + if self.frame % self.CCP.ACC_CONTROL_STEP == 0: + acc_control = self.CCS.acc_control_value(CS.out.cruiseState.available, CS.out.accFaulted, CC.longActive) + accel = float(np.clip(actuators.accel, self.CCP.ACCEL_MIN, self.CCP.ACCEL_MAX) if CC.longActive else 0) + stopping = actuators.longControlState == LongCtrlState.stopping + starting = actuators.longControlState == LongCtrlState.pid and (CS.esp_hold_confirmation or CS.out.vEgo < self.CP.vEgoStopping) + can_sends.extend(self.CCS.create_acc_accel_control(self.packer_pt, self.CAN.pt, CS.acc_type, CC.longActive, accel, + acc_control, stopping, starting, CS.esp_hold_confirmation)) + + #if self.aeb_available: + # if self.frame % self.CCP.AEB_CONTROL_STEP == 0: + # can_sends.append(self.CCS.create_aeb_control(self.packer_pt, False, False, 0.0)) + # if self.frame % self.CCP.AEB_HUD_STEP == 0: + # can_sends.append(self.CCS.create_aeb_hud(self.packer_pt, False, False)) + + # **** HUD Controls ***************************************************** # + + if self.frame % self.CCP.LDW_STEP == 0: + hud_alert = 0 + if hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw): + hud_alert = self.CCP.LDW_MESSAGES["laneAssistTakeOver"] + can_sends.append(self.CCS.create_lka_hud_control(self.packer_pt, self.CAN.pt, CS.ldw_stock_values, CC.latActive, + CS.out.steeringPressed, hud_alert, hud_control)) + + if self.frame % self.CCP.ACC_HUD_STEP == 0 and self.CP.openpilotLongitudinalControl: + lead_distance = 0 + if hud_control.leadVisible and self.frame * DT_CTRL > 1.0: # Don't display lead until we know the scaling factor + lead_distance = 512 if CS.upscale_lead_car_signal else 8 + acc_hud_status = self.CCS.acc_hud_status_value(CS.out.cruiseState.available, CS.out.accFaulted, CC.longActive) + # FIXME: PQ may need to use the on-the-wire mph/kmh toggle to fix rounding errors + # FIXME: Detect clusters with vEgoCluster offsets and apply an identical vCruiseCluster offset + set_speed = hud_control.setSpeed * CV.MS_TO_KPH + can_sends.append(self.CCS.create_acc_hud_control(self.packer_pt, self.CAN.pt, acc_hud_status, set_speed, + lead_distance, hud_control.leadDistanceBars)) + + # **** Stock ACC Button Controls **************************************** # + + gra_send_ready = self.CP.pcmCruise and CS.gra_stock_values["COUNTER"] != self.gra_acc_counter_last + if gra_send_ready and (CC.cruiseControl.cancel or CC.cruiseControl.resume): + can_sends.append(self.CCS.create_acc_buttons_control(self.packer_pt, self.CAN.ext, CS.gra_stock_values, + cancel=CC.cruiseControl.cancel, resume=CC.cruiseControl.resume)) + + new_actuators = actuators.as_builder() + new_actuators.torque = self.apply_torque_last / self.CCP.STEER_MAX + new_actuators.torqueOutputCan = self.apply_torque_last + + self.gra_acc_counter_last = CS.gra_stock_values["COUNTER"] + self.frame += 1 + return new_actuators, can_sends diff --git a/opendbc_repo/opendbc/car/volkswagen/carstate.py b/opendbc_repo/opendbc/car/volkswagen/carstate.py new file mode 100644 index 0000000000..9857c9d4d4 --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/carstate.py @@ -0,0 +1,277 @@ +from opendbc.can import CANParser +from opendbc.car import Bus, structs +from opendbc.car.interfaces import CarStateBase +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.volkswagen.values import DBC, CanBus, NetworkLocation, TransmissionType, GearShifter, \ + CarControllerParams, VolkswagenFlags + +ButtonType = structs.CarState.ButtonEvent.Type + + +class CarState(CarStateBase): + def __init__(self, CP): + super().__init__(CP) + self.frame = 0 + self.eps_init_complete = False + self.CCP = CarControllerParams(CP) + self.button_states = {button.event_type: False for button in self.CCP.BUTTONS} + self.esp_hold_confirmation = False + self.upscale_lead_car_signal = False + self.eps_stock_values = False + + def update_button_enable(self, buttonEvents: list[structs.CarState.ButtonEvent]): + if not self.CP.pcmCruise: + for b in buttonEvents: + # Enable OP long on falling edge of enable buttons + if b.type in (ButtonType.setCruise, ButtonType.resumeCruise) and not b.pressed: + return True + return False + + def create_button_events(self, pt_cp, buttons): + button_events = [] + + for button in buttons: + state = pt_cp.vl[button.can_addr][button.can_msg] in button.values + if self.button_states[button.event_type] != state: + event = structs.CarState.ButtonEvent() + event.type = button.event_type + event.pressed = state + button_events.append(event) + self.button_states[button.event_type] = state + + return button_events + + def update(self, can_parsers) -> structs.CarState: + pt_cp = can_parsers[Bus.pt] + cam_cp = can_parsers[Bus.cam] + ext_cp = pt_cp if self.CP.networkLocation == NetworkLocation.fwdCamera else cam_cp + + if self.CP.flags & VolkswagenFlags.PQ: + return self.update_pq(pt_cp, cam_cp, ext_cp) + + ret = structs.CarState() + + if self.CP.transmissionType == TransmissionType.direct: + ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Motor_EV_01"]["MO_Waehlpos"], None)) + elif self.CP.transmissionType == TransmissionType.manual: + if bool(pt_cp.vl["Gateway_72"]["BCM1_Rueckfahrlicht_Schalter"]): + ret.gearShifter = GearShifter.reverse + else: + ret.gearShifter = GearShifter.drive + else: + ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Gateway_73"]["GE_Fahrstufe"], None)) + + if True: + # MQB-specific + if self.CP.flags & VolkswagenFlags.KOMBI_PRESENT: + self.upscale_lead_car_signal = bool(pt_cp.vl["Kombi_03"]["KBI_Variante"]) # Analog vs digital instrument cluster + + self.parse_wheel_speeds(ret, + pt_cp.vl["ESP_19"]["ESP_VL_Radgeschw_02"], + pt_cp.vl["ESP_19"]["ESP_VR_Radgeschw_02"], + pt_cp.vl["ESP_19"]["ESP_HL_Radgeschw_02"], + pt_cp.vl["ESP_19"]["ESP_HR_Radgeschw_02"], + ) + + hca_status = self.CCP.hca_status_values.get(pt_cp.vl["LH_EPS_03"]["EPS_HCA_Status"]) + if self.CP.flags & VolkswagenFlags.STOCK_HCA_PRESENT: + ret.carFaultedNonCritical = bool(cam_cp.vl["HCA_01"]["EA_Ruckfreigabe"]) or cam_cp.vl["HCA_01"]["EA_ACC_Sollstatus"] > 0 # EA + + drive_mode = True + ret.brake = pt_cp.vl["ESP_05"]["ESP_Bremsdruck"] / 250.0 # FIXME: this is pressure in Bar, not sure what OP expects + brake_pedal_pressed = bool(pt_cp.vl["Motor_14"]["MO_Fahrer_bremst"]) + brake_pressure_detected = bool(pt_cp.vl["ESP_05"]["ESP_Fahrer_bremst"]) + ret.brakePressed = brake_pedal_pressed or brake_pressure_detected + ret.parkingBrake = bool(pt_cp.vl["Kombi_01"]["KBI_Handbremse"]) # FIXME: need to include an EPB check as well + + ret.doorOpen = any([pt_cp.vl["Gateway_72"]["ZV_FT_offen"], + pt_cp.vl["Gateway_72"]["ZV_BT_offen"], + pt_cp.vl["Gateway_72"]["ZV_HFS_offen"], + pt_cp.vl["Gateway_72"]["ZV_HBFS_offen"], + pt_cp.vl["Gateway_72"]["ZV_HD_offen"]]) + + if self.CP.enableBsm: + # Infostufe: BSM LED on, Warnung: BSM LED flashing + ret.leftBlindspot = bool(ext_cp.vl["SWA_01"]["SWA_Infostufe_SWA_li"]) or bool(ext_cp.vl["SWA_01"]["SWA_Warnung_SWA_li"]) + ret.rightBlindspot = bool(ext_cp.vl["SWA_01"]["SWA_Infostufe_SWA_re"]) or bool(ext_cp.vl["SWA_01"]["SWA_Warnung_SWA_re"]) + + ret.stockFcw = bool(ext_cp.vl["ACC_10"]["AWV2_Freigabe"]) + ret.stockAeb = bool(ext_cp.vl["ACC_10"]["ANB_Teilbremsung_Freigabe"]) or bool(ext_cp.vl["ACC_10"]["ANB_Zielbremsung_Freigabe"]) + + self.acc_type = ext_cp.vl["ACC_06"]["ACC_Typ"] + self.esp_hold_confirmation = bool(pt_cp.vl["ESP_21"]["ESP_Haltebestaetigung"]) + acc_limiter_mode = ext_cp.vl["ACC_02"]["ACC_Gesetzte_Zeitluecke"] == 0 + speed_limiter_mode = bool(pt_cp.vl["TSK_06"]["TSK_Limiter_ausgewaehlt"]) + + ret.cruiseState.available = pt_cp.vl["TSK_06"]["TSK_Status"] in (2, 3, 4, 5) + ret.cruiseState.enabled = pt_cp.vl["TSK_06"]["TSK_Status"] in (3, 4, 5) + ret.cruiseState.speed = ext_cp.vl["ACC_02"]["ACC_Wunschgeschw_02"] * CV.KPH_TO_MS if self.CP.pcmCruise else 0 + ret.accFaulted = pt_cp.vl["TSK_06"]["TSK_Status"] in (6, 7) + + ret.leftBlinker = bool(pt_cp.vl["Blinkmodi_02"]["Comfort_Signal_Left"]) + ret.rightBlinker = bool(pt_cp.vl["Blinkmodi_02"]["Comfort_Signal_Right"]) + + # Shared logic + ret.vEgoCluster = pt_cp.vl["Kombi_01"]["KBI_angez_Geschw"] * CV.KPH_TO_MS + + ret.steeringAngleDeg = pt_cp.vl["LWI_01"]["LWI_Lenkradwinkel"] * (1, -1)[int(pt_cp.vl["LWI_01"]["LWI_VZ_Lenkradwinkel"])] + ret.steeringRateDeg = pt_cp.vl["LWI_01"]["LWI_Lenkradw_Geschw"] * (1, -1)[int(pt_cp.vl["LWI_01"]["LWI_VZ_Lenkradw_Geschw"])] + ret.steeringTorque = pt_cp.vl["LH_EPS_03"]["EPS_Lenkmoment"] * (1, -1)[int(pt_cp.vl["LH_EPS_03"]["EPS_VZ_Lenkmoment"])] + ret.steeringPressed = abs(ret.steeringTorque) > self.CCP.STEER_DRIVER_ALLOWANCE + ret.steerFaultTemporary, ret.steerFaultPermanent = self.update_hca_state(hca_status, drive_mode) + + ret.gasPressed = pt_cp.vl["Motor_20"]["MO_Fahrpedalrohwert_01"] > 0 + ret.espActive = bool(pt_cp.vl["ESP_21"]["ESP_Eingriff"]) + ret.espDisabled = pt_cp.vl["ESP_21"]["ESP_Tastung_passiv"] != 0 + ret.seatbeltUnlatched = pt_cp.vl["Airbag_02"]["AB_Gurtschloss_FA"] != 3 + + ret.standstill = ret.vEgoRaw == 0 + ret.cruiseState.standstill = self.CP.pcmCruise and self.esp_hold_confirmation + ret.cruiseState.nonAdaptive = acc_limiter_mode or speed_limiter_mode + if ret.cruiseState.speed > 90: + ret.cruiseState.speed = 0 + + self.eps_stock_values = pt_cp.vl["LH_EPS_03"] + self.ldw_stock_values = cam_cp.vl["LDW_02"] if self.CP.networkLocation == NetworkLocation.fwdCamera else {} + self.gra_stock_values = pt_cp.vl["GRA_ACC_01"] + + ret.buttonEvents = self.create_button_events(pt_cp, self.CCP.BUTTONS) + + ret.lowSpeedAlert = self.update_low_speed_alert(ret.vEgo) + + self.frame += 1 + return ret + + def update_pq(self, pt_cp, cam_cp, ext_cp) -> structs.CarState: + ret = structs.CarState() + + # vEgo obtained from Bremse_1 vehicle speed rather than Bremse_3 wheel speeds because Bremse_3 isn't present on NSF + ret.vEgoRaw = pt_cp.vl["Bremse_1"]["BR1_Rad_kmh"] * CV.KPH_TO_MS + ret.vEgo, ret.aEgo = self.update_speed_kf(ret.vEgoRaw) + ret.standstill = ret.vEgoRaw == 0 + + # Update EPS position and state info. For signed values, VW sends the sign in a separate signal. + ret.steeringAngleDeg = pt_cp.vl["Lenkhilfe_3"]["LH3_BLW"] * (1, -1)[int(pt_cp.vl["Lenkhilfe_3"]["LH3_BLWSign"])] + ret.steeringRateDeg = pt_cp.vl["Lenkwinkel_1"]["LW1_Lenk_Gesch"] * (1, -1)[int(pt_cp.vl["Lenkwinkel_1"]["LW1_Gesch_Sign"])] + ret.steeringTorque = pt_cp.vl["Lenkhilfe_3"]["LH3_LM"] * (1, -1)[int(pt_cp.vl["Lenkhilfe_3"]["LH3_LMSign"])] + ret.steeringPressed = abs(ret.steeringTorque) > self.CCP.STEER_DRIVER_ALLOWANCE + hca_status = self.CCP.hca_status_values.get(pt_cp.vl["Lenkhilfe_2"]["LH2_Sta_HCA"]) + ret.steerFaultTemporary, ret.steerFaultPermanent = self.update_hca_state(hca_status) + + # Update gas, brakes, and gearshift. + ret.gasPressed = pt_cp.vl["Motor_3"]["Fahrpedal_Rohsignal"] > 0 + ret.brake = pt_cp.vl["Bremse_5"]["BR5_Bremsdruck"] / 250.0 # FIXME: this is pressure in Bar, not sure what OP expects + ret.brakePressed = bool(pt_cp.vl["Motor_2"]["MO2_BLS"]) + ret.parkingBrake = bool(pt_cp.vl["Kombi_1"]["Bremsinfo"]) + + # Update gear and/or clutch position data. + if self.CP.transmissionType == TransmissionType.automatic: + ret.gearShifter = self.parse_gear_shifter(self.CCP.shifter_values.get(pt_cp.vl["Getriebe_1"]["Waehlhebelposition__Getriebe_1_"], None)) + elif self.CP.transmissionType == TransmissionType.manual: + reverse_light = bool(pt_cp.vl["Gate_Komf_1"]["GK1_Rueckfahr"]) + if reverse_light: + ret.gearShifter = GearShifter.reverse + else: + ret.gearShifter = GearShifter.drive + + # Update door and trunk/hatch lid open status. + ret.doorOpen = any([pt_cp.vl["Gate_Komf_1"]["GK1_Fa_Tuerkont"], + pt_cp.vl["Gate_Komf_1"]["BSK_BT_geoeffnet"], + pt_cp.vl["Gate_Komf_1"]["BSK_HL_geoeffnet"], + pt_cp.vl["Gate_Komf_1"]["BSK_HR_geoeffnet"], + pt_cp.vl["Gate_Komf_1"]["BSK_HD_Hauptraste"]]) + + # Update seatbelt fastened status. + ret.seatbeltUnlatched = not bool(pt_cp.vl["Airbag_1"]["Gurtschalter_Fahrer"]) + + # Consume blind-spot monitoring info/warning LED states, if available. + # Infostufe: BSM LED on, Warnung: BSM LED flashing + if self.CP.enableBsm: + ret.leftBlindspot = bool(ext_cp.vl["SWA_1"]["SWA_Infostufe_SWA_li"]) or bool(ext_cp.vl["SWA_1"]["SWA_Warnung_SWA_li"]) + ret.rightBlindspot = bool(ext_cp.vl["SWA_1"]["SWA_Infostufe_SWA_re"]) or bool(ext_cp.vl["SWA_1"]["SWA_Warnung_SWA_re"]) + + # Consume factory LDW data relevant for factory SWA (Lane Change Assist) + # and capture it for forwarding to the blind spot radar controller + self.ldw_stock_values = cam_cp.vl["LDW_Status"] if self.CP.networkLocation == NetworkLocation.fwdCamera else {} + + # Stock FCW is considered active if the release bit for brake-jerk warning + # is set. Stock AEB considered active if the partial braking or target + # braking release bits are set. + # Refer to VW Self Study Program 890253: Volkswagen Driver Assistance + # Systems, chapters on Front Assist with Braking and City Emergency + # Braking for the 2016 Passat NMS + # TODO: deferred until we can collect data on pre-MY2016 behavior, AWV message may be shorter with fewer signals + ret.stockFcw = False + ret.stockAeb = False + + # Update ACC radar status. + self.acc_type = ext_cp.vl["ACC_System"]["ACS_Typ_ACC"] + ret.cruiseState.available = bool(pt_cp.vl["Motor_5"]["GRA_Hauptschalter"]) + ret.cruiseState.enabled = pt_cp.vl["Motor_2"]["MO2_Sta_GRA"] in (1, 2) + if self.CP.pcmCruise: + ret.accFaulted = ext_cp.vl["ACC_GRA_Anzeige"]["ACA_StaACC"] in (6, 7) + else: + ret.accFaulted = pt_cp.vl["Motor_2"]["MO2_Sta_GRA"] == 3 + + # Update ACC setpoint. When the setpoint reads as 255, the driver has not + # yet established an ACC setpoint, so treat it as zero. + ret.cruiseState.speed = ext_cp.vl["ACC_GRA_Anzeige"]["ACA_V_Wunsch"] * CV.KPH_TO_MS + if ret.cruiseState.speed > 70: # 255 kph in m/s == no current setpoint + ret.cruiseState.speed = 0 + + # Update button states for turn signals and ACC controls, capture all ACC button state/config for passthrough + ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_stalk(300, pt_cp.vl["Gate_Komf_1"]["GK1_Blinker_li"], + pt_cp.vl["Gate_Komf_1"]["GK1_Blinker_re"]) + ret.buttonEvents = self.create_button_events(pt_cp, self.CCP.BUTTONS) + self.gra_stock_values = pt_cp.vl["GRA_Neu"] + + # Additional safety checks performed in CarInterface. + ret.espDisabled = bool(pt_cp.vl["Bremse_1"]["BR1_ESPASR_passive"]) + + ret.lowSpeedAlert = self.update_low_speed_alert(ret.vEgo) + + self.frame += 1 + return ret + + def update_low_speed_alert(self, v_ego: float) -> bool: + # Low speed steer alert hysteresis logic + if (self.CP.minSteerSpeed - 1e-3) > CarControllerParams.DEFAULT_MIN_STEER_SPEED and v_ego < (self.CP.minSteerSpeed + 1.): + self.low_speed_alert = True + elif v_ego > (self.CP.minSteerSpeed + 2.): + self.low_speed_alert = False + return self.low_speed_alert + + def update_hca_state(self, hca_status, drive_mode=True): + # Treat FAULT as temporary for worst likely EPS recovery time, for cars without factory Lane Assist + # DISABLED means the EPS hasn't been configured to support Lane Assist + self.eps_init_complete = self.eps_init_complete or (hca_status in ("DISABLED", "READY", "ACTIVE") or self.frame > 600) + perm_fault = drive_mode and hca_status == "DISABLED" or (self.eps_init_complete and hca_status == "FAULT") + temp_fault = drive_mode and hca_status in ("REJECTED", "PREEMPTED") or not self.eps_init_complete + return temp_fault, perm_fault + + @staticmethod + def get_can_parsers(CP): + if CP.flags & VolkswagenFlags.PQ: + return CarState.get_can_parsers_pq(CP) + + # another case of the 1-50Hz + cam_messages = [] + if CP.flags & VolkswagenFlags.STOCK_HCA_PRESENT: + cam_messages += [ + ("HCA_01", 1), # From R242 Driver assistance camera, 50Hz if steering/1Hz if not + ] + + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [ + # the 50->1Hz is currently too much for the CANParser to figure out + ("Blinkmodi_02", 1), # From J519 BCM (sent at 1Hz when no lights active, 50Hz when active) + ], CanBus(CP).pt), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], cam_messages, CanBus(CP).cam), + } + + @staticmethod + def get_can_parsers_pq(CP): + return { + Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).pt), + Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus(CP).cam), + } diff --git a/opendbc_repo/opendbc/car/volkswagen/fingerprints.py b/opendbc_repo/opendbc/car/volkswagen/fingerprints.py new file mode 100644 index 0000000000..f29b6ff55e --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/fingerprints.py @@ -0,0 +1,1294 @@ +""" AUTO-FORMATTED USING opendbc/car/debug/format_fingerprints.py, EDIT STRUCTURE THERE.""" +from opendbc.car.structs import CarParams +from opendbc.car.volkswagen.values import CAR + +Ecu = CarParams.Ecu + +# TODO: Sharan Mk2 EPS and DQ250 auto trans both require KWP2000 support for fingerprinting + + +FW_VERSIONS = { + CAR.VOLKSWAGEN_ARTEON_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704L906026TM\xf1\x896847', + b'\xf1\x873G0906259AH\xf1\x890001', + b'\xf1\x873G0906259F \xf1\x890004', + b'\xf1\x873G0906259G \xf1\x890004', + b'\xf1\x873G0906259G \xf1\x890005', + b'\xf1\x873G0906259J \xf1\x890002', + b'\xf1\x873G0906259M \xf1\x890003', + b'\xf1\x873G0906259N \xf1\x890004', + b'\xf1\x873G0906259P \xf1\x890001', + b'\xf1\x875NA907115H \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158L \xf1\x893611', + b'\xf1\x870DL300014C \xf1\x893704', + b'\xf1\x870GC300011L \xf1\x891401', + b'\xf1\x870GC300013Q \xf1\x892402', + b'\xf1\x870GC300014M \xf1\x892802', + b'\xf1\x870GC300019G \xf1\x892804', + b'\xf1\x870GC300040P \xf1\x891401', + b'\xf1\x870GC300043 \xf1\x892303', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e1616001613121157161111572900', + b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e1616001613121177161113772900', + b'\xf1\x873Q0959655BK\xf1\x890712\xf1\x82\x0e1616001613121157161111572C00', + b'\xf1\x873Q0959655CK\xf1\x890711\xf1\x82\x0e1712141712141105121122052900', + b'\xf1\x873Q0959655CR\xf1\x890720\xf1\x82\x0e1616001613121105161111052900', + b'\xf1\x873Q0959655DA\xf1\x890720\xf1\x82\x0e1712141712141105121122052900', + b'\xf1\x873Q0959655DL\xf1\x890732\xf1\x82\x0e1812141812171105141123052J00', + b'\xf1\x875QF959655AP\xf1\x890755\xf1\x82\x1311110011111311111100110200--1611125F49', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144K \xf1\x895072\xf1\x82\x0571B41815A1', + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571B00817A1', + b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571B00818A1', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567B0020800', + b'\xf1\x875WA907145M \xf1\x891051\xf1\x82\x002MB4092M7N', + b'\xf1\x875WA907145M \xf1\x891051\xf1\x82\x002NB4202N7N', + b'\xf1\x875WA907145Q \xf1\x891063\xf1\x82\x002KB4092KOM', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572T \xf1\x890383', + b'\xf1\x875Q0907572J \xf1\x890654', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572R \xf1\x890771', + ], + }, + CAR.VOLKSWAGEN_ATLAS_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8703H906026AA\xf1\x899970', + b'\xf1\x8703H906026AG\xf1\x899971', + b'\xf1\x8703H906026AG\xf1\x899973', + b'\xf1\x8703H906026AJ\xf1\x890638', + b'\xf1\x8703H906026AJ\xf1\x891017', + b'\xf1\x8703H906026AT\xf1\x891922', + b'\xf1\x8703H906026BC\xf1\x892664', + b'\xf1\x8703H906026F \xf1\x896696', + b'\xf1\x8703H906026F \xf1\x899970', + b'\xf1\x8703H906026F \xf1\x899973', + b'\xf1\x8703H906026J \xf1\x896026', + b'\xf1\x8703H906026J \xf1\x899970', + b'\xf1\x8703H906026J \xf1\x899971', + b'\xf1\x8703H906026J \xf1\x899972', + b'\xf1\x8703H906026S \xf1\x896693', + b'\xf1\x8703H906026S \xf1\x899970', + b'\xf1\x8703H906026S \xf1\x899972', + b'\xf1\x873CN906259 \xf1\x890005', + b'\xf1\x873CN906259F \xf1\x890002', + b'\xf1\x873CN906259K \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158A \xf1\x893387', + b'\xf1\x8709G927158DR\xf1\x893536', + b'\xf1\x8709G927158DR\xf1\x893742', + b'\xf1\x8709G927158EN\xf1\x893691', + b'\xf1\x8709G927158F \xf1\x893489', + b'\xf1\x8709G927158FT\xf1\x893835', + b'\xf1\x8709G927158GK\xf1\x893941', + b'\xf1\x8709G927158GL\xf1\x893939', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655BC\xf1\x890503\xf1\x82\x0e1914151912001103111122031200', + b'\xf1\x873Q0959655BN\xf1\x890713\xf1\x82\x0e2214152212001105141122052900', + b'\xf1\x873Q0959655DB\xf1\x890720\xf1\x82\x0e1114151112001105111122052900', + b'\xf1\x873Q0959655DB\xf1\x890720\xf1\x82\x0e2214152212001105141122052900', + b'\xf1\x873Q0959655DM\xf1\x890732\xf1\x82\x0e1114151112001105111122052J00', + b'\xf1\x873Q0959655DM\xf1\x890732\xf1\x82\x0e1114151112001105161122052J00', + b'\xf1\x873Q0959655DM\xf1\x890732\xf1\x82\x0e1115151112001105121122052J00', + b'\xf1\x873Q0959655DM\xf1\x890732\xf1\x82\x0e1115151112001105171122052J00', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873QF909144B \xf1\x891582\xf1\x82\x0571B60924A1', + b'\xf1\x873QF909144B \xf1\x891582\xf1\x82\x0571B6G920A1', + b'\xf1\x873QF909144B \xf1\x891582\xf1\x82\x0571B6M921A1', + b'\xf1\x873QF909144B \xf1\x891582\xf1\x82\x0571B6N920A1', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820528B6080105', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820528B6090105', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572R \xf1\x890372', + b'\xf1\x872Q0907572T \xf1\x890383', + b'\xf1\x875Q0907572H \xf1\x890620', + b'\xf1\x875Q0907572J \xf1\x890654', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572S \xf1\x890780', + ], + }, + CAR.VOLKSWAGEN_CADDY_MK3: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906027T \xf1\x892363', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x872K5959655E \xf1\x890018\xf1\x82\x05000P037605', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x877N0907572C \xf1\x890211\xf1\x82\x0155', + ], + }, + CAR.VOLKSWAGEN_CRAFTER_MK2: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704L906056BP\xf1\x894729', + b'\xf1\x8704L906056EK\xf1\x896391', + b'\xf1\x8704L906056SH\xf1\x899973', + b'\xf1\x8705L906023BC\xf1\x892688', + b'\xf1\x8705L906023MH\xf1\x892588', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655AL\xf1\x890505\xf1\x82\x0e1411001413001203151311031100', + b'\xf1\x873Q0959655BG\xf1\x890703\xf1\x82\x0e16120016130012051G1313052900', + b'\xf1\x875QF959655AG\xf1\x890753\xf1\x82\x13151300151500111111000502----1111120749', + b'\xf1\x875QF959655AS\xf1\x890755\xf1\x82\x1315140015150011111100050200--1311120749', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x872N0909143D\x00\xf1\x897010\xf1\x82\x05183AZ306A2', + b'\xf1\x872N0909143E \xf1\x897021\xf1\x82\x05163AZ306A2', + b'\xf1\x872N0909143H \xf1\x897045\xf1\x82\x05263AZ309A2', + b'\xf1\x872N0909144K \xf1\x897045\xf1\x82\x05233AZ810A2', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572J \xf1\x890156', + b'\xf1\x872Q0907572M \xf1\x890233', + b'\xf1\x872Q0907572R \xf1\x890372', + ], + }, + CAR.VOLKSWAGEN_GOLF_MK7: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906016A \xf1\x897697', + b'\xf1\x8704E906016AD\xf1\x895758', + b'\xf1\x8704E906016CE\xf1\x899096', + b'\xf1\x8704E906016CH\xf1\x899226', + b'\xf1\x8704E906016DF\xf1\x896188', + b'\xf1\x8704E906016N \xf1\x899105', + b'\xf1\x8704E906023AG\xf1\x891726', + b'\xf1\x8704E906023BN\xf1\x894518', + b'\xf1\x8704E906024K \xf1\x896811', + b'\xf1\x8704E906024K \xf1\x899970', + b'\xf1\x8704E906027GR\xf1\x892394', + b'\xf1\x8704E906027HD\xf1\x892603', + b'\xf1\x8704E906027HD\xf1\x893742', + b'\xf1\x8704E906027MA\xf1\x894958', + b'\xf1\x8704L906021DT\xf1\x895520', + b'\xf1\x8704L906021DT\xf1\x898127', + b'\xf1\x8704L906021N \xf1\x895518', + b'\xf1\x8704L906021N \xf1\x898138', + b'\xf1\x8704L906026BN\xf1\x891197', + b'\xf1\x8704L906026BP\xf1\x897608', + b'\xf1\x8704L906026NF\xf1\x899528', + b'\xf1\x8704L906027AA\xf1\x899525', + b'\xf1\x8704L906056CL\xf1\x893823', + b'\xf1\x8704L906056CR\xf1\x895813', + b'\xf1\x8704L906056HE\xf1\x893758', + b'\xf1\x8704L906056HN\xf1\x896590', + b'\xf1\x8704L906056HT\xf1\x896591', + b'\xf1\x8704L997022N \xf1\x899459', + b'\xf1\x870EA906016A \xf1\x898343', + b'\xf1\x870EA906016E \xf1\x894219', + b'\xf1\x870EA906016F \xf1\x894238', + b'\xf1\x870EA906016F \xf1\x895002', + b'\xf1\x870EA906016Q \xf1\x895993', + b'\xf1\x870EA906016S \xf1\x897207', + b'\xf1\x875G0906259 \xf1\x890007', + b'\xf1\x875G0906259C \xf1\x890002', + b'\xf1\x875G0906259D \xf1\x890002', + b'\xf1\x875G0906259J \xf1\x890002', + b'\xf1\x875G0906259L \xf1\x890002', + b'\xf1\x875G0906259N \xf1\x890003', + b'\xf1\x875G0906259Q \xf1\x890002', + b'\xf1\x875G0906259Q \xf1\x892313', + b'\xf1\x875G0906259T \xf1\x890003', + b'\xf1\x878V0906259H \xf1\x890002', + b'\xf1\x878V0906259J \xf1\x890003', + b'\xf1\x878V0906259J \xf1\x890103', + b'\xf1\x878V0906259K \xf1\x890001', + b'\xf1\x878V0906259K \xf1\x890003', + b'\xf1\x878V0906259P \xf1\x890001', + b'\xf1\x878V0906259Q \xf1\x890002', + b'\xf1\x878V0906259R \xf1\x890002', + b'\xf1\x878V0906264F \xf1\x890003', + b'\xf1\x878V0906264L \xf1\x890002', + b'\xf1\x878V0906264M \xf1\x890001', + b'\xf1\x878V09C0BB01 \xf1\x890001', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927749AP\xf1\x892943', + b'\xf1\x8709S927158A \xf1\x893585', + b'\xf1\x870CW300040H \xf1\x890606', + b'\xf1\x870CW300041D \xf1\x891004', + b'\xf1\x870CW300041H \xf1\x891010', + b'\xf1\x870CW300042F \xf1\x891604', + b'\xf1\x870CW300043B \xf1\x891601', + b'\xf1\x870CW300043E \xf1\x891603', + b'\xf1\x870CW300044S \xf1\x894530', + b'\xf1\x870CW300044T \xf1\x895245', + b'\xf1\x870CW300045 \xf1\x894531', + b'\xf1\x870CW300046A \xf1\x895113', + b'\xf1\x870CW300047D \xf1\x895261', + b'\xf1\x870CW300047E \xf1\x895261', + b'\xf1\x870CW300048J \xf1\x890611', + b'\xf1\x870CW300049H \xf1\x890905', + b'\xf1\x870CW300050G \xf1\x891905', + b'\xf1\x870D9300012 \xf1\x894904', + b'\xf1\x870D9300012 \xf1\x894913', + b'\xf1\x870D9300012 \xf1\x894937', + b'\xf1\x870D9300012 \xf1\x895045', + b'\xf1\x870D9300012 \xf1\x895046', + b'\xf1\x870D9300014M \xf1\x895004', + b'\xf1\x870D9300014Q \xf1\x895006', + b'\xf1\x870D9300018 \xf1\x895201', + b'\xf1\x870D9300020D \xf1\x894309', + b'\xf1\x870D9300020J \xf1\x894902', + b'\xf1\x870D9300020Q \xf1\x895201', + b'\xf1\x870D9300020S \xf1\x895201', + b'\xf1\x870D9300040A \xf1\x893613', + b'\xf1\x870D9300040S \xf1\x894311', + b'\xf1\x870D9300041H \xf1\x895220', + b'\xf1\x870D9300041N \xf1\x894512', + b'\xf1\x870D9300041P \xf1\x894507', + b'\xf1\x870D9300043F \xf1\x895204', + b'\xf1\x870DD300045K \xf1\x891120', + b'\xf1\x870DD300046F \xf1\x891601', + b'\xf1\x870GC300012A \xf1\x891401', + b'\xf1\x870GC300012A \xf1\x891403', + b'\xf1\x870GC300012A \xf1\x891422', + b'\xf1\x870GC300012M \xf1\x892301', + b'\xf1\x870GC300014B \xf1\x892401', + b'\xf1\x870GC300014B \xf1\x892403', + b'\xf1\x870GC300014B \xf1\x892405', + b'\xf1\x870GC300014E \xf1\x892407', + b'\xf1\x870GC300020G \xf1\x892401', + b'\xf1\x870GC300020G \xf1\x892403', + b'\xf1\x870GC300020G \xf1\x892404', + b'\xf1\x870GC300020N \xf1\x892804', + b'\xf1\x870GC300043T \xf1\x899999', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655AA\xf1\x890386\xf1\x82\x111413001113120043114317121C111C9113', + b'\xf1\x875Q0959655AA\xf1\x890386\xf1\x82\x111413001113120053114317121C111C9113', + b'\xf1\x875Q0959655AA\xf1\x890388\xf1\x82\x111413001113120043114317121C111C9113', + b'\xf1\x875Q0959655AA\xf1\x890388\xf1\x82\x111413001113120043114417121411149113', + b'\xf1\x875Q0959655AA\xf1\x890388\xf1\x82\x111413001113120053114317121C111C9113', + b'\xf1\x875Q0959655AR\xf1\x890317\xf1\x82\x13141500111233003142114A2131219333313100', + b'\xf1\x875Q0959655BH\xf1\x890336\xf1\x82\x1314160011123300314211012230229333423100', + b'\xf1\x875Q0959655BH\xf1\x890336\xf1\x82\x1314160011123300314211012230229333463100', + b'\xf1\x875Q0959655BJ\xf1\x890336\xf1\x82\x13141300111233003142115A1932199333463100', + b'\xf1\x875Q0959655BJ\xf1\x890336\xf1\x82\x13141600111233003142115A2231229333423100', + b'\xf1\x875Q0959655BJ\xf1\x890339\xf1\x82\x13141600111233003142115A2232229333463100', + b'\xf1\x875Q0959655BS\xf1\x890403\xf1\x82\x1314160011123300314240012250229333463100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x13141600111233003142404A2251229333463100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x13141600111233003142404A2252229333463100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x13141600111233003142405A2251229333463100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x13141600111233003142405A2252229333463100', + b'\xf1\x875Q0959655C \xf1\x890361\xf1\x82\x111413001112120004110415121610169112', + b'\xf1\x875Q0959655CA\xf1\x890403\xf1\x82\x1314160011123300314240012250229333463100', + b'\xf1\x875Q0959655CA\xf1\x890403\xf1\x82\x13141600111233003142405A2251229333463100', + b'\xf1\x875Q0959655D \xf1\x890388\xf1\x82\x111413001113120006110417121A101A9113', + b'\xf1\x875Q0959655J \xf1\x890825\xf1\x82\x13271112111312--071104171825102591131211', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13271112111312--071104171825102591131211', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13271212111312--071104171838103891131211', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13272512111312--07110417182C102C91131211', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13341512112212--071104172328102891131211', + b'\xf1\x875Q0959655M \xf1\x890361\xf1\x82\x111413001112120041114115121611169112', + b'\xf1\x875Q0959655S \xf1\x890870\xf1\x82\x1315120011211200061104171717101791132111', + b'\xf1\x875Q0959655S \xf1\x890870\xf1\x82\x1315120011211200621143171717111791132111', + b'\xf1\x875Q0959655S \xf1\x890870\xf1\x82\x1324230011211200061104171724102491132111', + b'\xf1\x875Q0959655S \xf1\x890870\xf1\x82\x1324230011211200621143171724112491132111', + b'\xf1\x875Q0959655S \xf1\x890870\xf1\x82\x1324230011211200631143171724122491132111', + b'\xf1\x875Q0959655T \xf1\x890825\xf1\x82\x13271200111312--071104171837103791132111', + b'\xf1\x875Q0959655T \xf1\x890830\xf1\x82\x13271100111312--071104171826102691131211', + b'\xf1\x875QD959655 \xf1\x890388\xf1\x82\x111413001113120006110417121D101D9112', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144F \xf1\x895043\xf1\x82\x0561A01612A0', + b'\xf1\x873Q0909144H \xf1\x895061\xf1\x82\x0566A0J612A1', + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566A00514A1', + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566A01613A1', + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566A0J712A1', + b'\xf1\x873Q0909144K \xf1\x895072\xf1\x82\x0571A0J714A1', + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571A01A16A1', + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571A0JA15A1', + b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571A01A18A1', + b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571A02A16A1', + b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571A0JA16A1', + b'\xf1\x873QM909144 \xf1\x895072\xf1\x82\x0571A01714A1', + b'\xf1\x875Q0909143K \xf1\x892033\xf1\x820519A9040203', + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521A00441A1', + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521A00608A1', + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521A00641A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521A00442A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521A00642A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521A07B05A1', + b'\xf1\x875Q0909144L \xf1\x891021\xf1\x82\x0521A00502A0', + b'\xf1\x875Q0909144L \xf1\x891021\xf1\x82\x0521A00602A0', + b'\xf1\x875Q0909144L \xf1\x891021\xf1\x82\x0522A00402A0', + b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\x0511A00403A0', + b'\xf1\x875Q0909144R \xf1\x891061\xf1\x82\x0516A00604A1', + b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516A00404A1', + b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516A00504A1', + b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516A00604A1', + b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516A07A02A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521A00407A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521A00507A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521A07B04A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521A20B03A1', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567A2000400', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567A2000600', + b'\xf1\x875QD909144B \xf1\x891072\xf1\x82\x0521A00507A1', + b'\xf1\x875QM909144A \xf1\x891072\xf1\x82\x0521A20B03A1', + b'\xf1\x875QM909144B \xf1\x891081\xf1\x82\x0521A00442A1', + b'\xf1\x875QM909144B \xf1\x891081\xf1\x82\x0521A00642A1', + b'\xf1\x875QN909144A \xf1\x895081\xf1\x82\x0571A01A16A1', + b'\xf1\x875QN909144A \xf1\x895081\xf1\x82\x0571A01A17A1', + b'\xf1\x875QN909144A \xf1\x895081\xf1\x82\x0571A01A18A1', + b'\xf1\x875QN909144B \xf1\x895082\xf1\x82\x0571A01A18A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x875Q0907567G \xf1\x890390\xf1\x82\x0101', + b'\xf1\x875Q0907567J \xf1\x890396\xf1\x82\x0101', + b'\xf1\x875Q0907567L \xf1\x890098\xf1\x82\x0101', + b'\xf1\x875Q0907572A \xf1\x890141\xf1\x82\x0101', + b'\xf1\x875Q0907572B \xf1\x890200\xf1\x82\x0101', + b'\xf1\x875Q0907572C \xf1\x890210\xf1\x82\x0101', + b'\xf1\x875Q0907572D \xf1\x890304\xf1\x82\x0101', + b'\xf1\x875Q0907572E \xf1\x89X310\xf1\x82\x0101', + b'\xf1\x875Q0907572F \xf1\x890400\xf1\x82\x0101', + b'\xf1\x875Q0907572G \xf1\x890571', + b'\xf1\x875Q0907572H \xf1\x890620', + b'\xf1\x875Q0907572J \xf1\x890653', + b'\xf1\x875Q0907572J \xf1\x890654', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572R \xf1\x890771', + b'\xf1\x875Q0907572S \xf1\x890780', + ], + }, + CAR.VOLKSWAGEN_JETTA_MK6: { + (Ecu.srs, 0x715, None): [ + b'\xf1\x875C0959655M \xf1\x890726\xf1\x82\t00NB1108--------24', + b'\xf1\x875K0959655H \xf1\x890724\xf1\x82\t00131108--------02', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x877N0907572C \xf1\x890211\xf1\x82\x0151', + b'\xf1\x877N0907572C \xf1\x890211\xf1\x82\x0152', + ], + }, + CAR.VOLKSWAGEN_JETTA_MK7: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906024AF\xf1\x899970', + b'\xf1\x8704E906024AK\xf1\x899937', + b'\xf1\x8704E906024AS\xf1\x899912', + b'\xf1\x8704E906024AS\xf1\x899970', + b'\xf1\x8704E906024B \xf1\x895594', + b'\xf1\x8704E906024BC\xf1\x899971', + b'\xf1\x8704E906024BG\xf1\x891057', + b'\xf1\x8704E906024C \xf1\x899970', + b'\xf1\x8704E906024C \xf1\x899971', + b'\xf1\x8704E906024L \xf1\x895595', + b'\xf1\x8704E906024L \xf1\x899970', + b'\xf1\x8704E906027MS\xf1\x896223', + b'\xf1\x8705E906013BN\xf1\x893711', + b'\xf1\x8705E906013DB\xf1\x893361', + b'\xf1\x875G0906259T \xf1\x890003', + b'\xf1\x875G09C0BB02 \xf1\x890003', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158BQ\xf1\x893545', + b'\xf1\x8709H927158 \xf1\x890515', + b'\xf1\x8709S927158BS\xf1\x893642', + b'\xf1\x8709S927158BS\xf1\x893694', + b'\xf1\x8709S927158CK\xf1\x893770', + b'\xf1\x8709S927158JC\xf1\x894113', + b'\xf1\x8709S927158R \xf1\x893552', + b'\xf1\x8709S927158R \xf1\x893587', + b'\xf1\x870GC300020N \xf1\x892803', + b'\xf1\x870GC300020N \xf1\x892804', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655AG\xf1\x890336\xf1\x82\x1313171231313500314611011530159333463100', + b'\xf1\x875Q0959655AG\xf1\x890336\xf1\x82\x1314171231313500314611011630169333463100', + b'\xf1\x875Q0959655AG\xf1\x890338\xf1\x82\x1314171231313500314611011630169333463100', + b'\xf1\x875Q0959655BM\xf1\x890403\xf1\x82\x1314171231313500314642011650169333463100', + b'\xf1\x875Q0959655BM\xf1\x890403\xf1\x82\x1314171231313500314643011650169333463100', + b'\xf1\x875Q0959655BR\xf1\x890403\xf1\x82\x1311170031313300314240011150119333433100', + b'\xf1\x875Q0959655BR\xf1\x890403\xf1\x82\x1319170031313300314240011550159333463100', + b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1314171231313500314642021650169333613100', + b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1314171231313500314643021650169333613100', + b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1317171231313500314642023050309333613100', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144M \xf1\x895082\xf1\x82\x0571A10A11A1', + b'\xf1\x875QM907144D \xf1\x891063\xf1\x82\x000_A1080_OM', + b'\xf1\x875QM909144B \xf1\x891081\xf1\x82\x0521A10A01A1', + b'\xf1\x875QM909144B \xf1\x891081\xf1\x82\x0521B00404A1', + b'\xf1\x875QM909144C \xf1\x891082\xf1\x82\x0521A00642A1', + b'\xf1\x875QM909144C \xf1\x891082\xf1\x82\x0521A10A01A1', + b'\xf1\x875QN909144B \xf1\x895082\xf1\x82\x0571A10A11A1', + b'\xf1\x875QV907144F \xf1\x891122\xf1\x82\x0001A00701]V', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907567B \xf1\x890534', + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x875Q0907572N \xf1\x890681', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572R \xf1\x890771', + ], + }, + CAR.VOLKSWAGEN_PASSAT_MK8: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8703N906026E \xf1\x892114', + b'\xf1\x8704E906023AH\xf1\x893379', + b'\xf1\x8704E906023BF\xf1\x893842', + b'\xf1\x8704E906023BM\xf1\x894522', + b'\xf1\x8704L906026DP\xf1\x891538', + b'\xf1\x8704L906026ET\xf1\x891990', + b'\xf1\x8704L906026FP\xf1\x892012', + b'\xf1\x8704L906026GA\xf1\x892013', + b'\xf1\x8704L906026GK\xf1\x899971', + b'\xf1\x8704L906026KD\xf1\x894798', + b'\xf1\x8705L906022A \xf1\x890827', + b'\xf1\x873G0906259 \xf1\x890004', + b'\xf1\x873G0906259B \xf1\x890002', + b'\xf1\x873G0906264 \xf1\x890004', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300041E \xf1\x891006', + b'\xf1\x870CW300042H \xf1\x891601', + b'\xf1\x870CW300042H \xf1\x891607', + b'\xf1\x870CW300043H \xf1\x891601', + b'\xf1\x870CW300048R \xf1\x890610', + b'\xf1\x870D9300013A \xf1\x894905', + b'\xf1\x870D9300014L \xf1\x895002', + b'\xf1\x870D9300018C \xf1\x895297', + b'\xf1\x870D9300041A \xf1\x894801', + b'\xf1\x870D9300042H \xf1\x894901', + b'\xf1\x870DD300045T \xf1\x891601', + b'\xf1\x870DD300046B \xf1\x891601', + b'\xf1\x870DD300046H \xf1\x891601', + b'\xf1\x870DL300011H \xf1\x895201', + b'\xf1\x870GC300042H \xf1\x891404', + b'\xf1\x870GC300043 \xf1\x892301', + b'\xf1\x870GC300046P \xf1\x892805', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655AE\xf1\x890195\xf1\x82\r56140056130012416612124111', + b'\xf1\x873Q0959655AF\xf1\x890195\xf1\x82\r56140056130012026612120211', + b'\xf1\x873Q0959655AN\xf1\x890305\xf1\x82\r58160058140013036914110311', + b'\xf1\x873Q0959655AN\xf1\x890306\xf1\x82\r58160058140013036914110311', + b'\xf1\x873Q0959655BA\xf1\x890195\xf1\x82\r56140056130012416612124111', + b'\xf1\x873Q0959655BA\xf1\x890195\xf1\x82\r56140056130012516612125111', + b'\xf1\x873Q0959655BB\xf1\x890195\xf1\x82\r56140056130012026612120211', + b'\xf1\x873Q0959655BG\xf1\x890712\xf1\x82\x0e5915005914001305701311052900', + b'\xf1\x873Q0959655BJ\xf1\x890703\xf1\x82\x0e5915005914001305701311052900', + b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e5915005914001344701311442900', + b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e5915005914001354701311542900', + b'\xf1\x873Q0959655CN\xf1\x890720\xf1\x82\x0e5915005914001305701311052900', + b'\xf1\x875Q0959655S \xf1\x890870\xf1\x82\x1315120011111200631145171716121691132111', + b'\xf1\x875QF959655S \xf1\x890639\xf1\x82\x13131100131300111111000120----2211114A48', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566B00611A1', + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566B00711A1', + b'\xf1\x875Q0909143K \xf1\x892033\xf1\x820514B0060703', + b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820522B0060803', + b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820522B0080803', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820526B0060905', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820531B0062105', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521B00606A1', + b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516B00501A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521B00603A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521B00703A1', + b'\xf1\x875Q0910143B \xf1\x892201\xf1\x82\x0563B0000600', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567B0020600', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x873Q0907572A \xf1\x890126', + b'\xf1\x873Q0907572A \xf1\x890130', + b'\xf1\x873Q0907572B \xf1\x890192', + b'\xf1\x873Q0907572B \xf1\x890194', + b'\xf1\x873Q0907572C \xf1\x890195', + b'\xf1\x873Q0907572C \xf1\x890196', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572R \xf1\x890771', + b'\xf1\x875Q0907572S \xf1\x890780', + ], + }, + CAR.VOLKSWAGEN_PASSAT_NMS: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8706K906016C \xf1\x899609', + b'\xf1\x8706K906016E \xf1\x899830', + b'\xf1\x8706K906016G \xf1\x891124', + b'\xf1\x8706K906071BJ\xf1\x894891', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158AB\xf1\x893318', + b'\xf1\x8709G927158BD\xf1\x893121', + b'\xf1\x8709G927158DK\xf1\x893594', + b'\xf1\x8709G927158FQ\xf1\x893745', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x87561959655 \xf1\x890210\xf1\x82\x1212121111113000102011--121012--101312', + b'\xf1\x87561959655C \xf1\x890508\xf1\x82\x1215141111121100314919--153015--304831', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x87561907567A \xf1\x890132', + b'\xf1\x877N0907572C \xf1\x890211\xf1\x82\x0152', + ], + }, + CAR.VOLKSWAGEN_POLO_MK6: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704C906025H \xf1\x895177', + b'\xf1\x8705C906032J \xf1\x891702', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300042D \xf1\x891612', + b'\xf1\x870CW300050D \xf1\x891908', + b'\xf1\x870CW300051G \xf1\x891909', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x872Q0959655AG\xf1\x890248\xf1\x82\x1218130411110411--04040404231811152H14', + b'\xf1\x872Q0959655AJ\xf1\x890250\xf1\x82\x1248130411110416--04040404784811152H14', + b'\xf1\x872Q0959655AS\xf1\x890411\xf1\x82\x1384830511110516041405820599841215391471', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x872Q1909144M \xf1\x896041', + b'\xf1\x872Q2909144AB\xf1\x896050', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572R \xf1\x890372', + ], + }, + CAR.VOLKSWAGEN_SHARAN_MK2: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704L906016HE\xf1\x894635', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x877N0959655D \xf1\x890016\xf1\x82\x0801100705----10--', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x877N0907572C \xf1\x890211\xf1\x82\x0153', + ], + }, + CAR.VOLKSWAGEN_TAOS_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906025CK\xf1\x892228', + b'\xf1\x8704E906027NJ\xf1\x891445', + b'\xf1\x8704E906027NP\xf1\x891286', + b'\xf1\x8705E906013BD\xf1\x892496', + b'\xf1\x8705E906013DF\xf1\x893365', + b'\xf1\x8705E906013E \xf1\x891624', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158EM\xf1\x893812', + b'\xf1\x8709S927158BL\xf1\x893791', + b'\xf1\x8709S927158CR\xf1\x893924', + b'\xf1\x8709S927158DN\xf1\x893946', + b'\xf1\x8709S927158FF\xf1\x893876', + b'\xf1\x8709S927158HM\xf1\x894112', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1311111111333500314646021450149333613100', + b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1312111111333500314646021550159333613100', + b'\xf1\x875Q0959655CE\xf1\x890421\xf1\x82\x1311110011333300314240021350139333613100', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875QM907144D \xf1\x891063\xf1\x82\x001O06081OOM', + b'\xf1\x875QM909144C \xf1\x891082\xf1\x82\x0521060405A1', + b'\xf1\x875QM909144C \xf1\x891082\xf1\x82\x0521060605A1', + b'\xf1\x875QV907144F \xf1\x891122\xf1\x82\x0001060801]V', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907567B \xf1\x890534', + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.VOLKSWAGEN_TCROSS_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704C906025AK\xf1\x897053', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300050E \xf1\x891903', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x872Q0959655AJ\xf1\x890250\xf1\x82\x1212130411110411--04041104141311152H14', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x872Q1909144M \xf1\x896041', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.VOLKSWAGEN_TIGUAN_MK2: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8703N906026D \xf1\x893680', + b'\xf1\x8704E906024AP\xf1\x891461', + b'\xf1\x8704E906027NB\xf1\x899504', + b'\xf1\x8704L906026EJ\xf1\x893661', + b'\xf1\x8704L906026EJ\xf1\x893916', + b'\xf1\x8704L906026KR\xf1\x893919', + b'\xf1\x8704L906027G \xf1\x899893', + b'\xf1\x8705E906018BS\xf1\x890914', + b'\xf1\x8705L906022GL\xf1\x892112', + b'\xf1\x875N0906259 \xf1\x890002', + b'\xf1\x875NA906259H \xf1\x890002', + b'\xf1\x875NA907115E \xf1\x890003', + b'\xf1\x875NA907115E \xf1\x890005', + b'\xf1\x875NA907115J \xf1\x890002', + b'\xf1\x875NA907115K \xf1\x890004', + b'\xf1\x8783A907115 \xf1\x890007', + b'\xf1\x8783A907115B \xf1\x890005', + b'\xf1\x8783A907115F \xf1\x890002', + b'\xf1\x8783A907115G \xf1\x890001', + b'\xf1\x8783A907115K \xf1\x890001', + b'\xf1\x8783A907115K \xf1\x890002', + b'\xf1\x8783A907115Q \xf1\x890001', + b'\xf1\x8783A907115Q \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158DS\xf1\x893699', + b'\xf1\x8709G927158DT\xf1\x893698', + b'\xf1\x8709G927158FM\xf1\x893757', + b'\xf1\x8709G927158GC\xf1\x893821', + b'\xf1\x8709G927158GD\xf1\x893820', + b'\xf1\x8709G927158GM\xf1\x893936', + b'\xf1\x8709G927158GN\xf1\x893938', + b'\xf1\x8709G927158HB\xf1\x894069', + b'\xf1\x8709G927158HC\xf1\x894070', + b'\xf1\x870D9300043 \xf1\x895202', + b'\xf1\x870DD300046K \xf1\x892302', + b'\xf1\x870DL300011N \xf1\x892001', + b'\xf1\x870DL300011N \xf1\x892012', + b'\xf1\x870DL300011N \xf1\x892014', + b'\xf1\x870DL300012M \xf1\x892107', + b'\xf1\x870DL300012N \xf1\x892110', + b'\xf1\x870DL300012P \xf1\x892103', + b'\xf1\x870DL300013A \xf1\x893005', + b'\xf1\x870DL300013G \xf1\x892119', + b'\xf1\x870DL300013G \xf1\x892120', + b'\xf1\x870DL300014C \xf1\x893703', + b'\xf1\x870GC300013P \xf1\x892401', + b'\xf1\x870GC300018R \xf1\x892802', + b'\xf1\x870GC300046Q \xf1\x892802', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655AG\xf1\x890336\xf1\x82\x1316143231313500314617011730179333423100', + b'\xf1\x875Q0959655AG\xf1\x890338\xf1\x82\x1316143231313500314617011730179333423100', + b'\xf1\x875Q0959655AR\xf1\x890317\xf1\x82\x1331310031333334313132573732379333313100', + b'\xf1\x875Q0959655BJ\xf1\x890336\xf1\x82\x1311140031333300314232583632369333423100', + b'\xf1\x875Q0959655BJ\xf1\x890336\xf1\x82\x1312110031333300314232583732379333423100', + b'\xf1\x875Q0959655BJ\xf1\x890339\xf1\x82\x1331310031333334313132013730379333423100', + b'\xf1\x875Q0959655BK\xf1\x890339\xf1\x82\x1331310031333334313132573732379333423100', + b'\xf1\x875Q0959655BM\xf1\x890403\xf1\x82\x1316143231313500314641011750179333423100', + b'\xf1\x875Q0959655BS\xf1\x890403\xf1\x82\x1312110031333300314240013750379333423100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x1312110031333300314240583752379333423100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x1331310031333334313140013750379333423100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x1331310031333334313140573752379333423100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x1331310031333336313140013950399333423100', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x1331310031333336313140573952399333423100', + b'\xf1\x875Q0959655CB\xf1\x890421\xf1\x82\x1316143231313500314647021750179333613100', + b'\xf1\x875Q0959655CD\xf1\x890421\xf1\x82\x13123112313333003145406F6154619333613100', + b'\xf1\x875Q0959655CG\xf1\x890421\xf1\x82\x1331310031333300314240024050409333613100', + b'\xf1\x875Q0959655CH\xf1\x890421\xf1\x82\x13121100313333003142405G3754379333613100', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820529A6060603', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820527A6050705', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820527A6070705', + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521A60803A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521A60604A1', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567A6000600', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567A6017A00', + b'\xf1\x875QF909144 \xf1\x895572\xf1\x82\x0571A60833A1', + b'\xf1\x875QF909144A \xf1\x895581\xf1\x82\x0571A60834A1', + b'\xf1\x875QF909144B \xf1\x895582\xf1\x82\x0571A60634A1', + b'\xf1\x875QF909144B \xf1\x895582\xf1\x82\x0571A62A32A1', + b'\xf1\x875QM907144D \xf1\x891063\xf1\x82\x002RA60A2ROM', + b'\xf1\x875QM907144D \xf1\x891063\xf1\x82\x002SA6092SOM', + b'\xf1\x875QM909144B \xf1\x891081\xf1\x82\x0521A60604A1', + b'\xf1\x875QM909144B \xf1\x891081\xf1\x82\x0521A60804A1', + b'\xf1\x875QM909144C \xf1\x891082\xf1\x82\x0521A60604A1', + b'\xf1\x875QM909144C \xf1\x891082\xf1\x82\x0521A60804A1', + b'\xf1\x875QV907144F \xf1\x891122\xf1\x82\x0001A6CA01]V', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907567B \xf1\x890534', + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572AB\xf1\x890397', + b'\xf1\x872Q0907572J \xf1\x890156', + b'\xf1\x872Q0907572M \xf1\x890233', + b'\xf1\x872Q0907572Q \xf1\x890342', + b'\xf1\x872Q0907572R \xf1\x890372', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.VOLKSWAGEN_TOURAN_MK2: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906025BE\xf1\x890720', + b'\xf1\x8704E906027HQ\xf1\x893746', + b'\xf1\x8704L906026HM\xf1\x893017', + b'\xf1\x8705E906018CQ\xf1\x890808', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300020A \xf1\x891936', + b'\xf1\x870CW300041E \xf1\x891005', + b'\xf1\x870CW300041Q \xf1\x891606', + b'\xf1\x870CW300051M \xf1\x891926', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655AS\xf1\x890318\xf1\x82\x1336350021353335314132014730479333313100', + b'\xf1\x875Q0959655AS\xf1\x890318\xf1\x82\x13363500213533353141324C4732479333313100', + b'\xf1\x875Q0959655CH\xf1\x890421\xf1\x82\x1336350021353336314740025250529333613100', + b'\xf1\x875QD959655AJ\xf1\x890421\xf1\x82\x1336350021313300314240023330339333663100', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820531B0062105', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567A8090400', + b'\xf1\x875QD909144F \xf1\x891082\xf1\x82\x0521A00642A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x873Q0907572C \xf1\x890195', + b'\xf1\x875Q0907572R \xf1\x890771', + ], + }, + CAR.VOLKSWAGEN_TRANSPORTER_T61: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704L906056AG\xf1\x899970', + b'\xf1\x8704L906056AL\xf1\x899970', + b'\xf1\x8704L906057AP\xf1\x891186', + b'\xf1\x8704L906057N \xf1\x890413', + b'\xf1\x8705L906023E \xf1\x891352', + b'\xf1\x8705L906023MR\xf1\x892582', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870BT300012E \xf1\x893105', + b'\xf1\x870BT300012G \xf1\x893102', + b'\xf1\x870BT300046R \xf1\x893102', + b'\xf1\x870DV300012B \xf1\x893701', + b'\xf1\x870DV300012B \xf1\x893702', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x872Q0959655AE\xf1\x890506\xf1\x82\x1316170411110411--04041704161611152S1411', + b'\xf1\x872Q0959655AE\xf1\x890506\xf1\x82\x1316170411110411--04041704171711152S1411', + b'\xf1\x872Q0959655AF\xf1\x890506\xf1\x82\x1316171111110411--04041711121211152S1413', + b'\xf1\x872Q0959655AQ\xf1\x890511\xf1\x82\x1316170411110411--0404170426261215391421', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x877LA909144F \xf1\x897150\xf1\x82\x0532380518A2', + b'\xf1\x877LA909144F \xf1\x897150\xf1\x82\x05323A5519A2', + b'\xf1\x877LA909144G \xf1\x897160\xf1\x82\x05333A5519A2', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572R \xf1\x890372', + ], + }, + CAR.VOLKSWAGEN_TROC_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8705E906018AT\xf1\x899640', + b'\xf1\x8705E906018CK\xf1\x890863', + b'\xf1\x8705E906018P \xf1\x896020', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300041S \xf1\x891615', + b'\xf1\x870CW300050J \xf1\x891911', + b'\xf1\x870CW300051M \xf1\x891925', + b'\xf1\x870CW300051M \xf1\x891928', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655BH\xf1\x890712\xf1\x82\x0e1111001111001105111111052900', + b'\xf1\x875Q0959655BT\xf1\x890403\xf1\x82\x1311110012333300314240681152119333463100', + b'\xf1\x875Q0959655CF\xf1\x890421\xf1\x82\x1311110012333300314240021150119333613100', + b'\xf1\x875Q0959655CG\xf1\x890421\xf1\x82\x13111100123333003142404M1152119333613100', + b'\xf1\x875Q0959655CG\xf1\x890421\xf1\x82\x13111100123333003142404M1154119333613100', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521060403A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521060405A1', + b'\xf1\x875WA907144M \xf1\x891051\xf1\x82\x001T06081T7N', + b'\xf1\x875WA907144Q \xf1\x891063\xf1\x82\x001O06081OOM', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572M \xf1\x890233', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.AUDI_A3_MK3: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906023AN\xf1\x893695', + b'\xf1\x8704E906023AR\xf1\x893440', + b'\xf1\x8704E906023BL\xf1\x895190', + b'\xf1\x8704E906027CJ\xf1\x897798', + b'\xf1\x8704L997022N \xf1\x899459', + b'\xf1\x875G0906259A \xf1\x890004', + b'\xf1\x875G0906259D \xf1\x890002', + b'\xf1\x875G0906259L \xf1\x890002', + b'\xf1\x875G0906259Q \xf1\x890002', + b'\xf1\x875G0906259Q \xf1\x890007', + b'\xf1\x878V0906259E \xf1\x890001', + b'\xf1\x878V0906259F \xf1\x890002', + b'\xf1\x878V0906259H \xf1\x890002', + b'\xf1\x878V0906259J \xf1\x890002', + b'\xf1\x878V0906259K \xf1\x890001', + b'\xf1\x878V0906264B \xf1\x890003', + b'\xf1\x878V0907115B \xf1\x890007', + b'\xf1\x878V0907404A \xf1\x890005', + b'\xf1\x878V0907404G \xf1\x890004', + b'\xf1\x878V0907404G \xf1\x890005', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300044T \xf1\x895245', + b'\xf1\x870CW300048 \xf1\x895201', + b'\xf1\x870D9300012 \xf1\x894912', + b'\xf1\x870D9300012 \xf1\x894931', + b'\xf1\x870D9300012K \xf1\x894513', + b'\xf1\x870D9300012L \xf1\x894521', + b'\xf1\x870D9300013B \xf1\x894902', + b'\xf1\x870D9300013B \xf1\x894931', + b'\xf1\x870D9300041N \xf1\x894512', + b'\xf1\x870D9300043T \xf1\x899699', + b'\xf1\x870DD300046 \xf1\x891604', + b'\xf1\x870DD300046A \xf1\x891602', + b'\xf1\x870DD300046F \xf1\x891602', + b'\xf1\x870DD300046G \xf1\x891601', + b'\xf1\x870DL300012E \xf1\x892012', + b'\xf1\x870DL300012H \xf1\x892112', + b'\xf1\x870GC300011 \xf1\x890403', + b'\xf1\x870GC300013M \xf1\x892402', + b'\xf1\x870GC300042J \xf1\x891402', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655AB\xf1\x890388\xf1\x82\x111111001111111206110412111321139114', + b'\xf1\x875Q0959655AM\xf1\x890315\xf1\x82\x1311111111111111311411011231129321212100', + b'\xf1\x875Q0959655AM\xf1\x890318\xf1\x82\x1311111111111112311411011531159321212100', + b'\xf1\x875Q0959655AR\xf1\x890315\xf1\x82\x1311110011131115311211012331239321212100', + b'\xf1\x875Q0959655BJ\xf1\x890339\xf1\x82\x1311110011131100311111011731179321342100', + b'\xf1\x875Q0959655J \xf1\x890825\xf1\x82\x13111112111111--171115141112221291163221', + b'\xf1\x875Q0959655J \xf1\x890825\xf1\x82\x13111112111111--241115141112221291163221', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13111112111111--241115141112221291163221', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13121111111111--341117141212231291163221', + b'\xf1\x875Q0959655J \xf1\x890830\xf1\x82\x13121111111211--261117141112231291163221', + b'\xf1\x875Q0959655N \xf1\x890361\xf1\x82\x111212001112110004110411111421149114', + b'\xf1\x875Q0959655N \xf1\x890361\xf1\x82\x111212001112111104110411111521159114', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144F \xf1\x895043\xf1\x82\x0561G01A13A0', + b'\xf1\x873Q0909144H \xf1\x895061\xf1\x82\x0566G0HA14A1', + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566G0HA14A1', + b'\xf1\x873Q0909144K \xf1\x895072\xf1\x82\x0571G01A16A1', + b'\xf1\x873Q0909144K \xf1\x895072\xf1\x82\x0571G0HA16A1', + b'\xf1\x873Q0909144K \xf1\x895072\xf1\x82\x0571G0JA13A1', + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571G0JA14A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521G0G809A1', + b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\x0503G00303A0', + b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\x0503G00803A0', + b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\x0503G0G803A0', + b'\xf1\x875Q0909144R \xf1\x891061\xf1\x82\x0516G00804A1', + b'\xf1\x875Q0909144S \xf1\x891063\xf1\x82\x0516G00804A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521G00807A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x875Q0907567M \xf1\x890398\xf1\x82\x0101', + b'\xf1\x875Q0907567N \xf1\x890400\xf1\x82\x0101', + b'\xf1\x875Q0907572D \xf1\x890304\xf1\x82\x0101', + b'\xf1\x875Q0907572F \xf1\x890400\xf1\x82\x0101', + b'\xf1\x875Q0907572G \xf1\x890571', + b'\xf1\x875Q0907572H \xf1\x890620', + b'\xf1\x875Q0907572P \xf1\x890682', + ], + }, + CAR.AUDI_Q2_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906027JT\xf1\x894145', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300041F \xf1\x891006', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655BD\xf1\x890336\xf1\x82\x1311111111111100311211011231129321312111', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144K \xf1\x895072\xf1\x82\x0571F60511A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572M \xf1\x890233', + ], + }, + CAR.AUDI_Q3_MK2: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8705E906018N \xf1\x899970', + b'\xf1\x8705L906022M \xf1\x890901', + b'\xf1\x8783A906259 \xf1\x890001', + b'\xf1\x8783A906259 \xf1\x890005', + b'\xf1\x8783A906259C \xf1\x890002', + b'\xf1\x8783A906259D \xf1\x890001', + b'\xf1\x8783A906259F \xf1\x890001', + b'\xf1\x8783A906259H \xf1\x890002', + b'\xf1\x8783A907115P \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x8709G927158CN\xf1\x893608', + b'\xf1\x8709G927158FL\xf1\x893758', + b'\xf1\x8709G927158GG\xf1\x893825', + b'\xf1\x8709G927158GP\xf1\x893937', + b'\xf1\x8709G927158HC\xf1\x894070', + b'\xf1\x8709G927158HG\xf1\x894168', + b'\xf1\x870GC300045D \xf1\x892802', + b'\xf1\x870GC300046F \xf1\x892701', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655BF\xf1\x890403\xf1\x82\x1321211111211200311121232152219321422111', + b'\xf1\x875Q0959655BQ\xf1\x890421\xf1\x82\x132121111121120031112124218A219321532111', + b'\xf1\x875Q0959655BQ\xf1\x890421\xf1\x82\x132121111121120031112124218C219321532111', + b'\xf1\x875Q0959655CC\xf1\x890421\xf1\x82\x131111111111120031111224118A119321532111', + b'\xf1\x875Q0959655CC\xf1\x890421\xf1\x82\x131111111111120031111237116A119321532111', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567G6000300', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567G6000800', + b'\xf1\x875QF909144B \xf1\x895582\xf1\x82\x0571G60533A1', + b'\xf1\x875QF909144B \xf1\x895582\xf1\x82\x0571G60733A1', + b'\xf1\x875QS907145E \xf1\x891122\xf1\x82\x0001G67801]V', + b'\xf1\x875TA907145D \xf1\x891051\xf1\x82\x001PG60A1P7N', + b'\xf1\x875TA907145F \xf1\x891063\xf1\x82\x002VG60A2VOM', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907567C \xf1\x890541', + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572R \xf1\x890372', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.SEAT_ATECA_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906027KA\xf1\x893749', + b'\xf1\x8704L906021EL\xf1\x897542', + b'\xf1\x8704L906026BP\xf1\x891198', + b'\xf1\x8704L906026BP\xf1\x897608', + b'\xf1\x8704L906056CR\xf1\x892181', + b'\xf1\x8704L906056CR\xf1\x892797', + b'\xf1\x8705E906018AS\xf1\x899596', + b'\xf1\x8781A906259B \xf1\x890003', + b'\xf1\x878V0906264H \xf1\x890005', + b'\xf1\x878V0907115E \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300041D \xf1\x891004', + b'\xf1\x870CW300041G \xf1\x891003', + b'\xf1\x870CW300050J \xf1\x891908', + b'\xf1\x870D9300014S \xf1\x895202', + b'\xf1\x870D9300042M \xf1\x895016', + b'\xf1\x870GC300014P \xf1\x892801', + b'\xf1\x870GC300043A \xf1\x892304', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655AC\xf1\x890189\xf1\x82\r11110011110011021511110200', + b'\xf1\x873Q0959655AS\xf1\x890200\xf1\x82\r11110011110011021511110200', + b'\xf1\x873Q0959655AS\xf1\x890200\xf1\x82\r12110012120012021612110200', + b'\xf1\x873Q0959655BH\xf1\x890703\xf1\x82\x0e1212001211001305121211052900', + b'\xf1\x873Q0959655BH\xf1\x890703\xf1\x82\x0e1312001313001305171311052900', + b'\xf1\x873Q0959655BH\xf1\x890712\xf1\x82\x0e1312001313001305171311052900', + b'\xf1\x873Q0959655CM\xf1\x890720\xf1\x82\x0e1312001313001305171311052900', + b'\xf1\x875QF959655AT\xf1\x890755\xf1\x82\x1311110011110011111100110200--1113121149', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571N60511A1', + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521N01842A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521N01342A1', + b'\xf1\x875Q0909144P \xf1\x891043\xf1\x82\x0511N01805A0', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521N01309A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521N05808A1', + b'\xf1\x875WA907145M \xf1\x891051\xf1\x82\x0013N619137N', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572M \xf1\x890233', + b'\xf1\x875Q0907572B \xf1\x890200\xf1\x82\x0101', + b'\xf1\x875Q0907572H \xf1\x890620', + b'\xf1\x875Q0907572K \xf1\x890402\xf1\x82\x0101', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572R \xf1\x890771', + ], + }, + CAR.SKODA_FABIA_MK4: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8705C906032L \xf1\x891701', + b'\xf1\x8705E906018CF\xf1\x891905', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300051G \xf1\x891906', + b'\xf1\x870CW300051M \xf1\x891936', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875QF959655AF\xf1\x890753\xf1\x82\x13111100111100111111001102----1111120749', + b'\xf1\x875QF959655AT\xf1\x890755\xf1\x82\x1311110011110011111100110200--1111120749', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x872Q1909144S \xf1\x896042', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.SKODA_KAMIQ_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704C906025AK\xf1\x897053', + b'\xf1\x8705C906032M \xf1\x891333', + b'\xf1\x8705C906032M \xf1\x892365', + b'\xf1\x8705E906013CK\xf1\x892540', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300020 \xf1\x891906', + b'\xf1\x870CW300020 \xf1\x891907', + b'\xf1\x870CW300020T \xf1\x892204', + b'\xf1\x870CW300050 \xf1\x891709', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x872Q0959655AJ\xf1\x890250\xf1\x82\x1211110411110411--04040404131111112H14', + b'\xf1\x872Q0959655AM\xf1\x890351\xf1\x82\x12111104111104112104040404111111112H14', + b'\xf1\x872Q0959655AM\xf1\x890351\xf1\x82\x122221042111042121040404042E2711152H14', + b'\xf1\x872Q0959655AS\xf1\x890411\xf1\x82\x1311150411110411210404040417151215391413', + b'\xf1\x872Q0959655BJ\xf1\x890412\xf1\x82\x132223042111042121040404042B251215391423', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x872Q1909144AB\xf1\x896050', + b'\xf1\x872Q1909144M \xf1\x896041', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572R \xf1\x890372', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.SKODA_KAROQ_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8705E906013CL\xf1\x892541', + b'\xf1\x8705E906013H \xf1\x892407', + b'\xf1\x8705E906018P \xf1\x895472', + b'\xf1\x8705E906018P \xf1\x896020', + b'\xf1\x8705L906022BS\xf1\x890913', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300020T \xf1\x892202', + b'\xf1\x870CW300041S \xf1\x891615', + b'\xf1\x870GC300014L \xf1\x892802', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655BH\xf1\x890703\xf1\x82\x0e1213001211001101131112012100', + b'\xf1\x873Q0959655BH\xf1\x890712\xf1\x82\x0e1213001211001101131122012100', + b'\xf1\x873Q0959655DE\xf1\x890731\xf1\x82\x0e1213001211001101131121012J00', + b'\xf1\x875QF959655AT\xf1\x890755\xf1\x82\x1312110012120011111100010200--2521210749', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0910143B \xf1\x892201\xf1\x82\x0563T6090500', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567T6100500', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567T6100600', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567T6100700', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572AB\xf1\x890397', + b'\xf1\x872Q0907572M \xf1\x890233', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.SKODA_KODIAQ_MK1: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906027DD\xf1\x893123', + b'\xf1\x8704E906027LD\xf1\x893433', + b'\xf1\x8704E906027NB\xf1\x896517', + b'\xf1\x8704E906027NB\xf1\x899504', + b'\xf1\x8704L906026DE\xf1\x895418', + b'\xf1\x8704L906026EJ\xf1\x893661', + b'\xf1\x8704L906026HT\xf1\x893617', + b'\xf1\x8705E906018DJ\xf1\x890915', + b'\xf1\x8705E906018DJ\xf1\x891903', + b'\xf1\x8705L906022GM\xf1\x893411', + b'\xf1\x875NA906259E \xf1\x890003', + b'\xf1\x875NA907115D \xf1\x890003', + b'\xf1\x875NA907115E \xf1\x890003', + b'\xf1\x875NA907115E \xf1\x890005', + b'\xf1\x8783A907115E \xf1\x890001', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870D9300014S \xf1\x895201', + b'\xf1\x870D9300043 \xf1\x895202', + b'\xf1\x870DL300011N \xf1\x892014', + b'\xf1\x870DL300012G \xf1\x892006', + b'\xf1\x870DL300012M \xf1\x892107', + b'\xf1\x870DL300012N \xf1\x892110', + b'\xf1\x870DL300013G \xf1\x892119', + b'\xf1\x870GC300014N \xf1\x892801', + b'\xf1\x870GC300018S \xf1\x892803', + b'\xf1\x870GC300019H \xf1\x892806', + b'\xf1\x870GC300046Q \xf1\x892802', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655AN\xf1\x890306\xf1\x82\r11110011110011031111310311', + b'\xf1\x873Q0959655AP\xf1\x890306\xf1\x82\r11110011110011421111314211', + b'\xf1\x873Q0959655BH\xf1\x890703\xf1\x82\x0e1213001211001205212111052100', + b'\xf1\x873Q0959655BJ\xf1\x890703\xf1\x82\x0e1213001211001205212111052100', + b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e1213001211001244212111442100', + b'\xf1\x873Q0959655CN\xf1\x890720\xf1\x82\x0e1213001211001205212112052100', + b'\xf1\x873Q0959655CQ\xf1\x890720\xf1\x82\x0e1213111211001205212112052111', + b'\xf1\x873Q0959655DJ\xf1\x890731\xf1\x82\x0e1513001511001205232113052J00', + b'\xf1\x875QF959655AT\xf1\x890755\xf1\x82\x1311110011110011111100010200--1121240749', + b'\xf1\x875QF959655AT\xf1\x890755\xf1\x82\x1311110011110011111100010200--1121246149', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820527T6050405', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820527T6060405', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820527T6070405', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567T600G500', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567T600G600', + b'\xf1\x875TA907145F \xf1\x891063\xf1\x82\x0025T6BA25OM', + b'\xf1\x875TA907145F \xf1\x891063\xf1\x82\x002LT61A2LOM', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + b'\xf1\x872Q0907572AB\xf1\x890397', + b'\xf1\x872Q0907572M \xf1\x890233', + b'\xf1\x872Q0907572Q \xf1\x890342', + b'\xf1\x872Q0907572R \xf1\x890372', + b'\xf1\x872Q0907572T \xf1\x890383', + ], + }, + CAR.SKODA_OCTAVIA_MK3: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704C906025L \xf1\x896198', + b'\xf1\x8704C906026AB\xf1\x892993', + b'\xf1\x8704E906016ER\xf1\x895823', + b'\xf1\x8704E906027HD\xf1\x893742', + b'\xf1\x8704E906027MH\xf1\x894786', + b'\xf1\x8704L906021DT\xf1\x898127', + b'\xf1\x8704L906021ER\xf1\x898361', + b'\xf1\x8704L906026BP\xf1\x897608', + b'\xf1\x8704L906026BS\xf1\x891541', + b'\xf1\x8704L906026BT\xf1\x897612', + b'\xf1\x875G0906259C \xf1\x890002', + b'\xf1\x875G0906259N \xf1\x890003', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300041L \xf1\x891601', + b'\xf1\x870CW300041N \xf1\x891605', + b'\xf1\x870CW300043B \xf1\x891601', + b'\xf1\x870CW300043P \xf1\x891605', + b'\xf1\x870CW300049M \xf1\x890901', + b'\xf1\x870D9300012H \xf1\x894518', + b'\xf1\x870D9300014T \xf1\x895221', + b'\xf1\x870D9300041C \xf1\x894936', + b'\xf1\x870D9300041H \xf1\x895220', + b'\xf1\x870D9300041J \xf1\x894902', + b'\xf1\x870D9300041P \xf1\x894507', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655AC\xf1\x890200\xf1\x82\r11120011100010022212110200', + b'\xf1\x873Q0959655AK\xf1\x890306\xf1\x82\r31210031210021033733310331', + b'\xf1\x873Q0959655AP\xf1\x890305\xf1\x82\r11110011110011213331312131', + b'\xf1\x873Q0959655AQ\xf1\x890200\xf1\x82\r11120011100010312212113100', + b'\xf1\x873Q0959655AS\xf1\x890200\xf1\x82\r11120011100010022212110200', + b'\xf1\x873Q0959655BH\xf1\x890703\xf1\x82\x0e3221003221002105755331052100', + b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e3221003221002132755331322100', + b'\xf1\x873Q0959655CM\xf1\x890720\xf1\x82\x0e3221003221002105755331052100', + b'\xf1\x873Q0959655CN\xf1\x890720\xf1\x82\x0e3221003221002105755331052100', + b'\xf1\x875QD959655 \xf1\x890388\xf1\x82\x111101000011110006110411111111119111', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x873Q0909144J \xf1\x895063\xf1\x82\x0566A01513A1', + b'\xf1\x873Q0909144L \xf1\x895081\xf1\x82\x0571T01512A1', + b'\xf1\x875Q0909144AA\xf1\x891081\xf1\x82\x0521T00403A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521T00403A1', + b'\xf1\x875Q0909144AB\xf1\x891082\xf1\x82\x0521T00603A1', + b'\xf1\x875Q0909144R \xf1\x891061\xf1\x82\x0516A00604A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521T00401A1', + b'\xf1\x875Q0909144T \xf1\x891072\xf1\x82\x0521T00601A1', + b'\xf1\x875QD909144E \xf1\x891081\xf1\x82\x0521T00503A1', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x875Q0907567P \xf1\x890100\xf1\x82\x0101', + b'\xf1\x875Q0907572D \xf1\x890304\xf1\x82\x0101', + b'\xf1\x875Q0907572F \xf1\x890400\xf1\x82\x0101', + b'\xf1\x875Q0907572H \xf1\x890620', + b'\xf1\x875Q0907572J \xf1\x890654', + b'\xf1\x875Q0907572K \xf1\x890402\xf1\x82\x0101', + b'\xf1\x875Q0907572P \xf1\x890682', + b'\xf1\x875Q0907572R \xf1\x890771', + ], + }, + CAR.SKODA_SUPERB_MK3: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704E906027BS\xf1\x892887', + b'\xf1\x8704E906027BT\xf1\x899042', + b'\xf1\x8704L906026ET\xf1\x891343', + b'\xf1\x8704L906026ET\xf1\x891990', + b'\xf1\x8704L906026FP\xf1\x891196', + b'\xf1\x8704L906026KA\xf1\x896014', + b'\xf1\x8704L906026KB\xf1\x894071', + b'\xf1\x8704L906026KD\xf1\x894798', + b'\xf1\x8704L906026MT\xf1\x893076', + b'\xf1\x8705L906022BK\xf1\x899971', + b'\xf1\x873G0906259 \xf1\x890004', + b'\xf1\x873G0906259B \xf1\x890002', + b'\xf1\x873G0906259L \xf1\x890003', + b'\xf1\x873G0906264A \xf1\x890002', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300042H \xf1\x891601', + b'\xf1\x870CW300043B \xf1\x891603', + b'\xf1\x870CW300049Q \xf1\x890906', + b'\xf1\x870D9300011T \xf1\x894801', + b'\xf1\x870D9300012 \xf1\x894940', + b'\xf1\x870D9300013A \xf1\x894905', + b'\xf1\x870D9300014K \xf1\x895006', + b'\xf1\x870D9300041H \xf1\x894905', + b'\xf1\x870D9300042M \xf1\x895013', + b'\xf1\x870D9300043F \xf1\x895202', + b'\xf1\x870GC300013K \xf1\x892403', + b'\xf1\x870GC300014M \xf1\x892801', + b'\xf1\x870GC300019G \xf1\x892803', + b'\xf1\x870GC300043 \xf1\x892301', + b'\xf1\x870GC300046D \xf1\x892402', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875Q0959655AE\xf1\x890130\xf1\x82\x12111200111121001121110012211292221111', + b'\xf1\x875Q0959655AE\xf1\x890130\xf1\x82\x12111200111121001121118112231292221111', + b'\xf1\x875Q0959655AK\xf1\x890130\xf1\x82\x12111200111121001121110012211292221111', + b'\xf1\x875Q0959655AS\xf1\x890317\xf1\x82\x1331310031313100313131823133319331313100', + b'\xf1\x875Q0959655AT\xf1\x890317\xf1\x82\x1331310031313100313131013131319331313100', + b'\xf1\x875Q0959655BH\xf1\x890336\xf1\x82\x1331310031313100313131013141319331413100', + b'\xf1\x875Q0959655BK\xf1\x890336\xf1\x82\x1331310031313100313131013141319331413100', + b'\xf1\x875Q0959655BS\xf1\x890403\xf1\x82\x1333310031313100313152015351539331423100', + b'\xf1\x875Q0959655CA\xf1\x890403\xf1\x82\x1331310031313100313151013141319331423100', + b'\xf1\x875Q0959655CA\xf1\x890403\xf1\x82\x1331310031313100313151823143319331423100', + b'\xf1\x875Q0959655CH\xf1\x890421\xf1\x82\x1333310031313100313152025350539331463100', + b'\xf1\x875Q0959655CH\xf1\x890421\xf1\x82\x1333310031313100313152855372539331463100', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x875Q0909143K \xf1\x892033\xf1\x820514UZ070203', + b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820522UZ050303', + b'\xf1\x875Q0909143M \xf1\x892041\xf1\x820522UZ070303', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820526UZ060505', + b'\xf1\x875Q0909143P \xf1\x892051\xf1\x820526UZ070505', + b'\xf1\x875Q0910143B \xf1\x892201\xf1\x82\x0563UZ060600', + b'\xf1\x875Q0910143B \xf1\x892201\xf1\x82\x0563UZ060700', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567UZ070500', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567UZ070600', + b'\xf1\x875Q0910143C \xf1\x892211\xf1\x82\x0567UZ070700', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x873Q0907572B \xf1\x890192', + b'\xf1\x873Q0907572B \xf1\x890194', + b'\xf1\x873Q0907572C \xf1\x890195', + b'\xf1\x875Q0907572R \xf1\x890771', + b'\xf1\x875Q0907572S \xf1\x890780', + ], + }, +} diff --git a/opendbc_repo/opendbc/car/volkswagen/interface.py b/opendbc_repo/opendbc/car/volkswagen/interface.py new file mode 100644 index 0000000000..4c40f8740b --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/interface.py @@ -0,0 +1,97 @@ +from opendbc.car import get_safety_config, structs +from opendbc.car.interfaces import CarInterfaceBase +from opendbc.car.volkswagen.carcontroller import CarController +from opendbc.car.volkswagen.carstate import CarState +from opendbc.car.volkswagen.values import CanBus, CAR, NetworkLocation, TransmissionType, VolkswagenFlags, VolkswagenSafetyFlags + + +class CarInterface(CarInterfaceBase): + CarState = CarState + CarController = CarController + + @staticmethod + def _get_params(ret: structs.CarParams, candidate: CAR, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams: + ret.brand = "volkswagen" + ret.radarUnavailable = True + + if ret.flags & VolkswagenFlags.PQ: + # Set global PQ35/PQ46/NMS parameters + safety_configs = [get_safety_config(structs.CarParams.SafetyModel.volkswagenPq)] + ret.enableBsm = 0x3BA in fingerprint[0] # SWA_1 + + if 0x440 in fingerprint[0] or docs: # Getriebe_1 + ret.transmissionType = TransmissionType.automatic + else: + ret.transmissionType = TransmissionType.manual + + if any(msg in fingerprint[1] for msg in (0x1A0, 0xC2)): # Bremse_1, Lenkwinkel_1 + ret.networkLocation = NetworkLocation.gateway + else: + ret.networkLocation = NetworkLocation.fwdCamera + + # The PQ port is in dashcam-only mode due to a fixed six-minute maximum timer on HCA steering. An unsupported + # EPS flash update to work around this timer, and enable steering down to zero, is available from: + # https://github.com/pd0wm/pq-flasher + # It is documented in a four-part blog series: + # https://blog.willemmelching.nl/carhacking/2022/01/02/vw-part1/ + # Panda ALLOW_DEBUG firmware required. + ret.dashcamOnly = True + + else: + # Set global MQB parameters + safety_configs = [get_safety_config(structs.CarParams.SafetyModel.volkswagen)] + ret.enableBsm = 0x30F in fingerprint[0] # SWA_01 + + if 0xAD in fingerprint[0] or docs: # Getriebe_11 + ret.transmissionType = TransmissionType.automatic + elif 0x187 in fingerprint[0]: # Motor_EV_01 + ret.transmissionType = TransmissionType.direct + else: + ret.transmissionType = TransmissionType.manual + + if any(msg in fingerprint[1] for msg in (0x40, 0x86, 0xB2, 0xFD)): # Airbag_01, LWI_01, ESP_19, ESP_21 + ret.networkLocation = NetworkLocation.gateway + else: + ret.networkLocation = NetworkLocation.fwdCamera + + if 0x126 in fingerprint[2]: # HCA_01 + ret.flags |= VolkswagenFlags.STOCK_HCA_PRESENT.value + if 0x6B8 in fingerprint[0]: # Kombi_03 + ret.flags |= VolkswagenFlags.KOMBI_PRESENT.value + + # Global lateral tuning defaults, can be overridden per-vehicle + + ret.steerLimitTimer = 0.4 + if ret.flags & VolkswagenFlags.PQ: + ret.steerActuatorDelay = 0.2 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + else: + ret.steerActuatorDelay = 0.1 + ret.lateralTuning.pid.kpBP = [0.] + ret.lateralTuning.pid.kiBP = [0.] + ret.lateralTuning.pid.kf = 0.00006 + ret.lateralTuning.pid.kpV = [0.6] + ret.lateralTuning.pid.kiV = [0.2] + + # Global longitudinal tuning defaults, can be overridden per-vehicle + + ret.alphaLongitudinalAvailable = ret.networkLocation == NetworkLocation.gateway or docs + if alpha_long: + # Proof-of-concept, prep for E2E only. No radar points available. Panda ALLOW_DEBUG firmware required. + ret.openpilotLongitudinalControl = True + safety_configs[0].safetyParam |= VolkswagenSafetyFlags.LONG_CONTROL.value + if ret.transmissionType == TransmissionType.manual: + ret.minEnableSpeed = 4.5 + + ret.pcmCruise = not ret.openpilotLongitudinalControl + ret.stopAccel = -0.55 + ret.vEgoStarting = 0.1 + ret.vEgoStopping = 0.5 + ret.autoResumeSng = ret.minEnableSpeed == -1 + + CAN = CanBus(fingerprint=fingerprint) + if CAN.pt >= 4: + safety_configs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput)) + ret.safetyConfigs = safety_configs + + return ret diff --git a/opendbc_repo/opendbc/car/volkswagen/mqbcan.py b/opendbc_repo/opendbc/car/volkswagen/mqbcan.py new file mode 100644 index 0000000000..02580e9997 --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/mqbcan.py @@ -0,0 +1,258 @@ +from opendbc.car.crc import CRC8H2F + + +def create_steering_control(packer, bus, apply_torque, lkas_enabled): + values = { + "HCA_01_Status_HCA": 5 if lkas_enabled else 3, + "HCA_01_LM_Offset": abs(apply_torque), + "HCA_01_LM_OffSign": 1 if apply_torque < 0 else 0, + "HCA_01_Vib_Freq": 18, + "HCA_01_Sendestatus": 1 if lkas_enabled else 0, + "EA_ACC_Wunschgeschwindigkeit": 327.36, + } + return packer.make_can_msg("HCA_01", bus, values) + + +def create_eps_update(packer, bus, eps_stock_values, ea_simulated_torque): + values = {s: eps_stock_values[s] for s in [ + "COUNTER", # Sync counter value to EPS output + "EPS_Lenkungstyp", # EPS rack type + "EPS_Berechneter_LW", # Absolute raw steering angle + "EPS_VZ_BLW", # Raw steering angle sign + "EPS_HCA_Status", # EPS HCA control status + ]} + + values.update({ + # Absolute driver torque input and sign, with EA inactivity mitigation + "EPS_Lenkmoment": abs(ea_simulated_torque), + "EPS_VZ_Lenkmoment": 1 if ea_simulated_torque < 0 else 0, + }) + + return packer.make_can_msg("LH_EPS_03", bus, values) + + +def create_lka_hud_control(packer, bus, ldw_stock_values, lat_active, steering_pressed, hud_alert, hud_control): + values = {} + if len(ldw_stock_values): + values = {s: ldw_stock_values[s] for s in [ + "LDW_SW_Warnung_links", # Blind spot in warning mode on left side due to lane departure + "LDW_SW_Warnung_rechts", # Blind spot in warning mode on right side due to lane departure + "LDW_Seite_DLCTLC", # Direction of most likely lane departure (left or right) + "LDW_DLC", # Lane departure, distance to line crossing + "LDW_TLC", # Lane departure, time to line crossing + ]} + + values.update({ + "LDW_Status_LED_gelb": 1 if lat_active and steering_pressed else 0, + "LDW_Status_LED_gruen": 1 if lat_active and not steering_pressed else 0, + "LDW_Lernmodus_links": 3 if hud_control.leftLaneDepart else 1 + hud_control.leftLaneVisible, + "LDW_Lernmodus_rechts": 3 if hud_control.rightLaneDepart else 1 + hud_control.rightLaneVisible, + "LDW_Texte": hud_alert, + }) + return packer.make_can_msg("LDW_02", bus, values) + + +def create_acc_buttons_control(packer, bus, gra_stock_values, cancel=False, resume=False): + values = {s: gra_stock_values[s] for s in [ + "GRA_Hauptschalter", # ACC button, on/off + "GRA_Typ_Hauptschalter", # ACC main button type + "GRA_Codierung", # ACC button configuration/coding + "GRA_Tip_Stufe_2", # unknown related to stalk type + "GRA_ButtonTypeInfo", # unknown related to stalk type + ]} + + values.update({ + "COUNTER": (gra_stock_values["COUNTER"] + 1) % 16, + "GRA_Abbrechen": cancel, + "GRA_Tip_Wiederaufnahme": resume, + }) + + return packer.make_can_msg("GRA_ACC_01", bus, values) + + +def acc_control_value(main_switch_on, acc_faulted, long_active): + if acc_faulted: + acc_control = 6 + elif long_active: + acc_control = 3 + elif main_switch_on: + acc_control = 2 + else: + acc_control = 0 + + return acc_control + + +def acc_hud_status_value(main_switch_on, acc_faulted, long_active): + # TODO: happens to resemble the ACC control value for now, but extend this for init/gas override later + return acc_control_value(main_switch_on, acc_faulted, long_active) + + +def create_acc_accel_control(packer, bus, acc_type, acc_enabled, accel, acc_control, stopping, starting, esp_hold): + commands = [] + + acc_06_values = { + "ACC_Typ": acc_type, + "ACC_Status_ACC": acc_control, + "ACC_StartStopp_Info": acc_enabled, + "ACC_Sollbeschleunigung_02": accel if acc_enabled else 3.01, + "ACC_zul_Regelabw_unten": 0.2, # TODO: dynamic adjustment of comfort-band + "ACC_zul_Regelabw_oben": 0.2, # TODO: dynamic adjustment of comfort-band + "ACC_neg_Sollbeschl_Grad_02": 4.0 if acc_enabled else 0, # TODO: dynamic adjustment of jerk limits + "ACC_pos_Sollbeschl_Grad_02": 4.0 if acc_enabled else 0, # TODO: dynamic adjustment of jerk limits + "ACC_Anfahren": starting, + "ACC_Anhalten": stopping, + } + commands.append(packer.make_can_msg("ACC_06", bus, acc_06_values)) + + if starting: + acc_hold_type = 4 # hold release / startup + elif esp_hold: + acc_hold_type = 3 # hold standby + elif stopping: + acc_hold_type = 1 # hold request + else: + acc_hold_type = 0 + + acc_07_values = { + "ACC_Anhalteweg": 0.3 if stopping else 20.46, # Distance to stop (stopping coordinator handles terminal roll-out) + "ACC_Freilauf_Info": 2 if acc_enabled else 0, + "ACC_Folgebeschl": 3.02, # Not using secondary controller accel unless and until we understand its impact + "ACC_Sollbeschleunigung_02": accel if acc_enabled else 3.01, + "ACC_Anforderung_HMS": acc_hold_type, + "ACC_Anfahren": starting, + "ACC_Anhalten": stopping, + } + commands.append(packer.make_can_msg("ACC_07", bus, acc_07_values)) + + return commands + + +def create_acc_hud_control(packer, bus, acc_hud_status, set_speed, lead_distance, distance): + values = { + "ACC_Status_Anzeige": acc_hud_status, + "ACC_Wunschgeschw_02": set_speed if set_speed < 250 else 327.36, + "ACC_Gesetzte_Zeitluecke": distance + 2, + "ACC_Display_Prio": 3, + "ACC_Abstandsindex": lead_distance, + } + + return packer.make_can_msg("ACC_02", bus, values) + + +# AWV = Stopping Distance Reduction +# Refer to Self Study Program 890253: Volkswagen Driver Assistance Systems, Design and Function + + +def create_aeb_control(packer, fcw_active, aeb_active, accel): + values = { + "AWV_Vorstufe": 0, # Preliminary stage + "AWV1_Anf_Prefill": 0, # Brake pre-fill request + "AWV1_HBA_Param": 0, # Brake pre-fill level + "AWV2_Freigabe": 0, # Stage 2 braking release + "AWV2_Ruckprofil": 0, # Brake jerk level + "AWV2_Priowarnung": 0, # Suppress lane departure warning in favor of FCW + "ANB_Notfallblinken": 0, # Hazard flashers request + "ANB_Teilbremsung_Freigabe": 0, # Target braking release + "ANB_Zielbremsung_Freigabe": 0, # Partial braking release + "ANB_Zielbrems_Teilbrems_Verz_Anf": 0.0, # Acceleration requirement for target/partial braking, m/s/s + "AWV_Halten": 0, # Vehicle standstill request + "PCF_Time_to_collision": 0xFF, # Pre Crash Front, populated only with a target, might be used on Audi only + } + + return packer.make_can_msg("ACC_10", 0, values) + + +def create_aeb_hud(packer, aeb_supported, fcw_active): + values = { + "AWV_Texte": 5 if aeb_supported else 7, # FCW/AEB system status, display text (from menu in VAL) + "AWV_Status_Anzeige": 1 if aeb_supported else 2, # FCW/AEB system status, available or disabled + } + + return packer.make_can_msg("ACC_15", 0, values) + + +def volkswagen_mqb_meb_checksum(address: int, sig, d: bytearray) -> int: + crc = 0xFF + for i in range(1, len(d)): + crc ^= d[i] + crc = CRC8H2F[crc] + counter = d[1] & 0x0F + const = VOLKSWAGEN_MQB_MEB_CONSTANTS.get(address) + if const: + crc ^= const[counter] + crc = CRC8H2F[crc] + return crc ^ 0xFF + + +def xor_checksum(address: int, sig, d: bytearray) -> int: + checksum = 0 + checksum_byte = sig.start_bit // 8 + for i in range(len(d)): + if i != checksum_byte: + checksum ^= d[i] + return checksum + + +VOLKSWAGEN_MQB_MEB_CONSTANTS: dict[int, list[int]] = { + 0x40: [0x40] * 16, # Airbag_01 + 0x86: [0x86] * 16, # LWI_01 + 0x9F: [0xF5] * 16, # LH_EPS_03 + 0xAD: [0x3F, 0x69, 0x39, 0xDC, 0x94, 0xF9, 0x14, 0x64, + 0xD8, 0x6A, 0x34, 0xCE, 0xA2, 0x55, 0xB5, 0x2C], # Getriebe_11 + 0x0DB: [0x09, 0xFA, 0xCA, 0x8E, 0x62, 0xD5, 0xD1, 0xF0, + 0x31, 0xA0, 0xAF, 0xDA, 0x4D, 0x1A, 0x0A, 0x97], # AWV_03 + 0xFC: [0x77, 0x5C, 0xA0, 0x89, 0x4B, 0x7C, 0xBB, 0xD6, + 0x1F, 0x6C, 0x4F, 0xF6, 0x20, 0x2B, 0x43, 0xDD], # ESC_51 + 0xFD: [0xB4, 0xEF, 0xF8, 0x49, 0x1E, 0xE5, 0xC2, 0xC0, + 0x97, 0x19, 0x3C, 0xC9, 0xF1, 0x98, 0xD6, 0x61], # ESP_21 + 0x101: [0xAA] * 16, # ESP_02 + 0x102: [0xD7, 0x12, 0x85, 0x7E, 0x0B, 0x34, 0xFA, 0x16, + 0x7A, 0x25, 0x2D, 0x8F, 0x04, 0x8E, 0x5D, 0x35], # ESC_50 + 0x106: [0x07] * 16, # ESP_05 + 0x10B: [0x77, 0x5C, 0xA0, 0x89, 0x4B, 0x7C, 0xBB, 0xD6, + 0x1F, 0x6C, 0x4F, 0xF6, 0x20, 0x2B, 0x43, 0xDD], # Motor_51 + 0x116: [0xAC] * 16, # ESP_10 + 0x117: [0x16] * 16, # ACC_10 + 0x120: [0xC4, 0xE2, 0x4F, 0xE4, 0xF8, 0x2F, 0x56, 0x81, + 0x9F, 0xE5, 0x83, 0x44, 0x05, 0x3F, 0x97, 0xDF], # TSK_06 + 0x121: [0xE9, 0x65, 0xAE, 0x6B, 0x7B, 0x35, 0xE5, 0x5F, + 0x4E, 0xC7, 0x86, 0xA2, 0xBB, 0xDD, 0xEB, 0xB4], # Motor_20 + 0x122: [0x37, 0x7D, 0xF3, 0xA9, 0x18, 0x46, 0x6D, 0x4D, + 0x3D, 0x71, 0x92, 0x9C, 0xE5, 0x32, 0x10, 0xB9], # ACC_06 + 0x126: [0xDA] * 16, # HCA_01 + 0x12B: [0x6A, 0x38, 0xB4, 0x27, 0x22, 0xEF, 0xE1, 0xBB, + 0xF8, 0x80, 0x84, 0x49, 0xC7, 0x9E, 0x1E, 0x2B], # GRA_ACC_01 + 0x12E: [0xF8, 0xE5, 0x97, 0xC9, 0xD6, 0x07, 0x47, 0x21, + 0x66, 0xDD, 0xCF, 0x6F, 0xA1, 0x94, 0x74, 0x63], # ACC_07 + 0x139: [0xED, 0x03, 0x1C, 0x13, 0xC6, 0x23, 0x78, 0x7A, + 0x8B, 0x40, 0x14, 0x51, 0xBF, 0x68, 0x32, 0xBA], # VMM_02 + 0x13D: [0x20, 0xCA, 0x68, 0xD5, 0x1B, 0x31, 0xE2, 0xDA, + 0x08, 0x0A, 0xD4, 0xDE, 0x9C, 0xE4, 0x35, 0x5B], # QFK_01 + 0x14C: [0x16, 0x35, 0x59, 0x15, 0x9A, 0x2A, 0x97, 0xB8, + 0x0E, 0x4E, 0x30, 0xCC, 0xB3, 0x07, 0x01, 0xAD], # Motor_54 + 0x14D: [0x1A, 0x65, 0x81, 0x96, 0xC0, 0xDF, 0x11, 0x92, + 0xD3, 0x61, 0xC6, 0x95, 0x8C, 0x29, 0x21, 0xB5], # ACC_18 + 0x187: [0x7F, 0xED, 0x17, 0xC2, 0x7C, 0xEB, 0x44, 0x21, + 0x01, 0xFA, 0xDB, 0x15, 0x4A, 0x6B, 0x23, 0x05], # Motor_EV_01 + 0x1A4: [0x69, 0xBB, 0x54, 0xE6, 0x4E, 0x46, 0x8D, 0x7B, + 0xEA, 0x87, 0xE9, 0xB3, 0x63, 0xCE, 0xF8, 0xBF], # EA_01 + 0x1AB: [0x13, 0x21, 0x9B, 0x6A, 0x9A, 0x62, 0xD4, 0x65, + 0x18, 0xF1, 0xAB, 0x16, 0x32, 0x89, 0xE7, 0x26], # ESP_33 + 0x1F0: [0x2F, 0x3C, 0x22, 0x60, 0x18, 0xEB, 0x63, 0x76, + 0xC5, 0x91, 0x0F, 0x27, 0x34, 0x04, 0x7F, 0x02], # EA_02 + 0x20A: [0x9D, 0xE8, 0x36, 0xA1, 0xCA, 0x3B, 0x1D, 0x33, + 0xE0, 0xD5, 0xBB, 0x5F, 0xAE, 0x3C, 0x31, 0x9F], # EML_06 + 0x26B: [0xCE, 0xCC, 0xBD, 0x69, 0xA1, 0x3C, 0x18, 0x76, + 0x0F, 0x04, 0xF2, 0x3A, 0x93, 0x24, 0x19, 0x51], # TA_01 + 0x30C: [0x0F] * 16, # ACC_02 + 0x30F: [0x0C] * 16, # SWA_01 + 0x324: [0x27] * 16, # ACC_04 + 0x3BE: [0x1F, 0x28, 0xC6, 0x85, 0xE6, 0xF8, 0xB0, 0x19, + 0x5B, 0x64, 0x35, 0x21, 0xE4, 0xF7, 0x9C, 0x24], # Motor_14 + 0x3C0: [0xC3] * 16, # Klemmen_Status_01 + 0x3D5: [0xC5, 0x39, 0xC7, 0xF9, 0x92, 0xD8, 0x24, 0xCE, + 0xF1, 0xB5, 0x7A, 0xC4, 0xBC, 0x60, 0xE3, 0xD1], # Licht_Anf_01 + 0x65D: [0xAC, 0xB3, 0xAB, 0xEB, 0x7A, 0xE1, 0x3B, 0xF7, + 0x73, 0xBA, 0x7C, 0x9E, 0x06, 0x5F, 0x02, 0xD9], # ESP_20 +} diff --git a/opendbc_repo/opendbc/car/volkswagen/pqcan.py b/opendbc_repo/opendbc/car/volkswagen/pqcan.py new file mode 100644 index 0000000000..138e4ec5a0 --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/pqcan.py @@ -0,0 +1,106 @@ +def create_steering_control(packer, bus, apply_torque, lkas_enabled): + values = { + "LM_Offset": abs(apply_torque), + "LM_OffSign": 1 if apply_torque < 0 else 0, + "HCA_Status": 5 if (lkas_enabled and apply_torque != 0) else 3, + "Vib_Freq": 16, + } + + return packer.make_can_msg("HCA_1", bus, values) + + +def create_lka_hud_control(packer, bus, ldw_stock_values, lat_active, steering_pressed, hud_alert, hud_control): + values = {} + if len(ldw_stock_values): + values = {s: ldw_stock_values[s] for s in [ + "LDW_SW_Warnung_links", # Blind spot in warning mode on left side due to lane departure + "LDW_SW_Warnung_rechts", # Blind spot in warning mode on right side due to lane departure + "LDW_Seite_DLCTLC", # Direction of most likely lane departure (left or right) + "LDW_DLC", # Lane departure, distance to line crossing + "LDW_TLC", # Lane departure, time to line crossing + ]} + + values.update({ + "LDW_Kameratyp": 1, + "LDW_Lampe_gelb": 1 if lat_active and steering_pressed else 0, + "LDW_Lampe_gruen": 1 if lat_active and not steering_pressed else 0, + "LDW_Lernmodus_links": 3 if hud_control.leftLaneDepart else 1 + hud_control.leftLaneVisible, + "LDW_Lernmodus_rechts": 3 if hud_control.rightLaneDepart else 1 + hud_control.rightLaneVisible, + "LDW_Textbits": hud_alert, + }) + + return packer.make_can_msg("LDW_Status", bus, values) + + +def create_acc_buttons_control(packer, bus, gra_stock_values, cancel=False, resume=False): + values = {s: gra_stock_values[s] for s in [ + "GRA_Hauptschalt", # ACC button, on/off + "GRA_Typ_Hauptschalt", # ACC button, momentary vs latching + "GRA_Kodierinfo", # ACC button, configuration + "GRA_Sender", # ACC button, CAN message originator + ]} + + values.update({ + "COUNTER": (gra_stock_values["COUNTER"] + 1) % 16, + "GRA_Abbrechen": cancel, + "GRA_Recall": resume, + }) + + return packer.make_can_msg("GRA_Neu", bus, values) + + +def acc_control_value(main_switch_on, acc_faulted, long_active): + if long_active: + acc_control = 1 + elif main_switch_on: + acc_control = 2 + else: + acc_control = 0 + + return acc_control + + +def acc_hud_status_value(main_switch_on, acc_faulted, long_active): + if acc_faulted: + hud_status = 6 + elif long_active: + hud_status = 3 + elif main_switch_on: + hud_status = 2 + else: + hud_status = 0 + + return hud_status + + +def create_acc_accel_control(packer, bus, acc_type, acc_enabled, accel, acc_control, stopping, starting, esp_hold): + commands = [] + + values = { + "ACS_Sta_ADR": acc_control, + "ACS_StSt_Info": acc_enabled, + "ACS_Typ_ACC": acc_type, + "ACS_Anhaltewunsch": acc_type == 1 and stopping, + "ACS_FreigSollB": acc_enabled, + "ACS_Sollbeschl": accel if acc_enabled else 3.01, + "ACS_zul_Regelabw": 0.2 if acc_enabled else 1.27, + "ACS_max_AendGrad": 3.0 if acc_enabled else 5.08, + } + + commands.append(packer.make_can_msg("ACC_System", bus, values)) + + return commands + + +def create_acc_hud_control(packer, bus, acc_hud_status, set_speed, lead_distance, distance): + values = { + "ACA_StaACC": acc_hud_status, + "ACA_Zeitluecke": distance + 2, + "ACA_V_Wunsch": set_speed, + "ACA_gemZeitl": lead_distance, + "ACA_PrioDisp": 3, + # TODO: restore dynamic pop-to-foreground/highlight behavior with ACA_PrioDisp and ACA_AnzDisplay + # TODO: ACA_kmh_mph handling probably needed to resolve rounding errors in displayed setpoint + } + + return packer.make_can_msg("ACC_GRA_Anzeige", bus, values) diff --git a/opendbc_repo/opendbc/car/volkswagen/tests/__init__.py b/opendbc_repo/opendbc/car/volkswagen/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py b/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py new file mode 100644 index 0000000000..c0a7a6b65e --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/tests/test_volkswagen.py @@ -0,0 +1,60 @@ +import random +import re + +from opendbc.car.structs import CarParams +from opendbc.car.volkswagen.values import CAR, FW_QUERY_CONFIG, WMI +from opendbc.car.volkswagen.fingerprints import FW_VERSIONS + +Ecu = CarParams.Ecu + +CHASSIS_CODE_PATTERN = re.compile('[A-Z0-9]{2}') +# TODO: determine the unknown groups +SPARE_PART_FW_PATTERN = re.compile(b'\xf1\x87(?P[0-9][0-9A-Z]{2})(?P[0-9][0-9A-Z][0-9])(?P[0-9A-Z]{2}[0-9])([A-Z0-9]| )') + + +class TestVolkswagenPlatformConfigs: + def test_spare_part_fw_pattern(self, subtests): + # Relied on for determining if a FW is likely VW + for platform, ecus in FW_VERSIONS.items(): + with subtests.test(platform=platform.value): + for fws in ecus.values(): + for fw in fws: + assert SPARE_PART_FW_PATTERN.match(fw) is not None, f"Bad FW: {fw}" + + def test_chassis_codes(self, subtests): + for platform in CAR: + with subtests.test(platform=platform.value): + assert len(platform.config.wmis) > 0, "WMIs not set" + assert len(platform.config.chassis_codes) > 0, "Chassis codes not set" + assert all(CHASSIS_CODE_PATTERN.match(cc) for cc in + platform.config.chassis_codes), "Bad chassis codes" + + # No two platforms should share chassis codes + for comp in CAR: + if platform == comp: + continue + assert set() == platform.config.chassis_codes & comp.config.chassis_codes, \ + f"Shared chassis codes: {comp}" + + def test_custom_fuzzy_fingerprinting(self, subtests): + all_radar_fw = list({fw for ecus in FW_VERSIONS.values() for fw in ecus[Ecu.fwdRadar, 0x757, None]}) + + for platform in CAR: + with subtests.test(platform=platform.name): + for wmi in WMI: + for chassis_code in platform.config.chassis_codes | {"00"}: + vin = ["0"] * 17 + vin[0:3] = wmi + vin[6:8] = chassis_code + vin = "".join(vin) + + # Check a few FW cases - expected, unexpected + for radar_fw in random.sample(all_radar_fw, 5) + [b'\xf1\x875Q0907572G \xf1\x890571', b'\xf1\x877H9907572AA\xf1\x890396']: + should_match = ((wmi in platform.config.wmis and chassis_code in platform.config.chassis_codes) and + radar_fw in all_radar_fw) + + live_fws = {(0x757, None): [radar_fw]} + matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fws, vin, FW_VERSIONS) + + expected_matches = {platform} if should_match else set() + assert expected_matches == matches, "Bad match" diff --git a/opendbc_repo/opendbc/car/volkswagen/values.py b/opendbc_repo/opendbc/car/volkswagen/values.py new file mode 100644 index 0000000000..573596fb10 --- /dev/null +++ b/opendbc_repo/opendbc/car/volkswagen/values.py @@ -0,0 +1,554 @@ +from collections import defaultdict, namedtuple +from dataclasses import dataclass, field +from enum import Enum, IntFlag, StrEnum + +from opendbc.car import Bus, CanBusBase, CarSpecs, DbcDict, PlatformConfig, Platforms, structs, uds +from opendbc.can import CANDefine +from opendbc.car.common.conversions import Conversions as CV +from opendbc.car.docs_definitions import CarFootnote, CarHarness, CarDocs, CarParts, Column, \ + Device +from opendbc.car.fw_query_definitions import EcuAddrSubAddr, FwQueryConfig, Request, p16 +from opendbc.car.vin import Vin + +Ecu = structs.CarParams.Ecu +NetworkLocation = structs.CarParams.NetworkLocation +TransmissionType = structs.CarParams.TransmissionType +GearShifter = structs.CarState.GearShifter +Button = namedtuple('Button', ['event_type', 'can_addr', 'can_msg', 'values']) + + +class CanBus(CanBusBase): + def __init__(self, CP=None, fingerprint=None) -> None: + super().__init__(CP, fingerprint) + + self._ext = self.offset + if CP is not None: + self._ext = self.offset + 2 if CP.networkLocation == NetworkLocation.gateway else self.offset + + @property + def pt(self) -> int: + # ADAS / Extended CAN, gateway side of the relay + return self.offset + + @property + def aux(self) -> int: + # NetworkLocation.fwdCamera: radar-camera object fusion CAN + # NetworkLocation.gateway: powertrain CAN + return self.offset + 1 + + @property + def cam(self) -> int: + # ADAS / Extended CAN, camera side of the relay + return self.offset + 2 + + @property + def ext(self) -> int: + # ADAS / Extended CAN, side of the relay with the ACC radar + return self._ext + + +class CarControllerParams: + STEER_STEP = 2 # HCA_01/HCA_1 message frequency 50Hz + ACC_CONTROL_STEP = 2 # ACC_06/ACC_07/ACC_System frequency 50Hz + AEB_CONTROL_STEP = 2 # ACC_10 frequency 50Hz + AEB_HUD_STEP = 20 # ACC_15 frequency 5Hz + + # Documented lateral limits: 3.00 Nm max, rate of change 5.00 Nm/sec. + # MQB vs PQ maximums are shared, but rate-of-change limited differently + # based on safety requirements driven by lateral accel testing. + + STEER_MAX = 300 # Max heading control assist torque 3.00 Nm + STEER_DRIVER_MULTIPLIER = 3 # weight driver torque heavily + STEER_DRIVER_FACTOR = 1 # from dbc + + STEER_TIME_MAX = 360 # Max time that EPS allows uninterrupted HCA steering control + STEER_TIME_ALERT = STEER_TIME_MAX - 10 # If mitigation fails, time to soft disengage before EPS timer expires + STEER_TIME_STUCK_TORQUE = 1.9 # EPS limits same torque to 6 seconds, reset timer 3x within that period + + DEFAULT_MIN_STEER_SPEED = 0.4 # m/s, newer EPS racks fault below this speed, don't show a low speed alert + + ACCEL_MAX = 2.0 # 2.0 m/s max acceleration + ACCEL_MIN = -3.5 # 3.5 m/s max deceleration + + def __init__(self, CP): + can_define = CANDefine(DBC[CP.carFingerprint][Bus.pt]) + + if CP.flags & VolkswagenFlags.PQ: + self.LDW_STEP = 5 # LDW_1 message frequency 20Hz + self.ACC_HUD_STEP = 4 # ACC_GRA_Anzeige frequency 25Hz + self.STEER_DRIVER_ALLOWANCE = 80 # Driver intervention threshold 0.8 Nm + self.STEER_DELTA_UP = 6 # Max HCA reached in 1.00s (STEER_MAX / (50Hz * 1.00)) + self.STEER_DELTA_DOWN = 10 # Min HCA reached in 0.60s (STEER_MAX / (50Hz * 0.60)) + + if CP.transmissionType == TransmissionType.automatic: + self.shifter_values = can_define.dv["Getriebe_1"]["Waehlhebelposition__Getriebe_1_"] + self.hca_status_values = can_define.dv["Lenkhilfe_2"]["LH2_Sta_HCA"] + + self.BUTTONS = [ + Button(structs.CarState.ButtonEvent.Type.setCruise, "GRA_Neu", "GRA_Neu_Setzen", [1]), + Button(structs.CarState.ButtonEvent.Type.resumeCruise, "GRA_Neu", "GRA_Recall", [1]), + Button(structs.CarState.ButtonEvent.Type.accelCruise, "GRA_Neu", "GRA_Up_kurz", [1]), + Button(structs.CarState.ButtonEvent.Type.decelCruise, "GRA_Neu", "GRA_Down_kurz", [1]), + Button(structs.CarState.ButtonEvent.Type.cancel, "GRA_Neu", "GRA_Abbrechen", [1]), + Button(structs.CarState.ButtonEvent.Type.gapAdjustCruise, "GRA_Neu", "GRA_Zeitluecke", [1]), + ] + + self.LDW_MESSAGES = { + "none": 0, # Nothing to display + "laneAssistUnavail": 1, # "Lane Assist currently not available." + "laneAssistUnavailSysError": 2, # "Lane Assist system error" + "laneAssistUnavailNoSensorView": 3, # "Lane Assist not available. No sensor view." + "laneAssistTakeOver": 4, # "Lane Assist: Please Take Over Steering" + "laneAssistDeactivTrailer": 5, # "Lane Assist: no function with trailer" + } + + else: + self.LDW_STEP = 10 # LDW_02 message frequency 10Hz + self.ACC_HUD_STEP = 6 # ACC_02 message frequency 16Hz + self.STEER_DRIVER_ALLOWANCE = 80 # Driver intervention threshold 0.8 Nm + self.STEER_DELTA_UP = 4 # Max HCA reached in 1.50s (STEER_MAX / (50Hz * 1.50)) + self.STEER_DELTA_DOWN = 10 # Min HCA reached in 0.60s (STEER_MAX / (50Hz * 0.60)) + + if CP.transmissionType == TransmissionType.automatic: + self.shifter_values = can_define.dv["Gateway_73"]["GE_Fahrstufe"] + elif CP.transmissionType == TransmissionType.direct: + self.shifter_values = can_define.dv["Motor_EV_01"]["MO_Waehlpos"] + self.hca_status_values = can_define.dv["LH_EPS_03"]["EPS_HCA_Status"] + + self.BUTTONS = [ + Button(structs.CarState.ButtonEvent.Type.setCruise, "GRA_ACC_01", "GRA_Tip_Setzen", [1]), + Button(structs.CarState.ButtonEvent.Type.resumeCruise, "GRA_ACC_01", "GRA_Tip_Wiederaufnahme", [1]), + Button(structs.CarState.ButtonEvent.Type.accelCruise, "GRA_ACC_01", "GRA_Tip_Hoch", [1]), + Button(structs.CarState.ButtonEvent.Type.decelCruise, "GRA_ACC_01", "GRA_Tip_Runter", [1]), + Button(structs.CarState.ButtonEvent.Type.cancel, "GRA_ACC_01", "GRA_Abbrechen", [1]), + Button(structs.CarState.ButtonEvent.Type.gapAdjustCruise, "GRA_ACC_01", "GRA_Verstellung_Zeitluecke", [1]), + ] + + self.LDW_MESSAGES = { + "none": 0, # Nothing to display + "laneAssistUnavailChime": 1, # "Lane Assist currently not available." with chime + "laneAssistUnavailNoSensorChime": 3, # "Lane Assist not available. No sensor view." with chime + "laneAssistTakeOverUrgent": 4, # "Lane Assist: Please Take Over Steering" with urgent beep + "emergencyAssistUrgent": 6, # "Emergency Assist: Please Take Over Steering" with urgent beep + "laneAssistTakeOverChime": 7, # "Lane Assist: Please Take Over Steering" with chime + "laneAssistTakeOver": 8, # "Lane Assist: Please Take Over Steering" silent + "emergencyAssistChangingLanes": 9, # "Emergency Assist: Changing lanes..." with urgent beep + "laneAssistDeactivated": 10, # "Lane Assist deactivated." silent with persistent icon afterward + } + + +class WMI(StrEnum): + VOLKSWAGEN_USA_SUV = "1V2" + VOLKSWAGEN_USA_CAR = "1VW" + VOLKSWAGEN_MEXICO_SUV = "3VV" + VOLKSWAGEN_MEXICO_CAR = "3VW" + VOLKSWAGEN_ARGENTINA = "8AW" + VOLKSWAGEN_BRASIL = "9BW" + SAIC_VOLKSWAGEN = "LSV" + SKODA = "TMB" + SEAT = "VSS" + AUDI_EUROPE_MPV = "WA1" + AUDI_GERMANY_CAR = "WAU" + MAN = "WMA" + AUDI_SPORT = "WUA" + VOLKSWAGEN_COMMERCIAL = "WV1" + VOLKSWAGEN_COMMERCIAL_BUS_VAN = "WV2" + VOLKSWAGEN_EUROPE_SUV = "WVG" + VOLKSWAGEN_EUROPE_CAR = "WVW" + VOLKSWAGEN_GROUP_RUS = "XW8" + + +class VolkswagenSafetyFlags(IntFlag): + LONG_CONTROL = 1 + + +class VolkswagenFlags(IntFlag): + # Detected flags + STOCK_HCA_PRESENT = 1 + KOMBI_PRESENT = 4 + + # Static flags + PQ = 2 + + +@dataclass +class VolkswagenMQBPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'vw_mqb'}) + # Volkswagen uses the VIN WMI and chassis code to match in the absence of the comma power + # on camera-integrated cars, as we lose too many ECUs to reliably identify the vehicle + chassis_codes: set[str] = field(default_factory=set) + wmis: set[WMI] = field(default_factory=set) + + +@dataclass +class VolkswagenPQPlatformConfig(VolkswagenMQBPlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: {Bus.pt: 'vw_pq'}) + + def init(self): + self.flags |= VolkswagenFlags.PQ + + +@dataclass(frozen=True, kw_only=True) +class VolkswagenCarSpecs(CarSpecs): + centerToFrontRatio: float = 0.45 + steerRatio: float = 15.6 + minSteerSpeed: float = CarControllerParams.DEFAULT_MIN_STEER_SPEED + + +class Footnote(Enum): + KAMIQ = CarFootnote( + "Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform.", + Column.MODEL) + PASSAT = CarFootnote( + "Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets.", + Column.MODEL) + SKODA_HEATED_WINDSHIELD = CarFootnote( + "Some Škoda vehicles are equipped with heated windshields, which are known " + + "to block GPS signal needed for some comma 3X functionality.", + Column.MODEL) + VW_EXP_LONG = CarFootnote( + "Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness " + + "are limited to using stock ACC.", + Column.LONGITUDINAL, docs_only=True) + VW_MQB_A0 = CarFootnote( + "Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot " + + "in software, but doesn't yet have a harness available from the comma store.", + Column.HARDWARE) + + +@dataclass +class VWCarDocs(CarDocs): + package: str = "Adaptive Cruise Control (ACC) & Lane Assist" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.vw_j533])) + + def init_make(self, CP: structs.CarParams): + self.footnotes.append(Footnote.VW_EXP_LONG) + if "SKODA" in CP.carFingerprint: + self.footnotes.append(Footnote.SKODA_HEATED_WINDSHIELD) + + if CP.carFingerprint in (CAR.VOLKSWAGEN_CRAFTER_MK2, CAR.VOLKSWAGEN_TRANSPORTER_T61): + self.car_parts = CarParts([Device.threex_angled_mount, CarHarness.vw_j533]) + + if abs(CP.minSteerSpeed - CarControllerParams.DEFAULT_MIN_STEER_SPEED) < 1e-3: + self.min_steer_speed = 0 + + +# Check the 7th and 8th characters of the VIN before adding a new CAR. If the +# chassis code is already listed below, don't add a new CAR, just add to the +# FW_VERSIONS for that existing CAR. + +class CAR(Platforms): + config: VolkswagenMQBPlatformConfig | VolkswagenPQPlatformConfig + + VOLKSWAGEN_ARTEON_MK1 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Arteon 2018-23", video="https://youtu.be/FAomFKPFlDA"), + VWCarDocs("Volkswagen Arteon R 2020-23", video="https://youtu.be/FAomFKPFlDA"), + VWCarDocs("Volkswagen Arteon eHybrid 2020-23", video="https://youtu.be/FAomFKPFlDA"), + VWCarDocs("Volkswagen Arteon Shooting Brake 2020-23", video="https://youtu.be/FAomFKPFlDA"), + VWCarDocs("Volkswagen CC 2018-22", video="https://youtu.be/FAomFKPFlDA"), + ], + VolkswagenCarSpecs(mass=1733, wheelbase=2.84), + chassis_codes={"AN", "3H"}, + wmis={WMI.VOLKSWAGEN_EUROPE_CAR}, + ) + VOLKSWAGEN_ATLAS_MK1 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Atlas 2018-23"), + VWCarDocs("Volkswagen Atlas Cross Sport 2020-22"), + VWCarDocs("Volkswagen Teramont 2018-22"), + VWCarDocs("Volkswagen Teramont Cross Sport 2021-22"), + VWCarDocs("Volkswagen Teramont X 2021-22"), + ], + VolkswagenCarSpecs(mass=2011, wheelbase=2.98), + chassis_codes={"CA"}, + wmis={WMI.VOLKSWAGEN_USA_SUV, WMI.VOLKSWAGEN_EUROPE_SUV}, + ) + VOLKSWAGEN_CADDY_MK3 = VolkswagenPQPlatformConfig( + [ + VWCarDocs("Volkswagen Caddy 2019"), + VWCarDocs("Volkswagen Caddy Maxi 2019"), + ], + VolkswagenCarSpecs(mass=1613, wheelbase=2.6, minSteerSpeed=21 * CV.KPH_TO_MS), + chassis_codes={"2K"}, + wmis={WMI.VOLKSWAGEN_COMMERCIAL_BUS_VAN}, + ) + VOLKSWAGEN_CRAFTER_MK2 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Crafter 2017-24", video="https://youtu.be/4100gLeabmo"), + VWCarDocs("Volkswagen e-Crafter 2018-24", video="https://youtu.be/4100gLeabmo"), + VWCarDocs("Volkswagen Grand California 2019-24", video="https://youtu.be/4100gLeabmo"), + VWCarDocs("MAN TGE 2017-24", video="https://youtu.be/4100gLeabmo"), + VWCarDocs("MAN eTGE 2020-24", video="https://youtu.be/4100gLeabmo"), + ], + VolkswagenCarSpecs(mass=2100, wheelbase=3.64, minSteerSpeed=50 * CV.KPH_TO_MS), + chassis_codes={"SY", "SZ", "UY", "UZ"}, + wmis={WMI.VOLKSWAGEN_COMMERCIAL, WMI.MAN}, + ) + VOLKSWAGEN_GOLF_MK7 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen e-Golf 2014-20"), + VWCarDocs("Volkswagen Golf 2015-20", auto_resume=False), + VWCarDocs("Volkswagen Golf Alltrack 2015-19", auto_resume=False), + VWCarDocs("Volkswagen Golf GTD 2015-20"), + VWCarDocs("Volkswagen Golf GTE 2015-20"), + VWCarDocs("Volkswagen Golf GTI 2015-21", auto_resume=False), + VWCarDocs("Volkswagen Golf R 2015-19"), + VWCarDocs("Volkswagen Golf SportsVan 2015-20"), + ], + VolkswagenCarSpecs(mass=1397, wheelbase=2.62), + chassis_codes={"5G", "AU", "BA", "BE"}, + wmis={WMI.VOLKSWAGEN_MEXICO_CAR, WMI.VOLKSWAGEN_EUROPE_CAR}, + ) + VOLKSWAGEN_JETTA_MK6 = VolkswagenPQPlatformConfig( + [VWCarDocs("Volkswagen Jetta 2015-18")], + VolkswagenCarSpecs(mass=1518, wheelbase=2.65, minSteerSpeed=50 * CV.KPH_TO_MS, minEnableSpeed=20 * CV.KPH_TO_MS), + chassis_codes={"5K", "AJ"}, + wmis={WMI.VOLKSWAGEN_MEXICO_CAR}, + ) + VOLKSWAGEN_JETTA_MK7 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Jetta 2018-23"), + VWCarDocs("Volkswagen Jetta GLI 2021-23"), + ], + VolkswagenCarSpecs(mass=1328, wheelbase=2.71), + chassis_codes={"BU"}, + wmis={WMI.VOLKSWAGEN_MEXICO_CAR, WMI.VOLKSWAGEN_EUROPE_CAR}, + ) + VOLKSWAGEN_PASSAT_MK8 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Passat 2015-22", footnotes=[Footnote.PASSAT]), + VWCarDocs("Volkswagen Passat Alltrack 2015-22"), + VWCarDocs("Volkswagen Passat GTE 2015-22"), + ], + VolkswagenCarSpecs(mass=1551, wheelbase=2.79), + chassis_codes={"3C", "3G"}, + wmis={WMI.VOLKSWAGEN_EUROPE_CAR}, + ) + VOLKSWAGEN_PASSAT_NMS = VolkswagenPQPlatformConfig( + [VWCarDocs("Volkswagen Passat NMS 2017-22")], + VolkswagenCarSpecs(mass=1503, wheelbase=2.80, minSteerSpeed=50 * CV.KPH_TO_MS, minEnableSpeed=20 * CV.KPH_TO_MS), + chassis_codes={"A3"}, + wmis={WMI.VOLKSWAGEN_USA_CAR}, + ) + VOLKSWAGEN_POLO_MK6 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Polo 2018-23", footnotes=[Footnote.VW_MQB_A0]), + VWCarDocs("Volkswagen Polo GTI 2018-23", footnotes=[Footnote.VW_MQB_A0]), + ], + VolkswagenCarSpecs(mass=1230, wheelbase=2.55), + chassis_codes={"AW"}, + wmis={WMI.VOLKSWAGEN_EUROPE_CAR}, + ) + VOLKSWAGEN_SHARAN_MK2 = VolkswagenPQPlatformConfig( + [ + VWCarDocs("Volkswagen Sharan 2018-22"), + VWCarDocs("SEAT Alhambra 2018-20"), + ], + VolkswagenCarSpecs(mass=1639, wheelbase=2.92, minSteerSpeed=50 * CV.KPH_TO_MS), + chassis_codes={"7N"}, + wmis={WMI.VOLKSWAGEN_EUROPE_CAR}, + ) + VOLKSWAGEN_TAOS_MK1 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Volkswagen Taos 2022-24")], + VolkswagenCarSpecs(mass=1498, wheelbase=2.69), + chassis_codes={"B2"}, + wmis={WMI.VOLKSWAGEN_MEXICO_SUV, WMI.VOLKSWAGEN_ARGENTINA}, + ) + VOLKSWAGEN_TCROSS_MK1 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Volkswagen T-Cross 2021", footnotes=[Footnote.VW_MQB_A0])], + VolkswagenCarSpecs(mass=1150, wheelbase=2.60), + chassis_codes={"C1"}, + wmis={WMI.VOLKSWAGEN_EUROPE_SUV}, + ) + VOLKSWAGEN_TIGUAN_MK2 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Tiguan 2018-24"), + VWCarDocs("Volkswagen Tiguan eHybrid 2021-23"), + ], + VolkswagenCarSpecs(mass=1715, wheelbase=2.74), + chassis_codes={"5N", "AD", "AX", "BW"}, + wmis={WMI.VOLKSWAGEN_EUROPE_SUV, WMI.VOLKSWAGEN_MEXICO_SUV}, + ) + VOLKSWAGEN_TOURAN_MK2 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Volkswagen Touran 2016-23")], + VolkswagenCarSpecs(mass=1516, wheelbase=2.79), + chassis_codes={"1T"}, + wmis={WMI.VOLKSWAGEN_EUROPE_SUV}, + ) + VOLKSWAGEN_TRANSPORTER_T61 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Volkswagen Caravelle 2020"), + VWCarDocs("Volkswagen California 2021-23"), + ], + VolkswagenCarSpecs(mass=1926, wheelbase=3.00, minSteerSpeed=14.0), + chassis_codes={"7H", "7L"}, + wmis={WMI.VOLKSWAGEN_COMMERCIAL_BUS_VAN}, + ) + VOLKSWAGEN_TROC_MK1 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Volkswagen T-Roc 2018-23")], + VolkswagenCarSpecs(mass=1413, wheelbase=2.63), + chassis_codes={"A1"}, + wmis={WMI.VOLKSWAGEN_EUROPE_SUV}, + ) + AUDI_A3_MK3 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Audi A3 2014-19"), + VWCarDocs("Audi A3 Sportback e-tron 2017-18"), + VWCarDocs("Audi RS3 2018"), + VWCarDocs("Audi S3 2015-17"), + ], + VolkswagenCarSpecs(mass=1335, wheelbase=2.61), + chassis_codes={"8V", "FF"}, + wmis={WMI.AUDI_GERMANY_CAR, WMI.AUDI_SPORT}, + ) + AUDI_Q2_MK1 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Audi Q2 2018")], + VolkswagenCarSpecs(mass=1205, wheelbase=2.61), + chassis_codes={"GA"}, + wmis={WMI.AUDI_GERMANY_CAR}, + ) + AUDI_Q3_MK2 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Audi Q3 2019-24")], + VolkswagenCarSpecs(mass=1623, wheelbase=2.68), + chassis_codes={"8U", "F3", "FS"}, + wmis={WMI.AUDI_EUROPE_MPV, WMI.AUDI_GERMANY_CAR}, + ) + SEAT_ATECA_MK1 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("CUPRA Ateca 2018-23"), + VWCarDocs("SEAT Ateca 2016-23"), + VWCarDocs("SEAT Leon 2014-20"), + ], + VolkswagenCarSpecs(mass=1300, wheelbase=2.64), + chassis_codes={"5F"}, + wmis={WMI.SEAT}, + ) + SKODA_FABIA_MK4 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Škoda Fabia 2022-23", footnotes=[Footnote.VW_MQB_A0])], + VolkswagenCarSpecs(mass=1266, wheelbase=2.56), + chassis_codes={"PJ"}, + wmis={WMI.SKODA}, + ) + SKODA_KAMIQ_MK1 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Škoda Kamiq 2021-23", footnotes=[Footnote.VW_MQB_A0, Footnote.KAMIQ]), + VWCarDocs("Škoda Scala 2020-23", footnotes=[Footnote.VW_MQB_A0]), + ], + VolkswagenCarSpecs(mass=1230, wheelbase=2.66), + chassis_codes={"NW"}, + wmis={WMI.SKODA}, + ) + SKODA_KAROQ_MK1 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Škoda Karoq 2019-23")], + VolkswagenCarSpecs(mass=1278, wheelbase=2.66), + chassis_codes={"NU"}, + wmis={WMI.SKODA}, + ) + SKODA_KODIAQ_MK1 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Škoda Kodiaq 2017-23")], + VolkswagenCarSpecs(mass=1569, wheelbase=2.79), + chassis_codes={"NS"}, + wmis={WMI.SKODA, WMI.VOLKSWAGEN_GROUP_RUS}, + ) + SKODA_OCTAVIA_MK3 = VolkswagenMQBPlatformConfig( + [ + VWCarDocs("Škoda Octavia 2015-19"), + VWCarDocs("Škoda Octavia RS 2016"), + VWCarDocs("Škoda Octavia Scout 2017-19"), + ], + VolkswagenCarSpecs(mass=1388, wheelbase=2.68), + chassis_codes={"NE"}, + wmis={WMI.SKODA}, + ) + SKODA_SUPERB_MK3 = VolkswagenMQBPlatformConfig( + [VWCarDocs("Škoda Superb 2015-22")], + VolkswagenCarSpecs(mass=1505, wheelbase=2.84), + chassis_codes={"3V", "NP"}, + wmis={WMI.SKODA}, + ) + + +def match_fw_to_car_fuzzy(live_fw_versions, vin, offline_fw_versions) -> set[str]: + candidates = set() + + # Compile all FW versions for each ECU + all_ecu_versions: dict[EcuAddrSubAddr, set[str]] = defaultdict(set) + for ecus in offline_fw_versions.values(): + for ecu, versions in ecus.items(): + all_ecu_versions[ecu] |= set(versions) + + # Check the WMI and chassis code to determine the platform + # https://www.clubvw.org.au/vwreference/vwvin + vin_obj = Vin(vin) + chassis_code = vin_obj.vds[3:5] + + for platform in CAR: + valid_ecus = set() + for ecu in offline_fw_versions[platform]: + addr = ecu[1:] + if ecu[0] not in CHECK_FUZZY_ECUS: + continue + + # Sanity check that live FW is in the superset of all FW, Volkswagen ECU part numbers are commonly shared + found_versions = live_fw_versions.get(addr, []) + expected_versions = all_ecu_versions[ecu] + if not any(found_version in expected_versions for found_version in found_versions): + break + + valid_ecus.add(ecu[0]) + + if valid_ecus != CHECK_FUZZY_ECUS: + continue + + if vin_obj.wmi in platform.config.wmis and chassis_code in platform.config.chassis_codes: + candidates.add(platform) + + return {str(c) for c in candidates} + + +# These ECUs are required to match to gain a VIN match +# TODO: do we want to check camera when we add its FW? +CHECK_FUZZY_ECUS = {Ecu.fwdRadar} + +# All supported cars should return FW from the engine, srs, eps, and fwdRadar. Cars +# with a manual trans won't return transmission firmware, but all other cars will. +# +# The 0xF187 SW part number query should return in the form of N[NX][NX] NNN NNN [X[X]], +# where N=number, X=letter, and the trailing two letters are optional. Performance +# tuners sometimes tamper with that field (e.g. 8V0 9C0 BB0 1 from COBB/EQT). Tampered +# ECU SW part numbers are invalid for vehicle ID and compatibility checks. Try to have +# them repaired by the tuner before including them in openpilot. + +VOLKSWAGEN_VERSION_REQUEST_MULTI = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_SPARE_PART_NUMBER) + \ + p16(uds.DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_SOFTWARE_VERSION_NUMBER) + \ + p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION) +VOLKSWAGEN_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + +VOLKSWAGEN_RX_OFFSET = 0x6a + +FW_QUERY_CONFIG = FwQueryConfig( + requests=[request for bus, obd_multiplexing in [(1, True), (1, False), (0, False)] for request in [ + Request( + [VOLKSWAGEN_VERSION_REQUEST_MULTI], + [VOLKSWAGEN_VERSION_RESPONSE], + whitelist_ecus=[Ecu.srs, Ecu.eps, Ecu.fwdRadar, Ecu.fwdCamera], + rx_offset=VOLKSWAGEN_RX_OFFSET, + bus=bus, + obd_multiplexing=obd_multiplexing, + ), + Request( + [VOLKSWAGEN_VERSION_REQUEST_MULTI], + [VOLKSWAGEN_VERSION_RESPONSE], + whitelist_ecus=[Ecu.engine, Ecu.transmission], + bus=bus, + obd_multiplexing=obd_multiplexing, + ), + ]], + non_essential_ecus={Ecu.eps: list(CAR)}, + extra_ecus=[(Ecu.fwdCamera, 0x74f, None)], + match_fw_to_car_fuzzy=match_fw_to_car_fuzzy, +) + +DBC = CAR.create_dbc_map() diff --git a/opendbc_repo/opendbc/car/xcp.py b/opendbc_repo/opendbc/car/xcp.py new file mode 100644 index 0000000000..046df7403c --- /dev/null +++ b/opendbc_repo/opendbc/car/xcp.py @@ -0,0 +1,266 @@ +import sys +import time +import struct +from enum import IntEnum + + +class COMMAND_CODE(IntEnum): + CONNECT = 0xFF + DISCONNECT = 0xFE + GET_STATUS = 0xFD + SYNCH = 0xFC + GET_COMM_MODE_INFO = 0xFB + GET_ID = 0xFA + SET_REQUEST = 0xF9 + GET_SEED = 0xF8 + UNLOCK = 0xF7 + SET_MTA = 0xF6 + UPLOAD = 0xF5 + SHORT_UPLOAD = 0xF4 + BUILD_CHECKSUM = 0xF3 + TRANSPORT_LAYER_CMD = 0xF2 + USER_CMD = 0xF1 + DOWNLOAD = 0xF0 + DOWNLOAD_NEXT = 0xEF + DOWNLOAD_MAX = 0xEE + SHORT_DOWNLOAD = 0xED + MODIFY_BITS = 0xEC + SET_CAL_PAGE = 0xEB + GET_CAL_PAGE = 0xEA + GET_PAG_PROCESSOR_INFO = 0xE9 + GET_SEGMENT_INFO = 0xE8 + GET_PAGE_INFO = 0xE7 + SET_SEGMENT_MODE = 0xE6 + GET_SEGMENT_MODE = 0xE5 + COPY_CAL_PAGE = 0xE4 + CLEAR_DAQ_LIST = 0xE3 + SET_DAQ_PTR = 0xE2 + WRITE_DAQ = 0xE1 + SET_DAQ_LIST_MODE = 0xE0 + GET_DAQ_LIST_MODE = 0xDF + START_STOP_DAQ_LIST = 0xDE + START_STOP_SYNCH = 0xDD + GET_DAQ_CLOCK = 0xDC + READ_DAQ = 0xDB + GET_DAQ_PROCESSOR_INFO = 0xDA + GET_DAQ_RESOLUTION_INFO = 0xD9 + GET_DAQ_LIST_INFO = 0xD8 + GET_DAQ_EVENT_INFO = 0xD7 + FREE_DAQ = 0xD6 + ALLOC_DAQ = 0xD5 + ALLOC_ODT = 0xD4 + ALLOC_ODT_ENTRY = 0xD3 + PROGRAM_START = 0xD2 + PROGRAM_CLEAR = 0xD1 + PROGRAM = 0xD0 + PROGRAM_RESET = 0xCF + GET_PGM_PROCESSOR_INFO = 0xCE + GET_SECTOR_INFO = 0xCD + PROGRAM_PREPARE = 0xCC + PROGRAM_FORMAT = 0xCB + PROGRAM_NEXT = 0xCA + PROGRAM_MAX = 0xC9 + PROGRAM_VERIFY = 0xC8 + + +ERROR_CODES = { + 0x00: "Command processor synchronization", + 0x10: "Command was not executed", + 0x11: "Command rejected because DAQ is running", + 0x12: "Command rejected because PGM is running", + 0x20: "Unknown command or not implemented optional command", + 0x21: "Command syntax invalid", + 0x22: "Command syntax valid but command parameter(s) out of range", + 0x23: "The memory location is write protected", + 0x24: "The memory location is not accessible", + 0x25: "Access denied, Seed & Key is required", + 0x26: "Selected page not available", + 0x27: "Selected page mode not available", + 0x28: "Selected segment not valid", + 0x29: "Sequence error", + 0x2A: "DAQ configuration not valid", + 0x30: "Memory overflow error", + 0x31: "Generic error", + 0x32: "The slave internal program verify routine detects an error", +} + + +class CONNECT_MODE(IntEnum): + NORMAL = 0x00, + USER_DEFINED = 0x01, + + +class GET_ID_REQUEST_TYPE(IntEnum): + ASCII = 0x00, + ASAM_MC2_FILE = 0x01, + ASAM_MC2_PATH = 0x02, + ASAM_MC2_URL = 0x03, + ASAM_MC2_UPLOAD = 0x04, + # 128-255 user defined + + +class CommandTimeoutError(Exception): + pass + + +class CommandCounterError(Exception): + pass + + +class CommandResponseError(Exception): + def __init__(self, message, return_code): + super().__init__() + self.message = message + self.return_code = return_code + + def __str__(self): + return self.message + + +class XcpClient: + def __init__(self, panda, tx_addr: int, rx_addr: int, bus: int=0, timeout: float=0.1, debug=False, pad=True): + self.tx_addr = tx_addr + self.rx_addr = rx_addr + self.can_bus = bus + self.timeout = timeout + self.debug = debug + self._panda = panda + self._byte_order = ">" + self._max_cto = 8 + self._max_dto = 8 + self.pad = pad + + def _send_cto(self, cmd: int, dat: bytes = b"") -> None: + tx_data = (bytes([cmd]) + dat) + + # Some ECUs don't respond if the packets are not padded to 8 bytes + if self.pad: + tx_data = tx_data.ljust(8, b"\x00") + + if self.debug: + print("CAN-CLEAR: TX") + self._panda.can_clear(self.can_bus) + if self.debug: + print("CAN-CLEAR: RX") + self._panda.can_clear(0xFFFF) + if self.debug: + print(f"CAN-TX: {hex(self.tx_addr)} - 0x{bytes.hex(tx_data)}") + self._panda.can_send(self.tx_addr, tx_data, self.can_bus) + + def _recv_dto(self, timeout: float) -> bytes: + start_time = time.time() + while time.time() - start_time < timeout: + msgs = self._panda.can_recv() or [] + if len(msgs) >= 256: + print("CAN RX buffer overflow!!!", file=sys.stderr) + for rx_addr, rx_data, rx_bus in msgs: + if rx_bus == self.can_bus and rx_addr == self.rx_addr: + rx_data = bytes(rx_data) # convert bytearray to bytes + if self.debug: + print(f"CAN-RX: {hex(rx_addr)} - 0x{bytes.hex(rx_data)}") + + pid = rx_data[0] + if pid == 0xFE: + err = rx_data[1] + err_desc = ERROR_CODES.get(err, "unknown error") + dat = rx_data[2:] + raise CommandResponseError(f"{hex(err)} - {err_desc} {dat}", err) + + return bytes(rx_data[1:]) + time.sleep(0.001) + + raise CommandTimeoutError("timeout waiting for response") + + # commands + def connect(self, connect_mode: CONNECT_MODE=CONNECT_MODE.NORMAL) -> dict: + self._send_cto(COMMAND_CODE.CONNECT, bytes([connect_mode])) + resp = self._recv_dto(self.timeout) + assert len(resp) == 7, f"incorrect data length: {len(resp)}" + self._byte_order = ">" if resp[1] & 0x01 else "<" + self._slave_block_mode = resp[1] & 0x40 != 0 + self._max_cto = resp[2] + self._max_dto = struct.unpack(f"{self._byte_order}H", resp[3:5])[0] + return { + "cal_support": resp[0] & 0x01 != 0, + "daq_support": resp[0] & 0x04 != 0, + "stim_support": resp[0] & 0x08 != 0, + "pgm_support": resp[0] & 0x10 != 0, + "byte_order": self._byte_order, + "address_granularity": 2**((resp[1] & 0x06) >> 1), + "slave_block_mode": self._slave_block_mode, + "optional": resp[1] & 0x80 != 0, + "max_cto": self._max_cto, + "max_dto": self._max_dto, + "protocol_version": resp[5], + "transport_version": resp[6], + } + + def disconnect(self) -> None: + self._send_cto(COMMAND_CODE.DISCONNECT) + resp = self._recv_dto(self.timeout) + assert len(resp) == 0, f"incorrect data length: {len(resp)}" + + def get_id(self, req_id_type: GET_ID_REQUEST_TYPE = GET_ID_REQUEST_TYPE.ASCII) -> dict: + if req_id_type > 255: + raise ValueError("request id type must be less than 255") + self._send_cto(COMMAND_CODE.GET_ID, bytes([req_id_type])) + resp = self._recv_dto(self.timeout) + return { + # mode = 0 means MTA was set + # mode = 1 means data is at end (only CAN-FD has space for this) + "mode": resp[0], + "length": struct.unpack(f"{self._byte_order}I", resp[3:7])[0], + "identifier": resp[7:] if self._max_cto > 8 else None + } + + def get_seed(self, mode: int = 0) -> bytes: + if mode > 255: + raise ValueError("mode must be less than 255") + self._send_cto(COMMAND_CODE.GET_SEED, bytes([0, mode])) + + # TODO: add support for longer seeds spread over multiple blocks + ret = self._recv_dto(self.timeout) + length = ret[0] + return ret[1:length+1] + + def unlock(self, key: bytes) -> bytes: + # TODO: add support for longer keys spread over multiple blocks + self._send_cto(COMMAND_CODE.UNLOCK, bytes([len(key)]) + key) + return self._recv_dto(self.timeout) + + def set_mta(self, addr: int, addr_ext: int = 0) -> bytes: + if addr_ext > 255: + raise ValueError("address extension must be less than 256") + # TODO: this looks broken (missing addr extension) + self._send_cto(COMMAND_CODE.SET_MTA, bytes([0x00, 0x00, addr_ext]) + struct.pack(f"{self._byte_order}I", addr)) + return self._recv_dto(self.timeout) + + def upload(self, size: int) -> bytes: + if size > 255: + raise ValueError("size must be less than 256") + if not self._slave_block_mode and size > self._max_dto - 1: + raise ValueError("block mode not supported") + + self._send_cto(COMMAND_CODE.UPLOAD, bytes([size])) + resp = b"" + while len(resp) < size: + resp += self._recv_dto(self.timeout)[:size - len(resp) + 1] + return resp[:size] # trim off bytes with undefined values + + def short_upload(self, size: int, addr_ext: int, addr: int) -> bytes: + if size > 6: + raise ValueError("size must be less than 7") + if addr_ext > 255: + raise ValueError("address extension must be less than 256") + self._send_cto(COMMAND_CODE.SHORT_UPLOAD, bytes([size, 0x00, addr_ext]) + struct.pack(f"{self._byte_order}I", addr)) + return self._recv_dto(self.timeout)[:size] # trim off bytes with undefined values + + def download(self, data: bytes) -> bytes: + size = len(data) + if size > 255: + raise ValueError("size must be less than 256") + if not self._slave_block_mode and size > self._max_dto - 2: + raise ValueError("block mode not supported") + + self._send_cto(COMMAND_CODE.DOWNLOAD, bytes([size]) + data) + return self._recv_dto(self.timeout)[:size] diff --git a/opendbc_repo/opendbc/dbc/ESR.dbc b/opendbc_repo/opendbc/dbc/ESR.dbc new file mode 100644 index 0000000000..e3837a68b2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/ESR.dbc @@ -0,0 +1,1080 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: Gateway ESR +VAL_TABLE_ ForwardReverse 1 "Reverse" 0 "Forward" ; +VAL_TABLE_ LeftRight 1 "Right Clockwise" 0 "Left CounterClockwise" ; +VAL_TABLE_ ValidInvalid 1 "Valid" 0 "Invalid" ; +VAL_TABLE_ TrueFalse 1 "True" 0 "False" ; + + +BO_ 1343 Target64: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1342 Target63: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1341 Target62: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1340 Target61: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1339 Target60: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1338 Target59: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1337 Target58: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1336 Target57: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1335 Target56: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1334 Target55: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1333 Target54: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1332 Target53: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1331 Target52: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1330 Target51: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1329 Target50: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1328 Target49: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1327 Target48: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1326 Target47: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1325 Target46: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1324 Target45: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1323 Target44: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1322 Target43: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1321 Target42: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1320 Target41: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1319 Target40: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1318 Target39: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1317 Target38: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1316 Target37: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1315 Target36: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1314 Target35: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1313 Target34: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1312 Target33: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1311 Target32: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1310 Target31: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1309 Target30: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1308 Target29: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1307 Target28: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1306 Target27: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1305 Target26: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1304 Target25: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1303 Target24: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1302 Target23: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1301 Target22: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1300 Target21: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1299 Target20: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1298 Target19: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1297 Target18: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1296 Target17: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1295 Target16: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1294 Target15: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1293 Target14: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1292 Target13: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1291 Target12: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1290 Target11: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1289 Target10: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1288 Target9: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1287 Target8: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1285 Target6: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1286 Target7: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1284 Target5: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1283 Target4: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1282 Target3: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1281 Target2: 8 Vector__XXX + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1524 VehicleData3: 8 Gateway + SG_ CAN_RX_YAW_RATE_BIAS_SHIFT : 15|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_WHEELBASE : 55|8@0+ (2,200) [200|710] "cm" Vector__XXX + SG_ CAN_RX_STEERING_GEAR_RATIO : 63|8@0+ (0.125,0) [0|31.875] "" Vector__XXX + SG_ CAN_RX_OVERSTEER_UNDERSTEER : 7|8@0- (1,0) [-128|127] "%" Vector__XXX + SG_ CAN_RX_FUNNEL_OFFSET_RIGHT : 31|8@0- (0.1,0) [-12.8|12.7] "m" Vector__XXX + SG_ CAN_RX_FUNNEL_OFFSET_LEFT : 23|8@0- (0.1,0) [-12.8|12.7] "m" Vector__XXX + SG_ CAN_RX_DISTANCE_REAR_AXLE : 47|8@0+ (2,200) [200|710] "cm" Vector__XXX + SG_ CAN_RX_CW_BLOCKAGE_TRESHOLD : 39|8@0+ (0.0078125,0) [0|1.9921875] "" Vector__XXX + SG_ CAN_RX_BEAMWIDTH_VERT : 14|7@0+ (0.0625,0) [0|7.9375] "deg" Vector__XXX + +BO_ 1523 FactoryAlignment: 8 Gateway + +BO_ 1522 Vehicle_Data2: 8 Gateway + SG_ CAN_RX_WHEEL_SLIP : 41|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_RX_SERV_ALIGN_UPDATES_NEED : 55|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_RX_SERV_ALIGN_TYPE : 47|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_RADAR_HEIGHT : 38|7@0+ (1,0) [0|127] "cm" Vector__XXX + SG_ CAN_RX_RADAR_FOV_MR : 30|7@0+ (1,0) [0|127] "deg" Vector__XXX + SG_ CAN_RX_RADAR_FOV_LR : 19|5@0+ (1,0) [0|31] "deg" Vector__XXX + SG_ CAN_RX_LONG_ACCEL_VALIDITY : 7|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_LONG_ACCEL : 12|9@0- (0.03125,0) [-8|7.96875] "m/s^2" Vector__XXX + SG_ CAN_RX_LAT_ACCEL_VALIDITY : 6|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_LAT_ACCEL : 5|9@0- (0.03125,0) [-8|7.96875] "m/s^2" Vector__XXX + SG_ CAN_RX_AUTO_ALIGN_DISABLE : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_AUTO_ALIGN_CONVERGED : 42|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_ANGLE_MOUNTING_OFFSET : 63|8@0- (0.0625,0) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_RX_AALIGN_AVG_CTR_TOTAL : 45|3@0+ (250,250) [250|2000] "" Vector__XXX + +BO_ 1512 CIPV_Targets_Etc: 8 ESR + +BO_ 1511 ESR_History_Fault: 8 ESR + +BO_ 1510 ESR_Active_Fault: 8 ESR + +BO_ 1508 AD_Data: 8 ESR + +BO_ 1489 SensorValidation2: 8 ESR + SG_ CAN_TX_VALID_MR_SN : 7|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_VALID_MR_RANGE_RATE : 31|16@0- (0.0078125,0) [-256|255.9921875] "m/s" Vector__XXX + SG_ CAN_TX_VALID_MR_RANGE : 15|16@0+ (0.0078125,0) [0|511.9921875] "m" Vector__XXX + SG_ CAN_TX_VALID_MR_POWER : 63|8@0- (1,0) [-128|127] "db" Vector__XXX + SG_ CAN_TX_VALID_MR_ANGLE : 40|16@1- (0.0625,0) [-2048|2047.9375] "deg" Vector__XXX + +BO_ 1488 SensorValidation: 8 ESR + SG_ CAN_TX_VALID_LR_SN : 7|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_VALID_LR_RANGE_RATE : 31|16@0- (0.0078125,0) [-256|255.9921875] "m/s" Vector__XXX + SG_ CAN_TX_VALID_LR_RANGE : 15|16@0+ (0.0078125,0) [0|511.9921875] "m" Vector__XXX + SG_ CAN_TX_VALID_LR_POWER : 63|8@0- (1,0) [-128|127] "db" Vector__XXX + SG_ CAN_TX_VALID_LR_ANGLE : 47|16@0- (0.0625,0) [-2048|2047.9375] "deg" Vector__XXX + +BO_ 1344 Track_Sensor: 1 ESR + SG_ CAN_TX_TRACK_ROLLING_COUNT_2 : 4|1@0+ (1,0) [0|1] "" Vector__XXX + +BO_ 1280 Target1: 8 ESR + SG_ CAN_TX_TRACK_WIDTH : 37|4@0+ (0.5,0) [0|7.5] "" Vector__XXX + SG_ CAN_TX_TRACK_STATUS : 15|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ CAN_TX_TRACK_ROLLING_COUNT : 38|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_RATE : 53|14@0- (0.01,0) [-81.92|81.91] "m/s" Vector__XXX + SG_ CAN_TX_TRACK_RANGE_ACCEL : 33|10@0- (0.05,0) [-25.6|25.55] "m/s^2" Vector__XXX + SG_ CAN_TX_TRACK_RANGE : 18|11@0+ (0.1,0) [0|204.7] "m" Vector__XXX + SG_ CAN_TX_TRACK_ONCOMING : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_MED_RANGE_MODE : 55|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_TRACK_LAT_RATE : 7|6@0- (0.25,0) [-8|7.75] "" Vector__XXX + SG_ CAN_TX_TRACK_GROUPING_CHANGED : 1|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_BRIDGE_OBJECT : 39|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_TRACK_ANGLE : 12|10@0- (0.1,0) [-51.2|51.1] "" Vector__XXX + +BO_ 1265 SensorInput: 8 Gateway + SG_ CAN_RX_USE_ANGLE_MISALIGNMENT : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_RX_SCAN_INDEX_ACK : 7|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_RX_LATERAL_MOUNTING_OFFSET : 47|8@0- (0.01563,0) [-2.00064|1.98501] "m" Vector__XXX + SG_ CAN_RX_WIPER_STATUS : 57|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_VOLVO_SHORT_TRACK_ROC : 31|4@0- (500,0) [-4000|3500] "m" Vector__XXX + SG_ CAN_RX_VEHICLE_SPEED_VALIDITY : 61|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_TURN_SIGNAL_STATUS : 63|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_RX_RAW_DATA_ENABLE : 56|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_RADAR_CMD_RADIATE : 55|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_MR_ONLY_TRANSMIT : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_RX_MMR_UPSIDE_DOWN : 60|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_MAXIMUM_TRACKS : 53|6@0+ (1,0) [0|63] "" Vector__XXX + SG_ CAN_RX_LR_ONLY_TRANSMIT : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_RX_HIGH_YAW_ANGLE : 21|6@0- (1,0) [-32|31] "deg" Vector__XXX + SG_ CAN_RX_GROUPING_MODE : 59|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_RX_CLEAR_FAULTS : 22|1@0- (1,0) [0|0] "" Vector__XXX + SG_ CAN_RX_BLOCKAGE_DISABLE : 54|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_ANGLE_MISALIGNMENT : 39|8@0- (0.0625,0) [-8|7.9375] "deg" Vector__XXX + +BO_ 1264 Vehicle_Data: 8 Gateway + SG_ CAN_RX_YAW_RATE_VALIDITY : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_RX_YAW_RATE : 11|12@0- (0.0625,0) [-128|127.9375] "deg/s" Vector__XXX + SG_ CAN_RX_VEHICLE_SPEED_DIRECTION : 12|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_VEHICLE_SPEED : 7|11@0+ (0.0625,0) [0|127.9375] "m/s" Vector__XXX + SG_ CAN_RX_RADIUS_CURVATURE : 29|14@0- (1,0) [-8192|8191] "m" Vector__XXX + SG_ CAN_RX_STEERING_VALIDITY : 47|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_STEERING_ANGLE_SIGN : 46|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_STEERING_ANGLE_RATE_SIGN : 30|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_RX_STEERING_ANGLE_RATE : 50|11@0+ (1,0) [0|2047] "deg/s" Vector__XXX + SG_ CAN_RX_STEERING_ANGLE : 45|11@0+ (1,0) [0|2047] "deg" Vector__XXX + +BO_ 1251 ESR_Output_InPath: 8 ESR + SG_ CAN_TX_PATH_ID_ACC_MOVE : 15|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_TRUCK_TARGET_DET : 7|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_SIDELOBE_BLOCKATE : 5|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_ROLLING_COUNT_3 : 1|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_PATH_ID_FCW_STAT : 47|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_PATH_ID_FCW_MOVE : 39|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_PATH_ID_CMBB_STAT : 31|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_PATH_ID_CMBB_MOVE : 23|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_PATH_ID_ACC_STAT : 63|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_PARTIAL_BLOCKAGE : 4|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_LR_ONLY_GRATING_LOBE_DET : 6|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_LMR_LR_MODE : 3|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_AUTO_ALIGN_ANGLE : 55|8@0- (0.0625,0) [-8|7.9375] "" Vector__XXX + +BO_ 1250 ESR_SW: 8 ESR + SG_ CAN_TX_SW_VERSION_PLD : 63|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_TX_SW_VERSION_HOST : 15|24@0+ (1,0) [0|16777215] "" Vector__XXX + SG_ CAN_TX_SERIAL_NUM : 39|24@0+ (1,0) [0|16777215] "" Vector__XXX + SG_ CAN_TX_INTERFACE_VERSION : 7|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_TX_HW_VERSION : 3|4@0+ (1,0) [0|15] "" Vector__XXX + +BO_ 1249 ESR_Status2: 8 ESR + SG_ CAN_TX_YAW_RATE_BIAS : 47|8@0- (0.125,0) [-16|15.875] "" Vector__XXX + SG_ CAN_TX_XCVR_OPERATIONAL : 12|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_VEH_SPD_COMP_FACTOR : 39|6@0- (0.00195,1) [0.9376|1.06045] "" Vector__XXX + SG_ CAN_TX_TEMPERATURE : 31|8@0- (1,0) [-128|127] "degC" Vector__XXX + SG_ CAN_TX_SW_VERSION_DSP : 55|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_TX_STEERING_ANGLE_ACK : 10|11@0+ (1,0) [0|2047] "deg" Vector__XXX + SG_ CAN_TX_ROLLING_COUNT_2 : 1|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ CAN_TX_RAW_DATA_MODE : 11|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_RANGE_PERF_ERROR : 14|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_OVERHEAT_ERROR : 15|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_MAXIMUM_TRACKS_ACK : 7|6@0+ (1,1) [1|64] "" Vector__XXX + SG_ CAN_TX_INTERNAL_ERROR : 13|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_TX_GROUPING_MODE : 33|2@0+ (1,0) [0|3] "" Vector__XXX + +BO_ 1248 ESR_Status: 8 ESR + SG_ CAN_TX_COMM_ERROR : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_TX_RADIUS_CURVATURE_CALC : 13|14@0- (1,0) [-8192|8191] "" Vector__XXX + SG_ CAN_TX_YAW_RATE_CALC : 47|12@0- (0.0625,0) [-128|127.9375] "deg/s" Vector__XXX + SG_ CAN_TX_VEHICLE_SPEED_CALC : 50|11@0+ (0.0625,0) [0|127.9375] "m/s" Vector__XXX + SG_ CAN_TX_DSP_TIMESTAMP : 5|7@0+ (2,0) [0|254] "ms" Vector__XXX + SG_ CAN_TX_SCAN_INDEX : 31|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_TX_ROLLING_COUNT_1 : 6|2@1+ (1,0) [0|3] "" Vector__XXX + + + +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "BusType" "CAN"; +VAL_ 1264 CAN_RX_YAW_RATE_VALIDITY 1 "Valid" 0 "Invalid" ; +VAL_ 1264 CAN_RX_VEHICLE_SPEED_DIRECTION 1 "Reverse" 0 "Forward" ; +VAL_ 1264 CAN_RX_STEERING_VALIDITY 1 "True" 0 "False" ; +VAL_ 1264 CAN_RX_STEERING_ANGLE_SIGN 1 "Right Clockwise" 0 "Left CounterClockwise" ; +VAL_ 1264 CAN_RX_STEERING_ANGLE_RATE_SIGN 1 "Right Clockwise" 0 "Left CounterClockwise" ; + diff --git a/opendbc_repo/opendbc/dbc/FORD_CADS.dbc b/opendbc_repo/opendbc/dbc/FORD_CADS.dbc new file mode 100644 index 0000000000..569739c9c5 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/FORD_CADS.dbc @@ -0,0 +1,3544 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: +BU_: MRR +BO_ 1073741824 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ New_Signal_943 : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_SENSOR_VANGLE_OFFSET : 0|8@0+ (0.0625,-8) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_SENSOR_FOV_VER : 0|8@0+ (1,0) [0|255] "deg" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE_QF : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE_REF : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_MMIC_Temp4 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_MMIC_Temp3 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_MMIC_Temp2 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_Processor_Temp2 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_CHECKSUM : 0|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_COUNTER : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_VEHICLE_MODE : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_USC_CAL_VER_MAJOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_USC_CAL_VER_MINOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_SMC_CAL_VER_MAJOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_HW_VERSION : 0|32@0+ (1,0) [0|4.29497e+09] "" Vector__XXX + SG_ CAN_FAC_TGT_MTG_SPACE_VER : 0|8@0+ (1,-128) [-128|127] "cm" Vector__XXX + SG_ CAN_ANGLE_MISALIGNMENT_VER : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_ANGLE_MOUNTING_VOFFSET : 0|8@0+ (0.0625,-8) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_LATCH_FAULTS : 0|64@0+ (1,0) [0|100] "" Vector__XXX + SG_ CAN_ACTIVE_FAULTS : 0|64@0+ (1,0) [0|1.84467e+19] "" Vector__XXX + SG_ CAN_HISTORY_FAULTS : 0|64@0+ (1,0) [0|1.84467e+19] "" Vector__XXX + SG_ CAN_SERV_ALIGN_ENABLE : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_LONG_MOUNTING_OFFSET : 0|8@0+ (0.015625,-2) [-2|1.98438] "" Vector__XXX + SG_ CAN_BEAMWIDTH_VERT : 0|7@0+ (0.125,0) [0|15.875] "deg" Vector__XXX + SG_ CAN_VEHICLE_SPEED_CALC_QF : 0|2@0+ (1,0) [0|3] "" Vector__XXX + +BO_ 34 Active_Fault_Latched_2: 8 MRR + SG_ IPMA_PCAN_DataRangeCheck : 4|1@1+ (1,0) [0|1] "" External_Tool + SG_ IPMA_PCAN_MissingMsg : 3|1@1+ (1,0) [0|1] "" External_Tool + SG_ VINSignalCompareFailure : 2|1@1+ (1,0) [0|1] "" External_Tool + SG_ ModuleNotConfiguredError : 1|1@1+ (1,0) [0|1] "" External_Tool + SG_ CarCfgNotConfiguredError : 0|1@1+ (1,0) [0|1] "" External_Tool + +BO_ 33 Active_Fault_Latched_1: 8 MRR + SG_ Active_Flt_Latched_byte7_bit7 : 63|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit6 : 62|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit5 : 61|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit4 : 60|1@1+ (1,0) [0|1] "" External_Tool + SG_ ARMtoDSPChksumFault : 59|1@1+ (1,0) [0|1] "" External_Tool + SG_ DSPtoArmChksumFault : 58|1@1+ (1,0) [0|1] "" External_Tool + SG_ HostToArmChksumFault : 57|1@1+ (1,0) [0|1] "" External_Tool + SG_ ARMtoHostChksumFault : 56|1@1+ (1,0) [0|1] "" External_Tool + SG_ LoopBWOutOfRange : 55|1@1+ (1,0) [0|1] "" External_Tool + SG_ DSPOverrunFault : 54|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte6_bit5 : 53|1@1+ (1,0) [0|1] "" External_Tool + SG_ TuningSensitivityFault : 52|1@1+ (1,0) [0|1] "" External_Tool + SG_ SaturatedTuningFreqFault : 51|1@1+ (1,0) [0|1] "" External_Tool + SG_ LocalOscPowerFault : 50|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterPowerFault : 49|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte6_bit0 : 48|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit7 : 47|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit6 : 46|1@1+ (1,0) [0|1] "" External_Tool + SG_ XCVRDeviceSPIFault : 45|1@1+ (1,0) [0|1] "" External_Tool + SG_ FreqSynthesizerSPIFault : 44|1@1+ (1,0) [0|1] "" External_Tool + SG_ AnalogConverterDevicSPIFault : 43|1@1+ (1,0) [0|1] "" External_Tool + SG_ SidelobeBlockage : 42|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit1 : 41|1@1+ (1,0) [0|1] "" External_Tool + SG_ MNRBlocked : 40|1@1+ (1,0) [0|1] "" External_Tool + SG_ ECUTempHighFault : 39|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterTempHighFault : 38|1@1+ (1,0) [0|1] "" External_Tool + SG_ AlignmentRoutineFailedFault : 37|1@1+ (1,0) [0|1] "" External_Tool + SG_ UnreasonableRadarData : 36|1@1+ (1,0) [0|1] "" External_Tool + SG_ MicroprocessorTempHighFault : 35|1@1+ (1,0) [0|1] "" External_Tool + SG_ VerticalAlignmentOutOfRange : 34|1@1+ (1,0) [0|1] "" External_Tool + SG_ HorizontalAlignmentOutOfRange : 33|1@1+ (1,0) [0|1] "" External_Tool + SG_ FactoryAlignmentMode : 32|1@1+ (1,0) [0|1] "" External_Tool + SG_ BatteryLowFault : 31|1@1+ (1,0) [0|1] "" External_Tool + SG_ BatteryHighFault : 30|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_1p25SupplyOutOfRange : 29|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte3_bit4 : 28|1@1+ (1,0) [0|1] "" External_Tool + SG_ ThermistorOutOfRange : 27|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_3p3DACSupplyOutOfRange : 26|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_3p3RAWSupplyOutOfRange : 25|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_5_SupplyOutOfRange : 24|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterIDFault : 23|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit6 : 22|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit5 : 21|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit4 : 20|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit3 : 19|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit2 : 18|1@1+ (1,0) [0|1] "" External_Tool + SG_ PCANMissingMsgFault : 17|1@1+ (1,0) [0|1] "" External_Tool + SG_ PCANBusOff : 16|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit7 : 15|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit6 : 14|1@1+ (1,0) [0|1] "" External_Tool + SG_ InstructionSetCheckFault : 13|1@1+ (1,0) [0|1] "" External_Tool + SG_ StackOverflowFault : 12|1@1+ (1,0) [0|1] "" External_Tool + SG_ WatchdogFault : 11|1@1+ (1,0) [0|1] "" External_Tool + SG_ PLLLockFault : 10|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit1 : 9|1@1+ (1,0) [0|1] "" External_Tool + SG_ RAMMemoryTestFault : 8|1@1+ (1,0) [0|1] "" External_Tool + SG_ USCValidationFault : 7|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit6 : 6|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit5 : 5|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit4 : 4|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit3 : 3|1@1+ (1,0) [0|1] "" External_Tool + SG_ KeepAliveChecksumFault : 2|1@1+ (1,0) [0|1] "" External_Tool + SG_ ProgramCalibrationFlashChecksum : 1|1@1+ (1,0) [0|1] "" External_Tool + SG_ ApplicationFlashChecksumFault : 0|1@1+ (1,0) [0|1] "" External_Tool + +BO_ 500 XCP_MRR_DAQ_RESP: 8 MRR + SG_ MRR_xcp_daq_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 499 XCP_MRR_DTO_RESP: 8 MRR + SG_ MRR_xcp_dto_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 497 XCP_MRR_CTO_RESP: 8 MRR + SG_ MRR_xcp_cto_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 1900 Ford_Diag_Resp_Phys: 8 MRR + SG_ TesterPhysicalResCCM : 7|64@0+ (1,0) [0|1.84467e+19] "" IFV_Host + +BO_ 261 MRR_Status_SerialNumber: 8 MRR + SG_ CAN_SEQUENCE_NUMBER : 55|16@0+ (1,0) [0|65535] "" External_Tool + SG_ CAN_SERIAL_NUMBER : 7|40@0+ (1,0) [0|1.09951e+12] "" External_Tool + +BO_ 264 MRR_Status_SwVersion: 8 MRR + SG_ CAN_PBL_Field_Revision : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_PBL_Promote_Revision : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Field_Revision : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Promote_Revision : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Release_Revision : 7|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_PBL_Release_Revision : 31|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 373 MRR_Header_SensorPosition: 8 MRR + SG_ CAN_SENSOR_POLARITY : 55|1@0+ (1,0) [0|1] "" External_Tool + SG_ CAN_SENSOR_LAT_OFFSET : 39|16@0+ (0.01,0) [0|655.35] "cm" External_Tool + SG_ CAN_SENSOR_LONG_OFFSET : 23|16@0+ (0.01,0) [0|655.35] "cm" External_Tool + SG_ CAN_SENSOR_HANGLE_OFFSET : 7|8@0+ (0.0625,-8) [-8|7.9375] "deg" External_Tool + +BO_ 372 MRR_Header_SensorCoverage: 8 MRR + SG_ CAN_SENSOR_FOV_HOR : 39|8@0+ (1,0) [0|255] "deg" IFV_VFP + SG_ CAN_DOPPLER_COVERAGE : 23|8@0+ (1,-128) [-128|127] "m/s" IFV_VFP + SG_ CAN_RANGE_COVERAGE : 7|8@0+ (1,0) [0|255] "m" IFV_VFP + +BO_ 371 MRR_Header_AlignmentState: 8 MRR + SG_ CAN_AUTO_ALIGN_HANGLE_QF : 13|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_ALIGNMENT_STATUS : 51|4@0+ (1,0) [0|11] "" IFV_VFP + SG_ CAN_ALIGNMENT_STATE : 55|3@0+ (1,0) [0|7] "" IFV_VFP + SG_ CAN_AUTO_ALIGN_HANGLE_REF : 11|10@0+ (0.000341218,-0.174533) [-0.174533|0.174533] "rad" IFV_VFP + SG_ CAN_AUTO_ALIGN_HANGLE : 7|10@0+ (0.000341218,-0.174533) [-0.174533|0.174533] "rad" IFV_VFP + +BO_ 369 MRR_Header_Timestamps: 8 MRR + SG_ CAN_DET_TIME_SINCE_MEAS : 39|11@0+ (0.1,0) [0|204.7] "ms" IFV_Host + SG_ CAN_SENSOR_TIME_STAMP : 7|32@0+ (0.1,0) [0|4.29497e+08] "ms" IFV_VFP + +BO_ 368 MRR_Header_InformationDetections: 8 MRR + SG_ CAN_ALIGN_UPDATES_DONE : 55|16@0+ (1,0) [0|65535] "" IFV_VFP + SG_ CAN_SCAN_INDEX : 31|16@0+ (1,0) [0|65535] "" IFV_VFP + SG_ CAN_NUMBER_OF_DET : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_LOOK_ID : 23|2@0+ (1,0) [0|3] "" External_Tool + SG_ CAN_LOOK_INDEX : 7|16@0+ (1,0) [0|65535] "" External_Tool + +BO_ 265 MRR_Status_Temp_Volt: 8 MRR + SG_ CAN_BATT_VOLTS : 63|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_1_25_V : 55|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_5_V : 47|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_3_3_V_RAW : 31|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_3_3_V_DAC : 15|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_MMIC_Temp1 : 39|8@0+ (1,-50) [-50|205] "C" External_Tool + SG_ CAN_Processor_Thermistor : 23|8@0+ (1,-50) [-50|205] "C" External_Tool + SG_ CAN_Processor_Temp1 : 7|8@0+ (1,-50) [-50|205] "C" External_Tool + +BO_ 291 MRR_Detection_004: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_04 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 351 MRR_Detection_064: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_64 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_64 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_64 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_64 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_64 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_64 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_64 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_64 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_64 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_64 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 350 MRR_Detection_063: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_63 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_63 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_63 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_63 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_63 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_63 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_63 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_63 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_63 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_63 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 349 MRR_Detection_062: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_62 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_62 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_62 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_62 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_62 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_62 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_62 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_62 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_62 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_62 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 348 MRR_Detection_061: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_61 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_61 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_61 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_61 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_61 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_61 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_61 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_61 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_61 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_61 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 347 MRR_Detection_060: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_60 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_60 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_60 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_60 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_60 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_60 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_60 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_60 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_60 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_60 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 346 MRR_Detection_059: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_59 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_59 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_59 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_59 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_59 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_59 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_59 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_59 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_59 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_59 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 345 MRR_Detection_058: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_58 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_58 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_58 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_58 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_58 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_58 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_58 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_58 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_58 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_58 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 344 MRR_Detection_057: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_57 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_57 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_57 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_57 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_57 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_57 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_57 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_57 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_57 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_57 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 343 MRR_Detection_056: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_56 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_56 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_56 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_56 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_56 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_56 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_56 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_56 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_56 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_56 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 342 MRR_Detection_055: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_55 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_55 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_55 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_55 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_55 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_55 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_55 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_55 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_55 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_55 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 335 MRR_Detection_048: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_48 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_48 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_48 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_48 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_48 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_48 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_48 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_48 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_48 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_48 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 334 MRR_Detection_047: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_47 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_47 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_47 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_47 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_47 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_47 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_47 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_47 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_47 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_47 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 333 MRR_Detection_046: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_46 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_46 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_46 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_46 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_46 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_46 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_46 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_46 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_46 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_46 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 332 MRR_Detection_045: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_45 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_45 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_45 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_45 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_45 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_45 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_45 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_45 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_45 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_45 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 331 MRR_Detection_044: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_44 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_44 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_44 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_44 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_44 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_44 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_44 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_44 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_44 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_44 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 330 MRR_Detection_043: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_43 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_43 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_43 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_43 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_43 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_43 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_43 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_43 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_43 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_43 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 329 MRR_Detection_042: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_42 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_42 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_42 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_42 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_42 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_42 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_42 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_42 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_42 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_42 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 328 MRR_Detection_041: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_41 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_41 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_41 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_41 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_41 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_41 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_41 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_41 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_41 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_41 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 327 MRR_Detection_040: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_40 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_40 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_40 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_40 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_40 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_40 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_40 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_40 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_40 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_40 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 325 MRR_Detection_038: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_38 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_38 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_38 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_38 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_38 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_38 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_38 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_38 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_38 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_38 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 324 MRR_Detection_037: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_37 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_37 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_37 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_37 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_37 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_37 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_37 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_37 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_37 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_37 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 323 MRR_Detection_036: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_36 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_36 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_36 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_36 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_36 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_36 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_36 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_36 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_36 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_36 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 322 MRR_Detection_035: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_35 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_35 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_35 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_35 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_35 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_35 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_35 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_35 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_35 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_35 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 321 MRR_Detection_034: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_34 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_34 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_34 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_34 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_34 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_34 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_34 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_34 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_34 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_34 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 320 MRR_Detection_033: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_33 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_33 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_33 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_33 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_33 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_33 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_33 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_33 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_33 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_33 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 319 MRR_Detection_032: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_32 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_32 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_32 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_32 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_32 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_32 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_32 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_32 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_32 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_32 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 318 MRR_Detection_031: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_31 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_31 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_31 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_31 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_31 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_31 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_31 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_31 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_31 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_31 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 317 MRR_Detection_030: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_30 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_30 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_30 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_30 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_30 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_30 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_30 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_30 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_30 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_30 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 316 MRR_Detection_029: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_29 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_29 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_29 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_29 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_29 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_29 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_29 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_29 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_29 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_29 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 314 MRR_Detection_027: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_27 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_27 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_27 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_27 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_27 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_27 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_27 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_27 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_27 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_27 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 313 MRR_Detection_026: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_26 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_26 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_26 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_26 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_26 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_26 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_26 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_26 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_26 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_26 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 312 MRR_Detection_025: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_25 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_25 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_25 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_25 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_25 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_25 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_25 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_25 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_25 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_25 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 311 MRR_Detection_024: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_24 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_24 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_24 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_24 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_24 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_24 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_24 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_24 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_24 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_24 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 310 MRR_Detection_023: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_23 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_23 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_23 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_23 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_23 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_23 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_23 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_23 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_23 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_23 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 309 MRR_Detection_022: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_22 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_22 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_22 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_22 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_22 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_22 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_22 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_22 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_22 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_22 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 308 MRR_Detection_021: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_21 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 307 MRR_Detection_020: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_20 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 306 MRR_Detection_019: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_19 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 305 MRR_Detection_018: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_18 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 341 MRR_Detection_054: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_54 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_54 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_54 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_54 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_54 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_54 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_54 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_54 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_54 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_54 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 340 MRR_Detection_053: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_53 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_53 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_53 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_53 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_53 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_53 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_53 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_53 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_53 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_53 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 339 MRR_Detection_052: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_52 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_52 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_52 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_52 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_52 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_52 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_52 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_52 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_52 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_52 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 338 MRR_Detection_051: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_51 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_51 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_51 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_51 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_51 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_51 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_51 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_51 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_51 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_51 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 337 MRR_Detection_050: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_50 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_50 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_50 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_50 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_50 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_50 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_50 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_50 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_50 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_50 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 336 MRR_Detection_049: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_49 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_49 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_49 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_49 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_49 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_49 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_49 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_49 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_49 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_49 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 326 MRR_Detection_039: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_39 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_39 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_39 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_39 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_39 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_39 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_39 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_39 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_39 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_39 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 315 MRR_Detection_028: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_28 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_28 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_28 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_28 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_28 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_28 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_28 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_28 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_28 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_28 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 304 MRR_Detection_017: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_17 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 303 MRR_Detection_016: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_16 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 302 MRR_Detection_015: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_15 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 301 MRR_Detection_014: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_14 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 300 MRR_Detection_013: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_13 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 299 MRR_Detection_012: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_12 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 298 MRR_Detection_011: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_11 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 297 MRR_Detection_010: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_10 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 296 MRR_Detection_009: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_09 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 295 MRR_Detection_008: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_08 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 294 MRR_Detection_007: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_07 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 293 MRR_Detection_006: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_06 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 292 MRR_Detection_005: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_05 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 290 MRR_Detection_003: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_03 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 289 MRR_Detection_002: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_02 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 256 MRR_Status_CANVersion: 8 MRR + SG_ CAN_USC_SECTION_COMPATIBILITY : 23|16@0+ (1,0) [0|65535] "" External_Tool + SG_ CAN_PCAN_MINOR_MRR : 7|8@0+ (1,0) [0|255] "" IFV_VFP + SG_ CAN_PCAN_MAJOR_MRR : 15|8@0+ (1,0) [0|255] "" IFV_VFP + +BO_ 257 MRR_Status_Radar: 8 MRR + SG_ CAN_INTERFERENCE_TYPE : 11|2@0+ (1,0) [0|3] "" IFV_Host + SG_ CAN_RECOMMEND_UNCONVERGE : 9|1@0+ (1,0) [0|1] "" IFV_Host + SG_ CAN_BLOCKAGE_SIDELOBE_FILTER_VAL : 15|4@0+ (1,0) [0|15] "" IFV_Host + SG_ CAN_RADAR_ALIGN_INCOMPLETE : 8|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_BLOCKAGE_SIDELOBE : 4|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_BLOCKAGE_MNR : 5|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_EXT_COND_NOK : 1|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_ALIGN_OUT_RANGE : 2|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_ALIGN_NOT_START : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_OVERHEAT_ERROR : 3|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_NOT_OP : 6|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_XCVR_OPERATIONAL : 7|1@0+ (1,0) [0|1] "" IFV_VFP + +BO_ 288 MRR_Detection_001: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BA_DEF_ SG_ "CrossOver_InfoCAN" ENUM "No","Yes"; +BA_DEF_ SG_ "CrossOver_LIN" ENUM "No","Yes","No","Yes"; +BA_DEF_ SG_ "UsedOnPgmDBC" ENUM "No","Yes","No","Yes","No","Yes"; +BA_DEF_ SG_ "ContentDependant" ENUM "No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ SG_ "GenSigTimeoutTime_RCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_GWM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_OCS" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ABS_ESC" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_CCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_IPMA" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TSTR" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_SCCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_PSCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime__delete" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_Generic_BCM" INT 0 100000; +BA_DEF_ BO_ "NmMessage" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "DiagResponse" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "DiagRequest" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "TpTxIndex" INT 0 255; +BA_DEF_ BO_ "DiagState" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "TpApplType" STRING ; +BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "Mulitplexer" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "ConfiguredTransmitter" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "EventRateOfChange" INT 10 10000; +BA_DEF_ BO_ "GenMsgHandlingTypeDoc" STRING ; +BA_DEF_ BO_ "GenMsgHandlingTypeCode" STRING ; +BA_DEF_ BO_ "GenMsgMarked" STRING ; +BA_DEF_ SG_ "GenSigMarked" STRING ; +BA_DEF_ SG_ "GenSigVtIndex" STRING ; +BA_DEF_ SG_ "GenSigVtName" STRING ; +BA_DEF_ SG_ "GenSigVtEn" STRING ; +BA_DEF_ SG_ "GenSigSNA" STRING ; +BA_DEF_ SG_ "GenSigCmt" STRING ; +BA_DEF_ BO_ "GenMsgCmt" STRING ; +BA_DEF_ SG_ "GenSigSendType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType"; +BA_DEF_ SG_ "GenSigInactiveValue" INT 0 100000; +BA_DEF_ SG_ "GenSigMissingSourceValue" INT 0 1e+09; +BA_DEF_ SG_ "WakeupSignal" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes"; +BA_DEF_ SG_ "GenSigStartValue" INT 0 1e+09; +BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes"; +BA_DEF_ BO_ "NetworkInitializationCommand" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "GenMsgSendType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType"; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000; +BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 100000; +BA_DEF_ BO_ "GenMsgDelayTime" INT 0 1000; +BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100; +BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 10000; +BA_DEF_ BO_ "NetworkInitialization" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes"; +BA_DEF_ BO_ "MessageGateway" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes"; +BA_DEF_ BU_ "ILUsed" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BU_ "NetworkInitializationUsed" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BU_ "PowerType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes","No","Yes","Switched","Latched","Sleep","vector_leerstring","vector_leerstring"; +BA_DEF_ BU_ "NodeStartUpTime" INT 0 10000; +BA_DEF_ BU_ "NodeWakeUpTime" INT 0 10000; +BA_DEF_ BO_ "GenMsgBackgroundColor" STRING ; +BA_DEF_ BO_ "GenMsgForegroundColor" STRING ; +BA_ "GenMsgCycleTime" BO_ 34 1000; +BA_ "GenMsgSendType" BO_ 34 0; +BA_ "GenSigVtEn" SG_ 34 IPMA_PCAN_DataRangeCheck "IPMA_PCAN_DataRangeCheck"; +BA_ "GenSigVtName" SG_ 34 IPMA_PCAN_DataRangeCheck "IPMA_PCAN_DataRangeCheck"; +BA_ "GenSigVtEn" SG_ 34 IPMA_PCAN_MissingMsg "IPMA_PCAN_MissingMsg"; +BA_ "GenSigVtName" SG_ 34 IPMA_PCAN_MissingMsg "IPMA_PCAN_MissingMsg"; +BA_ "GenSigVtEn" SG_ 34 VINSignalCompareFailure "VINSignalCompareFailure"; +BA_ "GenSigVtName" SG_ 34 VINSignalCompareFailure "VINSignalCompareFailure"; +BA_ "GenSigVtEn" SG_ 34 ModuleNotConfiguredError "ModuleNotConfiguredError"; +BA_ "GenSigVtName" SG_ 34 ModuleNotConfiguredError "ModuleNotConfiguredError"; +BA_ "GenSigVtEn" SG_ 34 CarCfgNotConfiguredError "CarCfgNotConfiguredError"; +BA_ "GenSigVtName" SG_ 34 CarCfgNotConfiguredError "CarCfgNotConfiguredError"; +BA_ "GenMsgCycleTime" BO_ 33 1000; +BA_ "GenMsgSendType" BO_ 33 0; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit7 "Active_Flt_Latched_byte7_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit7 "Active_Flt_Latched_byte7_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit6 "Active_Flt_Latched_byte7_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit6 "Active_Flt_Latched_byte7_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit5 "Active_Flt_Latched_byte7_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit5 "Active_Flt_Latched_byte7_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit4 "Active_Flt_Latched_byte7_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit4 "Active_Flt_Latched_byte7_bit4"; +BA_ "GenSigVtEn" SG_ 33 ARMtoDSPChksumFault "ARMtoDSPChksumFault"; +BA_ "GenSigVtName" SG_ 33 ARMtoDSPChksumFault "ARMtoDSPChksumFault"; +BA_ "GenSigVtEn" SG_ 33 DSPtoArmChksumFault "DSPtoArmChksumFault"; +BA_ "GenSigVtName" SG_ 33 DSPtoArmChksumFault "DSPtoArmChksumFault"; +BA_ "GenSigVtEn" SG_ 33 HostToArmChksumFault "HostToArmChksumFault"; +BA_ "GenSigVtName" SG_ 33 HostToArmChksumFault "HostToArmChksumFault"; +BA_ "GenSigVtEn" SG_ 33 ARMtoHostChksumFault "ARMtoHostChksumFault"; +BA_ "GenSigVtName" SG_ 33 ARMtoHostChksumFault "ARMtoHostChksumFault"; +BA_ "GenSigVtEn" SG_ 33 LoopBWOutOfRange "LoopBWOutOfRange"; +BA_ "GenSigVtName" SG_ 33 LoopBWOutOfRange "LoopBWOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 DSPOverrunFault "DSPOverrunFault"; +BA_ "GenSigVtName" SG_ 33 DSPOverrunFault "DSPOverrunFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte6_bit5 "Active_Flt_Latched_byte6_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte6_bit5 "Active_Flt_Latched_byte6_bit5"; +BA_ "GenSigVtEn" SG_ 33 TuningSensitivityFault "TuningSensitivityFault"; +BA_ "GenSigVtName" SG_ 33 TuningSensitivityFault "TuningSensitivityFault"; +BA_ "GenSigVtEn" SG_ 33 SaturatedTuningFreqFault "SaturatedTuningFreqFault"; +BA_ "GenSigVtName" SG_ 33 SaturatedTuningFreqFault "SaturatedTuningFreqFault"; +BA_ "GenSigVtEn" SG_ 33 LocalOscPowerFault "LocalOscPowerFault"; +BA_ "GenSigVtName" SG_ 33 LocalOscPowerFault "LocalOscPowerFault"; +BA_ "GenSigVtEn" SG_ 33 TransmitterPowerFault "TransmitterPowerFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterPowerFault "TransmitterPowerFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte6_bit0 "Active_Flt_Latched_byte6_bit0"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte6_bit0 "Active_Flt_Latched_byte6_bit0"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit7 "Active_Flt_Latched_byte5_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit7 "Active_Flt_Latched_byte5_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit6 "Active_Flt_Latched_byte5_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit6 "Active_Flt_Latched_byte5_bit6"; +BA_ "GenSigVtEn" SG_ 33 XCVRDeviceSPIFault "XCVRDeviceSPIFault"; +BA_ "GenSigVtName" SG_ 33 XCVRDeviceSPIFault "XCVRDeviceSPIFault"; +BA_ "GenSigVtEn" SG_ 33 FreqSynthesizerSPIFault "FreqSynthesizerSPIFault"; +BA_ "GenSigVtName" SG_ 33 FreqSynthesizerSPIFault "FreqSynthesizerSPIFault"; +BA_ "GenSigVtEn" SG_ 33 AnalogConverterDevicSPIFault "AnalogConverterDevicSPIFault"; +BA_ "GenSigVtName" SG_ 33 AnalogConverterDevicSPIFault "AnalogConverterDevicSPIFault"; +BA_ "GenSigVtEn" SG_ 33 SidelobeBlockage "SidelobeBlockage"; +BA_ "GenSigVtName" SG_ 33 SidelobeBlockage "SidelobeBlockage"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit1 "Active_Flt_Latched_byte5_bit1"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit1 "Active_Flt_Latched_byte5_bit1"; +BA_ "GenSigVtEn" SG_ 33 MNRBlocked "MNRBlocked"; +BA_ "GenSigVtName" SG_ 33 MNRBlocked "MNRBlocked"; +BA_ "GenSigVtEn" SG_ 33 ECUTempHighFault "ECUTempHighFault"; +BA_ "GenSigVtName" SG_ 33 ECUTempHighFault "ECUTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 TransmitterTempHighFault "TransmitterTempHighFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterTempHighFault "TransmitterTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 AlignmentRoutineFailedFault "AlignmentRoutineFailedFault"; +BA_ "GenSigVtName" SG_ 33 AlignmentRoutineFailedFault "AlignmentRoutineFailedFault"; +BA_ "GenSigVtEn" SG_ 33 UnreasonableRadarData "UnreasonableRadarData"; +BA_ "GenSigVtName" SG_ 33 UnreasonableRadarData "UnreasonableRadarData"; +BA_ "GenSigVtEn" SG_ 33 MicroprocessorTempHighFault "MicroprocessorTempHighFault"; +BA_ "GenSigVtName" SG_ 33 MicroprocessorTempHighFault "MicroprocessorTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 VerticalAlignmentOutOfRange "VerticalAlignmentOutOfRange"; +BA_ "GenSigVtName" SG_ 33 VerticalAlignmentOutOfRange "VerticalAlignmentOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 HorizontalAlignmentOutOfRange "HorizontalAlignmentOutOfRange"; +BA_ "GenSigVtName" SG_ 33 HorizontalAlignmentOutOfRange "HorizontalAlignmentOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 FactoryAlignmentMode "FactoryAlignmentMode"; +BA_ "GenSigVtName" SG_ 33 FactoryAlignmentMode "FactoryAlignmentMode"; +BA_ "GenSigVtEn" SG_ 33 BatteryLowFault "BatteryLowFault"; +BA_ "GenSigVtName" SG_ 33 BatteryLowFault "BatteryLowFault"; +BA_ "GenSigVtEn" SG_ 33 BatteryHighFault "BatteryHighFault"; +BA_ "GenSigVtName" SG_ 33 BatteryHighFault "BatteryHighFault"; +BA_ "GenSigVtEn" SG_ 33 v_1p25SupplyOutOfRange "v_1p25SupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_1p25SupplyOutOfRange "v_1p25SupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte3_bit4 "Active_Flt_Latched_byte3_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte3_bit4 "Active_Flt_Latched_byte3_bit4"; +BA_ "GenSigVtEn" SG_ 33 ThermistorOutOfRange "ThermistorOutOfRange"; +BA_ "GenSigVtName" SG_ 33 ThermistorOutOfRange "ThermistorOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_3p3DACSupplyOutOfRange "v_3p3DACSupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_3p3DACSupplyOutOfRange "v_3p3DACSupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_3p3RAWSupplyOutOfRange "v_3p3RAWSupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_3p3RAWSupplyOutOfRange "v_3p3RAWSupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_5_SupplyOutOfRange "v_5_SupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_5_SupplyOutOfRange "v_5_SupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 TransmitterIDFault "TransmitterIDFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterIDFault "TransmitterIDFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit6 "Active_Flt_Latched_byte2_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit6 "Active_Flt_Latched_byte2_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit5 "Active_Flt_Latched_byte2_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit5 "Active_Flt_Latched_byte2_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit4 "Active_Flt_Latched_byte2_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit4 "Active_Flt_Latched_byte2_bit4"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit3 "Active_Flt_Latched_byte2_bit3"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit3 "Active_Flt_Latched_byte2_bit3"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit2 "Active_Flt_Latched_byte2_bit2"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit2 "Active_Flt_Latched_byte2_bit2"; +BA_ "GenSigVtEn" SG_ 33 PCANMissingMsgFault "PCANMissingMsgFault"; +BA_ "GenSigVtName" SG_ 33 PCANMissingMsgFault "PCANMissingMsgFault"; +BA_ "GenSigVtEn" SG_ 33 PCANBusOff "PCANBusOff"; +BA_ "GenSigVtName" SG_ 33 PCANBusOff "PCANBusOff"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit7 "Active_Flt_Latched_byte1_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit7 "Active_Flt_Latched_byte1_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit6 "Active_Flt_Latched_byte1_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit6 "Active_Flt_Latched_byte1_bit6"; +BA_ "GenSigVtEn" SG_ 33 InstructionSetCheckFault "InstructionSetCheckFault"; +BA_ "GenSigVtName" SG_ 33 InstructionSetCheckFault "InstructionSetCheckFault"; +BA_ "GenSigVtEn" SG_ 33 StackOverflowFault "StackOverflowFault"; +BA_ "GenSigVtName" SG_ 33 StackOverflowFault "StackOverflowFault"; +BA_ "GenSigVtEn" SG_ 33 WatchdogFault "WatchdogFault"; +BA_ "GenSigVtName" SG_ 33 WatchdogFault "WatchdogFault"; +BA_ "GenSigVtEn" SG_ 33 PLLLockFault "PLLLockFault"; +BA_ "GenSigVtName" SG_ 33 PLLLockFault "PLLLockFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit1 "Active_Flt_Latched_byte1_bit1"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit1 "Active_Flt_Latched_byte1_bit1"; +BA_ "GenSigVtEn" SG_ 33 RAMMemoryTestFault "RAMMemoryTestFault"; +BA_ "GenSigVtName" SG_ 33 RAMMemoryTestFault "RAMMemoryTestFault"; +BA_ "GenSigVtName" SG_ 33 USCValidationFault "USCValidationFault"; +BA_ "GenSigVtEn" SG_ 33 USCValidationFault "USCValidationFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit6 "Active_Flt_Latched_byte0_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit6 "Active_Flt_Latched_byte0_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit5 "Active_Flt_Latched_byte0_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit5 "Active_Flt_Latched_byte0_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit4 "Active_Flt_Latched_byte0_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit4 "Active_Flt_Latched_byte0_bit4"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit3 "Active_Flt_Latched_byte0_bit3"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit3 "Active_Flt_Latched_byte0_bit3"; +BA_ "GenSigVtEn" SG_ 33 KeepAliveChecksumFault "KeepAliveChecksumFault"; +BA_ "GenSigVtName" SG_ 33 KeepAliveChecksumFault "KeepAliveChecksumFault"; +BA_ "GenSigVtEn" SG_ 33 ProgramCalibrationFlashChecksum "ProgramCalibrationFlashChecksum"; +BA_ "GenSigVtName" SG_ 33 ProgramCalibrationFlashChecksum "ProgramCalibrationFlashChecksum"; +BA_ "GenSigVtEn" SG_ 33 ApplicationFlashChecksumFault "ApplicationFlashChecksumFault"; +BA_ "GenSigVtName" SG_ 33 ApplicationFlashChecksumFault "ApplicationFlashChecksumFault"; +BA_ "GenMsgNrOfRepetition" BO_ 500 0; +BA_ "GenMsgSendType" BO_ 500 1; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte7 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte7 "MRR_xcp_daq_resp_byte7"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte6 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte6 "MRR_xcp_daq_resp_byte6"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte5 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte5 "MRR_xcp_daq_resp_byte5"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte4 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte4 "MRR_xcp_daq_resp_byte4"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte3 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte3 "MRR_xcp_daq_resp_byte3"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte2 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte2 "MRR_xcp_daq_resp_byte2"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte1 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte1 "MRR_xcp_daq_resp_byte1"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte0 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte0 "MRR_xcp_daq_resp_byte0"; +BA_ "GenMsgNrOfRepetition" BO_ 499 0; +BA_ "GenMsgSendType" BO_ 499 1; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte7 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte7 "MRR_xcp_dto_resp_byte7"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte6 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte6 "MRR_xcp_dto_resp_byte6"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte5 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte5 "MRR_xcp_dto_resp_byte5"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte4 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte4 "MRR_xcp_dto_resp_byte4"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte3 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte3 "MRR_xcp_dto_resp_byte3"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte2 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte2 "MRR_xcp_dto_resp_byte2"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte1 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte1 "MRR_xcp_dto_resp_byte1"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte0 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte0 "MRR_xcp_dto_resp_byte0"; +BA_ "GenMsgNrOfRepetition" BO_ 497 0; +BA_ "GenMsgSendType" BO_ 497 1; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte7 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte7 "MRR_xcp_cto_resp_byte7"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte6 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte6 "MRR_xcp_cto_resp_byte6"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte5 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte5 "MRR_xcp_cto_resp_byte5"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte4 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte4 "MRR_xcp_cto_resp_byte4"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte3 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte3 "MRR_xcp_cto_resp_byte3"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte2 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte2 "MRR_xcp_cto_resp_byte2"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte1 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte1 "MRR_xcp_cto_resp_byte1"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte0 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte0 "MRR_xcp_cto_resp_byte0"; +BA_ "GenMsgSendType" BO_ 1900 1; +BA_ "GenMsgNrOfRepetition" BO_ 1900 0; +BA_ "DiagResponse" BO_ 1900 1; +BA_ "GenSigCmt" SG_ 1900 TesterPhysicalResCCM "TesterPhysicalResCCM"; +BA_ "GenSigSendType" SG_ 1900 TesterPhysicalResCCM 0; +BA_ "GenMsgSendType" BO_ 261 0; +BA_ "GenMsgCycleTime" BO_ 261 1000; +BA_ "GenMsgNrOfRepetition" BO_ 261 0; +BA_ "GenSigCmt" SG_ 261 CAN_SEQUENCE_NUMBER "CAN_SEQUENCE_NUMBER"; +BA_ "GenSigCmt" SG_ 261 CAN_SERIAL_NUMBER "CAN_SERIAL_NUMBER"; +BA_ "GenSigSendType" SG_ 261 CAN_SERIAL_NUMBER 0; +BA_ "GenMsgSendType" BO_ 264 1; +BA_ "GenMsgNrOfRepetition" BO_ 264 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Field_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Promote_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Field_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Promote_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Release_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Release_Revision 0; +BA_ "GenMsgSendType" BO_ 373 1; +BA_ "NetworkInitialization" BO_ 373 0; +BA_ "GenMsgNrOfRepetition" BO_ 373 0; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_POLARITY 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_POLARITY "CAN_SENSOR_POLARITY"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_LAT_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_LAT_OFFSET "CAN_SENSOR_LAT_OFFSET"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_LONG_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_LONG_OFFSET "CAN_SENSOR_LONG_OFFSET"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_HANGLE_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_HANGLE_OFFSET "CAN_SENSOR_HANGLE_OFFSET"; +BA_ "GenSigStartValue" SG_ 373 CAN_SENSOR_HANGLE_OFFSET 0; +BA_ "GenMsgSendType" BO_ 372 1; +BA_ "NetworkInitialization" BO_ 372 0; +BA_ "GenMsgNrOfRepetition" BO_ 372 0; +BA_ "GenSigSendType" SG_ 372 CAN_SENSOR_FOV_HOR 0; +BA_ "GenSigCmt" SG_ 372 CAN_SENSOR_FOV_HOR "CAN_SENSOR_FOV_HOR"; +BA_ "GenSigStartValue" SG_ 372 CAN_SENSOR_FOV_HOR 0; +BA_ "GenSigSendType" SG_ 372 CAN_DOPPLER_COVERAGE 0; +BA_ "GenSigCmt" SG_ 372 CAN_DOPPLER_COVERAGE "CAN_DOPPLER_COVERAGE"; +BA_ "GenSigStartValue" SG_ 372 CAN_DOPPLER_COVERAGE 0; +BA_ "GenSigSendType" SG_ 372 CAN_RANGE_COVERAGE 0; +BA_ "GenSigCmt" SG_ 372 CAN_RANGE_COVERAGE "CAN_RANGE_COVERAGE"; +BA_ "GenMsgSendType" BO_ 371 1; +BA_ "NetworkInitialization" BO_ 371 0; +BA_ "GenMsgNrOfRepetition" BO_ 371 0; +BA_ "GenSigVtEn" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigVtName" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigVtEn" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigVtName" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigSendType" SG_ 371 CAN_ALIGNMENT_STATUS 0; +BA_ "GenSigCmt" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigVtEn" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigVtName" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigSendType" SG_ 371 CAN_ALIGNMENT_STATE 0; +BA_ "GenSigCmt" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF 0; +BA_ "GenSigStartValue" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF "CAN_AUTO_ALIGN_HANGLE_REF"; +BA_ "GenSigStartValue" SG_ 371 CAN_AUTO_ALIGN_HANGLE 0; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE "CAN_AUTO_ALIGN_HANGLE"; +BA_ "GenMsgSendType" BO_ 369 1; +BA_ "NetworkInitialization" BO_ 369 0; +BA_ "GenMsgNrOfRepetition" BO_ 369 0; +BA_ "GenSigCmt" SG_ 369 CAN_DET_TIME_SINCE_MEAS "CAN_DET_TIME_SINCE_MEAS"; +BA_ "GenSigSendType" SG_ 369 CAN_DET_TIME_SINCE_MEAS 0; +BA_ "GenSigSendType" SG_ 369 CAN_SENSOR_TIME_STAMP 0; +BA_ "GenSigCmt" SG_ 369 CAN_SENSOR_TIME_STAMP "CAN_SENSOR_TIME_STAMP"; +BA_ "GenMsgSendType" BO_ 368 1; +BA_ "NetworkInitialization" BO_ 368 0; +BA_ "GenMsgNrOfRepetition" BO_ 368 0; +BA_ "GenSigSendType" SG_ 368 CAN_ALIGN_UPDATES_DONE 0; +BA_ "GenSigCmt" SG_ 368 CAN_ALIGN_UPDATES_DONE "CAN_ALIGN_UPDATES_DONE"; +BA_ "GenSigSendType" SG_ 368 CAN_SCAN_INDEX 0; +BA_ "GenSigCmt" SG_ 368 CAN_SCAN_INDEX "CAN_SCAN_INDEX"; +BA_ "GenSigSendType" SG_ 368 CAN_NUMBER_OF_DET 0; +BA_ "GenSigCmt" SG_ 368 CAN_NUMBER_OF_DET "CAN_NUMBER_OF_DET"; +BA_ "GenSigSendType" SG_ 368 CAN_LOOK_ID 0; +BA_ "GenSigCmt" SG_ 368 CAN_LOOK_ID "CAN_LOOK_ID"; +BA_ "GenSigSendType" SG_ 368 CAN_LOOK_INDEX 0; +BA_ "GenSigCmt" SG_ 368 CAN_LOOK_INDEX "CAN_LOOK_INDEX"; +BA_ "GenMsgSendType" BO_ 265 1; +BA_ "NetworkInitialization" BO_ 265 0; +BA_ "GenMsgNrOfRepetition" BO_ 265 0; +BA_ "GenSigCmt" SG_ 265 CAN_BATT_VOLTS "CAN_BATT_VOLTS"; +BA_ "GenSigCmt" SG_ 265 CAN_1_25_V "CAN_1_25_V"; +BA_ "GenSigCmt" SG_ 265 CAN_5_V "CAN_5_V"; +BA_ "GenSigCmt" SG_ 265 CAN_3_3_V_RAW "CAN_3_3_V_RAW"; +BA_ "GenSigCmt" SG_ 265 CAN_3_3_V_DAC "CAN_3_3_V_DAC"; +BA_ "GenSigSendType" SG_ 265 CAN_MMIC_Temp1 0; +BA_ "GenSigCmt" SG_ 265 CAN_MMIC_Temp1 "CAN_MMIC_Temp1"; +BA_ "GenSigStartValue" SG_ 265 CAN_MMIC_Temp1 0; +BA_ "GenSigSendType" SG_ 265 CAN_Processor_Thermistor 0; +BA_ "GenSigCmt" SG_ 265 CAN_Processor_Thermistor "CAN_Processor_Thermistor"; +BA_ "GenSigStartValue" SG_ 265 CAN_Processor_Thermistor 0; +BA_ "GenSigSendType" SG_ 265 CAN_Processor_Temp1 0; +BA_ "GenSigCmt" SG_ 265 CAN_Processor_Temp1 "CAN_Processor_Temp1"; +BA_ "GenSigStartValue" SG_ 265 CAN_Processor_Temp1 0; +BA_ "GenMsgSendType" BO_ 291 1; +BA_ "GenMsgILSupport" BO_ 291 1; +BA_ "GenMsgNrOfRepetition" BO_ 291 0; +BA_ "GenMsgCycleTime" BO_ 291 0; +BA_ "NetworkInitialization" BO_ 291 0; +BA_ "GenMsgDelayTime" BO_ 291 0; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04 "CAN_DET_CONFID_AZIMUTH_04"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04 "CAN_DET_CONFID_AZIMUTH_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04 "CAN_DET_CONFID_AZIMUTH_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04 "CAN_DET_SUPER_RES_TARGET_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04 "CAN_DET_ND_TARGET_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04 "CAN_DET_HOST_VEH_CLUTTER_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04 "CAN_DET_VALID_LEVEL_04"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04 "CAN_DET_AZIMUTH_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04 "CAN_DET_RANGE_04"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04 "CAN_DET_RANGE_RATE_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04 "CAN_DET_AMPLITUDE_04"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04 "CAN_SCAN_INDEX_2LSB_04"; +BA_ "GenMsgSendType" BO_ 351 1; +BA_ "GenMsgILSupport" BO_ 351 1; +BA_ "GenMsgNrOfRepetition" BO_ 351 0; +BA_ "GenMsgCycleTime" BO_ 351 0; +BA_ "NetworkInitialization" BO_ 351 0; +BA_ "GenMsgDelayTime" BO_ 351 0; +BA_ "GenSigVtEn" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigVtName" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_SUPER_RES_TARGET_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_SUPER_RES_TARGET_64 "CAN_DET_SUPER_RES_TARGET_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_ND_TARGET_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_ND_TARGET_64 "CAN_DET_ND_TARGET_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_HOST_VEH_CLUTTER_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_HOST_VEH_CLUTTER_64 "CAN_DET_HOST_VEH_CLUTTER_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_VALID_LEVEL_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_VALID_LEVEL_64 "CAN_DET_VALID_LEVEL_64"; +BA_ "GenSigStartValue" SG_ 351 CAN_DET_AZIMUTH_64 0; +BA_ "GenSigSendType" SG_ 351 CAN_DET_AZIMUTH_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_AZIMUTH_64 "CAN_DET_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_RANGE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_RANGE_64 "CAN_DET_RANGE_64"; +BA_ "GenSigStartValue" SG_ 351 CAN_DET_RANGE_RATE_64 0; +BA_ "GenSigSendType" SG_ 351 CAN_DET_RANGE_RATE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_RANGE_RATE_64 "CAN_DET_RANGE_RATE_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_AMPLITUDE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_AMPLITUDE_64 "CAN_DET_AMPLITUDE_64"; +BA_ "GenSigSendType" SG_ 351 CAN_SCAN_INDEX_2LSB_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_SCAN_INDEX_2LSB_64 "CAN_SCAN_INDEX_2LSB_64"; +BA_ "GenMsgSendType" BO_ 350 1; +BA_ "GenMsgILSupport" BO_ 350 1; +BA_ "GenMsgNrOfRepetition" BO_ 350 0; +BA_ "GenMsgCycleTime" BO_ 350 0; +BA_ "NetworkInitialization" BO_ 350 0; +BA_ "GenMsgDelayTime" BO_ 350 0; +BA_ "GenSigVtEn" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigVtName" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_SUPER_RES_TARGET_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_SUPER_RES_TARGET_63 "CAN_DET_SUPER_RES_TARGET_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_ND_TARGET_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_ND_TARGET_63 "CAN_DET_ND_TARGET_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_HOST_VEH_CLUTTER_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_HOST_VEH_CLUTTER_63 "CAN_DET_HOST_VEH_CLUTTER_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_VALID_LEVEL_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_VALID_LEVEL_63 "CAN_DET_VALID_LEVEL_63"; +BA_ "GenSigStartValue" SG_ 350 CAN_DET_AZIMUTH_63 0; +BA_ "GenSigSendType" SG_ 350 CAN_DET_AZIMUTH_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_AZIMUTH_63 "CAN_DET_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_RANGE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_RANGE_63 "CAN_DET_RANGE_63"; +BA_ "GenSigStartValue" SG_ 350 CAN_DET_RANGE_RATE_63 0; +BA_ "GenSigSendType" SG_ 350 CAN_DET_RANGE_RATE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_RANGE_RATE_63 "CAN_DET_RANGE_RATE_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_AMPLITUDE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_AMPLITUDE_63 "CAN_DET_AMPLITUDE_63"; +BA_ "GenSigSendType" SG_ 350 CAN_SCAN_INDEX_2LSB_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_SCAN_INDEX_2LSB_63 "CAN_SCAN_INDEX_2LSB_63"; +BA_ "GenMsgSendType" BO_ 349 1; +BA_ "GenMsgILSupport" BO_ 349 1; +BA_ "GenMsgNrOfRepetition" BO_ 349 0; +BA_ "GenMsgCycleTime" BO_ 349 0; +BA_ "NetworkInitialization" BO_ 349 0; +BA_ "GenMsgDelayTime" BO_ 349 0; +BA_ "GenSigVtEn" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigVtName" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_SUPER_RES_TARGET_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_SUPER_RES_TARGET_62 "CAN_DET_SUPER_RES_TARGET_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_ND_TARGET_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_ND_TARGET_62 "CAN_DET_ND_TARGET_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_HOST_VEH_CLUTTER_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_HOST_VEH_CLUTTER_62 "CAN_DET_HOST_VEH_CLUTTER_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_VALID_LEVEL_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_VALID_LEVEL_62 "CAN_DET_VALID_LEVEL_62"; +BA_ "GenSigStartValue" SG_ 349 CAN_DET_AZIMUTH_62 0; +BA_ "GenSigSendType" SG_ 349 CAN_DET_AZIMUTH_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_AZIMUTH_62 "CAN_DET_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_RANGE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_RANGE_62 "CAN_DET_RANGE_62"; +BA_ "GenSigStartValue" SG_ 349 CAN_DET_RANGE_RATE_62 0; +BA_ "GenSigSendType" SG_ 349 CAN_DET_RANGE_RATE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_RANGE_RATE_62 "CAN_DET_RANGE_RATE_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_AMPLITUDE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_AMPLITUDE_62 "CAN_DET_AMPLITUDE_62"; +BA_ "GenSigSendType" SG_ 349 CAN_SCAN_INDEX_2LSB_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_SCAN_INDEX_2LSB_62 "CAN_SCAN_INDEX_2LSB_62"; +BA_ "GenMsgSendType" BO_ 348 1; +BA_ "GenMsgILSupport" BO_ 348 1; +BA_ "GenMsgNrOfRepetition" BO_ 348 0; +BA_ "GenMsgCycleTime" BO_ 348 0; +BA_ "NetworkInitialization" BO_ 348 0; +BA_ "GenMsgDelayTime" BO_ 348 0; +BA_ "GenSigVtEn" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigVtName" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_SUPER_RES_TARGET_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_SUPER_RES_TARGET_61 "CAN_DET_SUPER_RES_TARGET_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_ND_TARGET_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_ND_TARGET_61 "CAN_DET_ND_TARGET_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_HOST_VEH_CLUTTER_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_HOST_VEH_CLUTTER_61 "CAN_DET_HOST_VEH_CLUTTER_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_VALID_LEVEL_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_VALID_LEVEL_61 "CAN_DET_VALID_LEVEL_61"; +BA_ "GenSigStartValue" SG_ 348 CAN_DET_AZIMUTH_61 0; +BA_ "GenSigSendType" SG_ 348 CAN_DET_AZIMUTH_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_AZIMUTH_61 "CAN_DET_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_RANGE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_RANGE_61 "CAN_DET_RANGE_61"; +BA_ "GenSigStartValue" SG_ 348 CAN_DET_RANGE_RATE_61 0; +BA_ "GenSigSendType" SG_ 348 CAN_DET_RANGE_RATE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_RANGE_RATE_61 "CAN_DET_RANGE_RATE_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_AMPLITUDE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_AMPLITUDE_61 "CAN_DET_AMPLITUDE_61"; +BA_ "GenSigSendType" SG_ 348 CAN_SCAN_INDEX_2LSB_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_SCAN_INDEX_2LSB_61 "CAN_SCAN_INDEX_2LSB_61"; +BA_ "GenMsgSendType" BO_ 347 1; +BA_ "GenMsgILSupport" BO_ 347 1; +BA_ "GenMsgNrOfRepetition" BO_ 347 0; +BA_ "GenMsgCycleTime" BO_ 347 0; +BA_ "NetworkInitialization" BO_ 347 0; +BA_ "GenMsgDelayTime" BO_ 347 0; +BA_ "GenSigVtEn" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigVtName" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_SUPER_RES_TARGET_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_SUPER_RES_TARGET_60 "CAN_DET_SUPER_RES_TARGET_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_ND_TARGET_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_ND_TARGET_60 "CAN_DET_ND_TARGET_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_HOST_VEH_CLUTTER_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_HOST_VEH_CLUTTER_60 "CAN_DET_HOST_VEH_CLUTTER_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_VALID_LEVEL_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_VALID_LEVEL_60 "CAN_DET_VALID_LEVEL_60"; +BA_ "GenSigStartValue" SG_ 347 CAN_DET_AZIMUTH_60 0; +BA_ "GenSigSendType" SG_ 347 CAN_DET_AZIMUTH_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_AZIMUTH_60 "CAN_DET_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_RANGE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_RANGE_60 "CAN_DET_RANGE_60"; +BA_ "GenSigStartValue" SG_ 347 CAN_DET_RANGE_RATE_60 0; +BA_ "GenSigSendType" SG_ 347 CAN_DET_RANGE_RATE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_RANGE_RATE_60 "CAN_DET_RANGE_RATE_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_AMPLITUDE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_AMPLITUDE_60 "CAN_DET_AMPLITUDE_60"; +BA_ "GenSigSendType" SG_ 347 CAN_SCAN_INDEX_2LSB_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_SCAN_INDEX_2LSB_60 "CAN_SCAN_INDEX_2LSB_60"; +BA_ "GenMsgSendType" BO_ 346 1; +BA_ "GenMsgILSupport" BO_ 346 1; +BA_ "GenMsgNrOfRepetition" BO_ 346 0; +BA_ "GenMsgCycleTime" BO_ 346 0; +BA_ "NetworkInitialization" BO_ 346 0; +BA_ "GenMsgDelayTime" BO_ 346 0; +BA_ "GenSigVtEn" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigVtName" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_SUPER_RES_TARGET_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_SUPER_RES_TARGET_59 "CAN_DET_SUPER_RES_TARGET_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_ND_TARGET_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_ND_TARGET_59 "CAN_DET_ND_TARGET_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_HOST_VEH_CLUTTER_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_HOST_VEH_CLUTTER_59 "CAN_DET_HOST_VEH_CLUTTER_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_VALID_LEVEL_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_VALID_LEVEL_59 "CAN_DET_VALID_LEVEL_59"; +BA_ "GenSigStartValue" SG_ 346 CAN_DET_AZIMUTH_59 0; +BA_ "GenSigSendType" SG_ 346 CAN_DET_AZIMUTH_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_AZIMUTH_59 "CAN_DET_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_RANGE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_RANGE_59 "CAN_DET_RANGE_59"; +BA_ "GenSigStartValue" SG_ 346 CAN_DET_RANGE_RATE_59 0; +BA_ "GenSigSendType" SG_ 346 CAN_DET_RANGE_RATE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_RANGE_RATE_59 "CAN_DET_RANGE_RATE_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_AMPLITUDE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_AMPLITUDE_59 "CAN_DET_AMPLITUDE_59"; +BA_ "GenSigSendType" SG_ 346 CAN_SCAN_INDEX_2LSB_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_SCAN_INDEX_2LSB_59 "CAN_SCAN_INDEX_2LSB_59"; +BA_ "GenMsgSendType" BO_ 345 1; +BA_ "GenMsgILSupport" BO_ 345 1; +BA_ "GenMsgNrOfRepetition" BO_ 345 0; +BA_ "GenMsgCycleTime" BO_ 345 0; +BA_ "NetworkInitialization" BO_ 345 0; +BA_ "GenMsgDelayTime" BO_ 345 0; +BA_ "GenSigVtEn" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigVtName" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_SUPER_RES_TARGET_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_SUPER_RES_TARGET_58 "CAN_DET_SUPER_RES_TARGET_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_ND_TARGET_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_ND_TARGET_58 "CAN_DET_ND_TARGET_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_HOST_VEH_CLUTTER_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_HOST_VEH_CLUTTER_58 "CAN_DET_HOST_VEH_CLUTTER_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_VALID_LEVEL_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_VALID_LEVEL_58 "CAN_DET_VALID_LEVEL_58"; +BA_ "GenSigStartValue" SG_ 345 CAN_DET_AZIMUTH_58 0; +BA_ "GenSigSendType" SG_ 345 CAN_DET_AZIMUTH_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_AZIMUTH_58 "CAN_DET_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_RANGE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_RANGE_58 "CAN_DET_RANGE_58"; +BA_ "GenSigStartValue" SG_ 345 CAN_DET_RANGE_RATE_58 0; +BA_ "GenSigSendType" SG_ 345 CAN_DET_RANGE_RATE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_RANGE_RATE_58 "CAN_DET_RANGE_RATE_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_AMPLITUDE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_AMPLITUDE_58 "CAN_DET_AMPLITUDE_58"; +BA_ "GenSigSendType" SG_ 345 CAN_SCAN_INDEX_2LSB_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_SCAN_INDEX_2LSB_58 "CAN_SCAN_INDEX_2LSB_58"; +BA_ "GenMsgSendType" BO_ 344 1; +BA_ "GenMsgILSupport" BO_ 344 1; +BA_ "GenMsgNrOfRepetition" BO_ 344 0; +BA_ "GenMsgCycleTime" BO_ 344 0; +BA_ "NetworkInitialization" BO_ 344 0; +BA_ "GenMsgDelayTime" BO_ 344 0; +BA_ "GenSigVtEn" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigVtName" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_SUPER_RES_TARGET_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_SUPER_RES_TARGET_57 "CAN_DET_SUPER_RES_TARGET_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_ND_TARGET_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_ND_TARGET_57 "CAN_DET_ND_TARGET_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_HOST_VEH_CLUTTER_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_HOST_VEH_CLUTTER_57 "CAN_DET_HOST_VEH_CLUTTER_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_VALID_LEVEL_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_VALID_LEVEL_57 "CAN_DET_VALID_LEVEL_57"; +BA_ "GenSigStartValue" SG_ 344 CAN_DET_AZIMUTH_57 0; +BA_ "GenSigSendType" SG_ 344 CAN_DET_AZIMUTH_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_AZIMUTH_57 "CAN_DET_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_RANGE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_RANGE_57 "CAN_DET_RANGE_57"; +BA_ "GenSigStartValue" SG_ 344 CAN_DET_RANGE_RATE_57 0; +BA_ "GenSigSendType" SG_ 344 CAN_DET_RANGE_RATE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_RANGE_RATE_57 "CAN_DET_RANGE_RATE_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_AMPLITUDE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_AMPLITUDE_57 "CAN_DET_AMPLITUDE_57"; +BA_ "GenSigSendType" SG_ 344 CAN_SCAN_INDEX_2LSB_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_SCAN_INDEX_2LSB_57 "CAN_SCAN_INDEX_2LSB_57"; +BA_ "GenMsgSendType" BO_ 343 1; +BA_ "GenMsgILSupport" BO_ 343 1; +BA_ "GenMsgNrOfRepetition" BO_ 343 0; +BA_ "GenMsgCycleTime" BO_ 343 0; +BA_ "NetworkInitialization" BO_ 343 0; +BA_ "GenMsgDelayTime" BO_ 343 0; +BA_ "GenSigVtEn" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigVtName" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_SUPER_RES_TARGET_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_SUPER_RES_TARGET_56 "CAN_DET_SUPER_RES_TARGET_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_ND_TARGET_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_ND_TARGET_56 "CAN_DET_ND_TARGET_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_HOST_VEH_CLUTTER_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_HOST_VEH_CLUTTER_56 "CAN_DET_HOST_VEH_CLUTTER_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_VALID_LEVEL_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_VALID_LEVEL_56 "CAN_DET_VALID_LEVEL_56"; +BA_ "GenSigStartValue" SG_ 343 CAN_DET_AZIMUTH_56 0; +BA_ "GenSigSendType" SG_ 343 CAN_DET_AZIMUTH_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_AZIMUTH_56 "CAN_DET_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_RANGE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_RANGE_56 "CAN_DET_RANGE_56"; +BA_ "GenSigStartValue" SG_ 343 CAN_DET_RANGE_RATE_56 0; +BA_ "GenSigSendType" SG_ 343 CAN_DET_RANGE_RATE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_RANGE_RATE_56 "CAN_DET_RANGE_RATE_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_AMPLITUDE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_AMPLITUDE_56 "CAN_DET_AMPLITUDE_56"; +BA_ "GenSigSendType" SG_ 343 CAN_SCAN_INDEX_2LSB_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_SCAN_INDEX_2LSB_56 "CAN_SCAN_INDEX_2LSB_56"; +BA_ "GenMsgSendType" BO_ 342 1; +BA_ "GenMsgILSupport" BO_ 342 1; +BA_ "GenMsgNrOfRepetition" BO_ 342 0; +BA_ "GenMsgCycleTime" BO_ 342 0; +BA_ "NetworkInitialization" BO_ 342 0; +BA_ "GenMsgDelayTime" BO_ 342 0; +BA_ "GenSigVtEn" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigVtName" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_SUPER_RES_TARGET_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_SUPER_RES_TARGET_55 "CAN_DET_SUPER_RES_TARGET_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_ND_TARGET_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_ND_TARGET_55 "CAN_DET_ND_TARGET_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_HOST_VEH_CLUTTER_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_HOST_VEH_CLUTTER_55 "CAN_DET_HOST_VEH_CLUTTER_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_VALID_LEVEL_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_VALID_LEVEL_55 "CAN_DET_VALID_LEVEL_55"; +BA_ "GenSigStartValue" SG_ 342 CAN_DET_AZIMUTH_55 0; +BA_ "GenSigSendType" SG_ 342 CAN_DET_AZIMUTH_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_AZIMUTH_55 "CAN_DET_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_RANGE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_RANGE_55 "CAN_DET_RANGE_55"; +BA_ "GenSigStartValue" SG_ 342 CAN_DET_RANGE_RATE_55 0; +BA_ "GenSigSendType" SG_ 342 CAN_DET_RANGE_RATE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_RANGE_RATE_55 "CAN_DET_RANGE_RATE_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_AMPLITUDE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_AMPLITUDE_55 "CAN_DET_AMPLITUDE_55"; +BA_ "GenSigSendType" SG_ 342 CAN_SCAN_INDEX_2LSB_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_SCAN_INDEX_2LSB_55 "CAN_SCAN_INDEX_2LSB_55"; +BA_ "GenMsgSendType" BO_ 335 1; +BA_ "GenMsgILSupport" BO_ 335 1; +BA_ "GenMsgNrOfRepetition" BO_ 335 0; +BA_ "GenMsgCycleTime" BO_ 335 0; +BA_ "NetworkInitialization" BO_ 335 0; +BA_ "GenMsgDelayTime" BO_ 335 0; +BA_ "GenSigVtEn" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigVtName" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_SUPER_RES_TARGET_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_SUPER_RES_TARGET_48 "CAN_DET_SUPER_RES_TARGET_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_ND_TARGET_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_ND_TARGET_48 "CAN_DET_ND_TARGET_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_HOST_VEH_CLUTTER_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_HOST_VEH_CLUTTER_48 "CAN_DET_HOST_VEH_CLUTTER_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_VALID_LEVEL_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_VALID_LEVEL_48 "CAN_DET_VALID_LEVEL_48"; +BA_ "GenSigStartValue" SG_ 335 CAN_DET_AZIMUTH_48 0; +BA_ "GenSigSendType" SG_ 335 CAN_DET_AZIMUTH_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_AZIMUTH_48 "CAN_DET_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_RANGE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_RANGE_48 "CAN_DET_RANGE_48"; +BA_ "GenSigStartValue" SG_ 335 CAN_DET_RANGE_RATE_48 0; +BA_ "GenSigSendType" SG_ 335 CAN_DET_RANGE_RATE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_RANGE_RATE_48 "CAN_DET_RANGE_RATE_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_AMPLITUDE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_AMPLITUDE_48 "CAN_DET_AMPLITUDE_48"; +BA_ "GenSigSendType" SG_ 335 CAN_SCAN_INDEX_2LSB_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_SCAN_INDEX_2LSB_48 "CAN_SCAN_INDEX_2LSB_48"; +BA_ "GenMsgSendType" BO_ 334 1; +BA_ "GenMsgILSupport" BO_ 334 1; +BA_ "GenMsgNrOfRepetition" BO_ 334 0; +BA_ "GenMsgCycleTime" BO_ 334 0; +BA_ "NetworkInitialization" BO_ 334 0; +BA_ "GenMsgDelayTime" BO_ 334 0; +BA_ "GenSigVtEn" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigVtName" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_SUPER_RES_TARGET_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_SUPER_RES_TARGET_47 "CAN_DET_SUPER_RES_TARGET_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_ND_TARGET_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_ND_TARGET_47 "CAN_DET_ND_TARGET_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_HOST_VEH_CLUTTER_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_HOST_VEH_CLUTTER_47 "CAN_DET_HOST_VEH_CLUTTER_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_VALID_LEVEL_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_VALID_LEVEL_47 "CAN_DET_VALID_LEVEL_47"; +BA_ "GenSigStartValue" SG_ 334 CAN_DET_AZIMUTH_47 0; +BA_ "GenSigSendType" SG_ 334 CAN_DET_AZIMUTH_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_AZIMUTH_47 "CAN_DET_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_RANGE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_RANGE_47 "CAN_DET_RANGE_47"; +BA_ "GenSigStartValue" SG_ 334 CAN_DET_RANGE_RATE_47 0; +BA_ "GenSigSendType" SG_ 334 CAN_DET_RANGE_RATE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_RANGE_RATE_47 "CAN_DET_RANGE_RATE_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_AMPLITUDE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_AMPLITUDE_47 "CAN_DET_AMPLITUDE_47"; +BA_ "GenSigSendType" SG_ 334 CAN_SCAN_INDEX_2LSB_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_SCAN_INDEX_2LSB_47 "CAN_SCAN_INDEX_2LSB_47"; +BA_ "GenMsgSendType" BO_ 333 1; +BA_ "GenMsgILSupport" BO_ 333 1; +BA_ "GenMsgNrOfRepetition" BO_ 333 0; +BA_ "GenMsgCycleTime" BO_ 333 0; +BA_ "NetworkInitialization" BO_ 333 0; +BA_ "GenMsgDelayTime" BO_ 333 0; +BA_ "GenSigVtEn" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigVtName" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_SUPER_RES_TARGET_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_SUPER_RES_TARGET_46 "CAN_DET_SUPER_RES_TARGET_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_ND_TARGET_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_ND_TARGET_46 "CAN_DET_ND_TARGET_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_HOST_VEH_CLUTTER_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_HOST_VEH_CLUTTER_46 "CAN_DET_HOST_VEH_CLUTTER_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_VALID_LEVEL_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_VALID_LEVEL_46 "CAN_DET_VALID_LEVEL_46"; +BA_ "GenSigStartValue" SG_ 333 CAN_DET_AZIMUTH_46 0; +BA_ "GenSigSendType" SG_ 333 CAN_DET_AZIMUTH_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_AZIMUTH_46 "CAN_DET_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_RANGE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_RANGE_46 "CAN_DET_RANGE_46"; +BA_ "GenSigStartValue" SG_ 333 CAN_DET_RANGE_RATE_46 0; +BA_ "GenSigSendType" SG_ 333 CAN_DET_RANGE_RATE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_RANGE_RATE_46 "CAN_DET_RANGE_RATE_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_AMPLITUDE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_AMPLITUDE_46 "CAN_DET_AMPLITUDE_46"; +BA_ "GenSigSendType" SG_ 333 CAN_SCAN_INDEX_2LSB_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_SCAN_INDEX_2LSB_46 "CAN_SCAN_INDEX_2LSB_46"; +BA_ "GenMsgSendType" BO_ 332 1; +BA_ "GenMsgILSupport" BO_ 332 1; +BA_ "GenMsgNrOfRepetition" BO_ 332 0; +BA_ "GenMsgCycleTime" BO_ 332 0; +BA_ "NetworkInitialization" BO_ 332 0; +BA_ "GenMsgDelayTime" BO_ 332 0; +BA_ "GenSigVtEn" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigVtName" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_SUPER_RES_TARGET_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_SUPER_RES_TARGET_45 "CAN_DET_SUPER_RES_TARGET_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_ND_TARGET_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_ND_TARGET_45 "CAN_DET_ND_TARGET_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_HOST_VEH_CLUTTER_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_HOST_VEH_CLUTTER_45 "CAN_DET_HOST_VEH_CLUTTER_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_VALID_LEVEL_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_VALID_LEVEL_45 "CAN_DET_VALID_LEVEL_45"; +BA_ "GenSigStartValue" SG_ 332 CAN_DET_AZIMUTH_45 0; +BA_ "GenSigSendType" SG_ 332 CAN_DET_AZIMUTH_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_AZIMUTH_45 "CAN_DET_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_RANGE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_RANGE_45 "CAN_DET_RANGE_45"; +BA_ "GenSigStartValue" SG_ 332 CAN_DET_RANGE_RATE_45 0; +BA_ "GenSigSendType" SG_ 332 CAN_DET_RANGE_RATE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_RANGE_RATE_45 "CAN_DET_RANGE_RATE_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_AMPLITUDE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_AMPLITUDE_45 "CAN_DET_AMPLITUDE_45"; +BA_ "GenSigSendType" SG_ 332 CAN_SCAN_INDEX_2LSB_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_SCAN_INDEX_2LSB_45 "CAN_SCAN_INDEX_2LSB_45"; +BA_ "GenMsgSendType" BO_ 331 1; +BA_ "GenMsgILSupport" BO_ 331 1; +BA_ "GenMsgNrOfRepetition" BO_ 331 0; +BA_ "GenMsgCycleTime" BO_ 331 0; +BA_ "NetworkInitialization" BO_ 331 0; +BA_ "GenMsgDelayTime" BO_ 331 0; +BA_ "GenSigVtEn" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigVtName" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_SUPER_RES_TARGET_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_SUPER_RES_TARGET_44 "CAN_DET_SUPER_RES_TARGET_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_ND_TARGET_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_ND_TARGET_44 "CAN_DET_ND_TARGET_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_HOST_VEH_CLUTTER_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_HOST_VEH_CLUTTER_44 "CAN_DET_HOST_VEH_CLUTTER_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_VALID_LEVEL_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_VALID_LEVEL_44 "CAN_DET_VALID_LEVEL_44"; +BA_ "GenSigStartValue" SG_ 331 CAN_DET_AZIMUTH_44 0; +BA_ "GenSigSendType" SG_ 331 CAN_DET_AZIMUTH_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_AZIMUTH_44 "CAN_DET_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_RANGE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_RANGE_44 "CAN_DET_RANGE_44"; +BA_ "GenSigStartValue" SG_ 331 CAN_DET_RANGE_RATE_44 0; +BA_ "GenSigSendType" SG_ 331 CAN_DET_RANGE_RATE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_RANGE_RATE_44 "CAN_DET_RANGE_RATE_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_AMPLITUDE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_AMPLITUDE_44 "CAN_DET_AMPLITUDE_44"; +BA_ "GenSigSendType" SG_ 331 CAN_SCAN_INDEX_2LSB_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_SCAN_INDEX_2LSB_44 "CAN_SCAN_INDEX_2LSB_44"; +BA_ "GenMsgSendType" BO_ 330 1; +BA_ "GenMsgILSupport" BO_ 330 1; +BA_ "GenMsgNrOfRepetition" BO_ 330 0; +BA_ "GenMsgCycleTime" BO_ 330 0; +BA_ "NetworkInitialization" BO_ 330 0; +BA_ "GenMsgDelayTime" BO_ 330 0; +BA_ "GenSigVtEn" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigVtName" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_SUPER_RES_TARGET_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_SUPER_RES_TARGET_43 "CAN_DET_SUPER_RES_TARGET_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_ND_TARGET_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_ND_TARGET_43 "CAN_DET_ND_TARGET_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_HOST_VEH_CLUTTER_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_HOST_VEH_CLUTTER_43 "CAN_DET_HOST_VEH_CLUTTER_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_VALID_LEVEL_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_VALID_LEVEL_43 "CAN_DET_VALID_LEVEL_43"; +BA_ "GenSigStartValue" SG_ 330 CAN_DET_AZIMUTH_43 0; +BA_ "GenSigSendType" SG_ 330 CAN_DET_AZIMUTH_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_AZIMUTH_43 "CAN_DET_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_RANGE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_RANGE_43 "CAN_DET_RANGE_43"; +BA_ "GenSigStartValue" SG_ 330 CAN_DET_RANGE_RATE_43 0; +BA_ "GenSigSendType" SG_ 330 CAN_DET_RANGE_RATE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_RANGE_RATE_43 "CAN_DET_RANGE_RATE_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_AMPLITUDE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_AMPLITUDE_43 "CAN_DET_AMPLITUDE_43"; +BA_ "GenSigSendType" SG_ 330 CAN_SCAN_INDEX_2LSB_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_SCAN_INDEX_2LSB_43 "CAN_SCAN_INDEX_2LSB_43"; +BA_ "GenMsgSendType" BO_ 329 1; +BA_ "GenMsgILSupport" BO_ 329 1; +BA_ "GenMsgNrOfRepetition" BO_ 329 0; +BA_ "GenMsgCycleTime" BO_ 329 0; +BA_ "NetworkInitialization" BO_ 329 0; +BA_ "GenMsgDelayTime" BO_ 329 0; +BA_ "GenSigVtEn" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigVtName" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_SUPER_RES_TARGET_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_SUPER_RES_TARGET_42 "CAN_DET_SUPER_RES_TARGET_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_ND_TARGET_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_ND_TARGET_42 "CAN_DET_ND_TARGET_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_HOST_VEH_CLUTTER_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_HOST_VEH_CLUTTER_42 "CAN_DET_HOST_VEH_CLUTTER_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_VALID_LEVEL_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_VALID_LEVEL_42 "CAN_DET_VALID_LEVEL_42"; +BA_ "GenSigStartValue" SG_ 329 CAN_DET_AZIMUTH_42 0; +BA_ "GenSigSendType" SG_ 329 CAN_DET_AZIMUTH_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_AZIMUTH_42 "CAN_DET_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_RANGE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_RANGE_42 "CAN_DET_RANGE_42"; +BA_ "GenSigStartValue" SG_ 329 CAN_DET_RANGE_RATE_42 0; +BA_ "GenSigSendType" SG_ 329 CAN_DET_RANGE_RATE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_RANGE_RATE_42 "CAN_DET_RANGE_RATE_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_AMPLITUDE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_AMPLITUDE_42 "CAN_DET_AMPLITUDE_42"; +BA_ "GenSigSendType" SG_ 329 CAN_SCAN_INDEX_2LSB_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_SCAN_INDEX_2LSB_42 "CAN_SCAN_INDEX_2LSB_42"; +BA_ "GenMsgSendType" BO_ 328 1; +BA_ "GenMsgILSupport" BO_ 328 1; +BA_ "GenMsgNrOfRepetition" BO_ 328 0; +BA_ "GenMsgCycleTime" BO_ 328 0; +BA_ "NetworkInitialization" BO_ 328 0; +BA_ "GenMsgDelayTime" BO_ 328 0; +BA_ "GenSigVtEn" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigVtName" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_SUPER_RES_TARGET_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_SUPER_RES_TARGET_41 "CAN_DET_SUPER_RES_TARGET_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_ND_TARGET_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_ND_TARGET_41 "CAN_DET_ND_TARGET_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_HOST_VEH_CLUTTER_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_HOST_VEH_CLUTTER_41 "CAN_DET_HOST_VEH_CLUTTER_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_VALID_LEVEL_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_VALID_LEVEL_41 "CAN_DET_VALID_LEVEL_41"; +BA_ "GenSigStartValue" SG_ 328 CAN_DET_AZIMUTH_41 0; +BA_ "GenSigSendType" SG_ 328 CAN_DET_AZIMUTH_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_AZIMUTH_41 "CAN_DET_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_RANGE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_RANGE_41 "CAN_DET_RANGE_41"; +BA_ "GenSigStartValue" SG_ 328 CAN_DET_RANGE_RATE_41 0; +BA_ "GenSigSendType" SG_ 328 CAN_DET_RANGE_RATE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_RANGE_RATE_41 "CAN_DET_RANGE_RATE_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_AMPLITUDE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_AMPLITUDE_41 "CAN_DET_AMPLITUDE_41"; +BA_ "GenSigSendType" SG_ 328 CAN_SCAN_INDEX_2LSB_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_SCAN_INDEX_2LSB_41 "CAN_SCAN_INDEX_2LSB_41"; +BA_ "GenMsgSendType" BO_ 327 1; +BA_ "GenMsgILSupport" BO_ 327 1; +BA_ "GenMsgNrOfRepetition" BO_ 327 0; +BA_ "GenMsgCycleTime" BO_ 327 0; +BA_ "NetworkInitialization" BO_ 327 0; +BA_ "GenMsgDelayTime" BO_ 327 0; +BA_ "GenSigVtEn" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigVtName" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_SUPER_RES_TARGET_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_SUPER_RES_TARGET_40 "CAN_DET_SUPER_RES_TARGET_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_ND_TARGET_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_ND_TARGET_40 "CAN_DET_ND_TARGET_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_HOST_VEH_CLUTTER_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_HOST_VEH_CLUTTER_40 "CAN_DET_HOST_VEH_CLUTTER_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_VALID_LEVEL_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_VALID_LEVEL_40 "CAN_DET_VALID_LEVEL_40"; +BA_ "GenSigStartValue" SG_ 327 CAN_DET_AZIMUTH_40 0; +BA_ "GenSigSendType" SG_ 327 CAN_DET_AZIMUTH_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_AZIMUTH_40 "CAN_DET_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_RANGE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_RANGE_40 "CAN_DET_RANGE_40"; +BA_ "GenSigStartValue" SG_ 327 CAN_DET_RANGE_RATE_40 0; +BA_ "GenSigSendType" SG_ 327 CAN_DET_RANGE_RATE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_RANGE_RATE_40 "CAN_DET_RANGE_RATE_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_AMPLITUDE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_AMPLITUDE_40 "CAN_DET_AMPLITUDE_40"; +BA_ "GenSigSendType" SG_ 327 CAN_SCAN_INDEX_2LSB_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_SCAN_INDEX_2LSB_40 "CAN_SCAN_INDEX_2LSB_40"; +BA_ "GenMsgSendType" BO_ 325 1; +BA_ "GenMsgILSupport" BO_ 325 1; +BA_ "GenMsgNrOfRepetition" BO_ 325 0; +BA_ "GenMsgCycleTime" BO_ 325 0; +BA_ "NetworkInitialization" BO_ 325 0; +BA_ "GenMsgDelayTime" BO_ 325 0; +BA_ "GenSigVtEn" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigVtName" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_SUPER_RES_TARGET_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_SUPER_RES_TARGET_38 "CAN_DET_SUPER_RES_TARGET_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_ND_TARGET_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_ND_TARGET_38 "CAN_DET_ND_TARGET_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_HOST_VEH_CLUTTER_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_HOST_VEH_CLUTTER_38 "CAN_DET_HOST_VEH_CLUTTER_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_VALID_LEVEL_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_VALID_LEVEL_38 "CAN_DET_VALID_LEVEL_38"; +BA_ "GenSigStartValue" SG_ 325 CAN_DET_AZIMUTH_38 0; +BA_ "GenSigSendType" SG_ 325 CAN_DET_AZIMUTH_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_AZIMUTH_38 "CAN_DET_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_RANGE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_RANGE_38 "CAN_DET_RANGE_38"; +BA_ "GenSigStartValue" SG_ 325 CAN_DET_RANGE_RATE_38 0; +BA_ "GenSigSendType" SG_ 325 CAN_DET_RANGE_RATE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_RANGE_RATE_38 "CAN_DET_RANGE_RATE_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_AMPLITUDE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_AMPLITUDE_38 "CAN_DET_AMPLITUDE_38"; +BA_ "GenSigSendType" SG_ 325 CAN_SCAN_INDEX_2LSB_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_SCAN_INDEX_2LSB_38 "CAN_SCAN_INDEX_2LSB_38"; +BA_ "GenMsgSendType" BO_ 324 1; +BA_ "GenMsgILSupport" BO_ 324 1; +BA_ "GenMsgNrOfRepetition" BO_ 324 0; +BA_ "GenMsgCycleTime" BO_ 324 0; +BA_ "NetworkInitialization" BO_ 324 0; +BA_ "GenMsgDelayTime" BO_ 324 0; +BA_ "GenSigVtEn" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigVtName" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_SUPER_RES_TARGET_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_SUPER_RES_TARGET_37 "CAN_DET_SUPER_RES_TARGET_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_ND_TARGET_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_ND_TARGET_37 "CAN_DET_ND_TARGET_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_HOST_VEH_CLUTTER_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_HOST_VEH_CLUTTER_37 "CAN_DET_HOST_VEH_CLUTTER_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_VALID_LEVEL_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_VALID_LEVEL_37 "CAN_DET_VALID_LEVEL_37"; +BA_ "GenSigStartValue" SG_ 324 CAN_DET_AZIMUTH_37 0; +BA_ "GenSigSendType" SG_ 324 CAN_DET_AZIMUTH_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_AZIMUTH_37 "CAN_DET_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_RANGE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_RANGE_37 "CAN_DET_RANGE_37"; +BA_ "GenSigStartValue" SG_ 324 CAN_DET_RANGE_RATE_37 0; +BA_ "GenSigSendType" SG_ 324 CAN_DET_RANGE_RATE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_RANGE_RATE_37 "CAN_DET_RANGE_RATE_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_AMPLITUDE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_AMPLITUDE_37 "CAN_DET_AMPLITUDE_37"; +BA_ "GenSigSendType" SG_ 324 CAN_SCAN_INDEX_2LSB_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_SCAN_INDEX_2LSB_37 "CAN_SCAN_INDEX_2LSB_37"; +BA_ "GenMsgSendType" BO_ 323 1; +BA_ "GenMsgILSupport" BO_ 323 1; +BA_ "GenMsgNrOfRepetition" BO_ 323 0; +BA_ "GenMsgCycleTime" BO_ 323 0; +BA_ "NetworkInitialization" BO_ 323 0; +BA_ "GenMsgDelayTime" BO_ 323 0; +BA_ "GenSigVtEn" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigVtName" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_SUPER_RES_TARGET_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_SUPER_RES_TARGET_36 "CAN_DET_SUPER_RES_TARGET_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_ND_TARGET_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_ND_TARGET_36 "CAN_DET_ND_TARGET_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_HOST_VEH_CLUTTER_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_HOST_VEH_CLUTTER_36 "CAN_DET_HOST_VEH_CLUTTER_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_VALID_LEVEL_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_VALID_LEVEL_36 "CAN_DET_VALID_LEVEL_36"; +BA_ "GenSigStartValue" SG_ 323 CAN_DET_AZIMUTH_36 0; +BA_ "GenSigSendType" SG_ 323 CAN_DET_AZIMUTH_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_AZIMUTH_36 "CAN_DET_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_RANGE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_RANGE_36 "CAN_DET_RANGE_36"; +BA_ "GenSigStartValue" SG_ 323 CAN_DET_RANGE_RATE_36 0; +BA_ "GenSigSendType" SG_ 323 CAN_DET_RANGE_RATE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_RANGE_RATE_36 "CAN_DET_RANGE_RATE_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_AMPLITUDE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_AMPLITUDE_36 "CAN_DET_AMPLITUDE_36"; +BA_ "GenSigSendType" SG_ 323 CAN_SCAN_INDEX_2LSB_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_SCAN_INDEX_2LSB_36 "CAN_SCAN_INDEX_2LSB_36"; +BA_ "GenMsgSendType" BO_ 322 1; +BA_ "GenMsgILSupport" BO_ 322 1; +BA_ "GenMsgNrOfRepetition" BO_ 322 0; +BA_ "GenMsgCycleTime" BO_ 322 0; +BA_ "NetworkInitialization" BO_ 322 0; +BA_ "GenMsgDelayTime" BO_ 322 0; +BA_ "GenSigVtEn" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigVtName" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_SUPER_RES_TARGET_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_SUPER_RES_TARGET_35 "CAN_DET_SUPER_RES_TARGET_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_ND_TARGET_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_ND_TARGET_35 "CAN_DET_ND_TARGET_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_HOST_VEH_CLUTTER_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_HOST_VEH_CLUTTER_35 "CAN_DET_HOST_VEH_CLUTTER_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_VALID_LEVEL_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_VALID_LEVEL_35 "CAN_DET_VALID_LEVEL_35"; +BA_ "GenSigStartValue" SG_ 322 CAN_DET_AZIMUTH_35 0; +BA_ "GenSigSendType" SG_ 322 CAN_DET_AZIMUTH_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_AZIMUTH_35 "CAN_DET_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_RANGE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_RANGE_35 "CAN_DET_RANGE_35"; +BA_ "GenSigStartValue" SG_ 322 CAN_DET_RANGE_RATE_35 0; +BA_ "GenSigSendType" SG_ 322 CAN_DET_RANGE_RATE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_RANGE_RATE_35 "CAN_DET_RANGE_RATE_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_AMPLITUDE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_AMPLITUDE_35 "CAN_DET_AMPLITUDE_35"; +BA_ "GenSigSendType" SG_ 322 CAN_SCAN_INDEX_2LSB_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_SCAN_INDEX_2LSB_35 "CAN_SCAN_INDEX_2LSB_35"; +BA_ "GenMsgSendType" BO_ 321 1; +BA_ "GenMsgILSupport" BO_ 321 1; +BA_ "GenMsgNrOfRepetition" BO_ 321 0; +BA_ "GenMsgCycleTime" BO_ 321 0; +BA_ "NetworkInitialization" BO_ 321 0; +BA_ "GenMsgDelayTime" BO_ 321 0; +BA_ "GenSigVtEn" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigVtName" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_SUPER_RES_TARGET_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_SUPER_RES_TARGET_34 "CAN_DET_SUPER_RES_TARGET_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_ND_TARGET_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_ND_TARGET_34 "CAN_DET_ND_TARGET_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_HOST_VEH_CLUTTER_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_HOST_VEH_CLUTTER_34 "CAN_DET_HOST_VEH_CLUTTER_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_VALID_LEVEL_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_VALID_LEVEL_34 "CAN_DET_VALID_LEVEL_34"; +BA_ "GenSigStartValue" SG_ 321 CAN_DET_AZIMUTH_34 0; +BA_ "GenSigSendType" SG_ 321 CAN_DET_AZIMUTH_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_AZIMUTH_34 "CAN_DET_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_RANGE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_RANGE_34 "CAN_DET_RANGE_34"; +BA_ "GenSigStartValue" SG_ 321 CAN_DET_RANGE_RATE_34 0; +BA_ "GenSigSendType" SG_ 321 CAN_DET_RANGE_RATE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_RANGE_RATE_34 "CAN_DET_RANGE_RATE_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_AMPLITUDE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_AMPLITUDE_34 "CAN_DET_AMPLITUDE_34"; +BA_ "GenSigSendType" SG_ 321 CAN_SCAN_INDEX_2LSB_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_SCAN_INDEX_2LSB_34 "CAN_SCAN_INDEX_2LSB_34"; +BA_ "GenMsgSendType" BO_ 320 1; +BA_ "GenMsgILSupport" BO_ 320 1; +BA_ "GenMsgNrOfRepetition" BO_ 320 0; +BA_ "GenMsgCycleTime" BO_ 320 0; +BA_ "NetworkInitialization" BO_ 320 0; +BA_ "GenMsgDelayTime" BO_ 320 0; +BA_ "GenSigVtEn" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigVtName" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_SUPER_RES_TARGET_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_SUPER_RES_TARGET_33 "CAN_DET_SUPER_RES_TARGET_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_ND_TARGET_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_ND_TARGET_33 "CAN_DET_ND_TARGET_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_HOST_VEH_CLUTTER_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_HOST_VEH_CLUTTER_33 "CAN_DET_HOST_VEH_CLUTTER_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_VALID_LEVEL_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_VALID_LEVEL_33 "CAN_DET_VALID_LEVEL_33"; +BA_ "GenSigStartValue" SG_ 320 CAN_DET_AZIMUTH_33 0; +BA_ "GenSigSendType" SG_ 320 CAN_DET_AZIMUTH_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_AZIMUTH_33 "CAN_DET_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_RANGE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_RANGE_33 "CAN_DET_RANGE_33"; +BA_ "GenSigStartValue" SG_ 320 CAN_DET_RANGE_RATE_33 0; +BA_ "GenSigSendType" SG_ 320 CAN_DET_RANGE_RATE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_RANGE_RATE_33 "CAN_DET_RANGE_RATE_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_AMPLITUDE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_AMPLITUDE_33 "CAN_DET_AMPLITUDE_33"; +BA_ "GenSigSendType" SG_ 320 CAN_SCAN_INDEX_2LSB_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_SCAN_INDEX_2LSB_33 "CAN_SCAN_INDEX_2LSB_33"; +BA_ "GenMsgSendType" BO_ 319 1; +BA_ "GenMsgILSupport" BO_ 319 1; +BA_ "GenMsgNrOfRepetition" BO_ 319 0; +BA_ "GenMsgCycleTime" BO_ 319 0; +BA_ "NetworkInitialization" BO_ 319 0; +BA_ "GenMsgDelayTime" BO_ 319 0; +BA_ "GenSigVtEn" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigVtName" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_SUPER_RES_TARGET_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_SUPER_RES_TARGET_32 "CAN_DET_SUPER_RES_TARGET_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_ND_TARGET_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_ND_TARGET_32 "CAN_DET_ND_TARGET_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_HOST_VEH_CLUTTER_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_HOST_VEH_CLUTTER_32 "CAN_DET_HOST_VEH_CLUTTER_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_VALID_LEVEL_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_VALID_LEVEL_32 "CAN_DET_VALID_LEVEL_32"; +BA_ "GenSigStartValue" SG_ 319 CAN_DET_AZIMUTH_32 0; +BA_ "GenSigSendType" SG_ 319 CAN_DET_AZIMUTH_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_AZIMUTH_32 "CAN_DET_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_RANGE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_RANGE_32 "CAN_DET_RANGE_32"; +BA_ "GenSigStartValue" SG_ 319 CAN_DET_RANGE_RATE_32 0; +BA_ "GenSigSendType" SG_ 319 CAN_DET_RANGE_RATE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_RANGE_RATE_32 "CAN_DET_RANGE_RATE_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_AMPLITUDE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_AMPLITUDE_32 "CAN_DET_AMPLITUDE_32"; +BA_ "GenSigSendType" SG_ 319 CAN_SCAN_INDEX_2LSB_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_SCAN_INDEX_2LSB_32 "CAN_SCAN_INDEX_2LSB_32"; +BA_ "GenMsgSendType" BO_ 318 1; +BA_ "GenMsgILSupport" BO_ 318 1; +BA_ "GenMsgNrOfRepetition" BO_ 318 0; +BA_ "GenMsgCycleTime" BO_ 318 0; +BA_ "NetworkInitialization" BO_ 318 0; +BA_ "GenMsgDelayTime" BO_ 318 0; +BA_ "GenSigVtEn" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigVtName" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_SUPER_RES_TARGET_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_SUPER_RES_TARGET_31 "CAN_DET_SUPER_RES_TARGET_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_ND_TARGET_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_ND_TARGET_31 "CAN_DET_ND_TARGET_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_HOST_VEH_CLUTTER_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_HOST_VEH_CLUTTER_31 "CAN_DET_HOST_VEH_CLUTTER_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_VALID_LEVEL_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_VALID_LEVEL_31 "CAN_DET_VALID_LEVEL_31"; +BA_ "GenSigStartValue" SG_ 318 CAN_DET_AZIMUTH_31 0; +BA_ "GenSigSendType" SG_ 318 CAN_DET_AZIMUTH_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_AZIMUTH_31 "CAN_DET_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_RANGE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_RANGE_31 "CAN_DET_RANGE_31"; +BA_ "GenSigStartValue" SG_ 318 CAN_DET_RANGE_RATE_31 0; +BA_ "GenSigSendType" SG_ 318 CAN_DET_RANGE_RATE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_RANGE_RATE_31 "CAN_DET_RANGE_RATE_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_AMPLITUDE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_AMPLITUDE_31 "CAN_DET_AMPLITUDE_31"; +BA_ "GenSigSendType" SG_ 318 CAN_SCAN_INDEX_2LSB_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_SCAN_INDEX_2LSB_31 "CAN_SCAN_INDEX_2LSB_31"; +BA_ "GenMsgSendType" BO_ 317 1; +BA_ "GenMsgILSupport" BO_ 317 1; +BA_ "GenMsgNrOfRepetition" BO_ 317 0; +BA_ "GenMsgCycleTime" BO_ 317 0; +BA_ "NetworkInitialization" BO_ 317 0; +BA_ "GenMsgDelayTime" BO_ 317 0; +BA_ "GenSigVtEn" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigVtName" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_SUPER_RES_TARGET_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_SUPER_RES_TARGET_30 "CAN_DET_SUPER_RES_TARGET_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_ND_TARGET_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_ND_TARGET_30 "CAN_DET_ND_TARGET_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_HOST_VEH_CLUTTER_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_HOST_VEH_CLUTTER_30 "CAN_DET_HOST_VEH_CLUTTER_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_VALID_LEVEL_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_VALID_LEVEL_30 "CAN_DET_VALID_LEVEL_30"; +BA_ "GenSigStartValue" SG_ 317 CAN_DET_AZIMUTH_30 0; +BA_ "GenSigSendType" SG_ 317 CAN_DET_AZIMUTH_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_AZIMUTH_30 "CAN_DET_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_RANGE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_RANGE_30 "CAN_DET_RANGE_30"; +BA_ "GenSigStartValue" SG_ 317 CAN_DET_RANGE_RATE_30 0; +BA_ "GenSigSendType" SG_ 317 CAN_DET_RANGE_RATE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_RANGE_RATE_30 "CAN_DET_RANGE_RATE_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_AMPLITUDE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_AMPLITUDE_30 "CAN_DET_AMPLITUDE_30"; +BA_ "GenSigSendType" SG_ 317 CAN_SCAN_INDEX_2LSB_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_SCAN_INDEX_2LSB_30 "CAN_SCAN_INDEX_2LSB_30"; +BA_ "GenMsgSendType" BO_ 316 1; +BA_ "GenMsgILSupport" BO_ 316 1; +BA_ "GenMsgNrOfRepetition" BO_ 316 0; +BA_ "GenMsgCycleTime" BO_ 316 0; +BA_ "NetworkInitialization" BO_ 316 0; +BA_ "GenMsgDelayTime" BO_ 316 0; +BA_ "GenSigVtEn" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigVtName" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_SUPER_RES_TARGET_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_SUPER_RES_TARGET_29 "CAN_DET_SUPER_RES_TARGET_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_ND_TARGET_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_ND_TARGET_29 "CAN_DET_ND_TARGET_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_HOST_VEH_CLUTTER_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_HOST_VEH_CLUTTER_29 "CAN_DET_HOST_VEH_CLUTTER_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_VALID_LEVEL_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_VALID_LEVEL_29 "CAN_DET_VALID_LEVEL_29"; +BA_ "GenSigStartValue" SG_ 316 CAN_DET_AZIMUTH_29 0; +BA_ "GenSigSendType" SG_ 316 CAN_DET_AZIMUTH_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_AZIMUTH_29 "CAN_DET_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_RANGE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_RANGE_29 "CAN_DET_RANGE_29"; +BA_ "GenSigStartValue" SG_ 316 CAN_DET_RANGE_RATE_29 0; +BA_ "GenSigSendType" SG_ 316 CAN_DET_RANGE_RATE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_RANGE_RATE_29 "CAN_DET_RANGE_RATE_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_AMPLITUDE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_AMPLITUDE_29 "CAN_DET_AMPLITUDE_29"; +BA_ "GenSigSendType" SG_ 316 CAN_SCAN_INDEX_2LSB_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_SCAN_INDEX_2LSB_29 "CAN_SCAN_INDEX_2LSB_29"; +BA_ "GenMsgSendType" BO_ 314 1; +BA_ "GenMsgILSupport" BO_ 314 1; +BA_ "GenMsgNrOfRepetition" BO_ 314 0; +BA_ "GenMsgCycleTime" BO_ 314 0; +BA_ "NetworkInitialization" BO_ 314 0; +BA_ "GenMsgDelayTime" BO_ 314 0; +BA_ "GenSigVtEn" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigVtName" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_SUPER_RES_TARGET_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_SUPER_RES_TARGET_27 "CAN_DET_SUPER_RES_TARGET_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_ND_TARGET_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_ND_TARGET_27 "CAN_DET_ND_TARGET_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_HOST_VEH_CLUTTER_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_HOST_VEH_CLUTTER_27 "CAN_DET_HOST_VEH_CLUTTER_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_VALID_LEVEL_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_VALID_LEVEL_27 "CAN_DET_VALID_LEVEL_27"; +BA_ "GenSigStartValue" SG_ 314 CAN_DET_AZIMUTH_27 0; +BA_ "GenSigSendType" SG_ 314 CAN_DET_AZIMUTH_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_AZIMUTH_27 "CAN_DET_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_RANGE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_RANGE_27 "CAN_DET_RANGE_27"; +BA_ "GenSigStartValue" SG_ 314 CAN_DET_RANGE_RATE_27 0; +BA_ "GenSigSendType" SG_ 314 CAN_DET_RANGE_RATE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_RANGE_RATE_27 "CAN_DET_RANGE_RATE_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_AMPLITUDE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_AMPLITUDE_27 "CAN_DET_AMPLITUDE_27"; +BA_ "GenSigSendType" SG_ 314 CAN_SCAN_INDEX_2LSB_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_SCAN_INDEX_2LSB_27 "CAN_SCAN_INDEX_2LSB_27"; +BA_ "GenMsgSendType" BO_ 313 1; +BA_ "GenMsgILSupport" BO_ 313 1; +BA_ "GenMsgNrOfRepetition" BO_ 313 0; +BA_ "GenMsgCycleTime" BO_ 313 0; +BA_ "NetworkInitialization" BO_ 313 0; +BA_ "GenMsgDelayTime" BO_ 313 0; +BA_ "GenSigVtEn" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigVtName" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_SUPER_RES_TARGET_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_SUPER_RES_TARGET_26 "CAN_DET_SUPER_RES_TARGET_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_ND_TARGET_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_ND_TARGET_26 "CAN_DET_ND_TARGET_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_HOST_VEH_CLUTTER_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_HOST_VEH_CLUTTER_26 "CAN_DET_HOST_VEH_CLUTTER_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_VALID_LEVEL_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_VALID_LEVEL_26 "CAN_DET_VALID_LEVEL_26"; +BA_ "GenSigStartValue" SG_ 313 CAN_DET_AZIMUTH_26 0; +BA_ "GenSigSendType" SG_ 313 CAN_DET_AZIMUTH_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_AZIMUTH_26 "CAN_DET_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_RANGE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_RANGE_26 "CAN_DET_RANGE_26"; +BA_ "GenSigStartValue" SG_ 313 CAN_DET_RANGE_RATE_26 0; +BA_ "GenSigSendType" SG_ 313 CAN_DET_RANGE_RATE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_RANGE_RATE_26 "CAN_DET_RANGE_RATE_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_AMPLITUDE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_AMPLITUDE_26 "CAN_DET_AMPLITUDE_26"; +BA_ "GenSigSendType" SG_ 313 CAN_SCAN_INDEX_2LSB_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_SCAN_INDEX_2LSB_26 "CAN_SCAN_INDEX_2LSB_26"; +BA_ "GenMsgSendType" BO_ 312 1; +BA_ "GenMsgILSupport" BO_ 312 1; +BA_ "GenMsgNrOfRepetition" BO_ 312 0; +BA_ "GenMsgCycleTime" BO_ 312 0; +BA_ "NetworkInitialization" BO_ 312 0; +BA_ "GenMsgDelayTime" BO_ 312 0; +BA_ "GenSigVtEn" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigVtName" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_SUPER_RES_TARGET_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_SUPER_RES_TARGET_25 "CAN_DET_SUPER_RES_TARGET_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_ND_TARGET_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_ND_TARGET_25 "CAN_DET_ND_TARGET_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_HOST_VEH_CLUTTER_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_HOST_VEH_CLUTTER_25 "CAN_DET_HOST_VEH_CLUTTER_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_VALID_LEVEL_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_VALID_LEVEL_25 "CAN_DET_VALID_LEVEL_25"; +BA_ "GenSigStartValue" SG_ 312 CAN_DET_AZIMUTH_25 0; +BA_ "GenSigSendType" SG_ 312 CAN_DET_AZIMUTH_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_AZIMUTH_25 "CAN_DET_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_RANGE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_RANGE_25 "CAN_DET_RANGE_25"; +BA_ "GenSigStartValue" SG_ 312 CAN_DET_RANGE_RATE_25 0; +BA_ "GenSigSendType" SG_ 312 CAN_DET_RANGE_RATE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_RANGE_RATE_25 "CAN_DET_RANGE_RATE_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_AMPLITUDE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_AMPLITUDE_25 "CAN_DET_AMPLITUDE_25"; +BA_ "GenSigSendType" SG_ 312 CAN_SCAN_INDEX_2LSB_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_SCAN_INDEX_2LSB_25 "CAN_SCAN_INDEX_2LSB_25"; +BA_ "GenMsgSendType" BO_ 311 1; +BA_ "GenMsgILSupport" BO_ 311 1; +BA_ "GenMsgNrOfRepetition" BO_ 311 0; +BA_ "GenMsgCycleTime" BO_ 311 0; +BA_ "NetworkInitialization" BO_ 311 0; +BA_ "GenMsgDelayTime" BO_ 311 0; +BA_ "GenSigVtEn" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigVtName" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_SUPER_RES_TARGET_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_SUPER_RES_TARGET_24 "CAN_DET_SUPER_RES_TARGET_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_ND_TARGET_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_ND_TARGET_24 "CAN_DET_ND_TARGET_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_HOST_VEH_CLUTTER_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_HOST_VEH_CLUTTER_24 "CAN_DET_HOST_VEH_CLUTTER_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_VALID_LEVEL_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_VALID_LEVEL_24 "CAN_DET_VALID_LEVEL_24"; +BA_ "GenSigStartValue" SG_ 311 CAN_DET_AZIMUTH_24 0; +BA_ "GenSigSendType" SG_ 311 CAN_DET_AZIMUTH_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_AZIMUTH_24 "CAN_DET_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_RANGE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_RANGE_24 "CAN_DET_RANGE_24"; +BA_ "GenSigStartValue" SG_ 311 CAN_DET_RANGE_RATE_24 0; +BA_ "GenSigSendType" SG_ 311 CAN_DET_RANGE_RATE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_RANGE_RATE_24 "CAN_DET_RANGE_RATE_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_AMPLITUDE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_AMPLITUDE_24 "CAN_DET_AMPLITUDE_24"; +BA_ "GenSigSendType" SG_ 311 CAN_SCAN_INDEX_2LSB_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_SCAN_INDEX_2LSB_24 "CAN_SCAN_INDEX_2LSB_24"; +BA_ "GenMsgSendType" BO_ 310 1; +BA_ "GenMsgILSupport" BO_ 310 1; +BA_ "GenMsgNrOfRepetition" BO_ 310 0; +BA_ "GenMsgCycleTime" BO_ 310 0; +BA_ "NetworkInitialization" BO_ 310 0; +BA_ "GenMsgDelayTime" BO_ 310 0; +BA_ "GenSigVtEn" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigVtName" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_SUPER_RES_TARGET_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_SUPER_RES_TARGET_23 "CAN_DET_SUPER_RES_TARGET_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_ND_TARGET_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_ND_TARGET_23 "CAN_DET_ND_TARGET_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_HOST_VEH_CLUTTER_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_HOST_VEH_CLUTTER_23 "CAN_DET_HOST_VEH_CLUTTER_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_VALID_LEVEL_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_VALID_LEVEL_23 "CAN_DET_VALID_LEVEL_23"; +BA_ "GenSigStartValue" SG_ 310 CAN_DET_AZIMUTH_23 0; +BA_ "GenSigSendType" SG_ 310 CAN_DET_AZIMUTH_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_AZIMUTH_23 "CAN_DET_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_RANGE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_RANGE_23 "CAN_DET_RANGE_23"; +BA_ "GenSigStartValue" SG_ 310 CAN_DET_RANGE_RATE_23 0; +BA_ "GenSigSendType" SG_ 310 CAN_DET_RANGE_RATE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_RANGE_RATE_23 "CAN_DET_RANGE_RATE_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_AMPLITUDE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_AMPLITUDE_23 "CAN_DET_AMPLITUDE_23"; +BA_ "GenSigSendType" SG_ 310 CAN_SCAN_INDEX_2LSB_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_SCAN_INDEX_2LSB_23 "CAN_SCAN_INDEX_2LSB_23"; +BA_ "GenMsgSendType" BO_ 309 1; +BA_ "GenMsgILSupport" BO_ 309 1; +BA_ "GenMsgNrOfRepetition" BO_ 309 0; +BA_ "GenMsgCycleTime" BO_ 309 0; +BA_ "NetworkInitialization" BO_ 309 0; +BA_ "GenMsgDelayTime" BO_ 309 0; +BA_ "GenSigVtEn" SG_ 309 CAN_DET_CONFID_AZIMUTH_22 "CAN_DET_CONFID_AZIMUTH_22"; +BA_ "GenSigVtName" SG_ 309 CAN_DET_CONFID_AZIMUTH_22 "CAN_DET_CONFID_AZIMUTH_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_CONFID_AZIMUTH_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_CONFID_AZIMUTH_22 "CAN_DET_CONFID_AZIMUTH_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_SUPER_RES_TARGET_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_SUPER_RES_TARGET_22 "CAN_DET_SUPER_RES_TARGET_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_ND_TARGET_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_ND_TARGET_22 "CAN_DET_ND_TARGET_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22 "CAN_DET_HOST_VEH_CLUTTER_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_VALID_LEVEL_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_VALID_LEVEL_22 "CAN_DET_VALID_LEVEL_22"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_AZIMUTH_22 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AZIMUTH_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AZIMUTH_22 "CAN_DET_AZIMUTH_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_22 "CAN_DET_RANGE_22"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_RANGE_RATE_22 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_RATE_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_RATE_22 "CAN_DET_RANGE_RATE_22"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AMPLITUDE_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AMPLITUDE_22 "CAN_DET_AMPLITUDE_22"; +BA_ "GenSigSendType" SG_ 309 CAN_SCAN_INDEX_2LSB_22 0; +BA_ "GenSigCmt" SG_ 309 CAN_SCAN_INDEX_2LSB_22 "CAN_SCAN_INDEX_2LSB_22"; +BA_ "GenMsgSendType" BO_ 308 1; +BA_ "GenMsgILSupport" BO_ 308 1; +BA_ "GenMsgNrOfRepetition" BO_ 308 0; +BA_ "GenMsgCycleTime" BO_ 308 0; +BA_ "NetworkInitialization" BO_ 308 0; +BA_ "GenMsgDelayTime" BO_ 308 0; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21 "CAN_DET_CONFID_AZIMUTH_21"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21 "CAN_DET_CONFID_AZIMUTH_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21 "CAN_DET_CONFID_AZIMUTH_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21 "CAN_DET_SUPER_RES_TARGET_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21 "CAN_DET_ND_TARGET_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21 "CAN_DET_HOST_VEH_CLUTTER_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21 "CAN_DET_VALID_LEVEL_21"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21 "CAN_DET_AZIMUTH_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21 "CAN_DET_RANGE_21"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21 "CAN_DET_RANGE_RATE_21"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21 "CAN_DET_AMPLITUDE_21"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21 "CAN_SCAN_INDEX_2LSB_21"; +BA_ "GenMsgSendType" BO_ 307 1; +BA_ "GenMsgILSupport" BO_ 307 1; +BA_ "GenMsgNrOfRepetition" BO_ 307 0; +BA_ "GenMsgCycleTime" BO_ 307 0; +BA_ "NetworkInitialization" BO_ 307 0; +BA_ "GenMsgDelayTime" BO_ 307 0; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20 "CAN_DET_CONFID_AZIMUTH_20"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20 "CAN_DET_CONFID_AZIMUTH_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20 "CAN_DET_CONFID_AZIMUTH_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20 "CAN_DET_SUPER_RES_TARGET_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20 "CAN_DET_ND_TARGET_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20 "CAN_DET_HOST_VEH_CLUTTER_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20 "CAN_DET_VALID_LEVEL_20"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20 "CAN_DET_AZIMUTH_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20 "CAN_DET_RANGE_20"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20 "CAN_DET_RANGE_RATE_20"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20 "CAN_DET_AMPLITUDE_20"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20 "CAN_SCAN_INDEX_2LSB_20"; +BA_ "GenMsgSendType" BO_ 306 1; +BA_ "GenMsgILSupport" BO_ 306 1; +BA_ "GenMsgNrOfRepetition" BO_ 306 0; +BA_ "GenMsgCycleTime" BO_ 306 0; +BA_ "NetworkInitialization" BO_ 306 0; +BA_ "GenMsgDelayTime" BO_ 306 0; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19 "CAN_DET_CONFID_AZIMUTH_19"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19 "CAN_DET_CONFID_AZIMUTH_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19 "CAN_DET_CONFID_AZIMUTH_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19 "CAN_DET_SUPER_RES_TARGET_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19 "CAN_DET_ND_TARGET_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19 "CAN_DET_HOST_VEH_CLUTTER_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19 "CAN_DET_VALID_LEVEL_19"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19 "CAN_DET_AZIMUTH_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19 "CAN_DET_RANGE_19"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19 "CAN_DET_RANGE_RATE_19"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19 "CAN_DET_AMPLITUDE_19"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19 "CAN_SCAN_INDEX_2LSB_19"; +BA_ "GenMsgSendType" BO_ 305 1; +BA_ "GenMsgILSupport" BO_ 305 1; +BA_ "GenMsgNrOfRepetition" BO_ 305 0; +BA_ "GenMsgCycleTime" BO_ 305 0; +BA_ "NetworkInitialization" BO_ 305 0; +BA_ "GenMsgDelayTime" BO_ 305 0; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18 "CAN_DET_CONFID_AZIMUTH_18"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18 "CAN_DET_CONFID_AZIMUTH_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18 "CAN_DET_CONFID_AZIMUTH_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18 "CAN_DET_SUPER_RES_TARGET_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18 "CAN_DET_ND_TARGET_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18 "CAN_DET_HOST_VEH_CLUTTER_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18 "CAN_DET_VALID_LEVEL_18"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18 "CAN_DET_AZIMUTH_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18 "CAN_DET_RANGE_18"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18 "CAN_DET_RANGE_RATE_18"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18 "CAN_DET_AMPLITUDE_18"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18 "CAN_SCAN_INDEX_2LSB_18"; +BA_ "GenMsgSendType" BO_ 341 1; +BA_ "GenMsgILSupport" BO_ 341 1; +BA_ "GenMsgNrOfRepetition" BO_ 341 0; +BA_ "GenMsgCycleTime" BO_ 341 0; +BA_ "NetworkInitialization" BO_ 341 0; +BA_ "GenMsgDelayTime" BO_ 341 0; +BA_ "GenSigVtEn" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigVtName" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_SUPER_RES_TARGET_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_SUPER_RES_TARGET_54 "CAN_DET_SUPER_RES_TARGET_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_ND_TARGET_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_ND_TARGET_54 "CAN_DET_ND_TARGET_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_HOST_VEH_CLUTTER_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_HOST_VEH_CLUTTER_54 "CAN_DET_HOST_VEH_CLUTTER_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_VALID_LEVEL_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_VALID_LEVEL_54 "CAN_DET_VALID_LEVEL_54"; +BA_ "GenSigStartValue" SG_ 341 CAN_DET_AZIMUTH_54 0; +BA_ "GenSigSendType" SG_ 341 CAN_DET_AZIMUTH_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_AZIMUTH_54 "CAN_DET_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_RANGE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_RANGE_54 "CAN_DET_RANGE_54"; +BA_ "GenSigStartValue" SG_ 341 CAN_DET_RANGE_RATE_54 0; +BA_ "GenSigSendType" SG_ 341 CAN_DET_RANGE_RATE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_RANGE_RATE_54 "CAN_DET_RANGE_RATE_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_AMPLITUDE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_AMPLITUDE_54 "CAN_DET_AMPLITUDE_54"; +BA_ "GenSigSendType" SG_ 341 CAN_SCAN_INDEX_2LSB_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_SCAN_INDEX_2LSB_54 "CAN_SCAN_INDEX_2LSB_54"; +BA_ "GenMsgSendType" BO_ 340 1; +BA_ "GenMsgILSupport" BO_ 340 1; +BA_ "GenMsgNrOfRepetition" BO_ 340 0; +BA_ "GenMsgCycleTime" BO_ 340 0; +BA_ "NetworkInitialization" BO_ 340 0; +BA_ "GenMsgDelayTime" BO_ 340 0; +BA_ "GenSigVtEn" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigVtName" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_SUPER_RES_TARGET_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_SUPER_RES_TARGET_53 "CAN_DET_SUPER_RES_TARGET_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_ND_TARGET_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_ND_TARGET_53 "CAN_DET_ND_TARGET_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_HOST_VEH_CLUTTER_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_HOST_VEH_CLUTTER_53 "CAN_DET_HOST_VEH_CLUTTER_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_VALID_LEVEL_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_VALID_LEVEL_53 "CAN_DET_VALID_LEVEL_53"; +BA_ "GenSigStartValue" SG_ 340 CAN_DET_AZIMUTH_53 0; +BA_ "GenSigSendType" SG_ 340 CAN_DET_AZIMUTH_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_AZIMUTH_53 "CAN_DET_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_RANGE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_RANGE_53 "CAN_DET_RANGE_53"; +BA_ "GenSigStartValue" SG_ 340 CAN_DET_RANGE_RATE_53 0; +BA_ "GenSigSendType" SG_ 340 CAN_DET_RANGE_RATE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_RANGE_RATE_53 "CAN_DET_RANGE_RATE_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_AMPLITUDE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_AMPLITUDE_53 "CAN_DET_AMPLITUDE_53"; +BA_ "GenSigSendType" SG_ 340 CAN_SCAN_INDEX_2LSB_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_SCAN_INDEX_2LSB_53 "CAN_SCAN_INDEX_2LSB_53"; +BA_ "GenMsgSendType" BO_ 339 1; +BA_ "GenMsgILSupport" BO_ 339 1; +BA_ "GenMsgNrOfRepetition" BO_ 339 0; +BA_ "GenMsgCycleTime" BO_ 339 0; +BA_ "NetworkInitialization" BO_ 339 0; +BA_ "GenMsgDelayTime" BO_ 339 0; +BA_ "GenSigVtEn" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigVtName" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_SUPER_RES_TARGET_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_SUPER_RES_TARGET_52 "CAN_DET_SUPER_RES_TARGET_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_ND_TARGET_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_ND_TARGET_52 "CAN_DET_ND_TARGET_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_HOST_VEH_CLUTTER_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_HOST_VEH_CLUTTER_52 "CAN_DET_HOST_VEH_CLUTTER_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_VALID_LEVEL_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_VALID_LEVEL_52 "CAN_DET_VALID_LEVEL_52"; +BA_ "GenSigStartValue" SG_ 339 CAN_DET_AZIMUTH_52 0; +BA_ "GenSigSendType" SG_ 339 CAN_DET_AZIMUTH_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_AZIMUTH_52 "CAN_DET_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_RANGE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_RANGE_52 "CAN_DET_RANGE_52"; +BA_ "GenSigStartValue" SG_ 339 CAN_DET_RANGE_RATE_52 0; +BA_ "GenSigSendType" SG_ 339 CAN_DET_RANGE_RATE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_RANGE_RATE_52 "CAN_DET_RANGE_RATE_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_AMPLITUDE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_AMPLITUDE_52 "CAN_DET_AMPLITUDE_52"; +BA_ "GenSigSendType" SG_ 339 CAN_SCAN_INDEX_2LSB_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_SCAN_INDEX_2LSB_52 "CAN_SCAN_INDEX_2LSB_52"; +BA_ "GenMsgSendType" BO_ 338 1; +BA_ "GenMsgILSupport" BO_ 338 1; +BA_ "GenMsgNrOfRepetition" BO_ 338 0; +BA_ "GenMsgCycleTime" BO_ 338 0; +BA_ "NetworkInitialization" BO_ 338 0; +BA_ "GenMsgDelayTime" BO_ 338 0; +BA_ "GenSigVtEn" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigVtName" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_SUPER_RES_TARGET_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_SUPER_RES_TARGET_51 "CAN_DET_SUPER_RES_TARGET_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_ND_TARGET_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_ND_TARGET_51 "CAN_DET_ND_TARGET_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_HOST_VEH_CLUTTER_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_HOST_VEH_CLUTTER_51 "CAN_DET_HOST_VEH_CLUTTER_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_VALID_LEVEL_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_VALID_LEVEL_51 "CAN_DET_VALID_LEVEL_51"; +BA_ "GenSigStartValue" SG_ 338 CAN_DET_AZIMUTH_51 0; +BA_ "GenSigSendType" SG_ 338 CAN_DET_AZIMUTH_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_AZIMUTH_51 "CAN_DET_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_RANGE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_RANGE_51 "CAN_DET_RANGE_51"; +BA_ "GenSigStartValue" SG_ 338 CAN_DET_RANGE_RATE_51 0; +BA_ "GenSigSendType" SG_ 338 CAN_DET_RANGE_RATE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_RANGE_RATE_51 "CAN_DET_RANGE_RATE_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_AMPLITUDE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_AMPLITUDE_51 "CAN_DET_AMPLITUDE_51"; +BA_ "GenSigSendType" SG_ 338 CAN_SCAN_INDEX_2LSB_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_SCAN_INDEX_2LSB_51 "CAN_SCAN_INDEX_2LSB_51"; +BA_ "GenMsgSendType" BO_ 337 1; +BA_ "GenMsgILSupport" BO_ 337 1; +BA_ "GenMsgNrOfRepetition" BO_ 337 0; +BA_ "GenMsgCycleTime" BO_ 337 0; +BA_ "NetworkInitialization" BO_ 337 0; +BA_ "GenMsgDelayTime" BO_ 337 0; +BA_ "GenSigVtEn" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigVtName" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_SUPER_RES_TARGET_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_SUPER_RES_TARGET_50 "CAN_DET_SUPER_RES_TARGET_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_ND_TARGET_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_ND_TARGET_50 "CAN_DET_ND_TARGET_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_HOST_VEH_CLUTTER_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_HOST_VEH_CLUTTER_50 "CAN_DET_HOST_VEH_CLUTTER_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_VALID_LEVEL_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_VALID_LEVEL_50 "CAN_DET_VALID_LEVEL_50"; +BA_ "GenSigStartValue" SG_ 337 CAN_DET_AZIMUTH_50 0; +BA_ "GenSigSendType" SG_ 337 CAN_DET_AZIMUTH_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_AZIMUTH_50 "CAN_DET_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_RANGE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_RANGE_50 "CAN_DET_RANGE_50"; +BA_ "GenSigStartValue" SG_ 337 CAN_DET_RANGE_RATE_50 0; +BA_ "GenSigSendType" SG_ 337 CAN_DET_RANGE_RATE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_RANGE_RATE_50 "CAN_DET_RANGE_RATE_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_AMPLITUDE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_AMPLITUDE_50 "CAN_DET_AMPLITUDE_50"; +BA_ "GenSigSendType" SG_ 337 CAN_SCAN_INDEX_2LSB_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_SCAN_INDEX_2LSB_50 "CAN_SCAN_INDEX_2LSB_50"; +BA_ "GenMsgSendType" BO_ 336 1; +BA_ "GenMsgILSupport" BO_ 336 1; +BA_ "GenMsgNrOfRepetition" BO_ 336 0; +BA_ "GenMsgCycleTime" BO_ 336 0; +BA_ "NetworkInitialization" BO_ 336 0; +BA_ "GenMsgDelayTime" BO_ 336 0; +BA_ "GenSigVtEn" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigVtName" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_SUPER_RES_TARGET_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_SUPER_RES_TARGET_49 "CAN_DET_SUPER_RES_TARGET_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_ND_TARGET_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_ND_TARGET_49 "CAN_DET_ND_TARGET_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_HOST_VEH_CLUTTER_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_HOST_VEH_CLUTTER_49 "CAN_DET_HOST_VEH_CLUTTER_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_VALID_LEVEL_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_VALID_LEVEL_49 "CAN_DET_VALID_LEVEL_49"; +BA_ "GenSigStartValue" SG_ 336 CAN_DET_AZIMUTH_49 0; +BA_ "GenSigSendType" SG_ 336 CAN_DET_AZIMUTH_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_AZIMUTH_49 "CAN_DET_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_RANGE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_RANGE_49 "CAN_DET_RANGE_49"; +BA_ "GenSigStartValue" SG_ 336 CAN_DET_RANGE_RATE_49 0; +BA_ "GenSigSendType" SG_ 336 CAN_DET_RANGE_RATE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_RANGE_RATE_49 "CAN_DET_RANGE_RATE_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_AMPLITUDE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_AMPLITUDE_49 "CAN_DET_AMPLITUDE_49"; +BA_ "GenSigSendType" SG_ 336 CAN_SCAN_INDEX_2LSB_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_SCAN_INDEX_2LSB_49 "CAN_SCAN_INDEX_2LSB_49"; +BA_ "GenMsgSendType" BO_ 326 1; +BA_ "GenMsgILSupport" BO_ 326 1; +BA_ "GenMsgNrOfRepetition" BO_ 326 0; +BA_ "GenMsgCycleTime" BO_ 326 0; +BA_ "NetworkInitialization" BO_ 326 0; +BA_ "GenMsgDelayTime" BO_ 326 0; +BA_ "GenSigVtEn" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigVtName" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_SUPER_RES_TARGET_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_SUPER_RES_TARGET_39 "CAN_DET_SUPER_RES_TARGET_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_ND_TARGET_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_ND_TARGET_39 "CAN_DET_ND_TARGET_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_HOST_VEH_CLUTTER_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_HOST_VEH_CLUTTER_39 "CAN_DET_HOST_VEH_CLUTTER_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_VALID_LEVEL_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_VALID_LEVEL_39 "CAN_DET_VALID_LEVEL_39"; +BA_ "GenSigStartValue" SG_ 326 CAN_DET_AZIMUTH_39 0; +BA_ "GenSigSendType" SG_ 326 CAN_DET_AZIMUTH_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_AZIMUTH_39 "CAN_DET_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_RANGE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_RANGE_39 "CAN_DET_RANGE_39"; +BA_ "GenSigStartValue" SG_ 326 CAN_DET_RANGE_RATE_39 0; +BA_ "GenSigSendType" SG_ 326 CAN_DET_RANGE_RATE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_RANGE_RATE_39 "CAN_DET_RANGE_RATE_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_AMPLITUDE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_AMPLITUDE_39 "CAN_DET_AMPLITUDE_39"; +BA_ "GenSigSendType" SG_ 326 CAN_SCAN_INDEX_2LSB_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_SCAN_INDEX_2LSB_39 "CAN_SCAN_INDEX_2LSB_39"; +BA_ "GenMsgSendType" BO_ 315 1; +BA_ "GenMsgILSupport" BO_ 315 1; +BA_ "GenMsgNrOfRepetition" BO_ 315 0; +BA_ "GenMsgCycleTime" BO_ 315 0; +BA_ "NetworkInitialization" BO_ 315 0; +BA_ "GenMsgDelayTime" BO_ 315 0; +BA_ "GenSigVtEn" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigVtName" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_SUPER_RES_TARGET_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_SUPER_RES_TARGET_28 "CAN_DET_SUPER_RES_TARGET_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_ND_TARGET_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_ND_TARGET_28 "CAN_DET_ND_TARGET_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_HOST_VEH_CLUTTER_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_HOST_VEH_CLUTTER_28 "CAN_DET_HOST_VEH_CLUTTER_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_VALID_LEVEL_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_VALID_LEVEL_28 "CAN_DET_VALID_LEVEL_28"; +BA_ "GenSigStartValue" SG_ 315 CAN_DET_AZIMUTH_28 0; +BA_ "GenSigSendType" SG_ 315 CAN_DET_AZIMUTH_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_AZIMUTH_28 "CAN_DET_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_RANGE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_RANGE_28 "CAN_DET_RANGE_28"; +BA_ "GenSigStartValue" SG_ 315 CAN_DET_RANGE_RATE_28 0; +BA_ "GenSigSendType" SG_ 315 CAN_DET_RANGE_RATE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_RANGE_RATE_28 "CAN_DET_RANGE_RATE_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_AMPLITUDE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_AMPLITUDE_28 "CAN_DET_AMPLITUDE_28"; +BA_ "GenSigSendType" SG_ 315 CAN_SCAN_INDEX_2LSB_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_SCAN_INDEX_2LSB_28 "CAN_SCAN_INDEX_2LSB_28"; +BA_ "GenMsgSendType" BO_ 304 1; +BA_ "GenMsgILSupport" BO_ 304 1; +BA_ "GenMsgNrOfRepetition" BO_ 304 0; +BA_ "GenMsgCycleTime" BO_ 304 0; +BA_ "NetworkInitialization" BO_ 304 0; +BA_ "GenMsgDelayTime" BO_ 304 0; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17 "CAN_DET_CONFID_AZIMUTH_17"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17 "CAN_DET_CONFID_AZIMUTH_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17 "CAN_DET_CONFID_AZIMUTH_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17 "CAN_DET_SUPER_RES_TARGET_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17 "CAN_DET_ND_TARGET_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17 "CAN_DET_HOST_VEH_CLUTTER_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17 "CAN_DET_VALID_LEVEL_17"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17 "CAN_DET_AZIMUTH_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17 "CAN_DET_RANGE_17"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17 "CAN_DET_RANGE_RATE_17"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17 "CAN_DET_AMPLITUDE_17"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17 "CAN_SCAN_INDEX_2LSB_17"; +BA_ "GenMsgSendType" BO_ 303 1; +BA_ "GenMsgILSupport" BO_ 303 1; +BA_ "GenMsgNrOfRepetition" BO_ 303 0; +BA_ "GenMsgCycleTime" BO_ 303 0; +BA_ "NetworkInitialization" BO_ 303 0; +BA_ "GenMsgDelayTime" BO_ 303 0; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16 "CAN_DET_CONFID_AZIMUTH_16"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16 "CAN_DET_CONFID_AZIMUTH_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16 "CAN_DET_CONFID_AZIMUTH_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16 "CAN_DET_SUPER_RES_TARGET_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16 "CAN_DET_ND_TARGET_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16 "CAN_DET_HOST_VEH_CLUTTER_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16 "CAN_DET_VALID_LEVEL_16"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16 "CAN_DET_AZIMUTH_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16 "CAN_DET_RANGE_16"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16 "CAN_DET_RANGE_RATE_16"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16 "CAN_DET_AMPLITUDE_16"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16 "CAN_SCAN_INDEX_2LSB_16"; +BA_ "GenMsgSendType" BO_ 302 1; +BA_ "GenMsgILSupport" BO_ 302 1; +BA_ "GenMsgNrOfRepetition" BO_ 302 0; +BA_ "GenMsgCycleTime" BO_ 302 0; +BA_ "NetworkInitialization" BO_ 302 0; +BA_ "GenMsgDelayTime" BO_ 302 0; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15 "CAN_DET_CONFID_AZIMUTH_15"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15 "CAN_DET_CONFID_AZIMUTH_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15 "CAN_DET_CONFID_AZIMUTH_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15 "CAN_DET_SUPER_RES_TARGET_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15 "CAN_DET_ND_TARGET_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15 "CAN_DET_HOST_VEH_CLUTTER_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15 "CAN_DET_VALID_LEVEL_15"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15 "CAN_DET_AZIMUTH_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15 "CAN_DET_RANGE_15"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15 "CAN_DET_RANGE_RATE_15"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15 "CAN_DET_AMPLITUDE_15"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15 "CAN_SCAN_INDEX_2LSB_15"; +BA_ "GenMsgSendType" BO_ 301 1; +BA_ "GenMsgILSupport" BO_ 301 1; +BA_ "GenMsgNrOfRepetition" BO_ 301 0; +BA_ "GenMsgCycleTime" BO_ 301 0; +BA_ "NetworkInitialization" BO_ 301 0; +BA_ "GenMsgDelayTime" BO_ 301 0; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14 "CAN_DET_CONFID_AZIMUTH_14"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14 "CAN_DET_CONFID_AZIMUTH_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14 "CAN_DET_CONFID_AZIMUTH_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14 "CAN_DET_SUPER_RES_TARGET_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14 "CAN_DET_ND_TARGET_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14 "CAN_DET_HOST_VEH_CLUTTER_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14 "CAN_DET_VALID_LEVEL_14"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14 "CAN_DET_AZIMUTH_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14 "CAN_DET_RANGE_14"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14 "CAN_DET_RANGE_RATE_14"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14 "CAN_DET_AMPLITUDE_14"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14 "CAN_SCAN_INDEX_2LSB_14"; +BA_ "GenMsgSendType" BO_ 300 1; +BA_ "GenMsgILSupport" BO_ 300 1; +BA_ "GenMsgNrOfRepetition" BO_ 300 0; +BA_ "GenMsgCycleTime" BO_ 300 0; +BA_ "NetworkInitialization" BO_ 300 0; +BA_ "GenMsgDelayTime" BO_ 300 0; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13 "CAN_DET_CONFID_AZIMUTH_13"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13 "CAN_DET_CONFID_AZIMUTH_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13 "CAN_DET_CONFID_AZIMUTH_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13 "CAN_DET_SUPER_RES_TARGET_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13 "CAN_DET_ND_TARGET_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13 "CAN_DET_HOST_VEH_CLUTTER_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13 "CAN_DET_VALID_LEVEL_13"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13 "CAN_DET_AZIMUTH_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13 "CAN_DET_RANGE_13"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13 "CAN_DET_RANGE_RATE_13"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13 "CAN_DET_AMPLITUDE_13"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13 "CAN_SCAN_INDEX_2LSB_13"; +BA_ "GenMsgSendType" BO_ 299 1; +BA_ "GenMsgILSupport" BO_ 299 1; +BA_ "GenMsgNrOfRepetition" BO_ 299 0; +BA_ "GenMsgCycleTime" BO_ 299 0; +BA_ "NetworkInitialization" BO_ 299 0; +BA_ "GenMsgDelayTime" BO_ 299 0; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12 "CAN_DET_CONFID_AZIMUTH_12"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12 "CAN_DET_CONFID_AZIMUTH_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12 "CAN_DET_CONFID_AZIMUTH_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12 "CAN_DET_SUPER_RES_TARGET_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12 "CAN_DET_ND_TARGET_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12 "CAN_DET_HOST_VEH_CLUTTER_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12 "CAN_DET_VALID_LEVEL_12"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12 "CAN_DET_AZIMUTH_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12 "CAN_DET_RANGE_12"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12 "CAN_DET_RANGE_RATE_12"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12 "CAN_DET_AMPLITUDE_12"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12 "CAN_SCAN_INDEX_2LSB_12"; +BA_ "GenMsgSendType" BO_ 298 1; +BA_ "GenMsgILSupport" BO_ 298 1; +BA_ "GenMsgNrOfRepetition" BO_ 298 0; +BA_ "GenMsgCycleTime" BO_ 298 0; +BA_ "NetworkInitialization" BO_ 298 0; +BA_ "GenMsgDelayTime" BO_ 298 0; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11 "CAN_DET_CONFID_AZIMUTH_11"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11 "CAN_DET_CONFID_AZIMUTH_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11 "CAN_DET_CONFID_AZIMUTH_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11 "CAN_DET_SUPER_RES_TARGET_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11 "CAN_DET_ND_TARGET_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11 "CAN_DET_HOST_VEH_CLUTTER_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11 "CAN_DET_VALID_LEVEL_11"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11 "CAN_DET_AZIMUTH_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11 "CAN_DET_RANGE_11"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11 "CAN_DET_RANGE_RATE_11"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11 "CAN_DET_AMPLITUDE_11"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11 "CAN_SCAN_INDEX_2LSB_11"; +BA_ "GenMsgSendType" BO_ 297 1; +BA_ "GenMsgILSupport" BO_ 297 1; +BA_ "GenMsgNrOfRepetition" BO_ 297 0; +BA_ "GenMsgCycleTime" BO_ 297 0; +BA_ "NetworkInitialization" BO_ 297 0; +BA_ "GenMsgDelayTime" BO_ 297 0; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10 "CAN_DET_CONFID_AZIMUTH_10"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10 "CAN_DET_CONFID_AZIMUTH_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10 "CAN_DET_CONFID_AZIMUTH_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10 "CAN_DET_SUPER_RES_TARGET_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10 "CAN_DET_ND_TARGET_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10 "CAN_DET_HOST_VEH_CLUTTER_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10 "CAN_DET_VALID_LEVEL_10"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10 "CAN_DET_AZIMUTH_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10 "CAN_DET_RANGE_10"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10 "CAN_DET_RANGE_RATE_10"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10 "CAN_DET_AMPLITUDE_10"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10 "CAN_SCAN_INDEX_2LSB_10"; +BA_ "GenMsgSendType" BO_ 296 1; +BA_ "GenMsgILSupport" BO_ 296 1; +BA_ "GenMsgNrOfRepetition" BO_ 296 0; +BA_ "GenMsgCycleTime" BO_ 296 0; +BA_ "NetworkInitialization" BO_ 296 0; +BA_ "GenMsgDelayTime" BO_ 296 0; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09 "CAN_DET_CONFID_AZIMUTH_09"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09 "CAN_DET_CONFID_AZIMUTH_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09 "CAN_DET_CONFID_AZIMUTH_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09 "CAN_DET_SUPER_RES_TARGET_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09 "CAN_DET_ND_TARGET_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09 "CAN_DET_HOST_VEH_CLUTTER_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09 "CAN_DET_VALID_LEVEL_09"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09 "CAN_DET_AZIMUTH_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09 "CAN_DET_RANGE_09"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09 "CAN_DET_RANGE_RATE_09"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09 "CAN_DET_AMPLITUDE_09"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09 "CAN_SCAN_INDEX_2LSB_09"; +BA_ "GenMsgSendType" BO_ 295 1; +BA_ "GenMsgILSupport" BO_ 295 1; +BA_ "GenMsgNrOfRepetition" BO_ 295 0; +BA_ "GenMsgCycleTime" BO_ 295 0; +BA_ "NetworkInitialization" BO_ 295 0; +BA_ "GenMsgDelayTime" BO_ 295 0; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08 "CAN_DET_CONFID_AZIMUTH_08"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08 "CAN_DET_CONFID_AZIMUTH_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08 "CAN_DET_CONFID_AZIMUTH_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08 "CAN_DET_SUPER_RES_TARGET_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08 "CAN_DET_ND_TARGET_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08 "CAN_DET_HOST_VEH_CLUTTER_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08 "CAN_DET_VALID_LEVEL_08"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08 "CAN_DET_AZIMUTH_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08 "CAN_DET_RANGE_08"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08 "CAN_DET_RANGE_RATE_08"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08 "CAN_DET_AMPLITUDE_08"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08 "CAN_SCAN_INDEX_2LSB_08"; +BA_ "GenMsgSendType" BO_ 294 1; +BA_ "GenMsgILSupport" BO_ 294 1; +BA_ "GenMsgNrOfRepetition" BO_ 294 0; +BA_ "GenMsgCycleTime" BO_ 294 0; +BA_ "NetworkInitialization" BO_ 294 0; +BA_ "GenMsgDelayTime" BO_ 294 0; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07 "CAN_DET_CONFID_AZIMUTH_07"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07 "CAN_DET_CONFID_AZIMUTH_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07 "CAN_DET_CONFID_AZIMUTH_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07 "CAN_DET_SUPER_RES_TARGET_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07 "CAN_DET_ND_TARGET_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07 "CAN_DET_HOST_VEH_CLUTTER_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07 "CAN_DET_VALID_LEVEL_07"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07 "CAN_DET_AZIMUTH_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07 "CAN_DET_RANGE_07"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07 "CAN_DET_RANGE_RATE_07"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07 "CAN_DET_AMPLITUDE_07"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07 "CAN_SCAN_INDEX_2LSB_07"; +BA_ "GenMsgSendType" BO_ 293 1; +BA_ "GenMsgILSupport" BO_ 293 1; +BA_ "GenMsgNrOfRepetition" BO_ 293 0; +BA_ "GenMsgCycleTime" BO_ 293 0; +BA_ "NetworkInitialization" BO_ 293 0; +BA_ "GenMsgDelayTime" BO_ 293 0; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06 "CAN_DET_CONFID_AZIMUTH_06"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06 "CAN_DET_CONFID_AZIMUTH_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06 "CAN_DET_CONFID_AZIMUTH_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06 "CAN_DET_SUPER_RES_TARGET_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06 "CAN_DET_ND_TARGET_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06 "CAN_DET_HOST_VEH_CLUTTER_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06 "CAN_DET_VALID_LEVEL_06"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06 "CAN_DET_AZIMUTH_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06 "CAN_DET_RANGE_06"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06 "CAN_DET_RANGE_RATE_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06 "CAN_DET_AMPLITUDE_06"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06 "CAN_SCAN_INDEX_2LSB_06"; +BA_ "GenMsgSendType" BO_ 292 1; +BA_ "GenMsgILSupport" BO_ 292 1; +BA_ "GenMsgNrOfRepetition" BO_ 292 0; +BA_ "GenMsgCycleTime" BO_ 292 0; +BA_ "NetworkInitialization" BO_ 292 0; +BA_ "GenMsgDelayTime" BO_ 292 0; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05 "CAN_DET_CONFID_AZIMUTH_05"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05 "CAN_DET_CONFID_AZIMUTH_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05 "CAN_DET_CONFID_AZIMUTH_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05 "CAN_DET_SUPER_RES_TARGET_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05 "CAN_DET_ND_TARGET_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05 "CAN_DET_HOST_VEH_CLUTTER_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05 "CAN_DET_VALID_LEVEL_05"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05 "CAN_DET_AZIMUTH_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05 "CAN_DET_RANGE_05"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05 "CAN_DET_RANGE_RATE_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05 "CAN_DET_AMPLITUDE_05"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05 "CAN_SCAN_INDEX_2LSB_05"; +BA_ "GenMsgSendType" BO_ 290 1; +BA_ "GenMsgILSupport" BO_ 290 1; +BA_ "GenMsgNrOfRepetition" BO_ 290 0; +BA_ "GenMsgCycleTime" BO_ 290 0; +BA_ "NetworkInitialization" BO_ 290 0; +BA_ "GenMsgDelayTime" BO_ 290 0; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03 "CAN_DET_CONFID_AZIMUTH_03"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03 "CAN_DET_CONFID_AZIMUTH_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03 "CAN_DET_CONFID_AZIMUTH_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03 "CAN_DET_SUPER_RES_TARGET_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03 "CAN_DET_ND_TARGET_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03 "CAN_DET_HOST_VEH_CLUTTER_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03 "CAN_DET_VALID_LEVEL_03"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03 "CAN_DET_AZIMUTH_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03 "CAN_DET_RANGE_03"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03 "CAN_DET_RANGE_RATE_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03 "CAN_DET_AMPLITUDE_03"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03 "CAN_SCAN_INDEX_2LSB_03"; +BA_ "GenMsgSendType" BO_ 289 1; +BA_ "GenMsgILSupport" BO_ 289 1; +BA_ "GenMsgNrOfRepetition" BO_ 289 0; +BA_ "GenMsgCycleTime" BO_ 289 0; +BA_ "NetworkInitialization" BO_ 289 0; +BA_ "GenMsgDelayTime" BO_ 289 0; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02 "CAN_DET_CONFID_AZIMUTH_02"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02 "CAN_DET_CONFID_AZIMUTH_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02 "CAN_DET_CONFID_AZIMUTH_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02 "CAN_DET_SUPER_RES_TARGET_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02 "CAN_DET_ND_TARGET_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02 "CAN_DET_HOST_VEH_CLUTTER_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02 "CAN_DET_VALID_LEVEL_02"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02 "CAN_DET_AZIMUTH_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02 "CAN_DET_RANGE_02"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02 "CAN_DET_RANGE_RATE_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02 "CAN_DET_AMPLITUDE_02"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02 "CAN_SCAN_INDEX_2LSB_02"; +BA_ "GenMsgSendType" BO_ 256 1; +BA_ "GenMsgILSupport" BO_ 256 1; +BA_ "GenMsgNrOfRepetition" BO_ 256 0; +BA_ "NetworkInitialization" BO_ 256 0; +BA_ "GenSigCmt" SG_ 256 CAN_PCAN_MINOR_MRR "CAN_PCAN_MINOR_MRR"; +BA_ "GenSigSendType" SG_ 256 CAN_PCAN_MINOR_MRR 0; +BA_ "GenSigCmt" SG_ 256 CAN_PCAN_MAJOR_MRR "CAN_PCAN_MAJOR_MRR"; +BA_ "GenSigSendType" SG_ 256 CAN_PCAN_MAJOR_MRR 0; +BA_ "GenMsgCycleTime" BO_ 257 30; +BA_ "GenMsgSendType" BO_ 257 0; +BA_ "GenMsgILSupport" BO_ 257 1; +BA_ "GenMsgNrOfRepetition" BO_ 257 0; +BA_ "NetworkInitialization" BO_ 257 0; +BA_ "GenSigCmt" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtEn" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtName" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtName" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigCmt" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigStartValue" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL 0; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL 0; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_SIDELOBE 0; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_MNR 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_EXT_COND_NOK 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_ALIGN_NOT_START 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_OVERHEAT_ERROR 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_NOT_OP 0; +BA_ "GenSigCmt" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigVtEn" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigVtName" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigSendType" SG_ 257 CAN_XCVR_OPERATIONAL 0; +BA_ "GenMsgSendType" BO_ 288 1; +BA_ "GenMsgILSupport" BO_ 288 1; +BA_ "GenMsgNrOfRepetition" BO_ 288 0; +BA_ "GenMsgCycleTime" BO_ 288 0; +BA_ "NetworkInitialization" BO_ 288 0; +BA_ "GenMsgDelayTime" BO_ 288 0; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01 "CAN_DET_CONFID_AZIMUTH_01"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01 "CAN_DET_CONFID_AZIMUTH_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01 "CAN_DET_CONFID_AZIMUTH_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01 "CAN_DET_SUPER_RES_TARGET_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01 "CAN_DET_ND_TARGET_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01 "CAN_DET_HOST_VEH_CLUTTER_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01 "CAN_DET_VALID_LEVEL_01"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01 "CAN_DET_AZIMUTH_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01 "CAN_DET_RANGE_01"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01 "CAN_DET_RANGE_RATE_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01 "CAN_DET_AMPLITUDE_01"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01 "CAN_SCAN_INDEX_2LSB_01"; +BA_DEF_DEF_ "CrossOver_InfoCAN" "No"; +BA_DEF_DEF_ "CrossOver_LIN" "No"; +BA_DEF_DEF_ "UsedOnPgmDBC" "Yes"; +BA_DEF_DEF_ "ContentDependant" "No"; +BA_DEF_DEF_ "GenSigTimeoutTime_RCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_GWM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_OCS" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ABS_ESC" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_CCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_IPMA" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TSTR" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_SCCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_PSCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime__delete" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_Generic_BCM" 0; +BA_DEF_DEF_ "NmMessage" "No"; +BA_DEF_DEF_ "DiagResponse" "No"; +BA_DEF_DEF_ "DiagRequest" "No"; +BA_DEF_DEF_ "TpTxIndex" 0; +BA_DEF_DEF_ "DiagState" "No"; +BA_DEF_DEF_ "TpApplType" ""; +BA_DEF_DEF_ "NmAsrMessage" "No"; +BA_DEF_DEF_ "Mulitplexer" "No"; +BA_DEF_DEF_ "ConfiguredTransmitter" "No"; +BA_DEF_DEF_ "EventRateOfChange" 10000; +BA_DEF_DEF_ "GenMsgHandlingTypeDoc" ""; +BA_DEF_DEF_ "GenMsgHandlingTypeCode" ""; +BA_DEF_DEF_ "GenMsgMarked" ""; +BA_DEF_DEF_ "GenSigMarked" ""; +BA_DEF_DEF_ "GenSigVtIndex" ""; +BA_DEF_DEF_ "GenSigVtName" ""; +BA_DEF_DEF_ "GenSigVtEn" ""; +BA_DEF_DEF_ "GenSigSNA" ""; +BA_DEF_DEF_ "GenSigCmt" ""; +BA_DEF_DEF_ "GenMsgCmt" ""; +BA_DEF_DEF_ "GenSigSendType" "NoSigSendType"; +BA_DEF_DEF_ "GenSigInactiveValue" 0; +BA_DEF_DEF_ "GenSigMissingSourceValue" 0; +BA_DEF_DEF_ "WakeupSignal" "No"; +BA_DEF_DEF_ "GenSigStartValue" 0; +BA_DEF_DEF_ "GenMsgILSupport" "Yes"; +BA_DEF_DEF_ "NetworkInitializationCommand" "No"; +BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType"; +BA_DEF_DEF_ "GenMsgCycleTime" 0; +BA_DEF_DEF_ "GenMsgCycleTimeFast" 0; +BA_DEF_DEF_ "GenMsgDelayTime" 0; +BA_DEF_DEF_ "GenMsgNrOfRepetition" 0; +BA_DEF_DEF_ "GenMsgStartDelayTime" 0; +BA_DEF_DEF_ "NetworkInitialization" "No"; +BA_DEF_DEF_ "MessageGateway" "No"; +BA_DEF_DEF_ "ILUsed" "Yes"; +BA_DEF_DEF_ "NetworkInitializationUsed" "No"; +BA_DEF_DEF_ "PowerType" "Switched"; +BA_DEF_DEF_ "NodeStartUpTime" 250; +BA_DEF_DEF_ "NodeWakeUpTime" 10; +BA_DEF_DEF_ "GenMsgBackgroundColor" "#ffffff"; +BA_DEF_DEF_ "GenMsgForegroundColor" "#000000"; +VAL_ 34 IPMA_PCAN_DataRangeCheck 1 "Fault Present" 0 "No Fault"; +VAL_ 34 IPMA_PCAN_MissingMsg 1 "Fault Present" 0 "No Fault "; +VAL_ 34 VINSignalCompareFailure 1 "Fault Present" 0 "No Fault"; +VAL_ 34 ModuleNotConfiguredError 1 "Fault Present" 0 "No Fault"; +VAL_ 34 CarCfgNotConfiguredError 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ARMtoDSPChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 DSPtoArmChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 HostToArmChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ARMtoHostChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 LoopBWOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 DSPOverrunFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte6_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TuningSensitivityFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 SaturatedTuningFreqFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 LocalOscPowerFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterPowerFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte6_bit0 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 XCVRDeviceSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 FreqSynthesizerSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 AnalogConverterDevicSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 SidelobeBlockage 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit1 1 "Fault Present" 0 "No Fault"; +VAL_ 33 MNRBlocked 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ECUTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 AlignmentRoutineFailedFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 UnreasonableRadarData 1 "Fault Present" 0 "No Fault"; +VAL_ 33 MicroprocessorTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 VerticalAlignmentOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 HorizontalAlignmentOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 FactoryAlignmentMode 1 "Fault Present" 0 "No Fault"; +VAL_ 33 BatteryLowFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 BatteryHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_1p25SupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte3_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ThermistorOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_3p3DACSupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_3p3RAWSupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_5_SupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterIDFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit3 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit2 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PCANMissingMsgFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PCANBusOff 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 InstructionSetCheckFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 StackOverflowFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 WatchdogFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PLLLockFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit1 1 "Fault Present" 0 "No Fault"; +VAL_ 33 RAMMemoryTestFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 USCValidationFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit3 1 "Fault Present" 0 "No Fault"; +VAL_ 33 KeepAliveChecksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ProgramCalibrationFlashChecksum 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ApplicationFlashChecksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 371 CAN_AUTO_ALIGN_HANGLE_QF 3 "Accurate" 2 "Inaccurate" 1 "Temporarily undefined" 0 "Undefined"; +VAL_ 371 CAN_ALIGNMENT_STATUS 15 "Undefined_2" 14 "Undefined_1" 13 "Low Amplitude (Flat-plate only)" 12 "No Peak (Flat-plate only)" 11 "Fail Ver and Hor OutOfRange" 10 "Fail Vertical Align OutOfRange" 9 "Fail Horizontal Align OutOfRange" 8 "Fail Time Out" 7 "Fail Only Right Target Found" 6 "Fail Only Left Target Found" 5 "Fail Variance Too Large" 4 "Fail Deviation Too Large" 3 "Fail No Target" 2 "Success" 1 "Busy" 0 "Off"; +VAL_ 371 CAN_ALIGNMENT_STATE 6 "Static alignment flat-plate" 5 "Static alignment 2-target" 4 "Static alignment 1-target" 3 "Service alignment" 2 "Short track alignment" 1 "Auto alignment" 0 "Off"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 351 CAN_DET_CONFID_AZIMUTH_64 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 350 CAN_DET_CONFID_AZIMUTH_63 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 349 CAN_DET_CONFID_AZIMUTH_62 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 348 CAN_DET_CONFID_AZIMUTH_61 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 347 CAN_DET_CONFID_AZIMUTH_60 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 346 CAN_DET_CONFID_AZIMUTH_59 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 345 CAN_DET_CONFID_AZIMUTH_58 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 344 CAN_DET_CONFID_AZIMUTH_57 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 343 CAN_DET_CONFID_AZIMUTH_56 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 342 CAN_DET_CONFID_AZIMUTH_55 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 335 CAN_DET_CONFID_AZIMUTH_48 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 334 CAN_DET_CONFID_AZIMUTH_47 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 333 CAN_DET_CONFID_AZIMUTH_46 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 332 CAN_DET_CONFID_AZIMUTH_45 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 331 CAN_DET_CONFID_AZIMUTH_44 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 330 CAN_DET_CONFID_AZIMUTH_43 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 329 CAN_DET_CONFID_AZIMUTH_42 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 328 CAN_DET_CONFID_AZIMUTH_41 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 327 CAN_DET_CONFID_AZIMUTH_40 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 325 CAN_DET_CONFID_AZIMUTH_38 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 324 CAN_DET_CONFID_AZIMUTH_37 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 323 CAN_DET_CONFID_AZIMUTH_36 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 322 CAN_DET_CONFID_AZIMUTH_35 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 321 CAN_DET_CONFID_AZIMUTH_34 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 320 CAN_DET_CONFID_AZIMUTH_33 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 319 CAN_DET_CONFID_AZIMUTH_32 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 318 CAN_DET_CONFID_AZIMUTH_31 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 317 CAN_DET_CONFID_AZIMUTH_30 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 316 CAN_DET_CONFID_AZIMUTH_29 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 314 CAN_DET_CONFID_AZIMUTH_27 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 313 CAN_DET_CONFID_AZIMUTH_26 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 312 CAN_DET_CONFID_AZIMUTH_25 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 311 CAN_DET_CONFID_AZIMUTH_24 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 310 CAN_DET_CONFID_AZIMUTH_23 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 309 CAN_DET_CONFID_AZIMUTH_22 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 341 CAN_DET_CONFID_AZIMUTH_54 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 340 CAN_DET_CONFID_AZIMUTH_53 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 339 CAN_DET_CONFID_AZIMUTH_52 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 338 CAN_DET_CONFID_AZIMUTH_51 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 337 CAN_DET_CONFID_AZIMUTH_50 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 336 CAN_DET_CONFID_AZIMUTH_49 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 326 CAN_DET_CONFID_AZIMUTH_39 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 315 CAN_DET_CONFID_AZIMUTH_28 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 257 CAN_INTERFERENCE_TYPE 2 "Star PD-Like" 1 "Slow FMCW" 0 "No Interference"; +VAL_ 257 CAN_RECOMMEND_UNCONVERGE 1 "Recommended" 0 "Not Recommended"; +VAL_ 257 CAN_RADAR_ALIGN_INCOMPLETE 1 "Alignment Incomplete" 0 "Alignment Completed"; +VAL_ 257 CAN_BLOCKAGE_SIDELOBE 1 "Radar Blockage" 0 "No Radar Blockage"; +VAL_ 257 CAN_BLOCKAGE_MNR 1 "Radar Blockage" 0 "No Radar Blockage"; +VAL_ 257 CAN_RADAR_EXT_COND_NOK 1 "Too high temp or insufficient pw" 0 "External conditions OK"; +VAL_ 257 CAN_RADAR_ALIGN_OUT_RANGE 1 "Radar out of range" 0 "Radar within range"; +VAL_ 257 CAN_RADAR_ALIGN_NOT_START 1 "Radar align not started" 0 "Radar align started"; +VAL_ 257 CAN_RADAR_OVERHEAT_ERROR 1 "Radar overheat condition" 0 "No Overheat"; +VAL_ 257 CAN_RADAR_NOT_OP 1 "Radar not operational" 0 "Radar operational"; +VAL_ 257 CAN_XCVR_OPERATIONAL 1 "On" 0 "Off "; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; diff --git a/opendbc_repo/opendbc/dbc/FORD_CADS_64.dbc b/opendbc_repo/opendbc/dbc/FORD_CADS_64.dbc new file mode 100644 index 0000000000..2ae927a6f2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/FORD_CADS_64.dbc @@ -0,0 +1,7289 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: +BU_: MRR +BO_ 1073741824 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ New_Signal_943 : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_SENSOR_VANGLE_OFFSET : 0|8@0+ (0.0625,-8) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_SENSOR_FOV_VER : 0|8@0+ (1,0) [0|255] "deg" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE_QF : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE_REF : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_MMIC_Temp4 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_MMIC_Temp3 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_MMIC_Temp2 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_Processor_Temp2 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_CHECKSUM : 0|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_COUNTER : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_VEHICLE_MODE : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_USC_CAL_VER_MAJOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_USC_CAL_VER_MINOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_SMC_CAL_VER_MAJOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_HW_VERSION : 0|32@0+ (1,0) [0|4.29497e+09] "" Vector__XXX + SG_ CAN_FAC_TGT_MTG_SPACE_VER : 0|8@0+ (1,-128) [-128|127] "cm" Vector__XXX + SG_ CAN_ANGLE_MISALIGNMENT_VER : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_ANGLE_MOUNTING_VOFFSET : 0|8@0+ (0.0625,-8) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_LATCH_FAULTS : 0|64@0+ (1,0) [0|100] "" Vector__XXX + SG_ CAN_ACTIVE_FAULTS : 0|64@0+ (1,0) [0|1.84467e+19] "" Vector__XXX + SG_ CAN_HISTORY_FAULTS : 0|64@0+ (1,0) [0|1.84467e+19] "" Vector__XXX + SG_ CAN_SERV_ALIGN_ENABLE : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_LONG_MOUNTING_OFFSET : 0|8@0+ (0.015625,-2) [-2|1.98438] "" Vector__XXX + SG_ CAN_BEAMWIDTH_VERT : 0|7@0+ (0.125,0) [0|15.875] "deg" Vector__XXX + SG_ CAN_VEHICLE_SPEED_CALC_QF : 0|2@0+ (1,0) [0|3] "" Vector__XXX + +BO_ 34 Active_Fault_Latched_2: 8 MRR + SG_ IPMA_PCAN_DataRangeCheck : 4|1@1+ (1,0) [0|1] "" External_Tool + SG_ IPMA_PCAN_MissingMsg : 3|1@1+ (1,0) [0|1] "" External_Tool + SG_ VINSignalCompareFailure : 2|1@1+ (1,0) [0|1] "" External_Tool + SG_ ModuleNotConfiguredError : 1|1@1+ (1,0) [0|1] "" External_Tool + SG_ CarCfgNotConfiguredError : 0|1@1+ (1,0) [0|1] "" External_Tool + +BO_ 33 Active_Fault_Latched_1: 8 MRR + SG_ Active_Flt_Latched_byte7_bit7 : 63|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit6 : 62|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit5 : 61|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit4 : 60|1@1+ (1,0) [0|1] "" External_Tool + SG_ ARMtoDSPChksumFault : 59|1@1+ (1,0) [0|1] "" External_Tool + SG_ DSPtoArmChksumFault : 58|1@1+ (1,0) [0|1] "" External_Tool + SG_ HostToArmChksumFault : 57|1@1+ (1,0) [0|1] "" External_Tool + SG_ ARMtoHostChksumFault : 56|1@1+ (1,0) [0|1] "" External_Tool + SG_ LoopBWOutOfRange : 55|1@1+ (1,0) [0|1] "" External_Tool + SG_ DSPOverrunFault : 54|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte6_bit5 : 53|1@1+ (1,0) [0|1] "" External_Tool + SG_ TuningSensitivityFault : 52|1@1+ (1,0) [0|1] "" External_Tool + SG_ SaturatedTuningFreqFault : 51|1@1+ (1,0) [0|1] "" External_Tool + SG_ LocalOscPowerFault : 50|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterPowerFault : 49|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte6_bit0 : 48|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit7 : 47|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit6 : 46|1@1+ (1,0) [0|1] "" External_Tool + SG_ XCVRDeviceSPIFault : 45|1@1+ (1,0) [0|1] "" External_Tool + SG_ FreqSynthesizerSPIFault : 44|1@1+ (1,0) [0|1] "" External_Tool + SG_ AnalogConverterDevicSPIFault : 43|1@1+ (1,0) [0|1] "" External_Tool + SG_ SidelobeBlockage : 42|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit1 : 41|1@1+ (1,0) [0|1] "" External_Tool + SG_ MNRBlocked : 40|1@1+ (1,0) [0|1] "" External_Tool + SG_ ECUTempHighFault : 39|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterTempHighFault : 38|1@1+ (1,0) [0|1] "" External_Tool + SG_ AlignmentRoutineFailedFault : 37|1@1+ (1,0) [0|1] "" External_Tool + SG_ UnreasonableRadarData : 36|1@1+ (1,0) [0|1] "" External_Tool + SG_ MicroprocessorTempHighFault : 35|1@1+ (1,0) [0|1] "" External_Tool + SG_ VerticalAlignmentOutOfRange : 34|1@1+ (1,0) [0|1] "" External_Tool + SG_ HorizontalAlignmentOutOfRange : 33|1@1+ (1,0) [0|1] "" External_Tool + SG_ FactoryAlignmentMode : 32|1@1+ (1,0) [0|1] "" External_Tool + SG_ BatteryLowFault : 31|1@1+ (1,0) [0|1] "" External_Tool + SG_ BatteryHighFault : 30|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_1p25SupplyOutOfRange : 29|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte3_bit4 : 28|1@1+ (1,0) [0|1] "" External_Tool + SG_ ThermistorOutOfRange : 27|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_3p3DACSupplyOutOfRange : 26|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_3p3RAWSupplyOutOfRange : 25|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_5_SupplyOutOfRange : 24|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterIDFault : 23|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit6 : 22|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit5 : 21|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit4 : 20|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit3 : 19|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit2 : 18|1@1+ (1,0) [0|1] "" External_Tool + SG_ PCANMissingMsgFault : 17|1@1+ (1,0) [0|1] "" External_Tool + SG_ PCANBusOff : 16|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit7 : 15|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit6 : 14|1@1+ (1,0) [0|1] "" External_Tool + SG_ InstructionSetCheckFault : 13|1@1+ (1,0) [0|1] "" External_Tool + SG_ StackOverflowFault : 12|1@1+ (1,0) [0|1] "" External_Tool + SG_ WatchdogFault : 11|1@1+ (1,0) [0|1] "" External_Tool + SG_ PLLLockFault : 10|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit1 : 9|1@1+ (1,0) [0|1] "" External_Tool + SG_ RAMMemoryTestFault : 8|1@1+ (1,0) [0|1] "" External_Tool + SG_ USCValidationFault : 7|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit6 : 6|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit5 : 5|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit4 : 4|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit3 : 3|1@1+ (1,0) [0|1] "" External_Tool + SG_ KeepAliveChecksumFault : 2|1@1+ (1,0) [0|1] "" External_Tool + SG_ ProgramCalibrationFlashChecksum : 1|1@1+ (1,0) [0|1] "" External_Tool + SG_ ApplicationFlashChecksumFault : 0|1@1+ (1,0) [0|1] "" External_Tool + +BO_ 500 XCP_MRR_DAQ_RESP: 8 MRR + SG_ MRR_xcp_daq_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 499 XCP_MRR_DTO_RESP: 8 MRR + SG_ MRR_xcp_dto_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 497 XCP_MRR_CTO_RESP: 8 MRR + SG_ MRR_xcp_cto_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 1900 Ford_Diag_Resp_Phys: 8 MRR + SG_ TesterPhysicalResCCM : 7|64@0+ (1,0) [0|1.84467e+19] "" IFV_Host + +BO_ 261 MRR_Status_SerialNumber: 8 MRR + SG_ CAN_SEQUENCE_NUMBER : 55|16@0+ (1,0) [0|65535] "" External_Tool + SG_ CAN_SERIAL_NUMBER : 7|40@0+ (1,0) [0|1.09951e+12] "" External_Tool + +BO_ 264 MRR_Status_SwVersion: 8 MRR + SG_ CAN_PBL_Field_Revision : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_PBL_Promote_Revision : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Field_Revision : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Promote_Revision : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Release_Revision : 7|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_PBL_Release_Revision : 31|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 373 MRR_Header_SensorPosition: 8 MRR + SG_ CAN_SENSOR_POLARITY : 55|1@0+ (1,0) [0|1] "" External_Tool + SG_ CAN_SENSOR_LAT_OFFSET : 39|16@0+ (0.01,0) [0|655.35] "cm" External_Tool + SG_ CAN_SENSOR_LONG_OFFSET : 23|16@0+ (0.01,0) [0|655.35] "cm" External_Tool + SG_ CAN_SENSOR_HANGLE_OFFSET : 7|8@0+ (0.0625,-8) [-8|7.9375] "deg" External_Tool + +BO_ 372 MRR_Header_SensorCoverage: 8 MRR + SG_ CAN_SENSOR_FOV_HOR : 39|8@0+ (1,0) [0|255] "deg" IFV_VFP + SG_ CAN_DOPPLER_COVERAGE : 23|8@0+ (1,-128) [-128|127] "m/s" IFV_VFP + SG_ CAN_RANGE_COVERAGE : 7|8@0+ (1,0) [0|255] "m" IFV_VFP + +BO_ 371 MRR_Header_AlignmentState: 8 MRR + SG_ CAN_AUTO_ALIGN_HANGLE_QF : 13|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_ALIGNMENT_STATUS : 51|4@0+ (1,0) [0|11] "" IFV_VFP + SG_ CAN_ALIGNMENT_STATE : 55|3@0+ (1,0) [0|7] "" IFV_VFP + SG_ CAN_AUTO_ALIGN_HANGLE_REF : 11|10@0+ (0.000341218,-0.174533) [-0.174533|0.174533] "rad" IFV_VFP + SG_ CAN_AUTO_ALIGN_HANGLE : 7|10@0+ (0.000341218,-0.174533) [-0.174533|0.174533] "rad" IFV_VFP + +BO_ 369 MRR_Header_Timestamps: 8 MRR + SG_ CAN_DET_TIME_SINCE_MEAS : 39|11@0+ (0.1,0) [0|204.7] "ms" IFV_Host + SG_ CAN_SENSOR_TIME_STAMP : 7|32@0+ (0.1,0) [0|4.29497e+08] "ms" IFV_VFP + +BO_ 368 MRR_Header_InformationDetections: 8 MRR + SG_ CAN_ALIGN_UPDATES_DONE : 55|16@0+ (1,0) [0|65535] "" IFV_VFP + SG_ CAN_SCAN_INDEX : 31|16@0+ (1,0) [0|65535] "" IFV_VFP + SG_ CAN_NUMBER_OF_DET : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_LOOK_ID : 23|2@0+ (1,0) [0|3] "" External_Tool + SG_ CAN_LOOK_INDEX : 7|16@0+ (1,0) [0|65535] "" External_Tool + +BO_ 265 MRR_Status_Temp_Volt: 8 MRR + SG_ CAN_BATT_VOLTS : 63|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_1_25_V : 55|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_5_V : 47|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_3_3_V_RAW : 31|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_3_3_V_DAC : 15|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_MMIC_Temp1 : 39|8@0+ (1,-50) [-50|205] "C" External_Tool + SG_ CAN_Processor_Thermistor : 23|8@0+ (1,-50) [-50|205] "C" External_Tool + SG_ CAN_Processor_Temp1 : 7|8@0+ (1,-50) [-50|205] "C" External_Tool + +BO_ 291 MRR_Detection_004: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_04_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_04_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_04_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_04_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_04_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_04_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_04_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_04_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_04_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_04_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_04_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_04_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_04_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_04_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_04_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 351 MRR_Detection_064: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_64 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_64 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_64 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_64 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_64 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_64 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_64 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_64 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_64 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_64 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 350 MRR_Detection_063: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_63 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_63 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_63 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_63 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_63 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_63 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_63 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_63 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_63 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_63 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 349 MRR_Detection_062: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_62 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_62 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_62 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_62 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_62 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_62 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_62 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_62 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_62 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_62 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 348 MRR_Detection_061: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_61 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_61 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_61 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_61 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_61 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_61 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_61 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_61 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_61 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_61 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 347 MRR_Detection_060: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_60 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_60 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_60 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_60 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_60 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_60 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_60 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_60 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_60 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_60 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 346 MRR_Detection_059: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_59 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_59 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_59 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_59 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_59 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_59 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_59 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_59 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_59 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_59 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 345 MRR_Detection_058: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_58 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_58 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_58 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_58 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_58 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_58 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_58 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_58 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_58 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_58 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 344 MRR_Detection_057: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_57 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_57 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_57 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_57 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_57 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_57 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_57 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_57 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_57 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_57 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 343 MRR_Detection_056: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_56 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_56 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_56 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_56 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_56 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_56 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_56 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_56 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_56 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_56 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 342 MRR_Detection_055: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_55 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_55 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_55 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_55 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_55 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_55 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_55 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_55 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_55 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_55 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 335 MRR_Detection_048: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_48 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_48 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_48 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_48 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_48 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_48 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_48 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_48 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_48 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_48 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 334 MRR_Detection_047: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_47 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_47 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_47 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_47 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_47 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_47 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_47 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_47 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_47 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_47 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 333 MRR_Detection_046: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_46 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_46 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_46 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_46 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_46 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_46 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_46 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_46 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_46 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_46 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 332 MRR_Detection_045: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_45 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_45 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_45 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_45 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_45 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_45 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_45 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_45 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_45 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_45 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 331 MRR_Detection_044: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_44 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_44 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_44 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_44 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_44 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_44 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_44 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_44 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_44 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_44 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 330 MRR_Detection_043: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_43 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_43 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_43 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_43 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_43 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_43 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_43 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_43 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_43 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_43 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 329 MRR_Detection_042: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_42 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_42 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_42 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_42 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_42 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_42 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_42 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_42 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_42 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_42 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 328 MRR_Detection_041: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_41 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_41 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_41 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_41 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_41 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_41 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_41 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_41 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_41 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_41 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 327 MRR_Detection_040: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_40 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_40 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_40 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_40 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_40 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_40 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_40 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_40 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_40 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_40 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 325 MRR_Detection_038: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_38 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_38 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_38 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_38 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_38 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_38 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_38 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_38 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_38 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_38 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 324 MRR_Detection_037: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_37 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_37 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_37 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_37 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_37 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_37 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_37 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_37 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_37 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_37 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 323 MRR_Detection_036: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_36 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_36 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_36 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_36 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_36 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_36 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_36 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_36 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_36 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_36 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 322 MRR_Detection_035: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_35 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_35 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_35 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_35 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_35 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_35 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_35 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_35 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_35 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_35 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 321 MRR_Detection_034: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_34 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_34 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_34 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_34 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_34 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_34 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_34 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_34 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_34 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_34 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 320 MRR_Detection_033: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_33 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_33 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_33 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_33 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_33 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_33 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_33 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_33 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_33 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_33 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 319 MRR_Detection_032: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_32 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_32 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_32 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_32 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_32 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_32 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_32 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_32 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_32 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_32 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 318 MRR_Detection_031: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_31 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_31 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_31 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_31 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_31 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_31 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_31 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_31 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_31 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_31 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 317 MRR_Detection_030: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_30 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_30 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_30 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_30 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_30 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_30 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_30 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_30 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_30 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_30 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 316 MRR_Detection_029: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_29 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_29 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_29 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_29 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_29 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_29 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_29 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_29 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_29 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_29 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 314 MRR_Detection_027: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_27 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_27 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_27 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_27 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_27 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_27 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_27 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_27 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_27 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_27 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 313 MRR_Detection_026: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_26 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_26 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_26 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_26 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_26 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_26 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_26 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_26 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_26 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_26 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 312 MRR_Detection_025: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_25 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_25 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_25 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_25 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_25 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_25 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_25 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_25 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_25 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_25 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 311 MRR_Detection_024: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_24 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_24 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_24 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_24 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_24 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_24 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_24 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_24 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_24 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_24 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 310 MRR_Detection_023: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_23 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_23 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_23 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_23 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_23 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_23 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_23 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_23 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_23 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_23 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 309 MRR_Detection_022: 24 MRR + SG_ CAN_DET_CONFID_AZIMUTH_22_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_22_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_22_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_22_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_22_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_22_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_22_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_22_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_22_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_22_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_22_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_22_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_22_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_22_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_22_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_22_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_22_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_22_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_22_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_22_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_22_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_22_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_22_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_22_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_22_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_22_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_22_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_22_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_22_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_22_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 308 MRR_Detection_021: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_21_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_21_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_21_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_21_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_21_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_21_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_21_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_21_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_21_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_21_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_21_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_21_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_21_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_21_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_21_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 307 MRR_Detection_020: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_20_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_20_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_20_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_20_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_20_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_20_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_20_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_20_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_20_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_20_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_20_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_20_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_20_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_20_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_20_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 306 MRR_Detection_019: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_19_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_19_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_19_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_19_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_19_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_19_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_19_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_19_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_19_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_19_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_19_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_19_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_19_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_19_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_19_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 305 MRR_Detection_018: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_18_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_18_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_18_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_18_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_18_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_18_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_18_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_18_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_18_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_18_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_18_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_18_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_18_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_18_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_18_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 341 MRR_Detection_054: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_54 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_54 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_54 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_54 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_54 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_54 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_54 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_54 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_54 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_54 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 340 MRR_Detection_053: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_53 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_53 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_53 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_53 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_53 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_53 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_53 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_53 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_53 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_53 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 339 MRR_Detection_052: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_52 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_52 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_52 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_52 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_52 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_52 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_52 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_52 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_52 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_52 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 338 MRR_Detection_051: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_51 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_51 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_51 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_51 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_51 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_51 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_51 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_51 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_51 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_51 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 337 MRR_Detection_050: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_50 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_50 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_50 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_50 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_50 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_50 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_50 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_50 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_50 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_50 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 336 MRR_Detection_049: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_49 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_49 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_49 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_49 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_49 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_49 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_49 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_49 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_49 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_49 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 326 MRR_Detection_039: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_39 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_39 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_39 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_39 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_39 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_39 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_39 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_39 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_39 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_39 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 315 MRR_Detection_028: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_28 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_28 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_28 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_28 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_28 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_28 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_28 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_28 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_28 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_28 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 304 MRR_Detection_017: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_17_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_17_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_17_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_17_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_17_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_17_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_17_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_17_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_17_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_17_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_17_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_17_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_17_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_17_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_17_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 303 MRR_Detection_016: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_16_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_16_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_16_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_16_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_16_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_16_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_16_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_16_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_16_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_16_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_16_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_16_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_16_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_16_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_16_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 302 MRR_Detection_015: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_15_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_15_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_15_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_15_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_15_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_15_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_15_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_15_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_15_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_15_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_15_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_15_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_15_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_15_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_15_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 301 MRR_Detection_014: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_14_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_14_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_14_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_14_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_14_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_14_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_14_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_14_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_14_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_14_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_14_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_14_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_14_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_14_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_14_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 300 MRR_Detection_013: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_13_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_13_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_13_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_13_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_13_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_13_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_13_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_13_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_13_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_13_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_13_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_13_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_13_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_13_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_13_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 299 MRR_Detection_012: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_12_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_12_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_12_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_12_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_12_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_12_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_12_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_12_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_12_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_12_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_12_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_12_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_12_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_12_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_12_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 298 MRR_Detection_011: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_11_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_11_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_11_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_11_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_11_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_11_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_11_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_11_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_11_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_11_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_11_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_11_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_11_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_11_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_11_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 297 MRR_Detection_010: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_10_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_10_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_10_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_10_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_10_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_10_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_10_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_10_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_10_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_10_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_10_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_10_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_10_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_10_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_10_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 296 MRR_Detection_009: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_09_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_09_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_09_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_09_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_09_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_09_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_09_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_09_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_09_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_09_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_09_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_09_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_09_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_09_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_09_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 295 MRR_Detection_008: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_08_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_08_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_08_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_08_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_08_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_08_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_08_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_08_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_08_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_08_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_08_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_08_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_08_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_08_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_08_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 294 MRR_Detection_007: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_07_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_07_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_07_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_07_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_07_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_07_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_07_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_07_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_07_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_07_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_07_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_07_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_07_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_07_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_07_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 293 MRR_Detection_006: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_06_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_06_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_06_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_06_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_06_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_06_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_06_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_06_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_06_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_06_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_06_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_06_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_06_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_06_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_06_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 292 MRR_Detection_005: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_05_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_05_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_05_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_05_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_05_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_05_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_05_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_05_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_05_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_05_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_05_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_05_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_05_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_05_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_05_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 290 MRR_Detection_003: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_03_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_03_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_03_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_03_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_03_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_03_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_03_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_03_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_03_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_03_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_03_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_03_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_03_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_03_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_03_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 289 MRR_Detection_002: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_02_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_02_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_02_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_02_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_02_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_02_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_02_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_02_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_02_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_02_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_02_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_02_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_02_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_02_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_02_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 256 MRR_Status_CANVersion: 8 MRR + SG_ CAN_USC_SECTION_COMPATIBILITY : 23|16@0+ (1,0) [0|65535] "" External_Tool + SG_ CAN_PCAN_MINOR_MRR : 7|8@0+ (1,0) [0|255] "" IFV_VFP + SG_ CAN_PCAN_MAJOR_MRR : 15|8@0+ (1,0) [0|255] "" IFV_VFP + +BO_ 257 MRR_Status_Radar: 8 MRR + SG_ CAN_INTERFERENCE_TYPE : 11|2@0+ (1,0) [0|3] "" IFV_Host + SG_ CAN_RECOMMEND_UNCONVERGE : 9|1@0+ (1,0) [0|1] "" IFV_Host + SG_ CAN_BLOCKAGE_SIDELOBE_FILTER_VAL : 15|4@0+ (1,0) [0|15] "" IFV_Host + SG_ CAN_RADAR_ALIGN_INCOMPLETE : 8|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_BLOCKAGE_SIDELOBE : 4|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_BLOCKAGE_MNR : 5|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_EXT_COND_NOK : 1|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_ALIGN_OUT_RANGE : 2|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_ALIGN_NOT_START : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_OVERHEAT_ERROR : 3|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_NOT_OP : 6|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_XCVR_OPERATIONAL : 7|1@0+ (1,0) [0|1] "" IFV_VFP + +BO_ 288 MRR_Detection_001: 64 MRR + SG_ CAN_DET_CONFID_AZIMUTH_01_01 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01_01 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01_01 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01_01 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01_01 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01_01 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01_01 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01_01 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01_01 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01_01 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_01_02 : 105|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01_02 : 128|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01_02 : 120|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01_02 : 121|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01_02 : 72|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01_02 : 119|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01_02 : 103|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01_02 : 87|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01_02 : 79|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01_02 : 89|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_01_03 : 177|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01_03 : 200|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01_03 : 192|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01_03 : 193|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01_03 : 144|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01_03 : 191|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01_03 : 175|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01_03 : 159|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01_03 : 151|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01_03 : 161|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_01_04 : 249|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01_04 : 272|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01_04 : 264|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01_04 : 265|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01_04 : 216|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01_04 : 263|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01_04 : 247|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01_04 : 231|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01_04 : 223|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01_04 : 233|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_01_05 : 321|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01_05 : 344|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01_05 : 336|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01_05 : 337|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01_05 : 288|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01_05 : 335|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01_05 : 319|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01_05 : 303|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01_05 : 295|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01_05 : 305|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_CONFID_AZIMUTH_01_06 : 393|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_01_06 : 416|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_01_06 : 408|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_01_06 : 409|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_01_06 : 360|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_01_06 : 407|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_01_06 : 391|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_01_06 : 375|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_01_06 : 367|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_01_06 : 377|2@0+ (1,0) [0|3] "" IFV_VFP + +BA_DEF_ SG_ "CrossOver_InfoCAN" ENUM "No","Yes"; +BA_DEF_ SG_ "CrossOver_LIN" ENUM "No","Yes","No","Yes"; +BA_DEF_ SG_ "UsedOnPgmDBC" ENUM "No","Yes","No","Yes","No","Yes"; +BA_DEF_ SG_ "ContentDependant" ENUM "No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ SG_ "GenSigTimeoutTime_RCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_GWM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_OCS" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ABS_ESC" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_CCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_IPMA" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TSTR" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_SCCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_PSCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime__delete" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_Generic_BCM" INT 0 100000; +BA_DEF_ BO_ "NmMessage" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "DiagResponse" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "DiagRequest" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "TpTxIndex" INT 0 255; +BA_DEF_ BO_ "DiagState" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "TpApplType" STRING ; +BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "Mulitplexer" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "ConfiguredTransmitter" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "EventRateOfChange" INT 10 10000; +BA_DEF_ BO_ "GenMsgHandlingTypeDoc" STRING ; +BA_DEF_ BO_ "GenMsgHandlingTypeCode" STRING ; +BA_DEF_ BO_ "GenMsgMarked" STRING ; +BA_DEF_ SG_ "GenSigMarked" STRING ; +BA_DEF_ SG_ "GenSigVtIndex" STRING ; +BA_DEF_ SG_ "GenSigVtName" STRING ; +BA_DEF_ SG_ "GenSigVtEn" STRING ; +BA_DEF_ SG_ "GenSigSNA" STRING ; +BA_DEF_ SG_ "GenSigCmt" STRING ; +BA_DEF_ BO_ "GenMsgCmt" STRING ; +BA_DEF_ SG_ "GenSigSendType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType"; +BA_DEF_ SG_ "GenSigInactiveValue" INT 0 100000; +BA_DEF_ SG_ "GenSigMissingSourceValue" INT 0 1e+09; +BA_DEF_ SG_ "WakeupSignal" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes"; +BA_DEF_ SG_ "GenSigStartValue" INT 0 1e+09; +BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes"; +BA_DEF_ BO_ "NetworkInitializationCommand" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "GenMsgSendType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType"; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000; +BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 100000; +BA_DEF_ BO_ "GenMsgDelayTime" INT 0 1000; +BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100; +BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 10000; +BA_DEF_ BO_ "NetworkInitialization" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes"; +BA_DEF_ BO_ "MessageGateway" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes"; +BA_DEF_ BU_ "ILUsed" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BU_ "NetworkInitializationUsed" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BU_ "PowerType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes","No","Yes","Switched","Latched","Sleep","vector_leerstring","vector_leerstring"; +BA_DEF_ BU_ "NodeStartUpTime" INT 0 10000; +BA_DEF_ BU_ "NodeWakeUpTime" INT 0 10000; +BA_DEF_ BO_ "GenMsgBackgroundColor" STRING ; +BA_DEF_ BO_ "GenMsgForegroundColor" STRING ; +BA_ "GenMsgCycleTime" BO_ 34 1000; +BA_ "GenMsgSendType" BO_ 34 0; +BA_ "GenSigVtEn" SG_ 34 IPMA_PCAN_DataRangeCheck "IPMA_PCAN_DataRangeCheck"; +BA_ "GenSigVtName" SG_ 34 IPMA_PCAN_DataRangeCheck "IPMA_PCAN_DataRangeCheck"; +BA_ "GenSigVtEn" SG_ 34 IPMA_PCAN_MissingMsg "IPMA_PCAN_MissingMsg"; +BA_ "GenSigVtName" SG_ 34 IPMA_PCAN_MissingMsg "IPMA_PCAN_MissingMsg"; +BA_ "GenSigVtEn" SG_ 34 VINSignalCompareFailure "VINSignalCompareFailure"; +BA_ "GenSigVtName" SG_ 34 VINSignalCompareFailure "VINSignalCompareFailure"; +BA_ "GenSigVtEn" SG_ 34 ModuleNotConfiguredError "ModuleNotConfiguredError"; +BA_ "GenSigVtName" SG_ 34 ModuleNotConfiguredError "ModuleNotConfiguredError"; +BA_ "GenSigVtEn" SG_ 34 CarCfgNotConfiguredError "CarCfgNotConfiguredError"; +BA_ "GenSigVtName" SG_ 34 CarCfgNotConfiguredError "CarCfgNotConfiguredError"; +BA_ "GenMsgCycleTime" BO_ 33 1000; +BA_ "GenMsgSendType" BO_ 33 0; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit7 "Active_Flt_Latched_byte7_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit7 "Active_Flt_Latched_byte7_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit6 "Active_Flt_Latched_byte7_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit6 "Active_Flt_Latched_byte7_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit5 "Active_Flt_Latched_byte7_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit5 "Active_Flt_Latched_byte7_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit4 "Active_Flt_Latched_byte7_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit4 "Active_Flt_Latched_byte7_bit4"; +BA_ "GenSigVtEn" SG_ 33 ARMtoDSPChksumFault "ARMtoDSPChksumFault"; +BA_ "GenSigVtName" SG_ 33 ARMtoDSPChksumFault "ARMtoDSPChksumFault"; +BA_ "GenSigVtEn" SG_ 33 DSPtoArmChksumFault "DSPtoArmChksumFault"; +BA_ "GenSigVtName" SG_ 33 DSPtoArmChksumFault "DSPtoArmChksumFault"; +BA_ "GenSigVtEn" SG_ 33 HostToArmChksumFault "HostToArmChksumFault"; +BA_ "GenSigVtName" SG_ 33 HostToArmChksumFault "HostToArmChksumFault"; +BA_ "GenSigVtEn" SG_ 33 ARMtoHostChksumFault "ARMtoHostChksumFault"; +BA_ "GenSigVtName" SG_ 33 ARMtoHostChksumFault "ARMtoHostChksumFault"; +BA_ "GenSigVtEn" SG_ 33 LoopBWOutOfRange "LoopBWOutOfRange"; +BA_ "GenSigVtName" SG_ 33 LoopBWOutOfRange "LoopBWOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 DSPOverrunFault "DSPOverrunFault"; +BA_ "GenSigVtName" SG_ 33 DSPOverrunFault "DSPOverrunFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte6_bit5 "Active_Flt_Latched_byte6_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte6_bit5 "Active_Flt_Latched_byte6_bit5"; +BA_ "GenSigVtEn" SG_ 33 TuningSensitivityFault "TuningSensitivityFault"; +BA_ "GenSigVtName" SG_ 33 TuningSensitivityFault "TuningSensitivityFault"; +BA_ "GenSigVtEn" SG_ 33 SaturatedTuningFreqFault "SaturatedTuningFreqFault"; +BA_ "GenSigVtName" SG_ 33 SaturatedTuningFreqFault "SaturatedTuningFreqFault"; +BA_ "GenSigVtEn" SG_ 33 LocalOscPowerFault "LocalOscPowerFault"; +BA_ "GenSigVtName" SG_ 33 LocalOscPowerFault "LocalOscPowerFault"; +BA_ "GenSigVtEn" SG_ 33 TransmitterPowerFault "TransmitterPowerFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterPowerFault "TransmitterPowerFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte6_bit0 "Active_Flt_Latched_byte6_bit0"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte6_bit0 "Active_Flt_Latched_byte6_bit0"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit7 "Active_Flt_Latched_byte5_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit7 "Active_Flt_Latched_byte5_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit6 "Active_Flt_Latched_byte5_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit6 "Active_Flt_Latched_byte5_bit6"; +BA_ "GenSigVtEn" SG_ 33 XCVRDeviceSPIFault "XCVRDeviceSPIFault"; +BA_ "GenSigVtName" SG_ 33 XCVRDeviceSPIFault "XCVRDeviceSPIFault"; +BA_ "GenSigVtEn" SG_ 33 FreqSynthesizerSPIFault "FreqSynthesizerSPIFault"; +BA_ "GenSigVtName" SG_ 33 FreqSynthesizerSPIFault "FreqSynthesizerSPIFault"; +BA_ "GenSigVtEn" SG_ 33 AnalogConverterDevicSPIFault "AnalogConverterDevicSPIFault"; +BA_ "GenSigVtName" SG_ 33 AnalogConverterDevicSPIFault "AnalogConverterDevicSPIFault"; +BA_ "GenSigVtEn" SG_ 33 SidelobeBlockage "SidelobeBlockage"; +BA_ "GenSigVtName" SG_ 33 SidelobeBlockage "SidelobeBlockage"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit1 "Active_Flt_Latched_byte5_bit1"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit1 "Active_Flt_Latched_byte5_bit1"; +BA_ "GenSigVtEn" SG_ 33 MNRBlocked "MNRBlocked"; +BA_ "GenSigVtName" SG_ 33 MNRBlocked "MNRBlocked"; +BA_ "GenSigVtEn" SG_ 33 ECUTempHighFault "ECUTempHighFault"; +BA_ "GenSigVtName" SG_ 33 ECUTempHighFault "ECUTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 TransmitterTempHighFault "TransmitterTempHighFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterTempHighFault "TransmitterTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 AlignmentRoutineFailedFault "AlignmentRoutineFailedFault"; +BA_ "GenSigVtName" SG_ 33 AlignmentRoutineFailedFault "AlignmentRoutineFailedFault"; +BA_ "GenSigVtEn" SG_ 33 UnreasonableRadarData "UnreasonableRadarData"; +BA_ "GenSigVtName" SG_ 33 UnreasonableRadarData "UnreasonableRadarData"; +BA_ "GenSigVtEn" SG_ 33 MicroprocessorTempHighFault "MicroprocessorTempHighFault"; +BA_ "GenSigVtName" SG_ 33 MicroprocessorTempHighFault "MicroprocessorTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 VerticalAlignmentOutOfRange "VerticalAlignmentOutOfRange"; +BA_ "GenSigVtName" SG_ 33 VerticalAlignmentOutOfRange "VerticalAlignmentOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 HorizontalAlignmentOutOfRange "HorizontalAlignmentOutOfRange"; +BA_ "GenSigVtName" SG_ 33 HorizontalAlignmentOutOfRange "HorizontalAlignmentOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 FactoryAlignmentMode "FactoryAlignmentMode"; +BA_ "GenSigVtName" SG_ 33 FactoryAlignmentMode "FactoryAlignmentMode"; +BA_ "GenSigVtEn" SG_ 33 BatteryLowFault "BatteryLowFault"; +BA_ "GenSigVtName" SG_ 33 BatteryLowFault "BatteryLowFault"; +BA_ "GenSigVtEn" SG_ 33 BatteryHighFault "BatteryHighFault"; +BA_ "GenSigVtName" SG_ 33 BatteryHighFault "BatteryHighFault"; +BA_ "GenSigVtEn" SG_ 33 v_1p25SupplyOutOfRange "v_1p25SupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_1p25SupplyOutOfRange "v_1p25SupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte3_bit4 "Active_Flt_Latched_byte3_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte3_bit4 "Active_Flt_Latched_byte3_bit4"; +BA_ "GenSigVtEn" SG_ 33 ThermistorOutOfRange "ThermistorOutOfRange"; +BA_ "GenSigVtName" SG_ 33 ThermistorOutOfRange "ThermistorOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_3p3DACSupplyOutOfRange "v_3p3DACSupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_3p3DACSupplyOutOfRange "v_3p3DACSupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_3p3RAWSupplyOutOfRange "v_3p3RAWSupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_3p3RAWSupplyOutOfRange "v_3p3RAWSupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_5_SupplyOutOfRange "v_5_SupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_5_SupplyOutOfRange "v_5_SupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 TransmitterIDFault "TransmitterIDFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterIDFault "TransmitterIDFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit6 "Active_Flt_Latched_byte2_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit6 "Active_Flt_Latched_byte2_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit5 "Active_Flt_Latched_byte2_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit5 "Active_Flt_Latched_byte2_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit4 "Active_Flt_Latched_byte2_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit4 "Active_Flt_Latched_byte2_bit4"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit3 "Active_Flt_Latched_byte2_bit3"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit3 "Active_Flt_Latched_byte2_bit3"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit2 "Active_Flt_Latched_byte2_bit2"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit2 "Active_Flt_Latched_byte2_bit2"; +BA_ "GenSigVtEn" SG_ 33 PCANMissingMsgFault "PCANMissingMsgFault"; +BA_ "GenSigVtName" SG_ 33 PCANMissingMsgFault "PCANMissingMsgFault"; +BA_ "GenSigVtEn" SG_ 33 PCANBusOff "PCANBusOff"; +BA_ "GenSigVtName" SG_ 33 PCANBusOff "PCANBusOff"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit7 "Active_Flt_Latched_byte1_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit7 "Active_Flt_Latched_byte1_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit6 "Active_Flt_Latched_byte1_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit6 "Active_Flt_Latched_byte1_bit6"; +BA_ "GenSigVtEn" SG_ 33 InstructionSetCheckFault "InstructionSetCheckFault"; +BA_ "GenSigVtName" SG_ 33 InstructionSetCheckFault "InstructionSetCheckFault"; +BA_ "GenSigVtEn" SG_ 33 StackOverflowFault "StackOverflowFault"; +BA_ "GenSigVtName" SG_ 33 StackOverflowFault "StackOverflowFault"; +BA_ "GenSigVtEn" SG_ 33 WatchdogFault "WatchdogFault"; +BA_ "GenSigVtName" SG_ 33 WatchdogFault "WatchdogFault"; +BA_ "GenSigVtEn" SG_ 33 PLLLockFault "PLLLockFault"; +BA_ "GenSigVtName" SG_ 33 PLLLockFault "PLLLockFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit1 "Active_Flt_Latched_byte1_bit1"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit1 "Active_Flt_Latched_byte1_bit1"; +BA_ "GenSigVtEn" SG_ 33 RAMMemoryTestFault "RAMMemoryTestFault"; +BA_ "GenSigVtName" SG_ 33 RAMMemoryTestFault "RAMMemoryTestFault"; +BA_ "GenSigVtName" SG_ 33 USCValidationFault "USCValidationFault"; +BA_ "GenSigVtEn" SG_ 33 USCValidationFault "USCValidationFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit6 "Active_Flt_Latched_byte0_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit6 "Active_Flt_Latched_byte0_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit5 "Active_Flt_Latched_byte0_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit5 "Active_Flt_Latched_byte0_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit4 "Active_Flt_Latched_byte0_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit4 "Active_Flt_Latched_byte0_bit4"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit3 "Active_Flt_Latched_byte0_bit3"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit3 "Active_Flt_Latched_byte0_bit3"; +BA_ "GenSigVtEn" SG_ 33 KeepAliveChecksumFault "KeepAliveChecksumFault"; +BA_ "GenSigVtName" SG_ 33 KeepAliveChecksumFault "KeepAliveChecksumFault"; +BA_ "GenSigVtEn" SG_ 33 ProgramCalibrationFlashChecksum "ProgramCalibrationFlashChecksum"; +BA_ "GenSigVtName" SG_ 33 ProgramCalibrationFlashChecksum "ProgramCalibrationFlashChecksum"; +BA_ "GenSigVtEn" SG_ 33 ApplicationFlashChecksumFault "ApplicationFlashChecksumFault"; +BA_ "GenSigVtName" SG_ 33 ApplicationFlashChecksumFault "ApplicationFlashChecksumFault"; +BA_ "GenMsgNrOfRepetition" BO_ 500 0; +BA_ "GenMsgSendType" BO_ 500 1; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte7 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte7 "MRR_xcp_daq_resp_byte7"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte6 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte6 "MRR_xcp_daq_resp_byte6"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte5 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte5 "MRR_xcp_daq_resp_byte5"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte4 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte4 "MRR_xcp_daq_resp_byte4"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte3 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte3 "MRR_xcp_daq_resp_byte3"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte2 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte2 "MRR_xcp_daq_resp_byte2"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte1 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte1 "MRR_xcp_daq_resp_byte1"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte0 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte0 "MRR_xcp_daq_resp_byte0"; +BA_ "GenMsgNrOfRepetition" BO_ 499 0; +BA_ "GenMsgSendType" BO_ 499 1; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte7 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte7 "MRR_xcp_dto_resp_byte7"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte6 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte6 "MRR_xcp_dto_resp_byte6"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte5 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte5 "MRR_xcp_dto_resp_byte5"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte4 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte4 "MRR_xcp_dto_resp_byte4"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte3 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte3 "MRR_xcp_dto_resp_byte3"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte2 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte2 "MRR_xcp_dto_resp_byte2"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte1 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte1 "MRR_xcp_dto_resp_byte1"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte0 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte0 "MRR_xcp_dto_resp_byte0"; +BA_ "GenMsgNrOfRepetition" BO_ 497 0; +BA_ "GenMsgSendType" BO_ 497 1; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte7 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte7 "MRR_xcp_cto_resp_byte7"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte6 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte6 "MRR_xcp_cto_resp_byte6"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte5 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte5 "MRR_xcp_cto_resp_byte5"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte4 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte4 "MRR_xcp_cto_resp_byte4"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte3 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte3 "MRR_xcp_cto_resp_byte3"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte2 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte2 "MRR_xcp_cto_resp_byte2"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte1 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte1 "MRR_xcp_cto_resp_byte1"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte0 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte0 "MRR_xcp_cto_resp_byte0"; +BA_ "GenMsgSendType" BO_ 1900 1; +BA_ "GenMsgNrOfRepetition" BO_ 1900 0; +BA_ "DiagResponse" BO_ 1900 1; +BA_ "GenSigCmt" SG_ 1900 TesterPhysicalResCCM "TesterPhysicalResCCM"; +BA_ "GenSigSendType" SG_ 1900 TesterPhysicalResCCM 0; +BA_ "GenMsgSendType" BO_ 261 0; +BA_ "GenMsgCycleTime" BO_ 261 1000; +BA_ "GenMsgNrOfRepetition" BO_ 261 0; +BA_ "GenSigCmt" SG_ 261 CAN_SEQUENCE_NUMBER "CAN_SEQUENCE_NUMBER"; +BA_ "GenSigCmt" SG_ 261 CAN_SERIAL_NUMBER "CAN_SERIAL_NUMBER"; +BA_ "GenSigSendType" SG_ 261 CAN_SERIAL_NUMBER 0; +BA_ "GenMsgSendType" BO_ 264 1; +BA_ "GenMsgNrOfRepetition" BO_ 264 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Field_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Promote_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Field_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Promote_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Release_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Release_Revision 0; +BA_ "GenMsgSendType" BO_ 373 1; +BA_ "NetworkInitialization" BO_ 373 0; +BA_ "GenMsgNrOfRepetition" BO_ 373 0; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_POLARITY 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_POLARITY "CAN_SENSOR_POLARITY"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_LAT_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_LAT_OFFSET "CAN_SENSOR_LAT_OFFSET"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_LONG_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_LONG_OFFSET "CAN_SENSOR_LONG_OFFSET"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_HANGLE_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_HANGLE_OFFSET "CAN_SENSOR_HANGLE_OFFSET"; +BA_ "GenSigStartValue" SG_ 373 CAN_SENSOR_HANGLE_OFFSET 0; +BA_ "GenMsgSendType" BO_ 372 1; +BA_ "NetworkInitialization" BO_ 372 0; +BA_ "GenMsgNrOfRepetition" BO_ 372 0; +BA_ "GenSigSendType" SG_ 372 CAN_SENSOR_FOV_HOR 0; +BA_ "GenSigCmt" SG_ 372 CAN_SENSOR_FOV_HOR "CAN_SENSOR_FOV_HOR"; +BA_ "GenSigStartValue" SG_ 372 CAN_SENSOR_FOV_HOR 0; +BA_ "GenSigSendType" SG_ 372 CAN_DOPPLER_COVERAGE 0; +BA_ "GenSigCmt" SG_ 372 CAN_DOPPLER_COVERAGE "CAN_DOPPLER_COVERAGE"; +BA_ "GenSigStartValue" SG_ 372 CAN_DOPPLER_COVERAGE 0; +BA_ "GenSigSendType" SG_ 372 CAN_RANGE_COVERAGE 0; +BA_ "GenSigCmt" SG_ 372 CAN_RANGE_COVERAGE "CAN_RANGE_COVERAGE"; +BA_ "GenMsgSendType" BO_ 371 1; +BA_ "NetworkInitialization" BO_ 371 0; +BA_ "GenMsgNrOfRepetition" BO_ 371 0; +BA_ "GenSigVtEn" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigVtName" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigVtEn" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigVtName" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigSendType" SG_ 371 CAN_ALIGNMENT_STATUS 0; +BA_ "GenSigCmt" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigVtEn" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigVtName" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigSendType" SG_ 371 CAN_ALIGNMENT_STATE 0; +BA_ "GenSigCmt" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF 0; +BA_ "GenSigStartValue" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF "CAN_AUTO_ALIGN_HANGLE_REF"; +BA_ "GenSigStartValue" SG_ 371 CAN_AUTO_ALIGN_HANGLE 0; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE "CAN_AUTO_ALIGN_HANGLE"; +BA_ "GenMsgSendType" BO_ 369 1; +BA_ "NetworkInitialization" BO_ 369 0; +BA_ "GenMsgNrOfRepetition" BO_ 369 0; +BA_ "GenSigCmt" SG_ 369 CAN_DET_TIME_SINCE_MEAS "CAN_DET_TIME_SINCE_MEAS"; +BA_ "GenSigSendType" SG_ 369 CAN_DET_TIME_SINCE_MEAS 0; +BA_ "GenSigSendType" SG_ 369 CAN_SENSOR_TIME_STAMP 0; +BA_ "GenSigCmt" SG_ 369 CAN_SENSOR_TIME_STAMP "CAN_SENSOR_TIME_STAMP"; +BA_ "GenMsgSendType" BO_ 368 1; +BA_ "NetworkInitialization" BO_ 368 0; +BA_ "GenMsgNrOfRepetition" BO_ 368 0; +BA_ "GenSigSendType" SG_ 368 CAN_ALIGN_UPDATES_DONE 0; +BA_ "GenSigCmt" SG_ 368 CAN_ALIGN_UPDATES_DONE "CAN_ALIGN_UPDATES_DONE"; +BA_ "GenSigSendType" SG_ 368 CAN_SCAN_INDEX 0; +BA_ "GenSigCmt" SG_ 368 CAN_SCAN_INDEX "CAN_SCAN_INDEX"; +BA_ "GenSigSendType" SG_ 368 CAN_NUMBER_OF_DET 0; +BA_ "GenSigCmt" SG_ 368 CAN_NUMBER_OF_DET "CAN_NUMBER_OF_DET"; +BA_ "GenSigSendType" SG_ 368 CAN_LOOK_ID 0; +BA_ "GenSigCmt" SG_ 368 CAN_LOOK_ID "CAN_LOOK_ID"; +BA_ "GenSigSendType" SG_ 368 CAN_LOOK_INDEX 0; +BA_ "GenSigCmt" SG_ 368 CAN_LOOK_INDEX "CAN_LOOK_INDEX"; +BA_ "GenMsgSendType" BO_ 265 1; +BA_ "NetworkInitialization" BO_ 265 0; +BA_ "GenMsgNrOfRepetition" BO_ 265 0; +BA_ "GenSigCmt" SG_ 265 CAN_BATT_VOLTS "CAN_BATT_VOLTS"; +BA_ "GenSigCmt" SG_ 265 CAN_1_25_V "CAN_1_25_V"; +BA_ "GenSigCmt" SG_ 265 CAN_5_V "CAN_5_V"; +BA_ "GenSigCmt" SG_ 265 CAN_3_3_V_RAW "CAN_3_3_V_RAW"; +BA_ "GenSigCmt" SG_ 265 CAN_3_3_V_DAC "CAN_3_3_V_DAC"; +BA_ "GenSigSendType" SG_ 265 CAN_MMIC_Temp1 0; +BA_ "GenSigCmt" SG_ 265 CAN_MMIC_Temp1 "CAN_MMIC_Temp1"; +BA_ "GenSigStartValue" SG_ 265 CAN_MMIC_Temp1 0; +BA_ "GenSigSendType" SG_ 265 CAN_Processor_Thermistor 0; +BA_ "GenSigCmt" SG_ 265 CAN_Processor_Thermistor "CAN_Processor_Thermistor"; +BA_ "GenSigStartValue" SG_ 265 CAN_Processor_Thermistor 0; +BA_ "GenSigSendType" SG_ 265 CAN_Processor_Temp1 0; +BA_ "GenSigCmt" SG_ 265 CAN_Processor_Temp1 "CAN_Processor_Temp1"; +BA_ "GenSigStartValue" SG_ 265 CAN_Processor_Temp1 0; +BA_ "GenMsgSendType" BO_ 291 1; +BA_ "GenMsgILSupport" BO_ 291 1; +BA_ "GenMsgNrOfRepetition" BO_ 291 0; +BA_ "GenMsgCycleTime" BO_ 291 0; +BA_ "NetworkInitialization" BO_ 291 0; +BA_ "GenMsgDelayTime" BO_ 291 0; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_01 "CAN_DET_CONFID_AZIMUTH_04_01"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_01 "CAN_DET_CONFID_AZIMUTH_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_01 "CAN_DET_CONFID_AZIMUTH_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_01 "CAN_DET_SUPER_RES_TARGET_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04_01 "CAN_DET_ND_TARGET_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_01 "CAN_DET_HOST_VEH_CLUTTER_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04_01 "CAN_DET_VALID_LEVEL_04_01"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04_01 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04_01 "CAN_DET_AZIMUTH_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04_01 "CAN_DET_RANGE_04_01"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04_01 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04_01 "CAN_DET_RANGE_RATE_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04_01 "CAN_DET_AMPLITUDE_04_01"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04_01 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04_01 "CAN_SCAN_INDEX_2LSB_04_01"; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_02 "CAN_DET_CONFID_AZIMUTH_04_02"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_02 "CAN_DET_CONFID_AZIMUTH_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_02 "CAN_DET_CONFID_AZIMUTH_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_02 "CAN_DET_SUPER_RES_TARGET_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04_02 "CAN_DET_ND_TARGET_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_02 "CAN_DET_HOST_VEH_CLUTTER_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04_02 "CAN_DET_VALID_LEVEL_04_02"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04_02 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04_02 "CAN_DET_AZIMUTH_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04_02 "CAN_DET_RANGE_04_02"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04_02 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04_02 "CAN_DET_RANGE_RATE_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04_02 "CAN_DET_AMPLITUDE_04_02"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04_02 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04_02 "CAN_SCAN_INDEX_2LSB_04_02"; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_03 "CAN_DET_CONFID_AZIMUTH_04_03"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_03 "CAN_DET_CONFID_AZIMUTH_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_03 "CAN_DET_CONFID_AZIMUTH_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_03 "CAN_DET_SUPER_RES_TARGET_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04_03 "CAN_DET_ND_TARGET_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_03 "CAN_DET_HOST_VEH_CLUTTER_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04_03 "CAN_DET_VALID_LEVEL_04_03"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04_03 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04_03 "CAN_DET_AZIMUTH_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04_03 "CAN_DET_RANGE_04_03"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04_03 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04_03 "CAN_DET_RANGE_RATE_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04_03 "CAN_DET_AMPLITUDE_04_03"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04_03 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04_03 "CAN_SCAN_INDEX_2LSB_04_03"; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_04 "CAN_DET_CONFID_AZIMUTH_04_04"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_04 "CAN_DET_CONFID_AZIMUTH_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_04 "CAN_DET_CONFID_AZIMUTH_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_04 "CAN_DET_SUPER_RES_TARGET_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04_04 "CAN_DET_ND_TARGET_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_04 "CAN_DET_HOST_VEH_CLUTTER_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04_04 "CAN_DET_VALID_LEVEL_04_04"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04_04 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04_04 "CAN_DET_AZIMUTH_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04_04 "CAN_DET_RANGE_04_04"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04_04 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04_04 "CAN_DET_RANGE_RATE_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04_04 "CAN_DET_AMPLITUDE_04_04"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04_04 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04_04 "CAN_SCAN_INDEX_2LSB_04_04"; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_05 "CAN_DET_CONFID_AZIMUTH_04_05"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_05 "CAN_DET_CONFID_AZIMUTH_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_05 "CAN_DET_CONFID_AZIMUTH_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_05 "CAN_DET_SUPER_RES_TARGET_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04_05 "CAN_DET_ND_TARGET_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_05 "CAN_DET_HOST_VEH_CLUTTER_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04_05 "CAN_DET_VALID_LEVEL_04_05"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04_05 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04_05 "CAN_DET_AZIMUTH_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04_05 "CAN_DET_RANGE_04_05"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04_05 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04_05 "CAN_DET_RANGE_RATE_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04_05 "CAN_DET_AMPLITUDE_04_05"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04_05 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04_05 "CAN_SCAN_INDEX_2LSB_04_05"; +BA_ "GenSigVtEn" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_06 "CAN_DET_CONFID_AZIMUTH_04_06"; +BA_ "GenSigVtName" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_06 "CAN_DET_CONFID_AZIMUTH_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_CONFID_AZIMUTH_04_06 "CAN_DET_CONFID_AZIMUTH_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_SUPER_RES_TARGET_04_06 "CAN_DET_SUPER_RES_TARGET_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_ND_TARGET_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_ND_TARGET_04_06 "CAN_DET_ND_TARGET_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_HOST_VEH_CLUTTER_04_06 "CAN_DET_HOST_VEH_CLUTTER_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_VALID_LEVEL_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_VALID_LEVEL_04_06 "CAN_DET_VALID_LEVEL_04_06"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_AZIMUTH_04_06 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AZIMUTH_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AZIMUTH_04_06 "CAN_DET_AZIMUTH_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_04_06 "CAN_DET_RANGE_04_06"; +BA_ "GenSigStartValue" SG_ 291 CAN_DET_RANGE_RATE_04_06 0; +BA_ "GenSigSendType" SG_ 291 CAN_DET_RANGE_RATE_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_RANGE_RATE_04_06 "CAN_DET_RANGE_RATE_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_DET_AMPLITUDE_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_DET_AMPLITUDE_04_06 "CAN_DET_AMPLITUDE_04_06"; +BA_ "GenSigSendType" SG_ 291 CAN_SCAN_INDEX_2LSB_04_06 0; +BA_ "GenSigCmt" SG_ 291 CAN_SCAN_INDEX_2LSB_04_06 "CAN_SCAN_INDEX_2LSB_04_06"; +BA_ "GenMsgSendType" BO_ 351 1; +BA_ "GenMsgILSupport" BO_ 351 1; +BA_ "GenMsgNrOfRepetition" BO_ 351 0; +BA_ "GenMsgCycleTime" BO_ 351 0; +BA_ "NetworkInitialization" BO_ 351 0; +BA_ "GenMsgDelayTime" BO_ 351 0; +BA_ "GenSigVtEn" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigVtName" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_SUPER_RES_TARGET_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_SUPER_RES_TARGET_64 "CAN_DET_SUPER_RES_TARGET_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_ND_TARGET_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_ND_TARGET_64 "CAN_DET_ND_TARGET_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_HOST_VEH_CLUTTER_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_HOST_VEH_CLUTTER_64 "CAN_DET_HOST_VEH_CLUTTER_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_VALID_LEVEL_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_VALID_LEVEL_64 "CAN_DET_VALID_LEVEL_64"; +BA_ "GenSigStartValue" SG_ 351 CAN_DET_AZIMUTH_64 0; +BA_ "GenSigSendType" SG_ 351 CAN_DET_AZIMUTH_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_AZIMUTH_64 "CAN_DET_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_RANGE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_RANGE_64 "CAN_DET_RANGE_64"; +BA_ "GenSigStartValue" SG_ 351 CAN_DET_RANGE_RATE_64 0; +BA_ "GenSigSendType" SG_ 351 CAN_DET_RANGE_RATE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_RANGE_RATE_64 "CAN_DET_RANGE_RATE_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_AMPLITUDE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_AMPLITUDE_64 "CAN_DET_AMPLITUDE_64"; +BA_ "GenSigSendType" SG_ 351 CAN_SCAN_INDEX_2LSB_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_SCAN_INDEX_2LSB_64 "CAN_SCAN_INDEX_2LSB_64"; +BA_ "GenMsgSendType" BO_ 350 1; +BA_ "GenMsgILSupport" BO_ 350 1; +BA_ "GenMsgNrOfRepetition" BO_ 350 0; +BA_ "GenMsgCycleTime" BO_ 350 0; +BA_ "NetworkInitialization" BO_ 350 0; +BA_ "GenMsgDelayTime" BO_ 350 0; +BA_ "GenSigVtEn" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigVtName" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_SUPER_RES_TARGET_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_SUPER_RES_TARGET_63 "CAN_DET_SUPER_RES_TARGET_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_ND_TARGET_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_ND_TARGET_63 "CAN_DET_ND_TARGET_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_HOST_VEH_CLUTTER_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_HOST_VEH_CLUTTER_63 "CAN_DET_HOST_VEH_CLUTTER_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_VALID_LEVEL_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_VALID_LEVEL_63 "CAN_DET_VALID_LEVEL_63"; +BA_ "GenSigStartValue" SG_ 350 CAN_DET_AZIMUTH_63 0; +BA_ "GenSigSendType" SG_ 350 CAN_DET_AZIMUTH_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_AZIMUTH_63 "CAN_DET_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_RANGE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_RANGE_63 "CAN_DET_RANGE_63"; +BA_ "GenSigStartValue" SG_ 350 CAN_DET_RANGE_RATE_63 0; +BA_ "GenSigSendType" SG_ 350 CAN_DET_RANGE_RATE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_RANGE_RATE_63 "CAN_DET_RANGE_RATE_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_AMPLITUDE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_AMPLITUDE_63 "CAN_DET_AMPLITUDE_63"; +BA_ "GenSigSendType" SG_ 350 CAN_SCAN_INDEX_2LSB_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_SCAN_INDEX_2LSB_63 "CAN_SCAN_INDEX_2LSB_63"; +BA_ "GenMsgSendType" BO_ 349 1; +BA_ "GenMsgILSupport" BO_ 349 1; +BA_ "GenMsgNrOfRepetition" BO_ 349 0; +BA_ "GenMsgCycleTime" BO_ 349 0; +BA_ "NetworkInitialization" BO_ 349 0; +BA_ "GenMsgDelayTime" BO_ 349 0; +BA_ "GenSigVtEn" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigVtName" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_SUPER_RES_TARGET_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_SUPER_RES_TARGET_62 "CAN_DET_SUPER_RES_TARGET_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_ND_TARGET_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_ND_TARGET_62 "CAN_DET_ND_TARGET_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_HOST_VEH_CLUTTER_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_HOST_VEH_CLUTTER_62 "CAN_DET_HOST_VEH_CLUTTER_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_VALID_LEVEL_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_VALID_LEVEL_62 "CAN_DET_VALID_LEVEL_62"; +BA_ "GenSigStartValue" SG_ 349 CAN_DET_AZIMUTH_62 0; +BA_ "GenSigSendType" SG_ 349 CAN_DET_AZIMUTH_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_AZIMUTH_62 "CAN_DET_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_RANGE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_RANGE_62 "CAN_DET_RANGE_62"; +BA_ "GenSigStartValue" SG_ 349 CAN_DET_RANGE_RATE_62 0; +BA_ "GenSigSendType" SG_ 349 CAN_DET_RANGE_RATE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_RANGE_RATE_62 "CAN_DET_RANGE_RATE_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_AMPLITUDE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_AMPLITUDE_62 "CAN_DET_AMPLITUDE_62"; +BA_ "GenSigSendType" SG_ 349 CAN_SCAN_INDEX_2LSB_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_SCAN_INDEX_2LSB_62 "CAN_SCAN_INDEX_2LSB_62"; +BA_ "GenMsgSendType" BO_ 348 1; +BA_ "GenMsgILSupport" BO_ 348 1; +BA_ "GenMsgNrOfRepetition" BO_ 348 0; +BA_ "GenMsgCycleTime" BO_ 348 0; +BA_ "NetworkInitialization" BO_ 348 0; +BA_ "GenMsgDelayTime" BO_ 348 0; +BA_ "GenSigVtEn" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigVtName" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_SUPER_RES_TARGET_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_SUPER_RES_TARGET_61 "CAN_DET_SUPER_RES_TARGET_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_ND_TARGET_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_ND_TARGET_61 "CAN_DET_ND_TARGET_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_HOST_VEH_CLUTTER_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_HOST_VEH_CLUTTER_61 "CAN_DET_HOST_VEH_CLUTTER_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_VALID_LEVEL_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_VALID_LEVEL_61 "CAN_DET_VALID_LEVEL_61"; +BA_ "GenSigStartValue" SG_ 348 CAN_DET_AZIMUTH_61 0; +BA_ "GenSigSendType" SG_ 348 CAN_DET_AZIMUTH_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_AZIMUTH_61 "CAN_DET_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_RANGE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_RANGE_61 "CAN_DET_RANGE_61"; +BA_ "GenSigStartValue" SG_ 348 CAN_DET_RANGE_RATE_61 0; +BA_ "GenSigSendType" SG_ 348 CAN_DET_RANGE_RATE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_RANGE_RATE_61 "CAN_DET_RANGE_RATE_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_AMPLITUDE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_AMPLITUDE_61 "CAN_DET_AMPLITUDE_61"; +BA_ "GenSigSendType" SG_ 348 CAN_SCAN_INDEX_2LSB_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_SCAN_INDEX_2LSB_61 "CAN_SCAN_INDEX_2LSB_61"; +BA_ "GenMsgSendType" BO_ 347 1; +BA_ "GenMsgILSupport" BO_ 347 1; +BA_ "GenMsgNrOfRepetition" BO_ 347 0; +BA_ "GenMsgCycleTime" BO_ 347 0; +BA_ "NetworkInitialization" BO_ 347 0; +BA_ "GenMsgDelayTime" BO_ 347 0; +BA_ "GenSigVtEn" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigVtName" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_SUPER_RES_TARGET_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_SUPER_RES_TARGET_60 "CAN_DET_SUPER_RES_TARGET_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_ND_TARGET_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_ND_TARGET_60 "CAN_DET_ND_TARGET_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_HOST_VEH_CLUTTER_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_HOST_VEH_CLUTTER_60 "CAN_DET_HOST_VEH_CLUTTER_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_VALID_LEVEL_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_VALID_LEVEL_60 "CAN_DET_VALID_LEVEL_60"; +BA_ "GenSigStartValue" SG_ 347 CAN_DET_AZIMUTH_60 0; +BA_ "GenSigSendType" SG_ 347 CAN_DET_AZIMUTH_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_AZIMUTH_60 "CAN_DET_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_RANGE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_RANGE_60 "CAN_DET_RANGE_60"; +BA_ "GenSigStartValue" SG_ 347 CAN_DET_RANGE_RATE_60 0; +BA_ "GenSigSendType" SG_ 347 CAN_DET_RANGE_RATE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_RANGE_RATE_60 "CAN_DET_RANGE_RATE_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_AMPLITUDE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_AMPLITUDE_60 "CAN_DET_AMPLITUDE_60"; +BA_ "GenSigSendType" SG_ 347 CAN_SCAN_INDEX_2LSB_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_SCAN_INDEX_2LSB_60 "CAN_SCAN_INDEX_2LSB_60"; +BA_ "GenMsgSendType" BO_ 346 1; +BA_ "GenMsgILSupport" BO_ 346 1; +BA_ "GenMsgNrOfRepetition" BO_ 346 0; +BA_ "GenMsgCycleTime" BO_ 346 0; +BA_ "NetworkInitialization" BO_ 346 0; +BA_ "GenMsgDelayTime" BO_ 346 0; +BA_ "GenSigVtEn" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigVtName" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_SUPER_RES_TARGET_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_SUPER_RES_TARGET_59 "CAN_DET_SUPER_RES_TARGET_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_ND_TARGET_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_ND_TARGET_59 "CAN_DET_ND_TARGET_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_HOST_VEH_CLUTTER_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_HOST_VEH_CLUTTER_59 "CAN_DET_HOST_VEH_CLUTTER_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_VALID_LEVEL_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_VALID_LEVEL_59 "CAN_DET_VALID_LEVEL_59"; +BA_ "GenSigStartValue" SG_ 346 CAN_DET_AZIMUTH_59 0; +BA_ "GenSigSendType" SG_ 346 CAN_DET_AZIMUTH_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_AZIMUTH_59 "CAN_DET_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_RANGE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_RANGE_59 "CAN_DET_RANGE_59"; +BA_ "GenSigStartValue" SG_ 346 CAN_DET_RANGE_RATE_59 0; +BA_ "GenSigSendType" SG_ 346 CAN_DET_RANGE_RATE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_RANGE_RATE_59 "CAN_DET_RANGE_RATE_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_AMPLITUDE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_AMPLITUDE_59 "CAN_DET_AMPLITUDE_59"; +BA_ "GenSigSendType" SG_ 346 CAN_SCAN_INDEX_2LSB_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_SCAN_INDEX_2LSB_59 "CAN_SCAN_INDEX_2LSB_59"; +BA_ "GenMsgSendType" BO_ 345 1; +BA_ "GenMsgILSupport" BO_ 345 1; +BA_ "GenMsgNrOfRepetition" BO_ 345 0; +BA_ "GenMsgCycleTime" BO_ 345 0; +BA_ "NetworkInitialization" BO_ 345 0; +BA_ "GenMsgDelayTime" BO_ 345 0; +BA_ "GenSigVtEn" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigVtName" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_SUPER_RES_TARGET_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_SUPER_RES_TARGET_58 "CAN_DET_SUPER_RES_TARGET_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_ND_TARGET_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_ND_TARGET_58 "CAN_DET_ND_TARGET_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_HOST_VEH_CLUTTER_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_HOST_VEH_CLUTTER_58 "CAN_DET_HOST_VEH_CLUTTER_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_VALID_LEVEL_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_VALID_LEVEL_58 "CAN_DET_VALID_LEVEL_58"; +BA_ "GenSigStartValue" SG_ 345 CAN_DET_AZIMUTH_58 0; +BA_ "GenSigSendType" SG_ 345 CAN_DET_AZIMUTH_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_AZIMUTH_58 "CAN_DET_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_RANGE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_RANGE_58 "CAN_DET_RANGE_58"; +BA_ "GenSigStartValue" SG_ 345 CAN_DET_RANGE_RATE_58 0; +BA_ "GenSigSendType" SG_ 345 CAN_DET_RANGE_RATE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_RANGE_RATE_58 "CAN_DET_RANGE_RATE_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_AMPLITUDE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_AMPLITUDE_58 "CAN_DET_AMPLITUDE_58"; +BA_ "GenSigSendType" SG_ 345 CAN_SCAN_INDEX_2LSB_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_SCAN_INDEX_2LSB_58 "CAN_SCAN_INDEX_2LSB_58"; +BA_ "GenMsgSendType" BO_ 344 1; +BA_ "GenMsgILSupport" BO_ 344 1; +BA_ "GenMsgNrOfRepetition" BO_ 344 0; +BA_ "GenMsgCycleTime" BO_ 344 0; +BA_ "NetworkInitialization" BO_ 344 0; +BA_ "GenMsgDelayTime" BO_ 344 0; +BA_ "GenSigVtEn" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigVtName" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_SUPER_RES_TARGET_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_SUPER_RES_TARGET_57 "CAN_DET_SUPER_RES_TARGET_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_ND_TARGET_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_ND_TARGET_57 "CAN_DET_ND_TARGET_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_HOST_VEH_CLUTTER_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_HOST_VEH_CLUTTER_57 "CAN_DET_HOST_VEH_CLUTTER_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_VALID_LEVEL_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_VALID_LEVEL_57 "CAN_DET_VALID_LEVEL_57"; +BA_ "GenSigStartValue" SG_ 344 CAN_DET_AZIMUTH_57 0; +BA_ "GenSigSendType" SG_ 344 CAN_DET_AZIMUTH_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_AZIMUTH_57 "CAN_DET_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_RANGE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_RANGE_57 "CAN_DET_RANGE_57"; +BA_ "GenSigStartValue" SG_ 344 CAN_DET_RANGE_RATE_57 0; +BA_ "GenSigSendType" SG_ 344 CAN_DET_RANGE_RATE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_RANGE_RATE_57 "CAN_DET_RANGE_RATE_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_AMPLITUDE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_AMPLITUDE_57 "CAN_DET_AMPLITUDE_57"; +BA_ "GenSigSendType" SG_ 344 CAN_SCAN_INDEX_2LSB_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_SCAN_INDEX_2LSB_57 "CAN_SCAN_INDEX_2LSB_57"; +BA_ "GenMsgSendType" BO_ 343 1; +BA_ "GenMsgILSupport" BO_ 343 1; +BA_ "GenMsgNrOfRepetition" BO_ 343 0; +BA_ "GenMsgCycleTime" BO_ 343 0; +BA_ "NetworkInitialization" BO_ 343 0; +BA_ "GenMsgDelayTime" BO_ 343 0; +BA_ "GenSigVtEn" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigVtName" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_SUPER_RES_TARGET_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_SUPER_RES_TARGET_56 "CAN_DET_SUPER_RES_TARGET_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_ND_TARGET_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_ND_TARGET_56 "CAN_DET_ND_TARGET_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_HOST_VEH_CLUTTER_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_HOST_VEH_CLUTTER_56 "CAN_DET_HOST_VEH_CLUTTER_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_VALID_LEVEL_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_VALID_LEVEL_56 "CAN_DET_VALID_LEVEL_56"; +BA_ "GenSigStartValue" SG_ 343 CAN_DET_AZIMUTH_56 0; +BA_ "GenSigSendType" SG_ 343 CAN_DET_AZIMUTH_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_AZIMUTH_56 "CAN_DET_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_RANGE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_RANGE_56 "CAN_DET_RANGE_56"; +BA_ "GenSigStartValue" SG_ 343 CAN_DET_RANGE_RATE_56 0; +BA_ "GenSigSendType" SG_ 343 CAN_DET_RANGE_RATE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_RANGE_RATE_56 "CAN_DET_RANGE_RATE_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_AMPLITUDE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_AMPLITUDE_56 "CAN_DET_AMPLITUDE_56"; +BA_ "GenSigSendType" SG_ 343 CAN_SCAN_INDEX_2LSB_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_SCAN_INDEX_2LSB_56 "CAN_SCAN_INDEX_2LSB_56"; +BA_ "GenMsgSendType" BO_ 342 1; +BA_ "GenMsgILSupport" BO_ 342 1; +BA_ "GenMsgNrOfRepetition" BO_ 342 0; +BA_ "GenMsgCycleTime" BO_ 342 0; +BA_ "NetworkInitialization" BO_ 342 0; +BA_ "GenMsgDelayTime" BO_ 342 0; +BA_ "GenSigVtEn" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigVtName" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_SUPER_RES_TARGET_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_SUPER_RES_TARGET_55 "CAN_DET_SUPER_RES_TARGET_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_ND_TARGET_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_ND_TARGET_55 "CAN_DET_ND_TARGET_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_HOST_VEH_CLUTTER_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_HOST_VEH_CLUTTER_55 "CAN_DET_HOST_VEH_CLUTTER_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_VALID_LEVEL_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_VALID_LEVEL_55 "CAN_DET_VALID_LEVEL_55"; +BA_ "GenSigStartValue" SG_ 342 CAN_DET_AZIMUTH_55 0; +BA_ "GenSigSendType" SG_ 342 CAN_DET_AZIMUTH_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_AZIMUTH_55 "CAN_DET_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_RANGE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_RANGE_55 "CAN_DET_RANGE_55"; +BA_ "GenSigStartValue" SG_ 342 CAN_DET_RANGE_RATE_55 0; +BA_ "GenSigSendType" SG_ 342 CAN_DET_RANGE_RATE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_RANGE_RATE_55 "CAN_DET_RANGE_RATE_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_AMPLITUDE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_AMPLITUDE_55 "CAN_DET_AMPLITUDE_55"; +BA_ "GenSigSendType" SG_ 342 CAN_SCAN_INDEX_2LSB_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_SCAN_INDEX_2LSB_55 "CAN_SCAN_INDEX_2LSB_55"; +BA_ "GenMsgSendType" BO_ 335 1; +BA_ "GenMsgILSupport" BO_ 335 1; +BA_ "GenMsgNrOfRepetition" BO_ 335 0; +BA_ "GenMsgCycleTime" BO_ 335 0; +BA_ "NetworkInitialization" BO_ 335 0; +BA_ "GenMsgDelayTime" BO_ 335 0; +BA_ "GenSigVtEn" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigVtName" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_SUPER_RES_TARGET_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_SUPER_RES_TARGET_48 "CAN_DET_SUPER_RES_TARGET_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_ND_TARGET_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_ND_TARGET_48 "CAN_DET_ND_TARGET_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_HOST_VEH_CLUTTER_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_HOST_VEH_CLUTTER_48 "CAN_DET_HOST_VEH_CLUTTER_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_VALID_LEVEL_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_VALID_LEVEL_48 "CAN_DET_VALID_LEVEL_48"; +BA_ "GenSigStartValue" SG_ 335 CAN_DET_AZIMUTH_48 0; +BA_ "GenSigSendType" SG_ 335 CAN_DET_AZIMUTH_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_AZIMUTH_48 "CAN_DET_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_RANGE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_RANGE_48 "CAN_DET_RANGE_48"; +BA_ "GenSigStartValue" SG_ 335 CAN_DET_RANGE_RATE_48 0; +BA_ "GenSigSendType" SG_ 335 CAN_DET_RANGE_RATE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_RANGE_RATE_48 "CAN_DET_RANGE_RATE_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_AMPLITUDE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_AMPLITUDE_48 "CAN_DET_AMPLITUDE_48"; +BA_ "GenSigSendType" SG_ 335 CAN_SCAN_INDEX_2LSB_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_SCAN_INDEX_2LSB_48 "CAN_SCAN_INDEX_2LSB_48"; +BA_ "GenMsgSendType" BO_ 334 1; +BA_ "GenMsgILSupport" BO_ 334 1; +BA_ "GenMsgNrOfRepetition" BO_ 334 0; +BA_ "GenMsgCycleTime" BO_ 334 0; +BA_ "NetworkInitialization" BO_ 334 0; +BA_ "GenMsgDelayTime" BO_ 334 0; +BA_ "GenSigVtEn" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigVtName" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_SUPER_RES_TARGET_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_SUPER_RES_TARGET_47 "CAN_DET_SUPER_RES_TARGET_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_ND_TARGET_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_ND_TARGET_47 "CAN_DET_ND_TARGET_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_HOST_VEH_CLUTTER_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_HOST_VEH_CLUTTER_47 "CAN_DET_HOST_VEH_CLUTTER_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_VALID_LEVEL_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_VALID_LEVEL_47 "CAN_DET_VALID_LEVEL_47"; +BA_ "GenSigStartValue" SG_ 334 CAN_DET_AZIMUTH_47 0; +BA_ "GenSigSendType" SG_ 334 CAN_DET_AZIMUTH_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_AZIMUTH_47 "CAN_DET_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_RANGE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_RANGE_47 "CAN_DET_RANGE_47"; +BA_ "GenSigStartValue" SG_ 334 CAN_DET_RANGE_RATE_47 0; +BA_ "GenSigSendType" SG_ 334 CAN_DET_RANGE_RATE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_RANGE_RATE_47 "CAN_DET_RANGE_RATE_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_AMPLITUDE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_AMPLITUDE_47 "CAN_DET_AMPLITUDE_47"; +BA_ "GenSigSendType" SG_ 334 CAN_SCAN_INDEX_2LSB_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_SCAN_INDEX_2LSB_47 "CAN_SCAN_INDEX_2LSB_47"; +BA_ "GenMsgSendType" BO_ 333 1; +BA_ "GenMsgILSupport" BO_ 333 1; +BA_ "GenMsgNrOfRepetition" BO_ 333 0; +BA_ "GenMsgCycleTime" BO_ 333 0; +BA_ "NetworkInitialization" BO_ 333 0; +BA_ "GenMsgDelayTime" BO_ 333 0; +BA_ "GenSigVtEn" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigVtName" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_SUPER_RES_TARGET_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_SUPER_RES_TARGET_46 "CAN_DET_SUPER_RES_TARGET_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_ND_TARGET_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_ND_TARGET_46 "CAN_DET_ND_TARGET_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_HOST_VEH_CLUTTER_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_HOST_VEH_CLUTTER_46 "CAN_DET_HOST_VEH_CLUTTER_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_VALID_LEVEL_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_VALID_LEVEL_46 "CAN_DET_VALID_LEVEL_46"; +BA_ "GenSigStartValue" SG_ 333 CAN_DET_AZIMUTH_46 0; +BA_ "GenSigSendType" SG_ 333 CAN_DET_AZIMUTH_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_AZIMUTH_46 "CAN_DET_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_RANGE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_RANGE_46 "CAN_DET_RANGE_46"; +BA_ "GenSigStartValue" SG_ 333 CAN_DET_RANGE_RATE_46 0; +BA_ "GenSigSendType" SG_ 333 CAN_DET_RANGE_RATE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_RANGE_RATE_46 "CAN_DET_RANGE_RATE_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_AMPLITUDE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_AMPLITUDE_46 "CAN_DET_AMPLITUDE_46"; +BA_ "GenSigSendType" SG_ 333 CAN_SCAN_INDEX_2LSB_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_SCAN_INDEX_2LSB_46 "CAN_SCAN_INDEX_2LSB_46"; +BA_ "GenMsgSendType" BO_ 332 1; +BA_ "GenMsgILSupport" BO_ 332 1; +BA_ "GenMsgNrOfRepetition" BO_ 332 0; +BA_ "GenMsgCycleTime" BO_ 332 0; +BA_ "NetworkInitialization" BO_ 332 0; +BA_ "GenMsgDelayTime" BO_ 332 0; +BA_ "GenSigVtEn" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigVtName" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_SUPER_RES_TARGET_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_SUPER_RES_TARGET_45 "CAN_DET_SUPER_RES_TARGET_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_ND_TARGET_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_ND_TARGET_45 "CAN_DET_ND_TARGET_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_HOST_VEH_CLUTTER_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_HOST_VEH_CLUTTER_45 "CAN_DET_HOST_VEH_CLUTTER_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_VALID_LEVEL_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_VALID_LEVEL_45 "CAN_DET_VALID_LEVEL_45"; +BA_ "GenSigStartValue" SG_ 332 CAN_DET_AZIMUTH_45 0; +BA_ "GenSigSendType" SG_ 332 CAN_DET_AZIMUTH_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_AZIMUTH_45 "CAN_DET_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_RANGE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_RANGE_45 "CAN_DET_RANGE_45"; +BA_ "GenSigStartValue" SG_ 332 CAN_DET_RANGE_RATE_45 0; +BA_ "GenSigSendType" SG_ 332 CAN_DET_RANGE_RATE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_RANGE_RATE_45 "CAN_DET_RANGE_RATE_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_AMPLITUDE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_AMPLITUDE_45 "CAN_DET_AMPLITUDE_45"; +BA_ "GenSigSendType" SG_ 332 CAN_SCAN_INDEX_2LSB_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_SCAN_INDEX_2LSB_45 "CAN_SCAN_INDEX_2LSB_45"; +BA_ "GenMsgSendType" BO_ 331 1; +BA_ "GenMsgILSupport" BO_ 331 1; +BA_ "GenMsgNrOfRepetition" BO_ 331 0; +BA_ "GenMsgCycleTime" BO_ 331 0; +BA_ "NetworkInitialization" BO_ 331 0; +BA_ "GenMsgDelayTime" BO_ 331 0; +BA_ "GenSigVtEn" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigVtName" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_SUPER_RES_TARGET_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_SUPER_RES_TARGET_44 "CAN_DET_SUPER_RES_TARGET_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_ND_TARGET_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_ND_TARGET_44 "CAN_DET_ND_TARGET_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_HOST_VEH_CLUTTER_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_HOST_VEH_CLUTTER_44 "CAN_DET_HOST_VEH_CLUTTER_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_VALID_LEVEL_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_VALID_LEVEL_44 "CAN_DET_VALID_LEVEL_44"; +BA_ "GenSigStartValue" SG_ 331 CAN_DET_AZIMUTH_44 0; +BA_ "GenSigSendType" SG_ 331 CAN_DET_AZIMUTH_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_AZIMUTH_44 "CAN_DET_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_RANGE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_RANGE_44 "CAN_DET_RANGE_44"; +BA_ "GenSigStartValue" SG_ 331 CAN_DET_RANGE_RATE_44 0; +BA_ "GenSigSendType" SG_ 331 CAN_DET_RANGE_RATE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_RANGE_RATE_44 "CAN_DET_RANGE_RATE_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_AMPLITUDE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_AMPLITUDE_44 "CAN_DET_AMPLITUDE_44"; +BA_ "GenSigSendType" SG_ 331 CAN_SCAN_INDEX_2LSB_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_SCAN_INDEX_2LSB_44 "CAN_SCAN_INDEX_2LSB_44"; +BA_ "GenMsgSendType" BO_ 330 1; +BA_ "GenMsgILSupport" BO_ 330 1; +BA_ "GenMsgNrOfRepetition" BO_ 330 0; +BA_ "GenMsgCycleTime" BO_ 330 0; +BA_ "NetworkInitialization" BO_ 330 0; +BA_ "GenMsgDelayTime" BO_ 330 0; +BA_ "GenSigVtEn" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigVtName" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_SUPER_RES_TARGET_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_SUPER_RES_TARGET_43 "CAN_DET_SUPER_RES_TARGET_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_ND_TARGET_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_ND_TARGET_43 "CAN_DET_ND_TARGET_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_HOST_VEH_CLUTTER_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_HOST_VEH_CLUTTER_43 "CAN_DET_HOST_VEH_CLUTTER_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_VALID_LEVEL_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_VALID_LEVEL_43 "CAN_DET_VALID_LEVEL_43"; +BA_ "GenSigStartValue" SG_ 330 CAN_DET_AZIMUTH_43 0; +BA_ "GenSigSendType" SG_ 330 CAN_DET_AZIMUTH_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_AZIMUTH_43 "CAN_DET_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_RANGE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_RANGE_43 "CAN_DET_RANGE_43"; +BA_ "GenSigStartValue" SG_ 330 CAN_DET_RANGE_RATE_43 0; +BA_ "GenSigSendType" SG_ 330 CAN_DET_RANGE_RATE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_RANGE_RATE_43 "CAN_DET_RANGE_RATE_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_AMPLITUDE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_AMPLITUDE_43 "CAN_DET_AMPLITUDE_43"; +BA_ "GenSigSendType" SG_ 330 CAN_SCAN_INDEX_2LSB_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_SCAN_INDEX_2LSB_43 "CAN_SCAN_INDEX_2LSB_43"; +BA_ "GenMsgSendType" BO_ 329 1; +BA_ "GenMsgILSupport" BO_ 329 1; +BA_ "GenMsgNrOfRepetition" BO_ 329 0; +BA_ "GenMsgCycleTime" BO_ 329 0; +BA_ "NetworkInitialization" BO_ 329 0; +BA_ "GenMsgDelayTime" BO_ 329 0; +BA_ "GenSigVtEn" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigVtName" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_SUPER_RES_TARGET_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_SUPER_RES_TARGET_42 "CAN_DET_SUPER_RES_TARGET_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_ND_TARGET_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_ND_TARGET_42 "CAN_DET_ND_TARGET_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_HOST_VEH_CLUTTER_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_HOST_VEH_CLUTTER_42 "CAN_DET_HOST_VEH_CLUTTER_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_VALID_LEVEL_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_VALID_LEVEL_42 "CAN_DET_VALID_LEVEL_42"; +BA_ "GenSigStartValue" SG_ 329 CAN_DET_AZIMUTH_42 0; +BA_ "GenSigSendType" SG_ 329 CAN_DET_AZIMUTH_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_AZIMUTH_42 "CAN_DET_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_RANGE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_RANGE_42 "CAN_DET_RANGE_42"; +BA_ "GenSigStartValue" SG_ 329 CAN_DET_RANGE_RATE_42 0; +BA_ "GenSigSendType" SG_ 329 CAN_DET_RANGE_RATE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_RANGE_RATE_42 "CAN_DET_RANGE_RATE_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_AMPLITUDE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_AMPLITUDE_42 "CAN_DET_AMPLITUDE_42"; +BA_ "GenSigSendType" SG_ 329 CAN_SCAN_INDEX_2LSB_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_SCAN_INDEX_2LSB_42 "CAN_SCAN_INDEX_2LSB_42"; +BA_ "GenMsgSendType" BO_ 328 1; +BA_ "GenMsgILSupport" BO_ 328 1; +BA_ "GenMsgNrOfRepetition" BO_ 328 0; +BA_ "GenMsgCycleTime" BO_ 328 0; +BA_ "NetworkInitialization" BO_ 328 0; +BA_ "GenMsgDelayTime" BO_ 328 0; +BA_ "GenSigVtEn" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigVtName" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_SUPER_RES_TARGET_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_SUPER_RES_TARGET_41 "CAN_DET_SUPER_RES_TARGET_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_ND_TARGET_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_ND_TARGET_41 "CAN_DET_ND_TARGET_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_HOST_VEH_CLUTTER_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_HOST_VEH_CLUTTER_41 "CAN_DET_HOST_VEH_CLUTTER_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_VALID_LEVEL_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_VALID_LEVEL_41 "CAN_DET_VALID_LEVEL_41"; +BA_ "GenSigStartValue" SG_ 328 CAN_DET_AZIMUTH_41 0; +BA_ "GenSigSendType" SG_ 328 CAN_DET_AZIMUTH_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_AZIMUTH_41 "CAN_DET_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_RANGE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_RANGE_41 "CAN_DET_RANGE_41"; +BA_ "GenSigStartValue" SG_ 328 CAN_DET_RANGE_RATE_41 0; +BA_ "GenSigSendType" SG_ 328 CAN_DET_RANGE_RATE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_RANGE_RATE_41 "CAN_DET_RANGE_RATE_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_AMPLITUDE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_AMPLITUDE_41 "CAN_DET_AMPLITUDE_41"; +BA_ "GenSigSendType" SG_ 328 CAN_SCAN_INDEX_2LSB_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_SCAN_INDEX_2LSB_41 "CAN_SCAN_INDEX_2LSB_41"; +BA_ "GenMsgSendType" BO_ 327 1; +BA_ "GenMsgILSupport" BO_ 327 1; +BA_ "GenMsgNrOfRepetition" BO_ 327 0; +BA_ "GenMsgCycleTime" BO_ 327 0; +BA_ "NetworkInitialization" BO_ 327 0; +BA_ "GenMsgDelayTime" BO_ 327 0; +BA_ "GenSigVtEn" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigVtName" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_SUPER_RES_TARGET_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_SUPER_RES_TARGET_40 "CAN_DET_SUPER_RES_TARGET_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_ND_TARGET_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_ND_TARGET_40 "CAN_DET_ND_TARGET_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_HOST_VEH_CLUTTER_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_HOST_VEH_CLUTTER_40 "CAN_DET_HOST_VEH_CLUTTER_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_VALID_LEVEL_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_VALID_LEVEL_40 "CAN_DET_VALID_LEVEL_40"; +BA_ "GenSigStartValue" SG_ 327 CAN_DET_AZIMUTH_40 0; +BA_ "GenSigSendType" SG_ 327 CAN_DET_AZIMUTH_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_AZIMUTH_40 "CAN_DET_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_RANGE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_RANGE_40 "CAN_DET_RANGE_40"; +BA_ "GenSigStartValue" SG_ 327 CAN_DET_RANGE_RATE_40 0; +BA_ "GenSigSendType" SG_ 327 CAN_DET_RANGE_RATE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_RANGE_RATE_40 "CAN_DET_RANGE_RATE_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_AMPLITUDE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_AMPLITUDE_40 "CAN_DET_AMPLITUDE_40"; +BA_ "GenSigSendType" SG_ 327 CAN_SCAN_INDEX_2LSB_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_SCAN_INDEX_2LSB_40 "CAN_SCAN_INDEX_2LSB_40"; +BA_ "GenMsgSendType" BO_ 325 1; +BA_ "GenMsgILSupport" BO_ 325 1; +BA_ "GenMsgNrOfRepetition" BO_ 325 0; +BA_ "GenMsgCycleTime" BO_ 325 0; +BA_ "NetworkInitialization" BO_ 325 0; +BA_ "GenMsgDelayTime" BO_ 325 0; +BA_ "GenSigVtEn" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigVtName" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_SUPER_RES_TARGET_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_SUPER_RES_TARGET_38 "CAN_DET_SUPER_RES_TARGET_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_ND_TARGET_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_ND_TARGET_38 "CAN_DET_ND_TARGET_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_HOST_VEH_CLUTTER_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_HOST_VEH_CLUTTER_38 "CAN_DET_HOST_VEH_CLUTTER_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_VALID_LEVEL_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_VALID_LEVEL_38 "CAN_DET_VALID_LEVEL_38"; +BA_ "GenSigStartValue" SG_ 325 CAN_DET_AZIMUTH_38 0; +BA_ "GenSigSendType" SG_ 325 CAN_DET_AZIMUTH_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_AZIMUTH_38 "CAN_DET_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_RANGE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_RANGE_38 "CAN_DET_RANGE_38"; +BA_ "GenSigStartValue" SG_ 325 CAN_DET_RANGE_RATE_38 0; +BA_ "GenSigSendType" SG_ 325 CAN_DET_RANGE_RATE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_RANGE_RATE_38 "CAN_DET_RANGE_RATE_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_AMPLITUDE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_AMPLITUDE_38 "CAN_DET_AMPLITUDE_38"; +BA_ "GenSigSendType" SG_ 325 CAN_SCAN_INDEX_2LSB_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_SCAN_INDEX_2LSB_38 "CAN_SCAN_INDEX_2LSB_38"; +BA_ "GenMsgSendType" BO_ 324 1; +BA_ "GenMsgILSupport" BO_ 324 1; +BA_ "GenMsgNrOfRepetition" BO_ 324 0; +BA_ "GenMsgCycleTime" BO_ 324 0; +BA_ "NetworkInitialization" BO_ 324 0; +BA_ "GenMsgDelayTime" BO_ 324 0; +BA_ "GenSigVtEn" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigVtName" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_SUPER_RES_TARGET_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_SUPER_RES_TARGET_37 "CAN_DET_SUPER_RES_TARGET_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_ND_TARGET_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_ND_TARGET_37 "CAN_DET_ND_TARGET_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_HOST_VEH_CLUTTER_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_HOST_VEH_CLUTTER_37 "CAN_DET_HOST_VEH_CLUTTER_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_VALID_LEVEL_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_VALID_LEVEL_37 "CAN_DET_VALID_LEVEL_37"; +BA_ "GenSigStartValue" SG_ 324 CAN_DET_AZIMUTH_37 0; +BA_ "GenSigSendType" SG_ 324 CAN_DET_AZIMUTH_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_AZIMUTH_37 "CAN_DET_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_RANGE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_RANGE_37 "CAN_DET_RANGE_37"; +BA_ "GenSigStartValue" SG_ 324 CAN_DET_RANGE_RATE_37 0; +BA_ "GenSigSendType" SG_ 324 CAN_DET_RANGE_RATE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_RANGE_RATE_37 "CAN_DET_RANGE_RATE_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_AMPLITUDE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_AMPLITUDE_37 "CAN_DET_AMPLITUDE_37"; +BA_ "GenSigSendType" SG_ 324 CAN_SCAN_INDEX_2LSB_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_SCAN_INDEX_2LSB_37 "CAN_SCAN_INDEX_2LSB_37"; +BA_ "GenMsgSendType" BO_ 323 1; +BA_ "GenMsgILSupport" BO_ 323 1; +BA_ "GenMsgNrOfRepetition" BO_ 323 0; +BA_ "GenMsgCycleTime" BO_ 323 0; +BA_ "NetworkInitialization" BO_ 323 0; +BA_ "GenMsgDelayTime" BO_ 323 0; +BA_ "GenSigVtEn" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigVtName" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_SUPER_RES_TARGET_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_SUPER_RES_TARGET_36 "CAN_DET_SUPER_RES_TARGET_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_ND_TARGET_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_ND_TARGET_36 "CAN_DET_ND_TARGET_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_HOST_VEH_CLUTTER_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_HOST_VEH_CLUTTER_36 "CAN_DET_HOST_VEH_CLUTTER_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_VALID_LEVEL_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_VALID_LEVEL_36 "CAN_DET_VALID_LEVEL_36"; +BA_ "GenSigStartValue" SG_ 323 CAN_DET_AZIMUTH_36 0; +BA_ "GenSigSendType" SG_ 323 CAN_DET_AZIMUTH_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_AZIMUTH_36 "CAN_DET_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_RANGE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_RANGE_36 "CAN_DET_RANGE_36"; +BA_ "GenSigStartValue" SG_ 323 CAN_DET_RANGE_RATE_36 0; +BA_ "GenSigSendType" SG_ 323 CAN_DET_RANGE_RATE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_RANGE_RATE_36 "CAN_DET_RANGE_RATE_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_AMPLITUDE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_AMPLITUDE_36 "CAN_DET_AMPLITUDE_36"; +BA_ "GenSigSendType" SG_ 323 CAN_SCAN_INDEX_2LSB_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_SCAN_INDEX_2LSB_36 "CAN_SCAN_INDEX_2LSB_36"; +BA_ "GenMsgSendType" BO_ 322 1; +BA_ "GenMsgILSupport" BO_ 322 1; +BA_ "GenMsgNrOfRepetition" BO_ 322 0; +BA_ "GenMsgCycleTime" BO_ 322 0; +BA_ "NetworkInitialization" BO_ 322 0; +BA_ "GenMsgDelayTime" BO_ 322 0; +BA_ "GenSigVtEn" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigVtName" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_SUPER_RES_TARGET_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_SUPER_RES_TARGET_35 "CAN_DET_SUPER_RES_TARGET_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_ND_TARGET_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_ND_TARGET_35 "CAN_DET_ND_TARGET_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_HOST_VEH_CLUTTER_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_HOST_VEH_CLUTTER_35 "CAN_DET_HOST_VEH_CLUTTER_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_VALID_LEVEL_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_VALID_LEVEL_35 "CAN_DET_VALID_LEVEL_35"; +BA_ "GenSigStartValue" SG_ 322 CAN_DET_AZIMUTH_35 0; +BA_ "GenSigSendType" SG_ 322 CAN_DET_AZIMUTH_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_AZIMUTH_35 "CAN_DET_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_RANGE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_RANGE_35 "CAN_DET_RANGE_35"; +BA_ "GenSigStartValue" SG_ 322 CAN_DET_RANGE_RATE_35 0; +BA_ "GenSigSendType" SG_ 322 CAN_DET_RANGE_RATE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_RANGE_RATE_35 "CAN_DET_RANGE_RATE_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_AMPLITUDE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_AMPLITUDE_35 "CAN_DET_AMPLITUDE_35"; +BA_ "GenSigSendType" SG_ 322 CAN_SCAN_INDEX_2LSB_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_SCAN_INDEX_2LSB_35 "CAN_SCAN_INDEX_2LSB_35"; +BA_ "GenMsgSendType" BO_ 321 1; +BA_ "GenMsgILSupport" BO_ 321 1; +BA_ "GenMsgNrOfRepetition" BO_ 321 0; +BA_ "GenMsgCycleTime" BO_ 321 0; +BA_ "NetworkInitialization" BO_ 321 0; +BA_ "GenMsgDelayTime" BO_ 321 0; +BA_ "GenSigVtEn" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigVtName" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_SUPER_RES_TARGET_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_SUPER_RES_TARGET_34 "CAN_DET_SUPER_RES_TARGET_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_ND_TARGET_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_ND_TARGET_34 "CAN_DET_ND_TARGET_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_HOST_VEH_CLUTTER_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_HOST_VEH_CLUTTER_34 "CAN_DET_HOST_VEH_CLUTTER_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_VALID_LEVEL_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_VALID_LEVEL_34 "CAN_DET_VALID_LEVEL_34"; +BA_ "GenSigStartValue" SG_ 321 CAN_DET_AZIMUTH_34 0; +BA_ "GenSigSendType" SG_ 321 CAN_DET_AZIMUTH_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_AZIMUTH_34 "CAN_DET_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_RANGE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_RANGE_34 "CAN_DET_RANGE_34"; +BA_ "GenSigStartValue" SG_ 321 CAN_DET_RANGE_RATE_34 0; +BA_ "GenSigSendType" SG_ 321 CAN_DET_RANGE_RATE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_RANGE_RATE_34 "CAN_DET_RANGE_RATE_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_AMPLITUDE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_AMPLITUDE_34 "CAN_DET_AMPLITUDE_34"; +BA_ "GenSigSendType" SG_ 321 CAN_SCAN_INDEX_2LSB_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_SCAN_INDEX_2LSB_34 "CAN_SCAN_INDEX_2LSB_34"; +BA_ "GenMsgSendType" BO_ 320 1; +BA_ "GenMsgILSupport" BO_ 320 1; +BA_ "GenMsgNrOfRepetition" BO_ 320 0; +BA_ "GenMsgCycleTime" BO_ 320 0; +BA_ "NetworkInitialization" BO_ 320 0; +BA_ "GenMsgDelayTime" BO_ 320 0; +BA_ "GenSigVtEn" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigVtName" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_SUPER_RES_TARGET_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_SUPER_RES_TARGET_33 "CAN_DET_SUPER_RES_TARGET_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_ND_TARGET_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_ND_TARGET_33 "CAN_DET_ND_TARGET_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_HOST_VEH_CLUTTER_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_HOST_VEH_CLUTTER_33 "CAN_DET_HOST_VEH_CLUTTER_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_VALID_LEVEL_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_VALID_LEVEL_33 "CAN_DET_VALID_LEVEL_33"; +BA_ "GenSigStartValue" SG_ 320 CAN_DET_AZIMUTH_33 0; +BA_ "GenSigSendType" SG_ 320 CAN_DET_AZIMUTH_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_AZIMUTH_33 "CAN_DET_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_RANGE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_RANGE_33 "CAN_DET_RANGE_33"; +BA_ "GenSigStartValue" SG_ 320 CAN_DET_RANGE_RATE_33 0; +BA_ "GenSigSendType" SG_ 320 CAN_DET_RANGE_RATE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_RANGE_RATE_33 "CAN_DET_RANGE_RATE_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_AMPLITUDE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_AMPLITUDE_33 "CAN_DET_AMPLITUDE_33"; +BA_ "GenSigSendType" SG_ 320 CAN_SCAN_INDEX_2LSB_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_SCAN_INDEX_2LSB_33 "CAN_SCAN_INDEX_2LSB_33"; +BA_ "GenMsgSendType" BO_ 319 1; +BA_ "GenMsgILSupport" BO_ 319 1; +BA_ "GenMsgNrOfRepetition" BO_ 319 0; +BA_ "GenMsgCycleTime" BO_ 319 0; +BA_ "NetworkInitialization" BO_ 319 0; +BA_ "GenMsgDelayTime" BO_ 319 0; +BA_ "GenSigVtEn" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigVtName" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_SUPER_RES_TARGET_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_SUPER_RES_TARGET_32 "CAN_DET_SUPER_RES_TARGET_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_ND_TARGET_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_ND_TARGET_32 "CAN_DET_ND_TARGET_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_HOST_VEH_CLUTTER_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_HOST_VEH_CLUTTER_32 "CAN_DET_HOST_VEH_CLUTTER_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_VALID_LEVEL_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_VALID_LEVEL_32 "CAN_DET_VALID_LEVEL_32"; +BA_ "GenSigStartValue" SG_ 319 CAN_DET_AZIMUTH_32 0; +BA_ "GenSigSendType" SG_ 319 CAN_DET_AZIMUTH_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_AZIMUTH_32 "CAN_DET_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_RANGE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_RANGE_32 "CAN_DET_RANGE_32"; +BA_ "GenSigStartValue" SG_ 319 CAN_DET_RANGE_RATE_32 0; +BA_ "GenSigSendType" SG_ 319 CAN_DET_RANGE_RATE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_RANGE_RATE_32 "CAN_DET_RANGE_RATE_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_AMPLITUDE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_AMPLITUDE_32 "CAN_DET_AMPLITUDE_32"; +BA_ "GenSigSendType" SG_ 319 CAN_SCAN_INDEX_2LSB_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_SCAN_INDEX_2LSB_32 "CAN_SCAN_INDEX_2LSB_32"; +BA_ "GenMsgSendType" BO_ 318 1; +BA_ "GenMsgILSupport" BO_ 318 1; +BA_ "GenMsgNrOfRepetition" BO_ 318 0; +BA_ "GenMsgCycleTime" BO_ 318 0; +BA_ "NetworkInitialization" BO_ 318 0; +BA_ "GenMsgDelayTime" BO_ 318 0; +BA_ "GenSigVtEn" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigVtName" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_SUPER_RES_TARGET_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_SUPER_RES_TARGET_31 "CAN_DET_SUPER_RES_TARGET_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_ND_TARGET_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_ND_TARGET_31 "CAN_DET_ND_TARGET_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_HOST_VEH_CLUTTER_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_HOST_VEH_CLUTTER_31 "CAN_DET_HOST_VEH_CLUTTER_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_VALID_LEVEL_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_VALID_LEVEL_31 "CAN_DET_VALID_LEVEL_31"; +BA_ "GenSigStartValue" SG_ 318 CAN_DET_AZIMUTH_31 0; +BA_ "GenSigSendType" SG_ 318 CAN_DET_AZIMUTH_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_AZIMUTH_31 "CAN_DET_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_RANGE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_RANGE_31 "CAN_DET_RANGE_31"; +BA_ "GenSigStartValue" SG_ 318 CAN_DET_RANGE_RATE_31 0; +BA_ "GenSigSendType" SG_ 318 CAN_DET_RANGE_RATE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_RANGE_RATE_31 "CAN_DET_RANGE_RATE_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_AMPLITUDE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_AMPLITUDE_31 "CAN_DET_AMPLITUDE_31"; +BA_ "GenSigSendType" SG_ 318 CAN_SCAN_INDEX_2LSB_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_SCAN_INDEX_2LSB_31 "CAN_SCAN_INDEX_2LSB_31"; +BA_ "GenMsgSendType" BO_ 317 1; +BA_ "GenMsgILSupport" BO_ 317 1; +BA_ "GenMsgNrOfRepetition" BO_ 317 0; +BA_ "GenMsgCycleTime" BO_ 317 0; +BA_ "NetworkInitialization" BO_ 317 0; +BA_ "GenMsgDelayTime" BO_ 317 0; +BA_ "GenSigVtEn" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigVtName" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_SUPER_RES_TARGET_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_SUPER_RES_TARGET_30 "CAN_DET_SUPER_RES_TARGET_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_ND_TARGET_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_ND_TARGET_30 "CAN_DET_ND_TARGET_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_HOST_VEH_CLUTTER_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_HOST_VEH_CLUTTER_30 "CAN_DET_HOST_VEH_CLUTTER_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_VALID_LEVEL_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_VALID_LEVEL_30 "CAN_DET_VALID_LEVEL_30"; +BA_ "GenSigStartValue" SG_ 317 CAN_DET_AZIMUTH_30 0; +BA_ "GenSigSendType" SG_ 317 CAN_DET_AZIMUTH_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_AZIMUTH_30 "CAN_DET_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_RANGE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_RANGE_30 "CAN_DET_RANGE_30"; +BA_ "GenSigStartValue" SG_ 317 CAN_DET_RANGE_RATE_30 0; +BA_ "GenSigSendType" SG_ 317 CAN_DET_RANGE_RATE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_RANGE_RATE_30 "CAN_DET_RANGE_RATE_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_AMPLITUDE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_AMPLITUDE_30 "CAN_DET_AMPLITUDE_30"; +BA_ "GenSigSendType" SG_ 317 CAN_SCAN_INDEX_2LSB_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_SCAN_INDEX_2LSB_30 "CAN_SCAN_INDEX_2LSB_30"; +BA_ "GenMsgSendType" BO_ 316 1; +BA_ "GenMsgILSupport" BO_ 316 1; +BA_ "GenMsgNrOfRepetition" BO_ 316 0; +BA_ "GenMsgCycleTime" BO_ 316 0; +BA_ "NetworkInitialization" BO_ 316 0; +BA_ "GenMsgDelayTime" BO_ 316 0; +BA_ "GenSigVtEn" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigVtName" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_SUPER_RES_TARGET_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_SUPER_RES_TARGET_29 "CAN_DET_SUPER_RES_TARGET_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_ND_TARGET_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_ND_TARGET_29 "CAN_DET_ND_TARGET_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_HOST_VEH_CLUTTER_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_HOST_VEH_CLUTTER_29 "CAN_DET_HOST_VEH_CLUTTER_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_VALID_LEVEL_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_VALID_LEVEL_29 "CAN_DET_VALID_LEVEL_29"; +BA_ "GenSigStartValue" SG_ 316 CAN_DET_AZIMUTH_29 0; +BA_ "GenSigSendType" SG_ 316 CAN_DET_AZIMUTH_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_AZIMUTH_29 "CAN_DET_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_RANGE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_RANGE_29 "CAN_DET_RANGE_29"; +BA_ "GenSigStartValue" SG_ 316 CAN_DET_RANGE_RATE_29 0; +BA_ "GenSigSendType" SG_ 316 CAN_DET_RANGE_RATE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_RANGE_RATE_29 "CAN_DET_RANGE_RATE_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_AMPLITUDE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_AMPLITUDE_29 "CAN_DET_AMPLITUDE_29"; +BA_ "GenSigSendType" SG_ 316 CAN_SCAN_INDEX_2LSB_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_SCAN_INDEX_2LSB_29 "CAN_SCAN_INDEX_2LSB_29"; +BA_ "GenMsgSendType" BO_ 314 1; +BA_ "GenMsgILSupport" BO_ 314 1; +BA_ "GenMsgNrOfRepetition" BO_ 314 0; +BA_ "GenMsgCycleTime" BO_ 314 0; +BA_ "NetworkInitialization" BO_ 314 0; +BA_ "GenMsgDelayTime" BO_ 314 0; +BA_ "GenSigVtEn" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigVtName" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_SUPER_RES_TARGET_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_SUPER_RES_TARGET_27 "CAN_DET_SUPER_RES_TARGET_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_ND_TARGET_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_ND_TARGET_27 "CAN_DET_ND_TARGET_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_HOST_VEH_CLUTTER_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_HOST_VEH_CLUTTER_27 "CAN_DET_HOST_VEH_CLUTTER_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_VALID_LEVEL_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_VALID_LEVEL_27 "CAN_DET_VALID_LEVEL_27"; +BA_ "GenSigStartValue" SG_ 314 CAN_DET_AZIMUTH_27 0; +BA_ "GenSigSendType" SG_ 314 CAN_DET_AZIMUTH_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_AZIMUTH_27 "CAN_DET_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_RANGE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_RANGE_27 "CAN_DET_RANGE_27"; +BA_ "GenSigStartValue" SG_ 314 CAN_DET_RANGE_RATE_27 0; +BA_ "GenSigSendType" SG_ 314 CAN_DET_RANGE_RATE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_RANGE_RATE_27 "CAN_DET_RANGE_RATE_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_AMPLITUDE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_AMPLITUDE_27 "CAN_DET_AMPLITUDE_27"; +BA_ "GenSigSendType" SG_ 314 CAN_SCAN_INDEX_2LSB_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_SCAN_INDEX_2LSB_27 "CAN_SCAN_INDEX_2LSB_27"; +BA_ "GenMsgSendType" BO_ 313 1; +BA_ "GenMsgILSupport" BO_ 313 1; +BA_ "GenMsgNrOfRepetition" BO_ 313 0; +BA_ "GenMsgCycleTime" BO_ 313 0; +BA_ "NetworkInitialization" BO_ 313 0; +BA_ "GenMsgDelayTime" BO_ 313 0; +BA_ "GenSigVtEn" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigVtName" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_SUPER_RES_TARGET_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_SUPER_RES_TARGET_26 "CAN_DET_SUPER_RES_TARGET_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_ND_TARGET_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_ND_TARGET_26 "CAN_DET_ND_TARGET_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_HOST_VEH_CLUTTER_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_HOST_VEH_CLUTTER_26 "CAN_DET_HOST_VEH_CLUTTER_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_VALID_LEVEL_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_VALID_LEVEL_26 "CAN_DET_VALID_LEVEL_26"; +BA_ "GenSigStartValue" SG_ 313 CAN_DET_AZIMUTH_26 0; +BA_ "GenSigSendType" SG_ 313 CAN_DET_AZIMUTH_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_AZIMUTH_26 "CAN_DET_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_RANGE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_RANGE_26 "CAN_DET_RANGE_26"; +BA_ "GenSigStartValue" SG_ 313 CAN_DET_RANGE_RATE_26 0; +BA_ "GenSigSendType" SG_ 313 CAN_DET_RANGE_RATE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_RANGE_RATE_26 "CAN_DET_RANGE_RATE_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_AMPLITUDE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_AMPLITUDE_26 "CAN_DET_AMPLITUDE_26"; +BA_ "GenSigSendType" SG_ 313 CAN_SCAN_INDEX_2LSB_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_SCAN_INDEX_2LSB_26 "CAN_SCAN_INDEX_2LSB_26"; +BA_ "GenMsgSendType" BO_ 312 1; +BA_ "GenMsgILSupport" BO_ 312 1; +BA_ "GenMsgNrOfRepetition" BO_ 312 0; +BA_ "GenMsgCycleTime" BO_ 312 0; +BA_ "NetworkInitialization" BO_ 312 0; +BA_ "GenMsgDelayTime" BO_ 312 0; +BA_ "GenSigVtEn" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigVtName" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_SUPER_RES_TARGET_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_SUPER_RES_TARGET_25 "CAN_DET_SUPER_RES_TARGET_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_ND_TARGET_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_ND_TARGET_25 "CAN_DET_ND_TARGET_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_HOST_VEH_CLUTTER_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_HOST_VEH_CLUTTER_25 "CAN_DET_HOST_VEH_CLUTTER_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_VALID_LEVEL_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_VALID_LEVEL_25 "CAN_DET_VALID_LEVEL_25"; +BA_ "GenSigStartValue" SG_ 312 CAN_DET_AZIMUTH_25 0; +BA_ "GenSigSendType" SG_ 312 CAN_DET_AZIMUTH_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_AZIMUTH_25 "CAN_DET_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_RANGE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_RANGE_25 "CAN_DET_RANGE_25"; +BA_ "GenSigStartValue" SG_ 312 CAN_DET_RANGE_RATE_25 0; +BA_ "GenSigSendType" SG_ 312 CAN_DET_RANGE_RATE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_RANGE_RATE_25 "CAN_DET_RANGE_RATE_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_AMPLITUDE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_AMPLITUDE_25 "CAN_DET_AMPLITUDE_25"; +BA_ "GenSigSendType" SG_ 312 CAN_SCAN_INDEX_2LSB_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_SCAN_INDEX_2LSB_25 "CAN_SCAN_INDEX_2LSB_25"; +BA_ "GenMsgSendType" BO_ 311 1; +BA_ "GenMsgILSupport" BO_ 311 1; +BA_ "GenMsgNrOfRepetition" BO_ 311 0; +BA_ "GenMsgCycleTime" BO_ 311 0; +BA_ "NetworkInitialization" BO_ 311 0; +BA_ "GenMsgDelayTime" BO_ 311 0; +BA_ "GenSigVtEn" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigVtName" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_SUPER_RES_TARGET_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_SUPER_RES_TARGET_24 "CAN_DET_SUPER_RES_TARGET_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_ND_TARGET_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_ND_TARGET_24 "CAN_DET_ND_TARGET_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_HOST_VEH_CLUTTER_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_HOST_VEH_CLUTTER_24 "CAN_DET_HOST_VEH_CLUTTER_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_VALID_LEVEL_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_VALID_LEVEL_24 "CAN_DET_VALID_LEVEL_24"; +BA_ "GenSigStartValue" SG_ 311 CAN_DET_AZIMUTH_24 0; +BA_ "GenSigSendType" SG_ 311 CAN_DET_AZIMUTH_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_AZIMUTH_24 "CAN_DET_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_RANGE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_RANGE_24 "CAN_DET_RANGE_24"; +BA_ "GenSigStartValue" SG_ 311 CAN_DET_RANGE_RATE_24 0; +BA_ "GenSigSendType" SG_ 311 CAN_DET_RANGE_RATE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_RANGE_RATE_24 "CAN_DET_RANGE_RATE_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_AMPLITUDE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_AMPLITUDE_24 "CAN_DET_AMPLITUDE_24"; +BA_ "GenSigSendType" SG_ 311 CAN_SCAN_INDEX_2LSB_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_SCAN_INDEX_2LSB_24 "CAN_SCAN_INDEX_2LSB_24"; +BA_ "GenMsgSendType" BO_ 310 1; +BA_ "GenMsgILSupport" BO_ 310 1; +BA_ "GenMsgNrOfRepetition" BO_ 310 0; +BA_ "GenMsgCycleTime" BO_ 310 0; +BA_ "NetworkInitialization" BO_ 310 0; +BA_ "GenMsgDelayTime" BO_ 310 0; +BA_ "GenSigVtEn" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigVtName" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_SUPER_RES_TARGET_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_SUPER_RES_TARGET_23 "CAN_DET_SUPER_RES_TARGET_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_ND_TARGET_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_ND_TARGET_23 "CAN_DET_ND_TARGET_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_HOST_VEH_CLUTTER_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_HOST_VEH_CLUTTER_23 "CAN_DET_HOST_VEH_CLUTTER_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_VALID_LEVEL_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_VALID_LEVEL_23 "CAN_DET_VALID_LEVEL_23"; +BA_ "GenSigStartValue" SG_ 310 CAN_DET_AZIMUTH_23 0; +BA_ "GenSigSendType" SG_ 310 CAN_DET_AZIMUTH_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_AZIMUTH_23 "CAN_DET_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_RANGE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_RANGE_23 "CAN_DET_RANGE_23"; +BA_ "GenSigStartValue" SG_ 310 CAN_DET_RANGE_RATE_23 0; +BA_ "GenSigSendType" SG_ 310 CAN_DET_RANGE_RATE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_RANGE_RATE_23 "CAN_DET_RANGE_RATE_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_AMPLITUDE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_AMPLITUDE_23 "CAN_DET_AMPLITUDE_23"; +BA_ "GenSigSendType" SG_ 310 CAN_SCAN_INDEX_2LSB_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_SCAN_INDEX_2LSB_23 "CAN_SCAN_INDEX_2LSB_23"; +BA_ "GenMsgSendType" BO_ 309 1; +BA_ "GenMsgILSupport" BO_ 309 1; +BA_ "GenMsgNrOfRepetition" BO_ 309 0; +BA_ "GenMsgCycleTime" BO_ 309 0; +BA_ "NetworkInitialization" BO_ 309 0; +BA_ "GenMsgDelayTime" BO_ 309 0; +BA_ "GenSigVtEn" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_01 "CAN_DET_CONFID_AZIMUTH_22_01"; +BA_ "GenSigVtName" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_01 "CAN_DET_CONFID_AZIMUTH_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_01 "CAN_DET_CONFID_AZIMUTH_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_SUPER_RES_TARGET_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_SUPER_RES_TARGET_22_01 "CAN_DET_SUPER_RES_TARGET_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_ND_TARGET_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_ND_TARGET_22_01 "CAN_DET_ND_TARGET_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22_01 "CAN_DET_HOST_VEH_CLUTTER_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_VALID_LEVEL_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_VALID_LEVEL_22_01 "CAN_DET_VALID_LEVEL_22_01"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_AZIMUTH_22_01 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AZIMUTH_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AZIMUTH_22_01 "CAN_DET_AZIMUTH_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_22_01 "CAN_DET_RANGE_22_01"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_RANGE_RATE_22_01 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_RATE_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_RATE_22_01 "CAN_DET_RANGE_RATE_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AMPLITUDE_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AMPLITUDE_22_01 "CAN_DET_AMPLITUDE_22_01"; +BA_ "GenSigSendType" SG_ 309 CAN_SCAN_INDEX_2LSB_22_01 0; +BA_ "GenSigCmt" SG_ 309 CAN_SCAN_INDEX_2LSB_22_01 "CAN_SCAN_INDEX_2LSB_22_01"; +BA_ "GenSigVtEn" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_02 "CAN_DET_CONFID_AZIMUTH_22_02"; +BA_ "GenSigVtName" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_02 "CAN_DET_CONFID_AZIMUTH_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_02 "CAN_DET_CONFID_AZIMUTH_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_SUPER_RES_TARGET_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_SUPER_RES_TARGET_22_02 "CAN_DET_SUPER_RES_TARGET_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_ND_TARGET_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_ND_TARGET_22_02 "CAN_DET_ND_TARGET_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22_02 "CAN_DET_HOST_VEH_CLUTTER_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_VALID_LEVEL_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_VALID_LEVEL_22_02 "CAN_DET_VALID_LEVEL_22_02"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_AZIMUTH_22_02 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AZIMUTH_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AZIMUTH_22_02 "CAN_DET_AZIMUTH_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_22_02 "CAN_DET_RANGE_22_02"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_RANGE_RATE_22_02 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_RATE_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_RATE_22_02 "CAN_DET_RANGE_RATE_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AMPLITUDE_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AMPLITUDE_22_02 "CAN_DET_AMPLITUDE_22_02"; +BA_ "GenSigSendType" SG_ 309 CAN_SCAN_INDEX_2LSB_22_02 0; +BA_ "GenSigCmt" SG_ 309 CAN_SCAN_INDEX_2LSB_22_02 "CAN_SCAN_INDEX_2LSB_22_02"; +BA_ "GenSigVtEn" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_03 "CAN_DET_CONFID_AZIMUTH_22_03"; +BA_ "GenSigVtName" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_03 "CAN_DET_CONFID_AZIMUTH_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_CONFID_AZIMUTH_22_03 "CAN_DET_CONFID_AZIMUTH_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_SUPER_RES_TARGET_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_SUPER_RES_TARGET_22_03 "CAN_DET_SUPER_RES_TARGET_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_ND_TARGET_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_ND_TARGET_22_03 "CAN_DET_ND_TARGET_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_HOST_VEH_CLUTTER_22_03 "CAN_DET_HOST_VEH_CLUTTER_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_VALID_LEVEL_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_VALID_LEVEL_22_03 "CAN_DET_VALID_LEVEL_22_03"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_AZIMUTH_22_03 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AZIMUTH_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AZIMUTH_22_03 "CAN_DET_AZIMUTH_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_22_03 "CAN_DET_RANGE_22_03"; +BA_ "GenSigStartValue" SG_ 309 CAN_DET_RANGE_RATE_22_03 0; +BA_ "GenSigSendType" SG_ 309 CAN_DET_RANGE_RATE_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_RANGE_RATE_22_03 "CAN_DET_RANGE_RATE_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_DET_AMPLITUDE_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_DET_AMPLITUDE_22_03 "CAN_DET_AMPLITUDE_22_03"; +BA_ "GenSigSendType" SG_ 309 CAN_SCAN_INDEX_2LSB_22_03 0; +BA_ "GenSigCmt" SG_ 309 CAN_SCAN_INDEX_2LSB_22_03 "CAN_SCAN_INDEX_2LSB_22_03"; +BA_ "GenMsgSendType" BO_ 308 1; +BA_ "GenMsgILSupport" BO_ 308 1; +BA_ "GenMsgNrOfRepetition" BO_ 308 0; +BA_ "GenMsgCycleTime" BO_ 308 0; +BA_ "NetworkInitialization" BO_ 308 0; +BA_ "GenMsgDelayTime" BO_ 308 0; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_01 "CAN_DET_CONFID_AZIMUTH_21_01"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_01 "CAN_DET_CONFID_AZIMUTH_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_01 "CAN_DET_CONFID_AZIMUTH_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_01 "CAN_DET_SUPER_RES_TARGET_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21_01 "CAN_DET_ND_TARGET_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_01 "CAN_DET_HOST_VEH_CLUTTER_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21_01 "CAN_DET_VALID_LEVEL_21_01"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21_01 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21_01 "CAN_DET_AZIMUTH_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21_01 "CAN_DET_RANGE_21_01"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21_01 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21_01 "CAN_DET_RANGE_RATE_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21_01 "CAN_DET_AMPLITUDE_21_01"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21_01 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21_01 "CAN_SCAN_INDEX_2LSB_21_01"; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_02 "CAN_DET_CONFID_AZIMUTH_21_02"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_02 "CAN_DET_CONFID_AZIMUTH_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_02 "CAN_DET_CONFID_AZIMUTH_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_02 "CAN_DET_SUPER_RES_TARGET_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21_02 "CAN_DET_ND_TARGET_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_02 "CAN_DET_HOST_VEH_CLUTTER_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21_02 "CAN_DET_VALID_LEVEL_21_02"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21_02 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21_02 "CAN_DET_AZIMUTH_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21_02 "CAN_DET_RANGE_21_02"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21_02 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21_02 "CAN_DET_RANGE_RATE_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21_02 "CAN_DET_AMPLITUDE_21_02"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21_02 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21_02 "CAN_SCAN_INDEX_2LSB_21_02"; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_03 "CAN_DET_CONFID_AZIMUTH_21_03"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_03 "CAN_DET_CONFID_AZIMUTH_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_03 "CAN_DET_CONFID_AZIMUTH_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_03 "CAN_DET_SUPER_RES_TARGET_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21_03 "CAN_DET_ND_TARGET_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_03 "CAN_DET_HOST_VEH_CLUTTER_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21_03 "CAN_DET_VALID_LEVEL_21_03"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21_03 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21_03 "CAN_DET_AZIMUTH_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21_03 "CAN_DET_RANGE_21_03"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21_03 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21_03 "CAN_DET_RANGE_RATE_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21_03 "CAN_DET_AMPLITUDE_21_03"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21_03 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21_03 "CAN_SCAN_INDEX_2LSB_21_03"; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_04 "CAN_DET_CONFID_AZIMUTH_21_04"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_04 "CAN_DET_CONFID_AZIMUTH_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_04 "CAN_DET_CONFID_AZIMUTH_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_04 "CAN_DET_SUPER_RES_TARGET_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21_04 "CAN_DET_ND_TARGET_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_04 "CAN_DET_HOST_VEH_CLUTTER_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21_04 "CAN_DET_VALID_LEVEL_21_04"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21_04 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21_04 "CAN_DET_AZIMUTH_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21_04 "CAN_DET_RANGE_21_04"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21_04 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21_04 "CAN_DET_RANGE_RATE_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21_04 "CAN_DET_AMPLITUDE_21_04"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21_04 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21_04 "CAN_SCAN_INDEX_2LSB_21_04"; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_05 "CAN_DET_CONFID_AZIMUTH_21_05"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_05 "CAN_DET_CONFID_AZIMUTH_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_05 "CAN_DET_CONFID_AZIMUTH_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_05 "CAN_DET_SUPER_RES_TARGET_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21_05 "CAN_DET_ND_TARGET_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_05 "CAN_DET_HOST_VEH_CLUTTER_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21_05 "CAN_DET_VALID_LEVEL_21_05"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21_05 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21_05 "CAN_DET_AZIMUTH_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21_05 "CAN_DET_RANGE_21_05"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21_05 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21_05 "CAN_DET_RANGE_RATE_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21_05 "CAN_DET_AMPLITUDE_21_05"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21_05 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21_05 "CAN_SCAN_INDEX_2LSB_21_05"; +BA_ "GenSigVtEn" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_06 "CAN_DET_CONFID_AZIMUTH_21_06"; +BA_ "GenSigVtName" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_06 "CAN_DET_CONFID_AZIMUTH_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_CONFID_AZIMUTH_21_06 "CAN_DET_CONFID_AZIMUTH_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_SUPER_RES_TARGET_21_06 "CAN_DET_SUPER_RES_TARGET_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_ND_TARGET_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_ND_TARGET_21_06 "CAN_DET_ND_TARGET_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_HOST_VEH_CLUTTER_21_06 "CAN_DET_HOST_VEH_CLUTTER_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_VALID_LEVEL_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_VALID_LEVEL_21_06 "CAN_DET_VALID_LEVEL_21_06"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_AZIMUTH_21_06 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AZIMUTH_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AZIMUTH_21_06 "CAN_DET_AZIMUTH_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_21_06 "CAN_DET_RANGE_21_06"; +BA_ "GenSigStartValue" SG_ 308 CAN_DET_RANGE_RATE_21_06 0; +BA_ "GenSigSendType" SG_ 308 CAN_DET_RANGE_RATE_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_RANGE_RATE_21_06 "CAN_DET_RANGE_RATE_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_DET_AMPLITUDE_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_DET_AMPLITUDE_21_06 "CAN_DET_AMPLITUDE_21_06"; +BA_ "GenSigSendType" SG_ 308 CAN_SCAN_INDEX_2LSB_21_06 0; +BA_ "GenSigCmt" SG_ 308 CAN_SCAN_INDEX_2LSB_21_06 "CAN_SCAN_INDEX_2LSB_21_06"; +BA_ "GenMsgSendType" BO_ 307 1; +BA_ "GenMsgILSupport" BO_ 307 1; +BA_ "GenMsgNrOfRepetition" BO_ 307 0; +BA_ "GenMsgCycleTime" BO_ 307 0; +BA_ "NetworkInitialization" BO_ 307 0; +BA_ "GenMsgDelayTime" BO_ 307 0; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_01 "CAN_DET_CONFID_AZIMUTH_20_01"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_01 "CAN_DET_CONFID_AZIMUTH_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_01 "CAN_DET_CONFID_AZIMUTH_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_01 "CAN_DET_SUPER_RES_TARGET_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20_01 "CAN_DET_ND_TARGET_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_01 "CAN_DET_HOST_VEH_CLUTTER_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20_01 "CAN_DET_VALID_LEVEL_20_01"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20_01 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20_01 "CAN_DET_AZIMUTH_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20_01 "CAN_DET_RANGE_20_01"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20_01 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20_01 "CAN_DET_RANGE_RATE_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20_01 "CAN_DET_AMPLITUDE_20_01"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20_01 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20_01 "CAN_SCAN_INDEX_2LSB_20_01"; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_02 "CAN_DET_CONFID_AZIMUTH_20_02"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_02 "CAN_DET_CONFID_AZIMUTH_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_02 "CAN_DET_CONFID_AZIMUTH_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_02 "CAN_DET_SUPER_RES_TARGET_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20_02 "CAN_DET_ND_TARGET_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_02 "CAN_DET_HOST_VEH_CLUTTER_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20_02 "CAN_DET_VALID_LEVEL_20_02"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20_02 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20_02 "CAN_DET_AZIMUTH_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20_02 "CAN_DET_RANGE_20_02"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20_02 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20_02 "CAN_DET_RANGE_RATE_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20_02 "CAN_DET_AMPLITUDE_20_02"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20_02 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20_02 "CAN_SCAN_INDEX_2LSB_20_02"; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_03 "CAN_DET_CONFID_AZIMUTH_20_03"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_03 "CAN_DET_CONFID_AZIMUTH_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_03 "CAN_DET_CONFID_AZIMUTH_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_03 "CAN_DET_SUPER_RES_TARGET_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20_03 "CAN_DET_ND_TARGET_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_03 "CAN_DET_HOST_VEH_CLUTTER_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20_03 "CAN_DET_VALID_LEVEL_20_03"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20_03 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20_03 "CAN_DET_AZIMUTH_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20_03 "CAN_DET_RANGE_20_03"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20_03 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20_03 "CAN_DET_RANGE_RATE_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20_03 "CAN_DET_AMPLITUDE_20_03"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20_03 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20_03 "CAN_SCAN_INDEX_2LSB_20_03"; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_04 "CAN_DET_CONFID_AZIMUTH_20_04"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_04 "CAN_DET_CONFID_AZIMUTH_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_04 "CAN_DET_CONFID_AZIMUTH_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_04 "CAN_DET_SUPER_RES_TARGET_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20_04 "CAN_DET_ND_TARGET_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_04 "CAN_DET_HOST_VEH_CLUTTER_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20_04 "CAN_DET_VALID_LEVEL_20_04"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20_04 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20_04 "CAN_DET_AZIMUTH_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20_04 "CAN_DET_RANGE_20_04"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20_04 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20_04 "CAN_DET_RANGE_RATE_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20_04 "CAN_DET_AMPLITUDE_20_04"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20_04 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20_04 "CAN_SCAN_INDEX_2LSB_20_04"; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_05 "CAN_DET_CONFID_AZIMUTH_20_05"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_05 "CAN_DET_CONFID_AZIMUTH_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_05 "CAN_DET_CONFID_AZIMUTH_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_05 "CAN_DET_SUPER_RES_TARGET_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20_05 "CAN_DET_ND_TARGET_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_05 "CAN_DET_HOST_VEH_CLUTTER_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20_05 "CAN_DET_VALID_LEVEL_20_05"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20_05 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20_05 "CAN_DET_AZIMUTH_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20_05 "CAN_DET_RANGE_20_05"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20_05 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20_05 "CAN_DET_RANGE_RATE_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20_05 "CAN_DET_AMPLITUDE_20_05"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20_05 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20_05 "CAN_SCAN_INDEX_2LSB_20_05"; +BA_ "GenSigVtEn" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_06 "CAN_DET_CONFID_AZIMUTH_20_06"; +BA_ "GenSigVtName" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_06 "CAN_DET_CONFID_AZIMUTH_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_CONFID_AZIMUTH_20_06 "CAN_DET_CONFID_AZIMUTH_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_SUPER_RES_TARGET_20_06 "CAN_DET_SUPER_RES_TARGET_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_ND_TARGET_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_ND_TARGET_20_06 "CAN_DET_ND_TARGET_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_HOST_VEH_CLUTTER_20_06 "CAN_DET_HOST_VEH_CLUTTER_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_VALID_LEVEL_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_VALID_LEVEL_20_06 "CAN_DET_VALID_LEVEL_20_06"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_AZIMUTH_20_06 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AZIMUTH_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AZIMUTH_20_06 "CAN_DET_AZIMUTH_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_20_06 "CAN_DET_RANGE_20_06"; +BA_ "GenSigStartValue" SG_ 307 CAN_DET_RANGE_RATE_20_06 0; +BA_ "GenSigSendType" SG_ 307 CAN_DET_RANGE_RATE_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_RANGE_RATE_20_06 "CAN_DET_RANGE_RATE_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_DET_AMPLITUDE_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_DET_AMPLITUDE_20_06 "CAN_DET_AMPLITUDE_20_06"; +BA_ "GenSigSendType" SG_ 307 CAN_SCAN_INDEX_2LSB_20_06 0; +BA_ "GenSigCmt" SG_ 307 CAN_SCAN_INDEX_2LSB_20_06 "CAN_SCAN_INDEX_2LSB_20_06"; +BA_ "GenMsgSendType" BO_ 306 1; +BA_ "GenMsgILSupport" BO_ 306 1; +BA_ "GenMsgNrOfRepetition" BO_ 306 0; +BA_ "GenMsgCycleTime" BO_ 306 0; +BA_ "NetworkInitialization" BO_ 306 0; +BA_ "GenMsgDelayTime" BO_ 306 0; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_01 "CAN_DET_CONFID_AZIMUTH_19_01"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_01 "CAN_DET_CONFID_AZIMUTH_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_01 "CAN_DET_CONFID_AZIMUTH_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_01 "CAN_DET_SUPER_RES_TARGET_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19_01 "CAN_DET_ND_TARGET_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_01 "CAN_DET_HOST_VEH_CLUTTER_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19_01 "CAN_DET_VALID_LEVEL_19_01"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19_01 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19_01 "CAN_DET_AZIMUTH_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19_01 "CAN_DET_RANGE_19_01"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19_01 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19_01 "CAN_DET_RANGE_RATE_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19_01 "CAN_DET_AMPLITUDE_19_01"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19_01 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19_01 "CAN_SCAN_INDEX_2LSB_19_01"; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_02 "CAN_DET_CONFID_AZIMUTH_19_02"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_02 "CAN_DET_CONFID_AZIMUTH_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_02 "CAN_DET_CONFID_AZIMUTH_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_02 "CAN_DET_SUPER_RES_TARGET_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19_02 "CAN_DET_ND_TARGET_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_02 "CAN_DET_HOST_VEH_CLUTTER_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19_02 "CAN_DET_VALID_LEVEL_19_02"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19_02 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19_02 "CAN_DET_AZIMUTH_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19_02 "CAN_DET_RANGE_19_02"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19_02 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19_02 "CAN_DET_RANGE_RATE_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19_02 "CAN_DET_AMPLITUDE_19_02"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19_02 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19_02 "CAN_SCAN_INDEX_2LSB_19_02"; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_03 "CAN_DET_CONFID_AZIMUTH_19_03"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_03 "CAN_DET_CONFID_AZIMUTH_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_03 "CAN_DET_CONFID_AZIMUTH_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_03 "CAN_DET_SUPER_RES_TARGET_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19_03 "CAN_DET_ND_TARGET_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_03 "CAN_DET_HOST_VEH_CLUTTER_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19_03 "CAN_DET_VALID_LEVEL_19_03"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19_03 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19_03 "CAN_DET_AZIMUTH_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19_03 "CAN_DET_RANGE_19_03"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19_03 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19_03 "CAN_DET_RANGE_RATE_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19_03 "CAN_DET_AMPLITUDE_19_03"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19_03 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19_03 "CAN_SCAN_INDEX_2LSB_19_03"; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_04 "CAN_DET_CONFID_AZIMUTH_19_04"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_04 "CAN_DET_CONFID_AZIMUTH_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_04 "CAN_DET_CONFID_AZIMUTH_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_04 "CAN_DET_SUPER_RES_TARGET_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19_04 "CAN_DET_ND_TARGET_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_04 "CAN_DET_HOST_VEH_CLUTTER_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19_04 "CAN_DET_VALID_LEVEL_19_04"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19_04 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19_04 "CAN_DET_AZIMUTH_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19_04 "CAN_DET_RANGE_19_04"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19_04 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19_04 "CAN_DET_RANGE_RATE_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19_04 "CAN_DET_AMPLITUDE_19_04"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19_04 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19_04 "CAN_SCAN_INDEX_2LSB_19_04"; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_05 "CAN_DET_CONFID_AZIMUTH_19_05"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_05 "CAN_DET_CONFID_AZIMUTH_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_05 "CAN_DET_CONFID_AZIMUTH_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_05 "CAN_DET_SUPER_RES_TARGET_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19_05 "CAN_DET_ND_TARGET_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_05 "CAN_DET_HOST_VEH_CLUTTER_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19_05 "CAN_DET_VALID_LEVEL_19_05"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19_05 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19_05 "CAN_DET_AZIMUTH_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19_05 "CAN_DET_RANGE_19_05"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19_05 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19_05 "CAN_DET_RANGE_RATE_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19_05 "CAN_DET_AMPLITUDE_19_05"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19_05 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19_05 "CAN_SCAN_INDEX_2LSB_19_05"; +BA_ "GenSigVtEn" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_06 "CAN_DET_CONFID_AZIMUTH_19_06"; +BA_ "GenSigVtName" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_06 "CAN_DET_CONFID_AZIMUTH_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_CONFID_AZIMUTH_19_06 "CAN_DET_CONFID_AZIMUTH_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_SUPER_RES_TARGET_19_06 "CAN_DET_SUPER_RES_TARGET_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_ND_TARGET_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_ND_TARGET_19_06 "CAN_DET_ND_TARGET_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_HOST_VEH_CLUTTER_19_06 "CAN_DET_HOST_VEH_CLUTTER_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_VALID_LEVEL_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_VALID_LEVEL_19_06 "CAN_DET_VALID_LEVEL_19_06"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_AZIMUTH_19_06 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AZIMUTH_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AZIMUTH_19_06 "CAN_DET_AZIMUTH_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_19_06 "CAN_DET_RANGE_19_06"; +BA_ "GenSigStartValue" SG_ 306 CAN_DET_RANGE_RATE_19_06 0; +BA_ "GenSigSendType" SG_ 306 CAN_DET_RANGE_RATE_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_RANGE_RATE_19_06 "CAN_DET_RANGE_RATE_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_DET_AMPLITUDE_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_DET_AMPLITUDE_19_06 "CAN_DET_AMPLITUDE_19_06"; +BA_ "GenSigSendType" SG_ 306 CAN_SCAN_INDEX_2LSB_19_06 0; +BA_ "GenSigCmt" SG_ 306 CAN_SCAN_INDEX_2LSB_19_06 "CAN_SCAN_INDEX_2LSB_19_06"; +BA_ "GenMsgSendType" BO_ 305 1; +BA_ "GenMsgILSupport" BO_ 305 1; +BA_ "GenMsgNrOfRepetition" BO_ 305 0; +BA_ "GenMsgCycleTime" BO_ 305 0; +BA_ "NetworkInitialization" BO_ 305 0; +BA_ "GenMsgDelayTime" BO_ 305 0; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_01 "CAN_DET_CONFID_AZIMUTH_18_01"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_01 "CAN_DET_CONFID_AZIMUTH_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_01 "CAN_DET_CONFID_AZIMUTH_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_01 "CAN_DET_SUPER_RES_TARGET_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18_01 "CAN_DET_ND_TARGET_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_01 "CAN_DET_HOST_VEH_CLUTTER_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18_01 "CAN_DET_VALID_LEVEL_18_01"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18_01 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18_01 "CAN_DET_AZIMUTH_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18_01 "CAN_DET_RANGE_18_01"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18_01 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18_01 "CAN_DET_RANGE_RATE_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18_01 "CAN_DET_AMPLITUDE_18_01"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18_01 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18_01 "CAN_SCAN_INDEX_2LSB_18_01"; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_02 "CAN_DET_CONFID_AZIMUTH_18_02"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_02 "CAN_DET_CONFID_AZIMUTH_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_02 "CAN_DET_CONFID_AZIMUTH_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_02 "CAN_DET_SUPER_RES_TARGET_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18_02 "CAN_DET_ND_TARGET_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_02 "CAN_DET_HOST_VEH_CLUTTER_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18_02 "CAN_DET_VALID_LEVEL_18_02"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18_02 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18_02 "CAN_DET_AZIMUTH_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18_02 "CAN_DET_RANGE_18_02"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18_02 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18_02 "CAN_DET_RANGE_RATE_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18_02 "CAN_DET_AMPLITUDE_18_02"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18_02 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18_02 "CAN_SCAN_INDEX_2LSB_18_02"; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_03 "CAN_DET_CONFID_AZIMUTH_18_03"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_03 "CAN_DET_CONFID_AZIMUTH_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_03 "CAN_DET_CONFID_AZIMUTH_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_03 "CAN_DET_SUPER_RES_TARGET_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18_03 "CAN_DET_ND_TARGET_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_03 "CAN_DET_HOST_VEH_CLUTTER_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18_03 "CAN_DET_VALID_LEVEL_18_03"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18_03 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18_03 "CAN_DET_AZIMUTH_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18_03 "CAN_DET_RANGE_18_03"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18_03 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18_03 "CAN_DET_RANGE_RATE_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18_03 "CAN_DET_AMPLITUDE_18_03"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18_03 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18_03 "CAN_SCAN_INDEX_2LSB_18_03"; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_04 "CAN_DET_CONFID_AZIMUTH_18_04"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_04 "CAN_DET_CONFID_AZIMUTH_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_04 "CAN_DET_CONFID_AZIMUTH_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_04 "CAN_DET_SUPER_RES_TARGET_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18_04 "CAN_DET_ND_TARGET_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_04 "CAN_DET_HOST_VEH_CLUTTER_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18_04 "CAN_DET_VALID_LEVEL_18_04"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18_04 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18_04 "CAN_DET_AZIMUTH_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18_04 "CAN_DET_RANGE_18_04"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18_04 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18_04 "CAN_DET_RANGE_RATE_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18_04 "CAN_DET_AMPLITUDE_18_04"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18_04 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18_04 "CAN_SCAN_INDEX_2LSB_18_04"; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_05 "CAN_DET_CONFID_AZIMUTH_18_05"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_05 "CAN_DET_CONFID_AZIMUTH_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_05 "CAN_DET_CONFID_AZIMUTH_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_05 "CAN_DET_SUPER_RES_TARGET_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18_05 "CAN_DET_ND_TARGET_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_05 "CAN_DET_HOST_VEH_CLUTTER_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18_05 "CAN_DET_VALID_LEVEL_18_05"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18_05 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18_05 "CAN_DET_AZIMUTH_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18_05 "CAN_DET_RANGE_18_05"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18_05 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18_05 "CAN_DET_RANGE_RATE_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18_05 "CAN_DET_AMPLITUDE_18_05"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18_05 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18_05 "CAN_SCAN_INDEX_2LSB_18_05"; +BA_ "GenSigVtEn" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_06 "CAN_DET_CONFID_AZIMUTH_18_06"; +BA_ "GenSigVtName" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_06 "CAN_DET_CONFID_AZIMUTH_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_CONFID_AZIMUTH_18_06 "CAN_DET_CONFID_AZIMUTH_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_SUPER_RES_TARGET_18_06 "CAN_DET_SUPER_RES_TARGET_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_ND_TARGET_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_ND_TARGET_18_06 "CAN_DET_ND_TARGET_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_HOST_VEH_CLUTTER_18_06 "CAN_DET_HOST_VEH_CLUTTER_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_VALID_LEVEL_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_VALID_LEVEL_18_06 "CAN_DET_VALID_LEVEL_18_06"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_AZIMUTH_18_06 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AZIMUTH_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AZIMUTH_18_06 "CAN_DET_AZIMUTH_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_18_06 "CAN_DET_RANGE_18_06"; +BA_ "GenSigStartValue" SG_ 305 CAN_DET_RANGE_RATE_18_06 0; +BA_ "GenSigSendType" SG_ 305 CAN_DET_RANGE_RATE_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_RANGE_RATE_18_06 "CAN_DET_RANGE_RATE_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_DET_AMPLITUDE_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_DET_AMPLITUDE_18_06 "CAN_DET_AMPLITUDE_18_06"; +BA_ "GenSigSendType" SG_ 305 CAN_SCAN_INDEX_2LSB_18_06 0; +BA_ "GenSigCmt" SG_ 305 CAN_SCAN_INDEX_2LSB_18_06 "CAN_SCAN_INDEX_2LSB_18_06"; +BA_ "GenMsgSendType" BO_ 341 1; +BA_ "GenMsgILSupport" BO_ 341 1; +BA_ "GenMsgNrOfRepetition" BO_ 341 0; +BA_ "GenMsgCycleTime" BO_ 341 0; +BA_ "NetworkInitialization" BO_ 341 0; +BA_ "GenMsgDelayTime" BO_ 341 0; +BA_ "GenSigVtEn" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigVtName" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_SUPER_RES_TARGET_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_SUPER_RES_TARGET_54 "CAN_DET_SUPER_RES_TARGET_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_ND_TARGET_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_ND_TARGET_54 "CAN_DET_ND_TARGET_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_HOST_VEH_CLUTTER_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_HOST_VEH_CLUTTER_54 "CAN_DET_HOST_VEH_CLUTTER_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_VALID_LEVEL_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_VALID_LEVEL_54 "CAN_DET_VALID_LEVEL_54"; +BA_ "GenSigStartValue" SG_ 341 CAN_DET_AZIMUTH_54 0; +BA_ "GenSigSendType" SG_ 341 CAN_DET_AZIMUTH_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_AZIMUTH_54 "CAN_DET_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_RANGE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_RANGE_54 "CAN_DET_RANGE_54"; +BA_ "GenSigStartValue" SG_ 341 CAN_DET_RANGE_RATE_54 0; +BA_ "GenSigSendType" SG_ 341 CAN_DET_RANGE_RATE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_RANGE_RATE_54 "CAN_DET_RANGE_RATE_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_AMPLITUDE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_AMPLITUDE_54 "CAN_DET_AMPLITUDE_54"; +BA_ "GenSigSendType" SG_ 341 CAN_SCAN_INDEX_2LSB_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_SCAN_INDEX_2LSB_54 "CAN_SCAN_INDEX_2LSB_54"; +BA_ "GenMsgSendType" BO_ 340 1; +BA_ "GenMsgILSupport" BO_ 340 1; +BA_ "GenMsgNrOfRepetition" BO_ 340 0; +BA_ "GenMsgCycleTime" BO_ 340 0; +BA_ "NetworkInitialization" BO_ 340 0; +BA_ "GenMsgDelayTime" BO_ 340 0; +BA_ "GenSigVtEn" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigVtName" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_SUPER_RES_TARGET_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_SUPER_RES_TARGET_53 "CAN_DET_SUPER_RES_TARGET_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_ND_TARGET_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_ND_TARGET_53 "CAN_DET_ND_TARGET_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_HOST_VEH_CLUTTER_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_HOST_VEH_CLUTTER_53 "CAN_DET_HOST_VEH_CLUTTER_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_VALID_LEVEL_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_VALID_LEVEL_53 "CAN_DET_VALID_LEVEL_53"; +BA_ "GenSigStartValue" SG_ 340 CAN_DET_AZIMUTH_53 0; +BA_ "GenSigSendType" SG_ 340 CAN_DET_AZIMUTH_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_AZIMUTH_53 "CAN_DET_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_RANGE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_RANGE_53 "CAN_DET_RANGE_53"; +BA_ "GenSigStartValue" SG_ 340 CAN_DET_RANGE_RATE_53 0; +BA_ "GenSigSendType" SG_ 340 CAN_DET_RANGE_RATE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_RANGE_RATE_53 "CAN_DET_RANGE_RATE_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_AMPLITUDE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_AMPLITUDE_53 "CAN_DET_AMPLITUDE_53"; +BA_ "GenSigSendType" SG_ 340 CAN_SCAN_INDEX_2LSB_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_SCAN_INDEX_2LSB_53 "CAN_SCAN_INDEX_2LSB_53"; +BA_ "GenMsgSendType" BO_ 339 1; +BA_ "GenMsgILSupport" BO_ 339 1; +BA_ "GenMsgNrOfRepetition" BO_ 339 0; +BA_ "GenMsgCycleTime" BO_ 339 0; +BA_ "NetworkInitialization" BO_ 339 0; +BA_ "GenMsgDelayTime" BO_ 339 0; +BA_ "GenSigVtEn" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigVtName" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_SUPER_RES_TARGET_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_SUPER_RES_TARGET_52 "CAN_DET_SUPER_RES_TARGET_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_ND_TARGET_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_ND_TARGET_52 "CAN_DET_ND_TARGET_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_HOST_VEH_CLUTTER_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_HOST_VEH_CLUTTER_52 "CAN_DET_HOST_VEH_CLUTTER_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_VALID_LEVEL_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_VALID_LEVEL_52 "CAN_DET_VALID_LEVEL_52"; +BA_ "GenSigStartValue" SG_ 339 CAN_DET_AZIMUTH_52 0; +BA_ "GenSigSendType" SG_ 339 CAN_DET_AZIMUTH_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_AZIMUTH_52 "CAN_DET_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_RANGE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_RANGE_52 "CAN_DET_RANGE_52"; +BA_ "GenSigStartValue" SG_ 339 CAN_DET_RANGE_RATE_52 0; +BA_ "GenSigSendType" SG_ 339 CAN_DET_RANGE_RATE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_RANGE_RATE_52 "CAN_DET_RANGE_RATE_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_AMPLITUDE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_AMPLITUDE_52 "CAN_DET_AMPLITUDE_52"; +BA_ "GenSigSendType" SG_ 339 CAN_SCAN_INDEX_2LSB_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_SCAN_INDEX_2LSB_52 "CAN_SCAN_INDEX_2LSB_52"; +BA_ "GenMsgSendType" BO_ 338 1; +BA_ "GenMsgILSupport" BO_ 338 1; +BA_ "GenMsgNrOfRepetition" BO_ 338 0; +BA_ "GenMsgCycleTime" BO_ 338 0; +BA_ "NetworkInitialization" BO_ 338 0; +BA_ "GenMsgDelayTime" BO_ 338 0; +BA_ "GenSigVtEn" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigVtName" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_SUPER_RES_TARGET_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_SUPER_RES_TARGET_51 "CAN_DET_SUPER_RES_TARGET_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_ND_TARGET_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_ND_TARGET_51 "CAN_DET_ND_TARGET_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_HOST_VEH_CLUTTER_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_HOST_VEH_CLUTTER_51 "CAN_DET_HOST_VEH_CLUTTER_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_VALID_LEVEL_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_VALID_LEVEL_51 "CAN_DET_VALID_LEVEL_51"; +BA_ "GenSigStartValue" SG_ 338 CAN_DET_AZIMUTH_51 0; +BA_ "GenSigSendType" SG_ 338 CAN_DET_AZIMUTH_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_AZIMUTH_51 "CAN_DET_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_RANGE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_RANGE_51 "CAN_DET_RANGE_51"; +BA_ "GenSigStartValue" SG_ 338 CAN_DET_RANGE_RATE_51 0; +BA_ "GenSigSendType" SG_ 338 CAN_DET_RANGE_RATE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_RANGE_RATE_51 "CAN_DET_RANGE_RATE_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_AMPLITUDE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_AMPLITUDE_51 "CAN_DET_AMPLITUDE_51"; +BA_ "GenSigSendType" SG_ 338 CAN_SCAN_INDEX_2LSB_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_SCAN_INDEX_2LSB_51 "CAN_SCAN_INDEX_2LSB_51"; +BA_ "GenMsgSendType" BO_ 337 1; +BA_ "GenMsgILSupport" BO_ 337 1; +BA_ "GenMsgNrOfRepetition" BO_ 337 0; +BA_ "GenMsgCycleTime" BO_ 337 0; +BA_ "NetworkInitialization" BO_ 337 0; +BA_ "GenMsgDelayTime" BO_ 337 0; +BA_ "GenSigVtEn" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigVtName" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_SUPER_RES_TARGET_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_SUPER_RES_TARGET_50 "CAN_DET_SUPER_RES_TARGET_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_ND_TARGET_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_ND_TARGET_50 "CAN_DET_ND_TARGET_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_HOST_VEH_CLUTTER_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_HOST_VEH_CLUTTER_50 "CAN_DET_HOST_VEH_CLUTTER_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_VALID_LEVEL_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_VALID_LEVEL_50 "CAN_DET_VALID_LEVEL_50"; +BA_ "GenSigStartValue" SG_ 337 CAN_DET_AZIMUTH_50 0; +BA_ "GenSigSendType" SG_ 337 CAN_DET_AZIMUTH_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_AZIMUTH_50 "CAN_DET_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_RANGE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_RANGE_50 "CAN_DET_RANGE_50"; +BA_ "GenSigStartValue" SG_ 337 CAN_DET_RANGE_RATE_50 0; +BA_ "GenSigSendType" SG_ 337 CAN_DET_RANGE_RATE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_RANGE_RATE_50 "CAN_DET_RANGE_RATE_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_AMPLITUDE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_AMPLITUDE_50 "CAN_DET_AMPLITUDE_50"; +BA_ "GenSigSendType" SG_ 337 CAN_SCAN_INDEX_2LSB_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_SCAN_INDEX_2LSB_50 "CAN_SCAN_INDEX_2LSB_50"; +BA_ "GenMsgSendType" BO_ 336 1; +BA_ "GenMsgILSupport" BO_ 336 1; +BA_ "GenMsgNrOfRepetition" BO_ 336 0; +BA_ "GenMsgCycleTime" BO_ 336 0; +BA_ "NetworkInitialization" BO_ 336 0; +BA_ "GenMsgDelayTime" BO_ 336 0; +BA_ "GenSigVtEn" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigVtName" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_SUPER_RES_TARGET_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_SUPER_RES_TARGET_49 "CAN_DET_SUPER_RES_TARGET_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_ND_TARGET_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_ND_TARGET_49 "CAN_DET_ND_TARGET_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_HOST_VEH_CLUTTER_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_HOST_VEH_CLUTTER_49 "CAN_DET_HOST_VEH_CLUTTER_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_VALID_LEVEL_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_VALID_LEVEL_49 "CAN_DET_VALID_LEVEL_49"; +BA_ "GenSigStartValue" SG_ 336 CAN_DET_AZIMUTH_49 0; +BA_ "GenSigSendType" SG_ 336 CAN_DET_AZIMUTH_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_AZIMUTH_49 "CAN_DET_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_RANGE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_RANGE_49 "CAN_DET_RANGE_49"; +BA_ "GenSigStartValue" SG_ 336 CAN_DET_RANGE_RATE_49 0; +BA_ "GenSigSendType" SG_ 336 CAN_DET_RANGE_RATE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_RANGE_RATE_49 "CAN_DET_RANGE_RATE_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_AMPLITUDE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_AMPLITUDE_49 "CAN_DET_AMPLITUDE_49"; +BA_ "GenSigSendType" SG_ 336 CAN_SCAN_INDEX_2LSB_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_SCAN_INDEX_2LSB_49 "CAN_SCAN_INDEX_2LSB_49"; +BA_ "GenMsgSendType" BO_ 326 1; +BA_ "GenMsgILSupport" BO_ 326 1; +BA_ "GenMsgNrOfRepetition" BO_ 326 0; +BA_ "GenMsgCycleTime" BO_ 326 0; +BA_ "NetworkInitialization" BO_ 326 0; +BA_ "GenMsgDelayTime" BO_ 326 0; +BA_ "GenSigVtEn" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigVtName" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_SUPER_RES_TARGET_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_SUPER_RES_TARGET_39 "CAN_DET_SUPER_RES_TARGET_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_ND_TARGET_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_ND_TARGET_39 "CAN_DET_ND_TARGET_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_HOST_VEH_CLUTTER_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_HOST_VEH_CLUTTER_39 "CAN_DET_HOST_VEH_CLUTTER_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_VALID_LEVEL_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_VALID_LEVEL_39 "CAN_DET_VALID_LEVEL_39"; +BA_ "GenSigStartValue" SG_ 326 CAN_DET_AZIMUTH_39 0; +BA_ "GenSigSendType" SG_ 326 CAN_DET_AZIMUTH_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_AZIMUTH_39 "CAN_DET_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_RANGE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_RANGE_39 "CAN_DET_RANGE_39"; +BA_ "GenSigStartValue" SG_ 326 CAN_DET_RANGE_RATE_39 0; +BA_ "GenSigSendType" SG_ 326 CAN_DET_RANGE_RATE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_RANGE_RATE_39 "CAN_DET_RANGE_RATE_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_AMPLITUDE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_AMPLITUDE_39 "CAN_DET_AMPLITUDE_39"; +BA_ "GenSigSendType" SG_ 326 CAN_SCAN_INDEX_2LSB_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_SCAN_INDEX_2LSB_39 "CAN_SCAN_INDEX_2LSB_39"; +BA_ "GenMsgSendType" BO_ 315 1; +BA_ "GenMsgILSupport" BO_ 315 1; +BA_ "GenMsgNrOfRepetition" BO_ 315 0; +BA_ "GenMsgCycleTime" BO_ 315 0; +BA_ "NetworkInitialization" BO_ 315 0; +BA_ "GenMsgDelayTime" BO_ 315 0; +BA_ "GenSigVtEn" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigVtName" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_SUPER_RES_TARGET_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_SUPER_RES_TARGET_28 "CAN_DET_SUPER_RES_TARGET_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_ND_TARGET_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_ND_TARGET_28 "CAN_DET_ND_TARGET_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_HOST_VEH_CLUTTER_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_HOST_VEH_CLUTTER_28 "CAN_DET_HOST_VEH_CLUTTER_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_VALID_LEVEL_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_VALID_LEVEL_28 "CAN_DET_VALID_LEVEL_28"; +BA_ "GenSigStartValue" SG_ 315 CAN_DET_AZIMUTH_28 0; +BA_ "GenSigSendType" SG_ 315 CAN_DET_AZIMUTH_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_AZIMUTH_28 "CAN_DET_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_RANGE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_RANGE_28 "CAN_DET_RANGE_28"; +BA_ "GenSigStartValue" SG_ 315 CAN_DET_RANGE_RATE_28 0; +BA_ "GenSigSendType" SG_ 315 CAN_DET_RANGE_RATE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_RANGE_RATE_28 "CAN_DET_RANGE_RATE_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_AMPLITUDE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_AMPLITUDE_28 "CAN_DET_AMPLITUDE_28"; +BA_ "GenSigSendType" SG_ 315 CAN_SCAN_INDEX_2LSB_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_SCAN_INDEX_2LSB_28 "CAN_SCAN_INDEX_2LSB_28"; +BA_ "GenMsgSendType" BO_ 304 1; +BA_ "GenMsgILSupport" BO_ 304 1; +BA_ "GenMsgNrOfRepetition" BO_ 304 0; +BA_ "GenMsgCycleTime" BO_ 304 0; +BA_ "NetworkInitialization" BO_ 304 0; +BA_ "GenMsgDelayTime" BO_ 304 0; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_01 "CAN_DET_CONFID_AZIMUTH_17_01"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_01 "CAN_DET_CONFID_AZIMUTH_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_01 "CAN_DET_CONFID_AZIMUTH_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_01 "CAN_DET_SUPER_RES_TARGET_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17_01 "CAN_DET_ND_TARGET_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_01 "CAN_DET_HOST_VEH_CLUTTER_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17_01 "CAN_DET_VALID_LEVEL_17_01"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17_01 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17_01 "CAN_DET_AZIMUTH_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17_01 "CAN_DET_RANGE_17_01"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17_01 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17_01 "CAN_DET_RANGE_RATE_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17_01 "CAN_DET_AMPLITUDE_17_01"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17_01 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17_01 "CAN_SCAN_INDEX_2LSB_17_01"; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_02 "CAN_DET_CONFID_AZIMUTH_17_02"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_02 "CAN_DET_CONFID_AZIMUTH_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_02 "CAN_DET_CONFID_AZIMUTH_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_02 "CAN_DET_SUPER_RES_TARGET_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17_02 "CAN_DET_ND_TARGET_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_02 "CAN_DET_HOST_VEH_CLUTTER_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17_02 "CAN_DET_VALID_LEVEL_17_02"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17_02 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17_02 "CAN_DET_AZIMUTH_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17_02 "CAN_DET_RANGE_17_02"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17_02 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17_02 "CAN_DET_RANGE_RATE_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17_02 "CAN_DET_AMPLITUDE_17_02"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17_02 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17_02 "CAN_SCAN_INDEX_2LSB_17_02"; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_03 "CAN_DET_CONFID_AZIMUTH_17_03"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_03 "CAN_DET_CONFID_AZIMUTH_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_03 "CAN_DET_CONFID_AZIMUTH_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_03 "CAN_DET_SUPER_RES_TARGET_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17_03 "CAN_DET_ND_TARGET_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_03 "CAN_DET_HOST_VEH_CLUTTER_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17_03 "CAN_DET_VALID_LEVEL_17_03"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17_03 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17_03 "CAN_DET_AZIMUTH_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17_03 "CAN_DET_RANGE_17_03"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17_03 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17_03 "CAN_DET_RANGE_RATE_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17_03 "CAN_DET_AMPLITUDE_17_03"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17_03 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17_03 "CAN_SCAN_INDEX_2LSB_17_03"; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_04 "CAN_DET_CONFID_AZIMUTH_17_04"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_04 "CAN_DET_CONFID_AZIMUTH_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_04 "CAN_DET_CONFID_AZIMUTH_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_04 "CAN_DET_SUPER_RES_TARGET_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17_04 "CAN_DET_ND_TARGET_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_04 "CAN_DET_HOST_VEH_CLUTTER_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17_04 "CAN_DET_VALID_LEVEL_17_04"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17_04 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17_04 "CAN_DET_AZIMUTH_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17_04 "CAN_DET_RANGE_17_04"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17_04 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17_04 "CAN_DET_RANGE_RATE_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17_04 "CAN_DET_AMPLITUDE_17_04"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17_04 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17_04 "CAN_SCAN_INDEX_2LSB_17_04"; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_05 "CAN_DET_CONFID_AZIMUTH_17_05"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_05 "CAN_DET_CONFID_AZIMUTH_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_05 "CAN_DET_CONFID_AZIMUTH_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_05 "CAN_DET_SUPER_RES_TARGET_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17_05 "CAN_DET_ND_TARGET_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_05 "CAN_DET_HOST_VEH_CLUTTER_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17_05 "CAN_DET_VALID_LEVEL_17_05"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17_05 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17_05 "CAN_DET_AZIMUTH_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17_05 "CAN_DET_RANGE_17_05"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17_05 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17_05 "CAN_DET_RANGE_RATE_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17_05 "CAN_DET_AMPLITUDE_17_05"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17_05 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17_05 "CAN_SCAN_INDEX_2LSB_17_05"; +BA_ "GenSigVtEn" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_06 "CAN_DET_CONFID_AZIMUTH_17_06"; +BA_ "GenSigVtName" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_06 "CAN_DET_CONFID_AZIMUTH_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_CONFID_AZIMUTH_17_06 "CAN_DET_CONFID_AZIMUTH_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_SUPER_RES_TARGET_17_06 "CAN_DET_SUPER_RES_TARGET_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_ND_TARGET_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_ND_TARGET_17_06 "CAN_DET_ND_TARGET_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_HOST_VEH_CLUTTER_17_06 "CAN_DET_HOST_VEH_CLUTTER_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_VALID_LEVEL_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_VALID_LEVEL_17_06 "CAN_DET_VALID_LEVEL_17_06"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_AZIMUTH_17_06 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AZIMUTH_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AZIMUTH_17_06 "CAN_DET_AZIMUTH_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_17_06 "CAN_DET_RANGE_17_06"; +BA_ "GenSigStartValue" SG_ 304 CAN_DET_RANGE_RATE_17_06 0; +BA_ "GenSigSendType" SG_ 304 CAN_DET_RANGE_RATE_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_RANGE_RATE_17_06 "CAN_DET_RANGE_RATE_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_DET_AMPLITUDE_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_DET_AMPLITUDE_17_06 "CAN_DET_AMPLITUDE_17_06"; +BA_ "GenSigSendType" SG_ 304 CAN_SCAN_INDEX_2LSB_17_06 0; +BA_ "GenSigCmt" SG_ 304 CAN_SCAN_INDEX_2LSB_17_06 "CAN_SCAN_INDEX_2LSB_17_06"; +BA_ "GenMsgSendType" BO_ 303 1; +BA_ "GenMsgILSupport" BO_ 303 1; +BA_ "GenMsgNrOfRepetition" BO_ 303 0; +BA_ "GenMsgCycleTime" BO_ 303 0; +BA_ "NetworkInitialization" BO_ 303 0; +BA_ "GenMsgDelayTime" BO_ 303 0; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_01 "CAN_DET_CONFID_AZIMUTH_16_01"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_01 "CAN_DET_CONFID_AZIMUTH_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_01 "CAN_DET_CONFID_AZIMUTH_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_01 "CAN_DET_SUPER_RES_TARGET_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16_01 "CAN_DET_ND_TARGET_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_01 "CAN_DET_HOST_VEH_CLUTTER_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16_01 "CAN_DET_VALID_LEVEL_16_01"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16_01 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16_01 "CAN_DET_AZIMUTH_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16_01 "CAN_DET_RANGE_16_01"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16_01 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16_01 "CAN_DET_RANGE_RATE_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16_01 "CAN_DET_AMPLITUDE_16_01"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16_01 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16_01 "CAN_SCAN_INDEX_2LSB_16_01"; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_02 "CAN_DET_CONFID_AZIMUTH_16_02"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_02 "CAN_DET_CONFID_AZIMUTH_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_02 "CAN_DET_CONFID_AZIMUTH_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_02 "CAN_DET_SUPER_RES_TARGET_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16_02 "CAN_DET_ND_TARGET_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_02 "CAN_DET_HOST_VEH_CLUTTER_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16_02 "CAN_DET_VALID_LEVEL_16_02"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16_02 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16_02 "CAN_DET_AZIMUTH_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16_02 "CAN_DET_RANGE_16_02"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16_02 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16_02 "CAN_DET_RANGE_RATE_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16_02 "CAN_DET_AMPLITUDE_16_02"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16_02 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16_02 "CAN_SCAN_INDEX_2LSB_16_02"; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_03 "CAN_DET_CONFID_AZIMUTH_16_03"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_03 "CAN_DET_CONFID_AZIMUTH_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_03 "CAN_DET_CONFID_AZIMUTH_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_03 "CAN_DET_SUPER_RES_TARGET_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16_03 "CAN_DET_ND_TARGET_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_03 "CAN_DET_HOST_VEH_CLUTTER_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16_03 "CAN_DET_VALID_LEVEL_16_03"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16_03 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16_03 "CAN_DET_AZIMUTH_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16_03 "CAN_DET_RANGE_16_03"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16_03 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16_03 "CAN_DET_RANGE_RATE_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16_03 "CAN_DET_AMPLITUDE_16_03"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16_03 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16_03 "CAN_SCAN_INDEX_2LSB_16_03"; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_04 "CAN_DET_CONFID_AZIMUTH_16_04"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_04 "CAN_DET_CONFID_AZIMUTH_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_04 "CAN_DET_CONFID_AZIMUTH_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_04 "CAN_DET_SUPER_RES_TARGET_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16_04 "CAN_DET_ND_TARGET_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_04 "CAN_DET_HOST_VEH_CLUTTER_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16_04 "CAN_DET_VALID_LEVEL_16_04"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16_04 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16_04 "CAN_DET_AZIMUTH_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16_04 "CAN_DET_RANGE_16_04"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16_04 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16_04 "CAN_DET_RANGE_RATE_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16_04 "CAN_DET_AMPLITUDE_16_04"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16_04 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16_04 "CAN_SCAN_INDEX_2LSB_16_04"; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_05 "CAN_DET_CONFID_AZIMUTH_16_05"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_05 "CAN_DET_CONFID_AZIMUTH_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_05 "CAN_DET_CONFID_AZIMUTH_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_05 "CAN_DET_SUPER_RES_TARGET_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16_05 "CAN_DET_ND_TARGET_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_05 "CAN_DET_HOST_VEH_CLUTTER_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16_05 "CAN_DET_VALID_LEVEL_16_05"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16_05 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16_05 "CAN_DET_AZIMUTH_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16_05 "CAN_DET_RANGE_16_05"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16_05 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16_05 "CAN_DET_RANGE_RATE_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16_05 "CAN_DET_AMPLITUDE_16_05"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16_05 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16_05 "CAN_SCAN_INDEX_2LSB_16_05"; +BA_ "GenSigVtEn" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_06 "CAN_DET_CONFID_AZIMUTH_16_06"; +BA_ "GenSigVtName" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_06 "CAN_DET_CONFID_AZIMUTH_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_CONFID_AZIMUTH_16_06 "CAN_DET_CONFID_AZIMUTH_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_SUPER_RES_TARGET_16_06 "CAN_DET_SUPER_RES_TARGET_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_ND_TARGET_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_ND_TARGET_16_06 "CAN_DET_ND_TARGET_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_HOST_VEH_CLUTTER_16_06 "CAN_DET_HOST_VEH_CLUTTER_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_VALID_LEVEL_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_VALID_LEVEL_16_06 "CAN_DET_VALID_LEVEL_16_06"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_AZIMUTH_16_06 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AZIMUTH_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AZIMUTH_16_06 "CAN_DET_AZIMUTH_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_16_06 "CAN_DET_RANGE_16_06"; +BA_ "GenSigStartValue" SG_ 303 CAN_DET_RANGE_RATE_16_06 0; +BA_ "GenSigSendType" SG_ 303 CAN_DET_RANGE_RATE_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_RANGE_RATE_16_06 "CAN_DET_RANGE_RATE_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_DET_AMPLITUDE_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_DET_AMPLITUDE_16_06 "CAN_DET_AMPLITUDE_16_06"; +BA_ "GenSigSendType" SG_ 303 CAN_SCAN_INDEX_2LSB_16_06 0; +BA_ "GenSigCmt" SG_ 303 CAN_SCAN_INDEX_2LSB_16_06 "CAN_SCAN_INDEX_2LSB_16_06"; +BA_ "GenMsgSendType" BO_ 302 1; +BA_ "GenMsgILSupport" BO_ 302 1; +BA_ "GenMsgNrOfRepetition" BO_ 302 0; +BA_ "GenMsgCycleTime" BO_ 302 0; +BA_ "NetworkInitialization" BO_ 302 0; +BA_ "GenMsgDelayTime" BO_ 302 0; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_01 "CAN_DET_CONFID_AZIMUTH_15_01"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_01 "CAN_DET_CONFID_AZIMUTH_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_01 "CAN_DET_CONFID_AZIMUTH_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_01 "CAN_DET_SUPER_RES_TARGET_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15_01 "CAN_DET_ND_TARGET_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_01 "CAN_DET_HOST_VEH_CLUTTER_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15_01 "CAN_DET_VALID_LEVEL_15_01"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15_01 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15_01 "CAN_DET_AZIMUTH_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15_01 "CAN_DET_RANGE_15_01"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15_01 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15_01 "CAN_DET_RANGE_RATE_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15_01 "CAN_DET_AMPLITUDE_15_01"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15_01 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15_01 "CAN_SCAN_INDEX_2LSB_15_01"; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_02 "CAN_DET_CONFID_AZIMUTH_15_02"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_02 "CAN_DET_CONFID_AZIMUTH_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_02 "CAN_DET_CONFID_AZIMUTH_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_02 "CAN_DET_SUPER_RES_TARGET_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15_02 "CAN_DET_ND_TARGET_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_02 "CAN_DET_HOST_VEH_CLUTTER_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15_02 "CAN_DET_VALID_LEVEL_15_02"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15_02 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15_02 "CAN_DET_AZIMUTH_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15_02 "CAN_DET_RANGE_15_02"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15_02 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15_02 "CAN_DET_RANGE_RATE_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15_02 "CAN_DET_AMPLITUDE_15_02"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15_02 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15_02 "CAN_SCAN_INDEX_2LSB_15_02"; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_03 "CAN_DET_CONFID_AZIMUTH_15_03"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_03 "CAN_DET_CONFID_AZIMUTH_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_03 "CAN_DET_CONFID_AZIMUTH_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_03 "CAN_DET_SUPER_RES_TARGET_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15_03 "CAN_DET_ND_TARGET_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_03 "CAN_DET_HOST_VEH_CLUTTER_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15_03 "CAN_DET_VALID_LEVEL_15_03"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15_03 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15_03 "CAN_DET_AZIMUTH_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15_03 "CAN_DET_RANGE_15_03"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15_03 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15_03 "CAN_DET_RANGE_RATE_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15_03 "CAN_DET_AMPLITUDE_15_03"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15_03 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15_03 "CAN_SCAN_INDEX_2LSB_15_03"; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_04 "CAN_DET_CONFID_AZIMUTH_15_04"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_04 "CAN_DET_CONFID_AZIMUTH_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_04 "CAN_DET_CONFID_AZIMUTH_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_04 "CAN_DET_SUPER_RES_TARGET_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15_04 "CAN_DET_ND_TARGET_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_04 "CAN_DET_HOST_VEH_CLUTTER_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15_04 "CAN_DET_VALID_LEVEL_15_04"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15_04 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15_04 "CAN_DET_AZIMUTH_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15_04 "CAN_DET_RANGE_15_04"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15_04 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15_04 "CAN_DET_RANGE_RATE_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15_04 "CAN_DET_AMPLITUDE_15_04"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15_04 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15_04 "CAN_SCAN_INDEX_2LSB_15_04"; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_05 "CAN_DET_CONFID_AZIMUTH_15_05"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_05 "CAN_DET_CONFID_AZIMUTH_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_05 "CAN_DET_CONFID_AZIMUTH_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_05 "CAN_DET_SUPER_RES_TARGET_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15_05 "CAN_DET_ND_TARGET_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_05 "CAN_DET_HOST_VEH_CLUTTER_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15_05 "CAN_DET_VALID_LEVEL_15_05"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15_05 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15_05 "CAN_DET_AZIMUTH_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15_05 "CAN_DET_RANGE_15_05"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15_05 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15_05 "CAN_DET_RANGE_RATE_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15_05 "CAN_DET_AMPLITUDE_15_05"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15_05 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15_05 "CAN_SCAN_INDEX_2LSB_15_05"; +BA_ "GenSigVtEn" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_06 "CAN_DET_CONFID_AZIMUTH_15_06"; +BA_ "GenSigVtName" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_06 "CAN_DET_CONFID_AZIMUTH_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_CONFID_AZIMUTH_15_06 "CAN_DET_CONFID_AZIMUTH_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_SUPER_RES_TARGET_15_06 "CAN_DET_SUPER_RES_TARGET_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_ND_TARGET_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_ND_TARGET_15_06 "CAN_DET_ND_TARGET_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_HOST_VEH_CLUTTER_15_06 "CAN_DET_HOST_VEH_CLUTTER_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_VALID_LEVEL_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_VALID_LEVEL_15_06 "CAN_DET_VALID_LEVEL_15_06"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_AZIMUTH_15_06 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AZIMUTH_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AZIMUTH_15_06 "CAN_DET_AZIMUTH_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_15_06 "CAN_DET_RANGE_15_06"; +BA_ "GenSigStartValue" SG_ 302 CAN_DET_RANGE_RATE_15_06 0; +BA_ "GenSigSendType" SG_ 302 CAN_DET_RANGE_RATE_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_RANGE_RATE_15_06 "CAN_DET_RANGE_RATE_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_DET_AMPLITUDE_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_DET_AMPLITUDE_15_06 "CAN_DET_AMPLITUDE_15_06"; +BA_ "GenSigSendType" SG_ 302 CAN_SCAN_INDEX_2LSB_15_06 0; +BA_ "GenSigCmt" SG_ 302 CAN_SCAN_INDEX_2LSB_15_06 "CAN_SCAN_INDEX_2LSB_15_06"; +BA_ "GenMsgSendType" BO_ 301 1; +BA_ "GenMsgILSupport" BO_ 301 1; +BA_ "GenMsgNrOfRepetition" BO_ 301 0; +BA_ "GenMsgCycleTime" BO_ 301 0; +BA_ "NetworkInitialization" BO_ 301 0; +BA_ "GenMsgDelayTime" BO_ 301 0; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_01 "CAN_DET_CONFID_AZIMUTH_14_01"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_01 "CAN_DET_CONFID_AZIMUTH_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_01 "CAN_DET_CONFID_AZIMUTH_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_01 "CAN_DET_SUPER_RES_TARGET_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14_01 "CAN_DET_ND_TARGET_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_01 "CAN_DET_HOST_VEH_CLUTTER_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14_01 "CAN_DET_VALID_LEVEL_14_01"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14_01 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14_01 "CAN_DET_AZIMUTH_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14_01 "CAN_DET_RANGE_14_01"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14_01 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14_01 "CAN_DET_RANGE_RATE_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14_01 "CAN_DET_AMPLITUDE_14_01"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14_01 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14_01 "CAN_SCAN_INDEX_2LSB_14_01"; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_02 "CAN_DET_CONFID_AZIMUTH_14_02"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_02 "CAN_DET_CONFID_AZIMUTH_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_02 "CAN_DET_CONFID_AZIMUTH_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_02 "CAN_DET_SUPER_RES_TARGET_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14_02 "CAN_DET_ND_TARGET_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_02 "CAN_DET_HOST_VEH_CLUTTER_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14_02 "CAN_DET_VALID_LEVEL_14_02"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14_02 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14_02 "CAN_DET_AZIMUTH_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14_02 "CAN_DET_RANGE_14_02"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14_02 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14_02 "CAN_DET_RANGE_RATE_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14_02 "CAN_DET_AMPLITUDE_14_02"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14_02 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14_02 "CAN_SCAN_INDEX_2LSB_14_02"; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_03 "CAN_DET_CONFID_AZIMUTH_14_03"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_03 "CAN_DET_CONFID_AZIMUTH_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_03 "CAN_DET_CONFID_AZIMUTH_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_03 "CAN_DET_SUPER_RES_TARGET_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14_03 "CAN_DET_ND_TARGET_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_03 "CAN_DET_HOST_VEH_CLUTTER_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14_03 "CAN_DET_VALID_LEVEL_14_03"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14_03 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14_03 "CAN_DET_AZIMUTH_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14_03 "CAN_DET_RANGE_14_03"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14_03 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14_03 "CAN_DET_RANGE_RATE_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14_03 "CAN_DET_AMPLITUDE_14_03"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14_03 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14_03 "CAN_SCAN_INDEX_2LSB_14_03"; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_04 "CAN_DET_CONFID_AZIMUTH_14_04"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_04 "CAN_DET_CONFID_AZIMUTH_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_04 "CAN_DET_CONFID_AZIMUTH_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_04 "CAN_DET_SUPER_RES_TARGET_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14_04 "CAN_DET_ND_TARGET_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_04 "CAN_DET_HOST_VEH_CLUTTER_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14_04 "CAN_DET_VALID_LEVEL_14_04"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14_04 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14_04 "CAN_DET_AZIMUTH_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14_04 "CAN_DET_RANGE_14_04"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14_04 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14_04 "CAN_DET_RANGE_RATE_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14_04 "CAN_DET_AMPLITUDE_14_04"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14_04 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14_04 "CAN_SCAN_INDEX_2LSB_14_04"; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_05 "CAN_DET_CONFID_AZIMUTH_14_05"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_05 "CAN_DET_CONFID_AZIMUTH_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_05 "CAN_DET_CONFID_AZIMUTH_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_05 "CAN_DET_SUPER_RES_TARGET_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14_05 "CAN_DET_ND_TARGET_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_05 "CAN_DET_HOST_VEH_CLUTTER_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14_05 "CAN_DET_VALID_LEVEL_14_05"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14_05 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14_05 "CAN_DET_AZIMUTH_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14_05 "CAN_DET_RANGE_14_05"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14_05 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14_05 "CAN_DET_RANGE_RATE_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14_05 "CAN_DET_AMPLITUDE_14_05"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14_05 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14_05 "CAN_SCAN_INDEX_2LSB_14_05"; +BA_ "GenSigVtEn" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_06 "CAN_DET_CONFID_AZIMUTH_14_06"; +BA_ "GenSigVtName" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_06 "CAN_DET_CONFID_AZIMUTH_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_CONFID_AZIMUTH_14_06 "CAN_DET_CONFID_AZIMUTH_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_SUPER_RES_TARGET_14_06 "CAN_DET_SUPER_RES_TARGET_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_ND_TARGET_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_ND_TARGET_14_06 "CAN_DET_ND_TARGET_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_HOST_VEH_CLUTTER_14_06 "CAN_DET_HOST_VEH_CLUTTER_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_VALID_LEVEL_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_VALID_LEVEL_14_06 "CAN_DET_VALID_LEVEL_14_06"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_AZIMUTH_14_06 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AZIMUTH_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AZIMUTH_14_06 "CAN_DET_AZIMUTH_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_14_06 "CAN_DET_RANGE_14_06"; +BA_ "GenSigStartValue" SG_ 301 CAN_DET_RANGE_RATE_14_06 0; +BA_ "GenSigSendType" SG_ 301 CAN_DET_RANGE_RATE_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_RANGE_RATE_14_06 "CAN_DET_RANGE_RATE_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_DET_AMPLITUDE_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_DET_AMPLITUDE_14_06 "CAN_DET_AMPLITUDE_14_06"; +BA_ "GenSigSendType" SG_ 301 CAN_SCAN_INDEX_2LSB_14_06 0; +BA_ "GenSigCmt" SG_ 301 CAN_SCAN_INDEX_2LSB_14_06 "CAN_SCAN_INDEX_2LSB_14_06"; +BA_ "GenMsgSendType" BO_ 300 1; +BA_ "GenMsgILSupport" BO_ 300 1; +BA_ "GenMsgNrOfRepetition" BO_ 300 0; +BA_ "GenMsgCycleTime" BO_ 300 0; +BA_ "NetworkInitialization" BO_ 300 0; +BA_ "GenMsgDelayTime" BO_ 300 0; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_01 "CAN_DET_CONFID_AZIMUTH_13_01"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_01 "CAN_DET_CONFID_AZIMUTH_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_01 "CAN_DET_CONFID_AZIMUTH_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_01 "CAN_DET_SUPER_RES_TARGET_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13_01 "CAN_DET_ND_TARGET_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_01 "CAN_DET_HOST_VEH_CLUTTER_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13_01 "CAN_DET_VALID_LEVEL_13_01"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13_01 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13_01 "CAN_DET_AZIMUTH_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13_01 "CAN_DET_RANGE_13_01"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13_01 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13_01 "CAN_DET_RANGE_RATE_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13_01 "CAN_DET_AMPLITUDE_13_01"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13_01 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13_01 "CAN_SCAN_INDEX_2LSB_13_01"; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_02 "CAN_DET_CONFID_AZIMUTH_13_02"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_02 "CAN_DET_CONFID_AZIMUTH_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_02 "CAN_DET_CONFID_AZIMUTH_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_02 "CAN_DET_SUPER_RES_TARGET_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13_02 "CAN_DET_ND_TARGET_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_02 "CAN_DET_HOST_VEH_CLUTTER_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13_02 "CAN_DET_VALID_LEVEL_13_02"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13_02 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13_02 "CAN_DET_AZIMUTH_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13_02 "CAN_DET_RANGE_13_02"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13_02 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13_02 "CAN_DET_RANGE_RATE_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13_02 "CAN_DET_AMPLITUDE_13_02"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13_02 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13_02 "CAN_SCAN_INDEX_2LSB_13_02"; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_03 "CAN_DET_CONFID_AZIMUTH_13_03"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_03 "CAN_DET_CONFID_AZIMUTH_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_03 "CAN_DET_CONFID_AZIMUTH_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_03 "CAN_DET_SUPER_RES_TARGET_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13_03 "CAN_DET_ND_TARGET_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_03 "CAN_DET_HOST_VEH_CLUTTER_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13_03 "CAN_DET_VALID_LEVEL_13_03"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13_03 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13_03 "CAN_DET_AZIMUTH_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13_03 "CAN_DET_RANGE_13_03"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13_03 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13_03 "CAN_DET_RANGE_RATE_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13_03 "CAN_DET_AMPLITUDE_13_03"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13_03 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13_03 "CAN_SCAN_INDEX_2LSB_13_03"; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_04 "CAN_DET_CONFID_AZIMUTH_13_04"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_04 "CAN_DET_CONFID_AZIMUTH_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_04 "CAN_DET_CONFID_AZIMUTH_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_04 "CAN_DET_SUPER_RES_TARGET_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13_04 "CAN_DET_ND_TARGET_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_04 "CAN_DET_HOST_VEH_CLUTTER_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13_04 "CAN_DET_VALID_LEVEL_13_04"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13_04 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13_04 "CAN_DET_AZIMUTH_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13_04 "CAN_DET_RANGE_13_04"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13_04 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13_04 "CAN_DET_RANGE_RATE_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13_04 "CAN_DET_AMPLITUDE_13_04"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13_04 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13_04 "CAN_SCAN_INDEX_2LSB_13_04"; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_05 "CAN_DET_CONFID_AZIMUTH_13_05"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_05 "CAN_DET_CONFID_AZIMUTH_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_05 "CAN_DET_CONFID_AZIMUTH_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_05 "CAN_DET_SUPER_RES_TARGET_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13_05 "CAN_DET_ND_TARGET_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_05 "CAN_DET_HOST_VEH_CLUTTER_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13_05 "CAN_DET_VALID_LEVEL_13_05"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13_05 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13_05 "CAN_DET_AZIMUTH_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13_05 "CAN_DET_RANGE_13_05"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13_05 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13_05 "CAN_DET_RANGE_RATE_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13_05 "CAN_DET_AMPLITUDE_13_05"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13_05 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13_05 "CAN_SCAN_INDEX_2LSB_13_05"; +BA_ "GenSigVtEn" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_06 "CAN_DET_CONFID_AZIMUTH_13_06"; +BA_ "GenSigVtName" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_06 "CAN_DET_CONFID_AZIMUTH_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_CONFID_AZIMUTH_13_06 "CAN_DET_CONFID_AZIMUTH_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_SUPER_RES_TARGET_13_06 "CAN_DET_SUPER_RES_TARGET_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_ND_TARGET_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_ND_TARGET_13_06 "CAN_DET_ND_TARGET_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_HOST_VEH_CLUTTER_13_06 "CAN_DET_HOST_VEH_CLUTTER_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_VALID_LEVEL_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_VALID_LEVEL_13_06 "CAN_DET_VALID_LEVEL_13_06"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_AZIMUTH_13_06 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AZIMUTH_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AZIMUTH_13_06 "CAN_DET_AZIMUTH_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_13_06 "CAN_DET_RANGE_13_06"; +BA_ "GenSigStartValue" SG_ 300 CAN_DET_RANGE_RATE_13_06 0; +BA_ "GenSigSendType" SG_ 300 CAN_DET_RANGE_RATE_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_RANGE_RATE_13_06 "CAN_DET_RANGE_RATE_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_DET_AMPLITUDE_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_DET_AMPLITUDE_13_06 "CAN_DET_AMPLITUDE_13_06"; +BA_ "GenSigSendType" SG_ 300 CAN_SCAN_INDEX_2LSB_13_06 0; +BA_ "GenSigCmt" SG_ 300 CAN_SCAN_INDEX_2LSB_13_06 "CAN_SCAN_INDEX_2LSB_13_06"; +BA_ "GenMsgSendType" BO_ 299 1; +BA_ "GenMsgILSupport" BO_ 299 1; +BA_ "GenMsgNrOfRepetition" BO_ 299 0; +BA_ "GenMsgCycleTime" BO_ 299 0; +BA_ "NetworkInitialization" BO_ 299 0; +BA_ "GenMsgDelayTime" BO_ 299 0; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_01 "CAN_DET_CONFID_AZIMUTH_12_01"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_01 "CAN_DET_CONFID_AZIMUTH_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_01 "CAN_DET_CONFID_AZIMUTH_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_01 "CAN_DET_SUPER_RES_TARGET_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12_01 "CAN_DET_ND_TARGET_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_01 "CAN_DET_HOST_VEH_CLUTTER_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12_01 "CAN_DET_VALID_LEVEL_12_01"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12_01 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12_01 "CAN_DET_AZIMUTH_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12_01 "CAN_DET_RANGE_12_01"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12_01 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12_01 "CAN_DET_RANGE_RATE_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12_01 "CAN_DET_AMPLITUDE_12_01"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12_01 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12_01 "CAN_SCAN_INDEX_2LSB_12_01"; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_02 "CAN_DET_CONFID_AZIMUTH_12_02"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_02 "CAN_DET_CONFID_AZIMUTH_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_02 "CAN_DET_CONFID_AZIMUTH_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_02 "CAN_DET_SUPER_RES_TARGET_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12_02 "CAN_DET_ND_TARGET_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_02 "CAN_DET_HOST_VEH_CLUTTER_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12_02 "CAN_DET_VALID_LEVEL_12_02"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12_02 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12_02 "CAN_DET_AZIMUTH_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12_02 "CAN_DET_RANGE_12_02"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12_02 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12_02 "CAN_DET_RANGE_RATE_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12_02 "CAN_DET_AMPLITUDE_12_02"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12_02 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12_02 "CAN_SCAN_INDEX_2LSB_12_02"; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_03 "CAN_DET_CONFID_AZIMUTH_12_03"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_03 "CAN_DET_CONFID_AZIMUTH_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_03 "CAN_DET_CONFID_AZIMUTH_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_03 "CAN_DET_SUPER_RES_TARGET_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12_03 "CAN_DET_ND_TARGET_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_03 "CAN_DET_HOST_VEH_CLUTTER_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12_03 "CAN_DET_VALID_LEVEL_12_03"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12_03 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12_03 "CAN_DET_AZIMUTH_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12_03 "CAN_DET_RANGE_12_03"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12_03 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12_03 "CAN_DET_RANGE_RATE_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12_03 "CAN_DET_AMPLITUDE_12_03"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12_03 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12_03 "CAN_SCAN_INDEX_2LSB_12_03"; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_04 "CAN_DET_CONFID_AZIMUTH_12_04"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_04 "CAN_DET_CONFID_AZIMUTH_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_04 "CAN_DET_CONFID_AZIMUTH_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_04 "CAN_DET_SUPER_RES_TARGET_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12_04 "CAN_DET_ND_TARGET_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_04 "CAN_DET_HOST_VEH_CLUTTER_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12_04 "CAN_DET_VALID_LEVEL_12_04"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12_04 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12_04 "CAN_DET_AZIMUTH_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12_04 "CAN_DET_RANGE_12_04"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12_04 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12_04 "CAN_DET_RANGE_RATE_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12_04 "CAN_DET_AMPLITUDE_12_04"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12_04 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12_04 "CAN_SCAN_INDEX_2LSB_12_04"; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_05 "CAN_DET_CONFID_AZIMUTH_12_05"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_05 "CAN_DET_CONFID_AZIMUTH_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_05 "CAN_DET_CONFID_AZIMUTH_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_05 "CAN_DET_SUPER_RES_TARGET_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12_05 "CAN_DET_ND_TARGET_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_05 "CAN_DET_HOST_VEH_CLUTTER_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12_05 "CAN_DET_VALID_LEVEL_12_05"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12_05 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12_05 "CAN_DET_AZIMUTH_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12_05 "CAN_DET_RANGE_12_05"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12_05 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12_05 "CAN_DET_RANGE_RATE_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12_05 "CAN_DET_AMPLITUDE_12_05"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12_05 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12_05 "CAN_SCAN_INDEX_2LSB_12_05"; +BA_ "GenSigVtEn" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_06 "CAN_DET_CONFID_AZIMUTH_12_06"; +BA_ "GenSigVtName" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_06 "CAN_DET_CONFID_AZIMUTH_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_CONFID_AZIMUTH_12_06 "CAN_DET_CONFID_AZIMUTH_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_SUPER_RES_TARGET_12_06 "CAN_DET_SUPER_RES_TARGET_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_ND_TARGET_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_ND_TARGET_12_06 "CAN_DET_ND_TARGET_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_HOST_VEH_CLUTTER_12_06 "CAN_DET_HOST_VEH_CLUTTER_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_VALID_LEVEL_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_VALID_LEVEL_12_06 "CAN_DET_VALID_LEVEL_12_06"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_AZIMUTH_12_06 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AZIMUTH_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AZIMUTH_12_06 "CAN_DET_AZIMUTH_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_12_06 "CAN_DET_RANGE_12_06"; +BA_ "GenSigStartValue" SG_ 299 CAN_DET_RANGE_RATE_12_06 0; +BA_ "GenSigSendType" SG_ 299 CAN_DET_RANGE_RATE_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_RANGE_RATE_12_06 "CAN_DET_RANGE_RATE_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_DET_AMPLITUDE_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_DET_AMPLITUDE_12_06 "CAN_DET_AMPLITUDE_12_06"; +BA_ "GenSigSendType" SG_ 299 CAN_SCAN_INDEX_2LSB_12_06 0; +BA_ "GenSigCmt" SG_ 299 CAN_SCAN_INDEX_2LSB_12_06 "CAN_SCAN_INDEX_2LSB_12_06"; +BA_ "GenMsgSendType" BO_ 298 1; +BA_ "GenMsgILSupport" BO_ 298 1; +BA_ "GenMsgNrOfRepetition" BO_ 298 0; +BA_ "GenMsgCycleTime" BO_ 298 0; +BA_ "NetworkInitialization" BO_ 298 0; +BA_ "GenMsgDelayTime" BO_ 298 0; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_01 "CAN_DET_CONFID_AZIMUTH_11_01"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_01 "CAN_DET_CONFID_AZIMUTH_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_01 "CAN_DET_CONFID_AZIMUTH_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_01 "CAN_DET_SUPER_RES_TARGET_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11_01 "CAN_DET_ND_TARGET_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_01 "CAN_DET_HOST_VEH_CLUTTER_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11_01 "CAN_DET_VALID_LEVEL_11_01"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11_01 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11_01 "CAN_DET_AZIMUTH_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11_01 "CAN_DET_RANGE_11_01"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11_01 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11_01 "CAN_DET_RANGE_RATE_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11_01 "CAN_DET_AMPLITUDE_11_01"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11_01 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11_01 "CAN_SCAN_INDEX_2LSB_11_01"; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_02 "CAN_DET_CONFID_AZIMUTH_11_02"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_02 "CAN_DET_CONFID_AZIMUTH_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_02 "CAN_DET_CONFID_AZIMUTH_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_02 "CAN_DET_SUPER_RES_TARGET_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11_02 "CAN_DET_ND_TARGET_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_02 "CAN_DET_HOST_VEH_CLUTTER_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11_02 "CAN_DET_VALID_LEVEL_11_02"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11_02 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11_02 "CAN_DET_AZIMUTH_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11_02 "CAN_DET_RANGE_11_02"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11_02 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11_02 "CAN_DET_RANGE_RATE_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11_02 "CAN_DET_AMPLITUDE_11_02"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11_02 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11_02 "CAN_SCAN_INDEX_2LSB_11_02"; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_03 "CAN_DET_CONFID_AZIMUTH_11_03"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_03 "CAN_DET_CONFID_AZIMUTH_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_03 "CAN_DET_CONFID_AZIMUTH_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_03 "CAN_DET_SUPER_RES_TARGET_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11_03 "CAN_DET_ND_TARGET_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_03 "CAN_DET_HOST_VEH_CLUTTER_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11_03 "CAN_DET_VALID_LEVEL_11_03"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11_03 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11_03 "CAN_DET_AZIMUTH_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11_03 "CAN_DET_RANGE_11_03"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11_03 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11_03 "CAN_DET_RANGE_RATE_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11_03 "CAN_DET_AMPLITUDE_11_03"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11_03 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11_03 "CAN_SCAN_INDEX_2LSB_11_03"; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_04 "CAN_DET_CONFID_AZIMUTH_11_04"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_04 "CAN_DET_CONFID_AZIMUTH_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_04 "CAN_DET_CONFID_AZIMUTH_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_04 "CAN_DET_SUPER_RES_TARGET_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11_04 "CAN_DET_ND_TARGET_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_04 "CAN_DET_HOST_VEH_CLUTTER_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11_04 "CAN_DET_VALID_LEVEL_11_04"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11_04 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11_04 "CAN_DET_AZIMUTH_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11_04 "CAN_DET_RANGE_11_04"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11_04 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11_04 "CAN_DET_RANGE_RATE_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11_04 "CAN_DET_AMPLITUDE_11_04"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11_04 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11_04 "CAN_SCAN_INDEX_2LSB_11_04"; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_05 "CAN_DET_CONFID_AZIMUTH_11_05"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_05 "CAN_DET_CONFID_AZIMUTH_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_05 "CAN_DET_CONFID_AZIMUTH_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_05 "CAN_DET_SUPER_RES_TARGET_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11_05 "CAN_DET_ND_TARGET_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_05 "CAN_DET_HOST_VEH_CLUTTER_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11_05 "CAN_DET_VALID_LEVEL_11_05"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11_05 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11_05 "CAN_DET_AZIMUTH_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11_05 "CAN_DET_RANGE_11_05"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11_05 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11_05 "CAN_DET_RANGE_RATE_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11_05 "CAN_DET_AMPLITUDE_11_05"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11_05 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11_05 "CAN_SCAN_INDEX_2LSB_11_05"; +BA_ "GenSigVtEn" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_06 "CAN_DET_CONFID_AZIMUTH_11_06"; +BA_ "GenSigVtName" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_06 "CAN_DET_CONFID_AZIMUTH_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_CONFID_AZIMUTH_11_06 "CAN_DET_CONFID_AZIMUTH_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_SUPER_RES_TARGET_11_06 "CAN_DET_SUPER_RES_TARGET_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_ND_TARGET_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_ND_TARGET_11_06 "CAN_DET_ND_TARGET_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_HOST_VEH_CLUTTER_11_06 "CAN_DET_HOST_VEH_CLUTTER_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_VALID_LEVEL_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_VALID_LEVEL_11_06 "CAN_DET_VALID_LEVEL_11_06"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_AZIMUTH_11_06 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AZIMUTH_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AZIMUTH_11_06 "CAN_DET_AZIMUTH_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_11_06 "CAN_DET_RANGE_11_06"; +BA_ "GenSigStartValue" SG_ 298 CAN_DET_RANGE_RATE_11_06 0; +BA_ "GenSigSendType" SG_ 298 CAN_DET_RANGE_RATE_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_RANGE_RATE_11_06 "CAN_DET_RANGE_RATE_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_DET_AMPLITUDE_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_DET_AMPLITUDE_11_06 "CAN_DET_AMPLITUDE_11_06"; +BA_ "GenSigSendType" SG_ 298 CAN_SCAN_INDEX_2LSB_11_06 0; +BA_ "GenSigCmt" SG_ 298 CAN_SCAN_INDEX_2LSB_11_06 "CAN_SCAN_INDEX_2LSB_11_06"; +BA_ "GenMsgSendType" BO_ 297 1; +BA_ "GenMsgILSupport" BO_ 297 1; +BA_ "GenMsgNrOfRepetition" BO_ 297 0; +BA_ "GenMsgCycleTime" BO_ 297 0; +BA_ "NetworkInitialization" BO_ 297 0; +BA_ "GenMsgDelayTime" BO_ 297 0; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_01 "CAN_DET_CONFID_AZIMUTH_10_01"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_01 "CAN_DET_CONFID_AZIMUTH_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_01 "CAN_DET_CONFID_AZIMUTH_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_01 "CAN_DET_SUPER_RES_TARGET_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10_01 "CAN_DET_ND_TARGET_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_01 "CAN_DET_HOST_VEH_CLUTTER_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10_01 "CAN_DET_VALID_LEVEL_10_01"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10_01 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10_01 "CAN_DET_AZIMUTH_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10_01 "CAN_DET_RANGE_10_01"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10_01 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10_01 "CAN_DET_RANGE_RATE_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10_01 "CAN_DET_AMPLITUDE_10_01"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10_01 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10_01 "CAN_SCAN_INDEX_2LSB_10_01"; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_02 "CAN_DET_CONFID_AZIMUTH_10_02"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_02 "CAN_DET_CONFID_AZIMUTH_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_02 "CAN_DET_CONFID_AZIMUTH_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_02 "CAN_DET_SUPER_RES_TARGET_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10_02 "CAN_DET_ND_TARGET_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_02 "CAN_DET_HOST_VEH_CLUTTER_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10_02 "CAN_DET_VALID_LEVEL_10_02"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10_02 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10_02 "CAN_DET_AZIMUTH_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10_02 "CAN_DET_RANGE_10_02"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10_02 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10_02 "CAN_DET_RANGE_RATE_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10_02 "CAN_DET_AMPLITUDE_10_02"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10_02 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10_02 "CAN_SCAN_INDEX_2LSB_10_02"; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_03 "CAN_DET_CONFID_AZIMUTH_10_03"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_03 "CAN_DET_CONFID_AZIMUTH_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_03 "CAN_DET_CONFID_AZIMUTH_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_03 "CAN_DET_SUPER_RES_TARGET_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10_03 "CAN_DET_ND_TARGET_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_03 "CAN_DET_HOST_VEH_CLUTTER_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10_03 "CAN_DET_VALID_LEVEL_10_03"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10_03 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10_03 "CAN_DET_AZIMUTH_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10_03 "CAN_DET_RANGE_10_03"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10_03 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10_03 "CAN_DET_RANGE_RATE_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10_03 "CAN_DET_AMPLITUDE_10_03"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10_03 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10_03 "CAN_SCAN_INDEX_2LSB_10_03"; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_04 "CAN_DET_CONFID_AZIMUTH_10_04"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_04 "CAN_DET_CONFID_AZIMUTH_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_04 "CAN_DET_CONFID_AZIMUTH_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_04 "CAN_DET_SUPER_RES_TARGET_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10_04 "CAN_DET_ND_TARGET_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_04 "CAN_DET_HOST_VEH_CLUTTER_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10_04 "CAN_DET_VALID_LEVEL_10_04"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10_04 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10_04 "CAN_DET_AZIMUTH_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10_04 "CAN_DET_RANGE_10_04"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10_04 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10_04 "CAN_DET_RANGE_RATE_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10_04 "CAN_DET_AMPLITUDE_10_04"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10_04 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10_04 "CAN_SCAN_INDEX_2LSB_10_04"; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_05 "CAN_DET_CONFID_AZIMUTH_10_05"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_05 "CAN_DET_CONFID_AZIMUTH_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_05 "CAN_DET_CONFID_AZIMUTH_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_05 "CAN_DET_SUPER_RES_TARGET_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10_05 "CAN_DET_ND_TARGET_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_05 "CAN_DET_HOST_VEH_CLUTTER_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10_05 "CAN_DET_VALID_LEVEL_10_05"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10_05 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10_05 "CAN_DET_AZIMUTH_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10_05 "CAN_DET_RANGE_10_05"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10_05 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10_05 "CAN_DET_RANGE_RATE_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10_05 "CAN_DET_AMPLITUDE_10_05"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10_05 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10_05 "CAN_SCAN_INDEX_2LSB_10_05"; +BA_ "GenSigVtEn" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_06 "CAN_DET_CONFID_AZIMUTH_10_06"; +BA_ "GenSigVtName" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_06 "CAN_DET_CONFID_AZIMUTH_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_CONFID_AZIMUTH_10_06 "CAN_DET_CONFID_AZIMUTH_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_SUPER_RES_TARGET_10_06 "CAN_DET_SUPER_RES_TARGET_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_ND_TARGET_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_ND_TARGET_10_06 "CAN_DET_ND_TARGET_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_HOST_VEH_CLUTTER_10_06 "CAN_DET_HOST_VEH_CLUTTER_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_VALID_LEVEL_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_VALID_LEVEL_10_06 "CAN_DET_VALID_LEVEL_10_06"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_AZIMUTH_10_06 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AZIMUTH_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AZIMUTH_10_06 "CAN_DET_AZIMUTH_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_10_06 "CAN_DET_RANGE_10_06"; +BA_ "GenSigStartValue" SG_ 297 CAN_DET_RANGE_RATE_10_06 0; +BA_ "GenSigSendType" SG_ 297 CAN_DET_RANGE_RATE_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_RANGE_RATE_10_06 "CAN_DET_RANGE_RATE_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_DET_AMPLITUDE_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_DET_AMPLITUDE_10_06 "CAN_DET_AMPLITUDE_10_06"; +BA_ "GenSigSendType" SG_ 297 CAN_SCAN_INDEX_2LSB_10_06 0; +BA_ "GenSigCmt" SG_ 297 CAN_SCAN_INDEX_2LSB_10_06 "CAN_SCAN_INDEX_2LSB_10_06"; +BA_ "GenMsgSendType" BO_ 296 1; +BA_ "GenMsgILSupport" BO_ 296 1; +BA_ "GenMsgNrOfRepetition" BO_ 296 0; +BA_ "GenMsgCycleTime" BO_ 296 0; +BA_ "NetworkInitialization" BO_ 296 0; +BA_ "GenMsgDelayTime" BO_ 296 0; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_01 "CAN_DET_CONFID_AZIMUTH_09_01"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_01 "CAN_DET_CONFID_AZIMUTH_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_01 "CAN_DET_CONFID_AZIMUTH_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_01 "CAN_DET_SUPER_RES_TARGET_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09_01 "CAN_DET_ND_TARGET_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_01 "CAN_DET_HOST_VEH_CLUTTER_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09_01 "CAN_DET_VALID_LEVEL_09_01"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09_01 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09_01 "CAN_DET_AZIMUTH_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09_01 "CAN_DET_RANGE_09_01"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09_01 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09_01 "CAN_DET_RANGE_RATE_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09_01 "CAN_DET_AMPLITUDE_09_01"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09_01 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09_01 "CAN_SCAN_INDEX_2LSB_09_01"; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_02 "CAN_DET_CONFID_AZIMUTH_09_02"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_02 "CAN_DET_CONFID_AZIMUTH_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_02 "CAN_DET_CONFID_AZIMUTH_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_02 "CAN_DET_SUPER_RES_TARGET_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09_02 "CAN_DET_ND_TARGET_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_02 "CAN_DET_HOST_VEH_CLUTTER_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09_02 "CAN_DET_VALID_LEVEL_09_02"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09_02 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09_02 "CAN_DET_AZIMUTH_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09_02 "CAN_DET_RANGE_09_02"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09_02 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09_02 "CAN_DET_RANGE_RATE_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09_02 "CAN_DET_AMPLITUDE_09_02"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09_02 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09_02 "CAN_SCAN_INDEX_2LSB_09_02"; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_03 "CAN_DET_CONFID_AZIMUTH_09_03"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_03 "CAN_DET_CONFID_AZIMUTH_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_03 "CAN_DET_CONFID_AZIMUTH_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_03 "CAN_DET_SUPER_RES_TARGET_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09_03 "CAN_DET_ND_TARGET_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_03 "CAN_DET_HOST_VEH_CLUTTER_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09_03 "CAN_DET_VALID_LEVEL_09_03"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09_03 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09_03 "CAN_DET_AZIMUTH_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09_03 "CAN_DET_RANGE_09_03"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09_03 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09_03 "CAN_DET_RANGE_RATE_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09_03 "CAN_DET_AMPLITUDE_09_03"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09_03 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09_03 "CAN_SCAN_INDEX_2LSB_09_03"; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_04 "CAN_DET_CONFID_AZIMUTH_09_04"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_04 "CAN_DET_CONFID_AZIMUTH_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_04 "CAN_DET_CONFID_AZIMUTH_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_04 "CAN_DET_SUPER_RES_TARGET_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09_04 "CAN_DET_ND_TARGET_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_04 "CAN_DET_HOST_VEH_CLUTTER_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09_04 "CAN_DET_VALID_LEVEL_09_04"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09_04 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09_04 "CAN_DET_AZIMUTH_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09_04 "CAN_DET_RANGE_09_04"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09_04 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09_04 "CAN_DET_RANGE_RATE_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09_04 "CAN_DET_AMPLITUDE_09_04"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09_04 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09_04 "CAN_SCAN_INDEX_2LSB_09_04"; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_05 "CAN_DET_CONFID_AZIMUTH_09_05"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_05 "CAN_DET_CONFID_AZIMUTH_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_05 "CAN_DET_CONFID_AZIMUTH_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_05 "CAN_DET_SUPER_RES_TARGET_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09_05 "CAN_DET_ND_TARGET_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_05 "CAN_DET_HOST_VEH_CLUTTER_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09_05 "CAN_DET_VALID_LEVEL_09_05"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09_05 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09_05 "CAN_DET_AZIMUTH_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09_05 "CAN_DET_RANGE_09_05"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09_05 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09_05 "CAN_DET_RANGE_RATE_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09_05 "CAN_DET_AMPLITUDE_09_05"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09_05 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09_05 "CAN_SCAN_INDEX_2LSB_09_05"; +BA_ "GenSigVtEn" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_06 "CAN_DET_CONFID_AZIMUTH_09_06"; +BA_ "GenSigVtName" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_06 "CAN_DET_CONFID_AZIMUTH_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_CONFID_AZIMUTH_09_06 "CAN_DET_CONFID_AZIMUTH_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_SUPER_RES_TARGET_09_06 "CAN_DET_SUPER_RES_TARGET_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_ND_TARGET_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_ND_TARGET_09_06 "CAN_DET_ND_TARGET_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_HOST_VEH_CLUTTER_09_06 "CAN_DET_HOST_VEH_CLUTTER_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_VALID_LEVEL_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_VALID_LEVEL_09_06 "CAN_DET_VALID_LEVEL_09_06"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_AZIMUTH_09_06 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AZIMUTH_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AZIMUTH_09_06 "CAN_DET_AZIMUTH_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_09_06 "CAN_DET_RANGE_09_06"; +BA_ "GenSigStartValue" SG_ 296 CAN_DET_RANGE_RATE_09_06 0; +BA_ "GenSigSendType" SG_ 296 CAN_DET_RANGE_RATE_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_RANGE_RATE_09_06 "CAN_DET_RANGE_RATE_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_DET_AMPLITUDE_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_DET_AMPLITUDE_09_06 "CAN_DET_AMPLITUDE_09_06"; +BA_ "GenSigSendType" SG_ 296 CAN_SCAN_INDEX_2LSB_09_06 0; +BA_ "GenSigCmt" SG_ 296 CAN_SCAN_INDEX_2LSB_09_06 "CAN_SCAN_INDEX_2LSB_09_06"; +BA_ "GenMsgSendType" BO_ 295 1; +BA_ "GenMsgILSupport" BO_ 295 1; +BA_ "GenMsgNrOfRepetition" BO_ 295 0; +BA_ "GenMsgCycleTime" BO_ 295 0; +BA_ "NetworkInitialization" BO_ 295 0; +BA_ "GenMsgDelayTime" BO_ 295 0; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_01 "CAN_DET_CONFID_AZIMUTH_08_01"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_01 "CAN_DET_CONFID_AZIMUTH_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_01 "CAN_DET_CONFID_AZIMUTH_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_01 "CAN_DET_SUPER_RES_TARGET_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08_01 "CAN_DET_ND_TARGET_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_01 "CAN_DET_HOST_VEH_CLUTTER_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08_01 "CAN_DET_VALID_LEVEL_08_01"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08_01 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08_01 "CAN_DET_AZIMUTH_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08_01 "CAN_DET_RANGE_08_01"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08_01 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08_01 "CAN_DET_RANGE_RATE_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08_01 "CAN_DET_AMPLITUDE_08_01"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08_01 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08_01 "CAN_SCAN_INDEX_2LSB_08_01"; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_02 "CAN_DET_CONFID_AZIMUTH_08_02"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_02 "CAN_DET_CONFID_AZIMUTH_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_02 "CAN_DET_CONFID_AZIMUTH_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_02 "CAN_DET_SUPER_RES_TARGET_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08_02 "CAN_DET_ND_TARGET_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_02 "CAN_DET_HOST_VEH_CLUTTER_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08_02 "CAN_DET_VALID_LEVEL_08_02"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08_02 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08_02 "CAN_DET_AZIMUTH_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08_02 "CAN_DET_RANGE_08_02"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08_02 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08_02 "CAN_DET_RANGE_RATE_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08_02 "CAN_DET_AMPLITUDE_08_02"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08_02 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08_02 "CAN_SCAN_INDEX_2LSB_08_02"; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_03 "CAN_DET_CONFID_AZIMUTH_08_03"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_03 "CAN_DET_CONFID_AZIMUTH_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_03 "CAN_DET_CONFID_AZIMUTH_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_03 "CAN_DET_SUPER_RES_TARGET_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08_03 "CAN_DET_ND_TARGET_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_03 "CAN_DET_HOST_VEH_CLUTTER_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08_03 "CAN_DET_VALID_LEVEL_08_03"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08_03 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08_03 "CAN_DET_AZIMUTH_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08_03 "CAN_DET_RANGE_08_03"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08_03 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08_03 "CAN_DET_RANGE_RATE_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08_03 "CAN_DET_AMPLITUDE_08_03"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08_03 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08_03 "CAN_SCAN_INDEX_2LSB_08_03"; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_04 "CAN_DET_CONFID_AZIMUTH_08_04"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_04 "CAN_DET_CONFID_AZIMUTH_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_04 "CAN_DET_CONFID_AZIMUTH_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_04 "CAN_DET_SUPER_RES_TARGET_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08_04 "CAN_DET_ND_TARGET_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_04 "CAN_DET_HOST_VEH_CLUTTER_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08_04 "CAN_DET_VALID_LEVEL_08_04"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08_04 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08_04 "CAN_DET_AZIMUTH_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08_04 "CAN_DET_RANGE_08_04"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08_04 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08_04 "CAN_DET_RANGE_RATE_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08_04 "CAN_DET_AMPLITUDE_08_04"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08_04 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08_04 "CAN_SCAN_INDEX_2LSB_08_04"; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_05 "CAN_DET_CONFID_AZIMUTH_08_05"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_05 "CAN_DET_CONFID_AZIMUTH_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_05 "CAN_DET_CONFID_AZIMUTH_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_05 "CAN_DET_SUPER_RES_TARGET_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08_05 "CAN_DET_ND_TARGET_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_05 "CAN_DET_HOST_VEH_CLUTTER_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08_05 "CAN_DET_VALID_LEVEL_08_05"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08_05 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08_05 "CAN_DET_AZIMUTH_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08_05 "CAN_DET_RANGE_08_05"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08_05 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08_05 "CAN_DET_RANGE_RATE_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08_05 "CAN_DET_AMPLITUDE_08_05"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08_05 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08_05 "CAN_SCAN_INDEX_2LSB_08_05"; +BA_ "GenSigVtEn" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_06 "CAN_DET_CONFID_AZIMUTH_08_06"; +BA_ "GenSigVtName" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_06 "CAN_DET_CONFID_AZIMUTH_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_CONFID_AZIMUTH_08_06 "CAN_DET_CONFID_AZIMUTH_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_SUPER_RES_TARGET_08_06 "CAN_DET_SUPER_RES_TARGET_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_ND_TARGET_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_ND_TARGET_08_06 "CAN_DET_ND_TARGET_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_HOST_VEH_CLUTTER_08_06 "CAN_DET_HOST_VEH_CLUTTER_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_VALID_LEVEL_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_VALID_LEVEL_08_06 "CAN_DET_VALID_LEVEL_08_06"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_AZIMUTH_08_06 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AZIMUTH_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AZIMUTH_08_06 "CAN_DET_AZIMUTH_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_08_06 "CAN_DET_RANGE_08_06"; +BA_ "GenSigStartValue" SG_ 295 CAN_DET_RANGE_RATE_08_06 0; +BA_ "GenSigSendType" SG_ 295 CAN_DET_RANGE_RATE_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_RANGE_RATE_08_06 "CAN_DET_RANGE_RATE_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_DET_AMPLITUDE_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_DET_AMPLITUDE_08_06 "CAN_DET_AMPLITUDE_08_06"; +BA_ "GenSigSendType" SG_ 295 CAN_SCAN_INDEX_2LSB_08_06 0; +BA_ "GenSigCmt" SG_ 295 CAN_SCAN_INDEX_2LSB_08_06 "CAN_SCAN_INDEX_2LSB_08_06"; +BA_ "GenMsgSendType" BO_ 294 1; +BA_ "GenMsgILSupport" BO_ 294 1; +BA_ "GenMsgNrOfRepetition" BO_ 294 0; +BA_ "GenMsgCycleTime" BO_ 294 0; +BA_ "NetworkInitialization" BO_ 294 0; +BA_ "GenMsgDelayTime" BO_ 294 0; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_01 "CAN_DET_CONFID_AZIMUTH_07_01"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_01 "CAN_DET_CONFID_AZIMUTH_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_01 "CAN_DET_CONFID_AZIMUTH_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_01 "CAN_DET_SUPER_RES_TARGET_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07_01 "CAN_DET_ND_TARGET_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_01 "CAN_DET_HOST_VEH_CLUTTER_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07_01 "CAN_DET_VALID_LEVEL_07_01"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07_01 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07_01 "CAN_DET_AZIMUTH_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07_01 "CAN_DET_RANGE_07_01"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07_01 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07_01 "CAN_DET_RANGE_RATE_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07_01 "CAN_DET_AMPLITUDE_07_01"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07_01 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07_01 "CAN_SCAN_INDEX_2LSB_07_01"; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_02 "CAN_DET_CONFID_AZIMUTH_07_02"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_02 "CAN_DET_CONFID_AZIMUTH_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_02 "CAN_DET_CONFID_AZIMUTH_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_02 "CAN_DET_SUPER_RES_TARGET_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07_02 "CAN_DET_ND_TARGET_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_02 "CAN_DET_HOST_VEH_CLUTTER_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07_02 "CAN_DET_VALID_LEVEL_07_02"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07_02 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07_02 "CAN_DET_AZIMUTH_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07_02 "CAN_DET_RANGE_07_02"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07_02 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07_02 "CAN_DET_RANGE_RATE_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07_02 "CAN_DET_AMPLITUDE_07_02"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07_02 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07_02 "CAN_SCAN_INDEX_2LSB_07_02"; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_03 "CAN_DET_CONFID_AZIMUTH_07_03"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_03 "CAN_DET_CONFID_AZIMUTH_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_03 "CAN_DET_CONFID_AZIMUTH_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_03 "CAN_DET_SUPER_RES_TARGET_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07_03 "CAN_DET_ND_TARGET_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_03 "CAN_DET_HOST_VEH_CLUTTER_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07_03 "CAN_DET_VALID_LEVEL_07_03"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07_03 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07_03 "CAN_DET_AZIMUTH_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07_03 "CAN_DET_RANGE_07_03"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07_03 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07_03 "CAN_DET_RANGE_RATE_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07_03 "CAN_DET_AMPLITUDE_07_03"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07_03 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07_03 "CAN_SCAN_INDEX_2LSB_07_03"; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_04 "CAN_DET_CONFID_AZIMUTH_07_04"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_04 "CAN_DET_CONFID_AZIMUTH_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_04 "CAN_DET_CONFID_AZIMUTH_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_04 "CAN_DET_SUPER_RES_TARGET_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07_04 "CAN_DET_ND_TARGET_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_04 "CAN_DET_HOST_VEH_CLUTTER_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07_04 "CAN_DET_VALID_LEVEL_07_04"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07_04 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07_04 "CAN_DET_AZIMUTH_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07_04 "CAN_DET_RANGE_07_04"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07_04 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07_04 "CAN_DET_RANGE_RATE_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07_04 "CAN_DET_AMPLITUDE_07_04"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07_04 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07_04 "CAN_SCAN_INDEX_2LSB_07_04"; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_05 "CAN_DET_CONFID_AZIMUTH_07_05"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_05 "CAN_DET_CONFID_AZIMUTH_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_05 "CAN_DET_CONFID_AZIMUTH_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_05 "CAN_DET_SUPER_RES_TARGET_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07_05 "CAN_DET_ND_TARGET_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_05 "CAN_DET_HOST_VEH_CLUTTER_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07_05 "CAN_DET_VALID_LEVEL_07_05"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07_05 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07_05 "CAN_DET_AZIMUTH_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07_05 "CAN_DET_RANGE_07_05"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07_05 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07_05 "CAN_DET_RANGE_RATE_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07_05 "CAN_DET_AMPLITUDE_07_05"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07_05 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07_05 "CAN_SCAN_INDEX_2LSB_07_05"; +BA_ "GenSigVtEn" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_06 "CAN_DET_CONFID_AZIMUTH_07_06"; +BA_ "GenSigVtName" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_06 "CAN_DET_CONFID_AZIMUTH_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_CONFID_AZIMUTH_07_06 "CAN_DET_CONFID_AZIMUTH_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_SUPER_RES_TARGET_07_06 "CAN_DET_SUPER_RES_TARGET_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_ND_TARGET_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_ND_TARGET_07_06 "CAN_DET_ND_TARGET_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_HOST_VEH_CLUTTER_07_06 "CAN_DET_HOST_VEH_CLUTTER_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_VALID_LEVEL_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_VALID_LEVEL_07_06 "CAN_DET_VALID_LEVEL_07_06"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_AZIMUTH_07_06 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AZIMUTH_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AZIMUTH_07_06 "CAN_DET_AZIMUTH_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_07_06 "CAN_DET_RANGE_07_06"; +BA_ "GenSigStartValue" SG_ 294 CAN_DET_RANGE_RATE_07_06 0; +BA_ "GenSigSendType" SG_ 294 CAN_DET_RANGE_RATE_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_RANGE_RATE_07_06 "CAN_DET_RANGE_RATE_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_DET_AMPLITUDE_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_DET_AMPLITUDE_07_06 "CAN_DET_AMPLITUDE_07_06"; +BA_ "GenSigSendType" SG_ 294 CAN_SCAN_INDEX_2LSB_07_06 0; +BA_ "GenSigCmt" SG_ 294 CAN_SCAN_INDEX_2LSB_07_06 "CAN_SCAN_INDEX_2LSB_07_06"; +BA_ "GenMsgSendType" BO_ 293 1; +BA_ "GenMsgILSupport" BO_ 293 1; +BA_ "GenMsgNrOfRepetition" BO_ 293 0; +BA_ "GenMsgCycleTime" BO_ 293 0; +BA_ "NetworkInitialization" BO_ 293 0; +BA_ "GenMsgDelayTime" BO_ 293 0; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_01 "CAN_DET_CONFID_AZIMUTH_06_01"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_01 "CAN_DET_CONFID_AZIMUTH_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_01 "CAN_DET_CONFID_AZIMUTH_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_01 "CAN_DET_SUPER_RES_TARGET_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06_01 "CAN_DET_ND_TARGET_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_01 "CAN_DET_HOST_VEH_CLUTTER_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06_01 "CAN_DET_VALID_LEVEL_06_01"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06_01 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06_01 "CAN_DET_AZIMUTH_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06_01 "CAN_DET_RANGE_06_01"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06_01 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06_01 "CAN_DET_RANGE_RATE_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06_01 "CAN_DET_AMPLITUDE_06_01"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06_01 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06_01 "CAN_SCAN_INDEX_2LSB_06_01"; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_02 "CAN_DET_CONFID_AZIMUTH_06_02"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_02 "CAN_DET_CONFID_AZIMUTH_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_02 "CAN_DET_CONFID_AZIMUTH_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_02 "CAN_DET_SUPER_RES_TARGET_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06_02 "CAN_DET_ND_TARGET_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_02 "CAN_DET_HOST_VEH_CLUTTER_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06_02 "CAN_DET_VALID_LEVEL_06_02"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06_02 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06_02 "CAN_DET_AZIMUTH_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06_02 "CAN_DET_RANGE_06_02"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06_02 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06_02 "CAN_DET_RANGE_RATE_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06_02 "CAN_DET_AMPLITUDE_06_02"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06_02 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06_02 "CAN_SCAN_INDEX_2LSB_06_02"; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_03 "CAN_DET_CONFID_AZIMUTH_06_03"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_03 "CAN_DET_CONFID_AZIMUTH_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_03 "CAN_DET_CONFID_AZIMUTH_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_03 "CAN_DET_SUPER_RES_TARGET_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06_03 "CAN_DET_ND_TARGET_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_03 "CAN_DET_HOST_VEH_CLUTTER_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06_03 "CAN_DET_VALID_LEVEL_06_03"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06_03 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06_03 "CAN_DET_AZIMUTH_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06_03 "CAN_DET_RANGE_06_03"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06_03 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06_03 "CAN_DET_RANGE_RATE_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06_03 "CAN_DET_AMPLITUDE_06_03"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06_03 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06_03 "CAN_SCAN_INDEX_2LSB_06_03"; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_04 "CAN_DET_CONFID_AZIMUTH_06_04"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_04 "CAN_DET_CONFID_AZIMUTH_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_04 "CAN_DET_CONFID_AZIMUTH_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_04 "CAN_DET_SUPER_RES_TARGET_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06_04 "CAN_DET_ND_TARGET_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_04 "CAN_DET_HOST_VEH_CLUTTER_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06_04 "CAN_DET_VALID_LEVEL_06_04"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06_04 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06_04 "CAN_DET_AZIMUTH_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06_04 "CAN_DET_RANGE_06_04"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06_04 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06_04 "CAN_DET_RANGE_RATE_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06_04 "CAN_DET_AMPLITUDE_06_04"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06_04 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06_04 "CAN_SCAN_INDEX_2LSB_06_04"; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_05 "CAN_DET_CONFID_AZIMUTH_06_05"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_05 "CAN_DET_CONFID_AZIMUTH_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_05 "CAN_DET_CONFID_AZIMUTH_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_05 "CAN_DET_SUPER_RES_TARGET_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06_05 "CAN_DET_ND_TARGET_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_05 "CAN_DET_HOST_VEH_CLUTTER_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06_05 "CAN_DET_VALID_LEVEL_06_05"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06_05 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06_05 "CAN_DET_AZIMUTH_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06_05 "CAN_DET_RANGE_06_05"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06_05 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06_05 "CAN_DET_RANGE_RATE_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06_05 "CAN_DET_AMPLITUDE_06_05"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06_05 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06_05 "CAN_SCAN_INDEX_2LSB_06_05"; +BA_ "GenSigVtEn" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_06 "CAN_DET_CONFID_AZIMUTH_06_06"; +BA_ "GenSigVtName" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_06 "CAN_DET_CONFID_AZIMUTH_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_CONFID_AZIMUTH_06_06 "CAN_DET_CONFID_AZIMUTH_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_SUPER_RES_TARGET_06_06 "CAN_DET_SUPER_RES_TARGET_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_ND_TARGET_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_ND_TARGET_06_06 "CAN_DET_ND_TARGET_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_HOST_VEH_CLUTTER_06_06 "CAN_DET_HOST_VEH_CLUTTER_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_VALID_LEVEL_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_VALID_LEVEL_06_06 "CAN_DET_VALID_LEVEL_06_06"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_AZIMUTH_06_06 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AZIMUTH_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AZIMUTH_06_06 "CAN_DET_AZIMUTH_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_06_06 "CAN_DET_RANGE_06_06"; +BA_ "GenSigStartValue" SG_ 293 CAN_DET_RANGE_RATE_06_06 0; +BA_ "GenSigSendType" SG_ 293 CAN_DET_RANGE_RATE_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_RANGE_RATE_06_06 "CAN_DET_RANGE_RATE_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_DET_AMPLITUDE_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_DET_AMPLITUDE_06_06 "CAN_DET_AMPLITUDE_06_06"; +BA_ "GenSigSendType" SG_ 293 CAN_SCAN_INDEX_2LSB_06_06 0; +BA_ "GenSigCmt" SG_ 293 CAN_SCAN_INDEX_2LSB_06_06 "CAN_SCAN_INDEX_2LSB_06_06"; +BA_ "GenMsgSendType" BO_ 292 1; +BA_ "GenMsgILSupport" BO_ 292 1; +BA_ "GenMsgNrOfRepetition" BO_ 292 0; +BA_ "GenMsgCycleTime" BO_ 292 0; +BA_ "NetworkInitialization" BO_ 292 0; +BA_ "GenMsgDelayTime" BO_ 292 0; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_01 "CAN_DET_CONFID_AZIMUTH_05_01"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_01 "CAN_DET_CONFID_AZIMUTH_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_01 "CAN_DET_CONFID_AZIMUTH_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_01 "CAN_DET_SUPER_RES_TARGET_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05_01 "CAN_DET_ND_TARGET_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_01 "CAN_DET_HOST_VEH_CLUTTER_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05_01 "CAN_DET_VALID_LEVEL_05_01"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05_01 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05_01 "CAN_DET_AZIMUTH_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05_01 "CAN_DET_RANGE_05_01"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05_01 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05_01 "CAN_DET_RANGE_RATE_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05_01 "CAN_DET_AMPLITUDE_05_01"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05_01 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05_01 "CAN_SCAN_INDEX_2LSB_05_01"; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_02 "CAN_DET_CONFID_AZIMUTH_05_02"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_02 "CAN_DET_CONFID_AZIMUTH_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_02 "CAN_DET_CONFID_AZIMUTH_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_02 "CAN_DET_SUPER_RES_TARGET_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05_02 "CAN_DET_ND_TARGET_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_02 "CAN_DET_HOST_VEH_CLUTTER_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05_02 "CAN_DET_VALID_LEVEL_05_02"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05_02 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05_02 "CAN_DET_AZIMUTH_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05_02 "CAN_DET_RANGE_05_02"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05_02 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05_02 "CAN_DET_RANGE_RATE_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05_02 "CAN_DET_AMPLITUDE_05_02"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05_02 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05_02 "CAN_SCAN_INDEX_2LSB_05_02"; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_03 "CAN_DET_CONFID_AZIMUTH_05_03"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_03 "CAN_DET_CONFID_AZIMUTH_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_03 "CAN_DET_CONFID_AZIMUTH_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_03 "CAN_DET_SUPER_RES_TARGET_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05_03 "CAN_DET_ND_TARGET_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_03 "CAN_DET_HOST_VEH_CLUTTER_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05_03 "CAN_DET_VALID_LEVEL_05_03"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05_03 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05_03 "CAN_DET_AZIMUTH_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05_03 "CAN_DET_RANGE_05_03"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05_03 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05_03 "CAN_DET_RANGE_RATE_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05_03 "CAN_DET_AMPLITUDE_05_03"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05_03 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05_03 "CAN_SCAN_INDEX_2LSB_05_03"; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_04 "CAN_DET_CONFID_AZIMUTH_05_04"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_04 "CAN_DET_CONFID_AZIMUTH_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_04 "CAN_DET_CONFID_AZIMUTH_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_04 "CAN_DET_SUPER_RES_TARGET_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05_04 "CAN_DET_ND_TARGET_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_04 "CAN_DET_HOST_VEH_CLUTTER_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05_04 "CAN_DET_VALID_LEVEL_05_04"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05_04 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05_04 "CAN_DET_AZIMUTH_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05_04 "CAN_DET_RANGE_05_04"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05_04 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05_04 "CAN_DET_RANGE_RATE_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05_04 "CAN_DET_AMPLITUDE_05_04"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05_04 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05_04 "CAN_SCAN_INDEX_2LSB_05_04"; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_05 "CAN_DET_CONFID_AZIMUTH_05_05"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_05 "CAN_DET_CONFID_AZIMUTH_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_05 "CAN_DET_CONFID_AZIMUTH_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_05 "CAN_DET_SUPER_RES_TARGET_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05_05 "CAN_DET_ND_TARGET_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_05 "CAN_DET_HOST_VEH_CLUTTER_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05_05 "CAN_DET_VALID_LEVEL_05_05"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05_05 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05_05 "CAN_DET_AZIMUTH_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05_05 "CAN_DET_RANGE_05_05"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05_05 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05_05 "CAN_DET_RANGE_RATE_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05_05 "CAN_DET_AMPLITUDE_05_05"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05_05 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05_05 "CAN_SCAN_INDEX_2LSB_05_05"; +BA_ "GenSigVtEn" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_06 "CAN_DET_CONFID_AZIMUTH_05_06"; +BA_ "GenSigVtName" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_06 "CAN_DET_CONFID_AZIMUTH_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_CONFID_AZIMUTH_05_06 "CAN_DET_CONFID_AZIMUTH_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_SUPER_RES_TARGET_05_06 "CAN_DET_SUPER_RES_TARGET_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_ND_TARGET_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_ND_TARGET_05_06 "CAN_DET_ND_TARGET_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_HOST_VEH_CLUTTER_05_06 "CAN_DET_HOST_VEH_CLUTTER_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_VALID_LEVEL_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_VALID_LEVEL_05_06 "CAN_DET_VALID_LEVEL_05_06"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_AZIMUTH_05_06 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AZIMUTH_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AZIMUTH_05_06 "CAN_DET_AZIMUTH_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_05_06 "CAN_DET_RANGE_05_06"; +BA_ "GenSigStartValue" SG_ 292 CAN_DET_RANGE_RATE_05_06 0; +BA_ "GenSigSendType" SG_ 292 CAN_DET_RANGE_RATE_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_RANGE_RATE_05_06 "CAN_DET_RANGE_RATE_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_DET_AMPLITUDE_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_DET_AMPLITUDE_05_06 "CAN_DET_AMPLITUDE_05_06"; +BA_ "GenSigSendType" SG_ 292 CAN_SCAN_INDEX_2LSB_05_06 0; +BA_ "GenSigCmt" SG_ 292 CAN_SCAN_INDEX_2LSB_05_06 "CAN_SCAN_INDEX_2LSB_05_06"; +BA_ "GenMsgSendType" BO_ 290 1; +BA_ "GenMsgILSupport" BO_ 290 1; +BA_ "GenMsgNrOfRepetition" BO_ 290 0; +BA_ "GenMsgCycleTime" BO_ 290 0; +BA_ "NetworkInitialization" BO_ 290 0; +BA_ "GenMsgDelayTime" BO_ 290 0; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_01 "CAN_DET_CONFID_AZIMUTH_03_01"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_01 "CAN_DET_CONFID_AZIMUTH_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_01 "CAN_DET_CONFID_AZIMUTH_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_01 "CAN_DET_SUPER_RES_TARGET_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03_01 "CAN_DET_ND_TARGET_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_01 "CAN_DET_HOST_VEH_CLUTTER_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03_01 "CAN_DET_VALID_LEVEL_03_01"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03_01 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03_01 "CAN_DET_AZIMUTH_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03_01 "CAN_DET_RANGE_03_01"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03_01 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03_01 "CAN_DET_RANGE_RATE_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03_01 "CAN_DET_AMPLITUDE_03_01"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03_01 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03_01 "CAN_SCAN_INDEX_2LSB_03_01"; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_02 "CAN_DET_CONFID_AZIMUTH_03_02"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_02 "CAN_DET_CONFID_AZIMUTH_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_02 "CAN_DET_CONFID_AZIMUTH_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_02 "CAN_DET_SUPER_RES_TARGET_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03_02 "CAN_DET_ND_TARGET_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_02 "CAN_DET_HOST_VEH_CLUTTER_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03_02 "CAN_DET_VALID_LEVEL_03_02"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03_02 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03_02 "CAN_DET_AZIMUTH_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03_02 "CAN_DET_RANGE_03_02"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03_02 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03_02 "CAN_DET_RANGE_RATE_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03_02 "CAN_DET_AMPLITUDE_03_02"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03_02 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03_02 "CAN_SCAN_INDEX_2LSB_03_02"; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_03 "CAN_DET_CONFID_AZIMUTH_03_03"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_03 "CAN_DET_CONFID_AZIMUTH_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_03 "CAN_DET_CONFID_AZIMUTH_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_03 "CAN_DET_SUPER_RES_TARGET_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03_03 "CAN_DET_ND_TARGET_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_03 "CAN_DET_HOST_VEH_CLUTTER_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03_03 "CAN_DET_VALID_LEVEL_03_03"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03_03 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03_03 "CAN_DET_AZIMUTH_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03_03 "CAN_DET_RANGE_03_03"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03_03 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03_03 "CAN_DET_RANGE_RATE_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03_03 "CAN_DET_AMPLITUDE_03_03"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03_03 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03_03 "CAN_SCAN_INDEX_2LSB_03_03"; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_04 "CAN_DET_CONFID_AZIMUTH_03_04"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_04 "CAN_DET_CONFID_AZIMUTH_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_04 "CAN_DET_CONFID_AZIMUTH_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_04 "CAN_DET_SUPER_RES_TARGET_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03_04 "CAN_DET_ND_TARGET_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_04 "CAN_DET_HOST_VEH_CLUTTER_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03_04 "CAN_DET_VALID_LEVEL_03_04"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03_04 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03_04 "CAN_DET_AZIMUTH_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03_04 "CAN_DET_RANGE_03_04"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03_04 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03_04 "CAN_DET_RANGE_RATE_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03_04 "CAN_DET_AMPLITUDE_03_04"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03_04 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03_04 "CAN_SCAN_INDEX_2LSB_03_04"; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_05 "CAN_DET_CONFID_AZIMUTH_03_05"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_05 "CAN_DET_CONFID_AZIMUTH_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_05 "CAN_DET_CONFID_AZIMUTH_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_05 "CAN_DET_SUPER_RES_TARGET_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03_05 "CAN_DET_ND_TARGET_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_05 "CAN_DET_HOST_VEH_CLUTTER_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03_05 "CAN_DET_VALID_LEVEL_03_05"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03_05 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03_05 "CAN_DET_AZIMUTH_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03_05 "CAN_DET_RANGE_03_05"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03_05 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03_05 "CAN_DET_RANGE_RATE_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03_05 "CAN_DET_AMPLITUDE_03_05"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03_05 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03_05 "CAN_SCAN_INDEX_2LSB_03_05"; +BA_ "GenSigVtEn" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_06 "CAN_DET_CONFID_AZIMUTH_03_06"; +BA_ "GenSigVtName" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_06 "CAN_DET_CONFID_AZIMUTH_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_CONFID_AZIMUTH_03_06 "CAN_DET_CONFID_AZIMUTH_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_SUPER_RES_TARGET_03_06 "CAN_DET_SUPER_RES_TARGET_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_ND_TARGET_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_ND_TARGET_03_06 "CAN_DET_ND_TARGET_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_HOST_VEH_CLUTTER_03_06 "CAN_DET_HOST_VEH_CLUTTER_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_VALID_LEVEL_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_VALID_LEVEL_03_06 "CAN_DET_VALID_LEVEL_03_06"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_AZIMUTH_03_06 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AZIMUTH_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AZIMUTH_03_06 "CAN_DET_AZIMUTH_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_03_06 "CAN_DET_RANGE_03_06"; +BA_ "GenSigStartValue" SG_ 290 CAN_DET_RANGE_RATE_03_06 0; +BA_ "GenSigSendType" SG_ 290 CAN_DET_RANGE_RATE_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_RANGE_RATE_03_06 "CAN_DET_RANGE_RATE_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_DET_AMPLITUDE_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_DET_AMPLITUDE_03_06 "CAN_DET_AMPLITUDE_03_06"; +BA_ "GenSigSendType" SG_ 290 CAN_SCAN_INDEX_2LSB_03_06 0; +BA_ "GenSigCmt" SG_ 290 CAN_SCAN_INDEX_2LSB_03_06 "CAN_SCAN_INDEX_2LSB_03_06"; +BA_ "GenMsgSendType" BO_ 289 1; +BA_ "GenMsgILSupport" BO_ 289 1; +BA_ "GenMsgNrOfRepetition" BO_ 289 0; +BA_ "GenMsgCycleTime" BO_ 289 0; +BA_ "NetworkInitialization" BO_ 289 0; +BA_ "GenMsgDelayTime" BO_ 289 0; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_01 "CAN_DET_CONFID_AZIMUTH_02_01"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_01 "CAN_DET_CONFID_AZIMUTH_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_01 "CAN_DET_CONFID_AZIMUTH_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_01 "CAN_DET_SUPER_RES_TARGET_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02_01 "CAN_DET_ND_TARGET_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_01 "CAN_DET_HOST_VEH_CLUTTER_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02_01 "CAN_DET_VALID_LEVEL_02_01"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02_01 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02_01 "CAN_DET_AZIMUTH_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02_01 "CAN_DET_RANGE_02_01"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02_01 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02_01 "CAN_DET_RANGE_RATE_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02_01 "CAN_DET_AMPLITUDE_02_01"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02_01 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02_01 "CAN_SCAN_INDEX_2LSB_02_01"; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_02 "CAN_DET_CONFID_AZIMUTH_02_02"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_02 "CAN_DET_CONFID_AZIMUTH_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_02 "CAN_DET_CONFID_AZIMUTH_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_02 "CAN_DET_SUPER_RES_TARGET_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02_02 "CAN_DET_ND_TARGET_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_02 "CAN_DET_HOST_VEH_CLUTTER_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02_02 "CAN_DET_VALID_LEVEL_02_02"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02_02 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02_02 "CAN_DET_AZIMUTH_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02_02 "CAN_DET_RANGE_02_02"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02_02 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02_02 "CAN_DET_RANGE_RATE_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02_02 "CAN_DET_AMPLITUDE_02_02"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02_02 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02_02 "CAN_SCAN_INDEX_2LSB_02_02"; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_03 "CAN_DET_CONFID_AZIMUTH_02_03"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_03 "CAN_DET_CONFID_AZIMUTH_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_03 "CAN_DET_CONFID_AZIMUTH_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_03 "CAN_DET_SUPER_RES_TARGET_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02_03 "CAN_DET_ND_TARGET_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_03 "CAN_DET_HOST_VEH_CLUTTER_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02_03 "CAN_DET_VALID_LEVEL_02_03"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02_03 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02_03 "CAN_DET_AZIMUTH_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02_03 "CAN_DET_RANGE_02_03"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02_03 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02_03 "CAN_DET_RANGE_RATE_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02_03 "CAN_DET_AMPLITUDE_02_03"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02_03 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02_03 "CAN_SCAN_INDEX_2LSB_02_03"; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_04 "CAN_DET_CONFID_AZIMUTH_02_04"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_04 "CAN_DET_CONFID_AZIMUTH_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_04 "CAN_DET_CONFID_AZIMUTH_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_04 "CAN_DET_SUPER_RES_TARGET_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02_04 "CAN_DET_ND_TARGET_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_04 "CAN_DET_HOST_VEH_CLUTTER_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02_04 "CAN_DET_VALID_LEVEL_02_04"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02_04 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02_04 "CAN_DET_AZIMUTH_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02_04 "CAN_DET_RANGE_02_04"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02_04 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02_04 "CAN_DET_RANGE_RATE_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02_04 "CAN_DET_AMPLITUDE_02_04"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02_04 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02_04 "CAN_SCAN_INDEX_2LSB_02_04"; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_05 "CAN_DET_CONFID_AZIMUTH_02_05"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_05 "CAN_DET_CONFID_AZIMUTH_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_05 "CAN_DET_CONFID_AZIMUTH_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_05 "CAN_DET_SUPER_RES_TARGET_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02_05 "CAN_DET_ND_TARGET_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_05 "CAN_DET_HOST_VEH_CLUTTER_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02_05 "CAN_DET_VALID_LEVEL_02_05"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02_05 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02_05 "CAN_DET_AZIMUTH_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02_05 "CAN_DET_RANGE_02_05"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02_05 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02_05 "CAN_DET_RANGE_RATE_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02_05 "CAN_DET_AMPLITUDE_02_05"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02_05 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02_05 "CAN_SCAN_INDEX_2LSB_02_05"; +BA_ "GenSigVtEn" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_06 "CAN_DET_CONFID_AZIMUTH_02_06"; +BA_ "GenSigVtName" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_06 "CAN_DET_CONFID_AZIMUTH_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_CONFID_AZIMUTH_02_06 "CAN_DET_CONFID_AZIMUTH_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_SUPER_RES_TARGET_02_06 "CAN_DET_SUPER_RES_TARGET_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_ND_TARGET_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_ND_TARGET_02_06 "CAN_DET_ND_TARGET_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_HOST_VEH_CLUTTER_02_06 "CAN_DET_HOST_VEH_CLUTTER_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_VALID_LEVEL_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_VALID_LEVEL_02_06 "CAN_DET_VALID_LEVEL_02_06"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_AZIMUTH_02_06 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AZIMUTH_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AZIMUTH_02_06 "CAN_DET_AZIMUTH_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_02_06 "CAN_DET_RANGE_02_06"; +BA_ "GenSigStartValue" SG_ 289 CAN_DET_RANGE_RATE_02_06 0; +BA_ "GenSigSendType" SG_ 289 CAN_DET_RANGE_RATE_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_RANGE_RATE_02_06 "CAN_DET_RANGE_RATE_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_DET_AMPLITUDE_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_DET_AMPLITUDE_02_06 "CAN_DET_AMPLITUDE_02_06"; +BA_ "GenSigSendType" SG_ 289 CAN_SCAN_INDEX_2LSB_02_06 0; +BA_ "GenSigCmt" SG_ 289 CAN_SCAN_INDEX_2LSB_02_06 "CAN_SCAN_INDEX_2LSB_02_06"; +BA_ "GenMsgSendType" BO_ 256 1; +BA_ "GenMsgILSupport" BO_ 256 1; +BA_ "GenMsgNrOfRepetition" BO_ 256 0; +BA_ "NetworkInitialization" BO_ 256 0; +BA_ "GenSigCmt" SG_ 256 CAN_PCAN_MINOR_MRR "CAN_PCAN_MINOR_MRR"; +BA_ "GenSigSendType" SG_ 256 CAN_PCAN_MINOR_MRR 0; +BA_ "GenSigCmt" SG_ 256 CAN_PCAN_MAJOR_MRR "CAN_PCAN_MAJOR_MRR"; +BA_ "GenSigSendType" SG_ 256 CAN_PCAN_MAJOR_MRR 0; +BA_ "GenMsgCycleTime" BO_ 257 30; +BA_ "GenMsgSendType" BO_ 257 0; +BA_ "GenMsgILSupport" BO_ 257 1; +BA_ "GenMsgNrOfRepetition" BO_ 257 0; +BA_ "NetworkInitialization" BO_ 257 0; +BA_ "GenSigCmt" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtEn" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtName" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtName" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigCmt" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigStartValue" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL 0; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL 0; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_SIDELOBE 0; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_MNR 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_EXT_COND_NOK 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_ALIGN_NOT_START 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_OVERHEAT_ERROR 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_NOT_OP 0; +BA_ "GenSigCmt" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigVtEn" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigVtName" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigSendType" SG_ 257 CAN_XCVR_OPERATIONAL 0; +BA_ "GenMsgSendType" BO_ 288 1; +BA_ "GenMsgILSupport" BO_ 288 1; +BA_ "GenMsgNrOfRepetition" BO_ 288 0; +BA_ "GenMsgCycleTime" BO_ 288 0; +BA_ "NetworkInitialization" BO_ 288 0; +BA_ "GenMsgDelayTime" BO_ 288 0; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_01 "CAN_DET_CONFID_AZIMUTH_01_01"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_01 "CAN_DET_CONFID_AZIMUTH_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_01 "CAN_DET_CONFID_AZIMUTH_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_01 "CAN_DET_SUPER_RES_TARGET_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01_01 "CAN_DET_ND_TARGET_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_01 "CAN_DET_HOST_VEH_CLUTTER_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01_01 "CAN_DET_VALID_LEVEL_01_01"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01_01 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01_01 "CAN_DET_AZIMUTH_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01_01 "CAN_DET_RANGE_01_01"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01_01 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01_01 "CAN_DET_RANGE_RATE_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01_01 "CAN_DET_AMPLITUDE_01_01"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01_01 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01_01 "CAN_SCAN_INDEX_2LSB_01_01"; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_02 "CAN_DET_CONFID_AZIMUTH_01_02"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_02 "CAN_DET_CONFID_AZIMUTH_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_02 "CAN_DET_CONFID_AZIMUTH_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_02 "CAN_DET_SUPER_RES_TARGET_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01_02 "CAN_DET_ND_TARGET_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_02 "CAN_DET_HOST_VEH_CLUTTER_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01_02 "CAN_DET_VALID_LEVEL_01_02"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01_02 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01_02 "CAN_DET_AZIMUTH_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01_02 "CAN_DET_RANGE_01_02"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01_02 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01_02 "CAN_DET_RANGE_RATE_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01_02 "CAN_DET_AMPLITUDE_01_02"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01_02 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01_02 "CAN_SCAN_INDEX_2LSB_01_02"; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_03 "CAN_DET_CONFID_AZIMUTH_01_03"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_03 "CAN_DET_CONFID_AZIMUTH_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_03 "CAN_DET_CONFID_AZIMUTH_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_03 "CAN_DET_SUPER_RES_TARGET_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01_03 "CAN_DET_ND_TARGET_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_03 "CAN_DET_HOST_VEH_CLUTTER_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01_03 "CAN_DET_VALID_LEVEL_01_03"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01_03 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01_03 "CAN_DET_AZIMUTH_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01_03 "CAN_DET_RANGE_01_03"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01_03 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01_03 "CAN_DET_RANGE_RATE_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01_03 "CAN_DET_AMPLITUDE_01_03"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01_03 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01_03 "CAN_SCAN_INDEX_2LSB_01_03"; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_04 "CAN_DET_CONFID_AZIMUTH_01_04"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_04 "CAN_DET_CONFID_AZIMUTH_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_04 "CAN_DET_CONFID_AZIMUTH_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_04 "CAN_DET_SUPER_RES_TARGET_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01_04 "CAN_DET_ND_TARGET_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_04 "CAN_DET_HOST_VEH_CLUTTER_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01_04 "CAN_DET_VALID_LEVEL_01_04"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01_04 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01_04 "CAN_DET_AZIMUTH_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01_04 "CAN_DET_RANGE_01_04"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01_04 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01_04 "CAN_DET_RANGE_RATE_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01_04 "CAN_DET_AMPLITUDE_01_04"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01_04 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01_04 "CAN_SCAN_INDEX_2LSB_01_04"; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_05 "CAN_DET_CONFID_AZIMUTH_01_05"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_05 "CAN_DET_CONFID_AZIMUTH_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_05 "CAN_DET_CONFID_AZIMUTH_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_05 "CAN_DET_SUPER_RES_TARGET_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01_05 "CAN_DET_ND_TARGET_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_05 "CAN_DET_HOST_VEH_CLUTTER_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01_05 "CAN_DET_VALID_LEVEL_01_05"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01_05 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01_05 "CAN_DET_AZIMUTH_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01_05 "CAN_DET_RANGE_01_05"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01_05 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01_05 "CAN_DET_RANGE_RATE_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01_05 "CAN_DET_AMPLITUDE_01_05"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01_05 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01_05 "CAN_SCAN_INDEX_2LSB_01_05"; +BA_ "GenSigVtEn" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_06 "CAN_DET_CONFID_AZIMUTH_01_06"; +BA_ "GenSigVtName" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_06 "CAN_DET_CONFID_AZIMUTH_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_CONFID_AZIMUTH_01_06 "CAN_DET_CONFID_AZIMUTH_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_SUPER_RES_TARGET_01_06 "CAN_DET_SUPER_RES_TARGET_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_ND_TARGET_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_ND_TARGET_01_06 "CAN_DET_ND_TARGET_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_HOST_VEH_CLUTTER_01_06 "CAN_DET_HOST_VEH_CLUTTER_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_VALID_LEVEL_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_VALID_LEVEL_01_06 "CAN_DET_VALID_LEVEL_01_06"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_AZIMUTH_01_06 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AZIMUTH_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AZIMUTH_01_06 "CAN_DET_AZIMUTH_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_01_06 "CAN_DET_RANGE_01_06"; +BA_ "GenSigStartValue" SG_ 288 CAN_DET_RANGE_RATE_01_06 0; +BA_ "GenSigSendType" SG_ 288 CAN_DET_RANGE_RATE_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_RANGE_RATE_01_06 "CAN_DET_RANGE_RATE_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_DET_AMPLITUDE_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_DET_AMPLITUDE_01_06 "CAN_DET_AMPLITUDE_01_06"; +BA_ "GenSigSendType" SG_ 288 CAN_SCAN_INDEX_2LSB_01_06 0; +BA_ "GenSigCmt" SG_ 288 CAN_SCAN_INDEX_2LSB_01_06 "CAN_SCAN_INDEX_2LSB_01_06"; +BA_DEF_DEF_ "CrossOver_InfoCAN" "No"; +BA_DEF_DEF_ "CrossOver_LIN" "No"; +BA_DEF_DEF_ "UsedOnPgmDBC" "Yes"; +BA_DEF_DEF_ "ContentDependant" "No"; +BA_DEF_DEF_ "GenSigTimeoutTime_RCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_GWM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_OCS" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ABS_ESC" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_CCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_IPMA" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TSTR" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_SCCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_PSCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime__delete" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_Generic_BCM" 0; +BA_DEF_DEF_ "NmMessage" "No"; +BA_DEF_DEF_ "DiagResponse" "No"; +BA_DEF_DEF_ "DiagRequest" "No"; +BA_DEF_DEF_ "TpTxIndex" 0; +BA_DEF_DEF_ "DiagState" "No"; +BA_DEF_DEF_ "TpApplType" ""; +BA_DEF_DEF_ "NmAsrMessage" "No"; +BA_DEF_DEF_ "Mulitplexer" "No"; +BA_DEF_DEF_ "ConfiguredTransmitter" "No"; +BA_DEF_DEF_ "EventRateOfChange" 10000; +BA_DEF_DEF_ "GenMsgHandlingTypeDoc" ""; +BA_DEF_DEF_ "GenMsgHandlingTypeCode" ""; +BA_DEF_DEF_ "GenMsgMarked" ""; +BA_DEF_DEF_ "GenSigMarked" ""; +BA_DEF_DEF_ "GenSigVtIndex" ""; +BA_DEF_DEF_ "GenSigVtName" ""; +BA_DEF_DEF_ "GenSigVtEn" ""; +BA_DEF_DEF_ "GenSigSNA" ""; +BA_DEF_DEF_ "GenSigCmt" ""; +BA_DEF_DEF_ "GenMsgCmt" ""; +BA_DEF_DEF_ "GenSigSendType" "NoSigSendType"; +BA_DEF_DEF_ "GenSigInactiveValue" 0; +BA_DEF_DEF_ "GenSigMissingSourceValue" 0; +BA_DEF_DEF_ "WakeupSignal" "No"; +BA_DEF_DEF_ "GenSigStartValue" 0; +BA_DEF_DEF_ "GenMsgILSupport" "Yes"; +BA_DEF_DEF_ "NetworkInitializationCommand" "No"; +BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType"; +BA_DEF_DEF_ "GenMsgCycleTime" 0; +BA_DEF_DEF_ "GenMsgCycleTimeFast" 0; +BA_DEF_DEF_ "GenMsgDelayTime" 0; +BA_DEF_DEF_ "GenMsgNrOfRepetition" 0; +BA_DEF_DEF_ "GenMsgStartDelayTime" 0; +BA_DEF_DEF_ "NetworkInitialization" "No"; +BA_DEF_DEF_ "MessageGateway" "No"; +BA_DEF_DEF_ "ILUsed" "Yes"; +BA_DEF_DEF_ "NetworkInitializationUsed" "No"; +BA_DEF_DEF_ "PowerType" "Switched"; +BA_DEF_DEF_ "NodeStartUpTime" 250; +BA_DEF_DEF_ "NodeWakeUpTime" 10; +BA_DEF_DEF_ "GenMsgBackgroundColor" "#ffffff"; +BA_DEF_DEF_ "GenMsgForegroundColor" "#000000"; +VAL_ 34 IPMA_PCAN_DataRangeCheck 1 "Fault Present" 0 "No Fault"; +VAL_ 34 IPMA_PCAN_MissingMsg 1 "Fault Present" 0 "No Fault "; +VAL_ 34 VINSignalCompareFailure 1 "Fault Present" 0 "No Fault"; +VAL_ 34 ModuleNotConfiguredError 1 "Fault Present" 0 "No Fault"; +VAL_ 34 CarCfgNotConfiguredError 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ARMtoDSPChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 DSPtoArmChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 HostToArmChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ARMtoHostChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 LoopBWOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 DSPOverrunFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte6_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TuningSensitivityFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 SaturatedTuningFreqFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 LocalOscPowerFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterPowerFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte6_bit0 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 XCVRDeviceSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 FreqSynthesizerSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 AnalogConverterDevicSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 SidelobeBlockage 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit1 1 "Fault Present" 0 "No Fault"; +VAL_ 33 MNRBlocked 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ECUTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 AlignmentRoutineFailedFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 UnreasonableRadarData 1 "Fault Present" 0 "No Fault"; +VAL_ 33 MicroprocessorTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 VerticalAlignmentOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 HorizontalAlignmentOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 FactoryAlignmentMode 1 "Fault Present" 0 "No Fault"; +VAL_ 33 BatteryLowFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 BatteryHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_1p25SupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte3_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ThermistorOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_3p3DACSupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_3p3RAWSupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_5_SupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterIDFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit3 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit2 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PCANMissingMsgFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PCANBusOff 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 InstructionSetCheckFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 StackOverflowFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 WatchdogFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PLLLockFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit1 1 "Fault Present" 0 "No Fault"; +VAL_ 33 RAMMemoryTestFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 USCValidationFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit3 1 "Fault Present" 0 "No Fault"; +VAL_ 33 KeepAliveChecksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ProgramCalibrationFlashChecksum 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ApplicationFlashChecksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 371 CAN_AUTO_ALIGN_HANGLE_QF 3 "Accurate" 2 "Inaccurate" 1 "Temporarily undefined" 0 "Undefined"; +VAL_ 371 CAN_ALIGNMENT_STATUS 15 "Undefined_2" 14 "Undefined_1" 13 "Low Amplitude (Flat-plate only)" 12 "No Peak (Flat-plate only)" 11 "Fail Ver and Hor OutOfRange" 10 "Fail Vertical Align OutOfRange" 9 "Fail Horizontal Align OutOfRange" 8 "Fail Time Out" 7 "Fail Only Right Target Found" 6 "Fail Only Left Target Found" 5 "Fail Variance Too Large" 4 "Fail Deviation Too Large" 3 "Fail No Target" 2 "Success" 1 "Busy" 0 "Off"; +VAL_ 371 CAN_ALIGNMENT_STATE 6 "Static alignment flat-plate" 5 "Static alignment 2-target" 4 "Static alignment 1-target" 3 "Service alignment" 2 "Short track alignment" 1 "Auto alignment" 0 "Off"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 291 CAN_DET_CONFID_AZIMUTH_04_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 351 CAN_DET_CONFID_AZIMUTH_64 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 350 CAN_DET_CONFID_AZIMUTH_63 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 349 CAN_DET_CONFID_AZIMUTH_62 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 348 CAN_DET_CONFID_AZIMUTH_61 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 347 CAN_DET_CONFID_AZIMUTH_60 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 346 CAN_DET_CONFID_AZIMUTH_59 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 345 CAN_DET_CONFID_AZIMUTH_58 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 344 CAN_DET_CONFID_AZIMUTH_57 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 343 CAN_DET_CONFID_AZIMUTH_56 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 342 CAN_DET_CONFID_AZIMUTH_55 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 335 CAN_DET_CONFID_AZIMUTH_48 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 334 CAN_DET_CONFID_AZIMUTH_47 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 333 CAN_DET_CONFID_AZIMUTH_46 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 332 CAN_DET_CONFID_AZIMUTH_45 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 331 CAN_DET_CONFID_AZIMUTH_44 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 330 CAN_DET_CONFID_AZIMUTH_43 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 329 CAN_DET_CONFID_AZIMUTH_42 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 328 CAN_DET_CONFID_AZIMUTH_41 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 327 CAN_DET_CONFID_AZIMUTH_40 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 325 CAN_DET_CONFID_AZIMUTH_38 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 324 CAN_DET_CONFID_AZIMUTH_37 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 323 CAN_DET_CONFID_AZIMUTH_36 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 322 CAN_DET_CONFID_AZIMUTH_35 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 321 CAN_DET_CONFID_AZIMUTH_34 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 320 CAN_DET_CONFID_AZIMUTH_33 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 319 CAN_DET_CONFID_AZIMUTH_32 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 318 CAN_DET_CONFID_AZIMUTH_31 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 317 CAN_DET_CONFID_AZIMUTH_30 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 316 CAN_DET_CONFID_AZIMUTH_29 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 314 CAN_DET_CONFID_AZIMUTH_27 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 313 CAN_DET_CONFID_AZIMUTH_26 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 312 CAN_DET_CONFID_AZIMUTH_25 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 311 CAN_DET_CONFID_AZIMUTH_24 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 310 CAN_DET_CONFID_AZIMUTH_23 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 309 CAN_DET_CONFID_AZIMUTH_22_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 309 CAN_DET_CONFID_AZIMUTH_22_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 309 CAN_DET_CONFID_AZIMUTH_22_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 308 CAN_DET_CONFID_AZIMUTH_21_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 307 CAN_DET_CONFID_AZIMUTH_20_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 306 CAN_DET_CONFID_AZIMUTH_19_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 305 CAN_DET_CONFID_AZIMUTH_18_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 341 CAN_DET_CONFID_AZIMUTH_54 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 340 CAN_DET_CONFID_AZIMUTH_53 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 339 CAN_DET_CONFID_AZIMUTH_52 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 338 CAN_DET_CONFID_AZIMUTH_51 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 337 CAN_DET_CONFID_AZIMUTH_50 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 336 CAN_DET_CONFID_AZIMUTH_49 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 326 CAN_DET_CONFID_AZIMUTH_39 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 315 CAN_DET_CONFID_AZIMUTH_28 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 304 CAN_DET_CONFID_AZIMUTH_17_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 303 CAN_DET_CONFID_AZIMUTH_16_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 302 CAN_DET_CONFID_AZIMUTH_15_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 301 CAN_DET_CONFID_AZIMUTH_14_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 300 CAN_DET_CONFID_AZIMUTH_13_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 299 CAN_DET_CONFID_AZIMUTH_12_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 298 CAN_DET_CONFID_AZIMUTH_11_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 297 CAN_DET_CONFID_AZIMUTH_10_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 296 CAN_DET_CONFID_AZIMUTH_09_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 295 CAN_DET_CONFID_AZIMUTH_08_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 294 CAN_DET_CONFID_AZIMUTH_07_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 293 CAN_DET_CONFID_AZIMUTH_06_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 292 CAN_DET_CONFID_AZIMUTH_05_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 290 CAN_DET_CONFID_AZIMUTH_03_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 289 CAN_DET_CONFID_AZIMUTH_02_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 257 CAN_INTERFERENCE_TYPE 2 "Star PD-Like" 1 "Slow FMCW" 0 "No Interference"; +VAL_ 257 CAN_RECOMMEND_UNCONVERGE 1 "Recommended" 0 "Not Recommended"; +VAL_ 257 CAN_RADAR_ALIGN_INCOMPLETE 1 "Alignment Incomplete" 0 "Alignment Completed"; +VAL_ 257 CAN_BLOCKAGE_SIDELOBE 1 "Radar Blockage" 0 "No Radar Blockage"; +VAL_ 257 CAN_BLOCKAGE_MNR 1 "Radar Blockage" 0 "No Radar Blockage"; +VAL_ 257 CAN_RADAR_EXT_COND_NOK 1 "Too high temp or insufficient pw" 0 "External conditions OK"; +VAL_ 257 CAN_RADAR_ALIGN_OUT_RANGE 1 "Radar out of range" 0 "Radar within range"; +VAL_ 257 CAN_RADAR_ALIGN_NOT_START 1 "Radar align not started" 0 "Radar align started"; +VAL_ 257 CAN_RADAR_OVERHEAT_ERROR 1 "Radar overheat condition" 0 "No Overheat"; +VAL_ 257 CAN_RADAR_NOT_OP 1 "Radar not operational" 0 "Radar operational"; +VAL_ 257 CAN_XCVR_OPERATIONAL 1 "On" 0 "Off "; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 288 CAN_DET_CONFID_AZIMUTH_01_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; diff --git a/opendbc_repo/opendbc/dbc/README.md b/opendbc_repo/opendbc/dbc/README.md new file mode 100644 index 0000000000..20e31a9034 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/README.md @@ -0,0 +1,49 @@ +## DBC file basics + +A DBC file encodes, in a humanly readable way, the information needed to understand a vehicle's CAN bus traffic. A vehicle might have multiple CAN buses and every CAN bus is represented by its own dbc file. +Wondering what's the DBC file format? [Here](http://www.socialledge.com/sjsu/index.php?title=DBC_Format) and [Here](https://github.com/stefanhoelzl/CANpy/blob/master/docs/DBC_Specification.md) a couple of good overviews. + +## How to start reverse engineering cars + +[opendbc](https://github.com/commaai/opendbc) is integrated with [cabana](https://github.com/commaai/openpilot/tree/master/tools/cabana). + +Use [panda](https://github.com/commaai/panda) to connect your car to a computer. + +## How to use reverse engineered DBC +To create custom CAN simulations or send reverse engineered signals back to the car you can use [CANdevStudio](https://github.com/GENIVI/CANdevStudio) project. + +## DBC file preprocessor + +DBC files for different models of the same brand have a lot of overlap. Therefore, we wrote a preprocessor to create DBC files from a brand DBC file and a model specific DBC file. The source DBC files can be found in the generator folder. After changing one of the files run the generator.py script to regenerate the output files. These output files will be placed in the root of the opendbc repository and are suffixed by _generated. + +## Good practices for contributing to opendbc + +- Comments: the best way to store comments is to add them directly to the DBC files. For example: + ``` + CM_ SG_ 490 LONG_ACCEL "wheel speed derivative, noisy and zero snapping"; + ``` + is a comment that refers to signal `LONG_ACCEL` in message `490`. Using comments is highly recommended, especially for doubts and uncertainties. [cabana](https://community.comma.ai/cabana/) can easily display/add/edit comments to signals and messages. + +- Units: when applicable, it's recommended to convert signals into physical units, by using a proper signal factor. Using a SI unit is preferred, unless a non-SI unit rounds the signal factor much better. +For example: + ``` + SG_ VEHICLE_SPEED : 7|15@0+ (0.00278,0) [0|70] "m/s" PCM + ``` + is better than: + ``` + SG_ VEHICLE_SPEED : 7|15@0+ (0.00620,0) [0|115] "mph" PCM + ``` + However, the cleanest option is really: + ``` + SG_ VEHICLE_SPEED : 7|15@0+ (0.01,0) [0|250] "kph" PCM + ``` + +- Signal size: always use the smallest amount of bits possible. For example, let's say I'm reverse engineering the gas pedal position and I've determined that it's in a 3 bytes message. For 0% pedal position I read a message value of `0x00 0x00 0x00`, while for 100% of pedal position I read `0x64 0x00 0x00`: clearly, the gas pedal position is within the first byte of the message and I might be tempted to define the signal `GAS_POS` as: + ``` + SG_ GAS_POS : 7|8@0+ (1,0) [0|100] "%" PCM + ``` + However, I can't be sure that the very first bit of the message is referred to the pedal position: I haven't seen it changing! Therefore, a safer way of defining the signal is: + ``` + SG_ GAS_POS : 6|7@0+ (1,0) [0|100] "%" PCM + ``` + which leaves the first bit unallocated. This prevents from very erroneous reading of the gas pedal position, in case the first bit is indeed used for something else. diff --git a/opendbc_repo/opendbc/dbc/SConscript b/opendbc_repo/opendbc/dbc/SConscript new file mode 100644 index 0000000000..481e024bac --- /dev/null +++ b/opendbc_repo/opendbc/dbc/SConscript @@ -0,0 +1,31 @@ +import os +from pathlib import Path + +env = Environment(ENV=os.environ) + +generator = File("generator/generator.py") + +source_files = [ + File(str(f)) + for f in Path("generator").rglob("*") + if f.is_file() and f.suffix in {".py", ".dbc"} +] + +output_files = [ + f.name.replace(".dbc", "_generated.dbc") + for f in Path("generator").rglob("*.dbc") + if not f.name.startswith("_") +] + +# include DBCs generated by python scripts +output_files += [ + f.name.replace(".py", "_generated.dbc") + for f in Path("generator").rglob("*.py") + if not f.name.startswith(("_", "test_")) and f.name != "generator.py" +] + +generated = env.Command( + target=list(set(output_files)), + source=[generator] + source_files, + action="python3 ${SOURCES[0]}", +) diff --git a/opendbc_repo/opendbc/dbc/__init__.py b/opendbc_repo/opendbc/dbc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/dbc/acura_ilx_2016_nidec.dbc b/opendbc_repo/opendbc/dbc/acura_ilx_2016_nidec.dbc new file mode 100644 index 0000000000..e73fcc4221 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/acura_ilx_2016_nidec.dbc @@ -0,0 +1,185 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: ADAS RADAR NEO XXX + + +BO_ 768 VEHICLE_STATE: 8 ADAS + SG_ SET_ME_XF9 : 7|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ VEHICLE_SPEED : 15|8@0+ (1,0) [0|255] "kph" Vector__XXX + +BO_ 769 VEHICLE_STATE2: 8 ADAS + SG_ SET_ME_0F18510 : 7|28@0+ (1,0) [0|268435455] "" Vector__XXX + SG_ SET_ME_25A0000 : 27|28@0+ (1,0) [0|268435455] "" Vector__XXX + +BO_ 1024 RADAR_DIAGNOSTIC: 8 RADAR + SG_ RADAR_STATE : 7|8@0+ (1,0) [0|255] "" NEO + +BO_ 1040 XXX_101: 8 RADAR + +BO_ 1041 XXX_102: 8 RADAR + +BO_ 1042 XXX_103: 8 RADAR + +BO_ 1043 XXX_104: 8 RADAR + +BO_ 1044 XXX_105: 8 RADAR + +BO_ 1045 XXX_106: 8 RADAR + +BO_ 1046 XXX_107: 8 RADAR + +BO_ 1047 XXX_108: 8 RADAR + +BO_ 1056 XXX_109: 8 RADAR + +BO_ 1057 XXX_110: 8 RADAR + +BO_ 1058 XXX_111: 8 RADAR + +BO_ 1059 XXX_112: 8 RADAR + +BO_ 1060 XXX_113: 8 RADAR + +BO_ 1072 TRACK_0: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1073 TRACK_1: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1074 TRACK_2: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1075 TRACK_3: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1076 TRACK_4: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1077 TRACK_5: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1078 TRACK_6: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1079 TRACK_7: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1080 TRACK_8: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1081 TRACK_9: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1088 TRACK_10: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1089 TRACK_11: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1090 TRACK_12: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1091 TRACK_13: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1092 TRACK_14: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1093 TRACK_15: 8 RADAR + SG_ LONG_DIST : 7|12@0+ (0.0625,0) [0|255.5] "m" NEO + SG_ NEW_TRACK : 11|1@0+ (1,0) [0|1] "" NEO + SG_ LAT_DIST : 9|10@0- (0.0625,0) [0|63.5] "m" NEO + SG_ REL_SPEED : 31|12@0- (0.03125,0) [0|127.5] "m/s" NEO + +BO_ 1279 XXX_114: 8 RADAR + +BO_ 1280 XXX_115: 8 RADAR + +BO_ 1296 XXX_116: 8 RADAR + +BO_ 1297 XXX_117: 8 RADAR + +BO_TX_BU_ 768 : NEO,ADAS; +BO_TX_BU_ 769 : NEO,ADAS; + + +CM_ SG_ 1024 RADAR_STATE "need to find out more diagnostic values"; +VAL_ 1024 RADAR_STATE 121 "ok" 110 "faulted" 105 "wrong_config"; diff --git a/opendbc_repo/opendbc/dbc/bmw_e9x_e8x.dbc b/opendbc_repo/opendbc/dbc/bmw_e9x_e8x.dbc new file mode 100644 index 0000000000..7ec95c0b19 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/bmw_e9x_e8x.dbc @@ -0,0 +1,913 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: EON XXX RDC SZL VGSG JBBF RFK FLA RAD1 CAS CID AHM HKL HUD EKP DWA DSC SM_BF GWS VDM DDE1 ACI CCC DSC SM_FA CTM LDM RSE MRSZ VDA EDCK ZBE EGS ACC_Sensor Kombi IHKA ARS ACSM FZD PGS NVC AFS DME FRMFA EMF FKA VSW EPS PDC DKG EHC Diagnosetool_PT_CAN Diagnosetool_K_CAN_System Vector__XXX + + +BO_ 170 AccPedal: 8 DME + SG_ KickDownPressed : 53|1@0+ (1,0) [0|3] "" XXX + SG_ CruisePedalActive : 54|1@0+ (1,0) [0|1] "" XXX + SG_ CruisePedalInactive : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ThrottlelPressed : 50|1@0+ (1,0) [0|1] "" XXX + SG_ AcceleratorPedalPressed : 52|1@0+ (1,0) [0|7] "" XXX + SG_ AcceleratorPedalPercentage : 16|16@1+ (0.04,0) [0|100] "" XXX + SG_ Counter_170 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EngineSpeed : 32|16@1+ (0.25,0) [0|8000] "rpm" XXX + SG_ Checksum_170 : 0|8@1- (1,0) [0|65535] "" XXX + +BO_ 404 CruiseControl: 4 SZL + SG_ plus1mph_request : 16|1@0+ (1,0) [0|1] "" XXX + SG_ minus1mph_request : 18|1@0+ (1,0) [0|1] "" XXX + SG_ Cancel_request_up_stalk : 23|1@0+ (1,0) [0|1] "" XXX + SG_ Cancel_request_up_or_down_stalk : 20|1@0+ (1,0) [0|1] "" XXX + SG_ Resume_request : 22|1@0+ (1,0) [0|1] "" XXX + SG_ setMe_0xFC : 31|8@0+ (1,0) [0|255] "" XXX + SG_ plus5mph_request : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ minus5mph_request : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ requests_0xF : 15|4@0+ (1,0) [0|15] "" XXX + SG_ Counter_404 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ Checksum_404 : 7|8@0+ (1,0) [0|15] "" XXX + +BO_ 512 CruiseControlStatus: 8 DME + SG_ CruiseControlInactiveFlag : 12|1@0+ (1,0) [0|1] "" XXX + SG_ CruiseCoontrolActiveFlag : 13|1@0+ (1,0) [0|1] "" XXX + SG_ CruiseControlSetpointSpeed : 7|8@0+ (0.25,0) [0|255] "mph" XXX + +BO_ 168 EngineAndBrake: 8 DME + SG_ Checksum_EngineAndBrake : 0|8@1+ (1,0) [0|0] "" XXX + SG_ BrakePressed : 61|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_active2 : 62|1@0+ (1,0) [0|1] "" XXX + SG_ ST_RCPT_ENG_DSC : 52|2@1+ (1,0) [0|0] "" XXX + SG_ ST_RCPT_ENG_ARS : 50|2@1+ (1,0) [0|0] "" XXX + SG_ ST_RCPT_ENG_ACC : 48|2@1+ (1,0) [0|0] "" XXX + SG_ ST_RCPT_ENG_EGS : 54|2@1+ (1,0) [0|0] "" XXX + SG_ ST_DMEA_SWO : 44|2@1+ (1,0) [0|0] "" XXX + SG_ EngineTorque : 12|12@1- (0.03125,0) [-1024|1023] "" XXX + SG_ ALIV_TORQ_1_DME : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EngineTorqueWoInterv : 24|16@1- (0.03125,0) [-1024|1023.96875] "" XXX + +BO_ 470 SteeringButtons: 2 SZL + SG_ Volume_DOWN : 2|1@0+ (1,0) [0|1] "" XXX + SG_ Volume_UP : 3|1@0+ (1,0) [0|1] "" XXX + SG_ VoiceControl : 8|1@0+ (1,0) [0|1] "" XXX + SG_ Telephone : 0|1@0+ (1,0) [0|1] "" XXX + SG_ Next_up : 5|1@0+ (1,0) [0|1] "" XXX + SG_ Previous_down : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 403 DynamicCruiseControlStatus: 8 DSC + SG_ Counter_403 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ CruiseActive : 43|1@0+ (1,0) [0|1] "" XXX + SG_ CruiseSpeedChangeRequest : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CruiseControlSetpointSpeed : 15|8@0+ (1,-2) [0|255] "kph/mph" XXX + +BO_ 201 SteeringWheelAngle_DSC: 8 SZL + SG_ Counter_201 : 20|4@1+ (1,0) [0|15] "" DSC + SG_ SteeringPositionComplementLow : 24|11@1- (1,0) [0|1] "" DSC + SG_ SteeringPosition : 0|16@1- (0.0428316886,0) [-600|600] "deg" DSC + +BO_ 206 WheelSpeeds: 8 DSC + SG_ Wheel_FL : 0|16@1- (0.0625,0) [0|255] "kph" XXX + SG_ Wheel_FR : 16|16@1- (0.0625,0) [0|255] "kph" XXX + SG_ Wheel_RL : 32|16@1- (0.0625,0) [0|255] "kph" XXX + SG_ Wheel_RR : 48|16@1- (0.0625,0) [0|255] "kph" XXX + +BO_ 884 WheelToleranceAdjustment: 8 DSC + +BO_ 678 WiperSwitch: 8 SZL + SG_ AutoWipersOn : 0|1@1+ (1,0) [0|3] "" XXX + +BO_ 304 TerminalStatus: 8 CAS + SG_ AccOn : 23|1@1+ (1,0) [0|255] "" XXX + SG_ IgnitionOff : 22|1@1+ (1,0) [0|3] "" XXX + SG_ Counter_304 : 32|4@1+ (1,0) [0|15] "" XXX + SG_ Checksum_304 : 36|4@1+ (1,0) [0|255] "" XXX + +BO_ 169 Torque2: 8 DME + SG_ TORQ_AVL_SPAR_POS : 52|12@1- (0.5,0) [-1023.5|1023.5] "Nm" XXX + SG_ TORQ_AVL_SPAR_NEG : 40|12@1- (0.5,0) [-1023.5|1023.5] "Nm" XXX + SG_ TORQ_AVL_MAX : 28|12@1- (0.5,0) [-1023.5|1023.5] "Nm" XXX + SG_ TORQ_AVL_MIN : 16|12@1- (0.5,0) [-1023.5|1023.5] "Nm" XXX + SG_ ST_INFS : 14|2@1+ (1,0) [0|0] "" XXX + SG_ ST_SW_LEV_RPM : 12|2@1+ (1,0) [0|0] "" XXX + SG_ ALIV_TORQ_2_DME : 8|4@1+ (1,0) [0|0] "" XXX + SG_ CHKSM_TORQ_2_DME : 0|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 184 TorqueTransmisionRequest: 8 LDM + SG_ Checksum_184 : 0|8@1+ (1,0) [0|15] "" XXX + SG_ Counter_184 : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 196 SteeringWheelAngle: 7 DSC + SG_ SteeringSpeed : 24|16@1- (0.0428316886,0) [0|255] "degree/s" XXX + SG_ SteeringPosition : 0|16@1- (0.0428316886,0) [-600|600] "degree" XXX + +BO_ 180 WheelTorqueDriveTrain1: 8 DME + +BO_ 182 DynamicCruiseControlTorqueDemand: 8 DSC + SG_ TORQ_TAR_DSC : 12|12@1- (0.5,0) [0|1000] "" XXX + SG_ Counter_182 : 8|4@1+ (1,0) [0|14] "" XXX + SG_ Checksum_182 : 0|8@1+ (1,0) [0|15] "" XXX + +BO_ 186 TransmissionData: 8 EGS + SG_ Counter_186 : 48|4@1+ (1,0) [0|14] "" XXX + SG_ Shifting : 4|1@1+ (1,0) [0|15] "" XXX + SG_ OutputShaftSpeed : 24|16@1- (0.125,0) [0|255] "rpm" XXX + SG_ GearRatio : 8|8@1+ (0.05,0) [0|255] "" XXX + SG_ GearTar : 0|4@1+ (1,-4) [0|255] "" XXX + SG_ Checksum_186 : 40|8@1+ (1,0) [0|15] "" XXX + +BO_ 191 RequestedWheelTorqueDriveTrain: 8 LDM + SG_ Checksum_191 : 0|8@1+ (1,0) [0|19] "" XXX + SG_ Counter_191 : 8|4@1- (1,0) [0|255] "" XXX + SG_ TorqueReq : 16|12@1- (0.5,350) [-1024|1023.96875] "" XXX + +BO_ 414 StatusDSC_KCAN: 8 DSC + SG_ BrakePressure : 48|8@1- (1,0) [0|255] "" XXX + SG_ BrakeStates : 40|8@1+ (1,0) [0|255] "" XXX + SG_ Checksum_414 : 56|8@1+ (1,0) [0|15] "" XXX + SG_ Counter_414 : 20|4@1+ (1,0) [0|15] "" XXX + SG_ DTC_on : 12|1@1+ (1,0) [0|3] "" XXX + SG_ DSC_full_off : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 416 Speed: 8 DSC + SG_ AccX : 28|12@1- (1,0) [0|15] "" XXX + SG_ YawRate : 40|12@1- (1,0) [0|255] "" XXX + SG_ VehicleSpeed : 0|12@1- (0.103,0) [0|255] "kph" XXX + SG_ MovingReverse : 13|1@1+ (1,0) [0|3] "" XXX + SG_ AccY : 16|12@1- (1,0) [0|255] "" XXX + SG_ Counter_416 : 52|4@1+ (1,0) [0|14] "" XXX + SG_ Checksum_416 : 56|8@1+ (1,0) [0|15] "" XXX + SG_ MovingForward : 12|1@1+ (1,0) [0|15] "" XXX + +BO_ 418 TransimissionData2: 8 EGS + SG_ ManualMode : 50|1@0+ (1,0) [0|255] "" XXX + SG_ Counter_418 : 28|4@1+ (1,0) [0|14] "" XXX + SG_ Checksum_418 : 56|8@1+ (1,0) [0|15] "" XXX + +BO_ 690 WheelPressure_KCAN: 8 DSC + +BO_ 691 AccelerationData: 8 DSC + +BO_ 402 GearSelectorSwitch_1: 4 XXX + SG_ Counter_402 : 24|4@1+ (1,0) [0|14] "" XXX + +BO_ 408 GearSelectorSwitch: 8 GWS + SG_ ParkButtonSecond : 26|2@1+ (1,0) [0|3] "" XXX + SG_ SideButton : 28|2@1+ (1,0) [0|3] "" XXX + SG_ SportButtonPressed : 34|2@1+ (1,0) [0|255] "" XXX + SG_ M3_button : 36|2@1+ (1,0) [0|3] "" XXX + SG_ SideButtonXOR11 : 30|2@1+ (1,0) [0|3] "" XXX + SG_ param1XOR11 : 22|2@1+ (1,0) [0|3] "" XXX + SG_ m3ShifterPositionXOR1111 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ always11 : 38|2@1+ (1,0) [0|3] "" XXX + SG_ m3ShifterPosition : 4|4@1+ (1,0) [0|15] "" XXX + SG_ param1 : 20|2@1+ (1,0) [0|3] "" XXX + SG_ param5 : 32|2@1+ (1,0) [0|3] "" XXX + SG_ Counter_408 : 0|4@1+ (1,0) [0|14] "" XXX + SG_ ParkButtonFirst : 24|2@1+ (1,0) [0|3] "" XXX + SG_ ShifterPositionXOR1111 : 16|4@1+ (1,0) [0|15] "" XXX + SG_ ShifterPosition : 12|4@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 422 DistanceRoute: 8 DSC + +BO_ 436 InstrumentClusterStatus_KOMBI: 8 CCC + SG_ HandbrakeActive : 41|1@1+ (1,0) [0|3] "" XXX + +BO_ 464 EngineData: 8 DME + SG_ RPM_IDLG_TAR : 56|8@1+ (5,0) [0|1270] "1/min" XXX + SG_ CTR_SLCK : 48|2@1+ (1,0) [0|0] "" XXX + SG_ IJV_FU : 32|16@1+ (1,-48) [0|0] "C" XXX + SG_ AIP_ENG : 24|8@1+ (2,598) [600|1106] "hPa" XXX + SG_ ST_SW_WAUP : 22|2@1+ (1,0) [0|0] "" XXX + SG_ ST_ENG_RUN : 20|2@1+ (1,0) [0|0] "" XXX + SG_ Counter_464 : 16|4@1+ (1,0) [0|14] "" XXX + SG_ TEMP_EOI : 8|8@1+ (1,-48) [0|0] "C" XXX + SG_ TEMP_ENG : 0|8@1+ (1,-48) [0|0] "C" XXX + +BO_ 945 TransmissionData3: 8 DKG + SG_ Checksum_946 : 0|8@1+ (1,0) [0|19] "" XXX + SG_ Counter_945 : 8|4@1+ (1,0) [0|14] "" XXX + +BO_ 200 SteeringWheelAngle_slow: 6 SZL + SG_ SteeringPosition : 0|16@1- (0.0428316886,0) [-600|600] "degree" XXX + SG_ SteeringSpeed : 24|16@1- (0.0428316886,0) [-65535|65535] "degree/s" XXX + SG_ Counter_200 : 20|4@1+ (1,0) [0|15] "" XXX + +BO_ 466 TransmissionDataDisplay: 8 EGS + SG_ ShiftLeverMode : 32|2@1+ (1,0) [0|3] "" XXX + SG_ GearAct : 12|4@1+ (1,-4) [0|15] "" XXX + SG_ Counter_466 : 28|4@1+ (1,0) [0|14] "" XXX + SG_ ShiftLeverPosition : 0|4@1+ (1,0) [0|8] "" XXX + SG_ xFF : 40|8@1+ (1,0) [0|255] "" XXX + SG_ ShiftLeverPositionXOR : 4|4@1+ (1,0) [0|0] "" Vector__XXX + SG_ SportButtonState : 26|1@1+ (1,0) [0|1] "" XXX + +BO_ 437 HeatFlow_LoadTorqueClimate: 8 IHKA + +BO_ 1152 NetworkManagment1: 8 XXX + +BO_ 1170 NetworkManagment2: 8 XXX + +BO_ 1175 NetworkManagment3: 8 XXX + +BO_ 1176 NetworkManagment4: 8 XXX + +BO_ 1193 NetworkManagment5: 8 XXX + +BO_ 1246 GWS_ShiftLeverHeartbeat: 8 XXX + SG_ IgnOff : 12|1@0+ (1,0) [0|3] "" XXX + +BO_ 438 HeatFlowEngine: 8 DME + +BO_ 784 AmbientTemperature_RelativeTime: 8 Kombi + +BO_ 821 ElectricFuelPumpStatus: 8 EKP + +BO_ 1007 EngineOBD_data: 8 DME + +BO_ 1432 ServicesDKG: 8 XXX + +BO_ 309 CrashDisconnectControl: 8 ACSM + +BO_ 502 TurnSignals: 2 FRMFA + SG_ TurnSignalIdle : 9|1@0+ (1,0) [0|1] "" XXX + SG_ TurnSignalActive : 8|1@0+ (1,0) [0|1] "" XXX + SG_ RightTurn : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LeftTurn : 4|1@1+ (1,0) [0|1] "" XXX + SG_ HoldActivated : 0|1@1+ (1,0) [0|1] "" XXX + +BO_ 514 Dimming: 8 FRMFA + +BO_ 538 LampStatus: 8 FRMFA + +BO_ 550 RainSensorWiperSpeed: 8 FZD + +BO_ 578 ClimateFrontStatus: 8 IHKA + +BO_ 704 LCD_lighting: 8 Kombi + +BO_ 758 LightControl: 8 FRMFA + +BO_ 760 Time_Date: 8 Kombi + +BO_ 762 OccupancySeatBeltContact: 8 ACSM + SG_ NEW_SIGNAL_1 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 0|8@1+ (1,0) [0|15] "" XXX + +BO_ 764 TrunkStatus: 8 CAS + +BO_ 797 TirePressureStatus: 8 DSC + +BO_ 816 Range_Mileage: 8 Kombi + +BO_ 823 StatusFuelControl: 8 DME + +BO_ 897 EngineOilLevel: 8 DME + +BO_ 940 RunOnTimeTerminal30: 8 JBBF + +BO_ 947 PowerManagmentConsumptionControl: 8 DME + +BO_ 948 PowerBatteryVoltage: 8 DME + SG_ BatteryVoltage : 7|24@0+ (0.001,0) [0|65535] "" XXX + +BO_ 958 PowerRunningTime: 8 CAS + +BO_ 1408 ServicesKGM: 8 XXX + +BO_ 1426 ServicesDME: 8 XXX + +BO_ 1449 ServicesDSC: 8 XXX + +BO_ 1504 ServicesKOMBI: 8 XXX + +BO_ 1522 ServicesKBM: 8 XXX + +BO_ 209 Accelerometer1: 8 XXX + SG_ Counter_209 : 52|4@1+ (1,0) [0|255] "" XXX + SG_ Unknown : 16|16@1- (1,0) [0|65535] "" XXX + SG_ YawRate : 0|16@1- (1,0) [0|7] "" XXX + SG_ PitchRate : 32|16@1- (1,0) [0|65535] "" XXX + SG_ CRC8_209 : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 172 WheelTorqueDrivetrain2: 8 DME + +BO_ 128 SYNC: 5 XXX + SG_ State2 : 24|4@1+ (1,0) [0|15] "" XXX + SG_ State1 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ Counter_128 : 28|4@1+ (1,0) [0|15] "" XXX + +BO_ 320 Unknown140: 2 XXX + SG_ State : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 212 Unknown_d4: 8 XXX + SG_ State1 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ Counter_212 : 52|4@1+ (1,0) [0|255] "" XXX + SG_ Checksum_212 : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 205 Accelerometer2: 8 XXX + SG_ Counter_205 : 52|4@1+ (1,0) [0|255] "" XXX + SG_ LateralAcceleration : 32|16@1- (1,0) [0|255] "" XXX + SG_ YawRate : 0|16@1- (1,0) [0|255] "" XXX + SG_ CRC8_205 : 16|16@1- (1,0) [0|65535] "" XXX + +BO_ 790 OperationPushButtonDTC: 2 JBBF + SG_ setMe_0x3FFF : 2|14@1+ (1,0) [0|63] "" DSC + SG_ DTC_pressed : 0|1@1+ (1,0) [0|3] "" DSC + +BO_ 1577 Unknown_629: 8 XXX + +BO_ 133 Synchronization_SC_VDA: 8 DSC + +BO_ 173 Delay_request_ACC: 8 LDM + +BO_ 177 Torque_request_steering: 8 DSC + +BO_ 181 Torque_request_EGS: 8 EGS + SG_ Checksum_Torque_request_EGS : 0|8@1+ (1,0) [0|0] "" XXX + SG_ Gearbox_temperature : 56|8@1+ (1,0) [0|0] "C" XXX + +BO_ 183 Torque_request_ACC: 8 LDM + +BO_ 187 Target_torque_request: 8 DSC + +BO_ 188 Status_target_torque_conversion: 8 VGSG + +BO_ 190 Alive_Counter: 8 ARS + +BO_ 192 Alive_Central_Gateway: 8 JBBF + +BO_ 193 Alive_counter_telephone: 8 CCC + +BO_ 213 Request_wheel_torque_brake: 8 DSC + +BO_ 215 Alive_Counter_Security: 8 ACSM + +BO_ 216 CLU1_VDA: 8 VDA + +BO_ 225 Wheel_torque_brake: 8 DSC + +BO_ 226 Status_central_locking_BFT: 8 JBBF + +BO_ 227 CLU2_VDA: 8 VDA + +BO_ 230 Status_central_locking_BFTH: 8 JBBF + +BO_ 234 Status_central_locking_FAT: 8 JBBF + +BO_ 238 Central_locking_status_FATH: 8 JBBF + +BO_ 242 Status_central_locking_HK: 8 JBBF + +BO_ 244 CLU3_VDA: 8 VDA + +BO_ 247 lateral_dynamics_ARS_VDM: 8 ARS + +BO_ 249 Vertical_dynamics_VDM_ARS: 8 VDM + +BO_ 250 Control_window_lifter_FAT: 8 FRMFA + +BO_ 251 Control_window_lifter_BFT: 8 JBBF + +BO_ 252 Control_window_lifter_FATH: 8 JBBF + +BO_ 253 Control_window_lifter_BFTH: 8 JBBF + +BO_ 254 Voltage_level_sensors: 8 VDM + +BO_ 280 Exchange_AFS_DSC: 8 AFS + +BO_ 286 Control_interventions_DSC_AFS: 8 DSC + +BO_ 288 Status_partial_setpoints_AFS_DSC_2: 8 AFS + +BO_ 298 Sensor_data_ROSE: 8 ASCM + +BO_ 300 input_data_ROSE: 8 DSC + +BO_ 336 Request_1_ACC: 8 LDM + +BO_ 339 Request_2_ACC: 8 LDM + +BO_ 345 Object_data_ACC: 8 ACC_Sensor + +BO_ 348 Status_ACC: 8 ACC_Sensor + +BO_ 351 Requirement_angle_FFP: 8 LDM + +BO_ 357 CLU_Status_VDA: 8 VDA + +BO_ 370 Acknowledgment_request_Kombination: 8 CCC + +BO_ 373 Display_motor_data: 8 DME + +BO_ 400 display_ACC: 8 LDM + +BO_ 405 Operation_push_button_MSA: 8 IHKA + +BO_ 419 Raw_data_longitudinal_acceleration: 8 DSC + +BO_ 423 actuation_request_EMF: 8 DSC + +BO_ 426 Effect_ErgoCommander: 8 CCC + +BO_ 428 Status_ARS_module: 8 ARS + +BO_ 440 Operation_ErgoCommander: 8 ZBE + +BO_ 450 Distance_message_PDC: 8 PDC + +BO_ 451 Distance_message_2_PDC: 8 PDC + +BO_ 454 Acoustic_message_PDC: 8 PDC + +BO_ 472 Operation_air_conditioning_air_distribution_FA: 8 CCC + +BO_ 473 Operation_pushbutton_MDrive: 8 SZL + +BO_ 474 Climate_control_remote_control: 8 CAS + +BO_ 476 Operation_stratification_seat_heating: 8 CCC + +BO_ 478 Air_conditioning_controls_rear: 8 CCC + +BO_ 480 Operation_air_conditioning_air_distribution_BF: 8 CCC + +BO_ 482 Operation_air_conditioning_front: 8 CCC + +BO_ 483 Operation_pushbutton_interior_lighting: 8 FZD + +BO_ 487 Operation_seat_heating_seat_climate_FA: 8 IHKA + +BO_ 488 Operation_seat_heating_seat_climate_BF: 8 IHKA + +BO_ 490 Steering_column_adjustment_control: 8 IHKA + +BO_ 491 Operation_active_seat_FA: 8 IHKA + +BO_ 492 Operation_active_seat_BF: 8 IHKA + +BO_ 494 Steering_column_switch_operation: 8 FRMFA + +BO_ 499 Operation_seat_memory_FA: 8 XXX + +BO_ 504 Operation_SHD_MDS: 8 FZD + +BO_ 507 Status_EPS: 8 EPS + +BO_ 508 Status_AFS: 8 AFS + +BO_ 509 Status_request_EMF_KCAN: 8 EMF + +BO_ 510 Crash: 8 ACSM + +BO_ 513 Status_EMF_KCAN: 8 EMF + +BO_ 517 Acoustic_request_Kombi: 8 Kombi + +BO_ 518 Control_Display_Shiftlights: 8 DME + +BO_ 523 Memory_adjustment: 8 SM_FA + +BO_ 524 Steering_column_control: 8 SM_FA + +BO_ 525 Position_steering_column: 8 IHKA + +BO_ 528 Operation_HUD: 8 CCC + +BO_ 529 Status_HUD: 8 HUD + +BO_ 530 Height_levels_air_spring: 8 EHC + +BO_ 540 Operation_NightVision: 8 CCC + +BO_ 542 Status_NightVision: 8 NVC + +BO_ 548 Operation_push_button_NSW: 8 FRMFA + +BO_ 552 Operation_special_function: 8 CCC + +BO_ 554 Status_BFS: 8 JBBF + +BO_ 556 Operation_push_button_NSL: 8 FRMFA + +BO_ 558 Status_BFSH: 8 XXX + +BO_ 562 Status_FAS: 8 JBBF + +BO_ 566 Status_FASH: 8 XXX + +BO_ 570 Status_radio_key: 8 CAS + +BO_ 571 Status_climate_front_extended: 8 IHKA + +BO_ 573 Request_display_climate: 8 IHKA + +BO_ 574 Status_Klima_Fond: 8 FKA + +BO_ 582 Status_air_conditioning_front_control_unit: 8 IHKA + +BO_ 584 Status_rear_view_camera: 8 RFK + +BO_ 585 Control_rear_view_camera: 8 CCC + +BO_ 586 Status_PDC: 8 PDC + +BO_ 587 Status_door_sensors: 8 FRMFA + +BO_ 594 Wiper_status: 8 JBBF + +BO_ 598 Challenge_Passive_Access: 8 CAS + +BO_ 600 Status_Transmission_Passive_Access: 8 PGS + +BO_ 604 Operation_of_climate_additional_programs: 8 CCC + +BO_ 621 Operation_blinds_MK: 8 IHKA + +BO_ 622 Control_FH_SHD_central_comfort: 8 CAS + +BO_ 635 Status_Shiftlights: 8 Kombi + +BO_ 637 Status_convertible_top_manual_convertible: 8 CAS + +BO_ 638 Status_convertible_top_convertible: 8 CTM + +BO_ 639 Status_central_locking_convertible_top: 8 JBBF + +BO_ 642 Control_security_vehicle_2: 8 XXX + +BO_ 644 Control_remote_start_safety_vehicle: 8 CAS + +BO_ 646 Electrochromic_control: 8 FZD + +BO_ 652 Pushbutton_vertical_dynamics: 8 GWS + +BO_ 653 Operation_pushbutton_sport: 8 GWS + +BO_ 656 Control_response_hydrogen_vehicle: 8 XXX + +BO_ 658 Control_high_beam_assistant: 8 FLA + +BO_ 670 Central_locking_control_for_security_vehicle: 8 XXX + +BO_ 671 Remote_control_FondCommander: 8 CAS + +BO_ 672 Central_locking_control: 8 CAS + +BO_ 674 Operation_of_climate_stand_functions: 8 CCC + +BO_ 676 Operation_personalization: 8 Kombi + +BO_ 692 DWA_Alarm: 8 DWA + +BO_ 694 Control_horn_DWA: 8 DWA + +BO_ 696 Operation_onboard_computer: 8 CCC + +BO_ 697 Operation_RSE: 8 CCC + +BO_ 698 Stopwatch: 8 Kombi + +BO_ 701 Request_switching_display: 8 CCC + +BO_ 702 Switch_status_display: 8 VSW + +BO_ 703 Water_valve_control: 8 IHKA + +BO_ 706 Temperatur_Ist_Fond: 8 FKA + +BO_ 711 Display_Kombination_extended: 8 DME + +BO_ 714 Outside_temperature: 8 Kombi + +BO_ 716 Control_monitor_rear: 8 RSE + +BO_ 718 Control_monitor: 8 CCC + +BO_ 719 Status_of_auxiliary_water_pump: 8 JBBF + +BO_ 720 Status_Sensor_AUC: 8 JBBF + +BO_ 721 Status_fitting_window_V: 8 FZD + +BO_ 722 Status_pressure_refrigeration_circuit: 8 JBBF + +BO_ 723 Status_stratification_rear: 8 JBBF + +BO_ 725 Status_heating_rear_window: 8 JBBF + +BO_ 726 Status_valve_air_conditioning_compressor: 8 JBBF + +BO_ 730 Status_tailgate_lift: 8 HKL + +BO_ 734 Switch_control_display: 8 VSW + +BO_ 738 Status_setting_video_night_vision: 8 NVC + +BO_ 739 Status_setting_video_rear_view_camera: 8 RFK + +BO_ 740 Status_trailer: 8 AHM + +BO_ 742 Status_of_air_distribution_FA: 8 IHKA + +BO_ 746 Status_air_distribution_BF: 8 IHKA + +BO_ 750 Status_climate_additional_programs: 8 IHKA + +BO_ 752 Status_air_condition_functions: 8 IHKA + +BO_ 753 Status_driver_detection: 8 MRSZ + +BO_ 755 Display_switching_instruction: 8 DME + +BO_ 756 Air_conditioning_control_SH_ZH_auxiliary_water_pump: 8 IHKA + +BO_ 759 Units: 8 Kombi + +BO_ 768 Status_RSE: 8 RSE + +BO_ 772 Status_Gang: 8 EGS + +BO_ 773 Operation_button_convertible_top: 8 IHKA + +BO_ 774 Vehicle_tilt: 8 FRMFA + +BO_ 775 Operation_button_flap_convertible_top: 8 IHKA + +BO_ 776 Status_MSA: 8 DME + +BO_ 785 Refill_quantity: 8 Kombi + +BO_ 786 Service_Call_Teleservice: 8 Kombi + +BO_ 787 Status_Service_Call_Teleservice: 8 CCC + +BO_ 788 Status_driving_light: 8 FZD + +BO_ 789 Vehicle_mode: 8 JBBF + +BO_ 791 Operation_button_parking_aids: 8 IHKA + +BO_ 792 Status_antennas_Passive_Access: 8 PGS + +BO_ 793 Operation_push_button_RDC: 8 JBBF + +BO_ 794 Operation_button_HDC: 8 IHKA + +BO_ 795 Operation_of_tailgate_interior_button: 8 IHKA + +BO_ 796 Status_tire_pressure: 8 RDC + +BO_ 801 Operation_button_camera_BF: 8 IHKA + +BO_ 802 Damper_current: 8 EDCK + +BO_ 806 Status_damper_program: 8 VDM + +BO_ 808 Relativzeit: 8 Kombi + +BO_ 813 Display_HDC: 8 DSC + +BO_ 814 Status_climate_internal_control_info: 8 IHKA + +BO_ 817 Programming_of_step_cruise_control: 8 CCC + +BO_ 818 Driver_display_speed_range: 8 DME + +BO_ 822 Display_check_control_message_role: 8 Kombi + +BO_ 824 Control_display_check_control_message: 8 Kombi + +BO_ 825 Status_display_climate: 8 CCC + +BO_ 826 Status_Monitor_Front: 8 CID + +BO_ 828 Status_Monitor_Fond_1: 8 CID + +BO_ 830 Status_Monitor_Fond_2: 8 CID + +BO_ 841 Raw_data_level_tank: 8 JBBF + +BO_ 843 Seat_back_lock_status_FA: 8 SM_FA + +BO_ 845 Status_seat_back_lock_BF: 8 SM_BF + +BO_ 847 Status_contact_handbrake: 8 JBBF + SG_ Handbrake_push : 0|2@1+ (1,0) [0|3] "" XXX + +BO_ 858 Appointment_Condition_Based_Service: 8 CCC + +BO_ 860 Status_onboard_computer: 8 Kombi + +BO_ 862 Onboard_computer_data_trip_data: 8 Kombi + +BO_ 864 Data_onboard_computer_start_of_journey: 8 Kombi + +BO_ 866 Data_onboard_computer_average_values: 8 Kombi + +BO_ 868 Data_onboard_computer_arrival: 8 Kombi + +BO_ 869 Status_terminal_request: 8 CAS + +BO_ 870 Display_Kombination_external_display: 8 Kombi + +BO_ 871 Control_display_of_demand_oriented_service: 8 Kombi + +BO_ 877 Setting_the_driving_dynamics_switch: 8 JBBF + +BO_ 886 Status_wear_lamella: 8 VGSG + +BO_ 893 Status_DKG: 8 DKG + +BO_ 894 Temperatur_Bremse: 8 DSC + +BO_ 895 Range_of_diesel_exhaust_gas_additive: 8 DDE1 + +BO_ 896 chassis_number: 8 CAS + +BO_ 898 Electronic_engine_oil_dipstick_M: 8 DME + +BO_ 899 Motor_data_2: 8 DME + +BO_ 904 Vehicle_type: 8 CAS + +BO_ 907 Status_battery: 8 DME + +BO_ 910 Start_speed: 8 DME + +BO_ 914 Status_System_AFS: 8 AFS + +BO_ 916 RDA_request_data_storage: 8 Kombi + +BO_ 917 Coding_power_management: 8 CAS + +BO_ 920 Operation_chassis: 8 CCC + +BO_ 921 Status_MDrive: 6 DME + +BO_ 926 Operation_time_date: 8 CCC + +BO_ 928 Vehicle_state: 8 JBBF + +BO_ 931 Request_Remote_Services: 8 CCC + +BO_ 937 Status_motor_control_CKM: 8 DME + +BO_ 939 Status_Shiftlights_CKM: 8 Kombi + +BO_ 944 Status_gear_reverse: 8 FRMFA + +BO_ 949 Status_water_valve: 8 JBBF + +BO_ 950 Position_window_lifter_FAT: 8 FRMFA + +BO_ 951 Position_window_lifter_FATH: 8 JBBF + +BO_ 952 Position_window_regulator_BFT: 8 FRMFA + +BO_ 953 Position_window_regulator_BFTH: 8 JBBF + +BO_ 954 Position_SHD: 8 FZD + +BO_ 956 Position_window_lifter_security_vehicle: 8 XXX + +BO_ 957 Status_consumer_shutdown: 8 FRMFA + +BO_ 959 Position_window_rear_window: 8 CTM + +BO_ 960 Configuration_FAS: 8 SM_FA + +BO_ 961 Configuration_BFS: 8 SM_BF + +BO_ 964 Status_EDCK_CKM: 8 JBBF + +BO_ 967 Access_radio: 8 RAD1 + +BO_ 968 Operation_push_button_radio: 8 RAD1 + +BO_ 974 Radio_audio_control_interface_display: 8 ACI + +BO_ 975 Acknowledgment_access_radio_audio_control_interface: 8 ACI + +BO_ 979 Status_solar_sensor: 8 FZD + +BO_ 980 Configuration_of_central_locking_CKM: 8 Kombi + +BO_ 981 Status_central_locking_CKM: 8 CAS + +BO_ 982 Configuration_DWA_CKM: 8 Kombi + +BO_ 983 Status_DWA_CKM: 8 FZD + +BO_ 984 Configuration_RLS_CKM: 8 Kombi + +BO_ 985 Status_RLS_CKM: 8 FZD + +BO_ 986 Configuration_of_memory_positions_CKM: 8 Kombi + +BO_ 987 Status_memory_positions_CKM: 8 SM_FA + +BO_ 988 Configuration_light_CKM: 8 Kombi + +BO_ 989 Status_light_CKM: 8 FRMFA + +BO_ 990 Configuration_Climate_CKM: 8 CCC + +BO_ 991 Status_Klima_CKM: 8 IHKA + +BO_ 994 Configuration_of_tailgate_CKM: 8 CCC + +BO_ 995 Status_tailgate_CKM: 8 HKL + +BO_ 996 Configuration_rear_view_camera_CKM: 8 CCC + + + + +CM_ SG_ 170 ThrottlelPressed "Active when accelerator pedal pressed or cruise control: drives"; +CM_ SG_ 170 AcceleratorPedalPressed "Active only when driver actually presses the pedal"; +CM_ SG_ 170 AcceleratorPedalPercentage "ToDo Factor to be adjusted"; +CM_ SG_ 404 plus1mph_request "Appears when +1mph/kph stalk is depressed"; +CM_ SG_ 404 minus1mph_request "Appears when -1mph/kph stalk is depressed"; +CM_ SG_ 404 Cancel_request_up_stalk "Appears when cancel stalk (up) is depressed"; +CM_ SG_ 404 Cancel_request_up_or_down_stalk "Appears when cancel stalk (up or down) is depressed"; +CM_ SG_ 404 Resume_request "It appears when resume stalk button is depressed"; +CM_ SG_ 404 Counter_404 "Message is sent at higher rate when cruise stalk is pressed"; + +CM_ SG_ 168 BrakePressed "Brake when driver presses the brake or hill hold"; +CM_ SG_ 168 EngineTorque "Engine torque without inertia - combustion torque"; +CM_ SG_ 168 EngineTorqueWoInterv "Engine torque without inertia and without shift intervention"; +CM_ SG_ 168 ALIV_TORQ_1_DME "Counter TORQ_1"; + +CM_ SG_ 169 ALIV_TORQ_2_DME "Counter TORQ_2"; + +CM_ SG_ 182 TORQ_TAR_DSC "torque target DSC"; + +CM_ SG_ 403 CruiseControlSetpointSpeed "Speed target - unit depends on locale"; +CM_ SG_ 186 GearTar "Values corresponds to forward gears. TBD Add enums for park, reverse"; +CM_ SG_ 466 GearAct "TransmissionDataDisplay"; +CM_ SG_ 414 DSC_full_off "0x4 enabling, 0xA enabled. TBD"; + +CM_ SG_ 416 YawRate "Lateral Acceleration"; + +CM_ SG_ 408 ParkButtonSecond "Redundant buton. 0x1 = pressed;"; +CM_ SG_ 408 SideButton "0x1 = pressed;"; +CM_ SG_ 408 SportButtonPressed "0x1 = pressed;"; +CM_ SG_ 408 M3_button "M3 POWER (?)"; +CM_ SG_ 408 SideButtonXOR11 "Complement value"; +CM_ SG_ 408 param1 "can not be 0x03. Always 0 in 135i."; +CM_ SG_ 408 param5 "Always 0 in 135i."; +CM_ SG_ 408 ParkButtonFirst "0x1 = pressed"; +CM_ SG_ 408 ShifterPosition "0001 = N|R, 0010 = R, 0011 = N|D, 0100 = D, 0101 = -1, 0110 = +1, 0111 = ManualMode, 1000 = inBetween,"; + +CM_ SG_ 466 ShiftLeverMode "On the dashboard, there are displayed: D1...D7 in Normal. S1...S6 in Sport. M1..M7 in Manual"; + +CM_ SG_ 502 TurnSignalIdle "Turn signal off"; +CM_ SG_ 502 TurnSignalActive "Turn signal on or transitioning"; +CM_ SG_ 502 RightTurn "Indicates right blinker or when steering returning right clears left blinker"; +CM_ SG_ 502 LeftTurn "Indicates left blinker or when steering returning left clears right blinker"; +CM_ SG_ 502 HoldActivated "Spikes down if blinker cleared with timeout or turn. Stays off if blinker cleared with stalk"; + +CM_ SG_ 790 setMe_0x3FFF "All ones"; +CM_ SG_ 790 DTC_pressed "Traction control off. Message transmitted when pressed. Few presses may be required followed by off."; + +VAL_ 408 ShifterPosition 1 "D" 2 "S" 3 "N" 4 "R" 5 "P" ; + +VAL_ 464 ST_SW_WAUP 3 "signal invalid" 2 "EGS forced switching active" 1 "engine warm" 0 "warming up" ; +VAL_ 464 ST_ENG_RUN 3 "signal invalid" 2 "engine running" 1 "engine starting" 0 "engine off" ; +VAL_ 464 CTR_SLCK 3 "signal invalid" 2 "requirement Shiftlock" 1 "no requirement Shiftlock" 0 "not allowed" ; + +VAL_ 466 ShiftLeverMode 0 "Normal" 1 "Sport" 2 "Manual" ; +VAL_ 466 ShiftLeverPosition 0 "Off" 1 "P" 2 "R" 4 "N" 8 "D" ; diff --git a/opendbc_repo/opendbc/dbc/cadillac_ct6_chassis.dbc b/opendbc_repo/opendbc/dbc/cadillac_ct6_chassis.dbc new file mode 100644 index 0000000000..9de969d762 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/cadillac_ct6_chassis.dbc @@ -0,0 +1,95 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: K182_PACM K43_PSCM K17_EBCM NEO K124_ASCM + + + +BO_ 823 PACMParkAssitCmd: 7 NEO + SG_ RollingCounter : 35|2@0+ (1,0) [0|0] "" NEO + SG_ SteeringWheelChecksum : 47|16@0+ (1,0) [0|0] "" NEO + SG_ SteeringWheelCmd : 23|16@0+ (1,0) [0|0] "" NEO + +BO_ 560 EBCMRegen: 6 K17_EBCM + SG_ Regen : 1|10@0+ (1,0) [0|0] "" NEO + +BO_ 338 ASCMLKASteeringCmd: 6 NEO + SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO + SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO + SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO + SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO + SG_ LKASMode : 36|2@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO + +BO_ 340 ASCMBLKASteeringCmd: 6 NEO + SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO + SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO + SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO + SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO + SG_ LKASteeringCmdActive2 : 35|1@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO + +BO_ 368 EBCMFrictionBrakeStatus: 8 K17_EBCM + SG_ FrictionBrakePressure : 23|16@0+ (1,0) [0|0] "" NEO + +BO_ 789 EBCMFrictionBrakeCmd: 5 K17_EBCM + SG_ RollingCounter : 37|6@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeMode : 7|4@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeChecksum : 23|16@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeCmd : 3|12@0- (1,0) [0|0] "" NEO + +BO_TX_BU_ 823 : K43_PSCM,NEO; +BO_TX_BU_ 789 : NEO,K17_EBCM; + + +CM_ BU_ K182_PACM "Parking Assist Control Module"; +CM_ BU_ K43_PSCM "Power Steering Control Module"; +CM_ BU_ K17_EBCM "Electronic Brake Control Module"; +CM_ BU_ NEO "Comma NEO"; +CM_ BU_ K124_ASCM "Active Safety Control Module"; +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "UseGMParameterIDs" 0; +BA_ "BusType" "CAN"; +BA_ "ProtocolType" "GMLAN"; + +VAL_ 338 LKASteeringCmdActive 1 "Active" 0 "Inactive" ; +VAL_ 338 LKASMode 2 "supercruise" 1 "lkas" 0 "Inactive" ; diff --git a/opendbc_repo/opendbc/dbc/cadillac_ct6_object.dbc b/opendbc_repo/opendbc/dbc/cadillac_ct6_object.dbc new file mode 100644 index 0000000000..3f7cf64cdc --- /dev/null +++ b/opendbc_repo/opendbc/dbc/cadillac_ct6_object.dbc @@ -0,0 +1,3470 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: RRSRR_FO LRSRR_FO CIPM_FO _DOFIMU2_FO _DOFIMU1_FO DMS_FO AMM_FO EOCM2B_IMX6_FO EOCM2B_K2_FO EOCM2B_K1_FO EOCM2A_IMX6_FO EOCM2A_K2_FO EOCM2A_K1_FO NVS_FO Dummy_FO TestTool_FO LRR_FO RFSRR_FO LFSRR_FO RSRR_FO VIS_FO EOCM_F_FO VIS2_FO +VAL_TABLE_ vt_BooleanValues 1 "true" 0 "false" ; +VAL_TABLE_ FrntVsnInPthVehBrkNwSt 10 "Active" 5 "Inactive" ; +VAL_TABLE_ FrntVsnClostPedBrkNwSt 10 "Active" 5 "Inactive" ; +VAL_TABLE_ DrvrMonSysEngSt 7 "Unused and Reserved 1" 6 "Recovering" 5 "Tracking" 4 "Searching" 3 "Video test port only" 2 "Idle" 1 "Invalid state" 0 "Does not exist or DME" ; +VAL_TABLE_ DrvrMonEngUnrecvrFltCod 7 "Unused and Reserved 3" 6 "Unused and Reserved 2" 5 "Unused and Reserved 1" 4 "Vehicle power supply Errors" 3 "Problem with LED illuminators" 2 "Vehicle input signals Errors" 1 "Problem with imager" 0 "Ok" ; +VAL_TABLE_ DrvrMonEngRecvrFltCod 3 "Engine is unable to find a face" 2 "Input Images too dark" 1 "Input images too bright" 0 "Ok" ; +VAL_TABLE_ DrvrMntrSysVTP 1 "Video test port active" 0 "Video test port inactive" ; +VAL_TABLE_ DrvrAttnStatCnfdc 3 "High" 2 "Medium" 1 "Low" 0 "Lowest" ; +VAL_TABLE_ DrvrAttnStat 7 "Invalid" 6 "Driver is exhibiting sleep" 5 "Driver is exhibiting microsleep" 4 "Attention is Center Console" 3 "Attention is Drivers Lap" 2 "Attention is Off Road" 1 "Attention is On Road" 0 "Unknown" ; +VAL_TABLE_ PPSMd 7 "GNSS and RTX and DR and MM" 6 "DR ONLY" 5 "GNSS and RTX and DR" 4 "GNSS and SBAS and DR" 3 "GNSS and DR" 2 "GNSS and RTX" 1 "GNSS and SBAS" 0 "GNSS Standalone" ; +VAL_TABLE_ AdvDrvAstMpPrfShrtAcur 3 "Accuracy Is Unknown" 2 "Lowest Accuracy" 1 "Medium Accuracy" 0 "Highest Accuracy" ; +VAL_TABLE_ AdvDrAstMpStbRtOfWay 3 "Not Applicable" 2 "Unknown" 1 "Sub Path Has Right Of Way Over Path" 0 "Path Has Right Of Way Over Sub Path" ; +VAL_TABLE_ AdvDrAstMpStbPrtCalRut 3 "Not Applicable" 2 "Unknown" 1 "Path From This Point On Is Part Of Calculated Route" 0 "Path From This Point On Is Not Part Of Calculated Route" ; +VAL_TABLE_ AdvDrAstMpStbMsgTyp 7 "Unused and Reserved 2" 6 "Metadata" 5 "Profile Long" 4 "Profile Short" 3 "Stub" 2 "Segment" 1 "Position" 0 "Unused and Reserved 1" ; +VAL_TABLE_ AdvDrAstMpStbFmOfWay 15 "Not Applicable" 14 "Pedestrian Zone" 13 "Entrance To Or Exit To Service" 12 "Entrance To Or Exit Of A Car Park" 11 "Service Road Or Frontage Road" 10 "Slip Road per Ramp" 9 "Slip Road per Ramp On A Freeway Or Controlled Access Road" 8 "Parallel Road" 7 "Unused and Reserved 2" 6 "Unused and Reserved 1" 5 "Traffic Square per Special Traffic Figure" 4 "Roundabout Circle" 3 "Single Carriageway" 2 "Multiple Carriageway Or Multiply Digitized Road" 1 "Freeway Or Controlled Access Road That Is Not A Slip Road Or Ramp" 0 "Unknown" ; +VAL_TABLE_ AdvDrAstMpStbCmplxInsct 3 "Not Applicable" 2 "Unknown" 1 "Stub Is Part Of Complex Intersection" 0 "Stub Is Not Part Of Complex Intersection" ; +VAL_TABLE_ AdvDrAstMpSegTunl 3 "Not Applicable" 2 "Unknown" 1 "Segment Is Part Of Tunnel" 0 "Segment Is Not A Part Of Tunnel" ; +VAL_TABLE_ AdvDrAstMpSegPrtCalRut 3 "Not Applicable" 2 "Unknown" 1 "Segment Is Part Of Calculated Route" 0 "Segment Is Not Part Of Calculated Route" ; +VAL_TABLE_ AdvDrAstMpSegMsgTyp 7 "Unused and Reserved 2" 6 "Metadata" 5 "Profile Long" 4 "Profile Short" 3 "Stub" 2 "Segment" 1 "Position" 0 "Unused and Reserved 1" ; +VAL_TABLE_ AdvDrAstMpSegFrmOfWay 15 "Not Applicable" 14 "Pedestrian Zone" 13 "Entrance To Or Exit To Service" 12 "Entrance To Or Exit Of A Car Park" 11 "Service Road Or Frontage Road" 10 "Slip Road per Ramp" 9 "Slip Road per Ramp On A Freeway Or Controlled Access Road" 8 "Parallel Road" 7 "Unused and Reserved 2" 6 "Unused and Reserved 1" 5 "Traffic Square per Special Traffic Figure" 4 "Roundabout Circle" 3 "Single Carriageway" 2 "Multiple Carriageway Or Multiply Digitized Road" 1 "Freeway Or Controlled Access Road That Is Not A Slip Road or Ramp" 0 "Unknown" ; +VAL_TABLE_ AdvDrAstMpSegEffSdLmtTp 7 "Not Applicable" 6 "Explicit Snow" 5 "Explicit Rain" 4 "Explicit Time Of Day" 3 "Explicit By Day" 2 "Explicit By Night" 1 "Explicit On Traffic Sign" 0 "Implicit" ; +VAL_TABLE_ AdvDrAstMpSegDivdRd 3 "Not Applicable" 2 "Unknown" 1 "Segment Is Part Of Divided Road" 0 "Segment Is Not Part Of Divided Road" ; +VAL_TABLE_ AdvDrAstMpSegCmplxInsct 3 "Not Applicable" 2 "Unknown" 1 "Segment Is Part Of Complex Intersection" 0 "Segment Is Not Part Of Complex Intersection" ; +VAL_TABLE_ AdvDrAstMpSegBrdg 3 "Not Applicable" 2 "Unknown" 1 "Segment Is Part Of Bridge" 0 "Segment Not Part Of Bridge" ; +VAL_TABLE_ AdvDrAstMpSegBldUpAra 3 "Not Applicable" 2 "Unknown" 1 "Segment Is Part Of Built Up Area" 0 "Segment Is Not Part Of Built Up Area" ; +VAL_TABLE_ AdvDrAstMpMtdtSpdUnt 1 "Miles Per Hour" 0 "Kilometers Per Hour" ; +VAL_TABLE_ AdvDrAstMpMtdtDrvSd 1 "Driving Side Right" 0 "Driving Side Left" ; +VAL_TABLE_ WSMR_WiFiAssnReq 3 "Unexpected Undefined Connection Behavior" 2 "Wi Fi association failed with available credentials" 1 "Failed to receive Wi Fi credentials after 255 attempts" 0 "SSID and Passphrase Request" ; +VAL_TABLE_ StrgColCommsFlt 2 "Disabled Communications DTC" 1 "No Communications Fault" 0 "Communications Fault" ; +VAL_TABLE_ CPMAPINFO4 1 "Hardware Or Software Error" 0 "No Hardware Or Software Error" ; +VAL_TABLE_ AdvDrvAstMpPrfShrt2Acur 3 "Accuracy Is Unknown" 2 "Lowest Accuracy" 1 "Medium Accuracy" 0 "Highest Accuracy" ; +VAL_TABLE_ InterLghtStat 1 "Interior Lights On" 0 "Interior Light Off" ; +VAL_TABLE_ VehLnStatConf 2 "High Confidence" 1 "Low Confidence" 0 "No Confidence" 3 "Very High Confidence" ; +VAL_TABLE_ VehLnStat 3 "Lane Change To Right" 2 "Lane Change To Left" 1 "Staying in Lane" 0 "Unknown" ; +VAL_TABLE_ HrznPrvdRstRq 1 "Reset Not Required" 0 "Reset Required" ; +VAL_TABLE_ ExptNxtTrnstnDirConf 3 "Very High Confidence" 2 "High Confidence" 1 "Low Confidence" 0 "No Confidence" ; +VAL_TABLE_ ExptNxtTrnstnDir 7 "Reserved4" 6 "Reserved3" 5 "Reserved2" 4 "Reserved1" 3 "Traversing Middle Transition" 2 "Traversing Next Transition Right" 1 "Traversing Next Transition Left" 0 "Unknown" ; +VAL_TABLE_ ADASISMsgTypRetrans 7 "GM System Specific" 6 "Meta Data" 5 "Profile Long" 4 "Profile Short" 3 "Stub" 2 "Segment" 1 "Position" 0 "Checksum" ; +VAL_TABLE_ NVSysStat 7 "Needs Headlights" 6 "Temporarily Unavailable" 5 "Not Dark" 4 "Needs Service" 3 "Active" 2 "Inactive" 1 "Initializing" 0 "Unknown" ; +VAL_TABLE_ NVSysPedWrnIndReq 3 "Unused & Reserved" 2 "Pedestrian Alert" 1 "Pedestrian Detected" 0 "None" ; +VAL_TABLE_ NVSysPedDetCstReq 2 "On" 1 "Off" 0 "No Value" ; +VAL_TABLE_ NVSysPedDetCsCrStVal 2 "On" 1 "Off" 0 "No Value" ; +VAL_TABLE_ FwVsnCinCoutPotT9Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT8Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT7Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT6Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT5Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT4Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT3Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT2Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT1Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT12Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT11Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT10Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ GFHBObjDirTrk8 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk7 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk6 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk5 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk4 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk3 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk2 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBObjDirTrk1 1 "Ahead Traffic" 0 "Incoming Traffic" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk8 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk7 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk6 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk5 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk4 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk3 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk2 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnRelLaneTrk1 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk8 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk7 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk6 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk5 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk4 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk3 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk2 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnMesStatTrk1 3 "Measured this cycle" 2 "Latent track not detected this cycle" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk8 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk7 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk6 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk5 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk4 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk3 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk2 3 "Confident" 2 "Speculative" 1 "Highly Speculative" 0 "Invalid" ; +VAL_TABLE_ GFHBFwVsnCnfdncTrk1 0 "Invalid" 3 "Confident" 2 "Speculative" 1 "Highly Speculative" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev8 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev7 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev6 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev5 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev4 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev3 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev2 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car)" 0 "Unknown" ; +VAL_TABLE_ GFHBFVsnObjTypTrkRev1 12 "Cluster Object" 11 "Child Close to Danger Zone" 10 "Pedestrian Moving Out of Danger Zone" 9 "Pedestrian Moving Into Danger Zone" 8 "Pedestrian Standing Outside Danger Zone" 7 "No Object Present" 6 "Fixed Roadside Object" 5 "Fixed Overhead Object" 4 "Pedestrian" 3 "Motorcycle/ Bicycle" 2 "Large Vehicle (Semi)" 1 "4 Wheel Vehicle (Car" 0 "Unknown" ; +VAL_TABLE_ CRL_Cnfdnc 7 "Reserved4" 6 "Reserved3" 5 "Reserved2" 4 "Reserved1" 3 "Best" 2 "Marking Present" 1 "Weak Marking" 0 "No Lane" ; +VAL_TABLE_ CLL_Cnfdnc 7 "Reserved4" 6 "Reserved3" 5 "Reserved2" 4 "Reserved1" 3 "Best" 2 "Marking Present" 1 "Weak Marking" 0 "No Lane" ; +VAL_TABLE_ VBBrkCtrlSt 4 "Release Control" 3 "Hold Vehicle" 2 "Apply Brake" 1 "Decrease Torque" 0 "No Action" ; +VAL_TABLE_ ObstacleType 6 "NO_OBJECT" 5 "OBJ_GUARDRAIL" 4 "OBJ_TUNNEL " 3 "OBJ_TRAFFIC_SIGN" 2 "OBJ_VEHICLE" 1 "OBJ_BRIDGE " 0 "OBJ_UNKNOWN" ; +VAL_TABLE_ VpathMode 2 "Mid Hi Speed" 1 "Low Speed" 0 "Disabled" ; +VAL_TABLE_ LaneChngStatus 2 "Lane Change Right" 1 "Lane Change Left" 0 "Idle" ; +VAL_TABLE_ TravelDirection 3 "Other (excessive side slip)" 2 "reverse / stopped in rvrs gear" 1 "Forward / stopped in frwd gear" 0 "Unknown" ; +VAL_TABLE_ TrueOrFalse 1 "true" 0 "false" ; +VAL_TABLE_ ModeCommand 5 "Sensing with Reduced Power" 4 "Undefined" 3 "Radio Silent" 2 "Sensing" 1 "Not Sensing" 0 "Undefined" ; +VAL_TABLE_ LaneSnsLLnPosValid 1 "Invalid" 0 "Valid" ; +VAL_TABLE_ LnSnsRLnPosValid 1 "Invalid" 0 "Valid" ; +VAL_TABLE_ Elevation 3 "Low " 2 "mid (reserved)" 1 "high " 0 "Unknown" ; +VAL_TABLE_ ModeCommandFdbk 5 "Sensing with reduced power" 4 "Undefined" 3 "Radio Silent" 2 "Sensing" 1 "Not Sensing" 0 "Undefined" ; +VAL_TABLE_ relativeLane 3 "Left Lane" 2 "Right Lane" 1 "Host Lane" 0 "Unknown" ; +VAL_TABLE_ RoadTypeInfo 5 "Constiction Zone Exit" 4 "Construction Zone Entry" 3 "Highway" 2 "Secondary Road" 1 "City" 0 "Unknown" ; +VAL_TABLE_ ObjectLossInfo 2 "elevation conditions" 1 "tight curve" 0 "not lost" ; +VAL_TABLE_ MeasurementStatus 3 "Measured this cycle" 2 "Latent track not detctd this cyc" 1 "New Object" 0 "No Object" ; +VAL_TABLE_ ObjectType 7 "no object present" 6 "fixed roadside object" 5 "fixed overhead object" 4 "pedestrian" 3 "motocycle / bicycle" 2 "Large vehicle (semi)" 1 "4 Wheel Vehicle (car, small trk)" 0 "Unknown" ; +VAL_TABLE_ Confidence 3 "confident" 2 "speculative" 1 "highly speculative" 0 "invalid" ; +VAL_TABLE_ DynamicProp 4 "Moving in opposite direction" 3 "Moving in same direction as host" 2 "Has moved but currently stopped" 1 "Has never moved" 0 "Unknown" ; +VAL_TABLE_ DrvWndPosSt 6 "Fully Opened" 5 "Open More Than C" 4 "Position C" 3 "Position B" 2 "Position A" 1 "Open Less Than A" 0 "Fully Closed" ; +VAL_TABLE_ VehMovSta 4 "Invalid" 3 "Reverse" 2 "Forward" 1 "Neutral" 0 "Parked" ; +VAL_TABLE_ OtsdAmbtLtLvlStat 2 "Day" 1 "Night" 0 "Unknown" ; +VAL_TABLE_ RtTrnLmpAtv 2 "On with telltale" 1 "On without telltale" 0 "Off" ; +VAL_TABLE_ LftTrnLmpAtv 2 "On with telltale" 1 "On without telltale" 0 "Off" ; +VAL_TABLE_ HdlmpBmSelectStat 2 "High Beams" 1 "Low Beams" 0 "Unknown" ; +VAL_TABLE_ DTCI_DTCFaultType 3 "Type C" 2 "Type B" 1 "Type A" 0 "Not Supported" ; +VAL_TABLE_ TrnsShftLvrPos 13 "Forward Range J" 12 "Forward Range I" 15 "Lever Position Unknown" 11 "Forward Range H" 10 "Forward Range G" 9 "Forward Range F" 8 "Forward Range E" 7 "Forward Range D" 6 "Forward Range C" 5 "Forward Range B" 4 "Forward Range A" 3 "Neutral Range" 2 "Reverse Range" 1 "Park Range" 0 "Between Ranges" ; +VAL_TABLE_ SysPwrMd 3 "Crank Request" 2 "Run" 1 "Accessory" 0 "Off" ; +VAL_TABLE_ ValidityStates 1 "Invalid" 0 "Valid" ; + + +BO_ 1548 ADAS_Profile_Short2_FO: 8 AMM_FO + SG_ AdvDrvAstMpPrfShrt2Val1 : 1|10@0+ (1,0) [0|1023] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2Val0 : 33|10@0+ (1,0) [0|1023] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2Updt : 39|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2RTrns : 3|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2Typ : 38|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2PthIdx : 23|6@0+ (1,0) [0|63] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2Ofst : 52|13@0+ (1,0) [0|8191] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2MsgTp : 55|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2Dist1 : 17|10@0+ (1,0) [0|1023] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2CycCnt : 7|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2CtlPt : 2|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpPrfShrt2Acur : 5|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 1547 ADAS_Profile_Long2_FO: 8 AMM_FO + SG_ AdvDrAstMpProfLng2Val : 39|32@0+ (1,0) [0|4294967295] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2Updt : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2RTrns : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2PrfTyp : 4|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2PthIdx : 13|6@0+ (1,0) [0|63] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2Ofst : 20|13@0+ (1,0) [0|8191] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2MgTyp : 23|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2CycCt : 15|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLng2CtrlPt : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 1630 USDT_Resp_From_EOCM2B_K2_FO: 8 EOCM2B_K2_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1374 UUDT_Resp_From_EOCM2B_K2_FO: 8 EOCM2B_K2_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 606 USDT_Req_to_EOCM2B_K2_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" EOCM2B_K2_FO + +BO_ 328 Vehicle_Info_FO: 5 EOCM2A_K1_FO + SG_ StrWhAngGrd : 27|12@0- (1,0) [-2048|2047] "deg/sec" DMS_FO + SG_ TrnsShftLvrPos : 31|4@0+ (1,0) [0|15] "" DMS_FO + SG_ StrWhAng_148 : 15|16@0- (0.0625,0) [-2048|2047.9375] "deg" DMS_FO + SG_ TrnsShftLvrPosV : 3|1@0+ (1,0) [0|1] "" DMS_FO + SG_ StrWhAngV_148 : 4|1@0+ (1,0) [0|1] "" DMS_FO + SG_ StrWhAngMsk_148 : 5|1@0+ (1,0) [0|1] "" DMS_FO + SG_ StrWhAngGrdV : 6|1@0+ (1,0) [0|1] "" DMS_FO + SG_ StrWhAngGrdMsk : 7|1@0+ (1,0) [0|1] "" DMS_FO + +BO_ 1930 DTC_Triggered_78A_FO: 7 LRSRR_FO + SG_ DTCI_CodeSupported_78A : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_78A : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_78A : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_78A : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_78A : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_78A : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_78A : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_78A : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_78A : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_78A : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_78A : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_78A : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_78A : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_78A : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_78A : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_78A : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_78A : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_78A : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_78A : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_78A : 47|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1624 USDT_Resp_From_LRSRR: 8 LRSRR_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1368 UUDT_Resp_From_LRSRR: 8 LRSRR_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 600 USDT_Req_to_LRSRR: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" LRSRR_FO + +BO_ 613 PPS_QualMetrics_FO: 8 EOCM2A_K1_FO + SG_ PPSPstnDilPrcs : 47|10@0+ (0.1,0) [0|102.3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSMd : 53|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPS3DAbsPosErrEstmt : 9|10@0+ (0.1,0) [0|102.3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSAbsHdngErrEstmt : 0|7@0+ (0.5,0) [0|63.5] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSAbsVelErrEstmt : 30|5@0+ (1,0) [0|31] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSPosQltyMtrcsChksm : 50|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPS2DAbsPosErrEstmt : 25|10@0+ (0.1,0) [0|102.3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSPosQltyMtcBrstID : 2|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPS2DAbsPosErrEstmtV : 5|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPS3DAbsPosErrEstmtV : 4|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSAbsHdngErrEstmtV : 3|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSAbsVelErrEstmtV : 31|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSMdV : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSPstnDilPrcsV : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + +BO_ 612 PPS_Time_FO: 8 EOCM2A_K1_FO + SG_ PPSTmdayV : 2|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSCldrDayV : 0|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSCldrDay : 8|9@0+ (1,0) [0|511] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSTmBrstID : 52|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSTmday : 31|27@0+ (1,0) [0|134217727] "ms" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSTmChksm : 50|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSCldrYrV : 1|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSCldrYr : 15|7@0+ (1,2014) [2014|2141] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + +BO_ 611 PPS_SigAcqTime_FO: 6 EOCM2A_K1_FO + SG_ PPSSigAqTmBrstID : 38|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSSigAcqTmV : 39|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSSigAcqTm : 7|32@0+ (1,0) [0|4294967295] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSSigAqTmChksm : 34|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + +BO_ 610 PPS_PosLong_FO: 6 EOCM2A_K1_FO + SG_ PPSLongBrstID : 39|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSLong : 6|31@0- (1,0) [-1073741824|1073741823] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSLongV : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSLongChksm : 34|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + +BO_ 609 PPS_PosLat_FO: 6 EOCM2A_K1_FO + SG_ PPSLatV : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSLatChksm : 34|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSLatBrstID : 36|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSLat : 5|30@0- (1,0) [-536870912|536870911] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + +BO_ 1160 PassPhrase_3_AMM_FO: 8 EOCM2A_K1_FO + SG_ WiFiPssPhrsDgts17to24_Mp : 7|64@0+ (1,0) [0|0] "" EOCM2B_K1_FO,AMM_FO + +BO_ 1159 PassPhrase_2_AMM_FO: 8 EOCM2A_K1_FO + SG_ WiFiPssPhrsDgts9to16_Mp : 7|64@0+ (1,0) [0|0] "" EOCM2B_K1_FO,AMM_FO + +BO_ 1158 PassPhrase_1_AMM_FO: 8 EOCM2A_K1_FO + SG_ WiFiPssPhrsDgts1to8_Mp : 7|64@0+ (1,0) [0|0] "" EOCM2B_K1_FO,AMM_FO + +BO_ 1546 ADAS_Protection_FO: 4 AMM_FO + SG_ AdvDrAstMpPrfLng2Avbl : 11|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPosAvbl : 15|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpHwFlt : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtAvbl : 8|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpProtChksm : 23|16@0+ (1,0) [0|65535] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpProtRTrns : 0|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpProtCycCtMsg : 2|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbAvbl : 9|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpSegAvbl : 10|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfShrtAvbl : 14|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfShrt2Avbl : 13|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrAstMpPrfLngAvbl : 12|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ AdvDrvAstMpInpSigFld : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 1545 ADAS_Metadata_FO: 8 AMM_FO + SG_ AdvDrAstMpMtdtVerYrQtr : 60|2@0+ (1,1) [1|4] "Qtr" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtVerYr : 53|6@0+ (1,2000) [2000|2063] "Year" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtSpdUnt : 39|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtPrvdr : 7|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtMsgTyp : 58|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtMnrPrtVr : 23|4@0+ (1,0) [0|15] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtCycCnt : 18|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtRgnCd : 38|15@0+ (1,0) [0|32767] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtHwVer : 16|9@0+ (1,0) [0|511] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtMnrPrtSbVr : 4|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtMjrPrtVr : 55|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtDrvSd : 19|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpMtdtCntryCd : 1|10@0+ (1,0) [0|1023] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 1543 ADAS_Profile_Long_FO: 8 AMM_FO + SG_ AdvDrAstMpPrfLngUpdt : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngRTrns : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngCtlPt : 5|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngTyp : 4|5@0+ (1,0) [0|31] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngCycCt : 15|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngPthIdx : 13|6@0+ (1,0) [0|63] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngMsgTp : 23|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngOfst : 20|13@0+ (1,0) [0|8191] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPrfLngVal : 39|32@0+ (1,0) [0|4294967295] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 1544 ADAS_Profile_Short_FO: 8 AMM_FO + SG_ AdvDrvAstMpPrfShrtVal1 : 1|10@0+ (1,0) [0|1023] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtVal0 : 33|10@0+ (1,0) [0|1023] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtDist1 : 17|10@0+ (1,0) [0|1023] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtCycCnt : 7|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtAcur : 5|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtCtlPt : 2|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtRetr : 3|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtTyp : 38|5@0+ (1,0) [0|31] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtUpdt : 39|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtPthIdx : 23|6@0+ (1,0) [0|63] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtMsgTp : 55|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrvAstMpPrfShrtOfst : 52|13@0+ (1,0) [0|8191] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 1542 ADAS_Stub_FO: 8 AMM_FO + SG_ AdvDrAstMpStbSubPthIdx : 63|6@0+ (1,0) [0|63] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbUpdt : 55|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbPrtCalRut : 57|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbNmLnDrvDir : 54|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbCycCnt : 51|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbCmplxInsct : 49|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbTrnAngl : 47|8@0+ (1.417,0) [0|361.335] "deg" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbRtOfWay : 38|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbRelProb : 36|5@0+ (3.333,0) [0|103.323] "%" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbRetr : 39|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbNmLnOppDir : 31|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbPathIdx : 29|6@0+ (1,0) [0|63] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbLstStbOfst : 23|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbMsgTyp : 22|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbFmOfWay : 19|4@0+ (1,0) [0|15] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbFuncRdCls : 7|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpStbOfst : 4|13@0+ (1,0) [0|8191] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 1541 ADAS_Segment_FO: 8 AMM_FO + SG_ AdvDrAstMpSegRelProb : 12|5@0+ (3.333,0) [0|103.323] "%" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegUpdt : 0|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegTunl : 25|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegCycCnt : 39|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegCmplxInsct : 37|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegBldUpAra : 43|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegBrdg : 41|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegRTrns : 1|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegDivdRd : 31|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegPthIdx : 7|6@0+ (1,0) [0|63] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegPrtCalRut : 27|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegNmLnOppDir : 29|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegNmLnDrvDir : 55|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegMsgTyp : 46|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegFunRdCls : 23|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegFrmOfWay : 35|4@0+ (1,0) [0|15] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegEffSpdLmt : 20|5@0+ (1,0) [0|31] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegEffSdLmtTp : 15|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpSegOffset : 52|13@0+ (1,0) [0|8191] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 608 PPS_ElevHdSpd_FO: 8 EOCM2A_K1_FO + SG_ PPSVel : 31|8@0+ (1,0) [0|255] "km / h" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSVelV : 3|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSElvHedngSpdBrstID : 5|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSElvHdengSpdChksm : 50|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSHedngV : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSHedng : 2|19@0+ (0.001,0) [0|524.287] "deg" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSElvtnV : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + SG_ PPSElvtn : 39|21@0+ (1,-100000) [-100000|1997151] "cm" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,AMM_FO + +BO_ 1168 WiFi_Station_AMM_FO: 5 AMM_FO + SG_ WSMR_WiFiStnMpMACAddr : 15|32@0+ (1,0) [0|4294967295] "" EOCM2B_K1_FO,EOCM2A_K1_FO + SG_ WSMR_WiFiAssnReq : 1|2@0+ (1,0) [0|3] "" EOCM2B_K1_FO,EOCM2A_K1_FO + +BO_ 1161 WiFi_AP_Data_AMM_FO: 2 EOCM2A_K1_FO + SG_ WAPDM_SecurityType : 15|4@0+ (1,0) [0|15] "" EOCM2B_K1_FO,AMM_FO + SG_ WAPDM_WiFiEnStat : 0|1@0+ (1,0) [0|1] "" EOCM2B_K1_FO,AMM_FO + SG_ WAPDM_EncrptnType : 11|4@0+ (1,0) [0|15] "" EOCM2B_K1_FO,AMM_FO + +BO_ 1157 SSID_AMM_3_FO: 8 EOCM2A_K1_FO + SG_ WiFiSSIDDgts17to24_Mp : 7|64@0+ (1,0) [0|0] "" EOCM2B_K1_FO,AMM_FO + +BO_ 326 DMS_Eye_AOI_Info_FO: 6 DMS_FO + SG_ DrvrMontSysInit : 1|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMontSysAvlbl : 3|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMontMdlDatFlshProgrs : 2|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonEngRecvrFltCodARC : 36|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrAttnStatChksm : 34|11@0+ (1,0) [0|2047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrAttnStat : 39|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrAttnStatPrd : 22|15@0+ (0.025,0) [0|819.175] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonEngRecvrFltCodV : 23|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonEngUnrecvrFltCod : 10|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonEngUnrecvrFltCodV : 11|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrAttnStatCnfdc : 13|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonEngRecvrFltCod : 15|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrAttnStatV : 0|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 324 DMS_RawMeasurement_Info2_FO: 8 DMS_FO + SG_ DrvrMonFrmNum : 47|8@0+ (1,0) [0|255] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMntrSysVTP : 29|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonSysEngStV : 2|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonSysEngSt : 28|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonFrmNumV : 3|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrHeadRotAngZV : 4|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrHeadRotAngYV : 5|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrHeadRotAngXV : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrHeadRotAngARC : 52|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonLatV : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrMonLat : 50|11@0+ (0.001,0) [0|2.047] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvHeadRotAngZ : 25|10@0- (0.00625,0) [-3.2|3.19375] "rad" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ DrvHeadRotAngY : 23|10@0- (0.00625,0) [-3.2|3.19375] "rad" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ DrvrHeadRotAngX : 1|10@0- (0.00625,0) [-3.2|3.19375] "rad" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 322 DMS_RawMeasurement_Info1_FO: 8 DMS_FO + SG_ DrvrEyeClosrRt : 47|8@0+ (0.005,0) [0|1.275] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrEyeClosrLft : 39|8@0+ (0.005,0) [0|1.275] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvHeadPosZV : 3|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvHeadPosYV : 4|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvHeadPosXV : 5|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrEyeClosrRtV : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrEyeClosrLftV : 7|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvrEyeClosrARC : 52|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ DrvHeadPosZ : 50|11@0- (0.005,0) [-5.12|5.115] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ DrvHeadPosY : 18|11@0- (0.005,0) [-5.12|5.115] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ DrvHeadPosX : 2|11@0- (0.005,0) [-5.12|5.115] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 320 Inertial2_Rates_FO: 8 _DOFIMU2_FO + SG_ MstrTgrSyncInrtl2Rte : 55|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2YawRteV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2YawRte : 36|13@0- (0.024,0) [-98.304|98.28] "deg/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2RollRteV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2RollRte : 20|13@0- (0.024,0) [-98.304|98.28] "deg/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2RteChksum : 50|11@0+ (1,0) [0|2047] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2PitchRteV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2PitchRte : 4|13@0- (0.024,0) [-98.304|98.28] "deg/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 308 Inertial1_Rates_FO: 8 _DOFIMU1_FO + SG_ MstrTrgrSyncInrtl1Rte : 55|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1YawRteV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1YawRte : 36|13@0- (0.024,0) [-98.304|98.28] "deg/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1RollRteV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1RollRte : 20|13@0- (0.024,0) [-98.304|98.28] "deg/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1RteChksum : 50|11@0+ (1,0) [0|2047] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1PitchRteV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial1PitchRte : 4|13@0- (0.024,0) [-98.304|98.28] "deg/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 312 Inertial2_Accel2_FO: 8 _DOFIMU2_FO + SG_ MstrTrigSyncInrtl22 : 55|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSns2AccFrm2Chksm : 50|11@0+ (1,0) [0|2047] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr2YawAccV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr2YawAcc : 36|13@0- (0.024,0) [-98.304|98.28] "deg/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr2RollAccV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr2RollAcc : 20|13@0- (0.024,0) [-98.304|98.28] "deg/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr2PtchAccV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr2PtchAcc : 4|13@0- (0.024,0) [-98.304|98.28] "deg/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 306 Inertial1_Accel2_FO: 8 _DOFIMU1_FO + SG_ MstrTrigSyncInrtl12 : 55|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1AccelFrm2Chksm : 50|11@0+ (1,0) [0|2047] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1YawAccV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1YawAcc : 36|13@0- (0.024,0) [-98.304|98.28] "deg/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1RollAccV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1RollAcc : 20|13@0- (0.024,0) [-98.304|98.28] "deg/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1PtchAccV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1PtchAcc : 4|13@0- (0.024,0) [-98.304|98.28] "deg/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 310 Inertial2_Accel1_FO: 8 _DOFIMU2_FO + SG_ MstrTrigSyncInrtl21 : 7|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2VertAccV : 34|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2VertAcc : 33|10@0- (0.0625,0) [-32|31.9375] "m/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2LonAccV : 2|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2LonAcc : 1|10@0- (0.0625,0) [-32|31.9375] "m/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2LatAccV : 18|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ Inertial2LatAcc : 17|10@0- (0.0625,0) [-32|31.9375] "m/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ IntlSnsr2AcelFm1Chksm : 50|11@0+ (1,0) [0|2047] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 304 Inertial1_Accel1_FO: 8 _DOFIMU1_FO + SG_ MstrTrigSyncInrtl11 : 7|5@0+ (1,0) [0|31] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1VertAccV : 34|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1VertAcc : 33|10@0- (0.0625,0) [-32|31.9375] "m/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1LonAccV : 2|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1LonAcc : 1|10@0- (0.0625,0) [-32|31.9375] "m/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1LatAccV : 18|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InrtlSnsr1LatAcc : 17|10@0- (0.0625,0) [-32|31.9375] "m/s^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ IntlSnsr1AcelFm1Chksm : 50|11@0+ (1,0) [0|2047] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 356 Map_Pos_Correction_FO: 4 EOCM2A_K1_FO + SG_ LongErrPstn : 7|8@0- (0.5,0) [-64|63.5] "m" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ LatErrPstn : 15|8@0- (0.5,0) [-64|63.5] "m" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ PstnErrChcksm : 18|11@0+ (1,0) [0|2047] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ PstnErrARC : 20|2@0+ (1,0) [0|3] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 354 Map_Retrans_Request_FO: 1 EOCM2A_K1_FO + SG_ HrznPrvdRstRq : 2|1@0+ (1,0) [0|1] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ ADASISRwDtMplxdCycCnt : 7|2@0+ (1,0) [0|3] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ ADASISMsgTypRetrans : 5|3@0+ (1,0) [0|7] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 352 Map_Path_Correction_FO: 6 EOCM2A_K1_FO + SG_ ExptNxtTrnstnDir : 37|3@0+ (1,0) [0|7] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ MstProbLnV : 15|1@0+ (1,0) [0|1] "" AMM_FO + SG_ MstProbLn : 14|5@0+ (1,0) [0|31] "" AMM_FO + SG_ PathCrtnChcksm : 34|11@0+ (1,0) [0|2047] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ PathCrtnARC : 4|2@0+ (1,0) [0|3] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ EgoLnCurvV : 2|1@0+ (1,0) [0|1] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ EgoLnCurv : 23|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m^2" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ VehLnStatV : 1|1@0+ (1,0) [0|1] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ VehLnStatConf : 6|2@0+ (1,0) [0|3] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ VehLnStat : 9|2@0+ (1,0) [0|3] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ ExptNxtTransDirV : 0|1@0+ (1,0) [0|1] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ ExptNxtTrnstnDirConf : 39|2@0+ (1,0) [0|3] "" AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 264 Inertial_Trigger_FO: 1 EOCM2A_K1_FO + SG_ InrtlSnsrMstrTrgrSync : 7|5@0+ (1,0) [0|31] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,_DOFIMU2_FO,_DOFIMU1_FO + +BO_ 1156 SSID_AMM_2_FO: 8 EOCM2A_K1_FO + SG_ WiFiSSIDDgts9to16_Mp : 7|64@0+ (1,0) [0|0] "" EOCM2B_K1_FO,AMM_FO + +BO_ 1155 SSID_AMM_1_FO: 8 EOCM2A_K1_FO + SG_ WiFiSSIDDgts1to8_Mp : 7|64@0+ (1,0) [0|0] "" EOCM2B_K1_FO,AMM_FO + +BO_ 1927 DTC_Triggered_787_FO: 7 DMS_FO + SG_ DTCI_CodeSupported_787 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_787 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_787 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_787 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_787 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_787 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_787 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_787 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_787 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_787 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_787 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_787 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_787 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_787 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_787 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_787 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_787 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_787 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_787 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_787 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1926 DTC_Triggered_786_FO: 7 AMM_FO + SG_ DTCI_CodeSupported_786 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_786 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_786 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_786 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_786 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_786 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_786 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_786 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_786 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_786 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_786 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_786 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_786 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_786 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_786 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_786 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_786 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_786 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_786 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_786 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1928 DTC_Triggered_788_FO: 7 _DOFIMU1_FO + SG_ DTCI_CodeSupported_788 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_788 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_788 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_788 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_788 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_788 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_788 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_788 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_788 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_788 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_788 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_788 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_788 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_788 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_788 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_788 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_788 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_788 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_788 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_788 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1929 DTC_Triggered_789_FO: 7 _DOFIMU2_FO + SG_ DTCI_CodeSupported_789 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_789 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_789 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_789 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_789 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_789 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_789 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_789 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_789 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_789 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_789 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_789 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_789 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_789 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_789 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_789 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_789 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_789 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_789 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_789 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1352 UUDT_Resp_From_6DOFIMU2_FO: 8 _DOFIMU2_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 588 USDT_Req_to_EOCM2B_K1_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" EOCM2B_K1_FO + +BO_ 1356 UUDT_Resp_From_EOCM2B_K1_FO: 8 EOCM2B_K1_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1612 USDT_Resp_From_EOCM2B_K1_FO: 8 EOCM2B_K1_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1616 USDT_Resp_From_EOCM2A_IMX6_FO: 8 EOCM2A_IMX6_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1360 UUDT_Resp_From_EOCM2A_IMX6_FO: 8 EOCM2A_IMX6_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 592 USDT_Req_to_EOCM2A_IMX6_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" EOCM2A_IMX6_FO + +BO_ 1610 USDT_Resp_From_EOCM2A_K1_FO: 8 EOCM2A_K1_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1354 UUDT_Resp_From_EOCM2A_K1_FO: 8 EOCM2A_K1_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 586 USDT_Req_to_EOCM2A_K1_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" EOCM2A_K1_FO + +BO_ 1925 DTC_Triggered_785_FO: 7 NVS_FO + SG_ DTCI_CodeSupported_785 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_785 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_785 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_785 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_785 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_785 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_785 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_785 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_785 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_785 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_785 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_785 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_785 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_785 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_785 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_785 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_785 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_785 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_785 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_785 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1859 VIN_Digits_10_to_17_FO: 8 EOCM_F_FO + SG_ VehIdNmDig10_17 : 7|64@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO + +BO_ 1857 VIN_Digits_2_to_9_FO: 8 EOCM_F_FO + SG_ VehIdNmDig2_9 : 7|64@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO + +BO_ 771 Outside_Air_Temperature_FO: 2 EOCM_F_FO + SG_ OtsAirTmpCrValV : 0|1@0+ (1,0) [0|1] "" NVS_FO + SG_ OtsAirTmpCrVal : 15|8@0+ (0.5,-40) [-40|87.5] "deg C" NVS_FO + +BO_ 777 Night_Vision_System_Ped_FO: 1 NVS_FO + SG_ NVSysStat : 3|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ NVSysPedWrnIndReq : 7|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ NVSysPedDetCsCrStVal : 5|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ NVSysPedDetCstStAvl : 0|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 607 USDT_Req_to_NVS_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" NVS_FO + +BO_ 1631 USDT_Resp_From_NVS_FO: 8 NVS_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1375 UUDT_Resp_From_NVS_FO: 8 NVS_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1540 ADAS_Position_FO: 8 AMM_FO + SG_ AdvDrAstMpLatOffst : 40|9@0+ (1,-256) [-256|255] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnIndx : 63|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnCnf : 61|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPsnIdxCrLn : 58|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnPthIndx : 46|6@0+ (1,0) [0|63] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnProb : 31|5@0+ (3.333,0) [0|103.323] "%" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnCycCnt : 26|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnAge : 24|9@0+ (5,0) [0|2555] "ms" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnRelHd : 23|8@0+ (1.417,0) [0|361.335] "deg" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnMsgTyp : 7|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + SG_ AdvDrAstMpPstnOfst : 4|13@0+ (1,0) [0|8191] "m" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO + +BO_ 1608 USDT_Resp_From_6DOFIMU2_FO: 8 _DOFIMU2_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 871 LGT_ObjectDetect_Info_8_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk8 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk8 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk8 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk8 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev8 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev8 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev8 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk8 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk8 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk8 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 870 LGT_ObjectDetect_Info_7_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk7 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk7 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk7 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk7 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev7 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev7 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev7 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk7 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk7 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk7 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 869 LGT_ObjectDetect_Info_6_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk6 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk6 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk6 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk6 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev6 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev6 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev6 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk6 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk6 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk6 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 868 LGT_ObjectDetect_Info_5_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk5 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk5 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk5 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk5 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev5 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev5 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev5 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk5 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk5 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk5 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 867 LGT_ObjectDetect_Info_4_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk4 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk4 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk4 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk4 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev4 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev4 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev4 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk4 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk4 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk4 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 866 LGT_ObjectDetect_Info_3_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk3 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk3 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk3 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk3 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev3 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev3 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev3 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk3 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk3 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk3 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 865 LGT_ObjectDetect_Info_2_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk2 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk2 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk2 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk2 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev2 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev2 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev2 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk2 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBObjDirTrk2 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk2 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 864 LGT_ObjectDetect_Info_1_FO: 8 VIS2_FO + SG_ GFHBFwVsnWidthTrk1 : 62|7@0+ (0.1,0) [0|12.7] "deg" EOCM_F_FO + SG_ GFHBFwVsnVertPosTrk1 : 53|6@0+ (0.25,-3) [-3|12.75] "deg" EOCM_F_FO + SG_ GFHBFwVsnRelLaneTrk1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnAzmthRtTrk1 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ GFHBFwVsnCnfdncTrk1 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnRngTrkRev1 : 16|12@0+ (0.2,0) [0|819] "m" EOCM_F_FO + SG_ GFHBFwVsnAzmthTrkRev1 : 10|10@0- (0.05,0) [-25.6|25.55] "deg" EOCM_F_FO + SG_ GFHBFVsnObjTypTrkRev1 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ GFHBObjDirTrk1 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ GFHBFwVsnMesStatTrk1 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ GFHBFwVsnObjIDTrk1 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1915 DTC_Triggered_77B_FO: 7 VIS_FO + SG_ DTCI_DTCFaultType_77B : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_CodeSupported_77B : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_77B : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_77B : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_77B : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_77B : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_77B : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_77B : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_77B : 47|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_77B : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_77B : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_77B : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_77B : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_77B : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_77B : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_77B : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_77B : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_77B : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_77B : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_77B : 7|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1923 DTC_Triggered_783_FO: 7 RSRR_FO + SG_ DTCI_WrnIndRqdSt_783 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_783 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_783 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_783 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_783 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_783 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCTriggered_783 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCSource_783 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_783 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCFaultType_783 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFailType_783 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_CurrentStatus_783 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CodeSupported_783 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_783 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_783 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_783 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_783 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_783 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_783 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_783 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1924 DTC_Triggered_784_FO: 7 RRSRR_FO + SG_ DTCI_HistStat_784 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_784 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_784 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_784 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_784 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_784 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_784 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_784 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_784 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_784 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_784 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_784 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_784 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CodeSupported_784 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CurrentStatus_784 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCFailType_784 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFaultType_784 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_784 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCSource_784 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCTriggered_784 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1922 DTC_Triggered_782_FO: 7 RFSRR_FO + SG_ DTCI_WrnIndRqdSt_782 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_782 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_782 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_782 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_782 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_782 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_782 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_782 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_782 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_782 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_782 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_782 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_782 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCTriggered_782 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCSource_782 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_782 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCFaultType_782 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFailType_782 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_CurrentStatus_782 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_CodeSupported_782 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1920 DTC_Triggered_780_FO: 7 LRR_FO + SG_ DTCI_CurrentStatus_780 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_780 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_780 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_780 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_780 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_780 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_780 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_780 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_780 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_780 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_780 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_780 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_780 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_780 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCTriggered_780 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCSource_780 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_780 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCFaultType_780 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFailType_780 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_CodeSupported_780 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1921 DTC_Triggered_781_FO: 7 LFSRR_FO + SG_ DTCI_CurrentStatus_781 : 41|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_WrnIndRqdSt_781 : 47|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused7_781 : 1|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused6_781 : 2|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused5_781 : 3|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused4_781 : 4|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused3_781 : 5|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused2_781 : 6|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCIUnused1_781 : 7|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdPwrUpSt_781 : 45|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstNPsdCdClrdSt_781 : 42|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldPwrUpSt_781 : 46|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_TstFldCdClrdStat_781 : 43|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_HistStat_781 : 44|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCTriggered_781 : 0|1@0+ (1,0) [0|1] "" TestTool_FO + SG_ DTCI_DTCSource_781 : 15|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCNumber_781 : 23|16@0+ (1,0) [0|65535] "" TestTool_FO + SG_ DTCI_DTCFaultType_781 : 55|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_DTCFailType_781 : 39|8@0+ (1,0) [0|255] "" TestTool_FO + SG_ DTCI_CodeSupported_781 : 40|1@0+ (1,0) [0|1] "" TestTool_FO + +BO_ 1034 Curvature_Right_Line_FO: 7 VIS2_FO + SG_ CRL_Cnfdnc : 50|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ CRL_ViewRng : 33|15@0+ (0.0039064,0) [0|128.0010088] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ CRL_CoefdA : 17|16@0- (3.6622E-009,0) [-0.0001200029696|0.0001199993074] "1/m^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ CRL_CoefA : 1|16@0- (6.1036E-007,0) [-0.02000027648|0.01999966612] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 1033 Curvature_Left_Line_FO: 7 VIS2_FO + SG_ CLL_Cnfdnc : 50|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ CLL_ViewRng : 33|15@0+ (0.0039064,0) [0|128.0010088] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ CLL_CoefdA : 17|16@0- (3.6622E-009,0) [-0.0001200029696|0.0001199993074] "1/m^2" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ CLL_CoefA : 1|16@0- (6.1036E-007,0) [-0.02000027648|0.01999966612] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + +BO_ 1365 UUDT_Resp_From_VIS2_FO: 8 VIS2_FO + SG_ DgnInf_OBJ555 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1621 USDT_Resp_From_VIS2_FO: 8 VIS2_FO + SG_ DgnInf_OBJ655 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1094 F_Vision_Obj_Track_12: 8 VIS2_FO + SG_ FwdVsnObjTypTr12Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk12Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk12Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FVisionWidthTrk12 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FVisionMeasStatTrk12 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk12 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisionRelLaneTrk12 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk12 : 34|11@0- (0.125,0) [-128|127.875] "deg/sec" EOCM_F_FO + SG_ FVisionConfTrk12 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ ObjDirTrk12 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk12 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk12 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1093 F_Vision_Obj_Track_11: 8 VIS2_FO + SG_ FwdVsnObjTypTr11Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk11Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk11Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FVisionWidthTrk11 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FVisionMeasStatTrk11 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk11 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisionRelLaneTrk11 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk11 : 34|11@0- (0.125,0) [-128|127.875] "deg/sec" EOCM_F_FO + SG_ FVisionConfTrk11 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ ObjDirTrk11 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk11 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk11 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1100 F_Vision_Obj_Track_12_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT12Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk12 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk12 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk12 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk12 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr12 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk12 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo12 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1099 F_Vision_Obj_Track_11_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT11Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk11 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk11 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk11 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk11 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr11 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk11 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo11 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1098 F_Vision_Obj_Track_10_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT10Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk10 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk10 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk10 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk10 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr10 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk10 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo10 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1097 F_Vision_Obj_Track_9_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT9Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk9 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk9 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk9 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk9 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr9 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk9 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo9 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1096 F_Vision_Obj_Track_8_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT8Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk8 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk8 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk8 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk8 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr8 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk8 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo8 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1095 F_Vision_Obj_Track_7_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT7Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk7 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk7 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk7 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk7 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr7 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk7 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo7 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 863 F_Vision_GFHB_Data_FO: 8 VIS2_FO + SG_ RgDtLgtSrcHrtAngl : 49|10@0- (0.04,0) [-20.48|20.44] "deg" EOCM_F_FO + SG_ RgDtLgtSrcHrtAngVcty : 55|6@0- (1,0) [-32|31] "deg/sec" EOCM_F_FO + SG_ LfDtLgtSrcHrtAngl : 33|10@0- (0.04,0) [-20.48|20.44] "deg" EOCM_F_FO + SG_ LfDtLgtSrcHrtAnVcty : 39|6@0- (1,0) [-32|31] "deg/sec" EOCM_F_FO + SG_ AdvWthrStat : 25|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ DtctdLghtSrcDstnc : 22|7@0+ (10,0) [0|1270] "m" EOCM_F_FO + SG_ DtctdLghtSrcVrtclAngl : 1|10@0- (0.04,0) [-20.48|20.44] "deg" EOCM_F_FO + SG_ IntLghtRngAct : 2|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ DtctdLghtSrcDstncV : 3|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ TwnDtctnSts : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ DtctdLghtSrcDrvngDrctn : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 862 LGT_ControlHighBeamGlare_FO: 2 VIS2_FO + SG_ FwdCamSysOpStat : 10|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ EnvIllum : 2|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RdTyp : 5|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ AutoHgBmSts : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1068 F_Vision_Obj_Track_6_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT6Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk6 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk6 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk6 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk6 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr6 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk6 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo6 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1067 F_Vision_Obj_Track_5_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT5Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk5 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk5 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk5 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk5 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr5 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk5 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo5 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1066 F_Vision_Obj_Track_4_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT4Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk4 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk4 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk4 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk4 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr4 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk4 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo4 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1065 F_Vision_Obj_Track_3_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT3Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk3 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk3 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk3 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk3 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr3 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk3 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo3 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1064 F_Vision_Obj_Track_2_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT2Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk2 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk2 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk2 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk2 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr2 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk2 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo2 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1063 F_Vision_Obj_Track_1_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT1Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk1 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FwdVsnObjAgeTrk1 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk1 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk1 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk1 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr1 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo1 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1151 Long_Range_Radar_add_Info_5_FO: 8 LRR_FO + SG_ FrtRdrRdEdgLtLatRdEdgDst : 63|8@0- (0.1,0) [-12.8|12.7] "m/m" EOCM_F_FO + SG_ FrtRdrRdEdgLtCrvtPrvDst : 5|4@0+ (10,0) [0|150] "" EOCM_F_FO + SG_ FrtRdrRdEdgLtTanHdgAng : 15|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM_F_FO + SG_ FrtRdrRdEdgLtCrvtV : 48|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtRdrRdEdgLtCrvtGradV : 0|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtRdrRdEdgLtCrvtGrad : 39|16@0- (5.96E-008,0) [-0.0019529728|0.0019529132] "1/(m*sec)" EOCM_F_FO + SG_ FrtRdrRdEdgLtCrvtConf : 55|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM_F_FO + SG_ FrtRdrRdEdgLtCrvt : 23|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m" EOCM_F_FO + SG_ FrtRdrRdEdgLtTanHdgAngV : 1|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAddInfo5BurstID : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1150 Long_Range_Radar_add_Info_4_FO: 8 LRR_FO + SG_ FrtRdrRdEdgRtLatRdEdgDst : 63|8@0- (0.1,0) [-12.8|12.7] "m/m" EOCM_F_FO + SG_ FrtRdrRdEdgRtCrvtPrvDst : 5|4@0+ (10,0) [0|150] "" EOCM_F_FO + SG_ FrtRdrRdEdgRtTanHdgAngV : 1|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtRdrRdEdgRtTanHdgAng : 15|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM_F_FO + SG_ FrtRdrRdEdgRtCrvtV : 48|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtRdrRdEdgRtCrvtGradV : 0|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtRdrRdEdgRtCrvtGrad : 39|16@0- (5.96E-008,0) [-0.0019529728|0.0019529132] "1/(m*sec)" EOCM_F_FO + SG_ FrtRdrRdEdgRtCrvtConf : 55|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM_F_FO + SG_ FrtRdrRdEdgRtCrvt : 23|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m" EOCM_F_FO + SG_ FLRRAddInfo4BurstID : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1088 F_Vision_Obj_Header_2: 8 VIS2_FO + SG_ FrntVsnInPthVehBrkNwSt : 35|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FrntVsnClostPedBrkNwSt : 39|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FrntVsnClostPedObjID : 29|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FrntVsnClostPedAlrtNwFlg : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrntVsnClostPedNotftnFlg : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrntVsnInPthVehAlrtNwFlg : 2|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnVldTgtNum2 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FrtVsnTmStmp2V : 31|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnTmStmp2 : 10|11@0+ (1,0) [0|2047] "" EOCM_F_FO + SG_ FrtVsnRollCnt2 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FrtVsnBrstChksum2 : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + +BO_ 854 F_Vision_Environment_7: 3 VIS2_FO + SG_ FwdVsnCnstrctAreaDst : 13|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnCnstrctZnDet : 15|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnEgoVehLnPos : 17|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnRdTypDet : 9|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnTunnlDetd : 23|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnTunnlDst : 21|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBrstID5 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 853 F_Vision_Environment_6: 8 VIS2_FO + SG_ LnMrkg4LnSnsLnHdngTngtV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnHdngTngt : 23|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnDstV : 56|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnDst : 15|8@0- (0.1,0) [-12.8|12.7] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvtV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvtGradV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvtGrad : 47|16@0- (5.96E-008,0) [-0.0019529728|0.0019529132] "1/(m*sec)" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvt : 31|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnQltyConfLvl : 63|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMrkrTyp : 4|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBrstID4 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 852 F_Vision_Environment_5: 8 VIS2_FO + SG_ LnMrkg3LnSnsLnHdngTngtV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnHdngTngt : 23|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnDstV : 56|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnDst : 15|8@0- (0.1,0) [-12.8|12.7] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvtV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvtGradV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvtGrad : 47|16@0- (5.96E-008,0) [-0.0019529728|0.0019529132] "1/(m*sec)" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvt : 31|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnQltyConfLvl : 63|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMrkrTyp : 4|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBrstID3 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 602 USDT_Req_to_RRSRR: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" RRSRR_FO + +BO_ 1626 USDT_Resp_From_RRSRR: 8 RRSRR_FO + SG_ DgnInf_OBJ65A : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1370 UUDT_Resp_From_RRSRR: 8 RRSRR_FO + SG_ DgnInf_OBJ55A : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1536 RR_SRR_Trace_data: 8 RRSRR_FO + SG_ RRSRRYear : 7|8@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ RRSRRSerialNmbr : 39|32@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ RRSRRJulianDate : 15|24@0+ (1,0) [0|0] "" EOCM_F_FO + +BO_ 1210 RR_SRR_Object_Track10: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth10 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate10 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange10 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange10 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID10 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation10 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus10 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp10 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth10 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID10 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1209 RR_SRR_Object_Track9: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth9 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate9 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange9 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange9 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID9 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation9 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus9 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp9 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth9 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID9 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1208 RR_SRR_Object_Track8: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth8 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate8 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange8 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange8 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID8 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation8 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp8 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth8 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID8 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1207 RR_SRR_Object_Track7: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth7 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate7 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange7 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange7 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID7 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation7 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp7 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth7 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID7 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1206 RR_SRR_Object_Track6: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth6 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate6 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange6 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange6 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID6 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation6 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp6 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth6 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID6 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1205 RR_SRR_Object_Track5: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth5 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate5 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange5 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange5 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID5 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation5 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp5 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth5 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID5 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 262 LHT_AutoHighBeamAssistStatus_FO: 5 EOCM_F_FO + SG_ NtVsnSysEnbld : 6|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO + SG_ VehMovState : 5|3@0+ (1,0) [0|7] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO + SG_ NVSysPedDetCstReq : 2|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO + SG_ StrWhAngV : 8|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO,VIS_FO + SG_ StrWhAngMsk : 9|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ StrWhAng : 23|16@0- (0.0625,0) [-2048|2047.9375] "deg" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO,VIS_FO + SG_ RtTrnLmpAtv : 13|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ MpDataAvlbl : 0|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ LftTrnLmpAtv : 11|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ HdlmpBmSelectStat : 33|2@0+ (1,0) [0|3] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ BldUpArDet : 14|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ FrFogLmpsAct : 15|1@0+ (1,0) [0|1] "" EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,NVS_FO,VIS_FO + +BO_ 309 LHT_CameraObjConfirmation_FO: 1 VIS_FO + SG_ HiBmRecmnd : 1|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ CtLghtDet : 0|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 2034 CCP_Data_Transmission_Object_FO: 8 VIS2_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 2032 CCP_Command_Receive_Object_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" VIS2_FO + +BO_ 1362 F_Vis_Obj_Conf_CPS_1B: 8 EOCM_F_FO + SG_ FObjConfCPSTrkObjectIDB : 7|6@0+ (1,0) [0|63] "" VIS_FO + SG_ CPSVisConfLonPos1 : 20|12@0- (0.125,0) [-256|255.875] "m" VIS_FO + SG_ CPSVisConfLatPos1 : 15|10@0- (0.125,0) [-64|63.875] "m" VIS_FO + SG_ CPSVisConfChecksum : 50|11@0+ (1,0) [0|2047] "" VIS_FO + SG_ FObjConfCPSTrkRangeRate : 45|11@0- (0.125,0) [-128|127.875] "m/s" VIS_FO + SG_ CPSConfTimeStamp : 24|11@0+ (1,0) [0|2047] "ms" VIS_FO + SG_ CPSConfTimeStampV : 21|1@0+ (1,0) [0|1] "" VIS_FO + SG_ FObjConfCPSRollingTrkCnt : 1|2@0+ (1,0) [0|3] "" VIS_FO + +BO_ 1413 TOS_ACC_IDS: 5 EOCM_F_FO + SG_ TOS_ACC_IDSRollCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ TOS_ACC_IDSFuncState : 5|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ TOS_ACC_ID1 : 3|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ TOS_ACC_ID2 : 13|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ TOS_ACC_ID3 : 23|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ TOS_ACC_ID4 : 17|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ TOS_ACC_ID5 : 27|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ TOS_ACC_ID6 : 37|6@0+ (1,0) [0|63] "" Dummy_FO + +BO_ 1412 F_ACC_Target: 8 EOCM_F_FO + SG_ FACCTOSRollCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FACCTOSFuncState : 5|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FACCTOSLongPos : 3|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FACCTOSLatPos : 23|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FACCTOSMeasStat : 28|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FACCTOSLongVel : 26|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FACCTOSTrgtDecelFlg : 47|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FACCTOSDynProp : 46|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FACCTOSLatVel : 42|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FACCTOSRelLane : 63|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FACCTOSHiThrtID : 61|6@0+ (1,0) [0|63] "" Dummy_FO + +BO_ 1409 F_CPS_TOS_B: 8 EOCM_F_FO + SG_ CPSTOSObjType : 7|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ CPSTOSHiThrtPriNo : 60|5@0+ (1,0) [0|31] "" Dummy_FO + SG_ CPSTOSRelLongAcc : 53|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ CPSTOSConfAsmt : 21|12@0+ (1,0) [0|4095] "" Dummy_FO + SG_ CPSTOSNumCycTrkd : 4|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ CPSTOSTimeToColl : 1|12@0+ (0.025,0) [0|102.375] "s" Dummy_FO + SG_ CPSTOSClosestInPthVehRng : 47|10@0+ (0.25,0) [0|255.75] "m" Dummy_FO + SG_ CPSTOSClosestInPthObID : 37|6@0+ (1,0) [0|63] "m" Dummy_FO + SG_ CPSTOSMeasStat : 39|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ CPSTOSFuncState : 25|2@0+ (1,0) [0|3] "" Dummy_FO + +BO_ 1408 F_CPS_TOS_A: 8 EOCM_F_FO + SG_ CPSTOSLongPos : 7|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ CPSTOSLatPos : 11|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ CPSTOSLongVel : 16|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ CPSTOSDynProp : 37|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ CPSTOSLatVel : 34|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ CPSTOSARelLane : 63|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ CPSTOSHiThrtID : 61|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ CPSTOSHighestThreatObAsmt : 55|8@0+ (1,0) [0|255] "" Dummy_FO + +BO_ 1344 FLPEstimate: 8 EOCM_F_FO + SG_ FLPRollCount : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ NewLaneIndex : 5|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ VehPathInOK : 3|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LaneSnsInOK : 2|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ MapInOK : 1|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FWDObjFusInOK : 0|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LngthFrstSeg : 15|4@0+ (10,0) [0|150] "m" Dummy_FO + SG_ LngthScndSeg : 11|4@0+ (10,0) [0|150] "m" Dummy_FO + SG_ CurvFrstSeg : 23|13@0- (5E-005,0) [-0.2048|0.20475] "1/m" Dummy_FO + SG_ CurvScndSeg : 26|3@0- (0.001,0) [-0.004|0.003] "1/m" Dummy_FO + SG_ OffstLaneCntr : 39|8@0- (0.05,0) [-6.4|6.35] "m" Dummy_FO + SG_ TngntLaneHead : 47|8@0- (0.002,0) [-0.256|0.254] "m/m" Dummy_FO + SG_ LaneWidth : 55|8@0+ (0.05,0) [0|12.75] "m" Dummy_FO + SG_ FLPDataTimeStampV : 63|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FLPDataTimeStamp : 62|7@0+ (16,0) [0|2032] "ms" Dummy_FO + +BO_ 770 F_Fwd_Collision_Alert: 8 EOCM_F_FO + SG_ Vpath_Accel : 51|11@0- (0.125,0) [-128|127.875] "m/s^2" NVS_FO,Dummy_FO + SG_ FCA_Ra : 7|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FCA_Range : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FCA_AlertLevel : 44|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FCA_Alert_Sup : 31|16@0+ (1,0) [0|65535] "" Dummy_FO + SG_ FCAStatus : 46|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FCA_VehAhead : 47|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FCA_CPS_Alert : 42|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FCAChime : 41|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FCADiagOK : 40|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ NBSMS_Alert : 55|1@0+ (1,0) [0|1] "" Dummy_FO + +BO_ 1601 USDT_Resp_From_VIS: 8 VIS_FO + SG_ DgnInf_OBJ641 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1606 USDT_Resp_From_RFSRR: 8 RFSRR_FO + SG_ DgnInf_OBJ646 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1603 USDT_Resp_From_LFSRR: 8 LFSRR_FO + SG_ DgnInf_OBJ643 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1602 USDT_Resp_From_LRR: 8 LRR_FO + SG_ DgnInf_OBJ642 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1625 USDT_Resp_From_RSRR: 8 RSRR_FO + SG_ DgnInf_OBJ644 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1611 USDT_Resp_From_FEOCM_FO: 8 EOCM_F_FO + SG_ DgnInf_OBJ64B : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 768 F_Smgr_Vehicle_Motion: 8 EOCM_F_FO + SG_ SmgrMotRollAngle : 44|10@0- (0.1,0) [-51.2|51.1] "deg" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotRollAngleV : 0|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotChecksum : 50|11@0+ (1,0) [0|2047] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotPitchAngle : 39|11@0- (0.1,0) [-102.4|102.3] "deg" CIPM_FO,NVS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotPitchAngleV : 1|1@0+ (1,0) [0|1] "" CIPM_FO,NVS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotLongSpeedV : 2|1@0+ (1,0) [0|1] " " CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotLongSpeed : 18|11@0- (0.1,0) [-102.4|102.3] "m/s" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotYawRate : 14|12@0- (0.05,0) [-102.4|102.35] "deg/s" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotYawRateV : 15|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + SG_ SmgrMotRollingCnt : 4|2@0+ (1,0) [0|3] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS_FO + +BO_ 1350 UUDT_Resp_From_RFSRR: 8 RFSRR_FO + SG_ DgnInf_OBJ546 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1369 UUDT_Resp_From_RSRR: 8 RSRR_FO + SG_ DgnInf_OBJ544 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1347 UUDT_Resp_From_LFSRR: 8 LFSRR_FO + SG_ DgnInf_OBJ543 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1346 UUDT_Resp_From_LRR: 8 LRR_FO + SG_ DgnInf_OBJ542 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1345 UUDT_Resp_From_VIS: 8 VIS_FO + SG_ DgnInf_OBJ541 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 579 USDT_Req_to_LFSRR: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" LFSRR_FO + +BO_ 577 USDT_Req_to_VIS: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" VIS_FO + +BO_ 578 USDT_Req_to_LRR: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" LRR_FO + +BO_ 582 USDT_Req_to_RFSRR: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" RFSRR_FO + +BO_ 601 USDT_Req_to_RSRR: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" RSRR_FO + +BO_ 1355 UUDT_Resp_From_FEOCM_FO: 8 EOCM_F_FO + SG_ DgnInf_OBJ54B : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 587 USDT_Req_to_FEOCM_obj: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" EOCM2A_K2_FO,EOCM_F_FO + +BO_ 784 Body_Info_FOB: 6 EOCM_F_FO + SG_ StrgColUpDwnPos : 39|8@0+ (1,0) [0|255] "" DMS_FO + SG_ CPMAPINFO4 : 47|1@0+ (1,0) [0|1] "" DMS_FO + SG_ StrgColInOutPos : 31|8@0+ (1,0) [0|255] "" DMS_FO + SG_ StrgColCommsFlt : 19|2@0+ (1,0) [0|3] "" DMS_FO + SG_ DrDoorOpenSwActV : 16|1@0+ (1,0) [0|1] "" DMS_FO + SG_ DrDoorOpenSwAct : 17|1@0+ (1,0) [0|1] "" DMS_FO + SG_ DrvWndPosStat : 22|3@0+ (1,0) [0|7] "" CIPM_FO,DMS_FO,VIS2_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ InterLghtStat : 23|1@0+ (1,0) [0|1] "" CIPM_FO,DMS_FO,VIS2_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ DrvrHndsOnWhlZn3 : 13|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,DMS_FO,VIS2_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ DrvrHndsOnWhlZn2 : 14|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,VIS2_FO + SG_ DrvrHndsOnWhlZn1 : 15|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,VIS2_FO + SG_ WSWshSwAtv : 11|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,VIS_FO,VIS2_FO + SG_ SysPwrMdV : 8|1@0+ (1,0) [0|1] "" NVS_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO,LRSRR_FO,CIPM_FO,_DOFIMU2_FO,_DOFIMU1_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,VIS2_FO + SG_ SysPwrMd : 10|2@0+ (1,0) [0|3] "" NVS_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO,LRSRR_FO,CIPM_FO,_DOFIMU2_FO,_DOFIMU1_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,VIS2_FO + SG_ WSWprAct : 2|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ RtLwBmFld : 4|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ OtsdAmbtLtLvlStatV : 5|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ OtsdAmbtLtLvlStat : 7|2@0+ (1,0) [0|3] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ LowBmAct : 1|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ LftLwBmFld : 3|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ HighBmAct : 0|1@0+ (1,0) [0|1] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,DMS_FO,AMM_FO,NVS_FO,VIS_FO,VIS2_FO + SG_ TrStLgMdAtv : 12|1@0+ (1,0) [0|1] "" CIPM_FO,NVS_FO,RRSRR_FO,LRSRR_FO,_DOFIMU2_FO,_DOFIMU1_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,LRR_FO,RFSRR_FO,LFSRR_FO,RSRR_FO,VIS_FO,VIS2_FO + +BO_ 1539 RF_SRR_Trace_Data: 8 RFSRR_FO + SG_ RFSRRYear : 7|8@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ RFSRRSerialNmbr : 39|32@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ RFSRRJulianDate : 15|24@0+ (1,0) [0|0] "" EOCM_F_FO + +BO_ 776 F_Vehicle_Path_Data_2: 7 EOCM_F_FO + SG_ Vpath_Data2ModeInfo : 44|2@0+ (1,0) [0|3] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath2_Checksum : 42|11@0+ (1,0) [0|2047] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RFSRR_FO,LFSRR_FO,RSRR_FO,LRR_FO + SG_ Vpath_Data2RollCnt : 46|2@0+ (1,0) [0|3] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2YawRateV : 2|1@0+ (1,0) [0|1] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,NVS_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2LongVelV : 1|1@0+ (1,0) [0|1] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,NVS_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2LatVelV : 47|1@0+ (1,0) [0|1] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2TravlDirctn : 4|2@0+ (1,0) [0|3] "" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2LongVel : 15|12@0- (0.0625,0) [-128|127.9375] "m/s" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,NVS_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2YawRate : 19|12@0- (0.0625,0) [-128|127.9375] "deg/s" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,NVS_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_Data2LatVel : 39|8@0- (0.05,0) [-6.4|6.35] "m/s" CIPM_FO,DMS_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + +BO_ 161 F_Master_Time_Sync: 7 EOCM_F_FO + SG_ FTimeSyncMstrChksm : 35|12@0+ (1,0) [0|4095] "" AMM_FO,CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ FTimeSyncMstrClock : 7|32@0+ (1,0) [0|4294967295] "ms" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ SensorModeCmdLRR : 39|3@0+ (1,0) [0|7] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ SensorModeCmdSRR : 50|3@0+ (1,0) [0|7] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ SensorModeCmdFCamera : 53|3@0+ (1,0) [0|7] "" CIPM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ FTimeSyncMstrClockV : 36|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,LRR_FO,RFSRR_FO,LFSRR_FO + +BO_ 774 F_Vehicle_Path_Estimate: 8 EOCM_F_FO + SG_ Vpath_RollingCount : 7|2@0+ (1,0) [0|3] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_TrnCtrLngOfstV : 1|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,LRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LFSRR_FO + SG_ Vpath_Checksum : 50|11@0+ (1,0) [0|2047] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_TrnCtrLngOfst : 15|8@0- (0.1,0) [-12.8|12.7] "m" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,LRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LFSRR_FO + SG_ Vpath_TrnCtrLatOfst : 21|14@0- (1,0) [-8192|8191] "m" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,LRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LFSRR_FO + SG_ Vpath_Curvature : 39|16@0- (1E-005,0) [-0.32768|0.32767] "1/m" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,RSRR_FO,RFSRR_FO,LRR_FO,LFSRR_FO + SG_ Vpath_CurvatureV : 0|1@0+ (1,0) [0|1] "" CIPM_FO,AMM_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,VIS2_FO,RRSRR_FO,VIS_FO,LRR_FO,RSRR_FO,RFSRR_FO,LFSRR_FO + +BO_ 848 F_Vision_Environment: 8 VIS_FO + SG_ FwdVsnEnvIllum : 37|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnRtV : 1|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnRt : 31|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnChngStatus : 39|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseRollingCount : 7|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseSystemOK : 4|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSnsLLnPosValid : 2|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSenseDistToLLnEdge : 14|7@0+ (0.05,0) [0|6.35] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsRLnPosValid : 0|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsDistToRLnEdge : 22|7@0+ (0.05,0) [0|6.35] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseTimeStampV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseTimeStamp : 34|11@0+ (1,0) [0|2047] "ms" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseSystemOKV : 3|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 849 F_Vision_Environment_2: 8 VIS_FO + SG_ LnSnsLatVRelToRgtMrkg : 23|8@0- (0.02,0) [-2.56|2.54] "m/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ LnSnsRtLnMrkgTypChgDst : 61|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntRtV : 63|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnMrkgWdthRt : 62|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsRtAnchrLn : 57|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtAnchrLn : 56|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrRghtV : 0|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrRght : 47|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntRt : 31|16@0- (5.96E-008,0) [-0.0019529728|0.0019529132] "1/rad/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstID : 2|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLatVRelToLftMrkg : 15|8@0- (0.02,0) [-2.56|2.54] "m/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 1184 R_SRR_Object_Header: 8 RSRR_FO + SG_ RSRRNumValidTargets : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ RSrrRollingCnt : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSRRModeCmdFdbk : 4|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTimeStampV : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSrrTimeStamp : 10|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ RSrrBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + SG_ RSRRSnstvFltPrsntInt : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRPlntAlgnInProc : 37|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRMsalgnYawRt : 47|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRMsalgnYawLt : 46|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRMsalgnRllRt : 35|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRMsalgnRllLt : 34|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRMsalgnPtchUp : 32|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRMsalgnPtchDn : 33|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRInitDiagCmplt : 40|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRHWFltPrsntInt : 25|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRExtIntrfrnc : 36|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRDiagSpare : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRCANSgnlSpvFld : 29|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRCANRxErr : 28|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRCANIDAddrsUnsbl : 27|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRAntTngFltPrsnt : 26|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRAmbTmpOutRngLw : 42|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRAmbTmpOutRngHi : 41|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRAlgnFltPrsnt : 39|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRVltgOutRngLo : 44|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRVltgOutRngHi : 43|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRSvcAlgnInPrcs : 38|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RSRRSnsrBlckd : 45|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1185 R_SRR_Object_Track1: 8 RSRR_FO + SG_ RSrrBurstID1 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange1 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate1 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth1 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID1 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation1 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp1 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange1 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth1 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1186 R_SRR_Object_Track2: 8 RSRR_FO + SG_ RSrrBurstID2 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange2 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate2 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth2 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID2 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation2 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp2 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange2 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth2 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1187 R_SRR_Object_Track3: 8 RSRR_FO + SG_ RSrrBurstID3 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange3 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate3 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth3 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID3 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation3 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp3 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange3 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth3 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1188 R_SRR_Object_Track4: 8 RSRR_FO + SG_ RSrrBurstID4 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange4 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate4 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth4 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID4 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation4 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp4 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange4 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth4 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1189 R_SRR_Object_Track5: 8 RSRR_FO + SG_ RSrrBurstID5 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange5 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate5 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth5 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID5 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation5 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp5 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange5 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth5 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1190 R_SRR_Object_Track6: 8 RSRR_FO + SG_ RSrrBurstID6 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange6 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate6 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth6 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID6 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation6 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp6 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange6 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth6 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1191 R_SRR_Object_Track7: 8 RSRR_FO + SG_ RSrrBurstID7 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange7 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate7 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth7 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID7 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation7 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp7 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange7 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth7 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1192 R_SRR_Object_Track8: 8 RSRR_FO + SG_ RSrrBurstID8 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange8 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate8 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth8 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID8 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation8 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp8 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange8 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth8 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1193 R_SRR_Object_Track9: 8 RSRR_FO + SG_ RSrrBurstID9 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange9 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate9 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth9 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID9 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation9 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp9 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus9 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange9 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth9 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1194 R_SRR_Object_Track10: 8 RSRR_FO + SG_ RSrrBurstID10 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkRange10 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RSrrTrkRRate10 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RSrrTrkAzimuth10 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RSrrTrkObjID10 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RSrrTrkObjElevation10 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkDynamProp10 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RSrrTrkMeasStatus10 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RSrrTrkObsRange10 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RSrrTrkRawAzimuth10 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1410 RVB_TVR_Debug: 6 EOCM_F_FO + SG_ VBBrkRqActv : 7|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ PATOSTTC : 37|12@0+ (0.025,0) [0|102.375] "s" Dummy_FO + SG_ BWTOSObjID : 27|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ BWTOSLonPstn : 23|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ VBSwInd : 10|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ VBBrkCtrlSt : 15|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ BrkPlsRqst : 6|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VBOpSt : 12|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ VBAccelOvrrd : 0|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VBUnavail : 1|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VBFld : 2|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VBDisbld : 3|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VBEnbl : 4|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VBBrkPrfReq : 5|1@0+ (1,0) [0|1] "" Dummy_FO + +BO_ 1216 LF_SRR_Object_Header: 8 LFSRR_FO + SG_ LFSRRNumValidTargets : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ LFSrrRollingCnt : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSRRModeCmdFdbk : 4|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTimeStampV : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSrrTimeStamp : 10|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ LFSrrBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + SG_ LFSRRVltgOutRngLo : 44|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRVltgOutRngHi : 43|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRSvcAlgnInPrcs : 38|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRSnsrBlckd : 45|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRSnstvFltPrsntInt : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRPlntAlgnInProc : 37|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRMsalgnYawRt : 47|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRMsalgnYawLt : 46|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRMsalgnRllRt : 35|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRMsalgnRllLt : 34|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRMsalgnPtchUp : 32|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRMsalgnPtchDn : 33|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRInitDiagCmplt : 40|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRHWFltPrsntInt : 25|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRExtIntrfrnc : 36|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRDiagSpare : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRCANSgnlSpvFld : 29|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRCANRxErr : 28|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRCANIDAddrsUnsbl : 27|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRAntTngFltPrsnt : 26|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRAmbTmpOutRngLw : 42|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRAmbTmpOutRngHi : 41|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ LFSRRAlgnFltPrsnt : 39|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1217 LF_SRR_Object_Track1: 8 LFSRR_FO + SG_ LFSrrBurstID1 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange1 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate1 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth1 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID1 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation1 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp1 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkObsRange1 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth1 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1218 LF_SRR_Object_Track2: 8 LFSRR_FO + SG_ LFSrrBurstID2 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange2 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate2 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth2 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID2 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation2 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp2 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkObsRange2 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth2 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1219 LF_SRR_Object_Track3: 8 LFSRR_FO + SG_ LFSrrBurstID3 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange3 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate3 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth3 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID3 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation3 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp3 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkObsRange3 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth3 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1220 LF_SRR_Object_Track4: 8 LFSRR_FO + SG_ LFSrrBurstID4 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange4 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate4 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkObsRange4 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrTrkAzimuth4 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID4 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation4 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp4 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth4 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1221 LF_SRR_Object_Track5: 8 LFSRR_FO + SG_ LFSrrTrkObsRange5 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrBurstID5 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange5 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate5 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth5 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID5 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation5 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp5 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth5 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1222 LF_SRR_Object_Track6: 8 LFSRR_FO + SG_ LFSrrTrkObsRange6 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrBurstID6 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange6 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate6 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth6 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID6 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation6 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp6 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth6 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1223 LF_SRR_Object_Track7: 8 LFSRR_FO + SG_ LFSrrTrkObsRange7 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrBurstID7 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange7 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate7 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth7 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID7 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation7 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp7 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth7 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1224 LF_SRR_Object_Track8: 8 LFSRR_FO + SG_ LFSrrTrkObsRange8 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrBurstID8 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange8 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate8 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth8 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID8 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation8 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp8 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth8 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1225 LF_SRR_Object_Track9: 8 LFSRR_FO + SG_ LFSrrTrkObsRange9 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrBurstID9 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange9 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate9 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth9 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID9 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation9 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp9 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus9 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth9 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1226 LF_SRR_Object_Track10: 8 LFSRR_FO + SG_ LFSrrTrkObsRange10 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ LFSrrBurstID10 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRange10 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ LFSrrTrkRRate10 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ LFSrrTrkAzimuth10 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ LFSrrTrkObjID10 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ LFSrrTrkObjElevation10 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkDynamProp10 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ LFSrrTrkMeasStatus10 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ LFSrrTrkRawAzimuth10 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + +BO_ 1232 RF_SRR_Object_Header: 8 RFSRR_FO + SG_ RFSRRVltgOutRngLo : 44|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRVltgOutRngHi : 43|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRSvcAlgnInPrcs : 38|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRSnsrBlckd : 45|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRSnstvFltPrsntInt : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRPlntAlgnInProc : 37|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRMsalgnYawRt : 47|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRMsalgnYawLt : 46|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRMsalgnRllRt : 35|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRMsalgnRllLt : 34|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRMsalgnPtchUp : 32|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRMsalgnPtchDn : 33|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRInitDiagCmplt : 40|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRHWFltPrsntInt : 25|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRExtIntrfrnc : 36|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRDiagSpare : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRCANSgnlSpvFld : 29|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRCANRxErr : 28|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRCANIDAddrsUnsbl : 27|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRAntTngFltPrsnt : 26|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRAmbTmpOutRngLw : 42|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRAmbTmpOutRngHi : 41|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRAlgnFltPrsnt : 39|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RFSRRNumValidTargets : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ RFSrrRollingCnt : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSRRModeCmdFdbk : 4|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTimeStamp : 10|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ RFSrrBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + SG_ RFSrrTimeStampV : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1233 RF_SRR_Object_Track1: 8 RFSRR_FO + SG_ RFSrrTrkObsRange1 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth1 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID1 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange1 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate1 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth1 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID1 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation1 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp1 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1234 RF_SRR_Object_Track2: 8 RFSRR_FO + SG_ RFSrrTrkObsRange2 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth2 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID2 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange2 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate2 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth2 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID2 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation2 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp2 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1235 RF_SRR_Object_Track3: 8 RFSRR_FO + SG_ RFSrrTrkObsRange3 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth3 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID3 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange3 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate3 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth3 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID3 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation3 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp3 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1236 RF_SRR_Object_Track4: 8 RFSRR_FO + SG_ RFSrrTrkObsRange4 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth4 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID4 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange4 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate4 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth4 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID4 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation4 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp4 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1237 RF_SRR_Object_Track5: 8 RFSRR_FO + SG_ RFSrrTrkObsRange5 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth5 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID5 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange5 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate5 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth5 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID5 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation5 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp5 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1238 RF_SRR_Object_Track6: 8 RFSRR_FO + SG_ RFSrrTrkObsRange6 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth6 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID6 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange6 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate6 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth6 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID6 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation6 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp6 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1239 RF_SRR_Object_Track7: 8 RFSRR_FO + SG_ RFSrrTrkObsRange7 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth7 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID7 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange7 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate7 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth7 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID7 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation7 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp7 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1240 RF_SRR_Object_Track8: 8 RFSRR_FO + SG_ RFSrrTrkObsRange8 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth8 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID8 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange8 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate8 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth8 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID8 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation8 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp8 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1241 RF_SRR_Object_Track9: 8 RFSRR_FO + SG_ RFSrrTrkObsRange9 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth9 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID9 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange9 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate9 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth9 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID9 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation9 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp9 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus9 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1242 RF_SRR_Object_Track10: 8 RFSRR_FO + SG_ RFSrrTrkObsRange10 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RFSrrTrkRawAzimuth10 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RFSrrBurstID10 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkRange10 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RFSrrTrkRRate10 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RFSrrTrkAzimuth10 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RFSrrTrkObjID10 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RFSrrTrkObjElevation10 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RFSrrTrkDynamProp10 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RFSrrTrkMeasStatus10 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1056 F_Vision_Obj_Header: 6 VIS_FO + SG_ FVsnSnsrBlckd : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ ClstInPathVehObjID : 30|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FrtVsnFld : 6|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnIniDiagSuccCmpt : 5|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnSrvAlgnInPrcs : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnUnvlbl : 7|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionRollingCnt : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVISModeCmdFdbk : 4|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FVisionNumValidTrgts : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FVisionTimeStampV : 31|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionTimeStamp : 10|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ VISBurstChecksum : 39|16@0+ (1,0) [0|65535] "" EOCM_F_FO + +BO_ 1057 F_Vision_Obj_Track_1: 8 VIS_FO + SG_ FwdVsnRngTrk1Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk1Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr1Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk1 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisBurstIDTrk1 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk1 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk1 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk1 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk1 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk1 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ ObjDirTrk1 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1058 F_Vision_Obj_Track_2: 8 VIS_FO + SG_ FwdVsnVertPosTrk2 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk2Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk2Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ ObjDirTrk2 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FwdVsnObjTypTr2Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FVisBurstIDTrk2 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk2 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk2 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk2 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk2 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk2 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1059 F_Vision_Obj_Track_3: 8 VIS_FO + SG_ FwdVsnVertPosTrk3 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk3Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk3Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr3Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk3 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk3 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk3 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk3 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk3 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk3 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk3 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1060 F_Vision_Obj_Track_4: 8 VIS_FO + SG_ FwdVsnVertPosTrk4 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisionMeasStatTrk4 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk4 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FwdVsnRngTrk4Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk4Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr4Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FVisBurstIDTrk4 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk4 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ ObjDirTrk4 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionConfTrk4 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk4 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1061 F_Vision_Obj_Track_5: 8 VIS_FO + SG_ FwdVsnVertPosTrk5 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk5Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk5Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr5Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk5 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk5 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk5 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk5 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk5 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk5 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk5 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1062 F_Vision_Obj_Track_6: 8 VIS_FO + SG_ FwdVsnVertPosTrk6 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk6Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk6Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr6Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk6 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk6 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk6 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk6 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk6 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk6 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk6 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1538 LF_SRR_Trace_Data: 8 LFSRR_FO + SG_ LFSRRYear : 7|8@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ LFSRRSerialNmbr : 39|32@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ LFSRRJulianDate : 15|24@0+ (1,0) [0|0] "" EOCM_F_FO + +BO_ 1537 R_SRR_Trace_data: 8 RSRR_FO + SG_ RSRRYear : 7|8@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ RSRRSerialNmbr : 39|32@0+ (1,0) [0|0] "" EOCM_F_FO + SG_ RSRRJulianDate : 15|24@0+ (1,0) [0|0] "" EOCM_F_FO + +BO_ 1089 F_Vision_Obj_Track_7: 8 VIS2_FO + SG_ FVisBurstIDTrk7 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk7 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk7 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk7 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk7 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk7 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FwdVsnRngTrk7Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnObjTypTr7Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk7Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnVertPosTrk7 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ ObjDirTrk7 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1090 F_Vision_Obj_Track_8: 8 VIS2_FO + SG_ FVisBurstIDTrk8 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk8 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk8Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnVertPosTrk8 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk8Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnObjTypTr8Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk8 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionConfTrk8 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk8 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk8 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk8 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1091 F_Vision_Obj_Track_9: 8 VIS2_FO + SG_ FwdVsnVertPosTrk9 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk9Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk9Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr9Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk9 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk9 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk9 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk9 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk9 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk9 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk9 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk9 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1092 F_Vision_Obj_Track_10: 8 VIS2_FO + SG_ FwdVsnRngTrk10Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk10Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr10Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk10 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ ObjDirTrk10 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk10 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk10 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk10 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk10 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk10 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk10 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk10 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1120 F_LRR_Obj_Header: 8 LRR_FO + SG_ FLRRRollingCount : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRModeCmdFdbk : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRNumValidTargets : 20|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ FLRRTimeStampV : 31|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRTimeStamp : 2|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ FLRRRoadTypeInfo : 5|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + SG_ FLRRDiagSpare : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRVltgOutRngLo : 44|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRVltgOutRngHi : 43|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRSvcAlgnInPrcs : 38|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRSnsrBlckd : 45|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRSnstvFltPrsntInt : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRPlntAlgnInProc : 37|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnYawRt : 47|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnYawLt : 46|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRLonVelPlsblityFlt : 35|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRYawRtPlsblityFlt : 34|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnPtchUp : 32|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnPtchDn : 33|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRInitDiagCmplt : 40|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRHWFltPrsntInt : 25|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRExtIntrfrnc : 36|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRCANSgnlSpvFld : 29|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRCANRxErr : 28|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRTunlDtctd : 27|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAmbTmpOutRngLw : 42|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAmbTmpOutRngHi : 41|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAntTngFltPrsnt : 26|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAlgnFltPrsnt : 39|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1121 F_LRR_Obj_Track_1: 8 LRR_FO + SG_ FLRRTrk1BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk1Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk1RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk1RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk1DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk1Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk1Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk1MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk1ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FLRRTrk1Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1122 F_LRR_Obj_Track_2: 8 LRR_FO + SG_ FLRRTrk2BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk2Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk2RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk2RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk2DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk2Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk2Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk2MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk2ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FLRRTrk2Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1123 F_LRR_Obj_Track_3: 8 LRR_FO + SG_ FLRRTrk3BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk3Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk3RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk3RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk3DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk3Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk3Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk3MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk3ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FLRRTrk3Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1124 F_LRR_Obj_Track_4: 8 LRR_FO + SG_ FLRRTrk4BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk4Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk4RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk4RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk4DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk4Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk4Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk4MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk4ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FLRRTrk4Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1125 F_LRR_Obj_Track_5: 8 LRR_FO + SG_ FLRRTrk5BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk5Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk5RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk5RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk5DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk5Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk5Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk5MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk5ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FLRRTrk5Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1126 F_LRR_Obj_Track_6: 8 LRR_FO + SG_ FLRRTrk6BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk6Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk6RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk6Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk6RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk6DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk6Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk6Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk6MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk6ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1127 F_LRR_Obj_Track_7: 8 LRR_FO + SG_ FLRRTrk7Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk7BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk7Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk7RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk7RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk7DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk7Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk7Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk7MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk7ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1128 F_LRR_Obj_Track_8: 8 LRR_FO + SG_ FLRRTrk8Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk8BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk8Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk8RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk8RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk8DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk8Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk8Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk8MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk8ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1129 F_LRR_Obj_Track_9: 8 LRR_FO + SG_ FLRRTrk9Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk9BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk9Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk9RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk9RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk9DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk9Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk9Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk9MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk9ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1130 F_LRR_Obj_Track_10: 8 LRR_FO + SG_ FLRRTrk10Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk10BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk10Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk10RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk10RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk10DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk10Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk10Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk10MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk10ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1131 F_LRR_Obj_Track_11: 8 LRR_FO + SG_ FLRRTrk11Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk11BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk11Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk11RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk11RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk11DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk11Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk11Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk11MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk11ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1132 F_LRR_Obj_Track_12: 8 LRR_FO + SG_ FLRRTrk12Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk12BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk12Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk12RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk12RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk12DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk12Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk12Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk12MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk12ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1133 F_LRR_Obj_Track_13: 8 LRR_FO + SG_ FLRRTrk13Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk13BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk13Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk13RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk13RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk13DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk13Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk13Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk13MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk13ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1134 F_LRR_Obj_Track_14: 8 LRR_FO + SG_ FLRRTrk14Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk14BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk14Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk14RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk14RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk14DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk14Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk14Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk14MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk14ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1135 F_LRR_Obj_Track_15: 8 LRR_FO + SG_ FLRRTrk15Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk15MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk15Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk15ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FLRRTrk15BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk15Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk15RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk15RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk15DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk15Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + +BO_ 1136 F_LRR_Obj_Track_16: 8 LRR_FO + SG_ FLRRTrk16Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk16BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk16Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk16RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk16RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk16DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk16Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk16Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk16MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk16ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1137 F_LRR_Obj_Track_17: 8 LRR_FO + SG_ FLRRTrk17Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk17BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk17Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk17RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk17RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk17DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk17Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk17Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk17MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk17ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1138 F_LRR_Obj_Track_18: 8 LRR_FO + SG_ FLRRTrk18Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk18BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk18Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk18RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk18RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk18DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk18Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk18Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk18MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk18ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1139 F_LRR_Obj_Track_19: 8 LRR_FO + SG_ FLRRTrk19Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk19BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk19Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk19RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk19RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk19DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk19Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk19Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk19MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk19ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1140 F_LRR_Obj_Track_20: 8 LRR_FO + SG_ FLRRTrk20Conf : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk20BurstID : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk20Range : 5|11@0+ (0.125,0) [0|255.875] "m" EOCM_F_FO + SG_ FLRRTrk20RangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ FLRRTrk20RangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" EOCM_F_FO + SG_ FLRRTrk20DynProp : 38|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk20Azimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" EOCM_F_FO + SG_ FLRRTrk20Width : 55|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FLRRTrk20MeasStatus : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk20ObjectID : 61|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1141 Long_Range_Radar_add_Info_1: 8 LRR_FO + SG_ FLRRAddInfo1BurstID : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ Cut_In_Out_Pot_Objtrk1 : 15|6@0+ (0.02,0) [0|1.26] "" EOCM_F_FO + SG_ ObjLossInfoObjTrk1 : 9|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ Cut_In_Out_Pot_Objtrk2 : 23|6@0+ (0.02,0) [0|1.26] "" EOCM_F_FO + SG_ ObjLossInfoObjTrk2 : 17|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ Cut_In_Out_Pot_Objtrk3 : 31|6@0+ (0.02,0) [0|1.26] "" EOCM_F_FO + SG_ ObjLossInfoObjTrk3 : 25|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ Cut_In_Out_Pot_Objtrk4 : 39|6@0+ (0.02,0) [0|1.26] "" EOCM_F_FO + SG_ ObjLossInfoObjTrk4 : 33|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ Cut_In_Out_Pot_Objtrk5 : 47|6@0+ (0.02,0) [0|1.26] "" EOCM_F_FO + SG_ ObjLossInfoObjTrk5 : 41|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ Cut_In_Out_Pot_Objtrk6 : 55|6@0+ (0.02,0) [0|1.26] "" EOCM_F_FO + SG_ ObjLossInfoObjTrk6 : 49|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1321 F_Fwd_Fus_Obj_TrackB_9: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn9 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB9RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB9Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB9MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB9DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB9RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB9RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB9Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB9ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB9ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB9ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB9ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB9ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB9ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB9NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB9LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB9LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1320 F_Fwd_Fus_Obj_TrackB_8: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn8 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB8RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB8Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB8MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB8DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB8RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB8RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB8Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB8ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB8ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB8ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB8ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB8ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB8ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB8NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB8LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB8LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1319 F_Fwd_Fus_Obj_TrackB_7: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn7 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB7RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB7Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB7MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB7DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB7RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB7RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB7Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB7ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB7ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB7ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB7ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB7ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB7ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB7NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB7LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB7LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1318 F_Fwd_Fus_Obj_TrackB_6: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn6 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB6RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB6Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB6MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB6DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB6RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB6RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB6Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB6ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB6ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB6ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB6ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB6ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB6ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB6NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB6LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB6LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1317 F_Fwd_Fus_Obj_TrackB_5: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn5 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB5RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB5Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB5MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB5DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB5RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB5RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB5Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB5ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB5ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB5ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB5ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB5ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB5ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB5NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB5LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB5LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1316 F_Fwd_Fus_Obj_TrackB_4: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn4 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB4RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB4Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB4MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB4DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB4RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB4RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB4Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB4ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB4ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB4ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB4ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB4ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB4ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB4NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB4LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB4LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1315 F_Fwd_Fus_Obj_TrackB_3: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn3 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB3RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB3Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB3MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB3DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB3RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB3RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB3Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB3ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB3ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB3ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB3ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB3ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB3ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB3NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB3LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB3LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1314 F_Fwd_Fus_Obj_TrackB_2: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn2 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB2RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB2Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB2MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB2DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB2RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB2RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB2Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB2ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB2ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB2ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB2ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB2ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB2ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB2NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB2LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB2LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1327 F_Fwd_Fus_Obj_TrackB_15: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn15 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB15RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB15Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB15MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB15DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB15RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB15RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB15Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB15ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB15ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB15ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB15ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTkB15ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB15ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB15NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB15LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB15LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1326 F_Fwd_Fus_Obj_TrackB_14: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn14 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB14RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB14Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB14MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB14DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB14RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB14RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB14Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB14ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB14ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB14ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB14ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB14ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB14ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB14NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB14LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB14LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1325 F_Fwd_Fus_Obj_TrackB_13: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn13 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB13RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB13Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB13MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB13DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB13RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB13RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB13Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB13ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB13ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB13ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB13ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB13ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB13ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB13NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB13LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB13LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1324 F_Fwd_Fus_Obj_TrackB_12: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn12 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB12RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB12Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB12MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB12DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB12RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB12RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB12Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB12ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB12ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB12ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB12ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB12ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB12ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB12NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB12LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB12LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1323 F_Fwd_Fus_Obj_TrackB_11: 7 EOCM_F_FO + SG_ FwdFusTrkB11DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB11RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB11RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB11Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB11ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB11ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB11ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB11ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB11ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB11ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB11NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB11LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB11LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkBAnlgRlLn11 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB11RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB11Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB11MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + +BO_ 1322 F_Fwd_Fus_Obj_TrackB_10: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn10 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB10RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB10Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB10MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB10DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB10RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB10RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB10Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB10ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB10ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB10ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB10ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB10ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB10ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB10NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB10LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB10LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1313 F_Fwd_Fus_Obj_TrackB_1: 7 EOCM_F_FO + SG_ FwdFusTrkBAnlgRlLn1 : 46|8@0- (0.1,0) [-12.8|12.7] "" Dummy_FO + SG_ FwdFusTrkB1RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB1Width : 5|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FwdFusTrkB1MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkB1DynProp : 11|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB1RelLnAccl : 8|9@0- (0.125,0) [-32|31.875] "m/s^2" Dummy_FO + SG_ FwdFusTrkB1RelLane : 31|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkB1Height : 54|6@0+ (0.25,0) [0|15.75] "m" Dummy_FO + SG_ FFusTrkB1ObjSrcLFSrr : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB1ObjSrcLCSrr : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB1ObjSrcRCSrr : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB1ObjSrcRFSrr : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FFusTrkB1ObjSrcVIs : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB1ObjSrcLrr : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FwdFusTrkB1NmCycTrkd : 39|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB1LatPosDev : 36|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkB1LngPosDev : 33|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1305 F_Fwd_Fus_Obj_TrackA_9: 8 EOCM_F_FO + SG_ FwdFusTrkA9RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA9ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA9MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA9LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA9RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA9Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA9LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA9RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA9MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA9ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1304 F_Fwd_Fus_Obj_TrackA_8: 8 EOCM_F_FO + SG_ FwdFusTrkA8RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA8ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA8MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA8LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA8RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA8Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA8LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA8RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA8MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA8ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1303 F_Fwd_Fus_Obj_TrackA_7: 8 EOCM_F_FO + SG_ FwdFusTrkA7RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA7ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA7MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA7LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA7RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA7Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA7LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA7RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA7MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA7ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1302 F_Fwd_Fus_Obj_TrackA_6: 8 EOCM_F_FO + SG_ FwdFusTrkA6RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA6ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA6MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA6LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA6RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA6Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA6LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA6RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA6MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA6ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1301 F_Fwd_Fus_Obj_TrackA_5: 8 EOCM_F_FO + SG_ FwdFusTrkA5RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA5ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA5MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA5LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA5RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA5Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA5LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA5RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA5MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA5ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1300 F_Fwd_Fus_Obj_TrackA_4: 8 EOCM_F_FO + SG_ FwdFusTrkA4RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA4ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA4MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA4LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA4RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA4Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA4LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA4RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA4MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA4ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1299 F_Fwd_Fus_Obj_TrackA_3: 8 EOCM_F_FO + SG_ FwdFusTrkA3RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA3ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA3MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA3LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA3RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA3Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA3LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA3RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA3MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA3ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1298 F_Fwd_Fus_Obj_TrackA_2: 8 EOCM_F_FO + SG_ FwdFusTrkA2RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA2ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA2MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA2LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA2RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA2Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA2LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA2RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA2MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA2ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1311 F_Fwd_Fus_Obj_TrackA_15: 8 EOCM_F_FO + SG_ FwdFusTrkA15RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA15ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA15MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA15LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA15RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA15Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA15LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA15RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA15MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA15ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1310 F_Fwd_Fus_Obj_TrackA_14: 8 EOCM_F_FO + SG_ FwdFusTrkA14RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA14ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA14MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA14LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA14RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA14Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA14LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA14RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA14MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA14ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1309 F_Fwd_Fus_Obj_TrackA_13: 8 EOCM_F_FO + SG_ FwdFusTrkA13RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA13ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA13MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA13LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA13RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA13Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA13LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA13RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA13MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA13ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1308 F_Fwd_Fus_Obj_TrackA_12: 8 EOCM_F_FO + SG_ FwdFusTrkA12RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA12ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA12MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA12LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA12RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA12Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA12LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA12RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA12MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA12ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1307 F_Fwd_Fus_Obj_TrackA_11: 8 EOCM_F_FO + SG_ FwdFusTrkA11ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA11MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA11LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA11RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA11Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA11LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA11RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA11MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA11ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + SG_ FwdFusTrkA11RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + +BO_ 1306 F_Fwd_Fus_Obj_TrackA_10: 8 EOCM_F_FO + SG_ FwdFusTrkA10RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA10ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA10MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA10LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA10RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA10Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA10LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA10RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA10MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA10ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1297 F_Fwd_Fus_Obj_TrackA_1: 8 EOCM_F_FO + SG_ FwdFusTrkA1RollingCnt : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA1ObjectID : 5|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ FwdFusTrkA1MsgIndex : 15|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ FwdFusTrkA1LongPos : 11|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + SG_ FwdFusTrkA1RelLongVel : 31|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA1Confidence : 36|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA1LatPos : 34|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ FwdFusTrkA1RelLatVel : 55|11@0- (0.125,0) [-128|127.875] "m/s" Dummy_FO + SG_ FwdFusTrkA1MeasStatus : 60|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ FwdFusTrkA1ObjType : 58|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 1296 F_Fwd_Fus_Obj_Header: 7 EOCM_F_FO + SG_ F_FusHeadRollingCount : 7|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ F_FusHeadFuncState : 5|2@0+ (1,0) [0|3] "" Dummy_FO + SG_ F_FusHedNmValTargts : 3|4@0+ (1,0) [0|15] "" Dummy_FO + SG_ F_FusHead_LrrOK : 15|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHead_LFSRROK : 14|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHead_VIsOK : 13|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHead_MapDataOK : 12|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHeadTimStmpV : 11|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHeadTimStmp : 10|11@0+ (1,0) [0|2047] "ms" Dummy_FO + SG_ F_FusHead_LCSRROK : 31|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHead_RCSRROK : 30|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHead_RFSRROK : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ F_FusHed_ObjClstrCurv : 28|13@0- (5E-005,0) [-0.2048|0.20475] "1/m" Dummy_FO + SG_ F_FusHdObjClstTanHdng : 47|8@0- (0.002,0) [-0.256|0.254] "m/m" Dummy_FO + SG_ RoadTypeInfo : 55|3@0+ (1,0) [0|7] "" Dummy_FO + +BO_ 257 USDT_Req_to_All_FO_ECUs: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" LRSRR_FO,_DOFIMU2_FO,_DOFIMU1_FO,DMS_FO,AMM_FO,EOCM2A_K2_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM2A_IMX6_FO,EOCM2A_K1_FO,NVS_FO,CIPM_FO,VIS2_FO,RRSRR_FO,VIS_FO,RFSRR_FO,LRR_FO,LFSRR_FO,RSRR_FO,EOCM_F_FO + +BO_ 584 USDT_Req_to_6DOFIMU2_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" _DOFIMU2_FO + +BO_ 1348 UUDT_Resp_From_6DOFIMU1_FO: 8 _DOFIMU1_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1604 USDT_Resp_From_6DOFIMU1_FO: 8 _DOFIMU1_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 580 USDT_Req_to_6DOFIMU1_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" _DOFIMU1_FO + +BO_ 1349 UUDT_Resp_From_DMS_FO: 8 DMS_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1605 USDT_Resp_From_DMS_FO: 8 DMS_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 581 USDT_Req_to_DMS_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" DMS_FO + +BO_ 1372 UUDT_Resp_From_AMM_FO: 8 AMM_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1628 USDT_Resp_From_AMM_FO: 8 AMM_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 604 USDT_Req_to_AMM_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" AMM_FO + +BO_ 1622 USDT_Resp_From_EOCM2B_IMX6_FO: 8 EOCM2B_IMX6_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 1366 UUDT_Resp_From_EOCM2B_IMX6_FO: 8 EOCM2B_IMX6_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" TestTool_FO + +BO_ 598 USDT_Req_to_EOCM2B_IMX6_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" EOCM2B_IMX6_FO + +BO_ 590 USDT_Req_to_Free_4E_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" Vector__XXX + +BO_ 1338 VPDR_Debug: 8 EOCM_F_FO + SG_ FrtRWARateDiagFA : 43|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FrtRWABiasDiagFA : 42|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ HWAFrtVal : 41|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ HWADotValFrt : 40|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAxRangeFA : 39|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAxRateFA : 38|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAxBiasFA : 37|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehAxCompFA : 36|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAxVal : 35|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAxVal : 34|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FrtRWACorrFA : 33|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FrtRWARangeDiagFA : 32|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAyBiasFA : 31|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehAyCompFA : 30|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAyVal : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAyVal : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehAxCorrFA : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAxRangeFA : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAxRateFA : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAxBiasFA : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehWzVal : 23|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehWzVal : 22|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehAyCorrDiagFA : 21|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAyRangeFA : 20|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAyRateFA : 19|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehAyBiasFA : 18|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAyRangeFA : 17|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehAyRateFA : 16|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehWzCorrDiagFA : 15|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehWzRangeFA : 14|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehWzRateFA : 13|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S1VehWzBiasFA : 12|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehWzRangeFA : 11|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehWzRateFA : 10|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ S2VehWzBiasFA : 9|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehWzCompFA : 8|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlVxLFCorrDiagFA : 7|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlVxRFCorrDiagFA : 6|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlVxLRCorrDiagFA : 5|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlVxRRCorrDiagFA : 4|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlLFVal : 3|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlRFVal : 2|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlLRVal : 1|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ WhlRRVal : 0|1@0+ (1,0) [0|1] "" Dummy_FO + +BO_ 1328 Diag_Debug1: 8 EOCM_F_FO + SG_ AlrtWrnIndReqFP : 1|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AlrtWrnIndReqFA : 0|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILRSRRSnsr_FP : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILRSRRSnsr_FA : 23|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILRSRRFrehns_FA : 22|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathEstCrvCSFP : 21|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathEstCrvCSFA : 20|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathWzEstCSFP : 19|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathWzEstCSFA : 18|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathVyEstCSFP : 17|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathVyEstCSFA : 16|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathVxEstCSFP : 15|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VehPathVxEstCSFA : 14|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTTCCSFP : 13|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTTCCSFA : 12|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLyCSFP : 11|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLyCSFA : 10|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThLxVxAxCSFP : 9|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThLxVxAxCSFA : 8|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ CurSetValDiagFP : 7|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ CurSetValDiagFA : 6|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ CrsAltDvrSlTpDiagFP : 5|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ CrsAltDvrSlTpDiagFA : 4|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FCAStatDiagFP : 3|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FCAStatDiagFA : 2|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBBrkCtrlStFP : 62|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBBrkCtrlStFA : 61|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBOpStFP : 60|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBOpStFA : 59|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBBrkCtrlAccFP : 58|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBBrkCtrlAccFA : 57|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBAxlTrqRqFP : 56|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ RVBAxlTrqRqFA : 55|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRUPATTCFP : 54|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRUPATTCFA : 53|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtObjIDFP : 52|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtObjIDFA : 51|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtTTCFP : 50|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtTTCFA : 49|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtLxFP : 48|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtLxFA : 47|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtLyFP : 46|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TVRHiThrtLyFA : 45|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFFuncStFP : 44|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFFuncStFA : 43|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFObjIDFP : 42|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFObjIDFA : 41|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFLatPstnVelRatFP : 40|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFLatPstnVelRatFA : 39|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFLonPstnVelFP : 38|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFLonPstnVelFA : 37|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFRltvLatVelDiagFP : 36|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFRltvLatVelDiagFA : 35|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFRltvLatPstnDiagFP : 34|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFRltvLatPstnDiagFA : 33|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFNrRltvLonPstnFP : 32|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFNrRltvLonPstnFA : 31|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFLonPstnVelRatFP : 30|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFLonPstnVelRatFA : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFConfDiagFP : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFConfDiagFA : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFRltvLnDiagFP : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ROFRltvLnDiagFA : 25|1@0+ (1,0) [0|1] "" Dummy_FO + +BO_ 1335 Diag_Debug3: 8 EOCM_F_FO + SG_ BrkSysCmdAxDiagFPQ : 63|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ BrkSysCmdAxDiagFAQ : 62|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AxleTorqReqDiagFPQ : 61|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AxleTorqReqDiagFAQ : 60|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AutoBrkTypeDiagFPQ : 59|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AutoBrkTypeDiagFAQ : 58|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTTCFPQ : 57|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTTCFAQ : 56|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTmpMemFPQ : 55|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTmpMemFAQ : 54|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLxVxAxFPQ : 53|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLxVxAxFAQ : 52|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtVyFPQ : 51|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtVyFAQ : 50|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLyFPQ : 49|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLyFAQ : 48|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtConPriFPQ : 47|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtConPriFAQ : 46|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtCJLFPQ : 45|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtCJLFAQ : 44|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPDynPropDiagFPQ : 43|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPDynPropDiagFAQ : 42|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRdTypInfoFPQ : 41|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRdTypInfoFAQ : 40|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRltvLnDiagFPQ : 39|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRltvLnDiagFAQ : 38|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumCycDiagFPQ : 37|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumCycDiagFAQ : 36|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumFusCyclsFPQ : 35|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumFusCyclsFAQ : 34|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNrRltvLonPstnFPQ : 33|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNrRltvLonPstnFAQ : 32|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonVelAccRatFPQ : 31|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonVelAccRatFAQ : 30|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPstnVelRatFPQ : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPstnVelRatFAQ : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPosVelAccFPQ : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPosVelAccFAQ : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatVelDiagFPQ : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatVelDiagFAQ : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatPstnDiagFPQ : 23|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatPstnDiagFAQ : 22|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFConfDiagFPQ : 21|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFConfDiagFAQ : 20|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFOvrlpRtlChk_FAQ : 19|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFOvrlpRtlChk_FAQ : 18|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRROvrlpRtlChk_FAQ : 17|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISOvrlpRtlChk_FAQ : 16|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISAlign_FAQ : 15|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISSnsr_FAQ : 14|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISSnsr_FPQ : 13|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISFrshns_FAQ : 12|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRAlign_FAQ : 11|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRFrshns_FAQ : 10|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRSnsr_FAQ : 9|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRSnsr_FPQ : 8|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRAlign_FAQ : 7|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRFrehns_FAQ : 6|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRSnsr_FAQ : 5|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRSnsr_FPQ : 4|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRSnsr_FPQ : 3|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRSnsr_FAQ : 2|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRFrshns_FAQ : 1|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRAlign_FAQ : 0|1@0+ (1,0) [0|1] "" Dummy_FO + +BO_ 1331 Diag_Debug2: 8 EOCM_F_FO + SG_ TCPHiThrtTmpMemFP : 63|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTmpMemFA : 62|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtConPriFP : 61|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtConPriFA : 60|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtCJLFP : 59|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTTCFP : 58|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtTTCFA : 57|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtVyFP : 56|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtVyFA : 55|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLyFP : 54|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLyFA : 53|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLxVxAxFP : 52|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtLxVxAxFA : 51|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRdTypInfoFP : 50|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRdTypInfoFA : 49|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AutoBrkTypeDiagFA : 48|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ BrkSysCmdAxDiagFP : 47|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ BrkSysCmdAxDiagFA : 46|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AxleTorqReqDiagFP : 45|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AxleTorqReqDiagFA : 44|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPDynPropDiagFP : 43|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPDynPropDiagFA : 42|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ TCPHiThrtCJLFA : 41|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumFusCyclsFP : 40|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ AutoBrkTypeDiagFP : 39|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumFusCyclsFA : 38|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatVelDiagFP : 37|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatVelDiagFA : 36|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatPstnDiagFP : 35|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLatPstnDiagFA : 34|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumCycDiagFP : 33|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNumCycDiagFA : 32|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRltvLnDiagFP : 31|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFRltvLnDiagFA : 30|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFConfDiagFP : 29|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFConfDiagFA : 28|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonVelAccRatFP : 27|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonVelAccRatFA : 26|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPstnVelRatFP : 25|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPstnVelRatFA : 24|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNrRltvLonPstnFP : 23|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFNrRltvLonPstnFA : 22|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPosVelAccFP : 21|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ FOFLonPosVelAccFA : 20|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISOvrlpRtlChk_FA : 19|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRROvrlpRtlChk_FA : 18|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFOvrlpRtlChk_FA : 17|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFOvrlpRtlChk_FA : 16|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISAlign_FA : 15|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISFrshns_FA : 14|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISSnsr_FP : 13|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ VISSnsr_FA : 12|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRAlign_FA : 11|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRFrshns_FA : 10|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRSnsr_FP : 9|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ LRRSnsr_FA : 8|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRAlign_FA : 7|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRFrehns_FA : 6|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRSnsr_FP : 5|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ IRFSRRSnsr_FA : 4|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRAlign_FA : 3|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRFrshns_FA : 2|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRSnsr_FP : 1|1@0+ (1,0) [0|1] "" Dummy_FO + SG_ ILFSRRSnsr_FA : 0|1@0+ (1,0) [0|1] "" Dummy_FO + +BO_ 1787 AL_Test_Tool_Rsp_RFSRR: 8 RFSRR_FO + SG_ RFSRREngRspDta : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" Dummy_FO + +BO_ 1788 AL_Test_Tool_Rsp_LFSRR: 8 LFSRR_FO + SG_ LFSRREngRspDta : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" Dummy_FO + +BO_ 1790 AL_Test_Tool_Req_RFSRR: 8 Dummy_FO + SG_ RFSRREngCmdDta : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" RFSRR_FO + +BO_ 1791 AL_Test_Tool_Req_LFSRR: 8 Dummy_FO + SG_ LFSRREngCmdDta : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" LFSRR_FO + +BO_ 1786 AL_Test_Tool_Rsp_RSRR: 8 RSRR_FO + SG_ RSRREngRspDta : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" Dummy_FO + +BO_ 1789 AL_Test_Tool_Req_RSRR: 8 Dummy_FO + SG_ RSRREngCmdDta : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" RSRR_FO + +BO_ 1149 F_LRR_Azmth_Rate_Info_4: 8 LRR_FO + SG_ FLRRTrk20AzmthRate : 50|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk19AzmthRate : 45|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk18AzmthRate : 24|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk17AzmthRate : 19|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk16AzmthRate : 14|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRAzRtInf4BurstID : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1148 F_LRR_Azmth_Rate_Info_3: 8 LRR_FO + SG_ FLRRTrk15AzmthRate : 50|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk14AzmthRate : 45|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk13AzmthRate : 24|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk12AzmthRate : 19|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk11AzmthRate : 14|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRAzRtInf3BurstID : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1147 F_LRR_Azmth_Rate_Info_2: 8 LRR_FO + SG_ FLRRTrk9AzmthRate : 45|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk8AzmthRate : 24|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk7AzmthRate : 19|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk6AzmthRate : 14|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk10AzmthRate : 50|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRAzRtInf2BurstID : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1146 F_LRR_Azmth_Rate_Info_1: 8 LRR_FO + SG_ FLRRTrk5AzmthRate : 50|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk4AzmthRate : 45|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk3AzmthRate : 24|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk2AzmthRate : 19|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRTrk1AzmthRate : 14|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FLRRAzRtInf1BurstID : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1143 Long_Range_Radar_add_Info_3: 8 LRR_FO + SG_ FLRRAddInfo3BurstID : 57|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk13ObstType : 60|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk20ObstTypeConf : 52|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk20ObstType : 55|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk19ObstTypeConf : 44|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk19ObstType : 47|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk18ObstTypeConf : 36|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk18ObstType : 39|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk17ObstTypeConf : 28|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk17ObstType : 31|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk16ObstTypeConf : 20|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk16ObstType : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk15ObstTypeConf : 12|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk15ObstType : 15|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk14ObstTypeConf : 4|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk14ObstType : 7|3@0+ (1,0) [0|7] "" EOCM_F_FO + +BO_ 1142 Long_Range_Radar_add_Info_2: 8 LRR_FO + SG_ FLRRAddInfo2BurstID : 62|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRTrk13ObstTypeConf : 60|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk12ObstTypeConf : 52|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk12ObstType : 55|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk11ObstTypeConf : 44|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk11ObstType : 47|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk10ObstTypeConf : 36|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk10ObstType : 39|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk9ObstTypeConf : 28|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk9ObstType : 31|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk8ObstTypeConf : 20|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk8ObstType : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk7ObstTypeConf : 12|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk7ObstType : 15|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRTrk1ObstTypeConf : 4|5@0+ (0.0323,0) [0|1.0013] "" EOCM_F_FO + SG_ FLRRTrk1ObstType : 7|3@0+ (1,0) [0|7] "" EOCM_F_FO + +BO_ 851 F_Vision_Environment_4: 8 VIS_FO + SG_ LnMrkg3LnPrvwDst : 45|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTtlNmLnMrkgDetRt : 4|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsRtLinCrsTm : 25|5@0+ (0.1,0) [0|3.1] "s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsNumPrlLnsDetRt : 33|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsNumPrlLnsDetLt : 36|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntLftV : 31|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtLinCrsTm : 30|5@0+ (0.1,0) [0|3.1] "s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnPrvwDst : 50|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMrkgTypChgDst : 61|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMrkgTypChgDst : 40|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMrkgWdth : 62|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMarkrElvtd : 51|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4AnchrLnLin : 57|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMrkgWdth : 41|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMarkrElvtd : 46|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3AnchrLnLin : 52|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstID2 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntLft : 15|16@0- (5.96E-008,0) [-0.0019529728|0.0019529132] "1/rad/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 597 USDT_Req_to_VIS2_FO: 8 TestTool_FO + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" CIPM_FO,VIS2_FO + +BO_ 1204 RR_SRR_Object_Track4: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth4 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate4 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange4 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange4 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID4 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation4 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp4 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth4 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID4 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1203 RR_SRR_Object_Track3: 8 RRSRR_FO + SG_ RRSrrTrkRawAzimuth3 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate3 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange3 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange3 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID3 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation3 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp3 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth3 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + SG_ RRSrrBurstID3 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1202 RR_SRR_Object_Track2: 8 RRSRR_FO + SG_ RRSrrBurstID2 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkRawAzimuth2 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate2 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange2 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange2 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID2 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation2 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp2 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth2 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + +BO_ 1201 RR_SRR_Object_Track1: 8 RRSRR_FO + SG_ RRSrrBurstID1 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkRawAzimuth1 : 61|6@0- (1,0) [-32|31] "deg" EOCM_F_FO + SG_ RRSrrTrkRRate1 : 18|11@0- (0.125,0) [-128|127.875] "m/s" EOCM_F_FO + SG_ RRSrrTrkRange1 : 2|11@0+ (0.02,0) [0|40.94] "m" EOCM_F_FO + SG_ RRSrrTrkObsRange1 : 53|6@0- (0.02,0) [-0.64|0.62] "m" EOCM_F_FO + SG_ RRSrrTrkObjID1 : 39|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ RRSrrTrkObjElevation1 : 20|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkMeasStatus1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSrrTrkDynamProp1 : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSrrTrkAzimuth1 : 34|11@0- (0.125,0) [-128|127.875] "deg" EOCM_F_FO + +BO_ 1200 RR_SRR_Object_Header: 8 RRSRR_FO + SG_ RRSrrTimeStampV : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSrrTimeStamp : 10|11@0+ (1,0) [0|2047] "" EOCM_F_FO + SG_ RRSrrRollingCnt : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ RRSRRNumValidTargets : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ RRSRRModeCmdFdbk : 4|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ RRSRRVltgOutRngLo : 44|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRVltgOutRngHi : 43|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRSvcAlgnInPrcs : 38|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRSnsrBlckd : 45|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRSnstvFltPrsntInt : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRPlntAlgnInProc : 37|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRMsalgnYawRt : 47|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRMsalgnYawLt : 46|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRMsalgnRllRt : 35|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRMsalgnRllLt : 34|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRMsalgnPtchUp : 32|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRMsalgnPtchDn : 33|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRInitDiagCmplt : 40|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRHWFltPrsntInt : 25|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRExtIntrfrnc : 36|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRDiagSpare : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRCANSgnlSpvFld : 29|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRCANRxErr : 28|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRCANIDAddrsUnsbl : 27|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRAntTngFltPrsnt : 26|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRAmbTmpOutRngLw : 42|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRAmbTmpOutRngHi : 41|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSRRAlgnFltPrsnt : 39|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ RRSrrBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + +BO_ 850 F_Vision_Environment_3: 8 VIS_FO + SG_ LnSnsTtlNmLnMrkgDetLt : 58|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtLnMrkgWdth : 63|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtLnMrkgTypChgDst : 62|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnLftV : 23|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnLft : 31|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrLftV : 15|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrLft : 39|16@0- (9.53E-007,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrTypRght : 50|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrTypLft : 53|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrElvtdRght : 54|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrElvtdLft : 55|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstID1 : 7|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnQltyCnfdncLvlRght : 22|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnQltyCnfdncLvlLft : 14|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnPrvwDstncRght : 2|3@0+ (10,0) [0|70] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnPrvwDstncLft : 5|3@0+ (10,0) [0|70] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 1414 RVB_TVR_Debug2_FO: 7 EOCM_F_FO + SG_ VBBrkCntlAccel : 45|12@0- (0.01,0) [-20.48|20.47] "m/s^2" Dummy_FO + SG_ VBTOSObjID : 35|6@0+ (1,0) [0|63] "" Dummy_FO + SG_ VBTOSTTC : 31|12@0+ (0.025,0) [0|102.375] "s" Dummy_FO + SG_ VBTOSLatPstn : 11|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO + SG_ VBTOSLonPstn : 7|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO + diff --git a/opendbc_repo/opendbc/dbc/cadillac_ct6_powertrain.dbc b/opendbc_repo/opendbc/dbc/cadillac_ct6_powertrain.dbc new file mode 100644 index 0000000000..2d0bb12174 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/cadillac_ct6_powertrain.dbc @@ -0,0 +1,248 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: K16_BECM K73_TCIC K9_BCM K43_PSCM K17_EBCM K20_ECM K114B_HPCM NEO K124_ASCM +VAL_TABLE_ TurnSignals 2 "Right Turn" 1 "Left Turn" 0 "None" ; +VAL_TABLE_ ACCLeadCar 1 "Present" 0 "Not Present" ; +VAL_TABLE_ ACCCmdActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ BrakePedalPressed 1 "Pressed" 0 "Depressed" ; +VAL_TABLE_ DistanceButton 1 "Active" 0 "Inactive" ; +VAL_TABLE_ LKAButton 1 "Active" 0 "Inactive" ; +VAL_TABLE_ ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ; +VAL_TABLE_ PRNDL 3 "Reverse" 2 "Drive" 1 "Neutral" 0 "Park" ; +VAL_TABLE_ DoorStatus 1 "Opened" 0 "Closed" ; +VAL_TABLE_ SeatBeltStatus 1 "Latched" 0 "Unlatched" ; +VAL_TABLE_ LKASteeringCmdActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ ACCGapLevel 3 "Far" 2 "Med" 1 "Near" 0 "Inactive" ; +VAL_TABLE_ GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ; +VAL_TABLE_ GasRegenCmdActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ LKATorqueDeliveredStatus 3 "Failed" 2 "Temp. Limited" 1 "Active" 0 "Inactive" ; +VAL_TABLE_ HandsOffSWDetectionStatus 1 "Hands On" 0 "Hands Off" ; +VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ; + + +BO_ 717 ASCM_2CD: 5 K124_ASCM + +BO_ 869 ASCM_365: 4 K124_ASCM + +BO_ 1034 ASCM_40A: 7 K124_ASCM + +BO_ 1296 ASCM_510: 4 K124_ASCM + +BO_ 1930 ASCM_78A: 7 K124_ASCM + +BO_ 190 ECMAcceleratorPos: 6 K20_ECM + SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO + SG_ GasPedalAndAcc : 23|8@0+ (1,0) [0|0] "" NEO + +BO_ 201 ECMEngineStatus: 8 K20_ECM + SG_ EngineTPS : 39|8@0+ (0.392156863,0) [0|100.000000065] "%" NEO + SG_ EngineRPM : 15|16@0+ (0.25,0) [0|0] "RPM" NEO + +BO_ 209 EBCMBrakePedalSensors: 7 K17_EBCM + SG_ Counter1 : 7|2@0+ (1,0) [0|3] "" XXX + SG_ Counter2 : 23|2@0+ (1,0) [0|3] "" XXX + SG_ BrakePedalPosition1 : 5|14@0+ (1,0) [0|16383] "" XXX + SG_ BrakePedalPosition2 : 21|14@0- (-1,0) [0|16383] "" XXX + SG_ BrakeNormalized1 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ BrakeNormalized2 : 47|8@0- (-1,0) [0|255] "" XXX + +BO_ 241 EBCMBrakePedalPosition: 6 K17_EBCM + SG_ BrakePedalPosition : 15|8@0+ (1,0) [0|255] "" NEO + +BO_ 298 BCMDoorBeltStatus: 8 K9_BCM + SG_ RearLeftDoor : 8|1@0+ (1,0) [0|0] "" NEO + SG_ FrontLeftDoor : 9|1@0+ (1,0) [0|0] "" NEO + SG_ FrontRightDoor : 10|1@0+ (1,0) [0|0] "" NEO + SG_ RearRightDoor : 23|1@0+ (1,0) [0|0] "" NEO + SG_ LeftSeatBelt : 12|1@0+ (1,0) [0|0] "" NEO + SG_ RightSeatBelt : 53|1@0+ (1,0) [0|0] "" NEO + +BO_ 309 ECMPRDNL: 8 K20_ECM + SG_ PRNDL : 2|3@0+ (1,0) [0|0] "" NEO + +BO_ 320 BCMTurnSignals: 3 K9_BCM + SG_ TurnSignals : 19|2@0+ (1,0) [0|0] "" NEO + +BO_ 336 ASCMLKASStatus: 1 NEO + SG_ Available : 7|1@0+ (1,0) [0|0] "" NEO + +BO_ 338 ASCMLKASteeringCmd: 6 NEO + SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO + SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO + SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO + SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO + SG_ LKASMode : 36|2@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO + +BO_ 340 ASCMBLKASteeringCmd: 6 NEO + SG_ LKASteeringCmdActive : 7|1@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmd : 5|14@0- (1,0) [0|0] "" NEO + SG_ RollingCounter : 23|2@0+ (1,0) [0|0] "" NEO + SG_ SetMe1 : 21|1@0+ (1,0) [0|0] "" NEO + SG_ LKASVehicleSpeed : 20|13@0+ (0.22,0) [0|0] "kph" NEO + SG_ LKASMode : 36|2@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmdChecksum : 33|10@0+ (1,0) [0|0] "" NEO + +BO_ 381 MSG_17D: 8 K20_ECM + SG_ MSG17D_AccPower : 35|12@0- (1,0) [0|0] "" NEO + +BO_ 356 PSCMStatus: 8 K43_PSCM + SG_ LKATorqueDeliveredStatus : 7|3@0+ (1,0) [0|7] "" NEO + SG_ LKADriverAppldTrq : 2|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO + SG_ LKATBDTorque : 21|14@0- (-0.005,0) [-10.24|10.23] "Nm" NEO + SG_ RollingCounter : 39|2@0+ (1,0) [0|0] "" NEO + SG_ LKATotalTorqueDelivered : 37|14@0- (0.01,0) [-10.24|10.23] "Nm" NEO + +BO_ 417 AcceleratorPedal: 7 XXX + SG_ AcceleratorPedal : 55|8@0+ (1,0) [0|0] "" NEO + +BO_ 451 GasAndAcc: 8 XXX + SG_ GasPedalAndAcc2 : 55|8@0+ (1,0) [0|0] "" NEO + +BO_ 452 AcceleratorPedal2: 8 XXX + SG_ AcceleratorPedal2 : 47|8@0+ (1,0) [0|0] "" NEO + +BO_ 481 ASCMSteeringButton: 7 K124_ASCM + SG_ DistanceButton : 22|1@0+ (1,0) [0|0] "" NEO + SG_ LKAButton : 23|1@0+ (1,0) [0|0] "" NEO + SG_ ACCButtons : 46|3@0+ (1,0) [0|0] "" NEO + +BO_ 485 PSCMSteeringAngle: 8 K43_PSCM + SG_ SteeringWheelAngle : 15|16@0- (0.0625,0) [-2047|2047] "deg" NEO + SG_ SteeringWheelRate : 27|12@0- (1,0) [-2047|2047] "deg/s" NEO + +BO_ 489 EBCMVehicleDynamic: 8 K17_EBCM + SG_ YawRate : 51|12@0- (0.0625,0) [-2047|2047] "grad/s" NEO + SG_ LateralAcceleration : 3|12@0- (0.0161,0) [-2047|2047] "m/s2" NEO + SG_ BrakePedalPressed : 6|1@0+ (1,0) [0|0] "" NEO + +BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM + SG_ HVBatteryVoltage : 31|12@0+ (0.125,0) [0|511.875] "V" NEO + SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO + +BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM + SG_ GasRegenAlwaysOne : 9|1@0+ (1,1) [1|1] "" NEO + SG_ GasRegenAlwaysThree : 15|2@0+ (1,1) [1|1] "" NEO + SG_ GasRegenChecksum : 47|24@0+ (1,0) [0|0] "" NEO + SG_ GasRegenCmdActiveInv : 32|1@0+ (1,0) [0|0] "" NEO + SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO + SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO + SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO + SG_ RollingCounter2 : 36|4@0+ (1,0) [0|0] "" NEO + SG_ GasRegenAlwaysOne2 : 23|1@0+ (1,0) [0|1] "" NEO + SG_ GasRegenCmd : 22|15@0+ (1,0) [0|0] "" NEO + +BO_ 810 TCICOnStarGPSPosition: 8 K73_TCIC + SG_ GPSLongitude : 39|32@0+ (1,-2147483648) [0|0] "milliarcsecond" NEO + SG_ GPSLatitude : 7|32@0+ (1,0) [0|0] "milliarcsecond" NEO + +BO_ 840 EBCMWheelSpdFront: 4 K17_EBCM + SG_ FLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO + SG_ FRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO + +BO_ 842 EBCMWheelSpdRear: 4 K17_EBCM + SG_ RLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO + SG_ RRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO + +BO_ 880 ASCMActiveCruiseControlStatus: 6 K124_ASCM + SG_ ACCLeadCar : 44|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCAlwaysOne2 : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCAlwaysOne : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCSpeedSetpoint : 19|12@0+ (0.0625,0) [0|255.9375] "km/h" NEO + SG_ ACCGapLevel : 21|2@0+ (1,0) [0|0] "" NEO + SG_ ACCResumeButton : 1|1@0+ (1,0) [0|0] "" NEO + SG_ ACCCmdActive : 23|1@0+ (1,0) [0|0] "" NEO + +BO_ 1001 ECMVehicleSpeed: 8 K20_ECM + SG_ VehicleSpeed : 7|16@0+ (0.01,0) [0|0] "mph" NEO + +BO_ 1033 ASCMKeepAlive: 7 NEO + SG_ ASCMKeepAliveAllZero : 7|56@0+ (1,0) [0|0] "" NEO + +BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM + SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "C" NEO + +BO_ 1249 VIN_Part2: 8 K20_ECM + SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO + +BO_ 1300 VIN_Part1: 8 K20_ECM + SG_ VINPart1 : 7|64@0+ (1,0) [0|0] "" NEO + +BO_ 1912 PSCM_778: 8 K43_PSCM + +BO_TX_BU_ 338 : K124_ASCM,NEO; +BO_TX_BU_ 880 : NEO,K124_ASCM; +BO_TX_BU_ 1033 : K124_ASCM,NEO; +BO_TX_BU_ 715 : NEO,K124_ASCM; + + +CM_ BU_ K16_BECM "Battery Energy Control Module"; +CM_ BU_ K73_TCIC "Telematics Communication Control Module"; +CM_ BU_ K9_BCM "Body Control Module"; +CM_ BU_ K43_PSCM "Power Steering Control Module"; +CM_ BU_ K17_EBCM "Electronic Brake Control Module"; +CM_ BU_ K20_ECM "Engine Control Module"; +CM_ BU_ K114B_HPCM "Hybrid Powertrain Control Module"; +CM_ BU_ NEO "Comma NEO"; +CM_ BU_ K124_ASCM "Active Safety Control Module"; +CM_ SG_ 381 MSG17D_AccPower "Need to investigate"; +CM_ SG_ 190 GasPedalAndAcc "ACC baseline is 62"; +CM_ SG_ 451 GasPedalAndAcc2 "ACC baseline is 62"; +CM_ SG_ 715 RollingCounter2 "Values cycle between 0, 7, 10, 13"; +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "BusType" "CAN"; +BA_ "ProtocolType" "GMLAN"; +BA_ "UseGMParameterIDs" 0; +VAL_ 481 DistanceButton 1 "Active" 0 "Inactive" ; +VAL_ 481 LKAButton 1 "Active" 0 "Inactive" ; +VAL_ 481 ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ; +VAL_ 309 PRNDL 3 "Reverse" 2 "Drive" 1 "Neutral" 0 "Park" ; +VAL_ 338 LKASteeringCmdActive 1 "Active" 0 "Inactive" ; +VAL_ 338 LKASMode 2 "supercruise" 1 "lkas" 0 "Inactive" ; +VAL_ 880 ACCLeadCar 1 "Present" 0 "Not Present" ; +VAL_ 880 ACCGapLevel 3 "Far" 2 "Med" 1 "Near" 0 "Inactive" ; +VAL_ 880 ACCResumeButton 1 "Pressed" 0 "Depressed" ; +VAL_ 880 ACCCmdActive 1 "Active" 0 "Inactive" ; +VAL_ 356 LKATorqueDeliveredStatus 7 "Override Fault" 6 "LKAS Fault but Responsive" 5 "TBD but Responsive" 4 "TBD but Responsive" 3 "Fault" 1 "Active" 0 "Inactive" ; +VAL_ 489 BrakePedalPressed 1 "Pressed" 0 "Depressed" ; +VAL_ 715 GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ; +VAL_ 715 GasRegenCmdActive 1 "Active" 0 "Inactive" ; diff --git a/opendbc_repo/opendbc/dbc/chrysler_cusw.dbc b/opendbc_repo/opendbc/dbc/chrysler_cusw.dbc new file mode 100644 index 0000000000..880f6e7255 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/chrysler_cusw.dbc @@ -0,0 +1,192 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 492 EPS_STATUS: 8 XXX + SG_ TORQUE_DRIVER : 3|12@0+ (1,-1024) [0|2048] "Nm" XXX + SG_ LKAS_STATE : 16|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_FAULT : 17|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_HIGH_TORQUE : 19|1@0+ (1,0) [0|1] "" XXX + SG_ TORQUE_MOTOR : 27|12@0+ (1,-2048) [0|1] "" XXX + SG_ LAT_TORQUE_REQUEST : 47|12@0+ (1,-2048) [0|4095] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1250 DOORS: 8 XXX + SG_ DOOR_OPEN_FL : 10|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 11|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 12|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 13|1@0+ (1,0) [0|1] "" XXX + SG_ TRUNK : 14|1@0+ (1,0) [0|1] "" XXX + +BO_ 1262 GEAR: 8 XXX + SG_ PRNDL : 11|4@0+ (1,0) [0|15] "" XXX + +BO_ 875 SEATBELT_STATUS: 8 XXX + SG_ SEATBELT_DRIVER_UNLATCHED : 16|1@0+ (1,0) [0|1] "" XXX + +BO_ 1264 STEERING_LEVERS: 7 XXX + SG_ TURN_SIGNALS : 3|4@0+ (1,0) [0|15] "" XXX + SG_ HIGH_BEAM_FLASH : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 480 TRACTION_BUTTON: 8 XXX + SG_ TRACTION_OFF : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 740 WHEEL_SPEEDS_REAR: 8 XXX + SG_ WHEEL_SPEED_RL : 5|13@0+ (0.0087,0) [0|1] "" XXX + SG_ WHEEL_SPEED_RR : 20|13@0+ (0.0087,0) [0|1] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|1] "" XXX + +BO_ 520 EPS_STATUS_2: 7 XXX + SG_ NEW_SIGNAL_1 : 3|12@0+ (1,-2048) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 19|12@0+ (1,-2048) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 39|12@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 43|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 55|8@0+ (1,0) [0|1] "" XXX + +BO_ 494 STEERING: 6 XXX + SG_ STEER_ANGLE : 5|14@0+ (0.1,-720) [0|1] "deg" XXX + SG_ STEERING_RATE : 19|12@0+ (1,-2000) [0|1] "" XXX + SG_ COUNTER : 35|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 738 BRAKE_2: 8 XXX + SG_ BRAKE_TORQUE : 7|12@0+ (1,0) [0|15] "" XXX + SG_ BRAKE_LIGHTS : 8|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_HUMAN : 9|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|1] "" XXX + +BO_ 742 WHEEL_SPEEDS_FRONT: 8 XXX + SG_ WHEEL_SPEED_FL : 5|13@0+ (0.0087,0) [0|1] "" XXX + SG_ WHEEL_SPEED_FR : 20|13@0+ (0.0087,0) [0|1] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|1] "" XXX + +BO_ 502 LKAS_COMMAND: 4 XXX + SG_ STEERING_TORQUE : 7|11@0+ (1,-1024) [0|4087] "" XXX + SG_ LKAS_CONTROL_BIT : 12|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 19|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 31|8@0+ (1,0) [0|1] "" XXX + +BO_ 1498 LKAS_1: 2 XXX + +BO_ 1500 DAS_6: 4 XXX + SG_ LKAS_ICON_COLOR : 1|2@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_0XAC : 15|8@0+ (1,0) [0|255] "" XXX + SG_ LKAS_LANE_LINES : 19|4@0+ (1,0) [0|15] "" XXX + +BO_ 1508 LKAS_HEARTBIT: 8 XXX + SG_ LKAS_STATUS_OK : 28|1@0+ (1,0) [0|1] "" XXX + +BO_ 762 CRUISE_BUTTONS: 3 XXX + SG_ ACC_Cancel : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Distance_Dec : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Accel : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Decel : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Resume : 4|1@0+ (1,0) [0|1] "" XXX + SG_ Cruise_OnOff : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_OnOff : 7|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Distance_Inc : 8|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 15|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 23|8@0+ (1,0) [0|1] "" XXX + +BO_ 484 BRAKE_1: 8 XXX + SG_ BRAKE_PSI : 7|12@0+ (1,0) [0|1] "" XXX + SG_ VEHICLE_SPEED : 35|12@0+ (0.0174,0) [0|4095] "m/s" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|1] "" XXX + +BO_ 500 GEARBOX_1: 7 XXX + SG_ DESIRED_GEAR : 35|4@0+ (1,0) [0|1] "" XXX + SG_ ACTUAL_GEAR : 39|4@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 43|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 55|8@0+ (1,0) [0|1] "" XXX + +BO_ 510 ACCEL_GAS: 5 XXX + SG_ ACC_ACTIVE : 2|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_HUMAN : 15|8@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 27|4@0+ (1,0) [0|1] "" XXX + SG_ GAS_ACC : 28|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|1] "" XXX + +BO_ 490 DASHBOARD: 4 XXX + SG_ ACC_SPEED_CONFIG_KPH : 7|8@0+ (0.1625,0) [0|1] "m/s" XXX + +BO_ 1006 ACC_HUD: 7 XXX + SG_ ACC_STATE : 7|3@0+ (1,0) [0|15] "" XXX + SG_ ACC_SET_SPEED_KMH : 14|8@0+ (1,0) [0|255] "km/h" XXX + SG_ DISTANCE_SETTING : 33|2@0+ (1,0) [0|3] "" XXX + SG_ DISTANCE_TO_LEAD : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 748 ACC_CONTROL: 8 XXX + SG_ ACC_MAIN_ON : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ACTIVE : 7|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_VALUE : 13|10@0+ (1,0) [0|1023] "" XXX + SG_ GAS_VALID : 15|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_VALUE : 28|10@0+ (1,0) [0|1023] "" XXX + SG_ BRAKE_VALID : 30|1@0+ (1,0) [0|1] "" XXX + SG_ UNKNOWN_1 : 33|1@0+ (1,0) [0|1] "" XXX + SG_ UNKNOWN_2 : 46|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 496 CLUSTER_1: 8 XXX + SG_ TACHOMETER : 3|12@0+ (1.024,0) [0|3] "" XXX + SG_ SPEEDOMETER : 19|12@0+ (0.01065,0) [0|1] "m/s" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|1] "" XXX + + +CM_ SG_ 1250 TRUNK "1 = open, 0 = closed"; +CM_ SG_ 1250 DOOR_OPEN_FL "1 = open, 0 = closed"; +CM_ SG_ 1250 DOOR_OPEN_FR "1 = open, 0 = closed"; +CM_ SG_ 1250 DOOR_OPEN_RL "1 = open, 0 = closed"; +CM_ SG_ 1250 DOOR_OPEN_RR "1 = open, 0 = closed"; +CM_ SG_ 1262 PRNDL "1 = park, 2 = reverse, 3 = neutral, 4 = drive, 5 = sport (snicker... sport)"; +CM_ SG_ 875 SEATBELT_DRIVER_UNLATCHED "1 = unlatched, 0 = safety first"; +CM_ SG_ 1264 TURN_SIGNALS "0 = off, 1 = left blinker, 2 = right blinker"; +CM_ SG_ 480 TRACTION_OFF "0 = TCS on, 1 = TCS off (light on dash ON)"; +CM_ SG_ 1500 LKAS_LANE_LINES "0x01 transparent lines, 0x02 left white, 0x03 right white, 0x04 left yellow with car on top, 0x05 left yellow with car on top, 0x06 both white, 0x07 left yellow, 0x08 left yellow right white, 0x09 right yellow, 0x0a right yellow left white, 0x0b left yellow with car on top right white, 0x0c right yellow with car on top left white, (0x00, 0x0d, 0x0e, 0x0f) null"; +CM_ SG_ 1492 LEAD_CAR "lead car present = 4, no car = 2 "; +CM_ SG_ 498 ACC_STATUS_2 "1 no ACC, 3 icpno "; +CM_ SG_ 498 ACC_STATUS_1 "0x00 = acc off, 0x03 = acc on, green, 0x02 acc on, white"; +CM_ SG_ 1006 ACC_STATE "0 = ACC off, 6 = ACC active (white), 8 = ACC engaged (green)"; +CM_ SG_ 502 LKAS_STATE "2 = active (green), 1 = error"; +CM_ SG_ 1006 ACC_SET_SPEED_KMH "min set appears to be 68 km/h, errors below 59 km/h "; +VAL_ 1262 PRNDL 1 "P" 2 "R" 3 "N" 4 "D" 5 "S"; diff --git a/opendbc_repo/opendbc/dbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc b/opendbc_repo/opendbc/dbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc new file mode 100644 index 0000000000..07c37e1fa2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/chrysler_pacifica_2017_hybrid_private_fusion.dbc @@ -0,0 +1,230 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 544 a_1: 8 XXX + SG_ track_id : 7|4@0+ (1,0) [0|15] "" XXX + SG_ REL_ACCEL : 3|12@0+ (1,0) [0|31] "" XXX + SG_ status1 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ REL_SPEED : 19|12@0+ (1,0) [0|65535] "" XXX + SG_ status2 : 39|6@0+ (1,0) [0|15] "" XXX + SG_ sig2 : 33|10@0+ (1,0) [0|255] "" XXX + SG_ zeros : 55|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 576 b_1: 8 XXX + SG_ sig0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ sig1 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ sig2 : 31|16@0+ (1,0) [0|255] "" XXX + SG_ zeros : 47|12@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 608 a_2: 8 XXX + SG_ track_id : 7|4@0+ (1,0) [0|15] "" XXX + SG_ REL_ACCEL : 3|12@0+ (1,0) [0|31] "" XXX + SG_ status1 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ REL_SPEED : 19|12@0+ (1,0) [0|65535] "" XXX + SG_ status2 : 39|6@0+ (1,0) [0|15] "" XXX + SG_ sig2 : 33|10@0+ (1,0) [0|255] "" XXX + SG_ zeros : 55|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 640 b_2: 8 XXX + SG_ sig0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ sig1 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ sig2 : 31|16@0+ (1,0) [0|255] "" XXX + SG_ zeros : 47|12@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 644 a_3: 8 XXX + SG_ track_id : 7|4@0+ (1,0) [0|15] "" XXX + SG_ REL_ACCEL : 3|12@0+ (1,0) [0|31] "" XXX + SG_ status1 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ REL_SPEED : 19|12@0+ (1,0) [0|65535] "" XXX + SG_ status2 : 39|6@0+ (1,0) [0|15] "" XXX + SG_ sig2 : 33|10@0+ (1,0) [0|255] "" XXX + SG_ zeros : 55|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 648 b_3: 8 XXX + SG_ sig0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ sig1 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ sig2 : 31|16@0+ (1,0) [0|255] "" XXX + SG_ zeros : 47|12@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 652 a_4: 8 XXX + SG_ track_id : 7|4@0+ (1,0) [0|15] "" XXX + SG_ REL_ACCEL : 3|12@0+ (1,0) [0|31] "" XXX + SG_ status1 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ REL_SPEED : 19|12@0+ (1,0) [0|65535] "" XXX + SG_ status2 : 39|6@0+ (1,0) [0|15] "" XXX + SG_ sig2 : 33|10@0+ (1,0) [0|255] "" XXX + SG_ zeros : 55|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 656 b_4: 8 XXX + SG_ sig0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ sig1 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ sig2 : 31|16@0+ (1,0) [0|255] "" XXX + SG_ zeros : 47|12@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 512 unknown_200: 8 XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ increasing : 31|16@0+ (1,0) [0|255] "" XXX + SG_ zeros_0 : 3|12@0+ (1,0) [0|63] "" XXX + SG_ zeros_1 : 47|12@0+ (1,0) [0|63] "" XXX + SG_ status0 : 7|4@0+ (1,0) [0|15] "" XXX + SG_ unknown_0 : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 514 unknown_202: 8 XXX + SG_ COUNTER : 43|4@0+ (1,0) [0|15] "" XXX + SG_ sig3 : 31|8@0+ (1,0) [0|65535] "" XXX + SG_ increasing : 39|12@0+ (1,0) [0|15] "" XXX + +BO_ 706 c_1: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + +BO_ 708 c_2: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 710 c_3: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 712 c_4: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 714 c_5: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 716 c_6: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 718 c_7: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 720 c_8: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 722 c_9: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 724 c_10: 8 XXX + SG_ LAT_DIST : 18|11@0+ (0.005,-1000) [0|2047] "m" XXX + SG_ LONG_DIST : 34|11@0+ (0.073,0) [0|255] "m" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 674 d_1: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 676 d_2: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 678 d_3: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 680 d_4: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 682 d_5: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 684 d_6: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 686 d_7: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 688 d_8: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 690 d_9: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 692 d_10: 8 XXX + SG_ REL_SPEED : 17|10@0+ (0.2857,-146.278) [0|1023] "m/s" XXX + +BO_ 672 NEW_MSG_5: 8 XXX + SG_ NEW_SIGNAL_1 : 9|10@0+ (1,0) [0|1023] "" XXX + SG_ NEW_SIGNAL_2 : 45|10@0+ (1,0) [0|1023] "" XXX + + + + +CM_ SG_ 544 track_id "for message a_1 track_id is always 1, similar for other messages and track_id"; +CM_ SG_ 544 REL_ACCEL "perhaps REL_ACCEL because it responds faster and before REL_SPEED"; +CM_ SG_ 544 sig2 "perhaps distance to object. LONG_DIST or REL_ACCEL or REL_SPEED"; +CM_ SG_ 576 zeros "not always zero, sometimes has value when another car changes lanes"; +CM_ SG_ 706 LAT_DIST "positive is to the right, negative is to the left"; diff --git a/opendbc_repo/opendbc/dbc/comma_body.dbc b/opendbc_repo/opendbc/dbc/comma_body.dbc new file mode 100644 index 0000000000..2b89f3a74a --- /dev/null +++ b/opendbc_repo/opendbc/dbc/comma_body.dbc @@ -0,0 +1,89 @@ +VERSION "0.0.02" + +BO_ 513 MOTORS_DATA: 8 XXX + SG_ SPEED_L : 7|16@0- (1,0) [-1000|1000] "" XXX + SG_ SPEED_R : 23|16@0- (1,0) [-1000|1000] "" XXX + SG_ ELEC_ANGLE_L : 39|8@0+ (1,0) [0|0] "deprecated" XXX + SG_ ELEC_ANGLE_R : 47|8@0+ (1,0) [0|0] "deprecated" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 514 VAR_VALUES: 3 XXX + SG_ IGNITION : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ENABLE_MOTORS : 1|1@0+ (1,0) [0|1] "" XXX + SG_ FAULT : 7|6@0+ (1,0) [0|63] "" XXX + SG_ MOTOR_ERR_L : 15|8@0+ (1,0) [0|255] "" XXX + SG_ MOTOR_ERR_R : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 515 BODY_DATA: 4 XXX + SG_ MCU_TEMP : 7|8@0+ (0.1,0) [0|125] "" XXX + SG_ BATT_VOLTAGE : 15|16@0+ (0.01,0) [0|60] "" XXX + SG_ BATT_PERCENTAGE : 31|7@0+ (1,0) [0|100] "" XXX + SG_ CHARGER_CONNECTED : 24|1@0+ (1,0) [0|1] "" XXX + +BO_ 516 MOTORS_CURRENT: 8 XXX + SG_ LEFT_PHA_AB : 7|16@0- (1,0) [-32768|32767] "" XXX + SG_ LEFT_PHA_BC : 23|16@0- (1,0) [-32768|32767] "" XXX + SG_ RIGHT_PHA_AB : 39|16@0- (1,0) [-32768|32767] "" XXX + SG_ RIGHT_PHA_BC : 55|16@0- (1,0) [-32768|32767] "" XXX + +BO_ 517 MOTORS_ANGLE: 8 XXX + SG_ LEFT_ANGLE_SENSOR : 7|16@0+ (1,0) [0|16384] "" XXX + SG_ RIGHT_ANGLE_SENSOR : 23|16@0+ (1,0) [0|16384] "" XXX + SG_ LEFT_HALL_SENSOR : 39|16@0+ (1,0) [0|360] "" XXX + SG_ RIGHT_HALL_SENSOR : 55|16@0+ (1,0) [0|360] "" XXX + +BO_ 592 TORQUE_CMD: 6 XXX + SG_ TORQUE_L : 7|16@0- (1,0) [-1000|1000] "" XXX + SG_ TORQUE_R : 23|16@0- (1,0) [-1000|1000] "" XXX + SG_ COUNTER : 35|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 593 MAX_MOTOR_RPM_CMD: 5 XXX + SG_ MAX_RPM_L : 7|16@0+ (1,0) [0|1000] "" XXX + SG_ MAX_RPM_R : 23|16@0+ (1,0) [0|1000] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 769 KNEE_MOTORS_DATA: 8 XXX + SG_ SPEED_L : 7|16@0- (1,0) [-1000|1000] "" XXX + SG_ SPEED_R : 23|16@0- (1,0) [-1000|1000] "" XXX + SG_ ELEC_ANGLE_L : 39|8@0+ (1,0) [0|0] "deprecated" XXX + SG_ ELEC_ANGLE_R : 47|8@0+ (1,0) [0|0] "deprecated" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 770 KNEE_VAR_VALUES: 3 XXX + SG_ IGNITION : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ENABLE_MOTORS : 1|1@0+ (1,0) [0|1] "" XXX + SG_ FAULT : 7|6@0+ (1,0) [0|63] "" XXX + SG_ MOTOR_ERR_L : 15|8@0+ (1,0) [0|255] "" XXX + SG_ MOTOR_ERR_R : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 771 KNEE_DATA: 4 XXX + SG_ MCU_TEMP : 7|8@0+ (0.1,0) [0|125] "" XXX + SG_ BATT_VOLTAGE : 15|16@0+ (0.01,0) [0|60] "" XXX + SG_ BATT_PERCENTAGE : 31|7@0+ (1,0) [0|100] "" XXX + SG_ CHARGER_CONNECTED : 24|1@0+ (1,0) [0|1] "" XXX + +BO_ 772 KNEE_MOTORS_CURRENT: 8 XXX + SG_ LEFT_PHA_AB : 7|16@0- (1,0) [-32768|32767] "" XXX + SG_ LEFT_PHA_BC : 23|16@0- (1,0) [-32768|32767] "" XXX + SG_ RIGHT_PHA_AB : 39|16@0- (1,0) [-32768|32767] "" XXX + SG_ RIGHT_PHA_BC : 55|16@0- (1,0) [-32768|32767] "" XXX + +BO_ 773 KNEE_MOTORS_ANGLE: 8 XXX + SG_ LEFT_ANGLE_SENSOR : 7|16@0+ (1,0) [0|16384] "" XXX + SG_ RIGHT_ANGLE_SENSOR : 23|16@0+ (1,0) [0|16384] "" XXX + SG_ LEFT_HALL_SENSOR : 39|16@0+ (1,0) [0|360] "" XXX + SG_ RIGHT_HALL_SENSOR : 55|16@0+ (1,0) [0|360] "" XXX + +BO_ 848 KNEE_TORQUE_CMD: 6 XXX + SG_ TORQUE_L : 7|16@0- (1,0) [-1000|1000] "" XXX + SG_ TORQUE_R : 23|16@0- (1,0) [-1000|1000] "" XXX + SG_ COUNTER : 35|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 849 KNEE_MAX_MOTOR_RPM_CMD: 5 XXX + SG_ MAX_RPM_L : 7|16@0+ (1,0) [0|1000] "" XXX + SG_ MAX_RPM_R : 23|16@0+ (1,0) [0|1000] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX diff --git a/opendbc_repo/opendbc/dbc/fca_giorgio.dbc b/opendbc_repo/opendbc/dbc/fca_giorgio.dbc new file mode 100644 index 0000000000..f3e22cf417 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/fca_giorgio.dbc @@ -0,0 +1,243 @@ +BO_ 171 NEW_MSG_AB: 8 XXX + SG_ NEW_SIGNAL_5 : 3|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_6 : 21|6@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_1 : 23|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 35|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 51|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_4 : 55|4@0+ (1,0) [0|15] "" XXX + +BO_ 222 EPS_1: 6 EPS + SG_ STEERING_ANGLE : 5|14@0+ (0.1,-716.8) [0|16383] "deg" XXX + SG_ STEERING_RATE : 19|12@0+ (0.5,-1000) [0|4095] "deg/s" XXX + SG_ UNKNOWN_1 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ UNKNOWN_2 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 35|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 228 NEW_MSG_E4: 6 XXX + SG_ NEW_SIGNAL_1 : 13|1@0+ (1,0) [0|1] "" XXX + +BO_ 238 ABS_1: 8 ABS + SG_ WHEEL_SPEED_FL : 7|13@0+ (0.017,0) [0|8191] "m/s" XXX + SG_ WHEEL_SPEED_FR : 10|13@0+ (0.017,0) [0|8191] "m/s" XXX + SG_ WHEEL_SPEED_RL : 29|13@0+ (0.017,0) [0|8191] "m/s" XXX + SG_ WHEEL_SPEED_RR : 32|13@0+ (0.017,0) [0|8191] "m/s" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 241 NEW_MSG_F1: 8 XXX + SG_ MAYBE_VOLTAGE : 18|10@0+ (0.02,0) [0|1023] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 249 NEW_MSG_F9: 4 XXX + SG_ COUNTER : 19|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 250 ABS_3: 8 ABS + SG_ BRAKE_PRESSURE_THRESHOLD : 2|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_PEDAL_SWITCH : 3|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 9|2@0+ (1,0) [0|3] "" XXX + SG_ XCOUNTER : 38|4@0+ (1,0) [0|15] "" XXX + SG_ XCHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 252 ENGINE_1: 8 ENGINE + SG_ ENGINE_RPM : 7|14@0+ (1,0) [0|255] "rev/min" XXX + SG_ ACCEL_PEDAL : 20|8@0+ (0.4,0) [0|255] "percent" XXX + SG_ REVERSE : 26|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 46|2@1+ (1,0) [0|3] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 254 ABS_2: 8 ABS + SG_ LONG_ACCEL : 7|12@0+ (0.01,-20.48) [0|4095] "m/s2" XXX + SG_ LATERAL_ACCEL : 11|12@0+ (0.01,-20.48) [0|4095] "m/s2" XXX + SG_ YAW_RATE : 31|12@0+ (-0.0014,2.86) [0|4095] "rad/s" XXX + SG_ NEW_SIGNAL_1 : 47|9@0+ (1,0) [0|511] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 257 ABS_6: 8 ABS + SG_ MAYBE_ACC_BRAKE : 5|1@0+ (1,0) [0|1] "" XXX + SG_ VEHICLE_SPEED : 15|11@0+ (0.017,0) [0|2047] "" XXX + SG_ BRAKE_PRESSURE_1 : 20|11@0+ (1,0) [0|2047] "" XXX + SG_ BRAKE_PRESSURE_2 : 43|12@0+ (1,0) [0|4095] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 262 EPS_2: 7 EPS + SG_ UNKNOWN_TORQUE : 7|12@0+ (1,-2000) [0|4095] "" XXX + SG_ UNKNOWN_1 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ UNKNOWN_STATUS : 9|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_TORQUE : 23|11@0+ (1,-1024) [0|2047] "" XXX + SG_ UNKNOWN_2 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ LKA_STATUS : 38|2@0+ (1,0) [0|3] "" XXX + SG_ LKA_FAULT : 39|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 43|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 263 ABS_4: 8 ABS + SG_ BRAKE_PRESSURE : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 265 NEW_MSG_109: 8 XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 270 ABS_7: 7 XXX + SG_ LONG_ACCEL_RAW : 7|12@0+ (0.01,-20.48) [0|4095] "" XXX + SG_ LATERAL_ACCEL_RAW : 11|12@0+ (0.01,-20.48) [0|4095] "" XXX + SG_ YAW_RATE_RAW : 31|12@0+ (-0.0014,2.86) [0|4095] "" XXX + SG_ COUNTER : 43|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 278 ABS_5: 8 ABS + SG_ WHEEL_IMPULSE_FL : 7|8@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_IMPULSE_FR : 15|8@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_IMPULSE_RL : 23|8@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_IMPULSE_RR : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ACTIVE_FL : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ACTIVE_FR : 33|1@0+ (1,0) [0|1] "" XXX + SG_ ACTIVE_RL : 34|1@0+ (1,0) [0|1] "" XXX + SG_ ACTIVE_RR : 35|1@0+ (1,0) [0|1] "" XXX + SG_ FORWARD_1 : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REVERSE_1 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ FORWARD_2 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ REVERSE_2 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 280 NEW_MSG_118: 6 XXX + SG_ COUNTER : 35|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 282 NEW_MSG_11A: 8 XXX + SG_ NEW_SIGNAL_1 : 7|11@0+ (1,-1000) [0|2047] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 284 NEW_MSG_11C: 8 XXX + SG_ NEW_SIGNAL_1 : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_2 : 11|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_3 : 28|13@0+ (1,0) [0|8191] "" XXX + SG_ NEW_SIGNAL_4 : 31|2@0+ (1,0) [0|3] "" XXX + SG_ VEHICLE_SPEED : 47|12@0+ (0.017,0) [0|4095] "m/s" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 288 NEW_MSG_120: 6 XXX + SG_ COUNTER : 19|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 290 EPS_3: 4 EPS + SG_ EPS_TORQUE : 7|12@0+ (1,-2048) [0|4095] "" XXX + SG_ COUNTER : 19|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 501 NEW_MSG_1F5: 5 XXX + SG_ NEW_SIGNAL_2 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 27|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 502 LKA_COMMAND: 8 CAMERA + SG_ LKA_TORQUE : 7|11@0+ (1,-1024) [0|2047] "" XXX + SG_ HAPTIC_WARN_1 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ LKA_ACTIVE : 11|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ HAPTIC_WARN_2 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 508 NEW_MSG_1FC: 8 XXX + SG_ NEW_SIGNAL_1 : 6|1@0+ (1,0) [0|1] "" XXX + +BO_ 601 NEW_MSG_259: 8 XXX + SG_ NEW_SIGNAL_1 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 762 NEW_MSG_2FA: 3 XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 766 CAM_UNKNOWN_1: 4 CAMERA + +BO_ 900 NEW_MSG_384: 8 XXX + SG_ NEW_SIGNAL_1 : 19|3@0+ (1,0) [0|7] "" XXX + +BO_ 1040 NEW_MSG_410: 8 XXX + SG_ NEW_SIGNAL_3 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 49|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1046 NEW_MSG_416: 8 XXX + SG_ MUX M : 1|2@0+ (1,0) [0|3] "" XXX + SG_ UNKNOWN_M0_1 m0 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M0_2 m0 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M0_3 m0 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M0_4 m0 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M0_5 m0 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M0_6 m0 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M0_7 m0 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_1 m1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_2 m1 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_3 m1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_4 m1 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_5 m1 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_6 m1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M1_7 m1 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_1 m2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_2 m2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_3 m2 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_4 m2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_5 m2 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_6 m2 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_M2_7 m2 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1194 CAM_UNKNOWN_2: 8 CAMERA + +BO_ 1198 LKA_HUD_1: 8 CAMERA + SG_ NEW_SIGNAL_1 : 4|5@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_3 : 12|5@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 38|3@0+ (1,0) [0|7] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1351 LKA_HUD_2: 8 CAMERA + SG_ NEW_SIGNAL_1 : 51|3@0+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_2 : 55|4@0+ (1,0) [0|15] "" XXX + +BO_ 1442 ACC_1: 8 RADAR + SG_ HUD_SPEED : 7|8@0+ (1,0) [0|255] "km/h" XXX + SG_ TARGET_SPEED : 15|8@0+ (0.433,0) [0|255] "m/s" XXX + SG_ NEW_SIGNAL_3 : 17|5@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_4 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_STATUS : 22|2@0+ (1,0) [0|3] "" XXX + SG_ MAYBE_TJA : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 1458 CAM_UNKNOWN_5: 4 CAMERA + SG_ NEW_SIGNAL_1 : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 1854 BCM_1: 4 BCM + SG_ RIGHT_TURN_STALK : 16|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_TURN_STALK : 17|1@0+ (1,0) [0|1] "" XXX + +BO_ 1865 NEW_MSG_749: 8 XXX + SG_ NEW_SIGNAL_1 : 23|2@0+ (1,0) [0|3] "" XXX + +BO_ 506855454 CAM_UNKNOWN_6: 1 CAMERA + +CM_ SG_ 254 LONG_ACCEL "scale TBD"; +CM_ SG_ 254 LATERAL_ACCEL "scale TBD"; +CM_ SG_ 254 YAW_RATE "scale estimated"; +CM_ SG_ 257 MAYBE_ACC_BRAKE "may correlate with ACC-actuated braking"; +CM_ SG_ 278 FORWARD_1 "probably per-axle"; +CM_ SG_ 278 REVERSE_1 "probably per-axle"; +CM_ SG_ 278 FORWARD_2 "probably per-axle"; +CM_ SG_ 278 REVERSE_2 "probably per-axle"; +CM_ SG_ 282 NEW_SIGNAL_1 "smoothed yaw rate with low speed cutoff, maybe active forward lighting target angle"; +CM_ SG_ 284 VEHICLE_SPEED "scale estimated"; +CM_ SG_ 502 HAPTIC_WARN_1 "correlates with steering wheel haptic"; +CM_ SG_ 502 HAPTIC_WARN_2 "correlates with steering wheel haptic"; +CM_ BO_ 1198 "Definite LKA activity, probably contains lane-line recognition and lane departure signals, indicator of LKA vs TJA, perhaps indicator of active assist in map-permitted areas"; +VAL_ 262 LKA_STATUS 0 "standby" 1 "lka_active"; diff --git a/opendbc_repo/opendbc/dbc/ford_cgea1_2_bodycan_2011.dbc b/opendbc_repo/opendbc/dbc/ford_cgea1_2_bodycan_2011.dbc new file mode 100644 index 0000000000..49fcae19c2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/ford_cgea1_2_bodycan_2011.dbc @@ -0,0 +1,1070 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 58 BCM_m_FrP01: 8 XXX + SG_ ChildLockCmd : 13|1@0+ (1,0) [0|0] "" XXX + SG_ ChildLockCmd_UB : 12|1@0+ (1,0) [0|0] "" XXX + SG_ CLockCmd : 31|8@0+ (1,0) [0|0] "" XXX + SG_ CLockCmd_UB : 14|1@0+ (1,0) [0|0] "" XXX + SG_ DDShortDrop : 3|2@0+ (1,0) [0|0] "" XXX + SG_ DDShortDrop_UB : 4|1@0+ (1,0) [0|0] "" XXX + SG_ DirectionIndication : 11|2@0+ (1,0) [0|0] "" XXX + SG_ DirectionIndication_UB : 0|1@0+ (1,0) [0|0] "" XXX + SG_ EpsDrvInfo_D_Dsply : 36|4@0+ (1,0) [0|0] "" XXX + SG_ EpsDrvInfo_D_Dsply_UB : 39|1@0+ (1,0) [0|0] "" XXX + SG_ GearRvrseActv_D_Actl : 38|2@0+ (1,0) [0|0] "" XXX + SG_ GearRvrseActv_D_Actl_UB : 15|1@0+ (1,0) [0|0] "" XXX + SG_ VehVActlEng_D_Qf_3A : 9|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_ActlEng_UB_3A : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_ActlEng_3A : 55|16@0+ (0.01,0) [0|0] "kph" XXX + SG_ Veh_V_DsplyCcSet : 23|8@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_RqCcSet : 32|9@0+ (0.5,0) [0|0] "kph" XXX + SG_ WasherFluidLevelLow : 5|1@0+ (1,0) [0|0] "" XXX + +BO_ 64 BCM_m_FrP02: 8 XXX + SG_ FuelCutoffReq : 7|4@0+ (1,0) [0|0] "" XXX + SG_ FuelCutoffReq_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ KVRFRSettings : 54|15@0+ (1,0) [0|0] "" XXX + SG_ KVRFRSettings_UB : 10|1@0+ (1,0) [0|0] "" XXX + SG_ PsngrFrntDetct_D_Actl : 23|2@0+ (1,0) [0|0] "" XXX + SG_ PsngrFrntDetct_D_Actl_UB : 3|1@0+ (1,0) [0|0] "" XXX + SG_ RILReq : 21|2@0+ (1,0) [0|0] "" XXX + SG_ RILReq_UB : 55|1@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBuckleDriver : 31|2@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBuckleDriver_UB : 0|1@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBuckleMid : 29|2@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBuckleMid_UB : 15|1@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBucklePsngr : 27|2@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBucklePsngr_UB : 14|1@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBuckleDriver : 25|2@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBuckleDriver_UB : 13|1@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBucklePsngr : 37|2@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBucklePsngr_UB : 11|1@0+ (1,0) [0|0] "" XXX + SG_ WheelRotationCnt : 47|8@0+ (1,0) [0|0] "" XXX + SG_ WheelRotationCnt_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ WheelRotationCntQF : 35|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRr_D_Actl_UB_40 : 2|1@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRr_D_Actl_40 : 39|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRl_D_Actl_UB_40 : 1|1@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRl_D_Actl_40 : 33|2@0+ (1,0) [0|0] "" XXX + +BO_ 131 MS_Steering_Data: 8 XXX + SG_ SteColumn_Status_UB : 28|1@0+ (1,0) [0|0] "" XXX + SG_ SteColumn_Status : 31|3@0+ (1,0) [0|0] "" XXX + SG_ SteCol_Manual_Override_UB : 26|1@0+ (1,0) [0|0] "" XXX + SG_ SteCol_Manual_Override : 27|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Send_UB : 20|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Send : 6|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Phone_UB : 17|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Phone : 3|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_OK_UB : 16|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_OK : 2|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Volume_Up_UB : 23|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Volume_Down_UB : 22|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Voice_PTT_UB : 21|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Seek_Right_UB : 19|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Seek_Left_UB : 18|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Mode_UB : 11|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Mode : 13|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Media_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Volume_Up : 15|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Volume_Down : 14|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Voice_PTT : 7|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Seek_Right : 5|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Seek_Left : 4|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Media : 1|1@0+ (1,0) [0|0] "" XXX + SG_ VehYaw_W_Actl : 55|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + SG_ SteWhlCtl_End_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_End : 0|1@0+ (1,0) [0|0] "" XXX + SG_ VehYaw_W_Actl_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Mute_UB : 10|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Mute : 12|1@0+ (1,0) [0|0] "" XXX + +BO_ 257 Driver_Seat_Information: 8 XXX + SG_ Reverse_Mirror_Stat : 3|2@0+ (1,0) [0|0] "" XXX + SG_ Memory_Feedback_Rqst : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Easy_Entry_Exit_Stat : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 260 Driver_Seat_Information_2: 8 XXX + SG_ Memory_Cmd : 15|4@0+ (1,0) [0|0] "" XXX + SG_ Easy_Entry_Rqst : 4|2@0+ (1,0) [0|0] "" XXX + SG_ DrvSeat_Stat : 7|3@0+ (1,0) [0|0] "" XXX + SG_ Cancel_Auto_Movement : 1|1@0+ (1,0) [0|0] "" XXX + +BO_ 269 IdleShutdown_Legacy: 8 XXX + SG_ IDLE_ENGINE_SHUTDOWN : 23|2@0+ (1,0) [0|0] "" XXX + +BO_ 272 Keyfob_Pad_Stat: 8 XXX + SG_ L_Pwr_Sliding_Dr_Rqst : 28|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Decklid_Rqst : 31|1@0+ (1,0) [0|0] "" XXX + SG_ R_Pwr_Sliding_Dr_Rqst : 29|1@0+ (1,0) [0|0] "" XXX + SG_ Keyfob_Pad_Msg_Count : 23|8@0+ (1,0) [0|0] "Counts" XXX + SG_ Keyfob_Pad_Id_Number : 15|8@0+ (1,0) [0|0] "" XXX + SG_ Keyfob_Pad_Button_Pressed : 7|8@0+ (1,0) [0|0] "" XXX + SG_ Power_Liftgate_Rqst : 30|1@0+ (1,0) [0|0] "" XXX + SG_ Keycode_Status : 27|20@0+ (1,0) [0|0] "" XXX + +BO_ 275 Power_Liftgate_Mode_StatM: 8 XXX + SG_ Power_Liftgate_Mode_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ DrTgateChime_D_Rq : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 276 Running_Board_CmdM: 8 XXX + SG_ Running_Board_Cmd : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 277 Running_Board_StatM: 8 XXX + SG_ Running_Board_Stat : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 288 ClmtCtrlSeat_SetCmdlegacy1: 8 XXX + SG_ ClmtCtrlSeat_SetCmd_Dvr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 289 ClmtCtrlSeat_SetStat_DvrM: 8 XXX + SG_ ClmtCtrlSeat_SetStat_Dvr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 290 ClmtCtrlSeat_SetCmdlegacy2: 8 XXX + SG_ ClmtCtrlSeat_SetCmd_Psgr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 291 ClmtCtrlSeat_SetStat_PsgrM: 8 XXX + SG_ ClmtCtrlSeat_SetStat_Psgr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 292 ClmtCtrlSeatSet_Cmd_v2_MS: 8 XXX + SG_ ClmtCtrlSeat_SetCmd_Psgr : 15|8@0+ (1,0) [0|0] "" XXX + SG_ ClmtCtrlSeat_SetCmd_Dvr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 293 ClmtCtrlSeatSet_Stat_v2: 8 XXX + SG_ ClmtCtrlSeat_SetStat_Psgr : 15|8@0+ (1,0) [0|0] "" XXX + SG_ ClmtCtrlSeat_SetStat_Dvr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 304 Mirror_Manual_Override_M: 8 XXX + SG_ Mirror_Manual_Override : 7|1@0+ (1,0) [0|0] "Binary" XXX + +BO_ 305 Memory_Sw_StatM: 8 XXX + SG_ Memory_Sw_Message_Count : 15|8@0+ (1,0) [0|0] "Counts" XXX + SG_ Memory_Set_Sw_Stat : 7|1@0+ (1,0) [0|0] "Binary" XXX + SG_ Memory_Set_Cancel : 3|1@0+ (1,0) [0|0] "Binary" XXX + SG_ Memory_3_Sw_Stat : 4|1@0+ (1,0) [0|0] "Binary" XXX + SG_ Memory_2_Sw_Stat : 5|1@0+ (1,0) [0|0] "Binary" XXX + SG_ Memory_1_Sw_Stat : 6|1@0+ (1,0) [0|0] "Binary" XXX + +BO_ 306 Driver_Lock_Sw_StatM: 8 XXX + SG_ Driver_Door_Key_Unlock : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Driver_Door_Key_Lock : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Driver_Lock_Sw_Message_Cnt : 7|8@0+ (1,0) [0|0] "Counts" XXX + SG_ Driver_Lock_Sw_Stat : 15|2@0+ (1,0) [0|0] "" XXX + +BO_ 309 Memory_Cancel_Cmd_M: 8 XXX + SG_ Memory_Cancel_Cmd : 7|1@0+ (1,0) [0|0] "Binary" XXX + +BO_ 310 Driver_Door_Lock_CmdM: 8 XXX + SG_ Driver_Door_Lock_Msg_Cnt : 7|8@0+ (1,0) [0|0] "Counts" XXX + SG_ Driver_Door_Lock_Cmd : 15|4@0+ (1,0) [0|0] "" XXX + +BO_ 311 Pass_Mirror_Sw_StatM: 8 XXX + SG_ Pass_Mirror_Sw_UD_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Mirror_Sw_LR_Stat : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 313 RPwrSlideDr_Unlock_RqstM: 8 XXX + SG_ RPwrSlideDr_Unlock_Rqst : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 320 LPwrSlideDr_Unlock_RqstM: 8 XXX + SG_ LPwrSlideDr_Unlock_Rqst : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 321 Passive_Entry_Ctrl_Data: 8 XXX + SG_ PE_Control_Data_1 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Control_Cmd : 7|3@0+ (1,0) [0|0] "" XXX + SG_ PK_SearchResults_Prog : 63|4@0+ (1,0) [0|0] "" XXX + SG_ PK_SearchResults_MyKey : 4|4@0+ (1,0) [0|0] "" XXX + SG_ PK_SearchResults_Found : 59|4@0+ (1,0) [0|0] "" XXX + SG_ PK_Search_EvNum : 15|8@0+ (1,0) [0|0] "Counts" XXX + SG_ PE_Control_Data_5 : 55|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Control_Data_4 : 47|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Control_Data_3 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Control_Data_2 : 31|8@0+ (1,0) [0|0] "" XXX + +BO_ 322 Passive_Entry_Target_Data: 8 XXX + SG_ PE_Target_Data_5 : 47|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Target_Cmd : 7|2@0+ (1,0) [0|0] "" XXX + SG_ PE_Target_Status : 5|1@0+ (1,0) [0|0] "" XXX + SG_ PE_Target_Data_1 : 15|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Search_Rqst : 4|2@0+ (1,0) [0|0] "" XXX + SG_ PE_Target_Data_4 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Target_Data_3 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Target_Data_2 : 23|8@0+ (1,0) [0|0] "" XXX + +BO_ 577 BCM_m_FrP28: 8 XXX + SG_ WheelRotToothCntFrL : 15|8@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntFrL_UB : 42|1@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntFrR : 23|8@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntFrR_UB : 41|1@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntReL : 31|8@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntReL_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntReR : 39|8@0+ (1,0) [0|0] "" XXX + SG_ WheelRotToothCntReR_UB : 43|1@0+ (1,0) [0|0] "" XXX + +BO_ 736 FCIM_Button_Press: 8 XXX + SG_ FCIM_Target_ID : 13|4@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Button_Type : 7|8@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Button_State : 15|2@0+ (1,0) [0|0] "" XXX + +BO_ 806 Compressor_Req: 8 XXX + SG_ HvacEvap_Te_Rq : 33|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ HvacEvap_Te_Actl : 17|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ HvacAirCond_B_Rq : 7|1@0+ (1,0) [0|0] "" XXX + SG_ HvacEvap_Te_Offst : 1|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + +BO_ 842 MassageSeat_Data1: 8 XXX + SG_ SeatLmbrUpDrv_Pc_Actl : 38|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrMidDrv_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrLoDrv_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlUpDrv_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlLoDrv_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 843 MassageSeat_Data2: 8 XXX + SG_ SeatLmbrUpPsgr_Pc_Actl : 38|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrMidPsgr_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrLoPsgr_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlUpPsgr_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlLoPsgr_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 844 MassageSeat_Stat1: 8 XXX + SG_ StmsLmbrDrv_D_Stat : 17|2@0+ (1,0) [0|0] "" XXX + SG_ StmsCshnDrv_D_Stat : 19|2@0+ (1,0) [0|0] "" XXX + SG_ SeatSwtchDrv_B_Stat : 31|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDrv_D_Stat : 23|3@0+ (1,0) [0|0] "" XXX + SG_ SeatAirAmb_P_Actl : 7|16@0+ (0.01,0) [0|0] "KiloPascal" XXX + SG_ SeatPDrv_B_Stat : 20|1@0+ (1,0) [0|0] "" XXX + +BO_ 845 MassageSeat_Stat2: 8 XXX + SG_ StmsLmbrPsgr_D_Stat : 15|2@0+ (1,0) [0|0] "" XXX + SG_ StmsCshnPsgr_D_Stat : 13|2@0+ (1,0) [0|0] "" XXX + SG_ SeatSwtchPsgr_B_Stat : 11|1@0+ (1,0) [0|0] "" XXX + SG_ SeatPPsgr_B_Stat : 7|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnPsgr_D_Stat : 6|3@0+ (1,0) [0|0] "" XXX + SG_ PsgrMemFeedback_Rsp : 3|4@0+ (1,0) [0|0] "" XXX + +BO_ 846 MassageSeat_Req_MS: 8 XXX + SG_ SeatFnPsgr_D_Rq : 15|3@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDrv_D_Rq : 12|3@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDfaltPsgr_B_Rq : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDfaltDrv_B_Rq : 8|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnChngPsgr_D_Rq : 7|2@0+ (1,0) [0|0] "" XXX + SG_ SeatFnChngDrv_D_Rq : 5|2@0+ (1,0) [0|0] "" XXX + SG_ PsgrMemory_Rq : 3|4@0+ (1,0) [0|0] "" XXX + +BO_ 849 MassageSeat_Data3: 8 XXX + SG_ SeatCshnDrvRR_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnDrvRL_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnDrvFR_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnDrvFL_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 850 MassageSeat_Data4: 8 XXX + SG_ SeatCshnPsgrRR_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnPsgrRL_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnPsgrFR_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnPsgrFL_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 853 EFP_CC_Status_MS: 8 XXX + SG_ Save_My_Temp : 59|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Left_Temp_Setpt : 31|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RrDefrost_HtdMirrorReq : 60|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Control_Status : 16|1@0+ (1,0) [0|0] "" XXX + SG_ MultipleButtonPressReq : 63|3@0+ (1,0) [0|0] "" XXX + SG_ Rear_System_Mode_Req : 19|3@0+ (1,0) [0|0] "" XXX + SG_ Recirc_Request : 23|2@0+ (1,0) [0|0] "" XXX + SG_ Front_Rt_Temp_Setpt : 39|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ AC_Request : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Windshield_ModeRequest : 15|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Panel_Mode_Request : 7|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Overriding_ModeReq : 10|3@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_Request : 3|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Rear_Right_Temp_Setpt : 55|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ Forced_Recirc_Req : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Left_Temp_Setpt : 47|8@0+ (1,0) [0|0] "Mixed" XXX + +BO_ 854 EFP_CC_Seat_Req_Stat_MS: 8 XXX + SG_ Front_Rear_Blower_Req : 31|6@0+ (1,0) [0|0] "Detents" XXX + SG_ Pass_Rr_Cond_Seat_Req : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Rr_Cond_Seat_Lvl : 8|3@0+ (1,0) [0|0] "" XXX + SG_ Pass_Fr_Cond_Seat_Req : 13|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Fr_Cond_Seat_Lvl : 11|3@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Rr_Cond_Seat_Req : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Rr_Cond_Seat_Lvl : 2|3@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Fr_Cond_Seat_Req : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Fr_Cond_Seat_Lvl : 5|3@0+ (1,0) [0|0] "" XXX + +BO_ 855 RCCM_CC_Status: 8 XXX + SG_ RrBlwrCondStLdShedStat : 25|2@0+ (1,0) [0|0] "" XXX + SG_ FrBlwrCondStLdShedStat : 20|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_Rr_Rt_TempSetpt : 63|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Rr_Left_TempSetpt : 55|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Fr_Rt_TempSetpt : 47|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Fr_Left_TempSetpt : 39|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Fr_Rr_Blower_Req : 31|6@0+ (1,0) [0|0] "Detents" XXX + SG_ Panel_Mode_State : 7|4@0+ (8.33,0) [0|0] "%" XXX + SG_ RrDefHtdMirrLdShedStat : 18|2@0+ (1,0) [0|0] "" XXX + SG_ Windshield_Mode_State : 15|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Recirc_Door_State : 11|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_System_Mode_State : 23|3@0+ (1,0) [0|0] "" XXX + SG_ Default_Defrost_State : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Auto_AC_Indicator_Temp : 16|1@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_State : 3|4@0+ (8.33,0) [0|0] "%" XXX + SG_ RrDefrost_HtdMirrState : 8|1@0+ (1,0) [0|0] "" XXX + +BO_ 856 RCCM_CC_Seat_Status: 8 XXX + SG_ Active_My_Temp : 2|1@0+ (1,0) [0|0] "" XXX + SG_ CC_HtdStrWhl_Req : 24|1@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PR_Cond_Seat_Lvl : 31|3@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PR_Cond_Seat_Req : 28|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PF_Cond_Seat_Req : 20|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PF_Cond_Seat_Lvl : 23|3@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DR_Cond_Seat_Req : 12|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DR_Cond_Seat_Lvl : 15|3@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DF_Cond_Seat_Req : 4|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DF_Cond_Seat_Lvl : 7|3@0+ (1,0) [0|0] "" XXX + SG_ PassRrCondStLdShedStat : 26|2@0+ (1,0) [0|0] "" XXX + SG_ PassFrCondStLdShedStat : 18|2@0+ (1,0) [0|0] "" XXX + SG_ DrvRrCondStLdShedStat : 10|2@0+ (1,0) [0|0] "" XXX + SG_ DrvFrCondStLdShedStat : 1|2@0+ (1,0) [0|0] "" XXX + +BO_ 857 RCCM_CC_MBP_Press_Stat: 8 XXX + SG_ Report_Active : 33|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Temp_Units : 35|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Fan_Bars_Disply : 39|3@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Temp_Units : 36|1@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyPass10 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyPass1 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyDrvr10 : 7|8@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyDrvr1 : 15|8@0+ (1,0) [0|0] "" XXX + +BO_ 859 MFD_CC_Status_MS: 8 XXX + SG_ Rear_Mode_Bttn_Status : 38|1@0+ (1,0) [0|0] "" XXX + +BO_ 860 EFP_CC_Info_Status_MS: 8 XXX + SG_ Rear_Panel_Btn_State : 41|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Floor_Btn_State : 40|1@0+ (1,0) [0|0] "" XXX + SG_ HtdStrWhl_SftBtt_Stt : 39|2@0+ (1,0) [0|0] "" XXX + SG_ AC_Sft_Button_State : 23|2@0+ (1,0) [0|0] "" XXX + SG_ DrvRrCondSeatSftBttnSt : 47|3@0+ (1,0) [0|0] "" XXX + SG_ DrvFrCondSeatSftBtnStt : 37|3@0+ (1,0) [0|0] "" XXX + SG_ CC_RecircSBtn_St : 27|2@0+ (1,0) [0|0] "" XXX + SG_ CC_RrDefrSBtn_St : 24|1@0+ (1,0) [0|0] "" XXX + SG_ PasRrCondSeatSftBttnSt : 44|3@0+ (1,0) [0|0] "" XXX + SG_ PasFrCondSeatSftBtnStt : 34|3@0+ (1,0) [0|0] "" XXX + SG_ MyTemp_Soft_Bttn_State : 25|1@0+ (1,0) [0|0] "" XXX + SG_ CC_MaxACSBtn_St : 28|1@0+ (1,0) [0|0] "" XXX + SG_ RearPowerButtonState : 16|1@0+ (1,0) [0|0] "" XXX + SG_ RearCoolBarsDisplayed : 11|3@0+ (1,0) [0|0] "Bars_On" XXX + SG_ Rear_Sft_Control_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ CC_RrNeutralBarDsp_St : 8|1@0+ (1,0) [0|0] "" XXX + SG_ CC_RrHeatBarsDsp_St : 31|3@0+ (1,0) [0|0] "Bars_On" XXX + SG_ Rear_Fan_Bars_Displayed : 19|3@0+ (1,0) [0|0] "" XXX + SG_ CC_RrCtrlBtn_St : 20|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Auto_Button_State : 21|1@0+ (1,0) [0|0] "" XXX + SG_ CC_FrPowerSBtn_St : 14|1@0+ (1,0) [0|0] "" XXX + SG_ CC_FrDefrostSBtn_St : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_Soft_Btn_Stt : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_MODE_State : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_FAN_State : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Dual_Button_State : 12|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarPnlSBtn_St : 5|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarPnFlrSBtn_St : 4|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarFlrWsSBtn_St : 2|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarDrvFlrSBtn_St : 3|1@0+ (1,0) [0|0] "" XXX + +BO_ 861 HSWheel_CC_Info_Stat: 8 XXX + SG_ HtdStrWhl_SftBtt_State : 57|2@0+ (1,0) [0|0] "" XXX + +BO_ 862 Climate_Control_Data_2: 8 XXX + SG_ HvacRec_Pc_Est : 31|7@0+ (1,0) [0|0] "%" XXX + SG_ HvacEngIdleInc_B_Rq : 24|1@0+ (1,0) [0|0] "" XXX + SG_ HvacAir_Flw_Est : 13|9@0+ (0.5,0) [0|0] "liter/second" XXX + SG_ AmbTempImpr : 7|10@0+ (0.25,-128.0) [0|0] "degreesC" XXX + +BO_ 900 Vehicle_Access_RqstM: 8 XXX + SG_ PE_AssocConfirm_D_Actl : 63|3@0+ (1,0) [0|0] "" XXX + SG_ DrTgateOpen_D_RqRfa : 51|2@0+ (1,0) [0|0] "" XXX + SG_ PE_Decklid_Inhibit_Rqst : 53|2@0+ (1,0) [0|0] "" XXX + SG_ PK_Program : 45|2@0+ (1,0) [0|0] "" XXX + SG_ PE_Packet_Cnt : 31|8@0+ (1,0) [0|0] "Counts" XXX + SG_ PE_Control_Status : 33|2@0+ (1,0) [0|0] "" XXX + SG_ PE_Control_Code : 7|8@0+ (1,0) [0|0] "" XXX + SG_ PE_Perimeter_Lighting_Stat : 15|2@0+ (1,0) [0|0] "" XXX + SG_ PE_RKE_Flash_Rqst : 34|1@0+ (1,0) [0|0] "" XXX + SG_ PE_Lock_EvNum : 23|8@0+ (1,0) [0|0] "Counts" XXX + SG_ PE_Lock_Requestor : 39|5@0+ (1,0) [0|0] "" XXX + SG_ PE_Lock_Sub_Id : 11|4@0+ (1,0) [0|0] "" XXX + SG_ PE_Lock_Status : 13|2@0+ (1,0) [0|0] "" XXX + SG_ PE_DrvCfg_Horn_Rqst : 47|2@0+ (1,0) [0|0] "" XXX + SG_ PEBackupSlot_Stats : 55|2@0+ (1,0) [0|0] "" XXX + SG_ PE_Fob_Number : 43|4@0+ (1,0) [0|0] "Number" XXX + SG_ PE_Keypad_LiftGlass_Rqst : 49|1@0+ (1,0) [0|0] "" XXX + +BO_ 901 Vehicle_Lock_Status: 8 XXX + SG_ CntrStkKeycodeActl : 55|16@0+ (1,0) [0|0] "" XXX + SG_ CntrStk_D_RqAssoc_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ CntrStk_D_RqAssoc : 43|3@0+ (1,0) [0|0] "" XXX + SG_ KeyTypeChngMykey_D_Rq : 45|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_Lock_Sub_Id : 21|4@0+ (1,0) [0|0] "" XXX + SG_ Veh_Lock_Status : 17|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_Lock_Requestor : 39|5@0+ (1,0) [0|0] "" XXX + SG_ Veh_Lock_EvNum : 31|8@0+ (1,0) [0|0] "Counts" XXX + SG_ Trim_Switch_Status_Count : 15|8@0+ (1,0) [0|0] "Counts" XXX + SG_ Trim_Switch_Status : 23|2@0+ (1,0) [0|0] "" XXX + SG_ DF_KeyCyl_Switch_Stat_Cnt : 7|8@0+ (1,0) [0|0] "Counts" XXX + SG_ DF_KeyCyl_Switch_Stat : 34|2@0+ (1,0) [0|0] "" XXX + SG_ Perimeter_Alarm_Status : 47|2@0+ (1,0) [0|0] "" XXX + SG_ KeyTypeChngMykey_D_Rq_UB : 32|1@0+ (1,0) [0|0] "" XXX + +BO_ 902 Remote_Start: 8 XXX + SG_ Remote_Start_Req : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 903 CC_FCIM_Update: 8 XXX + SG_ Rr_Temp_M_H_Heat_Ind : 30|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_7_Indicator : 45|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_6_Indicator : 46|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_5_Indicator : 47|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_4_Indicator : 32|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_3_Indicator : 33|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_2_Indicator : 34|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Fan_Low_Indicator : 35|1@0+ (1,0) [0|0] "" XXX + SG_ AC_Indicator : 36|1@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_Indicator : 37|1@0+ (1,0) [0|0] "" XXX + SG_ Panel_Mode_Indicator : 38|1@0+ (1,0) [0|0] "" XXX + SG_ Windshield_Mode_Indicator : 39|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_High_Cool_Ind : 24|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_M_H_Cool_Ind : 25|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_M_L_Cool_Ind : 26|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_Low_Cool_Ind : 27|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_Center_Ind_On : 28|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_High_Heat_Ind : 29|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_M_L_Heat_Ind : 31|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Temp_Low_Heat_Ind : 16|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Control_Indicator : 17|1@0+ (1,0) [0|0] "" XXX + SG_ Auto_Indicator_Rear : 18|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Indicator_Rear : 19|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_U_R_Seat_Cool_Ind : 20|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_M_Seat_Cool_Ind : 21|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_L_L_Seat_Cool_Ind : 22|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_U_R_Seat_Heat_Ind : 23|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_M_Seat_Heat_Ind : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_L_L_Seat_Heat_Ind : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_U_R_Seat_Cool_Ind : 10|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_M_Seat_Cool_Ind : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_L_L_Seat_Cool_Ind : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_U_R_Seat_Heat_Ind : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_M_Seat_Heat_Ind : 14|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_L_L_Seat_Heat_Ind : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Single_Mode_Indicator : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Auto_Indicator : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Recirc_Indicator : 2|1@0+ (1,0) [0|0] "" XXX + SG_ Max_AC_Econ_Indicator : 3|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_DefHtd_Mirr_Indicator : 4|1@0+ (1,0) [0|0] "" XXX + SG_ Defrost_Indicator : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Temp_Dual_Indicator : 6|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Indicator_Front : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 904 CC_NavChassis_Info_Status: 8 XXX + SG_ Rear_Defrost_Soft_Bttn_Stt : 52|1@0+ (1,0) [0|0] "" XXX + SG_ Recirc_Soft_Button_State : 54|2@0+ (1,0) [0|0] "" XXX + SG_ Max_AC_Soft_Button_State : 55|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_Soft_Btn_Stt : 24|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Power_Soft_Btn_State : 25|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Defrost_Soft_Btn_Stt : 26|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Power_Button_State : 33|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_FAN_Indicator : 27|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_MODE_Indicator : 28|1@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Rear_Set_Temp_Display : 17|1@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Rear_Set_Temp_Units : 19|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Heat_Bars_Displayed : 42|3@0+ (1,0) [0|0] "Bars_On" XXX + SG_ CC_Bar_Rear_Set_Temp_Dig3 : 21|2@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Rear_Set_Temp_Dig2 : 15|8@0+ (1,0) [0|0] "ASCII" XXX + SG_ CC_Bar_Rear_Set_Temp_Dig1 : 7|8@0+ (1,0) [0|0] "ASCII" XXX + SG_ Rear_Neutral_Bar_Displayed : 43|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Fan_Bars_Displayed : 46|3@0+ (1,0) [0|0] "" XXX + SG_ Rear_Control_Button_State : 47|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Auto_Button_State : 32|1@0+ (1,0) [0|0] "" XXX + SG_ AC_Sft_Button_State : 35|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Cool_Bars_Displayed : 38|3@0+ (1,0) [0|0] "Bars_On" XXX + SG_ Dual_Button_State : 39|1@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Sft_Btn_FlrWs_State : 29|1@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Sft_Btn_Floor_State : 30|1@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Sft_Btn_PnFlr_State : 31|1@0+ (1,0) [0|0] "" XXX + SG_ CC_Bar_Sft_Btn_Pnl_State : 16|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Sft_Control_Status : 23|2@0+ (1,0) [0|0] "" XXX + +BO_ 920 FCIM_CC_Status: 8 XXX + SG_ Manual_Temp_Knob_Pos : 8|9@0+ (1,0) [0|0] "Degrees CW" XXX + SG_ Manual_Blower_Knob_Pos : 24|9@0+ (1,0) [0|0] "Degrees CW" XXX + SG_ Rear_Blower_IncreaseButton : 40|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Blower_DecreaseButton : 55|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Temp_Decrease_Button : 41|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Temp_Increase_Button : 42|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Control_Button : 43|1@0+ (1,0) [0|0] "" XXX + SG_ Auto_Button_Rear : 44|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Button_Rear : 45|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_Heated_Seat_Btn : 47|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_Cooled_Seat_Btn : 46|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_Cooled_Seat_Btn : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_Heated_Seat_Btn : 10|1@0+ (1,0) [0|0] "" XXX + SG_ Blower_Decrease_Button : 25|1@0+ (1,0) [0|0] "" XXX + SG_ Blower_Increase_Button : 26|1@0+ (1,0) [0|0] "" XXX + SG_ Floor_Defrost_Mode_Button : 27|1@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_Button : 28|1@0+ (1,0) [0|0] "" XXX + SG_ Panel_Floor_Mode_Button : 29|1@0+ (1,0) [0|0] "" XXX + SG_ Panel_Mode_Button : 30|1@0+ (1,0) [0|0] "" XXX + SG_ Mode_Change_Button : 31|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_Temp_Increase : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_Temp_Decrease : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_Temp_Decrease : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Lft_Side_Temp_Increase : 14|1@0+ (1,0) [0|0] "" XXX + SG_ Auto_Button_Front : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Recirc_Button : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Max_AC_Econ_Button : 1|1@0+ (1,0) [0|0] "" XXX + SG_ AC_Button : 2|1@0+ (1,0) [0|0] "" XXX + SG_ Rr_Def_Htd_Mirr_Button : 3|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Defrost_Button : 4|1@0+ (1,0) [0|0] "" XXX + SG_ Rt_Side_Temp_Dual_Button : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Button_Front : 6|1@0+ (1,0) [0|0] "" XXX + SG_ Climate_Button : 7|1@0+ (1,0) [0|0] "" XXX + SG_ CcdMde_D_Rq : 54|2@0+ (1,0) [0|0] "" XXX + +BO_ 921 Nav_CC_Status: 8 XXX + SG_ Front_System_Button_Status : 7|5@0+ (1,0) [0|0] "" XXX + SG_ Rear_Temp_Button_Status : 23|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Man_Temp_Bar_Status : 11|4@0+ (1,0) [0|0] "" XXX + SG_ Rear_Fan_Button_Status : 13|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Man_ATC_Button_Status : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Blower_Bar_Status : 2|3@0+ (1,0) [0|0] "# of Bars" XXX + +BO_ 922 VoiceRec_CC_Request: 8 XXX + SG_ Recirculate_On : 10|1@0+ (1,0) [0|0] "" XXX + SG_ Recirculate_Off : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Defrost_On : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Defrost_Off : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Max_AC_On : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Max_AC_Off : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Defrost_On : 14|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Defrost_Off : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Blower_Increment : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Blower_Decrement : 23|1@0+ (1,0) [0|0] "" XXX + SG_ Dual_Zone_Off : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Driver_Temp_Increment : 22|1@0+ (1,0) [0|0] "" XXX + SG_ Driver_Temp_Decrement : 21|1@0+ (1,0) [0|0] "" XXX + SG_ Climate_On : 4|1@0+ (1,0) [0|0] "" XXX + SG_ Climate_Off : 3|1@0+ (1,0) [0|0] "" XXX + SG_ Automatic_Mode : 6|1@0+ (1,0) [0|0] "" XXX + SG_ AC_On : 2|1@0+ (1,0) [0|0] "" XXX + SG_ AC_Off : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Voice_Blower_Limit : 7|1@0+ (1,0) [0|0] "" XXX + SG_ Driver_Set_Temp : 31|8@0+ (0.5,0) [0|0] "Degrees" XXX + +BO_ 928 Ignition_Switch_PositionM: 8 XXX + SG_ AirAmb_Te_ActlFilt_UB : 14|1@0+ (1,0) [0|0] "" XXX + SG_ AirAmb_Te_ActlFilt : 49|10@0+ (0.25,-128.0) [0|0] "deg C" XXX + SG_ OdometerMasterValue_UB : 15|1@0+ (1,0) [0|0] "" XXX + SG_ OdometerMasterValue : 31|24@0+ (1,0) [0|0] "km" XXX + SG_ Remote_Start_Status : 13|2@0+ (1,0) [0|0] "" XXX + SG_ Key_In_Ignition_Stat : 3|2@0+ (1,0) [0|0] "" XXX + SG_ Ignition_Switch_Stable : 1|2@0+ (1,0) [0|0] "" XXX + SG_ Ignition_Status : 7|4@0+ (1,0) [0|0] "" XXX + SG_ BOO_Switch_Status : 9|2@0+ (1,0) [0|0] "" XXX + SG_ Remote_Device_Feedback : 23|3@0+ (1,0) [0|0] "" XXX + +BO_ 934 Side_Detect_L_StatusM: 8 XXX + SG_ Cross_Traffic_L_SnState : 23|2@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_L_SysOpState : 3|2@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_L_SnsrState : 1|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_L_Illum : 15|8@0+ (1,0) [0|0] "%" XXX + SG_ Side_Detect_L_Detect : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_Op_State : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_Alert : 19|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_L_Alert : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 935 Side_Detect_R_StatusM: 8 XXX + SG_ Cross_Traffic_R_Alert : 23|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_SnState : 19|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_Op_State : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_R_Detect : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_R_Illum : 15|8@0+ (1,0) [0|0] "%" XXX + SG_ SideDetect_R_SnsrState : 1|2@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_R_SysOpState : 3|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_R_Alert : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 944 Body_Information_6_MS: 8 XXX + SG_ DRV_SELECT_STAT : 3|4@0+ (1,0) [0|0] "" XXX + SG_ reserve_2bits : 7|2@0+ (1,0) [0|0] "" XXX + SG_ reserve_2 : 5|1@0+ (1,0) [0|0] "" XXX + SG_ reserve_3 : 4|1@0+ (1,0) [0|0] "" XXX + +BO_ 945 Ajar_Stat: 8 XXX + SG_ Decklid_Ajar_Status : 3|1@0+ (1,0) [0|0] "" XXX + SG_ Hood_Ajar_Status : 0|1@0+ (1,0) [0|0] "" XXX + SG_ LG_Glass_Ajar_Status : 2|1@0+ (1,0) [0|0] "" XXX + SG_ DF_Door_Ajar_Status : 7|1@0+ (1,0) [0|0] "" XXX + SG_ PF_Door_Ajar_Status : 6|1@0+ (1,0) [0|0] "" XXX + SG_ DR_Door_Ajar_Status : 5|1@0+ (1,0) [0|0] "" XXX + SG_ PR_Door_Ajar_Status : 4|1@0+ (1,0) [0|0] "" XXX + SG_ LG_Door_Ajar_Status : 1|1@0+ (1,0) [0|0] "" XXX + +BO_ 946 Body_Information_5_MS: 8 XXX + SG_ CoolantFanStepAct_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondRec_B_Rq_UB : 38|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondRec_B_Rq : 39|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondEvdc_D_Stats_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondEvdc_D_Stats : 37|3@0+ (1,0) [0|0] "" XXX + SG_ AirCondClutch_B_Stats_UB : 19|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondClutch_B_Stats : 20|1@0+ (1,0) [0|0] "" XXX + SG_ CoolantFanStepAct : 47|5@0+ (1,0) [0|0] "Steps" XXX + SG_ AirCondFluidHi_P_Actl_UB : 18|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondFluidHi_P_Actl : 31|8@0+ (0.125,0) [0|0] "bar" XXX + SG_ SECONDARY_HEATER_STAT_UB : 63|1@0+ (1,0) [0|0] "" XXX + SG_ CURRENT_DRAW_UB : 62|1@0+ (1,0) [0|0] "" XXX + SG_ SECONDARY_HEATER_STAT : 40|1@0+ (1,0) [0|0] "" XXX + SG_ CURRENT_DRAW : 55|8@0+ (0.5,0) [0|0] "Amps" XXX + +BO_ 947 BodyInformation_3_MS: 8 XXX + SG_ CamraDefog_B_Req_UB : 58|1@0+ (1,0) [0|0] "" XXX + SG_ TrStats_D_Actl_UB : 48|1@0+ (1,0) [0|0] "" XXX + SG_ RearFog_Lamp_Dbnce_UB : 49|1@0+ (1,0) [0|0] "" XXX + SG_ TrStats_D_Actl : 13|2@0+ (1,0) [0|0] "" XXX + SG_ CamraDefog_B_Req : 40|1@0+ (1,0) [0|0] "" XXX + SG_ RearFog_Lamp_Dbnce : 0|1@0+ (1,0) [0|0] "" XXX + SG_ CarMode : 53|4@0+ (1,0) [0|0] "" XXX + SG_ Day_Night_Status : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Parklamp_Status : 3|2@0+ (1,0) [0|0] "" XXX + SG_ Dimming_Lvl : 31|8@0+ (1,0) [0|0] "" XXX + SG_ Litval : 23|8@0+ (1,0) [0|0] "" XXX + SG_ Mfs_Turn_Stalk_SW_Status : 11|2@0+ (1,0) [0|0] "" XXX + SG_ PwMdeExten_D_Actl : 63|5@0+ (1,0) [0|0] "" XXX + SG_ STR_WHL_ANGLE : 39|15@0+ (0.1,-1000.0) [0|0] "Degrees" XXX + SG_ Turn_Seq_Cmd_Right : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Turn_Seq_Cmd_Left : 5|2@0+ (1,0) [0|0] "" XXX + SG_ Smart_Wiper_Motor_Stat_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Smart_Wiper_Motor_Stat : 55|2@0+ (1,0) [0|0] "" XXX + SG_ Mfs_Turn_Stalk_SW_Status_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ reserve : 1|1@0+ (1,0) [0|0] "" XXX + +BO_ 950 RKE_Packet: 8 XXX + SG_ RemoteKey_Packet_TIC : 7|32@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Packet_RollB : 55|8@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Packet_RollA : 47|8@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Packet_Ctrl : 39|8@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Packet_CkSum : 63|8@0+ (1,0) [0|0] "" XXX + +BO_ 951 TPM_Frame: 8 XXX + SG_ TirePress_Frame_Temp : 47|8@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Frame_Status : 55|8@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Frame_Press : 39|8@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Frame_ID : 7|32@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Frame_CkSum : 63|8@0+ (1,0) [0|0] "" XXX + +BO_ 952 RKE_TPM_Info: 8 XXX + SG_ TirePress_HitRate_Ctrl : 15|1@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_HitRate_Ctrl : 14|1@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Antenna_Ctrl : 7|2@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Filter_Ctrl : 5|2@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Filter_Ctrl : 3|2@0+ (1,0) [0|0] "" XXX + SG_ Modulation_Ctrl : 1|2@0+ (1,0) [0|0] "" XXX + +BO_ 953 RKE_Info: 8 XXX + SG_ RemoteKey_Info_TIC : 7|32@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Info_RollB : 55|8@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Info_RollA : 47|8@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Info_Ctrl : 39|8@0+ (1,0) [0|0] "" XXX + SG_ RemoteKey_Info_CkSum : 63|8@0+ (1,0) [0|0] "" XXX + +BO_ 954 Tire_Pressure_Info: 8 XXX + SG_ TirePress_Info_MaxInd : 47|8@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Info_Index : 39|8@0+ (1,0) [0|0] "" XXX + SG_ TirePress_Info_ID : 7|32@0+ (1,0) [0|0] "" XXX + +BO_ 956 Body_Information_7_MS: 8 XXX + SG_ GearLvrPos_D_Actl_UB : 21|1@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTot_Tq_Actl : 31|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ GearLvrPos_D_Actl : 7|4@0+ (1,0) [0|0] "" XXX + SG_ ApedPos_Pc_ActlArb : 15|10@0+ (0.1,0) [0|0] "%" XXX + SG_ PrplWhlTot_Tq_Actl_UB : 17|1@0+ (1,0) [0|0] "" XXX + SG_ EngOff_T_Actl : 47|16@0+ (1,0) [0|0] "seconds" XXX + SG_ ApedPos_Pc_ActlArb_UB : 20|1@0+ (1,0) [0|0] "" XXX + +BO_ 958 Rear_FoglampStat: 8 XXX + SG_ RearFog_Lamp_Ind : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 963 BCM_to_MS_Body: 8 XXX + SG_ LF_Low_Beam_CKT_CAN : 2|1@0+ (1,0) [0|0] "" XXX + SG_ IKT_Program_Status : 51|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_Spd_Slow_Puddle_Status : 41|2@0+ (1,0) [0|0] "" XXX + SG_ Illuminated_Exit_Status : 43|2@0+ (1,0) [0|0] "" XXX + SG_ Illuminated_Entry_Status : 45|2@0+ (1,0) [0|0] "" XXX + SG_ Door_Courtesy_Light_Status : 47|2@0+ (1,0) [0|0] "" XXX + SG_ Courtesy_Demand_BSave_Stat : 33|2@0+ (1,0) [0|0] "" XXX + SG_ Alarm_Lights_Courtesy_Stat : 35|2@0+ (1,0) [0|0] "" XXX + SG_ Courtesy_Delay_Status : 37|2@0+ (1,0) [0|0] "" XXX + SG_ Courtesy_Mode_Status : 39|2@0+ (1,0) [0|0] "" XXX + SG_ Front_Fog_Light_SW_Status : 22|2@0+ (1,0) [0|0] "" XXX + SG_ Brake_Lamp_On_Status : 23|1@0+ (1,0) [0|0] "" XXX + SG_ ParkLamps_CKT_CAN : 8|1@0+ (1,0) [0|0] "" XXX + SG_ RF_Low_Beam_CKT_CAN : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Brk_Fluid_Lvl_Low : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Park_Brake_Status : 4|1@0+ (1,0) [0|0] "" XXX + SG_ High_Beam_Indicator_Rqst : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Headlamp_On_Wrning_Cmd : 6|1@0+ (1,0) [0|0] "" XXX + SG_ Key_In_Ignition_Warn_Cmd : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Park_Brake_Chime_Rqst : 3|1@0+ (1,0) [0|0] "" XXX + SG_ Daytime_Running_Lamps : 0|1@0+ (1,0) [0|0] "" XXX + SG_ AutoHighBeam_Cmd : 18|2@0+ (1,0) [0|0] "" XXX + SG_ Perimeter_Alarm_Chime_Rqst : 20|2@0+ (1,0) [0|0] "" XXX + SG_ OCSSensrDataUpperLim_UB : 11|1@0+ (1,0) [0|0] "" XXX + SG_ OCSSensrDataLowerLim_UB : 12|1@0+ (1,0) [0|0] "" XXX + SG_ OCSSensrDataUpperLim : 63|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSensrDataLowerLim : 31|8@0+ (1,0) [0|0] "" XXX + SG_ AutoHighBeam_Cmd_UB : 16|1@0+ (1,0) [0|0] "" XXX + SG_ PrkBrkActv_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + SG_ Headlamp_Switch_Stat : 49|2@0+ (1,0) [0|0] "" XXX + SG_ Perimeter_Alarm_Inclin_Cmd : 53|2@0+ (1,0) [0|0] "" XXX + SG_ Perimeter_Alarm_Intrus_Cmd : 55|2@0+ (1,0) [0|0] "" XXX + +BO_ 964 BodyInformation_2_MS: 8 XXX + SG_ LockInhibit : 41|1@0+ (1,0) [0|0] "" XXX + SG_ MetricActvTe_B_Actl_UB : 12|1@0+ (1,0) [0|0] "" XXX + SG_ MetricActvTe_B_Actl : 14|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Liftgate_Mode_Cmd : 42|1@0+ (1,0) [0|0] "" XXX + SG_ AirAmb_Te_Actl : 55|10@0+ (0.25,-128.0) [0|0] "degC" XXX + SG_ EngClntTe_D_Qf : 47|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_Cmd : 26|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_Cmd : 28|2@0+ (1,0) [0|0] "" XXX + SG_ SAPPStatusCoding : 39|8@0+ (1,0) [0|0] "" XXX + SG_ Delay_Accy : 31|1@0+ (1,0) [0|0] "" XXX + SG_ Volume_Cutback : 7|1@0+ (1,0) [0|0] "" XXX + SG_ MetricActv_B_Actl : 0|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatTgate_B_Actl : 1|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatRr_B_Actl : 2|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatRl_B_Actl : 3|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatPsngr_B_Actl : 4|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatInnrTgate_B_Actl : 5|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatHood_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatDrv_B_Actl : 10|1@0+ (1,0) [0|0] "" XXX + SG_ EngClnt_Te_Actl : 23|8@0+ (1,-60.0) [0|0] "degC" XXX + SG_ AirAmbTe_D_Qf_UB : 59|1@0+ (1,0) [0|0] "" XXX + SG_ Volume_Cutback_UB : 58|1@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_Cmd_UB : 57|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPStatusCoding_UB : 56|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Liftgate_Mode_Cmd_UB : 15|1@0+ (1,0) [0|0] "" XXX + SG_ MetricActv_B_Actl_UB : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_Cmd_UB : 11|1@0+ (1,0) [0|0] "" XXX + SG_ AirAmbTe_D_Qf : 61|2@0+ (1,0) [0|0] "" XXX + SG_ AirAmb_Te_Actl_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ EngClnt_Te_Actl_UB : 24|1@0+ (1,0) [0|0] "" XXX + +BO_ 966 Delay_AccyM_for_P473: 8 XXX + SG_ Delay_Accy : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 967 CMPS_FDM_Info_StatusMS: 8 XXX + SG_ Segment_MSD_UB : 37|1@0+ (1,0) [0|0] "" XXX + SG_ Segment_LSD_UB : 36|1@0+ (1,0) [0|0] "" XXX + SG_ Compass_Display_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ Segment_LSD : 15|8@0+ (1,0) [0|0] "" XXX + SG_ Segment_MSD : 7|8@0+ (1,0) [0|0] "" XXX + SG_ Cal_Icon : 21|1@0+ (1,0) [0|0] "" XXX + SG_ Zone_Icon : 22|1@0+ (1,0) [0|0] "" XXX + SG_ Compass_Display : 23|1@0+ (1,0) [0|0] "" XXX + SG_ Zone_Icon_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ Cal_Icon_UB : 33|1@0+ (1,0) [0|0] "" XXX + +BO_ 968 EATC_FDM_Info_Status: 8 XXX + SG_ Outside_Rear_Temp_Digit3 : 47|4@0+ (1,0) [0|0] "BCD" XXX + SG_ Outside_Rear_Temp_Digit2 : 35|4@0+ (1,0) [0|0] "BCD" XXX + SG_ Outside_Rear_Temp_Digit1 : 39|4@0+ (1,0) [0|0] "BCD" XXX + SG_ EATC_Out_Rear_Units : 58|2@0+ (1,0) [0|0] "" XXX + SG_ Outside_Rear_Temp_Digit4 : 55|2@0+ (1,0) [0|0] "" XXX + SG_ EATC_RHS_Units : 60|2@0+ (1,0) [0|0] "" XXX + SG_ EATC_Fan_Speed : 51|3@0+ (1,0) [0|0] "" XXX + SG_ EATC_Outside_Rear_Display : 62|2@0+ (1,0) [0|0] "" XXX + SG_ RHS_Temp_Display_Digit2 : 31|8@0+ (1,0) [0|0] "ASCII" XXX + SG_ RHS_Temp_Display_Digit3 : 41|2@0+ (1,0) [0|0] "" XXX + SG_ RHS_Temp_Display_Digit1 : 23|8@0+ (1,0) [0|0] "ASCII" XXX + SG_ EATC_RHS_Display : 63|1@0+ (1,0) [0|0] "" XXX + SG_ LHS_Temp_Display_Digit3 : 43|2@0+ (1,0) [0|0] "" XXX + SG_ LHS_Temp_Display_Digit2 : 15|8@0+ (1,0) [0|0] "ASCII" XXX + SG_ LHS_Temp_Display_Digit1 : 7|8@0+ (1,0) [0|0] "ASCII" XXX + SG_ EATC_LHS_Display : 48|1@0+ (1,0) [0|0] "" XXX + SG_ EATC_LHS_Units : 53|2@0+ (1,0) [0|0] "" XXX + +BO_ 969 Aux_Body_Ctrl_Mod_Status: 8 XXX + SG_ Perimeter_Alrm_Intrus_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Turn_Outage_Stat_Rt_Rear : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Turn_Outage_Stat_Left_Rear : 1|2@0+ (1,0) [0|0] "" XXX + SG_ Perimeter_Alrm_Inclin_Stat : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 976 Veh_Characteristic_Set_2: 8 XXX + SG_ VehMykey_Vl_LimRq_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ CamraFrntStat_D_Stat : 21|2@0+ (1,0) [0|0] "" XXX + SG_ CamraZoomMan_D_Actl : 12|3@0+ (1,0) [0|0] "" XXX + SG_ CamZoomActiveState : 17|2@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlStat_D_Actl : 19|2@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlDyn_D_Actl : 39|2@0+ (1,0) [0|0] "" XXX + SG_ CamPDCGuidStat : 31|2@0+ (1,0) [0|0] "" XXX + SG_ VehMykey_Vl_LimRq : 14|1@0+ (1,0) [0|0] "" XXX + SG_ IgnKeyType_D_Actl : 4|4@0+ (1,0) [0|0] "" XXX + SG_ New_Module_Attn_Event : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Beltminder_Warn_Stats : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Attn_Info_Audio : 7|3@0+ (1,0) [0|0] "" XXX + +BO_ 977 ClmtCtrlSeat_SetCmd_LRPM: 8 XXX + SG_ ClmtCtrlSeat_SetCmd_LRP : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 978 ClmtCtrlSeat_SetStat_LRPM: 8 XXX + SG_ ClmtCtrlSeat_SetStat_LRP : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 979 ClmtCtrlSeat_SetCmd_RRPM: 8 XXX + SG_ ClmtCtrlSeat_SetCmd_RRP : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 980 ClmtCtrlSeat_SetStat_RRPM: 8 XXX + SG_ ClmtCtrlSeat_SetStat_RRP : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 981 Rear_HVAC_Control_Status: 8 XXX + SG_ Temp_Knob_Position : 23|9@0+ (1,0) [0|0] "Degrees CW" XXX + SG_ Rear_Lock_Ind_State : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Blower_Knob_Position : 7|9@0+ (1,0) [0|0] "Degrees CW" XXX + SG_ AUTO_Ind_State : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Panel_Mode_Ind_State : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Panel_Floor_Md_Ind_State : 10|2@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_Ind_State : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Status : 14|1@0+ (1,0) [0|0] "" XXX + +BO_ 982 Rear_HVAC_Control_Update: 8 XXX + SG_ Power_State_Commanded : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Lock_Indicator : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Panel_Floor_Mode_Indicator : 4|2@0+ (1,0) [0|0] "" XXX + SG_ R_Floor_Mode_Indicator : 2|1@0+ (1,0) [0|0] "" XXX + SG_ AUTO_Mode_Indicator : 1|2@0+ (1,0) [0|0] "" XXX + SG_ F_Panel_Mode_Indicator : 13|1@0+ (1,0) [0|0] "" XXX + SG_ R_Panel_Mode_Indicator : 12|2@0+ (1,0) [0|0] "" XXX + +BO_ 986 Personality_APIM_Data3_MS: 8 XXX + SG_ LightAmbIntSwtchInc_B : 22|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbIntSwtchDec_B : 21|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbIntsty_No_Rq : 15|8@0+ (1,0) [0|0] "% Intensity" XXX + SG_ LightAmbColor_No_Rq : 7|8@0+ (1,0) [0|0] "Color Index" XXX + SG_ LightAmbClrSwtchInc_B : 20|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbClrSwtchDec_B : 23|1@0+ (1,0) [0|0] "" XXX + +BO_ 987 RHVAC_Data: 8 XXX + SG_ CamraDefog_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 992 Personality_Data_MS: 8 XXX + SG_ PersSetupRestr_D_Actl : 45|2@0+ (1,0) [0|0] "" XXX + SG_ PersSetupAccessCtrl : 43|1@0+ (1,0) [0|0] "SES" XXX + SG_ PersSetup_No_Actl : 55|16@0+ (1,0) [0|0] "Number" XXX + SG_ MsgCntrPersIndex_D_Rq_UB : 47|1@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrFeatNoRq_UB : 46|1@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrFeatConfigRq_UB : 33|1@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrDsplyOp_D_Rq_UB : 32|1@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrPersIndex_D_Rq : 39|3@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrFeatConfigRq : 23|16@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrFeatNoRq : 7|16@0+ (1,0) [0|0] "Number" XXX + SG_ MsgCntrDsplyOp_D_Rq : 36|3@0+ (1,0) [0|0] "" XXX + +BO_ 993 Personality_DSM_Data: 8 XXX + SG_ PersIndexDsm_D_Actl : 47|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoDsmActl : 31|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigDsmActl : 15|16@0+ (1,0) [0|0] "" XXX + SG_ PersStore_D_Actl : 7|2@0+ (1,0) [0|0] "" XXX + SG_ MemSwtch_D_RqRecall : 5|3@0+ (1,0) [0|0] "" XXX + SG_ MemSwtch_D_RqAssoc : 2|3@0+ (1,0) [0|0] "" XXX + +BO_ 994 Personality_Data_MS_2: 8 XXX + SG_ RecallEvent_No_Cnt : 63|8@0+ (1,0) [0|0] "Counts" XXX + SG_ PersNo_D_Actl : 55|3@0+ (1,0) [0|0] "" XXX + SG_ PersNoPos_D_Actl : 44|3@0+ (1,0) [0|0] "" XXX + SG_ PersStore_D_Rq_UB : 41|1@0+ (1,0) [0|0] "" XXX + SG_ CtrStkPersIndex_D_Actl_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ CtrStkFeatNoActl_UB : 52|1@0+ (1,0) [0|0] "" XXX + SG_ CtrStkFeatConfigActl_UB : 33|1@0+ (1,0) [0|0] "" XXX + SG_ CtrStkDsplyOp_D_Rq_UB : 32|1@0+ (1,0) [0|0] "" XXX + SG_ CtrStkPersIndex_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ CtrStkFeatNoActl : 23|16@0+ (1,0) [0|0] "" XXX + SG_ PersStore_D_Rq : 36|3@0+ (1,0) [0|0] "" XXX + SG_ CtrStkFeatConfigActl : 7|16@0+ (1,0) [0|0] "" XXX + SG_ CtrStkDsplyOp_D_Rq : 47|3@0+ (1,0) [0|0] "" XXX + +BO_ 996 Personality_HCMB_Data: 8 XXX + SG_ PersIndexHcmb_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoHcmbActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigHcmbActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 999 Personality_HVAC_Data: 8 XXX + SG_ LightAmbIntsty_No_Actl : 55|8@0+ (1,0) [0|0] "% Intensity" XXX + SG_ LightAmbColor_No_Actl : 47|8@0+ (1,0) [0|0] "Color Index" XXX + SG_ PersIndexHvac_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoHvacActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigHvacActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1000 ACM_Status_Message: 8 XXX + SG_ Multimedia_System : 26|1@0+ (1,0) [0|0] "" XXX + +BO_ 1001 Personality_RFA_Data: 8 XXX + SG_ PersIndexRfa_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoRfaActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigRfaActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1005 Personality_RHVAC_Data: 8 XXX + SG_ PersIndexRhvac_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoRhvacActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigRhvacActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1006 Nav_HMI_Status: 8 XXX + SG_ Nav_Unit_Setting : 14|1@0+ (1,0) [0|0] "" XXX + SG_ Fuel_Econ_AFE_Reset_Req : 15|1@0+ (1,0) [0|0] "" XXX + SG_ DistanceBarSetting : 23|1@0+ (1,0) [0|0] "" XXX + SG_ CamraZoomMan_D_Rq : 22|3@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlStat_D_Rq : 19|1@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlDyn_D_Rq : 18|1@0+ (1,0) [0|0] "" XXX + SG_ CamAutoTowbarZoom : 17|1@0+ (1,0) [0|0] "" XXX + +BO_ 1023 Reserve_3FF_MKX_Audio: 8 XXX + SG_ reserve : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 1034 GGCC_Config_Mgmt_ID_1: 8 XXX + SG_ VehicleGGCCData : 7|64@0+ (1,0) [0|0] "mixed" XXX + +BO_ 1050 Climate_Control_Data: 8 XXX + SG_ SecondaryHeater_Rqst : 31|1@0+ (1,0) [0|0] "" XXX + SG_ Passenger_Sunload_Raw : 15|8@0+ (5.0,0) [0|0] "W/m^2" XXX + SG_ Driver_Sunload_Raw : 7|8@0+ (5.0,0) [0|0] "W/m^2" XXX + SG_ HvacEvap_Te_Rq : 43|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ HvacRemoteStrt_N_Rq : 47|4@0+ (100.0,450.0) [0|0] "RPM" XXX + SG_ Remote_Start_QuietMode : 28|1@0+ (1,0) [0|0] "" XXX + SG_ InCarTempQF : 30|2@0+ (1,0) [0|0] "" XXX + SG_ HvacAirCond_B_Rq : 27|1@0+ (1,0) [0|0] "" XXX + SG_ InCarTemp : 39|8@0+ (0.5,-57.0) [0|0] "degreesC" XXX + SG_ Outside_Air_Temp_Stat : 23|8@0+ (0.5,-40.0) [0|0] "Degrees C" XXX + SG_ HvacEvap_Te_Actl : 49|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + +BO_ 1059 Engine_Data_MS: 8 XXX + SG_ Res_UreaLvlLo_B_Dsply_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ Res_UreaLvlLo_B_Dsply : 36|1@0+ (1,0) [0|0] "" XXX + SG_ Fuel_Level_State : 47|2@0+ (1,0) [0|0] "" XXX + SG_ AwdOffRoadMode_D_Stats_UB : 55|1@0+ (1,0) [0|0] "" XXX + SG_ AwdRnge_D_Actl_UB : 42|1@0+ (1,0) [0|0] "" XXX + SG_ RearDiffLckLamp_D_Rq_UB : 32|1@0+ (1,0) [0|0] "" XXX + SG_ AwdOffRoadMode_D_Stats : 41|2@0+ (1,0) [0|0] "" XXX + SG_ AwdRnge_D_Actl : 45|3@0+ (1,0) [0|0] "" XXX + SG_ RearDiffLckLamp_D_Rq : 34|2@0+ (1,0) [0|0] "" XXX + SG_ VEH_SPD : 7|16@0+ (0.01,-100.0) [0|0] "KPH" XXX + SG_ ENG_SPD : 23|16@0+ (0.25,0) [0|0] "RPM" XXX + SG_ Fuel_Level_State_UB : 37|1@0+ (1,0) [0|0] "" XXX + +BO_ 1061 Engine_Data_2_MS: 8 XXX + SG_ RstrnImpactEvntStatus_UB : 56|1@0+ (1,0) [0|0] "" XXX + SG_ EngAirIn_Te_Actl_UB : 60|1@0+ (1,0) [0|0] "" XXX + SG_ EngAirIn_Te_Actl : 55|10@0+ (0.25,-128.0) [0|0] "degC" XXX + SG_ ACCompressorDisp_UB : 61|1@0+ (1,0) [0|0] "" XXX + SG_ ACCompressorDisp : 46|7@0+ (1,0) [0|0] "%" XXX + SG_ RstrnImpactEvntStatus : 59|3@0+ (1,0) [0|0] "" XXX + SG_ EngAout_N_Actl_UB : 47|1@0+ (1,0) [0|0] "" XXX + SG_ EngAout_N_Actl : 28|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ VehVActlEng_D_Qf : 31|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_ActlEng_UB : 29|1@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_ActlEng : 15|16@0+ (0.01,0) [0|0] "kph" XXX + SG_ PwPck_D_Stat_UB : 3|1@0+ (1,0) [0|0] "" XXX + SG_ PwPck_D_Stat : 7|4@0+ (1,0) [0|0] "" XXX + +BO_ 1062 ACM_NAV_WHEEL_INFO: 8 XXX + SG_ WhlRotatRr_No_Cnt_UB : 63|1@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatRl_No_Cnt_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFr_No_Cnt_UB : 41|1@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFl_No_Cnt_UB : 42|1@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRr_D_Actl_UB : 44|1@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRl_D_Actl_UB : 45|1@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFr_D_Actl_UB : 46|1@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFl_D_Actl_UB : 47|1@0+ (1,0) [0|0] "" XXX + SG_ WHEEL_ROLLING_TIMESTAMP_UB : 62|1@0+ (1,0) [0|0] "" XXX + SG_ ACM_NAV_WHEEL_INFO_RESET : 43|1@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatRr_No_Cnt : 39|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatRl_No_Cnt : 31|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFr_No_Cnt : 23|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFl_No_Cnt : 15|8@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRr_D_Actl : 1|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRl_D_Actl : 3|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFr_D_Actl : 5|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFl_D_Actl : 7|2@0+ (1,0) [0|0] "" XXX + SG_ WHEEL_ROLLING_TIMESTAMP : 55|8@0+ (1,0) [0|0] "" XXX + +BO_ 1068 Battery_Mgmt_2_MS: 8 XXX + SG_ Shed_T_Eng_Off_B : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Shed_Level_Req : 15|3@0+ (1,0) [0|0] "" XXX + SG_ Shed_Feature_Group_ID : 7|5@0+ (1,0) [0|0] "" XXX + SG_ Shed_Drain_Eng_Off_B : 2|1@0+ (1,0) [0|0] "" XXX + SG_ Batt_Lo_SoC_B : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Batt_Crit_SoC_B : 0|1@0+ (1,0) [0|0] "" XXX + +BO_ 1125 GPS_Data_Nav_1: 8 XXX + SG_ GpsHsphLattSth_D_Actl : 25|2@0+ (1,0) [0|0] "" XXX + SG_ GpsHsphLongEast_D_Actl : 9|2@0+ (1,0) [0|0] "" XXX + SG_ GPS_Longitude_Minutes : 46|6@0+ (1,0) [0|0] "Minutes" XXX + SG_ GPS_Longitude_Min_dec : 55|14@0+ (0.0001,0) [0|0] "Minutes" XXX + SG_ GPS_Longitude_Degrees : 39|9@0+ (1,-179.0) [0|0] "Degrees" XXX + SG_ GPS_Latitude_Minutes : 15|6@0+ (1,0) [0|0] "Minutes" XXX + SG_ GPS_Latitude_Min_dec : 23|14@0+ (0.0001,0) [0|0] "Minutes" XXX + SG_ GPS_Latitude_Degrees : 7|8@0+ (1,-89.0) [0|0] "Degrees" XXX + +BO_ 1126 GPS_Data_Nav_2: 8 XXX + SG_ Gps_B_Falt : 2|1@0+ (1,0) [0|0] "" XXX + SG_ GpsUtcYr_No_Actl : 55|5@0+ (1,1.0) [0|0] "Year" XXX + SG_ GpsUtcMnth_No_Actl : 47|4@0+ (1,1.0) [0|0] "Month" XXX + SG_ GpsUtcDay_No_Actl : 37|5@0+ (1,1.0) [0|0] "Day" XXX + SG_ GPS_UTC_seconds : 23|6@0+ (1,0) [0|0] "seconds" XXX + SG_ GPS_UTC_minutes : 15|6@0+ (1,0) [0|0] "Minutes" XXX + SG_ GPS_UTC_hours : 7|5@0+ (1,0) [0|0] "Hours" XXX + SG_ GPS_Pdop : 31|5@0+ (0.2,0) [0|0] "" XXX + SG_ GPS_Compass_direction : 26|4@0+ (1,0) [0|0] "" XXX + SG_ GPS_Actual_vs_Infer_pos : 38|1@0+ (1,0) [0|0] "" XXX + +BO_ 1127 GPS_Data_Nav_3: 8 XXX + SG_ GPS_Vdop : 63|5@0+ (0.2,0) [0|0] "" XXX + SG_ GPS_Speed : 47|8@0+ (1,0) [0|0] "MPH" XXX + SG_ GPS_Sat_num_in_view : 7|5@0+ (1,0) [0|0] "" XXX + SG_ GPS_MSL_altitude : 15|12@0+ (10.0,-20460.0) [0|0] "feet" XXX + SG_ GPS_Heading : 31|16@0+ (0.01,0) [0|0] "Degrees" XXX + SG_ GPS_Hdop : 55|5@0+ (0.2,0) [0|0] "" XXX + SG_ GPS_dimension : 2|3@0+ (1,0) [0|0] "" XXX + +BO_ 1144 GPS_Data_Nav_4: 8 XXX + SG_ VehPos_L_Est : 39|32@0+ (0.01,0) [0|0] "meter" XXX + SG_ VehHead_W_Actl : 23|16@0+ (0.01,-327.68) [0|0] "degrees/second" XXX + SG_ VehHead_An_Est : 7|16@0+ (0.01,0) [0|0] "degrees" XXX diff --git a/opendbc_repo/opendbc/dbc/ford_cgea1_2_ptcan_2011.dbc b/opendbc_repo/opendbc/dbc/ford_cgea1_2_ptcan_2011.dbc new file mode 100644 index 0000000000..128721cbbf --- /dev/null +++ b/opendbc_repo/opendbc/dbc/ford_cgea1_2_ptcan_2011.dbc @@ -0,0 +1,1487 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 65 Global_PATS_Control_Info: 8 XXX + SG_ immoControlData_T1 : 15|40@0+ (1,0) [0|0] "" XXX + SG_ immoControlCmd_T1 : 7|3@0+ (1,0) [0|0] "" XXX + +BO_ 66 Global_PATS_Control_Info2: 8 XXX + SG_ immoControlData_T2 : 15|40@0+ (1,0) [0|0] "" XXX + SG_ immoControlCmd_T2 : 7|3@0+ (1,0) [0|0] "" XXX + +BO_ 71 Global_PATS_Target_Info: 8 XXX + SG_ immoTarget1Status : 7|3@0+ (1,0) [0|0] "" XXX + SG_ immoTarget1Data : 15|40@0+ (1,0) [0|0] "" XXX + SG_ immoTarget1Cmd : 4|3@0+ (1,0) [0|0] "" XXX + +BO_ 72 Global_PATS_Target_Info_2: 8 XXX + SG_ immoTarget2Status : 7|3@0+ (1,0) [0|0] "" XXX + SG_ immoTarget2Data : 15|40@0+ (1,0) [0|0] "" XXX + SG_ immoTarget2Cmd : 4|3@0+ (1,0) [0|0] "" XXX + +BO_ 73 Global_PATS_SubTarget_FoE: 8 XXX + SG_ immoSubTarget1Data_T1 : 15|40@0+ (1,0) [0|0] "" XXX + SG_ immoSubTarget1Cmd_T1 : 7|3@0+ (1,0) [0|0] "" XXX + +BO_ 74 VehEmergencyData1: 8 XXX + SG_ VedsPasSideBag_D_Ltchd : 60|3@0+ (1,0) [0|0] "" XXX + SG_ VedsPasCrtnBag_D_Ltchd : 55|3@0+ (1,0) [0|0] "" XXX + SG_ VedsPasBelt_D_Ltchd : 52|3@0+ (1,0) [0|0] "" XXX + SG_ VedsPasBag_D_Ltchd : 47|3@0+ (1,0) [0|0] "" XXX + SG_ VedsMultiEvnt_D_Ltchd : 44|3@0+ (1,0) [0|0] "" XXX + SG_ VedsMaxDeltaV_D_Ltchd : 39|8@0+ (1,0) [0|0] "" XXX + SG_ VedsKneeBag_D_Ltchd : 63|3@0+ (1,0) [0|0] "" XXX + SG_ VedsEvntType_D_Ltchd : 31|3@0+ (1,0) [0|0] "" XXX + SG_ VedsEvntRoll_D_Ltchd : 28|3@0+ (1,0) [0|0] "" XXX + SG_ VedsDrvSideBag_D_Ltchd : 23|3@0+ (1,0) [0|0] "" XXX + SG_ VedsDrvCrtnBag_D_Ltchd : 20|3@0+ (1,0) [0|0] "" XXX + SG_ VedsDrvBelt_D_Ltchd : 15|3@0+ (1,0) [0|0] "" XXX + SG_ VedsDrvBag_D_Ltchd : 12|3@0+ (1,0) [0|0] "" XXX + SG_ eCallNotification : 2|2@0+ (1,0) [0|0] "" XXX + +BO_ 75 VehEmergencyData2: 8 XXX + SG_ VedsRw3rBckl_D_Ltchd : 39|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw3mBckl_D_Ltchd : 31|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw3lBckl_D_Ltchd : 28|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw2rBckl_D_Ltchd : 23|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw2mBckl_D_Ltchd : 20|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw2lBckl_D_Ltchd : 15|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw1PasChld_D_Ltchd : 12|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw1PasBckl_D_Ltchd : 7|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw1DrvBckl_D_Ltchd : 4|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw2rRib_D_Ltchd : 47|3@0+ (1,0) [0|0] "" XXX + SG_ VedsRw2lRib_D_Ltchd : 36|3@0+ (1,0) [0|0] "" XXX + +BO_ 116 BrakeSnData_2_CG1: 8 XXX + SG_ VehDynamicsSOS : 55|1@0+ (1,0) [0|0] "" XXX + SG_ AwdLck_Tq_RqMx : 27|12@0+ (1,0) [0|0] "Nm" XXX + SG_ AwdLck_Tq_RqMn : 23|12@0+ (1,0) [0|0] "Nm" XXX + SG_ SteWhlComp_An_Est : 7|15@0+ (0.1,-1600.0) [0|0] "deg" XXX + SG_ StopLamp_B_RqBrk : 8|1@0+ (1,0) [0|0] "" XXX + SG_ BrkTerrMdeChng_D_Rdy : 45|3@0+ (1,0) [0|0] "" XXX + SG_ BrkTerrMde_D_Actl : 42|3@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCompAnEst_D_Qf : 47|2@0+ (1,0) [0|0] "" XXX + +BO_ 117 BrakeSnData_3_CG1: 8 XXX + SG_ HsaStat_D_Dsply : 35|3@0+ (1,0) [0|0] "" XXX + SG_ HsaTrnAout_Tq_Rq : 55|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ HsaStat_D_Actl : 38|3@0+ (1,0) [0|0] "" XXX + SG_ HsaRoad_Grad_Est : 32|9@0+ (0.5,-127.0) [0|0] "%" XXX + SG_ VehYawComp_W_Actl : 7|12@0+ (0.03663,-75.0) [0|0] "deg/s" XXX + SG_ VehYaw_W_Rq : 11|12@0+ (0.03663,-75.0) [0|0] "deg/s" XXX + SG_ VehSideSlip_An_Est : 31|9@0+ (0.002,-0.5) [0|0] "rad" XXX + +BO_ 124 BrakeSnData_4_CG1: 8 XXX + SG_ EngRun_D_ReqBrk : 10|2@0+ (1,0) [0|0] "" XXX + SG_ BrkTotTqRqArb_No_Cs : 23|8@0+ (1,0) [0|0] "" XXX + SG_ BrkTotTqRqArb_No_Cnt : 31|4@0+ (1,0) [0|0] "" XXX + SG_ BrkTot_Tq_RqArb : 7|13@0+ (4.0,0) [0|0] "Nm" XXX + SG_ BrkTot_Tq_Actl : 39|13@0+ (4.0,0) [0|0] "Nm" XXX + SG_ VehOverGnd_V_Est : 55|16@0+ (0.01,0) [0|0] "kph" XXX + +BO_ 129 Steering_Wheel_Data2: 8 XXX + SG_ SteWhlCtl_RSide_OK : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_RSide_CursorUp : 8|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_RSide_CursorRt : 7|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_RSide_CursorLeft : 6|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_RSide_CursorDown : 5|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_LSide_OK : 4|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_LSide_CursorUp : 3|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_LSide_CursorRt : 2|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_LSide_CursorLeft : 1|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_LSide_CursorDown : 0|1@0+ (1,0) [0|0] "" XXX + +BO_ 130 EPAS_INFO: 8 XXX + SG_ SteMdule_U_Meas : 39|8@0+ (0.05,6.0) [0|0] "Volts" XXX + SG_ SteMdule_I_Est : 21|12@0+ (0.05,-64.0) [0|0] "Amps" XXX + SG_ EPAS_FAILURE : 9|2@0+ (1,0) [0|0] "" XXX + SG_ SteeringColumnTorque : 7|8@0+ (0.0625,-8.0) [0|0] "Nm" XXX + SG_ SAPPAngleControlStat6 : 15|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat5 : 14|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat4 : 13|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat3 : 12|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat2 : 11|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat1 : 23|2@0+ (1,0) [0|0] "" XXX + +BO_ 131 Steering_Data: 8 XXX + SG_ SteWhlCtl_Mute : 38|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Mode : 24|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_OK : 23|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Phone : 22|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_End : 21|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Send : 20|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Voice_PTT : 19|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Seek_Left : 10|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Seek_Right : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Media : 8|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Volume_Down : 6|1@0+ (1,0) [0|0] "" XXX + SG_ SteWhlCtl_Volume_Up : 7|1@0+ (1,0) [0|0] "" XXX + SG_ Smart_Wiper_Motor_Stat : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Mfs_Turn_Stalk_SW_Status : 1|2@0+ (1,0) [0|0] "" XXX + SG_ HighBeam_FlashToPassSw : 3|2@0+ (1,0) [0|0] "" XXX + SG_ SteColumn_Status : 13|3@0+ (1,0) [0|0] "" XXX + SG_ SteCol_Manual_Override : 4|1@0+ (1,0) [0|0] "" XXX + SG_ CcButtnStat_D_Actl : 34|11@0+ (1,0) [0|0] "" XXX + SG_ HeatedWash_Mode_Stat : 55|3@0+ (1,0) [0|0] "" XXX + SG_ LaSwtchPos_D_Stat : 18|2@0+ (1,0) [0|0] "" XXX + +BO_ 132 Steering_Wheel_Data_CG1: 8 XXX + SG_ SteWhlRelInit_An_Sns : 7|15@0+ (0.1,-1600.0) [0|0] "deg" XXX + SG_ SteWhlRelCalib_An_Sns : 23|15@0+ (0.1,-1600.0) [0|0] "deg" XXX + SG_ SteWhlRelInit2_An_Sns : 55|16@0+ (0.1,-3200.0) [0|0] "deg" XXX + SG_ SteWhlAn_No_Cs : 39|8@0+ (1,0) [0|0] "" XXX + SG_ SteWhlAn_No_Cnt : 47|4@0+ (1,0) [0|0] "Counts" XXX + +BO_ 145 Yaw_Data: 8 XXX + SG_ VehYaw_W_Actl : 39|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + SG_ VehRol_W_Actl : 23|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + SG_ VehPtch_W_Actl : 7|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + +BO_ 146 Accel_Data: 8 XXX + SG_ VehVertAActl_D_Qf : 38|2@0+ (1,0) [0|0] "" XXX + SG_ VehLongAActl_D_Qf : 22|2@0+ (1,0) [0|0] "" XXX + SG_ VehLatAActl_D_Qf : 6|2@0+ (1,0) [0|0] "" XXX + SG_ VehVert_A_Actl : 36|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX + SG_ VehLong_A_Actl : 20|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX + SG_ VehLat_A_Actl : 4|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX + +BO_ 258 Cluster_Legacy: 8 XXX + SG_ Veh_V_CompLimMx : 27|12@0+ (0.1,0) [0|0] "km/h" XXX + SG_ DISPLAY_SPEED_SCALING : 20|4@0+ (0.5,100.0) [0|0] "%" XXX + SG_ DISPLAY_SPEED_OFFSET : 23|3@0+ (0.5,0) [0|0] "kph" XXX + SG_ Reverse_Mirror_Cmd : 10|1@0+ (1,0) [0|0] "" XXX + SG_ Autolamp_Delay_Cmd : 7|8@0+ (1,0) [0|0] "Seconds" XXX + SG_ Running_Board_Cmd : 13|2@0+ (1,0) [0|0] "" XXX + SG_ Power_Liftgate_Mode_Cmd : 11|1@0+ (1,0) [0|0] "" XXX + +BO_ 259 Body_MsgCntr_Stat_CG1: 8 XXX + SG_ PE_PEPS_System_Stat : 47|8@0+ (1,0) [0|0] "" XXX + SG_ Keycode_Status : 11|20@0+ (1,0) [0|0] "" XXX + SG_ Autolamp_Delay_Stat : 7|8@0+ (1,0) [0|0] "Seconds" XXX + SG_ HvacEvap_Te_Rq_UB : 61|1@0+ (1,0) [0|0] "" XXX + SG_ HvacEvap_Te_Rq : 55|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ Remote_Start_QuietMode_UB : 33|1@0+ (1,0) [0|0] "" XXX + SG_ Remote_Start_QuietMode : 32|1@0+ (1,0) [0|0] "" XXX + +BO_ 264 Side_Detect_CmdM: 8 XXX + SG_ Cross_Traffic_Cmd : 5|2@0+ (1,0) [0|0] "" XXX + SG_ Side_Detect_Cmd : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 266 ParkAid_Audible_Warn_CmdM: 8 XXX + SG_ AutoPark_Cancel_Request : 15|2@0+ (1,0) [0|0] "" XXX + SG_ ParkAid_Audible_Warn_Cmd : 7|2@0+ (1,0) [0|0] "" XXX + SG_ ParkAid_Aud_Frt_Warn_Cmd : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 267 ParkAid_Audible_Warn_Stat: 8 XXX + SG_ RpaChime_D_Rq : 31|4@0+ (1,0) [0|0] "" XXX + SG_ FpaChime_D_Rq : 12|4@0+ (1,0) [0|0] "" XXX + SG_ SAPPStatusCoding : 23|8@0+ (1,0) [0|0] "" XXX + SG_ Volume_Cutback : 1|1@0+ (1,0) [0|0] "" XXX + SG_ ParkAid_Fault_Condition : 15|3@0+ (1,0) [0|0] "" XXX + SG_ ParkAid_Audible_Warn_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ ParkAid_Aud_Frt_Trgt_Warn : 3|2@0+ (1,0) [0|0] "" XXX + SG_ ParkAid_Aud_Frt_Warn_Stat : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 292 ClmtCtrlSeatSet_Cmd_v2: 8 XXX + SG_ ClmtCtrlSeat_SetCmd_Dvr : 7|8@0+ (1,0) [0|0] "" XXX + SG_ ClmtCtrlSeat_SetCmd_Psgr : 15|8@0+ (1,0) [0|0] "" XXX + +BO_ 293 ClmtCtrlSeatSetStat_v2_HS: 8 XXX + SG_ ClmtCtrlSeat_SetStat_Psgr : 15|8@0+ (1,0) [0|0] "" XXX + SG_ ClmtCtrlSeat_SetStat_Dvr : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 336 TransData_1_CG1: 8 XXX + SG_ TrnAinIdl_N_RqMn : 34|11@0+ (2.0,0) [0|0] "rpm" XXX + SG_ TrnAin_N_RqMxPrtct : 23|10@0+ (25.0,0) [0|0] "rpm" XXX + SG_ TrnAin_Tq_RqFstMx : 29|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_Tq_RqSlwMxPrs : 7|11@0+ (1,-500.0) [0|0] "Nm" XXX + +BO_ 337 EngineData_1_CG1: 8 XXX + SG_ TrnEngBrk_B_Allw : 24|1@0+ (1,0) [0|0] "" XXX + SG_ TrnAout_W_ActlUnfilt : 23|15@0+ (0.1,0) [0|0] "rad/s" XXX + SG_ TrnIpcDsplyGear_D_Actl : 7|4@0+ (1,0) [0|0] "" XXX + SG_ TrnIpcDsplyMde_D_Stat : 13|2@0+ (1,0) [0|0] "" XXX + SG_ TrnIpcDsplyMde_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ TrnIpcDsplyGear_D_Stat : 9|2@0+ (1,0) [0|0] "" XXX + SG_ TurboBoostPressure : 55|16@0+ (0.01,0) [0|0] "bar" XXX + +BO_ 338 TransData_2_CG1: 8 XXX + SG_ GearPos_D_Actl : 55|4@0+ (1,0) [0|0] "" XXX + SG_ TrnAout2_Tq_Actl : 39|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ TrnTotTq_Rt_Actl : 23|16@0+ (0.001,0) [0|0] "" XXX + SG_ TrnGbox_Rt_Pred : 7|16@0+ (0.001,0) [0|0] "" XXX + +BO_ 339 EngineData_2_CG1: 8 XXX + SG_ TrnAin_Tq_MxSpcPdlEngN : 55|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_Tq_MnSpcEngN : 31|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngPtoEngag_B_Actl : 60|1@0+ (1,0) [0|0] "" XXX + SG_ TrnAin_N_SpcEcho : 4|13@0+ (2.0,0) [0|0] "rpm" XXX + +BO_ 340 EngineData_3_CG1: 8 XXX + SG_ AirAmb_Te_ActlFilt : 33|10@0+ (0.25,-128.0) [0|0] "deg C" XXX + SG_ EngAout_N_RqMxPrtct : 12|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ TqmTerrMdeChng_D_Rdy : 39|3@0+ (1,0) [0|0] "" XXX + SG_ EngAoutIdl_N_RqVsc : 7|11@0+ (2.0,0) [0|0] "rpm" XXX + SG_ TqmTerrMde_D_Actl : 36|3@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTotVrt_Tq_RqArb : 55|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + +BO_ 341 EngineData_11_CG1: 8 XXX + SG_ DieslPrtc_D_RqDsply : 42|3@0+ (1,0) [0|0] "" XXX + SG_ EngPullUpPullDown_D_Rq : 20|4@0+ (1,0) [0|0] "" XXX + SG_ TrnAin_Tq_RqDrv : 15|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ DieslPrtcRgen_D_Actl : 4|2@0+ (1,0) [0|0] "" XXX + SG_ DieslPrtcRgen_D_Rq : 7|3@0+ (1,0) [0|0] "" XXX + SG_ EngAout_Aa_Actl : 39|10@0+ (0.05,-25.6) [0|0] "rpm/ms" XXX + SG_ EngIgnIndTq_Rt_MnEc : 31|8@0+ (0.005,0) [0|0] "" XXX + SG_ EngFuelCutFull_B_Allw : 45|1@0+ (1,0) [0|0] "" XXX + SG_ EngStrtStopDis_B_Rq : 0|1@0+ (1,0) [0|0] "" XXX + SG_ PrplTqSys_D_Stat : 2|2@0+ (1,0) [0|0] "" XXX + SG_ EngAoutTqDtrb_B_Actl : 16|1@0+ (1,0) [0|0] "" XXX + SG_ EngTurboMde_D_Actl : 44|2@0+ (1,0) [0|0] "" XXX + SG_ EngTeColdPrtct_D_Stats : 54|2@0+ (1,0) [0|0] "" XXX + SG_ EXHAUST_OVERTEMP_PROTECT : 63|1@0+ (1,0) [0|0] "" XXX + SG_ EngExhOvrTe_B_RqDsply : 55|1@0+ (1,0) [0|0] "" XXX + +BO_ 342 Engine_Data_6: 8 XXX + SG_ EngOvrhtMitgActv_D_Ind : 36|2@0+ (1,0) [0|0] "" XXX + SG_ Res_UreaLvlLo_B_Dsply : 34|1@0+ (1,0) [0|0] "" XXX + SG_ EngClntTe_D_Qf : 33|2@0+ (1,0) [0|0] "" XXX + SG_ EngAcsyArcPmp_Tq_Actl : 63|8@0+ (0.5,0) [0|0] "Nm" XXX + SG_ EngOilLvlDsply_D_Rq : 43|4@0+ (1,0) [0|0] "" XXX + SG_ EngCtlAlive_No_Cnt : 47|4@0+ (1,0) [0|0] "" XXX + SG_ EngCtl_No_Cs : 55|8@0+ (1,0) [0|0] "" XXX + SG_ EngOil_Te_Actl : 15|8@0+ (1,-60.0) [0|0] "degC" XXX + SG_ EngClnt_Te_Actl : 7|8@0+ (1,-60.0) [0|0] "degC" XXX + +BO_ 343 EngineData_13_CG1: 8 XXX + SG_ EngStrtFail_B_Actl : 40|1@0+ (1,0) [0|0] "" XXX + SG_ EngStrt_B_Complt : 24|1@0+ (1,0) [0|0] "" XXX + SG_ EngStrtSpin_B_Rdy : 58|1@0+ (1,0) [0|0] "" XXX + SG_ EngWarmUp_B_Complt : 41|1@0+ (1,0) [0|0] "" XXX + SG_ EngAoutTqCtl_B_Falt : 8|1@0+ (1,0) [0|0] "" XXX + SG_ EngAoutActl_No_Cs : 23|8@0+ (1,0) [0|0] "" XXX + SG_ EngAoutActl_No_Cnt : 45|4@0+ (1,0) [0|0] "" XXX + SG_ VehVLim_V_RqArb : 39|9@0+ (0.5,0) [0|0] "kph" XXX + +BO_ 344 EngineData_14: 8 XXX + SG_ ApedPosScal_Pc_Actl : 9|10@0+ (0.1,0) [0|0] "%" XXX + SG_ ApedPosPcActl_No_Cs : 39|8@0+ (1,0) [0|0] "" XXX + SG_ ApedPosPcActl_No_Cnt : 13|4@0+ (1,0) [0|0] "" XXX + +BO_ 345 Engine_Data_7_CG1: 8 XXX + SG_ EngDecelFuelCut_B_Allw : 25|1@0+ (1,0) [0|0] "" XXX + SG_ FuelFlw_Vl_Dsply : 55|10@0+ (25.0,0) [0|0] "Micro_Liter" XXX + SG_ FuelFillInlet_B_Dsply : 32|1@0+ (1,0) [0|0] "" XXX + SG_ EngSrvcRqd_B_Rq : 24|1@0+ (1,0) [0|0] "" XXX + SG_ OdoCount : 47|8@0+ (0.2,0) [0|0] "Meters" XXX + SG_ EngOilLife_Pc_Actl : 39|7@0+ (1,0) [0|0] "%" XXX + SG_ AirAmbTe_D_Qf : 28|2@0+ (1,0) [0|0] "" XXX + SG_ EngTqSlwDly_T_Est : 23|11@0+ (1,0) [0|0] "ms" XXX + SG_ TrnKickDown_B_RqDrv : 26|1@0+ (1,0) [0|0] "" XXX + SG_ AirAmb_Te_Actl : 1|10@0+ (0.25,-128.0) [0|0] "degC" XXX + SG_ AirAmb_P_Actl : 7|6@0+ (10.0,500.0) [0|0] "mbar" XXX + SG_ FuelFilterLamp_B_Dsply : 56|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondRec_B_Rq : 61|1@0+ (1,0) [0|0] "" XXX + SG_ AirCondEvdc_D_Stats : 60|3@0+ (1,0) [0|0] "" XXX + SG_ AirCondClutch_B_Stats : 57|1@0+ (1,0) [0|0] "" XXX + +BO_ 346 EngineData_4_CG1: 8 XXX + SG_ TrnAin_Tq_Rq : 12|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_Tq_RqWoMdfy : 55|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_Tq_ActlWoMdfy : 36|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_Tq_Actl : 7|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAinCtlN_B_Allw : 41|1@0+ (1,0) [0|0] "" XXX + SG_ TrnAinTq_D_Qf : 17|2@0+ (1,0) [0|0] "" XXX + +BO_ 348 EngineData_16_CG1: 8 XXX + SG_ EngOilLvlWarn_D_Rq1 : 50|3@0+ (1,0) [0|0] "" XXX + SG_ EngExhBrkOnLamp_B_Rq : 51|1@0+ (1,0) [0|0] "" XXX + SG_ EngExhBrkAutoLamp_B_Rq : 8|1@0+ (1,0) [0|0] "" XXX + SG_ EngAout_N_MxAllw : 36|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ EngAoutIdl_N_MnAllw : 31|11@0+ (1,0) [0|0] "rpm" XXX + SG_ EngAoutIdlRqEc_No_Cs : 23|8@0+ (1,0) [0|0] "" XXX + SG_ EngAoutIdlRqEc_No_Cnt : 12|4@0+ (1,0) [0|0] "" XXX + SG_ EngAoutIdl_N_RqEc : 7|11@0+ (2.0,0) [0|0] "rpm" XXX + SG_ EngExhBrkMde_D_Actl : 55|4@0+ (1,0) [0|0] "" XXX + +BO_ 349 EngineData_17_CG1: 8 XXX + SG_ EngResv_Tq_Actl : 52|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngAout_Tq_ActlSlw : 47|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngExhCat_Te_Est : 13|10@0+ (2.0,-60.0) [0|0] "degC" XXX + SG_ EngCylCutIndTq_Rt_Actl : 39|8@0+ (0.005,0) [0|0] "Nm" XXX + SG_ Eng_Aa_CalcEvntCyc : 7|10@0+ (0.05,-25.6) [0|0] "rpm/ms" XXX + SG_ Eng_Aa_CalcEvntCbust : 19|10@0+ (0.05,-25.6) [0|0] "rpm/ms" XXX + SG_ WaterInFuel : 25|1@0+ (1,0) [0|0] "" XXX + SG_ GlowIndication : 24|1@0+ (1,0) [0|0] "" XXX + +BO_ 350 EngineData_18_CG1: 8 XXX + SG_ EngAoutTqActl_D_Qf : 17|2@0+ (1,0) [0|0] "" XXX + SG_ EngAout_Tq_MnSpcNRtrd : 36|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngAout_Tq_Actl : 31|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngAoutLss_Tq_EstSpcN : 12|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngAout_Tq_MnSpcN : 7|11@0+ (1,-500.0) [0|0] "Nm" XXX + +BO_ 351 EngineData_19: 8 XXX + SG_ VehPreDelvr_V_LimMx : 15|16@0+ (0.01,0) [0|0] "kph" XXX + SG_ BattLo_U_MeasEngMdule : 7|8@0+ (0.1,0) [0|0] "V" XXX + SG_ EngStall_B_Actl : 47|1@0+ (1,0) [0|0] "" XXX + SG_ EngDashPotActv_B_Actl : 46|1@0+ (1,0) [0|0] "" XXX + SG_ EngAout_Tq_MnAllw : 42|11@0+ (1,-500.0) [0|0] "Nm" XXX + +BO_ 352 TransData_3_CG1: 8 XXX + SG_ TrnAinCtlN_N_RqMx : 7|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ TrnAin_Tq_RqSlwMxShif : 42|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAinCtlN_B_RqEnbl : 10|1@0+ (1,0) [0|0] "" XXX + SG_ TrnGboxIn_N_Actl : 23|13@0+ (2.0,0) [0|0] "rpm" XXX + +BO_ 353 Engine_Data_8: 8 XXX + SG_ TrnAinTqDtrb_B_Actl : 5|1@0+ (1,0) [0|0] "" XXX + SG_ TrnAin_Tq_MnSpcEngN : 34|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngAout_N_RqMnPrtct : 20|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ EngAout_N_MnAllw : 4|13@0+ (2.0,0) [0|0] "rpm" XXX + +BO_ 354 CGEA_Urea_Strategy_CG1: 8 XXX + SG_ UreaQltySys_D_RqDsply : 27|3@0+ (1,0) [0|0] "" XXX + SG_ UreaLvlTxt_D_RqDsply : 31|4@0+ (1,0) [0|0] "" XXX + SG_ VehUreaImmo_No_DsplyMx : 12|3@0+ (1,0) [0|0] "Counts" XXX + SG_ VehUreaWarn_V_DsplyMx : 23|7@0+ (1,0) [0|0] "km/h" XXX + SG_ VehUreaRnge_L_DsplyMx : 7|11@0+ (1,0) [0|0] "km" XXX + +BO_ 355 EngineData_10: 8 XXX + SG_ WhlRearDual_D_Stat : 57|2@0+ (1,0) [0|0] "" XXX + SG_ EngPtoMde_D_Actl : 60|3@0+ (1,0) [0|0] "" XXX + SG_ ManRgenVeh_V_MinAllw : 55|7@0+ (1,0) [0|0] "kilometer/hour" XXX + SG_ ManRgenTxt_D_RqDsply : 63|3@0+ (1,0) [0|0] "" XXX + SG_ ManRgenSoot_Pc_RqDsply : 39|7@0+ (1,0) [0|0] "%" XXX + SG_ ManRgenInhbt_T_RqDsply : 23|16@0+ (1,0) [0|0] "Minutes" XXX + SG_ ManRgenInhbt_Pc_Soot : 47|7@0+ (1,0) [0|0] "%" XXX + SG_ ManRgenInhbt_L_RqDsply : 7|16@0+ (1,0) [0|0] "kilometer" XXX + +BO_ 357 EngBrakeData: 8 XXX + SG_ CmbbDeny_B_ActlPrpl : 3|1@0+ (1,0) [0|0] "" XXX + SG_ BpedDrvAppl_No_Cs : 39|8@0+ (1,0) [0|0] "" XXX + SG_ BpedDrvAppl_No_Cnt : 27|4@0+ (1,0) [0|0] "" XXX + SG_ BpedDrvAppl_D_Actl : 31|2@0+ (1,0) [0|0] "" XXX + SG_ CmbbEngTqMn_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_DsplyCcSet : 23|8@0+ (1,0) [0|0] "" XXX + SG_ AccEngStat_D_Actl : 2|3@0+ (1,0) [0|0] "" XXX + SG_ CcMde_D_Actl : 13|3@0+ (1,0) [0|0] "" XXX + SG_ TrnAinTqDtrb_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + SG_ CcStat_D_Actl : 10|3@0+ (1,0) [0|0] "" XXX + SG_ CcOvrrdActv_B_Actl : 15|1@0+ (1,0) [0|0] "" XXX + SG_ PwPck_D_Stat : 59|4@0+ (1,0) [0|0] "" XXX + +BO_ 389 ACCDATA_CG1: 8 XXX + SG_ AccPrpl_A_Pred : 14|10@0+ (0.01,-5.0) [0|0] "m/s^2" XXX + SG_ AccBrkPrkEl_B_Rq : 41|1@0+ (1,0) [0|0] "" XXX + SG_ Cmbb_B_Enbl : 56|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbOvrrd_B_RqDrv : 57|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbDeny_B_Actl : 40|1@0+ (1,0) [0|0] "" XXX + SG_ AccVeh_V_Trg : 7|9@0+ (0.5,0) [0|0] "kph" XXX + SG_ CmbbEngTqMn_B_Rq : 58|1@0+ (1,0) [0|0] "" XXX + SG_ AccPrpl_A_Rq : 55|10@0+ (0.01,-5.0) [0|0] "m/s^2" XXX + SG_ AccDeny_B_Rq : 59|1@0+ (1,0) [0|0] "" XXX + SG_ AccCancl_B_Rq : 42|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkTot_A_Rq : 39|13@0+ (0.0039,-20.0) [0|0] "m/s^2" XXX + SG_ AccBrkPrchg_B_Rq : 60|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkDecel_B_Rq : 61|1@0+ (1,0) [0|0] "" XXX + +BO_ 392 HeadUpDisplayStat: 8 XXX + SG_ Hud_B_Falt : 5|1@0+ (1,0) [0|0] "" XXX + SG_ HudActv_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + SG_ Hud_B_Avail : 6|1@0+ (1,0) [0|0] "" XXX + +BO_ 393 ACCDATA_2_CG1: 8 XXX + SG_ ACC_AUTOBRAKE_CANCEL : 56|1@0+ (1,0) [0|0] "" XXX + SG_ ACC_RESUME_ACTIVE : 57|1@0+ (1,0) [0|0] "" XXX + SG_ FcwAudioWarn_B_Rq : 58|1@0+ (1,0) [0|0] "" XXX + SG_ CadsAudioMute_D_Rq : 61|2@0+ (1,0) [0|0] "" XXX + SG_ AccWarn_D_Dsply : 63|2@0+ (1,0) [0|0] "" XXX + SG_ HudDsplyIntns_No_Actl : 55|8@0+ (0.5,0) [0|0] "%" XXX + SG_ FcwVisblWarn_B_Rq : 40|1@0+ (1,0) [0|0] "" XXX + SG_ HudBlk3_B_Rq : 41|1@0+ (1,0) [0|0] "" XXX + SG_ HudBlk2_B_Rq : 43|1@0+ (1,0) [0|0] "" XXX + SG_ HudBlk1_B_Rq : 42|1@0+ (1,0) [0|0] "" XXX + SG_ HudFlashRate_D_Actl : 45|2@0+ (1,0) [0|0] "" XXX + SG_ CmbbBrkDecel_No_Cs : 39|8@0+ (1,0) [0|0] "" XXX + SG_ CmbbBrkDecel_A_Rq : 23|13@0+ (0.0039,-20.0) [0|0] "m/s^2" XXX + SG_ CmbbBrkPrchg_D_Rq : 47|2@0+ (1,0) [0|0] "" XXX + SG_ CmbbBrkDecel_B_Rq : 26|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbBaSens_D_Rq : 25|2@0+ (1,0) [0|0] "" XXX + SG_ AccPrpl_V_Rq : 7|16@0+ (0.01,0) [0|0] "kph" XXX + +BO_ 394 ACCDATA_3: 8 XXX + SG_ CadsMntr_No_Chk : 55|8@0+ (1,0) [0|0] "" XXX + SG_ FcwDeny_B_Dsply : 10|1@0+ (1,0) [0|0] "" XXX + SG_ FdaWarn_B_Rq : 21|1@0+ (1,0) [0|0] "" XXX + SG_ FcwMemStat_B_Actl : 30|1@0+ (1,0) [0|0] "" XXX + SG_ AccTGap_B_Dsply : 35|1@0+ (1,0) [0|0] "" XXX + SG_ AccMsgTxt_D_Rq : 39|4@0+ (1,0) [0|0] "" XXX + SG_ CadsAlignIncplt_B_Actl : 29|1@0+ (1,0) [0|0] "" XXX + SG_ AccLowVMde_B_Dsply : 16|1@0+ (1,0) [0|0] "" XXX + SG_ AccFllwMde_B_Dsply : 17|1@0+ (1,0) [0|0] "" XXX + SG_ CadsRadrBlck_B_Actl : 22|1@0+ (1,0) [0|0] "" XXX + SG_ FdaStat_D_Dsply : 3|3@0+ (1,0) [0|0] "" XXX + SG_ FdaDeny_B_Dsply : 4|1@0+ (1,0) [0|0] "" XXX + SG_ AccTrgDist_D_Dsply : 28|4@0+ (1,0) [0|0] "" XXX + SG_ CadsChime_B_Rq : 24|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbPostEvnt_B_Dsply : 15|1@0+ (1,0) [0|0] "" XXX + SG_ FcwCmbbSrvcRqd_B_Rq : 12|1@0+ (1,0) [0|0] "" XXX + SG_ AccStopMde_B_Dsply : 0|1@0+ (1,0) [0|0] "" XXX + SG_ CadsCamraBlck_B_Actl : 23|1@0+ (1,0) [0|0] "" XXX + SG_ FcwMemSens_D_Actl : 20|2@0+ (1,0) [0|0] "" XXX + SG_ FcwMemDfaltOn_B_Actl : 18|1@0+ (1,0) [0|0] "" XXX + SG_ AccSrvcRqd_B_Rq : 14|1@0+ (1,0) [0|0] "" XXX + SG_ FcwMsgTxt_D_Rq : 7|3@0+ (1,0) [0|0] "" XXX + SG_ FcwMemAudioOn_B_Actl : 9|1@0+ (1,0) [0|0] "" XXX + SG_ AccTGap_D_Dsply : 34|3@0+ (1,0) [0|0] "" XXX + SG_ AccMemEnbl_B_RqDrv : 42|1@0+ (1,0) [0|0] "" XXX + SG_ FdaMem_B_Stat : 41|1@0+ (1,0) [0|0] "" XXX + +BO_ 512 TorqueDataEngFlags: 8 XXX + SG_ BrkOnOffSwtch_D_Actl : 54|2@0+ (1,0) [0|0] "" XXX + SG_ PrplTqMnSat_B_Actl : 55|1@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTot_Tq_Rq : 39|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ PrplWhlTot_Tq_LimMn : 23|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ PrplWhlTot_Tq_Actl : 7|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ ACCompressorDisp : 63|7@0+ (1,0) [0|0] "%" XXX + +BO_ 513 EngVehicleSpThrottle_CG1: 8 XXX + SG_ ApedPos_PcRate_ActlArb : 63|8@0+ (0.04,-5.0) [0|0] "%/ms" XXX + SG_ Veh_V_RqCcSet : 45|9@0+ (0.5,0) [0|0] "kph" XXX + SG_ VehVActlEng_D_Qf : 9|2@0+ (1,0) [0|0] "" XXX + SG_ reserve : 10|1@0+ (1,0) [0|0] "" XXX + SG_ EngAout_N_Actl : 7|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ Veh_V_ActlEng : 23|16@0+ (0.01,0) [0|0] "kph" XXX + SG_ ApedPos_Pc_ActlArb : 39|10@0+ (0.1,0) [0|0] "%" XXX + SG_ ApedPosPcActl_D_Qf : 52|2@0+ (1,0) [0|0] "" XXX + SG_ Autostart_B_Stat : 50|1@0+ (1,0) [0|0] "" XXX + +BO_ 529 DesiredTorqBrk_CG1: 8 XXX + SG_ CmbbBrkDis_B_Actl : 56|1@0+ (1,0) [0|0] "" XXX + SG_ CMbbDeny_B_ActlBrk : 60|1@0+ (1,0) [0|0] "" XXX + SG_ RgenTqLimActv_B_Actl : 32|1@0+ (1,0) [0|0] "" XXX + SG_ CcDis_B_Cmd : 53|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrk_Pc_Rq : 39|7@0+ (1,0) [0|0] "%" XXX + SG_ RearDiffLck_Tq_RqMx : 23|12@0+ (1,0) [0|0] "Nm" XXX + SG_ VehLongOvrGnd_A_Est : 47|10@0+ (0.035,-17.9) [0|0] "m/s^2" XXX + SG_ StabCtlBrkActv_B_Actl : 27|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbBrkPrchg_B_Actl : 59|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbBrkDecel_B_Actl : 58|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbBaSensInc_B_Actl : 57|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkWarm_B_Actl : 63|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkTotTqMn_B_Actl : 62|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkPrchgActv_B_Actl : 61|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkDis_B_Actl : 50|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkDeny_B_Actl : 49|1@0+ (1,0) [0|0] "" XXX + SG_ AccBrkActv_B_Actl : 48|1@0+ (1,0) [0|0] "" XXX + SG_ PrplDrgCtlActv_B_Actl : 52|1@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTot_Tq_RqMx : 7|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ AbsActv_B_Actl : 51|1@0+ (1,0) [0|0] "" XXX + +BO_ 533 WheelSpeed_CG1: 8 XXX + SG_ WhlRr_W_Meas : 55|15@0+ (0.01,0) [0|0] "rad/s" XXX + SG_ WhlRl_W_Meas : 39|15@0+ (0.01,0) [0|0] "rad/s" XXX + SG_ WhlFr_W_Meas : 23|15@0+ (0.01,0) [0|0] "rad/s" XXX + SG_ WhlFl_W_Meas : 7|15@0+ (0.01,0) [0|0] "rad/s" XXX + +BO_ 534 WheelData: 8 XXX + SG_ WhlRotatRr_No_Cnt : 23|8@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRr_D_Actl : 33|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRl_D_Actl : 39|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFr_D_Actl : 37|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFl_D_Actl : 35|2@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatRl_No_Cnt : 31|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFr_No_Cnt : 7|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFl_No_Cnt : 15|8@0+ (1,0) [0|0] "" XXX + SG_ WHEEL_ROLLING_TIMESTAMP : 47|8@0+ (1,0) [0|0] "" XXX + +BO_ 557 InfoCAN_22D: 8 XXX + SG_ Multimedia_System : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 560 TransGearData: 8 XXX + SG_ TrnIpcDsplyRng_D_Actl : 14|3@0+ (1,0) [0|0] "" XXX + SG_ TrnGbox_Rt_Actl : 47|16@0+ (0.001,0) [0|0] "" XXX + SG_ TrnShifMde_D_RqDrv : 3|3@0+ (1,0) [0|0] "" XXX + SG_ TrnSrvcRqd_B_Rq : 63|1@0+ (1,0) [0|0] "" XXX + SG_ GearPos_D_Trg : 7|4@0+ (1,0) [0|0] "" XXX + SG_ TrnCnvtClu_D_Actl : 11|2@0+ (1,0) [0|0] "" XXX + SG_ TrnShifActv_B_Actl : 0|1@0+ (1,0) [0|0] "" XXX + SG_ RtmTerrMdeChng_D_Rdy : 58|3@0+ (1,0) [0|0] "" XXX + SG_ RtmTerrMde_D_Actl : 61|3@0+ (1,0) [0|0] "" XXX + SG_ GearRvrseActv_B_Actl : 62|1@0+ (1,0) [0|0] "" XXX + SG_ GearLvrPos_D_Actl : 23|4@0+ (1,0) [0|0] "" XXX + SG_ GboxOil_Te_Actl : 31|8@0+ (1,-60.0) [0|0] "degC" XXX + +BO_ 561 TransGearData_2: 8 XXX + SG_ MtrGen1Aout_Tq_Rq : 53|14@0+ (0.1,-800.0) [0|0] "Nm" XXX + SG_ MtrGen1AoutTqRq_No_Cs : 7|8@0+ (1,0) [0|0] "" XXX + SG_ MtrGen1AoutTqRq_No_Cnt : 15|4@0+ (1,0) [0|0] "" XXX + SG_ CoolFanTrn_D_Rq : 31|5@0+ (1,0) [0|0] "" XXX + SG_ TrnMsgTxt_D_Rq : 39|4@0+ (1,0) [0|0] "" XXX + SG_ TrnMil_D_Rq : 26|2@0+ (1,0) [0|0] "" XXX + SG_ EngExhBrkTq_Pc_Rq : 23|7@0+ (1,0) [0|0] "%" XXX + +BO_ 562 TransGearData_3_CG1: 8 XXX + SG_ TrnPto_D_Rdy : 12|2@0+ (1,0) [0|0] "" XXX + SG_ TipInMgrInhbt_B_RqTrn : 41|1@0+ (1,0) [0|0] "" XXX + SG_ TrnAinIdl_Tq_Actl : 39|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAinLss_Tq_Est : 7|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_Tq_RqSlwMn : 23|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ GearEngag_D_Actl : 10|3@0+ (1,0) [0|0] "" XXX + SG_ TrnAinTqDtrb_B_Rq : 40|1@0+ (1,0) [0|0] "" XXX + SG_ TrnTotLss_Tq_Actl : 55|8@0+ (0.5,0) [0|0] "Nm" XXX + +BO_ 563 TransGearData_4_CG1: 8 XXX + SG_ TrnAinCtlN_N_RqMn : 20|13@0+ (2.0,0) [0|0] "rpm" XXX + SG_ TrnAinTqMn_No_Cs : 63|8@0+ (1,0) [0|0] "" XXX + SG_ TrnAinTqMn_No_Cnt : 11|4@0+ (1,0) [0|0] "" XXX + SG_ TrnAinRq_Pc_SpcPdl : 7|10@0+ (0.1,0) [0|0] "%" XXX + SG_ TrnAin_Tq_RqFstMn : 42|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ TrnAin_N_SpcEng : 39|13@0+ (2.0,0) [0|0] "rpm" XXX + +BO_ 570 Suspension_Stat: 8 XXX + SG_ CcdMsgTxt_D_RqDsply : 7|4@0+ (1,0) [0|0] "" XXX + SG_ SuspRear_L_Prev : 48|9@0+ (0.782779,-200.0) [0|0] "millimeter" XXX + SG_ SuspRear_L_Actl : 32|9@0+ (0.782779,-200.0) [0|0] "millimeter" XXX + SG_ SuspFrnt_L_Prev : 16|9@0+ (0.782779,-200.0) [0|0] "millimeter" XXX + SG_ SuspFrnt_L_Actl : 0|9@0+ (0.782779,-200.0) [0|0] "millimeter" XXX + +BO_ 571 ColumnLockData: 8 XXX + SG_ SteWhlLckMsgTxt_D_Rq : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 576 Body_Information_4_CG1: 8 XXX + SG_ HvacRec_Pc_Est_UB : 51|1@0+ (1,0) [0|0] "" XXX + SG_ HvacRec_Pc_Est : 38|7@0+ (1,0) [0|0] "%" XXX + SG_ HvacEngIdleInc_B_Rq_UB : 49|1@0+ (1,0) [0|0] "" XXX + SG_ HvacEngIdleInc_B_Rq : 53|1@0+ (1,0) [0|0] "" XXX + SG_ HvacAir_Flw_Est_UB : 52|1@0+ (1,0) [0|0] "" XXX + SG_ HvacAir_Flw_Est : 31|9@0+ (0.5,0) [0|0] "liter/second" XXX + SG_ AmbTempImpr_UB : 50|1@0+ (1,0) [0|0] "" XXX + SG_ AmbTempImpr : 47|10@0+ (0.25,-128.0) [0|0] "degreesC" XXX + SG_ DriverCrankingReq : 16|1@0+ (1,0) [0|0] "" XXX + SG_ Fcw_B_DenyMntr : 23|1@0+ (1,0) [0|0] "" XXX + SG_ EngOff_T_Actl : 7|16@0+ (1,0) [0|0] "seconds" XXX + SG_ CmbbMntr_B_Err : 22|1@0+ (1,0) [0|0] "" XXX + SG_ CmbbDeny_B_RqMntr : 21|1@0+ (1,0) [0|0] "" XXX + SG_ AccMntr_B_Err : 20|1@0+ (1,0) [0|0] "" XXX + SG_ AccDeny_B_RqMntr : 19|1@0+ (1,0) [0|0] "" XXX + +BO_ 592 EONV_Status: 8 XXX + SG_ EONV_FAULT : 59|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_KAL_IC_RQST : 53|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_T_STATUS : 61|2@0+ (1,0) [0|0] "" XXX + SG_ EONV_VREF_FLT : 62|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_VBATT_FLT : 63|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_CANISTER_VENT_FLT : 54|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_CVS_CLOSED : 55|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_BATT_VOLT : 23|16@0+ (0.0009765625,0) [0|0] "volts" XXX + SG_ EONV_TANK_FLT : 48|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_TANK_PRESS : 7|16@0+ (0.001953125,-64.0) [0|0] "inches H2O" XXX + +BO_ 597 EONV_Control: 8 XXX + SG_ EONV_POS_DET_THRESHOLD : 23|16@0+ (0.001953125,-64.0) [0|0] "inches H2O" XXX + SG_ EONV_STAY_ALIVE : 15|1@0+ (1,0) [0|0] "" XXX + SG_ EONV_CVS_MODE : 7|3@0+ (1,0) [0|0] "" XXX + SG_ EONV_NEG_DET_THRESHOLD : 39|16@0+ (0.001953125,-64.0) [0|0] "inches H2O" XXX + SG_ EONV_MIL_ON : 14|1@0+ (1,0) [0|0] "" XXX + SG_ EonvMsgTxOff_B_Rq : 4|1@0+ (1,0) [0|0] "" XXX + +BO_ 608 Information4x4_CG1: 8 XXX + SG_ AwdRngeShifActv_B_Actl : 0|1@0+ (1,0) [0|0] "" XXX + SG_ TrnAout_Tq_RqMx : 47|13@0+ (1,-1250.0) [0|0] "Nm" XXX + SG_ AwdRngeFalt_D_Stat : 4|2@0+ (1,0) [0|0] "" XXX + SG_ AwdLck_Tq_Actl : 15|12@0+ (1,0) [0|0] "Nm" XXX + SG_ AwdRnge_D_Actl : 7|3@0+ (1,0) [0|0] "" XXX + SG_ AwdTerrMdeChng_D_Rdy : 50|3@0+ (1,0) [0|0] "" XXX + SG_ AwdTerrMde_D_Actl : 58|3@0+ (1,0) [0|0] "" XXX + SG_ AwdOffRoadMode_D_Stats : 25|2@0+ (1,0) [0|0] "" XXX + SG_ AwdStat_D_RqDsply : 63|5@0+ (1,0) [0|0] "" XXX + SG_ AwdLoLamp_D_RqDsply : 35|2@0+ (1,0) [0|0] "" XXX + SG_ AwdHiLamp_D_RqDsply : 19|2@0+ (1,0) [0|0] "" XXX + SG_ AwdAutoLamp_D_RqDsply : 17|2@0+ (1,0) [0|0] "" XXX + SG_ AwdLckLamp_D_RqDsply : 27|2@0+ (1,0) [0|0] "" XXX + SG_ AwdLck_D_Stat : 31|4@0+ (1,0) [0|0] "" XXX + SG_ Awd2wdLamp_D_RqDsply : 2|2@0+ (1,0) [0|0] "" XXX + +BO_ 609 AWD_4x4_Data: 8 XXX + SG_ AwdLck_Tq_Rq : 27|12@0+ (1,0) [0|0] "Nm" XXX + SG_ AwdSrvcRqd_B_Rq : 44|1@0+ (1,0) [0|0] "" XXX + +BO_ 613 PassengerSeatOCSInfo: 8 XXX + SG_ VehicleMYCalibrationId : 39|8@0+ (1,0) [0|0] "" XXX + SG_ VehicleCalibrationId : 31|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSensrDataUpperLim : 15|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSensrDataLowerLim : 23|8@0+ (1,0) [0|0] "" XXX + SG_ OCSLevel2Error : 0|1@0+ (1,0) [0|0] "" XXX + SG_ ObjectEntrapped : 2|1@0+ (1,0) [0|0] "" XXX + SG_ OCSLevel1Error : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 736 FCIM_Button_Press_HS: 8 XXX + SG_ FCIM_Target_ID : 13|4@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Button_Type : 7|8@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Button_State : 15|2@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Target_ID_UB : 23|1@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Button_Type_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ FCIM_Button_State_UB : 8|1@0+ (1,0) [0|0] "" XXX + +BO_ 806 Compressor_Req_HS: 8 XXX + SG_ HvacEvap_Te_Rq : 33|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ HvacEvap_Te_Actl : 17|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ HvacAirCond_B_Rq : 7|1@0+ (1,0) [0|0] "" XXX + SG_ HvacEvap_Te_Offst : 1|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + +BO_ 832 RCMStatusMessage: 8 XXX + SG_ eCallNotification : 2|2@0+ (1,0) [0|0] "" XXX + SG_ CrashNotification : 5|1@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBucklePsngr : 57|2@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBuckleMid : 59|2@0+ (1,0) [0|0] "" XXX + SG_ ThirdRowBuckleDriver : 61|2@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBucklePsngr : 63|2@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBuckleMid : 49|2@0+ (1,0) [0|0] "" XXX + SG_ SecondRowBuckleDriver : 51|2@0+ (1,0) [0|0] "" XXX + SG_ FirstRowBuckleDriver : 55|2@0+ (1,0) [0|0] "" XXX + SG_ RstrnTotalEvntCnt : 43|4@0+ (1,0) [0|0] "" XXX + SG_ RstrnCurrentEvntCnt : 39|8@0+ (1,0) [0|0] "" XXX + SG_ RILReq : 15|2@0+ (1,0) [0|0] "" XXX + SG_ FuelCutoffReq : 13|4@0+ (1,0) [0|0] "" XXX + SG_ SeatbeltIndicatorReq : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SeatbeltChimeReq : 8|1@0+ (1,0) [0|0] "" XXX + SG_ BeltMinderProgConfReq : 21|2@0+ (1,0) [0|0] "" XXX + SG_ BeltMinderLevelReq : 19|4@0+ (1,0) [0|0] "" XXX + SG_ FirstRowBucklePsngr : 53|2@0+ (1,0) [0|0] "" XXX + SG_ InfoLampReq : 29|1@0+ (1,0) [0|0] "" XXX + SG_ GenRedLampReq : 28|1@0+ (1,0) [0|0] "" XXX + SG_ RstrnTextMsgReq : 27|2@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNumRcvd : 3|1@0+ (1,0) [0|0] "" XXX + SG_ RstrnStatDeployEnbld : 6|1@0+ (1,0) [0|0] "" XXX + SG_ RstrnImpactEvntStatus : 46|3@0+ (1,0) [0|0] "" XXX + SG_ PassRstrnInd_Req : 25|2@0+ (1,0) [0|0] "" XXX + SG_ RstrnStatTrigEvnt : 7|1@0+ (1,0) [0|0] "" XXX + SG_ PsngrFrntDetct_D_Actl : 31|2@0+ (1,0) [0|0] "" XXX + SG_ Beltminder_Warn_Stats : 22|1@0+ (1,0) [0|0] "" XXX + SG_ EDRTriggerEvntSync : 47|1@0+ (1,0) [0|0] "" XXX + +BO_ 842 MassageSeat_Data1_HS: 8 XXX + SG_ SeatLmbrUpDrv_Pc_Actl : 38|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrMidDrv_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrLoDrv_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlUpDrv_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlLoDrv_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 843 MassageSeat_Data2_HS: 8 XXX + SG_ SeatLmbrUpPsgr_Pc_Actl : 38|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrMidPsgr_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatLmbrLoPsgr_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlUpPsgr_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatBlLoPsgr_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 844 MassageSeat_Stat1_HS: 8 XXX + SG_ StmsLmbrDrv_D_Stat : 17|2@0+ (1,0) [0|0] "" XXX + SG_ StmsCshnDrv_D_Stat : 19|2@0+ (1,0) [0|0] "" XXX + SG_ SeatSwtchDrv_B_Stat : 31|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDrv_D_Stat : 23|3@0+ (1,0) [0|0] "" XXX + SG_ SeatAirAmb_P_Actl : 7|16@0+ (0.01,0) [0|0] "KiloPascal" XXX + SG_ SeatPDrv_B_Stat : 20|1@0+ (1,0) [0|0] "" XXX + +BO_ 845 MassageSeat_Stat2_HS: 8 XXX + SG_ StmsLmbrPsgr_D_Stat : 15|2@0+ (1,0) [0|0] "" XXX + SG_ StmsCshnPsgr_D_Stat : 13|2@0+ (1,0) [0|0] "" XXX + SG_ SeatSwtchPsgr_B_Stat : 11|1@0+ (1,0) [0|0] "" XXX + SG_ SeatPPsgr_B_Stat : 7|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnPsgr_D_Stat : 6|3@0+ (1,0) [0|0] "" XXX + SG_ PsgrMemFeedback_Rsp : 3|4@0+ (1,0) [0|0] "" XXX + +BO_ 846 MassageSeat_Req: 8 XXX + SG_ SeatFnPsgr_D_Rq : 15|3@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDrv_D_Rq : 12|3@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDfaltPsgr_B_Rq : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnDfaltDrv_B_Rq : 8|1@0+ (1,0) [0|0] "" XXX + SG_ SeatFnChngPsgr_D_Rq : 7|2@0+ (1,0) [0|0] "" XXX + SG_ SeatFnChngDrv_D_Rq : 5|2@0+ (1,0) [0|0] "" XXX + SG_ PsgrMemory_Rq : 3|4@0+ (1,0) [0|0] "" XXX + +BO_ 848 RestraintsData: 8 XXX + SG_ PassRstrnInd_Stat_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ SeatBltWrnChmeStat : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Seatbelt_IndctrStat : 4|3@0+ (1,0) [0|0] "" XXX + SG_ RILStat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ PassRstrnInd_Stat : 15|4@0+ (1,0) [0|0] "" XXX + +BO_ 849 MassageSeat_Data3_HS: 8 XXX + SG_ SeatCshnDrvRR_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnDrvRL_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnDrvFR_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnDrvFL_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 850 MassageSeat_Data4_HS: 8 XXX + SG_ SeatCshnPsgrRR_Pc_Actl : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnPsgrRL_Pc_Actl : 22|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnPsgrFR_Pc_Actl : 14|7@0+ (1,0) [0|0] "%" XXX + SG_ SeatCshnPsgrFL_Pc_Actl : 6|7@0+ (1,0) [0|0] "%" XXX + +BO_ 853 EFP_CC_Status: 8 XXX + SG_ Save_My_Temp : 59|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Left_Temp_Setpt : 31|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RrDefrost_HtdMirrorReq : 60|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Control_Status : 16|1@0+ (1,0) [0|0] "" XXX + SG_ MultipleButtonPressReq : 63|3@0+ (1,0) [0|0] "" XXX + SG_ Rear_System_Mode_Req : 19|3@0+ (1,0) [0|0] "" XXX + SG_ Rear_Left_Temp_Setpt : 47|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ Recirc_Request : 23|2@0+ (1,0) [0|0] "" XXX + SG_ Front_Rt_Temp_Setpt : 39|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ AC_Request : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Windshield_ModeRequest : 15|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Panel_Mode_Request : 7|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Overriding_ModeReq : 10|3@0+ (1,0) [0|0] "" XXX + SG_ Forced_Recirc_Req : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_Request : 3|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Rear_Right_Temp_Setpt : 55|8@0+ (1,0) [0|0] "Mixed" XXX + +BO_ 854 EFP_CC_Seat_Req_Stat: 8 XXX + SG_ Front_Rear_Blower_Req : 31|6@0+ (1,0) [0|0] "Detents" XXX + SG_ Pass_Rr_Cond_Seat_Req : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Rr_Cond_Seat_Lvl : 8|3@0+ (1,0) [0|0] "" XXX + SG_ Pass_Fr_Cond_Seat_Req : 13|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Fr_Cond_Seat_Lvl : 11|3@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Rr_Cond_Seat_Req : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Rr_Cond_Seat_Lvl : 2|3@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Fr_Cond_Seat_Req : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Fr_Cond_Seat_Lvl : 5|3@0+ (1,0) [0|0] "" XXX + +BO_ 855 RCCM_CC_Status_HS: 8 XXX + SG_ RrBlwrCondStLdShedStat : 25|2@0+ (1,0) [0|0] "" XXX + SG_ FrBlwrCondStLdShedStat : 20|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_Rr_Rt_TempSetpt : 63|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Rr_Left_TempSetpt : 55|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Fr_Rt_TempSetpt : 47|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RCCM_Fr_Rr_Blower_Req : 31|6@0+ (1,0) [0|0] "Detents" XXX + SG_ Panel_Mode_State : 7|4@0+ (8.33,0) [0|0] "%" XXX + SG_ RrDefHtdMirrLdShedStat : 18|2@0+ (1,0) [0|0] "" XXX + SG_ Windshield_Mode_State : 15|4@0+ (8.33,0) [0|0] "%" XXX + SG_ Recirc_Door_State : 11|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_System_Mode_State : 23|3@0+ (1,0) [0|0] "" XXX + SG_ Default_Defrost_State : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Auto_AC_Indicator_Temp : 16|1@0+ (1,0) [0|0] "" XXX + SG_ Floor_Mode_State : 3|4@0+ (8.33,0) [0|0] "%" XXX + SG_ RCCM_Fr_Left_TempSetpt : 39|8@0+ (1,0) [0|0] "Mixed" XXX + SG_ RrDefrost_HtdMirrState : 8|1@0+ (1,0) [0|0] "" XXX + +BO_ 856 RCCM_CC_Seat_Status_HS: 8 XXX + SG_ Active_My_Temp : 2|1@0+ (1,0) [0|0] "" XXX + SG_ CC_HtdStrWhl_Req : 24|1@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PR_Cond_Seat_Lvl : 31|3@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PR_Cond_Seat_Req : 28|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PF_Cond_Seat_Req : 20|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_PF_Cond_Seat_Lvl : 23|3@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DR_Cond_Seat_Req : 12|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DR_Cond_Seat_Lvl : 15|3@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DF_Cond_Seat_Req : 4|2@0+ (1,0) [0|0] "" XXX + SG_ RCCM_DF_Cond_Seat_Lvl : 7|3@0+ (1,0) [0|0] "" XXX + SG_ PassRrCondStLdShedStat : 26|2@0+ (1,0) [0|0] "" XXX + SG_ PassFrCondStLdShedStat : 18|2@0+ (1,0) [0|0] "" XXX + SG_ DrvRrCondStLdShedStat : 10|2@0+ (1,0) [0|0] "" XXX + SG_ DrvFrCondStLdShedStat : 1|2@0+ (1,0) [0|0] "" XXX + +BO_ 857 RCCM_CC_MBP_Press_Stat_HS: 8 XXX + SG_ MultBtnPushDsplyPass10 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyPass1 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ Report_Active : 33|2@0+ (1,0) [0|0] "" XXX + SG_ Pass_Temp_Units : 35|1@0+ (1,0) [0|0] "" XXX + SG_ Front_Fan_Bars_Disply : 39|3@0+ (1,0) [0|0] "" XXX + SG_ Drvr_Temp_Units : 36|1@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyDrvr10 : 7|8@0+ (1,0) [0|0] "" XXX + SG_ MultBtnPushDsplyDrvr1 : 15|8@0+ (1,0) [0|0] "" XXX + +BO_ 859 MFD_CC_Status_HS: 8 XXX + SG_ Rear_Mode_Bttn_Status : 38|1@0+ (1,0) [0|0] "" XXX + SG_ ConditionSt_ButtonStat : 20|5@0+ (1,0) [0|0] "" XXX + SG_ Driver_Set_Temp : 31|8@0+ (0.5,0) [0|0] "Degrees" XXX + SG_ Frt_System_Button_Stat : 7|5@0+ (1,0) [0|0] "" XXX + SG_ Rear_Blower_Bar_Status : 2|3@0+ (1,0) [0|0] "# of Bars" XXX + SG_ Rear_Fan_Button_Status : 13|2@0+ (1,0) [0|0] "" XXX + SG_ Rear_Man_Temp_Bar_Stat : 11|4@0+ (1,0) [0|0] "" XXX + SG_ Rear_Temp_Button_Status : 23|2@0+ (1,0) [0|0] "" XXX + SG_ Voice_Blower_Limit : 21|1@0+ (1,0) [0|0] "" XXX + +BO_ 860 EFP_CC_Info_Status: 8 XXX + SG_ Rear_Panel_Btn_State : 41|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Floor_Btn_State : 40|1@0+ (1,0) [0|0] "" XXX + SG_ HtdStrWhl_SftBtt_Stt : 39|2@0+ (1,0) [0|0] "" XXX + SG_ AC_Sft_Button_State : 23|2@0+ (1,0) [0|0] "" XXX + SG_ DrvRrCondSeatSftBttnSt : 47|3@0+ (1,0) [0|0] "" XXX + SG_ DrvFrCondSeatSftBtnStt : 37|3@0+ (1,0) [0|0] "" XXX + SG_ CC_RecircSBtn_St : 27|2@0+ (1,0) [0|0] "" XXX + SG_ CC_RrDefrSBtn_St : 24|1@0+ (1,0) [0|0] "" XXX + SG_ PasRrCondSeatSftBttnSt : 44|3@0+ (1,0) [0|0] "" XXX + SG_ PasFrCondSeatSftBtnStt : 34|3@0+ (1,0) [0|0] "" XXX + SG_ MyTemp_Soft_Bttn_State : 25|1@0+ (1,0) [0|0] "" XXX + SG_ CC_MaxACSBtn_St : 28|1@0+ (1,0) [0|0] "" XXX + SG_ RearPowerButtonState : 16|1@0+ (1,0) [0|0] "" XXX + SG_ RearCoolBarsDisplayed : 11|3@0+ (1,0) [0|0] "Bars_On" XXX + SG_ Rear_Sft_Control_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ CC_RrNeutralBarDsp_St : 8|1@0+ (1,0) [0|0] "" XXX + SG_ CC_RrHeatBarsDsp_St : 31|3@0+ (1,0) [0|0] "Bars_On" XXX + SG_ Rear_Fan_Bars_Displayed : 19|3@0+ (1,0) [0|0] "" XXX + SG_ CC_RrCtrlBtn_St : 20|1@0+ (1,0) [0|0] "" XXX + SG_ Rear_Auto_Button_State : 21|1@0+ (1,0) [0|0] "" XXX + SG_ CC_FrPowerSBtn_St : 14|1@0+ (1,0) [0|0] "" XXX + SG_ CC_FrDefrostSBtn_St : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_Soft_Btn_Stt : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_MODE_State : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Front_AUTO_FAN_State : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Dual_Button_State : 12|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarPnlSBtn_St : 5|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarPnFlrSBtn_St : 4|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarFlrWsSBtn_St : 2|1@0+ (1,0) [0|0] "" XXX + SG_ CC_BarDrvFlrSBtn_St : 3|1@0+ (1,0) [0|0] "" XXX + +BO_ 890 Active_Noise: 8 XXX + SG_ ANC_Chime_Supported : 4|2@0+ (1,0) [0|0] "" XXX + SG_ ActvNseAudio_D_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ ActvNse_B_Actv : 5|1@0+ (1,0) [0|0] "" XXX + +BO_ 891 Active_Noise_Data: 8 XXX + SG_ CabnSndAmb_Db_Actl : 7|8@0+ (1,30.0) [0|0] "decibel" XXX + +BO_ 906 Body_Information_1: 8 XXX + SG_ CcdMde_D_Rq_UB : 0|1@0+ (1,0) [0|0] "" XXX + SG_ CcdMde_D_Rq : 7|2@0+ (1,0) [0|0] "" XXX + SG_ CarMode : 5|4@0+ (1,0) [0|0] "" XXX + SG_ SecondaryHeater_Rqst : 55|1@0+ (1,0) [0|0] "" XXX + SG_ Passenger_Sunload_Raw : 47|8@0+ (5.0,0) [0|0] "W/m^2" XXX + SG_ Driver_Sunload_Raw : 39|8@0+ (5.0,0) [0|0] "W/m^2" XXX + SG_ HvacEvap_Te_Actl_UB : 1|1@0+ (1,0) [0|0] "" XXX + SG_ HvacEvap_Te_Actl : 17|10@0+ (0.125,-50.0) [0|0] "Degrees C" XXX + SG_ SecondaryHeater_Rqst_UB : 18|1@0+ (1,0) [0|0] "" XXX + SG_ Outside_Air_Temp_Stat_UB : 23|1@0+ (1,0) [0|0] "" XXX + SG_ Outside_Air_Temp_Stat : 15|8@0+ (0.5,-40.0) [0|0] "Degrees C" XXX + SG_ Veh_Lock_Status : 54|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_Lock_Requestor : 52|5@0+ (1,0) [0|0] "" XXX + SG_ Veh_Lock_EvNum : 63|8@0+ (1,0) [0|0] "Counts" XXX + SG_ immoIndicatorCmd : 22|4@0+ (1,0) [0|0] "" XXX + +BO_ 909 Body_Information_6: 8 XXX + SG_ PEBackupSlot_Stats_UB : 43|1@0+ (1,0) [0|0] "" XXX + SG_ PEBackupSlot_Stats : 25|2@0+ (1,0) [0|0] "" XXX + SG_ KeyMykeyTot_No_Cnt : 47|4@0+ (1,0) [0|0] "Counts" XXX + SG_ SideDetect_R_SysOpState_UB : 26|1@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_R_SysOpState : 28|2@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_R_SnsrState_UB : 29|1@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_R_SnsrState : 31|2@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_L_SysOpState_UB : 16|1@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_L_SysOpState : 18|2@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_L_SnsrState_UB : 19|1@0+ (1,0) [0|0] "" XXX + SG_ SideDetect_L_SnsrState : 21|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_SnState_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_SnState : 23|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_Op_State_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_Op_State : 11|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_Alert_UB : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_R_Alert : 14|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_SnState_UB : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_SnState : 1|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_Op_State_UB : 2|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_Op_State : 4|2@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_Alert_UB : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Cross_Traffic_L_Alert : 7|2@0+ (1,0) [0|0] "" XXX + SG_ IgnKeyType_D_Actl : 39|4@0+ (1,0) [0|0] "" XXX + SG_ KeyAdmnTot_No_Cnt : 35|4@0+ (1,0) [0|0] "Counts" XXX + +BO_ 936 ParkAid_Data: 8 XXX + SG_ SAPPErrorCoding : 23|8@0+ (1,0) [0|0] "" XXX + SG_ ExtSteeringAngleReq : 7|15@0+ (0.1,-1000.0) [0|0] "Degrees" XXX + SG_ EPASExtAngleStatReq : 8|1@0+ (1,0) [0|0] "" XXX + +BO_ 937 ParkAid_Range_to_Target: 8 XXX + SG_ RangeToClosestObstacle : 55|12@0+ (1,0) [0|0] "cm" XXX + SG_ RangeRearCornerRtSn : 35|12@0+ (1,0) [0|0] "cm" XXX + SG_ RangeRearCornerLeftSn : 31|12@0+ (1,0) [0|0] "cm" XXX + SG_ RangeRearCenterRtSn : 11|12@0+ (1,0) [0|0] "cm" XXX + SG_ RangeRearCenterLeftSn : 7|12@0+ (1,0) [0|0] "cm" XXX + +BO_ 939 ParkAid_Data_CG1: 8 XXX + SG_ EPASExtAngleStatReq : 7|1@0+ (1,0) [0|0] "" XXX + SG_ ExtSteeringAngleReq : 6|15@0+ (0.1,-1000.0) [0|0] "Degrees" XXX + SG_ SAPPErrorCoding : 23|8@0+ (1,0) [0|0] "" XXX + SG_ RangeToClosestObstacle : 27|12@0+ (1,0) [0|0] "cm" XXX + +BO_ 942 BodyInformation_2: 8 XXX + SG_ Easy_Entry_Exit_Stat : 14|2@0+ (1,0) [0|0] "" XXX + SG_ Memory_Feedback_Rqst : 15|1@0+ (1,0) [0|0] "" XXX + SG_ Delay_Accy : 41|1@0+ (1,0) [0|0] "" XXX + SG_ Fuel_Econ_AFE_Reset_Req_UB : 43|1@0+ (1,0) [0|0] "" XXX + SG_ Multimedia_System : 42|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatDrv_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatHood_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatInnrTgate_B_Actl : 5|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatPsngr_B_Actl : 4|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatRl_B_Actl : 3|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatRr_B_Actl : 2|1@0+ (1,0) [0|0] "" XXX + SG_ DrStatTgate_B_Actl : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Fuel_Econ_AFE_Reset_Req : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Nav_Unit_Setting : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Cancel_Auto_Movement : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Cancel_Auto_Movement_UB : 8|1@0+ (1,0) [0|0] "" XXX + SG_ DrvSeat_Stat : 34|3@0+ (1,0) [0|0] "" XXX + SG_ DrvSeat_Stat_UB : 10|1@0+ (1,0) [0|0] "" XXX + SG_ Easy_Entry_Rqst : 47|2@0+ (1,0) [0|0] "" XXX + SG_ Easy_Entry_Rqst_UB : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Multimedia_System_UB : 40|1@0+ (1,0) [0|0] "" XXX + SG_ Memory_Cmd : 39|4@0+ (1,0) [0|0] "" XXX + SG_ Memory_Cmd_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ Memory_Feedback_Rqst_UB : 45|1@0+ (1,0) [0|0] "" XXX + SG_ Decklid_Ajar_Status : 44|1@0+ (1,0) [0|0] "" XXX + +BO_ 947 BodyInformation_3: 8 XXX + SG_ RearFog_Lamp_Ind_UB : 49|1@0+ (1,0) [0|0] "" XXX + SG_ RearFog_Lamp_Ind : 50|1@0+ (1,0) [0|0] "" XXX + SG_ PwMdeExten_D_Actl : 63|5@0+ (1,0) [0|0] "" XXX + SG_ Turn_Ind_Cmd_Right : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Turn_Ind_Cmd_Left : 9|1@0+ (1,0) [0|0] "" XXX + SG_ Ignition_Switch_Stable : 1|2@0+ (1,0) [0|0] "" XXX + SG_ Parklamp_Status : 3|2@0+ (1,0) [0|0] "" XXX + SG_ Litval : 47|8@0+ (1,0) [0|0] "" XXX + SG_ Key_In_Ignition_Stat : 11|2@0+ (1,0) [0|0] "" XXX + SG_ Ignition_Status : 7|4@0+ (1,0) [0|0] "" XXX + SG_ Dimming_Lvl : 31|8@0+ (1,0) [0|0] "" XXX + SG_ Day_Night_Status : 15|2@0+ (1,0) [0|0] "" XXX + SG_ Remote_Start_Status : 13|2@0+ (1,0) [0|0] "" XXX + SG_ DRV_SELECT_STAT : 19|4@0+ (1,0) [0|0] "" XXX + SG_ PrkBrkActv_B_Actl : 55|1@0+ (1,0) [0|0] "" XXX + SG_ HtdStrWhl_SftBtt_State_UB : 51|1@0+ (1,0) [0|0] "" XXX + SG_ HtdStrWhl_SftBtt_State : 53|2@0+ (1,0) [0|0] "" XXX + SG_ HvacRemoteStrt_N_Rq_UB : 56|1@0+ (1,0) [0|0] "" XXX + SG_ HvacRemoteStrt_N_Rq : 23|4@0+ (100.0,450.0) [0|0] "RPM" XXX + SG_ HvacAirCond_B_Rq_UB : 57|1@0+ (1,0) [0|0] "" XXX + SG_ Remote_Start_Warn_Req : 54|1@0+ (1,0) [0|0] "" XXX + SG_ HvacAirCond_B_Rq : 58|1@0+ (1,0) [0|0] "" XXX + +BO_ 948 Tire_Pressure_Status: 8 XXX + SG_ Tire_Press_ILR_Stat2 : 27|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_IRR_Stat2 : 31|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_LR_OLR_Stat2 : 19|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_RR_ORR_Stat2 : 23|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_RF_Stat2 : 11|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_LF_Stat2 : 15|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_System_Stat2 : 7|4@0+ (1,0) [0|0] "" XXX + SG_ Tire_Press_Telltale : 3|2@0+ (1,0) [0|0] "" XXX + +BO_ 949 Tire_Pressure_Data: 8 XXX + SG_ Tire_Press_RR_ORR_Data : 23|8@0+ (1,0) [0|0] "Psi" XXX + SG_ Tire_Press_RF_Data : 15|8@0+ (1,0) [0|0] "Psi" XXX + SG_ Tire_Press_LR_OLR_Data : 31|8@0+ (1,0) [0|0] "Psi" XXX + SG_ Tire_Press_IRR_Data : 39|8@0+ (1,0) [0|0] "Psi" XXX + SG_ Tire_Press_ILR_Data : 47|8@0+ (1,0) [0|0] "Psi" XXX + SG_ Tire_Press_LF_Data : 7|8@0+ (1,0) [0|0] "Psi" XXX + +BO_ 955 Smart_Headlamp_Stat: 8 XXX + SG_ Headlamp_Switch_Stat : 7|2@0+ (1,0) [0|0] "" XXX + SG_ Fog_Lamp_Dbnce : 5|2@0+ (1,0) [0|0] "" XXX + SG_ Digital_Dimmer_Sw_Stat : 3|3@0+ (1,0) [0|0] "" XXX + +BO_ 957 Rear_FogLamp: 8 XXX + SG_ RearFog_Lamp_Dbnce : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 963 BCM_to_HS_Body: 8 XXX + SG_ DrTgateChime_D_Rq_UB : 9|1@0+ (1,0) [0|0] "" XXX + SG_ DrTgateChime_D_Rq : 17|2@0+ (1,0) [0|0] "" XXX + SG_ CamraDefog_B_Actl : 4|1@0+ (1,0) [0|0] "" XXX + SG_ Reverse_Mirror_Stat : 61|2@0+ (1,0) [0|0] "" XXX + SG_ Power_Liftgate_Mode_Stat : 63|2@0+ (1,0) [0|0] "" XXX + SG_ IKT_Program_Status : 51|2@0+ (1,0) [0|0] "" XXX + SG_ Veh_Spd_Slow_Puddle_Status : 41|2@0+ (1,0) [0|0] "" XXX + SG_ Illuminated_Exit_Status : 43|2@0+ (1,0) [0|0] "" XXX + SG_ Illuminated_Entry_Status : 45|2@0+ (1,0) [0|0] "" XXX + SG_ Door_Courtesy_Light_Status : 47|2@0+ (1,0) [0|0] "" XXX + SG_ Courtesy_Demand_BSave_Stat : 33|2@0+ (1,0) [0|0] "" XXX + SG_ Alarm_Lights_Courtesy_Stat : 35|2@0+ (1,0) [0|0] "" XXX + SG_ Courtesy_Delay_Status : 37|2@0+ (1,0) [0|0] "" XXX + SG_ Courtesy_Mode_Status : 39|2@0+ (1,0) [0|0] "" XXX + SG_ Front_Fog_Light_SW_Status : 22|2@0+ (1,0) [0|0] "" XXX + SG_ Brake_Lamp_On_Status : 23|1@0+ (1,0) [0|0] "" XXX + SG_ LowBeam_CKT_CAN : 11|1@0+ (1,0) [0|0] "" XXX + SG_ ParkLamps_CKT_CAN : 8|1@0+ (1,0) [0|0] "" XXX + SG_ RF_Low_Beam_CKT_CAN : 13|1@0+ (1,0) [0|0] "" XXX + SG_ Brk_Fluid_Lvl_Low : 15|2@0+ (1,0) [0|0] "" XXX + SG_ LF_Low_Beam_CKT_CAN : 12|1@0+ (1,0) [0|0] "" XXX + SG_ High_Beam_Indicator_Rqst : 1|1@0+ (1,0) [0|0] "" XXX + SG_ Brake_Warn_Indicator_Rqst : 2|1@0+ (1,0) [0|0] "" XXX + SG_ Headlamp_On_Wrning_Cmd : 6|1@0+ (1,0) [0|0] "" XXX + SG_ Key_In_Ignition_Warn_Cmd : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Fog_Lamps_Rly_Ckt_CAN : 10|1@0+ (1,0) [0|0] "" XXX + SG_ Power_Liftgate_Mode_Stat_UB : 18|1@0+ (1,0) [0|0] "" XXX + SG_ Reverse_Mirror_Stat_UB : 7|1@0+ (1,0) [0|0] "" XXX + SG_ Park_Brake_Chime_Rqst : 3|1@0+ (1,0) [0|0] "" XXX + SG_ Daytime_Running_Lamps : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Running_Board_Stat_UB : 56|1@0+ (1,0) [0|0] "" XXX + SG_ Running_Board_Stat : 58|2@0+ (1,0) [0|0] "" XXX + SG_ Perimeter_Alarm_Chime_Rqst : 20|2@0+ (1,0) [0|0] "" XXX + +BO_ 967 CMPS_FDM_Info_Status: 8 XXX + SG_ CamraFrntStat_D_Stat : 41|2@0+ (1,0) [0|0] "" XXX + SG_ Zone_Icon_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ GPS_Compass_direction : 47|4@0+ (1,0) [0|0] "" XXX + SG_ Segment_MSD_UB : 37|1@0+ (1,0) [0|0] "" XXX + SG_ Segment_LSD_UB : 36|1@0+ (1,0) [0|0] "" XXX + SG_ ExcessiveMagnetism : 32|1@0+ (1,0) [0|0] "" XXX + SG_ Compass_Display_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ Segment_LSD : 15|8@0+ (1,0) [0|0] "" XXX + SG_ Segment_MSD : 7|8@0+ (1,0) [0|0] "" XXX + SG_ Cal_Icon : 21|1@0+ (1,0) [0|0] "" XXX + SG_ Zone_Icon : 22|1@0+ (1,0) [0|0] "" XXX + SG_ Compass_Display : 23|1@0+ (1,0) [0|0] "" XXX + SG_ Cal_Icon_UB : 33|1@0+ (1,0) [0|0] "" XXX + SG_ RearCameraDelayStat : 39|2@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlTow_D_Actl : 25|2@0+ (1,0) [0|0] "SE" XXX + SG_ CamZoomActiveState : 29|2@0+ (1,0) [0|0] "" XXX + SG_ CamraZoomMan_D_Actl : 18|3@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlStat_D_Actl : 27|2@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlDyn_D_Actl : 20|2@0+ (1,0) [0|0] "" XXX + SG_ CamPDCGuidStat : 31|2@0+ (1,0) [0|0] "" XXX + +BO_ 970 Lane_Assist_Data1: 8 XXX + SG_ LkaActvStats_D_Req : 7|3@0+ (1,0) [0|0] "" XXX + SG_ LdwActvStats_D_Req : 4|3@0+ (1,0) [0|0] "" XXX + SG_ LdwActvIntns_D_Req : 1|2@0+ (1,0) [0|0] "" XXX + +BO_ 971 Lane_Assist_Data2: 8 XXX + SG_ LaRefAng_No_Req : 19|12@0+ (0.05,-102.4) [0|0] "mrad" XXX + SG_ LaRampType_B_Req : 4|1@0+ (1,0) [0|0] "" XXX + SG_ LaCurvature_No_Calc : 3|12@0+ (5e-06,-0.01) [0|0] "1/m" XXX + +BO_ 972 Lane_Assist_Data3: 8 XXX + SG_ LaHandsOff_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + SG_ LaActDeny_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + SG_ LaActAvail_D_Actl : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 984 IPMA_Data: 8 XXX + SG_ LaSwtch_D_RqDrv : 45|1@0+ (1,0) [0|0] "" XXX + SG_ DasWarn_D_Dsply : 44|2@0+ (1,0) [0|0] "" XXX + SG_ DasStats_D_Dsply : 47|2@0+ (1,0) [0|0] "" XXX + SG_ DasAlrtLvl_D_Dsply : 55|3@0+ (1,0) [0|0] "" XXX + SG_ CamraStats_D_Dsply : 35|2@0+ (1,0) [0|0] "" XXX + SG_ CamraDefog_B_Req : 36|1@0+ (1,0) [0|0] "" XXX + SG_ LaSwtchStat_No_Actl : 63|1@0+ (1,0) [0|0] "" XXX + SG_ LaHandsOff_D_Dsply : 42|2@0+ (1,0) [0|0] "" XXX + SG_ LaDenyStats_B_Dsply : 40|1@0+ (1,0) [0|0] "" XXX + SG_ LaActvStats_D_Dsply : 52|5@0+ (1,0) [0|0] "" XXX + SG_ AhbcHiBeam_D_Rq : 33|2@0+ (1,0) [0|0] "" XXX + SG_ PersIndexIpma_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoIpmaActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigIpmaActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 986 Personality_APIM_Data3: 8 XXX + SG_ LightAmbIntSwtchInc_B : 22|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbIntSwtchDec_B : 21|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbIntsty_No_Rq : 15|8@0+ (1,0) [0|0] "% Intensity" XXX + SG_ LightAmbColor_No_Rq : 7|8@0+ (1,0) [0|0] "Color Index" XXX + SG_ LightAmbClrSwtchInc_B : 20|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbClrSwtchDec_B : 23|1@0+ (1,0) [0|0] "" XXX + +BO_ 991 Personality_VDM_Data: 8 XXX + SG_ PersIndexVdm_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoVdmActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigVdmActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 992 Personality_IPC_Data: 8 XXX + SG_ MsgCntrPersIndex_D_Rq : 39|3@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrFeatConfigRq : 23|16@0+ (1,0) [0|0] "" XXX + SG_ MsgCntrFeatNoRq : 7|16@0+ (1,0) [0|0] "Number" XXX + SG_ MsgCntrDsplyOp_D_Rq : 36|3@0+ (1,0) [0|0] "" XXX + +BO_ 993 Personality_Data_HS: 8 XXX + SG_ PersSetupRestr_D_Actl : 21|2@0+ (1,0) [0|0] "" XXX + SG_ PersSetupAccessCtrl : 19|1@0+ (1,0) [0|0] "SES" XXX + SG_ PersSetup_No_Actl : 31|16@0+ (1,0) [0|0] "Number" XXX + SG_ PersConflict_D_Actl : 22|1@0+ (1,0) [0|0] "" XXX + SG_ AssocConfirm_D_Actl : 15|3@0+ (1,0) [0|0] "" XXX + SG_ RecallEvent_No_Cnt : 7|8@0+ (1,0) [0|0] "Counts" XXX + SG_ PersNo_D_Actl : 10|3@0+ (1,0) [0|0] "" XXX + SG_ PersStore_D_Actl_UB : 23|1@0+ (1,0) [0|0] "" XXX + SG_ PersStore_D_Actl : 12|2@0+ (1,0) [0|0] "" XXX + +BO_ 994 Personality_APIM_Data: 8 XXX + SG_ CamraOvrlTow_D_Rq : 42|1@0+ (1,0) [0|0] "" XXX + SG_ Pers4OptIn_B_Stats : 43|1@0+ (1,0) [0|0] "" XXX + SG_ Pers3OptIn_B_Stats : 33|1@0+ (1,0) [0|0] "" XXX + SG_ Pers2OptIn_B_Stats : 32|1@0+ (1,0) [0|0] "" XXX + SG_ Pers1OptIn_B_Stats : 44|1@0+ (1,0) [0|0] "" XXX + SG_ CtrStkPersIndex_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ CtrStkFeatNoActl : 23|16@0+ (1,0) [0|0] "" XXX + SG_ PersStore_D_Rq : 36|3@0+ (1,0) [0|0] "" XXX + SG_ CtrStkFeatConfigActl : 7|16@0+ (1,0) [0|0] "" XXX + SG_ CtrStkDsplyOp_D_Rq : 47|3@0+ (1,0) [0|0] "" XXX + +BO_ 995 Personality_BCM_Data: 8 XXX + SG_ PersIndexBcm_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoBcm_No_Actl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigBcmActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 996 Personality_HCMB_Data_HS: 8 XXX + SG_ PersIndexHcmb_D_Actl_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ PersIndexHcmb_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoHcmbActl_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ FeatNoHcmbActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigHcmbActl_UB : 36|1@0+ (1,0) [0|0] "" XXX + SG_ FeatConfigHcmbActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 997 Personality_CCM_Data: 8 XXX + SG_ PersIndexCcm_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoCcmActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigCcmActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 998 Personality_SCCM_Data: 8 XXX + SG_ PersIndexSccm_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoSccmActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigSccmActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 999 Personality_HVAC_Data_HS: 8 XXX + SG_ LightAmbIntsty_No_Actl_UB : 33|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbIntsty_No_Actl : 55|8@0+ (1,0) [0|0] "% Intensity" XXX + SG_ LightAmbColor_No_Actl_UB : 32|1@0+ (1,0) [0|0] "" XXX + SG_ LightAmbColor_No_Actl : 47|8@0+ (1,0) [0|0] "Color Index" XXX + SG_ PersIndexHvac_D_Actl_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ FeatNoHvacActl_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ FeatConfigHvacActl_UB : 36|1@0+ (1,0) [0|0] "" XXX + SG_ PersIndexHvac_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoHvacActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigHvacActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1001 Personality_RFA_Data_HS: 8 XXX + SG_ PersIndexRfa_D_Actl_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ FeatNoRfaActl_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ FeatConfigRfaActl_UB : 36|1@0+ (1,0) [0|0] "" XXX + SG_ PersIndexRfa_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoRfaActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigRfaActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1002 Personality_APIM_Data2: 8 XXX + SG_ PersIndexApim_D_Actl : 63|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoApimActl : 39|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigApimActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ CntrStkKeycodeActl : 7|16@0+ (1,0) [0|0] "" XXX + SG_ CntrStk_D_RqRecall : 52|3@0+ (1,0) [0|0] "" XXX + SG_ CntrStk_D_RqAssoc : 55|3@0+ (1,0) [0|0] "" XXX + +BO_ 1003 Personality_IPC_Data_2: 8 XXX + SG_ PersIndexIpc_D_Actl : 34|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoIpcActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigIpcActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1004 Personality_DSM_Data_HS: 8 XXX + SG_ PersIndexDsm_D_Actl_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ PersIndexDsm_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoDsmActl_UB : 35|1@0+ (1,0) [0|0] "" XXX + SG_ FeatNoDsmActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigDsmActl_UB : 36|1@0+ (1,0) [0|0] "" XXX + SG_ FeatConfigDsmActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1005 Personality_RHVAC_Data_HS: 8 XXX + SG_ PersIndexRhvac_D_Actl_UB : 34|1@0+ (1,0) [0|0] "" XXX + SG_ FeatNoRhvacActl_UB : 33|1@0+ (1,0) [0|0] "" XXX + SG_ FeatConfigRhvacActl_UB : 32|1@0+ (1,0) [0|0] "" XXX + SG_ PersIndexRhvac_D_Actl : 39|3@0+ (1,0) [0|0] "" XXX + SG_ FeatNoRhvacActl : 23|16@0+ (1,0) [0|0] "Number" XXX + SG_ FeatConfigRhvacActl : 7|16@0+ (1,0) [0|0] "" XXX + +BO_ 1031 Diesel_Data_Legacy_1: 8 XXX + SG_ W2S_COMMAND : 7|1@0+ (1,0) [0|0] "" XXX + SG_ TURBO_BOOST : 1|10@0+ (0.1,-30.0) [0|0] "PSI" XXX + SG_ IDLE_ENGINE_SHUTDOWN : 42|2@0+ (1,0) [0|0] "" XXX + +BO_ 1034 GGCC_Config_Mgmt_ID_1: 8 XXX + SG_ VehicleGGCCData : 7|64@0+ (1,0) [0|0] "mixed" XXX + +BO_ 1036 Desired_Torq_BrkSys_Stat: 8 XXX + SG_ BRK_TC_TEMPORARILY_UNAVAIL : 47|1@0+ (1,0) [0|0] "" XXX + SG_ TRLR_SWAY_EVNT_IN_PROGRESS : 22|1@0+ (1,0) [0|0] "" XXX + +BO_ 1043 ADAPTIVE_HEADLAMP_STAT: 8 XXX + SG_ ADAPTIVE_HEADLAMP_FAILURE : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 1044 AccelerationData: 8 XXX + SG_ VehVertComp_A_Actl : 1|10@0+ (0.01,-0.4) [0|0] "m/s^2" XXX + SG_ VehRolComp_W_Actl : 19|12@0+ (0.0002,-0.82) [0|0] "rad/s" XXX + SG_ VehYawNonLin_W_Rq : 51|12@0+ (0.03663,-75.0) [0|0] "deg/s" XXX + SG_ VehYawLin_W_Rq : 35|12@0+ (0.03663,-75.0) [0|0] "deg/s" XXX + +BO_ 1045 BrakeSysFeatures: 8 XXX + SG_ TCMode : 34|1@0+ (1,0) [0|0] "" XXX + SG_ DrvSlipCtlLamp_D_Rq : 63|2@0+ (1,0) [0|0] "" XXX + SG_ RSCMode : 48|1@0+ (1,0) [0|0] "" XXX + SG_ EBAMode : 40|1@0+ (1,0) [0|0] "" XXX + SG_ DrvAntiLckLamp_D_Rq : 17|2@0+ (1,0) [0|0] "" XXX + SG_ ChimeBrk_B_Rq : 38|1@0+ (1,0) [0|0] "" XXX + SG_ BrkLamp_B_Rq : 39|1@0+ (1,0) [0|0] "" XXX + SG_ VehVActlBrk_No_Cs : 31|8@0+ (1,0) [0|0] "" XXX + SG_ VehVActlBrk_No_Cnt : 23|4@0+ (1,0) [0|0] "" XXX + SG_ Veh_V_ActlBrk : 7|16@0+ (0.01,0) [0|0] "kph" XXX + SG_ DrvSlipCtlMde_D_Ind : 33|2@0+ (1,0) [0|0] "" XXX + SG_ VehRol_An_Dsply : 55|7@0+ (1,-64.0) [0|0] "Degrees" XXX + SG_ VehPtch_An_Dsply : 47|7@0+ (1,-64.0) [0|0] "Degrees" XXX + SG_ VehVActlBrk_D_Qf : 19|2@0+ (1,0) [0|0] "" XXX + SG_ HILL_DESC_MC : 37|3@0+ (1,0) [0|0] "" XXX + +BO_ 1046 BrakeSysFeatures_2: 8 XXX + SG_ BpedMove_No_Cs : 23|8@0+ (1,0) [0|0] "" XXX + SG_ BpedMove_No_Cnt : 3|4@0+ (1,0) [0|0] "" XXX + SG_ BpedMove_D_Actl : 7|2@0+ (1,0) [0|0] "" XXX + SG_ AbsMduleAlive_No_Cnt : 39|4@0+ (1,0) [0|0] "" XXX + SG_ Abs_No_Cs : 31|8@0+ (1,0) [0|0] "" XXX + SG_ BrkAsst_B_Actl : 33|1@0+ (1,0) [0|0] "" XXX + SG_ StabCtlBrk_B_Avail : 4|1@0+ (1,0) [0|0] "" XXX + SG_ DrvHdcWarnInfo_D_Rq : 35|2@0+ (1,0) [0|0] "" XXX + SG_ DrvHdcMsg_D_Rq : 10|3@0+ (1,0) [0|0] "" XXX + SG_ DrvHdcLampInfo_D_Rq : 12|2@0+ (1,0) [0|0] "" XXX + SG_ Abs_B_Falt : 5|1@0+ (1,0) [0|0] "" XXX + SG_ VehLongComp_A_Actl : 49|10@0+ (0.035,-17.9) [0|0] "m/s^2" XXX + SG_ TRAILER_SWAY_CONFIG_STAT : 32|1@0+ (1,0) [0|0] "" XXX + SG_ VehLatComp_A_Actl : 47|10@0+ (0.035,-17.9) [0|0] "m/s^2" XXX + +BO_ 1047 TractionCtrlStatus_CG1: 8 XXX + SG_ EngEotcCtlMde_B_Ind : 3|1@0+ (1,0) [0|0] "" XXX + SG_ YawStabilityIndex : 48|9@0+ (1,-256.0) [0|0] "%" XXX + SG_ TCS_ENG_FAILD : 0|1@0+ (1,0) [0|0] "" XXX + SG_ TCS_ENG_ONLY_PRESENT : 1|1@0+ (1,0) [0|0] "" XXX + SG_ TCS_BRK_FAILD : 2|1@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTqRqMn_No_Cnt : 47|4@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTot_Tq_RqMn : 23|16@0+ (4.0,-131072.0) [0|0] "Nm" XXX + SG_ EngEotcCtlLamp_D_Rq : 9|2@0+ (1,0) [0|0] "" XXX + SG_ PrplWhlTqRqMn_No_Cs : 39|8@0+ (1,0) [0|0] "" XXX + SG_ HdcMde_D_Actl : 12|3@0+ (1,0) [0|0] "" XXX + SG_ VehicleDir_D_Est : 5|2@0+ (1,0) [0|0] "" XXX + SG_ TracCtlPtActv_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + +BO_ 1056 PowertrainData_1_CG1: 8 XXX + SG_ FUEL_ALCOHOL_PERCNT : 63|8@0+ (0.3937008,0) [0|0] "%" XXX + SG_ TrnTotTq_Rt_Est : 39|16@0+ (0.001,0) [0|0] "" XXX + SG_ TrnTotLss_Tq_Est : 31|8@0+ (0.5,0) [0|0] "Nm" XXX + SG_ ECMMILRequest : 9|2@0+ (1,0) [0|0] "" XXX + SG_ AirCondFluidHi_P_Actl : 55|8@0+ (0.125,0) [0|0] "bar" XXX + SG_ OilPressureWarning : 18|1@0+ (1,0) [0|0] "" XXX + SG_ CluPdlPos_Pc_Meas : 7|10@0+ (0.1,0) [0|0] "%" XXX + SG_ VehVLimStat_D_Actl : 12|3@0+ (1,0) [0|0] "" XXX + SG_ VehVLimActv_B_Actl : 13|1@0+ (1,0) [0|0] "" XXX + SG_ CluPdlPosPcMeas_D_Qf : 17|2@0+ (1,0) [0|0] "" XXX + SG_ CoolantFanStepAct : 23|5@0+ (1,0) [0|0] "Steps" XXX + +BO_ 1058 PowertrainData_2_CG1: 8 XXX + SG_ EngIdlShutDown_D_Stat : 19|2@0+ (1,0) [0|0] "" XXX + SG_ EngAout2_Tq_Actl : 55|11@0+ (1,-500.0) [0|0] "Nm" XXX + SG_ EngMsgTxt_D_Rq : 21|2@0+ (1,0) [0|0] "" XXX + SG_ EngClnt_Te_ActlDiag : 39|8@0+ (1,-40.0) [0|0] "degC" XXX + SG_ ThrPos_Pc_CalcDiag : 7|8@0+ (0.392157,0) [0|0] "%" XXX + SG_ EngLoad_Pc_CalcDiag : 47|8@0+ (0.392157,0) [0|0] "%" XXX + SG_ EngAirIn_Te_Actl : 15|10@0+ (0.25,-128.0) [0|0] "degC" XXX + SG_ ApedPos_Pc_ActlDiag : 31|8@0+ (0.392157,0) [0|0] "%" XXX + +BO_ 1064 StrgWheel_PolicePkg: 8 XXX + SG_ PoliceAux4Lamp_B_Rq : 4|1@0+ (1,0) [0|0] "" XXX + SG_ PoliceAux3Lamp_B_Rq : 5|1@0+ (1,0) [0|0] "" XXX + SG_ PoliceAux2Lamp_B_Rq : 6|1@0+ (1,0) [0|0] "" XXX + SG_ PoliceAux1Lamp_B_Rq : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 1067 Battery_Mgmt_1: 8 XXX + SG_ AlternatorExcDutyCycle : 31|5@0+ (3.22581,0) [0|0] "%" XXX + SG_ EngineEffStatus : 39|2@0+ (1,0) [0|0] "" XXX + SG_ AvailableCurrentAtIdle : 23|8@0+ (1,0) [0|0] "Amps" XXX + SG_ AvailableCurrent : 15|8@0+ (1,0) [0|0] "Amps" XXX + SG_ ActualCurrent : 7|8@0+ (1,0) [0|0] "Amps" XXX + SG_ NoAlternatorResponse : 26|1@0+ (1,0) [0|0] "" XXX + SG_ AlternatorTempFault : 25|1@0+ (1,0) [0|0] "" XXX + SG_ AlternatorMechFault : 24|1@0+ (1,0) [0|0] "" XXX + SG_ AlternatorElFault : 37|1@0+ (1,0) [0|0] "" XXX + +BO_ 1068 Battery_Mgmt_2: 8 XXX + SG_ ChargeMode : 39|3@0+ (1,0) [0|0] "" XXX + SG_ ChargeVoltageReq : 7|6@0+ (0.1,10.6) [0|0] "Volts" XXX + SG_ ChargeVoltageReqMax : 23|6@0+ (0.1,10.6) [0|0] "Volts" XXX + SG_ FrontBatteryTemp : 47|8@0+ (1,-60.0) [0|0] "DegC" XXX + SG_ IBoost_Msg : 52|4@0+ (1,0) [0|0] "" XXX + SG_ IdleSpeedIncrease_El : 8|1@0+ (1,0) [0|0] "" XXX + SG_ MaxLashStep : 11|3@0+ (0.1,0) [0|0] "Volts" XXX + SG_ PowerSystemStatus : 15|4@0+ (1,0) [0|0] "" XXX + SG_ Shed_T_Eng_Off_B : 17|1@0+ (1,0) [0|0] "" XXX + SG_ Shed_Level_Req : 55|3@0+ (1,0) [0|0] "" XXX + SG_ Shed_Feature_Group_ID : 36|5@0+ (1,0) [0|0] "" XXX + SG_ Shed_Drain_Eng_Off_B : 16|1@0+ (1,0) [0|0] "" XXX + SG_ Batt_Lo_SoC_B : 25|1@0+ (1,0) [0|0] "" XXX + SG_ VoltageRampRateUpMax : 31|6@0+ (0.1,0) [0|0] "Volts/sec" XXX + SG_ Batt_Crit_SoC_B : 24|1@0+ (1,0) [0|0] "" XXX + +BO_ 1069 Battery_Mgmt_3: 8 XXX + SG_ BSFault : 23|1@0+ (1,0) [0|0] "" XXX + SG_ BSBattSOC : 30|7@0+ (1,0) [0|0] "%" XXX + SG_ BSBattQDeltaRideAh : 38|15@0+ (0.0078125,-100.0) [0|0] "Ah" XXX + SG_ BSBattQCapAh : 22|7@0+ (1,0) [0|0] "Ah" XXX + SG_ BSBattCurrent : 5|14@0+ (0.0625,-512.0) [0|0] "Amps" XXX + SG_ BattULoState_D_Qlty : 7|2@0+ (1,0) [0|0] "" XXX + +BO_ 1072 Cluster_Information: 8 XXX + SG_ ManRgen_D_Rq : 5|2@0+ (1,0) [0|0] "" XXX + SG_ Easy_Entry_Exit_Cmd : 49|1@0+ (1,0) [0|0] "" XXX + SG_ KeyTypeChngMykey_D_Rq : 53|2@0+ (1,0) [0|0] "" XXX + SG_ DrvSlipCtlMde_B_Rq : 19|1@0+ (1,0) [0|0] "" XXX + SG_ MetricActv_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + SG_ LdwDfaltOn_B_Actl : 0|1@0+ (1,0) [0|0] "" XXX + SG_ Fda_B_Stat : 9|1@0+ (1,0) [0|0] "" XXX + SG_ ePRNDL_MODE : 8|1@0+ (1,0) [0|0] "" XXX + SG_ AccDeny_B_RqIpc : 7|1@0+ (1,0) [0|0] "" XXX + SG_ MetricActvTe_B_Actl : 23|1@0+ (1,0) [0|0] "" XXX + SG_ EngOilLife_B_RqReset : 18|1@0+ (1,0) [0|0] "" XXX + SG_ OdometerMasterValue : 31|24@0+ (1,0) [0|0] "km" XXX + SG_ New_Module_Attn_Event : 56|1@0+ (1,0) [0|0] "" XXX + SG_ TRAILER_SWAY_CONFIG_CMD : 60|1@0+ (1,0) [0|0] "" XXX + SG_ ParkDetect_Stat : 62|1@0+ (1,0) [0|0] "" XXX + SG_ Attn_Info_Audio : 59|3@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkMde_D_Rq : 61|1@0+ (1,0) [0|0] "" XXX + SG_ TRAILER_BRAKE_CONFIG : 48|1@0+ (1,0) [0|0] "" XXX + SG_ VehMykey_Vl_LimRq : 63|1@0+ (1,0) [0|0] "" XXX + SG_ VehMykey_V_LimRqMx : 51|1@0+ (1,0) [0|0] "" XXX + SG_ EmgcyCallAsstMykey_Rq : 50|1@0+ (1,0) [0|0] "" XXX + SG_ DrvSlipCtlMde_D_Rq : 17|2@0+ (1,0) [0|0] "" XXX + SG_ AccEnbl_B_RqDrv : 20|1@0+ (1,0) [0|0] "" XXX + SG_ AutoHighBeam_Cmd : 55|2@0+ (1,0) [0|0] "" XXX + +BO_ 1075 Cluster_Information_3_CG1: 8 XXX + SG_ CamraFrntStat_D_Rq : 58|1@0+ (1,0) [0|0] "" XXX + SG_ DieslFuelBio_B_ActlDrv : 56|1@0+ (1,0) [0|0] "" XXX + SG_ RearCameraDelayCmd : 59|1@0+ (1,0) [0|0] "" XXX + SG_ UreaWarnReset : 60|1@0+ (1,0) [0|0] "" XXX + SG_ DistanceBarSetting : 49|1@0+ (1,0) [0|0] "" XXX + SG_ CamraZoomMan_D_Rq : 63|3@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlStat_D_Rq : 48|1@0+ (1,0) [0|0] "" XXX + SG_ CamraOvrlDyn_D_Rq : 25|1@0+ (1,0) [0|0] "" XXX + SG_ CamAutoTowbarZoom : 24|1@0+ (1,0) [0|0] "" XXX + SG_ FuelSecndActv_B_Actl : 39|1@0+ (1,0) [0|0] "" XXX + SG_ HILL_DESC_SW : 38|1@0+ (1,0) [0|0] "" XXX + SG_ FuelLvlPssvSide_No_Raw : 19|10@0+ (1,0) [0|0] "" XXX + SG_ SPDJBCompassCMDDecalibrate : 50|1@0+ (1,0) [0|0] "" XXX + SG_ SPDJBCompassCMDChangeZone : 51|1@0+ (1,0) [0|0] "" XXX + SG_ SPDJBCompassCmdDesiredZone : 55|4@0+ (1,0) [0|0] "" XXX + SG_ FUEL_SENSOR_NUM : 35|1@0+ (1,0) [0|0] "" XXX + SG_ W2S_LAMP_OK : 37|1@0+ (1,0) [0|0] "" XXX + SG_ Beltminder_Warn_Stats_IPC : 32|1@0+ (1,0) [0|0] "" XXX + SG_ FuelLvlActvSide_No_Raw : 13|10@0+ (1,0) [0|0] "" XXX + SG_ FuelLvl_Pc_Dsply : 7|10@0+ (0.108696,-5.22) [0|0] "%" XXX + SG_ FUEL_LVL_PER_MEAN : 47|8@0+ (0.434783,-5.22) [0|0] "% Indication" XXX + SG_ Fuel_Level_State : 34|2@0+ (1,0) [0|0] "" XXX + SG_ H2O_IN_FUEL_LAMP_OK_OBD : 36|1@0+ (1,0) [0|0] "" XXX + +BO_ 1093 TrailerBrakeInfo: 8 XXX + SG_ TrlrLampCnnct_B_Actl : 22|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkActCnnct_B_Actl : 16|1@0+ (1,0) [0|0] "" XXX + SG_ StopLamp_B_RqTrlrBrk : 7|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkOut_No_Dsply : 3|4@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkGain_No_Actl : 21|5@0+ (0.5,0) [0|0] "" XXX + SG_ TrlrBrkDsply_B_Rq : 6|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkDcnnt_B_Actl : 5|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkCtl_B_Falt : 4|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkActCirct_B_Falt : 39|1@0+ (1,0) [0|0] "" XXX + SG_ TrlrBrkMde_D_Actl : 23|1@0+ (1,0) [0|0] "" XXX + +BO_ 1104 SHCM_Status: 8 XXX + SG_ CURRENT_DRAW : 15|8@0+ (0.5,0) [0|0] "Amps" XXX + SG_ SECONDARY_HEATER_STAT : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 1107 PassengerOCSSerialNum: 8 XXX + SG_ OCSSerialNoByte8 : 63|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte7 : 55|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte6 : 47|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte5 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte4 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte3 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte2 : 15|8@0+ (1,0) [0|0] "" XXX + SG_ OCSSerialNoByte1 : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 1108 RCMSerialNumber: 8 XXX + SG_ RCMSerialNoByte8 : 63|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte7 : 55|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte6 : 47|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte5 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte4 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte3 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte2 : 15|8@0+ (1,0) [0|0] "" XXX + SG_ RCMSerialNoByte1 : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 1109 eCall_Info: 8 XXX + SG_ eCallConfirmation : 7|3@0+ (1,0) [0|0] "" XXX + +BO_ 1125 GPS_Data_Nav_1_HS: 8 XXX + SG_ GpsHsphLattSth_D_Actl : 25|2@0+ (1,0) [0|0] "" XXX + SG_ GpsHsphLongEast_D_Actl : 9|2@0+ (1,0) [0|0] "" XXX + SG_ GPS_Longitude_Minutes : 46|6@0+ (1,0) [0|0] "Minutes" XXX + SG_ GPS_Longitude_Min_dec : 55|14@0+ (0.0001,0) [0|0] "Minutes" XXX + SG_ GPS_Longitude_Degrees : 39|9@0+ (1,-179.0) [0|0] "Degrees" XXX + SG_ GPS_Latitude_Minutes : 15|6@0+ (1,0) [0|0] "Minutes" XXX + SG_ GPS_Latitude_Min_dec : 23|14@0+ (0.0001,0) [0|0] "Minutes" XXX + SG_ GPS_Latitude_Degrees : 7|8@0+ (1,-89.0) [0|0] "Degrees" XXX + +BO_ 1126 GPS_Data_Nav_2_HS: 8 XXX + SG_ Gps_B_Falt : 2|1@0+ (1,0) [0|0] "" XXX + SG_ GpsUtcYr_No_Actl : 55|5@0+ (1,1.0) [0|0] "Year" XXX + SG_ GpsUtcMnth_No_Actl : 47|4@0+ (1,1.0) [0|0] "Month" XXX + SG_ GpsUtcDay_No_Actl : 37|5@0+ (1,1.0) [0|0] "Day" XXX + SG_ GPS_UTC_seconds : 23|6@0+ (1,0) [0|0] "seconds" XXX + SG_ GPS_UTC_minutes : 15|6@0+ (1,0) [0|0] "Minutes" XXX + SG_ GPS_UTC_hours : 7|5@0+ (1,0) [0|0] "Hours" XXX + SG_ GPS_Pdop : 31|5@0+ (0.2,0) [0|0] "" XXX + SG_ GPS_Compass_direction : 26|4@0+ (1,0) [0|0] "" XXX + SG_ GPS_Actual_vs_Infer_pos : 38|1@0+ (1,0) [0|0] "" XXX + +BO_ 1127 GPS_Data_Nav_3_HS: 8 XXX + SG_ GPS_Vdop : 63|5@0+ (0.2,0) [0|0] "" XXX + SG_ GPS_Speed : 47|8@0+ (1,0) [0|0] "MPH" XXX + SG_ GPS_Sat_num_in_view : 7|5@0+ (1,0) [0|0] "" XXX + SG_ GPS_MSL_altitude : 15|12@0+ (10.0,-20460.0) [0|0] "feet" XXX + SG_ GPS_Heading : 31|16@0+ (0.01,0) [0|0] "Degrees" XXX + SG_ GPS_Hdop : 55|5@0+ (0.2,0) [0|0] "" XXX + SG_ GPS_dimension : 2|3@0+ (1,0) [0|0] "" XXX + +BO_ 1152 All_Terrain_Data: 8 XXX + SG_ HdcSwitchPos_B_Actl : 0|1@0+ (1,0) [0|0] "" XXX + SG_ TerrStat_D_RqDsply : 7|4@0+ (1,0) [0|0] "" XXX + SG_ TerrMde_D_RqDrv : 3|3@0+ (1,0) [0|0] "" XXX + +BO_ 1186 Information_4x4_2_CG1: 8 XXX + SG_ RearDiffFalt_D_Stat : 23|2@0+ (1,0) [0|0] "" XXX + SG_ RearDiffLck_Tq_Actl : 7|12@0+ (1,0) [0|0] "Nm" XXX + SG_ RearDiffLckMsg_D_Rq : 20|3@0+ (1,0) [0|0] "" XXX + SG_ AwdSrvcRqd_B_Rq : 21|1@0+ (1,0) [0|0] "" XXX + SG_ RearDiffLckLamp_D_Rq : 11|2@0+ (1,0) [0|0] "" XXX diff --git a/opendbc_repo/opendbc/dbc/ford_fusion_2018_adas.dbc b/opendbc_repo/opendbc/dbc/ford_fusion_2018_adas.dbc new file mode 100644 index 0000000000..2e1647b3d8 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/ford_fusion_2018_adas.dbc @@ -0,0 +1,421 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + +BO_ 1280 Object_00: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1281 Object_01: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1282 Object_02: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1283 Object_03: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1284 Object_04: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1285 Object_05: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1286 Object_06: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1287 Object_07: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1288 Object_08: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1289 Object_09: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1290 Object_10: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1291 Object_11: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1292 Object_12: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1293 Object_13: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1294 Object_14: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1295 Object_15: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1296 Object_16: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1297 Object_17: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1298 Object_18: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1299 Object_19: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1300 Object_20: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1301 Object_21: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1302 Object_22: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1303 Object_23: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1304 Object_24: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1305 Object_25: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1306 Object_26: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1307 Object_27: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1308 Object_28: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1309 Object_29: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1310 Object_30: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1311 Object_31: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1312 Object_32: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1313 Object_33: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1314 Object_34: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1315 Object_35: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1316 Object_36: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1317 Object_37: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1318 Object_38: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1319 Object_39: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1320 Object_40: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1321 Object_41: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1322 Object_42: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1323 Object_43: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1324 Object_44: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1325 Object_45: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1326 Object_46: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1327 Object_47: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1328 Object_48: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1329 Object_49: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1330 Object_50: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1331 Object_51: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1332 Object_52: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1333 Object_53: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1334 Object_54: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1335 Object_55: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1336 Object_56: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1337 Object_57: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1338 Object_58: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1339 Object_59: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1340 Object_60: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1341 Object_61: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1342 Object_62: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + +BO_ 1343 Object_63: 8 XXX + SG_ X_Rel : 18|11@0+ (0.1,0) [0|0] "m" XXX + SG_ V_Rel : 52|13@0- (0.01,0) [0|0] "m/s" XXX + SG_ A_Rel : 33|10@0- (0.05,0) [0|0] "m/s2" XXX + SG_ Angle : 12|10@0- (-0.1,0) [0|0] "deg" XXX + diff --git a/opendbc_repo/opendbc/dbc/ford_fusion_2018_pt.dbc b/opendbc_repo/opendbc/dbc/ford_fusion_2018_pt.dbc new file mode 100644 index 0000000000..c4b706d064 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/ford_fusion_2018_pt.dbc @@ -0,0 +1,139 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + +BO_ 130 EPAS_INFO: 8 XXX + SG_ SteMdule_U_Meas : 39|8@0+ (0.05,6.0) [0|0] "Volts" XXX + SG_ SteMdule_I_Est : 21|12@0+ (0.05,-64.0) [0|0] "Amps" XXX + SG_ EPAS_FAILURE : 9|2@0+ (1,0) [0|0] "" XXX + SG_ SteeringColumnTorque : 7|8@0+ (0.0625,-8.0) [0|0] "Nm" XXX + SG_ SAPPAngleControlStat6 : 15|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat5 : 14|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat4 : 13|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat3 : 12|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat2 : 11|1@0+ (1,0) [0|0] "" XXX + SG_ SAPPAngleControlStat1 : 23|2@0+ (1,0) [0|0] "" XXX + +BO_ 118 Steering_Wheel_Data_CG1: 8 XXX + SG_ SteWhlRelInit_An_Sns : 6|15@0+ (0.1,-1600.0) [0|0] "deg" XXX + SG_ SteWhlRelCalib_An_Sns : 23|15@0+ (0.1,-1600.0) [0|0] "deg" XXX + SG_ SteWhlRelInit2_An_Sns : 55|16@0+ (0.1,-3200.0) [0|0] "deg" XXX + SG_ SteWhlAn_No_Cs : 39|8@0+ (1,0) [0|0] "" XXX + SG_ SteWhlAn_No_Cnt : 47|4@0+ (1,0) [0|0] "Counts" XXX + +BO_ 131 Steering_Buttons: 8 XXX + SG_ Right_Turn_Light : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Left_Turn_Light : 4|1@0+ (1,0) [0|0] "" XXX + SG_ Dist_Decr : 12|1@0+ (1,0) [0|0] "" XXX + SG_ Dist_Incr : 11|1@0+ (1,0) [0|0] "" XXX + SG_ Cancel : 8|1@0+ (1,0) [0|0] "" XXX + SG_ Resume : 29|1@0+ (1,0) [0|0] "" XXX + SG_ Set : 28|1@0+ (1,0) [0|0] "" XXX + SG_ Main : 38|1@0+ (1,0) [0|0] "" XXX + +BO_ 145 Yaw_Data: 8 XXX + SG_ VehYaw_W_Actl : 39|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + SG_ VehRol_W_Actl : 23|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + SG_ VehPtch_W_Actl : 7|16@0+ (0.0002,-6.5) [0|0] "rad/s" XXX + +BO_ 146 Accel_Data: 8 XXX + SG_ VehVertAActl_D_Qf : 38|2@0+ (1,0) [0|0] "" XXX + SG_ VehLongAActl_D_Qf : 22|2@0+ (1,0) [0|0] "" XXX + SG_ VehLatAActl_D_Qf : 6|2@0+ (1,0) [0|0] "" XXX + SG_ VehVert_A_Actl : 36|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX + SG_ VehLong_A_Actl : 20|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX + SG_ VehLat_A_Actl : 4|13@0+ (0.01,-40.0) [0|0] "m/s^2" XXX + +BO_ 357 Cruise_Status: 8 XXX + SG_ Brake_Drv_Appl : 5|1@0+ (1,0) [0|0] "" XXX + SG_ Cruise_State : 11|4@0+ (1,0) [0|0] "" XXX + SG_ Set_Speed : 23|8@0+ (1,0) [0|0] "" XXX + +BO_ 516 EngineData_14: 8 XXX + SG_ ApedPosScal_Pc_Actl : 1|10@0+ (0.1,0) [0|0] "%" XXX + +BO_ 535 WheelSpeed_CG1: 8 XXX + SG_ WhlRr_W_Meas : 55|14@0+ (0.04,0) [0|0] "rad/s" XXX + SG_ WhlRl_W_Meas : 39|14@0+ (0.04,0) [0|0] "rad/s" XXX + SG_ WhlFr_W_Meas : 23|14@0+ (0.04,0) [0|0] "rad/s" XXX + SG_ WhlFl_W_Meas : 7|14@0+ (0.04,0) [0|0] "rad/s" XXX + +BO_ 534 WheelData: 8 XXX + SG_ WhlRotatRr_No_Cnt : 23|8@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRr_D_Actl : 33|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirRl_D_Actl : 39|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFr_D_Actl : 37|2@0+ (1,0) [0|0] "" XXX + SG_ WhlDirFl_D_Actl : 35|2@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatRl_No_Cnt : 31|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFr_No_Cnt : 7|8@0+ (1,0) [0|0] "" XXX + SG_ WhlRotatFl_No_Cnt : 15|8@0+ (1,0) [0|0] "" XXX + SG_ WHEEL_ROLLING_TIMESTAMP : 47|8@0+ (1,0) [0|0] "" XXX + +BO_ 947 Doors: 8 XXX + SG_ Door_FL_Open : 61|1@0+ (1,0) [0|0] "" XXX + SG_ Door_FR_Open : 60|1@0+ (1,0) [0|0] "" XXX + SG_ Door_RL_Open : 48|1@0+ (1,0) [0|0] "" XXX + SG_ Door_RR_Open : 49|1@0+ (1,0) [0|0] "" XXX + +BO_ 963 BCM_to_HS_Body: 8 XXX + SG_ Brake_Lights : 8|1@0+ (1,0) [0|0] "" XXX + +BO_ 970 Lane_Keep_Assist_Control: 8 XXX + SG_ Lkas_Action : 7|4@0+ (1,0) [0|15] "" XXX + SG_ Lkas_Alert : 3|4@0+ (1,0) [0|15] "" XXX + SG_ Lane_Curvature : 15|12@0+ (5e-06,-0.01) [0|0] "1/m" XXX + SG_ Steer_Angle_Req : 19|12@0+ (0.04297,-88.00445) [0|0] "deg" XXX + +BO_ 972 Lane_Keep_Assist_Status: 8 XXX + SG_ LaHandsOff_B_Actl : 7|1@0+ (1,0) [0|0] "" XXX + SG_ LaActDeny_B_Actl : 6|1@0+ (1,0) [0|0] "" XXX + SG_ LaActAvail_D_Actl : 5|2@0+ (1,0) [0|0] "" XXX + +BO_ 984 Lane_Keep_Assist_Ui: 8 XXX + SG_ Set_Me_X80 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ Set_Me_X45 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ Lines_Hud : 55|4@0+ (1,0) [0|15] "" XXX + SG_ Hands_Warning_W_Chime : 50|1@0+ (1,0) [0|1] "" XXX + SG_ Hands_Warning : 49|1@0+ (1,0) [0|1] "" XXX + SG_ Set_Me_X30 : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ SG_ 970 Lkas_Action "only vals 4, 5, 8, 9 seem to work. 4 and 5 are a bit smoother" ; + +VAL_ 357 Cruise_State 4 "active" 3 "standby" 0 "off" ; +VAL_ 970 Lkas_Action 15 "off" 9 "abrupt" 8 "abrupt2" 5 "smooth" 4 "smooth2" ; +VAL_ 970 Lkas_Alert 15 "no_alert" 3 "high_intensity" 2 "mid_intensity" 1 "low_intensity" ; +VAL_ 972 LaActAvail_D_Actl 3 "available" 2 "tbd" 1 "not_available" 0 "fault" ; +VAL_ 984 Lines_Hud 15 "none" 11 "grey_yellow" 8 "green_red" 7 "yellow_grey" 6 "grey_grey" 4 "red_green" 3 "green_green" ; diff --git a/opendbc_repo/opendbc/dbc/ford_lincoln_base_pt.dbc b/opendbc_repo/opendbc/dbc/ford_lincoln_base_pt.dbc new file mode 100644 index 0000000000..828e4118ee --- /dev/null +++ b/opendbc_repo/opendbc/dbc/ford_lincoln_base_pt.dbc @@ -0,0 +1,12717 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: VDM CMR_DSMC SOBDMC_HPCM_FD1 IPMA_ADAS PSCM ABS_ESC TCCM TCM_DSL PCM_HEV PCM ECM_Diesel GENERIC_GWMWakeup GWM _delete TSTR + +VAL_TABLE_ DcacRdy_D_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "Faulted" 4 "ProtectionTempearture" 3 "ProtectionOverload" 2 "ProtectionGfci" 1 "Active" 0 "Idle"; +VAL_TABLE_ HvacCmprLim_D_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "CompressorHeadPressure" 4 "AvailableTorque" 3 "PedalPosition" 2 "RPM" 1 "ECT" 0 "NoLimit"; +VAL_TABLE_ AdvStrt_D_Stat 15 "NotUsed_15" 14 "NotUsed_14" 13 "NotUsed_13" 12 "NotUsed_12" 11 "NotUsed_11" 10 "NotUsed_10" 9 "NotUsed_9" 8 "NotUsed_8" 7 "NotUsed_7" 6 "NotUsed_6" 5 "NotUsed_5" 4 "NotUsed_4" 3 "NotUsed_3" 2 "NotUsed_2" 1 "NotUsed_1" 0 "NoAction"; +VAL_TABLE_ VehOnSrc_D_Stat 15 "NotUsed_11" 14 "NotUsed_10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "NotUsed_4" 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "OverTheAir" 3 "RemoteParkAssist" 2 "RemoteStart" 1 "Manual" 0 "Off"; +VAL_TABLE_ NoMessage_Msg1_63 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ TrlrRvrseEnbl_D2_Stat 7 "NotUsed" 6 "TbaActiveExpertActive" 5 "TbaActiveExpertAvail" 4 "TbaOffTrgActive" 3 "TbaOffTrgSetup" 2 "TbaSetup" 1 "TbaActive" 0 "Inactive"; +VAL_TABLE_ Off_On_FlashChime 7 "NotUsed_5" 6 "NotUsed_4" 5 "NotUsed_3" 4 "NotUsed_2" 3 "NotUsed_1" 2 "FlashChime" 1 "On" 0 "Off"; +VAL_TABLE_ DieslPrtcWarn_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "OCR_ExhFilterClean_Stopped" 10 "OCR_ExhFilterCleaned" 9 "RgnOff_AtLimit" 8 "RgnOff_OverLoaded" 7 "RgnOff_Loaded" 6 "Exhaust_Filter_Full" 5 "DPF_OverLimit" 4 "DPF_AtLimit" 3 "ExhFilter_Drive_Completed" 2 "Cleaning_Exhaust_Filter" 1 "DPF_OverLoaded" 0 "DPF_Normal_Operation"; +VAL_TABLE_ StrtrMtrCtlMsgTxt_D2_Rq 3 "NotUsed" 2 "ShiftToNeutralToStart" 1 "ShiftToParkToStart" 0 "NoRequest"; +VAL_TABLE_ PaakMyKey_D_Rq 3 "NotUsed" 2 "ConfirmNewPaakMyKey" 1 "RequestNewPaakMyKey" 0 "None"; +VAL_TABLE_ PaakMyKeySearch_D_Stat 7 "PhoneErased" 6 "LockButtonTimeOut" 5 "PressLockButton" 4 "ConfirmHmi" 3 "MyKeyPaakFound" 2 "StandardPaakFound" 1 "NoValidPaakFound" 0 "Null"; +VAL_TABLE_ TrlrIdType_D_Stat 3 "Gooseneck" 2 "FifthWheel" 1 "Conventional" 0 "Null"; +VAL_TABLE_ TrlrAidSetup_D2_Rq 15 "NotUsed_9" 14 "NotUsed_8" 13 "NotUsed_7" 12 "NotUsed_6" 11 "NotUsed_5" 10 "NotUsed_4" 9 "NotUsed_3" 8 "NotUsed_2" 7 "NotUsed_1" 6 "CompleteSetup" 5 "ReturnToSetup" 4 "StickerNotCircled" 3 "ConfirmSetup" 2 "EndSetup" 1 "BeginSetup" 0 "Inactive"; +VAL_TABLE_ TrlrAidEnbl_D2_Rq 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Deactivate" 2 "ActivateTrg" 1 "ActivateTba" 0 "Inactive"; +VAL_TABLE_ BattChrgMde_D_Actl 3 "NotUsed" 2 "ConstantCurrent" 1 "ConstantVoltage" 0 "NotCharging"; +VAL_TABLE_ LcwaLeft_D_Stat 7 "Faulty" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Disabled" 2 "TemporaryUnavailable" 1 "SensorBlocked" 0 "Available"; +VAL_TABLE_ LcwaMsgTxt_D_Stat 3 "SodXFaulty" 2 "SodXBlocked" 1 "TrailerConnected" 0 "NoMessage"; +VAL_TABLE_ Level_0_3 3 "Level_3" 2 "Level_2" 1 "Level_1" 0 "Level_0"; +VAL_TABLE_ SteWhlSwtchMde_D_Stat 3 "NotUsed_2" 2 "NotUsed_1" 1 "Dialog" 0 "Domain"; +VAL_TABLE_ TrlrRvrse_D_Stat 3 "Faulty" 2 "TrailerReverseGuidanceLite" 1 "On" 0 "Off"; +VAL_TABLE_ TrlrAid_D2_Stat 15 "Faulty" 14 "NotUsed_4" 13 "NotUsed_3" 12 "NotUsed_2" 11 "NotUsed_1" 10 "DirtyCamera" 9 "IncorrectLighting" 8 "TrackingLost" 7 "TrackingUnknownConfidence" 6 "TrackingHighConfidence" 5 "TrackingMediumConfidence" 4 "TrackingLowConfidence" 3 "TurnRequested" 2 "DriveStraighRequested" 1 "Initializing" 0 "NotTracking"; +VAL_TABLE_ AwdDrvMde_D2 15 "Faulty" 14 "NotUsed_7" 13 "NotUsed_6" 12 "NotUsed_5" 11 "NotUsed_4" 10 "NotUsed_3" 9 "NotUsed_2" 8 "NotUsed_1" 7 "NotAvailable" 6 "TowHaul" 5 "RockCrawl" 4 "Baja" 3 "MudAndSand" 2 "Weather" 1 "Sport" 0 "Normal"; +VAL_TABLE_ TrlrAidSetup_D2_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "SetupAcquisitionSuccess" 4 "TbaTadMonitor" 3 "SetupStartAcquisition" 2 "SetupPrepForAcquisition" 1 "TbaActive" 0 "Null"; +VAL_TABLE_ CamraRearOn_D2_Stat2 7 "Faulty" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Decommission" 2 "Activate" 1 "Deactivate" 0 "Null"; +VAL_TABLE_ AirCondClu_D_Stat 7 "NotUsed" 6 "FetLifeLimitReached" 5 "FetOpenCircuit" 4 "FetOutputShortToPower" 3 "FetOutputShortToGround" 2 "FetNotControlled" 1 "OnPowerToLoad" 0 "OffNoPowerToLoad"; +VAL_TABLE_ BattChrgTrgtSoC_D_Rq 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_TABLE_ OffNormalSoft 3 "NotUsed" 2 "Soft" 1 "Normal" 0 "Off"; +VAL_TABLE_ OffOnDisabledInhibited 3 "Inhibited" 2 "Disabled" 1 "On" 0 "Off"; +VAL_TABLE_ DgtlCommGtwyMde_D_Rq 15 "NotUsed_10" 14 "NotUsed_9" 13 "NotUsed_8" 12 "NotUsed_7" 11 "NotUsed_6" 10 "NotUsed_5" 9 "NotUsed_4" 8 "NotUsed_3" 7 "NotUsed_2" 6 "NotUsed_1" 5 "AcPnC" 4 "AcEIM" 3 "DcPnC" 2 "DcEIM" 1 "AttemptDgtlComm" 0 "NoDgtlComm"; +VAL_TABLE_ BattDcCnnct_D_Cmd 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "WeldCheck" 3 "OkToDischarge" 2 "Closed" 1 "Precharge" 0 "Open"; +VAL_TABLE_ Null_NoFault_Fault 3 "NotUsed" 2 "Fault" 1 "NoFault" 0 "Null"; +VAL_TABLE_ ModemReset_D_Rq 15 "NotUsed_11" 14 "NotUsed_10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "NotUsed_4" 7 "NotUsed_3" 6 "BrandConnectReset2" 5 "BrandConnectReset1" 4 "CcsReset" 3 "OnlineTrafficReset" 2 "PaakReset" 1 "WifiHotspotReset" 0 "Null"; +VAL_TABLE_ PrkAsstSlotId_D_Stat 7 "Faulty" 6 "Slot6" 5 "Slot5" 4 "Slot4" 3 "Slot3" 2 "Slot2" 1 "Slot1" 0 "NoSlotFound"; +VAL_TABLE_ RstrnOnPsngr_D_RqMnu 15 "Faulty" 14 "NotUsed_11" 13 "NotUsed_10" 12 "ConfiguredOff" 11 "NotUsed_9" 10 "On" 9 "NotUsed_8" 8 "NotUsed_7" 7 "NotUsed_6" 6 "NotUsed_5" 5 "Off" 4 "NotUsed_4" 3 "NotUsed_3" 2 "NotUsed_2" 1 "NotUsed_1" 0 "NoAction"; +VAL_TABLE_ BalrInnrLeft_D_Stat 3 "Reporting" 2 "NotReporting" 1 "SystemStandby" 0 "Initialization"; +VAL_TABLE_ Zero_1_2_4 3 "Four" 2 "Two" 1 "One" 0 "Zero"; +VAL_TABLE_ NoReq_AutoUp_Stop 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_TABLE_ BalrSnsLeft_D_Falt 3 "Invalid" 2 "SystemFailure" 1 "Blocked" 0 "Clear"; +VAL_TABLE_ Null_Low_Med_High 3 "High" 2 "Medium" 1 "Low" 0 "Null"; +VAL_TABLE_ Null_NotPressed_Pressed 3 "NotUsed" 2 "Pressed" 1 "NotPressed" 0 "Null"; +VAL_TABLE_ Low_Med_High 3 "NotUsed" 2 "High" 1 "Medium" 0 "Low"; +VAL_TABLE_ Null_NotAvail_Avail 3 "NotUsed" 2 "Available" 1 "NotAvailable" 0 "Null"; +VAL_TABLE_ ChrgGoTMnte_D_Stat 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Minute_55" 10 "Minute_50" 9 "Minute_45" 8 "Minute_40" 7 "Minute_35" 6 "Minute_30" 5 "Minute_25" 4 "Minute_20" 3 "Minute_15" 2 "Minute_10" 1 "Minute_5" 0 "Minute_0"; +VAL_TABLE_ NoData_Faulty_1E_1F 31 "Faulty" 30 "NoDataExists"; +VAL_TABLE_ PwFlwBatt_D_Dsply 15 "NotUsed_8" 14 "NotUsed_7" 13 "NotUsed_6" 12 "NotUsed_5" 11 "NotUsed_4" 10 "NotUsed_3" 9 "NotUsed_2" 8 "NotUsed_1" 7 "FlwFromWallToBatt" 6 "FlwFromAllWhlsToBatt" 5 "FlwFromBattToAllWhls" 4 "FlwFromFrontWhlsToBatt" 3 "FlwFromBattToFrontWhls" 2 "FlwFromRearWhlsToBatt" 1 "FlwFromBattToRearWhls" 0 "NoFlow"; +VAL_TABLE_ PwFlwFuelDrv_D_Dsply 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "FlwFromFuelToAllWhls" 2 "FlwFromFuelToFrontWhls" 1 "FlwFromFuelToRearWhls" 0 "NoFlow"; +VAL_TABLE_ TrlrAidMsgTxt_D2_Rq 63 "Message63" 62 "Message62" 61 "Message61" 60 "Message60" 55 "Message55" 50 "Message50" 45 "Message45" 40 "Message40" 35 "Message35" 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ TrlrAidEnbl_D2_Stat 7 "NotUsed_1" 6 "TbaActiveExpertActive" 5 "TbaActiveExpertAvail" 4 "TbaOffTrgActive" 3 "TbaOffTrgSetup" 2 "TbaSetup" 1 "TbaActive" 0 "Inactive"; +VAL_TABLE_ RbaCta_D_Stat 7 "Faulty" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Invalid" 3 "Disabled" 2 "On" 1 "Trailer_Tow_Off" 0 "Off"; +VAL_TABLE_ NoRequest_Mode1_2_3 3 "Mode_3" 2 "Mode_2" 1 "Mode_1" 0 "NoRequest"; +VAL_TABLE_ RvltnMatchAllw_D_Stat 3 "RevolutionMatchDisabled" 2 "RevolutionMatchEnabled" 1 "ChangeWithDriveMode" 0 "NoSelection"; +VAL_TABLE_ BattTracCnnct_D_Cmd 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "WeldCheck" 3 "OkToDischarge" 2 "Closed" 1 "Precharge" 0 "Open"; +VAL_TABLE_ NotDiagnose_FailPass 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_TABLE_ Null_Off_UnavailFaulty 3 "Faulty" 2 "Unavailable" 1 "Off" 0 "Null"; +VAL_TABLE_ OffOnDisabledNotUsed 3 "NotUsed" 2 "Disabled" 1 "On" 0 "Off"; +VAL_TABLE_ OffGraphicTextBoth 3 "Both" 2 "Text" 1 "Graphic" 0 "Off"; +VAL_TABLE_ NoneInactiveActive_NotUsed 3 "NotUsed" 2 "Active" 1 "Inactive" 0 "None"; +VAL_TABLE_ Off_On_NotUsed 3 "NotUsed_2" 2 "NotUsed_1" 1 "On" 0 "Off"; +VAL_TABLE_ RbaSys_D_Stat 3 "Faulty" 2 "Available" 1 "Suspended" 0 "Disabled"; +VAL_TABLE_ BrkAppl_D_RqPt 3 "BrakesSlowRelease" 2 "BrakesFastRelease" 1 "BrakesEngage" 0 "NotActive"; +VAL_TABLE_ Mtr2State_D_ActlMntr 7 "Faulty" 6 "NoDataExists" 5 "NotUsed_1" 4 "ReadinessState" 3 "DeactivationState" 2 "PowerGeneration" 1 "PowerConsumption" 0 "Null"; +VAL_TABLE_ HybVehMde_D_ActlMntr 7 "Faulty" 6 "NoDataExists" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Fuel" 2 "HybridElectric" 1 "AllElectric" 0 "Null"; +VAL_TABLE_ ChrgStat_D_ActlMntr 7 "Faulty" 6 "NoDataExists" 5 "NotUsed" 4 "ChargingCompleted" 3 "NotCharging" 2 "ChargingInDrivingState" 1 "ChargingInParkingState" 0 "Null"; +VAL_TABLE_ Null_HiPower_Low_Med 3 "MediumPower" 2 "LowPower" 1 "HighPower" 0 "Null"; +VAL_TABLE_ Inactive_Enable_Disable_NotUsed 0 "Inactive" 2 "Disable" 1 "Enable"; +VAL_TABLE_ Inactive_OffOn_NotUsed 0 "Inactive" 1 "On" 2 "Off" 3 "NotUsed"; +VAL_TABLE_ Null_NotPressed_Faulty 3 "Faulty" 2 "Pressed" 1 "NotPressed" 0 "Null"; +VAL_TABLE_ TrailCtl_D_Stat 7 "Faulty" 6 "DescentOnly" 5 "EnabledDeny" 4 "StandbyOverThreshold" 3 "StandbyOverride" 2 "Active" 1 "EnabledDescent" 0 "Off"; +VAL_TABLE_ Faulty_3F 63 "Faulty"; +VAL_TABLE_ ChrgOvrdExitScrn_D_Rq 3 "NotUsed_1" 2 "Request_override" 1 "Do_not_request_override" 0 "Inactive"; +VAL_TABLE_ Quality_Data_Faulty 3 "OK" 2 "Not_Within_Specifications" 1 "Eval_In_Progress" 0 "Faulty"; +VAL_TABLE_ TrlrHitchYaw_D_Stat 15 "Faulty" 14 "NotUsed_4" 13 "NotUsed_3" 12 "NotUsed_2" 11 "NotUsed_1" 10 "FaultyYrsuConnection" 9 "FaultyYrsu" 8 "HiConfdLrndAngle" 7 "LowConfdLrndAngle" 6 "HiConfdAngleMem" 5 "LowConfdAngleMem" 4 "InitNoTadAngle" 3 "InitInputs" 2 "TadTrlrDataOutOfRange" 1 "TadNotWithinSpecification" 0 "NoConnectionWithYrsu"; +VAL_TABLE_ NoData_Faulty_FFFFFFFFFFFE_FF -1 "Faulty_FFFFFFFFFFFF" -2 "NoDataExists_FFFFFFFFFFFE"; +VAL_TABLE_ NoFault_Fault 1 "Fault" 0 "No_Fault"; +VAL_TABLE_ OtaTrg_D_Stat 3 "NotUsed_1" 2 "Accepted" 1 "NotAccepted" 0 "Null"; +VAL_TABLE_ EdmMsgTxt_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "OverallGoodScore" 10 "WorkOnCompliance" 9 "GoodCompliance" 8 "WorkOnGearShifting" 7 "GoodGearShifting" 6 "WorkOnEfficientSpeed" 5 "GoodEfficientSpeed" 4 "WorkOnDeceleration" 3 "GoodDeceleration" 2 "WorkOnAcceleration" 1 "GoodAcceleration" 0 "NoMessage"; +VAL_TABLE_ EdmLamp_D_Dsply 15 "NotUsed_7" 14 "NotUsed_6" 13 "NotUsed_5" 12 "NotUsed_4" 11 "NotUsed_3" 10 "NotUsed_2" 9 "NotUsed_1" 8 "CoastingEngineBrake" 7 "CoastingShiftToNeutral" 6 "FreewayJunction" 5 "Curve2" 4 "Curve1" 3 "SpeedLimit" 2 "Crossing" 1 "FreewayExit" 0 "NoRecommendation"; +VAL_TABLE_ AwdCnnct_D_Stat 3 "Connecting" 2 "Disconnecting" 1 "Connected" 0 "Disconnected"; +VAL_TABLE_ EngAirFiltMsgTxt_D_Rq 7 "NotUsed_2" 6 "NotUsed_1" 5 "EngineAirFilterMonitorFalt" 4 "ResetComplete" 3 "Clogged" 2 "ReplaceNow" 1 "ReplaceSoon" 0 "NoMessage"; +VAL_TABLE_ ElPwPoint_D_Rq 3 "On" 2 "Off2" 1 "Off1" 0 "Null"; +VAL_TABLE_ EngExhMdeQuiet_D2_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Track" 3 "Sport" 2 "Normal" 1 "Stealth" 0 "Null"; +VAL_TABLE_ RearDiffThrml_D_Stat 3 "NotUsed_1" 2 "AboveThermalLimit" 1 "ThermalLimit" 0 "Normal"; +VAL_TABLE_ NoInhibit_Inhibit 1 "Inhibit" 0 "NoInhibit"; +VAL_TABLE_ PersRecallSrc_D_Actl 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "MemorySwitch" 3 "RemoteStart" 2 "KeyFob" 1 "CenterStack" 0 "Null"; +VAL_TABLE_ BattTracChiller_D_Stat 3 "NotUsed" 2 "ChillerNotAvailable" 1 "ChillerBrieflyAvailable" 0 "ChillerAvailable"; +VAL_TABLE_ SelDrvMdeChassis2_D_Rq 31 "Faulty" 30 "NotUsed17" 29 "NotUsed16" 28 "NotUsed15" 27 "NotUsed14" 26 "NotUsed13" 25 "NotUsed12" 24 "NotUsed11" 23 "NotUsed10" 22 "NotUsed9" 21 "NotUsed8" 20 "NotUsed7" 19 "NotUsed6" 18 "NotUsed5" 17 "NotUsed4" 16 "NotUsed3" 15 "NotUsed2" 14 "RoughRoadMode" 13 "TrackMode" 12 "HighSpeedDesertMode" 11 "TowHaulMode" 10 "RockCrawlMode" 9 "SandMode" 8 "MudAndRutsMode" 7 "LowMuMode" 6 "ComfortAdaptiveMode" 5 "ComfortMode" 4 "SportAdaptiveMode" 3 "SportMode" 2 "EconomyMode" 1 "NormalAdaptiveMode" 0 "NormalMode"; +VAL_TABLE_ TrnFaltOpenClu_B_Stat 1 "MayOpenClutch" 0 "Normal"; +VAL_TABLE_ UrbanAreaDetct_D_Stat 3 "NotUsed_1" 2 "City" 1 "Subdivision" 0 "None"; +VAL_TABLE_ Closed_Open 1 "Open" 0 "Closed"; +VAL_TABLE_ AdbBrdrDist 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_TABLE_ TCU_ESN_D_Rq 3 "NotUsed" 2 "TCU_ESN_Request" 1 "NoRequest" 0 "Inactive"; +VAL_TABLE_ FactoryReset_Rq 1 "ResetFactoryDefaults" 0 "Inactive"; +VAL_TABLE_ TCU_Init_Actvtn_St 3 "NotUsed" 2 "InitialActivateDeny" 1 "InitialActivateAccept" 0 "Invalid"; +VAL_TABLE_ TCU_Final_Actvtn_St 3 "NotUsed" 2 "FinalActivateDeny" 1 "FinalActivateAccept" 0 "Invalid"; +VAL_TABLE_ WaitToStartLamp_D_Falt 3 "NotUsed" 2 "Wait_to_start_lamp_failed" 1 "Diagnosis_not_ready" 0 "Wait_to_start_lamp_OK"; +VAL_TABLE_ BattTracCoolLvl_D_Rq 7 "Faulty" 6 "NotUsed" 5 "ChillerCoolingBattFirst" 4 "ChillerCoolingCabinFirst" 3 "ForcedCoolingRadiator" 2 "OpportunisticCoolingRad" 1 "CoolantFlowBypassLine" 0 "Off"; +VAL_TABLE_ BattClntVlvOvrrd_D_Rq 3 "NotUsed" 2 "OverrideTbcvToChiller" 1 "OverrideTbcvToRadiator" 0 "NoOverrideToTbcvCLogic"; +VAL_TABLE_ NonMagnetic_Magnetic 1 "Magnetic" 0 "NonMagnetic"; +VAL_TABLE_ RideHghtMde_D_Stat 15 "Faulty" 14 "NotUsed_5" 13 "NotUsed_4" 12 "NotUsed_3" 11 "NotUsed_2" 10 "NotUsed_1" 9 "AdjUpAero" 8 "AdjUpOffRoad" 7 "AdjUpNormal" 6 "AdjDownKneel" 5 "AdjDownAero" 4 "AdjDownNormal" 3 "OffRoad" 2 "Kneel" 1 "Aero" 0 "Normal"; +VAL_TABLE_ AutoTowAllw_D_StatMnu 3 "TowHaulCommandedOn" 2 "AutoTowHaulEnabled" 1 "AutoTowHaulDisabled" 0 "NoSelection"; +VAL_TABLE_ SrpEventRight_D_Stat 3 "Faulty" 2 "Bump" 1 "Pothole" 0 "NoEvent"; +VAL_TABLE_ RearDiff_D_Stat 15 "NotUsed_7" 14 "NotUsed_6" 13 "NotUsed_5" 12 "NotUsed_4" 11 "NotUsed_3" 10 "NotUsed_2" 9 "NotUsed_1" 8 "TorqueReqNotHonored" 7 "MissingSignal" 6 "ModuleFault" 5 "HydroTempSensorFault" 4 "ClutchPressSensorFault" 3 "AccumPressSensorFault" 2 "ControlValveFault" 1 "MotorFault" 0 "Normal"; +VAL_TABLE_ NotAllowed_Allowed 1 "Allowed" 0 "NotAllowed"; +VAL_TABLE_ EngTrlrCnnct_D_Stat 3 "NotUsed_1" 2 "UnverifiedTrailer" 1 "HeavyTrailer" 0 "NoTrailer"; +VAL_TABLE_ Faulty_FFFF 65535 "Faulty"; +VAL_TABLE_ NoData_Faulty_3FFE_3FFF 16383 "Faulty" 16382 "NoDataExists"; +VAL_TABLE_ Faulty_3FFF 16383 "Faulty"; +VAL_TABLE_ NotExceeded_Exceeded 1 "Exceeded" 0 "NotExceeded"; +VAL_TABLE_ EmgcyCall_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "ManualEmergencyCall" 3 "AutoEmergencyCall" 2 "NoEvent" 1 "EmergencyCallNotSupported" 0 "Null"; +VAL_TABLE_ NotAsserted_Asserted 1 "Asserted" 0 "NotAsserted"; +VAL_TABLE_ AirSprngRate_D_Stat 3 "Faulty" 2 "Firm" 1 "Medium" 0 "Soft"; +VAL_TABLE_ AirSprngRate_D_Rq 3 "NoRequest" 2 "Firm" 1 "Medium" 0 "Soft"; +VAL_TABLE_ GearLvr_D_ActlDrv 15 "Fault" 14 "Unknown_Position" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Range6" 10 "Range5" 9 "Range4" 8 "Range3_M3_L3" 7 "Range2_M2_L2" 6 "Range1_M1_L1" 5 "Low" 4 "Sport_DriveSport_Mposition" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_TABLE_ ChrgrInPwMde_D_Actl 15 "NotUsed_9" 14 "NotUsed_8" 13 "NotUsed_7" 12 "NotUsed_6" 11 "NotUsed_5" 10 "NotUsed_4" 9 "NotUsed_3" 8 "EvseFault" 7 "EvseNotCompatible" 6 "IcCharging" 5 "DcCharging" 4 "AcDigital" 3 "AcBasic" 2 "DigitalCommDetected" 1 "EvsePaused" 0 "EvseNotDetected"; +VAL_TABLE_ ChrgCordLck_D_Stat 7 "Faulty" 6 "LockFail" 5 "UnlockFail" 4 "LockInProgress" 3 "UnlockInProgress" 2 "Lock" 1 "Unlock" 0 "Retain"; +VAL_TABLE_ LkaActvStats_D2_Req 7 "NotUsed" 6 "LkaIncrIntervRight" 5 "LkaSupprRight" 4 "LkaStandIntervRight" 3 "LkaSupprLeft" 2 "LkaStandIntervLeft" 1 "LkaIncrIntervLeft" 0 "LkaNoInterv"; +VAL_TABLE_ OffOnNoDataFaulty 3 "Faulty" 2 "No_Data_Exists" 1 "On" 0 "Off"; +VAL_TABLE_ NoMessage_Msg1_3 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ TrnRng_D_RqGsm 15 "Fault" 14 "UnknownPosition" 13 "Undefined_2" 12 "Undefined_1" 11 "_6" 10 "_5" 9 "_4" 8 "_3" 7 "_2" 6 "_1" 5 "Low" 4 "Sport" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_TABLE_ PrkBrkActv_D_RqGsmGear 3 "NotUsed" 2 "RequestParkBrakeEngage" 1 "NoRequest" 0 "Null"; +VAL_TABLE_ TrnPrkSys_D_Actl 15 "Faulty" 14 "NotUsed_5" 13 "NotUsed_4" 12 "NotUsed_3" 11 "NotUsed_2" 10 "NotUsed_1" 9 "FrequencyError" 8 "OutOfRangeHigh" 7 "OutOfRangeLow" 6 "Override" 5 "OutOfPark" 4 "TransitionCloseToOutOfPark" 3 "AtNoSpring" 2 "TransitionCloseToPark" 1 "Park" 0 "NotKnown"; +VAL_TABLE_ OKLowUnknownInvalid 3 "Invalid" 2 "Unknown" 1 "Low" 0 "OK"; +VAL_TABLE_ Dsp_RotAddrBtnEv_St 15 "NotUsed_1" 14 "Pos_7Steps" 13 "Pos_6Steps" 12 "Pos_5Steps" 11 "Pos_4Steps" 10 "Pos_3Steps" 9 "Pos_2Steps" 8 "Pos_1Step" 7 "NotPressed" 6 "Neg_1Steps" 5 "Neg_2Steps" 4 "Neg_3Steps" 3 "Neg_4Steps" 2 "Neg_5Steps" 1 "Neg_6Steps" 0 "Neg_7Steps"; +VAL_TABLE_ PrkAidDrvDir_D_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "BackwardNegative" 4 "ForwardNegative" 3 "BackwardPositive" 2 "ForwardPositive" 1 "NoMotion" 0 "DirectionNotKnown"; +VAL_TABLE_ EngExhMdeQuiet_D2_Stat 7 "Faulty" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Track" 3 "Sport" 2 "Normal" 1 "Stealth" 0 "Null"; +VAL_TABLE_ GasPrtc_D_RqDsply 7 "NotUsed_5" 6 "NotUsed_4" 5 "NotUsed_3" 4 "NotUsed_2" 3 "NotUsed_1" 2 "GpfOverLimit" 1 "GpfAtLimit" 0 "NormalOperation"; +VAL_TABLE_ TjaWarn_D_Rq 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "HardTakeOverLevel2" 2 "HardTakeOverLevel1" 1 "TrafficJamAssistCancel" 0 "NoWarning"; +VAL_TABLE_ Faulty_7FF 2047 "Faulty"; +VAL_TABLE_ Tja_D_Stat 7 "NotUsed_1" 6 "ActiveWarningRight" 5 "ActiveWarningLeft" 4 "ActiveInterventionRight" 3 "ActiveInterventionLeft" 2 "Active" 1 "Standby" 0 "Off"; +VAL_TABLE_ TjaMsgTxt_D_Dsply 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "TurnOnAdaptCruiseControl" 2 "TrafficJamAssistSelected" 1 "TrafficJamAssistUnavailabl" 0 "NoMessage"; +VAL_TABLE_ PwSrcULowMde_D_Actl 3 "NotUsed_1" 2 "ReverseBoost" 1 "ForwardBuck" 0 "Standby"; +VAL_TABLE_ ApaTrgtDist_D_Stat 15 "Step15" 14 "Step14" 13 "Step13" 12 "Step12" 11 "Step11" 10 "Step10" 9 "Step9" 8 "Step8" 7 "Step7" 6 "Step6" 5 "Step5" 4 "Step4" 3 "Step3" 2 "Step2" 1 "Step1" 0 "Off"; +VAL_TABLE_ Memory_2_SwPsngr_Stat 1 "Pressed" 0 "Null"; +VAL_TABLE_ Pers3Key_D_Stat 3 "NotUsed_1" 2 "KeyUnAssociated" 1 "KeyAssociated" 0 "Null"; +VAL_TABLE_ PwSrcULoMde_D_Rq 3 "NotUsed_1" 2 "ReverseBoost" 1 "ForwardBuck" 0 "Standby"; +VAL_TABLE_ AccMsgTxt_D2_Rq 15 "NotUsed_1" 14 "NCC_Enabled_Warning" 13 "IACC_TJA_Selected" 12 "ACC_TJA_Selected" 11 "IACC_Selected" 10 "Press_Brake_To_Hold" 9 "Only_Following_In_Low_Spd" 8 "TJA_Unavailable" 7 "Shift_Down" 6 "IACC_Unavailable" 5 "ACC_Selected" 4 "ACC_Overridden" 3 "Brake_Capacity_Warning" 2 "ACC_Cancelled" 1 "ACC_Unavailable" 0 "No_Text"; +VAL_TABLE_ WakeAlarm0_B_Typ 1 "CanAndEcuDriveCircuit" 0 "CanOnly"; +VAL_TABLE_ WakeAlarm0_D_Stat 3 "PublisherReset" 2 "Wake" 1 "AlarmRunning" 0 "AlarmOff"; +VAL_TABLE_ EmPrflNo_D_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Pers4" 3 "Pers3" 2 "Pers2" 1 "Pers1" 0 "Null"; +VAL_TABLE_ EmPrflKeyAssoc_D_Rq 7 "NotUsed_3" 6 "DisassociatePhone" 5 "EnterPhoneAssociation" 4 "OverwriteKey" 3 "DisassociateKey" 2 "ExitKeyAssociation" 1 "EnterKeyAssociation" 0 "Null"; +VAL_TABLE_ Em_D_Stat 3 "NotSupported" 2 "ProfilesOff" 1 "ProfilesOn" 0 "Null"; +VAL_TABLE_ EmPrflButtnAssoc_D_Rq 3 "NotUsed" 2 "ExitButtonAssociation" 1 "EnterButtonAssociation" 0 "Null"; +VAL_TABLE_ EmPrflNo_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Pers4" 3 "Pers3" 2 "Pers2" 1 "Pers1" 0 "Null"; +VAL_TABLE_ EmPrflKeyAssoc_D_Stat 7 "WrongDevice" 6 "KeyAssociateFailed" 5 "KeyAssociateSuccess" 4 "KeyAlreadyInUse" 3 "KeyDisassociated" 2 "KeyAssociationExited" 1 "KeyAssociationEntered" 0 "Null"; +VAL_TABLE_ EsaEnbl_D2_Rq 3 "NotConfigured" 2 "Enabled" 1 "Pending" 0 "Disabled"; +VAL_TABLE_ PersNo_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "NotDetermined" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_TABLE_ WiprFront_D_Stat2 15 "NO_DATA_EXISTS" 14 "STALLED" 13 "NotUsed" 12 "AUTO_ADJUST" 11 "COURTESYWIPE" 10 "AUTO_HIGH" 9 "AUTO_LOW" 8 "WASH" 7 "MIST_FLICK" 6 "MAN_HIGH" 5 "MAN_LOW" 4 "MAN_INT_ON" 3 "MAN_INT_OFF" 2 "OFF_MOVING" 1 "AUTO_OFF" 0 "OFF"; +VAL_TABLE_ TurnLghtSwtch_D_Stat2 3 "NotUsed" 2 "Right" 1 "Left" 0 "Off"; +VAL_TABLE_ CcButtnOnOffCnclPress3 1 "Pressed" 0 "Not pressed"; +VAL_TABLE_ SelDrvMdePos01_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_TABLE_ SelDrvMdePos01_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_TABLE_ ImmedFastMediumSlow 3 "Slow" 2 "Medium" 1 "Fast" 0 "Immediately"; +VAL_TABLE_ AdbHiBeamKeepOff_D_Rq 3 "KeepBothOff" 2 "KeepLeftOff" 1 "KeepRightOff" 0 "BothFreeRunning"; +VAL_TABLE_ AdbLampOnOff_D_Rq 3 "BothOn" 2 "LeftOnRightOff" 1 "RightOnLeftOff" 0 "BothOff"; +VAL_TABLE_ AdbMde1_D_Rq 3 "MarkerLightFlashing" 2 "MarkerLightConstant" 1 "Spot" 0 "None"; +VAL_TABLE_ Closed_Open_Active_Denied 3 "Denied" 2 "Active" 1 "Open" 0 "Closed"; +VAL_TABLE_ OffLowMedMax 3 "Maximum" 2 "Medium" 1 "Low" 0 "Off"; +VAL_TABLE_ IaccLamp_D_Rq 3 "NotUsed_2" 2 "NotUsed_1" 1 "DisplayIaccIcon" 0 "DoNotDisplayIaccIcon"; +VAL_TABLE_ Low_High_Confidence 1 "High_Confidence" 0 "Low_Confidence"; +VAL_TABLE_ Fault_Occupied_Empty_Un 3 "Unknown" 2 "Empty" 1 "Occupied" 0 "Fault"; +VAL_TABLE_ Off_On_Flash_Triggered 3 "Triggered" 2 "Flash" 1 "On" 0 "Off"; +VAL_TABLE_ IaccVLim_D_Rq 252 "NotUsed_2" 250 "LimitSpeed_250" 240 "LimitSpeed_240" 230 "LimitSpeed_230" 220 "LimitSpeed_220" 210 "LimitSpeed_210" 200 "LimitSpeed_200" 190 "LimitSpeed_190" 150 "LimitSpeed_150" 140 "LimitSpeed_140" 130 "LimitSpeed_130" 120 "LimitSpeed_120" 110 "LimitSpeed_110" 100 "LimitSpeed_100" 90 "LimitSpeed_90" 80 "LimitSpeed_80" 70 "LimitSpeed_70" 60 "LimitSpeed_60" 50 "LimitSpeed_50" 40 "LimitSpeed_40" 30 "LimitSpeed_30" 20 "LimtSpeed_20" 251 "NotUsed_1" 255 "Faulty" 254 "NoDataExists" 253 "NotUsed_3" 180 "LimitSpeed_180" 179 "LimitSpeed_179" 178 "LimitSpeed_178" 177 "LimitSpeed_177" 176 "LimitSpeed_176" 175 "LimitSpeed_175" 174 "LimitSpeed_174" 173 "LimitSpeed_173" 172 "LimitSpeed_172" 171 "LimitSpeed_171" 170 "LimitSpeed_170" 169 "LimitSpeed_169" 168 "LimitSpeed_168" 167 "LimitSpeed_167" 166 "LimitSpeed_166" 165 "LimitSpeed_165" 164 "LimitSpeed_164" 163 "LimitSpeed_163" 162 "LimitSpeed_162" 161 "LimitSpeed_161" 160 "LimitSpeed_160" 15 "LimitSpeed_15" 14 "LimitSpeed_14" 13 "LimitSpeed_13" 12 "LimitSpeed_12" 11 "LimitSpeed_11" 10 "LimitSpeed_10" 9 "LimitSpeed_9" 8 "LimitSpeed_8" 7 "LimitSpeed_7" 6 "LimitSpeed_6" 5 "LimitSpeed_5" 4 "LimitSpeed_4" 3 "LimitSpeed_3" 2 "LimitSpeed_2" 1 "LimitSpeed_1" 0 "LimitSpeed_0"; +VAL_TABLE_ IaccVLimUnit_D_Rq 3 "NoDataExists" 2 "Mph" 1 "Kph" 0 "Null"; +VAL_TABLE_ SelDrvMdeAwd_D_Rq 31 "Faulty" 30 "NotUsed_17" 29 "NotUsed_16" 28 "NotUsed_15" 27 "NotUsed_14" 26 "NotUsed_13" 25 "NotUsed_12" 24 "NotUsed_11" 23 "NotUsed_10" 22 "NotUsed_9" 21 "NotUsed_8" 20 "NotUsed_7" 19 "NotUsed_6" 18 "NotUsed_5" 17 "EvLaterChargeMode" 16 "EvNowMode" 15 "TrackMode" 14 "RoughRoadMode" 13 "NotAvailable" 12 "HighSpeedDesertMode_Baja" 11 "SportAdaptiveMode" 10 "RockCrawlMode" 9 "MudRutsMode" 8 "SandMode" 7 "EconomyMode" 6 "GrassGravelSnow" 5 "TowHaulMode" 4 "SportMode" 3 "Normal_4L" 2 "Normal_4A" 1 "Normal_2H" 0 "NormalMode"; +VAL_TABLE_ SelDrvMdeAwd_D_Stat 0 "NotAvailable" 1 "Available" 2 "TemporarilyNotAvailable" 3 "Faulty"; +VAL_TABLE_ SelDrvMdeAwd2_D_Stat 31 "Faulty" 30 "NotUsed_17" 29 "NotUsed_16" 28 "NotUsed_15" 27 "NotUsed_14" 26 "NotUsed_13" 25 "NotUsed_12" 24 "NotUsed_11" 23 "NotUsed_10" 22 "NotUsed_9" 21 "NotUsed_8" 20 "NotUsed_7" 19 "NotUsed_6" 18 "NotUsed_5" 17 "EvLaterChargeMode" 16 "EvNowMode" 15 "TrackMode" 14 "RoughRoadMode" 13 "NotAvailable" 12 "HighSpeedDesertMode_Baja" 11 "SportAdaptiveMode" 10 "RockCrawlMode" 9 "MudRutsMode" 8 "SandMode" 7 "EconomyMode" 6 "GrassGravelSnow" 5 "TowHaulMode" 4 "SportMode" 3 "Normal_4L" 2 "Normal_4A" 1 "Normal_2H" 0 "NormalMode"; +VAL_TABLE_ RearDiffLckMsg2_D_Rq 15 "NotUsed_3" 14 "NotUsed_2" 13 "NotUsed_1" 12 "ElsdReduced" 11 "LockingFeatureNotAvailable" 10 "EsldOff" 9 "ElsdRestored" 8 "ElsdOverheated" 7 "Locker_Disabled" 6 "Locker_Enabled" 5 "LockerSpeed5" 4 "LockerSpeed4" 3 "LockerSpeed3" 2 "LockerSpeed2" 1 "LockerSpeed1" 0 "NormalNoMessage "; +VAL_TABLE_ Counts_ZeroToSeven 4 "FourCounts" 3 "ThreeCounts" 2 "TwoCounts" 1 "OneCount" 0 "ZeroCounts" 7 "SevenOrMoreCounts" 6 "SixCounts" 5 "FiveCounts"; +VAL_TABLE_ HeadLghtHiPrmsn_D_Stat 3 "CancelAndSuppress" 2 "Cancel" 1 "Hold" 0 "AllowChange"; +VAL_TABLE_ SelDrvMdeSwtch 3 "Faulty" 2 "SwitchState2" 1 "SwitchState1" 0 "NotPressed"; +VAL_TABLE_ NotAvail_Temp_Faulty 3 "Faulty" 2 "TemporarilyNotAvailable" 1 "Available" 0 "NotAvailable"; +VAL_TABLE_ AwdDrvMde 7 "Faulty" 6 "NotAvailable" 5 "RockCrawl" 4 "Baja" 3 "MudAndSand" 2 "Weather" 1 "Sport" 0 "Normal"; +VAL_TABLE_ SelDrvMdePt_D_Rq 31 "Faulty" 30 "NotUsed15" 29 "NotUsed14" 28 "NotUsed13" 27 "NotUsed12" 26 "NotUsed11" 25 "NotUsed10" 24 "NotUsed9" 23 "NotUsed8" 22 "NotUsed7" 21 "NotUsed6" 20 "NotUsed5" 19 "NotUsed4" 18 "EvLaterChargerMode" 17 "EvNowMode" 16 "DragMode" 15 "HighSpeedDesertMode_Baja" 14 "SportAdaptiveMode" 13 "NotAvailable_13" 12 "NotAvailable_12" 11 "NotAvailable_11" 10 "NotAvailable_10" 9 "RockCrawlMode" 8 "MudRutsMode" 7 "SandMode" 6 "EconomyMode" 5 "GrassGravelSnow" 4 "NotAvailable_04" 3 "TowHaulMode" 2 "NotAvailable_02" 1 "SportMode" 0 "NormalMode"; +VAL_TABLE_ SelDrvMde_D_Stat 3 "NotUsed" 2 "DriveModeChangeRequest" 1 "DriveModeChangeSelection" 0 "NoDriveModeChangeRequest"; +VAL_TABLE_ NoMessage_Msg1_15 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ SelDrvMdeChassis_D_Rq 31 "Faulty" 30 "NotUsed17" 29 "NotUsed16" 28 "NotUsed15" 27 "NotUsed14" 26 "NotUsed13" 25 "NotUsed12" 24 "NotUsed11" 23 "NotUsed10" 22 "NotUsed9" 21 "NotUsed8" 20 "NotUsed7" 19 "NotUsed6" 18 "NotUsed5" 17 "NotUsed4" 16 "NotUsed3" 15 "NotUsed2" 14 "NotUsed1" 13 "TrackMode" 12 "HighSpeedDesertMode" 11 "TowHaulMode" 10 "RockCrawlMode" 9 "SandMode" 8 "MudAndRutsMode" 7 "LowMuMode" 6 "ComfortAdaptiveMode" 5 "ComfortMode" 4 "SportAdaptiveMode" 3 "SportMode" 2 "EconomyMode" 1 "NormalAdaptiveMode" 0 "NormalMode"; +VAL_TABLE_ NotAvailable_Available 1 "Available" 0 "NotAvailable"; +VAL_TABLE_ PwStep_D_Stat 3 "PositionNotKnown" 2 "StepsNotStowed" 1 "StepsStowed" 0 "Off"; +VAL_TABLE_ PwStep_D_DrvInhbt 3 "NotUsed" 2 "DriveInhibitMalfunction" 1 "DriveInhibited" 0 "DriveNotInhibited"; +VAL_TABLE_ NoMessage_Msg1_31 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ VehTrvlDir_D_Stat 7 "Faulty" 6 "NoDataExists" 5 "NotUsed2" 4 "NotUsed1" 3 "Reverse" 2 "LikelyReverse" 1 "Forward" 0 "LikelyForward"; +VAL_TABLE_ TrnRng_D_RqFap 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Backwards" 3 "Forwards" 2 "NoMotion" 1 "Immobilize" 0 "NoRequest"; +VAL_TABLE_ SelDrvMdeSusp_D_Stat 3 "Faulty" 2 "TemporarilyNotAvailable" 1 "Available" 0 "NotAvailable"; +VAL_TABLE_ OffOnNoReqFaulty 3 "Faulty" 2 "NoRequest" 1 "On" 0 "Off"; +VAL_TABLE_ LatCtl_D_Rq 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "InterventionRight" 2 "InterventionLeft" 1 "ContinuousPathFollowing" 0 "NoLateralControl"; +VAL_TABLE_ LatCtlSte_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Denied" 3 "RampOut" 2 "ContLatControlInProgress" 1 "Available" 0 "Unavailable"; +VAL_TABLE_ SlowMedFastImmed 3 "Immediately" 2 "Fast" 1 "Medium" 0 "Slow"; +VAL_TABLE_ ComfortablePreciseNotUsed 3 "NotUsed2" 2 "NotUsed1" 1 "Precise" 0 "Comfortable"; +VAL_TABLE_ LatCtlLim_D_Stat 3 "LimitWithDriverActive" 2 "LimitReached" 1 "LimitClose" 0 "LimitNotReached"; +VAL_TABLE_ FuelLvlWarn_D_ActlEng 7 "DteLevel5Lowest" 6 "DteLevel4" 5 "DteLevel3" 4 "DteLevel2NonMyKey" 3 "DteLevel1MyKey" 2 "VeryLow" 1 "Low" 0 "OK"; +VAL_TABLE_ AwdMde_D_RqDrv 7 "Faulty" 6 "NotUsed2" 5 "NoRequest" 4 "Neutral" 3 "FourByFourLow" 2 "FourByFourHigh" 1 "FourByFourAuto" 0 "FourByTwo"; +VAL_TABLE_ ApaBrk_D_Stat 3 "Denied" 2 "Active" 1 "Open" 0 "Closed"; +VAL_TABLE_ AdptDrvMdePt_D_Rq 7 "Faulty" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "Powertrain2Sport" 2 "Powertrain2Normal" 1 "Powertrain2Comfort" 0 "AdaptiveNotActive"; +VAL_TABLE_ AdptDrvMdeChassis_D_Rq 7 "Faulty" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "Chassis2Sport" 2 "Chassis2Normal" 1 "Chassis2Comfort" 0 "AdaptiveNotActive"; +VAL_TABLE_ PwStepMsgTxt_D_Rq 1 "DriveInhibited" 0 "NoMessage" 3 "NotUsed" 2 "Malfunction"; +VAL_TABLE_ OffLowMedHigh 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_TABLE_ NotDeterminedLowMedHigh 3 "High" 2 "Medium" 1 "Low" 0 "NotDetermined"; +VAL_TABLE_ CmbbObjClass_D_Stat 15 "NotUsed_9" 14 "NotUsed_8" 13 "NotUsed_7" 12 "NotUsed_6" 11 "NotUsed_5" 10 "NotUsed_4" 9 "NotUsed_3" 8 "NotUsed_2" 7 "NotUsed_1" 6 "Unclassified_Vehicle" 5 "Bicycle" 4 "Pedestrian" 3 "Truck" 2 "Motorcycle" 1 "Vehicle" 0 "Undetermined"; +VAL_TABLE_ HeadLghtHiCtrl_D_RqAhb 7 "NotUsed2" 6 "NotUsed1" 5 "Auto_HiBeam" 4 "Auto_LoBeam" 3 "Flash" 2 "Man_HiBeam" 1 "Man_LoBeam" 0 "Null"; +VAL_TABLE_ AhbHiBeam_D_Rq 3 "NotUsed" 2 "HighBeamRecommended" 1 "LowBeamRecommended" 0 "DeactivatedUnavailable"; +VAL_TABLE_ AhbStatGfhbFdbk_D_Actl 3 "GfhbHighBeamFullyOn" 2 "GfhbHighBeamPartlyOn" 1 "GfhbHighBeamOff" 0 "GfhbUnavailable"; +VAL_TABLE_ AhbcRampingV_D_Rq 3 "Slow" 2 "Medium" 1 "Fast" 0 "Immediately"; +VAL_TABLE_ ApaGearShif_D_RqDrv 7 "NotUSed2" 6 "NotUsed1" 5 "ShiftToP" 4 "ShiftToN" 3 "ShiftToD" 2 "ShiftToR" 1 "NoRequest" 0 "Null"; +VAL_TABLE_ ApaLongCtl_D_RqDrv 7 "NotUsed3" 6 "NotUsed2" 5 "ReleaseBrake" 4 "DriveBackward" 3 "DriveForward" 2 "Stop" 1 "NoRequest" 0 "Null"; +VAL_TABLE_ ApaActvSide2_D_Stat 3 "NoSide" 2 "Right" 1 "Left" 0 "Null"; +VAL_TABLE_ ApaScan_D_Stat 3 "ParkSlotReady" 2 "ParkSlotFound" 1 "NoParkSlot" 0 "Null"; +VAL_TABLE_ ApaSelSapp_D_Stat 3 "NotConfigured" 2 "NotSelectable" 1 "Selectable" 0 "Null"; +VAL_TABLE_ ApaSys_D_Stat 7 "Faulty" 6 "Finished" 5 "NotAccessible" 4 "ApaCancelled" 3 "Overspeed" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ ApaSteScanMde_D_Stat 3 "Steering" 2 "Scanning" 1 "NotScanning" 0 "Null"; +VAL_TABLE_ ApaAcsy_D_RqDrv 7 "CloseDoor" 6 "SelectSideRight" 5 "SelectSideLeft" 4 "CheckForObject" 3 "PressApaButton" 2 "SelectSide" 1 "NoRequest" 0 "Null"; +VAL_TABLE_ ApaSteWhl_D_RqDrv 3 "TakeControl" 2 "RemoveHands" 1 "NoRequest" 0 "Null"; +VAL_TABLE_ WiprFrontSwtch_D_Stat 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "PositionNotDetermined" 8 "High" 7 "Low" 6 "Position6" 5 "Position5" 4 "Position4" 3 "Position3" 2 "Position2" 1 "Position1" 0 "Off"; +VAL_TABLE_ Off_On_Unknown_Invalid 3 "Invalid" 2 "Unknown" 1 "On" 0 "Off"; +VAL_TABLE_ Unknown_7FFE_Invalid_7FFF 32767 "Invalid" 32766 "Unknown"; +VAL_TABLE_ OffOnNotUsedFaulty 3 "Faulty" 2 "NotUsed" 1 "On" 0 "Off"; +VAL_TABLE_ BrkBstrVac_D_Stat 3 "NotUsed" 2 "BoosterVacEstimator" 1 "BoosterVacSensor" 0 "NoBoosterVacuumMonitor"; +VAL_TABLE_ AwdMde_D_RqArb 7 "Faulty" 6 "NotUsed2" 5 "NoRequest" 4 "Neutral" 3 "FourByFourLow" 2 "FourByFourHigh" 1 "FourByFourAuto" 0 "FourByTwo"; +VAL_TABLE_ CtaAlrt2_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "AlertZone4" 3 "AlertZone3" 2 "AlertZone2" 1 "AlertZone1" 0 "Off"; +VAL_TABLE_ BttRightLeft_D_Stat 7 "NotUsed" 6 "Disabled" 5 "Off" 4 "OffTemp" 3 "NotConnected" 2 "Pending" 1 "Connected" 0 "NotDetermined"; +VAL_TABLE_ Null_NoRequest_Request 3 "NotUsed" 2 "Request" 1 "NoRequest" 0 "Null"; +VAL_TABLE_ PoliceIdlMde_D_Stat 15 "NotUsed_7" 14 "NotUsed_6" 13 "NotUsed_5" 12 "NotUsed_4" 11 "NotUsed_3" 10 "NotUsed_2" 9 "PepsActive" 8 "Decommissioned" 7 "ActiveFault" 6 "ArmFault" 5 "PrearmedFault" 4 "OffFault" 3 "Active" 2 "Arm" 1 "Prearmed" 0 "Off"; +VAL_TABLE_ TripComputerMetricImperial 0 "TripComputer_metric" 1 "TripComputer_imperial"; +VAL_TABLE_ GrdAsstAllw_D_DsplyPt 3 "NotUsed" 2 "On" 1 "Off" 0 "NoModeSelected"; +VAL_TABLE_ PrkBrkMsgTxt_D_Rq 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "No_Message"; +VAL_TABLE_ AutoHoldMsgTxt_D_Rq 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ AutoHoldMde_D_Ind 3 "Indication_3" 2 "Indication_2" 1 "Indication_1" 0 "Off"; +VAL_TABLE_ AutoRgenTxt_B_RqDsply 1 "AutExhFilterCleanOFF" 0 "AutExhFilterCleanON"; +VAL_TABLE_ TrnMsgTxt2_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "TransTooHot_LoudChime" 3 "PressBrake_LoudChime" 2 "PressBrake_SoftChime" 1 "PressBrake_NoChime" 0 "NoText_NoChime"; +VAL_TABLE_ TrnGearMsgTxt_D_Rq 15 "Message_15" 14 "Message_14" 13 "Message_13" 12 "Message_12" 11 "Message_11" 10 "Message_10" 9 "Message_9" 8 "Message_8" 7 "Message_7" 6 "Message_6" 5 "Message_5" 4 "Message_4" 3 "Message_3" 2 "Message_2" 1 "Message_1" 0 "NoMessage"; +VAL_TABLE_ ChargeProfIDPref_Rq 3 "NotUsed" 2 "Value" 1 "ChargeNow" 0 "Inactive"; +VAL_TABLE_ EngExhMdeQuiet_D_Stat 3 "Faulty" 2 "QuietExhaust" 1 "LoudExhaust" 0 "Null"; +VAL_TABLE_ ConsAvgTrip_No_Dsply 4095 "Faulty" 4094 "No_Data_Exists"; +VAL_TABLE_ ElTrip_L_Dsply 65535 "Fault" 65534 "No_Data_Exists"; +VAL_TABLE_ ElLongTerm_L_Dsply 16777215 "Fault" 16777214 "No_Data_Exists"; +VAL_TABLE_ GearSelLck_D_Rq 3 "PreventionBlocker" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_TABLE_ BrkPadMsgTxt_D_Rq 3 "Faulty" 2 "PadsOk" 1 "ReplacePads" 0 "Null"; +VAL_TABLE_ BrkAutoHold_D_Stat 7 "Faulty" 6 "NotUsed" 5 "Releasing" 4 "HeldSecondary" 3 "HeldSecure" 2 "Held" 1 "Inactive" 0 "Off"; +VAL_TABLE_ SuspDrvMde_D_Rq 7 "Faulty" 6 "NotUsed2" 5 "NotUsed1" 4 "Drag" 3 "Track" 2 "Snow_Wet" 1 "Sport" 0 "Normal"; +VAL_TABLE_ NotPressed_PressedNotUsed 3 "NotUsed2" 2 "NotUsed1" 1 "Pressed" 0 "Not_Pressed"; +VAL_TABLE_ WhlRearDual_D_Stat 3 "NotUsed" 2 "Dual" 1 "Single" 0 "NoDataExists"; +VAL_TABLE_ TracKeyMde_D_Stat 3 "NotUsed" 2 "NotActive" 1 "Active" 0 "ModeNotDetermined"; +VAL_TABLE_ HudMde_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Manual" 3 "Drag" 2 "RoadCourse" 1 "Tach" 0 "Off"; +VAL_TABLE_ TrnManShifGear_D_IndDrv 7 "Indicate_Reverse_Gear" 6 "Indicate_Gear6" 5 "Indicate_Gear5" 4 "Indicate_Gear4" 3 "Indicate_Gear3" 2 "Indicate_Gear2" 1 "Indicate_Gear1" 0 "No_Indication"; +VAL_TABLE_ TrnStrtStop_D_Stat 3 "NotUsed_2" 2 "NotUsed_1" 1 "LowTransmissionTemperature" 0 "NoDriverIndicationRequired"; +VAL_TABLE_ LsmcBrkDecel_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Denied" 3 "FaultDegraded" 2 "FaultExt" 1 "On" 0 "Off"; +VAL_TABLE_ StePinOffst_D_Stat 3 "FineOffset" 2 "CoarseOffset" 1 "StoredOffset" 0 "OffsetNotCalculated"; +VAL_TABLE_ NoMessage_Override_Faulty 3 "NotUsed" 2 "Faulty" 1 "Override" 0 "NoMessage"; +VAL_TABLE_ TrnIpcDsplyRng2_D_Actl 15 "No_Range_Selected" 14 "Range_14" 13 "Range_13" 12 "Range_12" 11 "Range_11" 10 "Range_10" 9 "Range_9" 8 "Range_8" 7 "Range_7" 6 "Range_6" 5 "Range_5" 4 "Range_4" 3 "Range_3" 2 "Range_2" 1 "Range_1" 0 "NotUsed"; +VAL_TABLE_ OffOn_RampUpDown 3 "Ramp_Down" 2 "Ramp_Up" 1 "On" 0 "Off"; +VAL_TABLE_ DieslMsgTxt_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "ReducedEnginePower" 0 "NoMessage"; +VAL_TABLE_ NoMessage_Msg1_7 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ TrnAltShifMde_D_Rdy 3 "Faulty" 2 "NotUsed" 1 "UnavailDueToDynCond" 0 "ModeChangeAvailable"; +VAL_TABLE_ LnchCtl 3 "NotUsed2" 2 "NotUsed1" 1 "LC_On" 0 "LC_Off"; +VAL_TABLE_ BrkLineLck_D_Rq 3 "Off" 2 "Engage" 1 "Initiate" 0 "NoRequest"; +VAL_TABLE_ BrkLineLck_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "NotAvailable" 3 "Off" 2 "Engaged" 1 "Initiated" 0 "Available"; +VAL_TABLE_ LnchCtlSys_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "On_LC_Unavailable_TC_On" 3 "On_LC_Unavailable" 2 "On_LC_Available" 1 "On_LC_Active" 0 "LC_OFF"; +VAL_TABLE_ ActvFrontSteLck_D_Stat 3 "Test_passed" 2 "Test_failed" 1 "Test_cannot_run" 0 "Test_incomplete"; +VAL_TABLE_ Rght_Lefthand_Traffic 1 "Left_Hand_Traffic" 0 "Right_Hand_Traffic"; +VAL_TABLE_ NotPressed_Pressed_Faulty 3 "Faulty" 2 "NotUsed" 1 "Pressed" 0 "Not_Pressed"; +VAL_TABLE_ TrlrTrgtAcquire_D_Rq 7 "NotUsed_2" 6 "NotUsed_1" 5 "ActivateRVCforTBA" 4 "CancelAcquisition" 3 "RetryAcquisition" 2 "AcquisitionSuccessful" 1 "StartAcquisition" 0 "Inactive"; +VAL_TABLE_ TrlrTrgtAcquire_D_Stat 7 "Faulty" 6 "NotUsed_2" 5 "NotUsed_1" 4 "RVCforTBA_Activated" 3 "Processing" 2 "TargetNotAcquired" 1 "TargetAcquired" 0 "Null"; +VAL_TABLE_ TrlrAidSetup_D_Rq 3 "ConfirmSetup" 2 "EndSetup" 1 "BeginSetup" 0 "Inactive"; +VAL_TABLE_ TrlBrkInitOut 3 "Heavy" 2 "Medium" 1 "Light" 0 "Null"; +VAL_TABLE_ IsaOffst_D_Stat 15 "Faulty" 14 "Null" 13 "Thirteen" 12 "Twelve" 11 "Eleven" 10 "Ten" 9 "Nine" 8 "Eight" 7 "Seven" 6 "Six" 5 "Five" 4 "Four" 3 "Three" 2 "Two" 1 "One" 0 "Zero"; +VAL_TABLE_ IsaVLimUnit_D_Rq 3 "NoDataExists" 2 "Mph" 1 "Kph" 0 "Null"; +VAL_TABLE_ ApaChime_D_Rq 7 "NotUsed2" 6 "NotUsed1" 5 "Warning_Chime" 4 "Finish_Chime" 3 "Stop_Now_Chime" 2 "Spot_Ready_Chime" 1 "Spot_Found_Chime" 0 "No_Chime"; +VAL_TABLE_ SlMde_D_RqDsply 3 "NotUsed" 2 "ManualSpeed_LimiterSymbol" 1 "AutoSpeed_LimiterSymbol" 0 "NoSpeed_LimiterSymbol"; +VAL_TABLE_ SlMde_D_Rq 3 "IsaNotConfigured" 2 "Manual_Mode" 1 "Auto_Mode" 0 "Null"; +VAL_TABLE_ NotSupported_Supported 1 "Supported" 0 "NotSupported"; +VAL_TABLE_ OffOn_NotUsed_NoData 3 "No_Data_Present" 2 "NotUsed" 1 "On" 0 "Off"; +VAL_TABLE_ Faulty_FF 255 "Faulty"; +VAL_TABLE_ BrkDrvMde_D_Rq 7 "Faulty" 6 "RockCrawl" 5 "Baja" 4 "DragOrMudAndSand" 3 "Track" 2 "Snow_Wet" 1 "Sport" 0 "Normal"; +VAL_TABLE_ TrnIpcDsplyRng_D_Stat 3 "NotUsed" 2 "Flash" 1 "On" 0 "Blank_No_Display"; +VAL_TABLE_ NoYesNoDataFaulty 3 "Faulty" 2 "NoDataExists" 1 "Yes" 0 "No"; +VAL_TABLE_ SidePrkSnsR4_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_TABLE_ TsrVlPrmntMsgTxt_D_Rq 3 "NotUsed" 2 "ShowPermanentlyWithSupp" 1 "ShowPermanentlyWithoutSupp" 0 "DoNotShowSignPermanent"; +VAL_TABLE_ TsrVl1RstrcMsgTxt2_D_Rq 7 "NotUsed" 6 "Time" 5 "Trailer" 4 "Snow" 3 "RainWet" 2 "NoRecognizableRestrictn" 1 "NoSpeedLimitRestrictn" 0 "Null"; +VAL_TABLE_ PtDrvMde_D_Rq 15 "Faulty" 14 "NotUsed11" 13 "NotUsed10" 12 "NotUsed9" 11 "NotUsed8" 10 "NotUsed7" 9 "NotUsed6" 8 "NotUsed5" 7 "Drag" 6 "Rock" 5 "Baja" 4 "Sand" 3 "TowHaulGradeAssist" 2 "SnowWet" 1 "Sport" 0 "Normal"; +VAL_TABLE_ SteEffort_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "SpecialMode_2" 3 "SpecialMode_1" 2 "Comfort" 1 "Sport" 0 "Normal"; +VAL_TABLE_ TsrOvtkMsgTxt2_D_Rq 15 "NotUsed5" 14 "NotUsed4" 13 "NotUsed3" 12 "NotUsed2" 11 "NotUsed1" 10 "LimForTrucksCancelled" 9 "LimForTrucksWoQlfdRstrc" 8 "LimForTrucksWithoutRstrc" 7 "LimAllCancelled" 6 "LimAllWithRstrcTime" 5 "LimAllWithRstrcTrailer" 4 "LimAllWithRstrcSnow" 3 "LimAllWithRstrcRain" 2 "LimAllWithoutQlfdRstrc" 1 "LimAllWithoutRestriction" 0 "OvertakingAllowed"; +VAL_TABLE_ TrlrAnOffstDir 3 "NotUSed" 2 "Right" 1 "Left_or_Center" 0 "Null"; +VAL_TABLE_ Null_Off_On 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ TrlrBrkMde_D_Rq 1 "ElectricOverHydraulic" 0 "Electric"; +VAL_TABLE_ TrlrAidSetup_D_Stat 7 "Faulty" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "EnterParameters" 2 "EndSetup" 1 "BeginSetup" 0 "Null"; +VAL_TABLE_ TrlrAidMsgTxt_D_Rq 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ Invalid_7F 127 "Invalid"; +VAL_TABLE_ Faulty_1FFF 8191 "Faulty"; +VAL_TABLE_ VehStab_D_Stat 15 "Faulty" 14 "No_Data_Exists" 13 "NotUsed6" 12 "NotUsed5" 11 "NotUsed4" 10 "NotUsed3" 9 "NotUsed2" 8 "NotUsed1" 7 "High_SSRA_no_OS" 6 "Straight" 5 "Post_Oversteer" 4 "Post_Transition" 3 "Countersteer" 2 "Understeer" 1 "Oversteer" 0 "Linear"; +VAL_TABLE_ NoData_Faulty_1FF_1FE 511 "Faulty" 510 "NoDataExists"; +VAL_TABLE_ TrlrAidEnbl_D_Rq 3 "NotAvailable" 2 "DeactivateTba" 1 "ActivateTba" 0 "Inactive"; +VAL_TABLE_ FohEng_D_Rq 3 "AutoEnable_ParkEnable" 2 "AutoDisable_ParkEnable" 1 "AutoEnable_ParkDisable" 0 "Disable_Stop"; +VAL_TABLE_ Null_Hi_NotUsed_Low 3 "Low" 2 "Not_Used" 1 "High" 0 "Null"; +VAL_TABLE_ Current_Color 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "NotUsed3" 10 "NotUsed2" 9 "NotUsed1" 8 "Null" 7 "Color7" 6 "Color6" 5 "Color5" 4 "Color4" 3 "Color3" 2 "Color2" 1 "Color1" 0 "Off"; +VAL_TABLE_ Blended_Color 15 "NotUsed10" 14 "NotUsed9" 13 "NotUsed8" 12 "NotUsed7" 11 "NotUsed6" 10 "NotUsed5" 9 "NotUsed4" 8 "NotUsed3" 7 "NotUsed2" 6 "NotUsed1" 5 "_5" 4 "_4" 3 "_3" 2 "_2" 1 "_1" 0 "Null"; +VAL_TABLE_ OffOn_Null_NotUsed 3 "NotUsed" 2 "Null" 1 "On" 0 "Off"; +VAL_TABLE_ DieslPrtc2_D_RqDsply 15 "NotUsed4" 14 "NotUsed3" 13 "NotUsed2" 12 "NotUsed1" 11 "OCR_ExhFilterClean_Stopped" 10 "OCR_ExhFilterCleaned" 9 "RgnOff_AtLimit" 8 "RgnOff_Overloaded" 7 "RgnOff_Loaded" 6 "Exhaust_Filter_Full" 5 "DPF_Overlimit" 4 "DPF_AtLimit" 3 "ExhFilter_Drive_Completed" 2 "Cleaning_Exhaust_Filter" 1 "DPF_Overloaded" 0 "DPF_Normal_Operation"; +VAL_TABLE_ Null_Pers1_4_Vehicle 7 "Unused_2" 6 "Unused_1" 5 "Vehicle" 4 "PERS_4" 3 "PERS_3" 2 "PERS_2" 1 "PERS_1" 0 "Null"; +VAL_TABLE_ PrkLckCtlEnbl_D_RqIpc 3 "Rq_Towing" 2 "Rq_Enable" 1 "Rq_Disable" 0 "Null"; +VAL_TABLE_ PrkLckCtlUnlck_D_Stat 3 "Trans_And_Steer_Unlckd" 2 "Steering_Unlckd" 1 "Transmission_Unlckd" 0 "Null"; +VAL_TABLE_ VehKeyActv_D_Stat 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "NotUsed3" 10 "NotUsed2" 9 "NotUsed1" 8 "Key8Active" 7 "Key7Active" 6 "Key6Active" 5 "Key5Active" 4 "Key4Active" 3 "Key3Active" 2 "Key2Active" 1 "Key1Active" 0 "NoKeyActive"; +VAL_TABLE_ VehLckInd_D_Rq 3 "NotUsed" 2 "On_Day" 1 "On_Night" 0 "Off"; +VAL_TABLE_ PrkBrkDynmc_D_Allw 3 "NotUsed" 2 "EPB_ECD_NotPossible" 1 "EPB_ECD_Possible" 0 "Used_at_Start_Up"; +VAL_TABLE_ TowBarMsgTxt_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "TowBar_Ext_No_Trlr" 3 "Error_Dealer_Fix" 2 "Start_Engine_Swivel" 1 "Check_Tow_Bar" 0 "Null"; +VAL_TABLE_ PrkBrk_D_Stat 7 "Gen_Faults_or_Maint_Mode" 6 "ECD_by_Brake_ECU_Active" 5 "EPB_Limphome_Active" 4 "Rear_Caliper_Open" 3 "RWU_by_EPB_Active" 2 "Rear_Caliper_Transition" 1 "Rear_Caliper_Closed" 0 "Not_Supported"; +VAL_TABLE_ NoData_Faulty_3E_3F 63 "Faulty" 62 "NoDataExists"; +VAL_TABLE_ Unknown_Invalid_1FE_1FF 511 "Invalid" 510 "Unknown"; +VAL_TABLE_ Invalid_0x0 0 "Invalid"; +VAL_TABLE_ Unknown_Invalid_3E_3F 63 "Invalid" 62 "Unknown"; +VAL_TABLE_ Faulty_1FF 511 "Faulty"; +VAL_TABLE_ NoData_Faulty_1FFF_1FFE 8191 "Faulty" 8190 "NoDataExists"; +VAL_TABLE_ Null_Off_On_Faulty 3 "Faulty" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ EngOilSrvcMsgTxt_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "ResetComplete" 3 "ResetInProgress" 2 "ChangeOilNow" 1 "ChangeOilSoon" 0 "NoText"; +VAL_TABLE_ AirSusp_D_RqDrv 3 "NotUsed" 2 "On" 1 "Off" 0 "NoModeSelected"; +VAL_TABLE_ AwdSys_D_Stat 3 "Faulty" 2 "NotUsed" 1 "_4x4_L_H_Active" 0 "_4x4_L_H_Inactive"; +VAL_TABLE_ EmotiveType_D_Dsply 3 "EmotiveDisplay_3" 2 "EmotiveDisplay_2" 1 "EmotiveDisplay_1" 0 "Null"; +VAL_TABLE_ AutoRgen_D_Rq 3 "NotUsed" 2 "AutExhFilterCleanOFF" 1 "AutExhFilterCleanON" 0 "No_Mode_Selected"; +VAL_TABLE_ TrnSrvcRqd_B_Rq 1 "On" 0 "Off"; +VAL_TABLE_ PlgOvrrdStrt_D_Cmd 3 "NotUsed" 2 "Override_Plug_Status" 1 "Dont_Override_Plug_Status" 0 "Null_State"; +VAL_TABLE_ immoSecureIdleMode 3 "NotUsed2" 2 "NotUsed1" 1 "Active" 0 "Inactive"; +VAL_TABLE_ SteWhlOffstRq_D_Stat 3 "Faulty" 2 "NoDataExists" 1 "Allow_External_Angle_Req" 0 "Deny_External_Angle_Req"; +VAL_TABLE_ SteMdule_D_Stat 7 "NotUsed" 6 "EPAS_Failure3" 5 "EPAS_Failure2" 4 "System_Failure" 3 "EPAS_Shutdown" 2 "Normal_Op_Full_Assist" 1 "Normal_Op_Limited_Assist" 0 "EPAS_Initialization"; +VAL_TABLE_ Faulty_FFF 4095 "Faulty"; +VAL_TABLE_ Faulty_3FF 1023 "Faulty"; +VAL_TABLE_ NoData_Faulty_FE_FF 255 "Faulty" 254 "NoDataExists"; +VAL_TABLE_ ChkPlgtoStrt_D_Dsply 3 "NotUsed" 2 "Is_VehicleUnplugged_Prompt" 1 "Check_Plug_to_Start" 0 "No_Message_Display"; +VAL_TABLE_ PwrFlowTxt_D_Dsply 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "Disply_Rgen_Chrg_Txt" 10 "Disp_Fast_Charge_Txt" 9 "Disp_Fast_Charge_Cmplt_Txt" 8 "Disp_Charge_Cmplt_Txt" 7 "Disp_Remote_Start_Txt" 6 "Disp_Eng_Drv_Txt" 5 "Disp_Elec_Drv_Txt" 4 "Disp_Idle_with_Chrg_Txt" 3 "Disp_Idle_Txt" 2 "Disp_Charg_HV_Batt_Txt" 1 "Disp_Hyb_Drive_Txt" 0 "No_Text"; +VAL_TABLE_ EngOnMsg_D_Dsply 14 "_0xE_to_1F_NotUsed" 12 "Battery_Temperature" 11 "Hill_Decent_Control" 10 "Fuel_Maintenance" 9 "Oil_Maintenance" 8 "Normal_Operation" 7 "Low_Gear" 6 "Batt_Charging" 5 "Engine_Cold" 4 "Neutral_Gear" 3 "Heater_Setting" 2 "High_Speed" 1 "Acceleration" 0 "No_Display" 13 "Drive_Mode_Selection"; +VAL_TABLE_ PtDataKeyId_D_Stat 15 "NotUsed5" 14 "NotUsed4" 13 "NotUsed3" 12 "NotUsed2" 11 "NotUsed1" 10 "Tot_Veh_NUT" 9 "Cust_4_NUT" 8 "Cust_3_NUT" 7 "Cust_2_NUT" 6 "Cust_1_NUT" 5 "Tot_Veh_Stat" 4 "Cust_4_Stat" 3 "Cust_3_Stat" 2 "Cust_2_Stat" 1 "Cust_1_Stat" 0 "Null"; +VAL_TABLE_ ChrgStat_D_Dsply 7 "NotUsed" 6 "Complete" 5 "Scheduled" 4 "In_Progress" 3 "Fault_Outside_Car" 2 "Fault_Inside_Car" 1 "Fault_Unknown_Location" 0 "Not_Ready"; +VAL_TABLE_ TrnLvrV_D_Rq 3 "Full_Speed" 2 "Aggressive" 1 "Normal" 0 "Quiet"; +VAL_TABLE_ EngStrtStop_B_SrcOil 1 "Eng_start_stop_for_oilmnt" 0 "Not_Requested"; +VAL_TABLE_ FuelMaintMde_D_Rq 3 "Feature_Not_Present" 2 "Fuel_Maint_Req_Now" 1 "Fuel_Maint_Req_Soon" 0 "NoRequest"; +VAL_TABLE_ FuelMaintMde_D_Dsply 3 "Feature_Not_Present" 2 "In_Fuel_Maint_Mode" 1 "Close_to_Fuel_Maint" 0 "OK"; +VAL_TABLE_ DynoMde_B_Cmd 1 "Two_Wheel_Dyno" 0 "Normal_Operation"; +VAL_TABLE_ HvacPrecondRecirc_D_Rq 3 "Last_User_Setting" 2 "Auto" 1 "Recirc" 0 "Outside"; +VAL_TABLE_ HvacPrecondAC_D_Rq 3 "Last_User_Setting" 2 "Auto" 1 "On" 0 "Off"; +VAL_TABLE_ HybMdeStat_D_Dsply 7 "NotUsed2" 6 "EV_Charge" 5 "EV_Override" 4 "Forced_EV_Mode" 3 "Forced_Charge_Sustain_Mode" 2 "Auto_Charge_Sustain_Mode" 1 "Auto_Charge_Deplete_Mode" 0 "Null_State"; +VAL_TABLE_ PwFlowPlgBatt_D_Dsply 3 "NotUsed" 2 "Flow_from_Plug_to_Batt" 1 "Flow_from_Batt_to_Plug" 0 "No_Flow"; +VAL_TABLE_ PwFlowEngMtr_D_Dsply 3 "NotUsed" 2 "Flow_from_Eng_to_Mtr" 1 "Flow_from_Mtr_to_Eng" 0 "No_Flow"; +VAL_TABLE_ PwFlowEngFuel_D_Dsply 3 "NotUsed" 2 "Flow_from_Eng_to_Fuel" 1 "Flow_from_Fuel_to_Eng" 0 "No_Flow"; +VAL_TABLE_ PwFlowMtrDrv_D_Dsply 3 "NotUsed" 2 "Flow_from_Mtr_to_Axle" 1 "Flow_from_Axle_to_Mtr" 0 "No_FLow"; +VAL_TABLE_ PwFlowEngDrv_D_Dsply 3 "NotUsed" 2 "Flow_from_Eng_to_Axle" 1 "Flow_from_Axle_to_Eng" 0 "No_Flow"; +VAL_TABLE_ PwFlowBattMtr_D_Dsply 3 "NotUsed" 2 "Flow_from_Batt_to_Mtr" 1 "Flow_from_Mtr_to_Batt" 0 "No_Flow"; +VAL_TABLE_ Null_Override_Invalid 3 "NotUsed" 2 "Invalid" 1 "Override" 0 "Null"; +VAL_TABLE_ HybMdeMsgTxt_D_Rq 7 "NotUsed2" 6 "NotUsed1" 5 "EV_Not_Avail_Message" 4 "EV_Mode_Message" 3 "Delayed_Discharge_Message" 2 "Override_Available_Message" 1 "AutoMode_Message" 0 "Null_NoMessage_Request"; +VAL_TABLE_ HybMdeLimMsgTxt_D_Rq 3 "Limited_Req_Full_Defrost" 2 "Limited_Climate_Defrost" 1 "Limited_System_Performance" 0 "Null"; +VAL_TABLE_ CenterStackRing_D_Actl 3 "LimitedOn" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ NoData_Faulty_FFFE_FFFF 65535 "Faulty" 65534 "NoDataExists"; +VAL_TABLE_ NoData_Faulty_FFE_FFF 4095 "Faulty" 4094 "NoDataExists"; +VAL_TABLE_ NoData_Faulty_7FFE_7FFF 32767 "Faulty" 32766 "NoDataExists"; +VAL_TABLE_ NoData_Faulty_3FE_3FF 1023 "Faulty" 1022 "NoDataExists"; +VAL_TABLE_ ReFuelSysStat_D_Dsply 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Refuel_Err" 3 "Close_Fuel_Door" 2 "Refuel_Ready" 1 "Wait_To_Fuel" 0 "Null"; +VAL_TABLE_ OffOn_NotUsed 3 "NotUsed2" 2 "NotUsed1" 1 "On" 0 "Off"; +VAL_TABLE_ DrQltyDrv_D_StatGsm 7 "Faulty" 6 "NoDataExists" 5 "NotUsed2" 4 "NotUsed1" 3 "ClosedDegraded" 2 "OpenDegraded" 1 "ClosedOkay" 0 "OpenOkay"; +VAL_TABLE_ ChrgrInPwType_D_Actl 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "DC_Fast_Charging" 2 "AC_Level2_240v" 1 "AC_Level1_120v" 0 "EVSE_Not_Detected"; +VAL_TABLE_ ChrgCrdLck_D_Falt 3 "NotUsed" 2 "HardwareFault" 1 "CsiFault" 0 "NoFault"; +VAL_TABLE_ ChrgStat_D2_Dsply 15 "NotUsed_2" 14 "NotUsed_1" 13 "ChargeTargetReached" 12 "DriveConditioning" 11 "CabinPreconditioning" 10 "ChargingSystemMaintain" 9 "ChargingInductive" 8 "ChargingDCFastChange" 7 "ChargingAC" 6 "ChargeScheduled" 5 "EvsePaused" 4 "EvseNotDetected" 3 "EvseNotCompatible" 2 "FaultOutsideCar" 1 "FaultInsideCar" 0 "NotReady"; +VAL_TABLE_ EngMdeMsgTxt_D_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Charge" 3 "GlowingCharge" 2 "Hybrid" 1 "Ev" 0 "NoMessage"; +VAL_TABLE_ BattRgenLoStat_D_Qlty 3 "OK" 2 "Not_Within_Spec" 1 "Eval_In_Progress" 0 "Faulty"; +VAL_TABLE_ OpenClosedRetainDisable 3 "Disable" 2 "Retain" 1 "Closed" 0 "Open"; +VAL_TABLE_ OpenClosedStuckOpenClosed 3 "StuckClosed" 2 "StuckOpen" 1 "Closed" 0 "Open"; +VAL_TABLE_ NoData_Faulty_7FE_7FF 2047 "Faulty" 2046 "NoDataExists"; +VAL_TABLE_ DrTgateChime2_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Long_Repeated" 3 "Fast" 2 "Short" 1 "Long" 0 "Off"; +VAL_TABLE_ EngIdlShutDwnTxt_D_Rq 3 "NotUsed" 2 "EngineShutdownOnPrevDrive" 1 "FeatureDisabledDueToFault" 0 "NoMessage"; +VAL_TABLE_ DrvPerfMde 3 "Sport" 2 "Normal" 1 "NotUsed" 0 "NoModeSelected"; +VAL_TABLE_ NoData_Fault_1FF_1FE 511 "Fault" 510 "NoDataExists"; +VAL_TABLE_ NoData_Fault_FFE_FFF 4095 "Fault" 4094 "NoDataExists"; +VAL_TABLE_ WeekdayEndHR_St 31 "Invalid" 30 "Unknown" 29 "Reserved_29" 28 "Reserved_28" 27 "Reserved_27" 26 "Reserved_26" 25 "Reserved_25" 24 "Reserved_24"; +VAL_TABLE_ WeekdayEndMin_St 63 "Faulty" 62 "No_data_exists" 61 "Reserverd" 60 "Reserverd"; +VAL_TABLE_ WeekdayStartHR_St 31 "Invalid" 30 "Unknown" 29 "Reserved_29" 28 "Reserved_28" 27 "Reserved_27" 26 "Reserved_26" 25 "Reserved_25" 24 "Reserved_24"; +VAL_TABLE_ WeekdayStartMin_St 63 "Faulty" 62 "No_data_exists" 61 "Reserverd" 60 "Reserverd"; +VAL_TABLE_ EngIdlShutDown_D_Stat 3 "Not_used" 2 "Engine_Shutdown" 1 "Initiated_Countdown" 0 "Normal_Operation"; +VAL_TABLE_ StopStrtDrvMde_D_Indic 3 "NotUsed" 2 "StartStop_IndirectDeselect" 1 "StopStart_Deselected" 0 "StopStart_Selected"; +VAL_TABLE_ StopStrtDrvMde_D_RqMnu 3 "NotUsed2" 2 "NotUsed1" 1 "StopStart_Deselected" 0 "StopStart_Selected"; +VAL_TABLE_ StopStrtStdby_D_Indic 6 "NotUsed2" 5 "Telltale_Struck_Out" 4 "Telltale_Flashing_Amber" 3 "Telltale_On_Amber" 2 "Telltale_Flashing_Green" 1 "Telltale_On_Green" 0 "Telltale_Off" 7 "NotUsed3"; +VAL_TABLE_ Quality_Faulty 3 "OK" 2 "Degraded" 1 "No_Data_Exists" 0 "Faulty"; +VAL_TABLE_ TrnDtpCmd_D_Actl 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "Relatch" 3 "Deploy" 2 "Self_Test" 1 "No_Command" 0 "NotUsed1"; +VAL_TABLE_ TrnGsmNtmState_D_Actl 3 "Faulty" 2 "Neutral_Tow_Mode" 1 "Car_Wash_Mode" 0 "None"; +VAL_TABLE_ TrnTrcmPwmSig_D_Actl 15 "Faulty" 14 "NoDataExists" 13 "NotUsed5" 12 "NotUsed4" 11 "NotUsed3" 10 "NotUsed2" 9 "NotUsed1" 8 "Default_To_Park" 7 "Neutral_Tow" 6 "Car_Wash_Mode" 5 "Manual" 4 "Drive" 3 "Neutral" 2 "Reverse" 1 "Park" 0 "No_Gear"; +VAL_TABLE_ RgenBrkDynoMde_B_Actl 1 "TwoWheelDyno" 0 "NormalOperation"; +VAL_TABLE_ Fault_3FFF 16383 "Fault"; +VAL_TABLE_ CtaInnr_D_Stat 3 "Reporting" 2 "Not_Reporting" 1 "System_Standby" 0 "Initialization"; +VAL_TABLE_ PrkBrkActv_D_RqTrnGear 3 "NotUsed2" 2 "RequestParkBrakeEngage" 1 "NoRequest" 0 "NotUsed1"; +VAL_TABLE_ NoRequest_Request 1 "Request" 0 "NoRequest"; +VAL_TABLE_ Fault_FFF_NoData 4094 "NoDataExists" 4095 "Fault"; +VAL_TABLE_ Fault_3FF_NoData 1022 "NoDataExists" 1023 "Fault"; +VAL_TABLE_ Foh_D_Stat 7 "Unused3" 6 "Unused2" 5 "Unused1" 4 "Stopping" 3 "Running" 2 "Starting" 1 "Prestart" 0 "Off"; +VAL_TABLE_ OffOnNoDataUnused 3 "Unused" 2 "NoDataExists" 1 "On" 0 "Off"; +VAL_TABLE_ FohFalt_D_Stat 15 "NotUsed4" 14 "NotUsed3" 13 "NotUsed2" 12 "NotUsed1" 11 "FuelTypeDoesNotMatchFOH" 10 "Lifecycle_ModeNotSet" 9 "AuxElectricCoolantPumpInop" 8 "TimeDelayAvoidExcessCycl" 7 "Fuel_Level_OutofRange" 6 "External_Fault" 5 "Internal_Fault" 4 "Voltage_limitation" 3 "Impact_Event" 2 "CoolantTemp_OutofRange" 1 "AmbientTemp_OutofRange" 0 "No_Disable"; +VAL_TABLE_ FohRqRun_B_Rq 1 "SubmitRequest_toRun" 0 "DoesNotSubmitRequest_toRun"; +VAL_TABLE_ OKLowVeryLow 3 "NotUsed" 2 "VeryLow" 1 "Low" 0 "OK"; +VAL_TABLE_ Fault_1FF 511 "Fault"; +VAL_TABLE_ SteWhlHeat 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "Reserved_3" 8 "Reserved_2" 7 "Reserved_1" 6 "Level_3_Heating" 5 "Level_3_Heating_LS" 4 "Level_2_Heating" 3 "Level_2_Heating_LS" 2 "Level_1_Heating" 1 "Level_1_Heating_LS" 0 "Off"; +VAL_TABLE_ OffOnUnusedFault 3 "Fault" 2 "Unused" 1 "On" 0 "Off"; +VAL_TABLE_ NullKphMph 3 "NoDataExists" 2 "Mph" 1 "Kph" 0 "Null"; +VAL_TABLE_ TsrVLim1MsgTxt_D_Rq 255 "NoLimit" 254 "NotUsed2" 253 "NotUsed1" 252 "NotToBeDisplayed" 251 "LimitCancelled" 31 "1F_FA_Message31_250" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "Null"; +VAL_TABLE_ TsrVl1RstrcMsgTxt_D_Rq 3 "NotUsed" 2 "NoRecognizableRestriction" 1 "NoSpeedLimitRestriction" 0 "Null"; +VAL_TABLE_ TsrMsgTxt_D_Rq 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "RecgnzdSignNotUsblForDsply" 8 "LimitedSystemPerformance" 7 "OffRoad" 6 "RegionNotSupported" 5 "CountryNotSupported" 4 "WrngNavDatIncompDatCarrier" 3 "NoNavDataAvailable" 2 "NoNavAvailableSwitchedOff" 1 "NoInformationAllOK" 0 "Null"; +VAL_TABLE_ TsrOvtkTypeMsgTxt_D_Rq 3 "NotUsed" 2 "Explicit" 1 "Implicit" 0 "Null"; +VAL_TABLE_ TsrOvtkStatMsgTxt_D_Rq 3 "LimitOutdated" 2 "LimitReiable" 1 "LimitChanged" 0 "Null"; +VAL_TABLE_ TsrOvtkMsgTxt_D_Rq 7 "LimForTrucksCancelled" 6 "LimForTrucksWoQlfdRstrc" 5 "LimForTrucksWithoutRstrc" 4 "LimAllCancelled" 3 "LimAllWithoutQlfdRstrc" 2 "LimAllWithoutRestriction" 1 "OvertakingAllowed" 0 "Null"; +VAL_TABLE_ Null_False_True 3 "NotUsed" 2 "True" 1 "False" 0 "Null"; +VAL_TABLE_ TsrStatMsgTxt_D_Rq 7 "NotUsed" 6 "NoDataExists" 5 "TSR_Error" 4 "Available_NavigationOnly" 3 "Available_CameraOnly" 2 "Available_FusionMode" 1 "TSR_Off" 0 "Null"; +VAL_TABLE_ NoMessage_DisplayMessage 1 "DisplayMessage" 0 "NoMessage"; +VAL_TABLE_ FdsmTrgRight 1 "Object_in_Right_Lobe" 0 "No_Object"; +VAL_TABLE_ FdsmTrgCntr 1 "Object_in_Center_Lobe" 0 "No_Object"; +VAL_TABLE_ FdsmTrgLeft 1 "Object_in_Left_Lobe" 0 "No_Object"; +VAL_TABLE_ EngineBrakeOff_Active 1 "Engine_Braking_Activated" 0 "Engine_Braking_Off"; +VAL_TABLE_ NoEngineBrake_Brake 1 "Engine_Braking" 0 "No_Engine_Braking"; +VAL_TABLE_ PlgActv_D_ActlChrgr 3 "Faulty" 2 "Not used_2" 1 "On_Plug__Connected_" 0 "Off_Plug__Disconnected_"; +VAL_TABLE_ EngSrvcRqd_B_Rq 1 "Engine_Service_Required" 0 "No_engine_service_required"; +VAL_TABLE_ WeekendEndHR_St 31 "Invalid" 30 "Unknown" 29 "Reserved_29" 28 "Reserved_28" 27 "Reserved_27" 26 "Reserved_26" 25 "Reserved_25" 24 "Reserved_24"; +VAL_TABLE_ WeekendEndMin_St 63 "Faulty" 62 "No_data_exists" 61 "Reserverd" 60 "Reserverd"; +VAL_TABLE_ WeekendStartHR_St 31 "Invalid" 30 "Unknown" 29 "Reserved_29" 28 "Reserved_28" 27 "Reserved_27" 26 "Reserved_26" 25 "Reserved_25" 24 "Reserved_24"; +VAL_TABLE_ WeekendStartMin_St 63 "Faulty" 62 "No_data_exists" 61 "Reserverd" 60 "Reserverd"; +VAL_TABLE_ LscmbbBaSens_D_Rq 3 "Level3_EBA" 2 "Level2_EBA" 1 "Level1_EBA" 0 "Norman_EBA"; +VAL_TABLE_ Allowed_Denied 1 "Denied" 0 "Allowed"; +VAL_TABLE_ LscmbbBrkPrchg_D_Rq 3 "NotUsed" 2 "Level2_PreCharge" 1 "Level1_PreCharge" 0 "No_Precharge"; +VAL_TABLE_ LscmbbBrkDecel_B_Enabl 1 "ConductLSCMbBDecelReq" 0 "DoNotConductLSCMbBDecelReq"; +VAL_TABLE_ PrkAidMsgTxt_D_Rq 15 "All_Sns_Blk" 14 "R_Sns_ON_F_Sns_Blk" 13 "R_Sns_Blk_F_Sns_ON" 12 "R_Sns_Inactive_Trlr_atch" 11 "Not_Avail_Trlr_attchd" 10 "Fail_Mode_no_Chime" 9 "Fail_Mode_with_Chime" 8 "R_Sns_Trlr_F_Sns_Blk" 7 "NotUsed3" 6 "Park_Sys_Alternate_Mode" 5 "R_Snsrs_On_F_Snsrs_On" 4 "NotUsed2" 3 "Reset_Message_Warn" 2 "R_Snsrs_Off_F_Snsrs_On" 1 "R_Snsrs_On_F_Snsrs_Off" 0 "All_Park_Sensors_Off"; +VAL_TABLE_ PrkAidSns_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_TABLE_ PrkAid_D_Falt 7 "NotUsed2" 6 "NotUsed1" 5 "Failure_Front_PSM_Sensors" 4 "No_Data_Exists" 3 "Failure_Rear_Sensors" 2 "Speaker_Fault" 1 "ECU_Fault" 0 "No_Fault"; +VAL_TABLE_ OffOnNoDataFault 3 "Fault" 2 "No_Data_Exists" 1 "On" 0 "Off"; +VAL_TABLE_ ApaActvSd_D_Actl 3 "Dirver_Side" 2 "Passenger_Side" 1 "No_Side" 0 "Null"; +VAL_TABLE_ ApaMdeStat_D_RqDrv 7 "Faulty" 6 "Off" 5 "NotUsed2" 4 "NotUsed1" 3 "POA" 2 "PPA" 1 "SAPP" 0 "Inactive"; +VAL_TABLE_ ApaMde_D_Avail 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "NotUsed3" 10 "NotUsed2" 9 "NotUsed1" 8 "PPA_POA" 7 "SAPP_POA" 6 "POA" 5 "PPA" 4 "SAPP" 3 "SAPP_PPA_POA" 2 "SAPP_PPA" 1 "None" 0 "Null"; +VAL_TABLE_ ApaMde_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "POA" 3 "PPA" 2 "SAPP" 1 "Off" 0 "Null"; +VAL_TABLE_ FrostWarn_D_Stat 3 "NotUsed" 2 "On_Amber" 1 "On_Red" 0 "Off"; +VAL_TABLE_ SteWhlLckMsgTxt_D_Rq 3 "NotUsed" 2 "Message_2" 1 "Message_1" 0 "No_Message"; +VAL_TABLE_ GearRvrse_D_Actl 7 "Fault" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Active_confirmed" 2 "Active_not_confirmed" 1 "Inactive_confirmed" 0 "Inactive_not_confirmed"; +VAL_TABLE_ SideDetect_SnStat_Invalid 3 "Invalid" 2 "System_Failure" 1 "Blocked" 0 "Clear"; +VAL_TABLE_ SideDetect_OpStat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Invalid" 3 "Disabled" 2 "On" 1 "Trailer_Tow_Off" 0 "Off"; +VAL_TABLE_ SideDetect_Present 4 "Sensor_Blocked" 3 "Sensor_Fault" 2 "Flash_On" 1 "Alert_On" 0 "AlertOff_FlashOff_SensrClr"; +VAL_TABLE_ Off_On_Flash_BulbProveout 3 "Bulb_Proveout" 2 "Flash" 1 "On" 0 "Off"; +VAL_TABLE_ SideDetect_BLIS_Off_On 2 "BLIS_On_Second_Warning_ON" 1 "BLIS_On_Second_Warning_OFF" 0 "Off"; +VAL_TABLE_ SideDetect_report 3 "Reporting" 2 "Not_Reporting" 1 "System_Standby" 0 "Initialization"; +VAL_TABLE_ DrTGate_D_Rq 3 "NotUsed" 2 "Closing" 1 "Opening" 0 "Not_Moving"; +VAL_TABLE_ WndwSide_D_Stat 3 "BothWindow_Operating" 2 "RearWindow_Operating" 1 "FrontWindow_Operating" 0 "NoWindows_Operating"; +VAL_TABLE_ DcacElPw_D_Rq 3 "NotUsed" 2 "AC_HighPower_Requested" 1 "AC_LowPower_Requested" 0 "AC_Power_NotRequested"; +VAL_TABLE_ False_True 1 "True" 0 "False"; +VAL_TABLE_ Null_Reset 1 "Reset" 0 "Null"; +VAL_TABLE_ HvacBlwrFront_D_Stat 31 "Not_Used" 20 "Full_On" 19 "95_Percent" 18 "90_Percent" 17 "85_Percent" 16 "80_Percent" 15 "75_Percent" 14 "70_Percent" 13 "65_Percent" 12 "60_Percent" 11 "55_Percent" 10 "50_Percent" 9 "45_Percent" 8 "40_Percent" 7 "35_Percent" 6 "30_Percent" 5 "25_Percent" 4 "20_Percent" 3 "15_Percent" 2 "10_Percent" 1 "5_Percent" 0 "Off"; +VAL_TABLE_ immoMsgTxt_D_Rq 15 "Immo_Msg_15" 14 "Immo_Msg_14" 13 "Immo_Msg_13" 12 "Immo_Msg_12" 11 "Immo_Msg_11" 10 "Immo_Msg_10" 9 "Immo_Msg_9" 8 "Immo_Msg_8" 7 "Immo_Msg_7" 6 "Immo_Msg_6" 5 "Immo_Msg_5" 4 "Immo_Msg_4" 3 "Immo_Msg_3" 2 "Immo_Msg_2" 1 "Immo_Msg_1" 0 "Immo_Msg_0_Null"; +VAL_TABLE_ BattTracWarnLamp_B_Rq 1 "On" 0 "Off"; +VAL_TABLE_ BattTracSrvcRqd_B_Rq 1 "On" 0 "Off"; +VAL_TABLE_ HtrnWarnLamp_B_Dsply 1 "On" 0 "Off"; +VAL_TABLE_ HtrnSrvcRqd_B_Dsply 1 "On" 0 "Off"; +VAL_TABLE_ NoData_Faulty_7E_7F 127 "Faulty" 126 "NoDataExists"; +VAL_TABLE_ PreCondACSet_D_Actl 3 "Last_User_Setting" 2 "Auto" 1 "On" 0 "Off"; +VAL_TABLE_ PreCondFanSet_D_Actl 15 "Not_used" 14 "Not_used" 13 "Not_used" 12 "Not_used" 11 "Not_used" 10 "Not_used" 9 "Last_user_setting" 8 "Auto" 7 "Speed_7" 6 "Speed_6" 5 "Speed_5" 4 "Speed_4" 3 "Speed_3" 2 "Speed_2" 1 "Speed_1" 0 "OFF"; +VAL_TABLE_ PreCondID_No_Actl 0 "Invalid"; +VAL_TABLE_ PreCondRecrcSet_D_Actl 3 "Last_User_Setting" 2 "Auto" 1 "Recirc" 0 "Outside/Fresh"; +VAL_TABLE_ PreCondTeSet_Te_Actl 31 "HI" 1 "LO" 0 "Last_driver_setting"; +VAL_TABLE_ PreCondTPRDef_D_Actl 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ PreCondModeSet_D_Actl 15 "Not_used" 14 "Not_used" 13 "Not_used" 12 "Not_used" 11 "LastUserSetting" 10 "Auto" 9 "Max_Defrost" 8 "Windshield_Panel_Floor" 7 "Windshield_Panel" 6 "Windshield_(Defrost)" 5 "Windshield_Floor" 4 "Floor" 3 "Panel_Floor" 2 "Panel_(Vent)" 1 "Max_A/C" 0 "Off"; +VAL_TABLE_ ChargePortPwr_St 2 "LowPower" 1 "HighPower" 0 "Null"; +VAL_TABLE_ ChargeProfIDPref_St 3 "NotUsed" 2 "Value" 1 "ChargeNow" 0 "Null"; +VAL_TABLE_ ChrgGlobSched_D_Actl 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ ChrgLocEndHr_No_Actl 31 "Invalid" 30 "Unknown"; +VAL_TABLE_ ChrgLocEndMin_No_Actl 63 "Invalid" 62 "Unknown"; +VAL_TABLE_ ChrgLocProgram_D_Actl 7 "Not_used" 6 "Not_used" 5 "Not_used" 4 "Manual" 3 "TimeofUse" 2 "SmMet" 1 "ChargeImm" 0 "Null"; +VAL_TABLE_ ChrgLocSchedCat_D_Actl 11 "Reserved" 10 "Window_10" 9 "Window_9" 8 "Window_8" 7 "Window_7" 6 "Window_6" 5 "Window_5" 4 "Window_4" 3 "Window_3" 2 "Window_2" 1 "Window_1" 0 "Null"; +VAL_TABLE_ ChrgLocHsphs_D_Actl 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "SouthEast_Lat-_Long+" 3 "SouthWest_Lat-_Long-" 2 "NorthEast_Lat+_Long+" 1 "NorthWest_Lat+_Long-" 0 "NoDataExists"; +VAL_TABLE_ FuelPumpPwr_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Power_Off_Default" 3 "Power_Off_Command" 2 "Power_Off_Service" 1 "Power_Off_Impact" 0 "Power_On"; +VAL_TABLE_ ChrgrRdyStat_D_Actl 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "Charging" 2 "ChargerFault" 1 "ChargerReady" 0 "NotReady"; +VAL_TABLE_ PrmtrAlrmEvnt_D_Stat 15 "Diag_Tamper" 14 "Trailer" 13 "Shock_Sensor" 12 "Post_Crash" 11 "Panic" 10 "Intrusion" 9 "Inclination" 8 "Ign_Tamper" 7 "LG_Door" 6 "Decklid" 5 "Hood" 4 "PR_Door" 3 "PF_Door" 2 "DR_Door" 1 "DF_Door" 0 "Null"; +VAL_TABLE_ SecurityMsgTxt_D_Rq 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ BattChrgRdyStat_D_Actl 7 "NotUsed2" 6 "NotUsed1" 5 "Faulted" 4 "ChargeComplete" 3 "Charging" 2 "BatteryChargeReady" 1 "ChargeWait" 0 "NotReady"; +VAL_TABLE_ BattChrgInhbt_D_Rq 3 "MaintainTargetSoc" 2 "NotUsed" 1 "InhibitChargingThermal" 0 "Enable_Charging"; +VAL_TABLE_ Fault_7FF_NoData 2047 "Fault" 2046 "NoDataExists"; +VAL_TABLE_ Deactivate_Activate 1 "Activate" 0 "Deactivate"; +VAL_TABLE_ PtcHtr_D_Stat 3 "Faulty" 2 "NotUsed" 1 "On" 0 "Off"; +VAL_TABLE_ PtcHtr_D_Cmd 3 "TurnOn" 2 "AutoMode" 1 "TurnOff" 0 "NoDecision_Initializing"; +VAL_TABLE_ Fault_FFFFFF 16777215 "Fault"; +VAL_TABLE_ NoData_Fault_FFFE_FFFF 65535 "Fault" 65534 "NoDataExists"; +VAL_TABLE_ EngOffTe_B_Dsply 1 "Eng_warm_engh_for_pd" 0 "Eng_not_warm_engh_for_pd"; +VAL_TABLE_ Fault_FFFF_NoData_FFFE 65535 "Fault" 65534 "NoDataExists"; +VAL_TABLE_ Fault_1FFF 8191 "Fault"; +VAL_TABLE_ TrlrBattChrg_D_Stat 3 "Reverse" 2 "Normal" 1 "Low" 0 "Null"; +VAL_TABLE_ TrlrLampCtl_D_Stat 3 "NotUsed" 2 "TrlrLampCnnctDrvFailure" 1 "TrlrLampNotCnnctDrvFailure" 0 "Null"; +VAL_TABLE_ ElPw_D_StatStrtStop 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "Supported_Level_4" 8 "Supported_Level_3" 7 "Supported_Level_2" 6 "Supported_Level_1" 5 "Limited_Support" 4 "Fault_Limited" 3 "LV_Event_in_Progress" 2 "Not_Supported_Imminent" 1 "Supported_All" 0 "Not_Supported"; +VAL_TABLE_ ImpactEvntFdbck_D_Stat 3 "NotUsed" 2 "EventComplete" 1 "EventInProgress" 0 "Normal"; +VAL_TABLE_ StopStrtIODTxt_D_Rq 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_TABLE_ NoData_Fault_7FFE_7FFF 32767 "Fault" 32766 "NoDataExists"; +VAL_TABLE_ NoData_Fault_3E_3F 63 "Fault" 62 "NoDataExists"; +VAL_TABLE_ DrvSte_D_Stat 15 "NotUsed10" 14 "NotUsed9" 13 "NotUsed8" 12 "NotUsed7" 11 "NotUsed6" 10 "NotUsed5" 9 "NotUsed4" 8 "NotUsed3" 7 "NotUsed2" 6 "NotUsed1" 5 "Request_Active" 4 "Ignition_Off" 3 "DSR_in_Normal_Idle_Mode" 2 "EPAS_Comm_Disturbed" 1 "DSR_Request_Not_Applicable" 0 "DSR_Deactivated"; +VAL_TABLE_ StrtrMtrCtlMsgTxt_D_Rq 7 "Start_In_Gear_Allowed" 6 "Pending_Start_Cancelled" 5 "Start_Pending_Please_Wait" 4 "Cranking_Limit_Exceeded" 3 "Press_Brk_and_Shift_to_P_N" 2 "Press_Clutch_and_Brake" 1 "Press_Clutch_To_Start" 0 "No_Display"; +VAL_TABLE_ Null_Open 1 "Open" 0 "Null"; +VAL_TABLE_ Invalid_OffOn 0 "Invalid" 1 "Off" 2 "On"; +VAL_TABLE_ TempDegreesC_DegreesF 0 "Temperature_deg_c" 1 "Temperature_deg_f"; +VAL_TABLE_ BeltminderAudioMute 2 "On" 1 "Off" 0 "Invalid"; +VAL_TABLE_ Chime_Source 2 "Cluster" 1 "Infotainment_Sys" 0 "Invalid"; +VAL_TABLE_ Invalid_DayNight 2 "Night" 1 "Day" 0 "Invalid"; +VAL_TABLE_ Invalid_12h_24h 2 "24h_mode" 1 "12h_mode" 0 "Invalid"; +VAL_TABLE_ Invalid_Theme1_2 2 "Theme_2" 1 "Theme_1" 0 "Invalid"; +VAL_TABLE_ LanguageSelect_St 30 "Slovak" 29 "Arabic" 28 "Cantonese" 27 "Mandarin_Chinese" 26 "Korean" 25 "Japanese_Kanji" 24 "Japanese_Katakana" 23 "Braz_Portuguese" 22 "EU_Portuguese" 21 "Finish" 20 "Norwegian" 19 "Danish" 18 "Swedish" 17 "Hungarian" 16 "Greek" 15 "Czech" 14 "Polish" 13 "Flemish" 12 "Dutch" 11 "Russian" 10 "Turkish" 9 "Mex_Spanish" 8 "EU_Spanish" 7 "Cana_French" 6 "EU_French" 5 "Italian" 4 "German" 3 "NA_English" 2 "UK_English" 1 "Unknown" 0 "Invalid"; +VAL_TABLE_ Blower_Indicate 15 "Display_Blank" 14 "14_Indicators_On" 13 "13_Indicators_On" 12 "12_Indicators_On" 11 "11_Indicators_On" 10 "10_Indicators_On" 9 "9_Indicators_On" 8 "8_Indicators_On" 7 "7_Indicators_On" 6 "6_Indicators_On" 5 "5_Indicators_On" 4 "4_Indicators_On" 3 "3_Indicators_On" 2 "2_Indicators_On" 1 "1_Indicator_On" 0 "Indicators_Off"; +VAL_TABLE_ CC_Fr_Stat_User_Adj 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "Fr_Blwr_Spd_Selection" 2 "FRHS_SetPt_Selection" 1 "FLHS_SetPt_Selection" 0 "None"; +VAL_TABLE_ HeadLghtHiFdbck_D_Stat 3 "NotUsed" 2 "Cancel" 1 "Hold" 0 "Allow_Change"; +VAL_TABLE_ Backlit_LED_Status 15 "Unused3" 14 "Unused2" 13 "Unused1" 12 "Night_12" 11 "Night_11" 10 "Night_10" 9 "Night_9" 8 "Night_8" 7 "Night_7" 6 "Night_6" 5 "Night_5" 4 "Night_4" 3 "Night_3" 2 "Night_2" 1 "Night_1" 0 "Off"; +VAL_TABLE_ Veh_Lock_Status 3 "UNLOCK_DRV" 2 "UNLOCK_ALL" 1 "LOCK_ALL" 0 "LOCK_DBL"; +VAL_TABLE_ PrkLckCtlMsgTxt_D_Rq 3 "BTSI_DI_3" 2 "BTSI_DI_2" 1 "BTSI_DI_1" 0 "Null_BTSI_DI"; +VAL_TABLE_ NoShift_Shift 1 "Shift" 0 "NoShift"; +VAL_TABLE_ CcdMsgTxt_D_RqDsply 15 "Unused8" 14 "Unused7" 13 "Unused6" 12 "Unused5" 11 "Unused4" 10 "Unused3" 9 "Unused2" 8 "StationaryMode" 7 "Mode_Change_Unavailable" 6 "CCD_Temporarily_Off" 5 "CCD_Service_Required" 4 "Faulty" 3 "Sport" 2 "Normal" 1 "Comfort" 0 "No_Mode_Selected"; +VAL_TABLE_ CrashEvnt_D_Stat 3 "Invalid" 2 "Fuel_Cutoff_Event" 1 "Deploy_Event" 0 "No_Event"; +VAL_TABLE_ ReducedGuard_D_Stat 3 "NotUsed" 2 "Alarm_On" 1 "Alarm_Off_Previously_On" 0 "Alarm_Off"; +VAL_TABLE_ HvacPrecondBlwr_D_Rq 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "Last_User_Setting" 8 "Auto" 7 "Speed7" 6 "Speed6" 5 "Speed5" 4 "Speed4" 3 "Speed3" 2 "Speed2" 1 "Speed1" 0 "Off"; +VAL_TABLE_ HvacPrecondMode_D_Rq 15 "NotUsed4" 14 "NotUsed3" 13 "NotUsed2" 12 "NotUsed1" 11 "Last_User_Settings" 10 "Auto" 9 "Max_Defrost" 8 "Windshield_Panel_Floor" 7 "Windshield_Panel" 6 "Windshield" 5 "Windshield_Floor" 4 "Floor" 3 "Panel_Floor" 2 "Panel" 1 "MAX_AC" 0 "Off"; +VAL_TABLE_ ButtonNotPressed 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_TABLE_ Null_Pressed 1 "Pressed" 0 "Null"; +VAL_TABLE_ FobComm_D_Stat 3 "NotUsed" 2 "RemEngStartOK" 1 "RemEngStartFail" 0 "Null"; +VAL_TABLE_ PudLamp_D_Rq 3 "RAMP_DOWN" 2 "RAMP_UP" 1 "ON" 0 "OFF"; +VAL_TABLE_ WndwGlbl_D_Cmd 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "GLEARN" 3 "GCLOSE" 2 "GOPEN" 1 "GSTOP" 0 "Null"; +VAL_TABLE_ LockMsg 7 "MSG7" 6 "MSG6" 5 "MSG5" 4 "MSG4" 3 "MSG3" 2 "MSG2" 1 "MSG1" 0 "NO_WARNING"; +VAL_TABLE_ ChildLockDisplay 3 "NOT_SUPPORTED" 2 "ERROR" 1 "CHILD_UNLOCK" 0 "CHILD_LOCK"; +VAL_TABLE_ Null_Lock_Unlock 3 "NotUsed" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_TABLE_ Wiper 15 "NO_DATA_EXISTS" 14 "STALLED" 13 "RESERVED" 12 "AUTO_ADJUST" 11 "COURTESYWIPE" 10 "AUTO_HIGH" 9 "AUTO_LOW" 8 "WASH" 7 "MIST_FLICK" 6 "MAN_HIGH" 5 "MAN_LOW" 4 "MAN_INT_ON" 3 "MAN_INT_OFF" 2 "OFF_MOVING" 1 "AUTO_OFF" 0 "OFF"; +VAL_TABLE_ Turn_switch 3 "Unused_Treat_As_Off" 2 "Right" 1 "Left" 0 "Off"; +VAL_TABLE_ PrkLght_D_Stat 3 "Park_Both" 2 "Park_Right" 1 "Park_Left" 0 "Off"; +VAL_TABLE_ LghtAmb_D_Sns 7 "No_Data_Exists" 6 "Unused2" 5 "Unused1" 4 "Tunnel_Off" 3 "Tunnel_On" 2 "Twilight" 1 "Light" 0 "Dark"; +VAL_TABLE_ HeadLghtSwtch_D_Stat 3 "Autolamp" 2 "Headlamp" 1 "Parklamp" 0 "Off"; +VAL_TABLE_ EmgcyBrkLamp_D_Rq 3 "NotUsed" 2 "Active_at_standstill" 1 "Active_at_speed" 0 "Inactive"; +VAL_TABLE_ GearLvrPos_D_Unfilt 7 "Invalid" 6 "NotUsed" 5 "In_between" 4 "Low" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_TABLE_ EDrvTqMntrRconfg_D_Cmd 7 "OK" 6 "Disable_Cruise" 5 "NotUsed4" 4 "Supercreep" 3 "NotUsed3" 2 "NotUsed2" 1 "Engine_shutdown" 0 "NotUsed"; +VAL_TABLE_ OpenPressedFault 3 "Fault" 2 "Unused" 1 "Pressed" 0 "Open"; +VAL_TABLE_ LaHandsOff_D_Dsply 3 "Suppressed" 2 "Level2" 1 "Level1" 0 "HandsOn"; +VAL_TABLE_ Avail_Unavail 1 "Unavailable" 0 "Available"; +VAL_TABLE_ LaActvStats_D_Dsply 31 "Unused7" 30 "LA_Off" 29 "Unused5" 28 "Unused4" 27 "Unused3" 26 "Unused2" 25 "Unused1" 24 "InerveneLeft_InterveneRght" 23 "WarnLeft_InterveneRight" 22 "SuppressLeft_InterveneRght" 21 "AvailLeft_InterveneRhtt" 20 "NoLeft_InterveneRight" 19 "InterveneLeft_WarnRight" 18 "WarnLeft_WarnRight" 17 "SuppressLeft_WarnRight" 16 "AvailableLeft_WarnRight" 15 "NoLeft_WarnRight" 14 "InterveneLeft_SuppressRght" 13 "WarnLeft_SuppressRight" 12 "SuppressLeft_SuppressRight" 11 "AvailLeft_SuppressRight" 10 "NoLeft_SuppressRight" 9 "InterveneLeft_AvailRight" 8 "WarnLeft_AvailRight" 7 "SuppressLeft_AvailRight" 6 "AvailableLeft_AvailRight" 5 "NoLeft_AvailableRight" 4 "InterveneLeft_NoRight" 3 "WarnLeft_NoRight" 2 "SuppressLeft_NoRight" 1 "AvailableLeft_NoRight" 0 "NoLeft_NoRight"; +VAL_TABLE_ AhbcHiBeam_D_Rq 3 "Deactivated_Unavailabl" 2 "Unused" 1 "Main_HighBeamRecommend" 0 "Dipped_LowBeamRecommend"; +VAL_TABLE_ GrllShtrPos_D_Cmd 15 "Fully_Open" 14 "Position14" 13 "Position13" 12 "Position12" 11 "Position11" 10 "Position10" 9 "Position9" 8 "Position8" 7 "Position7" 6 "Position6" 5 "Position5" 4 "Position4" 3 "Position3" 2 "Position2" 1 "Position1" 0 "Fully_Closed"; +VAL_TABLE_ LifeCycMde_D_Actl 3 "Transport" 2 "NotUsed" 1 "Factory" 0 "Normal"; +VAL_TABLE_ TrnMsgTxt_D_Rq 15 "Message_15" 14 "Message_14" 13 "Message_13" 12 "Message_12" 11 "Message_11" 10 "Message_10" 9 "Message_9" 8 "Message_8" 7 "Message_7" 6 "Message_6" 5 "Message_5" 4 "Message_4" 3 "Message_3" 2 "Message_2" 1 "Message_1" 0 "NoMessage"; +VAL_TABLE_ DieslPrtcRgen_D_Rq 7 "Unused_2" 6 "Unused_1" 5 "Full_Regen_2" 4 "Full_Regen_1" 3 "HeatUp_3" 2 "HeatUp_2" 1 "HeatUp_1" 0 "Normal_Mode_NoRegen"; +VAL_TABLE_ ClimtHeat_D_Rq 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "PtcHtrTestMde" 3 "Defrost_Defog" 2 "FastTempPullDownHeatingReq" 1 "OpportunisticHeatingReq" 0 "NoHeatingRequest"; +VAL_TABLE_ TrnCapHlth_Actl 3 "Capacitor_OK" 2 "Degraded_Capacitor" 1 "Capacitor_State_Unknown" 0 "Capacitor_Fault"; +VAL_TABLE_ TrnSecPrkStat_D_Actl 7 "Faulty" 6 "Fault_Released" 5 "Fault_Latched" 4 "Recouple_in_Progress" 3 "Mechanism_Released" 2 "RTP_in_Progress" 1 "Pending" 0 "Latched"; +VAL_TABLE_ TrnGear_D_Actl 7 "Fault" 6 "NotUsed" 5 "Manual" 4 "Drive" 3 "Neutral" 2 "Reverse" 1 "Park" 0 "Transition_State"; +VAL_TABLE_ TrnNtrlTowCmd_D_Actl 3 "NotUsed" 2 "Neutral_Tow_Entry" 1 "Car_Wash_Mode" 0 "Normal_Mode"; +VAL_TABLE_ TrnValidGear_D_Cnfm 3 "Accept" 2 "Reject" 1 "Internal_Request" 0 "No_Command"; +VAL_TABLE_ TrnGear_D_RqPt 7 "Fault" 6 "NotUsed" 5 "Manual" 4 "Drive" 3 "Neutral" 2 "Reverse" 1 "Park" 0 "No_Gear"; +VAL_TABLE_ TrnValidGearRq_D_Stat 3 "Valid_Request" 2 "Valid_Degraded_Request" 1 "Invalid_Request" 0 "No_Request"; +VAL_TABLE_ NoData_Fault_3FE_3FF 1023 "Fault" 1022 "NoDataExists"; +VAL_TABLE_ ClimtCool_D_Rq 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "ElACTestMde" 3 "Defrost_Defog" 2 "FastTempPullDownCoolReq" 1 "OpportunisticCoolingReq" 0 "NoCoolingRequest"; +VAL_TABLE_ HtrnHvilOpen_B_Actl 1 "HVIL_is_Open" 0 "Normal_Operation"; +VAL_TABLE_ EngTeHi_B_Actl 1 "EngineTempHigh" 0 "Normal"; +VAL_TABLE_ Eng_D_StatPwPck 7 "NotUsed3" 6 "NotUsed2" 5 "Engine_Start_Cold_Cat" 4 "Engine_Disabled" 3 "Engine_Running" 2 "Engine_Run_CSER" 1 "Engine_Start" 0 "Off"; +VAL_TABLE_ EngFuelCutFull_B_Inhbt 1 "Inhibit_DFSO" 0 "Normal"; +VAL_TABLE_ EngFuelCutFull_B_Rq 1 "FuelCutRequest" 0 "NormalOperation"; +VAL_TABLE_ Fault_7FF 2047 "Fault"; +VAL_TABLE_ EngStopFst_B_Rq 1 "FastEngineShutdown" 0 "NormalOperation"; +VAL_TABLE_ EngStrtCold_B_Rq 1 "ExtremeColdStart" 0 "NormalStart"; +VAL_TABLE_ EngStrtSmooth_D_Rq 7 "NotUsed" 6 "Smooth_NoPedal" 5 "Smooth_LightPedal" 4 "Smooth_MediumPedal" 3 "Smooth_HeavyPedal" 2 "Smooth_WOP" 1 "Smooth_Cold" 0 "Smooth_ExtremeCold"; +VAL_TABLE_ Fault_FFF 4095 "Fault"; +VAL_TABLE_ VehStrtStop_D_Rq 3 "NotUsed" 2 "Vehicle_Start_Request" 1 "Vehicle_Stop_Request" 0 "NoRequest"; +VAL_TABLE_ HvacRec_D_RqMxBatt 15 "NotUsed5" 14 "NotUsed4" 13 "NotUsed3" 12 "NotUsed2" 11 "NotUsed1" 10 "No_Override" 9 "90Percent_RecircMax" 8 "80Percent_RecircMax" 7 "70Percent_RecircMax" 6 "60Percent_RecircMax" 5 "50Percent_RecircMax" 4 "40Percent_RecircMax" 3 "30Percent_RecircMax" 2 "20Percent_RecircMax" 1 "10Percent_RecircMax" 0 "0Percent_RecircFullOpen"; +VAL_TABLE_ FuelCtlOpenLp_B_Inhbt 1 " Inhibit_FullPedal_Actions" 0 "Normal_Operation"; +VAL_TABLE_ EngStrtStop_B_SrcSrvc 1 "Eng_StartStop_for_Service" 0 "Not_Requested"; +VAL_TABLE_ EngStrtStop_B_SrcCat 1 "Eng_StartStop_for_Catalyst" 0 "Not_Requested"; +VAL_TABLE_ PrkBrkStatus 7 "GeneralFault_MaintenceMode" 6 "ECD_by_Brake_ECU_Active" 5 "EPB_Limphome_Active" 4 "Rear_Caliper_Open" 3 "RWU_By_EPB_Active" 2 "Rear_Caliper_Transition" 1 "Rear_Caliper_Closed" 0 "Not_Supported"; +VAL_TABLE_ ElLoadCtl_D_Rq 7 "Unused3" 6 "Unused2" 5 "Unused1" 4 "HoldAllDrvrInvisibleLoads" 3 "StdDriverInvisibleLoadsOn" 2 "AllDriverInvisibleLoadsOn" 1 "All_Possible_Loads_Off" 0 "No_Request"; +VAL_TABLE_ BattTracCool 3 "NotUsed" 2 "DCDC_Overtemperature" 1 "CoolingRequiredbyDCDC" 0 "NoCoolingRequiredbyDCDC"; +VAL_TABLE_ NotReady_Active_Fault 3 "Fault" 2 "Active" 1 "Ready" 0 "Not_Ready"; +VAL_TABLE_ Quality_Data 3 "OK" 2 "Not_Within_Specifications" 1 "Eval_In_Progress" 0 "Fault"; +VAL_TABLE_ PwSrcULoFalt_D_Stat 3 "Fault_No_Output" 2 "Fault_Reduced_Output" 1 "Fault_NonSpecific" 0 "No_Fault"; +VAL_TABLE_ Connect_Discon_Loose 1 "Loose_or_Disconnected" 0 "Connected"; +VAL_TABLE_ DontCare_StartInhibit 1 "Start_Inhibit" 0 "Dont_Care"; +VAL_TABLE_ BattULoChrg_D_Rq 3 "Low_Battery_Temperature" 2 "Charging_Requested" 1 "Chrg_Requested_HighCurrent" 0 "No_Request"; +VAL_TABLE_ PwSysULoFalt_D_Stat 15 "Not_Used_6" 14 "LowBatterySOC" 13 "PSS_Shed2_Contin" 12 "Not_Used_4" 11 "Not_Used_3" 10 "Not_Used_2" 9 "BattMonitoringSensorFault" 8 "LowBattVoltDuringPwSrcOn" 7 "LowBatt2_PowerSaveMode" 6 "LowBatt1_Warning" 5 "Overvoltage" 4 "Fault_NoOutput" 3 "Fault_ReducedOutput" 2 "Fault_Nonspecific" 1 "Cluster_Proveout" 0 "No_Fault"; +VAL_TABLE_ AccStopMde_D_Rq 3 "Stop_Mode_Active" 2 "EPBApplyOrBrakeReleaseWarn" 1 "Limit_Rolling_Speed" 0 "Stop_Mode_Not_Active"; +VAL_TABLE_ EngFuelCutFull_B_Sched 1 "DFSO_Event_Scheduled" 0 "Normal"; +VAL_TABLE_ Eng_D_Stat 3 "NotUsed" 2 "EngAutoStopped" 1 "EngOn" 0 "EngOff"; +VAL_TABLE_ ElPw_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Fault_Limited" 3 "LV_Event_In_Progress" 2 "Not_Supported_Imminent" 1 "Supported" 0 "Not_Supported"; +VAL_TABLE_ PwPckTq_D_Stat 3 "PwPckOn_TqAvailable" 2 "StartInPrgrss_TqNotAvail" 1 "PwPckOn_TqNotAvailable" 0 "PwPckOff_TqNotAvailable"; +VAL_TABLE_ BattTracCool_D_Falt 3 "NotUsed" 2 "CoolSysPartialyOperational" 1 "Cooling_System_Faulted" 0 "Cooling_System_Operational"; +VAL_TABLE_ Fault_FF 255 "Fault"; +VAL_TABLE_ ElCmprOverTe_D_Stat 3 "OverTempStop" 2 "OverTempWarning" 1 "Normal" 0 "Undefined"; +VAL_TABLE_ ElCmprUHi_D_Stat 3 "Overvoltage" 2 "Undervoltage" 1 "InRange" 0 "Undetermined"; +VAL_TABLE_ ElCmpr_D_Stat 7 "Signal_Invalid" 6 "Comp_Off_ActlSpd_Abnormal" 5 "Comp_Off_TrgtSpd_OutRange" 4 "Comp_Shutdown" 3 "Comp_Stopped_Self_Protect" 2 "Comp_Degraded" 1 "Comp_On" 0 "Comp_Off"; +VAL_TABLE_ Southern_Northern 3 "Fault" 2 "Northern" 1 "Southern" 0 "Invalid"; +VAL_TABLE_ PsngrFrntDetct_D_Actl 3 "Unknown" 2 "Empty" 0 "Faulty" 1 "Occupied"; +VAL_TABLE_ Normal_Mode1_2 3 "Undefined" 2 "Mode2" 1 "Mode1" 0 "Normal_Mode"; +VAL_TABLE_ LaActvAvail 3 "LKA_LCA_LDW_Avail" 2 "LCA_LKA_Avail_LDW_Suppress" 1 "LCA_LKA_Suppress_LDW_Avail" 0 "LCA_LKA_LDW_Suppress"; +VAL_TABLE_ LA_NotDenied 1 "LA_Denied" 0 "LA_Not_Denied"; +VAL_TABLE_ HandsOn_Off 1 "Hands_Off" 0 "Hands_On"; +VAL_TABLE_ Smooth_Quick 1 "Quick" 0 "Smooth"; +VAL_TABLE_ None_Low_Med_High 3 "High" 2 "Medium" 1 "Low" 0 "None"; +VAL_TABLE_ LdwActvStats 7 "LDW_Suppress_Right_Left" 6 "Not_Used2" 5 "LDW_Suppress_Right" 4 "LDW_Warning_Right" 3 "LDW_Suppress_Left" 2 "LDW_Warning_Left" 1 "LDW_DemoVibration" 0 "LDW_Idle"; +VAL_TABLE_ Fault_3FF 1023 "Fault"; +VAL_TABLE_ EngStrtStop 15 "Unused_7" 14 "Unused_6" 13 "Unused_5" 12 "Unused_4" 11 "Unused_3" 10 "Unused_2" 9 "Unused_1" 8 "Force_Pull_Down" 7 "Force_Pull_Up" 6 "Pull_Down_Inhibit_Pull_Up" 5 "Inhibit_Change" 4 "Inhibit_Pull_Up" 3 "Pull_Down" 2 "Inhibit_Pull_Down" 1 "Pull_Up" 0 "No_Request"; +VAL_TABLE_ TrnMde_D_Rq 15 "Unused_4" 14 "Unused_3" 13 "Unused_2" 12 "Unused_1" 11 "InOutLckedHydStandby" 10 "InputOutputLocked" 9 "OutputLockedHydStandby" 8 "OutputLocked" 7 "ReducedOutTqHydStandby" 6 "Reduced_Output_Torque" 5 "TransInTqHydStandby" 4 "Transmit_Input_Torque" 3 "ActNeutralHydStandby" 2 "Active_Neutral" 1 "NeutralHydraulicStdby" 0 "Neutral"; +VAL_TABLE_ Fault_F 15 "Fault"; +VAL_TABLE_ Fault_1F 31 "Fault"; +VAL_TABLE_ TmsStatRqDsply 15 "Reserved4" 14 "Reserved3" 13 "Reserved2" 12 "Crawl_Mode_4LOW_Reqd" 11 "Economy_Mode_Select" 10 "ModeChangeNotAvailable" 9 "Terrain_Sys_Not_Avail" 8 "Terrain_System_Fault" 7 "Mode_Change_InProgress" 6 "Dynamics_Mode_Select" 5 "Rock_Crawl_Mode_Select" 4 "Sand_Mode_Select" 3 "Mud_Ruts_Mode_Select" 2 "Low_Mu_Mode_Select" 1 "Special_Modes_Off" 0 "No_Message"; +VAL_TABLE_ LockInhibit 1 "Inhibit" 0 "No_Inhibit"; +VAL_TABLE_ DieslFuelBio_B_ActlDrv 1 "Biodiesel_User" 0 "Non_Biodiesel_User"; +VAL_TABLE_ Invalid_FFF 4095 "Invalid"; +VAL_TABLE_ ParkAid_Chime 15 "Zone15_Chime" 14 "Zone14_Chime" 13 "Zone13_Chime" 12 "Zone12_Chime" 11 "Zone11_Chime" 10 "Zone10_Chime" 9 "Zone9_Chime" 8 "Zone8_Chime" 7 "Zone7_Chime" 6 "Zone6_Chime" 5 "Zone5_Chime" 4 "Zone4_Chime" 3 "Zone3_Chime" 2 "Zone2_Chime" 1 "Zone1_Chime" 0 "No_Chime"; +VAL_TABLE_ Shed_Feature_Group_ID 16 "PtcHeater" 14 "HtdMirr" 13 "HvacRearBlwr_Third" 12 "HvacRearBlwr_Second" 11 "HvacRearBlwr_First" 31 "All LSHED1 Features" 10 "Htd_Windscrn" 9 "SpltHtdBcklight_HtdMirr" 8 "HtdBcklight_HtdMirr" 7 "HtdCoolSeat_FrtDriver" 6 "HtdCoolSeat_FrtPass" 5 "HtdCoolSeat_RearPass" 4 "HtdCoolSeat_RearDriver" 3 "SmartTrlrTowBattCharge" 2 "Htd_StrWhl" 1 "Htd_Washer_Fluid" 0 "No_LSHED1_Features" 15 "Engine_Coolant_Fan"; +VAL_TABLE_ CoolantFanStepAct 31 "Unused7" 30 "Unused6" 29 "Unused5" 28 "Unused4" 27 "Unused3" 26 "Unused2" 25 "Unused1" 23 "Step23" 22 "Step22" 21 "Step21" 20 "Step20" 19 "Step19" 18 "Step18" 17 "Step17" 16 "Step16" 15 "Step15" 14 "Step14" 13 "Step13" 12 "Step12" 11 "Step11" 10 "Step10" 9 "Step9" 8 "Step8" 7 "Step7" 6 "Step6" 5 "Step5" 4 "Step4" 3 "Step3" 2 "Step2" 1 "Step1" 24 "Max_Fan_Speed_Req" 0 "Fan_Cmd_Off"; +VAL_TABLE_ Null_Cancel 1 "Cancel" 0 "Null"; +VAL_TABLE_ Veh_Lock_Requestor 31 "Unused8" 30 "Unused7" 29 "Unused6" 28 "Rgtm_Shutlock_Switch" 27 "Boundary_Alert" 26 "Transit_Vehicle_Relock" 25 "Transit_Cargo_Relock" 24 "Transit_Ajar_Lock" 23 "Diagnostics" 22 "Console_Lock" 21 "Child_Lock" 20 "Double_Lock" 19 "Passive_Pasenger" 18 "Passive_Driver" 17 "Slam_Lock_Protect" 16 "SYNC" 15 "Passport" 14 "Passive_Smart_Unlock" 13 "Autorelock" 12 "RemoteStart" 0 "Null" 1 "Autolock" 11 "Smart_Unlock" 10 "Sliding_Door" 9 "Passive" 8 "Remote" 7 "Programming" 6 "Powerslide" 5 "Keypad" 4 "Key_Cylinder" 3 "Interior" 2 "Auto_Unlock"; +VAL_TABLE_ EPAS_FAILURE 3 "SERVICE_POWER_STEERING_NOW" 2 "SERVICE_POWER_STEERING" 1 "POWER_STRG_ASSIST_FAULT" 0 "EPAS_OK_NO_MESSAGE"; +VAL_TABLE_ Perimeter_Alarm_Mode 3 "Activated" 2 "Armed" 1 "Prearmed" 0 "Disarmed"; +VAL_TABLE_ Invalid_FFFF 65535 "Invalid"; +VAL_TABLE_ FdaStat_D_Dsply 7 "Undefined_3" 6 "Undefined_2" 5 "Undefined_1" 4 "Distance_Alert_Unavailable" 3 "DistanceAlertUnavail_Low" 2 "DistanceAlertUnavailActive" 1 "Distance_Alert_Available" 0 "Distance_Alert_Off"; +VAL_TABLE_ OilPressureWarning 1 "Low_Pressure_Lamp_On" 0 "Normal_Pressure_Lamp_Off"; +VAL_TABLE_ MyKey_KeyTypeChangeReq 3 "Search_PE_BackupSlot" 2 "Clear_All_MyKeys" 1 "Request_New_MyKey" 0 "None"; +VAL_TABLE_ MyKey_Key_Count 13 "Thirteen" 12 "Twelve" 11 "Eleven" 10 "Ten" 9 "Nine" 8 "Eight" 7 "Seven" 6 "Six" 5 "Five" 4 "Four" 3 "Three" 2 "Two" 1 "One" 0 "Zero" 15 "Invalid" 14 "Unlimited"; +VAL_TABLE_ GearEngag_D_Actl 7 "Undefined" 6 "Fwd_Clutch_Fully_Engaged" 5 "Neutral_Idle" 4 "Disengaged_to_Neutral_Idle" 3 "Disengaged_to_Neutral_Park" 2 "Engagement_in_Progress" 1 "InitializeFwdClutchEngagmt" 0 "Park_Neutral"; +VAL_TABLE_ Shed_Level_Req 7 "Unused_2" 6 "Loads_On" 5 "SHED_ENG_OFF" 4 "SOON_ENG_OFF" 3 "SHED2_CONTIN" 2 "SHED2_TRANS" 1 "SHED1" 0 "NO_SHED"; +VAL_TABLE_ BpedMove_D_Actl 3 "Unknown" 2 "DriverApplyingBrakePedal" 1 "NoAutonomousBrkPdlMovement" 0 "AutonomousBrkPedalMove"; +VAL_TABLE_ Eastern_Western 0 "Invalid" 1 "Eastern" 2 "Western" 3 "Fault"; +VAL_TABLE_ EATC_Temp_Digit3 2 "_5" 1 "_0" 0 "OFF"; +VAL_TABLE_ EATC_Units 2 "Fahrenheit" 1 "Celsius" 0 "Off"; +VAL_TABLE_ BattTracOffFst_D_Actl 3 "Unexpected_Contactor_Open" 2 "Restraints_Impact_Event" 1 "Interlock_Open" 0 "Normal"; +VAL_TABLE_ Invalid_1FF 511 "Invalid"; +VAL_TABLE_ ChargeMode 7 "Undefined_2" 6 "Undefined_1" 5 "Battery_Identify" 4 "Battery_Refresh" 3 "SlowRegenAllowNoDischarge" 2 "Fast_Regen_Allowed" 1 "Slow_Regen_Allowed" 0 "Conventional_Charging"; +VAL_TABLE_ Unknown_FFFE_Invalid_FFFF 65535 "Invalid" 65534 "Unknown"; +VAL_TABLE_ SAPPAngleControlStat5 1 "StrgColTorqueExceed_EAROn" 0 "ExternalSigContentOKforEAC"; +VAL_TABLE_ Closed_Open_Active_Fault 3 "Fault" 2 "Active" 1 "Open" 0 "Closed"; +VAL_TABLE_ SAPPAngleControlStat2 1 "Rel_ExtSteeringAngleReqx" 0 "NoRel_ExtSteeringAngleReqx"; +VAL_TABLE_ SAPPAngleControlStat3 1 "EARactiveNoReverseEngage" 0 "ExternalSigContentOKforEAC"; +VAL_TABLE_ RstrnImpactEvntStatus 7 "Invalid" 6 "Not_Used_4" 5 "Threshold_2_Exceeded" 4 "Not_Used_3" 3 "Threshold_1_Exceeded" 2 "Not_Used_2" 1 "Not_Used_1" 0 "Normal"; +VAL_TABLE_ EDRTriggerEvntSync 1 "Threshold_Exceeded" 0 "Normal"; +VAL_TABLE_ EngTeColdPrtct_D_Stats 3 "Engine_Warm_RdcPwr" 2 "OK_to_Drive" 1 "Engine_Warm_PlsWait" 0 "Normal_Operation"; +VAL_TABLE_ HILL_DESC_MC 7 "Fault_Detected" 6 "Cooling_Down" 5 "Abort_Apply_Brakes" 4 "Active" 3 "Disabled" 2 "Enabled" 1 "Off_Road" 0 "Normal"; +VAL_TABLE_ Closed_Ajar 1 "Ajar" 0 "Closed"; +VAL_TABLE_ CADS_Autio_Mute 7 "Unknown" 6 "Attenuation_6" 5 "Attenuation_5" 4 "Attenuation_4" 3 "Attenuation_3" 2 "Attenuation_2" 1 "Attenuation_1" 0 "No_Attenuation_of_Audio"; +VAL_TABLE_ Quality_Factor 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_TABLE_ Null_Day_Night 3 "NotUsed" 2 "Night" 1 "Day" 0 "Null"; +VAL_TABLE_ Null_Flash_High 3 "NotUsed" 2 "High" 1 "Flash_to_Pass" 0 "Null"; +VAL_TABLE_ GearPos_D_Actl 15 "Unknown" 14 "Reverse" 13 "Undefined_5" 12 "Undefined_4" 11 "Undefined_3" 10 "Tenth" 9 "Ninth" 8 "Eighth" 7 "Seventh" 6 "Sixth" 5 "Fifth" 4 "Fourth" 3 "Third" 2 "Second" 1 "First" 0 "Neutral"; +VAL_TABLE_ OffOn_SlowFast_Flash 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_TABLE_ AwdStat_D_RqDsply 31 "NotUsed9" 30 "NotUsed8" 29 "NotUsed7" 28 "To_Engage_4x4_Release_Aped" 27 "To_Engage_4x4_Slow_To_3MPH" 26 "Shift_To_Neutral" 25 "Lkr_Mode_Unavail_TMS" 24 " _4x4_Mode_Unavail_TMS" 23 "Out_of_4Low_Crawl" 22 "AWD_PTU_Oil_Changed" 21 "Change_AWD_PTU_Oil" 20 "Neutral_Tow_Disabled" 19 "Neutral_Tow_Enabled" 18 "AWD_OFF" 17 "_4x4_Off_Road_Speed" 16 "_4x4_Extreme_Off_Road_Mode" 15 "_4x4_Exiting_Off_Road" 14 "_4x4_Off_Road_Mode" 10 "_4x4_Locked_Temporarily" 9 "Shift_In_Progress" 13 "Blocked_Shift_Assist" 12 "_4x4_Auto_Restored" 11 "_4x4_Disabled_Temporarily" 7 "Out_of_4Low__Neutral" 6 "Out_of_4Low__Brake" 5 "Out_of_4Low__Speed" 4 "Into_4Low__Clutch" 3 "Into_4Low__Neutral" 2 "Into_4Low__Brake" 1 "Into_4Low__Speed" 0 "Normal__No_Message" 8 "Out_of_4Low__Clutch"; +VAL_TABLE_ AngleReached 1 "RequestedAngleNotReached" 0 "RequestedAngleCanBeReached"; +VAL_TABLE_ WhlDir 3 "Failed" 2 "Unknown" 1 "Backward" 0 "Forward"; +VAL_TABLE_ VehVLimStat_D_Actl 7 "Undefined_3" 6 "Undefined_2" 5 "Undefined_1" 4 "ASL_Fault_Condition" 3 "Active_and_Limiting" 2 "Active_but_Not_Limiting" 1 "Standby" 0 "Off"; +VAL_TABLE_ Unknown_Fault_1FE_1FF 511 "Fault" 510 "Unknown"; +VAL_TABLE_ Fault_NoFault 1 "Fault" 0 "No_Fault"; +VAL_TABLE_ TrnIpcDsplyMde_D_Actl 7 "Manual_3" 6 "Manual_2" 5 "Manual_1_Low" 4 "Sport" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_TABLE_ TrnIpcDsplyMde_D_Stat 3 "Reserved_Blank_No_Display" 2 "Flash" 1 "On" 0 "Blank_No_Display"; +VAL_TABLE_ TrnIpcDsplyGear_D_Actl 15 "No_Gear_Selected" 14 "_14th_Gear" 13 "_13th_Gear" 12 "_12th_Gear" 11 "_11th_Gear" 10 "_10th_Gear" 9 "_9th_Gear" 8 "_8th_Gear" 7 "_7th_Gear" 6 "_6th_Gear" 5 "_5th_Gear" 4 "_4th_Gear" 3 "_3rd_Gear" 2 "_2nd_Gear" 1 "_1st_Gear" 0 "Neutral"; +VAL_TABLE_ TerrMde_D_Actl 7 "Fail_Safe_Default" 6 "Dynamic_Mode" 5 "Rock_Crawl_Mode" 4 "Mud_Ruts_Mode" 3 "Sand_Mode" 2 "Undefined" 1 "Low_Mu_Mode" 0 "Special_Operating_Mode_Off"; +VAL_TABLE_ TerrMdeChng_D_Rdy 7 "Fault" 6 "Undefined_2" 5 "Undefined_1" 4 "ModeUnavailDrInputRqd" 3 "SpOpModes_NotSupported" 2 "ModeUnavailDynamicCond" 1 "Module_In_Initialization" 0 "Mode_Change_Available"; +VAL_TABLE_ Unknown_Fault_FFFE_FFFF 65535 "Fault" 65534 "Unknown"; +VAL_TABLE_ Invalid_FFFFFF 16777215 "Invalid"; +VAL_TABLE_ AutoParkSpdExitCond 1 "SpeedLimitExceededEAROn" 0 "ExternalSigContentOKforEAC"; +VAL_TABLE_ EngOilLvlDsply_D_Rq 15 "EngOil_LevelSys_CheckFault" 14 "Reserved_2" 13 "Reserved_1" 12 "Conditions_Unsuitable" 11 "Dipstick_Below_Minimum" 10 "Dipstick_Above_Maximum" 9 "Dipstick_Minimum" 8 "Dipstick_12_5_MinMaxRange" 7 "Dipstick_25_MinMaxRange" 6 "Dipstick_37_5_MinMaxRange" 5 "Dipstick_50_MinMaxRange" 4 "Dipstick_62_5_MinMaxRange" 3 "Dipstick_75_MinMaxRange" 2 "Dipstick_87_5_MinMaxRange" 1 "Dipstick_Maximum_Displayed" 0 "No_Message"; +VAL_TABLE_ HdcMde_D_Actl 7 "Fault" 6 "Temporarily_Unavailable" 5 "NotEnabled_WrongGearSel" 4 "NotEnabled_SpdLimitExceed" 3 "Active_Braking" 2 "Not_Active_Braking" 1 "Off" 0 "Undefined"; +VAL_TABLE_ GearLvrPos_D_Actl 15 "Fault" 14 "Unknown_Position" 13 "Undefined_Treat_as__Fault" 12 "Undefined_Treat_as_Fault" 11 "sixth" 10 "fifth" 9 "fourth" 8 "third" 7 "second" 6 "first" 5 "Low" 4 "Sport_DriveSport" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_TABLE_ FcwMsgTxt_D_Rq 7 "Undefined_3" 6 "Undefined_2" 5 "Low_Visibility" 4 "Unavailable_DueTo_LowSpeed" 3 "Available" 2 "Unavailable" 1 "Off" 0 "No_Text"; +VAL_TABLE_ FcwSens_B_Actl 3 "FCW_Sensitivity_3" 2 "FCW_Sensitivity_2" 1 "FCW_Sensitivity_1" 0 "Not_Used"; +VAL_TABLE_ LastSettind_DefaultOn 1 "Default_On" 0 "Last_Setting"; +VAL_TABLE_ EngTurboMde_D_Actl 3 "Fault" 2 "One_Turbo_Active" 1 "Two_Turbos_Active" 0 "Initializing"; +VAL_TABLE_ EngPullUpPullDown 15 "Undefined_7" 14 "Undefined_6" 13 "Undefined_5" 12 "Undefined_4" 8 "Force_Pull_Down" 7 "Force_Pull_Up" 6 "PullDown_Inhibit_PullUp" 5 "Inhibit_Change" 4 "Inhibit_Pull_Up" 3 "Pull_Down" 2 "Inhibit_Pull_Down" 1 "Pull_Up" 0 "No_Request" 11 "Undefined_3" 10 "Undefined_2" 9 "Undefined_1"; +VAL_TABLE_ EngMde_D_Rq 8 "VSC_Sets_Speed_Type_3" 7 "VSC_Sets_Speed_Type_2" 6 "VSC_Sets_Torque_Type_2" 5 "Dependability_Shutdown" 4 "Dependability_Follow" 3 "Start" 2 "VSC_Sets_Torque_Type_1" 1 "VSC_Sets_Speed_Type_1" 0 "Off" 15 "Undefined_7" 14 "Undefined_6" 13 "Undefined_5" 12 "Undefined_4" 11 "Undefined_3" 10 "Undefined_2" 9 "Undefined_1"; +VAL_TABLE_ DrvHdcMsg_D_Rq 7 "Undefined" 6 "Speed_too_High" 5 "Temporarily_Unavailable" 4 "System_Fault" 3 "Select_Gear" 2 "Off" 1 "On" 0 "No_Message"; +VAL_TABLE_ CmbbBrkPrchg_B_Rq 3 "Undefined" 2 "Level_2_PreCharge_Request" 1 "Level_1_PreCharge_Request" 0 "No_PreCharge_Request"; +VAL_TABLE_ CmbbBaSens_D_Rq 3 "Level_3" 2 "Level_2" 1 "Level_1" 0 "Normal"; +VAL_TABLE_ CcStat_D_Actl 7 "Undefined_2" 6 "Undefined_1" 5 "Active" 4 "Active_Que_Assist" 3 "Standby" 2 "Standby_Denied" 1 "Denied" 0 "Off"; +VAL_TABLE_ CadsAudioMute_D_Rq 3 "Reserved" 2 "Partial_Audio_Mute" 1 "Full_Audio_Mute" 0 "No_Audio_Mute"; +VAL_TABLE_ BpedDrvAppl_D_Actl 3 "_Not_Allowed" 2 "Driver_Braking" 1 "Driver_Not_Braking" 0 "Not_Allowed"; +VAL_TABLE_ AslIconDsply_D_Rq 3 "On_Passive_Overridden" 2 "On_Active" 1 "On_Passive" 0 "Off"; +VAL_TABLE_ Unknown_Fault_3E_3F 63 "Fault" 62 "Unknown"; +VAL_TABLE_ AccWarn_D_Dsply 3 "BrakeReleaseWarn_In_StopMd" 2 "Brake_Capacity_Warning" 1 "Cancel_Warning" 0 "No_Warning"; +VAL_TABLE_ AccTrgDist2_D_Dsply 15 "DIST_ACTIVE_13_Farthest" 14 "DIST_ACTIVE_12" 13 "DIST_ACTIVE_11" 12 "DIST_ACTIVE_10" 11 "DIST_ACTIVE_9" 10 "DIST_ACTIVE_8" 9 "DIST_ACTIVE_7" 8 "DIST_ACTIVE_6" 7 "DIST_ACTIVE_5" 6 "DIST_ACTIVE_4" 5 "DIST_ACTIVE_3" 4 "DIST_ACTIVE_2" 3 "DIST_ACTIVE_1_Closest" 2 "DIST_ACTIVE_No_Target" 1 "DIST_STANDBY" 0 "DIST_OFF"; +VAL_TABLE_ AccTGap_D_Dsply 7 "Undefined_2" 6 "Undefined_1" 5 "Time_Gap_5" 4 "Time_Gap_4" 3 "Time_Gap_3" 2 "Time_Gap_2" 1 "Time_Gap_1" 0 "Not_Used"; +VAL_TABLE_ AccEngStat_D_Actl 7 "Undefined_2" 6 "Undefined_1" 5 "ACCSoonCancel_due_Low_Spd" 4 "Shift_Down_Recommendation" 3 "Shift_Up_Recommendation" 2 "ACCNotAllowedToBeActivated" 1 "ACCStandby_due_Auto_Cancel" 0 "Normal_Operation"; +VAL_TABLE_ NotPressed_Pressed 1 "Pressed" 0 "Not_Pressed"; +VAL_TABLE_ TrnGear_D_RqDrv 31 "Fault" 30 "NotUsed_25" 29 "NotUsed_24" 28 "NotUsed_23" 27 "NotUsed_22" 26 "Return_to_Park" 25 "NotUsed_20" 24 "NotUsed_19" 23 "NotUsed_18" 22 "NotUsed_17" 21 "Return_To_Park" 20 "NotUsed_15" 19 "NotUsed_14" 18 "NotUsed_13" 17 "NotUsed_12" 16 "Manual" 15 "Not_Used11" 14 "Not_Used10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "Drive" 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "Neutral" 3 "NotUsed_1" 2 "Reverse" 1 "Park" 0 "No_Gear"; +VAL_TABLE_ Open_Close 1 "Close" 0 "Open"; +VAL_TABLE_ OpenCloseRetainUndef 3 "Undefined" 2 "Retain" 1 "Close" 0 "Open"; +VAL_TABLE_ DasWarn 3 "Undefined" 2 "Warning_Level_2" 1 "Warning_Level_1" 0 "No_Warning"; +VAL_TABLE_ DasAlert 5 "Alertness_Level_5" 4 "Alertness_Level_4" 3 "Alertness_Level_3" 2 "Alertness_Level_2" 1 "Alertness_Level_1" 0 "Undefined"; +VAL_TABLE_ DasStat 3 "Available" 2 "Unavailable_Other" 1 "Feedback_due_to_Speed" 0 "Off"; +VAL_TABLE_ No_Crank_Req 1 "Crank_Request" 0 "No_Crank_Request"; +VAL_TABLE_ DrvSlipCtlMde_D_Rq 3 "App_Specific_Off_Mode_3" 2 "App_Specific_Off_Mode_2" 1 "App_Specific_Off_Mode_1" 0 "Default_Mode"; +VAL_TABLE_ AwdOffRoadMode 3 "Invalid" 2 "Extreme_Off_Road" 1 "Off_Road" 0 "Normal_Mode"; +VAL_TABLE_ NotQuiet_Quiet 1 "Quiet" 0 "Not_Quiet"; +VAL_TABLE_ Normal_AdaptiveCruise 1 "Adaptive_Cruise" 0 "Normal_Cruise"; +VAL_TABLE_ Remote_Device_Feedback 7 "Unused3" 6 "Unused2" 5 "Unused1" 4 "Shutdown" 3 "Running" 2 "Starting" 1 "Acknowledge" 0 "Null"; +VAL_TABLE_ TrnManShif_D_IndDrv 7 "Undefined_3" 6 "Undefined_2" 5 "Shift_to_Neutral" 4 "Downshift_Recommendation" 3 "Upshift_Warning" 2 "Upshift_Performance" 1 "Upshift_Fuel_Economy" 0 "No_Indication"; +VAL_TABLE_ Unlock_Lock 1 "Locked" 0 "Unlock"; +VAL_TABLE_ DieslPrtc_D_RqDsply 7 "Unused_2" 6 "Unused_1" 5 "DPF_SOOT_Level3_Blocked" 4 "DPFSootLvl2_SevereOverload" 3 "DPFRegen_ExhFilterComplete" 2 "DPFRegen_CleanExhFilter" 1 "DPF_Soot_Level1_Overloaded" 0 "DPF_OK_Normal_Operation"; +VAL_TABLE_ PE_BackupSlot_Status 3 "No_Valid_FOB_In_Slot" 2 "MyKey_FOB_In_Slot" 1 "Standard_FOB_In_Slot" 0 "Null"; +VAL_TABLE_ Unknown_Fault_FFE_FFF 4095 "Fault" 4094 "Unknown"; +VAL_TABLE_ Unknown_Fault_1FFE_1FFF 8191 "Fault" 8190 "Unknown"; +VAL_TABLE_ TrnCnvtClu_D_Actl 3 "Transition_or_Micro_Slip" 2 "Lock_Up_Fixed" 1 "Lock_Up_Slip" 0 "No_Lock_Up"; +VAL_TABLE_ InhibitNoinhibit 1 "Inhibit" 0 "No_Inibit"; +VAL_TABLE_ DisableEnable 1 "Enable" 0 "Disable"; +VAL_TABLE_ Unknown_Fault_7FFE_7FFF 32767 "Fault" 32766 "Unknown"; +VAL_TABLE_ Side_Detect_Sn_State 3 "Second_Warning_Audio" 2 "System_Failure" 1 "Blocked" 0 "Clear"; +VAL_TABLE_ Litval_values 255 "Invalid" 254 "Unknown" 5 "Day" 4 "Twilight_4" 3 "Twilight_3" 2 "Twilight_2" 1 "Twilight_1" 0 "Night"; +VAL_TABLE_ Dimming_Lvl 255 "Invalid" 254 "Unknown" 18 "Day_6" 17 "Day_5" 16 "Day_4" 15 "Day_3" 14 "Day_2" 13 "Day_1" 12 "Night_12" 11 "Night_11" 10 "Night_10" 9 "Night_9" 8 "Night_8" 7 "Night_7" 6 "Night_6" 5 "Night_5" 4 "Night_4" 3 "Night_3" 2 "Night_2" 1 "Night_1" 0 "Off"; +VAL_TABLE_ EngStrtStop_B_SrcChtLo 1 "Eng_StartStop_for_CHT_Low" 0 "Not_Requested"; +VAL_TABLE_ EngStrtStop_B_SrcChtHi 1 "Eng_StartStop_for_CHT_Hi" 0 "Not_Requested"; +VAL_TABLE_ EngDiag_D_RqHtrn 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "NoUsed1" 3 "Eng_Diag_Cstdn" 2 "Eng_Diag_Run" 1 "Eng_Diag_Crank" 0 "Eng_Diag_Normal"; +VAL_TABLE_ NotOperating 1 "Operating" 0 "Not_Operating"; +VAL_TABLE_ CamraStat 3 "FrtCam_TempUnavailOther" 2 "FrtCam_TempUnavailVisibile" 1 "Front_Camera_Service_Reqd" 0 "Front_Camera_OK"; +VAL_TABLE_ EngPtoMde_D_Actl 7 "Undefined" 6 "Split_Shaft_Stationary" 5 "Not_Used_2" 4 "PTO_Mobile" 3 "Not_Used_1" 2 "PTO_Stationary" 1 "BCP" 0 "Off"; +VAL_TABLE_ ManRgen_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "CustInitManExhFilterClean" 0 "No_Customer_Request"; +VAL_TABLE_ Remote_Start_Status 3 "Invalid" 2 "Unknown" 1 "Remote" 0 "Null"; +VAL_TABLE_ Lock_Subld 15 "Unused7" 14 "Unused6" 13 "Unused5" 12 "Unused4" 11 "Unused3" 10 "Unused2" 9 "Unused1" 8 "Customer_8" 7 "Customer_7" 6 "Customer_6" 5 "Customer_5" 4 "Customer_4" 3 "Customer_3" 2 "Customer_2" 1 "Customer_1" 0 "Null"; +VAL_TABLE_ Brake_Fluid 3 "Invalid" 2 "Unknown" 1 "Low" 0 "OK"; +VAL_TABLE_ Unknown_Invalid_FE_FF 255 "Invalid" 254 "Unknown"; +VAL_TABLE_ Invalid_FF 255 "Invalid"; +VAL_TABLE_ NotLow_Low 1 "Low" 0 "Not_Low"; +VAL_TABLE_ Disabled_Enabled_Status 2 "Status" 3 "NotUsed" 1 "Enabled" 0 "Disabled"; +VAL_TABLE_ Key_In_Ignition_Status 1 "In" 0 "Out"; +VAL_TABLE_ Ignition_Status 0 "Unknown" 1 "Off" 15 "Invalid" 8 "Start" 4 "Run" 2 "Accessory"; +VAL_TABLE_ Disabled_Enabled_Faulted 3 "Faulted" 2 "Unused" 1 "Enabled" 0 "Disabled"; +VAL_TABLE_ Disabled_Enabled_NoSupport 2 "Unused" 3 "Not_Supported" 1 "Enabled" 0 "Disabled"; +VAL_TABLE_ Unknown_Fault_FE_FF 255 "Fault" 254 "Unknown"; +VAL_TABLE_ Null_Unlock 1 "Unlock" 0 "Null"; +VAL_TABLE_ Null_Active 1 "Active" 0 "Null"; +VAL_TABLE_ HsaStat_D_Actl 7 "Faulty" 6 "FaultyWithDriverIndication" 5 "SlowRelease" 4 "FastRelease" 3 "ActiveBrakePedalReleased" 2 "ActiveBrakePedalPressed" 1 "FindingGradient" 0 "Inactive"; +VAL_TABLE_ Off_Auto_Manual 3 "Undefined" 2 "Manual" 1 "Automatic" 0 "Off"; +VAL_TABLE_ HsaStat_D_Dsply 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "NotAvailable" 3 "SlowReleaseWithChime" 2 "SlowReleaseWithoutChime" 1 "Active" 0 "Inactive"; +VAL_TABLE_ EngMsgTxt_D_Rq 3 "Undefined_2" 2 "Undefined_1" 1 "Power_Reduced_to_LowerTemp" 0 "No_Message"; +VAL_TABLE_ PassRstrnInd_Req 3 "ABOnNotIllum_OffNotIllum" 2 "AirbagOnNot_Illum_OffIllum" 1 "AirbagOn_Illum_OffNotIllum" 0 "AirbagOn_Illum_Off_Illum"; +VAL_TABLE_ RearDiffLckMsg_D_Rq 7 "Locker_Disabled" 6 "Locker_Enabled" 5 "Locker_Accel_Pedal" 4 "Speed4" 3 "Speed3" 2 "Spee2" 1 "Speed1" 0 "Normal__No_Message "; +VAL_TABLE_ GPS_Compass_dirctn 7 "NorthWest" 6 "West" 5 "SouthWest" 4 "South" 3 "SouthEast" 2 "East" 1 "NorthEast" 0 "North"; +VAL_TABLE_ GPS_Actual_Infer 1 "Inferred_Position" 0 "Actual_Postition"; +VAL_TABLE_ DrvHdcWarnInfo_D_Rq 3 "Undefined" 2 "Lamp_On_Continuously" 1 "Lamp_Flashing" 0 "Lamp_Off_Continuously"; +VAL_TABLE_ DieslPrtcRgen_D_Actl 3 "Undefined" 2 "Regen_Level_2" 1 "Regen_Level_1" 0 "No_regen"; +VAL_TABLE_ Off_On 1 "On" 0 "Off"; +VAL_TABLE_ CcMde_D_Actl 7 "TapDownWaiting" 6 "TapUpWaiting" 5 "Resuming_Low" 4 "Resuming_High" 3 "Decelerating" 2 "Accelerating" 1 "Keeping_Speed" 0 "Not_Active"; +VAL_TABLE_ InactiveActive 1 "Active" 0 "Inactive"; +VAL_TABLE_ ManRgenTxt_D_RqDsply 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Cleaning_Aborted_Stopped" 3 "Cleaning_Completed" 2 "Cleaning_In_Progress" 1 "Cleaning_Allowed" 0 "Cleaning_Not_Allowed"; +VAL_TABLE_ Fault_FFFF 65535 "Fault"; +VAL_TABLE_ Fault_7F 127 "Fault"; +VAL_TABLE_ EngOilLvlWarn_D_Rq 7 "Undefined_3" 6 "Undefined_2" 5 "Engine_Oil_Monitor_Fault" 3 "Engine_Oil_High" 2 "Engine_Oil_Critical_Low" 1 "Engine_Oil_Low" 0 "No_Message" 4 "Engine_Oil_Critical_High"; +VAL_TABLE_ UreaQltySys_D_RqDsply 7 "Undefined" 6 "ZZ_Overrides" 5 "EngineIdled" 4 "Engine_Idle_Upon_Refuel" 3 "SPEED_LIMITED_to_YY_mph" 2 "YY_MPH_MAX_UPON_Restart" 1 "CONTAMINATED_ExhFluid" 0 "NoQualityProblem"; +VAL_TABLE_ Unknown_Invalid_1E_1F 31 "Invalid" 30 "Unknown"; +VAL_TABLE_ Unknown_Invalid_3FFE_3FFF 16383 "Invalid" 16382 "Unknown"; +VAL_TABLE_ NoYes 1 "Yes" 0 "No"; +VAL_TABLE_ AwdRnge_D_Actl 7 "Unknown" 6 "High_Range_2wd" 5 "High_Range_Auto" 4 "High_Range_Locked" 3 "Neutral" 2 "Low_Range_2wd" 1 "Low_Range_Auto" 0 "Low_Range_Locked"; +VAL_TABLE_ AwdLck_D_Stat 9 "Undefined" 8 "Under_External_Torque_Ctrl" 7 "Torque_Limited_by_Cmd" 6 "Fully_Locked_by_Cmd" 5 "Disabled" 4 "Warning" 3 "Fault" 2 "Inactive" 1 "Completely_Opened_by_Cmd" 0 "OK"; +VAL_TABLE_ Unknown_Fault_3FE_3FF 1023 "Fault" 1022 "Unknown"; +VAL_TABLE_ LockSwStat 3 "Invalid" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_TABLE_ Null_Override 1 "Override" 0 "Null"; +VAL_TABLE_ Off_On_Flash 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_TABLE_ immoTargetStatCoding 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "DISABLED_RESET " 2 "ENABLED_NONMOTIVE_START" 1 "ENABLED_MOTIVE_START" 0 "DISABLED"; +VAL_TABLE_ BeltBuckle 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_TABLE_ RILReqCoding 3 "Not_Used" 2 "Plant_Mode" 1 "On" 0 "Off"; +VAL_TABLE_ Update_Bit 1 "Fresh_data" 0 "Unchanged_data"; +VAL_TABLE_ Running_Board 3 "Unused" 2 "Manually_Deployed" 1 "All_Enabled" 0 "All_Disabled"; +VAL_TABLE_ HudFlashRate 3 "Unused" 2 "Flash_4Hz_50Prct_DutyCycle" 1 "On" 0 "Off"; +VAL_TABLE_ Turn_Seq 3 "Seq" 2 "On" 1 "Off" 0 "Null"; +VAL_TABLE_ immoTargetCmdCoding 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "TARGET1_IDBLOCK2" 2 "TARGET1_IDBLOCK1" 1 "CHALLENGE" 0 "IDLE"; +VAL_TABLE_ immoSubTargetCmdCoding 7 "Unused3" 6 "Unused2" 5 "ECHO_TARGET1_IDBLOCK2" 4 "Unused1" 3 "RQST_TARGET1_IDBLOCK2" 2 "RQST_TARGET1_IDBLOCK1" 1 "RESPONSE" 0 "IDLE"; +VAL_TABLE_ immoCtrlCmdCoding 0 "IDLE" 1 "MOTIVE_START_RQST" 2 "NONMOTIVE_START_RQST" 3 "RQST_TARGET1_IDBLOCK1" 4 "RQST_TARGET1_IDBLOCK2" 5 "Unused" 6 "ECHO_TARGET1_IDBLOCK2" 7 "SHUTDOWN"; +VAL_TABLE_ Rvc_Zoom 7 "Unknown" 6 "Invalid" 5 "Zoom_Level_V" 4 "Zoom_Level_IV" 3 "Zoom_Level_III" 2 "Zoom_Level_II" 1 "Zoom_Level_I" 0 "Off"; +VAL_TABLE_ NotPark 1 "Park" 0 "Not_Park"; +VAL_TABLE_ Electric_EOH 1 "Electric_Over_Hydraulic" 0 "Electric"; +VAL_TABLE_ PersOptIn 1 "OPTED_IN" 0 "NOT_OPTED_IN"; +VAL_TABLE_ PersonalSetUp 3 "Non_Moveable_Person" 2 "Moveable_Person" 1 "Vehicle" 0 "Factory"; +VAL_TABLE_ Full_Limited 1 "Limited" 0 "Full"; +VAL_TABLE_ NoConflict_Conflict 1 "Conflict" 0 "No_Conflict"; +VAL_TABLE_ Assoc_Confirm 0 "None" 7 "Associate" 6 "Keycode_Rejected" 5 "Keycode_Accepted" 4 "In_Progress" 3 "Erase" 2 "Duplicate" 1 "Disassociate"; +VAL_TABLE_ Pers1_4 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_TABLE_ Null_Query 7 "Unused_2" 6 "Unused_1" 5 "Copy" 4 "Restore" 3 "Upload" 2 "Set" 1 "Query" 0 "Null"; +VAL_TABLE_ EngExhBrkMde_D_Actl 6 "ExhBrkDisable_NoError" 5 "ExhBrkActive_AUTO" 4 "ExhBrkActive_ON" 3 "ExhBrkRequest_AUTO" 2 "ExhBrkRequest_ON" 1 "ExhBrkNoRequest_OFF" 0 "ExhBrkUnavailable_Error"; +VAL_TABLE_ UreaLvlTxt_D_RqDsply 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "System_Error" 10 "Engine_Idled_See_Manual" 9 "Engine_Idled_Upon_Refuel" 8 "Speed_Limited_To_XX_mph" 7 "XXmph_Max_Upon_Restart" 6 "Speed_Limited_To_YY_mph" 5 "YYmph_Max_Upon_Restart" 4 "SpdLimtd_YYmph_In_XXmiles" 3 "ExFlRange_XXMiles_ScndWarn" 2 "Exh_Fluid_Range_XX_Miles" 1 "Exh_Fluid_Under_Half_Full" 0 "Exh_Fluid_Over_Half_Full"; +VAL_TABLE_ RearDiffFalt_D_Stat 3 "Diff_Failed_Closed" 2 "Diff_Failed_Open" 1 "Fault_Non_Specific" 0 "No_Fault"; +VAL_TABLE_ CCOverridden 1 "Cruise_Overridden" 0 "Cruise_Req_Not_Overridden"; +VAL_TABLE_ Ign_Key_Device_Type 15 "Invalid" 14 "Unknown" 3 "Key_Not_Prgrm_Read_Failure" 2 "Key_In_Ign_My_Key" 1 "Key_In_Ign_Standard_Key" 0 "Key_Read_In_Progress"; +VAL_TABLE_ Off_No_Eff_Unknown_Invalid 3 "Invalid" 2 "Unknown" 1 "No_Effect" 0 "Off"; +VAL_TABLE_ Null_Out 1 "Out" 0 "Null"; +VAL_TABLE_ FUEL_SENSORS 1 "Dual_Sensors" 0 "Single_Sensor"; + + +BO_ 823 DTE_HPCMtoECG: 8 Vector__XXX + SG_ DteVehPwId_No_Actl : 47|5@0+ (1,0) [0|31] "unitless" GWM + SG_ DteVehEId_No_Actl : 39|8@0+ (1,0) [0|255] "unitless" GWM + SG_ DteVehEffId_No_Actl : 6|7@0+ (1,0) [0|127] "unitless" GWM + SG_ DteVeh_Pw_Actl : 31|8@0+ (50,0) [0|12750] "watts" GWM + SG_ DteVeh_Eff_Actl : 23|8@0+ (10,-1000) [-1000|1550] "watt*hour/km" GWM + SG_ DteVeh_E_Actl : 15|8@0+ (100,0) [0|25500] "watt*hour" GWM + SG_ DteAcceptNew_B_Rq : 7|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 824 DTE_ECGtoHPCM: 8 GWM + SG_ DteCldTrlrOn_B_Stat : 51|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldTrlrOff_B_Stat : 52|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldTrip_L_Actl : 47|8@0+ (10,-1000) [-1000|1550] "watt*hour/km" Vector__XXX + SG_ DteCldTraffic_B_Stat : 53|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldTerrain_B_Stat : 54|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldRoute_B_Stat : 55|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldPayload_B_Stat : 16|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldId_No_Actl : 21|5@0+ (1,0) [0|31] "unitless" Vector__XXX + SG_ DteCldExtTe_B_Stat : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldExt_Eff_Actl : 39|8@0+ (10,-1000) [-1000|1550] "watt*hour/km" Vector__XXX + SG_ DteCldDrv_Eff_Actl : 31|8@0+ (10,-1000) [-1000|1550] "watt*hour/km" Vector__XXX + SG_ DteCldDcac_B_Stat : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DteCldClimt_Eff_Actl : 15|8@0+ (10,-1000) [-1000|1550] "watt*hour/km" Vector__XXX + SG_ DteCldBattULo_Eff_Actl : 7|8@0+ (10,-1000) [-1000|1550] "watt*hour/km" Vector__XXX + +BO_ 949 Tire_Pressure_Data_FD1: 8 GWM + SG_ Tire_Press_RR_ORR_Data : 39|16@0+ (1,0) [0|65533] "kilopascal" VDM + SG_ Tire_Press_LR_OLR_Data : 55|16@0+ (1,0) [0|65533] "kilopascal" VDM + SG_ Tire_Press_LF_Data : 7|16@0+ (1,0) [0|65533] "kilopascal" VDM + SG_ Tire_Press_RF_Data : 23|16@0+ (1,0) [0|65533] "kilopascal" VDM + +BO_ 1825 TesterPhysicalReqVDM_FD1: 64 GWM + SG_ TesterPhysicalReqVDM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" VDM + +BO_ 524 AWD_Torque_Data: 8 TCCM + SG_ PrplWhlTotTqRqMxAwd_No_Cs : 23|8@0+ (1,0) [0|255] "Unitless" ECM_Diesel + SG_ PrplWhlTot_Tq_RqMxAwd : 7|16@0+ (4,-131072) [-131072|131068] "Nm" ECM_Diesel + SG_ PrplWhlTotTqRqMxAwd_No_Cnt : 31|4@0+ (1,0) [0|15] "Unitless" ECM_Diesel + +BO_ 740 PHEV_Battery_Data1_FD1: 8 GWM + SG_ BattAuxCnnct_B_Cmd : 53|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + +BO_ 1160 ECG_Data2_FD1: 8 GWM + SG_ DgtlCommPncReset_B_Req : 62|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DataMntrSustn_B_Rq : 63|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PwSustnRdata_B_RqTelem : 60|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 776 SmartChargingData_ECG_3: 8 GWM + SG_ ScMnSoc_Pc_RqCld : 55|7@0+ (1,0) [0|127] "percent" Vector__XXX + SG_ ScChrgrPwMax_Pw_RqCld : 39|12@0+ (50,0) [0|204700] "watts" Vector__XXX + SG_ ScLocPwId_No_RqCld : 43|3@0+ (1,0) [0|7] "unitless" Vector__XXX + SG_ PrcondEdit_D_RqCld : 10|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ GoTEditMnte_T_RqCld : 29|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ GoTEditHr_T_RqCld : 15|5@0+ (1,0) [0|29] "SED" Vector__XXX + SG_ ChrgToPcEdit_Pc_RqCld : 7|7@0+ (1,0) [0|125] "percent" Vector__XXX + SG_ AirAmb_Te_ActlCld : 23|10@0+ (0.25,-128) [-128|127.75] "degC" Vector__XXX + SG_ ScFreshDataEnbl_B_Rq : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ScEnbl_D_RqCld : 25|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 775 SmartChargingData_ECG_2: 8 GWM + SG_ ScDayOfWeekId_D_RqCld : 63|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ScLocSetId_No_RqCld : 10|3@0+ (1,0) [0|7] "unitless" Vector__XXX + SG_ ScLocRdius_L_RqCld : 55|7@0+ (100,0) [0|12700] "meter" Vector__XXX + SG_ ScChrgToPc_Pc_RqCld : 47|7@0+ (1,0) [0|127] "percent" Vector__XXX + SG_ ScChrgPrfl_No_RqCld : 23|24@0+ (1,0) [0|16777215] "unitless" Vector__XXX + SG_ ScChrgDurSet_D_RqCld : 12|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ScChrgDur_T_RqCld : 7|11@0+ (1,0) [0|2045] "minute" Vector__XXX + +BO_ 774 SmartChargingData_ECG_1: 8 GWM + SG_ ScLocLongPostv_B_RqCld : 8|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ScLocLongFrct_An_RqCld : 35|20@0+ (1E-006,0) [0|1.048575] "degrees" Vector__XXX + SG_ ScLocLongDeg_An_RqCld : 63|8@0+ (1,0) [0|255] "degrees" Vector__XXX + SG_ ScLocLattPostv_B_RqCld : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ScLocLattFrct_An_RqCld : 23|20@0+ (1E-006,0) [0|1.048575] "degrees" Vector__XXX + SG_ ScLocLattDeg_An_RqCld : 15|7@0+ (1,0) [0|127] "percent" Vector__XXX + SG_ ScLocId_No_RqCld : 6|3@0+ (1,0) [0|7] "unitless" Vector__XXX + SG_ ScLocDelete_B_RqCld : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 811 APIM_Data_FD1: 8 GWM + SG_ DistToStopover_L_Actl : 31|16@0+ (0.1,0) [0|6553.4] "kilometer" Vector__XXX + SG_ StopoverType_D_Stat : 47|3@0+ (1,0) [0|0] "SED" Vector__XXX + SG_ ExtLghtDsply_D_Stat : 7|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ExtLghtRight_D_RqMnu : 11|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ AutoLghtOvrrd_B_RqDrv : 8|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ExtLghtRear_D_RqMnu : 14|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ExtLghtLeft_D_RqMnu : 1|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ExtLghtFront_D_RqMnu : 4|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ GoTEditMnte_T_RqMnu : 63|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ GoTEditHr_T_RqMnu : 44|5@0+ (1,0) [0|29] "SED" Vector__XXX + +BO_ 850 HEV_ChargeStat_FD1: 8 SOBDMC_HPCM_FD1 + SG_ VehElRngeNut_L_Dsply : 11|12@0+ (0.1,0) [0|409.3] "km" GWM + SG_ NxtUsgSocEst_Pc_Dsply : 7|8@0+ (0.5,0) [0|126.5] "unitless" GWM + SG_ EstmChrgTimeLP_St : 39|8@0+ (0.1,0) [0|25.4] "hour" GWM + SG_ EstmChrgTimeHP_St : 47|8@0+ (0.1,0) [0|25.4] "hour" GWM + SG_ ChargeNowDuration_St : 31|8@0+ (0.1,0) [0|25.4] "hour" GWM + +BO_ 563 MasterReset_HS3_ECGDat_FD1: 8 GWM + SG_ DrvBhavWarn_B_Rq : 12|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ OfbChrgSetSync_D_Rq : 1|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ KeyOffPwMde_D_Stat : 15|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ModemReset_D_Stat : 5|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ FactoryReset_St : 7|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 1833 TesterPhysicalResVDM: 64 VDM + SG_ TesterPhysicalResVDM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 570 Suspension_Data: 8 VDM + SG_ SuspClkSync_No_Rq : 63|8@0+ (1,0) [0|253] "unitless" GWM + SG_ SuspRearRight_L_Actl : 42|9@0+ (0.782779,-200) [-200|199.21729] "millimeter" GWM + SG_ SuspFrntRight_L_Actl : 35|9@0+ (0.782779,-200) [-200|199.21729] "millimeter" GWM + SG_ SuspRear_L_Prev : 28|9@0+ (0.782779,-200) [-200|199.21729] "millimeter" GWM + SG_ SuspRear_L_Actl : 21|9@0+ (0.782779,-200) [-200|199.21729] "millimeter" GWM + SG_ SuspFrnt_L_Prev : 14|9@0+ (0.782779,-200) [-200|199.21729] "millimeter" GWM + SG_ SuspFrnt_L_Actl : 7|9@0+ (0.782779,-200) [-200|199.21729] "millimeter" GWM + +BO_ 837 VeyDynamics_Data: 8 VDM + SG_ Ccd_B_Falt : 24|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdeSusp_D_Stat : 20|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdptDrvMdePt_D_Rq : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ AdptDrvMdeChassis_D_Rq : 10|3@0+ (1,0) [0|7] "SED" GWM + SG_ CcdMsgTxt_D_RqDsply : 7|4@0+ (1,0) [0|15] "SED" ECM_Diesel,GWM + +BO_ 885 ECG_Data3_FD1: 8 GWM + SG_ BattULoChrg_D_RqOta : 55|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ VehStrtInhbt_T_Dsply : 39|16@0+ (1,0) [0|65535] "second" Vector__XXX + SG_ VehStrtInhbt_D_Dsply : 27|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ VehOnRqstr_D_Stat : 21|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ VehStrtInhbt_D_RqCld : 23|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ VehOn_D_RqCld : 17|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ CanMsg375_No_Cnt : 11|4@0+ (1,0) [0|15] "unitless" Vector__XXX + SG_ CanMsg375_No_Crc : 7|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ OtaActv_D_Stat : 31|4@0+ (1,0) [0|15] "SED" Vector__XXX + +BO_ 1150 LocationServices_Data1_FD1: 8 GWM + SG_ LocationServices_1 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" SOBDMC_HPCM_FD1,IPMA_ADAS + +BO_ 542 LocationServices_3_FD1: 8 GWM + SG_ LocationServices_3 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" Vector__XXX + +BO_ 2612224016 PARSEDPushPCMtoGWM_ECG: 8 PCM_HEV + SG_ PARSEDPushPCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 810 ECG_Data_FD1: 8 GWM + SG_ OBCCSerial_D_Rq : 45|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TlghtTest_D_RqArb : 47|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ChrgrPncSustn_B_Rq : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ NtfyDrvTrgtDist_L_Rq : 23|12@0+ (0.1,0) [0.1|409.4] "Km" SOBDMC_HPCM_FD1 + SG_ NtfyDrvSocLvl1_Pc_Rq : 39|7@0+ (1,0) [1|100] "%" SOBDMC_HPCM_FD1 + SG_ PtRmtRprt_D_Stat : 27|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ ChrgrPncEnbl_D_Rq : 9|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ExtLghtDsply_B_StatArb : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ExtLghtRight_D_RqOta : 12|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ExtLghtRear_D_RqOta : 15|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ExtLghtLeft_D_RqOta : 3|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ExtLghtFront_D_RqOta : 6|3@0+ (1,0) [0|7] "SED" Vector__XXX + +BO_ 550 ECG_Data4_FD1: 8 GWM + SG_ PtWakeupActv1_B_Rq : 7|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + +BO_ 639 OffBrdChrg_Signals2: 8 GWM + SG_ OfbChrgPrflUpdate_B_Rq : 31|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgClearAll_B_Rq : 7|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTTouch_D_Rq : 17|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTPrcond_D_Rq : 19|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTOn_D_Rq : 10|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTMnte_D_Rq : 23|4@0+ (1,0) [0|15] "minute" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTHr_T_Rq : 15|5@0+ (1,0) [0|29] "hour" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTExtHtr_D_Rq : 1|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTElement_D_Rq : 5|4@0+ (1,0) [0|15] "Unitless" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTDelete_B_Rq : 6|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgGoTUpdate_B_Rq : 8|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + +BO_ 530 OffBrdChrg_Signals: 8 GWM + SG_ OfbChrgLocIdTrgt_No_Rq : 7|4@0+ (1,0) [0|15] "Unitless" SOBDMC_HPCM_FD1 + SG_ OfbChrgToPcWknd_D_Actl : 58|3@0+ (1,0) [0|7] "percent" SOBDMC_HPCM_FD1 + SG_ OfbChrgToPcWkdy_D_Actl : 61|3@0+ (1,0) [0|7] "percent" SOBDMC_HPCM_FD1 + SG_ OfbChrgSetNow_D_Rq : 63|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgSetDelete_B_Rq : 2|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OfbChrgPrflWknd_No_Rq : 39|24@0+ (1,0) [0|16777215] "unitless" SOBDMC_HPCM_FD1 + SG_ OfbChrgPrflWkdy_No_Rq : 15|24@0+ (1,0) [0|16777215] "unitless" SOBDMC_HPCM_FD1 + SG_ OfbChrgLocIdUns_B_Rq : 3|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + +BO_ 1142 ConsTip_Data_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ConsTipV_No_Dsply : 49|10@0+ (0.1,0) [0|102.1] "percent" GWM + +BO_ 817 Locking_Systems_2_FD1: 8 GWM + SG_ ChildLckMde_B_Stat : 56|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ VehLckInd_D_Rq : 58|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ DrTgateOpen_B_Rq : 59|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DrTgateExtSwMde_B_Stat : 32|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Remote_Device_Feedback : 50|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ Veh_Lock_Requestor : 55|5@0+ (1,0) [0|31] "SED" Vector__XXX + SG_ R_Pwr_Sliding_Dr_Rqst : 36|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Power_Liftgate_Rqst : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Veh_Lock_EvNum : 47|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ Power_Decklid_Rqst : 1|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ L_Pwr_Sliding_Dr_Rqst : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Keyfob_Pad_Msg_Count : 15|8@0+ (1,0) [0|255] "Counts" Vector__XXX + SG_ Veh_Lock_Sub_Id : 63|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ Veh_Lock_Status : 34|2@0+ (1,0) [0|3] "SED" CMR_DSMC + SG_ ChildLck_D_Dsply : 7|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ WindowLockout_B_Stat : 35|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ RollCodeUnlock : 23|16@0+ (1,0) [0|65535] "Unitless" Vector__XXX + SG_ Lockmsgtxt_D_Rq : 39|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ FobComm_D_Stat : 5|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ LockInhibit : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 879 BCMC_Data_FD1: 8 GWM + SG_ WndwRearHeat_I_Actl : 7|11@0+ (0.1,0) [0|204.6] "ampere" ECM_Diesel + SG_ WndwRearHeat_D_Stat : 12|3@0+ (1,0) [0|7] "SED" ECM_Diesel + +BO_ 878 DCACA_Data4: 8 PCM_HEV + SG_ DcacGfciTest_B_Rq : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ DcacOut_Pw_DsplyMx : 23|10@0+ (10,0) [0|10220] "watts" GWM + SG_ DcacOut1_Pw_Dsply : 39|7@0+ (100,0) [0|12600] "watts" GWM + SG_ DcacOut2_Pw_Dsply : 47|7@0+ (100,0) [0|12600] "watts" GWM + SG_ DcacHw_D_Confg : 11|4@0+ (1,0) [0|15] "SED" GWM + SG_ DcacFaltMsgTxt_D_Rq : 15|4@0+ (1,0) [0|15] "SED" GWM + SG_ DcacLoFuelMsgTxt_D_Rq : 29|5@0+ (1,0) [0|31] "SED" GWM + SG_ DcacEngOnMsgTxt_D_Rq : 55|2@0+ (1,0) [0|3] "SED" GWM + SG_ DcacElPw_D_Stat : 2|2@0+ (1,0) [0|3] "SED" GWM + SG_ PwBedPnlEnbl_B_Rq : 3|1@0+ (1,0) [0|1] "SED" GWM + SG_ DcacOn_B_Rq : 4|1@0+ (1,0) [0|1] "SED" GWM + SG_ DcacSys_B_Falt : 5|1@0+ (1,0) [0|1] "SED" GWM + SG_ DcacLedCtl_D_Rq : 7|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 395 HeadUpDisplayReq_FD1: 8 GWM + SG_ SelDrvMdeCnfm_D_Stat : 35|2@0+ (1,0) [0|3] "SED" ABS_ESC + +BO_ 2611055832 PARSEDPhysGWM_ECGtoSODR: 8 GWM + SG_ PARSEDPhysGWM_ECGtoSODR : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2611054808 PARSEDPhysGWM_ECGtoSODL: 8 GWM + SG_ PARSEDPhysGWM_ECGtoSODL : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2611026136 PARSEDPhysGWM_ECGtoSODCMD: 8 GWM + SG_ PARSEDPhysGWM_ECGtoSODCMD : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2611025112 PARSEDPhysGWM_ECGtoSODCMC: 8 GWM + SG_ PARSEDPhysGWM_ECGtoSODCMC : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2610975960 PARSEDPhysGWM_ECGtoCCM: 8 GWM + SG_ PARSEDPhysGWM_ECGtoCCM : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2610007256 OTAPhysGWM_ECGtoSODR: 8 GWM + SG_ OTAPhysGWM_ECGtoSODR : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2610006232 OTAPhysGWM_ECGtoSODL: 8 GWM + SG_ OTAPhysGWM_ECGtoSODL : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2609977560 OTAPhysGWM_ECGtoSODCMD: 8 GWM + SG_ OTAPhysGWM_ECGtoSODCMD : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2609976536 OTAPhysGWM_ECGtoSODCMC: 8 GWM + SG_ OTAPhysGWM_ECGtoSODCMC : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2609927384 OTAPhysGWM_ECGtoCCM: 8 GWM + SG_ OTAPhysGWM_ECGtoCCM : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2611175523 PARSEDPhysSODRtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysSODRtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224099 PARSEDPushSODRtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysSODR2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2611175522 PARSEDPhysSODLtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysSODLtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224098 PARSEDPushSODLtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysSODL2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2611175494 PARSEDPhysSODCMDtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysSODCMDtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224070 PARSEDPushSODCMDtoGWM: 8 IPMA_ADAS + SG_ PARSEDPhysSODCMD2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2611175493 PARSEDPhysSODCMCtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysSODCMCtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224069 PARSEDPushSODCMCtoGWM: 8 IPMA_ADAS + SG_ PARSEDPhysSODCMC2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2611175445 PARSEDPhysCCMtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysCCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224021 PARSEDPushCCMtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysCCM2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126947 OTAPhysSODRtoGWM_ECG: 8 IPMA_ADAS + SG_ OTAPhysSODRtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126946 OTAPhysSODLtoGWM_ECG: 8 IPMA_ADAS + SG_ OTAPhysSODLtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126918 OTAPhysSODCMDtoGWM_ECG: 8 IPMA_ADAS + SG_ OTAPhysSODCMDtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126917 OTAPhysSODCMCtoGWM_ECG: 8 IPMA_ADAS + SG_ OTAPhysSODCMCtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126869 OTAPhysCCMtoGWM_ECG: 8 IPMA_ADAS + SG_ OTAPhysCCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 984 IPMA_Data: 8 IPMA_ADAS + SG_ FeatConfigIpmaActl : 7|16@0+ (1,0) [0|65535] "Undefined" GWM + SG_ FeatNoIpmaActl : 23|16@0+ (1,0) [0|65535] "Number" GWM + SG_ PersIndexIpma_D_Actl : 39|3@0+ (1,0) [0|7] "SED" GWM + SG_ AhbcRampingV_D_Rq : 57|2@0+ (1,0) [0|3] "SED" GWM + SG_ LaActvStats_D_Dsply : 55|5@0+ (1,0) [0|31] "SED" GWM + SG_ LaDenyStats_B_Dsply : 32|1@0+ (1,0) [0|1] "SED" GWM + SG_ LaHandsOff_D_Dsply : 50|2@0+ (1,0) [0|3] "SED" GWM + SG_ CamraDefog_B_Req : 36|1@0+ (1,0) [0|1] "SED" GWM + SG_ CamraStats_D_Dsply : 35|2@0+ (1,0) [0|3] "SED" GWM + SG_ DasAlrtLvl_D_Dsply : 42|3@0+ (1,0) [0|7] "SED" GWM + SG_ DasStats_D_Dsply : 47|2@0+ (1,0) [0|3] "SED" GWM + SG_ DasWarn_D_Dsply : 44|2@0+ (1,0) [0|3] "SED" GWM + SG_ AhbHiBeam_D_Rq : 59|2@0+ (1,0) [0|3] "SED" GWM + SG_ Passthru_63 : 63|4@0+ (1,0) [0|15] "" XXX + SG_ Passthru_48 : 48|1@0+ (1,0) [0|1] "" XXX + +BO_ 985 IPMA_Data2: 8 IPMA_ADAS + SG_ LdwChime_B_Rq : 34|1@0+ (1,0) [0|1] "SED" GWM + SG_ TsrRegionTxt_D_Stat : 47|5@0+ (1,0) [0|31] "SED" GWM + SG_ SblmPedCrossScnr_B_Stat : 33|1@0+ (1,0) [0|1] "SED" GWM + SG_ LongCtrlEnbl_D_Rq : 42|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ SblmRndAbtScnr_B_Stat : 9|1@0+ (1,0) [0|1] "SED" GWM + SG_ DasAlrtInfo_D_Dsply : 13|2@0+ (1,0) [0|3] "SED" GWM + SG_ IaccVLim_D_Rq : 23|8@0+ (1,0) [0|255] "SED" ECM_Diesel,GWM + SG_ IaccVLimUnit_D_Rq : 11|2@0+ (1,0) [0|3] "SED" ECM_Diesel,GWM + SG_ IsaVLim_D_Rq : 7|8@0+ (1,0) [0|255] "SED" ECM_Diesel,GWM + SG_ SblmStopScnr_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ SblmYieldScnr_B_Stat : 31|1@0+ (1,0) [0|1] "SED" GWM + SG_ IsaVLimUnit_D_Rq : 15|2@0+ (1,0) [0|3] "SED" ECM_Diesel,GWM + SG_ AdbDividedRoad_B_Stat : 30|1@0+ (1,0) [0|1] "SED" GWM + SG_ LcwaMsgTxt_D_Stat : 37|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbDrvSide_B_Stat : 35|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 992 Personality_Data_FD1: 8 GWM + SG_ MsgCntrDsplyOp_D_Rq : 36|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ MsgCntrFeatNoRq : 7|16@0+ (1,0) [0|65535] "Number" IPMA_ADAS + SG_ MsgCntrFeatConfigRq : 23|16@0+ (1,0) [0|65535] "unitless" IPMA_ADAS + SG_ MsgCntrPersIndex_D_Rq : 39|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + +BO_ 2612019416 PARSEDPushFcGWM_ECGtoPCM: 8 GWM + SG_ PARSEDPhysGWM_ECG2toPCM : 7|29@0+ (1,0) [0|536870911] "unitless" PCM,PCM_HEV,ECM_Diesel + +BO_ 943 IPMA_Data4: 8 IPMA_ADAS + SG_ VehVActlAdas_D_Qf : 9|2@0+ (1,0) [0|3] "SED" PCM,PCM_HEV,ECM_Diesel + SG_ Veh_V_RqLsc : 23|14@0+ (0.01,0) [0|163.83] "kph" PCM,PCM_HEV,ECM_Diesel + SG_ Veh_V_ActlAdas : 7|14@0+ (0.01,0) [0|163.83] "kph" PCM,PCM_HEV,ECM_Diesel + SG_ AdasLcDistToObj_L_Actl : 39|12@0+ (0.002,0) [0|8.186] "meter" PCM,PCM_HEV,ECM_Diesel + +BO_ 515 PowertrainData_12: 8 ECM_Diesel + SG_ PtIgnSwtch_No_Cs : 15|8@0+ (1,0) [0|255] "Unitless" GWM + SG_ PtIgnSwtch_No_Cnt : 5|4@0+ (1,0) [0|15] "Unitless" GWM + SG_ PtIgnSwtch_D_Stat : 7|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 1111 TrailerAid_Stat2_FD1: 8 GWM + SG_ TrlrYawWActl_D_Qf : 43|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,PSCM + SG_ TrlrYaw_W_Actl : 7|16@0+ (0.0002,-6.5) [-6.5|6.6066] "radians/second" IPMA_ADAS,PSCM + SG_ TrlrHitYaw_AnRate_Actl : 27|12@0+ (0.1,-50) [-50|359.3] "degrees/second" IPMA_ADAS,PSCM + SG_ TrlrHitchYaw_D_Stat : 47|4@0+ (1,0) [0|15] "SED" IPMA_ADAS,PSCM + SG_ TrlrHitchYaw_An_Actl : 23|12@0+ (0.1,-90) [-90|319.3] "degrees" IPMA_ADAS,PSCM + +BO_ 1106 TrailerAid_Stat1_FD1: 8 GWM + SG_ TrlrSnsId_No_Actl : 7|48@0+ (1,0) [0|281474976710653] "unitless" IPMA_ADAS,PSCM + +BO_ 1985 TesterPhysicalReqCMR_DSMC: 64 TSTR + SG_ TesterPhysicalReqCMR_DSMC : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" CMR_DSMC + +BO_ 1993 TesterPhysicalResCMR_DSMC: 64 CMR_DSMC + SG_ TesterPhysicalResCMR_DSMC : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1104 DrvStatMonData: 8 CMR_DSMC + SG_ DrvEngageLevel_No_Cs : 31|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS + SG_ DrvEngageLevel_No_Cnt : 19|4@0+ (1,0) [0|15] "Unitless" IPMA_ADAS + SG_ DrvEngageLevel_D_Stat : 13|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ DrvImpLvlConfid_D_Stat : 39|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ DrvImpairLvl_D_Stat : 23|4@0+ (1,0) [0|15] "SED" IPMA_ADAS + SG_ DrvEngLvlConfid_D_Stat : 10|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ DrvCamPassIR_D_Stat : 36|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ DrvCamera_D_Stat : 15|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ DrvCamDrvIR_D_Stat : 1|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ DrvAttentZone_D_Stat : 5|4@0+ (1,0) [0|15] "SED" IPMA_ADAS + SG_ DrvAlertSt_D_Stat : 7|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + +BO_ 1503 CMR_DSMC_AutoSar_NetwrkMgt: 8 CMR_DSMC + SG_ CMR_DSMC_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_GWNMProxY : 47|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_AutoSarNMReserved : 63|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_AutoSarNMReserve4 : 55|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_AutoSarNMReserve3 : 31|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_AutoSarNMReserve2 : 23|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CMR_DSMC_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" Vector__XXX + +BO_ 2610995416 PARSEDPhysGWM_ECGtoABS: 8 GWM + SG_ PARSEDPhysGWM_ECGtoABS : 7|29@0+ (1,0) [0|536870911] "unitless" ABS_ESC + +BO_ 2612043992 PARSEDPushFcGWM_ECGtoABS: 8 GWM + SG_ PARSEDPhysGWM_ECG2toABS : 7|29@0+ (1,0) [0|536870911] "unitless" ABS_ESC + +BO_ 2609946840 OTAPhysGWM_ECGtoABS: 8 GWM + SG_ OTAPhysGWM_ECGtoABS : 7|29@0+ (1,0) [0|536870911] "unitless" ABS_ESC + +BO_ 2611175464 PARSEDPhysABStoGWM_ECG: 8 ABS_ESC + SG_ PARSEDPhysABStoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "Unitless" GWM + +BO_ 2612224040 PARSEDPushABStoGWM_ECG: 8 ABS_ESC + SG_ PARSEDPhysABS2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126888 OTAPhysABStoGWM_ECG: 8 ABS_ESC + SG_ OTAPhysABStoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610988248 PARSEDPhysGWM_ECGtoIPMA: 8 GWM + SG_ PARSEDPhysGWM_ECGtoIPMA : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 2609939672 OTAPhysGWM_ECGtoIPMA: 8 GWM + SG_ OTAPhysGWM_ECGtoIPMA : 7|29@0+ (1,0) [0|536870911] "unitless" IPMA_ADAS + +BO_ 1114 TrailerAid_Data_FD1: 8 GWM + SG_ TrailCtlSwtch_B_Stat2 : 16|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ TrlBrkInitOut_D_Rq : 60|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 1116 TrailerAid_Data3_FD1: 8 GWM + SG_ TrlrAidSetup_D2_Rq : 4|4@0+ (1,0) [0|15] "SED" IPMA_ADAS,PSCM + SG_ TrlrAidEnbl_D2_Rq : 7|3@0+ (1,0) [0|7] "SED" IPMA_ADAS,PSCM + SG_ TrlrTrgtToBmpr_L_Actl : 38|7@0+ (0.0127,0) [0|1.6129] "meter" IPMA_ADAS + SG_ TrlrTrgtPtrnId_No_Mem : 45|6@0+ (1,0) [0|63] "unitless" IPMA_ADAS + SG_ TrlrRvrseCancl_B_Rq : 0|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,PSCM + SG_ TrlrIdType_D_Stat : 51|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,PSCM + SG_ TrlrId_No_Actl : 55|4@0+ (1,0) [0|15] "unitless" IPMA_ADAS,PSCM + SG_ TrlrBallToBmpr_L_Actl : 22|7@0+ (0.0127,0) [0|1.6129] "meter" IPMA_ADAS,PSCM + SG_ TrlrAxleToBmpr_L_Actl : 31|9@0+ (0.0254,0) [0|12.9794] "meter" IPMA_ADAS,PSCM + SG_ TrlrAnOffstDir_D_Mem : 47|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,PSCM + SG_ TrlrAnOffst_An_Mem : 15|9@0+ (0.1,0) [0|51.1] "degrees" IPMA_ADAS + SG_ TrlrTrgtOffst_L_Actl : 63|7@0+ (0.0127,0) [0|1.6129] "meter" IPMA_ADAS + +BO_ 2611175457 PARSEDPhysIPMAtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysIPMAtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224033 PARSEDPushIPMAtoGWM_ECG: 8 IPMA_ADAS + SG_ PARSEDPhysIPMA2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126881 OTAPhysIPMAtoGWM_ECG: 8 IPMA_ADAS + SG_ OTAPhysIPMAtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 1085 Low_Voltage_Power_Data_FD1: 8 PCM + SG_ ULoRgenTestMde_B_Stat : 50|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwSrcULoOvrTe_B_Actl : 7|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwSrcULoFalt_D_Stat : 5|2@0+ (1,0) [0|3] "SED" GWM + SG_ PwSrcULoDcnnt_B_Stat : 3|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwSrcULo_Pc_Mx : 31|8@0+ (0.4,0) [0|101.6] "%" GWM + SG_ PwSrcULoComm_B_Falt : 2|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwSrcULo_I_Mx : 23|8@0+ (1,0) [0|254] "ampere" PCM_HEV,GWM + SG_ PwSrcULo_I_Actl : 15|8@0+ (1,0) [0|254] "ampere" PCM_HEV,GWM + +BO_ 791 Cluster_HEV_Data8_FD1: 8 GWM + SG_ EngAirFilt_B_RqReset : 48|1@0+ (1,0) [0|1] "SED" ECM_Diesel + SG_ GpsElMdeSel_B_Rq : 50|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ LongTermReset_B_Rq : 49|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DrvEffLvl_No_Stat : 61|6@0+ (1,0) [0|61] "unitless" Vector__XXX + SG_ ConsAvgTrip_Fe_Dsply : 31|24@0+ (0.0001,0) [0|1677.7215] "litre/100km" Vector__XXX + +BO_ 2610970840 PARSEDPhysGWM_ECGtoPCM: 8 GWM + SG_ PARSEDPhysGWM_ECGtoPCM : 7|29@0+ (1,0) [0|536870911] "unitless" ECM_Diesel,PCM_HEV,PCM + +BO_ 2609922264 OTAPhysGWM_ECGtoPCM: 8 GWM + SG_ OTAPhysGWM_ECGtoPCM : 7|29@0+ (1,0) [0|536870911] "unitless" ECM_Diesel,PCM_HEV,PCM + +BO_ 868 BattRgenLo_4_FD1: 8 GWM + SG_ BattRgenLoStat_D_Qlty : 25|2@0+ (1,0) [0|3] "SED" PCM_HEV,PCM + SG_ BattRgenLoSoc_Pc_Actl : 23|7@0+ (1,0) [0|100] "percent" PCM_HEV,PCM + SG_ BattRgenLoPulse_U_Pred : 15|8@0+ (0.0625,0) [0|15.9375] "volt" PCM_HEV,PCM + SG_ BattRgenLoPrtct_B_Stat : 39|1@0+ (1,0) [0|1] "SED" PCM_HEV,PCM + SG_ BattRgenLoDChrg_D_Stat : 27|2@0+ (1,0) [0|3] "SED" PCM_HEV,PCM + SG_ BattRgenLoDchrg_B_Rq : 28|1@0+ (1,0) [0|1] "SED" PCM_HEV,PCM + SG_ BattRgenLoChrg_D_Stat : 30|2@0+ (1,0) [0|3] "SED" PCM_HEV,PCM + SG_ BattRgenLoChrg_B_Rq : 31|1@0+ (1,0) [0|1] "SED" PCM_HEV,PCM + SG_ BattRgenLo_T_Est : 7|8@0+ (8,0) [0|2040] "second" PCM_HEV,PCM + SG_ BattRgenLo_B_Falt : 16|1@0+ (1,0) [0|1] "SED" PCM_HEV,PCM + +BO_ 867 BattRgenLo_3_FD1: 8 GWM + SG_ BattRgenLoBalnc_B_Rq : 16|1@0+ (1,0) [0|1] "SED" PCM_HEV,PCM + SG_ BattRgenLo_Te_Hi : 55|8@0+ (1,-20) [-20|235] "degC" PCM_HEV,PCM + SG_ BattRgenLo_Te_Actl : 47|8@0+ (1,-60) [-60|194] "degC" PCM_HEV,PCM + SG_ BattRgenLo_R_Actl : 31|9@0+ (0.0625,0) [0|31.9375] "milliohm" PCM_HEV,PCM + SG_ BattRgenLo_AhRide_Actl : 15|15@0+ (0.0078125,-100) [-100|155.9921875] "amperehour" PCM_HEV,PCM + SG_ BattRgenLo_Ah_Actl : 7|8@0+ (0.1,0) [0|25.5] "amperehour" PCM_HEV,PCM + +BO_ 866 BattRgenLo_2_FD1: 8 GWM + SG_ BattRgenLoOpen_U_Actl : 55|9@0+ (0.025,8.5) [8.5|21.275] "volt" PCM_HEV,PCM + SG_ BattRgenLoDchrg_U_Mn : 39|9@0+ (0.025,4) [4|16.775] "volt" PCM_HEV,PCM + SG_ BattRgenLoDchrg_I_Mx : 31|8@0+ (2,0) [0|510] "ampere" PCM_HEV,PCM + SG_ BattRgenLoChrg_U_Mx : 15|9@0+ (0.025,10.6) [10.6|23.375] "volt" PCM_HEV,PCM + SG_ BattRgenLoChrg_I_Mx : 7|8@0+ (2,0) [0|510] "ampere" PCM_HEV,PCM + +BO_ 865 BattRgenLo_1_FD1: 8 GWM + SG_ BattRgenLo_U_Actl : 23|11@0+ (0.015625,0) [0|31.96875] "volt" PCM_HEV,PCM + SG_ BattRgenLo_I_Actl : 7|16@0+ (0.015625,-512) [-512|511.96875] "ampere" PCM_HEV,PCM + +BO_ 2611175440 PARSEDPhysPCMtoGWM_ECG: 8 PCM + SG_ PARSEDPhysPCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126864 OTAPhysPCMtoGWM_ECG: 8 PCM + SG_ OTAPhysPCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2611175441 PARSEDHPCMtoGWM_ECG_FD1: 8 SOBDMC_HPCM_FD1 + SG_ PARSEDPhysHPCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2612224017 PARSEDPushSOBDMCtoGWM_FD1: 8 SOBDMC_HPCM_FD1 + SG_ PARSEDPhysHPCM2toGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 2610126865 OTAPhysSOBDMCtoGWM_FD1: 8 SOBDMC_HPCM_FD1 + SG_ OTAPhysHPCMtoGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" GWM + +BO_ 1679 SOBDMC_RapidData_Resp4_FD1: 8 SOBDMC_HPCM_FD1 + SG_ UUDTSOBDMCResponse4 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1678 SOBDMC_RapidData_Resp3_FD1: 8 SOBDMC_HPCM_FD1 + SG_ UUDTSOBDMCResponse3 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1677 SOBDMC_RapidData_Resp2_FD1: 8 SOBDMC_HPCM_FD1 + SG_ UUDTSOBDMCResponse2 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1676 SOBDMC_RapidData_Resp1_FD1: 8 SOBDMC_HPCM_FD1 + SG_ UUDTSOBDMCResponse1 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1445 SOBDMC_AutoSar_NetMgmt_FD1: 8 SOBDMC_HPCM_FD1 + SG_ SOBDMC_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ SOBDMC_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" Vector__XXX + +BO_ 1144 MHT_EV_Wakeup_FD1: 8 SOBDMC_HPCM_FD1 + SG_ WakeAlarm0_T_Rq : 7|15@0+ (1,0) [0|32767] "minute" GWM + SG_ WakeAlarm0_B_Typ : 21|1@0+ (1,0) [0|1] "SED" GWM + SG_ PreCondBatt_B_Actl : 32|1@0+ (1,0) [0|1] "SED" GWM + SG_ HtrnDcdcDis_B_Rq : 26|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgNowEvnt_B_Stat : 22|1@0+ (1,0) [0|1] "SED" GWM + SG_ CabinDrvSustn_B_Rq : 23|1@0+ (1,0) [0|1] "SED" GWM + SG_ BattChrgTrgtSoC_D_Rq : 35|3@0+ (1,0) [0|7] "Percent" GWM + SG_ CabnEvapSovFront_B_Rq : 38|1@0+ (1,0) [0|1] "SED" GWM + SG_ HeatCoreSovRear_B_Rq : 36|1@0+ (1,0) [0|1] "SED" GWM + SG_ BattChlrSov_B_Rq : 39|1@0+ (1,0) [0|1] "SED" GWM + SG_ CabnEvapSovRear_B_Rq : 37|1@0+ (1,0) [0|1] "SED" GWM + SG_ BrkAppl_D_RqPt : 25|2@0+ (1,0) [0|3] "SED" GWM + SG_ HtrnCnnctPwr_B_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ PtcHtr_D_Stat : 18|2@0+ (1,0) [0|3] "SED" GWM,PCM_HEV + SG_ HtrnClntFlw_D_Rq : 20|2@0+ (1,0) [0|3] "SED" GWM + SG_ BattTracDrvSustn_B_Rq : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BattTracClntVlv_B_Rq : 47|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 1141 Cluster_HEV_Data9_FD1: 8 SOBDMC_HPCM_FD1 + SG_ OfbChrgSetSync_D_Stat : 31|2@0+ (1,0) [0|3] "SED" GWM + SG_ PtRmtRprt_D_Rq : 59|4@0+ (1,0) [0|15] "SED" GWM + SG_ MtrTrac2_Tq_Actl : 29|12@0+ (1,-2047) [-2047|2048] "Nm" GWM + SG_ NtfctnConflict1_D_Rq : 53|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 1140 Cluster_HEV_Data7_FD1: 8 SOBDMC_HPCM_FD1 + SG_ RgenEvntLvl_Pc_Dsply : 9|10@0+ (0.1,0) [0|102.1] "percent" GWM + SG_ BrkEvntComplt_B_Dsply : 31|1@0+ (1,0) [0|1] "SED" GWM + SG_ PreCondStat_D_Dsply : 12|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 1139 GWM_HPCM_i_FrP11_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ActChrgStrtYr_No2_Actl : 7|7@0+ (1,2017) [2017|2144] "year" GWM + SG_ BattChrgTrgtLMax_T_Est : 10|11@0+ (1,0) [0|2045] "minute" GWM + SG_ ActChrgStrtYr_No_Actl : 60|5@0+ (1,2010) [2010|2040] "year" GWM + SG_ ActChrgStrtMin_No_Actl : 29|6@0+ (1,0) [0|61] "minute" GWM + SG_ ActChrgStrtHr_No_Actl : 36|5@0+ (1,0) [0|29] "hour" GWM + SG_ ActChrgStrtDay_No_Actl : 44|5@0+ (1,1) [1|31] "days" GWM + SG_ ActChrgStrMnth_No_Actl : 51|4@0+ (1,1) [1|15] "month" GWM + +BO_ 1138 GWM_HPCM_i_FrP10_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ActChrgEndYr_No2_Actl : 7|7@0+ (1,2017) [2017|2144] "year" GWM + SG_ BattChrgTrgtLMin_T_Est : 10|11@0+ (1,0) [0|2045] "minute" GWM + SG_ ActChrgEndYr_No_Actl : 60|5@0+ (1,2010) [2010|2040] "year" GWM + SG_ ActChrgEndMnth_No_Actl : 51|4@0+ (1,1) [1|15] "month" GWM + SG_ ActChrgEndMin_No_Actl : 29|6@0+ (1,0) [0|61] "minute" GWM + SG_ ActChrgEndHr_No_Actl : 36|5@0+ (1,0) [0|29] "hour" GWM + SG_ ActChrgEndDay_No_Actl : 44|5@0+ (1,1) [1|31] "days" GWM + +BO_ 1089 MtrTracData_1_FD1: 8 SOBDMC_HPCM_FD1 + SG_ Mtr2Aout_W_ActlMntr : 45|10@0+ (6.28,-3209) [-3209|3209.16] "radians/sec" GWM + SG_ Inv1_Te_Actl : 63|8@0+ (1,-40) [-40|213] "degC" GWM + SG_ MtrTrac2Coil_Te_Actl : 23|8@0+ (1,-40) [-40|213] "degC" GWM + SG_ MtrTrac2_U_Actl : 39|10@0+ (1,0) [0|1023] "volt" GWM + SG_ MtrTrac2Falt_B_Stat : 50|1@0+ (1,0) [0|1] "SED" GWM + SG_ MtrTrac2TeAlrm_B_Stat : 49|1@0+ (1,0) [0|1] "SED" GWM + SG_ Mtr2CntlTeAlrm_B_Stat : 51|1@0+ (1,0) [0|1] "SED" GWM + SG_ MtrTrac2Inv_Te_Actl : 31|8@0+ (1,-40) [-40|213] "degC" GWM + SG_ MtrTrac2_I_Actl : 7|16@0+ (0.1,-1000) [-1000|5553.4] "ampere" GWM + +BO_ 1088 PreCond_Hev_Data1_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ChrgTMatch_B_Stat : 55|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgStat_D2_Dsply : 7|4@0+ (1,0) [0|15] "SED" GWM + SG_ HvacPrecondRecirc_D_Rq : 63|2@0+ (1,0) [0|3] "SED" GWM + SG_ HvacPrecondMode2_D_Rq : 51|4@0+ (1,0) [0|15] "SED" GWM + SG_ HvacPrecondBlwr2_D_Rq : 61|4@0+ (1,0) [0|15] "SED" GWM + SG_ HvacPrecondAC_D_Rq : 57|2@0+ (1,0) [0|3] "SED" GWM + SG_ HvacPrecond_Te_Rq : 44|5@0+ (0.5,14.5) [14.5|30] "deg C" GWM + SG_ BattChrgInhbt_D_Rq : 53|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 1040 AC_Compressor_Req_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ElCmprEnbl_B_Rq : 23|1@0+ (1,0) [0|1] "SED" GWM,PCM_HEV + SG_ ElCmpr_N_Rq : 15|8@0+ (50,0) [0|12750] "RPM" GWM + +BO_ 1016 GoTimeSettings_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ChrgGoTElement_B_Dsply : 27|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocIdCurnt_D_Uns : 31|4@0+ (1,0) [0|15] "unitless" GWM + SG_ ChrgGoTTouchEnbl_B_Rq : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgGoTTouch_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgGoTPrcond_D_Stat : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ ChrgGoTNext_D_Stat : 19|4@0+ (1,0) [0|15] "Unitless" GWM + SG_ ChrgGoTMnte_D_Stat : 23|4@0+ (1,0) [0|15] "SED" GWM + SG_ ChrgGoTHr_T_Stat : 15|5@0+ (1,0) [0|29] "hour" GWM + SG_ ChrgGoTExtHtrEnbl_B_Rq : 1|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgGoTExtHtr_B_Stat : 2|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgGoTElement_D_Stat : 6|4@0+ (1,0) [0|15] "Unitless" GWM + SG_ ChrgGoTAllOn_B_Stat : 7|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 1013 ChargeSettings_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ChrgToPcWkndSav_D_Stat : 60|3@0+ (1,0) [0|7] "SED" GWM + SG_ ChrgToPcWkdySav_D_Stat : 63|3@0+ (1,0) [0|7] "SED" GWM + SG_ ChrgProgIdSaved_D_Stat : 51|4@0+ (1,0) [0|15] "Unitless" GWM + SG_ ChrgNowEnbl_B_Saved : 56|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocIdUnsAck_B_Stat : 57|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocIdCurnt_D_Sav : 55|4@0+ (1,0) [0|15] "unitless" GWM + SG_ ChrgPrflWknd_No_Actl : 31|24@0+ (1,0) [0|16777215] "unitless" GWM + SG_ ChrgPrflWkdy_No_Actl : 7|24@0+ (1,0) [0|16777215] "unitless" GWM + +BO_ 1012 Saved_Charge_Location_FD1: 8 SOBDMC_HPCM_FD1 + SG_ ChrgNowCurnt_B_Dsply : 58|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocSaved_B_Dsply : 57|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocLongPostv_B_Sav : 59|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocLongFrct_An_Sav : 47|20@0+ (1E-006,0) [0|1.048575] "degrees" GWM + SG_ ChrgLocLongDeg_An_Sav : 39|8@0+ (1,0) [0|255] "degrees" GWM + SG_ ChrgLocLattPostv_B_Sav : 24|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocLattFrct_An_Sav : 7|20@0+ (1E-006,0) [0|1.048575] "degrees" GWM + SG_ ChrgLocLattDeg_An_Sav : 31|7@0+ (1,0) [0|127] "unitless" GWM + SG_ ChrgLocId_D_Sav : 19|4@0+ (1,0) [0|15] "unitless" GWM + +BO_ 1011 Unsaved_Charge_LocationFD1: 8 SOBDMC_HPCM_FD1 + SG_ ChrgLocLongPostv_B_Uns : 59|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocLongFrct_An_Uns : 47|20@0+ (1E-006,0) [0|1.048575] "degrees" GWM + SG_ ChrgLocLongDeg_An_Uns : 39|8@0+ (1,0) [0|255] "degrees" GWM + SG_ ChrgLocLattPostv_B_Uns : 24|1@0+ (1,0) [0|1] "SED" GWM + SG_ ChrgLocLattFrct_An_Uns : 7|20@0+ (1E-006,0) [0|1.048575] "degrees" GWM + SG_ ChrgLocLattDeg_An_Uns : 31|7@0+ (1,0) [0|127] "unitless" GWM + SG_ ChrgLocId_D_Uns : 19|4@0+ (1,0) [0|15] "unitless" GWM + +BO_ 871 Cluster_HEV_Data4_FD1: 8 SOBDMC_HPCM_FD1 + SG_ BattElecPerf_D_Actl : 55|3@0+ (1,0) [0|7] "SED" GWM + SG_ BattChrgTrgtLPt_T_Est : 2|11@0+ (1,0) [0|2045] "minute" GWM + SG_ BattChrgTrgSocPt_T_Est : 18|11@0+ (1,0) [0|2045] "minute" GWM + SG_ BattChrgCmpltPt_T_Est : 34|11@0+ (1,0) [0|2045] "minute" GWM + +BO_ 786 Cluster_HEV_Data1_FD1: 8 SOBDMC_HPCM_FD1 + SG_ RgenTrip_Pc_Dsply : 33|10@0+ (0.1,0) [0|102.3] "percent" GWM + SG_ RgenTrip_L_Dsply : 55|16@0+ (0.1,0) [0|6553.3] "kilometer" GWM + SG_ ChrgStat_D_Dsply : 36|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 72 Global_PATS_Target2_FD1: 8 SOBDMC_HPCM_FD1 + SG_ immoTarget2Status : 7|3@0+ (1,0) [0|7] "SED" GWM + SG_ immoTarget2Data : 15|40@0+ (1,0) [0|1099511627775] "Encrypted" GWM + SG_ immoTarget2Cmd : 4|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 912 PowerDist_Data1_FD1: 8 GWM + SG_ CabnEvapSovFront_D_Stat : 15|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + SG_ BattChlrSov_D_Stat : 7|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracClntVlv_D_Stat : 28|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + +BO_ 874 PowerDistData_2_FD1: 8 GWM + SG_ AirCondCluOpen_D_Falt : 17|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ AirCondCluLife_D_Falt : 19|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ AirCondCluGnd_D_Falt : 21|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ AirCondClu_D_Stat : 31|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ AirCondCluBatt_D_Falt : 23|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ BattTracShrtGrnd_D_Falt : 9|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracShrtBatt_D_Falt : 11|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracOpnCirct_D_Falt : 13|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracLifeLim_D_Falt : 15|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattChlrShrtGrnd_D_Falt : 1|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattChlrShrtBatt_D_Falt : 3|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattChlrOpnCirct_D_Falt : 5|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattChlrLifeLim_D_Falt : 7|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracLow_D_Falt : 28|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + +BO_ 651 TCU_Send_Signals_FD1: 8 GWM + SG_ TelematicsSrvc_D_St : 47|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + SG_ EmgcyCallMute_D_Stat : 39|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ OfbChrgSetSync_D_Rq : 3|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 529 APIM_Request_Signals_5_FD1: 8 GWM + SG_ OnbChrgToPcWknd_D_Actl : 2|3@0+ (1,0) [0|7] "percent" SOBDMC_HPCM_FD1 + SG_ OnbChrgToPcWkdy_D_Actl : 60|3@0+ (1,0) [0|7] "percent" SOBDMC_HPCM_FD1 + SG_ OnbChrgSetNow_D_Rq : 63|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgSetDelete_B_Rq : 3|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgPrflWknd_No_Rq : 39|24@0+ (1,0) [0|16777215] "unitless" SOBDMC_HPCM_FD1 + SG_ OnbChrgPrflWkdy_No_Rq : 15|24@0+ (1,0) [0|16777215] "unitless" SOBDMC_HPCM_FD1 + SG_ OnbChrgPrflUpdate_B_Rq : 56|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgLocIdUns_B_Rq : 57|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgLocIdTrgt_No_Rq : 7|4@0+ (1,0) [0|15] "Unitless" SOBDMC_HPCM_FD1 + +BO_ 66 Global_PATS_Ctrl_Info2_FD1: 8 GWM + SG_ immoControlData_T2 : 15|40@0+ (1,0) [0|1099511627775] "Encrypted" SOBDMC_HPCM_FD1 + SG_ immoControlCmd_T2 : 7|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + +BO_ 2610971864 PARSEDPhysGWMtoSOBDMC_FD1: 8 GWM + SG_ PARSEDPhysGWM_ECGtoHPCM : 7|29@0+ (1,0) [0|536870911] "unitless" SOBDMC_HPCM_FD1 + +BO_ 2612002008 PARSEDFuncGWM_ECG_FD1: 8 GWM + SG_ PARSEDFuncGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" ABS_ESC,IPMA_ADAS,ECM_Diesel,PCM_HEV,PCM,SOBDMC_HPCM_FD1 + +BO_ 2609923288 OTAPhysGWM_ECGtoSOBDMC_FD1: 8 GWM + SG_ OTAPhysGWM_ECGtoHPCM : 7|29@0+ (1,0) [0|536870911] "unitless" SOBDMC_HPCM_FD1 + +BO_ 2610953432 OTAFuncGWM_ECG_FD1: 8 GWM + SG_ OTAFuncGWM_ECG : 7|29@0+ (1,0) [0|536870911] "unitless" ABS_ESC,IPMA_ADAS,ECM_Diesel,PCM_HEV,PCM,SOBDMC_HPCM_FD1 + +BO_ 2022 TesterPhysicalReqSOBDMC_FD: 64 TSTR + SG_ TesterPhysicalReqSOBDMC : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" SOBDMC_HPCM_FD1 + +BO_ 1124 APIMGPS_Data_Nav_3_FD1: 8 GWM + SG_ GPS_Vdop : 63|5@0+ (0.2,0) [0|5.8] "unitless" IPMA_ADAS + SG_ GPS_Speed : 47|8@0+ (1,0) [0|253] "MPH" Vector__XXX + SG_ GPS_Sat_num_in_view : 7|5@0+ (1,0) [0|29] "unitless" SOBDMC_HPCM_FD1 + SG_ GPS_MSL_altitude : 15|12@0+ (10,-20460) [-20460|20470] "feet" Vector__XXX + SG_ GPS_Heading : 31|16@0+ (0.01,0) [0|655.33] "Degrees" IPMA_ADAS + SG_ GPS_Hdop : 55|5@0+ (0.2,0) [0|5.8] "unitless" IPMA_ADAS + SG_ GPS_dimension : 2|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + +BO_ 1119 Voltage_Power_Data2_FD1: 8 GWM + SG_ CoolFanDcdc_D_Rq : 5|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ DcdcClntFlw_D_Rq : 7|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + +BO_ 132 GlobalClock_Data_FD1: 8 GWM + SG_ GlblClkYr_No_Actl : 7|8@0+ (1,2000) [2000|2255] "year" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GlblClkScnd_No_Actl : 47|8@0+ (1,0) [0|255] "second" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GlblClkMnte_No_Actl : 39|8@0+ (1,0) [0|255] "minute" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GlblClkHr_No_Actl : 55|8@0+ (1,0) [0|255] "hour" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GlblClkDay_No_Actl : 23|16@0+ (1,0) [0|65535] "julian day" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS + +BO_ 1990 TesterPhysicalReqSODR: 64 TSTR + SG_ TesterPhysicalReqSODR : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" IPMA_ADAS + +BO_ 1892 TesterPhysicalReqCCM: 64 TSTR + SG_ TesterPhysicalReqCCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" IPMA_ADAS + +BO_ 1798 TesterPhysicalReqIPMA: 64 TSTR + SG_ TesterPhysicalReqIPMA : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" IPMA_ADAS + +BO_ 1123 APIMGPS_Data_Nav_2_FD1: 8 GWM + SG_ GpsUtcYr_No_Actl : 55|5@0+ (1,2010) [2010|2040] "Year" IPMA_ADAS + SG_ GpsUtcMnth_No_Actl : 47|4@0+ (1,1) [1|15] "Month" IPMA_ADAS + SG_ GpsUtcDay_No_Actl : 37|5@0+ (1,1) [1|32] "Day" IPMA_ADAS + SG_ GPS_UTC_seconds : 23|6@0+ (1,0) [0|59] "seconds" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GPS_UTC_minutes : 15|6@0+ (1,0) [0|59] "Minutes" IPMA_ADAS + SG_ GPS_UTC_hours : 7|5@0+ (1,0) [0|23] "Hours" IPMA_ADAS + SG_ GPS_Pdop : 31|5@0+ (0.2,0) [0|5.8] "unitless" IPMA_ADAS + SG_ GPS_Compass_direction : 26|4@0+ (1,0) [0|15] "SED" IPMA_ADAS + SG_ GPS_Actual_vs_Infer_pos : 38|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ Gps_B_Falt : 2|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,IPMA_ADAS + +BO_ 1122 APIMGPS_Data_Nav_1_FD1: 8 GWM + SG_ GpsHsphLongEast_D_Actl : 9|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,SOBDMC_HPCM_FD1 + SG_ GpsHsphLattSth_D_Actl : 25|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,SOBDMC_HPCM_FD1 + SG_ GPS_Longitude_Minutes : 46|6@0+ (1,0) [0|61] "Minutes" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GPS_Longitude_Min_dec : 55|14@0+ (0.0001,0) [0|1.6381] "Minutes" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GPS_Longitude_Degrees : 39|9@0+ (1,-179) [-179|330] "Degrees" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GPS_Latitude_Minutes : 15|6@0+ (1,0) [0|61] "Minutes" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GPS_Latitude_Min_dec : 23|14@0+ (0.0001,0) [0|1.6381] "Minutes" SOBDMC_HPCM_FD1,IPMA_ADAS + SG_ GPS_Latitude_Degrees : 7|8@0+ (1,-89) [-89|164] "Degrees" SOBDMC_HPCM_FD1,IPMA_ADAS + +BO_ 1003 Personality_BCM2_Data_FD1: 8 GWM + SG_ PersRecallSrc_D_Actl : 63|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ Pers4Key_D_Stat : 49|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Pers3Key_D_Stat : 41|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Pers2Key_D_Stat : 43|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Pers1Key_D_Stat : 12|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ EmPrflNo_D_Stat : 52|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ EmPrflKeyAssoc_D_Stat : 55|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ VehKeyActv_D_Stat : 47|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ PersNoPos_D_Actl : 18|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ PersSetupRestr_D_Actl : 21|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PersSetupAccessCtrl : 19|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PersSetup_No_Actl : 31|16@0+ (1,0) [0|65535] "Number" Vector__XXX + SG_ PersConflict_D_Actl : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AssocConfirm_D_Actl : 15|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ RecallEvent_No_Cnt : 7|8@0+ (1,0) [0|255] "Counts" IPMA_ADAS + SG_ PersNo_D_Actl : 10|3@0+ (1,0) [0|7] "SED" ABS_ESC,IPMA_ADAS + +BO_ 994 Personality_APIM_Data_FD1: 8 GWM + SG_ PersStore_D_Rq : 36|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ Pers4OptIn_B_Stats : 43|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Pers3OptIn_B_Stats : 33|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Pers2OptIn_B_Stats : 32|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Pers1OptIn_B_Stats : 44|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CtrStkPersIndex_D_Actl : 39|3@0+ (1,0) [0|7] "SED" ABS_ESC,IPMA_ADAS + SG_ CtrStkFeatNoActl : 23|16@0+ (1,0) [0|65535] "Undefined" ABS_ESC,IPMA_ADAS + SG_ CtrStkFeatConfigActl : 7|16@0+ (1,0) [0|65535] "Undefined" ABS_ESC,IPMA_ADAS + SG_ CtrStkDsplyOp_D_Rq : 47|3@0+ (1,0) [0|7] "SED" ABS_ESC,IPMA_ADAS + +BO_ 778 ParkAid_Aud_Warn_CmdM_FD1: 8 GWM + SG_ PrkAidFront_D_RqDrv : 5|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ PrkAidAcsyRear_D_RqDrv : 13|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ PrkAidAcsyFront_D_RqDrv : 15|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ Cta_D_Rq : 1|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ PrkAidRear_D_RqDrv : 3|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ SteEffort_D_Rq : 10|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ Sod_D_Rq : 7|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + +BO_ 549 IPC_Infotainment_FD1: 8 GWM + SG_ Veh_V2_Dsply : 39|9@0+ (1,0) [0|511] "unitless" IPMA_ADAS + SG_ IPC_MyKeyVolLimit_St : 9|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ HdcOn_B_Rq : 19|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ IPC_Attn_Info_Audio : 4|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ BeltminderAudioMute : 6|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Power_Up_Chime_Modules : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Chime_Source : 15|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ IPC_New_Attn_Event : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 551 APIM_Request_Signals_1_FD1: 8 GWM + SG_ PmCabnLvl_D_Stat : 36|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ PmCabn_D_Stat : 38|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Cntr_Plg_Mode_Cmd : 39|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ChrgCrdLckEnbl_B_Stat : 47|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PwRnngBoardT_D_Rq : 25|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PwRnngBoardSwtch_D_Rq : 27|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PwRnngBoardMde_D_Rq : 29|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Btt_L_Actl2 : 55|7@0+ (0.1,0) [0|12.5] "meter" IPMA_ADAS + SG_ Rba_D_Rq : 31|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ EmPrflNo_D_Rq : 61|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ EmPrflButtnAssoc_D_Rq : 33|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ EmPrflKeyAssoc_D_Rq : 46|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ Em_D_Stat : 63|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ChrgOvrdExitScrn_D_Rq : 58|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 1010 IPMA_Data3: 8 IPMA_ADAS + SG_ MbdblActv_B_RqAdas : 48|1@0+ (1,0) [0|1] "SED" GWM + SG_ CbdblActv_B_RqAdas : 49|1@0+ (1,0) [0|1] "SED" GWM + SG_ AdbUrbanArea_B_Stat : 40|1@0+ (1,0) [0|1] "SED" GWM + SG_ LightRng_L_Max : 55|6@0+ (2,0) [0|126] "meter" GWM + SG_ LightPathOffst_L_Actl : 31|10@0+ (0.01,-5.12) [-5.12|5.11] "meter" GWM + SG_ LightPath_An_Actl : 12|11@0+ (0.0005,-0.5) [-0.5|0.5235] "radians" GWM + SG_ LightCurv_NoRate_Actl : 37|13@0+ (2.5E-007,-0.001024) [-0.001024|0.00102375] "1/meter" GWM + SG_ LightCurv_No_Actl : 7|11@0+ (2E-005,-0.02) [-0.02|0.02094] "1/meter" GWM + +BO_ 1070 Battery_Mgmt_24V_FD1: 8 GWM + SG_ BattULo24_D_Falt : 55|2@0+ (1,0) [0|3] "SED" PCM + SG_ BattULo24_Te_Actl : 47|7@0+ (1,-40) [-40|86] "degC" PCM + SG_ BattULo24State_D_Qlty : 25|2@0+ (1,0) [0|3] "SED" PCM + SG_ BattULo24Soc_Pc_Actl : 39|7@0+ (1,0) [0|127] "percent" PCM + SG_ BattULo24_I_Actl : 23|14@0+ (0.0625,-512) [-512|511.875] "ampere" PCM + SG_ BattULo24_B_Falt : 8|1@0+ (1,0) [0|1] "SED" PCM + SG_ BattULo24_Ah_DeltaRide : 7|15@0+ (0.0078125,-100) [-100|155.9921875] "amperehour" PCM + +BO_ 1186 Driveline_Data_2: 8 TCCM + SG_ SelDrvMdeAwd2_D_Stat : 31|5@0+ (1,0) [0|31] "SED" ABS_ESC,GWM + SG_ RearDiffLckMsg_D_Rq : 20|3@0+ (1,0) [0|7] "SED" GWM + SG_ RearDiffLckLamp_D_Rq : 11|2@0+ (1,0) [0|3] "SED" VDM,GWM,ABS_ESC + SG_ RearDiffLck_Tq_Actl : 7|12@0+ (1,0) [0|4093] "Nm" ABS_ESC,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ RearDiffFalt_D_Stat : 23|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + SG_ LsdSrvcRqd_B_Rq : 21|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 611 Driveline_Data_1: 8 TCCM + SG_ AwdSys_D_Stat : 27|2@0+ (1,0) [0|3] "SED" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ AwdStat_D_RqDsply : 63|5@0+ (1,0) [0|31] "SED" TCM_DSL,ABS_ESC,GWM + SG_ AwdLck_D_Stat : 31|4@0+ (1,0) [0|15] "SED" TCM_DSL,GWM,ABS_ESC + SG_ AwdSrvcRqd_B_Rq : 0|1@0+ (1,0) [0|1] "SED" GWM,PCM,PCM_HEV,TCM_DSL,ABS_ESC + SG_ NtrlTowAvail_B_Stat : 4|1@0+ (1,0) [0|1] "SED" GWM + SG_ AwdLck_Tq_Rq : 15|12@0+ (1,0) [0|4093] "Nm" PCM_HEV,GWM,ABS_ESC + SG_ TrnAout_Tq_RqMx : 47|13@0+ (1,-1250) [-1250|6941] "Nm" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ AwdOffRoadMode_D_Stats : 25|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ AwdLoLamp_D_RqDsply : 35|2@0+ (1,0) [0|3] "SED" GWM + SG_ AwdHiLamp_D_RqDsply : 19|2@0+ (1,0) [0|3] "SED" GWM,ABS_ESC + SG_ AwdAutoLamp_D_RqDsply : 17|2@0+ (1,0) [0|3] "SED" GWM,ABS_ESC + SG_ Awd2wdLamp_D_RqDsply : 2|2@0+ (1,0) [0|3] "SED" GWM + SG_ AwdRnge_D_Actl : 7|3@0+ (1,0) [0|7] "SED" VDM,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,ABS_ESC,GWM,IPMA_ADAS + +BO_ 1461 PSCM_AutoSar_NetwrkMgmt: 8 PSCM + SG_ PSCM_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + SG_ PSCM_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" GWM,ABS_ESC + +BO_ 1047 TrailerAid_Data2: 8 PSCM + SG_ TrlrAnOffst_An2_Calc : 39|8@0+ (0.5,-64) [-64|63.5] "degrees" IPMA_ADAS + SG_ TrlrAn_An_WarnCalc : 28|5@0+ (1,0) [0|31] "degrees" IPMA_ADAS + SG_ TrlrAn_An_MxCalc : 55|7@0+ (1,0) [0|127] "degrees" IPMA_ADAS + SG_ TrlrAidTrlrId_No_Rq : 63|4@0+ (1,0) [0|15] "unitless" GWM + SG_ TrlrAidTrgtId_No_Rq : 44|5@0+ (1,0) [0|31] "unitless" IPMA_ADAS + SG_ TrlrAidSetup_D2_Stat : 47|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ TrlrAidEnbl_D2_Stat : 31|3@0+ (1,0) [0|7] "SED" ABS_ESC,IPMA_ADAS,GWM,PCM,ECM_Diesel + SG_ TrlrAidMsgTxt_D2_Rq : 14|6@0+ (1,0) [0|63] "SED" IPMA_ADAS,GWM,ABS_ESC + SG_ EsaOn_B_Stat : 23|1@0+ (1,0) [0|1] "SED" GWM + SG_ HitchToTrlrAxle_L_Calc : 7|9@0+ (0.0254,0) [0|12.9794] "meter" IPMA_ADAS + SG_ SelDrvMdeSte_D_Stat : 17|2@0+ (1,0) [0|3] "SED" ABS_ESC + +BO_ 972 Lane_Assist_Data3_FD1: 8 PSCM + SG_ LatCtlSte_D_Stat : 18|3@0+ (1,0) [0|7] "SED" IPMA_ADAS,GWM + SG_ LatCtlLim_D_Stat : 33|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ LatCtlCpblty_D_Stat : 39|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ LatCtlCpbltyDStat_No_Cnt : 37|4@0+ (1,0) [0|15] "Unitless" IPMA_ADAS,GWM + SG_ LatCtlCpbltyDStat_No_Cs : 47|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS,GWM + SG_ TrlrAn_An_TrgtCalc : 31|8@0+ (1,-128) [-128|127] "degrees" IPMA_ADAS + SG_ LsmcBrkDecelEnbl_D_Rq : 1|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ TjaHandsOnCnfdnc_B_Est : 3|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ LaHandsOff_B_Actl : 7|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ LaActDeny_B_Actl : 6|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ LaActAvail_D_Actl : 5|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ LsmcBrk_Tq_Rq : 15|13@0+ (4,0) [0|32764] "Nm" ABS_ESC + +BO_ 130 EPAS_INFO: 8 PSCM + SG_ TrlrHitchLamp_D_Rqst : 24|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ VehVTrlrAid_B_Rq : 25|1@0+ (1,0) [0|1] "SED" PCM_HEV,GWM,ECM_Diesel,PCM + SG_ Veh_V_RqMxTrlrAid : 63|8@0+ (0.1,0) [0|25.5] "km/h" PCM_HEV,GWM,ECM_Diesel,PCM + SG_ DrvSteActv_B_Stat : 10|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ DrvSte_Tq_Actl : 47|8@0+ (0.0625,-8) [-8|7.8125] "Nm" GWM,ABS_ESC + SG_ SteMdule_D_Stat : 55|3@0+ (1,0) [0|7] "SED" GWM + SG_ SteMdule_U_Meas : 39|8@0+ (0.05,6) [6|18.7] "Volts" GWM + SG_ SteMdule_I_Est : 21|12@0+ (0.05,-64) [-64|140.7] "Amps" GWM + SG_ EPAS_Failure : 9|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ SteeringColumnTorque : 7|8@0+ (0.0625,-8) [-8|7.8125] "Nm" GWM,IPMA_ADAS,ABS_ESC + SG_ SAPPAngleControlStat6 : 15|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ SAPPAngleControlStat5 : 14|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ SAPPAngleControlStat4 : 13|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ SAPPAngleControlStat3 : 12|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ SAPPAngleControlStat2 : 11|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ SAPPAngleControlStat1 : 23|2@0+ (1,0) [0|3] "SED" GWM,IPMA_ADAS + +BO_ 126 SteeringPinion_Data: 8 PSCM + SG_ StePw_B_Rq : 23|1@0+ (1,0) [0|1] "SED" GWM,ECM_Diesel,PCM + SG_ StePinRelInit_An_Sns : 7|16@0+ (0.1,-3200) [-3200|3353.3] "degrees" VDM,IPMA_ADAS,GWM,ECM_Diesel,PCM,PCM_HEV,ABS_ESC,TCCM + SG_ StePinCompAnEst_D_Qf : 43|2@0+ (1,0) [0|3] "SED" VDM,CMR_DSMC,IPMA_ADAS,TCM_DSL,ECM_Diesel,PCM,PCM_HEV,ABS_ESC,TCCM,GWM + SG_ StePinComp_An_Est : 22|15@0+ (0.1,-1600) [-1600|1676.7] "degrees" VDM,CMR_DSMC,IPMA_ADAS,TCM_DSL,ECM_Diesel,PCM,PCM_HEV,ABS_ESC,TCCM,GWM + SG_ StePinAn_No_Cs : 39|8@0+ (1,0) [0|255] "Unitless" VDM,ABS_ESC,TCCM,GWM + SG_ StePinAn_No_Cnt : 47|4@0+ (1,0) [0|15] "unitless" VDM,TCCM,GWM,ABS_ESC + +BO_ 133 SteeringPinion_Data_Alt: 8 PSCM + SG_ StePw_B_Rq : 23|1@0+ (1,0) [0|1] "SED" GWM,ECM_Diesel,PCM + SG_ StePinRelInit_An_Sns : 7|16@0+ (0.1,-3200) [-3200|3353.3] "degrees" VDM,IPMA_ADAS,GWM,ECM_Diesel,PCM,PCM_HEV,ABS_ESC,TCCM + SG_ StePinCompAnEst_D_Qf : 43|2@0+ (1,0) [0|3] "SED" VDM,CMR_DSMC,IPMA_ADAS,TCM_DSL,ECM_Diesel,PCM,PCM_HEV,ABS_ESC,TCCM,GWM + SG_ StePinComp_An_Est : 22|15@0+ (0.1,-1600) [-1600|1676.7] "degrees" VDM,CMR_DSMC,IPMA_ADAS,TCM_DSL,ECM_Diesel,PCM,PCM_HEV,ABS_ESC,TCCM,GWM + SG_ StePinAn_No_Cs : 39|8@0+ (1,0) [0|255] "Unitless" VDM,ABS_ESC,TCCM,GWM + SG_ StePinAn_No_Cnt : 47|4@0+ (1,0) [0|15] "unitless" VDM,TCCM,GWM,ABS_ESC + +BO_ 1430 ABS_AutoSar_NetworkMgt: 8 ABS_ESC + SG_ ABS_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ABS_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" GWM + +BO_ 1200 ABS_BrkBst_Data: 8 ABS_ESC + SG_ BrkHold_D_Stat : 34|3@0+ (1,0) [0|7] "SED" ECM_Diesel,GWM,IPMA_ADAS,PCM,PCM_HEV + SG_ HsaTrnAout_Tq_Rq : 23|16@0+ (4,-131072) [-131072|131060] "Nm" GWM + SG_ BrkBstrVac_P_Actl : 7|7@0+ (8,0) [0|1008] "Millibar" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ YawStabilityIndex : 0|9@0+ (1,-256) [-256|255] "%" VDM,IPMA_ADAS,PSCM,GWM + SG_ BrkTot_Tq_RqDrv : 47|13@0+ (4,0) [0|32760] "Nm" IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,GWM,TCCM,PSCM + SG_ BrkTotTqRqDrv_No_Cnt : 39|4@0+ (1,0) [0|15] "unitless" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ BrkTotTqRqDrv_No_Cs : 63|8@0+ (1,0) [0|255] "unitless" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ HsaStat_D_Dsply : 50|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 1102 SelectDriveModeData2: 8 ABS_ESC + SG_ SelDrvMdePos12_D_Stat : 34|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos11_D_Stat : 45|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos10_D_Stat : 55|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos09_D_Stat : 50|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos08_D_Stat : 61|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos07_D_Stat : 39|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos06_D_Stat : 29|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos05_D_Stat : 18|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos04_D_Stat : 23|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos03_D_Stat : 13|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos02_D_Stat : 2|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePos01_D_Stat : 7|5@0+ (1,0) [0|31] "SED" GWM + +BO_ 1056 SelectDriveModeData: 8 ABS_ESC + SG_ AutoEpbMsgTxt_D_Rq : 58|3@0+ (1,0) [0|7] "SED" GWM + SG_ AutoEpbDsply_D_Stat : 37|2@0+ (1,0) [0|3] "SED" GWM + SG_ AutoEpbButtnOn_B_Stat : 48|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos12_B_Avail : 54|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos11_B_Avail : 55|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos10_B_Avail : 40|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos09_B_Avail : 41|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos08_B_Avail : 42|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos07_B_Avail : 43|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos06_B_Avail : 44|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos05_B_Avail : 45|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos04_B_Avail : 46|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos03_B_Avail : 47|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos02_B_Avail : 32|1@0+ (1,0) [0|1] "SED" GWM + SG_ SelDrvMdePos01_B_Avail : 24|1@0+ (1,0) [0|1] "SED" GWM + SG_ ActvDrvMde_D2_Stat : 53|5@0+ (1,0) [0|31] "SED" IPMA_ADAS,GWM + SG_ SelDrvMde_D2_Rq : 63|5@0+ (1,0) [0|31] "SED" GWM + SG_ SelDrvMdePt_D_Rq : 31|5@0+ (1,0) [0|31] "SED" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ SelDrvMdeMsgTxt_D_Rq : 19|4@0+ (1,0) [0|15] "SED" GWM + SG_ SelDrvMde_D_Stat : 26|2@0+ (1,0) [0|3] "SED" GWM + SG_ AwdMde_D_RqBrk : 35|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 1054 BrakeSysFeatures_3: 8 ABS_ESC + SG_ AirDamUp_B_RqBrk : 32|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM_HEV,PCM + SG_ RbaBrk_D_Stat : 63|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ SelDrvMdeChassis2_D_Rq : 45|5@0+ (1,0) [0|31] "SED" PSCM,GWM + SG_ TrailCtl_D_Stat : 55|3@0+ (1,0) [0|7] "SED" TCCM,PCM,GWM + SG_ TrailCtlMsgTxt_D_Rq : 52|4@0+ (1,0) [0|15] "SED" GWM + SG_ BrkBstrVac_D_Stat : 18|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ DrvSlipCtlOffLamp_D_Rq : 23|2@0+ (1,0) [0|3] "SED" GWM + SG_ DrvSlipCtlMdeMsg_D_Rq : 13|5@0+ (1,0) [0|31] "SED" GWM + SG_ AutoHoldMsgTxt_D_Rq : 4|4@0+ (1,0) [0|15] "SED" GWM + SG_ CtaBrk_D_Stat : 47|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ SelDrvMdeAwd_D_Rq : 29|5@0+ (1,0) [0|31] "SED" TCCM,GWM + SG_ AutoHoldSwMde_B_Ind : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ AutoHoldMde_D_Ind : 15|2@0+ (1,0) [0|3] "SED" GWM + SG_ SelDrvMdeChassis_D_Rq : 39|5@0+ (1,0) [0|31] "SED" VDM,GWM + SG_ ApaBrk_D_Stat : 34|2@0+ (1,0) [0|3] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,GWM + +BO_ 1046 BrakeSysFeatures_2: 8 ABS_ESC + SG_ HsaMde_D_Mem : 33|2@0+ (1,0) [0|3] "SED" GWM + SG_ BrkBstrVac_B_Rq : 27|1@0+ (1,0) [0|1] "Discrete" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ HdcMde_D_Actl : 31|3@0+ (1,0) [0|7] "SED" GWM + SG_ RearDiffLck_Tq2_RqMx : 51|12@0+ (4,0) [0|16376] "Nm" GWM + SG_ TRLR_SWAY_EVNT_IN_PROG : 25|1@0+ (1,0) [0|1] "SED" GWM + SG_ TRLR_SWAY_CONFIG_STAT : 26|1@0+ (1,0) [0|1] "SED" GWM + SG_ TCMode : 15|1@0+ (1,0) [0|1] "SED" VDM,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ DrvSlipCtlLamp_D_Rq : 42|2@0+ (1,0) [0|3] "SED" VDM,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ Abs_B_Falt : 5|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ DrvSlipCtlMde_D_Ind : 44|2@0+ (1,0) [0|3] "SED" TCCM,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ DrvAntiLckLamp_D_Rq : 55|2@0+ (1,0) [0|3] "SED" ECM_Diesel,GWM,IPMA_ADAS + SG_ BpedMove_No_Cnt : 3|4@0+ (1,0) [0|15] "Unitless" ECM_Diesel,GWM + SG_ StabCtlBrk_B_Avail : 4|1@0+ (1,0) [0|1] "SED" VDM,TCCM,GWM + SG_ DrvHdcWarnInfo_D_Rq : 35|2@0+ (1,0) [0|3] "SED" GWM + SG_ DrvHdcMsg_D_Rq : 10|3@0+ (1,0) [0|7] "SED" GWM + SG_ DrvHdcLampInfo_D_Rq : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ BpedMove_D_Actl : 7|2@0+ (1,0) [0|3] "SED" ECM_Diesel,GWM + SG_ ChimeBrk_B_Rq : 14|1@0+ (1,0) [0|1] "SED" GWM + SG_ BrkLamp_B_Rq : 13|1@0+ (1,0) [0|1] "SED" GWM + SG_ HILL_DESC_MC : 47|3@0+ (1,0) [0|7] "SED" GWM + SG_ RearDiffElckrOpen_B_Rq : 40|1@0+ (1,0) [0|1] "SED" GWM,TCCM + +BO_ 1045 BrakeSysFeatures: 8 ABS_ESC + SG_ VehStab_D_Stat : 55|4@0+ (1,0) [0|15] "SED" TCCM,PCM_HEV,PCM,GWM + SG_ BrkFluidLvl_D_Stat : 17|2@0+ (1,0) [0|3] "SED" GWM + SG_ LsmcBrkDecel_D_Stat : 39|3@0+ (1,0) [0|7] "SED" PSCM,GWM + SG_ VehYawNonLin_W_Rq : 51|12@0+ (0.03663,-75) [-75|74.92659] "deg/s" ECM_Diesel,GWM + SG_ VehYawLin_W_Rq : 35|12@0+ (0.03663,-75) [-75|74.92659] "deg/s" ECM_Diesel,GWM + SG_ VehVActlBrk_No_Cs : 31|8@0+ (1,0) [0|255] "Unitless" TCCM,CMR_DSMC,SOBDMC_HPCM_FD1,ECM_Diesel,PCM,PCM_HEV,PSCM,TCM_DSL,GWM,IPMA_ADAS + SG_ Veh_V_ActlBrk : 7|16@0+ (0.01,0) [0|655.35] "kph" TCCM,CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,PSCM,TCM_DSL,GWM + SG_ VehVActlBrk_No_Cnt : 21|4@0+ (1,0) [0|15] "Unitless" TCCM,CMR_DSMC,SOBDMC_HPCM_FD1,ECM_Diesel,PCM,PCM_HEV,PSCM,TCM_DSL,GWM,IPMA_ADAS + SG_ VehVActlBrk_D_Qf : 23|2@0+ (1,0) [0|3] "SED" TCCM,CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,PSCM,TCM_DSL,GWM + +BO_ 1044 BrakeSnData_6: 8 ABS_ESC + SG_ StePinOffst_An_Est : 7|16@0+ (0.1,-3200) [-3200|3353.3] "degrees" GWM,PSCM + SG_ StePinOffst_No_Cs : 31|8@0+ (1,0) [0|255] "Unitless" GWM,PSCM + SG_ StePinOffst_No_Cnt : 21|4@0+ (1,0) [0|15] "unitless" GWM,PSCM + SG_ StePinOffst_D_Stat : 23|2@0+ (1,0) [0|3] "SED" GWM,PSCM + +BO_ 1042 TrailerBrakeData: 8 ABS_ESC + SG_ VehRol_An_Dsply : 31|7@0+ (1,-64) [-64|61] "degrees" GWM + SG_ VehPtch_An_Dsply : 23|7@0+ (1,-64) [-64|61] "degrees" GWM,TCCM + SG_ TrlrBrk_Pc_Rq : 14|7@0+ (1,0) [0|127] "percent" GWM + +BO_ 535 WheelSpeed: 8 ABS_ESC + SG_ WhlRr_W_Meas : 54|15@0+ (0.01,0) [0|327.65] "rad/s" VDM,IPMA_ADAS,GWM,ECM_Diesel,PCM,PCM_HEV,PSCM,TCCM,TCM_DSL + SG_ WhlRl_W_Meas : 38|15@0+ (0.01,0) [0|327.65] "rad/s" VDM,IPMA_ADAS,GWM,ECM_Diesel,PCM,PCM_HEV,PSCM,TCCM,TCM_DSL + SG_ WhlFr_W_Meas : 22|15@0+ (0.01,0) [0|327.65] "rad/s" VDM,IPMA_ADAS,GWM,ECM_Diesel,PCM,PCM_HEV,PSCM,TCCM,TCM_DSL + SG_ WhlFl_W_Meas : 6|15@0+ (0.01,0) [0|327.65] "rad/s" VDM,IPMA_ADAS,GWM,ECM_Diesel,PCM,PCM_HEV,PSCM,TCCM,TCM_DSL + +BO_ 534 WheelData: 8 ABS_ESC + SG_ BrkObdData_No_Actl : 63|8@0+ (1,0) [0|255] "unitless" SOBDMC_HPCM_FD1,GWM + SG_ BrkObdIndex_No_Actl : 53|6@0+ (1,0) [0|63] "unitless" SOBDMC_HPCM_FD1,GWM + SG_ WhlRotatRr_No_Cnt : 23|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS,GWM,PSCM + SG_ WhlDirRr_D_Actl : 33|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM,ECM_Diesel,PCM_HEV,PSCM + SG_ WhlDirRl_D_Actl : 39|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM,PSCM,ECM_Diesel,PCM_HEV + SG_ WhlDirFr_D_Actl : 37|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM,ECM_Diesel,PCM_HEV,PSCM + SG_ WhlDirFl_D_Actl : 35|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM,ECM_Diesel,PCM_HEV,PSCM + SG_ WhlRotatRl_No_Cnt : 31|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS,GWM,PSCM + SG_ WhlRotatFr_No_Cnt : 7|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS,GWM,PSCM + SG_ WhlRotatFl_No_Cnt : 15|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS,GWM,PSCM + +BO_ 532 DesiredTorqBrk_2: 8 ABS_ESC + SG_ RgenTqFalt_B_Actl : 59|1@0+ (1,0) [0|1] "SED" GWM,PCM_HEV + SG_ RgenBrkDynoMde_B_Actl : 58|1@0+ (1,0) [0|1] "SED" GWM,PCM_HEV + SG_ PrplWhlTqRqMn_No_Cs : 55|8@0+ (1,0) [0|255] "Unitless" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ PrplWhlTot_Tq_RqMn : 7|16@0+ (4,-131072) [-131072|131068] "Nm" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ PrplWhlTqRqMn_No_Cnt : 63|4@0+ (1,0) [0|15] "Unitless" GWM,ECM_Diesel,PCM,PCM_HEV + +BO_ 531 DesiredTorqBrk: 8 ABS_ESC + SG_ VehStop_D_Stat : 28|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM + SG_ TracCtlPtActv_B_Actl : 31|1@0+ (1,0) [0|1] "SED" VDM,IPMA_ADAS,TCCM,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,GWM + SG_ LscmbbMntr_B_Err : 17|1@0+ (1,0) [0|1] "SED" GWM + SG_ LscmbbBrkDis_B_Actl : 19|1@0+ (1,0) [0|1] "SED" GWM + SG_ LscmbbDeny_B_ActlBrk : 18|1@0+ (1,0) [0|1] "SED" GWM + SG_ PrkBrkYwLamp_D_Rq : 38|2@0+ (1,0) [0|3] "SED" GWM + SG_ PrkBrkRedLamp_D_Rq : 30|2@0+ (1,0) [0|3] "SED" GWM + SG_ LscmbbBrkDecel_B_Actl : 20|1@0+ (1,0) [0|1] "SED" GWM + SG_ AbsActv_B_Actl : 45|1@0+ (1,0) [0|1] "SED" VDM,SOBDMC_HPCM_FD1,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,PSCM,GWM + SG_ StabCtlBrkActv_B_Actl : 23|1@0+ (1,0) [0|1] "SED" VDM,IPMA_ADAS,PCM,PCM_HEV,TCM_DSL,PSCM,TCCM,ECM_Diesel,GWM + SG_ CmbbBrkPrchg_B_Actl : 59|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ CmbbBrkDecel_B_Actl : 58|1@0+ (1,0) [0|1] "SED" CMR_DSMC,IPMA_ADAS,GWM + SG_ CmbbBaSensInc_B_Actl : 57|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ AccBrkWarm_B_Actl : 63|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ AccBrkTotTqMn_B_Actl : 62|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ AccBrkPrchgActv_B_Actl : 61|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ AccBrkDis_B_Actl : 44|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ AccBrkDeny_B_Actl : 42|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ AccBrkActv_B_Actl : 43|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,ECM_Diesel,GWM + SG_ PrplDrgCtlActv_B_Actl : 46|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV,TCM_DSL,GWM + SG_ PrplWhlTot_Tq_RqMx : 7|16@0+ (4,-131072) [-131072|131068] "Nm" ECM_Diesel,PCM,PCM_HEV,TCCM,GWM + SG_ LscmbbBaSensInc_B_Actl : 21|1@0+ (1,0) [0|1] "SED" GWM + SG_ CmbbBrkDis_B_Actl : 56|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,PSCM,GWM + SG_ CmbbDeny_B_ActlBrk : 60|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,PSCM,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ CcDis_B_Cmd : 47|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,GWM + SG_ VehLongOvrGnd_A_Est : 41|10@0+ (0.035,-17.9) [-17.9|17.835] "m/s^2" VDM,IPMA_ADAS,TCCM,GWM + SG_ LscmbBrkPrchg_B_Actl : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ AccStopActv_B_ActlBrk : 22|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ AccDis_B_ActlEpb : 32|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ PrkBrkMsgTxt_D_Rq : 36|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkBrkStatus : 26|3@0+ (1,0) [0|7] "SED" IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,GWM + +BO_ 136 ActiveFronSteering_Req: 8 ABS_ESC + SG_ SteWhlBrkOffst_An_Rq : 7|15@0+ (0.1,-1600) [-1600|1676.5] "degrees" GWM + SG_ SteWhlBrkAnRq_No_Cs : 23|8@0+ (1,0) [0|255] "Unitless" GWM + SG_ SteWhlBrkAnRq_No_Cnt : 31|4@0+ (1,0) [0|15] "Unitless" GWM + +BO_ 125 BrakeSnData_4: 8 ABS_ESC + SG_ VehRolComp_W_Actl : 51|12@0+ (0.03663,-75) [-75|74.92659] "degrees/sec" VDM,GWM + SG_ VehVertComp_A_Actl : 45|10@0+ (0.035,-17.9) [-17.9|17.835] "m/s^2" VDM,PSCM,GWM + SG_ BrkTotTqRqArb_No_Cs : 23|8@0+ (1,0) [0|255] "Unitless" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ BrkTotTqRqArb_No_Cnt : 31|4@0+ (1,0) [0|15] "Unitless" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ BrkTot_Tq_RqArb : 4|13@0+ (4,0) [0|32756] "Nm" VDM,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,PSCM,GWM + SG_ BrkTot_Tq_Actl : 27|13@0+ (4,0) [0|32756] "Nm" ECM_Diesel,PCM,PCM_HEV,PSCM,GWM,TCCM + SG_ HsaStat_D_Actl : 7|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM,PCM_HEV,TCM_DSL,GWM + +BO_ 119 BrakeSnData_3: 8 ABS_ESC + SG_ VehTrvlDir_D_Stat : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ VehOverGnd_V_Est : 7|16@0+ (0.01,0) [0|655.33] "kph" VDM,IPMA_ADAS,TCCM,PSCM,GWM + SG_ VehLongComp_A_Actl : 49|10@0+ (0.035,-17.9) [-17.9|17.835] "m/s^2" VDM,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,PSCM,GWM + SG_ VehLatComp_A_Actl : 43|10@0+ (0.035,-17.9) [-17.9|17.835] "m/s^2" VDM,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,PSCM,TCCM,GWM + SG_ VehYawComp_W_Actl : 19|12@0+ (0.03663,-75) [-75|74.92659] "deg/s" VDM,TCCM,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,PSCM,GWM + +BO_ 118 BrakeSnData_5: 8 ABS_ESC + SG_ BrkCtrFnd_B_Stat : 39|1@0+ (1,0) [0|1] "SED" GWM + SG_ AwdLck_Tq_RqMx : 35|12@0+ (1,0) [0|4095] "Nm" GWM,TCCM + SG_ AwdLck_Tq_RqMn : 51|12@0+ (1,0) [0|4095] "Nm" GWM,TCCM + SG_ DrvSte_D_Stat : 19|4@0+ (1,0) [0|15] "SED" PSCM,GWM + SG_ DrvSte_Tq_Rq : 31|8@0+ (0.0625,-8) [-8|7.8125] "Nm" PSCM,GWM + SG_ EmgcyBrkLamp_D_Rq : 21|2@0+ (1,0) [0|3] "SED" GWM + SG_ StopLamp_B_RqBrk : 7|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 73 Global_PATS_SubTarget: 8 ABS_ESC + SG_ immoSubTarget1Data_T1 : 15|40@0+ (1,0) [0|1099511627775] "Encrypted" ECM_Diesel,GWM,PCM,PCM_HEV + SG_ immoSubTarget1Cmd_T1 : 7|3@0+ (1,0) [0|7] "SED" ECM_Diesel,GWM,PCM,PCM_HEV + +BO_ 1034 GGCC_Config_Mgmt_ID_1_FD1: 8 GWM + SG_ VehicleGGCCData : 7|64@0+ (1,0) [0|1.84467E+019] "mixed" VDM,CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,ECM_Diesel,PCM,PCM_HEV,PSCM,TCCM,TCM_DSL + +BO_ 1440 TCM_AutoSar_NetworkMgt: 8 TCM_DSL + SG_ TCM_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCM_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" Vector__XXX + +BO_ 561 TransGearData_2: 8 TCM_DSL + SG_ TrnMsgTxt2_D_Rq : 39|3@0+ (1,0) [0|7] "SED" GWM + SG_ TrnMsgTxt_D_Rq : 23|4@0+ (1,0) [0|15] "SED" GWM + +BO_ 330 TransData_3: 8 TCM_DSL + SG_ TrnAout_W_ActlUnfilt : 22|15@0+ (0.1,0) [0|3276.5] "rad/s" ECM_Diesel,GWM + +BO_ 1090 MtrTrac_Data2_FD1: 8 PCM_HEV + SG_ Mtr2State_D_ActlMntr : 31|3@0+ (1,0) [0|7] "SED" GWM + SG_ Inv1Ain_I_ActlMntr : 7|15@0+ (0.1,-1000) [-1000|2276.5] "ampere" GWM + SG_ HybVehMde_D_ActlMntr : 20|3@0+ (1,0) [0|7] "SED" GWM + SG_ ChrgStat_D_ActlMntr : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ VehElRnge_L_Dsply : 28|12@0+ (0.1,0) [0|409.3] "kilometer" GWM + +BO_ 870 Cluster_HEV_Data3_FD1: 8 PCM_HEV + SG_ EngMdeMsgTxt_D_Rq : 12|3@0+ (1,0) [0|7] "SED" GWM + SG_ EffRgenThres_Pc_Dsply : 9|10@0+ (0.1,-102.3) [-102.3|0] "percent" GWM + SG_ RngPerChrgInst_L_Dsply : 45|12@0+ (0.1,0) [0|409.3] "km" GWM + +BO_ 869 Cluster_HEV_Data2: 8 PCM_HEV + SG_ PwrFlowTxt_D_Dsply : 21|4@0+ (1,0) [0|15] "SED" GWM + SG_ EngOnMsg2_D_Dsply : 54|5@0+ (1,0) [0|31] "SED" GWM + SG_ EngOnMsg1_D_Dsply : 38|5@0+ (1,0) [0|31] "SED" GWM + SG_ FuelMaintMde_D_Dsply : 23|2@0+ (1,0) [0|3] "SED" GWM + SG_ EffWhlLvl2_Pc_Dsply : 17|10@0+ (0.2,-102.2) [-102.2|102.4] "percent" GWM + SG_ EffWhlThres_Pc_Dsply : 49|10@0+ (0.1,0) [0|102.3] "percent" GWM + SG_ EngPwLvl_Pc_Dsply : 1|10@0+ (0.1,0) [0|102.3] "percent" GWM + SG_ EngActv_B_Dsply : 2|1@0+ (1,0) [0|1] "SED" GWM + SG_ EffWhlThresOn_B_Dsply : 3|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 606 HEV_Powertrain_Data8_FD1: 8 PCM_HEV + SG_ ElVehLaterMde_D_Stat : 7|2@0+ (1,0) [0|3] "SED" GWM + SG_ ElVehNowMde_D_Stat : 5|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 374 PowertrainData_10: 8 PCM + SG_ GearEngag_D_Actl : 47|3@0+ (1,0) [0|7] "SED" GWM + SG_ TrnRng_D_Rq : 27|4@0+ (1,0) [0|15] "SED" SOBDMC_HPCM_FD1,ABS_ESC,IPMA_ADAS,PSCM,ECM_Diesel,GWM + SG_ TrnPrkSys_D_Actl : 31|4@0+ (1,0) [0|15] "SED" SOBDMC_HPCM_FD1,ABS_ESC,IPMA_ADAS,ECM_Diesel,GWM + SG_ GearLvr_D_ActlDrv : 7|4@0+ (1,0) [0|15] "SED" SOBDMC_HPCM_FD1,ABS_ESC,IPMA_ADAS,TCCM,ECM_Diesel,GWM + SG_ GearPos_No_Cs : 23|8@0+ (1,0) [0|255] "unitless" SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,ECM_Diesel,GWM + SG_ GearPos_D_Trg : 15|4@0+ (1,0) [0|15] "SED" SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,TCCM,ECM_Diesel,GWM + SG_ GearPos_No_Cnt : 11|4@0+ (1,0) [0|15] "unitless" SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,ECM_Diesel,GWM + SG_ TrnIgnOffDly_T_Rq : 39|8@0+ (4,0) [0|1020] "ms" GWM + SG_ GearPos_D_Actl : 3|4@0+ (1,0) [0|15] "SED" SOBDMC_HPCM_FD1,PSCM,IPMA_ADAS,ABS_ESC,ECM_Diesel,GWM + +BO_ 603 HEV_Powertrain_Data2: 8 PCM_HEV + SG_ WhlDirAvgDrv_D_Actl : 6|2@0+ (1,0) [0|3] "SED" ABS_ESC,IPMA_ADAS,GWM + SG_ PrplTqMnRgen_B_Actl : 7|1@0+ (1,0) [0|1] "SED" ABS_ESC,GWM + SG_ BattTracCnnct_D_Rq : 20|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 602 HEV_Powertrain_Data: 8 PCM_HEV + SG_ HtrnWarnLamp_B_Dsply : 3|1@0+ (1,0) [0|1] "SED" GWM + SG_ HybPwLimOn_B_Stat : 7|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwPckTqRdy_B_Dsply : 31|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 1152 HEV_Powertrain_Data6: 8 PCM_HEV + SG_ BattTracDiagClr_B_Stat : 2|1@0+ (1,0) [0|1] "SED" GWM + SG_ EngTeHi_B_Actl : 5|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,GWM + SG_ DcdcOn_B_Rq : 6|1@0+ (1,0) [0|1] "SED" GWM + SG_ ULoBattSpprtSustn_B_Rq : 7|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,GWM + SG_ VehElEff_No_Avg : 15|7@0+ (10,-100) [-100|1150] "watt*hr/km" SOBDMC_HPCM_FD1,GWM + +BO_ 872 Cluster_HEV_Data5: 8 PCM_HEV + SG_ PlgActvArb_B_Dsply : 51|1@0+ (1,0) [0|1] "SED" GWM + SG_ HybMdeStat_D_Dsply : 39|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1,GWM + +BO_ 560 TransGearData: 8 TCM_DSL + SG_ SelDrvMdeSwtch_D_Stat3 : 15|2@0+ (1,0) [0|3] "SED" GWM,ABS_ESC + SG_ TrnSrvcRqd_B_Rq : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ TrnShifActv_B_Actl : 0|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC,ECM_Diesel + SG_ GearLvrPos_D_Actl : 12|4@0+ (1,0) [0|15] "SED" VDM,IPMA_ADAS,GWM,ABS_ESC,PSCM,TCCM,ECM_Diesel + SG_ GboxOil_Te_Actl : 39|8@0+ (1,-60) [-60|193] "degC" SOBDMC_HPCM_FD1,GWM,TCCM,ECM_Diesel + +BO_ 369 EngineData_1: 8 PCM + SG_ SeatWorkSrfc_B_Falt : 12|1@0+ (1,0) [0|1] "SED" GWM + SG_ TrnIpcDsplyRng2_D_Actl : 23|4@0+ (1,0) [0|15] "SED" GWM + SG_ TrnIpcDsplyRng_D_Stat : 9|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrnIpcDsplyGear_D_Actl : 7|4@0+ (1,0) [0|15] "SED" GWM + SG_ TrnIpcDsplyMde_D_Stat : 3|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrnIpcDsplyMde_D_Actl : 15|3@0+ (1,0) [0|7] "SED" GWM + SG_ TrnIpcDsplyGear_D_Stat : 1|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 92 Gear_Shift_by_Wire_3: 8 PCM_HEV + SG_ TrnLvrV_D_Rq : 43|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrnSbwSysHlth_D_Actl : 1|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrnGearNtmAllow_B_Stat : 47|1@0+ (1,0) [0|1] "SED" GWM + SG_ TrnDtpCmd_D_Actl : 46|3@0+ (1,0) [0|7] "SED" GWM + SG_ GearSelLck_D_Rq : 41|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrnGearCmd_No_Cs : 31|8@0+ (1,0) [0|255] "Unitless" GWM + SG_ TrnValidGear_D_Cnfm : 11|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrnNtrlTowCmd_D_Actl : 6|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,GWM,ABS_ESC + SG_ TrnGearCmd_Pc_ActlPt : 9|10@0+ (0.1,0) [0|102.2] "percent duty cycle" GWM + SG_ TrnGear_D_RqPt : 4|3@0+ (1,0) [0|7] "SED" GWM + SG_ TrnCmdState_B_Actl : 39|1@0+ (1,0) [0|1] "SED" GWM + SG_ TrnCmdCnt_B_Actl : 7|1@0+ (1,0) [0|1] "unitless" GWM + SG_ PrkBrkActv_D_RqTrnGear : 38|2@0+ (1,0) [0|3] "SED" GWM,ABS_ESC + SG_ TrnGearMsgTxt_D_Rq : 36|5@0+ (1,0) [0|31] "SED" GWM + SG_ TrnGearCmd_No_Cnt : 15|4@0+ (1,0) [0|15] "Unitless" GWM + +BO_ 2030 TesterPhysicalResSOBDMCFD1: 64 ECM_Diesel + SG_ TesterPhysicalResSOBDMC : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1087 Powertrain_Data_5: 8 PCM_HEV + SG_ BattRgenLoChrg_D_RqEng : 15|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdasLcObtclAbrt_B_Stat : 0|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ BattRgenLoDChrg_D_RqEng : 13|2@0+ (1,0) [0|3] "SED" GWM + SG_ AirDamPos_D_Stat : 11|2@0+ (1,0) [0|3] "SED" GWM,ABS_ESC + SG_ FapLcInhbt_B_Rq : 1|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ FapLcStopHold_B_Rq : 2|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ FapLcPrchgBrk_B_Rq : 3|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ FapLcObstcl_B_Stat : 4|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ FapLcMaxGrdInhbt_B_Stat : 5|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ FapLcMaxGrdAbrt_B_Stat : 6|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + SG_ FapLcActv_B_Stat : 7|1@0+ (1,0) [0|1] "SED" GWM,IPMA_ADAS + +BO_ 332 CGEA_Urea_Strategy: 8 ECM_Diesel + SG_ UreaLvlQlty_D_RqDsply : 51|3@0+ (1,0) [0|7] "SED" GWM + SG_ UreaLvlTxtWarn_D_Rq : 63|4@0+ (1,0) [0|15] "SED" GWM + SG_ UreaQltySysWarn_D_Rq : 59|3@0+ (1,0) [0|7] "SED" GWM + SG_ DieslPrtcWarn_D_Rq : 55|4@0+ (1,0) [0|15] "SED" GWM + SG_ UreaQltyFlg_B_RqDsply : 24|1@0+ (1,0) [0|1] "SED" GWM + SG_ UreaLvl_Pc_Actl : 47|8@0+ (0.4,0) [0|102] "percent" GWM + SG_ VehUreaRnge2_L_DsplyMx : 3|12@0+ (1,0) [0|4095] "kilometer" GWM + SG_ UreaQltySys_D_RqDsply : 27|3@0+ (1,0) [0|7] "SED" GWM + SG_ UreaLvlTxt_D_RqDsply : 31|4@0+ (1,0) [0|15] "SED" GWM + SG_ VehUreaWarn_V_DsplyMx : 23|7@0+ (1,0) [0|127] "km/h" GWM + +BO_ 1896 TesterPhysicalResABS: 64 ABS_ESC + SG_ TesterPhysicalResABS : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1889 TesterPhysicalReqTCCM: 64 TSTR + SG_ TesterPhysicalReqTCCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TCCM + +BO_ 1888 TesterPhysicalReqABS: 64 TSTR + SG_ TesterPhysicalReqABS : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" ABS_ESC + +BO_ 1848 TesterPhysicalResPSCM: 64 PSCM + SG_ TesterPhysicalResPSCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1840 TesterPhysicalReqPSCM: 64 TSTR + SG_ TesterPhysicalReqPSCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" PSCM + +BO_ 1713 ABS_Rapid_Data_Response_2: 8 ABS_ESC + SG_ UUDTABSResponse2 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1712 ABS_Rapid_Data_Response_1: 8 ABS_ESC + SG_ UUDTABSResponse1 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 2025 TesterPhysicalResTCM: 64 TCM_DSL + SG_ TesterPhysicalResTCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 2024 TesterPhysicalResPCM: 64 PCM_HEV + SG_ TesterPhysicalResPCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 2017 TesterPhysicalReqTCM: 64 TSTR + SG_ TesterPhysicalReqTCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TCM_DSL + +BO_ 2016 TesterPhysicalReqPCM: 64 TSTR + SG_ TesterPhysicalReqPCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" ECM_Diesel,PCM,PCM_HEV + +BO_ 2015 TesterFunctionalReq_FD1: 64 TSTR + SG_ TesterFunctionalReq : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" VDM,CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCCM,TCM_DSL,PSCM,ABS_ESC,GWM + +BO_ 1897 TesterPhysicalResTCCM: 64 TCCM + SG_ TesterPhysicalResTCCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1814 TesterPhysicalReqGWM_FD1: 64 TSTR + SG_ TesterPhysicalReqGWM_F1 : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" GWM + +BO_ 1701 TCM_Rapid_Data_Response_2: 8 TCM_DSL + SG_ UUDTTCMResponse2 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1700 TCM_Rapid_Data_Response_1: 8 TCM_DSL + SG_ UUDTTCMResponse1 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1697 PCM_Rapid_Data_Response_2: 8 PCM_HEV + SG_ UUDTPCMResponse2 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1696 PCM_Rapid_Data_Response_1: 8 PCM_HEV + SG_ UUDTPCMResponse1 : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" TSTR + +BO_ 1429 PCM_AutoSar_NetworkMgmt: 8 PCM_HEV + SG_ PCM_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" TCM_DSL + SG_ PCM_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" TCM_DSL + +BO_ 1100 PowertrainData_9: 8 PCM_HEV + SG_ EngExhMdeQuiet_D2_Stat : 28|3@0+ (1,0) [0|7] "SED" GWM + SG_ HvacCmprLim_D_Stat : 34|3@0+ (1,0) [0|7] "SED" GWM + SG_ WakeAlarm1_T_Rq : 55|15@0+ (1,0) [0|32767] "minute" GWM + SG_ WakeAlarm1_B_Typ : 56|1@0+ (1,0) [0|1] "SED" GWM + SG_ Veh_V_DsplyTrailCtlSet : 47|6@0+ (0.5,0) [0|31] "unitless" GWM + SG_ TrailCtlPt_B_Falt : 36|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + SG_ AutoTowAllw_D_StatMnu : 25|2@0+ (1,0) [0|3] "SED" GWM + SG_ AutoTowActv_B_Stat : 39|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ GrossTrainWeight_M_Est : 7|8@0+ (100,0) [0|25300] "kilogram" VDM,ABS_ESC,PSCM,IPMA_ADAS,TCCM,TCM_DSL,GWM + +BO_ 1098 EffDrvModeData: 8 ECM_Diesel + SG_ EdmVeh_V_Dsply : 31|5@0+ (5,0) [0|155] "km/h" GWM + SG_ EdmSailMdeOn_B_Stat : 25|1@0+ (1,0) [0|1] "SED" GWM + SG_ EdmPrev_Fe_Dsply : 23|8@0+ (0.1,0) [0|25.5] "litre/100km" GWM + SG_ EdmMsgTxt_D_Rq : 11|4@0+ (1,0) [0|15] "SED" GWM + SG_ EdmLamp_D_Dsply : 15|4@0+ (1,0) [0|15] "SED" GWM + SG_ EdmCurrent_Fe_Dsply : 7|8@0+ (0.1,0) [0|25.5] "litre/100km" GWM + SG_ EdmCmplnc_B_Dsply : 26|1@0+ (1,0) [0|1] "SED" GWM + SG_ EdmCmplnc_Pc_Dsply : 24|8@0+ (0.392157,0) [0|100.000035] "percent" GWM + +BO_ 1086 PowertrainData_3: 8 PCM_HEV + SG_ EngMnfld_P_Actl : 47|13@0+ (0.1,-206.8) [-206.8|612.3] "kilopascal" GWM + SG_ FuelPumpPwr_B_Rq : 20|1@0+ (1,0) [0|1] "SED" GWM + SG_ BattULoChrg_U_Cmd : 15|8@0+ (0.025,10.6) [10.6|16.975] "volt" GWM + SG_ ElLoadCtl_D_Rq : 23|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 1071 Engine_Clutch_Data: 8 PCM_HEV + SG_ EngAout_N_Dsply : 52|13@0+ (2,0) [0|16382] "rpm" GWM + SG_ CluPdl_PcRate_Actl : 7|8@0+ (0.04,-5) [-5|5.2] "%/ms" GWM + SG_ CluPdlPosPcMeas_D_Qf : 11|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + SG_ CluPdlPos_Pc_Meas : 9|10@0+ (0.1,0) [0|102.3] "%" ABS_ESC,GWM + SG_ EngAoutIdl_N_Ntrl : 31|11@0+ (2,0) [0|4094] "rpm" ABS_ESC,GWM + +BO_ 1069 PowertrainData_2: 8 PCM_HEV + SG_ SlMde_D_Stat : 57|2@0+ (1,0) [0|3] "SED" GWM + SG_ SlMde_D_RqDsply : 59|2@0+ (1,0) [0|3] "SED" GWM + SG_ IsaOffst_D_Stat : 63|4@0+ (1,0) [0|15] "SED" GWM + SG_ GrllShtrPos_D_Cmd : 55|4@0+ (1,0) [0|15] "SED" GWM + SG_ GrllShtrPos_B_Falt : 51|1@0+ (1,0) [0|1] "SED" GWM + SG_ ObdWarmUp_B_Complt : 12|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,GWM + SG_ EngMsgTxt_D_Rq : 11|2@0+ (1,0) [0|3] "SED" GWM + SG_ EngClnt_Te_ActlDiag : 39|8@0+ (1,-40) [-40|215] "degC" SOBDMC_HPCM_FD1,TCM_DSL,GWM + SG_ EngLoad_Pc_CalcDiag : 47|8@0+ (0.392157,0) [0|100.000035] "%" SOBDMC_HPCM_FD1,TCM_DSL,GWM + SG_ EngAirIn_Te_Actl : 9|10@0+ (0.25,-128) [-128|127.25] "degC" GWM,TCM_DSL + SG_ ApedPos_Pc_ActlDiag : 31|8@0+ (0.392157,0) [0|100.000035] "%" SOBDMC_HPCM_FD1,TCM_DSL,GWM + +BO_ 1060 Powertrain_Data_4: 8 PCM_HEV + SG_ RearDiffOilTeWarn_B_Rq : 20|1@0+ (1,0) [0|1] "SED" GWM + SG_ RearDiffOil_Te_Actl : 15|9@0+ (1,-40) [-40|470] "degC" GWM + SG_ BpedDrvMsgTxt_B_Dsply : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ FuelLvl_Pc_DsplyEng : 41|10@0+ (0.108696,-5.217408) [-5.217408|105.9786] "percent" GWM + SG_ FuelLvlWarn_D_ActlEng : 19|3@0+ (1,0) [0|7] "SED" GWM + SG_ FuelRange_L_DsplyEng : 39|14@0+ (0.1,0) [0|1638.3] "kilometer" GWM + SG_ SelDrvMdePt_D_Stat : 25|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + +BO_ 1057 PowertrainData_1: 8 PCM_HEV + SG_ FohEng_D_Rq : 1|2@0+ (1,0) [0|3] "SED" GWM + SG_ EngIdlShutDwnTxt_D_Rq : 17|2@0+ (1,0) [0|3] "SED" GWM + SG_ EngIdlShutDown_D_Stat : 9|2@0+ (1,0) [0|3] "SED" GWM + SG_ FUEL_ALCOHOL_PERCNT : 63|8@0+ (0.393700787,0) [0|99.999899898] "Percent" GWM + SG_ TrnTotTq_Rt_Est : 39|16@0+ (0.001,0) [0|65.533] "Unitless" GWM + SG_ TrnTotLss_Tq_Est : 31|8@0+ (0.5,0) [0|126.5] "Nm" GWM + SG_ ECMMILRequest : 3|2@0+ (1,0) [0|3] "SED" GWM + SG_ AirCondFluidHi_P_Actl : 55|8@0+ (0.125,0) [0|31.625] "bar" SOBDMC_HPCM_FD1,GWM + SG_ OilPressureWarning : 18|1@0+ (1,0) [0|1] "SED" GWM + SG_ VehVLimStat_D_Actl : 6|3@0+ (1,0) [0|7] "SED" GWM,TCM_DSL + SG_ VehVLimActv_B_Actl : 7|1@0+ (1,0) [0|1] "SED" GWM,TCM_DSL + SG_ CoolantFanStepAct : 23|5@0+ (1,0) [0|31] "Steps" GWM + +BO_ 1055 PowertrainData_7: 8 PCM_HEV + SG_ EcoCochInstNeg_B_Dsply : 53|1@0+ (1,0) [0|1] "SED" GWM + SG_ EcoCochShif_Pc_Dsply : 39|8@0+ (0.392157,0) [0|100.000035] "percent" GWM + SG_ EcoCochInst_Pc_Dsply : 47|10@0+ (0.1,0) [0|102.3] "percent" GWM + SG_ EcoCochIdlFuel_Pc_Dsply : 31|8@0+ (0.392157,0) [0|100.000035] "percent" GWM + SG_ EcoCochDecel_Pc_Dsply : 23|8@0+ (0.392157,0) [0|100.000035] "percent" GWM + SG_ EcoCochCrus_Pc_Dsply : 15|8@0+ (0.392157,0) [0|100.000035] "percent" GWM + SG_ EcoCochA_Pc_Dsply : 7|8@0+ (0.392157,0) [0|100.000035] "percent" GWM + +BO_ 562 PowertrainData_11: 8 ECM_Diesel + SG_ GearNtrl_No_Cs : 15|8@0+ (1,0) [0|255] "unitless" GWM + SG_ GearNtrl_No_Cnt : 5|4@0+ (1,0) [0|15] "unitless" GWM + SG_ GearNtrl_D_Stat : 7|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + +BO_ 523 Engine_Data_18: 8 ECM_Diesel + SG_ EngAirFiltMsgTxt_D_Rq : 2|3@0+ (1,0) [0|7] "SED" GWM + SG_ WaterInFuel_B_Falt : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ UreaMnAdd_L2_Actl : 23|8@0+ (0.1,0) [0|25.4] "litre" GWM + SG_ VehUreaRnge3_L_DsplyMx : 31|16@0+ (1,0) [0|65535] "unitless" GWM + SG_ UreaMxAdd_L2_Actl : 47|9@0+ (0.1,0) [0|51] "litre" GWM + +BO_ 517 PowertrainData_6: 8 PCM_HEV + SG_ FapLc_B_Err : 10|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ BrkTot_Tq_RqFapLc : 7|13@0+ (4,0) [0|32764] "Nm" ABS_ESC,GWM + SG_ TrnAin_Pc_RqDrv : 9|10@0+ (0.1,0) [0|102.3] "percent" TCCM,GWM + +BO_ 516 EngVehicleSpThrottle: 8 PCM_HEV + SG_ EngAoutNActl_D_QF : 31|2@0+ (1,0) [0|3] "SED" TCM_DSL,GWM + SG_ EngAout3_N_Actl : 55|16@0+ (0.25,0) [0|16383.5] "RPM" SOBDMC_HPCM_FD1,GWM + SG_ ApedPos_PcRate_ActlArb : 23|8@0+ (0.04,-5) [-5|5.12] "%/ms" TCM_DSL,GWM + SG_ ApedPos_Pc_ActlArb : 1|10@0+ (0.1,0) [0|102.3] "%" VDM,CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,TCCM,ABS_ESC,PSCM,TCM_DSL,GWM + SG_ ApedPosPcActl_D_Qf : 7|2@0+ (1,0) [0|3] "SED" VDM,CMR_DSMC,IPMA_ADAS,SOBDMC_HPCM_FD1,ABS_ESC,PSCM,TCM_DSL,GWM + SG_ EngAout_N_Actl : 28|13@0+ (2,0) [0|16382] "rpm" VDM,ABS_ESC,PSCM,TCCM,TCM_DSL,GWM + SG_ ApedPosPcActl_No_Cnt : 5|4@0+ (1,0) [0|15] "Unitless" ABS_ESC,SOBDMC_HPCM_FD1,GWM + SG_ ApedPosPcActl_No_Cs : 47|8@0+ (1,0) [0|255] "Unitless" ABS_ESC,SOBDMC_HPCM_FD1,GWM + +BO_ 514 EngVehicleSpThrottle2: 8 PCM_HEV + SG_ StrtrMtrDlyStrt_B_Stat : 39|1@0+ (1,0) [0|1] "SED" GWM + SG_ VehVTrlrAid_B_Avail : 23|1@0+ (1,0) [0|1] "SED" PSCM,GWM + SG_ StrtrMtrCtlMsgTxt_D_Rq : 7|3@0+ (1,0) [0|7] "SED" GWM + SG_ VehVActlEng_No_Cs : 15|8@0+ (1,0) [0|255] "Unitless" PSCM,GWM + SG_ VehVActlEng_No_Cnt : 22|4@0+ (1,0) [0|15] "Unitless" PSCM,GWM + SG_ Veh_V_RqCcSet : 32|9@0+ (0.5,0) [0|255.5] "kph" IPMA_ADAS,ABS_ESC,TCM_DSL,GWM + SG_ VehVActlEng_D_Qf : 38|2@0+ (1,0) [0|3] "SED" VDM,IPMA_ADAS,ABS_ESC,PSCM,TCM_DSL,GWM + SG_ Veh_V_ActlEng : 55|16@0+ (0.01,0) [0|655.35] "kph" VDM,SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,PSCM,TCM_DSL,GWM + SG_ GearRvrse_D_Actl : 4|3@0+ (1,0) [0|7] "SED" CMR_DSMC,IPMA_ADAS,ABS_ESC,PSCM,GWM + SG_ StrtrMtrCtlMsgTxt_D2_Rq : 1|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 512 TorqueDataEngFlags: 8 PCM_HEV + SG_ PrplWhlTotTqRq_No_Cs : 63|8@0+ (1,0) [0|255] "Unitless" ABS_ESC,GWM + SG_ PrplWhlTotTqRq_No_Cnt : 51|4@0+ (1,0) [0|15] "Unitless" ABS_ESC,GWM + SG_ PrplWhlTot_Tq_Rq : 39|16@0+ (4,-131072) [-131072|131068] "Nm" VDM,TCCM,ABS_ESC,GWM + SG_ PrplWhlTot_Tq_LimMn : 23|16@0+ (4,-131072) [-131072|131068] "Nm" ABS_ESC,GWM + SG_ PtDrvMde_D_Stat : 55|4@0+ (1,0) [0|15] "SED" IPMA_ADAS,GWM + +BO_ 381 EngineData_17: 8 ECM_Diesel + SG_ EngOilLife_T_Actl : 23|11@0+ (1,0) [0|2047] "days" GWM + SG_ EngOilSrvcMsgTxt_D_Rq : 55|3@0+ (1,0) [0|7] "SED" GWM + SG_ DistToNextOilChange : 7|16@0+ (1,0) [0|65535] "unitless" GWM + SG_ RunDryPrevent_B_Stat : 28|1@0+ (1,0) [0|1] "SED" GWM + SG_ WaterInFuel : 52|1@0+ (1,0) [0|1] "SED" GWM + SG_ GlowIndication : 51|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 380 EngineData_16: 8 PCM + SG_ EngOilLvlWarn_D_Rq1 : 55|3@0+ (1,0) [0|7] "SED" GWM + SG_ EngExhBrkOnLamp_B_Rq : 27|1@0+ (1,0) [0|1] "SED" GWM + SG_ EngExhBrkAutoLamp_B_Rq : 3|1@0+ (1,0) [0|1] "SED" GWM + SG_ EngAout_N_MxAllw : 52|13@0+ (2,0) [0|16382] "rpm" SOBDMC_HPCM_FD1,GWM + SG_ EngExhBrkMde_D_Actl : 31|4@0+ (1,0) [0|15] "SED" TCM_DSL,GWM + +BO_ 377 EngineData_7: 8 PCM_HEV + SG_ HvacAirFullOut_B_Rq : 23|1@0+ (1,0) [0|1] "SED" GWM + SG_ FuelFlw_Vl_Dsply : 49|10@0+ (25,0) [0|25575] "Micro_Liter" GWM + SG_ FuelFillInlet_B_Dsply : 32|1@0+ (1,0) [0|1] "SED" GWM + SG_ EngSrvcRqd_B_Rq : 19|1@0+ (1,0) [0|1] "SED" GWM + SG_ OdoCount : 47|8@0+ (0.2,0) [0|50.8] "Meters" GWM + SG_ EngOilLife_Pc_Actl : 39|7@0+ (1,0) [0|100] "Percent" GWM + SG_ FuelFilterLamp_B_Dsply : 50|1@0+ (1,0) [0|1] "SED" GWM + SG_ AirCondRec_B_Rq : 55|1@0+ (1,0) [0|1] "SED" GWM + SG_ AirCondClutch_B_Stats : 51|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 376 EngineClimateData: 8 PCM_HEV + SG_ GasPrtc_D_RqDsply : 22|3@0+ (1,0) [0|7] "SED" GWM + SG_ EngAout_Aa_Actl : 17|10@0+ (0.05,-25.6) [-25.6|25.55] "rpm/ms" ABS_ESC,GWM + SG_ DynoMde_B_Cmd : 4|1@0+ (1,0) [0|1] "SED" TCM_DSL,ABS_ESC,GWM + SG_ AslIconDsply_D_Rq : 3|2@0+ (1,0) [0|3] "SED" GWM + SG_ AslChime_B_Rq : 39|1@0+ (1,0) [0|1] "SED" GWM + SG_ HvacHtrCore2_Te_Actl : 1|10@0+ (0.25,-50) [-50|205.5] "degC" SOBDMC_HPCM_FD1,GWM + SG_ EcssLamp_D_RqDsply : 19|2@0+ (1,0) [0|3] "SED" GWM + SG_ AirAmbTe_D_Qf : 35|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,TCCM,GWM + SG_ AirAmb_Te_ActlFilt : 49|10@0+ (0.25,-128) [-128|127.75] "deg C" SOBDMC_HPCM_FD1,IPMA_ADAS,GWM + SG_ AirAmb_Te_Actl : 33|10@0+ (0.25,-128) [-128|127.75] "degC" ABS_ESC,TCCM,GWM + SG_ AirAmb_P_Actl : 55|6@0+ (10,500) [500|1110] "mbar" ABS_ESC,TCM_DSL,GWM + +BO_ 373 EngineData_11: 8 ECM_Diesel + SG_ DieslPrtc2_D_RqDsply : 47|4@0+ (1,0) [0|15] "SED" GWM + SG_ DieslPrtcRgen_D_Actl : 38|2@0+ (1,0) [0|3] "SED" TCM_DSL,GWM + SG_ EngTeColdPrtct_D_Stats : 4|2@0+ (1,0) [0|3] "SED" GWM + SG_ EngExhOvrTe_B_RqDsply : 39|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 359 VehicleOperatingModes: 8 PCM_HEV + SG_ PrplWhlRgenMn_Tq_Actl : 25|13@0+ (4,-16380) [-16380|16380] "Nm" ABS_ESC,GWM + SG_ ElPw_D_StatStrtStop : 31|4@0+ (1,0) [0|15] "SED" ABS_ESC,PSCM,GWM + SG_ TrnAin_Tq_Actl : 42|11@0+ (1,-500) [-500|1547] "Nm" ABS_ESC,GWM + SG_ PrplWhlTot2_Tq_Actl : 15|16@0+ (4,-131072) [-131072|131060] "Nm" ABS_ESC,PSCM,TCCM,GWM + SG_ PwPckTq_D_Stat : 5|2@0+ (1,0) [0|3] "SED" VDM,CMR_DSMC,IPMA_ADAS,ABS_ESC,PSCM,TCCM,TCM_DSL,GWM + SG_ Eng_D_Stat : 7|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + SG_ PlgActvArb_B_Actl : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ ElPw_D_Stat : 3|3@0+ (1,0) [0|7] "SED" VDM,CMR_DSMC,IPMA_ADAS,ABS_ESC,PSCM,TCCM,TCM_DSL,GWM + SG_ TrnAinTq_D_Qf : 44|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + +BO_ 358 Stop_Start: 8 PCM_HEV + SG_ StopStrtStdby_D_Indic : 55|3@0+ (1,0) [0|7] "SED" GWM + SG_ StopStrtIODTxt_D_Rq : 52|5@0+ (1,0) [0|31] "SED" GWM + SG_ StopStrtDrvMde_D_Indic : 13|2@0+ (1,0) [0|3] "SED" GWM + SG_ StopStrtMsgTxt_D_Rq : 11|4@0+ (1,0) [0|15] "SED" GWM + SG_ OdoTripVerify_L_Actl : 31|24@0+ (0.1,0) [0|1677721.4] "km" GWM + SG_ HiElPwInhbt_B_Stat : 15|1@0+ (1,0) [0|1] "SED" GWM + SG_ AutoStopPtDelta_I_Est : 7|8@0+ (1,-127) [-127|127] "Amps" GWM + +BO_ 357 EngBrakeData: 8 PCM_HEV + SG_ BPedDrvAppl_D_QF : 15|2@0+ (1,0) [0|3] "SED" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,PSCM,TCM_DSL,GWM + SG_ CmbbDeny_B_ActlPrpl : 3|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ PrplTqMnSat_B_Actl : 41|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ BpedDrvAppl_D_Actl : 5|2@0+ (1,0) [0|3] "SED" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,PSCM,TCCM,TCM_DSL,GWM + SG_ CmbbEngTqMn_B_Actl : 7|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,GWM + SG_ Veh_V_DsplyCcSet : 23|8@0+ (1,0) [0|253] "Unitless" GWM,IPMA_ADAS + SG_ AccEngStat_D_Actl : 2|3@0+ (1,0) [0|7] "SED" IPMA_ADAS,GWM + SG_ CcMde_D_Actl : 13|3@0+ (1,0) [0|7] "SED" VDM,TCM_DSL,ABS_ESC,GWM + SG_ CcStat_D_Actl : 10|3@0+ (1,0) [0|7] "SED" CMR_DSMC,SOBDMC_HPCM_FD1,IPMA_ADAS,ABS_ESC,TCCM,TCM_DSL,GWM + SG_ EngAout_N_MnAllw : 52|13@0+ (2,0) [0|16382] "rpm" SOBDMC_HPCM_FD1,GWM + SG_ CcOvrrdActv_B_Actl : 6|1@0+ (1,0) [0|1] "SED" VDM,IPMA_ADAS,ABS_ESC,TCCM,TCM_DSL,GWM + SG_ AccStopMde_D_Rq : 39|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,ABS_ESC,GWM + +BO_ 355 EngineData_10: 8 ECM_Diesel + SG_ AutoRgenTxt_B_RqDsply : 48|1@0+ (1,0) [0|1] "SED" GWM + SG_ AccFllwMdeActv_B_Actl : 32|1@0+ (1,0) [0|1] "SED" GWM + SG_ EngPtoMde_D_Actl : 60|3@0+ (1,0) [0|7] "SED" GWM + SG_ ManRgenTxt_D_RqDsply : 63|3@0+ (1,0) [0|7] "SED" GWM + SG_ ManRgenSoot_Pc_RqDsply : 39|7@0+ (1,0) [0|126] "%" GWM + SG_ DieslMsgTxt_D_Rq : 57|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 342 EngineData_6: 8 PCM_HEV + SG_ EngOvrhtMitgActv_D_Ind : 36|2@0+ (1,0) [0|3] "SED" GWM + SG_ EngClntTe_D_Qf : 33|2@0+ (1,0) [0|3] "SED" VDM,SOBDMC_HPCM_FD1,TCM_DSL,GWM + SG_ EngGoutLss_Tq_Est : 31|8@0+ (1,0) [0|255] "Nm" SOBDMC_HPCM_FD1,GWM + SG_ EngOil_Te_Actl : 15|8@0+ (1,-60) [-60|193] "degC" GWM + SG_ EngClnt_Te_Actl : 7|8@0+ (1,-60) [-60|195] "degC" VDM,SOBDMC_HPCM_FD1,TCM_DSL,GWM + +BO_ 71 Global_PATS_TargetInfo: 8 PCM_HEV + SG_ immoTarget1Status : 7|3@0+ (1,0) [0|7] "SED" ABS_ESC,TCM_DSL,GWM + SG_ immoTarget1Data : 15|40@0+ (1,0) [0|1099511627775] "Encrypted" ABS_ESC,GWM + SG_ immoTarget1Cmd : 4|3@0+ (1,0) [0|7] "SED" ABS_ESC,GWM + +BO_ 1822 TesterPhysicalResGWM_FD1: 64 GWM + SG_ TesterPhysicalResGWM_F1 : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1438 GWM_AutoSar_NetMgmt_FD1: 8 GWM + SG_ GWM_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + SG_ GWM_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" PCM_HEV,PCM,SOBDMC_HPCM_FD1,PSCM,ABS_ESC + +BO_ 954 Body_Info_10_FD1: 8 GWM + SG_ GenericSwtch3_No_Actl : 15|3@0+ (1,0) [0|7] "unitless" Vector__XXX + SG_ GenericSwtch2_No_Actl : 4|3@0+ (1,0) [0|7] "unitless" Vector__XXX + SG_ GenericSwtch1_No_Actl : 7|3@0+ (1,0) [0|7] "unitless" Vector__XXX + +BO_ 1006 Personality_IPMB_Data: 8 IPMA_ADAS + SG_ PersIndexIpmb_D_Actl : 39|3@0+ (1,0) [0|7] "SED" GWM + SG_ FeatNoIpmbActl : 23|16@0+ (1,0) [0|65535] "Number" GWM + SG_ FeatConfigIpmbActl : 7|16@0+ (1,0) [0|65535] "Undefined" GWM + +BO_ 820 Adaptive_Headlamp_Stat: 8 GWM + SG_ AhbStatGfhbFdbk_D_Actl : 53|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ HeadLghtDrvSide_B_Stat : 33|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ HeadLghtHiOn_B_StatHcm : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Adaptive_Hdlmp_Fault : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 137 ActiveFrontStrg_Stat_FD1: 8 GWM + SG_ SteWhlOffstRq_D_Stat : 43|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ SteWhlOffst_An_TotActl : 23|15@0+ (0.1,-1600) [-1600|1676.5] "degrees" ABS_ESC + SG_ SteWhlBrkOffst_An_Actl : 7|15@0+ (0.1,-1600) [-1600|1676.5] "degrees" ABS_ESC + SG_ SteWhlBrkAnActl_No_Cs : 39|8@0+ (1,0) [0|255] "Unitless" ABS_ESC + SG_ SteWhlBrkAnActl_No_Cnt : 47|4@0+ (1,0) [0|15] "Unitless" ABS_ESC + +BO_ 129 Steering_Wheel_Data2_FD1: 8 GWM + SG_ SelDrvMdeSwtch_D_Stat4 : 21|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ SteWhlSwtchView_B_Stat : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchSet_B_Stat : 8|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchPhon_B_Stat : 9|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchNav_B_Stat : 10|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchMed_B_Stat : 11|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchIod_B_Stat : 12|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchHud_B_Stat : 13|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchBack_B_Stat : 14|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchMenu_B_Stat : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteEffortInc_B_RqDrv : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SelDrvMdeInc_B_RqDrv : 6|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SelDrvMdeDec_B_RqDrv : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SuspDampInc_B_RqDrv : 15|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchUp_B_Stat : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchRght_B_Stat : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchOk_B_Stat : 4|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchLeft_B_Stat : 1|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchDown_B_Stat : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchHome_B_Stat : 19|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ SteWhlSwtchInfo_B_Stat : 18|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 935 Side_Detect_R_Stat: 8 IPMA_ADAS + SG_ SodRight_D_Stat : 15|3@0+ (1,0) [0|7] "SED" GWM + SG_ CtaAlrtRight2_D_Stat : 30|3@0+ (1,0) [0|7] "SED" GWM + SG_ BttRight_D_Stat : 45|3@0+ (1,0) [0|7] "SED" GWM + SG_ BttRight_D_RqDrv : 47|2@0+ (1,0) [0|3] "SED" GWM + SG_ CtaBrkRightMsgTxt_B_Rq : 42|1@0+ (1,0) [0|1] "SED" GWM + SG_ CtaRightBrkEnbl_B_Rq : 31|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ CtaRightBrkDecel_B_Rq : 7|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ Side_Detect_R_Illum : 39|8@0+ (1,0) [0|255] "Percent" GWM + SG_ CtaSnsRight_D_Stat : 25|2@0+ (1,0) [0|3] "SED" GWM + SG_ CtaAlrtRight_D_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ CtaRight_D_Stat : 18|3@0+ (1,0) [0|7] "SED" GWM + SG_ SodSnsRight_D_Stat : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ SodAlrtRight_D_Stat : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ SodDetctRight_D_Stat : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ SodWarnRight_Prd_Rq : 6|7@0+ (1,0) [0|127] "millisecond" GWM + +BO_ 1108 RCMSerialNumber_FD1: 8 GWM + SG_ RCMSerialNoByte8 : 63|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte7 : 55|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte6 : 47|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte5 : 39|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte4 : 31|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte3 : 23|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte2 : 15|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + SG_ RCMSerialNoByte1 : 7|8@0+ (1,0) [0|253] "Unitless" ABS_ESC + +BO_ 261 APIM_Request_Signals_FD1: 8 GWM + SG_ ChrgStatDsply_D_Rq : 47|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ OffPeakTimeSetMin_Rq : 13|6@0+ (1,0) [0|63] "unitless" Vector__XXX + SG_ OffPeakTimeSetHR_Rq : 7|5@0+ (1,0) [0|31] "unitless" Vector__XXX + SG_ NextUsageTimeToggle_Rq : 15|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ LongTermParking_Rq : 17|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ CbnCmrtPrefLstNmItm_Rq : 31|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ CbnCmrtPrefListIndx_Rq : 39|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ ModemReset_D_Rq : 45|4@0+ (1,0) [0|15] "SED" SOBDMC_HPCM_FD1 + SG_ StopStrtDrvMde_B_RqBtn3 : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TCU_ESN_D_Rq : 22|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ FactoryReset_Rq : 18|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + +BO_ 1146 TrailerInfo_2_FD1: 8 GWM + SG_ TrlrAidSwtch_D_RqDrv : 35|2@0+ (1,0) [0|3] "SED" PSCM,IPMA_ADAS + SG_ TrlrAidCtl_U_RqDrv : 31|12@0+ (0.00125,0) [0|5.11625] "volt" PSCM + +BO_ 533 APIM_Send_Signals_2_FD1: 8 GWM + SG_ DcacGfciTestBttn_B_Stat : 9|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ TrlrBrkGain_No_Rq : 55|5@0+ (0.5,0) [0|15.5] "unitless" Vector__XXX + SG_ DcacPwResetButtn_B_Stat : 11|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacPwOffButtn_B_Stat : 12|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacPwLoButtn_B_Stat : 13|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacPwHiButtn_B_Stat : 14|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacPwButtn_B_Falt : 15|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ TrlrHitch_D_RqMnu : 23|4@0+ (1,0) [0|15] "SED" IPMA_ADAS + SG_ AutoEpbZoomView_B_Stat : 32|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ AutoEpbButtn_B_Stat : 19|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ TrlrAidMde_D_Rq : 5|2@0+ (1,0) [0|3] "SED" PSCM + SG_ TCU_Init_Actvtn_St : 1|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TCU_Final_Actvtn_St : 3|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ OtaTrg_D_Stat : 41|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ OnbChrgGoTTouch_D_Rq : 43|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTPrcond_D_Rq : 34|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTOn_D_Rq : 25|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTMnte_D_Rq : 47|4@0+ (1,0) [0|15] "minute" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTHr_T_Rq : 39|5@0+ (1,0) [0|29] "hour" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTExtHtr_D_Rq : 27|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTElement_D_Rq : 31|4@0+ (1,0) [0|15] "Unitless" SOBDMC_HPCM_FD1 + SG_ OnbChrgGoTDelete_B_Rq : 17|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ OnbChrgClearAll_B_Rq : 18|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ PaakMyKey_D_Rq : 7|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ OnbChrgGoTUpdate_B_Rq : 16|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + +BO_ 1041 AC_Compressor_Data_FD1: 8 GWM + SG_ ElCmprUHi_U_Actl : 31|8@0+ (2,0) [0|510] "volt" SOBDMC_HPCM_FD1 + SG_ ElCmprUHi_D_Stat : 23|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprOverTe_D_Stat : 21|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmpr_N_Actl : 15|8@0+ (50,0) [0|12700] "RPM" SOBDMC_HPCM_FD1 + SG_ ElCmpr_Pw_Actl : 7|8@0+ (40,0) [0|10160] "watts" SOBDMC_HPCM_FD1,PCM_HEV + SG_ ElCmpr_D_Stat : 19|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprPerfErr_D_Falt : 43|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprInnrErr_D_Falt : 35|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprLostComm_D_Falt : 33|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprOverLoad_D_Falt : 47|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprOverTe_D_Falt : 45|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprBattURng_D_Falt : 37|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprBattSysU_D_Falt : 39|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ ElCmprSysU_D_Falt : 41|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + +BO_ 1067 Battery_Mgmt_4_FD1: 8 GWM + SG_ BattULoAuxIsol_D_Rq : 25|2@0+ (1,0) [0|3] "SED" PCM_HEV + SG_ BattULoAux_U_Rq : 55|12@0+ (0.00390625,0) [0|15.9921875] "volt" PCM_HEV + SG_ BattULoAuxSoc_Pc_Actl : 15|7@0+ (1,0) [0|127] "percent" PCM_HEV + SG_ BattULoAux_I_Actl : 23|12@0+ (0.0625,-128) [-128|127.875] "ampere" PCM_HEV + SG_ BattULoAux_D_Qlty : 27|2@0+ (1,0) [0|3] "SED" PCM_HEV + SG_ BattULoCrnkStrt_U_Pred : 47|7@0+ (0.1,0) [0|12.7] "volt" PCM_HEV + SG_ BattULoCrnkBelt_U_Pred : 39|7@0+ (0.1,0) [0|12.7] "volt" PCM_HEV + SG_ BattULoAux_U_Actl : 7|8@0+ (0.0625,0) [0|15.875] "volt" PCM_HEV + SG_ BattULoAux_B_Falt : 8|1@0+ (1,0) [0|1] "SED" PCM_HEV + +BO_ 1112 Battery_Traction_6_FD1: 8 GWM + SG_ BattTracChrgSustn_B_Rq : 4|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracCnnct_D_Cmd : 18|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracHvilOpen_B_Stat : 8|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracDcdcDis_B_Rq : 7|1@0+ (1,0) [0|1] "SED" PCM_HEV + SG_ HtrnClntPump_D_Stat : 6|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ BattTracDelta_Te_Actl : 63|8@0+ (0.5,-60) [-60|67.5] "degC" SOBDMC_HPCM_FD1 + SG_ BattTracClntPmp_D_Stat : 33|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + +BO_ 139 CruiseCtrl_Strg_Data_FD1: 8 GWM + SG_ AfsPw_B_Rq : 24|1@0+ (1,0) [0|1] "SED" PCM + SG_ AccButtnGpTogglePress2 : 25|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TjaButtnOnOffPress2 : 26|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ActvFrontSteMsgTxt_D_Rq : 31|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ ActvFrontSteLck_D_Stat : 17|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ SelDrvMdeAdptSte_D_Stat : 28|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ AslButtnOnOffPress2 : 4|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AslButtnOnOffCnclPres2 : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcButtnOnPress2 : 18|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcButtnOnOffPress2 : 19|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcButtnOnOffCnclPress2 : 20|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcButtnOffPress2 : 21|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAsllButtnResPress2 : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnSetPress2 : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnSetIncPress2 : 8|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnSetDecPress2 : 9|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnResIncPress2 : 10|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnResDecPress2 : 11|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnOnPress2 : 12|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnOnOffCncl2 : 13|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnOffCnclPres2 : 14|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnIndxIncPres2 : 15|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnIndxDecPres2 : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnDeny_B_Actl2 : 1|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnCnclResPres2 : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnCnclPress2 : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AccButtnGapIncPress2 : 6|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AccButtnGapDecPress2 : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 1121 AllTerrainControlData_FD1: 8 GWM + SG_ SelDrvMdeSwtch_No_Actl : 2|2@0+ (1,0) [0|3] "unitless" ABS_ESC + SG_ SelDrvMdeSwtch_D_Stat : 4|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ SelDrvMdeCnt_D_Stat : 7|3@0+ (1,0) [0|7] "Counts" ABS_ESC + +BO_ 1120 FourByFourSwitchData_FD1: 8 GWM + SG_ DrvSlipCtlMde_B_Rq3 : 14|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ HybMdeSwtch_B_Rq : 13|1@0+ (1,0) [0|1] "SED" PCM_HEV + SG_ TrailCtlSwtch_B_Stat3 : 15|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ RearDiffLck_D_RqDrv : 4|2@0+ (1,0) [0|3] "SED" PCM,TCCM + SG_ AwdMde_D_RqDrv : 7|3@0+ (1,0) [0|7] "SED" TCCM + SG_ HdcSwtchPos_B_Actl : 0|1@0+ (1,0) [0|1] "SED" ABS_ESC + +BO_ 1050 Climate_Control_Data_FD1: 8 GWM + SG_ AutoHoldSwtch_D_Stat : 20|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ LpdbPtc3_B_Rq : 36|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ LpdbPtc2_B_Rq : 37|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ LpdbPtc1_B_Rq : 38|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ LpdbHeatWiprPrk_B_Rq : 39|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ LpdbDfrstRearOn_B_Rq : 24|1@0+ (1,0) [0|1] "SED" ECM_Diesel + SG_ SteWhlHeat_D_Rq : 13|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ MirrorHeatOn_B_Rq : 14|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Remote_Start_QuietMode : 15|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Outside_Air_Temp_Stat : 7|8@0+ (0.5,-40) [-40|86.5] "Degrees C" VDM,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,PSCM + +BO_ 1137 Cluster_HEV_Data10_FD1: 8 PCM_HEV + SG_ RngPerChrgAvg_L_Dsply : 7|12@0+ (0.1,0) [0|409.3] "km" GWM + +BO_ 1255 BoundaryAlert_Right_4: 8 IPMA_ADAS + SG_ BalrRight4Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight4Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight4Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight4CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight4CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1254 BoundaryAlert_Right_3: 8 IPMA_ADAS + SG_ BalrRight3Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight3Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight3Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight3CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight3CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1253 BoundaryAlert_Right_2: 8 IPMA_ADAS + SG_ BalrRight2Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight2Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight2Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight2CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight2CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1252 BoundaryAlert_Right_1: 8 IPMA_ADAS + SG_ BalrRight1Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight1Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight1Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrRight1CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrRight1CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1251 BoundaryAlert_Left_4: 8 IPMA_ADAS + SG_ BalrLeft4Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft4Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft4Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft4CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft4CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1250 BoundaryAlert_Left_3: 8 IPMA_ADAS + SG_ BalrLeft3Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft3Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft3Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft3CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft3CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1249 BoundaryAlert_Left_2: 8 IPMA_ADAS + SG_ BalrLeft2Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft2Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft2Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft2CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft2CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1248 BoundaryAlert_Left_1: 8 IPMA_ADAS + SG_ BalrLeft1Threat_D_Stat : 16|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft1Prev3Y_L_Actl : 51|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1Prev3X_L_Actl : 42|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1Prev2Y_L_Actl : 33|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1Prev2X_L_Actl : 24|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1Prev1Y_L_Actl : 31|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1Prev1X_L_Actl : 23|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1Fast_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft1Dsply_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrLeft1CurntY_L_Actl : 15|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + SG_ BalrLeft1CurntX_L_Actl : 7|7@0+ (0.5,-32) [-32|31.5] "meter" GWM + +BO_ 1113 TrailerAid_Stat3: 8 IPMA_ADAS + SG_ TrlrTrgtAcquire_D_Stat : 51|3@0+ (1,0) [0|7] "SED" PSCM,GWM + SG_ TrlrAnOffst_An_Calc : 48|9@0+ (0.1,0) [0|51.1] "degrees" GWM + SG_ TrlrAnOffstDir_D_Calc : 33|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrlrAnCalib_B_Complt : 40|1@0+ (1,0) [0|1] "SED" GWM + SG_ TrlrRvrse_D_Stat : 42|2@0+ (1,0) [0|3] "SED" GWM,PSCM + SG_ TrlrAid_D2_Stat : 55|4@0+ (1,0) [0|15] "SED" GWM,PSCM + SG_ TrlrAidTrgtId_No_Actl : 47|5@0+ (1,0) [0|31] "unitless" GWM,PSCM + SG_ TrlrAid_An3_Actl : 28|11@0+ (0.125,-90) [-90|165.75] "degrees" PSCM,GWM + SG_ TrlrAid_AnRate2_Actl : 22|10@0+ (0.125,-50) [-50|77.75] "degrees/second" PSCM,GWM + SG_ HitchToVehAxle_L_Calc : 7|8@0+ (0.0127,-0.508) [-0.508|2.7178] "meter" PSCM,GWM + SG_ HitchToTrlrAxle_L_Calc2 : 15|9@0+ (0.0254,0) [0|12.9794] "meter" GWM + +BO_ 1105 Image_Processing_Data: 8 IPMA_ADAS + SG_ TrlrAidSwtchLamp_B_Rq : 32|1@0+ (1,0) [0|1] "SED" GWM + SG_ TrlrHitchMsgTxt_D_Rq : 47|6@0+ (1,0) [0|63] "SED" GWM + SG_ TrlrHitchIcon_D_Rq : 36|4@0+ (1,0) [0|15] "SED" GWM + SG_ TrlrHitchChime_D_Rq : 39|3@0+ (1,0) [0|7] "SED" GWM + SG_ TrlrAidEnbl_D_RqAdas : 5|3@0+ (1,0) [0|7] "SED" GWM,PSCM + SG_ TrlrRvrseMsgTxt_D2_Rq : 31|6@0+ (1,0) [0|63] "SED" PSCM,GWM + SG_ TrlrRvrseEnbl_D2_Stat : 18|3@0+ (1,0) [0|7] "SED" PSCM,GWM + SG_ RbaMsg_D_Rq : 22|2@0+ (1,0) [0|3] "SED" GWM + SG_ BrkDecel_B_RqRba : 8|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ BrkEnbl_B_RqRba : 23|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ Rba_D_Stat : 14|2@0+ (1,0) [0|3] "SED" GWM + SG_ RbaAlrt_D_Dsply : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ RbaMnu_D_Rq : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ CamraFrntStat_D_Stat : 7|2@0+ (1,0) [0|3] "SED" GWM + SG_ TrlrHitchLamp_D_Rq2 : 15|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 938 ParkAid_Aud_Warn_Stat: 8 IPMA_ADAS + SG_ SidePrkSnsR2_D_Stat : 59|4@0+ (1,0) [0|15] "SED" GWM + SG_ SidePrkSnsR1_D_Stat : 63|4@0+ (1,0) [0|15] "SED" GWM + SG_ SidePrkSnsL2_D_Stat : 51|4@0+ (1,0) [0|15] "SED" GWM + SG_ ApaMde_D_Stat : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ ApaActvSd_D_Actl : 14|2@0+ (1,0) [0|3] "SED" GWM + SG_ PrkAidSwtch_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ ApaMde_D_Avail : 12|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsFrCrnr_D_Stat : 47|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsFrCntr_D_Stat : 35|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsFlCrnr_D_Stat : 27|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsFlCntr_D_Stat : 31|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkBrkEl_B_RqFap : 20|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ RpaChime_D_Rq : 7|4@0+ (1,0) [0|15] "SED" GWM + SG_ FpaChime_D_Rq : 3|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidMsgTxt_D_Rq : 19|4@0+ (1,0) [0|15] "SED" GWM,PSCM + SG_ SidePrkSnsL1_D_Stat : 55|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidAudioMute_B_Rq : 15|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 939 ParkAid_Aud_Warn_Stat2: 8 IPMA_ADAS + SG_ ApaBrk_D_Rq : 51|2@0+ (1,0) [0|3] "SED" GWM + SG_ SidePrkSnsR4_D_Stat : 55|4@0+ (1,0) [0|15] "SED" GWM + SG_ SidePrkSnsR3_D_Stat : 47|4@0+ (1,0) [0|15] "SED" GWM + SG_ SidePrkSnsL4_D_Stat : 43|4@0+ (1,0) [0|15] "SED" GWM + SG_ SidePrkSnsL3_D_Stat : 37|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidChime_D_Stat : 4|2@0+ (1,0) [0|3] "SED" GWM + SG_ PrkAidSnsRlCntr_D_Stat : 15|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsRrCrnr_D_Stat : 31|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsRrCntr_D_Stat : 19|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidSnsRlCrnr_D_Stat : 11|4@0+ (1,0) [0|15] "SED" GWM + SG_ PrkAidRear_D_Stat : 39|2@0+ (1,0) [0|3] "SED" GWM + SG_ PrkAidFront_D_Stat : 2|2@0+ (1,0) [0|3] "SED" GWM + SG_ PrkAid_D_Falt : 7|3@0+ (1,0) [0|7] "SED" GWM + SG_ ApaLongCtrlEnbl_D_Rq : 0|1@0+ (1,0) [0|1] "SED" ABS_ESC,ECM_Diesel,PCM,PCM_HEV,TCM_DSL,GWM + SG_ ApaBrk_A_Rq : 63|8@0+ (0.05,-12.75) [-12.75|0] "m/sec^2" ABS_ESC,ECM_Diesel,PCM,PCM_HEV,GWM + SG_ PrkAidLamp_D_Rq : 33|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 937 ParkAid_Data_2: 8 IPMA_ADAS + SG_ Veh_V_RqFap : 31|8@0+ (0.1,0) [0|25.5] "km/h" ECM_Diesel,PCM,PCM_HEV + SG_ TrnRngDRqFap_No_Cs : 23|8@0+ (1,0) [0|255] "unitless" PCM,PCM_HEV,TCM_DSL + SG_ TrnRngDRqFap_No_Cnt : 15|4@0+ (1,0) [0|15] "unitless" PCM,PCM_HEV,TCM_DSL + SG_ TrnRng_D_RqFap : 11|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM,PCM_HEV,TCM_DSL,GWM + SG_ FapLcDistToObj_L_Actl : 7|8@0+ (0.01,0) [0|2.53] "meter" ECM_Diesel,PCM,PCM_HEV + +BO_ 936 ParkAid_Data: 8 IPMA_ADAS + SG_ ApaButtnPrssd_B_Stat : 58|1@0+ (1,0) [0|1] "SED" PSCM + SG_ SAPPStatusCoding : 7|8@0+ (1,0) [0|255] "unitless" GWM + SG_ ApaSys_D_Stat : 61|3@0+ (1,0) [0|7] "SED" PSCM,GWM,ECM_Diesel,PCM,PCM_HEV + SG_ ApaSteWhl_D_RqDrv : 63|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaSteScanMde_D_Stat : 49|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaSelSapp_D_Stat : 51|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaSelPpa_D_Stat : 53|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaSelPoa_D_Stat : 55|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaScan_D_Stat : 41|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaLongCtl_D_RqDrv : 44|3@0+ (1,0) [0|7] "SED" GWM + SG_ ApaGearShif_D_RqDrv : 47|3@0+ (1,0) [0|7] "SED" GWM + SG_ ApaActvSide2_D_Stat : 33|2@0+ (1,0) [0|3] "SED" GWM + SG_ ApaAcsy_D_RqDrv : 36|3@0+ (1,0) [0|7] "SED" GWM + SG_ ApaTrgtDist_D_Stat : 11|4@0+ (1,0) [0|15] "SED" GWM + SG_ ApaMsgTxt_D_Rq : 15|4@0+ (1,0) [0|15] "SED" GWM + SG_ ApaChime_D_Rq : 39|3@0+ (1,0) [0|7] "SED" GWM + SG_ EPASExtAngleStatReq : 23|1@0+ (1,0) [0|1] "SED" PSCM,GWM,ABS_ESC + SG_ ExtSteeringAngleReq2 : 22|15@0+ (0.1,-1000) [-1000|2276.5] "Degrees" GWM,PSCM + +BO_ 877 HEV_Powertrain_Data7_FD1: 8 PCM_HEV + SG_ RngImpctDrv_L_Dsply : 39|9@0+ (1,-255) [-255|256] "km" GWM + SG_ RngImpctClim_L_Dsply : 16|9@0+ (1,-255) [-255|256] "km" GWM + SG_ VehElEffAvg_No_Dsply : 23|7@0+ (10,-100) [-100|1150] "wattHr/km" GWM + SG_ PwFlwFuelDrv_D_Dsply : 15|3@0+ (1,0) [0|7] "SED" GWM + SG_ PwFlwFuelClimt_B_Dsply : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwFlwFuelBatt_B_Dsply : 1|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwFlwBattClimt_B_Dsply : 3|1@0+ (1,0) [0|1] "SED" GWM + SG_ PwFlwBatt_D_Dsply : 7|4@0+ (1,0) [0|15] "SED" GWM + +BO_ 589 Battery_Traction_5_FD1: 8 GWM + SG_ BattTrac2_Pw_LimChrg : 31|13@0+ (50,0) [0|409550] "watts" PCM_HEV + SG_ BattTrac2_Pw_LimDchrg : 34|13@0+ (50,0) [0|409550] "watts" PCM_HEV + SG_ BattTrac2_Pw_DchrgInst : 53|13@0+ (50,0) [0|409550] "watts" PCM_HEV + SG_ BattTrac2_Pw_ChrgInst : 7|13@0+ (50,0) [0|409550] "watts" PCM_HEV + +BO_ 588 Battery_Traction_4_FD1: 8 GWM + SG_ BattTracSoc2_Pc_Actl : 29|14@0+ (0.01,0) [0|163.81] "%" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTrac_Te_Actl : 9|10@0+ (0.5,-50) [-50|460.5] "degC" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracDiagClr_B_Rq : 30|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 587 Battery_Traction_3_FD1: 8 GWM + SG_ BattTracClnt_Te_Actl : 41|8@0+ (0.5,-60) [-60|67.5] "degC" SOBDMC_HPCM_FD1 + SG_ BattTracWarnLamp_B_Rq : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ BattTracSrvcRqd_B_Rq : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ BattTracSoc_Pc_MxPrtct : 35|10@0+ (0.1,0) [0|100] "%" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracSoc_Pc_MnPrtct : 29|10@0+ (0.1,0) [0|100] "%" PCM_HEV + SG_ BattTracSoc_Pc_LimLo : 23|10@0+ (0.1,0) [0|100] "%" PCM_HEV + SG_ BattTracSoc_Pc_LimHi : 1|10@0+ (0.1,0) [0|100] "%" PCM_HEV + +BO_ 389 PreCond_Hev_Data2_FD1: 8 SOBDMC_HPCM_FD1 + SG_ BattTracClntFlw_Pc_Rq : 63|7@0+ (1,0) [0|127] "percent" GWM + SG_ HtrnOvrTeLamp_B_Dsply : 5|1@0+ (1,0) [0|1] "SED" GWM + SG_ HtrnMil_D_Rq : 7|2@0+ (1,0) [0|3] "SED" GWM + SG_ HtrnAin_UHi_Actl : 39|10@0+ (0.5,0) [0|510.5] "volt" GWM,PCM_HEV + SG_ HtrnSrvcRqd_B_Dsply : 3|1@0+ (1,0) [0|1] "SED" GWM + SG_ HtrnHvilOpen_B_Actl : 24|1@0+ (1,0) [0|1] "SED" GWM,PCM_HEV + SG_ PtWakeupDeltaT_T_Rq : 2|11@0+ (1,0) [0|2045] "minute" GWM + SG_ PreCondActv_B_Actl : 50|1@0+ (1,0) [0|1] "SED" GWM + SG_ DrvCondTpRrDefrs_B_Rq : 49|1@0+ (1,0) [0|1] "SED" GWM + SG_ BattTrac_I_EstVsc : 23|15@0+ (0.05,-750) [-750|888.25] "Amps" GWM + +BO_ 1009 APIM_Send_Signals1_FD1: 8 GWM + SG_ ChrgCordUnlock_B_Rq : 60|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AutoHoldSwtch_D_Stat3 : 50|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ TrlrTrgtAcquire_D_Rq : 63|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ TrlrAidCancl_B_Rq : 48|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,PSCM + SG_ CenterStackRing_D_Actl : 59|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ APIM_NumberofTracks_St : 39|16@0+ (1,0) [0|65535] "unitless" Vector__XXX + SG_ APIM_ActiveTrackNum_St : 7|32@0+ (1,0) [0|4294967295] "unitless" Vector__XXX + SG_ ValetMode_D_Stat : 57|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TrlrAidSetup_D_Stat : 55|3@0+ (1,0) [0|7] "SED" Vector__XXX + +BO_ 360 Gear_Shift_by_Wire_2_FD1: 8 GWM + SG_ GsmSrvcRqd_B_Rq : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TrnGearPwmFalt_B_Actl : 15|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ GearButtnStuck_B_Actl : 14|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + +BO_ 122 Battery_Traction_1_FD1: 8 GWM + SG_ BattTrac_U_LimLo : 47|8@0+ (2,0) [0|510] "volt" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTrac_U_LimHi : 39|8@0+ (2,0) [0|510] "volt" SOBDMC_HPCM_FD1,PCM_HEV + SG_ VehStrtInhbt_B_RqBatt : 23|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracOffFst_D_Actl : 22|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracOff_B_Actl : 20|1@0+ (1,0) [0|1] "SED" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTracMil_D_Rq : 19|2@0+ (1,0) [0|3] "SED" PCM_HEV + SG_ BattTrac_U_Actl : 17|10@0+ (0.5,0) [0|510.5] "Volts" SOBDMC_HPCM_FD1,PCM_HEV + SG_ BattTrac_I_Actl : 6|15@0+ (0.05,-750) [-750|888.25] "Amps" SOBDMC_HPCM_FD1,PCM_HEV + +BO_ 90 Gear_Shift_by_Wire_FD1: 8 GWM + SG_ TrnGsmNtmState_D_Actl : 55|2@0+ (1,0) [0|3] "SED" ABS_ESC,PCM,PCM_HEV,TCM_DSL + SG_ DrQltyDrv_D_StatGsm : 42|3@0+ (1,0) [0|7] "SED" ABS_ESC,PCM,PCM_HEV,TCM_DSL,IPMA_ADAS + SG_ TrnBtsiOvrrd_B_Stat : 43|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ GsmGearMsgTxt_D_Rq : 63|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TrnRng_D_RqGsm : 51|4@0+ (1,0) [0|15] "SED" PCM,TCM_DSL + SG_ PrkBrkActv_D_RqGsmGear : 53|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ TrnValidGearRq_D_Stat : 25|2@0+ (1,0) [0|3] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearRqCnt_B_Actl : 26|1@0+ (1,0) [0|1] "unitless" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_U_Actl : 23|8@0+ (0.05,0) [0|12.7] "VOLT" TCM_DSL + SG_ TrnGearButtn_B_ActlR2 : 8|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlR1 : 9|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlR0 : 10|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlP2 : 11|1@0+ (1,0) [0|1] "SED" TCM_DSL,PCM,PCM_HEV + SG_ TrnGearButtn_B_ActlP1 : 12|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlP0 : 13|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlN2 : 14|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlN1 : 15|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlN0 : 0|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlM2 : 1|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlM1 : 2|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlM0 : 3|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlD2 : 4|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlD1 : 5|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGearButtn_B_ActlD0 : 6|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ TrnGear_No_Cs : 39|8@0+ (1,0) [0|255] "Unitless" SOBDMC_HPCM_FD1,PCM,PCM_HEV,TCM_DSL + SG_ TrnGear_No_Cnt : 47|4@0+ (1,0) [0|15] "Unitless" SOBDMC_HPCM_FD1,PCM,PCM_HEV,TCM_DSL + SG_ TrnGear_D_RqDrv : 31|5@0+ (1,0) [0|31] "SED" SOBDMC_HPCM_FD1,PCM,PCM_HEV,TCM_DSL + SG_ BrkSwtchPos_B_ActlGsm : 7|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + +BO_ 1091 TrailerInfo_FD1: 8 GWM + SG_ ParkLampTrlrOut_B_Stat : 15|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TrlrLampCtl_D_Stat : 4|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TrlrBattChrg_D_Stat : 2|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ StopLampTrlrOut_B_Stat : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TurnLampTrlrRr_B_Stat : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TurnLampTrlrRl_B_Stat : 6|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TrlrLampCnnct_B_Actl : 7|1@0+ (1,0) [0|1] "SED" VDM,PCM_HEV,ECM_Diesel,PCM,TCM_DSL,ABS_ESC,IPMA_ADAS,PSCM + +BO_ 138 ActiveFrontStrg_Stat2_FD1: 8 GWM + SG_ SteWhlRelCalib_T_Actl : 7|8@0+ (1,0) [0|255] "ms" ABS_ESC + SG_ SteWhlRelCalib_An_Sns : 15|15@0+ (0.1,-1600) [-1600|1676.5] "deg" CMR_DSMC,PSCM,TCCM + +BO_ 131 Steering_Data_FD1: 8 GWM + SG_ HeadLghtHiFlash_D_Stat : 7|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TurnLghtSwtch_D_Stat : 5|2@0+ (1,0) [0|3] "SED" IPMA_ADAS,PSCM + SG_ WiprFront_D_Stat : 3|4@0+ (1,0) [0|15] "SED" ABS_ESC,IPMA_ADAS,PCM,PCM_HEV + SG_ LghtAmb_D_Sns : 15|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ AccButtnGapDecPress : 12|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ AccButtnGapIncPress : 11|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ AslButtnOnOffCnclPress : 10|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ AslButtnOnOffPress : 9|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ CcAslButtnCnclPress : 8|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ LaSwtchPos_D_Stat : 23|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ CcAslButtnCnclResPress : 21|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcAslButtnDeny_B_Actl : 20|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcAslButtnIndxDecPress : 19|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ CcAslButtnIndxIncPress : 18|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ CcAslButtnOffCnclPress : 17|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnOnOffCncl : 16|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnOnPress : 31|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcAslButtnResDecPress : 30|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAslButtnResIncPress : 29|1@0+ (1,0) [0|1] "SED" ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcAslButtnSetDecPress : 28|1@0+ (1,0) [0|1] "SED" ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcAslButtnSetIncPress : 27|1@0+ (1,0) [0|1] "SED" ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcAslButtnSetPress : 26|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CcAsllButtnResPress : 25|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcButtnOffPress : 24|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcButtnOnOffCnclPress : 39|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcButtnOnOffPress : 38|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ CcButtnOnPress : 37|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ HeadLghtHiFlash_D_Actl : 36|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ HeadLghtHiOn_B_StatAhb : 34|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ AhbStat_B_Dsply : 33|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AccButtnGapTogglePress : 32|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ WiprFrontSwtch_D_Stat : 47|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ HeadLghtHiCtrl_D_RqAhb : 43|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ TjaButtnOnOffPress : 40|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + +BO_ 787 Power_Liftgate_Stat_FD1: 8 GWM + SG_ DrLckCnt_No_ActlTgate : 12|4@0+ (1,0) [0|15] "unitless" Vector__XXX + SG_ DrTgateChime2_D_Rq : 15|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ DrTGate_D_Rq : 2|2@0+ (1,0) [0|3] "SED" ECM_Diesel + SG_ PwLftgtIntSw_B_Stat : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Power_Liftgate_Mode_Stt : 4|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 953 Body_Info_8_FD1: 8 GWM + SG_ BattRgenLoDChrg_D_Rq : 27|2@0+ (1,0) [0|3] "SED" PCM_HEV,PCM + SG_ BattRgenLoChrg_D_Rq : 25|2@0+ (1,0) [0|3] "SED" PCM_HEV,PCM + SG_ ChrgCordLck_B_Stat : 31|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ChrgCordResp2_No_Actl : 23|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ ChrgCordResp1_No_Actl : 15|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ WakeAlarm3_D_Stat : 1|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ WakeAlarm2_D_Stat : 3|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ WakeAlarm1_D_Stat : 5|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM_HEV + SG_ WakeAlarm0_D_Stat : 7|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + +BO_ 1093 TrailerBrakeInfo_FD1: 8 GWM + SG_ TrlBrkInitOut_D_Stat : 10|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TrlrBrkOut_No_Dsply : 23|4@0+ (1,0) [0|15] "unitless" Vector__XXX + SG_ TrlrBrkMde_D_Actl : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TrlrBrkGain_No_Actl : 15|5@0+ (0.5,0) [0|15.5] "unitless" Vector__XXX + SG_ TrlrBrkDsply_B_Rq : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TrlrBrkDcnnt_B_Actl : 5|1@0+ (1,0) [0|1] "SED" VDM + SG_ TrlrBrkActCnnct_B_Actl : 6|1@0+ (1,0) [0|1] "SED" VDM,ECM_Diesel,PCM,TCM_DSL,ABS_ESC,PSCM,TCCM,IPMA_ADAS + SG_ StopLamp_B_RqTrlrBrk : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TrlrBrkCtl_B_Falt : 4|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ TrlrBrkActCirct_B_Falt : 1|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + +BO_ 792 IPC_Send_Signals_2_FD1: 8 GWM + SG_ FuelRange_L_Dsply : 45|14@0+ (0.1,0) [0|1638.3] "km" ECM_Diesel + SG_ ElTrip_L_Dsply : 31|16@0+ (0.1,0) [0|6553.3] "unitless" Vector__XXX + SG_ ElLongTerm_L_Dsply : 7|24@0+ (0.1,0) [0|1677721.3] "unitless" Vector__XXX + +BO_ 968 Cluster_Lighting_Rq_FD1: 8 GWM + SG_ SlMde_D_Rq : 27|2@0+ (1,0) [0|3] "SED" ECM_Diesel + SG_ IsaOffst_D_Rq : 31|4@0+ (1,0) [0|15] "SED" ECM_Diesel + +BO_ 819 Pass_Dr_Stat_FD1: 8 GWM + SG_ RollCode_No_ActlPdm : 31|16@0+ (1,0) [0|65535] "Unitless" Vector__XXX + SG_ Memory_3_SwPsngr_Stat : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Memory_2_SwPsngr_Stat : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Memory_1_SwPsngr_Stat : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ BLISLEDStatPassSide : 2|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ WndwPsngrSide_D_Stat : 4|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM + SG_ Pasngr_Lock_Sw_Stat : 6|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Pasngr_Lock_Sw_Cnt : 15|8@0+ (1,0) [0|255] "Cnt" Vector__XXX + SG_ ChildLckFdbckRp_B_Stat : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 818 Driver_Dr_Stat_FD1: 8 GWM + SG_ BLISLEDStatDriverSide : 47|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ ChildLckPw_N_Cnt : 39|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ WndwDrvSide_D_Stat : 1|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM + SG_ RollCodeDrvDrKeyCyl : 23|16@0+ (1,0) [0|65535] "Unitless" Vector__XXX + SG_ KeyCylSwDrvDr_D_Stat : 3|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Driver_Lock_Sw_Stat : 5|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Driver_Lock_Sw_Cnt : 15|8@0+ (1,0) [0|255] "Cnt" Vector__XXX + SG_ ChildLckPw_D_Rq : 6|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ChildLckFdbckRd_B_Stat : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ RvrseMirrorChime_B_Rq : 45|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 806 Compressor_Req_FD1: 8 GWM + SG_ SnowPlowMde_B_Enbl : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ StopStrtDrvMde_B_RqBtn : 3|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM + SG_ HvacHtrCore_Te_Rq : 49|10@0+ (0.25,-50) [-50|205.75] "degC" PCM_HEV,SOBDMC_HPCM_FD1,ECM_Diesel + SG_ ClimtHeat_D_Rq : 20|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1,ECM_Diesel,PCM,PCM_HEV + SG_ ClimtCool_D_Rq : 23|3@0+ (1,0) [0|7] "SED" SOBDMC_HPCM_FD1,ECM_Diesel,PCM,PCM_HEV + SG_ HvacEvap_Te_Rq : 33|10@0+ (0.125,-50) [-50|77.875] "Degrees C" SOBDMC_HPCM_FD1,ECM_Diesel,PCM,PCM_HEV + SG_ HvacEvap_Te_Actl : 17|10@0+ (0.125,-50) [-50|77.75] "Degrees C" SOBDMC_HPCM_FD1,ECM_Diesel,PCM,PCM_HEV + SG_ HvacAirCond_B_Rq : 7|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ HvacEvap_Te_Offst : 1|10@0+ (0.125,-50) [-50|77.875] "Degrees C" ECM_Diesel,PCM,PCM_HEV + SG_ ClimtPw_B_Rq : 5|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM + +BO_ 765 Mc_Send_Signals_2_FD1: 8 GWM + SG_ Mc_VehTimeFrmtUsrSel_St : 1|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Running_Board_Cmd : 21|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ EngExhMdeQuiet_D2_Rq : 55|3@0+ (1,0) [0|7] "SED" PCM + SG_ EdmSailMde_B_RqDrv : 48|1@0+ (1,0) [0|1] "SED" ECM_Diesel + SG_ DrvInputRequired_B_Rq : 32|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AwdRnge_D_ActlIpc : 29|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ BalrSwtch_D_Stat : 57|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ BalrMde_D_Rq : 59|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ WaitToStartLamp_D_Falt : 50|2@0+ (1,0) [0|3] "SED" ECM_Diesel + SG_ EsaOn_B_Rq : 15|1@0+ (1,0) [0|1] "SED" PSCM + SG_ BttOn_B_Rq : 26|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ Btt_L_Actl : 39|7@0+ (0.1,0) [0|12.5] "meter" IPMA_ADAS + SG_ SelDrvMdeTxtReset_B_Rq : 40|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ SelDrvMdeDsply_B_Avail : 41|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ Mc_VehUntTrpCoUsrSel_St : 23|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Mc_VehUnitTempUsrSel_St : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Mc_VehLangUsrSel_St : 7|6@0+ (1,0) [0|63] "SED" Vector__XXX + +BO_ 559 ElecHorizon_Data2_FD1: 8 GWM + SG_ EhData2_No_Actl : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" IPMA_ADAS,ECM_Diesel + +BO_ 558 ElecHorizon_Data1_FD1: 8 GWM + SG_ EhData1_No_Actl : 7|64@0+ (1,0) [0|1.84467440737096E+019] "unitless" IPMA_ADAS,ECM_Diesel + +BO_ 934 Side_Detect_L_Stat: 8 IPMA_ADAS + SG_ CtaAlrtLeft2_D_Stat : 30|3@0+ (1,0) [0|7] "SED" GWM + SG_ CtaBrkLeftMsgTxt_B_Rq : 42|1@0+ (1,0) [0|1] "SED" GWM + SG_ CtaLeftBrkDecel_B_Rq : 7|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ CtaLeftBrkEnbl_B_Rq : 31|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ Side_Detect_L_Illum : 39|8@0+ (1,0) [0|255] "Percent" GWM + SG_ BttLeft_D_Stat : 45|3@0+ (1,0) [0|7] "SED" GWM + SG_ BttLeft_D_RqDrv : 47|2@0+ (1,0) [0|3] "SED" GWM + SG_ CtaSnsLeft_D_Stat : 25|2@0+ (1,0) [0|3] "SED" GWM + SG_ SodDetctLeft_D_Stat : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ CtaLeft_D_Stat : 18|3@0+ (1,0) [0|7] "SED" GWM + SG_ CtaAlrtLeft_D_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ SodLeft_D_Stat : 15|3@0+ (1,0) [0|7] "SED" GWM + SG_ SodSnsLeft_D_Stat : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ SodAlrtLeft_D_Stat : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ SodWarnLeft_Prd_Rq : 6|7@0+ (1,0) [0|127] "millisecond" GWM + +BO_ 1072 Cluster_Info1_FD1: 8 GWM + SG_ LscmbbStat_B_Actl : 2|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ HaDsplyCpblty_B_Stat : 42|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ AccDeny_B_RqIpc : 7|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ DrvSlipCtlMde_D_Rq : 33|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ EngIdlShutDown_B_RqDrv : 3|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ HsaMde_D_Rq : 54|2@0+ (1,0) [0|3] "SED" ABS_ESC + SG_ NtrlTowMdeEnbl_B_RqDrv : 1|1@0+ (1,0) [0|1] "SED" TCCM,TCM_DSL,PCM_HEV,PCM + SG_ BulbChkActv_B_Stat : 55|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ParkDetect_Stat : 52|1@0+ (1,0) [0|1] "SED" PCM_HEV,PCM + SG_ ReducedGuard_D_Rq : 51|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TrlrBrkMde_D_Rq : 57|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TRLR_SWAY_CONFIG_CMD : 56|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ TRAILER_BRAKE_CONFIG : 37|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Power_Liftgate_Mode_Cmd : 39|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ AccEnbl_B_RqDrv : 35|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ OdometerMasterValue : 15|24@0+ (1,0) [0|16777214] "km" VDM,SOBDMC_HPCM_FD1,TCCM,CMR_DSMC,ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,PSCM,TCM_DSL + SG_ EngOilLife_B_RqReset : 43|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ ePRNDL_MODE : 0|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ DrvSlipCtlMde_B_Rq2 : 34|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ MetricActv_B_Actl : 6|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ KeyTypeChngMykey_D_Rq : 41|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ManRgen_D_Rq : 5|2@0+ (1,0) [0|3] "SED" ECM_Diesel + +BO_ 909 Body_Info_6_FD1: 8 GWM + SG_ IgnPsswrdDsply_B_Rq : 57|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ ElPwPoint_D_Rq : 59|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PoliceIdlMde_D_Stat : 55|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ DrLatchMsgTxt_D_Rq : 43|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ SecurityMsgTxt_D_Rq : 47|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PrmtrAlrmEvnt_D_Stat : 35|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ HeadLghtHiPrmsn_D_Stat : 51|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ SteWhlLckMsgTxt_D_Rq : 25|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ immoMsgTxt_D_Rq : 39|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ PrsnlDevcChrgEnbl_B_Rq : 40|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TracKeyMde_D_Stat : 45|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PEBackupSlot_Stats : 27|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ KeyMykeyTot_No_Cnt : 3|4@0+ (1,0) [0|15] "Counts" Vector__XXX + SG_ Keycode_Status : 15|20@0+ (1,0) [0|1048575] "unitless" Vector__XXX + SG_ KeyAdmnTot_No_Cnt : 7|4@0+ (1,0) [0|15] "Counts" Vector__XXX + +BO_ 963 BCM_Lamp_Stat_FD1: 8 GWM + SG_ Illuminated_Entry_Stat : 63|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Dr_Courtesy_Light_Stat : 49|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Courtesy_Delay_Status : 51|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ImpactEvntFdbck_D_Stat : 53|2@0+ (1,0) [0|3] "SED" CMR_DSMC + SG_ WrlssAcsyChrgInhbt_B_Rq : 40|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PudLampPsngr_D_Rq : 57|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ HeadLampLoOut_B_Stat : 32|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CrnrLghtRight_Pc_Rq : 47|7@0+ (1,0) [0|100] "percent" Vector__XXX + SG_ CrnrLghtLeft_Pc_Rq : 39|7@0+ (1,0) [0|100] "percent" Vector__XXX + SG_ HeadLghtHiFdbck_D_Stat : 55|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PudLampDrv_D_Rq : 59|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ TrnNotInPrkChime_B_Rq : 24|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PrkLightChime_B_Rq : 25|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ KeyInIgnWarn_B_Cmd : 27|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ HomeSafeLtChime_B_Rq : 28|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ StopLghtOn_B_Stat : 8|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ RvrseLghtOn_B_Stat : 9|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PrkLght_D_Stat : 13|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ HeadLghtSwtch_D_Stat : 15|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ HeadLampLoFrOn_B_Stat : 2|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ HeadLampLoFlOn_B_Stat : 3|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ HeadLampLoActv_B_Stat : 4|1@0+ (1,0) [0|1] "SED" IPMA_ADAS,PCM,ECM_Diesel + SG_ Headlamp_On_Wrning_Cmd : 29|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Park_Brake_Chime_Rqst : 26|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ HeadLghtHiOn_B_Stat : 1|1@0+ (1,0) [0|1] "SED" ECM_Diesel,IPMA_ADAS,PCM + SG_ BrkWarnInd_B_Rq : 20|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Brk_Fluid_Lvl_Low : 31|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ ReducedGuard_D_Stat : 19|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Perimeter_Alarm_Status : 17|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ Courtesy_BSave_Stat : 7|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ DrTgateLck_D_Stat : 61|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ WndwGlbl_D_Cmd : 23|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ PudLamp_D_Rq : 11|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ DayRnngLampOn_B_Stat : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PerimeterAlarmChimeRq : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 145 Yaw_Data_FD1: 8 GWM + SG_ VehYawWActl_D_Qf : 53|2@0+ (1,0) [0|3] "SED" VDM,IPMA_ADAS,ABS_ESC + SG_ VehRolWActl_D_Qf : 55|2@0+ (1,0) [0|3] "SED" VDM,IPMA_ADAS,ABS_ESC + SG_ VehRollYawW_No_Cs : 39|8@0+ (1,0) [0|255] "Unitless" IPMA_ADAS,ABS_ESC + SG_ VehRollYaw_No_Cnt : 47|8@0+ (1,0) [0|255] "Unitless" VDM,IPMA_ADAS,ABS_ESC + SG_ VehYaw_W_Actl : 23|16@0+ (0.0002,-6.5) [-6.5|6.6066] "rad/s" VDM,ABS_ESC,PSCM,IPMA_ADAS + SG_ VehRol_W_Actl : 7|16@0+ (0.0002,-6.5) [-6.5|6.6066] "rad/s" VDM,ABS_ESC,IPMA_ADAS + +BO_ 76 RCMStatusMessage2_FD1: 8 GWM + SG_ FirstRowBuckleMid : 28|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ SecondRowBucklePsngr : 23|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ SecondRowBuckleMid : 9|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ SecondRowBuckleDriver : 11|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ FirstRowBuckleDriver : 15|2@0+ (1,0) [0|3] "SED" CMR_DSMC,ABS_ESC,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCM_DSL + SG_ RILReq : 7|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ FirstRowBucklePsngr : 13|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ RstrnImpactEvntStatus : 3|3@0+ (1,0) [0|7] "SED" CMR_DSMC,SOBDMC_HPCM_FD1,ABS_ESC,IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV,TCM_DSL + SG_ PsngrFrntDetct_D_Actl : 5|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ EDRTriggerEvntSync : 29|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ PassRstrnInd_Req : 31|2@0+ (1,0) [0|3] "SED" Vector__XXX + +BO_ 65 Global_PATS_Cntrl_Info_FD1: 8 GWM + SG_ immoControlData_T1 : 15|40@0+ (1,0) [0|1099511627775] "Encrypted" ECM_Diesel,PCM,PCM_HEV + SG_ immoControlCmd_T1 : 7|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM,PCM_HEV + +BO_ 1076 Cluster_Info_3_FD1: 8 GWM + SG_ HILL_DESC_SW : 32|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ AutoRgen_D_Rq : 34|2@0+ (1,0) [0|3] "SED" ECM_Diesel + SG_ W2S_LAMP_OK : 37|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ OdoTripRx_B_Actl : 2|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ Veh_V_CompLimMx : 47|12@0+ (0.1,0) [0|409.5] "km/h" ECM_Diesel,PCM,PCM_HEV + SG_ DrvSlipCtlMde_B_RqMyKey : 38|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ FuelLvlWarn_D_Actl : 51|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ FuelSecndActv_B_Actl : 39|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ FuelLvlPssvSide_No_Raw : 17|10@0+ (1,0) [0|1023] "Unitless" ECM_Diesel,PCM,PCM_HEV + SG_ FUEL_SENSOR_NUM : 35|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ FuelLvlActvSide_No_Raw : 49|10@0+ (1,0) [0|1023] "Unitless" ECM_Diesel,PCM,PCM_HEV + SG_ FuelLvl_Pc_Dsply : 1|10@0+ (0.108696,-5.217408) [-5.217408|105.9786] "Percent" VDM,ECM_Diesel + SG_ DISPLAY_SPEED_SCALING : 23|4@0+ (0.5,100) [100|107.5] "%" IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV + SG_ DISPLAY_SPEED_OFFSET : 7|3@0+ (0.5,0) [0|3.5] "kph" IPMA_ADAS,ECM_Diesel,PCM,PCM_HEV + +BO_ 862 Climate_Cntrl_Data_2_FD1: 8 GWM + SG_ AutoStpHvacDelta_I_Est : 15|8@0+ (1,-192) [-192|62] "ampere" Vector__XXX + SG_ HvacBlwrFront_D_Stat : 55|5@0+ (1,0) [0|31] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ CabnAmb_Te_Actl : 39|8@0+ (0.5,-57) [-57|70] "degreesC" SOBDMC_HPCM_FD1,PCM_HEV + SG_ HvacRemoteStrt_N_Rq : 7|4@0+ (100,450) [450|1950] "RPM" ECM_Diesel,PCM,PCM_HEV + SG_ ClimtThrmlLoad_No_Actl : 47|8@0+ (1,0) [0|254] "unitless" SOBDMC_HPCM_FD1,PCM_HEV + SG_ HvacRec_Pc_Est : 23|7@0+ (1,0) [0|127] "Percent" PCM_HEV,SOBDMC_HPCM_FD1 + SG_ HvacAir_Flw_Est : 16|9@0+ (0.5,0) [0|255.5] "liter/second" SOBDMC_HPCM_FD1 + +BO_ 931 Body_Info_9_FD1: 8 GWM + SG_ PtWakeReas_D_Stat : 38|4@0+ (1,0) [0|15] "SED" PCM_HEV + SG_ VehOnSrc_D_Stat : 19|4@0+ (1,0) [0|15] "SED" ABS_ESC,PCM_HEV,ECM_Diesel,PCM + SG_ StrtrMtrCtlDStat_No_Cs : 31|8@0+ (1,0) [0|255] "unitless" PCM_HEV,ECM_Diesel,PCM + SG_ EngStrtActv_B_Stat : 39|1@0+ (1,0) [0|1] "SED" PCM_HEV,ECM_Diesel,PCM + SG_ EngStrt_B_Rq : 0|1@0+ (1,0) [0|1] "SED" PCM_HEV,ECM_Diesel,PCM + SG_ DrvInCtl_B_Stat : 1|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ AdvStrt_D_Stat : 23|4@0+ (1,0) [0|15] "SED" PCM_HEV,ECM_Diesel,PCM + SG_ CrnkInhbt_No_Cs : 15|8@0+ (1,0) [0|255] "Unitless" ECM_Diesel,PCM,PCM_HEV + SG_ CrnkInhbt_No_Cnt : 6|4@0+ (1,0) [0|15] "Unitless" ECM_Diesel,PCM,PCM_HEV + SG_ CrnkInhbt_B_Stat : 7|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ IgnPreOffActv_B_Stat : 2|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + +BO_ 578 Body_Info_4_FD1: 8 GWM + SG_ PtLatchActv_B_RqBcm : 56|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV,TCM_DSL + SG_ immoSecureIdleMode : 61|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ ReFuelSwtchStat_D_Actl : 63|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ FuelPumpPwr_D_Stat : 50|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ BattULo_U_Actl : 39|8@0+ (0.0625,0) [0|15.875] "volt" CMR_DSMC,SOBDMC_HPCM_FD1,ABS_ESC,IPMA_ADAS,PSCM,ECM_Diesel,PCM,PCM_HEV + SG_ PrkLckCtl_B_Enbl : 22|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PrkLckCtlMsgTxt_D_Rq : 55|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PrkLckCtlAvail_T_Stat : 47|8@0+ (1,0) [0|255] "second" Vector__XXX + SG_ BrkTrnShifLck_B_Stat : 23|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV,TCM_DSL + SG_ PrkLckCtlUnlck_D_Stat : 58|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ PrkLckCtlTow_B_Enbl : 59|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DriverCrankingReq : 51|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ EngOff_T_Actl : 7|16@0+ (1,0) [0|65534] "second^0.5" ABS_ESC,IPMA_ADAS,TCCM,ECM_Diesel,PCM,PCM_HEV,TCM_DSL + SG_ DcacElPw_D_Rq : 53|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM + SG_ BattULo_I_Actl : 21|14@0+ (0.0625,-512) [-512|511.875] "ampere" ECM_Diesel,PCM,PCM_HEV + +BO_ 947 BodyInfo_3_FD1: 8 GWM + SG_ ValetMode_D_Mem : 16|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DimmingLvlEvnt_No_Actl : 18|2@0+ (1,0) [0|3] "unitless" Vector__XXX + SG_ DrStatDrvErrCnt_B_Stat : 19|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ TurnLghtRight_D_Rq : 63|2@0+ (1,0) [0|3] "SED" CMR_DSMC,IPMA_ADAS + SG_ TurnLghtRightOn_B_Stat : 35|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ TurnLghtLeftOn_B_Stat : 54|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ FogLghtRearOn_B_Stat : 1|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ Backlit_LED_Status : 23|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ TurnLghtLeft_D_Rq : 9|2@0+ (1,0) [0|3] "SED" CMR_DSMC,IPMA_ADAS + SG_ FogLghtFrontOn_B_Stat : 56|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ IgnKeyType_D_Actl : 39|4@0+ (1,0) [0|15] "SED" ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV + SG_ Parklamp_Status : 3|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ Litval : 47|8@0+ (1,0) [0|253] "SED" IPMA_ADAS + SG_ Key_In_Ignition_Stat : 11|1@0+ (1,0) [0|1] "SED" ABS_ESC + SG_ Ignition_Status : 7|4@0+ (1,0) [0|15] "SED" VDM,CMR_DSMC,SOBDMC_HPCM_FD1,ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,PSCM,TCCM,TCM_DSL + SG_ Dimming_Lvl : 31|8@0+ (1,0) [0|253] "SED" IPMA_ADAS + SG_ Day_Night_Status : 15|2@0+ (1,0) [0|3] "SED" CMR_DSMC,ECM_Diesel,IPMA_ADAS,PCM + SG_ Remote_Start_Status : 13|2@0+ (1,0) [0|3] "SED" CMR_DSMC,IPMA_ADAS + SG_ DrStatTgate_B_Actl : 0|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ DrStatRr_B_Actl : 49|1@0+ (1,0) [0|1] "SED" ABS_ESC,IPMA_ADAS + SG_ DrStatRl_B_Actl : 48|1@0+ (1,0) [0|1] "SED" ABS_ESC,IPMA_ADAS + SG_ DrStatPsngr_B_Actl : 60|1@0+ (1,0) [0|1] "SED" CMR_DSMC,ABS_ESC,IPMA_ADAS + SG_ DrStatInnrTgate_B_Actl : 58|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ DrStatHood_B_Actl : 59|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DrStatDrv_B_Actl : 61|1@0+ (1,0) [0|1] "SED" CMR_DSMC,ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,TCCM + SG_ PrkBrkActv_B_Actl : 55|1@0+ (1,0) [0|1] "SED" ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,TCCM,TCM_DSL + SG_ LifeCycMde_D_Actl : 53|4@0+ (1,0) [0|15] "SED" VDM,SOBDMC_HPCM_FD1,ABS_ESC,ECM_Diesel,IPMA_ADAS,PCM,PCM_HEV,PSCM,TCM_DSL + SG_ Delay_Accy : 57|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CrashEvnt_D_Stat : 34|2@0+ (1,0) [0|3] "SED" Vector__XXX + SG_ FuelPmpInhbt_B_Stat : 32|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ BodySrvcRqd_B_Rq : 10|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 1084 Battery_Mgmt_3_FD1: 8 GWM + SG_ BattULoChrg_URate_RqMx : 63|6@0+ (0.1,0) [0|6.3] "volts/second" ECM_Diesel,PCM,PCM_HEV + SG_ BattULoChrg_U_RqMx : 55|6@0+ (0.1,10.6) [10.6|16.9] "volt" ECM_Diesel,PCM,PCM_HEV + SG_ BattULoChrg_U_RqMn : 45|6@0+ (0.1,10.6) [10.6|16.9] "volt" ECM_Diesel,PCM,PCM_HEV + SG_ BattULoState_D_Qlty : 47|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ BSFault : 7|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV + SG_ BattULo2_Te_Actl : 30|7@0+ (1,-40) [-40|86] "degC" ECM_Diesel,PCM,PCM_HEV + SG_ BSBattSOC : 22|7@0+ (1,0) [0|127] "%" ECM_Diesel,PCM,PCM_HEV + SG_ BSBattQDeltaRideAh : 6|15@0+ (0.0078125,-100) [-100|155.9921875] "ampere*hour" ECM_Diesel,PCM,PCM_HEV + SG_ BSBattQCapAh : 38|7@0+ (1,0) [0|127] "ampere*hour" ECM_Diesel,PCM,PCM_HEV + +BO_ 1068 Battery_Mgmt_2_FD1: 8 GWM + SG_ EngStrtInhbt_B_RqBatt : 2|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM + SG_ BattULoChrg_D_Rq : 7|2@0+ (1,0) [0|3] "SED" ECM_Diesel,PCM + SG_ PwSysULoFalt_D_Stat : 12|4@0+ (1,0) [0|15] "SED" Vector__XXX + SG_ Shed_T_Eng_Off_B : 8|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Shed_Feature_Group_ID : 20|5@0+ (1,0) [0|31] "SED" ECM_Diesel,PCM,PCM_HEV,IPMA_ADAS + SG_ Shed_Drain_Eng_Off_B : 0|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Shed_Level_Req : 23|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM,PCM_HEV,IPMA_ADAS + SG_ BattULoSrvc_T_Actl : 39|12@0+ (1,0) [0|4095] "days" Vector__XXX + SG_ ULoRgenTestMde_B_Rq : 31|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM + SG_ ChargeMode : 15|3@0+ (1,0) [0|7] "SED" ECM_Diesel,PCM + SG_ IdleSpeedIncrease_El : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ Batt_Lo_SoC_B : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ PeriodicElLoad_B_Stat : 1|1@0+ (1,0) [0|1] "SED" ECM_Diesel + SG_ Batt_Crit_SoC_B : 4|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 146 Accel_Data_FD1: 8 GWM + SG_ VehVert2_A_Actl : 36|13@0+ (0.01,-40) [-40|41.89] "m/s^2" VDM,TCCM,IPMA_ADAS,ABS_ESC,ECM_Diesel + SG_ VehLatLongVertA_No_Cs : 55|8@0+ (1,0) [0|255] "Unitless" TCCM,IPMA_ADAS,ABS_ESC + SG_ VehLatLongVert_No_Cnt : 63|8@0+ (1,0) [0|255] "Unitless" VDM,TCCM,IPMA_ADAS,ABS_ESC + SG_ VehLong2_A_Actl : 20|13@0+ (0.01,-40) [-40|41.89] "m/s^2" VDM,TCCM,ABS_ESC,ECM_Diesel,IPMA_ADAS + SG_ VehLat2_A_Actl : 4|13@0+ (0.01,-40) [-40|41.89] "m/s^2" VDM,TCCM,ABS_ESC,ECM_Diesel,IPMA_ADAS + SG_ VehVertAActl_D_Qf : 38|2@0+ (1,0) [0|3] "SED" VDM,TCCM,IPMA_ADAS,ABS_ESC + SG_ VehLongAActl_D_Qf : 22|2@0+ (1,0) [0|3] "SED" VDM,TCCM,ABS_ESC,ECM_Diesel + SG_ VehLatAActl_D_Qf : 6|2@0+ (1,0) [0|3] "SED" VDM,TCCM,ABS_ESC + +BO_ 1900 TesterPhysicalResCCM: 64 IPMA_ADAS + SG_ TesterPhysicalResCCM : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1806 TesterPhysicalResIPMA: 64 IPMA_ADAS + SG_ TesterPhysicalResIPMA : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 997 Personality_CCM_Data: 8 IPMA_ADAS + SG_ PersIndexCcm_D_Actl : 39|3@0+ (1,0) [0|7] "SED" GWM + SG_ FeatNoCcmActl : 23|16@0+ (1,0) [0|65535] "Number" GWM + SG_ FeatConfigCcmActl : 7|16@0+ (1,0) [0|65535] "Undefined" GWM + +BO_ 983 Steer_Assist_Data: 8 IPMA_ADAS + SG_ CmbbObjRelLong_V_Actl : 39|10@0+ (0.1,-102.1) [-102.1|0] "meters/sec" PSCM + SG_ CmbbObjRelLat_V_Actl : 23|9@0+ (0.1,-25.5) [-25.5|25.4] "meters/sec" PSCM + SG_ CmbbObjDistLong_L_Actl : 7|10@0+ (0.1,0) [0|102.1] "meter" PSCM + SG_ CmbbObjDistLat_L_Actl : 45|9@0+ (0.1,-25.5) [-25.5|25.4] "meter" PSCM + SG_ CmbbObjConfdnc_D_Stat : 9|2@0+ (1,0) [0|3] "SED" PSCM + SG_ CmbbObjColl_T_Actl : 30|7@0+ (0.05,0) [0|6.25] "second" PSCM + SG_ CmbbObjClass_D_Stat : 13|4@0+ (1,0) [0|15] "SED" PSCM + SG_ EsaEnbl_D2_Rq : 52|2@0+ (1,0) [0|3] "SED" PSCM + +BO_ 982 LateralMotionControl2: 8 IPMA_ADAS + SG_ LatCtlCrv_NoRate2_Actl : 55|11@0+ (1E-006,-0.001024) [-0.001024|0.001023] "meter^2" PSCM + SG_ LatCtlPath_No_Cnt : 60|4@0+ (1,0) [0|15] "Unitless" PSCM + SG_ LatCtlPath_No_Cs : 15|8@0+ (1,0) [0|255] "Unitless" PSCM + SG_ LatCtl_D2_Rq : 6|3@0+ (1,0) [0|7] "SED" PSCM + SG_ HandsOffCnfm_B_Rq : 7|1@0+ (1,0) [0|1] "SED" PSCM + SG_ LatCtlRampType_D_Rq : 1|2@0+ (1,0) [0|3] "SED" PSCM + SG_ LatCtlPrecision_D_Rq : 3|2@0+ (1,0) [0|3] "SED" PSCM + SG_ LatCtlPathOffst_L_Actl : 33|10@0+ (0.01,-5.12) [-5.12|5.11] "meter" PSCM + SG_ LatCtlPath_An_Actl : 28|11@0+ (0.0005,-0.5) [-0.5|0.5235] "radians" PSCM + SG_ LatCtlCurv_No_Actl : 23|11@0+ (2E-005,-0.02) [-0.02|0.02094] "1/meter" PSCM + +BO_ 981 GlareFreeBeam: 8 IPMA_ADAS + SG_ AdbRamping_T_Rq : 44|4@0+ (200,0) [0|3000] "millisecond" GWM + SG_ AdbBrdrTop_An_Rq : 7|8@0+ (0.04,-9.54) [-9.54|0.58] "degrees" GWM + SG_ AdbBrdrRight_L_Stat : 37|9@0+ (2,0) [0|1018] "meter" GWM + SG_ AdbBrdrRight_An_Rq : 31|10@0+ (0.04,-20.4) [-20.4|20.44] "degrees" GWM + SG_ AdbBrdrLeft_L_Stat : 40|9@0+ (2,0) [0|1018] "meter" GWM + SG_ AdbBrdrLeft_An_Rq : 9|10@0+ (0.04,-20.4) [-20.4|20.44] "degrees" GWM + SG_ AdbBrdrBottom_An_Rq : 15|6@0+ (0.04,-1.86) [-1.86|0.58] "degrees" GWM + SG_ AdbBeam_D_Rq : 63|3@0+ (1,0) [0|7] "SED" GWM + +BO_ 980 AutoDriveBeam_Data1: 8 IPMA_ADAS + SG_ AdbBrdr1DistRigh_D_Stat : 59|4@0+ (1,0) [0|15] "SED" GWM + SG_ AdbBrdr1DistLeft_D_Stat : 63|4@0+ (1,0) [0|15] "SED" GWM + SG_ AdbMde1_D_Rq : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbIntns1_D_Rq : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbBrdr1Up_An_Rq : 36|9@0+ (0.02,-8) [-8|2.18] "degrees" GWM + SG_ AdbBrdr1Right_An_Rq : 31|11@0+ (0.02,-20) [-20|20.9] "degrees" GWM + SG_ AdbBrdr1Low_An_Rq : 8|9@0+ (0.02,-8) [-8|2.18] "degrees" GWM + SG_ AdbBrdr1Left_An_Rq : 7|11@0+ (0.02,-20) [-20|20.9] "degrees" GWM + SG_ AdbBrdr1CritRigh_T_Stat : 43|4@0+ (100,0) [0|1500] "millisecond" GWM + SG_ AdbBrdr1CritLeft_T_Stat : 55|4@0+ (100,0) [0|1500] "millisecond" GWM + +BO_ 979 LateralMotionControl: 8 IPMA_ADAS + SG_ LatCtlRng_L_Max : 63|6@0+ (2,0) [0|126] "meter" GWM + SG_ HandsOffCnfm_B_Rq : 51|1@0+ (1,0) [0|1] "SED" GWM + SG_ LatCtl_D_Rq : 36|3@0+ (1,0) [0|7] "SED" GWM + SG_ LatCtlRampType_D_Rq : 53|2@0+ (1,0) [0|3] "SED" GWM + SG_ LatCtlPrecision_D_Rq : 33|2@0+ (1,0) [0|3] "SED" GWM + SG_ LatCtlPathOffst_L_Actl : 47|10@0+ (0.01,-5.12) [-5.12|5.11] "meter" GWM + SG_ LatCtlPath_An_Actl : 31|11@0+ (0.0005,-0.5) [-0.5|0.5235] "radians" GWM + SG_ LatCtlCurv_NoRate_Actl : 12|13@0+ (2.5E-007,-0.001024) [-0.001024|0.00102375] "1/meter" GWM + SG_ LatCtlCurv_No_Actl : 7|11@0+ (2E-005,-0.02) [-0.02|0.02094] "1/meter" GWM + +BO_ 976 SuspensionRoad_Data: 8 IPMA_ADAS + SG_ SuspClkSync_No_Actl : 55|8@0+ (1,0) [0|253] "unitless" GWM + SG_ SrpSigValid_B_Stat : 47|1@0+ (1,0) [0|1] "SED" GWM + SG_ SrpHghtRight_L_Actl : 24|9@0+ (0.000625,-0.16) [-0.16|0.158125] "meter" GWM + SG_ SrpHghtLeft_L_Actl : 17|9@0+ (0.000625,-0.16) [-0.16|0.158125] "meter" GWM + SG_ SrpEventRight_D_Stat : 19|2@0+ (1,0) [0|3] "SED" GWM + SG_ SrpEventLeft_D_Stat : 21|2@0+ (1,0) [0|3] "SED" GWM + SG_ SrpDistRight_L_Actl : 14|9@0+ (0.02,0) [0|10.18] "meter" GWM + SG_ SrpDistLeft_L_Actl : 7|9@0+ (0.02,0) [0|10.18] "meter" GWM + +BO_ 973 Traffic_RecognitnData: 8 IPMA_ADAS + SG_ TsrVl2PrmntMsgTxt_D_Rq : 60|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrVl1PrmntMsgTxt_D_Rq : 41|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrVl2RstrcMsgTxt2_D_Rq : 63|3@0+ (1,0) [0|7] "SED" GWM + SG_ TsrVl1RstrcMsgTxt2_D_Rq : 51|3@0+ (1,0) [0|7] "SED" GWM + SG_ TsrOvtkMsgTxt2_D_Rq : 55|4@0+ (1,0) [0|15] "SED" GWM + SG_ WwaWarn_B_Rq : 48|1@0+ (1,0) [0|1] "SED" GWM + SG_ TsrVlUnitMsgTxt_D_Rq : 43|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrVLim2MsgTxt_D_Rq : 39|8@0+ (1,0) [0|255] "SED" GWM + SG_ TsrVLim1MsgTxt_D_Rq : 31|8@0+ (1,0) [0|255] "SED" GWM + SG_ TsrVl2StatMsgTxt_D_Rq : 47|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrVl2RstrcMsgTxt_D_Rq : 17|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrVl1StatMsgTxt_D_Rq : 21|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrVl1RstrcMsgTxt_D_Rq : 23|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrStatMsgTxt_D_Rq : 10|3@0+ (1,0) [0|7] "SED" GWM + SG_ TsrOvtkStatMsgTxt_D_Rq : 1|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrOvtkMsgTxt_D_Rq : 15|3@0+ (1,0) [0|7] "SED" GWM + SG_ TsrOswWarnMsgTxt_D_Rq : 3|2@0+ (1,0) [0|3] "SED" GWM + SG_ TsrMsgTxt_D_Rq : 7|4@0+ (1,0) [0|15] "SED" GWM + +BO_ 970 Lane_Assist_Data1: 8 IPMA_ADAS + SG_ LkaDrvOvrrd_D_Rq : 38|2@0+ (1,0) [0|3] "SED" PSCM + SG_ LkaActvStats_D2_Req : 7|3@0+ (1,0) [0|7] "SED" PSCM + SG_ LaRefAng_No_Req : 19|12@0+ (0.05,-102.4) [-102.4|102.3] "mrad" PSCM + SG_ LaRampType_B_Req : 39|1@0+ (1,0) [0|1] "SED" PSCM + SG_ LaCurvature_No_Calc : 15|12@0+ (5E-006,-0.01024) [-0.01024|0.01023] "1/m" PSCM + SG_ LdwActvStats_D_Req : 4|3@0+ (1,0) [0|7] "SED" PSCM + SG_ LdwActvIntns_D_Req : 1|2@0+ (1,0) [0|3] "SED" PSCM + +BO_ 962 AutoDriveBeam_Data3: 8 IPMA_ADAS + SG_ AdbBrdr3DistRigh_D_Stat : 59|4@0+ (1,0) [0|15] "SED" GWM + SG_ AdbBrdr3DistLeft_D_Stat : 63|4@0+ (1,0) [0|15] "SED" GWM + SG_ AdbMde3_D_Rq : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbIntns3_D_Rq : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbBrdr3Up_An_Rq : 36|9@0+ (0.02,-8) [-8|2.18] "degrees" GWM + SG_ AdbBrdr3Right_An_Rq : 31|11@0+ (0.02,-20) [-20|20.9] "degrees" GWM + SG_ AdbBrdr3Low_An_Rq : 8|9@0+ (0.02,-8) [-8|2.18] "degrees" GWM + SG_ AdbBrdr3Left_An_Rq : 7|11@0+ (0.02,-20) [-20|20.9] "degrees" GWM + SG_ AdbBrdr3CritRigh_T_Stat : 43|4@0+ (100,0) [0|1500] "millisecond" GWM + SG_ AdbBrdr3CritLeft_T_Stat : 55|4@0+ (100,0) [0|1500] "millisecond" GWM + +BO_ 961 AutoDriveBeam_Data2: 8 IPMA_ADAS + SG_ AdbBrdr2DistRigh_D_Stat : 59|4@0+ (1,0) [0|15] "SED" GWM + SG_ AdbBrdr2DistLeft_D_Stat : 63|4@0+ (1,0) [0|15] "SED" GWM + SG_ AdbMde2_D_Rq : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbIntns2_D_Rq : 12|2@0+ (1,0) [0|3] "SED" GWM + SG_ AdbBrdr2Up_An_Rq : 36|9@0+ (0.02,-8) [-8|2.18] "degrees" GWM + SG_ AdbBrdr2Right_An_Rq : 31|11@0+ (0.02,-20) [-20|20.9] "degrees" GWM + SG_ AdbBrdr2Low_An_Rq : 8|9@0+ (0.02,-8) [-8|2.18] "degrees" GWM + SG_ AdbBrdr2Left_An_Rq : 7|11@0+ (0.02,-20) [-20|20.9] "degrees" GWM + SG_ AdbBrdr2CritRigh_T_Stat : 43|4@0+ (100,0) [0|1500] "millisecond" GWM + SG_ AdbBrdr2CritLeft_T_Stat : 55|4@0+ (100,0) [0|1500] "millisecond" GWM + +BO_ 394 ACCDATA_3: 8 IPMA_ADAS + SG_ HaDsply_No_Cs : 63|8@0+ (1,0) [0|255] "Unitless" GWM + SG_ HaDsply_No_Cnt : 4|4@0+ (1,0) [0|15] "Unitless" GWM + SG_ AccStopStat_D_Dsply : 41|2@0+ (1,0) [0|3] "SED" GWM + SG_ AccTrgDist2_D_Dsply : 27|4@0+ (1,0) [0|15] "SED" GWM + SG_ AccStopRes_B_Dsply : 54|1@0+ (1,0) [0|1] "SED" GWM + SG_ TjaWarn_D_Rq : 50|3@0+ (1,0) [0|7] "SED" GWM + SG_ Tja_D_Stat : 44|3@0+ (1,0) [0|7] "SED" GWM + SG_ TjaMsgTxt_D_Dsply : 53|3@0+ (1,0) [0|7] "SED" GWM + SG_ IaccLamp_D_Rq : 46|2@0+ (1,0) [0|3] "SED" GWM + SG_ AccMsgTxt_D2_Rq : 31|4@0+ (1,0) [0|15] "SED" GWM + SG_ FcwDeny_B_Dsply : 10|1@0+ (1,0) [0|1] "SED" GWM + SG_ FcwMemStat_B_Actl : 13|1@0+ (1,0) [0|1] "SED" GWM + SG_ AccTGap_B_Dsply : 35|1@0+ (1,0) [0|1] "SED" GWM + SG_ CadsAlignIncplt_B_Actl : 11|1@0+ (1,0) [0|1] "SED" GWM + SG_ AccFllwMde_B_Dsply : 17|1@0+ (1,0) [0|1] "SED" GWM + SG_ CadsRadrBlck_B_Actl : 22|1@0+ (1,0) [0|1] "SED" GWM + SG_ CmbbPostEvnt_B_Dsply : 15|1@0+ (1,0) [0|1] "SED" GWM + SG_ AccStopMde_B_Dsply : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ FcwMemSens_D_Actl : 20|2@0+ (1,0) [0|3] "SED" GWM + SG_ FcwMsgTxt_D_Rq : 7|3@0+ (1,0) [0|7] "SED" GWM + SG_ AccWarn_D_Dsply : 39|2@0+ (1,0) [0|3] "SED" GWM + SG_ FcwVisblWarn_B_Rq : 47|1@0+ (1,0) [0|1] "SED" GWM + SG_ FcwAudioWarn_B_Rq : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ AccTGap_D_Dsply : 34|3@0+ (1,0) [0|7] "SED" GWM + SG_ AccMemEnbl_B_RqDrv : 36|1@0+ (1,0) [0|1] "SED" GWM + SG_ FdaMem_B_Stat : 37|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 391 ACCDATA_2: 8 IPMA_ADAS + SG_ CmbbBrkDecel_No_Cnt : 47|4@0+ (1,0) [0|15] "Unitless" GWM,ABS_ESC + SG_ HudDsplyIntns_No_Actl : 31|8@0+ (0.5,0) [0|100] "%" GWM + SG_ HudBlk3_B_Rq : 37|1@0+ (1,0) [0|1] "SED" GWM + SG_ HudBlk2_B_Rq : 51|1@0+ (1,0) [0|1] "SED" GWM + SG_ HudBlk1_B_Rq : 50|1@0+ (1,0) [0|1] "SED" GWM + SG_ HudFlashRate_D_Actl : 53|2@0+ (1,0) [0|3] "SED" GWM + SG_ CmbbBrkDecel_No_Cs : 7|8@0+ (1,0) [0|255] "Unitless" GWM,ABS_ESC + SG_ CmbbBrkDecel_A_Rq : 12|13@0+ (0.0039,-20) [-20|11.9449] "m/s^2" ABS_ESC,GWM + SG_ CmbbBrkPrchg_D_Rq : 55|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + SG_ CmbbBrkDecel_B_Rq : 15|1@0+ (1,0) [0|1] "SED" ABS_ESC,GWM + SG_ CmbbBaSens_D_Rq : 14|2@0+ (1,0) [0|3] "SED" ABS_ESC,GWM + +BO_ 390 ACCDATA: 8 IPMA_ADAS + SG_ AccBrkPulse_B_Rq : 36|1@0+ (1,0) [0|1] "SED" ABS_ESC,GWM + SG_ AccAutoResum_D_Rq : 7|2@0+ (1,0) [0|3] "SED" PCM_HEV,PCM,ECM_Diesel + SG_ AccBrkTot_A_Rq : 4|13@0+ (0.0039,-20) [-20|11.9449] "m/s^2" GWM,ABS_ESC + SG_ AccPrpl_A_Pred : 17|10@0+ (0.01,-5) [-5|5.23] "m/s^2" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ AccVeh_V_Trg : 32|9@0+ (0.5,0) [0|255.5] "kph" GWM,ECM_Diesel,PCM,PCM_HEV,TCM_DSL + SG_ AccBrkPrkEl_B_Rq : 38|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ Cmbb_B_Enbl : 50|1@0+ (1,0) [0|1] "SED" GWM + SG_ CmbbOvrrd_B_RqDrv : 51|1@0+ (1,0) [0|1] "SED" GWM + SG_ CmbbDeny_B_Actl : 37|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ CmbbEngTqMn_B_Rq : 52|1@0+ (1,0) [0|1] "SED" ECM_Diesel,PCM,PCM_HEV,GWM + SG_ AccPrpl_A_Rq : 49|10@0+ (0.01,-5) [-5|5.23] "m/s^2" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ AccDeny_B_Rq : 53|1@0+ (1,0) [0|1] "SED" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ AccResumEnbl_B_Rq : 33|1@0+ (1,0) [0|1] "SED" GWM,ECM_Diesel,PCM,PCM_HEV + SG_ AccCancl_B_Rq : 39|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC,ECM_Diesel,PCM,PCM_HEV + SG_ AccBrkPrchg_B_Rq : 54|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ AccBrkDecel_B_Rq : 55|1@0+ (1,0) [0|1] "SED" GWM,ABS_ESC + SG_ AccStopStat_B_Rq : 34|1@0+ (1,0) [0|1] "SED" GWM,ECM_Diesel,PCM,PCM_HEV,ABS_ESC + +BO_ 1441 TCCM_AutoSar_NetwkMgmt: 8 TCCM + SG_ TCCM_GWOnBoardTester : 39|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_GWNMProxy : 47|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_AutoSarNMReserved4 : 63|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_AutoSarNMReserved3 : 55|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_AutoSarNMReserved2 : 31|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_AutoSarNMReserved1 : 23|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_AutoSarNMNodeId : 7|8@0+ (1,0) [0|255] "unitless" Vector__XXX + SG_ TCCM_AutoSarNMControl : 15|8@0+ (1,0) [0|255] "unitless" Vector__XXX + +BO_ 1787 TesterPhysicalResSODCMD: 64 IPMA_ADAS + SG_ TesterPhysicalResSODCMD : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1779 TesterPhysicalReqSODCMD: 64 TSTR + SG_ TesterPhysicalReqSODCMD : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" IPMA_ADAS + +BO_ 1786 TesterPhysicalResSODCMC: 64 IPMA_ADAS + SG_ TesterPhysicalResSODCMC : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1778 TesterPhysicalReqSODCMC: 64 TSTR + SG_ TesterPhysicalReqSODCMC : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" IPMA_ADAS + +BO_ 1153 All_Terrain_Data_FD1: 8 GWM + SG_ TerrMde_D_RqDrv : 3|3@0+ (1,0) [0|7] "SED" Vector__XXX + +BO_ 942 ParkAid_Data2: 8 IPMA_ADAS + SG_ PrkAidRdiusRight_L_Dsply : 15|8@0+ (1,0) [0|255] "unitless" GWM + SG_ PrkAidRdiusLeft_L_Dsply : 7|8@0+ (1,0) [0|255] "unitless" GWM + SG_ PrkAidDrvDir_D_Stat : 23|3@0+ (1,0) [0|7] "SED" GWM + SG_ PrkAidAcsyRear_D_Stat : 18|2@0+ (1,0) [0|3] "SED" GWM + SG_ PrkAidAcsyFront_D_Stat : 20|2@0+ (1,0) [0|3] "SED" GWM + +BO_ 930 Bndry_Alert_R_Data: 8 IPMA_ADAS + SG_ BalrWndwRight_B_Stat : 19|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrSnsRight_D_Falt : 21|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwPsngrRear_D_RqBalrr : 25|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwPsngr_D_RqBalrr : 27|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwDrvRear_D_RqBalrr : 29|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwDrv_D_RqBalrr : 31|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrRight_D_Stat : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrMdeSelRight_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrMdeRight_D_Stat : 23|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrLckRight_B_Stat : 11|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrChimeRight_D_Rq : 2|2@0+ (1,0) [0|3] "SED" GWM + SG_ CamraRearOn_B_RqBalrr : 7|1@0+ (1,0) [0|1] "SED" GWM + SG_ DrLckCnt_No_ActlBalrr : 5|3@0+ (1,0) [0|7] "unitless" GWM + SG_ DrLckActv_B_RqBalrr : 6|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 929 Bndry_Alert_L_Data: 8 IPMA_ADAS + SG_ BalrChimeLeft_D_Rq : 2|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrLeft_D_Stat : 10|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrWndwLeft_B_Stat : 0|1@0+ (1,0) [0|1] "SED" GWM + SG_ WndwPsngrRear_D_RqBalrl : 25|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwPsngr_D_RqBalrl : 27|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwDrvRear_D_RqBalrl : 29|2@0+ (1,0) [0|3] "SED" GWM + SG_ WndwDrv_D_RqBalrl : 31|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrSnsLeft_D_Falt : 21|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrMdeSelLeft_B_Stat : 8|1@0+ (1,0) [0|1] "SED" GWM + SG_ BalrMdeLeft_D_Stat : 23|2@0+ (1,0) [0|3] "SED" GWM + SG_ BalrLckLeft_B_Stat : 11|1@0+ (1,0) [0|1] "SED" GWM + SG_ CamraRearOn_B_RqBalrl : 7|1@0+ (1,0) [0|1] "SED" GWM + SG_ DrLckCnt_No_ActlBalrl : 5|3@0+ (1,0) [0|7] "unitless" GWM + SG_ DrLckActv_B_RqBalrl : 6|1@0+ (1,0) [0|1] "SED" GWM + +BO_ 402 Dsp_Request_Signals11_FD1: 8 GWM + SG_ PrkAidSwtch_D_RqMnu : 11|1@0+ (1,0) [0|1] "SED" IPMA_ADAS + SG_ ApaSwtch_D_RqMnu : 10|2@0+ (1,0) [0|3] "SED" IPMA_ADAS + SG_ ApaMdeStat_D_RqDrv : 2|3@0+ (1,0) [0|7] "SED" IPMA_ADAS + SG_ CamraViewSplit_B_Rq : 3|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CamraZoomMan_D_Rq : 15|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ CamraOvrlStat_D_Rq : 4|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CamraOvrlDyn_D_Rq : 7|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ CamAutoTowbarZoom : 6|1@0+ (1,0) [0|1] "SED" Vector__XXX + SG_ DistanceBarSetting : 5|1@0+ (1,0) [0|1] "SED" Vector__XXX + +BO_ 924 DCACA_Data3_FD1: 8 GWM + SG_ DcacOut_Pw_Mx : 34|11@0+ (5,0) [0|10225] "watts" PCM,PCM_HEV + SG_ DcacOut2_Pw_Actl : 31|13@0+ (1,0) [0|8189] "watts" PCM_HEV + SG_ DcacOut1_Pw_Actl : 12|13@0+ (1,0) [0|8189] "watts" PCM,PCM_HEV + SG_ DcacIn_Pw_Mx : 7|11@0+ (5,0) [0|10225] "watts" PCM,PCM_HEV + +BO_ 923 DCACA_Data2_FD1: 8 GWM + SG_ DcacIn_U2_Actl : 39|12@0+ (0.01,0) [0|40.93] "volt" PCM + SG_ DcacIn_U_Actl : 19|12@0+ (0.1,0) [0|409.3] "volt" PCM,PCM_HEV + SG_ DcacIn_I_Actl : 15|11@0+ (0.1,0) [0|204.5] "Amps" PCM,PCM_HEV + SG_ Dcac_Te_Actl : 7|8@0+ (1,-60) [-60|193] "degC" PCM + +BO_ 1998 TesterPhysicalResSODR: 64 IPMA_ADAS + SG_ TesterPhysicalResSODR : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1996 TesterPhysicalResSODL: 64 IPMA_ADAS + SG_ TesterPhysicalResSODL : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" TSTR + +BO_ 1988 TesterPhysicalReqSODL: 64 TSTR + SG_ TesterPhysicalReqSODL : 7|64@0+ (1,0) [0|1.84467E+019] "unitless" IPMA_ADAS + +BO_ 922 DCACA_Data1_FD1: 8 GWM + SG_ DcacBp2BrkrOpn_B_Falt : 13|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacBp1BrkrOpn_B_Falt : 14|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacIpRcBrkrOpn_B_Falt : 10|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacRdy_D2_Stat : 23|2@0+ (1,0) [0|3] "SED" PCM,PCM_HEV + SG_ DcacOvrld_B_Falt : 8|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacOverTe_B_Falt : 9|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacGfci_B_Falt : 11|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacErr_B_Stat : 12|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacAcUDetct_B_Falt : 15|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacRdy_D_Stat : 2|3@0+ (1,0) [0|7] "SED" Vector__XXX + SG_ DcacPlugPrsnt_B_Stat : 3|1@0+ (1,0) [0|1] "SED" PCM,PCM_HEV + SG_ DcacClntFlw_D_Rq : 5|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + SG_ CoolFanDcac_D_Rq : 7|2@0+ (1,0) [0|3] "SED" SOBDMC_HPCM_FD1 + +BO_ 1082 INSTRUMENT_PANEL: 8 GWM + SG_ METRIC_UNITS : 54|1@0+ (1,0) [0|1] "SED" IPMA,PCM,PCM_HEV + +BO_TX_BU_ 2612224016 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 878 : PCM,PCM_HEV; +BO_TX_BU_ 1085 : ECM_Diesel,PCM; +BO_TX_BU_ 2611175440 : ECM_Diesel,PCM_HEV,PCM; +BO_TX_BU_ 2610126864 : ECM_Diesel,PCM_HEV,PCM; +BO_TX_BU_ 786 : PCM_HEV,SOBDMC_HPCM_FD1; +BO_TX_BU_ 1090 : SOBDMC_HPCM_FD1,PCM_HEV; +BO_TX_BU_ 374 : PCM_HEV,TCM_DSL,PCM; +BO_TX_BU_ 872 : SOBDMC_HPCM_FD1,PCM_HEV; +BO_TX_BU_ 560 : PCM,PCM_HEV,TCM_DSL; +BO_TX_BU_ 369 : PCM_HEV,TCM_DSL,PCM; +BO_TX_BU_ 92 : PCM,TCM_DSL,PCM_HEV; +BO_TX_BU_ 2030 : SOBDMC_HPCM_FD1,ECM_Diesel; +BO_TX_BU_ 1087 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 2024 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1697 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1696 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1429 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1100 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1086 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1071 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1069 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1060 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1057 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 1055 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 517 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 516 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 514 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 512 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 380 : ECM_Diesel,PCM; +BO_TX_BU_ 377 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 376 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 359 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 358 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 357 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 342 : ECM_Diesel,PCM,PCM_HEV; +BO_TX_BU_ 71 : ECM_Diesel,PCM,PCM_HEV; + +CM_ "New CAN FD network"; +CM_ BU_ CMR_DSMC "Driver Status Monitor Camera"; +CM_ BU_ IPMA_ADAS "Assist Driving Alert System"; +CM_ BU_ PSCM "Passenger Front Climate Control Seat Module"; +CM_ BU_ ABS_ESC "Anti-lock Brake / Traction Control Module"; +CM_ BU_ TCCM "Transfer Case Control Module, 4x4 Control Module"; +CM_ BU_ TCM_DSL "Transmission Control Module"; +CM_ BU_ PCM "Powertrain Control Module"; +CM_ BU_ ECM_Diesel "Diesel"; +CM_ BU_ GWM "Gateway Module CGEA1.3(Star Architecture)"; +CM_ BU_ TSTR "Diagnostic Tester"; + +CM_ SG_ 524 PrplWhlTotTqRqMxAwd_No_Cs "Signal not transmitted on gas variants."; +CM_ SG_ 524 PrplWhlTotTqRqMxAwd_No_Cnt "Signal not transmitted on gas variants."; +CM_ SG_ 1150 LocationServices_1 "Tx by HS3 APIM"; +CM_ SG_ 542 LocationServices_3 "Tx by HS3 APIM"; +CM_ SG_ 810 NtfyDrvTrgtDist_L_Rq "Object.SetTripRangeAlert_Rq This signal is meant to provide the customer settings for the target distance remote notification"; +CM_ SG_ 810 NtfyDrvSocLvl1_Pc_Rq "Object.SetCustomerLevelAlert_Rq This signal is meant to provide the customer settings for the SOC remote notification."; +CM_ SG_ 810 PtRmtRprt_D_Stat "Object.RemoteDataReport_St"; +CM_ SG_ 550 PtWakeupActv1_B_Rq "ECG Application signal"; +CM_ SG_ 982 LatCtlPath_No_Cnt "Signal not transmitted on gas variants."; +CM_ SG_ 982 LatCtlPath_No_Cs "Signal not transmitted on gas variants."; +CM_ SG_ 1104 DrvEngageLevel_No_Cs "Signal not transmitted on gas variants."; +CM_ SG_ 1104 DrvEngageLevel_No_Cnt "Signal not transmitted on gas variants."; +CM_ SG_ 1085 ULoRgenTestMde_B_Stat "Signal not transmitted on HEV variants."; +CM_ SG_ 1085 PwSrcULoComm_B_Falt "Signal not transmitted on HEV variants."; +CM_ SG_ 1445 SOBDMC_AutoSarNMReserved4 "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 1445 SOBDMC_AutoSarNMReserved3 "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 1445 SOBDMC_AutoSarNMReserved2 "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 1445 SOBDMC_AutoSarNMReserved1 "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 1445 SOBDMC_AutoSarNMNodeId "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 1445 SOBDMC_AutoSarNMControl "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 1088 HvacPrecondMode2_D_Rq "Signal not transmitted on vehicles that do not have the Fuel operated heater feature."; +CM_ SG_ 1088 HvacPrecondBlwr2_D_Rq "Signal not transmitted on vehicles that do not have the Fuel operated heater feature."; +CM_ SG_ 786 ChrgStat_D_Dsply "Signal not transmitted by PCM_HEV"; +CM_ SG_ 66 immoControlData_T2 "Not transmitted on all vehicle variants"; +CM_ SG_ 66 immoControlCmd_T2 "Not transmitted on all vehicle variants"; +CM_ SG_ 549 BeltminderAudioMute "Object.MyKey.BeltMinderAudioMute.St"; +CM_ SG_ 549 Power_Up_Chime_Modules "Object.AlertMethod.IPC _Infotainment"; +CM_ SG_ 549 Chime_Source "Object.AlertMethod.IPC_infotainment"; +CM_ SG_ 611 AwdStat_D_RqDsply "Signal not transmitted on programs that do not have AWD."; +CM_ SG_ 611 AwdSrvcRqd_B_Rq "Signal not transmitted on programs that do not have AWD."; +CM_ SG_ 611 AwdLck_Tq_Rq "Signal not transmitted on programs that do not have AWD."; +CM_ SG_ 130 VehVTrlrAid_B_Rq "VR session start- req. limit blower speed no more than X volts. CC restriction on time msg. will be honored.Double Event msg1st event to request limit, 2nd event to release limit, No msg. CC Grammar v7.xls"; +CM_ SG_ 130 SteMdule_U_Meas "DCR 1745 to update Tx from GWM to EP100ms. SteMdule_I_Est & SteMdule_U_Meas are used by BMS system & filtered. The filter uses standard periodic rate & changing to EP would adversely affect the filter.(jweinfur)"; +CM_ SG_ 130 SteMdule_I_Est "DCR 1745 to update Tx from GWM to EP100ms. SteMdule_I_Est & SteMdule_U_Meas are used by BMS system & filtered. The filter uses standard periodic rate & changing to EP would adversely affect the filter.(jweinfur)"; +CM_ SG_ 126 StePinRelInit_An_Sns "SASM will transmit these signals on vehicles with SASM and without PSCM. SCCM will not Tx this signal when SASM is present."; +CM_ SG_ 126 StePinAn_No_Cs "Signal not transmitted on gas variants."; +CM_ BO_ 133 "Seen on Ford Edge MK2"; +CM_ SG_ 133 StePinRelInit_An_Sns "SASM will transmit these signals on vehicles with SASM and without PSCM. SCCM will not Tx this signal when SASM is present."; +CM_ SG_ 133 StePinAn_No_Cs "Signal not transmitted on gas variants."; +CM_ SG_ 1200 BrkTot_Tq_RqDrv "DCR 1836 to update Tx from GWM to EP100ms rejected due MPS6 TCM requires BrkTot_Tq_RqDrv at 20ms (bshu1)."; +CM_ SG_ 1046 TCMode "Signal data set to 0x0 for ABS only vehicle option content"; +CM_ SG_ 1046 DrvAntiLckLamp_D_Rq "update value table v8.34, not align w/GSDB, need etracker. ABS & IPC implemented as updated."; +CM_ SG_ 1046 BpedMove_D_Actl "CCMGenSigTimeoutTime=1000"; +CM_ SG_ 1044 StePinOffst_An_Est "SASM will transmit these signals on vehicles with SASM and without PSCM. SCCM will not Tx this signal when SASM is present."; +CM_ SG_ 1044 StePinOffst_No_Cs "Signal not transmitted on gas variants."; +CM_ SG_ 534 BrkObdData_No_Actl "Signal not transmitted on gas, diesel and HEV. Only supported on PHEV."; +CM_ SG_ 534 BrkObdIndex_No_Actl "Signal not transmitted on gas, diesel and HEV. Only supported on PHEV."; +CM_ SG_ 534 WhlRotatRr_No_Cnt "DCR 1833 to update Tx from GWM to EP100ms. Wheel Count signals are used by complex algorithm to determine Tire Pressure by Location & can't change from 20msec. (jweinfur)"; +CM_ SG_ 534 WhlRotatRl_No_Cnt "DCR 1833 to update Tx from GWM to EP100ms. Wheel Count signals are used by complex algorithm to determine Tire Pressure by Location & can't change from 20msec. (jweinfur)"; +CM_ SG_ 534 WhlRotatFr_No_Cnt "DCR 1833 to update Tx from GWM to EP100ms. Wheel Count signals are used by complex algorithm to determine Tire Pressure by Location & can't change from 20msec. (jweinfur)"; +CM_ SG_ 534 WhlRotatFl_No_Cnt "DCR 1833 to update Tx from GWM to EP100ms. Wheel Count signals are used by complex algorithm to determine Tire Pressure by Location & can't change from 20msec. (jweinfur)"; +CM_ SG_ 531 VehLongOvrGnd_A_Est "CCMGenSigTimeoutTime=1000"; +CM_ SG_ 1034 VehicleGGCCData "RCMGenSigTimeout=6000"; +CM_ SG_ 1090 Mtr2State_D_ActlMntr "Signal Not transmitted on PCM_HEV variant"; +CM_ SG_ 1090 Inv1Ain_I_ActlMntr "Signal Not transmitted on PCM_HEV variant"; +CM_ SG_ 1090 VehElRnge_L_Dsply "Signal Not transmitted on HPCM variant"; +CM_ SG_ 374 TrnRng_D_Rq "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 374 TrnPrkSys_D_Actl "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 374 GearLvr_D_ActlDrv "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 374 GearPos_No_Cs "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 374 GearPos_D_Trg "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 374 GearPos_No_Cnt "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 374 GearPos_D_Actl "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 603 WhlDirAvgDrv_D_Actl "48V mHEV: ECM_HEVDSL is Tx, MHT HEV: PCM_HEV is Tx, Powersplit HEV: SOBDMC_HPCM is Tx"; +CM_ SG_ 603 PrplTqMnRgen_B_Actl "48V mHEV: ECM_HEVDSL is Tx, MHT HEV: PCM_HEV is Tx, Powersplit HEV: SOBDMC_HPCM is Tx"; +CM_ SG_ 603 BattTracCnnct_D_Rq "48V mHEV: ECM_HEVDSL is Tx, MHT HEV: PCM_HEV is Tx, Powersplit HEV: SOBDMC_HPCM is Tx"; +CM_ SG_ 872 HybMdeStat_D_Dsply "Signal not transmitted by HPCM"; +CM_ SG_ 560 SelDrvMdeSwtch_D_Stat3 "ECM_HEV, PCM & PCM_HEV do not support or Transmit signal."; +CM_ SG_ 560 TrnSrvcRqd_B_Rq "Signal not transmitted on Diesel & HEV variants. MHT(U611/625) HPCM Rx 0x230 from PCM_HEV. Powersplit FWD HEVs(Cx482/3 430) HPCM Tx 0x230."; +CM_ SG_ 560 TrnShifActv_B_Actl "Signal not transmitted on HEV variants. MHT(U611/625) HPCM Rx 0x230 from PCM_HEV. Powersplit FWD HEVs(Cx482/3 430) HPCM Tx 0x230."; +CM_ SG_ 560 GboxOil_Te_Actl "Signal not transmitted on HEV variants. MHT(U611/625) HPCM Rx 0x230 from PCM_HEV. Powersplit FWD HEVs(Cx482/3 430) HPCM Tx 0x230."; +CM_ SG_ 369 SeatWorkSrfc_B_Falt "Signal Not transmitted by TCM_DSL"; +CM_ SG_ 369 TrnIpcDsplyRng2_D_Actl "Signal not transmitted on HEV variants."; +CM_ SG_ 369 TrnIpcDsplyRng_D_Stat "Signal not transmitted on HEV variants."; +CM_ SG_ 92 TrnLvrV_D_Rq "Signal not transmitted on vehicles with PCM_HEV"; +CM_ SG_ 92 TrnSbwSysHlth_D_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnGearNtmAllow_B_Stat "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnDtpCmd_D_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnGearCmd_No_Cs "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnValidGear_D_Cnfm "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnNtrlTowCmd_D_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnGearCmd_Pc_ActlPt "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnGear_D_RqPt "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnCmdState_B_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnCmdCnt_B_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 PrkBrkActv_D_RqTrnGear "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnGearMsgTxt_D_Rq "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 92 TrnGearCmd_No_Cnt "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 1087 BattRgenLoChrg_D_RqEng "Signal not transmitted on diesel variant"; +CM_ SG_ 1087 BattRgenLoDChrg_D_RqEng "Signal not transmitted on diesel variant"; +CM_ SG_ 1087 FapLcInhbt_B_Rq "Signal not transmitted on diesel variant"; +CM_ SG_ 1100 EngExhMdeQuiet_D2_Stat "Signal not transmitted on HEV & Diesel programs"; +CM_ SG_ 1100 HvacCmprLim_D_Stat "Signal not transmitted on Diesel variants"; +CM_ SG_ 1100 WakeAlarm1_T_Rq "Signal not transmitted on Gas variants"; +CM_ SG_ 1100 WakeAlarm1_B_Typ "Signal not transmitted on Gas variants"; +CM_ SG_ 1100 Veh_V_DsplyTrailCtlSet "Signal not transmitted on HEV & Diesel programs"; +CM_ SG_ 1100 TrailCtlPt_B_Falt "Signal not transmitted on HEV & Diesel programs"; +CM_ SG_ 1100 AutoTowAllw_D_StatMnu "Signal not transmitted on Gas & Diesel variants"; +CM_ SG_ 1100 AutoTowActv_B_Stat "Signal not transmitted on Gas & Diesel variants"; +CM_ SG_ 1086 EngMnfld_P_Actl "Signal not transmitted on HEV & Diesel programs"; +CM_ SG_ 1086 ElLoadCtl_D_Rq "Signal not transmitted on HEV variants."; +CM_ SG_ 1071 CluPdl_PcRate_Actl "Signal not transmitted on HEV and Gas variants."; +CM_ SG_ 1071 CluPdlPosPcMeas_D_Qf "Signal not transmitted on HEV and Gas variants."; +CM_ SG_ 1071 CluPdlPos_Pc_Meas "Signal not transmitted on HEV and Gas variants."; +CM_ SG_ 1071 EngAoutIdl_N_Ntrl "Signal not transmitted on HEV variants and diesel."; +CM_ SG_ 1069 SlMde_D_Stat "IPC and HUD_ADV Receve from HS3 FGW 0x42D, not HS3 0x38A, MSG DCR 506. Signal not transmitted on Gas & HEV variants"; +CM_ SG_ 1069 SlMde_D_RqDsply "IPC and HUD_ADV Receve from HS3 FGW 0x42D, not HS3 0x38A, MSG DCR 506. Signal not transmitted on Gas & HEV variants"; +CM_ SG_ 1069 IsaOffst_D_Stat "Signal not transmitted on Gas & HEV variants"; +CM_ SG_ 1069 ObdWarmUp_B_Complt "Signal not transmitted on diesel variants."; +CM_ SG_ 1069 EngMsgTxt_D_Rq "Signal not transmitted on diesel variants."; +CM_ SG_ 1069 EngClnt_Te_ActlDiag "Signal not transmitted on gas variants."; +CM_ SG_ 1069 EngLoad_Pc_CalcDiag "Signal not transmitted on gas variants."; +CM_ SG_ 1069 ApedPos_Pc_ActlDiag "Signal not transmitted on gas variants."; +CM_ SG_ 1060 RearDiffOilTeWarn_B_Rq "Signal not transmitted on HEV & Diesel programs"; +CM_ SG_ 1060 RearDiffOil_Te_Actl "Signal not transmitted on HEV & Diesel programs"; +CM_ SG_ 1057 FohEng_D_Rq "Signal not transmitted on vehicles that do not have the fuel operated heater feature. Signal not transmitted on HEV programs"; +CM_ SG_ 1057 EngIdlShutDown_D_Stat "Signal not transmitted on diesel variants."; +CM_ SG_ 1057 FUEL_ALCOHOL_PERCNT "signal not transmitted on diesel and HEV variants."; +CM_ SG_ 1057 TrnTotTq_Rt_Est "Signal not transmitted on gas and HEV variants."; +CM_ SG_ 1057 TrnTotLss_Tq_Est "Signal not transmitted on gas and HEV variants."; +CM_ SG_ 1057 VehVLimStat_D_Actl "Signal not transmitted on gas and HEV variants."; +CM_ SG_ 1057 VehVLimActv_B_Actl "Signal not transmitted on gas and HEV variants."; +CM_ SG_ 562 GearNtrl_No_Cs "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 562 GearNtrl_No_Cnt "Powersplit HEVs with HF45, HPCM will Tx this message. For all other programs it will be Tx by PCM or TCM. "; +CM_ SG_ 516 EngAoutNActl_D_QF "Signal not transmitted on Gas & HEV variants"; +CM_ SG_ 516 EngAout3_N_Actl "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 516 ApedPos_Pc_ActlArb "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 516 ApedPosPcActl_No_Cnt "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 516 ApedPosPcActl_No_Cs "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 514 VehVTrlrAid_B_Avail "Signal not transmitted on HEV variants."; +CM_ SG_ 514 GearRvrse_D_Actl "Do not implement GearRvrse_D_Actl until eTracker 8804151 is approved, 11/24/09"; +CM_ SG_ 512 PrplWhlTotTqRq_No_Cs "Signal not transmitted on gas & Diesel variants."; +CM_ SG_ 512 PrplWhlTotTqRq_No_Cnt "Signal not transmitted on gas & Diesel variants."; +CM_ SG_ 512 PtDrvMde_D_Stat "Signal not transmitted on Gas & HEV variants."; +CM_ SG_ 380 EngExhBrkOnLamp_B_Rq "Signal not transmitted on Gas variants"; +CM_ SG_ 380 EngExhBrkAutoLamp_B_Rq "Signal not transmitted on Gas variants"; +CM_ SG_ 380 EngAout_N_MxAllw "Signal not transmitted on Gas variants"; +CM_ SG_ 380 EngExhBrkMde_D_Actl "Signal not transmitted on Gas variants"; +CM_ SG_ 377 HvacAirFullOut_B_Rq "Signal not transmitted on diesel variant"; +CM_ SG_ 377 FuelFlw_Vl_Dsply "Signal not transmitted on diesel variants."; +CM_ SG_ 377 FuelFillInlet_B_Dsply "Signal not transmitted on diesel variants."; +CM_ SG_ 377 OdoCount "Signal not transmitted on diesel variants."; +CM_ SG_ 377 EngOilLife_Pc_Actl "Signal not transmitted on diesel variants."; +CM_ SG_ 377 FuelFilterLamp_B_Dsply "Signal not transmitted on Gas & HEV variants"; +CM_ SG_ 377 AirCondRec_B_Rq "Signal not transmitted on diesel variants."; +CM_ SG_ 377 AirCondClutch_B_Stats "Signal not transmitted on diesel variants."; +CM_ SG_ 376 GasPrtc_D_RqDsply "Signal not transmitted on HEV & Diesel variants."; +CM_ SG_ 376 EngAout_Aa_Actl "Signal not transmitted on HEV variants."; +CM_ SG_ 376 AslIconDsply_D_Rq "Signal not transmitted on HEV variants."; +CM_ SG_ 376 AslChime_B_Rq "Signal not transmitted on HEV variants."; +CM_ SG_ 376 HvacHtrCore2_Te_Actl "Signal not transmitted on Gas & Diesel variants"; +CM_ SG_ 376 EcssLamp_D_RqDsply "Signal not transmitted on Gas & HEV variants"; +CM_ SG_ 376 AirAmb_Te_Actl "Signal not transmitted on Gas variants"; +CM_ SG_ 359 PrplWhlRgenMn_Tq_Actl "Signal not transmitted on Gas & Diesel variants"; +CM_ SG_ 359 ElPw_D_StatStrtStop "Signal not transmitted on HEV variants."; +CM_ SG_ 359 TrnAin_Tq_Actl "Signal not transmitted on HEV variances."; +CM_ SG_ 359 PlgActvArb_B_Actl "Only supported on PHEV programs. PlgActvArb_B_Actl HPCM will Tx on Powersplit PHEVs, On MHT PHEVs the PCM_HEV will Tx and HPCM will Rx."; +CM_ SG_ 359 TrnAinTq_D_Qf "Signal not transmitted on HEV variances."; +CM_ SG_ 358 StopStrtStdby_D_Indic "Signal not transmitted on HEV variants."; +CM_ SG_ 358 StopStrtIODTxt_D_Rq "Signal not transmitted on HEV variants."; +CM_ SG_ 358 StopStrtDrvMde_D_Indic "Signal not transmitted on HEV variants."; +CM_ SG_ 358 StopStrtMsgTxt_D_Rq "Signal not transmitted on HEV variants."; +CM_ SG_ 358 HiElPwInhbt_B_Stat "Signal not transmitted on HEV programs"; +CM_ SG_ 358 AutoStopPtDelta_I_Est "Signal not transmitted on HEV variants. "; +CM_ SG_ 357 BpedDrvAppl_D_Actl "CCMGenSigTimeoutTime=1000"; +CM_ SG_ 357 CcStat_D_Actl "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 357 EngAout_N_MnAllw "Signal not transmitted on Gas & Diesel variants."; +CM_ SG_ 357 AccStopMde_D_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 342 EngOvrhtMitgActv_D_Ind "Signal not transmitted on diesel."; +CM_ SG_ 342 EngGoutLss_Tq_Est "Signal not transmitted on gas and diesel variants."; +CM_ SG_ 342 EngOil_Te_Actl "Signal not transmitted on Gas & HEV variants. "; +CM_ SG_ 954 GenericSwtch2_No_Actl "U625 Police Wig Wag feature"; +CM_ SG_ 935 SodRight_D_Stat "IPCGenSigTimeoutTime=1600"; +CM_ SG_ 935 Side_Detect_R_Illum "DDMGenSigTimeoutTime=2000"; +CM_ SG_ 935 SodSnsRight_D_Stat "IPCGenSigTimeoutTime=1600"; +CM_ SG_ 935 SodAlrtRight_D_Stat "DDMGenSigTimeoutTime=2000"; +CM_ SG_ 1112 BattTracClntPmp_D_Stat "48V mHEV: ECM_HEVDSL is Tx, MHT HEV: PCM_HEV is Tx, Powersplit HEV: SOBDMC_HPCM is Tx"; +CM_ SG_ 1050 Outside_Air_Temp_Stat "Filtered value, i.e. same as disply for customer"; +CM_ SG_ 1009 CenterStackRing_D_Actl "The Center Stack sends the CPLR a signal to turn On or Off the light Ring, This is a customer selectable preference switch"; +CM_ SG_ 1009 APIM_NumberofTracks_St "Object NumberofTracks"; +CM_ SG_ 1009 APIM_ActiveTrackNum_St "Object.ActiveTrackNum"; +CM_ SG_ 360 GsmSrvcRqd_B_Rq "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 360 TrnGearPwmFalt_B_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 360 GearButtnStuck_B_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGsmNtmState_D_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 DrQltyDrv_D_StatGsm "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnBtsiOvrrd_B_Stat "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnValidGearRq_D_Stat "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearRqCnt_B_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_U_Actl "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlR2 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlR1 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlR0 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlP2 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlP1 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlP0 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlN2 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlN1 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlN0 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlM2 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlM1 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlM0 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlD2 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlD1 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGearButtn_B_ActlD0 "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGear_No_Cs "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGear_No_Cnt "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 TrnGear_D_RqDrv "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 90 BrkSwtchPos_B_ActlGsm "Signal not transmitted on vehicles that do not have shift by wire."; +CM_ SG_ 138 SteWhlRelCalib_An_Sns "Signal is not transmitted on vehicles where PSCM is transmitting the message that contains this signal. Signal data set to 0x0 for ABS only vehicle option content"; +CM_ SG_ 1093 StopLamp_B_RqTrlrBrk "Signal not transmitted on all variants."; +CM_ SG_ 792 ElTrip_L_Dsply "Key cycle trip distance driven with the engine off (Trip EV Miles)"; +CM_ SG_ 792 ElLongTerm_L_Dsply "Long term distance distance driven with the engine off since the last long term reset (Long Term EV Miles)."; +CM_ SG_ 765 Mc_VehTimeFrmtUsrSel_St "Object.BodyInterface.Settings.VehicleTimeFormatUserSelection"; +CM_ SG_ 765 Mc_VehUntTrpCoUsrSel_St "Object.VehicleSettings.Disp_Miles_Kilometers.Rq"; +CM_ SG_ 765 Mc_VehUnitTempUsrSel_St "Object.VehicleSettings.Disp_Temperature.Rq"; +CM_ SG_ 765 Mc_VehLangUsrSel_St "Object.BodyInterface.Settings.VehicleLanguageUserSelection Object Vehicle Settings.Disp_LangSel"; +CM_ SG_ 934 Side_Detect_L_Illum "DDMGenSigTimeoutTime=2000"; +CM_ SG_ 934 SodLeft_D_Stat "IPCGenSigTimeoutTime=1600"; +CM_ SG_ 934 SodSnsLeft_D_Stat "IPCGenSigTimeoutTime=1600"; +CM_ SG_ 934 SodAlrtLeft_D_Stat "DDMGenSigTimeoutTime=2000"; +CM_ SG_ 1072 MetricActv_B_Actl "0 =Inactive(English), 1=Active(Metric)"; +CM_ SG_ 145 VehYaw_W_Actl "CCMGenSigTimeoutTime=1000"; +CM_ SG_ 931 CrnkInhbt_No_Cs "Signal not transmitted on gas and HEV variants."; +CM_ SG_ 931 CrnkInhbt_No_Cnt "Signal not transmitted on gas and HEV variants."; +CM_ SG_ 947 Dimming_Lvl "Refer to Vehicle Interior Illum Dimming Ctrl Sys Eng Spec, Table 2"; +CM_ SG_ 947 PrkBrkActv_B_Actl "Signal not transmitted on vehicles with electric park brake. "; +CM_ SG_ 394 HaDsply_No_Cs "Signal not transmitted on gas variants."; +CM_ SG_ 394 HaDsply_No_Cnt "Signal not transmitted on gas variants."; +CM_ SG_ 391 CmbbBrkDecel_A_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 391 CmbbBrkPrchg_D_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 391 CmbbBrkDecel_B_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 391 CmbbBaSens_D_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 390 AccBrkTot_A_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 390 AccBrkPrkEl_B_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 390 AccPrpl_A_Rq "PCMGenSigTimeoutTime=1000"; +CM_ SG_ 390 AccBrkPrchg_B_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 390 AccBrkDecel_B_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 390 AccStopStat_B_Rq "ABSGenSigTimeoutTime=1000"; +CM_ SG_ 942 PrkAidRdiusRight_L_Dsply "MSGDCR 679, set all signals to OnChange"; +CM_ SG_ 942 PrkAidRdiusLeft_L_Dsply "MSGDCR 679, set all signals to OnChange"; +CM_ SG_ 942 PrkAidDrvDir_D_Stat "MSGDCR 679, set all signals to OnChange"; + +BA_DEF_ BO_ "OvtpPushApplication" ENUM "FALSE","TRUE"; +BA_DEF_ BU_ "OvtpOperationMode" ENUM "SERVER","CLIENT"; +BA_DEF_ BU_ "OvtpEcuAddress" INT 0 1022; +BA_DEF_ SG_ "ECGUsedRxSignal" ENUM "No","Yes"; +BA_DEF_ SG_ "U_S650_MY2022_Rx" ENUM "No","Yes"; +BA_DEF_ SG_ "ECGUsedTxSignal" ENUM "No","Yes"; +BA_DEF_ SG_ "U_S650_MY2022_Tx" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigTimeoutTime_CHCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_SOBDMC_HPCM_F" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_CMR_DSMC" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ECM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ECM_HEVDSL" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_AWD_DLCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ECM_HEV" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_GENERIC" INT 0 100000; +BA_DEF_ BO_ "VFrameFormat" ENUM "StandardCAN","ExtendedCAN","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","reserved","StandardCAN_FD","ExtendedCAN_FD"; +BA_DEF_ SG_ "GenSigTimeoutTime_PSCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_HCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ABS_ESC" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ECM_Diesel" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TCCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime__delete" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TCM_DSL" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TSTR" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_IPMA_ADAS" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_GWM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_PCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_PCM_HEV" INT 0 100000; +BA_DEF_ "BusType" STRING; +BA_DEF_ BO_ "FrameRouting" STRING; +BA_DEF_ BO_ "FrameGatewayNetwork" STRING; +BA_DEF_ BO_ "FrameGateway_LC1" HEX 0 1407; +BA_DEF_ BO_ "FrameGatewayLC1_HS3" HEX 0 1407; +BA_DEF_ BO_ "FrameGatewayMS1" HEX 0 1407; +BA_DEF_ BO_ "FrameGatewayHS3" HEX 0 1407; +BA_DEF_ BO_ "FrameGatewayHS2" HEX 0 1407; +BA_DEF_ BO_ "FrameGatewayHS1" HEX 0 1407; +BA_DEF_ BO_ "NetworkInitialization" ENUM "No","Yes"; +BA_DEF_ BO_ "FrameGatewayId" HEX 0 1407; +BA_DEF_ BO_ "EventRateOfChange" INT 10 10000; +BA_DEF_ BO_ "ConfiguredTransmitter" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 10000; +BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100; +BA_DEF_ BO_ "GenMsgDelayTime" INT 0 1000; +BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 100000; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000; +BA_DEF_ BO_ "GenMsgSendType" ENUM "FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType"; +BA_DEF_ SG_ "U_T6_MCA_MY2020_Tx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_P702_MY2021_Tx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_CX727_MY2021_Tx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_F5X_MY20_Tx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_Commodity_MYXX_Tx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_T6_MCA_MY2020_Rx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_P702_MY2021_Rx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_CX727_MY2021_Rx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_F5X_MY20_Rx" ENUM "No","Yes"; +BA_DEF_ SG_ "U_Commodity_MYXX_Rx" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigStartValue" HEX 0 268435455; +BA_DEF_ SG_ "MetaData" ENUM "No","Yes"; +BA_DEF_ SG_ "ApprovedOrphan" ENUM "No","Yes"; +BA_DEF_ SG_ "ContentDependant" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigStartValueInteger" INT 0 1000000000; +BA_DEF_ SG_ "UsedOnPgmDBC" ENUM "No","Yes"; +BA_DEF_ SG_ "CrossOver_InfoCAN" ENUM "No","Yes"; +BA_DEF_ SG_ "WakeupSignal" ENUM "No","Yes"; +BA_DEF_ SG_ "GenSigInactiveValue" INT 0 100000; +BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType"; +BA_DEF_ BO_ "SCP_FreshnessValueLength" INT 0 512; +BA_DEF_ BO_ "AuthFreshnessCounterSyncAttempt" INT 0 512; +BA_DEF_ BO_ "SCP_DataID" INT 0 65535; +BA_DEF_ BO_ "SCP_FreshnessValueTxLength" INT 0 512; +BA_DEF_ BO_ "SCP_AuthInfoTxLength" INT 0 512; +BA_DEF_ BO_ "SC_Message" ENUM "No","Yes"; +BA_DEF_ BO_ "ProgBWConditional" STRING; +BA_DEF_ BO_ "GenMsgRoutingTimeoutTime" INT 0 5000; +BA_DEF_ BO_ "MessageGateway" ENUM "No","Yes"; +BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes"; +BA_DEF_ BO_ "TpApplType" STRING; +BA_DEF_ BO_ "DiagState" ENUM "No","Yes"; +BA_DEF_ BO_ "TpTxIndex" INT 0 536870911; +BA_DEF_ BO_ "NetworkInitializationCommand" ENUM "No","Yes"; +BA_DEF_ BO_ "DiagRequest" ENUM "No","Yes"; +BA_DEF_ BO_ "DiagResponse" ENUM "No","Yes"; +BA_DEF_ BO_ "NmMessage" ENUM "No","Yes"; +BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes"; +BA_DEF_ BU_ "Terminator" ENUM "No","Yes"; +BA_DEF_ BU_ "NodeWakeUpTime" INT 0 10000; +BA_DEF_ BU_ "NodeStartUpTime" INT 0 10000; +BA_DEF_ BU_ "NmAsrNodeIdentifier" HEX 128 255; +BA_DEF_ BU_ "NmAsrNode" ENUM "No","Yes"; +BA_DEF_ BU_ "PowerType" ENUM "Switched","Latched","Sleep","vector_leerstring","vector_leerstring"; +BA_DEF_ BU_ "DiagNode" ENUM "GGDS","GDS","NONE"; +BA_DEF_ BU_ "EOL_SB_Flash" ENUM "GGDS","GDS","NONE","vector_leerstring"; +BA_DEF_ BU_ "NetworkInitializationUsed" ENUM "No","Yes"; +BA_DEF_ BU_ "NmNode" ENUM "No","Yes"; +BA_DEF_ BU_ "NmStationAddress" INT 0 255; +BA_DEF_ BU_ "ILUsed" ENUM "No","Yes"; +BA_DEF_ BU_ "NosPackage" ENUM "None","I3_1","I3_2","1.0.1","RP","EuCD","Volcano","I3_3","FNOS_Autosar"; +BA_DEF_ BU_ "LIN_Master" ENUM "No","Yes"; +BA_DEF_ BU_ "PackageID" STRING; +BA_DEF_ BU_ "GatewayECU" ENUM "No","Yes"; +BA_DEF_ "NetworkSpeed" ENUM "500kBits/s","125kBit/s"; +BA_DEF_ "VersionNumber" INT 0 10000; +BA_DEF_ "StarNetworkGwType" ENUM "0=NotDefined","1=HS1","2=HS2","3=HS3","4=HS4","5=HS5","6=MS1","7=HS6","8=HS7","9=MS2","10=FD1","11=FD2","12=FD3","13=FD4","14=FD5","15=FD6","16=FD7","17=FD8"; +BA_DEF_ "CMDB_Version" STRING; +BA_DEF_ "NmType" STRING; +BA_DEF_ "NmAsrMessageCount" INT 128 128; +BA_DEF_ "NmAsrBaseAddress" HEX 1408 1408; +BA_DEF_ "DBName" STRING; +BA_DEF_ "VersionDay" INT 1 31; +BA_DEF_ "Manufacturer" STRING; +BA_DEF_ "VersionMonth" INT 1 12; +BA_DEF_ "VersionYear" INT 2000 3000; +BA_DEF_ "NmBaseAddress" HEX 1280 1280; +BA_DEF_ "NmMessageCount" INT 0 128; +BA_DEF_DEF_ "OvtpPushApplication" "FALSE"; +BA_DEF_DEF_ "OvtpOperationMode" "SERVER"; +BA_DEF_DEF_ "OvtpEcuAddress" 0; +BA_DEF_DEF_ "ECGUsedRxSignal" "No"; +BA_DEF_DEF_ "U_S650_MY2022_Rx" "No"; +BA_DEF_DEF_ "ECGUsedTxSignal" "No"; +BA_DEF_DEF_ "U_S650_MY2022_Tx" "No"; +BA_DEF_DEF_ "GenSigTimeoutTime_CHCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_SOBDMC_HPCM_F" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_CMR_DSMC" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ECM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ECM_HEVDSL" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_AWD_DLCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ECM_HEV" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_GENERIC" 0; +BA_DEF_DEF_ "VFrameFormat" "ExtendedCAN_FD"; +BA_DEF_DEF_ "GenSigTimeoutTime_PSCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_HCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ABS_ESC" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ECM_Diesel" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TCCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime__delete" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TCM_DSL" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TSTR" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_IPMA_ADAS" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_GWM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_PCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_PCM_HEV" 0; +BA_DEF_DEF_ "BusType" ""; +BA_DEF_DEF_ "FrameRouting" "NONE"; +BA_DEF_DEF_ "FrameGatewayNetwork" "NONE"; +BA_DEF_DEF_ "FrameGateway_LC1" 0; +BA_DEF_DEF_ "FrameGatewayLC1_HS3" 0; +BA_DEF_DEF_ "FrameGatewayMS1" 0; +BA_DEF_DEF_ "FrameGatewayHS3" 0; +BA_DEF_DEF_ "FrameGatewayHS2" 0; +BA_DEF_DEF_ "FrameGatewayHS1" 0; +BA_DEF_DEF_ "NetworkInitialization" "Yes"; +BA_DEF_DEF_ "FrameGatewayId" 0; +BA_DEF_DEF_ "EventRateOfChange" 10000; +BA_DEF_DEF_ "ConfiguredTransmitter" "No"; +BA_DEF_DEF_ "GenMsgStartDelayTime" 0; +BA_DEF_DEF_ "GenMsgNrOfRepetition" 1; +BA_DEF_DEF_ "GenMsgDelayTime" 20; +BA_DEF_DEF_ "GenMsgCycleTimeFast" 0; +BA_DEF_DEF_ "GenMsgCycleTime" 0; +BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType"; +BA_DEF_DEF_ "U_T6_MCA_MY2020_Tx" "No"; +BA_DEF_DEF_ "U_P702_MY2021_Tx" "No"; +BA_DEF_DEF_ "U_CX727_MY2021_Tx" "No"; +BA_DEF_DEF_ "U_F5X_MY20_Tx" "No"; +BA_DEF_DEF_ "U_Commodity_MYXX_Tx" "No"; +BA_DEF_DEF_ "U_T6_MCA_MY2020_Rx" "No"; +BA_DEF_DEF_ "U_P702_MY2021_Rx" "No"; +BA_DEF_DEF_ "U_CX727_MY2021_Rx" "No"; +BA_DEF_DEF_ "U_F5X_MY20_Rx" "No"; +BA_DEF_DEF_ "U_Commodity_MYXX_Rx" "No"; +BA_DEF_DEF_ "GenSigStartValue" 0; +BA_DEF_DEF_ "MetaData" "No"; +BA_DEF_DEF_ "ApprovedOrphan" "No"; +BA_DEF_DEF_ "ContentDependant" "No"; +BA_DEF_DEF_ "GenSigStartValueInteger" 0; +BA_DEF_DEF_ "UsedOnPgmDBC" "Yes"; +BA_DEF_DEF_ "CrossOver_InfoCAN" "No"; +BA_DEF_DEF_ "WakeupSignal" "No"; +BA_DEF_DEF_ "GenSigInactiveValue" 0; +BA_DEF_DEF_ "GenSigSendType" "NoSigSendType"; +BA_DEF_DEF_ "SCP_FreshnessValueLength" 64; +BA_DEF_DEF_ "AuthFreshnessCounterSyncAttempt" 2; +BA_DEF_DEF_ "SCP_DataID" 0; +BA_DEF_DEF_ "SCP_FreshnessValueTxLength" 8; +BA_DEF_DEF_ "SCP_AuthInfoTxLength" 56; +BA_DEF_DEF_ "SC_Message" "No"; +BA_DEF_DEF_ "ProgBWConditional" "NONE"; +BA_DEF_DEF_ "GenMsgRoutingTimeoutTime" 0; +BA_DEF_DEF_ "MessageGateway" "No"; +BA_DEF_DEF_ "NmAsrMessage" "No"; +BA_DEF_DEF_ "TpApplType" ""; +BA_DEF_DEF_ "DiagState" "No"; +BA_DEF_DEF_ "TpTxIndex" 0; +BA_DEF_DEF_ "NetworkInitializationCommand" "No"; +BA_DEF_DEF_ "DiagRequest" "No"; +BA_DEF_DEF_ "DiagResponse" "No"; +BA_DEF_DEF_ "NmMessage" "No"; +BA_DEF_DEF_ "GenMsgILSupport" "Yes"; +BA_DEF_DEF_ "Terminator" "No"; +BA_DEF_DEF_ "NodeWakeUpTime" 10; +BA_DEF_DEF_ "NodeStartUpTime" 250; +BA_DEF_DEF_ "NmAsrNodeIdentifier" 128; +BA_DEF_DEF_ "NmAsrNode" "No"; +BA_DEF_DEF_ "PowerType" "Switched"; +BA_DEF_DEF_ "DiagNode" "GGDS"; +BA_DEF_DEF_ "EOL_SB_Flash" "GGDS"; +BA_DEF_DEF_ "NetworkInitializationUsed" "No"; +BA_DEF_DEF_ "NmNode" "No"; +BA_DEF_DEF_ "NmStationAddress" 0; +BA_DEF_DEF_ "ILUsed" "Yes"; +BA_DEF_DEF_ "NosPackage" "I3_3"; +BA_DEF_DEF_ "LIN_Master" "No"; +BA_DEF_DEF_ "PackageID" "08.05.00.00.71.xx.xx.rr.00.00"; +BA_DEF_DEF_ "GatewayECU" "No"; +BA_DEF_DEF_ "NetworkSpeed" "500kBits/s"; +BA_DEF_DEF_ "VersionNumber" 1; +BA_DEF_DEF_ "StarNetworkGwType" "0=NotDefined"; +BA_DEF_DEF_ "CMDB_Version" "v11.01"; +BA_DEF_DEF_ "NmType" "Ford-OSEK"; +BA_DEF_DEF_ "NmAsrMessageCount" 128; +BA_DEF_DEF_ "NmAsrBaseAddress" 1408; +BA_DEF_DEF_ "DBName" ""; +BA_DEF_DEF_ "VersionDay" 1; +BA_DEF_DEF_ "Manufacturer" "Ford"; +BA_DEF_DEF_ "VersionMonth" 1; +BA_DEF_DEF_ "VersionYear" 2011; +BA_DEF_DEF_ "NmBaseAddress" 1280; +BA_DEF_DEF_ "NmMessageCount" 128; +BA_ "BusType" "CAN FD"; +BA_ "VersionYear" 2019; +BA_ "VersionMonth" 4; +BA_ "Manufacturer" "Ford"; +BA_ "VersionDay" 11; +BA_ "CMDB_Version" "FNV2_v18.07"; +BA_ "StarNetworkGwType" 10; +BA_ "VersionNumber" 6; +BA_ "NmType" "Ford-OSEK"; +BA_ "DBName" "FD1_CAN"; +BA_ "NmStationAddress" BU_ VDM 48; +BA_ "OvtpEcuAddress" BU_ VDM 32; +BA_ "OvtpEcuAddress" BU_ CMR_DSMC 187; +BA_ "NmStationAddress" BU_ CMR_DSMC 95; +BA_ "PowerType" BU_ CMR_DSMC 2; +BA_ "NmAsrNode" BU_ CMR_DSMC 1; +BA_ "NmAsrNodeIdentifier" BU_ CMR_DSMC 223; +BA_ "OvtpEcuAddress" BU_ SOBDMC_HPCM_FD1 17; +BA_ "NmStationAddress" BU_ SOBDMC_HPCM_FD1 37; +BA_ "OvtpEcuAddress" BU_ IPMA_ADAS 33; +BA_ "NmStationAddress" BU_ IPMA_ADAS 28; +BA_ "NodeStartUpTime" BU_ IPMA_ADAS 300; +BA_ "OvtpEcuAddress" BU_ PSCM 48; +BA_ "NmStationAddress" BU_ PSCM 53; +BA_ "PowerType" BU_ PSCM 1; +BA_ "NmAsrNode" BU_ PSCM 1; +BA_ "NmAsrNodeIdentifier" BU_ PSCM 181; +BA_ "Terminator" BU_ PSCM 1; +BA_ "OvtpEcuAddress" BU_ ABS_ESC 40; +BA_ "NmStationAddress" BU_ ABS_ESC 22; +BA_ "PowerType" BU_ ABS_ESC 2; +BA_ "NmAsrNode" BU_ ABS_ESC 1; +BA_ "NmAsrNodeIdentifier" BU_ ABS_ESC 150; +BA_ "NodeStartUpTime" BU_ ABS_ESC 1000; +BA_ "NodeWakeUpTime" BU_ ABS_ESC 300; +BA_ "OvtpEcuAddress" BU_ TCCM 25; +BA_ "NmStationAddress" BU_ TCCM 33; +BA_ "NmAsrNode" BU_ TCCM 1; +BA_ "NmAsrNodeIdentifier" BU_ TCCM 161; +BA_ "NodeStartUpTime" BU_ TCCM 1000; +BA_ "NodeWakeUpTime" BU_ TCCM 25; +BA_ "OvtpEcuAddress" BU_ TCM_DSL 24; +BA_ "NmStationAddress" BU_ TCM_DSL 32; +BA_ "PowerType" BU_ TCM_DSL 1; +BA_ "NmAsrNode" BU_ TCM_DSL 1; +BA_ "NmAsrNodeIdentifier" BU_ TCM_DSL 160; +BA_ "NodeWakeUpTime" BU_ TCM_DSL 200; +BA_ "NosPackage" BU_ TCM_DSL 4; +BA_ "OvtpEcuAddress" BU_ PCM_HEV 16; +BA_ "NmStationAddress" BU_ PCM_HEV 21; +BA_ "PowerType" BU_ PCM_HEV 1; +BA_ "NmAsrNode" BU_ PCM_HEV 1; +BA_ "NmAsrNodeIdentifier" BU_ PCM_HEV 149; +BA_ "NodeStartUpTime" BU_ PCM_HEV 350; +BA_ "OvtpEcuAddress" BU_ PCM 16; +BA_ "NmStationAddress" BU_ PCM 21; +BA_ "PowerType" BU_ PCM 1; +BA_ "NmAsrNode" BU_ PCM 1; +BA_ "NmAsrNodeIdentifier" BU_ PCM 149; +BA_ "NodeStartUpTime" BU_ PCM 350; +BA_ "OvtpEcuAddress" BU_ ECM_Diesel 16; +BA_ "NmStationAddress" BU_ ECM_Diesel 21; +BA_ "PowerType" BU_ ECM_Diesel 1; +BA_ "NmAsrNode" BU_ ECM_Diesel 1; +BA_ "NmAsrNodeIdentifier" BU_ ECM_Diesel 149; +BA_ "OvtpEcuAddress" BU_ GWM 216; +BA_ "OvtpOperationMode" BU_ GWM 1; +BA_ "NmStationAddress" BU_ GWM 30; +BA_ "PowerType" BU_ GWM 2; +BA_ "NmAsrNode" BU_ GWM 1; +BA_ "NmAsrNodeIdentifier" BU_ GWM 158; +BA_ "NodeStartUpTime" BU_ GWM 100; +BA_ "Terminator" BU_ GWM 1; +BA_ "GatewayECU" BU_ GWM 1; +BA_ "NosPackage" BU_ GWM 4; +BA_ "GenMsgSendType" BO_ 823 5; +BA_ "GenMsgCycleTime" BO_ 823 1000; +BA_ "VFrameFormat" BO_ 823 14; +BA_ "GenMsgSendType" BO_ 824 5; +BA_ "GenMsgCycleTime" BO_ 824 1000; +BA_ "VFrameFormat" BO_ 824 14; +BA_ "FrameGatewayId" BO_ 949 949; +BA_ "FrameGatewayNetwork" BO_ 949 "HS1_CAN"; +BA_ "FrameRouting" BO_ 949 ""; +BA_ "VFrameFormat" BO_ 949 14; +BA_ "GenMsgILSupport" BO_ 1825 0; +BA_ "DiagRequest" BO_ 1825 1; +BA_ "GenMsgSendType" BO_ 1825 1; +BA_ "GenMsgDelayTime" BO_ 1825 0; +BA_ "NetworkInitialization" BO_ 1825 0; +BA_ "VFrameFormat" BO_ 1825 14; +BA_ "GenMsgDelayTime" BO_ 524 0; +BA_ "GenMsgCycleTime" BO_ 524 10; +BA_ "GenMsgSendType" BO_ 524 0; +BA_ "ProgBWConditional" BO_ 524 "MSGDCR1008_CX48X_V03_HS1D_56.84_mHEV_54.89"; +BA_ "VFrameFormat" BO_ 524 14; +BA_ "FrameRouting" BO_ 740 ""; +BA_ "FrameGatewayNetwork" BO_ 740 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 740 740; +BA_ "VFrameFormat" BO_ 740 14; +BA_ "GenMsgCycleTime" BO_ 1160 1000; +BA_ "GenMsgSendType" BO_ 1160 5; +BA_ "VFrameFormat" BO_ 1160 14; +BA_ "GenMsgCycleTime" BO_ 776 1000; +BA_ "GenMsgSendType" BO_ 776 5; +BA_ "VFrameFormat" BO_ 776 14; +BA_ "GenMsgCycleTime" BO_ 775 1000; +BA_ "GenMsgSendType" BO_ 775 5; +BA_ "VFrameFormat" BO_ 775 14; +BA_ "GenMsgCycleTime" BO_ 774 1000; +BA_ "GenMsgSendType" BO_ 774 5; +BA_ "VFrameFormat" BO_ 774 14; +BA_ "FrameGatewayId" BO_ 811 811; +BA_ "FrameGatewayNetwork" BO_ 811 "HS3_CAN"; +BA_ "FrameRouting" BO_ 811 ""; +BA_ "VFrameFormat" BO_ 811 14; +BA_ "GenMsgSendType" BO_ 850 0; +BA_ "GenMsgCycleTime" BO_ 850 150; +BA_ "VFrameFormat" BO_ 850 14; +BA_ "GenMsgCycleTime" BO_ 563 1000; +BA_ "GenMsgSendType" BO_ 563 5; +BA_ "VFrameFormat" BO_ 563 14; +BA_ "GenMsgILSupport" BO_ 1833 0; +BA_ "DiagResponse" BO_ 1833 1; +BA_ "GenMsgSendType" BO_ 1833 1; +BA_ "GenMsgDelayTime" BO_ 1833 0; +BA_ "NetworkInitialization" BO_ 1833 0; +BA_ "VFrameFormat" BO_ 1833 14; +BA_ "FrameRouting" BO_ 570 ""; +BA_ "GenMsgSendType" BO_ 570 0; +BA_ "GenMsgCycleTime" BO_ 570 20; +BA_ "GenMsgDelayTime" BO_ 570 10; +BA_ "VFrameFormat" BO_ 570 14; +BA_ "FrameRouting" BO_ 837 ""; +BA_ "GenMsgSendType" BO_ 837 5; +BA_ "GenMsgCycleTime" BO_ 837 1000; +BA_ "VFrameFormat" BO_ 837 14; +BA_ "FrameRouting" BO_ 885 ""; +BA_ "GenMsgSendType" BO_ 885 0; +BA_ "GenMsgCycleTime" BO_ 885 200; +BA_ "VFrameFormat" BO_ 885 14; +BA_ "FrameRouting" BO_ 1150 ""; +BA_ "FrameGatewayNetwork" BO_ 1150 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 1150 1118; +BA_ "VFrameFormat" BO_ 1150 14; +BA_ "FrameRouting" BO_ 542 ""; +BA_ "FrameGatewayNetwork" BO_ 542 "HS4_CAN"; +BA_ "FrameGatewayId" BO_ 542 542; +BA_ "VFrameFormat" BO_ 542 14; +BA_ "FrameRouting" BO_ 2612224016 ""; +BA_ "TpTxIndex" BO_ 2612224016 464535768; +BA_ "GenMsgSendType" BO_ 2612224016 1; +BA_ "GenMsgCycleTime" BO_ 2612224016 0; +BA_ "GenMsgDelayTime" BO_ 2612224016 0; +BA_ "NetworkInitialization" BO_ 2612224016 0; +BA_ "OvtpPushApplication" BO_ 2612224016 1; +BA_ "VFrameFormat" BO_ 2612224016 15; +BA_ "FrameRouting" BO_ 810 ""; +BA_ "GenMsgCycleTime" BO_ 810 1000; +BA_ "GenMsgSendType" BO_ 810 5; +BA_ "VFrameFormat" BO_ 810 14; +BA_ "FrameRouting" BO_ 550 ""; +BA_ "GenMsgCycleTime" BO_ 550 1000; +BA_ "GenMsgSendType" BO_ 550 5; +BA_ "VFrameFormat" BO_ 550 14; +BA_ "FrameRouting" BO_ 639 ""; +BA_ "GenMsgCycleTime" BO_ 639 1000; +BA_ "GenMsgSendType" BO_ 639 5; +BA_ "VFrameFormat" BO_ 639 14; +BA_ "FrameRouting" BO_ 530 ""; +BA_ "GenMsgCycleTime" BO_ 530 1000; +BA_ "GenMsgSendType" BO_ 530 5; +BA_ "VFrameFormat" BO_ 530 14; +BA_ "FrameRouting" BO_ 1142 ""; +BA_ "GenMsgSendType" BO_ 1142 0; +BA_ "GenMsgCycleTime" BO_ 1142 500; +BA_ "VFrameFormat" BO_ 1142 14; +BA_ "FrameRouting" BO_ 817 ""; +BA_ "FrameGatewayId" BO_ 817 817; +BA_ "FrameGatewayNetwork" BO_ 817 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 817 14; +BA_ "FrameRouting" BO_ 879 ""; +BA_ "FrameGatewayNetwork" BO_ 879 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 879 879; +BA_ "VFrameFormat" BO_ 879 14; +BA_ "FrameRouting" BO_ 878 ""; +BA_ "GenMsgSendType" BO_ 878 5; +BA_ "GenMsgCycleTime" BO_ 878 1000; +BA_ "VFrameFormat" BO_ 878 14; +BA_ "FrameRouting" BO_ 395 ""; +BA_ "FrameGatewayNetwork" BO_ 395 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 395 395; +BA_ "VFrameFormat" BO_ 395 14; +BA_ "TpTxIndex" BO_ 2611055832 463572184; +BA_ "FrameRouting" BO_ 2611055832 ""; +BA_ "NetworkInitialization" BO_ 2611055832 0; +BA_ "GenMsgDelayTime" BO_ 2611055832 0; +BA_ "GenMsgSendType" BO_ 2611055832 1; +BA_ "VFrameFormat" BO_ 2611055832 15; +BA_ "TpTxIndex" BO_ 2611054808 463571160; +BA_ "FrameRouting" BO_ 2611054808 ""; +BA_ "NetworkInitialization" BO_ 2611054808 0; +BA_ "GenMsgDelayTime" BO_ 2611054808 0; +BA_ "GenMsgSendType" BO_ 2611054808 1; +BA_ "VFrameFormat" BO_ 2611054808 15; +BA_ "TpTxIndex" BO_ 2611026136 463542488; +BA_ "FrameRouting" BO_ 2611026136 ""; +BA_ "NetworkInitialization" BO_ 2611026136 0; +BA_ "GenMsgDelayTime" BO_ 2611026136 0; +BA_ "GenMsgSendType" BO_ 2611026136 1; +BA_ "VFrameFormat" BO_ 2611026136 15; +BA_ "TpTxIndex" BO_ 2611025112 463541464; +BA_ "FrameRouting" BO_ 2611025112 ""; +BA_ "NetworkInitialization" BO_ 2611025112 0; +BA_ "GenMsgDelayTime" BO_ 2611025112 0; +BA_ "GenMsgSendType" BO_ 2611025112 1; +BA_ "VFrameFormat" BO_ 2611025112 15; +BA_ "TpTxIndex" BO_ 2610975960 463492312; +BA_ "FrameRouting" BO_ 2610975960 ""; +BA_ "NetworkInitialization" BO_ 2610975960 0; +BA_ "GenMsgDelayTime" BO_ 2610975960 0; +BA_ "GenMsgSendType" BO_ 2610975960 1; +BA_ "VFrameFormat" BO_ 2610975960 15; +BA_ "FrameRouting" BO_ 2610007256 ""; +BA_ "NetworkInitialization" BO_ 2610007256 0; +BA_ "GenMsgDelayTime" BO_ 2610007256 0; +BA_ "GenMsgSendType" BO_ 2610007256 1; +BA_ "TpTxIndex" BO_ 2610007256 462523608; +BA_ "VFrameFormat" BO_ 2610007256 15; +BA_ "FrameRouting" BO_ 2610006232 ""; +BA_ "NetworkInitialization" BO_ 2610006232 0; +BA_ "GenMsgDelayTime" BO_ 2610006232 0; +BA_ "GenMsgSendType" BO_ 2610006232 1; +BA_ "TpTxIndex" BO_ 2610006232 462522584; +BA_ "VFrameFormat" BO_ 2610006232 15; +BA_ "FrameRouting" BO_ 2609977560 ""; +BA_ "NetworkInitialization" BO_ 2609977560 0; +BA_ "GenMsgDelayTime" BO_ 2609977560 0; +BA_ "GenMsgSendType" BO_ 2609977560 1; +BA_ "TpTxIndex" BO_ 2609977560 462493912; +BA_ "VFrameFormat" BO_ 2609977560 15; +BA_ "FrameRouting" BO_ 2609976536 ""; +BA_ "NetworkInitialization" BO_ 2609976536 0; +BA_ "GenMsgDelayTime" BO_ 2609976536 0; +BA_ "GenMsgSendType" BO_ 2609976536 1; +BA_ "TpTxIndex" BO_ 2609976536 462492888; +BA_ "VFrameFormat" BO_ 2609976536 15; +BA_ "FrameRouting" BO_ 2609927384 ""; +BA_ "NetworkInitialization" BO_ 2609927384 0; +BA_ "GenMsgDelayTime" BO_ 2609927384 0; +BA_ "GenMsgSendType" BO_ 2609927384 1; +BA_ "TpTxIndex" BO_ 2609927384 462443736; +BA_ "VFrameFormat" BO_ 2609927384 15; +BA_ "TpTxIndex" BO_ 2611175523 463572184; +BA_ "FrameRouting" BO_ 2611175523 ""; +BA_ "NetworkInitialization" BO_ 2611175523 0; +BA_ "GenMsgDelayTime" BO_ 2611175523 0; +BA_ "GenMsgSendType" BO_ 2611175523 1; +BA_ "VFrameFormat" BO_ 2611175523 15; +BA_ "TpTxIndex" BO_ 2612224099 464620760; +BA_ "OvtpPushApplication" BO_ 2612224099 1; +BA_ "FrameRouting" BO_ 2612224099 ""; +BA_ "NetworkInitialization" BO_ 2612224099 0; +BA_ "GenMsgDelayTime" BO_ 2612224099 0; +BA_ "GenMsgSendType" BO_ 2612224099 1; +BA_ "VFrameFormat" BO_ 2612224099 15; +BA_ "TpTxIndex" BO_ 2611175522 463571160; +BA_ "FrameRouting" BO_ 2611175522 ""; +BA_ "NetworkInitialization" BO_ 2611175522 0; +BA_ "GenMsgDelayTime" BO_ 2611175522 0; +BA_ "GenMsgSendType" BO_ 2611175522 1; +BA_ "VFrameFormat" BO_ 2611175522 15; +BA_ "TpTxIndex" BO_ 2612224098 464619736; +BA_ "OvtpPushApplication" BO_ 2612224098 1; +BA_ "FrameRouting" BO_ 2612224098 ""; +BA_ "NetworkInitialization" BO_ 2612224098 0; +BA_ "GenMsgDelayTime" BO_ 2612224098 0; +BA_ "GenMsgSendType" BO_ 2612224098 1; +BA_ "VFrameFormat" BO_ 2612224098 15; +BA_ "TpTxIndex" BO_ 2611175494 463542488; +BA_ "FrameRouting" BO_ 2611175494 ""; +BA_ "NetworkInitialization" BO_ 2611175494 0; +BA_ "GenMsgDelayTime" BO_ 2611175494 0; +BA_ "GenMsgSendType" BO_ 2611175494 1; +BA_ "VFrameFormat" BO_ 2611175494 15; +BA_ "TpTxIndex" BO_ 2612224070 464591064; +BA_ "OvtpPushApplication" BO_ 2612224070 1; +BA_ "FrameRouting" BO_ 2612224070 ""; +BA_ "NetworkInitialization" BO_ 2612224070 0; +BA_ "GenMsgDelayTime" BO_ 2612224070 0; +BA_ "GenMsgSendType" BO_ 2612224070 1; +BA_ "VFrameFormat" BO_ 2612224070 15; +BA_ "TpTxIndex" BO_ 2611175493 463541464; +BA_ "FrameRouting" BO_ 2611175493 ""; +BA_ "NetworkInitialization" BO_ 2611175493 0; +BA_ "GenMsgDelayTime" BO_ 2611175493 0; +BA_ "GenMsgSendType" BO_ 2611175493 1; +BA_ "VFrameFormat" BO_ 2611175493 15; +BA_ "TpTxIndex" BO_ 2612224069 464590040; +BA_ "OvtpPushApplication" BO_ 2612224069 1; +BA_ "FrameRouting" BO_ 2612224069 ""; +BA_ "NetworkInitialization" BO_ 2612224069 0; +BA_ "GenMsgDelayTime" BO_ 2612224069 0; +BA_ "GenMsgSendType" BO_ 2612224069 1; +BA_ "VFrameFormat" BO_ 2612224069 15; +BA_ "TpTxIndex" BO_ 2611175445 463492312; +BA_ "FrameRouting" BO_ 2611175445 ""; +BA_ "NetworkInitialization" BO_ 2611175445 0; +BA_ "GenMsgDelayTime" BO_ 2611175445 0; +BA_ "GenMsgSendType" BO_ 2611175445 1; +BA_ "VFrameFormat" BO_ 2611175445 15; +BA_ "TpTxIndex" BO_ 2612224021 464540888; +BA_ "OvtpPushApplication" BO_ 2612224021 1; +BA_ "FrameRouting" BO_ 2612224021 ""; +BA_ "NetworkInitialization" BO_ 2612224021 0; +BA_ "GenMsgDelayTime" BO_ 2612224021 0; +BA_ "GenMsgSendType" BO_ 2612224021 1; +BA_ "VFrameFormat" BO_ 2612224021 15; +BA_ "TpTxIndex" BO_ 2610126947 462523608; +BA_ "FrameRouting" BO_ 2610126947 ""; +BA_ "NetworkInitialization" BO_ 2610126947 0; +BA_ "GenMsgDelayTime" BO_ 2610126947 0; +BA_ "GenMsgSendType" BO_ 2610126947 1; +BA_ "VFrameFormat" BO_ 2610126947 15; +BA_ "TpTxIndex" BO_ 2610126946 462522584; +BA_ "FrameRouting" BO_ 2610126946 ""; +BA_ "NetworkInitialization" BO_ 2610126946 0; +BA_ "GenMsgDelayTime" BO_ 2610126946 0; +BA_ "GenMsgSendType" BO_ 2610126946 1; +BA_ "VFrameFormat" BO_ 2610126946 15; +BA_ "TpTxIndex" BO_ 2610126918 462493912; +BA_ "FrameRouting" BO_ 2610126918 ""; +BA_ "NetworkInitialization" BO_ 2610126918 0; +BA_ "GenMsgDelayTime" BO_ 2610126918 0; +BA_ "GenMsgSendType" BO_ 2610126918 1; +BA_ "VFrameFormat" BO_ 2610126918 15; +BA_ "TpTxIndex" BO_ 2610126917 462492888; +BA_ "FrameRouting" BO_ 2610126917 ""; +BA_ "NetworkInitialization" BO_ 2610126917 0; +BA_ "GenMsgDelayTime" BO_ 2610126917 0; +BA_ "GenMsgSendType" BO_ 2610126917 1; +BA_ "VFrameFormat" BO_ 2610126917 15; +BA_ "FrameRouting" BO_ 2610126869 ""; +BA_ "NetworkInitialization" BO_ 2610126869 0; +BA_ "GenMsgDelayTime" BO_ 2610126869 0; +BA_ "GenMsgSendType" BO_ 2610126869 1; +BA_ "TpTxIndex" BO_ 2610126869 462443736; +BA_ "VFrameFormat" BO_ 2610126869 15; +BA_ "FrameRouting" BO_ 984 ""; +BA_ "GenMsgCycleTime" BO_ 984 1000; +BA_ "GenMsgSendType" BO_ 984 5; +BA_ "VFrameFormat" BO_ 984 14; +BA_ "FrameRouting" BO_ 985 ""; +BA_ "GenMsgSendType" BO_ 985 5; +BA_ "GenMsgCycleTime" BO_ 985 1000; +BA_ "VFrameFormat" BO_ 985 14; +BA_ "FrameRouting" BO_ 992 ""; +BA_ "FrameGatewayNetwork" BO_ 992 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 992 992; +BA_ "VFrameFormat" BO_ 992 14; +BA_ "OvtpPushApplication" BO_ 2612019416 1; +BA_ "FrameRouting" BO_ 2612019416 ""; +BA_ "TpTxIndex" BO_ 2612019416 464535768; +BA_ "NetworkInitialization" BO_ 2612019416 0; +BA_ "GenMsgDelayTime" BO_ 2612019416 0; +BA_ "GenMsgSendType" BO_ 2612019416 1; +BA_ "VFrameFormat" BO_ 2612019416 15; +BA_ "FrameRouting" BO_ 943 ""; +BA_ "GenMsgSendType" BO_ 943 0; +BA_ "GenMsgCycleTime" BO_ 943 20; +BA_ "GenMsgDelayTime" BO_ 943 10; +BA_ "VFrameFormat" BO_ 943 14; +BA_ "FrameRouting" BO_ 515 ""; +BA_ "GenMsgSendType" BO_ 515 5; +BA_ "GenMsgCycleTime" BO_ 515 100; +BA_ "VFrameFormat" BO_ 515 14; +BA_ "FrameRouting" BO_ 1111 ""; +BA_ "FrameGatewayId" BO_ 1111 1111; +BA_ "FrameGatewayNetwork" BO_ 1111 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 1111 14; +BA_ "FrameRouting" BO_ 1106 ""; +BA_ "FrameGatewayId" BO_ 1106 1106; +BA_ "FrameGatewayNetwork" BO_ 1106 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 1106 14; +BA_ "FrameRouting" BO_ 982 ""; +BA_ "GenMsgSendType" BO_ 982 0; +BA_ "GenMsgCycleTime" BO_ 982 50; +BA_ "VFrameFormat" BO_ 982 14; +BA_ "FrameRouting" BO_ 1985 ""; +BA_ "NetworkInitialization" BO_ 1985 0; +BA_ "GenMsgDelayTime" BO_ 1985 0; +BA_ "GenMsgSendType" BO_ 1985 1; +BA_ "DiagRequest" BO_ 1985 1; +BA_ "GenMsgILSupport" BO_ 1985 0; +BA_ "VFrameFormat" BO_ 1985 14; +BA_ "FrameRouting" BO_ 1993 ""; +BA_ "NetworkInitialization" BO_ 1993 0; +BA_ "GenMsgDelayTime" BO_ 1993 0; +BA_ "GenMsgSendType" BO_ 1993 1; +BA_ "DiagResponse" BO_ 1993 1; +BA_ "GenMsgILSupport" BO_ 1993 0; +BA_ "VFrameFormat" BO_ 1993 14; +BA_ "FrameRouting" BO_ 1104 ""; +BA_ "GenMsgCycleTime" BO_ 1104 200; +BA_ "GenMsgSendType" BO_ 1104 0; +BA_ "VFrameFormat" BO_ 1104 14; +BA_ "FrameRouting" BO_ 1503 ""; +BA_ "NetworkInitialization" BO_ 1503 0; +BA_ "GenMsgCycleTime" BO_ 1503 1000; +BA_ "GenMsgSendType" BO_ 1503 0; +BA_ "NmAsrMessage" BO_ 1503 1; +BA_ "GenMsgILSupport" BO_ 1503 0; +BA_ "VFrameFormat" BO_ 1503 14; +BA_ "TpTxIndex" BO_ 2610995416 463511768; +BA_ "FrameRouting" BO_ 2610995416 ""; +BA_ "NetworkInitialization" BO_ 2610995416 0; +BA_ "GenMsgDelayTime" BO_ 2610995416 0; +BA_ "GenMsgSendType" BO_ 2610995416 1; +BA_ "VFrameFormat" BO_ 2610995416 15; +BA_ "TpTxIndex" BO_ 2612043992 464560344; +BA_ "OvtpPushApplication" BO_ 2612043992 1; +BA_ "FrameRouting" BO_ 2612043992 ""; +BA_ "NetworkInitialization" BO_ 2612043992 0; +BA_ "GenMsgDelayTime" BO_ 2612043992 0; +BA_ "GenMsgSendType" BO_ 2612043992 1; +BA_ "VFrameFormat" BO_ 2612043992 15; +BA_ "FrameRouting" BO_ 2609946840 ""; +BA_ "NetworkInitialization" BO_ 2609946840 0; +BA_ "GenMsgDelayTime" BO_ 2609946840 0; +BA_ "GenMsgSendType" BO_ 2609946840 1; +BA_ "TpTxIndex" BO_ 2609946840 462463192; +BA_ "VFrameFormat" BO_ 2609946840 15; +BA_ "TpTxIndex" BO_ 2611175464 463511768; +BA_ "FrameRouting" BO_ 2611175464 ""; +BA_ "NetworkInitialization" BO_ 2611175464 0; +BA_ "GenMsgDelayTime" BO_ 2611175464 0; +BA_ "GenMsgSendType" BO_ 2611175464 1; +BA_ "VFrameFormat" BO_ 2611175464 15; +BA_ "TpTxIndex" BO_ 2612224040 464560344; +BA_ "OvtpPushApplication" BO_ 2612224040 1; +BA_ "FrameRouting" BO_ 2612224040 ""; +BA_ "NetworkInitialization" BO_ 2612224040 0; +BA_ "GenMsgDelayTime" BO_ 2612224040 0; +BA_ "GenMsgSendType" BO_ 2612224040 1; +BA_ "VFrameFormat" BO_ 2612224040 15; +BA_ "TpTxIndex" BO_ 2610126888 462463192; +BA_ "FrameRouting" BO_ 2610126888 ""; +BA_ "NetworkInitialization" BO_ 2610126888 0; +BA_ "GenMsgDelayTime" BO_ 2610126888 0; +BA_ "GenMsgSendType" BO_ 2610126888 1; +BA_ "VFrameFormat" BO_ 2610126888 15; +BA_ "TpTxIndex" BO_ 2610988248 463504600; +BA_ "FrameRouting" BO_ 2610988248 ""; +BA_ "NetworkInitialization" BO_ 2610988248 0; +BA_ "GenMsgDelayTime" BO_ 2610988248 0; +BA_ "GenMsgSendType" BO_ 2610988248 1; +BA_ "VFrameFormat" BO_ 2610988248 15; +BA_ "FrameRouting" BO_ 2609939672 ""; +BA_ "NetworkInitialization" BO_ 2609939672 0; +BA_ "GenMsgDelayTime" BO_ 2609939672 0; +BA_ "GenMsgSendType" BO_ 2609939672 1; +BA_ "TpTxIndex" BO_ 2609939672 462456024; +BA_ "VFrameFormat" BO_ 2609939672 15; +BA_ "FrameRouting" BO_ 1114 ""; +BA_ "FrameGatewayNetwork" BO_ 1114 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 1114 1114; +BA_ "VFrameFormat" BO_ 1114 14; +BA_ "FrameRouting" BO_ 1116 ""; +BA_ "FrameGatewayNetwork" BO_ 1116 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 1116 1116; +BA_ "VFrameFormat" BO_ 1116 14; +BA_ "TpTxIndex" BO_ 2611175457 463504600; +BA_ "FrameRouting" BO_ 2611175457 ""; +BA_ "NetworkInitialization" BO_ 2611175457 0; +BA_ "GenMsgDelayTime" BO_ 2611175457 0; +BA_ "GenMsgSendType" BO_ 2611175457 1; +BA_ "VFrameFormat" BO_ 2611175457 15; +BA_ "TpTxIndex" BO_ 2612224033 464553176; +BA_ "OvtpPushApplication" BO_ 2612224033 1; +BA_ "FrameRouting" BO_ 2612224033 ""; +BA_ "NetworkInitialization" BO_ 2612224033 0; +BA_ "GenMsgDelayTime" BO_ 2612224033 0; +BA_ "GenMsgSendType" BO_ 2612224033 1; +BA_ "VFrameFormat" BO_ 2612224033 15; +BA_ "TpTxIndex" BO_ 2610126881 462456024; +BA_ "FrameRouting" BO_ 2610126881 ""; +BA_ "NetworkInitialization" BO_ 2610126881 0; +BA_ "GenMsgDelayTime" BO_ 2610126881 0; +BA_ "GenMsgSendType" BO_ 2610126881 1; +BA_ "VFrameFormat" BO_ 2610126881 15; +BA_ "FrameRouting" BO_ 1085 ""; +BA_ "GenMsgSendType" BO_ 1085 0; +BA_ "GenMsgCycleTime" BO_ 1085 50; +BA_ "VFrameFormat" BO_ 1085 14; +BA_ "FrameRouting" BO_ 981 ""; +BA_ "GenMsgSendType" BO_ 981 0; +BA_ "GenMsgCycleTime" BO_ 981 30; +BA_ "VFrameFormat" BO_ 981 14; +BA_ "FrameRouting" BO_ 791 ""; +BA_ "FrameGatewayId" BO_ 791 791; +BA_ "FrameGatewayNetwork" BO_ 791 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 791 14; +BA_ "TpTxIndex" BO_ 2610970840 463487192; +BA_ "FrameRouting" BO_ 2610970840 ""; +BA_ "NetworkInitialization" BO_ 2610970840 0; +BA_ "GenMsgDelayTime" BO_ 2610970840 0; +BA_ "GenMsgSendType" BO_ 2610970840 1; +BA_ "VFrameFormat" BO_ 2610970840 15; +BA_ "TpTxIndex" BO_ 2609922264 462438616; +BA_ "FrameRouting" BO_ 2609922264 ""; +BA_ "NetworkInitialization" BO_ 2609922264 0; +BA_ "GenMsgDelayTime" BO_ 2609922264 0; +BA_ "GenMsgSendType" BO_ 2609922264 1; +BA_ "VFrameFormat" BO_ 2609922264 15; +BA_ "FrameRouting" BO_ 868 ""; +BA_ "FrameGatewayNetwork" BO_ 868 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 868 868; +BA_ "VFrameFormat" BO_ 868 14; +BA_ "FrameRouting" BO_ 867 ""; +BA_ "FrameGatewayNetwork" BO_ 867 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 867 867; +BA_ "VFrameFormat" BO_ 867 14; +BA_ "FrameRouting" BO_ 866 ""; +BA_ "FrameGatewayNetwork" BO_ 866 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 866 866; +BA_ "VFrameFormat" BO_ 866 14; +BA_ "FrameRouting" BO_ 865 ""; +BA_ "FrameGatewayNetwork" BO_ 865 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 865 865; +BA_ "VFrameFormat" BO_ 865 14; +BA_ "TpTxIndex" BO_ 2611175440 463487192; +BA_ "FrameRouting" BO_ 2611175440 ""; +BA_ "NetworkInitialization" BO_ 2611175440 0; +BA_ "GenMsgDelayTime" BO_ 2611175440 0; +BA_ "GenMsgCycleTime" BO_ 2611175440 0; +BA_ "GenMsgSendType" BO_ 2611175440 1; +BA_ "VFrameFormat" BO_ 2611175440 15; +BA_ "TpTxIndex" BO_ 2610126864 462438616; +BA_ "FrameRouting" BO_ 2610126864 ""; +BA_ "NetworkInitialization" BO_ 2610126864 0; +BA_ "GenMsgDelayTime" BO_ 2610126864 0; +BA_ "GenMsgSendType" BO_ 2610126864 1; +BA_ "VFrameFormat" BO_ 2610126864 15; +BA_ "TpTxIndex" BO_ 2611175441 463488216; +BA_ "FrameRouting" BO_ 2611175441 ""; +BA_ "NetworkInitialization" BO_ 2611175441 0; +BA_ "GenMsgDelayTime" BO_ 2611175441 0; +BA_ "GenMsgSendType" BO_ 2611175441 1; +BA_ "VFrameFormat" BO_ 2611175441 15; +BA_ "TpTxIndex" BO_ 2612224017 463488216; +BA_ "OvtpPushApplication" BO_ 2612224017 1; +BA_ "FrameRouting" BO_ 2612224017 ""; +BA_ "NetworkInitialization" BO_ 2612224017 0; +BA_ "GenMsgDelayTime" BO_ 2612224017 0; +BA_ "GenMsgSendType" BO_ 2612224017 1; +BA_ "VFrameFormat" BO_ 2612224017 15; +BA_ "FrameRouting" BO_ 2610126865 ""; +BA_ "NetworkInitialization" BO_ 2610126865 0; +BA_ "GenMsgDelayTime" BO_ 2610126865 0; +BA_ "GenMsgSendType" BO_ 2610126865 1; +BA_ "TpTxIndex" BO_ 2610126865 462439640; +BA_ "VFrameFormat" BO_ 2610126865 15; +BA_ "FrameRouting" BO_ 1679 ""; +BA_ "GenMsgCycleTime" BO_ 1679 0; +BA_ "GenMsgSendType" BO_ 1679 1; +BA_ "TpApplType" BO_ 1679 "DiagUUDTResponse"; +BA_ "GenMsgILSupport" BO_ 1679 0; +BA_ "VFrameFormat" BO_ 1679 14; +BA_ "FrameRouting" BO_ 1678 ""; +BA_ "GenMsgCycleTime" BO_ 1678 0; +BA_ "GenMsgSendType" BO_ 1678 1; +BA_ "TpApplType" BO_ 1678 "DiagUUDTResponse"; +BA_ "GenMsgILSupport" BO_ 1678 0; +BA_ "VFrameFormat" BO_ 1678 14; +BA_ "FrameRouting" BO_ 1677 ""; +BA_ "GenMsgCycleTime" BO_ 1677 0; +BA_ "GenMsgSendType" BO_ 1677 1; +BA_ "TpApplType" BO_ 1677 "DiagUUDTResponse"; +BA_ "GenMsgILSupport" BO_ 1677 0; +BA_ "VFrameFormat" BO_ 1677 14; +BA_ "FrameRouting" BO_ 1676 ""; +BA_ "GenMsgCycleTime" BO_ 1676 0; +BA_ "GenMsgSendType" BO_ 1676 1; +BA_ "TpApplType" BO_ 1676 "DiagUUDTResponse"; +BA_ "GenMsgILSupport" BO_ 1676 0; +BA_ "VFrameFormat" BO_ 1676 14; +BA_ "FrameRouting" BO_ 1445 ""; +BA_ "GenMsgILSupport" BO_ 1445 0; +BA_ "NmAsrMessage" BO_ 1445 1; +BA_ "GenMsgSendType" BO_ 1445 0; +BA_ "GenMsgCycleTime" BO_ 1445 1000; +BA_ "NetworkInitialization" BO_ 1445 0; +BA_ "VFrameFormat" BO_ 1445 14; +BA_ "FrameRouting" BO_ 1144 ""; +BA_ "GenMsgSendType" BO_ 1144 5; +BA_ "GenMsgCycleTime" BO_ 1144 1000; +BA_ "VFrameFormat" BO_ 1144 14; +BA_ "FrameRouting" BO_ 1141 ""; +BA_ "GenMsgSendType" BO_ 1141 0; +BA_ "GenMsgCycleTime" BO_ 1141 500; +BA_ "VFrameFormat" BO_ 1141 14; +BA_ "FrameRouting" BO_ 1140 ""; +BA_ "GenMsgSendType" BO_ 1140 0; +BA_ "GenMsgCycleTime" BO_ 1140 1000; +BA_ "VFrameFormat" BO_ 1140 14; +BA_ "FrameRouting" BO_ 1139 ""; +BA_ "GenMsgCycleTime" BO_ 1139 1500; +BA_ "GenMsgSendType" BO_ 1139 0; +BA_ "VFrameFormat" BO_ 1139 14; +BA_ "FrameRouting" BO_ 1138 ""; +BA_ "GenMsgCycleTime" BO_ 1138 1500; +BA_ "GenMsgSendType" BO_ 1138 0; +BA_ "VFrameFormat" BO_ 1138 14; +BA_ "FrameRouting" BO_ 1089 ""; +BA_ "GenMsgCycleTime" BO_ 1089 1000; +BA_ "GenMsgSendType" BO_ 1089 0; +BA_ "VFrameFormat" BO_ 1089 14; +BA_ "FrameRouting" BO_ 1088 ""; +BA_ "GenMsgCycleTime" BO_ 1088 1000; +BA_ "GenMsgSendType" BO_ 1088 0; +BA_ "VFrameFormat" BO_ 1088 14; +BA_ "FrameRouting" BO_ 1040 ""; +BA_ "GenMsgCycleTime" BO_ 1040 100; +BA_ "GenMsgSendType" BO_ 1040 0; +BA_ "VFrameFormat" BO_ 1040 14; +BA_ "FrameRouting" BO_ 1016 ""; +BA_ "GenMsgCycleTime" BO_ 1016 1000; +BA_ "GenMsgSendType" BO_ 1016 5; +BA_ "VFrameFormat" BO_ 1016 14; +BA_ "FrameRouting" BO_ 1013 ""; +BA_ "GenMsgCycleTime" BO_ 1013 1000; +BA_ "GenMsgSendType" BO_ 1013 5; +BA_ "VFrameFormat" BO_ 1013 14; +BA_ "FrameRouting" BO_ 1012 ""; +BA_ "GenMsgCycleTime" BO_ 1012 1000; +BA_ "GenMsgSendType" BO_ 1012 5; +BA_ "VFrameFormat" BO_ 1012 14; +BA_ "FrameRouting" BO_ 1011 ""; +BA_ "GenMsgCycleTime" BO_ 1011 1000; +BA_ "GenMsgSendType" BO_ 1011 5; +BA_ "VFrameFormat" BO_ 1011 14; +BA_ "FrameRouting" BO_ 871 ""; +BA_ "GenMsgCycleTime" BO_ 871 100; +BA_ "GenMsgSendType" BO_ 871 0; +BA_ "VFrameFormat" BO_ 871 14; +BA_ "FrameRouting" BO_ 786 ""; +BA_ "GenMsgCycleTime" BO_ 786 100; +BA_ "GenMsgSendType" BO_ 786 0; +BA_ "VFrameFormat" BO_ 786 14; +BA_ "FrameRouting" BO_ 72 ""; +BA_ "GenMsgDelayTime" BO_ 72 10; +BA_ "GenMsgCycleTime" BO_ 72 20; +BA_ "GenMsgSendType" BO_ 72 0; +BA_ "VFrameFormat" BO_ 72 14; +BA_ "FrameRouting" BO_ 912 ""; +BA_ "FrameGatewayNetwork" BO_ 912 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 912 912; +BA_ "VFrameFormat" BO_ 912 14; +BA_ "FrameRouting" BO_ 874 ""; +BA_ "FrameGatewayNetwork" BO_ 874 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 874 874; +BA_ "VFrameFormat" BO_ 874 14; +BA_ "FrameRouting" BO_ 651 ""; +BA_ "FrameGatewayNetwork" BO_ 651 "HS4_CAN"; +BA_ "FrameGatewayId" BO_ 651 651; +BA_ "VFrameFormat" BO_ 651 14; +BA_ "FrameRouting" BO_ 529 ""; +BA_ "FrameGatewayNetwork" BO_ 529 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 529 529; +BA_ "VFrameFormat" BO_ 529 14; +BA_ "FrameRouting" BO_ 66 ""; +BA_ "FrameGatewayNetwork" BO_ 66 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 66 66; +BA_ "DiagResponse" BO_ 66 0; +BA_ "VFrameFormat" BO_ 66 14; +BA_ "TpTxIndex" BO_ 2610971864 463488216; +BA_ "FrameRouting" BO_ 2610971864 ""; +BA_ "NetworkInitialization" BO_ 2610971864 0; +BA_ "GenMsgDelayTime" BO_ 2610971864 0; +BA_ "GenMsgSendType" BO_ 2610971864 1; +BA_ "VFrameFormat" BO_ 2610971864 15; +BA_ "TpTxIndex" BO_ 2612002008 464518360; +BA_ "FrameRouting" BO_ 2612002008 ""; +BA_ "NetworkInitialization" BO_ 2612002008 0; +BA_ "GenMsgDelayTime" BO_ 2612002008 0; +BA_ "GenMsgSendType" BO_ 2612002008 1; +BA_ "VFrameFormat" BO_ 2612002008 15; +BA_ "FrameRouting" BO_ 2609923288 ""; +BA_ "NetworkInitialization" BO_ 2609923288 0; +BA_ "GenMsgDelayTime" BO_ 2609923288 0; +BA_ "GenMsgSendType" BO_ 2609923288 1; +BA_ "TpTxIndex" BO_ 2609923288 462439640; +BA_ "VFrameFormat" BO_ 2609923288 15; +BA_ "TpTxIndex" BO_ 2610953432 463469784; +BA_ "FrameRouting" BO_ 2610953432 ""; +BA_ "NetworkInitialization" BO_ 2610953432 0; +BA_ "GenMsgDelayTime" BO_ 2610953432 0; +BA_ "GenMsgSendType" BO_ 2610953432 1; +BA_ "VFrameFormat" BO_ 2610953432 15; +BA_ "FrameRouting" BO_ 2022 ""; +BA_ "GenMsgILSupport" BO_ 2022 0; +BA_ "DiagRequest" BO_ 2022 1; +BA_ "GenMsgSendType" BO_ 2022 1; +BA_ "GenMsgDelayTime" BO_ 2022 0; +BA_ "VFrameFormat" BO_ 2022 14; +BA_ "FrameRouting" BO_ 1124 ""; +BA_ "FrameGatewayId" BO_ 1124 1124; +BA_ "FrameGatewayNetwork" BO_ 1124 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1124 14; +BA_ "FrameRouting" BO_ 1119 ""; +BA_ "FrameGatewayId" BO_ 1119 1119; +BA_ "FrameGatewayNetwork" BO_ 1119 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1119 14; +BA_ "FrameRouting" BO_ 132 ""; +BA_ "FrameGatewayNetwork" BO_ 132 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 132 132; +BA_ "VFrameFormat" BO_ 132 14; +BA_ "FrameRouting" BO_ 1990 ""; +BA_ "NetworkInitialization" BO_ 1990 0; +BA_ "GenMsgDelayTime" BO_ 1990 0; +BA_ "GenMsgSendType" BO_ 1990 1; +BA_ "DiagRequest" BO_ 1990 1; +BA_ "GenMsgILSupport" BO_ 1990 0; +BA_ "VFrameFormat" BO_ 1990 14; +BA_ "FrameRouting" BO_ 1892 ""; +BA_ "NetworkInitialization" BO_ 1892 0; +BA_ "GenMsgDelayTime" BO_ 1892 0; +BA_ "GenMsgSendType" BO_ 1892 1; +BA_ "DiagRequest" BO_ 1892 1; +BA_ "GenMsgILSupport" BO_ 1892 0; +BA_ "VFrameFormat" BO_ 1892 14; +BA_ "FrameRouting" BO_ 1798 ""; +BA_ "NetworkInitialization" BO_ 1798 0; +BA_ "GenMsgDelayTime" BO_ 1798 0; +BA_ "GenMsgSendType" BO_ 1798 1; +BA_ "DiagRequest" BO_ 1798 1; +BA_ "GenMsgILSupport" BO_ 1798 0; +BA_ "VFrameFormat" BO_ 1798 14; +BA_ "FrameRouting" BO_ 1123 ""; +BA_ "FrameGatewayNetwork" BO_ 1123 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 1123 1123; +BA_ "VFrameFormat" BO_ 1123 14; +BA_ "FrameRouting" BO_ 1122 ""; +BA_ "FrameGatewayNetwork" BO_ 1122 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 1122 1122; +BA_ "VFrameFormat" BO_ 1122 14; +BA_ "FrameRouting" BO_ 1003 ""; +BA_ "FrameGatewayNetwork" BO_ 1003 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 1003 1003; +BA_ "VFrameFormat" BO_ 1003 14; +BA_ "FrameRouting" BO_ 994 ""; +BA_ "FrameGatewayNetwork" BO_ 994 "HS3_CAN"; +BA_ "FrameGatewayId" BO_ 994 994; +BA_ "VFrameFormat" BO_ 994 14; +BA_ "FrameRouting" BO_ 778 ""; +BA_ "FrameGatewayId" BO_ 778 778; +BA_ "FrameGatewayNetwork" BO_ 778 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 778 14; +BA_ "FrameRouting" BO_ 549 ""; +BA_ "FrameGatewayId" BO_ 549 549; +BA_ "FrameGatewayNetwork" BO_ 549 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 549 14; +BA_ "FrameRouting" BO_ 551 ""; +BA_ "FrameGatewayId" BO_ 551 551; +BA_ "FrameGatewayNetwork" BO_ 551 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 551 14; +BA_ "FrameRouting" BO_ 1010 ""; +BA_ "GenMsgCycleTime" BO_ 1010 50; +BA_ "GenMsgSendType" BO_ 1010 0; +BA_ "VFrameFormat" BO_ 1010 14; +BA_ "FrameRouting" BO_ 1070 ""; +BA_ "FrameGatewayNetwork" BO_ 1070 "HS1_CAN"; +BA_ "FrameGatewayId" BO_ 1070 1070; +BA_ "VFrameFormat" BO_ 1070 14; +BA_ "FrameRouting" BO_ 1186 ""; +BA_ "GenMsgSendType" BO_ 1186 0; +BA_ "GenMsgCycleTime" BO_ 1186 100; +BA_ "VFrameFormat" BO_ 1186 14; +BA_ "FrameRouting" BO_ 611 ""; +BA_ "GenMsgSendType" BO_ 611 0; +BA_ "GenMsgCycleTime" BO_ 611 100; +BA_ "VFrameFormat" BO_ 611 14; +BA_ "FrameRouting" BO_ 1461 ""; +BA_ "GenMsgILSupport" BO_ 1461 0; +BA_ "NmAsrMessage" BO_ 1461 1; +BA_ "GenMsgSendType" BO_ 1461 0; +BA_ "GenMsgCycleTime" BO_ 1461 1000; +BA_ "NetworkInitialization" BO_ 1461 0; +BA_ "VFrameFormat" BO_ 1461 14; +BA_ "FrameRouting" BO_ 1047 ""; +BA_ "GenMsgSendType" BO_ 1047 5; +BA_ "GenMsgCycleTime" BO_ 1047 1000; +BA_ "VFrameFormat" BO_ 1047 14; +BA_ "FrameRouting" BO_ 972 ""; +BA_ "GenMsgSendType" BO_ 972 0; +BA_ "GenMsgCycleTime" BO_ 972 30; +BA_ "GenMsgDelayTime" BO_ 972 10; +BA_ "VFrameFormat" BO_ 972 14; +BA_ "FrameRouting" BO_ 130 ""; +BA_ "GenMsgSendType" BO_ 130 0; +BA_ "GenMsgCycleTime" BO_ 130 20; +BA_ "GenMsgDelayTime" BO_ 130 10; +BA_ "VFrameFormat" BO_ 130 14; +BA_ "FrameRouting" BO_ 126 ""; +BA_ "GenMsgSendType" BO_ 126 0; +BA_ "GenMsgCycleTime" BO_ 126 10; +BA_ "GenMsgDelayTime" BO_ 126 0; +BA_ "VFrameFormat" BO_ 126 14; +BA_ "FrameRouting" BO_ 133 ""; +BA_ "GenMsgSendType" BO_ 133 0; +BA_ "GenMsgCycleTime" BO_ 133 10; +BA_ "GenMsgDelayTime" BO_ 133 0; +BA_ "VFrameFormat" BO_ 133 14; +BA_ "FrameRouting" BO_ 1430 ""; +BA_ "GenMsgILSupport" BO_ 1430 0; +BA_ "NmAsrMessage" BO_ 1430 1; +BA_ "GenMsgSendType" BO_ 1430 0; +BA_ "GenMsgCycleTime" BO_ 1430 1000; +BA_ "NetworkInitialization" BO_ 1430 0; +BA_ "VFrameFormat" BO_ 1430 14; +BA_ "FrameRouting" BO_ 1200 ""; +BA_ "GenMsgSendType" BO_ 1200 0; +BA_ "GenMsgCycleTime" BO_ 1200 20; +BA_ "GenMsgDelayTime" BO_ 1200 10; +BA_ "VFrameFormat" BO_ 1200 14; +BA_ "FrameRouting" BO_ 1102 ""; +BA_ "GenMsgSendType" BO_ 1102 5; +BA_ "GenMsgCycleTime" BO_ 1102 100000; +BA_ "GenMsgStartDelayTime" BO_ 1102 1130; +BA_ "VFrameFormat" BO_ 1102 14; +BA_ "FrameRouting" BO_ 1056 ""; +BA_ "GenMsgSendType" BO_ 1056 5; +BA_ "GenMsgCycleTime" BO_ 1056 1000; +BA_ "VFrameFormat" BO_ 1056 14; +BA_ "FrameRouting" BO_ 1054 ""; +BA_ "GenMsgSendType" BO_ 1054 5; +BA_ "GenMsgCycleTime" BO_ 1054 1000; +BA_ "VFrameFormat" BO_ 1054 14; +BA_ "FrameRouting" BO_ 1046 ""; +BA_ "GenMsgSendType" BO_ 1046 0; +BA_ "GenMsgCycleTime" BO_ 1046 100; +BA_ "VFrameFormat" BO_ 1046 14; +BA_ "FrameRouting" BO_ 1045 ""; +BA_ "GenMsgSendType" BO_ 1045 0; +BA_ "GenMsgCycleTime" BO_ 1045 20; +BA_ "GenMsgDelayTime" BO_ 1045 10; +BA_ "VFrameFormat" BO_ 1045 14; +BA_ "FrameRouting" BO_ 1044 ""; +BA_ "GenMsgSendType" BO_ 1044 0; +BA_ "GenMsgCycleTime" BO_ 1044 100; +BA_ "VFrameFormat" BO_ 1044 14; +BA_ "FrameRouting" BO_ 1042 ""; +BA_ "GenMsgSendType" BO_ 1042 0; +BA_ "GenMsgCycleTime" BO_ 1042 50; +BA_ "VFrameFormat" BO_ 1042 14; +BA_ "FrameRouting" BO_ 535 ""; +BA_ "GenMsgSendType" BO_ 535 0; +BA_ "GenMsgCycleTime" BO_ 535 10; +BA_ "GenMsgDelayTime" BO_ 535 0; +BA_ "VFrameFormat" BO_ 535 14; +BA_ "FrameRouting" BO_ 534 ""; +BA_ "GenMsgSendType" BO_ 534 0; +BA_ "GenMsgCycleTime" BO_ 534 20; +BA_ "GenMsgDelayTime" BO_ 534 10; +BA_ "VFrameFormat" BO_ 534 14; +BA_ "FrameRouting" BO_ 532 ""; +BA_ "GenMsgSendType" BO_ 532 0; +BA_ "GenMsgCycleTime" BO_ 532 20; +BA_ "GenMsgDelayTime" BO_ 532 10; +BA_ "VFrameFormat" BO_ 532 14; +BA_ "FrameRouting" BO_ 531 ""; +BA_ "GenMsgSendType" BO_ 531 0; +BA_ "GenMsgCycleTime" BO_ 531 20; +BA_ "GenMsgDelayTime" BO_ 531 10; +BA_ "VFrameFormat" BO_ 531 14; +BA_ "FrameRouting" BO_ 136 ""; +BA_ "GenMsgSendType" BO_ 136 0; +BA_ "GenMsgCycleTime" BO_ 136 10; +BA_ "GenMsgDelayTime" BO_ 136 0; +BA_ "VFrameFormat" BO_ 136 14; +BA_ "FrameRouting" BO_ 125 ""; +BA_ "GenMsgSendType" BO_ 125 0; +BA_ "GenMsgCycleTime" BO_ 125 20; +BA_ "GenMsgDelayTime" BO_ 125 10; +BA_ "VFrameFormat" BO_ 125 14; +BA_ "FrameRouting" BO_ 119 ""; +BA_ "GenMsgSendType" BO_ 119 0; +BA_ "GenMsgCycleTime" BO_ 119 20; +BA_ "GenMsgDelayTime" BO_ 119 10; +BA_ "VFrameFormat" BO_ 119 14; +BA_ "FrameRouting" BO_ 118 ""; +BA_ "GenMsgSendType" BO_ 118 5; +BA_ "GenMsgCycleTime" BO_ 118 500; +BA_ "VFrameFormat" BO_ 118 14; +BA_ "FrameRouting" BO_ 73 ""; +BA_ "GenMsgSendType" BO_ 73 0; +BA_ "GenMsgCycleTime" BO_ 73 20; +BA_ "GenMsgDelayTime" BO_ 73 10; +BA_ "VFrameFormat" BO_ 73 14; +BA_ "FrameRouting" BO_ 1034 ""; +BA_ "FrameGatewayId" BO_ 1034 1034; +BA_ "FrameGatewayNetwork" BO_ 1034 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1034 14; +BA_ "FrameRouting" BO_ 1440 ""; +BA_ "GenMsgILSupport" BO_ 1440 0; +BA_ "NmAsrMessage" BO_ 1440 1; +BA_ "GenMsgSendType" BO_ 1440 0; +BA_ "GenMsgCycleTime" BO_ 1440 1000; +BA_ "NetworkInitialization" BO_ 1440 0; +BA_ "VFrameFormat" BO_ 1440 14; +BA_ "FrameRouting" BO_ 561 ""; +BA_ "GenMsgSendType" BO_ 561 0; +BA_ "GenMsgCycleTime" BO_ 561 100; +BA_ "VFrameFormat" BO_ 561 14; +BA_ "FrameRouting" BO_ 330 ""; +BA_ "GenMsgSendType" BO_ 330 0; +BA_ "GenMsgCycleTime" BO_ 330 10; +BA_ "GenMsgDelayTime" BO_ 330 0; +BA_ "VFrameFormat" BO_ 330 14; +BA_ "FrameRouting" BO_ 1090 ""; +BA_ "GenMsgSendType" BO_ 1090 0; +BA_ "GenMsgCycleTime" BO_ 1090 1000; +BA_ "VFrameFormat" BO_ 1090 14; +BA_ "FrameRouting" BO_ 870 ""; +BA_ "GenMsgSendType" BO_ 870 0; +BA_ "GenMsgCycleTime" BO_ 870 100; +BA_ "VFrameFormat" BO_ 870 14; +BA_ "FrameRouting" BO_ 869 ""; +BA_ "GenMsgSendType" BO_ 869 0; +BA_ "GenMsgCycleTime" BO_ 869 100; +BA_ "VFrameFormat" BO_ 869 14; +BA_ "FrameRouting" BO_ 606 ""; +BA_ "GenMsgSendType" BO_ 606 5; +BA_ "GenMsgCycleTime" BO_ 606 1000; +BA_ "VFrameFormat" BO_ 606 14; +BA_ "FrameRouting" BO_ 374 ""; +BA_ "GenMsgSendType" BO_ 374 5; +BA_ "GenMsgCycleTime" BO_ 374 100; +BA_ "VFrameFormat" BO_ 374 14; +BA_ "FrameRouting" BO_ 603 ""; +BA_ "GenMsgSendType" BO_ 603 0; +BA_ "GenMsgCycleTime" BO_ 603 20; +BA_ "GenMsgDelayTime" BO_ 603 10; +BA_ "VFrameFormat" BO_ 603 14; +BA_ "FrameRouting" BO_ 602 ""; +BA_ "GenMsgSendType" BO_ 602 0; +BA_ "GenMsgCycleTime" BO_ 602 100; +BA_ "VFrameFormat" BO_ 602 14; +BA_ "FrameRouting" BO_ 1152 ""; +BA_ "GenMsgSendType" BO_ 1152 5; +BA_ "GenMsgCycleTime" BO_ 1152 1000; +BA_ "VFrameFormat" BO_ 1152 14; +BA_ "FrameRouting" BO_ 872 ""; +BA_ "GenMsgSendType" BO_ 872 0; +BA_ "GenMsgCycleTime" BO_ 872 100; +BA_ "VFrameFormat" BO_ 872 14; +BA_ "FrameRouting" BO_ 560 ""; +BA_ "GenMsgSendType" BO_ 560 0; +BA_ "GenMsgCycleTime" BO_ 560 20; +BA_ "GenMsgDelayTime" BO_ 560 10; +BA_ "VFrameFormat" BO_ 560 14; +BA_ "FrameRouting" BO_ 369 ""; +BA_ "GenMsgSendType" BO_ 369 0; +BA_ "GenMsgCycleTime" BO_ 369 30; +BA_ "GenMsgDelayTime" BO_ 369 10; +BA_ "VFrameFormat" BO_ 369 14; +BA_ "FrameRouting" BO_ 92 ""; +BA_ "GenMsgSendType" BO_ 92 5; +BA_ "GenMsgCycleTime" BO_ 92 100; +BA_ "VFrameFormat" BO_ 92 14; +BA_ "FrameRouting" BO_ 2030 ""; +BA_ "GenMsgILSupport" BO_ 2030 0; +BA_ "DiagResponse" BO_ 2030 1; +BA_ "GenMsgSendType" BO_ 2030 1; +BA_ "GenMsgDelayTime" BO_ 2030 0; +BA_ "NetworkInitialization" BO_ 2030 0; +BA_ "VFrameFormat" BO_ 2030 14; +BA_ "FrameRouting" BO_ 1087 ""; +BA_ "GenMsgSendType" BO_ 1087 0; +BA_ "GenMsgCycleTime" BO_ 1087 100; +BA_ "VFrameFormat" BO_ 1087 14; +BA_ "FrameRouting" BO_ 332 ""; +BA_ "GenMsgSendType" BO_ 332 0; +BA_ "GenMsgCycleTime" BO_ 332 200; +BA_ "VFrameFormat" BO_ 332 14; +BA_ "FrameRouting" BO_ 1896 ""; +BA_ "GenMsgILSupport" BO_ 1896 0; +BA_ "DiagResponse" BO_ 1896 1; +BA_ "GenMsgSendType" BO_ 1896 1; +BA_ "GenMsgDelayTime" BO_ 1896 0; +BA_ "NetworkInitialization" BO_ 1896 0; +BA_ "VFrameFormat" BO_ 1896 14; +BA_ "FrameRouting" BO_ 1889 ""; +BA_ "GenMsgILSupport" BO_ 1889 0; +BA_ "DiagRequest" BO_ 1889 1; +BA_ "GenMsgSendType" BO_ 1889 1; +BA_ "GenMsgDelayTime" BO_ 1889 0; +BA_ "NetworkInitialization" BO_ 1889 0; +BA_ "VFrameFormat" BO_ 1889 14; +BA_ "FrameRouting" BO_ 1888 ""; +BA_ "GenMsgILSupport" BO_ 1888 0; +BA_ "DiagRequest" BO_ 1888 1; +BA_ "GenMsgSendType" BO_ 1888 1; +BA_ "GenMsgDelayTime" BO_ 1888 0; +BA_ "NetworkInitialization" BO_ 1888 0; +BA_ "VFrameFormat" BO_ 1888 14; +BA_ "FrameRouting" BO_ 1848 ""; +BA_ "GenMsgILSupport" BO_ 1848 0; +BA_ "DiagResponse" BO_ 1848 1; +BA_ "GenMsgSendType" BO_ 1848 1; +BA_ "GenMsgDelayTime" BO_ 1848 0; +BA_ "NetworkInitialization" BO_ 1848 0; +BA_ "VFrameFormat" BO_ 1848 14; +BA_ "FrameRouting" BO_ 1840 ""; +BA_ "GenMsgILSupport" BO_ 1840 0; +BA_ "DiagRequest" BO_ 1840 1; +BA_ "GenMsgSendType" BO_ 1840 1; +BA_ "GenMsgDelayTime" BO_ 1840 0; +BA_ "NetworkInitialization" BO_ 1840 0; +BA_ "VFrameFormat" BO_ 1840 14; +BA_ "FrameRouting" BO_ 1713 ""; +BA_ "GenMsgILSupport" BO_ 1713 0; +BA_ "TpApplType" BO_ 1713 "DiagUUDTResponse"; +BA_ "GenMsgSendType" BO_ 1713 1; +BA_ "NetworkInitialization" BO_ 1713 0; +BA_ "VFrameFormat" BO_ 1713 14; +BA_ "FrameRouting" BO_ 1712 ""; +BA_ "GenMsgILSupport" BO_ 1712 0; +BA_ "TpApplType" BO_ 1712 "DiagUUDTResponse"; +BA_ "GenMsgSendType" BO_ 1712 1; +BA_ "NetworkInitialization" BO_ 1712 0; +BA_ "VFrameFormat" BO_ 1712 14; +BA_ "FrameRouting" BO_ 2025 ""; +BA_ "GenMsgILSupport" BO_ 2025 0; +BA_ "DiagResponse" BO_ 2025 1; +BA_ "GenMsgSendType" BO_ 2025 1; +BA_ "GenMsgDelayTime" BO_ 2025 0; +BA_ "NetworkInitialization" BO_ 2025 0; +BA_ "VFrameFormat" BO_ 2025 14; +BA_ "FrameRouting" BO_ 2024 ""; +BA_ "GenMsgILSupport" BO_ 2024 0; +BA_ "DiagResponse" BO_ 2024 1; +BA_ "GenMsgSendType" BO_ 2024 1; +BA_ "GenMsgDelayTime" BO_ 2024 0; +BA_ "NetworkInitialization" BO_ 2024 0; +BA_ "VFrameFormat" BO_ 2024 14; +BA_ "FrameRouting" BO_ 2017 ""; +BA_ "GenMsgILSupport" BO_ 2017 0; +BA_ "DiagRequest" BO_ 2017 1; +BA_ "GenMsgSendType" BO_ 2017 1; +BA_ "GenMsgDelayTime" BO_ 2017 0; +BA_ "NetworkInitialization" BO_ 2017 0; +BA_ "VFrameFormat" BO_ 2017 14; +BA_ "FrameRouting" BO_ 2016 ""; +BA_ "GenMsgILSupport" BO_ 2016 0; +BA_ "DiagRequest" BO_ 2016 1; +BA_ "GenMsgSendType" BO_ 2016 1; +BA_ "GenMsgDelayTime" BO_ 2016 0; +BA_ "NetworkInitialization" BO_ 2016 0; +BA_ "VFrameFormat" BO_ 2016 14; +BA_ "FrameRouting" BO_ 2015 ""; +BA_ "GenMsgILSupport" BO_ 2015 0; +BA_ "DiagState" BO_ 2015 1; +BA_ "GenMsgSendType" BO_ 2015 1; +BA_ "GenMsgDelayTime" BO_ 2015 0; +BA_ "NetworkInitialization" BO_ 2015 0; +BA_ "VFrameFormat" BO_ 2015 14; +BA_ "FrameRouting" BO_ 1897 ""; +BA_ "GenMsgILSupport" BO_ 1897 0; +BA_ "DiagResponse" BO_ 1897 1; +BA_ "GenMsgSendType" BO_ 1897 1; +BA_ "GenMsgDelayTime" BO_ 1897 0; +BA_ "NetworkInitialization" BO_ 1897 0; +BA_ "VFrameFormat" BO_ 1897 14; +BA_ "FrameRouting" BO_ 1814 ""; +BA_ "GenMsgILSupport" BO_ 1814 0; +BA_ "DiagRequest" BO_ 1814 1; +BA_ "GenMsgSendType" BO_ 1814 1; +BA_ "GenMsgDelayTime" BO_ 1814 0; +BA_ "NetworkInitialization" BO_ 1814 0; +BA_ "VFrameFormat" BO_ 1814 14; +BA_ "FrameRouting" BO_ 1701 ""; +BA_ "GenMsgILSupport" BO_ 1701 0; +BA_ "TpApplType" BO_ 1701 "DiagUUDTResponse"; +BA_ "GenMsgSendType" BO_ 1701 1; +BA_ "NetworkInitialization" BO_ 1701 0; +BA_ "VFrameFormat" BO_ 1701 14; +BA_ "FrameRouting" BO_ 1700 ""; +BA_ "GenMsgILSupport" BO_ 1700 0; +BA_ "TpApplType" BO_ 1700 "DiagUUDTResponse"; +BA_ "GenMsgSendType" BO_ 1700 1; +BA_ "NetworkInitialization" BO_ 1700 0; +BA_ "VFrameFormat" BO_ 1700 14; +BA_ "FrameRouting" BO_ 1697 ""; +BA_ "GenMsgILSupport" BO_ 1697 0; +BA_ "TpApplType" BO_ 1697 "DiagUUDTResponse"; +BA_ "GenMsgSendType" BO_ 1697 1; +BA_ "NetworkInitialization" BO_ 1697 0; +BA_ "VFrameFormat" BO_ 1697 14; +BA_ "FrameRouting" BO_ 1696 ""; +BA_ "GenMsgILSupport" BO_ 1696 0; +BA_ "TpApplType" BO_ 1696 "DiagUUDTResponse"; +BA_ "GenMsgSendType" BO_ 1696 1; +BA_ "NetworkInitialization" BO_ 1696 0; +BA_ "VFrameFormat" BO_ 1696 14; +BA_ "FrameRouting" BO_ 1429 ""; +BA_ "GenMsgILSupport" BO_ 1429 0; +BA_ "NmAsrMessage" BO_ 1429 1; +BA_ "GenMsgSendType" BO_ 1429 0; +BA_ "GenMsgCycleTime" BO_ 1429 1000; +BA_ "NetworkInitialization" BO_ 1429 0; +BA_ "VFrameFormat" BO_ 1429 14; +BA_ "FrameRouting" BO_ 1100 ""; +BA_ "GenMsgSendType" BO_ 1100 0; +BA_ "GenMsgCycleTime" BO_ 1100 100; +BA_ "VFrameFormat" BO_ 1100 14; +BA_ "FrameRouting" BO_ 1098 ""; +BA_ "GenMsgSendType" BO_ 1098 5; +BA_ "GenMsgCycleTime" BO_ 1098 500; +BA_ "VFrameFormat" BO_ 1098 14; +BA_ "FrameRouting" BO_ 1086 ""; +BA_ "GenMsgSendType" BO_ 1086 0; +BA_ "GenMsgCycleTime" BO_ 1086 100; +BA_ "VFrameFormat" BO_ 1086 14; +BA_ "FrameRouting" BO_ 1071 ""; +BA_ "GenMsgSendType" BO_ 1071 0; +BA_ "GenMsgCycleTime" BO_ 1071 100; +BA_ "VFrameFormat" BO_ 1071 14; +BA_ "FrameRouting" BO_ 1069 ""; +BA_ "GenMsgSendType" BO_ 1069 0; +BA_ "GenMsgCycleTime" BO_ 1069 100; +BA_ "VFrameFormat" BO_ 1069 14; +BA_ "FrameRouting" BO_ 1060 ""; +BA_ "GenMsgSendType" BO_ 1060 0; +BA_ "GenMsgCycleTime" BO_ 1060 100; +BA_ "VFrameFormat" BO_ 1060 14; +BA_ "FrameRouting" BO_ 1057 ""; +BA_ "GenMsgSendType" BO_ 1057 0; +BA_ "GenMsgCycleTime" BO_ 1057 100; +BA_ "VFrameFormat" BO_ 1057 14; +BA_ "FrameRouting" BO_ 1055 ""; +BA_ "GenMsgSendType" BO_ 1055 0; +BA_ "GenMsgCycleTime" BO_ 1055 100; +BA_ "VFrameFormat" BO_ 1055 14; +BA_ "FrameRouting" BO_ 562 ""; +BA_ "GenMsgSendType" BO_ 562 0; +BA_ "GenMsgCycleTime" BO_ 562 100; +BA_ "VFrameFormat" BO_ 562 14; +BA_ "FrameRouting" BO_ 523 ""; +BA_ "GenMsgSendType" BO_ 523 0; +BA_ "GenMsgCycleTime" BO_ 523 1000; +BA_ "VFrameFormat" BO_ 523 14; +BA_ "FrameRouting" BO_ 517 ""; +BA_ "GenMsgSendType" BO_ 517 0; +BA_ "GenMsgCycleTime" BO_ 517 20; +BA_ "GenMsgDelayTime" BO_ 517 10; +BA_ "VFrameFormat" BO_ 517 14; +BA_ "FrameRouting" BO_ 516 ""; +BA_ "GenMsgSendType" BO_ 516 0; +BA_ "GenMsgCycleTime" BO_ 516 10; +BA_ "GenMsgDelayTime" BO_ 516 0; +BA_ "VFrameFormat" BO_ 516 14; +BA_ "FrameRouting" BO_ 514 ""; +BA_ "GenMsgSendType" BO_ 514 0; +BA_ "GenMsgCycleTime" BO_ 514 20; +BA_ "GenMsgDelayTime" BO_ 514 10; +BA_ "VFrameFormat" BO_ 514 14; +BA_ "FrameRouting" BO_ 512 ""; +BA_ "GenMsgSendType" BO_ 512 0; +BA_ "GenMsgCycleTime" BO_ 512 20; +BA_ "GenMsgDelayTime" BO_ 512 10; +BA_ "VFrameFormat" BO_ 512 14; +BA_ "FrameRouting" BO_ 381 ""; +BA_ "GenMsgSendType" BO_ 381 0; +BA_ "GenMsgCycleTime" BO_ 381 100; +BA_ "VFrameFormat" BO_ 381 14; +BA_ "FrameRouting" BO_ 380 ""; +BA_ "GenMsgSendType" BO_ 380 0; +BA_ "GenMsgCycleTime" BO_ 380 100; +BA_ "VFrameFormat" BO_ 380 14; +BA_ "FrameRouting" BO_ 377 ""; +BA_ "GenMsgSendType" BO_ 377 0; +BA_ "GenMsgCycleTime" BO_ 377 100; +BA_ "VFrameFormat" BO_ 377 14; +BA_ "FrameRouting" BO_ 376 ""; +BA_ "GenMsgSendType" BO_ 376 0; +BA_ "GenMsgCycleTime" BO_ 376 100; +BA_ "VFrameFormat" BO_ 376 14; +BA_ "FrameRouting" BO_ 373 ""; +BA_ "GenMsgSendType" BO_ 373 0; +BA_ "GenMsgCycleTime" BO_ 373 20; +BA_ "GenMsgDelayTime" BO_ 373 10; +BA_ "VFrameFormat" BO_ 373 14; +BA_ "FrameRouting" BO_ 359 ""; +BA_ "GenMsgSendType" BO_ 359 0; +BA_ "GenMsgCycleTime" BO_ 359 10; +BA_ "GenMsgDelayTime" BO_ 359 0; +BA_ "VFrameFormat" BO_ 359 14; +BA_ "FrameRouting" BO_ 358 ""; +BA_ "GenMsgSendType" BO_ 358 0; +BA_ "GenMsgCycleTime" BO_ 358 100; +BA_ "VFrameFormat" BO_ 358 14; +BA_ "FrameRouting" BO_ 357 ""; +BA_ "GenMsgSendType" BO_ 357 0; +BA_ "GenMsgCycleTime" BO_ 357 20; +BA_ "GenMsgDelayTime" BO_ 357 10; +BA_ "VFrameFormat" BO_ 357 14; +BA_ "FrameRouting" BO_ 355 ""; +BA_ "GenMsgSendType" BO_ 355 0; +BA_ "GenMsgCycleTime" BO_ 355 100; +BA_ "VFrameFormat" BO_ 355 14; +BA_ "FrameRouting" BO_ 342 ""; +BA_ "GenMsgSendType" BO_ 342 0; +BA_ "GenMsgCycleTime" BO_ 342 100; +BA_ "VFrameFormat" BO_ 342 14; +BA_ "FrameRouting" BO_ 71 ""; +BA_ "GenMsgSendType" BO_ 71 0; +BA_ "GenMsgCycleTime" BO_ 71 20; +BA_ "GenMsgDelayTime" BO_ 71 10; +BA_ "VFrameFormat" BO_ 71 14; +BA_ "FrameRouting" BO_ 1822 ""; +BA_ "GenMsgILSupport" BO_ 1822 0; +BA_ "DiagResponse" BO_ 1822 1; +BA_ "GenMsgSendType" BO_ 1822 1; +BA_ "GenMsgDelayTime" BO_ 1822 0; +BA_ "NetworkInitialization" BO_ 1822 0; +BA_ "VFrameFormat" BO_ 1822 14; +BA_ "FrameRouting" BO_ 1438 ""; +BA_ "GenMsgILSupport" BO_ 1438 0; +BA_ "NmAsrMessage" BO_ 1438 1; +BA_ "GenMsgSendType" BO_ 1438 0; +BA_ "GenMsgCycleTime" BO_ 1438 1000; +BA_ "NetworkInitialization" BO_ 1438 0; +BA_ "VFrameFormat" BO_ 1438 14; +BA_ "FrameRouting" BO_ 954 ""; +BA_ "FrameGatewayId" BO_ 954 954; +BA_ "FrameGatewayNetwork" BO_ 954 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 954 14; +BA_ "FrameRouting" BO_ 1006 ""; +BA_ "GenMsgSendType" BO_ 1006 5; +BA_ "GenMsgCycleTime" BO_ 1006 1000; +BA_ "VFrameFormat" BO_ 1006 14; +BA_ "FrameRouting" BO_ 820 ""; +BA_ "FrameGatewayNetwork" BO_ 820 "HS2_CAN"; +BA_ "FrameGatewayId" BO_ 820 820; +BA_ "VFrameFormat" BO_ 820 14; +BA_ "FrameRouting" BO_ 137 ""; +BA_ "FrameGatewayId" BO_ 137 137; +BA_ "FrameGatewayNetwork" BO_ 137 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 137 14; +BA_ "FrameRouting" BO_ 129 ""; +BA_ "FrameGatewayId" BO_ 129 129; +BA_ "FrameGatewayNetwork" BO_ 129 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 129 14; +BA_ "FrameRouting" BO_ 935 ""; +BA_ "GenMsgSendType" BO_ 935 5; +BA_ "GenMsgCycleTime" BO_ 935 200; +BA_ "VFrameFormat" BO_ 935 14; +BA_ "FrameRouting" BO_ 1108 ""; +BA_ "FrameGatewayId" BO_ 1108 1108; +BA_ "FrameGatewayNetwork" BO_ 1108 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 1108 14; +BA_ "FrameRouting" BO_ 261 ""; +BA_ "FrameGatewayId" BO_ 261 261; +BA_ "FrameGatewayNetwork" BO_ 261 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 261 14; +BA_ "FrameRouting" BO_ 1146 ""; +BA_ "FrameGatewayId" BO_ 1146 1146; +BA_ "FrameGatewayNetwork" BO_ 1146 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1146 14; +BA_ "FrameRouting" BO_ 533 ""; +BA_ "FrameGatewayId" BO_ 533 533; +BA_ "FrameGatewayNetwork" BO_ 533 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 533 14; +BA_ "FrameRouting" BO_ 1041 ""; +BA_ "FrameGatewayId" BO_ 1041 1041; +BA_ "FrameGatewayNetwork" BO_ 1041 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1041 14; +BA_ "FrameRouting" BO_ 1067 ""; +BA_ "FrameGatewayId" BO_ 1067 1067; +BA_ "FrameGatewayNetwork" BO_ 1067 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1067 14; +BA_ "FrameRouting" BO_ 1112 ""; +BA_ "FrameGatewayId" BO_ 1112 1112; +BA_ "FrameGatewayNetwork" BO_ 1112 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1112 14; +BA_ "FrameRouting" BO_ 139 ""; +BA_ "FrameGatewayId" BO_ 139 139; +BA_ "FrameGatewayNetwork" BO_ 139 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 139 14; +BA_ "FrameRouting" BO_ 1121 ""; +BA_ "FrameGatewayId" BO_ 1121 1121; +BA_ "FrameGatewayNetwork" BO_ 1121 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 1121 14; +BA_ "FrameRouting" BO_ 1120 ""; +BA_ "FrameGatewayId" BO_ 1120 1120; +BA_ "FrameGatewayNetwork" BO_ 1120 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 1120 14; +BA_ "FrameRouting" BO_ 1050 ""; +BA_ "FrameGatewayId" BO_ 1050 1050; +BA_ "FrameGatewayNetwork" BO_ 1050 "MS1_CAN"; +BA_ "VFrameFormat" BO_ 1050 14; +BA_ "FrameRouting" BO_ 1137 ""; +BA_ "GenMsgSendType" BO_ 1137 0; +BA_ "GenMsgCycleTime" BO_ 1137 1000; +BA_ "VFrameFormat" BO_ 1137 14; +BA_ "FrameRouting" BO_ 1255 ""; +BA_ "GenMsgSendType" BO_ 1255 0; +BA_ "GenMsgCycleTime" BO_ 1255 1000; +BA_ "VFrameFormat" BO_ 1255 14; +BA_ "FrameRouting" BO_ 1254 ""; +BA_ "GenMsgSendType" BO_ 1254 0; +BA_ "GenMsgCycleTime" BO_ 1254 1000; +BA_ "VFrameFormat" BO_ 1254 14; +BA_ "FrameRouting" BO_ 1253 ""; +BA_ "GenMsgSendType" BO_ 1253 0; +BA_ "GenMsgCycleTime" BO_ 1253 1000; +BA_ "VFrameFormat" BO_ 1253 14; +BA_ "FrameRouting" BO_ 1252 ""; +BA_ "GenMsgSendType" BO_ 1252 0; +BA_ "GenMsgCycleTime" BO_ 1252 1000; +BA_ "VFrameFormat" BO_ 1252 14; +BA_ "FrameRouting" BO_ 1251 ""; +BA_ "GenMsgSendType" BO_ 1251 0; +BA_ "GenMsgCycleTime" BO_ 1251 1000; +BA_ "VFrameFormat" BO_ 1251 14; +BA_ "FrameRouting" BO_ 1250 ""; +BA_ "GenMsgSendType" BO_ 1250 0; +BA_ "GenMsgCycleTime" BO_ 1250 1000; +BA_ "VFrameFormat" BO_ 1250 14; +BA_ "FrameRouting" BO_ 1249 ""; +BA_ "GenMsgSendType" BO_ 1249 0; +BA_ "GenMsgCycleTime" BO_ 1249 1000; +BA_ "VFrameFormat" BO_ 1249 14; +BA_ "FrameRouting" BO_ 1248 ""; +BA_ "GenMsgSendType" BO_ 1248 0; +BA_ "GenMsgCycleTime" BO_ 1248 1000; +BA_ "VFrameFormat" BO_ 1248 14; +BA_ "FrameRouting" BO_ 1113 ""; +BA_ "GenMsgSendType" BO_ 1113 0; +BA_ "GenMsgCycleTime" BO_ 1113 50; +BA_ "VFrameFormat" BO_ 1113 14; +BA_ "FrameRouting" BO_ 1105 ""; +BA_ "GenMsgSendType" BO_ 1105 5; +BA_ "GenMsgCycleTime" BO_ 1105 1000; +BA_ "VFrameFormat" BO_ 1105 14; +BA_ "FrameRouting" BO_ 938 ""; +BA_ "GenMsgSendType" BO_ 938 5; +BA_ "GenMsgCycleTime" BO_ 938 200; +BA_ "VFrameFormat" BO_ 938 14; +BA_ "FrameRouting" BO_ 939 ""; +BA_ "GenMsgSendType" BO_ 939 5; +BA_ "GenMsgCycleTime" BO_ 939 200; +BA_ "VFrameFormat" BO_ 939 14; +BA_ "FrameRouting" BO_ 937 ""; +BA_ "GenMsgSendType" BO_ 937 0; +BA_ "GenMsgCycleTime" BO_ 937 20; +BA_ "GenMsgDelayTime" BO_ 937 10; +BA_ "VFrameFormat" BO_ 937 14; +BA_ "FrameRouting" BO_ 936 ""; +BA_ "GenMsgSendType" BO_ 936 0; +BA_ "GenMsgCycleTime" BO_ 936 20; +BA_ "GenMsgDelayTime" BO_ 936 10; +BA_ "VFrameFormat" BO_ 936 14; +BA_ "FrameRouting" BO_ 877 ""; +BA_ "GenMsgSendType" BO_ 877 5; +BA_ "GenMsgCycleTime" BO_ 877 1000; +BA_ "VFrameFormat" BO_ 877 14; +BA_ "FrameRouting" BO_ 589 ""; +BA_ "FrameGatewayId" BO_ 589 589; +BA_ "FrameGatewayNetwork" BO_ 589 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 589 14; +BA_ "FrameRouting" BO_ 588 ""; +BA_ "FrameGatewayId" BO_ 588 588; +BA_ "FrameGatewayNetwork" BO_ 588 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 588 14; +BA_ "FrameRouting" BO_ 587 ""; +BA_ "FrameGatewayId" BO_ 587 587; +BA_ "FrameGatewayNetwork" BO_ 587 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 587 14; +BA_ "FrameRouting" BO_ 389 ""; +BA_ "GenMsgSendType" BO_ 389 0; +BA_ "GenMsgCycleTime" BO_ 389 100; +BA_ "VFrameFormat" BO_ 389 14; +BA_ "FrameRouting" BO_ 1009 ""; +BA_ "FrameGatewayId" BO_ 1009 1009; +BA_ "FrameGatewayNetwork" BO_ 1009 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1009 14; +BA_ "FrameRouting" BO_ 360 ""; +BA_ "FrameGatewayId" BO_ 360 360; +BA_ "FrameGatewayNetwork" BO_ 360 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 360 14; +BA_ "FrameRouting" BO_ 122 ""; +BA_ "FrameGatewayId" BO_ 122 122; +BA_ "FrameGatewayNetwork" BO_ 122 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 122 14; +BA_ "FrameRouting" BO_ 90 ""; +BA_ "FrameGatewayId" BO_ 90 90; +BA_ "FrameGatewayNetwork" BO_ 90 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 90 14; +BA_ "FrameRouting" BO_ 1091 ""; +BA_ "FrameGatewayId" BO_ 1091 1091; +BA_ "FrameGatewayNetwork" BO_ 1091 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1091 14; +BA_ "FrameRouting" BO_ 138 ""; +BA_ "FrameGatewayId" BO_ 138 138; +BA_ "FrameGatewayNetwork" BO_ 138 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 138 14; +BA_ "FrameRouting" BO_ 131 ""; +BA_ "FrameGatewayId" BO_ 131 131; +BA_ "FrameGatewayNetwork" BO_ 131 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 131 14; +BA_ "FrameRouting" BO_ 787 ""; +BA_ "FrameGatewayId" BO_ 787 787; +BA_ "FrameGatewayNetwork" BO_ 787 "MS2_CAN"; +BA_ "VFrameFormat" BO_ 787 14; +BA_ "FrameRouting" BO_ 953 ""; +BA_ "FrameGatewayId" BO_ 953 953; +BA_ "FrameGatewayNetwork" BO_ 953 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 953 14; +BA_ "FrameRouting" BO_ 1093 ""; +BA_ "FrameGatewayId" BO_ 1093 1093; +BA_ "FrameGatewayNetwork" BO_ 1093 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1093 14; +BA_ "FrameRouting" BO_ 792 ""; +BA_ "FrameGatewayId" BO_ 792 792; +BA_ "FrameGatewayNetwork" BO_ 792 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 792 14; +BA_ "FrameRouting" BO_ 968 ""; +BA_ "FrameGatewayId" BO_ 968 968; +BA_ "FrameGatewayNetwork" BO_ 968 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 968 14; +BA_ "FrameRouting" BO_ 819 ""; +BA_ "FrameGatewayId" BO_ 819 819; +BA_ "FrameGatewayNetwork" BO_ 819 "MS1_CAN"; +BA_ "VFrameFormat" BO_ 819 14; +BA_ "FrameRouting" BO_ 818 ""; +BA_ "FrameGatewayId" BO_ 818 818; +BA_ "FrameGatewayNetwork" BO_ 818 "MS1_CAN"; +BA_ "VFrameFormat" BO_ 818 14; +BA_ "FrameRouting" BO_ 806 ""; +BA_ "FrameGatewayId" BO_ 806 806; +BA_ "FrameGatewayNetwork" BO_ 806 "MS1_CAN"; +BA_ "VFrameFormat" BO_ 806 14; +BA_ "FrameRouting" BO_ 765 ""; +BA_ "FrameGatewayId" BO_ 765 765; +BA_ "FrameGatewayNetwork" BO_ 765 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 765 14; +BA_ "FrameRouting" BO_ 559 ""; +BA_ "FrameGatewayId" BO_ 559 559; +BA_ "FrameGatewayNetwork" BO_ 559 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 559 14; +BA_ "FrameRouting" BO_ 558 ""; +BA_ "FrameGatewayId" BO_ 558 558; +BA_ "FrameGatewayNetwork" BO_ 558 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 558 14; +BA_ "FrameRouting" BO_ 934 ""; +BA_ "GenMsgSendType" BO_ 934 5; +BA_ "GenMsgCycleTime" BO_ 934 200; +BA_ "VFrameFormat" BO_ 934 14; +BA_ "FrameRouting" BO_ 1072 ""; +BA_ "FrameGatewayId" BO_ 1072 1072; +BA_ "FrameGatewayNetwork" BO_ 1072 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1072 14; +BA_ "FrameRouting" BO_ 909 ""; +BA_ "FrameGatewayId" BO_ 909 909; +BA_ "FrameGatewayNetwork" BO_ 909 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 909 14; +BA_ "FrameRouting" BO_ 963 ""; +BA_ "FrameGatewayId" BO_ 963 963; +BA_ "FrameGatewayNetwork" BO_ 963 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 963 14; +BA_ "FrameRouting" BO_ 145 ""; +BA_ "FrameGatewayId" BO_ 145 145; +BA_ "FrameGatewayNetwork" BO_ 145 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 145 14; +BA_ "FrameRouting" BO_ 76 ""; +BA_ "FrameGatewayId" BO_ 76 76; +BA_ "FrameGatewayNetwork" BO_ 76 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 76 14; +BA_ "FrameRouting" BO_ 65 ""; +BA_ "DiagResponse" BO_ 65 0; +BA_ "FrameGatewayId" BO_ 65 65; +BA_ "FrameGatewayNetwork" BO_ 65 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 65 14; +BA_ "FrameRouting" BO_ 1076 ""; +BA_ "FrameGatewayId" BO_ 1076 1076; +BA_ "FrameGatewayNetwork" BO_ 1076 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 1076 14; +BA_ "FrameRouting" BO_ 862 ""; +BA_ "FrameGatewayId" BO_ 862 862; +BA_ "FrameGatewayNetwork" BO_ 862 "MS1_CAN"; +BA_ "VFrameFormat" BO_ 862 14; +BA_ "FrameRouting" BO_ 931 ""; +BA_ "FrameGatewayId" BO_ 931 931; +BA_ "FrameGatewayNetwork" BO_ 931 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 931 14; +BA_ "FrameRouting" BO_ 578 ""; +BA_ "FrameGatewayId" BO_ 578 578; +BA_ "FrameGatewayNetwork" BO_ 578 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 578 14; +BA_ "FrameRouting" BO_ 947 ""; +BA_ "FrameGatewayId" BO_ 947 947; +BA_ "FrameGatewayNetwork" BO_ 947 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 947 14; +BA_ "FrameRouting" BO_ 1084 ""; +BA_ "FrameGatewayId" BO_ 1084 1084; +BA_ "FrameGatewayNetwork" BO_ 1084 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1084 14; +BA_ "FrameRouting" BO_ 1068 ""; +BA_ "FrameGatewayId" BO_ 1068 1068; +BA_ "FrameGatewayNetwork" BO_ 1068 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 1068 14; +BA_ "FrameRouting" BO_ 146 ""; +BA_ "FrameGatewayId" BO_ 146 146; +BA_ "FrameGatewayNetwork" BO_ 146 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 146 14; +BA_ "FrameRouting" BO_ 1900 ""; +BA_ "GenMsgILSupport" BO_ 1900 0; +BA_ "DiagResponse" BO_ 1900 1; +BA_ "GenMsgSendType" BO_ 1900 1; +BA_ "GenMsgDelayTime" BO_ 1900 0; +BA_ "NetworkInitialization" BO_ 1900 0; +BA_ "VFrameFormat" BO_ 1900 14; +BA_ "FrameRouting" BO_ 1806 ""; +BA_ "GenMsgILSupport" BO_ 1806 0; +BA_ "DiagResponse" BO_ 1806 1; +BA_ "GenMsgSendType" BO_ 1806 1; +BA_ "GenMsgDelayTime" BO_ 1806 0; +BA_ "NetworkInitialization" BO_ 1806 0; +BA_ "VFrameFormat" BO_ 1806 14; +BA_ "FrameRouting" BO_ 997 ""; +BA_ "GenMsgSendType" BO_ 997 5; +BA_ "GenMsgCycleTime" BO_ 997 1000; +BA_ "VFrameFormat" BO_ 997 14; +BA_ "FrameRouting" BO_ 983 ""; +BA_ "GenMsgSendType" BO_ 983 0; +BA_ "GenMsgCycleTime" BO_ 983 50; +BA_ "VFrameFormat" BO_ 983 14; +BA_ "FrameRouting" BO_ 980 ""; +BA_ "GenMsgSendType" BO_ 980 0; +BA_ "GenMsgCycleTime" BO_ 980 30; +BA_ "GenMsgDelayTime" BO_ 980 10; +BA_ "VFrameFormat" BO_ 980 14; +BA_ "FrameRouting" BO_ 979 ""; +BA_ "GenMsgSendType" BO_ 979 0; +BA_ "GenMsgCycleTime" BO_ 979 50; +BA_ "VFrameFormat" BO_ 979 14; +BA_ "FrameRouting" BO_ 976 ""; +BA_ "GenMsgSendType" BO_ 976 0; +BA_ "GenMsgCycleTime" BO_ 976 100; +BA_ "VFrameFormat" BO_ 976 14; +BA_ "FrameRouting" BO_ 973 ""; +BA_ "GenMsgSendType" BO_ 973 5; +BA_ "GenMsgCycleTime" BO_ 973 1000; +BA_ "VFrameFormat" BO_ 973 14; +BA_ "FrameRouting" BO_ 970 ""; +BA_ "GenMsgSendType" BO_ 970 0; +BA_ "GenMsgCycleTime" BO_ 970 30; +BA_ "GenMsgDelayTime" BO_ 970 10; +BA_ "VFrameFormat" BO_ 970 14; +BA_ "FrameRouting" BO_ 962 ""; +BA_ "GenMsgSendType" BO_ 962 5; +BA_ "GenMsgCycleTime" BO_ 962 1000; +BA_ "VFrameFormat" BO_ 962 14; +BA_ "FrameRouting" BO_ 961 ""; +BA_ "GenMsgSendType" BO_ 961 5; +BA_ "GenMsgCycleTime" BO_ 961 1000; +BA_ "VFrameFormat" BO_ 961 14; +BA_ "FrameRouting" BO_ 394 ""; +BA_ "GenMsgSendType" BO_ 394 5; +BA_ "GenMsgCycleTime" BO_ 394 200; +BA_ "VFrameFormat" BO_ 394 14; +BA_ "FrameRouting" BO_ 391 ""; +BA_ "GenMsgSendType" BO_ 391 0; +BA_ "GenMsgCycleTime" BO_ 391 20; +BA_ "GenMsgDelayTime" BO_ 391 10; +BA_ "VFrameFormat" BO_ 391 14; +BA_ "FrameRouting" BO_ 390 ""; +BA_ "GenMsgSendType" BO_ 390 0; +BA_ "GenMsgCycleTime" BO_ 390 20; +BA_ "GenMsgDelayTime" BO_ 390 10; +BA_ "VFrameFormat" BO_ 390 14; +BA_ "FrameRouting" BO_ 1441 ""; +BA_ "GenMsgILSupport" BO_ 1441 0; +BA_ "NmAsrMessage" BO_ 1441 1; +BA_ "GenMsgSendType" BO_ 1441 0; +BA_ "GenMsgCycleTime" BO_ 1441 1000; +BA_ "NetworkInitialization" BO_ 1441 0; +BA_ "VFrameFormat" BO_ 1441 14; +BA_ "FrameRouting" BO_ 1787 ""; +BA_ "GenMsgILSupport" BO_ 1787 0; +BA_ "DiagResponse" BO_ 1787 1; +BA_ "GenMsgSendType" BO_ 1787 1; +BA_ "GenMsgDelayTime" BO_ 1787 0; +BA_ "VFrameFormat" BO_ 1787 14; +BA_ "FrameRouting" BO_ 1779 ""; +BA_ "GenMsgILSupport" BO_ 1779 0; +BA_ "DiagRequest" BO_ 1779 1; +BA_ "GenMsgSendType" BO_ 1779 1; +BA_ "GenMsgDelayTime" BO_ 1779 0; +BA_ "VFrameFormat" BO_ 1779 14; +BA_ "FrameRouting" BO_ 1786 ""; +BA_ "GenMsgILSupport" BO_ 1786 0; +BA_ "DiagResponse" BO_ 1786 1; +BA_ "GenMsgSendType" BO_ 1786 1; +BA_ "GenMsgDelayTime" BO_ 1786 0; +BA_ "VFrameFormat" BO_ 1786 14; +BA_ "FrameRouting" BO_ 1778 ""; +BA_ "GenMsgILSupport" BO_ 1778 0; +BA_ "DiagRequest" BO_ 1778 1; +BA_ "GenMsgSendType" BO_ 1778 1; +BA_ "GenMsgDelayTime" BO_ 1778 0; +BA_ "VFrameFormat" BO_ 1778 14; +BA_ "FrameRouting" BO_ 1153 ""; +BA_ "FrameGatewayId" BO_ 1153 1152; +BA_ "FrameGatewayNetwork" BO_ 1153 "HS2_CAN"; +BA_ "VFrameFormat" BO_ 1153 14; +BA_ "FrameRouting" BO_ 942 ""; +BA_ "GenMsgSendType" BO_ 942 5; +BA_ "GenMsgCycleTime" BO_ 942 1000; +BA_ "VFrameFormat" BO_ 942 14; +BA_ "FrameRouting" BO_ 930 ""; +BA_ "GenMsgSendType" BO_ 930 5; +BA_ "GenMsgCycleTime" BO_ 930 1000; +BA_ "VFrameFormat" BO_ 930 14; +BA_ "FrameRouting" BO_ 929 ""; +BA_ "GenMsgSendType" BO_ 929 5; +BA_ "GenMsgCycleTime" BO_ 929 1000; +BA_ "VFrameFormat" BO_ 929 14; +BA_ "FrameRouting" BO_ 402 ""; +BA_ "FrameGatewayId" BO_ 402 402; +BA_ "FrameGatewayNetwork" BO_ 402 "HS3_CAN"; +BA_ "VFrameFormat" BO_ 402 14; +BA_ "FrameRouting" BO_ 924 ""; +BA_ "FrameGatewayId" BO_ 924 924; +BA_ "FrameGatewayNetwork" BO_ 924 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 924 14; +BA_ "FrameRouting" BO_ 923 ""; +BA_ "FrameGatewayId" BO_ 923 923; +BA_ "FrameGatewayNetwork" BO_ 923 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 923 14; +BA_ "FrameRouting" BO_ 1998 ""; +BA_ "GenMsgILSupport" BO_ 1998 0; +BA_ "DiagResponse" BO_ 1998 1; +BA_ "GenMsgSendType" BO_ 1998 1; +BA_ "GenMsgDelayTime" BO_ 1998 0; +BA_ "NetworkInitialization" BO_ 1998 0; +BA_ "VFrameFormat" BO_ 1998 14; +BA_ "FrameRouting" BO_ 1996 ""; +BA_ "GenMsgILSupport" BO_ 1996 0; +BA_ "DiagResponse" BO_ 1996 1; +BA_ "GenMsgSendType" BO_ 1996 1; +BA_ "GenMsgDelayTime" BO_ 1996 0; +BA_ "NetworkInitialization" BO_ 1996 0; +BA_ "VFrameFormat" BO_ 1996 14; +BA_ "FrameRouting" BO_ 1988 ""; +BA_ "GenMsgILSupport" BO_ 1988 0; +BA_ "DiagRequest" BO_ 1988 1; +BA_ "GenMsgSendType" BO_ 1988 1; +BA_ "GenMsgDelayTime" BO_ 1988 0; +BA_ "NetworkInitialization" BO_ 1988 0; +BA_ "VFrameFormat" BO_ 1988 14; +BA_ "FrameRouting" BO_ 922 ""; +BA_ "FrameGatewayId" BO_ 922 922; +BA_ "FrameGatewayNetwork" BO_ 922 "HS1_CAN"; +BA_ "VFrameFormat" BO_ 922 14; +BA_ "GenSigSendType" SG_ 823 DteVehPwId_No_Actl 3; +BA_ "ECGUsedRxSignal" SG_ 823 DteVehPwId_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 823 DteVehEId_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 823 DteVehEffId_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 823 DteVeh_Pw_Actl 1; +BA_ "GenSigStartValue" SG_ 823 DteVeh_Eff_Actl 100; +BA_ "ECGUsedRxSignal" SG_ 823 DteVeh_Eff_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 823 DteVeh_E_Actl 1; +BA_ "GenSigSendType" SG_ 823 DteAcceptNew_B_Rq 3; +BA_ "ECGUsedRxSignal" SG_ 823 DteAcceptNew_B_Rq 1; +BA_ "GenSigSendType" SG_ 824 DteCldTrlrOn_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldTrlrOn_B_Stat 1; +BA_ "GenSigSendType" SG_ 824 DteCldTrlrOff_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldTrlrOff_B_Stat 1; +BA_ "GenSigStartValue" SG_ 824 DteCldTrip_L_Actl 100; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldTrip_L_Actl 1; +BA_ "GenSigSendType" SG_ 824 DteCldTraffic_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldTraffic_B_Stat 1; +BA_ "GenSigSendType" SG_ 824 DteCldTerrain_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldTerrain_B_Stat 1; +BA_ "GenSigSendType" SG_ 824 DteCldRoute_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldRoute_B_Stat 1; +BA_ "GenSigSendType" SG_ 824 DteCldPayload_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldPayload_B_Stat 1; +BA_ "GenSigSendType" SG_ 824 DteCldId_No_Actl 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldId_No_Actl 1; +BA_ "GenSigSendType" SG_ 824 DteCldExtTe_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldExtTe_B_Stat 1; +BA_ "GenSigStartValue" SG_ 824 DteCldExt_Eff_Actl 100; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldExt_Eff_Actl 1; +BA_ "GenSigStartValue" SG_ 824 DteCldDrv_Eff_Actl 100; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldDrv_Eff_Actl 1; +BA_ "GenSigSendType" SG_ 824 DteCldDcac_B_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldDcac_B_Stat 1; +BA_ "GenSigStartValue" SG_ 824 DteCldClimt_Eff_Actl 100; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldClimt_Eff_Actl 1; +BA_ "GenSigStartValue" SG_ 824 DteCldBattULo_Eff_Actl 100; +BA_ "ECGUsedTxSignal" SG_ 824 DteCldBattULo_Eff_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 949 Tire_Press_RR_ORR_Data 65533; +BA_ "GenSigStartValue" SG_ 949 Tire_Press_RR_ORR_Data 65533; +BA_ "GenSigStartValueInteger" SG_ 949 Tire_Press_LR_OLR_Data 65533; +BA_ "GenSigStartValue" SG_ 949 Tire_Press_LR_OLR_Data 65533; +BA_ "GenSigStartValueInteger" SG_ 949 Tire_Press_LF_Data 65533; +BA_ "GenSigStartValue" SG_ 949 Tire_Press_LF_Data 65533; +BA_ "GenSigStartValueInteger" SG_ 949 Tire_Press_RF_Data 65533; +BA_ "GenSigStartValue" SG_ 949 Tire_Press_RF_Data 65533; +BA_ "GenSigSendType" SG_ 1825 TesterPhysicalReqVDM 3; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cs 1; +BA_ "MetaData" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cs 1; +BA_ "ContentDependant" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 524 PrplWhlTot_Tq_RqMxAwd 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 524 PrplWhlTot_Tq_RqMxAwd 1; +BA_ "GenSigStartValue" SG_ 524 PrplWhlTot_Tq_RqMxAwd 65535; +BA_ "GenSigStartValueInteger" SG_ 524 PrplWhlTot_Tq_RqMxAwd 65535; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cnt 1; +BA_ "MetaData" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cnt 1; +BA_ "ContentDependant" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 524 PrplWhlTotTqRqMxAwd_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 740 BattAuxCnnct_B_Cmd 1; +BA_ "GenSigSendType" SG_ 1160 DgtlCommPncReset_B_Req 3; +BA_ "ECGUsedTxSignal" SG_ 1160 DgtlCommPncReset_B_Req 1; +BA_ "ECGUsedTxSignal" SG_ 1160 DataMntrSustn_B_Rq 1; +BA_ "GenSigSendType" SG_ 1160 DataMntrSustn_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 1160 PwSustnRdata_B_RqTelem 1; +BA_ "GenSigSendType" SG_ 1160 PwSustnRdata_B_RqTelem 3; +BA_ "ECGUsedTxSignal" SG_ 776 ScMnSoc_Pc_RqCld 1; +BA_ "GenSigStartValue" SG_ 776 ScMnSoc_Pc_RqCld 100; +BA_ "GenSigSendType" SG_ 776 ScMnSoc_Pc_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 ScChrgrPwMax_Pw_RqCld 1; +BA_ "GenSigSendType" SG_ 776 ScChrgrPwMax_Pw_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 ScLocPwId_No_RqCld 1; +BA_ "GenSigSendType" SG_ 776 ScLocPwId_No_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 PrcondEdit_D_RqCld 1; +BA_ "GenSigSendType" SG_ 776 PrcondEdit_D_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 GoTEditMnte_T_RqCld 1; +BA_ "GenSigStartValue" SG_ 776 GoTEditMnte_T_RqCld 14; +BA_ "GenSigSendType" SG_ 776 GoTEditMnte_T_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 GoTEditHr_T_RqCld 1; +BA_ "GenSigStartValue" SG_ 776 GoTEditHr_T_RqCld 30; +BA_ "GenSigSendType" SG_ 776 GoTEditHr_T_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 ChrgToPcEdit_Pc_RqCld 1; +BA_ "GenSigStartValue" SG_ 776 ChrgToPcEdit_Pc_RqCld 126; +BA_ "GenSigSendType" SG_ 776 ChrgToPcEdit_Pc_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 AirAmb_Te_ActlCld 1; +BA_ "GenSigStartValueInteger" SG_ 776 AirAmb_Te_ActlCld 512; +BA_ "UsedOnPgmDBC" SG_ 776 AirAmb_Te_ActlCld 1; +BA_ "GenSigSendType" SG_ 776 AirAmb_Te_ActlCld 3; +BA_ "ECGUsedTxSignal" SG_ 776 ScFreshDataEnbl_B_Rq 1; +BA_ "GenSigSendType" SG_ 776 ScFreshDataEnbl_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 776 ScEnbl_D_RqCld 1; +BA_ "GenSigStartValue" SG_ 776 ScEnbl_D_RqCld 1; +BA_ "GenSigSendType" SG_ 776 ScEnbl_D_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScDayOfWeekId_D_RqCld 1; +BA_ "GenSigStartValue" SG_ 775 ScDayOfWeekId_D_RqCld 1; +BA_ "GenSigSendType" SG_ 775 ScDayOfWeekId_D_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScLocSetId_No_RqCld 1; +BA_ "GenSigSendType" SG_ 775 ScLocSetId_No_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScLocRdius_L_RqCld 1; +BA_ "GenSigStartValue" SG_ 775 ScLocRdius_L_RqCld 1; +BA_ "GenSigSendType" SG_ 775 ScLocRdius_L_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScChrgToPc_Pc_RqCld 1; +BA_ "GenSigStartValue" SG_ 775 ScChrgToPc_Pc_RqCld 100; +BA_ "GenSigSendType" SG_ 775 ScChrgToPc_Pc_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScChrgPrfl_No_RqCld 1; +BA_ "GenSigSendType" SG_ 775 ScChrgPrfl_No_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScChrgDurSet_D_RqCld 1; +BA_ "GenSigStartValue" SG_ 775 ScChrgDurSet_D_RqCld 1; +BA_ "GenSigSendType" SG_ 775 ScChrgDurSet_D_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 775 ScChrgDur_T_RqCld 1; +BA_ "GenSigSendType" SG_ 775 ScChrgDur_T_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocLongPostv_B_RqCld 1; +BA_ "GenSigSendType" SG_ 774 ScLocLongPostv_B_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocLongFrct_An_RqCld 1; +BA_ "GenSigStartValue" SG_ 774 ScLocLongFrct_An_RqCld 1048575; +BA_ "GenSigSendType" SG_ 774 ScLocLongFrct_An_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocLongDeg_An_RqCld 1; +BA_ "GenSigSendType" SG_ 774 ScLocLongDeg_An_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocLattPostv_B_RqCld 1; +BA_ "GenSigSendType" SG_ 774 ScLocLattPostv_B_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocLattFrct_An_RqCld 1; +BA_ "GenSigStartValue" SG_ 774 ScLocLattFrct_An_RqCld 1048575; +BA_ "GenSigSendType" SG_ 774 ScLocLattFrct_An_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocLattDeg_An_RqCld 1; +BA_ "GenSigSendType" SG_ 774 ScLocLattDeg_An_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocId_No_RqCld 1; +BA_ "GenSigSendType" SG_ 774 ScLocId_No_RqCld 3; +BA_ "ECGUsedTxSignal" SG_ 774 ScLocDelete_B_RqCld 1; +BA_ "GenSigSendType" SG_ 774 ScLocDelete_B_RqCld 3; +BA_ "GenSigStartValue" SG_ 811 DistToStopover_L_Actl 65535; +BA_ "WakeupSignal" SG_ 811 ExtLghtRight_D_RqMnu 1; +BA_ "WakeupSignal" SG_ 811 AutoLghtOvrrd_B_RqDrv 1; +BA_ "WakeupSignal" SG_ 811 ExtLghtRear_D_RqMnu 1; +BA_ "WakeupSignal" SG_ 811 ExtLghtLeft_D_RqMnu 1; +BA_ "WakeupSignal" SG_ 811 ExtLghtFront_D_RqMnu 1; +BA_ "GenSigStartValue" SG_ 811 GoTEditMnte_T_RqMnu 14; +BA_ "GenSigStartValue" SG_ 811 GoTEditHr_T_RqMnu 30; +BA_ "U_CX727_MY2021_Tx" SG_ 850 VehElRngeNut_L_Dsply 1; +BA_ "U_CX727_MY2021_Tx" SG_ 850 NxtUsgSocEst_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 850 EstmChrgTimeLP_St 1; +BA_ "U_CX727_MY2021_Tx" SG_ 850 EstmChrgTimeLP_St 1; +BA_ "ECGUsedRxSignal" SG_ 850 EstmChrgTimeHP_St 1; +BA_ "U_CX727_MY2021_Tx" SG_ 850 EstmChrgTimeHP_St 1; +BA_ "ECGUsedRxSignal" SG_ 850 ChargeNowDuration_St 1; +BA_ "U_CX727_MY2021_Tx" SG_ 850 ChargeNowDuration_St 1; +BA_ "ECGUsedTxSignal" SG_ 563 DrvBhavWarn_B_Rq 1; +BA_ "GenSigSendType" SG_ 563 DrvBhavWarn_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 563 OfbChrgSetSync_D_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 563 KeyOffPwMde_D_Stat 1; +BA_ "GenSigSendType" SG_ 563 KeyOffPwMde_D_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 563 ModemReset_D_Stat 1; +BA_ "GenSigSendType" SG_ 563 ModemReset_D_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 563 FactoryReset_St 1; +BA_ "GenSigSendType" SG_ 563 FactoryReset_St 3; +BA_ "GenSigSendType" SG_ 1833 TesterPhysicalResVDM 3; +BA_ "GenSigStartValueInteger" SG_ 570 SuspRearRight_L_Actl 511; +BA_ "GenSigStartValue" SG_ 570 SuspRearRight_L_Actl 511; +BA_ "U_CX727_MY2021_Rx" SG_ 570 SuspRearRight_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 570 SuspFrntRight_L_Actl 511; +BA_ "GenSigStartValue" SG_ 570 SuspFrntRight_L_Actl 511; +BA_ "U_CX727_MY2021_Rx" SG_ 570 SuspFrntRight_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 570 SuspRear_L_Prev 511; +BA_ "GenSigStartValue" SG_ 570 SuspRear_L_Prev 511; +BA_ "U_CX727_MY2021_Rx" SG_ 570 SuspRear_L_Prev 1; +BA_ "U_P702_MY2021_Rx" SG_ 570 SuspRear_L_Prev 1; +BA_ "GenSigStartValueInteger" SG_ 570 SuspRear_L_Actl 511; +BA_ "GenSigStartValue" SG_ 570 SuspRear_L_Actl 511; +BA_ "U_CX727_MY2021_Rx" SG_ 570 SuspRear_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 570 SuspRear_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 570 SuspFrnt_L_Prev 511; +BA_ "GenSigStartValue" SG_ 570 SuspFrnt_L_Prev 511; +BA_ "U_CX727_MY2021_Rx" SG_ 570 SuspFrnt_L_Prev 1; +BA_ "U_P702_MY2021_Rx" SG_ 570 SuspFrnt_L_Prev 1; +BA_ "GenSigStartValueInteger" SG_ 570 SuspFrnt_L_Actl 511; +BA_ "GenSigStartValue" SG_ 570 SuspFrnt_L_Actl 511; +BA_ "U_CX727_MY2021_Rx" SG_ 570 SuspFrnt_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 570 SuspFrnt_L_Actl 1; +BA_ "GenSigSendType" SG_ 837 Ccd_B_Falt 3; +BA_ "GenSigInactiveValue" SG_ 837 Ccd_B_Falt 0; +BA_ "GenSigSendType" SG_ 837 SelDrvMdeSusp_D_Stat 3; +BA_ "GenSigInactiveValue" SG_ 837 SelDrvMdeSusp_D_Stat 0; +BA_ "U_CX727_MY2021_Rx" SG_ 837 SelDrvMdeSusp_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 837 SelDrvMdeSusp_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 837 SelDrvMdeSusp_D_Stat 1; +BA_ "GenSigSendType" SG_ 837 AdptDrvMdePt_D_Rq 3; +BA_ "GenSigInactiveValue" SG_ 837 AdptDrvMdePt_D_Rq 0; +BA_ "U_CX727_MY2021_Rx" SG_ 837 AdptDrvMdePt_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 837 AdptDrvMdePt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 837 AdptDrvMdePt_D_Rq 1; +BA_ "GenSigSendType" SG_ 837 AdptDrvMdeChassis_D_Rq 3; +BA_ "GenSigInactiveValue" SG_ 837 AdptDrvMdeChassis_D_Rq 0; +BA_ "U_CX727_MY2021_Rx" SG_ 837 AdptDrvMdeChassis_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 837 AdptDrvMdeChassis_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 837 AdptDrvMdeChassis_D_Rq 1; +BA_ "GenSigSendType" SG_ 837 CcdMsgTxt_D_RqDsply 3; +BA_ "GenSigInactiveValue" SG_ 837 CcdMsgTxt_D_RqDsply 0; +BA_ "UsedOnPgmDBC" SG_ 837 CcdMsgTxt_D_RqDsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 837 CcdMsgTxt_D_RqDsply 1; +BA_ "ECGUsedTxSignal" SG_ 885 BattULoChrg_D_RqOta 1; +BA_ "ECGUsedTxSignal" SG_ 885 VehStrtInhbt_T_Dsply 1; +BA_ "ECGUsedTxSignal" SG_ 885 VehStrtInhbt_D_Dsply 1; +BA_ "ECGUsedTxSignal" SG_ 885 VehOnRqstr_D_Stat 1; +BA_ "ECGUsedTxSignal" SG_ 885 VehStrtInhbt_D_RqCld 1; +BA_ "ECGUsedTxSignal" SG_ 885 VehOn_D_RqCld 1; +BA_ "ECGUsedTxSignal" SG_ 885 CanMsg375_No_Cnt 1; +BA_ "ECGUsedTxSignal" SG_ 885 CanMsg375_No_Crc 1; +BA_ "ECGUsedTxSignal" SG_ 885 OtaActv_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1150 LocationServices_1 1; +BA_ "GenSigSendType" SG_ 2612224016 PARSEDPushPCMtoGWM_ECG 3; +BA_ "U_P702_MY2021_Tx" SG_ 2612224016 PARSEDPushPCMtoGWM_ECG 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 2612224016 PARSEDPushPCMtoGWM_ECG 1; +BA_ "ECGUsedRxSignal" SG_ 2612224016 PARSEDPushPCMtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 810 OBCCSerial_D_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 810 OBCCSerial_D_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 810 TlghtTest_D_RqArb 1; +BA_ "GenSigSendType" SG_ 810 TlghtTest_D_RqArb 3; +BA_ "ECGUsedTxSignal" SG_ 810 ChrgrPncSustn_B_Rq 1; +BA_ "GenSigStartValue" SG_ 810 ChrgrPncSustn_B_Rq 0; +BA_ "GenSigStartValueInteger" SG_ 810 ChrgrPncSustn_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 810 NtfyDrvTrgtDist_L_Rq 1; +BA_ "GenSigStartValue" SG_ 810 NtfyDrvTrgtDist_L_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 810 NtfyDrvTrgtDist_L_Rq 1; +BA_ "WakeupSignal" SG_ 810 NtfyDrvTrgtDist_L_Rq 1; +BA_ "GenSigSendType" SG_ 810 NtfyDrvTrgtDist_L_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 810 NtfyDrvSocLvl1_Pc_Rq 1; +BA_ "GenSigStartValue" SG_ 810 NtfyDrvSocLvl1_Pc_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 810 NtfyDrvSocLvl1_Pc_Rq 1; +BA_ "WakeupSignal" SG_ 810 NtfyDrvSocLvl1_Pc_Rq 1; +BA_ "GenSigSendType" SG_ 810 NtfyDrvSocLvl1_Pc_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 810 PtRmtRprt_D_Stat 1; +BA_ "WakeupSignal" SG_ 810 PtRmtRprt_D_Stat 1; +BA_ "GenSigSendType" SG_ 810 PtRmtRprt_D_Stat 3; +BA_ "ECGUsedTxSignal" SG_ 810 ChrgrPncEnbl_D_Rq 1; +BA_ "GenSigStartValue" SG_ 810 ChrgrPncEnbl_D_Rq 3; +BA_ "GenSigStartValueInteger" SG_ 810 ChrgrPncEnbl_D_Rq 3; +BA_ "GenSigSendType" SG_ 810 ChrgrPncEnbl_D_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 810 ExtLghtDsply_B_StatArb 1; +BA_ "WakeupSignal" SG_ 810 ExtLghtDsply_B_StatArb 1; +BA_ "GenSigSendType" SG_ 810 ExtLghtDsply_B_StatArb 3; +BA_ "ECGUsedTxSignal" SG_ 810 ExtLghtRight_D_RqOta 1; +BA_ "WakeupSignal" SG_ 810 ExtLghtRight_D_RqOta 1; +BA_ "GenSigSendType" SG_ 810 ExtLghtRight_D_RqOta 3; +BA_ "ECGUsedTxSignal" SG_ 810 ExtLghtRear_D_RqOta 1; +BA_ "WakeupSignal" SG_ 810 ExtLghtRear_D_RqOta 1; +BA_ "GenSigSendType" SG_ 810 ExtLghtRear_D_RqOta 3; +BA_ "ECGUsedTxSignal" SG_ 810 ExtLghtLeft_D_RqOta 1; +BA_ "WakeupSignal" SG_ 810 ExtLghtLeft_D_RqOta 1; +BA_ "GenSigSendType" SG_ 810 ExtLghtLeft_D_RqOta 3; +BA_ "ECGUsedTxSignal" SG_ 810 ExtLghtFront_D_RqOta 1; +BA_ "WakeupSignal" SG_ 810 ExtLghtFront_D_RqOta 1; +BA_ "GenSigSendType" SG_ 810 ExtLghtFront_D_RqOta 3; +BA_ "ECGUsedTxSignal" SG_ 550 PtWakeupActv1_B_Rq 1; +BA_ "WakeupSignal" SG_ 550 PtWakeupActv1_B_Rq 1; +BA_ "GenSigSendType" SG_ 550 PtWakeupActv1_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgPrflUpdate_B_Rq 1; +BA_ "GenSigSendType" SG_ 639 OfbChrgPrflUpdate_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgClearAll_B_Rq 1; +BA_ "GenSigSendType" SG_ 639 OfbChrgClearAll_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTTouch_D_Rq 1; +BA_ "GenSigSendType" SG_ 639 OfbChrgGoTTouch_D_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTPrcond_D_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTOn_D_Rq 1; +BA_ "GenSigStartValue" SG_ 639 OfbChrgGoTOn_D_Rq 2; +BA_ "GenSigStartValueInteger" SG_ 639 OfbChrgGoTOn_D_Rq 2; +BA_ "GenSigSendType" SG_ 639 OfbChrgGoTOn_D_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTMnte_D_Rq 1; +BA_ "MetaData" SG_ 639 OfbChrgGoTMnte_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 639 OfbChrgGoTMnte_D_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTHr_T_Rq 1; +BA_ "GenSigStartValue" SG_ 639 OfbChrgGoTHr_T_Rq 30; +BA_ "GenSigStartValueInteger" SG_ 639 OfbChrgGoTHr_T_Rq 30; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTExtHtr_D_Rq 1; +BA_ "GenSigSendType" SG_ 639 OfbChrgGoTExtHtr_D_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTElement_D_Rq 1; +BA_ "MetaData" SG_ 639 OfbChrgGoTElement_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 639 OfbChrgGoTElement_D_Rq 1; +BA_ "GenSigSendType" SG_ 639 OfbChrgGoTElement_D_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTDelete_B_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 639 OfbChrgGoTUpdate_B_Rq 1; +BA_ "GenSigSendType" SG_ 639 OfbChrgGoTUpdate_B_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgLocIdTrgt_No_Rq 1; +BA_ "MetaData" SG_ 530 OfbChrgLocIdTrgt_No_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 530 OfbChrgLocIdTrgt_No_Rq 1; +BA_ "GenSigSendType" SG_ 530 OfbChrgLocIdTrgt_No_Rq 3; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgToPcWknd_D_Actl 1; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgToPcWkdy_D_Actl 1; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgSetNow_D_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgSetDelete_B_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgPrflWknd_No_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgPrflWkdy_No_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 530 OfbChrgLocIdUns_B_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 1142 ConsTipV_No_Dsply 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1142 ConsTipV_No_Dsply 1; +BA_ "WakeupSignal" SG_ 817 DrTgateOpen_B_Rq 1; +BA_ "WakeupSignal" SG_ 817 DrTgateExtSwMde_B_Stat 1; +BA_ "WakeupSignal" SG_ 817 Remote_Device_Feedback 1; +BA_ "WakeupSignal" SG_ 817 Veh_Lock_Requestor 1; +BA_ "WakeupSignal" SG_ 817 R_Pwr_Sliding_Dr_Rqst 1; +BA_ "WakeupSignal" SG_ 817 Power_Liftgate_Rqst 1; +BA_ "WakeupSignal" SG_ 817 Veh_Lock_EvNum 1; +BA_ "WakeupSignal" SG_ 817 Power_Decklid_Rqst 1; +BA_ "WakeupSignal" SG_ 817 L_Pwr_Sliding_Dr_Rqst 1; +BA_ "WakeupSignal" SG_ 817 Keyfob_Pad_Msg_Count 1; +BA_ "WakeupSignal" SG_ 817 Veh_Lock_Status 1; +BA_ "GenSigStartValueInteger" SG_ 817 Veh_Lock_Status 1; +BA_ "GenSigStartValue" SG_ 817 Veh_Lock_Status 1; +BA_ "WakeupSignal" SG_ 817 ChildLck_D_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 817 ChildLck_D_Dsply 1; +BA_ "GenSigStartValue" SG_ 817 ChildLck_D_Dsply 1; +BA_ "WakeupSignal" SG_ 817 Lockmsgtxt_D_Rq 1; +BA_ "WakeupSignal" SG_ 817 LockInhibit 1; +BA_ "GenSigSendType" SG_ 878 DcacGfciTest_B_Rq 3; +BA_ "GenSigStartValue" SG_ 878 DcacOut_Pw_DsplyMx 0; +BA_ "GenSigStartValue" SG_ 878 DcacOut1_Pw_Dsply 0; +BA_ "GenSigStartValue" SG_ 878 DcacOut2_Pw_Dsply 0; +BA_ "GenSigSendType" SG_ 878 DcacHw_D_Confg 3; +BA_ "UsedOnPgmDBC" SG_ 878 DcacHw_D_Confg 1; +BA_ "GenSigStartValueInteger" SG_ 878 DcacHw_D_Confg 1; +BA_ "GenSigStartValue" SG_ 878 DcacHw_D_Confg 1; +BA_ "GenSigSendType" SG_ 878 DcacFaltMsgTxt_D_Rq 3; +BA_ "UsedOnPgmDBC" SG_ 878 DcacFaltMsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 878 DcacFaltMsgTxt_D_Rq 1; +BA_ "GenSigStartValue" SG_ 878 DcacFaltMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 878 DcacLoFuelMsgTxt_D_Rq 3; +BA_ "GenSigSendType" SG_ 878 DcacEngOnMsgTxt_D_Rq 3; +BA_ "GenSigSendType" SG_ 878 DcacElPw_D_Stat 3; +BA_ "UsedOnPgmDBC" SG_ 878 DcacElPw_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 878 DcacElPw_D_Stat 1; +BA_ "GenSigStartValue" SG_ 878 DcacElPw_D_Stat 1; +BA_ "GenSigSendType" SG_ 878 PwBedPnlEnbl_B_Rq 3; +BA_ "GenSigSendType" SG_ 878 DcacOn_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 878 DcacOn_B_Rq 1; +BA_ "GenSigSendType" SG_ 878 DcacSys_B_Falt 3; +BA_ "U_P702_MY2021_Tx" SG_ 878 DcacSys_B_Falt 1; +BA_ "GenSigSendType" SG_ 878 DcacLedCtl_D_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 878 DcacLedCtl_D_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 2611055832 PARSEDPhysGWM_ECGtoSODR 1; +BA_ "GenSigSendType" SG_ 2611055832 PARSEDPhysGWM_ECGtoSODR 3; +BA_ "ECGUsedTxSignal" SG_ 2611054808 PARSEDPhysGWM_ECGtoSODL 1; +BA_ "GenSigSendType" SG_ 2611054808 PARSEDPhysGWM_ECGtoSODL 3; +BA_ "ECGUsedTxSignal" SG_ 2611026136 PARSEDPhysGWM_ECGtoSODCMD 1; +BA_ "GenSigSendType" SG_ 2611026136 PARSEDPhysGWM_ECGtoSODCMD 3; +BA_ "ECGUsedTxSignal" SG_ 2611025112 PARSEDPhysGWM_ECGtoSODCMC 1; +BA_ "GenSigSendType" SG_ 2611025112 PARSEDPhysGWM_ECGtoSODCMC 3; +BA_ "ECGUsedTxSignal" SG_ 2610975960 PARSEDPhysGWM_ECGtoCCM 1; +BA_ "GenSigSendType" SG_ 2610975960 PARSEDPhysGWM_ECGtoCCM 3; +BA_ "ECGUsedTxSignal" SG_ 2610007256 OTAPhysGWM_ECGtoSODR 1; +BA_ "GenSigSendType" SG_ 2610007256 OTAPhysGWM_ECGtoSODR 3; +BA_ "ECGUsedTxSignal" SG_ 2610006232 OTAPhysGWM_ECGtoSODL 1; +BA_ "GenSigSendType" SG_ 2610006232 OTAPhysGWM_ECGtoSODL 3; +BA_ "ECGUsedTxSignal" SG_ 2609977560 OTAPhysGWM_ECGtoSODCMD 1; +BA_ "GenSigSendType" SG_ 2609977560 OTAPhysGWM_ECGtoSODCMD 3; +BA_ "ECGUsedTxSignal" SG_ 2609976536 OTAPhysGWM_ECGtoSODCMC 1; +BA_ "GenSigSendType" SG_ 2609976536 OTAPhysGWM_ECGtoSODCMC 3; +BA_ "ECGUsedTxSignal" SG_ 2609927384 OTAPhysGWM_ECGtoCCM 1; +BA_ "GenSigSendType" SG_ 2609927384 OTAPhysGWM_ECGtoCCM 3; +BA_ "ECGUsedRxSignal" SG_ 2611175523 PARSEDPhysSODRtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175523 PARSEDPhysSODRtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224099 PARSEDPhysSODR2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224099 PARSEDPhysSODR2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2611175522 PARSEDPhysSODLtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175522 PARSEDPhysSODLtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224098 PARSEDPhysSODL2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224098 PARSEDPhysSODL2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2611175494 PARSEDPhysSODCMDtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175494 PARSEDPhysSODCMDtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224070 PARSEDPhysSODCMD2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224070 PARSEDPhysSODCMD2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2611175493 PARSEDPhysSODCMCtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175493 PARSEDPhysSODCMCtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224069 PARSEDPhysSODCMC2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224069 PARSEDPhysSODCMC2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2611175445 PARSEDPhysCCMtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175445 PARSEDPhysCCMtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224021 PARSEDPhysCCM2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224021 PARSEDPhysCCM2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126947 OTAPhysSODRtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126947 OTAPhysSODRtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126946 OTAPhysSODLtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126946 OTAPhysSODLtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126918 OTAPhysSODCMDtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126918 OTAPhysSODCMDtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126917 OTAPhysSODCMCtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126917 OTAPhysSODCMCtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126869 OTAPhysCCMtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126869 OTAPhysCCMtoGWM_ECG 3; +BA_ "CrossOver_InfoCAN" SG_ 984 FeatConfigIpmaActl 1; +BA_ "CrossOver_InfoCAN" SG_ 984 FeatNoIpmaActl 1; +BA_ "GenSigStartValue" SG_ 984 PersIndexIpma_D_Actl 4; +BA_ "GenSigStartValueInteger" SG_ 984 PersIndexIpma_D_Actl 4; +BA_ "CrossOver_InfoCAN" SG_ 984 PersIndexIpma_D_Actl 1; +BA_ "GenSigSendType" SG_ 984 PersIndexIpma_D_Actl 3; +BA_ "U_P702_MY2021_Rx" SG_ 984 AhbcRampingV_D_Rq 1; +BA_ "GenSigSendType" SG_ 984 AhbcRampingV_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 984 LaActvStats_D_Dsply 1; +BA_ "GenSigSendType" SG_ 984 LaActvStats_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 984 LaDenyStats_B_Dsply 1; +BA_ "GenSigSendType" SG_ 984 LaDenyStats_B_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 984 LaHandsOff_D_Dsply 1; +BA_ "GenSigSendType" SG_ 984 LaHandsOff_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 984 CamraDefog_B_Req 1; +BA_ "GenSigSendType" SG_ 984 CamraDefog_B_Req 3; +BA_ "CrossOver_InfoCAN" SG_ 984 CamraStats_D_Dsply 1; +BA_ "GenSigSendType" SG_ 984 CamraStats_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 984 DasAlrtLvl_D_Dsply 1; +BA_ "GenSigSendType" SG_ 984 DasAlrtLvl_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 984 DasStats_D_Dsply 1; +BA_ "GenSigSendType" SG_ 984 DasStats_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 984 DasWarn_D_Dsply 1; +BA_ "GenSigSendType" SG_ 984 DasWarn_D_Dsply 3; +BA_ "GenSigSendType" SG_ 984 AhbHiBeam_D_Rq 3; +BA_ "GenSigSendType" SG_ 985 LdwChime_B_Rq 3; +BA_ "GenSigSendType" SG_ 985 TsrRegionTxt_D_Stat 3; +BA_ "GenSigSendType" SG_ 985 SblmPedCrossScnr_B_Stat 3; +BA_ "GenSigSendType" SG_ 985 LongCtrlEnbl_D_Rq 3; +BA_ "GenSigSendType" SG_ 985 SblmRndAbtScnr_B_Stat 3; +BA_ "GenSigSendType" SG_ 985 DasAlrtInfo_D_Dsply 3; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 985 IaccVLim_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 985 IaccVLim_D_Rq 1; +BA_ "GenSigStartValue" SG_ 985 IaccVLim_D_Rq 254; +BA_ "GenSigStartValueInteger" SG_ 985 IaccVLim_D_Rq 254; +BA_ "GenSigSendType" SG_ 985 IaccVLim_D_Rq 3; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 985 IaccVLimUnit_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 985 IaccVLimUnit_D_Rq 1; +BA_ "GenSigStartValue" SG_ 985 IaccVLimUnit_D_Rq 3; +BA_ "GenSigStartValueInteger" SG_ 985 IaccVLimUnit_D_Rq 3; +BA_ "GenSigSendType" SG_ 985 IaccVLimUnit_D_Rq 3; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 985 IsaVLim_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 985 IsaVLim_D_Rq 1; +BA_ "GenSigStartValue" SG_ 985 IsaVLim_D_Rq 254; +BA_ "GenSigStartValueInteger" SG_ 985 IsaVLim_D_Rq 254; +BA_ "GenSigSendType" SG_ 985 IsaVLim_D_Rq 3; +BA_ "GenSigSendType" SG_ 985 SblmStopScnr_B_Stat 3; +BA_ "GenSigSendType" SG_ 985 SblmYieldScnr_B_Stat 3; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 985 IsaVLimUnit_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 985 IsaVLimUnit_D_Rq 1; +BA_ "GenSigSendType" SG_ 985 IsaVLimUnit_D_Rq 3; +BA_ "GenSigSendType" SG_ 985 AdbDividedRoad_B_Stat 3; +BA_ "GenSigSendType" SG_ 985 LcwaMsgTxt_D_Stat 3; +BA_ "GenSigSendType" SG_ 985 AdbDrvSide_B_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 992 MsgCntrDsplyOp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 992 MsgCntrDsplyOp_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 992 MsgCntrFeatNoRq 1; +BA_ "CrossOver_InfoCAN" SG_ 992 MsgCntrFeatNoRq 1; +BA_ "U_P702_MY2021_Rx" SG_ 992 MsgCntrFeatConfigRq 1; +BA_ "CrossOver_InfoCAN" SG_ 992 MsgCntrFeatConfigRq 1; +BA_ "U_P702_MY2021_Rx" SG_ 992 MsgCntrPersIndex_D_Rq 1; +BA_ "GenSigStartValue" SG_ 992 MsgCntrPersIndex_D_Rq 4; +BA_ "GenSigStartValueInteger" SG_ 992 MsgCntrPersIndex_D_Rq 4; +BA_ "CrossOver_InfoCAN" SG_ 992 MsgCntrPersIndex_D_Rq 1; +BA_ "GenSigSendType" SG_ 2612019416 PARSEDPhysGWM_ECG2toPCM 3; +BA_ "ECGUsedTxSignal" SG_ 2612019416 PARSEDPhysGWM_ECG2toPCM 1; +BA_ "UsedOnPgmDBC" SG_ 943 VehVActlAdas_D_Qf 1; +BA_ "MetaData" SG_ 943 VehVActlAdas_D_Qf 1; +BA_ "GenSigStartValue" SG_ 943 VehVActlAdas_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 943 Veh_V_RqLsc 1; +BA_ "UsedOnPgmDBC" SG_ 943 Veh_V_ActlAdas 1; +BA_ "GenSigStartValue" SG_ 943 AdasLcDistToObj_L_Actl 4094; +BA_ "UsedOnPgmDBC" SG_ 515 PtIgnSwtch_No_Cs 1; +BA_ "MetaData" SG_ 515 PtIgnSwtch_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 515 PtIgnSwtch_No_Cnt 1; +BA_ "MetaData" SG_ 515 PtIgnSwtch_No_Cnt 1; +BA_ "GenSigSendType" SG_ 515 PtIgnSwtch_D_Stat 3; +BA_ "GenSigStartValue" SG_ 515 PtIgnSwtch_D_Stat 2; +BA_ "GenSigStartValueInteger" SG_ 1111 TrlrYawWActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 1111 TrlrYawWActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 1111 TrlrYawWActl_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1111 TrlrYawWActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 1111 TrlrYaw_W_Actl 65534; +BA_ "GenSigStartValue" SG_ 1111 TrlrYaw_W_Actl 65534; +BA_ "U_P702_MY2021_Rx" SG_ 1111 TrlrYaw_W_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1111 TrlrYaw_W_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1111 TrlrHitYaw_AnRate_Actl 4094; +BA_ "GenSigStartValue" SG_ 1111 TrlrHitYaw_AnRate_Actl 4093; +BA_ "U_P702_MY2021_Rx" SG_ 1111 TrlrHitYaw_AnRate_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1111 TrlrHitYaw_AnRate_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1111 TrlrHitchYaw_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1111 TrlrHitchYaw_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1111 TrlrHitchYaw_An_Actl 4094; +BA_ "GenSigStartValue" SG_ 1111 TrlrHitchYaw_An_Actl 4093; +BA_ "U_P702_MY2021_Rx" SG_ 1111 TrlrHitchYaw_An_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1111 TrlrHitchYaw_An_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1106 TrlrSnsId_No_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1106 TrlrSnsId_No_Actl 1; +BA_ "GenSigStartValue" SG_ 982 LatCtlCrv_NoRate2_Actl 1024; +BA_ "UsedOnPgmDBC" SG_ 982 LatCtlPath_No_Cnt 1; +BA_ "ContentDependant" SG_ 982 LatCtlPath_No_Cnt 1; +BA_ "MetaData" SG_ 982 LatCtlPath_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 982 LatCtlPath_No_Cs 1; +BA_ "ContentDependant" SG_ 982 LatCtlPath_No_Cs 1; +BA_ "MetaData" SG_ 982 LatCtlPath_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 982 HandsOffCnfm_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 982 HandsOffCnfm_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 982 LatCtlRampType_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 982 LatCtlRampType_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 982 LatCtlPrecision_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 982 LatCtlPrecision_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 982 LatCtlPathOffst_L_Actl 512; +BA_ "U_CX727_MY2021_Rx" SG_ 982 LatCtlPathOffst_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 982 LatCtlPathOffst_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 982 LatCtlPath_An_Actl 1000; +BA_ "U_CX727_MY2021_Rx" SG_ 982 LatCtlPath_An_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 982 LatCtlPath_An_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 982 LatCtlCurv_No_Actl 1000; +BA_ "U_CX727_MY2021_Rx" SG_ 982 LatCtlCurv_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 982 LatCtlCurv_No_Actl 1; +BA_ "GenSigSendType" SG_ 1985 TesterPhysicalReqCMR_DSMC 3; +BA_ "GenSigSendType" SG_ 1993 TesterPhysicalResCMR_DSMC 3; +BA_ "MetaData" SG_ 1104 DrvEngageLevel_No_Cs 1; +BA_ "ContentDependant" SG_ 1104 DrvEngageLevel_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 1104 DrvEngageLevel_No_Cs 1; +BA_ "MetaData" SG_ 1104 DrvEngageLevel_No_Cnt 1; +BA_ "ContentDependant" SG_ 1104 DrvEngageLevel_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 1104 DrvEngageLevel_No_Cnt 1; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_GWOnBoardTester 255; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_GWNMProxY 255; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_GWNMProxY 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_GWNMProxY 255; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_AutoSarNMReserved 255; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_AutoSarNMReserved 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_AutoSarNMReserved 255; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_AutoSarNMReserve4 255; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_AutoSarNMReserve4 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_AutoSarNMReserve4 255; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_AutoSarNMReserve3 255; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_AutoSarNMReserve3 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_AutoSarNMReserve3 255; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_AutoSarNMReserve2 255; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_AutoSarNMReserve2 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_AutoSarNMReserve2 255; +BA_ "GenSigStartValue" SG_ 1503 CMR_DSMC_AutoSarNMNodeId 223; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_AutoSarNMNodeId 1; +BA_ "GenSigStartValueInteger" SG_ 1503 CMR_DSMC_AutoSarNMNodeId 222; +BA_ "ContentDependant" SG_ 1503 CMR_DSMC_AutoSarNMControl 1; +BA_ "ECGUsedTxSignal" SG_ 2610995416 PARSEDPhysGWM_ECGtoABS 1; +BA_ "GenSigSendType" SG_ 2610995416 PARSEDPhysGWM_ECGtoABS 3; +BA_ "ECGUsedTxSignal" SG_ 2612043992 PARSEDPhysGWM_ECG2toABS 1; +BA_ "GenSigSendType" SG_ 2612043992 PARSEDPhysGWM_ECG2toABS 3; +BA_ "ECGUsedTxSignal" SG_ 2609946840 OTAPhysGWM_ECGtoABS 1; +BA_ "GenSigSendType" SG_ 2609946840 OTAPhysGWM_ECGtoABS 3; +BA_ "ECGUsedRxSignal" SG_ 2611175464 PARSEDPhysABStoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175464 PARSEDPhysABStoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224040 PARSEDPhysABS2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224040 PARSEDPhysABS2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126888 OTAPhysABStoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126888 OTAPhysABStoGWM_ECG 3; +BA_ "ECGUsedTxSignal" SG_ 2610988248 PARSEDPhysGWM_ECGtoIPMA 1; +BA_ "ECGUsedTxSignal" SG_ 2609939672 OTAPhysGWM_ECGtoIPMA 1; +BA_ "GenSigSendType" SG_ 2609939672 OTAPhysGWM_ECGtoIPMA 3; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1114 TrailCtlSwtch_B_Stat2 1; +BA_ "U_P702_MY2021_Rx" SG_ 1114 TrailCtlSwtch_B_Stat2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1116 TrlrAidSetup_D2_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1116 TrlrAidSetup_D2_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1116 TrlrAidEnbl_D2_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1116 TrlrAidEnbl_D2_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1116 TrlrTrgtToBmpr_L_Actl 0; +BA_ "U_P702_MY2021_Rx" SG_ 1116 TrlrIdType_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1116 TrlrIdType_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1116 TrlrBallToBmpr_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1116 TrlrAxleToBmpr_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1116 TrlrAnOffst_An_Mem 0; +BA_ "GenSigStartValueInteger" SG_ 1116 TrlrTrgtOffst_L_Actl 0; +BA_ "ECGUsedRxSignal" SG_ 2611175457 PARSEDPhysIPMAtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175457 PARSEDPhysIPMAtoGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2612224033 PARSEDPhysIPMA2toGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612224033 PARSEDPhysIPMA2toGWM_ECG 3; +BA_ "ECGUsedRxSignal" SG_ 2610126881 OTAPhysIPMAtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126881 OTAPhysIPMAtoGWM_ECG 3; +BA_ "UsedOnPgmDBC" SG_ 1085 ULoRgenTestMde_B_Stat 1; +BA_ "ContentDependant" SG_ 1085 ULoRgenTestMde_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 ULoRgenTestMde_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 ULoRgenTestMde_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1085 PwSrcULoOvrTe_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULoOvrTe_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULoOvrTe_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1085 PwSrcULoFalt_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULoFalt_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULoFalt_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1085 PwSrcULoDcnnt_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULoDcnnt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULoDcnnt_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULo_Pc_Mx 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULo_Pc_Mx 1; +BA_ "UsedOnPgmDBC" SG_ 1085 PwSrcULoComm_B_Falt 1; +BA_ "ContentDependant" SG_ 1085 PwSrcULoComm_B_Falt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULoComm_B_Falt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULoComm_B_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1085 PwSrcULo_I_Mx 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULo_I_Mx 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULo_I_Mx 1; +BA_ "U_P702_MY2021_Rx" SG_ 1085 PwSrcULo_I_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1085 PwSrcULo_I_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1085 PwSrcULo_I_Actl 1; +BA_ "GenSigStartValue" SG_ 981 AdbBrdrTop_An_Rq 254; +BA_ "GenSigStartValue" SG_ 981 AdbBrdrRight_L_Stat 510; +BA_ "GenSigStartValue" SG_ 981 AdbBrdrRight_An_Rq 1022; +BA_ "GenSigStartValue" SG_ 981 AdbBrdrLeft_L_Stat 510; +BA_ "GenSigStartValue" SG_ 981 AdbBrdrLeft_An_Rq 1022; +BA_ "GenSigStartValue" SG_ 981 AdbBrdrBottom_An_Rq 62; +BA_ "U_P702_MY2021_Rx" SG_ 791 EngAirFilt_B_RqReset 1; +BA_ "CrossOver_InfoCAN" SG_ 791 GpsElMdeSel_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 791 LongTermReset_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 791 DrvEffLvl_No_Stat 1; +BA_ "ECGUsedTxSignal" SG_ 2610970840 PARSEDPhysGWM_ECGtoPCM 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2610970840 PARSEDPhysGWM_ECGtoPCM 1; +BA_ "U_P702_MY2021_Rx" SG_ 2610970840 PARSEDPhysGWM_ECGtoPCM 1; +BA_ "GenSigSendType" SG_ 2610970840 PARSEDPhysGWM_ECGtoPCM 3; +BA_ "ECGUsedTxSignal" SG_ 2609922264 OTAPhysGWM_ECGtoPCM 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2609922264 OTAPhysGWM_ECGtoPCM 1; +BA_ "U_P702_MY2021_Rx" SG_ 2609922264 OTAPhysGWM_ECGtoPCM 1; +BA_ "GenSigSendType" SG_ 2609922264 OTAPhysGWM_ECGtoPCM 3; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoStat_D_Qlty 1; +BA_ "GenSigStartValue" SG_ 868 BattRgenLoStat_D_Qlty 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoSoc_Pc_Actl 1; +BA_ "GenSigStartValue" SG_ 868 BattRgenLoSoc_Pc_Actl 50; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoPulse_U_Pred 1; +BA_ "GenSigStartValue" SG_ 868 BattRgenLoPulse_U_Pred 216; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoPrtct_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoDChrg_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoDchrg_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoChrg_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLoChrg_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLo_T_Est 1; +BA_ "U_P702_MY2021_Rx" SG_ 868 BattRgenLo_B_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 867 BattRgenLoBalnc_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 867 BattRgenLo_Te_Hi 1; +BA_ "GenSigStartValue" SG_ 867 BattRgenLo_Te_Hi 45; +BA_ "U_P702_MY2021_Rx" SG_ 867 BattRgenLo_Te_Actl 1; +BA_ "GenSigStartValue" SG_ 867 BattRgenLo_Te_Actl 85; +BA_ "U_P702_MY2021_Rx" SG_ 867 BattRgenLo_R_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 867 BattRgenLo_AhRide_Actl 1; +BA_ "GenSigStartValue" SG_ 867 BattRgenLo_AhRide_Actl 12800; +BA_ "U_P702_MY2021_Rx" SG_ 867 BattRgenLo_Ah_Actl 1; +BA_ "GenSigStartValue" SG_ 867 BattRgenLo_Ah_Actl 50; +BA_ "U_P702_MY2021_Rx" SG_ 866 BattRgenLoOpen_U_Actl 1; +BA_ "GenSigStartValue" SG_ 866 BattRgenLoOpen_U_Actl 180; +BA_ "U_P702_MY2021_Rx" SG_ 866 BattRgenLoDchrg_U_Mn 1; +BA_ "GenSigStartValue" SG_ 866 BattRgenLoDchrg_U_Mn 280; +BA_ "U_P702_MY2021_Rx" SG_ 866 BattRgenLoDchrg_I_Mx 1; +BA_ "U_P702_MY2021_Rx" SG_ 866 BattRgenLoChrg_U_Mx 1; +BA_ "GenSigStartValue" SG_ 866 BattRgenLoChrg_U_Mx 96; +BA_ "U_P702_MY2021_Rx" SG_ 866 BattRgenLoChrg_I_Mx 1; +BA_ "U_P702_MY2021_Rx" SG_ 865 BattRgenLo_U_Actl 1; +BA_ "GenSigStartValue" SG_ 865 BattRgenLo_U_Actl 768; +BA_ "U_P702_MY2021_Rx" SG_ 865 BattRgenLo_I_Actl 1; +BA_ "GenSigStartValue" SG_ 865 BattRgenLo_I_Actl 32768; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 2611175440 PARSEDPhysPCMtoGWM_ECG 1; +BA_ "U_P702_MY2021_Tx" SG_ 2611175440 PARSEDPhysPCMtoGWM_ECG 1; +BA_ "ECGUsedRxSignal" SG_ 2611175440 PARSEDPhysPCMtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2611175440 PARSEDPhysPCMtoGWM_ECG 3; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 2610126864 OTAPhysPCMtoGWM_ECG 1; +BA_ "U_P702_MY2021_Tx" SG_ 2610126864 OTAPhysPCMtoGWM_ECG 1; +BA_ "ECGUsedRxSignal" SG_ 2610126864 OTAPhysPCMtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126864 OTAPhysPCMtoGWM_ECG 3; +BA_ "GenSigSendType" SG_ 2611175441 PARSEDPhysHPCMtoGWM_ECG 3; +BA_ "GenSigSendType" SG_ 2612224017 PARSEDPhysHPCM2toGWM_ECG 3; +BA_ "U_P702_MY2021_Tx" SG_ 2610126865 OTAPhysHPCMtoGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610126865 OTAPhysHPCMtoGWM_ECG 3; +BA_ "U_P702_MY2021_Tx" SG_ 1679 UUDTSOBDMCResponse4 1; +BA_ "UsedOnPgmDBC" SG_ 1679 UUDTSOBDMCResponse4 1; +BA_ "GenSigSendType" SG_ 1679 UUDTSOBDMCResponse4 3; +BA_ "U_P702_MY2021_Tx" SG_ 1678 UUDTSOBDMCResponse3 1; +BA_ "UsedOnPgmDBC" SG_ 1678 UUDTSOBDMCResponse3 1; +BA_ "GenSigSendType" SG_ 1678 UUDTSOBDMCResponse3 3; +BA_ "U_P702_MY2021_Tx" SG_ 1677 UUDTSOBDMCResponse2 1; +BA_ "UsedOnPgmDBC" SG_ 1677 UUDTSOBDMCResponse2 1; +BA_ "GenSigSendType" SG_ 1677 UUDTSOBDMCResponse2 3; +BA_ "U_P702_MY2021_Tx" SG_ 1676 UUDTSOBDMCResponse1 1; +BA_ "UsedOnPgmDBC" SG_ 1676 UUDTSOBDMCResponse1 1; +BA_ "GenSigSendType" SG_ 1676 UUDTSOBDMCResponse1 3; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1445 SOBDMC_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_AutoSarNMReserved4 255; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1445 SOBDMC_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_AutoSarNMReserved3 255; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1445 SOBDMC_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_AutoSarNMReserved2 255; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1445 SOBDMC_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_AutoSarNMReserved1 255; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_AutoSarNMNodeId 165; +BA_ "ContentDependant" SG_ 1445 SOBDMC_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_AutoSarNMNodeId 165; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1445 SOBDMC_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_AutoSarNMControl 1; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1445 SOBDMC_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_GWOnBoardTester 255; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1445 SOBDMC_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1445 SOBDMC_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1445 SOBDMC_GWNMProxy 255; +BA_ "U_P702_MY2021_Tx" SG_ 1445 SOBDMC_GWNMProxy 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1144 WakeAlarm0_T_Rq 1; +BA_ "GenSigStartValue" SG_ 1144 WakeAlarm0_T_Rq 32767; +BA_ "GenSigStartValueInteger" SG_ 1144 WakeAlarm0_T_Rq 32767; +BA_ "U_CX727_MY2021_Tx" SG_ 1144 WakeAlarm0_B_Typ 1; +BA_ "GenSigSendType" SG_ 1144 WakeAlarm0_B_Typ 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1144 PreCondBatt_B_Actl 1; +BA_ "GenSigSendType" SG_ 1144 PreCondBatt_B_Actl 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1144 HtrnDcdcDis_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1144 HtrnDcdcDis_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 HtrnDcdcDis_B_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1144 ChrgNowEvnt_B_Stat 1; +BA_ "GenSigSendType" SG_ 1144 ChrgNowEvnt_B_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1144 CabinDrvSustn_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1144 CabinDrvSustn_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 CabinDrvSustn_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1144 BattChrgTrgtSoC_D_Rq 1; +BA_ "GenSigSendType" SG_ 1144 CabnEvapSovFront_B_Rq 3; +BA_ "WakeupSignal" SG_ 1144 CabnEvapSovFront_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 CabnEvapSovFront_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 HeatCoreSovRear_B_Rq 3; +BA_ "WakeupSignal" SG_ 1144 HeatCoreSovRear_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 HeatCoreSovRear_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 BattChlrSov_B_Rq 3; +BA_ "WakeupSignal" SG_ 1144 BattChlrSov_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 BattChlrSov_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 CabnEvapSovRear_B_Rq 3; +BA_ "WakeupSignal" SG_ 1144 CabnEvapSovRear_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 CabnEvapSovRear_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 BrkAppl_D_RqPt 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1144 BrkAppl_D_RqPt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1144 BrkAppl_D_RqPt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 BrkAppl_D_RqPt 1; +BA_ "GenSigSendType" SG_ 1144 HtrnCnnctPwr_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1144 HtrnCnnctPwr_B_Stat 1; +BA_ "GenSigSendType" SG_ 1144 PtcHtr_D_Stat 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1144 PtcHtr_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1144 PtcHtr_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 PtcHtr_D_Stat 1; +BA_ "GenSigSendType" SG_ 1144 HtrnClntFlw_D_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1144 HtrnClntFlw_D_Rq 1; +BA_ "GenSigSendType" SG_ 1144 BattTracDrvSustn_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1144 BattTracDrvSustn_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1144 BattTracDrvSustn_B_Rq 1; +BA_ "GenSigSendType" SG_ 1144 BattTracClntVlv_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1144 BattTracClntVlv_B_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1141 OfbChrgSetSync_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1141 OfbChrgSetSync_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1141 PtRmtRprt_D_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 1141 PtRmtRprt_D_Rq 1; +BA_ "WakeupSignal" SG_ 1141 PtRmtRprt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1141 MtrTrac2_Tq_Actl 4095; +BA_ "GenSigStartValue" SG_ 1141 MtrTrac2_Tq_Actl 4095; +BA_ "U_P702_MY2021_Tx" SG_ 1141 MtrTrac2_Tq_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1141 MtrTrac2_Tq_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1141 NtfctnConflict1_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1141 NtfctnConflict1_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1140 RgenEvntLvl_Pc_Dsply 1; +BA_ "GenSigStartValue" SG_ 1140 RgenEvntLvl_Pc_Dsply 1022; +BA_ "GenSigStartValueInteger" SG_ 1140 RgenEvntLvl_Pc_Dsply 1023; +BA_ "U_CX727_MY2021_Tx" SG_ 1140 BrkEvntComplt_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1140 PreCondStat_D_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1140 PreCondStat_D_Dsply 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1139 ActChrgStrtYr_No2_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1139 ActChrgStrtYr_No2_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1139 ActChrgStrtYr_No2_Actl 0; +BA_ "U_P702_MY2021_Tx" SG_ 1139 BattChrgTrgtLMax_T_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1139 ActChrgStrtYr_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1139 ActChrgStrtYr_No_Actl 0; +BA_ "ECGUsedRxSignal" SG_ 1139 ActChrgStrtYr_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1139 ActChrgStrtMin_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1139 ActChrgStrtMin_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1139 ActChrgStrtHr_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1139 ActChrgStrtHr_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1139 ActChrgStrtDay_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1139 ActChrgStrtDay_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1139 ActChrgStrtDay_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1139 ActChrgStrtDay_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1139 ActChrgStrMnth_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1139 ActChrgStrMnth_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1139 ActChrgStrMnth_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1139 ActChrgStrMnth_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1138 ActChrgEndYr_No2_Actl 0; +BA_ "ECGUsedRxSignal" SG_ 1138 ActChrgEndYr_No2_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1138 ActChrgEndYr_No2_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1138 BattChrgTrgtLMin_T_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1138 ActChrgEndYr_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1138 ActChrgEndYr_No_Actl 0; +BA_ "ECGUsedRxSignal" SG_ 1138 ActChrgEndYr_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1138 ActChrgEndMnth_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1138 ActChrgEndMnth_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1138 ActChrgEndMnth_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1138 ActChrgEndMnth_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1138 ActChrgEndMin_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1138 ActChrgEndMin_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1138 ActChrgEndHr_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1138 ActChrgEndHr_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1138 ActChrgEndDay_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1138 ActChrgEndDay_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1138 ActChrgEndDay_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1138 ActChrgEndDay_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 Mtr2Aout_W_ActlMntr 1; +BA_ "GenSigStartValue" SG_ 1089 Mtr2Aout_W_ActlMntr 1023; +BA_ "GenSigStartValueInteger" SG_ 1089 Mtr2Aout_W_ActlMntr 1023; +BA_ "ECGUsedRxSignal" SG_ 1089 Mtr2Aout_W_ActlMntr 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 Inv1_Te_Actl 1; +BA_ "GenSigStartValue" SG_ 1089 Inv1_Te_Actl 254; +BA_ "GenSigStartValueInteger" SG_ 1089 Inv1_Te_Actl 254; +BA_ "U_P702_MY2021_Tx" SG_ 1089 MtrTrac2Coil_Te_Actl 1; +BA_ "GenSigStartValue" SG_ 1089 MtrTrac2Coil_Te_Actl 254; +BA_ "GenSigStartValueInteger" SG_ 1089 MtrTrac2Coil_Te_Actl 254; +BA_ "ECGUsedRxSignal" SG_ 1089 MtrTrac2Coil_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 MtrTrac2_U_Actl 1; +BA_ "GenSigStartValue" SG_ 1089 MtrTrac2_U_Actl 1023; +BA_ "GenSigStartValueInteger" SG_ 1089 MtrTrac2_U_Actl 1023; +BA_ "U_P702_MY2021_Tx" SG_ 1089 MtrTrac2Falt_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 MtrTrac2TeAlrm_B_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1089 MtrTrac2TeAlrm_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 Mtr2CntlTeAlrm_B_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1089 Mtr2CntlTeAlrm_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 MtrTrac2Inv_Te_Actl 1; +BA_ "GenSigStartValue" SG_ 1089 MtrTrac2Inv_Te_Actl 214; +BA_ "GenSigStartValueInteger" SG_ 1089 MtrTrac2Inv_Te_Actl 214; +BA_ "ECGUsedRxSignal" SG_ 1089 MtrTrac2Inv_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1089 MtrTrac2_I_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1089 MtrTrac2_I_Actl 10000; +BA_ "U_CX727_MY2021_Tx" SG_ 1088 ChrgTMatch_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1088 ChrgStat_D2_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1088 ChrgStat_D2_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1088 HvacPrecondRecirc_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1088 HvacPrecondMode2_D_Rq 1; +BA_ "ContentDependant" SG_ 1088 HvacPrecondMode2_D_Rq 1; +BA_ "WakeupSignal" SG_ 1088 HvacPrecondMode2_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1088 HvacPrecondBlwr2_D_Rq 1; +BA_ "ContentDependant" SG_ 1088 HvacPrecondBlwr2_D_Rq 1; +BA_ "WakeupSignal" SG_ 1088 HvacPrecondBlwr2_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1088 HvacPrecondAC_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1088 HvacPrecond_Te_Rq 1; +BA_ "GenSigStartValue" SG_ 1088 HvacPrecond_Te_Rq 2; +BA_ "GenSigStartValueInteger" SG_ 1088 HvacPrecond_Te_Rq 2; +BA_ "U_P702_MY2021_Tx" SG_ 1088 BattChrgInhbt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1040 ElCmprEnbl_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1040 ElCmprEnbl_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1040 ElCmprEnbl_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1040 ElCmpr_N_Rq 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTElement_B_Dsply 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTElement_B_Dsply 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1016 ChrgGoTElement_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgLocIdCurnt_D_Uns 1; +BA_ "GenSigSendType" SG_ 1016 ChrgLocIdCurnt_D_Uns 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgLocIdCurnt_D_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTTouchEnbl_B_Rq 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTTouchEnbl_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTTouch_B_Stat 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTTouch_B_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTTouch_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTPrcond_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTPrcond_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTNext_D_Stat 1; +BA_ "MetaData" SG_ 1016 ChrgGoTNext_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1016 ChrgGoTNext_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1016 ChrgGoTNext_D_Stat 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTNext_D_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTNext_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTMnte_D_Stat 1; +BA_ "MetaData" SG_ 1016 ChrgGoTMnte_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1016 ChrgGoTMnte_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1016 ChrgGoTMnte_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTMnte_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTHr_T_Stat 1; +BA_ "GenSigStartValue" SG_ 1016 ChrgGoTHr_T_Stat 30; +BA_ "GenSigStartValueInteger" SG_ 1016 ChrgGoTHr_T_Stat 30; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTHr_T_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTExtHtrEnbl_B_Rq 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTExtHtrEnbl_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTExtHtr_B_Stat 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTExtHtr_B_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTExtHtr_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTElement_D_Stat 1; +BA_ "MetaData" SG_ 1016 ChrgGoTElement_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1016 ChrgGoTElement_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1016 ChrgGoTElement_D_Stat 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTElement_D_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTElement_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1016 ChrgGoTAllOn_B_Stat 1; +BA_ "GenSigSendType" SG_ 1016 ChrgGoTAllOn_B_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1016 ChrgGoTAllOn_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgToPcWkndSav_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1013 ChrgToPcWkndSav_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgToPcWkndSav_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgToPcWkdySav_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1013 ChrgToPcWkdySav_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgToPcWkdySav_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgProgIdSaved_D_Stat 1; +BA_ "MetaData" SG_ 1013 ChrgProgIdSaved_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1013 ChrgProgIdSaved_D_Stat 1; +BA_ "GenSigSendType" SG_ 1013 ChrgProgIdSaved_D_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgProgIdSaved_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgNowEnbl_B_Saved 1; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgNowEnbl_B_Saved 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgLocIdUnsAck_B_Stat 1; +BA_ "GenSigSendType" SG_ 1013 ChrgLocIdUnsAck_B_Stat 3; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgLocIdUnsAck_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgLocIdCurnt_D_Sav 1; +BA_ "MetaData" SG_ 1013 ChrgLocIdCurnt_D_Sav 1; +BA_ "GenSigSendType" SG_ 1013 ChrgLocIdCurnt_D_Sav 3; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgLocIdCurnt_D_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgPrflWknd_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgPrflWknd_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1013 ChrgPrflWkdy_No_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 1013 ChrgPrflWkdy_No_Actl 1; +BA_ "GenSigSendType" SG_ 1012 ChrgNowCurnt_B_Dsply 3; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgNowCurnt_B_Dsply 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1012 ChrgNowCurnt_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgNowCurnt_B_Dsply 1; +BA_ "GenSigSendType" SG_ 1012 ChrgLocSaved_B_Dsply 3; +BA_ "UsedOnPgmDBC" SG_ 1012 ChrgLocSaved_B_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocSaved_B_Dsply 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1012 ChrgLocSaved_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocSaved_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocLongPostv_B_Sav 1; +BA_ "UsedOnPgmDBC" SG_ 1012 ChrgLocLongPostv_B_Sav 1; +BA_ "CrossOver_InfoCAN" SG_ 1012 ChrgLocLongPostv_B_Sav 1; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocLongPostv_B_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocLongFrct_An_Sav 1; +BA_ "GenSigStartValue" SG_ 1012 ChrgLocLongFrct_An_Sav 1048575; +BA_ "GenSigStartValueInteger" SG_ 1012 ChrgLocLongFrct_An_Sav 1048575; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocLongFrct_An_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocLongDeg_An_Sav 1; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocLongDeg_An_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocLattPostv_B_Sav 1; +BA_ "UsedOnPgmDBC" SG_ 1012 ChrgLocLattPostv_B_Sav 1; +BA_ "CrossOver_InfoCAN" SG_ 1012 ChrgLocLattPostv_B_Sav 1; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocLattPostv_B_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocLattFrct_An_Sav 1; +BA_ "GenSigStartValue" SG_ 1012 ChrgLocLattFrct_An_Sav 1048575; +BA_ "GenSigStartValueInteger" SG_ 1012 ChrgLocLattFrct_An_Sav 1048575; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocLattFrct_An_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocLattDeg_An_Sav 1; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocLattDeg_An_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1012 ChrgLocId_D_Sav 1; +BA_ "GenSigSendType" SG_ 1012 ChrgLocId_D_Sav 3; +BA_ "ECGUsedRxSignal" SG_ 1012 ChrgLocId_D_Sav 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocLongPostv_B_Uns 1; +BA_ "UsedOnPgmDBC" SG_ 1011 ChrgLocLongPostv_B_Uns 1; +BA_ "CrossOver_InfoCAN" SG_ 1011 ChrgLocLongPostv_B_Uns 1; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocLongPostv_B_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocLongFrct_An_Uns 1; +BA_ "GenSigStartValue" SG_ 1011 ChrgLocLongFrct_An_Uns 1048575; +BA_ "GenSigStartValueInteger" SG_ 1011 ChrgLocLongFrct_An_Uns 1048575; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocLongFrct_An_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocLongDeg_An_Uns 1; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocLongDeg_An_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocLattPostv_B_Uns 1; +BA_ "UsedOnPgmDBC" SG_ 1011 ChrgLocLattPostv_B_Uns 1; +BA_ "CrossOver_InfoCAN" SG_ 1011 ChrgLocLattPostv_B_Uns 1; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocLattPostv_B_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocLattFrct_An_Uns 1; +BA_ "GenSigStartValue" SG_ 1011 ChrgLocLattFrct_An_Uns 1048575; +BA_ "GenSigStartValueInteger" SG_ 1011 ChrgLocLattFrct_An_Uns 1048575; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocLattFrct_An_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocLattDeg_An_Uns 1; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocLattDeg_An_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 1011 ChrgLocId_D_Uns 1; +BA_ "GenSigSendType" SG_ 1011 ChrgLocId_D_Uns 3; +BA_ "ECGUsedRxSignal" SG_ 1011 ChrgLocId_D_Uns 1; +BA_ "U_P702_MY2021_Tx" SG_ 871 BattElecPerf_D_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 871 BattElecPerf_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 871 BattChrgTrgtLPt_T_Est 1; +BA_ "ECGUsedRxSignal" SG_ 871 BattChrgTrgtLPt_T_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 871 BattChrgTrgSocPt_T_Est 1; +BA_ "ECGUsedRxSignal" SG_ 871 BattChrgTrgSocPt_T_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 871 BattChrgCmpltPt_T_Est 1; +BA_ "ECGUsedRxSignal" SG_ 871 BattChrgCmpltPt_T_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 786 RgenTrip_Pc_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 786 RgenTrip_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 786 RgenTrip_Pc_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 786 RgenTrip_L_Dsply 1; +BA_ "GenSigStartValue" SG_ 786 RgenTrip_L_Dsply 65535; +BA_ "GenSigStartValueInteger" SG_ 786 RgenTrip_L_Dsply 65535; +BA_ "CrossOver_InfoCAN" SG_ 786 RgenTrip_L_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 786 RgenTrip_L_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 786 ChrgStat_D_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 786 ChrgStat_D_Dsply 1; +BA_ "UsedOnPgmDBC" SG_ 72 immoTarget2Status 1; +BA_ "UsedOnPgmDBC" SG_ 72 immoTarget2Data 1; +BA_ "UsedOnPgmDBC" SG_ 72 immoTarget2Cmd 1; +BA_ "U_P702_MY2021_Rx" SG_ 912 CabnEvapSovFront_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 912 BattChlrSov_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 912 BattTracClntVlv_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 874 BattTracShrtGrnd_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 874 BattTracShrtBatt_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 874 BattTracOpnCirct_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 874 BattChlrShrtGrnd_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 874 BattChlrShrtBatt_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 874 BattChlrOpnCirct_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 651 TelematicsSrvc_D_St 1; +BA_ "ECGUsedTxSignal" SG_ 651 OfbChrgSetSync_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgToPcWknd_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 529 OnbChrgToPcWknd_D_Actl 1; +BA_ "ECGUsedTxSignal" SG_ 529 OnbChrgToPcWknd_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgToPcWkdy_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 529 OnbChrgToPcWkdy_D_Actl 1; +BA_ "ECGUsedTxSignal" SG_ 529 OnbChrgToPcWkdy_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgSetNow_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgSetDelete_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 529 OnbChrgSetDelete_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgPrflWknd_No_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgPrflWkdy_No_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgPrflUpdate_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 529 OnbChrgPrflUpdate_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgLocIdUns_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 529 OnbChrgLocIdUns_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 529 OnbChrgLocIdTrgt_No_Rq 1; +BA_ "MetaData" SG_ 529 OnbChrgLocIdTrgt_No_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 529 OnbChrgLocIdTrgt_No_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 529 OnbChrgLocIdTrgt_No_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 66 immoControlData_T2 1; +BA_ "ContentDependant" SG_ 66 immoControlData_T2 1; +BA_ "U_P702_MY2021_Rx" SG_ 66 immoControlCmd_T2 1; +BA_ "ContentDependant" SG_ 66 immoControlCmd_T2 1; +BA_ "U_P702_MY2021_Rx" SG_ 2610971864 PARSEDPhysGWM_ECGtoHPCM 1; +BA_ "GenSigSendType" SG_ 2610971864 PARSEDPhysGWM_ECGtoHPCM 3; +BA_ "ECGUsedTxSignal" SG_ 2610971864 PARSEDPhysGWM_ECGtoHPCM 1; +BA_ "ECGUsedTxSignal" SG_ 2612002008 PARSEDFuncGWM_ECG 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2612002008 PARSEDFuncGWM_ECG 1; +BA_ "U_P702_MY2021_Rx" SG_ 2612002008 PARSEDFuncGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2612002008 PARSEDFuncGWM_ECG 3; +BA_ "U_P702_MY2021_Rx" SG_ 2609923288 OTAPhysGWM_ECGtoHPCM 1; +BA_ "GenSigSendType" SG_ 2609923288 OTAPhysGWM_ECGtoHPCM 3; +BA_ "ECGUsedTxSignal" SG_ 2609923288 OTAPhysGWM_ECGtoHPCM 1; +BA_ "ECGUsedTxSignal" SG_ 2610953432 OTAFuncGWM_ECG 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2610953432 OTAFuncGWM_ECG 1; +BA_ "U_P702_MY2021_Rx" SG_ 2610953432 OTAFuncGWM_ECG 1; +BA_ "GenSigSendType" SG_ 2610953432 OTAFuncGWM_ECG 3; +BA_ "GenSigSendType" SG_ 2022 TesterPhysicalReqSOBDMC 3; +BA_ "U_P702_MY2021_Rx" SG_ 2022 TesterPhysicalReqSOBDMC 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_Vdop 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_Speed 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_Sat_num_in_view 1; +BA_ "U_P702_MY2021_Rx" SG_ 1124 GPS_Sat_num_in_view 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_MSL_altitude 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_Heading 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_Hdop 1; +BA_ "CrossOver_InfoCAN" SG_ 1124 GPS_dimension 1; +BA_ "U_P702_MY2021_Rx" SG_ 1124 GPS_dimension 1; +BA_ "U_P702_MY2021_Rx" SG_ 1119 CoolFanDcdc_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1119 DcdcClntFlw_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 132 GlblClkYr_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 132 GlblClkScnd_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 132 GlblClkMnte_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 132 GlblClkHr_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 132 GlblClkDay_No_Actl 1; +BA_ "GenSigSendType" SG_ 1990 TesterPhysicalReqSODR 3; +BA_ "GenSigSendType" SG_ 1892 TesterPhysicalReqCCM 3; +BA_ "GenSigSendType" SG_ 1798 TesterPhysicalReqIPMA 3; +BA_ "GenSigStartValueInteger" SG_ 1123 GpsUtcYr_No_Actl 0; +BA_ "CrossOver_InfoCAN" SG_ 1123 GpsUtcYr_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1123 GpsUtcMnth_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1123 GpsUtcMnth_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GpsUtcMnth_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1123 GpsUtcDay_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1123 GpsUtcDay_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GpsUtcDay_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GPS_UTC_seconds 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GPS_UTC_minutes 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GPS_UTC_hours 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GPS_Pdop 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GPS_Compass_direction 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 GPS_Actual_vs_Infer_pos 1; +BA_ "CrossOver_InfoCAN" SG_ 1123 Gps_B_Falt 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GpsHsphLongEast_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GpsHsphLattSth_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GPS_Longitude_Minutes 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GPS_Longitude_Min_dec 1; +BA_ "GenSigStartValueInteger" SG_ 1122 GPS_Longitude_Degrees 179; +BA_ "CrossOver_InfoCAN" SG_ 1122 GPS_Longitude_Degrees 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GPS_Latitude_Minutes 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GPS_Latitude_Min_dec 1; +BA_ "CrossOver_InfoCAN" SG_ 1122 GPS_Latitude_Degrees 1; +BA_ "GenSigStartValue" SG_ 1003 PersNoPos_D_Actl 4; +BA_ "GenSigStartValueInteger" SG_ 1003 PersNoPos_D_Actl 4; +BA_ "CrossOver_InfoCAN" SG_ 1003 PersNoPos_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1003 PersSetupRestr_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1003 PersSetupAccessCtrl 1; +BA_ "CrossOver_InfoCAN" SG_ 1003 PersSetup_No_Actl 1; +BA_ "GenSigStartValue" SG_ 1003 PersConflict_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1003 PersConflict_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1003 PersConflict_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1003 AssocConfirm_D_Actl 1; +BA_ "MetaData" SG_ 1003 RecallEvent_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 1003 RecallEvent_No_Cnt 1; +BA_ "GenSigStartValue" SG_ 1003 PersNo_D_Actl 4; +BA_ "GenSigStartValueInteger" SG_ 1003 PersNo_D_Actl 4; +BA_ "CrossOver_InfoCAN" SG_ 1003 PersNo_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 994 PersStore_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 994 Pers4OptIn_B_Stats 1; +BA_ "WakeupSignal" SG_ 994 Pers4OptIn_B_Stats 1; +BA_ "CrossOver_InfoCAN" SG_ 994 Pers3OptIn_B_Stats 1; +BA_ "WakeupSignal" SG_ 994 Pers3OptIn_B_Stats 1; +BA_ "CrossOver_InfoCAN" SG_ 994 Pers2OptIn_B_Stats 1; +BA_ "WakeupSignal" SG_ 994 Pers2OptIn_B_Stats 1; +BA_ "CrossOver_InfoCAN" SG_ 994 Pers1OptIn_B_Stats 1; +BA_ "WakeupSignal" SG_ 994 Pers1OptIn_B_Stats 1; +BA_ "GenSigStartValue" SG_ 994 CtrStkPersIndex_D_Actl 4; +BA_ "GenSigStartValueInteger" SG_ 994 CtrStkPersIndex_D_Actl 4; +BA_ "CrossOver_InfoCAN" SG_ 994 CtrStkPersIndex_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 994 CtrStkFeatNoActl 1; +BA_ "CrossOver_InfoCAN" SG_ 994 CtrStkFeatConfigActl 1; +BA_ "CrossOver_InfoCAN" SG_ 994 CtrStkDsplyOp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 778 PrkAidFront_D_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 778 Cta_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 778 Cta_D_Rq 1; +BA_ "GenSigStartValue" SG_ 778 Cta_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 778 PrkAidRear_D_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 778 Sod_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 778 Sod_D_Rq 2; +BA_ "GenSigStartValue" SG_ 778 Sod_D_Rq 2; +BA_ "WakeupSignal" SG_ 549 Power_Up_Chime_Modules 1; +BA_ "WakeupSignal" SG_ 551 Cntr_Plg_Mode_Cmd 1; +BA_ "GenSigStartValue" SG_ 551 Btt_L_Actl2 30; +BA_ "GenSigStartValueInteger" SG_ 551 Btt_L_Actl2 126; +BA_ "WakeupSignal" SG_ 551 Em_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1010 CbdblActv_B_RqAdas 1; +BA_ "UsedOnPgmDBC" SG_ 1010 CbdblActv_B_RqAdas 1; +BA_ "U_P702_MY2021_Rx" SG_ 1010 LightRng_L_Max 1; +BA_ "U_P702_MY2021_Rx" SG_ 1010 LightPathOffst_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1010 LightPathOffst_L_Actl 512; +BA_ "U_P702_MY2021_Rx" SG_ 1010 LightPath_An_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1010 LightPath_An_Actl 1000; +BA_ "U_P702_MY2021_Rx" SG_ 1010 LightCurv_NoRate_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1010 LightCurv_NoRate_Actl 4096; +BA_ "U_P702_MY2021_Rx" SG_ 1010 LightCurv_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1010 LightCurv_No_Actl 1000; +BA_ "GenSigStartValue" SG_ 1070 BattULo24_Te_Actl 127; +BA_ "GenSigStartValueInteger" SG_ 1070 BattULo24_Te_Actl 127; +BA_ "UsedOnPgmDBC" SG_ 1070 BattULo24_Te_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1070 BattULo24State_D_Qlty 1; +BA_ "GenSigStartValue" SG_ 1070 BattULo24State_D_Qlty 1; +BA_ "U_P702_MY2021_Rx" SG_ 1070 BattULo24Soc_Pc_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1070 BattULo24Soc_Pc_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1070 BattULo24_I_Actl 1; +BA_ "GenSigStartValue" SG_ 1070 BattULo24_I_Actl 8192; +BA_ "U_P702_MY2021_Rx" SG_ 1070 BattULo24_B_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1070 BattULo24_Ah_DeltaRide 1; +BA_ "GenSigStartValue" SG_ 1070 BattULo24_Ah_DeltaRide 12800; +BA_ "GenSigStartValueInteger" SG_ 1186 SelDrvMdeAwd2_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1186 SelDrvMdeAwd2_D_Stat 31; +BA_ "U_CX727_MY2021_Rx" SG_ 1186 SelDrvMdeAwd2_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1186 SelDrvMdeAwd2_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1186 SelDrvMdeAwd2_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1186 RearDiffLckMsg_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1186 RearDiffLckLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1186 RearDiffLckLamp_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1186 RearDiffLck_Tq_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1186 RearDiffLck_Tq_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1186 RearDiffLck_Tq_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1186 RearDiffFalt_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1186 RearDiffFalt_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1186 LsdSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1186 LsdSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdSys_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 611 AwdSys_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdSys_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdStat_D_RqDsply 1; +BA_ "ContentDependant" SG_ 611 AwdStat_D_RqDsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdStat_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 611 AwdStat_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdStat_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdLck_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 611 AwdLck_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdLck_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 611 AwdLck_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdLck_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdSrvcRqd_B_Rq 1; +BA_ "ContentDependant" SG_ 611 AwdSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdSrvcRqd_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 611 AwdSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 NtrlTowAvail_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdLck_Tq_Rq 1; +BA_ "ContentDependant" SG_ 611 AwdLck_Tq_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdLck_Tq_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdLck_Tq_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 611 TrnAout_Tq_RqMx 1; +BA_ "GenSigStartValueInteger" SG_ 611 TrnAout_Tq_RqMx 8191; +BA_ "GenSigStartValue" SG_ 611 TrnAout_Tq_RqMx 8191; +BA_ "U_P702_MY2021_Rx" SG_ 611 TrnAout_Tq_RqMx 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 611 TrnAout_Tq_RqMx 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 TrnAout_Tq_RqMx 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdOffRoadMode_D_Stats 1; +BA_ "UsedOnPgmDBC" SG_ 611 AwdOffRoadMode_D_Stats 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdOffRoadMode_D_Stats 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdLoLamp_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdLoLamp_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdHiLamp_D_RqDsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdHiLamp_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdHiLamp_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdAutoLamp_D_RqDsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdAutoLamp_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdAutoLamp_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 611 Awd2wdLamp_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 Awd2wdLamp_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 611 AwdRnge_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 611 AwdRnge_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 611 AwdRnge_D_Actl 7; +BA_ "GenSigStartValue" SG_ 611 AwdRnge_D_Actl 7; +BA_ "U_P702_MY2021_Rx" SG_ 611 AwdRnge_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 611 AwdRnge_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 611 AwdRnge_D_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 611 AwdRnge_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1461 PSCM_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_GWOnBoardTester 255; +BA_ "U_P702_MY2021_Rx" SG_ 1461 PSCM_GWOnBoardTester 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_GWOnBoardTester 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1461 PSCM_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_GWNMProxy 255; +BA_ "U_P702_MY2021_Rx" SG_ 1461 PSCM_GWNMProxy 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_GWNMProxy 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_GWNMProxy 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1461 PSCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_AutoSarNMReserved4 255; +BA_ "U_P702_MY2021_Rx" SG_ 1461 PSCM_AutoSarNMReserved4 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved4 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1461 PSCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_AutoSarNMReserved3 255; +BA_ "U_P702_MY2021_Rx" SG_ 1461 PSCM_AutoSarNMReserved3 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved3 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1461 PSCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_AutoSarNMReserved2 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved2 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1461 PSCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_AutoSarNMReserved1 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved1 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1461 PSCM_AutoSarNMNodeId 181; +BA_ "ContentDependant" SG_ 1461 PSCM_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1461 PSCM_AutoSarNMNodeId 181; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMNodeId 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1461 PSCM_AutoSarNMControl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1461 PSCM_AutoSarNMControl 1; +BA_ "GenSigStartValueInteger" SG_ 1047 TrlrAnOffst_An2_Calc 128; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAnOffst_An2_Calc 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAn_An_WarnCalc 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAn_An_MxCalc 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAidTrlrId_No_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAidTrgtId_No_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAidSetup_D2_Stat 1; +BA_ "GenSigSendType" SG_ 1047 TrlrAidEnbl_D2_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 1047 TrlrAidEnbl_D2_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1047 TrlrAidEnbl_D2_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAidEnbl_D2_Stat 1; +BA_ "GenSigSendType" SG_ 1047 TrlrAidMsgTxt_D2_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 1047 TrlrAidMsgTxt_D2_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 TrlrAidMsgTxt_D2_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1047 EsaOn_B_Stat 1; +BA_ "GenSigStartValue" SG_ 1047 EsaOn_B_Stat 1; +BA_ "GenSigSendType" SG_ 1047 EsaOn_B_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1047 EsaOn_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 EsaOn_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 HitchToTrlrAxle_L_Calc 1; +BA_ "GenSigSendType" SG_ 1047 SelDrvMdeSte_D_Stat 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1047 SelDrvMdeSte_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1047 SelDrvMdeSte_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1047 SelDrvMdeSte_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1047 SelDrvMdeSte_D_Stat 1; +BA_ "GenSigSendType" SG_ 972 LatCtlSte_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 972 LatCtlSte_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LatCtlSte_D_Stat 1; +BA_ "GenSigSendType" SG_ 972 LatCtlLim_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 972 LatCtlLim_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LatCtlLim_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 972 LatCtlCpbltyDStat_No_Cnt 1; +BA_ "MetaData" SG_ 972 LatCtlCpbltyDStat_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 972 LatCtlCpbltyDStat_No_Cs 1; +BA_ "MetaData" SG_ 972 LatCtlCpbltyDStat_No_Cs 1; +BA_ "GenSigStartValueInteger" SG_ 972 TrlrAn_An_TrgtCalc 128; +BA_ "U_P702_MY2021_Tx" SG_ 972 TrlrAn_An_TrgtCalc 1; +BA_ "U_P702_MY2021_Rx" SG_ 972 LsmcBrkDecelEnbl_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LsmcBrkDecelEnbl_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 972 TjaHandsOnCnfdnc_B_Est 1; +BA_ "GenSigStartValue" SG_ 972 TjaHandsOnCnfdnc_B_Est 1; +BA_ "U_CX727_MY2021_Tx" SG_ 972 TjaHandsOnCnfdnc_B_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 TjaHandsOnCnfdnc_B_Est 1; +BA_ "CrossOver_InfoCAN" SG_ 972 LaHandsOff_B_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 972 LaHandsOff_B_Actl 1; +BA_ "GenSigStartValue" SG_ 972 LaHandsOff_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 972 LaHandsOff_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LaHandsOff_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 972 LaActDeny_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 972 LaActDeny_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LaActDeny_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 972 LaActAvail_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 972 LaActAvail_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LaActAvail_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 972 LsmcBrk_Tq_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 972 LsmcBrk_Tq_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 130 TrlrHitchLamp_D_Rqst 1; +BA_ "UsedOnPgmDBC" SG_ 130 TrlrHitchLamp_D_Rqst 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 TrlrHitchLamp_D_Rqst 1; +BA_ "CrossOver_InfoCAN" SG_ 130 VehVTrlrAid_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 130 VehVTrlrAid_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 130 VehVTrlrAid_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 VehVTrlrAid_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 130 Veh_V_RqMxTrlrAid 255; +BA_ "GenSigStartValue" SG_ 130 Veh_V_RqMxTrlrAid 255; +BA_ "U_P702_MY2021_Rx" SG_ 130 Veh_V_RqMxTrlrAid 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 130 Veh_V_RqMxTrlrAid 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 Veh_V_RqMxTrlrAid 1; +BA_ "UsedOnPgmDBC" SG_ 130 DrvSteActv_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 130 DrvSteActv_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 DrvSteActv_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 130 DrvSte_Tq_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 130 DrvSte_Tq_Actl 128; +BA_ "U_P702_MY2021_Rx" SG_ 130 DrvSte_Tq_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 DrvSte_Tq_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SteMdule_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SteMdule_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 130 SteMdule_U_Meas 1; +BA_ "GenSigStartValueInteger" SG_ 130 SteMdule_U_Meas 255; +BA_ "GenSigStartValue" SG_ 130 SteMdule_U_Meas 255; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SteMdule_U_Meas 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SteMdule_U_Meas 1; +BA_ "UsedOnPgmDBC" SG_ 130 SteMdule_I_Est 1; +BA_ "GenSigStartValueInteger" SG_ 130 SteMdule_I_Est 4095; +BA_ "GenSigStartValue" SG_ 130 SteMdule_I_Est 4095; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SteMdule_I_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SteMdule_I_Est 1; +BA_ "CrossOver_InfoCAN" SG_ 130 EPAS_Failure 1; +BA_ "UsedOnPgmDBC" SG_ 130 EPAS_Failure 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 EPAS_Failure 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 EPAS_Failure 1; +BA_ "UsedOnPgmDBC" SG_ 130 SteeringColumnTorque 1; +BA_ "GenSigStartValueInteger" SG_ 130 SteeringColumnTorque 254; +BA_ "GenSigStartValue" SG_ 130 SteeringColumnTorque 254; +BA_ "U_CX727_MY2021_Rx" SG_ 130 SteeringColumnTorque 1; +BA_ "U_P702_MY2021_Rx" SG_ 130 SteeringColumnTorque 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SteeringColumnTorque 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SteeringColumnTorque 1; +BA_ "UsedOnPgmDBC" SG_ 130 SAPPAngleControlStat6 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SAPPAngleControlStat6 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SAPPAngleControlStat6 1; +BA_ "UsedOnPgmDBC" SG_ 130 SAPPAngleControlStat5 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SAPPAngleControlStat5 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SAPPAngleControlStat5 1; +BA_ "UsedOnPgmDBC" SG_ 130 SAPPAngleControlStat4 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SAPPAngleControlStat4 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SAPPAngleControlStat4 1; +BA_ "UsedOnPgmDBC" SG_ 130 SAPPAngleControlStat3 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SAPPAngleControlStat3 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SAPPAngleControlStat3 1; +BA_ "UsedOnPgmDBC" SG_ 130 SAPPAngleControlStat2 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SAPPAngleControlStat2 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SAPPAngleControlStat2 1; +BA_ "UsedOnPgmDBC" SG_ 130 SAPPAngleControlStat1 1; +BA_ "U_CX727_MY2021_Tx" SG_ 130 SAPPAngleControlStat1 1; +BA_ "U_P702_MY2021_Tx" SG_ 130 SAPPAngleControlStat1 1; +BA_ "UsedOnPgmDBC" SG_ 126 StePw_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 126 StePw_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 126 StePw_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 126 StePw_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "GenSigStartValueInteger" SG_ 126 StePinRelInit_An_Sns 65535; +BA_ "ContentDependant" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "GenSigStartValue" SG_ 126 StePinRelInit_An_Sns 65535; +BA_ "U_P702_MY2021_Rx" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "U_CX727_MY2021_Rx" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "U_CX727_MY2021_Tx" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "U_P702_MY2021_Tx" SG_ 126 StePinRelInit_An_Sns 1; +BA_ "CrossOver_InfoCAN" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "GenSigStartValue" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "U_CX727_MY2021_Tx" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "ECGUsedRxSignal" SG_ 126 StePinCompAnEst_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 126 StePinComp_An_Est 16000; +BA_ "U_P702_MY2021_Rx" SG_ 126 StePinComp_An_Est 1; +BA_ "U_CX727_MY2021_Rx" SG_ 126 StePinComp_An_Est 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 126 StePinComp_An_Est 1; +BA_ "U_CX727_MY2021_Tx" SG_ 126 StePinComp_An_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 126 StePinComp_An_Est 1; +BA_ "ECGUsedRxSignal" SG_ 126 StePinComp_An_Est 1; +BA_ "UsedOnPgmDBC" SG_ 126 StePinAn_No_Cs 1; +BA_ "ContentDependant" SG_ 126 StePinAn_No_Cs 1; +BA_ "MetaData" SG_ 126 StePinAn_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 126 StePinAn_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 126 StePinAn_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 126 StePinAn_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 126 StePinAn_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 126 StePinAn_No_Cnt 1; +BA_ "MetaData" SG_ 126 StePinAn_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 126 StePinAn_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 126 StePinAn_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 126 StePinAn_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 126 StePinAn_No_Cnt 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1430 ABS_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_GWOnBoardTester 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_GWOnBoardTester 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1430 ABS_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_GWNMProxy 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_GWNMProxy 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_GWNMProxy 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1430 ABS_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_AutoSarNMReserved4 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved4 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1430 ABS_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_AutoSarNMReserved3 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved3 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1430 ABS_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_AutoSarNMReserved2 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved2 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1430 ABS_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_AutoSarNMReserved1 255; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved1 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1430 ABS_AutoSarNMNodeId 150; +BA_ "ContentDependant" SG_ 1430 ABS_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1430 ABS_AutoSarNMNodeId 150; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_AutoSarNMNodeId 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1430 ABS_AutoSarNMControl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1430 ABS_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1430 ABS_AutoSarNMControl 1; +BA_ "GenSigStartValueInteger" SG_ 1200 HsaTrnAout_Tq_Rq 32768; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 HsaTrnAout_Tq_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 HsaTrnAout_Tq_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1200 BrkBstrVac_P_Actl 127; +BA_ "GenSigStartValue" SG_ 1200 BrkBstrVac_P_Actl 127; +BA_ "U_P702_MY2021_Rx" SG_ 1200 BrkBstrVac_P_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1200 BrkBstrVac_P_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 BrkBstrVac_P_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 BrkBstrVac_P_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1200 YawStabilityIndex 256; +BA_ "U_CX727_MY2021_Rx" SG_ 1200 YawStabilityIndex 1; +BA_ "U_P702_MY2021_Rx" SG_ 1200 YawStabilityIndex 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 YawStabilityIndex 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 YawStabilityIndex 1; +BA_ "U_P702_MY2021_Rx" SG_ 1200 BrkTot_Tq_RqDrv 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1200 BrkTot_Tq_RqDrv 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 BrkTot_Tq_RqDrv 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 BrkTot_Tq_RqDrv 1; +BA_ "MetaData" SG_ 1200 BrkTotTqRqDrv_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1200 BrkTotTqRqDrv_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1200 BrkTotTqRqDrv_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 BrkTotTqRqDrv_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 BrkTotTqRqDrv_No_Cnt 1; +BA_ "MetaData" SG_ 1200 BrkTotTqRqDrv_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 1200 BrkTotTqRqDrv_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1200 BrkTotTqRqDrv_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 BrkTotTqRqDrv_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 BrkTotTqRqDrv_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1200 HsaStat_D_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1200 HsaStat_D_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos12_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos12_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos12_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos12_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos12_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos11_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos11_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos11_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos11_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos11_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos10_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos10_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos10_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos10_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos10_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos09_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos09_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos09_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos09_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos09_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos08_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos08_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos08_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos08_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos08_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos07_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos07_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos07_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos07_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos07_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos06_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos06_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos06_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos06_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos06_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos05_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos05_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos05_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos05_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos05_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos04_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos04_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos04_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos04_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos04_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos03_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos03_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos03_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos03_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos03_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos02_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos02_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos02_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos02_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos02_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1102 SelDrvMdePos01_D_Stat 31; +BA_ "GenSigStartValue" SG_ 1102 SelDrvMdePos01_D_Stat 31; +BA_ "GenSigSendType" SG_ 1102 SelDrvMdePos01_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1102 SelDrvMdePos01_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1102 SelDrvMdePos01_D_Stat 1; +BA_ "GenSigSendType" SG_ 1056 AutoEpbMsgTxt_D_Rq 3; +BA_ "GenSigSendType" SG_ 1056 AutoEpbDsply_D_Stat 3; +BA_ "GenSigSendType" SG_ 1056 AutoEpbButtnOn_B_Stat 3; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos12_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos12_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos12_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos11_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos11_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos11_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos10_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos10_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos10_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos09_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos09_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos09_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos08_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos08_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos08_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos07_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos07_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos07_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos06_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos06_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos06_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos05_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos05_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos05_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos04_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos04_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos04_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos03_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos03_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos03_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos02_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos02_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos02_B_Avail 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePos01_B_Avail 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePos01_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePos01_B_Avail 1; +BA_ "GenSigStartValueInteger" SG_ 1056 ActvDrvMde_D2_Stat 31; +BA_ "GenSigStartValue" SG_ 1056 ActvDrvMde_D2_Stat 31; +BA_ "GenSigSendType" SG_ 1056 ActvDrvMde_D2_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 ActvDrvMde_D2_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 ActvDrvMde_D2_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1056 SelDrvMde_D2_Rq 31; +BA_ "GenSigStartValue" SG_ 1056 SelDrvMde_D2_Rq 31; +BA_ "GenSigSendType" SG_ 1056 SelDrvMde_D2_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMde_D2_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMde_D2_Rq 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdePt_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 1056 SelDrvMdePt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1056 SelDrvMdePt_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdePt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdePt_D_Rq 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMdeMsgTxt_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMdeMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMdeMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 1056 SelDrvMde_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 SelDrvMde_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 SelDrvMde_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1056 AwdMde_D_RqBrk 5; +BA_ "GenSigStartValue" SG_ 1056 AwdMde_D_RqBrk 5; +BA_ "GenSigSendType" SG_ 1056 AwdMde_D_RqBrk 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1056 AwdMde_D_RqBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 1056 AwdMde_D_RqBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 AirDamUp_B_RqBrk 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1054 AirDamUp_B_RqBrk 1; +BA_ "U_P702_MY2021_Rx" SG_ 1054 AirDamUp_B_RqBrk 1; +BA_ "GenSigSendType" SG_ 1054 AirDamUp_B_RqBrk 3; +BA_ "GenSigSendType" SG_ 1054 RbaBrk_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 RbaBrk_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 RbaBrk_D_Stat 1; +BA_ "GenSigSendType" SG_ 1054 SelDrvMdeChassis2_D_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1054 SelDrvMdeChassis2_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1054 SelDrvMdeChassis2_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 SelDrvMdeChassis2_D_Rq 1; +BA_ "GenSigSendType" SG_ 1054 TrailCtl_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 1054 TrailCtl_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1054 TrailCtl_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 TrailCtl_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 TrailCtl_D_Stat 1; +BA_ "GenSigSendType" SG_ 1054 TrailCtlMsgTxt_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 TrailCtlMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 TrailCtlMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 1054 BrkBstrVac_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 1054 BrkBstrVac_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1054 BrkBstrVac_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 BrkBstrVac_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 BrkBstrVac_D_Stat 1; +BA_ "GenSigSendType" SG_ 1054 DrvSlipCtlOffLamp_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 DrvSlipCtlOffLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 DrvSlipCtlOffLamp_D_Rq 1; +BA_ "GenSigSendType" SG_ 1054 DrvSlipCtlMdeMsg_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 DrvSlipCtlMdeMsg_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 DrvSlipCtlMdeMsg_D_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 1054 DrvSlipCtlMdeMsg_D_Rq 1; +BA_ "GenSigSendType" SG_ 1054 AutoHoldMsgTxt_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 AutoHoldMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 AutoHoldMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 1054 CtaBrk_D_Stat 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 CtaBrk_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 CtaBrk_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1054 SelDrvMdeAwd_D_Rq 31; +BA_ "GenSigStartValue" SG_ 1054 SelDrvMdeAwd_D_Rq 31; +BA_ "GenSigSendType" SG_ 1054 SelDrvMdeAwd_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 1054 SelDrvMdeAwd_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 SelDrvMdeAwd_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1054 AutoHoldSwMde_B_Ind 1; +BA_ "ContentDependant" SG_ 1054 AutoHoldSwMde_B_Ind 1; +BA_ "GenSigSendType" SG_ 1054 AutoHoldSwMde_B_Ind 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 AutoHoldSwMde_B_Ind 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 AutoHoldSwMde_B_Ind 1; +BA_ "GenSigSendType" SG_ 1054 AutoHoldMde_D_Ind 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 AutoHoldMde_D_Ind 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 AutoHoldMde_D_Ind 1; +BA_ "GenSigSendType" SG_ 1054 SelDrvMdeChassis_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 SelDrvMdeChassis_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 SelDrvMdeChassis_D_Rq 1; +BA_ "GenSigSendType" SG_ 1054 ApaBrk_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 1054 ApaBrk_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1054 ApaBrk_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1054 ApaBrk_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1054 ApaBrk_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 HsaMde_D_Mem 1; +BA_ "UsedOnPgmDBC" SG_ 1046 HsaMde_D_Mem 1; +BA_ "GenSigStartValueInteger" SG_ 1046 HsaMde_D_Mem 1; +BA_ "GenSigStartValue" SG_ 1046 HsaMde_D_Mem 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 HsaMde_D_Mem 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 HsaMde_D_Mem 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 BrkBstrVac_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 BrkBstrVac_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 BrkBstrVac_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1046 BrkBstrVac_B_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 BrkBstrVac_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 BrkBstrVac_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 HdcMde_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1046 HdcMde_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 HdcMde_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 HdcMde_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1046 RearDiffLck_Tq2_RqMx 4094; +BA_ "GenSigStartValue" SG_ 1046 RearDiffLck_Tq2_RqMx 4094; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 RearDiffLck_Tq2_RqMx 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 RearDiffLck_Tq2_RqMx 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 TRLR_SWAY_EVNT_IN_PROG 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 TRLR_SWAY_EVNT_IN_PROG 1; +BA_ "ECGUsedRxSignal" SG_ 1046 TRLR_SWAY_EVNT_IN_PROG 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 TRLR_SWAY_CONFIG_STAT 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 TRLR_SWAY_CONFIG_STAT 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 TCMode 1; +BA_ "UsedOnPgmDBC" SG_ 1046 TCMode 1; +BA_ "ContentDependant" SG_ 1046 TCMode 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 TCMode 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1046 TCMode 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 TCMode 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 TCMode 1; +BA_ "ECGUsedRxSignal" SG_ 1046 TCMode 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 DrvSlipCtlLamp_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 DrvSlipCtlLamp_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 DrvSlipCtlLamp_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1046 DrvSlipCtlLamp_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 DrvSlipCtlLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 DrvSlipCtlLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 Abs_B_Falt 1; +BA_ "UsedOnPgmDBC" SG_ 1046 Abs_B_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 Abs_B_Falt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1046 Abs_B_Falt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 Abs_B_Falt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 Abs_B_Falt 1; +BA_ "ECGUsedRxSignal" SG_ 1046 Abs_B_Falt 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "UsedOnPgmDBC" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "ECGUsedRxSignal" SG_ 1046 DrvSlipCtlMde_D_Ind 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 DrvAntiLckLamp_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 DrvAntiLckLamp_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 DrvAntiLckLamp_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1046 DrvAntiLckLamp_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 DrvAntiLckLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 DrvAntiLckLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 BpedMove_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 1046 BpedMove_No_Cnt 1; +BA_ "MetaData" SG_ 1046 BpedMove_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1046 BpedMove_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 BpedMove_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 BpedMove_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 StabCtlBrk_B_Avail 1; +BA_ "UsedOnPgmDBC" SG_ 1046 StabCtlBrk_B_Avail 1; +BA_ "GenSigStartValueInteger" SG_ 1046 StabCtlBrk_B_Avail 1; +BA_ "GenSigStartValue" SG_ 1046 StabCtlBrk_B_Avail 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 StabCtlBrk_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 StabCtlBrk_B_Avail 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 DrvHdcWarnInfo_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 DrvHdcWarnInfo_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 DrvHdcWarnInfo_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 DrvHdcWarnInfo_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 DrvHdcMsg_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 DrvHdcMsg_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 DrvHdcMsg_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 DrvHdcMsg_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 DrvHdcLampInfo_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 DrvHdcLampInfo_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 DrvHdcLampInfo_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 DrvHdcLampInfo_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 BpedMove_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1046 BpedMove_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1046 BpedMove_D_Actl 3; +BA_ "GenSigStartValue" SG_ 1046 BpedMove_D_Actl 3; +BA_ "U_P702_MY2021_Rx" SG_ 1046 BpedMove_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 BpedMove_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 BpedMove_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 ChimeBrk_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 ChimeBrk_B_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 ChimeBrk_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 ChimeBrk_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 BrkLamp_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1046 BrkLamp_B_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 BrkLamp_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 BrkLamp_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1046 HILL_DESC_MC 1; +BA_ "UsedOnPgmDBC" SG_ 1046 HILL_DESC_MC 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1046 HILL_DESC_MC 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 HILL_DESC_MC 1; +BA_ "U_P702_MY2021_Tx" SG_ 1046 RearDiffElckrOpen_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1045 VehStab_D_Stat 14; +BA_ "GenSigStartValue" SG_ 1045 VehStab_D_Stat 14; +BA_ "U_P702_MY2021_Rx" SG_ 1045 VehStab_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 VehStab_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 VehStab_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 VehStab_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 BrkFluidLvl_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 BrkFluidLvl_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1045 LsmcBrkDecel_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 LsmcBrkDecel_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1045 VehYawNonLin_W_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1045 VehYawNonLin_W_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1045 VehYawNonLin_W_Rq 4094; +BA_ "GenSigStartValue" SG_ 1045 VehYawNonLin_W_Rq 4094; +BA_ "U_P702_MY2021_Rx" SG_ 1045 VehYawNonLin_W_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 VehYawNonLin_W_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 VehYawNonLin_W_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 VehYawNonLin_W_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1045 VehYawLin_W_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1045 VehYawLin_W_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1045 VehYawLin_W_Rq 4094; +BA_ "GenSigStartValue" SG_ 1045 VehYawLin_W_Rq 4094; +BA_ "U_P702_MY2021_Rx" SG_ 1045 VehYawLin_W_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 VehYawLin_W_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 VehYawLin_W_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 VehYawLin_W_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "MetaData" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 VehVActlBrk_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "UsedOnPgmDBC" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "U_P702_MY2021_Rx" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 Veh_V_ActlBrk 1; +BA_ "CrossOver_InfoCAN" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "MetaData" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 VehVActlBrk_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "MetaData" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 1045 VehVActlBrk_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 1044 StePinOffst_An_Est 1; +BA_ "GenSigStartValueInteger" SG_ 1044 StePinOffst_An_Est 65534; +BA_ "ContentDependant" SG_ 1044 StePinOffst_An_Est 1; +BA_ "GenSigStartValue" SG_ 1044 StePinOffst_An_Est 65533; +BA_ "U_CX727_MY2021_Rx" SG_ 1044 StePinOffst_An_Est 1; +BA_ "U_P702_MY2021_Rx" SG_ 1044 StePinOffst_An_Est 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1044 StePinOffst_An_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1044 StePinOffst_An_Est 1; +BA_ "UsedOnPgmDBC" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "ContentDependant" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "MetaData" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 1044 StePinOffst_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 1044 StePinOffst_No_Cnt 1; +BA_ "MetaData" SG_ 1044 StePinOffst_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1044 StePinOffst_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1044 StePinOffst_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1044 StePinOffst_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1044 StePinOffst_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1044 StePinOffst_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1044 StePinOffst_D_Stat 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1044 StePinOffst_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1044 StePinOffst_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1042 VehRol_An_Dsply 64; +BA_ "GenSigStartValue" SG_ 1042 VehRol_An_Dsply 0; +BA_ "U_P702_MY2021_Tx" SG_ 1042 VehRol_An_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1042 VehPtch_An_Dsply 64; +BA_ "GenSigStartValue" SG_ 1042 VehPtch_An_Dsply 0; +BA_ "U_P702_MY2021_Rx" SG_ 1042 VehPtch_An_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1042 VehPtch_An_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1042 TrlrBrk_Pc_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 535 WhlRr_W_Meas 1; +BA_ "U_P702_MY2021_Rx" SG_ 535 WhlRr_W_Meas 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 535 WhlRr_W_Meas 1; +BA_ "U_CX727_MY2021_Rx" SG_ 535 WhlRr_W_Meas 1; +BA_ "U_CX727_MY2021_Tx" SG_ 535 WhlRr_W_Meas 1; +BA_ "U_P702_MY2021_Tx" SG_ 535 WhlRr_W_Meas 1; +BA_ "UsedOnPgmDBC" SG_ 535 WhlRl_W_Meas 1; +BA_ "U_P702_MY2021_Rx" SG_ 535 WhlRl_W_Meas 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 535 WhlRl_W_Meas 1; +BA_ "U_CX727_MY2021_Rx" SG_ 535 WhlRl_W_Meas 1; +BA_ "U_CX727_MY2021_Tx" SG_ 535 WhlRl_W_Meas 1; +BA_ "U_P702_MY2021_Tx" SG_ 535 WhlRl_W_Meas 1; +BA_ "UsedOnPgmDBC" SG_ 535 WhlFr_W_Meas 1; +BA_ "U_P702_MY2021_Rx" SG_ 535 WhlFr_W_Meas 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 535 WhlFr_W_Meas 1; +BA_ "U_CX727_MY2021_Rx" SG_ 535 WhlFr_W_Meas 1; +BA_ "U_CX727_MY2021_Tx" SG_ 535 WhlFr_W_Meas 1; +BA_ "U_P702_MY2021_Tx" SG_ 535 WhlFr_W_Meas 1; +BA_ "UsedOnPgmDBC" SG_ 535 WhlFl_W_Meas 1; +BA_ "U_P702_MY2021_Rx" SG_ 535 WhlFl_W_Meas 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 535 WhlFl_W_Meas 1; +BA_ "U_CX727_MY2021_Rx" SG_ 535 WhlFl_W_Meas 1; +BA_ "U_CX727_MY2021_Tx" SG_ 535 WhlFl_W_Meas 1; +BA_ "U_P702_MY2021_Tx" SG_ 535 WhlFl_W_Meas 1; +BA_ "ContentDependant" SG_ 534 BrkObdData_No_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 BrkObdData_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 BrkObdData_No_Actl 1; +BA_ "ContentDependant" SG_ 534 BrkObdIndex_No_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 BrkObdIndex_No_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 BrkObdIndex_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlRotatRr_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlRotatRr_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlRotatRr_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlRotatRr_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlRotatRr_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlDirRr_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlDirRl_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlDirFr_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlDirFl_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlRotatRl_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlRotatRl_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlRotatRl_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlRotatRl_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlRotatRl_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlRotatFr_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlRotatFr_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlRotatFr_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlRotatFr_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlRotatFr_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 534 WhlRotatFl_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 534 WhlRotatFl_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 534 WhlRotatFl_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 534 WhlRotatFl_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 534 WhlRotatFl_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 532 RgenTqFalt_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 532 RgenTqFalt_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 532 RgenTqFalt_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 532 RgenTqFalt_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 532 RgenBrkDynoMde_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 532 RgenBrkDynoMde_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 532 RgenBrkDynoMde_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 532 RgenBrkDynoMde_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 532 PrplWhlTqRqMn_No_Cs 1; +BA_ "MetaData" SG_ 532 PrplWhlTqRqMn_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 532 PrplWhlTqRqMn_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 532 PrplWhlTqRqMn_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 532 PrplWhlTqRqMn_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 532 PrplWhlTqRqMn_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 532 PrplWhlTot_Tq_RqMn 1; +BA_ "U_P702_MY2021_Rx" SG_ 532 PrplWhlTot_Tq_RqMn 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 532 PrplWhlTot_Tq_RqMn 1; +BA_ "U_CX727_MY2021_Tx" SG_ 532 PrplWhlTot_Tq_RqMn 1; +BA_ "U_P702_MY2021_Tx" SG_ 532 PrplWhlTot_Tq_RqMn 1; +BA_ "UsedOnPgmDBC" SG_ 532 PrplWhlTqRqMn_No_Cnt 1; +BA_ "MetaData" SG_ 532 PrplWhlTqRqMn_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 532 PrplWhlTqRqMn_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 532 PrplWhlTqRqMn_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 532 PrplWhlTqRqMn_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 532 PrplWhlTqRqMn_No_Cnt 1; +BA_ "GenSigStartValueInteger" SG_ 531 VehStop_D_Stat 2; +BA_ "GenSigStartValue" SG_ 531 VehStop_D_Stat 2; +BA_ "U_CX727_MY2021_Tx" SG_ 531 VehStop_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 VehStop_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 531 TracCtlPtActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 TracCtlPtActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 TracCtlPtActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 TracCtlPtActv_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 TracCtlPtActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 TracCtlPtActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 LscmbbMntr_B_Err 1; +BA_ "UsedOnPgmDBC" SG_ 531 LscmbbMntr_B_Err 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 LscmbbMntr_B_Err 1; +BA_ "CrossOver_InfoCAN" SG_ 531 LscmbbBrkDis_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 LscmbbBrkDis_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 LscmbbBrkDis_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 LscmbbDeny_B_ActlBrk 1; +BA_ "UsedOnPgmDBC" SG_ 531 LscmbbDeny_B_ActlBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 LscmbbDeny_B_ActlBrk 1; +BA_ "WakeupSignal" SG_ 531 PrkBrkYwLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 531 PrkBrkYwLamp_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 531 PrkBrkYwLamp_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 PrkBrkYwLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 PrkBrkYwLamp_D_Rq 1; +BA_ "WakeupSignal" SG_ 531 PrkBrkRedLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 531 PrkBrkRedLamp_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 531 PrkBrkRedLamp_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 PrkBrkRedLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 PrkBrkRedLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 531 LscmbbBrkDecel_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 LscmbbBrkDecel_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 LscmbbBrkDecel_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AbsActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AbsActv_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 531 AbsActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 AbsActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 AbsActv_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AbsActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AbsActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 531 StabCtlBrkActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 CmbbBrkPrchg_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 CmbbBrkPrchg_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 CmbbBrkPrchg_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 CmbbBrkPrchg_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 CmbbBrkDecel_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 CmbbBrkDecel_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 CmbbBrkDecel_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 CmbbBrkDecel_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 CmbbBaSensInc_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 CmbbBaSensInc_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 CmbbBaSensInc_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 CmbbBaSensInc_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccBrkWarm_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccBrkWarm_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccBrkWarm_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccBrkWarm_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccBrkTotTqMn_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccBrkTotTqMn_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccBrkTotTqMn_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccBrkTotTqMn_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccBrkPrchgActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccBrkPrchgActv_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccBrkPrchgActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccBrkPrchgActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccBrkDis_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccBrkDis_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccBrkDis_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccBrkDis_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccBrkDeny_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccBrkDeny_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 AccBrkDeny_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 AccBrkDeny_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccBrkDeny_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccBrkDeny_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccBrkActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccBrkActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 AccBrkActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 AccBrkActv_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccBrkActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccBrkActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 PrplDrgCtlActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 PrplDrgCtlActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 PrplDrgCtlActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 PrplDrgCtlActv_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 PrplDrgCtlActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 PrplDrgCtlActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 PrplWhlTot_Tq_RqMx 1; +BA_ "UsedOnPgmDBC" SG_ 531 PrplWhlTot_Tq_RqMx 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 PrplWhlTot_Tq_RqMx 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 PrplWhlTot_Tq_RqMx 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 PrplWhlTot_Tq_RqMx 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 PrplWhlTot_Tq_RqMx 1; +BA_ "CrossOver_InfoCAN" SG_ 531 LscmbbBaSensInc_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 LscmbbBaSensInc_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 LscmbbBaSensInc_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 CmbbBrkDis_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 CmbbBrkDis_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 531 CmbbBrkDis_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 CmbbBrkDis_B_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 CmbbBrkDis_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 CmbbBrkDis_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "UsedOnPgmDBC" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "U_CX727_MY2021_Rx" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 CmbbDeny_B_ActlBrk 1; +BA_ "CrossOver_InfoCAN" SG_ 531 CcDis_B_Cmd 1; +BA_ "UsedOnPgmDBC" SG_ 531 CcDis_B_Cmd 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 CcDis_B_Cmd 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 CcDis_B_Cmd 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 CcDis_B_Cmd 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 CcDis_B_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 531 VehLongOvrGnd_A_Est 1; +BA_ "UsedOnPgmDBC" SG_ 531 VehLongOvrGnd_A_Est 1; +BA_ "GenSigStartValueInteger" SG_ 531 VehLongOvrGnd_A_Est 511; +BA_ "U_P702_MY2021_Rx" SG_ 531 VehLongOvrGnd_A_Est 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 VehLongOvrGnd_A_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 VehLongOvrGnd_A_Est 1; +BA_ "CrossOver_InfoCAN" SG_ 531 LscmbBrkPrchg_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 531 LscmbBrkPrchg_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 LscmbBrkPrchg_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccStopActv_B_ActlBrk 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccStopActv_B_ActlBrk 1; +BA_ "U_P702_MY2021_Rx" SG_ 531 AccStopActv_B_ActlBrk 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 AccStopActv_B_ActlBrk 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccStopActv_B_ActlBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccStopActv_B_ActlBrk 1; +BA_ "CrossOver_InfoCAN" SG_ 531 AccDis_B_ActlEpb 1; +BA_ "UsedOnPgmDBC" SG_ 531 AccDis_B_ActlEpb 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 AccDis_B_ActlEpb 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 AccDis_B_ActlEpb 1; +BA_ "WakeupSignal" SG_ 531 PrkBrkMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 531 PrkBrkMsgTxt_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 531 PrkBrkMsgTxt_D_Rq 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 PrkBrkMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 PrkBrkMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 531 PrkBrkStatus 1; +BA_ "UsedOnPgmDBC" SG_ 531 PrkBrkStatus 1; +BA_ "GenSigStartValueInteger" SG_ 531 PrkBrkStatus 7; +BA_ "GenSigStartValue" SG_ 531 PrkBrkStatus 7; +BA_ "U_P702_MY2021_Rx" SG_ 531 PrkBrkStatus 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 531 PrkBrkStatus 1; +BA_ "U_CX727_MY2021_Tx" SG_ 531 PrkBrkStatus 1; +BA_ "U_P702_MY2021_Tx" SG_ 531 PrkBrkStatus 1; +BA_ "ECGUsedRxSignal" SG_ 531 PrkBrkStatus 1; +BA_ "GenSigStartValueInteger" SG_ 136 SteWhlBrkOffst_An_Rq 32766; +BA_ "GenSigStartValue" SG_ 136 SteWhlBrkOffst_An_Rq 32765; +BA_ "U_P702_MY2021_Tx" SG_ 136 SteWhlBrkOffst_An_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 136 SteWhlBrkAnRq_No_Cs 1; +BA_ "MetaData" SG_ 136 SteWhlBrkAnRq_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 136 SteWhlBrkAnRq_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 136 SteWhlBrkAnRq_No_Cnt 1; +BA_ "MetaData" SG_ 136 SteWhlBrkAnRq_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 136 SteWhlBrkAnRq_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 125 VehRolComp_W_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 125 VehRolComp_W_Actl 4094; +BA_ "GenSigStartValue" SG_ 125 VehRolComp_W_Actl 4094; +BA_ "U_CX727_MY2021_Tx" SG_ 125 VehRolComp_W_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 VehRolComp_W_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 125 VehVertComp_A_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 125 VehVertComp_A_Actl 1022; +BA_ "GenSigStartValue" SG_ 125 VehVertComp_A_Actl 1022; +BA_ "U_P702_MY2021_Rx" SG_ 125 VehVertComp_A_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 125 VehVertComp_A_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 VehVertComp_A_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 125 BrkTotTqRqArb_No_Cs 1; +BA_ "MetaData" SG_ 125 BrkTotTqRqArb_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 125 BrkTotTqRqArb_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 125 BrkTotTqRqArb_No_Cs 1; +BA_ "U_CX727_MY2021_Tx" SG_ 125 BrkTotTqRqArb_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 BrkTotTqRqArb_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 125 BrkTotTqRqArb_No_Cnt 1; +BA_ "MetaData" SG_ 125 BrkTotTqRqArb_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 125 BrkTotTqRqArb_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 125 BrkTotTqRqArb_No_Cnt 1; +BA_ "U_CX727_MY2021_Tx" SG_ 125 BrkTotTqRqArb_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 BrkTotTqRqArb_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 125 BrkTot_Tq_RqArb 1; +BA_ "U_P702_MY2021_Rx" SG_ 125 BrkTot_Tq_RqArb 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 125 BrkTot_Tq_RqArb 1; +BA_ "U_CX727_MY2021_Tx" SG_ 125 BrkTot_Tq_RqArb 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 BrkTot_Tq_RqArb 1; +BA_ "ECGUsedRxSignal" SG_ 125 BrkTot_Tq_RqArb 1; +BA_ "UsedOnPgmDBC" SG_ 125 BrkTot_Tq_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 125 BrkTot_Tq_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 125 BrkTot_Tq_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 125 BrkTot_Tq_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 125 BrkTot_Tq_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 BrkTot_Tq_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 125 HsaStat_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 125 HsaStat_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 125 HsaStat_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 125 HsaStat_D_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 125 HsaStat_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 125 HsaStat_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 119 VehTrvlDir_D_Stat 6; +BA_ "GenSigStartValue" SG_ 119 VehTrvlDir_D_Stat 6; +BA_ "U_P702_MY2021_Tx" SG_ 119 VehTrvlDir_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 119 VehOverGnd_V_Est 1; +BA_ "U_CX727_MY2021_Rx" SG_ 119 VehOverGnd_V_Est 1; +BA_ "U_P702_MY2021_Rx" SG_ 119 VehOverGnd_V_Est 1; +BA_ "U_CX727_MY2021_Tx" SG_ 119 VehOverGnd_V_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 119 VehOverGnd_V_Est 1; +BA_ "UsedOnPgmDBC" SG_ 119 VehLongComp_A_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 119 VehLongComp_A_Actl 1022; +BA_ "GenSigStartValue" SG_ 119 VehLongComp_A_Actl 1022; +BA_ "U_P702_MY2021_Rx" SG_ 119 VehLongComp_A_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 119 VehLongComp_A_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 119 VehLongComp_A_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 119 VehLongComp_A_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 119 VehLongComp_A_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 119 VehLatComp_A_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 119 VehLatComp_A_Actl 1022; +BA_ "GenSigStartValue" SG_ 119 VehLatComp_A_Actl 1022; +BA_ "U_P702_MY2021_Rx" SG_ 119 VehLatComp_A_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 119 VehLatComp_A_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 119 VehLatComp_A_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 119 VehLatComp_A_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 119 VehLatComp_A_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 119 VehLatComp_A_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 119 VehYawComp_W_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 119 VehYawComp_W_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 119 VehYawComp_W_Actl 4094; +BA_ "GenSigStartValue" SG_ 119 VehYawComp_W_Actl 4094; +BA_ "U_CX727_MY2021_Rx" SG_ 119 VehYawComp_W_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 119 VehYawComp_W_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 119 VehYawComp_W_Actl 1; +BA_ "U_CX727_MY2021_Tx" SG_ 119 VehYawComp_W_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 119 VehYawComp_W_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 119 VehYawComp_W_Actl 1; +BA_ "GenSigSendType" SG_ 118 BrkCtrFnd_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 118 BrkCtrFnd_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 118 AwdLck_Tq_RqMx 1; +BA_ "U_P702_MY2021_Rx" SG_ 118 AwdLck_Tq_RqMx 1; +BA_ "U_P702_MY2021_Tx" SG_ 118 AwdLck_Tq_RqMx 1; +BA_ "UsedOnPgmDBC" SG_ 118 AwdLck_Tq_RqMn 1; +BA_ "U_P702_MY2021_Rx" SG_ 118 AwdLck_Tq_RqMn 1; +BA_ "U_P702_MY2021_Tx" SG_ 118 AwdLck_Tq_RqMn 1; +BA_ "UsedOnPgmDBC" SG_ 118 DrvSte_D_Stat 1; +BA_ "GenSigSendType" SG_ 118 DrvSte_D_Stat 3; +BA_ "U_CX727_MY2021_Rx" SG_ 118 DrvSte_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 118 DrvSte_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 118 DrvSte_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 118 DrvSte_Tq_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 118 DrvSte_Tq_Rq 128; +BA_ "U_CX727_MY2021_Rx" SG_ 118 DrvSte_Tq_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 118 DrvSte_Tq_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 118 DrvSte_Tq_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 118 EmgcyBrkLamp_D_Rq 1; +BA_ "GenSigSendType" SG_ 118 EmgcyBrkLamp_D_Rq 3; +BA_ "U_CX727_MY2021_Tx" SG_ 118 EmgcyBrkLamp_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 118 EmgcyBrkLamp_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 118 StopLamp_B_RqBrk 1; +BA_ "GenSigSendType" SG_ 118 StopLamp_B_RqBrk 3; +BA_ "U_CX727_MY2021_Tx" SG_ 118 StopLamp_B_RqBrk 1; +BA_ "U_P702_MY2021_Tx" SG_ 118 StopLamp_B_RqBrk 1; +BA_ "UsedOnPgmDBC" SG_ 73 immoSubTarget1Data_T1 1; +BA_ "U_P702_MY2021_Rx" SG_ 73 immoSubTarget1Data_T1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 73 immoSubTarget1Data_T1 1; +BA_ "U_CX727_MY2021_Tx" SG_ 73 immoSubTarget1Data_T1 1; +BA_ "U_P702_MY2021_Tx" SG_ 73 immoSubTarget1Data_T1 1; +BA_ "UsedOnPgmDBC" SG_ 73 immoSubTarget1Cmd_T1 1; +BA_ "U_P702_MY2021_Rx" SG_ 73 immoSubTarget1Cmd_T1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 73 immoSubTarget1Cmd_T1 1; +BA_ "U_CX727_MY2021_Tx" SG_ 73 immoSubTarget1Cmd_T1 1; +BA_ "U_P702_MY2021_Tx" SG_ 73 immoSubTarget1Cmd_T1 1; +BA_ "CrossOver_InfoCAN" SG_ 1034 VehicleGGCCData 1; +BA_ "UsedOnPgmDBC" SG_ 1034 VehicleGGCCData 1; +BA_ "U_P702_MY2021_Rx" SG_ 1034 VehicleGGCCData 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1034 VehicleGGCCData 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1034 VehicleGGCCData 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1440 TCM_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_GWOnBoardTester 255; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_GWOnBoardTester 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1440 TCM_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_GWNMProxy 255; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_GWNMProxy 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_GWNMProxy 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1440 TCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_AutoSarNMReserved4 255; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_AutoSarNMReserved4 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1440 TCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_AutoSarNMReserved3 255; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_AutoSarNMReserved3 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1440 TCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_AutoSarNMReserved2 255; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_AutoSarNMReserved2 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1440 TCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_AutoSarNMReserved1 255; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_AutoSarNMReserved1 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1440 TCM_AutoSarNMNodeId 160; +BA_ "ContentDependant" SG_ 1440 TCM_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1440 TCM_AutoSarNMNodeId 160; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_AutoSarNMNodeId 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1440 TCM_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1440 TCM_AutoSarNMControl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1440 TCM_AutoSarNMControl 1; +BA_ "CrossOver_InfoCAN" SG_ 561 TrnMsgTxt2_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 561 TrnMsgTxt2_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 561 TrnMsgTxt2_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 561 TrnMsgTxt_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 561 TrnMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 561 TrnMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 561 TrnMsgTxt_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 330 TrnAout_W_ActlUnfilt 1; +BA_ "U_P702_MY2021_Rx" SG_ 330 TrnAout_W_ActlUnfilt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 330 TrnAout_W_ActlUnfilt 1; +BA_ "U_P702_MY2021_Tx" SG_ 330 TrnAout_W_ActlUnfilt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 330 TrnAout_W_ActlUnfilt 1; +BA_ "ECGUsedRxSignal" SG_ 1090 Mtr2State_D_ActlMntr 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1090 Mtr2State_D_ActlMntr 1; +BA_ "GenSigStartValueInteger" SG_ 1090 Inv1Ain_I_ActlMntr 32766; +BA_ "GenSigStartValue" SG_ 1090 Inv1Ain_I_ActlMntr 32765; +BA_ "ECGUsedRxSignal" SG_ 1090 Inv1Ain_I_ActlMntr 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1090 Inv1Ain_I_ActlMntr 1; +BA_ "ECGUsedRxSignal" SG_ 1090 HybVehMde_D_ActlMntr 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1090 HybVehMde_D_ActlMntr 1; +BA_ "ECGUsedRxSignal" SG_ 1090 ChrgStat_D_ActlMntr 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1090 ChrgStat_D_ActlMntr 1; +BA_ "CrossOver_InfoCAN" SG_ 1090 VehElRnge_L_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1090 VehElRnge_L_Dsply 4095; +BA_ "GenSigStartValue" SG_ 1090 VehElRnge_L_Dsply 4093; +BA_ "U_P702_MY2021_Tx" SG_ 1090 VehElRnge_L_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1090 VehElRnge_L_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 870 EngMdeMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 870 EffRgenThres_Pc_Dsply 1; +BA_ "GenSigStartValue" SG_ 870 EffRgenThres_Pc_Dsply 1023; +BA_ "CrossOver_InfoCAN" SG_ 870 EffRgenThres_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 870 RngPerChrgInst_L_Dsply 4094; +BA_ "GenSigStartValue" SG_ 870 RngPerChrgInst_L_Dsply 4093; +BA_ "U_P702_MY2021_Tx" SG_ 870 RngPerChrgInst_L_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 PwrFlowTxt_D_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 EngOnMsg2_D_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 EngOnMsg1_D_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 FuelMaintMde_D_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 869 EffWhlLvl2_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 869 EffWhlLvl2_Pc_Dsply 511; +BA_ "U_P702_MY2021_Tx" SG_ 869 EffWhlLvl2_Pc_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 869 EffWhlThres_Pc_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 EffWhlThres_Pc_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 869 EngPwLvl_Pc_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 EngPwLvl_Pc_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 869 EngActv_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 EngActv_B_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 869 EffWhlThresOn_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 869 EffWhlThresOn_B_Dsply 1; +BA_ "GenSigSendType" SG_ 606 ElVehLaterMde_D_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 606 ElVehLaterMde_D_Stat 1; +BA_ "GenSigSendType" SG_ 606 ElVehNowMde_D_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 606 ElVehNowMde_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 374 GearEngag_D_Actl 1; +BA_ "GenSigSendType" SG_ 374 GearEngag_D_Actl 3; +BA_ "U_P702_MY2021_Tx" SG_ 374 GearEngag_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 374 TrnRng_D_Rq 14; +BA_ "ContentDependant" SG_ 374 TrnRng_D_Rq 1; +BA_ "GenSigStartValue" SG_ 374 TrnRng_D_Rq 14; +BA_ "GenSigSendType" SG_ 374 TrnRng_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 374 TrnRng_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 TrnRng_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 TrnRng_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 TrnRng_D_Rq 1; +BA_ "ContentDependant" SG_ 374 TrnPrkSys_D_Actl 1; +BA_ "GenSigSendType" SG_ 374 TrnPrkSys_D_Actl 3; +BA_ "U_P702_MY2021_Rx" SG_ 374 TrnPrkSys_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 TrnPrkSys_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 TrnPrkSys_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 TrnPrkSys_D_Actl 1; +BA_ "ContentDependant" SG_ 374 GearLvr_D_ActlDrv 1; +BA_ "GenSigSendType" SG_ 374 GearLvr_D_ActlDrv 3; +BA_ "U_P702_MY2021_Rx" SG_ 374 GearLvr_D_ActlDrv 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 GearLvr_D_ActlDrv 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 GearLvr_D_ActlDrv 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 GearLvr_D_ActlDrv 1; +BA_ "ContentDependant" SG_ 374 GearPos_No_Cs 1; +BA_ "MetaData" SG_ 374 GearPos_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 374 GearPos_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 GearPos_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 374 GearPos_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 GearPos_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 GearPos_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 374 GearPos_D_Trg 1; +BA_ "UsedOnPgmDBC" SG_ 374 GearPos_D_Trg 1; +BA_ "GenSigStartValueInteger" SG_ 374 GearPos_D_Trg 15; +BA_ "ContentDependant" SG_ 374 GearPos_D_Trg 1; +BA_ "GenSigStartValue" SG_ 374 GearPos_D_Trg 15; +BA_ "GenSigSendType" SG_ 374 GearPos_D_Trg 3; +BA_ "U_P702_MY2021_Rx" SG_ 374 GearPos_D_Trg 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 GearPos_D_Trg 1; +BA_ "U_CX727_MY2021_Rx" SG_ 374 GearPos_D_Trg 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 GearPos_D_Trg 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 GearPos_D_Trg 1; +BA_ "ContentDependant" SG_ 374 GearPos_No_Cnt 1; +BA_ "MetaData" SG_ 374 GearPos_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 374 GearPos_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 GearPos_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 374 GearPos_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 GearPos_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 GearPos_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 TrnIgnOffDly_T_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 TrnIgnOffDly_T_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 374 GearPos_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 374 GearPos_D_Actl 15; +BA_ "ContentDependant" SG_ 374 GearPos_D_Actl 1; +BA_ "GenSigStartValue" SG_ 374 GearPos_D_Actl 15; +BA_ "GenSigSendType" SG_ 374 GearPos_D_Actl 3; +BA_ "U_P702_MY2021_Rx" SG_ 374 GearPos_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 374 GearPos_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 374 GearPos_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 374 GearPos_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 374 GearPos_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 603 WhlDirAvgDrv_D_Actl 1; +BA_ "ContentDependant" SG_ 603 WhlDirAvgDrv_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 603 WhlDirAvgDrv_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 603 PrplTqMnRgen_B_Actl 1; +BA_ "ContentDependant" SG_ 603 PrplTqMnRgen_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 603 PrplTqMnRgen_B_Actl 1; +BA_ "ContentDependant" SG_ 603 BattTracCnnct_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 603 BattTracCnnct_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 602 HtrnWarnLamp_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 602 HtrnWarnLamp_B_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 602 HtrnWarnLamp_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 602 HybPwLimOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 602 PwPckTqRdy_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 602 PwPckTqRdy_B_Dsply 1; +BA_ "GenSigSendType" SG_ 1152 BattTracDiagClr_B_Stat 3; +BA_ "GenSigSendType" SG_ 1152 EngTeHi_B_Actl 3; +BA_ "U_P702_MY2021_Tx" SG_ 1152 EngTeHi_B_Actl 1; +BA_ "GenSigSendType" SG_ 1152 DcdcOn_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1152 DcdcOn_B_Rq 1; +BA_ "GenSigSendType" SG_ 1152 ULoBattSpprtSustn_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1152 ULoBattSpprtSustn_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1152 VehElEff_No_Avg 126; +BA_ "GenSigStartValue" SG_ 1152 VehElEff_No_Avg 126; +BA_ "U_P702_MY2021_Tx" SG_ 1152 VehElEff_No_Avg 1; +BA_ "CrossOver_InfoCAN" SG_ 872 PlgActvArb_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 872 PlgActvArb_B_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 872 PlgActvArb_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 872 HybMdeStat_D_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 872 HybMdeStat_D_Dsply 1; +BA_ "ContentDependant" SG_ 560 SelDrvMdeSwtch_D_Stat3 1; +BA_ "U_P702_MY2021_Rx" SG_ 560 SelDrvMdeSwtch_D_Stat3 1; +BA_ "U_P702_MY2021_Tx" SG_ 560 SelDrvMdeSwtch_D_Stat3 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 560 SelDrvMdeSwtch_D_Stat3 1; +BA_ "CrossOver_InfoCAN" SG_ 560 TrnSrvcRqd_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 560 TrnSrvcRqd_B_Rq 1; +BA_ "ContentDependant" SG_ 560 TrnSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 560 TrnSrvcRqd_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 560 TrnSrvcRqd_B_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 560 TrnSrvcRqd_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "ContentDependant" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 560 TrnShifActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 560 GearLvrPos_D_Actl 14; +BA_ "GenSigStartValue" SG_ 560 GearLvrPos_D_Actl 14; +BA_ "U_P702_MY2021_Rx" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 560 GearLvrPos_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 560 GboxOil_Te_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 560 GboxOil_Te_Actl 254; +BA_ "ContentDependant" SG_ 560 GboxOil_Te_Actl 1; +BA_ "GenSigStartValue" SG_ 560 GboxOil_Te_Actl 254; +BA_ "U_P702_MY2021_Rx" SG_ 560 GboxOil_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 560 GboxOil_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 560 GboxOil_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 560 GboxOil_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 369 TrnIpcDsplyRng2_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 369 TrnIpcDsplyRng2_D_Actl 15; +BA_ "GenSigStartValue" SG_ 369 TrnIpcDsplyRng2_D_Actl 15; +BA_ "U_P702_MY2021_Tx" SG_ 369 TrnIpcDsplyRng2_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 369 TrnIpcDsplyRng2_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 369 TrnIpcDsplyRng_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 369 TrnIpcDsplyRng_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 369 TrnIpcDsplyGear_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 369 TrnIpcDsplyGear_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 369 TrnIpcDsplyGear_D_Actl 15; +BA_ "GenSigStartValue" SG_ 369 TrnIpcDsplyGear_D_Actl 15; +BA_ "U_P702_MY2021_Tx" SG_ 369 TrnIpcDsplyGear_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 369 TrnIpcDsplyGear_D_Actl 1; +BA_ "WakeupSignal" SG_ 369 TrnIpcDsplyMde_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 369 TrnIpcDsplyMde_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 369 TrnIpcDsplyMde_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 369 TrnIpcDsplyMde_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 369 TrnIpcDsplyMde_D_Stat 1; +BA_ "WakeupSignal" SG_ 369 TrnIpcDsplyMde_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 369 TrnIpcDsplyMde_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 369 TrnIpcDsplyMde_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 369 TrnIpcDsplyMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 369 TrnIpcDsplyMde_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 369 TrnIpcDsplyGear_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 369 TrnIpcDsplyGear_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 369 TrnIpcDsplyGear_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 369 TrnIpcDsplyGear_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 92 TrnLvrV_D_Rq 1; +BA_ "GenSigStartValue" SG_ 92 TrnLvrV_D_Rq 1; +BA_ "GenSigSendType" SG_ 92 TrnLvrV_D_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnLvrV_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnLvrV_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 92 TrnSbwSysHlth_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 92 TrnSbwSysHlth_D_Actl 1; +BA_ "ContentDependant" SG_ 92 TrnSbwSysHlth_D_Actl 1; +BA_ "GenSigStartValue" SG_ 92 TrnSbwSysHlth_D_Actl 1; +BA_ "GenSigSendType" SG_ 92 TrnSbwSysHlth_D_Actl 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnSbwSysHlth_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnSbwSysHlth_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 92 TrnGearNtmAllow_B_Stat 1; +BA_ "ContentDependant" SG_ 92 TrnGearNtmAllow_B_Stat 1; +BA_ "GenSigSendType" SG_ 92 TrnGearNtmAllow_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnGearNtmAllow_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnGearNtmAllow_B_Stat 1; +BA_ "WakeupSignal" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "ContentDependant" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "GenSigStartValue" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "GenSigSendType" SG_ 92 TrnDtpCmd_D_Actl 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnDtpCmd_D_Actl 1; +BA_ "GenSigSendType" SG_ 92 GearSelLck_D_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 GearSelLck_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 GearSelLck_D_Rq 1; +BA_ "ContentDependant" SG_ 92 TrnGearCmd_No_Cs 1; +BA_ "MetaData" SG_ 92 TrnGearCmd_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnGearCmd_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnGearCmd_No_Cs 1; +BA_ "ContentDependant" SG_ 92 TrnValidGear_D_Cnfm 1; +BA_ "GenSigSendType" SG_ 92 TrnValidGear_D_Cnfm 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnValidGear_D_Cnfm 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnValidGear_D_Cnfm 1; +BA_ "ContentDependant" SG_ 92 TrnNtrlTowCmd_D_Actl 1; +BA_ "GenSigSendType" SG_ 92 TrnNtrlTowCmd_D_Actl 3; +BA_ "U_CX727_MY2021_Rx" SG_ 92 TrnNtrlTowCmd_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 92 TrnNtrlTowCmd_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnNtrlTowCmd_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnNtrlTowCmd_D_Actl 1; +BA_ "ContentDependant" SG_ 92 TrnGearCmd_Pc_ActlPt 1; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnGearCmd_Pc_ActlPt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnGearCmd_Pc_ActlPt 1; +BA_ "ContentDependant" SG_ 92 TrnGear_D_RqPt 1; +BA_ "GenSigSendType" SG_ 92 TrnGear_D_RqPt 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnGear_D_RqPt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnGear_D_RqPt 1; +BA_ "ContentDependant" SG_ 92 TrnCmdState_B_Actl 1; +BA_ "GenSigSendType" SG_ 92 TrnCmdState_B_Actl 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnCmdState_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnCmdState_B_Actl 1; +BA_ "ContentDependant" SG_ 92 TrnCmdCnt_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnCmdCnt_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnCmdCnt_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "GenSigStartValueInteger" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "ContentDependant" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "GenSigStartValue" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "GenSigSendType" SG_ 92 PrkBrkActv_D_RqTrnGear 3; +BA_ "U_CX727_MY2021_Rx" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "U_P702_MY2021_Rx" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "U_P702_MY2021_Tx" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 PrkBrkActv_D_RqTrnGear 1; +BA_ "CrossOver_InfoCAN" SG_ 92 TrnGearMsgTxt_D_Rq 1; +BA_ "ContentDependant" SG_ 92 TrnGearMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 92 TrnGearMsgTxt_D_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnGearMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnGearMsgTxt_D_Rq 1; +BA_ "ContentDependant" SG_ 92 TrnGearCmd_No_Cnt 1; +BA_ "MetaData" SG_ 92 TrnGearCmd_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 92 TrnGearCmd_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 92 TrnGearCmd_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 2030 TesterPhysicalResSOBDMC 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 2030 TesterPhysicalResSOBDMC 1; +BA_ "U_P702_MY2021_Tx" SG_ 1087 BattRgenLoChrg_D_RqEng 1; +BA_ "GenSigSendType" SG_ 1087 BattRgenLoChrg_D_RqEng 3; +BA_ "GenSigSendType" SG_ 1087 AdasLcObtclAbrt_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1087 BattRgenLoDChrg_D_RqEng 1; +BA_ "GenSigSendType" SG_ 1087 BattRgenLoDChrg_D_RqEng 3; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 AirDamPos_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1087 AirDamPos_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1087 AirDamPos_D_Stat 1; +BA_ "GenSigSendType" SG_ 1087 FapLcInhbt_B_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcInhbt_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcInhbt_B_Rq 1; +BA_ "GenSigSendType" SG_ 1087 FapLcStopHold_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1087 FapLcStopHold_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1087 FapLcStopHold_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcStopHold_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcStopHold_B_Rq 1; +BA_ "GenSigSendType" SG_ 1087 FapLcPrchgBrk_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1087 FapLcPrchgBrk_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1087 FapLcPrchgBrk_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcPrchgBrk_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcPrchgBrk_B_Rq 1; +BA_ "GenSigSendType" SG_ 1087 FapLcObstcl_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcObstcl_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcObstcl_B_Stat 1; +BA_ "GenSigSendType" SG_ 1087 FapLcMaxGrdInhbt_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcMaxGrdInhbt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcMaxGrdInhbt_B_Stat 1; +BA_ "GenSigSendType" SG_ 1087 FapLcMaxGrdAbrt_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcMaxGrdAbrt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcMaxGrdAbrt_B_Stat 1; +BA_ "GenSigSendType" SG_ 1087 FapLcActv_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1087 FapLcActv_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1087 FapLcActv_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 332 UreaLvlQlty_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaLvlQlty_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaLvlQlty_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 332 UreaLvlTxtWarn_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaLvlTxtWarn_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaLvlTxtWarn_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 332 UreaQltySysWarn_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaQltySysWarn_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaQltySysWarn_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 DieslPrtcWarn_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 DieslPrtcWarn_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaQltyFlg_B_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaQltyFlg_B_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 332 UreaQltyFlg_B_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaLvl_Pc_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaLvl_Pc_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 332 UreaLvl_Pc_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 VehUreaRnge2_L_DsplyMx 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 VehUreaRnge2_L_DsplyMx 1; +BA_ "ECGUsedRxSignal" SG_ 332 VehUreaRnge2_L_DsplyMx 1; +BA_ "CrossOver_InfoCAN" SG_ 332 UreaQltySys_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaQltySys_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaQltySys_D_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 332 UreaQltySys_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 332 UreaLvlTxt_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 UreaLvlTxt_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 UreaLvlTxt_D_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 332 UreaLvlTxt_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 332 VehUreaWarn_V_DsplyMx 1; +BA_ "U_P702_MY2021_Tx" SG_ 332 VehUreaWarn_V_DsplyMx 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 332 VehUreaWarn_V_DsplyMx 1; +BA_ "ECGUsedRxSignal" SG_ 332 VehUreaWarn_V_DsplyMx 1; +BA_ "UsedOnPgmDBC" SG_ 1896 TesterPhysicalResABS 1; +BA_ "GenSigSendType" SG_ 1896 TesterPhysicalResABS 3; +BA_ "U_CX727_MY2021_Tx" SG_ 1896 TesterPhysicalResABS 1; +BA_ "U_P702_MY2021_Tx" SG_ 1896 TesterPhysicalResABS 1; +BA_ "GenSigSendType" SG_ 1889 TesterPhysicalReqTCCM 3; +BA_ "U_P702_MY2021_Rx" SG_ 1889 TesterPhysicalReqTCCM 1; +BA_ "UsedOnPgmDBC" SG_ 1888 TesterPhysicalReqABS 1; +BA_ "GenSigSendType" SG_ 1888 TesterPhysicalReqABS 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1888 TesterPhysicalReqABS 1; +BA_ "U_P702_MY2021_Rx" SG_ 1888 TesterPhysicalReqABS 1; +BA_ "UsedOnPgmDBC" SG_ 1848 TesterPhysicalResPSCM 1; +BA_ "U_CX727_MY2021_Tx" SG_ 1848 TesterPhysicalResPSCM 1; +BA_ "U_P702_MY2021_Tx" SG_ 1848 TesterPhysicalResPSCM 1; +BA_ "UsedOnPgmDBC" SG_ 1840 TesterPhysicalReqPSCM 1; +BA_ "GenSigSendType" SG_ 1840 TesterPhysicalReqPSCM 3; +BA_ "U_CX727_MY2021_Rx" SG_ 1840 TesterPhysicalReqPSCM 1; +BA_ "U_P702_MY2021_Rx" SG_ 1840 TesterPhysicalReqPSCM 1; +BA_ "UsedOnPgmDBC" SG_ 1713 UUDTABSResponse2 1; +BA_ "U_P702_MY2021_Tx" SG_ 1713 UUDTABSResponse2 1; +BA_ "UsedOnPgmDBC" SG_ 1712 UUDTABSResponse1 1; +BA_ "U_P702_MY2021_Tx" SG_ 1712 UUDTABSResponse1 1; +BA_ "UsedOnPgmDBC" SG_ 2025 TesterPhysicalResTCM 1; +BA_ "U_P702_MY2021_Tx" SG_ 2025 TesterPhysicalResTCM 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 2025 TesterPhysicalResTCM 1; +BA_ "UsedOnPgmDBC" SG_ 2024 TesterPhysicalResPCM 1; +BA_ "U_P702_MY2021_Tx" SG_ 2024 TesterPhysicalResPCM 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 2024 TesterPhysicalResPCM 1; +BA_ "UsedOnPgmDBC" SG_ 2017 TesterPhysicalReqTCM 1; +BA_ "GenSigSendType" SG_ 2017 TesterPhysicalReqTCM 3; +BA_ "U_P702_MY2021_Rx" SG_ 2017 TesterPhysicalReqTCM 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2017 TesterPhysicalReqTCM 1; +BA_ "UsedOnPgmDBC" SG_ 2016 TesterPhysicalReqPCM 1; +BA_ "GenSigSendType" SG_ 2016 TesterPhysicalReqPCM 3; +BA_ "U_P702_MY2021_Rx" SG_ 2016 TesterPhysicalReqPCM 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2016 TesterPhysicalReqPCM 1; +BA_ "CrossOver_InfoCAN" SG_ 2015 TesterFunctionalReq 1; +BA_ "UsedOnPgmDBC" SG_ 2015 TesterFunctionalReq 1; +BA_ "GenSigSendType" SG_ 2015 TesterFunctionalReq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 2015 TesterFunctionalReq 1; +BA_ "U_P702_MY2021_Rx" SG_ 2015 TesterFunctionalReq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 2015 TesterFunctionalReq 1; +BA_ "ECGUsedRxSignal" SG_ 2015 TesterFunctionalReq 1; +BA_ "GenSigSendType" SG_ 1897 TesterPhysicalResTCCM 3; +BA_ "U_P702_MY2021_Tx" SG_ 1897 TesterPhysicalResTCCM 1; +BA_ "GenSigSendType" SG_ 1814 TesterPhysicalReqGWM_F1 3; +BA_ "ECGUsedRxSignal" SG_ 1814 TesterPhysicalReqGWM_F1 1; +BA_ "UsedOnPgmDBC" SG_ 1701 UUDTTCMResponse2 1; +BA_ "U_P702_MY2021_Tx" SG_ 1701 UUDTTCMResponse2 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1701 UUDTTCMResponse2 1; +BA_ "UsedOnPgmDBC" SG_ 1700 UUDTTCMResponse1 1; +BA_ "U_P702_MY2021_Tx" SG_ 1700 UUDTTCMResponse1 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1700 UUDTTCMResponse1 1; +BA_ "UsedOnPgmDBC" SG_ 1697 UUDTPCMResponse2 1; +BA_ "U_P702_MY2021_Tx" SG_ 1697 UUDTPCMResponse2 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1697 UUDTPCMResponse2 1; +BA_ "UsedOnPgmDBC" SG_ 1696 UUDTPCMResponse1 1; +BA_ "U_P702_MY2021_Tx" SG_ 1696 UUDTPCMResponse1 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1696 UUDTPCMResponse1 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1429 PCM_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_GWOnBoardTester 255; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_GWOnBoardTester 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_GWOnBoardTester 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_GWOnBoardTester 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1429 PCM_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_GWNMProxy 255; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_GWNMProxy 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_GWNMProxy 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_GWNMProxy 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_GWNMProxy 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1429 PCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_AutoSarNMReserved4 255; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_AutoSarNMReserved4 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_AutoSarNMReserved4 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_AutoSarNMReserved4 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1429 PCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_AutoSarNMReserved3 255; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_AutoSarNMReserved3 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_AutoSarNMReserved3 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_AutoSarNMReserved3 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1429 PCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_AutoSarNMReserved2 255; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_AutoSarNMReserved2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_AutoSarNMReserved2 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_AutoSarNMReserved2 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1429 PCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_AutoSarNMReserved1 255; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_AutoSarNMReserved1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_AutoSarNMReserved1 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_AutoSarNMReserved1 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1429 PCM_AutoSarNMNodeId 149; +BA_ "ContentDependant" SG_ 1429 PCM_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1429 PCM_AutoSarNMNodeId 149; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_AutoSarNMNodeId 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_AutoSarNMNodeId 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_AutoSarNMNodeId 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1429 PCM_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1429 PCM_AutoSarNMControl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1429 PCM_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1429 PCM_AutoSarNMControl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1429 PCM_AutoSarNMControl 1; +BA_ "GenSigStartValueInteger" SG_ 1100 EngExhMdeQuiet_D2_Stat 0; +BA_ "GenSigSendType" SG_ 1100 EngExhMdeQuiet_D2_Stat 3; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1100 HvacCmprLim_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1100 HvacCmprLim_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1100 WakeAlarm1_T_Rq 32767; +BA_ "GenSigStartValue" SG_ 1100 WakeAlarm1_T_Rq 32767; +BA_ "U_P702_MY2021_Tx" SG_ 1100 WakeAlarm1_T_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1100 WakeAlarm1_T_Rq 1; +BA_ "WakeupSignal" SG_ 1100 WakeAlarm1_B_Typ 1; +BA_ "GenSigSendType" SG_ 1100 WakeAlarm1_B_Typ 3; +BA_ "U_P702_MY2021_Tx" SG_ 1100 WakeAlarm1_B_Typ 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1100 WakeAlarm1_B_Typ 1; +BA_ "GenSigSendType" SG_ 1100 Veh_V_DsplyTrailCtlSet 3; +BA_ "U_P702_MY2021_Tx" SG_ 1100 Veh_V_DsplyTrailCtlSet 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1100 Veh_V_DsplyTrailCtlSet 1; +BA_ "GenSigSendType" SG_ 1100 TrailCtlPt_B_Falt 3; +BA_ "U_P702_MY2021_Rx" SG_ 1100 TrailCtlPt_B_Falt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1100 TrailCtlPt_B_Falt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1100 TrailCtlPt_B_Falt 1; +BA_ "GenSigSendType" SG_ 1100 AutoTowAllw_D_StatMnu 3; +BA_ "U_P702_MY2021_Tx" SG_ 1100 AutoTowAllw_D_StatMnu 1; +BA_ "GenSigSendType" SG_ 1100 AutoTowActv_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1100 AutoTowActv_B_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1100 GrossTrainWeight_M_Est 254; +BA_ "GenSigStartValue" SG_ 1100 GrossTrainWeight_M_Est 254; +BA_ "U_P702_MY2021_Rx" SG_ 1100 GrossTrainWeight_M_Est 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1100 GrossTrainWeight_M_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1100 GrossTrainWeight_M_Est 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1100 GrossTrainWeight_M_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmVeh_V_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmVeh_V_Dsply 1; +BA_ "GenSigSendType" SG_ 1098 EdmSailMdeOn_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmSailMdeOn_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmSailMdeOn_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmPrev_Fe_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmPrev_Fe_Dsply 1; +BA_ "GenSigSendType" SG_ 1098 EdmMsgTxt_D_Rq 3; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 1098 EdmLamp_D_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmLamp_D_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmLamp_D_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmCurrent_Fe_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmCurrent_Fe_Dsply 1; +BA_ "GenSigSendType" SG_ 1098 EdmCmplnc_B_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmCmplnc_B_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmCmplnc_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1098 EdmCmplnc_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1098 EdmCmplnc_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1086 EngMnfld_P_Actl 2068; +BA_ "U_P702_MY2021_Tx" SG_ 1086 EngMnfld_P_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1086 EngMnfld_P_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1086 FuelPumpPwr_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1086 FuelPumpPwr_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1086 BattULoChrg_U_Cmd 1; +BA_ "U_P702_MY2021_Tx" SG_ 1086 BattULoChrg_U_Cmd 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1086 BattULoChrg_U_Cmd 1; +BA_ "UsedOnPgmDBC" SG_ 1086 ElLoadCtl_D_Rq 1; +BA_ "ContentDependant" SG_ 1086 ElLoadCtl_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1086 ElLoadCtl_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1086 ElLoadCtl_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1071 EngAout_N_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1071 EngAout_N_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 1071 CluPdl_PcRate_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1071 CluPdl_PcRate_Actl 1; +BA_ "ContentDependant" SG_ 1071 CluPdl_PcRate_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1071 CluPdl_PcRate_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1071 CluPdl_PcRate_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "ContentDependant" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "MetaData" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "GenSigStartValue" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1071 CluPdlPosPcMeas_D_Qf 1; +BA_ "CrossOver_InfoCAN" SG_ 1071 CluPdlPos_Pc_Meas 1; +BA_ "UsedOnPgmDBC" SG_ 1071 CluPdlPos_Pc_Meas 1; +BA_ "ContentDependant" SG_ 1071 CluPdlPos_Pc_Meas 1; +BA_ "U_P702_MY2021_Rx" SG_ 1071 CluPdlPos_Pc_Meas 1; +BA_ "U_P702_MY2021_Tx" SG_ 1071 CluPdlPos_Pc_Meas 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1071 CluPdlPos_Pc_Meas 1; +BA_ "CrossOver_InfoCAN" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "UsedOnPgmDBC" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "ContentDependant" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1071 EngAoutIdl_N_Ntrl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 SlMde_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 SlMde_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 SlMde_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 SlMde_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 IsaOffst_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 IsaOffst_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 GrllShtrPos_D_Cmd 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 GrllShtrPos_D_Cmd 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 GrllShtrPos_D_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 GrllShtrPos_B_Falt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 GrllShtrPos_B_Falt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 GrllShtrPos_B_Falt 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 ObdWarmUp_B_Complt 1; +BA_ "ContentDependant" SG_ 1069 ObdWarmUp_B_Complt 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 ObdWarmUp_B_Complt 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 EngMsgTxt_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1069 EngMsgTxt_D_Rq 1; +BA_ "ContentDependant" SG_ 1069 EngMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 EngMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 EngMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 EngClnt_Te_ActlDiag 1; +BA_ "ContentDependant" SG_ 1069 EngClnt_Te_ActlDiag 1; +BA_ "U_P702_MY2021_Rx" SG_ 1069 EngClnt_Te_ActlDiag 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1069 EngClnt_Te_ActlDiag 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 EngClnt_Te_ActlDiag 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 EngClnt_Te_ActlDiag 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 EngLoad_Pc_CalcDiag 1; +BA_ "ContentDependant" SG_ 1069 EngLoad_Pc_CalcDiag 1; +BA_ "U_P702_MY2021_Rx" SG_ 1069 EngLoad_Pc_CalcDiag 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1069 EngLoad_Pc_CalcDiag 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 EngLoad_Pc_CalcDiag 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 EngLoad_Pc_CalcDiag 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 EngAirIn_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1069 EngAirIn_Te_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1069 EngAirIn_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1069 EngAirIn_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 EngAirIn_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 EngAirIn_Te_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1069 ApedPos_Pc_ActlDiag 1; +BA_ "ContentDependant" SG_ 1069 ApedPos_Pc_ActlDiag 1; +BA_ "U_P702_MY2021_Rx" SG_ 1069 ApedPos_Pc_ActlDiag 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1069 ApedPos_Pc_ActlDiag 1; +BA_ "U_P702_MY2021_Tx" SG_ 1069 ApedPos_Pc_ActlDiag 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1069 ApedPos_Pc_ActlDiag 1; +BA_ "U_P702_MY2021_Tx" SG_ 1060 RearDiffOilTeWarn_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 RearDiffOilTeWarn_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1060 RearDiffOil_Te_Actl 77; +BA_ "GenSigStartValue" SG_ 1060 RearDiffOil_Te_Actl 77; +BA_ "U_P702_MY2021_Tx" SG_ 1060 RearDiffOil_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 RearDiffOil_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1060 BpedDrvMsgTxt_B_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 BpedDrvMsgTxt_B_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1060 FuelLvl_Pc_DsplyEng 48; +BA_ "GenSigStartValue" SG_ 1060 FuelLvl_Pc_DsplyEng 0; +BA_ "U_P702_MY2021_Tx" SG_ 1060 FuelLvl_Pc_DsplyEng 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 FuelLvl_Pc_DsplyEng 1; +BA_ "U_P702_MY2021_Tx" SG_ 1060 FuelLvlWarn_D_ActlEng 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 FuelLvlWarn_D_ActlEng 1; +BA_ "U_P702_MY2021_Tx" SG_ 1060 FuelRange_L_DsplyEng 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 FuelRange_L_DsplyEng 1; +BA_ "U_P702_MY2021_Rx" SG_ 1060 SelDrvMdePt_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1060 SelDrvMdePt_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1060 SelDrvMdePt_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 FohEng_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1057 FohEng_D_Rq 2; +BA_ "ContentDependant" SG_ 1057 FohEng_D_Rq 1; +BA_ "GenSigStartValue" SG_ 1057 FohEng_D_Rq 2; +BA_ "U_P702_MY2021_Tx" SG_ 1057 FohEng_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 FohEng_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 EngIdlShutDwnTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 EngIdlShutDwnTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 EngIdlShutDown_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1057 EngIdlShutDown_D_Stat 1; +BA_ "ContentDependant" SG_ 1057 EngIdlShutDown_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 EngIdlShutDown_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 EngIdlShutDown_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 1057 EngIdlShutDown_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 FUEL_ALCOHOL_PERCNT 1; +BA_ "GenSigStartValueInteger" SG_ 1057 FUEL_ALCOHOL_PERCNT 255; +BA_ "ContentDependant" SG_ 1057 FUEL_ALCOHOL_PERCNT 1; +BA_ "GenSigStartValue" SG_ 1057 FUEL_ALCOHOL_PERCNT 255; +BA_ "U_P702_MY2021_Tx" SG_ 1057 FUEL_ALCOHOL_PERCNT 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 FUEL_ALCOHOL_PERCNT 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 TrnTotTq_Rt_Est 1; +BA_ "UsedOnPgmDBC" SG_ 1057 TrnTotTq_Rt_Est 1; +BA_ "ContentDependant" SG_ 1057 TrnTotTq_Rt_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 TrnTotTq_Rt_Est 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 TrnTotTq_Rt_Est 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 TrnTotLss_Tq_Est 1; +BA_ "UsedOnPgmDBC" SG_ 1057 TrnTotLss_Tq_Est 1; +BA_ "ContentDependant" SG_ 1057 TrnTotLss_Tq_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 TrnTotLss_Tq_Est 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 TrnTotLss_Tq_Est 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 ECMMILRequest 1; +BA_ "UsedOnPgmDBC" SG_ 1057 ECMMILRequest 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 ECMMILRequest 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 ECMMILRequest 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 AirCondFluidHi_P_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1057 AirCondFluidHi_P_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 AirCondFluidHi_P_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 AirCondFluidHi_P_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 OilPressureWarning 1; +BA_ "UsedOnPgmDBC" SG_ 1057 OilPressureWarning 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 OilPressureWarning 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 OilPressureWarning 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "ContentDependant" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 VehVLimStat_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "ContentDependant" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 VehVLimActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1057 CoolantFanStepAct 1; +BA_ "UsedOnPgmDBC" SG_ 1057 CoolantFanStepAct 1; +BA_ "U_P702_MY2021_Tx" SG_ 1057 CoolantFanStepAct 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1057 CoolantFanStepAct 1; +BA_ "CrossOver_InfoCAN" SG_ 1055 EcoCochInstNeg_B_Dsply 1; +BA_ "UsedOnPgmDBC" SG_ 1055 EcoCochInstNeg_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochInstNeg_B_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochInstNeg_B_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochInstNeg_B_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1055 EcoCochShif_Pc_Dsply 255; +BA_ "GenSigStartValue" SG_ 1055 EcoCochShif_Pc_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochShif_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochShif_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochShif_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1055 EcoCochInst_Pc_Dsply 1000; +BA_ "GenSigStartValue" SG_ 1055 EcoCochInst_Pc_Dsply 100; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochInst_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochInst_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochInst_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1055 EcoCochIdlFuel_Pc_Dsply 255; +BA_ "GenSigStartValue" SG_ 1055 EcoCochIdlFuel_Pc_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochIdlFuel_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochIdlFuel_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochIdlFuel_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1055 EcoCochDecel_Pc_Dsply 255; +BA_ "GenSigStartValue" SG_ 1055 EcoCochDecel_Pc_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochDecel_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochDecel_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochDecel_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1055 EcoCochCrus_Pc_Dsply 255; +BA_ "GenSigStartValue" SG_ 1055 EcoCochCrus_Pc_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochCrus_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochCrus_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochCrus_Pc_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1055 EcoCochA_Pc_Dsply 255; +BA_ "GenSigStartValue" SG_ 1055 EcoCochA_Pc_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 1055 EcoCochA_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 1055 EcoCochA_Pc_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 1055 EcoCochA_Pc_Dsply 1; +BA_ "ContentDependant" SG_ 562 GearNtrl_No_Cs 1; +BA_ "MetaData" SG_ 562 GearNtrl_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 562 GearNtrl_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 562 GearNtrl_No_Cs 1; +BA_ "ContentDependant" SG_ 562 GearNtrl_No_Cnt 1; +BA_ "MetaData" SG_ 562 GearNtrl_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 562 GearNtrl_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 562 GearNtrl_No_Cnt 1; +BA_ "GenSigStartValueInteger" SG_ 562 GearNtrl_D_Stat 2; +BA_ "GenSigStartValue" SG_ 562 GearNtrl_D_Stat 2; +BA_ "GenSigSendType" SG_ 562 GearNtrl_D_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 562 GearNtrl_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 562 GearNtrl_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 523 EngAirFiltMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 523 EngAirFiltMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 523 WaterInFuel_B_Falt 1; +BA_ "UsedOnPgmDBC" SG_ 523 WaterInFuel_B_Falt 1; +BA_ "U_P702_MY2021_Tx" SG_ 523 WaterInFuel_B_Falt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 523 WaterInFuel_B_Falt 1; +BA_ "U_P702_MY2021_Tx" SG_ 523 UreaMnAdd_L2_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 523 UreaMnAdd_L2_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 523 VehUreaRnge3_L_DsplyMx 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 523 VehUreaRnge3_L_DsplyMx 1; +BA_ "ECGUsedRxSignal" SG_ 523 VehUreaRnge3_L_DsplyMx 1; +BA_ "GenSigStartValueInteger" SG_ 523 UreaMxAdd_L2_Actl 510; +BA_ "GenSigStartValue" SG_ 523 UreaMxAdd_L2_Actl 510; +BA_ "U_P702_MY2021_Tx" SG_ 523 UreaMxAdd_L2_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 523 UreaMxAdd_L2_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 517 FapLc_B_Err 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 517 FapLc_B_Err 1; +BA_ "U_CX727_MY2021_Rx" SG_ 517 BrkTot_Tq_RqFapLc 1; +BA_ "U_P702_MY2021_Rx" SG_ 517 BrkTot_Tq_RqFapLc 1; +BA_ "U_P702_MY2021_Tx" SG_ 517 BrkTot_Tq_RqFapLc 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 517 BrkTot_Tq_RqFapLc 1; +BA_ "U_P702_MY2021_Tx" SG_ 517 TrnAin_Pc_RqDrv 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 517 TrnAin_Pc_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "UsedOnPgmDBC" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "GenSigStartValueInteger" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "MetaData" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "GenSigStartValue" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "U_P702_MY2021_Rx" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 EngAoutNActl_D_QF 1; +BA_ "CrossOver_InfoCAN" SG_ 516 EngAout3_N_Actl 1; +BA_ "ContentDependant" SG_ 516 EngAout3_N_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 EngAout3_N_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 516 ApedPos_PcRate_ActlArb 1; +BA_ "UsedOnPgmDBC" SG_ 516 ApedPos_PcRate_ActlArb 1; +BA_ "U_P702_MY2021_Rx" SG_ 516 ApedPos_PcRate_ActlArb 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 516 ApedPos_PcRate_ActlArb 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 ApedPos_PcRate_ActlArb 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 ApedPos_PcRate_ActlArb 1; +BA_ "CrossOver_InfoCAN" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "UsedOnPgmDBC" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "U_P702_MY2021_Rx" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "U_CX727_MY2021_Rx" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "ECGUsedRxSignal" SG_ 516 ApedPos_Pc_ActlArb 1; +BA_ "CrossOver_InfoCAN" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "MetaData" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 ApedPosPcActl_D_Qf 1; +BA_ "CrossOver_InfoCAN" SG_ 516 EngAout_N_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 516 EngAout_N_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 516 EngAout_N_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 516 EngAout_N_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 516 EngAout_N_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 EngAout_N_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 EngAout_N_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 516 EngAout_N_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 516 ApedPosPcActl_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 516 ApedPosPcActl_No_Cnt 1; +BA_ "ContentDependant" SG_ 516 ApedPosPcActl_No_Cnt 1; +BA_ "MetaData" SG_ 516 ApedPosPcActl_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 ApedPosPcActl_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 ApedPosPcActl_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 516 ApedPosPcActl_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 516 ApedPosPcActl_No_Cs 1; +BA_ "ContentDependant" SG_ 516 ApedPosPcActl_No_Cs 1; +BA_ "MetaData" SG_ 516 ApedPosPcActl_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 516 ApedPosPcActl_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 516 ApedPosPcActl_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 StrtrMtrDlyStrt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 StrtrMtrDlyStrt_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 VehVTrlrAid_B_Avail 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 VehVTrlrAid_B_Avail 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 VehVTrlrAid_B_Avail 1; +BA_ "CrossOver_InfoCAN" SG_ 514 StrtrMtrCtlMsgTxt_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 514 StrtrMtrCtlMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 StrtrMtrCtlMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 StrtrMtrCtlMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "MetaData" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 VehVActlEng_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "MetaData" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 VehVActlEng_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 514 Veh_V_RqCcSet 1; +BA_ "UsedOnPgmDBC" SG_ 514 Veh_V_RqCcSet 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 Veh_V_RqCcSet 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 514 Veh_V_RqCcSet 1; +BA_ "U_CX727_MY2021_Rx" SG_ 514 Veh_V_RqCcSet 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 Veh_V_RqCcSet 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 Veh_V_RqCcSet 1; +BA_ "CrossOver_InfoCAN" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "MetaData" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 VehVActlEng_D_Qf 1; +BA_ "CrossOver_InfoCAN" SG_ 514 Veh_V_ActlEng 1; +BA_ "UsedOnPgmDBC" SG_ 514 Veh_V_ActlEng 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 Veh_V_ActlEng 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 514 Veh_V_ActlEng 1; +BA_ "U_CX727_MY2021_Rx" SG_ 514 Veh_V_ActlEng 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 Veh_V_ActlEng 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 Veh_V_ActlEng 1; +BA_ "ECGUsedRxSignal" SG_ 514 Veh_V_ActlEng 1; +BA_ "CrossOver_InfoCAN" SG_ 514 GearRvrse_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 514 GearRvrse_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 514 GearRvrse_D_Actl 7; +BA_ "GenSigStartValue" SG_ 514 GearRvrse_D_Actl 7; +BA_ "U_CX727_MY2021_Rx" SG_ 514 GearRvrse_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 514 GearRvrse_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 GearRvrse_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 GearRvrse_D_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 514 GearRvrse_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 514 StrtrMtrCtlMsgTxt_D2_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 514 StrtrMtrCtlMsgTxt_D2_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 512 PrplWhlTotTqRq_No_Cs 1; +BA_ "ContentDependant" SG_ 512 PrplWhlTotTqRq_No_Cs 1; +BA_ "MetaData" SG_ 512 PrplWhlTotTqRq_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 512 PrplWhlTotTqRq_No_Cs 1; +BA_ "U_P702_MY2021_Tx" SG_ 512 PrplWhlTotTqRq_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 512 PrplWhlTotTqRq_No_Cnt 1; +BA_ "ContentDependant" SG_ 512 PrplWhlTotTqRq_No_Cnt 1; +BA_ "MetaData" SG_ 512 PrplWhlTotTqRq_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 512 PrplWhlTotTqRq_No_Cnt 1; +BA_ "U_P702_MY2021_Tx" SG_ 512 PrplWhlTotTqRq_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 512 PrplWhlTot_Tq_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 512 PrplWhlTot_Tq_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 512 PrplWhlTot_Tq_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 512 PrplWhlTot_Tq_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 512 PrplWhlTot_Tq_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 512 PrplWhlTot_Tq_LimMn 1; +BA_ "U_CX727_MY2021_Rx" SG_ 512 PrplWhlTot_Tq_LimMn 1; +BA_ "U_P702_MY2021_Rx" SG_ 512 PrplWhlTot_Tq_LimMn 1; +BA_ "U_P702_MY2021_Tx" SG_ 512 PrplWhlTot_Tq_LimMn 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 512 PrplWhlTot_Tq_LimMn 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 512 PtDrvMde_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 512 PtDrvMde_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 381 EngOilLife_T_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 381 EngOilLife_T_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 381 EngOilSrvcMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 381 EngOilSrvcMsgTxt_D_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 381 EngOilSrvcMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 381 DistToNextOilChange 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 381 DistToNextOilChange 1; +BA_ "U_P702_MY2021_Tx" SG_ 381 RunDryPrevent_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 381 RunDryPrevent_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 381 WaterInFuel 1; +BA_ "UsedOnPgmDBC" SG_ 381 WaterInFuel 1; +BA_ "U_P702_MY2021_Tx" SG_ 381 WaterInFuel 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 381 WaterInFuel 1; +BA_ "ECGUsedRxSignal" SG_ 381 WaterInFuel 1; +BA_ "CrossOver_InfoCAN" SG_ 381 GlowIndication 1; +BA_ "UsedOnPgmDBC" SG_ 381 GlowIndication 1; +BA_ "U_P702_MY2021_Tx" SG_ 381 GlowIndication 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 381 GlowIndication 1; +BA_ "WakeupSignal" SG_ 380 EngOilLvlWarn_D_Rq1 1; +BA_ "CrossOver_InfoCAN" SG_ 380 EngOilLvlWarn_D_Rq1 1; +BA_ "U_P702_MY2021_Tx" SG_ 380 EngOilLvlWarn_D_Rq1 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 380 EngOilLvlWarn_D_Rq1 1; +BA_ "CrossOver_InfoCAN" SG_ 380 EngExhBrkOnLamp_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 380 EngExhBrkOnLamp_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 380 EngExhBrkOnLamp_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 380 EngExhBrkAutoLamp_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 380 EngExhBrkAutoLamp_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 380 EngExhBrkAutoLamp_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 380 EngAout_N_MxAllw 1; +BA_ "UsedOnPgmDBC" SG_ 380 EngAout_N_MxAllw 1; +BA_ "U_P702_MY2021_Tx" SG_ 380 EngAout_N_MxAllw 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 380 EngAout_N_MxAllw 1; +BA_ "CrossOver_InfoCAN" SG_ 380 EngExhBrkMde_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 380 EngExhBrkMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 380 EngExhBrkMde_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 380 EngExhBrkMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 380 EngExhBrkMde_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 377 HvacAirFullOut_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 HvacAirFullOut_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 377 FuelFlw_Vl_Dsply 1; +BA_ "UsedOnPgmDBC" SG_ 377 FuelFlw_Vl_Dsply 1; +BA_ "ContentDependant" SG_ 377 FuelFlw_Vl_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 FuelFlw_Vl_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 FuelFlw_Vl_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 377 FuelFlw_Vl_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 377 FuelFillInlet_B_Dsply 1; +BA_ "UsedOnPgmDBC" SG_ 377 FuelFillInlet_B_Dsply 1; +BA_ "ContentDependant" SG_ 377 FuelFillInlet_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 FuelFillInlet_B_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 FuelFillInlet_B_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 377 EngSrvcRqd_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 377 EngSrvcRqd_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 EngSrvcRqd_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 EngSrvcRqd_B_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 377 EngSrvcRqd_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 377 OdoCount 1; +BA_ "UsedOnPgmDBC" SG_ 377 OdoCount 1; +BA_ "ContentDependant" SG_ 377 OdoCount 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 OdoCount 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 OdoCount 1; +BA_ "CrossOver_InfoCAN" SG_ 377 EngOilLife_Pc_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 377 EngOilLife_Pc_Actl 1; +BA_ "ContentDependant" SG_ 377 EngOilLife_Pc_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 EngOilLife_Pc_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 EngOilLife_Pc_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 377 EngOilLife_Pc_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 377 FuelFilterLamp_B_Dsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 FuelFilterLamp_B_Dsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 FuelFilterLamp_B_Dsply 1; +BA_ "ECGUsedRxSignal" SG_ 377 FuelFilterLamp_B_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 377 AirCondRec_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 377 AirCondRec_B_Rq 1; +BA_ "ContentDependant" SG_ 377 AirCondRec_B_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 AirCondRec_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 AirCondRec_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 377 AirCondClutch_B_Stats 1; +BA_ "UsedOnPgmDBC" SG_ 377 AirCondClutch_B_Stats 1; +BA_ "ContentDependant" SG_ 377 AirCondClutch_B_Stats 1; +BA_ "U_P702_MY2021_Tx" SG_ 377 AirCondClutch_B_Stats 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 377 AirCondClutch_B_Stats 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 GasPrtc_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 GasPrtc_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 376 EngAout_Aa_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 376 EngAout_Aa_Actl 1; +BA_ "ContentDependant" SG_ 376 EngAout_Aa_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 376 EngAout_Aa_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 376 EngAout_Aa_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 EngAout_Aa_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 EngAout_Aa_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 376 DynoMde_B_Cmd 1; +BA_ "U_P702_MY2021_Rx" SG_ 376 DynoMde_B_Cmd 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 376 DynoMde_B_Cmd 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 DynoMde_B_Cmd 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 DynoMde_B_Cmd 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 AslIconDsply_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 AslIconDsply_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 AslChime_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 AslChime_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 376 HvacHtrCore2_Te_Actl 200; +BA_ "U_P702_MY2021_Tx" SG_ 376 HvacHtrCore2_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 EcssLamp_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 EcssLamp_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "MetaData" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "GenSigStartValue" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 AirAmbTe_D_Qf 1; +BA_ "CrossOver_InfoCAN" SG_ 376 AirAmb_Te_ActlFilt 1; +BA_ "UsedOnPgmDBC" SG_ 376 AirAmb_Te_ActlFilt 1; +BA_ "GenSigStartValueInteger" SG_ 376 AirAmb_Te_ActlFilt 512; +BA_ "U_P702_MY2021_Tx" SG_ 376 AirAmb_Te_ActlFilt 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 AirAmb_Te_ActlFilt 1; +BA_ "ECGUsedRxSignal" SG_ 376 AirAmb_Te_ActlFilt 1; +BA_ "CrossOver_InfoCAN" SG_ 376 AirAmb_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 376 AirAmb_Te_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 376 AirAmb_Te_Actl 512; +BA_ "U_P702_MY2021_Rx" SG_ 376 AirAmb_Te_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 376 AirAmb_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 AirAmb_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 AirAmb_Te_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 376 AirAmb_P_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 376 AirAmb_P_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 376 AirAmb_P_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 376 AirAmb_P_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 376 AirAmb_P_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 373 DieslPrtc2_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 373 DieslPrtc2_D_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 373 DieslPrtc2_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 373 DieslPrtcRgen_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 373 DieslPrtcRgen_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 373 DieslPrtcRgen_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 373 DieslPrtcRgen_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 373 DieslPrtcRgen_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 373 DieslPrtcRgen_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 373 EngTeColdPrtct_D_Stats 1; +BA_ "UsedOnPgmDBC" SG_ 373 EngTeColdPrtct_D_Stats 1; +BA_ "U_P702_MY2021_Tx" SG_ 373 EngTeColdPrtct_D_Stats 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 373 EngTeColdPrtct_D_Stats 1; +BA_ "CrossOver_InfoCAN" SG_ 373 EngExhOvrTe_B_RqDsply 1; +BA_ "UsedOnPgmDBC" SG_ 373 EngExhOvrTe_B_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 373 EngExhOvrTe_B_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 373 EngExhOvrTe_B_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 373 EngExhOvrTe_B_RqDsply 1; +BA_ "GenSigStartValueInteger" SG_ 359 PrplWhlRgenMn_Tq_Actl 4095; +BA_ "U_CX727_MY2021_Rx" SG_ 359 PrplWhlRgenMn_Tq_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 PrplWhlRgenMn_Tq_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 PrplWhlRgenMn_Tq_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 359 ElPw_D_StatStrtStop 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 ElPw_D_StatStrtStop 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 ElPw_D_StatStrtStop 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 ElPw_D_StatStrtStop 1; +BA_ "CrossOver_InfoCAN" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "ContentDependant" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 TrnAin_Tq_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 359 PrplWhlTot2_Tq_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 359 PwPckTq_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 359 PwPckTq_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 PwPckTq_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 359 PwPckTq_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 359 PwPckTq_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 PwPckTq_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 PwPckTq_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 359 PwPckTq_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 359 Eng_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 359 Eng_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 359 Eng_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 Eng_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 Eng_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 Eng_D_Stat 1; +BA_ "ECGUsedRxSignal" SG_ 359 Eng_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 359 PlgActvArb_B_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 359 PlgActvArb_B_Actl 1; +BA_ "ContentDependant" SG_ 359 PlgActvArb_B_Actl 1; +BA_ "GenSigStartValue" SG_ 359 PlgActvArb_B_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 359 PlgActvArb_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 359 ElPw_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 359 ElPw_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 ElPw_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 359 ElPw_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 359 ElPw_D_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 ElPw_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 ElPw_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "ContentDependant" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "MetaData" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 359 TrnAinTq_D_Qf 1; +BA_ "CrossOver_InfoCAN" SG_ 358 StopStrtStdby_D_Indic 1; +BA_ "GenSigStartValueInteger" SG_ 358 StopStrtStdby_D_Indic 0; +BA_ "U_P702_MY2021_Tx" SG_ 358 StopStrtStdby_D_Indic 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 StopStrtStdby_D_Indic 1; +BA_ "CrossOver_InfoCAN" SG_ 358 StopStrtIODTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 358 StopStrtIODTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 StopStrtIODTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 358 StopStrtDrvMde_D_Indic 1; +BA_ "U_P702_MY2021_Tx" SG_ 358 StopStrtDrvMde_D_Indic 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 StopStrtDrvMde_D_Indic 1; +BA_ "CrossOver_InfoCAN" SG_ 358 StopStrtMsgTxt_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 358 StopStrtMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 StopStrtMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 358 OdoTripVerify_L_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 358 OdoTripVerify_L_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 OdoTripVerify_L_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 358 HiElPwInhbt_B_Stat 1; +BA_ "ContentDependant" SG_ 358 HiElPwInhbt_B_Stat 1; +BA_ "U_P702_MY2021_Tx" SG_ 358 HiElPwInhbt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 HiElPwInhbt_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 358 AutoStopPtDelta_I_Est 1; +BA_ "GenSigStartValueInteger" SG_ 358 AutoStopPtDelta_I_Est 127; +BA_ "ContentDependant" SG_ 358 AutoStopPtDelta_I_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 358 AutoStopPtDelta_I_Est 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 358 AutoStopPtDelta_I_Est 1; +BA_ "UsedOnPgmDBC" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "GenSigStartValueInteger" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "MetaData" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "GenSigStartValue" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "U_P702_MY2021_Rx" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "U_CX727_MY2021_Rx" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 BPedDrvAppl_D_QF 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 CmbbDeny_B_ActlPrpl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 CmbbDeny_B_ActlPrpl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 PrplTqMnSat_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 PrplTqMnSat_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "GenSigStartValue" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 357 BpedDrvAppl_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 CmbbEngTqMn_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 CmbbEngTqMn_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 357 Veh_V_DsplyCcSet 1; +BA_ "UsedOnPgmDBC" SG_ 357 Veh_V_DsplyCcSet 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 Veh_V_DsplyCcSet 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 Veh_V_DsplyCcSet 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 AccEngStat_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 AccEngStat_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 357 CcMde_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 357 CcMde_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 357 CcMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 357 CcMde_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 CcMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 CcMde_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 357 CcStat_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 357 CcStat_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 357 CcStat_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 357 CcStat_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 357 CcStat_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 CcStat_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 CcStat_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 EngAout_N_MnAllw 1; +BA_ "CrossOver_InfoCAN" SG_ 357 CcOvrrdActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 357 CcOvrrdActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 357 CcOvrrdActv_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 357 CcOvrrdActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 CcOvrrdActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 CcOvrrdActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 357 AccStopMde_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 357 AccStopMde_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 357 AccStopMde_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 357 AccStopMde_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 357 AccStopMde_D_Rq 1; +BA_ "U_P702_MY2021_Tx" SG_ 355 AutoRgenTxt_B_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 355 AutoRgenTxt_B_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 355 AutoRgenTxt_B_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 355 AccFllwMdeActv_B_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 355 AccFllwMdeActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 355 AccFllwMdeActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 355 EngPtoMde_D_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 355 EngPtoMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 355 EngPtoMde_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 355 ManRgenTxt_D_RqDsply 1; +BA_ "UsedOnPgmDBC" SG_ 355 ManRgenTxt_D_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 355 ManRgenTxt_D_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 355 ManRgenTxt_D_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 355 ManRgenTxt_D_RqDsply 1; +BA_ "CrossOver_InfoCAN" SG_ 355 ManRgenSoot_Pc_RqDsply 1; +BA_ "UsedOnPgmDBC" SG_ 355 ManRgenSoot_Pc_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 355 ManRgenSoot_Pc_RqDsply 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 355 ManRgenSoot_Pc_RqDsply 1; +BA_ "ECGUsedRxSignal" SG_ 355 ManRgenSoot_Pc_RqDsply 1; +BA_ "U_P702_MY2021_Tx" SG_ 355 DieslMsgTxt_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 355 DieslMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 342 EngOvrhtMitgActv_D_Ind 1; +BA_ "UsedOnPgmDBC" SG_ 342 EngOvrhtMitgActv_D_Ind 1; +BA_ "ContentDependant" SG_ 342 EngOvrhtMitgActv_D_Ind 1; +BA_ "U_P702_MY2021_Tx" SG_ 342 EngOvrhtMitgActv_D_Ind 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 342 EngOvrhtMitgActv_D_Ind 1; +BA_ "CrossOver_InfoCAN" SG_ 342 EngClntTe_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 342 EngClntTe_D_Qf 1; +BA_ "MetaData" SG_ 342 EngClntTe_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 342 EngClntTe_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 342 EngClntTe_D_Qf 1; +BA_ "U_P702_MY2021_Tx" SG_ 342 EngClntTe_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 342 EngClntTe_D_Qf 1; +BA_ "CrossOver_InfoCAN" SG_ 342 EngGoutLss_Tq_Est 1; +BA_ "ContentDependant" SG_ 342 EngGoutLss_Tq_Est 1; +BA_ "U_P702_MY2021_Tx" SG_ 342 EngGoutLss_Tq_Est 1; +BA_ "CrossOver_InfoCAN" SG_ 342 EngOil_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 342 EngOil_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 342 EngOil_Te_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 342 EngClnt_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 342 EngClnt_Te_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 342 EngClnt_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 342 EngClnt_Te_Actl 1; +BA_ "U_P702_MY2021_Tx" SG_ 342 EngClnt_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 342 EngClnt_Te_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 342 EngClnt_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 71 immoTarget1Status 1; +BA_ "U_P702_MY2021_Rx" SG_ 71 immoTarget1Status 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 71 immoTarget1Status 1; +BA_ "U_CX727_MY2021_Rx" SG_ 71 immoTarget1Status 1; +BA_ "U_P702_MY2021_Tx" SG_ 71 immoTarget1Status 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 71 immoTarget1Status 1; +BA_ "UsedOnPgmDBC" SG_ 71 immoTarget1Data 1; +BA_ "U_CX727_MY2021_Rx" SG_ 71 immoTarget1Data 1; +BA_ "U_P702_MY2021_Rx" SG_ 71 immoTarget1Data 1; +BA_ "U_P702_MY2021_Tx" SG_ 71 immoTarget1Data 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 71 immoTarget1Data 1; +BA_ "UsedOnPgmDBC" SG_ 71 immoTarget1Cmd 1; +BA_ "U_CX727_MY2021_Rx" SG_ 71 immoTarget1Cmd 1; +BA_ "U_P702_MY2021_Rx" SG_ 71 immoTarget1Cmd 1; +BA_ "U_P702_MY2021_Tx" SG_ 71 immoTarget1Cmd 1; +BA_ "U_T6_MCA_MY2020_Tx" SG_ 71 immoTarget1Cmd 1; +BA_ "GenSigSendType" SG_ 1822 TesterPhysicalResGWM_F1 3; +BA_ "ECGUsedTxSignal" SG_ 1822 TesterPhysicalResGWM_F1 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1438 GWM_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_GWOnBoardTester 255; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1438 GWM_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_GWNMProxy 255; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_GWNMProxy 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1438 GWM_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_AutoSarNMReserved4 255; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1438 GWM_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_AutoSarNMReserved3 255; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1438 GWM_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_AutoSarNMReserved2 255; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1438 GWM_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_AutoSarNMReserved1 255; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1438 GWM_AutoSarNMNodeId 158; +BA_ "ContentDependant" SG_ 1438 GWM_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1438 GWM_AutoSarNMNodeId 158; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1438 GWM_AutoSarNMControl 1; +BA_ "ECGUsedTxSignal" SG_ 1438 GWM_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Rx" SG_ 954 GenericSwtch3_No_Actl 1; +BA_ "ContentDependant" SG_ 954 GenericSwtch2_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 954 GenericSwtch2_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 954 GenericSwtch1_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1006 PersIndexIpmb_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1006 PersIndexIpmb_D_Actl 4; +BA_ "GenSigStartValue" SG_ 1006 PersIndexIpmb_D_Actl 4; +BA_ "GenSigSendType" SG_ 1006 PersIndexIpmb_D_Actl 3; +BA_ "CrossOver_InfoCAN" SG_ 1006 FeatNoIpmbActl 1; +BA_ "GenSigSendType" SG_ 1006 FeatNoIpmbActl 3; +BA_ "CrossOver_InfoCAN" SG_ 1006 FeatConfigIpmbActl 1; +BA_ "GenSigSendType" SG_ 1006 FeatConfigIpmbActl 3; +BA_ "GenSigSendType" SG_ 820 AhbStatGfhbFdbk_D_Actl 3; +BA_ "U_P702_MY2021_Tx" SG_ 820 AhbStatGfhbFdbk_D_Actl 1; +BA_ "GenSigSendType" SG_ 820 HeadLghtDrvSide_B_Stat 3; +BA_ "U_P702_MY2021_Tx" SG_ 820 HeadLghtDrvSide_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 820 HeadLghtHiOn_B_StatHcm 1; +BA_ "GenSigSendType" SG_ 820 HeadLghtHiOn_B_StatHcm 3; +BA_ "U_P702_MY2021_Tx" SG_ 820 HeadLghtHiOn_B_StatHcm 1; +BA_ "CrossOver_InfoCAN" SG_ 820 Adaptive_Hdlmp_Fault 1; +BA_ "GenSigSendType" SG_ 820 Adaptive_Hdlmp_Fault 3; +BA_ "U_P702_MY2021_Tx" SG_ 820 Adaptive_Hdlmp_Fault 1; +BA_ "GenSigStartValueInteger" SG_ 137 SteWhlOffstRq_D_Stat 2; +BA_ "GenSigStartValue" SG_ 137 SteWhlOffstRq_D_Stat 2; +BA_ "U_P702_MY2021_Rx" SG_ 137 SteWhlOffstRq_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 137 SteWhlOffst_An_TotActl 32766; +BA_ "GenSigStartValue" SG_ 137 SteWhlOffst_An_TotActl 32765; +BA_ "U_P702_MY2021_Rx" SG_ 137 SteWhlOffst_An_TotActl 1; +BA_ "GenSigStartValueInteger" SG_ 137 SteWhlBrkOffst_An_Actl 32766; +BA_ "GenSigStartValue" SG_ 137 SteWhlBrkOffst_An_Actl 32765; +BA_ "U_P702_MY2021_Rx" SG_ 137 SteWhlBrkOffst_An_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 137 SteWhlBrkAnActl_No_Cs 1; +BA_ "MetaData" SG_ 137 SteWhlBrkAnActl_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 137 SteWhlBrkAnActl_No_Cs 1; +BA_ "CrossOver_InfoCAN" SG_ 137 SteWhlBrkAnActl_No_Cnt 1; +BA_ "MetaData" SG_ 137 SteWhlBrkAnActl_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 137 SteWhlBrkAnActl_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 129 SelDrvMdeSwtch_D_Stat4 1; +BA_ "U_P702_MY2021_Rx" SG_ 129 SelDrvMdeSwtch_D_Stat4 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchView_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchSet_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchPhon_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchNav_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchMed_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchIod_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchHud_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchBack_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchMenu_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchUp_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchRght_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchOk_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchLeft_B_Stat 1; +BA_ "WakeupSignal" SG_ 129 SteWhlSwtchDown_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 935 SodRight_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 935 SodRight_D_Stat 2; +BA_ "GenSigStartValue" SG_ 935 SodRight_D_Stat 2; +BA_ "GenSigSendType" SG_ 935 SodRight_D_Stat 3; +BA_ "GenSigSendType" SG_ 935 CtaAlrtRight2_D_Stat 3; +BA_ "GenSigSendType" SG_ 935 BttRight_D_Stat 3; +BA_ "GenSigSendType" SG_ 935 BttRight_D_RqDrv 3; +BA_ "GenSigSendType" SG_ 935 CtaBrkRightMsgTxt_B_Rq 3; +BA_ "GenSigSendType" SG_ 935 CtaRightBrkEnbl_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 935 CtaRightBrkEnbl_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 935 CtaRightBrkEnbl_B_Rq 1; +BA_ "GenSigSendType" SG_ 935 CtaRightBrkDecel_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 935 CtaRightBrkDecel_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 935 CtaRightBrkDecel_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 935 Side_Detect_R_Illum 1; +BA_ "GenSigStartValueInteger" SG_ 935 Side_Detect_R_Illum 100; +BA_ "GenSigStartValue" SG_ 935 Side_Detect_R_Illum 100; +BA_ "CrossOver_InfoCAN" SG_ 935 CtaSnsRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 935 CtaSnsRight_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 935 CtaAlrtRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 935 CtaAlrtRight_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 935 CtaRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 935 CtaRight_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 935 SodSnsRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 935 SodSnsRight_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 935 SodAlrtRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 935 SodAlrtRight_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 935 SodDetctRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 935 SodDetctRight_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 935 SodWarnRight_Prd_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 935 SodWarnRight_Prd_Rq 14; +BA_ "GenSigStartValue" SG_ 935 SodWarnRight_Prd_Rq 14; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte8 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte8 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte8 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte7 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte7 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte7 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte6 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte6 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte6 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte5 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte5 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte5 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte4 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte4 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte4 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte3 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte3 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte3 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte2 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte2 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte2 1; +BA_ "UsedOnPgmDBC" SG_ 1108 RCMSerialNoByte1 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1108 RCMSerialNoByte1 1; +BA_ "U_P702_MY2021_Rx" SG_ 1108 RCMSerialNoByte1 1; +BA_ "GenSigStartValueInteger" SG_ 261 ChrgStatDsply_D_Rq 1; +BA_ "GenSigStartValue" SG_ 261 ChrgStatDsply_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1146 TrlrAidSwtch_D_RqDrv 1; +BA_ "GenSigStartValueInteger" SG_ 1146 TrlrAidCtl_U_RqDrv 4094; +BA_ "GenSigStartValue" SG_ 1146 TrlrAidCtl_U_RqDrv 4093; +BA_ "U_P702_MY2021_Rx" SG_ 1146 TrlrAidCtl_U_RqDrv 1; +BA_ "U_P702_MY2021_Rx" SG_ 533 TrlrAidMde_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 533 OnbChrgGoTOn_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 533 OnbChrgGoTOn_D_Rq 2; +BA_ "GenSigStartValue" SG_ 533 OnbChrgGoTOn_D_Rq 2; +BA_ "CrossOver_InfoCAN" SG_ 533 OnbChrgGoTMnte_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 533 OnbChrgGoTMnte_D_Rq 1; +BA_ "MetaData" SG_ 533 OnbChrgGoTMnte_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 533 OnbChrgGoTHr_T_Rq 30; +BA_ "GenSigStartValue" SG_ 533 OnbChrgGoTHr_T_Rq 30; +BA_ "CrossOver_InfoCAN" SG_ 533 OnbChrgGoTElement_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 533 OnbChrgGoTElement_D_Rq 1; +BA_ "MetaData" SG_ 533 OnbChrgGoTElement_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 533 OnbChrgGoTDelete_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 533 OnbChrgClearAll_B_Rq 1; +BA_ "ECGUsedTxSignal" SG_ 533 OnbChrgClearAll_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 533 OnbChrgGoTUpdate_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1041 ElCmpr_Pw_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAuxIsol_D_Rq 1; +BA_ "GenSigStartValue" SG_ 1067 BattULoAuxIsol_D_Rq 2; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAux_U_Rq 1; +BA_ "GenSigStartValue" SG_ 1067 BattULoAux_U_Rq 3296; +BA_ "GenSigStartValueInteger" SG_ 1067 BattULoAuxSoc_Pc_Actl 95; +BA_ "GenSigStartValue" SG_ 1067 BattULoAuxSoc_Pc_Actl 95; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAuxSoc_Pc_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1067 BattULoAux_I_Actl 2048; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAux_I_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAux_D_Qlty 1; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoCrnkStrt_U_Pred 1; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoCrnkBelt_U_Pred 1; +BA_ "GenSigStartValueInteger" SG_ 1067 BattULoAux_U_Actl 203; +BA_ "GenSigStartValue" SG_ 1067 BattULoAux_U_Actl 203; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAux_U_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1067 BattULoAux_B_Falt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1112 BattTracChrgSustn_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1112 BattTracCnnct_D_Cmd 1; +BA_ "U_P702_MY2021_Rx" SG_ 1112 BattTracHvilOpen_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1112 BattTracDcdcDis_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1112 BattTracDelta_Te_Actl 164; +BA_ "GenSigStartValue" SG_ 1112 BattTracDelta_Te_Actl 120; +BA_ "ContentDependant" SG_ 1112 BattTracClntPmp_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 139 AfsPw_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 139 AfsPw_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 139 ActvFrontSteLck_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 139 ActvFrontSteLck_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 139 SelDrvMdeAdptSte_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1121 SelDrvMdeSwtch_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1121 SelDrvMdeSwtch_No_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1121 SelDrvMdeSwtch_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1121 SelDrvMdeSwtch_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1121 SelDrvMdeCnt_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1121 SelDrvMdeCnt_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1120 DrvSlipCtlMde_B_Rq3 1; +BA_ "UsedOnPgmDBC" SG_ 1120 DrvSlipCtlMde_B_Rq3 1; +BA_ "U_P702_MY2021_Rx" SG_ 1120 DrvSlipCtlMde_B_Rq3 1; +BA_ "U_P702_MY2021_Rx" SG_ 1120 HybMdeSwtch_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1120 RearDiffLck_D_RqDrv 2; +BA_ "GenSigStartValue" SG_ 1120 RearDiffLck_D_RqDrv 2; +BA_ "U_P702_MY2021_Rx" SG_ 1120 RearDiffLck_D_RqDrv 1; +BA_ "GenSigStartValueInteger" SG_ 1120 AwdMde_D_RqDrv 5; +BA_ "GenSigStartValue" SG_ 1120 AwdMde_D_RqDrv 5; +BA_ "U_P702_MY2021_Rx" SG_ 1120 AwdMde_D_RqDrv 1; +BA_ "UsedOnPgmDBC" SG_ 1120 HdcSwtchPos_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1120 HdcSwtchPos_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1050 Outside_Air_Temp_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1050 Outside_Air_Temp_Stat 254; +BA_ "GenSigStartValue" SG_ 1050 Outside_Air_Temp_Stat 254; +BA_ "U_P702_MY2021_Rx" SG_ 1050 Outside_Air_Temp_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1050 Outside_Air_Temp_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 1137 RngPerChrgAvg_L_Dsply 4094; +BA_ "GenSigStartValue" SG_ 1137 RngPerChrgAvg_L_Dsply 4093; +BA_ "U_P702_MY2021_Tx" SG_ 1137 RngPerChrgAvg_L_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4Prev3X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4Prev1X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1255 BalrRight4CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1255 BalrRight4CurntX_L_Actl 0; +BA_ "GenSigSendType" SG_ 1254 BalrRight3Threat_D_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3Prev3X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3Prev1X_L_Actl 0; +BA_ "GenSigSendType" SG_ 1254 BalrRight3Fast_B_Stat 3; +BA_ "GenSigSendType" SG_ 1254 BalrRight3Dsply_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1254 BalrRight3CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1254 BalrRight3CurntX_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2Prev3X_L_Actl 0; +BA_ "GenSigSendType" SG_ 1253 BalrRight2Threat_D_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2Prev1X_L_Actl 0; +BA_ "GenSigSendType" SG_ 1253 BalrRight2Fast_B_Stat 3; +BA_ "GenSigSendType" SG_ 1253 BalrRight2Dsply_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1253 BalrRight2CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1253 BalrRight2CurntX_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1Prev3X_L_Actl 0; +BA_ "GenSigSendType" SG_ 1252 BalrRight1Threat_D_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1Prev1X_L_Actl 0; +BA_ "GenSigSendType" SG_ 1252 BalrRight1Fast_B_Stat 3; +BA_ "GenSigSendType" SG_ 1252 BalrRight1Dsply_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1252 BalrRight1CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1252 BalrRight1CurntX_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4Prev3X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4Prev1X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1251 BalrLeft4CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1251 BalrLeft4CurntX_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3Prev3X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3Prev1X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1250 BalrLeft3CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1250 BalrLeft3CurntX_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2Prev3X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2Prev1X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1249 BalrLeft2CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1249 BalrLeft2CurntX_L_Actl 0; +BA_ "GenSigSendType" SG_ 1248 BalrLeft1Threat_D_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1Prev3Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1Prev3Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1Prev3X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1Prev3X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1Prev2Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1Prev2Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1Prev2X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1Prev2X_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1Prev1Y_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1Prev1Y_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1Prev1X_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1Prev1X_L_Actl 0; +BA_ "GenSigSendType" SG_ 1248 BalrLeft1Fast_B_Stat 3; +BA_ "GenSigSendType" SG_ 1248 BalrLeft1Dsply_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1CurntY_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1CurntY_L_Actl 0; +BA_ "GenSigStartValueInteger" SG_ 1248 BalrLeft1CurntX_L_Actl 64; +BA_ "GenSigStartValue" SG_ 1248 BalrLeft1CurntX_L_Actl 0; +BA_ "U_P702_MY2021_Rx" SG_ 1113 TrlrTrgtAcquire_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1113 TrlrRvrse_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1113 TrlrAid_D2_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1113 TrlrAidTrgtId_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1113 TrlrAid_An3_Actl 720; +BA_ "U_P702_MY2021_Rx" SG_ 1113 TrlrAid_An3_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1113 TrlrAid_AnRate2_Actl 400; +BA_ "U_P702_MY2021_Rx" SG_ 1113 TrlrAid_AnRate2_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1113 HitchToVehAxle_L_Calc 255; +BA_ "GenSigStartValue" SG_ 1113 HitchToVehAxle_L_Calc 255; +BA_ "U_P702_MY2021_Rx" SG_ 1113 HitchToVehAxle_L_Calc 1; +BA_ "GenSigSendType" SG_ 1105 TrlrAidSwtchLamp_B_Rq 3; +BA_ "GenSigSendType" SG_ 1105 TrlrHitchMsgTxt_D_Rq 3; +BA_ "GenSigSendType" SG_ 1105 TrlrHitchIcon_D_Rq 3; +BA_ "GenSigSendType" SG_ 1105 TrlrHitchChime_D_Rq 3; +BA_ "GenSigSendType" SG_ 1105 TrlrAidEnbl_D_RqAdas 3; +BA_ "U_P702_MY2021_Rx" SG_ 1105 TrlrAidEnbl_D_RqAdas 1; +BA_ "GenSigSendType" SG_ 1105 TrlrRvrseMsgTxt_D2_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 1105 TrlrRvrseMsgTxt_D2_Rq 1; +BA_ "GenSigSendType" SG_ 1105 TrlrRvrseEnbl_D2_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 1105 TrlrRvrseEnbl_D2_Stat 1; +BA_ "GenSigSendType" SG_ 1105 RbaMsg_D_Rq 3; +BA_ "WakeupSignal" SG_ 1105 BrkDecel_B_RqRba 1; +BA_ "CrossOver_InfoCAN" SG_ 1105 BrkDecel_B_RqRba 1; +BA_ "UsedOnPgmDBC" SG_ 1105 BrkDecel_B_RqRba 1; +BA_ "GenSigSendType" SG_ 1105 BrkDecel_B_RqRba 3; +BA_ "U_P702_MY2021_Rx" SG_ 1105 BrkDecel_B_RqRba 1; +BA_ "WakeupSignal" SG_ 1105 BrkEnbl_B_RqRba 1; +BA_ "CrossOver_InfoCAN" SG_ 1105 BrkEnbl_B_RqRba 1; +BA_ "UsedOnPgmDBC" SG_ 1105 BrkEnbl_B_RqRba 1; +BA_ "GenSigSendType" SG_ 1105 BrkEnbl_B_RqRba 3; +BA_ "U_P702_MY2021_Rx" SG_ 1105 BrkEnbl_B_RqRba 1; +BA_ "GenSigStartValueInteger" SG_ 1105 Rba_D_Stat 1; +BA_ "GenSigStartValue" SG_ 1105 Rba_D_Stat 1; +BA_ "GenSigSendType" SG_ 1105 Rba_D_Stat 3; +BA_ "GenSigSendType" SG_ 1105 RbaAlrt_D_Dsply 3; +BA_ "GenSigSendType" SG_ 1105 RbaMnu_D_Rq 3; +BA_ "GenSigSendType" SG_ 1105 CamraFrntStat_D_Stat 3; +BA_ "GenSigSendType" SG_ 1105 TrlrHitchLamp_D_Rq2 3; +BA_ "GenSigSendType" SG_ 938 SidePrkSnsR2_D_Stat 3; +BA_ "GenSigSendType" SG_ 938 SidePrkSnsR1_D_Stat 3; +BA_ "GenSigSendType" SG_ 938 SidePrkSnsL2_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 ApaMde_D_Stat 1; +BA_ "GenSigSendType" SG_ 938 ApaMde_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 ApaActvSd_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 938 ApaActvSd_D_Actl 1; +BA_ "GenSigStartValue" SG_ 938 ApaActvSd_D_Actl 1; +BA_ "GenSigSendType" SG_ 938 ApaActvSd_D_Actl 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidSwtch_B_Stat 1; +BA_ "GenSigSendType" SG_ 938 PrkAidSwtch_B_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 ApaMde_D_Avail 1; +BA_ "GenSigSendType" SG_ 938 ApaMde_D_Avail 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidSnsFrCrnr_D_Stat 1; +BA_ "GenSigSendType" SG_ 938 PrkAidSnsFrCrnr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidSnsFrCntr_D_Stat 1; +BA_ "GenSigSendType" SG_ 938 PrkAidSnsFrCntr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidSnsFlCrnr_D_Stat 1; +BA_ "GenSigSendType" SG_ 938 PrkAidSnsFlCrnr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidSnsFlCntr_D_Stat 1; +BA_ "GenSigSendType" SG_ 938 PrkAidSnsFlCntr_D_Stat 3; +BA_ "GenSigSendType" SG_ 938 PrkBrkEl_B_RqFap 3; +BA_ "U_CX727_MY2021_Rx" SG_ 938 PrkBrkEl_B_RqFap 1; +BA_ "U_P702_MY2021_Rx" SG_ 938 PrkBrkEl_B_RqFap 1; +BA_ "CrossOver_InfoCAN" SG_ 938 RpaChime_D_Rq 1; +BA_ "GenSigSendType" SG_ 938 RpaChime_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 938 FpaChime_D_Rq 1; +BA_ "GenSigSendType" SG_ 938 FpaChime_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 938 PrkAidMsgTxt_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 938 PrkAidMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 938 SidePrkSnsL1_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 938 PrkAidAudioMute_B_Rq 1; +BA_ "GenSigSendType" SG_ 938 PrkAidAudioMute_B_Rq 3; +BA_ "GenSigSendType" SG_ 939 ApaBrk_D_Rq 3; +BA_ "GenSigSendType" SG_ 939 SidePrkSnsR4_D_Stat 3; +BA_ "GenSigSendType" SG_ 939 SidePrkSnsR3_D_Stat 3; +BA_ "GenSigSendType" SG_ 939 SidePrkSnsL4_D_Stat 3; +BA_ "GenSigSendType" SG_ 939 SidePrkSnsL3_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidChime_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidChime_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidSnsRlCntr_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidSnsRlCntr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidSnsRrCrnr_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidSnsRrCrnr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidSnsRrCntr_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidSnsRrCntr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidSnsRlCrnr_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidSnsRlCrnr_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidRear_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidRear_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAidFront_D_Stat 1; +BA_ "GenSigSendType" SG_ 939 PrkAidFront_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 939 PrkAid_D_Falt 1; +BA_ "GenSigSendType" SG_ 939 PrkAid_D_Falt 3; +BA_ "GenSigSendType" SG_ 939 ApaLongCtrlEnbl_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 939 ApaLongCtrlEnbl_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 939 ApaLongCtrlEnbl_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 939 ApaLongCtrlEnbl_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 939 ApaBrk_A_Rq 255; +BA_ "U_P702_MY2021_Rx" SG_ 939 ApaBrk_A_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 939 ApaBrk_A_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 939 ApaBrk_A_Rq 1; +BA_ "GenSigSendType" SG_ 939 PrkAidLamp_D_Rq 3; +BA_ "GenSigStartValueInteger" SG_ 937 Veh_V_RqFap 0; +BA_ "U_P702_MY2021_Rx" SG_ 937 Veh_V_RqFap 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 937 Veh_V_RqFap 1; +BA_ "MetaData" SG_ 937 TrnRngDRqFap_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 937 TrnRngDRqFap_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 937 TrnRngDRqFap_No_Cs 1; +BA_ "MetaData" SG_ 937 TrnRngDRqFap_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 937 TrnRngDRqFap_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 937 TrnRngDRqFap_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 937 TrnRng_D_RqFap 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 937 TrnRng_D_RqFap 1; +BA_ "GenSigStartValueInteger" SG_ 937 FapLcDistToObj_L_Actl 254; +BA_ "GenSigStartValue" SG_ 937 FapLcDistToObj_L_Actl 254; +BA_ "U_P702_MY2021_Rx" SG_ 937 FapLcDistToObj_L_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 937 FapLcDistToObj_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 936 ApaSys_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 936 ApaSys_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 936 EPASExtAngleStatReq 1; +BA_ "U_P702_MY2021_Rx" SG_ 936 EPASExtAngleStatReq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 936 ExtSteeringAngleReq2 1; +BA_ "U_P702_MY2021_Rx" SG_ 936 ExtSteeringAngleReq2 1; +BA_ "GenSigStartValueInteger" SG_ 877 RngImpctDrv_L_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 877 RngImpctDrv_L_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 877 RngImpctClim_L_Dsply 255; +BA_ "U_P702_MY2021_Tx" SG_ 877 RngImpctClim_L_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 877 VehElEffAvg_No_Dsply 126; +BA_ "GenSigStartValue" SG_ 877 VehElEffAvg_No_Dsply 126; +BA_ "U_P702_MY2021_Tx" SG_ 877 VehElEffAvg_No_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 877 PwFlwFuelDrv_D_Dsply 1; +BA_ "GenSigSendType" SG_ 877 PwFlwFuelDrv_D_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 877 PwFlwFuelDrv_D_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 877 PwFlwFuelClimt_B_Dsply 1; +BA_ "GenSigSendType" SG_ 877 PwFlwFuelClimt_B_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 877 PwFlwFuelClimt_B_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 877 PwFlwFuelBatt_B_Dsply 1; +BA_ "GenSigSendType" SG_ 877 PwFlwFuelBatt_B_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 877 PwFlwFuelBatt_B_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 877 PwFlwBattClimt_B_Dsply 1; +BA_ "GenSigSendType" SG_ 877 PwFlwBattClimt_B_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 877 PwFlwBattClimt_B_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 877 PwFlwBatt_D_Dsply 1; +BA_ "GenSigSendType" SG_ 877 PwFlwBatt_D_Dsply 3; +BA_ "U_P702_MY2021_Tx" SG_ 877 PwFlwBatt_D_Dsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 589 BattTrac2_Pw_LimChrg 1; +BA_ "U_P702_MY2021_Rx" SG_ 589 BattTrac2_Pw_LimDchrg 1; +BA_ "U_P702_MY2021_Rx" SG_ 589 BattTrac2_Pw_DchrgInst 1; +BA_ "U_P702_MY2021_Rx" SG_ 589 BattTrac2_Pw_ChrgInst 1; +BA_ "GenSigStartValueInteger" SG_ 588 BattTracSoc2_Pc_Actl 16382; +BA_ "GenSigStartValue" SG_ 588 BattTracSoc2_Pc_Actl 16382; +BA_ "U_P702_MY2021_Rx" SG_ 588 BattTracSoc2_Pc_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 588 BattTrac_Te_Actl 150; +BA_ "GenSigStartValue" SG_ 588 BattTrac_Te_Actl 150; +BA_ "U_P702_MY2021_Rx" SG_ 588 BattTrac_Te_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 588 BattTracDiagClr_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 588 BattTracDiagClr_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 587 BattTracClnt_Te_Actl 164; +BA_ "GenSigStartValue" SG_ 587 BattTracClnt_Te_Actl 164; +BA_ "CrossOver_InfoCAN" SG_ 587 BattTracWarnLamp_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 587 BattTracSrvcRqd_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 587 BattTracSoc_Pc_MxPrtct 700; +BA_ "GenSigStartValue" SG_ 587 BattTracSoc_Pc_MxPrtct 700; +BA_ "U_P702_MY2021_Rx" SG_ 587 BattTracSoc_Pc_MxPrtct 1; +BA_ "GenSigStartValueInteger" SG_ 587 BattTracSoc_Pc_MnPrtct 300; +BA_ "GenSigStartValue" SG_ 587 BattTracSoc_Pc_MnPrtct 30; +BA_ "U_P702_MY2021_Rx" SG_ 587 BattTracSoc_Pc_MnPrtct 1; +BA_ "GenSigStartValueInteger" SG_ 587 BattTracSoc_Pc_LimLo 400; +BA_ "GenSigStartValue" SG_ 587 BattTracSoc_Pc_LimLo 400; +BA_ "U_P702_MY2021_Rx" SG_ 587 BattTracSoc_Pc_LimLo 1; +BA_ "GenSigStartValueInteger" SG_ 587 BattTracSoc_Pc_LimHi 600; +BA_ "GenSigStartValue" SG_ 587 BattTracSoc_Pc_LimHi 600; +BA_ "U_P702_MY2021_Rx" SG_ 587 BattTracSoc_Pc_LimHi 1; +BA_ "CrossOver_InfoCAN" SG_ 389 HtrnOvrTeLamp_B_Dsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 389 HtrnAin_UHi_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 389 HtrnAin_UHi_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 389 HtrnSrvcRqd_B_Dsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 389 HtrnHvilOpen_B_Actl 1; +BA_ "ECGUsedRxSignal" SG_ 389 HtrnHvilOpen_B_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 389 BattTrac_I_EstVsc 15000; +BA_ "U_P702_MY2021_Rx" SG_ 1009 TrlrAidCancl_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1009 CenterStackRing_D_Actl 2; +BA_ "GenSigStartValue" SG_ 1009 CenterStackRing_D_Actl 2; +BA_ "CrossOver_InfoCAN" SG_ 1009 ValetMode_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 360 GsmSrvcRqd_B_Rq 1; +BA_ "ContentDependant" SG_ 360 GsmSrvcRqd_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 360 TrnGearPwmFalt_B_Actl 1; +BA_ "ContentDependant" SG_ 360 TrnGearPwmFalt_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 360 TrnGearPwmFalt_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 360 TrnGearPwmFalt_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 360 GearButtnStuck_B_Actl 1; +BA_ "ContentDependant" SG_ 360 GearButtnStuck_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 360 GearButtnStuck_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 360 GearButtnStuck_B_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 122 BattTrac_U_LimLo 88; +BA_ "GenSigStartValue" SG_ 122 BattTrac_U_LimLo 88; +BA_ "U_P702_MY2021_Rx" SG_ 122 BattTrac_U_LimLo 1; +BA_ "GenSigStartValueInteger" SG_ 122 BattTrac_U_LimHi 163; +BA_ "GenSigStartValue" SG_ 122 BattTrac_U_LimHi 163; +BA_ "U_P702_MY2021_Rx" SG_ 122 BattTrac_U_LimHi 1; +BA_ "CrossOver_InfoCAN" SG_ 122 VehStrtInhbt_B_RqBatt 1; +BA_ "U_P702_MY2021_Rx" SG_ 122 VehStrtInhbt_B_RqBatt 1; +BA_ "U_P702_MY2021_Rx" SG_ 122 BattTracOffFst_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 122 BattTracOff_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 122 BattTracOff_B_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 122 BattTrac_U_Actl 1022; +BA_ "GenSigStartValue" SG_ 122 BattTrac_U_Actl 1022; +BA_ "U_P702_MY2021_Rx" SG_ 122 BattTrac_U_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 122 BattTrac_I_Actl 15000; +BA_ "U_P702_MY2021_Rx" SG_ 122 BattTrac_I_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 90 TrnGsmNtmState_D_Actl 1; +BA_ "ContentDependant" SG_ 90 TrnGsmNtmState_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGsmNtmState_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGsmNtmState_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 90 TrnGsmNtmState_D_Actl 1; +BA_ "ContentDependant" SG_ 90 DrQltyDrv_D_StatGsm 1; +BA_ "GenSigStartValue" SG_ 90 DrQltyDrv_D_StatGsm 6; +BA_ "U_P702_MY2021_Rx" SG_ 90 DrQltyDrv_D_StatGsm 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 DrQltyDrv_D_StatGsm 1; +BA_ "U_CX727_MY2021_Rx" SG_ 90 DrQltyDrv_D_StatGsm 1; +BA_ "ContentDependant" SG_ 90 TrnBtsiOvrrd_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnBtsiOvrrd_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnBtsiOvrrd_B_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 90 TrnRng_D_RqGsm 14; +BA_ "GenSigStartValue" SG_ 90 TrnRng_D_RqGsm 14; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnRng_D_RqGsm 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnRng_D_RqGsm 1; +BA_ "U_CX727_MY2021_Rx" SG_ 90 PrkBrkActv_D_RqGsmGear 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 PrkBrkActv_D_RqGsmGear 1; +BA_ "ContentDependant" SG_ 90 TrnValidGearRq_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnValidGearRq_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnValidGearRq_D_Stat 1; +BA_ "ContentDependant" SG_ 90 TrnGearRqCnt_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearRqCnt_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearRqCnt_B_Actl 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_U_Actl 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_U_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_U_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_U_Actl 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlR2 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlR2 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlR2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlR2 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlR1 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlR1 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlR1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlR1 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlR0 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlR0 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlR0 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlR0 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlP2 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlP2 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlP2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlP2 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlP1 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlP1 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlP1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlP1 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlP0 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlP0 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlP0 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlP0 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlN2 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlN2 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlN2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlN2 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlN1 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlN1 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlN1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlN1 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlN0 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlN0 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlN0 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlN0 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlM2 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlM2 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlM2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlM2 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlM1 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlM1 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlM1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlM1 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlM0 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlM0 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlM0 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlM0 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlD2 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlD2 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlD2 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlD2 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlD1 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlD1 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlD1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlD1 1; +BA_ "WakeupSignal" SG_ 90 TrnGearButtn_B_ActlD0 1; +BA_ "ContentDependant" SG_ 90 TrnGearButtn_B_ActlD0 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGearButtn_B_ActlD0 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGearButtn_B_ActlD0 1; +BA_ "ContentDependant" SG_ 90 TrnGear_No_Cs 1; +BA_ "MetaData" SG_ 90 TrnGear_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGear_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGear_No_Cs 1; +BA_ "ContentDependant" SG_ 90 TrnGear_No_Cnt 1; +BA_ "MetaData" SG_ 90 TrnGear_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGear_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGear_No_Cnt 1; +BA_ "WakeupSignal" SG_ 90 TrnGear_D_RqDrv 1; +BA_ "ContentDependant" SG_ 90 TrnGear_D_RqDrv 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 TrnGear_D_RqDrv 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 TrnGear_D_RqDrv 1; +BA_ "ContentDependant" SG_ 90 BrkSwtchPos_B_ActlGsm 1; +BA_ "U_P702_MY2021_Rx" SG_ 90 BrkSwtchPos_B_ActlGsm 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 90 BrkSwtchPos_B_ActlGsm 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 ParkLampTrlrOut_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 TrlrLampCtl_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 TrlrBattChrg_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 StopLampTrlrOut_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 TurnLampTrlrRr_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 TurnLampTrlrRl_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1091 TrlrLampCnnct_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1091 TrlrLampCnnct_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1091 TrlrLampCnnct_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1091 TrlrLampCnnct_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1091 TrlrLampCnnct_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 138 SteWhlRelCalib_T_Actl 1; +BA_ "ContentDependant" SG_ 138 SteWhlRelCalib_An_Sns 1; +BA_ "U_P702_MY2021_Rx" SG_ 138 SteWhlRelCalib_An_Sns 1; +BA_ "U_CX727_MY2021_Rx" SG_ 138 SteWhlRelCalib_An_Sns 1; +BA_ "WakeupSignal" SG_ 131 HeadLghtHiCtrl_D_RqAhb 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 HeadLghtHiCtrl_D_RqAhb 1; +BA_ "GenSigStartValueInteger" SG_ 131 WiprFrontSwtch_D_Stat 9; +BA_ "GenSigStartValue" SG_ 131 WiprFrontSwtch_D_Stat 9; +BA_ "WakeupSignal" SG_ 131 HeadLghtHiOn_B_StatAhb 1; +BA_ "CrossOver_InfoCAN" SG_ 131 HeadLghtHiOn_B_StatAhb 1; +BA_ "WakeupSignal" SG_ 131 HeadLghtHiFlash_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 131 WiprFront_D_Stat 15; +BA_ "GenSigStartValue" SG_ 131 WiprFront_D_Stat 15; +BA_ "U_P702_MY2021_Rx" SG_ 131 WiprFront_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 WiprFront_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 131 WiprFront_D_Stat 1; +BA_ "WakeupSignal" SG_ 131 TurnLghtSwtch_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 131 TurnLghtSwtch_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 131 TurnLghtSwtch_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 TurnLghtSwtch_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 131 LghtAmb_D_Sns 7; +BA_ "GenSigStartValue" SG_ 131 LghtAmb_D_Sns 7; +BA_ "U_P702_MY2021_Rx" SG_ 131 LghtAmb_D_Sns 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 AslButtnOnOffPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 AslButtnOnOffPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 AslButtnOnOffCnclPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 AslButtnOnOffCnclPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcButtnOnPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcButtnOnPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcButtnOnOffPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcButtnOnOffPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcButtnOnOffCnclPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcButtnOnOffCnclPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcButtnOffPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcButtnOffPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAsllButtnResPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAsllButtnResPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnSetIncPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnSetIncPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnSetDecPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnSetDecPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnResIncPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnResIncPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnOnPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnOnPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnIndxIncPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnIndxIncPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnIndxDecPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnIndxDecPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnDeny_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnDeny_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnCnclResPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnCnclResPress 1; +BA_ "U_P702_MY2021_Rx" SG_ 131 CcAslButtnCnclPress 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 131 CcAslButtnCnclPress 1; +BA_ "WakeupSignal" SG_ 787 DrLckCnt_No_ActlTgate 1; +BA_ "WakeupSignal" SG_ 787 DrTgateChime2_D_Rq 1; +BA_ "WakeupSignal" SG_ 787 DrTGate_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 787 DrTGate_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 787 DrTGate_D_Rq 1; +BA_ "WakeupSignal" SG_ 787 PwLftgtIntSw_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 787 Power_Liftgate_Mode_Stt 1; +BA_ "U_P702_MY2021_Rx" SG_ 953 BattRgenLoDChrg_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 953 BattRgenLoChrg_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 953 WakeAlarm3_D_Stat 3; +BA_ "GenSigStartValue" SG_ 953 WakeAlarm3_D_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 953 WakeAlarm2_D_Stat 3; +BA_ "GenSigStartValue" SG_ 953 WakeAlarm2_D_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 953 WakeAlarm1_D_Stat 3; +BA_ "GenSigStartValue" SG_ 953 WakeAlarm1_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 953 WakeAlarm1_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 953 WakeAlarm1_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 953 WakeAlarm0_D_Stat 3; +BA_ "GenSigStartValue" SG_ 953 WakeAlarm0_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 1093 TrlrBrkActCnnct_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1093 TrlrBrkActCnnct_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1093 TrlrBrkActCnnct_B_Actl 1; +BA_ "ContentDependant" SG_ 1093 StopLamp_B_RqTrlrBrk 1; +BA_ "U_P702_MY2021_Rx" SG_ 792 FuelRange_L_Dsply 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 792 FuelRange_L_Dsply 1; +BA_ "ContentDependant" SG_ 792 ElTrip_L_Dsply 1; +BA_ "ContentDependant" SG_ 792 ElLongTerm_L_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 968 SlMde_D_Rq 2; +BA_ "GenSigStartValue" SG_ 968 SlMde_D_Rq 2; +BA_ "U_P702_MY2021_Rx" SG_ 968 SlMde_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 968 SlMde_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 968 IsaOffst_D_Rq 14; +BA_ "GenSigStartValue" SG_ 968 IsaOffst_D_Rq 14; +BA_ "U_P702_MY2021_Rx" SG_ 968 IsaOffst_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 968 IsaOffst_D_Rq 1; +BA_ "WakeupSignal" SG_ 819 Memory_3_SwPsngr_Stat 1; +BA_ "WakeupSignal" SG_ 819 Memory_2_SwPsngr_Stat 1; +BA_ "WakeupSignal" SG_ 819 Memory_1_SwPsngr_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 819 WndwPsngrSide_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 819 WndwPsngrSide_D_Stat 1; +BA_ "WakeupSignal" SG_ 819 Pasngr_Lock_Sw_Stat 1; +BA_ "WakeupSignal" SG_ 819 Pasngr_Lock_Sw_Cnt 1; +BA_ "MetaData" SG_ 819 Pasngr_Lock_Sw_Cnt 1; +BA_ "WakeupSignal" SG_ 819 ChildLckFdbckRp_B_Stat 1; +BA_ "WakeupSignal" SG_ 818 ChildLckPw_N_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 818 WndwDrvSide_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 818 WndwDrvSide_D_Stat 1; +BA_ "WakeupSignal" SG_ 818 KeyCylSwDrvDr_D_Stat 1; +BA_ "GenSigInactiveValue" SG_ 818 Driver_Lock_Sw_Stat 0; +BA_ "WakeupSignal" SG_ 818 Driver_Lock_Sw_Stat 1; +BA_ "WakeupSignal" SG_ 818 Driver_Lock_Sw_Cnt 1; +BA_ "MetaData" SG_ 818 Driver_Lock_Sw_Cnt 1; +BA_ "WakeupSignal" SG_ 818 ChildLckPw_D_Rq 1; +BA_ "WakeupSignal" SG_ 818 ChildLckFdbckRd_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 818 RvrseMirrorChime_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 806 StopStrtDrvMde_B_RqBtn 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 StopStrtDrvMde_B_RqBtn 1; +BA_ "GenSigStartValueInteger" SG_ 806 HvacHtrCore_Te_Rq 0; +BA_ "U_P702_MY2021_Rx" SG_ 806 HvacHtrCore_Te_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 HvacHtrCore_Te_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 806 ClimtHeat_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 ClimtHeat_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 806 ClimtCool_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 ClimtCool_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 806 HvacEvap_Te_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 806 HvacEvap_Te_Rq 400; +BA_ "U_P702_MY2021_Rx" SG_ 806 HvacEvap_Te_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 HvacEvap_Te_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 806 HvacEvap_Te_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 806 HvacEvap_Te_Actl 400; +BA_ "U_P702_MY2021_Rx" SG_ 806 HvacEvap_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 HvacEvap_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 806 HvacAirCond_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 806 HvacAirCond_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 HvacAirCond_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 806 HvacEvap_Te_Offst 1; +BA_ "GenSigStartValueInteger" SG_ 806 HvacEvap_Te_Offst 400; +BA_ "U_P702_MY2021_Rx" SG_ 806 HvacEvap_Te_Offst 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 HvacEvap_Te_Offst 1; +BA_ "U_P702_MY2021_Rx" SG_ 806 ClimtPw_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 806 ClimtPw_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 765 EngExhMdeQuiet_D2_Rq 0; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 765 EdmSailMde_B_RqDrv 1; +BA_ "WakeupSignal" SG_ 765 DrvInputRequired_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 765 AwdRnge_D_ActlIpc 1; +BA_ "UsedOnPgmDBC" SG_ 765 AwdRnge_D_ActlIpc 1; +BA_ "GenSigStartValueInteger" SG_ 765 AwdRnge_D_ActlIpc 7; +BA_ "GenSigStartValue" SG_ 765 AwdRnge_D_ActlIpc 7; +BA_ "U_P702_MY2021_Rx" SG_ 765 AwdRnge_D_ActlIpc 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 765 AwdRnge_D_ActlIpc 1; +BA_ "GenSigStartValueInteger" SG_ 765 BalrSwtch_D_Stat 1; +BA_ "GenSigStartValue" SG_ 765 BalrSwtch_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 765 BalrMde_D_Rq 0; +BA_ "GenSigStartValueInteger" SG_ 765 WaitToStartLamp_D_Falt 1; +BA_ "GenSigStartValue" SG_ 765 WaitToStartLamp_D_Falt 1; +BA_ "U_P702_MY2021_Rx" SG_ 765 WaitToStartLamp_D_Falt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 765 WaitToStartLamp_D_Falt 1; +BA_ "GenSigStartValueInteger" SG_ 765 EsaOn_B_Rq 1; +BA_ "GenSigStartValue" SG_ 765 EsaOn_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 765 EsaOn_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 765 Btt_L_Actl 126; +BA_ "GenSigStartValue" SG_ 765 Btt_L_Actl 126; +BA_ "U_P702_MY2021_Rx" SG_ 765 SelDrvMdeTxtReset_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 765 SelDrvMdeDsply_B_Avail 1; +BA_ "CrossOver_InfoCAN" SG_ 765 Mc_VehUnitTempUsrSel_St 1; +BA_ "CrossOver_InfoCAN" SG_ 559 EhData2_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 559 EhData2_No_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 559 EhData2_No_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 558 EhData1_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 558 EhData1_No_Actl 0; +BA_ "U_P702_MY2021_Rx" SG_ 558 EhData1_No_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 558 EhData1_No_Actl 1; +BA_ "GenSigSendType" SG_ 934 CtaAlrtLeft2_D_Stat 3; +BA_ "GenSigSendType" SG_ 934 CtaBrkLeftMsgTxt_B_Rq 3; +BA_ "GenSigSendType" SG_ 934 CtaLeftBrkDecel_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 934 CtaLeftBrkDecel_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 934 CtaLeftBrkDecel_B_Rq 1; +BA_ "GenSigSendType" SG_ 934 CtaLeftBrkEnbl_B_Rq 3; +BA_ "U_CX727_MY2021_Rx" SG_ 934 CtaLeftBrkEnbl_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 934 CtaLeftBrkEnbl_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 934 Side_Detect_L_Illum 1; +BA_ "GenSigStartValueInteger" SG_ 934 Side_Detect_L_Illum 100; +BA_ "GenSigStartValue" SG_ 934 Side_Detect_L_Illum 100; +BA_ "GenSigSendType" SG_ 934 BttLeft_D_Stat 3; +BA_ "GenSigSendType" SG_ 934 BttLeft_D_RqDrv 3; +BA_ "CrossOver_InfoCAN" SG_ 934 CtaSnsLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 934 CtaSnsLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 SodDetctLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 934 SodDetctLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 CtaLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 934 CtaLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 CtaAlrtLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 934 CtaAlrtLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 SodLeft_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 934 SodLeft_D_Stat 2; +BA_ "GenSigStartValue" SG_ 934 SodLeft_D_Stat 2; +BA_ "GenSigSendType" SG_ 934 SodLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 SodSnsLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 934 SodSnsLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 SodAlrtLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 934 SodAlrtLeft_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 934 SodWarnLeft_Prd_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 934 SodWarnLeft_Prd_Rq 14; +BA_ "GenSigStartValue" SG_ 934 SodWarnLeft_Prd_Rq 14; +BA_ "CrossOver_InfoCAN" SG_ 1072 DrvSlipCtlMde_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1072 DrvSlipCtlMde_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 DrvSlipCtlMde_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 EngIdlShutDown_B_RqDrv 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 EngIdlShutDown_B_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 HsaMde_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1072 HsaMde_D_Rq 1; +BA_ "GenSigStartValue" SG_ 1072 HsaMde_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 NtrlTowMdeEnbl_B_RqDrv 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 NtrlTowMdeEnbl_B_RqDrv 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 NtrlTowMdeEnbl_B_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 BulbChkActv_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 ParkDetect_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1072 ParkDetect_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 ReducedGuard_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 TRLR_SWAY_CONFIG_CMD 1; +BA_ "WakeupSignal" SG_ 1072 Power_Liftgate_Mode_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 Power_Liftgate_Mode_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 AccEnbl_B_RqDrv 1; +BA_ "GenSigStartValueInteger" SG_ 1072 AccEnbl_B_RqDrv 1; +BA_ "GenSigStartValue" SG_ 1072 AccEnbl_B_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 OdometerMasterValue 1; +BA_ "UsedOnPgmDBC" SG_ 1072 OdometerMasterValue 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 OdometerMasterValue 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 OdometerMasterValue 1; +BA_ "U_CX727_MY2021_Rx" SG_ 1072 OdometerMasterValue 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 EngOilLife_B_RqReset 1; +BA_ "UsedOnPgmDBC" SG_ 1072 EngOilLife_B_RqReset 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 EngOilLife_B_RqReset 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 EngOilLife_B_RqReset 1; +BA_ "WakeupSignal" SG_ 1072 ePRNDL_MODE 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 ePRNDL_MODE 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 ePRNDL_MODE 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 ePRNDL_MODE 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 DrvSlipCtlMde_B_Rq2 1; +BA_ "UsedOnPgmDBC" SG_ 1072 DrvSlipCtlMde_B_Rq2 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 DrvSlipCtlMde_B_Rq2 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 MetricActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1072 MetricActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 MetricActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 MetricActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 KeyTypeChngMykey_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 1072 ManRgen_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1072 ManRgen_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1072 ManRgen_D_Rq 1; +BA_ "WakeupSignal" SG_ 909 IgnPsswrdDsply_B_Rq 1; +BA_ "WakeupSignal" SG_ 909 ElPwPoint_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 909 SecurityMsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 909 HeadLghtHiPrmsn_D_Stat 3; +BA_ "GenSigStartValue" SG_ 909 HeadLghtHiPrmsn_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 909 HeadLghtHiPrmsn_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 909 SteWhlLckMsgTxt_D_Rq 1; +BA_ "WakeupSignal" SG_ 909 immoMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 909 immoMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 909 PEBackupSlot_Stats 1; +BA_ "CrossOver_InfoCAN" SG_ 909 KeyMykeyTot_No_Cnt 1; +BA_ "MetaData" SG_ 909 KeyMykeyTot_No_Cnt 1; +BA_ "CrossOver_InfoCAN" SG_ 909 Keycode_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 909 KeyAdmnTot_No_Cnt 1; +BA_ "MetaData" SG_ 909 KeyAdmnTot_No_Cnt 1; +BA_ "WakeupSignal" SG_ 963 ImpactEvntFdbck_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 ImpactEvntFdbck_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 963 ImpactEvntFdbck_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLampLoOut_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 963 HeadLampLoOut_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 CrnrLghtRight_Pc_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 CrnrLghtRight_Pc_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 CrnrLghtLeft_Pc_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 CrnrLghtLeft_Pc_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLghtHiFdbck_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 TrnNotInPrkChime_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 963 TrnNotInPrkChime_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 PrkLightChime_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 963 PrkLightChime_B_Rq 1; +BA_ "WakeupSignal" SG_ 963 KeyInIgnWarn_B_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 963 KeyInIgnWarn_B_Cmd 1; +BA_ "UsedOnPgmDBC" SG_ 963 KeyInIgnWarn_B_Cmd 1; +BA_ "WakeupSignal" SG_ 963 HomeSafeLtChime_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HomeSafeLtChime_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 963 HomeSafeLtChime_B_Rq 1; +BA_ "WakeupSignal" SG_ 963 StopLghtOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 StopLghtOn_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 963 StopLghtOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 StopLghtOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 RvrseLghtOn_B_Stat 1; +BA_ "WakeupSignal" SG_ 963 PrkLght_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 PrkLght_D_Stat 1; +BA_ "WakeupSignal" SG_ 963 HeadLghtSwtch_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLghtSwtch_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 963 HeadLghtSwtch_D_Stat 2; +BA_ "GenSigStartValue" SG_ 963 HeadLghtSwtch_D_Stat 2; +BA_ "U_P702_MY2021_Rx" SG_ 963 HeadLghtSwtch_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLampLoFrOn_B_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 963 HeadLampLoFrOn_B_Stat 1; +BA_ "GenSigStartValue" SG_ 963 HeadLampLoFrOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 HeadLampLoFrOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLampLoFlOn_B_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 963 HeadLampLoFlOn_B_Stat 1; +BA_ "GenSigStartValue" SG_ 963 HeadLampLoFlOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 HeadLampLoFlOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLampLoActv_B_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 963 HeadLampLoActv_B_Stat 1; +BA_ "GenSigStartValue" SG_ 963 HeadLampLoActv_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 HeadLampLoActv_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 963 HeadLampLoActv_B_Stat 1; +BA_ "WakeupSignal" SG_ 963 Headlamp_On_Wrning_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 963 Headlamp_On_Wrning_Cmd 1; +BA_ "UsedOnPgmDBC" SG_ 963 Headlamp_On_Wrning_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 963 Park_Brake_Chime_Rqst 1; +BA_ "UsedOnPgmDBC" SG_ 963 Park_Brake_Chime_Rqst 1; +BA_ "WakeupSignal" SG_ 963 HeadLghtHiOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 HeadLghtHiOn_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 963 HeadLghtHiOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 HeadLghtHiOn_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 963 HeadLghtHiOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 BrkWarnInd_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 963 BrkWarnInd_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 Brk_Fluid_Lvl_Low 1; +BA_ "UsedOnPgmDBC" SG_ 963 Brk_Fluid_Lvl_Low 1; +BA_ "CrossOver_InfoCAN" SG_ 963 ReducedGuard_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 963 ReducedGuard_D_Stat 1; +BA_ "WakeupSignal" SG_ 963 Perimeter_Alarm_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 963 Perimeter_Alarm_Status 1; +BA_ "WakeupSignal" SG_ 963 Courtesy_BSave_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 963 Courtesy_BSave_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 963 Courtesy_BSave_Stat 1; +BA_ "GenSigStartValue" SG_ 963 Courtesy_BSave_Stat 1; +BA_ "WakeupSignal" SG_ 963 WndwGlbl_D_Cmd 1; +BA_ "CrossOver_InfoCAN" SG_ 963 WndwGlbl_D_Cmd 1; +BA_ "WakeupSignal" SG_ 963 PudLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 PudLamp_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 DayRnngLampOn_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 963 DayRnngLampOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 963 DayRnngLampOn_B_Stat 1; +BA_ "WakeupSignal" SG_ 963 PerimeterAlarmChimeRq 1; +BA_ "CrossOver_InfoCAN" SG_ 963 PerimeterAlarmChimeRq 1; +BA_ "UsedOnPgmDBC" SG_ 963 PerimeterAlarmChimeRq 1; +BA_ "UsedOnPgmDBC" SG_ 145 VehYawWActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 145 VehYawWActl_D_Qf 1; +BA_ "MetaData" SG_ 145 VehYawWActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 145 VehYawWActl_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 145 VehYawWActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 145 VehYawWActl_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 145 VehRolWActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 145 VehRolWActl_D_Qf 1; +BA_ "MetaData" SG_ 145 VehRolWActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 145 VehRolWActl_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 145 VehRolWActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 145 VehRolWActl_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 145 VehRollYawW_No_Cs 1; +BA_ "MetaData" SG_ 145 VehRollYawW_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 145 VehRollYawW_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 145 VehRollYawW_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 145 VehRollYaw_No_Cnt 1; +BA_ "MetaData" SG_ 145 VehRollYaw_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 145 VehRollYaw_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 145 VehRollYaw_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 145 VehYaw_W_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 145 VehYaw_W_Actl 65534; +BA_ "GenSigStartValue" SG_ 145 VehYaw_W_Actl 65534; +BA_ "U_CX727_MY2021_Rx" SG_ 145 VehYaw_W_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 145 VehYaw_W_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 145 VehRol_W_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 145 VehRol_W_Actl 65534; +BA_ "GenSigStartValue" SG_ 145 VehRol_W_Actl 65534; +BA_ "U_CX727_MY2021_Rx" SG_ 145 VehRol_W_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 145 VehRol_W_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 76 FirstRowBuckleMid 1; +BA_ "UsedOnPgmDBC" SG_ 76 FirstRowBuckleMid 1; +BA_ "GenSigStartValueInteger" SG_ 76 FirstRowBuckleMid 3; +BA_ "GenSigStartValue" SG_ 76 FirstRowBuckleMid 3; +BA_ "CrossOver_InfoCAN" SG_ 76 SecondRowBucklePsngr 1; +BA_ "GenSigStartValueInteger" SG_ 76 SecondRowBucklePsngr 3; +BA_ "GenSigStartValue" SG_ 76 SecondRowBucklePsngr 3; +BA_ "CrossOver_InfoCAN" SG_ 76 SecondRowBuckleMid 1; +BA_ "GenSigStartValueInteger" SG_ 76 SecondRowBuckleMid 3; +BA_ "GenSigStartValue" SG_ 76 SecondRowBuckleMid 3; +BA_ "CrossOver_InfoCAN" SG_ 76 SecondRowBuckleDriver 1; +BA_ "GenSigStartValueInteger" SG_ 76 SecondRowBuckleDriver 3; +BA_ "GenSigStartValue" SG_ 76 SecondRowBuckleDriver 3; +BA_ "CrossOver_InfoCAN" SG_ 76 FirstRowBuckleDriver 1; +BA_ "UsedOnPgmDBC" SG_ 76 FirstRowBuckleDriver 1; +BA_ "GenSigStartValueInteger" SG_ 76 FirstRowBuckleDriver 3; +BA_ "GenSigStartValue" SG_ 76 FirstRowBuckleDriver 3; +BA_ "U_P702_MY2021_Rx" SG_ 76 FirstRowBuckleDriver 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 76 FirstRowBuckleDriver 1; +BA_ "U_CX727_MY2021_Rx" SG_ 76 FirstRowBuckleDriver 1; +BA_ "CrossOver_InfoCAN" SG_ 76 RILReq 1; +BA_ "UsedOnPgmDBC" SG_ 76 RILReq 1; +BA_ "CrossOver_InfoCAN" SG_ 76 FirstRowBucklePsngr 1; +BA_ "UsedOnPgmDBC" SG_ 76 FirstRowBucklePsngr 1; +BA_ "GenSigStartValueInteger" SG_ 76 FirstRowBucklePsngr 3; +BA_ "GenSigStartValue" SG_ 76 FirstRowBucklePsngr 3; +BA_ "WakeupSignal" SG_ 76 RstrnImpactEvntStatus 1; +BA_ "CrossOver_InfoCAN" SG_ 76 RstrnImpactEvntStatus 1; +BA_ "UsedOnPgmDBC" SG_ 76 RstrnImpactEvntStatus 1; +BA_ "U_P702_MY2021_Rx" SG_ 76 RstrnImpactEvntStatus 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 76 RstrnImpactEvntStatus 1; +BA_ "U_CX727_MY2021_Rx" SG_ 76 RstrnImpactEvntStatus 1; +BA_ "CrossOver_InfoCAN" SG_ 76 PsngrFrntDetct_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 76 PsngrFrntDetct_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 76 PsngrFrntDetct_D_Actl 3; +BA_ "GenSigStartValue" SG_ 76 PsngrFrntDetct_D_Actl 3; +BA_ "CrossOver_InfoCAN" SG_ 76 EDRTriggerEvntSync 1; +BA_ "CrossOver_InfoCAN" SG_ 76 PassRstrnInd_Req 1; +BA_ "GenSigStartValueInteger" SG_ 76 PassRstrnInd_Req 3; +BA_ "GenSigStartValue" SG_ 76 PassRstrnInd_Req 3; +BA_ "UsedOnPgmDBC" SG_ 65 immoControlData_T1 1; +BA_ "U_P702_MY2021_Rx" SG_ 65 immoControlData_T1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 65 immoControlData_T1 1; +BA_ "UsedOnPgmDBC" SG_ 65 immoControlCmd_T1 1; +BA_ "U_P702_MY2021_Rx" SG_ 65 immoControlCmd_T1 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 65 immoControlCmd_T1 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 HILL_DESC_SW 1; +BA_ "UsedOnPgmDBC" SG_ 1076 HILL_DESC_SW 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 HILL_DESC_SW 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 HILL_DESC_SW 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 AutoRgen_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 AutoRgen_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1076 W2S_LAMP_OK 1; +BA_ "GenSigStartValue" SG_ 1076 W2S_LAMP_OK 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 OdoTripRx_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 OdoTripRx_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 OdoTripRx_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 Veh_V_CompLimMx 1; +BA_ "GenSigStartValueInteger" SG_ 1076 Veh_V_CompLimMx 4095; +BA_ "GenSigStartValue" SG_ 1076 Veh_V_CompLimMx 4093; +BA_ "U_P702_MY2021_Rx" SG_ 1076 Veh_V_CompLimMx 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 Veh_V_CompLimMx 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 DrvSlipCtlMde_B_RqMyKey 1; +BA_ "UsedOnPgmDBC" SG_ 1076 DrvSlipCtlMde_B_RqMyKey 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 FuelLvlWarn_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 FuelSecndActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 FuelLvlPssvSide_No_Raw 1; +BA_ "UsedOnPgmDBC" SG_ 1076 FuelLvlPssvSide_No_Raw 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 FuelLvlPssvSide_No_Raw 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 FuelLvlPssvSide_No_Raw 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 FUEL_SENSOR_NUM 1; +BA_ "UsedOnPgmDBC" SG_ 1076 FUEL_SENSOR_NUM 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 FUEL_SENSOR_NUM 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 FUEL_SENSOR_NUM 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 FuelLvlActvSide_No_Raw 1; +BA_ "UsedOnPgmDBC" SG_ 1076 FuelLvlActvSide_No_Raw 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 FuelLvlActvSide_No_Raw 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 FuelLvlActvSide_No_Raw 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 FuelLvl_Pc_Dsply 1; +BA_ "UsedOnPgmDBC" SG_ 1076 FuelLvl_Pc_Dsply 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 FuelLvl_Pc_Dsply 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 FuelLvl_Pc_Dsply 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 DISPLAY_SPEED_SCALING 1; +BA_ "UsedOnPgmDBC" SG_ 1076 DISPLAY_SPEED_SCALING 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 DISPLAY_SPEED_SCALING 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 DISPLAY_SPEED_SCALING 1; +BA_ "CrossOver_InfoCAN" SG_ 1076 DISPLAY_SPEED_OFFSET 1; +BA_ "UsedOnPgmDBC" SG_ 1076 DISPLAY_SPEED_OFFSET 1; +BA_ "U_P702_MY2021_Rx" SG_ 1076 DISPLAY_SPEED_OFFSET 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1076 DISPLAY_SPEED_OFFSET 1; +BA_ "GenSigStartValueInteger" SG_ 862 AutoStpHvacDelta_I_Est 192; +BA_ "U_P702_MY2021_Rx" SG_ 862 HvacBlwrFront_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 862 HvacBlwrFront_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 862 CabnAmb_Te_Actl 114; +BA_ "GenSigStartValue" SG_ 862 CabnAmb_Te_Actl 0; +BA_ "U_P702_MY2021_Rx" SG_ 862 CabnAmb_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 862 HvacRemoteStrt_N_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 862 HvacRemoteStrt_N_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 862 HvacRemoteStrt_N_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 862 ClimtThrmlLoad_No_Actl 255; +BA_ "GenSigStartValue" SG_ 862 ClimtThrmlLoad_No_Actl 255; +BA_ "U_P702_MY2021_Rx" SG_ 862 ClimtThrmlLoad_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 PtWakeReas_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 VehOnSrc_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 VehOnSrc_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 StrtrMtrCtlDStat_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 StrtrMtrCtlDStat_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 EngStrtActv_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 EngStrtActv_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 EngStrt_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 EngStrt_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 DrvInCtl_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 DrvInCtl_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 AdvStrt_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 AdvStrt_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 931 CrnkInhbt_No_Cs 1; +BA_ "ContentDependant" SG_ 931 CrnkInhbt_No_Cs 1; +BA_ "MetaData" SG_ 931 CrnkInhbt_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 CrnkInhbt_No_Cs 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 CrnkInhbt_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 931 CrnkInhbt_No_Cnt 1; +BA_ "ContentDependant" SG_ 931 CrnkInhbt_No_Cnt 1; +BA_ "MetaData" SG_ 931 CrnkInhbt_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 CrnkInhbt_No_Cnt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 CrnkInhbt_No_Cnt 1; +BA_ "GenSigStartValueInteger" SG_ 931 CrnkInhbt_B_Stat 1; +BA_ "GenSigStartValue" SG_ 931 CrnkInhbt_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 CrnkInhbt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 CrnkInhbt_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 931 IgnPreOffActv_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 931 IgnPreOffActv_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 PtLatchActv_B_RqBcm 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 PtLatchActv_B_RqBcm 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 immoSecureIdleMode 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 immoSecureIdleMode 1; +BA_ "WakeupSignal" SG_ 578 ReFuelSwtchStat_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 FuelPumpPwr_D_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 FuelPumpPwr_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 578 BattULo_U_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 578 BattULo_U_Actl 255; +BA_ "GenSigStartValue" SG_ 578 BattULo_U_Actl 255; +BA_ "U_P702_MY2021_Rx" SG_ 578 BattULo_U_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 BattULo_U_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 578 BattULo_U_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 578 PrkLckCtl_B_Enbl 1; +BA_ "WakeupSignal" SG_ 578 PrkLckCtlMsgTxt_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 578 PrkLckCtlMsgTxt_D_Rq 1; +BA_ "WakeupSignal" SG_ 578 PrkLckCtlAvail_T_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 578 PrkLckCtlAvail_T_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 BrkTrnShifLck_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 BrkTrnShifLck_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 578 DriverCrankingReq 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 DriverCrankingReq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 DriverCrankingReq 1; +BA_ "UsedOnPgmDBC" SG_ 578 EngOff_T_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 EngOff_T_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 EngOff_T_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 578 EngOff_T_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 578 DcacElPw_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 578 DcacElPw_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 DcacElPw_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 578 BattULo_I_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 578 BattULo_I_Actl 16383; +BA_ "GenSigStartValue" SG_ 578 BattULo_I_Actl 16383; +BA_ "U_P702_MY2021_Rx" SG_ 578 BattULo_I_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 578 BattULo_I_Actl 1; +BA_ "WakeupSignal" SG_ 947 DimmingLvlEvnt_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 DrStatDrvErrCnt_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 DrStatDrvErrCnt_B_Stat 1; +BA_ "WakeupSignal" SG_ 947 TurnLghtRight_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 947 TurnLghtRight_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 TurnLghtRight_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 947 TurnLghtRightOn_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 947 TurnLghtRightOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 947 TurnLghtLeftOn_B_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 947 TurnLghtLeftOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 947 FogLghtRearOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 FogLghtRearOn_B_Stat 1; +BA_ "WakeupSignal" SG_ 947 Backlit_LED_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Backlit_LED_Status 1; +BA_ "WakeupSignal" SG_ 947 TurnLghtLeft_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 947 TurnLghtLeft_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 TurnLghtLeft_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 947 FogLghtFrontOn_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 FogLghtFrontOn_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 947 IgnKeyType_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 947 IgnKeyType_D_Actl 14; +BA_ "GenSigStartValue" SG_ 947 IgnKeyType_D_Actl 14; +BA_ "U_P702_MY2021_Rx" SG_ 947 IgnKeyType_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 IgnKeyType_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 947 IgnKeyType_D_Actl 1; +BA_ "WakeupSignal" SG_ 947 Parklamp_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Parklamp_Status 1; +BA_ "UsedOnPgmDBC" SG_ 947 Parklamp_Status 1; +BA_ "GenSigStartValueInteger" SG_ 947 Parklamp_Status 1; +BA_ "GenSigStartValue" SG_ 947 Parklamp_Status 1; +BA_ "WakeupSignal" SG_ 947 Litval 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Litval 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 Litval 1; +BA_ "WakeupSignal" SG_ 947 Key_In_Ignition_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Key_In_Ignition_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 947 Key_In_Ignition_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 947 Key_In_Ignition_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 Key_In_Ignition_Stat 1; +BA_ "WakeupSignal" SG_ 947 Ignition_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Ignition_Status 1; +BA_ "UsedOnPgmDBC" SG_ 947 Ignition_Status 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 Ignition_Status 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 Ignition_Status 1; +BA_ "U_CX727_MY2021_Rx" SG_ 947 Ignition_Status 1; +BA_ "WakeupSignal" SG_ 947 Dimming_Lvl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Dimming_Lvl 1; +BA_ "GenSigStartValueInteger" SG_ 947 Dimming_Lvl 12; +BA_ "GenSigStartValue" SG_ 947 Dimming_Lvl 12; +BA_ "WakeupSignal" SG_ 947 Day_Night_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Day_Night_Status 1; +BA_ "UsedOnPgmDBC" SG_ 947 Day_Night_Status 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 Day_Night_Status 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 Day_Night_Status 1; +BA_ "WakeupSignal" SG_ 947 Remote_Start_Status 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Remote_Start_Status 1; +BA_ "WakeupSignal" SG_ 947 DrStatTgate_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatTgate_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 DrStatRr_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatRr_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 DrStatRr_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 DrStatRl_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatRl_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 DrStatRl_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 DrStatPsngr_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatPsngr_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 DrStatPsngr_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 DrStatInnrTgate_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatInnrTgate_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 DrStatHood_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatHood_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 DrStatDrv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 DrStatDrv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 947 DrStatDrv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 DrStatDrv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 DrStatDrv_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 947 DrStatDrv_B_Actl 1; +BA_ "WakeupSignal" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "ContentDependant" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 947 PrkBrkActv_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 947 LifeCycMde_D_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 947 LifeCycMde_D_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 947 LifeCycMde_D_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 947 LifeCycMde_D_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 947 LifeCycMde_D_Actl 1; +BA_ "WakeupSignal" SG_ 947 Delay_Accy 1; +BA_ "CrossOver_InfoCAN" SG_ 947 Delay_Accy 1; +BA_ "WakeupSignal" SG_ 947 CrashEvnt_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 947 CrashEvnt_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 947 CrashEvnt_D_Stat 3; +BA_ "GenSigStartValue" SG_ 947 CrashEvnt_D_Stat 3; +BA_ "CrossOver_InfoCAN" SG_ 947 FuelPmpInhbt_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 947 BodySrvcRqd_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BattULoChrg_URate_RqMx 1; +BA_ "GenSigStartValueInteger" SG_ 1084 BattULoChrg_URate_RqMx 5; +BA_ "GenSigStartValue" SG_ 1084 BattULoChrg_URate_RqMx 5; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BattULoChrg_URate_RqMx 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BattULoChrg_URate_RqMx 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BattULoChrg_U_RqMx 1; +BA_ "GenSigStartValueInteger" SG_ 1084 BattULoChrg_U_RqMx 34; +BA_ "GenSigStartValue" SG_ 1084 BattULoChrg_U_RqMx 34; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BattULoChrg_U_RqMx 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BattULoChrg_U_RqMx 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BattULoChrg_U_RqMn 1; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BattULoChrg_U_RqMn 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BattULoChrg_U_RqMn 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BattULoState_D_Qlty 1; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BattULoState_D_Qlty 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BattULoState_D_Qlty 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BSFault 1; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BSFault 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BSFault 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BattULo2_Te_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 1084 BattULo2_Te_Actl 127; +BA_ "GenSigStartValue" SG_ 1084 BattULo2_Te_Actl 127; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BattULo2_Te_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BattULo2_Te_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BSBattSOC 1; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BSBattSOC 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BSBattSOC 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BSBattQDeltaRideAh 1; +BA_ "GenSigStartValueInteger" SG_ 1084 BSBattQDeltaRideAh 12800; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BSBattQDeltaRideAh 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BSBattQDeltaRideAh 1; +BA_ "UsedOnPgmDBC" SG_ 1084 BSBattQCapAh 1; +BA_ "U_P702_MY2021_Rx" SG_ 1084 BSBattQCapAh 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1084 BSBattQCapAh 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 EngStrtInhbt_B_RqBatt 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 EngStrtInhbt_B_RqBatt 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 BattULoChrg_D_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 BattULoChrg_D_Rq 1; +BA_ "WakeupSignal" SG_ 1068 PwSysULoFalt_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1068 PwSysULoFalt_D_Stat 1; +BA_ "UsedOnPgmDBC" SG_ 1068 PwSysULoFalt_D_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1068 Shed_T_Eng_Off_B 1; +BA_ "WakeupSignal" SG_ 1068 Shed_Feature_Group_ID 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 Shed_Feature_Group_ID 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 Shed_Feature_Group_ID 1; +BA_ "CrossOver_InfoCAN" SG_ 1068 Shed_Drain_Eng_Off_B 1; +BA_ "WakeupSignal" SG_ 1068 Shed_Level_Req 1; +BA_ "CrossOver_InfoCAN" SG_ 1068 Shed_Level_Req 1; +BA_ "UsedOnPgmDBC" SG_ 1068 Shed_Level_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 Shed_Level_Req 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 Shed_Level_Req 1; +BA_ "UsedOnPgmDBC" SG_ 1068 ULoRgenTestMde_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 ULoRgenTestMde_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 ULoRgenTestMde_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 ChargeMode 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 ChargeMode 1; +BA_ "CrossOver_InfoCAN" SG_ 1068 Batt_Lo_SoC_B 1; +BA_ "UsedOnPgmDBC" SG_ 1068 PeriodicElLoad_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 1068 PeriodicElLoad_B_Stat 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 1068 PeriodicElLoad_B_Stat 1; +BA_ "CrossOver_InfoCAN" SG_ 1068 Batt_Crit_SoC_B 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehVert2_A_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 146 VehVert2_A_Actl 8190; +BA_ "GenSigStartValue" SG_ 146 VehVert2_A_Actl 8190; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehVert2_A_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 146 VehVert2_A_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehVert2_A_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehLatLongVertA_No_Cs 1; +BA_ "MetaData" SG_ 146 VehLatLongVertA_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehLatLongVertA_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehLatLongVertA_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehLatLongVert_No_Cnt 1; +BA_ "MetaData" SG_ 146 VehLatLongVert_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehLatLongVert_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehLatLongVert_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehLong2_A_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 146 VehLong2_A_Actl 8190; +BA_ "GenSigStartValue" SG_ 146 VehLong2_A_Actl 8190; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehLong2_A_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 146 VehLong2_A_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehLong2_A_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehLat2_A_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 146 VehLat2_A_Actl 8190; +BA_ "GenSigStartValue" SG_ 146 VehLat2_A_Actl 8190; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehLat2_A_Actl 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 146 VehLat2_A_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehLat2_A_Actl 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehVertAActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 146 VehVertAActl_D_Qf 1; +BA_ "MetaData" SG_ 146 VehVertAActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 146 VehVertAActl_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehVertAActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehVertAActl_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "MetaData" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehLongAActl_D_Qf 1; +BA_ "UsedOnPgmDBC" SG_ 146 VehLatAActl_D_Qf 1; +BA_ "GenSigStartValueInteger" SG_ 146 VehLatAActl_D_Qf 1; +BA_ "MetaData" SG_ 146 VehLatAActl_D_Qf 1; +BA_ "GenSigStartValue" SG_ 146 VehLatAActl_D_Qf 1; +BA_ "U_CX727_MY2021_Rx" SG_ 146 VehLatAActl_D_Qf 1; +BA_ "U_P702_MY2021_Rx" SG_ 146 VehLatAActl_D_Qf 1; +BA_ "GenSigSendType" SG_ 1900 TesterPhysicalResCCM 3; +BA_ "GenSigSendType" SG_ 1806 TesterPhysicalResIPMA 3; +BA_ "CrossOver_InfoCAN" SG_ 997 PersIndexCcm_D_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 997 PersIndexCcm_D_Actl 4; +BA_ "GenSigStartValue" SG_ 997 PersIndexCcm_D_Actl 4; +BA_ "GenSigSendType" SG_ 997 PersIndexCcm_D_Actl 3; +BA_ "CrossOver_InfoCAN" SG_ 997 FeatNoCcmActl 1; +BA_ "GenSigSendType" SG_ 997 FeatNoCcmActl 3; +BA_ "CrossOver_InfoCAN" SG_ 997 FeatConfigCcmActl 1; +BA_ "GenSigSendType" SG_ 997 FeatConfigCcmActl 3; +BA_ "GenSigStartValueInteger" SG_ 983 CmbbObjRelLong_V_Actl 1022; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjRelLong_V_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjRelLong_V_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 983 CmbbObjRelLat_V_Actl 510; +BA_ "GenSigStartValue" SG_ 983 CmbbObjRelLat_V_Actl 510; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjRelLat_V_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjRelLat_V_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 983 CmbbObjDistLong_L_Actl 1022; +BA_ "GenSigStartValue" SG_ 983 CmbbObjDistLong_L_Actl 1022; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjDistLong_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjDistLong_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 983 CmbbObjDistLat_L_Actl 510; +BA_ "GenSigStartValue" SG_ 983 CmbbObjDistLat_L_Actl 510; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjDistLat_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjDistLat_L_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjConfdnc_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjConfdnc_D_Stat 1; +BA_ "GenSigStartValueInteger" SG_ 983 CmbbObjColl_T_Actl 126; +BA_ "GenSigStartValue" SG_ 983 CmbbObjColl_T_Actl 125; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjColl_T_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjColl_T_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 983 CmbbObjClass_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 CmbbObjClass_D_Stat 1; +BA_ "U_CX727_MY2021_Rx" SG_ 983 EsaEnbl_D2_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 983 EsaEnbl_D2_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1DistRigh_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1DistLeft_D_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbMde1_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbIntns1_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 980 AdbBrdr1Up_An_Rq 510; +BA_ "GenSigStartValue" SG_ 980 AdbBrdr1Up_An_Rq 509; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1Up_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 980 AdbBrdr1Right_An_Rq 2046; +BA_ "GenSigStartValue" SG_ 980 AdbBrdr1Right_An_Rq 2046; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1Right_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 980 AdbBrdr1Low_An_Rq 510; +BA_ "GenSigStartValue" SG_ 980 AdbBrdr1Low_An_Rq 509; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1Low_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 980 AdbBrdr1Left_An_Rq 2046; +BA_ "GenSigStartValue" SG_ 980 AdbBrdr1Left_An_Rq 2046; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1Left_An_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1CritRigh_T_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 980 AdbBrdr1CritLeft_T_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlRng_L_Max 1; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlRng_L_Max 1; +BA_ "U_CX727_MY2021_Rx" SG_ 979 HandsOffCnfm_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 HandsOffCnfm_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtl_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtl_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlRampType_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlRampType_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlPrecision_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlPrecision_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 979 LatCtlPathOffst_L_Actl 512; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlPathOffst_L_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlPathOffst_L_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 979 LatCtlPath_An_Actl 1000; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlPath_An_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlPath_An_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 979 LatCtlCurv_NoRate_Actl 4096; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlCurv_NoRate_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlCurv_NoRate_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 979 LatCtlCurv_No_Actl 1000; +BA_ "U_CX727_MY2021_Rx" SG_ 979 LatCtlCurv_No_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 979 LatCtlCurv_No_Actl 1; +BA_ "GenSigStartValueInteger" SG_ 976 SrpHghtRight_L_Actl 256; +BA_ "GenSigStartValueInteger" SG_ 976 SrpHghtLeft_L_Actl 256; +BA_ "GenSigSendType" SG_ 973 TsrVl2PrmntMsgTxt_D_Rq 3; +BA_ "GenSigSendType" SG_ 973 TsrVl1PrmntMsgTxt_D_Rq 3; +BA_ "GenSigStartValueInteger" SG_ 973 TsrVl2RstrcMsgTxt2_D_Rq 1; +BA_ "GenSigStartValue" SG_ 973 TsrVl2RstrcMsgTxt2_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrVl2RstrcMsgTxt2_D_Rq 3; +BA_ "GenSigStartValueInteger" SG_ 973 TsrVl1RstrcMsgTxt2_D_Rq 1; +BA_ "GenSigStartValue" SG_ 973 TsrVl1RstrcMsgTxt2_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrVl1RstrcMsgTxt2_D_Rq 3; +BA_ "GenSigSendType" SG_ 973 TsrOvtkMsgTxt2_D_Rq 3; +BA_ "GenSigSendType" SG_ 973 WwaWarn_B_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVlUnitMsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 973 TsrVlUnitMsgTxt_D_Rq 2; +BA_ "GenSigStartValue" SG_ 973 TsrVlUnitMsgTxt_D_Rq 2; +BA_ "GenSigSendType" SG_ 973 TsrVlUnitMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVLim2MsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 973 TsrVLim2MsgTxt_D_Rq 255; +BA_ "GenSigStartValue" SG_ 973 TsrVLim2MsgTxt_D_Rq 255; +BA_ "GenSigSendType" SG_ 973 TsrVLim2MsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVLim1MsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 973 TsrVLim1MsgTxt_D_Rq 255; +BA_ "GenSigStartValue" SG_ 973 TsrVLim1MsgTxt_D_Rq 255; +BA_ "GenSigSendType" SG_ 973 TsrVLim1MsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVl2StatMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrVl2StatMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVl2RstrcMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrVl2RstrcMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVl1StatMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrVl1StatMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrVl1RstrcMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrVl1RstrcMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrStatMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrStatMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrOvtkStatMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrOvtkStatMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrOvtkMsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 973 TsrOvtkMsgTxt_D_Rq 1; +BA_ "GenSigStartValue" SG_ 973 TsrOvtkMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrOvtkMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrOswWarnMsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 973 TsrOswWarnMsgTxt_D_Rq 1; +BA_ "GenSigStartValue" SG_ 973 TsrOswWarnMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrOswWarnMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 973 TsrMsgTxt_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 973 TsrMsgTxt_D_Rq 1; +BA_ "GenSigStartValue" SG_ 973 TsrMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 973 TsrMsgTxt_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 970 LkaDrvOvrrd_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 970 LkaActvStats_D2_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 970 LkaActvStats_D2_Req 1; +BA_ "GenSigStartValueInteger" SG_ 970 LaRefAng_No_Req 2048; +BA_ "U_CX727_MY2021_Rx" SG_ 970 LaRefAng_No_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 970 LaRefAng_No_Req 1; +BA_ "U_CX727_MY2021_Rx" SG_ 970 LaRampType_B_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 970 LaRampType_B_Req 1; +BA_ "GenSigStartValueInteger" SG_ 970 LaCurvature_No_Calc 2048; +BA_ "U_CX727_MY2021_Rx" SG_ 970 LaCurvature_No_Calc 1; +BA_ "U_P702_MY2021_Rx" SG_ 970 LaCurvature_No_Calc 1; +BA_ "U_CX727_MY2021_Rx" SG_ 970 LdwActvStats_D_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 970 LdwActvStats_D_Req 1; +BA_ "CrossOver_InfoCAN" SG_ 970 LdwActvIntns_D_Req 1; +BA_ "U_CX727_MY2021_Rx" SG_ 970 LdwActvIntns_D_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 970 LdwActvIntns_D_Req 1; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3DistRigh_D_Stat 1; +BA_ "GenSigSendType" SG_ 962 AdbBrdr3DistRigh_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3DistLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 962 AdbBrdr3DistLeft_D_Stat 3; +BA_ "GenSigSendType" SG_ 962 AdbMde3_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbMde3_D_Rq 1; +BA_ "GenSigSendType" SG_ 962 AdbIntns3_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbIntns3_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 962 AdbBrdr3Up_An_Rq 510; +BA_ "GenSigStartValue" SG_ 962 AdbBrdr3Up_An_Rq 509; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3Up_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 962 AdbBrdr3Right_An_Rq 2046; +BA_ "GenSigStartValue" SG_ 962 AdbBrdr3Right_An_Rq 2046; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3Right_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 962 AdbBrdr3Low_An_Rq 510; +BA_ "GenSigStartValue" SG_ 962 AdbBrdr3Low_An_Rq 509; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3Low_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 962 AdbBrdr3Left_An_Rq 2046; +BA_ "GenSigStartValue" SG_ 962 AdbBrdr3Left_An_Rq 2046; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3Left_An_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3CritRigh_T_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 962 AdbBrdr3CritLeft_T_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2DistRigh_D_Stat 1; +BA_ "GenSigSendType" SG_ 961 AdbBrdr2DistRigh_D_Stat 3; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2DistLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 961 AdbBrdr2DistLeft_D_Stat 3; +BA_ "GenSigSendType" SG_ 961 AdbMde2_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbMde2_D_Rq 1; +BA_ "GenSigSendType" SG_ 961 AdbIntns2_D_Rq 3; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbIntns2_D_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 961 AdbBrdr2Up_An_Rq 510; +BA_ "GenSigStartValue" SG_ 961 AdbBrdr2Up_An_Rq 509; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2Up_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 961 AdbBrdr2Right_An_Rq 2046; +BA_ "GenSigStartValue" SG_ 961 AdbBrdr2Right_An_Rq 2046; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2Right_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 961 AdbBrdr2Low_An_Rq 510; +BA_ "GenSigStartValue" SG_ 961 AdbBrdr2Low_An_Rq 509; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2Low_An_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 961 AdbBrdr2Left_An_Rq 2046; +BA_ "GenSigStartValue" SG_ 961 AdbBrdr2Left_An_Rq 2046; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2Left_An_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2CritRigh_T_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 961 AdbBrdr2CritLeft_T_Stat 1; +BA_ "MetaData" SG_ 394 HaDsply_No_Cs 1; +BA_ "ContentDependant" SG_ 394 HaDsply_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 394 HaDsply_No_Cs 1; +BA_ "GenSigSendType" SG_ 394 HaDsply_No_Cs 3; +BA_ "MetaData" SG_ 394 HaDsply_No_Cnt 1; +BA_ "ContentDependant" SG_ 394 HaDsply_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 394 HaDsply_No_Cnt 1; +BA_ "GenSigSendType" SG_ 394 HaDsply_No_Cnt 3; +BA_ "GenSigSendType" SG_ 394 AccStopStat_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 AccTrgDist2_D_Dsply 1; +BA_ "GenSigSendType" SG_ 394 AccTrgDist2_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 AccStopRes_B_Dsply 1; +BA_ "GenSigSendType" SG_ 394 AccStopRes_B_Dsply 3; +BA_ "GenSigSendType" SG_ 394 TjaWarn_D_Rq 3; +BA_ "GenSigSendType" SG_ 394 Tja_D_Stat 3; +BA_ "GenSigSendType" SG_ 394 TjaMsgTxt_D_Dsply 3; +BA_ "GenSigSendType" SG_ 394 IaccLamp_D_Rq 3; +BA_ "GenSigSendType" SG_ 394 AccMsgTxt_D2_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 394 FcwDeny_B_Dsply 1; +BA_ "GenSigSendType" SG_ 394 FcwDeny_B_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 FcwMemStat_B_Actl 1; +BA_ "GenSigSendType" SG_ 394 FcwMemStat_B_Actl 3; +BA_ "ECGUsedRxSignal" SG_ 394 FcwMemStat_B_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 394 AccTGap_B_Dsply 1; +BA_ "GenSigSendType" SG_ 394 AccTGap_B_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 CadsAlignIncplt_B_Actl 1; +BA_ "GenSigSendType" SG_ 394 CadsAlignIncplt_B_Actl 3; +BA_ "CrossOver_InfoCAN" SG_ 394 AccFllwMde_B_Dsply 1; +BA_ "GenSigSendType" SG_ 394 AccFllwMde_B_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 CadsRadrBlck_B_Actl 1; +BA_ "GenSigSendType" SG_ 394 CadsRadrBlck_B_Actl 3; +BA_ "CrossOver_InfoCAN" SG_ 394 CmbbPostEvnt_B_Dsply 1; +BA_ "GenSigSendType" SG_ 394 CmbbPostEvnt_B_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 AccStopMde_B_Dsply 1; +BA_ "GenSigSendType" SG_ 394 AccStopMde_B_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 FcwMemSens_D_Actl 1; +BA_ "GenSigSendType" SG_ 394 FcwMemSens_D_Actl 3; +BA_ "ECGUsedRxSignal" SG_ 394 FcwMemSens_D_Actl 1; +BA_ "CrossOver_InfoCAN" SG_ 394 FcwMsgTxt_D_Rq 1; +BA_ "GenSigSendType" SG_ 394 FcwMsgTxt_D_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 394 AccWarn_D_Dsply 1; +BA_ "GenSigSendType" SG_ 394 AccWarn_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 FcwVisblWarn_B_Rq 1; +BA_ "GenSigSendType" SG_ 394 FcwVisblWarn_B_Rq 3; +BA_ "CrossOver_InfoCAN" SG_ 394 FcwAudioWarn_B_Rq 1; +BA_ "GenSigSendType" SG_ 394 FcwAudioWarn_B_Rq 3; +BA_ "ECGUsedRxSignal" SG_ 394 FcwAudioWarn_B_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 394 AccTGap_D_Dsply 1; +BA_ "GenSigStartValueInteger" SG_ 394 AccTGap_D_Dsply 3; +BA_ "GenSigStartValue" SG_ 394 AccTGap_D_Dsply 3; +BA_ "GenSigSendType" SG_ 394 AccTGap_D_Dsply 3; +BA_ "CrossOver_InfoCAN" SG_ 394 AccMemEnbl_B_RqDrv 1; +BA_ "GenSigStartValueInteger" SG_ 394 AccMemEnbl_B_RqDrv 1; +BA_ "GenSigStartValue" SG_ 394 AccMemEnbl_B_RqDrv 1; +BA_ "GenSigSendType" SG_ 394 AccMemEnbl_B_RqDrv 3; +BA_ "CrossOver_InfoCAN" SG_ 394 FdaMem_B_Stat 1; +BA_ "GenSigSendType" SG_ 394 FdaMem_B_Stat 3; +BA_ "UsedOnPgmDBC" SG_ 391 CmbbBrkDecel_No_Cnt 1; +BA_ "MetaData" SG_ 391 CmbbBrkDecel_No_Cnt 1; +BA_ "U_CX727_MY2021_Rx" SG_ 391 CmbbBrkDecel_No_Cnt 1; +BA_ "U_P702_MY2021_Rx" SG_ 391 CmbbBrkDecel_No_Cnt 1; +BA_ "UsedOnPgmDBC" SG_ 391 CmbbBrkDecel_No_Cs 1; +BA_ "MetaData" SG_ 391 CmbbBrkDecel_No_Cs 1; +BA_ "U_CX727_MY2021_Rx" SG_ 391 CmbbBrkDecel_No_Cs 1; +BA_ "U_P702_MY2021_Rx" SG_ 391 CmbbBrkDecel_No_Cs 1; +BA_ "UsedOnPgmDBC" SG_ 391 CmbbBrkDecel_A_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 391 CmbbBrkDecel_A_Rq 5129; +BA_ "U_CX727_MY2021_Rx" SG_ 391 CmbbBrkDecel_A_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 391 CmbbBrkDecel_A_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 391 CmbbBrkPrchg_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 391 CmbbBrkPrchg_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 391 CmbbBrkPrchg_D_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 391 CmbbBrkPrchg_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 391 CmbbBrkDecel_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 391 CmbbBrkDecel_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 391 CmbbBrkDecel_B_Rq 1; +BA_ "ECGUsedRxSignal" SG_ 391 CmbbBrkDecel_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 391 CmbbBaSens_D_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 391 CmbbBaSens_D_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 391 CmbbBaSens_D_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 390 AccBrkTot_A_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 390 AccBrkTot_A_Rq 5129; +BA_ "U_CX727_MY2021_Rx" SG_ 390 AccBrkTot_A_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccBrkTot_A_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccPrpl_A_Pred 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccPrpl_A_Pred 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccVeh_V_Trg 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccVeh_V_Trg 1; +BA_ "UsedOnPgmDBC" SG_ 390 AccBrkPrkEl_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 390 AccBrkPrkEl_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccBrkPrkEl_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 390 CmbbDeny_B_Actl 1; +BA_ "U_CX727_MY2021_Rx" SG_ 390 CmbbDeny_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 CmbbDeny_B_Actl 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 CmbbEngTqMn_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 CmbbEngTqMn_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccPrpl_A_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccPrpl_A_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccDeny_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccDeny_B_Rq 1; +BA_ "WakeupSignal" SG_ 390 AccResumEnbl_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccResumEnbl_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccResumEnbl_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 390 AccCancl_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccCancl_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccCancl_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 390 AccBrkPrchg_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 390 AccBrkPrchg_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccBrkPrchg_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 390 AccBrkDecel_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 390 AccBrkDecel_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccBrkDecel_B_Rq 1; +BA_ "UsedOnPgmDBC" SG_ 390 AccStopStat_B_Rq 1; +BA_ "U_CX727_MY2021_Rx" SG_ 390 AccStopStat_B_Rq 1; +BA_ "U_P702_MY2021_Rx" SG_ 390 AccStopStat_B_Rq 1; +BA_ "U_T6_MCA_MY2020_Rx" SG_ 390 AccStopStat_B_Rq 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_GWOnBoardTester 255; +BA_ "ContentDependant" SG_ 1441 TCCM_GWOnBoardTester 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_GWOnBoardTester 255; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_GWOnBoardTester 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_GWNMProxy 255; +BA_ "ContentDependant" SG_ 1441 TCCM_GWNMProxy 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_GWNMProxy 255; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_GWNMProxy 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_AutoSarNMReserved4 255; +BA_ "ContentDependant" SG_ 1441 TCCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_AutoSarNMReserved4 255; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_AutoSarNMReserved4 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_AutoSarNMReserved3 255; +BA_ "ContentDependant" SG_ 1441 TCCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_AutoSarNMReserved3 255; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_AutoSarNMReserved3 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_AutoSarNMReserved2 255; +BA_ "ContentDependant" SG_ 1441 TCCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_AutoSarNMReserved2 255; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_AutoSarNMReserved2 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_AutoSarNMReserved1 255; +BA_ "ContentDependant" SG_ 1441 TCCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_AutoSarNMReserved1 255; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_AutoSarNMReserved1 1; +BA_ "GenSigStartValueInteger" SG_ 1441 TCCM_AutoSarNMNodeId 161; +BA_ "ContentDependant" SG_ 1441 TCCM_AutoSarNMNodeId 1; +BA_ "GenSigStartValue" SG_ 1441 TCCM_AutoSarNMNodeId 161; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_AutoSarNMNodeId 1; +BA_ "ContentDependant" SG_ 1441 TCCM_AutoSarNMControl 1; +BA_ "U_P702_MY2021_Tx" SG_ 1441 TCCM_AutoSarNMControl 1; +BA_ "GenSigSendType" SG_ 1787 TesterPhysicalResSODCMD 3; +BA_ "GenSigSendType" SG_ 1779 TesterPhysicalReqSODCMD 3; +BA_ "GenSigSendType" SG_ 1786 TesterPhysicalResSODCMC 3; +BA_ "GenSigSendType" SG_ 1778 TesterPhysicalReqSODCMC 3; +BA_ "CrossOver_InfoCAN" SG_ 1153 TerrMde_D_RqDrv 1; +BA_ "UsedOnPgmDBC" SG_ 1153 TerrMde_D_RqDrv 1; +BA_ "GenSigSendType" SG_ 942 PrkAidRdiusRight_L_Dsply 3; +BA_ "GenSigSendType" SG_ 942 PrkAidRdiusLeft_L_Dsply 3; +BA_ "GenSigSendType" SG_ 942 PrkAidDrvDir_D_Stat 3; +BA_ "GenSigSendType" SG_ 942 PrkAidAcsyRear_D_Stat 3; +BA_ "GenSigSendType" SG_ 942 PrkAidAcsyFront_D_Stat 3; +BA_ "GenSigSendType" SG_ 930 BalrWndwRight_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 930 BalrSnsRight_D_Falt 0; +BA_ "GenSigSendType" SG_ 930 BalrSnsRight_D_Falt 3; +BA_ "GenSigStartValueInteger" SG_ 930 WndwPsngrRear_D_RqBalrr 0; +BA_ "GenSigSendType" SG_ 930 WndwPsngrRear_D_RqBalrr 3; +BA_ "GenSigStartValueInteger" SG_ 930 WndwPsngr_D_RqBalrr 0; +BA_ "GenSigSendType" SG_ 930 WndwPsngr_D_RqBalrr 3; +BA_ "GenSigStartValueInteger" SG_ 930 WndwDrvRear_D_RqBalrr 0; +BA_ "GenSigSendType" SG_ 930 WndwDrvRear_D_RqBalrr 3; +BA_ "GenSigStartValueInteger" SG_ 930 WndwDrv_D_RqBalrr 0; +BA_ "GenSigSendType" SG_ 930 WndwDrv_D_RqBalrr 3; +BA_ "GenSigStartValueInteger" SG_ 930 BalrRight_D_Stat 2; +BA_ "GenSigStartValue" SG_ 930 BalrRight_D_Stat 2; +BA_ "GenSigSendType" SG_ 930 BalrRight_D_Stat 3; +BA_ "GenSigSendType" SG_ 930 BalrMdeSelRight_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 930 BalrMdeRight_D_Stat 1; +BA_ "GenSigStartValue" SG_ 930 BalrMdeRight_D_Stat 1; +BA_ "GenSigSendType" SG_ 930 BalrMdeRight_D_Stat 3; +BA_ "GenSigSendType" SG_ 930 BalrLckRight_B_Stat 3; +BA_ "GenSigSendType" SG_ 930 BalrChimeRight_D_Rq 3; +BA_ "GenSigSendType" SG_ 930 CamraRearOn_B_RqBalrr 3; +BA_ "GenSigSendType" SG_ 930 DrLckCnt_No_ActlBalrr 3; +BA_ "GenSigSendType" SG_ 930 DrLckActv_B_RqBalrr 3; +BA_ "GenSigSendType" SG_ 929 BalrChimeLeft_D_Rq 3; +BA_ "GenSigStartValueInteger" SG_ 929 BalrLeft_D_Stat 2; +BA_ "GenSigStartValue" SG_ 929 BalrLeft_D_Stat 2; +BA_ "GenSigSendType" SG_ 929 BalrLeft_D_Stat 3; +BA_ "GenSigSendType" SG_ 929 BalrWndwLeft_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 929 WndwPsngrRear_D_RqBalrl 0; +BA_ "GenSigSendType" SG_ 929 WndwPsngrRear_D_RqBalrl 3; +BA_ "GenSigStartValueInteger" SG_ 929 WndwPsngr_D_RqBalrl 0; +BA_ "GenSigSendType" SG_ 929 WndwPsngr_D_RqBalrl 3; +BA_ "GenSigStartValueInteger" SG_ 929 WndwDrvRear_D_RqBalrl 0; +BA_ "GenSigSendType" SG_ 929 WndwDrvRear_D_RqBalrl 3; +BA_ "GenSigStartValueInteger" SG_ 929 WndwDrv_D_RqBalrl 0; +BA_ "GenSigSendType" SG_ 929 WndwDrv_D_RqBalrl 3; +BA_ "GenSigStartValueInteger" SG_ 929 BalrSnsLeft_D_Falt 0; +BA_ "GenSigSendType" SG_ 929 BalrSnsLeft_D_Falt 3; +BA_ "GenSigSendType" SG_ 929 BalrMdeSelLeft_B_Stat 3; +BA_ "GenSigStartValueInteger" SG_ 929 BalrMdeLeft_D_Stat 1; +BA_ "GenSigStartValue" SG_ 929 BalrMdeLeft_D_Stat 1; +BA_ "GenSigSendType" SG_ 929 BalrMdeLeft_D_Stat 3; +BA_ "GenSigSendType" SG_ 929 BalrLckLeft_B_Stat 3; +BA_ "GenSigSendType" SG_ 929 CamraRearOn_B_RqBalrl 3; +BA_ "GenSigSendType" SG_ 929 DrLckCnt_No_ActlBalrl 3; +BA_ "GenSigSendType" SG_ 929 DrLckActv_B_RqBalrl 3; +BA_ "CrossOver_InfoCAN" SG_ 402 ApaMdeStat_D_RqDrv 1; +BA_ "CrossOver_InfoCAN" SG_ 402 CamraZoomMan_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 402 CamraOvrlStat_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 402 CamraOvrlDyn_D_Rq 1; +BA_ "CrossOver_InfoCAN" SG_ 402 CamAutoTowbarZoom 1; +BA_ "CrossOver_InfoCAN" SG_ 402 DistanceBarSetting 1; +BA_ "GenSigStartValue" SG_ 924 DcacOut_Pw_Mx 2046; +BA_ "U_P702_MY2021_Rx" SG_ 924 DcacOut_Pw_Mx 1; +BA_ "GenSigStartValue" SG_ 924 DcacOut2_Pw_Actl 8190; +BA_ "U_P702_MY2021_Rx" SG_ 924 DcacOut2_Pw_Actl 1; +BA_ "GenSigStartValue" SG_ 924 DcacOut1_Pw_Actl 8190; +BA_ "U_P702_MY2021_Rx" SG_ 924 DcacOut1_Pw_Actl 1; +BA_ "GenSigStartValue" SG_ 924 DcacIn_Pw_Mx 2046; +BA_ "U_P702_MY2021_Rx" SG_ 924 DcacIn_Pw_Mx 1; +BA_ "GenSigStartValue" SG_ 923 DcacIn_U2_Actl 4094; +BA_ "GenSigStartValue" SG_ 923 DcacIn_U_Actl 4094; +BA_ "U_P702_MY2021_Rx" SG_ 923 DcacIn_U_Actl 1; +BA_ "GenSigStartValue" SG_ 923 DcacIn_I_Actl 2046; +BA_ "U_P702_MY2021_Rx" SG_ 923 DcacIn_I_Actl 1; +BA_ "GenSigStartValue" SG_ 923 Dcac_Te_Actl 254; +BA_ "U_P702_MY2021_Rx" SG_ 923 Dcac_Te_Actl 1; +BA_ "GenSigSendType" SG_ 1998 TesterPhysicalResSODR 3; +BA_ "GenSigSendType" SG_ 1996 TesterPhysicalResSODL 3; +BA_ "GenSigSendType" SG_ 1988 TesterPhysicalReqSODL 3; +BA_ "U_P702_MY2021_Rx" SG_ 922 DcacRdy_D_Stat 1; +BA_ "GenSigStartValue" SG_ 922 DcacPlugPrsnt_B_Stat 1; +BA_ "U_P702_MY2021_Rx" SG_ 922 DcacPlugPrsnt_B_Stat 1; +VAL_ 823 DteAcceptNew_B_Rq 1 "Yes" 0 "No"; +VAL_ 824 DteCldTrlrOn_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldTrlrOff_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldTraffic_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldTerrain_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldRoute_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldPayload_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldExtTe_B_Stat 1 "Yes" 0 "No"; +VAL_ 824 DteCldDcac_B_Stat 1 "Yes" 0 "No"; +VAL_ 949 Tire_Press_RR_ORR_Data 65535 "Not_Supported" 65534 "Invalid" 65533 "Unknown"; +VAL_ 949 Tire_Press_LR_OLR_Data 65535 "Not_Supported" 65534 "Invalid" 65533 "Unknown"; +VAL_ 949 Tire_Press_LF_Data 65535 "Not_Supported" 65534 "Invalid" 65533 "Unknown"; +VAL_ 949 Tire_Press_RF_Data 65535 "Not_Supported" 65534 "Invalid" 65533 "Unknown"; +VAL_ 740 BattAuxCnnct_B_Cmd 1 "Close" 0 "Open"; +VAL_ 1160 DgtlCommPncReset_B_Req 1 "Yes" 0 "No"; +VAL_ 1160 DataMntrSustn_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 1160 PwSustnRdata_B_RqTelem 1 "Active" 0 "Inactive"; +VAL_ 776 ScChrgrPwMax_Pw_RqCld 4095 "Faulty"; +VAL_ 776 PrcondEdit_D_RqCld 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "High" 3 "Medium" 2 "Low" 1 "Off" 0 "Null"; +VAL_ 776 GoTEditMnte_T_RqCld 15 "Faulty" 14 "NoDataExists" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Minute_55" 10 "Minute_50" 9 "Minute_45" 8 "Minute_40" 7 "Minute_35" 6 "Minute_30" 5 "Minute_25" 4 "Minute_20" 3 "Minute_15" 2 "Minute_10" 1 "Minute_5" 0 "Minute_0"; +VAL_ 776 GoTEditHr_T_RqCld 31 "Faulty" 30 "NoDataExists"; +VAL_ 776 ChrgToPcEdit_Pc_RqCld 127 "Faulty" 126 "NoDataExists"; +VAL_ 776 ScFreshDataEnbl_B_Rq 1 "Yes" 0 "No"; +VAL_ 776 ScEnbl_D_RqCld 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 775 ScDayOfWeekId_D_RqCld 7 "Sunday" 6 "Saturday" 5 "Friday" 4 "Thursday" 3 "Wednesday" 2 "Tuesday" 1 "Monday" 0 "NotUsed"; +VAL_ 775 ScChrgDurSet_D_RqCld 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 775 ScChrgDur_T_RqCld 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 774 ScLocLongPostv_B_RqCld 1 "Yes" 0 "No"; +VAL_ 774 ScLocLattPostv_B_RqCld 1 "Yes" 0 "No"; +VAL_ 774 ScLocDelete_B_RqCld 1 "Request" 0 "NoRequest"; +VAL_ 811 DistToStopover_L_Actl 65535 "Faulty"; +VAL_ 811 ExtLghtDsply_D_Stat 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 811 ExtLghtRight_D_RqMnu 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 811 AutoLghtOvrrd_B_RqDrv 1 "Allowed" 0 "NotAllowed"; +VAL_ 811 ExtLghtRear_D_RqMnu 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 811 ExtLghtLeft_D_RqMnu 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 811 ExtLghtFront_D_RqMnu 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 811 GoTEditMnte_T_RqMnu 15 "Faulty" 14 "NoDataExists" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Minute_55" 10 "Minute_50" 9 "Minute_45" 8 "Minute_40" 7 "Minute_35" 6 "Minute_30" 5 "Minute_25" 4 "Minute_20" 3 "Minute_15" 2 "Minute_10" 1 "Minute_5" 0 "Minute_0"; +VAL_ 811 GoTEditHr_T_RqMnu 31 "Faulty" 30 "NoDataExists"; +VAL_ 850 VehElRngeNut_L_Dsply 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 850 NxtUsgSocEst_Pc_Dsply 255 "Faulty" 254 "NoDataExists"; +VAL_ 850 EstmChrgTimeLP_St 255 "Invalid"; +VAL_ 850 EstmChrgTimeHP_St 255 "Invalid"; +VAL_ 850 ChargeNowDuration_St 255 "Invalid"; +VAL_ 563 DrvBhavWarn_B_Rq 1 "On" 0 "Off"; +VAL_ 563 OfbChrgSetSync_D_Rq 3 "Fail" 2 "Success" 1 "InProgress" 0 "NoSyncInProgress"; +VAL_ 563 KeyOffPwMde_D_Stat 7 "NotUsed_6" 6 "NotUsed_5" 5 "NotUsed_4" 4 "NotUsed_3" 0 "Inactive" 1 "On" 2 "NotUsed_1" 3 "NotUsed_2"; +VAL_ 563 ModemReset_D_Stat 15 "NotUsed_10" 14 "NotUsed_9" 13 "NotUsed_8" 12 "NotUsed_7" 11 "NotUsed_6" 10 "NotUsed_5" 9 "NotUsed_4" 8 "NotUsed_3" 7 "NotUsed_2" 6 "NotUsed_1" 5 "WifiHotSpotResetComplete" 4 "CcsResetComplete" 3 "OnlineTrafficResetComplete" 2 "PaakResetComplete" 1 "ResetNotComplete" 0 "Null"; +VAL_ 563 FactoryReset_St 3 "NotUsed_2" 2 "NotUsed_1" 1 "FactoryDefaultsRestored" 0 "Null"; +VAL_ 570 SuspClkSync_No_Rq 255 "Faulty" 254 "NoDataExists"; +VAL_ 570 SuspRearRight_L_Actl 511 "Faulty"; +VAL_ 570 SuspFrntRight_L_Actl 511 "Faulty"; +VAL_ 570 SuspRear_L_Prev 511 "Fault"; +VAL_ 570 SuspRear_L_Actl 511 "Fault"; +VAL_ 570 SuspFrnt_L_Prev 511 "Fault"; +VAL_ 570 SuspFrnt_L_Actl 511 "Fault"; +VAL_ 837 Ccd_B_Falt 1 "Yes" 0 "No"; +VAL_ 837 SelDrvMdeSusp_D_Stat 3 "Faulty" 2 "TemporarilyNotAvailable" 1 "Available" 0 "NotAvailable"; +VAL_ 837 AdptDrvMdePt_D_Rq 7 "Faulty" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "Powertrain2Sport" 2 "Powertrain2Normal" 1 "Powertrain2Comfort" 0 "AdaptiveNotActive"; +VAL_ 837 AdptDrvMdeChassis_D_Rq 7 "Faulty" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "Chassis2Sport" 2 "Chassis2Normal" 1 "Chassis2Comfort" 0 "AdaptiveNotActive"; +VAL_ 837 CcdMsgTxt_D_RqDsply 15 "Unused8" 14 "Unused7" 13 "Unused6" 12 "Unused5" 11 "Unused4" 10 "Unused3" 9 "Unused2" 8 "StationaryMode" 7 "Mode_Change_Unavailable" 6 "CCD_Temporarily_Off" 5 "CCD_Service_Required" 4 "Faulty" 3 "Sport" 2 "Normal" 1 "Comfort" 0 "No_Mode_Selected"; +VAL_ 885 BattULoChrg_D_RqOta 1 "Yes" 0 "No"; +VAL_ 885 VehStrtInhbt_T_Dsply 15 "NotUsed_12" 14 "NotUsed_11" 13 "NotUsed_10" 12 "NotUsed_9" 11 "NotUsed_8" 10 "NotUsed_7" 9 "NotUsed_6" 8 "NotUsed_5" 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "PostOtaActivatePermFail" 2 "PostOtaActivateWarning" 1 "DuringOtaActivate" 0 "NoMessage"; +VAL_ 885 VehStrtInhbt_D_Dsply 15 "NotUsed_12" 14 "NotUsed_11" 13 "NotUsed_10" 12 "NotUsed_9" 11 "NotUsed_8" 10 "NotUsed_7" 9 "NotUsed_6" 8 "NotUsed_5" 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "PostOtaActivatePermFail" 2 "PostOtaActivateWarning" 1 "DuringOtaActivate" 0 "NoMessage"; +VAL_ 885 VehOnRqstr_D_Stat 11 "NotUsed_8" 10 "NotUsed_7" 9 "NotUsed_6" 8 "NotUsed_5" 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "FleetVehInhbt" 2 "StolenVehInhbt" 1 "OverTheAir" 0 "NoRequestor" 15 "NotUsed_12" 14 "NotUsed_11" 13 "NotUsed_10" 12 "NotUsed_9"; +VAL_ 885 VehStrtInhbt_D_RqCld 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 885 VehOn_D_RqCld 3 "NoControl" 2 "On" 1 "Off" 0 "Null"; +VAL_ 885 OtaActv_D_Stat 15 "NotUsed_10" 14 "NotUsed_9" 13 "NotUsed_8" 12 "NotUsed_7" 11 "NotUsed_6" 10 "NotUsed_5" 9 "NotUsed_4" 8 "NotUsed_3" 7 "NotUsed_2" 6 "NotUsed_1" 5 "NonInterruptible_Pending" 4 "NonInterruptible_Config" 3 "NonInterruptible_ER" 2 "NonInterruptible_AB" 1 "Interruptible_AB" 0 "NoInVehicleOta"; +VAL_ 810 OBCCSerial_D_Rq 3 "PresentAndProvisioned" 2 "PresentAndProvAlertAck" 1 "PresentAndUnprovisioned" 0 "NotPresent"; +VAL_ 810 TlghtTest_D_RqArb 3 "TestEndAcknowledge" 2 "StartTest" 1 "StopTest" 0 "Null"; +VAL_ 810 ChrgrPncSustn_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 810 NtfyDrvTrgtDist_L_Rq 4095 "Trip_dist_alert_disabled" 0 "Inactive"; +VAL_ 810 NtfyDrvSocLvl1_Pc_Rq 127 "TargetSOCNotificationAlert" 0 "Inactive"; +VAL_ 810 PtRmtRprt_D_Stat 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "SettingUpdated" 10 "FastChargeComplete" 9 "ChargeNotOccurring" 8 "OneTimeSocReached" 7 "BatteryTemperatureRemind" 6 "ReducedPerformance" 5 "LimitedPerformance" 4 "ChargeFault" 3 "ChargeComplete" 2 "VehiclePreconditioned" 1 "TripDistanceAchieved" 0 "NoReportRequest"; +VAL_ 810 ChrgrPncEnbl_D_Rq 3 "NotUsed" 2 "Enable" 1 "Disable" 0 "Null"; +VAL_ 810 ExtLghtDsply_B_StatArb 1 "On" 0 "Off"; +VAL_ 810 ExtLghtRight_D_RqOta 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 810 ExtLghtRear_D_RqOta 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 810 ExtLghtLeft_D_RqOta 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 810 ExtLghtFront_D_RqOta 7 "NotUsed" 6 "PressToOn3" 5 "PressToOff3" 4 "PressToOn2" 3 "PressToOff2" 2 "PressToOn1" 1 "PressToOff1" 0 "Reset"; +VAL_ 550 PtWakeupActv1_B_Rq 1 "Wake_up_Powertrain_via_HW" 0 "Don_t_Wake_Up_Powertrain"; +VAL_ 639 OfbChrgPrflUpdate_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 639 OfbChrgClearAll_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 639 OfbChrgGoTTouch_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 639 OfbChrgGoTPrcond_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 639 OfbChrgGoTOn_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 639 OfbChrgGoTMnte_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Minute_55" 10 "Minute_50" 9 "Minute_45" 8 "Minute_40" 7 "Minute_35" 6 "Minute_30" 5 "Minute_25" 4 "Minute_20" 3 "Minute_15" 2 "Minute_10" 1 "Minute_5" 0 "Minute_0"; +VAL_ 639 OfbChrgGoTHr_T_Rq 31 "Faulty" 30 "NoDataExists"; +VAL_ 639 OfbChrgGoTExtHtr_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 639 OfbChrgGoTDelete_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 639 OfbChrgGoTUpdate_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 530 OfbChrgToPcWknd_D_Actl 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 530 OfbChrgToPcWkdy_D_Actl 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 530 OfbChrgSetNow_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 530 OfbChrgSetDelete_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 530 OfbChrgLocIdUns_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 1142 ConsTipV_No_Dsply 1023 "Faulty" 1022 "NoDataExists"; +VAL_ 817 ChildLckMde_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 817 VehLckInd_D_Rq 3 "NotUsed" 2 "On_Day" 1 "On_Night" 0 "Off"; +VAL_ 817 DrTgateOpen_B_Rq 1 "Open" 0 "Null"; +VAL_ 817 DrTgateExtSwMde_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 817 Remote_Device_Feedback 7 "Unused3" 6 "Unused2" 5 "Unused1" 4 "Shutdown" 3 "Running" 2 "Starting" 1 "Acknowledge" 0 "Null"; +VAL_ 817 Veh_Lock_Requestor 31 "Unused8" 30 "Unused7" 29 "Unused6" 28 "Rgtm_Shutlock_Switch" 27 "Boundary_Alert" 26 "Transit_Vehicle_Relock" 25 "Transit_Cargo_Relock" 24 "Transit_Ajar_Lock" 23 "Diagnostics" 22 "Console_Lock" 21 "Child_Lock" 20 "Double_Lock" 19 "Passive_Pasenger" 18 "Passive_Driver" 17 "Slam_Lock_Protect" 16 "SYNC" 15 "Passport" 14 "Passive_Smart_Unlock" 13 "Autorelock" 12 "RemoteStart" 0 "Null" 1 "Autolock" 11 "Smart_Unlock" 10 "Sliding_Door" 9 "Passive" 8 "Remote" 7 "Programming" 6 "Powerslide" 5 "Keypad" 4 "Key_Cylinder" 3 "Interior" 2 "Auto_Unlock"; +VAL_ 817 R_Pwr_Sliding_Dr_Rqst 1 "Active" 0 "Null"; +VAL_ 817 Power_Liftgate_Rqst 1 "Active" 0 "Null"; +VAL_ 817 Power_Decklid_Rqst 1 "Active" 0 "Null"; +VAL_ 817 L_Pwr_Sliding_Dr_Rqst 1 "Active" 0 "Null"; +VAL_ 817 Veh_Lock_Sub_Id 15 "Unused7" 14 "Unused6" 13 "Unused5" 12 "Unused4" 11 "Unused3" 10 "Unused2" 9 "Unused1" 8 "Customer_8" 7 "Customer_7" 6 "Customer_6" 5 "Customer_5" 4 "Customer_4" 3 "Customer_3" 2 "Customer_2" 1 "Customer_1" 0 "Null"; +VAL_ 817 Veh_Lock_Status 3 "UNLOCK_DRV" 2 "UNLOCK_ALL" 1 "LOCK_ALL" 0 "LOCK_DBL"; +VAL_ 817 ChildLck_D_Dsply 3 "NOT_SUPPORTED" 2 "ERROR" 1 "CHILD_UNLOCK" 0 "CHILD_LOCK"; +VAL_ 817 WindowLockout_B_Stat 1 "Locked" 0 "Unlock"; +VAL_ 817 Lockmsgtxt_D_Rq 7 "MSG7" 6 "MSG6" 5 "MSG5" 4 "MSG4" 3 "MSG3" 2 "MSG2" 1 "MSG1" 0 "NO_WARNING"; +VAL_ 817 FobComm_D_Stat 3 "NotUsed" 2 "RemEngStartOK" 1 "RemEngStartFail" 0 "Null"; +VAL_ 817 LockInhibit 1 "Inhibit" 0 "No_Inhibit"; +VAL_ 879 WndwRearHeat_I_Actl 2047 "Faulty"; +VAL_ 879 WndwRearHeat_D_Stat 7 "NotUsed" 6 "FetLiftLimitReached" 5 "FetOpenCircuit" 4 "FetOutputShortToPower" 3 "FetOutputShortToGround" 2 "FetNotControlled" 1 "OnPowerToLoad" 0 "OffNoPowerToLoad"; +VAL_ 878 DcacGfciTest_B_Rq 1 "Pressed" 0 "Not_Pressed"; +VAL_ 878 DcacOut_Pw_DsplyMx 1023 "Faulty"; +VAL_ 878 DcacOut1_Pw_Dsply 63 "Faulty"; +VAL_ 878 DcacOut2_Pw_Dsply 63 "Faulty"; +VAL_ 878 DcacHw_D_Confg 15 "NotUsed_11" 14 "NotUsed_10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "NotUsed_4" 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Power_2300W" 3 "Power_7200W" 2 "Power_2400W" 1 "Power_2000W" 0 "NoDcacHardware"; +VAL_ 878 DcacFaltMsgTxt_D_Rq 15 "NotUsed" 14 "OvercurrentLP" 13 "EngineRun" 12 "Service" 11 "NotAvailable" 10 "PlugWarn" 9 "PlugWarnDrive" 8 "BreakerC" 7 "BreakerB" 6 "BreakerA" 5 "FuelLow" 4 "AcOnOutput" 3 "Temperature" 2 "Gfci" 1 "Overcurrent" 0 "Ok"; +VAL_ 878 DcacLoFuelMsgTxt_D_Rq 31 "Minute_31" 30 "Minute_30" 29 "Minute_29" 28 "Minute_28" 27 "Minute_27" 26 "Minute_26" 25 "Minute_25" 24 "Minute_24" 23 "Minute_23" 22 "Minute_22" 21 "Minute_21" 20 "Minute_20" 19 "Minute_19" 18 "Minute_18" 17 "Minute_17" 16 "Minute_16" 15 "Minute_15" 14 "Minute_14" 13 "Minute_13" 12 "Minute_12" 11 "Minute_11" 10 "Minute_10" 9 "Minute_9" 8 "Minute_8" 7 "Minute_7" 6 "Minute_6" 5 "Minute_5" 4 "Minute_4" 3 "Minute_3" 2 "Minute_2" 1 "Minute_1" 0 "Ok"; +VAL_ 878 DcacEngOnMsgTxt_D_Rq 3 "NotUsed" 2 "DisplayQuestion" 1 "DisplayWarning" 0 "Ok"; +VAL_ 878 DcacElPw_D_Stat 3 "NotUsed" 2 "High" 1 "Low" 0 "Off"; +VAL_ 878 PwBedPnlEnbl_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 878 DcacOn_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 878 DcacSys_B_Falt 1 "Yes" 0 "No"; +VAL_ 878 DcacLedCtl_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 395 SelDrvMdeCnfm_D_Stat 3 "NotUsed" 2 "Accepted" 1 "NotAccepted" 0 "Null"; +VAL_ 984 PersIndexIpma_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 984 AhbcRampingV_D_Rq 3 "Slow" 2 "Medium" 1 "Fast" 0 "Immediately"; +VAL_ 984 LaActvStats_D_Dsply 31 "Unused7" 30 "LA_Off" 29 "Unused5" 28 "Unused4" 27 "Unused3" 26 "Unused2" 25 "Unused1" 24 "InerveneLeft_InterveneRght" 23 "WarnLeft_InterveneRight" 22 "SuppressLeft_InterveneRght" 21 "AvailLeft_InterveneRhtt" 20 "NoLeft_InterveneRight" 19 "InterveneLeft_WarnRight" 18 "WarnLeft_WarnRight" 17 "SuppressLeft_WarnRight" 16 "AvailableLeft_WarnRight" 15 "NoLeft_WarnRight" 14 "InterveneLeft_SuppressRght" 13 "WarnLeft_SuppressRight" 12 "SuppressLeft_SuppressRight" 11 "AvailLeft_SuppressRight" 10 "NoLeft_SuppressRight" 9 "InterveneLeft_AvailRight" 8 "WarnLeft_AvailRight" 7 "SuppressLeft_AvailRight" 6 "AvailableLeft_AvailRight" 5 "NoLeft_AvailableRight" 4 "InterveneLeft_NoRight" 3 "WarnLeft_NoRight" 2 "SuppressLeft_NoRight" 1 "AvailableLeft_NoRight" 0 "NoLeft_NoRight"; +VAL_ 984 LaDenyStats_B_Dsply 1 "Unavailable" 0 "Available"; +VAL_ 984 LaHandsOff_D_Dsply 3 "Suppressed" 2 "Level2" 1 "Level1" 0 "HandsOn"; +VAL_ 984 CamraDefog_B_Req 1 "On" 0 "Off"; +VAL_ 984 CamraStats_D_Dsply 3 "FrtCam_TempUnavailOther" 2 "FrtCam_TempUnavailVisibile" 1 "Front_Camera_Service_Reqd" 0 "Front_Camera_OK"; +VAL_ 984 DasAlrtLvl_D_Dsply 5 "Alertness_Level_5" 4 "Alertness_Level_4" 3 "Alertness_Level_3" 2 "Alertness_Level_2" 1 "Alertness_Level_1" 0 "Undefined"; +VAL_ 984 DasStats_D_Dsply 3 "Available" 2 "Unavailable_Other" 1 "Feedback_due_to_Speed" 0 "Off"; +VAL_ 984 DasWarn_D_Dsply 3 "Undefined" 2 "Warning_Level_2" 1 "Warning_Level_1" 0 "No_Warning"; +VAL_ 984 AhbHiBeam_D_Rq 3 "NotUsed" 2 "HighBeamRecommended" 1 "LowBeamRecommended" 0 "DeactivatedUnavailable"; +VAL_ 985 LdwChime_B_Rq 1 "On" 0 "Off"; +VAL_ 985 TsrRegionTxt_D_Stat 31 "Faulty" 30 "NotUsed_8" 29 "NotUsed_7" 28 "NotUsed_6" 27 "NotUsed_5" 26 "NotUsed_4" 25 "NotUsed_3" 24 "NotUsed_2" 23 "NotUsed_1" 22 "Region_22" 21 "Region_21" 20 "Region_20" 19 "Region_19" 18 "Region_18" 17 "Region_17" 16 "Region_16" 15 "Region_15" 14 "Region_14" 13 "Region_13" 12 "Region_12" 11 "Region_11" 10 "Region_10" 9 "Region_09" 8 "Region_08" 7 "Region_07" 6 "Region_06" 5 "Region_05" 4 "Region_04" 3 "Region_03" 2 "Region_02" 1 "Region_01" 0 "NotDetermined"; +VAL_ 985 SblmPedCrossScnr_B_Stat 1 "Yes" 0 "No"; +VAL_ 985 LongCtrlEnbl_D_Rq 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "RemoteParking" 2 "Autohitch" 1 "AutomaticParking" 0 "None"; +VAL_ 985 SblmRndAbtScnr_B_Stat 1 "Yes" 0 "No"; +VAL_ 985 DasAlrtInfo_D_Dsply 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 985 IaccVLim_D_Rq 252 "NotUsed_2" 250 "LimitSpeed_250" 240 "LimitSpeed_240" 230 "LimitSpeed_230" 220 "LimitSpeed_220" 210 "LimitSpeed_210" 200 "LimitSpeed_200" 190 "LimitSpeed_190" 150 "LimitSpeed_150" 140 "LimitSpeed_140" 130 "LimitSpeed_130" 120 "LimitSpeed_120" 110 "LimitSpeed_110" 100 "LimitSpeed_100" 90 "LimitSpeed_90" 80 "LimitSpeed_80" 70 "LimitSpeed_70" 60 "LimitSpeed_60" 50 "LimitSpeed_50" 40 "LimitSpeed_40" 30 "LimitSpeed_30" 20 "LimtSpeed_20" 251 "NotUsed_1" 255 "Faulty" 254 "NoDataExists" 253 "NotUsed_3" 180 "LimitSpeed_180" 179 "LimitSpeed_179" 178 "LimitSpeed_178" 177 "LimitSpeed_177" 176 "LimitSpeed_176" 175 "LimitSpeed_175" 174 "LimitSpeed_174" 173 "LimitSpeed_173" 172 "LimitSpeed_172" 171 "LimitSpeed_171" 170 "LimitSpeed_170" 169 "LimitSpeed_169" 168 "LimitSpeed_168" 167 "LimitSpeed_167" 166 "LimitSpeed_166" 165 "LimitSpeed_165" 164 "LimitSpeed_164" 163 "LimitSpeed_163" 162 "LimitSpeed_162" 161 "LimitSpeed_161" 160 "LimitSpeed_160" 15 "LimitSpeed_15" 14 "LimitSpeed_14" 13 "LimitSpeed_13" 12 "LimitSpeed_12" 11 "LimitSpeed_11" 10 "LimitSpeed_10" 9 "LimitSpeed_9" 8 "LimitSpeed_8" 7 "LimitSpeed_7" 6 "LimitSpeed_6" 5 "LimitSpeed_5" 4 "LimitSpeed_4" 3 "LimitSpeed_3" 2 "LimitSpeed_2" 1 "LimitSpeed_1" 0 "LimitSpeed_0"; +VAL_ 985 IaccVLimUnit_D_Rq 3 "NoDataExists" 2 "Mph" 1 "Kph" 0 "Null"; +VAL_ 985 IsaVLim_D_Rq 252 "NotUsed_2" 250 "LimitSpeed_250" 240 "LimitSpeed_240" 230 "LimitSpeed_230" 220 "LimitSpeed_220" 210 "LimitSpeed_210" 200 "LimitSpeed_200" 190 "LimitSpeed_190" 150 "LimitSpeed_150" 140 "LimitSpeed_140" 130 "LimitSpeed_130" 120 "LimitSpeed_120" 110 "LimitSpeed_110" 100 "LimitSpeed_100" 90 "LimitSpeed_90" 80 "LimitSpeed_80" 70 "LimitSpeed_70" 60 "LimitSpeed_60" 50 "LimitSpeed_50" 40 "LimitSpeed_40" 30 "LimitSpeed_30" 20 "LimtSpeed_20" 251 "NotUsed_1" 255 "Faulty" 254 "NoDataExists" 253 "NotUsed_3" 180 "LimitSpeed_180" 179 "LimitSpeed_179" 178 "LimitSpeed_178" 177 "LimitSpeed_177" 176 "LimitSpeed_176" 175 "LimitSpeed_175" 174 "LimitSpeed_174" 173 "LimitSpeed_173" 172 "LimitSpeed_172" 171 "LimitSpeed_171" 170 "LimitSpeed_170" 169 "LimitSpeed_169" 168 "LimitSpeed_168" 167 "LimitSpeed_167" 166 "LimitSpeed_166" 165 "LimitSpeed_165" 164 "LimitSpeed_164" 163 "LimitSpeed_163" 162 "LimitSpeed_162" 161 "LimitSpeed_161" 160 "LimitSpeed_160" 15 "LimitSpeed_15" 14 "LimitSpeed_14" 13 "LimitSpeed_13" 12 "LimitSpeed_12" 11 "LimitSpeed_11" 10 "LimitSpeed_10" 9 "LimitSpeed_9" 8 "LimitSpeed_8" 7 "LimitSpeed_7" 6 "LimitSpeed_6" 5 "LimitSpeed_5" 4 "LimitSpeed_4" 3 "LimitSpeed_3" 2 "LimitSpeed_2" 1 "LimitSpeed_1" 0 "LimitSpeed_0"; +VAL_ 985 SblmStopScnr_B_Stat 1 "Yes" 0 "No"; +VAL_ 985 SblmYieldScnr_B_Stat 1 "Yes" 0 "No"; +VAL_ 985 IsaVLimUnit_D_Rq 3 "NoDataExists" 2 "Mph" 1 "Kph" 0 "Null"; +VAL_ 985 AdbDividedRoad_B_Stat 1 "Yes" 0 "No"; +VAL_ 985 LcwaMsgTxt_D_Stat 3 "SodXFaulty" 2 "SodXBlocked" 1 "TrailerConnected" 0 "NoMessage"; +VAL_ 985 AdbDrvSide_B_Stat 1 "Left_Hand_Traffic" 0 "Right_Hand_Traffic"; +VAL_ 992 MsgCntrDsplyOp_D_Rq 7 "Unused_2" 6 "Unused_1" 5 "Copy" 4 "Restore" 3 "Upload" 2 "Set" 1 "Query" 0 "Null"; +VAL_ 992 MsgCntrPersIndex_D_Rq 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 943 VehVActlAdas_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 943 AdasLcDistToObj_L_Actl 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 515 PtIgnSwtch_D_Stat 3 "Faulty" 2 "No_Data_Exists" 1 "On" 0 "Off"; +VAL_ 1111 TrlrYawWActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 1111 TrlrYaw_W_Actl 65535 "Faulty" 65534 "NoDataExists"; +VAL_ 1111 TrlrHitYaw_AnRate_Actl 4095 "Fault" 4094 "NoDataExists"; +VAL_ 1111 TrlrHitchYaw_D_Stat 15 "Faulty" 14 "NotUsed_4" 13 "NotUsed_3" 12 "NotUsed_2" 11 "NotUsed_1" 10 "FaultyYrsuConnection" 9 "FaultyYrsu" 8 "HiConfdLrndAngle" 7 "LowConfdLrndAngle" 6 "HiConfdAngleMem" 5 "LowConfdAngleMem" 4 "InitNoTadAngle" 3 "InitInputs" 2 "TadTrlrDataOutOfRange" 1 "TadNotWithinSpecification" 0 "NoConnectionWithYrsu"; +VAL_ 1111 TrlrHitchYaw_An_Actl 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 1106 TrlrSnsId_No_Actl -1 "Faulty_FFFFFFFFFFFF" -2 "NoDataExists_FFFFFFFFFFFE"; +VAL_ 982 LatCtl_D2_Rq 7 "NotUsed_5" 6 "NotUsed_4" 5 "NotUsed_3" 4 "NotUsed_2" 3 "SafeRampOut" 2 "PathFollowingExtendedMode" 1 "PathFollowingLimitedMode" 0 "NoLateralControl"; +VAL_ 982 HandsOffCnfm_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 982 LatCtlRampType_D_Rq 3 "Immediately" 2 "Fast" 1 "Medium" 0 "Slow"; +VAL_ 982 LatCtlPrecision_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "Precise" 0 "Comfortable"; +VAL_ 1104 DrvEngageLevel_D_Stat 7 "Faulty" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Disengaged" 3 "Distracted" 2 "Attentive" 1 "Invalid" 0 "NotDetermined"; +VAL_ 1104 DrvImpLvlConfid_D_Stat 7 "Faulty" 6 "NotUsed" 5 "High" 4 "MediumHigh" 3 "Medium" 2 "LowMedium" 1 "Low" 0 "NotDetermined"; +VAL_ 1104 DrvImpairLvl_D_Stat 15 "Faulty" 14 "NotUsed_5" 13 "NotUsed_4" 12 "NotUsed_3" 11 "NotUsed_2" 10 "NotUsed_1" 9 "Incapacitated" 8 "Asleep" 7 "Microsleep" 6 "MostDrowsy" 5 "Drowsy_4" 4 "Drowsy_3" 3 "Drowsy_2" 2 "LeastDrowsy" 1 "Alert" 0 "NotDetermined"; +VAL_ 1104 DrvEngLvlConfid_D_Stat 7 "Faulty" 6 "NotUsed" 5 "High" 4 "MediumHigh" 3 "Medium" 2 "LowMedium" 1 "Low" 0 "NotDetermined"; +VAL_ 1104 DrvCamPassIR_D_Stat 3 "Faulty" 2 "Blocked" 1 "Ok" 0 "TemporaryUnavailable"; +VAL_ 1104 DrvCamera_D_Stat 3 "Faulty" 2 "Blocked" 1 "Ok" 0 "TemporaryUnavailable"; +VAL_ 1104 DrvCamDrvIR_D_Stat 3 "Faulty" 2 "Blocked" 1 "Ok" 0 "TemporaryUnavailable"; +VAL_ 1104 DrvAttentZone_D_Stat 15 "Faulty" 14 "NotUsed_5" 13 "NotUsed_4" 12 "NotUsed_3" 11 "NotUsed_2" 10 "NotUsed_1" 9 "PassengerSideWindow" 8 "DriverSideWindow" 7 "DriverSideMirror" 6 "RearviewMirror" 5 "PassengerSideMirror" 4 "Infotainment" 3 "Cluster" 2 "FrontWindshield" 1 "Other" 0 "NotDetermined"; +VAL_ 1104 DrvAlertSt_D_Stat 3 "Faulty" 2 "EyesOffRoad" 1 "EyesOnRoad" 0 "NotDetermined"; +VAL_ 1114 TrailCtlSwtch_B_Stat2 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1114 TrlBrkInitOut_D_Rq 3 "Heavy" 2 "Medium" 1 "Light" 0 "Null"; +VAL_ 1116 TrlrAidSetup_D2_Rq 15 "NotUsed_9" 14 "NotUsed_8" 13 "NotUsed_7" 12 "NotUsed_6" 11 "NotUsed_5" 10 "NotUsed_4" 9 "NotUsed_3" 8 "NotUsed_2" 7 "NotUsed_1" 6 "CompleteSetup" 5 "ReturnToSetup" 4 "StickerNotCircled" 3 "ConfirmSetup" 2 "EndSetup" 1 "BeginSetup" 0 "Inactive"; +VAL_ 1116 TrlrAidEnbl_D2_Rq 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Deactivate" 2 "ActivateTrg" 1 "ActivateTba" 0 "Inactive"; +VAL_ 1116 TrlrRvrseCancl_B_Rq 1 "Cancel" 0 "Null"; +VAL_ 1116 TrlrIdType_D_Stat 3 "Gooseneck" 2 "FifthWheel" 1 "Conventional" 0 "Null"; +VAL_ 1116 TrlrAnOffstDir_D_Mem 3 "NotUSed" 2 "Right" 1 "Left_or_Center" 0 "Null"; +VAL_ 1085 ULoRgenTestMde_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1085 PwSrcULoOvrTe_B_Actl 1 "Yes" 0 "No"; +VAL_ 1085 PwSrcULoFalt_D_Stat 3 "Fault_No_Output" 2 "Fault_Reduced_Output" 1 "Fault_NonSpecific" 0 "No_Fault"; +VAL_ 1085 PwSrcULoDcnnt_B_Stat 1 "Loose_or_Disconnected" 0 "Connected"; +VAL_ 1085 PwSrcULo_Pc_Mx 255 "Fault"; +VAL_ 1085 PwSrcULoComm_B_Falt 1 "Fault" 0 "No_Fault"; +VAL_ 1085 PwSrcULo_I_Mx 255 "Fault"; +VAL_ 1085 PwSrcULo_I_Actl 255 "Fault"; +VAL_ 981 AdbBrdrTop_An_Rq 255 "Faulty" 254 "NoDataExists"; +VAL_ 981 AdbBrdrRight_L_Stat 511 "Faulty" 510 "NoDataExists"; +VAL_ 981 AdbBrdrRight_An_Rq 1023 "Faulty" 1022 "NoDataExists"; +VAL_ 981 AdbBrdrLeft_L_Stat 511 "Faulty" 510 "NoDataExists"; +VAL_ 981 AdbBrdrLeft_An_Rq 1023 "Faulty" 1022 "NoDataExists"; +VAL_ 981 AdbBrdrBottom_An_Rq 63 "Faulty" 62 "NoDataExists"; +VAL_ 981 AdbBeam_D_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "FullHighBeam" 3 "Spot_BothSide" 2 "Spot_OnlyRightSide" 1 "Spot_OnlyLeftSide" 0 "NoHighBeam"; +VAL_ 791 EngAirFilt_B_RqReset 1 "Yes" 0 "No"; +VAL_ 791 GpsElMdeSel_B_Rq 1 "On" 0 "Off"; +VAL_ 791 LongTermReset_B_Rq 1 "On" 0 "Off"; +VAL_ 791 DrvEffLvl_No_Stat 63 "Fault" 62 "NoDataExists"; +VAL_ 868 BattRgenLoStat_D_Qlty 3 "OK" 2 "Not_Within_Spec" 1 "Eval_In_Progress" 0 "Faulty"; +VAL_ 868 BattRgenLoPrtct_B_Stat 1 "Yes" 0 "No"; +VAL_ 868 BattRgenLoDChrg_D_Stat 3 "StuckClosed" 2 "StuckOpen" 1 "Closed" 0 "Open"; +VAL_ 868 BattRgenLoDchrg_B_Rq 1 "Yes" 0 "No"; +VAL_ 868 BattRgenLoChrg_D_Stat 3 "StuckClosed" 2 "StuckOpen" 1 "Closed" 0 "Open"; +VAL_ 868 BattRgenLoChrg_B_Rq 1 "Yes" 0 "No"; +VAL_ 868 BattRgenLo_B_Falt 1 "Yes" 0 "No"; +VAL_ 867 BattRgenLoBalnc_B_Rq 1 "Yes" 0 "No"; +VAL_ 867 BattRgenLo_Te_Actl 255 "Fault"; +VAL_ 865 BattRgenLo_U_Actl 2047 "Faulty"; +VAL_ 865 BattRgenLo_I_Actl 65535 "Faulty"; +VAL_ 1144 WakeAlarm0_B_Typ 1 "CanAndEcuDriveCircuit" 0 "CanOnly"; +VAL_ 1144 PreCondBatt_B_Actl 1 "On" 0 "Off"; +VAL_ 1144 HtrnDcdcDis_B_Rq 1 "Yes" 0 "No"; +VAL_ 1144 ChrgNowEvnt_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1144 CabinDrvSustn_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 1144 BattChrgTrgtSoC_D_Rq 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 1144 CabnEvapSovFront_B_Rq 1 "On" 0 "Off"; +VAL_ 1144 HeatCoreSovRear_B_Rq 1 "On" 0 "Off"; +VAL_ 1144 BattChlrSov_B_Rq 1 "On" 0 "Off"; +VAL_ 1144 CabnEvapSovRear_B_Rq 1 "On" 0 "Off"; +VAL_ 1144 BrkAppl_D_RqPt 3 "BrakesSlowRelease" 2 "BrakesFastRelease" 1 "BrakesEngage" 0 "NotActive"; +VAL_ 1144 HtrnCnnctPwr_B_Stat 1 "Asserted" 0 "NotAsserted"; +VAL_ 1144 PtcHtr_D_Stat 3 "Faulty" 2 "NotUsed" 1 "On" 0 "Off"; +VAL_ 1144 HtrnClntFlw_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 1144 BattTracDrvSustn_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 1144 BattTracClntVlv_B_Rq 1 "On" 0 "Off"; +VAL_ 1141 OfbChrgSetSync_D_Stat 3 "Fail" 2 "Success" 1 "InProgress" 0 "NoSyncInProgress"; +VAL_ 1141 PtRmtRprt_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "PlugInToMaintain12vBattery" 11 "SettingUpdated" 10 "FastChargeComplete" 9 "ChargeNotOccurring" 8 "OneTimeSocReached" 7 "BatteryTemperatureReminder" 6 "ReducedPerformance" 5 "LimitedPerformance" 4 "ChargeFault" 3 "ChargeComplete" 2 "VehiclePreconditioned" 1 "TripDistanceAchieved" 0 "NoReportRequest"; +VAL_ 1141 NtfctnConflict1_D_Rq 7 "NotUsed5" 6 "NotUsed4" 5 "NotUsed3" 4 "NotUsed2" 3 "NotUsed1" 2 "Clonflict_Exists" 1 "No_Conflict" 0 "Invalid"; +VAL_ 1140 RgenEvntLvl_Pc_Dsply 1023 "Fault" 1022 "NoDataExists"; +VAL_ 1140 BrkEvntComplt_B_Dsply 1 "On" 0 "Off"; +VAL_ 1140 PreCondStat_D_Dsply 7 "Reserved3" 6 "Reserved2" 5 "Reserved1" 4 "Faulted" 3 "Complete" 2 "In_Progress" 1 "Scheduled" 0 "Not_Scheduled"; +VAL_ 1139 BattChrgTrgtLMax_T_Est 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 1139 ActChrgStrtYr_No_Actl 31 "Invalid"; +VAL_ 1139 ActChrgStrtMin_No_Actl 63 "Invalid" 62 "Unknown"; +VAL_ 1139 ActChrgStrtHr_No_Actl 31 "Invalid" 30 "Unknown"; +VAL_ 1139 ActChrgStrtDay_No_Actl 31 "Invalid"; +VAL_ 1139 ActChrgStrMnth_No_Actl 15 "Invalid"; +VAL_ 1138 BattChrgTrgtLMin_T_Est 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 1138 ActChrgEndYr_No_Actl 31 "Invalid"; +VAL_ 1138 ActChrgEndMnth_No_Actl 15 "Invalid"; +VAL_ 1138 ActChrgEndMin_No_Actl 63 "Invalid" 62 "Unknown"; +VAL_ 1138 ActChrgEndHr_No_Actl 31 "Invalid" 30 "Unknown"; +VAL_ 1138 ActChrgEndDay_No_Actl 31 "Invalid"; +VAL_ 1089 Mtr2Aout_W_ActlMntr 1023 "Faulty"; +VAL_ 1089 Inv1_Te_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 1089 MtrTrac2Coil_Te_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 1089 MtrTrac2Falt_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1089 MtrTrac2TeAlrm_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1089 Mtr2CntlTeAlrm_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1089 MtrTrac2Inv_Te_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 1089 MtrTrac2_I_Actl 65535 "Faulty"; +VAL_ 1088 ChrgTMatch_B_Stat 1 "True" 0 "False"; +VAL_ 1088 ChrgStat_D2_Dsply 15 "NotUsed_2" 14 "NotUsed_1" 13 "ChargeTargetReached" 12 "DriveConditioning" 11 "CabinPreconditioning" 10 "ChargingSystemMaintain" 9 "ChargingInductive" 8 "ChargingDCFastChange" 7 "ChargingAC" 6 "ChargeScheduled" 5 "EvsePaused" 4 "EvseNotDetected" 3 "EvseNotCompatible" 2 "FaultOutsideCar" 1 "FaultInsideCar" 0 "NotReady"; +VAL_ 1088 HvacPrecondRecirc_D_Rq 3 "Last_User_Setting" 2 "Auto" 1 "Recirc" 0 "Outside"; +VAL_ 1088 HvacPrecondMode2_D_Rq 15 "NotUsed4" 14 "NotUsed3" 13 "NotUsed2" 12 "NotUsed1" 11 "Last_User_Settings" 10 "Auto" 9 "Max_Defrost" 8 "Windshield_Panel_Floor" 7 "Windshield_Panel" 6 "Windshield" 5 "Windshield_Floor" 4 "Floor" 3 "Panel_Floor" 2 "Panel" 1 "MAX_AC" 0 "Off"; +VAL_ 1088 HvacPrecondBlwr2_D_Rq 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "Last_User_Setting" 8 "Auto" 7 "Speed7" 6 "Speed6" 5 "Speed5" 4 "Speed4" 3 "Speed3" 2 "Speed2" 1 "Speed1" 0 "Off"; +VAL_ 1088 HvacPrecondAC_D_Rq 3 "Last_User_Setting" 2 "Auto" 1 "On" 0 "Off"; +VAL_ 1088 BattChrgInhbt_D_Rq 3 "MaintainTargetSoc" 2 "NotUsed" 1 "InhibitChargingThermal" 0 "Enable_Charging"; +VAL_ 1040 ElCmprEnbl_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 1016 ChrgGoTElement_B_Dsply 1 "Yes" 0 "No"; +VAL_ 1016 ChrgGoTTouchEnbl_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 1016 ChrgGoTTouch_B_Stat 1 "On" 0 "Off"; +VAL_ 1016 ChrgGoTPrcond_D_Stat 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 1016 ChrgGoTMnte_D_Stat 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Minute_55" 10 "Minute_50" 9 "Minute_45" 8 "Minute_40" 7 "Minute_35" 6 "Minute_30" 5 "Minute_25" 4 "Minute_20" 3 "Minute_15" 2 "Minute_10" 1 "Minute_5" 0 "Minute_0"; +VAL_ 1016 ChrgGoTHr_T_Stat 31 "Faulty" 30 "NoDataExists"; +VAL_ 1016 ChrgGoTExtHtrEnbl_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 1016 ChrgGoTExtHtr_B_Stat 1 "On" 0 "Off"; +VAL_ 1016 ChrgGoTAllOn_B_Stat 1 "On" 0 "Off"; +VAL_ 1013 ChrgToPcWkndSav_D_Stat 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 1013 ChrgToPcWkdySav_D_Stat 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 1013 ChrgNowEnbl_B_Saved 1 "On" 0 "Off"; +VAL_ 1013 ChrgLocIdUnsAck_B_Stat 1 "Yes" 0 "No"; +VAL_ 1012 ChrgNowCurnt_B_Dsply 1 "On" 0 "Off"; +VAL_ 1012 ChrgLocSaved_B_Dsply 1 "Yes" 0 "No"; +VAL_ 1012 ChrgLocLongPostv_B_Sav 1 "Yes" 0 "No"; +VAL_ 1012 ChrgLocLattPostv_B_Sav 1 "Yes" 0 "No"; +VAL_ 1011 ChrgLocLongPostv_B_Uns 1 "Yes" 0 "No"; +VAL_ 1011 ChrgLocLattPostv_B_Uns 1 "Yes" 0 "No"; +VAL_ 871 BattElecPerf_D_Actl 7 "NotUsed" 6 "Hot_Batt_Severe_Lim_Perf" 5 "Hot_Batt_Reduced_Perf" 4 "Hot_Batt_Close_to_lim_Per" 3 "Cold_Batt_Severe_Lim_Perf" 2 "Cold_Batt_Reduced_Perf" 1 "Cold_Batt_Close_to_lim_Pe" 0 "Ok_no_message_displayed"; +VAL_ 871 BattChrgTrgtLPt_T_Est 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 871 BattChrgTrgSocPt_T_Est 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 871 BattChrgCmpltPt_T_Est 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 786 RgenTrip_L_Dsply 65535 "Fault" 65534 "NoDataExists"; +VAL_ 786 ChrgStat_D_Dsply 7 "NotUsed" 6 "Complete" 5 "Scheduled" 4 "In_Progress" 3 "Fault_Outside_Car" 2 "Fault_Inside_Car" 1 "Fault_Unknown_Location" 0 "Not_Ready"; +VAL_ 72 immoTarget2Status 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "DISABLED_RESET " 2 "ENABLED_NONMOTIVE_START" 1 "ENABLED_MOTIVE_START" 0 "DISABLED"; +VAL_ 72 immoTarget2Cmd 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "TARGET1_IDBLOCK2" 2 "TARGET1_IDBLOCK1" 1 "CHALLENGE" 0 "IDLE"; +VAL_ 912 CabnEvapSovFront_D_Stat 7 "NotUsed_1" 6 "FetLifeLimitReached" 5 "FetOpenCircuit" 4 "FetOutputShortToPower" 3 "FetOutputShortToGround" 2 "FetNotControlled" 1 "OnPowerToLoad" 0 "OffNoPowerToLoad"; +VAL_ 912 BattChlrSov_D_Stat 7 "NotUsed_1" 6 "FetLifeLimitReached" 5 "FetOpenCircuit" 4 "FetOutputShortToPower" 3 "FetOutputShortToGround" 2 "FetNotControlled" 1 "OnPowerToLoad" 0 "OffNoPowerToLoad"; +VAL_ 912 BattTracClntVlv_D_Stat 7 "NotUsed" 6 "FetLifeLimitReached" 5 "FetOpenCircuit" 4 "FetOutputShortToPower" 3 "FetOutputShortToGround" 2 "FetNotControlled" 1 "OnPowerToLoad" 0 "OffNoPowerToLoad"; +VAL_ 874 AirCondCluOpen_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 AirCondCluLife_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 AirCondCluGnd_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 AirCondClu_D_Stat 7 "NotUsed" 6 "FetLifeLimitReached" 5 "FetOpenCircuit" 4 "FetOutputShortToPower" 3 "FetOutputShortToGround" 2 "FetNotControlled" 1 "OnPowerToLoad" 0 "OffNoPowerToLoad"; +VAL_ 874 AirCondCluBatt_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattTracShrtGrnd_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattTracShrtBatt_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattTracOpnCirct_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattTracLifeLim_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattChlrShrtGrnd_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattChlrShrtBatt_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattChlrOpnCirct_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattChlrLifeLim_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 874 BattTracLow_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 651 TelematicsSrvc_D_St 7 "NotUsed" 6 "NotifyNotActivatedYet" 5 "NotActivatedYet" 4 "NotifyExpired" 3 "Expired" 2 "ExpiringSoon" 1 "Active" 0 "Null"; +VAL_ 651 EmgcyCallMute_D_Stat 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "ManualEmergencyCallMute" 2 "AutomaticEmergencyCallMute" 1 "EmergencyCallUnmute" 0 "Null"; +VAL_ 651 OfbChrgSetSync_D_Rq 3 "Fail" 2 "Success" 1 "InProgress" 0 "NoSyncInProgress"; +VAL_ 529 OnbChrgToPcWknd_D_Actl 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 529 OnbChrgToPcWkdy_D_Actl 7 "Percent_50" 6 "Percent_60" 5 "Percent_70" 4 "Percent_80" 3 "Percent_85" 2 "Percent_90" 1 "Percent_95" 0 "Percent_100"; +VAL_ 529 OnbChrgSetNow_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 529 OnbChrgSetDelete_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 529 OnbChrgPrflUpdate_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 529 OnbChrgLocIdUns_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 66 immoControlCmd_T2 0 "IDLE" 1 "MOTIVE_START_RQST" 2 "NONMOTIVE_START_RQST" 3 "RQST_TARGET2_IDBLOCK1" 4 "RQST_TARGET2_IDBLOCK2" 5 "Unused" 6 "ECHO_TARGET2_IDBLOCK2" 7 "SHUTDOWN"; +VAL_ 1124 GPS_Vdop 31 "Invalid" 30 "Unknown"; +VAL_ 1124 GPS_Speed 255 "Invalid" 254 "Unknown"; +VAL_ 1124 GPS_Sat_num_in_view 31 "Invalid" 30 "Unknown"; +VAL_ 1124 GPS_MSL_altitude 4095 "Fault" 4094 "Unknown"; +VAL_ 1124 GPS_Heading 65535 "Fault" 65534 "Unknown"; +VAL_ 1124 GPS_Hdop 31 "Invalid" 30 "Unknown"; +VAL_ 1124 GPS_dimension 2 "_3D" 1 "_2D" 0 "No_Fix"; +VAL_ 1119 CoolFanDcdc_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 1119 DcdcClntFlw_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 1123 GpsUtcYr_No_Actl 31 "Fault"; +VAL_ 1123 GpsUtcMnth_No_Actl 15 "Fault"; +VAL_ 1123 GPS_UTC_seconds 63 "Fault" 62 "Unknown"; +VAL_ 1123 GPS_UTC_minutes 63 "Fault" 62 "Unknown"; +VAL_ 1123 GPS_UTC_hours 31 "Invalid" 30 "Unknown"; +VAL_ 1123 GPS_Pdop 31 "Invalid" 30 "Unknown"; +VAL_ 1123 GPS_Compass_direction 7 "NorthWest" 6 "West" 5 "SouthWest" 4 "South" 3 "SouthEast" 2 "East" 1 "NorthEast" 0 "North"; +VAL_ 1123 GPS_Actual_vs_Infer_pos 1 "Inferred_Position" 0 "Actual_Postition"; +VAL_ 1123 Gps_B_Falt 1 "Yes" 0 "No"; +VAL_ 1122 GpsHsphLongEast_D_Actl 0 "Invalid" 1 "Eastern" 2 "Western" 3 "Fault"; +VAL_ 1122 GpsHsphLattSth_D_Actl 3 "Fault" 2 "Northern" 1 "Southern" 0 "Invalid"; +VAL_ 1122 GPS_Longitude_Minutes 63 "Fault" 62 "Unknown"; +VAL_ 1122 GPS_Longitude_Min_dec 16383 "Invalid" 16382 "Unknown"; +VAL_ 1122 GPS_Longitude_Degrees 511 "Fault" 510 "Unknown"; +VAL_ 1122 GPS_Latitude_Minutes 63 "Fault" 62 "Unknown"; +VAL_ 1122 GPS_Latitude_Min_dec 16383 "Invalid" 16382 "Unknown"; +VAL_ 1122 GPS_Latitude_Degrees 255 "Invalid" 254 "Unknown"; +VAL_ 1003 PersRecallSrc_D_Actl 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "MemorySwitch" 3 "RemoteStart" 2 "KeyFob" 1 "CenterStack" 0 "Null"; +VAL_ 1003 Pers4Key_D_Stat 3 "NotUsed_1" 2 "KeyUnAssociated" 1 "KeyAssociated" 0 "Null"; +VAL_ 1003 Pers3Key_D_Stat 3 "NotUsed_1" 2 "KeyUnAssociated" 1 "KeyAssociated" 0 "Null"; +VAL_ 1003 Pers2Key_D_Stat 3 "NotUsed_1" 2 "KeyUnAssociated" 1 "KeyAssociated" 0 "Null"; +VAL_ 1003 Pers1Key_D_Stat 3 "NotUsed_1" 2 "KeyUnAssociated" 1 "KeyAssociated" 0 "Null"; +VAL_ 1003 EmPrflNo_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Pers4" 3 "Pers3" 2 "Pers2" 1 "Pers1" 0 "Null"; +VAL_ 1003 EmPrflKeyAssoc_D_Stat 7 "WrongDevice" 6 "KeyAssociateFailed" 5 "KeyAssociateSuccess" 4 "KeyAlreadyInUse" 3 "KeyDisassociated" 2 "KeyAssociationExited" 1 "KeyAssociationEntered" 0 "Null"; +VAL_ 1003 VehKeyActv_D_Stat 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "NotUsed3" 10 "NotUsed2" 9 "NotUsed1" 8 "Key8Active" 7 "Key7Active" 6 "Key6Active" 5 "Key5Active" 4 "Key4Active" 3 "Key3Active" 2 "Key2Active" 1 "Key1Active" 0 "NoKeyActive"; +VAL_ 1003 PersNoPos_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 1003 PersSetupRestr_D_Actl 3 "Non_Moveable_Person" 2 "Moveable_Person" 1 "Vehicle" 0 "Factory"; +VAL_ 1003 PersSetupAccessCtrl 1 "Limited" 0 "Full"; +VAL_ 1003 PersConflict_D_Actl 1 "Conflict" 0 "No_Conflict"; +VAL_ 1003 AssocConfirm_D_Actl 0 "None" 7 "Associate" 6 "Keycode_Rejected" 5 "Keycode_Accepted" 4 "In_Progress" 3 "Erase" 2 "Duplicate" 1 "Disassociate"; +VAL_ 1003 PersNo_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "NotDetermined" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 994 PersStore_D_Rq 7 "Unused_2" 6 "Unused_1" 5 "Vehicle" 4 "PERS_4" 3 "PERS_3" 2 "PERS_2" 1 "PERS_1" 0 "Null"; +VAL_ 994 Pers4OptIn_B_Stats 1 "OPTED_IN" 0 "NOT_OPTED_IN"; +VAL_ 994 Pers3OptIn_B_Stats 1 "OPTED_IN" 0 "NOT_OPTED_IN"; +VAL_ 994 Pers2OptIn_B_Stats 1 "OPTED_IN" 0 "NOT_OPTED_IN"; +VAL_ 994 Pers1OptIn_B_Stats 1 "OPTED_IN" 0 "NOT_OPTED_IN"; +VAL_ 994 CtrStkPersIndex_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 994 CtrStkDsplyOp_D_Rq 7 "Unused_2" 6 "Unused_1" 5 "Copy" 4 "Restore" 3 "Upload" 2 "Set" 1 "Query" 0 "Null"; +VAL_ 778 PrkAidFront_D_RqDrv 2 "Status" 3 "NotUsed" 1 "Enabled" 0 "Disabled"; +VAL_ 778 PrkAidAcsyRear_D_RqDrv 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 778 PrkAidAcsyFront_D_RqDrv 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 778 Cta_D_Rq 3 "Unused" 2 "NoDataExists" 1 "On" 0 "Off"; +VAL_ 778 PrkAidRear_D_RqDrv 2 "Status" 3 "NotUsed" 1 "Enabled" 0 "Disabled"; +VAL_ 778 SteEffort_D_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "SpecialMode_2" 3 "SpecialMode_1" 2 "Comfort" 1 "Sport" 0 "Normal"; +VAL_ 778 Sod_D_Rq 2 "BLIS_On_Second_Warning_ON" 1 "BLIS_On_Second_Warning_OFF" 0 "Off"; +VAL_ 549 IPC_MyKeyVolLimit_St 0 "Invalid" 1 "Off" 2 "On"; +VAL_ 549 HdcOn_B_Rq 1 "On" 0 "Off"; +VAL_ 549 IPC_Attn_Info_Audio 7 "Unknown" 6 "Attenuation_6" 5 "Attenuation_5" 4 "Attenuation_4" 3 "Attenuation_3" 2 "Attenuation_2" 1 "Attenuation_1" 0 "No_Attenuation_of_Audio"; +VAL_ 549 BeltminderAudioMute 2 "On" 1 "Off" 0 "Invalid"; +VAL_ 549 Power_Up_Chime_Modules 1 "Active" 0 "Inactive"; +VAL_ 549 Chime_Source 2 "Cluster" 1 "Infotainment_Sys" 0 "Invalid"; +VAL_ 549 IPC_New_Attn_Event 1 "Active" 0 "Inactive"; +VAL_ 551 PmCabnLvl_D_Stat 7 "NotUsed_1" 6 "Level_6_Worst" 5 "Level_5" 4 "Level_4" 3 "Level_3" 2 "Level_2" 1 "Level_1_Best" 0 "NotKnown"; +VAL_ 551 PmCabn_D_Stat 3 "FilteringComplete" 2 "FilteringOn" 1 "FilteringOff" 0 "NotKnown"; +VAL_ 551 Cntr_Plg_Mode_Cmd 1 "Enable" 0 "Disable"; +VAL_ 551 ChrgCrdLckEnbl_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 551 PwRnngBoardT_D_Rq 3 "NotUsed" 2 "Timer2" 1 "Timer1" 0 "Inactive"; +VAL_ 551 PwRnngBoardSwtch_D_Rq 3 "NotUsed" 2 "DeployUnlocked" 1 "AlwaysActive" 0 "Inactive"; +VAL_ 551 PwRnngBoardMde_D_Rq 0 "Inactive" 1 "Off" 2 "Out" 3 "Auto"; +VAL_ 551 Btt_L_Actl2 127 "Faulty" 126 "NoDataExists"; +VAL_ 551 Rba_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 551 EmPrflNo_D_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Pers4" 3 "Pers3" 2 "Pers2" 1 "Pers1" 0 "Null"; +VAL_ 551 EmPrflButtnAssoc_D_Rq 3 "NotUsed" 2 "ExitButtonAssociation" 1 "EnterButtonAssociation" 0 "Null"; +VAL_ 551 EmPrflKeyAssoc_D_Rq 7 "NotUsed_3" 6 "DisassociatePhone" 5 "EnterPhoneAssociation" 4 "OverwriteKey" 3 "DisassociateKey" 2 "ExitKeyAssociation" 1 "EnterKeyAssociation" 0 "Null"; +VAL_ 551 Em_D_Stat 3 "NotSupported" 2 "ProfilesOff" 1 "ProfilesOn" 0 "Null"; +VAL_ 551 ChrgOvrdExitScrn_D_Rq 3 "NotUsed_1" 2 "Request_override" 1 "Do_not_request_override" 0 "Inactive"; +VAL_ 1010 MbdblActv_B_RqAdas 1 "Yes" 0 "No"; +VAL_ 1010 CbdblActv_B_RqAdas 1 "Yes" 0 "No"; +VAL_ 1010 AdbUrbanArea_B_Stat 1 "Yes" 0 "No"; +VAL_ 1070 BattULo24_D_Falt 3 "NotUsed" 2 "TemporaryFault" 1 "Fault" 0 "NoFault"; +VAL_ 1070 BattULo24_Te_Actl 127 "Fault"; +VAL_ 1070 BattULo24State_D_Qlty 3 "OK" 2 "Not_Within_Spec" 1 "Eval_In_Progress" 0 "Faulty"; +VAL_ 1070 BattULo24_I_Actl 16383 "Faulty"; +VAL_ 1070 BattULo24_B_Falt 1 "Yes" 0 "No"; +VAL_ 1186 SelDrvMdeAwd2_D_Stat 31 "Faulty" 30 "NotUsed_17" 29 "NotUsed_16" 28 "NotUsed_15" 27 "NotUsed_14" 26 "NotUsed_13" 25 "NotUsed_12" 24 "NotUsed_11" 23 "NotUsed_10" 22 "NotUsed_9" 21 "NotUsed_8" 20 "NotUsed_7" 19 "NotUsed_6" 18 "NotUsed_5" 17 "EvLaterChargeMode" 16 "EvNowMode" 15 "TrackMode" 14 "RoughRoadMode" 13 "NotAvailable" 12 "HighSpeedDesertMode_Baja" 11 "SportAdaptiveMode" 10 "RockCrawlMode" 9 "MudRutsMode" 8 "SandMode" 7 "EconomyMode" 6 "GrassGravelSnow" 5 "TowHaulMode" 4 "SportMode" 3 "Normal_4L" 2 "Normal_4A" 1 "Normal_2H" 0 "NormalMode"; +VAL_ 1186 RearDiffLckMsg_D_Rq 7 "Locker_Disabled" 6 "Locker_Enabled" 5 "Locker_Accel_Pedal" 4 "Speed4" 3 "Speed3" 2 "Spee2" 1 "Speed1" 0 "Normal__No_Message "; +VAL_ 1186 RearDiffLckLamp_D_Rq 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 1186 RearDiffLck_Tq_Actl 4095 "Fault" 4094 "Unknown"; +VAL_ 1186 RearDiffFalt_D_Stat 3 "Diff_Failed_Closed" 2 "Diff_Failed_Open" 1 "Fault_Non_Specific" 0 "No_Fault"; +VAL_ 1186 LsdSrvcRqd_B_Rq 1 "On" 0 "Off"; +VAL_ 611 AwdSys_D_Stat 3 "Faulty" 2 "NotUsed" 1 "_4x4_L_H_Active" 0 "_4x4_L_H_Inactive"; +VAL_ 611 AwdStat_D_RqDsply 31 "NotUsed9" 30 "NotUsed8" 29 "NotUsed7" 28 "To_Engage_4x4_Release_Aped" 27 "To_Engage_4x4_Slow_To_3MPH" 26 "Shift_To_Neutral" 25 "Lkr_Mode_Unavail_TMS" 24 " _4x4_Mode_Unavail_TMS" 23 "Out_of_4Low_Crawl" 22 "AWD_PTU_Oil_Changed" 21 "Change_AWD_PTU_Oil" 20 "Neutral_Tow_Disabled" 19 "Neutral_Tow_Enabled" 18 "AWD_OFF" 17 "_4x4_Off_Road_Speed" 16 "_4x4_Extreme_Off_Road_Mode" 15 "_4x4_Exiting_Off_Road" 14 "_4x4_Off_Road_Mode" 10 "_4x4_Locked_Temporarily" 9 "Shift_In_Progress" 13 "Blocked_Shift_Assist" 12 "_4x4_Auto_Restored" 11 "_4x4_Disabled_Temporarily" 7 "Out_of_4Low__Neutral" 6 "Out_of_4Low__Brake" 5 "Out_of_4Low__Speed" 4 "Into_4Low__Clutch" 3 "Into_4Low__Neutral" 2 "Into_4Low__Brake" 1 "Into_4Low__Speed" 0 "Normal__No_Message" 8 "Out_of_4Low__Clutch"; +VAL_ 611 AwdLck_D_Stat 9 "Undefined" 8 "Under_External_Torque_Ctrl" 7 "Torque_Limited_by_Cmd" 6 "Fully_Locked_by_Cmd" 5 "Disabled" 4 "Warning" 3 "Fault" 2 "Inactive" 1 "Completely_Opened_by_Cmd" 0 "OK"; +VAL_ 611 AwdSrvcRqd_B_Rq 1 "On" 0 "Off"; +VAL_ 611 NtrlTowAvail_B_Stat 1 "Available" 0 "NotAvailable"; +VAL_ 611 AwdLck_Tq_Rq 4095 "Fault" 4094 "Unknown"; +VAL_ 611 AwdOffRoadMode_D_Stats 3 "Invalid" 2 "Extreme_Off_Road" 1 "Off_Road" 0 "Normal_Mode"; +VAL_ 611 AwdLoLamp_D_RqDsply 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 611 AwdHiLamp_D_RqDsply 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 611 AwdAutoLamp_D_RqDsply 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 611 Awd2wdLamp_D_RqDsply 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 611 AwdRnge_D_Actl 7 "Unknown" 6 "High_Range_2wd" 5 "High_Range_Auto" 4 "High_Range_Locked" 3 "Neutral" 2 "Low_Range_2wd" 1 "Low_Range_Auto" 0 "Low_Range_Locked"; +VAL_ 1047 TrlrAidSetup_D2_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "SetupAcquisitionSuccess" 4 "TbaTadMonitor" 3 "SetupStartAcquisition" 2 "SetupPrepForAcquisition" 1 "TbaActive" 0 "Null"; +VAL_ 1047 TrlrAidEnbl_D2_Stat 7 "NotUsed_1" 6 "TbaActiveExpertActive" 5 "TbaActiveExpertAvail" 4 "TbaOffTrgActive" 3 "TbaOffTrgSetup" 2 "TbaSetup" 1 "TbaActive" 0 "Inactive"; +VAL_ 1047 TrlrAidMsgTxt_D2_Rq 63 "Message63" 62 "Message62" 61 "Message61" 60 "Message60" 55 "Message55" 50 "Message50" 45 "Message45" 40 "Message40" 35 "Message35" 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1047 EsaOn_B_Stat 1 "On" 0 "Off"; +VAL_ 1047 SelDrvMdeSte_D_Stat 0 "NotAvailable" 1 "Available" 2 "TemporarilyNotAvailable" 3 "Faulty"; +VAL_ 972 LatCtlSte_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Denied" 3 "RampOut" 2 "ContLatControlInProgress" 1 "Available" 0 "Unavailable"; +VAL_ 972 LatCtlLim_D_Stat 3 "LimitWithDriverActive" 2 "LimitReached" 1 "LimitClose" 0 "LimitNotReached"; +VAL_ 972 LatCtlCpblty_D_Stat 3 "Faulty" 2 "ExtendedModeAvailable" 1 "LimitedModeAvailable" 0 "NoModeAvailable"; +VAL_ 972 LsmcBrkDecelEnbl_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "On" 0 "Off"; +VAL_ 972 TjaHandsOnCnfdnc_B_Est 1 "High_Confidence" 0 "Low_Confidence"; +VAL_ 972 LaHandsOff_B_Actl 1 "Hands_Off" 0 "Hands_On"; +VAL_ 972 LaActDeny_B_Actl 1 "LA_Denied" 0 "LA_Not_Denied"; +VAL_ 972 LaActAvail_D_Actl 3 "LKA_LCA_LDW_Avail" 2 "LCA_LKA_Avail_LDW_Suppress" 1 "LCA_LKA_Suppress_LDW_Avail" 0 "LCA_LKA_LDW_Suppress"; +VAL_ 130 TrlrHitchLamp_D_Rqst 1 "On" 0 "Off"; +VAL_ 130 VehVTrlrAid_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 130 DrvSteActv_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 130 DrvSte_Tq_Actl 255 "Invalid" 254 "Unknown"; +VAL_ 130 SteMdule_D_Stat 7 "NotUsed" 6 "EPAS_Failure3" 5 "EPAS_Failure2" 4 "System_Failure" 3 "EPAS_Shutdown" 2 "Normal_Op_Full_Assist" 1 "Normal_Op_Limited_Assist" 0 "EPAS_Initialization"; +VAL_ 130 SteMdule_U_Meas 255 "Invalid"; +VAL_ 130 SteMdule_I_Est 4095 "Invalid"; +VAL_ 130 EPAS_Failure 3 "SERVICE_POWER_STEERING_NOW" 2 "SERVICE_POWER_STEERING" 1 "POWER_STRG_ASSIST_FAULT" 0 "EPAS_OK_NO_MESSAGE"; +VAL_ 130 SteeringColumnTorque 255 "Invalid" 254 "Unknown"; +VAL_ 130 SAPPAngleControlStat6 1 "RequestedAngleNotReached" 0 "RequestedAngleCanBeReached"; +VAL_ 130 SAPPAngleControlStat5 1 "StrgColTorqueExceed_EAROn" 0 "ExternalSigContentOKforEAC"; +VAL_ 130 SAPPAngleControlStat4 1 "SpeedLimitExceededEAROn" 0 "ExternalSigContentOKforEAC"; +VAL_ 130 SAPPAngleControlStat3 1 "EARactiveNoReverseEngage" 0 "ExternalSigContentOKforEAC"; +VAL_ 130 SAPPAngleControlStat2 1 "Rel_ExtSteeringAngleReqx" 0 "NoRel_ExtSteeringAngleReqx"; +VAL_ 130 SAPPAngleControlStat1 3 "Fault" 2 "Active" 1 "Open" 0 "Closed"; +VAL_ 126 StePw_B_Rq 1 "Yes" 0 "No"; +VAL_ 126 StePinRelInit_An_Sns 65535 "Faulty" 65534 "NoDataExists"; +VAL_ 126 StePinCompAnEst_D_Qf 3 "OK" 2 "Degraded" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 133 StePw_B_Rq 1 "Yes" 0 "No"; +VAL_ 133 StePinRelInit_An_Sns 65535 "Faulty" 65534 "NoDataExists"; +VAL_ 133 StePinCompAnEst_D_Qf 3 "OK" 2 "Degraded" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 1200 BrkHold_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "HeldSecondary" 3 "HeldSecure" 2 "Held" 1 "Inactive" 0 "Off"; +VAL_ 1200 HsaTrnAout_Tq_Rq 65535 "Fault" 65534 "Unknown"; +VAL_ 1200 BrkBstrVac_P_Actl 127 "Invalid"; +VAL_ 1200 YawStabilityIndex 511 "Fault" 510 "NoDataExists"; +VAL_ 1200 BrkTot_Tq_RqDrv 8191 "Fault"; +VAL_ 1200 HsaStat_D_Dsply 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "NotAvailable" 3 "SlowReleaseWithChime" 2 "SlowReleaseWithoutChime" 1 "Active" 0 "Inactive"; +VAL_ 1102 SelDrvMdePos12_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos11_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos10_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos09_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos08_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos07_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos06_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos05_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos04_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos03_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos02_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1102 SelDrvMdePos01_D_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1056 AutoEpbMsgTxt_D_Rq 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1056 AutoEpbDsply_D_Stat 1 "Available" 0 "NotAvailable"; +VAL_ 1056 AutoEpbButtnOn_B_Stat 1 "On" 0 "Off"; +VAL_ 1056 SelDrvMdePos12_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos11_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos10_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos09_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos08_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos07_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos06_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos05_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos04_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos03_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos02_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 SelDrvMdePos01_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 1056 ActvDrvMde_D2_Stat 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1056 SelDrvMde_D2_Rq 31 "Faulty" 30 "SelDrvMde31" 29 "SelDrvMde30" 28 "SelDrvMde29" 27 "SelDrvMde28" 26 "SelDrvMde27" 25 "SelDrvMde26" 24 "SelDrvMde25" 23 "SelDrvMde24" 22 "SelDrvMde23" 21 "SelDrvMde22" 20 "SelDrvMde21" 19 "SelDrvMde20" 18 "SelDrvMde19" 17 "SelDrvMde18" 16 "SelDrvMde17" 15 "SelDrvMde16" 14 "SelDrvMde15" 13 "SelDrvMde14" 12 "SelDrvMde13" 11 "SelDrvMde12" 10 "SelDrvMde11" 9 "SelDrvMde10" 8 "SelDrvMde09" 7 "SelDrvMde08" 6 "SelDrvMde07" 5 "SelDrvMde06" 4 "SelDrvMde05" 3 "SelDrvMde04" 2 "SelDrvMde03" 1 "SelDrvMde02" 0 "SelDrvMde01"; +VAL_ 1056 SelDrvMdePt_D_Rq 31 "Faulty" 30 "NotUsed15" 29 "NotUsed14" 28 "NotUsed13" 27 "NotUsed12" 26 "NotUsed11" 25 "NotUsed10" 24 "NotUsed9" 23 "NotUsed8" 22 "NotUsed7" 21 "NotUsed6" 20 "NotUsed5" 19 "NotUsed4" 18 "EvLaterChargerMode" 17 "EvNowMode" 16 "DragMode" 15 "HighSpeedDesertMode_Baja" 14 "SportAdaptiveMode" 13 "NotAvailable_13" 12 "NotAvailable_12" 11 "NotAvailable_11" 10 "NotAvailable_10" 9 "RockCrawlMode" 8 "MudRutsMode" 7 "SandMode" 6 "EconomyMode" 5 "GrassGravelSnow" 4 "NotAvailable_04" 3 "TowHaulMode" 2 "NotAvailable_02" 1 "SportMode" 0 "NormalMode"; +VAL_ 1056 SelDrvMdeMsgTxt_D_Rq 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1056 SelDrvMde_D_Stat 3 "NotUsed" 2 "DriveModeChangeRequest" 1 "DriveModeChangeSelection" 0 "NoDriveModeChangeRequest"; +VAL_ 1056 AwdMde_D_RqBrk 7 "Faulty" 6 "NotUsed2" 5 "NoRequest" 4 "Neutral" 3 "FourByFourLow" 2 "FourByFourHigh" 1 "FourByFourAuto" 0 "FourByTwo"; +VAL_ 1054 AirDamUp_B_RqBrk 1 "Up" 0 "NoRequest"; +VAL_ 1054 RbaBrk_D_Stat 3 "Denied" 2 "Active" 1 "Open" 0 "Closed"; +VAL_ 1054 SelDrvMdeChassis2_D_Rq 31 "Faulty" 30 "NotUsed17" 29 "NotUsed16" 28 "NotUsed15" 27 "NotUsed14" 26 "NotUsed13" 25 "NotUsed12" 24 "NotUsed11" 23 "NotUsed10" 22 "NotUsed9" 21 "NotUsed8" 20 "NotUsed7" 19 "NotUsed6" 18 "NotUsed5" 17 "NotUsed4" 16 "NotUsed3" 15 "NotUsed2" 14 "RoughRoadMode" 13 "TrackMode" 12 "HighSpeedDesertMode" 11 "TowHaulMode" 10 "RockCrawlMode" 9 "SandMode" 8 "MudAndRutsMode" 7 "LowMuMode" 6 "ComfortAdaptiveMode" 5 "ComfortMode" 4 "SportAdaptiveMode" 3 "SportMode" 2 "EconomyMode" 1 "NormalAdaptiveMode" 0 "NormalMode"; +VAL_ 1054 TrailCtl_D_Stat 7 "Faulty" 6 "DescentOnly" 5 "EnabledDeny" 4 "StandbyOverThreshold" 3 "StandbyOverride" 2 "Active" 1 "EnabledDescent" 0 "Off"; +VAL_ 1054 TrailCtlMsgTxt_D_Rq 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1054 BrkBstrVac_D_Stat 3 "NotUsed" 2 "BoosterVacEstimator" 1 "BoosterVacSensor" 0 "NoBoosterVacuumMonitor"; +VAL_ 1054 DrvSlipCtlOffLamp_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 1054 DrvSlipCtlMdeMsg_D_Rq 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1054 AutoHoldMsgTxt_D_Rq 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1054 CtaBrk_D_Stat 3 "Denied" 2 "Active" 1 "Open" 0 "Closed"; +VAL_ 1054 SelDrvMdeAwd_D_Rq 31 "Faulty" 30 "NotUsed_17" 29 "NotUsed_16" 28 "NotUsed_15" 27 "NotUsed_14" 26 "NotUsed_13" 25 "NotUsed_12" 24 "NotUsed_11" 23 "NotUsed_10" 22 "NotUsed_9" 21 "NotUsed_8" 20 "NotUsed_7" 19 "NotUsed_6" 18 "NotUsed_5" 17 "EvLaterChargeMode" 16 "EvNowMode" 15 "TrackMode" 14 "RoughRoadMode" 13 "NotAvailable" 12 "HighSpeedDesertMode_Baja" 11 "SportAdaptiveMode" 10 "RockCrawlMode" 9 "MudRutsMode" 8 "SandMode" 7 "EconomyMode" 6 "GrassGravelSnow" 5 "TowHaulMode" 4 "SportMode" 3 "Normal_4L" 2 "Normal_4A" 1 "Normal_2H" 0 "NormalMode"; +VAL_ 1054 AutoHoldSwMde_B_Ind 1 "On" 0 "Off"; +VAL_ 1054 AutoHoldMde_D_Ind 3 "Indication_3" 2 "Indication_2" 1 "Indication_1" 0 "Off"; +VAL_ 1054 SelDrvMdeChassis_D_Rq 31 "Faulty" 30 "NotUsed17" 29 "NotUsed16" 28 "NotUsed15" 27 "NotUsed14" 26 "NotUsed13" 25 "NotUsed12" 24 "NotUsed11" 23 "NotUsed10" 22 "NotUsed9" 21 "NotUsed8" 20 "NotUsed7" 19 "NotUsed6" 18 "NotUsed5" 17 "NotUsed4" 16 "NotUsed3" 15 "NotUsed2" 14 "NotUsed1" 13 "TrackMode" 12 "HighSpeedDesertMode" 11 "TowHaulMode" 10 "RockCrawlMode" 9 "SandMode" 8 "MudAndRutsMode" 7 "LowMuMode" 6 "ComfortAdaptiveMode" 5 "ComfortMode" 4 "SportAdaptiveMode" 3 "SportMode" 2 "EconomyMode" 1 "NormalAdaptiveMode" 0 "NormalMode"; +VAL_ 1054 ApaBrk_D_Stat 3 "Denied" 2 "Active" 1 "Open" 0 "Closed"; +VAL_ 1046 HsaMde_D_Mem 3 "Undefined" 2 "Manual" 1 "Automatic" 0 "Off"; +VAL_ 1046 BrkBstrVac_B_Rq 1 "Yes" 0 "No"; +VAL_ 1046 HdcMde_D_Actl 7 "Fault" 6 "Temporarily_Unavailable" 5 "NotEnabled_WrongGearSel" 4 "NotEnabled_SpdLimitExceed" 3 "Active_Braking" 2 "Not_Active_Braking" 1 "Off" 0 "Undefined"; +VAL_ 1046 RearDiffLck_Tq2_RqMx 4095 "Faulty"; +VAL_ 1046 TRLR_SWAY_EVNT_IN_PROG 1 "Yes" 0 "No"; +VAL_ 1046 TRLR_SWAY_CONFIG_STAT 1 "On" 0 "Off"; +VAL_ 1046 TCMode 1 "Active" 0 "Inactive"; +VAL_ 1046 DrvSlipCtlLamp_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 1046 Abs_B_Falt 1 "Yes" 0 "No"; +VAL_ 1046 DrvSlipCtlMde_D_Ind 3 "App_Specific_Off_Mode_3" 2 "App_Specific_Off_Mode_2" 1 "App_Specific_Off_Mode_1" 0 "Default_Mode"; +VAL_ 1046 DrvAntiLckLamp_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 1046 StabCtlBrk_B_Avail 1 "Yes" 0 "No"; +VAL_ 1046 DrvHdcWarnInfo_D_Rq 3 "Undefined" 2 "Lamp_On_Continuously" 1 "Lamp_Flashing" 0 "Lamp_Off_Continuously"; +VAL_ 1046 DrvHdcMsg_D_Rq 7 "Undefined" 6 "Speed_too_High" 5 "Temporarily_Unavailable" 4 "System_Fault" 3 "Select_Gear" 2 "Off" 1 "On" 0 "No_Message"; +VAL_ 1046 DrvHdcLampInfo_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 1046 BpedMove_D_Actl 3 "Unknown" 2 "DriverApplyingBrakePedal" 1 "NoAutonomousBrkPdlMovement" 0 "AutonomousBrkPedalMove"; +VAL_ 1046 ChimeBrk_B_Rq 1 "Yes" 0 "No"; +VAL_ 1046 BrkLamp_B_Rq 1 "Yes" 0 "No"; +VAL_ 1046 HILL_DESC_MC 7 "Fault_Detected" 6 "Cooling_Down" 5 "Abort_Apply_Brakes" 4 "Active" 3 "Disabled" 2 "Enabled" 1 "Off_Road" 0 "Normal"; +VAL_ 1046 RearDiffElckrOpen_B_Rq 1 "Yes" 0 "No"; +VAL_ 1045 VehStab_D_Stat 15 "Faulty" 14 "No_Data_Exists" 13 "NotUsed6" 12 "NotUsed5" 11 "NotUsed4" 10 "NotUsed3" 9 "NotUsed2" 8 "NotUsed1" 7 "High_SSRA_no_OS" 6 "Straight" 5 "Post_Oversteer" 4 "Post_Transition" 3 "Countersteer" 2 "Understeer" 1 "Oversteer" 0 "Linear"; +VAL_ 1045 BrkFluidLvl_D_Stat 3 "Invalid" 2 "Unknown" 1 "Low" 0 "OK"; +VAL_ 1045 LsmcBrkDecel_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Denied" 3 "FaultDegraded" 2 "FaultExt" 1 "On" 0 "Off"; +VAL_ 1045 VehYawNonLin_W_Rq 4095 "Fault" 4094 "Unknown"; +VAL_ 1045 VehYawLin_W_Rq 4095 "Fault" 4094 "Unknown"; +VAL_ 1045 VehVActlBrk_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 1044 StePinOffst_An_Est 65535 "Faulty" 65534 "NoDataExists"; +VAL_ 1044 StePinOffst_D_Stat 3 "FineOffset" 2 "CoarseOffset" 1 "StoredOffset" 0 "OffsetNotCalculated"; +VAL_ 1042 VehRol_An_Dsply 127 "Faulty" 126 "NoDataExists"; +VAL_ 1042 VehPtch_An_Dsply 127 "Faulty" 126 "NoDataExists"; +VAL_ 535 WhlRr_W_Meas 32767 "Fault" 32766 "Unknown"; +VAL_ 535 WhlRl_W_Meas 32767 "Fault" 32766 "Unknown"; +VAL_ 535 WhlFr_W_Meas 32767 "Fault" 32766 "Unknown"; +VAL_ 535 WhlFl_W_Meas 32767 "Fault" 32766 "Unknown"; +VAL_ 534 WhlDirRr_D_Actl 3 "Faulty" 2 "NoDataExists" 1 "Backward" 0 "Forward"; +VAL_ 534 WhlDirRl_D_Actl 3 "Faulty" 2 "NoDataExists" 1 "Backward" 0 "Forward"; +VAL_ 534 WhlDirFr_D_Actl 3 "Faulty" 2 "NoDataExists" 1 "Backward" 0 "Forward"; +VAL_ 534 WhlDirFl_D_Actl 3 "Faulty" 2 "NoDataExists" 1 "Backward" 0 "Forward"; +VAL_ 532 RgenTqFalt_B_Actl 1 "Fault" 0 "No_Fault"; +VAL_ 532 RgenBrkDynoMde_B_Actl 1 "TwoWheelDyno" 0 "NormalOperation"; +VAL_ 531 VehStop_D_Stat 3 "Faulty" 2 "NoDataExists" 1 "Yes" 0 "No"; +VAL_ 531 TracCtlPtActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 531 LscmbbMntr_B_Err 1 "DisplayMessage" 0 "NoMessage"; +VAL_ 531 LscmbbBrkDis_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 LscmbbDeny_B_ActlBrk 1 "Yes" 0 "No"; +VAL_ 531 PrkBrkYwLamp_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 531 PrkBrkRedLamp_D_Rq 3 "Fast_Flash" 2 "Slow_Flash" 1 "On" 0 "Off"; +VAL_ 531 LscmbbBrkDecel_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AbsActv_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 StabCtlBrkActv_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 CmbbBrkPrchg_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 CmbbBrkDecel_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 CmbbBaSensInc_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AccBrkWarm_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AccBrkTotTqMn_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AccBrkPrchgActv_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AccBrkDis_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AccBrkDeny_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 AccBrkActv_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 PrplDrgCtlActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 531 LscmbbBaSensInc_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 CmbbBrkDis_B_Actl 1 "Yes" 0 "No"; +VAL_ 531 CmbbDeny_B_ActlBrk 1 "Yes" 0 "No"; +VAL_ 531 CcDis_B_Cmd 1 "Yes" 0 "No"; +VAL_ 531 VehLongOvrGnd_A_Est 1023 "Fault" 1022 "Unknown"; +VAL_ 531 LscmbBrkPrchg_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 531 AccStopActv_B_ActlBrk 1 "Yes" 0 "No"; +VAL_ 531 AccDis_B_ActlEpb 1 "Yes" 0 "No"; +VAL_ 531 PrkBrkMsgTxt_D_Rq 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "No_Message"; +VAL_ 531 PrkBrkStatus 7 "GeneralFault_MaintenceMode" 6 "ECD_by_Brake_ECU_Active" 5 "EPB_Limphome_Active" 4 "Rear_Caliper_Open" 3 "RWU_By_EPB_Active" 2 "Rear_Caliper_Transition" 1 "Rear_Caliper_Closed" 0 "Not_Supported"; +VAL_ 136 SteWhlBrkOffst_An_Rq 32767 "Faulty" 32766 "NoDataExists"; +VAL_ 125 VehRolComp_W_Actl 4094 "NoDataExists" 4095 "Fault"; +VAL_ 125 VehVertComp_A_Actl 1022 "NoDataExists" 1023 "Fault"; +VAL_ 125 BrkTot_Tq_RqArb 8191 "Fault" 8190 "Unknown"; +VAL_ 125 BrkTot_Tq_Actl 8191 "Fault" 8190 "Unknown"; +VAL_ 125 HsaStat_D_Actl 7 "Faulty" 6 "FaultyWithDriverIndication" 5 "SlowRelease" 4 "FastRelease" 3 "ActiveBrakePedalReleased" 2 "ActiveBrakePedalPressed" 1 "FindingGradient" 0 "Inactive"; +VAL_ 119 VehTrvlDir_D_Stat 7 "Faulty" 6 "NoDataExists" 5 "NotUsed2" 4 "NotUsed1" 3 "Reverse" 2 "LikelyReverse" 1 "Forward" 0 "LikelyForward"; +VAL_ 119 VehOverGnd_V_Est 65535 "Invalid" 65534 "Unknown"; +VAL_ 119 VehLongComp_A_Actl 1023 "Fault" 1022 "NoDataExists"; +VAL_ 119 VehLatComp_A_Actl 1023 "Fault" 1022 "NoDataExists"; +VAL_ 119 VehYawComp_W_Actl 4095 "Fault" 4094 "NoDataExists"; +VAL_ 118 BrkCtrFnd_B_Stat 1 "Yes" 0 "No"; +VAL_ 118 DrvSte_D_Stat 15 "NotUsed10" 14 "NotUsed9" 13 "NotUsed8" 12 "NotUsed7" 11 "NotUsed6" 10 "NotUsed5" 9 "NotUsed4" 8 "NotUsed3" 7 "NotUsed2" 6 "NotUsed1" 5 "Request_Active" 4 "Ignition_Off" 3 "DSR_in_Normal_Idle_Mode" 2 "EPAS_Comm_Disturbed" 1 "DSR_Request_Not_Applicable" 0 "DSR_Deactivated"; +VAL_ 118 DrvSte_Tq_Rq 255 "Invalid" 254 "Unknown"; +VAL_ 118 EmgcyBrkLamp_D_Rq 3 "NotUsed" 2 "Active_at_standstill" 1 "Active_at_speed" 0 "Inactive"; +VAL_ 118 StopLamp_B_RqBrk 1 "Active" 0 "Inactive"; +VAL_ 73 immoSubTarget1Cmd_T1 7 "Unused3" 6 "Unused2" 5 "ECHO_TARGET1_IDBLOCK2" 4 "Unused1" 3 "RQST_TARGET1_IDBLOCK2" 2 "RQST_TARGET1_IDBLOCK1" 1 "RESPONSE" 0 "IDLE"; +VAL_ 561 TrnMsgTxt2_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "TransTooHot_LoudChime" 3 "PressBrake_LoudChime" 2 "PressBrake_SoftChime" 1 "PressBrake_NoChime" 0 "NoText_NoChime"; +VAL_ 561 TrnMsgTxt_D_Rq 15 "Message_15" 14 "Message_14" 13 "Message_13" 12 "Message_12" 11 "Message_11" 10 "Message_10" 9 "Message_9" 8 "Message_8" 7 "Message_7" 6 "Message_6" 5 "Message_5" 4 "Message_4" 3 "Message_3" 2 "Message_2" 1 "Message_1" 0 "NoMessage"; +VAL_ 330 TrnAout_W_ActlUnfilt 32767 "Fault" 32766 "Unknown"; +VAL_ 1090 Mtr2State_D_ActlMntr 7 "Faulty" 6 "NoDataExists" 5 "NotUsed_1" 4 "ReadinessState" 3 "DeactivationState" 2 "PowerGeneration" 1 "PowerConsumption" 0 "Null"; +VAL_ 1090 Inv1Ain_I_ActlMntr 32767 "Faulty" 32766 "NoDataExists"; +VAL_ 1090 HybVehMde_D_ActlMntr 7 "Faulty" 6 "NoDataExists" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Fuel" 2 "HybridElectric" 1 "AllElectric" 0 "Null"; +VAL_ 1090 ChrgStat_D_ActlMntr 7 "Faulty" 6 "NoDataExists" 5 "NotUsed" 4 "ChargingCompleted" 3 "NotCharging" 2 "ChargingInDrivingState" 1 "ChargingInParkingState" 0 "Null"; +VAL_ 1090 VehElRnge_L_Dsply 4094 "NoDataExists" 4095 "Fault"; +VAL_ 870 EngMdeMsgTxt_D_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Charge" 3 "GlowingCharge" 2 "Hybrid" 1 "Ev" 0 "NoMessage"; +VAL_ 870 RngPerChrgInst_L_Dsply 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 869 PwrFlowTxt_D_Dsply 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "Disply_Rgen_Chrg_Txt" 10 "Disp_Fast_Charge_Txt" 9 "Disp_Fast_Charge_Cmplt_Txt" 8 "Disp_Charge_Cmplt_Txt" 7 "Disp_Remote_Start_Txt" 6 "Disp_Eng_Drv_Txt" 5 "Disp_Elec_Drv_Txt" 4 "Disp_Idle_with_Chrg_Txt" 3 "Disp_Idle_Txt" 2 "Disp_Charg_HV_Batt_Txt" 1 "Disp_Hyb_Drive_Txt" 0 "No_Text"; +VAL_ 869 EngOnMsg2_D_Dsply 14 "_0xE_to_1F_NotUsed" 12 "Battery_Temperature" 11 "Hill_Decent_Control" 10 "Fuel_Maintenance" 9 "Oil_Maintenance" 8 "Normal_Operation" 7 "Low_Gear" 6 "Batt_Charging" 5 "Engine_Cold" 4 "Neutral_Gear" 3 "Heater_Setting" 2 "High_Speed" 1 "Acceleration" 0 "No_Display" 13 "Drive_Mode_Selection"; +VAL_ 869 EngOnMsg1_D_Dsply 14 "_0xE_to_1F_NotUsed" 12 "Battery_Temperature" 11 "Hill_Decent_Control" 10 "Fuel_Maintenance" 9 "Oil_Maintenance" 8 "Normal_Operation" 7 "Low_Gear" 6 "Batt_Charging" 5 "Engine_Cold" 4 "Neutral_Gear" 3 "Heater_Setting" 2 "High_Speed" 1 "Acceleration" 0 "No_Display" 13 "Drive_Mode_Selection"; +VAL_ 869 FuelMaintMde_D_Dsply 3 "Feature_Not_Present" 2 "In_Fuel_Maint_Mode" 1 "Close_to_Fuel_Maint" 0 "OK"; +VAL_ 869 EngActv_B_Dsply 1 "On" 0 "Off"; +VAL_ 869 EffWhlThresOn_B_Dsply 1 "On" 0 "Off"; +VAL_ 606 ElVehLaterMde_D_Stat 3 "NotUsed" 2 "Available" 1 "NotAvailable" 0 "Null"; +VAL_ 606 ElVehNowMde_D_Stat 3 "NotUsed" 2 "Available" 1 "NotAvailable" 0 "Null"; +VAL_ 374 GearEngag_D_Actl 7 "Undefined" 6 "Fwd_Clutch_Fully_Engaged" 5 "Neutral_Idle" 4 "Disengaged_to_Neutral_Idle" 3 "Disengaged_to_Neutral_Park" 2 "Engagement_in_Progress" 1 "InitializeFwdClutchEngagmt" 0 "Park_Neutral"; +VAL_ 374 TrnRng_D_Rq 15 "Fault" 14 "Unknown_Position" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Range6" 10 "Range5" 9 "Range4" 8 "Range3_M3_L3" 7 "Range2_M2_L2" 6 "Range1_M1_L1" 5 "Low" 4 "Sport_DriveSport_Mposition" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_ 374 TrnPrkSys_D_Actl 15 "Faulty" 14 "NotUsed_5" 13 "NotUsed_4" 12 "NotUsed_3" 11 "NotUsed_2" 10 "NotUsed_1" 9 "FrequencyError" 8 "OutOfRangeHigh" 7 "OutOfRangeLow" 6 "Override" 5 "OutOfPark" 4 "TransitionCloseToOutOfPark" 3 "AtNoSpring" 2 "TransitionCloseToPark" 1 "Park" 0 "NotKnown"; +VAL_ 374 GearLvr_D_ActlDrv 15 "Fault" 14 "Unknown_Position" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Range6" 10 "Range5" 9 "Range4" 8 "Range3_M3_L3" 7 "Range2_M2_L2" 6 "Range1_M1_L1" 5 "Low" 4 "Sport_DriveSport_Mposition" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_ 374 GearPos_D_Trg 15 "Unknown" 14 "Reverse" 13 "Undefined_5" 12 "Undefined_4" 11 "Undefined_3" 10 "Tenth" 9 "Ninth" 8 "Eighth" 7 "Seventh" 6 "Sixth" 5 "Fifth" 4 "Fourth" 3 "Third" 2 "Second" 1 "First" 0 "Neutral"; +VAL_ 374 GearPos_D_Actl 15 "Unknown" 14 "Reverse" 13 "Undefined_5" 12 "Undefined_4" 11 "Undefined_3" 10 "Tenth" 9 "Ninth" 8 "Eighth" 7 "Seventh" 6 "Sixth" 5 "Fifth" 4 "Fourth" 3 "Third" 2 "Second" 1 "First" 0 "Neutral"; +VAL_ 603 WhlDirAvgDrv_D_Actl 3 "Failed" 2 "Unknown" 1 "Backward" 0 "Forward"; +VAL_ 603 PrplTqMnRgen_B_Actl 1 "Yes" 0 "No"; +VAL_ 603 BattTracCnnct_D_Rq 3 "Undefined" 2 "Retain" 1 "Close" 0 "Open"; +VAL_ 602 HtrnWarnLamp_B_Dsply 1 "On" 0 "Off"; +VAL_ 602 HybPwLimOn_B_Stat 1 "Yes" 0 "No"; +VAL_ 602 PwPckTqRdy_B_Dsply 1 "On" 0 "Off"; +VAL_ 1152 BattTracDiagClr_B_Stat 1 "On" 0 "Off"; +VAL_ 1152 EngTeHi_B_Actl 1 "EngineTempHigh" 0 "Normal"; +VAL_ 1152 DcdcOn_B_Rq 1 "On" 0 "Off"; +VAL_ 1152 ULoBattSpprtSustn_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 1152 VehElEff_No_Avg 127 "Faulty" 126 "NoDataExists"; +VAL_ 872 PlgActvArb_B_Dsply 1 "On" 0 "Off"; +VAL_ 872 HybMdeStat_D_Dsply 7 "NotUsed2" 6 "EV_Charge" 5 "EV_Override" 4 "Forced_EV_Mode" 3 "Forced_Charge_Sustain_Mode" 2 "Auto_Charge_Sustain_Mode" 1 "Auto_Charge_Deplete_Mode" 0 "Null_State"; +VAL_ 560 SelDrvMdeSwtch_D_Stat3 3 "Faulty" 2 "SwitchState2" 1 "SwitchState1" 0 "NotPressed"; +VAL_ 560 TrnSrvcRqd_B_Rq 1 "On" 0 "Off"; +VAL_ 560 TrnShifActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 560 GearLvrPos_D_Actl 15 "Fault" 14 "Unknown_Position" 13 "Undefined_Treat_as__Fault" 12 "Undefined_Treat_as_Fault" 11 "sixth" 10 "fifth" 9 "fourth" 8 "third" 7 "second" 6 "first" 5 "Low" 4 "Sport_DriveSport" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_ 560 GboxOil_Te_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 369 SeatWorkSrfc_B_Falt 1 "Active" 0 "Inactive"; +VAL_ 369 TrnIpcDsplyRng2_D_Actl 15 "No_Range_Selected" 14 "Range_14" 13 "Range_13" 12 "Range_12" 11 "Range_11" 10 "Range_10" 9 "Range_9" 8 "Range_8" 7 "Range_7" 6 "Range_6" 5 "Range_5" 4 "Range_4" 3 "Range_3" 2 "Range_2" 1 "Range_1" 0 "NotUsed"; +VAL_ 369 TrnIpcDsplyRng_D_Stat 3 "NotUsed" 2 "Flash" 1 "On" 0 "Blank_No_Display"; +VAL_ 369 TrnIpcDsplyGear_D_Actl 15 "No_Gear_Selected" 14 "_14th_Gear" 13 "_13th_Gear" 12 "_12th_Gear" 11 "_11th_Gear" 10 "_10th_Gear" 9 "_9th_Gear" 8 "_8th_Gear" 7 "_7th_Gear" 6 "_6th_Gear" 5 "_5th_Gear" 4 "_4th_Gear" 3 "_3rd_Gear" 2 "_2nd_Gear" 1 "_1st_Gear" 0 "Neutral"; +VAL_ 369 TrnIpcDsplyMde_D_Stat 3 "Reserved_Blank_No_Display" 2 "Flash" 1 "On" 0 "Blank_No_Display"; +VAL_ 369 TrnIpcDsplyMde_D_Actl 7 "Manual_3" 6 "Manual_2" 5 "Manual_1_Low" 4 "Sport" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_ 369 TrnIpcDsplyGear_D_Stat 3 "Reserved_Blank_No_Display" 2 "Flash" 1 "On" 0 "Blank_No_Display"; +VAL_ 92 TrnLvrV_D_Rq 3 "Full_Speed" 2 "Aggressive" 1 "Normal" 0 "Quiet"; +VAL_ 92 TrnSbwSysHlth_D_Actl 3 "OK" 2 "Degraded" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 92 TrnGearNtmAllow_B_Stat 1 "Yes" 0 "No"; +VAL_ 92 TrnDtpCmd_D_Actl 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "Relatch" 3 "Deploy" 2 "Self_Test" 1 "No_Command" 0 "NotUsed1"; +VAL_ 92 GearSelLck_D_Rq 3 "PreventionBlocker" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_ 92 TrnValidGear_D_Cnfm 3 "Accept" 2 "Reject" 1 "Internal_Request" 0 "No_Command"; +VAL_ 92 TrnNtrlTowCmd_D_Actl 3 "NotUsed" 2 "Neutral_Tow_Entry" 1 "Car_Wash_Mode" 0 "Normal_Mode"; +VAL_ 92 TrnGearCmd_Pc_ActlPt 1023 "Fault"; +VAL_ 92 TrnGear_D_RqPt 7 "Fault" 6 "NotUsed" 5 "Manual" 4 "Drive" 3 "Neutral" 2 "Reverse" 1 "Park" 0 "No_Gear"; +VAL_ 92 TrnCmdState_B_Actl 1 "Yes" 0 "No"; +VAL_ 92 PrkBrkActv_D_RqTrnGear 3 "NotUsed2" 2 "RequestParkBrakeEngage" 1 "NoRequest" 0 "NotUsed1"; +VAL_ 92 TrnGearMsgTxt_D_Rq 15 "Message_15" 14 "Message_14" 13 "Message_13" 12 "Message_12" 11 "Message_11" 10 "Message_10" 9 "Message_9" 8 "Message_8" 7 "Message_7" 6 "Message_6" 5 "Message_5" 4 "Message_4" 3 "Message_3" 2 "Message_2" 1 "Message_1" 0 "NoMessage"; +VAL_ 1087 BattRgenLoChrg_D_RqEng 3 "Disable" 2 "Retain" 1 "Closed" 0 "Open"; +VAL_ 1087 AdasLcObtclAbrt_B_Stat 1 "Yes" 0 "No"; +VAL_ 1087 BattRgenLoDChrg_D_RqEng 3 "Disable" 2 "Retain" 1 "Closed" 0 "Open"; +VAL_ 1087 AirDamPos_D_Stat 3 "Faulty" 2 "NotUsed" 1 "Down" 0 "Up"; +VAL_ 1087 FapLcInhbt_B_Rq 1 "Yes" 0 "No"; +VAL_ 1087 FapLcStopHold_B_Rq 1 "Yes" 0 "No"; +VAL_ 1087 FapLcPrchgBrk_B_Rq 1 "Yes" 0 "No"; +VAL_ 1087 FapLcObstcl_B_Stat 1 "Yes" 0 "No"; +VAL_ 1087 FapLcMaxGrdInhbt_B_Stat 1 "Yes" 0 "No"; +VAL_ 1087 FapLcMaxGrdAbrt_B_Stat 1 "Yes" 0 "No"; +VAL_ 1087 FapLcActv_B_Stat 1 "Yes" 0 "No"; +VAL_ 332 UreaLvlQlty_D_RqDsply 7 "NotUsed_5" 6 "NotUsed_4" 5 "NotUsed_3" 4 "NotUsed_2" 3 "NotUsed_1" 2 "FlashChime" 1 "On" 0 "Off"; +VAL_ 332 UreaLvlTxtWarn_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "System_Error" 10 "Engine_Idled_See_Manual" 9 "Engine_Idled_Upon_Refuel" 8 "Speed_Limited_To_XX_mph" 7 "XXmph_Max_Upon_Restart" 6 "Speed_Limited_To_YY_mph" 5 "YYmph_Max_Upon_Restart" 4 "SpdLimtd_YYmph_In_XXmiles" 3 "ExFlRange_XXMiles_ScndWarn" 2 "Exh_Fluid_Range_XX_Miles" 1 "Exh_Fluid_Under_Half_Full" 0 "Exh_Fluid_Over_Half_Full"; +VAL_ 332 UreaQltySysWarn_D_Rq 7 "Undefined" 6 "ZZ_Overrides" 5 "EngineIdled" 4 "Engine_Idle_Upon_Refuel" 3 "SPEED_LIMITED_to_YY_mph" 2 "YY_MPH_MAX_UPON_Restart" 1 "CONTAMINATED_ExhFluid" 0 "NoQualityProblem"; +VAL_ 332 DieslPrtcWarn_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "OCR_ExhFilterClean_Stopped" 10 "OCR_ExhFilterCleaned" 9 "RgnOff_AtLimit" 8 "RgnOff_OverLoaded" 7 "RgnOff_Loaded" 6 "Exhaust_Filter_Full" 5 "DPF_OverLimit" 4 "DPF_AtLimit" 3 "ExhFilter_Drive_Completed" 2 "Cleaning_Exhaust_Filter" 1 "DPF_OverLoaded" 0 "DPF_Normal_Operation"; +VAL_ 332 UreaQltyFlg_B_RqDsply 1 "True" 0 "False"; +VAL_ 332 UreaQltySys_D_RqDsply 7 "Undefined" 6 "ZZ_Overrides" 5 "EngineIdled" 4 "Engine_Idle_Upon_Refuel" 3 "SPEED_LIMITED_to_YY_mph" 2 "YY_MPH_MAX_UPON_Restart" 1 "CONTAMINATED_ExhFluid" 0 "NoQualityProblem"; +VAL_ 332 UreaLvlTxt_D_RqDsply 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "System_Error" 10 "Engine_Idled_See_Manual" 9 "Engine_Idled_Upon_Refuel" 8 "Speed_Limited_To_XX_mph" 7 "XXmph_Max_Upon_Restart" 6 "Speed_Limited_To_YY_mph" 5 "YYmph_Max_Upon_Restart" 4 "SpdLimtd_YYmph_In_XXmiles" 3 "ExFlRange_XXMiles_ScndWarn" 2 "Exh_Fluid_Range_XX_Miles" 1 "Exh_Fluid_Under_Half_Full" 0 "Exh_Fluid_Over_Half_Full"; +VAL_ 1100 EngExhMdeQuiet_D2_Stat 7 "Faulty" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Track" 3 "Sport" 2 "Normal" 1 "Stealth" 0 "Null"; +VAL_ 1100 HvacCmprLim_D_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "CompressorHeadPressure" 4 "AvailableTorque" 3 "PedalPosition" 2 "RPM" 1 "ECT" 0 "NoLimit"; +VAL_ 1100 WakeAlarm1_B_Typ 1 "CanAndEcuDriveCircuit" 0 "CanOnly"; +VAL_ 1100 Veh_V_DsplyTrailCtlSet 63 "Faulty"; +VAL_ 1100 TrailCtlPt_B_Falt 1 "Fault" 0 "No_Fault"; +VAL_ 1100 AutoTowAllw_D_StatMnu 3 "TowHaulCommandedOn" 2 "AutoTowHaulEnabled" 1 "AutoTowHaulDisabled" 0 "NoSelection"; +VAL_ 1100 AutoTowActv_B_Stat 1 "Yes" 0 "No"; +VAL_ 1100 GrossTrainWeight_M_Est 255 "Faulty" 254 "NoDataExists"; +VAL_ 1098 EdmSailMdeOn_B_Stat 1 "On" 0 "Off"; +VAL_ 1098 EdmMsgTxt_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "OverallGoodScore" 10 "WorkOnCompliance" 9 "GoodCompliance" 8 "WorkOnGearShifting" 7 "GoodGearShifting" 6 "WorkOnEfficientSpeed" 5 "GoodEfficientSpeed" 4 "WorkOnDeceleration" 3 "GoodDeceleration" 2 "WorkOnAcceleration" 1 "GoodAcceleration" 0 "NoMessage"; +VAL_ 1098 EdmLamp_D_Dsply 15 "NotUsed_7" 14 "NotUsed_6" 13 "NotUsed_5" 12 "NotUsed_4" 11 "NotUsed_3" 10 "NotUsed_2" 9 "NotUsed_1" 8 "CoastingEngineBrake" 7 "CoastingShiftToNeutral" 6 "FreewayJunction" 5 "Curve2" 4 "Curve1" 3 "SpeedLimit" 2 "Crossing" 1 "FreewayExit" 0 "NoRecommendation"; +VAL_ 1098 EdmCmplnc_B_Dsply 1 "Yes" 0 "No"; +VAL_ 1086 FuelPumpPwr_B_Rq 1 "On" 0 "Off"; +VAL_ 1086 ElLoadCtl_D_Rq 7 "Unused3" 6 "Unused2" 5 "Unused1" 4 "HoldAllDrvrInvisibleLoads" 3 "StdDriverInvisibleLoadsOn" 2 "AllDriverInvisibleLoadsOn" 1 "All_Possible_Loads_Off" 0 "No_Request"; +VAL_ 1071 CluPdlPosPcMeas_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 1069 SlMde_D_Stat 3 "IsaNotConfigured" 2 "Manual_Mode" 1 "Auto_Mode" 0 "Null"; +VAL_ 1069 SlMde_D_RqDsply 3 "NotUsed" 2 "ManualSpeed_LimiterSymbol" 1 "AutoSpeed_LimiterSymbol" 0 "NoSpeed_LimiterSymbol"; +VAL_ 1069 IsaOffst_D_Stat 15 "Faulty" 14 "Null" 13 "Thirteen" 12 "Twelve" 11 "Eleven" 10 "Ten" 9 "Nine" 8 "Eight" 7 "Seven" 6 "Six" 5 "Five" 4 "Four" 3 "Three" 2 "Two" 1 "One" 0 "Zero"; +VAL_ 1069 GrllShtrPos_D_Cmd 15 "Fully_Open" 14 "Position14" 13 "Position13" 12 "Position12" 11 "Position11" 10 "Position10" 9 "Position9" 8 "Position8" 7 "Position7" 6 "Position6" 5 "Position5" 4 "Position4" 3 "Position3" 2 "Position2" 1 "Position1" 0 "Fully_Closed"; +VAL_ 1069 GrllShtrPos_B_Falt 1 "Fault" 0 "No_Fault"; +VAL_ 1069 ObdWarmUp_B_Complt 1 "Yes" 0 "No"; +VAL_ 1069 EngMsgTxt_D_Rq 3 "Undefined_2" 2 "Undefined_1" 1 "Power_Reduced_to_LowerTemp" 0 "No_Message"; +VAL_ 1069 EngAirIn_Te_Actl 1023 "Fault" 1022 "Unknown"; +VAL_ 1060 RearDiffOilTeWarn_B_Rq 1 "On" 0 "Off"; +VAL_ 1060 RearDiffOil_Te_Actl 511 "Faulty"; +VAL_ 1060 BpedDrvMsgTxt_B_Dsply 1 "On" 0 "Off"; +VAL_ 1060 FuelLvlWarn_D_ActlEng 7 "DteLevel5Lowest" 6 "DteLevel4" 5 "DteLevel3" 4 "DteLevel2NonMyKey" 3 "DteLevel1MyKey" 2 "VeryLow" 1 "Low" 0 "OK"; +VAL_ 1060 SelDrvMdePt_D_Stat 0 "NotAvailable" 1 "Available" 2 "TemporarilyNotAvailable" 3 "Faulty"; +VAL_ 1057 FohEng_D_Rq 3 "AutoEnable_ParkEnable" 2 "AutoDisable_ParkEnable" 1 "AutoEnable_ParkDisable" 0 "Disable_Stop"; +VAL_ 1057 EngIdlShutDwnTxt_D_Rq 3 "NotUsed" 2 "EngineShutdownOnPrevDrive" 1 "FeatureDisabledDueToFault" 0 "NoMessage"; +VAL_ 1057 EngIdlShutDown_D_Stat 3 "Not_used" 2 "Engine_Shutdown" 1 "Initiated_Countdown" 0 "Normal_Operation"; +VAL_ 1057 FUEL_ALCOHOL_PERCNT 255 "Invalid"; +VAL_ 1057 TrnTotTq_Rt_Est 65535 "Fault" 65534 "Unknown"; +VAL_ 1057 TrnTotLss_Tq_Est 255 "Fault" 254 "Unknown"; +VAL_ 1057 ECMMILRequest 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 1057 AirCondFluidHi_P_Actl 255 "Fault" 254 "Unknown"; +VAL_ 1057 OilPressureWarning 1 "Low_Pressure_Lamp_On" 0 "Normal_Pressure_Lamp_Off"; +VAL_ 1057 VehVLimStat_D_Actl 7 "Undefined_3" 6 "Undefined_2" 5 "Undefined_1" 4 "ASL_Fault_Condition" 3 "Active_and_Limiting" 2 "Active_but_Not_Limiting" 1 "Standby" 0 "Off"; +VAL_ 1057 VehVLimActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 1057 CoolantFanStepAct 31 "Unused7" 30 "Unused6" 29 "Unused5" 28 "Unused4" 27 "Unused3" 26 "Unused2" 25 "Unused1" 23 "Step23" 22 "Step22" 21 "Step21" 20 "Step20" 19 "Step19" 18 "Step18" 17 "Step17" 16 "Step16" 15 "Step15" 14 "Step14" 13 "Step13" 12 "Step12" 11 "Step11" 10 "Step10" 9 "Step9" 8 "Step8" 7 "Step7" 6 "Step6" 5 "Step5" 4 "Step4" 3 "Step3" 2 "Step2" 1 "Step1" 24 "Max_Fan_Speed_Req" 0 "Fan_Cmd_Off"; +VAL_ 1055 EcoCochInstNeg_B_Dsply 1 "True" 0 "False"; +VAL_ 562 GearNtrl_D_Stat 3 "Faulty" 2 "NoDataExists" 1 "Yes" 0 "No"; +VAL_ 523 EngAirFiltMsgTxt_D_Rq 7 "NotUsed_2" 6 "NotUsed_1" 5 "EngineAirFilterMonitorFalt" 4 "ResetComplete" 3 "Clogged" 2 "ReplaceNow" 1 "ReplaceSoon" 0 "NoMessage"; +VAL_ 523 WaterInFuel_B_Falt 1 "Fault" 0 "No_Fault"; +VAL_ 523 UreaMnAdd_L2_Actl 255 "Faulty"; +VAL_ 523 UreaMxAdd_L2_Actl 511 "Faulty"; +VAL_ 517 FapLc_B_Err 1 "Yes" 0 "No"; +VAL_ 516 EngAoutNActl_D_QF 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 516 EngAout3_N_Actl 65535 "Invalid"; +VAL_ 516 ApedPos_PcRate_ActlArb 255 "Fault" 254 "Unknown"; +VAL_ 516 ApedPosPcActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 514 StrtrMtrDlyStrt_B_Stat 1 "Yes" 0 "No"; +VAL_ 514 VehVTrlrAid_B_Avail 1 "Yes" 0 "No"; +VAL_ 514 StrtrMtrCtlMsgTxt_D_Rq 7 "Start_In_Gear_Allowed" 6 "Pending_Start_Cancelled" 5 "Start_Pending_Please_Wait" 4 "Cranking_Limit_Exceeded" 3 "Press_Brk_and_Shift_to_P_N" 2 "Press_Clutch_and_Brake" 1 "Press_Clutch_To_Start" 0 "No_Display"; +VAL_ 514 VehVActlEng_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 514 GearRvrse_D_Actl 7 "Fault" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Active_confirmed" 2 "Active_not_confirmed" 1 "Inactive_confirmed" 0 "Inactive_not_confirmed"; +VAL_ 514 StrtrMtrCtlMsgTxt_D2_Rq 3 "NoRequestPcmStartingMsgCtl" 2 "ShiftToNeutralToStart" 1 "ShiftToParkToStart" 0 "NoRequestBcmStartingMsgCtl"; +VAL_ 512 PtDrvMde_D_Stat 15 "Faulty" 14 "NotUsed11" 13 "NotUsed10" 12 "NotUsed9" 11 "NotUsed8" 10 "NotUsed7" 9 "NotUsed6" 8 "NotUsed5" 7 "Drag" 6 "Rock" 5 "Baja" 4 "Sand" 3 "TowHaulGradeAssist" 2 "SnowWet" 1 "Sport" 0 "Normal"; +VAL_ 381 EngOilSrvcMsgTxt_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "ResetComplete" 3 "ResetInProgress" 2 "ChangeOilNow" 1 "ChangeOilSoon" 0 "NoText"; +VAL_ 381 RunDryPrevent_B_Stat 1 "True" 0 "False"; +VAL_ 381 WaterInFuel 1 "On" 0 "Off"; +VAL_ 381 GlowIndication 1 "On" 0 "Off"; +VAL_ 380 EngOilLvlWarn_D_Rq1 7 "Undefined_3" 6 "Undefined_2" 5 "Engine_Oil_Monitor_Fault" 3 "Engine_Oil_High" 2 "Engine_Oil_Critical_Low" 1 "Engine_Oil_Low" 0 "No_Message" 4 "Engine_Oil_Critical_High"; +VAL_ 380 EngExhBrkOnLamp_B_Rq 1 "On" 0 "Off"; +VAL_ 380 EngExhBrkAutoLamp_B_Rq 1 "On" 0 "Off"; +VAL_ 380 EngExhBrkMde_D_Actl 6 "ExhBrkDisable_NoError" 5 "ExhBrkActive_AUTO" 4 "ExhBrkActive_ON" 3 "ExhBrkRequest_AUTO" 2 "ExhBrkRequest_ON" 1 "ExhBrkNoRequest_OFF" 0 "ExhBrkUnavailable_Error"; +VAL_ 377 HvacAirFullOut_B_Rq 1 "Yes" 0 "No"; +VAL_ 377 FuelFillInlet_B_Dsply 1 "Yes" 0 "No"; +VAL_ 377 EngSrvcRqd_B_Rq 1 "Engine_Service_Required" 0 "No_engine_service_required"; +VAL_ 377 OdoCount 255 "Invalid"; +VAL_ 377 FuelFilterLamp_B_Dsply 1 "On" 0 "Off"; +VAL_ 377 AirCondRec_B_Rq 1 "Yes" 0 "No"; +VAL_ 377 AirCondClutch_B_Stats 1 "Yes" 0 "No"; +VAL_ 376 GasPrtc_D_RqDsply 7 "NotUsed_5" 6 "NotUsed_4" 5 "NotUsed_3" 4 "NotUsed_2" 3 "NotUsed_1" 2 "GpfOverLimit" 1 "GpfAtLimit" 0 "NormalOperation"; +VAL_ 376 DynoMde_B_Cmd 1 "Two_Wheel_Dyno" 0 "Normal_Operation"; +VAL_ 376 AslIconDsply_D_Rq 3 "On_Passive_Overridden" 2 "On_Active" 1 "On_Passive" 0 "Off"; +VAL_ 376 AslChime_B_Rq 1 "Yes" 0 "No"; +VAL_ 376 HvacHtrCore2_Te_Actl 1023 "Faulty"; +VAL_ 376 EcssLamp_D_RqDsply 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 376 AirAmbTe_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 376 AirAmb_P_Actl 63 "Fault" 62 "NoDataExists"; +VAL_ 373 DieslPrtc2_D_RqDsply 15 "NotUsed4" 14 "NotUsed3" 13 "NotUsed2" 12 "NotUsed1" 11 "OCR_ExhFilterClean_Stopped" 10 "OCR_ExhFilterCleaned" 9 "RgnOff_AtLimit" 8 "RgnOff_Overloaded" 7 "RgnOff_Loaded" 6 "Exhaust_Filter_Full" 5 "DPF_Overlimit" 4 "DPF_AtLimit" 3 "ExhFilter_Drive_Completed" 2 "Cleaning_Exhaust_Filter" 1 "DPF_Overloaded" 0 "DPF_Normal_Operation"; +VAL_ 373 DieslPrtcRgen_D_Actl 3 "Undefined" 2 "Regen_Level_2" 1 "Regen_Level_1" 0 "No_regen"; +VAL_ 373 EngTeColdPrtct_D_Stats 3 "Engine_Warm_RdcPwr" 2 "OK_to_Drive" 1 "Engine_Warm_PlsWait" 0 "Normal_Operation"; +VAL_ 373 EngExhOvrTe_B_RqDsply 1 "Active" 0 "Inactive"; +VAL_ 359 PrplWhlRgenMn_Tq_Actl 8191 "Faulty"; +VAL_ 359 ElPw_D_StatStrtStop 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "Supported_Level_4" 8 "Supported_Level_3" 7 "Supported_Level_2" 6 "Supported_Level_1" 5 "Limited_Support" 4 "Fault_Limited" 3 "LV_Event_in_Progress" 2 "Not_Supported_Imminent" 1 "Supported_All" 0 "Not_Supported"; +VAL_ 359 PrplWhlTot2_Tq_Actl 65535 "Fault" 65534 "NoDataExists"; +VAL_ 359 PwPckTq_D_Stat 3 "PwPckOn_TqAvailable" 2 "StartInPrgrss_TqNotAvail" 1 "PwPckOn_TqNotAvailable" 0 "PwPckOff_TqNotAvailable"; +VAL_ 359 Eng_D_Stat 3 "NotUsed" 2 "EngAutoStopped" 1 "EngOn" 0 "EngOff"; +VAL_ 359 PlgActvArb_B_Actl 1 "On" 0 "Off"; +VAL_ 359 ElPw_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Fault_Limited" 3 "LV_Event_In_Progress" 2 "Not_Supported_Imminent" 1 "Supported" 0 "Not_Supported"; +VAL_ 359 TrnAinTq_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 358 StopStrtStdby_D_Indic 6 "NotUsed2" 5 "Telltale_Struck_Out" 4 "Telltale_Flashing_Amber" 3 "Telltale_On_Amber" 2 "Telltale_Flashing_Green" 1 "Telltale_On_Green" 0 "Telltale_Off" 7 "NotUsed3"; +VAL_ 358 StopStrtIODTxt_D_Rq 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 358 StopStrtDrvMde_D_Indic 3 "NotUsed" 2 "StartStop_IndirectDeselect" 1 "StopStart_Deselected" 0 "StopStart_Selected"; +VAL_ 358 StopStrtMsgTxt_D_Rq 15 "Message_15" 14 "Message_14" 13 "Message_13" 12 "Message_12" 11 "Message_11" 10 "Message_10" 9 "Message_9" 8 "Message_8" 7 "Message_7" 6 "Message_6" 5 "Message_5" 4 "Message_4" 3 "Message_3" 2 "Message_2" 1 "Message_1" 0 "NoMessage"; +VAL_ 358 OdoTripVerify_L_Actl 16777215 "Fault"; +VAL_ 358 HiElPwInhbt_B_Stat 1 "Inhibit" 0 "No_Inibit"; +VAL_ 358 AutoStopPtDelta_I_Est 255 "Fault"; +VAL_ 357 BPedDrvAppl_D_QF 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 357 CmbbDeny_B_ActlPrpl 1 "Yes" 0 "No"; +VAL_ 357 PrplTqMnSat_B_Actl 1 "Yes" 0 "No"; +VAL_ 357 BpedDrvAppl_D_Actl 3 "_Not_Allowed" 2 "Driver_Braking" 1 "Driver_Not_Braking" 0 "Not_Allowed"; +VAL_ 357 CmbbEngTqMn_B_Actl 1 "Yes" 0 "No"; +VAL_ 357 Veh_V_DsplyCcSet 255 "Fault" 254 "Unknown"; +VAL_ 357 AccEngStat_D_Actl 7 "Undefined_2" 6 "Undefined_1" 5 "ACCSoonCancel_due_Low_Spd" 4 "Shift_Down_Recommendation" 3 "Shift_Up_Recommendation" 2 "ACCNotAllowedToBeActivated" 1 "ACCStandby_due_Auto_Cancel" 0 "Normal_Operation"; +VAL_ 357 CcMde_D_Actl 7 "TapDownWaiting" 6 "TapUpWaiting" 5 "Resuming_Low" 4 "Resuming_High" 3 "Decelerating" 2 "Accelerating" 1 "Keeping_Speed" 0 "Not_Active"; +VAL_ 357 CcStat_D_Actl 7 "Undefined_2" 6 "Undefined_1" 5 "Active" 4 "Active_Que_Assist" 3 "Standby" 2 "Standby_Denied" 1 "Denied" 0 "Off"; +VAL_ 357 CcOvrrdActv_B_Actl 1 "Cruise_Overridden" 0 "Cruise_Req_Not_Overridden"; +VAL_ 357 AccStopMde_D_Rq 3 "Stop_Mode_Active" 2 "EPBApplyOrBrakeReleaseWarn" 1 "Limit_Rolling_Speed" 0 "Stop_Mode_Not_Active"; +VAL_ 355 AutoRgenTxt_B_RqDsply 1 "AutExhFilterCleanOFF" 0 "AutExhFilterCleanON"; +VAL_ 355 AccFllwMdeActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 355 EngPtoMde_D_Actl 7 "Undefined" 6 "Split_Shaft_Stationary" 5 "Not_Used_2" 4 "PTO_Mobile" 3 "Not_Used_1" 2 "PTO_Stationary" 1 "BCP" 0 "Off"; +VAL_ 355 ManRgenTxt_D_RqDsply 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Cleaning_Aborted_Stopped" 3 "Cleaning_Completed" 2 "Cleaning_In_Progress" 1 "Cleaning_Allowed" 0 "Cleaning_Not_Allowed"; +VAL_ 355 ManRgenSoot_Pc_RqDsply 127 "Fault"; +VAL_ 355 DieslMsgTxt_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "ReducedEnginePower" 0 "NoMessage"; +VAL_ 342 EngOvrhtMitgActv_D_Ind 3 "Undefined" 2 "Mode2" 1 "Mode1" 0 "Normal_Mode"; +VAL_ 342 EngClntTe_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 342 EngOil_Te_Actl 255 "Fault" 254 "Unknown"; +VAL_ 71 immoTarget1Status 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "DISABLED_RESET " 2 "ENABLED_NONMOTIVE_START" 1 "ENABLED_MOTIVE_START" 0 "DISABLED"; +VAL_ 71 immoTarget1Cmd 7 "Unused4" 6 "Unused3" 5 "Unused2" 4 "Unused1" 3 "TARGET1_IDBLOCK2" 2 "TARGET1_IDBLOCK1" 1 "CHALLENGE" 0 "IDLE"; +VAL_ 1006 PersIndexIpmb_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 820 AhbStatGfhbFdbk_D_Actl 3 "GfhbHighBeamFullyOn" 2 "GfhbHighBeamPartlyOn" 1 "GfhbHighBeamOff" 0 "GfhbUnavailable"; +VAL_ 820 HeadLghtDrvSide_B_Stat 1 "Left_Hand_Traffic" 0 "Right_Hand_Traffic"; +VAL_ 820 HeadLghtHiOn_B_StatHcm 1 "On" 0 "Off"; +VAL_ 820 Adaptive_Hdlmp_Fault 1 "Yes" 0 "No"; +VAL_ 137 SteWhlOffstRq_D_Stat 3 "Faulty" 2 "NoDataExists" 1 "Allow_External_Angle_Req" 0 "Deny_External_Angle_Req"; +VAL_ 137 SteWhlOffst_An_TotActl 32767 "Faulty" 32766 "NoDataExists"; +VAL_ 137 SteWhlBrkOffst_An_Actl 32767 "Faulty" 32766 "NoDataExists"; +VAL_ 129 SelDrvMdeSwtch_D_Stat4 3 "Faulty" 2 "SwitchState2" 1 "SwitchState1" 0 "NotPressed"; +VAL_ 129 SteWhlSwtchView_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchSet_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchPhon_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchNav_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchMed_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchIod_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchHud_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchBack_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchMenu_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteEffortInc_B_RqDrv 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SelDrvMdeInc_B_RqDrv 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SelDrvMdeDec_B_RqDrv 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SuspDampInc_B_RqDrv 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchUp_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchRght_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchOk_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchLeft_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchDown_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchHome_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 129 SteWhlSwtchInfo_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 935 SodRight_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Invalid" 3 "Disabled" 2 "On" 1 "Trailer_Tow_Off" 0 "Off"; +VAL_ 935 CtaAlrtRight2_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "AlertZone4" 3 "AlertZone3" 2 "AlertZone2" 1 "AlertZone1" 0 "Off"; +VAL_ 935 BttRight_D_Stat 7 "NotUsed" 6 "Disabled" 5 "Off" 4 "OffTemp" 3 "NotConnected" 2 "Pending" 1 "Connected" 0 "NotDetermined"; +VAL_ 935 BttRight_D_RqDrv 3 "NotUsed" 2 "Request" 1 "NoRequest" 0 "Null"; +VAL_ 935 CtaBrkRightMsgTxt_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 935 CtaRightBrkEnbl_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 935 CtaRightBrkDecel_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 935 CtaSnsRight_D_Stat 3 "Invalid" 2 "System_Failure" 1 "Blocked" 0 "Clear"; +VAL_ 935 CtaAlrtRight_D_Stat 1 "On" 0 "Off"; +VAL_ 935 CtaRight_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Invalid" 3 "Disabled" 2 "On" 1 "Trailer_Tow_Off" 0 "Off"; +VAL_ 935 SodSnsRight_D_Stat 3 "Second_Warning_Audio" 2 "System_Failure" 1 "Blocked" 0 "Clear"; +VAL_ 935 SodAlrtRight_D_Stat 3 "Bulb_Proveout" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 935 SodDetctRight_D_Stat 4 "Sensor_Blocked" 3 "Sensor_Fault" 2 "Flash_On" 1 "Alert_On" 0 "AlertOff_FlashOff_SensrClr"; +VAL_ 1108 RCMSerialNoByte8 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte7 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte6 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte5 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte4 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte3 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte2 255 "Invalid" 254 "Unknown"; +VAL_ 1108 RCMSerialNoByte1 255 "Invalid" 254 "Unknown"; +VAL_ 261 ChrgStatDsply_D_Rq 3 "NotUsed_2" 2 "NotUsed_1" 1 "On" 0 "Off"; +VAL_ 261 NextUsageTimeToggle_Rq 0 "Inactive" 2 "Disable" 1 "Enable"; +VAL_ 261 LongTermParking_Rq 0 "Inactive" 1 "On" 2 "Off" 3 "NotUsed"; +VAL_ 261 ModemReset_D_Rq 15 "NotUsed_11" 14 "NotUsed_10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "NotUsed_4" 7 "NotUsed_3" 6 "BrandConnectReset2" 5 "BrandConnectReset1" 4 "CcsReset" 3 "OnlineTrafficReset" 2 "PaakReset" 1 "WifiHotspotReset" 0 "Null"; +VAL_ 261 StopStrtDrvMde_B_RqBtn3 1 "Pressed" 0 "Not_Pressed"; +VAL_ 261 TCU_ESN_D_Rq 3 "NotUsed" 2 "TCU_ESN_Request" 1 "NoRequest" 0 "Inactive"; +VAL_ 261 FactoryReset_Rq 1 "ResetFactoryDefaults" 0 "Inactive"; +VAL_ 1146 TrlrAidSwtch_D_RqDrv 3 "Faulty" 2 "NotUsed" 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1146 TrlrAidCtl_U_RqDrv 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 533 DcacGfciTestBttn_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 533 DcacPwResetButtn_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 533 DcacPwOffButtn_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 533 DcacPwLoButtn_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 533 DcacPwHiButtn_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 533 DcacPwButtn_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 533 TrlrHitch_D_RqMnu 15 "NotUsed_10" 14 "NotUsed_9" 13 "NotUsed_8" 12 "NotUsed_7" 11 "NotUsed_6" 10 "NotUsed_5" 9 "NotUsed_4" 8 "NotUsed_3" 7 "NotUsed_2" 6 "NotUsed_1" 5 "GoToTraileringDomain" 4 "Confirm" 3 "TurnOnTba" 2 "TurnOnAutohitch" 1 "CancelAutohitch" 0 "NoRequest"; +VAL_ 533 AutoEpbZoomView_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 533 AutoEpbButtn_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 533 TrlrAidMde_D_Rq 3 "Mode_3" 2 "Mode_2" 1 "Mode_1" 0 "NoRequest"; +VAL_ 533 TCU_Init_Actvtn_St 3 "NotUsed" 2 "InitialActivateDeny" 1 "InitialActivateAccept" 0 "Invalid"; +VAL_ 533 TCU_Final_Actvtn_St 3 "NotUsed" 2 "FinalActivateDeny" 1 "FinalActivateAccept" 0 "Invalid"; +VAL_ 533 OtaTrg_D_Stat 3 "NotUsed_1" 2 "Accepted" 1 "NotAccepted" 0 "Null"; +VAL_ 533 OnbChrgGoTTouch_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 533 OnbChrgGoTPrcond_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 533 OnbChrgGoTOn_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 533 OnbChrgGoTMnte_D_Rq 15 "NotUsed_4" 14 "NotUsed_3" 13 "NotUsed_2" 12 "NotUsed_1" 11 "Minute_55" 10 "Minute_50" 9 "Minute_45" 8 "Minute_40" 7 "Minute_35" 6 "Minute_30" 5 "Minute_25" 4 "Minute_20" 3 "Minute_15" 2 "Minute_10" 1 "Minute_5" 0 "Minute_0"; +VAL_ 533 OnbChrgGoTHr_T_Rq 31 "Faulty" 30 "NoDataExists"; +VAL_ 533 OnbChrgGoTExtHtr_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 533 OnbChrgGoTDelete_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 533 OnbChrgClearAll_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 533 PaakMyKey_D_Rq 3 "NotUsed" 2 "ConfirmNewPaakMyKey" 1 "RequestNewPaakMyKey" 0 "None"; +VAL_ 533 OnbChrgGoTUpdate_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 1041 ElCmprUHi_D_Stat 3 "Overvoltage" 2 "Undervoltage" 1 "InRange" 0 "Undetermined"; +VAL_ 1041 ElCmprOverTe_D_Stat 3 "OverTempStop" 2 "OverTempWarning" 1 "Normal" 0 "Undefined"; +VAL_ 1041 ElCmpr_N_Actl 255 "Invalid"; +VAL_ 1041 ElCmpr_Pw_Actl 255 "Invalid"; +VAL_ 1041 ElCmpr_D_Stat 7 "Signal_Invalid" 6 "Comp_Off_ActlSpd_Abnormal" 5 "Comp_Off_TrgtSpd_OutRange" 4 "Comp_Shutdown" 3 "Comp_Stopped_Self_Protect" 2 "Comp_Degraded" 1 "Comp_On" 0 "Comp_Off"; +VAL_ 1041 ElCmprPerfErr_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprInnrErr_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprLostComm_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprOverLoad_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprOverTe_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprBattURng_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprBattSysU_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1041 ElCmprSysU_D_Falt 3 "NotUsed" 2 "Pass" 1 "Fail" 0 "Not_Diagnose_Yet"; +VAL_ 1067 BattULoAuxIsol_D_Rq 3 "Undefined" 2 "Retain" 1 "Close" 0 "Open"; +VAL_ 1067 BattULoAux_U_Rq 4095 "Faulty"; +VAL_ 1067 BattULoAux_I_Actl 4095 "Faulty"; +VAL_ 1067 BattULoAux_D_Qlty 3 "OK" 2 "Not_Within_Specifications" 1 "Eval_In_Progress" 0 "Faulty"; +VAL_ 1067 BattULoAux_U_Actl 255 "Faulty"; +VAL_ 1067 BattULoAux_B_Falt 1 "Fault" 0 "No_Fault"; +VAL_ 1112 BattTracChrgSustn_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 1112 BattTracCnnct_D_Cmd 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "WeldCheck" 3 "OkToDischarge" 2 "Closed" 1 "Precharge" 0 "Open"; +VAL_ 1112 BattTracHvilOpen_B_Stat 1 "Open" 0 "Closed"; +VAL_ 1112 BattTracDcdcDis_B_Rq 1 "Yes" 0 "No"; +VAL_ 1112 HtrnClntPump_D_Stat 3 "Faulty" 2 "No_Data_Exists" 1 "On" 0 "Off"; +VAL_ 1112 BattTracClntPmp_D_Stat 3 "Faulty" 2 "No_Data_Exists" 1 "On" 0 "Off"; +VAL_ 139 AfsPw_B_Rq 1 "Yes" 0 "No"; +VAL_ 139 AccButtnGpTogglePress2 1 "Pressed" 0 "Not_Pressed"; +VAL_ 139 TjaButtnOnOffPress2 1 "Pressed" 0 "Not_Pressed"; +VAL_ 139 ActvFrontSteMsgTxt_D_Rq 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 139 ActvFrontSteLck_D_Stat 3 "Test_passed" 2 "Test_failed" 1 "Test_cannot_run" 0 "Test_incomplete"; +VAL_ 139 SelDrvMdeAdptSte_D_Stat 3 "Faulty" 2 "TemporarilyNotAvailable" 1 "Available" 0 "NotAvailable"; +VAL_ 139 AslButtnOnOffPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 AslButtnOnOffCnclPres2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcButtnOnPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcButtnOnOffPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcButtnOnOffCnclPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcButtnOffPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAsllButtnResPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnSetPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnSetIncPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnSetDecPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnResIncPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnResDecPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnOnPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnOnOffCncl2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnOffCnclPres2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnIndxIncPres2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnIndxDecPres2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnDeny_B_Actl2 1 "Yes" 0 "No"; +VAL_ 139 CcAslButtnCnclResPres2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 CcAslButtnCnclPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 AccButtnGapIncPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 139 AccButtnGapDecPress2 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 1121 SelDrvMdeSwtch_D_Stat 3 "Faulty" 2 "SwitchState2" 1 "SwitchState1" 0 "NotPressed"; +VAL_ 1121 SelDrvMdeCnt_D_Stat 4 "FourCounts" 3 "ThreeCounts" 2 "TwoCounts" 1 "OneCount" 0 "ZeroCounts" 7 "SevenOrMoreCounts" 6 "SixCounts" 5 "FiveCounts"; +VAL_ 1120 DrvSlipCtlMde_B_Rq3 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1120 HybMdeSwtch_B_Rq 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1120 TrailCtlSwtch_B_Stat3 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1120 RearDiffLck_D_RqDrv 3 "Faulty" 2 "NoRequest" 1 "On" 0 "Off"; +VAL_ 1120 AwdMde_D_RqDrv 7 "Faulty" 6 "NotUsed2" 5 "NoRequest" 4 "Neutral" 3 "FourByFourLow" 2 "FourByFourHigh" 1 "FourByFourAuto" 0 "FourByTwo"; +VAL_ 1120 HdcSwtchPos_B_Actl 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1050 AutoHoldSwtch_D_Stat 3 "Faulty" 2 "NotUsed" 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1050 LpdbPtc3_B_Rq 1 "On" 0 "Off"; +VAL_ 1050 LpdbPtc2_B_Rq 1 "On" 0 "Off"; +VAL_ 1050 LpdbPtc1_B_Rq 1 "On" 0 "Off"; +VAL_ 1050 LpdbHeatWiprPrk_B_Rq 1 "On" 0 "Off"; +VAL_ 1050 LpdbDfrstRearOn_B_Rq 1 "On" 0 "Off"; +VAL_ 1050 SteWhlHeat_D_Rq 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "Reserved_3" 8 "Reserved_2" 7 "Reserved_1" 6 "Level_3_Heating" 5 "Level_3_Heating_LS" 4 "Level_2_Heating" 3 "Level_2_Heating_LS" 2 "Level_1_Heating" 1 "Level_1_Heating_LS" 0 "Off"; +VAL_ 1050 MirrorHeatOn_B_Rq 1 "True" 0 "False"; +VAL_ 1050 Remote_Start_QuietMode 1 "Quiet" 0 "Not_Quiet"; +VAL_ 1050 Outside_Air_Temp_Stat 255 "Invalid" 254 "Unknown"; +VAL_ 1137 RngPerChrgAvg_L_Dsply 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 1255 BalrRight4Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1255 BalrRight4Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1255 BalrRight4Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1254 BalrRight3Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1254 BalrRight3Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1254 BalrRight3Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1253 BalrRight2Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1253 BalrRight2Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1253 BalrRight2Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1252 BalrRight1Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1252 BalrRight1Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1252 BalrRight1Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1251 BalrLeft4Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1251 BalrLeft4Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1251 BalrLeft4Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1250 BalrLeft3Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1250 BalrLeft3Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1250 BalrLeft3Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1249 BalrLeft2Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1249 BalrLeft2Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1249 BalrLeft2Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1248 BalrLeft1Threat_D_Stat 1 "Yes" 0 "No"; +VAL_ 1248 BalrLeft1Fast_B_Stat 1 "Yes" 0 "No"; +VAL_ 1248 BalrLeft1Dsply_B_Stat 1 "Yes" 0 "No"; +VAL_ 1113 TrlrTrgtAcquire_D_Stat 7 "Faulty" 6 "NotUsed_2" 5 "NotUsed_1" 4 "RVCforTBA_Activated" 3 "Processing" 2 "TargetNotAcquired" 1 "TargetAcquired" 0 "Null"; +VAL_ 1113 TrlrAnOffstDir_D_Calc 3 "NotUSed" 2 "Right" 1 "Left_or_Center" 0 "Null"; +VAL_ 1113 TrlrAnCalib_B_Complt 1 "Yes" 0 "No"; +VAL_ 1113 TrlrRvrse_D_Stat 3 "Faulty" 2 "TrailerReverseGuidanceLite" 1 "On" 0 "Off"; +VAL_ 1113 TrlrAid_D2_Stat 15 "Faulty" 14 "NotUsed_4" 13 "NotUsed_3" 12 "NotUsed_2" 11 "NotUsed_1" 10 "DirtyCamera" 9 "IncorrectLighting" 8 "TrackingLost" 7 "TrackingUnknownConfidence" 6 "TrackingHighConfidence" 5 "TrackingMediumConfidence" 4 "TrackingLowConfidence" 3 "TurnRequested" 2 "DriveStraighRequested" 1 "Initializing" 0 "NotTracking"; +VAL_ 1113 TrlrAid_An3_Actl 2047 "Faulty"; +VAL_ 1113 TrlrAid_AnRate2_Actl 1023 "Faulty"; +VAL_ 1113 HitchToVehAxle_L_Calc 255 "Faulty"; +VAL_ 1105 TrlrAidSwtchLamp_B_Rq 1 "On" 0 "Off"; +VAL_ 1105 TrlrHitchMsgTxt_D_Rq 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage" 63 "Message63" 47 "Message47"; +VAL_ 1105 TrlrHitchIcon_D_Rq 15 "Icon15" 14 "Icon14" 13 "Icon13" 12 "Icon12" 11 "Icon11" 10 "Icon10" 9 "Icon9" 8 "Icon8" 7 "Icon7" 6 "Icon6" 5 "Icon5" 4 "Icon4" 3 "Icon3" 2 "Icon2" 1 "Icon1" 0 "NoIcon"; +VAL_ 1105 TrlrHitchChime_D_Rq 7 "NotUsed_1" 6 "NotUsed_1" 5 "WarningChime" 4 "NonCriticalAlertChime" 3 "StopNowChime" 2 "ManeuveringReadyChime" 1 "TrailerFoundChime" 0 "NoChime"; +VAL_ 1105 TrlrAidEnbl_D_RqAdas 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "Deactivate" 2 "NotAvailable" 1 "ActiveTba" 0 "Inactive"; +VAL_ 1105 TrlrRvrseMsgTxt_D2_Rq 31 "Message31" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 1105 TrlrRvrseEnbl_D2_Stat 7 "NotUsed" 6 "TbaActiveExpertActive" 5 "TbaActiveExpertAvail" 4 "TbaOffTrgActive" 3 "TbaOffTrgSetup" 2 "TbaSetup" 1 "TbaActive" 0 "Inactive"; +VAL_ 1105 RbaMsg_D_Rq 3 "Faulty" 2 "Unavailable" 1 "Off" 0 "Null"; +VAL_ 1105 BrkDecel_B_RqRba 1 "Enable" 0 "Disable"; +VAL_ 1105 BrkEnbl_B_RqRba 1 "Enable" 0 "Disable"; +VAL_ 1105 Rba_D_Stat 3 "NotUsed" 2 "Disabled" 1 "On" 0 "Off"; +VAL_ 1105 RbaAlrt_D_Dsply 3 "Both" 2 "Text" 1 "Graphic" 0 "Off"; +VAL_ 1105 RbaMnu_D_Rq 3 "NotUsed" 2 "Active" 1 "Inactive" 0 "None"; +VAL_ 1105 CamraFrntStat_D_Stat 3 "No_Data_Present" 2 "NotUsed" 1 "On" 0 "Off"; +VAL_ 1105 TrlrHitchLamp_D_Rq2 1 "On" 0 "Off"; +VAL_ 938 SidePrkSnsR2_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 938 SidePrkSnsR1_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 938 SidePrkSnsL2_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 938 ApaMde_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "POA" 3 "PPA" 2 "SAPP" 1 "Off" 0 "Null"; +VAL_ 938 ApaActvSd_D_Actl 3 "Dirver_Side" 2 "Passenger_Side" 1 "No_Side" 0 "Null"; +VAL_ 938 PrkAidSwtch_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 938 ApaMde_D_Avail 15 "NotUsed7" 14 "NotUsed6" 13 "NotUsed5" 12 "NotUsed4" 11 "NotUsed3" 10 "NotUsed2" 9 "NotUsed1" 8 "PPA_POA" 7 "SAPP_POA" 6 "POA" 5 "PPA" 4 "SAPP" 3 "SAPP_PPA_POA" 2 "SAPP_PPA" 1 "None" 0 "Null"; +VAL_ 938 PrkAidSnsFrCrnr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 938 PrkAidSnsFrCntr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 938 PrkAidSnsFlCrnr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 938 PrkAidSnsFlCntr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 938 PrkBrkEl_B_RqFap 1 "Yes" 0 "No"; +VAL_ 938 RpaChime_D_Rq 15 "Zone15_Chime" 14 "Zone14_Chime" 13 "Zone13_Chime" 12 "Zone12_Chime" 11 "Zone11_Chime" 10 "Zone10_Chime" 9 "Zone9_Chime" 8 "Zone8_Chime" 7 "Zone7_Chime" 6 "Zone6_Chime" 5 "Zone5_Chime" 4 "Zone4_Chime" 3 "Zone3_Chime" 2 "Zone2_Chime" 1 "Zone1_Chime" 0 "No_Chime"; +VAL_ 938 FpaChime_D_Rq 15 "Zone15_Chime" 14 "Zone14_Chime" 13 "Zone13_Chime" 12 "Zone12_Chime" 11 "Zone11_Chime" 10 "Zone10_Chime" 9 "Zone9_Chime" 8 "Zone8_Chime" 7 "Zone7_Chime" 6 "Zone6_Chime" 5 "Zone5_Chime" 4 "Zone4_Chime" 3 "Zone3_Chime" 2 "Zone2_Chime" 1 "Zone1_Chime" 0 "No_Chime"; +VAL_ 938 PrkAidMsgTxt_D_Rq 15 "All_Sns_Blk" 14 "R_Sns_ON_F_Sns_Blk" 13 "R_Sns_Blk_F_Sns_ON" 12 "R_Sns_Inactive_Trlr_atch" 11 "Not_Avail_Trlr_attchd" 10 "Fail_Mode_no_Chime" 9 "Fail_Mode_with_Chime" 8 "R_Sns_Trlr_F_Sns_Blk" 7 "NotUsed3" 6 "Park_Sys_Alternate_Mode" 5 "R_Snsrs_On_F_Snsrs_On" 4 "NotUsed2" 3 "Reset_Message_Warn" 2 "R_Snsrs_Off_F_Snsrs_On" 1 "R_Snsrs_On_F_Snsrs_Off" 0 "All_Park_Sensors_Off"; +VAL_ 938 SidePrkSnsL1_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 938 PrkAidAudioMute_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 939 ApaBrk_D_Rq 3 "NotUsed" 2 "LowDecel" 1 "HighDecel" 0 "NoRequest"; +VAL_ 939 SidePrkSnsR4_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 939 SidePrkSnsR3_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 939 SidePrkSnsL4_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 939 SidePrkSnsL3_D_Stat 15 "NotUsed" 14 "NotFullyScannedYet" 13 "NoObjectInSector" 12 "Zone12" 11 "Zone11" 10 "Zone10" 9 "Zone9" 8 "Zone8" 7 "Zone7" 6 "Zone6" 5 "Zone5" 4 "Zone4" 3 "Zone3" 2 "Zone2" 1 "Zone1" 0 "Off"; +VAL_ 939 PrkAidChime_D_Stat 3 "Fault" 2 "No_Data_Exists" 1 "On" 0 "Off"; +VAL_ 939 PrkAidSnsRlCntr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 939 PrkAidSnsRrCrnr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 939 PrkAidSnsRrCntr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 939 PrkAidSnsRlCrnr_D_Stat 15 "Zone_15" 14 "Zone_14" 13 "Zone_13" 12 "Zone_12" 11 "Zone_11" 10 "Zone_10" 9 "Zone_9" 8 "Zone_8" 7 "Zone_7" 6 "Zone_6" 5 "Zone_5" 4 "Zone_4" 3 "Zone_3" 2 "Zone_2" 1 "Zone_1" 0 "Off"; +VAL_ 939 PrkAidRear_D_Stat 3 "Faulted" 2 "Unused" 1 "Enabled" 0 "Disabled"; +VAL_ 939 PrkAidFront_D_Stat 3 "Faulted" 2 "Unused" 1 "Enabled" 0 "Disabled"; +VAL_ 939 PrkAid_D_Falt 7 "NotUsed2" 6 "NotUsed1" 5 "Failure_Front_PSM_Sensors" 4 "No_Data_Exists" 3 "Failure_Rear_Sensors" 2 "Speaker_Fault" 1 "ECU_Fault" 0 "No_Fault"; +VAL_ 939 ApaLongCtrlEnbl_D_Rq 1 "Enable" 0 "Disable"; +VAL_ 939 PrkAidLamp_D_Rq 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 937 TrnRng_D_RqFap 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Backwards" 3 "Forwards" 2 "NoMotion" 1 "Immobilize" 0 "NoRequest"; +VAL_ 937 FapLcDistToObj_L_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 936 ApaButtnPrssd_B_Stat 1 "Pressed" 0 "Not_Pressed"; +VAL_ 936 ApaSys_D_Stat 7 "Faulty" 6 "Finished" 5 "NotAccessible" 4 "ApaCancelled" 3 "Overspeed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 936 ApaSteWhl_D_RqDrv 3 "TakeControl" 2 "RemoveHands" 1 "NoRequest" 0 "Null"; +VAL_ 936 ApaSteScanMde_D_Stat 3 "Steering" 2 "Scanning" 1 "NotScanning" 0 "Null"; +VAL_ 936 ApaSelSapp_D_Stat 3 "NotConfigured" 2 "NotSelectable" 1 "Selectable" 0 "Null"; +VAL_ 936 ApaSelPpa_D_Stat 3 "NotConfigured" 2 "NotSelectable" 1 "Selectable" 0 "Null"; +VAL_ 936 ApaSelPoa_D_Stat 3 "NotConfigured" 2 "NotSelectable" 1 "Selectable" 0 "Null"; +VAL_ 936 ApaScan_D_Stat 3 "ParkSlotReady" 2 "ParkSlotFound" 1 "NoParkSlot" 0 "Null"; +VAL_ 936 ApaLongCtl_D_RqDrv 7 "NotUsed3" 6 "NotUsed2" 5 "ReleaseBrake" 4 "DriveBackward" 3 "DriveForward" 2 "Stop" 1 "NoRequest" 0 "Null"; +VAL_ 936 ApaGearShif_D_RqDrv 7 "NotUSed2" 6 "NotUsed1" 5 "ShiftToP" 4 "ShiftToN" 3 "ShiftToD" 2 "ShiftToR" 1 "NoRequest" 0 "Null"; +VAL_ 936 ApaActvSide2_D_Stat 3 "NoSide" 2 "Right" 1 "Left" 0 "Null"; +VAL_ 936 ApaAcsy_D_RqDrv 7 "CloseDoor" 6 "SelectSideRight" 5 "SelectSideLeft" 4 "CheckForObject" 3 "PressApaButton" 2 "SelectSide" 1 "NoRequest" 0 "Null"; +VAL_ 936 ApaTrgtDist_D_Stat 15 "Step15" 14 "Step14" 13 "Step13" 12 "Step12" 11 "Step11" 10 "Step10" 9 "Step9" 8 "Step8" 7 "Step7" 6 "Step6" 5 "Step5" 4 "Step4" 3 "Step3" 2 "Step2" 1 "Step1" 0 "Off"; +VAL_ 936 ApaChime_D_Rq 7 "NotUsed2" 6 "NotUsed1" 5 "Warning_Chime" 4 "Finish_Chime" 3 "Stop_Now_Chime" 2 "Spot_Ready_Chime" 1 "Spot_Found_Chime" 0 "No_Chime"; +VAL_ 936 EPASExtAngleStatReq 1 "Request" 0 "NoRequest"; +VAL_ 936 ExtSteeringAngleReq2 32767 "Invalid" 32766 "Unknown"; +VAL_ 877 VehElEffAvg_No_Dsply 127 "Faulty" 126 "NoDataExists"; +VAL_ 877 PwFlwFuelDrv_D_Dsply 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "FlwFromFuelToAllWhls" 2 "FlwFromFuelToFrontWhls" 1 "FlwFromFuelToRearWhls" 0 "NoFlow"; +VAL_ 877 PwFlwFuelClimt_B_Dsply 1 "On" 0 "Off"; +VAL_ 877 PwFlwFuelBatt_B_Dsply 1 "On" 0 "Off"; +VAL_ 877 PwFlwBattClimt_B_Dsply 1 "On" 0 "Off"; +VAL_ 877 PwFlwBatt_D_Dsply 15 "NotUsed_8" 14 "NotUsed_7" 13 "NotUsed_6" 12 "NotUsed_5" 11 "NotUsed_4" 10 "NotUsed_3" 9 "NotUsed_2" 8 "NotUsed_1" 7 "FlwFromWallToBatt" 6 "FlwFromAllWhlsToBatt" 5 "FlwFromBattToAllWhls" 4 "FlwFromFrontWhlsToBatt" 3 "FlwFromBattToFrontWhls" 2 "FlwFromRearWhlsToBatt" 1 "FlwFromBattToRearWhls" 0 "NoFlow"; +VAL_ 588 BattTracSoc2_Pc_Actl 16383 "Faulty" 16382 "NoDataExists"; +VAL_ 588 BattTrac_Te_Actl 1023 "Fault" 1022 "Unknown"; +VAL_ 588 BattTracDiagClr_B_Rq 1 "On" 0 "Off"; +VAL_ 587 BattTracWarnLamp_B_Rq 1 "On" 0 "Off"; +VAL_ 587 BattTracSrvcRqd_B_Rq 1 "On" 0 "Off"; +VAL_ 389 HtrnOvrTeLamp_B_Dsply 1 "On" 0 "Off"; +VAL_ 389 HtrnMil_D_Rq 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 389 HtrnAin_UHi_Actl 1023 "Fault" 1022 "Unknown"; +VAL_ 389 HtrnSrvcRqd_B_Dsply 1 "On" 0 "Off"; +VAL_ 389 HtrnHvilOpen_B_Actl 1 "HVIL_is_Open" 0 "Normal_Operation"; +VAL_ 389 PtWakeupDeltaT_T_Rq 2047 "Fault" 2046 "NoDataExists"; +VAL_ 389 PreCondActv_B_Actl 1 "On" 0 "Off"; +VAL_ 389 DrvCondTpRrDefrs_B_Rq 1 "On" 0 "Off"; +VAL_ 389 BattTrac_I_EstVsc 32767 "Fault" 32766 "NoDataExists"; +VAL_ 1009 ChrgCordUnlock_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 1009 AutoHoldSwtch_D_Stat3 3 "Faulty" 2 "NotUsed" 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1009 TrlrTrgtAcquire_D_Rq 7 "NotUsed_2" 6 "NotUsed_1" 5 "ActivateRVCforTBA" 4 "CancelAcquisition" 3 "RetryAcquisition" 2 "AcquisitionSuccessful" 1 "StartAcquisition" 0 "Inactive"; +VAL_ 1009 TrlrAidCancl_B_Rq 1 "Cancel" 0 "Null"; +VAL_ 1009 CenterStackRing_D_Actl 3 "LimitedOn" 2 "On" 1 "Off" 0 "Null"; +VAL_ 1009 ValetMode_D_Stat 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 1009 TrlrAidSetup_D_Stat 7 "Faulty" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "EnterParameters" 2 "EndSetup" 1 "BeginSetup" 0 "Null"; +VAL_ 360 GsmSrvcRqd_B_Rq 1 "Yes" 0 "No"; +VAL_ 360 TrnGearPwmFalt_B_Actl 1 "Yes" 0 "No"; +VAL_ 360 GearButtnStuck_B_Actl 1 "Yes" 0 "No"; +VAL_ 122 VehStrtInhbt_B_RqBatt 1 "Yes" 0 "No"; +VAL_ 122 BattTracOffFst_D_Actl 3 "Unexpected_Contactor_Open" 2 "Restraints_Impact_Event" 1 "Interlock_Open" 0 "Normal"; +VAL_ 122 BattTracOff_B_Actl 1 "Yes" 0 "No"; +VAL_ 122 BattTracMil_D_Rq 3 "Not_Used" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 122 BattTrac_U_Actl 1023 "Fault" 1022 "Unknown"; +VAL_ 122 BattTrac_I_Actl 32767 "Fault" 32766 "Unknown"; +VAL_ 90 TrnGsmNtmState_D_Actl 3 "Faulty" 2 "Neutral_Tow_Mode" 1 "Car_Wash_Mode" 0 "None"; +VAL_ 90 DrQltyDrv_D_StatGsm 7 "Faulty" 6 "NoDataExists" 5 "NotUsed2" 4 "NotUsed1" 3 "ClosedDegraded" 2 "OpenDegraded" 1 "ClosedOkay" 0 "OpenOkay"; +VAL_ 90 TrnBtsiOvrrd_B_Stat 1 "Override" 0 "Null"; +VAL_ 90 GsmGearMsgTxt_D_Rq 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 90 TrnRng_D_RqGsm 15 "Fault" 14 "UnknownPosition" 13 "Undefined_2" 12 "Undefined_1" 11 "_6" 10 "_5" 9 "_4" 8 "_3" 7 "_2" 6 "_1" 5 "Low" 4 "Sport_DriveSport" 3 "Drive" 2 "Neutral" 1 "Reverse" 0 "Park"; +VAL_ 90 PrkBrkActv_D_RqGsmGear 3 "NotUsed" 2 "RequestParkBrakeEngage" 1 "NoRequest" 0 "Null"; +VAL_ 90 TrnValidGearRq_D_Stat 3 "Valid_Request" 2 "Valid_Degraded_Request" 1 "Invalid_Request" 0 "No_Request"; +VAL_ 90 TrnGearButtn_U_Actl 255 "Fault"; +VAL_ 90 TrnGearButtn_B_ActlR2 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlR1 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlR0 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlP2 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlP1 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlP0 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlN2 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlN1 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlN0 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlM2 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlM1 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlM0 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlD2 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlD1 1 "Yes" 0 "No"; +VAL_ 90 TrnGearButtn_B_ActlD0 1 "Yes" 0 "No"; +VAL_ 90 TrnGear_D_RqDrv 31 "Fault" 30 "NotUsed_25" 29 "NotUsed_24" 28 "NotUsed_23" 27 "NotUsed_22" 26 "Return_to_Park" 25 "NotUsed_20" 24 "NotUsed_19" 23 "NotUsed_18" 22 "NotUsed_17" 21 "Return_To_Park" 20 "NotUsed_15" 19 "NotUsed_14" 18 "NotUsed_13" 17 "NotUsed_12" 16 "Manual" 15 "Not_Used11" 14 "Not_Used10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "Drive" 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "Neutral" 3 "NotUsed_1" 2 "Reverse" 1 "Park" 0 "No_Gear"; +VAL_ 90 BrkSwtchPos_B_ActlGsm 1 "Yes" 0 "No"; +VAL_ 1091 ParkLampTrlrOut_B_Stat 1 "Out" 0 "Null"; +VAL_ 1091 TrlrLampCtl_D_Stat 3 "NotUsed" 2 "TrlrLampCnnctDrvFailure" 1 "TrlrLampNotCnnctDrvFailure" 0 "Null"; +VAL_ 1091 TrlrBattChrg_D_Stat 3 "Reverse" 2 "Normal" 1 "Low" 0 "Null"; +VAL_ 1091 StopLampTrlrOut_B_Stat 1 "Out" 0 "Null"; +VAL_ 1091 TurnLampTrlrRr_B_Stat 1 "Out" 0 "Null"; +VAL_ 1091 TurnLampTrlrRl_B_Stat 1 "Out" 0 "Null"; +VAL_ 1091 TrlrLampCnnct_B_Actl 1 "Yes" 0 "No"; +VAL_ 138 SteWhlRelCalib_An_Sns 32767 "Fault" 32766 "NoDataExists"; +VAL_ 131 AccButtnGapDecPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 HeadLghtHiCtrl_D_RqAhb 7 "NotUsed2" 6 "NotUsed1" 5 "Auto_HiBeam" 4 "Auto_LoBeam" 3 "Flash" 2 "Man_HiBeam" 1 "Man_LoBeam" 0 "Null"; +VAL_ 131 AhbStat_B_Dsply 1 "On" 0 "Off"; +VAL_ 131 WiprFrontSwtch_D_Stat 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "PositionNotDetermined" 8 "High" 7 "Low" 6 "Position6" 5 "Position5" 4 "Position4" 3 "Position3" 2 "Position2" 1 "Position1" 0 "Off"; +VAL_ 131 HeadLghtHiOn_B_StatAhb 1 "On" 0 "Off"; +VAL_ 131 HeadLghtHiFlash_D_Actl 3 "NotUsed" 2 "High" 1 "Flash_to_Pass" 0 "Null"; +VAL_ 131 TjaButtnOnOffPress 1 "Pressed" 0 "Not_Pressed"; +VAL_ 131 AccButtnGapTogglePress 1 "Pressed" 0 "Not_Pressed"; +VAL_ 131 HeadLghtHiFlash_D_Stat 3 "NotUsed" 2 "High" 1 "Flash_to_Pass" 0 "Null"; +VAL_ 131 WiprFront_D_Stat 15 "NO_DATA_EXISTS" 14 "STALLED" 13 "RESERVED" 12 "AUTO_ADJUST" 11 "COURTESYWIPE" 10 "AUTO_HIGH" 9 "AUTO_LOW" 8 "WASH" 7 "MIST_FLICK" 6 "MAN_HIGH" 5 "MAN_LOW" 4 "MAN_INT_ON" 3 "MAN_INT_OFF" 2 "OFF_MOVING" 1 "AUTO_OFF" 0 "OFF"; +VAL_ 131 TurnLghtSwtch_D_Stat 3 "Unused_Treat_As_Off" 2 "Right" 1 "Left" 0 "Off"; +VAL_ 131 LghtAmb_D_Sns 7 "No_Data_Exists" 6 "Unused2" 5 "Unused1" 4 "Tunnel_Off" 3 "Tunnel_On" 2 "Twilight" 1 "Light" 0 "Dark"; +VAL_ 131 AccButtnGapIncPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 AslButtnOnOffPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 AslButtnOnOffCnclPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcButtnOnPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcButtnOnOffPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcButtnOnOffCnclPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcButtnOffPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAsllButtnResPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnSetPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnSetIncPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnSetDecPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnResIncPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnResDecPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnOnPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnOnOffCncl 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnOffCnclPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnIndxIncPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnIndxDecPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnDeny_B_Actl 1 "Yes" 0 "No"; +VAL_ 131 CcAslButtnCnclResPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 CcAslButtnCnclPress 1 "Button_Pressed" 0 "Button_Not_Pressed"; +VAL_ 131 LaSwtchPos_D_Stat 3 "Fault" 2 "Unused" 1 "Pressed" 0 "Open"; +VAL_ 787 DrTgateChime2_D_Rq 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Long_Repeated" 3 "Fast" 2 "Short" 1 "Long" 0 "Off"; +VAL_ 787 DrTGate_D_Rq 3 "NotUsed" 2 "Closing" 1 "Opening" 0 "Not_Moving"; +VAL_ 787 PwLftgtIntSw_B_Stat 1 "Pressed" 0 "Null"; +VAL_ 787 Power_Liftgate_Mode_Stt 2 "Unused" 3 "Not_Supported" 1 "Enabled" 0 "Disabled"; +VAL_ 953 BattRgenLoDChrg_D_Rq 3 "DoNotCare" 2 "Retain" 1 "Closed" 0 "Open"; +VAL_ 953 BattRgenLoChrg_D_Rq 3 "DoNotCare" 2 "Retain" 1 "Closed" 0 "Open"; +VAL_ 953 ChrgCordLck_B_Stat 1 "Unlock" 0 "Null"; +VAL_ 953 WakeAlarm3_D_Stat 3 "PublisherReset" 2 "Wake" 1 "AlarmRunning" 0 "AlarmOff"; +VAL_ 953 WakeAlarm2_D_Stat 3 "PublisherReset" 2 "Wake" 1 "AlarmRunning" 0 "AlarmOff"; +VAL_ 953 WakeAlarm1_D_Stat 3 "PublisherReset" 2 "Wake" 1 "AlarmRunning" 0 "AlarmOff"; +VAL_ 953 WakeAlarm0_D_Stat 3 "PublisherReset" 2 "Wake" 1 "AlarmRunning" 0 "AlarmOff"; +VAL_ 1093 TrlBrkInitOut_D_Stat 3 "Heavy" 2 "Medium" 1 "Light" 0 "Null"; +VAL_ 1093 TrlrBrkMde_D_Actl 1 "Electric_Over_Hydraulic" 0 "Electric"; +VAL_ 1093 TrlrBrkDsply_B_Rq 1 "Yes" 0 "No"; +VAL_ 1093 TrlrBrkDcnnt_B_Actl 1 "Yes" 0 "No"; +VAL_ 1093 TrlrBrkActCnnct_B_Actl 1 "Yes" 0 "No"; +VAL_ 1093 StopLamp_B_RqTrlrBrk 1 "Yes" 0 "No"; +VAL_ 1093 TrlrBrkCtl_B_Falt 1 "Yes" 0 "No"; +VAL_ 1093 TrlrBrkActCirct_B_Falt 1 "Yes" 0 "No"; +VAL_ 792 ElTrip_L_Dsply 65535 "Fault" 65534 "No_Data_Exists"; +VAL_ 792 ElLongTerm_L_Dsply 16777215 "Fault" 16777214 "No_Data_Exists"; +VAL_ 968 SlMde_D_Rq 3 "IsaNotConfigured" 2 "Manual_Mode" 1 "Auto_Mode" 0 "Null"; +VAL_ 968 IsaOffst_D_Rq 15 "Faulty" 14 "Null" 13 "Thirteen" 12 "Twelve" 11 "Eleven" 10 "Ten" 9 "Nine" 8 "Eight" 7 "Seven" 6 "Six" 5 "Five" 4 "Four" 3 "Three" 2 "Two" 1 "One" 0 "Zero"; +VAL_ 819 Memory_3_SwPsngr_Stat 1 "Pressed" 0 "Null"; +VAL_ 819 Memory_2_SwPsngr_Stat 1 "Pressed" 0 "Null"; +VAL_ 819 Memory_1_SwPsngr_Stat 1 "Pressed" 0 "Null"; +VAL_ 819 BLISLEDStatPassSide 3 "Fault" 2 "Unused" 1 "On" 0 "Off"; +VAL_ 819 WndwPsngrSide_D_Stat 3 "BothWindow_Operating" 2 "RearWindow_Operating" 1 "FrontWindow_Operating" 0 "NoWindows_Operating"; +VAL_ 819 Pasngr_Lock_Sw_Stat 3 "Invalid" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_ 819 ChildLckFdbckRp_B_Stat 1 "Locked" 0 "Unlock"; +VAL_ 818 BLISLEDStatDriverSide 3 "Fault" 2 "Unused" 1 "On" 0 "Off"; +VAL_ 818 WndwDrvSide_D_Stat 3 "BothWindow_Operating" 2 "RearWindow_Operating" 1 "FrontWindow_Operating" 0 "NoWindows_Operating"; +VAL_ 818 KeyCylSwDrvDr_D_Stat 3 "NotUsed" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_ 818 Driver_Lock_Sw_Stat 3 "Invalid" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_ 818 ChildLckPw_D_Rq 1 "Active" 0 "Null"; +VAL_ 818 ChildLckFdbckRd_B_Stat 1 "Locked" 0 "Unlock"; +VAL_ 818 RvrseMirrorChime_B_Rq 1 "Yes" 0 "No"; +VAL_ 806 SnowPlowMde_B_Enbl 1 "Enable" 0 "Disable"; +VAL_ 806 StopStrtDrvMde_B_RqBtn 1 "Pressed" 0 "Not_Pressed"; +VAL_ 806 ClimtHeat_D_Rq 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "PtcHtrTestMde" 3 "Defrost_Defog" 2 "FastTempPullDownHeatingReq" 1 "OpportunisticHeatingReq" 0 "NoHeatingRequest"; +VAL_ 806 ClimtCool_D_Rq 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "ElACTestMde" 3 "Defrost_Defog" 2 "FastTempPullDownCoolReq" 1 "OpportunisticCoolingReq" 0 "NoCoolingRequest"; +VAL_ 806 HvacEvap_Te_Actl 1023 "Fault"; +VAL_ 806 HvacAirCond_B_Rq 1 "Yes" 0 "No"; +VAL_ 806 ClimtPw_B_Rq 1 "Yes" 0 "No"; +VAL_ 765 Mc_VehTimeFrmtUsrSel_St 2 "24h_mode" 1 "12h_mode" 0 "Invalid"; +VAL_ 765 Running_Board_Cmd 3 "Unused" 2 "Manually_Deployed" 1 "All_Enabled" 0 "All_Disabled"; +VAL_ 765 EngExhMdeQuiet_D2_Rq 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Track" 3 "Sport" 2 "Normal" 1 "Stealth" 0 "Null"; +VAL_ 765 EdmSailMde_B_RqDrv 1 "On" 0 "Off"; +VAL_ 765 DrvInputRequired_B_Rq 1 "Yes" 0 "No"; +VAL_ 765 AwdRnge_D_ActlIpc 7 "Unknown" 6 "High_Range_2wd" 5 "High_Range_Auto" 4 "High_Range_Locked" 3 "Neutral" 2 "Low_Range_2wd" 1 "Low_Range_Auto" 0 "Low_Range_Locked"; +VAL_ 765 BalrSwtch_D_Stat 3 "NotUsed" 2 "Pressed" 1 "NotPressed" 0 "Null"; +VAL_ 765 BalrMde_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Null"; +VAL_ 765 WaitToStartLamp_D_Falt 3 "NotUsed" 2 "Wait_to_start_lamp_failed" 1 "Diagnosis_not_ready" 0 "Wait_to_start_lamp_OK"; +VAL_ 765 EsaOn_B_Rq 1 "On" 0 "Off"; +VAL_ 765 BttOn_B_Rq 1 "On" 0 "Off"; +VAL_ 765 Btt_L_Actl 127 "Faulty" 126 "NoDataExists"; +VAL_ 765 SelDrvMdeTxtReset_B_Rq 1 "Yes" 0 "No"; +VAL_ 765 SelDrvMdeDsply_B_Avail 1 "Available" 0 "NotAvailable"; +VAL_ 765 Mc_VehUntTrpCoUsrSel_St 0 "TripComputer_metric" 1 "TripComputer_imperial"; +VAL_ 765 Mc_VehUnitTempUsrSel_St 0 "Temperature_deg_c" 1 "Temperature_deg_f"; +VAL_ 765 Mc_VehLangUsrSel_St 30 "Slovak" 29 "Arabic" 28 "Cantonese" 27 "Mandarin_Chinese" 26 "Korean" 25 "Japanese_Kanji" 24 "Japanese_Katakana" 23 "Braz_Portuguese" 22 "EU_Portuguese" 21 "Finish" 20 "Norwegian" 19 "Danish" 18 "Swedish" 17 "Hungarian" 16 "Greek" 15 "Czech" 14 "Polish" 13 "Flemish" 12 "Dutch" 11 "Russian" 10 "Turkish" 9 "Mex_Spanish" 8 "EU_Spanish" 7 "Cana_French" 6 "EU_French" 5 "Italian" 4 "German" 3 "NA_English" 2 "UK_English" 1 "Unknown" 0 "Invalid"; +VAL_ 934 CtaAlrtLeft2_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "AlertZone4" 3 "AlertZone3" 2 "AlertZone2" 1 "AlertZone1" 0 "Off"; +VAL_ 934 CtaBrkLeftMsgTxt_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 934 CtaLeftBrkDecel_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 934 CtaLeftBrkEnbl_B_Rq 1 "Enable" 0 "Disable"; +VAL_ 934 BttLeft_D_Stat 7 "NotUsed" 6 "Disabled" 5 "Off" 4 "OffTemp" 3 "NotConnected" 2 "Pending" 1 "Connected" 0 "NotDetermined"; +VAL_ 934 BttLeft_D_RqDrv 3 "NotUsed" 2 "Request" 1 "NoRequest" 0 "Null"; +VAL_ 934 CtaSnsLeft_D_Stat 3 "Invalid" 2 "System_Failure" 1 "Blocked" 0 "Clear"; +VAL_ 934 SodDetctLeft_D_Stat 4 "Sensor_Blocked" 3 "Sensor_Fault" 2 "Flash_On" 1 "Alert_On" 0 "AlertOff_FlashOff_SensrClr"; +VAL_ 934 CtaLeft_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Invalid" 3 "Disabled" 2 "On" 1 "Trailer_Tow_Off" 0 "Off"; +VAL_ 934 CtaAlrtLeft_D_Stat 1 "On" 0 "Off"; +VAL_ 934 SodLeft_D_Stat 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "Invalid" 3 "Disabled" 2 "On" 1 "Trailer_Tow_Off" 0 "Off"; +VAL_ 934 SodSnsLeft_D_Stat 3 "Second_Warning_Audio" 2 "System_Failure" 1 "Blocked" 0 "Clear"; +VAL_ 934 SodAlrtLeft_D_Stat 3 "Bulb_Proveout" 2 "Flash" 1 "On" 0 "Off"; +VAL_ 1072 LscmbbStat_B_Actl 1 "On" 0 "Off"; +VAL_ 1072 HaDsplyCpblty_B_Stat 1 "Available" 0 "NotAvailable"; +VAL_ 1072 AccDeny_B_RqIpc 1 "Yes" 0 "No"; +VAL_ 1072 DrvSlipCtlMde_D_Rq 3 "App_Specific_Off_Mode_3" 2 "App_Specific_Off_Mode_2" 1 "App_Specific_Off_Mode_1" 0 "Default_Mode"; +VAL_ 1072 EngIdlShutDown_B_RqDrv 1 "Inhibit" 0 "No_Inibit"; +VAL_ 1072 HsaMde_D_Rq 3 "Undefined" 2 "Manual" 1 "Automatic" 0 "Off"; +VAL_ 1072 NtrlTowMdeEnbl_B_RqDrv 1 "Yes" 0 "No"; +VAL_ 1072 BulbChkActv_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1072 ParkDetect_Stat 1 "Park" 0 "Not_Park"; +VAL_ 1072 ReducedGuard_D_Rq 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 1072 TrlrBrkMde_D_Rq 1 "ElectricOverHydraulic" 0 "Electric"; +VAL_ 1072 TRLR_SWAY_CONFIG_CMD 1 "On" 0 "Off"; +VAL_ 1072 TRAILER_BRAKE_CONFIG 1 "Yes" 0 "No"; +VAL_ 1072 Power_Liftgate_Mode_Cmd 1 "Enable" 0 "Disable"; +VAL_ 1072 AccEnbl_B_RqDrv 1 "Adaptive_Cruise" 0 "Normal_Cruise"; +VAL_ 1072 OdometerMasterValue 16777215 "Invalid"; +VAL_ 1072 EngOilLife_B_RqReset 1 "Yes" 0 "No"; +VAL_ 1072 ePRNDL_MODE 1 "On" 0 "Off"; +VAL_ 1072 DrvSlipCtlMde_B_Rq2 1 "Pressed" 0 "Not_Pressed"; +VAL_ 1072 MetricActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 1072 KeyTypeChngMykey_D_Rq 3 "Search_PE_BackupSlot" 2 "Clear_All_MyKeys" 1 "Request_New_MyKey" 0 "None"; +VAL_ 1072 ManRgen_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "CustInitManExhFilterClean" 0 "No_Customer_Request"; +VAL_ 909 IgnPsswrdDsply_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 909 ElPwPoint_D_Rq 3 "On" 2 "Off2" 1 "Off1" 0 "Null"; +VAL_ 909 PoliceIdlMde_D_Stat 15 "NotUsed_7" 14 "NotUsed_6" 13 "NotUsed_5" 12 "NotUsed_4" 11 "NotUsed_3" 10 "NotUsed_2" 9 "PepsActive" 8 "Decommissioned" 7 "ActiveFault" 6 "ArmFault" 5 "PrearmedFault" 4 "OffFault" 3 "Active" 2 "Arm" 1 "Prearmed" 0 "Off"; +VAL_ 909 DrLatchMsgTxt_D_Rq 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 909 SecurityMsgTxt_D_Rq 3 "Message3" 2 "Message2" 1 "Message1" 0 "NoMessage"; +VAL_ 909 PrmtrAlrmEvnt_D_Stat 15 "Diag_Tamper" 14 "Trailer" 13 "Shock_Sensor" 12 "Post_Crash" 11 "Panic" 10 "Intrusion" 9 "Inclination" 8 "Ign_Tamper" 7 "LG_Door" 6 "Decklid" 5 "Hood" 4 "PR_Door" 3 "PF_Door" 2 "DR_Door" 1 "DF_Door" 0 "Null"; +VAL_ 909 HeadLghtHiPrmsn_D_Stat 3 "CancelAndSuppress" 2 "Cancel" 1 "Hold" 0 "AllowChange"; +VAL_ 909 SteWhlLckMsgTxt_D_Rq 3 "NotUsed" 2 "Message_2" 1 "Message_1" 0 "No_Message"; +VAL_ 909 immoMsgTxt_D_Rq 15 "Immo_Msg_15" 14 "Immo_Msg_14" 13 "Immo_Msg_13" 12 "Immo_Msg_12" 11 "Immo_Msg_11" 10 "Immo_Msg_10" 9 "Immo_Msg_9" 8 "Immo_Msg_8" 7 "Immo_Msg_7" 6 "Immo_Msg_6" 5 "Immo_Msg_5" 4 "Immo_Msg_4" 3 "Immo_Msg_3" 2 "Immo_Msg_2" 1 "Immo_Msg_1" 0 "Immo_Msg_0_Null"; +VAL_ 909 PrsnlDevcChrgEnbl_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 909 TracKeyMde_D_Stat 3 "NotUsed" 2 "NotActive" 1 "Active" 0 "ModeNotDetermined"; +VAL_ 909 PEBackupSlot_Stats 3 "No_Valid_FOB_In_Slot" 2 "MyKey_FOB_In_Slot" 1 "Standard_FOB_In_Slot" 0 "Null"; +VAL_ 909 KeyMykeyTot_No_Cnt 13 "Thirteen" 12 "Twelve" 11 "Eleven" 10 "Ten" 9 "Nine" 8 "Eight" 7 "Seven" 6 "Six" 5 "Five" 4 "Four" 3 "Three" 2 "Two" 1 "One" 0 "Zero" 15 "Invalid" 14 "Unlimited"; +VAL_ 909 KeyAdmnTot_No_Cnt 13 "Thirteen" 12 "Twelve" 11 "Eleven" 10 "Ten" 9 "Nine" 8 "Eight" 7 "Seven" 6 "Six" 5 "Five" 4 "Four" 3 "Three" 2 "Two" 1 "One" 0 "Zero" 15 "Invalid" 14 "Unlimited"; +VAL_ 963 Illuminated_Entry_Stat 3 "Invalid" 2 "Unknown" 1 "On" 0 "Off"; +VAL_ 963 Dr_Courtesy_Light_Stat 3 "Invalid" 2 "Unknown" 1 "On" 0 "Off"; +VAL_ 963 Courtesy_Delay_Status 3 "Invalid" 2 "Unknown" 1 "On" 0 "Off"; +VAL_ 963 ImpactEvntFdbck_D_Stat 3 "NotUsed" 2 "EventComplete" 1 "EventInProgress" 0 "Normal"; +VAL_ 963 WrlssAcsyChrgInhbt_B_Rq 1 "Yes" 0 "No"; +VAL_ 963 PudLampPsngr_D_Rq 3 "Ramp_Down" 2 "Ramp_Up" 1 "On" 0 "Off"; +VAL_ 963 HeadLampLoOut_B_Stat 1 "Out" 0 "Null"; +VAL_ 963 HeadLghtHiFdbck_D_Stat 3 "NotUsed" 2 "Cancel" 1 "Hold" 0 "Allow_Change"; +VAL_ 963 PudLampDrv_D_Rq 3 "Ramp_Down" 2 "Ramp_Up" 1 "On" 0 "Off"; +VAL_ 963 TrnNotInPrkChime_B_Rq 1 "On" 0 "Off"; +VAL_ 963 PrkLightChime_B_Rq 1 "On" 0 "Off"; +VAL_ 963 KeyInIgnWarn_B_Cmd 1 "On" 0 "Off"; +VAL_ 963 HomeSafeLtChime_B_Rq 1 "On" 0 "Off"; +VAL_ 963 StopLghtOn_B_Stat 1 "On" 0 "Off"; +VAL_ 963 RvrseLghtOn_B_Stat 1 "On" 0 "Off"; +VAL_ 963 PrkLght_D_Stat 3 "Park_Both" 2 "Park_Right" 1 "Park_Left" 0 "Off"; +VAL_ 963 HeadLghtSwtch_D_Stat 3 "Autolamp" 2 "Headlamp" 1 "Parklamp" 0 "Off"; +VAL_ 963 HeadLampLoFrOn_B_Stat 1 "Low" 0 "Not_Low"; +VAL_ 963 HeadLampLoFlOn_B_Stat 1 "Low" 0 "Not_Low"; +VAL_ 963 HeadLampLoActv_B_Stat 1 "On" 0 "Off"; +VAL_ 963 Headlamp_On_Wrning_Cmd 1 "On" 0 "Off"; +VAL_ 963 Park_Brake_Chime_Rqst 1 "On" 0 "Off"; +VAL_ 963 HeadLghtHiOn_B_Stat 1 "On" 0 "Off"; +VAL_ 963 BrkWarnInd_B_Rq 1 "On" 0 "Off"; +VAL_ 963 Brk_Fluid_Lvl_Low 3 "Invalid" 2 "Unknown" 1 "Low" 0 "OK"; +VAL_ 963 ReducedGuard_D_Stat 3 "NotUsed" 2 "Alarm_On" 1 "Alarm_Off_Previously_On" 0 "Alarm_Off"; +VAL_ 963 Perimeter_Alarm_Status 3 "Activated" 2 "Armed" 1 "Prearmed" 0 "Disarmed"; +VAL_ 963 Courtesy_BSave_Stat 3 "Invalid" 2 "Unknown" 1 "No_Effect" 0 "Off"; +VAL_ 963 DrTgateLck_D_Stat 3 "NotUsed" 2 "Unlock" 1 "Lock" 0 "Null"; +VAL_ 963 WndwGlbl_D_Cmd 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "GLEARN" 3 "GCLOSE" 2 "GOPEN" 1 "GSTOP" 0 "Null"; +VAL_ 963 PudLamp_D_Rq 3 "RAMP_DOWN" 2 "RAMP_UP" 1 "ON" 0 "OFF"; +VAL_ 963 DayRnngLampOn_B_Stat 1 "On" 0 "Off"; +VAL_ 963 PerimeterAlarmChimeRq 1 "On" 0 "Off"; +VAL_ 145 VehYawWActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 145 VehRolWActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 145 VehYaw_W_Actl 65535 "Faulty" 65534 "NoDataExists"; +VAL_ 145 VehRol_W_Actl 65535 "Faulty" 65534 "NoDataExists"; +VAL_ 76 FirstRowBuckleMid 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_ 76 SecondRowBucklePsngr 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_ 76 SecondRowBuckleMid 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_ 76 SecondRowBuckleDriver 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_ 76 FirstRowBuckleDriver 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_ 76 RILReq 3 "Not_Used" 2 "Plant_Mode" 1 "On" 0 "Off"; +VAL_ 76 FirstRowBucklePsngr 3 "Unknown" 2 "Unbelted" 1 "Belted" 0 "Faulty"; +VAL_ 76 RstrnImpactEvntStatus 7 "Invalid" 6 "Not_Used_4" 5 "Threshold_2_Exceeded" 4 "Not_Used_3" 3 "Threshold_1_Exceeded" 2 "Not_Used_2" 1 "Not_Used_1" 0 "Normal"; +VAL_ 76 PsngrFrntDetct_D_Actl 3 "Unknown" 2 "Empty" 0 "Faulty" 1 "Occupied"; +VAL_ 76 EDRTriggerEvntSync 1 "Threshold_Exceeded" 0 "Normal"; +VAL_ 76 PassRstrnInd_Req 3 "ABOnNotIllum_OffNotIllum" 2 "AirbagOnNot_Illum_OffIllum" 1 "AirbagOn_Illum_OffNotIllum" 0 "AirbagOn_Illum_Off_Illum"; +VAL_ 65 immoControlCmd_T1 0 "IDLE" 1 "MOTIVE_START_RQST" 2 "NONMOTIVE_START_RQST" 3 "RQST_TARGET1_IDBLOCK1" 4 "RQST_TARGET1_IDBLOCK2" 5 "Unused" 6 "ECHO_TARGET1_IDBLOCK2" 7 "SHUTDOWN"; +VAL_ 1076 HILL_DESC_SW 1 "On" 0 "Off"; +VAL_ 1076 AutoRgen_D_Rq 3 "NotUsed" 2 "AutExhFilterCleanOFF" 1 "AutExhFilterCleanON" 0 "No_Mode_Selected"; +VAL_ 1076 W2S_LAMP_OK 1 "Yes" 0 "No"; +VAL_ 1076 OdoTripRx_B_Actl 1 "Yes" 0 "No"; +VAL_ 1076 DrvSlipCtlMde_B_RqMyKey 1 "On" 0 "Off"; +VAL_ 1076 FuelLvlWarn_D_Actl 3 "NotUsed" 2 "VeryLow" 1 "Low" 0 "OK"; +VAL_ 1076 FuelSecndActv_B_Actl 1 "Yes" 0 "No"; +VAL_ 1076 FUEL_SENSOR_NUM 1 "Dual_Sensors" 0 "Single_Sensor"; +VAL_ 862 AutoStpHvacDelta_I_Est 255 "Fault"; +VAL_ 862 HvacBlwrFront_D_Stat 31 "Not_Used" 20 "Full_On" 19 "95_Percent" 18 "90_Percent" 17 "85_Percent" 16 "80_Percent" 15 "75_Percent" 14 "70_Percent" 13 "65_Percent" 12 "60_Percent" 11 "55_Percent" 10 "50_Percent" 9 "45_Percent" 8 "40_Percent" 7 "35_Percent" 6 "30_Percent" 5 "25_Percent" 4 "20_Percent" 3 "15_Percent" 2 "10_Percent" 1 "5_Percent" 0 "Off"; +VAL_ 862 CabnAmb_Te_Actl 255 "Fault"; +VAL_ 862 ClimtThrmlLoad_No_Actl 255 "Fault"; +VAL_ 931 PtWakeReas_D_Stat 15 "NotUsed_9" 14 "NotUsed_8" 13 "NotUsed_7" 12 "NotUsed_6" 11 "NotUsed_5" 10 "NotUsed_4" 9 "NotUsed_3" 8 "NotUsed_2" 7 "NotUsed_1" 6 "ElapsedTime" 5 "ThirdPartyWakeup" 4 "DoorAjar" 3 "EarlyWake" 2 "NonMotiveStart" 1 "MotiveStart" 0 "Null"; +VAL_ 931 VehOnSrc_D_Stat 15 "NotUsed_11" 14 "NotUsed_10" 13 "NotUsed_9" 12 "NotUsed_8" 11 "NotUsed_7" 10 "NotUsed_6" 9 "NotUsed_5" 8 "NotUsed_4" 7 "NotUsed_3" 6 "NotUsed_2" 5 "NotUsed_1" 4 "OverTheAir" 3 "RemoteParkAssist" 2 "RemoteStart" 1 "Manual" 0 "Off"; +VAL_ 931 EngStrtActv_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 931 EngStrt_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 931 DrvInCtl_B_Stat 1 "Yes" 0 "No"; +VAL_ 931 AdvStrt_D_Stat 15 "NotUsed_15" 14 "NotUsed_14" 13 "NotUsed_13" 12 "NotUsed_12" 11 "NotUsed_11" 10 "NotUsed_10" 9 "NotUsed_9" 8 "NotUsed_8" 7 "NotUsed_7" 6 "NotUsed_6" 5 "NotUsed_5" 4 "NotUsed_4" 3 "NotUsed_3" 2 "NotUsed_2" 1 "NotUsed_1" 0 "NoAction"; +VAL_ 931 CrnkInhbt_B_Stat 1 "Inhibit" 0 "NoInhibit"; +VAL_ 931 IgnPreOffActv_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 578 PtLatchActv_B_RqBcm 1 "On" 0 "Off"; +VAL_ 578 immoSecureIdleMode 3 "NotUsed2" 2 "NotUsed1" 1 "Active" 0 "Inactive"; +VAL_ 578 ReFuelSwtchStat_D_Actl 3 "NotUsed2" 2 "NotUsed1" 1 "On" 0 "Off"; +VAL_ 578 FuelPumpPwr_D_Stat 7 "NotUsed3" 6 "NotUsed2" 5 "NotUsed1" 4 "Power_Off_Default" 3 "Power_Off_Command" 2 "Power_Off_Service" 1 "Power_Off_Impact" 0 "Power_On"; +VAL_ 578 BattULo_U_Actl 255 "Fault"; +VAL_ 578 PrkLckCtl_B_Enbl 1 "Enable" 0 "Disable"; +VAL_ 578 PrkLckCtlMsgTxt_D_Rq 3 "BTSI_DI_3" 2 "BTSI_DI_2" 1 "BTSI_DI_1" 0 "Null_BTSI_DI"; +VAL_ 578 BrkTrnShifLck_B_Stat 1 "Shift" 0 "NoShift"; +VAL_ 578 PrkLckCtlUnlck_D_Stat 3 "Trans_And_Steer_Unlckd" 2 "Steering_Unlckd" 1 "Transmission_Unlckd" 0 "Null"; +VAL_ 578 PrkLckCtlTow_B_Enbl 1 "Enable" 0 "Disable"; +VAL_ 578 DriverCrankingReq 1 "Crank_Request" 0 "No_Crank_Request"; +VAL_ 578 EngOff_T_Actl 65535 "Invalid"; +VAL_ 578 DcacElPw_D_Rq 3 "NotUsed" 2 "AC_HighPower_Requested" 1 "AC_LowPower_Requested" 0 "AC_Power_NotRequested"; +VAL_ 578 BattULo_I_Actl 16383 "Fault"; +VAL_ 947 ValetMode_D_Mem 1 "On" 0 "Off"; +VAL_ 947 DrStatDrvErrCnt_B_Stat 1 "Yes" 0 "No"; +VAL_ 947 TurnLghtRight_D_Rq 3 "Seq" 2 "On" 1 "Off" 0 "Null"; +VAL_ 947 TurnLghtRightOn_B_Stat 1 "On" 0 "Off"; +VAL_ 947 TurnLghtLeftOn_B_Stat 1 "On" 0 "Off"; +VAL_ 947 FogLghtRearOn_B_Stat 1 "On" 0 "Off"; +VAL_ 947 Backlit_LED_Status 15 "Unused3" 14 "Unused2" 13 "Unused1" 12 "Night_12" 11 "Night_11" 10 "Night_10" 9 "Night_9" 8 "Night_8" 7 "Night_7" 6 "Night_6" 5 "Night_5" 4 "Night_4" 3 "Night_3" 2 "Night_2" 1 "Night_1" 0 "Off"; +VAL_ 947 TurnLghtLeft_D_Rq 3 "Seq" 2 "On" 1 "Off" 0 "Null"; +VAL_ 947 FogLghtFrontOn_B_Stat 1 "On" 0 "Off"; +VAL_ 947 IgnKeyType_D_Actl 15 "Invalid" 14 "Unknown" 3 "Key_Not_Prgrm_Read_Failure" 2 "Key_In_Ign_My_Key" 1 "Key_In_Ign_Standard_Key" 0 "Key_Read_In_Progress"; +VAL_ 947 Parklamp_Status 3 "Invalid" 2 "Unknown" 1 "On" 0 "Off"; +VAL_ 947 Litval 255 "Invalid" 254 "Unknown" 5 "Day" 4 "Twilight_4" 3 "Twilight_3" 2 "Twilight_2" 1 "Twilight_1" 0 "Night"; +VAL_ 947 Key_In_Ignition_Stat 1 "In" 0 "Out"; +VAL_ 947 Ignition_Status 0 "Unknown" 1 "Off" 15 "Invalid" 8 "Start" 4 "Run" 2 "Accessory"; +VAL_ 947 Dimming_Lvl 255 "Invalid" 254 "Unknown" 18 "Day_6" 17 "Day_5" 16 "Day_4" 15 "Day_3" 14 "Day_2" 13 "Day_1" 12 "Night_12" 11 "Night_11" 10 "Night_10" 9 "Night_9" 8 "Night_8" 7 "Night_7" 6 "Night_6" 5 "Night_5" 4 "Night_4" 3 "Night_3" 2 "Night_2" 1 "Night_1" 0 "Off"; +VAL_ 947 Day_Night_Status 3 "NotUsed" 2 "Night" 1 "Day" 0 "Null"; +VAL_ 947 Remote_Start_Status 3 "Invalid" 2 "Unknown" 1 "Remote" 0 "Null"; +VAL_ 947 DrStatTgate_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 DrStatRr_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 DrStatRl_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 DrStatPsngr_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 DrStatInnrTgate_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 DrStatHood_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 DrStatDrv_B_Actl 1 "Ajar" 0 "Closed"; +VAL_ 947 PrkBrkActv_B_Actl 1 "Active" 0 "Inactive"; +VAL_ 947 LifeCycMde_D_Actl 3 "Transport" 2 "NotUsed" 1 "Factory" 0 "Normal"; +VAL_ 947 Delay_Accy 1 "On" 0 "Off"; +VAL_ 947 CrashEvnt_D_Stat 3 "Invalid" 2 "Fuel_Cutoff_Event" 1 "Deploy_Event" 0 "No_Event"; +VAL_ 947 FuelPmpInhbt_B_Stat 1 "Inhibit" 0 "No_Inibit"; +VAL_ 947 BodySrvcRqd_B_Rq 1 "Yes" 0 "No"; +VAL_ 1084 BattULoState_D_Qlty 3 "OK" 2 "Not_Within_Specifications" 1 "Eval_In_Progress" 0 "Fault"; +VAL_ 1084 BSFault 1 "Fault" 0 "No_Fault"; +VAL_ 1084 BattULo2_Te_Actl 127 "Fault"; +VAL_ 1068 EngStrtInhbt_B_RqBatt 1 "Start_Inhibit" 0 "Dont_Care"; +VAL_ 1068 BattULoChrg_D_Rq 3 "Low_Battery_Temperature" 2 "Charging_Requested" 1 "Chrg_Requested_HighCurrent" 0 "No_Request"; +VAL_ 1068 PwSysULoFalt_D_Stat 15 "Not_Used_6" 14 "LowBatterySOC" 13 "PSS_Shed2_Contin" 12 "Not_Used_4" 11 "Not_Used_3" 10 "Not_Used_2" 9 "BattMonitoringSensorFault" 8 "LowBattVoltDuringPwSrcOn" 7 "LowBatt2_PowerSaveMode" 6 "LowBatt1_Warning" 5 "Overvoltage" 4 "Fault_NoOutput" 3 "Fault_ReducedOutput" 2 "Fault_Nonspecific" 1 "Cluster_Proveout" 0 "No_Fault"; +VAL_ 1068 Shed_T_Eng_Off_B 1 "Active" 0 "Inactive"; +VAL_ 1068 Shed_Feature_Group_ID 16 "PtcHeater" 14 "HtdMirr" 13 "HvacRearBlwr_Third" 12 "HvacRearBlwr_Second" 11 "HvacRearBlwr_First" 31 "All LSHED1 Features" 10 "Htd_Windscrn" 9 "SpltHtdBcklight_HtdMirr" 8 "HtdBcklight_HtdMirr" 7 "HtdCoolSeat_FrtDriver" 6 "HtdCoolSeat_FrtPass" 5 "HtdCoolSeat_RearPass" 4 "HtdCoolSeat_RearDriver" 3 "SmartTrlrTowBattCharge" 2 "Htd_StrWhl" 1 "Htd_Washer_Fluid" 0 "No_LSHED1_Features" 15 "Engine_Coolant_Fan"; +VAL_ 1068 Shed_Drain_Eng_Off_B 1 "Active" 0 "Inactive"; +VAL_ 1068 Shed_Level_Req 7 "Unused_2" 6 "Loads_On" 5 "SHED_ENG_OFF" 4 "SOON_ENG_OFF" 3 "SHED2_CONTIN" 2 "SHED2_TRANS" 1 "SHED1" 0 "NO_SHED"; +VAL_ 1068 ULoRgenTestMde_B_Rq 1 "Request" 0 "NoRequest"; +VAL_ 1068 ChargeMode 7 "Undefined_2" 6 "Undefined_1" 5 "Battery_Identify" 4 "Battery_Refresh" 3 "SlowRegenAllowNoDischarge" 2 "Fast_Regen_Allowed" 1 "Slow_Regen_Allowed" 0 "Conventional_Charging"; +VAL_ 1068 IdleSpeedIncrease_El 1 "Yes" 0 "No"; +VAL_ 1068 Batt_Lo_SoC_B 1 "Active" 0 "Inactive"; +VAL_ 1068 PeriodicElLoad_B_Stat 1 "Active" 0 "Inactive"; +VAL_ 1068 Batt_Crit_SoC_B 1 "Active" 0 "Inactive"; +VAL_ 146 VehVert2_A_Actl 8191 "Faulty" 8190 "NoDataExists"; +VAL_ 146 VehLong2_A_Actl 8191 "Faulty" 8190 "NoDataExists"; +VAL_ 146 VehLat2_A_Actl 8191 "Faulty" 8190 "NoDataExists"; +VAL_ 146 VehVertAActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 146 VehLongAActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 146 VehLatAActl_D_Qf 3 "OK" 2 "Not_Within_Specifications" 1 "No_Data_Exists" 0 "Faulty"; +VAL_ 997 PersIndexCcm_D_Actl 7 "Unused_3" 6 "Unused_2" 5 "Unused_1" 4 "Vehicle" 3 "PERS_4" 2 "PERS_3" 1 "PERS_2" 0 "PERS_1"; +VAL_ 983 CmbbObjRelLong_V_Actl 1023 "Faulty" 1022 "NoDataExists"; +VAL_ 983 CmbbObjRelLat_V_Actl 511 "Faulty" 510 "NoDataExists"; +VAL_ 983 CmbbObjDistLong_L_Actl 1023 "Faulty" 1022 "NoDataExists"; +VAL_ 983 CmbbObjDistLat_L_Actl 511 "Faulty" 510 "NoDataExists"; +VAL_ 983 CmbbObjConfdnc_D_Stat 3 "High" 2 "Medium" 1 "Low" 0 "NotDetermined"; +VAL_ 983 CmbbObjColl_T_Actl 127 "Faulty" 126 "NoDataExists"; +VAL_ 983 CmbbObjClass_D_Stat 15 "NotUsed_9" 14 "NotUsed_8" 13 "NotUsed_7" 12 "NotUsed_6" 11 "NotUsed_5" 10 "NotUsed_4" 9 "NotUsed_3" 8 "NotUsed_2" 7 "NotUsed_1" 6 "Unclassified_Vehicle" 5 "Bicycle" 4 "Pedestrian" 3 "Truck" 2 "Motorcycle" 1 "Vehicle" 0 "Undetermined"; +VAL_ 983 EsaEnbl_D2_Rq 3 "NotConfigured" 2 "Enabled" 1 "Pending" 0 "Disabled"; +VAL_ 980 AdbBrdr1DistRigh_D_Stat 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_ 980 AdbBrdr1DistLeft_D_Stat 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_ 980 AdbMde1_D_Rq 3 "MarkerLightFlashing" 2 "MarkerLightConstant" 1 "Spot" 0 "None"; +VAL_ 980 AdbIntns1_D_Rq 3 "Maximum" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 980 AdbBrdr1Up_An_Rq 511 "Faulty" 510 "NoDataExists"; +VAL_ 980 AdbBrdr1Right_An_Rq 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 980 AdbBrdr1Low_An_Rq 511 "Faulty" 510 "NoDataExists"; +VAL_ 980 AdbBrdr1Left_An_Rq 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 979 HandsOffCnfm_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 979 LatCtl_D_Rq 7 "NotUsed4" 6 "NotUsed3" 5 "NotUsed2" 4 "NotUsed1" 3 "InterventionRight" 2 "InterventionLeft" 1 "ContinuousPathFollowing" 0 "NoLateralControl"; +VAL_ 979 LatCtlRampType_D_Rq 3 "Immediately" 2 "Fast" 1 "Medium" 0 "Slow"; +VAL_ 979 LatCtlPrecision_D_Rq 3 "NotUsed2" 2 "NotUsed1" 1 "Precise" 0 "Comfortable"; +VAL_ 976 SuspClkSync_No_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 976 SrpSigValid_B_Stat 1 "True" 0 "False"; +VAL_ 976 SrpHghtRight_L_Actl 511 "Faulty" 510 "NoDataExists"; +VAL_ 976 SrpHghtLeft_L_Actl 511 "Faulty" 510 "NoDataExists"; +VAL_ 976 SrpEventRight_D_Stat 3 "Faulty" 2 "Bump" 1 "Pothole" 0 "NoEvent"; +VAL_ 976 SrpEventLeft_D_Stat 3 "Faulty" 2 "Bump" 1 "Pothole" 0 "NoEvent"; +VAL_ 976 SrpDistRight_L_Actl 511 "Faulty" 510 "NoDataExists"; +VAL_ 976 SrpDistLeft_L_Actl 511 "Faulty" 510 "NoDataExists"; +VAL_ 973 TsrVl2PrmntMsgTxt_D_Rq 3 "NotUsed" 2 "ShowPermanentlyWithSupp" 1 "ShowPermanentlyWithoutSupp" 0 "DoNotShowSignPermanent"; +VAL_ 973 TsrVl1PrmntMsgTxt_D_Rq 3 "NotUsed" 2 "ShowPermanentlyWithSupp" 1 "ShowPermanentlyWithoutSupp" 0 "DoNotShowSignPermanent"; +VAL_ 973 TsrVl2RstrcMsgTxt2_D_Rq 7 "NotUsed" 6 "Time" 5 "Trailer" 4 "Snow" 3 "RainWet" 2 "NoRecognizableRestrictn" 1 "NoSpeedLimitRestrictn" 0 "Null"; +VAL_ 973 TsrVl1RstrcMsgTxt2_D_Rq 7 "NotUsed" 6 "Time" 5 "Trailer" 4 "Snow" 3 "RainWet" 2 "NoRecognizableRestrictn" 1 "NoSpeedLimitRestrictn" 0 "Null"; +VAL_ 973 TsrOvtkMsgTxt2_D_Rq 15 "NotUsed5" 14 "NotUsed4" 13 "NotUsed3" 12 "NotUsed2" 11 "NotUsed1" 10 "LimForTrucksCancelled" 9 "LimForTrucksWoQlfdRstrc" 8 "LimForTrucksWithoutRstrc" 7 "LimAllCancelled" 6 "LimAllWithRstrcTime" 5 "LimAllWithRstrcTrailer" 4 "LimAllWithRstrcSnow" 3 "LimAllWithRstrcRain" 2 "LimAllWithoutQlfdRstrc" 1 "LimAllWithoutRestriction" 0 "OvertakingAllowed"; +VAL_ 973 WwaWarn_B_Rq 1 "On" 0 "Off"; +VAL_ 973 TsrVlUnitMsgTxt_D_Rq 3 "NoDataExists" 2 "Mph" 1 "Kph" 0 "Null"; +VAL_ 973 TsrVLim2MsgTxt_D_Rq 255 "NoLimit" 254 "NotUsed2" 253 "NotUsed1" 252 "NotToBeDisplayed" 251 "LimitCancelled" 31 "1F_FA_Message31_250" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "Null"; +VAL_ 973 TsrVLim1MsgTxt_D_Rq 255 "NoLimit" 254 "NotUsed2" 253 "NotUsed1" 252 "NotToBeDisplayed" 251 "LimitCancelled" 31 "1F_FA_Message31_250" 30 "Message30" 29 "Message29" 28 "Message28" 27 "Message27" 26 "Message26" 25 "Message25" 24 "Message24" 23 "Message23" 22 "Message22" 21 "Message21" 20 "Message20" 19 "Message19" 18 "Message18" 17 "Message17" 16 "Message16" 15 "Message15" 14 "Message14" 13 "Message13" 12 "Message12" 11 "Message11" 10 "Message10" 9 "Message9" 8 "Message8" 7 "Message7" 6 "Message6" 5 "Message5" 4 "Message4" 3 "Message3" 2 "Message2" 1 "Message1" 0 "Null"; +VAL_ 973 TsrVl2StatMsgTxt_D_Rq 3 "LimitOutdated" 2 "LimitReiable" 1 "LimitChanged" 0 "Null"; +VAL_ 973 TsrVl2RstrcMsgTxt_D_Rq 3 "NotUsed" 2 "NoRecognizableRestriction" 1 "NoSpeedLimitRestriction" 0 "Null"; +VAL_ 973 TsrVl1StatMsgTxt_D_Rq 3 "LimitOutdated" 2 "LimitReiable" 1 "LimitChanged" 0 "Null"; +VAL_ 973 TsrVl1RstrcMsgTxt_D_Rq 3 "NotUsed" 2 "NoRecognizableRestriction" 1 "NoSpeedLimitRestriction" 0 "Null"; +VAL_ 973 TsrStatMsgTxt_D_Rq 7 "NotUsed" 6 "NoDataExists" 5 "TSR_Error" 4 "Available_NavigationOnly" 3 "Available_CameraOnly" 2 "Available_FusionMode" 1 "TSR_Off" 0 "Null"; +VAL_ 973 TsrOvtkStatMsgTxt_D_Rq 3 "LimitOutdated" 2 "LimitReiable" 1 "LimitChanged" 0 "Null"; +VAL_ 973 TsrOvtkMsgTxt_D_Rq 7 "LimForTrucksCancelled" 6 "LimForTrucksWoQlfdRstrc" 5 "LimForTrucksWithoutRstrc" 4 "LimAllCancelled" 3 "LimAllWithoutQlfdRstrc" 2 "LimAllWithoutRestriction" 1 "OvertakingAllowed" 0 "Null"; +VAL_ 973 TsrOswWarnMsgTxt_D_Rq 3 "NotUsed" 2 "True" 1 "False" 0 "Null"; +VAL_ 973 TsrMsgTxt_D_Rq 15 "NotUsed6" 14 "NotUsed5" 13 "NotUsed4" 12 "NotUsed3" 11 "NotUsed2" 10 "NotUsed1" 9 "RecgnzdSignNotUsblForDsply" 8 "LimitedSystemPerformance" 7 "OffRoad" 6 "RegionNotSupported" 5 "CountryNotSupported" 4 "WrngNavDatIncompDatCarrier" 3 "NoNavDataAvailable" 2 "NoNavAvailableSwitchedOff" 1 "NoInformationAllOK" 0 "Null"; +VAL_ 970 LkaDrvOvrrd_D_Rq 3 "Level_3" 2 "Level_2" 1 "Level_1" 0 "Level_0"; +VAL_ 970 LkaActvStats_D2_Req 7 "NotUsed" 6 "LkaIncrIntervRight" 5 "LkaSupprRight" 4 "LkaStandIntervRight" 3 "LkaSupprLeft" 2 "LkaStandIntervLeft" 1 "LkaIncrIntervLeft" 0 "LkaNoInterv"; +VAL_ 970 LaRefAng_No_Req 4095 "Fault"; +VAL_ 970 LaRampType_B_Req 1 "Quick" 0 "Smooth"; +VAL_ 970 LaCurvature_No_Calc 4095 "Fault"; +VAL_ 970 LdwActvStats_D_Req 7 "LDW_Suppress_Right_Left" 6 "Not_Used2" 5 "LDW_Suppress_Right" 4 "LDW_Warning_Right" 3 "LDW_Suppress_Left" 2 "LDW_Warning_Left" 1 "LDW_DemoVibration" 0 "LDW_Idle"; +VAL_ 970 LdwActvIntns_D_Req 3 "High" 2 "Medium" 1 "Low" 0 "None"; +VAL_ 962 AdbBrdr3DistRigh_D_Stat 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_ 962 AdbBrdr3DistLeft_D_Stat 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_ 962 AdbMde3_D_Rq 3 "MarkerLightFlashing" 2 "MarkerLightConstant" 1 "Spot" 0 "None"; +VAL_ 962 AdbIntns3_D_Rq 3 "Maximum" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 962 AdbBrdr3Up_An_Rq 511 "Faulty" 510 "NoDataExists"; +VAL_ 962 AdbBrdr3Right_An_Rq 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 962 AdbBrdr3Low_An_Rq 511 "Faulty" 510 "NoDataExists"; +VAL_ 962 AdbBrdr3Left_An_Rq 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 961 AdbBrdr2DistRigh_D_Stat 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_ 961 AdbBrdr2DistLeft_D_Stat 15 "DistGreater800m" 14 "Dist700mTo800m" 13 "Dist600mTo700m" 12 "Dist500mTo600m" 11 "Dist400mTo500m" 10 "Dist300mTo400m" 9 "Dist200mTo300m" 8 "Dist175mTo200m" 7 "Dist150mTo175m" 6 "Dist125mTo150m" 5 "Dist100mTo125m" 4 "Dist75mTo100m" 3 "Dist50mTo75m" 2 "Dist25mTo50m" 1 "Dist15mTo25m" 0 "Dist0mTo15m"; +VAL_ 961 AdbMde2_D_Rq 3 "MarkerLightFlashing" 2 "MarkerLightConstant" 1 "Spot" 0 "None"; +VAL_ 961 AdbIntns2_D_Rq 3 "Maximum" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 961 AdbBrdr2Up_An_Rq 511 "Faulty" 510 "NoDataExists"; +VAL_ 961 AdbBrdr2Right_An_Rq 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 961 AdbBrdr2Low_An_Rq 511 "Faulty" 510 "NoDataExists"; +VAL_ 961 AdbBrdr2Left_An_Rq 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 394 AccStopStat_D_Dsply 3 "PressResume" 2 "Stopped" 1 "ResumeReady" 0 "NoDisplay"; +VAL_ 394 AccTrgDist2_D_Dsply 15 "DIST_ACTIVE_13_Farthest" 14 "DIST_ACTIVE_12" 13 "DIST_ACTIVE_11" 12 "DIST_ACTIVE_10" 11 "DIST_ACTIVE_9" 10 "DIST_ACTIVE_8" 9 "DIST_ACTIVE_7" 8 "DIST_ACTIVE_6" 7 "DIST_ACTIVE_5" 6 "DIST_ACTIVE_4" 5 "DIST_ACTIVE_3" 4 "DIST_ACTIVE_2" 3 "DIST_ACTIVE_1_Closest" 2 "DIST_ACTIVE_No_Target" 1 "DIST_STANDBY" 0 "DIST_OFF"; +VAL_ 394 AccStopRes_B_Dsply 1 "Yes" 0 "No"; +VAL_ 394 TjaWarn_D_Rq 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "HardTakeOverLevel2" 2 "HardTakeOverLevel1" 1 "TrafficJamAssistCancel" 0 "NoWarning"; +VAL_ 394 Tja_D_Stat 7 "NotUsed_1" 6 "ActiveWarningRight" 5 "ActiveWarningLeft" 4 "ActiveInterventionRight" 3 "ActiveInterventionLeft" 2 "Active" 1 "Standby" 0 "Off"; +VAL_ 394 TjaMsgTxt_D_Dsply 7 "NotUsed_4" 6 "NotUsed_3" 5 "NotUsed_2" 4 "NotUsed_1" 3 "TurnOnAdaptCruiseControl" 2 "TrafficJamAssistSelected" 1 "TrafficJamAssistUnavailabl" 0 "NoMessage"; +VAL_ 394 IaccLamp_D_Rq 3 "NotUsed_2" 2 "NotUsed_1" 1 "DisplayIaccIcon" 0 "DoNotDisplayIaccIcon"; +VAL_ 394 AccMsgTxt_D2_Rq 15 "NotUsed_1" 14 "NCC_Enabled_Warning" 13 "IACC_TJA_Selected" 12 "ACC_TJA_Selected" 11 "IACC_Selected" 10 "Press_Brake_To_Hold" 9 "Only_Following_In_Low_Spd" 8 "TJA_Unavailable" 7 "Shift_Down" 6 "IACC_Unavailable" 5 "ACC_Selected" 4 "ACC_Overridden" 3 "Brake_Capacity_Warning" 2 "ACC_Cancelled" 1 "ACC_Unavailable" 0 "No_Text"; +VAL_ 394 FcwDeny_B_Dsply 1 "Yes" 0 "No"; +VAL_ 394 FcwMemStat_B_Actl 1 "On" 0 "Off"; +VAL_ 394 AccTGap_B_Dsply 1 "Yes" 0 "No"; +VAL_ 394 CadsAlignIncplt_B_Actl 1 "Yes" 0 "No"; +VAL_ 394 AccFllwMde_B_Dsply 1 "Yes" 0 "No"; +VAL_ 394 CadsRadrBlck_B_Actl 1 "Yes" 0 "No"; +VAL_ 394 CmbbPostEvnt_B_Dsply 1 "Yes" 0 "No"; +VAL_ 394 AccStopMde_B_Dsply 1 "Yes" 0 "No"; +VAL_ 394 FcwMemSens_D_Actl 3 "FCW_Sensitivity_3" 2 "FCW_Sensitivity_2" 1 "FCW_Sensitivity_1" 0 "Not_Used"; +VAL_ 394 FcwMsgTxt_D_Rq 7 "Undefined_3" 6 "Undefined_2" 5 "Low_Visibility" 4 "Unavailable_DueTo_LowSpeed" 3 "Available" 2 "Unavailable" 1 "Off" 0 "No_Text"; +VAL_ 394 AccWarn_D_Dsply 3 "BrakeReleaseWarn_In_StopMd" 2 "Brake_Capacity_Warning" 1 "Cancel_Warning" 0 "No_Warning"; +VAL_ 394 FcwVisblWarn_B_Rq 1 "On" 0 "Off"; +VAL_ 394 FcwAudioWarn_B_Rq 1 "On" 0 "Off"; +VAL_ 394 AccTGap_D_Dsply 7 "Undefined_2" 6 "Undefined_1" 5 "Time_Gap_5" 4 "Time_Gap_4" 3 "Time_Gap_3" 2 "Time_Gap_2" 1 "Time_Gap_1" 0 "Not_Used"; +VAL_ 394 AccMemEnbl_B_RqDrv 1 "Adaptive_Cruise" 0 "Normal_Cruise"; +VAL_ 394 FdaMem_B_Stat 1 "On" 0 "Off"; +VAL_ 391 HudBlk3_B_Rq 1 "Yes" 0 "No"; +VAL_ 391 HudBlk2_B_Rq 1 "Yes" 0 "No"; +VAL_ 391 HudBlk1_B_Rq 1 "Yes" 0 "No"; +VAL_ 391 HudFlashRate_D_Actl 3 "Unused" 2 "Flash_4Hz_50Prct_DutyCycle" 1 "On" 0 "Off"; +VAL_ 391 CmbbBrkPrchg_D_Rq 3 "Undefined" 2 "Level_2_PreCharge_Request" 1 "Level_1_PreCharge_Request" 0 "No_PreCharge_Request"; +VAL_ 391 CmbbBrkDecel_B_Rq 1 "Yes" 0 "No"; +VAL_ 391 CmbbBaSens_D_Rq 3 "Level_3" 2 "Level_2" 1 "Level_1" 0 "Normal"; +VAL_ 390 AccBrkPulse_B_Rq 1 "True" 0 "False"; +VAL_ 390 AccAutoResum_D_Rq 3 "NotUsed" 2 "Active" 1 "Pending" 0 "Off"; +VAL_ 390 AccBrkPrkEl_B_Rq 1 "Yes" 0 "No"; +VAL_ 390 Cmbb_B_Enbl 1 "Yes" 0 "No"; +VAL_ 390 CmbbOvrrd_B_RqDrv 1 "Yes" 0 "No"; +VAL_ 390 CmbbDeny_B_Actl 1 "Yes" 0 "No"; +VAL_ 390 CmbbEngTqMn_B_Rq 1 "Yes" 0 "No"; +VAL_ 390 AccDeny_B_Rq 1 "Yes" 0 "No"; +VAL_ 390 AccResumEnbl_B_Rq 1 "Yes" 0 "No"; +VAL_ 390 AccCancl_B_Rq 1 "Yes" 0 "No"; +VAL_ 390 AccBrkPrchg_B_Rq 1 "Yes" 0 "No"; +VAL_ 390 AccBrkDecel_B_Rq 1 "Active" 0 "Inactive"; +VAL_ 390 AccStopStat_B_Rq 1 "Yes" 0 "No"; +VAL_ 1153 TerrMde_D_RqDrv 7 "Fail_Safe_Default" 6 "Dynamic_Mode" 5 "Rock_Crawl_Mode" 4 "Mud_Ruts_Mode" 3 "Sand_Mode" 2 "Undefined" 1 "Low_Mu_Mode" 0 "Special_Operating_Mode_Off"; +VAL_ 942 PrkAidDrvDir_D_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "BackwardNegative" 4 "ForwardNegative" 3 "BackwardPositive" 2 "ForwardPositive" 1 "NoMotion" 0 "DirectionNotKnown"; +VAL_ 942 PrkAidAcsyRear_D_Stat 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 942 PrkAidAcsyFront_D_Stat 3 "NotUsed" 2 "On" 1 "Off" 0 "Null"; +VAL_ 930 BalrWndwRight_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 930 BalrSnsRight_D_Falt 3 "Invalid" 2 "SystemFailure" 1 "Blocked" 0 "Clear"; +VAL_ 930 WndwPsngrRear_D_RqBalrr 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 930 WndwPsngr_D_RqBalrr 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 930 WndwDrvRear_D_RqBalrr 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 930 WndwDrv_D_RqBalrr 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 930 BalrRight_D_Stat 3 "Inhibited" 2 "Disabled" 1 "On" 0 "Off"; +VAL_ 930 BalrMdeSelRight_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 930 BalrMdeRight_D_Stat 3 "NotUsed" 2 "High" 1 "Medium" 0 "Low"; +VAL_ 930 BalrLckRight_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 930 BalrChimeRight_D_Rq 3 "NotUsed" 2 "Soft" 1 "Normal" 0 "Off"; +VAL_ 930 CamraRearOn_B_RqBalrr 1 "Active" 0 "Inactive"; +VAL_ 930 DrLckActv_B_RqBalrr 1 "Active" 0 "Null"; +VAL_ 929 BalrChimeLeft_D_Rq 3 "NotUsed" 2 "Soft" 1 "Normal" 0 "Off"; +VAL_ 929 BalrLeft_D_Stat 3 "Inhibited" 2 "Disabled" 1 "On" 0 "Off"; +VAL_ 929 BalrWndwLeft_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 929 WndwPsngrRear_D_RqBalrl 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 929 WndwPsngr_D_RqBalrl 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 929 WndwDrvRear_D_RqBalrl 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 929 WndwDrv_D_RqBalrl 3 "NotUsed" 2 "Stop" 1 "AutoUp" 0 "NoRequest"; +VAL_ 929 BalrSnsLeft_D_Falt 3 "Invalid" 2 "SystemFailure" 1 "Blocked" 0 "Clear"; +VAL_ 929 BalrMdeSelLeft_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 929 BalrMdeLeft_D_Stat 3 "NotUsed" 2 "High" 1 "Medium" 0 "Low"; +VAL_ 929 BalrLckLeft_B_Stat 1 "Enable" 0 "Disable"; +VAL_ 929 CamraRearOn_B_RqBalrl 1 "Active" 0 "Inactive"; +VAL_ 929 DrLckActv_B_RqBalrl 1 "Active" 0 "Null"; +VAL_ 402 PrkAidSwtch_D_RqMnu 1 "Pressed" 0 "Not_Pressed"; +VAL_ 402 ApaSwtch_D_RqMnu 3 "NotUsed2" 2 "NotUsed1" 1 "Pressed" 0 "Not_Pressed"; +VAL_ 402 ApaMdeStat_D_RqDrv 7 "Faulty" 6 "Off" 5 "NotUsed2" 4 "NotUsed1" 3 "POA" 2 "PPA" 1 "SAPP" 0 "Inactive"; +VAL_ 402 CamraViewSplit_B_Rq 1 "On" 0 "Off"; +VAL_ 402 CamraZoomMan_D_Rq 7 "Unknown" 6 "Invalid" 5 "Zoom_Level_V" 4 "Zoom_Level_IV" 3 "Zoom_Level_III" 2 "Zoom_Level_II" 1 "Zoom_Level_I" 0 "Off"; +VAL_ 402 CamraOvrlStat_D_Rq 1 "On" 0 "Off"; +VAL_ 402 CamraOvrlDyn_D_Rq 1 "On" 0 "Off"; +VAL_ 402 CamAutoTowbarZoom 1 "On" 0 "Off"; +VAL_ 402 DistanceBarSetting 1 "On" 0 "Off"; +VAL_ 924 DcacOut_Pw_Mx 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 924 DcacOut2_Pw_Actl 8191 "Faulty" 8190 "NoDataExists"; +VAL_ 924 DcacOut1_Pw_Actl 8191 "Faulty" 8190 "NoDataExists"; +VAL_ 924 DcacIn_Pw_Mx 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 923 DcacIn_U2_Actl 4095 "Faulty" 4094 "NoDataExists"; +VAL_ 923 DcacIn_U_Actl 4095 "Fault" 4094 "NoDataExists"; +VAL_ 923 DcacIn_I_Actl 2047 "Faulty" 2046 "NoDataExists"; +VAL_ 923 Dcac_Te_Actl 255 "Faulty" 254 "NoDataExists"; +VAL_ 922 DcacBp2BrkrOpn_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacBp1BrkrOpn_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacIpRcBrkrOpn_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacRdy_D2_Stat 3 "Faulted" 2 "RecoverableFault" 1 "Active" 0 "Idle"; +VAL_ 922 DcacOvrld_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacOverTe_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacGfci_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacErr_B_Stat 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacAcUDetct_B_Falt 1 "Faulted" 0 "NotFaulted"; +VAL_ 922 DcacRdy_D_Stat 7 "NotUsed_2" 6 "NotUsed_1" 5 "Faulted" 4 "ProtectionTempearture" 3 "ProtectionOverload" 2 "ProtectionGfci" 1 "Active" 0 "Idle"; +VAL_ 922 DcacPlugPrsnt_B_Stat 1 "Yes" 0 "No"; +VAL_ 922 DcacClntFlw_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; +VAL_ 922 CoolFanDcac_D_Rq 3 "High" 2 "Medium" 1 "Low" 0 "Off"; diff --git a/opendbc_repo/opendbc/dbc/generator/chrysler/.gitignore b/opendbc_repo/opendbc/dbc/generator/chrysler/.gitignore new file mode 100644 index 0000000000..46fc4e0d88 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/chrysler/.gitignore @@ -0,0 +1 @@ +_*generated.dbc diff --git a/opendbc_repo/opendbc/dbc/generator/chrysler/_stellantis_common.dbc b/opendbc_repo/opendbc/dbc/generator/chrysler/_stellantis_common.dbc new file mode 100644 index 0000000000..df913561de --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/chrysler/_stellantis_common.dbc @@ -0,0 +1,185 @@ +BO_ 258 STEERING: 8 XXX + SG_ STEERING_ANGLE : 5|14@0+ (0.5,-2048) [-2048|2047] "deg" XXX + SG_ STEERING_RATE : 21|14@0+ (0.5,-2048) [-2048|2047] "deg/s" XXX + SG_ STEERING_ANGLE_HP : 48|4@1+ (0.1,-0.4) [-0.4|0.4] "deg" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 264 ECM_1: 8 XXX + SG_ ENGINE_RPM : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ ENGINE_TORQUE : 20|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX + SG_ EXPECTED_ENGINE_TORQUE : 36|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 280 ECM_TRQ: 8 XXX + SG_ ENGINE_TORQ_MAX : 4|13@0+ (.25,-500) [-500|1547.5] "NM" XXX + SG_ ENGINE_TORQ_MIN : 20|13@0+ (.25,-500) [-500|1547.5] "NM" XXX + +BO_ 284 ESP_8: 8 XXX + SG_ BRK_PRESSURE : 3|12@0+ (1,0) [0|1] "" XXX + SG_ Vehicle_Stopped : 7|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_PEDAL : 19|12@0+ (1,0) [0|1] "" XXX + SG_ Vehicle_Speed : 39|16@0+ (0.0078125,0) [0|511.984375] "km/h" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 288 ECM_2: 7 XXX + SG_ ACC_TORQUE_REQ_ENABLE : 5|1@1+ (1,0) [0|0] "" XXX + SG_ ESC_TORQUE_REQ_ENABLE : 6|1@1+ (1,0) [0|0] "" XXX + SG_ TCM_TORQUE_REQ_ENABLE : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Accelerator_Position : 16|8@1+ (0.4,0) [0|100] "%" XXX + SG_ CRUISE_OVERRIDE : 31|1@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 47|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 55|8@0+ (1,0) [0|0] "" XXX + +BO_ 320 ESP_1: 8 XXX + SG_ Brake_State : 0|2@1+ (1,0) [0|0] "" XXX + SG_ Brake_Pedal_State : 2|2@1+ (1,0) [0|0] "" XXX + SG_ ACC_Engaged : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Enabled : 23|1@0+ (1,0) [0|1] "" XXX + SG_ Vehicle_Speed : 33|10@0+ (0.5,0) [0|511] "km/h" XXX + SG_ ACC_OFF_REQ : 39|2@0+ (1,0) [0|0] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRESSED_ACC : 6|1@0+ (1,0) [0|3] "" XXX + +BO_ 268 ESP_2: 8 ESC + SG_ ESC_TORQUE_REQ : 4|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX + SG_ ACC_TORQUE_REQ_ENABLE : 5|1@1+ (1,0) [0|0] "" XXX + SG_ ESC_TORQUE_REQ_MAX : 6|1@1+ (1,0) [0|0] "" XXX + SG_ ESC_TORQUE_REQ_MIN : 7|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_TORQUE_REQ : 20|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX + SG_ TCS_ACTIVE : 21|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_TORQUE_REQ_MAX : 22|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_BRK_PREP : 40|1@1+ (1,0) [0|0] "" XXX + SG_ DISABLE_FUEL_SHUTOFF : 47|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_REQ_ACTIVE : 48|3@1+ (1,0) [0|0] "" XXX + SG_ COLLISION_BRK_PREP : 51|1@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] "" XXX + +BO_ 344 ESP_6: 8 XXX + SG_ WHEEL_SPEED_FL : 5|14@0+ (0.5,0) [0|8191] "rpm" XXX + SG_ WHEEL_SPEED_FR : 21|14@0+ (0.5,0) [0|8191] "rpm" XXX + SG_ WHEEL_SPEED_RL : 37|14@0+ (0.5,0) [0|8191] "rpm" XXX + SG_ WHEEL_SPEED_RR : 53|14@0+ (0.5,0) [0|8191] "rpm" XXX + +BO_ 368 Transmission_Status: 8 XXX + SG_ Gear_State : 2|3@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 464 ORC_1: 8 XXX + SG_ SEATBELT_DRIVER_UNLATCHED : 13|1@0+ (1,0) [0|1] "" XXX + +BO_ 500 DAS_3: 8 XXX + SG_ ENGINE_TORQUE_REQUEST : 4|13@0+ (0.25,-500) [-500|1547.5] "Nm" XXX + SG_ ENGINE_TORQUE_REQUEST_MAX : 7|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_STANDSTILL : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_GO : 6|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_DECEL : 19|12@0+ (0.004885,-16) [-16|4] "m/s2" XXX + SG_ ACC_AVAILABLE : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ACTIVE : 21|1@0+ (1,0) [0|1] "" XXX + SG_ DISABLE_FUEL_SHUTOFF : 23|1@1+ (1,0) [0|0] "" XXX + SG_ GR_MAX_REQ : 32|4@1+ (1,0) [0|0] "" XXX + SG_ ACC_DECEL_REQ : 36|3@1+ (1,0) [0|0] "" XXX + SG_ ACC_FAULTED : 46|2@1+ (1,0) [0|0] "" XXX + SG_ COLLISION_BRK_PREP : 48|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_BRK_PREP : 49|1@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 501 DAS_4: 8 XXX + SG_ ACC_SET_SPEED_KPH : 15|8@0+ (1,0) [0|3] "km/h" XXX + SG_ ACC_SET_SPEED_MPH : 23|8@0+ (1,0) [0|3] "mph" XXX + SG_ ACC_DISTANCE_CONFIG_1 : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ACC_DISTANCE_CONFIG_2 : 41|2@0+ (1,0) [0|3] "" XXX + SG_ SPEED_DIGITAL : 63|8@0+ (1,0) [0|255] "mph" XXX + SG_ ACC_STATE : 38|3@0+ (1,0) [0|7] "" XXX + SG_ FCW_OFF : 25|2@0+ (1,0) [0|3] "" XXX + SG_ FCW_ERROR : 27|2@0+ (1,0) [0|3] "" XXX + SG_ FCW_BRAKE_ENABLED : 29|1@0+ (1,0) [0|1] "" XXX + SG_ FCW_BRAKE_DISABLED : 47|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_FAULTED : 50|1@0+ (1,0) [0|1] "" XXX + +BO_ 544 EPS_2: 8 XXX + SG_ LKAS_STATE : 23|4@0+ (1,0) [0|15] "" XXX + SG_ COLUMN_TORQUE : 2|11@0+ (1,-1024) [-1024|1023] "" XXX + SG_ TORQUE_OVERLAY_STATUS : 6|4@0+ (1,0) [0|15] "" XXX + SG_ EPS_TORQUE_MOTOR_RAW : 19|12@0+ (1,-2048) [-2048|2047] "" XXX + SG_ EPS_TORQUE_MOTOR : 34|11@0+ (1,-1024) [-1024|1023] "" XXX + SG_ LKAS_TEMPORARY_FAULT : 38|1@0+ (1,0) [0|1] "" XXX + SG_ AUTO_PARK_HAS_CONTROL_2 : 51|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 559 ECM_5: 8 XXX + SG_ Accelerator_Position : 0|8@1+ (0.4,0) [0|100] "%" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 571 CRUISE_BUTTONS: 3 XXX + SG_ ACC_Cancel : 0|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_Distance_Dec : 1|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_Accel : 2|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_Decel : 3|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_Resume : 4|1@0+ (1,0) [0|1] "" XXX + SG_ Cruise_OnOff : 6|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_OnOff : 7|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_Distance_Inc : 8|1@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 15|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 625 DAS_5: 8 XXX + SG_ FCW_STATE : 2|1@1+ (1,0) [0|0] "" XXX + SG_ FCW_DISTANCE : 3|2@1+ (1,0) [0|0] "" XXX + SG_ ACCFCW_MESSAGE : 12|4@1+ (1,0) [0|0] "" XXX + SG_ SET_SPEED_KPH : 24|8@1+ (1,0) [0|250] "km/h" XXX + SG_ WHEEL_TORQUE_REQUEST : 38|15@0+ (1,-7767) [-7767|24999] "Nm" XXX + SG_ WHEEL_TORQUE_REQUEST_ACTIVE : 39|1@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 669 EPB_1: 3 XXX + SG_ PARKING_BRAKE_STATUS : 11|3@0+ (1,0) [0|7] "" XXX + SG_ COUNTER : 15|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 678 DAS_6: 8 XXX + SG_ LKAS_ICON_COLOR : 1|2@0+ (1,0) [0|3] "" XXX + SG_ LKAS_LANE_LINES : 19|4@0+ (1,0) [0|1] "" XXX + SG_ LKAS_ALERTS : 27|4@0+ (1,0) [0|1] "" XXX + SG_ CAR_MODEL : 15|8@0+ (1,0) [0|255] "" XXX + SG_ AUTO_HIGH_BEAM_ON : 47|1@1+ (1,0) [0|0] "" XXX + SG_ LKAS_DISABLED : 56|1@1+ (1,0) [0|0] "" XXX + +BO_ 720 BSM_1: 6 XXX + SG_ RIGHT_STATUS : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_STATUS : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 792 STEERING_LEVERS: 8 XXX + SG_ TURN_SIGNALS : 0|2@1+ (1,0) [0|3] "" XXX + SG_ HIGH_BEAM_PRESSED : 2|1@0+ (1,0) [0|3] "" XXX + +BO_ 820 BCM_1: 8 XXX + SG_ DOOR_OPEN_FL : 17|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 18|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 20|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_TRUNK : 22|1@0+ (1,0) [0|1] "" XXX + SG_ PARKING_BRAKE_SWITCH : 23|1@0+ (1,0) [0|1] "" XXX + SG_ TURN_LIGHT_LEFT : 31|1@0+ (1,0) [0|1] "" XXX + SG_ TURN_LIGHT_RIGHT : 30|1@0+ (1,0) [0|1] "" XXX + SG_ HIGH_BEAM_DISPLAY : 58|1@0+ (1,0) [0|1] "" XXX + +VAL_ 320 ACC_OFF_REQ 2 "PERMANENT" 1 "TEMPORARY" 0 "NONE" +VAL_ 368 Gear_State 4 "D" 2 "N" 1 "R" 0 "P" ; +VAL_ 669 PARKING_BRAKE_STATUS 3 "RELEASING" 2 "APPLYING" 1 "APPLIED" 0 "OFF" ; + +CM_ SG_ 258 STEERING_ANGLE_HP "Steering angle high precision"; +CM_ SG_ 264 ENGINE_TORQUE "Effective engine torque"; +CM_ SG_ 264 EXPECTED_ENGINE_TORQUE "Expected Engine Torque based on target engine speed"; +CM_ SG_ 678 LKAS_ICON_COLOR "3 is yellow, 2 is green, 1 is white, 0 is null"; +CM_ SG_ 678 LKAS_LANE_LINES "0x01 transparent lines, 0x02 left white, 0x03 right white, 0x04 left yellow with car on top, 0x05 left yellow with car on top, 0x06 both white, 0x07 left yellow, 0x08 left yellow right white, 0x09 right yellow, 0x0a right yellow left white, 0x0b left yellow with car on top right white, 0x0c right yellow with car on top left white, (0x00, 0x0d, 0x0e, 0x0f) null"; +CM_ SG_ 678 LKAS_ALERTS "(0x01, 0x02) lane sense off, (0x03, 0x04, 0x06) place hands on steering wheel, 0x07 lane departure detected + place hands on steering wheel, (0x08, 0x09) lane sense unavailable + clean front windshield, 0x0b lane sense and auto high beam unavailable + clean front windshield, 0x0c lane sense unavailable + service required, (0x00, 0x05, 0x0a, 0x0d, 0x0e, 0x0f) null"; diff --git a/opendbc_repo/opendbc/dbc/generator/chrysler/_stellantis_common_ram.py b/opendbc_repo/opendbc/dbc/generator/chrysler/_stellantis_common_ram.py new file mode 100755 index 0000000000..fa408f1315 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/chrysler/_stellantis_common_ram.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import os + +chrysler_to_ram = { + "_stellantis_common_ram_dt_generated.dbc": { + 258: 35, + 264: 37, + 268: 113, + 280: 181, + 284: 121, + 288: 123, + 320: 131, + 344: 139, + 368: 147, + 464: 464, + 500: 153, + 501: 232, + 544: 49, + 571: 177, + 559: 157, + 625: 163, + 669: 213, + 678: 250, + 720: 720, + 792: 792, + 820: 657, + }, + "_stellantis_common_ram_hd_generated.dbc": { + 571: 570, + 678: 629, + }, +} + +if __name__ == "__main__": + src = '_stellantis_common.dbc' + chrysler_path = os.path.dirname(os.path.realpath(__file__)) + + for out, addr_lookup in chrysler_to_ram.items(): + with open(os.path.join(chrysler_path, src), encoding='utf-8') as in_f, open(os.path.join(chrysler_path, out), 'w', encoding='utf-8') as out_f: + out_f.write(f'CM_ "Generated from {src}"\n\n') + + wrote_addrs = set() + for line in in_f.readlines(): + if line.startswith(('BO_', 'VAL_')): + sl = line.split(' ') + addr = int(sl[1]) + wrote_addrs.add(addr) + + sl[1] = str(addr_lookup.get(addr, addr)) + line = ' '.join(sl) + out_f.write(line) + + missing_addrs = set(addr_lookup.keys()) - wrote_addrs + assert len(missing_addrs) == 0, f"Missing addrs from {src}: {missing_addrs}" diff --git a/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_pacifica_2017_hybrid.dbc b/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_pacifica_2017_hybrid.dbc new file mode 100644 index 0000000000..3f4b373843 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_pacifica_2017_hybrid.dbc @@ -0,0 +1,172 @@ +CM_ "IMPORT _stellantis_common.dbc"; + +BO_ 514 SPEED_1: 8 XXX + SG_ SPEED_LEFT : 7|12@0+ (0.071028,0) [0|65535] "m/s" XXX + SG_ SPEED_RIGHT : 23|12@0+ (0.071028,0) [0|1023] "m/s" XXX + +BO_ 653 BRAKE_MODULE: 2 XXX + SG_ BRAKE_PRESSURE : 15|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRESSED : 4|1@0+ (1,0) [0|4] "" XXX + +BO_ 746 GEAR: 5 XXX + SG_ PRNDL : 2|3@0+ (1,0) [0|7] "" XXX + SG_ GEAR_CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 31|4@0+ (1,0) [0|15] "" XXX + +BO_ 736 TRIP: 8 XXX + SG_ COUNTER : 7|16@0+ (1,0) [0|65535] "Meters" XXX + SG_ COUNTER_2 : 23|16@0+ (1,0) [0|65535] "Meters" XXX + +BO_ 658 LKAS_COMMAND: 6 XXX + SG_ COUNTER : 39|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + SG_ STEERING_TORQUE : 2|11@0+ (1,-1024) [0|1] "" XXX + SG_ LKAS_CONTROL_BIT : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 705 AUTO_PARK_BUTTON: 8 XXX + SG_ AUTO_PARK_TOGGLE_2 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ AUTO_PARK_TOGGLE_1 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ INCREASING_UNKNOWN : 38|7@0+ (1,0) [0|15] "" XXX + +BO_ 719 AUTO_PARK_SIGNALS_1: 8 XXX + SG_ AUTO_PARK_UNKNOWN_1 : 7|16@0+ (1,0) [0|31] "" XXX + +BO_ 671 AUTO_PARK_REQUEST: 8 XXX + SG_ AUTO_PARK_CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ AUTO_PARK_STATUS : 7|5@0+ (1,0) [0|15] "" XXX + SG_ AUTO_PARK_COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ AUTO_PARK_MODE : 22|2@0+ (1,0) [0|3] "" XXX + SG_ AUTO_PARK_CMD : 2|11@0+ (1,-1024) [0|1] "NM" XXX + +BO_ 784 AUTO_PARK_LESS_INTERESTING: 8 XXX + SG_ INCREASING_UNKNOWN : 55|8@0+ (1,0) [0|7] "" XXX + SG_ AUTO_PARK_PERPENDICULAR_2 : 61|1@0+ (1,0) [0|255] "" XXX + +BO_ 826 AUTO_PARK_SIGNALS_3: 8 XXX + SG_ AUTO_PARK_HAS_CONTROL_3 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HUMAN_HAS_CONTROL : 2|1@0+ (1,0) [0|1] "" XXX + SG_ AUTO_PARK_GEAR_1 : 27|4@0+ (1,0) [0|255] "" XXX + SG_ AUTO_PARK_GEAR_2 : 35|4@0+ (1,0) [0|15] "" XXX + SG_ AUTO_PARK_GEAR_3 : 51|4@0+ (1,0) [0|15] "" XXX + +BO_ 332 STEERING_2: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ ENERGY_RELATED : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ STEER_ANGLE_2 : 7|13@0+ (0.3187251,-1307.888) [-360|360] "deg" XXX + +BO_ 331 BRAKE_3: 8 XXX + SG_ BRAKE_RELATED_3 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 608 PARKSENSE_SIGNAL: 8 XXX + SG_ PARKSENSE_DISABLED : 34|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ IN_REVERSE : 10|1@0+ (1,0) [0|255] "" XXX + SG_ AUTO_PARK_HAS_CONTROL_1 : 16|1@0+ (1,0) [0|255] "" XXX + SG_ HUMAN_HAS_CONTROL : 17|1@0+ (1,0) [0|3] "" XXX + +BO_ 729 LKAS_HEARTBIT: 5 XXX + SG_ LKAS_STATUS_OK : 31|16@0+ (1,0) [0|65535] "" XXX + +BO_ 257 ACCEL_RELATED_101: 5 XXX + SG_ ENERGY_OR_RPM : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 825 AUDIBLE_BEEP_339: 2 XXX + SG_ BEEP_339 : 7|16@0+ (1,0) [0|65535] "" XXX + +BO_ 168 ACCEL_RELATED_a8: 8 XXX + SG_ ACCEL_RELATED : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 270 ACCEL_RELATED_10e: 8 XXX + SG_ ACCEL_OR_RPM : 7|16@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ ELECTRIC_MOTOR : 23|16@0+ (1,0) [0|65535] "" XXX + +BO_ 291 ENERGY_RELATED_123: 8 XXX + SG_ ENERGY_GAIN_LOSS : 18|11@0- (1,0) [0|255] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ ENERGY_SMOOTHER_CURVE : 35|12@0+ (1,0) [0|2047] "" XXX + +BO_ 294 ENERGY_RELATED_126: 8 XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_126_1 : 3|12@0+ (1,0) [0|4095] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ UNKNOWN_126_2 : 35|12@0+ (1,0) [0|4095] "" XXX + SG_ ENERGY_GAIN_LOSS_NOISY : 19|12@0+ (1,0) [0|2047] "" XXX + +BO_ 308 ACCEL_GAS_134: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ ACCEL_134 : 46|7@0+ (1,0) [0|127] "" XXX + +BO_ 532 ENERGY_RELATED_214: 8 XXX + SG_ NOISY_SLOWLY_DECREASING : 16|9@0+ (1,0) [0|255] "" XXX + SG_ ENERGY_RELATED : 0|9@0+ (1,0) [0|255] "" XXX + +BO_ 655 CHARGING_MAYBE_28F: 8 XXX + SG_ CHARGING : 1|2@0+ (1,0) [0|3] "" XXX + +BO_ 660 BRAKE_RELATED_294: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PERHAPS_294 : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 764 ACCEL_RELATED_2FC: 8 XXX + SG_ ACCEL_2FC : 13|6@0+ (1,0) [0|255] "" XXX + +BO_ 816 TRACTION_BUTTON: 8 XXX + SG_ TRACTION_OFF : 19|1@0+ (1,0) [0|3] "" XXX + SG_ TOGGLE_PARKSENSE : 52|1@0+ (1,0) [0|3] "" XXX + +BO_ 878 ACCEL_RELATED_36E: 8 XXX + SG_ ACCEL_OR_RPM_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ACCEL_OR_RPM_1 : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 324 SPEED_2: 8 XXX + SG_ SPEED_2 : 31|16@0+ (0.01,0) [0|255] "m/s" XXX + +BO_ 832 UNKNOWN_340: 8 XXX + SG_ SPEED_DIGITAL : 63|8@0+ (1,0) [0|255] "mph" XXX + +CM_ SG_ 653 BRAKE_PRESSURE "max seems to be 148"; +CM_ SG_ 746 PRNDL "5=L, 4=D, 3=N, 2=R, 1=P"; +CM_ SG_ 320 BRAKE_PRESSED_2 "Value is 5 when brake is pressed by human, 1 when ACC brake"; +CM_ SG_ 320 BRAKE_PRESSED_ACC "set when ACC brakes"; +CM_ SG_ 792 TURN_SIGNALS "1=Left, 2=Right"; +CM_ SG_ 264 ACCEL_PEDAL "not in ACC so seems to be actual pedal. Use for gasPressed"; +CM_ SG_ 544 LKAS_STATE "2 when autopark has control, 8 when is actuatable by lkas, 4 when there is a fault"; +CM_ SG_ 658 LKAS_STEERING_TORQUE "Most sent by stock system is 1024+-230. + is left. typically changes by 2 or 3 each 0.01s"; +CM_ SG_ 678 LKAS_ICON_COLOR "3 is yellow, 2 is green, 1 is white, 0 is null"; +CM_ SG_ 678 LKAS_LANE_LINES "0x01 transparent lines, 0x02 left white, 0x03 right white, 0x04 left yellow with car on top, 0x05 left yellow with car on top, 0x06 both white, 0x07 left yellow, 0x08 left yellow right white, 0x09 right yellow, 0x0a right yellow left white, 0x0b left yellow with car on top right white, 0x0c right yellow with car on top left white, (0x00, 0x0d, 0x0e, 0x0f) null"; +CM_ SG_ 678 LKAS_ALERTS "(0x01, 0x02) lane sense off, (0x03, 0x04, 0x06) place hands on steering wheel, 0x07 lane departure detected + place hands on steering wheel, (0x08, 0x09) lane sense unavailable + clean front windshield, 0x0b lane sense and auto high beam unavailable + clean front windshield, 0x0c lane sense unavailable + service required, (0x00, 0x05, 0x0a, 0x0d, 0x0e, 0x0f) null"; +CM_ SG_ 705 AUTO_PARK_TOGGLE_1 "set briefly when turning on or off self-parking"; +CM_ SG_ 671 AUTO_PARK_CMD "Request Appears to be in NM"; +CM_ SG_ 671 AUTO_PARK_STATUS "1 = IDLE / NO REQUEST 9 = START REQUEST 10 = REQUEST MODE 11 = REQUEST MODE"; +CM_ SG_ 826 AUTO_PARK_GEAR_1 "Reverse=0, Forward=f"; +CM_ SG_ 826 AUTO_PARK_GEAR_2 "Reverse=0, Forward=f"; +CM_ SG_ 826 AUTO_PARK_GEAR_3 "Reverse=0, Forward=f"; +CM_ SG_ 332 STEER_ANGLE_2 "slightly lags the other steer_angle signal. also more noisy."; +CM_ SG_ 608 PARKSENSE_DISABLED "set if parksense is disabled"; +CM_ SG_ 729 LKAS_STATUS_OK "Set to 0x0820 when LKAS system is plugged in."; +CM_ SG_ 825 BEEP_339 "sent every 0.5s. 0050 is no beep. To beep send 4355 or 4155. Used by ParkSense warning."; +CM_ SG_ 270 ELECTRIC_MOTOR "0x7fff indicates electric motor not in use"; +CM_ SG_ 291 ENERGY_GAIN_LOSS "unsure what this actually is"; +CM_ SG_ 291 ENERGY_SMOOTHER_CURVE "unsure what it is, but smoother"; +CM_ SG_ 308 ACCEL_134 "only set when human presses accel pedal"; +CM_ SG_ 532 NOISY_SLOWLY_DECREASING "perhaps battery but do not know"; +CM_ SG_ 816 TRACTION_OFF "set when traction off button is enabled"; +CM_ SG_ 816 TOGGLE_PARKSENSE "sending 3000071ec0ff9000 enables or disables parksense"; +CM_ SG_ 324 SPEED_2 "signal is approx half other speeds"; +CM_ SG_ 501 ACC_SPEED_CONFIG_KPH "speed configured for ACC"; +CM_ SG_ 501 ACC_SPEED_CONFIG_MPH "speed configured for ACC"; +CM_ SG_ 501 CRUISE_STATE "may just be an icon, but seems to indicate different cruise modes: ACC and Non-ACC and engaged state for both."; +CM_ SG_ 625 SPEED "zero on non-acc drives"; + +VAL_ 501 CRUISE_STATE 0 "Off" 1 "CC On" 2 "CC Engaged" 3 "ACC On" 4 "ACC Engaged"; +VAL_ 746 PRNDL 5 "L" 4 "D" 3 "N" 2 "R" 1 "P"; +VAL_ 792 TURN_SIGNALS 2 "Right" 1 "Left"; diff --git a/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_ram_dt.dbc b/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_ram_dt.dbc new file mode 100644 index 0000000000..c9be635e10 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_ram_dt.dbc @@ -0,0 +1,57 @@ +CM_ "IMPORT _stellantis_common_ram_dt_generated.dbc"; + +BO_ 53 PCM_2: 8 XXX + SG_ ENG_TORQUE_REQ : 3|12@0+ (1,0) [0|7] "" XXX + SG_ ENG_TORQUE_OUT : 19|12@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + +BO_ 133 TCM_1: 8 XXX + SG_ SHIFT_PENDING : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACTUAL_GEAR : 11|4@0+ (1,0) [0|15] "" XXX + SG_ DESIRED_GEAR : 15|4@0+ (1,0) [0|1] "" XXX + SG_ TC_LOCKED : 17|1@1+ (1,0) [0|0] "" XXX + SG_ OUTPUT_SPEED : 31|16@0+ (1,0) [0|65534] "rpm" XXX + SG_ INPUT_SPEED : 47|16@0+ (1,0) [0|65534] "rpm" XXX + SG_ OUTPUT_SPEED_SIGN : 57|2@0+ (1,0) [0|3] "" XXX + SG_ COUNTER : 61|4@0+ (1,0) [0|15] "" XXX + +BO_ 135 ABS_2: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_BRAKE : 15|8@0+ (1,0) [0|1] "" XXX + +BO_ 137 ESP_4: 8 XXX + SG_ Yaw_Rate : 7|16@0+ (0.01,-327.68) [-327.68|327.66] "deg/s" XXX + SG_ Acceleration : 32|8@1+ (0.08,-10.24) [-10.24|10.08] "m/s2" XXX + +BO_ 164 EPS_3: 8 XXX + SG_ DASM_FAULT : 34|1@0+ (1,0) [0|1] "" XXX + SG_ Activation_Status : 48|3@1+ (1,0) [0|1] "" XXX + SG_ Driver_Override : 35|1@0+ (1,0) [0|1] "" XXX + SG_ Hands_on_Wheel : 51|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 166 LKAS_COMMAND: 8 XXX + SG_ STEERING_TORQUE : 10|11@0+ (1,-1024) [0|1] "" XXX + SG_ LKAS_CONTROL_BIT : 24|3@1+ (1,0) [0|1] "" XXX + SG_ DASM_FAULT : 51|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 221 Center_Stack_1: 8 XXX + SG_ LKAS_Button : 53|1@1+ (1,0) [0|0] "" XXX + SG_ Traction_Button : 54|1@0+ (1,0) [0|1] "" XXX + +BO_ 650 Center_Stack_2: 8 XXX + SG_ LKAS_Button : 57|1@1+ (1,0) [0|0] "" XXX + + +CM_ SG_ 133 ACTUAL_GEAR "0xd = P, 0x1-8 = D (actual gear), 0xb = R or N?? TODO find R vs N"; +CM_ SG_ 153 ACC_Engaged "SENT BY FORWARD CAMERA 1 = ACTIVE, 3 = ENGAGED, 0 = DISENGAGED/OFF"; +CM_ SG_ 166 LKAS_CONTROL_BIT "0=IDLE, 1=HAS 2=LKAS 3=ABSD, 4=TJA, 7=SNA"; +CM_ SG_ 250 Auto_High_Beam "1 = HIGH BEAMS OK 0 = HIGH BEAMS OFF "; +CM_ SG_ 250 LKAS_LANE_LINES "9 = LEFT CAUTION, 11 = VERY LEFT CAUTION 10 = RIGHT CAUTION, 14 = VERY RIGHT, 4 = NO LINES DETECTED, 3 = LINES DETECTED, SYSTEM ACTIVE"; +CM_ SG_ 464 Driver_Seatbelt_Status "1 unbuckled 0 buckled"; +CM_ SG_ 792 High_Beam_Lever_Status "1 is high beam, 0 reg"; diff --git a/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_ram_hd.dbc b/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_ram_hd.dbc new file mode 100644 index 0000000000..373c041667 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/chrysler/chrysler_ram_hd.dbc @@ -0,0 +1,17 @@ +CM_ "IMPORT _stellantis_common_ram_hd_generated.dbc"; + +BO_ 545 EPS_3: 8 XXX + SG_ DASM_FAULT : 34|1@0+ (1,0) [0|1] "" XXX + SG_ Activation_Status : 48|3@1+ (1,0) [0|1] "" XXX + SG_ Driver_Override : 35|1@0+ (1,0) [0|1] "" XXX + SG_ Hands_on_Wheel : 51|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 630 LKAS_COMMAND: 8 XXX + SG_ STEERING_TORQUE : 10|11@0+ (1,-1024) [0|1] "" XXX + SG_ LKAS_CONTROL_BIT : 24|3@1+ (1,0) [0|1] "" XXX + SG_ DASM_FAULT : 51|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + diff --git a/opendbc_repo/opendbc/dbc/generator/ford/FORD_CADS_64.sh b/opendbc_repo/opendbc/dbc/generator/ford/FORD_CADS_64.sh new file mode 100755 index 0000000000..4732a854e5 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/ford/FORD_CADS_64.sh @@ -0,0 +1,2845 @@ +#!/bin/bash + +OUT_FILENAME="../../FORD_CADS_64.dbc" + + +build_bo(){ +id=$1 +# bo=$(($id + 287)) +bo=$(expr $id + 287) + +len=64 +if [ "$id" = "22" ]; then + len=24 +fi + +cat <> ${OUT_FILENAME} +BO_ ${bo} MRR_Detection_0${id}: ${len} MRR +EOF + +build_bo_segment $id "01" +build_bo_segment $id "02" +build_bo_segment $id "03" +if [ "$id" != "22" ]; then + build_bo_segment $id "04" + build_bo_segment $id "05" + build_bo_segment $id "06" +fi +echo "" >> ${OUT_FILENAME} + +} + +build_bo_segment(){ + id=$1 + seg=$2 + base=$((($2 - 1)*72)) +cat <> ${OUT_FILENAME} + SG_ CAN_DET_CONFID_AZIMUTH_${id}_${seg} : $(expr $base + 33)|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_${id}_${seg} : $(expr $base + 56)|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_${id}_${seg} : $(expr $base + 48)|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_${id}_${seg} : $(expr $base + 49)|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_${id}_${seg} : $(expr $base + 0)|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_${id}_${seg} : $(expr $base + 47)|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_${id}_${seg} : $(expr $base + 31)|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_${id}_${seg} : $(expr $base + 15)|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_${id}_${seg} : $(expr $base + 7)|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_${id}_${seg} : $(expr $base + 17)|2@0+ (1,0) [0|3] "" IFV_VFP +EOF +} + + +build_ba(){ +id=$1 +# bo=$(($id + 287)) +ba=$(expr $id + 287) + +len=64 +if [ "$id" = "22" ]; then + len=24 +fi + +cat <> ${OUT_FILENAME} +BA_ "GenMsgSendType" BO_ ${ba} 1; +BA_ "GenMsgILSupport" BO_ ${ba} 1; +BA_ "GenMsgNrOfRepetition" BO_ ${ba} 0; +BA_ "GenMsgCycleTime" BO_ ${ba} 0; +BA_ "NetworkInitialization" BO_ ${ba} 0; +BA_ "GenMsgDelayTime" BO_ ${ba} 0; +EOF + +build_ba_segment $ba $id "01" +build_ba_segment $ba $id "02" +build_ba_segment $ba $id "03" +if [ "$id" != "22" ]; then + build_ba_segment $ba $id "04" + build_ba_segment $ba $id "05" + build_ba_segment $ba $id "06" +fi + +} + +build_ba_segment(){ + ba=$1 + id=$2 + seg=$3 + +cat <> ${OUT_FILENAME} +BA_ "GenSigVtEn" SG_ ${ba} CAN_DET_CONFID_AZIMUTH_${id}_${seg} "CAN_DET_CONFID_AZIMUTH_${id}_${seg}"; +BA_ "GenSigVtName" SG_ ${ba} CAN_DET_CONFID_AZIMUTH_${id}_${seg} "CAN_DET_CONFID_AZIMUTH_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_CONFID_AZIMUTH_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_CONFID_AZIMUTH_${id}_${seg} "CAN_DET_CONFID_AZIMUTH_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_SUPER_RES_TARGET_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_SUPER_RES_TARGET_${id}_${seg} "CAN_DET_SUPER_RES_TARGET_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_ND_TARGET_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_ND_TARGET_${id}_${seg} "CAN_DET_ND_TARGET_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_HOST_VEH_CLUTTER_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_HOST_VEH_CLUTTER_${id}_${seg} "CAN_DET_HOST_VEH_CLUTTER_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_VALID_LEVEL_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_VALID_LEVEL_${id}_${seg} "CAN_DET_VALID_LEVEL_${id}_${seg}"; +BA_ "GenSigStartValue" SG_ ${ba} CAN_DET_AZIMUTH_${id}_${seg} 0; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_AZIMUTH_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_AZIMUTH_${id}_${seg} "CAN_DET_AZIMUTH_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_RANGE_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_RANGE_${id}_${seg} "CAN_DET_RANGE_${id}_${seg}"; +BA_ "GenSigStartValue" SG_ ${ba} CAN_DET_RANGE_RATE_${id}_${seg} 0; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_RANGE_RATE_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_RANGE_RATE_${id}_${seg} "CAN_DET_RANGE_RATE_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_DET_AMPLITUDE_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_DET_AMPLITUDE_${id}_${seg} "CAN_DET_AMPLITUDE_${id}_${seg}"; +BA_ "GenSigSendType" SG_ ${ba} CAN_SCAN_INDEX_2LSB_${id}_${seg} 0; +BA_ "GenSigCmt" SG_ ${ba} CAN_SCAN_INDEX_2LSB_${id}_${seg} "CAN_SCAN_INDEX_2LSB_${id}_${seg}"; +EOF +} + +build_val(){ +id=$1 +# bo=$(($id + 287)) +val=$(expr $id + 287) + +cat <> ${OUT_FILENAME} +VAL_ ${val} CAN_DET_CONFID_AZIMUTH_${id}_01 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ ${val} CAN_DET_CONFID_AZIMUTH_${id}_02 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ ${val} CAN_DET_CONFID_AZIMUTH_${id}_03 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +EOF +if [ "$id" != "22" ]; then +cat <> ${OUT_FILENAME} +VAL_ ${val} CAN_DET_CONFID_AZIMUTH_${id}_04 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ ${val} CAN_DET_CONFID_AZIMUTH_${id}_05 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ ${val} CAN_DET_CONFID_AZIMUTH_${id}_06 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +EOF +fi + +} + + +cat < ${OUT_FILENAME} +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: +BU_: MRR +BO_ 1073741824 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ New_Signal_943 : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ CAN_SENSOR_VANGLE_OFFSET : 0|8@0+ (0.0625,-8) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_SENSOR_FOV_VER : 0|8@0+ (1,0) [0|255] "deg" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE_QF : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE_REF : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_AUTO_ALIGN_VANGLE : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_MMIC_Temp4 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_MMIC_Temp3 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_MMIC_Temp2 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_Processor_Temp2 : 0|8@0+ (1,-50) [-50|205] "C" Vector__XXX + SG_ CAN_CHECKSUM : 0|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ CAN_COUNTER : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_VEHICLE_MODE : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ CAN_USC_CAL_VER_MAJOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_USC_CAL_VER_MINOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_SMC_CAL_VER_MAJOR : 0|16@0+ (1,0) [0|65535] "" Vector__XXX + SG_ CAN_HW_VERSION : 0|32@0+ (1,0) [0|4.29497e+09] "" Vector__XXX + SG_ CAN_FAC_TGT_MTG_SPACE_VER : 0|8@0+ (1,-128) [-128|127] "cm" Vector__XXX + SG_ CAN_ANGLE_MISALIGNMENT_VER : 0|10@0+ (0.03125,-10) [-10|21.9688] "deg" Vector__XXX + SG_ CAN_ANGLE_MOUNTING_VOFFSET : 0|8@0+ (0.0625,-8) [-8|7.9375] "deg" Vector__XXX + SG_ CAN_LATCH_FAULTS : 0|64@0+ (1,0) [0|100] "" Vector__XXX + SG_ CAN_ACTIVE_FAULTS : 0|64@0+ (1,0) [0|1.84467e+19] "" Vector__XXX + SG_ CAN_HISTORY_FAULTS : 0|64@0+ (1,0) [0|1.84467e+19] "" Vector__XXX + SG_ CAN_SERV_ALIGN_ENABLE : 0|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ CAN_LONG_MOUNTING_OFFSET : 0|8@0+ (0.015625,-2) [-2|1.98438] "" Vector__XXX + SG_ CAN_BEAMWIDTH_VERT : 0|7@0+ (0.125,0) [0|15.875] "deg" Vector__XXX + SG_ CAN_VEHICLE_SPEED_CALC_QF : 0|2@0+ (1,0) [0|3] "" Vector__XXX + +BO_ 34 Active_Fault_Latched_2: 8 MRR + SG_ IPMA_PCAN_DataRangeCheck : 4|1@1+ (1,0) [0|1] "" External_Tool + SG_ IPMA_PCAN_MissingMsg : 3|1@1+ (1,0) [0|1] "" External_Tool + SG_ VINSignalCompareFailure : 2|1@1+ (1,0) [0|1] "" External_Tool + SG_ ModuleNotConfiguredError : 1|1@1+ (1,0) [0|1] "" External_Tool + SG_ CarCfgNotConfiguredError : 0|1@1+ (1,0) [0|1] "" External_Tool + +BO_ 33 Active_Fault_Latched_1: 8 MRR + SG_ Active_Flt_Latched_byte7_bit7 : 63|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit6 : 62|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit5 : 61|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte7_bit4 : 60|1@1+ (1,0) [0|1] "" External_Tool + SG_ ARMtoDSPChksumFault : 59|1@1+ (1,0) [0|1] "" External_Tool + SG_ DSPtoArmChksumFault : 58|1@1+ (1,0) [0|1] "" External_Tool + SG_ HostToArmChksumFault : 57|1@1+ (1,0) [0|1] "" External_Tool + SG_ ARMtoHostChksumFault : 56|1@1+ (1,0) [0|1] "" External_Tool + SG_ LoopBWOutOfRange : 55|1@1+ (1,0) [0|1] "" External_Tool + SG_ DSPOverrunFault : 54|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte6_bit5 : 53|1@1+ (1,0) [0|1] "" External_Tool + SG_ TuningSensitivityFault : 52|1@1+ (1,0) [0|1] "" External_Tool + SG_ SaturatedTuningFreqFault : 51|1@1+ (1,0) [0|1] "" External_Tool + SG_ LocalOscPowerFault : 50|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterPowerFault : 49|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte6_bit0 : 48|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit7 : 47|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit6 : 46|1@1+ (1,0) [0|1] "" External_Tool + SG_ XCVRDeviceSPIFault : 45|1@1+ (1,0) [0|1] "" External_Tool + SG_ FreqSynthesizerSPIFault : 44|1@1+ (1,0) [0|1] "" External_Tool + SG_ AnalogConverterDevicSPIFault : 43|1@1+ (1,0) [0|1] "" External_Tool + SG_ SidelobeBlockage : 42|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte5_bit1 : 41|1@1+ (1,0) [0|1] "" External_Tool + SG_ MNRBlocked : 40|1@1+ (1,0) [0|1] "" External_Tool + SG_ ECUTempHighFault : 39|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterTempHighFault : 38|1@1+ (1,0) [0|1] "" External_Tool + SG_ AlignmentRoutineFailedFault : 37|1@1+ (1,0) [0|1] "" External_Tool + SG_ UnreasonableRadarData : 36|1@1+ (1,0) [0|1] "" External_Tool + SG_ MicroprocessorTempHighFault : 35|1@1+ (1,0) [0|1] "" External_Tool + SG_ VerticalAlignmentOutOfRange : 34|1@1+ (1,0) [0|1] "" External_Tool + SG_ HorizontalAlignmentOutOfRange : 33|1@1+ (1,0) [0|1] "" External_Tool + SG_ FactoryAlignmentMode : 32|1@1+ (1,0) [0|1] "" External_Tool + SG_ BatteryLowFault : 31|1@1+ (1,0) [0|1] "" External_Tool + SG_ BatteryHighFault : 30|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_1p25SupplyOutOfRange : 29|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte3_bit4 : 28|1@1+ (1,0) [0|1] "" External_Tool + SG_ ThermistorOutOfRange : 27|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_3p3DACSupplyOutOfRange : 26|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_3p3RAWSupplyOutOfRange : 25|1@1+ (1,0) [0|1] "" External_Tool + SG_ v_5_SupplyOutOfRange : 24|1@1+ (1,0) [0|1] "" External_Tool + SG_ TransmitterIDFault : 23|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit6 : 22|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit5 : 21|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit4 : 20|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit3 : 19|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte2_bit2 : 18|1@1+ (1,0) [0|1] "" External_Tool + SG_ PCANMissingMsgFault : 17|1@1+ (1,0) [0|1] "" External_Tool + SG_ PCANBusOff : 16|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit7 : 15|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit6 : 14|1@1+ (1,0) [0|1] "" External_Tool + SG_ InstructionSetCheckFault : 13|1@1+ (1,0) [0|1] "" External_Tool + SG_ StackOverflowFault : 12|1@1+ (1,0) [0|1] "" External_Tool + SG_ WatchdogFault : 11|1@1+ (1,0) [0|1] "" External_Tool + SG_ PLLLockFault : 10|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte1_bit1 : 9|1@1+ (1,0) [0|1] "" External_Tool + SG_ RAMMemoryTestFault : 8|1@1+ (1,0) [0|1] "" External_Tool + SG_ USCValidationFault : 7|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit6 : 6|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit5 : 5|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit4 : 4|1@1+ (1,0) [0|1] "" External_Tool + SG_ Active_Flt_Latched_byte0_bit3 : 3|1@1+ (1,0) [0|1] "" External_Tool + SG_ KeepAliveChecksumFault : 2|1@1+ (1,0) [0|1] "" External_Tool + SG_ ProgramCalibrationFlashChecksum : 1|1@1+ (1,0) [0|1] "" External_Tool + SG_ ApplicationFlashChecksumFault : 0|1@1+ (1,0) [0|1] "" External_Tool + +BO_ 500 XCP_MRR_DAQ_RESP: 8 MRR + SG_ MRR_xcp_daq_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_daq_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 499 XCP_MRR_DTO_RESP: 8 MRR + SG_ MRR_xcp_dto_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_dto_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 497 XCP_MRR_CTO_RESP: 8 MRR + SG_ MRR_xcp_cto_resp_byte7 : 63|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte6 : 55|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte5 : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte4 : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte3 : 31|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte2 : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte1 : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ MRR_xcp_cto_resp_byte0 : 7|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 1900 Ford_Diag_Resp_Phys: 8 MRR + SG_ TesterPhysicalResCCM : 7|64@0+ (1,0) [0|1.84467e+19] "" IFV_Host + +BO_ 261 MRR_Status_SerialNumber: 8 MRR + SG_ CAN_SEQUENCE_NUMBER : 55|16@0+ (1,0) [0|65535] "" External_Tool + SG_ CAN_SERIAL_NUMBER : 7|40@0+ (1,0) [0|1.09951e+12] "" External_Tool + +BO_ 264 MRR_Status_SwVersion: 8 MRR + SG_ CAN_PBL_Field_Revision : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_PBL_Promote_Revision : 39|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Field_Revision : 23|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Promote_Revision : 15|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_SW_Release_Revision : 7|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_PBL_Release_Revision : 31|8@0+ (1,0) [0|255] "" External_Tool + +BO_ 373 MRR_Header_SensorPosition: 8 MRR + SG_ CAN_SENSOR_POLARITY : 55|1@0+ (1,0) [0|1] "" External_Tool + SG_ CAN_SENSOR_LAT_OFFSET : 39|16@0+ (0.01,0) [0|655.35] "cm" External_Tool + SG_ CAN_SENSOR_LONG_OFFSET : 23|16@0+ (0.01,0) [0|655.35] "cm" External_Tool + SG_ CAN_SENSOR_HANGLE_OFFSET : 7|8@0+ (0.0625,-8) [-8|7.9375] "deg" External_Tool + +BO_ 372 MRR_Header_SensorCoverage: 8 MRR + SG_ CAN_SENSOR_FOV_HOR : 39|8@0+ (1,0) [0|255] "deg" IFV_VFP + SG_ CAN_DOPPLER_COVERAGE : 23|8@0+ (1,-128) [-128|127] "m/s" IFV_VFP + SG_ CAN_RANGE_COVERAGE : 7|8@0+ (1,0) [0|255] "m" IFV_VFP + +BO_ 371 MRR_Header_AlignmentState: 8 MRR + SG_ CAN_AUTO_ALIGN_HANGLE_QF : 13|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_ALIGNMENT_STATUS : 51|4@0+ (1,0) [0|11] "" IFV_VFP + SG_ CAN_ALIGNMENT_STATE : 55|3@0+ (1,0) [0|7] "" IFV_VFP + SG_ CAN_AUTO_ALIGN_HANGLE_REF : 11|10@0+ (0.000341218,-0.174533) [-0.174533|0.174533] "rad" IFV_VFP + SG_ CAN_AUTO_ALIGN_HANGLE : 7|10@0+ (0.000341218,-0.174533) [-0.174533|0.174533] "rad" IFV_VFP + +BO_ 369 MRR_Header_Timestamps: 8 MRR + SG_ CAN_DET_TIME_SINCE_MEAS : 39|11@0+ (0.1,0) [0|204.7] "ms" IFV_Host + SG_ CAN_SENSOR_TIME_STAMP : 7|32@0+ (0.1,0) [0|4.29497e+08] "ms" IFV_VFP + +BO_ 368 MRR_Header_InformationDetections: 8 MRR + SG_ CAN_ALIGN_UPDATES_DONE : 55|16@0+ (1,0) [0|65535] "" IFV_VFP + SG_ CAN_SCAN_INDEX : 31|16@0+ (1,0) [0|65535] "" IFV_VFP + SG_ CAN_NUMBER_OF_DET : 47|8@0+ (1,0) [0|255] "" External_Tool + SG_ CAN_LOOK_ID : 23|2@0+ (1,0) [0|3] "" External_Tool + SG_ CAN_LOOK_INDEX : 7|16@0+ (1,0) [0|65535] "" External_Tool + +BO_ 265 MRR_Status_Temp_Volt: 8 MRR + SG_ CAN_BATT_VOLTS : 63|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_1_25_V : 55|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_5_V : 47|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_3_3_V_RAW : 31|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_3_3_V_DAC : 15|8@0+ (0.08,0) [0|20.4] "V" External_Tool + SG_ CAN_MMIC_Temp1 : 39|8@0+ (1,-50) [-50|205] "C" External_Tool + SG_ CAN_Processor_Thermistor : 23|8@0+ (1,-50) [-50|205] "C" External_Tool + SG_ CAN_Processor_Temp1 : 7|8@0+ (1,-50) [-50|205] "C" External_Tool + +EOF + +build_bo "04" + +cat <> ${OUT_FILENAME} +BO_ 351 MRR_Detection_064: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_64 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_64 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_64 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_64 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_64 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_64 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_64 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_64 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_64 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_64 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 350 MRR_Detection_063: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_63 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_63 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_63 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_63 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_63 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_63 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_63 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_63 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_63 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_63 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 349 MRR_Detection_062: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_62 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_62 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_62 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_62 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_62 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_62 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_62 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_62 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_62 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_62 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 348 MRR_Detection_061: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_61 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_61 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_61 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_61 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_61 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_61 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_61 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_61 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_61 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_61 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 347 MRR_Detection_060: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_60 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_60 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_60 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_60 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_60 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_60 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_60 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_60 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_60 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_60 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 346 MRR_Detection_059: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_59 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_59 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_59 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_59 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_59 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_59 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_59 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_59 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_59 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_59 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 345 MRR_Detection_058: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_58 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_58 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_58 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_58 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_58 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_58 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_58 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_58 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_58 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_58 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 344 MRR_Detection_057: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_57 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_57 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_57 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_57 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_57 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_57 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_57 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_57 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_57 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_57 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 343 MRR_Detection_056: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_56 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_56 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_56 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_56 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_56 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_56 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_56 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_56 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_56 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_56 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 342 MRR_Detection_055: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_55 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_55 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_55 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_55 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_55 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_55 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_55 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_55 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_55 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_55 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 335 MRR_Detection_048: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_48 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_48 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_48 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_48 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_48 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_48 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_48 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_48 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_48 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_48 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 334 MRR_Detection_047: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_47 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_47 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_47 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_47 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_47 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_47 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_47 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_47 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_47 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_47 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 333 MRR_Detection_046: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_46 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_46 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_46 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_46 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_46 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_46 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_46 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_46 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_46 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_46 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 332 MRR_Detection_045: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_45 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_45 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_45 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_45 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_45 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_45 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_45 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_45 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_45 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_45 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 331 MRR_Detection_044: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_44 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_44 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_44 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_44 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_44 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_44 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_44 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_44 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_44 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_44 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 330 MRR_Detection_043: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_43 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_43 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_43 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_43 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_43 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_43 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_43 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_43 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_43 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_43 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 329 MRR_Detection_042: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_42 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_42 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_42 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_42 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_42 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_42 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_42 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_42 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_42 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_42 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 328 MRR_Detection_041: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_41 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_41 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_41 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_41 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_41 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_41 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_41 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_41 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_41 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_41 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 327 MRR_Detection_040: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_40 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_40 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_40 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_40 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_40 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_40 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_40 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_40 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_40 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_40 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 325 MRR_Detection_038: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_38 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_38 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_38 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_38 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_38 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_38 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_38 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_38 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_38 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_38 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 324 MRR_Detection_037: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_37 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_37 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_37 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_37 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_37 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_37 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_37 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_37 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_37 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_37 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 323 MRR_Detection_036: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_36 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_36 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_36 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_36 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_36 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_36 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_36 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_36 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_36 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_36 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 322 MRR_Detection_035: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_35 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_35 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_35 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_35 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_35 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_35 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_35 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_35 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_35 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_35 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 321 MRR_Detection_034: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_34 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_34 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_34 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_34 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_34 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_34 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_34 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_34 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_34 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_34 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 320 MRR_Detection_033: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_33 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_33 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_33 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_33 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_33 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_33 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_33 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_33 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_33 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_33 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 319 MRR_Detection_032: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_32 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_32 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_32 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_32 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_32 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_32 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_32 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_32 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_32 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_32 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 318 MRR_Detection_031: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_31 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_31 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_31 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_31 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_31 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_31 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_31 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_31 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_31 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_31 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 317 MRR_Detection_030: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_30 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_30 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_30 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_30 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_30 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_30 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_30 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_30 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_30 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_30 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 316 MRR_Detection_029: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_29 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_29 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_29 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_29 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_29 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_29 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_29 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_29 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_29 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_29 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 314 MRR_Detection_027: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_27 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_27 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_27 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_27 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_27 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_27 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_27 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_27 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_27 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_27 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 313 MRR_Detection_026: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_26 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_26 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_26 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_26 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_26 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_26 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_26 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_26 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_26 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_26 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 312 MRR_Detection_025: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_25 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_25 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_25 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_25 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_25 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_25 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_25 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_25 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_25 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_25 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 311 MRR_Detection_024: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_24 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_24 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_24 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_24 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_24 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_24 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_24 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_24 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_24 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_24 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 310 MRR_Detection_023: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_23 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_23 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_23 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_23 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_23 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_23 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_23 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_23 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_23 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_23 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +EOF + +build_bo "22" +build_bo "21" +build_bo "20" +build_bo "19" +build_bo "18" + +cat <> ${OUT_FILENAME} +BO_ 341 MRR_Detection_054: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_54 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_54 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_54 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_54 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_54 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_54 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_54 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_54 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_54 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_54 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 340 MRR_Detection_053: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_53 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_53 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_53 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_53 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_53 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_53 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_53 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_53 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_53 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_53 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 339 MRR_Detection_052: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_52 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_52 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_52 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_52 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_52 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_52 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_52 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_52 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_52 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_52 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 338 MRR_Detection_051: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_51 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_51 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_51 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_51 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_51 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_51 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_51 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_51 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_51 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_51 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 337 MRR_Detection_050: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_50 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_50 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_50 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_50 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_50 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_50 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_50 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_50 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_50 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_50 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 336 MRR_Detection_049: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_49 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_49 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_49 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_49 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_49 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_49 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_49 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_49 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_49 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_49 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 326 MRR_Detection_039: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_39 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_39 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_39 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_39 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_39 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_39 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_39 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_39 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_39 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_39 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +BO_ 315 MRR_Detection_028: 8 MRR + SG_ CAN_DET_CONFID_AZIMUTH_28 : 33|2@0+ (1,0) [0|3] "" IFV_VFP + SG_ CAN_DET_SUPER_RES_TARGET_28 : 56|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_ND_TARGET_28 : 48|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_HOST_VEH_CLUTTER_28 : 49|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_VALID_LEVEL_28 : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_DET_AZIMUTH_28 : 47|14@0+ (0.0003834,-3.1416) [-3.1416|3.13964] "rad" IFV_VFP + SG_ CAN_DET_RANGE_28 : 31|14@0+ (0.015625,0) [0|255.984] "m" IFV_VFP + SG_ CAN_DET_RANGE_RATE_28 : 15|14@0+ (0.015625,-128) [-128|127.984] "m/s" IFV_VFP + SG_ CAN_DET_AMPLITUDE_28 : 7|7@0+ (1,-64) [-64|63] "dBsm" IFV_VFP + SG_ CAN_SCAN_INDEX_2LSB_28 : 17|2@0+ (1,0) [0|3] "" IFV_VFP + +EOF + +build_bo "17" +build_bo "16" +build_bo "15" +build_bo "14" +build_bo "13" +build_bo "12" +build_bo "11" +build_bo "10" +build_bo "09" +build_bo "08" +build_bo "07" +build_bo "06" +build_bo "05" +build_bo "03" +build_bo "02" + +cat <> ${OUT_FILENAME} +BO_ 256 MRR_Status_CANVersion: 8 MRR + SG_ CAN_USC_SECTION_COMPATIBILITY : 23|16@0+ (1,0) [0|65535] "" External_Tool + SG_ CAN_PCAN_MINOR_MRR : 7|8@0+ (1,0) [0|255] "" IFV_VFP + SG_ CAN_PCAN_MAJOR_MRR : 15|8@0+ (1,0) [0|255] "" IFV_VFP + +BO_ 257 MRR_Status_Radar: 8 MRR + SG_ CAN_INTERFERENCE_TYPE : 11|2@0+ (1,0) [0|3] "" IFV_Host + SG_ CAN_RECOMMEND_UNCONVERGE : 9|1@0+ (1,0) [0|1] "" IFV_Host + SG_ CAN_BLOCKAGE_SIDELOBE_FILTER_VAL : 15|4@0+ (1,0) [0|15] "" IFV_Host + SG_ CAN_RADAR_ALIGN_INCOMPLETE : 8|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_BLOCKAGE_SIDELOBE : 4|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_BLOCKAGE_MNR : 5|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_EXT_COND_NOK : 1|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_ALIGN_OUT_RANGE : 2|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_ALIGN_NOT_START : 0|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_OVERHEAT_ERROR : 3|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_RADAR_NOT_OP : 6|1@0+ (1,0) [0|1] "" IFV_VFP + SG_ CAN_XCVR_OPERATIONAL : 7|1@0+ (1,0) [0|1] "" IFV_VFP + +EOF + +build_bo "01" + +cat <> ${OUT_FILENAME} +BA_DEF_ SG_ "CrossOver_InfoCAN" ENUM "No","Yes"; +BA_DEF_ SG_ "CrossOver_LIN" ENUM "No","Yes","No","Yes"; +BA_DEF_ SG_ "UsedOnPgmDBC" ENUM "No","Yes","No","Yes","No","Yes"; +BA_DEF_ SG_ "ContentDependant" ENUM "No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ SG_ "GenSigTimeoutTime_RCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_GWM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_OCS" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_ABS_ESC" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_CCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_IPMA" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_TSTR" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_SCCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_PSCM" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime__delete" INT 0 100000; +BA_DEF_ SG_ "GenSigTimeoutTime_Generic_BCM" INT 0 100000; +BA_DEF_ BO_ "NmMessage" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "DiagResponse" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "DiagRequest" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "TpTxIndex" INT 0 255; +BA_DEF_ BO_ "DiagState" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "TpApplType" STRING ; +BA_DEF_ BO_ "NmAsrMessage" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "Mulitplexer" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "ConfiguredTransmitter" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "EventRateOfChange" INT 10 10000; +BA_DEF_ BO_ "GenMsgHandlingTypeDoc" STRING ; +BA_DEF_ BO_ "GenMsgHandlingTypeCode" STRING ; +BA_DEF_ BO_ "GenMsgMarked" STRING ; +BA_DEF_ SG_ "GenSigMarked" STRING ; +BA_DEF_ SG_ "GenSigVtIndex" STRING ; +BA_DEF_ SG_ "GenSigVtName" STRING ; +BA_DEF_ SG_ "GenSigVtEn" STRING ; +BA_DEF_ SG_ "GenSigSNA" STRING ; +BA_DEF_ SG_ "GenSigCmt" STRING ; +BA_DEF_ BO_ "GenMsgCmt" STRING ; +BA_DEF_ SG_ "GenSigSendType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType"; +BA_DEF_ SG_ "GenSigInactiveValue" INT 0 100000; +BA_DEF_ SG_ "GenSigMissingSourceValue" INT 0 1e+09; +BA_DEF_ SG_ "WakeupSignal" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes"; +BA_DEF_ SG_ "GenSigStartValue" INT 0 1e+09; +BA_DEF_ BO_ "GenMsgILSupport" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes"; +BA_DEF_ BO_ "NetworkInitializationCommand" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BO_ "GenMsgSendType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType"; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 100000; +BA_DEF_ BO_ "GenMsgCycleTimeFast" INT 0 100000; +BA_DEF_ BO_ "GenMsgDelayTime" INT 0 1000; +BA_DEF_ BO_ "GenMsgNrOfRepetition" INT 0 100; +BA_DEF_ BO_ "GenMsgStartDelayTime" INT 0 10000; +BA_DEF_ BO_ "NetworkInitialization" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes"; +BA_DEF_ BO_ "MessageGateway" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes"; +BA_DEF_ BU_ "ILUsed" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BU_ "NetworkInitializationUsed" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes","No","Yes"; +BA_DEF_ BU_ "PowerType" ENUM "No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","No","Yes","Cyclic","OnWrite","vector_leerstring","OnChange","vector_leerstring","IfActive","vector_leerstring","NoSigSendType","No","Yes","No","Yes","No","Yes","FixedPeriodic","Event","EnabledPeriodic","NotUsed","NotUsed","EventPeriodic","NotUsed","NotUsed","NoMsgSendType","No","Yes","No","Yes","No","Yes","No","Yes","Switched","Latched","Sleep","vector_leerstring","vector_leerstring"; +BA_DEF_ BU_ "NodeStartUpTime" INT 0 10000; +BA_DEF_ BU_ "NodeWakeUpTime" INT 0 10000; +BA_DEF_ BO_ "GenMsgBackgroundColor" STRING ; +BA_DEF_ BO_ "GenMsgForegroundColor" STRING ; +BA_ "GenMsgCycleTime" BO_ 34 1000; +BA_ "GenMsgSendType" BO_ 34 0; +BA_ "GenSigVtEn" SG_ 34 IPMA_PCAN_DataRangeCheck "IPMA_PCAN_DataRangeCheck"; +BA_ "GenSigVtName" SG_ 34 IPMA_PCAN_DataRangeCheck "IPMA_PCAN_DataRangeCheck"; +BA_ "GenSigVtEn" SG_ 34 IPMA_PCAN_MissingMsg "IPMA_PCAN_MissingMsg"; +BA_ "GenSigVtName" SG_ 34 IPMA_PCAN_MissingMsg "IPMA_PCAN_MissingMsg"; +BA_ "GenSigVtEn" SG_ 34 VINSignalCompareFailure "VINSignalCompareFailure"; +BA_ "GenSigVtName" SG_ 34 VINSignalCompareFailure "VINSignalCompareFailure"; +BA_ "GenSigVtEn" SG_ 34 ModuleNotConfiguredError "ModuleNotConfiguredError"; +BA_ "GenSigVtName" SG_ 34 ModuleNotConfiguredError "ModuleNotConfiguredError"; +BA_ "GenSigVtEn" SG_ 34 CarCfgNotConfiguredError "CarCfgNotConfiguredError"; +BA_ "GenSigVtName" SG_ 34 CarCfgNotConfiguredError "CarCfgNotConfiguredError"; +BA_ "GenMsgCycleTime" BO_ 33 1000; +BA_ "GenMsgSendType" BO_ 33 0; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit7 "Active_Flt_Latched_byte7_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit7 "Active_Flt_Latched_byte7_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit6 "Active_Flt_Latched_byte7_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit6 "Active_Flt_Latched_byte7_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit5 "Active_Flt_Latched_byte7_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit5 "Active_Flt_Latched_byte7_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte7_bit4 "Active_Flt_Latched_byte7_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte7_bit4 "Active_Flt_Latched_byte7_bit4"; +BA_ "GenSigVtEn" SG_ 33 ARMtoDSPChksumFault "ARMtoDSPChksumFault"; +BA_ "GenSigVtName" SG_ 33 ARMtoDSPChksumFault "ARMtoDSPChksumFault"; +BA_ "GenSigVtEn" SG_ 33 DSPtoArmChksumFault "DSPtoArmChksumFault"; +BA_ "GenSigVtName" SG_ 33 DSPtoArmChksumFault "DSPtoArmChksumFault"; +BA_ "GenSigVtEn" SG_ 33 HostToArmChksumFault "HostToArmChksumFault"; +BA_ "GenSigVtName" SG_ 33 HostToArmChksumFault "HostToArmChksumFault"; +BA_ "GenSigVtEn" SG_ 33 ARMtoHostChksumFault "ARMtoHostChksumFault"; +BA_ "GenSigVtName" SG_ 33 ARMtoHostChksumFault "ARMtoHostChksumFault"; +BA_ "GenSigVtEn" SG_ 33 LoopBWOutOfRange "LoopBWOutOfRange"; +BA_ "GenSigVtName" SG_ 33 LoopBWOutOfRange "LoopBWOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 DSPOverrunFault "DSPOverrunFault"; +BA_ "GenSigVtName" SG_ 33 DSPOverrunFault "DSPOverrunFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte6_bit5 "Active_Flt_Latched_byte6_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte6_bit5 "Active_Flt_Latched_byte6_bit5"; +BA_ "GenSigVtEn" SG_ 33 TuningSensitivityFault "TuningSensitivityFault"; +BA_ "GenSigVtName" SG_ 33 TuningSensitivityFault "TuningSensitivityFault"; +BA_ "GenSigVtEn" SG_ 33 SaturatedTuningFreqFault "SaturatedTuningFreqFault"; +BA_ "GenSigVtName" SG_ 33 SaturatedTuningFreqFault "SaturatedTuningFreqFault"; +BA_ "GenSigVtEn" SG_ 33 LocalOscPowerFault "LocalOscPowerFault"; +BA_ "GenSigVtName" SG_ 33 LocalOscPowerFault "LocalOscPowerFault"; +BA_ "GenSigVtEn" SG_ 33 TransmitterPowerFault "TransmitterPowerFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterPowerFault "TransmitterPowerFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte6_bit0 "Active_Flt_Latched_byte6_bit0"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte6_bit0 "Active_Flt_Latched_byte6_bit0"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit7 "Active_Flt_Latched_byte5_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit7 "Active_Flt_Latched_byte5_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit6 "Active_Flt_Latched_byte5_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit6 "Active_Flt_Latched_byte5_bit6"; +BA_ "GenSigVtEn" SG_ 33 XCVRDeviceSPIFault "XCVRDeviceSPIFault"; +BA_ "GenSigVtName" SG_ 33 XCVRDeviceSPIFault "XCVRDeviceSPIFault"; +BA_ "GenSigVtEn" SG_ 33 FreqSynthesizerSPIFault "FreqSynthesizerSPIFault"; +BA_ "GenSigVtName" SG_ 33 FreqSynthesizerSPIFault "FreqSynthesizerSPIFault"; +BA_ "GenSigVtEn" SG_ 33 AnalogConverterDevicSPIFault "AnalogConverterDevicSPIFault"; +BA_ "GenSigVtName" SG_ 33 AnalogConverterDevicSPIFault "AnalogConverterDevicSPIFault"; +BA_ "GenSigVtEn" SG_ 33 SidelobeBlockage "SidelobeBlockage"; +BA_ "GenSigVtName" SG_ 33 SidelobeBlockage "SidelobeBlockage"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte5_bit1 "Active_Flt_Latched_byte5_bit1"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte5_bit1 "Active_Flt_Latched_byte5_bit1"; +BA_ "GenSigVtEn" SG_ 33 MNRBlocked "MNRBlocked"; +BA_ "GenSigVtName" SG_ 33 MNRBlocked "MNRBlocked"; +BA_ "GenSigVtEn" SG_ 33 ECUTempHighFault "ECUTempHighFault"; +BA_ "GenSigVtName" SG_ 33 ECUTempHighFault "ECUTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 TransmitterTempHighFault "TransmitterTempHighFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterTempHighFault "TransmitterTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 AlignmentRoutineFailedFault "AlignmentRoutineFailedFault"; +BA_ "GenSigVtName" SG_ 33 AlignmentRoutineFailedFault "AlignmentRoutineFailedFault"; +BA_ "GenSigVtEn" SG_ 33 UnreasonableRadarData "UnreasonableRadarData"; +BA_ "GenSigVtName" SG_ 33 UnreasonableRadarData "UnreasonableRadarData"; +BA_ "GenSigVtEn" SG_ 33 MicroprocessorTempHighFault "MicroprocessorTempHighFault"; +BA_ "GenSigVtName" SG_ 33 MicroprocessorTempHighFault "MicroprocessorTempHighFault"; +BA_ "GenSigVtEn" SG_ 33 VerticalAlignmentOutOfRange "VerticalAlignmentOutOfRange"; +BA_ "GenSigVtName" SG_ 33 VerticalAlignmentOutOfRange "VerticalAlignmentOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 HorizontalAlignmentOutOfRange "HorizontalAlignmentOutOfRange"; +BA_ "GenSigVtName" SG_ 33 HorizontalAlignmentOutOfRange "HorizontalAlignmentOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 FactoryAlignmentMode "FactoryAlignmentMode"; +BA_ "GenSigVtName" SG_ 33 FactoryAlignmentMode "FactoryAlignmentMode"; +BA_ "GenSigVtEn" SG_ 33 BatteryLowFault "BatteryLowFault"; +BA_ "GenSigVtName" SG_ 33 BatteryLowFault "BatteryLowFault"; +BA_ "GenSigVtEn" SG_ 33 BatteryHighFault "BatteryHighFault"; +BA_ "GenSigVtName" SG_ 33 BatteryHighFault "BatteryHighFault"; +BA_ "GenSigVtEn" SG_ 33 v_1p25SupplyOutOfRange "v_1p25SupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_1p25SupplyOutOfRange "v_1p25SupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte3_bit4 "Active_Flt_Latched_byte3_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte3_bit4 "Active_Flt_Latched_byte3_bit4"; +BA_ "GenSigVtEn" SG_ 33 ThermistorOutOfRange "ThermistorOutOfRange"; +BA_ "GenSigVtName" SG_ 33 ThermistorOutOfRange "ThermistorOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_3p3DACSupplyOutOfRange "v_3p3DACSupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_3p3DACSupplyOutOfRange "v_3p3DACSupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_3p3RAWSupplyOutOfRange "v_3p3RAWSupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_3p3RAWSupplyOutOfRange "v_3p3RAWSupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 v_5_SupplyOutOfRange "v_5_SupplyOutOfRange"; +BA_ "GenSigVtName" SG_ 33 v_5_SupplyOutOfRange "v_5_SupplyOutOfRange"; +BA_ "GenSigVtEn" SG_ 33 TransmitterIDFault "TransmitterIDFault"; +BA_ "GenSigVtName" SG_ 33 TransmitterIDFault "TransmitterIDFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit6 "Active_Flt_Latched_byte2_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit6 "Active_Flt_Latched_byte2_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit5 "Active_Flt_Latched_byte2_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit5 "Active_Flt_Latched_byte2_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit4 "Active_Flt_Latched_byte2_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit4 "Active_Flt_Latched_byte2_bit4"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit3 "Active_Flt_Latched_byte2_bit3"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit3 "Active_Flt_Latched_byte2_bit3"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte2_bit2 "Active_Flt_Latched_byte2_bit2"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte2_bit2 "Active_Flt_Latched_byte2_bit2"; +BA_ "GenSigVtEn" SG_ 33 PCANMissingMsgFault "PCANMissingMsgFault"; +BA_ "GenSigVtName" SG_ 33 PCANMissingMsgFault "PCANMissingMsgFault"; +BA_ "GenSigVtEn" SG_ 33 PCANBusOff "PCANBusOff"; +BA_ "GenSigVtName" SG_ 33 PCANBusOff "PCANBusOff"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit7 "Active_Flt_Latched_byte1_bit7"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit7 "Active_Flt_Latched_byte1_bit7"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit6 "Active_Flt_Latched_byte1_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit6 "Active_Flt_Latched_byte1_bit6"; +BA_ "GenSigVtEn" SG_ 33 InstructionSetCheckFault "InstructionSetCheckFault"; +BA_ "GenSigVtName" SG_ 33 InstructionSetCheckFault "InstructionSetCheckFault"; +BA_ "GenSigVtEn" SG_ 33 StackOverflowFault "StackOverflowFault"; +BA_ "GenSigVtName" SG_ 33 StackOverflowFault "StackOverflowFault"; +BA_ "GenSigVtEn" SG_ 33 WatchdogFault "WatchdogFault"; +BA_ "GenSigVtName" SG_ 33 WatchdogFault "WatchdogFault"; +BA_ "GenSigVtEn" SG_ 33 PLLLockFault "PLLLockFault"; +BA_ "GenSigVtName" SG_ 33 PLLLockFault "PLLLockFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte1_bit1 "Active_Flt_Latched_byte1_bit1"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte1_bit1 "Active_Flt_Latched_byte1_bit1"; +BA_ "GenSigVtEn" SG_ 33 RAMMemoryTestFault "RAMMemoryTestFault"; +BA_ "GenSigVtName" SG_ 33 RAMMemoryTestFault "RAMMemoryTestFault"; +BA_ "GenSigVtName" SG_ 33 USCValidationFault "USCValidationFault"; +BA_ "GenSigVtEn" SG_ 33 USCValidationFault "USCValidationFault"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit6 "Active_Flt_Latched_byte0_bit6"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit6 "Active_Flt_Latched_byte0_bit6"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit5 "Active_Flt_Latched_byte0_bit5"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit5 "Active_Flt_Latched_byte0_bit5"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit4 "Active_Flt_Latched_byte0_bit4"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit4 "Active_Flt_Latched_byte0_bit4"; +BA_ "GenSigVtEn" SG_ 33 Active_Flt_Latched_byte0_bit3 "Active_Flt_Latched_byte0_bit3"; +BA_ "GenSigVtName" SG_ 33 Active_Flt_Latched_byte0_bit3 "Active_Flt_Latched_byte0_bit3"; +BA_ "GenSigVtEn" SG_ 33 KeepAliveChecksumFault "KeepAliveChecksumFault"; +BA_ "GenSigVtName" SG_ 33 KeepAliveChecksumFault "KeepAliveChecksumFault"; +BA_ "GenSigVtEn" SG_ 33 ProgramCalibrationFlashChecksum "ProgramCalibrationFlashChecksum"; +BA_ "GenSigVtName" SG_ 33 ProgramCalibrationFlashChecksum "ProgramCalibrationFlashChecksum"; +BA_ "GenSigVtEn" SG_ 33 ApplicationFlashChecksumFault "ApplicationFlashChecksumFault"; +BA_ "GenSigVtName" SG_ 33 ApplicationFlashChecksumFault "ApplicationFlashChecksumFault"; +BA_ "GenMsgNrOfRepetition" BO_ 500 0; +BA_ "GenMsgSendType" BO_ 500 1; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte7 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte7 "MRR_xcp_daq_resp_byte7"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte6 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte6 "MRR_xcp_daq_resp_byte6"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte5 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte5 "MRR_xcp_daq_resp_byte5"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte4 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte4 "MRR_xcp_daq_resp_byte4"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte3 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte3 "MRR_xcp_daq_resp_byte3"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte2 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte2 "MRR_xcp_daq_resp_byte2"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte1 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte1 "MRR_xcp_daq_resp_byte1"; +BA_ "GenSigSendType" SG_ 500 MRR_xcp_daq_resp_byte0 0; +BA_ "GenSigCmt" SG_ 500 MRR_xcp_daq_resp_byte0 "MRR_xcp_daq_resp_byte0"; +BA_ "GenMsgNrOfRepetition" BO_ 499 0; +BA_ "GenMsgSendType" BO_ 499 1; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte7 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte7 "MRR_xcp_dto_resp_byte7"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte6 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte6 "MRR_xcp_dto_resp_byte6"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte5 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte5 "MRR_xcp_dto_resp_byte5"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte4 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte4 "MRR_xcp_dto_resp_byte4"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte3 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte3 "MRR_xcp_dto_resp_byte3"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte2 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte2 "MRR_xcp_dto_resp_byte2"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte1 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte1 "MRR_xcp_dto_resp_byte1"; +BA_ "GenSigSendType" SG_ 499 MRR_xcp_dto_resp_byte0 0; +BA_ "GenSigCmt" SG_ 499 MRR_xcp_dto_resp_byte0 "MRR_xcp_dto_resp_byte0"; +BA_ "GenMsgNrOfRepetition" BO_ 497 0; +BA_ "GenMsgSendType" BO_ 497 1; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte7 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte7 "MRR_xcp_cto_resp_byte7"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte6 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte6 "MRR_xcp_cto_resp_byte6"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte5 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte5 "MRR_xcp_cto_resp_byte5"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte4 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte4 "MRR_xcp_cto_resp_byte4"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte3 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte3 "MRR_xcp_cto_resp_byte3"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte2 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte2 "MRR_xcp_cto_resp_byte2"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte1 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte1 "MRR_xcp_cto_resp_byte1"; +BA_ "GenSigSendType" SG_ 497 MRR_xcp_cto_resp_byte0 0; +BA_ "GenSigCmt" SG_ 497 MRR_xcp_cto_resp_byte0 "MRR_xcp_cto_resp_byte0"; +BA_ "GenMsgSendType" BO_ 1900 1; +BA_ "GenMsgNrOfRepetition" BO_ 1900 0; +BA_ "DiagResponse" BO_ 1900 1; +BA_ "GenSigCmt" SG_ 1900 TesterPhysicalResCCM "TesterPhysicalResCCM"; +BA_ "GenSigSendType" SG_ 1900 TesterPhysicalResCCM 0; +BA_ "GenMsgSendType" BO_ 261 0; +BA_ "GenMsgCycleTime" BO_ 261 1000; +BA_ "GenMsgNrOfRepetition" BO_ 261 0; +BA_ "GenSigCmt" SG_ 261 CAN_SEQUENCE_NUMBER "CAN_SEQUENCE_NUMBER"; +BA_ "GenSigCmt" SG_ 261 CAN_SERIAL_NUMBER "CAN_SERIAL_NUMBER"; +BA_ "GenSigSendType" SG_ 261 CAN_SERIAL_NUMBER 0; +BA_ "GenMsgSendType" BO_ 264 1; +BA_ "GenMsgNrOfRepetition" BO_ 264 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Field_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Promote_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Field_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Promote_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_SW_Release_Revision 0; +BA_ "GenSigSendType" SG_ 264 CAN_PBL_Release_Revision 0; +BA_ "GenMsgSendType" BO_ 373 1; +BA_ "NetworkInitialization" BO_ 373 0; +BA_ "GenMsgNrOfRepetition" BO_ 373 0; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_POLARITY 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_POLARITY "CAN_SENSOR_POLARITY"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_LAT_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_LAT_OFFSET "CAN_SENSOR_LAT_OFFSET"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_LONG_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_LONG_OFFSET "CAN_SENSOR_LONG_OFFSET"; +BA_ "GenSigSendType" SG_ 373 CAN_SENSOR_HANGLE_OFFSET 0; +BA_ "GenSigCmt" SG_ 373 CAN_SENSOR_HANGLE_OFFSET "CAN_SENSOR_HANGLE_OFFSET"; +BA_ "GenSigStartValue" SG_ 373 CAN_SENSOR_HANGLE_OFFSET 0; +BA_ "GenMsgSendType" BO_ 372 1; +BA_ "NetworkInitialization" BO_ 372 0; +BA_ "GenMsgNrOfRepetition" BO_ 372 0; +BA_ "GenSigSendType" SG_ 372 CAN_SENSOR_FOV_HOR 0; +BA_ "GenSigCmt" SG_ 372 CAN_SENSOR_FOV_HOR "CAN_SENSOR_FOV_HOR"; +BA_ "GenSigStartValue" SG_ 372 CAN_SENSOR_FOV_HOR 0; +BA_ "GenSigSendType" SG_ 372 CAN_DOPPLER_COVERAGE 0; +BA_ "GenSigCmt" SG_ 372 CAN_DOPPLER_COVERAGE "CAN_DOPPLER_COVERAGE"; +BA_ "GenSigStartValue" SG_ 372 CAN_DOPPLER_COVERAGE 0; +BA_ "GenSigSendType" SG_ 372 CAN_RANGE_COVERAGE 0; +BA_ "GenSigCmt" SG_ 372 CAN_RANGE_COVERAGE "CAN_RANGE_COVERAGE"; +BA_ "GenMsgSendType" BO_ 371 1; +BA_ "NetworkInitialization" BO_ 371 0; +BA_ "GenMsgNrOfRepetition" BO_ 371 0; +BA_ "GenSigVtEn" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigVtName" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE_QF "CAN_AUTO_ALIGN_HANGLE_QF"; +BA_ "GenSigVtEn" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigVtName" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigSendType" SG_ 371 CAN_ALIGNMENT_STATUS 0; +BA_ "GenSigCmt" SG_ 371 CAN_ALIGNMENT_STATUS "CAN_ALIGNMENT_STATUS"; +BA_ "GenSigVtEn" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigVtName" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigSendType" SG_ 371 CAN_ALIGNMENT_STATE 0; +BA_ "GenSigCmt" SG_ 371 CAN_ALIGNMENT_STATE "CAN_ALIGNMENT_STATE"; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF 0; +BA_ "GenSigStartValue" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE_REF "CAN_AUTO_ALIGN_HANGLE_REF"; +BA_ "GenSigStartValue" SG_ 371 CAN_AUTO_ALIGN_HANGLE 0; +BA_ "GenSigSendType" SG_ 371 CAN_AUTO_ALIGN_HANGLE 0; +BA_ "GenSigCmt" SG_ 371 CAN_AUTO_ALIGN_HANGLE "CAN_AUTO_ALIGN_HANGLE"; +BA_ "GenMsgSendType" BO_ 369 1; +BA_ "NetworkInitialization" BO_ 369 0; +BA_ "GenMsgNrOfRepetition" BO_ 369 0; +BA_ "GenSigCmt" SG_ 369 CAN_DET_TIME_SINCE_MEAS "CAN_DET_TIME_SINCE_MEAS"; +BA_ "GenSigSendType" SG_ 369 CAN_DET_TIME_SINCE_MEAS 0; +BA_ "GenSigSendType" SG_ 369 CAN_SENSOR_TIME_STAMP 0; +BA_ "GenSigCmt" SG_ 369 CAN_SENSOR_TIME_STAMP "CAN_SENSOR_TIME_STAMP"; +BA_ "GenMsgSendType" BO_ 368 1; +BA_ "NetworkInitialization" BO_ 368 0; +BA_ "GenMsgNrOfRepetition" BO_ 368 0; +BA_ "GenSigSendType" SG_ 368 CAN_ALIGN_UPDATES_DONE 0; +BA_ "GenSigCmt" SG_ 368 CAN_ALIGN_UPDATES_DONE "CAN_ALIGN_UPDATES_DONE"; +BA_ "GenSigSendType" SG_ 368 CAN_SCAN_INDEX 0; +BA_ "GenSigCmt" SG_ 368 CAN_SCAN_INDEX "CAN_SCAN_INDEX"; +BA_ "GenSigSendType" SG_ 368 CAN_NUMBER_OF_DET 0; +BA_ "GenSigCmt" SG_ 368 CAN_NUMBER_OF_DET "CAN_NUMBER_OF_DET"; +BA_ "GenSigSendType" SG_ 368 CAN_LOOK_ID 0; +BA_ "GenSigCmt" SG_ 368 CAN_LOOK_ID "CAN_LOOK_ID"; +BA_ "GenSigSendType" SG_ 368 CAN_LOOK_INDEX 0; +BA_ "GenSigCmt" SG_ 368 CAN_LOOK_INDEX "CAN_LOOK_INDEX"; +BA_ "GenMsgSendType" BO_ 265 1; +BA_ "NetworkInitialization" BO_ 265 0; +BA_ "GenMsgNrOfRepetition" BO_ 265 0; +BA_ "GenSigCmt" SG_ 265 CAN_BATT_VOLTS "CAN_BATT_VOLTS"; +BA_ "GenSigCmt" SG_ 265 CAN_1_25_V "CAN_1_25_V"; +BA_ "GenSigCmt" SG_ 265 CAN_5_V "CAN_5_V"; +BA_ "GenSigCmt" SG_ 265 CAN_3_3_V_RAW "CAN_3_3_V_RAW"; +BA_ "GenSigCmt" SG_ 265 CAN_3_3_V_DAC "CAN_3_3_V_DAC"; +BA_ "GenSigSendType" SG_ 265 CAN_MMIC_Temp1 0; +BA_ "GenSigCmt" SG_ 265 CAN_MMIC_Temp1 "CAN_MMIC_Temp1"; +BA_ "GenSigStartValue" SG_ 265 CAN_MMIC_Temp1 0; +BA_ "GenSigSendType" SG_ 265 CAN_Processor_Thermistor 0; +BA_ "GenSigCmt" SG_ 265 CAN_Processor_Thermistor "CAN_Processor_Thermistor"; +BA_ "GenSigStartValue" SG_ 265 CAN_Processor_Thermistor 0; +BA_ "GenSigSendType" SG_ 265 CAN_Processor_Temp1 0; +BA_ "GenSigCmt" SG_ 265 CAN_Processor_Temp1 "CAN_Processor_Temp1"; +BA_ "GenSigStartValue" SG_ 265 CAN_Processor_Temp1 0; +EOF + +build_ba "04" + +cat <> ${OUT_FILENAME} +BA_ "GenMsgSendType" BO_ 351 1; +BA_ "GenMsgILSupport" BO_ 351 1; +BA_ "GenMsgNrOfRepetition" BO_ 351 0; +BA_ "GenMsgCycleTime" BO_ 351 0; +BA_ "NetworkInitialization" BO_ 351 0; +BA_ "GenMsgDelayTime" BO_ 351 0; +BA_ "GenSigVtEn" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigVtName" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_CONFID_AZIMUTH_64 "CAN_DET_CONFID_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_SUPER_RES_TARGET_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_SUPER_RES_TARGET_64 "CAN_DET_SUPER_RES_TARGET_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_ND_TARGET_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_ND_TARGET_64 "CAN_DET_ND_TARGET_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_HOST_VEH_CLUTTER_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_HOST_VEH_CLUTTER_64 "CAN_DET_HOST_VEH_CLUTTER_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_VALID_LEVEL_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_VALID_LEVEL_64 "CAN_DET_VALID_LEVEL_64"; +BA_ "GenSigStartValue" SG_ 351 CAN_DET_AZIMUTH_64 0; +BA_ "GenSigSendType" SG_ 351 CAN_DET_AZIMUTH_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_AZIMUTH_64 "CAN_DET_AZIMUTH_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_RANGE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_RANGE_64 "CAN_DET_RANGE_64"; +BA_ "GenSigStartValue" SG_ 351 CAN_DET_RANGE_RATE_64 0; +BA_ "GenSigSendType" SG_ 351 CAN_DET_RANGE_RATE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_RANGE_RATE_64 "CAN_DET_RANGE_RATE_64"; +BA_ "GenSigSendType" SG_ 351 CAN_DET_AMPLITUDE_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_DET_AMPLITUDE_64 "CAN_DET_AMPLITUDE_64"; +BA_ "GenSigSendType" SG_ 351 CAN_SCAN_INDEX_2LSB_64 0; +BA_ "GenSigCmt" SG_ 351 CAN_SCAN_INDEX_2LSB_64 "CAN_SCAN_INDEX_2LSB_64"; +BA_ "GenMsgSendType" BO_ 350 1; +BA_ "GenMsgILSupport" BO_ 350 1; +BA_ "GenMsgNrOfRepetition" BO_ 350 0; +BA_ "GenMsgCycleTime" BO_ 350 0; +BA_ "NetworkInitialization" BO_ 350 0; +BA_ "GenMsgDelayTime" BO_ 350 0; +BA_ "GenSigVtEn" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigVtName" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_CONFID_AZIMUTH_63 "CAN_DET_CONFID_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_SUPER_RES_TARGET_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_SUPER_RES_TARGET_63 "CAN_DET_SUPER_RES_TARGET_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_ND_TARGET_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_ND_TARGET_63 "CAN_DET_ND_TARGET_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_HOST_VEH_CLUTTER_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_HOST_VEH_CLUTTER_63 "CAN_DET_HOST_VEH_CLUTTER_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_VALID_LEVEL_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_VALID_LEVEL_63 "CAN_DET_VALID_LEVEL_63"; +BA_ "GenSigStartValue" SG_ 350 CAN_DET_AZIMUTH_63 0; +BA_ "GenSigSendType" SG_ 350 CAN_DET_AZIMUTH_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_AZIMUTH_63 "CAN_DET_AZIMUTH_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_RANGE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_RANGE_63 "CAN_DET_RANGE_63"; +BA_ "GenSigStartValue" SG_ 350 CAN_DET_RANGE_RATE_63 0; +BA_ "GenSigSendType" SG_ 350 CAN_DET_RANGE_RATE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_RANGE_RATE_63 "CAN_DET_RANGE_RATE_63"; +BA_ "GenSigSendType" SG_ 350 CAN_DET_AMPLITUDE_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_DET_AMPLITUDE_63 "CAN_DET_AMPLITUDE_63"; +BA_ "GenSigSendType" SG_ 350 CAN_SCAN_INDEX_2LSB_63 0; +BA_ "GenSigCmt" SG_ 350 CAN_SCAN_INDEX_2LSB_63 "CAN_SCAN_INDEX_2LSB_63"; +BA_ "GenMsgSendType" BO_ 349 1; +BA_ "GenMsgILSupport" BO_ 349 1; +BA_ "GenMsgNrOfRepetition" BO_ 349 0; +BA_ "GenMsgCycleTime" BO_ 349 0; +BA_ "NetworkInitialization" BO_ 349 0; +BA_ "GenMsgDelayTime" BO_ 349 0; +BA_ "GenSigVtEn" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigVtName" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_CONFID_AZIMUTH_62 "CAN_DET_CONFID_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_SUPER_RES_TARGET_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_SUPER_RES_TARGET_62 "CAN_DET_SUPER_RES_TARGET_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_ND_TARGET_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_ND_TARGET_62 "CAN_DET_ND_TARGET_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_HOST_VEH_CLUTTER_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_HOST_VEH_CLUTTER_62 "CAN_DET_HOST_VEH_CLUTTER_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_VALID_LEVEL_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_VALID_LEVEL_62 "CAN_DET_VALID_LEVEL_62"; +BA_ "GenSigStartValue" SG_ 349 CAN_DET_AZIMUTH_62 0; +BA_ "GenSigSendType" SG_ 349 CAN_DET_AZIMUTH_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_AZIMUTH_62 "CAN_DET_AZIMUTH_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_RANGE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_RANGE_62 "CAN_DET_RANGE_62"; +BA_ "GenSigStartValue" SG_ 349 CAN_DET_RANGE_RATE_62 0; +BA_ "GenSigSendType" SG_ 349 CAN_DET_RANGE_RATE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_RANGE_RATE_62 "CAN_DET_RANGE_RATE_62"; +BA_ "GenSigSendType" SG_ 349 CAN_DET_AMPLITUDE_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_DET_AMPLITUDE_62 "CAN_DET_AMPLITUDE_62"; +BA_ "GenSigSendType" SG_ 349 CAN_SCAN_INDEX_2LSB_62 0; +BA_ "GenSigCmt" SG_ 349 CAN_SCAN_INDEX_2LSB_62 "CAN_SCAN_INDEX_2LSB_62"; +BA_ "GenMsgSendType" BO_ 348 1; +BA_ "GenMsgILSupport" BO_ 348 1; +BA_ "GenMsgNrOfRepetition" BO_ 348 0; +BA_ "GenMsgCycleTime" BO_ 348 0; +BA_ "NetworkInitialization" BO_ 348 0; +BA_ "GenMsgDelayTime" BO_ 348 0; +BA_ "GenSigVtEn" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigVtName" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_CONFID_AZIMUTH_61 "CAN_DET_CONFID_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_SUPER_RES_TARGET_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_SUPER_RES_TARGET_61 "CAN_DET_SUPER_RES_TARGET_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_ND_TARGET_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_ND_TARGET_61 "CAN_DET_ND_TARGET_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_HOST_VEH_CLUTTER_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_HOST_VEH_CLUTTER_61 "CAN_DET_HOST_VEH_CLUTTER_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_VALID_LEVEL_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_VALID_LEVEL_61 "CAN_DET_VALID_LEVEL_61"; +BA_ "GenSigStartValue" SG_ 348 CAN_DET_AZIMUTH_61 0; +BA_ "GenSigSendType" SG_ 348 CAN_DET_AZIMUTH_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_AZIMUTH_61 "CAN_DET_AZIMUTH_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_RANGE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_RANGE_61 "CAN_DET_RANGE_61"; +BA_ "GenSigStartValue" SG_ 348 CAN_DET_RANGE_RATE_61 0; +BA_ "GenSigSendType" SG_ 348 CAN_DET_RANGE_RATE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_RANGE_RATE_61 "CAN_DET_RANGE_RATE_61"; +BA_ "GenSigSendType" SG_ 348 CAN_DET_AMPLITUDE_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_DET_AMPLITUDE_61 "CAN_DET_AMPLITUDE_61"; +BA_ "GenSigSendType" SG_ 348 CAN_SCAN_INDEX_2LSB_61 0; +BA_ "GenSigCmt" SG_ 348 CAN_SCAN_INDEX_2LSB_61 "CAN_SCAN_INDEX_2LSB_61"; +BA_ "GenMsgSendType" BO_ 347 1; +BA_ "GenMsgILSupport" BO_ 347 1; +BA_ "GenMsgNrOfRepetition" BO_ 347 0; +BA_ "GenMsgCycleTime" BO_ 347 0; +BA_ "NetworkInitialization" BO_ 347 0; +BA_ "GenMsgDelayTime" BO_ 347 0; +BA_ "GenSigVtEn" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigVtName" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_CONFID_AZIMUTH_60 "CAN_DET_CONFID_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_SUPER_RES_TARGET_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_SUPER_RES_TARGET_60 "CAN_DET_SUPER_RES_TARGET_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_ND_TARGET_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_ND_TARGET_60 "CAN_DET_ND_TARGET_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_HOST_VEH_CLUTTER_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_HOST_VEH_CLUTTER_60 "CAN_DET_HOST_VEH_CLUTTER_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_VALID_LEVEL_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_VALID_LEVEL_60 "CAN_DET_VALID_LEVEL_60"; +BA_ "GenSigStartValue" SG_ 347 CAN_DET_AZIMUTH_60 0; +BA_ "GenSigSendType" SG_ 347 CAN_DET_AZIMUTH_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_AZIMUTH_60 "CAN_DET_AZIMUTH_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_RANGE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_RANGE_60 "CAN_DET_RANGE_60"; +BA_ "GenSigStartValue" SG_ 347 CAN_DET_RANGE_RATE_60 0; +BA_ "GenSigSendType" SG_ 347 CAN_DET_RANGE_RATE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_RANGE_RATE_60 "CAN_DET_RANGE_RATE_60"; +BA_ "GenSigSendType" SG_ 347 CAN_DET_AMPLITUDE_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_DET_AMPLITUDE_60 "CAN_DET_AMPLITUDE_60"; +BA_ "GenSigSendType" SG_ 347 CAN_SCAN_INDEX_2LSB_60 0; +BA_ "GenSigCmt" SG_ 347 CAN_SCAN_INDEX_2LSB_60 "CAN_SCAN_INDEX_2LSB_60"; +BA_ "GenMsgSendType" BO_ 346 1; +BA_ "GenMsgILSupport" BO_ 346 1; +BA_ "GenMsgNrOfRepetition" BO_ 346 0; +BA_ "GenMsgCycleTime" BO_ 346 0; +BA_ "NetworkInitialization" BO_ 346 0; +BA_ "GenMsgDelayTime" BO_ 346 0; +BA_ "GenSigVtEn" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigVtName" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_CONFID_AZIMUTH_59 "CAN_DET_CONFID_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_SUPER_RES_TARGET_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_SUPER_RES_TARGET_59 "CAN_DET_SUPER_RES_TARGET_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_ND_TARGET_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_ND_TARGET_59 "CAN_DET_ND_TARGET_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_HOST_VEH_CLUTTER_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_HOST_VEH_CLUTTER_59 "CAN_DET_HOST_VEH_CLUTTER_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_VALID_LEVEL_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_VALID_LEVEL_59 "CAN_DET_VALID_LEVEL_59"; +BA_ "GenSigStartValue" SG_ 346 CAN_DET_AZIMUTH_59 0; +BA_ "GenSigSendType" SG_ 346 CAN_DET_AZIMUTH_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_AZIMUTH_59 "CAN_DET_AZIMUTH_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_RANGE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_RANGE_59 "CAN_DET_RANGE_59"; +BA_ "GenSigStartValue" SG_ 346 CAN_DET_RANGE_RATE_59 0; +BA_ "GenSigSendType" SG_ 346 CAN_DET_RANGE_RATE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_RANGE_RATE_59 "CAN_DET_RANGE_RATE_59"; +BA_ "GenSigSendType" SG_ 346 CAN_DET_AMPLITUDE_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_DET_AMPLITUDE_59 "CAN_DET_AMPLITUDE_59"; +BA_ "GenSigSendType" SG_ 346 CAN_SCAN_INDEX_2LSB_59 0; +BA_ "GenSigCmt" SG_ 346 CAN_SCAN_INDEX_2LSB_59 "CAN_SCAN_INDEX_2LSB_59"; +BA_ "GenMsgSendType" BO_ 345 1; +BA_ "GenMsgILSupport" BO_ 345 1; +BA_ "GenMsgNrOfRepetition" BO_ 345 0; +BA_ "GenMsgCycleTime" BO_ 345 0; +BA_ "NetworkInitialization" BO_ 345 0; +BA_ "GenMsgDelayTime" BO_ 345 0; +BA_ "GenSigVtEn" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigVtName" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_CONFID_AZIMUTH_58 "CAN_DET_CONFID_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_SUPER_RES_TARGET_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_SUPER_RES_TARGET_58 "CAN_DET_SUPER_RES_TARGET_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_ND_TARGET_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_ND_TARGET_58 "CAN_DET_ND_TARGET_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_HOST_VEH_CLUTTER_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_HOST_VEH_CLUTTER_58 "CAN_DET_HOST_VEH_CLUTTER_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_VALID_LEVEL_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_VALID_LEVEL_58 "CAN_DET_VALID_LEVEL_58"; +BA_ "GenSigStartValue" SG_ 345 CAN_DET_AZIMUTH_58 0; +BA_ "GenSigSendType" SG_ 345 CAN_DET_AZIMUTH_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_AZIMUTH_58 "CAN_DET_AZIMUTH_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_RANGE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_RANGE_58 "CAN_DET_RANGE_58"; +BA_ "GenSigStartValue" SG_ 345 CAN_DET_RANGE_RATE_58 0; +BA_ "GenSigSendType" SG_ 345 CAN_DET_RANGE_RATE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_RANGE_RATE_58 "CAN_DET_RANGE_RATE_58"; +BA_ "GenSigSendType" SG_ 345 CAN_DET_AMPLITUDE_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_DET_AMPLITUDE_58 "CAN_DET_AMPLITUDE_58"; +BA_ "GenSigSendType" SG_ 345 CAN_SCAN_INDEX_2LSB_58 0; +BA_ "GenSigCmt" SG_ 345 CAN_SCAN_INDEX_2LSB_58 "CAN_SCAN_INDEX_2LSB_58"; +BA_ "GenMsgSendType" BO_ 344 1; +BA_ "GenMsgILSupport" BO_ 344 1; +BA_ "GenMsgNrOfRepetition" BO_ 344 0; +BA_ "GenMsgCycleTime" BO_ 344 0; +BA_ "NetworkInitialization" BO_ 344 0; +BA_ "GenMsgDelayTime" BO_ 344 0; +BA_ "GenSigVtEn" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigVtName" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_CONFID_AZIMUTH_57 "CAN_DET_CONFID_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_SUPER_RES_TARGET_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_SUPER_RES_TARGET_57 "CAN_DET_SUPER_RES_TARGET_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_ND_TARGET_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_ND_TARGET_57 "CAN_DET_ND_TARGET_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_HOST_VEH_CLUTTER_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_HOST_VEH_CLUTTER_57 "CAN_DET_HOST_VEH_CLUTTER_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_VALID_LEVEL_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_VALID_LEVEL_57 "CAN_DET_VALID_LEVEL_57"; +BA_ "GenSigStartValue" SG_ 344 CAN_DET_AZIMUTH_57 0; +BA_ "GenSigSendType" SG_ 344 CAN_DET_AZIMUTH_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_AZIMUTH_57 "CAN_DET_AZIMUTH_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_RANGE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_RANGE_57 "CAN_DET_RANGE_57"; +BA_ "GenSigStartValue" SG_ 344 CAN_DET_RANGE_RATE_57 0; +BA_ "GenSigSendType" SG_ 344 CAN_DET_RANGE_RATE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_RANGE_RATE_57 "CAN_DET_RANGE_RATE_57"; +BA_ "GenSigSendType" SG_ 344 CAN_DET_AMPLITUDE_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_DET_AMPLITUDE_57 "CAN_DET_AMPLITUDE_57"; +BA_ "GenSigSendType" SG_ 344 CAN_SCAN_INDEX_2LSB_57 0; +BA_ "GenSigCmt" SG_ 344 CAN_SCAN_INDEX_2LSB_57 "CAN_SCAN_INDEX_2LSB_57"; +BA_ "GenMsgSendType" BO_ 343 1; +BA_ "GenMsgILSupport" BO_ 343 1; +BA_ "GenMsgNrOfRepetition" BO_ 343 0; +BA_ "GenMsgCycleTime" BO_ 343 0; +BA_ "NetworkInitialization" BO_ 343 0; +BA_ "GenMsgDelayTime" BO_ 343 0; +BA_ "GenSigVtEn" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigVtName" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_CONFID_AZIMUTH_56 "CAN_DET_CONFID_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_SUPER_RES_TARGET_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_SUPER_RES_TARGET_56 "CAN_DET_SUPER_RES_TARGET_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_ND_TARGET_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_ND_TARGET_56 "CAN_DET_ND_TARGET_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_HOST_VEH_CLUTTER_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_HOST_VEH_CLUTTER_56 "CAN_DET_HOST_VEH_CLUTTER_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_VALID_LEVEL_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_VALID_LEVEL_56 "CAN_DET_VALID_LEVEL_56"; +BA_ "GenSigStartValue" SG_ 343 CAN_DET_AZIMUTH_56 0; +BA_ "GenSigSendType" SG_ 343 CAN_DET_AZIMUTH_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_AZIMUTH_56 "CAN_DET_AZIMUTH_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_RANGE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_RANGE_56 "CAN_DET_RANGE_56"; +BA_ "GenSigStartValue" SG_ 343 CAN_DET_RANGE_RATE_56 0; +BA_ "GenSigSendType" SG_ 343 CAN_DET_RANGE_RATE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_RANGE_RATE_56 "CAN_DET_RANGE_RATE_56"; +BA_ "GenSigSendType" SG_ 343 CAN_DET_AMPLITUDE_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_DET_AMPLITUDE_56 "CAN_DET_AMPLITUDE_56"; +BA_ "GenSigSendType" SG_ 343 CAN_SCAN_INDEX_2LSB_56 0; +BA_ "GenSigCmt" SG_ 343 CAN_SCAN_INDEX_2LSB_56 "CAN_SCAN_INDEX_2LSB_56"; +BA_ "GenMsgSendType" BO_ 342 1; +BA_ "GenMsgILSupport" BO_ 342 1; +BA_ "GenMsgNrOfRepetition" BO_ 342 0; +BA_ "GenMsgCycleTime" BO_ 342 0; +BA_ "NetworkInitialization" BO_ 342 0; +BA_ "GenMsgDelayTime" BO_ 342 0; +BA_ "GenSigVtEn" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigVtName" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_CONFID_AZIMUTH_55 "CAN_DET_CONFID_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_SUPER_RES_TARGET_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_SUPER_RES_TARGET_55 "CAN_DET_SUPER_RES_TARGET_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_ND_TARGET_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_ND_TARGET_55 "CAN_DET_ND_TARGET_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_HOST_VEH_CLUTTER_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_HOST_VEH_CLUTTER_55 "CAN_DET_HOST_VEH_CLUTTER_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_VALID_LEVEL_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_VALID_LEVEL_55 "CAN_DET_VALID_LEVEL_55"; +BA_ "GenSigStartValue" SG_ 342 CAN_DET_AZIMUTH_55 0; +BA_ "GenSigSendType" SG_ 342 CAN_DET_AZIMUTH_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_AZIMUTH_55 "CAN_DET_AZIMUTH_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_RANGE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_RANGE_55 "CAN_DET_RANGE_55"; +BA_ "GenSigStartValue" SG_ 342 CAN_DET_RANGE_RATE_55 0; +BA_ "GenSigSendType" SG_ 342 CAN_DET_RANGE_RATE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_RANGE_RATE_55 "CAN_DET_RANGE_RATE_55"; +BA_ "GenSigSendType" SG_ 342 CAN_DET_AMPLITUDE_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_DET_AMPLITUDE_55 "CAN_DET_AMPLITUDE_55"; +BA_ "GenSigSendType" SG_ 342 CAN_SCAN_INDEX_2LSB_55 0; +BA_ "GenSigCmt" SG_ 342 CAN_SCAN_INDEX_2LSB_55 "CAN_SCAN_INDEX_2LSB_55"; +BA_ "GenMsgSendType" BO_ 335 1; +BA_ "GenMsgILSupport" BO_ 335 1; +BA_ "GenMsgNrOfRepetition" BO_ 335 0; +BA_ "GenMsgCycleTime" BO_ 335 0; +BA_ "NetworkInitialization" BO_ 335 0; +BA_ "GenMsgDelayTime" BO_ 335 0; +BA_ "GenSigVtEn" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigVtName" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_CONFID_AZIMUTH_48 "CAN_DET_CONFID_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_SUPER_RES_TARGET_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_SUPER_RES_TARGET_48 "CAN_DET_SUPER_RES_TARGET_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_ND_TARGET_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_ND_TARGET_48 "CAN_DET_ND_TARGET_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_HOST_VEH_CLUTTER_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_HOST_VEH_CLUTTER_48 "CAN_DET_HOST_VEH_CLUTTER_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_VALID_LEVEL_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_VALID_LEVEL_48 "CAN_DET_VALID_LEVEL_48"; +BA_ "GenSigStartValue" SG_ 335 CAN_DET_AZIMUTH_48 0; +BA_ "GenSigSendType" SG_ 335 CAN_DET_AZIMUTH_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_AZIMUTH_48 "CAN_DET_AZIMUTH_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_RANGE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_RANGE_48 "CAN_DET_RANGE_48"; +BA_ "GenSigStartValue" SG_ 335 CAN_DET_RANGE_RATE_48 0; +BA_ "GenSigSendType" SG_ 335 CAN_DET_RANGE_RATE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_RANGE_RATE_48 "CAN_DET_RANGE_RATE_48"; +BA_ "GenSigSendType" SG_ 335 CAN_DET_AMPLITUDE_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_DET_AMPLITUDE_48 "CAN_DET_AMPLITUDE_48"; +BA_ "GenSigSendType" SG_ 335 CAN_SCAN_INDEX_2LSB_48 0; +BA_ "GenSigCmt" SG_ 335 CAN_SCAN_INDEX_2LSB_48 "CAN_SCAN_INDEX_2LSB_48"; +BA_ "GenMsgSendType" BO_ 334 1; +BA_ "GenMsgILSupport" BO_ 334 1; +BA_ "GenMsgNrOfRepetition" BO_ 334 0; +BA_ "GenMsgCycleTime" BO_ 334 0; +BA_ "NetworkInitialization" BO_ 334 0; +BA_ "GenMsgDelayTime" BO_ 334 0; +BA_ "GenSigVtEn" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigVtName" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_CONFID_AZIMUTH_47 "CAN_DET_CONFID_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_SUPER_RES_TARGET_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_SUPER_RES_TARGET_47 "CAN_DET_SUPER_RES_TARGET_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_ND_TARGET_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_ND_TARGET_47 "CAN_DET_ND_TARGET_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_HOST_VEH_CLUTTER_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_HOST_VEH_CLUTTER_47 "CAN_DET_HOST_VEH_CLUTTER_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_VALID_LEVEL_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_VALID_LEVEL_47 "CAN_DET_VALID_LEVEL_47"; +BA_ "GenSigStartValue" SG_ 334 CAN_DET_AZIMUTH_47 0; +BA_ "GenSigSendType" SG_ 334 CAN_DET_AZIMUTH_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_AZIMUTH_47 "CAN_DET_AZIMUTH_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_RANGE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_RANGE_47 "CAN_DET_RANGE_47"; +BA_ "GenSigStartValue" SG_ 334 CAN_DET_RANGE_RATE_47 0; +BA_ "GenSigSendType" SG_ 334 CAN_DET_RANGE_RATE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_RANGE_RATE_47 "CAN_DET_RANGE_RATE_47"; +BA_ "GenSigSendType" SG_ 334 CAN_DET_AMPLITUDE_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_DET_AMPLITUDE_47 "CAN_DET_AMPLITUDE_47"; +BA_ "GenSigSendType" SG_ 334 CAN_SCAN_INDEX_2LSB_47 0; +BA_ "GenSigCmt" SG_ 334 CAN_SCAN_INDEX_2LSB_47 "CAN_SCAN_INDEX_2LSB_47"; +BA_ "GenMsgSendType" BO_ 333 1; +BA_ "GenMsgILSupport" BO_ 333 1; +BA_ "GenMsgNrOfRepetition" BO_ 333 0; +BA_ "GenMsgCycleTime" BO_ 333 0; +BA_ "NetworkInitialization" BO_ 333 0; +BA_ "GenMsgDelayTime" BO_ 333 0; +BA_ "GenSigVtEn" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigVtName" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_CONFID_AZIMUTH_46 "CAN_DET_CONFID_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_SUPER_RES_TARGET_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_SUPER_RES_TARGET_46 "CAN_DET_SUPER_RES_TARGET_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_ND_TARGET_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_ND_TARGET_46 "CAN_DET_ND_TARGET_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_HOST_VEH_CLUTTER_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_HOST_VEH_CLUTTER_46 "CAN_DET_HOST_VEH_CLUTTER_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_VALID_LEVEL_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_VALID_LEVEL_46 "CAN_DET_VALID_LEVEL_46"; +BA_ "GenSigStartValue" SG_ 333 CAN_DET_AZIMUTH_46 0; +BA_ "GenSigSendType" SG_ 333 CAN_DET_AZIMUTH_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_AZIMUTH_46 "CAN_DET_AZIMUTH_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_RANGE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_RANGE_46 "CAN_DET_RANGE_46"; +BA_ "GenSigStartValue" SG_ 333 CAN_DET_RANGE_RATE_46 0; +BA_ "GenSigSendType" SG_ 333 CAN_DET_RANGE_RATE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_RANGE_RATE_46 "CAN_DET_RANGE_RATE_46"; +BA_ "GenSigSendType" SG_ 333 CAN_DET_AMPLITUDE_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_DET_AMPLITUDE_46 "CAN_DET_AMPLITUDE_46"; +BA_ "GenSigSendType" SG_ 333 CAN_SCAN_INDEX_2LSB_46 0; +BA_ "GenSigCmt" SG_ 333 CAN_SCAN_INDEX_2LSB_46 "CAN_SCAN_INDEX_2LSB_46"; +BA_ "GenMsgSendType" BO_ 332 1; +BA_ "GenMsgILSupport" BO_ 332 1; +BA_ "GenMsgNrOfRepetition" BO_ 332 0; +BA_ "GenMsgCycleTime" BO_ 332 0; +BA_ "NetworkInitialization" BO_ 332 0; +BA_ "GenMsgDelayTime" BO_ 332 0; +BA_ "GenSigVtEn" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigVtName" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_CONFID_AZIMUTH_45 "CAN_DET_CONFID_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_SUPER_RES_TARGET_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_SUPER_RES_TARGET_45 "CAN_DET_SUPER_RES_TARGET_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_ND_TARGET_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_ND_TARGET_45 "CAN_DET_ND_TARGET_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_HOST_VEH_CLUTTER_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_HOST_VEH_CLUTTER_45 "CAN_DET_HOST_VEH_CLUTTER_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_VALID_LEVEL_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_VALID_LEVEL_45 "CAN_DET_VALID_LEVEL_45"; +BA_ "GenSigStartValue" SG_ 332 CAN_DET_AZIMUTH_45 0; +BA_ "GenSigSendType" SG_ 332 CAN_DET_AZIMUTH_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_AZIMUTH_45 "CAN_DET_AZIMUTH_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_RANGE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_RANGE_45 "CAN_DET_RANGE_45"; +BA_ "GenSigStartValue" SG_ 332 CAN_DET_RANGE_RATE_45 0; +BA_ "GenSigSendType" SG_ 332 CAN_DET_RANGE_RATE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_RANGE_RATE_45 "CAN_DET_RANGE_RATE_45"; +BA_ "GenSigSendType" SG_ 332 CAN_DET_AMPLITUDE_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_DET_AMPLITUDE_45 "CAN_DET_AMPLITUDE_45"; +BA_ "GenSigSendType" SG_ 332 CAN_SCAN_INDEX_2LSB_45 0; +BA_ "GenSigCmt" SG_ 332 CAN_SCAN_INDEX_2LSB_45 "CAN_SCAN_INDEX_2LSB_45"; +BA_ "GenMsgSendType" BO_ 331 1; +BA_ "GenMsgILSupport" BO_ 331 1; +BA_ "GenMsgNrOfRepetition" BO_ 331 0; +BA_ "GenMsgCycleTime" BO_ 331 0; +BA_ "NetworkInitialization" BO_ 331 0; +BA_ "GenMsgDelayTime" BO_ 331 0; +BA_ "GenSigVtEn" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigVtName" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_CONFID_AZIMUTH_44 "CAN_DET_CONFID_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_SUPER_RES_TARGET_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_SUPER_RES_TARGET_44 "CAN_DET_SUPER_RES_TARGET_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_ND_TARGET_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_ND_TARGET_44 "CAN_DET_ND_TARGET_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_HOST_VEH_CLUTTER_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_HOST_VEH_CLUTTER_44 "CAN_DET_HOST_VEH_CLUTTER_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_VALID_LEVEL_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_VALID_LEVEL_44 "CAN_DET_VALID_LEVEL_44"; +BA_ "GenSigStartValue" SG_ 331 CAN_DET_AZIMUTH_44 0; +BA_ "GenSigSendType" SG_ 331 CAN_DET_AZIMUTH_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_AZIMUTH_44 "CAN_DET_AZIMUTH_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_RANGE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_RANGE_44 "CAN_DET_RANGE_44"; +BA_ "GenSigStartValue" SG_ 331 CAN_DET_RANGE_RATE_44 0; +BA_ "GenSigSendType" SG_ 331 CAN_DET_RANGE_RATE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_RANGE_RATE_44 "CAN_DET_RANGE_RATE_44"; +BA_ "GenSigSendType" SG_ 331 CAN_DET_AMPLITUDE_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_DET_AMPLITUDE_44 "CAN_DET_AMPLITUDE_44"; +BA_ "GenSigSendType" SG_ 331 CAN_SCAN_INDEX_2LSB_44 0; +BA_ "GenSigCmt" SG_ 331 CAN_SCAN_INDEX_2LSB_44 "CAN_SCAN_INDEX_2LSB_44"; +BA_ "GenMsgSendType" BO_ 330 1; +BA_ "GenMsgILSupport" BO_ 330 1; +BA_ "GenMsgNrOfRepetition" BO_ 330 0; +BA_ "GenMsgCycleTime" BO_ 330 0; +BA_ "NetworkInitialization" BO_ 330 0; +BA_ "GenMsgDelayTime" BO_ 330 0; +BA_ "GenSigVtEn" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigVtName" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_CONFID_AZIMUTH_43 "CAN_DET_CONFID_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_SUPER_RES_TARGET_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_SUPER_RES_TARGET_43 "CAN_DET_SUPER_RES_TARGET_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_ND_TARGET_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_ND_TARGET_43 "CAN_DET_ND_TARGET_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_HOST_VEH_CLUTTER_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_HOST_VEH_CLUTTER_43 "CAN_DET_HOST_VEH_CLUTTER_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_VALID_LEVEL_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_VALID_LEVEL_43 "CAN_DET_VALID_LEVEL_43"; +BA_ "GenSigStartValue" SG_ 330 CAN_DET_AZIMUTH_43 0; +BA_ "GenSigSendType" SG_ 330 CAN_DET_AZIMUTH_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_AZIMUTH_43 "CAN_DET_AZIMUTH_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_RANGE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_RANGE_43 "CAN_DET_RANGE_43"; +BA_ "GenSigStartValue" SG_ 330 CAN_DET_RANGE_RATE_43 0; +BA_ "GenSigSendType" SG_ 330 CAN_DET_RANGE_RATE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_RANGE_RATE_43 "CAN_DET_RANGE_RATE_43"; +BA_ "GenSigSendType" SG_ 330 CAN_DET_AMPLITUDE_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_DET_AMPLITUDE_43 "CAN_DET_AMPLITUDE_43"; +BA_ "GenSigSendType" SG_ 330 CAN_SCAN_INDEX_2LSB_43 0; +BA_ "GenSigCmt" SG_ 330 CAN_SCAN_INDEX_2LSB_43 "CAN_SCAN_INDEX_2LSB_43"; +BA_ "GenMsgSendType" BO_ 329 1; +BA_ "GenMsgILSupport" BO_ 329 1; +BA_ "GenMsgNrOfRepetition" BO_ 329 0; +BA_ "GenMsgCycleTime" BO_ 329 0; +BA_ "NetworkInitialization" BO_ 329 0; +BA_ "GenMsgDelayTime" BO_ 329 0; +BA_ "GenSigVtEn" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigVtName" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_CONFID_AZIMUTH_42 "CAN_DET_CONFID_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_SUPER_RES_TARGET_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_SUPER_RES_TARGET_42 "CAN_DET_SUPER_RES_TARGET_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_ND_TARGET_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_ND_TARGET_42 "CAN_DET_ND_TARGET_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_HOST_VEH_CLUTTER_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_HOST_VEH_CLUTTER_42 "CAN_DET_HOST_VEH_CLUTTER_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_VALID_LEVEL_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_VALID_LEVEL_42 "CAN_DET_VALID_LEVEL_42"; +BA_ "GenSigStartValue" SG_ 329 CAN_DET_AZIMUTH_42 0; +BA_ "GenSigSendType" SG_ 329 CAN_DET_AZIMUTH_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_AZIMUTH_42 "CAN_DET_AZIMUTH_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_RANGE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_RANGE_42 "CAN_DET_RANGE_42"; +BA_ "GenSigStartValue" SG_ 329 CAN_DET_RANGE_RATE_42 0; +BA_ "GenSigSendType" SG_ 329 CAN_DET_RANGE_RATE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_RANGE_RATE_42 "CAN_DET_RANGE_RATE_42"; +BA_ "GenSigSendType" SG_ 329 CAN_DET_AMPLITUDE_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_DET_AMPLITUDE_42 "CAN_DET_AMPLITUDE_42"; +BA_ "GenSigSendType" SG_ 329 CAN_SCAN_INDEX_2LSB_42 0; +BA_ "GenSigCmt" SG_ 329 CAN_SCAN_INDEX_2LSB_42 "CAN_SCAN_INDEX_2LSB_42"; +BA_ "GenMsgSendType" BO_ 328 1; +BA_ "GenMsgILSupport" BO_ 328 1; +BA_ "GenMsgNrOfRepetition" BO_ 328 0; +BA_ "GenMsgCycleTime" BO_ 328 0; +BA_ "NetworkInitialization" BO_ 328 0; +BA_ "GenMsgDelayTime" BO_ 328 0; +BA_ "GenSigVtEn" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigVtName" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_CONFID_AZIMUTH_41 "CAN_DET_CONFID_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_SUPER_RES_TARGET_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_SUPER_RES_TARGET_41 "CAN_DET_SUPER_RES_TARGET_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_ND_TARGET_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_ND_TARGET_41 "CAN_DET_ND_TARGET_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_HOST_VEH_CLUTTER_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_HOST_VEH_CLUTTER_41 "CAN_DET_HOST_VEH_CLUTTER_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_VALID_LEVEL_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_VALID_LEVEL_41 "CAN_DET_VALID_LEVEL_41"; +BA_ "GenSigStartValue" SG_ 328 CAN_DET_AZIMUTH_41 0; +BA_ "GenSigSendType" SG_ 328 CAN_DET_AZIMUTH_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_AZIMUTH_41 "CAN_DET_AZIMUTH_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_RANGE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_RANGE_41 "CAN_DET_RANGE_41"; +BA_ "GenSigStartValue" SG_ 328 CAN_DET_RANGE_RATE_41 0; +BA_ "GenSigSendType" SG_ 328 CAN_DET_RANGE_RATE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_RANGE_RATE_41 "CAN_DET_RANGE_RATE_41"; +BA_ "GenSigSendType" SG_ 328 CAN_DET_AMPLITUDE_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_DET_AMPLITUDE_41 "CAN_DET_AMPLITUDE_41"; +BA_ "GenSigSendType" SG_ 328 CAN_SCAN_INDEX_2LSB_41 0; +BA_ "GenSigCmt" SG_ 328 CAN_SCAN_INDEX_2LSB_41 "CAN_SCAN_INDEX_2LSB_41"; +BA_ "GenMsgSendType" BO_ 327 1; +BA_ "GenMsgILSupport" BO_ 327 1; +BA_ "GenMsgNrOfRepetition" BO_ 327 0; +BA_ "GenMsgCycleTime" BO_ 327 0; +BA_ "NetworkInitialization" BO_ 327 0; +BA_ "GenMsgDelayTime" BO_ 327 0; +BA_ "GenSigVtEn" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigVtName" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_CONFID_AZIMUTH_40 "CAN_DET_CONFID_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_SUPER_RES_TARGET_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_SUPER_RES_TARGET_40 "CAN_DET_SUPER_RES_TARGET_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_ND_TARGET_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_ND_TARGET_40 "CAN_DET_ND_TARGET_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_HOST_VEH_CLUTTER_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_HOST_VEH_CLUTTER_40 "CAN_DET_HOST_VEH_CLUTTER_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_VALID_LEVEL_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_VALID_LEVEL_40 "CAN_DET_VALID_LEVEL_40"; +BA_ "GenSigStartValue" SG_ 327 CAN_DET_AZIMUTH_40 0; +BA_ "GenSigSendType" SG_ 327 CAN_DET_AZIMUTH_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_AZIMUTH_40 "CAN_DET_AZIMUTH_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_RANGE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_RANGE_40 "CAN_DET_RANGE_40"; +BA_ "GenSigStartValue" SG_ 327 CAN_DET_RANGE_RATE_40 0; +BA_ "GenSigSendType" SG_ 327 CAN_DET_RANGE_RATE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_RANGE_RATE_40 "CAN_DET_RANGE_RATE_40"; +BA_ "GenSigSendType" SG_ 327 CAN_DET_AMPLITUDE_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_DET_AMPLITUDE_40 "CAN_DET_AMPLITUDE_40"; +BA_ "GenSigSendType" SG_ 327 CAN_SCAN_INDEX_2LSB_40 0; +BA_ "GenSigCmt" SG_ 327 CAN_SCAN_INDEX_2LSB_40 "CAN_SCAN_INDEX_2LSB_40"; +BA_ "GenMsgSendType" BO_ 325 1; +BA_ "GenMsgILSupport" BO_ 325 1; +BA_ "GenMsgNrOfRepetition" BO_ 325 0; +BA_ "GenMsgCycleTime" BO_ 325 0; +BA_ "NetworkInitialization" BO_ 325 0; +BA_ "GenMsgDelayTime" BO_ 325 0; +BA_ "GenSigVtEn" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigVtName" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_CONFID_AZIMUTH_38 "CAN_DET_CONFID_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_SUPER_RES_TARGET_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_SUPER_RES_TARGET_38 "CAN_DET_SUPER_RES_TARGET_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_ND_TARGET_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_ND_TARGET_38 "CAN_DET_ND_TARGET_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_HOST_VEH_CLUTTER_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_HOST_VEH_CLUTTER_38 "CAN_DET_HOST_VEH_CLUTTER_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_VALID_LEVEL_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_VALID_LEVEL_38 "CAN_DET_VALID_LEVEL_38"; +BA_ "GenSigStartValue" SG_ 325 CAN_DET_AZIMUTH_38 0; +BA_ "GenSigSendType" SG_ 325 CAN_DET_AZIMUTH_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_AZIMUTH_38 "CAN_DET_AZIMUTH_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_RANGE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_RANGE_38 "CAN_DET_RANGE_38"; +BA_ "GenSigStartValue" SG_ 325 CAN_DET_RANGE_RATE_38 0; +BA_ "GenSigSendType" SG_ 325 CAN_DET_RANGE_RATE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_RANGE_RATE_38 "CAN_DET_RANGE_RATE_38"; +BA_ "GenSigSendType" SG_ 325 CAN_DET_AMPLITUDE_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_DET_AMPLITUDE_38 "CAN_DET_AMPLITUDE_38"; +BA_ "GenSigSendType" SG_ 325 CAN_SCAN_INDEX_2LSB_38 0; +BA_ "GenSigCmt" SG_ 325 CAN_SCAN_INDEX_2LSB_38 "CAN_SCAN_INDEX_2LSB_38"; +BA_ "GenMsgSendType" BO_ 324 1; +BA_ "GenMsgILSupport" BO_ 324 1; +BA_ "GenMsgNrOfRepetition" BO_ 324 0; +BA_ "GenMsgCycleTime" BO_ 324 0; +BA_ "NetworkInitialization" BO_ 324 0; +BA_ "GenMsgDelayTime" BO_ 324 0; +BA_ "GenSigVtEn" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigVtName" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_CONFID_AZIMUTH_37 "CAN_DET_CONFID_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_SUPER_RES_TARGET_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_SUPER_RES_TARGET_37 "CAN_DET_SUPER_RES_TARGET_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_ND_TARGET_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_ND_TARGET_37 "CAN_DET_ND_TARGET_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_HOST_VEH_CLUTTER_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_HOST_VEH_CLUTTER_37 "CAN_DET_HOST_VEH_CLUTTER_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_VALID_LEVEL_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_VALID_LEVEL_37 "CAN_DET_VALID_LEVEL_37"; +BA_ "GenSigStartValue" SG_ 324 CAN_DET_AZIMUTH_37 0; +BA_ "GenSigSendType" SG_ 324 CAN_DET_AZIMUTH_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_AZIMUTH_37 "CAN_DET_AZIMUTH_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_RANGE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_RANGE_37 "CAN_DET_RANGE_37"; +BA_ "GenSigStartValue" SG_ 324 CAN_DET_RANGE_RATE_37 0; +BA_ "GenSigSendType" SG_ 324 CAN_DET_RANGE_RATE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_RANGE_RATE_37 "CAN_DET_RANGE_RATE_37"; +BA_ "GenSigSendType" SG_ 324 CAN_DET_AMPLITUDE_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_DET_AMPLITUDE_37 "CAN_DET_AMPLITUDE_37"; +BA_ "GenSigSendType" SG_ 324 CAN_SCAN_INDEX_2LSB_37 0; +BA_ "GenSigCmt" SG_ 324 CAN_SCAN_INDEX_2LSB_37 "CAN_SCAN_INDEX_2LSB_37"; +BA_ "GenMsgSendType" BO_ 323 1; +BA_ "GenMsgILSupport" BO_ 323 1; +BA_ "GenMsgNrOfRepetition" BO_ 323 0; +BA_ "GenMsgCycleTime" BO_ 323 0; +BA_ "NetworkInitialization" BO_ 323 0; +BA_ "GenMsgDelayTime" BO_ 323 0; +BA_ "GenSigVtEn" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigVtName" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_CONFID_AZIMUTH_36 "CAN_DET_CONFID_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_SUPER_RES_TARGET_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_SUPER_RES_TARGET_36 "CAN_DET_SUPER_RES_TARGET_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_ND_TARGET_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_ND_TARGET_36 "CAN_DET_ND_TARGET_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_HOST_VEH_CLUTTER_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_HOST_VEH_CLUTTER_36 "CAN_DET_HOST_VEH_CLUTTER_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_VALID_LEVEL_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_VALID_LEVEL_36 "CAN_DET_VALID_LEVEL_36"; +BA_ "GenSigStartValue" SG_ 323 CAN_DET_AZIMUTH_36 0; +BA_ "GenSigSendType" SG_ 323 CAN_DET_AZIMUTH_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_AZIMUTH_36 "CAN_DET_AZIMUTH_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_RANGE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_RANGE_36 "CAN_DET_RANGE_36"; +BA_ "GenSigStartValue" SG_ 323 CAN_DET_RANGE_RATE_36 0; +BA_ "GenSigSendType" SG_ 323 CAN_DET_RANGE_RATE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_RANGE_RATE_36 "CAN_DET_RANGE_RATE_36"; +BA_ "GenSigSendType" SG_ 323 CAN_DET_AMPLITUDE_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_DET_AMPLITUDE_36 "CAN_DET_AMPLITUDE_36"; +BA_ "GenSigSendType" SG_ 323 CAN_SCAN_INDEX_2LSB_36 0; +BA_ "GenSigCmt" SG_ 323 CAN_SCAN_INDEX_2LSB_36 "CAN_SCAN_INDEX_2LSB_36"; +BA_ "GenMsgSendType" BO_ 322 1; +BA_ "GenMsgILSupport" BO_ 322 1; +BA_ "GenMsgNrOfRepetition" BO_ 322 0; +BA_ "GenMsgCycleTime" BO_ 322 0; +BA_ "NetworkInitialization" BO_ 322 0; +BA_ "GenMsgDelayTime" BO_ 322 0; +BA_ "GenSigVtEn" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigVtName" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_CONFID_AZIMUTH_35 "CAN_DET_CONFID_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_SUPER_RES_TARGET_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_SUPER_RES_TARGET_35 "CAN_DET_SUPER_RES_TARGET_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_ND_TARGET_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_ND_TARGET_35 "CAN_DET_ND_TARGET_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_HOST_VEH_CLUTTER_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_HOST_VEH_CLUTTER_35 "CAN_DET_HOST_VEH_CLUTTER_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_VALID_LEVEL_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_VALID_LEVEL_35 "CAN_DET_VALID_LEVEL_35"; +BA_ "GenSigStartValue" SG_ 322 CAN_DET_AZIMUTH_35 0; +BA_ "GenSigSendType" SG_ 322 CAN_DET_AZIMUTH_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_AZIMUTH_35 "CAN_DET_AZIMUTH_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_RANGE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_RANGE_35 "CAN_DET_RANGE_35"; +BA_ "GenSigStartValue" SG_ 322 CAN_DET_RANGE_RATE_35 0; +BA_ "GenSigSendType" SG_ 322 CAN_DET_RANGE_RATE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_RANGE_RATE_35 "CAN_DET_RANGE_RATE_35"; +BA_ "GenSigSendType" SG_ 322 CAN_DET_AMPLITUDE_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_DET_AMPLITUDE_35 "CAN_DET_AMPLITUDE_35"; +BA_ "GenSigSendType" SG_ 322 CAN_SCAN_INDEX_2LSB_35 0; +BA_ "GenSigCmt" SG_ 322 CAN_SCAN_INDEX_2LSB_35 "CAN_SCAN_INDEX_2LSB_35"; +BA_ "GenMsgSendType" BO_ 321 1; +BA_ "GenMsgILSupport" BO_ 321 1; +BA_ "GenMsgNrOfRepetition" BO_ 321 0; +BA_ "GenMsgCycleTime" BO_ 321 0; +BA_ "NetworkInitialization" BO_ 321 0; +BA_ "GenMsgDelayTime" BO_ 321 0; +BA_ "GenSigVtEn" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigVtName" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_CONFID_AZIMUTH_34 "CAN_DET_CONFID_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_SUPER_RES_TARGET_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_SUPER_RES_TARGET_34 "CAN_DET_SUPER_RES_TARGET_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_ND_TARGET_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_ND_TARGET_34 "CAN_DET_ND_TARGET_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_HOST_VEH_CLUTTER_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_HOST_VEH_CLUTTER_34 "CAN_DET_HOST_VEH_CLUTTER_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_VALID_LEVEL_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_VALID_LEVEL_34 "CAN_DET_VALID_LEVEL_34"; +BA_ "GenSigStartValue" SG_ 321 CAN_DET_AZIMUTH_34 0; +BA_ "GenSigSendType" SG_ 321 CAN_DET_AZIMUTH_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_AZIMUTH_34 "CAN_DET_AZIMUTH_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_RANGE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_RANGE_34 "CAN_DET_RANGE_34"; +BA_ "GenSigStartValue" SG_ 321 CAN_DET_RANGE_RATE_34 0; +BA_ "GenSigSendType" SG_ 321 CAN_DET_RANGE_RATE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_RANGE_RATE_34 "CAN_DET_RANGE_RATE_34"; +BA_ "GenSigSendType" SG_ 321 CAN_DET_AMPLITUDE_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_DET_AMPLITUDE_34 "CAN_DET_AMPLITUDE_34"; +BA_ "GenSigSendType" SG_ 321 CAN_SCAN_INDEX_2LSB_34 0; +BA_ "GenSigCmt" SG_ 321 CAN_SCAN_INDEX_2LSB_34 "CAN_SCAN_INDEX_2LSB_34"; +BA_ "GenMsgSendType" BO_ 320 1; +BA_ "GenMsgILSupport" BO_ 320 1; +BA_ "GenMsgNrOfRepetition" BO_ 320 0; +BA_ "GenMsgCycleTime" BO_ 320 0; +BA_ "NetworkInitialization" BO_ 320 0; +BA_ "GenMsgDelayTime" BO_ 320 0; +BA_ "GenSigVtEn" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigVtName" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_CONFID_AZIMUTH_33 "CAN_DET_CONFID_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_SUPER_RES_TARGET_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_SUPER_RES_TARGET_33 "CAN_DET_SUPER_RES_TARGET_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_ND_TARGET_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_ND_TARGET_33 "CAN_DET_ND_TARGET_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_HOST_VEH_CLUTTER_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_HOST_VEH_CLUTTER_33 "CAN_DET_HOST_VEH_CLUTTER_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_VALID_LEVEL_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_VALID_LEVEL_33 "CAN_DET_VALID_LEVEL_33"; +BA_ "GenSigStartValue" SG_ 320 CAN_DET_AZIMUTH_33 0; +BA_ "GenSigSendType" SG_ 320 CAN_DET_AZIMUTH_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_AZIMUTH_33 "CAN_DET_AZIMUTH_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_RANGE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_RANGE_33 "CAN_DET_RANGE_33"; +BA_ "GenSigStartValue" SG_ 320 CAN_DET_RANGE_RATE_33 0; +BA_ "GenSigSendType" SG_ 320 CAN_DET_RANGE_RATE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_RANGE_RATE_33 "CAN_DET_RANGE_RATE_33"; +BA_ "GenSigSendType" SG_ 320 CAN_DET_AMPLITUDE_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_DET_AMPLITUDE_33 "CAN_DET_AMPLITUDE_33"; +BA_ "GenSigSendType" SG_ 320 CAN_SCAN_INDEX_2LSB_33 0; +BA_ "GenSigCmt" SG_ 320 CAN_SCAN_INDEX_2LSB_33 "CAN_SCAN_INDEX_2LSB_33"; +BA_ "GenMsgSendType" BO_ 319 1; +BA_ "GenMsgILSupport" BO_ 319 1; +BA_ "GenMsgNrOfRepetition" BO_ 319 0; +BA_ "GenMsgCycleTime" BO_ 319 0; +BA_ "NetworkInitialization" BO_ 319 0; +BA_ "GenMsgDelayTime" BO_ 319 0; +BA_ "GenSigVtEn" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigVtName" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_CONFID_AZIMUTH_32 "CAN_DET_CONFID_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_SUPER_RES_TARGET_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_SUPER_RES_TARGET_32 "CAN_DET_SUPER_RES_TARGET_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_ND_TARGET_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_ND_TARGET_32 "CAN_DET_ND_TARGET_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_HOST_VEH_CLUTTER_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_HOST_VEH_CLUTTER_32 "CAN_DET_HOST_VEH_CLUTTER_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_VALID_LEVEL_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_VALID_LEVEL_32 "CAN_DET_VALID_LEVEL_32"; +BA_ "GenSigStartValue" SG_ 319 CAN_DET_AZIMUTH_32 0; +BA_ "GenSigSendType" SG_ 319 CAN_DET_AZIMUTH_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_AZIMUTH_32 "CAN_DET_AZIMUTH_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_RANGE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_RANGE_32 "CAN_DET_RANGE_32"; +BA_ "GenSigStartValue" SG_ 319 CAN_DET_RANGE_RATE_32 0; +BA_ "GenSigSendType" SG_ 319 CAN_DET_RANGE_RATE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_RANGE_RATE_32 "CAN_DET_RANGE_RATE_32"; +BA_ "GenSigSendType" SG_ 319 CAN_DET_AMPLITUDE_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_DET_AMPLITUDE_32 "CAN_DET_AMPLITUDE_32"; +BA_ "GenSigSendType" SG_ 319 CAN_SCAN_INDEX_2LSB_32 0; +BA_ "GenSigCmt" SG_ 319 CAN_SCAN_INDEX_2LSB_32 "CAN_SCAN_INDEX_2LSB_32"; +BA_ "GenMsgSendType" BO_ 318 1; +BA_ "GenMsgILSupport" BO_ 318 1; +BA_ "GenMsgNrOfRepetition" BO_ 318 0; +BA_ "GenMsgCycleTime" BO_ 318 0; +BA_ "NetworkInitialization" BO_ 318 0; +BA_ "GenMsgDelayTime" BO_ 318 0; +BA_ "GenSigVtEn" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigVtName" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_CONFID_AZIMUTH_31 "CAN_DET_CONFID_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_SUPER_RES_TARGET_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_SUPER_RES_TARGET_31 "CAN_DET_SUPER_RES_TARGET_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_ND_TARGET_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_ND_TARGET_31 "CAN_DET_ND_TARGET_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_HOST_VEH_CLUTTER_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_HOST_VEH_CLUTTER_31 "CAN_DET_HOST_VEH_CLUTTER_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_VALID_LEVEL_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_VALID_LEVEL_31 "CAN_DET_VALID_LEVEL_31"; +BA_ "GenSigStartValue" SG_ 318 CAN_DET_AZIMUTH_31 0; +BA_ "GenSigSendType" SG_ 318 CAN_DET_AZIMUTH_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_AZIMUTH_31 "CAN_DET_AZIMUTH_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_RANGE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_RANGE_31 "CAN_DET_RANGE_31"; +BA_ "GenSigStartValue" SG_ 318 CAN_DET_RANGE_RATE_31 0; +BA_ "GenSigSendType" SG_ 318 CAN_DET_RANGE_RATE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_RANGE_RATE_31 "CAN_DET_RANGE_RATE_31"; +BA_ "GenSigSendType" SG_ 318 CAN_DET_AMPLITUDE_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_DET_AMPLITUDE_31 "CAN_DET_AMPLITUDE_31"; +BA_ "GenSigSendType" SG_ 318 CAN_SCAN_INDEX_2LSB_31 0; +BA_ "GenSigCmt" SG_ 318 CAN_SCAN_INDEX_2LSB_31 "CAN_SCAN_INDEX_2LSB_31"; +BA_ "GenMsgSendType" BO_ 317 1; +BA_ "GenMsgILSupport" BO_ 317 1; +BA_ "GenMsgNrOfRepetition" BO_ 317 0; +BA_ "GenMsgCycleTime" BO_ 317 0; +BA_ "NetworkInitialization" BO_ 317 0; +BA_ "GenMsgDelayTime" BO_ 317 0; +BA_ "GenSigVtEn" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigVtName" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_CONFID_AZIMUTH_30 "CAN_DET_CONFID_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_SUPER_RES_TARGET_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_SUPER_RES_TARGET_30 "CAN_DET_SUPER_RES_TARGET_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_ND_TARGET_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_ND_TARGET_30 "CAN_DET_ND_TARGET_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_HOST_VEH_CLUTTER_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_HOST_VEH_CLUTTER_30 "CAN_DET_HOST_VEH_CLUTTER_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_VALID_LEVEL_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_VALID_LEVEL_30 "CAN_DET_VALID_LEVEL_30"; +BA_ "GenSigStartValue" SG_ 317 CAN_DET_AZIMUTH_30 0; +BA_ "GenSigSendType" SG_ 317 CAN_DET_AZIMUTH_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_AZIMUTH_30 "CAN_DET_AZIMUTH_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_RANGE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_RANGE_30 "CAN_DET_RANGE_30"; +BA_ "GenSigStartValue" SG_ 317 CAN_DET_RANGE_RATE_30 0; +BA_ "GenSigSendType" SG_ 317 CAN_DET_RANGE_RATE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_RANGE_RATE_30 "CAN_DET_RANGE_RATE_30"; +BA_ "GenSigSendType" SG_ 317 CAN_DET_AMPLITUDE_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_DET_AMPLITUDE_30 "CAN_DET_AMPLITUDE_30"; +BA_ "GenSigSendType" SG_ 317 CAN_SCAN_INDEX_2LSB_30 0; +BA_ "GenSigCmt" SG_ 317 CAN_SCAN_INDEX_2LSB_30 "CAN_SCAN_INDEX_2LSB_30"; +BA_ "GenMsgSendType" BO_ 316 1; +BA_ "GenMsgILSupport" BO_ 316 1; +BA_ "GenMsgNrOfRepetition" BO_ 316 0; +BA_ "GenMsgCycleTime" BO_ 316 0; +BA_ "NetworkInitialization" BO_ 316 0; +BA_ "GenMsgDelayTime" BO_ 316 0; +BA_ "GenSigVtEn" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigVtName" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_CONFID_AZIMUTH_29 "CAN_DET_CONFID_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_SUPER_RES_TARGET_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_SUPER_RES_TARGET_29 "CAN_DET_SUPER_RES_TARGET_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_ND_TARGET_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_ND_TARGET_29 "CAN_DET_ND_TARGET_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_HOST_VEH_CLUTTER_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_HOST_VEH_CLUTTER_29 "CAN_DET_HOST_VEH_CLUTTER_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_VALID_LEVEL_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_VALID_LEVEL_29 "CAN_DET_VALID_LEVEL_29"; +BA_ "GenSigStartValue" SG_ 316 CAN_DET_AZIMUTH_29 0; +BA_ "GenSigSendType" SG_ 316 CAN_DET_AZIMUTH_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_AZIMUTH_29 "CAN_DET_AZIMUTH_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_RANGE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_RANGE_29 "CAN_DET_RANGE_29"; +BA_ "GenSigStartValue" SG_ 316 CAN_DET_RANGE_RATE_29 0; +BA_ "GenSigSendType" SG_ 316 CAN_DET_RANGE_RATE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_RANGE_RATE_29 "CAN_DET_RANGE_RATE_29"; +BA_ "GenSigSendType" SG_ 316 CAN_DET_AMPLITUDE_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_DET_AMPLITUDE_29 "CAN_DET_AMPLITUDE_29"; +BA_ "GenSigSendType" SG_ 316 CAN_SCAN_INDEX_2LSB_29 0; +BA_ "GenSigCmt" SG_ 316 CAN_SCAN_INDEX_2LSB_29 "CAN_SCAN_INDEX_2LSB_29"; +BA_ "GenMsgSendType" BO_ 314 1; +BA_ "GenMsgILSupport" BO_ 314 1; +BA_ "GenMsgNrOfRepetition" BO_ 314 0; +BA_ "GenMsgCycleTime" BO_ 314 0; +BA_ "NetworkInitialization" BO_ 314 0; +BA_ "GenMsgDelayTime" BO_ 314 0; +BA_ "GenSigVtEn" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigVtName" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_CONFID_AZIMUTH_27 "CAN_DET_CONFID_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_SUPER_RES_TARGET_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_SUPER_RES_TARGET_27 "CAN_DET_SUPER_RES_TARGET_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_ND_TARGET_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_ND_TARGET_27 "CAN_DET_ND_TARGET_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_HOST_VEH_CLUTTER_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_HOST_VEH_CLUTTER_27 "CAN_DET_HOST_VEH_CLUTTER_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_VALID_LEVEL_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_VALID_LEVEL_27 "CAN_DET_VALID_LEVEL_27"; +BA_ "GenSigStartValue" SG_ 314 CAN_DET_AZIMUTH_27 0; +BA_ "GenSigSendType" SG_ 314 CAN_DET_AZIMUTH_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_AZIMUTH_27 "CAN_DET_AZIMUTH_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_RANGE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_RANGE_27 "CAN_DET_RANGE_27"; +BA_ "GenSigStartValue" SG_ 314 CAN_DET_RANGE_RATE_27 0; +BA_ "GenSigSendType" SG_ 314 CAN_DET_RANGE_RATE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_RANGE_RATE_27 "CAN_DET_RANGE_RATE_27"; +BA_ "GenSigSendType" SG_ 314 CAN_DET_AMPLITUDE_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_DET_AMPLITUDE_27 "CAN_DET_AMPLITUDE_27"; +BA_ "GenSigSendType" SG_ 314 CAN_SCAN_INDEX_2LSB_27 0; +BA_ "GenSigCmt" SG_ 314 CAN_SCAN_INDEX_2LSB_27 "CAN_SCAN_INDEX_2LSB_27"; +BA_ "GenMsgSendType" BO_ 313 1; +BA_ "GenMsgILSupport" BO_ 313 1; +BA_ "GenMsgNrOfRepetition" BO_ 313 0; +BA_ "GenMsgCycleTime" BO_ 313 0; +BA_ "NetworkInitialization" BO_ 313 0; +BA_ "GenMsgDelayTime" BO_ 313 0; +BA_ "GenSigVtEn" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigVtName" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_CONFID_AZIMUTH_26 "CAN_DET_CONFID_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_SUPER_RES_TARGET_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_SUPER_RES_TARGET_26 "CAN_DET_SUPER_RES_TARGET_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_ND_TARGET_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_ND_TARGET_26 "CAN_DET_ND_TARGET_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_HOST_VEH_CLUTTER_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_HOST_VEH_CLUTTER_26 "CAN_DET_HOST_VEH_CLUTTER_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_VALID_LEVEL_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_VALID_LEVEL_26 "CAN_DET_VALID_LEVEL_26"; +BA_ "GenSigStartValue" SG_ 313 CAN_DET_AZIMUTH_26 0; +BA_ "GenSigSendType" SG_ 313 CAN_DET_AZIMUTH_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_AZIMUTH_26 "CAN_DET_AZIMUTH_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_RANGE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_RANGE_26 "CAN_DET_RANGE_26"; +BA_ "GenSigStartValue" SG_ 313 CAN_DET_RANGE_RATE_26 0; +BA_ "GenSigSendType" SG_ 313 CAN_DET_RANGE_RATE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_RANGE_RATE_26 "CAN_DET_RANGE_RATE_26"; +BA_ "GenSigSendType" SG_ 313 CAN_DET_AMPLITUDE_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_DET_AMPLITUDE_26 "CAN_DET_AMPLITUDE_26"; +BA_ "GenSigSendType" SG_ 313 CAN_SCAN_INDEX_2LSB_26 0; +BA_ "GenSigCmt" SG_ 313 CAN_SCAN_INDEX_2LSB_26 "CAN_SCAN_INDEX_2LSB_26"; +BA_ "GenMsgSendType" BO_ 312 1; +BA_ "GenMsgILSupport" BO_ 312 1; +BA_ "GenMsgNrOfRepetition" BO_ 312 0; +BA_ "GenMsgCycleTime" BO_ 312 0; +BA_ "NetworkInitialization" BO_ 312 0; +BA_ "GenMsgDelayTime" BO_ 312 0; +BA_ "GenSigVtEn" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigVtName" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_CONFID_AZIMUTH_25 "CAN_DET_CONFID_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_SUPER_RES_TARGET_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_SUPER_RES_TARGET_25 "CAN_DET_SUPER_RES_TARGET_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_ND_TARGET_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_ND_TARGET_25 "CAN_DET_ND_TARGET_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_HOST_VEH_CLUTTER_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_HOST_VEH_CLUTTER_25 "CAN_DET_HOST_VEH_CLUTTER_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_VALID_LEVEL_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_VALID_LEVEL_25 "CAN_DET_VALID_LEVEL_25"; +BA_ "GenSigStartValue" SG_ 312 CAN_DET_AZIMUTH_25 0; +BA_ "GenSigSendType" SG_ 312 CAN_DET_AZIMUTH_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_AZIMUTH_25 "CAN_DET_AZIMUTH_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_RANGE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_RANGE_25 "CAN_DET_RANGE_25"; +BA_ "GenSigStartValue" SG_ 312 CAN_DET_RANGE_RATE_25 0; +BA_ "GenSigSendType" SG_ 312 CAN_DET_RANGE_RATE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_RANGE_RATE_25 "CAN_DET_RANGE_RATE_25"; +BA_ "GenSigSendType" SG_ 312 CAN_DET_AMPLITUDE_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_DET_AMPLITUDE_25 "CAN_DET_AMPLITUDE_25"; +BA_ "GenSigSendType" SG_ 312 CAN_SCAN_INDEX_2LSB_25 0; +BA_ "GenSigCmt" SG_ 312 CAN_SCAN_INDEX_2LSB_25 "CAN_SCAN_INDEX_2LSB_25"; +BA_ "GenMsgSendType" BO_ 311 1; +BA_ "GenMsgILSupport" BO_ 311 1; +BA_ "GenMsgNrOfRepetition" BO_ 311 0; +BA_ "GenMsgCycleTime" BO_ 311 0; +BA_ "NetworkInitialization" BO_ 311 0; +BA_ "GenMsgDelayTime" BO_ 311 0; +BA_ "GenSigVtEn" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigVtName" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_CONFID_AZIMUTH_24 "CAN_DET_CONFID_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_SUPER_RES_TARGET_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_SUPER_RES_TARGET_24 "CAN_DET_SUPER_RES_TARGET_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_ND_TARGET_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_ND_TARGET_24 "CAN_DET_ND_TARGET_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_HOST_VEH_CLUTTER_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_HOST_VEH_CLUTTER_24 "CAN_DET_HOST_VEH_CLUTTER_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_VALID_LEVEL_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_VALID_LEVEL_24 "CAN_DET_VALID_LEVEL_24"; +BA_ "GenSigStartValue" SG_ 311 CAN_DET_AZIMUTH_24 0; +BA_ "GenSigSendType" SG_ 311 CAN_DET_AZIMUTH_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_AZIMUTH_24 "CAN_DET_AZIMUTH_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_RANGE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_RANGE_24 "CAN_DET_RANGE_24"; +BA_ "GenSigStartValue" SG_ 311 CAN_DET_RANGE_RATE_24 0; +BA_ "GenSigSendType" SG_ 311 CAN_DET_RANGE_RATE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_RANGE_RATE_24 "CAN_DET_RANGE_RATE_24"; +BA_ "GenSigSendType" SG_ 311 CAN_DET_AMPLITUDE_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_DET_AMPLITUDE_24 "CAN_DET_AMPLITUDE_24"; +BA_ "GenSigSendType" SG_ 311 CAN_SCAN_INDEX_2LSB_24 0; +BA_ "GenSigCmt" SG_ 311 CAN_SCAN_INDEX_2LSB_24 "CAN_SCAN_INDEX_2LSB_24"; +BA_ "GenMsgSendType" BO_ 310 1; +BA_ "GenMsgILSupport" BO_ 310 1; +BA_ "GenMsgNrOfRepetition" BO_ 310 0; +BA_ "GenMsgCycleTime" BO_ 310 0; +BA_ "NetworkInitialization" BO_ 310 0; +BA_ "GenMsgDelayTime" BO_ 310 0; +BA_ "GenSigVtEn" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigVtName" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_CONFID_AZIMUTH_23 "CAN_DET_CONFID_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_SUPER_RES_TARGET_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_SUPER_RES_TARGET_23 "CAN_DET_SUPER_RES_TARGET_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_ND_TARGET_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_ND_TARGET_23 "CAN_DET_ND_TARGET_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_HOST_VEH_CLUTTER_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_HOST_VEH_CLUTTER_23 "CAN_DET_HOST_VEH_CLUTTER_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_VALID_LEVEL_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_VALID_LEVEL_23 "CAN_DET_VALID_LEVEL_23"; +BA_ "GenSigStartValue" SG_ 310 CAN_DET_AZIMUTH_23 0; +BA_ "GenSigSendType" SG_ 310 CAN_DET_AZIMUTH_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_AZIMUTH_23 "CAN_DET_AZIMUTH_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_RANGE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_RANGE_23 "CAN_DET_RANGE_23"; +BA_ "GenSigStartValue" SG_ 310 CAN_DET_RANGE_RATE_23 0; +BA_ "GenSigSendType" SG_ 310 CAN_DET_RANGE_RATE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_RANGE_RATE_23 "CAN_DET_RANGE_RATE_23"; +BA_ "GenSigSendType" SG_ 310 CAN_DET_AMPLITUDE_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_DET_AMPLITUDE_23 "CAN_DET_AMPLITUDE_23"; +BA_ "GenSigSendType" SG_ 310 CAN_SCAN_INDEX_2LSB_23 0; +BA_ "GenSigCmt" SG_ 310 CAN_SCAN_INDEX_2LSB_23 "CAN_SCAN_INDEX_2LSB_23"; +EOF + +build_ba "22" +build_ba "21" +build_ba "20" +build_ba "19" +build_ba "18" + +cat <> ${OUT_FILENAME} +BA_ "GenMsgSendType" BO_ 341 1; +BA_ "GenMsgILSupport" BO_ 341 1; +BA_ "GenMsgNrOfRepetition" BO_ 341 0; +BA_ "GenMsgCycleTime" BO_ 341 0; +BA_ "NetworkInitialization" BO_ 341 0; +BA_ "GenMsgDelayTime" BO_ 341 0; +BA_ "GenSigVtEn" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigVtName" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_CONFID_AZIMUTH_54 "CAN_DET_CONFID_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_SUPER_RES_TARGET_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_SUPER_RES_TARGET_54 "CAN_DET_SUPER_RES_TARGET_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_ND_TARGET_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_ND_TARGET_54 "CAN_DET_ND_TARGET_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_HOST_VEH_CLUTTER_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_HOST_VEH_CLUTTER_54 "CAN_DET_HOST_VEH_CLUTTER_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_VALID_LEVEL_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_VALID_LEVEL_54 "CAN_DET_VALID_LEVEL_54"; +BA_ "GenSigStartValue" SG_ 341 CAN_DET_AZIMUTH_54 0; +BA_ "GenSigSendType" SG_ 341 CAN_DET_AZIMUTH_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_AZIMUTH_54 "CAN_DET_AZIMUTH_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_RANGE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_RANGE_54 "CAN_DET_RANGE_54"; +BA_ "GenSigStartValue" SG_ 341 CAN_DET_RANGE_RATE_54 0; +BA_ "GenSigSendType" SG_ 341 CAN_DET_RANGE_RATE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_RANGE_RATE_54 "CAN_DET_RANGE_RATE_54"; +BA_ "GenSigSendType" SG_ 341 CAN_DET_AMPLITUDE_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_DET_AMPLITUDE_54 "CAN_DET_AMPLITUDE_54"; +BA_ "GenSigSendType" SG_ 341 CAN_SCAN_INDEX_2LSB_54 0; +BA_ "GenSigCmt" SG_ 341 CAN_SCAN_INDEX_2LSB_54 "CAN_SCAN_INDEX_2LSB_54"; +BA_ "GenMsgSendType" BO_ 340 1; +BA_ "GenMsgILSupport" BO_ 340 1; +BA_ "GenMsgNrOfRepetition" BO_ 340 0; +BA_ "GenMsgCycleTime" BO_ 340 0; +BA_ "NetworkInitialization" BO_ 340 0; +BA_ "GenMsgDelayTime" BO_ 340 0; +BA_ "GenSigVtEn" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigVtName" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_CONFID_AZIMUTH_53 "CAN_DET_CONFID_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_SUPER_RES_TARGET_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_SUPER_RES_TARGET_53 "CAN_DET_SUPER_RES_TARGET_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_ND_TARGET_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_ND_TARGET_53 "CAN_DET_ND_TARGET_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_HOST_VEH_CLUTTER_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_HOST_VEH_CLUTTER_53 "CAN_DET_HOST_VEH_CLUTTER_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_VALID_LEVEL_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_VALID_LEVEL_53 "CAN_DET_VALID_LEVEL_53"; +BA_ "GenSigStartValue" SG_ 340 CAN_DET_AZIMUTH_53 0; +BA_ "GenSigSendType" SG_ 340 CAN_DET_AZIMUTH_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_AZIMUTH_53 "CAN_DET_AZIMUTH_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_RANGE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_RANGE_53 "CAN_DET_RANGE_53"; +BA_ "GenSigStartValue" SG_ 340 CAN_DET_RANGE_RATE_53 0; +BA_ "GenSigSendType" SG_ 340 CAN_DET_RANGE_RATE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_RANGE_RATE_53 "CAN_DET_RANGE_RATE_53"; +BA_ "GenSigSendType" SG_ 340 CAN_DET_AMPLITUDE_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_DET_AMPLITUDE_53 "CAN_DET_AMPLITUDE_53"; +BA_ "GenSigSendType" SG_ 340 CAN_SCAN_INDEX_2LSB_53 0; +BA_ "GenSigCmt" SG_ 340 CAN_SCAN_INDEX_2LSB_53 "CAN_SCAN_INDEX_2LSB_53"; +BA_ "GenMsgSendType" BO_ 339 1; +BA_ "GenMsgILSupport" BO_ 339 1; +BA_ "GenMsgNrOfRepetition" BO_ 339 0; +BA_ "GenMsgCycleTime" BO_ 339 0; +BA_ "NetworkInitialization" BO_ 339 0; +BA_ "GenMsgDelayTime" BO_ 339 0; +BA_ "GenSigVtEn" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigVtName" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_CONFID_AZIMUTH_52 "CAN_DET_CONFID_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_SUPER_RES_TARGET_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_SUPER_RES_TARGET_52 "CAN_DET_SUPER_RES_TARGET_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_ND_TARGET_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_ND_TARGET_52 "CAN_DET_ND_TARGET_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_HOST_VEH_CLUTTER_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_HOST_VEH_CLUTTER_52 "CAN_DET_HOST_VEH_CLUTTER_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_VALID_LEVEL_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_VALID_LEVEL_52 "CAN_DET_VALID_LEVEL_52"; +BA_ "GenSigStartValue" SG_ 339 CAN_DET_AZIMUTH_52 0; +BA_ "GenSigSendType" SG_ 339 CAN_DET_AZIMUTH_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_AZIMUTH_52 "CAN_DET_AZIMUTH_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_RANGE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_RANGE_52 "CAN_DET_RANGE_52"; +BA_ "GenSigStartValue" SG_ 339 CAN_DET_RANGE_RATE_52 0; +BA_ "GenSigSendType" SG_ 339 CAN_DET_RANGE_RATE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_RANGE_RATE_52 "CAN_DET_RANGE_RATE_52"; +BA_ "GenSigSendType" SG_ 339 CAN_DET_AMPLITUDE_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_DET_AMPLITUDE_52 "CAN_DET_AMPLITUDE_52"; +BA_ "GenSigSendType" SG_ 339 CAN_SCAN_INDEX_2LSB_52 0; +BA_ "GenSigCmt" SG_ 339 CAN_SCAN_INDEX_2LSB_52 "CAN_SCAN_INDEX_2LSB_52"; +BA_ "GenMsgSendType" BO_ 338 1; +BA_ "GenMsgILSupport" BO_ 338 1; +BA_ "GenMsgNrOfRepetition" BO_ 338 0; +BA_ "GenMsgCycleTime" BO_ 338 0; +BA_ "NetworkInitialization" BO_ 338 0; +BA_ "GenMsgDelayTime" BO_ 338 0; +BA_ "GenSigVtEn" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigVtName" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_CONFID_AZIMUTH_51 "CAN_DET_CONFID_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_SUPER_RES_TARGET_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_SUPER_RES_TARGET_51 "CAN_DET_SUPER_RES_TARGET_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_ND_TARGET_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_ND_TARGET_51 "CAN_DET_ND_TARGET_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_HOST_VEH_CLUTTER_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_HOST_VEH_CLUTTER_51 "CAN_DET_HOST_VEH_CLUTTER_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_VALID_LEVEL_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_VALID_LEVEL_51 "CAN_DET_VALID_LEVEL_51"; +BA_ "GenSigStartValue" SG_ 338 CAN_DET_AZIMUTH_51 0; +BA_ "GenSigSendType" SG_ 338 CAN_DET_AZIMUTH_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_AZIMUTH_51 "CAN_DET_AZIMUTH_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_RANGE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_RANGE_51 "CAN_DET_RANGE_51"; +BA_ "GenSigStartValue" SG_ 338 CAN_DET_RANGE_RATE_51 0; +BA_ "GenSigSendType" SG_ 338 CAN_DET_RANGE_RATE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_RANGE_RATE_51 "CAN_DET_RANGE_RATE_51"; +BA_ "GenSigSendType" SG_ 338 CAN_DET_AMPLITUDE_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_DET_AMPLITUDE_51 "CAN_DET_AMPLITUDE_51"; +BA_ "GenSigSendType" SG_ 338 CAN_SCAN_INDEX_2LSB_51 0; +BA_ "GenSigCmt" SG_ 338 CAN_SCAN_INDEX_2LSB_51 "CAN_SCAN_INDEX_2LSB_51"; +BA_ "GenMsgSendType" BO_ 337 1; +BA_ "GenMsgILSupport" BO_ 337 1; +BA_ "GenMsgNrOfRepetition" BO_ 337 0; +BA_ "GenMsgCycleTime" BO_ 337 0; +BA_ "NetworkInitialization" BO_ 337 0; +BA_ "GenMsgDelayTime" BO_ 337 0; +BA_ "GenSigVtEn" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigVtName" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_CONFID_AZIMUTH_50 "CAN_DET_CONFID_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_SUPER_RES_TARGET_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_SUPER_RES_TARGET_50 "CAN_DET_SUPER_RES_TARGET_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_ND_TARGET_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_ND_TARGET_50 "CAN_DET_ND_TARGET_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_HOST_VEH_CLUTTER_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_HOST_VEH_CLUTTER_50 "CAN_DET_HOST_VEH_CLUTTER_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_VALID_LEVEL_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_VALID_LEVEL_50 "CAN_DET_VALID_LEVEL_50"; +BA_ "GenSigStartValue" SG_ 337 CAN_DET_AZIMUTH_50 0; +BA_ "GenSigSendType" SG_ 337 CAN_DET_AZIMUTH_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_AZIMUTH_50 "CAN_DET_AZIMUTH_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_RANGE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_RANGE_50 "CAN_DET_RANGE_50"; +BA_ "GenSigStartValue" SG_ 337 CAN_DET_RANGE_RATE_50 0; +BA_ "GenSigSendType" SG_ 337 CAN_DET_RANGE_RATE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_RANGE_RATE_50 "CAN_DET_RANGE_RATE_50"; +BA_ "GenSigSendType" SG_ 337 CAN_DET_AMPLITUDE_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_DET_AMPLITUDE_50 "CAN_DET_AMPLITUDE_50"; +BA_ "GenSigSendType" SG_ 337 CAN_SCAN_INDEX_2LSB_50 0; +BA_ "GenSigCmt" SG_ 337 CAN_SCAN_INDEX_2LSB_50 "CAN_SCAN_INDEX_2LSB_50"; +BA_ "GenMsgSendType" BO_ 336 1; +BA_ "GenMsgILSupport" BO_ 336 1; +BA_ "GenMsgNrOfRepetition" BO_ 336 0; +BA_ "GenMsgCycleTime" BO_ 336 0; +BA_ "NetworkInitialization" BO_ 336 0; +BA_ "GenMsgDelayTime" BO_ 336 0; +BA_ "GenSigVtEn" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigVtName" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_CONFID_AZIMUTH_49 "CAN_DET_CONFID_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_SUPER_RES_TARGET_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_SUPER_RES_TARGET_49 "CAN_DET_SUPER_RES_TARGET_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_ND_TARGET_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_ND_TARGET_49 "CAN_DET_ND_TARGET_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_HOST_VEH_CLUTTER_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_HOST_VEH_CLUTTER_49 "CAN_DET_HOST_VEH_CLUTTER_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_VALID_LEVEL_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_VALID_LEVEL_49 "CAN_DET_VALID_LEVEL_49"; +BA_ "GenSigStartValue" SG_ 336 CAN_DET_AZIMUTH_49 0; +BA_ "GenSigSendType" SG_ 336 CAN_DET_AZIMUTH_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_AZIMUTH_49 "CAN_DET_AZIMUTH_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_RANGE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_RANGE_49 "CAN_DET_RANGE_49"; +BA_ "GenSigStartValue" SG_ 336 CAN_DET_RANGE_RATE_49 0; +BA_ "GenSigSendType" SG_ 336 CAN_DET_RANGE_RATE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_RANGE_RATE_49 "CAN_DET_RANGE_RATE_49"; +BA_ "GenSigSendType" SG_ 336 CAN_DET_AMPLITUDE_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_DET_AMPLITUDE_49 "CAN_DET_AMPLITUDE_49"; +BA_ "GenSigSendType" SG_ 336 CAN_SCAN_INDEX_2LSB_49 0; +BA_ "GenSigCmt" SG_ 336 CAN_SCAN_INDEX_2LSB_49 "CAN_SCAN_INDEX_2LSB_49"; +BA_ "GenMsgSendType" BO_ 326 1; +BA_ "GenMsgILSupport" BO_ 326 1; +BA_ "GenMsgNrOfRepetition" BO_ 326 0; +BA_ "GenMsgCycleTime" BO_ 326 0; +BA_ "NetworkInitialization" BO_ 326 0; +BA_ "GenMsgDelayTime" BO_ 326 0; +BA_ "GenSigVtEn" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigVtName" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_CONFID_AZIMUTH_39 "CAN_DET_CONFID_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_SUPER_RES_TARGET_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_SUPER_RES_TARGET_39 "CAN_DET_SUPER_RES_TARGET_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_ND_TARGET_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_ND_TARGET_39 "CAN_DET_ND_TARGET_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_HOST_VEH_CLUTTER_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_HOST_VEH_CLUTTER_39 "CAN_DET_HOST_VEH_CLUTTER_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_VALID_LEVEL_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_VALID_LEVEL_39 "CAN_DET_VALID_LEVEL_39"; +BA_ "GenSigStartValue" SG_ 326 CAN_DET_AZIMUTH_39 0; +BA_ "GenSigSendType" SG_ 326 CAN_DET_AZIMUTH_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_AZIMUTH_39 "CAN_DET_AZIMUTH_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_RANGE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_RANGE_39 "CAN_DET_RANGE_39"; +BA_ "GenSigStartValue" SG_ 326 CAN_DET_RANGE_RATE_39 0; +BA_ "GenSigSendType" SG_ 326 CAN_DET_RANGE_RATE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_RANGE_RATE_39 "CAN_DET_RANGE_RATE_39"; +BA_ "GenSigSendType" SG_ 326 CAN_DET_AMPLITUDE_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_DET_AMPLITUDE_39 "CAN_DET_AMPLITUDE_39"; +BA_ "GenSigSendType" SG_ 326 CAN_SCAN_INDEX_2LSB_39 0; +BA_ "GenSigCmt" SG_ 326 CAN_SCAN_INDEX_2LSB_39 "CAN_SCAN_INDEX_2LSB_39"; +BA_ "GenMsgSendType" BO_ 315 1; +BA_ "GenMsgILSupport" BO_ 315 1; +BA_ "GenMsgNrOfRepetition" BO_ 315 0; +BA_ "GenMsgCycleTime" BO_ 315 0; +BA_ "NetworkInitialization" BO_ 315 0; +BA_ "GenMsgDelayTime" BO_ 315 0; +BA_ "GenSigVtEn" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigVtName" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_CONFID_AZIMUTH_28 "CAN_DET_CONFID_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_SUPER_RES_TARGET_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_SUPER_RES_TARGET_28 "CAN_DET_SUPER_RES_TARGET_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_ND_TARGET_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_ND_TARGET_28 "CAN_DET_ND_TARGET_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_HOST_VEH_CLUTTER_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_HOST_VEH_CLUTTER_28 "CAN_DET_HOST_VEH_CLUTTER_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_VALID_LEVEL_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_VALID_LEVEL_28 "CAN_DET_VALID_LEVEL_28"; +BA_ "GenSigStartValue" SG_ 315 CAN_DET_AZIMUTH_28 0; +BA_ "GenSigSendType" SG_ 315 CAN_DET_AZIMUTH_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_AZIMUTH_28 "CAN_DET_AZIMUTH_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_RANGE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_RANGE_28 "CAN_DET_RANGE_28"; +BA_ "GenSigStartValue" SG_ 315 CAN_DET_RANGE_RATE_28 0; +BA_ "GenSigSendType" SG_ 315 CAN_DET_RANGE_RATE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_RANGE_RATE_28 "CAN_DET_RANGE_RATE_28"; +BA_ "GenSigSendType" SG_ 315 CAN_DET_AMPLITUDE_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_DET_AMPLITUDE_28 "CAN_DET_AMPLITUDE_28"; +BA_ "GenSigSendType" SG_ 315 CAN_SCAN_INDEX_2LSB_28 0; +BA_ "GenSigCmt" SG_ 315 CAN_SCAN_INDEX_2LSB_28 "CAN_SCAN_INDEX_2LSB_28"; +EOF + +build_ba "17" +build_ba "16" +build_ba "15" +build_ba "14" +build_ba "13" +build_ba "12" +build_ba "11" +build_ba "10" +build_ba "09" +build_ba "08" +build_ba "07" +build_ba "06" +build_ba "05" +build_ba "03" +build_ba "02" + +cat <> ${OUT_FILENAME} +BA_ "GenMsgSendType" BO_ 256 1; +BA_ "GenMsgILSupport" BO_ 256 1; +BA_ "GenMsgNrOfRepetition" BO_ 256 0; +BA_ "NetworkInitialization" BO_ 256 0; +BA_ "GenSigCmt" SG_ 256 CAN_PCAN_MINOR_MRR "CAN_PCAN_MINOR_MRR"; +BA_ "GenSigSendType" SG_ 256 CAN_PCAN_MINOR_MRR 0; +BA_ "GenSigCmt" SG_ 256 CAN_PCAN_MAJOR_MRR "CAN_PCAN_MAJOR_MRR"; +BA_ "GenSigSendType" SG_ 256 CAN_PCAN_MAJOR_MRR 0; +BA_ "GenMsgCycleTime" BO_ 257 30; +BA_ "GenMsgSendType" BO_ 257 0; +BA_ "GenMsgILSupport" BO_ 257 1; +BA_ "GenMsgNrOfRepetition" BO_ 257 0; +BA_ "NetworkInitialization" BO_ 257 0; +BA_ "GenSigCmt" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtEn" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtName" SG_ 257 CAN_INTERFERENCE_TYPE "CAN_INTERFERENCE_TYPE"; +BA_ "GenSigVtName" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigCmt" SG_ 257 CAN_RECOMMEND_UNCONVERGE "CAN_RECOMMEND_UNCONVERGE"; +BA_ "GenSigStartValue" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL 0; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL 0; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_SIDELOBE_FILTER_VAL "CAN_BLOCKAGE_SIDELOBE_FILTER_VAL"; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_INCOMPLETE "CAN_RADAR_ALIGN_INCOMPLETE"; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_SIDELOBE "CAN_BLOCKAGE_SIDELOBE"; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_SIDELOBE 0; +BA_ "GenSigCmt" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigVtEn" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigVtName" SG_ 257 CAN_BLOCKAGE_MNR "CAN_BLOCKAGE_MNR"; +BA_ "GenSigSendType" SG_ 257 CAN_BLOCKAGE_MNR 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_EXT_COND_NOK "CAN_RADAR_EXT_COND_NOK"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_EXT_COND_NOK 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE "CAN_RADAR_ALIGN_OUT_RANGE"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_ALIGN_OUT_RANGE 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_ALIGN_NOT_START "CAN_RADAR_ALIGN_NOT_START"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_ALIGN_NOT_START 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_OVERHEAT_ERROR "CAN_RADAR_OVERHEAT_ERROR"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_OVERHEAT_ERROR 0; +BA_ "GenSigCmt" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigVtEn" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigVtName" SG_ 257 CAN_RADAR_NOT_OP "CAN_RADAR_NOT_OP"; +BA_ "GenSigSendType" SG_ 257 CAN_RADAR_NOT_OP 0; +BA_ "GenSigCmt" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigVtEn" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigVtName" SG_ 257 CAN_XCVR_OPERATIONAL "CAN_XCVR_OPERATIONAL"; +BA_ "GenSigSendType" SG_ 257 CAN_XCVR_OPERATIONAL 0; +EOF + +build_ba "01" + +cat <> ${OUT_FILENAME} +BA_DEF_DEF_ "CrossOver_InfoCAN" "No"; +BA_DEF_DEF_ "CrossOver_LIN" "No"; +BA_DEF_DEF_ "UsedOnPgmDBC" "Yes"; +BA_DEF_DEF_ "ContentDependant" "No"; +BA_DEF_DEF_ "GenSigTimeoutTime_RCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_GWM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_OCS" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_ABS_ESC" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_CCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_IPMA" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_TSTR" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_SCCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_PSCM" 0; +BA_DEF_DEF_ "GenSigTimeoutTime__delete" 0; +BA_DEF_DEF_ "GenSigTimeoutTime_Generic_BCM" 0; +BA_DEF_DEF_ "NmMessage" "No"; +BA_DEF_DEF_ "DiagResponse" "No"; +BA_DEF_DEF_ "DiagRequest" "No"; +BA_DEF_DEF_ "TpTxIndex" 0; +BA_DEF_DEF_ "DiagState" "No"; +BA_DEF_DEF_ "TpApplType" ""; +BA_DEF_DEF_ "NmAsrMessage" "No"; +BA_DEF_DEF_ "Mulitplexer" "No"; +BA_DEF_DEF_ "ConfiguredTransmitter" "No"; +BA_DEF_DEF_ "EventRateOfChange" 10000; +BA_DEF_DEF_ "GenMsgHandlingTypeDoc" ""; +BA_DEF_DEF_ "GenMsgHandlingTypeCode" ""; +BA_DEF_DEF_ "GenMsgMarked" ""; +BA_DEF_DEF_ "GenSigMarked" ""; +BA_DEF_DEF_ "GenSigVtIndex" ""; +BA_DEF_DEF_ "GenSigVtName" ""; +BA_DEF_DEF_ "GenSigVtEn" ""; +BA_DEF_DEF_ "GenSigSNA" ""; +BA_DEF_DEF_ "GenSigCmt" ""; +BA_DEF_DEF_ "GenMsgCmt" ""; +BA_DEF_DEF_ "GenSigSendType" "NoSigSendType"; +BA_DEF_DEF_ "GenSigInactiveValue" 0; +BA_DEF_DEF_ "GenSigMissingSourceValue" 0; +BA_DEF_DEF_ "WakeupSignal" "No"; +BA_DEF_DEF_ "GenSigStartValue" 0; +BA_DEF_DEF_ "GenMsgILSupport" "Yes"; +BA_DEF_DEF_ "NetworkInitializationCommand" "No"; +BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType"; +BA_DEF_DEF_ "GenMsgCycleTime" 0; +BA_DEF_DEF_ "GenMsgCycleTimeFast" 0; +BA_DEF_DEF_ "GenMsgDelayTime" 0; +BA_DEF_DEF_ "GenMsgNrOfRepetition" 0; +BA_DEF_DEF_ "GenMsgStartDelayTime" 0; +BA_DEF_DEF_ "NetworkInitialization" "No"; +BA_DEF_DEF_ "MessageGateway" "No"; +BA_DEF_DEF_ "ILUsed" "Yes"; +BA_DEF_DEF_ "NetworkInitializationUsed" "No"; +BA_DEF_DEF_ "PowerType" "Switched"; +BA_DEF_DEF_ "NodeStartUpTime" 250; +BA_DEF_DEF_ "NodeWakeUpTime" 10; +BA_DEF_DEF_ "GenMsgBackgroundColor" "#ffffff"; +BA_DEF_DEF_ "GenMsgForegroundColor" "#000000"; +VAL_ 34 IPMA_PCAN_DataRangeCheck 1 "Fault Present" 0 "No Fault"; +VAL_ 34 IPMA_PCAN_MissingMsg 1 "Fault Present" 0 "No Fault "; +VAL_ 34 VINSignalCompareFailure 1 "Fault Present" 0 "No Fault"; +VAL_ 34 ModuleNotConfiguredError 1 "Fault Present" 0 "No Fault"; +VAL_ 34 CarCfgNotConfiguredError 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte7_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ARMtoDSPChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 DSPtoArmChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 HostToArmChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ARMtoHostChksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 LoopBWOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 DSPOverrunFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte6_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TuningSensitivityFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 SaturatedTuningFreqFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 LocalOscPowerFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterPowerFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte6_bit0 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 XCVRDeviceSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 FreqSynthesizerSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 AnalogConverterDevicSPIFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 SidelobeBlockage 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte5_bit1 1 "Fault Present" 0 "No Fault"; +VAL_ 33 MNRBlocked 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ECUTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 AlignmentRoutineFailedFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 UnreasonableRadarData 1 "Fault Present" 0 "No Fault"; +VAL_ 33 MicroprocessorTempHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 VerticalAlignmentOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 HorizontalAlignmentOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 FactoryAlignmentMode 1 "Fault Present" 0 "No Fault"; +VAL_ 33 BatteryLowFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 BatteryHighFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_1p25SupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte3_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ThermistorOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_3p3DACSupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_3p3RAWSupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 v_5_SupplyOutOfRange 1 "Fault Present" 0 "No Fault"; +VAL_ 33 TransmitterIDFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit3 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte2_bit2 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PCANMissingMsgFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PCANBusOff 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit7 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 InstructionSetCheckFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 StackOverflowFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 WatchdogFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 PLLLockFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte1_bit1 1 "Fault Present" 0 "No Fault"; +VAL_ 33 RAMMemoryTestFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 USCValidationFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit6 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit5 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit4 1 "Fault Present" 0 "No Fault"; +VAL_ 33 Active_Flt_Latched_byte0_bit3 1 "Fault Present" 0 "No Fault"; +VAL_ 33 KeepAliveChecksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ProgramCalibrationFlashChecksum 1 "Fault Present" 0 "No Fault"; +VAL_ 33 ApplicationFlashChecksumFault 1 "Fault Present" 0 "No Fault"; +VAL_ 371 CAN_AUTO_ALIGN_HANGLE_QF 3 "Accurate" 2 "Inaccurate" 1 "Temporarily undefined" 0 "Undefined"; +VAL_ 371 CAN_ALIGNMENT_STATUS 15 "Undefined_2" 14 "Undefined_1" 13 "Low Amplitude (Flat-plate only)" 12 "No Peak (Flat-plate only)" 11 "Fail Ver and Hor OutOfRange" 10 "Fail Vertical Align OutOfRange" 9 "Fail Horizontal Align OutOfRange" 8 "Fail Time Out" 7 "Fail Only Right Target Found" 6 "Fail Only Left Target Found" 5 "Fail Variance Too Large" 4 "Fail Deviation Too Large" 3 "Fail No Target" 2 "Success" 1 "Busy" 0 "Off"; +VAL_ 371 CAN_ALIGNMENT_STATE 6 "Static alignment flat-plate" 5 "Static alignment 2-target" 4 "Static alignment 1-target" 3 "Service alignment" 2 "Short track alignment" 1 "Auto alignment" 0 "Off"; +EOF + +build_val "04" + +cat <> ${OUT_FILENAME} +VAL_ 351 CAN_DET_CONFID_AZIMUTH_64 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 350 CAN_DET_CONFID_AZIMUTH_63 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 349 CAN_DET_CONFID_AZIMUTH_62 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 348 CAN_DET_CONFID_AZIMUTH_61 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 347 CAN_DET_CONFID_AZIMUTH_60 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 346 CAN_DET_CONFID_AZIMUTH_59 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 345 CAN_DET_CONFID_AZIMUTH_58 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 344 CAN_DET_CONFID_AZIMUTH_57 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 343 CAN_DET_CONFID_AZIMUTH_56 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 342 CAN_DET_CONFID_AZIMUTH_55 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 335 CAN_DET_CONFID_AZIMUTH_48 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 334 CAN_DET_CONFID_AZIMUTH_47 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 333 CAN_DET_CONFID_AZIMUTH_46 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 332 CAN_DET_CONFID_AZIMUTH_45 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 331 CAN_DET_CONFID_AZIMUTH_44 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 330 CAN_DET_CONFID_AZIMUTH_43 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 329 CAN_DET_CONFID_AZIMUTH_42 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 328 CAN_DET_CONFID_AZIMUTH_41 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 327 CAN_DET_CONFID_AZIMUTH_40 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 325 CAN_DET_CONFID_AZIMUTH_38 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 324 CAN_DET_CONFID_AZIMUTH_37 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 323 CAN_DET_CONFID_AZIMUTH_36 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 322 CAN_DET_CONFID_AZIMUTH_35 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 321 CAN_DET_CONFID_AZIMUTH_34 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 320 CAN_DET_CONFID_AZIMUTH_33 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 319 CAN_DET_CONFID_AZIMUTH_32 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 318 CAN_DET_CONFID_AZIMUTH_31 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 317 CAN_DET_CONFID_AZIMUTH_30 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 316 CAN_DET_CONFID_AZIMUTH_29 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 314 CAN_DET_CONFID_AZIMUTH_27 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 313 CAN_DET_CONFID_AZIMUTH_26 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 312 CAN_DET_CONFID_AZIMUTH_25 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 311 CAN_DET_CONFID_AZIMUTH_24 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 310 CAN_DET_CONFID_AZIMUTH_23 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +EOF + +build_val "22" +build_val "21" +build_val "20" +build_val "19" +build_val "18" + +cat <> ${OUT_FILENAME} +VAL_ 341 CAN_DET_CONFID_AZIMUTH_54 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 340 CAN_DET_CONFID_AZIMUTH_53 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 339 CAN_DET_CONFID_AZIMUTH_52 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 338 CAN_DET_CONFID_AZIMUTH_51 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 337 CAN_DET_CONFID_AZIMUTH_50 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 336 CAN_DET_CONFID_AZIMUTH_49 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 326 CAN_DET_CONFID_AZIMUTH_39 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +VAL_ 315 CAN_DET_CONFID_AZIMUTH_28 3 "Low" 2 "Medium_Low" 1 "Medium_High" 0 "High"; +EOF + +build_val "17" +build_val "16" +build_val "15" +build_val "14" +build_val "13" +build_val "12" +build_val "11" +build_val "10" +build_val "09" +build_val "08" +build_val "07" +build_val "06" +build_val "05" +build_val "03" +build_val "02" + +cat <> ${OUT_FILENAME} +VAL_ 257 CAN_INTERFERENCE_TYPE 2 "Star PD-Like" 1 "Slow FMCW" 0 "No Interference"; +VAL_ 257 CAN_RECOMMEND_UNCONVERGE 1 "Recommended" 0 "Not Recommended"; +VAL_ 257 CAN_RADAR_ALIGN_INCOMPLETE 1 "Alignment Incomplete" 0 "Alignment Completed"; +VAL_ 257 CAN_BLOCKAGE_SIDELOBE 1 "Radar Blockage" 0 "No Radar Blockage"; +VAL_ 257 CAN_BLOCKAGE_MNR 1 "Radar Blockage" 0 "No Radar Blockage"; +VAL_ 257 CAN_RADAR_EXT_COND_NOK 1 "Too high temp or insufficient pw" 0 "External conditions OK"; +VAL_ 257 CAN_RADAR_ALIGN_OUT_RANGE 1 "Radar out of range" 0 "Radar within range"; +VAL_ 257 CAN_RADAR_ALIGN_NOT_START 1 "Radar align not started" 0 "Radar align started"; +VAL_ 257 CAN_RADAR_OVERHEAT_ERROR 1 "Radar overheat condition" 0 "No Overheat"; +VAL_ 257 CAN_RADAR_NOT_OP 1 "Radar not operational" 0 "Radar operational"; +VAL_ 257 CAN_XCVR_OPERATIONAL 1 "On" 0 "Off "; +EOF + +build_val "01" \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/generator/generator.py b/opendbc_repo/opendbc/dbc/generator/generator.py new file mode 100755 index 0000000000..187eabf018 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/generator.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import os +import re +import glob +import subprocess + +generator_path = os.path.dirname(os.path.realpath(__file__)) +opendbc_root = os.path.join(generator_path, '../') +include_pattern = re.compile(r'CM_ "IMPORT (.*?)";\n') +generated_suffix = '_generated.dbc' + + +def read_dbc(src_dir: str, filename: str) -> str: + with open(os.path.join(src_dir, filename), encoding='utf-8') as file_in: + return file_in.read() + + +def create_dbc(src_dir: str, filename: str, output_path: str): + dbc_file_in = read_dbc(src_dir, filename) + + includes = include_pattern.findall(dbc_file_in) + + output_filename = filename.replace('.dbc', generated_suffix) + output_file_location = os.path.join(output_path, output_filename) + + with open(output_file_location, 'w', encoding='utf-8') as dbc_file_out: + dbc_file_out.write('CM_ "AUTOGENERATED FILE, DO NOT EDIT";\n') + + for include_filename in includes: + include_file_header = f'\n\nCM_ "Imported file {include_filename} starts here";\n' + dbc_file_out.write(include_file_header) + + include_file = read_dbc(src_dir, include_filename) + dbc_file_out.write(include_file) + + dbc_file_out.write(f'\nCM_ "{filename} starts here";\n') + + core_dbc = include_pattern.sub('', dbc_file_in) + dbc_file_out.write(core_dbc) + + +def create_all(output_path: str): + # clear out old DBCs + for f in glob.glob(f"{output_path}/*{generated_suffix}"): + os.remove(f) + + # run python generator scripts first + for f in glob.glob(f"{generator_path}/*/*.py"): + subprocess.check_call(f) + + for src_dir, _, filenames in os.walk(generator_path): + if src_dir == generator_path: + continue + + #print(src_dir) + for filename in filenames: + if filename.startswith('_') or not filename.endswith('.dbc'): + continue + + #print(filename) + create_dbc(src_dir, filename, output_path) + + +if __name__ == "__main__": + create_all(opendbc_root) diff --git a/opendbc_repo/opendbc/dbc/generator/gm/_community.dbc b/opendbc_repo/opendbc/dbc/generator/gm/_community.dbc new file mode 100644 index 0000000000..d8855b3594 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/gm/_community.dbc @@ -0,0 +1,15 @@ +BO_ 512 GAS_COMMAND: 6 NEO + SG_ GAS_COMMAND : 7|16@0+ (0.125677,-75.909) [0|1] "" INTERCEPTOR + SG_ GAS_COMMAND2 : 23|16@0+ (0.251976,-76.601) [0|1] "" INTERCEPTOR + SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR + SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" INTERCEPTOR + SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" INTERCEPTOR + +BO_ 513 GAS_SENSOR: 6 INTERCEPTOR + SG_ INTERCEPTOR_GAS : 7|16@0+ (0.125677,-75.909) [0|1] "" NEO + SG_ INTERCEPTOR_GAS2 : 23|16@0+ (0.251976,-76.601) [0|1] "" NEO + SG_ STATE : 39|4@0+ (1,0) [0|15] "" NEO + SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" NEO + SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" NEO + +VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ; diff --git a/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc b/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc new file mode 100644 index 0000000000..e9a469e090 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/gm/gm_global_a_powertrain.dbc @@ -0,0 +1,352 @@ + +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: K16_BECM K73_TCIC K9_BCM K43_PSCM K17_EBCM K20_ECM K114B_HPCM NEO K124_ASCM EPB +VAL_TABLE_ TurnSignals 2 "Right Turn" 1 "Left Turn" 0 "None" ; +VAL_TABLE_ Intellibeam 1 "Active" 0 "Inactive" ; +VAL_TABLE_ HighBeamsActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ HighBeamsTemporary 1 "Active" 0 "Inactive" ; +VAL_TABLE_ ACCLeadCar 1 "Present" 0 "Not Present" ; +VAL_TABLE_ ACCCmdActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ BrakePedalPressed 1 "Pressed" 0 "Depressed" ; +VAL_TABLE_ DistanceButton 1 "Active" 0 "Inactive" ; +VAL_TABLE_ LKAButton 1 "Active" 0 "Inactive" ; +VAL_TABLE_ ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ; +VAL_TABLE_ DriveModeButton 1 "Active" 0 "Inactive" ; +VAL_TABLE_ PRNDL 3 "Reverse" 2 "Drive" 1 "Neutral" 0 "Park" ; +VAL_TABLE_ ESPButton 1 "Active" 0 "Inactive" ; +VAL_TABLE_ DoorStatus 1 "Opened" 0 "Closed" ; +VAL_TABLE_ SeatBeltStatus 1 "Latched" 0 "Unlatched" ; +VAL_TABLE_ LKASteeringCmdActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ ACCGapLevel 3 "Far" 2 "Med" 1 "Near" 0 "Inactive" ; +VAL_TABLE_ GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ; +VAL_TABLE_ GasRegenCmdActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ LKATorqueDeliveredStatus 3 "Failed" 2 "Temp. Limited" 1 "Active" 0 "Inactive" ; +VAL_TABLE_ HandsOffSWDetectionStatus 1 "Hands On" 0 "Hands Off" ; +VAL_TABLE_ HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ; + + +BO_ 189 EBCMRegenPaddle: 7 K17_EBCM + SG_ RegenPaddle : 7|4@0+ (1,0) [0|0] "" NEO + +BO_ 190 ECMAcceleratorPos: 6 K20_ECM + SG_ BrakePedalPos : 15|8@0+ (1,0) [0|0] "sticky" NEO + SG_ GasPedalAndAcc : 23|8@0+ (1,0) [0|0] "" NEO + +BO_ 201 ECMEngineStatus: 8 K20_ECM + SG_ EngineTPS : 39|8@0+ (0.392156863,0) [0|100.000000065] "%" NEO + SG_ EngineRPM : 15|16@0+ (0.25,0) [0|0] "RPM" NEO + SG_ CruiseMainOn : 29|1@0+ (1,0) [0|1] "" NEO + SG_ BrakePressed : 40|1@0+ (1,0) [0|1] "" NEO + SG_ Standstill : 2|1@0+ (1,0) [0|1] "" NEO + SG_ CruiseActive : 31|2@0+ (1,0) [0|3] "" NEO + +BO_ 209 EBCMBrakePedalSensors: 7 K17_EBCM + SG_ Counter1 : 7|2@0+ (1,0) [0|3] "" XXX + SG_ Counter2 : 23|2@0+ (1,0) [0|3] "" XXX + SG_ BrakePedalPosition1 : 5|14@0+ (1,0) [0|16383] "" XXX + SG_ BrakePedalPosition2 : 21|14@0- (-1,0) [0|16383] "" XXX + SG_ BrakeNormalized1 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ BrakeNormalized2 : 47|8@0- (-1,0) [0|255] "" XXX + +BO_ 241 EBCMBrakePedalPosition: 6 K17_EBCM + SG_ BrakePressed : 1|1@0+ (1,0) [0|1] "" XXX + SG_ BrakePedalPosition : 15|8@0+ (1,0) [0|255] "" NEO + +BO_ 298 BCMDoorBeltStatus: 8 K9_BCM + SG_ RearLeftDoor : 8|1@0+ (1,0) [0|0] "" NEO + SG_ FrontLeftDoor : 9|1@0+ (1,0) [0|0] "" NEO + SG_ FrontRightDoor : 10|1@0+ (1,0) [0|0] "" NEO + SG_ RearRightDoor : 23|1@0+ (1,0) [0|0] "" NEO + SG_ LeftSeatBelt : 12|1@0+ (1,0) [0|0] "" NEO + SG_ RightSeatBelt : 53|1@0+ (1,0) [0|0] "" NEO + +BO_ 309 ECMPRDNL: 8 K20_ECM + SG_ PRNDL : 2|3@0+ (1,0) [0|0] "" NEO + SG_ ESPButton : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 320 BCMTurnSignals: 3 K9_BCM + SG_ TurnSignals : 19|2@0+ (1,0) [0|0] "" NEO + SG_ Intellibeam : 13|1@0+ (1,0) [0|1] "" XXX + SG_ HighBeamsActive : 7|1@0+ (1,0) [0|1] "" XXX + SG_ HighBeamsTemporary : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 322 BCMBlindSpotMonitor: 7 K9_BCM + SG_ LeftBSM : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RightBSM : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 328 PSCM_148: 1 K43_PSCM + +BO_ 381 ESPStatus: 6 K20_ECM + SG_ TractionControlOn : 5|1@0+ (1,0) [0|0] "" NEO + SG_ MSG17D_AccPower : 35|12@0- (1,0) [0|0] "" NEO + +BO_ 384 ASCMLKASteeringCmd: 4 NEO + SG_ RollingCounter : 5|2@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmdChecksum : 19|12@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmdActive : 3|1@0+ (1,0) [0|0] "" NEO + SG_ LKASteeringCmd : 2|11@0- (1,0) [0|0] "" NEO + +BO_ 388 PSCMStatus: 8 K43_PSCM + SG_ HandsOffSWDetectionMode : 20|2@0+ (1,0) [0|3] "" NEO + SG_ HandsOffSWlDetectionStatus : 21|1@0+ (1,0) [0|1] "" NEO + SG_ LKATorqueDeliveredStatus : 5|3@0+ (1,0) [0|7] "" NEO + SG_ LKADriverAppldTrq : 50|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO + SG_ LKATorqueDelivered : 18|11@0- (0.01,0) [0|1] "" NEO + SG_ LKATotalTorqueDelivered : 2|11@0- (0.01,0) [-10.24|10.23] "Nm" NEO + SG_ RollingCounter : 38|4@0+ (1,0) [0|15] "" XXX + SG_ PSCMStatusChecksum : 33|10@0+ (1,0) [0|1023] "" XXX + +BO_ 417 AcceleratorPedal: 7 XXX + SG_ AcceleratorPedal : 55|8@0+ (1,0) [0|0] "" NEO + +BO_ 451 GasAndAcc: 8 XXX + SG_ GasPedalAndAcc2 : 55|8@0+ (1,0) [0|0] "" NEO + +BO_ 452 AcceleratorPedal2: 8 XXX + SG_ CruiseState : 15|3@0+ (1,0) [0|7] "" NEO + SG_ AcceleratorPedal2 : 47|8@0+ (1,0) [0|0] "" NEO + +BO_ 481 ASCMSteeringButton: 7 K124_ASCM + SG_ DistanceButton : 22|1@0+ (1,0) [0|0] "" NEO + SG_ LKAButton : 23|1@0+ (1,0) [0|0] "" NEO + SG_ ACCAlwaysOne : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ACCButtons : 46|3@0+ (1,0) [0|0] "" NEO + SG_ DriveModeButton : 39|1@0+ (1,0) [0|1] "" XXX + SG_ RollingCounter : 33|2@0+ (1,0) [0|3] "" NEO + SG_ SteeringButtonChecksum : 43|12@0+ (1,0) [0|255] "" NEO + +BO_ 485 PSCMSteeringAngle: 8 K43_PSCM + SG_ SteeringWheelAngle : 15|16@0- (0.0625,0) [-2047|2047] "deg" NEO + SG_ SteeringWheelRate : 27|12@0- (1,0) [-2047|2047] "deg/s" NEO + +BO_ 489 EBCMVehicleDynamic: 8 K17_EBCM + SG_ BrakePedalPressed : 6|1@0+ (1,0) [0|0] "" NEO + SG_ LateralAcceleration : 3|10@0- (0.161,0) [-2047|2047] "m/s2" NEO + SG_ YawRate : 35|12@0- (0.625,0) [0|1] "" NEO + SG_ YawRate2 : 51|12@0- (0.0625,0) [-2047|2047] "grad/s" NEO + +BO_ 352 BCMImmobilizer: 5 K9_BCM + SG_ ImmobilizerInfo : 7|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 497 BCMGeneralPlatformStatus: 8 K9_BCM + SG_ SystemPowerMode : 1|2@0+ (1,0) [0|3] "" XXX + SG_ SystemBackUpPowerMode : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ParkBrakeSwActive : 36|1@0+ (1,0) [0|3] "" XXX + +BO_ 500 SportMode: 6 XXX + SG_ SnowIceMode : 9|1@0+ (1,0) [0|1] "" XXX + SG_ SportMode : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 501 ECMPRDNL2: 8 K20_ECM + SG_ TransmissionState : 48|4@1+ (1,0) [0|7] "" NEO + SG_ PRNDL2 : 27|4@0+ (1,0) [0|255] "" NEO + SG_ ManualMode : 41|1@0+ (1,0) [0|1] "" NEO + +BO_ 532 BRAKE_RELATED: 6 XXX + SG_ UserBrakePressure : 0|9@0+ (1,0) [0|511] "" XXX + +BO_ 560 EPBStatus: 8 EPB + SG_ EPBClosed : 12|1@0+ (1,0) [0|1] "" NEO + +BO_ 562 EBCMFrictionBrakeStatus: 8 K17_EBCM + SG_ FrictionBrakeUnavailable : 46|1@0+ (1,0) [0|1] "" XXX + +BO_ 608 SPEED_RELATED: 8 XXX + SG_ RollingCounter : 5|2@0+ (1,0) [0|0] "" XXX + SG_ ClusterSpeed : 31|8@0+ (1,0) [0|0] "" XXX + +BO_ 711 BECMBatteryVoltageCurrent: 6 K17_EBCM + SG_ HVBatteryVoltage : 31|12@0+ (0.125,0) [0|511.875] "V" NEO + SG_ HVBatteryCurrent : 12|13@0- (0.15,0) [-614.4|614.25] "A" NEO + +BO_ 715 ASCMGasRegenCmd: 8 K124_ASCM + SG_ GasRegenAccType : 15|2@0+ (1,0) [0|3] "" NEO + SG_ GasRegenChecksum : 32|25@0+ (1,0) [0|0] "" NEO + SG_ GasRegenFullStopActive : 13|1@0+ (1,0) [0|0] "" NEO + SG_ GasRegenCmdActive : 0|1@0+ (1,0) [0|0] "" NEO + SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" NEO + SG_ GasRegenCmd : 10|19@0+ (0.125,-22534) [-22534|43001.875] "Nm" NEO + +BO_ 717 ASCM_2CD: 5 K124_ASCM + +BO_ 761 BRAKE_RELATED_2: 7 XXX + SG_ UserBrakePressure2 : 47|9@0+ (1,0) [0|511] "" XXX + +BO_ 789 EBCMFrictionBrakeCmd: 5 K124_ASCM + SG_ RollingCounter : 33|2@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeMode : 7|4@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeChecksum : 23|16@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeCmd : 3|12@0- (1,0) [0|0] "" NEO + +BO_ 800 AEBCmd: 6 K124_ASCM + SG_ RollingCounter : 5|2@0+ (1,0) [0|3] "" NEO + SG_ AEBChecksum : 27|20@0+ (1,0) [0|0] "" NEO + SG_ AEBCmdActive : 3|1@1+ (1,0) [0|1] "" NEO + SG_ AEBCmd : 2|11@0+ (1,0) [0|0] "" NEO + SG_ AEBCmd2 : 23|8@0+ (1,0) [0|0] "" NEO + +BO_ 810 TCICOnStarGPSPosition: 8 K73_TCIC + SG_ GPSLongitude : 39|32@0+ (1,-2147483648) [0|0] "milliarcsecond" NEO + SG_ GPSLatitude : 7|32@0+ (1,0) [0|0] "milliarcsecond" NEO + +BO_ 840 EBCMWheelSpdFront: 5 K17_EBCM + SG_ FLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO + SG_ FRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO + +BO_ 842 EBCMWheelSpdRear: 5 K17_EBCM + SG_ RLWheelSpd : 7|16@0+ (0.0311,0) [0|255] "km/h" NEO + SG_ RRWheelSpd : 23|16@0+ (0.0311,0) [0|255] "km/h" NEO + SG_ RRWheelDir : 34|3@0+ (1,0) [0|7] "" NEO + SG_ RLWheelDir : 37|3@0+ (1,0) [0|7] "" NEO + +BO_ 869 ASCM_365: 4 K124_ASCM + +BO_ 880 ASCMActiveCruiseControlStatus: 6 K124_ASCM + SG_ ACCCruiseState : 8|3@1+ (1,0) [0|7] "" XXX + SG_ ACCLeadCar : 44|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCAlwaysOne2 : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCAlwaysOne : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCSpeedSetpoint : 19|12@0+ (0.0625,0) [0|255.9375] "km/h" NEO + SG_ ACCGapLevel : 21|2@0+ (1,0) [0|0] "" NEO + SG_ ACCResumeButton : 1|1@0+ (1,0) [0|0] "" NEO + SG_ ACCCmdActive : 23|1@0+ (1,0) [0|0] "" NEO + SG_ FCWAlert : 41|2@0+ (1,0) [0|3] "" XXX + +BO_ 967 EVDriveMode: 4 XXX + SG_ SinglePedalModeActive : 7|1@0+ (1,0) [0|1] "" XXX + SG_ SinglePedalModeRisingEdge : 21|1@0+ (1,0) [0|1] "" XXX + SG_ SinglePedalModeFallingEdge : 22|1@0+ (1,0) [0|1] "" XXX + +BO_ 977 ECMCruiseControl: 8 K20_ECM + SG_ CruiseActive : 39|1@0+ (1,0) [0|3] "" NEO + SG_ CruiseSetSpeed : 19|12@0+ (0.0625,0) [0|0] "km/h" NEO + +BO_ 1001 ECMVehicleSpeed: 8 K20_ECM + SG_ VehicleSpeed : 7|16@0+ (0.01,0) [0|0] "mph" NEO + SG_ VehicleSpeedLeft : 39|16@0+ (0.01,0) [0|0] "mph" NEO + +BO_ 1033 ASCMKeepAlive: 7 NEO + SG_ ASCMKeepAliveAllZero : 7|56@0+ (1,0) [0|0] "" NEO + +BO_ 1034 ASCM_40A: 7 K124_ASCM + +BO_ 1217 ECMEngineCoolantTemp: 8 K20_ECM + SG_ EngineCoolantTemp : 23|8@0+ (1,-40) [0|0] "C" NEO + +BO_ 1249 VIN_Part2: 8 K20_ECM + SG_ VINPart2 : 7|64@0+ (1,0) [0|0] "" NEO + +BO_ 1296 ASCM_510: 4 K124_ASCM + +BO_ 1300 VIN_Part1: 8 K20_ECM + SG_ VINPart1 : 7|64@0+ (1,0) [0|0] "" NEO + +BO_ 1912 PSCM_778: 8 K43_PSCM + +BO_ 1930 ASCM_78A: 7 K124_ASCM + +BO_TX_BU_ 384 : K124_ASCM,NEO; +BO_TX_BU_ 880 : NEO,K124_ASCM; +BO_TX_BU_ 1033 : K124_ASCM,NEO; +BO_TX_BU_ 715 : NEO,K124_ASCM; +BO_TX_BU_ 789 : NEO,K124_ASCM; +BO_TX_BU_ 800 : NEO,K124_ASCM; + + +CM_ BU_ K16_BECM "Battery Energy Control Module"; +CM_ BU_ K73_TCIC "Telematics Communication Control Module"; +CM_ BU_ K9_BCM "Body Control Module"; +CM_ BU_ K43_PSCM "Power Steering Control Module"; +CM_ BU_ K17_EBCM "Electronic Brake Control Module"; +CM_ BU_ K20_ECM "Engine Control Module"; +CM_ BU_ K114B_HPCM "Hybrid Powertrain Control Module"; +CM_ BU_ NEO "Comma NEO"; +CM_ BU_ K124_ASCM "Active Safety Control Module"; +CM_ SG_ 381 MSG17D_AccPower "Need to investigate"; +CM_ BO_ 190 "Length varies from 6 to 8 bytes by car"; +CM_ SG_ 190 GasPedalAndAcc "ACC baseline is 62"; +CM_ SG_ 322 LeftBSM "For some cars, this can only be when the blinker is also active"; +CM_ SG_ 322 RightBSM "For some cars, this can only be when the blinker is also active"; +CM_ SG_ 352 ImmobilizerInfo "Non-zero when ignition or accessory mode"; +CM_ SG_ 451 GasPedalAndAcc2 "ACC baseline is 62"; +CM_ SG_ 481 ACCAlwaysOne "Usually 1 if the car is equipped with ACC"; +CM_ SG_ 562 FrictionBrakeUnavailable "1 when ACC brake control is unavailable. Stays high if brake command messages are blocked for a period of time"; +CM_ SG_ 497 SystemPowerMode "Describes ignition"; +CM_ SG_ 497 SystemBackUpPowerMode "Describes ignition + preconditioning mode, noisy"; +CM_ SG_ 501 PRNDL2 "When ManualMode is Active, Value is 13=L1 12=L2 11=L3 ... 5=Full 70kW Paddle Regen Unlocked for Gen2 Bolts 4=L10"; +CM_ SG_ 532 UserBrakePressure "can be lower than other brake position signals when the brakes are pre-filled from ACC braking and the user presses on the brakes. user-only pressure?"; +CM_ SG_ 608 ClusterSpeed "Cluster speed signal seems to match dash on newer cars, but is a lower rate and can be noisier."; +CM_ SG_ 761 UserBrakePressure2 "Similar to BRAKE_RELATED->UserBrakePressure"; +CM_ SG_ 1001 VehicleSpeed "Spinouts show here on 2wd. Speed derived from right front wheel (drive tire)"; +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "BusType" "CAN"; +BA_ "ProtocolType" "GMLAN"; +BA_ "UseGMParameterIDs" 0; +VAL_ 497 SystemPowerMode 3 "Crank Request" 2 "Run" 1 "Accessory" 0 "Off"; +VAL_ 497 SystemBackUpPowerMode 3 "Crank Request" 2 "Run" 1 "Accessory" 0 "Off"; +VAL_ 481 DistanceButton 1 "Active" 0 "Inactive" ; +VAL_ 481 LKAButton 1 "Active" 0 "Inactive" ; +VAL_ 481 ACCButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ; +VAL_ 481 DriveModeButton 1 "Active" 0 "Inactive" ; +VAL_ 452 CruiseState 4 "Standstill" 3 "Faulted" 1 "Active" 0 "Off" ; +VAL_ 309 PRNDL 3 "R" 2 "D" 1 "N" 0 "P" ; +VAL_ 309 ESPButton 1 "Active" 0 "Inactive" ; +VAL_ 384 LKASteeringCmdActive 1 "Active" 0 "Inactive" ; +VAL_ 842 RRWheelDir 0 "Stationary" 1 "Forward" 2 "Reverse" 3 "Unsupported" 4 "Fault"; +VAL_ 842 RLWheelDir 0 "Stationary" 1 "Forward" 2 "Reverse" 3 "Unsupported" 4 "Fault"; +VAL_ 880 ACCCruiseState 2 "Adaptive" 3 "Adaptive" 4 "Non-adaptive" 5 "Non-adaptive" ; +VAL_ 880 ACCLeadCar 1 "Present" 0 "Not Present" ; +VAL_ 880 ACCGapLevel 3 "Far" 2 "Med" 1 "Near" 0 "Inactive" ; +VAL_ 880 ACCResumeButton 1 "Pressed" 0 "Depressed" ; +VAL_ 880 ACCCmdActive 1 "Active" 0 "Inactive" ; +VAL_ 388 HandsOffSWDetectionMode 2 "Failed" 1 "Enabled" 0 "Disabled" ; +VAL_ 388 HandsOffSWlDetectionStatus 1 "Hands On" 0 "Hands Off" ; +VAL_ 388 LKATorqueDeliveredStatus 3 "Failed" 2 "Temp. Limited" 1 "Active" 0 "Inactive" ; +VAL_ 489 BrakePedalPressed 1 "Pressed" 0 "Depressed" ; +VAL_ 715 GasRegenCmdActiveInv 1 "Inactive" 0 "Active" ; +VAL_ 715 GasRegenCmdActive 1 "Active" 0 "Inactive" ; +VAL_ 320 Intellibeam 1 "Active" 0 "Inactive" ; +VAL_ 320 HighBeamsActive 1 "Active" 0 "Inactive" ; +VAL_ 320 HighBeamsTemporary 1 "Active" 0 "Inactive" ; +VAL_ 501 PRNDL2 7 "L3" 6 "L" 5 "L2" 4 "D" 3 "N" 2 "R" 1 "P" 0 "Shifting"; +VAL_ 501 TransmissionState 11 "Shifting" 10 "Reverse" 9 "Forward" 8 "Disengaged"; +VAL_ 501 ManualMode 1 "Active" 0 "Inactive" diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc new file mode 100644 index 0000000000..d5171fdefa --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_2018.dbc @@ -0,0 +1,220 @@ +BO_ 228 STEERING_CONTROL: 5 EON + SG_ STEER_TORQUE : 7|16@0- (1,0) [-4096|4096] "" EPS + SG_ DRIVER_OVERRIDE : 17|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS + SG_ CONTROL_STATE : 26|3@0+ (1,0) [0|7] "" XXX + SG_ CHECKSUM : 35|4@0+ (1,0) [0|15] "" EPS + SG_ COUNTER : 37|2@0+ (1,0) [0|3] "" EPS + SG_ STEER_DOWN_TO_ZERO : 38|1@0+ (1,0) [0|1] "" EPS + SG_ HAPTIC_WARNING : 39|1@0+ (1,0) [0|1] "" XXX + +BO_ 229 BOSCH_SUPPLEMENTAL_1: 8 XXX + SG_ SET_ME_X04 : 0|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_X80 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_X10 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 232 BRAKE_HOLD: 7 XXX + SG_ XMISSION_SPEED : 7|14@0- (1,0) [1|0] "" XXX + SG_ COMPUTER_BRAKE : 39|16@0+ (1,0) [0|0] "" XXX + SG_ COMPUTER_BRAKE_REQUEST : 29|1@0+ (1,0) [0|0] "" XXX + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 51|4@0+ (1,0) [0|15] "" XXX + +BO_ 399 STEER_STATUS: 7 EPS + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_ANGLE_RATE : 23|16@0- (-0.1,0) [-31000|31000] "deg/s" EON + SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON + SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON + SG_ STEER_CONFIG_INDEX : 43|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 51|4@0+ (1,0) [0|15] "" EON + +BO_ 446 BRAKE_MODULE: 3 VSA + SG_ BRAKE_PRESSED : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_FAULT : 22|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 21|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 19|4@0+ (1,0) [0|15] "" XXX + +BO_ 506 LEGACY_BRAKE_COMMAND: 8 ADAS + SG_ CHIME : 40|8@1+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 545 ECON_STATUS: 6 SCM + SG_ ECON_ON : 23|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_MODE : 37|2@0+ (1,0) [0|3] "" XXX + SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" BDY + SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" BDY + +BO_ 576 LEFT_LANE_LINE_1: 8 CAM + SG_ LINE_DISTANCE_VISIBLE : 39|9@0+ (1,0) [0|1] "" XXX + SG_ LINE_PROBABILITY : 46|6@0+ (0.015625,0) [0|1] "" XXX + SG_ LINE_OFFSET : 23|12@0+ (0.004,-8.192) [0|1] "Meters" XXX + SG_ LINE_ANGLE : 7|12@0+ (0.0005,-1.024) [0|1] "" XXX + SG_ FRAME_INDEX : 8|4@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 577 LEFT_LANE_LINE_2: 8 CAM + SG_ LINE_FAR_EDGE_POSITION : 55|8@0+ (1,-128) [0|1] "" XXX + SG_ LINE_SOLID : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_DASHED : 14|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_CURVATURE : 23|12@0+ (0.00001,-0.02048) [0|1] "" XXX + SG_ LINE_PARAMETER : 39|12@0+ (1,0) [0|1] "" XXX + SG_ FRAME_INDEX : 7|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 579 RIGHT_LANE_LINE_1: 8 CAM + SG_ LINE_DISTANCE_VISIBLE : 39|9@0+ (1,0) [0|1] "" XXX + SG_ LINE_PROBABILITY : 46|6@0+ (0.015625,0) [0|1] "" XXX + SG_ LINE_OFFSET : 23|12@0+ (0.004,-8.192) [0|1] "Meters" XXX + SG_ LINE_ANGLE : 7|12@0+ (0.0005,-1.024) [0|1] "" XXX + SG_ FRAME_INDEX : 8|4@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 580 RIGHT_LANE_LINE_2: 8 CAM + SG_ LINE_FAR_EDGE_POSITION : 55|8@0+ (1,-128) [0|1] "" XXX + SG_ LINE_SOLID : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_DASHED : 14|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_CURVATURE : 23|12@0+ (0.00001,-0.02048) [0|1] "" XXX + SG_ LINE_PARAMETER : 39|12@0+ (1,0) [0|1] "" XXX + SG_ FRAME_INDEX : 7|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 582 ADJACENT_LEFT_LANE_LINE_1: 8 CAM + SG_ LINE_DISTANCE_VISIBLE : 39|9@0+ (1,0) [0|1] "" XXX + SG_ LINE_PROBABILITY : 46|6@0+ (0.015625,0) [0|1] "" XXX + SG_ LINE_OFFSET : 23|12@0+ (0.004,-8.192) [0|1] "Meters" XXX + SG_ LINE_ANGLE : 7|12@0+ (0.0005,-1.024) [0|1] "" XXX + SG_ FRAME_INDEX : 8|4@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 583 ADJACENT_LEFT_LANE_LINE_2: 8 CAM + SG_ LINE_FAR_EDGE_POSITION : 55|8@0+ (1,-128) [0|1] "" XXX + SG_ LINE_SOLID : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_DASHED : 14|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_CURVATURE : 23|12@0+ (0.00001,-0.02048) [0|1] "" XXX + SG_ LINE_PARAMETER : 39|12@0+ (1,0) [0|1] "" XXX + SG_ FRAME_INDEX : 7|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 585 ADJACENT_RIGHT_LANE_LINE_1: 8 CAM + SG_ LINE_DISTANCE_VISIBLE : 39|9@0+ (1,0) [0|1] "" XXX + SG_ LINE_PROBABILITY : 46|6@0+ (0.015625,0) [0|1] "" XXX + SG_ LINE_OFFSET : 23|12@0+ (0.004,-8.192) [0|1] "Meters" XXX + SG_ LINE_ANGLE : 7|12@0+ (0.0005,-1.024) [0|1] "" XXX + SG_ FRAME_INDEX : 8|4@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 586 ADJACENT_RIGHT_LANE_LINE_2: 8 CAM + SG_ LINE_FAR_EDGE_POSITION : 55|8@0+ (1,-128) [0|1] "" XXX + SG_ LINE_SOLID : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_DASHED : 14|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_CURVATURE : 23|12@0+ (0.00001,-0.02048) [0|1] "" XXX + SG_ LINE_PARAMETER : 39|12@0+ (1,0) [0|1] "" XXX + SG_ FRAME_INDEX : 7|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|1] "" XXX + +BO_ 662 SCM_BUTTONS: 4 SCM + SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON + SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON + +BO_ 806 SCM_FEEDBACK: 8 SCM + SG_ DRIVERS_DOOR_OPEN : 17|1@0+ (1,0) [0|1] "" XXX + SG_ REVERSE_LIGHT : 18|1@0+ (1,0) [0|1] "" EON + SG_ PARKING_BRAKE_ON : 29|1@0+ (1,0) [0|1] "" XXX + SG_ MAIN_ON : 28|1@0+ (1,0) [0|1] "" EON + SG_ RIGHT_BLINKER : 27|1@0+ (1,0) [0|1] "" EON + SG_ LEFT_BLINKER : 26|1@0+ (1,0) [0|1] "" EON + SG_ CMBS_STATES : 22|2@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 927 RADAR_HUD: 8 RADAR + SG_ ZEROS_BOH : 7|10@0+ (1,0) [0|127] "" BDY + SG_ CMBS_OFF : 12|1@0+ (1,0) [0|1] "" BDY + SG_ RESUME_INSTRUCTION : 21|1@0+ (1,0) [0|1] "" XXX + SG_ SET_TO_1 : 13|1@0+ (1,0) [0|1] "" BDY + SG_ ZEROS_BOH2 : 11|4@0+ (1,0) [0|1] "" XXX + SG_ APPLY_BRAKES_FOR_CANC : 23|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ALERTS : 20|5@0+ (1,0) [0|1] "" BDY + SG_ SET_TO_0 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ HUD_LEAD : 40|1@0+ (1,0) [0|1] "" XXX + SG_ SET_TO_64 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ LEAD_DISTANCE : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ZEROS_BOH3 : 47|7@0+ (1,0) [0|127] "" XXX + SG_ ZEROS_BOH4 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 13274 LKAS_HUD_A: 5 ADAS + SG_ LKAS_READY : 0|1@0+ (1,0) [0|127] "" BDY + SG_ LKAS_STATE_CHANGE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ CAM_TEMP_HIGH : 7|1@0+ (1,0) [0|255] "" BDY + SG_ DASHED_LANES : 14|1@0+ (1,0) [0|1] "" BDY + SG_ DTC : 13|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_PROBLEM : 12|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_OFF : 11|1@0+ (1,0) [0|1] "" BDY + SG_ SOLID_LANES : 10|1@0+ (1,0) [0|1] "" BDY + SG_ CLEAN_WINDSHIELD : 26|1@0+ (1,0) [0|1] "" BDY + SG_ STEERING_REQUIRED : 8|1@0+ (1,0) [0|1] "" BDY + SG_ BEEP : 17|2@0+ (1,0) [0|1] "" BDY + SG_ RDM_PROBLEM : 21|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD : 9|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD_2 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_OFF : 27|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_ON : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_ON_2 : 28|1@0+ (1,0) [0|1] "" BDY + SG_ LANE_ASSIST_BEEP_OFF : 30|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 35|4@0+ (1,0) [0|15] "" BDY + SG_ COUNTER : 37|2@0+ (1,0) [0|3] "" BDY + +BO_ 13275 LKAS_HUD_B: 8 ADAS + SG_ LKAS_READY : 0|1@0+ (1,0) [0|127] "" BDY + SG_ LKAS_STATE_CHANGE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ CAM_TEMP_HIGH : 7|1@0+ (1,0) [0|255] "" BDY + SG_ DASHED_LANES : 14|1@0+ (1,0) [0|1] "" BDY + SG_ DTC : 13|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_PROBLEM : 12|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_OFF : 11|1@0+ (1,0) [0|1] "" BDY + SG_ SOLID_LANES : 10|1@0+ (1,0) [0|1] "" BDY + SG_ CLEAN_WINDSHIELD : 26|1@0+ (1,0) [0|1] "" BDY + SG_ STEERING_REQUIRED : 8|1@0+ (1,0) [0|1] "" BDY + SG_ BEEP : 17|2@0+ (1,0) [0|1] "" BDY + SG_ RDM_PROBLEM : 21|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD : 9|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD_2 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_OFF : 27|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_ON : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_ON_2 : 28|1@0+ (1,0) [0|1] "" BDY + SG_ LANE_ASSIST_BEEP_OFF : 30|1@0+ (1,0) [0|1] "" XXX + SG_ LANE_LINES : 36|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" BDY + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY + +CM_ SG_ 228 DRIVER_OVERRIDE "Appears to acknowledge STEER_STATUS.NO_TORQUE_ALERT_1"; +CM_ SG_ 576 LINE_DISTANCE_VISIBLE "Length of line visible, undecoded"; +CM_ SG_ 577 LINE_FAR_EDGE_POSITION "Appears to be a measure of line thickness, indicates location of the portion of the line furthest from the car, undecoded"; +CM_ SG_ 577 LINE_PARAMETER "Unclear if this is low quality line curvature rate or if this is something else, but it is correlated with line curvature, undecoded"; +CM_ SG_ 577 LINE_DASHED "1 = line is dashed"; +CM_ SG_ 577 LINE_SOLID "1 = line is solid"; + +VAL_ 228 CONTROL_STATE 0 "init" 1 "standby" 2 "lka_active" 3 "driver_override" 5 "rdm_active"; +VAL_ 399 STEER_STATUS 6 "tmp_fault" 5 "fault_1" 4 "no_torque_alert_2" 3 "low_speed_lockout" 2 "no_torque_alert_1" 0 "normal"; +VAL_ 662 CRUISE_BUTTONS 7 "tbd" 6 "tbd" 5 "tbd" 4 "accel_res" 3 "decel_set" 2 "cancel" 1 "main" 0 "none" ; +VAL_ 662 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none" ; +VAL_ 806 CMBS_STATES 3 "pressed" 0 "released" ; +VAL_ 862 SPEED_LIMIT_SIGN 97 "SPEED_LIMIT_5" 98 "SPEED_LIMIT_10" 99 "SPEED_LIMIT_15" 100 "SPEED_LIMIT_20" 101 "SPEED_LIMIT_25" 102 "SPEED_LIMIT_30" 103 "SPEED_LIMIT_35" 104 "SPEED_LIMIT_40" 105 "SPEED_LIMIT_45" 106 "SPEED_LIMIT_50" 107 "SPEED_LIMIT_55" 108 "SPEED_LIMIT_60" 109 "SPEED_LIMIT_65" 110 "SPEED_LIMIT_70" 111 "SPEED_LIMIT_75" 112 "SPEED_LIMIT_80" 113 "SPEED_LIMIT_85" 125 "SPEED_LIMIT_NA" 0 "STOP_SIGN"; +VAL_ 862 ROAD_SIGN 0 "NO_SIGN" 89 "STOP_SIGN"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_bosch_radar_acc.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_radar_acc.dbc new file mode 100644 index 0000000000..0a7f75f797 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_radar_acc.dbc @@ -0,0 +1,30 @@ +BO_ 479 ACC_CONTROL: 8 EON + SG_ SET_TO_0 : 20|5@0+ (1,0) [0|1] "" XXX + SG_ CONTROL_ON : 23|3@0+ (1,0) [0|5] "" XXX + SG_ GAS_COMMAND : 7|16@0- (1,0) [0|0] "" XXX + SG_ ACCEL_COMMAND : 31|11@0- (0.01,0) [0|0] "m/s2" XXX + SG_ BRAKE_LIGHTS : 62|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_REQUEST : 34|1@0+ (1,0) [0|1] "" XXX + SG_ STANDSTILL : 35|1@0+ (1,0) [0|1] "" XXX + SG_ STANDSTILL_RELEASE : 36|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_STATUS : 33|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_BRAKING : 47|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_PREPARE : 43|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 495 ACC_CONTROL_ON: 8 XXX + SG_ SET_TO_75 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SET_TO_30 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ZEROS_BOH : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ZEROS_BOH2 : 47|16@0+ (1,0) [0|255] "" XXX + SG_ SET_TO_FF : 15|8@0+ (1,0) [0|255] "" XXX + SG_ SET_TO_3 : 6|7@0+ (1,0) [0|4095] "" XXX + SG_ CONTROL_ON : 7|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +CM_ SG_ 479 CONTROL_ON "Set to 5 when car is being controlled"; +CM_ SG_ 479 AEB_STATUS "set for the duration of AEB event"; +CM_ SG_ 479 AEB_BRAKING "set when braking is commanded during AEB event"; +CM_ SG_ 479 AEB_PREPARE "set 1s before AEB"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_bosch_standstill.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_standstill.dbc new file mode 100644 index 0000000000..2980097935 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_bosch_standstill.dbc @@ -0,0 +1,7 @@ +BO_ 432 STANDSTILL: 7 VSA + SG_ CONTROLLED_STANDSTILL : 0|1@0+ (1,0) [0|1] "" EON + SG_ WHEELS_MOVING : 12|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_ERROR_1 : 11|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_ERROR_2 : 9|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] "" EON diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_community.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_community.dbc new file mode 100644 index 0000000000..8be69203ef --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_community.dbc @@ -0,0 +1,15 @@ +BO_ 512 GAS_COMMAND: 6 EON + SG_ GAS_COMMAND : 7|16@0+ (0.253984064,-83.3) [0|1] "" INTERCEPTOR + SG_ GAS_COMMAND2 : 23|16@0+ (0.126992032,-83.3) [0|1] "" INTERCEPTOR + SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR + SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" INTERCEPTOR + SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" INTERCEPTOR + +BO_ 513 GAS_SENSOR: 6 INTERCEPTOR + SG_ INTERCEPTOR_GAS : 7|16@0+ (1,0) [0|1] "" EON + SG_ INTERCEPTOR_GAS2 : 23|16@0+ (1,0) [0|1] "" EON + SG_ STATE : 39|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" EON + SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" EON + +VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc new file mode 100644 index 0000000000..6cd9ccb625 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_gearbox_common.dbc @@ -0,0 +1,41 @@ +BO_ 401 GEARBOX_CVT: 8 PCM + SG_ SELECTED_P : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SELECTED_R : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SELECTED_N : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SELECTED_D : 3|1@0+ (1,0) [0|1] "" XXX + SG_ FORWARD_DRIVING_MODE : 23|1@0+ (1,0) [0|1] "" XXX + SG_ CVT_UNKNOWN_1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ CVT_UNKNOWN_2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ GEAR_SHIFTER : 44|5@0+ (1,0) [0|31] "" XXX + SG_ SHIFTER_POSITION_VALID : 45|1@0+ (1,0) [0|1] "" XXX + SG_ NOT_FORWARD_GEAR : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CVT_UNKNOWN_3 : 53|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 419 GEARBOX_AUTO: 8 PCM + SG_ TRANS_SHIFT_ACTIVITY : 7|8@0+ (1,0) [0|256] "" EON + SG_ TRANS_TARGET_GEAR : 11|4@0+ (1,0) [0|15] "" XXX + SG_ REGEN_STAGE_SELECTION : 14|3@0+ (1,0) [0|7] "Stage" XXX + SG_ REGEN_MEMORY : 16|1@0+ (1,0) [0|1] "" XXX + SG_ FORWARD_DRIVING_MODE : 20|1@0+ (1,0) [0|1] "" XXX + SG_ AUTO_UNKNOWN_1 : 27|2@0+ (1,0) [0|3] "" XXX + SG_ AUTO_UNKNOWN_2 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ GEAR_SHIFTER : 35|4@0+ (1,0) [0|15] "" EON + SG_ REGEN_UNKNOWN : 50|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ AUTO_UNKNOWN_3 : 62|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 401 CVT_UNKNOWN_1 "Probably measured/actual CVT ratio"; +CM_ SG_ 401 CVT_UNKNOWN_2 "Probably target/commanded CVT ratio"; +CM_ SG_ 419 TRANS_SHIFT_ACTIVITY "Tracks but trails TRANS_TARGET_GEAR with extra activity, probable solenoid activations or TC lockup"; +CM_ SG_ 419 REGEN_STAGE_SELECTION "Driver-selected regenerative braking threshold"; +CM_ SG_ 419 REGEN_MEMORY "Driver-selected persistence setting, M shown in instrument cluster"; +CM_ SG_ 419 REGEN_UNKNOWN "Both bits set when user enables regen, otherwise zero"; + +VAL_ 401 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 419 GEAR_SHIFTER 1 "P" 2 "R" 3 "N" 4 "D" 7 "L" 10 "S"; +VAL_ 419 TRANS_TARGET_GEAR 0 "None / Neutral / Park" 1 "1st" 2 "2nd" 3 "3rd" 4 "4th" 5 "5th" 6 "6th" 7 "7th" 8 "8th" 9 "9th" 10 "10th" 13 "Reverse"; +VAL_ 419 REGEN_STAGE_SELECTION 0 "disabled" 1 "stage_1" 2 "stage_2" 3 "stage_3" 4 "stage_4" 5 "stage_5" 6 "stage_6"; +VAL_ 419 REGEN_MEMORY 0 "disabled" 1 "persistent"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_honda_common.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_honda_common.dbc new file mode 100644 index 0000000000..24d3ed564b --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_honda_common.dbc @@ -0,0 +1,214 @@ +BO_ 145 KINEMATICS_ALT: 8 XXX + SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] "m/s2" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + +BO_ 148 KINEMATICS: 8 XXX + SG_ LAT_ACCEL : 7|10@0+ (0.02,-512) [-20|20] "m/s2" EON + SG_ LONG_ACCEL : 24|9@0- (-0.02,0) [-20|20] "m/s2" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 304 GAS_PEDAL_2: 8 PCM + SG_ ENGINE_TORQUE_ESTIMATE : 7|16@0- (1,0) [-1000|1000] "Nm" EON + SG_ ENGINE_TORQUE_REQUEST : 23|16@0- (1,0) [-1000|1000] "Nm" EON + SG_ CAR_GAS : 39|8@0+ (1,0) [0|255] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 316 GAS_PEDAL: 8 PCM + SG_ CAR_GAS : 39|8@0+ (1,0) [0|255] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 344 ENGINE_DATA: 8 PCM + SG_ XMISSION_SPEED : 7|16@0+ (0.01,0) [0|250] "kph" EON + SG_ ENGINE_RPM : 23|16@0+ (1,0) [0|15000] "rpm" EON + SG_ XMISSION_SPEED2 : 39|16@0+ (0.01,0) [0|250] "kph" EON + SG_ ODOMETER : 55|8@0+ (10,0) [0|2550] "m" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 380 POWERTRAIN_DATA: 8 PCM + SG_ PEDAL_GAS : 7|8@0+ (1,0) [0|255] "" EON + SG_ ENGINE_RPM : 23|16@0+ (1,0) [0|15000] "rpm" EON + SG_ GAS_PRESSED : 39|1@0+ (1,0) [0|1] "" EON + SG_ ACC_STATUS : 38|1@0+ (1,0) [0|1] "" EON + SG_ BOH_17C : 37|5@0+ (1,0) [0|1] "" EON + SG_ BRAKE_SWITCH : 32|1@0+ (1,0) [0|1] "" EON + SG_ BOH2_17C : 47|10@0+ (1,0) [0|1] "" EON + SG_ BRAKE_PRESSED : 53|1@0+ (1,0) [0|1] "" EON + SG_ BOH3_17C : 52|5@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 388 HYBRID_BRAKE_ERROR: 8 XXX + SG_ BRAKE_ERROR_1 : 32|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_ERROR_2 : 34|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + +BO_ 420 VSA_STATUS: 8 VSA + SG_ USER_BRAKE : 7|16@0+ (0.015625,-1.609375) [0|1000] "" EON + SG_ COMPUTER_BRAKING : 23|1@0+ (1,0) [0|1] "" EON + SG_ ESP_DISABLED : 28|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_HOLD_RELATED : 52|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_HOLD_ACTIVE : 46|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_HOLD_ENABLED : 45|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 427 STEER_MOTOR_TORQUE: 3 EPS + SG_ CONFIG_VALID : 7|1@0+ (1,0) [0|1] "" EON + SG_ MOTOR_TORQUE : 1|10@0+ (1,0) [0|256] "" EON + SG_ OUTPUT_DISABLED : 22|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 21|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 19|4@0+ (1,0) [0|15] "" EON + +BO_ 450 EPB_STATUS: 8 XXX + SG_ EPB_BRAKE_AND_PULL : 6|1@0+ (1,0) [0|1] "" XXX + SG_ EPB_ACTIVE : 3|1@0+ (1,0) [0|1] "" XXX + SG_ EPB_STATE : 29|2@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 464 WHEEL_SPEEDS: 8 VSA + SG_ WHEEL_SPEED_FL : 7|15@0+ (0.01,0) [0|250] "kph" EON + SG_ WHEEL_SPEED_FR : 8|15@0+ (0.01,0) [0|250] "kph" EON + SG_ WHEEL_SPEED_RL : 25|15@0+ (0.01,0) [0|250] "kph" EON + SG_ WHEEL_SPEED_RR : 42|15@0+ (0.01,0) [0|250] "kph" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + +BO_ 490 VEHICLE_DYNAMICS: 8 VSA + SG_ LAT_ACCEL : 7|16@0- (0.0015,0) [-20|20] "m/s2" EON + SG_ LONG_ACCEL : 23|16@0- (0.0015,0) [-20|20] "m/s2" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + +BO_ 597 ROUGH_WHEEL_SPEED: 8 VSA + SG_ WHEEL_SPEED_FL : 7|8@0+ (1,0) [0|255] "kph" EON + SG_ WHEEL_SPEED_FR : 15|8@0+ (1,0) [0|255] "kph" EON + SG_ WHEEL_SPEED_RL : 23|8@0+ (1,0) [0|255] "kph" EON + SG_ WHEEL_SPEED_RR : 31|8@0+ (1,0) [0|255] "kph" EON + SG_ SET_TO_X55 : 39|8@0+ (1,0) [0|255] "" EON + SG_ SET_TO_X55_2 : 47|8@0+ (1,0) [0|255] "" EON + SG_ LONG_COUNTER : 55|8@0+ (1,0) [0|255] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 773 SEATBELT_STATUS: 7 BDY + SG_ SEATBELT_DRIVER_LAMP : 7|1@0+ (1,0) [0|1] "" EON + SG_ SEATBELT_PASS_UNLATCHED : 10|1@0+ (1,0) [0|1] "" EON + SG_ SEATBELT_PASS_LATCHED : 11|1@0+ (1,0) [0|1] "" EON + SG_ SEATBELT_DRIVER_UNLATCHED : 12|1@0+ (1,0) [0|1] "" EON + SG_ SEATBELT_DRIVER_LATCHED : 13|1@0+ (1,0) [0|1] "" EON + SG_ PASS_AIRBAG_OFF : 14|1@0+ (1,0) [0|1] "" EON + SG_ PASS_AIRBAG_ON : 15|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] "" EON + +BO_ 777 CAR_SPEED: 8 PCM + SG_ ROUGH_CAR_SPEED : 23|8@0+ (1,0) [0|255] "mph" XXX + SG_ CAR_SPEED : 7|16@0+ (0.01,0) [0|65535] "kph" XXX + SG_ ROUGH_CAR_SPEED_3 : 39|16@0+ (0.01,0) [0|65535] "kph" XXX + SG_ ROUGH_CAR_SPEED_2 : 31|8@0+ (1,0) [0|255] "mph" XXX + SG_ LOCK_STATUS : 55|2@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ IMPERIAL_UNIT : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 780 ACC_HUD: 8 ADAS + SG_ PCM_SPEED : 7|16@0+ (0.01,0) [0|250] "kph" BDY + SG_ PCM_GAS : 23|8@0+ (1,0) [0|127] "" BDY + SG_ CRUISE_SPEED : 31|8@0+ (1,0) [0|255] "kph" BDY + SG_ DTC_MODE : 39|1@0+ (1,0) [0|1] "" BDY + SG_ BRAKE_SYSTEM_ICON : 38|1@0+ (1,0) [0|1] "" BDY + SG_ ACC_PROBLEM : 37|1@0+ (1,0) [0|1] "" BDY + SG_ FCM_OFF : 35|1@0+ (1,0) [0|1] "" BDY + SG_ FCM_OFF_2 : 36|1@0+ (1,0) [0|1] "" BDY + SG_ FCM_PROBLEM : 34|1@0+ (1,0) [0|1] "" BDY + SG_ RADAR_OBSTRUCTED : 33|1@0+ (1,0) [0|1] "" BDY + SG_ ENABLE_MINI_CAR : 32|1@0+ (1,0) [0|1] "" BDY + SG_ HUD_DISTANCE : 47|2@0+ (1,0) [0|3] "" BDY + SG_ HUD_LEAD : 45|2@0+ (1,0) [0|3] "" BDY + SG_ BOH_3 : 43|1@0+ (1,0) [0|3] "" BDY + SG_ BOH_4 : 42|1@0+ (1,0) [0|3] "" BDY + SG_ BOH_5 : 41|1@0+ (1,0) [0|3] "" BDY + SG_ CRUISE_CONTROL_LABEL : 40|1@0+ (1,0) [0|3] "" BDY + SG_ SET_ME_X01_2 : 55|1@0+ (1,0) [0|1] "" BDY + SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY + SG_ ACC_ON : 52|1@0+ (1,0) [0|1] "" BDY + SG_ CHIME : 51|3@0+ (1,0) [0|1] "" BDY + SG_ SET_ME_X01 : 48|1@0+ (1,0) [0|1] "" BDY + SG_ ICONS : 63|2@0+ (1,0) [0|1] "" BDY + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" BDY + +BO_ 804 CRUISE: 8 PCM + SG_ HUD_SPEED_KPH : 7|8@0+ (1,0) [0|255] "kph" EON + SG_ HUD_SPEED_MPH : 15|8@0+ (1,0) [0|255] "mph" EON + SG_ TRIP_FUEL_CONSUMED : 23|16@0+ (1,0) [0|255] "" EON + SG_ CRUISE_SPEED_PCM : 39|8@0+ (1,0) [0|255] "" EON + SG_ BOH2 : 47|8@0- (1,0) [0|255] "" EON + SG_ BOH3 : 55|8@0+ (1,0) [0|255] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 862 CAMERA_MESSAGES: 8 CAM + SG_ ZEROS_BOH : 7|16@0+ (1,0) [0|127] "" BDY + SG_ SPEED_LIMIT_SIGN : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ROAD_SIGN : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ZEROS_BOH_2 : 51|4@0+ (1,0) [0|15] "" XXX + SG_ HIGHBEAMS_ON : 52|1@0+ (1,0) [0|1] "" XXX + SG_ AUTO_HIGHBEAMS_ACTIVE : 53|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 884 STALK_STATUS: 8 XXX + SG_ DASHBOARD_ALERT : 39|8@0+ (1,0) [0|255] "" EON + SG_ AUTO_HEADLIGHTS : 46|1@0+ (1,0) [0|1] "" EON + SG_ HIGH_BEAM_HOLD : 47|1@0+ (1,0) [0|1] "" EON + SG_ HIGH_BEAM_FLASH : 45|1@0+ (1,0) [0|1] "" EON + SG_ HEADLIGHTS_ON : 54|1@0+ (1,0) [0|1] "" EON + SG_ WIPER_SWITCH : 53|2@0+ (1,0) [0|3] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 891 STALK_STATUS_2: 8 XXX + SG_ WIPERS : 17|2@0+ (1,0) [0|3] "" EON + SG_ LOW_BEAMS : 35|1@0+ (1,0) [0|1] "" XXX + SG_ HIGH_BEAMS : 34|1@0+ (1,0) [0|1] "" XXX + SG_ PARK_LIGHTS : 36|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 1029 DOORS_STATUS: 8 BDY + SG_ DOOR_OPEN_FL : 37|1@0+ (1,0) [0|1] "" EON + SG_ DOOR_OPEN_FR : 38|1@0+ (1,0) [0|1] "" EON + SG_ DOOR_OPEN_RL : 39|1@0+ (1,0) [0|1] "" EON + SG_ DOOR_OPEN_RR : 40|1@0+ (1,0) [0|1] "" EON + SG_ TRUNK_OPEN : 41|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 1302 ODOMETER: 8 XXX + SG_ ODOMETER : 7|24@0+ (1,0) [0|16777215] "km" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + +CM_ SG_ 304 "Seems to be platform-agnostic"; +CM_ SG_ 316 "Should exist on Nidec"; +CM_ SG_ 420 BRAKE_HOLD_RELATED "On when Brake Hold engaged"; +CM_ SG_ 490 LONG_ACCEL "wheel speed derivative, noisy and zero snapping"; +CM_ SG_ 773 PASS_AIRBAG_ON "Might just be indicator light"; +CM_ SG_ 773 PASS_AIRBAG_OFF "Might just be indicator light"; +CM_ SG_ 780 CRUISE_SPEED "255 = no speed"; +CM_ SG_ 780 PCM_SPEED "Used by Nidec"; +CM_ SG_ 780 PCM_GAS "Used by Nidec"; +CM_ SG_ 804 CRUISE_SPEED_PCM "255 = no speed"; + +VAL_ 450 EPB_STATE 3 "engaged" 2 "disengaging" 1 "engaging" 0 "disengaged" ; +VAL_ 780 CRUISE_SPEED 255 "no_speed" 252 "stopped"; +VAL_ 780 HUD_LEAD 3 "acc_off" 2 "solid_car" 1 "dashed_car" 0 "no_car"; +VAL_ 884 DASHBOARD_ALERT 0 "none" 51 "acc_problem" 55 "cmbs_problem" 75 "key_not_detected" 79 "fasten_seatbelt" 111 "lkas_problem" 131 "brake_system_problem" 132 "brake_hold_problem" 139 "tbd" 161 "door_open"; +VAL_ 891 WIPERS 4 "High" 2 "Low" 0 "Off"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_lkas_hud_5byte.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_lkas_hud_5byte.dbc new file mode 100644 index 0000000000..12c3a48c96 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_lkas_hud_5byte.dbc @@ -0,0 +1,28 @@ +BO_ 829 LKAS_HUD: 5 ADAS + SG_ LKAS_READY : 0|1@0+ (1,0) [0|127] "" BDY + SG_ LKAS_STATE_CHANGE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ CAM_TEMP_HIGH : 7|1@0+ (1,0) [0|255] "" BDY + SG_ DASHED_LANES : 14|1@0+ (1,0) [0|1] "" BDY + SG_ DTC : 13|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_PROBLEM : 12|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_OFF : 11|1@0+ (1,0) [0|1] "" BDY + SG_ SOLID_LANES : 10|1@0+ (1,0) [0|1] "" BDY + SG_ CLEAN_WINDSHIELD : 26|1@0+ (1,0) [0|1] "" BDY + SG_ STEERING_REQUIRED : 8|1@0+ (1,0) [0|1] "" BDY + SG_ BEEP : 17|2@0+ (1,0) [0|1] "" BDY + SG_ RDM_PROBLEM : 21|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD : 9|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD_2 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_OFF : 27|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_ON : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_ON_2 : 28|1@0+ (1,0) [0|1] "" BDY + SG_ LANE_ASSIST_BEEP_OFF : 30|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 35|4@0+ (1,0) [0|15] "" BDY + SG_ COUNTER : 37|2@0+ (1,0) [0|3] "" BDY + + +CM_ SG_ 829 BEEP "beeps are pleasant, chimes are for warnings etc..."; +CM_ SG_ 829 CAM_TEMP_HIGH "Some Driver Assist Systems Cannot Operate: Camera Temperature Too High"; +CM_ SG_ 829 CAMERA_OVERHEAT "Lane Keeping Assist Cannot Operate: Camera Too Hot"; + +VAL_ 829 BEEP 5 "solid_beep" 4 "double_beep" 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_lkas_hud_8byte.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_lkas_hud_8byte.dbc new file mode 100644 index 0000000000..d2dbed64dc --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_lkas_hud_8byte.dbc @@ -0,0 +1,29 @@ +BO_ 829 LKAS_HUD: 8 ADAS + SG_ LKAS_READY : 0|1@0+ (1,0) [0|127] "" BDY + SG_ LKAS_STATE_CHANGE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ CAM_TEMP_HIGH : 7|1@0+ (1,0) [0|255] "" BDY + SG_ DASHED_LANES : 14|1@0+ (1,0) [0|1] "" BDY + SG_ DTC : 13|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_PROBLEM : 12|1@0+ (1,0) [0|1] "" BDY + SG_ LKAS_OFF : 11|1@0+ (1,0) [0|1] "" BDY + SG_ SOLID_LANES : 10|1@0+ (1,0) [0|1] "" BDY + SG_ CLEAN_WINDSHIELD : 26|1@0+ (1,0) [0|1] "" BDY + SG_ STEERING_REQUIRED : 8|1@0+ (1,0) [0|1] "" BDY + SG_ BEEP : 17|2@0+ (1,0) [0|1] "" BDY + SG_ RDM_PROBLEM : 21|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD : 9|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_HUD_2 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_OFF : 27|1@0+ (1,0) [0|1] "" BDY + SG_ RDM_ON : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RDM_ON_2 : 28|1@0+ (1,0) [0|1] "" BDY + SG_ LANE_ASSIST_BEEP_OFF : 30|1@0+ (1,0) [0|1] "" XXX + SG_ LANE_LINES : 36|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +CM_ SG_ 829 BEEP "beeps are pleasant, chimes are for warnings etc..."; +CM_ SG_ 829 CAM_TEMP_HIGH "Some Driver Assist Systems Cannot Operate: Camera Temperature Too High"; +CM_ SG_ 829 CAMERA_OVERHEAT "Lane Keeping Assist Cannot Operate: Camera Too Hot"; + +VAL_ 829 BEEP 5 "solid_beep" 4 "double_beep" 3 "single_beep" 2 "triple_beep" 1 "repeated_beep" 0 "no_beep"; +VAL_ 829 LANE_LINES 7 "both_lines_green" 6 "both_lines_white" 2 "left_line_white" 0 "no_lines"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_nidec_common.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_nidec_common.dbc new file mode 100644 index 0000000000..d22c28a56e --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_nidec_common.dbc @@ -0,0 +1,71 @@ +BO_ 432 STANDSTILL: 7 VSA + SG_ CONTROLLED_STANDSTILL : 0|1@0+ (1,0) [0|1] "" EON + SG_ WHEELS_MOVING : 12|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_ERROR_1 : 11|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_ERROR_2 : 9|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] "" EON + +BO_ 487 BRAKE_PRESSURE: 4 VSA + SG_ BRAKE_PRESSURE1 : 7|10@0+ (0.015625,-103) [0|1000] "" EON + SG_ BRAKE_PRESSURE2 : 9|10@0+ (0.015625,-103) [0|1000] "" EON + SG_ CHECKSUM : 27|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON + +BO_ 506 BRAKE_COMMAND: 8 ADAS + SG_ COMPUTER_BRAKE : 7|10@0+ (1,0) [0|1] "" EBCM + SG_ BRAKE_PUMP_REQUEST : 8|1@0+ (1,0) [0|1] "" EBCM + SG_ BRAKE_PUMP_REQUEST_HYBRID : 11|1@0+ (1,0) [0|1] "" EBCM + SG_ SET_ME_X00 : 23|3@0+ (1,0) [0|1] "" EBCM + SG_ CRUISE_OVERRIDE : 20|1@0+ (1,0) [0|1] "" EBCM + SG_ SET_ME_X00_2 : 19|1@0+ (1,0) [0|1] "" EBCM + SG_ CRUISE_FAULT_CMD : 18|1@0+ (1,0) [0|1] "" EBCM + SG_ CRUISE_CANCEL_CMD : 17|1@0+ (1,0) [0|1] "" EBCM + SG_ COMPUTER_BRAKE_REQUEST : 16|1@0+ (1,0) [0|1] "" EBCM + SG_ SET_ME_1 : 31|1@0+ (1,0) [0|1] "" EBCM + SG_ AEB_REQ_1 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_REQ_2 : 26|3@0+ (1,0) [0|7] "" XXX + SG_ BRAKE_LIGHTS : 39|1@0+ (1,0) [0|1] "" EBCM + SG_ CRUISE_STATES : 38|7@0+ (1,0) [0|1] "" EBCM + SG_ CHIME : 47|3@0+ (1,0) [0|7] "" EBCM + SG_ SET_ME_X00_3 : 44|1@0+ (1,0) [0|1] "" EBCM + SG_ FCW : 43|2@0+ (1,0) [0|3] "" EBCM + SG_ AEB_STATUS : 41|2@0+ (1,0) [0|3] "" XXX + SG_ COMPUTER_BRAKE_HYBRID : 55|10@0+ (1,0) [0|0] "" EBCM + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EBCM + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EBCM + +BO_ 547 BRAKE_HOLD_HYBRID_ALT: 6 XXX + SG_ BRAKE_HOLD_FAULT_BIT : 33|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_HOLD_ENABLED : 37|2@0+ (1,0) [0|7] "" XXX + SG_ BRAKE_HOLD_ACTIVE : 38|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" XXX + +BO_ 892 CRUISE_PARAMS: 8 PCM + SG_ CRUISE_SPEED_OFFSET : 31|8@0- (0.1,0) [-128|127] "kph" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + +BO_ 927 RADAR_HUD: 8 ADAS + SG_ ZEROS_BOH : 7|16@0+ (1,0) [0|127] "" BDY + SG_ ACC_ALERTS : 20|5@0+ (1,0) [0|15] "" BDY + SG_ RESUME_INSTRUCTION : 21|1@0+ (1,0) [0|15] "" BDY + SG_ APPLY_BRAKES_FOR_CANC : 23|1@0+ (1,0) [0|15] "" BDY + SG_ ZEROS_BOH2 : 31|8@0+ (1,0) [0|127] "" BDY + SG_ LEAD_SPEED : 39|9@0+ (1,0) [0|127] "" BDY + SG_ LEAD_DISTANCE : 46|8@0+ (1,0) [0|31] "" BDY + SG_ ZEROS_BOH3 : 54|7@0+ (1,0) [0|127] "" BDY + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" BDY + +CM_ SG_ 506 AEB_REQ_1 "set for duration of suspected AEB event"; +CM_ SG_ 506 COMPUTER_BRAKE_HYBRID "Used by Hybrid Nidec"; +CM_ SG_ 506 BRAKE_PUMP_REQUEST_HYBRID "Used by Hybrid Nidec"; + +VAL_ 506 FCW 3 "fcw" 2 "fcw" 1 "fcw" 0 "no_fcw"; +VAL_ 506 CHIME 4 "double_chime" 3 "single_chime" 2 "continuous_chime" 1 "repeating_chime" 0 "no_chime"; +VAL_ 506 AEB_STATUS 3 "aeb_prepare" 2 "aeb_ready" 1 "aeb_braking" 0 "no_aeb"; +VAL_ 927 ACC_ALERTS 29 "esp_active_acc_canceled" 10 "b_pedal_applied" 9 "speed_too_low" 8 "speed_too_high" 7 "p_brake_applied" 6 "gear_no_d" 5 "seatbelt" 4 "too_steep_downhill" 3 "too_steep_uphill" 2 "too_close" 1 "no_vehicle_ahead" ; +VAL_ 927 LEAD_DISTANCE 254 "no lead"; +VAL_ 927 LEAD_SPEED 510 "no lead"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_nidec_scm_group_a.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_nidec_scm_group_a.dbc new file mode 100644 index 0000000000..7b25e2406d --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_nidec_scm_group_a.dbc @@ -0,0 +1,20 @@ +BO_ 660 SCM_FEEDBACK: 8 SCM + SG_ RIGHT_BLINKER : 6|1@0+ (1,0) [0|1] "" EON + SG_ LEFT_BLINKER : 5|1@0+ (1,0) [0|1] "" EON + SG_ WIPERS_SPEED : 4|2@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +BO_ 422 SCM_BUTTONS: 8 SCM + SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON + SG_ LIGHTS_SETTING : 1|2@0+ (1,0) [0|3] "" EON + SG_ PARKING_BRAKE_ON : 2|1@0+ (1,0) [0|1] "" EON + SG_ MAIN_ON : 47|1@0+ (1,0) [0|1] "" EON + SG_ CRUISE_SETTING : 43|2@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + SG_ DRIVERS_DOOR_OPEN : 63|1@0+ (1,0) [0|1] "" EON + +VAL_ 422 CRUISE_BUTTONS 7 "tbd" 6 "tbd" 5 "tbd" 4 "accel_res" 3 "decel_set" 2 "cancel" 1 "main" 0 "none" ; +VAL_ 422 LIGHTS_SETTING 3 "high_beam" 2 "low_beam" 1 "position" 0 "no_lights" ; +VAL_ 422 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_nidec_scm_group_b.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_nidec_scm_group_b.dbc new file mode 100644 index 0000000000..ce8d2c482d --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_nidec_scm_group_b.dbc @@ -0,0 +1,20 @@ +BO_ 662 SCM_BUTTONS: 4 SCM + SG_ CRUISE_BUTTONS : 7|3@0+ (1,0) [0|7] "" EON + SG_ CRUISE_SETTING : 3|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 27|4@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 29|2@0+ (1,0) [0|3] "" EON + +BO_ 806 SCM_FEEDBACK: 8 SCM + SG_ DRIVERS_DOOR_OPEN : 17|1@0+ (1,0) [0|1] "" XXX + SG_ REVERSE_LIGHT : 18|1@0+ (1,0) [0|1] "" EON + SG_ CMBS_BUTTON : 22|2@0+ (1,0) [0|3] "" EON + SG_ LEFT_BLINKER : 26|1@0+ (1,0) [0|1] "" EON + SG_ RIGHT_BLINKER : 27|1@0+ (1,0) [0|1] "" EON + SG_ MAIN_ON : 28|1@0+ (1,0) [0|1] "" EON + SG_ PARKING_BRAKE_ON : 29|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON + +VAL_ 662 CRUISE_BUTTONS 7 "tbd" 6 "tbd" 5 "tbd" 4 "accel_res" 3 "decel_set" 2 "cancel" 1 "main" 0 "none" ; +VAL_ 662 CRUISE_SETTING 3 "distance_adj" 2 "tbd" 1 "lkas_button" 0 "none" ; +VAL_ 806 CMBS_BUTTON 3 "pressed" 0 "released" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_steering_control_a.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_steering_control_a.dbc new file mode 100644 index 0000000000..87bd969480 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_steering_control_a.dbc @@ -0,0 +1,18 @@ +BO_ 228 STEERING_CONTROL: 5 ADAS + SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS + SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS + SG_ SET_ME_X00 : 22|7@0+ (1,0) [0|127] "" EPS + SG_ SET_ME_X00_2 : 31|8@0+ (1,0) [0|0] "" EPS + SG_ COUNTER : 37|2@0+ (1,0) [0|3] "" EPS + SG_ CHECKSUM : 35|4@0+ (1,0) [0|15] "" EPS + +BO_ 399 STEER_STATUS: 7 EPS + SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON + SG_ STEER_ANGLE_RATE : 23|16@0- (-0.1,0) [-31000|31000] "deg/s" EON + SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON + SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON + SG_ STEER_CONFIG_INDEX : 43|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] "" EON + +VAL_ 399 STEER_STATUS 7 "permanent_fault" 6 "tmp_fault" 5 "fault_1" 4 "no_torque_alert_2" 3 "low_speed_lockout" 2 "no_torque_alert_1" 1 "driver_steering" 0 "normal" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_steering_control_b.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_steering_control_b.dbc new file mode 100644 index 0000000000..0b39c15ebb --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_steering_control_b.dbc @@ -0,0 +1,17 @@ +BO_ 404 STEERING_CONTROL: 4 EON + SG_ STEER_TORQUE : 7|12@0- (1,0) [-768|768] "" EPS + SG_ SET_ME_X00 : 11|4@0+ (1,0) [0|15] "" EPS + SG_ STEER_TORQUE_REQUEST : 23|1@0+ (1,0) [0|1] "" EPS + SG_ SET_ME_X00_2 : 22|7@0+ (1,0) [0|127] "" EPS + SG_ COUNTER : 29|2@0+ (1,0) [0|15] "" EPS + SG_ CHECKSUM : 27|4@0+ (1,0) [0|3] "" EPS + +BO_ 399 STEER_STATUS: 6 EPS + SG_ STEER_TORQUE_SENSOR : 7|12@0- (-1,0) [-2047.5|2047.5] "tbd" EON + SG_ STEER_ANGLE_RATE : 23|16@0- (-0.1,0) [-31000|31000] "deg/s" EON + SG_ STEER_CONTROL_ACTIVE : 36|1@0+ (1,0) [0|1] "" EON + SG_ STEER_STATUS : 35|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" EON + +VAL_ 399 STEER_STATUS 7 "permanent_fault" 6 "tmp_fault" 5 "fault_1" 4 "no_torque_alert_2" 3 "low_speed_lockout" 2 "no_torque_alert_1" 1 "driver_steering" 0 "normal" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_steering_sensors_a.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_steering_sensors_a.dbc new file mode 100644 index 0000000000..52805d6227 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_steering_sensors_a.dbc @@ -0,0 +1,9 @@ +BO_ 330 STEERING_SENSORS: 8 EPS + SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON + SG_ STEER_ANGLE_RATE : 23|16@0- (-1,0) [-3000|3000] "deg/s" EON + SG_ STEER_SENSOR_STATUS_1 : 34|1@0+ (1,0) [0|1] "" EON + SG_ STEER_SENSOR_STATUS_2 : 33|1@0+ (1,0) [0|1] "" EON + SG_ STEER_SENSOR_STATUS_3 : 32|1@0+ (1,0) [0|1] "" EON + SG_ STEER_WHEEL_ANGLE : 47|16@0- (-0.1,0) [-500|500] "deg" EON + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON diff --git a/opendbc_repo/opendbc/dbc/generator/honda/_steering_sensors_b.dbc b/opendbc_repo/opendbc/dbc/generator/honda/_steering_sensors_b.dbc new file mode 100644 index 0000000000..35e9b27520 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/_steering_sensors_b.dbc @@ -0,0 +1,5 @@ +BO_ 342 STEERING_SENSORS: 6 EPS + SG_ STEER_ANGLE : 7|16@0- (-0.1,0) [-500|500] "deg" EON + SG_ STEER_ANGLE_RATE : 23|16@0- (-1,0) [-3000|3000] "deg/s" EON + SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" EON diff --git a/opendbc_repo/opendbc/dbc/generator/honda/acura_ilx_2016_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/acura_ilx_2016_can.dbc new file mode 100644 index 0000000000..bd4a08fdb7 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/acura_ilx_2016_can.dbc @@ -0,0 +1,7 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _nidec_common.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _nidec_scm_group_a.dbc"; +CM_ "IMPORT _steering_sensors_b.dbc"; +CM_ "IMPORT _steering_control_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/acura_rdx_2018_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/acura_rdx_2018_can.dbc new file mode 100644 index 0000000000..4c95ee5792 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/acura_rdx_2018_can.dbc @@ -0,0 +1,15 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _nidec_common.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _nidec_scm_group_a.dbc"; +CM_ "IMPORT _steering_sensors_b.dbc"; +CM_ "IMPORT _steering_control_b.dbc"; + +BO_ 392 GEARBOX_AUTO: 6 XXX + SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" XXX + SG_ GEAR_SHIFTER : 27|4@0+ (1,0) [0|15] "" EON + SG_ GEAR : 36|5@0+ (1,0) [0|31] "" EON + +VAL_ 392 GEAR_SHIFTER 0 "S" 1 "P" 2 "R" 4 "N" 8 "D" ; +VAL_ 392 GEAR 26 "S" 4 "D" 3 "N" 2 "R" 1 "P" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/acura_rdx_2020_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/acura_rdx_2020_can.dbc new file mode 100644 index 0000000000..9c469e3e66 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/acura_rdx_2020_can.dbc @@ -0,0 +1,7 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _bosch_2018.dbc"; +CM_ "IMPORT _bosch_radar_acc.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _bosch_standstill.dbc"; +CM_ "IMPORT _steering_sensors_b.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_bosch_radarless.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_bosch_radarless.dbc new file mode 100644 index 0000000000..2b86a33136 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_bosch_radarless.dbc @@ -0,0 +1,51 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _bosch_2018.dbc"; +CM_ "IMPORT _lkas_hud_8byte.dbc"; +CM_ "IMPORT _bosch_standstill.dbc"; +CM_ "IMPORT _steering_sensors_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; + +BO_ 456 ACC_CONTROL: 8 XXX + SG_ ACCEL_COMMAND : 7|12@0- (0.01,0) [0|0] "m/s^2" XXX + SG_ IDLESTOP_ALLOW : 8|1@0+ (1,0) [0|1] "" XXX + SG_ STANDSTILL : 9|1@0+ (1,0) [0|1] "" XXX + SG_ CONTROL_ON : 10|1@0+ (1,0) [0|1] "" XXX + SG_ BOH : 23|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_STATUS : 33|1@1+ (1,0) [0|7] "" XXX + SG_ AEB_BRAKING : 47|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_PREPARE : 43|1@0+ (1,0) [0|1] "" XXX + SG_ FCW_1 : 24|1@1+ (1,0) [0|3] "" XXX + SG_ FCW_2 : 54|1@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 467 CRUISE_FAULT_STATUS: 8 XXX + SG_ CRUISE_FAULT : 3|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 477 GEARBOX_ALT_2: 8 XXX + SG_ GEAR_MT : 39|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 495 SPEED_LIMIT_DASH_DISPLAY: 8 ADAS + SG_ SPEED_LIMIT : 47|8@0+ (1,0) [0|255] "mph" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 254913108 LKAS_HUD_2: 8 ADAS + SG_ COUNTER_2 : 7|2@0+ (1,0) [0|3] "" XXX + SG_ SET_ME_X01 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_BOH_1 : 15|6@0+ (1,0) [0|63] "" XXX + SG_ LEFT_LANE : 23|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_LANE : 21|2@0+ (1,0) [0|3] "" XXX + SG_ LKAS_BOH_2 : 30|5@0+ (1,0) [0|31] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + +CM_ SG_ 456 IDLESTOP_ALLOW "allows car to turn off engine at a standstill"; +CM_ SG_ 456 STANDSTILL "set to 1 when camera requests -4.0 m/s^2"; +CM_ SG_ 495 SPEED_LIMIT "Defaults to 0xFF if no speed limit found"; + +VAL_ 477 GEAR_MT 14 "reverse" 6 "6th" 5 "5th" 4 "4th" 3 "3rd" 2 "2nd" 1 "1st" 0 "Clutch"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_civic_hatchback_ex_2017_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_civic_hatchback_ex_2017_can.dbc new file mode 100644 index 0000000000..b6be281bb7 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_civic_hatchback_ex_2017_can.dbc @@ -0,0 +1,7 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _bosch_2018.dbc"; +CM_ "IMPORT _bosch_radar_acc.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _bosch_standstill.dbc"; +CM_ "IMPORT _steering_sensors_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_civic_touring_2016_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_civic_touring_2016_can.dbc new file mode 100644 index 0000000000..1e1f378034 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_civic_touring_2016_can.dbc @@ -0,0 +1,18 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _nidec_common.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _nidec_scm_group_b.dbc"; +CM_ "IMPORT _steering_sensors_a.dbc"; +CM_ "IMPORT _steering_control_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; + +BO_ 493 HUD_SETTING: 5 XXX + SG_ IMPERIAL_UNIT : 5|1@0+ (1,0) [0|1] "" EON + +BO_ 545 ECON_STATUS: 6 XXX + SG_ ECON_ON_2 : 37|2@0+ (1,0) [0|3] "" EON + SG_ ECON_ON : 23|1@0+ (1,0) [0|1] "" EON + SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON + SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON + +VAL_ 545 ECON_ON_2 0 "off" 3 "on" ; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_clarity_hybrid_2018_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_clarity_hybrid_2018_can.dbc new file mode 100644 index 0000000000..4df7722655 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_clarity_hybrid_2018_can.dbc @@ -0,0 +1,23 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _nidec_common.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _nidec_scm_group_b.dbc"; +CM_ "IMPORT _steering_sensors_a.dbc"; +CM_ "IMPORT _steering_control_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; + +BO_ 768 VEHICLE_STATE: 8 ADAS + SG_ SET_ME_XF9 : 7|8@0+ (1,0) [0|255] "" Vector__XXX + SG_ VEHICLE_SPEED : 15|8@0+ (1,0) [0|255] "kph" Vector__XXX + SG_ SET_ME_X8A : 23|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_XD0 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SALTED_WITH_IDX : 39|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 769 VEHICLE_STATE2: 8 ADAS + SG_ SET_ME_X5D : 23|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X02 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X5F : 39|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" XXX diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc new file mode 100644 index 0000000000..cd7efe7be7 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_common_canfd.dbc @@ -0,0 +1,7 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _bosch_2018.dbc"; +CM_ "IMPORT _bosch_radar_acc.dbc"; +CM_ "IMPORT _lkas_hud_8byte.dbc"; +CM_ "IMPORT _bosch_standstill.dbc"; +CM_ "IMPORT _steering_sensors_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_crv_ex_2017_body.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_crv_ex_2017_body.dbc new file mode 100644 index 0000000000..363b595817 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_crv_ex_2017_body.dbc @@ -0,0 +1,10 @@ +BO_ 318291879 BSM_STATUS_RIGHT: 8 XXX + SG_ BSM_ALERT : 4|1@0+ (1,0) [0|1] "" XXX + SG_ BSM_MODE : 6|2@0+ (1,0) [0|3] "" XXX + +BO_ 318291615 BSM_STATUS_LEFT: 8 XXX + SG_ BSM_ALERT : 4|1@0+ (1,0) [0|1] "" XXX + SG_ BSM_MODE : 6|2@0+ (1,0) [0|3] "" XXX + +VAL_ 318291879 BSM_MODE 2 "blind_spot" 1 "cross_traffic" 0 "off"; +VAL_ 318291615 BSM_MODE 2 "blind_spot" 1 "cross_traffic" 0 "off"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_crv_touring_2016_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_crv_touring_2016_can.dbc new file mode 100644 index 0000000000..6af4d57cbd --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_crv_touring_2016_can.dbc @@ -0,0 +1,7 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _nidec_common.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _nidec_scm_group_a.dbc"; +CM_ "IMPORT _steering_sensors_b.dbc"; +CM_ "IMPORT _steering_control_b.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_insight_ex_2019_can.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_insight_ex_2019_can.dbc new file mode 100644 index 0000000000..4da20adea8 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_insight_ex_2019_can.dbc @@ -0,0 +1,14 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _bosch_2018.dbc"; +CM_ "IMPORT _bosch_radar_acc.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _steering_sensors_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; + +BO_ 432 STANDSTILL: 7 VSA + SG_ BRAKE_ERROR_1 : 13|1@0+ (1,0) [0|1] "" EON + SG_ BRAKE_ERROR_2 : 12|1@0+ (1,0) [0|1] "" EON + SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON + SG_ CHECKSUM : 51|4@0+ (1,0) [0|15] "" EON + +CM_ BO_ 432 "Slightly conflicting definition with common Bosch standstill message, this one could be broken"; diff --git a/opendbc_repo/opendbc/dbc/generator/honda/honda_odyssey_exl_2018.dbc b/opendbc_repo/opendbc/dbc/generator/honda/honda_odyssey_exl_2018.dbc new file mode 100644 index 0000000000..0d739118d2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/honda/honda_odyssey_exl_2018.dbc @@ -0,0 +1,7 @@ +CM_ "IMPORT _honda_common.dbc"; +CM_ "IMPORT _nidec_common.dbc"; +CM_ "IMPORT _lkas_hud_5byte.dbc"; +CM_ "IMPORT _nidec_scm_group_b.dbc"; +CM_ "IMPORT _steering_sensors_b.dbc"; +CM_ "IMPORT _steering_control_a.dbc"; +CM_ "IMPORT _gearbox_common.dbc"; diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/.gitignore b/opendbc_repo/opendbc/dbc/generator/hyundai/.gitignore new file mode 100644 index 0000000000..81f73f3551 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/.gitignore @@ -0,0 +1,2 @@ +hyundai_kia_mando_front_radar.dbc +hyundai_kia_mando_corner_radar.dbc diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/_hyundai_canfd_common.dbc b/opendbc_repo/opendbc/dbc/generator/hyundai/_hyundai_canfd_common.dbc new file mode 100644 index 0000000000..19751557b8 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/_hyundai_canfd_common.dbc @@ -0,0 +1,232 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX CAMERA FRONT_RADAR ADRV APRK + + +BO_ 80 LKAS: 16 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ LKA_MODE : 24|3@1+ (1,0) [0|7] "" XXX + SG_ LKA_AVAILABLE : 27|2@1+ (1,0) [0|255] "" XXX + SG_ LKA_WARNING : 32|1@1+ (1,0) [0|1] "" XXX + SG_ LKA_ICON : 38|2@1+ (1,0) [0|255] "" XXX + SG_ FCA_SYSWARN : 40|1@0+ (1,0) [0|1] "" XXX + SG_ TORQUE_REQUEST : 41|11@1+ (1,-1024) [0|4095] "" XXX + SG_ STEER_REQ : 52|1@1+ (1,0) [0|1] "" XXX + SG_ LFA_BUTTON : 56|1@1+ (1,0) [0|255] "" XXX + SG_ LKA_ASSIST : 62|1@1+ (1,0) [0|1] "" XXX + SG_ STEER_MODE : 65|3@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 70|2@0+ (1,0) [0|3] "" XXX + SG_ HAS_LANE_SAFETY : 80|1@0+ (1,0) [0|1] "" XXX + SG_ DAMP_FACTOR : 64|8@1+ (1,0) [0|255] "" XXX + +BO_ 81 ADRV_0x51: 32 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 384 CAM_0x180: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 385 CAM_0x181: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 386 CAM_0x182: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 387 CAM_0x183: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 388 CAM_0x184: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 389 CAM_0x185: 8 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 438 CAM_0x1b6: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 439 CAM_0x1b7: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 440 CAM_0x1b8: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 441 CAM_0x1b9: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 513 RADAR_0x201: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 528 RADAR_0x210: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 529 RADAR_0x211: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 530 RADAR_0x212: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 531 RADAR_0x213: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 532 RADAR_0x214: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 533 RADAR_0x215: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 534 RADAR_0x216: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 535 RADAR_0x217: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 536 RADAR_0x218: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 537 RADAR_0x219: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 538 RADAR_0x21a: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 539 RADAR_0x21b: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 540 RADAR_0x21c: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 541 RADAR_0x21d: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 542 RADAR_0x21e: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 543 RADAR_0x21f: 32 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 576 RADAR_0x240: 16 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 674 CAM_0x2a2: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 675 CAM_0x2a3: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 676 CAM_0x2a4: 24 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ LEFT_LANE_LINE : 56|2@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_0 : 58|2@1+ (1,0) [0|3] "" XXX + SG_ RIGHT_LANE_LINE : 60|2@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_0_2 : 62|2@1+ (1,0) [0|3] "" XXX + SG_ BYTE8 : 64|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE9 : 72|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE10 : 80|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE11 : 88|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE12 : 96|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE13 : 104|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE14 : 112|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE15 : 120|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE16 : 128|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE17 : 136|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE18 : 144|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE19 : 152|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE20 : 160|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE21 : 168|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE22 : 176|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE23 : 184|8@1+ (1,0) [0|255] "" XXX + +BO_ 699 CAM_0x2bb: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 700 CAM_0x2bc: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 701 CAM_0x2bd: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 702 CAM_0x2be: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +CM_ BO_ 676 "Contains signals with detailed lane line information. Used by ADAS ECU on HDA 2 vehicles to operate LFA."; + +CM_ SG_ 80 HAS_LANE_SAFETY "If 0, hides LKAS 'Lane Safety' menu from vehicle settings"; +CM_ SG_ 676 LEFT_LANE_LINE "Left lane line confidence"; +CM_ SG_ 676 RIGHT_LANE_LINE "Right lane line confidence"; +VAL_ 80 LKA_ICON 0 "hidden" 1 "grey" 2 "green" 3 "flashing green" ; +VAL_ 80 LKA_MODE 1 "warning only" 2 "assist" 6 "off" ; +VAL_ 676 LEFT_LANE_LINE 0 "Not Detected" 1 "Low Confidence" 2 "Medium Confidence" 3 "High Confidence"; +VAL_ 676 RIGHT_LANE_LINE 0 "Not Detected" 1 "Low Confidence" 2 "Medium Confidence" 3 "High Confidence"; diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc new file mode 100644 index 0000000000..7fc2ec6a19 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc @@ -0,0 +1,987 @@ +CM_ "IMPORT _hyundai_canfd_common.dbc"; + +BO_ 53 ACCELERATOR: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ ACCELERATOR_PEDAL : 40|8@1+ (1,0) [0|255] "" XXX + SG_ GEAR : 192|3@1+ (1,0) [0|7] "" XXX + +BO_ 64 GEAR_ALT: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ GEAR : 32|3@1+ (1,0) [0|7] "" XXX + +BO_ 69 GEAR: 24 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ GEAR : 44|3@1+ (1,0) [0|7] "" XXX + +BO_ 96 ESP_STATUS: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ TRACTION_AND_STABILITY_CONTROL : 42|3@1+ (1,0) [0|63] "" XXX + SG_ BRAKE_PRESSURE : 128|10@1+ (1,0) [0|65535] "" XXX + SG_ BRAKE_PRESSED : 148|1@1+ (1,0) [0|3] "" XXX + +BO_ 101 BRAKE: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ BRAKE_POSITION : 40|16@1- (1,0) [0|65535] "" XXX + SG_ BRAKE_PRESSED : 57|1@1+ (1,0) [0|3] "" XXX + +BO_ 112 GEAR_ALT_2: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ GEAR : 60|3@1+ (1,0) [0|7] "" XXX + +BO_ 160 WHEEL_SPEEDS: 24 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ MOVING_FORWARD : 56|1@0+ (1,0) [0|1] "" XXX + SG_ MOVING_BACKWARD : 57|1@0+ (1,0) [0|1] "" XXX + SG_ MOVING_FORWARD2 : 58|1@0+ (1,0) [0|1] "" XXX + SG_ MOVING_BACKWARD2 : 59|1@0+ (1,0) [0|1] "" XXX + SG_ WHL_SpdFLVal : 64|14@1+ (0.03125,0) [0|0] "km^h" XXX + SG_ WHL_SpdFRVal : 80|14@1+ (0.03125,0) [0|0] "km^h" XXX + SG_ WHL_SpdRLVal : 96|14@1+ (0.03125,0) [0|0] "km^h" XXX + SG_ WHL_SpdRRVal : 112|14@1+ (0.03125,0) [0|0] "km^h" XXX + +BO_ 203 ADAS_CMD_35_10ms: 24 CGW_CCU + SG_ CHECKSUM : 0|16@1+ (1,0) [0|0] "0" FCU_C,GW_RGW,MDPS,SFA + SG_ COUNTER : 16|8@1+ (1,0) [0|0] "0" FCU_C,GW_RGW,MDPS,SFA + SG_ ADAS_ActvACISta : 24|4@1+ (1,0) [0|0] "" GW_RGW,MDPS,SFA + SG_ ADAS_ActvACILvl2Sta : 28|4@1+ (1,0) [0|0] "" ESC,FCU_C,GW_RGW,MDPS,SFA,VPC_C + SG_ ADAS_StrAnglReqVal : 32|14@1- (0.1,0) [0|119.9] "Deg" GW_RGW,MDPS,SFA + SG_ ADAS_ACIAnglTqRedcGainVal : 48|8@1+ (0.004,0) [0|1] "" GW_RGW,MDPS,SFA + SG_ FCA_ESA_ActvSta : 56|2@1+ (1,0) [0|0] "" GW_RGW,MDPS,SFA + SG_ FCA_ESA_TqBstGainVal : 64|8@1+ (0.004,0) [0|0] "" GW_RGW,MDPS,SFA + +BO_ 234 MDPS: 24 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ LKA_ACTIVE : 48|1@0+ (1,0) [0|16777215] "" XXX + SG_ LKA_FAULT : 54|1@0+ (1,0) [0|1] "" XXX + SG_ STEERING_OUT_TORQUE : 64|12@1+ (0.1,-204.8) [0|65535] "" XXX + SG_ STEERING_COL_TORQUE : 80|13@1+ (1,-4095) [0|4095] "" XXX + SG_ STEERING_ANGLE : 96|16@1- (0.1,0) [0|255] "deg" XXX + SG_ STEERING_ANGLE_2 : 128|16@1- (0.1,0) [0|65535] "deg" XXX + SG_ LKA_ANGLE_ACTIVE : 145|2@0+ (1,0) [0|3] "" XXX + SG_ LKA_ANGLE_FAULT : 149|1@0+ (1,0) [0|1] "" XXX + +BO_ 256 ACCELERATOR_BRAKE_ALT: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRESSED : 32|1@1+ (1,0) [0|1] "" XXX + SG_ ACCELERATOR_PEDAL_PRESSED : 176|1@1+ (1,0) [0|1] "" XXX + +BO_ 261 ACCELERATOR_ALT: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ ACCELERATOR_PEDAL : 103|10@1+ (0.25,0) [0|1022] "" XXX + +BO_ 272 LKAS_ALT: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ LKA_MODE : 24|3@1+ (1,0) [0|7] "" XXX + SG_ LKA_AVAILABLE : 27|2@1+ (1,0) [0|255] "" XXX + SG_ LKA_WARNING : 32|1@1+ (1,0) [0|1] "" XXX + SG_ LKA_ICON : 38|2@1+ (1,0) [0|255] "" XXX + SG_ FCA_SYSWARN : 40|1@0+ (1,0) [0|1] "" XXX + SG_ TORQUE_REQUEST : 41|11@1+ (1,-1024) [0|4095] "" XXX + SG_ STEER_REQ : 52|1@1+ (1,0) [0|1] "" XXX + SG_ LFA_BUTTON : 56|1@1+ (1,0) [0|255] "" XXX + SG_ LKA_ASSIST : 62|1@1+ (1,0) [0|1] "" XXX + SG_ STEER_MODE : 65|3@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 70|2@0+ (1,0) [0|3] "" XXX + SG_ LKAS_ANGLE_ACTIVE : 77|2@0+ (1,0) [0|3] "" XXX + SG_ HAS_LANE_SAFETY : 80|1@0+ (1,0) [0|1] "" XXX + SG_ ADAS_StrAnglReqVal : 82|14@1- (0.1,0) [0|176.7] "Deg" GW_RGW,MDPS,SFA + SG_ ADAS_ACIAnglTqRedcGainVal : 96|8@1+ (0.004,0) [0|1] "" GW_RGW,MDPS,SFA + SG_ DAMP_FACTOR : 64|8@1+ (1,0) [0|255] "" XXX + +BO_ 282 FR_CMR_01_10ms: 16 FR_CMR + SG_ FR_CMR_Crc1Val : 0|16@1+ (1,0) [0|0] "" Dummy,IBU_HS,vBDM + SG_ FR_CMR_AlvCnt1Val : 16|8@1+ (1,0) [0|0] "" CLU,IBU_HS,vBDM + SG_ HBA_SysOptSta : 24|2@1+ (1,0) [0|3] "" CLU,IBU_HS,vBDM + SG_ HBA_SysSta : 26|3@1+ (1,0) [0|7] "" CLU,IBU_HS,vBDM + SG_ HBA_IndLmpReq : 29|2@1+ (1,0) [0|3] "" CLU,vBDM + SG_ iHBAref_VehLftSta : 31|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM + SG_ iHBAref_VehCtrSta : 33|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM + SG_ iHBAref_VehRtSta : 35|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM + SG_ iHBAref_ILLAmbtSta : 37|2@1+ (1,0) [0|3] "" IBU_HS,ICU,vBDM + SG_ FCA_Equip_MFC : 39|3@1+ (1,0) [0|0] "" ADAS_DRV,RR_C_RDR,vBDM + SG_ HBA_OptUsmSta : 42|2@1+ (1,0) [0|3] "" CLU,H_U_MM + SG_ FCAref_FusSta : 45|3@1+ (1,0) [0|0] "" vBDM + SG_ DAW_LVDA_PUDis : 48|2@1+ (1,0) [0|0] "" CLU,vBDM + SG_ DAW_LVDA_OptUsmSta : 50|2@1+ (1,0) [0|3] "" CLU,H_U_MM,vBDM + SG_ DAW_OptUsmSta : 52|3@1+ (1,0) [0|0] "" CLU,H_U_MM + SG_ DAW_SysSta : 55|4@1+ (1,0) [0|0] "" CLU + SG_ DAW_WrnMsgSta : 59|3@1+ (1,0) [0|0] "" CLU + SG_ DAW_TimeRstReq : 62|2@1+ (1,0) [0|0] "" CLU + SG_ DAW_SnstvtyModRetVal : 64|3@1+ (1,0) [0|0] "" CLU,H_U_MMz + SG_ FR_CMR_SCCEquipSta : 85|2@1+ (1,0) [0|3] "" CGW + SG_ FR_CMR_ReqADASMapMsgVal : 96|16@1+ (1,0) [0|65535] "" CGW + SG_ FR_CMR_SwVer1Val : 112|4@1+ (1,0) [0|15] "" CGW + SG_ FR_CMR_SwVer2Val : 120|8@1+ (1,0) [0|255] "" CGW + +BO_ 293 STEERING_SENSORS: 16 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ STEERING_ANGLE : 24|16@1- (0.1,0) [0|255] "deg" XXX + SG_ STEERING_RATE : 40|8@1+ (4,0) [0|1016] "deg/s" XXX + +BO_ 298 LFA: 16 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ LKA_MODE : 24|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_1 : 27|2@1+ (1,0) [0|255] "" XXX + SG_ LKA_WARNING : 32|1@1+ (1,0) [0|1] "" XXX + SG_ LKA_ICON : 38|2@1+ (1,0) [0|255] "" XXX + SG_ TORQUE_REQUEST : 41|11@1+ (1,-1024) [0|4095] "" XXX + SG_ STEER_REQ : 52|1@1+ (1,0) [0|1] "" XXX + SG_ LFA_BUTTON : 56|1@1+ (1,0) [0|255] "" XXX + SG_ LKA_ASSIST : 62|1@1+ (1,0) [0|1] "" XXX + SG_ STEER_MODE : 65|3@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 70|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_4 : 72|4@1+ (1,0) [0|15] "" XXX + SG_ HAS_LANE_SAFETY : 80|1@0+ (1,0) [0|1] "" XXX + SG_ DAMP_FACTOR : 104|8@1+ (1,0) [0|255] "" XXX + +BO_ 304 GEAR_SHIFTER: 16 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ PARK_BUTTON : 32|2@1+ (1,0) [0|3] "" XXX + SG_ KNOB_POSITION : 40|3@1+ (1,0) [0|3] "" XXX + SG_ GEAR : 64|3@1+ (1,0) [0|7] "" XXX + +BO_ 352 ADRV_0x160: 16 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ AEB_SETTING : 24|2@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_2 : 56|8@1+ (1,0) [0|1] "" XXX + SG_ SET_ME_FF : 64|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_FC : 72|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_9 : 80|8@1+ (1,0) [0|255] "" XXX + +BO_ 353 CCNC_0x161: 32 CCNC + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ FCA_ICON : 24|3@1+ (1,0) [0|7] "" XXX + SG_ FCA_ALT_ICON : 27|3@1+ (1,0) [0|7] "" XXX + SG_ LKA_ICON : 30|3@1+ (1,0) [0|3] "" XXX + SG_ HBA_ICON : 33|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_1 : 36|4@1+ (1,0) [0|15] "" XXX + SG_ ZEROS_2 : 40|2@1+ (1,0) [0|3] "" XXX + SG_ FCA_IMAGE : 42|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_3 : 45|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_4 : 48|3@1+ (1,0) [0|7] "" XXX + SG_ BCA_LEFT : 51|3@1+ (1,0) [0|7] "" XXX + SG_ BCA_RIGHT : 54|3@1+ (1,0) [0|7] "" XXX + SG_ LCA_LEFT_ARROW : 57|3@1+ (1,0) [0|7] "" XXX + SG_ LCA_RIGHT_ARROW : 60|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_5 : 63|1@0+ (1,0) [0|1] "" XXX + SG_ CENTERLINE : 64|2@1+ (1,0) [0|3] "" XXX + SG_ TARGET : 66|3@1+ (1,0) [0|7] "" XXX + SG_ TARGET_DISTANCE : 69|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ LANELINE_LEFT : 80|4@1+ (1,0) [0|15] "" XXX + SG_ LANELINE_LEFT_POSITION : 84|6@1+ (1,0) [0|15] "" XXX + SG_ LANELINE_RIGHT : 90|4@1+ (1,0) [0|15] "" XXX + SG_ LANELINE_RIGHT_POSITION : 94|6@1+ (1,0) [0|3] "" XXX + SG_ LANELINE_CURVATURE : 100|5@1- (1,15) [0|31] "" XXX + SG_ LANE_HIGHLIGHT : 105|4@1+ (1,0) [0|15] "" XXX + SG_ LANE_HIGHLIGHT_DISTANCE : 109|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ LANE_LEFT : 120|3@1+ (1,0) [0|7] "" XXX + SG_ LANE_RIGHT : 123|3@1+ (1,0) [0|7] "" XXX + SG_ LANE_ZOOM : 126|2@1+ (1,0) [0|3] "" XXX + SG_ ALERTS_1 : 128|6@1+ (1,0) [0|63] "" XXX + SG_ ALERTS_2 : 134|5@1+ (1,0) [0|3] "" XXX + SG_ ALERTS_3 : 139|5@1+ (1,0) [0|15] "" XXX + SG_ ALERTS_4 : 144|8@1+ (1,0) [0|511] "" XXX + SG_ ALERTS_5 : 152|5@1+ (1,0) [0|7] "" XXX + SG_ MUTE : 157|3@1+ (1,0) [0|7] "" XXX + SG_ SOUNDS_1 : 160|4@1+ (1,0) [0|3] "" XXX + SG_ SOUNDS_2 : 164|4@1+ (1,0) [0|3] "" XXX + SG_ SOUNDS_3 : 168|4@1+ (1,0) [0|15] "" XXX + SG_ SOUNDS_4 : 172|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_6 : 175|1@0+ (1,0) [0|1] "" XXX + SG_ ZEROS_7 : 176|5@1+ (1,0) [0|31] "" XXX + SG_ SETSPEED_HUD : 181|3@1+ (1,0) [0|3] "" XXX + SG_ DISTANCE_LEAD : 184|5@1+ (1,0) [0|31] "" XXX + SG_ DISTANCE_CAR : 189|3@1+ (1,0) [0|7] "" XXX + SG_ DISTANCE_SPACING : 192|4@1+ (1,0) [0|15] "" XXX + SG_ DISTANCE : 196|4@1+ (1,0) [0|7] "" XXX + SG_ SETSPEED_SPEED : 200|8@1+ (1,0) [0|255] "" XXX + SG_ SETSPEED : 208|4@1+ (1,0) [0|3] "" XXX + SG_ HDA_ICON : 212|4@1+ (1,0) [0|3] "" XXX + SG_ SLA_ICON : 216|4@1+ (1,0) [0|15] "" XXX + SG_ NAV_ICON : 220|4@1+ (1,0) [0|3] "" XXX + SG_ LFA_ICON : 224|4@1+ (1,0) [0|3] "" XXX + SG_ LCA_LEFT_ICON : 228|4@1+ (1,0) [0|15] "" XXX + SG_ LCA_RIGHT_ICON : 232|4@1+ (1,0) [0|15] "" XXX + SG_ BACKGROUND : 236|4@1+ (1,0) [0|15] "" XXX + SG_ DAW_ICON : 240|3@1+ (1,0) [0|7] "" XXX + SG_ CAR_CIRCLE : 243|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_8 : 246|2@1+ (1,0) [0|3] "" XXX + SG_ ZEROS_9 : 248|8@1+ (1,0) [0|255] "" XXX + +BO_ 354 CCNC_0x162: 32 CCNC + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTRY : 24|4@1+ (1,0) [0|7] "" XXX + SG_ SPEEDLIMIT_FLASH : 28|4@1+ (1,0) [0|15] "" XXX + SG_ SPEEDLIMIT : 32|8@1+ (1,0) [0|255] "" XXX + SG_ SIGNS : 40|8@1+ (1,0) [0|15] "" XXX + SG_ SPEEDLIMIT_WEATHER : 48|4@1+ (1,0) [0|15] "" XXX + SG_ VIBRATE : 52|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_1 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ZEROS_2 : 56|8@1+ (1,0) [0|255] "" XXX + SG_ LEAD : 64|5@1+ (1,0) [0|31] "" XXX + SG_ LEAD_DISTANCE : 69|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ LEAD_LATERAL : 80|7@1+ (0.1,0) [0|127] "m" XXX + SG_ ZEROS_3 : 87|1@0+ (1,0) [0|1] "" XXX + SG_ LEAD_ALT : 88|5@1+ (1,0) [0|31] "" XXX + SG_ LEAD_ALT_DISTANCE : 93|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ LEAD_ALT_LATERAL : 104|7@1+ (0.1,0) [0|127] "m" XXX + SG_ ZEROS_4 : 111|1@0+ (1,0) [0|1] "" XXX + SG_ LEAD_LEFT : 112|5@1+ (1,0) [0|31] "" XXX + SG_ LEAD_LEFT_DISTANCE : 117|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ LEAD_LEFT_LATERAL : 128|7@1+ (0.1,0) [0|127] "m" XXX + SG_ ZEROS_5 : 135|1@0+ (1,0) [0|1] "" XXX + SG_ LEAD_RIGHT : 136|5@1+ (1,0) [0|31] "" XXX + SG_ LEAD_RIGHT_DISTANCE : 141|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ LEAD_RIGHT_LATERAL : 152|7@1+ (0.1,0) [0|127] "m" XXX + SG_ ZEROS_6 : 159|1@0+ (1,0) [0|1] "" XXX + SG_ ZEROS_7 : 162|3@0+ (1,0) [0|7] "" XXX + SG_ LEAD_LEFT_REAR_STATUS : 167|5@0+ (1,0) [0|31] "" XXX + SG_ LEAD_LEFT_REAR_DISTANCE : 175|8@0+ (0.1,0) [0|255] "m" XXX + SG_ LEAD_LEFT_REAR_LATERAL : 182|7@0+ (0.1,0) [0|127] "m" XXX + SG_ ZEROS_8 : 183|1@0+ (1,0) [0|1] "" XXX + SG_ ZEROS_9 : 191|8@0+ (1,0) [0|255] "" XXX + SG_ LEAD_RIGHT_REAR_STATUS : 196|5@0+ (1,0) [0|31] "" XXX + SG_ LEAD_RIGHT_REAR_DISTANCE : 197|8@1+ (0.1,0) [0|255] "m" XXX + SG_ LEAD_RIGHT_REAR_LATERAL : 205|7@1+ (0.1,0) [0|127] "m" XXX + SG_ ZEROS_10 : 212|1@0+ (1,0) [0|1] "" XXX + SG_ FAULT_FSS : 213|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_FCA : 216|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_LSS : 219|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_SLA : 222|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_DAW : 225|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_HBA : 228|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_SCC : 231|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_LFA : 234|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_HDA : 237|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_LCA : 240|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_HDP : 243|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_DAS : 246|3@1+ (1,0) [0|7] "" XXX + SG_ FAULT_ESS : 249|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_11 : 252|4@1+ (1,0) [0|15] "" XXX + +BO_ 357 SPAS1: 24 APRK + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_2 : 90|3@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 96|16@1- (0.1,0) [0|0] "" XXX + +BO_ 362 SPAS2: 32 APRK + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BLINKER_CONTROL : 133|3@1+ (1,0) [0|0] "" XXX + +BO_ 373 TCS: 24 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 24|7@1+ (1,0) [0|127] "" XXX + SG_ aBasis : 32|11@1+ (0.01,-10.23) [0|7] "m/s^2" XXX + SG_ ACCEL_REF_ACC : 48|11@1- (1,0) [0|1023] "" XXX + SG_ EQUIP_MAYBE : 64|1@0+ (1,0) [0|1] "" XXX + SG_ ACCEnable : 67|2@0+ (1,0) [0|3] "" XXX + SG_ ACC_REQ : 68|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 72|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 74|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 76|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 80|1@0+ (1,0) [0|1] "" XXX + SG_ DriverBraking : 81|1@0+ (1,0) [0|1] "" XXX + SG_ DriverBrakingLowSens : 84|1@1+ (1,0) [0|1] "" XXX + SG_ AEB_EQUIP_MAYBE : 96|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 128|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_7 : 135|2@0+ (1,0) [0|3] "" XXX + SG_ PROBABLY_EQUIP : 136|2@1+ (1,0) [0|3] "" XXX + +BO_ 416 SCC_CONTROL: 32 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ ACC_ObjDist : 24|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ ACC_ObjRelSpd : 35|9@1+ (0.1,-16.4) [-16.4|34.7] "m/s" XXX + SG_ SET_ME_3 : 45|2@0+ (1,0) [0|3] "" XXX + SG_ ObjValid : 46|1@0+ (1,0) [0|3] "" XXX + SG_ SET_ME_TMP_64 : 55|8@0+ (1,0) [0|63] "" XXX + SG_ ZEROS_7 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 64|2@1+ (1,0) [0|3] "" XXX + SG_ MainMode_ACC : 66|1@1+ (1,0) [0|1] "" XXX + SG_ ACCMode : 68|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_9 : 71|5@1+ (1,0) [0|15] "" XXX + SG_ CRUISE_STANDSTILL : 76|1@1+ (1,0) [0|1] "" XXX + SG_ ZEROS_5 : 77|11@1+ (1,0) [0|2047] "" XXX + SG_ DISTANCE_SETTING : 88|3@1+ (1,0) [0|3] "" XXX + SG_ ZEROS_8 : 95|5@0+ (1,0) [0|31] "" XXX + SG_ VSetDis : 103|8@0+ (1,0) [0|255] "km/h or mph" XXX + SG_ NEW_SIGNAL_6 : 104|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_2 : 105|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_3 : 109|2@0+ (1,0) [0|1] "" XXX + SG_ ZEROS_10 : 111|2@0+ (1,0) [0|3] "" XXX + SG_ ZEROS_6 : 119|16@0+ (1,0) [0|65535] "" XXX + SG_ aReqValue : 128|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX + SG_ aReqRaw : 140|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX + SG_ JerkUpperLimit : 158|7@0+ (0.1,0) [0|0] "" XXX + SG_ JerkLowerLimit : 166|7@0+ (0.1,0) [0|12.7] "m/s^3" XXX + SG_ NEW_SIGNAL_2 : 168|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_8 : 170|4@1+ (1,0) [0|15] "" XXX + SG_ OBJ_STATUS : 176|3@1+ (1,0) [0|7] "" XXX + SG_ ZEROS_4 : 183|4@0+ (1,0) [0|63] "" XXX + SG_ StopReq : 184|1@0+ (1,0) [0|1] "" XXX + SG_ ZEROS_3 : 191|7@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_15 : 192|11@1+ (0.1,0) [0|204.7] "m" XXX + SG_ ZEROS_2 : 207|5@0+ (1,0) [0|63] "" XXX + SG_ ZEROS : 215|48@0+ (1,0) [0|281474976710655] "" XXX + +BO_ 426 CRUISE_BUTTONS_ALT: 16 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 24|4@1+ (1,0) [0|15] "" XXX + SG_ SET_ME_1 : 28|2@1+ (1,0) [0|3] "" XXX + SG_ DISTANCE_UNIT : 30|1@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 31|3@1+ (1,0) [0|7] "" XXX + SG_ ADAPTIVE_CRUISE_MAIN_BTN : 34|1@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 35|1@1+ (1,0) [0|1] "" XXX + SG_ CRUISE_BUTTONS : 36|3@1+ (1,0) [0|4] "" XXX + SG_ LDA_BTN : 39|1@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 40|1@1+ (1,0) [0|1] "" XXX + SG_ NORMAL_CRUISE_MAIN_BTN : 41|1@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 42|2@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_2 : 44|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_6 : 47|1@1+ (1,0) [0|1] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE8 : 64|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE9 : 72|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE10 : 80|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE11 : 88|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE12 : 96|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE13 : 104|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE14 : 112|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE15 : 120|8@1+ (1,0) [0|255] "" XXX + +BO_ 437 FR_CMR_03_50ms: 32 FR_CMR + SG_ FR_CMR_Crc3Val : 0|16@1+ (1,0) [0|65535] "" RR_C_RDR,CGW + SG_ FR_CMR_AlvCnt3Val : 16|8@1+ (1,0) [0|255] "" RR_C_RDR,CGW + SG_ Info_LftLnQualSta : 24|3@1+ (1,0) [0|7] "" RR_C_RDR,CGW + SG_ Info_LftLnDptSta : 27|2@1+ (1,0) [0|3] "" RR_C_RDR,CGW + SG_ Info_LftLnPosVal : 29|14@1- (0.0039625,0) [-32.4608|32.4568375] "m" RR_C_RDR,CGW + SG_ Info_LftLnHdingAnglVal : 43|10@1- (0.000976563,0) [-0.500000256|0.499023693] "rad" RR_C_RDR,CGW + SG_ Info_LftLnCvtrVal : 64|16@1- (1e-06,0) [-0.032768|0.032767] "1/m" CGW + SG_ Info_LftLnCrvtrDrvtvVal : 80|16@1- (4e-09,0) [-0.000131072|0.000131068] "1/m2" CGW + SG_ Info_RtLnQualSta : 96|3@1+ (1,0) [0|7] "" RR_C_RDR,CGW + SG_ Info_RtLnDptSta : 99|2@1+ (1,0) [0|3] "" RR_C_RDR,CGW + SG_ Info_RtLnPosVal : 101|14@1- (0.0039625,0) [-32.4608|32.4568375] "m" RR_C_RDR,CGW + SG_ Info_RtLnHdingAnglVal : 115|10@1- (0.000976563,0) [-0.500000256|0.499023693] "rad" RR_C_RDR,CGW + SG_ Info_RtLnCvtrVal : 128|16@1- (1e-06,0) [-0.032768|0.032767] "1/m" CGW + SG_ Info_RtLnCrvtrDrvtvVal : 144|16@1- (4e-09,0) [-0.000131072|0.000131068] "1/m2" CGW + SG_ ID_CIPV : 192|8@1+ (1,0) [0|255] "" XXX + SG_ Relative_Velocity : 200|12@1+ (0.05,-100) [-100|104.75] "m/s" XXX + SG_ Longitudinal_Distance : 212|12@1+ (0.05,0) [0|204.75] "m" XXX + +BO_ 442 BLINDSPOTS_REAR_CORNERS: 24 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ LEFT_BLOCKED : 24|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_MB : 30|1@0+ (1,0) [0|3] "" XXX + SG_ MORE_LEFT_PROB : 32|1@1+ (1,0) [0|3] "" XXX + SG_ FL_INDICATOR : 46|6@0+ (1,0) [0|1] "" XXX + SG_ FR_INDICATOR : 54|6@0+ (1,0) [0|63] "" XXX + SG_ RIGHT_BLOCKED : 64|1@0+ (1,0) [0|1] "" XXX + SG_ COLLISION_AVOIDANCE_ACTIVE : 68|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 96|1@0+ (1,0) [0|1] "" XXX + SG_ FL_INDICATOR_ALT : 138|1@0+ (1,0) [0|1] "" XXX + SG_ FR_INDICATOR_ALT : 141|1@0+ (1,0) [0|1] "" XXX + +BO_ 463 CRUISE_BUTTONS: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|255] "" XXX + SG_ CRUISE_BUTTONS : 16|3@1+ (1,0) [0|3] "" XXX + SG_ ADAPTIVE_CRUISE_MAIN_BTN : 19|1@1+ (1,0) [0|1] "" XXX + SG_ NORMAL_CRUISE_MAIN_BTN : 21|1@1+ (1,0) [0|1] "" XXX + SG_ LDA_BTN : 23|1@1+ (1,0) [0|1] "" XXX + SG_ RIGHT_PADDLE : 25|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_PADDLE : 27|1@1+ (1,0) [0|1] "" XXX + SG_ SET_ME_1 : 29|1@1+ (1,0) [0|1] "" XXX + +BO_ 474 ADRV_0x1da: 32 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_22 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_41 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 480 LFAHDA_CLUSTER: 16 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ HDA_ICON : 31|1@1+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 32|3@1+ (1,0) [0|7] "" XXX + SG_ LFA_ICON : 47|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 49|1@0+ (1,0) [0|1] "" XXX + +BO_ 485 BLINDSPOTS_FRONT_CORNER_1: 16 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ REVERSING : 24|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 31|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_7 : 32|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_8 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_9 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 80|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 88|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 96|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 108|2@0+ (1,0) [0|3] "" XXX + +BO_ 490 ADRV_0x1ea: 32 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_1C : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 32|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 47|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 64|6@1+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_5 : 72|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_6 : 75|5@1+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_7 : 80|5@1+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_8 : 88|7@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_9 : 96|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_FF : 120|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_10 : 143|5@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_11 : 144|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_12 : 152|6@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_13 : 160|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_14 : 163|5@1+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_16 : 168|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_15 : 175|4@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_17 : 176|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_18 : 184|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_19 : 208|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_20 : 212|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_TMP_F : 232|5@1+ (1,0) [0|31] "" XXX + SG_ SET_ME_TMP_F_2 : 240|5@1+ (1,0) [0|31] "" XXX + +BO_ 506 FR_CMR_02_100ms: 32 FR_CMR + SG_ FR_CMR_Crc2Val : 0|16@1+ (1,0) [0|65535] "" CGW + SG_ FR_CMR_AlvCnt2Val : 16|8@1+ (1,0) [0|255] "" CGW + SG_ ISLW_OptUsmSta : 24|2@1+ (1,0) [0|3] "" CLU,CGW + SG_ ISLW_SysSta : 26|2@1+ (1,0) [0|3] "" CLU,CGW + SG_ ISLW_NoPassingInfoDis : 28|3@1+ (1,0) [0|7] "" CLU,CGW + SG_ ISLW_OvrlpSignDis : 31|2@1+ (1,0) [0|3] "" CLU,CGW + SG_ ISLW_SpdCluMainDis : 33|8@1+ (1,0) [0|255] "" CLU,CGW + SG_ ISLW_SpdNaviMainDis : 41|8@1+ (1,0) [0|255] "" CGW + SG_ ISLW_SubCondinfoSta1 : 49|4@1+ (1,0) [0|15] "" CLU,CGW + SG_ ISLW_SubCondinfoSta2 : 53|4@1+ (1,0) [0|15] "" CLU,CGW + SG_ ISLW_SpdCluSubMainDis : 64|8@1+ (1,0) [0|255] "" CLU + SG_ ISLW_SpdCluDisSubCond1 : 72|8@1+ (1,0) [0|255] "" CLU,CGW + SG_ ISLW_SpdCluDisSubCond2 : 80|8@1+ (1,0) [0|255] "" CLU,CGW + SG_ ISLW_SpdNaviSubMainDis : 88|8@1+ (1,0) [0|255] "" CLU + SG_ ISLW_SpdNaviDisSubCond1 : 96|8@1+ (1,0) [0|255] "" CLU,CGW + SG_ ISLW_SpdNaviDisSubCond2 : 104|8@1+ (1,0) [0|255] "" CLU,CGW + SG_ ISLA_SpdwOffst : 112|8@1+ (1,0) [0|255] "" CLU,CGW + SG_ ISLA_SwIgnoreReq : 120|2@1+ (1,0) [0|3] "" CGW + SG_ ISLA_SpdChgReq : 122|2@1+ (1,0) [0|3] "" CGW + SG_ ISLA_SpdWrn : 124|2@1+ (1,0) [0|3] "" CLU,CGW + SG_ ISLA_IcyWrn : 126|2@1+ (1,0) [0|3] "" CLU,CGW + SG_ ISLA_SymFlashMod : 128|3@1+ (1,0) [0|7] "" CLU,CGW + SG_ ISLA_Popup : 131|3@1+ (1,0) [0|7] "" CLU + SG_ ISLA_OptUsmSta : 136|3@1+ (1,0) [0|7] "" CLU,CGW + SG_ ISLA_OffstUsmSta : 139|3@1+ (1,0) [0|7] "" CLU,CGW + SG_ ISLA_AutoUsmSta : 142|2@1+ (1,0) [0|3] "" CLU,CGW + SG_ ISLA_Cntry : 144|4@1+ (1,0) [0|15] "" CLU,CGW + SG_ ISLA_AddtnlSign : 149|5@1+ (1,0) [0|31] "" CLU,CGW + SG_ ISLA_SchoolZone : 154|2@1+ (1,0) [0|3] "" CLU,CGW + +BO_ 507 CAM_0x1fb: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 512 ADRV_0x200: 8 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_E1 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_3A : 32|8@1+ (1,0) [0|255] "" XXX + +BO_ 593 RADAR_0x251: 16 FRONT_RADAR + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 687 HOD_FD_01_100ms: 8 XXX + SG_ HOD_Dir_Status : 18|3@0+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_2 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ HOD_Option : 48|2@1+ (1,0) [0|255] "" XXX + +BO_ 698 FR_CMR_04_40ms: 32 FR_CMR + SG_ FR_CMR_Crc4Val : 0|16@1+ (1,0) [0|65535] "" Dummy + SG_ FR_CMR_AlvCnt4Val : 16|8@1+ (1,0) [0|255] "" Dummy + SG_ IFSref_FR_CMR_Sta : 24|2@1+ (1,0) [0|3] "" CGW + SG_ IFSref_VehNumVal : 26|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_ILLAmbtSta : 30|2@1+ (0.1,0) [0|0.3] "" CGW + SG_ IFSref_VehLftAngl1Val : 32|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl1Val : 41|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl2Val : 50|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehDst1Val : 59|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehRtAngl2Val : 64|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl3Val : 73|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl3Val : 82|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl4Val : 91|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl4Val : 100|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl5Val : 109|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl5Val : 118|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl6Val : 128|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl6Val : 137|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl7Val : 146|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl7Val : 155|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl8Val : 164|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl8Val : 173|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl9Val : 182|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl9Val : 192|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehLftAngl10Val : 201|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehRtAngl10Val : 210|9@1+ (0.1,-25) [-25|26.1] "Deg" CGW + SG_ IFSref_VehDst2Val : 219|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst3Val : 223|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst4Val : 227|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst5Val : 231|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst6Val : 235|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst7Val : 239|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst8Val : 243|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst9Val : 247|4@1+ (1,0) [0|15] "" CGW + SG_ IFSref_VehDst10Val : 251|4@1+ (1,0) [0|15] "" CGW + +BO_ 736 MANUAL_SPEED_LIMIT_ASSIST: 32 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ MSLA_STATUS : 26|2@1+ (1,0) [0|3] "" XXX + SG_ MSLA_ENABLED : 38|1@1+ (1,0) [0|1] "" XXX + SG_ MAX_SPEED : 55|8@0+ (1,0) [0|255] "" XXX + SG_ MAX_SPEED_COPY : 144|8@1+ (1,0) [0|255] "" XXX + +BO_ 837 ADRV_0x345: 8 ADRV + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_15 : 24|8@1+ (1,0) [0|255] "" XXX + +BO_ 866 CAM_0x362: 32 CAMERA + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ LEFT_LANE_LINE : 56|2@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_0 : 58|2@1+ (1,0) [0|3] "" XXX + SG_ RIGHT_LANE_LINE : 60|2@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_0_2 : 62|2@1+ (1,0) [0|3] "" XXX + SG_ BYTE8 : 64|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE9 : 72|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE10 : 80|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE11 : 88|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE12 : 96|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE13 : 104|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE14 : 112|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE15 : 120|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE16 : 128|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE17 : 136|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE18 : 144|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE19 : 152|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE20 : 160|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE21 : 168|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE22 : 176|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE23 : 184|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE24 : 192|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE25 : 200|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE26 : 208|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE27 : 216|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE28 : 224|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE29 : 232|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE30 : 240|8@1+ (1,0) [0|255] "" XXX + SG_ BYTE31 : 248|8@1+ (1,0) [0|255] "" XXX + +BO_ 874 BLINDSPOTS_FRONT_CORNER_2: 16 XXX + SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 961 BLINKER_STALKS: 8 XXX + SG_ CHECKSUM_MAYBE : 7|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER_ALT : 15|4@0+ (1,0) [0|15] "" XXX + SG_ HIGHBEAM_FORWARD : 18|1@0+ (1,0) [0|1] "" XXX + SG_ LIGHT_KNOB_POSITION : 21|2@0+ (1,0) [0|3] "" XXX + SG_ HIGHBEAM_BACKWARD : 26|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_BLINKER : 30|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_BLINKER : 32|1@0+ (1,0) [0|1] "" XXX + +BO_ 1041 DOORS_SEATBELTS: 8 XXX + SG_ CHECKSUM_MAYBE : 7|8@0+ (1,0) [0|65535] "" XXX + SG_ COUNTER_ALT : 15|4@0+ (1,0) [0|15] "" XXX + SG_ DRIVER_DOOR : 24|1@1+ (1,0) [0|1] "" XXX + SG_ PASSENGER_DOOR : 34|1@0+ (1,0) [0|1] "" XXX + SG_ PASSENGER_SEATBELT : 36|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_SEATBELT : 42|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_REAR_DOOR : 52|1@0+ (1,0) [0|1] "" XXX + SG_ PASSENGER_REAR_DOOR : 56|1@0+ (1,0) [0|1] "" XXX + +BO_ 1043 BLINKERS: 8 XXX + SG_ LEFT_STALK : 8|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_STALK : 10|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER_ALT : 15|4@0+ (1,0) [0|15] "" XXX + SG_ LEFT_LAMP : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_LAMP : 22|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_LAMP_ALT : 59|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_LAMP_ALT : 61|1@0+ (1,0) [0|1] "" XXX + SG_ USE_ALT_LAMP : 62|1@0+ (1,0) [0|1] "" XXX + +BO_ 1144 DRIVE_MODE: 8 XXX + SG_ DRIVE_MODE : 0|16@1+ (1,-61611) [0|61611] "" XXX + SG_ DRIVE_MODE2 : 28|3@1+ (1,0) [1|3] "" XXX + +BO_ 1151 HVAC_TOUCH_BUTTONS: 8 XXX + SG_ AUTO_BUTTON : 8|1@0+ (1,0) [0|1] "" XXX + SG_ SYNC_BUTTON : 12|1@0+ (1,0) [0|1] "" XXX + SG_ FR_DEFROST_BUTTON : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RR_DEFROST_BUTTON : 22|1@0+ (1,0) [0|1] "" XXX + SG_ FAN_SPEED_UP_BUTTON : 24|1@0+ (1,0) [0|1] "" XXX + SG_ FAN_SPEED_DOWN_BUTTON : 26|1@0+ (1,0) [0|1] "" XXX + SG_ AIR_DIRECTION_BUTTON : 28|1@0+ (1,0) [0|1] "" XXX + SG_ AC_BUTTON : 40|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_ONLY_BUTTON : 44|1@0+ (1,0) [0|1] "" XXX + SG_ RECIRC_BUTTON : 48|1@0+ (1,0) [0|1] "" XXX + SG_ HEAT_BUTTON : 52|1@0+ (1,0) [0|1] "" XXX + +BO_ 1240 CLUSTER_INFO: 8 XXX + SG_ DISTANCE_UNIT : 0|1@1+ (1,0) [0|1] "" XXX + +BO_ 1259 LOCAL_TIME2: 8 XXX + SG_ HOURS : 15|5@0+ (1,0) [0|31] "" XXX + SG_ MINUTES : 21|6@0+ (1,0) [0|63] "" XXX + SG_ SECONDS : 24|6@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_3 : 39|1@0+ (1,0) [0|1] "" XXX + +BO_ 1264 LOCAL_TIME: 8 XXX + SG_ HOURS : 12|5@0+ (1,0) [0|31] "" XXX + SG_ MINUTES : 21|6@0+ (1,0) [0|63] "" XXX + SG_ SECONDS : 31|8@0+ (1,0) [0|59] "" XXX + +CM_ SG_ 96 BRAKE_PRESSURE "User applied brake pedal pressure. Ramps from computer applied pressure on falling edge of cruise. Cruise cancels if !=0"; +CM_ SG_ 101 BRAKE_POSITION "User applied brake pedal position, max is ~700. Signed on some vehicles"; +CM_ SG_ 203 ADAS_ActvACISta "ADAS Active AngleControlInterface State"; +CM_ SG_ 203 ADAS_ActvACILvl2Sta "ADAS Active AngleControlInterface Level 2 State"; +CM_ SG_ 203 ADAS_StrAnglReqVal "(LFA) ADAS Steering Angle Request Value; Capped at 119.9;"; +CM_ SG_ 203 ADAS_ACIAnglTqRedcGainVal "(LFA) ADAS AngleControlInterface Angle Torque Reduction Gain Value"; +CM_ SG_ 203 FCA_ESA_ActvSta "FCA_ESA Active State"; +CM_ SG_ 203 FCA_ESA_TqBstGainVal "FCA_ESA Torque Boost Gain Value"; +CM_ BO_ 272 "Alternative LKAS message, used on cars such as 2023 Ioniq 6, 2nd gen Kona. Matches LKAS except size is 32 bytes"; +CM_ SG_ 272 LKA_AVAILABLE "Angle control cars: 3 when LKA is generally available, goes to 0 during changes with LFA"; +CM_ SG_ 272 ADAS_StrAnglReqVal "(LKAS) ADAS Steering Angle Request Value; Capped at 176.7; tracks MDPS->STEERING_ANGLE when not engaged, not STEERING_SENSORS->STEERING_ANGLE"; +CM_ SG_ 272 ADAS_ACIAnglTqRedcGainVal "(LKAS) ADAS AngleControlInterface Angle Torque Reduction Gain Value"; +CM_ BO_ 282 "Sent by the camera containing DAW (Driver Attention Warning) information and information about HBA (High Beam Assist)."; +CM_ SG_ 282 FR_CMR_Crc1Val "The data area for CRC calculation is based on the data length (DLC) of the message DB. The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID - CRC Polynomial (0x1021) , In"; +CM_ SG_ 282 FR_CMR_AlvCnt1Val "For the first transmission request for a data element the counter shall be initialized with 0 and shall be incremented by 1 for every subsequent send request. When the counter reaches the maximum value(0xFF), then it shall restart with 0 for the next s"; +CM_ SG_ 282 HBA_SysOptSta "HBA System Option Information to Lamp Controller"; +CM_ SG_ 282 HBA_SysSta "This signal indicates the status of High Beam Assist system."; +CM_ SG_ 282 HBA_IndLmpReq "HBA System Indicator Lamp Status"; +CM_ SG_ 282 FCA_Equip_MFC "FCA Sensor Type"; +CM_ SG_ 282 HBA_OptUsmSta "HBA Option USM Status"; +CM_ SG_ 282 DAW_LVDA_PUDis "Message for displaying LVDA(Leading Vehicle Departure Alert) Warning"; +CM_ SG_ 282 DAW_LVDA_OptUsmSta "LVDA USM state"; +CM_ SG_ 282 DAW_OptUsmSta "This signal represents the lastest DAW ON/OFF value of USM."; +CM_ SG_ 282 DAW_SysSta "This signal represents Attention Assist System Status or Attention Level."; +CM_ SG_ 282 DAW_WrnMsgSta "0x1 value requests DAW Rest recommend warning message popup at CLU. 0x2 value requests HDA/LFA Hands-Off call at TMS."; +CM_ SG_ 282 DAW_TimeRstReq "This signal requests CLU 'Last Break Time' Reset. DAW send '0x1' when detecting driver's rest."; +CM_ SG_ 282 DAW_SnstvtyModRetVal "This signal represents the feedback value of the current ADAS warning timing."; +CM_ SG_ 282 FR_CMR_SCCEquipSta "This signal indicates equipment for SCC"; +CM_ SG_ 282 FR_CMR_ReqADASMapMsgVal "This signal indicates an ADAS map message request from FR_CMR to H_U. Each bit indicates the request messages as follows. - Bit 0 : H_U_NAVI_V2_STUB_E - Bit 1 : HU_NAVI_V2_PROSHORT_E_00 (곡률) - Bit 2 : HU_NAVI_V2_PROSHORT_E_00 (곡률 외 정보)"; +CM_ SG_ 282 FR_CMR_SwVer1Val "This signal indicates a major version of FR_CMR software. If FR_CMR software version is A.00, 'A' and '00' mean major and minor version respectively."; +CM_ SG_ 282 FR_CMR_SwVer2Val "This signal indicates a minor version of FR_CMR software. If FR_CMR software version is A.00, 'A' and '00' mean major and minor version respectively."; +CM_ SG_ 298 NEW_SIGNAL_4 "todo: figure out why always set to 9"; +CM_ SG_ 352 SET_ME_9 "has something to do with AEB settings"; +CM_ SG_ 373 ACCEnable "Likely a copy of CAN's TCS13->ACCEnable"; +CM_ SG_ 373 DriverBraking "Likely derived from BRAKE->BRAKE_POSITION"; +CM_ SG_ 373 DriverBrakingLowSens "Higher threshold version of DriverBraking"; +CM_ SG_ 373 PROBABLY_EQUIP "aeb equip?"; +CM_ SG_ 416 VSetDis "set speed in display units"; +CM_ BO_ 437 "Sent by the camera containing lane and lead information."; +CM_ SG_ 437 FR_CMR_Crc3Val "The data area for CRC calculation is based on the data length (DLC) of the message DB. The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID - CRC Polynomial (0x1021) , In"; +CM_ SG_ 437 FR_CMR_AlvCnt3Val "For the first transmission request for a data element the counter shall be initialized with 0 and shall be incremented by 1 for every subsequent send request. When the counter reaches the maximum value(0xFF), then it shall restart with 0 for the next s"; +CM_ SG_ 437 Info_LftLnQualSta "This signal indicates the quality of left line."; +CM_ SG_ 437 Info_LftLnDptSta "This signal indicates the lane departure status of left line."; +CM_ SG_ 437 Info_LftLnPosVal "This signal outputs the position of left line from camera center."; +CM_ SG_ 437 Info_LftLnHdingAnglVal "This signal outputs the heading angle of left line."; +CM_ SG_ 437 Info_LftLnCvtrVal "This signal outputs the curvature of left line."; +CM_ SG_ 437 Info_RtLnQualSta "This signal indicates the quality of right line."; +CM_ SG_ 437 Info_RtLnDptSta "This signal indicates the lane departure status of right line."; +CM_ SG_ 437 Info_RtLnPosVal "This signal outputs the position of right line from camera center."; +CM_ SG_ 437 Info_RtLnHdingAnglVal "This signal outputs the heading angle of right line."; +CM_ SG_ 437 Info_RtLnCvtrVal "This signal outputs the curvature of right line."; +CM_ SG_ 437 ID_CIPV "Valid Object = 1 to 255 - ID detected by front camera can vary depending on vehicle environment. - Additional logic would be required to apply this signal for ISG."; +CM_ SG_ 437 Relative_Velocity "+ : Preceding, - : Oncoming - Velocity detected by front camera can vary depending on vehicle environment. - Additional logic would be required to apply this signal for ISG. - Confirmaiton by Autonomous Driving Engineering Team is required to use ID_C"; +CM_ SG_ 480 NEW_SIGNAL_5 "todo: figure out why always set to 1"; +CM_ BO_ 506 "Sent by the camera containing speed limit information. ISLW stands for Intelligent Speed Limit Warning, and ISLA is Intelligent Speed Limit Assist. it also contains road sign information."; +CM_ SG_ 506 FR_CMR_Crc2Val "The data area for CRC calculation is based on the data length (DLC) of the message DB.The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID - CRC Polynomial (0x1021) , In"; +CM_ SG_ 506 FR_CMR_AlvCnt2Val "For the first transmission request for a data element the counter shall be initialized with 0 and shall be incremented by 1 for every subsequent send request. When the counter reaches the maximum value(0xFF), then it shall restart with 0 for the next s"; +CM_ SG_ 506 ISLW_OptUsmSta "ISLW option information"; +CM_ SG_ 506 ISLW_SysSta "Validity of ISLW information"; +CM_ SG_ 506 ISLW_NoPassingInfoDis "This signal indicates additional information of ISLW. For example no passing."; +CM_ SG_ 506 ISLW_OvrlpSignDis "indicates presence of Overlap sign"; +CM_ SG_ 506 ISLW_SpdCluMainDis "Main Speed Information for cluster display in main page(0x1~0xFCH: 1*(HEX VALUE) [KPH or MPH :Reference signal is CF_Clu_SPEED_UNIT of CLU])"; +CM_ SG_ 506 ISLW_SpdNaviMainDis "Main Speed information for navigation display in main page(0x1~0xFCH: 1*(HEX VALUE) [KPH or MPH :Reference signal is Navi_ISLW_SpdUnit of Navigation)"; +CM_ SG_ 506 ISLW_SubCondinfoSta1 "Indicates 1st conditional traffic sign status"; +CM_ SG_ 506 ISLW_SubCondinfoSta2 "Indicates 2nd conditional traffic sign status"; +CM_ SG_ 506 ISLW_SpdCluSubMainDis "Main Speed Information for cluster display in ISLW detail page"; +CM_ SG_ 506 ISLW_SpdCluDisSubCond1 "Indicates conditional speed limit/no passing of 1st conditional traffic sign for Cluster in ISLW Detail page"; +CM_ SG_ 506 ISLW_SpdCluDisSubCond2 "Indicates conditional speed limit/no passing of 2nd conditional traffic sign for Cluster in ISLW Detail page"; +CM_ SG_ 506 ISLW_SpdNaviSubMainDis "Main Speed Information for NAVI display in ISLW detail page"; +CM_ SG_ 506 ISLW_SpdNaviDisSubCond1 "Indicates conditional speed limit/no passing of 1st conditional traffic sign for NAVI in ISLW Detail page"; +CM_ SG_ 506 ISLW_SpdNaviDisSubCond2 "Indicates conditional speed limit/no passing of 2nd conditional traffic sign for NAVI in ISLW Detail page"; +CM_ SG_ 506 ISLA_SpdwOffst "This is a ISLA speed with offset to change the set speed of MSLA/CC/SCC.Unit (kph or mph) refers to cluster signal: CLU_SpdUnitTyp@CLU_01_20ms"; +CM_ SG_ 506 ISLA_SwIgnoreReq "This is a signal requesting to ignore the -(SET) or +(SET) switch input of the driver."; +CM_ SG_ 506 ISLA_SpdChgReq "This is a signal requesting to change the set speed of MSLA/CC/SCC to the ISLA speed."; +CM_ SG_ 506 ISLA_SpdWrn "This is a warning signal when VANZ exceeds the speed limit."; +CM_ SG_ 506 ISLA_IcyWrn "This is a warning signal when the snow or ice sign is recognized when it is less than 4 'C."; +CM_ SG_ 506 ISLA_SymFlashMod "This is a signal for the flashing mode of the symbol."; +CM_ SG_ 506 ISLA_Popup "This is a signal for ISLA pop-up."; +CM_ SG_ 506 ISLA_OptUsmSta "This is a ISLA option USM signal set by the driver."; +CM_ SG_ 506 ISLA_OffstUsmSta "This is a signal for offset speed set by the driver. Unit (kph or mph) refers to cluster signal: CLU_SpdUnitTyp@CLU_01_20ms"; +CM_ SG_ 506 ISLA_AutoUsmSta "This is a signal for ISLA AUTO USM set by the driver."; +CM_ SG_ 506 ISLA_Cntry "This is a signal for categorizing countries"; +CM_ SG_ 506 ISLA_AddtnlSign "This is a signal for additional sign"; +CM_ SG_ 506 ISLA_SchoolZone "This is a signal for School Zone"; +CM_ SG_ 687 HOD_Dir_Status "This signal indicates the status of hands on/off"; +CM_ BO_ 698 "Sent by the camera containing information about vehicles in front of us. IFS stands for Intelligent Front-lighting System, and this signal provides the information necessary for it to operate."; +CM_ SG_ 698 FR_CMR_Crc4Val "The data area for CRC calculation is based on the data length (DLC) of the message DB. The CRC shall be calculated over the entire data block (excluding the CRC bytes) including the user data, alive counter and Data ID - CRC Polynomial (0x1021) , In"; +CM_ SG_ 698 FR_CMR_AlvCnt4Val "For the first transmission request for a data element the counter shall be initialized with 0 and shall be incremented by 1 for every subsequent send request. When the counter reaches the maximum value(0xFF), then it shall restart with 0 for the next s"; +CM_ SG_ 698 IFSref_FR_CMR_Sta "This is IFS system status needed for operate the IFS function of headlamp highbeam"; +CM_ SG_ 698 IFSref_VehNumVal "This is number of vehicles detected from camera"; +CM_ SG_ 698 IFSref_ILLAmbtSta "This signal is status of the ambient brightness 0x0 is bright condition (HighBeam off), 0x1 is dark condition (None)"; +CM_ SG_ 698 IFSref_VehLftAngl1Val "This is left angle of vehicle 1 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl1Val "This is right angle of vehicle 1 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl2Val "This is left angle of vehicle 2 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehDst1Val "IFSref_VehicleDistance1Value"; +CM_ SG_ 698 IFSref_VehRtAngl2Val "This is right angle of vehicle 2 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl3Val "This is left angle of vehicle 3 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl3Val "This is right angle of vehicle 3 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl4Val "This is left angle of vehicle 4 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl4Val "This is right angle of vehicle 4 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl5Val "This is left angle of vehicle 5 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl5Val "This is right angle of vehicle 5 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl6Val "This is left angle of vehicle 6 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl6Val "This is right angle of vehicle 6 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl7Val "This is left angle of vehicle 7 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl7Val "This is right angle of vehicle 7 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl8Val "This is left angle of vehicle 8 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl8Val "This is right angle of vehicle 8 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl9Val "This is left angle of vehicle 9 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl9Val "This is right angle of vehicle 9 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehLftAngl10Val "This is left angle of vehicle 10 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehRtAngl10Val "This is right angle of vehicle 10 Deg = (HEX)*0.1-25"; +CM_ SG_ 698 IFSref_VehDst2Val "IFSref_VehicleDistance2Value"; +CM_ SG_ 698 IFSref_VehDst3Val "IFSref_VehicleDistance3Value"; +CM_ SG_ 698 IFSref_VehDst4Val "IFSref_VehicleDistance4Value"; +CM_ SG_ 698 IFSref_VehDst5Val "IFSref_VehicleDistance5Value"; +CM_ SG_ 698 IFSref_VehDst6Val "IFSref_VehicleDistance6Value"; +CM_ SG_ 698 IFSref_VehDst7Val "IFSref_VehicleDistance7Value"; +CM_ SG_ 698 IFSref_VehDst8Val "IFSref_VehicleDistance8Value"; +CM_ SG_ 698 IFSref_VehDst9Val "IFSref_VehicleDistance9Value"; +CM_ SG_ 698 IFSref_VehDst10Val "IFSref_VehicleDistance10Value"; +CM_ SG_ 736 MAX_SPEED "Display units. Restricts car from driving above this speed unless accelerator pedal is depressed beyond pressure point"; +CM_ BO_ 866 "Contains signals with detailed lane line information. Used by ADAS ECU on HDA 2 vehicles to operate LFA. Used on cars that use message 272."; +CM_ SG_ 866 LEFT_LANE_LINE "Left lane line confidence"; +CM_ SG_ 866 RIGHT_LANE_LINE "Right lane line confidence"; +CM_ SG_ 961 COUNTER_ALT "only increments on change"; +CM_ SG_ 1041 COUNTER_ALT "only increments on change"; +CM_ BO_ 1043 "Lamp signals do not seem universal on cars that use LKAS_ALT, but stalk signals do."; +CM_ SG_ 1043 COUNTER_ALT "only increments on change"; +CM_ SG_ 1043 USE_ALT_LAMP "likely 1 on cars that use alt lamp signals"; +VAL_ 53 GEAR 0 "P" 5 "D" 6 "N" 7 "R"; +VAL_ 64 GEAR 0 "P" 5 "D" 6 "N" 7 "R"; +VAL_ 69 GEAR 0 "P" 5 "D" 6 "N" 7 "R"; +VAL_ 96 TRACTION_AND_STABILITY_CONTROL 0 "On" 5 "Limited" 1 "Off"; +VAL_ 112 GEAR 0 "P" 5 "D" 6 "N" 7 "R"; +VAL_ 203 ADAS_ActvACISta 0 "INIT" 1 "INACTIVE" 2 "ACTIVE35(ACTIVE)" 3 "ACTIVE33(Redundancy)" 4 "RESERVED" 5 "RESERVED" 6 "RESERVED" 7 "RESERVED" 8 "RESERVED" 9 "RESERVED" 10 "RESERVED" 11 "RESERVED" 12 "RESERVED" 13 "RESERVED" 14 "RESERVED" 15 "RESERVED"; +VAL_ 203 ADAS_ActvACILvl2Sta 0 "INIT" 1 "INACTIVE" 2 "ACTIVE35(ACTIVE)" 3 "RESERVED" 4 "RESERVED" 5 "RESERVED" 6 "RESERVED" 7 "RESERVED" 8 "RESERVED" 9 "RESERVED" 10 "RESERVED" 11 "RESERVED" 12 "RESERVED" 13 "RESERVED" 14 "RESERVED" 15 "RESERVED"; +VAL_ 203 ADAS_StrAnglReqVal 0 "0x0x000~0x3FFF:Real Values" 16383 "0x0x000~0x3FFF:Real Values"; +VAL_ 203 ADAS_ACIAnglTqRedcGainVal 0 "0x0x00~0xFA:Real Values" 250 "0x0x00~0xFA:Real Values" 251 "RESERVED" 252 "RESERVED" 253 "RESERVED" 254 "RESERVED" 255 "RESERVED"; +VAL_ 203 FCA_ESA_ActvSta 0 "Inactive" 1 "Active" 2 "RESERVED" 3 "RESERVED"; +VAL_ 203 FCA_ESA_TqBstGainVal 0 "0x0x00~0xFA:Real Values" 250 "0x0x00~0xFA:Real Values" 251 "RESERVED" 252 "RESERVED" 253 "RESERVED" 254 "RESERVED" 255 "RESERVED"; +VAL_ 234 LKA_FAULT 0 "ok" 1 "lka fault"; +VAL_ 272 LKA_MODE 1 "warning only" 2 "assist" 6 "off"; +VAL_ 272 LKA_ICON 0 "hidden" 1 "grey" 2 "green" 3 "flashing green"; +VAL_ 272 LKAS_ANGLE_ACTIVE 0 "off" 1 "not active" 2 "active"; +VAL_ 282 HBA_SysOptSta 0 "None HBA Option (Default)" 1 "HBA Option" 2 "Reserved" 3 "Error indicator"; +VAL_ 282 HBA_SysSta 0 "HBA Disable" 1 "HBA Enable & High Beam Off" 2 "HBA Enable & High Beam On" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "System Fail"; +VAL_ 282 HBA_IndLmpReq 0 "HBA Indicator Lamp Off" 1 "HBA Indicator Lamp On" 2 "Reserved" 3 "Error indicator"; +VAL_ 282 FCA_Equip_MFC 0 "No Coding" 1 "Sensor Fusion FCA" 2 "Camera only FCA" 3 "No FCA Option" 4 "ADAS_DRV Option" 5 "Reserved" 6 "Not used" 7 "Error indicator"; +VAL_ 282 HBA_OptUsmSta 0 "None HBA Option (Default)" 1 "HBA Function Off" 2 "HBA Function On" 3 "Invalid (Fail)"; +VAL_ 282 DAW_LVDA_PUDis 0 "Default" 1 "Display “Leading vehicle departure alert”" 2 "Reserved" 3 "Error indicator"; +VAL_ 282 DAW_LVDA_OptUsmSta 0 "No Option (default)" 1 "Off" 2 "On" 3 "Error Indicator"; +VAL_ 282 DAW_OptUsmSta 0 "None DAW Option (Default)" 1 "System Off" 2 "System On" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid (Gray)"; +VAL_ 282 DAW_SysSta 0 "System Off" 1 "Attention Level 1" 2 "Attention Level 2" 3 "Attention Level 3" 4 "Attention Level 4" 5 "Attention Level 5" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "System Standby" 15 "System Fail"; +VAL_ 282 DAW_WrnMsgSta 0 "No Warning" 1 "Rest Recommend Warning" 2 "Hands-Off TMS call request" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Error indicator"; +VAL_ 282 DAW_TimeRstReq 0 "No signal" 1 "Time reset" 2 "Reserved" 3 "Error indicator"; +VAL_ 282 DAW_SnstvtyModRetVal 0 "Default" 1 "Late" 2 "Normal" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid"; +VAL_ 282 FR_CMR_SCCEquipSta 0 "Not Applied" 1 "Applied" 2 "Not used" 3 "Error Indicator"; +VAL_ 298 LKA_MODE 1 "warning only" 2 "assist" 6 "off"; +VAL_ 298 LKA_ICON 0 "hidden" 1 "grey" 2 "green" 3 "flashing green"; +VAL_ 304 PARK_BUTTON 1 "Pressed" 2 "Not Pressed"; +VAL_ 304 KNOB_POSITION 1 "R" 2 "N (on R side)" 3 "Centered" 4 "N (on D side)" 5 "D"; +VAL_ 304 GEAR 1 "P" 2 "R" 3 "N" 4 "D"; +VAL_ 352 AEB_SETTING 1 "off" 2 "warning only" 3 "active assist"; +VAL_ 353 FCA_ICON 0 "HIDDEN" 1 "ORANGE" 2 "RED"; +VAL_ 353 FCA_ALT_ICON 0 "HIDDEN" 1 "ORANGE" 3 "RED"; +VAL_ 353 LKA_ICON 0 "HIDDEN" 1 "ORANGE" 3 "GRAY" 4 "GREEN"; +VAL_ 353 HBA_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN"; +VAL_ 353 FCA_IMAGE 0 "HIDDEN" 2 "VISIBLE"; +VAL_ 353 BCA_LEFT 0 "HIDDEN" 1 "VISIBLE" 2 "VISIBLE+ICON"; +VAL_ 353 BCA_RIGHT 0 "HIDDEN" 1 "VISIBLE" 2 "VISIBLE+ICON"; +VAL_ 353 LCA_LEFT_ARROW 0 "HIDDEN" 1 "VISIBLE"; +VAL_ 353 LCA_RIGHT_ARROW 0 "HIDDEN" 1 "VISIBLE"; +VAL_ 353 CENTERLINE 0 "HIDDEN" 1 "GREEN"; +VAL_ 353 TARGET 0 "HIDDEN" 1 "BLUE" 3 "WHITE"; +VAL_ 353 LANELINE_LEFT 0 "GRAY" 1 "HIDDEN" 2 "WHITE" 4 "ORANGE" 6 "GREEN"; +VAL_ 353 LANELINE_RIGHT 0 "GRAY" 1 "HIDDEN" 2 "WHITE" 4 "ORANGE" 6 "GREEN"; +VAL_ 353 LANE_HIGHLIGHT 0 "HIDDEN" 1 "GREEN" 2 "WHITE" 3 "BLUE" 4 "ORANGE" 5 "RED"; +VAL_ 353 LANE_LEFT 0 "HIDDEN" 1 "GREEN"; +VAL_ 353 LANE_RIGHT 0 "HIDDEN" 1 "GREEN"; +VAL_ 353 LANE_ZOOM 0 "ZOOM" 1 "HIDDEN"; +VAL_ 353 ALERTS_1 0 "HIDDEN" 1 "WARNING_ONLY_CAR_CENTER" 2 "WARNING_ONLY_CAR_LEFT" 3 "WARNING_ONLY_CAR_RIGHT" 4 "WARNING_ONLY_LEFT" 5 "WARNING_ONLY_RIGHT" 11 "EMERGENCY_BRAKING_CAR_CENTER" 12 "EMERGENCY_BRAKING_CAR_LEFT" 13 "EMERGENCY_BRAKING_CAR_RIGHT" 14 "EMERGENCY_BRAKING_LEFT" 15 "EMERGENCY_BRAKING_RIGHT" 21 "EMERGENCY_STEERING_CAR_LEFT" 22 "EMERGENCY_STEERING_CAR_RIGHT" 23 "EMERGENCY_STEERING_CAR_LEFT_AWAY" 24 "EMERGENCY_STEERING_CAR_RIGHT_AWAY" 25 "EMERGENCY_STEERING_REAR_LEFT" 26 "EMERGENCY_STEERING_REAR_RIGHT" 33 "DRIVE_CAREFULLY"; +VAL_ 353 ALERTS_2 0 "HIDDEN" 1 "KEEP_HANDS_ON_STEERING_WHEEL" 2 "KEEP_HANDS_ON_STEERING_WHEEL_RED" 3 "LANE_FOLLOWING_ASSIST_DEACTIVATED" 4 "HIGHWAY_DRIVING_ASSIST_DEACTIVATED" 5 "CONSIDER_TAKING_A_BREAK" 6 "PRESS_OK_BUTTON_TO_ENABLE_LANE_CHANGE_ASSIST" 7 "COLLISION_RISK_VEHICLE_TAKING_EMERGENCY_CONTROL" 8 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY_VEHICLE_IS_STOPPING" 9 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY" 11 "HIGHWAY_DRIVING_PILOT_SYSTEM_DEACTIVATED_AUDIBLE" 12 "KEEP_YOUR_EYES_ON_THE_ROAD" 13 "HIGHWAY_DRIVING_PILOT_CONDITIONS_NOT_MET_AUDIBLE" 14 "COLLISION_RISK_VEHICLE_TAKING_EMERGENCY_CONTROL" 15 "SET_THE_WIPER_AND_LIGHT_CONTROLS_TO_AUTO" 16 "BE_PREPARED_TO_TAKE_CONTROL_OF_THE_VEHICLE_AT_ANY_TIME" 21 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY_VEHICLE_IS_STOPPING" 10 "TAKE_CONTROL_OF_THE_VEHICLE_IMMEDIATELY"; +VAL_ 353 ALERTS_3 1 "AUTOMATICALLY_ADJUSTING_TO_THE_POSTED_SPEED_LIMIT" 2 "SET_SPEED_CHANGED" 3 "AUTOMATICALLY_ADJUSTING_TO_THE_POSTED_SPEED_LIMIT" 4 "SET_SPEED_CHANGED" 7 "DISTANCE_1" 8 "DISTANCE_2" 9 "DISTANCE_3" 10 "DISTANCE_4" 17 "DRIVE_CAREFULLY" 18 "CHECK_SURROUNDINGS" 19 "CONDITIONS_NOT_MET" 20 "LANES_NOT_DETECTED" 21 "CURVE_TOO_SHARP" 22 "LANE_TOO_NARROW" 23 "ROAD_TYPE_NOT_SUPPORTED" 24 "UNAVAILABLE_WITH_HAZARD_LIGHTS_ON" 25 "VEHICLE_SPEED_IS_TOO_LOW" 26 "KEEP_HANDS_ON_STEERING_WHEEL" 27 "LANE_TYPE_NOT_SUPPORTED" 28 "LANE_ASSIST_CANCELED_STEERING_INPUT_DETECTED" 0 "HIDDEN"; +VAL_ 353 ALERTS_4 0 "HIDDEN" 1 "TAKE_FOOT_OFF_THE_ACCELERATOR_PEDAL" 2 "TAKE_FOOT_OFF_THE_BRAKE_PEDAL" 3 "UNAVAILABLE_WHILE_HIGHWAY_DRIVING_PILOT_SYSTEM_IS_ACTIVE" 4 "TO_EXIT_HDP_GRASP_THE_STEERING_WHEEL_THEN_PRESS_AND_HOLD_THE_HDP_BUTTON" 5 "ACCELERATOR_PEDAL_OPERATION_LIMITED_FOR_SAFETY" 6 "TURN_OFF_HAZARD_WARNING_LIGHTS_AND_TURN_SIGNAL" 7 "KEEP_THE_DRIVERS_SEAT_IN_A_SAFE_DRIVING_POSITION" 16 "SET_SPEED_CHANGED" 17 "ACTIVATING_WINDSHIELD_DEFOG_TO_MAINTAIN_THE_DRIVERS_VIEW" 18 "SET_THE_WIPER_AND_LIGHT_CONTROLS_TO_AUTO" 19 "VEHICLE_SPEED_REDUCED_FOR_SAFETY_MERGING_LANES_AHEAD" 20 "SPEED_REDUCED_FOR_SAFETY_CONSTRUCTION_ZONE_DETECTED" 21 "VEHICLE_SPEED_LIMITED_SENSOR_DETECTION_RANGE_LIMITED" 22 "PREPARE_TO_TAKE_CONTROL_UNSUPPORTED_ROAD_TYPE_AHEAD" 23 "PREPARE_TO_TAKE_CONTROL_ENTRANCE_AND_EXIT_RAMPS_AHEAD" 24 "PREPARE_TO_TAKE_CONTROL_TOLLGATE_AHEAD" 25 "PREPARE_TO_TAKE_CONTROL_ROAD_EVENT_AHEAD" 26 "CLEARING_PATH_FOR_EMERGENCY_VEHICLE" 27 "VEHICLE_IS_TOO_SLOW_COMPARED_TO_TRAFFIC_FLOW" 28 "AFTER_SUNSET_HDP_IS_AVAILABLE_IN_AN_INSIDE_LANE_BEHIND_A_LEADING_VEHICLE" 29 "VEHICLE_SPEED_LIMITED_MERGING_LANES_AHEAD" 30 "VEHICLE_SPEED_LIMITED_CONSTRUCTION_ZONE_DETECTED" 31 "VEHICLE_SPEED_TEMPORARILY_LIMITED_FOR_SAFETY" 32 "PRESS_AND_HOLD_THE_BUTTON_TO_ACTIVATE_HIGHWAY_DRIVING_PILOT" 40 "HIGHWAY_DRIVING_PILOT_SYSTEM_IS_AVAILABLE" 64 "RESTART_VEHICLE_AFTER_EMERGENCY_STOP" 65 "CONNECTED_SERVICES_UNAVAILABLE" 66 "AVAILABLE_AFTER_VEHICLE_SOFTWARE_IS_UPDATED" 67 "ROAD_TYPE_NOT_SUPPORTED" 68 "ONLY_AVAILABLE_WHILE_DRIVING_ON_HIGHWAY_LANES" 69 "UNAVAILABLE_WHILE_OTHER_WARNINGS_ARE_ACTIVE" 70 "CANNOT_ACTIVATE_AT_ENTRANCE_EXIT_RAMPS" 71 "LANE_UNSUPPORTED" 72 "NOT_AVAILABLE_IN_THIS_COUNTRY" 79 "CHECKING_THE_DETECTION_RANGE_OF_THE_SENSOR" 80 "SHIFT_TO_D" 81 "ENGINE_STOPPED_BY_AUTO_STOP" 82 "INCREASE_DISTANCE_FROM_VEHICLE_AHEAD" 83 "VEHICLE_SPEED_IS_TOO_HIGH" 84 "CENTER_VEHICLE_IN_THE_LANE" 85 "PARKING_ASSIST_IS_ACTIVE" 86 "ESC_ACTIVIATION_REQUIRED" 87 "UNFOLD_SIDE_VIEW_MIRRORS" 88 "UNAVAILABLE_IN_THE_OUTER_LANE_AFTER_SUNSET" 89 "VEHICLE_SPEED_LIMITED_AFTER_SUNSET_FOR_SAFETY" 90 "LEADING_VEHICLE_NOT_DETECTED" 104 "AGGRESSIVE_BRAKING_OR_STEERING_DETECTED" 110 "SENSOR_AUTO_CALIBRATION_IN_PROGRESS_THIS_MAY_TAKE_SEVERAL_MINUTES" 111 "HIGHWAY_DRIVING_PILOT_WILL_BE_AVAILABLE_SHORTLY" 112 "IF_STEERING_WHEEL_IS_USED_HDP_WILL_BE_DEACTIVATED" 120 "IMPACT_DETECTED" 128 "UNSUITABLE_USE_OF_ACCELERATOR_PEDAL_DETECTED" 129 "GEAR_SHIFTER_USE_DETECTED" 130 "UNSUITABLE_BRAKE_PEDAL_USE_DETECTED" 131 "VEHICLE_START_BUTTON_PRESSED" 132 "VEHICLE_HAS_BEEN_STOPPED_FOR_TOO_LONG" 141 "TRAFFIC_CONGESTION_HAS_CLEARED" 142 "ENTRANCE_AND_EXIT_RAMPS_AHEAD" 143 "UNSUPPORTED_LANE_AHEAD" 144 "UNSUPPORTED_ROAD_TYPE_AHEAD" 145 "LANE_DEPARTURE_DETECTED" 146 "MAXIMUM_SPEED_EXCEEDED" 147 "HIGHWAY_DRIVING_PILOT_LIMITED_ABNORMAL_VEHICLE_CONTROLLER_STATUS" 148 "WIPER_LIGHT_CONTROL_SETTINGS_ARE_UNSUITABLE_FOR_USE_WITH_HDP" 149 "WINDSHIELD_DEFOG_SYSTEM_STATUS_IS_UNSUITABLE_FOR_USE_WITH_HDP" 150 "HAZARD_WARNING_LIGHTS_OR_TURN_SIGNAL_OPERATION_DETECTED" 151 "PERFORMING_EVASIVE_STEERING_OBSTACLES_DETECTED_AHEAD" 152 "HIGHWAY_DRIVING_PILOT_LIMITED_SENSOR_DETECTION_RANGE_LIMITED" 160 "CHECK_HIGHWAY_DRIVING_PILOT_SYSTEM" 161 "SAFETY_FUNCTION_ACTIVATED" 176 "CAMERA_OBSCURED" 177 "RADAR_BLOCKED" 178 "LIDAR_BLOCKED" 179 "AIRBAG_WARNING_LIGHT_IS_ON" 180 "ATTACHED_TRAILED_DETECTED" 181 "HIGH_OUTSIDE_TEMPERATURE" 182 "LOW_OUTSIDE_TEMPERATURE" 190 "UNAVAILABLE_DUE_TO_THE_ROAD_EVENT_INFORMATION_RECEIVED" 191 "UNAVAILABLE_NEAR_TOLLGATES" 192 "DRIVERS_SEAT_IS_NOT_IN_A_SAFE_DRIVING_POSITION" 193 "VEHICLE_DRIVING_THE_WRONG_WAY_DETECTED_AHEAD" 194 "EMERGENCY_VEHICLE_DETECTED" 195 "OBSTACLE_DETECTED_AHEAD" 196 "SENSOR_BLOCKED_DUE_TO_RAIN_SNOW_OR_ROAD_DEBRIS" 197 "SLIPPERY_ROAD_SURFACE_DETECTED" 198 "CONSTRUCTION_ZONE_DETECTED_AHEAD" 199 "PEDESTRIAN_DETECTED_AHEAD" 200 "UNSUITABLE_DRIVERS_SEAT_POSITION_DETECTED" 201 "FOLDED_SIDE_VIEW_MIRRORS_DETECTED" 208 "VEHICLE_POSITION_NOT_DETECTED" 209 "LANE_NOT_DETECTED" 210 "DRIVER_NOT_DETECTED" 211 "KEEP_YOUR_EYES_ON_THE_ROAD" 212 "LEADING_VEHICLE_REQUIRED_AFTER_SUNSET" 213 "TBD" 240 "LOW_FUEL" 241 "LOW_TIRE_PRESSURE" 242 "DOOR_OPEN" 243 "TRUNK_OPEN" 244 "HOOD_OPEN" 245 "SEAT_BELT_NOT_FASTENED" 246 "PARKING_BRAKE_ACTIVATED" 247 "LOW_EV_BATTERY" 248 "HDP_DEACTIVATION_DELAYED_RISK_OF_COLLISION_DETECTED" 249 "LIFTGATE_OPENED"; +VAL_ 353 ALERTS_5 0 "HIDDEN" 1 "DRIVERS_GRASP_NOT_DETECTED_DRIVING_SPEED_WILL_BE_LIMITED" 2 "WATCH_FOR_SURROUNDING_VEHICLES" 3 "SMART_CRUISE_CONTROL_DEACTIVATED" 4 "SMART_CRUISE_CONTROL_CONDITIONS_NOT_MET" 5 "USE_SWITCH_OR_PEDAL_TO_ACCELERATE" 6 "DRIVER_ASSISTNCE_SYSTEM_LIMITED_TRAILER_ATTACHED" 7 "DRIVER_ASSISTNCE_SYSTEM_LIMITED_DRIVER_FULL_FACE_NOT_VISIBLE" 11 "LEADING_VEHICLE_IS_DRIVING_AWAY" 12 "STOP_VEHICLE_THEN_TRY_AGAIN" 19 "ACTIVATING_HIGHWAY_DRIVING_PILOT_SYSTEM" 20 "CONTINUING_USE_OF_HIGHWAY_DRIVING_PILOT_WILL_RESULT_IN_DEVIATION_FROM_THE_NAVIGATION_ROUTE" 21 "HIGHWAY_DRIVING_PILOT_SYSTEM_DEACTIVATED_SILENT" 22 "HIGHWAY_DRIVING_PILOT_SYSTEM_NOT_APPLIED" 23 "HIGHWAY_DRIVING_PILOT_CONDITIONS_NOT_MET_SILENT"; +VAL_ 353 MUTE 0 "NONE" 1 "MUTED"; +VAL_ 353 SOUNDS_1 0 "NONE" 3 "FAST BEEP" 6 "CONSTANT BEEP"; +VAL_ 353 SOUNDS_2 0 "NONE" 2 "SINGLE CHIME" 3 "CONSTANT CHIME" 6 "FAST BEEP"; +VAL_ 353 SOUNDS_3 0 "NONE" 3 "SOFT CHIME" 5 "SINGLE CHIME"; +VAL_ 353 SOUNDS_4 0 "NONE" 2 "DOUBLE CHIME"; +VAL_ 353 SETSPEED_HUD 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 5 "CYAN"; +VAL_ 353 DISTANCE_LEAD 0 "HIDDEN" 1 "GRAY" 2 "WHITE"; +VAL_ 353 DISTANCE_CAR 0 "HIDDEN" 1 "GRAY" 2 "WHITE" 3 "CYAN A"; +VAL_ 353 DISTANCE_SPACING 0 "HIDDEN" 1 "BLUE" 3 "WHITE" 5 "CYAN"; +VAL_ 353 SETSPEED 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 6 "CYAN"; +VAL_ 353 HDA_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 5 "CYAN HDP"; +VAL_ 353 SLA_ICON 0 "HIDDEN" 1 "WHITE UP" 2 "WHITE DOWN" 3 "GREEN UP" 4 "GREEN DOWN"; +VAL_ 353 NAV_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 4 "WHITE"; +VAL_ 353 LFA_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 3 "WHITE" 5 "CYAN"; +VAL_ 353 LCA_LEFT_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 4 "WHITE"; +VAL_ 353 LCA_RIGHT_ICON 0 "HIDDEN" 1 "GRAY" 2 "GREEN" 4 "WHITE"; +VAL_ 353 BACKGROUND 0 "HIDDEN" 1 "BLUE" 3 "ORANGE" 4 "FLASHING ORANGE" 6 "FLASHING RED" 7 "GRAY"; +VAL_ 353 DAW_ICON 0 "HIDDEN" 1 "ORANGE"; +VAL_ 353 CAR_CIRCLE 0 "HIDDEN" 1 "GRAY" 2 "CYAN"; +VAL_ 354 COUNTRY 0 "HIDDEN" 1 "SOUTH_KOREA" 4 "INTL" 5 "JAPAN" 6 "CANADA" 7 "USA" 8 "CHINA" 9 "INTL"; +VAL_ 354 SPEEDLIMIT_FLASH 0 "HIDDEN" 1 "ERROR" 2 "NORMAL" 4 "RED"; +VAL_ 354 SIGNS 0 "HIDDEN" 1 "PEDESTRIAN_CROSSING" 2 "SCHOOL_CROSSWALK" 8 "STOP" 9 "YIELD" 16 "DO_NOT_PASS" 19 "DO_NOT_ENTER" 24 "ROUNDABOUT" 26 "RIGHT_CURVE_AHEAD" 27 "LEFT_CURVE_AHEAD" 28 "SLIGHT_RIGHT_CURVE_AHEAD" 29 "SLIGHT_LEFT_CURVE_AHEAD"; +VAL_ 354 SPEEDLIMIT_WEATHER 0 "HIDDEN" 1 "RAIN" 2 "SNOW" 3 "RAIN+SNOW" 4 "TRAILER"; +VAL_ 354 VIBRATE 0 "NONE" 1 "VIBRATE"; +VAL_ 354 LEAD 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "GRAY CAR" 4 "WHITE CAR" 5 "GRAY TRUCK" 6 "WHITE TRUCK" 7 "GRAY PERSON" 8 "WHITE PERSON" 9 "GRAY BICYCLE" 10 "WHITE BICYCLE" 11 "GRAY MOTORCYCLE" 12 "WHITE MOTORCYCLE" 13 "DARK CONE" 14 "ORANGE CONE"; +VAL_ 354 LEAD_ALT 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "DIM CONE" 4 "ORANGE CONE"; +VAL_ 354 LEAD_LEFT 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "GRAY CAR" 4 "WHITE CAR" 5 "GRAY TRUCK" 6 "WHITE TRUCK" 7 "GRAY PERSON" 8 "WHITE PERSON" 9 "GRAY BICYCLE" 10 "WHITE BICYCLE" 11 "GRAY MOTORCYCLE" 12 "WHITE MOTORCYCLE" 13 "DARK CONE" 14 "ORANGE CONE"; +VAL_ 354 LEAD_RIGHT 0 "HIDDEN" 1 "GRAY BOX" 2 "WHITE BOX" 3 "GRAY CAR" 4 "WHITE CAR" 5 "GRAY TRUCK" 6 "WHITE TRUCK" 7 "GRAY PERSON" 8 "WHITE PERSON" 9 "GRAY BICYCLE" 10 "WHITE BICYCLE" 11 "GRAY MOTORCYCLE" 12 "WHITE MOTORCYCLE" 13 "DARK CONE" 14 "ORANGE CONE"; +VAL_ 354 FAULT_FSS 0 "HIDDEN" 1 "CHECK_FORWARD_SAFETY_SYSTEM" 2 "FORWARD_SAFETY_SYSTEM_LIMITED_CAMERA_OBSCURED" 3 "FORWARD_SAFETY_SYSTEM_LIMITED_RADAR_BLOCKED"; +VAL_ 354 FAULT_FCA 0 "HIDDEN" 1 "CHECK_FORWARD_SIDE_SAFETY_SYSTEM" 2 "FORWARD_SIDE_SAFETY_SYSTEM_LIMITED_CAMERA_OBSCURED" 3 "FORWARD_SIDE_SAFETY_SYSTEM_LIMITED_RADAR_BLOCKED"; +VAL_ 354 FAULT_LSS 0 "HIDDEN" 1 "CHECK_LANE_SAFETY_SYSTEM" 2 "LANE_SAFETY_SYSTEM_DISABLED_CAMERA_OBSCURED"; +VAL_ 354 FAULT_SLA 0 "HIDDEN" 1 "CHECK_SPEED_LIMIT_SYSTEM" 2 "SPEED_LIMIT_SYSTEM_DISABLED_CAMERA_OBSCURED"; +VAL_ 354 FAULT_DAW 0 "HIDDEN" 1 "CHECK_INATTENTIVE_DRIVING_WARNING_SYSTEM" 2 "INATTENTIVE_DRIVING_WARNING_SYSTEM_DISABLED_CAMERA_OBSCURED"; +VAL_ 354 FAULT_HBA 0 "HIDDEN" 1 "CHECK_HIGH_BEAM_ASSIST_SYSTEM"; +VAL_ 354 FAULT_SCC 0 "HIDDEN" 1 "CHECK_SMART_CRUISE_CONTROL_SYSTEM" 2 "SMART_CRUISE_CONTROL_DISABLED_RADAR_BLOCKED"; +VAL_ 354 FAULT_LFA 0 "HIDDEN" 1 "CHECK_LANE_FOLLOWING_SYSTEM_ASSIST_SYSTEM"; +VAL_ 354 FAULT_HDA 0 "HIDDEN" 1 "CHECK_HIGHWAY_DRIVING_ASSIST_SYSTEM"; +VAL_ 354 FAULT_LCA 0 "HIDDEN" 1 "CHECK_LANE_CHANGE_ASSIST_FUNCTION" 2 "LANE_CHANGE_ASSIST_FUNCTION_DISABLED_CAMERA_OBSCURED" 3 "LANE_CHANGE_ASSIST_FUNCTION_DISABLED_RADAR_BLOCKED"; +VAL_ 354 FAULT_HDP 0 "HIDDEN" 1 "CHECK_HIGHWAY_DRIVING_PILOT_SYSTEM" 2 "HIGHWAY_DRIVING_PILOT_DISABLED_CAMERA_OBSCURED" 3 "HIGHWAY_DRIVING_PILOT_DISABLED_RADAR_BLOCKED" 4 "HIGHWAY_DRIVING_PILOT_DISABLED_LIDAR_BLOCKED"; +VAL_ 354 FAULT_DAS 0 "HIDDEN" 1 "CHECK_DRIVER_ASSISTANCE_SYSTEM" 2 "DRIVER_ASSISTANCE_SYSTEM_LIMITED_CAMERA_OBSCURED" 3 "DRIVER_ASSISTANCE_SYSTEM_LIMITED_RADAR_BLOCKED" 4 "DRIVER_ASSISTANCE_SYSTEM_LIMITED_CAMERA_OBSCURED_AND_RADAR_BLOCKED"; +VAL_ 354 FAULT_ESS 0 "HIDDEN" 1 "CHECK_EMERGENCY_STOPPING_FUNCTION" 2 "EMERGENCY_STOPPING_FUNCTION_DISABLED_CAMERA_OBSCURED" 3 "EMERGENCY_STOPPING_FUNCTION_DISABLED_RADAR_BLOCKED"; +VAL_ 362 BLINKER_CONTROL 1 "hazards" 2 "hazards button backlight" 3 "left blinkers" 4 "right blinkers"; +VAL_ 373 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue"; +VAL_ 416 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled"; +VAL_ 426 CRUISE_BUTTONS 0 "none" 1 "res_accel" 2 "set_decel" 3 "gap_distance" 4 "pause_resume"; +VAL_ 437 Info_LftLnQualSta 0 "Very Low Quality" 1 "Low Quality" 2 "High Quality" 3 "Very High Quality" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Error indicator"; +VAL_ 437 Info_LftLnDptSta 0 "No Left Line Departure" 1 "Left Line Departure" 2 "Reserved" 3 "Error Indicator"; +VAL_ 437 Info_RtLnQualSta 0 "Very Low Quality" 1 "Low Quality" 2 "High Quality" 3 "Very High Quality" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Error indicator"; +VAL_ 437 Info_RtLnDptSta 0 "No Right Line Departure" 1 "Right Line Departure" 2 "Reserved" 3 "Error Indicator"; +VAL_ 437 Info_RtLnCvtrVal 65534 "Reserved" 65535 "Error indicator"; +VAL_ 463 CRUISE_BUTTONS 0 "none" 1 "res_accel" 2 "set_decel" 3 "gap_distance" 4 "pause_resume"; +VAL_ 463 RIGHT_PADDLE 0 "Not Pulled" 1 "Pulled"; +VAL_ 463 LEFT_PADDLE 0 "Not Pulled" 1 "Pulled"; +VAL_ 506 ISLW_OptUsmSta 0 "None ISLW Option (Default)" 1 "System Disabled by USM" 2 "System Enable by USM" 3 "Invalid"; +VAL_ 506 ISLW_SysSta 0 "Normal (Default)" 1 "System Fail" 2 "ISLW Temporary Unavailable" 3 "Reserved"; +VAL_ 506 ISLW_NoPassingInfoDis 0 "None Display (Default)" 1 "LHD No Passing Zone Display" 2 "RHD No Passing Zone Display" 3 "Reserved" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid"; +VAL_ 506 ISLW_OvrlpSignDis 0 "None (Default)" 1 "Overlap Sign" 2 "Reserved" 3 "Error indicator"; +VAL_ 506 ISLW_SpdCluMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid"; +VAL_ 506 ISLW_SpdNaviMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid"; +VAL_ 506 ISLW_SubCondinfoSta1 0 "None (Default)" 1 "Rain" 2 "Snow" 3 "Snow&Rain" 4 "Trailer" 5 "Reserved" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Generic" 15 "Invalid"; +VAL_ 506 ISLW_SubCondinfoSta2 0 "None (Default)" 1 "Rain" 2 "Snow" 3 "Snow&Rain" 4 "Trailer" 5 "Reserved" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Generic" 15 "Invalid"; +VAL_ 506 ISLW_SpdCluSubMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid"; +VAL_ 506 ISLW_SpdCluDisSubCond1 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid"; +VAL_ 506 ISLW_SpdCluDisSubCond2 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid"; +VAL_ 506 ISLW_SpdNaviSubMainDis 0 "No Recognition (Default)" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid"; +VAL_ 506 ISLW_SpdNaviDisSubCond1 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid"; +VAL_ 506 ISLW_SpdNaviDisSubCond2 0 "No Recognition (Default)" 253 "LHD Conditional No Passing ZONE" 254 "RHD Conditional No Passing ZONE" 255 "Invalid"; +VAL_ 506 ISLA_SpdwOffst 0 "No Recognition" 253 "Unlimited Speed" 254 "Reserved" 255 "Invalid"; +VAL_ 506 ISLA_SwIgnoreReq 0 "Allow All Switch Inputs (default)" 1 "-(SET) Switch Input Ignore" 2 "+(SET) Switch Input Ignore" 3 "-(SET) & +(SET) Switch Inputs Ignore"; +VAL_ 506 ISLA_SpdChgReq 0 "Default" 1 "Speed Change Request" 2 "Reserved" 3 "Reserved"; +VAL_ 506 ISLA_SpdWrn 0 "No Warning" 1 "Warning" 2 "Reserved" 3 "Reserved"; +VAL_ 506 ISLA_IcyWrn 0 "No Warning" 1 "Warning" 2 "Reserved" 3 "Reserved"; +VAL_ 506 ISLA_SymFlashMod 0 "No Flasing" 1 "Flashing Sign" 2 "Flashing - Arrow Symbol" 3 "Flashing + Arrow Symbol" 4 "Flashing Auto Symbol" 5 "Reserved" 6 "Reserved" 7 "Reserved"; +VAL_ 506 ISLA_Popup 0 "No Popup" 1 "MSLA Speed will Change" 2 "MSLA Speed has Changed" 3 "CC_SCC Speed will Change" 4 "CC_SCC Speed has Changed" 5 "Reserved" 6 "Reserved" 7 "Reserved"; +VAL_ 506 ISLA_OptUsmSta 0 "None ISLA Option (속도 제한 메뉴 삭제)" 1 "Off" 2 "Warning" 3 "Assist" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Invalid (GRAY)"; +VAL_ 506 ISLA_OffstUsmSta 0 "None Offset Function" 1 "-10kph or -5mph" 2 "-5kph or -3mph" 3 "0kph or 0mph" 4 "+5kph or +3mph" 5 "+10kph or +5mph" 6 "Reserved" 7 "Invalid (GRAY)"; +VAL_ 506 ISLA_AutoUsmSta 0 "None Auto Function (Delete Menu)" 1 "Auto Off" 2 "Auto On" 3 "Invalid (GRAY)"; +VAL_ 506 ISLA_Cntry 0 "Europe/Russia/Australia" 1 "Domestic" 2 "China" 3 "USA" 4 "Canada" 5 "Australia" 6 "Reserved" 7 "Reserved" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Reserved" 15 "Initial Value (default)"; +VAL_ 506 ISLA_AddtnlSign 0 "No Recognition (default)" 1 "School Crossing" 16 "Do Not Pass" 17 "Reserved" 18 "Reserved" 19 "Reserved" 20 "Reserved" 21 "Reserved" 22 "Reserved" 23 "Reserved" 24 "Exit" 25 "Roundabout" 26 "Right Curve" 27 "Left Curve" 28 "Winding Road" 29 "Reserved" 30 "Reserved" 31 "Reserved" 2 "Pedestrian Crossing" 3 "Bicycle Crossing" 4 "Reserved" 5 "Reserved" 6 "Reserved" 7 "Reserved" 8 "Stop" 9 "Yield" 10 "Stop Ahead" 11 "Yield Ahead" 12 "Road Construction Ahead" 13 "Lane Reduction" 14 "Reserved" 15 "Reserved"; +VAL_ 506 ISLA_SchoolZone 0 "No School Zone" 1 "School Zone" 2 "Reserved" 3 "Reserved"; +VAL_ 687 HOD_Dir_Status 0 "HANDS OFF" 1 "HAND TOUCH (SOFT)" 2 "HAND TOUCH (STRONG)" 3 "HAND GRIP (SOFT)" 4 "HAND GRIP (STRONG)" 5 "RESERVED" 6 "RESERVED"; +VAL_ 698 IFSref_FR_CMR_Sta 0 "None Option (Default)" 1 "Normal" 2 "Blockage Status" 3 "Error Indicator"; +VAL_ 698 IFSref_VehNumVal 0 "No vehicle" 1 "Number of vehicles" 2 "Number of vehicles" 3 "Number of vehicles" 4 "Number of vehicles" 5 "Number of vehicles" 6 "Number of vehicles" 7 "Number of vehicles" 8 "Number of vehicles" 9 "Number of vehicles" 10 "Number of vehicles" 11 "Over than 10 vehicles" 12 "Reserved" 13 "Reserved" 14 "Default" 15 "Error indicator"; +VAL_ 698 IFSref_ILLAmbtSta 0 "Bright" 1 "Dark" 2 "Not used" 3 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl1Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl1Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl2Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehDst1Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl2Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl3Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl3Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl4Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl4Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl5Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl5Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl6Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl6Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl7Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl7Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl8Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl8Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl9Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl9Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehLftAngl10Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehRtAngl10Val 501 "Not used" 502 "Not used" 503 "Not used" 504 "Not used" 505 "Not used" 506 "Not used" 507 "Not used" 508 "Not used" 509 "Not used" 510 "Default" 511 "Error indicator"; +VAL_ 698 IFSref_VehDst2Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst3Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst4Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst5Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst6Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst7Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst8Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst9Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 698 IFSref_VehDst10Val 0 "No Value" 1 "1~10m" 2 "11~20m" 3 "21~30m" 4 "31~40m" 5 "41~50m" 6 "51~60m" 7 "61~70m" 8 "71~80m" 9 "81~90m" 10 "91~100m" 11 "101~200m" 12 "201~300m" 13 "301~400m" 14 "401m~" 15 "Error indicator"; +VAL_ 736 MSLA_STATUS 0 "disabled" 1 "active" 2 "paused"; +VAL_ 866 LEFT_LANE_LINE 0 "Not Detected" 1 "Low Confidence" 2 "Medium Confidence" 3 "High Confidence"; +VAL_ 866 RIGHT_LANE_LINE 0 "Not Detected" 1 "Low Confidence" 2 "Medium Confidence" 3 "High Confidence"; +VAL_ 1041 DRIVER_DOOR 0 "Closed" 1 "Opened"; +VAL_ 1041 PASSENGER_DOOR 0 "Closed" 1 "Opened"; +VAL_ 1041 PASSENGER_SEATBELT 0 "Unlatched" 1 "Latched"; +VAL_ 1041 DRIVER_SEATBELT 0 "Unlatched" 1 "Latched"; +VAL_ 1041 DRIVER_REAR_DOOR 0 "Closed" 1 "Opened"; +VAL_ 1041 PASSENGER_REAR_DOOR 0 "Closed" 1 "Opened"; +VAL_ 1144 DRIVE_MODE2 3 "Set Sport" 1 "Set Normal" 2 "Set Eco"; +VAL_ 1240 DISTANCE_UNIT 1 "Miles" 0 "Kilometers"; diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_kia_mando_corner_radar.py b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_kia_mando_corner_radar.py new file mode 100755 index 0000000000..aad417e32a --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_kia_mando_corner_radar.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +from collections import namedtuple +import os + +if __name__ == "__main__": + dbc_name = os.path.basename(__file__).replace(".py", ".dbc") + hyundai_path = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(hyundai_path, dbc_name), "w", encoding='utf-8') as f: + f.write(""" +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX +""") + + for a in [0x100, 0x200]: + f.write(f""" +BO_ {a} RADAR_POINTS_METADATA_0x{a:x}: 64 RADAR + SG_ SIGNAL_1 : 0|32@1+ (1,0) [0|255] "" XXX + SG_ SIGNAL_2 : 32|32@1+ (1,0) [0|65535] "" XXX + SG_ SIGNAL_3 : 64|4@1+ (1,0) [0|15] "" XXX + SG_ SIGNAL_4 : 68|4@1+ (1,0) [0|15] "" XXX + SG_ RADAR_POINT_COUNT : 72|8@1+ (1,0) [0|255] "" XXX + SG_ SIGNAL_6 : 80|7@1+ (0.015625,0) [0|3] "" XXX + SG_ SIGNAL_7 : 87|1@1+ (1,0) [0|1] "" XXX + SG_ SIGNAL_8 : 88|3@1+ (1,0) [0|7] "" XXX + SG_ SIGNAL_9 : 91|5@1+ (0.0625,0) [0|31] "" XXX + SG_ SIGNAL_10 : 96|8@1+ (1,0) [0|255] "" XXX + SG_ SIGNAL_11 : 104|7@1+ (0.015625,0) [0|127] "" XXX + SG_ SIGNAL_12 : 111|2@1+ (1,0) [0|65535] "" XXX + SG_ SIGNAL_13 : 113|7@1+ (0.015625,0) [0|127] "" XXX + SG_ SIGNAL_14 : 120|7@1+ (0.015625,0) [0|127] "" XXX + SG_ SIGNAL_15 : 127|3@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_16 : 130|2@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_17 : 133|2@0+ (1,0) [0|3] "" XXX + SG_ SIGNAL_18 : 134|1@0+ (1,0) [0|3] "" XXX + SG_ SIGNAL_19 : 135|3@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_20 : 138|8@1+ (1,0) [0|63] "" XXX + SG_ SIGNAL_21 : 146|2@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_22 : 148|1@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_23 : 149|4@1+ (1,0) [0|7] "" XXX + SG_ SIGNAL_24 : 153|1@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_25 : 154|2@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_26 : 157|2@0+ (1,0) [0|3] "" XXX + SG_ SIGNAL_27 : 158|7@1+ (0.125,0) [0|3] "" XXX + SG_ SIGNAL_28 : 165|7@1+ (0.015625,0) [0|31] "" XXX + SG_ SIGNAL_29 : 172|7@1+ (0.125,0) [0|3] "" XXX + SG_ SIGNAL_30 : 179|7@1+ (0.015625,0) [0|1] "" XXX + SG_ SIGNAL_31 : 186|4@1+ (1,0) [0|7] "" XXX + SG_ SIGNAL_32 : 190|14@1+ (0.015625,0) [0|15] "" XXX + SG_ SIGNAL_33 : 204|11@1+ (0.03125,0) [0|8191] "" XXX + SG_ SIGNAL_34 : 215|2@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_35 : 217|7@1+ (1,0) [0|127] "" XXX + SG_ SIGNAL_36 : 224|6@1+ (1,0) [0|63] "" XXX + SG_ SIGNAL_37 : 230|6@1+ (0.2,0) [0|31] "" XXX + SG_ SIGNAL_38 : 236|6@1+ (0.2,0) [0|7] "" XXX + SG_ SIGNAL_39 : 242|8@1+ (1,-90) [0|255] "" XXX + SG_ SIGNAL_40 : 250|6@1+ (1,0) [0|63] "" XXX + SG_ SIGNAL_41 : 256|8@1+ (0.25,0) [0|255] "" XXX + SG_ SIGNAL_42 : 264|3@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_43 : 267|12@1+ (0.01,0) [0|31] "" XXX + SG_ SIGNAL_44 : 279|32@1+ (1,0) [0|63] "" XXX + SG_ SIGNAL_45 : 311|1@1+ (1,0) [0|1] "" XXX + SG_ SIGNAL_46 : 312|2@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_47 : 314|32@1+ (1,0) [0|255] "" XXX + SG_ SIGNAL_48 : 346|6@1+ (1,0) [0|63] "" XXX + SG_ SIGNAL_49 : 352|7@1+ (0.25,0) [0|127] "" XXX + SG_ SIGNAL_50 : 359|6@1+ (0.03125,0) [0|31] "" XXX + SG_ SIGNAL_51 : 365|10@1+ (0.125,0) [0|3] "" XXX + SG_ SIGNAL_52 : 375|10@1+ (0.125,0) [0|63] "" XXX + SG_ SIGNAL_53 : 385|7@1+ (1,0) [0|127] "" XXX + SG_ SIGNAL_54 : 392|7@1+ (1,0) [0|127] "" XXX + SG_ SIGNAL_55 : 399|8@1+ (0.00390625,0) [0|31] "" XXX + SG_ SIGNAL_56 : 407|10@1+ (0.125,0) [0|63] "" XXX + SG_ SIGNAL_57 : 417|1@1+ (1,0) [0|3] "" XXX + SG_ SIGNAL_58 : 418|1@1+ (1,0) [0|3] "" XXX +""") + + # radar points are sent at 20 Hz in groups of 1 to 13 messages + # each message has 5 radar points for a total of 65 points max + # each radar point is 101 bits so the alignment is not consistent + RadarPointSignal = namedtuple("RadarPointSignal", ["name", "start", "length", "scale", "offset"]) + radar_point_signals = ( + RadarPointSignal("DISTANCE", 7, 14, 1/64, 0), + RadarPointSignal("", 21, 2, 1, 0), + RadarPointSignal("", 23, 8, 1/512, -127/512), + RadarPointSignal("REL_VELOCITY", 31, 13, 1/32, -66), + RadarPointSignal("", 44, 2, 1, 0), + RadarPointSignal("", 46, 2, 1, 0), + RadarPointSignal("AZIMUTH", 48, 12, 1/512, -2047/512), + RadarPointSignal("", 60, 2, 1, 0), + RadarPointSignal("", 62, 1, 1, 0), + RadarPointSignal("", 63, 7, 1, 0), + RadarPointSignal("", 70, 1, 1, 0), + RadarPointSignal("", 71, 6, 1, 0), + RadarPointSignal("", 77, 2, 1, 0), + RadarPointSignal("", 79, 8, 1/512, -127/512), + RadarPointSignal("", 87, 1, 1, 0), + RadarPointSignal("", 88, 2, 1, 0), + RadarPointSignal("", 90, 3, 1, 0), + # last 15 bits are controlled by LAYOUT_ID (seems to always zero, so below is layout 0) + RadarPointSignal("", 93, 6, 1, 0), + RadarPointSignal("", 99, 8, 1, 0), + RadarPointSignal("", 107, 1, 1, 0), + ) + radar_point_bit_count = sum([s.length for s in radar_point_signals]) + + for a in [0x101, 0x201]: + f.write(f""" +BO_ {a} RADAR_POINTS_0x{a:x}: 64 RADAR + SG_ MESSAGE_ID : 0|5@1+ (1,0) [0|31] "" XXX + SG_ LAYOUT_ID : 5|2@1+ (1,0) [0|3] "" XXX +""") + bit_idx = radar_point_signals[0].start + for i in range(5): + signal_idx = 1 + for sig in radar_point_signals: + if sig.name: + sig_name = f"POINT_{i+1}_{sig.name}" + else: + sig_name = f"POINT_{i+1}_SIGNAL_{signal_idx}" + signal_idx += 1 + + sig_start_idx = i * radar_point_bit_count + sig.start + assert bit_idx == sig_start_idx, f"signal overlap or gap!!! {bit_idx} != {sig_start_idx}" + min_val = round(sig.offset, 10) + max_val = round((2**sig.length - 1) * sig.scale + sig.offset, 10) + + f.write(f" SG_ {sig_name} : {sig_start_idx}|{sig.length}@1+ ({sig.scale},{sig.offset}) [{min_val}|{max_val}] \"\" XXX\n") + bit_idx += sig.length + + # checksum is across a group of 0x100/200 and 0x101/201 messages (no checksums inside the other messages) + # ccitt_crc16 = mkCrcFun(0x11021, initCrc=0xffff, xorOut=0x0000, rev=False) + for a in [0x104, 0x204]: + f.write(f""" +BO_ {a} RADAR_POINTS_CHECKSUM_0x{a:x}: 3 RADAR + SG_ CRC16 : 0|16@1+ (1,0) [0|65535] "" XXX +""") diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_kia_mando_front_radar.py b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_kia_mando_front_radar.py new file mode 100755 index 0000000000..ee8dde64d4 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_kia_mando_front_radar.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import os + +if __name__ == "__main__": + dbc_name = os.path.basename(__file__).replace(".py", ".dbc") + hyundai_path = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(hyundai_path, dbc_name), "w", encoding='utf-8') as f: + f.write(""" +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + """) + + # note: 0x501/0x502 seem to be special in 0x5XX range + for a in range(0x500, 0x500 + 32): + f.write(f""" +BO_ {a} RADAR_TRACK_{a:x}: 8 RADAR + SG_ UNKNOWN_1 : 7|8@0- (1,0) [-128|127] "" XXX + SG_ AZIMUTH : 12|10@0- (0.2,0) [-102.4|102.2] "" XXX + SG_ STATE : 15|3@0+ (1,0) [0|7] "" XXX + SG_ LONG_DIST : 18|11@0+ (0.1,0) [0|204.7] "" XXX + SG_ REL_ACCEL : 33|10@0- (0.02,0) [-10.24|10.22] "" XXX + SG_ ZEROS : 37|4@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 38|1@0+ (1,0) [0|1] "" XXX + SG_ STATE_3 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX + SG_ STATE_2 : 55|2@0+ (1,0) [0|3] "" XXX + """) diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_palisade_2023.dbc b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_palisade_2023.dbc new file mode 100644 index 0000000000..68f5d60af4 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_palisade_2023.dbc @@ -0,0 +1,865 @@ +CM_ "IMPORT _hyundai_canfd_common.dbc"; + +BO_ 67 DATC13: 8 XXX + SG_ CF_Datc_AcDisp : 22|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_AqsDisp : 20|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_AutoDefogBlink : 16|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_AutoDisp : 12|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_ChgReqDisp : 8|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_ClmScanDisp : 18|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_DualDisp : 30|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_FrDefLed : 14|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_FrontBlwDisp : 60|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_IntakeDisp : 10|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_IonClean : 6|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_ModDisp : 2|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_OpSts : 25|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_PSModDisp : 56|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_PwrInf : 32|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearAutoDisp : 40|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearBlwDisp : 52|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearChgReqDisp : 46|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearClimateScnDisp : 44|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearManual : 38|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearModDisp : 48|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_RearOffDisp : 42|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Datc_TempDispUnit : 0|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Mtc_MaxAcDisp : 28|2@1+ (1,0) [0|0] "" XXX + +BO_ 127 CGW5: 8 XXX + SG_ C_DRLLampLhOpenSts : 7|1@1+ (1,0) [0|0] "" XXX + SG_ C_DRLLampRhOpenSts : 8|1@1+ (1,0) [0|0] "" XXX + SG_ C_FrontEXTTailLhOpenSts : 15|1@1+ (1,0) [0|0] "" XXX + SG_ C_FrontEXTTailRhOpenSts : 16|1@1+ (1,0) [0|0] "" XXX + SG_ C_FrontFOGLhOpenSts : 11|1@1+ (1,0) [0|0] "" XXX + SG_ C_FrontFOGRhOpenSts : 12|1@1+ (1,0) [0|0] "" XXX + SG_ C_FrontTSIGLhOpenSts : 19|1@1+ (1,0) [0|0] "" XXX + SG_ C_FrontTSIGRhOpenSts : 20|1@1+ (1,0) [0|0] "" XXX + SG_ C_HLampHighLhOpenSts : 5|1@1+ (1,0) [0|0] "" XXX + SG_ C_HLampHighRhOpenSts : 6|1@1+ (1,0) [0|0] "" XXX + SG_ C_HLampLowLhOpenSts : 3|1@1+ (1,0) [0|0] "" XXX + SG_ C_HLampLowRhOpenSts : 4|1@1+ (1,0) [0|0] "" XXX + SG_ C_HMSLOpenSts : 2|1@1+ (1,0) [0|0] "" XXX + SG_ C_LicensePlateLhOpenSts : 23|1@1+ (1,0) [0|0] "" XXX + SG_ C_LicensePlateRhOpenSts : 24|1@1+ (1,0) [0|0] "" XXX + SG_ C_RearEXTTailLhOpenSts : 13|1@1+ (1,0) [0|0] "" XXX + SG_ C_RearEXTTailRhOpenSts : 14|1@1+ (1,0) [0|0] "" XXX + SG_ C_RearFOGLhOpenSts : 9|1@1+ (1,0) [0|0] "" XXX + SG_ C_RearFOGRhOpenSts : 10|1@1+ (1,0) [0|0] "" XXX + SG_ C_RearTSIGLhOpenSts : 17|1@1+ (1,0) [0|0] "" XXX + SG_ C_RearTSIGRhOpenSts : 18|1@1+ (1,0) [0|0] "" XXX + SG_ C_SBendingLhOpenSts : 21|1@1+ (1,0) [0|0] "" XXX + SG_ C_SBendingRhOpenSts : 22|1@1+ (1,0) [0|0] "" XXX + SG_ C_StopLampLhOpenSts : 0|1@1+ (1,0) [0|0] "" XXX + SG_ C_StopLampRhOpenSts : 1|1@1+ (1,0) [0|0] "" XXX + +BO_ 304 YRS11: 8 XXX + SG_ CF_Yrs_LatAcStat : 36|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Yrs_MCUStat : 40|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Yrs_YrStat : 32|4@1+ (1,0) [0|0] "" XXX + SG_ CR_Yrs_Crc1 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ CR_Yrs_LatAc : 16|16@1+ (0.000127465,-4.17677312) [0|0] "" XXX + SG_ CR_Yrs_MsgCnt1 : 48|4@1+ (1,0) [0|0] "" XXX + SG_ CR_Yrs_Yr : 0|16@1+ (0.005,-163.84) [0|0] "" XXX + +BO_ 320 YRS12: 8 XXX + SG_ CF_IMU_ResetStat : 20|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Yrs_LongAcStat : 16|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Yrs_Type : 36|4@1+ (1,0) [0|0] "" XXX + SG_ CR_Yrs_Crc2 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ CR_Yrs_LongAc : 0|16@1+ (0.000127465,-4.17677312) [0|0] "" XXX + SG_ CR_Yrs_MsgCnt2 : 48|4@1+ (1,0) [0|0] "" XXX + SG_ YRS_Temp : 24|8@1+ (1,-68) [0|0] "" XXX + SG_ YRS_TempStat : 32|4@1+ (1,0) [0|0] "" XXX + +BO_ 339 TCS11: 8 XXX + SG_ ABS_ACT : 10|1@1+ (1,0) [0|0] "" XXX + SG_ ABS_DEF : 7|1@1+ (1,0) [0|0] "" XXX + SG_ ABS_DIAG : 6|1@1+ (1,0) [0|0] "" XXX + SG_ AliveCounter_TCS1 : 52|4@1+ (1,0) [0|0] "" XXX + SG_ BLA_CTL : 49|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Esc_BrkCtl : 48|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Esc_LimoInfo : 4|2@1+ (1,0) [0|0] "" XXX + SG_ CheckSum_TCS1 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ DBC_CTL : 16|1@1+ (1,0) [0|0] "" XXX + SG_ DBC_DEF : 18|1@1+ (1,0) [0|0] "" XXX + SG_ DBC_PAS : 17|1@1+ (1,0) [0|0] "" XXX + SG_ EBD_DEF : 11|1@1+ (1,0) [0|0] "" XXX + SG_ ESP_CTL : 14|1@1+ (1,0) [0|0] "" XXX + SG_ ESP_DEF : 13|1@1+ (1,0) [0|0] "" XXX + SG_ ESP_PAS : 12|1@1+ (1,0) [0|0] "" XXX + SG_ ESS_STAT : 22|2@1+ (1,0) [0|0] "" XXX + SG_ HAC_CTL : 19|1@1+ (1,0) [0|0] "" XXX + SG_ HAC_DEF : 21|1@1+ (1,0) [0|0] "" XXX + SG_ HAC_PAS : 20|1@1+ (1,0) [0|0] "" XXX + SG_ MSR_C_REQ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ TCS_CTL : 9|1@1+ (1,0) [0|0] "" XXX + SG_ TCS_DEF : 8|1@1+ (1,0) [0|0] "" XXX + SG_ TCS_GSC : 3|1@1+ (1,0) [0|0] "" XXX + SG_ TCS_MFRN : 15|1@1+ (1,0) [0|0] "" XXX + SG_ TCS_PAS : 2|1@1+ (1,0) [0|0] "" XXX + SG_ TCS_REQ : 0|1@1+ (1,0) [0|0] "" XXX + SG_ TQI_MSR : 32|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_SLW_TCS : 40|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_TCS : 24|8@1+ (0.390625,0) [0|0] "" XXX + +BO_ 356 VSM11: 4 XXX + SG_ CF_Esc_Act : 12|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Esc_AliveCnt : 17|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Esc_Chksum : 24|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Esc_CtrMode : 13|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Esc_Def : 16|1@1+ (1,0) [0|0] "" XXX + SG_ CR_Esc_StrTqReq : 0|12@1+ (0.01,-20.48) [0|0] "" XXX + +BO_ 544 ESP12: 8 XXX + SG_ CYL_PRES : 26|12@1+ (0.1,0) [0|0] "" XXX + SG_ CYL_PRESS_DIAG : 39|1@1+ (1,0) [0|0] "" XXX + SG_ CYL_PRES_STAT : 38|1@1+ (1,0) [0|0] "" XXX + SG_ ESP12_AliveCounter : 60|4@1+ (1,0) [0|0] "" XXX + SG_ ESP12_Checksum : 56|4@1+ (1,0) [0|0] "" XXX + SG_ LAT_ACCEL : 0|11@1+ (0.01,-10.23) [0|0] "" XXX + SG_ LAT_ACCEL_DIAG : 12|1@1+ (1,0) [0|0] "" XXX + SG_ LAT_ACCEL_STAT : 11|1@1+ (1,0) [0|0] "" XXX + SG_ LONG_ACCEL : 13|11@1+ (0.01,-10.23) [0|0] "" XXX + SG_ LONG_ACCEL_DIAG : 25|1@1+ (1,0) [0|0] "" XXX + SG_ LONG_ACCEL_STAT : 24|1@1+ (1,0) [0|0] "" XXX + SG_ YAW_RATE : 40|13@1+ (0.01,-40.95) [0|0] "" XXX + SG_ YAW_RATE_DIAG : 54|1@1+ (1,0) [0|0] "" XXX + SG_ YAW_RATE_STAT : 53|1@1+ (1,0) [0|0] "" XXX + +BO_ 593 MDPS12: 8 XXX + SG_ CF_Mdps_Chksum2 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_Def : 11|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_FailStat : 15|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_MsgCount2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_SErr : 37|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_ToiActive : 13|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_ToiFlt : 14|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_ToiUnavail : 12|1@1+ (1,0) [0|0] "" XXX + SG_ CR_Mdps_OutTq : 52|12@1+ (0.1,-204.8) [0|0] "" XXX + SG_ CR_Mdps_StrColTq : 0|11@1+ (1,-1024) [0|0] "" XXX + SG_ CR_Mdps_StrTq : 40|12@1+ (0.01,-20.48) [0|0] "" XXX + +BO_ 608 EMS16: 8 XXX + SG_ AliveCounter : 60|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_AclAct : 62|2@1+ (1,0) [0|0] "" XXX + SG_ CRUISE_LAMP_M : 25|1@1+ (1,0) [0|0] "" XXX + SG_ CRUISE_LAMP_S : 26|1@1+ (1,0) [0|0] "" XXX + SG_ Checksum : 56|4@1+ (1,0) [0|0] "" XXX + SG_ ENG_STAT : 28|3@1+ (1,0) [0|0] "" XXX + SG_ GLOW_STAT : 24|1@1+ (1,0) [0|0] "" XXX + SG_ PRE_FUEL_CUT_IN : 27|1@1+ (1,0) [0|0] "" XXX + SG_ SOAK_TIME : 32|8@1+ (1,0) [0|0] "" XXX + SG_ SOAK_TIME_ERROR : 31|1@1+ (1,0) [0|0] "" XXX + SG_ SPK_TIME_CUR : 48|8@1+ (0.375,-35.625) [0|0] "" XXX + SG_ TQI : 8|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_MAX : 40|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_MIN : 0|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_TARGET : 16|8@1+ (0.390625,0) [0|0] "" XXX + +BO_ 625 LPI11: 8 XXX + SG_ BFS_CYL : 48|8@1+ (1,0) [0|0] "" XXX + SG_ ERR_GAS : 16|8@1+ (1,0) [0|0] "" XXX + SG_ FAC_TI_GAS_COR : 24|16@1+ (3.05e-05,0) [0|0] "" XXX + SG_ FTL_AFU : 40|8@1+ (0.392,0) [0|0] "" XXX + SG_ FUP_LPG_MMV : 0|8@1+ (128,0) [0|0] "" XXX + SG_ LPI_OBD : 12|4@1+ (1,0) [0|0] "" XXX + SG_ LV_BFS_IN_PROGRESS : 9|1@1+ (1,0) [0|0] "" XXX + SG_ LV_CONF_INJECTION_DELAY : 57|1@1+ (1,0) [0|0] "" XXX + SG_ LV_FUEL_TYPE_BOX : 8|1@1+ (1,0) [0|0] "" XXX + SG_ LV_FUP_ENA_THD : 11|1@1+ (1,0) [0|0] "" XXX + SG_ LV_GAS_OK : 10|1@1+ (1,0) [0|0] "" XXX + SG_ LV_LPG_SW_DRIVER_REQ : 58|1@1+ (1,0) [0|0] "" XXX + SG_ LV_PRE_CDN_LEAK : 56|1@1+ (1,0) [0|0] "" XXX + +BO_ 640 EMS13: 8 XXX + SG_ AMP : 56|8@1+ (21.22,0) [0|0] "" XXX + SG_ EOS : 16|8@1+ (1,0) [0|0] "" XXX + SG_ ERR_FUEL : 8|8@1+ (1,0) [0|0] "" XXX + SG_ LV_BFS_CFIRM : 1|1@1+ (1,0) [0|0] "" XXX + SG_ LV_CRASH : 2|1@1+ (1,0) [0|0] "" XXX + SG_ LV_ENG_TURN : 5|1@1+ (1,0) [0|0] "" XXX + SG_ LV_FUEL_TYPE_ECU : 0|1@1+ (1,0) [0|0] "" XXX + SG_ LV_GSL_MAP : 4|1@1+ (1,0) [0|0] "" XXX + SG_ LV_VB_OFF_ACT : 3|1@1+ (1,0) [0|0] "" XXX + SG_ MAF : 40|8@1+ (5.447,0) [0|0] "" XXX + SG_ MAP : 56|8@1+ (0.47058,0) [0|0] "" XXX + SG_ N_32 : 32|8@1+ (32,0) [0|0] "" XXX + SG_ TCO : 24|8@1+ (0.75,-48) [0|0] "" XXX + SG_ TIA : 48|8@1+ (0.75,-48) [0|0] "" XXX + +BO_ 688 SAS11: 5 XXX + SG_ CheckSum : 36|4@1+ (1,0) [0|0] "" XXX + SG_ MsgCount : 32|4@1+ (1,0) [0|0] "" XXX + SG_ SAS_Angle : 0|16@1- (0.1,0) [0|0] "" XXX + SG_ SAS_Speed : 16|8@1+ (4,0) [0|0] "" XXX + SG_ SAS_Stat : 24|8@1+ (1,0) [0|0] "" XXX + +BO_ 790 EMS11: 8 XXX + SG_ ACK_TCS : 2|1@1+ (1,0) [0|0] "" XXX + SG_ F_N_ENG : 1|1@1+ (1,0) [0|0] "" XXX + SG_ F_SUB_TQI : 7|1@1+ (1,0) [0|0] "" XXX + SG_ N : 16|16@1+ (0.25,0) [0|0] "" XXX + SG_ PUC_STAT : 3|1@1+ (1,0) [0|0] "" XXX + SG_ RATIO_TQI_BAS_MAX_STND : 56|8@1+ (0.0078,0) [0|0] "" XXX + SG_ RLY_AC : 6|1@1+ (1,0) [0|0] "" XXX + SG_ SWI_IGK : 0|1@1+ (1,0) [0|0] "" XXX + SG_ TQFR : 40|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI : 32|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_ACOR : 8|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQ_COR_STAT : 4|2@1+ (1,0) [0|0] "" XXX + SG_ VS : 48|8@1+ (1,0) [0|0] "" XXX + +BO_ 809 EMS12: 8 XXX + SG_ ACC_ACT : 30|1@1+ (1,0) [0|0] "" XXX + SG_ ACK_ES : 25|1@1+ (1,0) [0|0] "" XXX + SG_ BRAKE_ACT : 32|2@1+ (1,0) [0|0] "" XXX + SG_ CAN_VERS : 0|6@1+ (1,0) [0|0] "" XXX + SG_ CLU_ACK : 31|1@1+ (1,0) [0|0] "" XXX + SG_ CONF_MIL_FMY : 26|3@1+ (1,0) [0|0] "" XXX + SG_ CONF_TCU : 0|6@1+ (1,0) [0|0] "" XXX + SG_ ENG_CHR : 34|4@1+ (1,0) [0|0] "" XXX + SG_ ENG_VOL : 56|8@1+ (0.1,0) [0|0] "" XXX + SG_ GP_CTL : 38|2@1+ (1,0) [0|0] "" XXX + SG_ MAF_FAC_ALTI_MMV : 16|8@1+ (0.00781,0) [0|0] "" XXX + SG_ MUL_CODE : 6|2@1+ (1,0) [0|0] "" XXX + SG_ OBD_FRF_ACK : 0|6@1+ (1,0) [0|0] "" XXX + SG_ OD_OFF_REQ : 29|1@1+ (1,0) [0|0] "" XXX + SG_ PV_AV_CAN : 48|8@1+ (0.3906,0) [0|0] "" XXX + SG_ TEMP_ENG : 8|8@1+ (0.75,-48) [0|0] "" XXX + SG_ TPS : 40|8@1+ (0.4694836,-15.0234742) [0|0] "" XXX + SG_ TQ_STND : 0|6@1+ (10,0) [0|0] "" XXX + SG_ VB_OFF_ACT : 24|1@1+ (1,0) [0|0] "" XXX + +BO_ 832 LKAS11: 8 XXX + SG_ CF_Lkas_ActToi : 27|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Lkas_Chksum : 0|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Lkas_FcwOpt_USM : 32|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Lkas_LdwsActivemode : 30|2@1+ (1,0) [0|3] "" CLU,IBOX,PSB + SG_ CF_Lkas_LdwsLHWarning : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,PSB + SG_ CF_Lkas_LdwsRHWarning : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,PSB + SG_ CF_Lkas_MsgCount : 36|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,MDPS + SG_ CF_Lkas_ToiFlt : 28|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CR_Lkas_StrToqReq : 16|11@1+ (1.0,-1024.0) [-1024.0|1024.0] "" MDPS + SG_ NEW_SIGNAL_1 : 8|2@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_2 : 14|2@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_3 : 29|1@0+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_4 : 35|1@0+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 854 M_356: 8 XXX + SG_ PAINT1 : 32|1@0+ (1,0) [0|0] "" XXX + SG_ PAINT2 : 34|2@0+ (1,0) [0|0] "" XXX + SG_ PAINT3 : 36|2@0+ (1,0) [0|0] "" XXX + SG_ PAINT4 : 38|1@0+ (1,0) [0|0] "" XXX + +BO_ 867 RADAR_0x363: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ FCA_ESA : 8|2@1+ (1,0) [0|3] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 870 EMS_366: 8 XXX + SG_ N : 8|16@1+ (0.25,0) [0|0] "" XXX + SG_ SWI_IGK : 48|1@0+ (1,0) [0|0] "" XXX + SG_ TQI_1 : 0|8@1+ (0.390625,0) [0|0] "" XXX + SG_ TQI_2 : 24|8@1+ (0.390625,0) [0|0] "" XXX + SG_ VS : 40|8@1+ (1,0) [0|0] "" XXX + +BO_ 871 LVR12: 8 XXX + SG_ CF_Lvr_CruiseSet : 0|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_Gear : 32|4@1+ (1,0) [0|0] "" XXX + +BO_ 872 LVR11: 8 XXX + SG_ CF_Lvr_AC : 48|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_BkeAct : 5|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_CS : 52|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_GearInf : 0|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_NFnStat : 6|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_PNStat : 20|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_PRelStat : 4|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_PosCpl : 12|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_PosInf : 8|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_ShfErrInf : 28|20@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_ShtLkStat : 24|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Lvr_UlkButStat : 18|2@1+ (1,0) [0|0] "" XXX + +BO_ 897 MDPS11: 8 XXX + SG_ CF_MDPS_VSM_FUNC : 56|1@0+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_ALTRequest : 23|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_AliveCnt : 40|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_Chksum : 48|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_CurrMode : 59|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_Flex : 2|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_FlexDisp : 5|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_LKAS_FUNC : 58|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_SPAS_FUNC : 57|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_Stat : 7|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_Type : 61|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Mdps_WLmp : 0|2@1+ (1,0) [0|0] "" XXX + SG_ CR_Mdps_DrvTq : 11|12@1+ (1,-2048) [0|0] "" XXX + SG_ CR_Mdps_StrAng : 24|16@1- (0.1,0) [0|0] "" XXX + +BO_ 902 WHL_SPD11: 8 XXX + SG_ WHL_SPD_AliveCounter_LSB : 14|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_SPD_AliveCounter_MSB : 30|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_SPD_Checksum_LSB : 46|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_SPD_Checksum_MSB : 62|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_SPD_FL : 0|14@1+ (0.03125,0) [0|0] "" XXX + SG_ WHL_SPD_FR : 16|14@1+ (0.03125,0) [0|0] "" XXX + SG_ WHL_SPD_RL : 32|14@1+ (0.03125,0) [0|0] "" XXX + SG_ WHL_SPD_RR : 48|14@1+ (0.03125,0) [0|0] "" XXX + +BO_ 903 WHL_PUL11: 6 XXX + SG_ WHL_DIR_FL : 32|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_DIR_FR : 34|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_DIR_RL : 36|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_DIR_RR : 38|2@1+ (1,0) [0|0] "" XXX + SG_ WHL_PUL_Chksum : 40|8@1+ (1,0) [0|0] "" XXX + SG_ WHL_PUL_FL : 0|8@1+ (0.5,0) [0|0] "" XXX + SG_ WHL_PUL_FR : 8|8@1+ (0.5,0) [0|0] "" XXX + SG_ WHL_PUL_RL : 16|8@1+ (0.5,0) [0|0] "" XXX + SG_ WHL_PUL_RR : 24|8@1+ (0.5,0) [0|0] "" XXX + +BO_ 905 SCC14: 8 XXX + SG_ ACC_ObjLatPos : 16|9@1+ (0.1,-20) [-20|31.1] "m" ABS,ESC + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ ObjGap : 51|3@1+ (1,0) [0|255] "" CLU,HUD,ESC + +BO_ 909 FCA11: 8 XXX + SG_ CR_FCA_ChkSum : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ CR_FCA_Alive : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 913 BCM_PO_11: 8 XXX + SG_ BCM_Door_Dri_Status : 5|1@0+ (1,0) [0|0] "" XXX + SG_ BCM_Shift_R_MT_SW_Status : 39|2@0+ (1,0) [0|0] "" XXX + SG_ LFA_Pressed : 4|1@0+ (1,0) [0|0] "" XXX + +BO_ 916 TCS13: 8 XXX + SG_ ACCEL_REF_ACC : 32|11@1+ (0.01,-10.23) [0|0] "" XXX + SG_ ACCEnable : 43|2@1+ (1,0) [0|0] "" XXX + SG_ ACC_EQUIP : 52|1@1+ (1,0) [0|0] "" XXX + SG_ ACC_REQ : 54|1@1+ (1,0) [0|0] "" XXX + SG_ AEB_EQUIP : 63|1@1+ (1,0) [0|0] "" XXX + SG_ AliveCounterTCS : 13|3@1+ (1,0) [0|0] "" XXX + SG_ BrakeLight : 11|1@1+ (1,0) [0|0] "" XXX + SG_ CF_DriBkeStat : 60|1@1+ (1,0) [0|0] "" XXX + SG_ CF_VSM_Avail : 57|2@1+ (1,0) [0|0] "" XXX + SG_ CF_VSM_Coded : 56|1@1+ (1,0) [0|0] "" XXX + SG_ CF_VSM_ConfSwi : 61|2@1+ (1,0) [0|0] "" XXX + SG_ CF_VSM_Handshake : 59|1@1+ (1,0) [0|0] "" XXX + SG_ CheckSum_TCS3 : 48|4@1+ (1,0) [0|0] "" XXX + SG_ DCEnable : 12|1@1+ (1,0) [0|0] "" XXX + SG_ DF_BF_STAT : 19|2@1+ (1,0) [0|0] "" XXX + SG_ DriverBraking : 55|1@1+ (1,0) [0|0] "" XXX + SG_ DriverOverride : 45|2@1+ (1,0) [0|0] "" XXX + SG_ EBA_ACK : 17|1@1+ (1,0) [0|0] "" XXX + SG_ FCA_ACK : 18|1@1+ (1,0) [0|0] "" XXX + SG_ PBRAKE_ACT : 53|1@1+ (1,0) [0|0] "" XXX + SG_ Pre_TCS_CTL : 16|1@1+ (1,0) [0|0] "" XXX + SG_ SCCReqLim : 22|2@1+ (1,0) [0|0] "" XXX + SG_ StandStill : 47|1@1+ (1,0) [0|0] "" XXX + SG_ TQI_SCC : 24|8@1+ (0.390625,0) [0|0] "" XXX + SG_ aBasis : 0|11@1+ (0.01,-10.23) [0|0] "" XXX + +BO_ 920 RADAR_0x398: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 921 RADAR_0x399: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 922 RADAR_0x39a: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 923 RADAR_0x39b: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 924 RADAR_0x39c: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 1040 CGW_USM1: 8 XXX + SG_ CF_Gway_ADrLRValue : 8|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ADrURValue : 11|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ATTurnRValue : 0|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_AutoLightRValue : 35|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrLockSoundRValue : 24|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_EscortHLRValue : 4|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HAnBRValue : 27|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HfreeTrunkRValue : 32|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_MoodLpRValue : 30|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_OTTurnRValue : 21|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PSMRValue : 18|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PTGMRValue : 2|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PasSpkrLvRValue : 40|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RearWiperRValue : 38|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SCMRValue : 14|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_TTUnlockRValue : 6|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WlightRValue : 16|2@1+ (1,0) [0|0] "" XXX + +BO_ 1042 ICM_412h: 8 XXX + SG_ PopupMessageOutput_1Level : 48|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_2Level : 49|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_3Level : 50|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_4Level : 51|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_5Level : 52|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_6Level : 53|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_7Level : 54|1@0+ (1,0) [0|0] "" XXX + SG_ PopupMessageOutput_8Level : 55|1@0+ (1,0) [0|0] "" XXX + SG_ TRIP_A_DT_Display_clock : 22|7@0+ (1,0) [0|0] "" XXX + SG_ TRIP_A_DT_Display_minute : 29|6@0+ (1,0) [0|0] "" XXX + SG_ TRIP_B_DT_Display_clock : 38|7@0+ (1,0) [0|0] "" XXX + SG_ TRIP_B_DT_Display_minute : 45|6@0+ (1,0) [0|0] "" XXX + SG_ T_Outside_input : 0|9@0+ (0.01,0) [0|0] "" XXX + SG_ WarningSoundOutput_1Group : 5|1@0+ (1,0) [0|0] "" XXX + SG_ WarningSoundOutput_2Group : 6|1@0+ (1,0) [0|0] "" XXX + SG_ WarningSoundOutput_3Group : 7|1@0+ (1,0) [0|0] "" XXX + +BO_ 1056 SCC11: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ AliveCounterACC : 12|4@1+ (1,0) [0|15] "" CLU,EMS,ESC,TCU + SG_ JerkLowerLimit : 50|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC + SG_ JerkUpperLimit : 43|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC + SG_ ObjValid : 59|1@1+ (1,0) [0|1] "" CLU,ESC,TCU + SG_ aReqRaw : 27|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" Vector__XXX + SG_ aReqValue : 16|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" Vector__XXX + +BO_ 1057 SCC12: 8 XXX + SG_ ACCMode : 28|2@1+ (1,0) [0|3] "" CLU,HUD,LDWS_LKAS,ESC + SG_ ACCMode_Inactive : 30|1@1+ (1,0) [0|1] "" CLU,HUD,LDWS_LKAS,ESC + SG_ ACC_ObjDist : 16|11@1+ (0.1,0) [0|204.7] "m" ABS,ESC + SG_ CR_VSM_ChkSum : 0|8@1+ (1,0) [0|0] "" XXX + SG_ CR_VSM_Alive : 12|4@1+ (1,0) [0|15] "" ESC,PSB + SG_ MainMode_ACC : 27|1@1+ (1,0) [0|1] "" CLU,EMS,ESC + SG_ SCCInfoDisplay : 32|3@1+ (1,0) [0|7] "" CLU,ESC + SG_ TauGapSet : 37|3@1+ (1,0) [0|7] "" CLU,ESC,TCU + SG_ VSetDis : 41|8@1+ (1,0) [0|255] "km/h or MPH" CLU,ESC,TCU + SG_ StopReq : 49|1@1+ (1,0) [0|1] "" EPB,ESC + +BO_ 1064 _4WD11: 8 XXX + SG_ AUTO_ACT : 43|1@1+ (1,0) [0|0] "" XXX + SG_ CLU_DUTY : 16|8@1+ (1,0) [0|0] "" XXX + SG_ LOCK_ACT : 44|1@1+ (1,0) [0|0] "" XXX + SG_ LOW_ACT : 42|1@1+ (1,0) [0|0] "" XXX + SG_ R_TIRE : 24|8@1+ (1,200) [0|0] "" XXX + SG_ _2H_ACT : 40|1@1+ (1,0) [0|0] "" XXX + SG_ _4H_ACT : 41|1@1+ (1,0) [0|0] "" XXX + SG_ _4WD_ERR : 8|8@1+ (1,0) [0|0] "" XXX + SG_ _4WD_SUPPORT : 2|2@1+ (1,0) [0|0] "" XXX + SG_ _4WD_SW : 32|8@1+ (1,0) [0|0] "" XXX + SG_ _4WD_TQC_CUR : 48|16@1+ (1,0) [0|0] "" XXX + SG_ _4WD_TYPE : 0|2@1+ (1,0) [0|0] "" XXX + +BO_ 1078 PAS11: 4 XXX + SG_ CF_Gway_PASCheckSound : 22|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDisplayFCTR : 8|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDisplayFLH : 0|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDisplayFRH : 3|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDisplayRCTR : 11|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDisplayRLH : 16|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDisplayRRH : 19|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASDistance : 28|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASFsound : 14|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASOption : 26|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASRsound : 6|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PASSystemOn : 24|2@1+ (1,0) [0|0] "" XXX + +BO_ 1082 RADAR_0x43a: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 1136 P_STS: 8 XXX + SG_ Checksum : 62|2@1+ (1,0) [0|0] "" XXX + SG_ Counter : 58|4@1+ (1,0) [0|0] "" XXX + SG_ HCU1_STS : 6|2@1+ (1,0) [0|0] "" XXX + SG_ HCU5_STS : 8|2@1+ (1,0) [0|0] "" XXX + +BO_ 1151 ESP11: 6 XXX + SG_ AVH_STAT : 0|2@1+ (1,0) [0|0] "" XXX + SG_ ECD_ACT : 6|1@1+ (1,0) [0|0] "" XXX + SG_ LDM_STAT : 2|1@1+ (1,0) [0|0] "" XXX + SG_ REQ_EPB_ACT : 3|2@1+ (1,0) [0|0] "" XXX + SG_ REQ_EPB_STAT : 5|1@1+ (1,0) [0|0] "" XXX + SG_ ROL_CNT_ESP : 8|8@1+ (1,0) [0|0] "" XXX + SG_ _4WD_CLU_LIM : 32|8@1+ (0.390625,0) [0|0] "" XXX + SG_ _4WD_LIM_MODE : 42|1@1+ (1,0) [0|0] "" XXX + SG_ _4WD_LIM_REQ : 7|1@1+ (1,0) [0|0] "" XXX + SG_ _4WD_OPEN : 40|2@1+ (1,0) [0|0] "" XXX + SG_ _4WD_TQC_LIM : 16|16@1+ (1,0) [0|0] "" XXX + +BO_ 1157 LFAHDA_MFC: 8 XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_1 : 8|4@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_2 : 16|1@0+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_3 : 17|1@0+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_4 : 18|1@0+ (1,0) [0|0] "" XXX + SG_ HDA_Icon_State : 19|2@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_5 : 21|3@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_6 : 24|1@0+ (1,0) [0|0] "" XXX + SG_ LFA_Icon_State : 25|2@1+ (1,0) [0|0] "" XXX + SG_ NEW_SIGNAL_7 : 27|37@1+ (1,0) [0|0] "" XXX + +BO_ 1162 BCA11: 8 XXX + SG_ AliveCounter : 21|4@1+ (1,0) [0|0] "" XXX + SG_ CF_BCA_State : 16|3@1+ (1,0) [0|0] "" XXX + SG_ CF_BCA_Warning : 19|2@1+ (1,0) [0|0] "" XXX + SG_ Check_Sum : 56|8@1+ (1,0) [0|0] "" XXX + SG_ RCCA_Brake_Command : 29|1@1+ (1,0) [0|0] "" XXX + +BO_ 1168 EPB11: 7 XXX + SG_ EPB_ALARM : 6|2@1+ (1,0) [0|0] "" XXX + SG_ EPB_CLU : 8|8@1+ (1,0) [0|0] "" XXX + SG_ EPB_DBF_DECEL : 48|8@1+ (0.01,0) [0|0] "" XXX + SG_ EPB_DBF_REQ : 26|1@1+ (1,0) [0|0] "" XXX + SG_ EPB_DBF_STAT : 24|1@1+ (1,0) [0|0] "" XXX + SG_ EPB_FAIL : 29|3@1+ (1,0) [0|0] "" XXX + SG_ EPB_FORCE : 32|12@1+ (1,-1000) [0|0] "" XXX + SG_ EPB_FRC_ERR : 22|2@1+ (1,0) [0|0] "" XXX + SG_ EPB_F_LAMP : 4|2@1+ (1,0) [0|0] "" XXX + SG_ EPB_I_LAMP : 0|4@1+ (1,0) [0|0] "" XXX + SG_ EPB_RBL : 18|1@1+ (1,0) [0|0] "" XXX + SG_ EPB_STATUS : 19|3@1+ (1,0) [0|0] "" XXX + SG_ EPB_SWITCH : 16|2@1+ (1,0) [0|0] "" XXX + SG_ ESP_ACK : 25|1@1+ (1,0) [0|0] "" XXX + +BO_ 1170 EMS19: 8 XXX + SG_ BAT_LAMP_STAT : 42|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_AAFOpenReq : 7|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_AliveCounterEMS9 : 58|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_BrkReq : 0|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_ChecksumEMS9 : 60|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_DecelReq : 8|12@1+ (0.001,-4.094) [0|0] "" XXX + SG_ CF_Ems_DnShftReq : 1|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_ModeledAmbTemp : 48|8@1+ (0.5,-41) [0|0] "" XXX + SG_ CF_Ems_OPSFail : 56|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Ems_RepModChk : 5|2@1+ (1,0) [0|0] "" XXX + SG_ CR_Ems_BstPre : 20|12@1+ (1.322,0) [0|0] "" XXX + SG_ CR_Ems_EngOilTemp : 32|8@1+ (0.75,-40) [0|0] "" XXX + SG_ DPF_LAMP_STAT : 40|2@1+ (1,0) [0|0] "" XXX + +BO_ 1173 YRS13: 8 XXX + SG_ YRS_SeralNo : 16|48@1+ (1,0) [0|0] "" XXX + +BO_ 1186 FRT_RADAR11: 2 XXX + SG_ BYTE0 : 0|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE1 : 8|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE2 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE3 : 24|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE4 : 32|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE5 : 40|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE6 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ BYTE7 : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 1265 CLU11: 4 XXX + SG_ CF_Clu_AliveCnt1 : 28|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_AmpInfo : 25|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_CluInfo : 24|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_CruiseSwMain : 3|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_CruiseSwState : 0|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_DetentOut : 18|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_ParityBit1 : 5|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_RheostatLevel : 19|5@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_SPEED_UNIT : 17|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_SldMainSW : 4|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_Vanz : 8|9@1+ (0.5,0) [0|0] "" XXX + SG_ CF_Clu_VanzDecimal : 6|2@1+ (0.125,0) [0|0] "" XXX + +BO_ 1280 ACU14: 1 XXX + SG_ CF_SBR_Ind : 4|2@1+ (1,0) [0|0] "" XXX + SG_ CF_SWL_Ind : 0|2@1+ (1,0) [0|0] "" XXX + SG_ CF_TTL_Ind : 2|2@1+ (1,0) [0|0] "" XXX + +BO_ 1287 TCS15: 4 XXX + SG_ ABS_W_LAMP : 0|1@1+ (1,0) [0|0] "" XXX + SG_ AVH_ALARM : 27|2@1+ (1,0) [0|0] "" XXX + SG_ AVH_CLU : 16|8@1+ (1,0) [0|0] "" XXX + SG_ AVH_I_LAMP : 24|2@1+ (1,0) [0|0] "" XXX + SG_ AVH_LAMP : 29|3@1+ (1,0) [0|0] "" XXX + SG_ DBC_F_LAMP : 6|2@1+ (1,0) [0|0] "" XXX + SG_ DBC_W_LAMP : 5|1@1+ (1,0) [0|0] "" XXX + SG_ EBD_W_LAMP : 26|1@1+ (1,0) [0|0] "" XXX + SG_ ESC_Off_Step : 8|2@1+ (1,0) [0|0] "" XXX + SG_ TCS_LAMP : 3|2@1+ (1,0) [0|0] "" XXX + SG_ TCS_OFF_LAMP : 1|2@1+ (1,0) [0|0] "" XXX + +BO_ 1292 CLU13: 8 XXX + SG_ CF_Clu_ActiveEcoSW : 39|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_AliveCnt2 : 60|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_AltLStatus : 59|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_AvgFCI : 6|10@1+ (0.1,0) [0|0] "" XXX + SG_ CF_Clu_AvgFCU : 3|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_AvsmCur : 5|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_DTE : 24|10@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_DrivingModeSwi : 16|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_EcoDriveInf : 40|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_FlexSteerSW : 23|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_FuelDispLvl : 18|5@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_IsaMainSW : 43|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_LdwsLkasSW : 56|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_LowfuelWarn : 0|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_RefDetMod : 2|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_SWL_Stat : 36|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_TripUnit : 34|2@1+ (1,0) [0|0] "" XXX + +BO_ 1312 CGW3: 8 XXX + SG_ CF_Hoodsw_memory : 22|2@1+ (1,0) [0|0] "" XXX + SG_ CR_Photosensor_LH : 0|8@1+ (78.125,0) [0|0] "" XXX + SG_ CR_Photosensor_RH : 10|8@1+ (78.125,0) [0|0] "" XXX + SG_ C_MirOutTempSns : 24|8@1+ (0.5,-40.5) [0|0] "" XXX + +BO_ 1322 CLU15: 8 XXX + SG_ CF_Clu_ClusterSound : 38|1@1- (1,0) [0|0] "" XXX + SG_ CF_Clu_Gear : 9|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudBrightDnSW : 24|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudBrightUpSW : 22|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudFontColorSet : 20|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudFontSizeSet : 31|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudHeightDnSW : 28|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudHeightUpSW : 26|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudInfoSet : 13|7@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_HudSet : 30|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_LanguageInfo : 33|5@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_VehicleSpeed : 0|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Clu_VehicleSpeed2 : 48|8@1+ (1,0) [0|0] "" XXX + +BO_ 1342 LKAS12: 8 XXX + SG_ CF_LkasDawStatus : 40|3@1+ (1,0) [0|0] "" XXX + SG_ CF_LkasTsrSpeed_Display_Navi : 24|8@1+ (1,0) [0|0] "" XXX + SG_ CF_Lkas_Daw_USM : 37|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Lkas_TsrAddinfo_Display : 32|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Lkas_TsrSlifOpt : 10|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Lkas_TsrSpeed_Display_Clu : 16|8@1+ (1,0) [0|0] "" XXX + SG_ _CHECKSUM : 0|8@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|0] "" XXX + +BO_ 1345 CGW1: 8 XXX + SG_ CF_Gway_ALightStat : 37|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_AstDrSw : 35|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_AstSeatBeltSw : 14|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DefoggerRly : 36|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DriveTypeOption : 43|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvDrSw : 8|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvKeyLockSw : 6|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvKeyUnlockSw : 7|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvSeatBeltSw : 10|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_Frt_Fog_Act : 40|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HBAControlMode : 52|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HLpHighSw : 53|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HazardSw : 33|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HeadLampHigh : 32|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HeadLampLow : 31|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HoodSw : 17|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_IGNSw : 0|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_Ign1 : 58|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_Ign2 : 59|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_InhibitRMT : 54|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_LightSwState : 38|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ParkBrakeSw : 60|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PassingSW : 51|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PassiveAccessLock : 45|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PassiveAccessUnlock : 48|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RKECmd : 3|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RainSnsOption : 56|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RainSnsState : 28|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RrSunRoofOpenState : 50|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SMKOption : 16|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_StarterRlyState : 44|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_TSigLHSw : 42|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_TSigRHSw : 41|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_TrunkTgSw : 12|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_TurnSigLh : 19|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_TurnSigRh : 62|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperAutoSw : 27|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperHighSw : 26|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperIntSw : 24|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperIntT : 21|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperLowSw : 25|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperMistSw : 47|1@1+ (1,0) [0|0] "" XXX + SG_ C_SunRoofOpenState : 57|1@1+ (1,0) [0|0] "" XXX + +BO_ 1348 Navi_HU: 8 XXX + SG_ SpeedLim_Nav_Clu : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 1363 CGW2: 8 XXX + SG_ CF_Gway_AutoLightOption : 54|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_AutoLightValue : 16|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_AvTail : 20|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_BCMRKEID : 41|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_BrakeFluidSw : 17|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_CLUSwEnter : 15|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_CLUSwGroup : 13|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_CLUSwGuiCtrl : 10|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_CLUSwMode : 14|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_CountryCfg : 26|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DDMDiagState : 1|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DeactivationWarn : 45|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvSeatBeltInd : 18|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ESCLFailWarn : 35|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ESCLNotLockedWarn : 36|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ESCLNotUnlockWarn : 37|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ExtTailAct : 22|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_GwayDiagState : 0|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HLLowLHFail : 33|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_HLLowRHFail : 34|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_IDoutWarn : 38|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_IPMDiagState : 5|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_ImmoLp : 40|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_IntTailAct : 25|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_KeyBATDischargeWarn : 46|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_KeyoutLp : 56|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_LDMFail : 6|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PSMDiagState : 3|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RLDrSw : 24|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RRDrSw : 23|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RearFogAct : 21|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SCMDiagState : 2|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SJBDeliveryMode : 55|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SJBDiagState : 4|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SMKDispWarn : 57|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SMKFobID : 48|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SMKRKECmd : 51|3@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_SSBWarn : 47|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_VehicleNotPWarn : 44|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WiperParkPosition : 32|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_WngBuz : 61|3@1+ (1,0) [0|0] "" XXX + +BO_ 1369 CGW4: 8 XXX + SG_ CF_Gway_AstSeatBeltInd : 38|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_AstWdwStat : 11|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvSeatBeltInd : 36|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_DrvWdwStat : 8|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_IMSBuzzer : 15|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_MemoryEnable : 12|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_MemoryP1Cmd : 0|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_MemoryP2Cmd : 1|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PBACKStop : 14|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PBACKStopCmd : 13|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PBackP1Cmd : 2|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PBackP2Cmd : 3|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_PBackStopCmd : 5|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RCSeatBeltInd : 40|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RLSeatBeltInd : 42|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RLWdwState : 9|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RRSeatBeltInd : 44|2@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RRWdwState : 10|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RrWiperHighSw : 46|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_RrWiperLowSw : 47|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_StaticBendLhAct : 6|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_StaticBendRhAct : 7|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Gway_StrgWhlHeatedState : 4|1@1+ (1,0) [0|0] "" XXX + +BO_ 1370 HU_AVM_PE_00: 8 XXX + SG_ HU_AVM_Status : 0|2@1+ (1,0) [0|0] "" XXX + +BO_ 1371 AVM_HU_PE_00: 8 XXX + SG_ AVM_Display_Message : 8|8@1+ (1,0) [0|0] "" XXX + SG_ AVM_FrontBtn_Type : 28|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_HU_FrontViewPointOpt : 36|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_HU_FrontView_Option : 44|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_HU_RearView_Option : 40|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_Option : 32|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_ParkingAssist_BtnSts : 5|3@1+ (1,0) [0|0] "" XXX + SG_ AVM_ParkingAssist_Step : 24|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_Popup_Msg : 16|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_Ready : 20|4@1+ (1,0) [0|0] "" XXX + SG_ AVM_Version : 48|16@1+ (1,0) [0|0] "" XXX + SG_ AVM_View : 0|5@1+ (1,0) [0|0] "" XXX + +BO_ 1407 HU_MON_PE_01: 8 XXX + SG_ HU_Type : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1419 LCA11: 8 XXX + SG_ CF_Lca_IndLeft : 29|1@1+ (1,0) [0|0] "" XXX + SG_ CF_Lca_IndRight : 37|1@1+ (1,0) [0|0] "" XXX + +BO_ 1427 TPMS11: 6 XXX + SG_ POS_FL_W_LAMP : 4|1@1+ (1,0) [0|0] "" XXX + SG_ POS_FR_W_LAMP : 5|1@1+ (1,0) [0|0] "" XXX + SG_ POS_RL_W_LAMP : 6|1@1+ (1,0) [0|0] "" XXX + SG_ POS_RR_W_LAMP : 7|1@1+ (1,0) [0|0] "" XXX + SG_ PRESSURE_FL : 16|8@1+ (1,0) [0|0] "" XXX + SG_ PRESSURE_FR : 24|8@1+ (1,0) [0|0] "" XXX + SG_ PRESSURE_RL : 32|8@1+ (1,0) [0|0] "" XXX + SG_ PRESSURE_RR : 40|8@1+ (1,0) [0|0] "" XXX + SG_ STATUS_TPMS : 8|3@1+ (1,0) [0|0] "" XXX + SG_ TPMS_W_LAMP : 0|2@1+ (1,0) [0|0] "" XXX + SG_ TREAD_W_LAMP : 2|2@1+ (1,0) [0|0] "" XXX + SG_ UNIT : 11|2@1+ (1,0) [0|0] "" XXX + +BO_ 1456 CLU12: 4 XXX + SG_ CF_Clu_Odometer : 0|24@1+ (0.1,0) [0|0] "" XXX + + +CM_ SG_ 1348 SpeedLim_Nav_Clu "Speed limit displayed on Nav, Cluster and HUD"; + +VAL_ 871 CF_Lvr_Gear 12 "T" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; +VAL_ 909 CF_VSM_Warn 2 "FCW" 3 "AEB"; +VAL_ 916 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue"; +VAL_ 1057 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled"; +VAL_ 1157 HDA_Icon_State 0 "no_hda" 1 "white_hda" 2 "green_hda"; +VAL_ 1157 LFA_SysWarning 0 "no_message" 1 "switching_to_hda" 2 "switching_to_scc" 3 "lfa_error" 4 "check_hda" 5 "keep_hands_on_wheel_orange" 6 "keep_hands_on_wheel_red"; +VAL_ 1157 LFA_Icon_State 0 "no_wheel" 1 "white_wheel" 2 "green_wheel" 3 "green_wheel_blink"; +VAL_ 1157 HDA_SysWarning 0 "no_message" 1 "driving_convenience_systems_cancelled" 2 "highway_drive_assist_system_cancelled"; +VAL_ 1322 CF_Clu_Gear 1 "P" 2 "R" 4 "N" 8 "D"; diff --git a/opendbc_repo/opendbc/dbc/generator/nissan/_nissan_common.dbc b/opendbc_repo/opendbc/dbc/generator/nissan/_nissan_common.dbc new file mode 100644 index 0000000000..46a65a7b7e --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/nissan/_nissan_common.dbc @@ -0,0 +1,117 @@ +BO_ 2 STEER_ANGLE_SENSOR: 5 XXX + SG_ STEER_ANGLE_RATE : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SET_ME_X07 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ STEER_ANGLE : 0|16@1- (-0.1,0) [0|65535] "" XXX + SG_ COUNTER : 32|4@1+ (1,0) [0|15] "" XXX + +BO_ 361 LKAS: 8 XXX + SG_ MAX_TORQUE : 39|8@0+ (0.01,0) [0|255] "Nm" XXX + SG_ SET_0x80 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ LKA_ACTIVE : 52|1@0+ (1,0) [0|15] "" XXX + SG_ SET_0x80_2 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ DESIRED_ANGLE : 7|18@0+ (-0.01,1310) [-1311.43|1310] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 389 STEER_TORQUE_SENSOR: 8 XXX + SG_ LKAS_ACTIVE : 37|1@0+ (1,0) [0|3] "" XXX + SG_ STEER_TORQUE_LKAS : 47|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_ANGLE : 23|18@0+ (-0.01,1310) [0|262143] "" XXX + SG_ STEER_TORQUE_DRIVER : 7|12@0+ (-0.01,20.47) [0|4095] "Nm" XXX + SG_ COUNTER : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|127] "" XXX + +BO_ 645 WHEEL_SPEEDS_REAR: 8 XXX + SG_ WHEEL_SPEED_RR : 7|16@0+ (0.005,0) [0|65535] "KPH" XXX + SG_ WHEEL_SPEED_RL : 23|16@0+ (0.005,0) [0|65535] "KPH" XXX + +BO_ 689 PROPILOT_HUD: 8 XXX + SG_ LARGE_WARNING_FLASHING : 9|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_ERROR_FLASHING1 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_ERROR_FLASHING2 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_LANE_YELLOW_FLASH : 12|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_LANE_YELLOW_FLASH : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LEAD_CAR : 14|1@0+ (1,0) [0|1] "" XXX + SG_ LEAD_CAR_ERROR : 15|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_RADAR_ERROR : 16|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_RADAR_ERROR_FLASHING : 17|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_LANE_GREEN : 24|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_LANE_GREEN : 25|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_ERROR_FLASHING3 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_ERROR_FLASHING : 29|1@0+ (1,0) [0|1] "" XXX + SG_ SAFETY_SHIELD_ACTIVE : 44|1@0+ (1,0) [0|1] "" XXX + SG_ LARGE_STEERING_WHEEL_ICON : 61|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_LANE_GREEN_FLASH : 62|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_LANE_GREEN_FLASH : 63|1@0+ (1,0) [0|1] "" XXX + SG_ FOLLOW_DISTANCE : 3|2@0+ (1,0) [0|3] "" XXX + SG_ AUDIBLE_TONE : 47|3@0+ (1,0) [0|8] "" XXX + SG_ SPEED_SET_ICON : 7|2@0+ (1,0) [0|3] "" XXX + SG_ SMALL_STEERING_WHEEL_ICON : 42|3@0+ (1,0) [0|7] "" XXX + SG_ SET_SPEED : 39|8@0+ (1,0) [0|255] "" XXX + SG_ unknown02 : 1|2@0+ (1,0) [0|3] "" XXX + SG_ unknown05 : 5|2@0+ (1,0) [0|3] "" XXX + SG_ unknown08 : 8|7@0+ (1,0) [0|63] "" XXX + SG_ unknown26 : 26|1@0+ (1,0) [0|1] "" XXX + SG_ unknown28 : 28|1@0+ (1,0) [0|1] "" XXX + SG_ unknown31 : 31|2@0+ (1,0) [0|3] "" XXX + SG_ unknown43 : 43|1@0+ (1,0) [0|1] "" XXX + SG_ unknown55 : 55|8@0+ (1,0) [0|63] "" XXX + SG_ unknown59 : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 451 PROPILOT_BRAKE: 8 XXX + SG_ BRAKE_PRESSURE : 5|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_ACTIVE : 47|1@0+ (1,0) [0|1] "" XXX + +BO_ 783 CRUISE_STATE: 3 XXX + SG_ CRUISE_ENABLED : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 1228 PROPILOT_HUD_INFO_MSG: 8 XXX + SG_ NA_HIGH_ACCEL_TEMP : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_NA_HIGH_CABIN_TEMP : 8|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_MALFUNCTION : 11|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_MALFUNCTION : 12|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_RADAR_MALFUNCTION : 13|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_NA_CLEAN_REAR_CAMERA : 14|1@0+ (1,0) [0|1] "" XXX + SG_ NA_POOR_ROAD_CONDITIONS : 16|1@0+ (1,0) [0|1] "" XXX + SG_ CURRENTLY_UNAVAILABLE : 17|1@0+ (1,0) [0|1] "" XXX + SG_ SAFETY_SHIELD_OFF : 18|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_COLLISION_NA_FRONT_RADAR_OBSTRUCTION : 20|1@0+ (1,0) [0|1] "" XXX + SG_ PEDAL_MISSAPPLICATION_SYSTEM_ACTIVATED : 24|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_IMPACT_NA_RADAR_OBSTRUCTION : 25|1@0+ (1,0) [0|1] "" XXX + SG_ WARNING_DO_NOT_ENTER : 33|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_IMPACT_SYSTEM_OFF : 34|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_IMPACT_MALFUNCTION : 35|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_COLLISION_MALFUNCTION : 36|1@0+ (1,0) [0|1] "" XXX + SG_ SIDE_RADAR_MALFUNCTION2 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_MALFUNCTION2 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_RADAR_MALFUNCTION2 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ PROPILOT_NA_MSGS : 42|3@0+ (1,0) [0|7] "" XXX + SG_ BOTTOM_MSG : 45|3@0+ (1,0) [0|7] "" XXX + SG_ HANDS_ON_WHEEL_WARNING : 47|1@0+ (1,0) [0|1] "" XXX + SG_ WARNING_STEP_ON_BRAKE_NOW : 51|1@0+ (1,0) [0|1] "" XXX + SG_ PROPILOT_NA_FRONT_CAMERA_OBSTRUCTED : 52|1@0+ (1,0) [0|1] "" XXX + SG_ PROPILOT_NA_HIGH_CABIN_TEMP : 53|1@0+ (1,0) [0|1] "" XXX + SG_ WARNING_PROPILOT_MALFUNCTION : 54|1@0+ (1,0) [0|3] "" XXX + SG_ ACC_UNAVAILABLE_HIGH_CABIN_TEMP : 62|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_NA_FRONT_CAMERA_IMPARED : 63|1@0+ (1,0) [0|1] "" XXX + SG_ unknown07 : 7|7@0+ (1,0) [0|127] "" XXX + SG_ unknown10 : 10|2@0+ (1,0) [0|3] "" XXX + SG_ unknown15 : 15|1@0+ (1,0) [0|1] "" XXX + SG_ unknown23 : 23|3@0+ (1,0) [0|7] "" XXX + SG_ unknown19 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ unknown31 : 31|6@0+ (1,0) [0|63] "" XXX + SG_ unknown32 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ unknown46 : 46|1@0+ (1,0) [0|1] "" XXX + SG_ unknown50 : 50|3@0+ (1,0) [0|7] "" XXX + SG_ unknown55 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ unknown61 : 61|6@0+ (1,0) [0|63] "" XXX + +BO_ 1227 LKAS_SETTINGS: 8 XXX + SG_ LKAS_ENABLED : 51|1@0+ (1,0) [0|1] "" XXX + +VAL_ 1228 PROPILOT_NA_MSGS 0 "NO_MSG" 1 "NA_FRONT_CAMERA_IMPARED" 2 "STEERING_ASSIST_ON_STANDBY" 3 "NA_PARKING_ASSIST_ENABLED" 4 "STEER_ASSIST_CURRENTLY_NA" 5 "NA_BAD_WEATHER" 6 "NA_PARK_BRAKE_ON" 7 "NA_SEATBELT_NOT_FASTENED" ; +VAL_ 1228 BOTTOM_MSG 0 "OK_STEER_ASSIST_SETTINGS" 1 "NO_MSG" 2 "PRESS_SET_TO_SET_SPEED" 3 "PRESS_RES_SET_TO_CHANGE_SPEED" 4 "PRESS_RES_TO_RESTART" 5 "NO_MSG" 6 "CRUISE_NOT_AVAIL" 7 "NO_MSG" ; +VAL_ 689 FOLLOW_DISTANCE 0 "NO_FOLLOW_DISTANCE" 1 "FOLLOW_DISTANCE_1" 2 "FOLLOW_DISTANCE_2" 3 "FOLLOW_DISTANCE_3" ; +VAL_ 689 AUDIBLE_TONE 0 "NO_TONE" 1 "CONT" 2 "FAST_BEEP_CONT" 3 "TRIPLE_FAST_BEEP_CONT" 4 "SLOW_BEEP_CONT" 5 "QUAD_SLOW_BEEP_CONT" 6 "SINGLE_BEEP_ONCE" 7 "DOUBLE_BEEP_ONCE" ; +VAL_ 689 SMALL_STEERING_WHEEL_ICON 0 "NO_ICON" 1 "GRAY_ICON" 2 "GRAY_ICON_FLASHING" 3 "GREEN_ICON" 4 "GREEN_ICON_FLASHING" 5 "RED_ICON" 6 "RED_ICON_FLASHING" 7 "YELLOW_ICON" ; +VAL_ 689 LARGE_STEERING_WHEEL_ICON 0 "NO_STEERINGWHEEL" 1 "GRAY_STEERINGWHEEL" 2 "GREEN_STEERINGWHEEL" 3 "GREEN_STEERINGWHEEL_FLASHING" ; diff --git a/opendbc_repo/opendbc/dbc/generator/nissan/nissan_leaf_2018.dbc b/opendbc_repo/opendbc/dbc/generator/nissan/nissan_leaf_2018.dbc new file mode 100644 index 0000000000..3376c3784c --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/nissan/nissan_leaf_2018.dbc @@ -0,0 +1,62 @@ +CM_ "IMPORT _nissan_common.dbc"; + +BO_ 42 SEATBELT: 8 XXX + SG_ SEATBELT_DRIVER_LATCHED : 27|1@1+ (1,0) [0|3] "" XXX + SG_ SEATBELT_DRIVER_UNLATCHED : 26|1@0+ (1,0) [0|1] "" XXX + SG_ unknown2 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ unknown3 : 24|2@1+ (1,0) [0|3] "" XXX + SG_ unknown1 : 7|24@0+ (1,0) [0|16777215] "" XXX + SG_ unknown4 : 39|16@0+ (1,0) [0|65535] "" XXX + +BO_ 460 BRAKE_PEDAL: 8 XXX + SG_ BRAKE_PEDAL : 7|8@0+ (1,0) [0|256] "" XXX + +BO_ 569 CRUISE_THROTTLE: 8 XXX + SG_ GAS_PEDAL_INVERTED : 15|8@0+ (1,0) [0|255] "" XXX + SG_ GAS_PEDAL : 7|8@0+ (1,0) [0|255] "" XXX + SG_ CRUISE_AVAILABLE : 17|1@0+ (1,0) [0|1] "" XXX + SG_ unsure1 : 23|6@0+ (1,0) [0|63] "" XXX + SG_ unsure2 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ unsure3 : 31|2@0+ (1,0) [0|3] "" XXX + SG_ NO_BUTTON_PRESSED : 29|1@0+ (1,0) [0|1] "" XXX + SG_ RES_BUTTON : 28|1@0+ (1,0) [0|1] "" XXX + SG_ SET_BUTTON : 27|1@0+ (1,0) [0|1] "" XXX + SG_ FOLLOW_DISTANCE_BUTTON : 26|1@0+ (1,0) [0|1] "" XXX + SG_ CANCEL_BUTTON : 25|1@0+ (1,0) [0|1] "" XXX + SG_ PROPILOT_BUTTON : 24|1@0+ (1,0) [0|1] "" XXX + SG_ USER_BRAKE_PRESSED : 37|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 32|2@1+ (1,0) [0|3] "" XXX + SG_ unsure5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ unsure6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ unsure7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 640 CANCEL_MSG: 8 XXX + SG_ CANCEL_SEATBELT : 1|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 7|6@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_2 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 15|56@0+ (1,0) [0|72057594037927940] "" XXX + +BO_ 644 WHEEL_SPEEDS_FRONT: 8 XXX + SG_ WHEEL_SPEED_FR : 7|16@0+ (0.005,0) [0|65535] "KPH" XXX + SG_ WHEEL_SPEED_FL : 23|16@0+ (0.005,0) [0|65535] "KPH" XXX + +BO_ 852 ESP: 8 XXX + SG_ ESP_DISABLED : 38|1@0+ (1,0) [0|1] "" XXX + +BO_ 853 HUD_SETTINGS: 8 XXX + SG_ SPEED_MPH : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 856 LIGHTS: 8 XXX + SG_ LEFT_BLINKER : 17|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_BLINKER : 18|1@0+ (1,0) [0|1] "" XXX + +BO_ 1057 GEARBOX: 3 XXX + SG_ GEAR_SHIFTER : 5|3@0+ (1,0) [0|255] "" XXX + +BO_ 1549 DOORS_LIGHTS: 8 XXX + SG_ DOOR_OPEN_FL : 3|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 5|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 6|1@0+ (1,0) [0|1] "" XXX + +VAL_ 1057 GEAR_SHIFTER 7 "B" 4 "D" 3 "N" 2 "R" 1 "P" ; diff --git a/opendbc_repo/opendbc/dbc/generator/nissan/nissan_x_trail_2017.dbc b/opendbc_repo/opendbc/dbc/generator/nissan/nissan_x_trail_2017.dbc new file mode 100644 index 0000000000..46e6f9c99a --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/nissan/nissan_x_trail_2017.dbc @@ -0,0 +1,69 @@ +CM_ "IMPORT _nissan_common.dbc"; + +BO_ 348 GAS_PEDAL: 8 XXX + SG_ GAS_PEDAL_RAW : 26|11@0+ (1,0) [0|2047] "" XXX + SG_ GAS_PEDAL : 47|10@0+ (1,0) [0|1023] "" XXX + +BO_ 438 PRO_PILOT: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X03 : 33|2@0+ (1,0) [0|15] "" XXX + SG_ CRUISE_ACTIVATED : 38|1@0+ (1,0) [0|3] "" XXX + SG_ CRUISE_ON : 36|1@0+ (1,0) [0|255] "" XXX + SG_ STEER_STATUS : 51|1@0+ (1,0) [0|3] "" XXX + +BO_ 523 CRUISE_THROTTLE: 6 XXX + SG_ PROPILOT_BUTTON : 8|1@0+ (1,0) [0|1] "" XXX + SG_ CANCEL_BUTTON : 9|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_PEDAL_INVERTED : 37|10@0+ (1,0) [0|1023] "" XXX + SG_ SET_BUTTON : 11|1@0+ (1,0) [0|1] "" XXX + SG_ RES_BUTTON : 12|1@0+ (1,0) [0|1] "" XXX + SG_ FOLLOW_DISTANCE_BUTTON : 10|1@0+ (1,0) [0|1] "" XXX + SG_ NO_BUTTON_PRESSED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_PEDAL : 31|10@0+ (1,0) [0|255] "" XXX + SG_ USER_BRAKE_PRESSED : 21|1@0+ (1,0) [0|1] "" XXX + SG_ USER_BRAKE_PRESSED_INVERTED : 22|1@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_PRESSED_INVERTED : 20|1@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 17|2@0+ (1,0) [0|3] "" XXX + SG_ unsure1 : 7|10@0+ (1,0) [0|1023] "" XXX + SG_ unsure2 : 43|4@0+ (1,0) [0|1] "" XXX + SG_ unsure3 : 19|2@0+ (1,0) [0|3] "" XXX + +BO_ 665 ESP: 8 XXX + SG_ ESP_DISABLED : 24|1@0+ (1,0) [0|1] "" XXX + +BO_ 666 WHEEL_SPEEDS_FRONT: 8 XXX + SG_ WHEEL_SPEED_FR : 7|16@0+ (0.005,0) [0|65535] "KPH" XXX + SG_ WHEEL_SPEED_FL : 23|16@0+ (0.005,0) [0|65535] "KPH" XXX + +BO_ 768 STEER_TORQUE_SENSOR2: 2 XXX + SG_ STEERING_TORQUE : 6|7@0+ (1,0) [0|127] "" XXX + SG_ STEERING_PRESSED : 15|1@0+ (-1,1) [0|7] "" XXX + +BO_ 1055 GEARBOX: 2 XXX + SG_ SPORTS_MODE : 13|1@0+ (1,0) [0|1] "" XXX + SG_ GEAR_SHIFTER : 5|3@0+ (1,0) [0|255] "" XXX + +BO_ 1107 LIGHTS: 8 XXX + SG_ RIGHT_BLINKER : 12|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_BLINKER : 11|1@0+ (1,0) [0|1] "" XXX + SG_ HEADLIGHTS : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 1108 DOORS_LIGHTS: 8 XXX + SG_ DOOR_CLOSED_RR : 40|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 41|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_RL : 42|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 43|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_FL : 44|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FL : 45|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_FR : 46|1@0+ (1,0) [0|3] "" XXX + SG_ DOOR_OPEN_FR : 47|1@0+ (1,0) [0|3] "" XXX + SG_ BOOT_OPEN : 55|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_LIGHT : 54|1@0+ (1,0) [0|1] "" XXX + SG_ USER_BRAKE_PRESSED : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 1273 HUD: 7 XXX + SG_ SEATBELT_DRIVER_LATCHED : 25|1@0+ (1,0) [0|1] "" XXX + SG_ SPEED_MPH : 5|1@0+ (1,0) [0|1] "" XXX + +VAL_ 1055 GEAR_SHIFTER 6 "L" 4 "D" 3 "N" 2 "R" 1 "P" ; diff --git a/opendbc_repo/opendbc/dbc/generator/rivian/.gitignore b/opendbc_repo/opendbc/dbc/generator/rivian/.gitignore new file mode 100644 index 0000000000..c6687b3e56 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/rivian/.gitignore @@ -0,0 +1 @@ +rivian_mando_front_radar.dbc \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/generator/rivian/rivian_mando_front_radar.py b/opendbc_repo/opendbc/dbc/generator/rivian/rivian_mando_front_radar.py new file mode 100755 index 0000000000..cdddfd8f28 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/rivian/rivian_mando_front_radar.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +import os + +if __name__ == "__main__": + dbc_name = os.path.basename(__file__).replace(".py", ".dbc") + rivian_path = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(rivian_path, dbc_name), "w", encoding='utf-8') as f: + f.write(""" +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + """) + + # note: 0x501/0x502 seem to be special in 0x5XX range + for a in range(0x500, 0x500 + 32): + f.write(f""" +BO_ {a} RADAR_TRACK_{a:x}: 8 RADAR + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 11|4@0+ (1,0) [0|15] "" XXX + SG_ UNKNOWN_1 : 23|8@0- (1,0) [-128|127] "" XXX + SG_ AZIMUTH : 28|10@0- (0.1,0) [-61.2|62.1] "" XXX + SG_ STATE : 31|3@0+ (1,0) [0|7] "" XXX + SG_ LONG_DIST : 34|11@0+ (0.1,0) [0|204.7] "" XXX + SG_ STATE_2 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 53|14@0- (0.01,0) [-81.92|81.92] "" XXX + """) diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/_subaru_global.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/_subaru_global.dbc new file mode 100644 index 0000000000..69c8361938 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/_subaru_global.dbc @@ -0,0 +1,302 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX X + + +BO_ 2 Steering: 8 XXX + SG_ Steering_Angle : 7|16@0- (0.1,0) [0|65535] "" XXX + SG_ COUNTER : 25|3@1+ (1,0) [0|7] "" XXX + SG_ CHECKSUM : 32|8@1+ (1,0) [0|255] "" XXX + +BO_ 64 Throttle: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Engine_RPM : 16|12@1+ (1,0) [0|4095] "" XXX + SG_ Signal2 : 28|4@1+ (1,0) [0|15] "" XXX + SG_ Throttle_Pedal : 32|8@1+ (1,0) [0|255] "" XXX + SG_ Throttle_Cruise : 40|8@1+ (1,0) [0|255] "" XXX + SG_ Throttle_Combo : 48|8@1+ (1,0) [0|255] "" XXX + SG_ Signal3 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ Off_Accel : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 316 Brake_Status: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|46@1+ (1,0) [0|1] "" XXX + SG_ ES_Brake : 58|1@1+ (1,0) [0|1] "" XXX + SG_ Signal2 : 59|3@1+ (1,0) [0|1] "" XXX + SG_ Brake : 62|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 326 Cruise_Buttons: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|30@1+ (1,0) [0|1073741823] "" XXX + SG_ Main : 42|1@1+ (1,0) [0|1] "" XXX + SG_ Set : 43|1@1+ (1,0) [0|1] "" XXX + SG_ Resume : 44|1@1+ (1,0) [0|1] "" XXX + SG_ Signal2 : 45|19@1+ (1,0) [0|524287] "" XXX + +BO_ 315 G_Sensor: 8 XXX + SG_ Lateral : 48|8@1- (-0.1,0) [0|255] "m/s2" XXX + SG_ Longitudinal : 56|8@1- (-0.1,0) [0|255] "m/s2" XXX + +BO_ 314 Wheel_Speeds: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ FR : 12|13@1+ (0.057,0) [0|255] "kph" XXX + SG_ RR : 25|13@1+ (0.057,0) [0|255] "kph" XXX + SG_ FL : 51|13@1+ (0.057,0) [0|255] "kph" XXX + SG_ RL : 38|13@1+ (0.057,0) [0|255] "kph" XXX + +BO_ 280 Steering_Torque_2: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Steer_Torque_Output : 13|11@1- (-10,0) [0|255] "" XXX + SG_ Signal1 : 24|8@1+ (1,0) [0|511] "" XXX + SG_ Steer_Torque_Sensor : 45|11@1- (-1,0) [0|255] "" XXX + SG_ Steering_Active : 61|1@0+ (1,0) [0|1] "" XXX + SG_ Steering_Disabled : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 281 Steering_Torque: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Steer_Error_1 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ Steer_Torque_Sensor : 16|11@1- (-1,0) [-1000|1000] "" XXX + SG_ Steer_Error_2 : 28|1@1+ (1,0) [0|1] "" XXX + SG_ Steer_Warning : 29|1@1+ (1,0) [0|1] "" XXX + SG_ Steering_Angle : 32|16@1- (-0.0217,0) [-600|600] "" X + SG_ Steer_Torque_Output : 48|11@1- (-10,0) [-1000|1000] "" XXX + +BO_ 282 Steering_2: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|1] "" XXX + SG_ Steering_Angle : 24|17@1- (-0.01,0) [0|1] "" XXX + +BO_ 312 Brake_Pressure_L_R: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Brake_1 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ Brake_2 : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 313 Brake_Pedal: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Speed : 16|12@1+ (0.05625,0) [0|255] "kph" XXX + SG_ Signal2 : 28|6@1+ (1,0) [0|63] "" XXX + SG_ Brake_Lights : 34|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 35|1@1+ (1,0) [0|1] "" XXX + SG_ Brake_Pedal : 36|12@1+ (1,0) [0|4095] "" XXX + SG_ Signal4 : 48|16@1+ (1,0) [0|65535] "" XXX + +BO_ 372 Engine_Stop_Start: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ Counter : 8|4@1+ (1,0) [0|15] "" XXX + SG_ STOP_START_STATE : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 290 ES_LKAS: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ SET_1 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_Output : 16|13@1- (-1,0) [-8191|8191] "" XXX + SG_ LKAS_Request : 29|1@0+ (1,0) [0|1] "" XXX + +BO_ 292 ES_LKAS_ANGLE: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Request : 12|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Output : 40|17@1- (-0.01,0) [0|1] "deg" XXX + SG_ SET_3 : 60|2@1+ (1,0) [0|1] "" XXX + +BO_ 544 ES_Brake: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Brake_Pressure : 16|16@1+ (1,0) [0|65535] "" XXX + SG_ AEB_Status : 32|4@1+ (1,0) [0|15] "" XXX + SG_ Cruise_Brake_Lights : 36|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Brake_Fault : 37|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Brake_Active : 38|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 39|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 40|24@1+ (1,0) [0|16777215] "" XXX + +BO_ 577 Cruise_Status: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Cruise_Set_Speed : 51|12@0+ (1,0) [0|120] "" XXX + SG_ Cruise_On : 54|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 55|1@1+ (1,0) [0|1] "" XXX + +BO_ 552 BSD_RCTA: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ R_ADJACENT : 48|1@1+ (1,0) [0|1] "" XXX + SG_ L_ADJACENT : 49|1@1+ (1,0) [0|1] "" XXX + SG_ R_APPROACHING : 58|1@1+ (1,0) [0|1] "" XXX + SG_ L_APPROACHING : 59|1@1+ (1,0) [0|1] "" XXX + +BO_ 912 Dashlights: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ UNITS : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ICY_ROAD : 32|2@1+ (1,0) [0|3] "" XXX + SG_ SEATBELT_FL : 48|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_BLINKER : 50|1@1+ (1,0) [0|1] "" XXX + SG_ RIGHT_BLINKER : 51|1@1+ (1,0) [0|1] "" XXX + SG_ STOP_START : 54|1@0+ (1,0) [0|1] "" XXX + +BO_ 940 BodyInfo: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ DOOR_OPEN_FL : 32|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 33|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 34|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 35|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_TRUNK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE : 54|1@1+ (1,0) [0|1] "" XXX + SG_ DASH_BTN_LIGHTS : 56|1@0+ (1,0) [0|1] "" XXX + SG_ LOWBEAM : 57|1@1+ (1,0) [0|1] "" XXX + SG_ HIGHBEAM : 58|1@1+ (1,0) [0|1] "" XXX + SG_ FOG_LIGHTS : 60|1@1+ (1,0) [0|1] "" XXX + SG_ WIPERS : 62|1@0+ (1,0) [0|1] "" XXX + +BO_ 801 ES_DashStatus: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ PCB_Off : 12|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Off : 13|1@1+ (1,0) [0|1] "" XXX + SG_ Signal1 : 14|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_State_Msg : 16|4@1+ (1,0) [0|15] "" XXX + SG_ LKAS_State_Msg : 20|3@1+ (1,0) [0|7] "" XXX + SG_ Signal2 : 23|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Soft_Disable : 24|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Status_Msg : 25|2@1+ (1,0) [0|3] "" XXX + SG_ Signal3 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Distance : 28|3@1+ (1,0) [0|7] "" XXX + SG_ Signal4 : 31|1@1+ (1,0) [0|1] "" XXX + SG_ Conventional_Cruise : 32|1@1+ (1,0) [0|1] "" XXX + SG_ Signal5 : 33|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_Disengaged : 35|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 36|1@1+ (1,0) [0|1] "" XXX + SG_ Signal6 : 37|3@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Set_Speed : 40|8@1+ (1,0) [0|255] "" XXX + SG_ Cruise_Fault : 48|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_On : 49|1@1+ (1,0) [0|1] "" XXX + SG_ Display_Own_Car : 50|1@1+ (1,0) [0|1] "" XXX + SG_ Brake_Lights : 51|1@1+ (1,0) [0|1] "" XXX + SG_ Car_Follow : 52|1@1+ (1,0) [0|1] "" XXX + SG_ Signal7 : 53|3@1+ (1,0) [0|1] "" XXX + SG_ Far_Distance : 56|4@1+ (5,0) [0|75] "m" XXX + SG_ Cruise_State : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 802 ES_LKAS_State: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ LKAS_Alert_Msg : 12|3@1+ (1,0) [0|7] "" XXX + SG_ Signal1 : 15|2@1+ (1,0) [0|3] "" XXX + SG_ LKAS_ACTIVE : 17|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Dash_State : 18|2@1+ (1,0) [0|2] "" XXX + SG_ Signal2 : 20|3@1+ (1,0) [0|7] "" XXX + SG_ Backward_Speed_Limit_Menu : 23|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Left_Line_Enable : 24|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Left_Line_Light_Blink : 25|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Right_Line_Enable : 26|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Right_Line_Light_Blink : 27|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Left_Line_Visible : 28|2@1+ (1,0) [0|3] "" XXX + SG_ LKAS_Right_Line_Visible : 30|2@1+ (1,0) [0|3] "" XXX + SG_ LKAS_Alert : 32|5@1+ (1,0) [0|31] "" XXX + SG_ Signal3 : 37|27@1+ (1,0) [0|1] "" XXX + +BO_ 803 ES_Infotainment: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ LKAS_Blue_Lines : 15|4@0+ (1,0) [0|15] "" XXX + SG_ Signal1 : 19|4@0+ (1,0) [0|15] "" XXX + SG_ LKAS_State_Infotainment : 22|3@0+ (1,0) [0|7] "" XXX + SG_ Signal2 : 24|1@0+ (1,0) [0|1] "" XXX + +BO_ 722 AC_State: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ AC_Mode : 37|3@1+ (1,0) [0|1] "" XXX + SG_ AC_ON : 24|2@1+ (1,0) [0|1] "" XXX + +BO_ 1677 Dash_State: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Units : 29|3@1+ (1,0) [0|7] "" XXX + +BO_ 554 ES_HighBeamAssist: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ HBA_Available : 13|1@0+ (1,0) [0|1] "" XXX + +BO_ 805 ES_STATIC_1: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ SET_3 : 23|2@0+ (1,0) [0|3] "" XXX + +BO_ 289 ES_STATIC_2: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ SET_3 : 15|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_Fault : 18|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 64 Throttle_Combo "Throttle Cruise + Pedal"; +CM_ SG_ 313 Brake_Lights "Driver or Cruise Brake on"; +CM_ SG_ 544 Cruise_Brake_Lights "1 = switch on brake lights"; +CM_ SG_ 544 Brake_Pressure "Winds down after cruise disabled. Also can be non-zero when likely preparing for AEB"; +CM_ SG_ 544 Signal3 "Usually goes to 2 if AEB_Status is 4"; +CM_ SG_ 544 AEB_Status "Occasionally is 4 instead of 8 while Brake_Pressure is non-zero, unsure why"; +CM_ SG_ 801 PCB_Off "Pre-Collision Braking off"; +CM_ SG_ 801 Brake_Lights "Driver or Cruise brake on"; +CM_ SG_ 801 Cruise_State "0 = Normal, 1 = Hold+User Brake, 2 = Ready, 3 = Hold"; +CM_ SG_ 801 Far_Distance "1=0-5m, 2=5-10m, 3=10-15m, 4=15-20m, 5=20-25m, 6=25-30m, 7=30-35m, 8=35-40m, 9=40-45m, 10=45-50m, 11=50-55m, 12=55-60m, 13=60-65m, 14=65-70m, 15=75m+"; +CM_ SG_ 801 LKAS_State_Msg "1 = LKAS_Off_Sharp_Curve, 2 = Keep_Hands_On_Steering_wheel_disabled, 3 = LKAS_Off, 4 = LKAS_Off_Too_Slow, 5 = LKAS_Off_Too_Fast"; +CM_ SG_ 801 Cruise_State_Msg "1 = Cruise_Off_Steep_Slope, 2 = Cruise_lvl1_eco, 3 = Cruise_lvl2_comfort, 4 = Cruise_off_empty_reason, 5 = Cruise_off, 6 = Cruise_Unable_to_set, 7 = Cruise_Unable_to_set_brakes_applied, 8 = Eyesight_not_ready, 9 = Cruise_lvl3_standard, 10 = Cruise_lvl4_dynamic, 11 = Cruise_Unable_to_set_steep_slope"; +CM_ SG_ 801 Cruise_Soft_Disable "Eyesight soft disable (eg direct sunlight)"; +CM_ SG_ 801 Cruise_Status_Msg "1 = Disabled_Bad_Visibility, 2 = Disabled_Check_Manual"; +CM_ SG_ 802 LKAS_ACTIVE "Turns on the full LKAS dash display"; +CM_ SG_ 802 LKAS_Alert_Msg "1 = Keep_Hands_On_Wheel, 6 = Pre_Collision_Braking, 7 = Keep_Hands_On_Wheel_Off"; +CM_ SG_ 802 LKAS_Alert "1 = FCW_Cont_Beep, 2 = FCW_Repeated_Beep, 3 = Throttle_Management_Activated_Warning, 4 = Throttle_Management_Activated_Alert, 5 = Pre_Collision_Activated_Alert, 8 = Traffic_Light_Ahead, 9 = Apply_Brake_to_Hold Position, 11 = LDW_Right, 12 = LDW_Left, 13 = Stay_Alert, 14 = Lead_Vehicle_Start_Alert, 18 = Keep_Hands_On_Steering_Alert, 24 = Audio_Beep, 25 = Audio_Lead_Car_Change, 26 = Audio_ACC_Disengaged, 27 = Audio_LKAS_disabled, 28 = Audio_Ding_Ding, 30 = Audio_Repeated_Beep"; +CM_ SG_ 802 LKAS_Left_Line_Visible "0 = Off, 1 = White, 2 = Green, 3 = Orange"; +CM_ SG_ 802 LKAS_Dash_State "0 = Off, 1 = Ready, 2 = Active"; +CM_ SG_ 802 LKAS_Right_Line_Visible "0 = Off, 1 = White, 2 = Green, 3 = Orange"; +CM_ SG_ 912 UNITS "0 = Metric, 1 = Imperial"; +CM_ SG_ 912 ICY_ROAD "1 = DASHLIGHT ON, 2 = WARNING, 3 = OFF"; +VAL_ 544 AEB_Status 12 "AEB related" 8 "AEB actuation" 4 "AEB related" 0 "No AEB actuation"; diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/_subaru_preglobal_2015.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/_subaru_preglobal_2015.dbc new file mode 100644 index 0000000000..68481791fb --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/_subaru_preglobal_2015.dbc @@ -0,0 +1,245 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX X + + +BO_ 2 Steering: 8 XXX + SG_ Steering_Angle : 7|16@0- (0.1,0) [-500|500] "degree" XXX + SG_ COUNTER : 27|3@0+ (1,0) [0|7] "" XXX + SG_ Checksum : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 208 G_Sensor: 8 XXX + SG_ Steering_Angle : 0|16@1- (-0.1,0) [-500|500] "" XXX + SG_ Lateral : 16|16@1- (-0.0035,1) [-255|255] "" XXX + SG_ Longitudinal : 48|16@1- (-0.00035,0) [-255|255] "" XXX + +BO_ 209 Brake_Pedal: 4 XXX + SG_ Speed : 0|16@1+ (0.05625,0) [0|255] "KPH" XXX + SG_ Brake_Pedal : 16|8@1+ (1,0) [0|255] "" XXX + +BO_ 210 Brake_2: 8 XXX + SG_ Brake_Light : 35|1@1+ (1,0) [0|1] "" XXX + SG_ Brake_Related : 36|1@1+ (1,0) [0|1] "" XXX + SG_ Right_Brake : 48|8@1+ (1,0) [0|255] "" XXX + SG_ Left_Brake : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 211 Brake_Type: 8 XXX + SG_ Brake_Light : 21|1@1+ (1,0) [0|1] "" XXX + SG_ Speed_Counter : 32|8@1+ (1,0) [0|255] "" XXX + SG_ Brake_Cruise_On : 42|1@1+ (1,0) [0|1] "" XXX + SG_ Brake_Pedal_On : 46|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 48|8@1+ (1,0) [0|255] "" XXX + +BO_ 212 Wheel_Speeds: 8 XXX + SG_ FL : 0|16@1+ (0.0592,0) [0|255] "KPH" XXX + SG_ FR : 16|16@1+ (0.0592,0) [0|255] "KPH" XXX + SG_ RL : 32|16@1+ (0.0592,0) [0|255] "KPH" XXX + SG_ RR : 48|16@1+ (0.0592,0) [0|255] "KPH" XXX + +BO_ 320 Throttle: 8 XXX + SG_ Throttle_Pedal : 0|8@1+ (0.392157,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|2@1+ (1,0) [0|7] "" XXX + SG_ Not_Full_Throttle : 14|1@1+ (1,0) [0|1] "" XXX + SG_ Signal2 : 15|1@1+ (1,0) [0|1] "" XXX + SG_ Engine_RPM : 16|14@1+ (1,0) [0|32767] "" XXX + SG_ Off_Throttle : 30|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 31|1@1+ (1,0) [0|1] "" XXX + SG_ Throttle_Cruise : 32|8@1+ (1,0) [0|255] "" XXX + SG_ Throttle_Combo : 40|8@1+ (1,0) [0|255] "" XXX + SG_ Throttle_Body : 48|8@1+ (1,0) [0|255] "" XXX + SG_ Off_Throttle_2 : 56|1@1+ (1,0) [0|1] "" XXX + SG_ Signal4 : 57|7@1+ (1,0) [0|127] "" XXX + +BO_ 321 Engine: 8 XXX + SG_ Engine_Torque : 0|15@1+ (1,0) [0|255] "" XXX + SG_ Engine_Stop : 15|1@1+ (1,0) [0|1] "" XXX + SG_ Wheel_Torque : 16|12@1+ (1,0) [0|4095] "" XXX + SG_ Engine_RPM : 32|12@1+ (1,0) [0|8191] "" XXX + +BO_ 324 CruiseControl: 8 XXX + SG_ OnOffButton : 2|1@1+ (1,0) [0|1] "" XXX + SG_ SET_BUTTON : 3|1@1+ (1,0) [0|1] "" XXX + SG_ RES_BUTTON : 4|1@1+ (1,0) [0|1] "" XXX + SG_ Button : 13|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_On : 48|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 49|1@1+ (1,0) [0|1] "" XXX + SG_ Brake_Pedal_On : 51|1@1+ (1,0) [0|1] "" XXX + +BO_ 328 Transmission: 8 XXX + SG_ Manual_Gear : 4|4@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Transmission_Engine : 16|15@1+ (1,0) [0|65535] "" XXX + SG_ Gear : 48|4@1+ (1,0) [0|15] "" XXX + SG_ Gear_2 : 52|4@1+ (1,0) [0|15] "" XXX + SG_ Paddle_Shift : 60|2@1+ (1,0) [0|3] "" XXX + +BO_ 329 CVT_Ratio: 8 XXX + +BO_ 336 Brake_Pressure: 8 XXX + SG_ Brake_Pressure_Right : 0|8@1+ (1,0) [0|255] "" XXX + SG_ Brake_Pressure_Left : 8|8@1+ (1,0) [0|255] "" XXX + +BO_ 338 Stalk: 8 XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Brake_Light : 52|1@1+ (1,0) [0|1] "" XXX + SG_ Runlights : 58|1@1+ (1,0) [0|1] "" XXX + SG_ Headlights : 59|1@1+ (1,0) [0|1] "" XXX + SG_ Highbeam : 60|1@1+ (1,0) [0|1] "" XXX + SG_ Wiper : 62|1@1+ (1,0) [0|1] "" XXX + +BO_ 352 ES_Brake: 8 XXX + SG_ Brake_Pressure : 0|16@1+ (1,0) [0|255] "" XXX + SG_ Cruise_Brake_Lights : 20|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Fault : 21|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Brake_Active : 22|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 23|1@1+ (1,0) [0|1] "" XXX + SG_ SET_1 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 48|3@1+ (1,0) [0|7] "" XXX + SG_ Checksum : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 353 ES_Distance: 8 XXX + SG_ Cruise_Throttle : 0|12@1+ (1,0) [0|4095] "" XXX + SG_ Signal1 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Car_Follow : 16|1@1+ (1,0) [0|1] "" XXX + SG_ Signal2 : 17|3@1+ (1,0) [0|7] "" XXX + SG_ Cruise_Brake_Active : 20|1@1+ (1,0) [0|1] "" XXX + SG_ Distance_Swap : 21|1@1+ (1,0) [0|1] "" XXX + SG_ Standstill : 22|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 23|1@1+ (1,0) [0|1] "" XXX + SG_ Close_Distance : 24|8@1+ (0.019607,0) [0|5] "m" XXX + SG_ Signal4 : 32|9@1+ (1,0) [0|255] "" XXX + SG_ Standstill_2 : 41|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Fault : 42|1@1+ (1,0) [0|1] "" XXX + SG_ Signal5 : 43|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 44|3@1+ (1,0) [0|7] "" XXX + SG_ Signal6 : 47|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Button : 48|3@1+ (1,0) [0|7] "" XXX + SG_ Signal7 : 51|5@1+ (1,0) [0|31] "" XXX + SG_ Checksum : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 354 ES_Status: 8 XXX + SG_ Brake : 8|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 9|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_RPM : 16|16@1+ (1,0) [0|65535] "" XXX + SG_ Checksum : 32|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 48|3@1+ (1,0) [0|7] "" XXX + +BO_ 356 ES_LKAS: 8 XXX + SG_ COUNTER : 0|3@1+ (1,0) [0|7] "" XXX + SG_ LKAS_Command : 8|13@1- (-1,0) [-4096|4096] "" XXX + SG_ LKAS_Active : 24|1@1+ (1,0) [0|1] "" XXX + SG_ Checksum : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 359 ES_LDW: 8 XXX + SG_ All_depart_2015 : 0|1@1+ (1,0) [0|1] "" XXX + SG_ Right_Line_2017 : 24|1@1+ (1,0) [0|1] "" XXX + SG_ Left_Line_2017 : 25|1@1+ (1,0) [0|1] "" XXX + SG_ Sig1All_Depart : 28|1@1+ (1,0) [0|1] "" XXX + SG_ Sig2All_Depart : 31|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Inactive_2017 : 36|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_Active : 37|1@1+ (1,0) [0|1] "" XXX + SG_ Sig1Right_Depart : 48|1@1+ (1,0) [0|1] "" XXX + SG_ Sig1Right_Depart_Front : 49|1@1+ (1,0) [0|1] "" XXX + SG_ Sig2Right_Depart : 50|1@1+ (1,0) [0|1] "" XXX + SG_ Left_Depart_Front : 51|1@1+ (1,0) [0|1] "" XXX + SG_ Sig3All_Depart : 52|1@1+ (1,0) [0|1] "" XXX + +BO_ 604 BSD_RCTA: 8 XXX + SG_ COUNTER : 0|3@1+ (1,0) [0|7] "" XXX + SG_ State : 5|1@1+ (1,0) [0|1] "" XXX + SG_ R_ADJACENT : 32|1@1+ (1,0) [0|1] "" XXX + SG_ L_ADJACENT : 33|1@1+ (1,0) [0|1] "" XXX + SG_ R_APPROACHING : 42|1@1+ (1,0) [0|1] "" XXX + SG_ L_APPROACHING : 43|1@1+ (1,0) [0|1] "" XXX + SG_ R_RCTA : 46|1@1+ (1,0) [0|1] "" XXX + SG_ L_RCTA : 47|1@1+ (1,0) [0|1] "" XXX + +BO_ 642 Dashlights: 8 XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|15] "" XXX + SG_ SEATBELT_FL : 40|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_BLINKER : 44|1@1+ (1,0) [0|1] "" XXX + SG_ RIGHT_BLINKER : 45|1@1+ (1,0) [0|1] "" XXX + +BO_ 880 Steering_Torque_2: 8 XXX + SG_ Steering_Voltage_Flat : 0|8@1+ (1,0) [0|255] "" XXX + SG_ Steer_Torque_Sensor : 29|11@1- (-1,0) [-1000|1000] "" XXX + SG_ COUNTER : 40|4@1+ (1,0) [0|15] "" XXX + +BO_ 884 BodyInfo: 8 XXX + SG_ DOOR_OPEN_FR : 24|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FL : 25|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 26|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 27|1@1+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_Hatch : 28|1@1+ (1,0) [0|1] "" XXX + +BO_ 864 Engine_Temp: 8 XXX + SG_ Oil_Temp : 16|8@1+ (1,-40) [0|255] "" XXX + SG_ Coolant_Temp : 24|8@1+ (1,-40) [0|255] "" XXX + SG_ Cruise_Activated : 45|1@1+ (1,0) [0|1] "" XXX + SG_ Saved_Speed : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 866 Fuel: 8 XXX + +BO_ 977 Dash_State2: 8 XXX + SG_ UNITS : 15|1@1+ (1,0) [0|1] "" XXX + +BO_ 1745 Dash_State: 8 XXX + SG_ Units : 15|1@1+ (1,0) [0|1] "" XXX + +CM_ SG_ 320 Off_Throttle_2 "Less sensitive"; +CM_ SG_ 320 Throttle_Body "Throttle related"; +CM_ SG_ 328 Gear "15 = P, 14 = R, 0 = N, 1-6=gear"; +CM_ SG_ 328 Gear_2 "15 = P, 14 = R, 0 = N, 1-6=gear"; +CM_ SG_ 353 Cruise_Button "1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 resume deep"; +CM_ SG_ 354 RPM "20hz version of Transmission_Engine under Transmission"; +CM_ SG_ 359 Sig1Right_Depart "right depart, hill steep and seatbelt disengage"; +CM_ SG_ 359 LKAS_Inactive_2017 "1 when not steering, 0 when lkas steering"; +CM_ SG_ 359 Sig1Right_Depart_Front "object in front, right depart, hill steep and seatbelt disengage alert "; +CM_ SG_ 359 Left_Depart_Front "warning after acceleration into car in front and left depart"; +CM_ SG_ 359 Sig1All_Depart "Left and right depart"; +CM_ SG_ 359 Sig2All_Depart "Left and right depart"; +CM_ SG_ 359 All_depart_2015 "always 1 on 2017"; +CM_ SG_ 604 R_APPROACHING "Faster car approaching in far right lane"; +CM_ SG_ 604 L_APPROACHING "Faster car approaching in far left lane"; +CM_ SG_ 604 R_RCTA "Rear cross traffic alert, only when in R gear"; +CM_ SG_ 604 L_RCTA "Rear cross traffic alert, only when in R gear"; +CM_ SG_ 642 COUNTER "Affected by signals"; +CM_ SG_ 642 SEATBELT_FL "Driver seatbelt"; +CM_ SG_ 880 Steering_Voltage_Flat "receives later than 371"; +CM_ SG_ 977 UNITS "0 = Metric, 1 = Imperial"; + +VAL_ 328 Gear 0 "N" 1 "D" 2 "D" 3 "D" 4 "D" 5 "D" 6 "D" 14 "R" 15 "P"; diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/subaru_forester_2017.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_forester_2017.dbc new file mode 100644 index 0000000000..6d5d46bc9a --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_forester_2017.dbc @@ -0,0 +1,18 @@ +CM_ "IMPORT _subaru_preglobal_2015.dbc"; + +BO_ 355 ES_DashStatus: 8 XXX + SG_ Not_Ready_Startup : 4|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_On : 16|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 17|1@0+ (1,0) [0|1] "" XXX + SG_ Cruise_Set_Speed : 24|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 40|3@1+ (1,0) [0|7] "" XXX + SG_ Brake : 43|1@1+ (1,0) [0|1] "" XXX + SG_ Car_Follow : 54|1@1+ (1,0) [0|1] "" XXX + SG_ Far_Distance : 56|4@1+ (5,0) [0|75] "m" XXX + +BO_ 881 Steering_Torque: 8 XXX + SG_ Steering_Motor_Flat : 0|10@1+ (32,0) [0|1000] "" XXX + SG_ Steer_Torque_Output : 16|11@1- (-32,0) [-1000|1000] "" XXX + SG_ Steer_Error_1 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Steer_Torque_Sensor : 29|11@1- (-1,0) [-1000|1000] "" XXX + SG_ Steering_Angle : 40|16@1- (-0.033,0) [-600|600] "" XXX diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/subaru_global_2017.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_global_2017.dbc new file mode 100644 index 0000000000..83a36ff8f7 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_global_2017.dbc @@ -0,0 +1,65 @@ +CM_ "IMPORT _subaru_global.dbc"; + +BO_ 72 Transmission: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Gear : 24|8@1+ (1,0) [0|255] "" XXX + SG_ RPM : 40|15@1+ (1,0) [0|65535] "" XXX + +BO_ 73 CVT: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ CVT_Gear : 24|8@1+ (1,0) [0|255] "" XXX + +BO_ 545 ES_Distance: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|3@1+ (1,0) [0|7] "" XXX + SG_ Cruise_Fault : 15|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Throttle : 16|13@1+ (1,0) [0|4095] "" XXX + SG_ Signal2 : 29|3@1+ (1,0) [0|15] "" XXX + SG_ Car_Follow : 32|1@1+ (1,0) [0|1] "" XXX + SG_ Low_Speed_Follow : 33|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Soft_Disable : 34|1@1+ (1,0) [0|1] "" XXX + SG_ Signal7 : 35|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Brake_Active : 36|1@1+ (1,0) [0|1] "" XXX + SG_ Distance_Swap : 37|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_EPB : 38|1@1+ (1,0) [0|1] "" XXX + SG_ Signal4 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ Close_Distance : 40|8@1+ (0.019607,0) [0|5] "m" XXX + SG_ Signal5 : 48|8@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Cancel : 56|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Set : 57|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Resume : 58|1@1+ (1,0) [0|1] "" XXX + SG_ Signal6 : 59|5@1+ (1,0) [0|1] "" XXX + +BO_ 546 ES_Status: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|3@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Fault : 15|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_RPM : 16|13@1+ (1,0) [0|4095] "" XXX + SG_ Cruise_Activated : 29|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_Lights : 30|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Hold : 31|1@1+ (1,0) [0|1] "" XXX + SG_ Signal3 : 32|32@1+ (1,0) [0|1] "" XXX + +BO_ 576 CruiseControl: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Signal1 : 12|28@1+ (1,0) [0|268435455] "" XXX + SG_ Cruise_On : 40|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 41|1@1+ (1,0) [0|1] "" XXX + SG_ Signal2 : 42|22@1+ (1,0) [0|4194303] "" XXX + +CM_ SG_ 545 Cruise_Throttle "RPM-like output signal"; +CM_ SG_ 545 Cruise_EPB "1 = Electric Parking Brake set"; +CM_ SG_ 545 Distance_Swap "Switch from Close to Far distance"; +CM_ SG_ 545 Cruise_Soft_Disable "Eyesight Temporary disable, sets CruiseControl Activated = 0"; +CM_ SG_ 546 Cruise_RPM "ES RPM output for ECM and TCM"; +CM_ SG_ 546 Signal3 "0 when cruise_activated = 1"; +CM_ SG_ 803 Signal1 "Seems to be static, set only on some cars"; +CM_ SG_ 803 Signal2 "Seems to be static, set only on some cars"; +VAL_ 803 LKAS_Blue_Lines 0 "no modifier" 2 "changes lines to blue"; +VAL_ 803 LKAS_State_Infotainment 0 "none" 2 "Obstacle Detected" 3 "Keep Hands On Wheel" 4 "Keep Hands On Wheel Off"; +VAL_ 72 Gear 2 "N" 3 "R" 4 "P" 121 "D" 137 "1" 145 "2" 153 "3" 161 "4" 169 "5" 177 "6"; diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/subaru_global_2020_hybrid.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_global_2020_hybrid.dbc new file mode 100644 index 0000000000..a4dbe9c37d --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_global_2020_hybrid.dbc @@ -0,0 +1,18 @@ +CM_ "IMPORT _subaru_global.dbc"; + +BO_ 39 Cruise_Status_2: 8 XXX + SG_ Cruise_Activated : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 295 Transmission: 8 XXX + SG_ Gear : 44|4@1+ (1,0) [0|15] "" XXX + +BO_ 360 Throttle_Hybrid: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Throttle_Pedal : 32|8@1+ (1,0) [0|255] "" XXX + +BO_ 550 Brake_Hybrid: 8 XXX + SG_ Brake_Pedal : 24|8@1+ (1,0) [0|1] "" XXX + SG_ Brake : 37|1@1+ (1,0) [0|1] "" XXX + +VAL_ 295 Gear 0 "P" 1 "R" 3 "D"; diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/subaru_outback_2015.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_outback_2015.dbc new file mode 100644 index 0000000000..cc1fa16d19 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_outback_2015.dbc @@ -0,0 +1,30 @@ +CM_ "IMPORT _subaru_preglobal_2015.dbc"; + +BO_ 358 ES_DashStatus: 8 XXX + SG_ Not_Ready_Startup : 0|3@1+ (1,0) [0|7] "" XXX + SG_ Seatbelt_Disengage : 12|2@1+ (1,0) [0|3] "" XXX + SG_ Disengage_Alert : 14|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_On : 16|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 17|1@1+ (1,0) [0|1] "" XXX + SG_ Signal1 : 18|1@1+ (1,0) [0|1] "" XXX + SG_ WHEELS_MOVING_2015 : 19|1@1+ (1,0) [0|1] "" XXX + SG_ Driver_Input : 20|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Distance : 21|3@1+ (1,0) [0|7] "" XXX + SG_ Cruise_Set_Speed : 24|8@1+ (1,0) [0|255] "" XXX + SG_ Cruise_Fault : 32|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_On_2 : 34|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 37|3@1+ (1,0) [0|7] "" XXX + SG_ Steep_Hill_Disengage : 44|1@1+ (1,0) [0|3] "" XXX + SG_ Car_Follow : 46|1@1+ (1,0) [0|1] "" XXX + SG_ Far_Distance : 48|4@1+ (5,0) [0|75] "m" XXX + +BO_ 881 Steering_Torque: 8 XXX + SG_ Steering_Motor_Flat : 0|10@1+ (32,0) [0|1000] "" XXX + SG_ Steer_Torque_Output : 16|11@1- (-32,0) [-1000|1000] "" XXX + SG_ Steer_Error_1 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Steer_Torque_Sensor : 29|11@1- (1,0) [-1000|1000] "" XXX + SG_ Steering_Angle : 40|16@1- (-0.033,0) [-600|600] "" XXX + +CM_ SG_ 358 Disengage_Alert "seatbelt and steep hill disengage"; +CM_ SG_ 358 Cruise_Fault "No engagement until restart"; +CM_ SG_ 358 Car_Follow "lead car detected"; diff --git a/opendbc_repo/opendbc/dbc/generator/subaru/subaru_outback_2019.dbc b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_outback_2019.dbc new file mode 100644 index 0000000000..d886954cfe --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/subaru/subaru_outback_2019.dbc @@ -0,0 +1,30 @@ +CM_ "IMPORT _subaru_preglobal_2015.dbc"; + +BO_ 358 ES_DashStatus: 8 XXX + SG_ Not_Ready_Startup : 0|3@1+ (1,0) [0|7] "" XXX + SG_ Seatbelt_Disengage : 12|2@1+ (1,0) [0|3] "" XXX + SG_ Disengage_Alert : 14|2@1+ (1,0) [0|3] "" XXX + SG_ Cruise_On : 16|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Activated : 17|1@1+ (1,0) [0|1] "" XXX + SG_ Signal1 : 18|1@1+ (1,0) [0|1] "" XXX + SG_ WHEELS_MOVING_2015 : 19|1@1+ (1,0) [0|1] "" XXX + SG_ Driver_Input : 20|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Distance : 21|3@1+ (1,0) [0|7] "" XXX + SG_ Cruise_Set_Speed : 24|8@1+ (1,0) [0|255] "" XXX + SG_ Cruise_Fault : 32|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_On_2 : 34|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 37|3@1+ (1,0) [0|7] "" XXX + SG_ Steep_Hill_Disengage : 44|1@1+ (1,0) [0|3] "" XXX + SG_ Car_Follow : 46|1@1+ (1,0) [0|1] "" XXX + SG_ Far_Distance : 48|4@1+ (5,0) [0|75] "m" XXX + +BO_ 881 Steering_Torque: 8 XXX + SG_ Steering_Motor_Flat : 0|10@1+ (32,0) [0|1000] "" XXX + SG_ Steer_Torque_Output : 16|11@1- (-32,0) [-1000|1000] "" XXX + SG_ Steer_Error_1 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Steer_Torque_Sensor : 29|11@1- (-1,0) [-1000|1000] "" XXX + SG_ Steering_Angle : 40|16@1- (-0.033,0) [-600|600] "" XXX + +CM_ SG_ 358 Disengage_Alert "seatbelt and steep hill disengage"; +CM_ SG_ 358 Cruise_Fault "No engagement until restart"; +CM_ SG_ 358 Car_Follow "lead car detected"; diff --git a/opendbc_repo/opendbc/dbc/generator/tesla/.gitignore b/opendbc_repo/opendbc/dbc/generator/tesla/.gitignore new file mode 100644 index 0000000000..554aeeaf24 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/tesla/.gitignore @@ -0,0 +1 @@ +*.dbc \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/generator/tesla/_radar_common.py b/opendbc_repo/opendbc/dbc/generator/tesla/_radar_common.py new file mode 100755 index 0000000000..c25f57d3e4 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/tesla/_radar_common.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 + +def get_radar_point_definition(base_id, base_name): + return f""" +BO_ {base_id} {base_name}_A: 8 Radar + SG_ LongDist : 0|12@1+ (0.0625,0) [0|255.9] "meters" Autopilot + SG_ LongSpeed : 12|12@1+ (0.0625,-128) [-128|128] "meters/sec" Autopilot + SG_ LatDist : 24|11@1+ (0.125,-128) [-128|128] "meters" Autopilot + SG_ ProbExist : 35|5@1+ (3.125,0) [0|96.875] "%" Autopilot + SG_ LongAccel : 40|10@1+ (0.03125,-16) [-16|16] "meters/sec/sec" Autopilot + SG_ ProbObstacle : 50|5@1+ (3.125,0) [0|96.875] "%" Autopilot + SG_ Valid : 55|1@1+ (1,0) [0|1] "" Autopilot + SG_ ProbNonObstacle : 56|5@1+ (3.125,0) [0|96.875] "%" Autopilot + SG_ Meas : 61|1@1+ (1,0) [0|1] "" Autopilot + SG_ Tracked : 62|1@1+ (1,0) [0|1] "" Autopilot + SG_ Index : 63|1@1+ (1,0) [0|1] "" Autopilot + +BO_ {base_id+1} {base_name}_B: 8 Radar + SG_ LatSpeed : 0|10@1+ (0.125,-64) [-64|64] "meters/sec" Autopilot + SG_ Length : 10|6@1+ (0.125,0) [0|7.875] "m" Autopilot + SG_ dZ : 16|6@1+ (0.25,-5) [-5|10.75] "m" Autopilot + SG_ MovingState : 22|2@1+ (1,0) [0|3] "" Autopilot + SG_ dxSigma : 24|6@1+ (1,0) [0|63] "" Autopilot + SG_ vxSigma : 30|6@1+ (1,0) [0|63] "" Autopilot + SG_ axSigma : 36|6@1+ (1,0) [0|63] "" Autopilot + SG_ dySigma : 42|6@1+ (1,0) [0|63] "" Autopilot + SG_ ProbClass : 48|5@1+ (3.125,0) [0|96.875] "%" Autopilot + SG_ Class : 53|3@1+ (1,0) [0|7] "" Autopilot + SG_ dxRearEndLoss : 56|6@1+ (1,0) [0|63] "" Autopilot + SG_ NotUsed : 62|1@1+ (1,0) [0|1] "" Autopilot + SG_ Index2 : 63|1@1+ (1,0) [0|1] "" Autopilot +""" + + +def get_val_definition(base_id): + return f""" +VAL_ {base_id+1} MovingState 3 "RADAR_MOVESTATE_STANDING" 2 "RADAR_MOVESTATE_STOPPED" 1 "RADAR_MOVESTATE_MOVING" 0 "RADAR_MOVESTATE_INDETERMINATE" ; +VAL_ {base_id+1} Class 4 "RADAR_CLASS_CONSTRUCTION_ELEMENT" 3 "RADAR_CLASS_MOVING_PEDESTRIAN" 2 "RADAR_CLASS_MOVING_TWO_WHEEL_VEHICLE" 1 \ +"RADAR_CLASS_MOVING_FOUR_WHEEL_VEHICLE" 0 "RADAR_CLASS_UNKNOWN" ;""" \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/generator/tesla/tesla_radar_bosch.py b/opendbc_repo/opendbc/dbc/generator/tesla/tesla_radar_bosch.py new file mode 100755 index 0000000000..6586655ec0 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/tesla/tesla_radar_bosch.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 + +import os +from opendbc.dbc.generator.tesla._radar_common import get_radar_point_definition, get_val_definition + +if __name__ == "__main__": + dbc_name = os.path.basename(__file__).replace(".py", ".dbc") + tesla_path = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(tesla_path, dbc_name), "w", encoding='utf-8') as f: + f.write(""" +VERSION "" + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: Autopilot Radar Diag + + +BO_ 769 TeslaRadarSguInfo: 8 Radar + SG_ RADC_VerticalMisalignment : 0|8@1+ (1,0) [0|255] "" Autopilot + SG_ RADC_SCUTemperature : 8|8@1+ (1,-128) [-128|127] "" Autopilot + SG_ RADC_VMA_Plaus : 16|8@1+ (1,0) [0|255] "" Autopilot + SG_ RADC_SGU_ITC : 24|8@1+ (1,0) [0|255] "" Autopilot + SG_ RADC_HorizontMisalignment : 32|12@1+ (1,0) [0|4096] "" Autopilot + SG_ RADC_SensorDirty : 44|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_HWFail : 45|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_SGUFail : 46|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_SGUInfoConsistBit : 47|1@1+ (1,0) [0|1] "" Autopilot + +BO_ 770 TeslaRadarTguInfo: 8 Radar + SG_ RADC_ACCTargObj1_sguIndex : 0|6@1+ (1,0) [0|63] "" Autopilot + SG_ RADC_ACCTargObj2_sguIndex : 6|6@1+ (1,0) [0|63] "" Autopilot + SG_ RADC_ACCTargObj3_sguIndex : 12|6@1+ (1,0) [0|63] "" Autopilot + SG_ RADC_ACCTargObj4_sguIndex : 18|6@1+ (1,0) [0|63] "" Autopilot + SG_ RADC_ACCTargObj5_sguIndex : 24|6@1+ (1,0) [0|63] "" Autopilot + SG_ unused30 : 30|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_TGUInfoConsistBit : 31|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_ACCTargObj1_dBPower : 32|16@1+ (1,0) [0|65535] "" Autopilot + SG_ RADC_ACCTargObj5_dBPower : 48|16@1+ (1,0) [0|65535] "" Autopilot + +BO_ 1281 TeslaRadarAlertMatrix: 8 Radar + SG_ RADC_a001_ecuInternalPerf : 0|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a002_flashPerformance : 1|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a003_vBatHigh : 2|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a004_adjustmentNotDone : 3|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a005_adjustmentReq : 4|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a006_adjustmentNotOk : 5|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a007_sensorBlinded : 6|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a008_plantModeActive : 7|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a009_configMismatch : 8|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a010_canBusOff : 9|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a011_bdyMIA : 10|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a012_espMIA : 11|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a013_gtwMIA : 12|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a014_sccmMIA : 13|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a015_adasMIA : 14|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a016_bdyInvalidCount : 15|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a017_adasInvalidCount : 16|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a018_espInvalidCount : 17|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a019_sccmInvalidCount : 18|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a020_bdyInvalidChkSm : 19|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a021_espInvalidChkSm : 20|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a022_sccmInvalidChkSm : 21|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a023_sccmInvalidChkSm : 22|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a024_absValidity : 23|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a025_ambTValidity : 24|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a026_brakeValidity : 25|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a027_CntryCdValidity : 26|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a028_espValidity : 27|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a029_longAccOffValidity : 28|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a030_longAccValidity : 29|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a031_odoValidity : 30|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a032_gearValidity : 31|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a033_steerAngValidity : 32|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a034_steerAngSpdValidity : 33|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a035_indctrValidity : 34|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a036_vehStandStillValidity : 35|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a037_vinValidity : 36|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a038_whlRotValidity : 37|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a039_whlSpdValidity : 38|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a040_whlStandStillValidity : 39|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a041_wiperValidity : 40|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a042_xwdValidity : 41|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a043_yawOffValidity : 42|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a044_yawValidity : 43|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a045_bsdSanity : 44|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a046_rctaSanity : 45|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a047_lcwSanity : 46|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a048_steerAngOffSanity : 47|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a049_tireSizeSanity : 48|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a050_velocitySanity : 49|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a051_yawSanity : 50|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a052_radomeHtrInop : 51|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a053_espmodValidity : 52|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a054_gtwmodValidity : 53|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a055_stwmodValidity : 54|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a056_bcmodValidity : 55|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a057_dimodValidity : 56|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a058_opmodValidity : 57|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a059_drmiInvalidChkSm : 58|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a060_drmiInvalidCount : 59|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a061_radPositionMismatch : 60|1@1+ (1,0) [0|1] "" Autopilot + SG_ RADC_a062_strRackMismatch : 61|1@1+ (1,0) [0|1] "" Autopilot + SG_ unused62 : 62|2@1+ (1,0) [0|3] "" Autopilot +""") + + M_RANGE = range(0x310, 0x36D + 1, 3) + for i, base_id in enumerate(M_RANGE): + f.write(get_radar_point_definition(base_id, f"RadarPoint{i}")) + + L_RANGE = range(0x371, 0x37D + 1, 3) + for i, base_id in enumerate(L_RANGE): + f.write(get_radar_point_definition(base_id, f"ProcessedRadarPoint{i+1}")) + + f.write(""" +BO_ 697 VIN_VIP_405HS: 8 Autopilot + SG_ VIN_MuxID M : 0|8@1+ (1,0) [0|0] "" Radar + SG_ VIN_Part1 m16 : 47|24@0+ (1,0) [0|16777215] "" Radar + SG_ VIN_Part2 m17 : 15|56@0+ (1,0) [0|7.2057594038E+16] "" Radar + SG_ VIN_Part3 m18 : 15|56@0+ (1,0) [0|7.2057594038E+16] "" Radar + +BO_ 681 Msg2A9_GTW_carConfig: 8 Autopilot + SG_ Msg2A9_Always0x02 : 48|8@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_Always0x10 : 56|8@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_Always0x16 : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_Always0x41 : 24|8@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_Value1_0x02 : 0|3@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_FourWheelDrive : 3|2@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_Value2_0x02 : 5|3@1+ (1,0) [0|0] "" Radar + SG_ Msg2A9_Always0x43 : 16|8@1+ (1,0) [0|0] "" Radar + +BO_ 409 Msg199_STW_ANGLHP_STAT: 8 Autopilot + SG_ Msg199Always0x04 : 32|8@1+ (1,0) [0|0] "" Radar + SG_ Msg199Always0x20 : 16|8@1+ (1,0) [0|0] "" Radar + SG_ Msg199Always0x2F : 0|8@1+ (1,0) [0|0] "" Radar + SG_ Msg199Always0x67 : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg199Always0xFF : 40|8@1+ (1,0) [0|0] "" Radar + SG_ Msg199Checksum : 56|8@1+ (1,0) [0|0] "" Radar + SG_ Msg199Counter : 52|4@1+ (1,0) [0|0] "" Radar + +BO_ 361 Msg169_ESP_wheelSpeeds: 8 Autopilot + SG_ ESP_wheelSpeedFrL_HS : 0|13@1+ (0.04,0) [0|327.64] "km/h" Radar + SG_ ESP_wheelSpeedFrR_HS : 13|13@1+ (0.04,0) [0|327.64] "km/h" Radar + SG_ ESP_wheelSpeedReL_HS : 26|13@1+ (0.04,0) [0|327.64] "km/h" Radar + SG_ ESP_wheelSpeedReR_HS : 39|13@1+ (0.04,0) [0|327.64] "km/h" Radar + SG_ Msg169Checksum : 56|8@1+ (1,0) [0|0] "" Radar + SG_ Msg169Counter : 52|4@1+ (1,0) [0|0] "" Radar + +BO_ 345 Msg159_ESP_C: 8 Autopilot + SG_ Msg159Always0x3A : 16|8@1+ (1,0) [0|0] "" Radar + SG_ Msg159Always0xA5 : 0|8@1+ (1,0) [0|0] "" Radar + SG_ Msg159Always0xCF : 32|8@1+ (1,0) [0|0] "" Radar + SG_ Msg159Always0xF4 : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg159Counter : 44|4@1+ (1,0) [0|0] "" Radar + SG_ Msg159Checksum : 24|8@1+ (1,0) [0|0] "" Radar + +BO_ 329 Msg149_ESP_145h: 8 Autopilot + SG_ Msg149Always0x02 : 16|8@1+ (1,0) [0|0] "" Radar + SG_ Msg149Always0x04 : 40|8@1+ (1,0) [0|0] "" Radar + SG_ Msg149Always0x26 : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg149Always0x6A : 24|8@1+ (1,0) [0|0] "" Radar + SG_ Msg149Always0xAA : 32|8@1+ (1,0) [0|0] "" Radar + SG_ Msg149Always0xF : 48|4@1+ (1,0) [0|0] "" Radar + SG_ Msg149Checksum : 56|8@1+ (1,0) [0|0] "" Radar + SG_ Msg149Counter : 52|4@1+ (1,0) [0|0] "" Radar + +BO_ 297 Msg129_ESP_115h: 6 Autopilot + SG_ Msg129Always0x20 : 24|8@1+ (1,0) [0|0] "" Radar + SG_ Msg129Checksum : 40|8@1+ (1,0) [0|0] "" Radar + SG_ Msg129Counter : 36|4@1+ (1,0) [0|0] "" Radar + +BO_ 281 Msg119_DI_torque2: 6 Autopilot + SG_ Msg119Always0x11 : 24|8@1+ (1,0) [0|0] "" Radar + SG_ Msg119Always0x1F : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg119Always0x8 : 36|4@1+ (1,0) [0|0] "" Radar + SG_ Msg119Always0xF4 : 16|8@1+ (1,0) [0|0] "" Radar + SG_ Msg119Always0xFF : 0|8@1+ (1,0) [0|0] "" Radar + SG_ Msg119Checksum : 40|8@1+ (1,0) [0|0] "" Radar + SG_ Msg119Counter : 32|4@1+ (1,0) [0|0] "" Radar + +BO_ 265 Msg109_DI_torque1: 8 Autopilot + SG_ Msg109Always0x80 : 24|8@1+ (1,0) [0|0] "" Radar + SG_ Msg109Checksum : 56|8@1+ (1,0) [0|0] "" Radar + SG_ Msg109Counter : 13|3@1+ (1,0) [0|0] "" Radar + +BO_ 521 Msg209_GTW_odo: 8 Autopilot + SG_ Msg209Always0x61 : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg209Always0x94 : 16|8@1+ (1,0) [0|0] "" Radar + SG_ Msg209Always0x52 : 24|8@1+ (1,0) [0|0] "" Radar + SG_ Msg209Always0x13 : 32|8@1+ (1,0) [0|0] "" Radar + SG_ Msg209Always0x03 : 40|8@1+ (1,0) [0|0] "" Radar + SG_ Msg209Always0x80 : 48|8@1+ (1,0) [0|0] "" Radar + +BO_ 537 Msg219_STW_ACTN_RQ: 8 Autopilot + SG_ Msg219Counter : 52|4@1+ (1,0) [0|15] "" Radar + SG_ Msg219CRC : 56|8@1+ (1,0) [0|0] "" Radar + +BO_ 425 Msg1A9_DI_espControl: 5 Autopilot + SG_ Msg1A9Always0x0C : 16|8@1+ (1,0) [0|0] "" Radar + SG_ Msg1A9Counter : 28|4@1+ (1,0) [0|0] "" Radar + SG_ Msg1A9Checksum : 32|8@1+ (1,0) [0|0] "" Radar + +BO_ 729 Msg2D9_BC_status : 8 Autopilot + SG_ Msg2D9Always0x80 : 0|8@1+ (1,0) [0|0] "" Radar + SG_ Msg2D9Always0x40 : 8|8@1+ (1,0) [0|0] "" Radar + SG_ Msg2D9Always0x83 : 16|8@1+ (1,0) [0|0] "" Radar + +BO_ 1601 UDS_radarRequest: 8 Diag + SG_ UDS_radarRequestData : 7|64@0+ (1,0) [0|0] "" Radar + +BO_ 1617 Radar_udsResponse: 8 Radar + SG_ Radar_udsResponseData : 7|64@0+ (1,0) [0|0] "" Diag + +CM_ BO_ 697 "Start with MuxID 0x12, then 0x11 and finally 0x10 (VIN is then transmitted in the reverse order)"; +CM_ BO_ 681 "Message sent every 1000 ms. All fixed bytes, no checksum, the byte for RWD or AWD needs to match VIN config"; +CM_ BO_ 409 "Message sent every 10ms. Checksum : use all first 7 bytes with the SAE J1850 CRC algo"; +CM_ BO_ 361 "Message sent every 10ms. Checksum : Sum of all first 7 bytes + 0x76"; +CM_ BO_ 345 "Message sent every 20ms. Checksum : Sum of all first bytes + 0xc; place checksum in 4th octet"; +CM_ BO_ 329 "Message sent every 20ms. Checksum : Sum of all first 7 bytes + 0x46"; +CM_ BO_ 297 "Message sent every 20ms. Checksum : Sum of all first 5 bytes + 0x16"; +CM_ BO_ 281 "Message sent every 10ms. Checksum : Sum of all first 5 bytes + 0x17"; +CM_ BO_ 265 "Message sent every 10ms. Checksum : Sum of all first 7 bytes + 0x7"; +CM_ BO_ 521 "Message sent every 100ms. All fixed bytes, no checksum."; +CM_ BO_ 537 "Message sent every 100ms. Checksum : use all first 7 bytes with the SAE J1850 CRC algo"; +CM_ BO_ 425 "Message sent every 20ms. Checksum : Sum of all first 4 bytes + 0x38"; +CM_ BO_ 729 "Message sent every 1000ms. All fixed bytes, no checksum."; + +BA_DEF_ "BusType" STRING ; +BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0; +BA_DEF_ SG_ "FieldType" STRING ; + +BA_DEF_DEF_ "BusType" "CAN"; +BA_DEF_DEF_ "FieldType" ""; +BA_DEF_DEF_ "GenMsgCycleTime" 0; + +BA_ "GenMsgCycleTime" BO_ 697 250; +BA_ "GenMsgCycleTime" BO_ 681 1000; +BA_ "GenMsgCycleTime" BO_ 409 10; +BA_ "GenMsgCycleTime" BO_ 361 10; +BA_ "GenMsgCycleTime" BO_ 345 20; +BA_ "GenMsgCycleTime" BO_ 329 20; +BA_ "GenMsgCycleTime" BO_ 297 20; +BA_ "GenMsgCycleTime" BO_ 281 10; +BA_ "GenMsgCycleTime" BO_ 265 10; +BA_ "GenMsgCycleTime" BO_ 521 100; +BA_ "GenMsgCycleTime" BO_ 537 100; +BA_ "GenMsgCycleTime" BO_ 425 20; +BA_ "GenMsgCycleTime" BO_ 729 1000; + +VAL_ 681 Msg2A9_FourWheelDrive 3 "SNA" 2 "UNUSED" 1 "4WD" 0 "2WD" ;""") + + for base_id in list(M_RANGE) + list(L_RANGE): + f.write(get_val_definition(base_id)) diff --git a/opendbc_repo/opendbc/dbc/generator/tesla/tesla_radar_continental.py b/opendbc_repo/opendbc/dbc/generator/tesla/tesla_radar_continental.py new file mode 100755 index 0000000000..36355d4a03 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/tesla/tesla_radar_continental.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 + +import os +from opendbc.dbc.generator.tesla._radar_common import get_radar_point_definition, get_val_definition + +if __name__ == "__main__": + dbc_name = os.path.basename(__file__).replace(".py", ".dbc") + tesla_path = os.path.dirname(os.path.realpath(__file__)) + with open(os.path.join(tesla_path, dbc_name), "w", encoding='utf-8') as f: + f.write(""" +VERSION "" + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: Autopilot Radar Diag + +BO_ 1025 RadarStatus: 8 Radar + SG_ carparkDetected : 29|1@1+ (1,0) [0|1] "" Autopilot + SG_ decreaseBlockage : 25|1@1+ (1,0) [0|1] "" Autopilot + SG_ horizontMisalignment : 8|12@1+ (0.00012207,-0.25) [-0.25|0.249878] "rad" Autopilot + SG_ increaseBlockage : 24|1@1+ (1,0) [0|1] "" Autopilot + SG_ lowPowerMode : 20|2@1+ (1,0) [0|3] "" Autopilot + SG_ powerOnSelfTest : 22|1@1+ (1,0) [0|1] "" Autopilot + SG_ sensorBlocked : 26|1@1+ (1,0) [0|1] "" Autopilot + SG_ sensorInfoConsistBit : 30|1@1+ (1,0) [0|1] "" Autopilot + SG_ sensorReplace : 31|1@1+ (1,0) [0|1] "" Autopilot + SG_ shortTermUnavailable : 23|1@1+ (1,0) [0|1] "" Autopilot + SG_ tunnelDetected : 28|1@1+ (1,0) [0|1] "" Autopilot + SG_ vehDynamicsError : 27|1@1+ (1,0) [0|1] "" Autopilot + SG_ verticalMisalignment : 0|8@1+ (0.00195313,-0.25) [-0.25|0.248047] "rad" Autopilot + +BO_ 1617 Radar_udsResponse: 8 Radar + SG_ Radar_udsResponseData : 7|64@0+ (1,0) [0|1.84467e+19] "" Diag + +BO_ 1601 UDS_radcRequest: 8 Diag + SG_ UDS_radcRequestData : 7|64@0+ (1,0) [0|1.84467e+19] "" Radar +""") + + POINT_RANGE = range(0x410, 0x45E + 1, 2) + for i, base_id in enumerate(POINT_RANGE): + f.write(get_radar_point_definition(base_id, f"RadarPoint{i}")) + + f.write(""" +VAL_ 1025 lowPowerMode 1 "COMMANDED_LOW_POWER" 0 "DEFAULT_LOW_POWER" 2 "NORMAL_POWER" 3 "SNA";""") + + for base_id in list(POINT_RANGE): + f.write(get_val_definition(base_id)) diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/_community.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/_community.dbc new file mode 100644 index 0000000000..58bcfd3be4 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/_community.dbc @@ -0,0 +1,41 @@ +BO_ 359 STEERING_IPAS_COMMA: 8 IPAS + SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX + SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX + SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX + SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00_1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "BO_ STEERING_IPAS_COMMA: Copy of msg 614 so we can do angle control while the Park Assist ECU is connected (Panda spoofs 614 with 359 on connector J70). Note that addresses 0x266 and 0x167 are checksum-invariant"; + +BO_ 512 GAS_COMMAND: 6 EON + SG_ GAS_COMMAND : 7|16@0+ (0.159375,-75.555) [0|1] "" INTERCEPTOR + SG_ GAS_COMMAND2 : 23|16@0+ (0.159375,-151.111) [0|1] "" INTERCEPTOR + SG_ ENABLE : 39|1@0+ (1,0) [0|1] "" INTERCEPTOR + SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" INTERCEPTOR + SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" INTERCEPTOR + +BO_ 513 GAS_SENSOR: 6 INTERCEPTOR + SG_ INTERCEPTOR_GAS : 7|16@0+ (1,0) [0|1] "" EON + SG_ INTERCEPTOR_GAS2 : 23|16@0+ (1,0) [0|1] "" EON + SG_ STATE : 39|4@0+ (1,0) [0|15] "" EON + SG_ COUNTER_PEDAL : 35|4@0+ (1,0) [0|15] "" EON + SG_ CHECKSUM_PEDAL : 47|8@0+ (1,0) [0|255] "" EON + +VAL_ 513 STATE 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ; + +BO_ 35 SECONDARY_STEER_ANGLE: 8 XXX + SG_ ZORRO_STEER : 7|24@0- (0.004901594652,0) [-500|500] "" XXX + +CM_ "BO_ SECONDARY_STEER_ANGLE: ZSS is a high-precision steering angle sensor that can replace the lower resolution sensor in most TSS1 Toyotas. Learn more: https://github.com/commaai/openpilot/wiki/Toyota-Lexus#zorro-steering-sensor-zss"; + +BO_ 767 SDSU: 8 XXX + SG_ FD_BUTTON : 7|1@0+ (1,0) [0|1] "" XXX + SG_ STATE : 23|4@0+ (1,0) [0|15] "" XXX + +CM_ "BO_ SDSU: The sDSU is a modified DSU for use in TSS-P Toyotas. Learn more: https://github.com/RetroPilot/ocelot/tree/main/firmware/smart_dsu"; +CM_ SG_ 767 FD_BUTTON "The follow distance button signal as forwarded by the sdsu"; + +VAL_ 767 STATE 7 "STATE_AEB_CTRL" 6 "FAULT_INVALID" 5 "FAULT_TIMEOUT" 4 "FAULT_STARTUP" 3 "FAULT_SCE" 2 "FAULT_SEND" 1 "FAULT_BAD_CHECKSUM" 0 "NO_FAULT" ; diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/_toyota_2017.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/_toyota_2017.dbc new file mode 100644 index 0000000000..4524b1ea61 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/_toyota_2017.dbc @@ -0,0 +1,560 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX DSU HCU EPS IPAS CGW BGM + +BO_ 36 KINEMATICS: 8 XXX + SG_ ACCEL_Y : 33|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + SG_ YAW_RATE : 1|10@0+ (0.244,-125) [0|65535] "deg/s" XXX + SG_ ACCEL_X : 17|10@0+ (0.03589,-18.375) [0|65535] "m/s^2" XXX + +BO_ 37 STEER_ANGLE_SENSOR: 8 XXX + SG_ STEER_ANGLE : 3|12@0- (1.5,0) [-500|500] "deg" XXX + SG_ STEER_FRACTION : 39|4@0- (0.1,0) [-0.7|0.7] "deg" XXX + SG_ STEER_RATE : 35|12@0- (1,0) [-2000|2000] "deg/s" XXX + +BO_ 119 ENG2F41: 6 CGW + SG_ FDRV : 7|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ FDRVREAL : 23|13@0- (10,0) [0|0] "N" Vector__XXX + SG_ XAECT : 39|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XFDRVCOL : 38|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FDRVSELP : 34|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ ENG2F41S : 47|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 120 ENG2F42: 4 CGW + SG_ FAVLMCHH : 7|16@0- (2,0) [0|0] "N" Vector__XX228X + SG_ CCRNG : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FDRVTYPD : 22|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ GEARHD : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ENG2F42S : 31|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 166 BRAKE: 8 XXX + SG_ BRAKE_AMOUNT : 7|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_FORCE : 23|8@0+ (40,0) [0|10200] "N" XXX + +BO_ 170 WHEEL_SPEEDS: 8 XXX + SG_ WHEEL_SPEED_FR : 7|16@0+ (0.01,-67.67) [0|250] "km/h" XXX + SG_ WHEEL_SPEED_FL : 23|16@0+ (0.01,-67.67) [0|250] "km/h" XXX + SG_ WHEEL_SPEED_RR : 39|16@0+ (0.01,-67.67) [0|250] "km/h" XXX + SG_ WHEEL_SPEED_RL : 55|16@0+ (0.01,-67.67) [0|250] "km/h" XXX + +BO_ 180 SPEED: 8 XXX + SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX + SG_ SPEED : 47|16@0+ (0.01,0) [0|250] "km/h" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 295 GEAR_PACKET_HYBRID: 8 XXX + SG_ FDRVREAL : 26|11@0- (25,0) [-25600|25575] "N" XXX + SG_ UNKNOWN : 55|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ GEAR : 47|4@0+ (1,0) [0|15] "" XXX + +BO_ 353 DSU_SPEED: 7 XXX + SG_ FORWARD_SPEED : 15|16@0- (0.00390625,-30) [0|255] "km/h" XXX + +BO_ 452 ENGINE_RPM: 8 CGW + SG_ RPM : 7|16@0- (0.78125,0) [0|0] "rpm" SCS + SG_ ENGINE_RUNNING : 27|1@0+ (1,0) [0|1] "" XXX + +BO_ 467 PCM_CRUISE_2: 8 XXX + SG_ BRAKE_PRESSED : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PCM_FOLLOW_DISTANCE : 12|2@0+ (1,0) [0|3] "" XXX + SG_ LOW_SPEED_LOCKOUT : 14|2@0+ (1,0) [0|3] "" XXX + SG_ MAIN_ON : 15|1@0+ (1,0) [0|1] "" XXX + SG_ SET_SPEED : 23|8@0+ (1,0) [0|255] "km/h" XXX + SG_ ACC_FAULTED : 47|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 552 VSC1S29: 4 CGW + SG_ ICBACT : 7|1@0+ (1,0) [0|0] "" DS1 + SG_ DVS0PCS : 6|15@0- (0.001,0) [0|0] "m/s^2" DS1 + SG_ SM228 : 31|8@0+ (1,0) [0|0] "" DS1 + +BO_ 560 BRAKE_2: 7 XXX + SG_ BRAKE_PRESSED : 26|1@0+ (1,0) [0|1] "" XXX + +BO_ 581 GAS_PEDAL_HYBRID: 8 XXX + SG_ GAS_PEDAL : 23|8@0+ (0.005,0) [0|1] "" XXX + +BO_ 608 STEER_TORQUE_SENSOR: 8 XXX + SG_ STEER_TORQUE_EPS : 47|16@0- (1,0) [-32768|32767] "" XXX + SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX + SG_ STEER_ANGLE : 31|16@0- (0.0573,0) [-500|500] "" XXX + SG_ STEER_ANGLE_INITIALIZING : 3|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 614 STEERING_IPAS: 8 IPAS + SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX + SG_ ANGLE : 3|12@0- (1.5,0) [-510|510] "deg" XXX + SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX + SG_ SET_ME_X40 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00_1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 742 LEAD_INFO: 8 DSU + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" HCU + SG_ LEAD_REL_SPEED : 23|12@0- (0.025,0) [-100|100] "m/s" HCU + SG_ LEAD_LONG_DIST : 7|13@0+ (0.05,0) [0|300] "m" HCU + +BO_ 800 VSC1S07: 8 CGW + SG_ FBKRLY : 6|1@0+ (1,0) [0|0] "" DS1 + SG_ FVSCM : 4|1@0+ (1,0) [0|0] "" DS1 + SG_ FVSCSFT : 3|1@0+ (1,0) [0|0] "" DS1 + SG_ FABS : 2|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ TSVSC : 1|1@0+ (1,0) [0|0] "" DS1 + SG_ FVSCL : 0|1@0+ (1,0) [0|0] "" DS1 + SG_ RQCSTBKB : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PSBSTBY : 14|1@0+ (1,0) [0|0] "" DS1 + SG_ P2BRXMK : 13|1@0+ (1,0) [0|0] "" DS1 + SG_ MCC : 11|1@0+ (1,0) [0|0] "" DS1 + SG_ RQBKB : 10|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRSTOP : 9|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ BRKON : 8|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ ASLP : 23|8@0- (1,0) [0|0] "deg" DS1 + SG_ BRTYPACC : 31|2@0+ (1,0) [0|0] "" DS1 + SG_ BRKABT3 : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRKABT2 : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRKABT1 : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GVC : 39|8@0- (0.04,0) [0|0] "m/s^2" DS1 + SG_ XGVCINV : 43|1@0+ (1,0) [0|0] "" DS1 + SG_ S07CNT : 52|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSBRSTA : 50|2@0+ (1,0) [0|0] "" DS1 + SG_ VSC07SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 835 ACC_CONTROL: 8 DSU + SG_ ACCEL_CMD : 7|16@0- (0.001,0) [-20|20] "m/s^2" HCU + SG_ ALLOW_LONG_PRESS : 17|2@0+ (1,0) [0|2] "" XXX + SG_ ACC_MALFUNCTION : 18|1@0+ (1,0) [0|0] "" XXX + SG_ RADAR_DIRTY : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DISTANCE : 20|1@0+ (1,0) [0|1] "" XXX + SG_ MINI_CAR : 21|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_TYPE : 23|2@0+ (1,0) [0|3] "" HCU + SG_ CANCEL_REQ : 24|1@0+ (1,0) [0|1] "" HCU + SG_ ACC_CUT_IN : 25|1@0+ (1,0) [0|1] "" XXX + SG_ LEAD_VEHICLE_STOPPED : 29|1@0+ (1,0) [0|0] "" DSU + SG_ PERMIT_BRAKING : 30|1@0+ (1,0) [0|1] "" HCU + SG_ RELEASE_STANDSTILL : 31|1@0+ (1,0) [0|1] "" HCU + SG_ ITS_CONNECT_LEAD : 39|8@0+ (1,0) [0|1] "" Vector__XXX + SG_ ACCEL_CMD_ALT : 47|8@0- (0.05,0) [0|0] "m/s^2" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 865 CLUTCH: 8 XXX + SG_ ACC_FAULTED : 32|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_PEDAL_ALT : 23|8@0+ (0.005,0) [0|1] "" XXX + SG_ CLUTCH_RELEASED : 38|1@0+ (1,0) [0|1] "" XXX + SG_ ACCEL_NET : 48|16@1+ (0.0002,-6.5536) [-6.5536|6.5534] "" XXX + +BO_ 869 DSU_CRUISE : 7 DSU + SG_ RES_BTN : 3|1@0+ (1,0) [0|0] "" XXX + SG_ SET_BTN : 2|1@0+ (1,0) [0|0] "" XXX + SG_ CANCEL_BTN : 1|1@0+ (1,0) [0|0] "" XXX + SG_ MAIN_ON : 0|1@0+ (1,0) [0|0] "" XXX + SG_ SET_SPEED : 15|8@0+ (1,0) [0|0] "km/h" XXX + SG_ CRUISE_REQUEST : 31|8@0+ (100,-12800) [0|0] "N" XXX + SG_ LEAD_DISTANCE : 39|8@0+ (1,0) [0|0] "m" XXX + +BO_ 898 AIR_CONDITIONER: 8 XXX + SG_ CLIMATE_SET_POINT : 5|6@0+ (1,0) [5|33] "" XXX + SG_ AIR_CONDITIONER_STATE : 48|7@1+ (1,0) [0|127] "" XXX + +BO_ 921 PCM_CRUISE_SM: 8 XXX + SG_ MAIN_ON : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_STATE : 11|4@0+ (1,0) [0|15] "" XXX + SG_ DISTANCE_LINES : 14|2@0+ (1,0) [0|3] "" XXX + SG_ TEMP_ACC_FAULTED : 15|1@0+ (1,0) [0|1] "" XXX + SG_ UI_SET_SPEED : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 944 AIR_CONDITIONER_2: 8 XXX + SG_ WINDSCREEN_DEFOG : 43|1@0+ (1,0) [0|1] "" XXX + +BO_ 951 ESP_CONTROL: 8 ESP + SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VSC_DISABLED : 12|2@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_LIGHTS_ACC : 18|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_HOLD_ENABLED : 33|1@1+ (1,0) [0|1] "" XXX + SG_ BRAKE_HOLD_ACTIVE : 36|1@0+ (1,0) [0|1] "" XXX + +BO_ 956 GEAR_PACKET: 8 XXX + SG_ SPORT_ON : 2|1@0+ (1,0) [0|1] "" XXX + SG_ GEAR : 13|6@0+ (1,0) [0|63] "" XXX + SG_ SPORT_GEAR_ON : 33|1@0+ (1,0) [0|1] "" XXX + SG_ SPORT_GEAR : 38|3@0+ (1,0) [0|7] "" XXX + SG_ ECON_ON : 40|1@0+ (1,0) [0|1] "" XXX + SG_ B_GEAR_ENGAGED : 41|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_ENGAGED : 47|1@0+ (1,0) [0|1] "" XXX + +BO_ 1005 REVERSE_CAMERA_STATE: 2 BGM + SG_ REVERSE_CAMERA_GUIDELINES : 9|2@0+ (1,0) [1|3] "" XXX + +BO_ 1009 PCM_CRUISE_ALT: 8 XXX + SG_ PCM_FOLLOW_DISTANCE : 4|2@1+ (1,0) [0|3] "" XXX + SG_ MAIN_ON : 13|1@0+ (1,0) [0|3] "" XXX + SG_ CRUISE_STATE : 10|1@0+ (1,0) [0|1] "" XXX + SG_ UI_SET_SPEED : 23|8@0+ (1,0) [0|255] "mph" XXX + +BO_ 1020 SOLAR_SENSOR: 8 XXX + SG_ LUX_SENSOR : 55|13@0+ (1,0) [0|0] "" XXX + +BO_ 1041 PCS_HUD: 8 DSU + SG_ PCS_INDICATOR : 7|2@0+ (1,0) [0|3] "" XXX + SG_ FCW : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_X20 : 15|8@0+ (1,0) [0|1] "" XXX + SG_ PCS_DUST : 34|1@0+ (1,0) [0|0] "" XXX + SG_ PCS_TEMP : 35|1@0+ (1,0) [0|0] "" XXX + SG_ PCS_DUST2 : 41|1@0+ (1,0) [0|0] "" XXX + SG_ PCS_TEMP2 : 42|1@0+ (1,0) [0|0] "" XXX + SG_ SET_ME_X10 : 39|8@0+ (1,0) [0|1] "" XXX + SG_ PCS_OFF : 40|1@0+ (1,0) [0|0] "" XXX + SG_ FRD_ADJ : 53|3@0+ (1,0) [0|0] "" XXX + SG_ PCS_SENSITIVITY : 55|8@0+ (1,0) [0|1] "" XXX + +BO_ 1042 LKAS_HUD: 8 DSU + SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_LINE : 3|2@0+ (1,0) [0|3] "" XXX + SG_ LEFT_LINE : 5|2@0+ (1,0) [0|3] "" XXX + SG_ LKAS_STATUS : 7|2@0+ (1,0) [0|3] "" XXX + SG_ LDA_ALERT : 9|2@0+ (1,0) [0|3] "" XXX + SG_ LDW_EXIST : 10|1@0+ (1,0) [0|1] "" XXX + SG_ TWO_BEEPS : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ADJUSTING_CAMERA : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_UNAVAILABLE_QUIET : 14|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_MALFUNCTION : 15|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_UNAVAILABLE : 16|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_SENSITIVITY : 18|2@0+ (1,0) [0|3] "" XXX + SG_ LDA_SA_TOGGLE : 20|2@0+ (1,0) [0|3] "" XXX + SG_ LDA_MESSAGES : 23|3@0+ (1,0) [0|1] "" XXX + SG_ LDA_ON_MESSAGE : 31|2@0+ (1,0) [0|3] "" XXX + SG_ REPEATED_BEEPS : 32|1@0+ (1,0) [0|1] "" XXX + SG_ LANE_SWAY_TOGGLE : 43|1@0+ (1,0) [0|1] "" XXX + SG_ LANE_SWAY_SENSITIVITY : 45|2@0+ (1,0) [0|3] "" XXX + SG_ TAKE_CONTROL : 46|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_FRONT_CAMERA_BLOCKED : 47|1@0+ (1,0) [0|1] "" XXX + SG_ LANE_SWAY_BUZZER : 50|2@0+ (1,0) [0|0] "" XXX + SG_ LANE_SWAY_FLD : 53|3@0+ (1,0) [0|7] "" XXX + SG_ LANE_SWAY_WARNING : 55|2@0+ (1,0) [0|3] "" XXX + SG_ SET_ME_X01 : 42|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_X02 : 63|8@0+ (1,0) [0|1] "" XXX + +BO_ 1043 TIME : 8 CGW + SG_ YEAR : 7|8@0+ (1,0) [0|0] "year" XXX + SG_ MONTH : 15|8@0+ (1,0) [0|0] "month" XXX + SG_ DAY : 23|8@0+ (1,0) [0|0] "day" XXX + SG_ HOUR : 31|8@0+ (1,0) [0|0] "hour" XXX + SG_ MINUTE : 39|8@0+ (1,0) [0|0] "minute" XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" XXX + SG_ GMTDIFF_HOURS : 54|4@0+ (1,0) [0|0] "hours" XXX + SG_ GMTDIFF_MINUTES : 50|6@0+ (1,0) [0|0] "minutes" XXX + SG_ SUMMER : 60|1@0+ (1,0) [0|0] "" XXX + +BO_ 1044 AUTO_HIGH_BEAM: 8 FCM + SG_ AHB_DUTY : 47|8@0+ (0.5,0) [0|0] "%" Vector__XXX + SG_ F_AHB : 55|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_AHB : 51|4@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1056 VSC1S08: 8 CGW + SG_ YR1Z : 7|16@0- (1,0) [0|0] "rad/s" DS1,FCM,MAV + SG_ YR2Z : 23|16@0- (1,0) [0|0] "rad/s" DS1,FCM,MAV + SG_ GL1Z : 39|8@0- (0.0359,0) [0|0] "m/s^2" DS1,FCM,KSS,MAV,SCS + SG_ GL2Z : 47|8@0- (0.0359,0) [0|0] "m/s^2" DS1,FCM,KSS,MAV,SCS + SG_ YRGSDIR : 55|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,SCS + SG_ GLZS : 51|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ YRZF : 50|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRZS : 49|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRZKS : 48|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ VSC08SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + +BO_ 1083 AUTOPARK_STATUS: 8 IPAS + SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX + +BO_ 1161 RSA1: 8 FCM + SG_ TSGN1 : 7|8@0+ (1,0) [0|0] "" XXX + SG_ TSGNGRY1 : 12|3@0+ (1,0) [0|0] "" XXX + SG_ TSGNHLT1 : 9|2@0+ (1,0) [0|0] "" XXX + SG_ SPDVAL1 : 23|8@0+ (1,0) [0|0] "km/h" XXX + SG_ SPLSGN1 : 31|4@0+ (1,0) [0|0] "" XXX + SG_ SPLSGN2 : 27|4@0+ (1,0) [0|0] "" XXX + SG_ TSGN2 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ TSGNGRY2 : 44|3@0+ (1,0) [0|0] "" XXX + SG_ TSGNHLT2 : 41|2@0+ (1,0) [0|0] "" XXX + SG_ SPDVAL2 : 55|8@0+ (1,0) [0|0] "" XXX + SG_ BZRRQ_P : 63|2@0+ (1,0) [0|0] "" XXX + SG_ BZRRQ_A : 61|2@0+ (1,0) [0|0] "" XXX + SG_ SYNCID1 : 59|4@0+ (1,0) [0|0] "" XXX + +BO_ 1162 RSA2: 8 FCM + SG_ TSGN3 : 7|8@0+ (1,0) [0|0] "" XXX + SG_ TSGNGRY3 : 12|3@0+ (1,0) [0|0] "" XXX + SG_ TSGNHLT3 : 9|2@0+ (1,0) [0|0] "" XXX + SG_ SPLSGN3 : 31|4@0+ (1,0) [0|0] "" XXX + SG_ SPLSGN4 : 27|4@0+ (1,0) [0|0] "" XXX + SG_ TSGN4 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ TSGNGRY4 : 44|3@0+ (1,0) [0|0] "" XXX + SG_ TSGNHLT4 : 41|2@0+ (1,0) [0|0] "" XXX + SG_ DPSGNREQ : 54|1@0+ (1,0) [0|0] "" XXX + SG_ SGNNUMP : 53|3@0+ (1,0) [0|0] "" XXX + SG_ SGNNUMA : 50|3@0+ (1,0) [0|0] "" XXX + SG_ SPDUNT : 63|2@0+ (1,0) [0|0] "" XXX + SG_ TSRWMSG : 61|2@0+ (1,0) [0|0] "" XXX + SG_ SYNCID2 : 59|4@0+ (1,0) [0|0] "" XXX + +BO_ 1163 RSA3: 8 FCM + SG_ TSREQPD : 7|1@0+ (1,0) [0|0] "" XXX + SG_ TSRMSW : 6|1@0+ (1,0) [0|0] "" XXX + SG_ OTSGNNTM : 5|2@0+ (1,0) [0|0] "" XXX + SG_ NTLVLSPD : 3|2@0+ (1,0) [0|0] "" XXX + SG_ OVSPNTM : 1|2@0+ (1,0) [0|0] "" XXX + SG_ OVSPVALL : 11|4@0+ (1,-5) [0|0] "" XXX + SG_ OVSPVALM : 19|4@0+ (1,-5) [0|0] "" XXX + SG_ OVSPVALH : 27|4@0+ (1,-5) [0|0] "" XXX + SG_ TSRSPU : 33|2@0+ (1,0) [0|0] "" XXX + +BO_ 1408 VIN_PART_1: 8 CGW + SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_3 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_4 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_5 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_6 : 47|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_7 : 55|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_8 : 63|8@0+ (1,0) [0|0] "" XXX + +BO_ 1409 VIN_PART_2: 8 CGW + SG_ VIN_9 : 7|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_10 : 15|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_11 : 23|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_12 : 31|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_13 : 39|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_14 : 47|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_15 : 55|8@0+ (1,0) [0|0] "" XXX + SG_ VIN_16 : 63|8@0+ (1,0) [0|0] "" XXX + +BO_ 1410 VIN_PART_3: 8 CGW + SG_ VIN_17 : 7|8@0+ (1,0) [0|0] "" XXX + +BO_ 1552 BODY_CONTROL_STATE_2: 8 XXX + SG_ UI_SPEED : 23|8@0+ (1,0) [0|255] "" XXX + SG_ METER_SLIDER_BRIGHTNESS_PCT : 30|7@0+ (1,0) [12|100] "%" XXX + SG_ METER_SLIDER_LOW_BRIGHTNESS : 37|1@0+ (1,0) [0|1] "" XXX + SG_ METER_SLIDER_DIMMED : 38|1@0+ (1,0) [0|1] "" XXX + SG_ UNITS : 63|3@0+ (1,0) [1|4] "" XXX + +BO_ 1553 UI_SETTING: 8 XXX + SG_ UNITS : 26|2@0+ (1,0) [0|3] "" XXX + SG_ ODOMETER : 39|32@0+ (1,0) [0|1048575] "" XXX + +BO_ 1556 BLINKERS_STATE: 8 XXX + SG_ BLINKER_BUTTON_PRESSED : 15|1@0+ (1,0) [0|1] "" XXX + SG_ HAZARD_LIGHT : 27|1@0+ (1,0) [0|1] "" XXX + SG_ TURN_SIGNALS : 29|2@0+ (1,0) [0|3] "" XXX + +BO_ 1568 BODY_CONTROL_STATE: 8 XXX + SG_ METER_DIMMED : 38|1@0+ (1,0) [0|1] "" XXX + SG_ PARKING_BRAKE : 60|1@0+ (1,0) [0|1] "" XXX + SG_ SEATBELT_DRIVER_UNLATCHED : 62|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FL : 45|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 42|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 43|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 44|1@0+ (1,0) [0|1] "" XXX + +BO_ 1570 LIGHT_STALK: 8 SCM + SG_ LIGHT_STALK_MOVED : 15|1@0+ (1,0) [0|1] "" XXX + SG_ TAIL_LIGHT : 19|1@0+ (1,0) [0|1] "" XXX + SG_ HEADLIGHT_MODE : 21|3@1+ (1,0) [0|7] "" XXX + SG_ FRONT_FOG : 27|1@0+ (1,0) [0|1] "" XXX + SG_ PARKING_LIGHT : 28|1@0+ (1,0) [0|1] "" XXX + SG_ LOW_BEAM : 29|1@0+ (1,0) [0|1] "" XXX + SG_ HIGH_BEAM : 30|1@0+ (1,0) [0|1] "" XXX + SG_ DAYTIME_RUNNING_LIGHT : 31|1@0+ (1,0) [0|1] "" XXX + SG_ AUTO_HIGH_BEAM : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 1571 CERTIFICATION_ECU: 8 CGW + SG_ DOOR_LOCK_FEEDBACK_LIGHT : 15|1@0+ (1,0) [0|0] "" XXX + SG_ KEYFOB_LOCKING_FEEDBACK_LIGHT : 61|1@0+ (1,0) [0|0] "" XXX + SG_ KEYFOB_UNLOCKING_FEEDBACK_LIGHT : 62|1@0+ (1,0) [0|0] "" XXX + +BO_ 1592 DOOR_LOCKS: 8 XXX + SG_ LOCK_STATUS_CHANGED : 15|1@0+ (1,0) [0|1] "" XXX + SG_ LOCK_STATUS : 20|1@0+ (1,0) [0|1] "" XXX + SG_ LOCKED_VIA_KEYFOB : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 1779 ADAS_TOGGLE_STATE: 8 XXX + SG_ OK_BUTTON_PRESSED : 15|1@0+ (1,0) [0|1] "" BCM + SG_ SWS_TOGGLE_CMD : 24|1@0+ (1,0) [0|1] "" XXX + SG_ SWS_SENSITIVITY_CMD : 26|2@0+ (1,0) [0|3] "" XXX + SG_ LKAS_ON_CMD : 28|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_OFF_CMD : 29|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_SENSITIVITY_HI_CMD : 30|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_SENSITIVITY_STD_CMD : 31|1@0+ (1,0) [0|1] "" XXX + SG_ IPAS_TOGGLE : 34|1@0+ (1,0) [0|1] "" XXX + SG_ BSM_TOGGLE_CMD : 37|1@0+ (1,0) [0|1] "" XXX + SG_ IPAS_SONAR_TOGGLE : 38|1@0+ (1,0) [0|1] "" XXX + SG_ PCS_TOGGLE_CMD : 40|1@0+ (1,0) [0|1] "" XXX + SG_ PCS_SENSITIVITY_CMD : 41|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 36 YAW_RATE "verify"; +CM_ SG_ 36 ACCEL_X "x-axis accel"; +CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set"; +CM_ SG_ 37 STEER_RATE "factor is tbd"; +CM_ SG_ 119 FDRVREAL "ICE only: force applied by wheels from the engine. includes creeping force, regen, and engine braking"; +CM_ SG_ 166 BRAKE_FORCE "hybrid only: force applied by friction brakes from user or ACC command"; +CM_ SG_ 295 FDRVREAL "hybrid only: force applied by wheels from the engine and/or electric motors. includes creeping force, regen, and engine braking"; +CM_ SG_ 467 ACC_FAULTED "1 when ACC is faulted and the PCM disallows engagement"; +CM_ SG_ 467 SET_SPEED "43 km/h are shown as 28 mph, so conversion isn't perfect"; +CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph"; +CM_ SG_ 560 BRAKE_PRESSED "another brake pressed?"; +CM_ SG_ 581 GAS_PEDAL "it seems slightly filtered"; +CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque"; +CM_ SG_ 608 STEER_OVERRIDE "set when driver torque exceeds a certain value"; +CM_ SG_ 614 ANGLE "set to measured angle when ipas control isn't active"; +CM_ SG_ 835 ACC_TYPE "if 2, car is likely to have a permanent low speed lockout. 1 is ok"; +CM_ SG_ 835 RADAR_DIRTY "Display Clean Radar Sensor message on HUD"; +CM_ SG_ 835 ACC_MALFUNCTION "display ACC fault on dash if set to 1"; +CM_ SG_ 835 ACC_CUT_IN "Display blinking yellow lead if set to 1"; +CM_ SG_ 835 DISTANCE "Cycle through ACC following distance from long, mid, short when set to 1"; +CM_ SG_ 835 ITS_CONNECT_LEAD "Displayed when lead car is capable of ITS Connect"; +CM_ SG_ 835 LEAD_VEHICLE_STOPPED "Set to 1 when lead is stopped, likely only used in older TSS-P vehicles"; +CM_ SG_ 835 ALLOW_LONG_PRESS "Enable Toyota's factory set speed increment behaviour, available on both metrics cars and imperial unit cars"; +CM_ SG_ 835 PERMIT_BRAKING "Original ACC has this going high when a car in front is detected. In openpilot and before the PERMIT_BRAKING name, this was 'SET_ME_1' and is hardcoded to be high. Unsure if only informational or has an effect though existing usage in openpilot is to always set it to 1. Originally 'PMTBRKG' in the leaked toyota_2017_ref_pt.dbc file and name expansion speculated to be PerMiT BRaKinG."; +CM_ SG_ 835 ACCEL_CMD_ALT "Copy of main ACCEL_CMD, but across 8 bits instead of 16 bits like ACCEL_CMD. Unsure if only informational or has an effect. Likely informational as existing openpilot sets this to 0 and no loss of functionality observed. Originally 'AT_RAW' in leaked toyota_2017_ref_pt.dbc file."; +CM_ SG_ 865 GAS_PEDAL_ALT "copy of main GAS_PEDAL. Both use 8 bits. Might indicate that this message is for pedals."; +CM_ SG_ 865 CLUTCH_RELEASED "boolean of clutch for 6MT."; +CM_ SG_ 865 ACCEL_NET "net positive acceleration (gas) applied by the system if on flat ground, may not include creeping force"; +CM_ SG_ 865 ACC_FAULTED "1 when ACC is faulted and the PCM disallows engagement. Also describes a lockout when the ACC_CONTROL->ACC_MALFUNCTION bit is set."; +CM_ SG_ 898 AIR_CONDITIONER_STATE "very difficult to parse with some air register motors operating without user-inputs"; +CM_ SG_ 921 UI_SET_SPEED "set speed shown in the vehicle's UI with the vehicle's unit"; +CM_ SG_ 921 TEMP_ACC_FAULTED "1 when the UI is displaying or playing fault-related alerts or sounds. Also 1 when pressing main on."; +CM_ SG_ 951 BRAKE_LIGHTS_ACC "brake lights when ACC commands decel"; +CM_ SG_ 956 GEAR "on 6MT, only R shows."; +CM_ SG_ 1009 UI_SET_SPEED "units seem to be whatever the car is set to"; +CM_ SG_ 1041 PCS_INDICATOR "Pre-Collision System Indicator"; +CM_ SG_ 1041 PCS_SENSITIVITY "Pre-Collision System Sensitivity"; +CM_ SG_ 1041 PCS_DUST "alert: Front Camera Low Visibility Unavailable See Owner's Manual"; +CM_ SG_ 1041 PCS_DUST2 "alert: Pre-Collision System Radar Sensor Blocked Unavailable Clean Radar Sensor"; +CM_ SG_ 1041 PCS_TEMP "alert: Front Camera Out of Temperature Range Unavailable Wait until Normal Temperature"; +CM_ SG_ 1041 PCS_TEMP2 "alert: Pre-Collision System Out of Temperature Range Unavailable See Owner's Manual"; +CM_ SG_ 1041 FRD_ADJ "alert: ERROR ADJUSTING FRONT RADAR BEAM"; +CM_ SG_ 1042 LDA_SA_TOGGLE "LDA Steering Assist Toggle"; +CM_ SG_ 1042 LDW_EXIST "Unclear what this is, it's usually set to 0"; +CM_ SG_ 1042 LDA_SENSITIVITY "LDA Sensitivity"; +CM_ SG_ 1042 LDA_ON_MESSAGE "Display LDA Turned ON message"; +CM_ SG_ 1042 REPEATED_BEEPS "LDA audible warning"; +CM_ SG_ 1042 LDA_UNAVAILABLE_QUIET "LDA toggles and sensitivity settings are greyed out if set to 1"; +CM_ SG_ 1042 LDA_MESSAGES "Various LDA Messages"; +CM_ SG_ 1042 LDA_FRONT_CAMERA_BLOCKED "originally LDAFCVB, LDA related settings are greyed out if set to 1"; +CM_ SG_ 1042 TAKE_CONTROL "Please Control Steering Wheel warning"; +CM_ SG_ 1042 LANE_SWAY_TOGGLE "Lane Sway Warning System SWS Switch"; +CM_ SG_ 1042 LANE_SWAY_WARNING "Lane Sway Warning System Triggered"; +CM_ SG_ 1042 LANE_SWAY_FLD "Unknown signal for Lane Sway Warning System, set to 7 on stock system when SWS is enabled, 0 when SWS is disabled"; +CM_ SG_ 1042 LANE_SWAY_BUZZER "Similar to TWO_BEEPS"; +CM_ SG_ 1042 SET_ME_X01 "empty bit on leaked dbc, always set to 1 during normal operations"; +CM_ SG_ 1042 SET_ME_X02 "empty bit on leaked dbc, always set to 2 during normal operations"; +CM_ SG_ 1083 STATE "when the dashboard button is pressed, the value changes from zero to non-zero"; +CM_ SG_ 1161 SPDVAL1 "Numbers 0-199 is displayed, 200-254 displays circle without number and 255 is for no limit."; +CM_ SG_ 1161 SYNCID1 "counter from 1 to f at 1 Hz"; +CM_ SG_ 1161 SPDVAL2 "conditional speed value 70"; +CM_ SG_ 1162 SGNNUMP "1 if SPDVAL1 is set, otherwise 0"; +CM_ SG_ 1162 SYNCID2 "counter from 1 to f at 1 Hz"; +CM_ SG_ 1163 TSREQPD "always 1"; +CM_ SG_ 1163 TSRMSW "always 1"; +CM_ SG_ 1163 OTSGNNTM "always 3"; +CM_ SG_ 1163 NTLVLSPD "always 3"; +CM_ SG_ 1163 OVSPNTM "always 3"; +CM_ SG_ 1163 OVSPVALL "-5 at start then 2 after 2 seconds"; +CM_ SG_ 1163 OVSPVALM "-5 at start then 5 after 2 seconds"; +CM_ SG_ 1163 OVSPVALH "-5 at start then 10 after 2 seconds"; +CM_ SG_ 1163 TSRSPU "always 1"; +CM_ SG_ 1552 UI_SPEED "Does not appear to match dash"; +CM_ SG_ 1552 METER_SLIDER_BRIGHTNESS_PCT "Combination display brightness setting, scales from 12 per cent to 100 per cent, reflects combination meter settings only, not linked with headlight state"; +CM_ SG_ 1552 METER_SLIDER_LOW_BRIGHTNESS "Combination display low brightness mode, also controls footwell lighting"; +CM_ SG_ 1552 METER_SLIDER_DIMMED "Combination display slider not at max, reflects combination meter settings only, not linked with headlight state"; +CM_ SG_ 1553 ODOMETER "Unit is dependent upon units signal"; +CM_ SG_ 1592 LOCK_STATUS_CHANGED "1 on rising edge of lock/unlocking"; +CM_ SG_ 1592 LOCK_STATUS "The next 3 bits always seem to follow this signal."; +CM_ SG_ 1592 LOCKED_VIA_KEYFOB "1 for as long as car is locked with key fob or door handle touch"; + +VAL_ 295 GEAR 0 "P" 1 "R" 2 "N" 3 "D" 4 "B"; +VAL_ 467 LOW_SPEED_LOCKOUT 2 "low speed locked" 1 "ok"; +VAL_ 467 PCM_FOLLOW_DISTANCE 1 "far" 2 "medium" 3 "close"; +VAL_ 614 STATE 3 "enabled" 1 "disabled"; +VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left"; +VAL_ 835 ACC_TYPE 2 "permanent low speed lockout" 1 "ok"; +VAL_ 835 ACC_MALFUNCTION 1 "faulted" 0 "ok"; +VAL_ 835 ACC_CUT_IN 1 "CUT-IN Detected" 0 "clear"; +VAL_ 835 ALLOW_LONG_PRESS 2 "set speed increase by 5 speed units regardless" 1 "set speed increase by 1 speed unit on short press, 5 speed units on long press"; +VAL_ 865 CLUTCH_RELEASED 0 "clutch pressed any amount" 1 "clutch released"; +VAL_ 898 CLIMATE_SET_POINT 0 "CLIMATE LO MODE" 55 "CLIMATE HI MODE" 57 "CLIMATE OFF"; +VAL_ 898 AIR_CONDITIONER_STATE 20 "CLIMATE OFF"; +VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted"; +VAL_ 921 DISTANCE_LINES 0 "not displayed" 1 "close" 2 "medium" 3 "far"; +VAL_ 956 SPORT_ON 0 "off" 1 "on"; +VAL_ 956 GEAR 0 "D" 1 "S" 8 "N" 16 "R" 32 "P"; +VAL_ 956 SPORT_GEAR_ON 0 "off" 1 "on"; +VAL_ 956 SPORT_GEAR 1 "S1" 2 "S2" 3 "S3" 4 "S4" 5 "S5" 6 "S6"; +VAL_ 956 ECON_ON 0 "off" 1 "on"; +VAL_ 956 B_GEAR_ENGAGED 0 "off" 1 "on"; +VAL_ 956 DRIVE_ENGAGED 0 "off" 1 "on"; +VAL_ 1005 REVERSE_CAMERA_GUIDELINES 3 "No guidelines" 2 "Static guidelines" 1 "Active guidelines"; +VAL_ 1009 PCM_FOLLOW_DISTANCE 1 "far" 2 "medium" 3 "close"; +VAL_ 1041 PCS_INDICATOR 2 "PCS Faulted" 1 "PCS Turned Off By User" 0 "PCS Enabled"; +VAL_ 1041 PCS_SENSITIVITY 64 "high sensitivity" 128 "mid sensitivity" 192 "low sensitivity" 0 "off"; +VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none"; +VAL_ 1042 BARRIERS 3 "left" 2 "right" 1 "both" 0 "none"; +VAL_ 1042 RIGHT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none"; +VAL_ 1042 LKAS_STATUS 1 "on" 0 "off"; +VAL_ 1042 LEFT_LINE 3 "orange" 2 "faded" 1 "solid" 0 "none"; +VAL_ 1042 LDA_ON_MESSAGE 2 "Lane Departure Alert Turned ON, Steering Assist Inactive" 1 "Lane Departure Alert Turned ON, Steering Assist Active" 0 "clear"; +VAL_ 1042 LDA_SA_TOGGLE 2 "steering assist off" 1 "steering assist on"; +VAL_ 1042 LDA_SENSITIVITY 2 "standard" 1 "high" 0 "undefined"; +VAL_ 1042 LDA_MESSAGES 4 "lda unavailable at this speed" 1 "lda unavailable below approx 50km/h" 0 "ok"; +VAL_ 1042 LDA_FRONT_CAMERA_BLOCKED 1 "lda unavailable" 0 "ok"; +VAL_ 1042 TAKE_CONTROL 1 "take control" 0 "ok"; +VAL_ 1042 LANE_SWAY_WARNING 3 "ok" 2 "orange please take a break" 1 "prompt would you like to take a break" 0 "ok"; +VAL_ 1042 LANE_SWAY_BUZZER 3 "ok" 2 "beep twice" 1 "beep twice" 0 "ok"; +VAL_ 1161 TSGN1 1 "speed sign" 0 "none"; +VAL_ 1161 TSGN2 1 "speed sign" 0 "none"; +VAL_ 1161 SPLSGN2 15 "conditional blank" 4 "wet road" 5 "rain" 0 "none"; +VAL_ 1162 TSGN3 0 "none" 1 "speed sign" 2 "0 unlimited" 7 "unlimited" 16 "highway" 17 "no highway" 18 "motorway" 19 "no motorway" 20 "in city" 21 "outside city" 22 "pedestrian area" 23 "no pedestrian area" 65 "no overtaking left" 66 "no overtaking right" 67 "overtaking allowed again" 81 "no right turn" 97 "stop" 105 "yield" 113 "stop" 114 "yield us" 129 "no entry" 138 "no entry tss2" 145 "do not enter"; +VAL_ 1162 SPLSGN3 15 "conditional blank" 4 "wet road" 5 "rain" 0 "none"; +VAL_ 1552 METER_SLIDER_LOW_BRIGHTNESS 1 "Low brightness mode, footwell lights off" 0 "Normal mode, footwell lights on"; +VAL_ 1552 METER_SLIDER_DIMMED 1 "Dimmed" 0 "Not Dimmed"; +VAL_ 1552 UNITS 1 "km (km/L)" 2 "km (L/100km)" 3 "miles (MPG US)" 4 "miles (MPG Imperial)"; +VAL_ 1553 UNITS 1 "km" 2 "miles"; +VAL_ 1556 TURN_SIGNALS 3 "none" 2 "right" 1 "left"; +VAL_ 1556 BLINKER_BUTTON_PRESSED 1 "button pressed" 0 "not pressed"; +VAL_ 1570 HEADLIGHT_MODE 0 "headlights off" 2 "force parking lights" 4 "force low beams" 7 "auto low beams" 6 "auto parking lights"; +VAL_ 1592 LOCK_STATUS 0 "locked" 1 "unlocked"; diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/_toyota_adas_standard.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/_toyota_adas_standard.dbc new file mode 100644 index 0000000000..20680225aa --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/_toyota_adas_standard.dbc @@ -0,0 +1,56 @@ +BO_ 466 PCM_CRUISE: 8 XXX + SG_ GAS_RELEASED : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_ACTIVE : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_BRAKING : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ACCEL_NET : 23|16@0- (0.0009765625,0) [-20|20] "m/s^2" XXX + SG_ NEUTRAL_FORCE : 39|16@0- (2,0) [-65536|65534] "N" XXX + SG_ CRUISE_STATE : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CANCEL_REQ : 49|1@1+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 643 PRE_COLLISION: 7 DSU + SG_ _COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ FORCE : 23|16@0- (2,0) [0|255] "N" XXX + SG_ SET_ME_X002 : 33|8@0+ (1,0) [0|3] "" XXX + SG_ BRAKE_STATUS : 39|3@0+ (1,0) [0|255] "" XXX + SG_ STATE : 36|3@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X003 : 40|1@0+ (1,0) [0|1] "" XXX + SG_ PRECOLLISION_ACTIVE : 41|1@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 705 GAS_PEDAL: 8 XXX + SG_ GAS_RELEASED : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ETQLVSC : 15|16@0- (0.03125,0) [0|0] "Nm" XXX + SG_ ETQREAL : 31|16@0- (0.03125,0) [0|0] "Nm" SCS + SG_ ETQISC : 47|8@0+ (1,-192) [0|0] "Nm" XXX + SG_ GAS_PEDAL : 55|8@0+ (0.5,0) [0|0] "%" DS1,FCM + SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 740 STEERING_LKA: 5 XXX + SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 6|6@0+ (1,0) [0|63] "" XXX + SG_ SET_ME_1 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 836 PRE_COLLISION_2: 8 DSU + SG_ DSS1GDRV : 7|10@0- (0.1,0) [0|0] "m/s^2" Vector__XXX + SG_ PCSALM : 17|1@0+ (1,0) [0|0] "" FCM + SG_ IBTRGR : 27|1@0+ (1,0) [0|0] "" FCM + SG_ PBATRGR : 30|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PREFILL : 33|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVSTRGR : 36|1@0+ (1,0) [0|0] "" SCS + SG_ CHECKSUM : 63|8@0+ (1,0) [0|0] "" XXX + +CM_ SG_ 466 NEUTRAL_FORCE "force in newtons the engine/electric motors are applying without any acceleration commands or user input"; +CM_ SG_ 466 ACC_BRAKING "whether brakes are being actuated from ACC command"; +CM_ SG_ 466 ACCEL_NET "net negative acceleration (braking) applied by the system if on flat ground"; +CM_ SG_ 466 CRUISE_STATE "Active state is 8, if standstill is requested will switch to state 11(3 sec timer), after timer is elapsed will switch into state 7(standstill). If plus button was pressed - status 9, minus button pressed - status 10"; +CM_ SG_ 643 _COUNTER "only used on cars that use this msg for cruise control"; +CM_ SG_ 643 BRAKE_STATUS "only used on cars that use this msg for cruise control"; +CM_ SG_ 643 PRECOLLISION_ACTIVE "set 0.5s before any braking"; + +VAL_ 466 CRUISE_STATE 11 "timer_3sec" 10 "adaptive click down" 9 "adaptive click up" 8 "adaptive engaged" 7 "standstill" 6 "non-adaptive click up" 5 "non-adaptive click down" 4 "non-adaptive hold down" 3 "non-adaptive hold up" 2 "non-adaptive being engaged" 1 "non-adaptive engaged" 0 "off"; +VAL_ 643 STATE 0 "normal" 1 "adaptive_cruise_control" 3 "emergency_braking"; diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/toyota_new_mc_pt.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_new_mc_pt.dbc new file mode 100644 index 0000000000..97182f93a9 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_new_mc_pt.dbc @@ -0,0 +1,21 @@ +CM_ "IMPORT _toyota_2017.dbc"; +CM_ "IMPORT _toyota_adas_standard.dbc"; + +BO_ 548 BRAKE_MODULE: 8 XXX + SG_ BRAKE_PRESSURE : 43|12@0+ (1,0) [0|4047] "" XXX + SG_ BRAKE_PRESSED : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 610 EPS_STATUS: 5 EPS + SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX + SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 1178 BRAKE_RELATED: 8 XXX + SG_ BRAKE_PRESSED : 48|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 548 BRAKE_PRESSURE "seems prop to pedal force"; +CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others"; + +VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled"; +VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby"; diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/toyota_nodsu_pt.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_nodsu_pt.dbc new file mode 100644 index 0000000000..a7ffbf1564 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_nodsu_pt.dbc @@ -0,0 +1,78 @@ +CM_ "IMPORT _toyota_2017.dbc"; +CM_ "IMPORT _toyota_adas_standard.dbc"; + +BO_ 401 STEERING_LTA: 8 XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ SETME_X3 : 29|2@0+ (1,0) [0|3] "" XXX + SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] "" XXX + SG_ TORQUE_WIND_DOWN : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ANGLE : 55|8@0- (0.5,0) [0|255] "" XXX + SG_ STEER_ANGLE_CMD : 15|16@0- (0.0573,0) [-540|540] "" XXX + SG_ STEER_REQUEST_2 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ LKA_ACTIVE : 26|1@0+ (1,0) [0|1] "" XXX + SG_ CLEAR_HOLD_STEERING_ALERT : 30|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 6|6@0+ (1,0) [0|255] "" XXX + SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SETME_X1 : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 550 BRAKE_MODULE: 8 XXX + SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 610 EPS_STATUS: 8 EPS + SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX + SG_ LTA_STATE : 15|5@0+ (1,0) [0|31] "" XXX + SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 881 LTA_RELATED: 8 FCM + SG_ GAS_PEDAL : 15|8@0+ (0.005,0) [0|1] "" XXX + SG_ STEER_ANGLE : 23|16@0- (0.0573,0) [-500|500] "" XXX + SG_ TURN_SIGNALS : 35|2@0+ (1,0) [0|3] "" XXX + SG_ UNKNOWN_2 : 58|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_SA_TOGGLE : 59|1@0+ (1,0) [0|1] "" XXX + SG_ LTA_STEER_REQUEST : 60|1@0+ (1,0) [0|1] "" XXX + SG_ UNKNOWN : 61|1@0+ (1,0) [0|1] "" XXX + SG_ STEERING_PRESSED : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 1014 BSM: 8 XXX + SG_ L_ADJACENT : 0|1@0+ (1,0) [0|1] "" XXX + SG_ L_APPROACHING : 8|1@0+ (1,0) [0|1] "" XXX + SG_ R_ADJACENT : 1|1@0+ (1,0) [0|1] "" XXX + SG_ R_APPROACHING : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ADJACENT_ENABLED : 7|1@0+ (1,0) [0|1] "" XXX + SG_ APPROACHING_ENABLED : 15|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 401 PERCENTAGE "driver override percentage (0-100), very close to steeringPressed in OP"; +CM_ SG_ 401 TORQUE_WIND_DOWN "used to wind down torque on user override"; +CM_ SG_ 401 ANGLE "angle of car relative to lane center on LTA camera"; +CM_ SG_ 401 STEER_ANGLE_CMD "desired angle, OEM steers up to 95 degrees, no angle limit but torque will bottom out"; +CM_ SG_ 401 CLEAR_HOLD_STEERING_ALERT "set to 1 when user clears LKAS_HUD->LDA_ALERT ('Hold Steering') by applying torque to steering wheel"; +CM_ SG_ 401 STEER_REQUEST "enable bit for steering, 1 to steer, 0 to not"; +CM_ SG_ 401 STEER_REQUEST_2 "enable bit for steering, 1 to steer, 0 to not"; +CM_ SG_ 401 LKA_ACTIVE "1 when using LTA for LKA"; +CM_ SG_ 401 SETME_X1 "usually 1, seen at 0 on some South American Corollas indicating lack of stock Lane Tracing Assist"; +CM_ SG_ 401 SETME_X3 "almost completely correlates with Toyota Safety Sense version, but may instead describe max torque when using LTA. if TSS 2.5 or 2022 RAV4, this is always 1. if TSS 2.0 this is always 3 (or 0 on Alphard, Highlander, NX)"; +CM_ SG_ 550 BRAKE_PRESSURE "seems prop to pedal force"; +CM_ SG_ 550 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8"; +CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others"; +CM_ SG_ 881 GAS_PEDAL "not set on all cars, only seen on TSS 2.5 Camry Hybrid so far"; +CM_ SG_ 881 STEER_ANGLE "matches STEER_TORQUE_SENSOR->STEER_ANGLE"; +CM_ SG_ 881 TURN_SIGNALS "flipped on some cars"; +CM_ SG_ 881 LDA_SA_TOGGLE "not applicable for all cars"; +CM_ SG_ 881 LTA_STEER_REQUEST "only applicable for TSS 2.5: matches STEERING_LTA->STEER_REQUEST"; +CM_ SG_ 881 UNKNOWN "related to steering wheel angle"; +CM_ SG_ 881 STEERING_PRESSED "only applicable for TSS 2.5: low sensitivity steering wheel pressed by driver signal"; +CM_ SG_ 1014 L_ADJACENT "vehicle adjacent left side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 L_APPROACHING "vehicle approaching from left side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 R_ADJACENT "vehicle adjacent right side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 R_APPROACHING "vehicle approaching from right side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 ADJACENT_ENABLED "when BSM is enabled in settings, this is on along with APPROACHING_ENABLED. this controls bsm alert visibility"; +CM_ SG_ 1014 APPROACHING_ENABLED "when BSM is enabled in settings, this is on along with ADJACENT_ENABLED. this controls bsm alert visibility"; + +VAL_ 401 SETME_X3 3 "TSS 2.0" 1 "TSS 2.5 or 2022 RAV4" 0 "TSS 2.0 on Alphard, Highlander, NX"; +VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled"; +VAL_ 610 LKA_STATE 25 "temporary_fault" 17 "permanent_fault" 11 "lka_missing_unavailable2" 9 "temporary_fault2" 5 "active" 3 "lka_missing_unavailable" 1 "standby"; +VAL_ 610 LTA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 3 "lta_missing_unavailable" 1 "standby"; diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/toyota_secoc_pt.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_secoc_pt.dbc new file mode 100644 index 0000000000..eefe990667 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_secoc_pt.dbc @@ -0,0 +1,156 @@ +CM_ "IMPORT _toyota_2017.dbc"; + +BO_ 15 SECOC_SYNCHRONIZATION: 8 XXX + SG_ TRIP_CNT : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ RESET_CNT : 23|20@0+ (1,0) [0|65535] "" XXX + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + +BO_ 257 BRAKE_MODULE: 8 XXX + SG_ BRAKE_PRESSED : 3|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_PRESSURE_1 : 31|8@0+ (1,0) [0|15] "" XXX + SG_ BRAKE_PRESSURE_2 : 61|6@0+ (1,0) [0|63] "" XXX + +BO_ 278 GAS_PEDAL: 8 XXX + SG_ GAS_PEDAL_ACC : 7|8@0+ (0.005,0) [0|255] "" XXX + SG_ GAS_PEDAL_USER : 15|8@0+ (0.005,0) [0|255] "" XXX + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 305 STEERING_LTA_2: 8 XXX + SG_ STEER_REQUEST_2 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_REQUEST : 3|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 13|6@0+ (1,0) [0|63] "" XXX + SG_ STEER_ANGLE_CMD : 23|16@0- (0.0573,0) [0|65535] "" XXX + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 374 PCM_CRUISE: 8 XXX + SG_ CRUISE_ACTIVE : 5|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_STATE : 31|4@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 375 PCM_CRUISE_3: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0- (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 21|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_RELEASED : 30|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 31|1@0+ (1,0) [0|1] "" XXX + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 387 ACC_CONTROL_2: 8 XXX + SG_ ACCEL_CMD : 7|16@0- (0.001,0) [-20|20] "m/s^2" HCU + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 401 STEERING_LTA: 8 XXX + SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 6|6@0+ (1,0) [0|255] "" XXX + SG_ SETME_X1 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_ANGLE_CMD : 15|16@0- (0.0573,0) [-540|540] "" XXX + SG_ STEER_REQUEST_2 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ LKA_ACTIVE : 26|1@0+ (1,0) [0|1] "" XXX + SG_ SETME_X3 : 29|2@0+ (1,0) [0|3] "" XXX + SG_ CLEAR_HOLD_STEERING_ALERT : 30|1@0+ (1,0) [0|1] "" XXX + SG_ PERCENTAGE : 39|8@0+ (1,0) [0|255] "" XXX + SG_ TORQUE_WIND_DOWN : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ANGLE : 55|8@0- (0.5,0) [0|255] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 418 CRUISE_RELATED: 8 XXX + SG_ CRUISE_ACTIVE : 7|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 589 PCM_CRUISE_4: 8 PCM + SG_ DISTANCE : 2|1@0+ (1,0) [0|1] "" XXX + SG_ CANCEL : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DECREASE : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ENABLE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ INCREASE : 7|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 27|4@0+ (1,0) [0|15] "" XXX + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 610 EPS_STATUS: 8 EPS + SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LTA_STATE : 15|5@0+ (1,0) [0|31] "" XXX + SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX + SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 643 PRE_COLLISION: 8 DSU + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 740 STEERING_LKA: 8 XXX + SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 6|6@0+ (1,0) [0|63] "" XXX + SG_ SET_ME_1 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] "" XXX + SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] "" XXX + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 836 PRE_COLLISION_2: 8 DSU + SG_ AUTHENTICATOR : 35|28@0+ (1,0) [0|268435455] "" XXX + SG_ RESET_FLAG : 37|2@0+ (1,0) [0|3] "" XXX + SG_ MSG_CNT_LOWER : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 881 LTA_RELATED: 8 FCM + SG_ GAS_PEDAL : 15|8@0+ (0.005,0) [0|1] "" XXX + SG_ STEER_ANGLE : 23|16@0- (0.0573,0) [-500|500] "" XXX + SG_ TURN_SIGNALS : 35|2@0+ (1,0) [0|3] "" XXX + SG_ UNKNOWN_2 : 58|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_SA_TOGGLE : 59|1@0+ (1,0) [0|1] "" XXX + SG_ LTA_STEER_REQUEST : 60|1@0+ (1,0) [0|1] "" XXX + SG_ UNKNOWN : 61|1@0+ (1,0) [0|1] "" XXX + SG_ STEERING_PRESSED : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 1014 BSM: 8 XXX + SG_ L_ADJACENT : 0|1@0+ (1,0) [0|1] "" XXX + SG_ R_ADJACENT : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ADJACENT_ENABLED : 7|1@0+ (1,0) [0|1] "" XXX + SG_ L_APPROACHING : 8|1@0+ (1,0) [0|1] "" XXX + SG_ R_APPROACHING : 10|1@0+ (1,0) [0|1] "" XXX + SG_ APPROACHING_ENABLED : 15|1@0+ (1,0) [0|1] "" XXX + +CM_ SG_ 305 STEER_ANGLE_CMD "Used in place of STEERING_LTA.STEER_ANGLE_CMD on SecOC cars"; +CM_ SG_ 387 ACCEL_CMD "Used in place of ACC_CONTROL.ACCEL_CMD on SecOC cars"; +CM_ SG_ 401 STEER_REQUEST "enable bit for steering, 1 to steer, 0 to not"; +CM_ SG_ 401 SETME_X1 "usually 1, seen at 0 on some South American Corollas indicating lack of stock Lane Tracing Assist"; +CM_ SG_ 401 STEER_ANGLE_CMD "desired angle, OEM steers up to 95 degrees, no angle limit but torque will bottom out"; +CM_ SG_ 401 STEER_REQUEST_2 "enable bit for steering, 1 to steer, 0 to not"; +CM_ SG_ 401 LKA_ACTIVE "1 when using LTA for LKA"; +CM_ SG_ 401 SETME_X3 "almost completely correlates with Toyota Safety Sense version, but may instead describe max torque when using LTA. if TSS 2.5 or 2022 RAV4, this is always 1. if TSS 2.0 this is always 3 (or 0 on Alphard, Highlander, NX)"; +CM_ SG_ 401 CLEAR_HOLD_STEERING_ALERT "set to 1 when user clears LKAS_HUD->LDA_ALERT ('Hold Steering') by applying torque to steering wheel"; +CM_ SG_ 401 PERCENTAGE "driver override percentage (0-100), very close to steeringPressed in OP"; +CM_ SG_ 401 TORQUE_WIND_DOWN "used to wind down torque on user override"; +CM_ SG_ 401 ANGLE "angle of car relative to lane center on LTA camera"; +CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others"; +CM_ SG_ 881 GAS_PEDAL "not set on all cars, only seen on TSS 2.5 Camry Hybrid so far"; +CM_ SG_ 881 STEER_ANGLE "matches STEER_TORQUE_SENSOR->STEER_ANGLE"; +CM_ SG_ 881 TURN_SIGNALS "flipped on some cars"; +CM_ SG_ 881 LDA_SA_TOGGLE "not applicable for all cars"; +CM_ SG_ 881 LTA_STEER_REQUEST "only applicable for TSS 2.5: matches STEERING_LTA->STEER_REQUEST"; +CM_ SG_ 881 UNKNOWN "related to steering wheel angle"; +CM_ SG_ 881 STEERING_PRESSED "only applicable for TSS 2.5: low sensitivity steering wheel pressed by driver signal"; +CM_ SG_ 1014 L_ADJACENT "vehicle adjacent left side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 R_ADJACENT "vehicle adjacent right side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 ADJACENT_ENABLED "when BSM is enabled in settings, this is on along with APPROACHING_ENABLED. this controls bsm alert visibility"; +CM_ SG_ 1014 L_APPROACHING "vehicle approaching from left side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 R_APPROACHING "vehicle approaching from right side of car. enabled above 10mph, regardless of ADJACENT_ENABLED or APPROACHING_ENABLED"; +CM_ SG_ 1014 APPROACHING_ENABLED "when BSM is enabled in settings, this is on along with ADJACENT_ENABLED. this controls bsm alert visibility"; + +VAL_ 401 SETME_X3 3 "TSS 2.0" 1 "TSS 2.5 or 2022 RAV4" 0 "TSS 2.0 on Alphard, Highlander, NX"; +VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled"; +VAL_ 610 LTA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 3 "lta_missing_unavailable" 1 "standby"; +VAL_ 610 LKA_STATE 25 "temporary_fault" 17 "permanent_fault" 11 "lka_missing_unavailable2" 9 "temporary_fault2" 5 "active" 3 "lka_missing_unavailable" 1 "standby"; diff --git a/opendbc_repo/opendbc/dbc/generator/toyota/toyota_tnga_k_pt.dbc b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_tnga_k_pt.dbc new file mode 100644 index 0000000000..a8f071c368 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/generator/toyota/toyota_tnga_k_pt.dbc @@ -0,0 +1,20 @@ +CM_ "IMPORT _toyota_2017.dbc"; +CM_ "IMPORT _toyota_adas_standard.dbc"; + +BO_ 550 BRAKE_MODULE: 8 XXX + SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 610 EPS_STATUS: 5 EPS + SG_ IPAS_STATE : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LKA_STATE : 31|7@0+ (1,0) [0|127] "" XXX + SG_ TYPE : 24|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + +CM_ SG_ 550 BRAKE_PRESSURE "seems prop to pedal force"; +CM_ SG_ 550 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8"; +CM_ SG_ 610 TYPE "seems 1 on Corolla, 0 on all others"; + +VAL_ 610 IPAS_STATE 5 "override" 3 "enabled" 1 "disabled"; +VAL_ 610 LKA_STATE 25 "temporary_fault" 9 "temporary_fault2" 5 "active" 1 "standby"; diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_chassis.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_chassis.dbc new file mode 100644 index 0000000000..e1fc1ccbff --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gm_global_a_chassis.dbc @@ -0,0 +1,75 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: K182_PACM K43_PSCM K17_EBCM NEO K124_ASCM + + + +BO_ 823 PACMParkAssitCmd: 7 NEO + SG_ RollingCounter : 35|2@0+ (1,0) [0|0] "" NEO + SG_ SteeringWheelChecksum : 47|16@0+ (1,0) [0|0] "" NEO + SG_ SteeringWheelCmd : 23|16@0+ (1,0) [0|0] "" NEO + +BO_ 560 EBCMRegen: 6 K17_EBCM + SG_ Regen : 1|10@0+ (1,0) [0|0] "" NEO + +BO_ 368 EBCMFrictionBrakeStatus: 8 K17_EBCM + SG_ FrictionBrakePressure : 23|16@0+ (1,0) [0|0] "" NEO + +BO_ 789 EBCMFrictionBrakeCmd: 5 K17_EBCM + SG_ RollingCounter : 33|2@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeMode : 7|4@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeChecksum : 23|16@0+ (1,0) [0|0] "" NEO + SG_ FrictionBrakeCmd : 3|12@0- (1,0) [0|0] "" NEO + +BO_TX_BU_ 823 : K43_PSCM,NEO; +BO_TX_BU_ 789 : NEO,K17_EBCM; + + +CM_ BU_ K182_PACM "Parking Assist Control Module"; +CM_ BU_ K43_PSCM "Power Steering Control Module"; +CM_ BU_ K17_EBCM "Electronic Brake Control Module"; +CM_ BU_ NEO "Comma NEO"; +CM_ BU_ K124_ASCM "Active Safety Control Module"; +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "UseGMParameterIDs" 0; +BA_ "BusType" "CAN"; +BA_ "ProtocolType" "GMLAN"; + diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_high_voltage_management.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_high_voltage_management.dbc new file mode 100644 index 0000000000..60729e5692 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gm_global_a_high_voltage_management.dbc @@ -0,0 +1,196 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: +BU_: K16_BECM K114B_HPCM T18_BatteryCharger +BO_ 512 Battery_Module_1: 8 K16_BECM + SG_ Voltage_1_0_A m0 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_0_B m0 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_0_C m0 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_1_A m1 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_1_B m1 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_1_C m1 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_2_A m2 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_2_B m2 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_2_C m2 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_3_A m3 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_3_B m3 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_3_C m3 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_4_A m4 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_4_B m4 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_4_C m4 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_5_A m5 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_5_B m5 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_5_C m5 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_6_A m6 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_6_B m6 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_6_C m6 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_7_A m7 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_7_B m7 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_1_7_C m7 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Cell_Bank_Number_1 M : 55|3@0+ (1,0) [0|0] "" K16_BECM + +BO_ 514 Battery_Module_2: 8 K16_BECM + SG_ Voltage_2_0_A m0 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_0_B m0 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_0_C m0 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_1_A m1 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_1_B m1 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_1_C m1 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_2_A m2 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_2_B m2 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_2_C m2 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_3_A m3 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_3_B m3 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_3_C m3 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_4_A m4 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_4_B m4 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_4_C m4 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_5_A m5 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_5_B m5 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_5_C m5 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_6_A m6 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_6_B m6 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_6_C m6 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_7_A m7 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_7_B m7 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_2_7_C m7 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Cell_Bank_Number_2 M : 55|3@0+ (1,0) [0|0] "" K16_BECM + +BO_ 516 Battery_Module_3: 8 K16_BECM + SG_ Voltage_3_0_A m0 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_0_B m0 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_0_C m0 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_1_A m1 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_1_B m1 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_1_C m1 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_2_A m2 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_2_B m2 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_2_C m2 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_3_A m3 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_3_B m3 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_3_C m3 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_4_A m4 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_4_B m4 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_4_C m4 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_5_A m5 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_5_B m5 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_5_C m5 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_6_A m6 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_6_B m6 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_6_C m6 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_7_A m7 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_7_B m7 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_3_7_C m7 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Cell_Bank_Number_3 M : 55|3@0+ (1,0) [0|0] "" K16_BECM + +BO_ 518 Battery_Module_4: 8 K16_BECM + SG_ Voltage_4_0_A m0 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_0_B m0 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_0_C m0 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_1_A m1 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_1_B m1 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_1_C m1 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_2_A m2 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_2_B m2 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_2_C m2 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_3_A m3 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_3_B m3 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_3_C m3 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_4_A m4 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_4_B m4 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_4_C m4 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_5_A m5 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_5_B m5 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_5_C m5 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_6_A m6 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_6_B m6 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_6_C m6 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_7_A m7 : 4|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_7_B m7 : 20|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Voltage_4_7_C m7 : 39|12@0+ (0.00125,0) [0|0] "V" K16_BECM + SG_ Cell_Bank_Number_4 M : 55|3@0+ (1,0) [0|0] "" K16_BECM + +BO_ 528 Pack_Stats: 8 K16_BECM + SG_ Pack_Voltage : 7|12@0+ (0.125,0) [0|0] "V" K16_BECM + SG_ Pack_Current : 23|8@0- (0.1,-0.1) [0|0] "A" K16_BECM + +BO_ 530 Charger_stats: 6 T18_BatteryCharger + SG_ Charger_HV_Current : 7|13@0+ (0.05,0) [0|0] "A" K16_BECM + SG_ HV_Voltage : 10|10@0+ (0.5,0) [0|0] "V" K16_BECM + SG_ LV_Current : 16|8@0+ (0.2,0) [0|0] "A" K16_BECM + SG_ LV_Voltage : 24|8@0+ (0.1,0) [0|0] "V" K16_BECM + +BO_ 770 Battery_temp: 8 K16_BECM + SG_ Temp_A m0 : 8|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_B m0 : 16|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_C m0 : 24|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_D m0 : 32|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_E m0 : 40|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_F m0 : 48|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_G m1 : 8|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_H m1 : 16|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Temp_I m1 : 24|8@1+ (0.5,-40) [0|0] "C" K16_BECM + SG_ Switch M : 2|1@1+ (1,0) [0|0] "" K16_BECM + +BO_ 782 Charger_Command: 1 T18_BatteryCharger + SG_ Command : 0|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 772 Charger_parameters: 4 T18_BatteryCharger + SG_ Unknown : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ Current : 8|8@1+ (0.05,0) [0|0] "A" Vector__XXX + SG_ Voltage : 23|16@0+ (0.5,0) [0|0] "V" Vector__XXX + +BO_ 1120 Coolant_Temp: 4 K16_BECM + SG_ Inlet_Coolant_Temp : 1|10@0+ (0.125,-40) [0|0] "" Vector__XXX + SG_ Outlet_Coolant_Temp : 17|10@0+ (0.125,-40) [0|0] "" Vector__XXX + +BO_ 778 AC_Stats: 7 T18_BatteryCharger + SG_ Mains_Voltage : 10|2@0+ (1,0) [0|0] "V" Vector__XXX + SG_ Total_Charge : 19|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 776 Charger_status: 5 T18_BatteryCharger + SG_ Status : 20|3@1+ (1,0) [0|0] "" Vector__XXX + +BA_DEF_ BO_ "GenMsgBackgroundColor" STRING ; +BA_DEF_ BO_ "GenMsgForegroundColor" STRING ; +BA_DEF_ BO_ "isj1939dbc" INT 0 0; +BA_DEF_DEF_ "GenMsgBackgroundColor" "#ffffff"; +BA_DEF_DEF_ "GenMsgForegroundColor" "#000000"; +BA_DEF_DEF_ "isj1939dbc" 0; +CM_ BU_ K16_BECM "Battery Energy Control Module"; +CM_ BU_ K114B_HPCM "Hybrid Powertrain Control Module"; +CM_ BU_ T18_BatteryCharger "Battery Charger"; +VAL_ 782 Command 1 "12V_Only" 2 "HV_Only" 3 "12V_and_HV"; +VAL_ 778 Mains_Voltage 0 "Unplugged" 1 "110V" 3 "220V"; +VAL_ 776 Status 0 "Off" 5 "LV_Only" 7 "HV_and_LV" 3 "HV_Only"; diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_lowspeed.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_lowspeed.dbc new file mode 100644 index 0000000000..524eeed8be --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gm_global_a_lowspeed.dbc @@ -0,0 +1,118 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: GMLAN NEO +VAL_TABLE_ GearShifter 3 "Park" 0 "Drive/Low" ; +VAL_TABLE_ DriverDoorStatus 1 "Opened" 0 "Closed" ; +VAL_TABLE_ LKAGapButton 2 "???" 1 "??" 0 "None" ; +VAL_TABLE_ CruiseButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ; +VAL_TABLE_ CruiseControlActive 1 "Active" 0 "Inactive" ; +VAL_TABLE_ BlinkerStatus 1 "Active" 0 "Inactive" ; + + +BO_ 274923520 DriverDoorStatus: 1 GMLAN + SG_ DriverDoorOpened : 0|1@0+ (1,0) [0|0] "" NEO + +BO_ 272629760 Chime: 5 NEO + SG_ ChimeType : 7|8@0+ (1,0) [0|0] "" GMLAN + SG_ ChimeRepeat : 23|8@0+ (1,0) [0|0] "" GMLAN + SG_ ChimeDuration : 15|8@0+ (1,0) [0|0] "" GMLAN + SG_ ChimeByte5 : 39|8@0+ (1,0) [0|0] "" GMLAN + SG_ ChimeByte4 : 31|8@0+ (1,0) [0|0] "" GMLAN + +BO_ 270581760 BlinkerStatus: 5 GMLAN + SG_ RightBlinker : 6|1@0+ (1,0) [0|0] "" NEO + SG_ LeftBlinker : 7|1@0+ (1,0) [0|0] "" NEO + SG_ BlinkerLight : 25|1@0+ (1,0) [0|0] "" NEO + +BO_ 270794752 SteeringWheelAngle: 8 GMLAN + SG_ SteeringWheelAngle : 39|16@0- (0.0625,0) [-540|540] "deg" NEO + +BO_ 271368192 GearShifter: 8 GMLAN + SG_ GearShifter : 17|2@0+ (1,0) [0|3] "" NEO + +BO_ 271360000 GasPedalRegenCruise: 8 GMLAN + SG_ CruiseControlActive : 56|1@0+ (1,0) [0|0] "" GMLAN + SG_ MaxRegen : 12|1@0+ (1,0) [0|1] "" GMLAN,NEO + SG_ GasPedal : 47|8@0+ (1,0) [0|254] "" GMLAN,NEO + SG_ GearShifter2NotUsed : 55|8@0+ (1,0) [0|255] "" GMLAN,NEO + +BO_ 270860288 BrakePedal: 2 GMLAN + SG_ BrakeLevel : 2|2@0+ (1,0) [0|3] "" NEO + SG_ BrakeSensor : 15|8@0+ (1,0) [0|255] "" NEO + +BO_ 275480576 WheelSpeed: 8 GMLAN + SG_ WheelSpeedFL : 7|16@0+ (0.01,0) [0|70] "yd/s" NEO + SG_ WheelSpeedFR : 39|16@0+ (0.01,0) [0|70] "yd/s" NEO + SG_ WheelSpeedRL : 23|16@0+ (0.01,0) [0|70] "yd/s" NEO + SG_ WheelSpeedRR : 55|16@0+ (0.01,0) [0|70] "yd/s" NEO + +BO_ 270598144 VehicleSpeed: 8 GMLAN + SG_ VehicleSpeed1 : 7|16@0+ (0.01,0) [0|100] "mph" NEO + SG_ VehicleSpeed2 : 39|16@0+ (0.01,0) [0|100] "mph" NEO + +BO_ 276135936 CruiseButtons: 3 GMLAN + SG_ CruiseButtons : 3|3@0+ (1,0) [0|12] "" NEO + +BO_ 276127744 CruiseButtons2: 1 GMLAN + SG_ LKAGapButton : 1|2@0+ (1,0) [0|2] "" NEO + +BO_ 275955897 LeftRadar: 2 GMLAN + SG_ BSM_Indicator_Light : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 275980379 RightRadar: 2 GMLAN + SG_ BSM_Indicator_Light : 0|1@0+ (1,0) [0|1] "" XXX + + + +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "BusType" "CAN"; +BA_ "ProtocolType" "GMLAN"; +VAL_ 274923520 DriverDoorOpened 1 "Opened" 0 "Closed" ; +VAL_ 270581760 RightBlinker 1 "Active" 0 "Inactive" ; +VAL_ 270581760 LeftBlinker 1 "Active" 0 "Inactive" ; +VAL_ 270581760 BlinkerLight 1 "Active" 0 "Inactive" ; +VAL_ 271368192 GearShifter 3 "Park" 0 "Drive/Low" ; +VAL_ 271360000 CruiseControlActive 1 "Active" 0 "Inactive" ; +VAL_ 276135936 CruiseButtons 6 "Cancel" 5 "Main" 3 "Set" 2 "Resume" 1 "None" ; +VAL_ 276127744 LKAGapButton 2 "???" 1 "??" 0 "None" ; +VAL_ 275955897 BSM_Indicator_Light 0 "Disabled" 1 "Enabled"; +VAL_ 275980379 BSM_Indicator_Right 0 "Disabled" 1 "Enabled"; + diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_lowspeed_1818125.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_lowspeed_1818125.dbc new file mode 100644 index 0000000000..3f5b15e6f2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gm_global_a_lowspeed_1818125.dbc @@ -0,0 +1,3993 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 2152177664 OTA_Electric_Pwr_Readiness_LS: 1 XXX + SG_ RmtRflshElecPwrRdness : 7|8@0+ (0.025,0) [0|6.375] "AmpHour" XXX + +BO_ 2152013824 Smart_High_Beam_Cust_LS: 1 XXX + SG_ SmrtHgBmAstCstSetAvail : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SmrtHgBmAstCstCurrSetVal : 7|3@0+ (1,0) [0|7] "" XXX + +BO_ 2159255552 ODI_CenterStack_2_BCM_LS: 8 XXX + SG_ ODI_CntrStck2BCM : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159247360 ODI_BCM_2_CenterStack_LS: 8 XXX + SG_ ODI_BCM2CntrStck : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2152046592 Remote_Climate_Control_Req_LS: 5 XXX + SG_ RmClmCtrlHMIActIndReq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RmClmCtrlRcrcSetReq : 3|3@0+ (1,0) [0|7] "" XXX + SG_ RmClmCtrlACSetReq : 10|3@0+ (1,0) [0|7] "" XXX + SG_ RmClmCtrlFrntFanStReq : 15|5@0+ (1,0) [0|31] "" XXX + SG_ RmClmCtrlFLAirDtStReq : 19|4@0+ (1,0) [0|15] "" XXX + SG_ RmClmCtrlClmModSetReq : 23|4@0+ (1,0) [0|15] "" XXX + SG_ RmClmCtrlLtSTempStReq : 29|6@0+ (1,0) [0|63] "" XXX + SG_ RmClmCtrlRrDfgSetReq : 31|2@0+ (1,0) [0|3] "" XXX + SG_ RmClmCtrlRtSTempStReq : 37|6@0+ (1,0) [0|63] "" XXX + SG_ RmClmCtrlSyncSetReq : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152030208 Tuner_Frequency_Request_LS: 8 XXX + SG_ TnrFrqBndReq : 3|4@0+ (1,0) [0|15] "" XXX + SG_ TnrFrqChnlReq : 15|56@0+ (1,0) [0|1] "" XXX + +BO_ 2150531072 Regen_Power_Ind_LS: 4 XXX + SG_ RegPwrLmtdDspPrcnt : 0|9@0- (0.392157,0) [-100.392192|100.000035] "%" XXX + SG_ RegPwrLmtdDspPrcntVs : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RegPwrLmtdIO : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151833600 Heated_Wndshild_CstmrIhbt_Req_LS: 1 XXX + SG_ HtdFrntWSCustRqIhbt : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HtdFrntWSDispReq : 7|2@0+ (1,0) [0|3] "" XXX + +BO_ 2151817216 Heated_Wndshild_Cstmr_Req_LS: 1 XXX + SG_ HtdFrntWSCustRq : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151849984 Seat_Level_Setting_Request_LS: 2 XXX + SG_ AutoThrmlStPasLvlStRq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ AutoThrmlStDrvLvStRq : 5|3@0+ (1,0) [0|7] "" XXX + SG_ AutoThrmlStPassMdStRq : 7|2@0+ (1,0) [0|3] "" XXX + SG_ AutoThrmlStDrvMdStRq : 15|2@0+ (1,0) [0|3] "" XXX + +BO_ 2153897984 ARB_OpMode_Customization_LS: 1 XXX + SG_ RunBrdExtdFtrAvail : 3|1@0+ (1,0) [0|1] "" XXX + SG_ RunBrdOpMdCstCurrStVal : 6|3@0+ (1,0) [0|7] "" XXX + SG_ RunBrdOpMdCstStAvail : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151702528 Lane_Keeping_Assist_LS: 2 XXX + SG_ LnKpngAstRecfblIndRq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ LnMrkngIndLft : 4|2@0+ (1,0) [0|3] "" XXX + SG_ LnKepAsstStIndLft : 7|3@0+ (1,0) [0|7] "" XXX + SG_ LnMrkngIndRgt : 12|2@0+ (1,0) [0|3] "" XXX + SG_ LnKepAsstStIndRgt : 15|3@0+ (1,0) [0|7] "" XXX + +BO_ 2156986368 PassPhrase_3_AMM_LS: 8 XXX + SG_ WiFiPssPhrsDgts17to24_Mp : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156978176 PassPhrase_2_AMM_LS: 8 XXX + SG_ WiFiPssPhrsDgts9to16_Mp : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156969984 PassPhrase_1_AMM_LS: 8 XXX + SG_ WiFiPssPhrsDgts1to8_Mp : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2150236160 Unlock_Key_Store_Crypt_2_LS: 8 XXX + SG_ UlckKyStrCrptoDt2Group : 4|61@0+ (1,0) [0|0] "" XXX + SG_ UlckKyStrCrptoDt2 : 3|60@0+ (1,0) [0|1.15292150460685E+018] "" XXX + SG_ UlckKyStrCrptoDt2M : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150170624 Unlock_Key_Store_Crypt_1_LS: 8 XXX + SG_ UlckKyStrCrptoDt1Group : 4|61@0+ (1,0) [0|0] "" XXX + SG_ UlckKyStrCrptoDt1 : 3|60@0+ (1,0) [0|1.15292150460685E+018] "" XXX + SG_ UlckKyStrCrptoDt1M : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155126784 Drvr_Seat_Rearward_Movmnt_LS: 1 XXX + SG_ DrvrSetRrwrdMvmnt : 7|3@0+ (1,0) [0|7] "" XXX + +BO_ 2154725376 Auxiliary_Heater_LS: 1 XXX + SG_ AuxHtrAtv378 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ AuxHtrRq : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2157051904 WiFi_Station_AMM_LS: 5 XXX + SG_ WiFiStatnMpReq : 1|34@0+ (1,0) [0|0] "" XXX + SG_ WSMR_WiFiAssnReq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ WSMR_WiFiStnMpMACAddr : 15|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2156994560 WiFi_AP_Data_AMM_LS: 2 XXX + SG_ WiFiAccsPntData_Mp : 0|9@0+ (1,0) [0|0] "" XXX + SG_ WAPDM_WiFiEnStat : 0|1@0+ (1,0) [0|1] "" XXX + SG_ WAPDM_EncrptnType : 11|4@0+ (1,0) [0|15] "" XXX + SG_ WAPDM_SecurityType : 15|4@0+ (1,0) [0|15] "" XXX + +BO_ 2158133248 Hill_Top_Customization_LS: 6 XXX + SG_ HTRCsStAvail : 0|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCsAvail : 7|7@0+ (1,0) [0|0] "" XXX + SG_ HTRCA_Res3Avail : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCA_Res2Avail : 2|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCA_Res1Avail : 3|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCA_OnAwAvail : 4|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCA_OnHmAvail : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCA_OnAvail : 6|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCA_OffAvail : 7|1@0+ (1,0) [0|1] "" XXX + SG_ HTRCsCrStVal : 10|3@0+ (1,0) [0|7] "" XXX + SG_ HVDpltnMdMxCnfdcRgExt : 21|14@0+ (0.1,0) [0|1638.3] "km" XXX + SG_ HVDpltnMdMiCnfdcRgExt : 37|14@0+ (0.1,0) [0|1638.3] "km" XXX + +BO_ 2154651648 Telematics_Audio_Control_LS: 1 XXX + SG_ TeleAudCtl : 7|8@0+ (1,0) [0|0] "" XXX + SG_ TAC_AudConctOutcm : 3|4@0+ (1,0) [0|15] "" XXX + SG_ TAC_AudChConctStat : 7|4@0+ (1,0) [0|15] "" XXX + +BO_ 2154635264 Telematics_Audio_Request_LS: 1 XXX + SG_ TeleAudReq : 7|8@0+ (1,0) [0|0] "" XXX + SG_ TAR_AudSrcStat : 3|4@0+ (1,0) [0|15] "" XXX + SG_ TAR_AudConctReq : 7|4@0+ (1,0) [0|15] "" XXX + +BO_ 2152529920 LVM_Audio_Video_Command_LS: 2 XXX + SG_ LowVolModAudVidCmd : 5|14@0+ (1,0) [0|0] "" XXX + SG_ LVMAVC_StreoAudRsp : 0|2@0+ (1,0) [0|3] "" XXX + SG_ LVMAVC_PrmtAudRsp : 2|2@0+ (1,0) [0|3] "" XXX + SG_ LVMAVC_RemtEnbl : 5|3@0+ (1,0) [0|7] "" XXX + SG_ LVMAVC_SpchRcgnAval : 9|2@0+ (1,0) [0|3] "" XXX + SG_ LVMAVC_RemSpchRcgnActn : 11|2@0+ (1,0) [0|3] "" XXX + SG_ LVMAVC_RemSpchRcgnID : 14|3@0+ (1,0) [0|7] "" XXX + +BO_ 2152513536 LVM_Audio_Video_Req_LS: 2 XXX + SG_ LowVolModAudVidReq : 0|9@0+ (1,0) [0|0] "" XXX + SG_ LVMAVR_DispReq : 0|3@0+ (1,0) [0|7] "" XXX + SG_ LVMAVR_SpchRcgnAct : 9|2@0+ (1,0) [0|3] "" XXX + SG_ LVMAVR_PrmtAudReq : 11|2@0+ (1,0) [0|3] "" XXX + SG_ LVMAVR_StreoAudReq : 13|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154889216 Cluster_HMI_Animation_Req_LS: 1 XXX + SG_ ClstrHMIAnmReq : 7|3@0+ (1,0) [0|7] "" XXX + +BO_ 2154872832 Infotainment_Activation_Req_LS: 1 XXX + SG_ RmRflshUpdtAvail : 6|1@0+ (1,0) [0|1] "" XXX + SG_ InfoActvnReq : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2156961792 SSID_AMM_3_LS: 8 XXX + SG_ WiFiSSIDDgts17to24_Mp : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2154569728 Infotainment_System_State_LS: 1 XXX + SG_ InfotnmntSysSt : 7|5@0+ (1,0) [0|31] "" XXX + +BO_ 2151931904 Custom_Launch_Ctrl_LS: 8 XXX + SG_ LnchCtrlMdStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ LnchCtrlWhlSlpStat : 7|5@0+ (1,0) [0|31] "" XXX + SG_ PTExPrtclFltWrng3IO : 8|1@0+ (1,0) [0|1] "" XXX + SG_ AWDRecmndIO : 9|1@0+ (1,0) [0|1] "" XXX + SG_ LnchCtrlEngRPMStat : 15|6@0+ (1,0) [0|63] "" XXX + SG_ ACCSysSltdMd : 17|2@0+ (1,0) [0|3] "" XXX + SG_ VehSpdCntlSystmType : 20|3@0+ (1,0) [0|7] "" XXX + SG_ PTExPartFltManRegStat : 23|3@0+ (1,0) [0|7] "" XXX + SG_ TCSTempDsblReqIO : 24|1@0+ (1,0) [0|1] "" XXX + SG_ VehStbCmptvMdCstAvl : 25|1@0+ (1,0) [0|1] "" XXX + SG_ VehStbEnmntCstAvl : 26|1@0+ (1,0) [0|1] "" XXX + SG_ TCSysCstAvl : 27|1@0+ (1,0) [0|1] "" XXX + SG_ VehStbCmptvMdCurSt : 28|1@0+ (1,0) [0|1] "" XXX + SG_ ElctShfPriLtdPerfMdIO : 29|1@0+ (1,0) [0|1] "" XXX + SG_ RegVltCtlEngyRcvryAct : 30|1@0+ (1,0) [0|1] "" XXX + SG_ ACCSysSltdMdDispIO : 31|1@0+ (1,0) [0|1] "" XXX + SG_ LnchCtrlTmrVal : 35|4@0+ (1,0) [0|15] "" XXX + SG_ VehStbEnhmntCurSt : 36|1@0+ (1,0) [0|1] "" XXX + SG_ TCSysCurSt : 37|1@0+ (1,0) [0|1] "" XXX + SG_ TracAndStbScrnCnfg : 39|2@0+ (1,0) [0|3] "" XXX + SG_ BiFuelRflGaslinIndReq : 42|3@0+ (1,0) [0|7] "" XXX + SG_ AutoShtdwnIO : 43|1@0+ (1,0) [0|1] "" XXX + SG_ LnchCtrlBrkPresVal : 47|4@0+ (10,0) [0|150] "%" XXX + SG_ AutoShtdwnTmr : 55|8@0+ (1,0) [0|255] "min" XXX + SG_ FuelMdTrnstnIndReq : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2150244352 HMI_EngyConsmpHistGrph_1_LS: 8 XXX + SG_ EngyCnsHsGrphDspDtVal : 7|55@0+ (1,0) [0|0] "" XXX + SG_ ECHGDDV_Col1 : 2|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_EngyConsAvg : 7|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col3 : 8|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col2 : 13|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col4 : 19|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col6 : 25|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col5 : 30|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col7 : 36|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col9 : 42|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col8 : 47|5@0+ (1,0) [0|31] "" XXX + SG_ ECHGDDV_Col10 : 53|5@0+ (1,0) [0|31] "" XXX + +BO_ 2156953600 SSID_AMM_2_LS: 8 XXX + SG_ WiFiSSIDDgts9to16_Mp : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2151686144 SD_Card_LS: 2 XXX + SG_ SDCrdFullIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SDCrdErrIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ NoSDCrdPrIO : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155028480 Lane_Change_Threat_LS: 2 XXX + SG_ RgtLnChgThrt : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RtLnChngThrtAprchSpd : 15|8@0- (1,0) [-128|127] "km/h" XXX + +BO_ 2151915520 HMI_Display_LS: 8 XXX + SG_ AHDisbldDrOpnIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ AHDisbldStbltIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ AHAppBrkPedlIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ AHServcIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ShfToPrkBfExtngIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ AHEnbld : 5|1@0+ (1,0) [0|1] "" XXX + SG_ AHAct : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ESPDrvrIlkShfAtdIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ ESPTransMalfIO : 9|1@0+ (1,0) [0|1] "" XXX + SG_ ESPRngInvldReqIO : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ESPPrkInvldReqIO : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ESPHldShfLvrToEngRgIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ESPDrvrPrkIlkSftAtdIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ EngIntkArBstPrExtRngGroup : 14|15@0+ (1,0) [0|0] "" XXX + SG_ EngIntkArBstPrExtRng : 8|9@0+ (1,-110) [-110|401] "kPa" XXX + SG_ EngIntkArBstPrExtRngV : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ElcTransRngSlctVDA : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ElecShfRngDispRCExtd : 27|4@0+ (1,0) [0|15] "" XXX + SG_ ElecShfRngDisp : 31|4@0+ (1,0) [0|15] "" XXX + SG_ DrvEffInd : 39|8@0- (0.78125,0) [-100|99.21875] "%" XXX + SG_ ESPShfToDrvTryAgnIO : 43|1@0+ (1,0) [0|1] "" XXX + SG_ ESPTrnVehOffFrPrkIO : 44|1@0+ (1,0) [0|1] "" XXX + SG_ ESPTrnsCtlrMalfIO : 45|1@0+ (1,0) [0|1] "" XXX + SG_ ElcShfPriTwoGrsSlInRq : 47|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152153088 Right_Rear_Seat_Display_Stats_LS: 6 XXX + SG_ RRStCtlDispStat : 3|44@0+ (1,0) [0|0] "" XXX + SG_ RRSCDS_MassgTyp : 1|4@0+ (1,0) [0|15] "" XXX + SG_ RRSCDS_Massg : 3|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_HdrstFwdRrwd : 8|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_HdrstUpDn : 10|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_MassgIntsty : 13|3@0+ (1,0) [0|7] "" XXX + SG_ RRSCDS_HdrstTltFwdRr : 17|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_HdrstWngInOt : 19|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_HdrstFdRrUDn : 22|3@0+ (1,0) [0|7] "" XXX + SG_ RRSCDS_LmbrUDnFdRr : 25|3@0+ (1,0) [0|7] "" XXX + SG_ RRSCDS_LmbrFwdRr : 27|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_LmbrUpDwn : 29|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_UprShldrFdRr : 31|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_BkCshBlstInOt : 34|3@0+ (1,0) [0|7] "" XXX + SG_ RRSCDS_CshBlstrInOut : 36|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_BkBlstrInOut : 38|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_UnsdRsrvd : 42|3@0+ (1,0) [0|7] "" XXX + SG_ RRSCDS_DispReq : 43|1@0+ (1,0) [0|1] "" XXX + SG_ RRSCDS_DispSz : 45|2@0+ (1,0) [0|3] "" XXX + SG_ RRSCDS_CshLgAdjFdRr : 47|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152136704 Right_Rear_Seat_Massage_LS: 8 XXX + SG_ RRStMassgPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ RRSMP_Type2 : 3|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type1 : 7|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type4 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type3 : 15|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type6 : 19|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type5 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type8 : 27|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type7 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type10 : 35|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type9 : 39|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type12 : 43|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type11 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type14 : 51|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_Type13 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ RRSMP_UnsdRsrvd : 56|1@0+ (1,0) [0|1] "" XXX + SG_ RRSMP_MaxDispVal : 59|3@0+ (1,0) [0|7] "" XXX + SG_ RRSMP_Type15 : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2152120320 Right_Rear_Seat_Actuator_LS: 8 XXX + SG_ RRStActPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ RRSAP_HdrstUpDn : 3|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_Massg : 7|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_HdrstUpDnFdRr : 11|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_HdrstFwdRrwd : 15|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_HdrstTltFwdRr : 19|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_HdrstWngsInOut : 23|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_LmbrUpDwn : 27|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_UprShldrFwdRr : 31|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_LmbrUpDnFdRr : 35|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_LmbrFwdRr : 39|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_CshBlstrInOut : 43|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_BkBlstrInOut : 47|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_CshLgthAdjFdRr : 51|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_BkCshBlstrInOut : 55|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_UnsdRsrvd : 59|4@0+ (1,0) [0|15] "" XXX + SG_ RRSAP_DispSz : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2152103936 Left_Rear_Seat_Display_Status_LS: 6 XXX + SG_ LRStCtlDispStat : 3|44@0+ (1,0) [0|0] "" XXX + SG_ LRSCDS_MassgTyp : 1|4@0+ (1,0) [0|15] "" XXX + SG_ LRSCDS_Massg : 3|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_HdrstFwdRrwd : 8|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_HdrstUpDn : 10|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_MassgIntsty : 13|3@0+ (1,0) [0|7] "" XXX + SG_ LRSCDS_HdrstTltFwdRr : 17|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_HdrstWngInOt : 19|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_HdrstFdRrUDn : 22|3@0+ (1,0) [0|7] "" XXX + SG_ LRSCDS_LmbrUDnFdRr : 25|3@0+ (1,0) [0|7] "" XXX + SG_ LRSCDS_LmbrFwdRr : 27|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_LmbrUpDwn : 29|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_UprShldrFdRr : 31|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_BkCshBlstInOt : 34|3@0+ (1,0) [0|7] "" XXX + SG_ LRSCDS_CshBlstrInOut : 36|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_BkBlstrInOut : 38|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_UnsdRsrvd : 42|3@0+ (1,0) [0|7] "" XXX + SG_ LRSCDS_DispReq : 43|1@0+ (1,0) [0|1] "" XXX + SG_ LRSCDS_DispSz : 45|2@0+ (1,0) [0|3] "" XXX + SG_ LRSCDS_CshLgAdjFdRr : 47|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152087552 Left_Rear_Seat_Massage_LS: 8 XXX + SG_ LRStMassgPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ LRSMP_Type2 : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type1 : 7|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type4 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type3 : 15|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type6 : 19|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type5 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type8 : 27|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type7 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type10 : 35|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type9 : 39|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type12 : 43|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type11 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type14 : 51|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_Type13 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ LRSMP_UnsdRsrvd : 56|1@0+ (1,0) [0|1] "" XXX + SG_ LRSMP_MaxDispVal : 59|3@0+ (1,0) [0|7] "" XXX + SG_ LRSMP_Type15 : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2152071168 Left_Rear_Seat_Actuator_LS: 8 XXX + SG_ LRStActPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ LRSAP_HdrstUpDn : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_Massg : 7|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_HdrstUpDnFdRr : 11|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_HdrstFwdRrwd : 15|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_HdrstTltFwdRr : 19|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_HdrstWngsInOut : 23|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_LmbrUpDwn : 27|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_UprShldrFwdRr : 31|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_LmbrUpDnFdRr : 35|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_LmbrFwdRr : 39|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_CshBlstrInOut : 43|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_BkBlstrInOut : 47|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_CshLgthAdjFdRr : 51|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_BkCshBlstrInOut : 55|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_UnsdRsrvd : 59|4@0+ (1,0) [0|15] "" XXX + SG_ LRSAP_DispSz : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2153947136 Remote_Reflash_Stat_LS: 1 XXX + SG_ RmtRflshMdAct : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2152628224 OnBoard_Tester_Response_LS: 2 XXX + SG_ OBTCResp : 2|11@0+ (1,0) [0|0] "" XXX + SG_ OBTCR_Stat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ OBTCR_ReqstrID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ OBTCMstrStat : 5|3@0+ (1,0) [0|7] "" XXX + +BO_ 2152112128 Performanc_Mode_Vis_Scrn_Stat_LS: 5 XXX + SG_ PerfMdVislztnScrnStat : 0|33@0+ (1,0) [0|0] "" XXX + SG_ PMVSS_Snd : 0|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Trans : 10|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Eng : 13|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Drvln : 17|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Susp : 20|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Strng : 23|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_PsngrSeat : 24|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_DrvrSeat : 27|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_AdptCrsCnt : 30|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Disps : 34|3@0+ (1,0) [0|7] "" XXX + SG_ PMVSS_Exhst : 37|3@0+ (1,0) [0|7] "" XXX + SG_ PerfMdMainMenuType : 3|3@0+ (1,0) [0|7] "" XXX + +BO_ 2152775680 Front_360_Camera_On_LS: 3 XXX + SG_ DispFrt360CamOn : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RrPedDetCstStAvl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RrPedDetCstStVal : 4|3@0+ (1,0) [0|7] "" XXX + SG_ RrPdDetHptcStVbRqSeqN : 6|2@0+ (1,0) [0|3] "" XXX + SG_ TrgdVidRecFetrPrsnt : 7|1@0+ (1,0) [0|1] "" XXX + SG_ RrPdDetHptcStVbRq : 13|6@0+ (1,0) [0|63] "Pulse" XXX + SG_ DispTrgdVidOn : 14|1@0+ (1,0) [0|1] "" XXX + SG_ a_360DegVidFetrPrsnt : 15|1@0+ (1,0) [0|1] "" XXX + SG_ DispSmrtTwVidOn : 16|1@0+ (1,0) [0|1] "" XXX + SG_ RrPedDetCstAvail : 23|7@0+ (1,0) [0|0] "" XXX + SG_ RPDCA_Resrv3Avail : 17|1@0+ (1,0) [0|1] "" XXX + SG_ RPDCA_Resrv2Avail : 18|1@0+ (1,0) [0|1] "" XXX + SG_ RPDCA_Resrv1Avail : 19|1@0+ (1,0) [0|1] "" XXX + SG_ RPDCA_AlrtBrkAvail : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RPDCA_AlrtAvail : 21|1@0+ (1,0) [0|1] "" XXX + SG_ RPDCA_OnAvail : 22|1@0+ (1,0) [0|1] "" XXX + SG_ RPDCA_OfAvail : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 2153857024 Teen_Driver_Event_Report_2_LS: 8 XXX + SG_ TnDrvRptCrdAvlDspDat : 6|13@0+ (1,0) [0|0] "" XXX + SG_ TDRCADD_FCHdwyAlrt : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_ABSAtvEvt : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_StCtrlEvnts : 2|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_TrCtrlEvnts : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_OvSpdEvnt : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_DistDrvn : 5|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_MaxSpd : 6|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_LDWEvnts : 10|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_WOTEvnts : 11|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_DrwDrvAlrt : 12|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_FCMBrEvts : 13|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_RCMBrEvts : 14|1@0+ (1,0) [0|1] "" XXX + SG_ TDRCADD_FCImntAlrts : 15|1@0+ (1,0) [0|1] "" XXX + SG_ TeenDrvWOTEvntsRpt : 9|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TnDrvABSAtvEvntsRpt : 31|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TnDrvStblCtrlEvntsRpt : 37|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TnDrvDrowDrvAlrtsRpt : 43|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TnDrvTrCtrlEvntsRpt : 49|10@0+ (1,0) [0|1023] "counts" XXX + +BO_ 2153865216 Teen_Driver_Customization_Req_LS: 4 XXX + SG_ TeenDrvReq : 3|4@0+ (1,0) [0|15] "" XXX + SG_ TDOvSpdWrnCstStReq : 12|5@0+ (1,0) [0|0] "" XXX + SG_ TDOWCSR_DecSwAct : 8|1@0+ (1,0) [0|1] "" XXX + SG_ TDOWCSR_IncSwAct : 9|1@0+ (1,0) [0|1] "" XXX + SG_ TDOWCSR_StatReq : 12|3@0+ (1,0) [0|7] "" XXX + SG_ TnDrvSpdLmtCstStReq : 15|3@0+ (1,0) [0|7] "" XXX + SG_ TeenDrvPinCd : 23|16@0+ (1,0) [0|39321] "" XXX + +BO_ 2153840640 Teen_Driver_Event_Report_1_LS: 8 XXX + SG_ TDFwdClnHdwyAlrtsRpt : 5|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TnDrvDRLOffUnbIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvALCOffUnbIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ TDFwdClnImntAlrtsRpt : 11|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TDFwdClnMtgnBrEvRpt : 17|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TDRevClnMtgnBrEvRpt : 39|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TeenDrvMaxSpdRpt : 45|12@0+ (0.0625,0) [0|255.9375] "km/h" XXX + SG_ TeenDrvLDWEvntsRpt : 49|10@0+ (1,0) [0|1023] "counts" XXX + +BO_ 2153824256 Teen_Driver_Control_Info_LS: 8 XXX + SG_ TnDrvSpdLmtCstCrStVl : 2|11@0+ (1,0) [0|0] "" XXX + SG_ TDSLCCSV_SpLmtStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ TDSLCCSV_SpLmDisVl : 15|8@0+ (2,0) [0|510] "km/h" XXX + SG_ TnDrvSpdLmtCstStAvl : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvOvrSpdIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvGapAdjUnbIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ TeenDrvPINStrd : 6|1@0+ (1,0) [0|1] "" XXX + SG_ TeenDrvFtrAvl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ TDOvSpdWrnCstCrStVl : 22|15@0+ (1,0) [0|0] "" XXX + SG_ TDOWCCSV_CrStVl : 19|12@0+ (0.0625,0) [0|255.9375] "km/h" XXX + SG_ TDOWCCSV_CrStat : 22|3@0+ (1,0) [0|7] "" XXX + SG_ TDOvSpdWrnCstStAvl : 23|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvOvSpdEvntsRpt : 33|10@0+ (1,0) [0|1023] "counts" XXX + SG_ TeenDrvRsp : 37|4@0+ (1,0) [0|15] "" XXX + SG_ TeenDrvAct : 38|1@0+ (1,0) [0|1] "" XXX + SG_ TeenDrvAccelLimIO : 39|1@0+ (1,0) [0|1] "" XXX + SG_ TeenDrvDistDrvnRpt : 55|16@0+ (1,0) [0|65535] "km" XXX + +BO_ 2155151360 Psngr_Seat_Massage_Priority_LS: 8 XXX + SG_ PsngrStMassgPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ PSMP_Type2 : 3|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type1 : 7|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type4 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type3 : 15|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type6 : 19|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type5 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type8 : 27|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type7 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type10 : 35|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type9 : 39|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type12 : 43|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type11 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type14 : 51|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_Type13 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ PSMP_UnsdRsrvd : 56|1@0+ (1,0) [0|1] "" XXX + SG_ PSMP_MaxDispVal : 59|3@0+ (1,0) [0|7] "" XXX + SG_ PSMP_Type15 : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2155134976 Psngr_Seat_Control_Disp_Stat_LS: 6 XXX + SG_ PsngrStCtlDispStat : 3|44@0+ (1,0) [0|0] "" XXX + SG_ PSCDS_MassgTyp : 1|4@0+ (1,0) [0|15] "" XXX + SG_ PSCDS_Massg : 3|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_HdrstFwdRrwd : 8|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_HdrstUpDn : 10|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_MassgIntsty : 13|3@0+ (1,0) [0|7] "" XXX + SG_ PSCDS_HdrstTltFwdRr : 17|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_HdrstWngInOt : 19|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_HdrstUDnFdRr : 22|3@0+ (1,0) [0|7] "" XXX + SG_ PSCDS_LmbrUDnFdRr : 25|3@0+ (1,0) [0|7] "" XXX + SG_ PSCDS_LmbrFwdRr : 27|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_LmbrUpDwn : 29|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_UprShldrFdRr : 31|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_BkCshBlstInOt : 34|3@0+ (1,0) [0|7] "" XXX + SG_ PSCDS_CshBlstrInOut : 36|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_BkBlstrInOut : 38|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_UnsdRsrvd : 42|3@0+ (1,0) [0|7] "" XXX + SG_ PSCDS_DispReq : 43|1@0+ (1,0) [0|1] "" XXX + SG_ PSCDS_DispSz : 45|2@0+ (1,0) [0|3] "" XXX + SG_ PSCDS_CshLgAdjFdRr : 47|2@0+ (1,0) [0|3] "" XXX + SG_ PsngrSetRrwdMvmnt : 6|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155118592 Psngr_Seat_Actuator_Priority_LS: 8 XXX + SG_ PsngrStActPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ PSAP_HdrstUpDn : 3|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_Massg : 7|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_HdrstUpDnFdRr : 11|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_HdrstFwdRrwd : 15|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_HdrstTltFwdRr : 19|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_HdrstWngsInOut : 23|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_LmbrUpDwn : 27|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_UprShldrFwdRr : 31|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_LmbrUpDnFdRr : 35|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_LmbrFwdRr : 39|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_CshBlstrInOut : 43|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_BkBlstrInOut : 47|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_CshLgthAdjFdRr : 51|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_BkCshBlstrInOut : 55|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_UnsdRsrvd : 59|4@0+ (1,0) [0|15] "" XXX + SG_ PSAP_DispSz : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2155102208 Driver_Seat_Massage_Priority_LS: 8 XXX + SG_ DrvStMassgPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ DSMP_Type2 : 3|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type1 : 7|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type4 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type3 : 15|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type6 : 19|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type5 : 23|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type8 : 27|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type7 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type10 : 35|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type9 : 39|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type12 : 43|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type11 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type14 : 51|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_Type13 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ DSMP_UnsdRsrvd : 56|1@0+ (1,0) [0|1] "" XXX + SG_ DSMP_MaxDispVal : 59|3@0+ (1,0) [0|7] "" XXX + SG_ DSMP_Type15 : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2155085824 Driver_Seat_Control_Disp_Stat_LS: 8 XXX + SG_ DrvStCtlDispStat : 3|44@0+ (1,0) [0|0] "" XXX + SG_ DSCDS_MassgTyp : 1|4@0+ (1,0) [0|15] "" XXX + SG_ DSCDS_Massg : 3|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_HdrstFwdRrwd : 8|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_HdrstUpDn : 10|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_MassgIntsty : 13|3@0+ (1,0) [0|7] "" XXX + SG_ DSCDS_HdrstTltFwdRr : 17|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_HdrstWngInOt : 19|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_HdrstUDnFdRr : 22|3@0+ (1,0) [0|7] "" XXX + SG_ DSCDS_LmbrUDnFdRr : 25|3@0+ (1,0) [0|7] "" XXX + SG_ DSCDS_LmbrFwdRr : 27|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_LmbrUpDwn : 29|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_UprShldrFdRr : 31|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_BkCshBlstInOt : 34|3@0+ (1,0) [0|7] "" XXX + SG_ DSCDS_CshBlstrInOut : 36|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_BkBlstrInOut : 38|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_UnsdRsrvd : 42|3@0+ (1,0) [0|7] "" XXX + SG_ DSCDS_DispReq : 43|1@0+ (1,0) [0|1] "" XXX + SG_ DSCDS_DispSz : 45|2@0+ (1,0) [0|3] "" XXX + SG_ DSCDS_CshLgAdjFdRr : 47|2@0+ (1,0) [0|3] "" XXX + SG_ CPMAPINFO4 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ StrgColCommsFlt : 7|2@0+ (1,0) [0|3] "" XXX + SG_ StrgColInOutPos : 55|8@0+ (1,0) [0|255] "" XXX + SG_ StrgColUpDwnPos : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2155069440 Driver_Seat_Actuator_Priority_LS: 8 XXX + SG_ DrvStActPrty : 7|64@0+ (1,0) [0|0] "" XXX + SG_ DSAP_HdrstUpDn : 3|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_Massg : 7|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_HdrstUpDnFdRr : 11|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_HdrstFwdRrwd : 15|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_HdrstTltFwdRr : 19|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_HdrstWngsInOut : 23|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_LmbrUpDwn : 27|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_UprShldrFwdRr : 31|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_LmbrUpDnFdRr : 35|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_LmbrFwdRr : 39|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_CshBlstrInOut : 43|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_BkBlstrInOut : 47|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_CshLgthAdjFdRr : 51|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_BkCshBlstrInOut : 55|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_UnsdRsrvd : 59|4@0+ (1,0) [0|15] "" XXX + SG_ DSAP_DispSz : 63|4@0+ (1,0) [0|15] "" XXX + +BO_ 2156937216 PassPhrase_Digits_17_to_24_LS: 8 XXX + SG_ WiFiPssPhrsDgts17to24 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156929024 PassPhrase_Digits_9_to_16_LS: 8 XXX + SG_ WiFiPssPhrsDgts9to16 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156920832 PassPhrase_Digits_1_to_8_LS: 8 XXX + SG_ WiFiPssPhrsDgts1to8 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156871680 SSID_Digits_17_to_24_LS: 8 XXX + SG_ WiFiSSIDDgts17to24 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156863488 SSID_Digits_9_to_16_LS: 8 XXX + SG_ WiFiSSIDDgts9to16 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156855296 SSID_Digits_1_to_8_LS: 8 XXX + SG_ WiFiSSIDDgts1to8 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2152480768 Perfr_Data_Recorder_Lap_Info_LS: 6 XXX + SG_ PerfDatRecBstLpInfo : 2|19@0+ (1,0) [0|0] "" XXX + SG_ PDRBLI_BstLpTmMins : 2|6@0+ (1,0) [0|63] "min" XXX + SG_ PDRBLI_BstLpTmSecs : 12|6@0+ (1,0) [0|63] "sec" XXX + SG_ PDRBLI_BstLpTm100s : 22|7@0+ (0.01,0) [0|1.27] "sec" XXX + SG_ PerfDatRecLstLpInfo : 26|19@0+ (1,0) [0|0] "" XXX + SG_ PDRLLI_LstLpTmMins : 26|6@0+ (1,0) [0|63] "min" XXX + SG_ PDRLLI_LstLpTmSecs : 36|6@0+ (1,0) [0|63] "sec" XXX + SG_ PDRLLI_LstLpTm100s : 46|7@0+ (0.01,0) [0|1.27] "sec" XXX + +BO_ 2152497152 Perf_Data_Recroder_RT_Info_LS: 4 XXX + SG_ PerfDatRecRltmInfo : 1|26@0+ (1,0) [0|0] "" XXX + SG_ PDRRI_CrLpTmMins : 1|6@0+ (1,0) [0|63] "min" XXX + SG_ PDRRI_CrLpTmSecs : 11|6@0+ (1,0) [0|63] "" XXX + SG_ PDRRI_LpDiffTmSecs : 17|6@0+ (1,0) [0|63] "sec" XXX + SG_ PDRRI_CrLpTm10sSec : 21|4@0+ (0.1,0) [0|1.5] "sec" XXX + SG_ PDRRI_LpDiffTm10s : 27|4@0+ (0.1,0) [0|1.5] "sec" XXX + +BO_ 2153791488 ARB_State_LS: 1 XXX + SG_ ArtcldRngBrdSt : 2|3@0+ (1,0) [0|7] "" XXX + +BO_ 2149883904 BluetoothTetheringPairingRsp_LS: 7 XXX + SG_ BTTethrngPrngRsp : 4|53@0+ (1,0) [0|0] "" XXX + SG_ BTPR_RspInfoAvail : 0|1@0+ (1,0) [0|1] "" XXX + SG_ BTPR_RspStat : 4|4@0+ (1,0) [0|15] "" XXX + SG_ BTPR_RspVal : 15|48@0+ (1,0) [0|281474976710655] "" XXX + +BO_ 2150252544 HMI_EngyConsmpHistGrph_LS: 8 XXX + SG_ EngyConsmpHistGrph : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ECHG_EngyCnsmdAvg : 4|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_MeasUnit : 7|3@0+ (1,0) [0|7] "" XXX + SG_ ECHG_Column02 : 10|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column01 : 15|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column04 : 16|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column03 : 21|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column05 : 27|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column07 : 33|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column06 : 38|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column08 : 44|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column10 : 50|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_Column09 : 55|5@0+ (1,0) [0|31] "" XXX + SG_ ECHG_YAxisMaxVal : 58|3@0+ (1,0) [0|7] "" XXX + SG_ ECHG_XAxisTkMrkIntvl : 61|3@0+ (1,0) [0|7] "" XXX + +BO_ 2150391808 HMI_Hourmeter_Data_LS: 6 XXX + SG_ EngIdlAtvTm : 7|24@0+ (1,0) [0|16777215] "min" XXX + SG_ EngRunAtvTm : 31|24@0+ (1,0) [0|16777215] "min" XXX + +BO_ 2155913216 Diesel_Information_2_LS: 7 XXX + SG_ DslExhFldRmngDstHRsGroup : 7|16@0+ (1,0) [0|0] "" XXX + SG_ DslExhFldRmngDstHRs : 6|15@0+ (2,0) [0|65534] "km" XXX + SG_ DslExhFldRmngDstHRsV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ DslExhFluidLvlPrcntGroup : 16|9@0+ (1,0) [0|0] "" XXX + SG_ DslExhFluidLvlPrcntV : 16|1@0+ (1,0) [0|1] "" XXX + SG_ DslExhFluidLvlPrcnt : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DslEmnsOBDMrkt : 18|2@0+ (1,0) [0|3] "" XXX + SG_ PedFrndlyAlrtCsCrStVal : 21|3@0+ (1,0) [0|7] "" XXX + SG_ PedFrndlyAlrtCsSetAvl : 22|1@0+ (1,0) [0|1] "" XXX + SG_ PedFrndlyAlrtStat : 39|24@0+ (1,0) [0|0] "" XXX + SG_ PFAS_PFACrsOvrSpd : 34|8@0+ (1,0) [0|255] "km/h" XXX + SG_ PFAS_PFARevSnd : 36|2@0+ (1,0) [0|3] "" XXX + SG_ PFAS_PFAFwdSnd : 38|2@0+ (1,0) [0|3] "" XXX + SG_ PFAS_PFASndGenEn : 39|1@0+ (1,0) [0|1] "" XXX + SG_ PFAS_PFASndVolCtrl : 42|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ PFAS_SrvPedAlrtIO : 48|1@0+ (1,0) [0|1] "" XXX + SG_ PFAS_PFASysStat : 50|2@0+ (1,0) [0|3] "" XXX + +BO_ 2034 CCP_Data_Transmission_Object_LS: 8 XXX + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2032 CCP_Command_Receive_Object_LS: 8 XXX + SG_ DgnInf : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2152095744 HSGMLAN_Customization_Setings_LS: 5 XXX + SG_ DrvlnPerfMdCustAvl : 5|6@0+ (1,0) [0|0] "" XXX + SG_ DPMCA_DrvlPrfMd6Avl : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DrvlPrfMd5Avl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DrvlPrfMd4Avl : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DrvlPrfMd3Avl : 3|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DrvlPrfMd2Avl : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DrvlPrfMd1Avl : 5|1@0+ (1,0) [0|1] "" XXX + SG_ DispPerfCustMdAvl : 13|6@0+ (1,0) [0|0] "" XXX + SG_ DPMCA_DispPrfMd6Avl : 8|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DispPrfMd5Avl : 9|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DispPrfMd4Avl : 10|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DispPrfMd3Avl : 11|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DispPrfMd2Avl : 12|1@0+ (1,0) [0|1] "" XXX + SG_ DPMCA_DispPrfMd1Avl : 13|1@0+ (1,0) [0|1] "" XXX + SG_ SndPerfMdCustAvl : 21|6@0+ (1,0) [0|0] "" XXX + SG_ SPMCA_SndPrfMd6Avl : 16|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SndPrfMd5Avl : 17|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SndPrfMd4Avl : 18|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SndPrfMd3Avl : 19|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SndPrfMd2Avl : 20|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SndPrfMd1Avl : 21|1@0+ (1,0) [0|1] "" XXX + SG_ StrPerfMdCustAvl : 29|6@0+ (1,0) [0|0] "" XXX + SG_ SPMCA_StrPrfMd6Avl : 24|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_StrPrfMd5Avl : 25|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_StrPrfMd4Avl : 26|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_StrPrfMd3Avl : 27|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_StrPrfMd2Avl : 28|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_StrPrfMd1Avl : 29|1@0+ (1,0) [0|1] "" XXX + SG_ SusPerfMdCustAvl : 37|6@0+ (1,0) [0|0] "" XXX + SG_ SPMCA_SusPrfMd6Avl : 32|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SusPrfMd5Avl : 33|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SusPrfMd4Avl : 34|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SusPrfMd3Avl : 35|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SusPrfMd2Avl : 36|1@0+ (1,0) [0|1] "" XXX + SG_ SPMCA_SusPrfMd1Avl : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 2156945408 SSID_AMM_1_LS: 8 XXX + SG_ WiFiSSIDDgts1to8_Mp : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2152611840 OnBoard_Tester_Request_LS: 2 XXX + SG_ OBTCReq : 4|5@0+ (1,0) [0|0] "" XXX + SG_ OBTCR_Prty : 3|4@0+ (1,0) [0|15] "" XXX + SG_ OBTCR_Actv : 4|1@0+ (1,0) [0|1] "" XXX + SG_ OBTCReqstrStat : 7|3@0+ (1,0) [0|7] "" XXX + SG_ OBTCReqstrID : 15|8@0+ (1,0) [0|255] "" XXX + +BO_ 2153308160 Hyb_Redundant_Batt_Data2_LS: 4 XXX + SG_ RdHVltBatPckCrntGroup : 6|15@0+ (1,0) [0|0] "" XXX + SG_ RdHVltBatPckCrnt : 4|13@0- (0.15,0) [-614.4|614.25] "A" XXX + SG_ RdHVltBatPckCrntV : 5|1@0+ (1,0) [0|1] "" XXX + SG_ RdHVltBatPckCrntM : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RdHVltBatPckVltGroup : 21|14@0+ (1,0) [0|0] "" XXX + SG_ RdHVltBatPckVlt : 19|12@0+ (0.125,0) [0|511.875] "V" XXX + SG_ RdHVltBatPckVltV : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RdHVltBatPckVltM : 21|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155970560 HVAC_PowerManager_Status_LS: 1 XXX + SG_ ClmCntLdShdLvlRq : 3|4@0+ (1,0) [0|15] "" XXX + SG_ ClmCntBatSaverIO : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151178240 Lighting_Customization_Rqst_1_LS: 4 XXX + SG_ LtRtHnTrGPSCstStRq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ LtRtHnTrCstStReq : 5|3@0+ (1,0) [0|7] "" XXX + SG_ AutHgBmAsSnCsStRq : 10|3@0+ (1,0) [0|7] "" XXX + SG_ AutHgBmAstCstStRq : 13|3@0+ (1,0) [0|7] "" XXX + SG_ AdpHgBmAsSnCsStRq : 18|3@0+ (1,0) [0|7] "" XXX + SG_ AdpHgBmAstCstStRq : 21|3@0+ (1,0) [0|7] "" XXX + SG_ AFLGPSCstStReq : 26|3@0+ (1,0) [0|7] "" XXX + SG_ AFLCstStReq : 29|3@0+ (1,0) [0|7] "" XXX + +BO_ 2154790912 Lighting_Customization_Info_2_LS: 2 XXX + SG_ AutHgBmAsCsCrStVal : 2|3@0+ (1,0) [0|7] "" XXX + SG_ AutHgBmAsSnCsCrStVa : 5|3@0+ (1,0) [0|7] "" XXX + SG_ AutHgBmAsCsStAvl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ AutHgBmAsSnCsStAvl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ AdpHgBmAsCsCrStVal : 10|3@0+ (1,0) [0|7] "" XXX + SG_ AdpHgBmAsSnCsCrStVal : 13|3@0+ (1,0) [0|7] "" XXX + SG_ AdpHgBmAsCsStAvl : 14|1@0+ (1,0) [0|1] "" XXX + SG_ AdpHgBmAsSnCsStAvl : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151292928 V2V_Customization_Menu_LS: 5 XXX + SG_ TrfRdsdInfCsStAvail : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CntdVehBrkAltCsStAvl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ IntrStopAlrtCsSetAvl : 2|1@0+ (1,0) [0|1] "" XXX + SG_ IntrStAlrtCsCrSetVal : 5|3@0+ (1,0) [0|7] "" XXX + SG_ TrfRdsdInfCsCrStVal : 10|3@0+ (1,0) [0|7] "" XXX + SG_ CntdVehBrAltCsCrStVal : 13|3@0+ (1,0) [0|7] "" XXX + SG_ IntrStAlrtCsAvail : 22|7@0+ (1,0) [0|0] "" XXX + SG_ ISACA_Resrv4Avail : 16|1@0+ (1,0) [0|1] "" XXX + SG_ ISACA_Resrv3Avail : 17|1@0+ (1,0) [0|1] "" XXX + SG_ ISACA_Resrv2Avail : 18|1@0+ (1,0) [0|1] "" XXX + SG_ ISACA_Resrv1Avail : 19|1@0+ (1,0) [0|1] "" XXX + SG_ ISACA_AlrtBrkAvail : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ISACA_AlrtAvail : 21|1@0+ (1,0) [0|1] "" XXX + SG_ ISACA_OfAvail : 22|1@0+ (1,0) [0|1] "" XXX + SG_ CntdVehBrkAlrtCsAvail : 30|7@0+ (1,0) [0|0] "" XXX + SG_ CVBACA_Resrv5Avail : 24|1@0+ (1,0) [0|1] "" XXX + SG_ CVBACA_Resrv4Avail : 25|1@0+ (1,0) [0|1] "" XXX + SG_ CVBACA_Resrv3Avail : 26|1@0+ (1,0) [0|1] "" XXX + SG_ CVBACA_Resrv2Avail : 27|1@0+ (1,0) [0|1] "" XXX + SG_ CVBACA_Resrv1Avail : 28|1@0+ (1,0) [0|1] "" XXX + SG_ CVBACA_OnAvail : 29|1@0+ (1,0) [0|1] "" XXX + SG_ CVBACA_OfAvail : 30|1@0+ (1,0) [0|1] "" XXX + SG_ TrfRdsdInfCsAvail : 38|7@0+ (1,0) [0|0] "" XXX + SG_ TRICA_Resrv5Avail : 32|1@0+ (1,0) [0|1] "" XXX + SG_ TRICA_Resrv4Avail : 33|1@0+ (1,0) [0|1] "" XXX + SG_ TRICA_Resrv3Avail : 34|1@0+ (1,0) [0|1] "" XXX + SG_ TRICA_Resrv2Avail : 35|1@0+ (1,0) [0|1] "" XXX + SG_ TRICA_Resrv1Avail : 36|1@0+ (1,0) [0|1] "" XXX + SG_ TRICA_OnAvail : 37|1@0+ (1,0) [0|1] "" XXX + SG_ TRICA_OfAvail : 38|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151464960 V2V_Warnings_LS: 5 XXX + SG_ V2VWrngIndReq : 4|5@0+ (1,0) [0|31] "" XXX + SG_ V2VWrngDirctn : 7|3@0+ (1,0) [0|7] "" XXX + SG_ V2VWrngDistRemng : 9|10@0+ (1,0) [0|1023] "" XXX + SG_ V2VTrfLghtInfo : 28|13@0+ (1,0) [0|0] "" XXX + SG_ V2VTLI_TrfLghtTmPhsSw : 28|6@0+ (1,0) [0|63] "" XXX + SG_ V2VTLI_TrfLghtMntngDirctn : 32|1@0+ (1,0) [0|1] "" XXX + SG_ V2VTLI_TrfLghtValDirctn : 34|2@0+ (1,0) [0|3] "" XXX + SG_ V2VTLI_TrfLghtPhsArivl : 36|2@0+ (1,0) [0|3] "" XXX + SG_ V2VTLI_TrfLghtActlPhs : 38|2@0+ (1,0) [0|3] "" XXX + SG_ V2VSrvIndReq : 30|2@0+ (1,0) [0|3] "" XXX + +BO_ 2151448576 V2V_Seat_Vib_Request_LS: 3 XXX + SG_ V2VSysHptcStVibReq : 5|6@0+ (1,0) [0|63] "" XXX + SG_ V2VSysHptStVibRqSN : 7|2@0+ (1,0) [0|3] "" XXX + SG_ V2VSyLftHptStVbRq : 13|6@0+ (1,0) [0|63] "" XXX + SG_ V2VSyLftHptStVbRqSN : 15|2@0+ (1,0) [0|3] "" XXX + SG_ V2VSyRghtHptStVbRq : 21|6@0+ (1,0) [0|63] "" XXX + SG_ V2VSyRghtHptStVbRqSN : 23|2@0+ (1,0) [0|3] "" XXX + +BO_ 2153930752 Lane_Centering_Convenience_LS: 3 XXX + SG_ LCWrnIndReq : 4|5@0+ (1,0) [0|31] "" XXX + SG_ LCCDrvrAwrnsIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LnCntrVhlStpd : 6|1@0+ (1,0) [0|1] "" XXX + SG_ LnCntrNonRspDrvrCnd : 7|1@0+ (1,0) [0|1] "" XXX + SG_ LCConvMsgIndreq : 12|5@0+ (1,0) [0|31] "" XXX + SG_ LCCIndReq : 15|3@0+ (1,0) [0|7] "" XXX + SG_ LnCntrEsclnStat : 17|2@0+ (1,0) [0|3] "" XXX + SG_ LnCntrSpchPrmtReq : 19|2@0+ (1,0) [0|3] "" XXX + SG_ LnCntrngCtlIcnLoctn : 23|4@0- (1,0) [-8|7] "" XXX + +BO_ 2153889792 Lane_Centering_Arrow_LS: 5 XXX + SG_ LCArrwBlk1Act : 0|1@0+ (1,0) [0|1] "" XXX + SG_ LCArrwBlk2Act : 1|1@0+ (1,0) [0|1] "" XXX + SG_ LCArrwBlk3Act : 2|1@0+ (1,0) [0|1] "" XXX + SG_ LCArrwBlk4Act : 3|1@0+ (1,0) [0|1] "" XXX + SG_ LCArrwBlk5Act : 4|1@0+ (1,0) [0|1] "" XXX + SG_ LCArrwBlk2Offst : 15|8@0- (1,0) [-128|127] "" XXX + SG_ LCArrwBlk3Offst : 23|8@0- (1,0) [-128|127] "" XXX + SG_ LCArrwBlk4Offst : 31|8@0- (1,0) [-128|127] "" XXX + SG_ LCArrwBlk5Offst : 39|8@0- (1,0) [-128|127] "" XXX + +BO_ 2153914368 Energy_Usage_LS: 7 XXX + SG_ EngyUsgScrScal : 7|56@0+ (1,0) [0|0] "" XXX + SG_ EUSS_OTEgUgScrMxScVal : 0|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_OTEgUgScrMnScVal : 7|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_ITEgUgScrMnScVal : 9|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_ITEgUgScrMxScVal : 18|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_TcEgUgScrMnScVal : 27|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_TcEgUgScrMxScVal : 36|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_TrEgUgScrMnScVal : 45|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUSS_TrEgUgScrMxScVal : 54|7@0- (0.1,0) [-5|5] "" XXX + +BO_ 2151882752 PTO_Customization_Request_LS: 3 XXX + SG_ PTOTpStpSpdCsStReq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ PTOEngRnTmrCsStRq : 11|4@0+ (1,0) [0|15] "" XXX + SG_ PTOStdbySpdCsStReq : 14|3@0+ (1,0) [0|7] "" XXX + SG_ PTOSet1SpdCsStReq : 19|4@0+ (1,0) [0|15] "" XXX + SG_ PTOSet2SpdCsStReq : 23|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151899136 PTO_Status_LS: 5 XXX + SG_ PTORelBrkPedIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ PTORelAccPedIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PTORedEngSpdIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PTOPrsRelCltPedIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PTOPrsRelBrkPedIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PTOEngmntStatInd : 6|2@0+ (1,0) [0|3] "" XXX + SG_ PTODisengCrsCntlIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ PTOSet1SpdCsStAvl : 8|1@0+ (1,0) [0|1] "" XXX + SG_ PTOSet2SpdCsStAvl : 9|1@0+ (1,0) [0|1] "" XXX + SG_ PTOTpStpSpdCsStAvl : 10|1@0+ (1,0) [0|1] "" XXX + SG_ PTOEngRnTmrCsStAvl : 11|1@0+ (1,0) [0|1] "" XXX + SG_ PTOStdbySpdCsStAvl : 12|1@0+ (1,0) [0|1] "" XXX + SG_ PTOTransInGearIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ PTOSetPrkBrkIO : 14|1@0+ (1,0) [0|1] "" XXX + SG_ PTORelCltPedIO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ PTOStdbSpdCsCrStVal : 18|3@0+ (1,0) [0|7] "" XXX + SG_ PTOGroup : 20|2@0+ (1,0) [0|0] "" XXX + SG_ PTOVDA : 19|1@0+ (1,0) [0|1] "" XXX + SG_ PTOVDM : 20|1@0+ (1,0) [0|1] "" XXX + SG_ PTOManTransInGrIO : 21|1@0+ (1,0) [0|1] "" XXX + SG_ PTOAccelUpnBrkRelIO : 22|1@0+ (1,0) [0|1] "" XXX + SG_ PTOEngUpnBrkRelIO : 23|1@0+ (1,0) [0|1] "" XXX + SG_ PTOTpStSpdCsCrStVal : 26|3@0+ (1,0) [0|7] "" XXX + SG_ PTOEnRnTmCsCrStVal : 30|4@0+ (1,0) [0|15] "" XXX + SG_ PTOServIndOn : 31|1@0+ (1,0) [0|1] "" XXX + SG_ PTOSet1SpdCsCrStVal : 35|4@0+ (1,0) [0|15] "" XXX + SG_ PTOSet2SpdCsCrStVal : 39|4@0+ (1,0) [0|15] "" XXX + +BO_ 2150580224 HMI_UtlChrgIntrfr_Indication_LS: 5 XXX + SG_ CstmrNonUsblSOCGroup : 1|10@0+ (1,0) [0|0] "" XXX + SG_ CstmrNonUsblSOCV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ CstmrNonUsblSOC : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ CstNonUsbSOCDspLvl : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ PrpDspTtlPwrLvlPct : 24|9@0- (0.392157,0) [-100.392192|100.000035] "%" XXX + +BO_ 2151735296 Rear_Cross_Traffic_Alert_Ind_LS: 1 XXX + SG_ RrCrsTrfcAlrtOffIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ LnChgAlrtOffIndOn : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RtRrCrsTrfcAlrtEnbld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RtSBZAlrtEnbld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ RtLnChgAlrtEnbld : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RtSdDetSysTmpDsbld : 5|1@0+ (1,0) [0|1] "" XXX + SG_ RtSdDetSysServDsbld : 6|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151792640 Rear_Cross_Traffic_Alert_Rght_LS: 5 XXX + SG_ RrCTfcRHptcStRqSqN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ RrCTfcRHptcStReq : 7|6@0+ (1,0) [0|63] "" XXX + SG_ RrCrsTrfAltRgtIndCtrl : 34|3@0+ (1,0) [0|0] "" XXX + SG_ RCTARIC_IndReq : 33|2@0+ (1,0) [0|3] "" XXX + SG_ RCTARIC_Indctr1Act : 34|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149826560 FCA_VisionBased_Info_2_LS: 4 XXX + SG_ FCAGpStng : 2|3@0+ (1,0) [0|7] "" XXX + SG_ FCAHdwyStngIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ FCACrusCtrlCnclReqd : 4|1@0+ (1,0) [0|1] "" XXX + SG_ FCABrkPrflReq : 5|1@0+ (1,0) [0|1] "" XXX + SG_ FwdClnAlrtOffIO11E : 6|1@0+ (1,0) [0|1] "" XXX + SG_ FwdClnAlrtPr11E : 7|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtVsnFsdSpdGroup : 15|15@0+ (1,0) [0|0] "" XXX + SG_ SpdLmtVsnFsdSpd : 15|8@0+ (1,0) [0|255] "" XXX + SG_ SpdLmtVsnFsdSpdM : 17|1@0+ (1,0) [0|1] "" XXX + SG_ FwdObjAlrtInd11E : 16|9@0+ (1,0) [0|0] "" XXX + SG_ FOAI_AlrtChmIhbRq11E : 16|1@0+ (1,0) [0|1] "" XXX + SG_ FOAI_VehAhdIndRq11E : 27|4@0+ (1,0) [0|15] "" XXX + SG_ FOAI_AlrtWrnIndRq11E : 31|4@0+ (1,0) [0|15] "" XXX + SG_ SpdLmtVnFsSpdNwDet : 18|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtVsnFsdSpdUnt : 19|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149957632 Park_Assist_ESSprocess_Info_LS: 1 XXX + SG_ ClsnMtgtnInhbtd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstInhbtReq : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstRrObjSnsngRqAct : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstOprtrDsrdStat : 4|2@0+ (1,0) [0|3] "" XXX + +BO_ 2149941248 Park_Assist_ESSbased_Info_LS: 5 XXX + SG_ PrkAstRrExtdDstUnfltd : 3|12@0+ (0.01,0) [0|40.95] "m" XXX + SG_ PrkAstRrSysStatUnfltd : 5|2@0+ (1,0) [0|3] "" XXX + SG_ PrkAstFntnSnsDstrbdIO : 16|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstFntnSnrsBlkd : 17|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstFntnFld : 18|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstFntnDsbldIO : 19|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstFntnClnPrkAstIO : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ClsnMtgtnInhbtReqtd : 21|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstRrObjSnsngAct : 22|1@0+ (1,0) [0|1] "" XXX + SG_ PARrRgn3ObjStatUnfltd : 27|4@0+ (1,0) [0|15] "" XXX + SG_ PARrRgn4ObjStatUnfltd : 31|4@0+ (1,0) [0|15] "" XXX + SG_ PARrRgn1ObjStatUnfltd : 35|4@0+ (1,0) [0|15] "" XXX + SG_ PARrRgn2ObjStatUnfltd : 39|4@0+ (1,0) [0|15] "" XXX + +BO_ 2156314624 High_Volt_Time_Based_Chrg_LS: 8 XXX + SG_ TODCNxtPlnndDprtrTm : 5|14@0+ (1,0) [0|0] "" XXX + SG_ TODCNPDT_Hr : 2|5@0+ (1,0) [0|31] "Hour" XXX + SG_ TODCNPDT_DyOfWk : 5|3@0+ (1,0) [0|7] "" XXX + SG_ TODCNPDT_Min : 13|6@0+ (1,0) [0|63] "Minute" XXX + SG_ OffBrdCSFltDtctd : 6|1@0+ (1,0) [0|1] "" XXX + SG_ OBVhCsACChgRqBnVs : 7|1@0+ (1,0) [0|1] "" XXX + SG_ HVChgSyChgLvlPrfDt : 16|25@0+ (1,0) [0|0] "" XXX + SG_ HVCSCLPD_UsrIntTyp : 16|2@0+ (1,0) [0|3] "" XXX + SG_ HVCSCLPD_NrmChrgC : 27|5@0+ (1,0) [0|31] "A" XXX + SG_ HVCSCLPD_ChgLvlPfS : 30|3@0+ (1,0) [0|7] "" XXX + SG_ HVCSCLPD_RdCrntLv2 : 33|5@0+ (1,0) [0|31] "A" XXX + SG_ HVCSCLPD_RdCrntLv1 : 38|5@0+ (1,0) [0|31] "A" XXX + SG_ HVCSCLPD_RdCrntLv3 : 44|5@0+ (1,0) [0|31] "A" XXX + SG_ HVChrgAbrtRsn : 19|3@0+ (1,0) [0|7] "" XXX + SG_ TODCOpMd : 22|3@0+ (1,0) [0|7] "" XXX + SG_ HVChrgSysSplyFltIO : 23|1@0+ (1,0) [0|1] "" XXX + SG_ TODCDspMnPgTmpOr : 52|5@0+ (1,0) [0|0] "" XXX + SG_ TODCDMPTO_TpOvR : 51|4@0+ (1,0) [0|15] "" XXX + SG_ TODCDMPTO_CmPgR : 52|1@0+ (1,0) [0|1] "" XXX + SG_ HVChrgSysStNot : 55|3@0+ (1,0) [0|7] "" XXX + SG_ HVBatBlkSOC : 63|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2150449152 Engine_Information_5_LS: 4 XXX + SG_ SrvcFlSysPrkInOpnArIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvTrCtrlOffUnbIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvStblCtrlOffUnbIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ InActFuelMdFuelLvlIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ FuelSysNEmsRltMalfAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ EngInltSpcfcHmdtyGroup : 7|16@0+ (1,0) [0|0] "" XXX + SG_ EngInltSpcfcHmdtyM : 6|1@0+ (1,0) [0|1] "" XXX + SG_ EngInltSpcfcHmdtyV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EngInltSpcfcHmdty : 15|8@0+ (0.0196078,0) [0|4.999989] "% water" XXX + SG_ AutoStpInhbtRsnInd : 23|8@0+ (1,0) [0|0] "" XXX + SG_ ASIRI_Indication08 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication07 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication06 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication05 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication04 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication03 : 21|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication02 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ASIRI_Indication01 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtrSttngTypAct : 25|2@0+ (1,0) [0|3] "" XXX + SG_ ManTransIndReq : 28|3@0+ (1,0) [0|7] "" XXX + SG_ ESPDrvrExtIO : 29|1@0+ (1,0) [0|1] "" XXX + SG_ ESPDrvrDrStIndtrmntIO : 30|1@0+ (1,0) [0|1] "" XXX + SG_ ESPAutoPrkIO : 31|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149810176 FCA_VisionBased_Info_1_LS: 1 XXX + SG_ FCAHptcStVbnRqSeqN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ FCAHptcStVbnReq : 7|6@0+ (1,0) [0|63] "" XXX + +BO_ 2149793792 FCA_VisionBased_Info_LS: 6 XXX + SG_ FwdClnAlrtCustCrntSetngVal : 3|3@0+ (1,0) [0|7] "" XXX + SG_ FCACustStngAvlbl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ VhlAhdDstIndReq : 26|19@0+ (1,0) [0|0] "" XXX + SG_ VADIR_IndLvl : 26|4@0+ (1,0) [0|15] "" XXX + SG_ VADIR_FlwTme : 38|7@0+ (0.1,0) [0|12.7] "s" XXX + SG_ VADIR_FlwDst : 47|8@0+ (1,0) [0|255] "m" XXX + +BO_ 2150080512 Aux_Coolant_Heater_Status_LS: 8 XXX + SG_ EngAstHtDfrdHtMdAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCsCrStVal : 2|2@0+ (1,0) [0|3] "" XXX + SG_ AuxClntHtrVlvStat : 5|3@0+ (1,0) [0|7] "" XXX + SG_ LBCChrgLvlPrfExpIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCsStAvl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCstmrDaRstResp : 12|5@0+ (1,0) [0|0] "" XXX + SG_ LBCCDRR_PosNumbr : 10|3@0+ (1,0) [0|7] "" XXX + SG_ LBCCDRR_ClrStrdPosResp : 12|2@0+ (1,0) [0|3] "" XXX + SG_ LBCPosStgStat : 20|5@0+ (1,0) [0|0] "" XXX + SG_ LBCPSS_PosUpdtLct : 18|3@0+ (1,0) [0|7] "" XXX + SG_ LBCPSS_PosUpdtStat : 20|2@0+ (1,0) [0|3] "" XXX + SG_ LBCVehLctStat : 27|4@0+ (1,0) [0|0] "" XXX + SG_ LBCVLS_VehGPSLct : 26|3@0+ (1,0) [0|7] "" XXX + SG_ LBCVLS_VehGPSLctV : 27|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCstmrFdbk : 31|4@0+ (1,0) [0|0] "" XXX + SG_ LBCCF_Lct4PosStrdIO : 28|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCF_Lct3PosStrdIO : 29|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCF_Lct2PosStrdIO : 30|1@0+ (1,0) [0|1] "" XXX + SG_ LBCCF_Lct1PosStrdIO : 31|1@0+ (1,0) [0|1] "" XXX + SG_ ChrgCyclElecEngyEcnEq : 35|12@0+ (0.1,0) [0|409.5] "km/l" XXX + SG_ ChrgCyclOvrlEngyEcnEq : 51|12@0+ (0.1,0) [0|409.5] "km/l" XXX + +BO_ 2153873408 Heated_Steering_Whl_Rqsted_LS: 1 XXX + SG_ MnlHtdStWhlRqstd : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2152128512 Performance_Mode_Cust_Setings_LS: 4 XXX + SG_ ACCPerfMdCustAvl : 5|6@0+ (1,0) [0|0] "" XXX + SG_ ACCPMCA_ACCPrfMd6Avl : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ACCPMCA_ACCPrfMd5Avl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ACCPMCA_ACCPrfMd4Avl : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACCPMCA_ACCPrfMd3Avl : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ACCPMCA_ACCPrfMd2Avl : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ACCPMCA_ACCPrfMd1Avl : 5|1@0+ (1,0) [0|1] "" XXX + SG_ DrvrStPerfMdCustAvl : 13|6@0+ (1,0) [0|0] "" XXX + SG_ DSPMCA_DrvrStPrfMd6Avl : 8|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvrStPrfMd5Avl : 9|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvrStPrfMd4Avl : 10|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvrStPrfMd3Avl : 11|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvrStPrfMd2Avl : 12|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvrStPrfMd1Avl : 13|1@0+ (1,0) [0|1] "" XXX + SG_ PsngStPerfMdCustAvl : 21|6@0+ (1,0) [0|0] "" XXX + SG_ PSPMCA_PsngStPrfMd6Avl : 16|1@0+ (1,0) [0|1] "" XXX + SG_ PSPMCA_PsngStPrfMd5Avl : 17|1@0+ (1,0) [0|1] "" XXX + SG_ PSPMCA_PsngStPrfMd4Avl : 18|1@0+ (1,0) [0|1] "" XXX + SG_ PSPMCA_PsngStPrfMd3Avl : 19|1@0+ (1,0) [0|1] "" XXX + SG_ PSPMCA_PsngStPrfMd2Avl : 20|1@0+ (1,0) [0|1] "" XXX + SG_ PSPMCA_PsngStPrfMd1Avl : 21|1@0+ (1,0) [0|1] "" XXX + SG_ DrvStyPerfMdCustAvl : 30|7@0+ (1,0) [0|0] "" XXX + SG_ DSPMCA_DrvStyPrfMd7Avl : 24|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvStyPrfMd6Avl : 25|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvStyPrfMd5Avl : 26|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvStyPrfMd4Avl : 27|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvStyPrfMd3Avl : 28|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvStyPrfMd2Avl : 29|1@0+ (1,0) [0|1] "" XXX + SG_ DSPMCA_DrvStyPrfMd1Avl : 30|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151997440 Driver_Drowsiness_Dtctn_Stat_LS: 5 XXX + SG_ DrvDrowSysIndRq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ DrvDrwDetCsCrStVal : 5|3@0+ (1,0) [0|7] "" XXX + SG_ DrvDrowDetCstStAvl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ DrvDrsnHptcStRqSeqN : 9|2@0+ (1,0) [0|3] "" XXX + SG_ DrDrwSysHptcStVbnRq : 15|6@0+ (1,0) [0|63] "" XXX + +BO_ 2156331008 High_Voltage_EnergyMgmt_Ctrl_LS: 7 XXX + SG_ LwRngLVLdShdRq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ HVDpltnMdMxCnfdcRg : 11|12@0+ (0.1,0) [0|409.5] "km" XXX + SG_ HVDpltnMdMiCnfdcRg : 27|12@0+ (0.1,0) [0|409.5] "km" XXX + SG_ HVDpltnMdMxGugRg : 43|12@0+ (0.1,0) [0|409.5] "km" XXX + +BO_ 2151776256 Rear_Cross_Traffic_Alert_Left_LS: 5 XXX + SG_ RrCTfcLHptcStRqSeqN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ RrCTfcLHptcStReq : 7|6@0+ (1,0) [0|63] "" XXX + SG_ RrCrsTrfAltLftIndCtrl : 34|3@0+ (1,0) [0|0] "" XXX + SG_ RCTALIC_IndReq : 33|2@0+ (1,0) [0|3] "" XXX + SG_ RCTALIC_Indctr1Act : 34|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154774528 Lighting_Customization_Info_1_LS: 1 XXX + SG_ LtRtHnTrCstStVal : 2|3@0+ (1,0) [0|7] "" XXX + SG_ LtRtHnTrGPCsCrStVal : 5|3@0+ (1,0) [0|7] "" XXX + SG_ LtRtHnTrCstStAvail : 6|1@0+ (1,0) [0|1] "" XXX + SG_ LtRtHnTrGPSCsStAvl : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150375424 Eng_Maintenance_Mode_Strt_Req_LS: 3 XXX + SG_ MntnceMdStEngRq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ EngAstHtCstStRq : 3|3@0+ (1,0) [0|7] "" XXX + SG_ EngAstHtPlgInCstStRq : 6|3@0+ (1,0) [0|7] "" XXX + SG_ DsplTrnsShftLvrLckRqd : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EngyCnsHistGrphRstRq : 8|1@0+ (1,0) [0|1] "" XXX + SG_ USBProgInPrgrs : 9|1@0+ (1,0) [0|1] "" XXX + SG_ LBCPosMdfcReq : 12|3@0+ (1,0) [0|7] "" XXX + SG_ LBCCsStReq : 14|2@0+ (1,0) [0|3] "" XXX + SG_ LBCCstmrDaRstReq : 20|5@0+ (1,0) [0|0] "" XXX + SG_ LBCCDRR_PosNum : 18|3@0+ (1,0) [0|7] "" XXX + SG_ LBCCDRR_ClrStrdPosReq : 20|2@0+ (1,0) [0|3] "" XXX + +BO_ 2150383616 Engine_Maintenance_Mode_Req_LS: 8 XXX + SG_ MntnceMdDsplyRq : 3|4@0+ (1,0) [0|15] "" XXX + SG_ EngMntnceMdAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ EngMntncePrcntCpl : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ EngPrpDspPwrLvlPct : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ EstElecPrpCap : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ PrpCapDspOpPs : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ PrpDspTtlPwr : 45|13@0+ (0.5,-326.6) [-326.6|3768.9] "kW" XXX + SG_ BatPrpDspPwrLvlPct : 48|9@0- (0.392157,0) [-100.392192|100.000035] "%" XXX + +BO_ 2151981056 Drive_Cycle_Efficiency_LS: 8 XXX + SG_ DstTrvldDt : 7|51@0+ (1,0) [0|0] "" XXX + SG_ DTD_BattPrpDstTrvld : 7|17@0+ (0.015625,0) [0|2047.984375] "km" XXX + SG_ DTD_FuelPrpDstTrvld : 22|17@0+ (0.015625,0) [0|2047.984375] "km" XXX + SG_ DTD_DrvCyclDstTrvld : 37|17@0+ (0.015625,0) [0|2047.984375] "km" XXX + SG_ DrvCyclBatPropRat : 50|11@0+ (0.048852,0) [0|100.000044] "%" XXX + +BO_ 2151964672 Drive_Cycle_Energy_Efficiency_LS: 8 XXX + SG_ DrvCyclBatCondEnrgEfncy : 7|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DrvCyclCbnCondEnrgEfncy : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DrvCyclDrvStEnrgEfncy : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DrvCyclTtlEnrgEfncy : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DrvCyclFuelEnmy : 47|12@0+ (0.1,0) [0|409.5] "km/liters" XXX + SG_ DrvCyclFuelUsd : 51|12@0+ (0.125,0) [0|511.875] "liters" XXX + +BO_ 2156298240 High_Volt_Batt_Time_Pwr_Chrg_LS: 8 XXX + SG_ HVBatCmpltTmHghPwrChrg : 7|14@0+ (1,0) [0|0] "" XXX + SG_ HVBCTHPC_HrOfDy : 4|5@0+ (1,0) [0|31] "Hour" XXX + SG_ HVBCTHPC_DyOfWk : 7|3@0+ (1,0) [0|7] "" XXX + SG_ HVBCTHPC_MntOfHr : 15|6@0+ (1,0) [0|63] "Minute" XXX + SG_ HVBatCmpltTmLwPwrChrg : 9|14@0+ (1,0) [0|0] "" XXX + SG_ HVBCTLPC_DyOfWk : 9|3@0+ (1,0) [0|7] "" XXX + SG_ HVBCTLPC_MntOfHr : 17|6@0+ (1,0) [0|63] "Minute" XXX + SG_ HVBCTLPC_HrOfDy : 22|5@0+ (1,0) [0|31] "Hour" XXX + SG_ HVBatStrTmHghPwrChrg : 27|14@0+ (1,0) [0|0] "" XXX + SG_ HVBSTHPC_HrOfDy : 24|5@0+ (1,0) [0|31] "Hour" XXX + SG_ HVBSTHPC_DyOfWk : 27|3@0+ (1,0) [0|7] "" XXX + SG_ HVBSTHPC_MntOfHr : 35|6@0+ (1,0) [0|63] "Minute" XXX + SG_ HVBatStrTmLwPwrChrg : 45|14@0+ (1,0) [0|0] "" XXX + SG_ HVBSTLPC_HrOfDy : 42|5@0+ (1,0) [0|31] "Hour" XXX + SG_ HVBSTLPC_DyOfWk : 45|3@0+ (1,0) [0|7] "" XXX + SG_ HVBSTLPC_MntOfHr : 53|6@0+ (1,0) [0|63] "Minute" XXX + SG_ HVChrgSysDpTmExdSt : 58|3@0+ (1,0) [0|0] "" XXX + SG_ HVCSDTES_NPDTIO : 56|1@0+ (1,0) [0|1] "" XXX + SG_ HVCSDTES_HiPwrCIO : 57|1@0+ (1,0) [0|1] "" XXX + SG_ HVCSDTES_LoPwrCIO : 58|1@0+ (1,0) [0|1] "" XXX + SG_ HTRActvIndOn : 59|1@0+ (1,0) [0|1] "" XXX + SG_ InsfcntTmTFlChrgIO : 60|1@0+ (1,0) [0|1] "" XXX + SG_ InvldHMIEtrIO : 61|1@0+ (1,0) [0|1] "" XXX + SG_ HVBatChrgCrdAlrtReq : 63|2@0+ (1,0) [0|3] "" XXX + +BO_ 2149924864 Drv_Pref_Mode_Switch_Status_LS: 8 XXX + SG_ DrvSelMd1Stat : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd1ReqDnd : 1|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd2Stat : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd2ReqDnd : 3|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd3Stat : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd3ReqDnd : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HilRlbkCtrlActIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ FwdClnMtgnBrkReqAct : 7|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMdSelnStat : 8|17@0+ (1,0) [0|0] "" XXX + SG_ DSMSS_DrvSelMd1Un : 8|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd1Pn : 16|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd8Un : 17|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd7Un : 18|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd6Un : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd5Un : 20|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd4Un : 21|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd3Un : 22|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd2Un : 23|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd0Pn : 24|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd8Pn : 25|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd7Pn : 26|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd6Pn : 27|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd5Pn : 28|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd4Pn : 29|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd3Pn : 30|1@0+ (1,0) [0|1] "" XXX + SG_ DSMSS_DrvSelMd2Pn : 31|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd4Stat : 9|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd4ReqDnd : 10|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd5Stat : 11|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd5ReqDnd : 12|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd6Stat : 13|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd6ReqDnd : 14|1@0+ (1,0) [0|1] "" XXX + SG_ PTOMobModTrnsInGrIO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ECODrvAsstDsplyStat : 34|11@0+ (1,0) [0|0] "" XXX + SG_ EDADS_ShftIndStat : 33|2@0+ (1,0) [0|3] "" XXX + SG_ EDADS_EcoDrvShftIO : 34|1@0+ (1,0) [0|1] "" XXX + SG_ EDADS_RcmndtFwdGr : 43|4@0+ (1,0) [0|15] "" XXX + SG_ EDADS_CrntFwdMsdG : 47|4@0+ (1,0) [0|15] "" XXX + SG_ DrvSelMd7Stat : 35|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd7ReqDnd : 36|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd8Stat : 37|1@0+ (1,0) [0|1] "" XXX + SG_ DrvSelMd8ReqDnd : 38|1@0+ (1,0) [0|1] "" XXX + SG_ FstIdlMdAct : 39|1@0+ (1,0) [0|1] "" XXX + SG_ DsplyPerfMdRq : 50|3@0+ (1,0) [0|7] "" XXX + SG_ TireLFLowTracIO : 51|1@0+ (1,0) [0|1] "" XXX + SG_ TireLRLowTracIO : 52|1@0+ (1,0) [0|1] "" XXX + SG_ TireRFLowTracIO : 53|1@0+ (1,0) [0|1] "" XXX + SG_ TireRRLowTracIO : 54|1@0+ (1,0) [0|1] "" XXX + SG_ a_12VBatSysUnstab : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ColPrepSysCustAvail : 62|7@0+ (1,0) [0|0] "" XXX + SG_ CPSCA_Resrv3Avail : 56|1@0+ (1,0) [0|1] "" XXX + SG_ CPSCA_Resrv2Avail : 57|1@0+ (1,0) [0|1] "" XXX + SG_ CPSCA_Resrv1Avail : 58|1@0+ (1,0) [0|1] "" XXX + SG_ CPSCA_AlrtBrkStrAvail : 59|1@0+ (1,0) [0|1] "" XXX + SG_ CPSCA_AlrtBrkAvail : 60|1@0+ (1,0) [0|1] "" XXX + SG_ CPSCA_AlrtAvail : 61|1@0+ (1,0) [0|1] "" XXX + SG_ CPSCA_OffAvail : 62|1@0+ (1,0) [0|1] "" XXX + +BO_ 2152054784 HMI_Disp_Hyb_Animation_Status_LS: 1 XXX + SG_ AnmStrtReq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ IntPnlClstrAnmtStat : 5|3@0+ (1,0) [0|7] "" XXX + SG_ FuelEconMetDispUnts : 6|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150301696 HMI_Animation_Initiator_LS: 1 XXX + SG_ WlcAnmReq : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150563840 HMI_AnimationHybridRadio_LS: 3 XXX + SG_ RadAnmtStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ RadAudQueStat : 5|3@0+ (1,0) [0|7] "" XXX + SG_ DrStStatDispAct : 6|1@0+ (1,0) [0|1] "" XXX + SG_ PsStStatDispAct : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154758144 Auxiliary_Heater_Active_LS: 1 XXX + SG_ ChldLckOtSwAct : 1|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154577920 Amp_Sink_Stat_LS: 2 XXX + SG_ AmpSnkStat : 4|13@0+ (1,0) [0|0] "" XXX + SG_ ASS_SurndAvail : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPAvail : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_VehNoisCmpnAvail : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_PhLckdLpLckd : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_MtxSnkMutStat : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd7Prsnt : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd6Prsnt : 9|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd5Prsnt : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd4Prsnt : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd3Prsnt : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd2Prsnt : 13|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd1Prsnt : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ASS_DSPMd0Prsnt : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154594304 Amp_Settings_Tone_Ctrl_LS: 5 XXX + SG_ AmpSetTonCtrl : 1|34@0+ (1,0) [0|0] "" XXX + SG_ ASTC_ChimSnkLvl : 1|8@0+ (0.5,-127.5) [-127.5|0] "dB" XXX + SG_ ASTC_ChimSnkSpkrPos : 9|4@0+ (1,0) [0|15] "" XXX + SG_ ASTC_SurndLvl : 21|6@0- (1,0) [-32|31] "" XXX + SG_ ASTC_MtxSnkMutRmpTm : 25|8@0+ (5,0) [0|1275] "ms" XXX + SG_ ASTC_MtxSnkMut : 26|1@0+ (1,0) [0|1] "" XXX + SG_ ASTC_DSPMd : 30|4@0+ (1,0) [0|15] "" XXX + SG_ ASTC_VehNoisCmpnAct : 31|1@0+ (1,0) [0|1] "" XXX + SG_ ASTC_GblAudSnkMut : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ASTC_AmpLwPwrSt : 33|1@0+ (1,0) [0|1] "" XXX + SG_ InfotnBkltngConfigSt : 3|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154586112 Amp_Settings_Sink_Lvl_Ctrl_LS: 8 XXX + SG_ AmpSetSnkLvlCtrl : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ASSLC_MtxSnkLvl : 7|8@0+ (0.5,-127.5) [-127.5|0] "dB" XXX + SG_ ASSLC_MxPrmtSnkLvl : 15|8@0+ (0.5,-127.5) [-127.5|0] "dB" XXX + SG_ ASSLC_AudFdbkSnkLvl : 23|8@0+ (0.5,-127.5) [-127.5|0] "dB" XXX + SG_ ASSLC_FvSnkLvl : 31|8@0+ (0.5,-127.5) [-127.5|0] "dB" XXX + SG_ ASSLC_MtxSnkFd : 33|6@0- (1,0) [-32|31] "" XXX + SG_ ASSLC_MtxSnkBal : 39|6@0- (1,0) [-32|31] "" XXX + SG_ ASSLC_MtxSnkBass : 43|6@0- (1,0) [-32|31] "" XXX + SG_ ASSLC_MtxSnkMdrng : 53|6@0- (1,0) [-32|31] "" XXX + SG_ ASSLC_AutoLdnsCmpnAct : 56|1@0+ (1,0) [0|1] "" XXX + SG_ ASSLC_VcSrcActOnMtx : 57|1@0+ (1,0) [0|1] "" XXX + SG_ ASSLC_MtxSnkTrbl : 63|6@0- (1,0) [-32|31] "" XXX + +BO_ 2152857600 ACC_TrafficJam_RouteSpd_Stat_LS: 3 XXX + SG_ ACCRteSpdDrvIntvReq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ACCTrfcJamAstActStat : 10|3@0+ (1,0) [0|7] "" XXX + SG_ ACCRteSpdAdaptStat : 12|2@0+ (1,0) [0|3] "" XXX + SG_ ACCGrnMdStat : 14|2@0+ (1,0) [0|3] "" XXX + SG_ ACCTrfcJamAstRmnTm : 23|8@0+ (1,0) [0|255] "sec" XXX + +BO_ 2158149632 High_Volt_Bat_Time_Bsd_Rsp_1_LS: 7 XXX + SG_ HVBatTmBsSsnChRsp : 0|14@0+ (1,0) [0|0] "" XXX + SG_ HVBTBSCR_SsnStat : 0|2@0+ (1,0) [0|3] "" XXX + SG_ HVBTBSCR_SsnMthStat : 11|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBSCR_SsnSlctStat : 14|3@0+ (1,0) [0|7] "" XXX + SG_ HVBTBSCR_SsnDyStat : 23|5@0+ (1,0) [0|31] "day" XXX + SG_ HVBatTmBsChrgStRsp : 3|3@0+ (1,0) [0|7] "" XXX + SG_ HVBatCrgDspStat : 6|3@0+ (1,0) [0|7] "" XXX + SG_ HVBatTmBsChrgRtRsp : 17|10@0+ (1,0) [0|0] "" XXX + SG_ HVBTBCRS_ChRtEnblStat : 17|2@0+ (1,0) [0|3] "" XXX + SG_ HVBTBCRS_ChRtSlctStat : 27|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBCRS_ChRtDStat : 31|4@0+ (1,0) [0|15] "" XXX + SG_ EngyCnsHsGrphCnfgDt : 36|13@0+ (1,0) [0|0] "" XXX + SG_ ECHGCD_YAxMaxVal : 32|6@0+ (4,0) [0|252] "" XXX + SG_ ECHGCD_MeasUt : 36|4@0+ (1,0) [0|15] "" XXX + SG_ ECHGCD_XAxTkMrkInterv : 42|3@0+ (1,0) [0|7] "" XXX + SG_ EgyCnsHstGphInsEgyCns : 55|5@0+ (1,0) [0|31] "" XXX + +BO_ 2158116864 High_Volt_Bat_Time_Bsd_Rsp_LS: 8 XXX + SG_ OBHVBCMinsRmng : 5|6@0+ (1,0) [0|63] "" XXX + SG_ OBHVBCCompTmDispFrmt : 7|2@0+ (1,0) [0|3] "" XXX + SG_ HVBatTmBsDelChrgRsp : 12|21@0+ (1,0) [0|0] "" XXX + SG_ HVBTBDCRS_DlChHRsp : 12|5@0+ (1,0) [0|31] "hr" XXX + SG_ HVBTBDCRS_DlChSlctStat : 19|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBDCRS_DlChDStat : 23|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBDCRS_DlChMHRsp : 29|6@0+ (1,0) [0|63] "min" XXX + SG_ HVBTBDCRS_DlChSsnStat : 31|2@0+ (1,0) [0|3] "" XXX + SG_ HVBatTmBsRtChrgRsp : 34|27@0+ (1,0) [0|0] "" XXX + SG_ HVBTBRCR_RtChMHRsp : 32|6@0+ (1,0) [0|63] "min" XXX + SG_ HVBTBRCR_RtChSsnStat : 34|2@0+ (1,0) [0|3] "" XXX + SG_ HVBTBRCR_RtChSlctStat : 42|3@0+ (1,0) [0|7] "" XXX + SG_ HVBTBRCR_RtChDStat : 50|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBRCR_RtChHRsp : 55|5@0+ (1,0) [0|31] "hr" XXX + SG_ HVBTBRCR_RtCHSlctTblRwStat : 58|3@0+ (1,0) [0|7] "rows" XXX + SG_ HVBTBRCR_RtChSlRtStat : 62|4@0+ (1,0) [0|15] "" XXX + +BO_ 2156281856 High_Volt_Bat_Time_Bsd_Req_1_LS: 7 XXX + SG_ HVBatTmBsSsnChStReq : 0|14@0+ (1,0) [0|0] "" XXX + SG_ HVBTBSCSR_SsnStReq : 0|2@0+ (1,0) [0|3] "" XXX + SG_ HVBTBSCSR_SsnMthStReq : 11|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBSCSR_SsnSlStReq : 14|3@0+ (1,0) [0|7] "" XXX + SG_ HVBTBSCSR_SsnDayStReq : 23|5@0+ (1,0) [0|31] "day" XXX + SG_ HVBatTmBsChrgMdReq : 3|3@0+ (1,0) [0|7] "" XXX + SG_ HVChgSyChgLvlPrfSt : 6|3@0+ (1,0) [0|7] "" XXX + SG_ StTODChrgTmpOvrd : 7|1@0+ (1,0) [0|1] "" XXX + SG_ HVBatTmBsChrgRtStReq : 17|10@0+ (1,0) [0|0] "" XXX + SG_ HVBTBCRSR_ChRtEnblStReq : 17|2@0+ (1,0) [0|3] "" XXX + SG_ HVBTBCRSR_ChRtSlStReq : 27|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBCRSR_ChRtDStReq : 31|4@0+ (1,0) [0|15] "" XXX + SG_ TmpOvdNxtPlnDptTmRq : 32|17@0+ (1,0) [0|0] "" XXX + SG_ TONPDTR_StTmpOvrAtv : 32|2@0+ (1,0) [0|3] "" XXX + SG_ TONPDTR_HrOfDy : 42|5@0+ (1,0) [0|31] "Hour" XXX + SG_ TONPDTR_DyOfWk : 46|4@0+ (1,0) [0|15] "" XXX + SG_ TONPDTR_MntOfHr : 53|6@0+ (1,0) [0|63] "Minute" XXX + SG_ RtBsChrgCmplnTmPrfReq : 34|2@0+ (1,0) [0|3] "" XXX + SG_ HTRCsStReq : 37|3@0+ (1,0) [0|7] "" XXX + +BO_ 2156265472 High_Volt_Bat_Time_Bsd_Req_LS: 8 XXX + SG_ ChgCdTfAlCzStRq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ ChgPwLsAlCzStRq : 5|3@0+ (1,0) [0|7] "" XXX + SG_ PrtyChrgRq : 7|2@0+ (1,0) [0|3] "" XXX + SG_ HVBatTmBsDlChStReq : 12|21@0+ (1,0) [0|0] "" XXX + SG_ HVBTBDCSRQ_DlChHStReq : 12|5@0+ (1,0) [0|31] "hr" XXX + SG_ HVBTBDCSRQ_DlChSlStReq : 19|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBDCSRQ_DlChDStReq : 23|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBDCSRQ_DlChMHStReq : 29|6@0+ (1,0) [0|63] "min" XXX + SG_ HVBTBDCSRQ_DlChSsnStReq : 31|2@0+ (1,0) [0|3] "" XXX + SG_ ChgSysAudInCsStReq : 15|3@0+ (1,0) [0|7] "" XXX + SG_ HVBatTmBsRtChrgStReq : 34|27@0+ (1,0) [0|0] "" XXX + SG_ HVBTBRCSR_RtChDStReq : 34|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBRCSR_RtChSlStReq : 42|3@0+ (1,0) [0|7] "" XXX + SG_ HVBTBRCSR_RtChSlRtStReq : 46|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBRCSR_RtChMHStReq : 48|6@0+ (1,0) [0|63] "min" XXX + SG_ HVBTBRCSR_RtChSsnStReq : 50|2@0+ (1,0) [0|3] "" XXX + SG_ HVBTBRCSR_RtChHStReq : 55|5@0+ (1,0) [0|31] "hr" XXX + SG_ HVBTBRCSR_RtChSlTbRwReq : 58|3@0+ (1,0) [0|7] "rows" XXX + SG_ OffBrdHVCVehCsChRq : 35|1@0+ (1,0) [0|1] "" XXX + SG_ EngyUsgScrnMeasUtStat : 39|4@0+ (1,0) [0|15] "" XXX + +BO_ 2150113280 Energy_Storage_System_LS: 8 XXX + SG_ EngyStgSysActCoolEnb : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrvCycElEnrgUsd : 21|14@0+ (0.36,0) [0|5897.88] "MJ" XXX + SG_ DrvCyclElecEngyEcon : 32|9@0+ (0.1,0) [0|51.1] "" XXX + SG_ HVChrgInhbRsn : 36|4@0+ (1,0) [0|15] "" XXX + SG_ DrvCyclTrpDstTrvld : 54|15@0+ (0.1,0) [0|3276.7] "km" XXX + +BO_ 2150055936 Climate_Control_Status_LS: 5 XXX + SG_ ClmtCtrlUpprPwrLmt : 7|8@0+ (0.1,0) [0|25.5] "kW" XXX + SG_ ClmtCtrlLwrPwrLmt : 15|8@0+ (0.1,0) [0|25.5] "kW" XXX + SG_ ClimCtrlHVDvcShtdwnCmd : 16|1@0+ (1,0) [0|1] "" XXX + SG_ ClmCntCmpPwrUsdClc : 39|8@0+ (0.04,0) [0|10.2] "kW" XXX + +BO_ 2150039552 Thrml_Ref_Compressor_Status_LS: 5 XXX + SG_ ThrmlRefCompStat : 3|4@0+ (1,0) [0|15] "" XXX + SG_ EvpCorOtltAirTmpCalcdGroup : 4|13@0+ (1,0) [0|0] "" XXX + SG_ EvpCorOtltAirTmpCalcdV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ EvpCorOtltAirTmpCalcd : 15|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + SG_ ThrmlRefCompSpdGroup : 22|15@0+ (1,0) [0|0] "" XXX + SG_ ThrmlRefCompSpd : 21|14@0+ (1,0) [0|16383] "rpm" XXX + SG_ ThrmlRefCompSpdV : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ThrmlRfCmpOvTmpFltPr : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154856448 Humidity_Sensor_Status_LS: 5 XXX + SG_ HmdtySnsrGlssTemp : 1|10@0+ (0.146628,-50) [-50|100.000444] "deg C" XXX + SG_ HmdtySnsrTemp : 17|10@0+ (0.146628,-50) [-50|100.000444] "deg C" XXX + SG_ HmdtySnsrRltvHmdty : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2151342080 Park_Assistant_Right_Status_LS: 2 XXX + SG_ PARtRgn1ObjStat : 3|4@0+ (1,0) [0|15] "" XXX + SG_ PrkAstRtSysStat : 5|2@0+ (1,0) [0|3] "" XXX + SG_ PARtRgn3ObjStat : 11|4@0+ (1,0) [0|15] "" XXX + SG_ PARtRgn2ObjStat : 15|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151325696 Park_Assistant_Left_Status_LS: 2 XXX + SG_ PALtRgn1ObjStat : 3|4@0+ (1,0) [0|15] "" XXX + SG_ PrkAstLtSysStat : 5|2@0+ (1,0) [0|3] "" XXX + SG_ PALtRgn3ObjStat : 11|4@0+ (1,0) [0|15] "" XXX + SG_ PALtRgn2ObjStat : 15|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151809024 Drv_Cycl_Elec_Enrgy_Consumd_LS: 8 XXX + SG_ DrvCycElecEngySt5 : 5|14@0+ (0.36,0) [0|5897.88] "MJ" XXX + SG_ DrvCycElecEngyCnsmd : 23|32@0+ (1,0) [0|0] "" XXX + SG_ DCEEC_EngyPct1 : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DCEEC_EngyPct2 : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DCEEC_EngyPct3 : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ DCEEC_EngyPct4 : 47|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ ElecEngyEconAvg : 48|9@0+ (0.1,0) [0|51.1] "" XXX + +BO_ 2151858176 Drv_Cycl_Elec_Enrgy_States_LS: 8 XXX + SG_ DrvCycElecEngySt1 : 5|14@0+ (0.36,0) [0|5897.88] "MJ" XXX + SG_ DrvCycElecEngySt2 : 21|14@0+ (0.36,0) [0|5897.88] "MJ" XXX + SG_ DrvCycElecEngySt3 : 37|14@0+ (0.36,0) [0|5897.88] "MJ" XXX + SG_ DrvCycElecEngySt4 : 53|14@0+ (0.36,0) [0|5897.88] "MJ" XXX + +BO_ 2150547456 HMI_Hybrid_Vehicle_Status_LS: 8 XXX + SG_ HVDpltnMdRng : 0|16@0+ (0.015625,0) [0|1023.984375] "km" XXX + SG_ VehChrgMdSt : 3|3@0+ (1,0) [0|7] "" XXX + SG_ GrnAudQueReq : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SvcHybChrgSysIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HVBatChrgCrdConnIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ CntrsOpnUndrTmpIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ OffBrdHVCVehCplrLkd : 16|1@0+ (1,0) [0|1] "" XXX + SG_ HVBatLimDTmpInd : 25|2@0+ (1,0) [0|3] "" XXX + SG_ OffBrdHVCVehPwrDrtd : 26|1@0+ (1,0) [0|1] "" XXX + SG_ HVChrgrSysStat : 29|3@0+ (1,0) [0|7] "" XXX + SG_ HVChrgrCplrStat : 31|2@0+ (1,0) [0|3] "" XXX + SG_ ChgrSysAdblIndReq : 33|2@0+ (1,0) [0|3] "" XXX + SG_ HVBatOutOfEnrgyInd : 36|3@0+ (1,0) [0|7] "" XXX + SG_ OffBrdHVBlkChrgCmp : 37|1@0+ (1,0) [0|1] "" XXX + SG_ ElecPrplsnMtrOvrSpdIO : 38|1@0+ (1,0) [0|1] "" XXX + SG_ HVBatCntctrsOpnIO : 39|1@0+ (1,0) [0|1] "" XXX + SG_ HVDpltnMdCnfdcTrndg : 47|8@0- (0.787402,0) [-100.787456|100.000054] "%" XXX + SG_ OffBrdHVBlkChgCpltTm : 53|14@0+ (1,0) [0|0] "" XXX + SG_ OBHVBCCT_HrofDay : 50|5@0+ (1,0) [0|31] "" XXX + SG_ OBHVBCCT_DayofWk : 53|3@0+ (1,0) [0|7] "" XXX + SG_ OBHVBCCT_MinofHr : 61|6@0+ (1,0) [0|63] "" XXX + SG_ OffBrdHVCVehPwrLvl : 55|2@0+ (1,0) [0|3] "" XXX + +BO_ 2151489536 CSV_EOCM_R_Indications_LS: 1 XXX + SG_ RVBShtToPrkBfExtngVehIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RVBAutoBrkRlsIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ NVSysStat : 4|3@0+ (1,0) [0|7] "" XXX + +BO_ 2149761024 Chassis_Information_2_LS: 6 XXX + SG_ PerfTrcCrnExStngVal : 4|5@0+ (1,0) [0|31] "" XXX + SG_ ActVehAccelGroup : 5|22@0+ (1,0) [0|0] "" XXX + SG_ ActVehAccelV : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ActVehAccel : 11|12@0- (0.01,0) [-20.48|20.47] "m/s^2" XXX + SG_ TrlrStabAstActIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ElvtdIdlCstStAvl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ ElvtdIdlCstCrStVal : 13|2@0+ (1,0) [0|3] "" XXX + SG_ TrnsCltchThrmlProtIndR : 27|20@0+ (1,0) [0|0] "" XXX + SG_ TCTPIR_DrvNotfn : 27|4@0+ (1,0) [0|15] "" XXX + SG_ TCTPIR_TnsEsClTmpD : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ TCTPIR_TnsEsClCDwT : 47|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ PsngStPerfMdCsCrStVal : 30|3@0+ (1,0) [0|7] "" XXX + SG_ PsngStPerfMdCsStAvl : 31|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155012096 SBZA_Right_Status_LS: 1 XXX + SG_ SODTmpUnavlbleIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SODSnsClnRqdIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SODRtIndCntl : 6|5@0+ (1,0) [0|0] "" XXX + SG_ SODRIC_Ind3 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SODRIC_Ind2 : 3|1@0+ (1,0) [0|1] "" XXX + SG_ SODRIC_Ind1 : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SODRIC_IndReq : 6|2@0+ (1,0) [0|3] "" XXX + SG_ SrvSODSysIO : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150514688 Power_Slidining_Door_Status_LS: 1 XXX + SG_ SldngDrRgtStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ SldngDrLftStat : 5|3@0+ (1,0) [0|7] "" XXX + SG_ PwrSldngDrUnavlblIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ SdClsrObstclDtctdStat : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2158067712 Video_Master_Info_2_LS: 5 XXX + SG_ TchScnDsplUsrActnExt : 1|34@0+ (1,0) [0|0] "" XXX + SG_ TSDUAE_RotBtnPsh : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TSDUAE_ScrnPrsdRq : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TSDUAE_GrphStrkInfRq : 15|8@0+ (1,0) [0|255] "" XXX + SG_ TSDUAE_XCoOdntRq : 23|8@0+ (1,0) [0|255] "" XXX + SG_ TSDUAE_YCoOdntRq : 31|8@0+ (1,0) [0|255] "" XXX + SG_ TSDUAE_RotEnc : 39|8@0- (1,0) [-128|127] "Detentions" XXX + +BO_ 2158051328 Video_Master_Info_1_LS: 5 XXX + SG_ RemRcvrSrcInpCmd : 3|4@0+ (1,0) [0|15] "" XXX + SG_ VidMstrDsplyMd : 5|2@0+ (1,0) [0|3] "" XXX + SG_ VidSrcUICntrlStat : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RmtRcvrTunCmnd : 12|5@0+ (1,0) [0|31] "" XXX + SG_ VidMstrArbCmd : 15|3@0+ (1,0) [0|7] "" XXX + SG_ RmtRcvrTunVal : 23|16@0- (1,0) [-32768|32767] "" XXX + SG_ VidMstrSrcType : 36|5@0+ (1,0) [0|31] "" XXX + SG_ TVDspCmd : 39|3@0+ (1,0) [0|7] "" XXX + +BO_ 2158034944 TV_Tuner_Info_LS: 6 XXX + SG_ VidSrcCompFormatER : 3|4@0+ (1,0) [0|15] "" XXX + SG_ CurntTVStnServc : 6|3@0+ (1,0) [0|7] "" XXX + SG_ CurntTVStnQual : 7|1@0+ (1,0) [0|1] "" XXX + SG_ RmtRcvrCmndStat : 10|3@0+ (1,0) [0|7] "" XXX + SG_ RmtRecvtDataTyp : 13|3@0+ (1,0) [0|7] "" XXX + SG_ RmtRcvrTunStat : 14|1@0+ (1,0) [0|1] "" XXX + SG_ TVTunerPres : 15|1@0+ (1,0) [0|1] "" XXX + SG_ RmtRcvrPrgrmServID : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ VidSrcStatCode : 35|4@0+ (1,0) [0|15] "" XXX + SG_ RemRcvrSrcInpStat : 39|4@0+ (1,0) [0|15] "" XXX + SG_ VidSrcType : 44|5@0+ (1,0) [0|31] "" XXX + +BO_ 2158018560 TV_Station_Name_LS: 8 XXX + SG_ TVStatNmeChar1_8 : 7|64@0+ (1,0) [0|0] "" XXX + +BO_ 2156838912 WiFi_Station_LS: 7 XXX + SG_ WiFiStationResp : 3|52@0+ (1,0) [0|0] "" XXX + SG_ WSR_WiFiAssnStat : 3|4@0+ (1,0) [0|15] "" XXX + SG_ WSR_WiFiStnMACAddr : 15|48@0+ (1,0) [0|281474976710655] "" XXX + +BO_ 2156822528 WiFi_AP_Data_LS: 2 XXX + SG_ WiFiAccsPntData : 0|9@0+ (1,0) [0|0] "" XXX + SG_ WAPD_IHUWiFiEnStat : 0|1@0+ (1,0) [0|1] "" XXX + SG_ WAPD_EncrptnType : 11|4@0+ (1,0) [0|15] "" XXX + SG_ WAPD_SecurityType : 15|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151948288 Driver_Drow_Det_Cst_Rqst_LS: 1 XXX + SG_ DrvDrowDetCstStRq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ RunBrdOpMdCstStReq : 7|3@0+ (1,0) [0|7] "" XXX + +BO_ 2158002176 XM_Radio_Service_LS: 1 XXX + SG_ CurntStnServc : 2|3@0+ (1,0) [0|7] "" XXX + SG_ SrvcPrvdr : 5|3@0+ (1,0) [0|7] "" XXX + +BO_ 2149728256 Charging_Sys_Trans_Shift_Lock_LS: 5 XXX + SG_ ChrgSysTrnsShftLckRq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ChrgPrtDrStat : 2|2@0+ (1,0) [0|3] "" XXX + SG_ PrtyChrgActIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PrtyChrgAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ HghVltgPropState : 7|3@0+ (1,0) [0|7] "" XXX + SG_ ChgCdTfAlCzCrStVal : 10|3@0+ (1,0) [0|7] "" XXX + SG_ ChgCdTfAlCzStAvbl : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ChgPwLsAlCzCrStVal : 14|3@0+ (1,0) [0|7] "" XXX + SG_ ChgPwLsAlCzStAvbl : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ChgSyAudInCsCrStVa : 18|3@0+ (1,0) [0|7] "" XXX + SG_ ChgSysAudInCsStAvl : 19|1@0+ (1,0) [0|1] "" XXX + SG_ HVChrgPwrLvl : 22|3@0+ (1,0) [0|7] "" XXX + SG_ EngAstHtCsCrStVal : 26|3@0+ (1,0) [0|7] "" XXX + SG_ EngAstHtCsStAvl : 27|1@0+ (1,0) [0|1] "" XXX + SG_ EngAstHtPlgInCsCrStVl : 30|3@0+ (1,0) [0|7] "" XXX + SG_ EngAstHtPlgInCsStAvl : 31|1@0+ (1,0) [0|1] "" XXX + SG_ PrtyChrgStPnt : 38|7@0+ (1,0) [0|127] "" XXX + +BO_ 2150023168 Hybrid_Information_LS: 5 XXX + SG_ HybChrgMdStat : 1|2@0+ (1,0) [0|3] "" XXX + SG_ HVInvRatVltGroup : 2|19@0+ (1,0) [0|0] "" XXX + SG_ HVInvRatVltV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ HVInvRatVlt : 8|9@0+ (1,0) [0|511] "volts" XXX + SG_ OffBrdVehImmbNot : 5|3@0+ (1,0) [0|7] "" XXX + SG_ ElecPrplsnMtrTach : 28|13@0+ (1,0) [0|8191] "rpm" XXX + +BO_ 2153988096 Power_Elec_Info_LS: 7 XXX + SG_ PwrElecCoolLpTempGroup : 1|10@0+ (1,0) [0|0] "" XXX + SG_ PwrElecCoolLpTempV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ PwrElecCoolLpTempM : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PwrElecCoolLpTemp : 15|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ EngyUsgScr : 20|37@0+ (1,0) [0|0] "" XXX + SG_ EUS_TcEngyUsgScrAvVal : 20|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUS_TrEngyUsgScrAvVal : 29|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUS_OTEngyUsgScrAvVal : 38|7@0- (0.1,0) [-5|5] "" XXX + SG_ EUS_TtEngyUsgScrAvVal : 40|9@0- (0.1,0) [-20|20] "" XXX + SG_ EUS_ITEngyUsgScrAvVal : 47|7@0- (0.1,0) [-5|5] "" XXX + +BO_ 2155945984 Jump_Start_Req_LS: 1 XXX + SG_ JmpStrtReq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TCSysCurStReq : 2|2@0+ (1,0) [0|3] "" XXX + SG_ VehStbEnhmntCurStRq : 4|2@0+ (1,0) [0|3] "" XXX + SG_ VehStbCmptvMdCurStRq : 6|2@0+ (1,0) [0|3] "" XXX + +BO_ 2155585536 MSB_Customization_Setting_Req_LS: 1 XXX + SG_ StBltTgtCSRq : 2|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155569152 CPS_Customization_Setting_Req_LS: 3 XXX + SG_ ColPrSysCustReq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ ExtHlStrAssCsStRq : 5|3@0+ (1,0) [0|7] "" XXX + SG_ IntDimSeldClrTypStReq : 12|5@0+ (1,0) [0|31] "" XXX + SG_ HLOCCstSetReq : 15|3@0+ (1,0) [0|7] "" XXX + SG_ IntDimSeldAnmTypStReq : 19|4@0+ (1,0) [0|15] "" XXX + SG_ SmPhRmFunCstStReq : 22|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155233280 VICM_Info_LS: 8 XXX + SG_ VehRefuelSt : 2|3@0+ (1,0) [0|7] "" XXX + SG_ FlDrOpenIndOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ UtlChrgPopUpAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ UtlChrgIntrfrIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ShftPrkIO_3B2 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ NtrlCstdwnCrtMdActvIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ RtBsChrgCmplnTmPrfRsp : 9|2@0+ (1,0) [0|3] "" XXX + SG_ EngRnngDutoVehSpdIO : 10|1@0+ (1,0) [0|1] "" XXX + SG_ NtrlGrWrngIO : 11|1@0+ (1,0) [0|1] "" XXX + SG_ LftmFuelEcon : 19|12@0+ (0.1,0) [0|409.5] "kilometers/liter" XXX + SG_ LiftimeFuelEcnEquiv : 35|12@0+ (0.1,0) [0|409.5] "km/l" XXX + SG_ ChrgCyclFuelEcn : 51|12@0+ (0.1,0) [0|409.5] "km/l" XXX + +BO_ 2152169472 Coolant_Heater_Status_LS: 3 XXX + SG_ ClntHtrSt : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ClntHtrPCBOvTmpFlt : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ClntHtrHtSnkOvTmpFlt : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ClntHtrElecPwrGroup : 4|13@0+ (1,0) [0|0] "" XXX + SG_ ClntHtrElecPwrV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ClntHtrElecPwr : 15|8@0+ (0.04,0) [0|10.2] "kW" XXX + SG_ ClntHtrFlt : 7|3@0+ (1,0) [0|7] "" XXX + SG_ ClntHtrInltClntTmp : 23|8@0+ (1,-40) [-40|215] "deg C" XXX + +BO_ 2152759296 SITM_Front_Sensor_IO_LS: 1 XXX + SG_ FrtCmrBlckdIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ FrtEOCMMdlFldIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ FrtCmrFldIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ FrtRdrFldIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PedWrnIndReq : 5|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152742912 SITM_Rear_Sensor_IO_LS: 1 XXX + SG_ RrEOCMMdlFldIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RrRdrBlckdIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RrRdrFldIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ShrtRngRdrOffIO : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150891520 Go_Notifier_Req_LS: 5 XXX + SG_ DgtlMapSpdCat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ FwdClnAlrtCustStngReq : 5|3@0+ (1,0) [0|7] "" XXX + SG_ GNCustStngReq : 7|2@0+ (1,0) [0|3] "" XXX + SG_ DgtlMapDrvngSd : 8|1@0+ (1,0) [0|1] "" XXX + SG_ DgtlMapPsgRstrctn : 11|3@0+ (1,0) [0|7] "" XXX + SG_ RrStRmndrCstSetReq : 14|3@0+ (1,0) [0|7] "" XXX + SG_ DgtlMapEffSpdLmt : 20|5@0+ (1,0) [0|31] "" XXX + SG_ DgtlMapEffSpdLmtTyp : 23|3@0+ (1,0) [0|7] "" XXX + SG_ DgtlMapVerYr : 29|6@0+ (1,0) [0|63] "" XXX + SG_ DgtlMapVerQtr : 31|2@0+ (1,0) [0|3] "" XXX + SG_ DgtlMapCndlSpdLmt : 36|5@0+ (1,0) [0|31] "" XXX + SG_ DgtlMapCndlSpdLmtTyp : 39|3@0+ (1,0) [0|7] "" XXX + +BO_ 2151751680 Haptic_Seat_Status_LS: 3 XXX + SG_ CrshAlrtDrvrSlctdType : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CrshAlrtStPrsnt : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HptcStVbnStat : 3|2@0+ (1,0) [0|3] "" XXX + SG_ HptcStFldIO : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155536384 Rear_Virtual_Bmper_Indication_LS: 1 XXX + SG_ RVBDsbldIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RVBEnbldIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RVBFldIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RVBUnblIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvRIMOffUnbIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RevClnMtgnBrkReqAct : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151481344 CSV_FSRACC_Indications_LS: 1 XXX + SG_ AutoBrkRlsIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ShtToPrkBfExtngVehIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HdUpDsplyUnblIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ FSRACCFrstRsmPrssIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ FrtRdrBlckdIO : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151432192 ACC_Drv_Seat_Vib_Req_IO_LS: 1 XXX + SG_ ACCHptcStVbnRqSeqN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ACCHptcStVbnReq : 7|6@0+ (1,0) [0|63] "" XXX + +BO_ 2151415808 Ln_Dep_Wrn_Drv_Seat_Vib_Req_LS: 5 XXX + SG_ LDWLftHptcStRqSN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ LDWLftHptcStRq : 7|6@0+ (1,0) [0|63] "" XXX + SG_ LDWRghtHptcStRqSN : 9|2@0+ (1,0) [0|3] "" XXX + SG_ LDWRghtHptcStRq : 15|6@0+ (1,0) [0|63] "" XXX + SG_ LftLnChgThrtHptStRqSN : 17|2@0+ (1,0) [0|3] "" XXX + SG_ LftLnChgThrtHptStRq : 23|6@0+ (1,0) [0|63] "Pulse" XXX + SG_ RgtLnChgThrtHptStRqSN : 25|2@0+ (1,0) [0|3] "" XXX + SG_ RgtLnChgThrtHptStRq : 31|6@0+ (1,0) [0|63] "Pulse" XXX + SG_ FrPedDetCsStAvl : 32|1@0+ (1,0) [0|1] "" XXX + SG_ FrPedDetCsCrStVal : 35|3@0+ (1,0) [0|7] "" XXX + +BO_ 2151350272 Frnt_Prk_Ast_Drv_Seat_Vib_Req_LS: 3 XXX + SG_ FPAHptcStVbnRqSeqN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ FPAHptcStVbnReq : 7|6@0+ (1,0) [0|63] "" XXX + SG_ APAIconDispRq : 10|3@0+ (1,0) [0|7] "" XXX + SG_ APAIconFilPctRq : 22|7@0+ (1,0) [0|127] "" XXX + +BO_ 2151333888 Rear_Prk_Ast_Drv_Seat_Vib_Req_LS: 1 XXX + SG_ RPAHptcStVbRqSeqN : 1|2@0+ (1,0) [0|3] "" XXX + SG_ RPAHptcStVbnReq : 7|6@0+ (1,0) [0|63] "" XXX + +BO_ 2151522304 Reset_FuelLife_Request_LS: 1 XXX + SG_ FuelFltLfRstRqd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ElEngyEconAvgRstRq : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TCSTmpDsblReqConf : 3|2@0+ (1,0) [0|3] "" XXX + SG_ LnchCtrlRelLnLockReqd : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150629376 CV_System_Failure_LS: 1 XXX + SG_ CVSysFlrIO : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155929600 Diesel_Information_LS: 8 XXX + SG_ DslExFldTpWrngIndRq : 3|4@0+ (1,0) [0|15] "" XXX + SG_ DslExhFldDiagWrnIdRq : 6|3@0+ (1,0) [0|7] "" XXX + SG_ DslExhFldQlyWrngIReq : 11|4@0+ (1,0) [0|15] "" XXX + SG_ DslExhFldWrngIdRqER : 15|4@0+ (1,0) [0|15] "" XXX + SG_ DslExhFluidDistTIndcmt : 22|15@0+ (2,0) [0|65534] "km" XXX + SG_ DslExNxEmWrngIndRq : 35|4@0+ (1,0) [0|15] "" XXX + SG_ DslExFldCnWrngIndRq : 39|4@0+ (1,0) [0|15] "" XXX + SG_ DslExFldWrngVSpdLmt : 47|24@0+ (1,0) [0|0] "" XXX + SG_ DEFWVSL_S1SpdLmt : 47|8@0+ (1,0) [0|255] "km / h" XXX + SG_ DEFWVSL_S2SpdLmt : 55|8@0+ (1,0) [0|255] "km / h" XXX + SG_ DEFWVSL_S3SpdLmt : 63|8@0+ (1,0) [0|255] "km / h" XXX + +BO_ 2154741760 RSA_Status_LS: 1 XXX + SG_ RSAPrsnt : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154807296 Lighting_Customization_Info_3_LS: 4 XXX + SG_ AFLGPSCstCrStVal : 2|3@0+ (1,0) [0|7] "" XXX + SG_ AFLCstCrStVal : 5|3@0+ (1,0) [0|7] "" XXX + SG_ AFLGPSCstStAvl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ AFLCstStAvl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ AFLGPSMnu2CstStAvl : 8|1@0+ (1,0) [0|1] "" XXX + SG_ AFLMnu2CstStAvl : 9|1@0+ (1,0) [0|1] "" XXX + SG_ AFLMnu3CstStAvl : 10|1@0+ (1,0) [0|1] "" XXX + SG_ EngAutoStpNotProb : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ESCMHiEleclLdReqAct : 12|1@0+ (1,0) [0|1] "" XXX + SG_ EngAutoStrtStpInfo : 17|10@0+ (1,0) [0|0] "" XXX + SG_ EASSI_StrtStpSt : 17|2@0+ (1,0) [0|3] "" XXX + SG_ EASSI_UnsdRsrvd2 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ EASSI_TorqDetdIndet : 25|1@0+ (1,0) [0|1] "" XXX + SG_ EASSI_StlDetd : 26|1@0+ (1,0) [0|1] "" XXX + SG_ EASSI_TrqDetd : 27|1@0+ (1,0) [0|1] "" XXX + SG_ EASSI_FuelReqOn : 28|1@0+ (1,0) [0|1] "" XXX + SG_ EASSI_StrtTyp : 31|3@0+ (1,0) [0|7] "" XXX + +BO_ 2151079936 PDIM_Status_LS: 1 XXX + SG_ PDIMPrsnt : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155364352 Hybrid_Information_SuperSlow_LS: 5 XXX + SG_ SvcHybridSysIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ JmpStrtStat : 3|3@0+ (1,0) [0|7] "" XXX + SG_ HybMdDisp : 7|4@0+ (1,0) [0|15] "" XXX + SG_ CstmrUsblSOCGroup : 15|15@0+ (1,0) [0|0] "" XXX + SG_ CstmrUsblSOC : 15|8@0+ (0.39216,0) [0|100.0008] "%" XXX + SG_ CstmrUsblSOCV : 17|1@0+ (1,0) [0|1] "" XXX + SG_ BattCntrlPrcssrVDA : 16|1@0+ (1,0) [0|1] "" XXX + SG_ InstDrvEff : 31|8@0- (0.78125,0) [-100|99.21875] "%" XXX + SG_ ClntCrcFlwRtEst : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2154979328 Front_Seat_Heat_Cool_Req_LS: 1 XXX + SG_ FrntStVoltBstModReq : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155282432 RearSeat_HeatVent_Cool_LS: 1 XXX + SG_ RrStVoltBstModReq : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151505920 VehInfoTripComputer_LS: 7 XXX + SG_ SpdCurvAdvSysEnbld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrBrkDsplyAct : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ACCSettingType : 3|2@0+ (1,0) [0|3] "" XXX + SG_ AutoMdSpdLmtCnfrmd : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PTExPrtclFltManRgnRqd : 5|1@0+ (1,0) [0|1] "" XXX + SG_ Trp2OdomtrGroup : 6|55@0+ (1,0) [0|0] "" XXX + SG_ Trp2OdomtrV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ Trp2Odomtr : 38|23@0+ (0.015625,0) [0|131071.984375] "km" XXX + SG_ Trp1OdomtrGroup : 7|32@0+ (1,0) [0|0] "" XXX + SG_ Trp1OdomtrV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ Trp1Odomtr : 14|23@0+ (0.015625,0) [0|131071.984375] "km" XXX + +BO_ 2155896832 Alternative_Fuel_Information_LS: 5 XXX + SG_ FuelMdStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ AltFuelMdReqDndIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ FlLvlTank2PctGroup : 4|13@0+ (1,0) [0|0] "" XXX + SG_ FlLvlTank2PctV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ FlLvlTank2Pct : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ AltFuelAccWrnngAct : 5|1@0+ (1,0) [0|1] "" XXX + SG_ AltFuelLvlLo : 6|1@0+ (1,0) [0|1] "" XXX + SG_ AltFuelPHeatAct : 7|1@0+ (1,0) [0|1] "" XXX + SG_ FuelTotCapTnk2 : 19|12@0+ (0.125,0) [0|511.875] "liters" XXX + SG_ FuelAlchlCompAdptnPrg : 20|1@0+ (1,0) [0|1] "" XXX + SG_ FuelAlcoholCompGroup : 21|22@0+ (1,0) [0|0] "" XXX + SG_ FuelAlcoholCompV : 21|1@0+ (1,0) [0|1] "" XXX + SG_ FuelAlcoholComp : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2155552768 Exterior_Lock_Switch_Req_LS: 1 XXX + SG_ PsvEntCmftWndRq : 1|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154496000 Rear_Closure_Soft_Top_Info_LS: 1 XXX + SG_ CmpSftTopMotBfrOpTrnkIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TargaTopStateGroup : 2|2@0+ (1,0) [0|0] "" XXX + SG_ TargaTopState : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TargaTopStateV : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155208704 Power_Conv_Top_Info_LS: 3 XXX + SG_ SftTpAbvWrngSpdIndOn : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpFlrIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpLtcIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpMnlLtchIndOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpMchnOvhtIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpRmCrgCrrIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpStrIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpTmpLwIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpTneuCvrIO : 8|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpVehOvSpdIndOn : 9|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpVltLwIO : 10|1@0+ (1,0) [0|1] "" XXX + SG_ CkSoftTpIO : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ClsTrnkLidIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ FTUpdWndPsLmtEnbld : 13|1@0+ (1,0) [0|1] "" XXX + SG_ VltSwAtvIndOn : 14|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpTrnLmpsRqd : 15|1@0+ (1,0) [0|1] "" XXX + SG_ FldngTpSt : 18|3@0+ (1,0) [0|7] "" XXX + SG_ FldngTpWndCmftRq : 20|2@0+ (1,0) [0|3] "" XXX + SG_ SftTpPlsDnSrtdIndOn : 21|1@0+ (1,0) [0|1] "" XXX + SG_ SftTpPlsDnWrngIndOn : 22|1@0+ (1,0) [0|1] "" XXX + +BO_ 2153390080 Manual_Liftgate_Control_LS: 1 XXX + SG_ RrClosOpenSwAct_2D1Group : 3|3@0+ (1,0) [0|0] "" XXX + SG_ RrClosOpenSwAct_2D1 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RrClosOpenSwAct_2D1V : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155175936 CruiseControlGapSwitch_LS: 1 XXX + SG_ AdptCrsGapSwAct : 1|2@0+ (1,0) [0|3] "" XXX + SG_ AdptCrsLKALDWSwAct : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2156806144 Cellular_Network_Date_and_Time: 6 XXX + SG_ CldrDayCmpstdVal : 4|5@0+ (1,0) [0|31] "days" XXX + SG_ HrsCmpstdValGroup : 5|30@0+ (1,0) [0|0] "" XXX + SG_ HrsCmpstdValV : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HrsCmpstdVal : 28|5@0+ (1,0) [0|31] "h" XXX + SG_ MinsCmpstdValGroup : 6|39@0+ (1,0) [0|0] "" XXX + SG_ MinsCmpstdValV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ MinsCmpstdVal : 37|6@0+ (1,0) [0|63] "min" XXX + SG_ SecCmpstdValGroup : 7|48@0+ (1,0) [0|0] "" XXX + SG_ SecCmpstdValV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ SecCmpstdVal : 45|6@0+ (1,0) [0|63] "secs" XXX + SG_ CldrMthCmpstdVal : 11|4@0+ (1,0) [0|15] "" XXX + SG_ CellNtwrkDtTmAvl : 12|1@0+ (1,0) [0|1] "" XXX + SG_ CldrYrCmpstdVal : 23|8@0+ (1,2000) [2000|2255] "year" XXX + +BO_ 2154078208 Window_Position_Status_LS: 2 XXX + SG_ DrvWndPosStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ LRWndPosStat : 5|3@0+ (1,0) [0|7] "" XXX + SG_ PsWndPosStat : 10|3@0+ (1,0) [0|7] "" XXX + SG_ RRWndPosStat : 13|3@0+ (1,0) [0|7] "" XXX + +BO_ 2159058944 ODIEvent_IPC_LS: 3 XXX + SG_ ODIEvntPkt_IPC : 5|22@0+ (1,0) [0|0] "" XXX + SG_ ODIEI_EvID : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ODIEI_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODIEI_MultiFrRetCh : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 2159042560 ODI_DynData_IPC_LS: 8 XXX + SG_ ODIDynData_IPC : 14|55@0+ (1,0) [0|0] "" XXX + SG_ ODDI_InvldData : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ODDI_DataType : 14|6@0+ (1,0) [0|63] "" XXX + SG_ ODDI_FUCID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDI_DataId : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDI_DataVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2150006784 System_Power_Mode_Pushbutton_LS: 1 XXX + SG_ SysPwrMdPshbtnActGroup : 1|2@0+ (1,0) [0|0] "" XXX + SG_ SysPwrMdPshbtnAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SysPwrMdPshbtnActV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PEPSRunCrnkRlyDctd : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155216896 Road_Type_Information_LS: 6 XXX + SG_ MpDataAvlbl : 0|1@0+ (1,0) [0|1] "" XXX + SG_ BldUpArDet : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SprtLnRd : 2|1@0+ (1,0) [0|1] "" XXX + SG_ CntrldAccRd : 3|1@0+ (1,0) [0|1] "" XXX + SG_ CurvAdvInd : 5|2@0+ (1,0) [0|3] "" XXX + SG_ SpdLmtPstdSpdGroup : 6|23@0+ (1,0) [0|0] "" XXX + SG_ SpdLmtPstdSpdM : 6|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtPstdSpd : 23|8@0+ (1,0) [0|255] "" XXX + SG_ DgtlMapPstdSpdLimAsrd : 7|1@0+ (1,0) [0|1] "" XXX + SG_ FncRdClass : 10|3@0+ (1,0) [0|7] "" XXX + SG_ RdSpdCatType : 12|2@0+ (1,0) [0|3] "" XXX + SG_ LnCat : 14|2@0+ (1,0) [0|3] "" XXX + SG_ SpdLmtUnits : 15|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtRecmndSpd : 31|8@0+ (1,0) [0|255] "" XXX + SG_ IntlStdAlph2CddCntryCd : 33|10@0+ (1,0) [0|0] "" XXX + SG_ ISA2CCC_FrstCdChr : 33|5@0+ (1,0) [0|31] "" XXX + SG_ ISA2CCC_ScndCdChr : 44|5@0+ (1,0) [0|31] "" XXX + +BO_ 2156216320 TTY_Status_LS: 1 XXX + SG_ TxtTelephoneDevPr : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2158813184 ODIIndication_IPC_LS: 8 XXX + SG_ ODIInd_IPC : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODIIIPC_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODIIIPC_ODIInd8 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd7 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd6 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd5 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd4 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd3 : 13|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd2 : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd1 : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd16 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd15 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd14 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd13 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd12 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd11 : 21|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd10 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd9 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd24 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd23 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd22 : 26|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd21 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd20 : 28|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd19 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd18 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd17 : 31|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd32 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd31 : 33|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd30 : 34|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd29 : 35|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd28 : 36|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd27 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd26 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd25 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd40 : 40|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd39 : 41|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd38 : 42|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd37 : 43|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd36 : 44|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd35 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd34 : 46|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd33 : 47|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd48 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd47 : 49|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd46 : 50|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd45 : 51|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd44 : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd43 : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd42 : 54|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd41 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd56 : 56|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd55 : 57|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd54 : 58|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd53 : 59|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd52 : 60|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd51 : 61|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd50 : 62|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIIPC_ODIInd49 : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150277120 GPS_Geographical_Position_LS: 8 XXX + SG_ PsngSysLatGroup : 6|31@0+ (1,0) [0|0] "" XXX + SG_ PsngSysLat : 5|30@0- (1,0) [-536870912|536870911] "mas" XXX + SG_ PsngSysLatV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ PsngSysLongGroup : 39|32@0+ (1,0) [0|0] "" XXX + SG_ PsngSysLong : 38|31@0- (1,0) [-1073741824|1073741823] "mas" XXX + SG_ PsngSysLongV : 39|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150285312 GPS_Elevation_and_Heading_LS: 8 XXX + SG_ PsngSysHdingGroup : 3|37@0+ (1,0) [0|0] "" XXX + SG_ PsngSysHding : 3|12@0+ (0.1,0) [0|409.5] "deg" XXX + SG_ PsngSysHdingV : 47|1@0+ (1,0) [0|1] "" XXX + SG_ PsngSysDilPrcsGroup : 4|29@0+ (1,0) [0|0] "" XXX + SG_ PsngSysDilPrcsV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PsngSysDilPrcs : 17|10@0+ (0.1,0) [0|102.3] "" XXX + SG_ PsngSysCalcSpdGroup : 39|10@0+ (1,0) [0|0] "" XXX + SG_ PsngSysCalcSpd : 39|8@0+ (1,0) [0|255] "km / h" XXX + SG_ PsngSysCalcSpdV : 46|1@0+ (1,0) [0|1] "" XXX + SG_ PsngSysElvtnGroup : 45|22@0+ (1,0) [0|0] "" XXX + SG_ PsngSysElvtn : 44|21@0+ (1,-100000) [-100000|1997151] "cm" XXX + SG_ PsngSysElvtnV : 45|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151890944 Telematics_Indication_Request_LS: 4 XXX + SG_ TlmtcsIndCntrlReq : 15|24@0+ (1,0) [0|0] "" XXX + SG_ TICR_Ind1Cnt : 11|4@0+ (1,0) [0|15] "" XXX + SG_ TICR_Ind1 : 13|2@0+ (1,0) [0|3] "" XXX + SG_ TICR_Ind1Req : 15|2@0+ (1,0) [0|3] "" XXX + SG_ TICR_Ind1FlshRtOff : 23|8@0+ (10,0) [0|2550] "ms" XXX + SG_ TICR_Ind1FlshRtOn : 31|8@0+ (10,0) [0|2550] "ms" XXX + +BO_ 2151251968 Telematics_Indication_Control_LS: 4 XXX + SG_ TlmtcsIndCntrlStat : 12|21@0+ (1,0) [0|0] "" XXX + SG_ TICS_Ind1V : 8|1@0+ (1,0) [0|1] "" XXX + SG_ TICS_Ind1 : 10|2@0+ (1,0) [0|3] "" XXX + SG_ TICS_Ind1Stat : 12|2@0+ (1,0) [0|3] "" XXX + SG_ TICS_Ind1FlshRtOffSt : 23|8@0+ (10,0) [0|2550] "ms" XXX + SG_ TICS_Ind1FlshRtOnSt : 31|8@0+ (10,0) [0|2550] "ms" XXX + +BO_ 2155495424 Remote_Start_Seat_Request_LS: 1 XXX + SG_ RmStrCldStEnReq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RmStrHtdStEnRq : 1|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149990400 HS_Indications_Fast_LS: 8 XXX + SG_ ABSIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ StpOnBrkToRelPBIndOn : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrBrkngVDA : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DrvThrtlOvrdIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TreInfMonSysRstPrfmd : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ACCHdwayStngIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ACCDrvrSeltdSpdIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrWiringFltIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ AdvHlmpsVDA : 9|1@0+ (1,0) [0|1] "" XXX + SG_ SADmpVDA : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ScndryAxleVDA : 11|1@0+ (1,0) [0|1] "" XXX + SG_ SrvTrlrBrkngSysIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrBrkngGainSetIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrCnctdIO : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ChkTrlrIO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrBrkngFrcOtpt : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ TrlrBrkngGainSet : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ TrlrHtchSwAtv_ITBC : 32|1@0+ (1,0) [0|1] "" XXX + SG_ TransNtrlCntrlMdStat : 34|2@0+ (1,0) [0|3] "" XXX + SG_ MotStBltFldIO : 35|1@0+ (1,0) [0|1] "" XXX + SG_ MotStBltUnblIO : 36|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsfrCsRngShfSpdLmt : 47|8@0+ (1,0) [0|255] "km / h" XXX + SG_ InstFuelConsmpRate : 51|12@0+ (0.025,0) [0|102.375] "liters/hr" XXX + SG_ SecAxlOperMod : 55|4@0+ (1,0) [0|15] "" XXX + +BO_ 2155380736 HS_Indications_SuperSlow_LS: 6 XXX + SG_ VehOvrLdIndOn : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SrvLevSysIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HdLtLvlFlrIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RrLevVDA : 3|1@0+ (1,0) [0|1] "" XXX + SG_ AirCndOffIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilHotIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ PTExPrtclFltrWrnIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ DslGlwPlgIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EngHotFuelEnrchmntIO : 8|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilChngIO : 9|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilLvlLwIO : 10|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilPrsLwIO : 11|1@0+ (1,0) [0|1] "" XXX + SG_ EngWtrInFlIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ RdcdPwrIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ CkFlFilrCapIO : 14|1@0+ (1,0) [0|1] "" XXX + SG_ EngHt_StpEngIO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ StrAsstRdcdLvl2IO : 16|1@0+ (1,0) [0|1] "" XXX + SG_ PwrStrIO : 17|1@0+ (1,0) [0|1] "" XXX + SG_ PTExPrtclFltrWrn2IO : 18|1@0+ (1,0) [0|1] "" XXX + SG_ AdvFrntLghtSysIndRq : 21|3@0+ (1,0) [0|7] "" XXX + SG_ StrngAsstRdcdIO : 22|1@0+ (1,0) [0|1] "" XXX + SG_ StrAsstRdcdLvl3IO : 23|1@0+ (1,0) [0|1] "" XXX + SG_ PwrPckAirInTempFlt : 31|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ PwrPkFnSpd : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ ARSFlrIO : 40|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150498304 Analog_Values_Slow_LS: 8 XXX + SG_ EngCltTmpGroup : 0|57@0+ (1,0) [0|0] "" XXX + SG_ EngCltTmpV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ EngCltTmp : 63|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ EngIntAirTmpGroup : 1|50@0+ (1,0) [0|0] "" XXX + SG_ EngIntAirTmpV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ EngIntAirTmp : 55|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ EngOilTmpGroup : 2|43@0+ (1,0) [0|0] "" XXX + SG_ EngOilTmpV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilTmp : 47|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ OAT_PT_EstGroup : 4|37@0+ (1,0) [0|0] "" XXX + SG_ OAT_PT_EstV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ OAT_PT_EstM : 4|1@0+ (1,0) [0|1] "" XXX + SG_ OAT_PT_Est : 39|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + SG_ TrnOilTmpGroup : 5|30@0+ (1,0) [0|0] "" XXX + SG_ TrnOilTmpV : 5|1@0+ (1,0) [0|1] "" XXX + SG_ TrnOilTmp : 31|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ BarPrsAbsGroup : 6|23@0+ (1,0) [0|0] "" XXX + SG_ BarPrsAbsV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ BarPrsAbs : 23|8@0+ (0.5,0) [0|127.5] "kPa" XXX + SG_ EngOilPrsGroup : 7|16@0+ (1,0) [0|0] "" XXX + SG_ EngOilPrsV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilPrs : 15|8@0+ (4,0) [0|1020] "kPa" XXX + +BO_ 2151047168 HUD_Status_LS: 1 XXX + SG_ HUDActv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ HdUpDspAnmtStat : 3|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155331584 Wheel_Pulses_LS: 4 XXX + SG_ WhlPlsPerRevDrvn : 6|7@0+ (1,0) [0|127] "" XXX + SG_ WhlPlsPerRevNonDrvn : 14|7@0+ (1,0) [0|127] "" XXX + SG_ WhlRotStatTmstmpRes : 18|11@0+ (0.002,0) [0|4.094] "uSec" XXX + +BO_ 2154225664 Door_Handle_Switch_Status_LS: 1 XXX + SG_ DrvDrHndleSwAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ PasDrHndleSwAtv : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RCHndleSwAtv : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RRDrHndleSwAtv : 3|1@0+ (1,0) [0|1] "" XXX + SG_ RLDrHndleSwAtv : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149900288 Telematics_Contol_LS: 3 XXX + SG_ EnhSrvRClsRlsRq : 1|1@0+ (1,0) [0|1] "" XXX + SG_ EnhSrvVisAlRq : 3|2@0+ (1,0) [0|3] "" XXX + SG_ EnhSrvAudAlRq : 5|2@0+ (1,0) [0|3] "" XXX + SG_ EnhSrvRmStrtRq : 7|2@0+ (1,0) [0|3] "" XXX + SG_ EnhSrvLckRq : 10|3@0+ (1,0) [0|7] "" XXX + SG_ BTTethrngPrngReq : 14|4@0+ (1,0) [0|15] "" XXX + SG_ EnhSvVehTopSpdLim : 23|8@0+ (2,0) [0|510] "km / h" XXX + +BO_ 2159001600 ODIEnumDynamicData_IPC_LS: 8 XXX + SG_ ODIEnmDynData_IPC : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIEDDIPC_Data2Value : 2|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data1Value : 5|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data5Value : 9|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data4Value : 12|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data3Value : 15|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data8Value : 16|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data7Value : 19|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data6Value : 22|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data10Value : 26|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data9Value : 29|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data13Value : 33|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data12Value : 36|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data11Value : 39|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data16Value : 40|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data15Value : 43|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data14Value : 46|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data18Value : 50|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_Data17Value : 53|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDIPC_FUCID : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2158993408 ODIEnumDynamicData_CntrStack_LS: 8 XXX + SG_ ODIEnmDynData_CenterStack : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIEDDCS_Data2Value : 2|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data1Value : 5|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data5Value : 9|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data4Value : 12|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data3Value : 15|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data8Value : 16|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data7Value : 19|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data6Value : 22|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data10Value : 26|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data9Value : 29|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data13Value : 33|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data12Value : 36|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data11Value : 39|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data16Value : 40|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data15Value : 43|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data14Value : 46|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data18Value : 50|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_Data17Value : 53|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDDCS_FUCID : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2154708992 Audio_Master_Source_Status_LS: 2 XXX + SG_ AudSrcStat2 : 3|12@0+ (1,0) [0|0] "" XXX + SG_ ASS2AudSrcType : 3|5@0+ (1,0) [0|31] "" XXX + SG_ ASS2AudSrcStatCode : 11|4@0+ (1,0) [0|15] "" XXX + SG_ ASS2AudSrcChType : 14|3@0+ (1,0) [0|7] "" XXX + +BO_ 2158985216 ODIDynDataMultiReq_OTIM_LS: 8 XXX + SG_ ODIDynDataMltRq_OTIM : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODDMO_DataID2Vld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMO_DataID3Vld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMO_DataID4Vld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMO_DataID5Vld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMO_ReqType : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ODDMO_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMO_DispMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMO_DataID1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMO_DataID2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMO_DataID3 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMO_DataID4 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMO_DataID5 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2154471424 Rear_Closure_Ajar_Switch_Status: 1 XXX + SG_ RrClosAjarSwAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RrClsrSnwLdIO : 1|1@0+ (1,0) [0|1] "" XXX + +BO_ 2159149056 ODI_TEL_2_CenterStack_LS: 8 XXX + SG_ ODI_TEL2CntrStck : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159116288 ODI_TEL_2_AuxIP_LS: 8 XXX + SG_ ODI_TEL2AxIP : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2158796800 ODIIndication_LS: 8 XXX + SG_ ODIInd : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODII_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODII_ODIInd8 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd7 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd6 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd5 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd4 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd3 : 13|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd2 : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd1 : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd16 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd15 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd14 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd13 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd12 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd11 : 21|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd10 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd9 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd24 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd23 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd22 : 26|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd21 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd20 : 28|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd19 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd18 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd17 : 31|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd32 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd31 : 33|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd30 : 34|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd29 : 35|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd28 : 36|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd27 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd26 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd25 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd40 : 40|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd39 : 41|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd38 : 42|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd37 : 43|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd36 : 44|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd35 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd34 : 46|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd33 : 47|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd48 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd47 : 49|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd46 : 50|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd45 : 51|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd44 : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd43 : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd42 : 54|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd41 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd56 : 56|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd55 : 57|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd54 : 58|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd53 : 59|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd52 : 60|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd51 : 61|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd50 : 62|1@0+ (1,0) [0|1] "" XXX + SG_ ODII_ODIInd49 : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 2158755840 ODIEvent_LS: 4 XXX + SG_ ODIEvntPkt : 13|22@0+ (1,0) [0|0] "" XXX + SG_ ODIE_EvID : 13|6@0+ (1,0) [0|63] "" XXX + SG_ ODIE_FUCID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIE_MultiFrRetCh : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 2159157248 ODI_CenterStack_2_TEL_LS: 8 XXX + SG_ ODI_CntrStck2TEL : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2153955328 Infrastructure_Timer_Status_LS: 5 XXX + SG_ EngOffTmExtRngGroup : 0|33@0+ (1,0) [0|0] "" XXX + SG_ EngOffTmExtRngV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ EngOffTmExtRng : 39|8@0+ (4,0) [0|1020] "min" XXX + SG_ ElpsdTimeCntRstOcc : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ElpsdTimeCnt : 15|24@0+ (1,0) [0|16777215] "min" XXX + +BO_ 2151063552 Infotainment_Operation_LS: 7 XXX + SG_ InftnOprAlwd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ValetMdAct : 1|1@0+ (1,0) [0|1] "" XXX + SG_ Frnt360CamSwAct : 2|1@0+ (1,0) [0|1] "" XXX + SG_ CamVideoICSDispAct : 3|1@0+ (1,0) [0|1] "" XXX + SG_ LRStStatDispAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RRStStatDispAct : 5|1@0+ (1,0) [0|1] "" XXX + SG_ TrgdVidRecSwAct : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RrPedDetCstStReq : 10|3@0+ (1,0) [0|7] "" XXX + SG_ IntrStopAlrtCsSetReq : 13|3@0+ (1,0) [0|7] "" XXX + SG_ ICSTchStat : 17|34@0+ (1,0) [0|0] "" XXX + SG_ ICSTS_TchPrxmty : 17|2@0+ (1,0) [0|3] "" XXX + SG_ ICSTS_X1TchCrdnt : 31|16@0+ (0.001526,0) [0|100] "" XXX + SG_ ICSTS_Y1TchCrdnt : 47|16@0+ (0.001526,0) [0|100] "" XXX + SG_ TrfRdsdInfCsStReq : 20|3@0+ (1,0) [0|7] "" XXX + SG_ CntdVehBrAltCsStReq : 23|3@0+ (1,0) [0|7] "" XXX + +BO_ 2157985792 Fob_Programming_Request_LS: 1 XXX + SG_ FobProgEvntRqd : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151284736 Park_Assistant_General_Status: 1 XXX + SG_ PrkAsstClnPrkAstIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAsstDisablIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstFld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstSnrsBlk : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstSnsDistrbdIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvPrkAstOffUnbIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAstOprtrDsrdStat_1D0 : 7|2@0+ (1,0) [0|3] "" XXX + +BO_ 2159099904 ODI_DAB_2_AuxIP_LS: 8 XXX + SG_ ODI_DAB2AxIP : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159067136 ODI_DAB_2_IPC_LS: 8 XXX + SG_ ODI_DAB2IPC : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159206400 ODI_AuxIP_2_IPC_LS: 8 XXX + SG_ ODI_AxIP2IPC : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159198208 ODI_IPC_2_AuxIP_LS: 8 XXX + SG_ ODI_IPC2AxIP : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159190016 ODI_AuxIP_2_CenterStack_LS: 8 XXX + SG_ ODI_AxIP2CntrStck : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159181824 ODI_CenterStack_2_AuxIP_LS: 8 XXX + SG_ ODI_CntrStck2AxIP : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159173632 ODI_IPC_2_CenterStack_LS: 8 XXX + SG_ ODI_IPC2CntrStck : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159165440 ODI_CenterStack_2_IPC_LS: 8 XXX + SG_ ODI_CntrStck2IPC : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159108096 ODI_AuxIP_2_DAB_LS: 8 XXX + SG_ ODI_AxIP2DAB : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159075328 ODI_IPC_2_DAB_LS: 8 XXX + SG_ ODI_IPC2DAB : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2151718912 Chime_Active: 1 XXX + SG_ ChmAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ChmVolSt : 2|2@0+ (1,0) [0|3] "" XXX + +BO_ 2155479040 Customization_Setting_Request_LS: 5 XXX + SG_ DrvlnCustStngReq : 2|3@0+ (1,0) [0|7] "" XXX + SG_ RstrCustFctrDef : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PedFrndlyAlrtCsStReq : 6|3@0+ (1,0) [0|7] "" XXX + SG_ SusCustStngReq : 10|3@0+ (1,0) [0|7] "" XXX + SG_ StrCustStngReq : 13|3@0+ (1,0) [0|7] "" XXX + SG_ ElvtdIdlCstStReq : 15|2@0+ (1,0) [0|3] "" XXX + SG_ SndPerfMdCsStRq : 18|3@0+ (1,0) [0|7] "" XXX + SG_ DispPerfMdCsStRq : 21|3@0+ (1,0) [0|7] "" XXX + SG_ ACCPerfMdCsStReq : 26|3@0+ (1,0) [0|7] "" XXX + SG_ DrvrStPerfMdCsStReq : 29|3@0+ (1,0) [0|7] "" XXX + SG_ PsngStPerfMdCsStReq : 34|3@0+ (1,0) [0|7] "" XXX + SG_ DrvStyPerfMdCsStReq : 37|3@0+ (1,0) [0|7] "" XXX + +BO_ 2151383040 Reset_TP_request_LS: 1 XXX + SG_ TreInfMonSysRstReq : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155421696 Passive_Entry_Challenge_LS: 5 XXX + SG_ PsvEntChlng : 7|32@0+ (1,0) [0|4294967295] "passwrd" XXX + SG_ ServKylsStSysIO : 32|1@0+ (1,0) [0|1] "" XXX + SG_ PsvEntApprchDtcd : 33|1@0+ (1,0) [0|1] "" XXX + SG_ PsvEntAprchDrctn : 36|3@0+ (1,0) [0|7] "" XXX + SG_ PsvEntApprchCnfgReq : 39|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155413504 Drv_Dr_Key_Cyl_Status_LS: 3 XXX + SG_ DrvrDrKeyCylUlkSwActGroup : 1|2@0+ (1,0) [0|0] "" XXX + SG_ DrvrDrKeyCylUlkSwAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrvrDrKeyCylUlkSwActV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PsvLckngReqd : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PsvApprchVehId : 15|16@0+ (1,0) [0|65535] "" XXX + +BO_ 2159026176 ODIDynamicData_LS: 8 XXX + SG_ ODIDynData : 14|55@0+ (1,0) [0|0] "" XXX + SG_ ODD_InvldData : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ODD_DataType : 14|6@0+ (1,0) [0|63] "" XXX + SG_ ODD_FUCID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODD_DataId : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODD_DataVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2158936064 ODIEnumDynamicData_LS: 8 XXX + SG_ ODIEnmDynData : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIEDD_Data2Value : 2|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data1Value : 5|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data5Value : 9|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data4Value : 12|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data3Value : 15|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data8Value : 16|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data7Value : 19|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data6Value : 22|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data10Value : 26|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data9Value : 29|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data13Value : 33|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data12Value : 36|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data11Value : 39|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data16Value : 40|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data15Value : 43|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data14Value : 46|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data18Value : 50|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_Data17Value : 53|3@0+ (1,0) [0|7] "" XXX + SG_ ODIEDD_FUCID : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2158845952 ODIAction_CntrStack_LS: 8 XXX + SG_ ODIActn_CntrStck : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIAC_DaTy : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ODIAC_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAC_ActnID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAC_DspMID : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAC_ActnVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2158886912 ODIDynDataListRequest_IPC_LS: 8 XXX + SG_ ODIDynDataLstRq_IPC : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODDLI_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLI_DataId : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLI_DspMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLI_ReqDir : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLI_NmEntries : 31|7@0+ (1,0) [0|127] "" XXX + SG_ ODDLI_Idx : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ ODDLI_SubIdReqM : 51|12@0+ (1,0) [0|4095] "" XXX + SG_ ODDLI_WrpArnd : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLI_BckgndFlag : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLI_ReqType : 55|2@0+ (1,0) [0|3] "" XXX + +BO_ 2151366656 Man_Prk_Brk_LS: 1 XXX + SG_ RrAxlLckIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ FrntAxlLckIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PrkBrkSwAtv : 2|1@0+ (1,0) [0|1] "" XXX + SG_ AxlLcksServIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ AxlLckUnavailIndReq : 6|3@0+ (1,0) [0|7] "" XXX + SG_ AxlLcksVDA : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149842944 Vehicle_Stability_LS: 8 XXX + SG_ IMUProtLonAccGroup : 2|11@0+ (1,0) [0|0] "" XXX + SG_ IMUProtLonAcc : 1|10@0- (0.03,0) [-15.36|15.33] "m/s^2" XXX + SG_ IMUProtLonAccV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ TCSysAtv : 3|1@0+ (1,0) [0|1] "" XXX + SG_ BrkSysAutBrkFld : 4|1@0+ (1,0) [0|1] "" XXX + SG_ VSEAct : 5|1@0+ (1,0) [0|1] "" XXX + SG_ StrWhAngGroup : 6|47@0+ (1,0) [0|0] "" XXX + SG_ StrWhAngV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ StrWhAng : 39|16@0- (0.0625,0) [-2048|2047.9375] "deg" XXX + SG_ StWhAnVDA : 7|1@0+ (1,0) [0|1] "" XXX + SG_ VehStabEnhmntStat : 18|3@0+ (1,0) [0|7] "" XXX + SG_ VehStabEnhmntMd : 21|3@0+ (1,0) [0|7] "" XXX + SG_ StrWhlAngSenCalStat : 23|2@0+ (1,0) [0|3] "" XXX + SG_ TCSysOpMd : 26|3@0+ (1,0) [0|7] "" XXX + SG_ TCSysOpStat : 29|3@0+ (1,0) [0|7] "" XXX + SG_ VSELatAccGroup : 52|13@0+ (1,0) [0|0] "" XXX + SG_ VSELatAcc : 51|12@0- (0.015625,0) [-32|31.984375] "m/s^2" XXX + SG_ VSELatAccV : 52|1@0+ (1,0) [0|1] "" XXX + SG_ AdptDrvrSeatStng : 55|3@0+ (1,0) [0|7] "" XXX + +BO_ 2159132672 ODIAction_RearSeat_LS: 8 XXX + SG_ ODIActn_RSD : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIAR_DaTy : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ODIAR_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAR_ActnID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAR_DspMID : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAR_ActnVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2158968832 ODI_RearSeat_2_Centerstack_LS: 8 XXX + SG_ ODI_RSD2CntrStck : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2158960640 ODIIndication_Centerstack_LS: 8 XXX + SG_ ODIInd_CntrStck : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODIIC_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODIIC_ODIInd8 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd7 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd6 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd5 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd4 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd3 : 13|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd2 : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd1 : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd16 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd15 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd14 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd13 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd12 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd11 : 21|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd10 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd9 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd24 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd23 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd22 : 26|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd21 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd20 : 28|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd19 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd18 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd17 : 31|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd32 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd31 : 33|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd30 : 34|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd29 : 35|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd28 : 36|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd27 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd26 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd25 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd40 : 40|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd39 : 41|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd38 : 42|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd37 : 43|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd36 : 44|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd35 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd34 : 46|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd33 : 47|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd48 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd47 : 49|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd46 : 50|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd45 : 51|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd44 : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd43 : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd42 : 54|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd41 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd56 : 56|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd55 : 57|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd54 : 58|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd53 : 59|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd52 : 60|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd51 : 61|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd50 : 62|1@0+ (1,0) [0|1] "" XXX + SG_ ODIIC_ODIInd49 : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 2158977024 ODIEvent_Centerstack_LS: 4 XXX + SG_ ODIEvntPkt_CntrStck : 13|22@0+ (1,0) [0|0] "" XXX + SG_ ODIEC_EvID : 13|6@0+ (1,0) [0|63] "" XXX + SG_ ODIEC_FUCID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIEC_MultiFrRetCh : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 2158952448 ODIDynDataMultiReq_RearSeat_LS: 8 XXX + SG_ ODIDynDataMltRq_RSD : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODDMR_DataID2Vld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMR_DataID3Vld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMR_DataID4Vld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMR_DataID5Vld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMR_ReqType : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ODDMR_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMR_DispMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMR_DataID1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMR_DataID2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMR_DataID3 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMR_DataID4 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMR_DataID5 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2158944256 ODIDynDataListReq_RearSeat_LS: 8 XXX + SG_ ODIDynDataLstRq_RSD : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODDLR_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLR_DataId : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLR_DspMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLR_ReqDir : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLR_NmEntries : 31|7@0+ (1,0) [0|127] "" XXX + SG_ ODDLR_Idx : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ ODDLR_SubIdReqM : 51|12@0+ (1,0) [0|4095] "" XXX + SG_ ODDLR_WrpArnd : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLR_BckgndFlag : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLR_ReqType : 55|2@0+ (1,0) [0|3] "" XXX + +BO_ 2158927872 ODI_DynData_CenterStack_LS: 8 XXX + SG_ ODIDynData_CntrStck : 14|55@0+ (1,0) [0|0] "" XXX + SG_ ODDC_InvldData : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ODDC_DataType : 14|6@0+ (1,0) [0|63] "" XXX + SG_ ODDC_FUCID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDC_DataId : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDC_DataVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2158895104 ODI_CenterStack_2_RearSeat_LS: 8 XXX + SG_ ODI_CntrStck2RSD : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2152038400 Infomatics_Response_Payload_LS: 8 XXX + SG_ InfMdRspPld : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2152022016 Infomatics_Metadata_Response_LS: 7 XXX + SG_ InfMdRspCmplt : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ InfMdRspInf : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ InfMdStRsp : 35|4@0+ (1,0) [0|15] "" XXX + SG_ AudSelctdSrcReq : 44|5@0+ (1,0) [0|31] "" XXX + SG_ AudSysVolSetCtrl : 55|8@0+ (1,0) [0|0] "" XXX + SG_ ASVSC_ReqEnbld : 48|1@0+ (1,0) [0|1] "" XXX + SG_ ASVSC_VolReq : 55|7@0+ (0.787402,0) [0|100.000054] "" XXX + +BO_ 2152005632 Infomatics_Request_Payload_LS: 8 XXX + SG_ InfMdRqstPld : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2151989248 Infomatics_Metadata_Request_LS: 5 XXX + SG_ InfMdRqstCmplt : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ InfMdRqstInt : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ InfMdStReq : 35|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151972864 Fuel_Level_Status_LS: 4 XXX + SG_ FuelLvlLwIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ LnchCtrlMdReq : 2|2@0+ (1,0) [0|3] "" XXX + SG_ LnchCtrlWhlSlpReq : 7|5@0+ (1,0) [0|31] "" XXX + SG_ VehFuelRngCalcGroup : 9|18@0+ (1,0) [0|0] "" XXX + SG_ VehFuelRngCalc : 8|17@0+ (0.015625,0) [0|2047.984375] "km" XXX + SG_ VehFuelRngCalcV : 9|1@0+ (1,0) [0|1] "" XXX + SG_ LnchCtrlEngRPMReq : 15|6@0+ (1,0) [0|63] "" XXX + +BO_ 2154528768 Wheel_Grnd_Velocity_LS: 8 XXX + SG_ WhlGrndVlctyLftDrvnGroup : 6|15@0+ (1,0) [0|0] "" XXX + SG_ WhlGrndVlctyLftDrvn : 5|14@0+ (0.03125,0) [0|511.96875] "km / h" XXX + SG_ WhlGrndVlctyLftDrvnV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ WhlGrndVlctyLftNnDrvnGroup : 22|15@0+ (1,0) [0|0] "" XXX + SG_ WhlGrndVlctyLftNnDrvn : 21|14@0+ (0.03125,0) [0|511.96875] "km / h" XXX + SG_ WhlGrndVlctyLftNnDrvnV : 22|1@0+ (1,0) [0|1] "" XXX + SG_ WhlGrndVlctyRtDrvnGroup : 38|15@0+ (1,0) [0|0] "" XXX + SG_ WhlGrndVlctyRtDrvn : 37|14@0+ (0.03125,0) [0|511.96875] "km / h" XXX + SG_ WhlGrndVlctyRtDrvnV : 38|1@0+ (1,0) [0|1] "" XXX + SG_ WhlGrndVlctyRtNnDrvnGroup : 54|15@0+ (1,0) [0|0] "" XXX + SG_ WhlGrndVlctyRtNnDrvn : 53|14@0+ (0.03125,0) [0|511.96875] "km / h" XXX + SG_ WhlGrndVlctyRtNnDrvnV : 54|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150916096 Park_Heater_Info_LS: 4 XXX + SG_ PrkHtrAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ClntCircPmpAct : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PrkHtrCoolntTempGroup : 2|11@0+ (1,0) [0|0] "" XXX + SG_ PrkHtrCoolntTempV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PrkHtrCoolntTemp : 15|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ PrkHtrFlCsmdRlCntRsOc : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PrkHtrFlCnsmdRolCntGroup : 4|29@0+ (1,0) [0|0] "" XXX + SG_ PrkHtrFlCnsmdRolCntV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PrkHtrFlCnsmdRolCnt : 23|16@0+ (3.05176E-006,0) [0|0.1999970916] "liters" XXX + SG_ PrkHtrPrhtAch : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150367232 Immobilizer_Identifier_LS: 5 XXX + SG_ ImoId : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ LrnEnvId : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ LrnEnvIdSt : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ImoIdSt : 33|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150621184 Keyless_Start_Auth_LS: 1 XXX + SG_ KylsStrAuthRslt : 7|8@0+ (1,0) [0|0] "" XXX + SG_ KSARUID8 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID7 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID6 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID5 : 3|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID4 : 4|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID3 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID2 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ KSARUID1 : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151309312 Inflatable_Restraints_Key_Id_LS: 2 XXX + SG_ InflRestId : 7|16@0+ (1,0) [0|39321] "" XXX + +BO_ 2154061824 Window_Normalized_Indication_LS: 1 XXX + SG_ PsWndNtNrmIndOn : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrWndNtNrmIndOn : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RLWndNtNrmIndOn : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RRWndNtNrmIndOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ RmtWndMvmntAtv : 4|1@0+ (1,0) [0|1] "" XXX + SG_ WndOprAlwd : 5|1@0+ (1,0) [0|1] "" XXX + SG_ RrDrUnlckIO : 6|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154512384 Rear_Closure_Rel_Sw_Sta_LS: 1 XXX + SG_ RrClosRelSwActGroup : 1|2@0+ (1,0) [0|0] "" XXX + SG_ RrClosRelSwAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RrClosRelSwActV : 1|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155347968 HS_Indications_Slow_LS: 8 XXX + SG_ ActVbnCtrlMlfIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ PedtrnProtSysDpl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TirePrsLowIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACCUnavlbleDTWthrIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilStrvtnIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ SecAxlNonEmMalfIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ BrkFldLvlLwGroup : 7|4@0+ (1,0) [0|0] "" XXX + SG_ BrkFldLvlLwV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ BrkFldLvlLw : 7|1@0+ (1,0) [0|1] "" XXX + SG_ ACCSnsClnRqdIO : 8|1@0+ (1,0) [0|1] "" XXX + SG_ ACCTmpUnavlbleIO : 9|1@0+ (1,0) [0|1] "" XXX + SG_ EngRecmndUpshftIO : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ServAdpCrsCtrlIndOn : 11|1@0+ (1,0) [0|1] "" XXX + SG_ SrvSuspSysIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ BrkPadWrnIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ BrkSysMalFuncIndOn : 15|1@0+ (1,0) [0|1] "" XXX + SG_ EngEmsRelMalfIndReq : 18|3@0+ (1,0) [0|7] "" XXX + SG_ RrAxlMalfIO : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DrShftCntrlReqDndIO : 20|1@0+ (1,0) [0|1] "" XXX + SG_ CompOvrhtIndOn : 21|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsSkpShftIO : 22|1@0+ (1,0) [0|1] "" XXX + SG_ RrAxlTmpInhIO : 23|1@0+ (1,0) [0|1] "" XXX + SG_ SecAxlTmpInhIO : 24|1@0+ (1,0) [0|1] "" XXX + SG_ CPSAlrtOnlIO : 25|1@0+ (1,0) [0|1] "" XXX + SG_ EPBSysStatIndReq : 27|2@0+ (1,0) [0|3] "" XXX + SG_ EPBSysWrnIndReq : 29|2@0+ (1,0) [0|3] "" XXX + SG_ CPSFldIO : 30|1@0+ (1,0) [0|1] "" XXX + SG_ CPSOffIO : 31|1@0+ (1,0) [0|1] "" XXX + SG_ CPSUnblIO : 32|1@0+ (1,0) [0|1] "" XXX + SG_ SrvPedtrnProtSysIO : 33|1@0+ (1,0) [0|1] "" XXX + SG_ PedtrnProtSysDisbld : 34|1@0+ (1,0) [0|1] "" XXX + SG_ PedtrnProtVDA : 35|1@0+ (1,0) [0|1] "" XXX + SG_ AppCltchAutSrtIO : 36|1@0+ (1,0) [0|1] "" XXX + SG_ StBltTgtSetAvl : 37|1@0+ (1,0) [0|1] "" XXX + SG_ FourWhlDrvIndReq : 42|3@0+ (1,0) [0|7] "" XXX + SG_ EngRecDwnshftIO : 43|1@0+ (1,0) [0|1] "" XXX + SG_ StBltTgtCrtSetVal : 46|3@0+ (1,0) [0|7] "" XXX + SG_ HillDesCtrlRedVehSpIO : 47|1@0+ (1,0) [0|1] "" XXX + SG_ VehRollAngleGroup : 55|8@0+ (1,0) [0|0] "" XXX + SG_ VehRollAngle : 54|7@0+ (0.703125,-45) [-45|44.296875] "deg" XXX + SG_ VehRollAngleV : 55|1@0+ (1,0) [0|1] "" XXX + SG_ ACCPerfMdCsCrStVal : 58|3@0+ (1,0) [0|7] "" XXX + SG_ ACCPerfMdCsStAvl : 59|1@0+ (1,0) [0|1] "" XXX + SG_ DrvrStPerfMdCsCrStVal : 62|3@0+ (1,0) [0|7] "" XXX + SG_ DrvrStPerfMdCsStAvl : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149777408 Non_Drvn_Whl_Rot_Status_LS: 8 XXX + SG_ WhlRotStatLftNDrvn : 7|32@0+ (1,0) [0|0] "" XXX + SG_ WRSLNDWhlDistPCntr : 1|10@0+ (1,0) [0|1023] "counts" XXX + SG_ WRSLNDWhlDistVal : 2|1@0+ (1,0) [0|1] "" XXX + SG_ WRSLNDWhlRotStRst : 3|1@0+ (1,0) [0|1] "" XXX + SG_ WRSLNDSeqNum : 5|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSLNDWhlDisTpRC : 7|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSLNDWhlDistTstm : 23|16@0+ (1,0) [0|65535] "counts" XXX + SG_ WhlRotStatRghtNDrvn : 39|32@0+ (1,0) [0|0] "" XXX + SG_ WRSRNDWhlDistPCntr : 33|10@0+ (1,0) [0|1023] "counts" XXX + SG_ WRSRNDWhlDistVal : 34|1@0+ (1,0) [0|1] "" XXX + SG_ WRSRNDWhlRotStRst : 35|1@0+ (1,0) [0|1] "" XXX + SG_ WRSRNDSeqNum : 37|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSRNDWhlDisTpRC : 39|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSRNDWhlDistTstm : 55|16@0+ (1,0) [0|65535] "counts" XXX + +BO_ 2149769216 Driven_Whl_Rotational_Stat_LS: 8 XXX + SG_ WhlRotatStatLftDrvn : 7|32@0+ (1,0) [0|0] "" XXX + SG_ WRSLDWhlDistPlsCntr : 1|10@0+ (1,0) [0|1023] "counts" XXX + SG_ WRSLDWhlDistVal : 2|1@0+ (1,0) [0|1] "" XXX + SG_ WRSLDWhlRotStatRst : 3|1@0+ (1,0) [0|1] "" XXX + SG_ WRSLDSeqNum : 5|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSLDWhlDisTpRC : 7|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSLDWhlDistTmstm : 23|16@0+ (1,0) [0|65535] "counts" XXX + SG_ WhlRotatStatRtDrvn : 39|32@0+ (1,0) [0|0] "" XXX + SG_ WRSRDWhlDistPlsCntr : 33|10@0+ (1,0) [0|1023] "counts" XXX + SG_ WRSRDWhlDistVal : 34|1@0+ (1,0) [0|1] "" XXX + SG_ WRSRDWhlRotStatRst : 35|1@0+ (1,0) [0|1] "" XXX + SG_ WRSRDSeqNum : 37|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSRDWhlDisTpRC : 39|2@0+ (1,0) [0|3] "counts" XXX + SG_ WRSRDWhlDistTmstm : 55|16@0+ (1,0) [0|65535] "counts" XXX + +BO_ 2156789760 Time_of_Day_LS: 6 XXX + SG_ CldrYr : 7|8@0+ (1,2000) [2000|2255] "year" XXX + SG_ CldrMth : 11|4@0+ (1,0) [0|15] "" XXX + SG_ FrPedDetCsStReq : 14|3@0+ (1,0) [0|7] "" XXX + SG_ CldrDay : 20|5@0+ (1,0) [0|31] "days" XXX + SG_ SmrtHgBmAstCstSetReq : 23|3@0+ (1,0) [0|7] "" XXX + SG_ TmofDay : 24|17@0+ (1,0) [0|0] "" XXX + SG_ TOD_HrofDay : 24|5@0+ (1,0) [0|31] "hr" XXX + SG_ TOD_MinofHr : 35|6@0+ (1,0) [0|63] "min" XXX + SG_ TOD_SecofMin : 45|6@0+ (1,0) [0|63] "s" XXX + SG_ TimeDispFormat : 25|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155020288 Language_Selection_LS: 1 XXX + SG_ LngSelExt : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ChVolRq2 : 7|2@0+ (1,0) [0|3] "" XXX + +BO_ 2150432768 Engine_Information_4_LS: 8 XXX + SG_ TransOilTempSensPres : 0|1@0+ (1,0) [0|1] "" XXX + SG_ GenFldDutCycGroup : 1|42@0+ (1,0) [0|0] "" XXX + SG_ GenFldDutCycV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ GenFldDutCyc : 47|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ FuelFltLifRstPerf : 2|1@0+ (1,0) [0|1] "" XXX + SG_ TrnEmsMlfAtv : 3|1@0+ (1,0) [0|1] "" XXX + SG_ GrdBrkgAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsNEmsRltMalfActv : 5|1@0+ (1,0) [0|1] "" XXX + SG_ EngShtdwnPndgIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ EngManfldAirTempCrtdGroup : 7|16@0+ (1,0) [0|0] "" XXX + SG_ EngManfldAirTempCrtdV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EngManfldAirTempCrtd : 15|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ FuelTotCap : 19|12@0+ (0.125,0) [0|511.875] "liters" XXX + SG_ TrnsThrmlMngmntStat : 21|2@0+ (1,0) [0|3] "" XXX + SG_ PTHiElecLdReqd : 22|1@0+ (1,0) [0|1] "" XXX + SG_ EngOilRmnLf : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ FuelFltRmnLf : 63|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2155298816 Tire_Pressure_Sensor_Prog_Req_LS: 1 XXX + SG_ TrPrsSnsProgEvntRqd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TrPrsMntrTrLdRstRqstd : 2|2@0+ (1,0) [0|3] "" XXX + +BO_ 2158878720 ODIDynDataListReq_CntrStack_LS: 8 XXX + SG_ ODIDynDataLstRq_CntrStck : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODDLC_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLC_DataId : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLC_DspMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLC_ReqDir : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLC_NmEntries : 31|7@0+ (1,0) [0|127] "" XXX + SG_ ODDLC_Idx : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ ODDLC_SubIdReqM : 51|12@0+ (1,0) [0|4095] "" XXX + SG_ ODDLC_WrpArnd : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLC_BckgndFlag : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLC_ReqType : 55|2@0+ (1,0) [0|3] "" XXX + +BO_ 2158870528 ODIDynDataListRequest_AuxIP_LS: 8 XXX + SG_ ODIDynDataLstRq_AxIP : 7|64@0+ (1,0) [0|0] "" XXX + SG_ ODDLA_FUCID : 7|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLA_DataId : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLA_DspMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDLA_ReqDir : 24|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLA_NmEntries : 31|7@0+ (1,0) [0|127] "" XXX + SG_ ODDLA_Idx : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ ODDLA_SubIdReqM : 51|12@0+ (1,0) [0|4095] "" XXX + SG_ ODDLA_WrpArnd : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLA_BckgndFlag : 53|1@0+ (1,0) [0|1] "" XXX + SG_ ODDLA_ReqType : 55|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154692608 Audio_Source_Status_LS: 2 XXX + SG_ AudSrcStat : 3|12@0+ (1,0) [0|0] "" XXX + SG_ ASSAudSrcType : 3|5@0+ (1,0) [0|31] "" XXX + SG_ ASSAudSrcStatCode : 11|4@0+ (1,0) [0|15] "" XXX + SG_ ASSAudSrcChType : 14|3@0+ (1,0) [0|7] "" XXX + SG_ LgclAVChnl : 7|4@0+ (1,0) [0|15] "" XXX + +BO_ 2154627072 Audio_Master_Arbitration_Command: 2 XXX + SG_ AudMstrArbCom : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LgclAVChnl_368 : 7|4@0+ (1,0) [0|15] "" XXX + SG_ AudMstrSrcTyp : 12|5@0+ (1,0) [0|31] "" XXX + SG_ AudMstrChnnlTyp : 15|3@0+ (1,0) [0|7] "" XXX + +BO_ 2151112704 Occupant_Sensning_Status_LS: 2 XXX + SG_ FrntPassClass : 2|3@0+ (1,0) [0|7] "" XXX + SG_ FrPsSeatOccSnsOpMd : 5|3@0+ (1,0) [0|7] "N/A" XXX + SG_ FrPasSeatResCtrlOccStGroup : 7|14@0+ (1,0) [0|0] "" XXX + SG_ FrPasSeatResCtrlOccSt : 7|2@0+ (1,0) [0|3] "" XXX + SG_ FrPasSeatResCtrlOccStV : 10|1@0+ (1,0) [0|1] "" XXX + SG_ FrPsSeatOccFltSt : 9|2@0+ (1,0) [0|3] "N/A" XXX + SG_ FrPasSeatbltRemOccSt : 11|1@0+ (1,0) [0|1] "" XXX + +BO_ 2153938944 Remote_Reflash_Req_LS: 1 XXX + SG_ RmtRflshMdReqtd : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2159239168 ODI_TEL_2_OTIM_LS: 8 XXX + SG_ ODI_TEL2OTIM : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159230976 ODI_OTIM_2_TEL_LS: 8 XXX + SG_ ODI_OTIM2TEL : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159222784 ODI_PDIM_2_CenterStack_LS: 8 XXX + SG_ ODI_PDIM2CntrStck : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2159214592 ODI_CenterStack_2_PDIM_LS: 8 XXX + SG_ ODI_CntrStck2PDIM : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2158862336 ODIAction_OTIM_LS: 8 XXX + SG_ ODIActn_OTIM : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIAOT_DaTy : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ODIAOT_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAOT_ActnID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAOT_DspMID : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAOT_ActnVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2150662144 Environment_Id_Resp_3_LS: 3 XXX + SG_ EnvIdRsp3 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ EnvIdRspSt3 : 17|2@0+ (1,0) [0|3] "" XXX + +BO_ 2150653952 Environment_Id_Resp_2_LS: 3 XXX + SG_ EnvIdRsp2 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ EnvIdRspSt2 : 17|2@0+ (1,0) [0|3] "" XXX + +BO_ 2150850560 Seatbelt_Information_LS: 1 XXX + SG_ DrSbltAtcGroup : 1|2@0+ (1,0) [0|0] "" XXX + SG_ DrSbltAtc : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrSbltAtcV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PsSbltAtcGroup : 3|2@0+ (1,0) [0|0] "" XXX + SG_ PsSbltAtc : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PsSbltAtcV : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154659840 Column_Lock_Status_2: 2 XXX + SG_ UnlckRtryRotIndOn : 2|1@0+ (1,0) [0|1] "" XXX + SG_ UnlockRtryPshIndOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ StrgClmnLckVisNot : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ClmnLckStatGroup : 5|6@0+ (1,0) [0|0] "" XXX + SG_ ClmnLckStat : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ClmnLckStatV : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ClmSysFlrIndOn : 7|1@0+ (1,0) [0|1] "" XXX + SG_ StrngClmnLckTT : 9|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154938368 Fob_Programming_Mode_Status_LS: 1 XXX + SG_ FobProgMdStat : 1|2@0+ (1,0) [0|3] "" XXX + +BO_ 2155266048 Rear_Seat_Heat_Cool_Switches_LS: 1 XXX + SG_ RLHCSeatSw1Act : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSeatSw2Act : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSeatSw3Act : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSeatSw1Act : 3|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSeatSw2Act : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSeatSw3Act : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155249664 Rear_Seat_Heat_Cool_Control_LS: 4 XXX + SG_ RLHCSModeIndCtrl : 4|5@0+ (1,0) [0|0] "" XXX + SG_ RLHCSMInd3 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSMInd2 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSMInd1 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSMIndReq : 4|2@0+ (1,0) [0|3] "" XXX + SG_ RRHCSModeIndCtrl : 12|5@0+ (1,0) [0|0] "" XXX + SG_ RRHCSMInd3 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSMInd2 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSMInd1 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSMIndReq : 12|2@0+ (1,0) [0|3] "" XXX + SG_ RLHCSeatLevIndCtrl : 22|7@0+ (1,0) [0|0] "" XXX + SG_ RLHCSLSeatLev5 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSLSeatLev4 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSLSeatLev3 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSLSeatLev2 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSLSeatLev1 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RLHCSLIndReq : 22|2@0+ (1,0) [0|3] "" XXX + SG_ RRHCSeatLevIndCtrl : 30|7@0+ (1,0) [0|0] "" XXX + SG_ RRHCSLSeatLev5 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSLSeatLev4 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSLSeatLev3 : 26|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSLSeatLev2 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSLSeatLev1 : 28|1@0+ (1,0) [0|1] "" XXX + SG_ RRHCSLIndReq : 30|2@0+ (1,0) [0|3] "" XXX + +BO_ 2155184128 CruiseControl_LS: 3 XXX + SG_ CrsCntAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CrsSpdLmtrSwStat : 4|4@0+ (1,0) [0|15] "" XXX + SG_ TrnsShftLvrLckStat : 5|1@0+ (1,0) [0|1] "" XXX + SG_ RrStRmndrIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RrStRmndrCstSetAvail : 7|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntrlSwStat : 15|8@0+ (1,0) [0|0] "" XXX + SG_ CrsCntrlSwStSwDataIntgty : 9|2@0+ (1,0) [0|3] "" XXX + SG_ CrsCntrlSwStSpDcSwAct : 10|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntrlSwStSpdInSwAct : 11|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntrlSwStSetSwAct : 12|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntrlSwStResSwAct : 13|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntrlSwStOnSwAct : 14|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntrlSwStCanSwAct : 15|1@0+ (1,0) [0|1] "" XXX + SG_ SmPhRmFunCstCurStVal : 18|3@0+ (1,0) [0|7] "" XXX + SG_ SmPhRmFunCstStAval : 19|1@0+ (1,0) [0|1] "" XXX + SG_ IdlRecmndToClEngIO : 20|1@0+ (1,0) [0|1] "" XXX + SG_ RrStRmndrCstCurrSetVal : 23|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155167744 Power_Mode_Info_LS: 3 XXX + SG_ ShftPrkIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ShftToNtrlIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ Ky_IdDevPr : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SecPwrMdPshBtnAtv : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TransModActIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TransModInactIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ KylsStrtUseTxPckIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ TrStLgMdAtv : 7|1@0+ (1,0) [0|1] "" XXX + SG_ VehMovState : 10|3@0+ (1,0) [0|7] "" XXX + SG_ AutoShtdwnDsblIO : 11|1@0+ (1,0) [0|1] "" XXX + SG_ AppPrkBrkIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ NRmtDtdPsCluRstIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ ApplyBrkPdlIO : 14|1@0+ (1,0) [0|1] "" XXX + SG_ ApplyCltPdlIO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ NoReDetInOn : 16|1@0+ (1,0) [0|1] "" XXX + SG_ NRmtDtdPsBrkRstIO : 17|1@0+ (1,0) [0|1] "" XXX + SG_ PrsBtnAgnTTrnEngOffIO : 18|1@0+ (1,0) [0|1] "" XXX + SG_ TSLgMdPwrCtOWAtv : 19|1@0+ (1,0) [0|1] "" XXX + SG_ NRmtDtctdRstrtAllwd : 20|1@0+ (1,0) [0|1] "" XXX + SG_ PrsStrtAgnIO : 21|1@0+ (1,0) [0|1] "" XXX + SG_ PrsCltchPrsStrtAgnIO : 22|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154921984 Fob_Status_LS: 2 XXX + SG_ RFAFnc : 1|10@0+ (1,0) [0|0] "" XXX + SG_ RFRmtCntFobNm : 1|3@0+ (1,0) [0|7] "" XXX + SG_ RFRmtCntFobBatLw : 8|1@0+ (1,0) [0|1] "" XXX + SG_ RFRmtCntrlFobFnc : 14|6@0+ (1,0) [0|63] "" XXX + SG_ FobPogLimRchdIndOn : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151317504 Park_Assistant_Rear_Status: 4 XXX + SG_ PrkAsstRrExtdDist : 3|12@0+ (0.01,0) [0|40.95] "m" XXX + SG_ PrkAstRrSysStat : 5|2@0+ (1,0) [0|3] "" XXX + SG_ PARrRgn1ObjStat : 19|4@0+ (1,0) [0|15] "" XXX + SG_ PARrRgn2ObjStat : 23|4@0+ (1,0) [0|15] "" XXX + SG_ PARrRgn3ObjStat : 27|4@0+ (1,0) [0|15] "" XXX + SG_ PARrRgn4ObjStat : 31|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151301120 Park_Assistant_Front_Status: 4 XXX + SG_ PrkAsstFrtExtdDist : 3|12@0+ (0.01,0) [0|40.95] "m" XXX + SG_ PrkAstFrSysStat : 5|2@0+ (1,0) [0|3] "" XXX + SG_ PrkAstAdvSysAct : 6|1@0+ (1,0) [0|1] "" XXX + SG_ PrkAsstRrOffIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ PAFrtRgn1ObjStat : 19|4@0+ (1,0) [0|15] "" XXX + SG_ PAFrtRgn2ObjStat : 23|4@0+ (1,0) [0|15] "" XXX + SG_ PAFrtRgn3ObjStat : 27|4@0+ (1,0) [0|15] "" XXX + SG_ PAFrtRgn4ObjStat : 31|4@0+ (1,0) [0|15] "" XXX + +BO_ 2159083520 ODI_TEL_2_IPC_LS: 8 XXX + SG_ ODI_TEL2IPC : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2153922560 Climate_Control_Voltage_LS: 3 XXX + SG_ ClimCtrlVoltBstModReq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ClmtCtrlHtrEngRunRq : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HtrVlvRqstdPstn : 3|2@0+ (1,0) [0|3] "" XXX + SG_ ClntHtrElecPwrRatGroup : 4|13@0+ (1,0) [0|0] "" XXX + SG_ ClntHtrElecPwrRatV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ClntHtrElecPwrRat : 15|8@0+ (0.04,0) [0|10.2] "kW" XXX + SG_ ClmCtrHiVltPwrRqtd : 23|8@0+ (0.1,0) [0|25.5] "kW" XXX + +BO_ 2153807872 Door_Open_Switch_Status_LS: 1 XXX + SG_ DrDoorOpenSwActGroup : 1|2@0+ (1,0) [0|0] "" XXX + SG_ DrDoorOpenSwAct : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrDoorOpenSwActV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ PsDoorOpenSwActGroup : 3|2@0+ (1,0) [0|0] "" XXX + SG_ PsDoorOpenSwAct : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PsDoorOpenSwActV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ClmSysAuxFlrIndOn : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PsvStrtStrngClmnLckTT : 6|2@0+ (1,0) [0|3] "" XXX + +BO_ 2150703104 Audio_Amplifier_Status: 1 XXX + SG_ AudSysDigSigProcPres : 0|1@0+ (1,0) [0|1] "" XXX + SG_ AudSysSurSndSysPres : 1|1@0+ (1,0) [0|1] "" XXX + SG_ AudSysVNoisCompPres : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151399424 Wash_Level_LS: 1 XXX + SG_ WshFldLw : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151956480 Driver_Workload_LS: 2 XXX + SG_ DrvWrkldLvl : 3|4@0+ (1,0) [0|15] "" XXX + SG_ ClstrHMIAnmSt : 6|3@0+ (1,0) [0|7] "" XXX + SG_ ClstrHMIRdy : 7|1@0+ (1,0) [0|1] "" XXX + SG_ StrWhlThbwhlCnts : 13|6@0- (1,0) [-32|31] "counts" XXX + +BO_ 2151940096 Alarm_2_Request_LS: 7 XXX + SG_ Alrm2ExtRngReq : 1|26@0+ (1,0) [0|0] "" XXX + SG_ A2ERRAlrmReq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ A2ERRAlrmTime : 15|24@0+ (1,0) [0|16777215] "min" XXX + SG_ EstBulkIntAirTmpGroup : 2|35@0+ (1,0) [0|0] "" XXX + SG_ EstBulkIntAirTmpV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ EstBulkIntAirTmp : 39|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + SG_ EstIntRfSrfcTmpGroup : 3|44@0+ (1,0) [0|0] "" XXX + SG_ EstIntRfSrfcTmpV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ EstIntRfSrfcTmp : 47|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + SG_ EstIntHorzDshSrfTmpGroup : 4|53@0+ (1,0) [0|0] "" XXX + SG_ EstIntHorzDshSrfTmpM : 4|1@0+ (1,0) [0|1] "" XXX + SG_ EstIntHorzDshSrfTmp : 55|8@0+ (1,-40) [-40|215] "deg C" XXX + +BO_ 2151923712 Alarm_1_Request_LS: 5 XXX + SG_ Alrm1ExtRngReq : 1|26@0+ (1,0) [0|0] "" XXX + SG_ A1ERRAlrmReq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ A1ERRAlrmTime : 15|24@0+ (1,0) [0|16777215] "min" XXX + SG_ HLOCCstCurrSetVal : 6|3@0+ (1,0) [0|7] "" XXX + SG_ HLOCCstSetAvail : 7|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCstAvail : 39|7@0+ (1,0) [0|0] "" XXX + SG_ HLOCCA_Res4Avail : 33|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCA_Res3Avail : 34|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCA_Res2Avail : 35|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCA_Res1Avail : 36|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCA_OnOpnOnlyAvail : 37|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCA_OnAvail : 38|1@0+ (1,0) [0|1] "" XXX + SG_ HLOCCA_OffAvail : 39|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150645760 Environment_Id_Resp_1_LS: 3 XXX + SG_ EnvIdRsp1 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ EnvIdRspSt1 : 17|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152464384 Lane_Departure_Warning_LS: 3 XXX + SG_ LaneDepWrnDisbldIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ LnKpAstDisbldIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SrvcLaneDepWrnSysIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SrvcLnKpAstSysIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ HndsOffStrWhlDtIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TnDrvLDWOffUnbIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LftLnDepWrnSt : 7|2@0+ (1,0) [0|3] "" XXX + SG_ LaneDepWrnIndCntrl : 13|6@0+ (1,0) [0|0] "" XXX + SG_ LDWIC_LnDepWAWLn : 9|2@0+ (1,0) [0|3] "" XXX + SG_ LDWIC_Ind2 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ LDWIC_Ind1 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ LDWIC_IndReq : 13|2@0+ (1,0) [0|3] "" XXX + SG_ RtLnDepWrnSt : 15|2@0+ (1,0) [0|3] "" XXX + SG_ LnKpAstIndCntrl : 21|6@0+ (1,0) [0|0] "" XXX + SG_ LKAIC_AdbWngLn : 17|2@0+ (1,0) [0|3] "" XXX + SG_ LKAIC_Ind2 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ LKAIC_Ind1 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ LKAIC_IndReq : 21|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154971136 Front_Seat_Heat_Cool_Switches_LS: 1 XXX + SG_ DrvHCSeatSw1Act : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSeatSw2Act : 1|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSeatSw3Act : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSeatSw1Act : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSeatSw2Act : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSeatSw3Act : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154962944 Front_Seat_Heat_Cool_Control_LS: 4 XXX + SG_ DrvHCSModeIndCtrl : 4|5@0+ (1,0) [0|0] "" XXX + SG_ DrvHCSMInd3 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSMInd2 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSMInd1 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSMIndReq : 4|2@0+ (1,0) [0|3] "" XXX + SG_ PassHCSModeIndCtrl : 12|5@0+ (1,0) [0|0] "" XXX + SG_ PassHCSMInd3 : 8|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSMInd2 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSMInd1 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSMIndReq : 12|2@0+ (1,0) [0|3] "" XXX + SG_ DrvHCSLevIndCtrl : 22|7@0+ (1,0) [0|0] "" XXX + SG_ DrvHCSLSeatLev5 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSLSeatLev4 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSLSeatLev3 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSLSeatLev2 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSLSeatLev1 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ DrvHCSLIndReq : 22|2@0+ (1,0) [0|3] "" XXX + SG_ PassHCSeatLevIndCtrl : 30|7@0+ (1,0) [0|0] "" XXX + SG_ PassHCSLSeatLev5 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSLSeatLev4 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSLSeatLev3 : 26|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSLSeatLev2 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSLSeatLev1 : 28|1@0+ (1,0) [0|1] "" XXX + SG_ PassHCSLIndReq : 30|2@0+ (1,0) [0|3] "" XXX + +BO_ 2156232704 Alarm_Clock_Status_LS: 4 XXX + SG_ AlrmClkStat : 7|32@0+ (1,0) [0|0] "" XXX + SG_ ACSAlarm3 : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm2 : 3|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm1 : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm0 : 7|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm7 : 9|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm6 : 11|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm5 : 13|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm4 : 15|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm11 : 17|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm10 : 19|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm9 : 21|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm8 : 23|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm15 : 25|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm14 : 27|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm13 : 29|2@0+ (1,0) [0|3] "" XXX + SG_ ACSAlarm12 : 31|2@0+ (1,0) [0|3] "" XXX + +BO_ 2154987520 Hood_Status_LS: 1 XXX + SG_ HdStGroup : 2|3@0+ (1,0) [0|0] "" XXX + SG_ HdSt : 1|2@0+ (1,0) [0|3] "" XXX + SG_ HdStV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ WrlsChrgSysChrgStat : 5|3@0+ (1,0) [0|7] "" XXX + +BO_ 2154840064 Compass_Status_LS: 4 XXX + SG_ CmpsOctHdingDataSrc : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsModFltPrs : 1|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsModManCalInPrc : 2|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsZnNvrSet : 3|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsDecZone : 11|4@0+ (1,0) [0|15] "" XXX + SG_ CmpsOctHding : 14|3@0+ (1,0) [0|7] "" XXX + SG_ CmpsSatrtd : 15|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsCrHding : 23|16@0+ (0.0054932,0) [0|359.996862] "deg" XXX + +BO_ 2154676224 Compass_Request_LS: 1 XXX + SG_ CmpsDecZonCmndVal : 3|4@0+ (1,0) [0|15] "" XXX + SG_ CmpsDecZonSetReq : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsModManCalReq : 5|1@0+ (1,0) [0|1] "" XXX + SG_ CmpsModSlfTstReq : 6|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154643456 Auxiliary_Heater_Status_LS: 3 XXX + SG_ AuxHtrAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ HtrCoreInltClntTmpCalcGroup : 4|21@0+ (1,0) [0|0] "" XXX + SG_ HtrCoreInltClntTmpCalcV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ HtrCoreInltClntTmpCalc : 23|8@0+ (1,-40) [-40|215] "deg C" XXX + SG_ CCClntCrcFlwRtReq : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2154905600 Driver_Identifier_LS: 1 XXX + SG_ DrId : 2|3@0+ (1,0) [0|7] "" XXX + SG_ DrvSeatPrsMemID : 5|3@0+ (1,0) [0|7] "" XXX + +BO_ 2154954752 High_Volt_Climate_Pwr_Status_LS: 5 XXX + SG_ ClmtHtPwrRqd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ HtdStWhlCmd : 2|2@0+ (1,0) [0|3] "" XXX + SG_ HtdStWhlInd : 4|2@0+ (1,0) [0|3] "" XXX + SG_ HtdStWhlCtrlSrc : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ClntHtrElecPwrReq : 15|8@0+ (0.04,0) [0|10.2] "kW" XXX + SG_ EstACCompPwrRchCbnCmf : 23|8@0+ (0.04,0) [0|10.2] "kw" XXX + SG_ EstACCompPwrMtnCbnCmf : 31|8@0+ (0.04,0) [0|10.2] "kW" XXX + +BO_ 2153381888 Control_Power_Liftgate_LS: 4 XXX + SG_ FnshRrClsrMtnBfrDrvIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RrClsrObstclDtctd : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RrClsrInMtn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ RrClosOpenSwActGroup : 4|3@0+ (1,0) [0|0] "" XXX + SG_ RrClosOpenSwAct : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RrClosOpenSwActV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RrWprInhbRq : 5|1@0+ (1,0) [0|1] "" XXX + SG_ GrgPrgMdCmpl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ PwrLftgtInclAngGroup : 7|16@0+ (1,0) [0|0] "" XXX + SG_ PwrLftgtInclAngV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ PwrLftgtInclAng : 15|8@0+ (1,0) [0|255] "" XXX + SG_ VehIncAngEst : 23|8@0+ (1,0) [0|255] "deg" XXX + SG_ PwrLftgtMotStat : 26|3@0+ (1,0) [0|7] "" XXX + SG_ VltActRrAccUnavlIO : 27|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149752832 Chassis_Information_LS: 8 XXX + SG_ VehHghtStatGroup : 0|9@0+ (1,0) [0|0] "" XXX + SG_ VehHghtStatV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ VehHghtStat : 11|4@0+ (1,0) [0|15] "" XXX + SG_ IntBrkAssPreFilReq : 1|1@0+ (1,0) [0|1] "N/A" XXX + SG_ BksOvht : 2|1@0+ (1,0) [0|1] "" XXX + SG_ HalfSysFail : 3|1@0+ (1,0) [0|1] "" XXX + SG_ BrkSysRedBrkTlltlReq : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ABSAtv : 5|1@0+ (1,0) [0|1] "" XXX + SG_ DrvlnCustStngAvlbl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ StrCustStngAvlbl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ PrkBrkVDA : 12|1@0+ (1,0) [0|1] "" XXX + SG_ PowStVDA : 13|1@0+ (1,0) [0|1] "" XXX + SG_ RrDrCntVDA : 14|1@0+ (1,0) [0|1] "" XXX + SG_ BrkSysVDA : 15|1@0+ (1,0) [0|1] "" XXX + SG_ SprTireSt : 18|3@0+ (1,0) [0|7] "" XXX + SG_ EPBSysAudWarnReq : 20|2@0+ (1,0) [0|3] "" XXX + SG_ EPBSysDspMsgReq : 23|3@0+ (1,0) [0|7] "" XXX + SG_ DrvlnCustCurrStngVal : 26|3@0+ (1,0) [0|7] "" XXX + SG_ StrCustCurrStngVal : 29|3@0+ (1,0) [0|7] "" XXX + SG_ SusCustStngAvlbl : 30|1@0+ (1,0) [0|1] "" XXX + SG_ EBDFailed : 31|1@0+ (1,0) [0|1] "" XXX + SG_ SusCustCurrStngVal : 34|3@0+ (1,0) [0|7] "" XXX + SG_ HillDscntCntlSysStat : 37|3@0+ (1,0) [0|7] "" XXX + SG_ ElecPrkBrkStat : 39|2@0+ (1,0) [0|3] "" XXX + SG_ HlStrAssActIO : 41|1@0+ (1,0) [0|1] "" XXX + SG_ ColPrSysStngAvl : 42|1@0+ (1,0) [0|1] "" XXX + SG_ GNCustSetngAvlbl : 44|1@0+ (1,0) [0|1] "" XXX + SG_ GNCustCrntStngVal : 47|3@0+ (1,0) [0|7] "" XXX + SG_ CPSInfotmntMtReq : 49|2@0+ (1,0) [0|3] "" XXX + SG_ ColPrSysCrntStng : 52|3@0+ (1,0) [0|7] "" XXX + SG_ SndEnhcmtPerfMdRq : 55|3@0+ (1,0) [0|7] "" XXX + SG_ DispPerfMdCsCrStVal : 58|3@0+ (1,0) [0|7] "" XXX + SG_ DispPerfMdCsStAvl : 59|1@0+ (1,0) [0|1] "" XXX + SG_ SndPerfMdCsCrStVal : 62|3@0+ (1,0) [0|7] "" XXX + SG_ SndPerfMdCsStAvl : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151514112 Reset_OilLife_Request_LS: 1 XXX + SG_ EngOilLfRstRq : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2158903296 ODIDynDataMultiRequest_AuxIP_LS: 8 XXX + SG_ ODIDynDataMltRq_AuxIP : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODDMA_DataID2Vld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMA_DataID3Vld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMA_DataID4Vld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMA_DataID5Vld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMA_ReqType : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ODDMA_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMA_DispMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMA_DataID1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMA_DataID2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMA_DataID3 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMA_DataID4 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMA_DataID5 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2158911488 ODIDynDataMultiReq_CntrStack_LS: 8 XXX + SG_ ODIDynDataMltRq_CntrStck : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODDMC_DataID2Vld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMC_DataID3Vld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMC_DataID4Vld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMC_DataID5Vld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMC_ReqType : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ODDMC_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMC_DispMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMC_DataID1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMC_DataID2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMC_DataID3 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMC_DataID4 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMC_DataID5 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2158919680 ODIDynDataMultiRequest_IPC_LS: 8 XXX + SG_ ODIDynDataMltRq_IPC : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODDMI_DataID2Vld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMI_DataID3Vld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMI_DataID4Vld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMI_DataID5Vld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ODDMI_ReqType : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ODDMI_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMI_DispMID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMI_DataID1 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMI_DataID2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMI_DataID3 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMI_DataID4 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ODDMI_DataID5 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2151825408 Outside_Air_Temperature_LS: 3 XXX + SG_ OtsAirTmpCrValGroup : 0|9@0+ (1,0) [0|0] "" XXX + SG_ OtsAirTmpCrValV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ OtsAirTmpCrVal : 15|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + SG_ OtsAirTmpGroup : 1|18@0+ (1,0) [0|0] "" XXX + SG_ OtsAirTmpV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ OtsAirTmp : 23|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + SG_ OtsAirTmpCrValMsk : 2|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151153664 Rear_Window_Defog_Status_LS: 1 XXX + SG_ RrWndDfgOn : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151170048 Trailer_Status_LS: 2 XXX + SG_ TrlrHtchSwAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrBrkLtFld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrFgLtFld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrRvsLtFld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrTlLtFld : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrFgLtPrs : 5|1@0+ (1,0) [0|1] "" XXX + SG_ TrlrRtTrInLtFld : 6|1@0+ (1,0) [0|1] "" XXX + SG_ TrlLfTrInLtFld : 7|1@0+ (1,0) [0|1] "" XXX + SG_ LftSecTrnIndFld : 8|1@0+ (1,0) [0|1] "" XXX + SG_ RtSecTrnIndFld : 9|1@0+ (1,0) [0|1] "" XXX + SG_ DisRrPrmryLmps : 10|1@0+ (1,0) [0|1] "" XXX + SG_ RLftPrkLmpFld : 11|1@0+ (1,0) [0|1] "" XXX + SG_ RRPrkLmpFld : 12|1@0+ (1,0) [0|1] "" XXX + SG_ RrEndCrrStat : 13|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151841792 Wipe_Wash_Status_LS: 1 XXX + SG_ TurnWprIntIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RnSnsActIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RnSnsOffIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ WSWprAct : 3|1@0+ (1,0) [0|1] "" XXX + SG_ HtdFrntWSSt : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154995712 Air_Conditioning_Comp_Type_LS: 1 XXX + SG_ HVHtrOvrTmpIndOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ HVHtrFldIO : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154094592 Adjustable_Pedal_Motion_Inh_LS: 8 XXX + SG_ AdjPdlMotInhbtd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ IntDimSeldAnmTypStVal : 4|4@0+ (1,0) [0|15] "" XXX + SG_ IntDimSeldClrTypStVal : 12|5@0+ (1,0) [0|31] "" XXX + SG_ IntDimAnmTypAvl : 22|15@0+ (1,0) [0|0] "" XXX + SG_ IDATA_AnmTyp6Avl : 16|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp5Avl : 17|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp4Avl : 18|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp3Avl : 19|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp2Avl : 20|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp1Avl : 21|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_OffAvl : 22|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp14Avl : 24|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp13Avl : 25|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp12Avl : 26|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp11Avl : 27|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp10Avl : 28|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp9Avl : 29|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp8Avl : 30|1@0+ (1,0) [0|1] "" XXX + SG_ IDATA_AnmTyp7Avl : 31|1@0+ (1,0) [0|1] "" XXX + SG_ IntDimClrTypAvl : 38|31@0+ (1,0) [0|0] "" XXX + SG_ IDCTA_ClrTyp6Avl : 32|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp5Avl : 33|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp4Avl : 34|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp3Avl : 35|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp2Avl : 36|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp1Avl : 37|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_OffAvl : 38|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp14Avl : 40|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp13Avl : 41|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp12Avl : 42|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp11Avl : 43|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp10Avl : 44|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp9Avl : 45|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp8Avl : 46|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp7Avl : 47|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp22Avl : 48|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp21Avl : 49|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp20Avl : 50|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp19Avl : 51|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp18Avl : 52|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp17Avl : 53|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp16Avl : 54|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp15Avl : 55|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp30Avl : 56|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp29Avl : 57|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp28Avl : 58|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp27Avl : 59|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp26Avl : 60|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp25Avl : 61|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp24Avl : 62|1@0+ (1,0) [0|1] "" XXX + SG_ IDCTA_ClrTyp23Avl : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149711872 ACC_YawRate_Information_LS: 8 XXX + SG_ ACCDrvrSeltdSpd : 3|12@0+ (0.0625,0) [0|255.9375] "km / h" XXX + SG_ AdapCrsCntVDA : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ACCAct370 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ CrsCntlDrSelSpdAct : 7|1@0+ (1,0) [0|1] "" XXX + SG_ CrsSpdLmtrDrvSelSpd : 19|12@0+ (0.0625,0) [0|255.9375] "km / h" XXX + SG_ ACCHdwyStg : 22|3@0+ (1,0) [0|7] "" XXX + SG_ FwdClnAlrtPr : 23|1@0+ (1,0) [0|1] "" XXX + SG_ VehDynYawRateGroup : 36|13@0+ (1,0) [0|0] "" XXX + SG_ VehDynYawRate : 35|12@0- (0.0625,0) [-128|127.9375] "deg/sec" XXX + SG_ VehDynYawRateV : 36|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtrSpdWrngEnbld : 37|1@0+ (1,0) [0|1] "" XXX + SG_ SpdLmtrSpdWrngAct : 38|1@0+ (1,0) [0|1] "" XXX + SG_ FwdClnAlrtOffIO : 39|1@0+ (1,0) [0|1] "" XXX + SG_ FwdObjAlrtInd : 48|9@0+ (1,0) [0|0] "" XXX + SG_ FOAI_AlrtChmIhbRq : 48|1@0+ (1,0) [0|1] "" XXX + SG_ FOAI_AlrtWrnIndRq : 59|4@0+ (1,0) [0|15] "" XXX + SG_ FOAI_VehAhdIndRq : 63|4@0+ (1,0) [0|15] "" XXX + SG_ AutoMdSpdLmtStat : 50|2@0+ (1,0) [0|3] "" XXX + SG_ ACCAutoSetSpdStat : 52|2@0+ (1,0) [0|3] "" XXX + SG_ SetSpdLmtRchd : 54|2@0+ (1,0) [0|3] "" XXX + +BO_ 2153979904 BulbOutage_LS: 2 XXX + SG_ CHMSLFld : 0|1@0+ (1,0) [0|1] "" XXX + SG_ FLTrnIndLtFld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ FRTrnIndLtFld : 2|1@0+ (1,0) [0|1] "" XXX + SG_ LftBrkLtFld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ LftLwBmFld : 4|1@0+ (1,0) [0|1] "" XXX + SG_ LftPrkLtFld : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LicPltLtFld : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RLTrnIndLtFld : 7|1@0+ (1,0) [0|1] "" XXX + SG_ RRTrnIndLtFld : 8|1@0+ (1,0) [0|1] "" XXX + SG_ RtBrkLtFld : 9|1@0+ (1,0) [0|1] "" XXX + SG_ RtLwBmFld : 10|1@0+ (1,0) [0|1] "" XXX + SG_ RtPrkLtFld : 11|1@0+ (1,0) [0|1] "" XXX + SG_ RFgLtFld : 12|1@0+ (1,0) [0|1] "" XXX + SG_ RvsLtFld : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LftDytmRunLmpFld : 14|1@0+ (1,0) [0|1] "" XXX + SG_ RtDytmRunLmpFld : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150154240 Passive_Entry_Reply_LS: 8 XXX + SG_ PsvEntVehIdExt : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ PsvEntChlngRply : 39|32@0+ (1,0) [0|4294967295] "passwrd" XXX + +BO_ 2155003904 Side_Blind_Zone_Alert_Status: 2 XXX + SG_ SBZASysClnIndOn : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SBZASysOffIndOn : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SBZASysSrvIndOn : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SBZATmpUnvIndOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ LftLnChgThrt : 4|1@0+ (1,0) [0|1] "" XXX + SG_ LfLnChngThrtAprchSpd : 15|8@0- (1,0) [-128|127] "km/h" XXX + +BO_ 2150817792 Airbag_Impact_Data_5: 3 XXX + SG_ ImpMaxLateralDeltaVel : 7|8@0- (1,0) [-128|127] "" XXX + SG_ ImpMaxLongDeltaVel : 15|8@0- (1,0) [-128|127] "" XXX + SG_ ImpTimeToMaxDeltaVel : 23|8@0+ (10,0) [0|2550] "ms" XXX + +BO_ 2150227968 Phone_Speech_Rec_Status_LS: 1 XXX + SG_ PhnSpRcgnApSt : 1|2@0+ (1,0) [0|3] "" XXX + +BO_ 2162982912 VIN_Digits_10_to_17: 8 XXX + SG_ VehIdNmDig10_17 : 7|64@0+ (1,0) [0|1] "" XXX + +BO_ 2162966528 VIN_Digits_2_to_9: 8 XXX + SG_ VehIdNmDig2_9 : 7|64@0+ (1,0) [0|1] "" XXX + +BO_ 2151497728 Tire_Pressure_Sensors_LS: 6 XXX + SG_ TireLFPrsGroup : 0|17@0+ (1,0) [0|0] "" XXX + SG_ TireLFPrsV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TireLFPrs : 23|8@0+ (4,0) [0|1020] "kPaG" XXX + SG_ TireRFPrsGroup : 1|34@0+ (1,0) [0|0] "" XXX + SG_ TireRFPrsV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TireRFPrs : 39|8@0+ (4,0) [0|1020] "kPaG" XXX + SG_ TireLFPrsStat : 4|3@0+ (1,0) [0|7] "" XXX + SG_ TireRFPrsStat : 7|3@0+ (1,0) [0|7] "" XXX + SG_ TireLRPrsGroup : 8|17@0+ (1,0) [0|0] "" XXX + SG_ TireLRPrsV : 8|1@0+ (1,0) [0|1] "" XXX + SG_ TireLRPrs : 31|8@0+ (4,0) [0|1020] "kPaG" XXX + SG_ TireRRPrsGroup : 9|34@0+ (1,0) [0|0] "" XXX + SG_ TireRRPrsV : 9|1@0+ (1,0) [0|1] "" XXX + SG_ TireRRPrs : 47|8@0+ (4,0) [0|1020] "kPaG" XXX + SG_ TireLRPrsStat : 12|3@0+ (1,0) [0|7] "" XXX + SG_ TireRRPrsStat : 15|3@0+ (1,0) [0|7] "" XXX + +BO_ 2151219200 Remote_Start_Status: 1 XXX + SG_ RemStrtSt : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RmVehStrRq : 1|1@0+ (1,0) [0|1] "" XXX + +BO_ 2153775104 DTC_Triggered: 7 XXX + SG_ DTCInfo : 7|56@0+ (1,0) [0|0] "" XXX + SG_ DTCI_DTCTriggered : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused1 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused2 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused3 : 3|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused4 : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused5 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused6 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ DTCIUnused7 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_DTCSource : 15|8@0+ (1,0) [0|255] "" XXX + SG_ DTCI_DTCNumber : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ DTCI_DTCFailType : 39|8@0+ (1,0) [0|255] "" XXX + SG_ DTCI_CodeSupported : 40|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_CurrentStatus : 41|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_TstNPsdCdClrdSt : 42|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_TstFldCdClrdStat : 43|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_HistStat : 44|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_TstNPsdPwrUpSt : 45|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_TstFldPwrUpSt : 46|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_WrnIndRqdSt : 47|1@0+ (1,0) [0|1] "" XXX + SG_ DTCI_DTCFaultType : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 2151235584 Vehicle_Theft_Notification_Stat: 5 XXX + SG_ DrIdDevLrnd : 0|1@0+ (1,0) [0|1] "" XXX + SG_ VehSecSysFldIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ VTDTmprDetected : 2|1@0+ (1,0) [0|1] "" XXX + SG_ EhnSrvEngImmStat : 3|1@0+ (1,0) [0|1] "" XXX + SG_ IllDrIdDevDtctd : 4|1@0+ (1,0) [0|1] "" XXX + SG_ AlcKyIIncmIndOn : 5|1@0+ (1,0) [0|1] "" XXX + SG_ VehSecStrgColLckPwdGroup : 6|31@0+ (1,0) [0|0] "" XXX + SG_ VehSecStrgColLckPwdV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ VehSecStrgColLckPwd : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ VehSecAuthnSesComp : 7|1@0+ (1,0) [0|1] "" XXX + SG_ VhSecNImmoIndRq : 9|2@0+ (1,0) [0|3] "" XXX + SG_ StrgColLckCmd : 11|2@0+ (1,0) [0|3] "" XXX + SG_ NmofPrgKFbExtd : 15|4@0+ (1,0) [0|15] "" XXX + SG_ VehStatStAtv : 32|1@0+ (1,0) [0|1] "" XXX + SG_ EhnSrvImmbComRst : 33|1@0+ (1,0) [0|1] "" XXX + SG_ ClmSysBkupFlrIndOn : 34|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150809600 Airbag_Impact_Data_4: 8 XXX + SG_ ImpDltVlcSamp12 : 7|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS12_Axis1 : 7|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS12_Axis2 : 15|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp13 : 23|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS13_Axis1 : 23|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS13_Axis2 : 31|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp14 : 39|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS14_Axis1 : 39|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS14_Axis2 : 47|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp15 : 55|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS15_Axis1 : 55|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS15_Axis2 : 63|8@0- (1,0) [-128|127] "counts" XXX + +BO_ 2150793216 Airbag_Impact_Data_2: 8 XXX + SG_ ImpDltVlcSamp4 : 7|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS4_Axis1 : 7|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS4_Axis2 : 15|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp5 : 23|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS5_Axis1 : 23|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS5_Axis2 : 31|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp6 : 39|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS6_Axis1 : 39|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS6_Axis2 : 47|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp7 : 55|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS7_Axis1 : 55|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS7_Axis2 : 63|8@0- (1,0) [-128|127] "counts" XXX + +BO_ 2150801408 Airbag_Impact_Data_3: 8 XXX + SG_ ImpDltVlcSamp8 : 7|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS8_Axis1 : 7|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS8_Axis2 : 15|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp9 : 23|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS9_Axis1 : 23|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS9_Axis2 : 31|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp10 : 39|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS10_Axis1 : 39|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS10_Axis2 : 47|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp11 : 55|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS11_Axis1 : 55|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS11_Axis2 : 63|8@0- (1,0) [-128|127] "counts" XXX + +BO_ 2150785024 Airbag_Impact_Data_1: 8 XXX + SG_ ImpDltVlcScal : 7|8@0+ (0.00245,0.706) [0.706|1.33075] "kph/cnt" XXX + SG_ AirbgAccelOrien : 10|3@0+ (45,0) [0|315] "deg" XXX + SG_ ImpDltVlcSamp1 : 23|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS1_Axis1 : 23|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS1_Axis2 : 31|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp2 : 39|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS2_Axis1 : 39|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS2_Axis2 : 47|8@0- (1,0) [-128|127] "counts" XXX + SG_ ImpDltVlcSamp3 : 55|16@0+ (1,0) [0|0] "" XXX + SG_ IDVS3_Axis1 : 55|8@0- (1,0) [-128|127] "counts" XXX + SG_ IDVS3_Axis2 : 63|8@0- (1,0) [-128|127] "counts" XXX + +BO_ 2151202816 Rear_Window_Defog_Inhibit: 5 XXX + SG_ RrWndDfgInhRq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RrWndDfgSwAtv : 1|1@0+ (1,0) [0|1] "" XXX + SG_ ILSSCommErr : 2|1@0+ (1,0) [0|1] "" XXX + SG_ IPSnsrRwSolrIntFltd : 3|1@0+ (1,0) [0|1] "" XXX + SG_ IPSnsrSolrAnglFltd : 4|1@0+ (1,0) [0|1] "" XXX + SG_ IPSnsrTpCvrTempFltd : 5|1@0+ (1,0) [0|1] "" XXX + SG_ AuxHtrAlwd : 6|1@0+ (1,0) [0|1] "" XXX + SG_ IPSnsrRwSolrInt : 15|8@0+ (3,0) [0|765] "W/m2" XXX + SG_ IPSnsrSolrAzmthAngl : 23|8@0+ (2,-180) [-180|330] "deg" XXX + SG_ IPSnsrSolrElvtnAngl : 31|8@0+ (1,0) [0|255] "deg" XXX + SG_ IPSnsrTpCvrTemp : 39|8@0+ (0.5,-40) [-40|87.5] "deg C" XXX + +BO_ 2150825984 Airbag_Indications: 6 XXX + SG_ FsnDrvStbltIC : 7|8@0+ (1,0) [0|0] "" XXX + SG_ FDSIC_IndPer : 3|4@0+ (1,0) [0|15] "" XXX + SG_ FDSIC_IndDC : 6|3@0+ (12.5,12.5) [12.5|100] "%" XXX + SG_ FDSIC_IO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ FsnPsngStbltIC : 15|8@0+ (1,0) [0|0] "" XXX + SG_ FPSIC_IndPer : 11|4@0+ (1,0) [0|15] "" XXX + SG_ FPSIC_IndDtCyc : 14|3@0+ (12.5,12.5) [12.5|100] "%" XXX + SG_ FPSIC_IO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ AirbgIC : 23|8@0+ (1,0) [0|0] "" XXX + SG_ AirbgICIndPer : 19|4@0+ (1,0) [0|15] "" XXX + SG_ AirbgICDutCyc : 22|3@0+ (12.5,12.5) [12.5|100] "%" XXX + SG_ AirbgICIO : 23|1@0+ (1,0) [0|1] "" XXX + SG_ FstnSndRwLtPsStbtInR : 25|2@0+ (1,0) [0|3] "" XXX + SG_ FstnSndRwCtPsStbtInR : 27|2@0+ (1,0) [0|3] "" XXX + SG_ FstnSndRwRtPsStbtInR : 29|2@0+ (1,0) [0|3] "" XXX + SG_ FsnDrStbAuxIR : 31|2@0+ (1,0) [0|3] "" XXX + SG_ FsnPsStbAuxIR : 34|3@0+ (1,0) [0|7] "" XXX + SG_ AirbgFldIO : 35|1@0+ (1,0) [0|1] "" XXX + SG_ SndRwStbltRdIndMd : 37|2@0+ (1,0) [0|3] "" XXX + SG_ FstnThrdRwCtPsStbtInR : 39|2@0+ (1,0) [0|3] "" XXX + SG_ FstnThrdRwRtPsStbtInR : 41|2@0+ (1,0) [0|3] "" XXX + SG_ FstnThrdRwLtPsStbtInR : 43|2@0+ (1,0) [0|3] "" XXX + SG_ SrvIntdPdstProtSysIO : 44|1@0+ (1,0) [0|1] "" XXX + SG_ PdstIntdProtSysDsbld : 45|1@0+ (1,0) [0|1] "" XXX + SG_ PdstIntdProtSysDplyd : 46|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151759872 Door_Lock_Command: 4 XXX + SG_ CntrlLckRqwExtActFun : 9|18@0+ (1,0) [0|0] "" XXX + SG_ CLRAF_Unl_Lk : 9|3@0+ (1,0) [0|7] "" XXX + SG_ CLRAF_FuelD : 16|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_RrCls : 17|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_Hd : 18|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_RLD : 19|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_RRD : 20|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_PD : 21|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_DD : 22|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_ActFunc : 28|5@0+ (1,0) [0|31] "" XXX + SG_ CLRAF_UnandRsv3 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_UnandRsv2 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ CLRAF_UnandRsv1 : 31|1@0+ (1,0) [0|1] "" XXX + SG_ RrClsRelRq : 10|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149974016 Content_Theft_Sensor_Status: 3 XXX + SG_ SrvAlrmSysIO : 0|1@0+ (1,0) [0|1] "" XXX + SG_ IntrSnsDisbld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgDrvDr : 3|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgPsngDr : 4|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgRrRtDr : 5|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgRrLftDr : 6|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrigTonn : 7|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgTrnk : 8|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgTltSns : 9|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgIntMvmntSns : 10|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrggrdBattRcnctd : 11|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgGlsBrkSns : 12|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgNonOffPM : 13|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrigMidClsr : 14|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmTrgdIO : 15|1@0+ (1,0) [0|1] "" XXX + SG_ AlrmStat : 18|3@0+ (1,0) [0|7] "" XXX + SG_ AlrmTrgHd : 21|1@0+ (1,0) [0|1] "" XXX + +BO_ 2151907328 Steering_Wheel_Control_Switches: 1 XXX + SG_ StrgWhlUnit1SwStat : 3|4@0+ (1,0) [0|15] "" XXX + SG_ StrgWhlUnit2SwStat : 7|4@0+ (1,0) [0|15] "" XXX + +BO_ 2150219776 Voice_Recognition_Status: 1 XXX + SG_ PhnSpRcgnRq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ VcRecVcFdbckSt : 3|2@0+ (1,0) [0|3] "" XXX + +BO_ 2152685568 Radiomarks_Response: 8 XXX + SG_ RadBrdcstSrc : 3|4@0+ (1,0) [0|15] "" XXX + SG_ RadConInfReqSrc : 7|4@0+ (1,0) [0|15] "" XXX + SG_ RadConInfCmd : 11|4@0+ (1,0) [0|15] "" XXX + SG_ RadConInfID : 31|40@0+ (1,0) [0|1099511627775] "" XXX + +BO_ 2151874560 Vehicle_Theft_Notify_Reset_Req: 8 XXX + SG_ EhnSrvEngImmbCom : 0|57@0+ (1,0) [0|0] "" XXX + SG_ ESEIC_EngImmbRq : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ESEIC_EngImRqPsw : 15|56@0+ (1,0) [0|1] "" XXX + SG_ RstVTDTmprDtctd : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RstIllDrIdDevDtctd : 2|1@0+ (1,0) [0|1] "" XXX + SG_ RstDrIdDevLrnd : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150268928 GPS_Date_and_Time_LS: 6 XXX + SG_ CldrYr_154 : 7|8@0+ (1,2000) [2000|2255] "year" XXX + SG_ CldrMth_154 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ CldrDay_154 : 20|5@0+ (1,0) [0|31] "days" XXX + SG_ HrsGroup : 29|6@0+ (1,0) [0|0] "" XXX + SG_ Hrs : 28|5@0+ (1,0) [0|31] "h" XXX + SG_ HrsV : 29|1@0+ (1,0) [0|1] "" XXX + SG_ MinsGroup : 38|7@0+ (1,0) [0|0] "" XXX + SG_ Mins : 37|6@0+ (1,0) [0|63] "min" XXX + SG_ MinsV : 38|1@0+ (1,0) [0|1] "" XXX + SG_ SecGroup : 46|7@0+ (1,0) [0|0] "" XXX + SG_ Sec : 45|6@0+ (1,0) [0|63] "s" XXX + SG_ SecV : 46|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150137856 RFA_Status_LS: 3 XXX + SG_ FobPrevLrndIndOn : 0|1@0+ (1,0) [0|1] "" XXX + SG_ Ky_IdDevNotPrIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ FbProgCustActRqd : 2|1@0+ (1,0) [0|1] "" XXX + SG_ KeyInWrnIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ VehSecAtoLrnAtv : 4|1@0+ (1,0) [0|1] "" XXX + SG_ Ky_IdDevPrgmAuthReq : 5|1@0+ (1,0) [0|1] "" XXX + SG_ LMTTCPrsnOffStat : 6|1@0+ (1,0) [0|1] "" XXX + SG_ VehSecAtoLrnDlyTmr : 12|5@0+ (1,0) [0|31] "min" XXX + SG_ FldTpMotReq : 15|3@0+ (1,0) [0|7] "" XXX + SG_ RemCtrlFobNumForProgER : 19|4@0+ (1,0) [0|15] "" XXX + +BO_ 2151677952 Chime_Command: 5 XXX + SG_ SndChrs : 3|28@0+ (1,0) [0|0] "" XXX + SG_ SC_SndTne : 3|4@0+ (1,0) [0|15] "" XXX + SG_ SC_SndCdnPrd : 15|8@0+ (10,0) [0|2550] "ms" XXX + SG_ SC_NmofRp : 23|8@0+ (1,0) [0|255] "reps" XXX + SG_ SC_SndDutCyc : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ SndLoc : 7|4@0+ (1,0) [0|0] "" XXX + SG_ SndLocRtRr : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SndLocLftRr : 5|1@0+ (1,0) [0|1] "" XXX + SG_ SndLocPasFr : 6|1@0+ (1,0) [0|1] "" XXX + SG_ SndLocDrFr : 7|1@0+ (1,0) [0|1] "" XXX + SG_ SndPriority : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 2150776832 Airbag_Status: 6 XXX + SG_ ShfUlkBrToShftIndCtrl : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ShftLkdBuStbltIndCtrl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SbItlkTrnsShftLvLkRd : 2|1@0+ (1,0) [0|1] "" XXX + SG_ MmryRclImpctDisRq : 3|1@0+ (1,0) [0|1] "" XXX + SG_ EvntEnbld : 4|1@0+ (1,0) [0|1] "" XXX + SG_ SftyMuteRd : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HybVehHiVltInvDisRqd : 6|1@0+ (1,0) [0|1] "" XXX + SG_ HybImpSnsDsbld : 7|1@0+ (1,0) [0|1] "" XXX + SG_ SIREvntSychCntr : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ FrPsngrStOccSnsngPriDat : 39|16@0+ (1,0) [0|39321] "" XXX + +BO_ 2150760448 Airbag_Impact_Data: 8 XXX + SG_ SIRDpl : 1|1@0+ (1,0) [0|1] "" XXX + SG_ NotPsSeatStat : 5|2@0+ (1,0) [0|3] "" XXX + SG_ NotDrvSeatStat : 7|2@0+ (1,0) [0|3] "" XXX + SG_ NotSecRowRtSeaOccStat : 9|2@0+ (1,0) [0|3] "" XXX + SG_ NotSndRwMdlSeatStat : 11|2@0+ (1,0) [0|3] "" XXX + SG_ NotSndRwRtSeatStat : 13|2@0+ (1,0) [0|3] "" XXX + SG_ NotSndRwLtSeatStat : 15|2@0+ (1,0) [0|3] "" XXX + SG_ NotEventStat : 17|2@0+ (1,0) [0|3] "" XXX + SG_ NotSecRowLeSeaOccStat : 25|2@0+ (1,0) [0|3] "" XXX + SG_ NotSecRowCtSeaOccStat : 27|2@0+ (1,0) [0|3] "" XXX + SG_ NotiFrntPasSeatOccSta : 34|3@0+ (1,0) [0|7] "" XXX + SG_ NoEvDeLoSt : 46|7@0+ (1,0) [0|0] "" XXX + SG_ NEDLSSdCrtnArbgDpld : 40|1@0+ (1,0) [0|1] "" XXX + SG_ NEDLSRtSdArbgDld : 41|1@0+ (1,0) [0|1] "" XXX + SG_ NEDLSLtSdArbgDld : 42|1@0+ (1,0) [0|1] "" XXX + SG_ NEDLSPaFrSt2De : 43|1@0+ (1,0) [0|1] "" XXX + SG_ NEDLSPaFrSt1De : 44|1@0+ (1,0) [0|1] "" XXX + SG_ NEDLSDrFrSt2De : 45|1@0+ (1,0) [0|1] "" XXX + SG_ NEDLSDrFrSt1De : 46|1@0+ (1,0) [0|1] "" XXX + SG_ NoEvSevSt : 54|7@0+ (1,0) [0|0] "" XXX + SG_ NESSRoSevSt : 48|1@0+ (1,0) [0|1] "" XXX + SG_ NESSRiSiSevSt : 49|1@0+ (1,0) [0|1] "" XXX + SG_ NESSReImpSevSt : 50|1@0+ (1,0) [0|1] "" XXX + SG_ NESSLeSiSevSt : 51|1@0+ (1,0) [0|1] "" XXX + SG_ NESSFrImpSt2SevSt : 52|1@0+ (1,0) [0|1] "" XXX + SG_ NESSFrImpSt1SevSt : 53|1@0+ (1,0) [0|1] "" XXX + SG_ NESSFrImpPreSevSt : 54|1@0+ (1,0) [0|1] "" XXX + SG_ NotiEventCount : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 2155872256 Fuel_Information: 6 XXX + SG_ FlLvlPctGroup : 0|9@0+ (1,0) [0|0] "" XXX + SG_ FlLvlPctV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ FlLvlPct : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ FlInjRlCtRstOcc : 1|1@0+ (1,0) [0|1] "" XXX + SG_ FuelFltChgNwIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DrvStyPerfMdCsCrStVal : 5|3@0+ (1,0) [0|7] "" XXX + SG_ DrvStyPerfMdCsStAvl : 6|1@0+ (1,0) [0|1] "" XXX + SG_ RdWhlAngGroup : 23|8@0+ (1,0) [0|0] "" XXX + SG_ RdWhlAng : 22|7@0+ (0.703125,-45) [-45|44.296875] "deg" XXX + SG_ RdWhlAngV : 23|1@0+ (1,0) [0|1] "" XXX + SG_ VehPitchAngleGroup : 31|8@0+ (1,0) [0|0] "" XXX + SG_ VehPitchAngle : 30|7@0+ (0.703125,-45) [-45|44.296875] "deg" XXX + SG_ VehPitchAngleV : 31|1@0+ (1,0) [0|1] "" XXX + SG_ FlInjRlCt : 39|16@0+ (3.05176E-005,0) [0|1.999970916] "liters" XXX + +BO_ 2156175360 Display_Measurement_System_LS: 1 XXX + SG_ DispMeasSysExt : 1|2@0+ (1,0) [0|3] "" XXX + SG_ DispMeasSys : 2|1@0+ (1,0) [0|1] "" XXX + SG_ NtVsnSysEnbld : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149859328 System_Power_Mode_Backup_LS: 1 XXX + SG_ SysBkupPwrMdEn : 2|1@0+ (1,0) [0|1] "" XXX + SG_ SysBkUpPwrMdGroup : 3|4@0+ (1,0) [0|0] "" XXX + SG_ SysBkUpPwrMd : 1|2@0+ (1,0) [0|3] "" XXX + SG_ SysBkUpPwrMdV : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2158854144 ODIAction_IPC_LS: 8 XXX + SG_ ODIActn_IPC : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIAI_DaTy : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ODIAI_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAI_ActnID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAI_DspMID : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAI_ActnVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2158837760 ODIAction_AuxIP_LS: 8 XXX + SG_ ODIActn_AxIP : 5|62@0+ (1,0) [0|0] "" XXX + SG_ ODIAA_DaTy : 5|6@0+ (1,0) [0|63] "" XXX + SG_ ODIAA_FUCID : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAA_ActnID : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAA_DspMID : 31|8@0+ (1,0) [0|255] "" XXX + SG_ ODIAA_ActnVal : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2159091712 ODI_IPC_2_TEL_LS: 8 XXX + SG_ ODI_IPC2TEL : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2154561536 Vehicle_Odo_LS: 5 XXX + SG_ VehOdoGroup : 7|40@0+ (1,0) [0|0] "" XXX + SG_ VehOdo : 7|32@0+ (0.015625,0) [0|67108863.984375] "km" XXX + SG_ VehOdoV : 32|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149908480 Brake_Pedal_Status_LS: 2 XXX + SG_ BrkPedInitTrvlAchvdStat : 1|2@0+ (1,0) [0|0] "" XXX + SG_ BrkPedTrvlAchvdV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ BrkPedTrvlAchvd : 1|1@0+ (1,0) [0|1] "" XXX + SG_ BrkPdlModTrvlGroup : 3|2@0+ (1,0) [0|0] "" XXX + SG_ BrkPdlModTrvl : 2|1@0+ (1,0) [0|1] "" XXX + SG_ BrkPdlModTrvlV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ BrkPdlPos : 15|8@0+ (0.392157,0) [0|100.000035] "% full" XXX + +BO_ 2151268352 Column_Lock_Status: 1 XXX + SG_ ClmnLckTT : 1|2@0+ (1,0) [0|3] "" XXX + +BO_ 2150604800 Right_Rear_Door_Status: 1 XXX + SG_ RRDoorAjarSwAct : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150588416 Passenger_Door_Status_LS: 1 XXX + SG_ PDAjrSwAtv : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150596608 Left_Rear_Door_Status: 1 XXX + SG_ RLDoorAjarSwAct : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 2155036672 Climate_Control_General_Status: 6 XXX + SG_ ACCompNormLdGroup : 0|9@0+ (1,0) [0|0] "" XXX + SG_ ACCompNormLdV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ACCompNormLd : 15|8@0+ (0.1,0) [0|25.5] "l/min" XXX + SG_ ACCmEngRunReq : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACCmpsrFldOn : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ACCompModReq : 5|2@0+ (1,0) [0|3] "" XXX + SG_ ClmtCtrlTrgtTemp : 17|10@0+ (0.1,-10) [-10|92.3] "deg C" XXX + +BO_ 2150424576 Engine_Information_3_LS: 8 XXX + SG_ TrnsEngdStateGroup : 2|3@0+ (1,0) [0|0] "" XXX + SG_ TrnsEngdState : 1|2@0+ (1,0) [0|3] "" XXX + SG_ TrnsEngdStateV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACRfHiSdFldPrsGroup : 3|20@0+ (1,0) [0|0] "" XXX + SG_ ACRfHiSdFldPrsV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ACRfHiSdFldPrs : 23|8@0+ (14,0) [0|3570] "kPaG" XXX + SG_ ACCompCmnd : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RrAxlELSDCplLwResGroup : 5|46@0+ (1,0) [0|0] "" XXX + SG_ RrAxlELSDCplLwResV : 5|1@0+ (1,0) [0|1] "" XXX + SG_ RrAxlELSDCplLwRes : 47|8@0+ (10,0) [0|2550] "Nm" XXX + SG_ EngAirIntBstPrGroup : 6|39@0+ (1,0) [0|0] "" XXX + SG_ EngAirIntBstPrV : 6|1@0+ (1,0) [0|1] "" XXX + SG_ EngAirIntBstPr : 39|8@0- (1,0) [-128|127] "kPaG" XXX + SG_ ExtHlStrAssCsStAvl : 7|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsRngInhbtStat : 10|3@0+ (1,0) [0|7] "" XXX + SG_ DrvtShftCntrlTrgtGear : 14|4@0+ (1,0) [0|15] "" XXX + SG_ ACCmpNrmLdGrdAld : 31|8@0+ (0.1,0) [0|25.5] "dm3/m/s" XXX + SG_ EngTrqDrRqdExtRngGroup : 52|13@0+ (1,0) [0|0] "" XXX + SG_ EngTrqDrRqdExtRng : 51|12@0+ (0.5,-848) [-848|1199.5] "Nm" XXX + SG_ EngTrqDrRqdExtRngV : 52|1@0+ (1,0) [0|1] "" XXX + SG_ ExtHlStrAssCsCrStVal : 55|3@0+ (1,0) [0|7] "" XXX + +BO_ 2150416384 Engine_Information_2_LS: 8 XXX + SG_ EngBstPrsIndGroup : 0|33@0+ (1,0) [0|0] "" XXX + SG_ EngBstPrsIndV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ EngBstPrsInd : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ VaccBoostFailure : 2|1@0+ (1,0) [0|1] "" XXX + SG_ GenFld : 3|1@0+ (1,0) [0|1] "" XXX + SG_ EngSpdLmtnMdAct : 4|1@0+ (1,0) [0|1] "" XXX + SG_ PTWrmgWtToShftIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ EngNEmsnsRelMalfAct : 6|1@0+ (1,0) [0|1] "" XXX + SG_ EngCstFlCutAct : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EngRunAtv : 8|1@0+ (1,0) [0|1] "" XXX + SG_ EngIdlAtv : 11|1@0+ (1,0) [0|1] "" XXX + SG_ VehTopSpdLmtMdAct : 13|1@0+ (1,0) [0|1] "" XXX + SG_ EngCylDeactMd : 15|2@0+ (1,0) [0|3] "" XXX + SG_ TransEstGearGroup : 20|5@0+ (1,0) [0|0] "" XXX + SG_ TransEstGear : 19|4@0+ (1,0) [0|15] "" XXX + SG_ TransEstGearV : 20|1@0+ (1,0) [0|1] "" XXX + SG_ EngTrqActExtRngGroup : 21|46@0+ (1,0) [0|0] "" XXX + SG_ EngTrqActExtRngV : 21|1@0+ (1,0) [0|1] "" XXX + SG_ EngTrqActExtRng : 51|12@0+ (0.5,-848) [-848|1199.5] "Nm" XXX + SG_ EngVDA : 22|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsVDA : 23|1@0+ (1,0) [0|1] "" XXX + SG_ EngCoolFanSpd : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ VehTopSpdLmtArbVal : 47|8@0+ (2,0) [0|510] "km / h" XXX + SG_ EngSpdStat : 53|2@0+ (1,0) [0|3] "" XXX + SG_ RmVhStrtEngRng : 54|1@0+ (1,0) [0|1] "" XXX + SG_ TrnCrpMdAtv : 55|1@0+ (1,0) [0|1] "" XXX + +BO_ 2150408192 Engine_Information_1_LS: 8 XXX + SG_ TrnsSftMdStat : 2|3@0+ (1,0) [0|7] "" XXX + SG_ ThrPosGroup : 3|36@0+ (1,0) [0|0] "" XXX + SG_ ThrPosV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ThrPos : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ AccActPosGroup : 4|45@0+ (1,0) [0|0] "" XXX + SG_ AccActPosV : 4|1@0+ (1,0) [0|1] "" XXX + SG_ AccActPos : 47|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ ElcRngSelDrvAct : 5|1@0+ (1,0) [0|1] "" XXX + SG_ TmpDrvrShftCtlAct : 6|1@0+ (1,0) [0|1] "" XXX + SG_ AccPdlOvrrdAtv : 7|1@0+ (1,0) [0|1] "" XXX + SG_ TrnShftPtrnActStat : 10|3@0+ (1,0) [0|7] "" XXX + SG_ TransTUDMdStat : 12|2@0+ (1,0) [0|3] "" XXX + SG_ Eng12vStrtrMtrCmmdOn : 13|1@0+ (1,0) [0|1] "" XXX + SG_ EngRunng : 14|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsShftLvrPosGroup : 15|48@0+ (1,0) [0|0] "" XXX + SG_ TrnsShftLvrPosV : 15|1@0+ (1,0) [0|1] "" XXX + SG_ TrnsShftLvrPos : 51|4@0+ (1,0) [0|15] "" XXX + SG_ EngSpd : 23|16@0+ (0.25,0) [0|16383.75] "rpm" XXX + SG_ AutoTransComndGear : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CrsCntEnbld : 56|1@0+ (1,0) [0|1] "" XXX + SG_ CltStartSwAtvGroup : 58|2@0+ (1,0) [0|0] "" XXX + SG_ CltStartSwAtv : 57|1@0+ (1,0) [0|1] "" XXX + SG_ CltStartSwAtvV : 58|1@0+ (1,0) [0|1] "" XXX + SG_ TopTrvlCltchSwActGroup : 60|2@0+ (1,0) [0|0] "" XXX + SG_ TopTrvlCltchSwAct : 59|1@0+ (1,0) [0|1] "" XXX + SG_ TopTrvlCltchSwActV : 60|1@0+ (1,0) [0|1] "" XXX + SG_ AdptPsngrSeatStng : 63|3@0+ (1,0) [0|7] "" XXX + +BO_ 2155954176 Climate_Control_Basic_Status_LS: 4 XXX + SG_ ACHtIdleBstLevReq : 1|2@0+ (1,0) [0|3] "" XXX + SG_ ClimCtrlAftBlowModActv : 2|1@0+ (1,0) [0|1] "" XXX + SG_ AirCndActIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ ClmCntlExtDefActIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ClntCircPmpRq : 7|1@0+ (1,0) [0|1] "" XXX + SG_ ClmCntFrBlwFnSp : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ AirCndCmptLdEst : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ ClmCntRrBlwFnSp : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2153971712 Driver_Door_Status: 1 XXX + SG_ LftglsAjrSwAct : 1|1@0+ (1,0) [0|1] "" XXX + SG_ LftglsRelSwAct : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DDAjrSwAtvGroup : 7|8@0+ (1,0) [0|0] "" XXX + SG_ DDAjrSwAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DDAjrSwAtvM : 7|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149875712 Battery_Voltage: 7 XXX + SG_ BatVltGroup : 0|17@0+ (1,0) [0|0] "" XXX + SG_ BatVltV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ BatVlt : 23|8@0+ (0.1,3) [3|28.5] "volts" XXX + SG_ BatSaverIO : 1|1@0+ (1,0) [0|1] "" XXX + SG_ SrvBattChrgSysIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ BatSOCGroup : 3|28@0+ (1,0) [0|0] "" XXX + SG_ BatSOCV : 3|1@0+ (1,0) [0|1] "" XXX + SG_ BatSOC : 31|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ BattStOfChrgCrtyLow : 4|1@0+ (1,0) [0|1] "" XXX + SG_ IntlgntBattSnsFldIO : 5|1@0+ (1,0) [0|1] "" XXX + SG_ BattStOfChrgLowIO : 6|1@0+ (1,0) [0|1] "" XXX + SG_ DCCnvStblznErrIO : 7|1@0+ (1,0) [0|1] "" XXX + SG_ EnrgMgtLdShdRq : 11|4@0+ (1,0) [0|15] "" XXX + SG_ BattVltIRq : 13|2@0+ (1,0) [0|3] "" XXX + SG_ PwrMdOffBattSOC : 39|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ BattCrntFltrd : 47|8@0- (0.5,0) [-64|63.5] "A" XXX + SG_ BatSvrMdSevLvl : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 2151186432 Auto_High_Beam_Status: 1 XXX + SG_ AutoBmSlctStat : 1|2@0+ (1,0) [0|3] "" XXX + SG_ CtLghtDet : 2|1@0+ (1,0) [0|1] "" XXX + SG_ AutoHgBmCtrlInOn : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2149629952 Lighting_Status_LS: 5 XXX + SG_ OtsdAmbtLtLvlStatGroup : 0|23@0+ (1,0) [0|0] "" XXX + SG_ OtsdAmbtLtLvlStatV : 0|1@0+ (1,0) [0|1] "" XXX + SG_ OtsdAmbtLtLvlStat : 27|2@0+ (1,0) [0|3] "" XXX + SG_ DRLAct : 1|1@0+ (1,0) [0|1] "" XXX + SG_ HazSwAtv : 2|1@0+ (1,0) [0|1] "" XXX + SG_ PrkLtLeftIO : 3|1@0+ (1,0) [0|1] "" XXX + SG_ PrkLtRightIO : 4|1@0+ (1,0) [0|1] "" XXX + SG_ TrnSwAct : 6|2@0+ (1,0) [0|3] "" XXX + SG_ FrFogLmpsAct : 7|1@0+ (1,0) [0|1] "" XXX + SG_ PrkLtLeftOn : 8|1@0+ (1,0) [0|1] "" XXX + SG_ FrFgLtIO : 9|1@0+ (1,0) [0|1] "" XXX + SG_ AutoLtsInactIO : 10|1@0+ (1,0) [0|1] "" XXX + SG_ AutoLtsActIO : 11|1@0+ (1,0) [0|1] "" XXX + SG_ RrFgLtIO : 12|1@0+ (1,0) [0|1] "" XXX + SG_ HiBmIO : 13|1@0+ (1,0) [0|1] "" XXX + SG_ PrkLtIO : 14|1@0+ (1,0) [0|1] "" XXX + SG_ BrkLtsAtv : 15|1@0+ (1,0) [0|1] "" XXX + SG_ FlToPsSwAtv : 16|1@0+ (1,0) [0|1] "" XXX + SG_ RevLmpAtv : 17|1@0+ (1,0) [0|1] "N/A" XXX + SG_ PrkngLtsAct : 18|1@0+ (1,0) [0|1] "" XXX + SG_ RrFogLmpsAct : 19|1@0+ (1,0) [0|1] "" XXX + SG_ HiBmReqd : 20|1@0+ (1,0) [0|1] "" XXX + SG_ AutoBmSlctAllwd : 21|1@0+ (1,0) [0|1] "" XXX + SG_ PrkLtRightOn : 22|1@0+ (1,0) [0|1] "" XXX + SG_ SrvlnceMdAct : 23|1@0+ (1,0) [0|1] "" XXX + SG_ RtTrnLmpAtv : 25|2@0+ (1,0) [0|3] "" XXX + SG_ LftTrnLmpAtv : 29|2@0+ (1,0) [0|3] "" XXX + SG_ MainLghtSw : 31|2@0+ (1,0) [0|3] "N/A" XXX + SG_ HdlmpBmSelectStat : 33|2@0+ (1,0) [0|3] "" XXX + +BO_ 2149646336 Vehicle_Speed_Information: 8 XXX + SG_ VehSpdAvgDrvnGroup : 7|16@0+ (1,0) [0|0] "" XXX + SG_ VehSpdAvgDrvn : 6|15@0+ (0.015625,0) [0|511.984375] "km / h" XXX + SG_ VehSpdAvgDrvnV : 7|1@0+ (1,0) [0|1] "" XXX + SG_ DstRolCntAvgDrnRstOc : 21|1@0+ (1,0) [0|1] "" XXX + SG_ DistRollCntAvgDrvnGroup : 22|15@0+ (1,0) [0|0] "" XXX + SG_ DistRollCntAvgDrvn : 20|13@0+ (0.125,0) [0|1023.875] "m" XXX + SG_ DistRollCntAvgDrvnV : 22|1@0+ (1,0) [0|1] "" XXX + SG_ VehSpdAvgDrvnSrc : 23|1@0+ (1,0) [0|1] "" XXX + SG_ VehSpdAvgNDrvnGroup : 38|17@0+ (1,0) [0|0] "" XXX + SG_ VehSpdAvgNDrvn : 38|15@0+ (0.015625,0) [0|511.984375] "km / h" XXX + SG_ VehSpdAvgNDrvnV : 54|1@0+ (1,0) [0|1] "" XXX + SG_ DstRolCntAvgNonDrvnGroup : 39|32@0+ (1,0) [0|0] "" XXX + SG_ DstRolCntAvgNonDrvnV : 39|1@0+ (1,0) [0|1] "" XXX + SG_ DstRolCntAvgNonDrvn : 52|13@0+ (0.125,0) [0|1023.875] "m" XXX + SG_ DstRolCntAvNDrRstOc : 53|1@0+ (1,0) [0|1] "" XXX + SG_ DistRollCntAvgDrvnSrc : 55|1@0+ (1,0) [0|1] "" XXX + +BO_ 2154053632 Dimming_Information_LS: 3 XXX + SG_ IntDimNtPnlAtv : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DispNtSchmAtv : 1|1@0+ (1,0) [0|1] "" XXX + SG_ CargoLmpActIO : 2|1@0+ (1,0) [0|1] "" XXX + SG_ IntDimLvl : 15|8@0+ (0.392157,0) [0|100.000035] "%" XXX + SG_ IntDimDspLvl : 23|8@0+ (0.392157,0) [0|100.000035] "%" XXX + +BO_ 2149851136 System_Power_Mode_LS: 1 XXX + SG_ SysPwrMdGroup : 2|3@0+ (1,0) [0|0] "" XXX + SG_ SysPwrMd : 1|2@0+ (1,0) [0|3] "" XXX + SG_ SysPwrMdV : 2|1@0+ (1,0) [0|1] "" XXX + SG_ KylsStrtAuthRq : 3|1@0+ (1,0) [0|1] "" XXX + +BO_ 2159124480 ODI_AuxIP_2_TEL_LS: 8 XXX + SG_ ODI_AxIP2TEL : 7|64@0+ (1,0) [0|1.84467440737096E+019] "" XXX + +BO_ 2151530496 TPM_Display_Commands: 6 XXX + SG_ TPMTrLrnMdCmplt : 0|1@0+ (1,0) [0|1] "" XXX + SG_ TrPrsMntrAtLocFld : 1|1@0+ (1,0) [0|1] "" XXX + SG_ TrPrsMntrTrLdStat : 3|2@0+ (1,0) [0|3] "" XXX + SG_ TireTrdTmpStat : 6|3@0+ (1,0) [0|7] "" XXX + SG_ TrFrntAxlPresStat : 9|2@0+ (1,0) [0|3] "" XXX + SG_ TrRrAxlPresStat : 11|2@0+ (1,0) [0|3] "" XXX + SG_ WintTrRecIndOn : 12|1@0+ (1,0) [0|1] "" XXX + SG_ TrPrsMntrFld : 13|1@0+ (1,0) [0|1] "" XXX + SG_ TireLocatnWarnEn : 15|1@0+ (1,0) [0|1] "" XXX + SG_ HVChgSyChgLvPfStRmt1 : 18|3@0+ (1,0) [0|7] "" XXX + SG_ StTODChrgTmpOvrdRmt1 : 20|2@0+ (1,0) [0|3] "" XXX + SG_ PrtyChrgRqRmt1 : 22|2@0+ (1,0) [0|3] "" XXX + SG_ OfBrdHVCVhCsChRqRmt1 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ HVBatTmBsDlChStRqRmt1 : 28|21@0+ (1,0) [0|0] "" XXX + SG_ HVBTBDCSRR1_DChHStRq : 28|5@0+ (1,0) [0|31] "hr" XXX + SG_ HVBTBDCSRR1_DChSlSRq : 35|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBDCSRR1_DChDStRq : 39|4@0+ (1,0) [0|15] "" XXX + SG_ HVBTBDCSRR1_DChMHSRq : 45|6@0+ (1,0) [0|63] "min" XXX + SG_ HVBTBDCSRR1_DChSnSRq : 47|2@0+ (1,0) [0|3] "" XXX + SG_ HVBatTmBsChgMdRqRmt1 : 31|3@0+ (1,0) [0|7] "" XXX + + + +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "ProtocolType" "GMLAN"; +BA_ "BusType" "CAN"; + diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_object.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_object.dbc new file mode 100644 index 0000000000..4643a640ac --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gm_global_a_object.dbc @@ -0,0 +1,724 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: K109_FCM B233B_LRR NEO VIS_FO VIS2_FO K124_ASCM Vector__XXX EOCM_F_FO EOCM2A_IMX6_FO EOCM2A_K2_FO EOCM2A_K1_FO EOCM2B_IMX6_FO EOCM2B_K2_FO EOCM2B_K1_FO +VAL_TABLE_ RangeMode 1 "Active" 0 "Inactive" ; +VAL_TABLE_ TrkConf 3 "Confident" 2 "Speculative" 1 "Highly speculative" 0 "Invalid" ; +VAL_TABLE_ TrkMeasStatus 3 "Measured current cycle" 2 "Latent track not detected" 1 "New object" 0 "No object" ; +VAL_TABLE_ TrkDynProp 4 "Moving in opposite direction" 3 "Moving in same direction" 2 "Has moved but currently stopped" 1 "Has never moved," 0 "Unknown" ; +VAL_TABLE_ FrntVsnInPthVehBrkNwSt 10 "Active" 5 "Inactive" ; +VAL_TABLE_ FrntVsnClostPedBrkNwSt 10 "Active" 5 "Inactive" ; +VAL_TABLE_ LaneSnsLLnPosValid 1 "Invalid" 0 "Valid" ; +VAL_TABLE_ LnSnsRLnPosValid 1 "Invalid" 0 "Valid" ; +VAL_TABLE_ ObjectType 7 "no object present" 6 "fixed roadside object" 5 "fixed overhead object" 4 "pedestrian" 3 "motocycle / bicycle" 2 "Large vehicle (semi)" 1 "4 Wheel Vehicle (car, small trk)" 0 "Unknown" ; +VAL_TABLE_ FwVsnCinCoutPotT9Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT8Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT7Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT6Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT5Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT4Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT3Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT2Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT1Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT12Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT11Rev 2 "Right" 1 "Left" 0 "None" ; +VAL_TABLE_ FwVsnCinCoutPotT10Rev 2 "Right" 1 "Left" 0 "None" ; + + +BO_ 3221225472 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ Always12 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TimeStatusChecksum : 0|12@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 161 ASCMTimeStatus: 7 NEO + SG_ TimeStatus : 7|28@0+ (1,0) [0|0] "" B233B_LRR + SG_ RollingCounter : 27|2@0+ (1,0) [0|0] "" B233B_LRR + +BO_ 774 ASCMSteeringStatus: 8 NEO + SG_ ASCMSterringStatusChecksum : 55|16@0+ (1,0) [0|0] "" B233B_LRR + SG_ AlwaysF0 : 15|8@0+ (1,0) [0|0] "" B233B_LRR + SG_ Always20 : 23|8@0+ (1,0) [0|0] "" B233B_LRR + SG_ RollingCounter : 7|2@0+ (1,0) [0|0] "" B233B_LRR + +BO_ 784 ASCMHeadlight: 2 NEO + SG_ Always42 : 7|8@0+ (1,0) [0|0] "" B233B_LRR + SG_ Always4 : 15|8@0+ (1,0) [0|0] "" B233B_LRR + +BO_ 776 ASCMAccSpeedStatus: 7 NEO + SG_ AccSpeedChecksum : 42|11@0+ (1,0) [0|0] "" B233B_LRR + SG_ RollingCounter : 46|2@0+ (1,0) [0|0] "" B233B_LRR + SG_ NearRangeMode : 43|1@0+ (1,0) [0|0] "" B233B_LRR + SG_ FarRangeMode : 44|1@0+ (1,0) [0|0] "" B233B_LRR + SG_ VehicleAcceleration : 19|12@0+ (1,0) [0|0] "" B233B_LRR + SG_ VehicleSpeed : 15|12@0+ (1,0) [0|0] "" B233B_LRR + SG_ AlwaysOne : 3|1@0+ (1,0) [0|0] "" B233B_LRR + +BO_ 1120 F_LRR_Obj_Header: 8 LRR_FO + SG_ FLRRRollingCount : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FLRRModeCmdFdbk : 23|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRNumValidTargets : 20|5@0+ (1,0) [0|31] "" EOCM_F_FO + SG_ FLRRTimeStampV : 31|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRTimeStamp : 2|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ FLRRRoadTypeInfo : 5|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FLRRBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + SG_ FLRRDiagSpare : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRVltgOutRngLo : 44|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRVltgOutRngHi : 43|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRSvcAlgnInPrcs : 38|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRSnsrBlckd : 45|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRSnstvFltPrsntInt : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRPlntAlgnInProc : 37|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnYawRt : 47|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnYawLt : 46|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRLonVelPlsblityFlt : 35|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRYawRtPlsblityFlt : 34|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnPtchUp : 32|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRMsalgnPtchDn : 33|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRInitDiagCmplt : 40|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRHWFltPrsntInt : 25|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRExtIntrfrnc : 36|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRCANSgnlSpvFld : 29|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRCANRxErr : 28|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRTunlDtctd : 27|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAmbTmpOutRngLw : 42|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAmbTmpOutRngHi : 41|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAntTngFltPrsnt : 26|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FLRRAlgnFltPrsnt : 39|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1134 LRRObject14: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1132 LRRObject12: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1131 LRRObject11: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1130 LRRObject10: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1129 LRRObject09: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1128 LRRObject08: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1127 LRRObject07: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1126 LRRObject06: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1125 LRRObject05: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1124 LRRObject04: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1123 LRRObject03: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1140 LRRObject20: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1139 LRRObject19: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1138 LRRObject18: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1137 LRRObject17: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1136 LRRObject16: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1135 LRRObject15: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1133 LRRObject13: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1122 LRRObject02: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + +BO_ 1121 LRRObject01: 8 B233B_LRR + SG_ TrkRange : 5|11@0+ (0.125,0) [0|255.875] "m" NEO + SG_ TrkRangeRate : 10|11@0- (0.125,0) [-128|127.875] "m/s" NEO + SG_ TrkRangeAccel : 31|9@0- (0.125,0) [-32|31.875] "m/s^2" NEO + SG_ TrkAzimuth : 35|12@0- (0.125,0) [-256|255.875] "deg" NEO + SG_ TrkWidth : 55|6@0+ (0.25,0) [0|15.75] "m" NEO + SG_ TrkObjectID : 61|6@0+ (1,0) [0|63] "" NEO + + BO_ 1094 F_Vision_Obj_Track_12: 8 VIS2_FO + SG_ FwdVsnObjTypTr12Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk12Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk12Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FVisionWidthTrk12 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FVisionMeasStatTrk12 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk12 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisionRelLaneTrk12 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk12 : 34|11@0- (0.125,0) [-128|127.875] "deg/sec" EOCM_F_FO + SG_ FVisionConfTrk12 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ ObjDirTrk12 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk12 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk12 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1093 F_Vision_Obj_Track_11: 8 VIS2_FO + SG_ FwdVsnObjTypTr11Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk11Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk11Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FVisionWidthTrk11 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FVisionMeasStatTrk11 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk11 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisionRelLaneTrk11 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk11 : 34|11@0- (0.125,0) [-128|127.875] "deg/sec" EOCM_F_FO + SG_ FVisionConfTrk11 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ ObjDirTrk11 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk11 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk11 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + +BO_ 1100 F_Vision_Obj_Track_12_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT12Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk12 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk12 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk12 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk12 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr12 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk12 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo12 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1099 F_Vision_Obj_Track_11_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT11Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk11 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk11 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk11 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk11 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr11 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk11 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo11 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1098 F_Vision_Obj_Track_10_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT10Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk10 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk10 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk10 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk10 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr10 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk10 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo10 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1097 F_Vision_Obj_Track_9_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT9Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk9 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk9 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk9 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk9 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr9 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk9 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo9 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1096 F_Vision_Obj_Track_8_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT8Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk8 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk8 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk8 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk8 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr8 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk8 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo8 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1095 F_Vision_Obj_Track_7_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT7Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk7 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk7 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk7 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk7 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr7 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk7 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo7 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1068 F_Vision_Obj_Track_6_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT6Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk6 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk6 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk6 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk6 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr6 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk6 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo6 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1067 F_Vision_Obj_Track_5_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT5Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk5 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk5 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk5 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk5 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr5 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk5 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo5 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1066 F_Vision_Obj_Track_4_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT4Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk4 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk4 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk4 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk4 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr4 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk4 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo4 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1065 F_Vision_Obj_Track_3_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT3Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk3 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk3 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk3 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk3 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr3 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk3 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo3 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1064 F_Vision_Obj_Track_2_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT2Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjAgeTrk2 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk2 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk2 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk2 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr2 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk2 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo2 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1063 F_Vision_Obj_Track_1_B: 8 VIS2_FO + SG_ FwVsnCinCoutPotT1Rev : 5|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnObjSclChgTrk1 : 15|16@0- (0.0002,0) [-6.5536|6.5534] "pix/sec" EOCM_F_FO + SG_ FwdVsnObjAgeTrk1 : 62|7@0+ (1,0) [0|127] "" EOCM_F_FO + SG_ FwdVsnLongVlctyTrk1 : 42|12@0- (0.0625,0) [-128|127.9375] "m/sec" EOCM_F_FO + SG_ FwdVsnLatOfstTrk1 : 36|10@0- (0.125,0) [-64|63.875] "m" EOCM_F_FO + SG_ FwdVsnBrkLtStatTrk1 : 38|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FwdVsnTrnSigStatTr1 : 25|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FrtVsnBrstIDAddInfo1 : 7|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1088 F_Vision_Obj_Header_2: 8 VIS2_FO + SG_ FrntVsnInPthVehBrkNwSt : 35|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FrntVsnClostPedBrkNwSt : 39|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FrntVsnClostPedObjID : 29|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FrntVsnClostPedAlrtNwFlg : 30|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrntVsnClostPedNotftnFlg : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrntVsnInPthVehAlrtNwFlg : 2|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnVldTgtNum2 : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FrtVsnTmStmp2V : 31|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnTmStmp2 : 10|11@0+ (1,0) [0|2047] "" EOCM_F_FO + SG_ FrtVsnRollCnt2 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FrtVsnBrstChksum2 : 55|16@0+ (1,0) [0|65535] "" EOCM_F_FO + +BO_ 854 F_Vision_Environment_7: 3 VIS2_FO + SG_ FwdVsnCnstrctAreaDst : 13|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnCnstrctZnDet : 15|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnEgoVehLnPos : 17|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnRdTypDet : 9|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnTunnlDetd : 23|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ FwdVsnTunnlDst : 21|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBrstID5 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 853 F_Vision_Environment_6: 8 VIS2_FO + SG_ LnMrkg4LnSnsLnHdngTngtV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnHdngTngt : 23|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnDstV : 56|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnDst : 15|8@0- (0.1,0) [-12.8|12.7] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvtV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvtGradV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvtGrad : 47|16@0- (5.96e-8,0) [-0.0019529728|0.0019529132] "1/(m*sec)" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnSnsLnCrvt : 31|16@0- (9.53e-7,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnQltyConfLvl : 63|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMrkrTyp : 4|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBrstID4 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 852 F_Vision_Environment_5: 8 VIS2_FO + SG_ LnMrkg3LnSnsLnHdngTngtV : 7|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnHdngTngt : 23|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnDstV : 56|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnDst : 15|8@0- (0.1,0) [-12.8|12.7] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvtV : 6|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvtGradV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvtGrad : 47|16@0- (5.96e-8,0) [-0.0019529728|0.0019529132] "1/(m*sec)" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnSnsLnCrvt : 31|16@0- (9.53e-7,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnQltyConfLvl : 63|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMrkrTyp : 4|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBrstID3 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 309 LHT_CameraObjConfirmation_FO: 1 VIS_FO + SG_ HiBmRecmnd : 1|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ CtLghtDet : 0|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 848 F_Vision_Environment: 8 VIS_FO + SG_ FwdVsnEnvIllum : 37|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnRtV : 1|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnRt : 31|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnChngStatus : 39|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstChecksum : 55|16@0+ (1,0) [0|65535] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseRollingCount : 7|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseSystemOK : 4|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSnsLLnPosValid : 2|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSenseDistToLLnEdge : 14|7@0+ (0.05,0) [0|6.35] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsRLnPosValid : 0|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsDistToRLnEdge : 22|7@0+ (0.05,0) [0|6.35] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseTimeStampV : 5|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseTimeStamp : 34|11@0+ (1,0) [0|2047] "ms" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LaneSenseSystemOKV : 3|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 849 F_Vision_Environment_2: 8 VIS_FO + SG_ LnSnsLatVRelToRgtMrkg : 23|8@0- (0.02,0) [-2.56|2.54] "m/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM_F_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO + SG_ LnSnsRtLnMrkgTypChgDst : 61|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntRtV : 63|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnMrkgWdthRt : 62|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsRtAnchrLn : 57|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtAnchrLn : 56|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrRghtV : 0|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrRght : 47|16@0- (9.53e-7,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntRt : 31|16@0- (5.96e-8,0) [-0.0019529728|0.0019529132] "1/rad/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstID : 2|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLatVRelToLftMrkg : 15|8@0- (0.02,0) [-2.56|2.54] "m/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + +BO_ 1056 F_Vision_Obj_Header: 6 VIS_FO + SG_ FVsnSnsrBlckd : 24|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ ClstInPathVehObjID : 30|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FrtVsnFld : 6|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnIniDiagSuccCmpt : 5|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnSrvAlgnInPrcs : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FrtVsnUnvlbl : 7|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionRollingCnt : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVISModeCmdFdbk : 4|3@0+ (1,0) [0|7] "" EOCM_F_FO + SG_ FVisionNumValidTrgts : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FVisionTimeStampV : 31|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionTimeStamp : 10|11@0+ (1,0) [0|2047] "ms" EOCM_F_FO + SG_ VISBurstChecksum : 39|16@0+ (1,0) [0|65535] "" EOCM_F_FO + +BO_ 1057 F_Vision_Obj_Track_1: 8 VIS_FO + SG_ FwdVsnRngTrk1Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk1Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr1Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk1 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisBurstIDTrk1 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk1 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk1 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk1 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk1 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk1 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk1 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ ObjDirTrk1 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1058 F_Vision_Obj_Track_2: 8 VIS_FO + SG_ FwdVsnVertPosTrk2 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk2Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk2Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ ObjDirTrk2 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FwdVsnObjTypTr2Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FVisBurstIDTrk2 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk2 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk2 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk2 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk2 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk2 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk2 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1059 F_Vision_Obj_Track_3: 8 VIS_FO + SG_ FwdVsnVertPosTrk3 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk3Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk3Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr3Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk3 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk3 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk3 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk3 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk3 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk3 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk3 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk3 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1060 F_Vision_Obj_Track_4: 8 VIS_FO + SG_ FwdVsnVertPosTrk4 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FVisionMeasStatTrk4 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk4 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FwdVsnRngTrk4Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk4Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr4Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FVisBurstIDTrk4 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk4 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ ObjDirTrk4 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionConfTrk4 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk4 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk4 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + +BO_ 1061 F_Vision_Obj_Track_5: 8 VIS_FO + SG_ FwdVsnVertPosTrk5 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk5Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk5Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr5Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk5 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk5 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk5 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk5 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk5 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk5 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk5 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk5 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1062 F_Vision_Obj_Track_6: 8 VIS_FO + SG_ FwdVsnVertPosTrk6 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk6Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk6Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr6Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk6 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk6 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk6 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk6 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk6 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk6 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk6 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk6 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1089 F_Vision_Obj_Track_7: 8 VIS2_FO + SG_ FVisBurstIDTrk7 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk7 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk7 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk7 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk7 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk7 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk7 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + SG_ FwdVsnRngTrk7Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnObjTypTr7Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk7Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnVertPosTrk7 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ ObjDirTrk7 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + +BO_ 1090 F_Vision_Obj_Track_8: 8 VIS2_FO + SG_ FVisBurstIDTrk8 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk8 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FwdVsnAzmthTrk8Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnVertPosTrk8 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk8Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnObjTypTr8Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk8 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisionConfTrk8 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk8 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk8 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk8 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk8 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1091 F_Vision_Obj_Track_9: 8 VIS2_FO + SG_ FwdVsnVertPosTrk9 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ FwdVsnRngTrk9Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk9Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr9Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ ObjDirTrk9 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk9 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk9 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk9 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk9 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk9 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk9 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk9 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 1092 F_Vision_Obj_Track_10: 8 VIS2_FO + SG_ FwdVsnRngTrk10Rev : 16|12@0+ (0.1,0) [0|409.5] "m" EOCM_F_FO + SG_ FwdVsnAzmthTrk10Rev : 10|10@0- (0.1,0) [-51.2|51.1] "deg" EOCM_F_FO + SG_ FwdVsnObjTypTr10Rev : 14|4@0+ (1,0) [0|15] "" EOCM_F_FO + SG_ FwdVsnVertPosTrk10 : 53|6@0+ (0.25,-2) [-2|13.75] "deg" EOCM_F_FO + SG_ ObjDirTrk10 : 15|1@0+ (1,0) [0|1] "" EOCM_F_FO + SG_ FVisBurstIDTrk10 : 1|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionObjectIDTrk10 : 7|6@0+ (1,0) [0|63] "" EOCM_F_FO + SG_ FVisionConfTrk10 : 36|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionAzRateTrk10 : 34|11@0- (0.125,0) [-128|127.875] "deg/s" EOCM_F_FO + SG_ FVisionRelLaneTrk10 : 55|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionMeasStatTrk10 : 63|2@0+ (1,0) [0|3] "" EOCM_F_FO + SG_ FVisionWidthTrk10 : 61|6@0+ (0.25,0) [0|15.75] "m" EOCM_F_FO + +BO_ 851 F_Vision_Environment_4: 8 VIS_FO + SG_ LnMrkg3LnPrvwDst : 45|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTtlNmLnMrkgDetRt : 4|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsRtLinCrsTm : 25|5@0+ (0.1,0) [0|3.1] "s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsNumPrlLnsDetRt : 33|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsNumPrlLnsDetLt : 36|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntLftV : 31|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtLinCrsTm : 30|5@0+ (0.1,0) [0|3.1] "s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnPrvwDst : 50|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMrkgTypChgDst : 61|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMrkgTypChgDst : 40|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMrkgWdth : 62|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4LnMarkrElvtd : 51|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg4AnchrLnLin : 57|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMrkgWdth : 41|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3LnMarkrElvtd : 46|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkg3AnchrLnLin : 52|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstID2 : 1|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsCrvtGrdntLft : 15|16@0- (5.96e-8,0) [-0.0019529728|0.0019529132] "1/rad/s" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + + BO_ 850 F_Vision_Environment_3: 8 VIS_FO + SG_ LnSnsTtlNmLnMrkgDetLt : 58|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtLnMrkgWdth : 63|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLtLnMrkgTypChgDst : 62|4@0+ (10,0) [0|150] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnLftV : 23|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsTngtOfHdngLnLft : 31|8@0- (0.002,0) [-0.256|0.254] "m/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrLftV : 15|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsLnCrvtrLft : 39|16@0- (9.53e-7,0) [-0.031227904|0.031226951] "1/m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrTypRght : 50|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrTypLft : 53|3@0+ (1,0) [0|7] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrElvtdRght : 54|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnMrkrElvtdLft : 55|1@0+ (1,0) [0|1] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnSnsBurstID1 : 7|2@0+ (1,0) [0|3] "" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnQltyCnfdncLvlRght : 22|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnQltyCnfdncLvlLft : 14|7@0+ (0.7874016,0) [0|100.0000032] "%" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnPrvwDstncRght : 2|3@0+ (10,0) [0|70] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + SG_ LnPrvwDstncLft : 5|3@0+ (10,0) [0|70] "m" EOCM2A_IMX6_FO,EOCM2A_K2_FO,EOCM2A_K1_FO,EOCM2B_IMX6_FO,EOCM2B_K2_FO,EOCM2B_K1_FO,EOCM_F_FO + + +BO_TX_BU_ 161 : K124_ASCM,NEO; +BO_TX_BU_ 774 : K124_ASCM,NEO; +BO_TX_BU_ 784 : K124_ASCM,NEO; +BO_TX_BU_ 776 : K124_ASCM,NEO; + + +CM_ BU_ K109_FCM "Frontview Camera Module"; +CM_ BU_ B233B_LRR "Radar Sensor Module Long Range"; +CM_ BU_ NEO "Comma NEO"; +CM_ BU_ VIS_FO "Front Camera Data"; +CM_ BU_ VIS2_FO "Front Camera Data2"; +CM_ BU_ K124_ASCM "Active Safety Control Module"; +CM_ BO_ 3221225472 "This is a message for not used signals, created by Vector CANdb++ DBC OLE DB Provider."; +BA_DEF_ "UseGMParameterIDs" INT 0 0; +BA_DEF_ "ProtocolType" STRING ; +BA_DEF_ "BusType" STRING ; +BA_DEF_DEF_ "UseGMParameterIDs" 1; +BA_DEF_DEF_ "ProtocolType" "GMLAN"; +BA_DEF_DEF_ "BusType" ""; +BA_ "BusType" "CAN"; +BA_ "ProtocolType" "GMLAN"; +BA_ "UseGMParameterIDs" 0; +VAL_ 776 NearRangeMode 1 "Active" 0 "Inactive"; +VAL_ 776 FarRangeMode 1 "Active" 0 "Inactive"; diff --git a/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_expansion.dbc b/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_expansion.dbc new file mode 100644 index 0000000000..b18ac6974d --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gm_global_a_powertrain_expansion.dbc @@ -0,0 +1,56 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: +BU_: K1_APM +BO_ 470 APM_Stats: 7 K1_APM + SG_ APM_Low_Voltage_Sensed : 16|8@1+ (0.0787402,0) [0|0] "V" Vector__XXX + SG_ APM_Temperature_1 : 24|8@1+ (1,-40) [0|0] "C" Vector__XXX + SG_ APM_Temperature_2 : 32|8@1+ (1,-40) [0|0] "C" Vector__XXX + SG_ APM_Low_Voltage_Current_Output : 40|8@1- (1,0) [0|0] "A" Vector__XXX + SG_ APM_Status : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ APM_High_Voltage_Input_Current : 8|8@1- (0.15,-7) [0|0] "A" Vector__XXX + SG_ APM_Counter : 48|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 468 APM_Command: 2 K1_APM + SG_ APM_Status : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ APM_Voltage_Requested : 8|8@1+ (0.0787402,0) [0|0] "V" Vector__XXX + +BA_DEF_ BO_ "GenMsgBackgroundColor" STRING ; +BA_DEF_ BO_ "GenMsgForegroundColor" STRING ; +BA_DEF_ BO_ "isj1939dbc" INT 0 0; +BA_DEF_DEF_ "GenMsgBackgroundColor" "#ffffff"; +BA_DEF_DEF_ "GenMsgForegroundColor" "#000000"; +BA_DEF_DEF_ "isj1939dbc" 0; +CM_ BU_ K1_APM "14V Power Module"; +VAL_ 468 APM_Status 0 "Off" 160 "On"; diff --git a/opendbc_repo/opendbc/dbc/gwm_haval_h6_phev_2024.dbc b/opendbc_repo/opendbc/dbc/gwm_haval_h6_phev_2024.dbc new file mode 100644 index 0000000000..960f3e87ec --- /dev/null +++ b/opendbc_repo/opendbc/dbc/gwm_haval_h6_phev_2024.dbc @@ -0,0 +1,251 @@ +BO_ 96 CAR_OVERALL_SIGNALS2: 64 XXX + SG_ CRC1 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER1 : 59|4@0+ (1,0) [0|15] "" XXX + SG_ CRC2 : 71|8@0+ (1,0) [0|255] "" XXX + SG_ GAS_POSITION : 79|8@0+ (0.393700787,0) [0|255] "%" XXX + SG_ BRAKE_SIGNAL : 86|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_GAS_POSITION : 103|8@0+ (0.393700787,0) [0|255] "%" XXX + SG_ COUNTER2 : 123|4@0+ (1,0) [0|15] "" XXX + SG_ CRC3 : 135|8@0+ (1,0) [0|255] "" XXX + SG_ REQ_REVIEW_UND_SIGNAL : 143|10@0+ (1,0) [0|255] "" XXX + SG_ REQ_REVIEW_POWER_CONSUMPTION : 144|9@0+ (1,-175) [0|511] "" XXX + SG_ REQ_REVIEW_POWER_CONSUMPTION2 : 180|9@0+ (1,-176) [0|511] "" XXX + SG_ COUNTER3 : 187|4@0+ (1,0) [0|15] "" XXX + SG_ REQ_REVIEW_POWER_STATE_SIGNAL : 302|4@0+ (1,0) [0|15] "" XXX + SG_ REQ_REVIEW_POWER_STATE_SIGNAL2 : 370|1@0+ (1,0) [0|1] "" XXX + +BO_ 147 IMPRECISE_SPEED_INFORMATION: 8 XXX + SG_ IMPRECISE_SPEED : 15|8@0+ (3.5,0) [0|255] "kph" XXX + SG_ REQ_REVIEW_SPEED : 31|8@0+ (0.430107526,0) [0|255] "Kph" XXX + SG_ REQ_REVIEW_SPEED2 : 39|8@0+ (0.430107526,0) [0|255] "Kph" XXX + SG_ REQ_REVIEW_POWER_CONSUMPTION : 52|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 161 STEER_AND_AP_STALK: 8 XXX + SG_ CRC : 7|8@0+ (1,0) [0|255] "" XXX + SG_ STEERING_ANGLE : 15|16@0+ (0.05,0) [0|65535] "degs" XXX + SG_ STEERING_TORQUE : 31|16@0+ (1,0) [0|65535] "??" XXX + SG_ AP_REDUCE_DISTANCE_COMMAND : 44|1@0+ (1,0) [0|1] "" XXX + SG_ AP_INCREASE_DISTANCE_COMMAND : 45|1@0+ (1,0) [0|1] "AUTOPILOT_STALK" XXX + SG_ AP_CANCEL_COMMAND : 46|1@0+ (1,0) [0|1] "" XXX + SG_ AP_ENABLE_COMMAND : 47|1@0+ (1,0) [0|1] "" XXX + SG_ AP_DECREASE_SPEED_COMMAND : 50|1@0+ (1,0) [0|1] "" XXX + SG_ AP_INCREASE_SPEED_COMMAND : 51|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 59|4@0+ (1,0) [0|255] "" XXX + +BO_ 259 SPEED: 64 XXX + SG_ CRC : 199|8@0+ (1,0) [0|255] "" XXX + SG_ UNDEFINED_ACCUMULATOR : 207|8@0+ (1,0) [0|255] "" XXX + SG_ UNDEFINED_COUNTER : 215|8@0+ (1,0) [0|255] "" XXX + SG_ ODD_GAS_POSITION : 231|8@0+ (1,0) [0|255] "" XXX + SG_ SPEED : 239|8@0+ (1,0) [0|255] "Khp" XXX + SG_ COUNTER2 : 251|4@0+ (1,0) [0|15] "" XXX + +BO_ 273 UNDEFINED_2: 8 XXX + SG_ CRC : 7|8@0+ (1,0) [0|255] "" XXX + SG_ UNDEFINED_SIGNAL_RELATED_ACC : 46|13@0+ (1,0) [0|8191] "" XXX + SG_ COUNTER : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 288 BRAKE2: 64 XXX + SG_ CRC : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REVIEW_REQ_BRAKE_SIGNAL1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ REQ_REVIEW_MOVING : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ODD_BRAKE_PRESSURE : 39|8@0+ (1,-27) [0|255] "" XXX + SG_ REVIEW_REQ_BRAKE_SIGNAL2 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 299 AUTOPILOT: 64 XXX + SG_ REQ_REVIEW_CRC : 71|8@0+ (1,0) [0|255] "" XXX + SG_ AP_UNDEFINED_SIGNAL2 : 73|2@0+ (1,0) [0|3] "" XXX + SG_ REQ_REVIEW_COUNTER : 78|5@0+ (1,0) [0|31] "" XXX + SG_ AP_UNDEFINED_SIGNAL : 87|6@0+ (1,0) [0|63] "" XXX + SG_ AP_STEERING_UNDEFINED_SIGNAL1 : 102|10@0- (1,0) [0|2047] "" XXX + SG_ AP_UNDEFINED_SIGNAL3 : 103|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 123|4@0+ (1,0) [0|15] "" XXX + SG_ AP_STATE : 125|1@0+ (1,0) [0|1] "" XXX + SG_ CRC : 135|8@0+ (1,0) [0|255] "" XXX + +BO_ 303 CAR_OVERALL_SIGNALS: 64 XXX + SG_ CRC1 : 71|8@0+ (1,0) [0|255] "" XXX + SG_ DRIVE_MODE_SIGNAL : 73|1@0+ (1,0) [0|1] "" XXX + SG_ REQ_REVIEW_POWER_STATE : 80|1@0+ (1,0) [0|1] "" XXX + SG_ REQ_REVIEW_POWER_STATE2 : 83|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_SIGNAL : 86|1@0+ (1,0) [0|1] "" XXX + SG_ REQ_REVIEW_POWER_STATE3 : 113|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER1 : 123|4@0+ (1,0) [0|15] "" XXX + SG_ CRC2 : 135|8@0+ (1,0) [0|255] "" XXX + SG_ DRIVER_MODE_SIGNAL2 : 161|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_MODE_P : 162|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_MODE_D : 163|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_MODE_SIGNAL3 : 165|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_MODE : 166|2@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_SIGNAL : 176|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER2 : 187|4@0+ (1,0) [0|15] "" XXX + +BO_ 311 BRAKE: 64 XXX + SG_ CRC1 : 71|8@0+ (1,0) [0|255] "" XXX + SG_ REQ_REVIEW_DRIVE_MODE : 77|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER1 : 123|4@0+ (1,0) [0|15] "" XXX + SG_ CRC2 : 135|8@0+ (1,0) [0|255] "" XXX + SG_ REQ_REVIEW_HANDBRAKE_ENABLED : 143|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_SIGNAL1 : 152|1@0+ (1,0) [0|1] "" XXX + SG_ REVIEW_REQ_HANDBRAKE_RELEASED : 153|1@0+ (1,0) [0|1] "" XXX + SG_ REVIEW_REQ_HANDBRAKE_ENABLED : 154|1@0+ (1,0) [0|1] "DURING POWER BRAKE IS FALSE" XXX + SG_ BRAKE_SIGNAL2 : 155|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER2 : 187|4@0+ (1,0) [0|15] "" XXX + SG_ CRC3 : 199|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRESSURE : 207|13@0+ (1,0) [0|8191] "" XXX + SG_ REQ_REVIEW_BRAKE_PRESSURE : 207|14@0+ (1,0) [0|1] "" XXX + SG_ COUNTER3 : 251|4@0+ (1,0) [0|15] "" XXX + SG_ CRC4 : 263|8@0+ (1,0) [0|255] "" XXX + +BO_ 315 WHEEL_SPEEDS: 64 XXX + SG_ FRONT_CRC : 7|8@0+ (1,0) [0|255] "" XXX + SG_ FRONT_LEFT_WHEEL_SPEED : 12|13@0+ (0.05924739,0) [0|8191] "Kph" XXX + SG_ FRONT_RIGHT_WHEEL_SPEED : 28|13@0+ (0.05924739,0) [0|8191] "Kph" XXX + SG_ FRONT_DISTANCE_ACCUMULATOR : 47|16@0+ (1,0) [0|65535] "??" XXX + SG_ FRONT_COUNTER : 59|4@0+ (1,0) [0|15] "" XXX + SG_ REAR_CRC : 327|8@0+ (1,0) [0|255] "" XXX + SG_ REAR_LEFT_WHEEL_SPEED : 332|13@0+ (0.05924739,0) [0|8191] "Kph" XXX + SG_ REAR_RIGHT_WHEEL_SPEED : 348|13@0+ (0.05924739,0) [0|8191] "Kph" XXX + SG_ REAR_DISTANCE_ACCUMULATOR : 367|16@0+ (1,0) [0|65535] "" XXX + SG_ REAR_COUNTER : 379|4@0+ (1,0) [0|15] "" XXX + +BO_ 323 SPEED2: 64 XXX + SG_ NEW_SIGNAL_1 : 71|8@0+ (1,0) [0|255] "" XXX + SG_ SPEED_REAL : 119|8@0+ (1,0) [0|255] "Kph" XXX + SG_ COUNTER : 123|4@0+ (1,0) [0|15] "" XXX + SG_ CRC2 : 135|8@0+ (1,0) [0|255] "" XXX + +BO_ 327 NEW_MSG_147: 64 XXX + +BO_ 347 NEW_MSG_15B: 64 XXX + +BO_ 357 NEW_MSG_165: 8 XXX + +BO_ 367 NEW_MSG_16F: 64 XXX + +BO_ 412 LIGHTS: 16 XXX + SG_ BRAKE_LIGHTS : 24|3@0+ (1,0) [0|7] "" XXX + SG_ RIGHT_TURN_SIGNAL : 30|1@0+ (1,0) [0|1] "ON/OFF ACCORDINGLY LIGHT" XXX + SG_ LEFT_TURN_SIGNAL : 31|1@0+ (1,0) [0|1] "ON/OFF ACCORDINGLY LIGHT" XXX + +BO_ 415 NEW_MSG_19F: 64 XXX + +BO_ 573 UNDEFINED_RELATIONSHIP_WITH_CAR_RUNNING: 64 XXX + SG_ COUNTER1 : 123|4@0+ (1,0) [0|15] "" XXX + SG_ CRC2 : 135|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER2 : 187|12@0+ (1,0) [0|4095] "" XXX + SG_ COUNTER3 : 251|4@0+ (1,0) [0|15] "" XXX + SG_ CRC3 : 263|8@0+ (1,0) [0|255] "" XXX + +BO_ 581 NEW_MSG_245: 8 XXX + +BO_ 639 NEW_MSG_27F: 16 XXX + SG_ CRC : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REQ_REVIEW_ODOMETER : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 59|4@0+ (1,0) [0|15] "" XXX + +BO_ 649 DRIVE_MODE: 64 XXX + SG_ DRIVE_MODE_ENABLED : 382|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE_MODE_DISABLED : 383|1@0+ (1,0) [0|1] "" XXX + +BO_ 683 ACC: 64 XXX + SG_ COUNTER1 : 123|4@0+ (1,0) [0|15] "" XXX + SG_ CRC1 : 135|8@0+ (1,0) [0|255] "" XXX + SG_ CAR_DISTANCE_SELECTION : 170|3@0+ (1,0) [0|7] "" XXX + SG_ ACC_SPEED_SELECTION : 183|8@0+ (1,0) [0|255] "Kph" XXX + SG_ COUNTER2 : 187|4@0+ (1,0) [0|15] "" XXX + +BO_ 696 UNDEFINED_INTERESTING_SIGNALS: 64 XXX + SG_ UNDEFINED_SIGNAL2 : 20|9@0+ (1,0) [0|511] "" XXX + SG_ UNDEFINED_SIGNAL1 : 27|12@0+ (1,0) [0|4095] "" XXX + SG_ UNDEFINED_ACCUMULATOR : 47|8@0+ (1,0) [0|255] "" XXX + SG_ UNDEFINED_ACCUMULATOR2 : 47|12@0+ (1,0) [0|15] "" XXX + SG_ UNDEFINED_SIGNAL3 : 51|12@0+ (1,0) [0|4095] "" XXX + SG_ UNDEFINED_SIGNAL4 : 265|10@0+ (1,0) [0|1023] "" XXX + SG_ NEW_SIGNAL_1 : 354|7@0+ (1,0) [0|127] "" XXX + +BO_ 714 BUTTONS: 8 XXX + SG_ LOCK_DOORS_BUTTON : 16|1@0+ (1,0) [0|1] "" XXX + +BO_ 793 DOOR_DRIVER: 16 XXX + SG_ REQ_REVIEW_CAR_STATE : 16|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_REAR_RIGHT_OPEN : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_FRONT_RIGHT_OPEN : 20|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_REAR_LEFT_OPEN : 21|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_DRIVER_OPEN : 22|1@0+ (1,0) [0|1] "" XXX + +BO_ 837 DOOR_LOCK_STATES: 16 XXX + SG_ DOOR_LOCK_STATE : 13|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_LOCK_STATE2 : 34|1@0+ (1,0) [0|1] "" XXX + +BO_ 849 SEATBELT: 16 XXX + SG_ CRC : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SEAT_BELT_DRIVER_STATE : 11|1@0+ (1,0) [0|1] "" XXX + SG_ SEAT_BELT_DRIVER_STATE2 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 59|4@0+ (1,0) [0|15] "" XXX + +CM_ SG_ 96 GAS_POSITION "0 - 100%"; +CM_ SG_ 96 BRAKE_SIGNAL "1 = BRAKE PRESSED"; +CM_ SG_ 96 ACC_GAS_POSITION "0 - 100% | WHEN ACC REMAINS INFORMATION"; +CM_ SG_ 96 REQ_REVIEW_POWER_CONSUMPTION2 "REQ FACTOR CONVERTER"; +CM_ SG_ 96 REQ_REVIEW_POWER_STATE_SIGNAL "1 = OFF | 12 WARM-UP | 5 = ON"; +CM_ SG_ 96 REQ_REVIEW_POWER_STATE_SIGNAL2 "1 = OFF | 0 = ON"; +CM_ SG_ 147 IMPRECISE_SPEED "lower precision, reverse is positive as well"; +CM_ SG_ 147 REQ_REVIEW_SPEED "INITIALLY ADJUSTED TO KPH BUT ITS NOT"; +CM_ SG_ 147 REQ_REVIEW_SPEED2 "INITIALLY ADJUSTED TO KPH BUT ITS NOT"; +CM_ SG_ 161 STEERING_ANGLE "0 CENTER, NO LEFT / RIGHT SIGNAL"; +CM_ SG_ 161 STEERING_TORQUE "Peak identified 3680, 0 = stopped"; +CM_ SG_ 161 AP_REDUCE_DISTANCE_COMMAND "AUTOPILOT STALK"; +CM_ SG_ 161 AP_CANCEL_COMMAND "AUTOPILOT STALK - FRONT MOVEMENT = CANCEL COMMAND"; +CM_ SG_ 161 AP_ENABLE_COMMAND "AUTOPILOT STALK - REAR MOVEMENT = ENABLE COMMAND"; +CM_ SG_ 161 AP_DECREASE_SPEED_COMMAND "AUTOPILOT STALK - MOVEMENT"; +CM_ SG_ 161 AP_INCREASE_SPEED_COMMAND "AUTOPILOT STALK - DOWN MOVEMENT]"; +CM_ SG_ 259 UNDEFINED_ACCUMULATOR "WHEN ELETRIC MODE = 0, PERHAPS COMBUSTION ENGINE"; +CM_ SG_ 259 UNDEFINED_COUNTER "0 WHEN ELECTRIC, PERHAPS COMBUSTION ENGINE"; +CM_ SG_ 259 ODD_GAS_POSITION "17 = 0, 253 = FULL, SOMETIMES 4"; +CM_ SG_ 259 SPEED "PRECISE, KPH, DASHBOARD SPEED, BIT LOWER THAN GPS SPEED"; +CM_ SG_ 288 REVIEW_REQ_BRAKE_SIGNAL1 "0 | 128 SIMILAR TO BRAKE SIGNAL BUT ADDITIONAL DELAY"; +CM_ SG_ 288 REQ_REVIEW_MOVING "1 = CAR IS MOVING"; +CM_ SG_ 288 ODD_BRAKE_PRESSURE "ODD BRAKE PRESSURE, NEGATIVE/OFFSET"; +CM_ SG_ 288 REVIEW_REQ_BRAKE_SIGNAL2 "0 | 128 BRAKE PRESSED"; +CM_ SG_ 299 REQ_REVIEW_COUNTER "COUNTER NOT STABLE"; +CM_ SG_ 299 AP_UNDEFINED_SIGNAL3 "PERHAPS HANDS ON SENSOR"; +CM_ SG_ 299 AP_STATE "1 = ON | 0 = OFF"; +CM_ SG_ 303 DRIVE_MODE_SIGNAL "D/R = 0 | N/P = 1"; +CM_ SG_ 303 REQ_REVIEW_POWER_STATE "1 = ON | 0 = IDLE"; +CM_ SG_ 303 REQ_REVIEW_POWER_STATE2 "1 = ON | 0 = IDLE"; +CM_ SG_ 303 GAS_SIGNAL "1 = GAS PRESSED"; +CM_ SG_ 303 REQ_REVIEW_POWER_STATE3 "0 = OFF / 1 = ON"; +CM_ SG_ 303 DRIVER_MODE_SIGNAL2 "D/R = 1 | N/P=0"; +CM_ SG_ 303 DRIVE_MODE_SIGNAL3 "P/R = 1 | P/N = 0"; +CM_ SG_ 303 DRIVE_MODE "0 = P | 1 = D | 2 = N | 3 = R (GOOD SIGNAL)"; +CM_ SG_ 303 BRAKE_SIGNAL "1 BRAKE PRESSED"; +CM_ SG_ 311 REQ_REVIEW_DRIVE_MODE "1 = P | 0 = D"; +CM_ SG_ 311 BRAKE_SIGNAL1 "0 = NO | 1 = BRAKE PRESSED"; +CM_ SG_ 311 REVIEW_REQ_HANDBRAKE_RELEASED "DURING POWER BRAKE IS TRUE"; +CM_ SG_ 311 BRAKE_SIGNAL2 "0 NO | 1 = BRAKE PRESSED"; +CM_ SG_ 311 BRAKE_PRESSURE "MAX PRESSURE IDENTIFIED = 4184 | 0 = NO PRESSURE"; +CM_ SG_ 311 REQ_REVIEW_BRAKE_PRESSURE "ADDITIONAL BIT"; +CM_ SG_ 315 FRONT_LEFT_WHEEL_SPEED "Based on the car's dashboard speed"; +CM_ SG_ 315 FRONT_RIGHT_WHEEL_SPEED "Based on the car's dashboard speed"; +CM_ SG_ 315 FRONT_DISTANCE_ACCUMULATOR "?? doubts"; +CM_ SG_ 315 REAR_LEFT_WHEEL_SPEED "Based on the car's dashboard speed"; +CM_ SG_ 315 REAR_RIGHT_WHEEL_SPEED "Based on the car's dashboard speed"; +CM_ SG_ 315 REAR_DISTANCE_ACCUMULATOR "PULSES"; +CM_ SG_ 323 SPEED_REAL "PRECISE, EQUAL GPS SPEED"; +CM_ SG_ 412 BRAKE_LIGHTS "POSSIBLE 3 DIFFERENT LIGHTS"; +CM_ SG_ 412 LEFT_TURN_SIGNAL "ON/OFF ACCORDINGLY LIGHT"; +CM_ BO_ 573 "APPEARS TO HAVE GOOD MOVING INFORMATION"; +CM_ BO_ 649 "FRONT"; +CM_ SG_ 649 DRIVE_MODE_ENABLED "DRIVE = 1 | OTHER MODES = 0"; +CM_ SG_ 649 DRIVE_MODE_DISABLED "D = 0 | OTHER MODES = 0"; +CM_ SG_ 683 CAR_DISTANCE_SELECTION "AUTOPILOT CAR DISTANCE SELECTED BY DRIVER, OPTIONS 1, 2, 3, 4"; +CM_ BO_ 696 "POSSIBLE RELATED TO ACC OR ENGINE"; +CM_ SG_ 714 LOCK_DOORS_BUTTON "1 = PRESSED"; +CM_ SG_ 793 REQ_REVIEW_CAR_STATE "1 = STOPPED | 0 = MOVING"; +CM_ SG_ 837 DOOR_LOCK_STATE "0 = LOCKED / 1 = UNLOCKED"; +CM_ SG_ 837 DOOR_LOCK_STATE2 "0 = LOCKED / 1 = UNLOCKED"; +CM_ SG_ 849 SEAT_BELT_DRIVER_STATE "0 = Fastened / 1 = Released"; +CM_ SG_ 849 SEAT_BELT_DRIVER_STATE2 "0 = Fastened / 1 = Released"; diff --git a/opendbc_repo/opendbc/dbc/hongqi_hs5.dbc b/opendbc_repo/opendbc/dbc/hongqi_hs5.dbc new file mode 100644 index 0000000000..76b41d873c --- /dev/null +++ b/opendbc_repo/opendbc/dbc/hongqi_hs5.dbc @@ -0,0 +1,160 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 146 ECM_1: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ THROTTLE_1 : 8|12@1+ (1,0) [0|255] "" XXX + SG_ THROTTLE_2 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ THROTTLE_3 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ DRIVER_THROTTLE : 40|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 192 ABS_1: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|15] "" XXX + SG_ FRONT_LEFT : 8|16@1+ (0.01,0) [0|65535] "km/h" XXX + SG_ FRONT_RIGHT : 24|16@1+ (0.01,0) [0|65535] "km/h" XXX + SG_ VEHICLE_SPEED : 40|16@1+ (0.01,0) [0|65535] "km/h" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 194 ABS_2: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|15] "" XXX + SG_ REAR_LEFT : 8|16@1+ (0.01,0) [0|65535] "km/h" XXX + SG_ REAR_RIGHT : 24|16@1+ (0.01,0) [0|65535] "km/h" XXX + SG_ BRAKE_PRESSURE : 40|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 208 EPS_1: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|15] "" XXX + SG_ STEER_ANGLE : 8|15@1+ (0.0225,0) [0|65535] "" XXX + SG_ STEER_ANGLE_DIRECTION : 23|1@1+ (1,0) [0|1] "direction" XXX + SG_ STEER_RATE : 24|15@1+ (0.0225,0) [0|65535] "" XXX + SG_ STEER_RATE_DIRECTION : 39|1@1+ (1,0) [0|1] "direction" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 336 EPS_2: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ EPS_TORQUE : 8|10@1- (1,0) [0|255] "" XXX + SG_ EPS_TORQUE_DIRECTION : 18|1@1+ (1,0) [0|1] "direction" XXX + SG_ UNKNOWN : 22|2@1+ (1,0) [0|3] "" XXX + SG_ LKAS_STATUS : 24|4@1+ (1,0) [0|15] "" XXX + SG_ DRIVER_INPUT_TORQUE : 32|8@1+ (1,0) [0|255] "" XXX + SG_ LKAS_TORQUE : 40|10@1+ (1,0) [0|1023] "" XXX + SG_ LKAS_TORQUE_DIRECTION : 50|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 272 ACC: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_1 : 8|12@1+ (1,0) [0|4095] "" XXX + SG_ UNKNOWN_2 : 20|4@1+ (1,0) [0|15] "" XXX + SG_ ACCELERATION : 24|12@1+ (1,-300) [0|255] "" XXX + SG_ STATUS : 36|4@1+ (1,0) [0|31] "x" XXX + SG_ UNKNOWN_3 : 46|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 274 LKAS: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ LKAS_TORQUE : 8|10@1+ (1,0) [0|2047] "x" XXX + SG_ LKAS_TORQUE_DIRECTION : 18|1@1+ (1,0) [0|1] "" XXX + SG_ LKAS_TORQUE_ACTIVE : 19|1@1+ (1,0) [0|1] "" XXX + SG_ UNKNOWN_ACTIVE_STATE : 26|1@1+ (1,0) [0|1] "" XXX + SG_ MAYBE_HUD_LANE_STATES : 28|2@1+ (1,0) [0|3] "" XXX + SG_ LKAS_ACTIVE : 32|1@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 148 MAYBE_ABS: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ UNKNOWN_1 : 8|16@1+ (1,0) [0|15] "x" XXX + SG_ UNKNOWN_2 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRESSED : 35|1@1+ (1,0) [0|1] "x" XXX + SG_ UNKNOWN_3 : 46|2@1+ (1,0) [0|3] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 304 ABS_3: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 15|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 23|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 31|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 47|8@1+ (1,0) [0|255] "" XXX + SG_ DRIVER_BRAKE_PRESSURE : 48|12@1+ (1,0) [0|65535] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 144 MAYBE_ENGINE: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 8|12@1+ (1,0) [0|255] "" XXX + SG_ MAYBE_RPM : 20|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 46|14@1+ (1,0) [0|4095] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 422 MAYBE_ACC_BUTTONS: 8 XXX + SG_ NEW_SIGNAL_1 : 18|1@0+ (1,0) [0|1] "" XXX + +BO_ 560 TURN_SIGNALS: 8 XXX + SG_ RIGHT_TURN_SIGNALING : 45|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_TURN_SIGNALING : 44|1@1+ (1,0) [0|1] "" XXX + SG_ RIGHT_TURN_BULB_3 : 21|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_TURN_BULB_3 : 20|1@1+ (1,0) [0|1] "" XXX + SG_ RIGHT_TURN_BULB_2 : 19|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_TURN_BULB_2 : 18|1@1+ (1,0) [0|1] "" XXX + SG_ LEFT_TURN_BULB_1 : 16|1@1+ (1,0) [0|1] "" XXX + SG_ RIGHT_TURN_BULB_1 : 17|1@1+ (1,0) [0|1] "" XXX + +BO_ 586 DOOR_FL: 8 XXX + SG_ OPEN : 2|1@1+ (1,0) [0|1] "" XXX + +BO_ 588 DOOR_FR: 8 XXX + SG_ OPEN : 2|1@1+ (1,0) [0|1] "" XXX + +BO_ 590 DOOR_RL: 8 XXX + SG_ OPEN : 2|1@1+ (1,0) [0|1] "" XXX + +BO_ 591 DOOR_RR: 8 XXX + SG_ OPEN : 2|1@1+ (1,0) [0|1] "" XXX + + + + +CM_ SG_ 274 UNKNOWN_ACTIVE_STATE "Triggers changes from 8 to 9 in EPS_2.LKAS_STATUS"; +CM_ SG_ 560 RIGHT_TURN_SIGNALING "Includes 2.5 second convenience lane change interval"; +CM_ SG_ 560 LEFT_TURN_SIGNALING "Includes 2.5 second convenience lane change interval"; +VAL_ 336 LKAS_STATUS 1 "INITIALIZING" 5 "READY" 8 "ACTIVE_1" 9 "ACTIVE_2" 13 "FAULT" ; +VAL_ 586 OPEN 0 "CLOSED" 1 "OPEN" ; +VAL_ 588 OPEN 0 "CLOSED" 1 "OPEN" ; +VAL_ 590 OPEN 0 "CLOSED" 1 "OPEN" ; +VAL_ 591 OPEN 0 "CLOSED" 1 "OPEN" ; diff --git a/opendbc_repo/opendbc/dbc/hyundai_2015_ccan.dbc b/opendbc_repo/opendbc/dbc/hyundai_2015_ccan.dbc new file mode 100644 index 0000000000..fc1e173907 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/hyundai_2015_ccan.dbc @@ -0,0 +1,1416 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: IAP ODS _4WD BCM HUD DATC MDPS AAF_Tester AEMC SMK _4WD EPB CUBIS MTS TMU EVP CGW TPMS LPI DI_BOX SPAS EMS LCA TCU IBOX FATC AFLS FPCM SCC AHLS AVM ABS SNV OPI PGS SAS AAF Dummy LDWS_LKAS LVR ESC PSB CLU ECS ACU REA + +BO_ 1532 ODS13: 5 ODS + SG_ CR_Ods_ID : 0|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_Chksum_H : 8|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + SG_ CR_Ods_Chksum_L : 16|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + SG_ CR_Ods_RomID_H : 24|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + SG_ CR_Ods_RomID_L : 32|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + +BO_ 1531 ODS12: 8 ODS + SG_ CR_Ods_SerNum0 : 0|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum1 : 8|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum3 : 24|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum4 : 32|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum5 : 40|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum6 : 48|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum7 : 56|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + +BO_ 1530 ODS11: 8 ODS + SG_ CF_Ods_PrcCmd : 1|1@1+ (1.0,0.0) [0.0|1.0] "" Dummy + SG_ CF_Ods_BtsFail : 3|1@1+ (1.0,0.0) [0.0|1.0] "" Dummy + SG_ CF_Ods_AcuRcvSN : 4|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_EolCal : 5|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_PsFail : 6|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_EcuFail : 7|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_WgtStat : 8|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_OccStat : 16|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CR_Wcs_ErrStat : 32|8@1+ (1.0,0.0) [0.0|63.0] "" ACU + SG_ CR_Wcs_ClassStat : 40|8@1+ (1.0,0.0) [0.0|4.0] "" ACU,BCM + +BO_ 1017 ECS12: 4 ECS + SG_ Height_FL : 0|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + SG_ Height_FR : 8|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + SG_ Height_RL : 16|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + SG_ Height_RR : 24|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + +BO_ 1268 SPAS12: 8 SPAS + SG_ CF_Spas_HMI_Stat : 0|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_Spas_Disp : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS + SG_ CF_Spas_FIL_Ind : 10|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FIR_Ind : 13|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FOL_Ind : 16|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FOR_Ind : 19|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_VolDown : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_RIL_Ind : 24|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_RIR_Ind : 27|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FLS_Alarm : 30|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_ROL_Ind : 32|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_ROR_Ind : 35|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FCS_Alarm : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_FI_Ind : 40|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_RI_Ind : 43|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FRS_Alarm : 46|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_FR_Alarm : 48|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Spas_RR_Alarm : 50|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Spas_BEEP_Alarm : 52|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Spas_StatAlarm : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Spas_RLS_Alarm : 57|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_RCS_Alarm : 59|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_RRS_Alarm : 61|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1265 CLU11: 4 CLU + SG_ CF_Clu_CruiseSwState : 0|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,LDWS_LKAS,SCC + SG_ CF_Clu_CruiseSwMain : 3|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,LDWS_LKAS,SCC + SG_ CF_Clu_SldMainSW : 4|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Clu_ParityBit1 : 5|1@1+ (1.0,0.0) [0.0|1.0] "pulse count" EMS + SG_ CF_Clu_VanzDecimal : 6|2@1+ (0.125,0.0) [0.0|0.375] "" EMS + SG_ CF_Clu_Vanz : 8|9@1+ (0.5,0.0) [0.0|255.5] "km/h or MPH" BCM,CUBIS,EMS,IBOX,LDWS_LKAS,MDPS,SCC + SG_ CF_Clu_SPEED_UNIT : 17|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CUBIS,EMS,IBOX,LDWS_LKAS,MDPS,SCC + SG_ CF_Clu_DetentOut : 18|1@1+ (1.0,0.0) [0.0|1.0] "" AVM,BCM,LCA,PGS,SPAS + SG_ CF_Clu_RheostatLevel : 19|5@1+ (1.0,0.0) [0.0|31.0] "" AVM,BCM,LCA,PGS,SPAS + SG_ CF_Clu_CluInfo : 24|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_AmpInfo : 25|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_AliveCnt1 : 28|4@1+ (1.0,0.0) [0.0|15.0] "" AHLS,EMS,EPB,LDWS_LKAS,MDPS,SCC + +BO_ 1492 TMU_GW_PE_01: 8 CLU + SG_ TMU_IVRActivity : 0|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ TMU_PhoneActivity : 2|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + +BO_ 1491 HU_DATC_PE_00: 8 CLU + SG_ HU_VRActivity : 0|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ HU_PhoneActivity : 2|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ BlowerNoiseControl : 4|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + +BO_ 1490 HU_DATC_E_02: 8 CLU + SG_ HU_DATC_RearOnOffSet : 6|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ HU_DATC_ADSOnOffSet : 8|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + +BO_ 1479 EMS21: 8 EMS + SG_ SCR_LEVEL_WARN_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ SCR_LEVEL_WARN : 1|3@1+ (1.0,0.0) [0.0|4.0] "" CLU + SG_ SCR_SYS_ERROR_WARN : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ SCR_SYSTEM_WARN_LAMP : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ SCR_INDUCEMENT_EXIT_COND : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ SCR_UREA_LEVEL : 16|8@1+ (0.5,0.0) [0.0|100.0] "%" CLU + SG_ SCR_NO_REMAINING_RESTARTS : 24|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ SCR_REMAINING_DISTANCE : 32|16@1+ (1.0,0.0) [0.0|25000.0] "km" CLU + +BO_ 1472 GW_Warning_PE: 8 BCM + SG_ Audio_VolumeDown : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Flh_Alarm : 48|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Fcnt_Alarm : 50|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Frh_Alarm : 52|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Rlh_Alarm : 56|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,PGS + SG_ Pas_Spkr_Rcnt_Alarm : 58|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Rrh_Alarm : 60|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,PGS + +BO_ 1984 CAL_SAS11: 2 ESC + SG_ CCW : 0|4@1+ (1.0,0.0) [0.0|15.0] "" SAS + SG_ SAS_CID : 4|11@1+ (1.0,0.0) [0.0|2047.0] "" SAS + +BO_ 1456 CLU12: 4 CLU + SG_ CF_Clu_Odometer : 0|24@1+ (0.1,0.0) [0.0|1677721.4] "km" _4WD,AAF,BCM,CUBIS,EMS,EPB,IBOX,LDWS_LKAS,SCC,TPMS + +BO_ 688 SAS11: 5 MDPS + SG_ SAS_Angle : 0|16@1- (0.1,0.0) [-3276.8|3276.7] "Deg" _4WD,ACU,AFLS,AVM,CLU,ECS,EMS,ESC,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SPAS,TCU,_4WD,ACU,AFLS,AVM,BCM,CLU,ECS,EMS,ESC,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SPAS,TCU + SG_ SAS_Speed : 16|8@1+ (4.0,0.0) [0.0|1016.0] "" AFLS,ECS,ESC,IBOX,LDWS_LKAS,SCC,SPAS,TCU,AFLS,ECS,ESC,IBOX,LDWS_LKAS,SCC,SPAS,TCU + SG_ SAS_Stat : 24|8@1+ (1.0,0.0) [0.0|255.0] "" ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU,ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ MsgCount : 32|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS + SG_ CheckSum : 36|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS + +BO_ 1441 ACU12: 8 ACU + SG_ CR_Acu_SN : 0|64@1+ (1.0,0.0) [0.0|0.0] "" ODS + +BO_ 1440 ACU11: 8 ACU + SG_ CF_Ods_SNRcv : 1|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Ods_IDRcv : 2|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Ods_RZReq : 4|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Abg_DepInhEnt : 6|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Abg_DepEnt : 7|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_PasBkl_FltStat : 28|1@1+ (1.0,0.0) [0.0|1.0] "" ODS,PSB + SG_ CF_DriBkl_FltStat : 29|1@1+ (1.0,0.0) [0.0|1.0] "" ODS,PSB + SG_ CF_PasBkl_Stat : 30|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,ODS,PSB,TMU + SG_ CF_DriBkl_Stat : 31|1@1+ (1.0,0.0) [0.0|1.0] "" ODS,PSB + SG_ CF_SWL_Ind : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CUBIS,IBOX + SG_ CF_Acu_FltStat : 34|2@1+ (1.0,0.0) [0.0|3.0] "" CUBIS,IBOX + SG_ CF_Acu_ExtOfSab : 36|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,CUBIS,IBOX + SG_ CF_Acu_Dtc : 40|16@1+ (1.0,0.0) [0.0|65535.0] "" CUBIS,IBOX + SG_ CF_Acu_NumOfFlt : 56|8@1+ (1.0,0.0) [0.0|255.0] "" CUBIS,IBOX + +BO_ 1437 AHLS11: 8 AHLS + SG_ CF_Ahls_WarnLamp : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Ahls_WarnMsg : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1434 PSB11: 2 PSB + SG_ PSB_LH_FAIL : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ PSB_LH_TGL : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ PSB_LH_ACT : 3|4@1+ (1.0,0.0) [0.0|4.0] "" Dummy + SG_ PSB_RH_FAIL : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ PSB_RH_TGL : 10|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ PSB_RH_ACT : 11|4@1+ (1.0,0.0) [0.0|4.0] "" Dummy + +BO_ 916 TCS13: 8 ESC + SG_ aBasis : 0|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" EMS,SCC + SG_ BrakeLight : 11|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,SCC + SG_ DCEnable : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ AliveCounterTCS : 13|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,SCC + SG_ ACCReqLim : 22|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,SCC + SG_ TQI_ACC : 24|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS + SG_ ACCEL_REF_ACC : 32|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" EMS,SCC + SG_ ACCEnable : 43|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,SCC + SG_ DriverOverride : 45|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,SCC + SG_ StandStill : 47|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ CheckSum_TCS3 : 48|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,SCC + SG_ ACC_EQUIP : 52|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ PBRAKE_ACT : 53|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ ACC_REQ : 54|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ DriverBraking : 55|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ CF_VSM_Coded : 56|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + SG_ CF_VSM_Avail : 57|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,SCC + SG_ CF_VSM_Handshake : 59|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + SG_ CF_DriBkeStat : 60|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + SG_ CF_VSM_ConfSwi : 61|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ AEB_EQUIP : 63|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + +BO_ 1427 TPMS11: 6 BCM + SG_ TPMS_W_LAMP : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,HUD,IBOX,CLU,CUBIS,HUD,IBOX + SG_ TREAD_W_LAMP : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,HUD,IBOX,CLU,CUBIS,HUD,IBOX + SG_ POS_FL_W_LAMP : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ POS_FR_W_LAMP : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ POS_RL_W_LAMP : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ POS_RR_W_LAMP : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ STATUS_TPMS : 8|3@1+ (1.0,0.0) [0.0|0.0] "" CLU + SG_ UNIT : 11|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ PRESSURE_FL : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ PRESSURE_FR : 24|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ PRESSURE_RL : 32|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ PRESSURE_RR : 40|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + +BO_ 915 TCS12: 4 ESC + SG_ SA_COUNT : 0|16@1+ (2.0,-32768.0) [-32768.0|98302.0] "" _4WD,ACU,MDPS + SG_ SA_Z_COUNT : 16|15@1+ (2.0,-32768.0) [-32768.0|32766.0] "" _4WD,ACU,MDPS + SG_ SA_Z_FLAG : 31|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,MDPS + +BO_ 1170 EMS19: 8 EMS + SG_ CF_Ems_BrkReq : 0|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX,TCU + SG_ CF_Ems_DnShftReq : 1|4@1+ (1.0,0.0) [0.0|14.0] "" IBOX,TCU + SG_ CF_Ems_RepModChk : 5|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX + SG_ CF_Ems_AAFOpenReq : 7|1@1+ (1.0,0.0) [0.0|1.0] "" AAF,IBOX + SG_ CF_Ems_DecelReq : 8|12@1+ (0.0010,-4.094) [-4.094|0.0] "m/s^2" ESC,IBOX,TCU + SG_ CR_Ems_BstPre : 20|12@1+ (1.322,0.0) [0.0|4094.0] "hPa" CLU,IBOX + SG_ CR_Ems_EngOilTemp : 32|8@1+ (0.75,-40.0) [0.0|254.0] "deg" CLU,IBOX + SG_ DPF_LAMP_STAT : 40|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX + SG_ BAT_LAMP_STAT : 42|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_ModeledAmbTemp : 48|8@1+ (0.5,-41.0) [-41.0|85.5] "deg" AAF,IBOX + SG_ CF_Ems_OPSFail : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_AliveCounterEMS9 : 58|2@1+ (1.0,0.0) [0.0|3.0] "" AAF,ABS,CUBIS,ECS,EPB,IBOX,MDPS,REA,SCC,SMK,TCU + SG_ CF_Ems_ChecksumEMS9 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" AAF,ABS,CUBIS,ECS,EPB,IBOX,MDPS,REA,SCC,SMK,TCU + +BO_ 1425 AFLS11: 2 AFLS + SG_ AFLS_STAT : 1|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Afls_TrfChgStat : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Afls_LedHLStat : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 912 SPAS11: 7 SPAS + SG_ CF_Spas_Stat : 0|4@1+ (1.0,0.0) [0.0|15.0] "" ESC,MDPS + SG_ CF_Spas_TestMode : 4|2@1+ (1.0,0.0) [0.0|3.0] "" MDPS + SG_ CR_Spas_StrAngCmd : 8|16@1- (0.1,0.0) [-3276.8|3276.7] "" MDPS + SG_ CF_Spas_BeepAlarm : 24|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Spas_Mode_Seq : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_AliveCnt : 32|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Spas_Chksum : 40|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Spas_PasVol : 48|3@1+ (1.0,0.0) [0.0|7.0] "" CGW,CLU + +BO_ 1168 EPB11: 7 EPB + SG_ EPB_I_LAMP : 0|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU,CUBIS,ESC,IBOX + SG_ EPB_F_LAMP : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,ESC,IBOX + SG_ EPB_ALARM : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC + SG_ EPB_CLU : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,ESC + SG_ EPB_SWITCH : 16|2@1+ (1.0,0.0) [0.0|3.0] "" ESC,SCC + SG_ EPB_RBL : 18|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,ESC + SG_ EPB_STATUS : 19|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EMS,ESC,SCC,TCU + SG_ EPB_FRC_ERR : 22|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,SCC,TCU + SG_ EPB_DBF_STAT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ ESP_ACK : 25|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ EPB_DBF_REQ : 26|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ EPB_FAIL : 29|3@1+ (1.0,0.0) [0.0|7.0] "" ESC,SCC + SG_ EPB_FORCE : 32|12@1+ (1.0,-1000.0) [-1000.0|3000.0] "" ESC + SG_ EPB_DBF_DECEL : 48|8@1+ (0.01,0.0) [0.0|2.54] "g" ESC + +BO_ 399 EMS_H12: 8 EMS + SG_ R_TqAcnApvC : 0|8@1+ (0.2,0.0) [0.0|51.0] "Nm" DATC,IBOX + SG_ R_PAcnC : 8|8@1+ (125.0,0.0) [0.0|31875.0] "hPa" DATC,IBOX + SG_ TQI_B : 16|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ABS,ESC,IBOX + SG_ SLD_VS : 24|8@1+ (1.0,0.0) [0.0|255.0] "km/h" CLU,IBOX + SG_ CF_CdaStat : 32|3@1+ (1.0,0.0) [0.0|7.0] "" AEMC,IBOX,TCU + SG_ CF_Ems_IsgStat : 35|3@1+ (1.0,0.0) [0.0|7.0] "" ABS,BCM,CLU,DATC,EPB,ESC,IBOX,LDWS_LKAS,MDPS,SMK,TCU + SG_ CF_Ems_OilChg : 38|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_EtcLimpMod : 39|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ R_NEngIdlTgC : 40|8@1+ (10.0,0.0) [0.0|2550.0] "rpm" DATC,IBOX,TCU + SG_ CF_Ems_UpTarGr : 48|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_DownTarGr : 49|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_DesCurGr : 50|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,IBOX + SG_ CF_Ems_SldAct : 54|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_SldPosAct : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_HPresStat : 56|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ CF_Ems_IsgBuz : 57|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_IdlStpFCO : 58|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_FCopen : 59|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_ActEcoAct : 60|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,TCU + SG_ CF_Ems_EngRunNorm : 61|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC,IBOX,TCU + SG_ CF_Ems_IsgStat2 : 62|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX,TCU + +BO_ 1419 LCA11: 8 LCA + SG_ CF_Lca_Stat : 0|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Rcta_Stat : 4|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Lca_IndLeft : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Rcw_Stat : 10|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_RCW_Warning : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Lca_IndRight : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Lca_SndWan_Stat : 18|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_FR_SndWan : 20|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_FL_SndWan : 21|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_RR_SndWan : 22|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_RL_SndWan : 23|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_Lca_IndBriLeft : 24|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_Lca_IndBriRight : 32|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_RCTA_IndBriLeft : 40|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_RCTA_IndBriRight : 48|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_RCTA_IndLeft : 56|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_RCTA_IndRight : 58|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_SndWarnForClu : 60|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 906 ABS11: 8 ABS + SG_ ABS_DEF : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,EMS,SPAS,TCU + SG_ EBD_DEF : 1|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,SPAS,TCU + SG_ ABS_ACT : 2|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,EPB,SPAS,TCU + SG_ ABS_W_LAMP : 3|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,CUBIS,MTS,TMU + SG_ EBD_W_LAMP : 4|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ ABS_DIAG : 5|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ ESS_STAT : 6|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,BCM,CLU,EMS + +BO_ 903 WHL_PUL11: 6 ABS + SG_ WHL_PUL_FL : 0|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_PUL_FR : 8|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_PUL_RL : 16|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_PUL_RR : 24|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_DIR_FL : 32|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_DIR_FR : 34|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_DIR_RL : 36|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_DIR_RR : 38|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_PUL_Chksum : 40|8@1+ (1.0,0.0) [0.0|255.0] "" EPB,SPAS,TPMS,EPB,LCA,LDWS_LKAS,SPAS,TPMS + +BO_ 1415 TMU11: 8 IBOX + SG_ CF_Tmu_VehSld : 0|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Tmu_VehImmo : 1|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Tmu_ReqRepCnd : 2|2@1+ (1.0,0.0) [0.0|3.0] "" EMS + SG_ CF_Tmu_AirconCtr : 4|1@1+ (1.0,0.0) [0.0|1.0] "" DATC + SG_ CF_Tmu_TempMd : 5|1@1+ (1.0,0.0) [0.0|1.0] "" DATC + SG_ CF_Tmu_TempSet : 6|16@1+ (1.0,0.0) [0.0|20.0] "" DATC + SG_ CF_Tmu_DefrostCtr : 22|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,FATC + SG_ CF_Tmu_AliveCnt1 : 56|4@1+ (1.0,0.0) [0.0|15.0] "" EMS + +BO_ 902 WHL_SPD11: 8 ABS + SG_ WHL_SPD_FL : 0|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,AFLS,AHLS,AVM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_FR : 16|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,ACU,AFLS,AHLS,AVM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_RL : 32|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,AFLS,AHLS,AVM,BCM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,BCM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_RR : 48|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,AFLS,AHLS,AVM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_AliveCounter_LSB : 14|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ WHL_SPD_AliveCounter_MSB : 30|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ WHL_SPD_Checksum_LSB : 46|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ WHL_SPD_Checksum_MSB : 62|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + +BO_ 1414 EVP11: 3 EVP + SG_ CF_Evp_Stat : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 1412 AAF11: 8 AAF + SG_ CF_Aaf_ActFlapStatus : 0|2@1+ (1.0,0.0) [0.0|3.0] "" AAF_Tester + SG_ CF_Aaf_ModeStatus : 2|3@1+ (1.0,0.0) [0.0|7.0] "" AAF_Tester + SG_ CF_Aaf_WrnLamp : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Aaf_ErrStatus : 6|10@1+ (1.0,0.0) [0.0|1023.0] "" AAF_Tester,EMS + SG_ CF_Aaf_OpenRqSysAct : 16|8@1+ (1.0,0.0) [0.0|255.0] "" AAF_Tester + SG_ CF_Aaf_PStatus : 24|8@1+ (1.0,0.0) [0.0|100.0] "%" AAF_Tester + SG_ CF_Aaf_OpenRqSysSol : 32|8@1+ (1.0,0.0) [0.0|255.0] "" AAF_Tester + SG_ CF_Aaf_SolFlapStatus : 40|2@1+ (1.0,0.0) [0.0|3.0] "" AAF_Tester + SG_ CF_Aaf_MilOnReq : 42|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 900 EMS17: 8 EMS + SG_ CF_Ems_PkpCurMSV : 0|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_HolCurMSV : 8|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_InjVBnkAct : 16|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_InjVActSet : 24|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_DiagFulHDEV : 32|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CF_Ems_SwiOffIC1 : 33|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CF_Ems_SwiOffIC2 : 34|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CF_Ems_DiagReqHDEV : 38|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CR_Ems_DutyCycMSV : 40|8@1+ (0.3921568627,0.0) [0.0|100.0] "%" DI_BOX + SG_ CR_Ems_BatVolRly : 48|8@1+ (0.1,0.0) [0.0|25.5] "V" DI_BOX + +BO_ 387 REA11: 8 REA + SG_ CF_EndBst_PwmDuH : 0|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PwmDuL : 1|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PwmFqOutRng : 2|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_HbriOverCur : 3|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_HbriOverTemp : 4|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PosSnsKOR : 6|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PosSnsOSOR : 7|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_EepFlt : 8|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_RomFlt : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_RamFlt : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_CanFlt : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_AgH : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_AgL : 13|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_ORVol : 14|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CR_EndBst_ActPos : 16|16@1+ (0.117,0.0) [1.989|118.053] "" EMS + SG_ CR_EndBst_DemPos : 32|16@1+ (0.117,0.0) [0.0|119.691] "" EMS + SG_ CR_EndBst_HbriPwr : 48|16@1+ (0.045,0.0) [0.0|99.99] "%" EMS + +BO_ 1411 CUBIS11: 8 CUBIS + SG_ CF_Cubis_HUDisp : 0|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + +BO_ 899 FATC11: 8 DATC + SG_ CR_Fatc_TqAcnOut : 0|8@1+ (0.2,0.0) [0.0|50.8] "Nm" EMS,IBOX + SG_ CF_Fatc_AcnRqSwi : 8|1@1+ (1.0,0.0) [0.0|1.0] "" AAF,EMS,IBOX + SG_ CF_Fatc_AcnCltEnRq : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_EcvFlt : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_BlwrOn : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_FATC_Iden : 12|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Fatc_BlwrMax : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX + SG_ CF_Fatc_EngStartReq : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_IsgStopReq : 16|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_CtrInf : 17|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,IBOX + SG_ CF_Fatc_MsgCnt : 20|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,IBOX + SG_ CR_Fatc_OutTemp : 24|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" BCM,CLU,EMS,IBOX,SPAS,TCU,TPMS + SG_ CR_Fatc_OutTempSns : 32|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" AAF,AHLS,CLU,EMS,IBOX,SPAS,TCU + SG_ CF_Fatc_Compload : 40|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,IBOX + SG_ CF_Fatc_ActiveEco : 43|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Fatc_AutoActivation : 44|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX + SG_ CF_Fatc_DefSw : 45|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,IBOX + SG_ CF_Fatc_PtcRlyStat : 46|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_ChkSum : 56|8@1+ (1.0,0.0) [0.0|255.0] "" EMS,IBOX,SPAS + +BO_ 129 EMS_DCT12: 8 EMS + SG_ CR_Ems_SoakTimeExt : 0|6@1+ (5.0,0.0) [0.0|315.0] "Min" TCU + SG_ BRAKE_ACT : 6|2@1+ (1.0,0.0) [0.0|3.0] "" TCU + SG_ CF_Ems_EngOperStat : 8|8@1+ (1.0,0.0) [0.0|255.0] "" TCU + SG_ CR_Ems_IndAirTemp : 16|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" TCU + SG_ CF_Ems_Alive2 : 56|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Ems_ChkSum2 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + +BO_ 897 MDPS11: 8 MDPS + SG_ CF_Mdps_WLmp : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,EMS,IBOX,SPAS + SG_ CF_Mdps_Flex : 2|3@1+ (1.0,0.0) [0.0|3.0] "" CLU,LDWS_LKAS + SG_ CF_Mdps_FlexDisp : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Mdps_Stat : 7|4@1+ (1.0,0.0) [0.0|15.0] "" SPAS + SG_ CR_Mdps_DrvTq : 11|12@1+ (0.01,-20.48) [-20.48|20.46] "" SPAS + SG_ CF_Mdps_ALTRequest : 23|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CR_Mdps_StrAng : 24|16@1- (0.1,0.0) [-3276.8|3276.7] "Deg" SPAS + SG_ CF_Mdps_AliveCnt : 40|8@1+ (1.0,0.0) [0.0|255.0] "" LDWS_LKAS,SPAS + SG_ CF_Mdps_Chksum : 48|8@1+ (1.0,0.0) [0.0|255.0] "" LDWS_LKAS,SPAS + SG_ CF_Mdps_SPAS_FUNC : 57|1@1+ (1.0,0.0) [0.0|1.0] "flag" SPAS + SG_ CF_Mdps_LKAS_FUNC : 58|1@1+ (1.0,0.0) [0.0|1.0] "flag" LDWS_LKAS + SG_ CF_Mdps_CurrMode : 59|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Mdps_Type : 61|2@1+ (1.0,0.0) [0.0|2.0] "" LDWS_LKAS,SPAS + +BO_ 896 DI_BOX13: 8 DI_BOX + SG_ CF_DiBox_HPreInjVConfStat : 0|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVStat1 : 8|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVStat2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVPkp : 24|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVBpt : 32|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_ErrRegFrtMSV : 40|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_ErrRegSedMSV : 48|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SPIErrSedMSV : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_SPIErrFrtMSV : 57|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_IDErrSedMSV : 58|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_IDErrFrtMSV : 59|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_IniStatMSV : 60|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 640 EMS13: 8 EMS + SG_ LV_FUEL_TYPE_ECU : 0|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,LPI,SMK + SG_ LV_BFS_CFIRM : 1|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_CRASH : 2|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_VB_OFF_ACT : 3|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_GSL_MAP M : 4|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_ENG_TURN : 5|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ ERR_FUEL : 8|8@1+ (1.0,0.0) [0.0|255.0] "" LPI + SG_ EOS : 16|8@1+ (1.0,0.0) [0.0|255.0] "" LPI + SG_ TCO : 24|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" LPI + SG_ N_32 : 32|8@1+ (32.0,0.0) [0.0|8160.0] "rpm" LPI + SG_ MAF : 40|8@1+ (5.447,0.0) [0.0|1388.985] "mg/TDC" LPI + SG_ TIA : 48|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" LPI + SG_ MAP m1 : 56|8@1+ (0.47058,0.0) [0.0|119.9979] "kPa" LPI + SG_ AMP m0 : 56|8@1+ (21.22,0.0) [0.0|5411.1] "hPa" LPI + +BO_ 128 EMS_DCT11: 8 EMS + SG_ PV_AV_CAN : 0|8@1+ (0.3906,0.0) [0.0|99.603] "%" TCU + SG_ TQ_STND : 8|6@1+ (10.0,0.0) [0.0|630.0] "Nm" TCU + SG_ F_N_ENG : 14|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ F_SUB_TQI : 15|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ N : 16|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" TCU + SG_ TQI_ACOR : 32|8@1+ (0.390625,0.0) [0.0|99.6094] "%" IBOX,TCU + SG_ TQFR : 40|8@1+ (0.390625,0.0) [0.0|99.6094] "%" TCU + SG_ TQI : 48|8@1+ (0.390625,0.0) [0.0|99.609375] "%" TCU + SG_ CF_Ems_Alive : 56|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Ems_ChkSum : 60|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + +BO_ 1407 HU_MON_PE_01: 8 CLU + SG_ HU_Type : 0|8@1+ (1.0,0.0) [0.0|255.0] "" AVM,PGS + +BO_ 127 CGW5: 8 BCM + SG_ C_StopLampLhOpenSts : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_StopLampRhOpenSts : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HMSLOpenSts : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampLowLhOpenSts : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampLowRhOpenSts : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampHighLhOpenSts : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampHighRhOpenSts : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_DRLLampLhOpenSts : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_DRLLampRhOpenSts : 8|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearFOGLhOpenSts : 9|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearFOGRhOpenSts : 10|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontFOGLhOpenSts : 11|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontFOGRhOpenSts : 12|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearEXTTailLhOpenSts : 13|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearEXTTailRhOpenSts : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontEXTTailLhOpenSts : 15|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontEXTTailRhOpenSts : 16|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearTSIGLhOpenSts : 17|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearTSIGRhOpenSts : 18|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontTSIGLhOpenSts : 19|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontTSIGRhOpenSts : 20|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_SBendingLhOpenSts : 21|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_SBendingRhOpenSts : 22|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_LicensePlateLhOpenSts : 23|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_LicensePlateRhOpenSts : 24|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 1151 ESP11: 6 ESC + SG_ AVH_STAT : 0|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EPB,TCU + SG_ LDM_STAT : 2|1@1+ (1.0,0.0) [0.0|1.0] "" EPB,TCU + SG_ REQ_EPB_ACT : 3|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,TCU + SG_ REQ_EPB_STAT : 5|1@1+ (1.0,0.0) [0.0|1.0] "" EPB + SG_ ECD_ACT : 6|1@1+ (1.0,0.0) [0.0|1.0] "" EPB + SG_ _4WD_LIM_REQ : 7|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS + SG_ ROL_CNT_ESP : 8|8@1+ (1.0,0.0) [0.0|255.0] "" EPB,TCU + SG_ _4WD_TQC_LIM : 16|16@1+ (1.0,0.0) [0.0|65535.0] "Nm" _4WD,EMS + SG_ _4WD_CLU_LIM : 32|8@1+ (0.390625,0.0) [0.0|99.609375] "%" _4WD,EMS + SG_ _4WD_OPEN : 40|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,EMS + SG_ _4WD_LIM_MODE : 42|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD + +BO_ 1397 HU_AVM_E_00: 8 CLU + SG_ HU_AVM_Cal_Cmd : 0|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_Cal_Method : 4|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + SG_ HU_AVM_Save_Controlpoint : 6|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + SG_ HU_AVM_PT_X : 8|12@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_RearViewPointOpt : 20|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_PT_Y : 24|12@1+ (1.0,0.0) [0.0|4095.0] "" AVM,PGS + SG_ HU_AVM_FrontViewPointOpt : 36|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_SelectedMenu : 40|5@1+ (1.0,0.0) [0.0|31.0] "" AVM,PGS + SG_ HU_AVM_CameraOff : 45|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + SG_ HU_AVM_Option : 48|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_CrossLineMove_Cmd : 52|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_RearView_Option : 56|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_FrontView_Option : 60|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + +BO_ 1395 HU_AVM_E_01: 8 CLU + SG_ HU_PGSSelectedMenu : 0|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_PGSOption : 8|5@1+ (1.0,0.0) [0.0|31.0] "" AVM,PGS + SG_ HU_AVM_ParkingAssistMenu : 56|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_ParkingAssistSB : 60|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + +BO_ 1393 OPI11: 5 OPI + SG_ CR_Opi_Spd_Rpm : 0|8@1+ (20.0,0.0) [0.0|3500.0] "rpm" TCU + SG_ CF_Opi_Over_Temp : 8|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Opi_Over_Cur : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,TCU + SG_ CF_Opi_Over_Vol : 10|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Opi_Hall_Fail : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,TCU + SG_ CF_Opi_Flt : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,TCU + SG_ CF_Opi_Motor_Dir : 15|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Opi_Romver : 16|8@1+ (1.0,0.0) [0.0|255.0] "" TCU + SG_ CF_Opi_PWM_Rate : 24|12@1+ (1.0,0.0) [0.0|100.0] "%" TCU + +BO_ 625 LPI11: 8 LPI + SG_ FUP_LPG_MMV : 0|8@1+ (128.0,0.0) [0.0|32640.0] "hPa" EMS + SG_ LV_FUEL_TYPE_BOX : 8|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_BFS_IN_PROGRESS : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_GAS_OK : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_FUP_ENA_THD : 11|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,EMS,SMK + SG_ LPI_OBD : 12|4@1+ (1.0,0.0) [0.0|15.0] "" EMS + SG_ ERR_GAS : 16|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ FAC_TI_GAS_COR : 24|16@1+ (3.05E-5,0.0) [0.0|1.9988175] "" EMS + SG_ FTL_AFU : 40|8@1+ (0.392,0.0) [0.0|99.96] "%" EMS + SG_ BFS_CYL : 48|8@1+ (1.0,0.0) [0.0|6.0] "Cyl Nr." EMS + SG_ LV_PRE_CDN_LEAK : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_CONF_INJECTION_DELAY : 57|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_LPG_SW_DRIVER_REQ : 58|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 356 VSM11: 4 ESC + SG_ CR_Esc_StrTqReq : 0|12@1+ (0.01,-20.48) [-20.48|20.47] "Nm" MDPS + SG_ CF_Esc_Act : 12|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS,MDPS + SG_ CF_Esc_CtrMode : 13|3@1+ (1.0,0.0) [0.0|7.0] "" MDPS + SG_ CF_Esc_Def : 16|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Esc_AliveCnt : 17|4@1+ (1.0,0.0) [0.0|15.0] "" LDWS_LKAS,MDPS + SG_ CF_Esc_Chksum : 24|8@1+ (1.0,0.0) [0.0|255.0] "" LDWS_LKAS,MDPS + +BO_ 1379 PGS_HU_PE_01: 8 PGS + SG_ PGS_State : 0|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ PGS_ParkGuideState : 8|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ PGS_Option : 16|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ PGS_Version : 32|16@1+ (1.0,0.0) [0.0|65535.0] "" CLU + +BO_ 354 TCU_DCT13: 3 TCU + SG_ Clutch_Driving_Tq : 0|10@1+ (1.0,-512.0) [0.0|0.0] "Nm" ESC + SG_ Cluster_Engine_RPM : 10|13@1+ (0.9766,0.0) [0.0|0.0] "" CLU + SG_ Cluster_Engine_RPM_Flag : 23|1@1+ (1.0,0.0) [0.0|0.0] "" CLU + +BO_ 1378 HUD11: 4 HUD + SG_ CF_Hud_HeightStaus : 0|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ CF_Hud_PBackStatus : 6|2@1+ (1.0,0.0) [0.0|0.0] "" BCM,CLU + SG_ CF_Hud_Brightness : 8|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + +BO_ 608 EMS16: 8 EMS + SG_ TQI_MIN : 0|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ESC,IBOX,TCU + SG_ TQI : 8|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ESC,IBOX,TCU + SG_ TQI_TARGET : 16|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EPB,ESC,IBOX,TCU + SG_ GLOW_STAT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,IBOX,SMK + SG_ CRUISE_LAMP_M : 25|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,TCU + SG_ CRUISE_LAMP_S : 26|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,TCU + SG_ PRE_FUEL_CUT_IN : 27|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ ENG_STAT : 28|3@1+ (1.0,0.0) [0.0|7.0] "" ABS,AHLS,AVM,BCM,CLU,EPB,ESC,EVP,FPCM,IBOX,LCA,LDWS_LKAS,MDPS,SCC,SMK,TCU + SG_ SOAK_TIME_ERROR : 31|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,EPB,IBOX,TCU + SG_ SOAK_TIME : 32|8@1+ (1.0,0.0) [0.0|255.0] "Min" _4WD,DATC,EPB,IBOX,TCU + SG_ TQI_MAX : 40|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ESC,IBOX,TCU + SG_ SPK_TIME_CUR : 48|8@1+ (0.375,-35.625) [-35.625|60.0] "" IBOX,TCU + SG_ Checksum : 56|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,IBOX,LDWS_LKAS,MDPS,SCC + SG_ AliveCounter : 60|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX,LDWS_LKAS,MDPS,SCC + SG_ CF_Ems_AclAct : 62|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX,SCC + +BO_ 1371 AVM_HU_PE_00: 8 AVM + SG_ AVM_View : 0|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ AVM_ParkingAssist_BtnSts : 5|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ AVM_Display_Message : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ AVM_Popup_Msg : 16|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_Ready : 20|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_ParkingAssist_Step : 24|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_FrontBtn_Type : 28|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_Option : 32|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_HU_FrontViewPointOpt : 36|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_HU_RearView_Option : 40|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_HU_FrontView_Option : 44|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_Version : 48|16@1+ (1.0,0.0) [0.0|65535.0] "" CLU + +BO_ 1370 HU_AVM_PE_00: 8 CLU + SG_ HU_AVM_Status : 0|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + +BO_ 1369 CGW4: 8 BCM + SG_ CF_Gway_MemoryP1Cmd : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_MemoryP2Cmd : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBackP1Cmd : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBackP2Cmd : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_StrgWhlHeatedState : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBackStopCmd : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,HUD + SG_ CF_Gway_StaticBendLhAct : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_StaticBendRhAct : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_DrvWdwStat : 8|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_RLWdwState : 9|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_RRWdwState : 10|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_AstWdwStat : 11|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_MemoryEnable : 12|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBACKStopCmd : 13|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBACKStop : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,HUD + SG_ CF_Gway_IMSBuzzer : 15|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_DrvSeatBeltInd : 36|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_AstSeatBeltInd : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RCSeatBeltInd : 40|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RLSeatBeltInd : 42|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RRSeatBeltInd : 44|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RrWiperHighSw : 46|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_RrWiperLowSw : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 1367 EngFrzFrm12: 8 EMS + SG_ PID_06h : 0|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_07h : 8|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_08h : 16|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_09h : 24|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_0Bh : 32|8@1+ (1.0,0.0) [0.0|255.0] "kPa" AAF,IBOX,TCU + SG_ PID_23h : 40|16@1+ (10.0,0.0) [0.0|655350.0] "kPa" AAF,IBOX,TCU + +BO_ 1366 EngFrzFrm11: 8 EMS + SG_ PID_04h : 0|8@1+ (0.3921568627,0.0) [0.0|100.0] "%" AAF,TCU + SG_ PID_05h : 8|8@1+ (1.0,-40.0) [-40.0|215.0] "deg" AAF,TCU + SG_ PID_0Ch : 16|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" AAF,TCU + SG_ PID_0Dh : 32|8@1+ (1.0,0.0) [0.0|255.0] "km/h" AAF,TCU + SG_ PID_11h : 40|8@1+ (0.3921568627,0.0) [0.0|100.0] "%" AAF,TCU + SG_ PID_03h : 48|16@1+ (1.0,0.0) [0.0|65535.0] "" AAF,TCU + +BO_ 1365 FPCM11: 8 FPCM + SG_ CR_Fpcm_LPActPre : 0|8@1+ (3.137254902,0.0) [0.0|800.0] "kPa" EMS + SG_ CF_Fpcm_LPPumpOverCur : 8|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrHi : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrDisc : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrShort : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_LPPumpDiscShort : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_LP_System_Error : 13|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrSigErr : 14|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_LPCtrCirFlt : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 852 LVR11: 7 LVR + SG_ CF_Lvr_GearInf : 0|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,TCU + SG_ CF_Lvr_PRelStat : 4|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,SMK,TCU + SG_ CF_Lvr_BkeAct : 5|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Lvr_NFnStat : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Lvr_PosInf : 8|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_PosCpl : 12|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_UlkButStat : 18|2@1+ (1.0,0.0) [0.0|3.0] "" TCU + SG_ CF_Lvr_PNStat : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lvr_ShtLkStat : 24|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_ShfErrInf : 28|20@1+ (1.0,0.0) [0.0|8191.0] "" CLU,TCU + SG_ CF_Lvr_AC : 48|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_CS : 52|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + +BO_ 1363 CGW2: 8 BCM + SG_ CF_Gway_GwayDiagState : 0|1@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_DDMDiagState : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SCMDiagState : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_PSMDiagState : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SJBDiagState : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_IPMDiagState : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_LDMFail : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,LDWS_LKAS,LDWS_LKAS + SG_ CF_Gway_CLUSwGuiCtrl : 10|3@1+ (1.0,0.0) [0.0|63.0] "" CLU,Dummy + SG_ CF_Gway_CLUSwGroup : 13|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_CLUSwMode : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_CLUSwEnter : 15|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_AutoLightValue : 16|1@1+ (1.0,0.0) [0.0|1.0] "" LCA,LCA + SG_ CF_Gway_BrakeFluidSw : 17|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_DrvSeatBeltInd : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_AvTail : 20|1@1+ (1.0,0.0) [0.0|3.0] "" CLU,SNV,SNV + SG_ CF_Gway_RearFogAct : 21|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ExtTailAct : 22|1@1+ (1.0,0.0) [0.0|1.0] "" AVM,CLU,LCA,PGS,SPAS,AVM,LCA,PGS,SPAS + SG_ CF_Gway_RRDrSw : 23|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_RLDrSw : 24|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_IntTailAct : 25|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_CountryCfg : 26|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,Dummy + SG_ CF_Gway_WiperParkPosition : 32|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,EMS,LDWS_LKAS,AFLS,EMS,LDWS_LKAS + SG_ CF_Gway_HLLowLHFail : 33|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS,SNV,LDWS_LKAS,SNV + SG_ CF_Gway_HLLowRHFail : 34|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS,SNV,LDWS_LKAS,SNV + SG_ CF_Gway_ESCLFailWarn : 35|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ESCLNotLockedWarn : 36|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ESCLNotUnlockWarn : 37|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_IDoutWarn : 38|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ImmoLp : 40|1@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_BCMRKEID : 41|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + SG_ CF_Gway_VehicleNotPWarn : 44|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_DeactivationWarn : 45|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_KeyBATDischargeWarn : 46|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SSBWarn : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SMKFobID : 48|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + SG_ CF_Gway_SMKRKECmd : 51|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + SG_ CF_Gway_AutoLightOption : 54|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_SJBDeliveryMode : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_KeyoutLp : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SMKDispWarn : 57|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,Dummy + SG_ CF_Gway_WngBuz : 61|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + +BO_ 339 TCS11: 8 ESC + SG_ TCS_REQ : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,TCU + SG_ MSR_C_REQ : 1|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,EPB,SCC,TCU + SG_ TCS_PAS : 2|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,SCC,SPAS,TCU + SG_ TCS_GSC : 3|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,TCU + SG_ CF_Esc_LimoInfo : 4|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,SCC + SG_ ABS_DIAG : 6|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB + SG_ ABS_DEF : 7|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,SCC,SPAS,TCU + SG_ TCS_DEF : 8|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,SCC,SPAS,TCU + SG_ TCS_CTL : 9|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,SCC,SPAS,TCU + SG_ ABS_ACT : 10|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,LDWS_LKAS,SCC,SPAS,TCU + SG_ EBD_DEF : 11|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,SPAS,TCU + SG_ ESP_PAS : 12|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,CLU,EMS,EPB,LDWS_LKAS,SCC,TCU + SG_ ESP_DEF : 13|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,LDWS_LKAS,SCC,TCU + SG_ ESP_CTL : 14|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,LDWS_LKAS,SCC,SPAS,TCU + SG_ TCS_MFRN : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,EPB,TCU + SG_ DBC_CTL : 16|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB + SG_ DBC_PAS : 17|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB + SG_ DBC_DEF : 18|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB + SG_ HAC_CTL : 19|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB,TCU + SG_ HAC_PAS : 20|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB,TCU + SG_ HAC_DEF : 21|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB,TCU + SG_ ESS_STAT : 22|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,BCM,CLU,EMS,EPB + SG_ TQI_TCS : 24|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,EPB,TCU + SG_ TQI_MSR : 32|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,EPB,TCU + SG_ TQI_SLW_TCS : 40|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,EPB,TCU + SG_ CF_Esc_BrkCtl : 48|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ BLA_CTL : 49|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CGW,CLU + SG_ AliveCounter_TCS1 : 52|4@1+ (1.0,0.0) [0.0|14.0] "" EMS,EPB,LDWS_LKAS + SG_ CheckSum_TCS1 : 56|8@1+ (1.0,0.0) [0.0|255.0] "" EMS,EPB,LDWS_LKAS + +BO_ 1362 SNV11: 4 SNV + SG_ CF_SNV_DisplayControl : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,HUD + SG_ CF_Snv_BeepWarning : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,HUD + SG_ CF_Snv_WarningMessage : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,HUD + SG_ CF_Snv_DetectionEnable : 7|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,HUD + SG_ CF_Snv_PedestrianDetect : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,HUD + SG_ CF_Snv_IRLampControl : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,HUD + +BO_ 593 MDPS12: 8 MDPS + SG_ CR_Mdps_StrColTq : 0|11@1+ (0.0078125,-8.0) [-8.0|7.9921875] "Nm" LDWS_LKAS + SG_ CF_Mdps_Def : 11|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ CF_Mdps_ToiUnavail : 12|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_ToiActive : 13|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_ToiFlt : 14|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_FailStat : 15|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_MsgCount2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" ESC,LDWS_LKAS + SG_ CF_Mdps_Chksum2 : 24|8@1+ (1.0,0.0) [0.0|255.0] "" ESC,LDWS_LKAS + SG_ CF_Mdps_SErr : 37|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ CR_Mdps_StrTq : 40|12@1+ (0.01,-20.48) [-20.48|20.47] "Nm" ESC + SG_ CR_Mdps_OutTq : 52|12@1+ (0.1,-204.8) [-204.8|204.7] "" ESC,LDWS_LKAS + +BO_ 1360 IAP11: 3 IAP + SG_ CF_Iap_EcoPmodSwi : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Iap_EcoPmodAct : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Iap_ReqWarn : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1356 TCU_DCT14: 8 TCU + SG_ Vehicle_Stop_Time : 0|5@1+ (1.0,0.0) [0.0|0.0] "" CLU + SG_ HILL_HOLD_WARNING : 5|1@1+ (1.0,0.0) [0.0|0.0] "" CLU + +BO_ 1353 BAT11: 8 EMS + SG_ BAT_SNSR_I : 0|16@1+ (0.01,-327.0) [-327.0|328.0] "A" CGW,CUBIS,IBOX,TMU + SG_ BAT_SOC : 16|8@1+ (1.0,0.0) [0.0|100.0] "%" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_V : 24|14@1+ (0.0010,6.0) [6.0|18.0] "V" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_Temp : 38|9@1- (0.5,-40.0) [-40.0|125.0] "deg" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_State : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CGW,CUBIS,IBOX,TMU + SG_ BAT_SOH : 48|7@1+ (1.0,0.0) [0.0|100.0] "%" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_Invalid : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CGW,CUBIS,IBOX,TMU + SG_ BAT_SOF : 56|7@1+ (0.1,0.0) [0.0|12.0] "V" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_Error : 63|1@1+ (1.0,0.0) [0.0|1.0] "" CGW,CUBIS,IBOX,TMU + +BO_ 1351 EMS15: 8 EMS + SG_ ECGPOvrd : 0|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX,SCC + SG_ QECACC : 1|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ ECFail : 2|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ SwitchOffCondExt : 3|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ BLECFail : 4|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ CF_Ems_IsaAct : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ FA_PV_CAN : 8|8@1+ (0.3906,0.0) [0.0|99.2] "%" IBOX,LDWS_LKAS,TCU + SG_ IntAirTemp : 16|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" _4WD,ECS,EPB,IBOX,TCU + SG_ STATE_DC_OBD : 24|7@1+ (1.0,0.0) [0.0|127.0] "" IBOX,TCU + SG_ INH_DC_OBD : 31|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ CTR_IG_CYC_OBD : 32|16@1+ (1.0,0.0) [0.0|65535.0] "" ACU,IBOX,TCU + SG_ CTR_CDN_OBD : 48|16@1+ (1.0,0.0) [0.0|65535.0] "" IBOX,TCU + +BO_ 1350 DI_BOX12: 8 DI_BOX + SG_ CF_DiBox_FrtInjVDiagReg0 : 0|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_FrtInjVDiagReg1 : 8|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_FrtInjVDiagReg2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SedInjVDiagReg0 : 24|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SedInjVDiagReg1 : 32|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SedInjVDiagReg2 : 40|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CR_DiBox_BatVol : 48|8@1+ (0.1,0.0) [0.0|25.5] "V" EMS + SG_ CF_DiBox_SedInjVChg : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_FrtInjVChg : 57|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_SedInjVErrSPI : 58|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_FrtInjVErrSPI : 59|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 1349 EMS14: 8 EMS + SG_ IMMO_LAMP_STAT : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ L_MIL : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,IBOX + SG_ IM_STAT : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ AMP_CAN : 3|5@1+ (10.731613,458.98) [458.98|791.660003] "mmHg" CLU,IBOX,TCU,TPMS + SG_ BAT_Alt_FR_Duty : 8|8@1+ (0.4,0.0) [0.0|100.0] "%" CGW,CUBIS,IBOX,TMU + SG_ VB : 24|8@1+ (0.1015625,0.0) [0.0|25.8984375] "V" CLU,CUBIS,DATC,EPB,FPCM,IBOX + SG_ EMS_VS : 32|12@1+ (0.0625,0.0) [0.0|255.875] "km/h" CLU + SG_ TEMP_FUEL : 56|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" FPCM + +BO_ 68 DATC11: 8 DATC + SG_ CF_Datc_Type : 0|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_Datc_VerMaj : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_Datc_VerMin : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CR_Datc_OutTempC : 24|8@1+ (0.5,-41.0) [-41.0|86.5] "deg" CLU,FPCM + SG_ CR_Datc_OutTempF : 32|8@1+ (1.0,-42.0) [-42.0|213.0] "deg" CLU + SG_ CF_Datc_IncarTemp : 40|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" BCM,CLU + +BO_ 67 DATC13: 8 DATC + SG_ CF_Datc_TempDispUnit : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX + SG_ CF_Datc_ModDisp : 2|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_IonClean : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_ChgReqDisp : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_IntakeDisp : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_AutoDisp : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_FrDefLed : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX + SG_ CF_Datc_AutoDefogBlink : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_ClmScanDisp : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_AqsDisp : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_AcDisp : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_OpSts : 25|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Mtc_MaxAcDisp : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_DualDisp : 30|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_PwrInf : 32|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_RearManual : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearAutoDisp : 40|2@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Datc_RearOffDisp : 42|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearClimateScnDisp : 44|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearChgReqDisp : 46|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearModDisp : 48|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_RearBlwDisp : 52|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_PSModDisp : 56|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_FrontBlwDisp : 60|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,IBOX + +BO_ 66 DATC12: 8 DATC + SG_ CR_Datc_DrTempDispC : 0|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU,IBOX + SG_ CR_Datc_DrTempDispF : 8|8@1+ (1.0,56.0) [58.0|90.0] "" CLU,IBOX + SG_ CR_Datc_PsTempDispC : 16|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU,IBOX + SG_ CR_Datc_PsTempDispF : 24|8@1+ (1.0,56.0) [58.0|90.0] "" CLU,IBOX + SG_ CR_Datc_RearDrTempDispC : 40|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU + SG_ CR_Datc_RearDrTempDispF : 48|8@1+ (1.0,58.0) [58.0|90.0] "" CLU + SG_ CF_Datc_CO2_Warning : 56|8@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1345 CGW1: 8 BCM + SG_ CF_Gway_IGNSw : 0|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,ECS,EMS,EPB,ESC,IBOX,LVR,MDPS,SAS,SCC,ECS,EMS,EPB,ESC,IBOX,LVR,MDPS,SAS,SCC + SG_ CF_Gway_RKECmd : 3|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,ECS,EMS,IBOX,ECS,EMS,IBOX + SG_ CF_Gway_DrvKeyLockSw : 6|1@1+ (1.0,0.0) [0.0|1.0] "" ECS,EMS,IBOX,ECS,EMS,IBOX + SG_ CF_Gway_DrvKeyUnlockSw : 7|1@1+ (1.0,0.0) [0.0|1.0] "" ECS,EMS,IBOX,ECS,EMS,IBOX + SG_ CF_Gway_DrvDrSw : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ECS,EMS,EPB,ESC,IBOX,SCC,TCU,ECS,EMS,EPB,ESC,IBOX,SCC,TCU + SG_ CF_Gway_DrvSeatBeltSw : 10|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EPB,ESC,IBOX,PSB,TCU,EMS,EPB,ESC,IBOX,PSB,TCU + SG_ CF_Gway_TrunkTgSw : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ECS,EMS,EPB,ESC,IBOX,ECS,EMS,EPB,ESC,IBOX + SG_ CF_Gway_AstSeatBeltSw : 14|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX,PSB,IBOX,PSB + SG_ CF_Gway_SMKOption : 16|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,EMS,IBOX,SMK + SG_ CF_Gway_HoodSw : 17|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,EPB,ESC,IBOX,EMS,EPB,ESC,IBOX + SG_ CF_Gway_TurnSigLh : 19|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,IBOX,LCA,LDWS_LKAS,SCC,EMS,IBOX,LCA,LDWS_LKAS,SCC + SG_ CF_Gway_WiperIntT : 21|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperIntSw : 24|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperLowSw : 25|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperHighSw : 26|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperAutoSw : 27|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_RainSnsState : 28|3@1+ (1.0,0.0) [0.0|7.0] "" AFLS,EMS,IBOX,LDWS_LKAS,AFLS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_HeadLampLow : 31|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,CLU,EMS,IBOX,LDWS_LKAS,SNV,AFLS,EMS,IBOX,LDWS_LKAS,SNV + SG_ CF_Gway_HeadLampHigh : 32|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,CLU,EMS,IBOX,LDWS_LKAS,AFLS,EMS,IBOX,LDWS_LKAS + SG_ CF_Gway_HazardSw : 33|2@1+ (1.0,0.0) [0.0|3.0] "" ABS,EMS,ESC,IBOX,LCA,LDWS_LKAS,ABS,EMS,ESC,IBOX,LCA,LDWS_LKAS + SG_ CF_Gway_AstDrSw : 35|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,IBOX + SG_ CF_Gway_DefoggerRly : 36|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX,EMS,IBOX + SG_ CF_Gway_ALightStat : 37|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_LightSwState : 38|2@1+ (1.0,0.0) [0.0|3.0] "" AFLS,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_Frt_Fog_Act : 40|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,CLU,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_TSigRHSw : 41|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_TSigLHSw : 42|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_DriveTypeOption : 43|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_StarterRlyState : 44|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX,EMS,IBOX,SMK + SG_ CF_Gway_PassiveAccessLock : 45|2@1+ (1.0,0.0) [0.0|7.0] "" CLU,ECS,EMS,IBOX,ECS,EMS,IBOX,SMK + SG_ CF_Gway_WiperMistSw : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS + SG_ CF_Gway_PassiveAccessUnlock : 48|2@1+ (1.0,0.0) [0.0|7.0] "" CLU,ECS,EMS,IBOX,ECS,EMS,IBOX,SMK + SG_ CF_Gway_RrSunRoofOpenState : 50|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,DATC,IBOX + SG_ CF_Gway_PassingSW : 51|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_HBAControlMode : 52|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_HLpHighSw : 53|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_InhibitRMT : 54|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EPB,ESC,IBOX,LCA,LDWS_LKAS,MDPS,PGS,SCC,SPAS,TPMS,EPB,ESC,IBOX,LCA,LDWS_LKAS,PGS,SCC,SPAS,TPMS + SG_ CF_Gway_RainSnsOption : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_SunRoofOpenState : 57|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,DATC,IBOX,DATC,IBOX + SG_ CF_Gway_Ign1 : 58|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_Ign2 : 59|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_ParkBrakeSw : 60|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC,IBOX,SCC,ESC,IBOX,SCC + SG_ CF_Gway_TurnSigRh : 62|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,IBOX,LCA,LDWS_LKAS,SCC,EMS,IBOX,LCA,LDWS_LKAS,SCC + +BO_ 64 DATC14: 8 DATC + SG_ CF_Datc_AqsLevelOut : 0|4@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_DiagMode : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CR_Datc_SelfDiagCode : 8|8@1+ (1.0,-1.0) [0.0|254.0] "" CLU + SG_ DATC_SyncDisp : 16|4@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_OffDisp : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_SmartVentDisp : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_SmartVentOnOffStatus : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_AutoDefogSysOff_Disp : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_ADSDisp : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 832 LKAS11: 8 LDWS_LKAS + SG_ CF_Lkas_LdwsSysState : 2|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,IBOX,PSB + SG_ CF_Lkas_SysWarning : 6|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Lkas_LdwsLHWarning : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,PSB + SG_ CF_Lkas_LdwsRHWarning : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,PSB + SG_ CF_Lkas_HbaLamp : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Lkas_FcwBasReq : 15|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC + SG_ CR_Lkas_StrToqReq : 16|11@1+ (0.0078125,-8.0) [-8.0|8.0] "Nm" MDPS + SG_ CF_Lkas_ActToi : 27|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Lkas_ToiFlt : 28|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Lkas_HbaSysState : 29|3@1+ (1.0,0.0) [0.0|7.0] "" BCM,CLU + SG_ CF_Lkas_FcwOpt : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lkas_HbaOpt : 34|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CGW + SG_ CF_Lkas_MsgCount : 36|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,MDPS + SG_ CF_Lkas_FcwSysState : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Lkas_FcwCollisionWarning : 43|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lkas_FusionState : 45|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Lkas_Chksum : 48|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Lkas_FcwOpt_USM : 56|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Lkas_LdwsOpt_USM : 59|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,MDPS + +BO_ 1342 LKAS12: 6 LDWS_LKAS + SG_ CF_Lkas_TsrSlifOpt : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_LkasTsrStatus : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lkas_TsrSpeed_Display_Clu : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_LkasTsrSpeed_Display_Navi : 24|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_Lkas_TsrAddinfo_Display : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1338 TMU_GW_E_01: 8 CLU + SG_ CF_Gway_TeleReqDrLock : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqDrUnlock : 2|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqHazard : 4|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqHorn : 6|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqEngineOperate : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 1078 PAS11: 4 BCM + SG_ CF_Gway_PASDisplayFLH : 0|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,AVM + SG_ CF_Gway_PASDisplayFRH : 3|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,AVM + SG_ CF_Gway_PASRsound : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASDisplayFCTR : 8|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,AVM + SG_ CF_Gway_PASDisplayRCTR : 11|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,AVM + SG_ CF_Gway_PASFsound : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASDisplayRLH : 16|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,AVM + SG_ CF_Gway_PASDisplayRRH : 19|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,AVM + SG_ CF_Gway_PASCheckSound : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASSystemOn : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASOption : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PASDistance : 28|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 48 EMS18: 6 EMS + SG_ CF_Ems_DC1NumPerMSV : 0|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_DC2NumPerMSV : 8|16@1+ (1.0,0.0) [0.0|65535.0] "" DI_BOX + SG_ CR_Ems_DutyCyc1MSV : 24|8@1+ (0.1953,0.0) [0.0|49.8] "%" DI_BOX + SG_ CR_Ems_DutyCyc2MSV : 32|8@1+ (0.13725,0.0) [0.0|35.0] "%" DI_BOX + SG_ CR_Ems_DutyCyc3MSV : 40|8@1+ (0.392,0.0) [0.0|100.0] "%" DI_BOX + +BO_ 1322 CLU15: 8 CLU + SG_ CF_Clu_VehicleSpeed : 0|8@1+ (1.0,0.0) [0.0|255.0] "" BCM + SG_ CF_Clu_InhibitP : 9|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_InhibitR : 10|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_InhibitN : 11|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_InhibitD : 12|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_HudInfoSet : 13|7@1+ (1.0,0.0) [0.0|127.0] "" HUD + SG_ CF_Clu_HudFontColorSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudBrightUpSW : 22|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudBrightDnSW : 24|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudHeightUpSW : 26|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudHeightDnSW : 28|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudSet : 30|1@1+ (1.0,0.0) [0.0|1.0] "" HUD + SG_ CF_Clu_HudFontSizeSet : 31|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_LanguageInfo : 33|5@1+ (1.0,0.0) [0.0|31.0] "" BCM,PGS + SG_ CF_Clu_ClusterSound : 38|1@1- (1.0,0.0) [0.0|0.0] "" BCM,CGW,FATC + +BO_ 1066 _4WD13: 6 _4WD + SG_ _4WD_CURRENT : 0|8@1+ (0.390625,0.0) [-50.0|50.0] "A" TCU + SG_ _4WD_POSITION : 8|16@1+ (0.015625,0.0) [-180.0|180.0] "Deg" TCU + SG_ _4WD_CLU_THERM_STR : 24|8@1+ (1.0,0.0) [0.0|100.0] "%" TCU + SG_ _4WD_STATUS : 32|8@1+ (1.0,0.0) [0.0|15.0] "" ESC,TCU + +BO_ 1065 _4WD12: 8 _4WD + SG_ Ster_Pos : 0|16@1+ (1.0,-600.0) [-600.0|600.0] "Deg" ESC + SG_ FRSS : 16|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ FLSS : 24|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ RRSS : 32|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ RLSS : 40|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ CLU_PRES : 48|16@1+ (0.0625,-50.0) [-50.0|50.0] "Bar" ESC + +BO_ 809 EMS12: 8 EMS + SG_ CONF_TCU m1 : 0|6@1+ (1.0,0.0) [0.0|63.0] "" _4WD,ACU,BCM,CLU,DATC,EPB,ESC,IBOX,LCA,SMK + SG_ CAN_VERS m0 : 0|6@1+ (1.0,0.0) [0.0|7.7] "" _4WD,ABS,ESC,IBOX + SG_ TQ_STND m3 : 0|6@1+ (10.0,0.0) [0.0|630.0] "Nm" _4WD,DATC,ECS,EPB,ESC,FATC,IBOX + SG_ OBD_FRF_ACK m2 : 0|6@1+ (1.0,0.0) [0.0|63.0] "" _4WD,ESC,IBOX + SG_ MUL_CODE M : 6|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ABS,ACU,BCM,CLU,DATC,ECS,EPB,ESC,IBOX,LCA,SMK,TCU + SG_ TEMP_ENG : 8|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" _4WD,BCM,CLU,DATC,EPB,ESC,IBOX,SMK,TCU + SG_ MAF_FAC_ALTI_MMV : 16|8@1+ (0.00781,0.0) [0.0|1.99155] "" IBOX,TCU + SG_ VB_OFF_ACT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ ACK_ES : 25|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,IBOX + SG_ CONF_MIL_FMY : 26|3@1+ (1.0,0.0) [0.0|7.0] "" ESC,IBOX,TCU + SG_ OD_OFF_REQ : 29|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ ACC_ACT : 30|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ABS,CLU,ESC,IAP,IBOX,SCC,TCU + SG_ CLU_ACK : 31|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EPB,ESC,IBOX + SG_ BRAKE_ACT : 32|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ABS,ACU,AFLS,CLU,DATC,ECS,EPB,ESC,IBOX,LDWS_LKAS,TCU + SG_ ENG_CHR : 34|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,ABS,ACU,CLU,DATC,EPB,ESC,FATC,IBOX,SCC,SMK,TCU + SG_ GP_CTL : 38|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX + SG_ TPS : 40|8@1+ (0.4694836,-15.0234742) [-15.0234742|104.6948357] "%" _4WD,ABS,ACU,CLU,DATC,ECS,EPB,ESC,IBOX,TCU + SG_ PV_AV_CAN : 48|8@1+ (0.3906,0.0) [0.0|99.603] "%" _4WD,AAF,ABS,ACU,AFLS,CLU,DATC,EPB,ESC,IAP,IBOX,LDWS_LKAS,SCC,TCU + SG_ ENG_VOL : 56|8@1+ (0.1,0.0) [0.0|25.5] "liter" _4WD,ABS,ACU,BCM,CLU,DATC,EPB,ESC,IBOX,LDWS_LKAS,SCC,SMK + +BO_ 1064 _4WD11: 8 _4WD + SG_ _4WD_TYPE : 0|2@1+ (1.0,0.0) [0.0|3.0] "" ACU,ESC,TPMS + SG_ _4WD_SUPPORT : 2|2@1+ (1.0,0.0) [0.0|3.0] "" ABS,ESC,TPMS + SG_ _4WD_ERR : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,ESC + SG_ CLU_DUTY : 16|8@1+ (1.0,0.0) [0.0|64.0] "%" ABS,ESC + SG_ R_TIRE : 24|8@1+ (1.0,200.0) [200.0|455.0] "mm" ABS,ESC,TPMS + SG_ _4WD_SW : 32|8@1+ (1.0,0.0) [0.0|9.9] "" ESC + SG_ _2H_ACT : 40|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC + SG_ _4H_ACT : 41|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,CLU,ESC,TPMS + SG_ LOW_ACT : 42|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC,TCU,TPMS + SG_ AUTO_ACT : 43|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC,TPMS + SG_ LOCK_ACT : 44|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,CLU,ESC,TPMS + SG_ _4WD_TQC_CUR : 48|16@1+ (1.0,0.0) [0.0|65535.0] "Nm" ABS,ESC + +BO_ 1319 HU_GW_E_01: 8 CLU + SG_ C_ADrLNValueSet : 0|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ C_ADrUNValueSet : 4|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ C_TwUnNValueSet : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_ABuzzerNValueSet : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_ArmWKeyNValueSet : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_PSMNValueSet : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_SCMNValueSet : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_HLEscortNValueSet : 18|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_WELNValueSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_TriTurnLNValueSet : 22|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_SNVWarnNValueSet : 24|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_LkasWarnNValueSet : 26|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 1318 HU_GW_E_00: 8 CLU + SG_ C_ADrLURValueReq : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_TwUnRValueReq : 2|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_AlarmRValueReq : 4|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_IMSRValueReq : 6|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_HLEscortRValueReq : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_WELRValueReq : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_TriTurnLRValueReq : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_SNVWarnRValueReq : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_LkasWarnRValueReq : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 1317 GW_HU_E_01: 8 BCM + SG_ C_ADrLRValue : 0|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_ADrURValue : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_TwUnRValue : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ABuzzerRValue : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ArmWKeyRValue : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_PSMRValue : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SCMRValue : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_HLEscortRValue : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_WELRValue : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TriTurnLRValue : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1316 GW_HU_E_00: 8 BCM + SG_ C_ADrLUNValueConf : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TwUnNValueConf : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_AlarmNValueConf : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_PSMNValueConf : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SCMNValueConf : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_HLEscortNValueConf : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_WELNValueConf : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TriTurnLNValueConf : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1315 GW_SWRC_PE: 8 BCM + SG_ C_ModeSW : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_MuteSW : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SeekDnSW : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SeekUpSW : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_BTPhoneCallSW : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_BTPhoneHangUpSW : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_DISCDownSW : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_DISCUpSW : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SdsSW : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_MTSSW : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_VolDnSW : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_VolUpSW : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1314 GW_IPM_PE_1: 8 BCM + SG_ C_AV_Tail : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ParkingBrakeSW : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_RKECMD : 4|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ C_BAState : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_IGNSW : 12|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_CountryCfg : 16|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_TailLampActivity : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ RearSW_RSELockOnOff : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SMKTeleCrankingState : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SMKTeleCrankingFailRes : 34|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1057 SCC12: 8 SCC + SG_ CF_VSM_Prefill : 0|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ CF_VSM_DecCmdAct : 1|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ CF_VSM_HBACmd : 2|2@1+ (1.0,0.0) [0.0|3.0] "" ESC + SG_ CF_VSM_Warn : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC,IAP + SG_ CF_VSM_Stat : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC,PSB + SG_ CF_VSM_BeltCmd : 8|3@1+ (1.0,0.0) [0.0|7.0] "" ESC,PSB + SG_ ACCFailInfo : 11|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,ESC,IBOX + SG_ ACCMode : 13|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC,IBOX,TCU + SG_ StopReq : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EPB,ESC + SG_ CR_VSM_DecCmd : 16|8@1+ (0.01,0.0) [0.0|2.55] "g" ESC + SG_ aReqMax : 24|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" EMS,ESC,TCU + SG_ TakeOverReq : 35|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,ESC,TCU + SG_ PreFill : 36|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,TCU + SG_ aReqMin : 37|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" EMS,ESC,TCU + SG_ CF_VSM_ConfMode : 48|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC + SG_ AEB_Failinfo : 50|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC + SG_ AEB_Status : 52|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC + SG_ AEB_CmdAct : 54|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ AEB_StopReq : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,ESC + SG_ CR_VSM_Alive : 56|4@1+ (1.0,0.0) [0.0|15.0] "" ESC,PSB + SG_ CR_VSM_ChkSum : 60|4@1+ (1.0,0.0) [0.0|15.0] "" ESC,PSB + +BO_ 1313 GW_DDM_PE: 8 BCM + SG_ C_DRVDoorStatus : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ASTDoorStatus : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_RLDoorStatus : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_RRDoorStatus : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TrunkStatus : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_OSMirrorStatus : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1056 SCC11: 8 SCC + SG_ MainMode_ACC : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,ESC + SG_ SCCInfoDisplay : 1|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,ESC + SG_ AliveCounterACC : 4|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,EMS,ESC,TCU + SG_ VSetDis : 8|8@1+ (1.0,0.0) [0.0|255.0] "km/h or MPH" CLU,ESC,TCU + SG_ ObjValid : 16|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,ESC,TCU + SG_ DriverAlertDisplay : 17|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC + SG_ TauGapSet : 19|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,ESC,TCU + SG_ ACC_ObjStatus : 22|2@1+ (1.0,0.0) [0.0|3.0] "" ABS,ESC + SG_ ACC_ObjLatPos : 24|9@1+ (0.1,-20.0) [-20.0|31.1] "m" ABS,ESC + SG_ ACC_ObjDist : 33|11@1+ (0.1,0.0) [0.0|204.7] "m" ABS,ESC + SG_ ACC_ObjRelSpd : 44|12@1+ (0.1,-170.0) [-170.0|239.5] "m/s" ABS,ESC + SG_ Navi_SCC_Curve_Status : 56|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Navi_SCC_Curve_Act : 58|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Navi_SCC_Camera_Act : 60|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Navi_SCC_Camera_Status : 62|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1312 CGW3: 8 BCM + SG_ CR_Photosensor_LH : 0|8@1+ (78.125,0.0) [0.0|20000.0] "" DATC,DATC + SG_ CR_Photosensor_RH : 10|8@1+ (78.125,0.0) [0.0|20000.0] "" DATC,DATC + SG_ CF_Hoodsw_memory : 22|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EMS + SG_ C_MirOutTempSns : 24|8@1+ (0.5,-40.5) [-40.0|60.0] "deg" AAF,CLU,DATC,EMS,SPAS,AAF,DATC,EMS,SPAS + +BO_ 544 ESP12: 8 ESC + SG_ LAT_ACCEL : 0|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" _4WD,ECS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,TCU + SG_ LAT_ACCEL_STAT : 11|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,IBOX,LDWS_LKAS,MDPS,PSB,SCC,TCU + SG_ LAT_ACCEL_DIAG : 12|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,IBOX,LDWS_LKAS,MDPS,PSB,SCC,TCU + SG_ LONG_ACCEL : 13|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" _4WD,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ LONG_ACCEL_STAT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ LONG_ACCEL_DIAG : 25|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ CYL_PRES : 26|12@1+ (0.1,0.0) [0.0|409.5] "Bar" _4WD,ECS,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,TCU + SG_ CYL_PRES_STAT : 38|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ECS,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,TCU + SG_ CYL_PRESS_DIAG : 39|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ECS,EMS,EPB,IBOX,PSB,SCC,TCU + SG_ YAW_RATE : 40|13@1+ (0.01,-40.95) [-40.95|40.96] "" _4WD,AFLS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,SPAS,TCU + SG_ YAW_RATE_STAT : 53|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,AFLS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,SPAS,TCU + SG_ YAW_RATE_DIAG : 54|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,AFLS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,SPAS,TCU + SG_ ESP12_AliveCounter : 56|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ ESP12_Checksum : 60|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + +BO_ 1307 CLU16: 8 CLU + SG_ CF_Clu_TirePressUnitNValueSet : 0|3@1+ (1.0,0.0) [0.0|7.0] "" TPMS + SG_ CF_Clu_SlifNValueSet : 3|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Clu_RearWiperNValueSet : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 790 EMS11: 8 EMS + SG_ SWI_IGK : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ABS,ACU,AHLS,CUBIS,DI_BOX,ECS,EPB,ESC,IBOX,LDWS_LKAS,MDPS,REA,SAS,SCC,TCU + SG_ F_N_ENG : 1|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,AFLS,CLU,CUBIS,DATC,ECS,EPB,ESC,IBOX,MDPS,SCC,TCU + SG_ ACK_TCS : 2|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ PUC_STAT : 3|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,DATC,IBOX,TCU + SG_ TQ_COR_STAT : 4|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ESC,IBOX,TCU + SG_ RLY_AC : 6|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,IBOX,TCU + SG_ F_SUB_TQI : 7|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ECS,EPB,ESC,IBOX,TCU + SG_ TQI_ACOR : 8|8@1+ (0.390625,0.0) [0.0|99.6094] "%" _4WD,EPB,ESC,IBOX,TCU + SG_ N : 16|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" _4WD,ACU,AFLS,CLU,CUBIS,DATC,ECS,EPB,ESC,FPCM,IBOX,MDPS,SCC,TCU + SG_ TQI : 32|8@1+ (0.390625,0.0) [0.0|99.6094] "%" _4WD,ECS,EPB,ESC,IBOX,TCU + SG_ TQFR : 40|8@1+ (0.390625,0.0) [0.0|99.6094] "%" _4WD,EPB,ESC,IBOX,TCU + SG_ VS : 48|8@1+ (1.0,0.0) [0.0|254.0] "km/h" _4WD,AAF,ACU,AHLS,BCM,CLU,DATC,ECS,EPB,IBOX,LCA,LDWS_LKAS,LVR,MDPS,ODS,SCC,SMK,SPAS,TCU,TPMS + SG_ RATIO_TQI_BAS_MAX_STND : 56|8@1+ (0.0078,0.0) [0.0|2.0] "" _4WD,IBOX,TCU + +BO_ 1301 CLU14: 8 CLU + SG_ CF_Clu_ADrUNValueSet : 0|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_ADrLNValueSet : 3|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_EscortHLNValueSet : 6|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_DoorLSNValueSet : 8|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_PSMNValueSet : 11|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_TTUnlockNValueSet : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_PTGMNValueSet : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_SCMNValueSet : 18|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_WlightNValueSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_TempUnitNValueSet : 22|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,DATC + SG_ CF_Clu_MoodLpNValueSet : 24|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_TrfChgSet : 27|2@1+ (1.0,0.0) [0.0|3.0] "" AFLS + SG_ CF_Clu_OTTurnNValueSet : 29|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_LcaNValueSet : 32|2@1+ (1.0,0.0) [0.0|3.0] "" LCA + SG_ CF_Clu_RctaNValueSet : 34|2@1+ (1.0,0.0) [0.0|3.0] "" LCA + SG_ CF_Clu_RcwNValueSet : 36|2@1+ (1.0,0.0) [0.0|3.0] "" LCA + SG_ CF_Clu_EscOffNValueSet : 38|3@1+ (1.0,0.0) [0.0|7.0] "" ESC + SG_ CF_Clu_SccNaviCrvNValueSet : 41|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Clu_SccNaviCamNValueSet : 43|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Clu_SccAebNValueSet : 45|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Clu_LkasModeNValueSet : 47|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Clu_FcwNValueSet : 51|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Clu_PasSpkrLvNValueSet : 53|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_SccDrvModeNValueSet : 56|3@1+ (1.0,0.0) [0.0|7.0] "" SCC + SG_ CF_Clu_HAnBNValueSet : 59|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_HfreeTrunkTgNValueSet : 61|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + +BO_ 275 TCU13: 8 TCU + SG_ N_TGT_LUP : 0|8@1+ (10.0,500.0) [500.0|3040.0] "rpm" EMS,IBOX + SG_ SLOPE_TCU : 8|6@1+ (0.5,-16.0) [-16.0|15.5] "%" CLU,CUBIS,EMS,IBOX + SG_ CF_Tcu_InhCda : 14|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_IsgInhib : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_BkeOnReq : 16|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_NCStat : 18|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_TarGr : 20|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,CLU,DATC,EMS,EPB,ESC,IBOX,SCC + SG_ CF_Tcu_ShfPatt : 24|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,CUBIS,EMS,IBOX + SG_ CF_Tcu_InhVis : 28|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_PRelReq : 29|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LVR + SG_ CF_Tcu_ITPhase : 30|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_ActEcoRdy : 31|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_TqGrdLim : 32|8@1+ (10.0,0.0) [0.0|2540.0] "Nm/s" EMS,IBOX + SG_ CR_Tcu_IsgTgtRPM : 40|8@1+ (20.0,0.0) [0.0|3500.0] "rpm" EMS,IBOX + SG_ CF_Tcu_SptRdy : 48|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Tcu_SbwPInfo : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_Alive3 : 58|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_ChkSum3 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,IBOX + +BO_ 274 TCU12: 8 TCU + SG_ ETL_TCU : 0|8@1+ (2.0,0.0) [0.0|508.0] "Nm" EMS,IBOX + SG_ CUR_GR : 8|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,ESC,IBOX,SCC,TPMS + SG_ CF_Tcu_Alive : 12|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,IBOX,SCC + SG_ CF_Tcu_ChkSum : 14|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,IBOX,SCC + SG_ VS_TCU : 16|8@1+ (1.0,0.0) [0.0|254.0] "km/h" BCM,CLU,DATC,EMS,IBOX,LCA,LVR,PGS,SMK,SNV + SG_ FUEL_CUT_TCU : 28|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ INH_FUEL_CUT : 29|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ IDLE_UP_TCU : 30|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ N_INC_TCU : 31|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ SPK_RTD_TCU : 32|8@1+ (0.375,-23.625) [-15.0|15.0] "" EMS,IBOX + SG_ N_TC_RAW : 40|16@1+ (0.25,0.0) [0.0|16383.5] "rpm" EMS,IBOX + SG_ VS_TCU_DECIMAL : 56|8@1+ (0.0078125,0.0) [0.0|0.9921875] "km/h" CLU,EMS,IBOX,LCA + +BO_ 273 TCU11: 8 TCU + SG_ TQI_TCU_INC : 0|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,ESC,IBOX + SG_ G_SEL_DISP : 8|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,AFLS,AVM,BCM,CGW,CLU,CUBIS,ECS,EMS,EPB,ESC,IAP,IBOX,LCA,LDWS_LKAS,LVR,MDPS,PGS,SCC,SMK,SNV,SPAS,TPMS + SG_ F_TCU : 12|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,IBOX + SG_ TCU_TYPE : 14|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,EMS,ESC,IBOX + SG_ TCU_OBD : 16|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,ESC,IBOX + SG_ SWI_GS : 19|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,ESC,IBOX,SCC + SG_ GEAR_TYPE : 20|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,CLU,EMS,ESC,IBOX,SCC + SG_ TQI_TCU : 24|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,ESC,IBOX + SG_ TEMP_AT : 32|8@1+ (1.0,-40.0) [-40.0|214.0] "deg" AAF,CLU,CUBIS,EMS,ESC,IBOX + SG_ N_TC : 40|16@1+ (0.25,0.0) [0.0|16383.5] "rpm" _4WD,EMS,EPB,ESC,IBOX + SG_ SWI_CC : 56|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,CLU,EMS,ESC,IBOX + SG_ CF_Tcu_Alive1 : 58|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_ChkSum1 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,IBOX + +BO_ 16 ACU13: 8 ACU + SG_ CF_Acu_CshAct : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CUBIS,IBOX,ODS + +BO_ 1040 CGW_USM1: 8 BCM + SG_ CF_Gway_ATTurnRValue : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PTGMRValue : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_EscortHLRValue : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_TTUnlockRValue : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_ADrLRValue : 8|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_ADrURValue : 11|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_SCMRValue : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_WlightRValue : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PSMRValue : 18|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_OTTurnRValue : 21|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_DrLockSoundRValue : 24|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_HAnBRValue : 27|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_MoodLpRValue : 30|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_HfreeTrunkRValue : 32|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_AutoLightRValue : 35|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_RearWiperRValue : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PasSpkrLvRValue : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + +BO_ 1292 CLU13: 8 CLU + SG_ CF_Clu_LowfuelWarn : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,FPCM,IBOX + SG_ CF_Clu_RefDetMod : 2|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX + SG_ CF_Clu_AvgFCU : 3|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX + SG_ CF_Clu_AvsmCur : 5|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,SCC + SG_ CF_Clu_AvgFCI : 6|10@1+ (0.1,0.0) [0.0|102.2] "" IBOX + SG_ CF_Clu_DrivingModeSwi : 16|2@1+ (1.0,0.0) [0.0|3.0] "" DATC,ECS,EMS,ESC,IAP,MDPS,TCU + SG_ CF_Clu_FuelDispLvl : 18|5@1+ (1.0,0.0) [0.0|31.0] "" CGW,IBOX + SG_ CF_Clu_FlexSteerSW : 23|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Clu_DTE : 24|10@1+ (1.0,0.0) [0.0|1023.0] "" DATC + SG_ CF_Clu_TripUnit : 34|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ CF_Clu_SWL_Stat : 36|3@1+ (1.0,0.0) [0.0|7.0] "" ACU,EMS + SG_ CF_Clu_ActiveEcoSW : 39|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,EMS,TCU + SG_ CF_Clu_EcoDriveInf : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CUBIS,EMS,IAP,IBOX + SG_ CF_Clu_IsaMainSW : 43|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Clu_LdwsLkasSW : 56|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Clu_AltLStatus : 59|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,DATC,EMS + SG_ CF_Clu_AliveCnt2 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,LDWS_LKAS + +BO_ 1290 SCC13: 8 SCC + SG_ SCCDrvModeRValue : 0|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ SCC_Equip : 3|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ AebDrvSetStatus : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,ESC + +BO_ 1287 TCS15: 4 ESC + SG_ ABS_W_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,CUBIS,IBOX + SG_ TCS_OFF_LAMP : 1|2@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,CLU + SG_ TCS_LAMP : 3|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ACU,CLU,CUBIS,IBOX,SCC + SG_ DBC_W_LAMP : 5|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ DBC_F_LAMP : 6|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,CLU + SG_ ESC_Off_Step : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ AVH_CLU : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,EPB + SG_ AVH_I_LAMP : 24|2@1+ (1.0,0.0) [0.0|3.0] "" EPB + SG_ EBD_W_LAMP : 26|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ AVH_ALARM : 27|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ AVH_LAMP : 29|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EPB,SPAS + +BO_ 1282 TCU14: 4 TCU + SG_ CF_TCU_WarnMsg : 0|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_TCU_WarnImg : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_TCU_WarnSnd : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Tcu_GSel_BlinkReq : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,LVR + SG_ CF_Tcu_StRelStat : 12|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,ESC + SG_ CF_Tcu_DriWarn1 : 13|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EMS,ESC + SG_ CF_Tcu_DriWarn2 : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,ESC + +BO_ 1281 ECS11: 3 ECS + SG_ ECS_W_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,IBOX + SG_ SYS_NA : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ ECS_DEF : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ ECS_DIAG : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ L_CHG_NA : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Leveling_Off : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ LC_overheat : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Lifting : 8|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Lowering : 9|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Damping_Mode : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ REQ_Damping : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ REQ_Height : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ REQ_level : 16|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ ACT_Height : 20|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + +BO_ 1024 CLU_CFG11: 2 CLU + SG_ Vehicle_Type : 0|16@1+ (1.0,0.0) [0.0|65536.0] "" _4WD + +BO_ 1280 ACU14: 1 ACU + SG_ CF_SWL_Ind : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_TTL_Ind : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_SBR_Ind : 4|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + +BO_ 512 EMS20: 6 EMS + SG_ FCO : 0|16@1+ (0.128,0.0) [0.0|8388.48] "ul" CLU,CUBIS,FPCM,IBOX + SG_ CF_Ems_PumpTPres : 16|8@1+ (3.137254902,0.0) [0.0|800.0] "kPa" FPCM,IBOX + SG_ Split_Stat : 32|1@1+ (1.0,0.0) [0.0|1.0] "" FPCM diff --git a/opendbc_repo/opendbc/dbc/hyundai_2015_mcan.dbc b/opendbc_repo/opendbc/dbc/hyundai_2015_mcan.dbc new file mode 100644 index 0000000000..6bcd771e51 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/hyundai_2015_mcan.dbc @@ -0,0 +1,1564 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: CLOCK HUD H_U DATC CCP KMA_TMU CUBIS TMU IPM RSE_R RRC CGW RSE_L AMP EDT SWRC IBOX CLU FHCU ASD MON AVM KBD + + +BO_ 3221225472 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ C_WHEEL_FL : 0|12@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_WHEEL_FR : 0|12@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_WHEEL_RL : 0|12@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_WHEEL_RR : 0|12@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 2046 TP_EDT_AMP: 8 EDT + SG_ Byte0_TCP_7FE : 7|8@0+ (1,0) [0|0] "" AMP + SG_ Byte1_Data_7FE : 15|8@0+ (1,0) [0|0] "" AMP + SG_ Byte2_Data_7FE : 23|8@0+ (1,0) [0|0] "" AMP + SG_ Byte3_Data_7FE : 31|8@0+ (1,0) [0|0] "" AMP + SG_ Byte4_Data_7FE : 39|8@0+ (1,0) [0|0] "" AMP + SG_ Byte5_Data_7FE : 47|8@0+ (1,0) [0|0] "" AMP + SG_ Byte6_Data_7FE : 55|8@0+ (1,0) [0|0] "" AMP + SG_ Byte7_Data_7FE : 63|8@0+ (1,0) [0|0] "" AMP + +BO_ 251 HU_TMU_E_02: 8 H_U + SG_ HU_GPS_Year : 7|8@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ HU_GPS_Month : 15|8@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ HU_GPS_Day : 23|8@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ HU_GPS_Hour : 31|8@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ HU_GPS_Minute : 39|8@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ HU_GPS_Second : 47|8@0+ (1,0) [0|0] "" CUBIS,TMU + +BO_ 250 HU_TMU_E_01: 8 H_U + SG_ HU_VoiceRecCom : 2|3@0+ (1,0) [0|0] "" TMU + SG_ HU_LangChgCom : 5|3@0+ (1,0) [0|0] "" TMU + SG_ HU_CallEndCmd : 9|2@0+ (1,0) [0|0] "" TMU + SG_ HU_ServiceReqtID : 13|4@0+ (1,0) [0|0] "" TMU + SG_ HU_MicReqCmd : 15|2@0+ (1,0) [0|0] "" TMU + SG_ HU_SeviceAction : 18|3@0+ (1,0) [0|0] "" TMU + SG_ HU_eCallStatus : 20|2@0+ (1,0) [0|0] "" TMU + +BO_ 1269 TP_CLU_ANDAUTO_HU: 8 CLU + SG_ Byte0_TCP_4F5 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4F5 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4F5 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4F5 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4F5 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4F5 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4F5 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4F5 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1268 TP_HU_ANDAUTO_CLU: 8 H_U + SG_ Byte0_TCP_4F4 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4F4 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4F4 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4F4 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4F4 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4F4 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4F4 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4F4 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1267 TP_CLU_CARPLAY_HU: 8 CLU + SG_ Byte0_TCP_4F3 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4F3 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4F3 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4F3 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4F3 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4F3 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4F3 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4F3 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1266 TP_HU_CARPLAY_CLU: 8 H_U + SG_ Byte0_TCP_4F2 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4F2 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4F2 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4F2 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4F2 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4F2 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4F2 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4F2 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1263 TP_CLU_IBOX_HU: 8 CLU + SG_ Byte0_TCP_4EF : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4EF : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4EF : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4EF : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4EF : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4EF : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4EF : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4EF : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1262 TP_HU_IBOX_CLU: 8 H_U + SG_ Byte0_TCP_4EE : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4EE : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4EE : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4EE : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4EE : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4EE : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4EE : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4EE : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1261 TP_CLU_DLNA_HU: 8 CLU + SG_ Byte0_TCP_4ED : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4ED : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4ED : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4ED : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4ED : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4ED : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4ED : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4ED : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1260 TP_HU_DLNA_CLU: 8 H_U + SG_ Byte0_TCP_4EC : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4EC : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4EC : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4EC : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4EC : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4EC : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4EC : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4EC : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 491 GW_DDM_PE: 8 CLU + SG_ C_DRVDoorStatus : 1|2@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CUBIS,DATC,EDT,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ C_ASTDoorStatus : 3|2@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CUBIS,DATC,EDT,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ C_RLDoorStatus : 5|2@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CUBIS,DATC,EDT,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ C_RRDoorStatus : 7|2@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CUBIS,DATC,EDT,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ C_TrunkStatus : 9|2@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CUBIS,DATC,EDT,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ C_OSMirrorStatus : 11|2@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CUBIS,DATC,EDT,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + +BO_ 1259 TP_CLU_MP_HU: 8 CLU + SG_ Byte0_TCP_4EB : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4EB : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4EB : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4EB : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4EB : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4EB : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4EB : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4EB : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1258 TP_HU_MP_CLU: 8 H_U + SG_ Byte0_TCP_4EA : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4EA : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4EA : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4EA : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4EA : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4EA : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4EA : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4EA : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1257 TP_CLU_FM_HU: 8 CLU + SG_ Byte0_TCP_4E9 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4E9 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4E9 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4E9 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4E9 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4E9 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4E9 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4E9 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1256 TP_HU_FM_CLU: 8 H_U + SG_ Byte0_TCP_4E8 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4E8 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4E8 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4E8 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4E8 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4E8 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4E8 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4E8 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1255 TP_CLU_MLT_HU: 8 CLU + SG_ Byte0_TCP_4E7 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4E7 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4E7 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4E7 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4E7 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4E7 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4E7 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4E7 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 487 HU_CLU_PE_13: 8 H_U + SG_ Navi_DistToPoint1_F : 11|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint1_I : 7|12@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint1_U : 23|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint2_I : 19|12@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint2_F : 35|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint2_U : 39|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint3_F : 51|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint3_I : 47|12@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToPoint3_U : 63|4@0+ (1,0) [0|0] "" CLU,HUD + +BO_ 1254 TP_HU_MLT_CLU: 8 H_U + SG_ Byte0_TCP_4E6 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4E6 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4E6 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4E6 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4E6 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4E6 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4E6 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4E6 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 486 HU_CLU_PE_12: 8 H_U + SG_ Navi_DistToDest_I : 7|16@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToDest_F : 19|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_DistToDest_U : 23|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_EstimHour : 31|8@0+ (1,0) [0|254] "hh" CLU,HUD + SG_ Navi_EstimMin : 37|6@0+ (1,0) [0|59] "mm" CLU,HUD + SG_ Navi_EstimTimeType : 39|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_Compass : 45|6@0+ (7.5,-7.5) [0|352.5] "Degree" CLU,HUD + +BO_ 229 HU_SYS_E_00: 8 H_U + SG_ SYS_SW_Ver_Req : 1|2@0+ (1,0) [0|0] "" AMP,CCP,CGW,CLOCK,CLU,HUD,IBOX,RRC,RSE_L + SG_ SYS_CAN_Ver_Req : 3|2@0+ (1,0) [0|0] "" AMP,CCP,CGW,CLOCK,CLU,HUD,IBOX,RRC,RSE_L + SG_ SYS_HW_Ver_Req : 5|2@0+ (1,0) [0|0] "" AMP,CCP,CGW,CLOCK,CLU,IBOX,RRC + SG_ SYS_RBD_Req : 9|2@0+ (1,0) [0|0] "" AMP,IBOX + SG_ SYS_MOSTErrorDiag_Req : 11|2@0+ (1,0) [0|0] "" AMP,IBOX + SG_ SYS_Reset_Req : 17|2@0+ (1,0) [0|0] "" AMP,IBOX + +BO_ 1253 TP_CLU_VCDC_HU: 8 CLU + SG_ Byte0_TCP_4E5 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4E5 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4E5 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4E5 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4E5 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4E5 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4E5 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4E5 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 485 HU_CLU_PE_11: 8 H_U + SG_ Navi_FixedSpdTrap : 3|4@0+ (10,0) [10|110] "Km/h" CLU,HUD + SG_ Navi_MobileSpdTrap : 7|4@0+ (10,0) [10|110] "Km/h" CLU,HUD + SG_ Navi_OverSpdAlarm : 11|2@0+ (1,0) [0|0] "" CGW,CLU,HUD + SG_ Navi_SpdRedlightTrap : 15|4@0+ (10,0) [10|110] "Km/h" CLU,HUD + SG_ Navi_NonSpdTrap : 20|5@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_WarningZone : 27|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_MergeWarning : 33|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_CurveWarning : 39|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_BusSpdTrap : 43|4@0+ (10,0) [10|110] "Km/h" CLU,HUD + SG_ Navi_SpdLimit_Type : 49|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_SpdLimit_Unit : 51|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_SpdInfo_Type : 55|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ Navi_SpdLimit : 63|8@0+ (1,0) [1|254] "" CLU,HUD + +BO_ 1252 TP_HU_VCDC_CLU: 8 H_U + SG_ Byte0_TCP_4E4 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4E4 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4E4 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4E4 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4E4 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4E4 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4E4 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4E4 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1251 TP_CLU_JB_HU: 8 CLU + SG_ Byte0_TCP_4E3 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4E3 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4E3 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4E3 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4E3 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4E3 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4E3 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4E3 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1250 TP_HU_JB_CLU: 8 H_U + SG_ Byte0_TCP_4E2 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4E2 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4E2 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4E2 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4E2 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4E2 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4E2 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4E2 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1248 TP_TMU_HU: 8 TMU + SG_ Byte0_TCP_4E0 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4E0 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4E0 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4E0 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4E0 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4E0 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4E0 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4E0 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 479 CLU_HU_PE_01: 8 CLU + SG_ CLU_Type : 7|8@0+ (1,0) [0|0] "" H_U + SG_ CLU_Region : 15|8@0+ (1,0) [0|0] "" H_U + SG_ CLU_VersionMinor : 23|8@0+ (1,0) [0|0] "" H_U + SG_ CLU_VersionMajor : 31|8@0+ (1,0) [0|0] "" H_U + SG_ CLU_CurrentDispState : 39|8@0+ (1,0) [0|0] "" H_U + SG_ C_DRVDRSW : 41|2@0+ (1,0) [0|0] "" H_U + SG_ CF_Clu_LowfuelWarning : 44|2@0+ (1,0) [0|0] "" H_U + SG_ CLU_PowerInfo : 46|2@0+ (1,0) [0|0] "" H_U + SG_ C_DrivingModeState : 50|3@0+ (1,0) [0|0] "" H_U + SG_ Clu_RheostatLvl : 55|5@0+ (1,0) [0|0] "" H_U,MON,SWRC + SG_ C_Clu_ActiveEcoSW : 57|2@0+ (1,0) [0|0] "" H_U + SG_ C_Detent : 59|2@0+ (1,0) [0|0] "" CCP,CLOCK,H_U,KBD,MON,RRC,RSE_L,RSE_R + SG_ C_DrivingModeOn : 61|2@0+ (1,0) [0|0] "" H_U + +BO_ 2015 TP_EDT_All_Req: 8 EDT + SG_ Byte0_TCP_7DF : 7|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte1_Data_7DF : 15|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte2_Data_7DF : 23|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte3_Data_7DF : 31|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte4_Data_7DF : 39|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte5_Data_7DF : 47|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte6_Data_7DF : 55|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + SG_ Byte7_Data_7DF : 63|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,FHCU,HUD,H_U,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + +BO_ 474 CLU_HU_PE_02: 8 CLU + SG_ CF_Clu_AvgFCU : 1|2@0+ (1,0) [0|0] "" H_U + SG_ CF_Clu_AvgFCL : 9|10@0+ (1,0) [0|0] "" H_U + SG_ CF_Clu_TermAvgSync : 25|2@0+ (1,0) [0|0] "" H_U + SG_ CF_Clu_EcoDriveInf : 36|3@0+ (1,0) [0|0] "" H_U + SG_ CR_Clu_TermAvgFCI : 33|10@0+ (1,0) [0|0] "" H_U + SG_ CF_CLU_EcoScore : 55|16@0+ (1,0) [0|0] "" H_U + +BO_ 1495 CLU_HU_P_05: 8 CLU + SG_ Clu_TripUnit : 9|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ Clu_DTEWarn : 11|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ Clu_DTE : 7|12@0+ (1,0) [0|1500] "km" H_U,IBOX + SG_ Clu_AFC : 23|10@0+ (0.1,0) [0|99.9] "" H_U,IBOX + SG_ Clu_IFC : 29|10@0+ (0.1,0) [0|99.9] "" H_U,IBOX + SG_ Clu_Odometer : 47|24@0+ (1,0) [0|999999] "" H_U,IBOX + +BO_ 1494 CLU_HU_P_01: 8 CLU + SG_ CF_TripUnit : 13|2@0+ (1,0) [0|0] "" H_U + SG_ CF_DTE : 7|10@0+ (1,0) [0|0] "" H_U + +BO_ 214 AMP_HU_E_SYS: 8 AMP + SG_ AMP_SWVerMajor : 7|8@0+ (1,0) [0|254] "" H_U,IBOX + SG_ AMP_SWVerMinor : 15|8@0+ (1,0) [0|254] "" H_U,IBOX + SG_ AMP_CANVerMajor : 23|8@0+ (1,0) [0|254] "" H_U,IBOX + SG_ AMP_CANVerMinor : 31|8@0+ (1,0) [0|254] "" H_U,IBOX + SG_ AMP_RBDResult : 34|3@0+ (1,0) [0|0] "" H_U + SG_ AMP_MOSTErrorDiagResult : 38|3@0+ (1,0) [0|0] "" H_U + SG_ AMP_HWVerMajor : 55|8@0+ (1,0) [0|254] "" H_U,IBOX + SG_ AMP_HWVerMinor : 63|8@0+ (1,0) [0|254] "" H_U,IBOX + +BO_ 1492 CLU_HU_P_04: 8 CLU + SG_ MM_CR_Fatc_AcnComCst_W : 7|10@0+ (10,0) [0|8000] "W" H_U + SG_ MM_CR_Ldc_PwrMon_W : 12|8@0+ (10,0) [0|2550] "W" H_U + SG_ MM_CR_Fatc_PTCPwrCon_W : 17|10@0+ (10,0) [0|10000] "W" H_U + SG_ MM_CR_BmsChgExp_T_Fast : 39|16@0+ (1,0) [0|0] "minute" H_U + SG_ MM_CR_BmsChgExp_T_Slow : 55|16@0+ (1,0) [0|0] "minute" H_U + +BO_ 1491 CLU_HU_P_03: 8 CLU + SG_ MM_CF_Vcu_EvMod : 3|4@0+ (1,0) [0|0] "" H_U + SG_ MM_CF_Vcu_GarSelDisp : 7|4@0+ (999,0) [0|0] "" H_U + SG_ MM_CF_Vcu_ThiBatTir : 8|1@0+ (1,0) [0|0] "" H_U + SG_ CR_Mcu_MotEstTqPc : 23|10@0+ (0.2,-100) [-100|99.8] "%" H_U + SG_ CR_Mcu_MotActRotSpd_rpm : 39|16@0+ (1,-32768) [-32768|32767] "rpm" H_U + +BO_ 1490 CLU_HU_P_02: 8 CLU + SG_ MM_CR_Vcu_EcoSco : 3|4@0+ (1,0) [0|0] "" H_U + SG_ MM_CF_Vcu_PgmRun5 : 5|2@0+ (1,0) [0|0] "" H_U + SG_ MM_CR_Clu_Odometer_kph : 15|24@0+ (0.1,0) [0|0] "km" H_U + +BO_ 1489 DATC_P_B_01: 8 CLU + SG_ C_InhibitR_DATC : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_InhibitP_DATC : 50|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_InhibitN_DATC : 49|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_InhibitD_DATC : 48|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 465 CLU_HU_PE_03: 8 CLU + SG_ CF_Clu_EVDTEDisp : 0|9@0+ (1,0) [0|0] "" H_U,IBOX + SG_ CF_Clu_GasDTEDisp : 17|10@0+ (1,0) [0|0] "" H_U,IBOX + SG_ MM_CR_Clu_TotalDTEDisp : 34|11@0+ (1,0) [0|0] "" H_U,IBOX + SG_ CF_Clu_TripUnit : 49|2@0+ (1,0) [0|0] "" H_U,IBOX + +BO_ 1232 TP_HU_TMU: 8 H_U + SG_ Byte0_TCP_4D0 : 7|8@0+ (1,0) [0|0] "" TMU + SG_ Byte1_Data_4D0 : 15|8@0+ (1,0) [0|0] "" TMU + SG_ Byte2_Data_4D0 : 23|8@0+ (1,0) [0|0] "" TMU + SG_ Byte3_Data_4D0 : 31|8@0+ (1,0) [0|0] "" TMU + SG_ Byte4_Data_4D0 : 39|8@0+ (1,0) [0|0] "" TMU + SG_ Byte5_Data_4D0 : 47|8@0+ (1,0) [0|0] "" TMU + SG_ Byte6_Data_4D0 : 55|8@0+ (1,0) [0|0] "" TMU + SG_ Byte7_Data_4D0 : 63|8@0+ (1,0) [0|0] "" TMU + +BO_ 1488 CLU_HU_P_00: 8 CLU + SG_ MM_CR_Mcu_VehSpd_Kph : 7|8@0+ (1,0) [0|0] "" H_U + SG_ MM_CR_Mcu_VehSpdDec_Kph : 15|8@0+ (1,0) [0|0] "" H_U + SG_ MM_CR_Bms_Soc_Pc : 23|8@0+ (1,0) [0|0] "" H_U + SG_ MM_CR_Vcu_TqMotClu_Pc : 31|8@0+ (1,-127) [0|0] "" H_U + SG_ MM_CR_Bms_DrvEnaDist : 39|8@0+ (1,0) [0|0] "" H_U + SG_ MM_CR_Clu_Soc_Seg : 44|5@0+ (1,0) [0|0] "" H_U,IBOX + +BO_ 208 CLU_HU_E_SYS: 8 CLU + SG_ CLU_SWVerMajor : 7|8@0+ (1,0) [0|254] "" H_U + SG_ CLU_SWVerMinor : 15|8@0+ (1,0) [0|254] "" H_U + SG_ CLU_CANVerMajor : 23|8@0+ (1,0) [0|254] "" H_U + SG_ CLU_CANVerMinor : 31|8@0+ (1,0) [0|254] "" H_U + SG_ CLU_HWVerMajor : 55|8@0+ (1,0) [0|254] "" H_U + SG_ CLU_HWVerMinor : 63|8@0+ (1,0) [0|254] "" H_U + +BO_ 448 HU_DATC_PE_00: 8 H_U + SG_ DATC_AqsLevelChg : 3|4@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ RSELockOnOff : 7|2@0+ (1,0) [0|0] "" CGW,DATC,IPM,RRC + SG_ DATC_AqsMode : 9|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_Graphreset_Info : 17|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_VRActivity : 33|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_PhoneActivity : 35|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ BlowerNoiseControl : 37|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + +BO_ 1211 TP_HU_TBT_CLU: 8 H_U + SG_ Byte0_TCP_4BB : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4BB : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4BB : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4BB : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4BB : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4BB : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4BB : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4BB : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1207 TP_HU_DAB_CLU: 8 H_U + SG_ Byte0_TCP_4B7 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4B7 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4B7 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4B7 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4B7 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4B7 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4B7 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4B7 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1206 TP_HU_XM_CLU: 8 H_U + SG_ Byte0_TCP_4B6 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4B6 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4B6 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4B6 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4B6 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4B6 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4B6 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4B6 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1204 TP_HU_DMB_CLU: 8 H_U + SG_ Byte0_TCP_4B4 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_4B4 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_4B4 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_4B4 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_4B4 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_4B4 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_4B4 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_4B4 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 432 TMU_GW_PE_01: 8 TMU + SG_ C_DATCOnOffReq : 1|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,H_U,IPM + SG_ C_DATCTempUnit : 3|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,H_U,IPM + SG_ C_DATCTempSet : 15|8@0+ (1,0) [0|0] "" CGW,CLU,DATC,H_U,IPM + SG_ TMU_IVRActivity : 33|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,H_U,IPM + SG_ TMU_PhoneActivity : 35|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,H_U,IPM + +BO_ 1195 TP_CLU_TBT_HU: 8 CLU + SG_ Byte0_TCP_4AB : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4AB : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4AB : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4AB : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4AB : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4AB : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4AB : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4AB : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1191 TP_CLU_DAB_HU: 8 CLU + SG_ Byte0_TCP_4A7 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4A7 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4A7 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4A7 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4A7 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4A7 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4A7 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4A7 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1190 TP_CLU_XM_HU: 8 CLU + SG_ Byte0_TCP_4A6 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4A6 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4A6 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4A6 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4A6 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4A6 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4A6 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4A6 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1188 TP_CLU_DMB_HU: 8 CLU + SG_ Byte0_TCP_4A4 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_4A4 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_4A4 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_4A4 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_4A4 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_4A4 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_4A4 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_4A4 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1179 TP_HU_NAVI_CLU: 8 H_U + SG_ Byte0_TCP_49B : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_49B : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_49B : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_49B : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_49B : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_49B : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_49B : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_49B : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1178 TP_CLU_Ipod_HU: 8 CLU + SG_ Byte0_TCP_49A : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_49A : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_49A : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_49A : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_49A : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_49A : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_49A : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_49A : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 410 HU_CLU_PE_08: 8 H_U + SG_ VCDC_SelDiscNo : 11|4@0+ (1,0) [0|0] "" CLU + SG_ VCDC_TrackChapterNo : 7|10@0+ (1,0) [0|0] "" CLU + SG_ VCDC_PlayTime : 23|24@0+ (1,0) [0|0] "" CLU + SG_ MLT_PlayTime : 47|24@0+ (1,0) [0|0] "" CLU + +BO_ 1176 TP_CLU_DVD_HU: 8 CLU + SG_ Byte0_TCP_498 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_498 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_498 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_498 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_498 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_498 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_498 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_498 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 1175 TP_CLU_USB_HU: 8 CLU + SG_ Byte0_TCP_497 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_497 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_497 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_497 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_497 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_497 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_497 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_497 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 407 HU_CLU_PE_05: 8 H_U + SG_ HU_LanguageInfo : 7|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ HU_MuteStatus : 9|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ HU_VolumeStatus : 15|6@0+ (1,0) [0|0] "" CLU,HUD + SG_ HU_NaviDisp : 17|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ HU_NaviStatus : 19|2@0+ (1,0) [0|0] "" CGW,CLU,HUD,IPM + SG_ HU_DistanceUnit : 21|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ HU_Navigation_On_Off : 23|2@0+ (1,0) [0|0] "" AVM,CGW,CLU,DATC,HUD,IPM + +BO_ 1942 TP_AMP_HU_DiagRes: 8 AMP + SG_ Byte0_TCP_796 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_796 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_796 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_796 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_796 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_796 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_796 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_796 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 406 HU_CLU_PE_04: 8 H_U + SG_ C_SDARS_ChannelNo : 7|8@0+ (1,0) [0|0] "" CLU + SG_ C_NaviRouteGuidance : 11|2@0+ (1,0) [0|0] "" CLU + SG_ HD_SPS_ChannelNo : 15|4@0+ (1,0) [0|0] "" CLU + SG_ C_SDARS_PresetNo : 19|4@0+ (1,0) [0|0] "" CLU + SG_ DAB_ServiceFollowing : 21|2@0+ (1,0) [0|0] "" CLU + SG_ SXM_ChannelNo : 25|10@0+ (1,0) [0|999] "" AMP,CLU,HUD + +BO_ 1941 TP_HU_AMP_DiagReq: 8 H_U + SG_ Byte0_TCP_795 : 7|8@0+ (1,0) [0|0] "" AMP + SG_ Byte1_Data_795 : 15|8@0+ (1,0) [0|0] "" AMP + SG_ Byte2_Data_795 : 23|8@0+ (1,0) [0|0] "" AMP + SG_ Byte3_Data_795 : 31|8@0+ (1,0) [0|0] "" AMP + SG_ Byte4_Data_795 : 39|8@0+ (1,0) [0|0] "" AMP + SG_ Byte5_Data_795 : 47|8@0+ (1,0) [0|0] "" AMP + SG_ Byte6_Data_795 : 55|8@0+ (1,0) [0|0] "" AMP + SG_ Byte7_Data_795 : 63|8@0+ (1,0) [0|0] "" AMP + +BO_ 1173 TP_CLU_CD_HU: 8 CLU + SG_ Byte0_TCP_495 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_495 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_495 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_495 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_495 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_495 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_495 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_495 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 405 HU_CLU_PE_03: 8 H_U + SG_ HU_IntegPresetNum : 7|8@0+ (1,0) [0|0] "" AMP,CLU,HUD + SG_ Radio_Area : 10|8@0+ (1,0) [0|0] "" CLU + SG_ DMB_PresetNo : 29|5@0+ (1,0) [0|0] "" CLU + SG_ RADIO_PresetNo : 18|5@0+ (1,0) [0|0] "" CLU + SG_ HU_Opstate_DIS2 : 38|7@0+ (1,0) [0|0] "" AMP,CLU,HUD + +BO_ 1168 TP_HU_USB_CLU: 8 H_U + SG_ Byte0_TCP_490 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_490 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_490 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_490 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_490 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_490 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_490 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_490 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1936 TP_HU_All_Req: 8 H_U + SG_ Byte0_TCP_790 : 7|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte1_Data_790 : 15|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte2_Data_790 : 23|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte3_Data_790 : 31|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte4_Data_790 : 39|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte5_Data_790 : 47|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte6_Data_790 : 55|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + SG_ Byte7_Data_790 : 63|8@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CGW,CLOCK,CLU,CUBIS,DATC,EDT,FHCU,HUD,IBOX,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,SWRC,TMU + +BO_ 1167 TP_HU_Ipod_CLU: 8 H_U + SG_ Byte0_TCP_48F : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_48F : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_48F : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_48F : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_48F : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_48F : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_48F : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_48F : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1166 TP_HU_DVD_CLU: 8 H_U + SG_ Byte0_TCP_48E : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_48E : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_48E : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_48E : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_48E : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_48E : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_48E : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_48E : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1165 TP_HU_CD_CLU: 8 H_U + SG_ Byte0_TCP_48D : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_48D : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_48D : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_48D : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_48D : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_48D : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_48D : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_48D : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 1164 TP_CLU_NAVI_HU: 8 CLU + SG_ Byte0_TCP_48C : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_48C : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_48C : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_48C : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_48C : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_48C : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_48C : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_48C : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 139 AMP_HU_E_12: 8 AMP + SG_ AMP_Beep2VolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep2FrequencyState : 15|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep2OutputMaskState : 31|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep2DOnState : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep2DOffState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep2NOfCycleState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 138 AMP_HU_E_11: 8 AMP + SG_ AMP_Beep1VolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep1FrequencyState : 15|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep1OutputMaskState : 31|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep1DOnState : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep1DOffState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep1NOfCycleState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 137 AMP_HU_E_10: 8 AMP + SG_ AMP_MTSOutputMaskSupport : 1|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_MTSMuteMaskSupport : 5|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_HFOutputMaskSupport : 9|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_HFMuteMaskSupport : 13|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_NaviOutputMaskSupport : 17|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_NaviMuteMaskSupport : 21|2@0+ (1,0) [0|0] "" H_U + +BO_ 1928 TP_HU_PhyRes: 8 H_U + SG_ Byte0_TCP_788 : 7|8@0+ (1,0) [0|0] "" EDT + SG_ Byte1_Data_788 : 15|8@0+ (1,0) [0|0] "" EDT + SG_ Byte2_Data_788 : 23|8@0+ (1,0) [0|0] "" EDT + SG_ Byte3_Data_788 : 31|8@0+ (1,0) [0|0] "" EDT + SG_ Byte4_Data_788 : 39|8@0+ (1,0) [0|0] "" EDT + SG_ Byte5_Data_788 : 47|8@0+ (1,0) [0|0] "" EDT + SG_ Byte6_Data_788 : 55|8@0+ (1,0) [0|0] "" EDT + SG_ Byte7_Data_788 : 63|8@0+ (1,0) [0|0] "" EDT + +BO_ 136 AMP_HU_E_09: 8 AMP + SG_ AMP_MaxBeep2VolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep2Freq_State : 15|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep2OutputMaskSup : 33|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep2DOnState : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep2DOffState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep2NOfCycleState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 135 AMP_HU_E_08: 8 AMP + SG_ AMP_MaxBeep1VolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep1Freq_State : 15|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_Beep1OutputMaskSup : 33|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep1DOnState : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep1DOffState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBeep1NOfCycleState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 134 AMP_HU_E_07: 8 AMP + SG_ ASD_SetValue : 2|3@0+ (1,0) [0|0] "" H_U,IBOX + SG_ ASD_Version : 15|8@0+ (1,0) [0|0] "" H_U,IBOX + +BO_ 1157 TP_HU_CLU_HF: 8 H_U + SG_ Byte0_TCP_485 : 7|8@0+ (1,0) [0|0] "" CLU + SG_ Byte1_Data_485 : 15|8@0+ (1,0) [0|0] "" CLU + SG_ Byte2_Data_485 : 23|8@0+ (1,0) [0|0] "" CLU + SG_ Byte3_Data_485 : 31|8@0+ (1,0) [0|0] "" CLU + SG_ Byte4_Data_485 : 39|8@0+ (1,0) [0|0] "" CLU + SG_ Byte5_Data_485 : 47|8@0+ (1,0) [0|0] "" CLU + SG_ Byte6_Data_485 : 55|8@0+ (1,0) [0|0] "" CLU + SG_ Byte7_Data_485 : 63|8@0+ (1,0) [0|0] "" CLU + +BO_ 133 AMP_HU_E_06: 8 AMP + SG_ AMP_MaxVolumeStep : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBalanceStep : 15|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxFadeStep : 23|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxBassStep : 31|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxMidStep : 39|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxTrebleStep : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_ASDMajorVer : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_ASDMinorVer : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 389 AMP_HU_PE_05: 8 AMP + SG_ AMP_EngOrderC2Setting : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_EngOrderC4Setting : 15|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_EngOrderC6Setting : 23|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_APSBand0Setting : 31|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_APSBand1Setting : 39|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_APSBand2Setting : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_APSBand3Setting : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_APSBand4Setting : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 132 AMP_HU_E_05: 8 AMP + SG_ AMP_HFVolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_HFAudioCutState : 15|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_HFOutputMaskState : 23|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_HFMuteMaskState : 39|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxHFVolumeState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxHFAudioCutState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 388 AMP_HU_PE_04: 8 AMP + SG_ AMP_PESSModeState : 1|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_PESSDesignSetting : 4|3@0+ (1,0) [0|0] "" H_U + SG_ AMP_PESSAPSSetting : 7|3@0+ (1,0) [0|0] "" H_U + SG_ AMP_PESSVolumeSetting : 15|8@0+ (1,0) [0|0] "" H_U + +BO_ 1156 TP_CLU_HF_HU: 8 CLU + SG_ Byte0_TCP_484 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_484 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_484 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_484 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_484 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_484 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_484 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_484 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 131 AMP_HU_E_04: 8 AMP + SG_ AMP_MTSVolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MTSAudioCutState : 15|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MTSOutputMaskState : 23|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_MTSMuteMaskState : 39|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxMTSVolumeState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxMTSAudioCutState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 387 AMP_HU_PE_03: 8 AMP + SG_ AMP_MainVolumeSetting : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_BalanceSetting : 15|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_FadeSetting : 23|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_BassSetting : 31|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MidSetting : 39|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_TrebleSetting : 47|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_VehicleSpeedamp : 55|8@0+ (1,0) [0|0] "" H_U + +BO_ 130 AMP_HU_E_03: 8 AMP + SG_ AMP_NaviVolumeState : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_NaviAudioCutState : 15|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_NaviOutputMaskState : 23|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_NaviMuteMaskState : 39|16@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxNaviVolumeState : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_MaxNaviAudioCutState : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 129 AMP_HU_E_02: 8 AMP + SG_ AMP_DriveState : 1|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_ConvertibleTopState : 5|2@0+ (1,0) [0|0] "" H_U + +BO_ 385 AMP_HU_PE_02: 8 AMP + SG_ AMP_MuteState : 1|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_RearSpMuteState : 3|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SurroundModeState : 9|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_EQState : 13|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SPDIFMuteSt : 17|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_BeatsModeState : 21|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_DefaultBeep1St : 25|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_DefaultBeep2St : 29|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_AudioSource : 39|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_VIPModeState : 41|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_QLSModeState : 43|2@0+ (1,0) [0|0] "" H_U + +BO_ 128 AMP_HU_E_01: 8 AMP + SG_ AMP_CurrentVehicleID : 7|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_SPDIFModeState : 11|4@0+ (1,0) [0|0] "" H_U + SG_ AMP_MajorVer : 23|8@0+ (1,0) [0|0] "" H_U,MON + SG_ AMP_MinorVer : 31|8@0+ (1,0) [0|0] "" H_U,MON + SG_ AMP_UpdateStartResp : 33|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_UpdateEndResp : 41|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_TuningMajorVer : 55|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_TuningMinorVer : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 384 AMP_HU_PE_01: 8 AMP + SG_ AMP_HFModeState : 1|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ HU_InitInfo : 3|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_ASDModeState : 6|3@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_NaviModeState : 9|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_SPDIFInfo : 12|3@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_MTSModeState : 17|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_VSCModeState : 25|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_SDVCStepState : 29|3@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_Beep1ModeState : 33|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_Beep2ModeState : 41|2@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_DistrInfoState : 55|8@0+ (1,0) [0|0] "" CLU,H_U + SG_ AMP_INFORM_TO_IPM : 57|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,H_U,IPM + SG_ AMP_SignalDoctorState : 59|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_AutoVolumeState : 61|2@0+ (1,0) [0|0] "" H_U + +BO_ 1408 AMP_HU_P_01: 8 AMP + SG_ AMP_SupportMute : 1|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportHFMode : 3|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportCfgBeep1 : 5|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportCfgBeep2 : 7|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportSpeedAdjust : 9|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportSurroundMode : 11|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportNaviMode : 13|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportMTSMode : 15|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportTopState : 17|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportBothLHDandRHD : 19|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportEQState : 21|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportVehicleID : 23|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportAudioSource : 25|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportSPDIFModeState : 27|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportRearSpMute : 29|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportVEQMode : 31|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_MakerID : 39|8@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportASDMode : 41|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportBeatsMode : 43|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportVIPMode : 45|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportQLS : 47|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportSignalDoctor : 49|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportAutoVolume : 51|2@0+ (1,0) [0|0] "" H_U + SG_ AMP_SupportPESSMode : 53|2@0+ (1,0) [0|0] "" H_U + +BO_ 1920 TP_HU_PhyReq: 8 EDT + SG_ Byte0_TCP_780 : 7|8@0+ (1,0) [0|0] "" H_U + SG_ Byte1_Data_780 : 15|8@0+ (1,0) [0|0] "" H_U + SG_ Byte2_Data_780 : 23|8@0+ (1,0) [0|0] "" H_U + SG_ Byte3_Data_780 : 31|8@0+ (1,0) [0|0] "" H_U + SG_ Byte4_Data_780 : 39|8@0+ (1,0) [0|0] "" H_U + SG_ Byte5_Data_780 : 47|8@0+ (1,0) [0|0] "" H_U + SG_ Byte6_Data_780 : 55|8@0+ (1,0) [0|0] "" H_U + SG_ Byte7_Data_780 : 63|8@0+ (1,0) [0|0] "" H_U + +BO_ 371 HU_TMU_PE_01: 8 H_U + SG_ HU_AliveStatus : 1|2@0+ (1,0) [0|0] "" CLU,CGW,TMU + SG_ HU_DeviceType : 5|4@0+ (1,0) [0|0] "" TMU + SG_ HU_DistanceUnit : 7|2@0+ (1,0) [0|0] "" TMU + SG_ HU_AudAllocStatus : 9|2@0+ (1,0) [0|0] "" TMU + SG_ HU_PowerStatus : 12|3@0+ (1,0) [0|0] "" TMU + SG_ HU_BTCallStatus : 15|3@0+ (1,0) [0|0] "" TMU + SG_ HU_VoiceRecStatus : 17|2@0+ (1,0) [0|0] "" TMU + SG_ HU_LangStatus : 20|3@0+ (1,0) [0|0] "" TMU + +BO_ 369 HU_Car_PE_01: 8 H_U + SG_ HU_VehiclePwr : 3|4@0+ (1,0) [0|0] "" AMP,ASD,AVM,CCP,CLOCK,CLU,CUBIS,DATC,FHCU,IPM,KBD,KMA_TMU,MON,RRC,RSE_L,RSE_R,TMU + +BO_ 1392 HU_TMU_P_01: 8 H_U + SG_ HU_GPS_Signal : 7|64@0+ (1,0) [0|0] "" TMU + +BO_ 112 HU_AMP_E_09: 8 H_U + SG_ AMP_Beep1VolumeStep : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep1Frequency : 15|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep1Ch_OutputMask : 31|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep1DurationOn : 47|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep1DurationOff : 55|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep1NumberOfCycles : 63|8@0+ (1,0) [0|0] "" AMP + +BO_ 1390 GW_CLU_P: 8 CLU + SG_ C_VehicleSpeed : 7|8@0+ (1,0) [0|254] "" H_U,IBOX + SG_ C_Odometer : 15|24@0+ (1,0) [0|999999] "" H_U,IBOX + +BO_ 363 GW_IPM_PE_2: 8 CLU + SG_ C_DRVUnlockState : 1|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_ASTUnlockState : 3|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_RLUnlockstate : 5|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_RRUnlockState : 7|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_VehicleInfoTMU : 9|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_Engine_Status : 11|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_TMULockFeedBack : 23|2@0+ (1,0) [0|0] "" CUBIS,TMU + +BO_ 362 GW_IPM_PE_1: 8 CLU + SG_ C_AV_Tail : 1|2@0+ (1,0) [0|0] "" AMP,CCP,CLOCK,CLU,HUD,H_U,IBOX,RRC,RSE_L + SG_ C_ParkingBrakeSW : 3|2@0+ (1,0) [0|0] "" H_U + SG_ C_RKECMD : 7|4@0+ (1,0) [0|0] "" H_U + SG_ C_BAState : 9|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_IGNSW : 14|3@0+ (1,0) [0|0] "" AMP,AVM,CUBIS,EDT,H_U,MON,RRC,SWRC + SG_ C_CountryCfg : 18|3@0+ (1,0) [0|0] "" AVM,H_U + SG_ C_AltL : 25|2@0+ (1,0) [0|0] "" H_U + SG_ C_TailLampActivity : 27|2@0+ (1,0) [0|0] "" AMP,CCP,CLOCK,HUD,H_U,IBOX,RRC,RSE_L,SWRC + SG_ RearSW_RSELockOnOff : 29|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_TMULockFeedBack : 31|2@0+ (1,0) [0|0] "" CUBIS,TMU + SG_ C_SMKTeleCrankingState : 33|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_SMKTeleCrankingFailRes : 35|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_RKECMD_GEN2 : 39|3@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_Acu_CshAct : 41|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_IntTailAct : 43|2@0+ (1,0) [0|0] "" AMP,CCP,CLOCK,CLU,HUD,H_U,IBOX,RRC,RSE_L + SG_ C_PassiveAccessUnlock : 47|3@0+ (1,0) [0|0] "" H_U,IBOX + SG_ Lca_IndLeft : 49|2@0+ (1,0) [0|0] "" H_U + SG_ FL_SndWarn : 51|2@0+ (1,0) [0|0] "" AMP + SG_ FR_SndWarn : 53|2@0+ (1,0) [0|0] "" AMP + SG_ Lca_IndRight : 55|2@0+ (1,0) [0|0] "" H_U + SG_ RCTA_IndLeft : 57|2@0+ (1,0) [0|0] "" H_U + SG_ RL_SndWarn : 59|2@0+ (1,0) [0|0] "" AMP + SG_ RR_SndWarn : 61|2@0+ (1,0) [0|0] "" AMP + SG_ RCTA_IndRight : 63|2@0+ (1,0) [0|0] "" H_U + +BO_ 361 GW_CHASSIS_PE_1: 8 CLU + SG_ C_Inhibit_State : 3|4@0+ (1,0) [0|0] "" AVM,H_U + SG_ C_P_BrakeStatus : 5|2@0+ (1,0) [0|0] "" AVM,H_U + SG_ C_Clu_AltLStatus : 7|2@0+ (1,0) [0|0] "" AVM,H_U + +BO_ 359 GW_WARNING_PE_01: 8 CLU + SG_ Spas_BEEP_Alarm : 3|4@0+ (1,0) [0|0] "" AMP + SG_ Spas_Audio_VolumeDown : 5|2@0+ (1,0) [0|0] "" AMP + SG_ Spas_Spkr_Flh_Alarm : 9|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Spas_Spkr_Fcnt_Alarm : 11|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Spas_Spkr_Frh_Alarm : 13|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Spas_Spkr_Rlh_Alarm : 17|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Spas_Spkr_Rcnt_Alarm : 19|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Spas_Spkr_Rrh_Alarm : 21|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Lkas_SysStatus : 27|4@0+ (1,0) [0|0] "" AMP,H_U + SG_ Lkas_LH_Warning : 29|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Lkas_RH_Warning : 31|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Spas_Spkr_Level : 35|3@0+ (1,0) [0|0] "" AMP + SG_ Lkas_Audio_VolumeDown : 37|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Audio_VolumeDown : 39|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_BEEP_Alarm : 43|4@0+ (1,0) [0|0] "" AMP + SG_ Pas_Audio_VolumeDown : 45|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_Spkr_Level : 32|3@0+ (1,0) [0|0] "" AMP + SG_ Pas_Spkr_Flh_Alarm : 49|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_Spkr_Fcnt_Alarm : 51|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_Spkr_Frh_Alarm : 53|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_Spkr_Rlh_Alarm : 57|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_Spkr_Rcnt_Alarm : 59|2@0+ (1,0) [0|0] "" AMP,H_U + SG_ Pas_Spkr_Rrh_Alarm : 61|2@0+ (1,0) [0|0] "" AMP,H_U + +BO_ 1376 HU_TMU_P_02: 8 H_U + SG_ HU_GPS_Signal2 : 7|8@0+ (2,0) [0|0] "Degree" TMU + SG_ HU_GPS_Signal3 : 9|2@0+ (1,0) [0|0] "" TMU + SG_ HU_GPS_Signal4 : 12|3@0+ (1,0) [0|0] "" TMU + +BO_ 93 DATC_HU_E_SYS: 8 CLU + SG_ DATC_SWVerMajor : 7|8@0+ (1,0) [0|254] "" H_U + SG_ DATC_SWVerMinor : 15|8@0+ (1,0) [0|254] "" H_U + SG_ DATC_CANVerMajor : 23|8@0+ (1,0) [0|254] "" H_U + SG_ DATC_CANVerMinor : 31|8@0+ (1,0) [0|254] "" H_U + +BO_ 344 GW_CLU_PE: 8 CLU + SG_ C_InhibitP : 1|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_InhibitR : 3|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_InhibitN : 5|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_InhibitD : 7|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_P_BrakeStatus : 9|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_Clu_AltLStatus : 11|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ CF_Clu_LowfuelWarning : 13|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ C_InhibitRMT : 15|2@0+ (1,0) [0|0] "" H_U + SG_ CF_SMKRKECmd : 18|3@0+ (1,0) [0|0] "" H_U + +BO_ 87 HU_E_02: 8 H_U + SG_ NaviValidity : 1|2@0+ (1,0) [0|0] "" CGW,CLU + +BO_ 343 GW_WARNING_PE_02: 8 CLU + SG_ CF_Lkas_TsrSlifOpt : 1|2@0+ (1,0) [0|3] "" H_U + SG_ CF_Lkas_TsrStatus : 3|2@0+ (1,0) [0|3] "" H_U + SG_ CF_Lkas_TsrAddinfo_Disp : 7|2@0+ (1,0) [0|3] "" H_U + SG_ CF_Lkas_TsrSpeed_Display : 15|8@0+ (1,0) [0|255] "" H_U + +BO_ 75 HU_AMP_E_12: 8 H_U + SG_ AMP_EngOrderC2GainSet : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_EngOrderC4GainSet : 15|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_EngOrderC6GainSet : 23|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_APSBand0GainSet : 31|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_APSBand1GainSet : 39|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_APSBand2GainSet : 47|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_APSBand3GainSet : 55|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_APSBand4GainSet : 63|8@0+ (1,0) [0|0] "" AMP + +BO_ 74 HU_AMP_E_11: 8 H_U + SG_ AMP_PESSMode : 1|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_PESSDesignSet : 4|3@0+ (1,0) [0|0] "" AMP + SG_ AMP_PESSAPSSet : 7|3@0+ (1,0) [0|0] "" AMP + SG_ AMP_PESSVolumeSet : 15|8@0+ (1,0) [0|0] "" AMP + +BO_ 1864 TP_AMP_EDT: 8 AMP + SG_ Byte0_TCP_748 : 7|8@0+ (1,0) [0|0] "" EDT + SG_ Byte1_Data_748 : 15|8@0+ (1,0) [0|0] "" EDT + SG_ Byte2_Data_748 : 23|8@0+ (1,0) [0|0] "" EDT + SG_ Byte3_Data_748 : 31|8@0+ (1,0) [0|0] "" EDT + SG_ Byte4_Data_748 : 39|8@0+ (1,0) [0|0] "" EDT + SG_ Byte5_Data_748 : 47|8@0+ (1,0) [0|0] "" EDT + SG_ Byte6_Data_748 : 55|8@0+ (1,0) [0|0] "" EDT + SG_ Byte7_Data_748 : 63|8@0+ (1,0) [0|0] "" EDT + +BO_ 327 TMU_HU_PE_03: 8 TMU + SG_ TMU_TbT_TurnIcon : 7|8@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_CountDownBar : 11|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_Distance_Unit : 13|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_DestDistance_Unit : 15|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_DistanceLo : 27|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_DistanceHi : 23|12@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_DestDistanceLo : 43|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_DestDistanceHi : 39|12@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_ExpectRemainHour : 55|8@0+ (1,0) [0|0] "" H_U + SG_ TMU_TbT_ExpectRemainMin : 61|6@0+ (1,0) [0|0] "" H_U + +BO_ 326 TMU_HU_PE_02: 8 TMU + SG_ TMU_CallStatus : 3|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_CallType : 6|3@0+ (1,0) [0|0] "" H_U + SG_ TMU_CDMA_Streng : 11|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_PacketStatus : 13|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_TalkTimeHour : 20|5@0+ (1,0) [0|0] "" H_U + SG_ TMU_TalkTimeMinute : 29|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_TalkTimeSecond : 37|6@0+ (1,0) [0|0] "" H_U + +BO_ 325 TMU_HU_PE_01: 8 TMU + SG_ TMU_AliveStatus : 2|3@0+ (1,0) [0|0] "" H_U + SG_ TMU_AudioStatus : 4|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_UpdateStatus : 7|3@0+ (1,0) [0|0] "" H_U + SG_ TMU_LangStatus : 10|3@0+ (1,0) [0|0] "" H_U + SG_ TMU_VoiceRecStatus : 12|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_MicStatus : 14|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_ServCommuStatus : 19|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_PowerStatus : 21|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_EngineStatus : 23|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_DownProgress : 31|8@0+ (1,0) [0|0] "" H_U + +BO_ 69 TMU_HU_E_04: 8 TMU + SG_ TMU_eCall : 1|2@0+ (1,0) [0|0] "" H_U + +BO_ 67 TMU_GW_E_01: 8 TMU + SG_ C_ReqDrLock : 1|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ C_ReqDrUnlock : 3|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ C_ReqHazard : 5|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ C_ReqHorn : 7|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ C_ReqEngineOperate : 9|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + +BO_ 66 TMU_HU_E_03: 8 TMU + SG_ CDMA_SelfDiag : 1|2@0+ (1,0) [0|0] "" H_U + SG_ CDMA_Antena_SelfDiag : 3|2@0+ (1,0) [0|0] "" H_U + +BO_ 1345 TMU_HU_P_02: 8 TMU + SG_ TMU_SupVoiceTextService : 1|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_SupEcoCoachService : 3|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_SupSongTagService : 5|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_SupContentService : 7|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_MajorVersion : 15|8@0+ (1,0) [0|0] "" H_U + SG_ TMU_MinorVersion : 23|8@0+ (1,0) [0|0] "" H_U + SG_ TMU_DistributeInfo : 27|4@0+ (1,0) [0|0] "" H_U + +BO_ 65 TMU_HU_E_02: 8 TMU + SG_ TMU_BarLevel1 : 7|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel2 : 1|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel4 : 21|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel3 : 11|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel5 : 31|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel6 : 25|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel8 : 45|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel7 : 35|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel9 : 55|6@0+ (1,0) [0|0] "" H_U + SG_ TMU_BarLevel10 : 63|6@0+ (1,0) [0|0] "" H_U + +BO_ 1344 TMU_HU_P_01: 8 TMU + SG_ TMU_Arrow : 3|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_ReFill_Info : 5|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_AverageMPG : 1|10@0+ (1,0) [0|0] "" H_U + SG_ TMU_TotalMPG : 23|10@0+ (1,0) [0|0] "" H_U + SG_ TMU_RewardStar : 37|14@0+ (1,0) [0|0] "" H_U + +BO_ 64 TMU_HU_E_01: 8 TMU + SG_ TMU_DisMode : 3|4@0+ (1,0) [0|0] "" H_U + SG_ TMU_AudSrcType : 7|4@0+ (1,0) [0|0] "" CLU,DATC,H_U + SG_ TMU_AudReqCmd : 9|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_LangCmd : 12|3@0+ (1,0) [0|0] "" H_U + SG_ TMU_ServReq : 15|3@0+ (1,0) [0|0] "" H_U + SG_ TMU_ErrorEvent : 23|8@0+ (1,0) [0|0] "" H_U + SG_ TMU_BeepCmd : 25|2@0+ (1,0) [0|0] "" H_U + SG_ TMU_eCall : 28|3@0+ (1,0) [0|0] "" H_U + +BO_ 62 HU_Navi_E_00: 8 H_U + SG_ Navi_SLIF_SpdUnit : 1|2@0+ (1,0) [0|0] "" CGW,CLU,HUD + SG_ Navi_SLIF_Frwinfo : 4|3@0+ (1,0) [0|0] "" CGW,CLU,HUD + SG_ Navi_SLIF_LinkClass : 7|3@0+ (1,0) [0|0] "" CGW,CLU,HUD + SG_ Navi_SLIF_SpdLimit : 15|8@0+ (1,0) [1|254] "" CGW,CLU,HUD + SG_ Navi_SLIFMapSource : 29|4@0+ (1,0) [0|8] "" CGW,CLU,HUD + SG_ Navi_SLIF_CountryCode : 23|10@0+ (1,0) [0|0] "" CGW,CLU,HUD + +BO_ 52 HU_DATC_E_02: 8 H_U + SG_ HU_DATC_DrTempUpDn : 1|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_PsTempUpDn : 3|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_RlTempUpDn : 5|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_RrTempUpDn : 7|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_MainBlower : 11|4@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_SubBlower : 15|4@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_RearBlower : 19|4@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATCRearPsModeSet : 23|4@0+ (1,0) [0|0] "" CGW,CLU + SG_ HU_DATC_FrontModeSet : 27|4@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_RearModeSet : 31|4@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_AutoSet : 33|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_OffReq : 35|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_IntakeSet : 37|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_RearOnOffSet : 39|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_AcSet : 41|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_AqsSet : 43|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_FrontDefog : 45|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_RearDefog : 47|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_ZoneControl : 49|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ HU_DATC_CO2Set : 51|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ DATC_SmartVentOnOffSet : 53|2@0+ (1,0) [0|0] "" CGW,CLU,DATC,IPM + SG_ DATC_ADSOnOffSet : 55|2@0+ (1,0) [0|0] "" CGW,CLU + SG_ HU_DATC_RearAutoDisp : 57|2@0+ (1,0) [0|0] "" CGW,CLU + SG_ HU_DATC_RearOffDisp : 59|2@0+ (1,0) [0|0] "" CGW,CLU + +BO_ 308 DATC_PE_05: 8 CLU + SG_ DATC_PwrInfo : 3|4@0+ (1,0) [0|0] "" AMP,AVM,CUBIS,H_U,MON + SG_ DATC_AltL : 5|2@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_CarInfo : 7|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_ParkingBrake : 9|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_LowFuelWarn : 11|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_Rear_Off_Disp : 13|2@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_Rear_AutoDisp : 15|2@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_Rear_BlowerDisp : 19|4@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_DrSeatWarmerDisp : 22|3@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_SyncDisp : 27|4@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_RearDispCtrl : 31|4@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_RearDrModeDisp : 35|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_PsSeatWarmerDisp : 38|3@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_DrVentSeatDisp : 42|3@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_PSVentSeatDisp : 46|3@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_RrDefLed : 49|2@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_SmartVentOnOffStatus : 51|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_ADSOnOffStatus : 53|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_AcDisp_OSD : 55|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_PsModeDisp_OSD : 59|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_ModeDisp_OSD : 63|4@0+ (1,0) [0|0] "" H_U + +BO_ 307 DATC_PE_04: 8 CLU + SG_ DATC_DiagMode : 1|2@0+ (1,0) [0|0] "" H_U,IBOX,MON + SG_ DATC_Rear_ChangeReqDisp : 3|2@0+ (1,0) [0|0] "" H_U,IBOX,MON + SG_ DATC_Rear_ClimateScnDisp : 5|2@0+ (1,0) [0|0] "" H_U,IBOX,MON + SG_ DATC_CO2OnOffStatus : 7|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_SelfDiagDisp : 15|8@0+ (1,0) [0|0] "" H_U,IBOX,MON + SG_ DATC_RearBlwDisp_OSD : 19|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_AqsLevelOut : 23|4@0+ (1,0) [0|0] "" H_U,IBOX,MON + SG_ DATC_RearModeDisp : 27|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_RearPsModeDisp : 31|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_FrontBlwDisp_Ps : 35|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_AutoDisp_Ps : 39|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_RearModeDisp_OSD : 43|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_RearPSModeDisp_OSD : 47|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_FrontBlwDisp_OSD : 51|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_FrontBlwDispPs_OSD : 55|4@0+ (1,0) [0|0] "" H_U + SG_ DATC_Variant : 63|8@0+ (1,0) [0|0] "" H_U,IBOX,MON + +BO_ 306 DATC_PE_03: 8 CLU + SG_ DATC_ModeDisp : 3|4@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_TempUnit : 5|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_AutoDisp : 9|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_IntakeDisp : 11|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_ChangeReqDisp : 13|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_AcDisp : 17|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_AqsDisp : 19|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_ClimateScnDisp : 21|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_DualDisp : 25|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_OffDisp : 27|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_OpSts : 30|3@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_RearManual : 33|2@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_FrDefLed : 37|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_SmartVentDisp : 39|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_AutoDefogBlink : 41|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_ADSDisp : 43|2@0+ (1,0) [0|0] "" H_U + SG_ DATC_IonClean : 45|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_CO2Warning : 47|2@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_SubBlowerDisp : 51|4@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_BeepReq : 55|4@0+ (1,0) [0|0] "" H_U,KBD,MON + SG_ DATC_MainBlowerDisp : 59|4@0+ (1,0) [0|0] "" H_U,IBOX + SG_ DATC_PsModeDisp : 63|4@0+ (1,0) [0|0] "" H_U,IBOX + +BO_ 1329 DATC_P_02: 8 CLU + SG_ DATC_AmbientTemp_C : 7|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_AmbientTemp_F : 23|8@0+ (1,0) [0|0] "" H_U,MON + +BO_ 305 DATC_PE_02: 8 CLU + SG_ DATC_DrTempDispC : 7|8@0+ (0.5,14) [15|32] "C" H_U,IBOX,MON + SG_ DATC_Rear_DrTempDispC : 15|8@0+ (0.5,14) [15|32] "C" H_U,IBOX,MON + SG_ DATC_DrTempDispF : 23|8@0+ (1,56) [58|90] "F" H_U,IBOX,MON + SG_ DATC_Rear_DrTempDispF : 31|8@0+ (1,56) [58|90] "F" H_U,IBOX,MON + SG_ DATC_PsTempDispC : 39|8@0+ (0.5,14) [15|32] "C" H_U,IBOX,MON + SG_ Datc_RearPsTempDispC : 47|8@0+ (0.5,14) [15|32] "C" H_U,IBOX,MON + SG_ DATC_PsTempDispF : 55|8@0+ (1,56) [58|90] "F" H_U,IBOX,MON + SG_ DATC_RearPsTempDispF : 63|8@0+ (1,56) [58|90] "F" H_U,IBOX,MON + +BO_ 304 DATC_PE_01: 8 CLU + SG_ DATC_Type : 7|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_VerMMMajor : 15|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_VerMMMinor : 23|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_VerBDFMajor : 31|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_VerBDMinor : 39|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_VerCSMajor : 47|8@0+ (1,0) [0|0] "" H_U,MON + SG_ DATC_VerCSMinor : 55|8@0+ (1,0) [0|0] "" H_U,MON + +BO_ 291 HU_CLU_PE_07: 8 H_U + SG_ NV_DS_Curve : 3|4@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_Merge : 7|4@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_RailCross : 9|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_FallingRocks : 11|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_SchoolZone : 13|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_AccidentBlack : 15|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_SpeedBump : 17|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_RoadKill : 19|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_Downhill : 21|2@0+ (1,0) [0|0] "" CLU + SG_ NV_DS_Fog : 23|2@0+ (1,0) [0|0] "" CLU + SG_ NV_Display_TG : 31|2@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_Charge : 39|16@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_Charge_Unit : 55|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ TBT_BarGraph100Level : 63|8@0+ (1,0) [0|100] "%" CLU,HUD + +BO_ 290 HU_CLU_PE_06: 8 H_U + SG_ NV_SD_SpdLimit2 : 3|4@0+ (10,0) [0|0] "km/h" CLU + SG_ NV_SD_SpdLimit1 : 7|4@0+ (10,0) [0|0] "km/h" CLU + SG_ NV_SD_EtcCam : 11|4@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_SpdLimit3 : 15|4@0+ (10,0) [0|0] "km/h" CLU + SG_ NV_SD_SignCam : 17|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_SignOverCam : 19|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_MobileCam : 21|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_FixedCam : 23|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_OverLoadCam : 25|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_ParkCam : 27|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_CutInCam : 29|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_BusOnlyCam : 31|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_ShoulderCam : 35|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_TrafficCam : 37|2@0+ (1,0) [0|0] "" CLU + SG_ NV_SD_PlateRcgCam : 39|2@0+ (1,0) [0|0] "" CLU + +BO_ 286 HU_CLU_PE_10: 8 H_U + SG_ Navi_TBTInfo : 63|8@0+ (1,0) [0|0] "" CGW,CLU + +BO_ 29 CLU_HU_E_00: 8 CLU + SG_ SYS_CLUVer : 7|16@0+ (1,0) [0|0] "" CUBIS,H_U + SG_ CLU_ClockInfoReq : 17|2@0+ (1,0) [0|0] "" H_U + SG_ CLU_DateInfoReq : 19|2@0+ (1,0) [0|0] "" H_U + +BO_ 27 AMP_HU_E_00: 8 AMP + SG_ SYS_AMPVer : 7|16@0+ (1,0) [0|0] "" H_U + +BO_ 23 HU_IPM_E_00: 8 H_U + SG_ C_ADrLNValueSet : 2|3@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ADrUNValueSet : 5|3@0+ (1,0) [0|0] "" DATC,IPM + SG_ SYS_Ver_Req : 7|2@0+ (1,0) [0|0] "" AMP,AVM,CLU,CUBIS,DATC,IPM + SG_ C_IMSRValueReq : 9|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_PSMNValueSet : 11|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_SCMNValueSet : 13|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ADrLURValueReq : 15|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ABuzzerNValueSet : 17|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_AlarmRValueReq : 19|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ArmWKeyNValueSet : 21|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_TwUnRValueReq : 23|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_TwUnNValueSet : 25|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_AutoMRFoldRValueReq : 27|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_AutoMRFoldNValueSet : 29|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ADrLRValueReq : 31|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ArmWKeyRValueReq : 33|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ABuzzerRValueReq : 35|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_ADrURValueReq : 37|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_PSMRValueReq : 39|2@0+ (1,0) [0|0] "" DATC,IPM + SG_ C_SCMRValueReq : 47|2@0+ (1,0) [0|0] "" DATC,IPM + +BO_ 277 HU_CLU_PE_02: 8 H_U + SG_ TBT_Display_Type : 7|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ TBT_Side_Street : 15|16@0+ (1,0) [0|0] "" CLU,HUD + SG_ TBT_Direction : 31|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ TBT_Distance_Turn_Point : 39|16@0+ (1,0) [0|0] "m" CLU,HUD + SG_ TBT_Combined_Side_Street : 51|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ TBT_Scale : 55|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ TBT_DistancetoTurnPoint : 59|4@0+ (1,0) [0|0] "times" CLU,HUD + SG_ TBT_Bar_Graph_Level : 63|4@0+ (10,0) [0|100] "" CLU,HUD + +BO_ 276 HU_CLU_PE_01: 8 H_U + SG_ HU_OpState : 6|7@0+ (1,0) [0|0] "" AMP,CLU + SG_ HU_Navi_On_Off : 7|1@0+ (1,0) [0|0] "" CLU,HUD + SG_ HU_Preset_Number : 12|5@0+ (1,1) [1|30] "" AMP,CLU + SG_ HU_Tuner_Area : 15|3@0+ (1,0) [0|0] "" AMP,CLU + SG_ HU_Track_Number : 23|16@0+ (1,0) [0|0] "" CLU + SG_ HU_Play_time_Sec : 39|6@0+ (1,0) [0|0] "" CLU + SG_ HU_Play_time_Min : 33|7@0+ (1,0) [0|0] "" CLU + SG_ HU_Play_time_Hour : 42|6@0+ (1,0) [0|0] "" CLU + SG_ HU_Disc_select_No : 59|4@0+ (1,0) [0|0] "" CLU + SG_ HU_Frequency : 52|9@0+ (1,0) [0|0] "" AMP,CLU + +BO_ 17 HU_AMP_E_10: 8 H_U + SG_ AMP_Beep2VolumeStep : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep2Frequency : 15|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep2Ch_OutputMask : 31|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep2DurationOn : 47|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep2DurationOff : 55|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep2NumberOfCycles : 63|8@0+ (1,0) [0|0] "" AMP + +BO_ 15 HU_AMP_E_08: 8 H_U + SG_ AMP_MainVolumeSet : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_BalanceSet : 15|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_FadeSet : 23|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_BassSet : 31|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_MidSet : 39|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_TrebleSet : 47|8@0+ (1,0) [0|0] "" AMP + +BO_ 14 HU_AMP_E_07: 8 H_U + SG_ AMP_HFVolumeStep : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_HFMainAudioCut : 15|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_HFChannelOutputMask : 23|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_HFChannelMuteMask : 39|16@0+ (1,0) [0|0] "" AMP + +BO_ 13 HU_AMP_E_06: 8 H_U + SG_ AMP_MTSVolumeStep : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_MTSMainAudioCut : 15|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_MTSChannelOutputMask : 23|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_MTSChannelMuteMask : 39|16@0+ (1,0) [0|0] "" AMP + +BO_ 12 HU_AMP_E_05: 8 H_U + SG_ AMP_NaviVolumeStep : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_NaviMainAudioCut : 15|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_NaviChannelOutputMask : 23|16@0+ (1,0) [0|0] "" AMP + SG_ AMP_NaviChannelMuteMask : 39|16@0+ (1,0) [0|0] "" AMP + +BO_ 11 HU_AMP_E_04: 8 H_U + SG_ AMP_Drive : 1|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_ConvertibleTop : 5|2@0+ (1,0) [0|0] "" AMP + +BO_ 10 HU_AMP_E_03: 8 H_U + SG_ AMP_CrtVehicleID : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_SPDIFMode : 11|4@0+ (1,0) [0|0] "" AMP + SG_ AMP_VersionReq : 17|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_UpdateStart : 25|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_UpdateEnd : 33|2@0+ (1,0) [0|0] "" AMP + +BO_ 9 HU_AMP_E_02: 8 H_U + SG_ AMP_Mute : 1|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_RearSpMute : 3|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_SurroundMode : 5|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_VEQMode : 7|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_AudioMode : 15|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_EQ : 17|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_Reset : 19|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_SPDIFMute : 21|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_DefaultBeep1 : 25|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_DefaultBeep2 : 29|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_BeatsMode : 33|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_VIPMode : 35|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_QLSMode : 37|2@0+ (1,0) [0|0] "" AMP + +BO_ 1288 HU_CLU_P_02: 8 H_U + SG_ NV_TIME_TYPE : 3|4@0+ (1,0) [0|0] "" CLU + SG_ NV_Hour : 15|8@0+ (1,0) [0|0] "" CLU + SG_ NV_Min : 23|8@0+ (1,0) [0|0] "" CLU + +BO_ 8 HU_AMP_E_01: 8 H_U + SG_ AMP_HFMode : 1|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_NaviMode : 3|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_MTSMode : 5|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_VSCMode : 7|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep1Mode : 9|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_Beep2Mode : 11|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_SDVCStep : 14|3@0+ (1,0) [0|0] "" AMP + SG_ AMP_ASDMode : 18|3@0+ (1,0) [0|0] "" AMP + SG_ AMP_SignalDoctor : 20|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_AutoVolume : 22|2@0+ (1,0) [0|0] "" AMP + +BO_ 1287 HU_CLU_P_01: 8 H_U + SG_ NV_DistToTurn_F1 : 3|4@0+ (1,0) [0|0] "" CLU + SG_ NV_DistToTurn_Unit : 7|4@0+ (1,0) [0|0] "" CLU + SG_ NV_DistToTurn_F3 : 11|4@0+ (1,0) [0|0] "" CLU + SG_ NV_DistToTurn_F2 : 15|4@0+ (1,0) [0|0] "" CLU + SG_ NV_DistToTurn_I1 : 23|16@0+ (1,0) [0|0] "" CLU + SG_ NV_DistToTurn_I2 : 39|16@0+ (1,0) [0|0] "" CLU + SG_ NV_DistToTurn_I3 : 55|16@0+ (1,0) [0|0] "" CLU + +BO_ 1286 HU_CLU_P_00: 8 H_U + SG_ NV_EstDist_F : 3|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_EstDist_Unit : 7|4@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_EstHour : 15|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_EstMin : 23|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_Azimuth : 31|8@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_EstDist_I : 39|16@0+ (1,0) [0|0] "" CLU,HUD + SG_ NV_EstimTimeType : 49|2@0+ (1,0) [0|0] "" CGW,CLU,HUD + SG_ NV_EstimTimeFormat : 51|2@0+ (1,0) [0|0] "" CGW,CLU,HUD + +BO_ 1284 HU_AMP_P_01: 8 H_U + SG_ HU_VehicleSpeed : 7|8@0+ (1,0) [0|0] "" AMP + SG_ AMP_SetMaxMainVolStep : 9|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_LKASWarningOn : 21|2@0+ (1,0) [0|0] "" AMP + SG_ AMP_BSDWarningOn : 23|2@0+ (1,0) [0|0] "" AMP + +BO_ 256 HU_MON_PE_01: 8 H_U + SG_ HU_Type : 7|8@0+ (1,0) [0|0] "" AMP,CGW,CLU,HUD,KMA_TMU + SG_ HU_VerMajor : 15|8@0+ (1,0) [0|0] "" AMP,CLU,KMA_TMU,MON + SG_ HU_VerMinor : 23|8@0+ (1,0) [0|0] "" AMP,CLU,KMA_TMU,MON + SG_ HU_DistributeInfo : 31|8@0+ (1,0) [0|0] "" AMP,CGW,CLU,KMA_TMU,MON,RRC + SG_ HU_SubVerMajor : 39|8@0+ (1,0) [0|0] "" AMP,MON + SG_ HU_SubVerMinor : 47|8@0+ (1,0) [0|0] "" AMP,MON + SG_ HU_SDARSVersion : 55|8@0+ (1,0) [0|0] "" AMP,MON + SG_ HU_AdasSupport : 58|3@0+ (1,0) [0|0] "" CGW,CLU + +BO_ 1092 NM_CLOCK: 8 CLOCK + SG_ Destination_CLOCK : 7|8@0+ (1,0) [0|0] "" HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_CLOCK : 13|2@0+ (1,0) [0|0] "" HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_CLOCK : 10|3@0+ (1,0) [0|0] "" HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1108 NM_HUD: 8 HUD + SG_ Destination_HUD : 7|8@0+ (1,0) [0|0] "" CLOCK,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_HUD : 13|2@0+ (1,0) [0|0] "" CLOCK,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_HUD : 10|3@0+ (1,0) [0|0] "" CLOCK,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1088 NM_H_U: 8 H_U + SG_ Destination_H_U : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_H_U : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_H_U : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1091 NM_DATC: 8 DATC + SG_ Destination_DATC : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_DATC : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_DATC : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1105 NM_CCP: 8 CCP + SG_ Destination_CCP : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_CCP : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_CCP : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1100 NM_KMA_TMU: 8 KMA_TMU + SG_ Destination_KMA_TMU : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_KMA_TMU : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_KMA_TMU : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1098 NM_CUBIS: 8 CUBIS + SG_ Destination_CUBIS : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_CUBIS : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_CUBIS : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1099 NM_TMU: 8 TMU + SG_ Destination_TMU : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_TMU : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_TMU : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1095 NM_IPM: 8 IPM + SG_ Destination_IPM : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_IPM : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_IPM : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1107 NM_RSE_R: 8 RSE_R + SG_ Destination_RSE_R : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_RSE_R : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_RSE_R : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1093 NM_RRC: 8 RRC + SG_ Destination_RRC : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_RRC : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_RRC : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1109 NM_CGW: 8 CGW + SG_ Destination_CGW : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_CGW : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_CGW : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1106 NM_RSE_L: 8 RSE_L + SG_ Destination_RSE_L : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_RSE_L : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_RSE_L : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1096 NM_AMP: 8 AMP + SG_ Destination_AMP : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_AMP : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_AMP : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1103 NM_EDT: 8 EDT + SG_ Destination_EDT : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_EDT : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_EDT : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1110 NM_SWRC: 8 SWRC + SG_ Destination_SWRC : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_SWRC : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_SWRC : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,IBOX,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1102 NM_IBOX: 8 IBOX + SG_ Destination_IBOX : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_IBOX : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,CLU,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_IBOX : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,CLU,FHCU,ASD,MON,AVM,KBD + +BO_ 1101 NM_CLU: 8 CLU + SG_ Destination_CLU : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,FHCU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_CLU : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,FHCU,ASD,MON,AVM,KBD + SG_ NMCommandCode_CLU : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,FHCU,ASD,MON,AVM,KBD + +BO_ 1097 NM_FHCU: 8 FHCU + SG_ Destination_FHCU : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,ASD,MON,AVM,KBD + SG_ NMSleepFlag_FHCU : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,ASD,MON,AVM,KBD + SG_ NMCommandCode_FHCU : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,ASD,MON,AVM,KBD + +BO_ 1094 NM_ASD: 8 ASD + SG_ Destination_ASD : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,MON,AVM,KBD + SG_ NMSleepFlag_ASD : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,MON,AVM,KBD + SG_ NMCommandCode_ASD : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,MON,AVM,KBD + +BO_ 1089 NM_MON: 8 MON + SG_ Destination_MON : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,AVM,KBD + SG_ NMSleepFlag_MON : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,AVM,KBD + SG_ NMCommandCode_MON : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,AVM,KBD + +BO_ 1104 NM_AVM: 8 AVM + SG_ Destination_AVM : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,KBD + SG_ NMSleepFlag_AVM : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,KBD + SG_ NMCommandCode_AVM : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,KBD + +BO_ 1090 NM_KBD: 8 KBD + SG_ Destination_KBD : 7|8@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM + SG_ NMSleepFlag_KBD : 13|2@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM + SG_ NMCommandCode_KBD : 10|3@0+ (1,0) [0|0] "" CLOCK,HUD,H_U,DATC,CCP,KMA_TMU,CUBIS,TMU,IPM,RSE_R,RRC,CGW,RSE_L,AMP,EDT,SWRC,IBOX,CLU,FHCU,ASD,MON,AVM + diff --git a/opendbc_repo/opendbc/dbc/hyundai_i30_2014.dbc b/opendbc_repo/opendbc/dbc/hyundai_i30_2014.dbc new file mode 100644 index 0000000000..3524f9b21a --- /dev/null +++ b/opendbc_repo/opendbc/dbc/hyundai_i30_2014.dbc @@ -0,0 +1,549 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 128 EMS_DCT1: 8 XXX + SG_ PV_AV_CAN : 0|8@1+ (0.3906,0) [0|99.603] "%" XXX + SG_ TQ_STND : 8|6@1+ (10,0) [0|630] "Nm" XXX + SG_ F_N_ENG : 14|1@1+ (1,0) [0|1] "" XXX + SG_ F_SUB_TQI : 15|1@1+ (1,0) [0|1] "" XXX + SG_ N : 16|16@1+ (0.25,0) [0|16383.8] "rpm" XXX + SG_ TQI_ACOR : 32|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQFR : 40|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQI : 48|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ CF_Ems_Alive : 56|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Ems_ChkSum : 60|4@1+ (1,0) [0|15] "" XXX + + +BO_ 129 EMS_DCT2: 8 XXX + SG_ CR_Ems_SoakTimeExt : 0|6@1+ (5,0) [0|315] "Min" XXX + SG_ BRAKE_ACT : 6|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Ems_EngOperStat : 8|8@1+ (1,0) [0|255] "" XXX + SG_ CR_Ems_IndAirTemp : 16|8@1+ (0.75,-48) [-48|143.25] "" XXX + SG_ CF_Ems_Alive2 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Ems_ChkSum2 : 60|4@1+ (1,0) [0|15] "" XXX + + +BO_ 160 EngFrzFrm1: 8 XXX + SG_ PID_04h : 0|8@1+ (0.392157,0) [0|100] "%" XXX + SG_ PID_05h : 8|8@1+ (1,-40) [-40|215] "" XXX + SG_ PID_0Ch : 16|16@1+ (0.25,0) [0|16383.8] "rpm" XXX + SG_ PID_0Dh : 32|8@1+ (1,0) [0|255] "km/h" XXX + SG_ PID_11h : 40|8@1+ (0.392157,0) [0|100] "%" XXX + SG_ PID_03h : 48|16@1+ (1,0) [0|65535] "" XXX + + +BO_ 161 EngFrzFrm2: 8 XXX + SG_ PID_06h : 0|8@1+ (0.78125,-100) [-100|99.22] "%" XXX + SG_ PID_07h : 8|8@1+ (0.78125,-100) [-100|99.22] "%" XXX + SG_ PID_08h : 16|8@1+ (0.78125,-100) [-100|99.22] "%" XXX + SG_ PID_09h : 24|8@1+ (0.78125,-100) [-100|99.22] "%" XXX + SG_ PID_0Bh : 32|8@1+ (1,0) [0|255] "kPa" XXX + SG_ PID_23h : 40|16@1+ (10,0) [0|655350] "kPa" XXX + + +BO_ 304 YRS1: 8 XXX + SG_ CR_Yrs_Yr : 0|16@1+ (0.005,-163.84) [-163.84|163.83] "" XXX + SG_ CF_Yrs_SnsStat1 : 16|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Yrs_YrStat : 20|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Yrs_LatAc : 32|16@1+ (0.000127465,-4.17677) [-4.17677|4.17652] "g" XXX + SG_ CR_Yrs_MsgCnt1 : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Yrs_LatAcStat1 : 52|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Yrs_Crc1 : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 305 YRS3: 8 XXX + SG_ CR_Yrs_YawAcc : 0|16@1+ (0.125,-4096) [-4096|4095.75] "" XXX + SG_ CF_Yrs_YawAccStat : 20|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Yrs_Ax : 32|16@1+ (0.000127465,-4.17677) [-4.17677|4.17652] "g" XXX + SG_ CR_Yrs_MsgCnt3 : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Yrs_AxStat : 52|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Yrs_Crc3 : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 320 YRS2: 8 XXX + SG_ CF_Yrs_McuStat : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CF_Yrs_SnsStat2 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ CF_Yrs_ExtSysStat : 32|8@1+ (1,0) [0|255] "" XXX + SG_ CR_Yrs_Diag : 40|8@1+ (1,0) [0|255] "" XXX + SG_ CR_Yrs_MsgCnt2 : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Yrs_Type : 52|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Yrs_Crc2 : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 339 TCS1: 8 XXX + SG_ TCS_REQ : 0|1@1+ (1,0) [0|1] "" XXX + SG_ MSR_C_REQ : 1|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_PAS : 2|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_GSC : 3|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Esc_LimoInfo : 4|2@1+ (1,0) [0|3] "" XXX + SG_ ABS_DIAG : 6|1@1+ (1,0) [0|1] "" XXX + SG_ ABS_DEF : 7|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_DEF : 8|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_CTL : 9|1@1+ (1,0) [0|1] "" XXX + SG_ ABS_ACT : 10|1@1+ (1,0) [0|1] "" XXX + SG_ EBD_DEF : 11|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_PAS : 12|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_DEF : 13|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_CTL : 14|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_MFRN : 15|1@1+ (1,0) [0|1] "" XXX + SG_ DBC_CTL : 16|1@1+ (1,0) [0|1] "" XXX + SG_ DBC_PAS : 17|1@1+ (1,0) [0|1] "" XXX + SG_ DBC_DEF : 18|1@1+ (1,0) [0|1] "" XXX + SG_ HAC_CTL : 19|1@1+ (1,0) [0|1] "" XXX + SG_ HAC_PAS : 20|1@1+ (1,0) [0|1] "" XXX + SG_ HAC_DEF : 21|1@1+ (1,0) [0|1] "" XXX + SG_ ESS_STAT : 22|2@1+ (1,0) [0|3] "" XXX + SG_ TQI_TCS : 24|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQI_MSR : 32|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQI_SLW_TCS : 40|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ CF_Esc_BrkCtl : 48|1@1+ (1,0) [0|1] "" XXX + SG_ ESC_OFF_STEP : 49|2@1+ (1,0) [0|3] "" XXX + SG_ _4WD_Status : 51|1@1+ (1,0) [0|1] "" XXX + SG_ AliveCounter_TCS1 : 52|4@1+ (1,0) [0|1] "" XXX + SG_ CheckSum_TCS1 : 56|8@1+ (1,0) [0|1] "" XXX + + +BO_ 356 VSM1: 8 XXX + SG_ CR_Esc_StrTqReq : 0|12@1+ (0.01,-20.48) [-20.48|20.47] "Nm" XXX + SG_ CF_Esc_Act : 12|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Esc_CtrMode : 13|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Esc_Def : 16|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Esc_AliveCnt : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Esc_Chksum : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 357 VSM2: 8 XXX + SG_ CR_Mdps_StrTq : 0|12@1+ (0.01,-20.48) [-20.48|20.47] "Nm" XXX + SG_ CR_Mdps_OutTq : 12|12@1+ (0.1,-204.8) [-204.8|204.7] "" XXX + SG_ CF_Mdps_Def : 24|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Mdps_SErr : 25|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Mdps_AliveCnt : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Mdps_Chksum : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 399 EMS_H2: 8 XXX + SG_ R_TqAcnApvC : 0|8@1+ (0.2,0) [0|51] "Nm" XXX + SG_ R_PAcnC : 8|8@1+ (125,0) [0|31875] "hPa" XXX + SG_ TQI_B : 16|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ SLD_VS : 24|8@1+ (1,0) [0|255] "km/h" XXX + SG_ CF_CdaStat : 32|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Ems_IsgStat : 35|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Ems_OilChg : 38|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_EtcLimpMod : 39|1@1+ (1,0) [0|1] "" XXX + SG_ R_NEngIdlTgC : 40|8@1+ (10,0) [0|2550] "rpm" XXX + SG_ CF_Ems_UpTarGr : 48|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_DownTarGr : 49|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_DesCurGr : 50|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Ems_SldAct : 54|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_SldPosAct : 55|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_HPresStat : 56|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_IsgBuz : 57|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_IdlStpFCO : 58|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_FCopen : 59|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_ActEcoAct : 60|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_EngRunNorm : 61|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_IsgStat2 : 62|2@1+ (2,0) [0|3] "" XXX + + +BO_ 497 TCS5: 8 XXX + SG_ ABS_W_LAMP : 0|1@1+ (1,0) [0|1] "" XXX + SG_ EBD_W_LAMP : 1|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_OFF_LAMP : 2|1@1+ (1,0) [0|1] "" XXX + SG_ TCS_LAMP : 3|2@1+ (1,0) [0|3] "" XXX + SG_ DBC_W_LAMP : 5|1@1+ (1,0) [0|1] "" XXX + SG_ DBC_F_LAMP : 6|2@1+ (1,0) [0|3] "" XXX + SG_ ODOMETER_LEFT : 8|4@1+ (1,0) [0|15] "m" XXX + SG_ ODOMETER_RIGHT : 12|4@1+ (1,0) [0|15] "m" XXX + SG_ WHEEL_FL : 16|12@1+ (0.125,0) [0|511.875] "km/h" XXX + SG_ WHEEL_FR : 28|12@1+ (0.125,0) [0|511.875] "km/h" XXX + SG_ WHEEL_RL : 40|12@1+ (0.125,0) [0|511.875] "km/h" XXX + SG_ WHEEL_RR : 52|12@1+ (0.125,0) [0|511.875] "km/h" XXX + + +BO_ 544 ESP2: 8 XXX + SG_ LAT_ACCEL : 0|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX + SG_ ESP2_AliveCounter_LSB : 11|3@1+ (1,0) [0|7] "" XXX + SG_ LAT_ACCEL_STAT : 14|1@1+ (1,0) [0|1] "" XXX + SG_ LAT_ACCEL_DIAG : 15|1@1+ (1,0) [0|1] "" XXX + SG_ LONG_ACCEL : 16|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" XXX + SG_ ESP2_AliveCounter_MSB : 27|1@1+ (1,0) [0|1] "" XXX + SG_ ESP2_Checksum_LSB : 28|2@1+ (1,0) [0|3] "" XXX + SG_ LONG_ACCEL_STAT : 30|1@1+ (1,0) [0|1] "" XXX + SG_ LONG_ACCEL_DIAG : 31|1@1+ (1,0) [0|1] "" XXX + SG_ CYL_PRES : 32|12@1+ (0.1,0) [0|409.5] "Bar" XXX + SG_ ESP12_Checksum_MSB : 44|2@1+ (1,0) [0|3] "" XXX + SG_ CYL_PRES_STAT : 46|1@1+ (1,0) [0|1] "" XXX + SG_ CYL_PRESS_DIAG : 47|1@1+ (1,0) [0|1] "" XXX + SG_ YAW_RATE : 48|13@1+ (0.01,-40.95) [-40.95|40.96] "" XXX + SG_ CYL_PRES_FLAG : 61|1@1+ (1,0) [0|1] "" XXX + SG_ YAW_RATE_STAT : 62|1@1+ (1,0) [0|1] "" XXX + SG_ YAW_RATE_DIAG : 63|1@1+ (1,0) [0|1] "" XXX + + +BO_ 608 EMS6: 8 XXX + SG_ TQI_MIN : 0|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQI : 8|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQI_TARGET : 16|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ GLOW_STAT : 24|1@1+ (1,0) [0|1] "" XXX + SG_ CRUISE_LAMP_M : 25|1@1+ (1,0) [0|1] "" XXX + SG_ CRUISE_LAMP_S : 26|1@1+ (1,0) [0|1] "" XXX + SG_ PRE_FUEL_CUT_IN : 27|1@1+ (1,0) [0|1] "" XXX + SG_ ENG_STAT : 28|3@1+ (1,0) [0|7] "" XXX + SG_ SOAK_TIME_ERROR : 31|1@1+ (1,0) [0|1] "" XXX + SG_ SOAK_TIME : 32|8@1+ (1,0) [0|255] "Min" XXX + SG_ TQI_MAX : 40|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ SPK_TIME_CUR : 48|8@1+ (0.375,-35.625) [-35.625|60] "" XXX + SG_ Checksum : 56|4@1+ (1,0) [0|15] "" XXX + SG_ AliveCounter : 60|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Ems_AclAct : 62|2@1+ (1,0) [0|3] "" XXX + + +BO_ 672 EMS5: 8 XXX + SG_ ECGPOvrd : 0|1@1+ (1,0) [0|1] "" XXX + SG_ QECACC : 1|1@1+ (1,0) [0|1] "" XXX + SG_ ECFail : 2|1@1+ (1,0) [0|1] "" XXX + SG_ SwitchOffCondExt : 3|1@1+ (1,0) [0|1] "" XXX + SG_ BLECFail : 4|1@1+ (1,0) [0|1] "" XXX + SG_ AliveCounter : 5|2@1+ (1,0) [0|3] "" XXX + SG_ Byte0Parity : 7|1@1+ (1,0) [0|1] "" XXX + SG_ FA_PV_CAN : 8|8@1+ (0.3906,0) [0|99.2] "%" XXX + SG_ IntAirTemp : 16|8@1+ (0.75,-48) [-48|143.25] "" XXX + SG_ STATE_DC_OBD : 24|7@1+ (1,0) [0|127] "" XXX + SG_ INH_DC_OBD : 31|1@1+ (1,0) [0|1] "" XXX + SG_ CTR_IG_CYC_OBD : 32|16@1+ (1,0) [0|65535] "" XXX + SG_ CTR_CDN_OBD : 48|16@1+ (1,0) [0|65535] "" XXX + + +BO_ 688 SAS1: 8 XXX + SG_ SAS_Angle : 0|16@1+ (0.1,0) [-3276.8|3276.7] "Deg" XXX + SG_ SAS_Speed : 16|8@1+ (4,0) [0|1016] "" XXX + SG_ SAS_Stat : 24|8@1+ (1,0) [0|255] "" XXX + SG_ MsgCount : 32|4@1+ (1,0) [0|15] "" XXX + SG_ CheckSum : 36|4@1+ (1,0) [0|15] "" XXX + + +BO_ 790 EMS1: 8 XXX + SG_ SWI_IGK : 0|1@1+ (1,0) [0|1] "" XXX + SG_ F_N_ENG : 1|1@1+ (1,0) [0|1] "" XXX + SG_ ACK_TCS : 2|1@1+ (1,0) [0|1] "" XXX + SG_ PUC_STAT : 3|1@1+ (1,0) [0|1] "" XXX + SG_ TQ_COR_STAT : 4|2@1+ (1,0) [0|3] "" XXX + SG_ RLY_AC : 6|1@1+ (1,0) [0|1] "" XXX + SG_ F_SUB_TQI : 7|1@1+ (1,0) [0|1] "" XXX + SG_ TQI_ACOR : 8|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ N : 16|16@1+ (0.25,0) [0|16383.8] "rpm" XXX + SG_ TQI : 32|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ TQFR : 40|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ VS : 48|8@1+ (1,0) [0|254] "km/h" XXX + SG_ RATIO_TQI_BAS_MAX_STND : 56|8@1+ (0.0078,0) [0|2] "" XXX + + +BO_ 809 EMS2: 8 XXX + SG_ TQ_STND : 0|6@1+ (10,0) [0|630] "Nm" XXX + SG_ CAN_VERS : 0|6@1+ (1,0) [0|7.7] "" XXX + SG_ CONF_TCU : 0|6@1+ (1,0) [0|63] "" XXX + SG_ OBD_FRF_ACK : 0|6@1+ (1,0) [0|63] "" XXX + SG_ MUL_CODE : 6|2@1+ (1,0) [0|3] "" XXX + SG_ TEMP_ENG : 8|8@1+ (0.75,-48) [-48|143.25] "" XXX + SG_ MAF_FAC_ALTI_MMV : 16|8@1+ (0.00781,0) [0|1.99155] "" XXX + SG_ VB_OFF_ACT : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ACK_ES : 25|1@1+ (1,0) [0|1] "" XXX + SG_ CONF_MIL_FMY : 26|3@1+ (1,0) [0|7] "" XXX + SG_ OD_OFF_REQ : 29|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_ACT : 30|1@1+ (1,0) [0|1] "" XXX + SG_ CLU_ACK : 31|1@1+ (1,0) [0|1] "" XXX + SG_ BRAKE_ACT : 32|2@1+ (1,0) [0|3] "" XXX + SG_ ENG_CHR : 34|4@1+ (1,0) [0|15] "" XXX + SG_ GP_CTL : 38|2@1+ (1,0) [0|3] "" XXX + SG_ TPS : 40|8@1+ (0.469484,-15.0235) [-15.0235|104.695] "%" XXX + SG_ PV_AV_CAN : 48|8@1+ (0.3906,0) [0|99.603] "%" XXX + SG_ ENG_VOL : 56|8@1+ (0.1,0) [0|25.5] "liter" XXX + + +BO_ 848 FATC: 8 XXX + SG_ CR_Fatc_TqAcnOut : 0|8@1+ (0.2,0) [0|50.8] "Nm" XXX + SG_ CF_Fatc_AcnRqSwi : 8|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_AcnCltEnRq : 9|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_EcvFlt : 10|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_BlwrOn : 11|1@1+ (1,0) [0|1] "" XXX + SG_ CF_FATC_Iden : 12|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Fatc_BlwrMax : 14|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_EngStartReq : 15|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_IsgStopReq : 16|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_CtrInf : 17|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Fatc_MsgCnt : 20|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Fatc_OutTemp : 24|8@1+ (0.5,-40) [-40|60] "" XXX + SG_ CR_Fatc_OutTempSns : 32|8@1+ (0.5,-40) [-40|60] "" XXX + SG_ CF_Fatc_Compload : 40|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Fatc_ActiveEco : 43|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_AutoActivation : 44|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_DefSw : 45|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_PtcRlyStat : 46|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Fatc_ChkSum : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 880 TCU3: 8 XXX + SG_ N_TGT_LUP : 0|8@1+ (10,500) [500|3040] "rpm" XXX + SG_ SLOPE_TCU : 8|6@1+ (0.5,-16) [-16|15.5] "%" XXX + SG_ CF_Tcu_InhCda : 14|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_IsgInhib : 15|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_BkeOnReq : 16|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_NCStat : 18|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_TarGr : 20|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Tcu_ShfPatt : 24|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Tcu_InhVis : 28|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_PRelReq : 29|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_ITPhase : 30|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_ActEcoRdy : 31|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_TqGrdLim : 32|8@1+ (10,0) [0|2540] "Nm/s" XXX + SG_ CR_Tcu_IsgTgtRPM : 40|8@1+ (20,0) [0|3500] "rpm" XXX + SG_ TQI_TCU_INC : 48|8@1+ (0.390625,0) [0|99.6094] "%" XXX + SG_ CF_Tcu_SbwPInfo : 56|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_SptRdy : 57|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_Alive3 : 58|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_ChkSum3 : 60|4@1+ (1,0) [0|15] "" XXX + + +BO_ 898 EMS9: 8 XXX + SG_ CF_Ems_BrkReq : 0|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_DnShftReq : 1|4@1+ (1,0) [0|14] "" XXX + SG_ CF_Ems_RepModChk : 5|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Ems_AAFOpenReq : 7|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_DecelReq : 8|12@1+ (0.001,-4.094) [-4.094|0] "m/s^2" XXX + SG_ CR_Ems_BstPre : 20|12@1+ (1.322,0) [0|4094] "hPa" XXX + SG_ CR_Ems_EngOilTemp : 32|8@1+ (0.75,-40) [0|254] "" XXX + SG_ CF_Ems_PumpTPres : 40|8@1+ (3.13725,0) [0|800] "kPa" XXX + SG_ CF_Ems_ModeledAmbTemp : 48|8@1+ (0.5,-41) [-40|60] "" XXX + SG_ CF_Ems_OPSFail : 56|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_ECTTRQLIM : 57|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_AliveCounterEMS9 : 58|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Ems_ChecksumEMS9 : 60|4@1+ (1,0) [0|15] "" XXX + + +BO_ 1075 EPB1: 8 XXX + SG_ EPB_I_LAMP : 0|4@1+ (1,0) [0|15] "" XXX + SG_ EPB_F_LAMP : 4|2@1+ (1,0) [0|3] "" XXX + SG_ EPB_ALARM : 6|2@1+ (1,0) [0|3] "" XXX + SG_ EPB_CLU : 8|8@1+ (1,0) [0|255] "" XXX + SG_ EPB_SWITCH : 16|2@1+ (1,0) [0|3] "" XXX + SG_ EPB_RBL : 18|1@1+ (1,0) [0|1] "" XXX + SG_ EPB_STATUS : 19|3@1+ (1,0) [0|7] "" XXX + SG_ EPB_FRC_ERR : 22|2@1+ (1,0) [0|3] "" XXX + SG_ EPB_DBF_STAT : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_ACK : 25|1@1+ (1,0) [0|1] "" XXX + SG_ EPB_DBF_REQ : 26|1@1+ (1,0) [0|1] "" XXX + SG_ EPB_FAIL : 29|3@1+ (1,0) [0|7] "" XXX + SG_ EPB_FORCE : 32|12@1+ (1,-1000) [-1000|3000] "" XXX + SG_ EPB_DBF_DECEL : 48|8@1+ (0.01,0) [0|2.54] "g" XXX + + +BO_ 1087 TCU1: 8 XXX + SG_ ETL_TCU : 0|8@1+ (2,0) [0|508] "Nm" XXX + SG_ CUR_GR : 8|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Tcu_Alive : 12|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_ChkSum : 14|2@1+ (1,0) [0|3] "" XXX + SG_ VS_TCU : 16|8@1+ (1,0) [0|254] "km/h" XXX + SG_ FAN_CTRL_TCU : 24|2@1+ (1,0) [0|3] "" XXX + SG_ BRAKE_ACT_TCU : 26|2@1+ (1,0) [0|3] "" XXX + SG_ FUEL_CUT_TCU : 28|1@1+ (1,0) [0|1] "" XXX + SG_ INH_FUEL_CUT : 29|1@1+ (1,0) [0|1] "" XXX + SG_ IDLE_UP_TCU : 30|1@1+ (1,0) [0|1] "" XXX + SG_ N_INC_TCU : 31|1@1+ (1,0) [0|1] "" XXX + SG_ SPK_RTD_TCU : 32|8@1+ (0.375,-23.625) [-15|15] "" XXX + SG_ N_TC_RAW : 40|16@1+ (0.25,0) [0|16383.5] "rpm" XXX + SG_ VS_TCU_DECIMAL : 56|8@1+ (0.0078125,0) [0|0.992188] "km/h" XXX + + +BO_ 1088 TCU2: 8 XXX + SG_ ETL_TCU : 0|8@1+ (2,0) [0|508] "Nm" XXX + SG_ CUR_GR : 8|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Tcu_Alive : 12|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_ChkSum : 14|2@1+ (1,0) [0|3] "" XXX + SG_ VS_TCU : 16|8@1+ (1,0) [0|254] "km/h" XXX + SG_ FAN_CTRL_TCU : 24|2@1+ (1,0) [0|3] "" XXX + SG_ BRAKE_ACT_TCU : 26|2@1+ (1,0) [0|3] "" XXX + SG_ FUEL_CUT_TCU : 28|1@1+ (1,0) [0|1] "" XXX + SG_ INH_FUEL_CUT : 29|1@1+ (1,0) [0|1] "" XXX + SG_ IDLE_UP_TCU : 30|1@1+ (1,0) [0|1] "" XXX + SG_ N_INC_TCU : 31|1@1+ (1,0) [0|1] "" XXX + SG_ SPK_RTD_TCU : 32|8@1+ (0.375,-23.625) [-15|15] "" XXX + SG_ N_TC_RAW : 40|16@1+ (0.25,0) [0|16383.5] "rpm" XXX + SG_ VS_TCU_DECIMAL : 56|8@1+ (0.0078125,0) [0|0.992188] "km/h" XXX + + +BO_ 1200 WHL_SPD: 8 XXX + SG_ WHL_SPD_FL : 0|14@1+ (0.03125,0) [0|511.969] "km/h" XXX + SG_ WHL_SPD_FR : 16|14@1+ (0.03125,0) [0|511.969] "km/h" XXX + SG_ WHL_SPD_RL : 32|14@1+ (0.03125,0) [0|511.969] "km/h" XXX + SG_ WHL_SPD_RR : 48|14@1+ (0.03125,0) [0|511.969] "km/h" XXX + + +BO_ 1201 WHL_PUL: 8 XXX + SG_ WHL_PUL_FL : 0|8@1+ (0.5,0) [0|127.5] "pulse count" XXX + SG_ WHL_PUL_FR : 8|8@1+ (0.5,0) [0|127.5] "pulse count" XXX + SG_ WHL_PUL_RL : 16|8@1+ (0.5,0) [0|127.5] "pulse count" XXX + SG_ WHL_PUL_RR : 24|8@1+ (0.5,0) [0|127.5] "pulse count" XXX + SG_ WHL_DIR_FL : 32|2@1+ (1,0) [0|3] "" XXX + SG_ WHL_DIR_FR : 34|2@1+ (1,0) [0|3] "" XXX + SG_ WHL_DIR_RL : 36|2@1+ (1,0) [0|3] "" XXX + SG_ WHL_DIR_RR : 38|2@1+ (1,0) [0|3] "" XXX + SG_ WHL_PUL_Chksum : 56|8@1+ (1,0) [0|255] "" XXX + + +BO_ 1264 CLU1: 8 XXX + SG_ CF_Clu_CruiseSwState : 0|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Blr_MaxStat : 3|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_SldMainSW : 4|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_ParityBit1 : 5|1@1+ (1,0) [0|1] "pulse count" XXX + SG_ CF_Clu_SPEED_UNIT : 6|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_ParkBrakeSw : 7|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_Vanz : 8|9@1+ (0.5,0) [0|255.5] "km/h or MPH" XXX + SG_ CF_Clu_AliveCounter : 17|7@1+ (1,0) [0|127] "" XXX + SG_ CF_Clu_CruiseSwMain : 24|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_VanzDecimal : 25|2@1+ (1,0) [0|0.375] "" XXX + SG_ VEHICLE_INFO : 27|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_StrRlyState : 30|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_SMKOption : 31|1@1+ (1,0) [0|1] "" XXX + SG_ R_TqAcnOutC : 32|8@1+ (1,0) [0|51] "Nm" XXX + SG_ CF_Clu_Odometer : 40|24@1+ (0.1,0) [0|1.67772e+006] "km" XXX + + +BO_ 1265 CLU3: 8 XXX + SG_ CF_Clu_AcnRqSwi : 0|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_AcnCltEnRq : 1|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_RefDetMod : 2|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_DefoggerRly : 5|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_LowfuelWarn : 16|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_SportsModeSwi : 18|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_ALightStat : 20|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_FrtFog : 21|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_DetentOut : 22|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HeadLampTail : 23|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_TrailerMode : 24|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_DTE : 25|10@1+ (1,0) [0|1023] "" XXX + SG_ CF_Clu_TripUnit : 35|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_IsaMainSW : 37|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_FlexSteerSW : 40|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_AvsmCur : 41|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HudSpeedset : 42|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HudTbtSet : 43|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HudSccSet : 44|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HudLdwsSet : 45|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HudDisSet : 46|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HudFontSizeSet : 47|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_HudFontColorSet : 49|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_HudBrightSet : 51|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_HudHeightSet : 53|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_CluInfo : 55|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_RheostatLevel : 56|5@1+ (1,0) [0|31] "" XXX + SG_ CF_Clu_DrivinglampStat : 61|3@1+ (1,0) [0|7] "" XXX + + +BO_ 1349 EMS4: 8 XXX + SG_ IMMO_LAMP_STAT : 0|1@1+ (1,0) [0|1] "" XXX + SG_ L_MIL : 1|1@1+ (1,0) [0|1] "" XXX + SG_ IM_STAT : 2|1@1+ (1,0) [0|1] "" XXX + SG_ AMP_CAN : 3|5@1+ (10.7316,458.98) [458.98|791.66] "mmHg" XXX + SG_ FCO : 8|16@1+ (0.128,0) [0|8388.48] "ul" XXX + SG_ VB : 24|8@1+ (0.101563,0) [0|25.8984] "V" XXX + SG_ TEMP_FUEL : 48|8@1+ (0.75,-48) [-48|143.25] "" XXX + SG_ Split_Stat : 56|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Ems_IsaAct : 57|1@1+ (1,0) [0|1] "" XXX + + +BO_ 1435 TCU4: 8 XXX + SG_ CF_TCU_WarnMsg : 0|3@1+ (1,0) [0|7] "" XXX + SG_ CF_TCU_WarnImg : 3|1@1+ (1,0) [0|1] "" XXX + SG_ CF_TCU_WarnSnd : 4|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_EolStat : 5|1@1+ (1,0) [0|1] "" XXX + SG_ CR_Tcu_GearSelDisp2 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Tcu_StRelStat : 12|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_DriWarn1 : 13|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Tcu_DriWarn2 : 16|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_DrivingModeReq : 18|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Tcu_DrivingModeDisp : 22|4@1+ (1,0) [0|0] "" XXX + SG_ CF_Tcu_SiCluster : 26|5@1+ (1,0) [0|0] "" XXX + SG_ CF_Tcu_DSmode_Inf : 31|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Tcu_Alive4 : 58|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Tcu_ChkSum4 : 60|4@1+ (1,0) [0|15] "" XXX + + +BO_ 1508 MDPS1: 8 XXX + SG_ CF_Mdps_WLmp : 1|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Mdps_ALTRequest : 5|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Mdps_Flex : 8|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Mdps_FlexDisp : 11|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Mdps_CurrMode : 12|2@1+ (1,0) [0|3] "" XXX + + +BO_ 1680 CLU2: 8 XXX + SG_ CF_Clu_IGNSw : 0|3@1+ (1,0) [0|7] "" XXX + SG_ RKE_CMD : 3|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_DrvDrSw : 6|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_DrvKeyLockSw : 8|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_DrvKeyUnlockSw : 9|1@1+ (1,0) [0|1] "" XXX + SG_ PIC_Lock : 10|3@1+ (1,0) [0|7] "" XXX + SG_ PIC_Unlock : 13|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_DrvSeatBeltSw : 16|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_TrunkTgSw : 18|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_AstSeatBeltSw : 20|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_HoodSw : 22|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_TurnSigLh : 24|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_TurnSigRh : 25|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_LdwsLkasSW : 26|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_WiperIntT : 27|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_WiperIntSW : 30|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_WiperLow : 31|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_WiperHigh : 32|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_WiperAuto : 33|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_RainSnsStat : 34|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_HeadLampLow : 37|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HeadLampHigh : 38|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_AltLStatus : 39|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_EcoDriveInf : 40|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_SwiGearR : 43|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_SWL_Stat : 45|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Clu_ActiveEcoSW : 48|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_HazardSW : 49|1@1+ (1,0) [0|1] "" XXX + SG_ CF_Clu_AliveCnt2 : 50|4@1+ (1,0) [0|15] "" XXX + SG_ CF_Clu_AstDrSw : 54|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_LkasDispMode : 56|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_AutoLightLevel : 58|2@1+ (1,0) [0|3] "" XXX + SG_ CF_Clu_SunRoofOpenState : 60|1@1+ (1,0) [0|1] "" XXX + + diff --git a/opendbc_repo/opendbc/dbc/hyundai_kia_generic.dbc b/opendbc_repo/opendbc/dbc/hyundai_kia_generic.dbc new file mode 100644 index 0000000000..f94511ad42 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/hyundai_kia_generic.dbc @@ -0,0 +1,1676 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: IAP ODS _4WD BCM HUD DATC MDPS AAF_Tester AEMC SMK _4WD EPB CUBIS MTS TMU EVP CGW TPMS LPI DI_BOX SPAS EMS LCA TCU IBOX FATC AFLS FPCM SCC AHLS AVM ABS SNV OPI PGS SAS AAF Dummy LDWS_LKAS LVR ESC PSB CLU ECS ACU REA + +BO_ 1532 ODS13: 5 ODS + SG_ CR_Ods_ID : 0|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_Chksum_H : 8|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + SG_ CR_Ods_Chksum_L : 16|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + SG_ CR_Ods_RomID_H : 24|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + SG_ CR_Ods_RomID_L : 32|8@1+ (1.0,0.0) [0.0|255.0] "" Dummy + +BO_ 1531 ODS12: 8 ODS + SG_ CR_Ods_SerNum0 : 0|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum1 : 8|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum3 : 24|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum4 : 32|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum5 : 40|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum6 : 48|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + SG_ CR_Ods_SerNum7 : 56|8@1+ (1.0,0.0) [0.0|255.0] "" ACU + +BO_ 1530 ODS11: 8 ODS + SG_ CF_Ods_PrcCmd : 1|1@1+ (1.0,0.0) [0.0|1.0] "" Dummy + SG_ CF_Ods_BtsFail : 3|1@1+ (1.0,0.0) [0.0|1.0] "" Dummy + SG_ CF_Ods_AcuRcvSN : 4|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_EolCal : 5|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_PsFail : 6|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_EcuFail : 7|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_WgtStat : 8|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CF_Ods_OccStat : 16|1@1+ (1.0,0.0) [0.0|1.0] "" ACU + SG_ CR_Wcs_ErrStat : 32|8@1+ (1.0,0.0) [0.0|63.0] "" ACU + SG_ CR_Wcs_ClassStat : 40|8@1+ (1.0,0.0) [0.0|4.0] "" ACU,BCM + +BO_ 1017 ECS12: 4 ECS + SG_ Height_FL : 0|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + SG_ Height_FR : 8|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + SG_ Height_RL : 16|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + SG_ Height_RR : 24|8@1+ (1.0,-128.0) [-128.0|127.0] "mm" AFLS + +BO_ 1268 SPAS12: 8 SPAS + SG_ CF_Spas_HMI_Stat : 0|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_Spas_Disp : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS + SG_ CF_Spas_FIL_Ind : 10|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FIR_Ind : 13|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FOL_Ind : 16|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FOR_Ind : 19|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_VolDown : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_RIL_Ind : 24|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_RIR_Ind : 27|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FLS_Alarm : 30|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_ROL_Ind : 32|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_ROR_Ind : 35|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FCS_Alarm : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_FI_Ind : 40|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_RI_Ind : 43|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU + SG_ CF_Spas_FRS_Alarm : 46|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_FR_Alarm : 48|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Spas_RR_Alarm : 50|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Spas_BEEP_Alarm : 52|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Spas_StatAlarm : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Spas_RLS_Alarm : 57|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_RCS_Alarm : 59|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_RRS_Alarm : 61|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1265 CLU11: 4 CLU + SG_ CF_Clu_CruiseSwState : 0|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,LDWS_LKAS,SCC + SG_ CF_Clu_CruiseSwMain : 3|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,LDWS_LKAS,SCC + SG_ CF_Clu_SldMainSW : 4|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Clu_ParityBit1 : 5|1@1+ (1.0,0.0) [0.0|1.0] "pulse count" EMS + SG_ CF_Clu_VanzDecimal : 6|2@1+ (0.125,0.0) [0.0|0.375] "" EMS + SG_ CF_Clu_Vanz : 8|9@1+ (0.5,0.0) [0.0|255.5] "km/h or MPH" BCM,CUBIS,EMS,IBOX,LDWS_LKAS,MDPS,SCC + SG_ CF_Clu_SPEED_UNIT : 17|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CUBIS,EMS,IBOX,LDWS_LKAS,MDPS,SCC + SG_ CF_Clu_DetentOut : 18|1@1+ (1.0,0.0) [0.0|1.0] "" AVM,BCM,LCA,PGS,SPAS + SG_ CF_Clu_RheostatLevel : 19|5@1+ (1.0,0.0) [0.0|31.0] "" AVM,BCM,LCA,PGS,SPAS + SG_ CF_Clu_CluInfo : 24|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_AmpInfo : 25|1@1+ (1.0,0.0) [0.0|1.0] "" BCM + SG_ CF_Clu_AliveCnt1 : 28|4@1+ (1.0,0.0) [0.0|15.0] "" AHLS,EMS,EPB,LDWS_LKAS,MDPS,SCC + +BO_ 1260 Sign_Detection: 8 XXX + SG_ SpeedLim_Nav_Cam : 40|8@1+ (1,0) [0|255] "km/h / mph" XXX + SG_ SpeedLim_Nav_Cam2 : 48|8@1+ (1,0) [0|255] "km/h / mph" XXX + +BO_ 1492 TMU_GW_PE_01: 8 CLU + SG_ TMU_IVRActivity : 0|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ TMU_PhoneActivity : 2|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + +BO_ 1491 HU_DATC_PE_00: 8 CLU + SG_ HU_VRActivity : 0|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ HU_PhoneActivity : 2|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ BlowerNoiseControl : 4|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + +BO_ 1490 HU_DATC_E_02: 8 CLU + SG_ HU_DATC_RearOnOffSet : 6|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ HU_DATC_ADSOnOffSet : 8|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + +BO_ 1479 EMS21: 8 EMS + SG_ SCR_LEVEL_WARN_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ SCR_LEVEL_WARN : 1|3@1+ (1.0,0.0) [0.0|4.0] "" CLU + SG_ SCR_SYS_ERROR_WARN : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ SCR_SYSTEM_WARN_LAMP : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ SCR_INDUCEMENT_EXIT_COND : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ SCR_UREA_LEVEL : 16|8@1+ (0.5,0.0) [0.0|100.0] "%" CLU + SG_ SCR_NO_REMAINING_RESTARTS : 24|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ SCR_REMAINING_DISTANCE : 32|16@1+ (1.0,0.0) [0.0|25000.0] "km" CLU + +BO_ 1472 GW_Warning_PE: 8 BCM + SG_ Audio_VolumeDown : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Flh_Alarm : 48|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Fcnt_Alarm : 50|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Frh_Alarm : 52|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Rlh_Alarm : 56|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,PGS + SG_ Pas_Spkr_Rcnt_Alarm : 58|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ Pas_Spkr_Rrh_Alarm : 60|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,PGS + +BO_ 1984 CAL_SAS11: 2 ESC + SG_ CCW : 0|4@1+ (1.0,0.0) [0.0|15.0] "" SAS + SG_ SAS_CID : 4|11@1+ (1.0,0.0) [0.0|2047.0] "" SAS + +BO_ 1456 CLU12: 4 CLU + SG_ CF_Clu_Odometer : 0|24@1+ (0.1,0.0) [0.0|1677721.4] "km" _4WD,AAF,BCM,CUBIS,EMS,EPB,IBOX,LDWS_LKAS,SCC,TPMS + +BO_ 688 SAS11: 5 MDPS + SG_ SAS_Angle : 0|16@1- (0.1,0.0) [-3276.8|3276.7] "Deg" _4WD,ACU,AFLS,AVM,CLU,ECS,EMS,ESC,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SPAS,TCU,_4WD,ACU,AFLS,AVM,BCM,CLU,ECS,EMS,ESC,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SPAS,TCU + SG_ SAS_Speed : 16|8@1+ (4.0,0.0) [0.0|1016.0] "" AFLS,ECS,ESC,IBOX,LDWS_LKAS,SCC,SPAS,TCU,AFLS,ECS,ESC,IBOX,LDWS_LKAS,SCC,SPAS,TCU + SG_ SAS_Stat : 24|8@1+ (1.0,0.0) [0.0|255.0] "" ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU,ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ MsgCount : 32|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS + SG_ CheckSum : 36|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS + +BO_ 1441 ACU12: 8 ACU + SG_ CR_Acu_SN : 0|64@1+ (1.0,0.0) [0.0|0.0] "" ODS + +BO_ 1440 ACU11: 8 ACU + SG_ CF_Ods_SNRcv : 1|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Ods_IDRcv : 2|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Ods_RZReq : 4|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Abg_DepInhEnt : 6|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_Abg_DepEnt : 7|1@1+ (1.0,0.0) [0.0|1.0] "" ODS + SG_ CF_PasBkl_FltStat : 28|1@1+ (1.0,0.0) [0.0|1.0] "" ODS,PSB + SG_ CF_DriBkl_FltStat : 29|1@1+ (1.0,0.0) [0.0|1.0] "" ODS,PSB + SG_ CF_PasBkl_Stat : 30|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,ODS,PSB,TMU + SG_ CF_DriBkl_Stat : 31|1@1+ (1.0,0.0) [0.0|1.0] "" ODS,PSB + SG_ CF_SWL_Ind : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CUBIS,IBOX + SG_ CF_Acu_FltStat : 34|2@1+ (1.0,0.0) [0.0|3.0] "" CUBIS,IBOX + SG_ CF_Acu_ExtOfSab : 36|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,CUBIS,IBOX + SG_ CF_Acu_Dtc : 40|16@1+ (1.0,0.0) [0.0|65535.0] "" CUBIS,IBOX + SG_ CF_Acu_NumOfFlt : 56|8@1+ (1.0,0.0) [0.0|255.0] "" CUBIS,IBOX + +BO_ 1437 AHLS11: 8 AHLS + SG_ CF_Ahls_WarnLamp : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Ahls_WarnMsg : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1434 PSB11: 2 PSB + SG_ PSB_LH_FAIL : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ PSB_LH_TGL : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ PSB_LH_ACT : 3|4@1+ (1.0,0.0) [0.0|4.0] "" Dummy + SG_ PSB_RH_FAIL : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ PSB_RH_TGL : 10|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ PSB_RH_ACT : 11|4@1+ (1.0,0.0) [0.0|4.0] "" Dummy + +BO_ 916 TCS13: 8 ESC + SG_ aBasis : 0|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" EMS,SCC + SG_ BrakeLight : 11|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,SCC + SG_ DCEnable : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ AliveCounterTCS : 13|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,SCC + SG_ Pre_TCS_CTL : 16|1@1+ (1.0,0.0) [0.0|1.0] "" Vector__XXX + SG_ EBA_ACK : 17|1@1+ (1.0,0.0) [0.0|1.0] "" Vector__XXX + SG_ FCA_ACK : 18|1@1+ (1.0,0.0) [0.0|1.0] "" Vector__XXX + SG_ DF_BF_STAT : 19|2@1+ (1.0,0.0) [0.0|3.0] "" BCW + SG_ SCCReqLim : 22|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ TQI_SCC : 24|8@1+ (0.390625,0.0) [0.0|199.609375] "%" Vector__XXX + SG_ ACCEL_REF_ACC : 32|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" EMS,SCC + SG_ ACCEnable : 43|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,SCC + SG_ DriverOverride : 45|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,SCC + SG_ StandStill : 47|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ CheckSum_TCS3 : 48|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,SCC + SG_ ACC_EQUIP : 52|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ PBRAKE_ACT : 53|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ ACC_REQ : 54|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ DriverBraking : 55|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,SCC + SG_ CF_VSM_Coded : 56|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + SG_ CF_VSM_Avail : 57|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,SCC + SG_ CF_VSM_Handshake : 59|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + SG_ CF_DriBkeStat : 60|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + SG_ CF_VSM_ConfSwi : 61|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ AEB_EQUIP : 63|1@1+ (1.0,0.0) [0.0|1.0] "" SCC + +BO_ 1427 TPMS11: 6 BCM + SG_ TPMS_W_LAMP : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,HUD,IBOX,CLU,CUBIS,HUD,IBOX + SG_ TREAD_W_LAMP : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,HUD,IBOX,CLU,CUBIS,HUD,IBOX + SG_ POS_FL_W_LAMP : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ POS_FR_W_LAMP : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ POS_RL_W_LAMP : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ POS_RR_W_LAMP : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,HUD,IBOX + SG_ STATUS_TPMS : 8|3@1+ (1.0,0.0) [0.0|0.0] "" CLU + SG_ UNIT : 11|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ PRESSURE_FL : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ PRESSURE_FR : 24|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ PRESSURE_RL : 32|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ PRESSURE_RR : 40|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + +BO_ 915 TCS12: 4 ESC + SG_ SA_COUNT : 0|16@1+ (2.0,-32768.0) [-32768.0|98302.0] "" _4WD,ACU,MDPS + SG_ SA_Z_COUNT : 16|15@1+ (2.0,-32768.0) [-32768.0|32766.0] "" _4WD,ACU,MDPS + SG_ SA_Z_FLAG : 31|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,MDPS + +BO_ 1170 EMS19: 8 EMS + SG_ CF_Ems_BrkReq : 0|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX,TCU + SG_ CF_Ems_DnShftReq : 1|4@1+ (1.0,0.0) [0.0|14.0] "" IBOX,TCU + SG_ CF_Ems_RepModChk : 5|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX + SG_ CF_Ems_AAFOpenReq : 7|1@1+ (1.0,0.0) [0.0|1.0] "" AAF,IBOX + SG_ CF_Ems_DecelReq : 8|12@1+ (0.0010,-4.094) [-4.094|0.0] "m/s^2" ESC,IBOX,TCU + SG_ CR_Ems_BstPre : 20|12@1+ (1.322,0.0) [0.0|4094.0] "hPa" CLU,IBOX + SG_ CR_Ems_EngOilTemp : 32|8@1+ (0.75,-40.0) [0.0|254.0] "deg" CLU,IBOX + SG_ DPF_LAMP_STAT : 40|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX + SG_ BAT_LAMP_STAT : 42|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_ModeledAmbTemp : 48|8@1+ (0.5,-41.0) [-41.0|85.5] "deg" AAF,IBOX + SG_ CF_Ems_OPSFail : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_AliveCounterEMS9 : 58|2@1+ (1.0,0.0) [0.0|3.0] "" AAF,ABS,CUBIS,ECS,EPB,IBOX,MDPS,REA,SCC,SMK,TCU + SG_ CF_Ems_ChecksumEMS9 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" AAF,ABS,CUBIS,ECS,EPB,IBOX,MDPS,REA,SCC,SMK,TCU + +BO_ 1425 AFLS11: 2 AFLS + SG_ AFLS_STAT : 1|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Afls_TrfChgStat : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Afls_LedHLStat : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 912 SPAS11: 7 SPAS + SG_ CF_Spas_Stat : 0|4@1+ (1.0,0.0) [0.0|15.0] "" ESC,MDPS + SG_ CF_Spas_TestMode : 4|2@1+ (1.0,0.0) [0.0|3.0] "" MDPS + SG_ CR_Spas_StrAngCmd : 8|16@1- (0.1,0.0) [-3276.8|3276.7] "" MDPS + SG_ CF_Spas_BeepAlarm : 24|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Spas_Mode_Seq : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Spas_AliveCnt : 32|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Spas_Chksum : 40|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Spas_PasVol : 48|3@1+ (1.0,0.0) [0.0|7.0] "" CGW,CLU + +BO_ 1168 EPB11: 7 EPB + SG_ EPB_I_LAMP : 0|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU,CUBIS,ESC,IBOX + SG_ EPB_F_LAMP : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,ESC,IBOX + SG_ EPB_ALARM : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC + SG_ EPB_CLU : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,ESC + SG_ EPB_SWITCH : 16|2@1+ (1.0,0.0) [0.0|3.0] "" ESC,SCC + SG_ EPB_RBL : 18|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,ESC + SG_ EPB_STATUS : 19|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EMS,ESC,SCC,TCU + SG_ EPB_FRC_ERR : 22|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,SCC,TCU + SG_ EPB_DBF_STAT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ ESP_ACK : 25|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ EPB_DBF_REQ : 26|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ EPB_FAIL : 29|3@1+ (1.0,0.0) [0.0|7.0] "" ESC,SCC + SG_ EPB_FORCE : 32|12@1+ (1.0,-1000.0) [-1000.0|3000.0] "" ESC + SG_ EPB_DBF_DECEL : 48|8@1+ (0.01,0.0) [0.0|2.54] "g" ESC + +BO_ 399 EMS_H12: 8 EMS + SG_ R_TqAcnApvC : 0|8@1+ (0.2,0.0) [0.0|51.0] "Nm" DATC,IBOX + SG_ R_PAcnC : 8|8@1+ (125.0,0.0) [0.0|31875.0] "hPa" DATC,IBOX + SG_ TQI_B : 16|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ABS,ESC,IBOX + SG_ SLD_VS : 24|8@1+ (1.0,0.0) [0.0|255.0] "km/h" CLU,IBOX + SG_ CF_CdaStat : 32|3@1+ (1.0,0.0) [0.0|7.0] "" AEMC,IBOX,TCU + SG_ CF_Ems_IsgStat : 35|3@1+ (1.0,0.0) [0.0|7.0] "" ABS,BCM,CLU,DATC,EPB,ESC,IBOX,LDWS_LKAS,MDPS,SMK,TCU + SG_ CF_Ems_OilChg : 38|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_EtcLimpMod : 39|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ R_NEngIdlTgC : 40|8@1+ (10.0,0.0) [0.0|2550.0] "rpm" DATC,IBOX,TCU + SG_ CF_Ems_UpTarGr : 48|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_DownTarGr : 49|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_DesCurGr : 50|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,IBOX + SG_ CF_Ems_SldAct : 54|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_SldPosAct : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_HPresStat : 56|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ CF_Ems_IsgBuz : 57|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_IdlStpFCO : 58|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_FCopen : 59|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Ems_ActEcoAct : 60|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,TCU + SG_ CF_Ems_EngRunNorm : 61|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC,IBOX,TCU + SG_ CF_Ems_IsgStat2 : 62|2@1+ (2.0,0.0) [0.0|3.0] "" CLU,IBOX,TCU + +BO_ 1419 LCA11: 8 LCA + SG_ CF_Lca_Stat : 0|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Rcta_Stat : 4|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Lca_IndLeft : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Rcw_Stat : 10|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_RCW_Warning : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Lca_IndRight : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_Lca_SndWan_Stat : 18|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_FR_SndWan : 20|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_FL_SndWan : 21|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_RR_SndWan : 22|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_RL_SndWan : 23|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU + SG_ CF_Lca_IndBriLeft : 24|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_Lca_IndBriRight : 32|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_RCTA_IndBriLeft : 40|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_RCTA_IndBriRight : 48|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_RCTA_IndLeft : 56|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_RCTA_IndRight : 58|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + SG_ CF_SndWarnForClu : 60|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 906 ABS11: 8 ABS + SG_ ABS_DEF : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,EMS,SPAS,TCU + SG_ EBD_DEF : 1|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,SPAS,TCU + SG_ ABS_ACT : 2|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,EPB,SPAS,TCU + SG_ ABS_W_LAMP : 3|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,CUBIS,MTS,TMU + SG_ EBD_W_LAMP : 4|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ ABS_DIAG : 5|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ ESS_STAT : 6|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,BCM,CLU,EMS + +BO_ 903 WHL_PUL11: 6 ABS + SG_ WHL_PUL_FL : 0|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_PUL_FR : 8|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_PUL_RL : 16|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_PUL_RR : 24|8@1+ (0.5,0.0) [0.0|127.5] "pulse count" CUBIS,EPB,IBOX,SPAS,TMU,TPMS,CUBIS,EPB,IBOX,LDWS_LKAS,SPAS,TMU,TPMS + SG_ WHL_DIR_FL : 32|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_DIR_FR : 34|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_DIR_RL : 36|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_DIR_RR : 38|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,SPAS,TPMS,EPB,LCA,SPAS,TPMS + SG_ WHL_PUL_Chksum : 40|8@1+ (1.0,0.0) [0.0|255.0] "" EPB,SPAS,TPMS,EPB,LCA,LDWS_LKAS,SPAS,TPMS + +BO_ 1415 TMU11: 8 IBOX + SG_ CF_Tmu_VehSld : 0|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Tmu_VehImmo : 1|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Tmu_ReqRepCnd : 2|2@1+ (1.0,0.0) [0.0|3.0] "" EMS + SG_ CF_Tmu_AirconCtr : 4|1@1+ (1.0,0.0) [0.0|1.0] "" DATC + SG_ CF_Tmu_TempMd : 5|1@1+ (1.0,0.0) [0.0|1.0] "" DATC + SG_ CF_Tmu_TempSet : 6|16@1+ (1.0,0.0) [0.0|20.0] "" DATC + SG_ CF_Tmu_DefrostCtr : 22|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,FATC + SG_ CF_Tmu_AliveCnt1 : 56|4@1+ (1.0,0.0) [0.0|15.0] "" EMS + +BO_ 902 WHL_SPD11: 8 ABS + SG_ WHL_SPD_FL : 0|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,AFLS,AHLS,AVM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_FR : 16|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,ACU,AFLS,AHLS,AVM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_RL : 32|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,AFLS,AHLS,AVM,BCM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,BCM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_RR : 48|14@1+ (0.03125,0.0) [0.0|511.96875] "km/h" _4WD,AFLS,AHLS,AVM,CLU,CUBIS,ECS,EMS,EPB,IBOX,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS,_4WD,ACU,AFLS,AHLS,AVM,CLU,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PGS,PSB,SCC,SMK,SPAS,TCU,TPMS + SG_ WHL_SPD_AliveCounter_LSB : 14|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ WHL_SPD_AliveCounter_MSB : 30|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ WHL_SPD_Checksum_LSB : 46|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ WHL_SPD_Checksum_MSB : 62|2@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + +BO_ 1414 EVP11: 3 EVP + SG_ CF_Evp_Stat : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 1412 AAF11: 8 AAF + SG_ CF_Aaf_ActFlapStatus : 0|2@1+ (1.0,0.0) [0.0|3.0] "" AAF_Tester + SG_ CF_Aaf_ModeStatus : 2|3@1+ (1.0,0.0) [0.0|7.0] "" AAF_Tester + SG_ CF_Aaf_WrnLamp : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Aaf_ErrStatus : 6|10@1+ (1.0,0.0) [0.0|1023.0] "" AAF_Tester,EMS + SG_ CF_Aaf_OpenRqSysAct : 16|8@1+ (1.0,0.0) [0.0|255.0] "" AAF_Tester + SG_ CF_Aaf_PStatus : 24|8@1+ (1.0,0.0) [0.0|100.0] "%" AAF_Tester + SG_ CF_Aaf_OpenRqSysSol : 32|8@1+ (1.0,0.0) [0.0|255.0] "" AAF_Tester + SG_ CF_Aaf_SolFlapStatus : 40|2@1+ (1.0,0.0) [0.0|3.0] "" AAF_Tester + SG_ CF_Aaf_MilOnReq : 42|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 900 EMS17: 8 EMS + SG_ CF_Ems_PkpCurMSV : 0|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_HolCurMSV : 8|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_InjVBnkAct : 16|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_InjVActSet : 24|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_DiagFulHDEV : 32|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CF_Ems_SwiOffIC1 : 33|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CF_Ems_SwiOffIC2 : 34|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CF_Ems_DiagReqHDEV : 38|1@1+ (1.0,0.0) [0.0|1.0] "" DI_BOX + SG_ CR_Ems_DutyCycMSV : 40|8@1+ (0.3921568627,0.0) [0.0|100.0] "%" DI_BOX + SG_ CR_Ems_BatVolRly : 48|8@1+ (0.1,0.0) [0.0|25.5] "V" DI_BOX + +BO_ 387 REA11: 8 REA + SG_ CF_EndBst_PwmDuH : 0|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PwmDuL : 1|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PwmFqOutRng : 2|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_HbriOverCur : 3|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_HbriOverTemp : 4|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PosSnsKOR : 6|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_PosSnsOSOR : 7|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_EepFlt : 8|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_RomFlt : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_RamFlt : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_CanFlt : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_AgH : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_AgL : 13|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_EndBst_ORVol : 14|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CR_EndBst_ActPos : 16|16@1+ (0.117,0.0) [1.989|118.053] "" EMS + SG_ CR_EndBst_DemPos : 32|16@1+ (0.117,0.0) [0.0|119.691] "" EMS + SG_ CR_EndBst_HbriPwr : 48|16@1+ (0.045,0.0) [0.0|99.99] "%" EMS + +BO_ 1411 CUBIS11: 8 CUBIS + SG_ CF_Cubis_HUDisp : 0|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + +BO_ 899 FATC11: 8 DATC + SG_ CR_Fatc_TqAcnOut : 0|8@1+ (0.2,0.0) [0.0|50.8] "Nm" EMS,IBOX + SG_ CF_Fatc_AcnRqSwi : 8|1@1+ (1.0,0.0) [0.0|1.0] "" AAF,EMS,IBOX + SG_ CF_Fatc_AcnCltEnRq : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_EcvFlt : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_BlwrOn : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_FATC_Iden : 12|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Fatc_BlwrMax : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX + SG_ CF_Fatc_EngStartReq : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_IsgStopReq : 16|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_CtrInf : 17|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,IBOX + SG_ CF_Fatc_MsgCnt : 20|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,IBOX + SG_ CR_Fatc_OutTemp : 24|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" BCM,CLU,EMS,IBOX,SPAS,TCU,TPMS + SG_ CR_Fatc_OutTempSns : 32|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" AAF,AHLS,CLU,EMS,IBOX,SPAS,TCU + SG_ CF_Fatc_Compload : 40|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,IBOX + SG_ CF_Fatc_ActiveEco : 43|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Fatc_AutoActivation : 44|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX + SG_ CF_Fatc_DefSw : 45|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,IBOX + SG_ CF_Fatc_PtcRlyStat : 46|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Fatc_ChkSum : 56|8@1+ (1.0,0.0) [0.0|255.0] "" EMS,IBOX,SPAS + +BO_ 129 EMS_DCT12: 8 EMS + SG_ CR_Ems_SoakTimeExt : 0|6@1+ (5.0,0.0) [0.0|315.0] "Min" TCU + SG_ BRAKE_ACT : 6|2@1+ (1.0,0.0) [0.0|3.0] "" TCU + SG_ CF_Ems_EngOperStat : 8|8@1+ (1.0,0.0) [0.0|255.0] "" TCU + SG_ CR_Ems_IndAirTemp : 16|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" TCU + SG_ CF_Ems_Alive2 : 56|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Ems_ChkSum2 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + +BO_ 145 FCEV_ACCELERATOR: 8 XXX + SG_ ACCELERATOR_PEDAL : 48|8@1+ (1,0) [0|255] "" XXX + +BO_ 897 MDPS11: 8 MDPS + SG_ CF_Mdps_WLmp : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,CUBIS,EMS,IBOX,SPAS + SG_ CF_Mdps_Flex : 2|3@1+ (1.0,0.0) [0.0|3.0] "" CLU,LDWS_LKAS + SG_ CF_Mdps_FlexDisp : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Mdps_Stat : 7|4@1+ (1.0,0.0) [0.0|15.0] "" SPAS + SG_ CR_Mdps_DrvTq : 11|12@1+ (1.0,-2048.0) [-2048.0|2046.0] "" SPAS + SG_ CF_Mdps_ALTRequest : 23|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CR_Mdps_StrAng : 24|16@1- (0.1,0.0) [-3276.8|3276.7] "Deg" SPAS + SG_ CF_Mdps_AliveCnt : 40|8@1+ (1.0,0.0) [0.0|255.0] "" LDWS_LKAS,SPAS + SG_ CF_Mdps_Chksum : 48|8@1+ (1.0,0.0) [0.0|255.0] "" LDWS_LKAS,SPAS + SG_ CF_Mdps_SPAS_FUNC : 57|1@1+ (1.0,0.0) [0.0|1.0] "flag" SPAS + SG_ CF_Mdps_LKAS_FUNC : 58|1@1+ (1.0,0.0) [0.0|1.0] "flag" LDWS_LKAS + SG_ CF_Mdps_CurrMode : 59|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Mdps_Type : 61|2@1+ (1.0,0.0) [0.0|2.0] "" LDWS_LKAS,SPAS + SG_ CF_MDPS_VSM_FUNC : 56|1@0+ (1.0,0.0) [0.0|1.0] "" XXX + +BO_ 896 DI_BOX13: 8 DI_BOX + SG_ CF_DiBox_HPreInjVConfStat : 0|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVStat1 : 8|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVStat2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVPkp : 24|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_HPreInjVBpt : 32|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_ErrRegFrtMSV : 40|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_ErrRegSedMSV : 48|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SPIErrSedMSV : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_SPIErrFrtMSV : 57|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_IDErrSedMSV : 58|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_IDErrFrtMSV : 59|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_IniStatMSV : 60|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 640 EMS13: 8 EMS + SG_ LV_FUEL_TYPE_ECU : 0|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,LPI,SMK + SG_ LV_BFS_CFIRM : 1|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_CRASH : 2|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_VB_OFF_ACT : 3|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_GSL_MAP M : 4|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ LV_ENG_TURN : 5|1@1+ (1.0,0.0) [0.0|1.0] "" LPI + SG_ ERR_FUEL : 8|8@1+ (1.0,0.0) [0.0|255.0] "" LPI + SG_ EOS : 16|8@1+ (1.0,0.0) [0.0|255.0] "" LPI + SG_ TCO : 24|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" LPI + SG_ N_32 : 32|8@1+ (32.0,0.0) [0.0|8160.0] "rpm" LPI + SG_ MAF : 40|8@1+ (5.447,0.0) [0.0|1388.985] "mg/TDC" LPI + SG_ TIA : 48|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" LPI + SG_ MAP m1 : 56|8@1+ (0.47058,0.0) [0.0|119.9979] "kPa" LPI + SG_ AMP m0 : 56|8@1+ (21.22,0.0) [0.0|5411.1] "hPa" LPI + +BO_ 128 EMS_DCT11: 8 EMS + SG_ PV_AV_CAN : 0|8@1+ (0.3906,0.0) [0.0|99.603] "%" TCU + SG_ TQ_STND : 8|6@1+ (10.0,0.0) [0.0|630.0] "Nm" TCU + SG_ F_N_ENG : 14|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ F_SUB_TQI : 15|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ N : 16|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" TCU + SG_ TQI_ACOR : 32|8@1+ (0.390625,0.0) [0.0|99.6094] "%" IBOX,TCU + SG_ TQFR : 40|8@1+ (0.390625,0.0) [0.0|99.6094] "%" TCU + SG_ TQI : 48|8@1+ (0.390625,0.0) [0.0|99.609375] "%" TCU + SG_ CF_Ems_Alive : 56|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Ems_ChkSum : 60|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + +BO_ 1407 HU_MON_PE_01: 8 CLU + SG_ HU_Type : 0|8@1+ (1.0,0.0) [0.0|255.0] "" AVM,PGS + +BO_ 127 CGW5: 8 BCM + SG_ C_StopLampLhOpenSts : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_StopLampRhOpenSts : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HMSLOpenSts : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampLowLhOpenSts : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampLowRhOpenSts : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampHighLhOpenSts : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_HLampHighRhOpenSts : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_DRLLampLhOpenSts : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_DRLLampRhOpenSts : 8|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearFOGLhOpenSts : 9|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearFOGRhOpenSts : 10|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontFOGLhOpenSts : 11|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontFOGRhOpenSts : 12|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearEXTTailLhOpenSts : 13|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearEXTTailRhOpenSts : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontEXTTailLhOpenSts : 15|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontEXTTailRhOpenSts : 16|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearTSIGLhOpenSts : 17|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_RearTSIGRhOpenSts : 18|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontTSIGLhOpenSts : 19|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_FrontTSIGRhOpenSts : 20|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_SBendingLhOpenSts : 21|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_SBendingRhOpenSts : 22|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_LicensePlateLhOpenSts : 23|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_LicensePlateRhOpenSts : 24|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 1151 ESP11: 6 ESC + SG_ AVH_STAT : 0|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EPB,TCU + SG_ LDM_STAT : 2|1@1+ (1.0,0.0) [0.0|1.0] "" EPB,TCU + SG_ REQ_EPB_ACT : 3|2@1+ (1.0,0.0) [0.0|3.0] "" EPB,TCU + SG_ REQ_EPB_STAT : 5|1@1+ (1.0,0.0) [0.0|1.0] "" EPB + SG_ ECD_ACT : 6|1@1+ (1.0,0.0) [0.0|1.0] "" EPB + SG_ _4WD_LIM_REQ : 7|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS + SG_ ROL_CNT_ESP : 8|8@1+ (1.0,0.0) [0.0|255.0] "" EPB,TCU + SG_ _4WD_TQC_LIM : 16|16@1+ (1.0,0.0) [0.0|65535.0] "Nm" _4WD,EMS + SG_ _4WD_CLU_LIM : 32|8@1+ (0.390625,0.0) [0.0|99.609375] "%" _4WD,EMS + SG_ _4WD_OPEN : 40|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,EMS + SG_ _4WD_LIM_MODE : 42|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD + +BO_ 1397 HU_AVM_E_00: 8 CLU + SG_ HU_AVM_Cal_Cmd : 0|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_Cal_Method : 4|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + SG_ HU_AVM_Save_Controlpoint : 6|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + SG_ HU_AVM_PT_X : 8|12@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_RearViewPointOpt : 20|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_PT_Y : 24|12@1+ (1.0,0.0) [0.0|4095.0] "" AVM,PGS + SG_ HU_AVM_FrontViewPointOpt : 36|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_SelectedMenu : 40|5@1+ (1.0,0.0) [0.0|31.0] "" AVM,PGS + SG_ HU_AVM_CameraOff : 45|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + SG_ HU_AVM_Option : 48|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_CrossLineMove_Cmd : 52|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_RearView_Option : 56|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_FrontView_Option : 60|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + +BO_ 1395 HU_AVM_E_01: 8 CLU + SG_ HU_PGSSelectedMenu : 0|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_PGSOption : 8|5@1+ (1.0,0.0) [0.0|31.0] "" AVM,PGS + SG_ HU_AVM_ParkingAssistMenu : 56|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + SG_ HU_AVM_ParkingAssistSB : 60|4@1+ (1.0,0.0) [0.0|15.0] "" AVM,PGS + +BO_ 1393 OPI11: 5 OPI + SG_ CR_Opi_Spd_Rpm : 0|8@1+ (20.0,0.0) [0.0|3500.0] "rpm" TCU + SG_ CF_Opi_Over_Temp : 8|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Opi_Over_Cur : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,TCU + SG_ CF_Opi_Over_Vol : 10|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Opi_Hall_Fail : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,TCU + SG_ CF_Opi_Flt : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,TCU + SG_ CF_Opi_Motor_Dir : 15|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Opi_Romver : 16|8@1+ (1.0,0.0) [0.0|255.0] "" TCU + SG_ CF_Opi_PWM_Rate : 24|12@1+ (1.0,0.0) [0.0|100.0] "%" TCU + +BO_ 625 LPI11: 8 LPI + SG_ FUP_LPG_MMV : 0|8@1+ (128.0,0.0) [0.0|32640.0] "hPa" EMS + SG_ LV_FUEL_TYPE_BOX : 8|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_BFS_IN_PROGRESS : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_GAS_OK : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_FUP_ENA_THD : 11|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,EMS,SMK + SG_ LPI_OBD : 12|4@1+ (1.0,0.0) [0.0|15.0] "" EMS + SG_ ERR_GAS : 16|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ FAC_TI_GAS_COR : 24|16@1+ (3.05E-5,0.0) [0.0|1.9988175] "" EMS + SG_ FTL_AFU : 40|8@1+ (0.392,0.0) [0.0|99.96] "%" EMS + SG_ BFS_CYL : 48|8@1+ (1.0,0.0) [0.0|6.0] "Cyl Nr." EMS + SG_ LV_PRE_CDN_LEAK : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_CONF_INJECTION_DELAY : 57|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ LV_LPG_SW_DRIVER_REQ : 58|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 356 VSM11: 4 ESC + SG_ CR_Esc_StrTqReq : 0|12@1+ (0.01,-20.48) [-20.48|20.47] "Nm" MDPS + SG_ CF_Esc_Act : 12|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS,MDPS + SG_ CF_Esc_CtrMode : 13|3@1+ (1.0,0.0) [0.0|7.0] "" MDPS + SG_ CF_Esc_Def : 16|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Esc_AliveCnt : 17|4@1+ (1.0,0.0) [0.0|15.0] "" LDWS_LKAS,MDPS + SG_ CF_Esc_Chksum : 24|8@1+ (1.0,0.0) [0.0|255.0] "" LDWS_LKAS,MDPS + +BO_ 1379 PGS_HU_PE_01: 8 PGS + SG_ PGS_State : 0|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ PGS_ParkGuideState : 8|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ PGS_Option : 16|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ PGS_Version : 32|16@1+ (1.0,0.0) [0.0|65535.0] "" CLU + +BO_ 354 TCU_DCT13: 3 TCU + SG_ Clutch_Driving_Tq : 0|10@1+ (1.0,-512.0) [0.0|0.0] "Nm" ESC + SG_ Cluster_Engine_RPM : 10|13@1+ (0.9766,0.0) [0.0|0.0] "" CLU + SG_ Cluster_Engine_RPM_Flag : 23|1@1+ (1.0,0.0) [0.0|0.0] "" CLU + +BO_ 1378 HUD11: 4 HUD + SG_ CF_Hud_HeightStaus : 0|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ CF_Hud_PBackStatus : 6|2@1+ (1.0,0.0) [0.0|0.0] "" BCM,CLU + SG_ CF_Hud_Brightness : 8|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + +BO_ 608 EMS16: 8 EMS + SG_ TQI_MIN : 0|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ESC,IBOX,TCU + SG_ TQI : 8|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ESC,IBOX,TCU + SG_ TQI_TARGET : 16|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EPB,ESC,IBOX,TCU + SG_ GLOW_STAT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,IBOX,SMK + SG_ CRUISE_LAMP_M : 25|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,TCU + SG_ CRUISE_LAMP_S : 26|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,TCU + SG_ PRE_FUEL_CUT_IN : 27|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ ENG_STAT : 28|3@1+ (1.0,0.0) [0.0|7.0] "" ABS,AHLS,AVM,BCM,CLU,EPB,ESC,EVP,FPCM,IBOX,LCA,LDWS_LKAS,MDPS,SCC,SMK,TCU + SG_ SOAK_TIME_ERROR : 31|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,EPB,IBOX,TCU + SG_ SOAK_TIME : 32|8@1+ (1.0,0.0) [0.0|255.0] "Min" _4WD,DATC,EPB,IBOX,TCU + SG_ TQI_MAX : 40|8@1+ (0.390625,0.0) [0.0|99.609375] "%" ESC,IBOX,TCU + SG_ SPK_TIME_CUR : 48|8@1+ (0.375,-35.625) [-35.625|60.0] "" IBOX,TCU + SG_ Checksum : 56|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,IBOX,LDWS_LKAS,MDPS,SCC + SG_ AliveCounter : 60|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX,LDWS_LKAS,MDPS,SCC + SG_ CF_Ems_AclAct : 62|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX,SCC + +BO_ 1371 AVM_HU_PE_00: 8 AVM + SG_ AVM_View : 0|5@1+ (1.0,0.0) [0.0|31.0] "" CLU + SG_ AVM_ParkingAssist_BtnSts : 5|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ AVM_Display_Message : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ AVM_Popup_Msg : 16|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_Ready : 20|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_ParkingAssist_Step : 24|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_FrontBtn_Type : 28|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_Option : 32|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_HU_FrontViewPointOpt : 36|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_HU_RearView_Option : 40|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_HU_FrontView_Option : 44|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ AVM_Version : 48|16@1+ (1.0,0.0) [0.0|65535.0] "" CLU + +BO_ 1370 HU_AVM_PE_00: 8 CLU + SG_ HU_AVM_Status : 0|2@1+ (1.0,0.0) [0.0|3.0] "" AVM,PGS + +BO_ 1369 CGW4: 8 BCM + SG_ CF_Gway_MemoryP1Cmd : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_MemoryP2Cmd : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBackP1Cmd : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBackP2Cmd : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_StrgWhlHeatedState : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBackStopCmd : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,HUD + SG_ CF_Gway_StaticBendLhAct : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_StaticBendRhAct : 7|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_DrvWdwStat : 8|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_RLWdwState : 9|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_RRWdwState : 10|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_AstWdwStat : 11|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_MemoryEnable : 12|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBACKStopCmd : 13|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_PBACKStop : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,HUD + SG_ CF_Gway_IMSBuzzer : 15|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_DrvSeatBeltInd : 36|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_AstSeatBeltInd : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RCSeatBeltInd : 40|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RLSeatBeltInd : 42|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RRSeatBeltInd : 44|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_RrWiperHighSw : 46|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_RrWiperLowSw : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 1367 EngFrzFrm12: 8 EMS + SG_ PID_06h : 0|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_07h : 8|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_08h : 16|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_09h : 24|8@1+ (0.78125,-100.0) [-100.0|99.22] "%" AAF,IBOX,TCU + SG_ PID_0Bh : 32|8@1+ (1.0,0.0) [0.0|255.0] "kPa" AAF,IBOX,TCU + SG_ PID_23h : 40|16@1+ (10.0,0.0) [0.0|655350.0] "kPa" AAF,IBOX,TCU + +BO_ 1366 EngFrzFrm11: 8 EMS + SG_ PID_04h : 0|8@1+ (0.3921568627,0.0) [0.0|100.0] "%" AAF,TCU + SG_ PID_05h : 8|8@1+ (1.0,-40.0) [-40.0|215.0] "deg" AAF,TCU + SG_ PID_0Ch : 16|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" AAF,TCU + SG_ PID_0Dh : 32|8@1+ (1.0,0.0) [0.0|255.0] "km/h" AAF,TCU + SG_ PID_11h : 40|8@1+ (0.3921568627,0.0) [0.0|100.0] "%" AAF,TCU + SG_ PID_03h : 48|16@1+ (1.0,0.0) [0.0|65535.0] "" AAF,TCU + +BO_ 1365 FPCM11: 8 FPCM + SG_ CR_Fpcm_LPActPre : 0|8@1+ (3.137254902,0.0) [0.0|800.0] "kPa" EMS + SG_ CF_Fpcm_LPPumpOverCur : 8|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrHi : 9|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrDisc : 10|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrShort : 11|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_LPPumpDiscShort : 12|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_LP_System_Error : 13|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_PreSnrSigErr : 14|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Fpcm_LPCtrCirFlt : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 871 LVR12: 8 LVR + SG_ CF_Lvr_CruiseSet : 0|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,TCU + SG_ CF_Lvr_IsgState : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,TCU + SG_ CF_Lvr_Gear : 32|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,TCU + +BO_ 872 LVR11: 8 LVR + SG_ CF_Lvr_GearInf : 0|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,TCU + SG_ CF_Lvr_PRelStat : 4|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,SMK,TCU + SG_ CF_Lvr_BkeAct : 5|1@1+ (1.0,0.0) [0.0|1.0] "" TCU + SG_ CF_Lvr_NFnStat : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Lvr_PosInf : 8|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_PosCpl : 12|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_UlkButStat : 18|2@1+ (1.0,0.0) [0.0|3.0] "" TCU + SG_ CF_Lvr_PNStat : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lvr_ShtLkStat : 24|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_ShfErrInf : 28|20@1+ (1.0,0.0) [0.0|8191.0] "" CLU,TCU + SG_ CF_Lvr_AC : 48|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + SG_ CF_Lvr_CS : 52|4@1+ (1.0,0.0) [0.0|15.0] "" TCU + +BO_ 1363 CGW2: 8 BCM + SG_ CF_Gway_GwayDiagState : 0|1@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_DDMDiagState : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SCMDiagState : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_PSMDiagState : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SJBDiagState : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_IPMDiagState : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_LDMFail : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,LDWS_LKAS,LDWS_LKAS + SG_ CF_Gway_CLUSwGuiCtrl : 10|3@1+ (1.0,0.0) [0.0|63.0] "" CLU,Dummy + SG_ CF_Gway_CLUSwGroup : 13|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_CLUSwMode : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_CLUSwEnter : 15|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_AutoLightValue : 16|1@1+ (1.0,0.0) [0.0|1.0] "" LCA,LCA + SG_ CF_Gway_BrakeFluidSw : 17|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_DrvSeatBeltInd : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_AvTail : 20|1@1+ (1.0,0.0) [0.0|3.0] "" CLU,SNV,SNV + SG_ CF_Gway_RearFogAct : 21|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ExtTailAct : 22|1@1+ (1.0,0.0) [0.0|1.0] "" AVM,CLU,LCA,PGS,SPAS,AVM,LCA,PGS,SPAS + SG_ CF_Gway_RRDrSw : 23|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_RLDrSw : 24|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_IntTailAct : 25|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_CountryCfg : 26|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,Dummy + SG_ CF_Gway_WiperParkPosition : 32|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,EMS,LDWS_LKAS,AFLS,EMS,LDWS_LKAS + SG_ CF_Gway_HLLowLHFail : 33|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS,SNV,LDWS_LKAS,SNV + SG_ CF_Gway_HLLowRHFail : 34|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS,SNV,LDWS_LKAS,SNV + SG_ CF_Gway_ESCLFailWarn : 35|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ESCLNotLockedWarn : 36|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ESCLNotUnlockWarn : 37|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_IDoutWarn : 38|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_ImmoLp : 40|1@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_BCMRKEID : 41|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + SG_ CF_Gway_VehicleNotPWarn : 44|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_DeactivationWarn : 45|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_KeyBATDischargeWarn : 46|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SSBWarn : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SMKFobID : 48|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + SG_ CF_Gway_SMKRKECmd : 51|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + SG_ CF_Gway_AutoLightOption : 54|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_SJBDeliveryMode : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_KeyoutLp : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,Dummy + SG_ CF_Gway_SMKDispWarn : 57|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,Dummy + SG_ CF_Gway_WngBuz : 61|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,Dummy + +BO_ 339 TCS11: 8 ESC + SG_ TCS_REQ : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,TCU + SG_ MSR_C_REQ : 1|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,EPB,SCC,TCU + SG_ TCS_PAS : 2|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,SCC,SPAS,TCU + SG_ TCS_GSC : 3|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,TCU + SG_ CF_Esc_LimoInfo : 4|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,SCC + SG_ ABS_DIAG : 6|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB + SG_ ABS_DEF : 7|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,SCC,SPAS,TCU + SG_ TCS_DEF : 8|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,SCC,SPAS,TCU + SG_ TCS_CTL : 9|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,SCC,SPAS,TCU + SG_ ABS_ACT : 10|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,LDWS_LKAS,SCC,SPAS,TCU + SG_ EBD_DEF : 11|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,SPAS,TCU + SG_ ESP_PAS : 12|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,CLU,EMS,EPB,LDWS_LKAS,SCC,TCU + SG_ ESP_DEF : 13|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,LDWS_LKAS,SCC,TCU + SG_ ESP_CTL : 14|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,ECS,EMS,EPB,LDWS_LKAS,SCC,SPAS,TCU + SG_ TCS_MFRN : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,EPB,TCU + SG_ DBC_CTL : 16|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB + SG_ DBC_PAS : 17|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB + SG_ DBC_DEF : 18|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB + SG_ HAC_CTL : 19|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB,TCU + SG_ HAC_PAS : 20|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB,TCU + SG_ HAC_DEF : 21|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,EMS,EPB,TCU + SG_ ESS_STAT : 22|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,BCM,CLU,EMS,EPB + SG_ TQI_TCS : 24|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,EPB,TCU + SG_ TQI_MSR : 32|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,EPB,TCU + SG_ TQI_SLW_TCS : 40|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,EPB,TCU + SG_ CF_Esc_BrkCtl : 48|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ BLA_CTL : 49|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CGW,CLU + SG_ AliveCounter_TCS1 : 52|4@1+ (1.0,0.0) [0.0|14.0] "" EMS,EPB,LDWS_LKAS + SG_ CheckSum_TCS1 : 56|8@1+ (1.0,0.0) [0.0|255.0] "" EMS,EPB,LDWS_LKAS + +BO_ 1362 SNV11: 4 SNV + SG_ CF_SNV_DisplayControl : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,HUD + SG_ CF_Snv_BeepWarning : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,HUD + SG_ CF_Snv_WarningMessage : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,HUD + SG_ CF_Snv_DetectionEnable : 7|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,CLU,HUD + SG_ CF_Snv_PedestrianDetect : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,HUD + SG_ CF_Snv_IRLampControl : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,HUD + +BO_ 593 MDPS12: 8 MDPS + SG_ CR_Mdps_StrColTq : 0|11@1+ (1.0,-1024.0) [-1024.0|1024.0] "" LDWS_LKAS + SG_ CF_Mdps_Def : 11|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ CF_Mdps_ToiUnavail : 12|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_ToiActive : 13|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_ToiFlt : 14|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_FailStat : 15|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Mdps_MsgCount2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" ESC,LDWS_LKAS + SG_ CF_Mdps_Chksum2 : 24|8@1+ (1.0,0.0) [0.0|255.0] "" ESC,LDWS_LKAS + SG_ CF_Mdps_SErr : 37|1@1+ (1.0,0.0) [0.0|1.0] "" ESC + SG_ CR_Mdps_StrTq : 40|12@1+ (0.01,-20.48) [-20.48|20.47] "Nm" ESC + SG_ CR_Mdps_OutTq : 52|12@1+ (0.1,-204.8) [-204.8|204.7] "" ESC,LDWS_LKAS + +BO_ 1360 IAP11: 3 IAP + SG_ CF_Iap_EcoPmodSwi : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Iap_EcoPmodAct : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Iap_ReqWarn : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1356 TCU_DCT14: 8 TCU + SG_ Vehicle_Stop_Time : 0|5@1+ (1.0,0.0) [0.0|0.0] "" CLU + SG_ HILL_HOLD_WARNING : 5|1@1+ (1.0,0.0) [0.0|0.0] "" CLU + +BO_ 1353 BAT11: 8 EMS + SG_ BAT_SNSR_I : 0|16@1+ (0.01,-327.0) [-327.0|328.0] "A" CGW,CUBIS,IBOX,TMU + SG_ BAT_SOC : 16|8@1+ (1.0,0.0) [0.0|100.0] "%" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_V : 24|14@1+ (0.0010,6.0) [6.0|18.0] "V" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_Temp : 38|9@1- (0.5,-40.0) [-40.0|125.0] "deg" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_State : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CGW,CUBIS,IBOX,TMU + SG_ BAT_SOH : 48|7@1+ (1.0,0.0) [0.0|100.0] "%" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_Invalid : 55|1@1+ (1.0,0.0) [0.0|1.0] "" CGW,CUBIS,IBOX,TMU + SG_ BAT_SOF : 56|7@1+ (0.1,0.0) [0.0|12.0] "V" CGW,CUBIS,IBOX,TMU + SG_ BAT_SNSR_Error : 63|1@1+ (1.0,0.0) [0.0|1.0] "" CGW,CUBIS,IBOX,TMU + +BO_ 1351 EMS15: 8 EMS + SG_ ECGPOvrd : 0|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX,SCC + SG_ QECACC : 1|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ ECFail : 2|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ SwitchOffCondExt : 3|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ BLECFail : 4|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ CF_Ems_IsaAct : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ FA_PV_CAN : 8|8@1+ (0.3906,0.0) [0.0|99.2] "%" IBOX,LDWS_LKAS,TCU + SG_ IntAirTemp : 16|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" _4WD,ECS,EPB,IBOX,TCU + SG_ STATE_DC_OBD : 24|7@1+ (1.0,0.0) [0.0|127.0] "" IBOX,TCU + SG_ INH_DC_OBD : 31|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ CTR_IG_CYC_OBD : 32|16@1+ (1.0,0.0) [0.0|65535.0] "" ACU,IBOX,TCU + SG_ CTR_CDN_OBD : 48|16@1+ (1.0,0.0) [0.0|65535.0] "" IBOX,TCU + +BO_ 1350 DI_BOX12: 8 DI_BOX + SG_ CF_DiBox_FrtInjVDiagReg0 : 0|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_FrtInjVDiagReg1 : 8|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_FrtInjVDiagReg2 : 16|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SedInjVDiagReg0 : 24|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SedInjVDiagReg1 : 32|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CF_DiBox_SedInjVDiagReg2 : 40|8@1+ (1.0,0.0) [0.0|255.0] "" EMS + SG_ CR_DiBox_BatVol : 48|8@1+ (0.1,0.0) [0.0|25.5] "V" EMS + SG_ CF_DiBox_SedInjVChg : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_FrtInjVChg : 57|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_SedInjVErrSPI : 58|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_DiBox_FrtInjVErrSPI : 59|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + +BO_ 1349 EMS14: 8 EMS + SG_ IMMO_LAMP_STAT : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ L_MIL : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,IBOX + SG_ IM_STAT : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ AMP_CAN : 3|5@1+ (10.731613,458.98) [458.98|791.660003] "mmHg" CLU,IBOX,TCU,TPMS + SG_ BAT_Alt_FR_Duty : 8|8@1+ (0.4,0.0) [0.0|100.0] "%" CGW,CUBIS,IBOX,TMU + SG_ VB : 24|8@1+ (0.1015625,0.0) [0.0|25.8984375] "V" CLU,CUBIS,DATC,EPB,FPCM,IBOX + SG_ EMS_VS : 32|12@1+ (0.0625,0.0) [0.0|255.875] "km/h" CLU + SG_ TEMP_FUEL : 56|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" FPCM + +BO_ 68 DATC11: 8 DATC + SG_ CF_Datc_Type : 0|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_Datc_VerMaj : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_Datc_VerMin : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CR_Datc_OutTempC : 24|8@1+ (0.5,-41.0) [-41.0|86.5] "deg" CLU,FPCM + SG_ CR_Datc_OutTempF : 32|8@1+ (1.0,-42.0) [-42.0|213.0] "deg" CLU + SG_ CF_Datc_IncarTemp : 40|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" BCM,CLU + +BO_ 67 DATC13: 8 DATC + SG_ CF_Datc_TempDispUnit : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX + SG_ CF_Datc_ModDisp : 2|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_IonClean : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_ChgReqDisp : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_IntakeDisp : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_AutoDisp : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_FrDefLed : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,IBOX + SG_ CF_Datc_AutoDefogBlink : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_ClmScanDisp : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_AqsDisp : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_AcDisp : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_OpSts : 25|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Mtc_MaxAcDisp : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_DualDisp : 30|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_PwrInf : 32|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_RearManual : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearAutoDisp : 40|2@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Datc_RearOffDisp : 42|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearClimateScnDisp : 44|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearChgReqDisp : 46|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_RearModDisp : 48|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_RearBlwDisp : 52|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_PSModDisp : 56|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ CF_Datc_FrontBlwDisp : 60|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,IBOX + +BO_ 66 DATC12: 8 DATC + SG_ CR_Datc_DrTempDispC : 0|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU,IBOX + SG_ CR_Datc_DrTempDispF : 8|8@1+ (1.0,56.0) [58.0|90.0] "deg" CLU,IBOX + SG_ CR_Datc_PsTempDispC : 16|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU,IBOX + SG_ CR_Datc_PsTempDispF : 24|8@1+ (1.0,56.0) [58.0|90.0] "deg" CLU,IBOX + SG_ CR_Datc_RearDrTempDispC : 40|8@1+ (0.5,14.0) [15.0|32.0] "deg" CLU + SG_ CR_Datc_RearDrTempDispF : 48|8@1+ (1.0,58.0) [58.0|90.0] "deg" CLU + SG_ CF_Datc_CO2_Warning : 56|8@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1345 CGW1: 8 BCM + SG_ CF_Gway_IGNSw : 0|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,ECS,EMS,EPB,ESC,IBOX,LVR,MDPS,SAS,SCC,ECS,EMS,EPB,ESC,IBOX,LVR,MDPS,SAS,SCC + SG_ CF_Gway_RKECmd : 3|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,ECS,EMS,IBOX,ECS,EMS,IBOX + SG_ CF_Gway_DrvKeyLockSw : 6|1@1+ (1.0,0.0) [0.0|1.0] "" ECS,EMS,IBOX,ECS,EMS,IBOX + SG_ CF_Gway_DrvKeyUnlockSw : 7|1@1+ (1.0,0.0) [0.0|1.0] "" ECS,EMS,IBOX,ECS,EMS,IBOX + SG_ CF_Gway_DrvDrSw : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ECS,EMS,EPB,ESC,IBOX,SCC,TCU,ECS,EMS,EPB,ESC,IBOX,SCC,TCU + SG_ CF_Gway_DrvSeatBeltSw : 10|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EPB,ESC,IBOX,PSB,TCU,EMS,EPB,ESC,IBOX,PSB,TCU + SG_ CF_Gway_TrunkTgSw : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ECS,EMS,EPB,ESC,IBOX,ECS,EMS,EPB,ESC,IBOX + SG_ CF_Gway_AstSeatBeltSw : 14|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX,PSB,IBOX,PSB + SG_ CF_Gway_SMKOption : 16|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,EMS,IBOX,SMK + SG_ CF_Gway_HoodSw : 17|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,EPB,ESC,IBOX,EMS,EPB,ESC,IBOX + SG_ CF_Gway_TurnSigLh : 19|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,IBOX,LCA,LDWS_LKAS,SCC,EMS,IBOX,LCA,LDWS_LKAS,SCC + SG_ CF_Gway_WiperIntT : 21|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperIntSw : 24|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperLowSw : 25|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperHighSw : 26|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_WiperAutoSw : 27|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_RainSnsState : 28|3@1+ (1.0,0.0) [0.0|7.0] "" AFLS,EMS,IBOX,LDWS_LKAS,AFLS,EMS,ESC,IBOX,LDWS_LKAS + SG_ CF_Gway_HeadLampLow : 31|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,CLU,EMS,IBOX,LDWS_LKAS,SNV,AFLS,EMS,IBOX,LDWS_LKAS,SNV + SG_ CF_Gway_HeadLampHigh : 32|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,CLU,EMS,IBOX,LDWS_LKAS,AFLS,EMS,IBOX,LDWS_LKAS + SG_ CF_Gway_HazardSw : 33|2@1+ (1.0,0.0) [0.0|3.0] "" ABS,EMS,ESC,IBOX,LCA,LDWS_LKAS,ABS,EMS,ESC,IBOX,LCA,LDWS_LKAS + SG_ CF_Gway_AstDrSw : 35|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,IBOX + SG_ CF_Gway_DefoggerRly : 36|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX,EMS,IBOX + SG_ CF_Gway_ALightStat : 37|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_LightSwState : 38|2@1+ (1.0,0.0) [0.0|3.0] "" AFLS,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_Frt_Fog_Act : 40|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,CLU,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_TSigRHSw : 41|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_TSigLHSw : 42|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_DriveTypeOption : 43|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_StarterRlyState : 44|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX,EMS,IBOX,SMK + SG_ CF_Gway_PassiveAccessLock : 45|2@1+ (1.0,0.0) [0.0|7.0] "" CLU,ECS,EMS,IBOX,ECS,EMS,IBOX,SMK + SG_ CF_Gway_WiperMistSw : 47|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,IBOX,LDWS_LKAS + SG_ CF_Gway_PassiveAccessUnlock : 48|2@1+ (1.0,0.0) [0.0|7.0] "" CLU,ECS,EMS,IBOX,ECS,EMS,IBOX,SMK + SG_ CF_Gway_RrSunRoofOpenState : 50|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,DATC,IBOX + SG_ CF_Gway_PassingSW : 51|1@1+ (1.0,0.0) [0.0|1.0] "" AFLS,IBOX,LDWS_LKAS,AFLS,IBOX,LDWS_LKAS + SG_ CF_Gway_HBAControlMode : 52|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_HLpHighSw : 53|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LDWS_LKAS,IBOX,LDWS_LKAS + SG_ CF_Gway_InhibitRMT : 54|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EPB,ESC,IBOX,LCA,LDWS_LKAS,MDPS,PGS,SCC,SPAS,TPMS,EPB,ESC,IBOX,LCA,LDWS_LKAS,PGS,SCC,SPAS,TPMS + SG_ CF_Gway_RainSnsOption : 56|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ C_SunRoofOpenState : 57|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,DATC,IBOX,DATC,IBOX + SG_ CF_Gway_Ign1 : 58|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_Ign2 : 59|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Gway_ParkBrakeSw : 60|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,ESC,IBOX,SCC,ESC,IBOX,SCC + SG_ CF_Gway_TurnSigRh : 62|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,IBOX,LCA,LDWS_LKAS,SCC,EMS,IBOX,LCA,LDWS_LKAS,SCC + +BO_ 64 DATC14: 8 DATC + SG_ CF_Datc_AqsLevelOut : 0|4@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Datc_DiagMode : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CR_Datc_SelfDiagCode : 8|8@1+ (1.0,-1.0) [0.0|254.0] "" CLU + SG_ DATC_SyncDisp : 16|4@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_OffDisp : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_SmartVentDisp : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_SmartVentOnOffStatus : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_AutoDefogSysOff_Disp : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ DATC_ADSDisp : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 832 LKAS11: 8 LDWS_LKAS + SG_ CF_Lkas_LdwsActivemode : 0|2@1+ (1,0) [0|3] "" CLU,IBOX,PSB + SG_ CF_Lkas_LdwsSysState : 2|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,IBOX,PSB + SG_ CF_Lkas_SysWarning : 6|4@1+ (1.0,0.0) [0.0|15.0] "" BCM,CLU + SG_ CF_Lkas_LdwsLHWarning : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,PSB + SG_ CF_Lkas_LdwsRHWarning : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU,PSB + SG_ CF_Lkas_HbaLamp : 14|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Lkas_FcwBasReq : 15|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC + SG_ CR_Lkas_StrToqReq : 16|11@1+ (1.0,-1024.0) [-1024.0|1024.0] "" MDPS + SG_ CF_Lkas_ActToi : 27|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Lkas_ToiFlt : 28|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Lkas_HbaSysState : 29|3@1+ (1.0,0.0) [0.0|7.0] "" BCM,CLU + SG_ CF_Lkas_FcwOpt : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lkas_HbaOpt : 34|2@1+ (1.0,0.0) [0.0|1.0] "" BCM,CGW + SG_ CF_Lkas_MsgCount : 36|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,MDPS + SG_ CF_Lkas_FcwSysState : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Lkas_FcwCollisionWarning : 43|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lkas_FusionState : 45|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Lkas_Unknown1 : 47|1@1+ (1.0,0.0) [0.0|1.0] "" XXX + SG_ CF_Lkas_Chksum : 48|8@1+ (1.0,0.0) [0.0|255.0] "" MDPS + SG_ CF_Lkas_FcwOpt_USM : 56|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Lkas_LdwsOpt_USM : 59|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,MDPS + SG_ CF_Lkas_Unknown2 : 62|2@1+ (1.0,0.0) [0.0|1.0] "" XXX + +BO_ 1342 LKAS12: 6 LDWS_LKAS + SG_ CF_Lkas_TsrSlifOpt : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_LkasTsrStatus : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Lkas_TsrSpeed_Display_Clu : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU + SG_ CF_LkasTsrSpeed_Display_Navi : 24|8@1+ (1.0,0.0) [0.0|255.0] "" BCM,CLU + SG_ CF_Lkas_TsrAddinfo_Display : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_LkasDawStatus : 40|3@1+ (1,0) [0|7] "" CLU + SG_ CF_Lkas_Daw_USM : 37|3@1+ (1,0) [0|7] "" CLU + +BO_ 1338 TMU_GW_E_01: 8 CLU + SG_ CF_Gway_TeleReqDrLock : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqDrUnlock : 2|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqHazard : 4|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqHorn : 6|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Gway_TeleReqEngineOperate : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 1078 PAS11: 4 BCM + SG_ CF_Gway_PASDisplayFLH : 0|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,AVM + SG_ CF_Gway_PASDisplayFRH : 3|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,AVM + SG_ CF_Gway_PASRsound : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASDisplayFCTR : 8|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,AVM + SG_ CF_Gway_PASDisplayRCTR : 11|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,AVM + SG_ CF_Gway_PASFsound : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASDisplayRLH : 16|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,AVM + SG_ CF_Gway_PASDisplayRRH : 19|3@1+ (1.0,0.0) [0.0|7.0] "" AVM,CLU,PGS,AVM + SG_ CF_Gway_PASCheckSound : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASSystemOn : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,Dummy + SG_ CF_Gway_PASOption : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PASDistance : 28|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + +BO_ 48 EMS18: 6 EMS + SG_ CF_Ems_DC1NumPerMSV : 0|8@1+ (1.0,0.0) [0.0|255.0] "" DI_BOX + SG_ CF_Ems_DC2NumPerMSV : 8|16@1+ (1.0,0.0) [0.0|65535.0] "" DI_BOX + SG_ CR_Ems_DutyCyc1MSV : 24|8@1+ (0.1953,0.0) [0.0|49.8] "%" DI_BOX + SG_ CR_Ems_DutyCyc2MSV : 32|8@1+ (0.13725,0.0) [0.0|35.0] "%" DI_BOX + SG_ CR_Ems_DutyCyc3MSV : 40|8@1+ (0.392,0.0) [0.0|100.0] "%" DI_BOX + +BO_ 1322 CLU15: 8 CLU + SG_ CF_Clu_VehicleSpeed : 0|8@1+ (1.0,0.0) [0.0|255.0] "" BCM + SG_ CF_Clu_Gear : 9|4@1+ (1,0) [0|15] "" BCM + SG_ CF_Clu_HudInfoSet : 13|7@1+ (1.0,0.0) [0.0|127.0] "" HUD + SG_ CF_Clu_HudFontColorSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudBrightUpSW : 22|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudBrightDnSW : 24|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudHeightUpSW : 26|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudHeightDnSW : 28|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_HudSet : 30|1@1+ (1.0,0.0) [0.0|1.0] "" HUD + SG_ CF_Clu_HudFontSizeSet : 31|2@1+ (1.0,0.0) [0.0|3.0] "" HUD + SG_ CF_Clu_LanguageInfo : 33|5@1+ (1.0,0.0) [0.0|31.0] "" BCM,PGS + SG_ CF_Clu_ClusterSound : 38|1@1- (1.0,0.0) [0.0|0.0] "" BCM,CGW,FATC + SG_ CF_Clu_VehicleSpeed2 : 48|8@1+ (1,0) [0|255] "" XXX + +BO_ 1066 _4WD13: 6 _4WD + SG_ _4WD_CURRENT : 0|8@1+ (0.390625,0.0) [-50.0|50.0] "A" TCU + SG_ _4WD_POSITION : 8|16@1+ (0.015625,0.0) [-180.0|180.0] "Deg" TCU + SG_ _4WD_CLU_THERM_STR : 24|8@1+ (1.0,0.0) [0.0|100.0] "%" TCU + SG_ _4WD_STATUS : 32|8@1+ (1.0,0.0) [0.0|15.0] "" ESC,TCU + +BO_ 1065 _4WD12: 8 _4WD + SG_ Ster_Pos : 0|16@1+ (1.0,-600.0) [-600.0|600.0] "Deg" ESC + SG_ FRSS : 16|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ FLSS : 24|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ RRSS : 32|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ RLSS : 40|8@1+ (1.0,0.0) [0.0|254.0] "km/h" ESC + SG_ CLU_PRES : 48|16@1+ (0.0625,-50.0) [-50.0|50.0] "Bar" ESC + +BO_ 809 EMS12: 8 EMS + SG_ CONF_TCU m1 : 0|6@1+ (1.0,0.0) [0.0|63.0] "" _4WD,ACU,BCM,CLU,DATC,EPB,ESC,IBOX,LCA,SMK + SG_ CAN_VERS m0 : 0|6@1+ (1.0,0.0) [0.0|7.7] "" _4WD,ABS,ESC,IBOX + SG_ TQ_STND m3 : 0|6@1+ (10.0,0.0) [0.0|630.0] "Nm" _4WD,DATC,ECS,EPB,ESC,FATC,IBOX + SG_ OBD_FRF_ACK m2 : 0|6@1+ (1.0,0.0) [0.0|63.0] "" _4WD,ESC,IBOX + SG_ MUL_CODE M : 6|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ABS,ACU,BCM,CLU,DATC,ECS,EPB,ESC,IBOX,LCA,SMK,TCU + SG_ TEMP_ENG : 8|8@1+ (0.75,-48.0) [-48.0|143.25] "deg" _4WD,BCM,CLU,DATC,EPB,ESC,IBOX,SMK,TCU + SG_ MAF_FAC_ALTI_MMV : 16|8@1+ (0.00781,0.0) [0.0|1.99155] "" IBOX,TCU + SG_ VB_OFF_ACT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ ACK_ES : 25|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,IBOX + SG_ CONF_MIL_FMY : 26|3@1+ (1.0,0.0) [0.0|7.0] "" ESC,IBOX,TCU + SG_ OD_OFF_REQ : 29|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,TCU + SG_ ACC_ACT : 30|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ABS,CLU,ESC,IAP,IBOX,SCC,TCU + SG_ CLU_ACK : 31|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EPB,ESC,IBOX + SG_ BRAKE_ACT : 32|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ABS,ACU,AFLS,CLU,DATC,ECS,EPB,ESC,IBOX,LDWS_LKAS,TCU + SG_ ENG_CHR : 34|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,ABS,ACU,CLU,DATC,EPB,ESC,FATC,IBOX,SCC,SMK,TCU + SG_ GP_CTL : 38|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX + SG_ TPS : 40|8@1+ (0.4694836,-15.0234742) [-15.0234742|104.6948357] "%" _4WD,ABS,ACU,CLU,DATC,ECS,EPB,ESC,IBOX,TCU + SG_ PV_AV_CAN : 48|8@1+ (0.3906,0.0) [0.0|99.603] "%" _4WD,AAF,ABS,ACU,AFLS,CLU,DATC,EPB,ESC,IAP,IBOX,LDWS_LKAS,SCC,TCU + SG_ ENG_VOL : 56|8@1+ (0.1,0.0) [0.0|25.5] "liter" _4WD,ABS,ACU,BCM,CLU,DATC,EPB,ESC,IBOX,LDWS_LKAS,SCC,SMK + +BO_ 1064 _4WD11: 8 _4WD + SG_ _4WD_TYPE : 0|2@1+ (1.0,0.0) [0.0|3.0] "" ACU,ESC,TPMS + SG_ _4WD_SUPPORT : 2|2@1+ (1.0,0.0) [0.0|3.0] "" ABS,ESC,TPMS + SG_ _4WD_ERR : 8|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,ESC + SG_ CLU_DUTY : 16|8@1+ (1.0,0.0) [0.0|64.0] "%" ABS,ESC + SG_ R_TIRE : 24|8@1+ (1.0,200.0) [200.0|455.0] "mm" ABS,ESC,TPMS + SG_ _4WD_SW : 32|8@1+ (1.0,0.0) [0.0|9.9] "" ESC + SG_ _2H_ACT : 40|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC + SG_ _4H_ACT : 41|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,CLU,ESC,TPMS + SG_ LOW_ACT : 42|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC,TCU,TPMS + SG_ AUTO_ACT : 43|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,ESC,TPMS + SG_ LOCK_ACT : 44|1@1+ (1.0,0.0) [0.0|1.0] "" ABS,CLU,ESC,TPMS + SG_ _4WD_TQC_CUR : 48|16@1+ (1.0,0.0) [0.0|65535.0] "Nm" ABS,ESC + +BO_ 1319 HU_GW_E_01: 8 CLU + SG_ C_ADrLNValueSet : 0|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ C_ADrUNValueSet : 4|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ C_TwUnNValueSet : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_ABuzzerNValueSet : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_ArmWKeyNValueSet : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_PSMNValueSet : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_SCMNValueSet : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_HLEscortNValueSet : 18|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_WELNValueSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_TriTurnLNValueSet : 22|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_SNVWarnNValueSet : 24|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_LkasWarnNValueSet : 26|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 1318 HU_GW_E_00: 8 CLU + SG_ C_ADrLURValueReq : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_TwUnRValueReq : 2|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_AlarmRValueReq : 4|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_IMSRValueReq : 6|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_HLEscortRValueReq : 8|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_WELRValueReq : 10|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_TriTurnLRValueReq : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_SNVWarnRValueReq : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ C_LkasWarnRValueReq : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 1317 GW_HU_E_01: 8 BCM + SG_ C_ADrLRValue : 0|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_ADrURValue : 4|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_TwUnRValue : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ABuzzerRValue : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ArmWKeyRValue : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_PSMRValue : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SCMRValue : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_HLEscortRValue : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_WELRValue : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TriTurnLRValue : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1316 GW_HU_E_00: 8 BCM + SG_ C_ADrLUNValueConf : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TwUnNValueConf : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_AlarmNValueConf : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_PSMNValueConf : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SCMNValueConf : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_HLEscortNValueConf : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_WELNValueConf : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TriTurnLNValueConf : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1315 GW_SWRC_PE: 8 BCM + SG_ C_ModeSW : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_MuteSW : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SeekDnSW : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SeekUpSW : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_BTPhoneCallSW : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_BTPhoneHangUpSW : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_DISCDownSW : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_DISCUpSW : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SdsSW : 18|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_MTSSW : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_VolDnSW : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_VolUpSW : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1314 GW_IPM_PE_1: 8 BCM + SG_ C_AV_Tail : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ParkingBrakeSW : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_RKECMD : 4|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ C_BAState : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_IGNSW : 12|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_CountryCfg : 16|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ C_TailLampActivity : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ RearSW_RSELockOnOff : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SMKTeleCrankingState : 32|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_SMKTeleCrankingFailRes : 34|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1057 SCC12: 8 SCC + SG_ CF_VSM_Prefill : 0|1@1+ (1,0) [0|1] "" ESC + SG_ CF_VSM_DecCmdAct : 1|1@1+ (1,0) [0|1] "" ESC + SG_ CF_VSM_HBACmd : 2|2@1+ (1,0) [0|3] "" ESC + SG_ CF_VSM_Warn : 4|2@1+ (1,0) [0|3] "" CLU,ESC,IAP + SG_ CF_VSM_Stat : 6|2@1+ (1,0) [0|3] "" CLU,ESC,PSB + SG_ CF_VSM_BeltCmd : 8|3@1+ (1,0) [0|7] "" ESC,PSB + SG_ ACCFailInfo : 11|2@1+ (1,0) [0|3] "" CLU,CUBIS,ESC,IBOX + SG_ ACCMode : 13|2@1+ (1,0) [0|3] "" CLU,ESC,IBOX,TCU + SG_ StopReq : 15|1@1+ (1,0) [0|1] "" EPB,ESC + SG_ CR_VSM_DecCmd : 16|8@1+ (0.01,0) [0|2.55] "g" ESC + SG_ TakeOverReq : 35|1@1+ (1,0) [0|1] "" CLU,ESC,TCU + SG_ PreFill : 36|1@1+ (1,0) [0|1] "" ESC,TCU + SG_ CF_VSM_ConfMode : 48|2@1+ (1,0) [0|3] "" CLU,ESC + SG_ AEB_Failinfo : 50|2@1+ (1,0) [0|3] "" CLU,ESC + SG_ AEB_Status : 52|2@1+ (1,0) [0|3] "" CLU,ESC + SG_ AEB_CmdAct : 54|1@1+ (1,0) [0|1] "" ESC + SG_ AEB_StopReq : 55|1@1+ (1,0) [0|1] "" CLU,ESC + SG_ CR_VSM_Alive : 56|4@1+ (1,0) [0|15] "" ESC,PSB + SG_ CR_VSM_ChkSum : 60|4@1+ (1,0) [0|15] "" ESC,PSB + SG_ aReqValue : 37|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" Vector__XXX + SG_ aReqRaw : 24|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" Vector__XXX + +BO_ 1313 GW_DDM_PE: 8 BCM + SG_ C_DRVDoorStatus : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_ASTDoorStatus : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_RLDoorStatus : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_RRDoorStatus : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_TrunkStatus : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ C_OSMirrorStatus : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + +BO_ 1056 SCC11: 8 SCC + SG_ MainMode_ACC : 0|1@1+ (1,0) [0|1] "" CLU,EMS,ESC + SG_ SCCInfoDisplay : 1|3@1+ (1,0) [0|7] "" CLU,ESC + SG_ AliveCounterACC : 4|4@1+ (1,0) [0|15] "" CLU,EMS,ESC,TCU + SG_ VSetDis : 8|8@1+ (1,0) [0|255] "km/h or MPH" CLU,ESC,TCU + SG_ ObjValid : 16|1@1+ (1,0) [0|1] "" CLU,ESC,TCU + SG_ DriverAlertDisplay : 17|2@1+ (1,0) [0|3] "" CLU,ESC + SG_ TauGapSet : 19|3@1+ (1,0) [0|7] "" CLU,ESC,TCU + SG_ Navi_SCC_Curve_Status : 56|2@1+ (1,0) [0|3] "" CLU + SG_ Navi_SCC_Curve_Act : 58|2@1+ (1,0) [0|3] "" CLU + SG_ Navi_SCC_Camera_Act : 60|2@1+ (1,0) [0|3] "" CLU + SG_ Navi_SCC_Camera_Status : 62|2@1+ (1,0) [0|3] "" CLU + SG_ ACC_ObjStatus : 22|2@1+ (1,0) [0|3] "" ABS,ESC + SG_ ACC_ObjLatPos : 24|9@1+ (0.1,-20) [-20|31.1] "m" ABS,ESC + SG_ ACC_ObjRelSpd : 44|12@1+ (0.1,-170) [-170|239.5] "m/s" ABS,ESC + SG_ ACC_ObjDist : 33|11@1+ (0.1,0) [0|204.7] "m" ABS,ESC + +BO_ 1312 CGW3: 8 BCM + SG_ CR_Photosensor_LH : 0|8@1+ (78.125,0.0) [0.0|20000.0] "" DATC,DATC + SG_ CR_Photosensor_RH : 10|8@1+ (78.125,0.0) [0.0|20000.0] "" DATC,DATC + SG_ CF_Hoodsw_memory : 22|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,EMS + SG_ C_MirOutTempSns : 24|8@1+ (0.5,-40.5) [-40.0|60.0] "deg" AAF,CLU,DATC,EMS,SPAS,AAF,DATC,EMS,SPAS + +BO_ 544 ESP12: 8 ESC + SG_ LAT_ACCEL : 0|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" _4WD,ECS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,TCU + SG_ LAT_ACCEL_STAT : 11|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,IBOX,LDWS_LKAS,MDPS,PSB,SCC,TCU + SG_ LAT_ACCEL_DIAG : 12|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,IBOX,LDWS_LKAS,MDPS,PSB,SCC,TCU + SG_ LONG_ACCEL : 13|11@1+ (0.01,-10.23) [-10.23|10.24] "m/s^2" _4WD,ECS,EMS,EPB,IBOX,LCA,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ LONG_ACCEL_STAT : 24|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ LONG_ACCEL_DIAG : 25|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,SPAS,TCU + SG_ CYL_PRES : 26|12@1+ (0.1,0.0) [0.0|409.5] "Bar" _4WD,ECS,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,TCU + SG_ CYL_PRES_STAT : 38|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ECS,EMS,EPB,IBOX,LDWS_LKAS,PSB,SCC,TCU + SG_ CYL_PRESS_DIAG : 39|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ECS,EMS,EPB,IBOX,PSB,SCC,TCU + SG_ YAW_RATE : 40|13@1+ (0.01,-40.95) [-40.95|40.96] "" _4WD,AFLS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,SPAS,TCU + SG_ YAW_RATE_STAT : 53|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,AFLS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,SPAS,TCU + SG_ YAW_RATE_DIAG : 54|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,AFLS,IBOX,LCA,LDWS_LKAS,MDPS,PSB,SCC,SPAS,TCU + SG_ ESP12_Checksum : 56|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + SG_ ESP12_AliveCounter : 60|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,LPI,TCU,TMU + +BO_ 1307 CLU16: 8 CLU + SG_ CF_Clu_TirePressUnitNValueSet : 0|3@1+ (1.0,0.0) [0.0|7.0] "" TPMS + SG_ CF_Clu_SlifNValueSet : 3|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Clu_RearWiperNValueSet : 12|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + +BO_ 790 EMS11: 8 EMS + SG_ SWI_IGK : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ABS,ACU,AHLS,CUBIS,DI_BOX,ECS,EPB,ESC,IBOX,LDWS_LKAS,MDPS,REA,SAS,SCC,TCU + SG_ F_N_ENG : 1|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,AFLS,CLU,CUBIS,DATC,ECS,EPB,ESC,IBOX,MDPS,SCC,TCU + SG_ ACK_TCS : 2|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,IBOX + SG_ PUC_STAT : 3|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,DATC,IBOX,TCU + SG_ TQ_COR_STAT : 4|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ESC,IBOX,TCU + SG_ RLY_AC : 6|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,IBOX,TCU + SG_ F_SUB_TQI : 7|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ECS,EPB,ESC,IBOX,TCU + SG_ TQI_ACOR : 8|8@1+ (0.390625,0.0) [0.0|99.6094] "%" _4WD,EPB,ESC,IBOX,TCU + SG_ N : 16|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" _4WD,ACU,AFLS,CLU,CUBIS,DATC,ECS,EPB,ESC,FPCM,IBOX,MDPS,SCC,TCU + SG_ TQI : 32|8@1+ (0.390625,0.0) [0.0|99.6094] "%" _4WD,ECS,EPB,ESC,IBOX,TCU + SG_ TQFR : 40|8@1+ (0.390625,0.0) [0.0|99.6094] "%" _4WD,EPB,ESC,IBOX,TCU + SG_ VS : 48|8@1+ (1.0,0.0) [0.0|254.0] "km/h" _4WD,AAF,ACU,AHLS,BCM,CLU,DATC,ECS,EPB,IBOX,LCA,LDWS_LKAS,LVR,MDPS,ODS,SCC,SMK,SPAS,TCU,TPMS + SG_ RATIO_TQI_BAS_MAX_STND : 56|8@1+ (0.0078,0.0) [0.0|2.0] "" _4WD,IBOX,TCU + +BO_ 1301 CLU14: 8 CLU + SG_ CF_Clu_ADrUNValueSet : 0|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_ADrLNValueSet : 3|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_EscortHLNValueSet : 6|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_DoorLSNValueSet : 8|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_PSMNValueSet : 11|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_TTUnlockNValueSet : 14|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_PTGMNValueSet : 16|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_SCMNValueSet : 18|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_WlightNValueSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_TempUnitNValueSet : 22|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,DATC + SG_ CF_Clu_MoodLpNValueSet : 24|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_TrfChgSet : 27|2@1+ (1.0,0.0) [0.0|3.0] "" AFLS + SG_ CF_Clu_OTTurnNValueSet : 29|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_LcaNValueSet : 32|2@1+ (1.0,0.0) [0.0|3.0] "" LCA + SG_ CF_Clu_RctaNValueSet : 34|2@1+ (1.0,0.0) [0.0|3.0] "" LCA + SG_ CF_Clu_RcwNValueSet : 36|2@1+ (1.0,0.0) [0.0|3.0] "" LCA + SG_ CF_Clu_EscOffNValueSet : 38|3@1+ (1.0,0.0) [0.0|7.0] "" ESC + SG_ CF_Clu_SccNaviCrvNValueSet : 41|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Clu_SccNaviCamNValueSet : 43|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Clu_SccAebNValueSet : 45|2@1+ (1.0,0.0) [0.0|3.0] "" SCC + SG_ CF_Clu_LkasModeNValueSet : 47|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Clu_FcwNValueSet : 51|2@1+ (1.0,0.0) [0.0|3.0] "" LDWS_LKAS + SG_ CF_Clu_PasSpkrLvNValueSet : 53|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + SG_ CF_Clu_SccDrvModeNValueSet : 56|3@1+ (1.0,0.0) [0.0|7.0] "" SCC + SG_ CF_Clu_HAnBNValueSet : 59|2@1+ (1.0,0.0) [0.0|3.0] "" BCM + SG_ CF_Clu_HfreeTrunkTgNValueSet : 61|3@1+ (1.0,0.0) [0.0|7.0] "" BCM + +BO_ 275 TCU13: 8 TCU + SG_ N_TGT_LUP : 0|8@1+ (10.0,500.0) [500.0|3040.0] "rpm" EMS,IBOX + SG_ SLOPE_TCU : 8|6@1+ (0.5,-16.0) [-16.0|15.5] "%" CLU,CUBIS,EMS,IBOX + SG_ CF_Tcu_InhCda : 14|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_IsgInhib : 15|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_BkeOnReq : 16|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_NCStat : 18|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_TarGr : 20|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,CLU,DATC,EMS,EPB,ESC,IBOX,SCC + SG_ CF_Tcu_ShfPatt : 24|4@1+ (1.0,0.0) [0.0|15.0] "" CLU,CUBIS,EMS,IBOX + SG_ CF_Tcu_InhVis : 28|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_PRelReq : 29|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX,LVR + SG_ CF_Tcu_ITPhase : 30|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_ActEcoRdy : 31|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_TqGrdLim : 32|8@1+ (10.0,0.0) [0.0|2540.0] "Nm/s" EMS,IBOX + SG_ CR_Tcu_IsgTgtRPM : 40|8@1+ (20.0,0.0) [0.0|3500.0] "rpm" EMS,IBOX + SG_ CF_Tcu_SptRdy : 48|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,IBOX + SG_ CF_Tcu_SbwPInfo : 56|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ CF_Tcu_Alive3 : 58|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_ChkSum3 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,IBOX + +BO_ 274 TCU12: 8 TCU + SG_ ETL_TCU : 0|8@1+ (2.0,0.0) [0.0|508.0] "Nm" EMS,IBOX + SG_ CUR_GR : 8|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,EMS,ESC,IBOX,SCC,TPMS + SG_ CF_Tcu_Alive : 12|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,IBOX,SCC + SG_ CF_Tcu_ChkSum : 14|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,IBOX,SCC + SG_ VS_TCU : 16|8@1+ (1.0,0.0) [0.0|254.0] "km/h" BCM,CLU,DATC,EMS,IBOX,LCA,LVR,PGS,SMK,SNV + SG_ FUEL_CUT_TCU : 28|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ INH_FUEL_CUT : 29|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ IDLE_UP_TCU : 30|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ N_INC_TCU : 31|1@1+ (1.0,0.0) [0.0|1.0] "" EMS,IBOX + SG_ SPK_RTD_TCU : 32|8@1+ (0.375,-23.625) [-15.0|15.0] "" EMS,IBOX + SG_ N_TC_RAW : 40|16@1+ (0.25,0.0) [0.0|16383.5] "rpm" EMS,IBOX + SG_ VS_TCU_DECIMAL : 56|8@1+ (0.0078125,0.0) [0.0|0.9921875] "km/h" CLU,EMS,IBOX,LCA + +BO_ 273 TCU11: 8 TCU + SG_ TQI_TCU_INC : 0|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,ESC,IBOX + SG_ G_SEL_DISP : 8|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,AFLS,AVM,BCM,CGW,CLU,CUBIS,ECS,EMS,EPB,ESC,IAP,IBOX,LCA,LDWS_LKAS,LVR,MDPS,PGS,SCC,SMK,SNV,SPAS,TPMS + SG_ F_TCU : 12|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,ESC,IBOX + SG_ TCU_TYPE : 14|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,EMS,ESC,IBOX + SG_ TCU_OBD : 16|3@1+ (1.0,0.0) [0.0|7.0] "" EMS,ESC,IBOX + SG_ SWI_GS : 19|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,EMS,EPB,ESC,IBOX,SCC + SG_ GEAR_TYPE : 20|4@1+ (1.0,0.0) [0.0|15.0] "" _4WD,CLU,EMS,ESC,IBOX,SCC + SG_ TQI_TCU : 24|8@1+ (0.390625,0.0) [0.0|99.609375] "%" EMS,ESC,IBOX + SG_ TEMP_AT : 32|8@1+ (1.0,-40.0) [-40.0|214.0] "deg" AAF,CLU,CUBIS,EMS,ESC,IBOX + SG_ N_TC : 40|16@1+ (0.25,0.0) [0.0|16383.5] "rpm" _4WD,EMS,EPB,ESC,IBOX + SG_ SWI_CC : 56|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,CLU,EMS,ESC,IBOX + SG_ CF_Tcu_Alive1 : 58|2@1+ (1.0,0.0) [0.0|3.0] "" EMS,IBOX + SG_ CF_Tcu_ChkSum1 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,IBOX + +BO_ 16 ACU13: 8 ACU + SG_ CF_Acu_CshAct : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CUBIS,IBOX,ODS + +BO_ 1040 CGW_USM1: 8 BCM + SG_ CF_Gway_ATTurnRValue : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PTGMRValue : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_EscortHLRValue : 4|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_TTUnlockRValue : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_ADrLRValue : 8|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_ADrURValue : 11|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_SCMRValue : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_WlightRValue : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PSMRValue : 18|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_OTTurnRValue : 21|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_DrLockSoundRValue : 24|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_HAnBRValue : 27|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_MoodLpRValue : 30|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_HfreeTrunkRValue : 32|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_AutoLightRValue : 35|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_Gway_RearWiperRValue : 38|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_Gway_PasSpkrLvRValue : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + +BO_ 1292 CLU13: 8 CLU + SG_ CF_Clu_LowfuelWarn : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,FPCM,IBOX + SG_ CF_Clu_RefDetMod : 2|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX + SG_ CF_Clu_AvgFCU : 3|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX + SG_ CF_Clu_AvsmCur : 5|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,SCC + SG_ CF_Clu_AvgFCI : 6|10@1+ (0.1,0.0) [0.0|102.2] "" IBOX + SG_ CF_Clu_DrivingModeSwi : 16|2@1+ (1.0,0.0) [0.0|3.0] "" DATC,ECS,EMS,ESC,IAP,MDPS,TCU + SG_ CF_Clu_FuelDispLvl : 18|5@1+ (1.0,0.0) [0.0|31.0] "" CGW,IBOX + SG_ CF_Clu_FlexSteerSW : 23|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS + SG_ CF_Clu_DTE : 24|10@1+ (1.0,0.0) [0.0|1023.0] "" DATC + SG_ CF_Clu_TripUnit : 34|2@1+ (1.0,0.0) [0.0|3.0] "" DATC + SG_ CF_Clu_SWL_Stat : 36|3@1+ (1.0,0.0) [0.0|7.0] "" ACU,EMS + SG_ CF_Clu_ActiveEcoSW : 39|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,EMS,TCU + SG_ CF_Clu_EcoDriveInf : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CUBIS,EMS,IAP,IBOX + SG_ CF_Clu_IsaMainSW : 43|1@1+ (1.0,0.0) [0.0|1.0] "" EMS + SG_ CF_Clu_LdwsLkasSW : 56|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS + SG_ CF_Clu_AltLStatus : 59|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,DATC,EMS + SG_ CF_Clu_AliveCnt2 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,LDWS_LKAS + +BO_ 1290 SCC13: 8 SCC + SG_ SCCDrvModeRValue : 0|3@1+ (1,0) [0|7] "" CLU + SG_ SCC_Equip : 3|1@1+ (1,0) [0|1] "" ESC + SG_ AebDrvSetStatus : 4|3@1+ (1,0) [0|7] "" CLU,ESC + SG_ Lead_Veh_Dep_Alert_USM : 13|2@0+ (1,0) [0|3] "" XXX + +BO_ 1287 TCS15: 4 ESC + SG_ ABS_W_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU,CUBIS,IBOX + SG_ TCS_OFF_LAMP : 1|2@1+ (1.0,0.0) [0.0|1.0] "" _4WD,ACU,CLU + SG_ TCS_LAMP : 3|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,ACU,CLU,CUBIS,IBOX,SCC + SG_ DBC_W_LAMP : 5|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ DBC_F_LAMP : 6|2@1+ (1.0,0.0) [0.0|3.0] "" _4WD,CLU + SG_ ESC_Off_Step : 8|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ AVH_CLU : 16|8@1+ (1.0,0.0) [0.0|255.0] "" CLU,EPB + SG_ AVH_I_LAMP : 24|2@1+ (1.0,0.0) [0.0|3.0] "" EPB + SG_ EBD_W_LAMP : 26|1@1+ (1.0,0.0) [0.0|1.0] "" _4WD,CLU + SG_ AVH_ALARM : 27|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ AVH_LAMP : 29|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EPB,SPAS + +BO_ 1282 TCU14: 4 TCU + SG_ CF_TCU_WarnMsg : 0|3@1+ (1.0,0.0) [0.0|7.0] "" CLU + SG_ CF_TCU_WarnImg : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_TCU_WarnSnd : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ CF_Tcu_GSel_BlinkReq : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,LVR + SG_ CF_Tcu_StRelStat : 12|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,EMS,ESC + SG_ CF_Tcu_DriWarn1 : 13|3@1+ (1.0,0.0) [0.0|7.0] "" CLU,EMS,ESC + SG_ CF_Tcu_DriWarn2 : 16|2@1+ (1.0,0.0) [0.0|3.0] "" CLU,EMS,ESC + +BO_ 1281 ECS11: 3 ECS + SG_ ECS_W_LAMP : 0|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,CUBIS,IBOX + SG_ SYS_NA : 1|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ ECS_DEF : 2|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ ECS_DIAG : 3|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ L_CHG_NA : 4|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Leveling_Off : 5|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ LC_overheat : 6|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Lifting : 8|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Lowering : 9|1@1+ (1.0,0.0) [0.0|1.0] "" CLU + SG_ Damping_Mode : 10|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ REQ_Damping : 12|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ REQ_Height : 14|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ REQ_level : 16|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + SG_ ACT_Height : 20|4@1+ (1.0,0.0) [0.0|15.0] "" CLU + +BO_ 1024 CLU_CFG11: 2 CLU + SG_ Vehicle_Type : 0|16@1+ (1.0,0.0) [0.0|65536.0] "" _4WD + +BO_ 1280 ACU14: 1 ACU + SG_ CF_SWL_Ind : 0|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_TTL_Ind : 2|2@1+ (1.0,0.0) [0.0|3.0] "" CLU + SG_ CF_SBR_Ind : 4|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,CLU + +BO_ 512 EMS20: 6 EMS + SG_ HYDROGEN_GEAR_SHIFTER : 11|3@1+ (1,0) [0|7] "" XXX + SG_ CF_Ems_PumpTPres : 16|8@1+ (3.137254902,0.0) [0.0|800.0] "kPa" FPCM,IBOX + SG_ Split_Stat : 32|1@1+ (1.0,0.0) [0.0|1.0] "" FPCM + +BO_ 909 FCA11: 8 FCA + SG_ CF_VSM_Prefill : 0|1@1+ (1,0) [0|1] "" ESC + SG_ CF_VSM_HBACmd : 1|2@1+ (1,0) [0|3] "" ESC + SG_ CF_VSM_Warn : 3|2@1+ (1,0) [0|3] "" ACU,CLU,ESC + SG_ CF_VSM_BeltCmd : 5|3@1+ (1,0) [0|7] "" ESC + SG_ CR_VSM_DecCmd : 8|8@1+ (0.01,0) [0|2.55] "g" ESC + SG_ FCA_Status : 18|2@1+ (1,0) [0|3] "" ACU,CLU,ESC + SG_ FCA_CmdAct : 20|1@1+ (1,0) [0|1] "" ESC + SG_ FCA_StopReq : 21|1@1+ (1,0) [0|1] "" CLU,ESC + SG_ FCA_DrvSetStatus : 22|3@1+ (1,0) [0|7] "" CLU,ESC + SG_ CF_VSM_DecCmdAct : 31|1@1+ (1,0) [0|1] "" ESC + SG_ FCA_Failinfo : 32|3@1+ (1,0) [0|7] "" ACU,CLU,ESC + SG_ CR_FCA_Alive : 35|4@1+ (1,0) [0|15] "" ESC + SG_ FCA_RelativeVelocity : 39|9@1+ (0.1,-25.5) [-25.5|25.5] "m/s" iBAU + SG_ FCA_TimetoCollision : 48|8@1+ (10,0) [0|2540] "ms" iBAU + SG_ CR_FCA_ChkSum : 56|8@1+ (1,0) [0|255] "" ESC + SG_ PAINT1_Status : 16|2@1+ (1,0) [0|1] "" XXX + +BO_ 1156 HDA11_MFC: 8 XXX + SG_ Counter : 5|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 1|2@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 7|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 16|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 18|14@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_6 : 33|2@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 34|14@1+ (1,0) [0|16383] "" XXX + SG_ NEW_SIGNAL_8 : 49|2@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_9 : 50|14@1- (1,-4095) [0|16383] "" XXX + +BO_ 1155 FCA12: 8 FCA + SG_ FCA_USM : 0|3@1+ (1,0) [0|7] "" CGW,CLU,ESC + SG_ FCA_DrvSetState : 3|3@1+ (1,0) [0|7] "" CGW + +BO_ 1186 FRT_RADAR11: 2 FCA + SG_ CF_FCA_Equip_Front_Radar : 0|3@1+ (1,0) [0|7] "" LDWS_LKAS,LDW_LKA,ESC + +BO_ 905 SCC14: 8 SCC + SG_ ComfortBandUpper : 0|6@1+ (0.02,0) [0|1.26] "m/s^2" ESC + SG_ ComfortBandLower : 6|6@1+ (0.02,0) [0|1.26] "m/s^2" ESC + SG_ JerkUpperLimit : 12|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC + SG_ JerkLowerLimit : 19|7@1+ (0.1,0) [0|12.7] "m/s^3" ESC + SG_ ACCMode : 32|3@1+ (1,0) [0|7] "" CLU,HUD,LDWS_LKAS,ESC + SG_ ObjGap : 56|8@1+ (1,0) [0|255] "" CLU,HUD,ESC + +BO_ 1157 LFAHDA_MFC: 4 XXX + SG_ HDA_USM : 0|2@1+ (1,0) [0|3] "" XXX + SG_ HDA_Active : 2|1@1+ (1,0) [0|1] "" XXX + SG_ HDA_Icon_State : 3|2@1+ (1,0) [0|3] "" XXX + SG_ HDA_Chime : 7|1@1+ (1,0) [0|1] "" XXX + SG_ HDA_VSetReq : 8|8@1+ (1,0) [0|255] "km/h" XXX + SG_ LFA_SysWarning : 16|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_1 : 20|3@1+ (1,0) [0|7] "" XXX + SG_ LFA_Icon_State : 24|2@1+ (1,0) [0|3] "" XXX + SG_ LFA_USM : 27|2@1+ (1,0) [0|3] "" XXX + SG_ HDA_SysWarning : 29|2@1+ (1,0) [0|3] "" XXX + +BO_ 913 BCM_PO_11: 8 Vector__XXX + SG_ BCM_Door_Dri_Status : 5|1@0+ (1,0) [0|1] "" PT_ESC_ABS + SG_ BCM_Shift_R_MT_SW_Status : 39|2@0+ (1,0) [0|3] "" PT_ESC_ABS + SG_ LDA_BTN : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 1426 LABEL11: 8 XXX + SG_ CC_React : 34|1@1+ (1,0) [0|1] "" XXX + +BO_ 910 WHL_SPD12_FS: 5 iBAU + SG_ CRC : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ WHL_SPD12_AliveCounter : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ WHL_SPD_FL : 12|14@1+ (0.03125,0) [0|511.96875] "km/h" Vector__XXX + SG_ WHL_SPD_FR : 26|14@1+ (0.03125,0) [0|511.96875] "km/h" Vector__XXX + +BO_ 911 WHL_SPD13_FS: 5 iBAU + SG_ CRC : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ WHL_SPD13_AliveCounter : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ WHL_SPD_RL : 12|14@1+ (0.03125,0) [0|511.96875] "km/h" Vector__XXX + SG_ WHL_SPD_RR : 26|14@1+ (0.03125,0) [0|511.96875] "km/h" Vector__XXX + +BO_ 865 ADAS_PRK_11: 8 ADAS_PRK + SG_ CF_PCA_BrkReq : 24|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ CF_PCA_DclTrgtVal : 28|4@1+ (0.04,0) [0|0] "g" Vector__XXX + SG_ PCA_ALIVE_CNT : 40|4@1+ (1,0) [0|0] "" Vector__XXX + SG_ PCA_CHECK_SUM : 48|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 882 ELECT_GEAR: 8 XXX + SG_ Elect_Gear_Shifter : 16|4@1+ (1,0) [0|7] "" CLU + SG_ SLC_ON : 31|1@0+ (1,0) [0|1] "" CLU + SG_ SLC_SET_SPEED : 32|8@1+ (1,0) [0|255] "" CLU + +BO_ 881 E_EMS11: 8 XXX + SG_ Brake_Pedal_Pos : 0|8@1+ (1,0) [0|127] "" XXX + SG_ IG_Reactive_Stat : 8|3@1+ (1,0) [0|3] "" XXX + SG_ Gear_Change : 12|1@0+ (1,0) [0|31] "" XXX + SG_ Cruise_Limit_Status : 13|1@1+ (1,0) [0|1] "" XXX + SG_ Cruise_Limit_Target : 23|8@1+ (1,0) [0|15] "" XXX + SG_ Accel_Pedal_Pos : 31|8@1+ (1,0) [0|254] "" XXX + SG_ CR_Vcu_AccPedDep_Pos : 56|8@1+ (1,0) [0|254] "" XXX + +BO_ 1355 EV_PC6: 8 CGW + SG_ CF_Vcu_SbwWarnMsg : 16|3@1+ (1,0) [0|7] "" Vector__XXX + +BO_ 1430 EV_PC2: 8 CGW + SG_ CR_Ldc_ActVol_LS_V : 32|8@1+ (0.1,0) [0|0] "V" Vector__XXX + +BO_ 1535 EV_PC10: 8 CGW + SG_ CF_Vcu_EpbRequest : 37|1@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 908 RSPA11: 8 RSPA + SG_ CF_RSPA_State : 0|4@1+ (1,0) [0|15] "" XXX + SG_ CF_RSPA_Act : 4|2@1+ (1,0) [0|3] "" XXX + SG_ CF_RSPA_DecCmd : 6|2@1+ (1,0) [0|3] "" XXX + SG_ CF_RSPA_Trgt_Spd : 8|10@1+ (0.01,0) [0|10.23] "km/h" XXX + SG_ CF_RSPA_StopReq : 18|1@1+ (1,0) [0|2] "" XXX + SG_ CR_RSPA_EPB_Req : 22|2@1+ (1,0) [0|3] "" XXX + SG_ CF_RSPA_ACC_ACT : 50|1@1+ (1,0) [0|2] "" XXX + SG_ CF_RSPA_AliveCounter : 52|4@1+ (1,0) [0|15] "" XXX + SG_ CF_RSPA_CRC : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 914 S_MDPS11: 8 XXX + SG_ CF_Mdps_Stat : 0|4@1+ (1,0) [0|15] "" XXX + SG_ CR_Mdps_DrvTq : 8|12@1+ (1,0) [0|15] "" XXX + SG_ CR_Mdps_StrAng : 24|16@1- (1,0) [0|65535] "" XXX + SG_ CF_Mdps_AliveCnt : 47|8@0+ (1,0) [0|255] "" XXX + SG_ CF_Mdps_Chksum : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 357 S_MDPS12: 8 XXX + SG_ NEW_SIGNAL_1 : 0|12@1+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_2 : 12|12@1+ (1,0) [0|4095] "" XXX + SG_ Counter : 48|4@1+ (1,0) [0|15] "" XXX + SG_ Checksum : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 352 AHB1: 8 iBAU + SG_ CF_Ahb_SLmp : 0|2@1+ (1,0) [0|3] "" CLU + SG_ CF_Ahb_Def : 2|2@1+ (1,0) [0|3] "" CGW + SG_ CF_Ahb_Act : 4|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ CF_Ahb_Diag : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ CF_Ahb_WLmp : 7|1@1+ (1,0) [0|1] "" CLU + SG_ CR_Ahb_StDep_mm : 8|16@1- (0.1,0) [-3276.8|3276.7] "mm" Vector__XXX + SG_ CF_Ahb_SnsFail : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ CF_Ahb_PedalCalStat : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ CF_Ahb_Bzzr : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ CF_Ahb_ChkSum : 56|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 1191 MFC_4a7: 8 XXX + SG_ PAINT1 : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 1162 BCA11: 8 BCW + SG_ CF_BCA_State : 16|3@1+ (1,0) [0|7] "" CLU,iBAU + SG_ CF_BCA_Warning : 19|2@1+ (1,0) [0|3] "" CLU,iBAU + SG_ AliveCounter : 21|4@1+ (1,0) [0|15] "" CLU,iBAU + SG_ RCCA_Brake_Command : 29|1@1+ (1,0) [0|1] "" iBAU + SG_ Check_Sum : 56|8@1+ (1,0) [0|16] "" iBAU + +BO_ 1136 P_STS: 8 CGW + SG_ HCU1_STS : 6|2@1+ (1,0) [0|3] "" BCW,EPB,FCA,MDPS,SCC,iBAU + SG_ HCU5_STS : 8|2@1+ (1,0) [0|3] "" EPB,FCA,MDPS,iBAU + SG_ Counter : 58|4@1+ (1,0) [0|15] "" MDPS + SG_ Checksum : 62|2@1+ (1,0) [0|3] "" MDPS + +BO_ 304 YRS11: 8 ACU + SG_ CR_Yrs_Yr : 0|16@1+ (0.005,-163.84) [-163.84|163.83] "deg/s" CGW,iBAU + SG_ CR_Yrs_LatAc : 16|16@1+ (0.000127465,-4.17677312) [-4.17677312|4.17651819] "g" iBAU + SG_ CF_Yrs_YrStat : 32|4@1+ (1,0) [0|15] "" iBAU + SG_ CF_Yrs_LatAcStat : 36|4@1+ (1,0) [0|15] "" iBAU + SG_ CF_Yrs_MCUStat : 40|4@1+ (1,0) [0|15] "" iBAU + SG_ CR_Yrs_MsgCnt1 : 48|4@1+ (1,0) [0|15] "" iBAU + SG_ CR_Yrs_Crc1 : 56|8@1+ (1,0) [0|255] "" iBAU + +BO_ 320 YRS12: 8 ACU + SG_ CF_Yrs_LongAcStat : 16|4@1+ (1,0) [0|15] "" iBAU + SG_ CF_IMU_ResetStat : 20|4@1+ (1,0) [0|15] "" iBAU + SG_ YRS_Temp : 24|8@1+ (1,-68) [-68|187] "" iBAU + SG_ YRS_TempStat : 32|4@1+ (1,0) [0|15] "" iBAU + SG_ CF_Yrs_Type : 36|4@1+ (1,0) [0|15] "" iBAU + SG_ CR_Yrs_MsgCnt2 : 48|4@1+ (1,0) [0|15] "" iBAU + SG_ CR_Yrs_Crc2 : 56|8@1+ (1,0) [0|255] "" iBAU + SG_ CR_Yrs_LongAc : 0|16@1+ (0.000127465,-4.17677312) [-4.17677312|4.17651819] "g" CGW,iBAU + +BO_ 1173 YRS13: 8 ACU + SG_ YRS_SeralNo : 16|48@1+ (1,0) [0|281474976710655] "" iBAU + +BO_ 870 EMS_366: 8 EMS + SG_ TQI_1 : 0|8@1+ (0.390625,0) [0|99.6094] "%" MDPS + SG_ N : 8|16@1+ (0.25,0.0) [0.0|16383.75] "rpm" MDPS + SG_ TQI_2 : 24|8@1+ (0.390625,0) [0|99.6094] "%" MDPS + SG_ VS : 40|8@1+ (1,0) [0|255] "km/h" MDPS + SG_ SWI_IGK : 48|1@0+ (1,0) [0|1] "" XXX + +BO_ 854 M_356: 8 XXX + SG_ PAINT1 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ PAINT2 : 34|2@0+ (1,0) [0|1] "" XXX + SG_ PAINT3 : 36|2@0+ (1,0) [0|3] "" XXX + SG_ PAINT4 : 38|1@0+ (1,0) [0|1] "" XXX + +BO_ 1042 ICM_412h: 8 ICM + SG_ T_Outside_input : 0|9@0+ (0.01,0) [0|5] "V" Vector__XXX + SG_ WarningSoundOutput_1Group : 5|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ WarningSoundOutput_2Group : 6|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ WarningSoundOutput_3Group : 7|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ TRIP_A_DT_Display_clock : 22|7@0+ (1,0) [0|99] "clock" Vector__XXX + SG_ TRIP_A_DT_Display_minute : 29|6@0+ (1,0) [0|59] "minute" Vector__XXX + SG_ TRIP_B_DT_Display_clock : 38|7@0+ (1,0) [0|99] "clock" Vector__XXX + SG_ TRIP_B_DT_Display_minute : 45|6@0+ (1,0) [0|59] "minute" Vector__XXX + SG_ PopupMessageOutput_1Level : 48|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_2Level : 49|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_3Level : 50|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_4Level : 51|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_5Level : 52|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_6Level : 53|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_7Level : 54|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PopupMessageOutput_8Level : 55|1@0+ (1,0) [0|1] "" Vector__XXX + +BO_ 1348 Navi_HU: 8 XXX + SG_ SpeedLim_Nav_Clu : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SpeedLim_Nav_General : 29|1@0+ (1,0) [0|1] "" XXX + SG_ SpeedLim_Nav_Cam : 30|1@0+ (1,0) [0|1] "" XXX + +CM_ "BO_ E_EMS11: All (plug-in) hybrids use this gas signal: CR_Vcu_AccPedDep_Pos, and all EVs use the Accel_Pedal_Pos signal. See hyundai/values.py for a specific car list"; +CM_ 145 "Contains signal with accelerator pedal press. Used by fuel cell hydrogen-powered (FCEV) cars such as the 2021 Hyundai Nexo."; +CM_ 512 "Contains signal with gear shifter. Used by fuel cell hydrogen-powered (FCEV) cars such as the 2021 Hyundai Nexo."; +CM_ SG_ 871 CF_Lvr_IsgState "Idle Stop and Go"; +CM_ SG_ 1056 SCCInfoDisplay "Goes to 1 for a second while transitioning from Cruise Control to No Message"; +CM_ SG_ 1348 SpeedLim_Nav_Clu "Speed limit displayed on Nav, Cluster and HUD"; + +VAL_ 274 CUR_GR 1 "D" 2 "D" 3 "D" 4 "D" 5 "D" 6 "D" 7 "D" 8 "D" 14 "R" 0 "P"; +VAL_ 512 HYDROGEN_GEAR_SHIFTER 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; +VAL_ 871 CF_Lvr_IsgState 0 "enabled" 1 "activated" 2 "unknown" 3 "disabled"; +VAL_ 871 CF_Lvr_Gear 12 "T" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; +VAL_ 882 Elect_Gear_Shifter 4 "S" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; +VAL_ 905 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled"; +VAL_ 909 CF_VSM_Warn 2 "FCW" 3 "AEB"; +VAL_ 916 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue"; +VAL_ 1056 SCCInfoDisplay 0 "No Message" 2 "Cruise Control" 3 "Lost Lead" 4 "Standstill"; +VAL_ 1057 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault"; +VAL_ 1157 HDA_Icon_State 0 "no_hda" 1 "white_hda" 2 "green_hda"; +VAL_ 1157 LFA_SysWarning 0 "no_message" 1 "switching_to_hda" 2 "switching_to_scc" 3 "lfa_error" 4 "check_hda" 5 "keep_hands_on_wheel_orange" 6 "keep_hands_on_wheel_red"; +VAL_ 1157 LFA_Icon_State 0 "no_wheel" 1 "white_wheel" 2 "green_wheel" 3 "green_wheel_blink"; +VAL_ 1157 HDA_SysWarning 0 "no_message" 1 "driving_convenience_systems_cancelled" 2 "highway_drive_assist_system_cancelled"; +VAL_ 1322 CF_Clu_Gear 1 "P" 2 "R" 4 "N" 8 "D"; diff --git a/opendbc_repo/opendbc/dbc/hyundai_santafe_2007.dbc b/opendbc_repo/opendbc/dbc/hyundai_santafe_2007.dbc new file mode 100644 index 0000000000..c0f4f7e180 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/hyundai_santafe_2007.dbc @@ -0,0 +1,118 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: AWD ECU TCU ESP SAS ABS + + +BO_ 339 ESP_Flags: 8 ESP + SG_ ABD_Active : 3|1@1+ (1,0) [0|1] "yes/no" AWD,ECU,TCU + SG_ TCS_Active : 9|1@1+ (1,0) [0|1] "yes/no" AWD,ECU,TCU + SG_ ABS_Active : 10|1@1+ (1,0) [0|1] "yes/no" AWD,ECU,TCU + SG_ ESP_Off : 12|1@1+ (1,0) [0|1] "yes/no" AWD,ECU,TCU + SG_ ESP_Active : 14|1@1+ (1,0) [0|1] "yes/no" AWD,ECU,TCU + SG_ VehicleSpeed : 16|8@1+ (1,0) [0|254] "km/h" AWD,ECU,TCU + SG_ TorqueRequestFast : 24|8@1+ (0.390625,0) [0|99.609375] "%" ECU,TCU + SG_ TorqueRequestSlow : 40|8@1+ (0.390625,0) [0|99.609375] "%" ECU,TCU + +BO_ 497 ESP_WheelSpeed: 8 ESP + SG_ FrontRightWheelSpeed : 16|12@1+ (0.125,0) [0|511.875] "km/h" AWD + SG_ FrontLeftWheelSpeed : 28|12@1+ (0.125,0) [0|511.875] "km/h" AWD + SG_ RearRightWheelSpeed : 40|12@1+ (0.125,0) [0|511.875] "km/h" AWD + SG_ RearLeftWheelSpeed : 52|12@1+ (0.125,0) [0|511.875] "km/h" AWD + +BO_ 608 ECU_Data1: 8 ECU + SG_ TorqueMin : 0|8@1+ (0.390625,0) [0|99.609375] "%" ESP,TCU + SG_ Torque : 8|8@1+ (0.390625,0) [0|99.609375] "%" ESP,TCU + SG_ TorqueTarget : 16|8@1+ (0.390625,0) [0|99.609375] "%" ESP,TCU + SG_ CruiseEnabled : 25|1@1+ (1,0) [0|1] "yes/no" TCU + SG_ CruiseActive : 26|1@1+ (1,0) [0|1] "yes/no" TCU + SG_ TorqueMax : 40|8@1+ (0.390625,0) [0|99.609375] "%" ESP,TCU + +BO_ 640 ECU_Data2: 8 ECU + SG_ RPM : 32|8@1+ (32,0) [0|8160] "rpm" TCU + SG_ MAF : 40|8@1+ (5.447,0) [0|1388.985] "mg/TDC" TCU + SG_ IAT : 48|8@1- (0.75,-48) [-48|143.25] "C" TCU + SG_ MAP : 56|8@1+ (0.47058,0) [0|119.9979] "KPa" TCU + +BO_ 688 SAS_Data: 5 SAS + SG_ SAS_Angle : 0|16@1- (0.1,0) [-3276.8|3276.7] "deg" AWD,ECU,ESP,TCU + SG_ SAS_Speed : 16|8@1+ (4,0) [0|1016] "deg/s" ESP,TCU + SG_ SAS_Status : 24|8@1+ (1,0) [0|255] "" ESP,TCU + SG_ Msg_Count : 32|4@1+ (1,0) [0|15] "" ESP + SG_ Check_Sum : 36|4@1+ (1,0) [0|15] "" ECU,ESP + +BO_ 809 ECU_Data5: 8 ECU + SG_ ECT : 8|8@1- (0.75,-48) [-48|143.25] "C" AWD,ABS,ESP,TCU + SG_ BrakeActive : 32|2@1+ (1,0) [0|3] "yes/no" AWD,ABS,ESP,TCU + SG_ TPS : 40|8@1+ (0.47265625,-15) [-15|105.52734375] "%" AWD,ABS,ESP,TCU + +BO_ 1064 AWD_Data1: 8 AWD + SG_ ClutchDuty : 16|8@1+ (1,0) [0|100] "%" ABS,ESP + SG_ ClutchLocked : 44|1@1+ (1,0) [0|1] "yes/no" ABS,ESP + +BO_ 1065 AWD_Data2: 8 AWD + SG_ SteeringWheelPosition : 0|16@1+ (1,-600) [-600|600] "deg" ABS + SG_ FrontRightWheelSpeed : 16|8@1+ (1,0) [0|254] "km/h" ABS + SG_ FrontLeftWheelSpeed : 24|8@1+ (1,0) [0|254] "km/h" ABS + SG_ RearRightWheelSpeed : 32|8@1+ (1,0) [0|254] "km/h" ABS + SG_ RearLeftWheelSpeed : 40|8@1+ (1,0) [0|254] "km/h" ABS + +BO_ 1087 TCU_Data: 8 TCU + SG_ CurrentGear : 0|3@1+ (1,0) [0|7] "" ECU + SG_ GearSwitch : 3|1@1+ (1,0) [0|1] "yes/no" ECU + SG_ SelectorPosition : 8|4@1+ (1,0) [0|15] "" ECU + SG_ InputShaftSpeed : 40|16@1+ (0.25,0) [0|16383.5] "rpm" ECU + +BO_ 1349 ECU_Data6: 8 ECU + SG_ BatteryVoltage : 24|8@1+ (0.1015625,0) [0|25.8984375] "V" ABS,ESP + +BO_ 1408 ABS_WheelSpeed: 8 ABS + SG_ FrontRightWheelSpeed : 16|12@1+ (0.125,0) [0|511.875] "km/h" AWD + SG_ FrontLeftWheelSpeed : 28|12@1+ (0.125,0) [0|511.875] "km/h" AWD + SG_ RearRightWheelSpeed : 40|12@1+ (0.125,0) [0|511.875] "km/h" AWD + SG_ RearLeftWheelSpeed : 52|12@1+ (0.125,0) [0|511.875] "km/h" AWD + +BO_ 1695 ECU_Data7: 8 ECU + SG_ ECU_Temperature : 8|8@1- (1,-28) [-28|227] "C" TCU + +BO_ 1984 SAS_Calibration: 2 ESP + SG_ CCW : 0|4@1+ (1,0) [0|15] "" SAS + SG_ CID : 4|11@1+ (1,0) [0|2047] "" SAS + + + +VAL_ 1087 CurrentGear 7 "R" 0 "N" 1 "1" 2 "2" 3 "3" 4 "4" ; +VAL_ 1087 SelectorPosition 7 "R" 6 "N" 5 "D" 8 "M" 15 "P" ; + diff --git a/opendbc_repo/opendbc/dbc/luxgen_s5_2015.dbc b/opendbc_repo/opendbc/dbc/luxgen_s5_2015.dbc new file mode 100644 index 0000000000..34fe6b6460 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/luxgen_s5_2015.dbc @@ -0,0 +1,153 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 928 EPB_STATUS: 8 XXX + SG_ EPB_BRAKE : 16|1@1+ (1,0) [0|3] "" XXX + +BO_ 1104 SEATBELT_STATUS: 8 XXX + SG_ DRIVER_SEAT_BELT_ONOFF : 21|1@0+ (1,0) [0|3] "" XXX + +BO_ 1056 BODY_ECU_STATUS: 8 XXX + SG_ DOOR_RL_STATUS : 18|1@0+ (1,0) [0|255] "" XXX + SG_ DOOR_FL_STATUS : 13|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_FR_STATUS : 12|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_RR_STATUS : 19|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_BACK_DOOR_STATUS : 22|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_SIGNAL_STATUS : 10|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_SIGNAL_STATUS : 9|1@0+ (1,0) [0|1] "" XXX + +BO_ 832 GEAR_RPM_SPEED_STATUS: 8 XXX + SG_ TRANS_MODE : 7|5@1+ (1,0) [0|0] "" XXX + SG_ TRANS_GEAR_POS : 2|3@0+ (1,0) [0|1] "" XXX + SG_ ENGINE_RPM1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ENGINE_TEMP : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 821 THROTTLE_STATUS: 8 XXX + SG_ CRUSE_ONOFF : 2|1@0+ (1,0) [0|1] "on/off" XXX + SG_ CRUSE_ENABLED : 4|1@0+ (1,0) [0|1] "" XXX + SG_ THROTTLE_PEDAL_POS : 32|8@1+ (1,0) [0|255] "" XXX + SG_ THROTTLE_POS : 24|8@1+ (1,0) [0|255] "" XXX + SG_ RPM : 48|8@1- (1,0) [0|65535] "" XXX + +BO_ 922 STEERING_ANGLE_STATUS: 8 XXX + SG_ STEER_ANGLE_9000 : 7|16@0- (1,0) [0|65535] "" XXX + +BO_ 906 WHEEL_SPEEDS: 8 XXX + SG_ SPEED_FR : 24|8@1+ (1,0) [0|255] "" XXX + SG_ ABS_UNDEF1 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ SPEED_FL : 0|8@1+ (1,0) [0|255] "" XXX + +BO_ 848 ABS_WHEELS_STATUS: 8 XXX + SG_ NEW_SIGNAL_1 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 15|8@0+ (1,0) [0|255] "" XXX + +BO_ 1402 DASH_STATUS: 8 XXX + SG_ CAR_SPEED : 32|8@1+ (1,0) [0|255] "" XXX + SG_ DASH_INFO2 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ DASH_INFO0 : 0|8@1+ (1,0) [0|255] "" XXX + SG_ DASH_INFO_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ DASH_INFO_3 : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 1306 _SPEEDX: 8 XXX + SG_ DASH_CAR_SPEED : 7|9@0+ (1,0) [0|255] "" XXX + +BO_ 1296 undefined: 8 XXX + +BO_ 790 ENGINE_DATA: 8 XXX + SG_ _X2 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 1313 undefined_2: 8 XXX + +BO_ 1312 __trigger_every_range: 8 XXX + SG_ __SIGNAL_every_interval : 4|1@0+ (1,0) [0|1] "" XXX + +BO_ 896 undefined_3: 8 XXX + SG_ NEW_SIGNAL_1 : 32|4@1+ (1,0) [0|15] "" XXX + +BO_ 809 undefined_4: 8 XXX + +BO_ 864 BREAK_TCS_STATUS: 8 XXX + SG_ SPEED3 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ TCS_ON_FF : 45|1@0+ (1,0) [0|1] "" XXX + SG_ XXXX1 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRSSED : 42|1@0+ (1,0) [0|1] "" XXX + +BO_ 842 undefined_5: 8 XXX + +BO_ 880 WHEEL_RPM_STATUS: 8 XXX + SG_ WHEEL_RL_SPEED : 23|16@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_FR_SPEED : 39|16@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_FL_SPEED : 55|16@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_RR_SPEED : 7|16@0- (1,0) [0|255] "" XXX + +BO_ 1040 CONSOLE_STATUS: 8 XXX + SG_ LEFT_SIGNAL_SWITCH : 1|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_SIGNAL_SWITCH : 2|1@0+ (1,0) [0|1] "" XXX + SG_ HEAD_LIGHT_HANDLE_SWITCH : 3|1@0+ (1,0) [0|1] "" XXX + SG_ HID_LIGHT_SWITCH : 4|1@0+ (1,0) [0|1] "" XXX + SG_ YELLOW_WARN_TEMP_TRIGGER : 5|1@0+ (1,0) [0|1] "" XXX + SG_ HID_LIGHT_HANDLE_SWITCH : 6|1@0+ (1,0) [0|1] "" XXX + SG_ MIX_MODE : 7|1@0+ (1,0) [0|1] "" XXX + SG_ slider_rain_bar : 13|1@0+ (1,0) [0|1] "" XXX + SG_ temp_slider_rain_bar : 15|1@0+ (1,0) [0|1] "" XXX + SG_ temp_water_push : 11|1@0+ (1,0) [0|1] "" XXX + +BO_ 1120 HAVC_STATUS: 8 XXX + SG_ HAVC_TEMP : 32|8@1+ (1,0) [0|255] "" XXX + + +CM_ SG_ 1104 DRIVER_SEAT_BELT_ONOFF "0 - on , 1 = off"; +CM_ SG_ 1056 DOOR_RL_STATUS "04 - RL - open"; +CM_ SG_ 1056 DOOR_FL_STATUS "28 - FL open , 38 - FR"; +CM_ SG_ 1056 RIGHT_SIGNAL_STATUS "R,L shows at same time means hazard"; +CM_ SG_ 832 TRANS_MODE "AT - 85 / MT - 8D"; +CM_ SG_ 832 TRANS_GEAR_POS "R-7 , 0 - N"; +CM_ SG_ 821 CRUSE_ONOFF "Cruse Switch"; +CM_ SG_ 821 CRUSE_ENABLED "Cruse enabled"; +CM_ SG_ 821 THROTTLE_PEDAL_POS "Real Pedal Pos"; +CM_ SG_ 821 THROTTLE_POS "Throttle Pos for Cruse Mode"; +CM_ SG_ 906 ABS_UNDEF1 "ABS force"; +CM_ SG_ 906 SPEED_FL "used for car speed in dash board"; +CM_ SG_ 864 TCS_ON_FF "ON = 1, OFF =0"; diff --git a/opendbc_repo/opendbc/dbc/mazda_2017.dbc b/opendbc_repo/opendbc/dbc/mazda_2017.dbc new file mode 100644 index 0000000000..d2bb77b351 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/mazda_2017.dbc @@ -0,0 +1,791 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 117 STEER_RELATED: 8 XXX + SG_ CTR : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 49|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 50|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 54|4@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_3 : 55|1@0+ (1,0) [0|63] "" XXX + SG_ STEER_ANGLE_2 : 39|16@0+ (0.1,-1800) [0|131071] "" XXX + SG_ STEER_TORQUE : 19|12@0+ (1,-2000) [0|255] "" XXX + +BO_ 118 RPM_RELATED: 8 XXX + SG_ CTR : 7|8@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_2 : 19|12@0+ (1,0) [0|4095] "" XXX + +BO_ 514 ENGINE_DATA: 8 XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|127] "" XXX + SG_ RPM : 7|16@0+ (0.25,0) [0|8500] "rpm" XXX + SG_ SPEED : 23|16@0+ (0.01,0) [0|32767] "kph" XXX + SG_ PEDAL_GAS : 39|12@0+ (1,0) [0|255] "%" XXX + +BO_ 357 PEDALS: 8 XXX + SG_ NEW_SIGNAL_6 : 31|4@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 8|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_ACTIVE : 3|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_OFF : 2|1@1+ (1,0) [0|15] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|15] "" XXX + SG_ STANDSTILL : 26|1@0+ (1,0) [0|16777215] "" XXX + SG_ NEW_SIGNAL_3 : 23|8@0+ (1,0) [0|3] "" XXX + SG_ BRAKE_ON : 4|1@0+ (1,0) [0|1] "" XXX + SG_ NO_BRAKE : 6|1@0+ (1,0) [0|7] "" XXX + SG_ BRAKE_ON_2 : 7|1@1+ (1,0) [0|255] "" XXX + SG_ NO_BRAKE_2 : 15|1@0+ (1,0) [0|7] "" XXX + SG_ GEAR : 48|5@1+ (1,0) [0|255] "" XXX + +BO_ 533 WHEEL_SPEEDS: 8 XXX + SG_ FL : 7|16@0+ (0.01,-100) [0|16383] "kph" XXX + SG_ FR : 23|16@0+ (0.01,-100) [0|65535] "kph" XXX + SG_ RL : 39|16@0+ (0.01,-100) [0|15] "kph" XXX + SG_ RR : 55|16@0+ (0.01,-100) [0|65535] "kph" XXX + +BO_ 134 STEER2: 8 XXX + SG_ CTR : 22|4@0+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_4 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ CTR_2 : 28|3@1+ (1,0) [0|7] "" XXX + SG_ STEER_ANGLE_ROUGH : 26|11@0+ (1,-1000) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 18|3@0+ (1,0) [0|1] "" XXX + SG_ STEER_ANGLE : 7|16@0+ (0.1,-1600) [-500|500] "deg" XXX + SG_ NEW_SIGNAL_1 : 63|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 47|8@0+ (1,0) [0|7] "" XXX + +BO_ 576 STEER_TORQUE: 8 XXX + SG_ NEW_SIGNAL_1 : 23|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 47|1@0+ (1,0) [0|1] "" XXX + SG_ SENSOR1 : 39|8@0+ (1,-128) [0|127] "" XXX + SG_ STEER_TORQUE_MOTOR : 46|15@0- (0.1,0) [-3000|3000] "tbd" XXX + SG_ NEW_SIGNAL_2 : 62|4@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_4 : 15|8@0+ (1,0) [0|127] "" XXX + SG_ STEER_TORQUE_SENSOR : 7|8@0+ (1,-127) [-85|85] "" XXX + +BO_ 577 STEER_RATE: 8 XXX + SG_ STEER_ANGLE_RATE : 23|16@0+ (0.25,-8192) [0|1] "deg/s" XXX + SG_ CTR : 7|4@0+ (1,0) [0|15] "" XXX + SG_ LKAS_REQUEST : 3|12@0+ (1,-2048) [0|15] "" XXX + SG_ LKAS_EFFECTIVE : 39|12@0+ (1,-2048) [0|255] "" XXX + SG_ HANDS_OFF_5_SECONDS : 51|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_BLOCK : 50|1@1+ (1,0) [0|3] "" XXX + SG_ LKAS_TRACK_STATE : 52|1@0+ (1,0) [0|3] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 582 CAM_LANEMAYBE: 8 XXX + SG_ NEW_SIGNAL_4 : 40|8@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_1 : 31|16@0- (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 55|16@0+ (1,0) [0|65535] "" XXX + SG_ CTR : 7|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 15|16@0+ (1,0) [0|65535] "" XXX + +BO_ 541 CAM_EMPTY: 8 XXX + +BO_ 605 CAM_PEDESTRIAN: 8 XXX + SG_ CTR : 17|4@0+ (1,0) [0|255] "" XXX + SG_ AEB_NOT_ENGAGED : 13|1@0+ (1,0) [0|1] "" XXX + SG_ PED_WARNING : 9|1@0+ (1,0) [0|255] "" XXX + SG_ PED_BRAKE : 3|3@0+ (1,0) [0|7] "" XXX + SG_ RST_CTR : 23|6@0+ (1,0) [0|63] "" XXX + SG_ S1 : 29|4@0+ (1,0) [0|31] "" XXX + SG_ BRAKE_WARNING : 25|1@0+ (1,0) [0|1] "" XXX + +BO_ 578 CAM_LANETRACK: 8 XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ ZERO : 53|6@0+ (1,0) [0|63] "" XXX + SG_ CTR : 7|4@0+ (1,0) [0|15] "" XXX + SG_ LINE2 : 9|10@0+ (1,-686) [0|255] "" XXX + SG_ LANE_CURVE : 31|8@0+ (1,-127) [0|255] "" XXX + SG_ SIG1 : 39|8@0+ (1,-128) [0|255] "" XXX + SG_ SIG2 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ SIG3 : 55|2@0+ (1,0) [0|3] "" XXX + SG_ LINE1 : 3|10@0+ (1,-686) [0|1] "" XXX + +BO_ 579 CAM_LKAS: 8 XXX + SG_ CTR : 7|4@0+ (1,0) [0|15] "" XXX + SG_ ERR_BIT_1 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|15] "" XXX + SG_ LINE_NOT_VISIBLE : 19|1@0+ (1,0) [0|1] "" XXX + SG_ BIT_1 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ LDW : 23|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_REQUEST : 3|12@0+ (1,-2048) [0|2048] "" XXX + SG_ ERR_BIT_2 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ ANGLE_ENABLED : 52|1@0+ (1,0) [0|1] "" XXX + SG_ STEERING_ANGLE : 33|12@0+ (1,-2048) [-2048|2047] "" XXX + +BO_ 580 CAM_DISTANCE: 8 XXX + SG_ S1 : 0|8@1+ (1,0) [0|127] "" XXX + SG_ S2 : 15|8@0+ (1,0) [0|1] "" XXX + SG_ S3 : 16|8@1+ (1,0) [0|3] "" XXX + SG_ S4 : 24|8@1+ (1,0) [0|31] "" XXX + SG_ S5 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ DISTANCE : 47|8@0+ (1,0) [0|65535] "" XXX + SG_ S6 : 55|16@0+ (1,0) [0|255] "" XXX + +BO_ 581 CAM_IDK3: 8 XXX + SG_ S1 : 0|8@1+ (1,0) [0|15] "" XXX + SG_ S2 : 8|6@1+ (1,0) [0|255] "" XXX + SG_ S3 : 15|2@0+ (1,0) [0|3] "" XXX + SG_ S4 : 16|8@1+ (1,0) [0|15] "" XXX + SG_ S5 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ S6 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ S7 : 40|8@1+ (1,0) [0|3] "" XXX + SG_ S8 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ S9 : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 863 CAM_TRAFFIC_SIGNS: 8 XXX + SG_ NEW_SIGNAL_3 : 55|1@0+ (1,0) [0|127] "" XXX + SG_ FORWARD_COLLISION : 40|8@1+ (1,0) [0|7] "" XXX + SG_ SPEED_SIGN : 4|7@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 52|5@0+ (1,0) [0|31] "" XXX + SG_ SPEED_SIGN_CAM : 32|1@0+ (1,0) [0|32767] "" XXX + SG_ SPEED_SIGN_ON : 12|1@0+ (1,0) [0|3] "" XXX + SG_ STOP_SIGN : 31|4@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 33|1@0+ (1,0) [0|1] "" XXX + +BO_ 1157 CAM_SETTINGS: 8 XXX + SG_ SBS_WARNING_DISTANCE : 25|2@0+ (1,0) [0|127] "" XXX + SG_ SBS_SCBC : 28|2@0+ (1,0) [0|7] "" XXX + SG_ LKAS_ASSIT_TIMING : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LKAS_SENSETIVITY : 10|1@0+ (1,0) [0|1] "" XXX + SG_ ILKAS_NTERVENTION_ON2 : 17|1@0+ (1,0) [0|255] "" XXX + SG_ LANEE_DEPARTURE_ALERT : 16|2@0+ (1,0) [0|1] "" XXX + SG_ LKAS_INERVENTION_ON1 : 15|1@0+ (1,0) [0|1] "" XXX + SG_ WARNING : 11|1@0+ (1,0) [0|1] "" XXX + SG_ BIT1 : 12|1@0+ (1,0) [0|7] "" XXX + SG_ BIT2 : 14|1@0+ (1,0) [0|1] "" XXX + SG_ BIT3 : 18|1@0+ (1,0) [0|1] "" XXX + +BO_ 1160 CAM_Empty3: 8 XXX + SG_ NEW_SIGNAL_1 : 47|24@0+ (1,0) [0|16777215] "" XXX + +BO_ 1088 CAM_LANEINFO: 8 XXX + SG_ BIT3 : 62|1@0+ (1,0) [0|3] "" XXX + SG_ HANDS_ON_STEER_WARN_2 : 59|1@0+ (1,0) [0|1] "" XXX + SG_ HANDS_ON_STEER_WARN : 56|1@0+ (1,0) [0|3] "" XXX + SG_ S1_HBEAM : 54|1@0+ (1,0) [0|31] "" XXX + SG_ S1 : 52|1@0+ (1,0) [0|1] "" XXX + SG_ HANDS_WARN_3_BITS : 51|3@0+ (1,0) [0|7] "" XXX + SG_ ERR_BIT : 40|1@0+ (1,0) [0|1] "" XXX + SG_ NO_ERR_BIT : 14|1@0+ (1,0) [0|1] "" XXX + SG_ BIT2 : 13|1@0+ (1,0) [0|15] "" XXX + SG_ LANE_LINES : 10|3@0+ (1,0) [0|3] "" XXX + SG_ BIT1 : 6|1@0+ (1,0) [0|65535] "" XXX + SG_ LINE_NOT_VISIBLE : 1|1@0+ (1,0) [0|1] "" XXX + SG_ LINE_VISIBLE : 0|1@0+ (1,0) [0|3] "" XXX + SG_ LDW_WARN_RL : 58|1@0+ (1,0) [0|1] "" XXX + SG_ LDW_WARN_LL : 57|1@0+ (1,0) [0|1] "" XXX + SG_ TJA : 38|3@0+ (1,0) [0|7] "" XXX + SG_ TJA_TRANSITION : 27|2@0+ (1,0) [0|63] "" XXX + +BO_ 1479 NEW_MSG_470: 8 XXX + +BO_ 1456 NEW_MSG_300: 8 XXX + +BO_ 1446 NEW_MSG_a600: 8 XXX + +BO_ 1416 MSG_18: 8 XXX + +BO_ 1086 DOORS: 8 XXX + SG_ LEFTGATE : 32|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 53|1@0+ (1,0) [0|255] "" XXX + SG_ KEYFOB_HORN : 2|1@0+ (1,0) [0|1] "" XXX + SG_ KEYFOB_LOCK : 3|1@0+ (1,0) [0|1] "" XXX + SG_ KEYFOB_UNLOCK : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CTR1 : 8|4@1+ (1,0) [0|3] "" XXX + SG_ CTR2 : 16|4@1+ (1,0) [0|15] "" XXX + SG_ BR : 34|1@0+ (1,0) [0|1] "" XXX + SG_ BL : 35|1@0+ (1,0) [0|1] "" XXX + SG_ FR : 36|1@0+ (1,0) [0|1] "" XXX + SG_ FL : 37|1@0+ (1,0) [0|255] "" XXX + SG_ DOORS_UNLOCKED : 30|1@0+ (1,0) [0|255] "" XXX + +BO_ 977 TWO_STATES: 8 XXX + SG_ NEW_SIGNAL_1 : 50|1@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_2 : 56|4@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_3 : 28|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 24|4@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 36|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 47|8@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 51|1@0+ (1,0) [0|1] "" XXX + +BO_ 1085 MSG_12: 8 XXX + SG_ NEW_SIGNAL_3 : 36|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 16|8@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 48|8@1+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 31|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 24|1@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_6 : 40|3@1+ (1,0) [0|7] "" XXX + +BO_ 159 MSG_11: 8 XXX + SG_ NEW_SIGNAL_1 : 50|4@1+ (1,0) [0|15] "" XXX + SG_ INCREASEING : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 1278 NEW_MSG_3: 8 XXX + SG_ NEW_SIGNAL_2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ MILAGE_MAYBE : 7|16@0+ (1,0) [0|255] "" XXX + +BO_ 1277 NEW_MSG_10: 8 XXX + SG_ NEW_SIGNAL_3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ counter : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 1275 2017_5: 8 XXX + SG_ counter : 4|5@0+ (1,0) [0|255] "" XXX + +BO_ 1274 NEW_MSG_12: 8 XXX + SG_ NEW_SIGNAL_1 : 24|4@1+ (1,0) [0|15] "" XXX + SG_ CTR : 55|4@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_2 : 35|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 32|3@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_4 : 48|4@1+ (1,0) [0|7] "" XXX + +BO_ 1180 last_byte_roughRPM: 8 XXX + SG_ NEW_SIGNAL_1 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1078 HVAC: 8 XXX + SG_ NEW_SIGNAL_1 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 8|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 23|1@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 56|5@0+ (1,0) [0|255] "" XXX + +BO_ 1056 CHECK_AND_TEMP: 8 XXX + SG_ NEW_SIGNAL_1 : 29|6@0+ (1,0) [0|255] "" XXX + SG_ counter_or_GEAR : 15|8@0+ (1,0) [0|255] "" XXX + SG_ CTR : 23|8@0+ (1,0) [0|255] "" XXX + SG_ STANDSTILL : 32|1@0+ (1,0) [0|255] "" XXX + SG_ COOLANT_TEMP : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LOW_ENGINE_OIL_PRESSURE : 43|1@0+ (1,0) [0|1] "" XXX + SG_ CHECK_FUEL_CAP : 40|1@0+ (1,0) [0|1] "" XXX + SG_ CHARGING_SYSTEM_MALFUNCTION : 38|1@0+ (1,0) [0|1] "" XXX + SG_ OUTDOOR_TEMP : 63|8@0+ (0.25,-63) [0|255] "cel" XXX + +BO_ 1045 TRACTION: 8 XXX + SG_ NEW_SIGNAL_2 : 20|1@0+ (1,0) [0|3] "" XXX + SG_ CTR2 : 19|4@0+ (1,0) [0|31] "" XXX + SG_ CTR3 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ IS_MOVING : 12|1@0+ (1,0) [0|3] "" XXX + SG_ CTR1 : 53|6@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 54|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE : 55|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_WARNING : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ABS_MALFUNCTION : 1|2@0+ (1,0) [0|3] "" XXX + SG_ DSC_OFF : 3|1@0+ (1,0) [0|1] "" XXX + SG_ TCS_DCS_MALFUNCTION : 6|2@0+ (1,0) [0|3] "" XXX + SG_ LOUD_BEEP : 28|1@0+ (1,0) [0|1] "" XXX + SG_ TPMS_WARNING_DOUBLE_BLINK : 31|1@0+ (1,0) [0|1] "" XXX + +BO_ 1034 MSG_07: 8 XXX + SG_ NEW_SIGNAL_1 : 6|3@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 0|4@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 15|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_4 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_8 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_9 : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 870 RADAR_366_STATIC: 8 XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 867 RADAR_363: 8 XXX + SG_ CTR : 59|4@0+ (1,0) [0|255] "" XXX + SG_ STATIC_4 : 43|16@0+ (1,0) [0|255] "" XXX + SG_ FLIPPY_1 : 31|3@0+ (1,0) [0|7] "" XXX + SG_ FLIPPY_2 : 47|1@0+ (1,0) [0|15] "" XXX + SG_ FLIPPY_4 : 44|1@0+ (1,0) [0|3] "" XXX + SG_ FLIPPY_3 : 46|1@0+ (1,0) [0|3] "" XXX + SG_ CURVE_1 : 7|12@0+ (1,0) [0|255] "" XXX + SG_ CURVE_2 : 11|12@0+ (1,0) [0|255] "" XXX + SG_ CURVE_3 : 28|13@0+ (1,0) [0|255] "" XXX + +BO_ 130 STEER: 8 XXX + SG_ NEW_SIGNAL_5 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ CTR : 47|4@0+ (1,0) [0|255] "" XXX + SG_ STEER_ANGLE : 23|16@0+ (0.05,-1600) [500|-500] "deg" XXX + SG_ CHKSUM_MAYBE : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 120 BRAKE: 8 XXX + SG_ CTR : 55|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PRESSURE : 39|8@0+ (1,0) [0|255] "" XXX + SG_ VEHICLE_ACC_X : 5|13@0+ (0.01,-40) [-40|40] "m/s^2" XXX + SG_ VEHICLE_ACC_Y : 8|13@0+ (0.001,-4.096) [-4.096|4.096] "m/s^2" XXX + +BO_ 304 GEAR_RELATED: 8 XXX + SG_ NEW_SIGNAL_1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 865 RADAR_DISTANCE: 8 XXX + SG_ CTR : 56|4@1+ (1,0) [0|15] "" XXX + SG_ STATIC : 36|3@0+ (1,0) [0|31] "" XXX + SG_ DISTANCE_RELATED : 33|4@0+ (1,0) [0|3] "" XXX + SG_ SPEED_INVERSE : 43|12@0- (-0.225,0) [0|255] "kph" XXX + SG_ DISTANCE_LEAD : 7|24@0+ (1,0) [0|31] "" XXX + SG_ RELATIVE_VEL_LEAD : 31|11@0- (1,0) [0|255] "" XXX + +BO_ 836 NEW_MSG_19: 8 XXX + SG_ CTR : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CTR2 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 832 SEATBELT: 8 XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ PASSENGER_SEATBELT : 26|1@1+ (1,0) [0|7] "" XXX + SG_ CTR1 : 15|4@0+ (1,0) [0|15] "" XXX + SG_ CTR2 : 23|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 8|4@1+ (1,0) [0|3] "" XXX + SG_ DRIVER_SEATBELT : 27|1@0+ (1,0) [0|1] "" XXX + +BO_ 866 RADAR_TURN: 8 XXX + SG_ CTR : 59|4@0+ (1,0) [0|15] "" XXX + SG_ STEER_ANGLE : 43|12@0+ (-1,2048) [0|7] "" XXX + SG_ STATIC_2 : 63|4@0+ (1,0) [0|15] "" XXX + SG_ CURVE_1 : 7|12@0+ (1,0) [0|131071] "" XXX + SG_ CURVE_2 : 11|12@0- (1,0) [0|127] "" XXX + SG_ FLIPPY_1 : 44|1@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_4 : 34|3@1+ (1,0) [0|3] "" XXX + SG_ CURVE_3 : 31|11@0- (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_1 : 33|4@0+ (1,0) [0|3] "" XXX + +BO_ 158 MSG_05: 8 XXX + SG_ NEW_SIGNAL_1 : 23|8@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 157 CRZ_BTNS: 8 XXX + SG_ BIT1 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ BIT2 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ BIT3 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ SET_P_INV : 21|1@0+ (1,0) [0|1] "" XXX + SG_ CAN_OFF_INV : 17|1@0+ (1,0) [0|1] "" XXX + SG_ CAN_OFF : 0|1@0+ (1,0) [0|1] "" XXX + SG_ SET_M_INV : 22|1@0+ (1,0) [0|1] "" XXX + SG_ SET_M : 5|1@0+ (1,0) [0|1] "" XXX + SG_ SET_P : 4|1@0+ (1,0) [0|1] "" XXX + SG_ RES_INV : 19|1@0+ (1,0) [0|1] "" XXX + SG_ RES : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DISTANCE_LESS : 7|1@0+ (1,0) [0|1] "" XXX + SG_ DISTANCE_LESS_INV : 8|1@0+ (1,0) [0|1] "" XXX + SG_ DISTANCE_MORE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ DISTANCE_MORE_INV : 23|1@0+ (1,0) [0|1] "" XXX + SG_ MODE_Y : 13|1@0+ (1,0) [0|1] "" XXX + SG_ MODE_X : 14|1@0+ (1,0) [0|1] "" XXX + SG_ MODE_Y_INV : 30|1@0+ (1,0) [0|1] "" XXX + SG_ MODE_X_INV : 31|1@0+ (1,0) [0|1] "" XXX + SG_ CTR : 29|4@0+ (1,0) [0|15] "" XXX + +BO_ 154 BLINK_INFO: 8 XXX + SG_ LEFT_BLINK : 18|1@1+ (1,0) [0|3] "" XXX + SG_ RIGHT_BLINK : 19|1@0+ (1,0) [0|255] "" XXX + SG_ REAR_WIPER_ON : 0|1@0+ (1,0) [0|1] "" XXX + SG_ WIPER_LO : 33|1@1+ (1,0) [0|31] "" XXX + SG_ WIPER_HI : 34|1@0+ (1,0) [0|1] "" XXX + SG_ LOW_BEAMS : 5|2@0+ (1,0) [0|3] "" XXX + SG_ HIGH_BEAMS : 7|2@0+ (1,0) [0|3] "" XXX + SG_ LBEAM1 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ LBEAM2 : 50|1@0+ (1,0) [0|1] "" XXX + SG_ LBEAM3 : 60|1@0+ (1,0) [0|1] "" XXX + +BO_ 145 TURN_SWITCH: 8 XXX + SG_ HAZARD : 10|1@0+ (1,0) [0|1] "" XXX + SG_ TURN_RIGHT_SWITCH : 12|1@0+ (1,0) [0|3] "" XXX + SG_ TURN_LEFT_SWITCH : 13|1@0+ (1,0) [0|255] "" XXX + SG_ CTR : 27|4@0+ (1,0) [0|255] "" XXX + SG_ CHKSUM : 39|8@0+ (1,0) [0|15] "" XXX + +BO_ 80 MSG_04: 8 XXX + SG_ NEW_SIGNAL_1 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ SIGNAL : 24|1@0+ (1,0) [0|1] "" XXX + +BO_ 978 MSG_03: 8 XXX + SG_ NEW_SIGNAL_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 23|8@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_8 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ CTR : 1|2@0+ (1,0) [0|255] "" XXX + +BO_ 607 NEW_MSG_25: 8 XXX + +BO_ 1115 MSG_02: 8 XXX + SG_ NEW_SIGNAL_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 47|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 63|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ CTR : 2|3@0+ (1,0) [0|255] "" XXX + +BO_ 1067 NEW_MSG_27: 8 XXX + SG_ NEW_SIGNAL_2 : 3|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 11|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_7 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_9 : 8|1@0+ (1,0) [0|1] "" XXX + +BO_ 358 NEW_MSG_28: 8 XXX + +BO_ 608 NEW_MSG_29: 8 XXX + SG_ NEW_SIGNAL_1 : 8|5@1+ (1,0) [0|7] "" XXX + +BO_ 606 SPEED_TBD: 8 XXX + SG_ SPEED_TBD : 7|12@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 23|12@0- (1,0) [0|65535] "" XXX + +BO_ 552 GEAR: 8 XXX + SG_ NEW_SIGNAL_3 : 11|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 26|3@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 31|5@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_7 : 39|1@0+ (1,0) [0|255] "" XXX + SG_ MORE_GEAR : 7|4@0+ (1,0) [0|15] "" XXX + SG_ GEAR : 2|3@0+ (1,0) [0|7] "" XXX + SG_ GEAR_BOX : 36|4@0+ (1,0) [0|15] "" XXX + +BO_ 543 CRZ_EVENTS: 8 XXX + SG_ CTR : 51|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_21 : 23|1@0+ (1,0) [0|15] "" XXX + SG_ GAS_MAYBE : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ACCEL_CMD : 46|8@0- (1,0) [0|15] "" XXX + SG_ CRUISE_ACTIVE_CAR_MOVING : 16|1@0+ (1,0) [0|1] "" XXX + SG_ PLUS_ONE_CRZ : 17|1@0+ (1,0) [0|255] "" XXX + SG_ CRZ_STARTED : 18|1@0+ (1,0) [0|1] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|15] "" XXX + SG_ PLUS_ONE_CRZ_2 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ ACCEL_CMD_LOW_RES : 29|8@0- (1,0) [0|255] "" XXX + SG_ CRZ_SPEED : 7|16@0+ (0.005,-0.5) [0|328] "kph" XXX + +BO_ 542 NEW_MSG_33: 8 XXX + SG_ CTR : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CTR2 : 56|4@1+ (1,0) [0|15] "" XXX + +BO_ 868 RADAR_364: 8 XXX + SG_ CTR : 59|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 7|12@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 11|12@0- (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 27|12@0- (1,0) [0|255] "" XXX + SG_ FLIPPERS_1 : 31|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_4 : 44|1@1+ (1,0) [0|3] "" XXX + SG_ FLIPPY_1 : 46|1@0+ (1,0) [0|3] "" XXX + SG_ STATIC_1 : 47|1@0+ (1,0) [0|15] "" XXX + SG_ STATIC_2 : 43|16@0+ (1,0) [0|7] "" XXX + +BO_ 869 RADAR_365: 8 XXX + SG_ CTR : 59|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|6@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_1 : 7|14@0+ (1,0) [0|65535] "" XXX + SG_ RELATED_1 : 9|18@0+ (1,0) [0|3] "" XXX + SG_ RELATED_2 : 33|18@0+ (1,0) [0|15] "" XXX + SG_ STATIC : 61|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 63|2@0+ (1,0) [0|15] "" XXX + +BO_ 1114 NEW_MSG_4: 8 XXX + +BO_ 535 CURVE_CTRS: 8 XXX + SG_ CTR_A_1 : 4|3@0+ (1,0) [0|31] "" XXX + SG_ CTR_A_2 : 7|3@0+ (1,0) [0|255] "" XXX + SG_ CTR_B_1 : 12|3@0+ (1,0) [0|7] "" XXX + SG_ CTR_B_2 : 15|3@0+ (1,0) [0|7] "" XXX + SG_ CTR_C_1 : 20|3@0+ (1,0) [0|7] "" XXX + SG_ CTR_C_2 : 23|3@0+ (1,0) [0|255] "" XXX + SG_ CTR_D_2 : 31|3@0+ (1,0) [0|7] "" XXX + SG_ CTR_D_1 : 28|3@0+ (1,0) [0|7] "" XXX + SG_ SPEED : 39|16@0+ (0.01,0) [0|7] "kph" XXX + SG_ CTR : 55|8@0+ (1,0) [0|255] "" XXX + SG_ CHK_MAYBE : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 17|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 25|1@0+ (1,0) [0|1] "" XXX + SG_ SEATBELT_MAYBE : 8|1@0+ (1,0) [0|1] "" XXX + SG_ NO_SEATBELT_MAYBE : 16|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 9|1@0+ (1,0) [0|1] "" XXX + +BO_ 540 CRZ_CTRL: 8 XXX + SG_ NEW_SIGNAL_6 : 10|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_9 : 31|1@0+ (1,0) [0|255] "" XXX + SG_ ACC_GAS_MAYBE2 : 29|1@0+ (1,0) [0|1] "" XXX + SG_ HANDS_OFF_STEERING : 48|1@0+ (1,0) [0|1] "" XXX + SG_ HANDS_ON_STEER_WARN : 59|4@0+ (1,0) [0|255] "" XXX + SG_ CRZ_ACTIVE : 3|1@0+ (1,0) [0|1] "" XXX + SG_ CRZ_AVAILABLE : 17|1@0+ (1,0) [0|255] "" XXX + SG_ DISTANCE_SETTING : 20|3@0+ (1,0) [0|7] "" XXX + SG_ MSG_1_INV : 1|1@0+ (1,0) [0|1] "" XXX + SG_ MSG_1_COPY : 9|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_GAS_MAYBE : 23|1@0+ (1,0) [0|31] "" XXX + SG_ ACC_ACTIVE_2 : 52|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_10 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ MSG_1 : 0|1@0+ (1,0) [0|3] "" XXX + SG_ 5_SEC_DISABLE_TIMER : 45|3@0+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_3 : 13|1@0+ (1,0) [0|3] "" XXX + SG_ MSG_1_INV_COPY : 8|1@0+ (1,0) [0|7] "" XXX + SG_ RADAR_HAS_LEAD : 23|1@0+ (1,0) [0|1] "" XXX + SG_ RADAR_LEAD_RELATIVE_DISTANCE : 31|3@0+ (1,0) [0|5] "" XXX + +BO_ 539 CRZ_INFO: 8 XXX + SG_ CTR1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ ACC_ACTIVE : 33|1@0+ (1,0) [0|1] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 47|1@0+ (1,0) [0|255] "" XXX + SG_ ACC_SET_ALLOWED : 34|1@0+ (1,0) [0|1] "" XXX + SG_ CRZ_ENDED : 36|1@0+ (1,0) [0|255] "" XXX + SG_ ACCEL_CMD : 17|13@0+ (1,-4096) [0|1] "" XXX + SG_ STATIC_1 : 15|11@0+ (1,0) [0|16383] "" XXX + SG_ STATIC_2 : 18|3@1+ (1,0) [0|3] "" XXX + SG_ ERROR_STATUS : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 121 EPB: 8 XXX + SG_ NEW_SIGNAL_1 : 4|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 25|2@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ CTR : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_8 : 41|2@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_9 : 47|1@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_10 : 46|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_11 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ EPB_ACTIVE : 29|1@0+ (1,0) [0|15] "" XXX + +BO_ 1070 2017_1: 8 XXX + +BO_ 1183 2017_2: 8 XXX + +BO_ 1243 2017_3: 8 XXX + SG_ NEW_SIGNAL_1 : 7|64@0+ (1,0) [0|18446744073709552000] "" XXX + +BO_ 1269 MSG_2017_4: 8 XXX + SG_ NEW_SIGNAL_1 : 55|16@0+ (1,0) [0|18446744073709552000] "" XXX + +BO_ 1178 2017_6: 8 XXX + SG_ NEW_SIGNAL_1 : 7|64@0+ (1,0) [0|18446744073709552000] "" XXX + +BO_ 1179 2017_7: 8 XXX + SG_ NEW_SIGNAL_1 : 7|64@0+ (1,0) [0|18446744073709552000] "" XXX + +BO_ 1435 2017_8: 8 XXX + +BO_ 253 GAS: 8 XXX + SG_ NEW_SIGNAL_1 : 16|1@0+ (1,0) [0|65535] "" XXX + SG_ CTR : 23|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 41|1@0+ (1,0) [0|255] "" XXX + SG_ CRZ_NOT_ACTIVE : 61|1@0+ (1,0) [0|255] "" XXX + SG_ GAS_CMD : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 359 MORE_GAS: 8 XXX + SG_ NEW_SIGNAL_1 : 15|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ CTR : 31|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 36|5@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 38|1@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 47|4@0+ (1,0) [0|255] "" XXX + +BO_ 512 NEW_MSG_30: 8 XXX + SG_ NEW_SIGNAL_1 : 6|7@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 23|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 22|7@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_6 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 38|7@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_9 : 40|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_10 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ CTR : 51|3@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_11 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 515 MSG_01: 8 XXX + SG_ CTR : 39|4@0+ (1,0) [0|65535] "" XXX + SG_ CHKSUM : 47|8@0+ (1,0) [0|255] "" XXX + SG_ START1 : 6|1@0+ (1,0) [0|1] "" XXX + SG_ START2 : 28|5@0+ (1,0) [0|255] "" XXX + +BO_ 529 NEW_MSG_36: 8 XXX + SG_ NEW_SIGNAL_1 : 22|5@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 31|8@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 32|4@1+ (1,0) [0|3] "" XXX + SG_ CTR : 39|4@0+ (1,0) [0|255] "" XXX + SG_ CTR_2 : 47|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 40|4@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 53|1@0+ (1,0) [0|255] "" XXX + +BO_ 1242 NEW_MSG_37: 8 XXX + +BO_ 1266 MSG_09: 8 XXX + SG_ NEW_SIGNAL_1 : 20|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 19|4@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 31|1@0+ (1,0) [0|255] "" XXX + +BO_ 976 MSG_15: 8 XXX + SG_ NEW_SIGNAL_1 : 55|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 61|6@0+ (1,0) [0|1] "" XXX + +BO_ 155 MSG_14: 8 XXX + +BO_ 1267 MSG_10: 8 XXX + SG_ NEW_SIGNAL_1 : 40|1@0+ (1,0) [0|16777215] "" XXX + SG_ NEW_SIGNAL_2 : 42|1@0+ (1,0) [0|1] "" XXX + +BO_ 305 NEW_MSG_6: 8 XXX + SG_ NEW_SIGNAL_1 : 8|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 9|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 10|1@0+ (1,0) [0|1] "" XXX + +BO_ 1238 TEMPERATURE: 8 XXX + SG_ TEMPERATURE_MAYBE : 47|8@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1087 NEW_MSG_1: 8 XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 1143 BSM: 8 XXX + SG_ BSM_OFF : 0|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_BS_3 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ STANDSTILL : 8|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_BS_STATUS : 13|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_BS_STATUS : 15|2@0+ (1,0) [0|3] "" XXX + SG_ LEFT_BS3 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_BS4 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_BS_SIDE : 36|1@0+ (1,0) [0|1] "" XXX + SG_ IS_MOVING : 9|1@0+ (1,0) [0|1] "" XXX + SG_ LEFT_BS_BEHIND : 46|2@1+ (1,0) [0|16777215] "" XXX + SG_ RIGHT_BS_DISTANCE : 35|3@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ REAR_CT_ALERT : 23|5@0+ (1,0) [0|63] "" XXX + +BO_ 480 ACCEL_TEST: 8 XXX + SG_ ACCEL_COMMAND : 7|32@0- (1,0) [-2147483647|2147483647] "" XXX + SG_ ENABLED : 32|1@0+ (1,0) [0|1] "" XXX + SG_ STARTING : 40|1@0+ (1,0) [0|1] "" XXX + SG_ STOPPING : 48|1@0+ (1,0) [0|1] "" XXX + +BO_ 1361 KEY_POSITION: 8 XXX + +BO_ 1283 KEY_POSITION2: 8 XXX + +BO_ 628 MSG_06: 8 XXX + +BO_ 1154 MSG_08: 8 XXX + +BO_ 1139 MSG_13: 8 XXX + +BO_ 1270 MSG_16: 8 XXX + +BO_ 1272 MSG_17: 8 XXX + +BO_ 1425 MSG_19: 8 XXX + +BO_ 70 MOB1: 8 XXX + SG_ NEW_SIGNAL_1 : 1|3@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 14|6@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_3 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 30|6@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 38|6@0+ (1,0) [0|7] "" XXX + +BO_ 64 MOB2: 8 XXX + SG_ NEW_SIGNAL_1 : 7|2@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 10|3@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 16|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 24|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 35|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 0|3@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_7 : 13|3@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_8 : 15|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_9 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_10 : 31|6@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_11 : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 1171 MOB3: 8 XXX + +BO_ 1248 MOB4: 8 XXX + +BO_ 1177 RADAR_499_STATIC: 8 XXX + + + + +CM_ SG_ 357 GEAR "13P, 26R, 13N, 24D"; +CM_ SG_ 605 PED_BRAKE "3: no brake, 4: brake"; +CM_ SG_ 605 BRAKE_WARNING "Flashing brake warning and audible alert for potential forward collision"; +CM_ SG_ 579 STEERING_ANGLE "steering angle aligns with 0.022 factor and -45.06 offset"; +CM_ SG_ 863 SPEED_SIGN "speed limit in MPH"; +CM_ SG_ 863 SPEED_SIGN_CAM "1: The speed limit is recognized by the camera. 0: speed limit is map based or is not available"; +CM_ SG_ 863 STOP_SIGN "value 9 when stop sign is active"; +CM_ SG_ 1157 SBS_WARNING_DISTANCE "1 far, 2 mid, 3 near"; +CM_ SG_ 1157 SBS_SCBC "1 off, 2 on"; +CM_ SG_ 1157 LKAS_ASSIT_TIMING "1 at, 0 before"; +CM_ SG_ 1157 LKAS_SENSETIVITY "0 low, 1 high"; +CM_ SG_ 1157 LANEE_DEPARTURE_ALERT "1 off, 2 on"; +CM_ SG_ 1157 WARNING "1 Rare, 0 often"; +CM_ SG_ 1088 LANE_LINES "0 LKAS disabled, 1 no lines, 2 two lines, 3 left line, 4 right line"; +CM_ SG_ 1088 TJA "2: crz not active, 3: TJA not allowed, 4: TJA allowed"; +CM_ SG_ 1088 TJA_TRANSITION "3: if TJA signal is 3, otherwise set to 0"; +CM_ SG_ 1045 ABS_MALFUNCTION "off: 0, solid: 1, slow blink: 2, fast blink: 3"; +CM_ SG_ 120 VEHICLE_ACC_X "Vehicle acceleration of X-axis wrt. NED frame."; +CM_ SG_ 120 VEHICLE_ACC_Y "Vehicle acceleration of Y-axis wrt. NED frame."; +CM_ SG_ 157 CAN_OFF "Disengage Cruise if enabled, if already disabled TURN it OFF "; +CM_ SG_ 552 MORE_GEAR ""; +CM_ SG_ 552 GEAR "0 Shifting, 1 P, 2 R, 3 N, 4 D"; +CM_ SG_ 552 GEAR_BOX "0 P, 14 R, 1 though 6 D for speeds, 15 Shift"; +CM_ SG_ 540 HANDS_ON_STEER_WARN "0 no warning, b warning"; +CM_ SG_ 540 DISTANCE_SETTING "Radar distance 0: disabled, 1: 4 bars, 2: 3 bars, 3: 2 bars, 4: 1 bar"; +CM_ SG_ 1143 REAR_CT_ALERT "Rear Cross Traffic Alert"; +VAL_ 552 GEAR 1 "P" 2 "R" 3 "N" 4 "D" ; +VAL_ 540 RADAR_HAS_LEAD 0 "NO LEAD" 1 "HAS LEAD" ; +VAL_ 540 RADAR_LEAD_RELATIVE_DISTANCE 0 "NO LEAD" 1 "FARTHEST" 2 "4" 3 "3" 4 "2" 5 "NEAREST" ; +VAL_ 1143 LEFT_BS_STATUS 0 "No object detected" 1 "Object detected in left blindspot" 2 "Object detected in left blindspot with blinker - warning" +VAL_ 1143 RIGHT_BS_STATUS 0 "No object detected" 1 "Object detected in right blindspot" 2 "Object detected in right blindspot with blinker - warning" diff --git a/opendbc_repo/opendbc/dbc/mazda_3_2019.dbc b/opendbc_repo/opendbc/dbc/mazda_3_2019.dbc new file mode 100644 index 0000000000..b23e7196bf --- /dev/null +++ b/opendbc_repo/opendbc/dbc/mazda_3_2019.dbc @@ -0,0 +1,408 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 256 CAM_Start: 8 XXX + SG_ NEW_SIGNAL_7 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_8 : 61|2@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_10 : 44|12@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 63|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 24|12@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 2|2@0+ (1,0) [0|1] "" XXX + SG_ ACTIVE_TARGET : 4|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 20|12@0+ (1,0) [0|7] "" XXX + SG_ DISTANCE_LEAD_CAR : 0|12@0+ (1,0) [0|255] "" XXX + +BO_ 358 CAM_End: 8 XXX + SG_ NEW_SIGNAL_2 : 61|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_3 : 59|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 1216 CAM_69: 8 XXX + SG_ NEW_SIGNAL_1 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_5 : 55|12@0+ (1,0) [0|7] "" XXX + +BO_ 1120 CAM_KEEP_ALIVE_2: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 1436 CAM_71: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 18 STEER: 8 XXX + SG_ NEW_SIGNAL_3 : 55|2@0+ (1,0) [0|15] "" XXX + SG_ CTR : 41|2@0+ (1,0) [0|3] "" XXX + SG_ STEER_LEFT_BIT : 26|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_ANGLE : 25|14@0- (1,375) [0|65536] "" XXX + SG_ ENGINE_OFF : 43|2@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_2 : 53|6@0+ (1,0) [0|15] "" XXX + +BO_ 257 LKAS: 8 XXX + SG_ CTR : 59|4@0+ (1,0) [0|255] "" XXX + SG_ CTR_ACT : 61|2@0+ (1,0) [0|3] "" XXX + SG_ SET_0 : 48|1@1+ (1,0) [0|3] "" XXX + SG_ SET_0_1 : 63|2@0+ (1,0) [0|3] "" XXX + SG_ SET_19 : 2|2@0+ (1,0) [0|255] "" XXX + SG_ LEAD_DIST : 0|12@0+ (1,0) [0|255] "" XXX + SG_ ANGLE_TARGET : 20|12@0+ (1,0) [0|4095] "" XXX + SG_ UNKNOWN : 24|12@0+ (1,0) [0|4095] "" XXX + SG_ MAX_TORQUE__ : 44|12@0- (1,0) [0|4095] "" XXX + +BO_ 258 NEW_MSG_3: 8 XXX + SG_ NEW_SIGNAL_3 : 59|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 44|10@0- (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 1|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_4 : 39|10@0- (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 13|10@0- (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 18|10@0- (1,0) [0|255] "" XXX + +BO_ 28 WHEEL_SPEEDS: 8 XXX + SG_ RR : 55|16@0+ (0.01,-100) [0|65535] "" XXX + SG_ RL : 39|16@0+ (0.01,-102) [0|65535] "" XXX + SG_ FL : 7|16@0+ (0.01,-100) [0|65535] "" XXX + SG_ FR : 23|16@0+ (0.01,-100) [0|65535] "" XXX + +BO_ 259 NEW_MSG_5: 8 XXX + SG_ NEW_SIGNAL_3 : 39|10@0- (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 44|10@0- (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 0|12@0- (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 19|11@0- (1,0) [0|10000000] "" XXX + +BO_ 260 NEW_MSG_6: 8 XXX + SG_ NEW_SIGNAL_1 : 0|12@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 24|12@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 20|12@0- (1,0) [0|1] "" XXX + +BO_ 261 NEW_MSG_7: 8 XXX + SG_ NEW_SIGNAL_1 : 15|8@0+ (1,0) [0|255] "" XXX + +BO_ 262 NEW_MSG_8: 8 XXX + SG_ NEW_SIGNAL_1 : 15|8@0- (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 263 NEW_MSG_9: 8 XXX + SG_ NEW_SIGNAL_1 : 15|8@0+ (1,0) [0|255] "" XXX + +BO_ 310 NEW_MSG_10: 8 XXX + SG_ NEW_SIGNAL_1 : 56|4@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 308 ACC_POSSIBLY: 8 XXX + SG_ NEW_SIGNAL_1 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 4|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 54|7@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 0|7@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_7 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 18|7@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 36|7@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 55|1@0+ (1,0) [0|1] "" XXX + +BO_ 304 CAM_LANES: 8 XXX + SG_ NEW_SIGNAL_3 : 59|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 61|2@0+ (1,0) [0|3] "" XXX + SG_ LEFT_LANE_DETECTED : 7|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_LANE_DETECTED : 4|1@0+ (1,0) [0|255] "" XXX + SG_ DISTANCE_TO_LEFT_LANE_LOW_RES : 29|8@0+ (1,0) [0|4095] "" XXX + SG_ DISTANCE_TO_RIGHT_LANE_LOW_RES : 37|8@0+ (1,0) [0|15] "" XXX + SG_ DISTANCE_TO_RIGHT_LANE : 23|10@0- (1,0) [0|2047] "" XXX + SG_ DISTANCE_TO_LEFT_LANE : 1|10@0- (1,0) [0|1] "" XXX + +BO_ 305 CAM_LANES_2_MAYBE: 8 XXX + SG_ NEW_SIGNAL_1 : 1|10@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 37|8@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_6 : 61|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_4 : 29|8@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 4|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 23|10@0+ (1,0) [0|4095] "" XXX + +BO_ 352 NEW_MSG_14: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 355 NEW_MSG_15: 8 XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|127] "" XXX + +BO_ 356 NEW_MSG_16: 8 XXX + SG_ NEW_SIGNAL_1 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 61|2@0+ (1,0) [0|3] "" XXX + +BO_ 357 NEW_MSG_17: 8 XXX + SG_ NEW_SIGNAL_1 : 61|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ NEW_SIGNAL_3 : 56|4@1+ (1,0) [0|15] "" XXX + +BO_ 59 STEER_RATE: 8 XXX + SG_ NEW_SIGNAL_2 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ STEER_ANGLE_RATE : 55|8@0+ (0.05,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_1 : 43|4@0+ (1,0) [0|15] "" XXX + SG_ STEER_ANGLE : 23|16@0+ (0.05,-1600) [-500|500] "" XXX + SG_ CHKSUM : 39|8@0+ (1,0) [0|15] "" XXX + +BO_ 24 BRAKE_PEDAL: 8 XXX + SG_ BRAKE_PEDAL_PRESSED_AND_ENGINE_ON : 0|1@0+ (1,0) [0|3] "" XXX + SG_ NOT_BRAKE_PEDAL_PRESSED : 6|1@0+ (1,0) [0|3] "" XXX + SG_ BRAKE_PEDAL_PRESSED : 7|1@0+ (1,0) [0|65535] "" XXX + SG_ NOT_BRAKE_PEDAL_PRESSED_AND_ENGINE_ON : 15|1@0+ (1,0) [0|7] "" XXX + +BO_ 26 ENGINE_DATA: 8 XXX + SG_ PEDAL_GAS : 39|10@0+ (1,0) [0|15] "" XXX + SG_ CHKSUM : 63|8@0- (1,0) [0|15] "" XXX + SG_ RPM : 7|13@0+ (1,0) [0|15] "" XXX + SG_ ENGINE_ON : 52|1@0+ (1,0) [0|15] "" XXX + +BO_ 145 BLINK_INFO: 8 XXX + SG_ RIGHT_BLINK : 12|1@0+ (1,0) [0|3] "" XXX + SG_ LEFT_BLINK : 13|1@0+ (1,0) [0|3] "" XXX + SG_ Speed : 27|12@0+ (1,0) [0|255] "" XXX + SG_ CTR : 51|4@0+ (1,0) [0|15] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|15] "" XXX + +BO_ 16 STEER_TORQUE: 8 XXX + SG_ NEW_SIGNAL_12 : 7|2@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 43|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 51|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_4 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ STEER_TORQUE_SENSOR : 5|13@0+ (1,-4000) [0|15] "" XXX + SG_ CHKSUM : 63|8@0- (1,0) [0|15] "" XXX + SG_ STEER_TORQUE_MOTOR : 8|13@0+ (0.05,-205) [0|15] "" XXX + SG_ BRAKE_PREASURE : 27|12@0+ (1,0) [0|15] "" XXX + +BO_ 17 STEER_TORQUE_2: 8 XXX + SG_ CTR : 51|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_TORQUE_MOTOR : 7|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 27|14@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 45|6@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 23|12@0+ (1,0) [0|255] "" XXX + +BO_ 29 WHEEL: 8 XXX + SG_ STANDSTILL : 52|1@0+ (1,0) [0|15] "" XXX + SG_ SPEED : 39|16@0+ (1,0) [0|127] "" XXX + SG_ ENCODER_1 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ ENCODER_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_6 : 55|3@0+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_1 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 51|4@0+ (1,0) [0|15] "" XXX + +BO_ 31 GEAR: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 55|16@0+ (1,0) [0|65535] "" XXX + SG_ GEAR : 36|4@0+ (1,0) [0|65535] "" XXX + +BO_ 96 STEER2: 8 XXX + SG_ NEW_SIGNAL_5 : 48|4@1+ (1,0) [0|15] "" XXX + SG_ CTR : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ TURN_ON : 34|1@0+ (1,0) [0|1] "" XXX + SG_ TURN_OFF : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ENGINE_ON : 33|1@0+ (1,0) [0|1] "" XXX + SG_ CAR_MOVING_FORWARD : 21|1@0+ (1,0) [0|15] "" XXX + SG_ CAR_REVERSING : 22|1@0+ (1,0) [0|1] "" XXX + SG_ ENGINE_OFF : 23|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 45|1@0+ (1,0) [0|15] "" XXX + SG_ SPEED : 18|16@0- (0.00621371,-62.1371) [-65635|65635] "MPH" XXX + SG_ STEER__ : 7|16@0+ (1,0) [0|65535] "" XXX + +BO_ 1209 KEEP_ALIVE_1: 8 XXX + SG_ NEW_SIGNAL_1 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_6 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_8 : 4|5@0+ (1,0) [0|127] "" XXX + +BO_ 37 BLANK_1: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 44 BLANK_2: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|16777215] "" XXX + SG_ NEW_SIGNAL_3 : 55|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 39|16@0+ (1,0) [0|16777215] "" XXX + +BO_ 128 RADARS: 8 XXX + SG_ NEW_SIGNAL_1 : 59|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 15|1@0+ (1,0) [0|255] "" XXX + SG_ FRONT_LEFT : 19|1@0+ (1,0) [0|255] "" XXX + SG_ FRONT : 21|1@0+ (1,0) [0|1] "" XXX + SG_ FRONT_RIGHT : 18|1@0+ (1,0) [0|1] "" XXX + SG_ REAR_RIGHT : 20|1@0+ (1,0) [0|15] "" XXX + SG_ REAR_LEFT : 17|1@0+ (1,0) [0|1] "" XXX + +BO_ 129 NEW_MSG_19: 8 XXX + SG_ NEW_SIGNAL_2 : 15|1@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 31|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 47|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_5 : 56|8@1+ (1,0) [0|15] "" XXX + +BO_ 1034 KEEP_ALIVE_2: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 23|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 55|16@0+ (1,0) [0|255] "" XXX + +BO_ 1200 KEEP_ALIVE_3: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 55|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 39|16@0+ (1,0) [0|65535] "" XXX + +BO_ 354 CAM_KEEP_ALIVE_1: 8 XXX + SG_ NEW_SIGNAL_1 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_2 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_3 : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_4 : 55|30@0+ (1,0) [0|65535] "" XXX + +BO_ 336 NEW_MSG_20: 8 XXX + SG_ NEW_SIGNAL_2 : 7|8@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_1 : 11|12@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 342 NEW_MSG_21: 8 XXX + SG_ NEW_SIGNAL_1 : 56|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 63|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_4 : 55|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 39|16@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 48|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_7 : 7|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_8 : 23|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_6 : 40|4@1+ (1,0) [0|15] "" XXX + +BO_ 264 NEW_MSG_2: 8 XXX + SG_ NEW_SIGNAL_1 : 56|8@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 49|3@1+ (1,0) [0|7] "" XXX + SG_ CRZ_CTRL_PRESSED : 48|1@0+ (1,0) [0|1] "" XXX + +BO_ 22 CRZ_CTRL_BTNS: 8 XXX + SG_ CRZ_CTRL_BTN_PRESSED : 48|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 51|3@0+ (1,0) [0|7] "" XXX + SG_ SIGNAL : 45|1@0+ (1,0) [0|15] "" XXX + SG_ NOT_SIGNAL : 46|1@0+ (1,0) [0|3] "" XXX + +BO_ 306 CAM_LANE_3_MAYBE: 8 XXX + SG_ NEW_SIGNAL_1 : 19|10@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_2 : 13|10@0+ (1,0) [0|255] "" XXX + SG_ LANE_DETECTED_1 : 44|1@0+ (1,0) [0|1] "" XXX + SG_ LANE_DETECTED_2 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 25|10@0+ (1,0) [0|1] "" XXX + SG_ STEER : 7|10@0+ (1,0) [0|1] "" XXX + +BO_ 307 NEW_MSG_1: 8 XXX + SG_ NEW_SIGNAL_2 : 13|10@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 61|6@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 25|10@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 7|10@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 19|10@0+ (1,0) [0|1] "" XXX + +BO_ 320 NEW_MSG_4: 8 XXX + SG_ NEW_SIGNAL_4 : 16|1@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 43|6@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 36|9@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 27|7@0+ (1,0) [0|1] "" XXX + +BO_ 321 NEW_MSG_11: 8 XXX + SG_ NEW_SIGNAL_1 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 32|1@0+ (1,0) [0|1] "" XXX + +BO_ 293 NEW_MSG_12: 8 XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 39|16@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 19|4@0+ (1,0) [0|1] "" XXX + +BO_ 294 NEW_MSG_13: 8 XXX + SG_ NEW_SIGNAL_1 : 59|4@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 61|2@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 7|16@0+ (1,0) [0|1] "" XXX + +BO_ 292 NEW_MSG_18: 8 XXX + SG_ NEW_SIGNAL_1 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 291 NEW_MSG_22: 8 XXX + SG_ NEW_SIGNAL_1 : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 290 NEW_MSG_23: 8 XXX + SG_ NEW_SIGNAL_1 : 31|5@0+ (1,0) [0|255] "" XXX + +BO_ 277 NEW_MSG_24: 8 XXX + SG_ NEW_SIGNAL_1 : 47|8@0+ (1,0) [0|1] "" XXX + +BO_ 278 NEW_MSG_25: 8 XXX + +BO_ 273 NEW_MSG_26: 8 XXX + SG_ NEW_SIGNAL_1 : 23|4@0+ (1,0) [0|3] "" XXX + +BO_ 274 NEW_MSG_27: 8 XXX + SG_ NEW_SIGNAL_1 : 39|8@0+ (1,0) [0|1] "" XXX + +BO_ 289 NEW_MSG_28: 8 XXX + SG_ NEW_SIGNAL_1 : 55|8@0+ (1,0) [0|1] "" XXX + +BO_ 20 NEW_MSG_29: 8 XXX + SG_ RIGHT_BLINK_CLOCK : 23|8@0+ (1,0) [0|1] "" XXX + +BO_ 288 NEW_MSG_30: 8 XXX + + + + +CM_ SG_ 31 GEAR "13-P, 12-R, 11-N, 1-6-D"; +CM_ SG_ 96 SPEED ""; +VAL_ 31 GEAR 13 "P" 12 "R" 11 "N" 1 "D" 2 "D" 3 "D" 4 "D" 5 "D" 6 "D"; diff --git a/opendbc_repo/opendbc/dbc/mazda_radar.dbc b/opendbc_repo/opendbc/dbc/mazda_radar.dbc new file mode 100644 index 0000000000..a4fe3b4b9e --- /dev/null +++ b/opendbc_repo/opendbc/dbc/mazda_radar.dbc @@ -0,0 +1,73 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 540 CRZ_CTRL: 8 XXX + +BO_ 539 CRZ_INFO: 8 XXX + +BO_ 865 RADAR_TRACK_361: 8 XXX + SG_ DIST_OBJ : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ ANG_OBJ : 11|12@0- (1,0) [-2047|2047] "" XXX + SG_ RELV_OBJ : 31|11@0- (1,0) [-1023|1023] "" XXX + +BO_ 866 RADAR_TRACK_362: 8 XXX + SG_ DIST_OBJ : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ ANG_OBJ : 11|12@0- (1,0) [-2047|2047] "" XXX + SG_ RELV_OBJ : 31|11@0- (1,0) [-1023|1023] "" XXX + +BO_ 867 RADAR_TRACK_363: 8 XXX + SG_ DIST_OBJ : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ ANG_OBJ : 11|12@0- (1,0) [-2047|2047] "" XXX + SG_ RELV_OBJ : 31|11@0- (1,0) [-1023|1023] "" XXX + +BO_ 868 RADAR_TRACK_364: 8 XXX + SG_ DIST_OBJ : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ ANG_OBJ : 11|12@0- (1,0) [-2047|2047] "" XXX + SG_ RELV_OBJ : 31|11@0- (1,0) [-1023|1023] "" XXX + +BO_ 869 RADAR_TRACK_365: 8 XXX + SG_ DIST_OBJ : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ ANG_OBJ : 11|12@0- (1,0) [-2047|2047] "" XXX + SG_ RELV_OBJ : 31|11@0- (1,0) [-1023|1023] "" XXX + +BO_ 870 RADAR_TRACK_366: 8 XXX + SG_ DIST_OBJ : 7|12@0+ (1,0) [0|4095] "" XXX + SG_ ANG_OBJ : 11|12@0- (1,0) [-2047|2047] "" XXX + SG_ RELV_OBJ : 31|11@0- (1,0) [-1023|1023] "" XXX + +BO_ 1177 RADAR_499: 8 XXX \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/mazda_rx8.dbc b/opendbc_repo/opendbc/dbc/mazda_rx8.dbc new file mode 100644 index 0000000000..f491a9698f --- /dev/null +++ b/opendbc_repo/opendbc/dbc/mazda_rx8.dbc @@ -0,0 +1,77 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: PowertrainControlModule InstrumentCluster ElectricPowerSteering AntilockBrakeSystem + + +BO_ 129 steering: 8 ElectricPowerSteering + SG_ SteeringAngle : 23|16@0- (1,0) [0|0] "deg" Vector__XXX + +BO_ 513 speed: 8 PowertrainControlModule + SG_ EngineRPM : 7|16@0+ (0.25,0) [0|0] "rpm" Vector__XXX + SG_ VehicleSpeed : 39|16@0+ (0.01,-100) [0|0] "kph" Vector__XXX + SG_ AcceleratorPos : 55|8@0+ (0.5,0) [0|0] "%" Vector__XXX + +BO_ 592 throttle_body: 8 PowertrainControlModule + SG_ IntakeAirTemperature : 31|8@0+ (1,-40) [0|0] "Cel" Vector__XXX + SG_ AcceleratorPedalSensorRaw : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ AcceleratorPedalSensorFiltered : 55|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 658 brake_controls: 8 PowertrainControlModule + SG_ BrakePedalSwitch : 43|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ ParkingBrakeSwitch : 38|1@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 1056 coolant: 8 PowertrainControlModule + SG_ CoolantTemperature : 7|8@0+ (1,-40) [0|0] "Cel" Vector__XXX + +BO_ 1072 instrument_cluster: 8 InstrumentCluster + SG_ FuelLevel : 7|8@0+ (0.392156,0) [0|0] "%" Vector__XXX + SG_ FuelTankSensorLeft : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ FuelTankSensorRight : 23|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1200 wheel_speed: 8 AntilockBrakeSystem + SG_ WheelSpeedFL : 7|16@0+ (0.01,-100) [0|0] "kph" Vector__XXX + SG_ WheelSpeedFR : 23|16@0+ (0.01,-100) [0|0] "kph" Vector__XXX + SG_ WheelSpeedRL : 39|16@0+ (0.01,-100) [0|0] "kph" Vector__XXX + SG_ WheelSpeedRR : 55|16@0+ (0.01,-100) [0|0] "kph" Vector__XXX + +CM_ SG_ 129 SteeringAngle "Steering wheel angle: positive is right and negative is left"; +CM_ SG_ 513 AcceleratorPos "processed interpretation of AcceleratorPedalSensor values"; +CM_ SG_ 1072 FuelTankSensorLeft "lower sensor values indicate a more full tank"; +CM_ SG_ 1072 FuelTankSensorRight "lower sensor values indicate a more full tank"; + + + + diff --git a/opendbc_repo/opendbc/dbc/mercedes_benz_e350_2010.dbc b/opendbc_repo/opendbc/dbc/mercedes_benz_e350_2010.dbc new file mode 100644 index 0000000000..da6ae4c15e --- /dev/null +++ b/opendbc_repo/opendbc/dbc/mercedes_benz_e350_2010.dbc @@ -0,0 +1,176 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 3 STEER_SENSOR: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_RATE : 19|12@0- (0.5,0) [0|255] "" XXX + SG_ STEER_DIRECTION : 4|1@0+ (1,2) [0|1] "" XXX + SG_ STEER_ANGLE : 3|12@0- (-0.5,0) [-500|500] "degrees" XXX + +BO_ 5 BRAKE_MODULE: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_HOLD : 2|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_POSITION : 17|10@0+ (1,0) [0|65535] "" XXX + SG_ DRIVER_BRAKE : 4|1@0+ (1,0) [0|1] "" XXX + SG_ COMPUTER_BRAKE : 10|1@0+ (1,0) [0|1] "" XXX + SG_ BRAKE_PRESSED : 0|1@1+ (1,0) [0|1] "" XXX + +BO_ 69 DRIVER_CONTROLS: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ STEERING_WHEEL_BUTTONS : 32|16@1+ (1,0) [0|255] "4 directional, 2 volume control & 2 phone buttons" XXX + SG_ LEFT_BLINKER : 16|1@0+ (1,0) [0|1] "" XXX + SG_ RIGHT_BLINKER : 17|1@0+ (1,0) [0|1] "" XXX + SG_ HIGHBEAM_TOGGLE : 18|1@0+ (1,0) [0|1] "" XXX + SG_ HIGHBEAM_MOMENTARY : 19|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_CANCEL : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_RESUME : 1|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_ACCEL_HIGH : 2|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_DECEL_HIGH : 3|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_ACCEL_LOW : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_DECEL_LOW : 5|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_XFF : 15|8@0+ (1,0) [0|255] "" XXX + +BO_ 513 WHEEL_ENCODERS: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ WHEEL_ENCODER_2 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_ENCODER_3 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ WHEEL_ENCODER_4 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX + SG_ WHEEL_ENCODER_1 : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 261 GAS_PEDAL: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ ENGINE_RPM : 4|5@0+ (1,0) [0|255] "" XXX + SG_ GAS_PEDAL : 39|8@0+ (1,0) [0|255] "" XXX + SG_ COMBINED_GAS : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 643 DOOR_SENSORS: 8 XXX + SG_ BRAKE_PRESSED : 27|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 3|1@1+ (1,0) [0|3] "" XXX + SG_ DOOR_OPEN_RL : 5|1@0+ (1,0) [0|3] "" XXX + SG_ DOOR_OPEN_RR : 7|1@0+ (1,0) [0|3] "" XXX + SG_ DOOR_OPEN_FL : 1|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_FL : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_FR : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_RL : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_CLOSED_RR : 6|1@0+ (1,0) [0|1] "" XXX + +BO_ 885 SEATBELT_SENSORS: 8 XXX + SG_ SEATBELT_DRIVER_LATCHED : 16|1@0+ (1,0) [0|1] "" XXX + SG_ SEATBELT_PASSENGER_LATCHED : 18|1@0+ (1,0) [0|1] "" XXX + +BO_ 257 CRUISE_CONTROL: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 6|1@0+ (1,0) [0|255] "" XXX + SG_ CRUISE_DISABLED : 23|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_X002 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X003 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_1 : 5|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_ACCELERATING : 22|1@0+ (1,0) [0|1] "" XXX + SG_ LONGITUDINAL_ACCEL_REQUEST : 15|8@0- (1,0) [0|127] "" XXX + +BO_ 260 CRUISE_CONTROL2: 8 XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_XFF : 31|8@0+ (1,0) [0|65535] "" XXX + SG_ SET_ME_X02 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_XFF2 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 7|4@0+ (1,0) [0|255] "" XXX + +BO_ 14 STEER_TORQUE: 8 XXX + SG_ STEER_TORQUE : 15|8@0+ (1,0) [0|255] "" XXX + SG_ COUNTER : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 888 CRUISE_CONTROL3: 8 XXX + SG_ NEW_SIGNAL_2 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_DISABLED : 36|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_ENABLED : 34|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_X003 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X004 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X002 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ CRUISE_SET_SPEED : 15|8@0+ (1,0) [0|63] "mph" XXX + SG_ CRUISE_SPEED_CHANGE : 55|1@0+ (1,0) [0|1] "" XXX + +BO_ 307 POWER_SEATS: 8 XXX + SG_ DRIVER_FORWARD : 0|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_BACK : 1|1@0+ (1,0) [0|1] "" XXX + +BO_ 109 GEAR_LEVER: 8 XXX + SG_ PARK_BUTTON : 12|1@0+ (1,0) [0|1] "" XXX + SG_ NEUTRAL_UP : 9|1@0+ (1,0) [0|1] "" XXX + SG_ NEUTRAL_DOWN : 10|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVE : 11|1@0+ (1,0) [0|1] "" XXX + SG_ REVERSE : 8|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 23|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 115 GEAR_PACKET: 8 XXX + SG_ GEAR : 0|4@1+ (1,0) [0|15] "" XXX + +BO_ 581 IGNITION: 8 XXX + +BO_ 515 WHEEL_SPEEDS: 8 XXX + SG_ WHEEL_MOVING_FR : 22|1@1+ (1,0) [0|15] "" XXX + SG_ WHEEL_MOVING_RL : 38|1@0+ (1,0) [0|1] "" XXX + SG_ WHEEL_MOVING_FL : 6|1@0+ (1,0) [0|1] "" XXX + SG_ WHEEL_MOVING_RR : 54|1@0+ (1,0) [0|1] "" XXX + SG_ WHEEL_SPEED_FL : 2|11@0+ (0.0375,0) [0|255] "mph" XXX + SG_ WHEEL_SPEED_FR : 18|11@0+ (0.0375,0) [0|255] "mph" XXX + SG_ WHEEL_SPEED_RL : 34|11@0+ (0.0375,0) [0|255] "mph" XXX + SG_ WHEEL_SPEED_RR : 50|11@0+ (0.0375,0) [0|255] "mph" XXX + + + + +CM_ SG_ 3 STEER_DIRECTION "0 = left, 1 = right"; +CM_ SG_ 5 BRAKE_POSITION "computer and driver"; +CM_ SG_ 5 BRAKE_PRESSED "computer and driver"; +CM_ SG_ 261 GAS_PEDAL "user gas input"; +CM_ SG_ 261 COMBINED_GAS "computer and driver gas"; +CM_ SG_ 257 CRUISE_ACCELERATING ""; \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/nissan_xterra_2011.dbc b/opendbc_repo/opendbc/dbc/nissan_xterra_2011.dbc new file mode 100644 index 0000000000..1e7bd4c4ae --- /dev/null +++ b/opendbc_repo/opendbc/dbc/nissan_xterra_2011.dbc @@ -0,0 +1,96 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + +BO_ 2 STEERING: 5 XXX + SG_ COUNTER : 35|4@0+ (1,0) [0|255] "" XXX + SG_ STEERING_ANGLE : 0|16@1- (0.1,0) [0|65535] "deg" XXX + SG_ POWER_STEER_RATE : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 505 ENGINE_1: 8 XXX + SG_ RPM : 16|16@1+ (0.125,0) [0|45000] "R/min" XXX + SG_ FAN_REQ : 6|2@1+ (1,0) [0|3] "" XXX + SG_ AC_REQ : 3|1@1+ (1,0) [0|1] "" XXX + +BO_ 561 ENGINE_2: 8 XXX + SG_ Pedal_position : 16|8@1+ (0.5,0) [0|200] "%" XXX + +BO_ 563 ENGINE_7: 8 XXX + SG_ CLT : 0|8@1+ (0.366666,0) [0|255] "C" XXX + SG_ RPMlow : 32|8@1+ (3.15,0) [0|45000] "R/min" XXX + SG_ RPMhi : 56|8@1+ (3.15,0) [0|45000] "R/min" XXX + +BO_ 573 ENGINE_3: 8 XXX + SG_ Pedal_position : 8|8@1+ (0.392,0) [0|255] "%" XXX + SG_ Throttle_position_capped : 16|8@1+ (0.392,0) [0|255] "%" XXX + SG_ RPM : 24|16@1+ (3.15,0) [0|45000] "R/min" XXX + SG_ CLT : 56|8@1+ (0.366666,0) [0|255] "C" XXX + +BO_ 574 ENGINE_4: 8 XXX + SG_ Throttle_position_inverted : 16|8@1+ (0.392,0) [0|255] "%" XXX + SG_ EstimatedTorque : 24|16@1+ (0.1,0) [0|45000] "nM" XXX + SG_ Throttle_position : 48|8@1+ (0.392,0) [0|255] "%" XXX + +BO_ 595 TCU_1: 8 XXX + SG_ SHAFT_1_SPEED : 32|16@1+ (1,0) [0|45000] "r/min" XXX + SG_ SHAFT_2_SPEED : 48|16@1+ (1,0) [0|45000] "r/min" XXX + +BO_ 640 SPEED: 8 XXX + SG_ SPEED : 32|16@1+ (0.01,0) [0|45000] "km/h" XXX + +BO_ 644 ABS_1: 8 XXX + SG_ WHEEL_1 : 0|16@1+ (0.01,0) [0|45000] "km/h" XXX + SG_ WHEEL_2 : 15|16@1+ (0.01,0) [0|45000] "km/h" XXX + +BO_ 645 ABS_2: 8 XXX + SG_ WHEEL_3 : 0|16@1+ (0.01,0) [0|45000] "km/h" XXX + SG_ WHEEL_4 : 15|16@1+ (0.01,0) [0|45000] "km/h" XXX + +BO_ 852 SPEED_BREAK: 8 XXX + SG_ BREAK_LIGHT : 52|1@0+ (1,0) [0|3] "" XXX + SG_ SPEED_MPH : 7|16@0+ (0.0066,0) [0|65535] "mph" XXX + SG_ TCS_OFF : 38|1@0+ (1,0) [0|255] "" XXX + +BO_ 861 BCM: 8 XXX + +BO_ 1361 ENGINE_5: 8 XXX + SG_ CLT : 0|8@1+ (1,-45) [-45|150] "" XXX + +BO_ 1408 ENGINE_6: 8 XXX + SG_ RPM : 7|16@0+ (1.5,0) [0|65535] "" XXX + SG_ OIL_TEMP : 32|8@1+ (1,-40) [-40|150] "" XXX + +BO_ 1477 MILEAGE: 8 XXX \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/opel_omega_2001.dbc b/opendbc_repo/opendbc/dbc/opel_omega_2001.dbc new file mode 100644 index 0000000000..8f8e0cfdea --- /dev/null +++ b/opendbc_repo/opendbc/dbc/opel_omega_2001.dbc @@ -0,0 +1,104 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: ABS ESP ECU TCU SAS + + +BO_ 272 TCU_Data1: 8 TCU + SG_ TorqueRequest1 : 15|8@0+ (1,0) [0|255] "" ABS,ESP,ECU + SG_ TorqueRequest2 : 31|8@0+ (1,0) [0|255] "" ABS,ESP,ECU + SG_ OutputShaftSpeed : 55|16@0+ (1,0) [0|65535] "rpm" ABS,ESP,ECU + +BO_ 288 ESP_Data1: 8 ESP + SG_ ABD_Active : 4|1@0+ (1,0) [0|1] "yes/no" ECU,TCU + SG_ TorqueRequestFast : 15|8@0+ (1,0) [0|255] "" ECU,TCU + SG_ TorqueRequestSlow : 31|8@0+ (1,0) [0|255] "" ECU,TCU + +BO_ 384 SAS_Data: 8 SAS + SG_ SteeringAngle : 0|16@1- (0.1,0) [-3276.8|3276.7] "yes/no" ECU,TCU + SG_ SteeringSpeed : 16|8@1+ (1,0) [0|255] "" ECU,TCU + +BO_ 416 ECU_Data1: 8 ECU + SG_ RPM : 15|16@0+ (1,0) [0|65535] "rpm" ABS,ESP,TCU + SG_ TorqueResponse : 31|8@0+ (1,0) [0|255] "" ABS,ESP,TCU + SG_ TorqueLost : 39|8@0+ (1,0) [0|255] "" ABS,ESP,TCU + SG_ APP : 47|8@0+ (1,0) [0|102] "" ABS,ESP,TCU + SG_ TorqueRequest : 63|8@0+ (1,0) [0|255] "" ABS,ESP,TCU + +BO_ 448 ECU_Data2: 8 ECU + SG_ TPS : 23|8@0+ (1,0) [0|100] "" ABS,ESP,TCU + +BO_ 640 ECU_Data3: 8 ECU + SG_ BrakeActive : 18|1@0+ (1,0) [0|1] "yes/no" ABS,ESP,TCU + SG_ KickdownActive : 20|1@0+ (1,0) [0|1] "yes/no" ABS,ESP,TCU + SG_ CruiseActive : 22|1@0+ (1,0) [0|1] "yes/no" ABS,ESP,TCU + +BO_ 736 TCU_Data2: 8 TCU + SG_ TOT : 31|8@0- (1,-40) [-40|215] "" ECU + SG_ InputShaftSpeed : 47|16@0+ (1,0) [0|65535] "rpm" ECU + +BO_ 768 ABS_WheelSpeed: 8 ABS + SG_ FrontLeftWheelSpeed : 5|14@0+ (0.112,0) [0|255] "km/h" ECU,TCU + SG_ FrontLeftWheelErrorFlag : 7|1@0+ (1,0) [0|1] "" ECU,TCU + SG_ FrontRightWheelSpeed : 21|14@0+ (0.112,0) [0|255] "km/h" ECU,TCU + SG_ FrontRightWheelErrorFlag : 23|1@0+ (1,0) [0|1] "" ECU,TCU + SG_ RearLeftWheelSpeed : 37|14@0+ (0.112,0) [0|255] "km/h" ECU,TCU + SG_ RearLeftWheelErrorFlag : 39|1@0+ (1,0) [0|1] "" ECU,TCU + SG_ RearRightWheelSpeed : 53|14@0+ (0.112,0) [0|255] "km/h" ECU,TCU + SG_ RearRightWheelErrorFlag : 55|1@0+ (1,0) [0|1] "" ECU,TCU + +BO_ 792 ESP_Data2: 8 ESP + SG_ ABS_Active : 12|1@0+ (1,0) [0|1] "yes/no" ECU,TCU + SG_ ESP_Off : 20|1@0+ (1,0) [0|1] "yes/no" ECU,TCU + SG_ ESP_Active : 21|1@0+ (1,0) [0|1] "yes/no" ECU,TCU + +BO_ 992 TCU_Data3: 8 TCU + SG_ CurrentGear : 11|4@0+ (1,0) [0|15] "" ECU + SG_ SelectorPosition : 18|3@0+ (1,0) [0|7] "" ECU + SG_ AutoNeutralActive : 26|1@0+ (1,0) [0|1] "yes/no" ECU + SG_ WinterModeActive : 29|1@0+ (1,0) [0|1] "yes/no" ECU + SG_ SportModeActive : 30|1@0+ (1,0) [0|1] "yes/no" ECU + SG_ TCC_State : 37|2@0+ (1,0) [0|2] "" ECU + +BO_ 1472 ECU_Data4: 8 ECU + SG_ ECT : 15|8@0- (1,-40) [-40|215] "" TCU + SG_ IAT : 47|8@0- (1,-40) [-40|215] "" TCU + + + +VAL_ 992 CurrentGear 5 "1" 6 "2" 7 "3" 8 "4" ; +VAL_ 992 SelectorPosition 1 "P" 2 "R" 3 "N" 4 "D" 7 "3" 6 "2" 5 "1" ; +VAL_ 992 TCC_State 0 "Off" 1 "Partially Locked" 2 "Locked" ; + diff --git a/opendbc_repo/opendbc/dbc/psa_aee2010_r3.dbc b/opendbc_repo/opendbc/dbc/psa_aee2010_r3.dbc new file mode 100644 index 0000000000..8f76dede82 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/psa_aee2010_r3.dbc @@ -0,0 +1,1041 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: UTIL__Traminator CMM___Motor_SG CDS___Fahrdynamikregelung BVA___Automatikgetriebe BSI___Kombiinstrument AR2S_StartStop ABS___Antiblockiersystem + + +BO_ 114 RQD_CMM: 5 CMM___Motor_SG + SG_ ADC2_Req_Status : 0|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ ADC2_Seed_Byte3 : 8|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ ADC2_Seed_Byte2 : 16|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ ADC2_Seed_Byte1 : 24|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ ADC2_Seed_Byte0 : 32|8@1+ (1,0) [0|255] "-" BSI___Kombiinstrument + +BO_ 146 Elec_Int: 1 BSI___Kombiinstrument + SG_ P__Elec_Int_Cntrl_Word : 7|8@0+ (1,0) [0|255] "" Vector__XXX + +BO_ 168 CFD_BSI: 5 BSI___Kombiinstrument + SG_ ADC2_Key_Status : 0|8@1+ (1,0) [0|0] "-" Vector__XXX + SG_ ADC2_Key_Byte3 : 8|8@1+ (1,0) [0|255] "-" CMM___Motor_SG + SG_ ADC2_Key_Byte2 : 16|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ ADC2_Key_Byte1 : 24|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ ADC2_Key_Byte0 : 32|8@1+ (1,0) [0|255] "-" Vector__XXX + +BO_ 264 Vers_CMM: 8 CMM___Motor_SG + SG_ P076_System : 0|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P077_Day : 8|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P078_Month : 16|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P079_Year : 24|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P080_Application : 32|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P081_Version : 40|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P082_Edition : 48|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P083_Calibration : 56|8@1+ (1,0) [0|255] "-" Vector__XXX + +BO_ 461 ESP: 3 XXX + SG_ COUNTER : 3|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 4|4@1+ (1,0) [0|15] "" XXX + SG_ UNCLEAR : 14|10@0+ (1,0) [0|1023] "" XXX + SG_ ESP_STATUS : 15|1@0+ (1,0) [0|1] "" XXX + SG_ ESP_STATUS_INV : 20|1@0+ (1,0) [0|1] "" XXX + +BO_ 488 DAT3_CMM: 3 Vector__XXX + SG_ Reserved_3 : 5|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ P413_Com_stRstrtStSpPrgs : 7|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ P426_Com_ctRstrtStSp : 15|16@0+ (1,0) [0|3276750] "" Vector__XXX + +BO_ 520 Dyn_CMM: 8 CMM___Motor_SG + SG_ P000_Com_nEng : 7|16@0+ (0.125,0) [0|8191.75] "1/min" Vector__XXX + SG_ P003_Com_trqActOut : 16|8@1+ (3,-150) [-150|615] "Nm" Vector__XXX + SG_ P002_Com_rAPP : 24|8@1+ (0.5,0) [0|100] "%" Vector__XXX + SG_ P027_ACCtl_stLogicOut : 32|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P014_Brk_stRed : 33|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P037_VehV_stXVV : 34|2@1+ (1,0) [0|2] "-" Vector__XXX + SG_ P153_Com_bTrqInacc : 36|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P042_Inm_bCanMon : 38|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P127_EGT_st_Bit30 : 39|1@1+ (1,0) [0|0] "-" Vector__XXX + SG_ P198_ActMod_trqClthTraIntv : 56|8@1+ (2,-100) [-100|410] "Nm" Vector__XXX + +BO_ 552 Dyn5_CMM: 5 CMM___Motor_SG + SG_ P320_EasyMvTrqInfo : 0|8@1+ (3,-150) [-150|615] "Nm" Vector__XXX + SG_ P411_Com_stTrqAvlStSp : 12|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P410_Com_stEngTrqStSp : 13|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P321_StatusOfEasyMvTrq : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P334_ACCPed_Position : 16|8@1+ (0.5,0) [0|100] "%" Vector__XXX + SG_ P336_Com_xDyn5CMMChkSum : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P335_Com_ctDyn5CMMCntr : 28|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P388_Com_rClthPedPos : 39|8@0+ (0.5,0) [0|100] "" Vector__XXX + +BO_ 694 HS2_DYN1_MDD_ETAT_2B6: 8 ARTIV + SG_ MDD_DESIRED_DECELERATION : 7|8@0+ (0.05,-10.65) [-10.65|2] "m/s2" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ POTENTIAL_WHEEL_TORQUE_REQUEST : 9|2@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ MIN_TIME_FOR_DESIRED_GEAR : 15|6@0+ (0.1,0) [0|6.2] "s" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ GMP_POTENTIAL_WHEEL_TORQUE : 23|12@0+ (4,-4000) [-4000|11000] "N.m" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ ACC_STATUS : 27|4@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ GMP_WHEEL_TORQUE : 39|14@0+ (1,-4000) [-4000|11000] "N.m" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ WHEEL_TORQUE_REQUEST : 41|2@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ AUTO_BRAKING_STATUS : 50|3@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ MDD_DECEL_TYPE : 52|2@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ MDD_DECEL_CONTROL_REQ : 53|1@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ GEAR_TYPE : 54|1@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ PREFILL_REQUEST : 55|1@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ DYN_ACC_CHECKSUM : 59|4@0+ (1,0) [0|0] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + SG_ DYN_ACC_PROCESS_COUNTER : 63|4@0+ (1,0) [0|15] "" CMM,UC_FREIN,BSI,PASS_HCU2,CMF + +BO_ 717 HS2_DYN_UCF_2CD: 3 UC_FREIN + SG_ AUTO_BRAKING_PRESSURE : 7|8@0+ (0.2,0) [0|50.6] "bar" BV,BVN + SG_ VITESSE_LACET : 15|16@0- (0.1,0) [-100|100] "Degré/s" BV,BVN + +BO_ 728 NEW_MSG_2D8: 7 XXX + SG_ ACC_RELATED : 17|1@0+ (1,0) [0|1] "" XXX + SG_ ESP_STATUS_RELATED : 28|1@0+ (1,0) [0|1] "" XXX + SG_ ESP_STATUS_RELATED_INV : 29|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ACTIVATION_RELATED : 43|1@0+ (1,0) [0|1] "" XXX + +BO_ 757 STEERING: 7 XXX + SG_ COUNTER : 3|4@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 7|4@0+ (1,0) [0|15] "" XXX + SG_ DRIVER_TORQUE : 15|8@0- (1,0) [0|255] "" XXX + SG_ ANGLE : 31|16@0- (0.1,0) [-3276.8|3276.7] "degrees" XXX + SG_ RATE : 47|12@0- (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_1 : 48|1@0+ (1,0) [0|1] "" XXX + +BO_ 758 HS2_DYN_MDD_ETAT_2F6: 8 ARTIV + SG_ TARGET_DETECTED : 0|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ REQUEST_TAKEOVER : 2|2@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ BLIND_SENSOR : 4|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ REQ_VISUAL_COLL_ALERT_ARC : 5|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ REQ_AUDIO_COLL_ALERT_ARC : 6|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ REQ_HAPTIC_COLL_ALERT_ARC : 7|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ INTER_VEHICLE_DISTANCE : 15|10@0+ (0.25,0) [0|255.5] "m" BSI,CMM,UC_FREIN,CMF + SG_ ARC_STATUS : 19|4@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ AUTO_BRAKING_IN_PROGRESS : 20|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ AEB_ENABLED : 21|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ DRIVE_AWAY_REQUEST : 33|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ DISPLAY_INTERVEHICLE_TIME : 39|6@0+ (0.1,0) [0|6.1] "s" BSI,CMM,UC_FREIN,CMF + SG_ MDD_DECEL_CONTROL_REQ : 42|1@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ AUTO_BRAKING_STATUS : 47|3@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ CHECKSUM_TRANSM_DYN_ACC2 : 51|4@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + SG_ PROCESS_COUNTER_4B_ACC2 : 55|4@0+ (1,0) [0|15] "" BSI,CMM,UC_FREIN,CMF + SG_ TARGET_POSITION : 63|3@0+ (1,0) [0|0] "" BSI,CMM,UC_FREIN,CMF + +BO_ 760 NEW_MSG_2F8: 7 XXX + SG_ ESP_STATUS_RELATED : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ESP_STATUS_RELATED_INV : 13|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_ACTIVATION_RELATED : 35|1@0+ (1,0) [0|1] "" XXX + +BO_ 770 NEW_MSG_302: 7 XXX + SG_ ACC_RELATED : 46|1@0+ (1,0) [0|1] "" XXX + +BO_ 773 STEERING_ALT: 7 XXX + SG_ ANGLE : 7|16@0- (0.1,0) [-3276.8|3276.7] "degrees" XXX + SG_ RATE : 23|8@0+ (1,0) [0|255] "" XXX + SG_ RATE_SIGN : 31|1@0+ (1,0) [0|1] "" XXX + SG_ 0_COUNTER : 35|4@0+ (1,0) [0|255] "" XXX + SG_ 0_CHECKSUM : 39|4@0+ (1,0) [0|15] "" XXX + SG_ RATE_ALT : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 781 Dyn4_FRE: 8 CDS___Fahrdynamikregelung + SG_ P263_VehV_VPsvValWhlFrtL : 7|16@0+ (0.01,0) [0|655.35] "km/h" Vector__XXX + SG_ P264_VehV_VPsvValWhlFrtR : 23|16@0+ (0.01,0) [0|655.35] "km/h" Vector__XXX + SG_ P265_VehV_VPsvValWhlBckL : 39|16@0+ (0.01,0) [0|655.35] "km/h" Vector__XXX + SG_ P266_VehV_VPsvValWhlBckR : 55|16@0+ (0.01,0) [0|655.35] "km/h" Vector__XXX + +BO_ 792 NEW_MSG_318: 5 XXX + SG_ ACC_RELATED : 14|13@0+ (1,0) [0|8191] "" XXX + SG_ ACC_RELATED_2 : 30|13@0+ (1,0) [0|8191] "" XXX + SG_ ACC_GO_RELATED : 32|1@0+ (1,0) [0|1] "" XXX + +BO_ 809 Dyn_STT_BV: 4 BVA___Automatikgetriebe + SG_ P230_Com_ctGbxCnt3 : 3|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ P340_Com_xChkSum3 : 7|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ P441_Com_bGbxAuthRstrtRaw : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P444_Com_bGbxSysFaultRaw : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P443_Com_bGbxRstrtReq : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P442_Com_bGbxAuthStopRaw : 15|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 813 HS2_DYN_UCF_MDD_32D: 8 UC_FREIN + SG_ ACCEL_LONGI_CALIB : 7|12@0+ (0.02,-40.96) [-40.96|40.92] "m/s2" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ VAL_INFO_VIT_LACET : 8|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ EFFORT_FREIN : 9|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ FA_ETAT_DECEL : 11|2@0+ (1,0) [0|3] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ APPUI_FREIN_RECONSTRUIT : 17|2@0+ (1,0) [0|3] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ PREFILL_EN_COURS : 18|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ ACC_ETAT_DECEL_OR_ESP_STATUS : 20|2@0+ (1,0) [0|3] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ VEHICLE_STANDSTILL : 21|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ FREINAGE_DYN_EN_COURS : 22|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ BRAKE_RELEASED_FAILSAFE : 23|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ EFFORT_FREIN_ERRONE : 28|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ ARRET_VHL_ADAS : 30|2@0+ (1,0) [0|3] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ DEFAUT_ACC_FREIN : 31|1@0+ (1,0) [0|1] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ VITESSE_LACET_BRUTE : 39|12@0+ (0.08,-163.84) [-163.84|163.68] "Degré/s" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ CHKSUM_TRME_DYN_UCF_ACC : 59|4@0+ (1,0) [0|15] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + SG_ CPT_PROCESS_4B_UC_FREIN : 63|4@0+ (1,0) [0|15] "" CMM,BSI,PASS_HCU2,CMF,ARTIV + +BO_ 840 Dyn2_CMM: 8 CMM___Motor_SG + SG_ P165_FlFCD_stWtLvlSensDebVal : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P152_Gearbx_stGear : 4|4@1+ (1,0) [0|15] "-" Vector__XXX + SG_ P019_Com_trqPrp : 8|8@1+ (2,-100) [-100|410] "Nm" Vector__XXX + SG_ P211_AirC_pClnt : 16|8@1+ (1,110) [110|2904] "kpa" Vector__XXX + SG_ P017_Com_trqFrc : 24|8@1+ (2,-100) [-100|408] "Nm" Vector__XXX + SG_ P026_Com_bESPAck : 32|1@1+ (1,0) [0|0] "-" Vector__XXX + SG_ P025_Com_stESPErr : 33|2@1+ (1,0) [0|0] "-" Vector__XXX + SG_ P091_ConvCD_stDebVal : 35|2@1+ (1,0) [0|3] "-" Vector__XXX + SG_ P212_Comp_load_shed : 37|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ P134_Com_stEng : 40|4@1+ (1,0) [0|0] "-" Vector__XXX + SG_ P343_Com_bOBDErr : 49|1@1- (1,0) [0|0] "" Vector__XXX + SG_ P344_Com_bMILOn : 50|1@1- (1,0) [0|0] "" Vector__XXX + SG_ P345_Com_bMILBln : 51|1@1- (1,0) [0|0] "" Vector__XXX + SG_ P370_Com_bWUC : 52|1@1- (1,0) [0|0] "" Vector__XXX + SG_ P371_Com_bDrivingCycl : 53|1@1- (1,0) [0|0] "" Vector__XXX + SG_ P372_T15_st : 54|1@1- (1,0) [0|0] "" Vector__XXX + SG_ P207_Fan_rAct : 56|6@1+ (2,0) [0|100] "" Vector__XXX + SG_ P269_StSys_stStrtBVMPAuth : 62|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 841 Dyn_V2_BVMP: 8 BVA___Automatikgetriebe + SG_ P030_Gbx_stDrvTrnEgd : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P360_Com_stIntvTyp : 2|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ P440_Com_bUCAPSWkUpReqRaw : 5|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ P057_Com_xTrqTIIDes : 8|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P009_Com_bGearShftActv : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P362_Com_bGearShftExpt : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P333_Com_stGbxTrqIntv : 18|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P085_Com_bGbxACCmprShOff : 20|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P167_Com_stEngSpdCtl : 21|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P287_Com_stGearRat : 24|4@1+ (1,0) [0|15] "-" Vector__XXX + SG_ P283_Com_stGearTrgtPos : 28|4@1+ (1,0) [0|15] "-" Vector__XXX + SG_ P230_Com_ctTSCCntr : 51|4@0+ (1,0) [0|15] "-" Vector__XXX + SG_ P340_Com_xTSCChkSum : 55|4@0+ (1,0) [0|15] "-" Vector__XXX + SG_ P166_Com_nEngTSC : 56|8@1+ (25,750) [750|7075] "RPM" Vector__XXX + +BO_ 845 Dyn_CDS: 8 CDS___Fahrdynamikregelung + SG_ P047_Com_stESPIntv : 0|3@1+ (1,0) [0|7] "-" CMM___Motor_SG + SG_ P088_CutOffForbidden_OR_ESP_STATUS_INV : 3|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P147_Com_bESPIntvActv : 6|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P043_Com_xTCSStatRaw : 16|8@1+ (3,-150) [-150|612] "Nm" Vector__XXX + SG_ P044_Com_trqTCSRaw : 24|8@1+ (2,-100) [-100|410] "Nm" Vector__XXX + SG_ P045_Com_trqDCSRaw : 32|8@1+ (2,-100) [-100|410] "Nm" Vector__XXX + SG_ P157_Com_ctESP : 40|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P352_StbIntv_bTCSIntvActv : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P353_StbIntv_bESPExclvIntvActv : 52|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 904 Dyn_Veh: 7 CMM___Motor_SG + SG_ P060_vECU : 7|16@0+ (0.01,0) [0|655.34] "km/h" Vector__XXX + SG_ P062_sECU : 23|16@0+ (0.1,0) [0|6553.5] "m" Vector__XXX + SG_ P066_aECU : 32|8@1+ (0.08,-14) [-14|6.32] "m/s**2" Vector__XXX + +BO_ 909 HS2_DYN_ABR_38D: 8 UC_FREIN + SG_ VITESSE_VEHICULE_ROUES : 7|16@0+ (0.01,0) [0|655.34] "km/h" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ DISTANCE_ROUES : 23|16@0+ (0.1,0) [0|6553.5] "m" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ P052_Com_aLng : 32|8@1+ (0.08,-14) [-14|6.32] "m/s**2" Vector__XXX + SG_ ACCEL_LONGI_ROUES : 39|8@0+ (0.08,-14) [-14|6.32] "m/s2" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ CHECKSUM : 43|4@0+ (1,0) [0|7] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ COUNTER : 47|4@0+ (1,0) [0|15] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ VHL_MVT : 49|2@0+ (1,0) [0|3] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ VVH_INDISP : 51|2@0+ (1,0) [0|3] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ SENS_ROULAGE : 53|2@0+ (1,0) [0|3] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ AUTOR_ARRET_HILL_STT : 54|1@0+ (1,0) [0|1] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ REQ_LAMPE_WARNING : 55|1@0+ (1,0) [0|1] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ HADC_FAULTY : 58|2@0+ (1,0) [0|3] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ HADC_STATUS : 60|2@0+ (1,0) [0|3] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ HADC_SPEED_CONDITION : 61|1@0+ (1,0) [0|1] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + SG_ HADC_CLUTCH_CONDITION : 63|2@0+ (1,0) [0|3] "" CMF,CMM,BV,BSI,HCU1,ARTIV,BVN,AVAS + +BO_ 941 Dyn_EasyMove: 8 CDS___Fahrdynamikregelung + SG_ P299_Com_bCrCtlInhib : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P337_Com_stPrkBrk : 24|3@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 968 Dyn_STT_CMM: 2 Vector__XXX + SG_ P412_Com_stDeadPnt : 2|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P428_Com_stCDTReq : 6|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 969 Dyn2_V2_BV: 6 BVA___Automatikgetriebe + SG_ P291_Com_trqMaxConv : 7|8@0+ (3,-150) [-150|615] "" Vector__XXX + SG_ P__Rapport_cible : 23|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ P230_Com_ctGbxCnt2 : 27|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ P340_Com_xChkSum2 : 31|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ P293_Com_stGbxEngShOff : 38|2@0+ (1,0) [0|3] "" Vector__XXX + +BO_ 973 Dyn2_FRE: 8 ABS___Antiblockiersystem + SG_ P226_Com_stBrkActv : 0|2@1+ (1,0) [0|4] "" Vector__XXX + SG_ P225_Com_stBrkRaw_0 : 37|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P224_Com_stBrkRaw_1 : 38|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ BRAKE_PRESSURE : 47|12@0+ (1,0) [0|0] "" Vector__XXX + SG_ P319_FrmMng_rClthPos : 56|8@1+ (0.5,0) [0|255] "%" Vector__XXX + +BO_ 1010 LANE_KEEP_ASSIST: 8 XXX + SG_ DRIVE : 6|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 11|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 15|4@0+ (1,0) [0|15] "" XXX + SG_ unknown2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ TORQUE : 31|11@0- (1,0) [0|2047] "" XXX + SG_ LANE_DEPARTURE : 33|2@0+ (1,0) [0|3] "" XXX + SG_ STATUS : 36|3@0+ (1,0) [0|3] "" XXX + SG_ LXA_ACTIVATION : 40|1@0+ (1,0) [0|1] "" XXX + SG_ TORQUE_FACTOR : 47|7@0+ (1,0) [0|127] "" XXX + SG_ SET_ANGLE : 55|14@0- (0.1,0) [-90|90] "" XXX + SG_ unknown4 : 57|1@0+ (1,0) [0|1] "" XXX + +BO_ 1042 Dat_BSI: 8 BSI___Kombiinstrument + SG_ P040_MainBrakeFault : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P103_Com_bRevGear : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PARKING_BRAKE : 3|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ P013_MainBrake : 5|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P277_Com_bOilLvlDem : 10|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P298_Req_RTE_Ena : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P012_Com_bFlMin : 24|1@1+ (1,0) [0|0] "-" Vector__XXX + SG_ P086_Com_stFlLvlDia : 25|2@1+ (1,0) [0|3] "-" Vector__XXX + SG_ P328_Com_stEHRPmp : 27|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P104_Dspl_stAOHt : 30|2@1+ (1,0) [0|3] "-" CMM___Motor_SG + SG_ DRIVER_DOOR : 51|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ PASSENGER_DOOR : 52|1@0+ (1,0) [0|1] "" Vector__XXX + +BO_ 1069 NEW_MSG_42D: 4 XXX + SG_ COUNTER : 16|4@1+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 20|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_RELATED : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 1074 Dat_BSI1: 8 BSI___Kombiinstrument + SG_ P249_Com_stEngStopReq : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P216_Com_bSiaWkUp : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P214_Com_stMnWkUp : 6|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P402_Com_stStaDemActv : 12|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P253_Com_bEngPrepReq : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P267_Exh_volRefl : 24|8@1+ (0.5,0) [0|255] "l" Vector__XXX + SG_ P276_Com_bOilWkUp : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P274_Exh_ctRefl : 40|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ P403_Com_stStaReq : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P439_Com_bUCAPSWkUpReqRaw : 45|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P350_Com_bPstVtln : 46|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P368_Com_stMnSEVRaw : 48|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P367_Com_stCtxJDDRaw : 50|6@1+ (1,0) [0|63] "" Vector__XXX + SG_ P369_Com_stElecNetRaw : 60|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 1101 Vroues_ABR: 8 CDS___Fahrdynamikregelung + SG_ P330_VehV_vWhlRrL : 23|16@0+ (0.01,0) [0|655.34] "km/h" Vector__XXX + SG_ P331_VehV_vWhlRrR : 39|16@0+ (0.01,0) [0|655.34] "km/h" Vector__XXX + SG_ P354_VehV_nWhlAvrg : 55|16@0+ (0.04,0) [0|0] "rpm" Vector__XXX + +BO_ 1106 HS2_DAT_MDD_CMD_452: 6 BSI + SG_ LONGITUDINAL_REGULATION_TYPE : 1|2@0+ (1,0) [0|3] "" CMF,ARTIV,CMM,UC_FREIN + SG_ TURN_SIGNAL_STATUS : 5|2@0+ (1,0) [0|3] "" CMF,ARTIV,CMM,UC_FREIN + SG_ FRONT_WIPER_STATUS : 7|2@0+ (1,0) [0|3] "" CMF,ARTIV,CMM,UC_FREIN + SG_ SPEED_SETPOINT : 15|8@0+ (1,0) [0|255] "km/h" CMF,ARTIV,CMM,UC_FREIN + SG_ CHECKSUM_CONS_RVV_LVV2 : 17|2@0+ (1,0) [0|3] "" CMF,ARTIV,CMM,UC_FREIN + SG_ BRAKE_ONLY_CMD_BSI : 18|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ LVV_ACTIVATION_REQ : 22|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ RVV_ACC_ACTIVATION_REQ : 23|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ ARC_HABIT_SENSITIVITY : 26|3@0+ (1,0) [0|7] "" CMF,ARTIV,CMM,UC_FREIN + SG_ ARC_HABIT_ACTIVATION_REQ : 27|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ COUNTER : 31|4@0+ (1,0) [0|15] "" CMF,ARTIV,CMM,UC_FREIN + SG_ FRONT_WASH_STATUS : 32|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ FORCE_ACTIVATION_HAB_CMD : 33|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ INTER_VEHICLE_TIME_SETPOINT : 39|6@0+ (0.1,0) [0|6.1] "s" CMF,ARTIV,CMM,UC_FREIN + SG_ CHECKSUM : 43|4@0+ (1,0) [0|15] "" CMF,ARTIV,CMM,UC_FREIN + SG_ COCKPIT_GO_ACC_REQUEST : 45|1@0+ (1,0) [0|1] "" CMF,ARTIV,CMM,UC_FREIN + SG_ ACC_PROGRAM_MODE : 47|2@0+ (1,0) [0|3] "" CMF,ARTIV,CMM,UC_FREIN + +BO_ 1128 Dyn3_CMM: 6 CMM___Motor_SG + SG_ P247_Com_stStaFunc : 3|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P246_Com_bStaPrt : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P245_Com_stRedBrkPlaus : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P244_Com_bSta : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P400_Com_stDrvTrnTx : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P401_Com_stStrtAuth : 10|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P234_Com_stAcvWarn : 13|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ P347_Alt_uSetPoint : 25|6@0+ (1,0) [0|63] "" Vector__XXX + SG_ P346_Alt_enumPwrProd : 26|3@1+ (1,0) [0|7] "-" Vector__XXX + SG_ P408_Com_bRly3CtlReq : 40|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1160 Dat_CMM: 8 CMM___Motor_SG + SG_ P005_CEngDst_tSens : 0|8@1+ (1,-40) [-40|214] "°C" Vector__XXX + SG_ P021_Com_volFlCons : 8|8@1+ (80,0) [0|20400] "mm^3" Vector__XXX + SG_ P022_Com_nSetPLo : 16|8@1+ (8,0) [0|2032] "1/min" Vector__XXX + SG_ P032_Com_bEngStrt : 24|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P031_GlwLmp_st : 25|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P105_Com_bTtLmp : 27|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P108_Fid_ComAddPmpLvl : 28|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P296_AOHt_stPmp : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P063_vehV_bXVVErr : 30|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P233_Fid_PFltDef_mp : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P053_ACCtl_stHys : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P051_ACCD_stPres : 33|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P154_PFlt_bPFltClnReq : 38|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P011_Oil_tSwmp : 40|8@1+ (1,-40) [-40|213] "" Vector__XXX + SG_ P056_ACCD_p : 48|8@1+ (25,0) [100|3100] "kPa" Vector__XXX + SG_ P158_Air_tAFS : 56|8@1+ (1,-40) [-40|214] "°C" Vector__XXX + +BO_ 1161 Dat_V2_BV: 8 BVA___Automatikgetriebe + SG_ P374_Com_bOBDRdy : 8|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ P029_Com_stPrg : 11|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ P282_Com_stGbxErr : 12|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P375_Com_bMILDem : 16|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ P376_Com_bMILcntResDemRaw : 18|1@0+ (1,0) [0|1] "" Vector__XXX + SG_ P285_Com_bPNDia : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P218_Com_stDrvIdx : 48|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 1173 IS_DAT_DIRA: 4 PSCM + SG_ EPS_TORQUE : 7|8@0- (0.25,0) [-32|31.5] "Nm" Tester + SG_ ETAT_DA_2004 : 9|2@0+ (1,0) [0|3] "" Tester + SG_ ETAT_DA_DYN : 13|2@0+ (1,0) [0|3] "" Tester + SG_ ETAT_DA_2010 : 15|2@0+ (1,0) [0|3] "" Tester + SG_ TRQ_LIMIT_STATE : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ STEERWHL_HOLD_BY_DRV : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ EPS_STATE_LKA : 20|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ AUTOR_ARRET_MOT_DA : 21|1@0+ (1,0) [0|1] "" Tester + SG_ STEERING_REBOOT_REQUEST : 23|1@0+ (1,0) [0|1] "" Tester + SG_ Reserved : 31|8@0+ (1,0) [0|255] "" Tester + +BO_ 1224 Etat_Crash: 3 BSI___Kombiinstrument + SG_ Reserved_1 : 7|8@0+ (1,0) [0|0] "-" Vector__XXX + SG_ P223_CrashInfo : 8|1@0+ (1,0) [0|0] "-" Vector__XXX + SG_ Reserved_2 : 23|8@0+ (1,0) [0|0] "-" Vector__XXX + +BO_ 1266 Dat3_BSI: 8 Vector__XXX + SG_ P434_Com_rBattChHiRes : 7|10@0+ (0.1,0) [0|100] "" Vector__XXX + SG_ P429_Com_stSOCInfoInvldRaw : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P435_Com_stUCAPRechCrntRaw : 10|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P438_Com_uBattIntRstnRaw : 23|10@0+ (0.01,0) [0|10.23] "" Vector__XXX + SG_ P437_Com_uBattOpnCir : 24|9@0+ (0.01,0) [0|14] "" Vector__XXX + SG_ P493_Com_stPrioVoltMin : 41|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ P490_Com_uVoltCtlProdMin : 47|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ P494_Com_stPrioVoltMax : 49|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ P491_Com_uVoltCtlProdMax : 55|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ P492_Com_uVarProdMax : 63|7@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1270 HS2_DAT_ARTIV_V2_4F6: 5 ARTIV + SG_ TIME_GAP : 7|8@0+ (0.1,0) [0|25.4] "s" RITCS,BSI,CMF + SG_ DISTANCE_GAP : 15|8@0+ (1,0) [0|253] "m" RITCS,BSI,CMF + SG_ RELATIVE_SPEED : 20|13@0+ (0.02,-70) [-70|70] "m/s" RITCS,BSI,CMF + SG_ ARTIV_SENSOR_STATE : 23|3@0+ (1,0) [0|0] "" RITCS,BSI,CMF + SG_ TARGET_DETECTED : 36|1@0+ (1,0) [0|0] "" RITCS,BSI,CMF + SG_ ARTIV_TARGET_CHANGE_INFO : 37|1@0+ (1,0) [0|0] "" RITCS,BSI,CMF + SG_ TRAFFIC_DIRECTION : 39|2@0+ (1,0) [0|0] "" RITCS,BSI,CMF + +BO_ 1293 Dat_ABR: 7 ABS___Antiblockiersystem + SG_ P351_Com_bABSIntvActv : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P415_Com_stABSSTTReqRaw : 52|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1294 Dat_CLIM: 8 BSI___Kombiinstrument + SG_ P050_Com_stAC : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P209_Com_stACRaw : 1|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P433_Com_bCmptEngStopReqRaw : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P232_Com_stXVVChkSum : 4|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P046_Com_rFanClgDes : 8|6@1+ (2,0) [0|110] "%" Vector__XXX + SG_ P164_Com_stPFltFan : 14|2@1+ (1,0) [0|0] "" Vector__XXX + SG_ P144_Com_bPFltGlw : 17|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P189_Com_stEEMIdlDem : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P432_Com_bCmptEngRstrtReqRaw : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P417_Com_stDrvPrsRaw : 25|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P210_Com_pwrACDem : 32|8@1+ (25,0) [0|6350] "W" Vector__XXX + SG_ P208_Com_nACIdlDem : 40|8@1+ (8,0) [0|2032] "" Vector__XXX + SG_ P219_Com_xPrpReqRaw : 48|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P231_Com_ctBSIFrm : 56|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P222_Typ_PrpCtl_Req : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P221_Speed_setPoint_Typ : 61|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P220_Com_stPrpMsgRaw : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1362 DAT4_BSI_AEE2010: 8 Vector__XXX + SG_ P325_Com_tiEngOff : 7|32@0+ (1,0) [0|1000] "" Vector__XXX + SG_ P015_Com_lTotDst : 39|24@0+ (1,0) [0|16777215] "km" Vector__XXX + SG_ P326_Com_ctTmrRst : 63|8@0+ (1,0) [0|255] "" Vector__XXX + +BO_ 1375 ACQ_NEW_JDD: 1 Vector__XXX + SG_ P__JDD_Com_stFaultAck : 7|8@0+ (1,0) [0|255] "" Vector__XXX + +BO_ 1390 DRIVER: 6 XXX + SG_ NEW_SIGNAL_3 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ BRIGHTNESS_SETTING : 7|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 13|1@0+ (1,0) [0|1] "" XXX + SG_ GAS_PEDAL : 31|8@0+ (0.5,0) [0|99.5] "%" XXX + +BO_ 1394 RESTRAINTS: 8 XXX + SG_ PASSENGER_SEATBELT : 5|2@0+ (1,0) [0|3] "" XXX + SG_ DRIVER_SEATBELT : 7|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_1 : 23|11@0+ (1,0) [0|1] "" XXX + SG_ IGNITION : 32|1@0+ (1,0) [0|1] "" XXX + +BO_ 1416 Dat2_CMM: 8 CMM___Motor_SG + SG_ P275_EngOilLvl : 7|8@0- (3,0) [0|0] "" Vector__XXX + SG_ P268_AdPmp_volAddInjStp : 8|8@1+ (5,0) [0|255] "mm3" Vector__XXX + SG_ P278_Oil_stPSwmp : 16|1@1- (1,0) [0|1] "" Vector__XXX + SG_ P424_Com_bMMIClthReq : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P423_Com_bMMIStSpAvl : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P316_FlSys_volFlConsVirt : 24|8@1+ (80,0) [0|20400] "mm^3" Vector__XXX + SG_ P373_CoETS_rTrq : 32|8@1+ (0.39215686275,0) [0|100] "%" Vector__XXX + SG_ P414_Com_stSTTFunc : 40|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P338_EnvP_p : 42|5@1+ (15,685) [0|1120] "" Vector__XXX + SG_ P288_Com_bSVSLmp : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P366_CoEom_stEngOpm : 48|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P446_Com_bAuthAdPmp : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P425_Com_stVltgSysLd : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P422_Com_bSyncDlyStSp : 54|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P359_SITUATION_VIE : 58|3@0+ (1,0) [0|7] "" Vector__XXX + SG_ P358_SENS_CHGMT_RAP : 60|2@0+ (1,0) [0|3] "" Vector__XXX + SG_ P357_RAP_CIBLE_TRANSMIS : 63|3@0+ (1,0) [0|7] "" Vector__XXX + +BO_ 1423 Rep_Diag_OBC_DCDC: 7 XXX + +BO_ 1424 Req_Diag_OBC_DCDC: 3 XXX + +BO_ 1426 Dat6_BSI: 8 CMM___Motor_SG + SG_ P272_Com_rBattCh : 0|8@1+ (1,0) [0|100] "%" Vector__XXX + SG_ P273_Com_tBatt : 8|8@1+ (0.5,-30) [-30|97.5] "deg C" Vector__XXX + SG_ P418_Com_uBattRaw : 28|11@0+ (0.01,5) [5|25.47] "" Vector__XXX + SG_ P349_EEM_stAltCtlType : 29|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ P420_Com_stBattCrntMeasRaw : 40|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P419_Com_stSTTActvRaw : 44|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P421_Com_xBattCrnt : 55|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1458 Contexte1_5B2: 8 Vector__XXX + SG_ P146_Com_tEnvT : 16|8@1+ (0.5,-40) [-40|87] "°C" Vector__XXX + SG_ P100_Com_stAddPmpDef : 24|8@1+ (1,0) [0|255] "-" Vector__XXX + SG_ P__Com_stEOBD : 39|8@0+ (1,0) [0|255] "-" Vector__XXX + +BO_ 1475 NEW_MSG_5C3: 8 XXX + SG_ ESP_STATUS_RELATED_1 : 27|2@0+ (1,0) [0|3] "" XXX + SG_ ESP_STATUS_RELATED_2 : 28|1@0+ (1,0) [0|1] "" XXX + +BO_ 1544 EOBD_CMM: 8 CMM___Motor_SG + SG_ P__LID_No : 0|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data1_PID : 8|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data2_PID : 16|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data3_PID : 24|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data4_PID : 32|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data5_PID : 40|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data6_PID : 48|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ P__Data7_PID : 56|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 1554 HS2_DAT7_BSI_612: 8 BSI + SG_ INH_ECLAIRAGE_VIRAGE_DYN : 5|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ INH_ECLAIRAGE_AUTOROUTE : 6|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ INH_DIURNE_ECLRGE : 7|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ ETAT_FEUX_CROIST : 9|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ ETAT_FEUX_ROUTE : 10|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ MODE_CONF_VEH : 13|2@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ CDE_CLG_ET_HDC : 15|2@0+ (1,0) [0|3] "" CMM,BV,BVN + SG_ MODE_ECO : 17|2@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ MODE_ASR_PLUS_SELECT : 19|2@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ DEF_FEU_ROUTE_G : 20|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ DEF_FEU_ROUTE_D : 21|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ DEF_FEU_CROISMNT_G : 22|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ DEF_FEU_CROISMNT_D : 23|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ INFO_NIV_CARB : 31|8@0+ (0.5,0) [0|127] "L" CMM,BV,BVN + SG_ U_PRED_DEMARRAGE : 34|11@0+ (0.01,0) [0|13] "V" CMM,BV,BVN + SG_ POS_DEFLEC_MOBILE : 38|3@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ INFO_REQ_OLVI_REAR_ACT : 39|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ UB_D_LIGNE_REL_RX : 49|1@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ D_LIGNE_REL_R2 : 52|3@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ D_LIGNE_REL_R1 : 55|3@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ CONFIG_VHL : 60|3@0+ (1,0) [0|0] "" CMM,BV,BVN + SG_ D_LIGNE_REL_R3 : 63|3@0+ (1,0) [0|0] "" CMM,BV,BVN + +BO_ 1610 Rep_Diag_CVM: 7 XXX + +BO_ 1666 Rep_Diag_VCU: 7 XXX + +BO_ 1670 Rep_Diag_HCU2: 7 XXX + +BO_ 1672 Rep_Diag_On_CAN_688: 8 Vector__XXX + +BO_ 1677 Rep_Diag_ABRASR: 7 XXX + +BO_ 1684 Rep_Diag_MSB: 7 XXX + +BO_ 1685 Rep_Diag_DIRECTN: 7 XXX + +BO_ 1686 Rep_Diag_ARTIV: 7 XXX + +BO_ 1697 Req_Diag_SCR: 3 XXX + +BO_ 1698 Req_Diag_VCU: 3 XXX + +BO_ 1702 Req_Diag_HCU2: 3 XXX + +BO_ 1704 Req_Diag_On_CAN_6A8: 8 Vector__XXX + +BO_ 1705 Req_Diag_BOITEVIT: 3 XXX + +BO_ 1709 Req_Diag_ABRASR: 3 XXX + +BO_ 1716 Req_Diag_MSB: 3 XXX + +BO_ 1717 Req_Diag_DIRECTN: 3 XXX + +BO_ 1718 Req_Diag_ARTIV: 3 XXX + +BO_ 1719 Req_Diag_CORPRO: 3 XXX + +BO_ 1722 Req_Diag_CONV_PUIS: 3 XXX + +BO_ 1792 Req_Diag_BMF_UDS_CQCA: 8 XXX + +BO_ 1793 Req_Diag_COMBINE_UDS_CQCA: 8 XXX + +BO_ 1810 Rep_Diag_BAAST: 8 XXX + +BO_ 1815 Rep_Diag_CTPA: 8 XXX + +BO_ 1824 Req_Diag_BSP: 8 XXX + +BO_ 1840 Req_Diag_CPL_MOTED_SUSPVAR: 8 XXX + +BO_ 1842 Req_Diag_BAAST_BAASL_FEU_AR_C_CCE: 8 XXX + +BO_ 1847 Req_Diag_CTPA: 4 XXX + +BO_ 1856 Req_Diag_IDB: 8 XXX + +BO_ 1858 Req_Diag_HDC: 8 XXX + +BO_ 1859 Req_Diag_AFFICHEUR_LVDS_BD: 8 XXX + +BO_ 1860 Req_Diag_AIRBAG: 8 XXX + +BO_ 1862 Req_Diag_RHF: 8 XXX + +BO_ 1866 Req_Diag_CVM_CPL: 3 XXX + +BO_ 1871 Req_Diag_AVM_AVE: 8 XXX + +BO_ 1872 Req_Diag_PDSP_DCU_FD_AUTDEM_BML_ES_CSP: 8 XXX + +BO_ 1875 Req_Diag_RETRO_INT: 8 XXX + +BO_ 1879 Req_Diag_BDMAR_DCU_RL: 8 XXX + +BO_ 1888 Req_Diag_AUTORADIO: 8 XXX + +BO_ 1889 Req_Diag_BMU_IVC_D: 8 XXX + +BO_ 1892 Req_Diag_TELEMAT: 8 XXX + +BO_ 1896 BSI_FaultLog: 8 CMM___Motor_SG + SG_ P__BSI_FaultLog_Header : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_DTC1 : 8|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_DTC2 : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_Env1 : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_Env2 : 32|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_Env3 : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_Env4 : 48|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ P__BSI_FaultLog_Env5 : 56|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 1906 FaultLog_Ack: 1 BSI___Kombiinstrument + SG_ P__FaultLog_Ack : 0|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 1922 Req_Diag_CMB: 8 XXX + +BO_ 1927 Req_Diag_TRANSMISSION: 8 XXX + +BO_ 1928 Supv_CMM: 8 CMM___Motor_SG + SG_ P073_SupervisionFaultCodes : 7|8@0+ (1,0) [0|255] "-" Vector__XXX + SG_ P071_ConfirmedAbsentFlags : 15|32@0+ (1,0) [0|4294967295] "-" Vector__XXX + SG_ P284_T15CD_stPart : 43|12@0+ (1,0) [0|4095] "" Vector__XXX + SG_ P242_T15CD_stElec : 44|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 1942 HS2_SUPV_ARTIV_796: 8 ARTIV + SG_ FAULT_CODE : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ STATUS_NO_CONFIG : 15|32@0+ (1,0) [0|0] "" Vector__XXX + SG_ STATUS_PARTIAL_WAKEUP_GMP : 43|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ UCE_ELECTR_STATE : 47|4@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1953 Rep_Diag_BMF_CAN_MMC_2: 8 XXX + +BO_ 1968 Req_Diag_BMF_CAN_FIAT_CONBINE_CAN_FIAT_SUSPVAR: 8 XXX + +BO_ 2015 Req_EOBD_On_Can_7DF: 8 Vector__XXX + +BO_ 2016 Req_Diag_INJ_T: 8 Vector__XXX + +BO_ 2024 Rep_Diag_INJ_T: 8 Vector__XXX + +BO_ 3221225472 VECTOR__INDEPENDENT_SIG_MSG: 0 Vector__XXX + SG_ Code : 0|5@0+ (1,0) [0|0] "" Vector__XXX + SG_ ConfIdCde : 0|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ ConfIdStatus : 0|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data0 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data1 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data2 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data3 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data4 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data5 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data6 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Data7 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Diagnostic_On_Can : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ Edge : 0|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ GetConfIdCde : 0|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ GetConfIdStatus : 0|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ IdPert : 0|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ Input1 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Input2 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Input3 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Input4 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Local_ID : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ Mask0 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask1 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask2 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask3 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask4 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask5 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask6 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Mask7 : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MaskIdPert : 0|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ NumScenario : 0|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ Output0 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Output1 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Output2 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ Output3 : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OutputNumber : 0|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ P004_ActualTorqueNoGearbox : 0|8@1+ (2,-100) [-100|408] "Nm" Vector__XXX + SG_ P013_Com_stBrk1 : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P028_Gbx_stEOBDFault : 0|4@1+ (1,0) [0|15] "-" Vector__XXX + SG_ P033_sABS : 0|16@0+ (0.1,0) [0|6553.5] "m" Vector__XXX + SG_ P040_Com_stBrkRaw1 : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P041_Cde_RVV : 0|2@1+ (1,0) [0|3] "-" Vector__XXX + SG_ P049_Com_bMIL : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P051_ACCD_stPres : 0|2@1+ (1,0) [0|3] "-" Vector__XXX + SG_ P053_ACCtl_stHys : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P055_Com_trqTCSAbs : 0|8@1+ (2,-100) [-100|408] "Nm" Vector__XXX + SG_ P069_Act_RVV : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P084_CoDT_trqGearbxDes : 0|8@1+ (2,-100) [-100|408] "Nm" Vector__XXX + SG_ P087_Com_stClth : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P093_Temp_aval_FAP : 0|8@1+ (4,-40) [0|255] "°C" Vector__XXX + SG_ P095_EngPrt_stOvrSpd : 0|2@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P101_Com_mAddPmpTot : 0|16@0+ (0.05,0) [0|3276.5] "g" Vector__XXX + SG_ P107_Com_stAddPmpLvl : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P128_Forcage_Encl_GMV : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P133_StSys_stEngSTT2Rls : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P135_StSys_stAR2s : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P145_Saturation_Active : 0|1@1+ (1,0) [0|1] "-" Vector__XXX + SG_ P227_Pwr_Gen_Support_state : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P229_Com_xTCChkSum : 0|4@1+ (1,0) [0|0] "" Vector__XXX + SG_ P243_FrmMng_stFlCnsmp_mp : 0|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ P248_StarterStopReq : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P250_MajorStartRequest : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P251_Com_stScndStrtReq : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P252_ImpluseStart : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P255_Com_tiSec : 0|20@0+ (1,0) [0|0] "" Vector__XXX + SG_ P256_Com_tiDay : 0|12@0+ (1,0) [0|0] "" Vector__XXX + SG_ P257_Com_tiYr : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ P261_PCH_WakeUP : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P268_AddPmpCD_volAddInjStp : 0|8@1+ (10,0) [0|255] "" Vector__XXX + SG_ P284_T15CD_stPart_byte6 : 0|4@0+ (1,0) [0|15] "" Vector__XXX + SG_ P284_T15CD_stPart_byte8 : 0|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P290_StSys_stGlwAuth : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P292_FrmMng_stGearTrqReq : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P296_Fans_bEHRPmpReq : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P297_RTE_Fun_StErr : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P298_Com_stEHRCtl : 0|1@1- (1,0) [0|1] "" Vector__XXX + SG_ P308_EOBD_Rediness : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P314_VehDa_stTrqMax : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P315_VehDa_stEngSpdMax : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P317_FrmMng_dtBVMPChkSum : 0|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P318_FrmMng_ctBVMPCntr : 0|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ P325_Com_tiEngOffLSB : 0|16@1+ (1,0) [0|65535] "" Vector__XXX + SG_ P325_Com_tiEngOffMSB : 0|16@1+ (1,0) [0|65535] "" Vector__XXX + SG_ P348_Alt_bFault : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P361_Com_stTscEngDemTyp : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P363_Com_trqRelCrSConv : 0|8@1- (3,-150) [0|0] "Nm" Vector__XXX + SG_ P364_Gbx_nGbxIPSpeedFlt : 0|12@0+ (2,0) [0|0] "rpm" Vector__XXX + SG_ P399_Com_stProd : 0|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ P405_Com_stRly1DiagRaw : 0|3@1- (1,0) [0|7] "" Vector__XXX + SG_ P407_Com_stRly2DiagRaw : 0|3@1- (1,0) [-4|3] "" Vector__XXX + SG_ P416_Com_bStSpCabReqRaw : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ P427_Com_stBattTypEstRaw : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ P436_Com_uPrdcVltgStrtRaw : 0|11@0+ (0.01,0) [0|13] "" Vector__XXX + SG_ Rate : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Reserved_1 : 0|16@1+ (1,0) [0|255] "-" Vector__XXX + SG_ VersionActel : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionBaudRate : 0|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionDate : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionInput : 0|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionMajor : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionMinor : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionMode : 0|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionMonth : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VersionYear : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ code : 0|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ commande : 0|5@0+ (1,0) [0|0] "" Vector__XXX + +CM_ BO_ 114 "ID 072: Unlock Request Frame or LockingStatus (Event triggered)"; +CM_ SG_ 114 ADC2_Req_Status "Unlock request"; +CM_ SG_ 114 ADC2_Seed_Byte3 "SEED1 of RQD_CMM (highest byte)"; +CM_ SG_ 114 ADC2_Seed_Byte2 "SEED2 of RQD_CMM (high byte)"; +CM_ SG_ 114 ADC2_Seed_Byte1 "SEED3 of RQD_CMM (low byte)"; +CM_ SG_ 114 ADC2_Seed_Byte0 "SEED4 of RQD_CMM (lowest byte)"; +CM_ BO_ 146 "Trame BSI émise toutes les 100 ms pendant 1 seconde."; +CM_ BO_ 168 "ID A8: Unlock Permission Frame Code (Period time 10 ms)"; +CM_ SG_ 168 ADC2_Key_Status "Unlock permission"; +CM_ SG_ 168 ADC2_Key_Byte3 "KEY1 of CFD_BSI (highest byte)"; +CM_ SG_ 168 ADC2_Key_Byte2 "KEY2 of CFD_BSI (high byte)"; +CM_ SG_ 168 ADC2_Key_Byte1 "KEY3 of CFD_BSI (low byte)"; +CM_ SG_ 168 ADC2_Key_Byte0 "KEY4 of CFD_BSI (lowest byte)"; +CM_ BO_ 264 "ID 108: ECM Version Frame - Vers_CMM (Period: Single shot) + +Le contenu de la trame est une recopie d'un sous-ensemble de la zone d'identification de la Flash Eprom définie dans le document Application flash EPROM 2000 ref. 96.285.582.9."; +CM_ SG_ 264 P076_System "P076 system version"; +CM_ SG_ 264 P077_Day "P077 Date: day of the version"; +CM_ SG_ 264 P078_Month "P078 Date: month of the version"; +CM_ SG_ 264 P079_Year "P079 Date: year of the version"; +CM_ SG_ 264 P080_Application "P080 supplier application"; +CM_ SG_ 264 P081_Version "P081 Software version"; +CM_ SG_ 264 P082_Edition "P082 Software issue"; +CM_ SG_ 264 P083_Calibration "P083 Calibration issue"; +CM_ BO_ 520 "ID 208: Engine Dynamic Frame (Period time 10 ms)"; +CM_ SG_ 520 P000_Com_nEng "P000 Motordrehzahl"; +CM_ SG_ 520 P003_Com_trqActOut "P003 Actual torque"; +CM_ SG_ 520 P002_Com_rAPP "P002 rueckgerechnete PWG-Stellung"; +CM_ SG_ 520 P027_ACCtl_stLogicOut "P027 Klimakompressor Status ein/aus"; +CM_ SG_ 520 P014_Brk_stRed "P014 Redundanter Bremskontakt"; +CM_ SG_ 520 P037_VehV_stXVV "P037 Zustand des FGR (Ein/Aus,Ueberdruecken)"; +CM_ SG_ 520 P153_Com_bTrqInacc "P153: Indicates to the torque consumers that the accuracy of the +torque data output is not guaranteed by the CMM."; +CM_ SG_ 520 P042_Inm_bCanMon "P042 CAN-Fehlerbehandlung im Startfall mit Hilfe der + Startendekennung unterdrücken"; +CM_ SG_ 520 P127_EGT_st_Bit30 "P127: Regeneration aid by electric consumers (engine load increase)."; +CM_ SG_ 520 P198_ActMod_trqClthTraIntv "P084 Vorweggenommenes Drehmoment"; +CM_ SG_ 694 ACC_STATUS "Indicates the operational state of the ACC system."; +CM_ SG_ 694 DYN_ACC_CHECKSUM "CHK_INI = 0x3"; +CM_ SG_ 694 DYN_ACC_PROCESS_COUNTER "This counter increments from 0 to 15 at each activation of the calculation process."; +CM_ SG_ 757 ANGLE "asymmetric, could be init"; +CM_ SG_ 758 CHECKSUM_TRANSM_DYN_ACC2 "CHK_INI = 0x7"; +CM_ SG_ 758 PROCESS_COUNTER_4B_ACC2 "This counter increments from 0 to 15 at each activation of the calculation process."; +CM_ SG_ 773 ANGLE "-565 to 560, seems like estimate and not init"; +CM_ SG_ 773 RATE_SIGN "1=moving clockwise, 0=moving anticlockwise"; +CM_ SG_ 773 0_CHECKSUM "TODO: find checksum"; +CM_ BO_ 840 "ID 348: Engine Dynamic Frame 2 (Period time 20 ms)"; +CM_ SG_ 840 P165_FlFCD_stWtLvlSensDebVal "P165: Water in fuel indication (1 = water in fuel detected / 0 = no water in fuel)"; +CM_ SG_ 840 P152_Gearbx_stGear "P152: Gear detected by ratio vehicule speed to engine speed"; +CM_ SG_ 840 P019_Com_trqPrp "P019 Requested torque before processing."; +CM_ SG_ 840 P211_AirC_pClnt "P084 Vorweggenommenes Drehmoment"; +CM_ SG_ 840 P017_Com_trqFrc "P017 Torque lost by AC, friction, high pressure pump and acsessories."; +CM_ SG_ 840 P026_Com_bESPAck "P026 TCS/DCS (ASR/MSR) acknowledgement by engine ECU +(1 = communication correct)"; +CM_ SG_ 840 P025_Com_stESPErr "P025 TCS/DCS (ASR/MSR) request state"; +CM_ SG_ 840 P091_ConvCD_stDebVal "P091 clutch pedal switch and status"; +CM_ SG_ 840 P212_Comp_load_shed "Compressor load shedding command"; +CM_ SG_ 840 P134_Com_stEng "Engine status"; +CM_ BO_ 841 "ID 349: Gearbox Synchronisation Frame (Period time 20 ms)"; +CM_ SG_ 841 P009_Com_bGearShftActv "P057 Gearbox torque request"; +CM_ SG_ 841 P085_Com_bGbxACCmprShOff "P085 AC compressor inhibit"; +CM_ SG_ 841 P167_Com_stEngSpdCtl "P009 shift in progress"; +CM_ SG_ 841 P287_Com_stGearRat "P008 transmission range engaged"; +CM_ SG_ 841 P283_Com_stGearTrgtPos "P087 gearbox converter state"; +CM_ SG_ 841 P230_Com_ctTSCCntr "P048 fan request for gearbox"; +CM_ SG_ 841 P340_Com_xTSCChkSum "P097 request to increase the idle speed"; +CM_ SG_ 841 P166_Com_nEngTSC "P055 torque limitation for gearbox"; +CM_ BO_ 845 "ID 34D: ESP Synchronisation frame (Period time 20 ms)"; +CM_ SG_ 845 P047_Com_stESPIntv "P047 ESP torque request status"; +CM_ SG_ 845 P088_CutOffForbidden_OR_ESP_STATUS_INV "P088 Cut off of injection is forbidden."; +CM_ SG_ 845 P147_Com_bESPIntvActv "P147 ESP-TCS (ASR) in regulation"; +CM_ SG_ 845 P043_Com_xTCSStatRaw "P043 TCS (ASR) static torque request = max. threshold"; +CM_ SG_ 845 P044_Com_trqTCSRaw "P044 TCS (ASR) dynamic torque request"; +CM_ SG_ 845 P045_Com_trqDCSRaw "P045 DCS (MSR) torque request = min. threshold"; +CM_ SG_ 845 P157_Com_ctESP "P157 Check counter"; +CM_ BO_ 904 "ID 388: Engine Dynamic Frame 3 (Period time 40ms)"; +CM_ SG_ 904 P060_vECU "P060 velocity by engine ECU"; +CM_ SG_ 904 P062_sECU "P062 odometer by engine ECU"; +CM_ SG_ 904 P066_aECU "P066 longitudinal acceleration by engine ECU"; +CM_ BO_ 909 "ID 38D: ABS Vehicle Dynamic Frame (Period time 40 ms)"; +CM_ SG_ 909 P052_Com_aLng "P052 longitudinal acceleration (FrmMng_a)"; +CM_ BO_ 969 "Pour application MCP SSTG"; +CM_ SG_ 1010 TORQUE "Set to ~2043 when active"; +CM_ SG_ 1010 LANE_DEPARTURE "UNUSED in HDA"; +CM_ SG_ 1010 STATUS "0=LKA OFF (button in console)"; +CM_ SG_ 1010 LXA_ACTIVATION "Set = 0, no activity seen in routes"; +CM_ BO_ 1042 "ID 412: Body Car Data Frame (Period time 50 ms)"; +CM_ SG_ 1042 P040_MainBrakeFault "P040 Main brake switch is defect."; +CM_ SG_ 1042 P103_Com_bRevGear "P013 main brake signal"; +CM_ SG_ 1042 P013_MainBrake "P013 main brake signal"; +CM_ SG_ 1042 P012_Com_bFlMin "P012 Minimum fuel level detected. If fuel level < 15 % signal P012 will be set to one."; +CM_ SG_ 1042 P086_Com_stFlLvlDia "P086 Minimum fuel level diagnosis status. (00 Minimum fuel is valid / 01 Minimum fuel is not valid / others are not defined)"; +CM_ SG_ 1042 P104_Dspl_stAOHt "P104 Ansteuerung Zusatzheizer"; +CM_ SG_ 1074 P249_Com_stEngStopReq "Engine stop request"; +CM_ SG_ 1074 P216_Com_bSiaWkUp "Immobilizer anticipation with wake up"; +CM_ SG_ 1074 P214_Com_stMnWkUp "Main wake-up (RCD )"; +CM_ SG_ 1074 P253_Com_bEngPrepReq "Engine preparation request"; +CM_ BO_ 1101 "ID 44D: Rear unfiltered wheel speeds, used for EasyMove"; +CM_ SG_ 1101 P330_VehV_vWhlRrL "P010 vehicle speed of ABS. This signal is loaded into VSSCD_v"; +CM_ SG_ 1101 P331_VehV_vWhlRrR "P010 vehicle speed of ABS. This signal is loaded into VSSCD_v"; +CM_ SG_ 1106 LONGITUDINAL_REGULATION_TYPE "Defines if the system is in RVV (Vehicle Speed Governor) or LVV (Vehicle Speed Limiter) or ACC (Adaptive Cruise Control) or without regulation."; +CM_ SG_ 1106 FRONT_WIPER_STATUS "Emitted when the rain sensor is active."; +CM_ SG_ 1106 SPEED_SETPOINT "Setpoint or limit: based on the value of the 'requested speed type' bit."; +CM_ SG_ 1106 CHECKSUM_CONS_RVV_LVV2 "Used to secure the RVV or LVV setpoint sent via the CAN network (signal SPEED_SETPOINT)."; +CM_ SG_ 1106 CHECKSUM "CHK_INI = 0xB"; +CM_ SG_ 1128 P247_Com_stStaFunc "CMM DAMP function state"; +CM_ SG_ 1128 P246_Com_bStaPrt "Starter protection"; +CM_ SG_ 1128 P245_Com_stRedBrkPlaus "Uncertain redendant brake contact"; +CM_ SG_ 1128 P244_Com_bSta "Starter state"; +CM_ BO_ 1160 "ID 488: Engine Data Frame (Period time 100 ms)"; +CM_ SG_ 1160 P005_CEngDst_tSens "P005 Wassertemperatur"; +CM_ SG_ 1160 P021_Com_volFlCons "P021 Kraftstoffverbrauch"; +CM_ SG_ 1160 P032_Com_bEngStrt "P032 Zustand Motor"; +CM_ SG_ 1160 P031_GlwLmp_st "P031 Ansteuerung Gluehanzeige"; +CM_ SG_ 1160 P105_Com_bTtLmp "P105 Temperaturwarnlampe: ein/aus"; +CM_ SG_ 1160 P108_Fid_ComAddPmpLvl "P106 Temperaturwarnlampe : blinken"; +CM_ SG_ 1160 P063_vehV_bXVVErr "P063 FGR-Fehler"; +CM_ SG_ 1160 P154_PFlt_bPFltClnReq "P154: Tell-tale lamp for \"risk of clogged filter\""; +CM_ SG_ 1160 P056_ACCD_p "P056 Kältemitteldruck"; +CM_ SG_ 1160 P158_Air_tAFS "P158: Intake air temperature."; +CM_ BO_ 1224 "ID 4C8: Crash status by Airbag Control (Event triggered / Period time 50 ms)"; +CM_ SG_ 1224 P223_CrashInfo "Crash Information"; +CM_ BO_ 1294 "ID 50E: Body Car & Air Conditioning Data Frame (Period time 100 ms)"; +CM_ SG_ 1294 P050_Com_stAC "P050 Fahrerwunsch Klimakompressor ein/aus ermitteln"; +CM_ SG_ 1294 P164_Com_stPFltFan "P164: Fan speed setpoint increase"; +CM_ BO_ 1362 "Trame utilisable uniquement sur véhicules en archi EE 2010 + +cette trame est émise toutes les 100ms pendant 1seconde puis toutes les secondes"; +CM_ SG_ 1362 P015_Com_lTotDst "P015: covered distance from dashboard"; +CM_ BO_ 1375 "trame utilisable uniquement pour le JDD en archi EE 2010"; +CM_ SG_ 1390 GAS_PEDAL "Max 99.5%"; +CM_ SG_ 1394 IGNITION "doesn't turn off straight away"; +CM_ BO_ 1458 "trame utilisable uniquement sur véhicules en archi EE 2010"; +CM_ SG_ 1458 P146_Com_tEnvT "P146: Environment air temperature"; +CM_ SG_ 1458 P100_Com_stAddPmpDef "P100: Status of additive for FAP"; +CM_ SG_ 1458 P__Com_stEOBD "Pxxx: EOBD relevant errors in the network"; +CM_ BO_ 1554 "trame consommée uniquement sur véhicules en archi EE 2010"; +CM_ BO_ 1610 "CVM_3, CVM_2, CVM"; +CM_ BO_ 1666 "VCU_EMS8000, E_VCU"; +CM_ BO_ 1670 "HCU2"; +CM_ BO_ 1677 "ABS81, ESP81, ABS8_BOSCH, ESP8_BOSCH, ESP90, ABSMK100, ESPMK100, ESP_KP1, ABS_KP1, ASC, ABS, ESP, ABS80, ESP80, ASR80, ABS90_D, ESP90_D, ESP90_F, ESPMK100_UDS, ESP_EBC_440_CAN, ESP_EBC_440_K, ESP_EBC_440, ABSMK70_1, ESPMK60_O, ABSMK100_UDS, ABS90_T, ABS_8_0_C1, ESP_8_0_C1, ABS_4x4, ESP_4x4, ABS81_BOSCH, ESP81_BOSCH, ABS90_F, RBV"; +CM_ BO_ 1684 "TBMU, TBMU_PHEV, BMU_CTE1"; +CM_ BO_ 1685 "GEP, DAE_BVH2, DAE, DAE_A515, DAE_UDS, EPS, SSCU, DAE_D, GEP_UDS, EPS_T"; +CM_ BO_ 1686 "ARTIV, RADAR_AV_4, LIDAR, ARTIV_UDS"; +CM_ BO_ 1704 "Le mécanisme d'émission utilisé est événementiel de l'outil vers le calculateur via la BSI +Trame question pour le téléchargement et le Diag On CAN."; +CM_ BO_ 1810 "BAAST"; +CM_ BO_ 1815 "CTPA"; +CM_ BO_ 1906 "Le mécanisme d'émission utilisé est événementiel de la BSI vers le CMM. + +Trame d'acquittement du Journal Des Défauts BSI."; +CM_ BO_ 1928 "ID 788: CMM Supervision Frame (Period time 1000 ms)"; +CM_ SG_ 1928 P073_SupervisionFaultCodes "P073 Supervision fault codes"; +CM_ SG_ 1928 P071_ConfirmedAbsentFlags "P071 confirmed absent status flags of the ECU"; +CM_ SG_ 1928 P284_T15CD_stPart "ECU electronic state"; +CM_ SG_ 1928 P242_T15CD_stElec "ECU electronic state"; +CM_ BO_ 1953 "BSI"; +CM_ BO_ 2015 "Le mécanisme d'émission utilisé est événementiel de l'outil branché sur le réseau Can vers les calculateurs. + +Trame question EOBD On Can adresse a tous les calculateurs"; +CM_ BO_ 2016 "Le mécanisme d'émission utilisé est événementiel de l'outil branché sur le réseau Can vers le CMM + +Trame question EOBD On Can adresse au CMM +ECU Family: INT_J"; +CM_ BO_ 2024 "Le mécanisme d'émission utilisé est événementiel du CMM vers l'outil branché sur le réseau Can + +Trame réponse EOBD On Can du CMM + +ECU Family: INJ_T"; +CM_ BO_ 3221225472 "This is a message for not used signals, created by Vector CANdb++ DBC OLE DB Provider."; +CM_ SG_ 3221225472 P004_ActualTorqueNoGearbox "P004 Actual torque before torque intervention by automatic gearbox"; +CM_ SG_ 3221225472 P028_Gbx_stEOBDFault "P028 MIL request gearbox"; +CM_ SG_ 3221225472 P033_sABS "P033 odometer"; +CM_ SG_ 3221225472 P041_Cde_RVV "P041 FGR-Bedienteilinfo"; +CM_ SG_ 3221225472 P049_Com_bMIL "P049 Ansteuerung DIA-Lampe"; +CM_ SG_ 3221225472 P051_ACCD_stPres "P051 Abschaltung Klimakompressor wegen Ueber- oder +Unterdruck im Kaeltemittelkreislauf"; +CM_ SG_ 3221225472 P053_ACCtl_stHys "P053 Abschaltung Klimakompressor aus Sicherheitsgruenden +oder wegen Komfortfunktionen"; +CM_ SG_ 3221225472 P069_Act_RVV "P069 FGR-Hauptschalter"; +CM_ SG_ 3221225472 P084_CoDT_trqGearbxDes "P084 Vorweggenommenes Drehmoment"; +CM_ SG_ 3221225472 P087_Com_stClth "Clutch signal for AM6"; +CM_ SG_ 3221225472 P093_Temp_aval_FAP "P093 FAP-Temperatur"; +CM_ SG_ 3221225472 P101_Com_mAddPmpTot "P101: absolute Menge des eingespritztem Additivs (Cerium)"; +CM_ SG_ 3221225472 P107_Com_stAddPmpLvl "P107 Minimum of FAP additive exeeded"; +CM_ SG_ 3221225472 P227_Pwr_Gen_Support_state "P165: Water in fuel indication (1 = water in fueel detected / 0 = no water in fuel)"; +CM_ SG_ 3221225472 P243_FrmMng_stFlCnsmp_mp "P155: Preparation of glow activation."; +CM_ SG_ 3221225472 P248_StarterStopReq "starter stop request"; +CM_ SG_ 3221225472 P250_MajorStartRequest "Main latch starting request"; +CM_ SG_ 3221225472 P251_Com_stScndStrtReq "Secondary latched starting request"; +CM_ SG_ 3221225472 P252_ImpluseStart "Momentary starting request"; +CM_ SG_ 3221225472 P284_T15CD_stPart_byte6 "ECU electronic state"; +CM_ SG_ 3221225472 P284_T15CD_stPart_byte8 "ECU electronic state"; +CM_ SG_ 3221225472 Reserved_1 "P074 Number of BusOff in driving cycle"; +VAL_ 461 ESP_STATUS 0 "DISABLED" 1 "ENABLED"; +VAL_ 461 ESP_STATUS_INV 0 "ENABLED" 1 "DISABLED"; +VAL_ 694 POTENTIAL_WHEEL_TORQUE_REQUEST 0 "Not requested" 1 "Requested in GMP mode" 2 "Requested in Brake mode" 3 "Not used"; +VAL_ 694 ACC_STATUS 0 "Initialization" 1 "OFF" 2 "Inhibited" 3 "Waiting" 4 "Active" 5 "Suspended" 6 "Brake only" 7 "Wait ramp" 8 "Reserved" 9 "Reserved" 10 "Reserved" 11 "Reserved" 12 "Reserved" 13 "Reserved" 14 "Reserved" 15 "Fault"; +VAL_ 694 WHEEL_TORQUE_REQUEST 0 "Not requested" 1 "High range requested" 2 "Low range requested" 3 "Not used"; +VAL_ 694 AUTO_BRAKING_STATUS 0 "Unavailable" 1 "Initialization" 2 "Not used" 3 "Inhibited" 4 "Not used" 5 "Waiting" 6 "Active" 7 "Fault"; +VAL_ 694 MDD_DECEL_TYPE 0 "No braking" 1 "ACC" 2 "FA_HV (high-speed automatic braking) / AFUi braking" 3 "FA_BV (low-speed automatic braking) / FARC2 braking"; +VAL_ 694 MDD_DECEL_CONTROL_REQ 0 "No UCF control request" 1 "UCF control request"; +VAL_ 694 GEAR_TYPE 0 "Downshift" 1 "Upshift"; +VAL_ 694 PREFILL_REQUEST 0 "No prefill request" 1 "Prefill request"; +VAL_ 728 ESP_STATUS_RELATED 0 "DISABLED" 1 "ENABLED"; +VAL_ 728 ESP_STATUS_RELATED_INV 0 "ENABLED" 1 "DISABLED"; +VAL_ 758 TARGET_DETECTED 0 "initialization or no target detected" 1 "target detected"; +VAL_ 758 REQUEST_TAKEOVER 0 "No request" 1 "Non-critical request" 2 "Critical request" 3 "Invalid"; +VAL_ 758 BLIND_SENSOR 0 "False" 1 "True"; +VAL_ 758 REQ_VISUAL_COLL_ALERT_ARC 0 "no visual alert request" 1 "visual alert request"; +VAL_ 758 REQ_AUDIO_COLL_ALERT_ARC 0 "no audio alert request" 1 "audio alert request"; +VAL_ 758 REQ_HAPTIC_COLL_ALERT_ARC 0 "no haptic alert request" 1 "haptic alert request"; +VAL_ 758 ARC_STATUS 0 "unavailable" 1 "not used" 2 "not used" 3 "initialization" 4 "not used" 5 "not used" 6 "inhibited" 7 "not used" 8 "not used" 9 "not used" 10 "waiting" 11 "not used" 12 "active" 13 "not used" 14 "not used" 15 "fault"; +VAL_ 758 AUTO_BRAKING_IN_PROGRESS 0 "no braking in progress" 1 "braking in progress"; +VAL_ 758 AEB_ENABLED 0 "FALSE" 1 "TRUE"; +VAL_ 758 DRIVE_AWAY_REQUEST 0 "No drive away required" 1 "Drive away required"; +VAL_ 758 MDD_DECEL_CONTROL_REQ 0 "no UCF control request" 1 "UCF control request"; +VAL_ 758 AUTO_BRAKING_STATUS 0 "unavailable" 1 "initialization" 2 "not used" 3 "inhibited" 4 "not used" 5 "waiting" 6 "active" 7 "fault"; +VAL_ 758 TARGET_POSITION 0 "POS1" 1 "POS2" 2 "POS3" 3 "POS4" 4 "POS5" 5 "POS6" 6 "POS7" 7 "Invalid"; +VAL_ 760 ESP_STATUS_RELATED 0 "DISABLED" 1 "ENABLED"; +VAL_ 760 ESP_STATUS_RELATED_INV 0 "ENABLED" 1 "DISABLED"; +VAL_ 840 P134_Com_stEng 7 "RESERVED" 6 "DegradedGO" 5 "GO" 4 "Stopped" 3 "Running" 2 "Starting" 1 "Cut" 0 "Locked"; +VAL_ 909 VITESSE_VEHICULE_ROUES 65535 "Invalid"; +VAL_ 1010 LANE_DEPARTURE 0 "NOT_DEPARTED" 1 "DEPARTED_RIGHT" 2 "DEPARTED_LEFT"; +VAL_ 1010 STATUS 0 "UNAVAILABLE" 1 "UNSELECTED" 2 "SELECTED" 3 "AUTHORIZED" 4 "ACTIVE" 5 "DEFECT" 6 "COLLISION" 7 "RESERVED"; +VAL_ 1106 LONGITUDINAL_REGULATION_TYPE 0 "None" 1 "RVV: Vehicle Speed Governor" 2 "LVV: Vehicle Speed Limiter" 3 "ACC: Adaptive Cruise Control"; +VAL_ 1106 TURN_SIGNAL_STATUS 0 "Turn signal inactive" 1 "Right turn signal active" 2 "Left turn signal active" 3 "Both turn signals active"; +VAL_ 1106 FRONT_WIPER_STATUS 0 "Off" 1 "Front wiper confirmed" 2 "Low speed" 3 "High speed"; +VAL_ 1106 CHECKSUM_CONS_RVV_LVV2 0 "Most significant nibble of SPEED_SETPOINT is even AND least significant nibble of SPEED_SETPOINT is even" 1 "Most significant nibble of SPEED_SETPOINT is even AND least significant nibble of SPEED_SETPOINT is odd" 2 "Most significant nibble of SPEED_SETPOINT is odd AND least significant nibble of SPEED_SETPOINT is even" 3 "Most significant nibble of SPEED_SETPOINT is odd AND least significant nibble of SPEED_SETPOINT is odd"; +VAL_ 1106 BRAKE_ONLY_CMD_BSI 0 "No brake-only command requested by BSI" 1 "Brake-only command requested by BSI"; +VAL_ 1106 LVV_ACTIVATION_REQ 0 "No LVV activation request" 1 "LVV activation requested"; +VAL_ 1106 RVV_ACC_ACTIVATION_REQ 0 "No RVV/ACC activation request" 1 "RVV/ACC activation requested"; +VAL_ 1106 ARC_HABIT_SENSITIVITY 0 "Unused value" 1 "1" 2 "2" 3 "3" 4 "Unused value" 5 "Unused value" 6 "Unused value" 7 "Unused value"; +VAL_ 1106 ARC_HABIT_ACTIVATION_REQ 0 "ARC deactivation" 1 "ARC activation"; +VAL_ 1106 FRONT_WASH_STATUS 0 "Off" 1 "Wash"; +VAL_ 1106 FORCE_ACTIVATION_HAB_CMD 0 "Deactivation" 1 "Activation"; +VAL_ 1106 COCKPIT_GO_ACC_REQUEST 0 "VALUE_1" 1 "VALUE_2"; +VAL_ 1106 ACC_PROGRAM_MODE 0 "Comfort" 1 "Sport" 2 "Eco" 3 "Reserved"; +VAL_ 1173 EPS_TORQUE 127 "Invalid"; +VAL_ 1173 ETAT_DA_2004 3 "Reserved" 2 "Orange LED" 1 "Red LED" 0 "No Demand"; +VAL_ 1173 ETAT_DA_DYN 3 "Invalid" 2 "Adjustable Mode" 1 "Dynamic Mode" 0 "Normal Mode"; +VAL_ 1173 ETAT_DA_2010 3 "Reserved" 2 "Orange LED" 1 "Red LED" 0 "No Demand"; +VAL_ 1173 TRQ_LIMIT_STATE 1 "Saturation Effective" 0 "No Saturation"; +VAL_ 1173 STEERWHL_HOLD_BY_DRV 1 "Steer Activity From Drv Trq" 0 "No Steer Activity From Drv Trq"; +VAL_ 1173 EPS_STATE_LKA 4 "Defect" 3 "Active" 2 "Available" 1 "Authorised" 0 "Unauthorised"; +VAL_ 1173 AUTOR_ARRET_MOT_DA 1 "Permission to Stop" 0 "No Permission to Stop"; +VAL_ 1173 STEERING_REBOOT_REQUEST 1 "Request Reboot" 0 "No Reboot Required"; +VAL_ 1270 ARTIV_SENSOR_STATE 0 "Initialization" 1 "Inactive" 2 "Active" 3 "Reduced visibility" 4 "Simulation" 5 "Learning" 6 "Free" 7 "Fault"; +VAL_ 1270 TARGET_DETECTED 0 "initialization or no target detected" 1 "target detected"; +VAL_ 1270 ARTIV_TARGET_CHANGE_INFO 0 "VALUE_1" 1 "VALUE_2"; +VAL_ 1270 TRAFFIC_DIRECTION 0 "right" 1 "left" 2 "reserved" 3 "undetermined"; diff --git a/opendbc_repo/opendbc/dbc/rivian_park_assist_can.dbc b/opendbc_repo/opendbc/dbc/rivian_park_assist_can.dbc new file mode 100644 index 0000000000..b18f0a53d8 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/rivian_park_assist_can.dbc @@ -0,0 +1,55 @@ +VERSION "ParkAssistCAN" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: ACM CGM EPAS_P ESP IBM OCS RCM SAS TestTool VDM Vector_XXX + +BO_ 794 WheelButtons: 7 XXX + SG_ LeftButton_ScrollClick : 19|2@0+ (1,0) [0|3] "" XXX + SG_ LeftButton_RightClick : 21|2@0+ (1,0) [0|3] "" XXX + SG_ LeftButton_LeftClick : 22|2@1+ (1,0) [0|3] "" XXX + SG_ LeftButton_Scroll : 31|8@0+ (1,0) [0|255] "" XXX + SG_ RightButton_ScrollClick : 35|2@0+ (1,0) [0|3] "" XXX + SG_ RightButton_RightClick : 37|2@0+ (1,0) [0|3] "" XXX + SG_ RightButton_LeftClick : 38|2@1+ (1,0) [0|3] "" XXX + SG_ RightButton_Scroll : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 848 BSM_BlindSpotIndicator: 4 XXX + SG_ BSM_BlindSpotIndicator_Checksum : 0|8@1+ (1,0) [0|255] "" XXX + SG_ BSM_BlindSpotIndicator_Counter : 11|4@0+ (1,0) [0|15] "" XXX + SG_ BSM_BlindSpotIndicator_Left : 29|2@0+ (1,0) [0|3] "" XXX + SG_ BSM_BlindSpotIndicator_Right : 30|2@1+ (1,0) [0|3] "" XXX + +VAL_ 848 BSM_BlindSpotIndicator_Left 0 "OFF" 1 "OBJECT_DETECTED" 2 "ACTIVE_WARNING" ; +VAL_ 848 BSM_BlindSpotIndicator_Right 0 "OFF" 1 "OBJECT_DETECTED" 2 "ACTIVE_WARNING" ; \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/rivian_primary_actuator.dbc b/opendbc_repo/opendbc/dbc/rivian_primary_actuator.dbc new file mode 100644 index 0000000000..1e01124324 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/rivian_primary_actuator.dbc @@ -0,0 +1,1021 @@ +VERSION "PrimaryActuatorCAN" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: ACM CGM EPAS_P ESP IBM OCS RCM SAS TestTool VDM Vector_XXX + + +BO_ 64 SAS_Status: 8 SAS + SG_ SAS_Status_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ACM,EPAS_P,ESP,RCM,VDM + SG_ SAS_Status_Counter : 11|4@0+ (1,0) [0|15] "Unitless" ACM,EPAS_P,ESP,RCM,VDM + SG_ SAS_Status_AngleSafe : 23|15@0- (0.0009765625,0) [-14.5|14.5] "rad" ACM,EPAS_P,ESP,RCM,VDM + SG_ SAS_Status_Calibrated : 24|1@0+ (1,0) [0|1] "" ACM,EPAS_P,ESP,RCM,VDM + SG_ SAS_Status_AngleSpeedSafe : 39|14@0- (0.0078125,0) [-50|50] "rad/s" ACM,EPAS_P,ESP,RCM,VDM + SG_ SAS_StatusQ : 41|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,RCM,VDM + +BO_ 256 ACM_Status: 8 ACM + SG_ ACM_Status_Checksum : 7|8@0+ (1,0) [0|255] "-" EPAS_P,VDM + SG_ ACM_Status_Counter : 11|4@0+ (1,0) [0|15] "-" EPAS_P,VDM + SG_ ACM_Unkown1 : 18|1@0+ (1,0) [0|1] "" XXX + SG_ ACM_FeatureStatus : 23|3@0+ (1,0) [0|7] "" EPAS_P,VDM + SG_ ACM_FaultStatus : 26|3@0+ (1,0) [0|7] "" EPAS_P,VDM + SG_ ACM_FaultSupervisorState : 42|3@0+ (1,0) [0|7] "" ACMB + +BO_ 257 ACM_AebRequest: 8 ACM + SG_ ACM_AebRequest_Checksum : 7|8@0+ (1,0) [0|255] "" ESP,VDM + SG_ ACM_AebRequest_Counter : 11|4@0+ (1,0) [0|15] "" ESP,VDM + SG_ ACM_StopRequest : 17|1@0+ (1,0) [0|1] "" ESP,VDM + SG_ ACM_FailInfo : 19|2@0+ (1,0) [0|3] "" ESP,VDM + SG_ ACM_DbsLevel : 21|2@0+ (1,0) [0|3] "" ESP,VDM + SG_ ACM_OnOffStatus : 23|2@0+ (1,0) [0|3] "" ESP,VDM + SG_ ACM_DecelRequest : 27|12@0+ (0.004885,0) [0|15.998375] "m/s^2" ESP,VDM + SG_ ACM_WarnLevel : 44|2@0+ (1,0) [0|3] "" ESP,VDM + SG_ ACM_PrefillEnableRequest : 46|1@0+ (1,0) [0|1] "" ESP,VDM + SG_ ACM_EnableRequest : 47|1@0+ (1,0) [0|1] "" ESP,VDM + +BO_ 258 ESP_AebFb: 8 ESP + SG_ ESP_AebFeedback_Checksum : 7|8@0+ (1,0) [0|255] "" ACM + SG_ ESP_AebFeedback_Counter : 11|4@0+ (1,0) [0|15] "" ACM + SG_ iB_BrakePedalApplied_Q : 14|2@0+ (1,0) [0|3] "" ACM + SG_ iB_BrakePedalApplied : 15|1@0+ (1,0) [0|1] "" ACM + SG_ ESP_DecelFeedback : 23|12@0+ (0.004885,-16) [-16|3.99919] "m/s^2" ACM + SG_ ESP_AebActive : 24|1@0+ (1,0) [0|1] "" ACM + SG_ ESP_AebAvailable : 25|1@0+ (1,0) [0|1] "" ACM + SG_ ESP_DbsActive : 26|1@0+ (1,0) [0|1] "" ACM + SG_ ESP_PrefillActiveFeedback : 27|1@0+ (1,0) [0|1] "" ACM + SG_ ESP_PrefillAvailable : 32|1@0+ (1,0) [0|1] "" ACM + SG_ ESP_DbsAvailable : 33|1@0+ (1,0) [0|1] "" ACM + +BO_ 272 ACM_SteeringControl: 8 ACM + SG_ ACM_SteeringControl_Checksum : 7|8@0+ (1,0) [0|0] "" EPAS_P + SG_ ACM_SteeringControl_Counter : 11|4@0+ (1,0) [0|0] "" EPAS_P + SG_ ACM_EacEnabled : 13|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_HapticRequired : 15|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_SteeringAngleRequest : 23|15@0+ (0.1,-1638.4) [-1638.4|1638.3] "deg" EPAS_P + +BO_ 288 ACM_lkaHbaCmd: 8 ACM + SG_ ACM_lkaHbaCmd_Checksum : 7|8@0+ (1,0) [0|255] "" EPAS_P + SG_ ACM_lkaHbaCmd_Counter : 11|4@0+ (1,0) [0|15] "" EPAS_P + SG_ ACM_lkaElkRequest : 14|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_HapticRequest : 15|1@0+ (1,0) [0|1] "" EPAS_P + SG_ ACM_lkaStrToqReq : 23|11@0+ (1,-1024) [-1024|1024] "" EPAS_P + SG_ ACM_lkaSymbolState : 26|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_lkaToiFlt : 27|1@0+ (1,0) [0|1] "" EPAS_P + SG_ ACM_lkaActToi : 28|1@0+ (1,0) [0|1] "" EPAS_P + SG_ ACM_hbaSysState : 34|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_hbaLamp : 35|1@0+ (1,0) [0|1] "" EPAS_P + SG_ ACM_slifOnOffState : 37|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_elkOnOffState : 39|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_ldwLHWarning : 43|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_lkaLaneRecogState : 45|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_hbaOnOffState : 47|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_ldwlkaOnOffState : 48|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_ldwWarnTimingState : 51|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_lkaHandsoffSoundWarning : 53|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_lkaHandsoffDisplayWarning : 55|2@0+ (1,0) [0|3] "" EPAS_P + SG_ ACM_ldwRHWarning : 58|3@0+ (1,0) [0|7] "" EPAS_P + SG_ ACM_ldwWarnTypeState : 61|3@0+ (1,0) [0|7] "" EPAS_P + +BO_ 304 RCM_IMU_LatAccYaw: 8 RCM + SG_ RCM_LateralAccelYaw_Checksum : 7|8@0+ (1,0) [0|25] "" ACM,ESP,VDM + SG_ RCM_LateralAccelYaw_Counter : 11|4@0+ (1,0) [0|15] "" ACM,ESP,VDM + SG_ RCM_IMU_LatAcc_Stat_SensAvail : 12|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LatAcc_Stat_Fail : 13|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LatAcc_Stat_Init : 14|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LatAcc_Stat_Startup : 15|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_Yaw_Stat_SensAvail : 16|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_Yaw_Stat_Fail : 17|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_Yaw_Stat_Init : 18|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_Yaw_Stat_Startup : 19|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LatAcc : 39|16@0+ (0.004998293,-163.784065024) [-40.961|40.961] "m/s2" ACM,ESP,VDM + SG_ RCM_IMU_Yaw : 55|16@0+ (0.0125,-409.6) [-163.85|163.85] "deg/sec" ACM,ESP,VDM + +BO_ 309 RCM_IMU_HeaveRoll: 8 RCM + SG_ RCM_HeaveRoll_Checksum : 7|8@0+ (1,0) [0|25] "" VDM + SG_ RCM_HeaveRoll_Counter : 11|4@0+ (1,0) [0|15] "" VDM + SG_ RCM_IMU_Heave : 23|16@0+ (0.004998293,-163.784065024) [-34.32328|34.32328] "m/s2" VDM + SG_ RCM_IMU_Roll : 39|16@0+ (0.0125,-409.6) [-100.0125|100.0125] "deg/sec" VDM + SG_ RCM_IMU_Roll_Stat_SensAvail : 48|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Roll_Stat_Fail : 49|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Roll_Stat_Init : 50|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Roll_Stat_Startup : 51|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Heave_Stat_SensAvail : 52|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Heave_Stat_Fail : 53|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Heave_Stat_Init : 54|1@0+ (1,0) [0|1] "" VDM + SG_ RCM_IMU_Heave_Stat_Startup : 55|1@0+ (1,0) [0|1] "" VDM + +BO_ 320 RCM_IMU_LongAcc: 8 RCM + SG_ RCM_LongAcc_Checksum : 7|8@0+ (1,0) [0|25] "" ACM,ESP,VDM + SG_ RCM_LongAcc_Counter : 11|4@0+ (1,0) [0|15] "" ACM,ESP,VDM + SG_ RCM_IMU_LongAcc_Sig : 39|16@0+ (0.004998293,-163.784065024) [-40.961|40.961] "m/s2" ACM,ESP,VDM + SG_ RCM_IMU_LongAcc_Stat_SensAvail : 48|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LongAcc_Stat_Fail : 49|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LongAcc_Stat_Init : 50|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ RCM_IMU_LongAcc_Stat_Startup : 51|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + +BO_ 336 VDM_PropStatus: 7 VDM + SG_ VDM_PropStatus_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ACM,EPAS_P,ESP,RCM + SG_ VDM_PropStatus_Counter : 11|4@0+ (1,0) [0|15] "Unitless" ACM,EPAS_P,ESP,RCM + SG_ VDM_PropsnActv : 13|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,RCM + SG_ VDM_VehicleSpeedQ : 15|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,RCM + SG_ VDM_Prndl_Status : 19|4@0+ (1,0) [0|15] "" ACM,EPAS_P,ESP,RCM + SG_ VDM_Prndl_Request : 23|4@0+ (1,0) [0|15] "" ACM,EPAS_P,ESP,RCM + SG_ VDM_AcceleratorPedalPosition : 31|10@0+ (0.1,0) [0|102.3] "" ACM,EPAS_P,ESP,RCM + SG_ VDM_VehicleSpeed : 47|16@0+ (0.01,0) [0|400] "Kph" ACM,EPAS_P,ESP,RCM + +BO_ 338 VDM_OutputSignals: 8 VDM + SG_ VDM_OutputSigs_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_OutputSigs_Counter : 11|4@0+ (1,0) [0|15] "Unitless" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_LfcRequestType : 13|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_LfcActiveRequest : 14|1@0+ (1,0) [0|1] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_BrakeLightRequest : 15|1@0+ (1,0) [0|0] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_Lfc_BrakeTorqueRequest : 23|15@0+ (2,-65534) [-65534|0] "Nm" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_StcTorqueRequest : 39|11@0+ (0.0078125,-8) [-8|7.9921875] "Nm" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_StcFault : 43|1@0+ (1,0) [0|1] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_StcActiveRequest : 44|1@0+ (1,0) [0|1] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_EpbRequest : 49|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_ABSOffRoadModeRequest : 50|1@0+ (1,0) [0|1] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_HhcActiveRequest : 51|1@0+ (1,0) [0|1] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_EspPartialModeRequest : 53|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_SteeringModeRequest : 59|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,IBM,RCM + SG_ VDM_EpasPowerMode : 61|2@0+ (1,0) [0|3] "" ACM,EPAS_P,ESP,IBM,RCM + +BO_ 352 ACM_longitudinalRequest: 5 ACM + SG_ ACM_longitudinalRequest_Checksum : 7|8@0+ (1,0) [0|255] "-" VDM + SG_ ACM_longitudinalRequest_Counter : 11|4@0+ (1,0) [0|15] "-" VDM + SG_ ACM_AccelerationRequest : 23|11@0+ (0.01,-10.24) [-10.24|10.23] "m/s^2" VDM + SG_ ACM_PrndRequest : 27|4@0+ (1,0) [0|7] "" VDM + SG_ ACM_longInterfaceEnable : 37|2@0+ (1,0) [0|3] "" VDM + SG_ ACM_VehicleHoldRequest : 39|2@0+ (1,0) [0|3] "" VDM + +BO_ 354 VDM_AdasSts: 8 VDM + SG_ VDM_AdasStatus_Checksum : 7|8@0+ (1,0) [0|0] "" ACM + SG_ VDM_AdasStatus_Counter : 11|4@0+ (1,0) [0|0] "" ACM + SG_ VDM_AdasDecelLimit : 17|10@0+ (0.01,0) [0|-10.23] "m/s^2" ACM + SG_ VDM_AdasDriverAccelPriorityStatus : 19|2@0+ (1,0) [0|3] "" ACM + SG_ VDM_AdasFaultStatus : 23|4@0+ (1,0) [0|15] "" ACM + SG_ VDM_AdasAccelLimit : 33|10@0+ (0.01,0) [0|10.23] "m/s^2" ACM + SG_ VDM_AdasDriverModeStatus : 36|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AdasUnkown1 : 50|8@0+ (1,0) [0|255] "" XXX + SG_ VDM_AdasInterfaceStatus : 52|2@0+ (1,0) [0|3] "" ACM + SG_ VDM_AdasVehicleHoldStatus : 55|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_UserAdasRequest : 58|3@0+ (1,0) [0|7] "" ACM + +BO_ 357 VDM_AdasStalk: 4 VDM + SG_ VDM_AdasStalk_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ACM + SG_ VDM_AdasStalk_Counter : 11|4@0+ (1,0) [0|15] "Unitless" ACM + SG_ VDM_AdasStalkGapAdjust : 17|2@0+ (1,0) [0|3] "" ACM + SG_ VDM_AdasStalkAccCancelRes : 19|2@0+ (1,0) [0|3] "" ACM + SG_ VDM_AdasStalkAutonomyButton : 20|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AdasStalkAccEnableAdj : 23|3@0+ (1,0) [0|7] "" ACM + +BO_ 384 VDM_CGM_GW: 8 CGM + SG_ VDM_CGM_GW_Checksum : 7|8@0+ (1,0) [0|0] "" ESP,IBM + SG_ VDM_CGM_GW_Counter : 11|4@0+ (1,0) [0|0] "" ESP,IBM + SG_ CGM_TrailerPresent : 13|2@0+ (1,0) [0|3] "" ESP,IBM + SG_ CGM_DriverPresent : 15|2@0+ (1,0) [0|3] "" ESP,IBM + SG_ CGM_TimeSinceLastIgnitionOn : 23|16@0+ (1,0) [0|65535] "s" ESP,IBM + SG_ CGM_IgnSwtState : 35|4@0+ (1,0) [0|15] "" ESP,IBM + +BO_ 432 ESP_TorqueLimit_Front: 8 ESP + SG_ ESP_Torque_Front_Checksum : 7|8@0+ (1,0) [0|255] "" VDM + SG_ ESP_Torque_Front_Counter : 11|4@0+ (1,0) [0|15] "" VDM + SG_ ESP_Torque_Front_MinQ : 14|1@0+ (1,0) [0|1] "" VDM + SG_ ESP_Torque_Front_MaxQ : 15|1@0+ (1,0) [0|1] "" VDM + SG_ ESP_Torque_Front_Max : 23|16@0+ (0.5,-16384) [-16384|16383] "Nm" VDM + SG_ ESP_Torque_Front_Min : 39|16@0+ (0.5,-16384) [-16384|16383] "Nm" VDM + +BO_ 448 ESP_TorqueLimit_Rear: 8 ESP + SG_ ESP_Torque_Rear_Checksum : 7|8@0+ (1,0) [0|255] "" VDM + SG_ ESP_Torque_Rear_Counter : 11|4@0+ (1,0) [0|15] "" VDM + SG_ ESP_Torque_Rear_MinQ : 14|1@0+ (1,0) [0|1] "" VDM + SG_ ESP_Torque_Rear_MaxQ : 15|1@0+ (1,0) [0|1] "" VDM + SG_ ESP_Torque_Rear_Max : 23|16@0+ (0.5,-16384) [-16384|16383] "Nm" VDM + SG_ ESP_Torque_Rear_Min : 39|16@0+ (0.5,-16384) [-16384|16383] "Nm" VDM + +BO_ 516 RCM_ALR_Status: 8 RCM + SG_ RCM_ALR_Status_Signal : 0|2@1+ (1,0) [0|3] "" OCS + +BO_ 520 ESP_Status: 8 ESP + SG_ ESP_Status_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Status_Counter : 11|4@0+ (1,0) [0|15] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_BrakeLightActive_Q : 12|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_BrakeLightActive : 13|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Hhc_Active : 14|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Hhc_Available : 15|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Abs_OffRoad_Mode : 16|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Tsm_Active : 17|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_FaultLamp_EBD : 18|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_FaultLamp_VDC : 19|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_FaultLamp_ABS : 20|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Esp_Active : 21|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Abs_Active : 23|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Partial_Mode : 25|2@0+ (1,0) [0|3] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Dtc_Active : 26|1@0+ (1,0) [0|1] "Enum" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Vehicle_Speed_Q : 28|2@0+ (1,0) [0|3] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Lfc_Available : 30|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Hba_Active : 31|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_BrkTrq : 38|15@0+ (2,-65534) [-65534|0] "Nm" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Lfc_Active : 39|1@0+ (1,0) [0|1] "" ACM,CGM,EPAS_P,RCM,VDM + SG_ ESP_Vehicle_Speed : 55|16@0+ (0.01,0) [0|400] "kph" ACM,CGM,EPAS_P,RCM,VDM + +BO_ 521 ESP_WSpeed_Front: 8 ESP + SG_ ESP_WSpeed_Front_CRC : 7|8@0+ (1,0) [0|255] "" ACM,VDM + SG_ ESP_WSpeed_Front_Message_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ ESP_Wheel_Speed_Left_Front_Q : 13|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Speed_Right_Front_Q : 15|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Speed_Left_Front : 23|16@0+ (0.01,0) [0|400] "kph" ACM,VDM + SG_ ESP_Wheel_Speed_Right_Front : 39|16@0+ (0.01,0) [0|400] "kph" ACM,VDM + SG_ ESP_Wheel_Dir_Right_Front : 53|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Dir_Left_Front : 55|2@0+ (1,0) [0|3] "" ACM,VDM + +BO_ 522 ESP_WSpeed_Rear: 8 ESP + SG_ ESP_WSpeed_Rear_CRC : 7|8@0+ (1,0) [0|255] "" ACM,VDM + SG_ ESP_WSpeed_Rear_Message_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ ESP_Wheel_Speed_Left_Rear_Q : 13|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Speed_Right_Rear_Q : 15|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Speed_Left_Rear : 23|16@0+ (0.01,0) [0|400] "kph" ACM,VDM + SG_ ESP_Wheel_Speed_Right_Rear : 39|16@0+ (0.01,0) [0|400] "kph" ACM,VDM + SG_ ESP_Wheel_Dir_Right_Rear : 53|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Dir_Left_Rear : 55|2@0+ (1,0) [0|3] "" ACM,VDM + +BO_ 523 ESP_Wheel_Pulse_Veh: 8 ESP + SG_ ESP_Wheel_Pulse_CRC : 7|8@0+ (1,0) [0|255] "" ACM,VDM + SG_ ESP_Wheel_Pulse_Message_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ ESP_Wheel_Pulse_Left_Front : 23|8@0+ (1,0) [0|255] "Pulse" ACM,VDM + SG_ ESP_Wheel_Pulse_Left_Rear : 31|8@0+ (1,0) [0|255] "Pulse" ACM,VDM + SG_ ESP_Wheel_Pulse_Right_Front : 39|8@0+ (1,0) [0|255] "Pulse" ACM,VDM + SG_ ESP_Wheel_Pulse_Right_Rear : 47|8@0+ (1,0) [0|255] "Pulse" ACM,VDM + SG_ ESP_Wheel_Pulse_Right_Front_Q : 49|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Pulse_Right_Rear_Q : 51|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Pulse_Left_Rear_Q : 53|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_Wheel_Pulse_Left_Front_Q : 55|2@0+ (1,0) [0|3] "" ACM,VDM + +BO_ 524 ESP_Brake_Pressure: 8 ESP + SG_ ESP_BrakeP_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,RCM,VDM + SG_ ESP_BrakeP_Message_Counter : 11|4@0+ (1,0) [0|15] "" ACM,RCM,VDM + SG_ ESP_BrakePressure_RF_Q : 13|2@0+ (1,0) [0|3] "" ACM,RCM,VDM + SG_ ESP_BrakePressure_LF_Q : 15|2@0+ (1,0) [0|3] "" ACM,RCM,VDM + SG_ ESP_BrakePressure_LF : 23|8@0+ (1,0) [0|255] "bar" ACM,RCM,VDM + SG_ ESP_BrakePressure_LR : 31|8@0+ (1,0) [0|255] "bar" ACM,RCM,VDM + SG_ ESP_BrakePressure_RF : 39|8@0+ (1,0) [0|255] "bar" ACM,RCM,VDM + SG_ ESP_BrakePressure_RR : 47|8@0+ (1,0) [0|255] "bar" ACM,RCM,VDM + SG_ ESP_MasterCyl_Pressure : 55|10@0+ (0.25,0) [0|255] "bar" ACM,RCM,VDM + SG_ ESP_MasterCyl_Pressure_Q : 57|2@0+ (1,0) [0|3] "" ACM,RCM,VDM + SG_ ESP_BrakePressure_RR_Q : 59|2@0+ (1,0) [0|3] "" ACM,RCM,VDM + SG_ ESP_BrakePressure_LR_Q : 61|2@0+ (1,0) [0|3] "" ACM,RCM,VDM + +BO_ 529 VDM_Torque_Front: 8 VDM + SG_ VDM_Torque_Front_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ESP + SG_ VDM_Torque_Front_Counter : 11|4@0+ (1,0) [0|15] "Unitless" ESP + SG_ VDM_Torque_Front_Max : 23|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_Torque_Front_Min : 26|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_Torque_Front_MaxQ : 28|1@0+ (1,0) [0|1] "" ESP + SG_ VDM_OutputTorqueFront : 47|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_DriverIntendedTorqueFront : 50|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_OutputTorqueFrontQ : 51|1@0+ (1,0) [0|1] "" ESP + SG_ VDM_Torque_Front_MinQ : 52|1@0+ (1,0) [0|1] "" ESP + +BO_ 530 VDM_Torque_Rear: 8 VDM + SG_ VDM_Torque_Rear_Checksum : 7|8@0+ (1,0) [0|255] "Unitless" ESP + SG_ VDM_Torque_Rear_Counter : 11|4@0+ (1,0) [0|15] "Unitless" ESP + SG_ VDM_Torque_Rear_Max : 23|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_Torque_Rear_Min : 26|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_Torque_Rear_MaxQ : 28|1@0+ (1,0) [0|1] "" ESP + SG_ VDM_OutputTorqueRear : 47|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_DriverIntendedTorque_Rear : 50|11@0+ (1,-1023) [-1023|1024] "Nm" ESP + SG_ VDM_OutputTorqueRearQ : 51|1@0+ (1,0) [0|1] "" ESP + SG_ VDM_Torque_Rear_MinQ : 52|1@0+ (1,0) [0|1] "" ESP + +BO_ 565 IndicatorLights: 8 XXX + SG_ checksum : 0|8@1+ (1,0) [0|255] "" XXX + SG_ counter : 8|4@1+ (1,0) [0|15] "" XXX + SG_ RearDriverDoor : 24|2@0+ (1,0) [0|3] "" XXX + SG_ FrontPassengerDoor : 26|2@0+ (1,0) [0|3] "" XXX + SG_ DriverDoor : 28|2@0+ (1,0) [0|3] "" XXX + SG_ RearPassengerDoor : 38|2@0+ (1,0) [0|3] "" XXX + SG_ TurnLightLeft : 40|2@0+ (1,0) [0|3] "" XXX + SG_ IgnitionOn : 48|1@0+ (1,0) [0|1] "" XXX + SG_ TurnLightRight : 54|2@0+ (1,0) [0|3] "" XXX + +BO_ 592 VDM_EcasStatus: 8 VDM + SG_ VDM_EcasHeightFL : 7|8@0- (1,0) [-128|127] "mm" ACM + SG_ VDM_EcasHeightFR : 15|8@0- (1,0) [-128|127] "mm" ACM + SG_ VDM_EcasHeightRL : 23|8@0- (1,0) [-128|127] "mm" ACM + SG_ VDM_EcasHeightRR : 31|8@0- (1,0) [-128|127] "mm" ACM + +BO_ 789 BCM_Status: 8 VDM + SG_ BCM_AmbientAirTemperature : 15|8@0- (1,0) [-60|100] "degC" ESP + +BO_ 801 SCCM_WheelTouch: 7 SCCM + SG_ SCCM_WheelTouch_Checksum : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SCCM_WheelTouch_Counter : 11|4@0+ (1,0) [0|15] "" XXX + SG_ SCCM_WheelTouch_HandsOn : 21|1@0+ (1,0) [0|1] "" XXX + SG_ SETME_X52 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ SCCM_WheelTouch_CapacitiveValue : 32|12@1+ (1,0) [0|4095] "" XXX + +BO_ 811 ESP_EpbStatus: 8 ESP + SG_ ESP_EpbStatus_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,VDM + SG_ ESP_EpbStatus_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ ESP_EpbAvailable : 12|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ ESP_EpbServiceMode : 13|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ ESP_EpbWarningLamp : 15|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ ESP_EpbMessageDisplayRequest : 20|5@0+ (1,0) [0|30] "" ACM,VDM + SG_ ESP_EpbStatus : 23|3@0+ (1,0) [0|7] "" ACM,VDM + SG_ ESP_EpbClampForce : 31|16@0+ (1,0) [0|65534] "N" ACM,VDM + SG_ ESP_EpbFunctionLamp : 47|2@0+ (1,0) [0|3] "" ACM,VDM + +BO_ 826 RCM_Status: 8 RCM + SG_ RCM_IMU_LongAcc_Checksum : 7|8@0+ (1,0) [0|25] "" ACM,ESP,VDM + SG_ RCM_IMU_LongAcc_MSG_Counter : 11|4@0+ (1,0) [0|15] "" ACM,ESP,VDM + SG_ RCM_Status_DETECT_CRUSH : 21|3@0+ (1,0) [0|7] "" ACM,ESP,VDM + SG_ RCM_Status_IND_WARN_RCM : 23|2@0+ (1,0) [0|3] "" ACM,ESP,VDM + SG_ RCM_Status_IND_ACT_RCM_PASS : 25|2@0+ (1,0) [0|3] "" ACM,ESP,VDM + SG_ RCM_Status_IND_WARN_BELT_DRIVER : 27|2@0+ (1,0) [0|3] "" ACM,ESP,VDM + SG_ RCM_Status_IND_WARN_BELT_PASS : 31|2@0+ (1,0) [0|3] "" ACM,ESP,VDM + +BO_ 848 EPASP_Status: 4 EPAS_P + SG_ EPAS_Ecu1Status_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,VDM + SG_ EPAS_Ecu1Status_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ EPAS_Ecu1EacSts : 14|3@0+ (1,0) [0|7] "" ACM,VDM + SG_ EPAS_Ecu1PowerMode : 18|3@0+ (1,0) [0|7] "" ACM,VDM + SG_ EPAS_Ecu1Role : 20|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ EPAS_Ecu1State : 31|4@0+ (1,0) [0|15] "" ACM,VDM + +BO_ 864 EPASS_Status: 4 VDM + SG_ EPASS_Ecu2Status_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,EPAS_P + SG_ EPASS_Ecu2Status_Counter : 11|4@0+ (1,0) [0|15] "" ACM,EPAS_P + SG_ EPAS_Ecu2EacSts : 14|3@0+ (1,0) [0|7] "" ACM,EPAS_P + SG_ EPAS_Ecu2PowerMode : 18|3@0+ (1,0) [0|7] "" ACM,EPAS_P + SG_ EPASS_Ecu2Role : 20|2@0+ (1,0) [0|3] "" ACM,EPAS_P + SG_ EPASS_Ecu2State : 31|4@0+ (1,0) [0|15] "" ACM,EPAS_P + +BO_ 880 ACM_tsrCmd: 8 ACM + SG_ ACM_tsrCmd_Checksum : 7|8@0+ (1,0) [0|0] "" Vector_XXX + SG_ ACM_tsrCmd_Counter : 11|4@0+ (1,0) [0|15] "" Vector_XXX + SG_ ACM_tsrConInfoStaCon2 : 19|4@0+ (1,0) [0|15] "" Vector_XXX + SG_ ACM_tsrConInfoStaCon1 : 23|4@0+ (1,0) [0|15] "" Vector_XXX + SG_ ACM_tsrSpdDisClsMain : 31|8@0+ (1,0) [0|255] "" Vector_XXX + SG_ ACM_tsrSpdDisCluCon1 : 39|8@0+ (1,0) [0|255] "" Vector_XXX + SG_ ACM_tsrSpdDisCluCon2 : 47|8@0+ (1,0) [0|255] "" Vector_XXX + SG_ ACM_tsrSpdDisCluConM : 55|8@0+ (1,0) [0|255] "" Vector_XXX + SG_ ACM_tsrAddInfoDisplay : 59|2@0+ (1,0) [0|3] "" Vector_XXX + SG_ ACM_tsrOvrlapSignDis : 61|2@0+ (1,0) [0|3] "" Vector_XXX + SG_ ACM_tsrStatus : 63|2@0+ (1,0) [0|3] "" Vector_XXX + +BO_ 896 EPAS_SystemStatus: 5 EPAS_P + SG_ EPAS_SytemStatus_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,VDM + SG_ EPAS_SystemStatus_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ EPAS_SteeringReduced : 12|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ EPAS_SteeringFault : 13|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ EPAS_SteeringMode : 15|2@0+ (1,0) [0|3] "" ACM,VDM + SG_ EPAS_TorsionBarTorque : 23|12@0+ (0.01,-20.5) [-20.49|20.43] "" ACM,VDM + SG_ EPAS_StcFault : 32|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ EPAS_StcActive : 33|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ EPAS_StcUnavailable : 34|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ H_CAN_EPSS_ToiFlt : 35|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ H_CAN_EPSS_ToiActive : 36|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ H_CAN_EPS_ToiUnavailable : 37|1@0+ (1,0) [0|1] "" ACM,VDM + SG_ EPAS_HandsOnLevel : 39|2@0+ (1,0) [0|3] "" ACM,VDM + +BO_ 907 ESPiB1: 6 ESP + SG_ ESPiB1_Checksum : 7|8@0+ (1,0) [0|255] "" IBM + SG_ ESPiB1_AliveCounter : 11|4@0+ (1,0) [0|15] "" IBM + SG_ ESPiB1_IgnitionOn : 12|1@0+ (1,0) [0|1] "" IBM + SG_ ESPiB1_VehicleSpeed_Q : 15|2@0+ (1,0) [0|3] "" IBM + SG_ ESPiB1_VehicleSpeed : 23|8@0+ (0.4,0) [0|100] "m/s" IBM + +BO_ 908 ESPiB2: 4 ESP + SG_ ESPiB2_Checksum : 7|8@0+ (1,0) [0|255] "" IBM + SG_ ESPiB2_Alive_Counter : 11|4@0+ (1,0) [0|15] "" IBM + SG_ ESPiB2_qTargetExternal_Q : 15|2@0+ (1,0) [0|3] "" IBM + SG_ ESPiB2_qTargetExternal : 23|16@0+ (0.0078125,-252) [-252|252] "ml/s" IBM + +BO_ 909 ESPiB3: 7 ESP + SG_ ESPiB3_Checksum : 7|8@0+ (1,0) [0|255] "" IBM + SG_ ESPiB3_AliveCounter : 11|4@0+ (1,0) [0|15] "" IBM + SG_ ESPiB3_ABSActive : 12|1@0+ (1,0) [0|1] "" IBM + SG_ ESPiB3_ForceBlendingActive : 15|2@0+ (1,0) [0|3] "" IBM + SG_ ESPiB3_pMcVirtual : 23|10@0+ (0.25,0) [0|250] "bar" IBM + SG_ ESPiB3_pMcVirtual_Q : 29|2@0+ (1,0) [0|3] "" IBM + SG_ ESPiB3_pForceBlendingMC : 39|10@0+ (0.25,0) [0|250] "" IBM + SG_ ESPiB3_pMC1 : 43|10@0+ (0.3,-30) [-30|276.6] "bar" IBM + SG_ ESPiB3_pForceBlendingMC_Q : 45|2@0+ (1,0) [0|3] "" IBM + SG_ ESPiB3_pMC1_Q : 49|2@0+ (1,0) [0|3] "" IBM + +BO_ 910 iBESP1: 7 IBM + SG_ iBESP1_Checksum : 7|8@0+ (1,0) [0|255] "" ESP,VDM + SG_ iBESP1_AliveCounter : 11|4@0+ (1,0) [0|15] "" ESP,VDM + SG_ iBESP1_ExtReqPrio : 12|1@0+ (1,0) [0|1] "" ESP,VDM + SG_ iBESP1_ExtReqStatus : 15|3@0+ (1,0) [0|7] "" ESP,VDM + SG_ iBESP1_sOutputRodDriver : 23|12@0+ (0.015625,-5) [-5|47] "mm" ESP,VDM + SG_ iBESP1_sOutputRodDriver_Q : 27|2@0+ (1,0) [0|3] "" ESP,VDM + SG_ iBESP1_sOutputRodAct : 39|12@0+ (0.015625,-5) [-5|47] "mm" ESP,VDM + SG_ iBESP1_sOutputRodAct_Q : 43|2@0+ (1,0) [0|3] "" ESP,VDM + +BO_ 911 iBESP2: 6 IBM + SG_ iBESP2_Checksum : 7|8@0+ (1,0) [0|255] "" ACM,ESP,VDM + SG_ iBESP2_AliveCounter : 11|4@0+ (1,0) [0|15] "" ACM,ESP,VDM + SG_ iBESP2_CompatibilityIndex : 15|4@0+ (1,0) [0|15] "" ACM,ESP,VDM + SG_ iBESP2_pRunout_Q : 17|2@0+ (1,0) [0|3] "" ACM,ESP,VDM + SG_ iBESP2_iBDiagActive : 19|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ iBESP2_HbcRequest : 20|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ iBESP2_BrakePedalApplied_Q : 22|2@0+ (1,0) [0|3] "" ACM,ESP,VDM + SG_ iBESP2_BrakePedalApplied : 23|1@0+ (1,0) [0|1] "" ACM,ESP,VDM + SG_ iBESP2_pRunout : 31|8@0+ (1,0) [0|250] "bar" ACM,ESP,VDM + SG_ iBESP2_RprMode : 39|3@0+ (1,0) [0|7] "" ACM,ESP,VDM + +BO_ 912 EPAS_AdasStatus: 7 EPAS_P + SG_ EPAS_AdasStatus_Checksum : 7|8@0+ (1,0) [0|0] "" ACM,VDM + SG_ EPAS_AdasStatus_Counter : 11|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ EPAS_SteeringAngleSpeed : 23|14@0+ (0.1,-819) [-819|819.3] "deg/s" ACM,VDM + SG_ EPAS_EacStatus : 35|3@0+ (1,0) [0|7] "" ACM,VDM + SG_ EPAS_EacErrorCode : 39|4@0+ (1,0) [0|15] "" ACM,VDM + SG_ EPAS_InternalSas : 47|14@0+ (0.1,-819.2) [-819.2|819] "deg" ACM,VDM + SG_ EPAS_InternalSasQ : 49|1@0+ (1,0) [0|1] "" ACM,VDM + +BO_ 929 VDM_ModSw_DrvModPosSts_GW: 8 VDM + SG_ VDM_AchDriveModeRequestConfirm : 0|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AchDriveModeRequestPullRearw : 1|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AchDriveModeRequestPushDown : 2|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AchDriveModeRequestPushForwa : 3|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AchDriveModeRequestPushUp : 4|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AchDriveModeRequestRest : 5|1@0+ (1,0) [0|1] "" ACM + SG_ VDM_AchDriveMode4x4 : 20|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveMode : 23|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeAirSuspension : 28|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeAbs : 31|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeDrivability : 36|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeDamping : 39|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeRollControl : 44|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeEsp : 47|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeEpas : 52|3@0+ (1,0) [0|7] "" ACM + SG_ VDM_AchDriveModeTcs : 55|3@0+ (1,0) [0|7] "" ACM + +BO_ 1024 VehicleConfig: 7 CGM + SG_ VCM_VehicleType : 7|8@0+ (1,0) [0|255] "" ACM,ESP + SG_ VCM_HandOfDrive : 9|1@0+ (1,0) [0|1] "" ACM,ESP + SG_ VCM_BatterySize : 15|6@0+ (1,0) [0|63] "" ACM,ESP + SG_ VCM_Market : 23|8@0+ (1,0) [0|255] "" ACM,ESP + +BO_ 1265 Cluster: 6 XXX + SG_ Cluster_Unit : 7|1@0+ (1,0) [0|1] "" XXX + SG_ Cluster_VehicleSpeed : 15|8@0+ (1,0) [0|255] "mph" XXX + SG_ Cluster_Odometer : 23|32@0+ (0.1,0) [0|429496729.5] "" XXX + +BO_ 1280 RCM_Dtc: 8 RCM + SG_ RCM_Dtc_Checksum : 7|8@0+ (1,0) [0|25] "" VDM + SG_ RCM_Dtc_Counter : 11|4@0+ (1,0) [0|15] "" VDM + SG_ RCM_Dtc_HighByte : 23|8@0+ (1,0) [0|255] "" VDM + SG_ RCM_Dtc_MidByte : 31|8@0+ (1,0) [0|255] "" VDM + SG_ RCM_Dtc_LowByte : 39|8@0+ (1,0) [0|255] "" VDM + SG_ RCM_Dtc_Stat_Bit : 47|8@0+ (1,0) [0|255] "" VDM + SG_ RCM_Dtc_Number : 55|8@0+ (1,0) [0|255] "" VDM + +BO_ 1281 RCM_SerialIdentifier: 8 RCM + SG_ RCM_SerialNumber : 7|64@0+ (1,0) [0|1.84467440737096e+19] "" ESP,VDM + +BO_ 1328 Dummy_ACM_PrimaryActuatorCAN: 8 ACM + SG_ Dummy_ACM_PrimaryActuatorCAN : 7|8@0+ (1,0) [0|255] "" TestTool + +BO_ 1329 Dummy_CGM_PrimaryActuatorCAN: 1 CGM + SG_ Dummy_CGM_PrimaryActuatorCAN : 7|8@0+ (1,0) [0|255] "" TestTool + +BO_ 1330 Dummy_VDM_PrimaryActuatorCAN: 1 VDM + SG_ Dummy_VDM_PrimaryActuatorCAN : 7|8@0+ (1,0) [0|255] "" TestTool + +BO_ 1535 DoorStatus: 8 XXX + SG_ DoorOpen : 8|1@0+ (1,0) [0|1] "" XXX + +BO_ 1545 XCP_Cmd_VDM: 8 TestTool + +BO_ 1609 XCP_Resp_VDM: 8 VDM + +BO_ 1635 XCP_Cmd_EPAS_P: 8 TestTool + +BO_ 1636 XCP_Daq_EPAS_P: 8 EPAS_P + +BO_ 1637 XCP_Resp_EPAS_P: 8 EPAS_P + +BO_ 1640 OCS_PassSeatInfo: 8 OCS + SG_ OCS_Checksum : 0|8@1+ (1,0) [0|255] "-" RCM + SG_ OCS_Counter : 8|4@1+ (1,0) [0|15] "-" RCM + SG_ OCS_FrontPassClass : 16|4@1+ (1,0) [0|15] "" RCM + SG_ OCS_FrontPassClassValid : 20|1@1+ (1,0) [0|1] "" RCM + SG_ OCS_FrontPassFaultStatus : 21|2@1+ (1,0) [0|3] "" RCM + SG_ OCS_Reserved_1 : 23|1@1+ (1,0) [0|1] "" RCM + SG_ OCS_FrontPassSBRStatus : 24|4@1+ (1,0) [0|15] "" RCM + SG_ OCS_OperatingMode : 28|4@1+ (1,0) [0|15] "" RCM + SG_ OCS_Reserved_2 : 56|8@1+ (1,0) [0|255] "" RCM + +BO_ 1705 XCP_Daq_VDM: 8 VDM + +BO_ 1800 Diag_PhysReq_ACM_PrimaryActuator: 8 TestTool + +BO_ 1843 Diag_PhysReq_EPAS_P_PrimaryActua: 8 TestTool + +BO_ 1844 Diag_PhysReq_RCM_PrimaryActuator: 8 TestTool + +BO_ 1845 Diag_PhysReq_ESP_PrimaryActuator: 8 TestTool + +BO_ 1846 Diag_PhysReq_IBM_PrimaryActuator: 8 TestTool + +BO_ 1864 Diag_PhysResp_ACM_PrimaryActuato: 8 ACM + +BO_ 1907 Diag_PhysResp_EPAS_P_PrimaryActu: 8 EPAS_P + +BO_ 1908 Diag_PhysResp_RCM_PrimaryActuato: 8 RCM + +BO_ 1909 Diag_PhysResp_ESP_PrimaryActuato: 8 ESP + +BO_ 1910 Diag_PhysResp_IBM_PrimaryActuato: 8 IBM + +CM_ BO_ 64 "External steering angle sensor message."; +CM_ BO_ 801 "Not a reference message. Suspected ECU source is SCCM (Steering Column Control Module). Used by ACM to show hold wheel message on ACC engagement."; +CM_ SG_ 64 SAS_Status_Checksum "Actual steering wheel angle from the actual centre position of the steering wheel. The signal value is a signed value from zero (at centre steering wheel position) where a left turn (counterclockwise from steering wheel centre position) is represented by positive values and right turn (clockwise from steering wheel centre position) will have negative value. Checksum for steering wheel sensor data."; +CM_ SG_ 64 SAS_Status_Counter "Actual steering wheel angle from the actual centre position of the steering wheel. The signal value is a signed value from zero (at centre steering wheel position) where a left turn (counterclockwise from steering wheel centre position) is represented by positive values and right turn (clockwise from steering wheel centre position) will have negative value. Counter value for steering wheel sensor data."; +CM_ SG_ 64 SAS_Status_AngleSafe "Actual steering wheel angle from the actual centre position of the steering wheel. The signal value is a signed value from zero (at centre steering wheel position) where a left turn (counterclockwise from steering wheel centre position) is represented by positive values and right turn (clockwise from steering wheel centre position) will have negative value. Actual steering wheel angle from the actual centre position of the steering wheel. The signal value is a signed value from zero (at centre steering wheel"; +CM_ SG_ 64 SAS_Status_AngleSpeedSafe "Actual steering wheel angle from the actual centre position of the steering wheel. The signal value is a signed value from zero (at centre steering wheel position) where a left turn (counterclockwise from steering wheel centre position) is represented by positive values and right turn (clockwise from steering wheel centre position) will have negative value. Steering angle speed with steering wheel rotation direction. Turning the steering wheel left (counterclockwise) is represented by positive values and"; +CM_ SG_ 64 SAS_StatusQ "Actual steering wheel angle from the actual centre position of the steering wheel. The signal value is a signed value from zero (at centre steering wheel position) where a left turn (counterclockwise from steering wheel centre position) is represented by positive values and right turn (clockwise from steering wheel centre position) will have negative value. Qf for steering wheel sensor information"; +CM_ SG_ 256 ACM_Status_Checksum "Checksum signal for frame"; +CM_ SG_ 256 ACM_Status_Counter "Message counter signal for frame"; +CM_ SG_ 256 ACM_FeatureStatus "Current active ADAS feature"; +CM_ SG_ 256 ACM_FaultStatus "Reason for ACM fault"; +CM_ SG_ 257 ACM_AebRequest_Checksum "J1850"; +CM_ SG_ 257 ACM_AebRequest_Counter "Message Counter"; +CM_ SG_ 257 ACM_StopRequest "AEB Stop Request subsequent to AEB event"; +CM_ SG_ 257 ACM_FailInfo "AEB System Failure flags"; +CM_ SG_ 257 ACM_DbsLevel "Dynamic Braking Support (DBS) Level"; +CM_ SG_ 257 ACM_OnOffStatus "AEB System On/Off Status"; +CM_ SG_ 257 ACM_DecelRequest "AEB Target Deceleration command"; +CM_ SG_ 257 ACM_WarnLevel "AEB Warning Level"; +CM_ SG_ 257 ACM_PrefillEnableRequest "AEB Pre-fill Enable Request"; +CM_ SG_ 257 ACM_EnableRequest "AEB Enable Request"; +CM_ SG_ 258 ESP_AebFeedback_Checksum "J1850 Checksum"; +CM_ SG_ 258 ESP_AebFeedback_Counter "Message Counter"; +CM_ SG_ 258 iB_BrakePedalApplied_Q "Description: Qualifier for iBESP2_BrakePedalApplied signal"; +CM_ SG_ 258 iB_BrakePedalApplied "Description: Indicates whether the driver operates the brake pedal. Only active when the driver brakes, not when an external brake command implemented on iB + +Note: +1.Needed for HBB and HBC + +2. Monitoring for pMC (BSM)"; +CM_ SG_ 258 ESP_DecelFeedback "AEB Decel Feedback"; +CM_ SG_ 258 ESP_AebActive "AEB Active"; +CM_ SG_ 258 ESP_AebAvailable "AEB Available"; +CM_ SG_ 258 ESP_DbsActive "DBS Active"; +CM_ SG_ 258 ESP_PrefillActiveFeedback "Prefill Active Feedback"; +CM_ BO_ 272 "External steering angle control message for EPAS."; +CM_ SG_ 272 ACM_SteeringControl_Checksum "Checksum for DAS_steeringControl message. Refer to AUTOSAR E2E library Profile 1."; +CM_ SG_ 272 ACM_SteeringControl_Counter "Message counter for DAS_steeringControl message. It counts from 0 to 14 and rolls back to 0 after reaching14. Refer to AUTOSAR E2E library Profile 1."; +CM_ SG_ 272 ACM_EacEnabled "External angle control type for EPAS."; +CM_ SG_ 272 ACM_HapticRequired "External angle control type for EPAS."; +CM_ SG_ 272 ACM_SteeringAngleRequest "External angle control request for EPAS"; +CM_ SG_ 304 RCM_IMU_LatAcc "Inertial Measurement Unit Lateral Acceleration Primary"; +CM_ SG_ 320 RCM_IMU_LongAcc_Sig "Inertial Measurement Unit Longitudinal Accleration Primary"; +CM_ SG_ 338 VDM_EpbRequest "Apply and release request (EVIC, Shift to From Park/Stalk Switch Input)"; +CM_ SG_ 338 VDM_EpasPowerMode "EPAS power mode request."; +CM_ SG_ 352 ACM_longitudinalRequest_Checksum "Checksum signal for frame"; +CM_ SG_ 352 ACM_longitudinalRequest_Counter "Message counter signal for frame"; +CM_ SG_ 352 ACM_AccelerationRequest "Acceleration Request command from the ACM"; +CM_ SG_ 352 ACM_VehicleHoldRequired "Vehicle hold request flag"; +CM_ SG_ 352 ACM_PrndRequest "Gear state Request command from the ACM"; +CM_ SG_ 352 ACM_longInterfaceEnable "Acceleration Interface Enable Request from the ACM"; +CM_ SG_ 352 ACM_VehicleHoldRequest "Vehicle hold request from ACM"; +CM_ SG_ 354 VDM_AdasStatus_Checksum "VDM_AdasSts message j1850 checksum."; +CM_ SG_ 354 VDM_AdasStatus_Counter "VDM_AdasSts message counter."; +CM_ SG_ 354 VDM_AdasFaultStatus "Fault status of ADAS requests from VDM."; +CM_ SG_ 354 VDM_AdasDriverModeStatus "Signal which describes who is commanding the torque - Human or ADAS"; +CM_ SG_ 432 ESP_Torque_Front_MinQ "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 432 ESP_Torque_Front_MaxQ "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 432 ESP_Torque_Front_Max "ESP intervention, ESP tractive torque limit per axle."; +CM_ SG_ 432 ESP_Torque_Front_Min "ESP intervention, ESP regen torque limit per axle."; +CM_ SG_ 448 ESP_Torque_Rear_Checksum "J1850 Checksum"; +CM_ SG_ 448 ESP_Torque_Rear_Counter "Message Counter"; +CM_ SG_ 448 ESP_Torque_Rear_MinQ "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 448 ESP_Torque_Rear_MaxQ "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 448 ESP_Torque_Rear_Max "ESP intervention, ESP tractive torque limit per axle."; +CM_ SG_ 448 ESP_Torque_Rear_Min "ESP intervention, ESP regen torque limit per axle."; +CM_ SG_ 520 ESP_Status_Checksum "J1850 Checksum"; +CM_ SG_ 520 ESP_Status_Counter "Message Counter"; +CM_ SG_ 520 ESP_BrakeLightActive_Q "Indication of whether ESP_BrakeLightActive signal is valid"; +CM_ SG_ 520 ESP_BrakeLightActive "ESP Request to Activate Rear Brake Lamps"; +CM_ SG_ 520 ESP_Hhc_Active "HHC Active"; +CM_ SG_ 520 ESP_Hhc_Available "HHC Available"; +CM_ SG_ 520 ESP_Tsm_Active "Trailer Sway Mitigation Active Flag"; +CM_ SG_ 520 ESP_FaultLamp_EBD "ESP request to display ABS-TC Fault Lamp"; +CM_ SG_ 520 ESP_FaultLamp_VDC "ESP request to display ABS/ESP Fault Lamp"; +CM_ SG_ 520 ESP_FaultLamp_ABS "ESP request to display ABS Fault Lamp"; +CM_ SG_ 520 ESP_Esp_Active "Vehicle Stability Control is actively managing a stability event"; +CM_ SG_ 520 ESP_Abs_Active "Anti-Lock Brakes is actively working to prevent the brakes from locking up"; +CM_ SG_ 520 ESP_Partial_Mode "ESP current PATA mode"; +CM_ SG_ 520 ESP_Dtc_Active "Drag Torque Control is actively requesting torque."; +CM_ SG_ 520 ESP_Vehicle_Speed_Q "Indication of whether ESP_VehicleSpeed signal is valid"; +CM_ SG_ 520 ESP_Lfc_Available "LFC Available"; +CM_ SG_ 520 ESP_Hba_Active "HBA Active"; +CM_ SG_ 520 ESP_BrkTrq "ESP Brake Torque"; +CM_ SG_ 520 ESP_Lfc_Active "LFC Active"; +CM_ SG_ 520 ESP_Vehicle_Speed "ESP calculated vehicle speed. Average of front wheels on rear wheel drive vehicles. Average of all four wheels on dual motor vehicles."; +CM_ SG_ 521 ESP_WSpeed_Front_CRC "J1850 Checksum"; +CM_ SG_ 521 ESP_WSpeed_Front_Message_Counter "Message Counter"; +CM_ SG_ 521 ESP_Wheel_Speed_Left_Front_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 521 ESP_Wheel_Speed_Right_Front_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 521 ESP_Wheel_Speed_Left_Front "Wheel Speed Left Front"; +CM_ SG_ 521 ESP_Wheel_Speed_Right_Front "Wheel Speed Right Front"; +CM_ SG_ 521 ESP_Wheel_Dir_Right_Front "Wheel Rotation Direction Right Front"; +CM_ SG_ 521 ESP_Wheel_Dir_Left_Front "Wheel Rotation Direction Left Front"; +CM_ SG_ 522 ESP_WSpeed_Rear_CRC "J1850 Checksum"; +CM_ SG_ 522 ESP_WSpeed_Rear_Message_Counter "Message Counter"; +CM_ SG_ 522 ESP_Wheel_Speed_Left_Rear_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 522 ESP_Wheel_Speed_Right_Rear_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 522 ESP_Wheel_Speed_Left_Rear "Wheel Speed Left Rear"; +CM_ SG_ 522 ESP_Wheel_Speed_Right_Rear "Wheel Speed Right Rear"; +CM_ SG_ 522 ESP_Wheel_Dir_Right_Rear "Wheel Rotation Direction Right Rear"; +CM_ SG_ 522 ESP_Wheel_Dir_Left_Rear "Wheel Rotation Direction Left Rear"; +CM_ SG_ 523 ESP_Wheel_Pulse_CRC "J1850 Checksum"; +CM_ SG_ 523 ESP_Wheel_Pulse_Message_Counter "Message Counter"; +CM_ SG_ 523 ESP_Wheel_Pulse_Left_Front "Wheel Pulse Left Front"; +CM_ SG_ 523 ESP_Wheel_Pulse_Left_Rear "Wheel Pule Left Rear"; +CM_ SG_ 523 ESP_Wheel_Pulse_Right_Front "Wheel Pulse Right Front"; +CM_ SG_ 523 ESP_Wheel_Pulse_Right_Rear "Wheel Pulse Right Rear"; +CM_ SG_ 523 ESP_Wheel_Pulse_Right_Front_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 523 ESP_Wheel_Pulse_Right_Rear_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 523 ESP_Wheel_Pulse_Left_Rear_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 523 ESP_Wheel_Pulse_Left_Front_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 524 ESP_BrakeP_Checksum "J1850 Checksum"; +CM_ SG_ 524 ESP_BrakeP_Message_Counter "Message Counter"; +CM_ SG_ 524 ESP_BrakePressure_RF_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 524 ESP_BrakePressure_LF_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 524 ESP_BrakePressure_LF "Brake Pressure Left Front"; +CM_ SG_ 524 ESP_BrakePressure_LR "Brake Pressure Left Rear"; +CM_ SG_ 524 ESP_BrakePressure_RF "Brake Pressure Right Front"; +CM_ SG_ 524 ESP_BrakePressure_RR "Brake Pressure Right Rear"; +CM_ SG_ 524 ESP_MasterCyl_Pressure "Master Cylinder Brake Pressure"; +CM_ SG_ 524 ESP_MasterCyl_Pressure_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 524 ESP_BrakePressure_RR_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 524 ESP_BrakePressure_LR_Q "Indication of whether signal with corresponding name is valid"; +CM_ SG_ 529 VDM_OutputTorqueFront "Output torque which is currently provided by the electric machine"; +CM_ SG_ 529 VDM_DriverIntendedTorqueFront "Driver Requested Torque pre ESP limits being applied"; +CM_ SG_ 530 VDM_OutputTorqueRear "Output torque which is currently provided by the electric machine"; +CM_ SG_ 530 VDM_DriverIntendedTorque_Rear "Driver Requested Torque pre ESP limits being applied"; +CM_ SG_ 592 VDM_EcasHeightFL "Change in ride height, with zero referenced to normal/design ride height"; +CM_ SG_ 592 VDM_EcasHeightFR "Change in ride height, with zero referenced to normal/design ride height"; +CM_ SG_ 592 VDM_EcasHeightRL "Change in ride height, with zero referenced to normal/design ride height"; +CM_ SG_ 592 VDM_EcasHeightRR "Change in ride height, with zero referenced to normal/design ride height"; +CM_ SG_ 811 ESP_EpbStatus_Checksum "J1850 Checksum"; +CM_ SG_ 811 ESP_EpbStatus_Counter "Message Counter"; +CM_ SG_ 811 ESP_EpbAvailable "EPB Availability. Shows the availability of the EPB function."; +CM_ SG_ 811 ESP_EpbServiceMode "Indication whether EPB is in service mode."; +CM_ SG_ 811 ESP_EpbWarningLamp "Failure Driver Lamp indication for EPB."; +CM_ SG_ 811 ESP_EpbMessageDisplayRequest "EPB text message"; +CM_ SG_ 811 ESP_EpbStatus "Current EPB actuator state."; +CM_ SG_ 811 ESP_EpbClampForce "Currently applied clamp force of EPB."; +CM_ SG_ 811 ESP_EpbFunctionLamp "Driver Lamp indication for EPB (LED on button)."; +CM_ BO_ 848 "Forwarded Message from EPAS Primary to Secondary ECU via Public CAN."; +CM_ BO_ 864 "Forwarded Message from EPAS Secondary to Primary ECU via Public CAN ."; +CM_ BO_ 896 "EPAS status info."; +CM_ SG_ 896 EPAS_SytemStatus_Checksum "Checksum for EPAS_sysStatus message. Refer to AUTOSAR E2E library Profile 1."; +CM_ SG_ 896 EPAS_SystemStatus_Counter "Message counter for EPAS_sysStatus message. It counts from 0 to 14 and rolls back to 0 after reaching14. Refer to AUTOSAR E2E library Profile 1."; +CM_ SG_ 896 EPAS_SteeringReduced "Power steering is functional, but reduced."; +CM_ SG_ 896 EPAS_SteeringFault "Power steering is not-available."; +CM_ SG_ 896 EPAS_SteeringMode "ESP current PATA mode"; +CM_ BO_ 907 "Basic communication ESP iBooster"; +CM_ SG_ 907 ESPiB1_Checksum "J1850 Checksum"; +CM_ SG_ 907 ESPiB1_AliveCounter "Message Counter"; +CM_ SG_ 907 ESPiB1_IgnitionOn "Description: Indicates whether the key is turned or not in the car + +Note: Used in PostRun calculation in iBooster"; +CM_ SG_ 907 ESPiB1_VehicleSpeed_Q "Description: Qualifier of the signal : ESPiB1_VehicleSpeed_Q + +Note: Robert Bosch Standard qualifier"; +CM_ SG_ 907 ESPiB1_VehicleSpeed "Description: Averaged wheel speed (signal in m/s on CAN but monitored in km/h in dbc) + +Note: +for standstill detection in iBooster + +1. For HEV function in iBoosterhev + +2. For EBR +3. Logic for Pressure Reduction"; +CM_ SG_ 908 ESPiB2_Checksum "J1850 Checksum"; +CM_ SG_ 908 ESPiB2_Alive_Counter "Message Counter"; +CM_ SG_ 908 ESPiB2_qTargetExternal_Q "Description: Qualifier for the volume flow interface + +Note: Qualifier for the volume flow interface"; +CM_ SG_ 908 ESPiB2_qTargetExternal "Description: Target flow of the brake system to be applied by iBooster for EBR. + +Note: For EBR through iBooster, interface needs to be operated together with ESPiB_pTargetExternal."; +CM_ BO_ 909 "Extended communication ESP iBooster"; +CM_ SG_ 909 ESPiB3_Checksum "J1850 Checksum"; +CM_ SG_ 909 ESPiB3_AliveCounter "Message Counter"; +CM_ SG_ 909 ESPiB3_ABSActive "Description: Indicates that at least one wheel ABS is in control + +Note: +1. For ABS pressure limitation + +2. For HEV function"; +CM_ SG_ 909 ESPiB3_ForceBlendingActive "Description: Control state of force-blending interface + +Note: Used by PFC in iB"; +CM_ SG_ 909 ESPiB3_pMcVirtual "Description: Virtual master cylinder pressure determined in ESP from boost body position of iBooster. + +note: +1. to control the force-blending of recuperation in ESPhev. +2. For JumpIn/Gain Adjustment in iBooster"; +CM_ SG_ 909 ESPiB3_pMcVirtual_Q "Description: Qualifier for the ESPiB3_pMcVirtual_Q signal"; +CM_ SG_ 909 ESPiB3_pForceBlendingMC "Description : Master Cylinder pressure used by force blending function. Can differ from real master cylinder pressure, to avoid short peaks and disturbances which should not be compensated by force-blending + +Note: Used by PFC in iB"; +CM_ SG_ 909 ESPiB3_pMC1 "Description: Current pressure of the master cylinder pressure sensor in the ESP. Raw value without offset compensation. + + +Note: +1. For pressure reduction logic + +2. For HEV Function + +3. For EBR + +4. For runout definition"; +CM_ SG_ 909 ESPiB3_pForceBlendingMC_Q "Description: Qualifier for the ESPiB3_pForceBlendingMC"; +CM_ SG_ 909 ESPiB3_pMC1_Q "Description: Qualifier for ESPiB3_pMC1_Q signal"; +CM_ SG_ 910 iBESP1_ExtReqPrio "To determine driver's braking request for EBR together with sPushRod, eg for CDD"; +CM_ SG_ 910 iBESP1_ExtReqStatus "Status of external brake request (EBR) function"; +CM_ SG_ 910 iBESP1_sOutputRodDriver "Information of driver brake request. +Calculation of: +- target value for output rod in iBooster +Also shows pedal travel with active pressure increase via iBooster"; +CM_ SG_ 910 iBESP1_sOutputRodDriver_Q "Information about the signal quality of sOutputRodDriver"; +CM_ SG_ 910 iBESP1_sOutputRodAct "Current value for output rod in iBooster indicates the shifted volume in master cylinder. Gives information, if the compensation port is closed."; +CM_ SG_ 910 iBESP1_sOutputRodAct_Q "Information about the signal quality of sOutputRodAct"; +CM_ SG_ 911 iBESP2_CompatibilityIndex "Description: iB is sending an static number which which must fit to the same number monitored in ESP to ensure the compatibility of the two ECU."; +CM_ SG_ 911 iBESP2_pRunout_Q "Description: Qualifier for the iBESP2_pRunout signal"; +CM_ SG_ 911 iBESP2_iBDiagActive "iB is in extended Diag Session (iB_ActiveMode = Diagnosis)"; +CM_ SG_ 911 iBESP2_HbcRequest "request HBC if amplification of iB is not possible"; +CM_ SG_ 911 iBESP2_BrakePedalApplied_Q "Description: Qualifier for iBESP2_BrakePedalApplied signal"; +CM_ SG_ 911 iBESP2_BrakePedalApplied "Description: Indicates whether the driver operates the brake pedal. Only active when the driver brakes, not when an external brake command implemented on iB + +Note: +1.Needed for HBB and HBC + +2. Monitoring for pMC (BSM)"; +CM_ SG_ 911 iBESP2_pRunout "Description: In driver braking: maximum achievable master cylinder pressure with boost (runout.) +With an active pressure increase: maximum achievable brake master cylinder pressure. + +Note: +1. Required for HBB + +2. For LDM demand on iB (EBR)"; +CM_ SG_ 912 EPAS_EacStatus "Status of the EAC function of EPAS, to indicate what mode is active."; +CM_ SG_ 912 EPAS_EacErrorCode "EPAS external angle control error code."; +CM_ SG_ 912 EPAS_InternalSas "Steering wheel angle measured by EPAS"; +CM_ SG_ 912 EPAS_InternalSasQ "Steering angle sensor validity status"; +CM_ SG_ 1640 OCS_Checksum "Checksum signal for frame"; +VAL_ 64 SAS_Status_Calibrated 0 "SAS_Status_Calibrated_Not_Calibrated" 1 "SAS_Status_Calibrated_Calibrated"; +VAL_ 64 SAS_StatusQ 0 "SAS_Status_UndefinedDataACCur" 1 "SAS_Status_TmpUnDefinedData" 2 "SAS_Status_DataACCurrentNotWithinSpecification" 3 "SAS_Status_ACCurrentData"; +VAL_ 256 ACM_FeatureStatus 0 "ACM_FeatureStatus_Standby" 1 "ACM_FeatureStatus_Acc" 2 "ACM_FeatureStatus_Hwp" 3 "ACM_FeatureStatus_Uf" 4 "ACM_FeatureStatus_Faulted"; +VAL_ 256 ACM_FaultStatus 0 "ACM_FaultStatus_NoFault" 1 "ACM_FaultStatus_Faulted" 7 "ACM_FaultStatus_Sna"; +VAL_ 256 ACM_FaultSupervisorState 0 "Nominal_Operation" 1 "SS_1" 2 "SS_2" 3 "SS_3" 4 "SS_4" 5 "SS_5" 6 "SS_6" 7 "Reserved"; +VAL_ 257 ACM_StopRequest 0 "ACM_StopRequest_No_Request" 1 "ACM_StopRequest_Request"; +VAL_ 257 ACM_FailInfo 0 "ACM_FailInfo_Normal" 1 "ACM_FailInfo_Temp_Unav_By_Camera" 2 "ACM_FailInfo_Temp_Unav_By_Radar" 3 "ACM_FailInfo_Service_Required"; +VAL_ 257 ACM_DbsLevel 0 "ACM_DbsLevel_No_Activation" 1 "ACM_DbsLevel_Level_1" 2 "ACM_DbsLevel_Level_2" 3 "ACM_DbsLevel_Level_3"; +VAL_ 257 ACM_OnOffStatus 0 "ACM_OnOffStatus_Off" 1 "ACM_OnOffStatus_On_Fcw" 2 "ACM_OnOffStatus_On_Aeb" 3 "ACM_OnOffStatus_Invalid"; +VAL_ 257 ACM_WarnLevel 0 "ACM_WarnLevel_No_Warning" 1 "ACM_WarnLevel_Warning_Level_1" 2 "ACM_WarnLevel_Warning_Level_2" 3 "ACM_WarnLevel_Warning_Level_3"; +VAL_ 257 ACM_PrefillEnableRequest 0 "ACM_PrefillEnableRequest_Disable" 1 "ACM_PrefillEnableRequest_Enable"; +VAL_ 257 ACM_EnableRequest 0 "ACM_EnableRequest_Disable" 1 "ACM_EnableRequest_Enable"; +VAL_ 258 iB_BrakePedalApplied_Q 0 "iB_BrakePedalApplied_Q_No_Init_Or_Off" 1 "iB_BrakePedalApplied_Q_Applied_Normal" 2 "iB_BrakePedalApplied_Q_Applied_Faulty"; +VAL_ 258 iB_BrakePedalApplied 0 "iB_BrakePedalApplied_NotApplied" 1 "iB_BrakePedalApplied_Applied"; +VAL_ 258 ESP_AebActive 0 "ESP_AebActive_Inactive" 1 "ESP_AebActive_Active"; +VAL_ 258 ESP_AebAvailable 0 "ESP_AebAvailable_Not_Available" 1 "ESP_AebAvailable_Available"; +VAL_ 258 ESP_DbsActive 0 "ESP_DbsActive_Dbs_Inactive" 1 "ESP_DbsActive_Dbs_Active"; +VAL_ 258 ESP_PrefillActiveFeedback 0 "ESP_PrefillActiveFeedback_Inactive" 1 "ESP_PrefillActiveFeedback_Active"; +VAL_ 258 ESP_PrefillAvailable 0 "ESP_PrefillAvailible_NotAvailable" 1 "ESP_PrefillAvailible_Available"; +VAL_ 258 ESP_DbsAvailable 0 "ESP_DbsAvailable_NotAvailable" 1 "ESP_DbsAvailable_Available"; +VAL_ 272 ACM_EacEnabled 0 "ACM_EacEnable_None" 1 "ACM_EacEnable_Enabled" 2 "ACM_EacEnable_Reserved"; +VAL_ 272 ACM_HapticRequired 0 "ACM_HapticRequired_Inactive" 1 "ACM_HapticRequired_Active"; +VAL_ 288 ACM_HapticRequest 0 "ACM_HapticRequest_No_Request" 1 "ACM_HapticRequest_Haptic_Request"; +VAL_ 288 ACM_lkaSymbolState 0 "ACM_LKASYMBOLSTATE_OFF" 1 "ACM_LKASYMBOLSTATE_WHITE_ON_LDW_STANDBY" 2 "ACM_LKASYMBOLSTATE_GREEN_ON_LDW_LKA_STANDBY" 3 "ACM_LKASYMBOLSTATE_GREEN_BLNK_LDW_WARN_OR_LKA_CNTRL" 4 "ACM_LKASYMBOLSTATE_ORANGE_ON_FAIL" 5 "ACM_LKASYMBOLSTATE_ORANGE_BLINK_NOT_CALIBRATED" 6 "ACM_LKASYMBOLSTATE_ORANGE_ON_REGULATION" 7 "ACM_LKASYMBOLSTATE_WHITE_BLINK"; +VAL_ 288 ACM_lkaToiFlt 0 "ACM_LKATOIFLT_NO_FAULT" 1 "ACM_LKATOIFLT_FAULT_PRESENT"; +VAL_ 288 ACM_lkaActToi 0 "ACM_LKAACTTOI_DE_ACTIVATE_TOI" 1 "ACM_LKAACTTOI_ACTIVATE_TOI"; +VAL_ 288 ACM_hbaSysState 0 "ACM_HBASYSSTATE_DEFAULT_DISABLE" 1 "ACM_HBASYSSTATE_HBA_ENABLE_HIGH_BEAM_OFF" 2 "ACM_HBASYSSTATE_HBA_ENABLE_HIGH_BEAM_ON" 7 "ACM_HBASYSSTATE_SYSTEM_FAIL"; +VAL_ 288 ACM_ldwRHWarning 0 "ACM_LKARHWARNING_NO_WARNING" 1 "ACM_LKARHWARNING_HAPTIC_WARNING_AND_DISPLAY" 2 "ACM_LKARHWARNING_ACOUSTIC_WARNING_AND_DISPLAY" 3 "ACM_LKARHWARNING_HAPTIC_ACOUSTIC_AND_DISPLAY"; +VAL_ 288 ACM_ldwLHWarning 0 "ACM_LKALHWARNING_NO_WARNING" 1 "ACM_LKALHWARNING_HAPTIC_WARNING_AND_DISPLAY" 2 "ACM_LKALHWARNING_ACOUSTIC_WARNING_AND_DISPLAY" 3 "ACM_LKALHWARNING_HAPTIC_ACOUSTIC_AND_DISPLAY"; +VAL_ 288 ACM_lkaLaneRecogState 0 "ACM_LKALANERECOGSTATE_NOT_RECOGNITION" 1 "ACM_LKALANERECOGSTATE_LEFT_LANE_RECOGNITION" 2 "ACM_LKALANERECOGSTATE_RIGHT_LANE_RECOGNITION" 3 "ACM_LKALANERECOGSTATE_FULL_LANE_RECOGNITION"; +VAL_ 288 ACM_hbaLamp 0 "ACM_HBALAMP_HBA_INDICATOR_LAMP_OFF" 1 "ACM_HBALAMP_HBA_INDICATOR_LAMP_ON"; +VAL_ 288 ACM_lkaHandsoffSoundWarning 0 "ACM_LKAHANDSOFFSOUNDWARNING_NO_INFO" 1 "ACM_LKAHANDSOFFSOUNDWARNING_WARNING" 2 "ACM_LKAHANDSOFFSOUNDWARNING_RESERVED_2" 3 "ACM_LKAHANDSOFFSOUNDWARNING_RESERVED_3"; +VAL_ 288 ACM_lkaHandsoffDisplayWarning 0 "ACM_LKAHANDSOFFDISPLAYWARNING_NO_INFO" 1 "ACM_LKAHANDSOFFDISPLAYWARNING_WARNING" 2 "ACM_LKAHANDSOFFDISPLAYWARNING_RESERVED_2" 3 "ACM_LKAHANDSOFFDISPLAYWARNING_RESERVED_3"; +VAL_ 288 ACM_lkaElkRequest 0 "off" 1 "applying torque right for left departure" 2 "applying torque left for right departure"; +VAL_ 288 ACM_ldwlkaOnOffState 1 "LDW on" 2 "LKAS+LDW on" 3 "all off"; +VAL_ 288 ACM_elkOnOffState 1 "LKAS toggled on" 2 "LKAS toggled off"; +VAL_ 304 RCM_IMU_LatAcc_Stat_SensAvail 0 "RCM_IMU_LatAcc_Stat_SensAvail_InSpec" 1 "RCM_IMU_LatAcc_Stat_SensAvail_NotInSpec"; +VAL_ 304 RCM_IMU_LatAcc_Stat_Fail 0 "RCM_IMU_LatAcc_Stat_Fail_NotFailed" 1 "RCM_IMU_LatAcc_Stat_Fail_Failed"; +VAL_ 304 RCM_IMU_LatAcc_Stat_Init 0 "RCM_IMU_LatAcc_Stat_Init_Finished" 1 "RCM_IMU_LatAcc_Stat_Init_Running"; +VAL_ 304 RCM_IMU_LatAcc_Stat_Startup 0 "RCM_IMU_LatAcc_Stat_Startup_Finished" 1 "RCM_IMU_LatAcc_Stat_Startup_Running"; +VAL_ 304 RCM_IMU_Yaw_Stat_SensAvail 0 "RCM_IMU_Yaw_Stat_SensAvail_InSpec" 1 "RCM_IMU_Yaw_Stat_SensAvail_NotInSpec"; +VAL_ 304 RCM_IMU_Yaw_Stat_Fail 0 "RCM_IMU_Yaw_Stat_Fail_NotFailed" 1 "RCM_IMU_Yaw_Stat_Fail_Failed"; +VAL_ 304 RCM_IMU_Yaw_Stat_Init 0 "RCM_IMU_Yaw_Stat_Init_Finish" 1 "RCM_IMU_Yaw_Stat_Init_Running"; +VAL_ 304 RCM_IMU_Yaw_Stat_Startup 0 "RCM_IMU_Yaw_Stat_Startup_Finished" 1 "RCM_IMU_Yaw_Stat_Startup_Running"; +VAL_ 309 RCM_IMU_Roll_Stat_SensAvail 0 "RCM_IMU_Roll_Stat_SensAvail_InSpec" 1 "RCM_IMU_Roll_Stat_SensAvail_NotInSpec"; +VAL_ 309 RCM_IMU_Roll_Stat_Fail 0 "RCM_IMU_Roll_Stat_Fail_NotFailed" 1 "RCM_IMU_Roll_Stat_Fail_Failed"; +VAL_ 309 RCM_IMU_Roll_Stat_Init 0 "RCM_IMU_Roll_Stat_Init_Finished" 1 "RCM_IMU_Roll_Stat_Init_Running"; +VAL_ 309 RCM_IMU_Roll_Stat_Startup 0 "RCM_IMU_Roll_Stat_Startup_Finished" 1 "RCM_IMU_Roll_Stat_Startup_Running"; +VAL_ 309 RCM_IMU_Heave_Stat_SensAvail 0 "RCM_IMU_Heave_Stat_SensAvail_InSpec" 1 "RCM_IMU_Heave_Stat_SensAvail_NotInSpec"; +VAL_ 309 RCM_IMU_Heave_Stat_Fail 0 "RCM_IMU_Heave_Stat_Fail_NotFailed" 1 "RCM_IMU_Heave_Stat_Fail_Failed"; +VAL_ 309 RCM_IMU_Heave_Stat_Init 0 "RCM_IMU_Heave_Stat_Init_Finished" 1 "RCM_IMU_Heave_Stat_Init_Running"; +VAL_ 309 RCM_IMU_Heave_Stat_Startup 0 "RCM_IMU_Heave_Stat_Startup_Finished" 1 "RCM_IMU_Heave_Stat_Startup_Running"; +VAL_ 320 RCM_IMU_LongAcc_Stat_SensAvail 0 "RCM_IMU_LongAcc_Stat_SensAvail_InSpec" 1 "RCM_IMU_LongAcc_Stat_SensAvail_NotInSpec"; +VAL_ 320 RCM_IMU_LongAcc_Stat_Fail 0 "RCM_IMU_LongAcc_Stat_Fail_NotFailed" 1 "RCM_IMU_LongAcc_Stat_Fail_Failed"; +VAL_ 320 RCM_IMU_LongAcc_Stat_Init 0 "RCM_IMU_LongAcc_Stat_Init_Finished" 1 "RCM_IMU_LongAcc_Stat_Init_Running"; +VAL_ 320 RCM_IMU_LongAcc_Stat_Startup 0 "RCM_IMU_LongAcc_Stat_Startup_Finished" 1 "RCM_IMU_LongAcc_Stat_Startup_Running"; +VAL_ 336 VDM_PropsnActv 0 "VDM_PropsnActv_Not_Defined" 1 "VDM_PropsnActv_Active" 2 "VDM_PropsnActv_Inactive"; +VAL_ 336 VDM_VehicleSpeedQ 0 "VDM_VehSpdQ_Inactive" 1 "VDM_VehSpdQ_Active"; +VAL_ 336 VDM_Prndl_Status 0 "VDM_Prndl_Status_Not_Defined" 1 "VDM_Prndl_Status_Park" 2 "VDM_Prndl_Status_Reverse" 3 "VDM_Prndl_Status_Neutral" 4 "VDM_Prndl_Status_Drive"; +VAL_ 336 VDM_Prndl_Request 0 "VDM_Prndl_Request_No_Req" 1 "VDM_Prndl_Request_Park" 2 "VDM_Prndl_Request_Reverse" 3 "VDM_Prndl_Request_Neutral" 4 "VDM_Prndl_Request_Drive"; +VAL_ 338 VDM_LfcRequestType 0 "LFC_Request_Type_No_Request" 1 "LFC_Request_Type_Brake_Torque_Request_Fx" 2 "LFC_Request_Type_Standstill_Hold_Request_Ssm" 3 "LFC_Request_Type_Release_Ssm"; +VAL_ 338 VDM_LfcActiveRequest 0 "VDM_LfcActiveRequest_Inactive" 1 "VDM_LfcActiveRequest_Active"; +VAL_ 338 VDM_StcFault 0 "Stc_NoFault" 1 "Stc_Fault"; +VAL_ 338 VDM_StcActiveRequest 0 "Stc_NotActive" 1 "Stc_Active"; +VAL_ 338 VDM_EpbRequest 0 "VDM_EpbRequest_No_Request" 1 "VDM_EpbRequest_Release_Req" 2 "VDM_EpbRequest_Apply_Req" 3 "VDM_EpbRequest_Sna"; +VAL_ 338 VDM_ABSOffRoadModeRequest 0 "VDM_ABSOffRoadModeRequest_Inactive" 1 "VDM_ABSOffRoadModeRequest_Active"; +VAL_ 338 VDM_HhcActiveRequest 0 "VDM_HhcActiveRequest_Inactive" 1 "VDM_HhcActiveRequest_Active"; +VAL_ 338 VDM_EspPartialModeRequest 0 "VDM_EspPartialModeRequest_Normal" 1 "VDM_EspPartialModeRequest_Sport" 2 "VDM_EspPartialModeRequest_Esc_Off" 3 "VDM_EspPartialModeRequest_Reserved"; +VAL_ 338 VDM_SteeringModeRequest 0 "VDM_SteeringModeRequest_Default" 1 "VDM_SteeringModeRequest_Normal" 2 "VDM_SteeringModeRequest_Sport" 3 "VDM_SteeringModeRequest_Comfort"; +VAL_ 338 VDM_EpasPowerMode 0 "VDM_EpasPowerMode_Drive_Off" 1 "VDM_EpasPowerMode_Drive_On" 2 "VDM_EpasPowerMode_Shutdown"; +VAL_ 352 ACM_VehicleHoldRequired 0 "ACM_VEHICLEHOLDREQ_NO_REQUEST" 1 "ACM_VEHICLEHOLDREQ_VEHICLE_HOLD_REQUEST"; +VAL_ 352 ACM_PrndRequest 0 "ACM_PRNDREQ_NO_REQUEST" 1 "ACM_PRNDREQ_PARK" 2 "ACM_PRNDREQ_REVERSE" 3 "ACM_PRNDREQ_NEUTRAL" 4 "ACM_PRNDREQ_DRIVE"; +VAL_ 352 ACM_longInterfaceEnable 0 "ACM_LONGIFEN_INIT" 1 "ACM_LONGIFEN_LONGITUDINAL_INTERFACE_ENABLE" 2 "ACM_LONGIFEN_LONGITUDINAL_INTERFACE_DISABLE" 3 "ACM_LONGIFEN_SNA"; +VAL_ 352 ACM_VehicleHoldRequest 0 "NO_REQUEST" 1 "HOLD_REQUEST"; +VAL_ 354 VDM_AdasDriverAccelPriorityStatus 0 "VDM_AdasDriverAccelPriorityStatus_Driver" 1 "VDM_AdasDriverAccelPriorityStatus_Adas"; +VAL_ 354 VDM_AdasFaultStatus 0 "VDM_AdasFlaultStatus_No_Fault" 1 "VDM_AdasFaultStatus_Brk_Intv" 2 "VDM_AdasFlaultStatus_Cntr_Fault" 3 "VDM_AdasFlaultStatus_Imps_Cmd" 15 "VDM_AdasFlaultStatus_Sna"; +VAL_ 354 VDM_AdasDriverModeStatus 0 "VDM_AdasDriverModeStatus_Human" 1 "VDM_AdasDriverModeStatus_Adas" 2 "VDM_AdasDriverModeStatus_Reserved" 3 "VDM_AdasDriverModeStatus_Sna"; +VAL_ 354 VDM_AdasInterfaceStatus 0 "VDM_AdasInterfaceStatus_Unavailable" 1 "VDM_AdasInterfaceStatus_Available" 2 "VDM_AdasInterfaceStatus_Enabled" 3 "VDM_AdasInterfaceStatus_Faulted"; +VAL_ 354 VDM_AdasVehicleHoldStatus 0 "VDM_AdasVehicleHoldStatus_NotHold" 1 "VDM_AdasVehicleHoldStatus_Hold"; +VAL_ 357 VDM_AdasStalkGapAdjust 0 "VDM_AdasStalkGapAdjust_No_Required" 1 "VDM_AdasStalkGapAdjust_GapDecrement" 2 "VDM_AdasStalkGapAdjust_GapIncrement"; +VAL_ 357 VDM_AdasStalkAccCancelRes 0 "VDM_AdasStalkAccCancelRes_NoRequired" 1 "VDM_AdasStalkAccCancelRes_Cancel" 2 "VDM_AdasStalkAccCancelRes_Resume"; +VAL_ 357 VDM_AdasStalkAutonomyButton 0 "VDM_AdasStalkAutonomyButton_No_Required" 1 "VDM_AdasStalkAutonomyButton_Pressed"; +VAL_ 357 VDM_AdasStalkAccEnableAdj 0 "VDM_AdasStalkAccEnableAdj_No_Required" 1 "VDM_AdasStalkAccEnableAdj_UpDetent1" 2 "VDM_AdasStalkAccEnableAdj_UpDetent2" 3 "VDM_AdasStalkAccEnableAdj_DownDetent1" 4 "VDM_AdasStalkAccEnableAdj_DownDetent2"; +VAL_ 384 CGM_TrailerPresent 0 "CGM_TrailerPresent_Trailer_Not_Present" 1 "CGM_TrailerPresent_Trailer_Present" 3 "CGM_TrailerPresent_Invalid"; +VAL_ 384 CGM_DriverPresent 0 "CGM_DriverPresent_Driver_Not_Present" 1 "CGM_DriverPresent_Driver_Present" 3 "CGM_DriverPresent_Invalid"; +VAL_ 384 CGM_IgnSwtState 0 "IGNSWTSTATE_OFF" 1 "IGNSWTSTATE_STANDBY" 2 "IGNSWTSTATE_ACCESSORY" 3 "IGNSWTSTATE_RUN" 4 "IGNSWTSTATE_CRANK"; +VAL_ 432 ESP_Torque_Front_MinQ 0 "ESP_TorqueFront_MinQ_Invalid" 1 "ESP_TorqueFront_MinQ_Valid"; +VAL_ 432 ESP_Torque_Front_MaxQ 0 "ESP_TorqueFront_MaxQ_Invalid" 1 "ESP_TorqueFront_MaxQ_Valid"; +VAL_ 448 ESP_Torque_Rear_MinQ 0 "ESP_TorqueLimitRear_MinQ_Invalid" 1 "ESP_TorqueLimitRear_MinQ_Valid"; +VAL_ 448 ESP_Torque_Rear_MaxQ 0 "ESP_TorqueLimitRear_MaxQ_Invalid" 1 "ESP_TorqueLimitRear_MaxQ_Valid"; +VAL_ 516 RCM_ALR_Status_Signal 0 "ALR_Unknown" 1 "ALR_Not_Engaged" 2 "ALR_Engaged" 3 "ALR_Invalid"; +VAL_ 520 ESP_BrakeLightActive_Q 0 "ESP_BRAKELIGHTACTIVE_Q_INVALID" 1 "ESP_BRAKELIGHTACTIVE_Q_VALID"; +VAL_ 520 ESP_BrakeLightActive 0 "ESP_BRAKELIGHTACTIVE_INACTIVE" 1 "ESP_BRAKELIGHTACTIVE_ACTIVE"; +VAL_ 520 ESP_Hhc_Active 0 "ESP_HHCACTV_INACTIVE" 1 "ESP_HHCACTV_ACTIVE"; +VAL_ 520 ESP_Hhc_Available 0 "ESP_HHCAVL_NOT_INITIALIZED" 1 "ESP_HHCAVL_ACTIVE"; +VAL_ 520 ESP_Abs_OffRoad_Mode 0 "ABS_OFFROAD_NORMAL" 1 "ABS_OFFROAD_OFFROAD"; +VAL_ 520 ESP_Tsm_Active 0 "TSM_ACTIVE_INACTIVE" 1 "TSM_ACTIVE_ACTIVE"; +VAL_ 520 ESP_FaultLamp_EBD 0 "ESP_FAULTLAMP_EBD_OFF" 1 "ESP_FAULTLAMP_EBD_ON"; +VAL_ 520 ESP_FaultLamp_VDC 0 "ESP_FAULTLAMP_VDC_OFF" 1 "ESP_FAULTLAMP_VDC_ON"; +VAL_ 520 ESP_FaultLamp_ABS 0 "ESP_FAULTLAMP_ABS_OFF" 1 "ESP_FAULTLAMP_ABS_ON"; +VAL_ 520 ESP_Esp_Active 0 "ESP_ACTIVE_INACTIVE" 1 "ESP_ACTIVE_ACTIVE"; +VAL_ 520 ESP_Abs_Active 0 "ABS_ACTIVE_INACTIVE" 1 "ABS_ACTIVE_ACTIVE"; +VAL_ 520 ESP_Partial_Mode 0 "ESP_PATA_MODE_NORMAL" 1 "ESP_PATA_MODE_SPORT" 2 "ESP_PATA_MODE_ESC_OFF" 3 "ESP_PATA_MODE_RESERVED"; +VAL_ 520 ESP_Vehicle_Speed_Q 0 "ESP_VEHICLE_SPEED_Q_NOT_INITIALIZED" 1 "ESP_VEHICLE_SPEED_Q_NORMAL" 2 "ESP_VEHICLE_SPEED_Q_FAULT"; +VAL_ 520 ESP_Lfc_Available 0 "LFC_AVAILABLE_NOT_AVAILABLE" 1 "LFC_AVAILABLE_AVAILABLE"; +VAL_ 520 ESP_Hba_Active 0 "ESP_HBAACTV_INACTIVE" 1 "ESP_HBAACTV_ACTIVE"; +VAL_ 520 ESP_Lfc_Active 0 "LFC_ACTIVE_INACTIVE" 1 "LFC_ACTIVE_ACTIVE"; +VAL_ 521 ESP_Wheel_Speed_Left_Front_Q 0 "ESP_WHEEL_SPEED_LEFT_FRONT_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_SPEED_LEFT_FRONT_Q_NORMAL" 2 "ESP_WHEEL_SPEED_LEFT_FRONT_Q_FAULT"; +VAL_ 521 ESP_Wheel_Speed_Right_Front_Q 0 "ESP_WHEEL_SPEED_RIGHT_FRONT_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_SPEED_RIGHT_FRONT_Q_NORMAL" 2 "ESP_WHEEL_SPEED_RIGHT_FRONT_Q_FAULT"; +VAL_ 521 ESP_Wheel_Dir_Right_Front 0 "ESP_WHEEL_DIR_RIGHT_FRONT_FORWARDDIRECTION" 1 "ESP_WHEEL_DIR_RIGHT_FRONT_BACKWARDDIRECTION" 2 "ESP_WHEEL_DIR_RIGHT_FRONT_STANDSTILL" 3 "ESP_WHEEL_DIR_RIGHT_FRONT_NOTDEFINABLE"; +VAL_ 521 ESP_Wheel_Dir_Left_Front 0 "ESP_WHEEL_DIR_LEFT_FRONT_FORWARDDIRECTION" 1 "ESP_WHEEL_DIR_LEFT_FRONT_BACKWARDDIRECTION" 2 "ESP_WHEEL_DIR_LEFT_FRONT_STANDSTILL" 3 "ESP_WHEEL_DIR_LEFT_FRONT_NOTDEFINABLE"; +VAL_ 522 ESP_Wheel_Speed_Left_Rear_Q 0 "ESP_WHEEL_SPEED_LEFT_REAR_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_SPEED_LEFT_REAR_Q_NORMAL" 2 "ESP_WHEEL_SPEED_LEFT_REAR_Q_FAULT"; +VAL_ 522 ESP_Wheel_Speed_Right_Rear_Q 0 "ESP_WHEEL_SPEED_RIGHT_REAR_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_SPEED_RIGHT_REAR_Q_NORMAL" 2 "ESP_WHEEL_SPEED_RIGHT_REAR_Q_FAULT"; +VAL_ 522 ESP_Wheel_Dir_Right_Rear 0 "ESP_WHEEL_DIR_RIGHT_REAR_FORWARDDIRECTION" 1 "ESP_WHEEL_DIR_RIGHT_REAR_BACKWARDDIRECTION" 2 "ESP_WHEEL_DIR_RIGHT_REAR_STANDSTILL" 3 "ESP_WHEEL_DIR_RIGHT_REAR_NOTDEFINABLE"; +VAL_ 522 ESP_Wheel_Dir_Left_Rear 0 "ESP_WHEEL_DIR_LEFT_REAR_FORWARDDIRECTION" 1 "ESP_WHEEL_DIR_LEFT_REAR_BACKWARDDIRECTION" 2 "ESP_WHEEL_DIR_LEFT_REAR_STANDSTILL" 3 "ESP_WHEEL_DIR_LEFT_REAR_NOTDEFINABLE"; +VAL_ 523 ESP_Wheel_Pulse_Right_Front_Q 0 "ESP_WHEEL_PULSE_RIGHT_FRONT_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_PULSE_RIGHT_FRONT_Q_NORMAL" 2 "ESP_WHEEL_PULSE_RIGHT_FRONT_Q_FAULT"; +VAL_ 523 ESP_Wheel_Pulse_Right_Rear_Q 0 "ESP_WHEEL_PULSE_RIGHT_REAR_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_PULSE_RIGHT_REAR_Q_NORMAL" 2 "ESP_WHEEL_PULSE_RIGHT_REAR_Q_FAULT"; +VAL_ 523 ESP_Wheel_Pulse_Left_Rear_Q 0 "ESP_WHEEL_PULSE_LEFT_REAR_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_PULSE_LEFT_REAR_Q_NORMAL" 2 "ESP_WHEEL_PULSE_LEFT_REAR_Q_FAULT"; +VAL_ 523 ESP_Wheel_Pulse_Left_Front_Q 0 "ESP_WHEEL_PULSE_LEFT_FRONT_Q_NOT_INITIALIZED" 1 "ESP_WHEEL_PULSE_LEFT_FRONT_Q_NORMAL" 2 "ESP_WHEEL_PULSE_LEFT_FRONT_Q_FAULT"; +VAL_ 524 ESP_BrakePressure_RF_Q 0 "ESP_BRAKEPRESSURE_RF_Q_NOT_INITIALIZED" 1 "ESP_BRAKEPRESSURE_RF_Q_NORMAL" 2 "ESP_BRAKEPRESSURE_RF_Q_FAULT"; +VAL_ 524 ESP_BrakePressure_LF_Q 0 "ESP_BRAKEPRESSURE_LF_Q_NOT_INITIALIZED" 1 "ESP_BRAKEPRESSURE_LF_Q_NORMAL" 2 "ESP_BRAKEPRESSURE_LF_Q_FAULT"; +VAL_ 524 ESP_MasterCyl_Pressure_Q 0 "ESP_MASTERCYL_PRESSURE_Q_NOT_INITIALIZED" 1 "ESP_MASTERCYL_PRESSURE_Q_NORMAL" 2 "ESP_MASTERCYL_PRESSURE_Q_FAULT"; +VAL_ 524 ESP_BrakePressure_RR_Q 0 "ESP_BRAKEPRESSURE_RR_Q_NOT_INITIALIZED" 1 "ESP_BRAKEPRESSURE_RR_Q_NORMAL" 2 "ESP_BRAKEPRESSURE_RR_Q_FAULT"; +VAL_ 524 ESP_BrakePressure_LR_Q 0 "ESP_BRAKEPRESSURE_LR_Q_NOT_INITIALIZED" 1 "ESP_BRAKEPRESSURE_LR_Q_NORMAL" 2 "ESP_BRAKEPRESSURE_LR_Q_FAULT"; +VAL_ 529 VDM_Torque_Front_MaxQ 0 "VDM_Torque_Front_MaxQ_Invalid" 1 "VDM_Torque_Front_MaxQ_Valid"; +VAL_ 529 VDM_OutputTorqueFrontQ 0 "VDM_OutputTorqueFrontQ_Invalid" 1 "VDM_OutputTorqueFrontQ_Valid"; +VAL_ 529 VDM_Torque_Front_MinQ 0 "VDM_Torque_Front_MinQ_Invalid" 1 "VDM_Torque_FrontinQ_Valid"; +VAL_ 530 VDM_Torque_Rear_MaxQ 0 "VDM_Torque_Rear_MaxQ_Invalid" 1 "VDM_Torque_Rear_MaxQ_Valid"; +VAL_ 530 VDM_OutputTorqueRearQ 0 "VDM_OutputTorqueRearQ_Invalid" 1 "VDM_OutputTorqueRearQ_Valid"; +VAL_ 530 VDM_Torque_Rear_MinQ 0 "VDM_Torque_Rear_MinQ_Invalid" 1 "VDM_Torque_Rear_MinQ_Valid"; +VAL_ 565 RearDriverDoor 0 "SNA" 1 "Open" 2 "Closed" 3 "SNA"; +VAL_ 565 FrontPassengerDoor 0 "SNA" 1 "Open" 2 "Closed" 3 "SNA"; +VAL_ 565 DriverDoor 0 "SNA" 1 "Open" 2 "Closed" 3 "SNA"; +VAL_ 565 RearPassengerDoor 0 "SNA" 1 "Open" 2 "Closed" 3 "SNA"; +VAL_ 811 ESP_EpbAvailable 0 "ESP_EpbAvailable_Not_Available" 1 "ESP_EpbAvailable_Available"; +VAL_ 811 ESP_EpbServiceMode 0 "ESP_EpbServiceMode_Not_Active" 1 "ESP_EpbServiceMode_Active"; +VAL_ 811 ESP_EpbWarningLamp 0 "ESP_EpbWarningLamp_Off" 1 "ESP_EpbWarningLamp_Continous" 2 "ESP_EpbWarningLamp_Blink" 3 "ESP_EpbWarningLamp_Sna"; +VAL_ 811 ESP_EpbStatus 0 "ESP_EpbStatus_Released" 1 "ESP_EpbStatus_Applied" 2 "ESP_EpbStatus_Releasing" 3 "ESP_EpbStatus_Applying" 4 "ESP_EpbStatus_Dynamic_Control" 5 "ESP_EpbStatus_Unknown" 7 "ESP_EpbStatus_Sna"; +VAL_ 811 ESP_EpbFunctionLamp 0 "ESP_EpbFunction_Lamp_Off" 1 "ESP_EpbFunctionLamp_Continous" 2 "ESP_EpbFunctionLamp_Blink" 3 "ESP_EpbFunctionLamp_Sna"; +VAL_ 826 RCM_Status_DETECT_CRUSH 0 "DETECT_CRUSH_Normal_Condition" 1 "DETECT_CRUSH_Collision_Detection"; +VAL_ 826 RCM_Status_IND_WARN_RCM 0 "IND_WARN_RCM_Off" 1 "IND_WARN_RCM_Lighting"; +VAL_ 826 RCM_Status_IND_ACT_RCM_PASS 0 "IWBP_On_Ind_onOFF_Ind_on" 1 "IWBP_On_Ind_offOFF_Ind_on" 2 "IWBP_On_Ind_onOFF_Ind_off" 3 "IWBP_On_Ind_offOFF_Ind_off"; +VAL_ 826 RCM_Status_IND_WARN_BELT_DRIVER 0 "IWBP_Equipped" 1 "IWBP_Not_Equipped" 2 "IWBP_Undetermined" 3 "IWBP_SW_Failure"; +VAL_ 826 RCM_Status_IND_WARN_BELT_PASS 0 "IWBP_Equipped" 1 "IWBP_Not_Equipped" 2 "IWBP_Undetermined" 3 "IWBP_SW_Failure"; +VAL_ 848 EPAS_Ecu1EacSts 0 "EPAS_Ecu1EacSts_Eac_Inhibited" 1 "EPAS_Ecu1EacSts_Eac_Available" 2 "EPAS_Ecu1EacSts_Eac_Active" 3 "EPAS_Ecu1EacSts_Eac_Fault" 7 "EPAS_Ecu1EacSts_Sna"; +VAL_ 848 EPAS_Ecu1PowerMode 0 "EPASP_powerMode_Drive_Off" 1 "EPASP_powerMode_Drive_On" 2 "EPASP_powerMode_Shutdown" 3 "EPASP_powerMode_Sna"; +VAL_ 848 EPAS_Ecu1Role 0 "EPASP_ROLE_MASTER" 1 "EPASP_ROLE_SLAVE" 2 "EPASP_ROLE_RESERVED"; +VAL_ 848 EPAS_Ecu1State 0 "EPAS_Ecu1State_Initialisation_Arbitration" 1 "EPAS_Ecu1State_Reserved" 2 "EPAS_Ecu1State_Reserved1" 3 "EPAS_Ecu1State_Initialisation_Complete" 4 "EPAS_Ecu1State_Passive" 5 "EPAS_Ecu1State_Passive_Faulted" 6 "EPAS_Ecu1State_Assist_Active" 7 "EPAS_Ecu1State_Assist_Standby" 8 "EPAS_Ecu1State_Eac_Active" 9 "EPAS_Ecu1State_Eac_Standby" 15 "EPAS_Ecu1State_Invalid"; +VAL_ 864 EPAS_Ecu2EacSts 0 "EPAS_Ecu2EacSts_Eac_Inhibited" 1 "EPAS_Ecu2EacSts_Eac_Available" 2 "EPAS_Ecu2EacSts_Eac_Active" 3 "EPAS_Ecu2EacSts_Eac_Fault" 7 "EPAS_Ecu2EacSts_Sna"; +VAL_ 864 EPAS_Ecu2PowerMode 0 "EPASS_powerMode_Drive_Off" 1 "EPASS_powerMode_Drive_On" 2 "EPASS_powerMode_Shutdown" 3 "EPASS_powerMode_Sna"; +VAL_ 864 EPASS_Ecu2Role 0 "EPASS_Ecu2Role_Master" 1 "EPASS_Ecu2Role_Slave" 2 "EPASS_Ecu2Role_Reserved"; +VAL_ 864 EPASS_Ecu2State 0 "EPASS_Ecu2State_Initialisation_Arbitration" 1 "EPASS_Ecu2State_Reserved" 2 "EPASS_Ecu2State_Reserved1" 3 "EPASS_Ecu2State_Initialisation_Complete" 4 "EPASS_Ecu2State_Passive" 5 "EPASS_Ecu2State_Passive_Faulted" 6 "EPASS_Ecu2State_Assist_Active" 7 "EPASS_Ecu2State_Assist_Standby" 8 "EPASS_Ecu2State_Eac_Active" 9 "EPASS_Ecu2State_Eac_Standby" 15 "EPASS_Ecu2State_Invalid"; +VAL_ 880 ACM_tsrConInfoStaCon2 0 "ACM_TSRCONINFOSTACON2_NONE_DEFAULT" 1 "ACM_TSRCONINFOSTACON2_RAIN" 2 "ACM_TSRCONINFOSTACON2_SNOW" 3 "ACM_TSRCONINFOSTACON2_SNOW_RAIN" 4 "ACM_TSRCONINFOSTACON2_TARILER" 5 "ACM_TSRCONINFOSTACON2_DISTANCE" 6 "ACM_TSRCONINFOSTACON2_TIME" 7 "ACM_TSRCONINFOSTACON2_FOG" 8 "ACM_TSRCONINFOSTACON2_RESERVED_8" 9 "ACM_TSRCONINFOSTACON2_RESERVED_9" 10 "ACM_TSRCONINFOSTACON2_RESERVED_10" 11 "ACM_TSRCONINFOSTACON2_RESERVED_11" 12 "ACM_TSRCONINFOSTACON2_RESERVED_12" 14 "ACM_TSRCONINFOSTACON2_GENERIC" 15 "ACM_TSRCONINFOSTACON2_RESERVED_15"; +VAL_ 880 ACM_tsrConInfoStaCon1 0 "ACM_TSRCONINFOSTACON1_NONE_DEFAULT" 1 "ACM_TSRCONINFOSTACON1_RAIN" 2 "ACM_TSRCONINFOSTACON1_SNOW" 3 "ACM_TSRCONINFOSTACON1_SNOW_RAIN" 4 "ACM_TSRCONINFOSTACON1_TARILER" 5 "ACM_TSRCONINFOSTACON1_DISTANCE" 6 "ACM_TSRCONINFOSTACON1_TIME" 7 "ACM_TSRCONINFOSTACON1_FOG" 8 "ACM_TSRCONINFOSTACON1_RESERVED_8" 9 "ACM_TSRCONINFOSTACON1_RESERVED_9" 10 "ACM_TSRCONINFOSTACON1_RESERVED_10" 11 "ACM_TSRCONINFOSTACON1_RESERVED_11" 12 "ACM_TSRCONINFOSTACON1_RESERVED_12" 14 "ACM_TSRCONINFOSTACON1_GENERIC" 15 "ACM_TSRCONINFOSTACON1_RESERVED_15"; +VAL_ 880 ACM_tsrSpdDisClsMain 0 "TSR_Speed_No_Recognition_Default" 253 "TSR_Speed_Unlimited_Speed" 254 "TSR_Speed_Reserved" 255 "TSR_Speed_Invalid"; +VAL_ 880 ACM_tsrSpdDisCluCon1 0 "ACM_TSRSPDDISCLUCON1_NO_RECOGNITION_DEFAULT" 1 "ACM_TSRSPDDISCLUCON1_A1_252_PH_1XHEX_KPHORMPH" 253 "ACM_TSRSPDDISCLUCON1_LHD_CONDITIONAL_NO_PASSING_ZONE" 254 "ACM_TSRSPDDISCLUCON1_RHD_CONDITIONAL_NO_PASSING_ZONE" 255 "ACM_TSRSPDDISCLUCON1_INVALID"; +VAL_ 880 ACM_tsrSpdDisCluCon2 0 "ACM_TSRSPDDISCLUCON2_NO_RECOGNITION_DEFAULT" 1 "ACM_TSRSPDDISCLUCON2_A1_252_PH_1XHEX_KPHORMPH" 253 "ACM_TSRSPDDISCLUCON2_LHD_CONDITIONAL_NO_PASSING_ZONE" 254 "ACM_TSRSPDDISCLUCON2_RHD_CONDITIONAL_NO_PASSING_ZONE" 255 "ACM_TSRSPDDISCLUCON2_INVALID"; +VAL_ 880 ACM_tsrSpdDisCluConM 0 "ACM_TSRSPDDISCLUCONM_NO_RECOGNITION_DEFAULT" 253 "ACM_TSRSPDDISCLUCONM_UNLIMITED_SPEED" 254 "ACM_TSRSPDDISCLUCONM_RESERVED" 255 "ACM_TSRSPDDISCLUCONM_INVALID"; +VAL_ 880 ACM_tsrAddInfoDisplay 0 "ACM_TSRADDINFODISPLAY_NONE_DISPLAY_DEFAULT" 1 "ACM_TSRADDINFODISPLAY_LHD_NO_PASSING_ZONE_DISPLAY" 2 "ACM_TSRADDINFODISPLAY_RHD_NO_PASSING_ZONE_DISPLAY" 3 "ACM_TSRADDINFODISPLAY_INVALID"; +VAL_ 880 ACM_tsrOvrlapSignDis 0 "ACM_TSROVRLAPSIGNDIS_NONE_DEFAULT" 1 "ACM_TSROVRLAPSIGNDIS_OVERLAP_SIGN" 2 "ACM_TSROVRLAPSIGNDIS_RESERVED"; +VAL_ 880 ACM_tsrStatus 0 "ACM_TSRSTATUS_TSR_INFORMATION_VALID_DEFAULT" 1 "ACM_TSRSTATUS_TSR_INFORMATION_INVALID_FAILURE" 2 "ACM_TSRSTATUS_TSR_INFORMATION_TEMPORARY_UNAVAILABLE"; +VAL_ 896 EPAS_SteeringReduced 0 "EPAS_EPAS_SteeringReduced_Normal_Assist" 1 "EPAS_EPAS_SteeringReduced_Reduced_Assist"; +VAL_ 896 EPAS_SteeringFault 0 "EPAS_SteeringFault_No_Fault" 1 "EPAS_SteeringFault_Fault"; +VAL_ 896 EPAS_SteeringMode 0 "EPASP_SteeringMode_Default" 1 "EPASP_SteeringMode_Normal" 2 "EPASP_SteeringMode_Sport" 3 "EPASP_SteeringMode_Comfort"; +VAL_ 896 EPAS_StcFault 0 "Stc_NoFault" 1 "Stc_Fault"; +VAL_ 896 EPAS_StcActive 0 "Stc_NotActive" 1 "Stc_Active"; +VAL_ 896 EPAS_StcUnavailable 0 "Stc_Available" 1 "Stc_Unavailable"; +VAL_ 896 H_CAN_EPSS_ToiFlt 0 "H_CAN_EPS_ToiFault_No_Fault" 1 "H_CAN_EPS_ToiFault_Fault"; +VAL_ 896 H_CAN_EPSS_ToiActive 0 "H_CAN_EPS_ToiActive_Deactivated" 1 "H_CAN_EPS_ToiActive_Activated"; +VAL_ 896 H_CAN_EPS_ToiUnavailable 0 "H_CAN_EPS_ToiUnavailable_Available" 1 "H_CAN_EPS_ToiUnavailable_Unavailable"; +VAL_ 896 EPAS_HandsOnLevel 0 "EPAS_HandsOnLevel_Level_0" 1 "EPAS_HandsOnLevel_Level_1" 2 "EPAS_HandsOnLevel_Level_2" 3 "EPAS_HandsOnLevel_Level_3"; +VAL_ 907 ESPiB1_IgnitionOn 0 "ESPIB1_IgnitionOn_Not_Initilized" 1 "ESPIB1_IgnitionOn_Normal"; +VAL_ 907 ESPiB1_VehicleSpeed_Q 0 "ESPiB1_VehicleSpeed_Q_VehicleSpeedQualifier_NotInit" 1 "ESPiB1_VehicleSpeed_Q_VehicleSpeedQualifier_Normal" 2 "ESPiB1_VehicleSpeed_Q_VehicleSpeedQualifier_Faulty"; +VAL_ 908 ESPiB2_qTargetExternal_Q 0 "ESPiB2_qTargetExternal_Q_QTarget_Off" 1 "ESPiB2_qTargetExternal_Q_QTarget_EBR" 2 "ESPiB2_qTargetExternal_Q_QTarget_EBRmaxPerformance"; +VAL_ 909 ESPiB3_ABSActive 0 "ESPIB3_ABSACTIVE_ABS_IS_INACTIVE" 1 "ESPIB3_ABSACTIVE_ABS_IS_ACTIVE"; +VAL_ 909 ESPiB3_ForceBlendingActive 0 "ESPIB3_FORCEBLENDINGACTIVE_PFC_INACTIVE" 1 "ESPIB3_FORCEBLENDINGACTIVE_PFC_HOLD" 2 "ESPIB3_FORCEBLENDINGACTIVE_PFC_ACTIVE"; +VAL_ 909 ESPiB3_pMcVirtual_Q 0 "ESPIB3_PMCVIRTUAL_Q_PMCVIRTUAL_NOTINITIALIZED" 1 "ESPIB3_PMCVIRTUAL_Q_PMCVIRTUAL_NORMAL" 2 "ESPIB3_PMCVIRTUAL_Q_PMCVIRTUAL_FAULTY"; +VAL_ 909 ESPiB3_pForceBlendingMC_Q 0 "ESPIB3_PFORCEBLENDINGMC_Q_PFORCEBLENDINGMC_NOTINITIALIZED" 1 "ESPIB3_PFORCEBLENDINGMC_Q_PFORCEBLENDINGMC_NORMAL" 2 "ESPIB3_PFORCEBLENDINGMC_Q_PFORCEBLENDINGMC_FAULTY"; +VAL_ 909 ESPiB3_pMC1_Q 0 "ESPIB3_PMC1_Q_MCPRESSUREQUALIFIER_NOTINIT" 1 "ESPIB3_PMC1_Q_MCPRESSUREQUALIFIER_NORMAL" 2 "ESPIB3_PMC1_Q_MCPRESSUREQUALIFIER_FAULTY"; +VAL_ 910 iBESP1_ExtReqStatus 0 "iBESP1_ExtReqStatus_NotInitialized" 1 "iBESP1_ExtReqStatus_EBR_NotAvailable" 2 "iBESP1_ExtReqStatus_EBR_Available"; +VAL_ 910 iBESP1_sOutputRodDriver_Q 0 "IBESP1_SOUTPUTRODDRIVER_Q_SOUTPUTRODDRIVER_NOTINITIALIZED" 1 "IBESP1_SOUTPUTRODDRIVER_Q_SOUTPUTRODDRIVER_NORMAL" 2 "IBESP1_SOUTPUTRODDRIVER_Q_SOUTPUTRODDRIVER_FAULTY"; +VAL_ 910 iBESP1_sOutputRodAct_Q 0 "IBESP1_SOUTPUTRODACT_Q_SOUTPUTRODACT_NOTINITIALIZED" 1 "IBESP1_SOUTPUTRODACT_Q_SOUTPUTRODACT_NORMAL" 2 "IBESP1_SOUTPUTRODACT_Q_SOUTPUTRODACT_FAULTY"; +VAL_ 911 iBESP2_pRunout_Q 0 "IBESP2_PRUNOUT_Q_P_RUNOUT_NOT_INITIALIZED" 1 "IBESP2_PRUNOUT_Q_P_RUNOUT_NORMAL" 2 "IBESP2_PRUNOUT_Q_P_RUNOUT_FAULTY"; +VAL_ 911 iBESP2_BrakePedalApplied_Q 0 "IBESP2_BRAKEPEDALAPPLIED_Q_BRAKE_PEDAL_APPLIED_NO_INIT_OR_OFF" 1 "IBESP2_BRAKEPEDALAPPLIED_Q_BRAKE_PEDAL_APPLIED_NORMAL" 2 "IBESP2_BRAKEPEDALAPPLIED_Q_BRAKE_PEDAL_APPLIED_FAULTY"; +VAL_ 911 iBESP2_BrakePedalApplied 0 "iBESP2_BrakePedalApplied_NotApplied" 1 "iBESP2_BrakePedalApplied_Applied"; +VAL_ 911 iBESP2_RprMode 0 "IBESP2_RPRMODE_RPR_PASSIVE" 1 "IBESP2_RPRMODE_RPR_PRELOAD" 2 "IBESP2_RPRMODE_RPR_HOLD" 3 "IBESP2_RPRMODE_RPR_SUCTION" 4 "IBESP2_RPRMODE_RPR_HOLDLOWPRESSURE" 5 "IBESP2_RPRMODE_RPR_ABORT"; +VAL_ 912 EPAS_EacStatus 0 "EPAS_EacStatus_Eac_Inhibited" 1 "EPAS_EacStatus_Eac_Available" 2 "EPAS_EacStatus_Eac_Active" 3 "EPAS_EacStatus_Eac_Standby" 4 "EPAS_EacStatus_Eac_Fault" 5 "EPAS_EacStatus_Sna"; +VAL_ 912 EPAS_EacErrorCode 0 "EPAS_No_Err" 1 "EPAS_High_Angle_Cmd_Err" 2 "EPAS_High_Actual_Angle_Err" 3 "EPAS_High_Actual_Angle_Rate_Err" 4 "EPAS_Feature_Fault_Err" 5 "EPAS_Feature_Status_Invalid_Err" 6 "EPAS_Feature_Angle_Thd_Err" 7 "EPAS_Angle_Control_Cntr_Err" 8 "EPAS_Angle_Control_Mia_Err" 9 "EPAS_Angle_Control_Crc_Err" 10 "EPAS_Vehspd_Corrln_Failr_Err" 11 "EPAS_Vehspd_Max_Thd_Err" 12 "EPAS_Hands_On_Detn_Err" 13 "EPAS_Ext_Angle_Plausibility_Err" 14 "EPAS_High_Delta_Angle_Err" 15 "EPAS_Max_Steady_State_Err"; +VAL_ 912 EPAS_InternalSasQ 0 "EPAS_INTERNALSASQF_VALID" 1 "EPAS_INTERNALSASQF_INVALID"; +VAL_ 929 VDM_AchDriveModeRequestConfirm 0 "VDM_AchDriveModeRequestConfirm_NoRequest" 1 "VDM_AchDriveModeRequestConfirm_Request"; +VAL_ 929 VDM_AchDriveModeRequestPullRearw 0 "VDM_AchDriveModeRequestPullRearward_NoRequired" 1 "VDM_AchDriveModeRequestPullRearward_Required"; +VAL_ 929 VDM_AchDriveModeRequestPushDown 0 "VDM_AchDriveModeRequestPushDown_NoRequired" 1 "VDM_AchDriveModeRequestPushDown_Required"; +VAL_ 929 VDM_AchDriveModeRequestPushForwa 0 "VDM_AchDriveModeRequestPushForward_NoRequired" 1 "VDM_AchDriveModeRequestPushForward_Required"; +VAL_ 929 VDM_AchDriveModeRequestPushUp 0 "VDM_AchDriveModeRequestPushUp_NoRequired" 1 "VDM_AchDriveModeRequestPushUp_Required"; +VAL_ 929 VDM_AchDriveModeRequestRest 0 "VDM_AchDriveModeRequestRest_NoRequired" 1 "VDM_AchDriveModeRequestRest_Required"; +VAL_ 929 VDM_AchDriveMode4x4 0 "VDM_AchDriveMode4x4_A4x4Auto" 1 "VDM_AchDriveMode4x4_P4x4Permenant" 6 "VDM_AchDriveMode4x4_I_Transition" 7 "VDM_AchDriveMode4x4_Fault"; +VAL_ 929 VDM_AchDriveMode 0 "VDM_AchDriveMode_Eco" 1 "VDM_AchDriveMode_OnRoadComford" 2 "VDM_AchDriveMode_OnRoadSport" 3 "VDM_AchDriveMode_OffRoad" 4 "VDM_AchDriveMode_OffRoadSport" 5 "VDM_AchDriveMode_Autonomy"; +VAL_ 929 VDM_AchDriveModeAirSuspension 0 "VDM_AchDriveModeAirSuspension_Kneel" 1 "VDM_AchDriveModeAirSuspension_Aero" 2 "VDM_AchDriveModeAirSuspension_Design" 3 "VDM_AchDriveModeAirSuspension_High" 4 "VDM_AchDriveModeAirSuspension_Max" 7 "VDM_AchDriveModeAirSuspension_Null"; +VAL_ 929 VDM_AchDriveModeAbs 0 "VDM_AchDriveModeAbs_OnRoad" 1 "VDM_AchDriveModeAbs_OffRoad" 6 "VDM_AchDriveModeAbs_InTransition" 7 "VDM_AchDriveModeAbs_Fault"; +VAL_ 929 VDM_AchDriveModeDrivability 0 "VDM_AchDriveModeDrivability_Eco" 1 "VDM_AchDriveModeDrivability_Sport" 2 "VDM_AchDriveModeDrivability_OffRoad" 6 "VDM_AchDriveModeDrivability_InTransition" 7 "VDM_AchDriveModeDrivability_Null"; +VAL_ 929 VDM_AchDriveModeDamping 0 "VDM_AchDriveModeDamping_Kneel" 1 "VDM_AchDriveModeDamping_Aero" 2 "VDM_AchDriveModeDamping_Design" 3 "VDM_AchDriveModeDamping_High" 4 "VDM_AchDriveModeDamping_AirSuspensionMax" 6 "VDM_AchDriveModeDamping_InTransition" 7 "VDM_AchDriveModeDamping_Fault"; +VAL_ 929 VDM_AchDriveModeRollControl 0 "VDM_AchDriveModeRollControl_Low" 1 "VDM_AchDriveModeRollControl_Middle" 2 "VDM_AchDriveModeRollControl_High" 6 "VDM_AchDriveModeRollControl_InTransition" 7 "VDM_AchDriveModeRollControl_Null"; +VAL_ 929 VDM_AchDriveModeEsp 0 "VDM_AchDriveModeEsp_EspOn" 1 "VDM_AchDriveModeEsp_EspReduced" 2 "VDM_AchDriveModeEsp_EspOff" 6 "VDM_AchDriveModeEsp_InTransition" 7 "VDM_AchDriveModeEsp_Null"; +VAL_ 929 VDM_AchDriveModeEpas 0 "VDM_AchDriveModeEpas_TcsStable" 1 "VDM_AchDriveModeEpas_TcsSportRoad" 2 "VDM_AchDriveModeEpas_TcsSportOffRoad" 3 "VDM_AchDriveModeEpas_TcsOff" 7 "VDM_AchDriveModeEpas_Null"; +VAL_ 929 VDM_AchDriveModeTcs 0 "VDM_AchDriveModeTcs_Stable" 1 "VDM_AchDriveModeTcs_SportRoad" 2 "VDM_AchDriveModeTcs_SportOffRoad" 3 "VDM_AchDriveModeTcs_Off" 7 "VDM_AchDriveModeTcs_Null"; +VAL_ 1024 VCM_VehicleType 0 "VCM_VehicleType_Sna" 1 "VCM_VehicleType_R1T" 2 "VCM_VehicleType_R1S" 3 "VCM_VehicleType_Reserved_AProj" 4 "VCM_VehicleType_Reserved_BProj" 5 "VCM_VehicleType_Reserved_CProj" 6 "VCM_VehicleType_Reserved_DProj" 7 "VCM_VehicleType_Reserved_EProj"; +VAL_ 1024 VCM_HandOfDrive 0 "VCM_HandOfDrive_Lhd" 1 "VCM_HandOfDrive_Rhd"; +VAL_ 1024 VCM_BatterySize 0 "VCM_BatterySize_Sna" 1 "VCM_BatterySize_A105kW" 2 "VCM_BatterySize_A130kW" 3 "VCM_BatterySize_A180kW" 4 "VCM_BatterySize_BxxxkW" 5 "VCM_BatterySize_CxxxkW" 6 "VCM_BatterySize_DxxxkW" 7 "VCM_BatterySize_ExxxkW"; +VAL_ 1024 VCM_Market 0 "VCM_Market_Sna" 1 "VCM_Market_RegionB" 2 "VCM_Market_RegionC" 3 "VCM_Market_RegionD" 4 "VCM_Market_RegionE" 5 "VCM_Market_RegionF" 6 "VCM_Market_RegionG" 7 "VCM_Market_RegionH"; +VAL_ 1265 Cluster_Unit 0 "KPH" 1 "MPH"; +VAL_ 1640 OCS_FrontPassClass 0 "OCS_FrontPassClass_Classification_Unknown" 1 "OCS_FrontPassClass_Reserved_1" 2 "OCS_FrontPassClass_One_YO_CRS" 3 "OCS_FrontPassClass_Reserved_2" 4 "OCS_FrontPassClass_Reserved_3" 5 "OCS_FrontPassClass_Reserved_4" 6 "OCS_FrontPassClass_Small_Adult" 7 "OCS_FrontPassClass_Medium_Adult" 8 "OCS_FrontPassClass_Reserved_5" 9 "OCS_FrontPassClass_Reserved_6" 10 "OCS_FrontPassClass_Reserved_7" 11 "OCS_FrontPassClass_Reserved_8" 12 "OCS_FrontPassClass_Reserved_9" 13 "OCS_FrontPassClass_Reserved_10" 14 "OCS_FrontPassClass_Reserved_11" 15 "OCS_FrontPassClass_Reserved_12"; +VAL_ 1640 OCS_FrontPassClassValid 0 "Not_Valid" 1 "Valid"; +VAL_ 1640 OCS_FrontPassFaultStatus 0 "No_Fault_Present" 1 "Fault_Status" 2 "Reserved_1" 3 "Reserved_2"; +VAL_ 1640 OCS_Reserved_1 0 "OCS_Reserved_Reserved"; +VAL_ 1640 OCS_FrontPassSBRStatus 0 "Unknown" 1 "Empty" 2 "Occupied"; +VAL_ 1640 OCS_OperatingMode 0 "OCS_OperatingMode_Initialisation" 1 "OCS_OperatingMode_Normal_Mode" 2 "OCS_OperatingMode_Empty_Seat_Calibration_Active" 3 "OCS_OperatingMode_Barrier_Airbag_Test_Mode" 4 "OCS_OperatingMode_Voltage_Out_Of_Range" 5 "OCS_OperatingMode_Falut_Active" 6 "OCS_OperatingMode_Reserved_1" 7 "OCS_OperatingMode_Reserved_2" 8 "OCS_OperatingMode_Reserved_3" 9 "OCS_OperatingMode_Reserved_4" 10 "OCS_OperatingMode_Reserved_5" 11 "OCS_OperatingMode_Reserved_6" 12 "OCS_OperatingMode_Reserved_7" 13 "OCS_OperatingMode_Reserved_8" 14 "OCS_OperatingMode_Reserved_9" 15 "OCS_OperatingMode_Reserved_10"; +VAL_ 1640 OCS_Reserved_2 0 "OCS_Reserved_2_Reserved"; diff --git a/opendbc_repo/opendbc/dbc/tesla_can.dbc b/opendbc_repo/opendbc/dbc/tesla_can.dbc new file mode 100644 index 0000000000..56624c3e54 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/tesla_can.dbc @@ -0,0 +1,901 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: + NEO + MCU + GTW + EPAS + DI + ESP + SBW + STW + APP + DAS + XXX + +VAL_TABLE_ StW_AnglHP_Spd 16383 "SNA" ; +VAL_TABLE_ DI_aebFaultReason 15 "DI_AEB_FAULT_DAS_REQ_DI_UNAVAIL" 14 "DI_AEB_FAULT_ACCEL_REQ_INVALID" 13 "DI_AEB_FAULT_MIN_TIME_BTWN_EVENTS" 12 "DI_AEB_FAULT_ESP_MIA" 11 "DI_AEB_FAULT_ESP_FAULT" 10 "DI_AEB_FAULT_EPB_NOT_PARKED" 9 "DI_AEB_FAULT_ACCEL_OUT_OF_BOUNDS" 8 "DI_AEB_FAULT_PM_REQUEST" 7 "DI_AEB_FAULT_VEL_EST_ABNORMAL" 6 "DI_AEB_FAULT_DAS_SNA" 5 "DI_AEB_FAULT_DAS_CONTROL_MIA" 4 "DI_AEB_FAULT_SPEED_DELTA" 3 "DI_AEB_FAULT_EBR_FAULT" 2 "DI_AEB_FAULT_PM_MIA" 1 "DI_AEB_FAULT_EPB_MIA" 0 "DI_AEB_FAULT_NONE" ; +VAL_TABLE_ DI_aebLockState 3 "AEB_LOCK_STATE_SNA" 2 "AEB_LOCK_STATE_UNUSED" 1 "AEB_LOCK_STATE_UNLOCKED" 0 "AEB_LOCK_STATE_LOCKED" ; +VAL_TABLE_ DI_aebSmState 7 "DI_AEB_STATE_FAULT" 6 "DI_AEB_STATE_EXIT" 5 "DI_AEB_STATE_STANDSTILL" 4 "DI_AEB_STATE_STOPPING" 3 "DI_AEB_STATE_ENABLE" 2 "DI_AEB_STATE_ENABLE_INIT" 1 "DI_AEB_STATE_STANDBY" 0 "DI_AEB_STATE_UNAVAILABLE" ; +VAL_TABLE_ DI_aebState 7 "AEB_CAN_STATE_SNA" 4 "AEB_CAN_STATE_FAULT" 3 "AEB_CAN_STATE_STANDSTILL" 2 "AEB_CAN_STATE_ENABLED" 1 "AEB_CAN_STATE_STANDBY" 0 "AEB_CAN_STATE_UNAVAILABLE" ; +VAL_TABLE_ DI_epbInterfaceReady 1 "EPB_INTERFACE_READY" 0 "EPB_INTERFACE_NOT_READY" ; +VAL_TABLE_ DI_gear 7 "DI_GEAR_SNA" 4 "DI_GEAR_D" 3 "DI_GEAR_N" 2 "DI_GEAR_R" 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" ; +VAL_TABLE_ DI_gpoReason 8 "DI_GPO_NUMREASONS" 7 "DI_GPO_CAPACITOR_OVERTEMP" 6 "DI_GPO_NOT_ENOUGH_12V" 5 "DI_GPO_NO_BATTERY_POWER" 4 "DI_GPO_AMBIENT_OVERTEMP" 3 "DI_GPO_FLUID_DELTAT" 2 "DI_GPO_STATOR_OVERTEMP" 1 "DI_GPO_HEATSINK_OVERTEMP" 0 "DI_GPO_OUTLET_OVERTEMP" ; +VAL_TABLE_ DI_immobilizerCondition 1 "DI_IMM_CONDITION_LEARNED" 0 "DI_IMM_CONDITION_VIRGIN_SNA" ; +VAL_TABLE_ DI_immobilizerState 7 "DI_IMM_STATE_FAULT" 6 "DI_IMM_STATE_FAULTRETRY" 5 "DI_IMM_STATE_RESET" 4 "DI_IMM_STATE_LEARN" 3 "DI_IMM_STATE_DISARMED" 2 "DI_IMM_STATE_AUTHENTICATING" 1 "DI_IMM_STATE_REQUEST" 0 "DI_IMM_STATE_INIT_SNA" ; +VAL_TABLE_ DI_limpReason 24 "DI_LIMP_NUMREASONS" 23 "DI_LIMP_CAPACITOR_OVERTEMP" 22 "DI_LIMP_GTW_MIA" 21 "DI_LIMP_TRQCMD_VALIDITY_UNKNOWN" 20 "DI_LIMP_DI_MIA" 19 "DI_LIMP_CONFIG_MISMATCH" 18 "DI_LIMP_HEATSINK_TEMP" 17 "DI_LIMP_PMREQUEST" 16 "DI_LIMP_PMHEARTBEAT" 15 "DI_LIMP_TRQ_CROSS_CHECK" 14 "DI_LIMP_EXTERNAL_COMMAND" 13 "DI_LIMP_WRONG_CS_CALIBRATION" 12 "DI_LIMP_STATOR_TEMP" 11 "DI_LIMP_DELTAT_TOO_NEGATIVE" 10 "DI_LIMP_DELTAT_TOO_POSITIVE" 9 "DI_LIMP_AMBIENT_TEMP" 8 "DI_LIMP_OUTLET_TEMP" 7 "DI_LIMP_LOW_FLOW" 6 "DI_LIMP_BMS_MIA" 5 "DI_LIMP_12V_SUPPLY_UNDERVOLTAGE" 4 "DI_LIMP_NO_FLUID" 3 "DI_LIMP_NO_FUNC_HEATSINK_SENSOR" 2 "DI_LIMP_NO_FUNC_STATORT_SENSOR" 1 "DI_LIMP_BUSV_SENSOR_IRRATIONAL" 0 "DI_LIMP_PHASE_IMBALANCE" ; +VAL_TABLE_ DI_mode 2 "DI_MODE_DYNO" 1 "DI_MODE_DRIVE" 0 "DI_MODE_UNDEF" ; +VAL_TABLE_ DI_motorType 14 "DI_MOTOR_F2AE" 13 "DI_MOTOR_F2AD" 12 "DI_MOTOR_F2AC" 11 "DI_MOTOR_F2AB" 10 "DI_MOTOR_F1AC" 9 "DI_MOTOR_SSR1A" 8 "DI_MOTOR_F1A" 7 "DI_MOTOR_M7M6" 6 "DI_MOTOR_M8A" 5 "DI_MOTOR_M7M5" 4 "DI_MOTOR_M7M4" 3 "DI_MOTOR_M7M3" 2 "DI_MOTOR_ROADSTER_SPORT" 1 "DI_MOTOR_ROADSTER_BASE" 0 "DI_MOTOR_SNA" ; +VAL_TABLE_ DI_speedUnits 1 "DI_SPEED_KPH" 0 "DI_SPEED_MPH" ; +VAL_TABLE_ DI_state 4 "DI_STATE_ENABLE" 3 "DI_STATE_FAULT" 2 "DI_STATE_CLEAR_FAULT" 1 "DI_STATE_STANDBY" 0 "DI_STATE_PREAUTH" ; +VAL_TABLE_ DI_velocityEstimatorState 4 "VE_STATE_BACKUP_MOTOR" 3 "VE_STATE_BACKUP_WHEELS_B" 2 "VE_STATE_BACKUP_WHEELS_A" 1 "VE_STATE_WHEELS_NORMAL" 0 "VE_STATE_NOT_INITIALIZED" ; + + +BO_ 1160 DAS_steeringControl: 4 NEO + SG_ DAS_steeringControlType : 23|2@0+ (1,0) [0|0] "" EPAS + SG_ DAS_steeringControlChecksum : 31|8@0+ (1,0) [0|0] "" EPAS + SG_ DAS_steeringControlCounter : 19|4@0+ (1,0) [0|0] "" EPAS + SG_ DAS_steeringAngleRequest : 6|15@0+ (0.1,-1638.35) [-1638.35|1638.35] "deg" EPAS + SG_ DAS_steeringHapticRequest : 7|1@0+ (1,0) [0|0] "" EPAS + +BO_ 697 DAS_control: 8 NEO + SG_ DAS_setSpeed : 0|12@1+ (0.1,0) [0|409.4] "kph" NEO + SG_ DAS_accState : 12|4@1+ (1,0) [0|0] "" NEO + SG_ DAS_aebEvent : 16|2@1+ (1,0) [0|3] "" NEO + SG_ DAS_jerkMin : 18|9@1+ (0.03,-15.232) [-15.232|0.098] "m/s^3" NEO + SG_ DAS_jerkMax : 27|8@1+ (0.059,0) [0|15.045] "m/s^3" NEO + SG_ DAS_accelMin : 35|9@1+ (0.04,-15) [-15|5.44] "m/s^2" NEO + SG_ DAS_accelMax : 44|9@1+ (0.04,-15) [-15|5.44] "m/s^2" NEO + SG_ DAS_controlCounter : 53|3@1+ (1,0) [0|0] "" NEO + SG_ DAS_controlChecksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 521 DAS_longControl: 8 NEO + SG_ DAS_locMode : 0|2@1+ (1,0) [0|0] "" NEO + SG_ DAS_locState : 2|3@1+ (1,0) [0|0] "" NEO + SG_ DAS_locRequest : 5|3@1+ (1,0) [0|0] "" NEO + SG_ DAS_locJerkMin : 8|8@1+ (0.034,-8.67) [-8.67|0] "m/s^3" NEO + SG_ DAS_locJerkMax : 16|8@1+ (0.034,0) [0|8.67] "m/s^3" NEO + SG_ DAS_locSpeed : 24|11@1+ (0.1,0) [0|204.7] "kph" NEO + SG_ DAS_locAccelMin : 35|9@1+ (0.04,-15) [-15|5.44] "m/s^2" NEO + SG_ DAS_locAccelMax : 44|9@1+ (0.04,-15) [-15|5.44] "m/s^2" NEO + SG_ DAS_longControlCounter : 53|3@1+ (1,0) [0|0] "" NEO + SG_ DAS_longControlChecksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 569 DAS_lanes: 8 NEO + SG_ DAS_leftLaneExists : 0|1@1+ (1,0) [0|0] "" NEO + SG_ DAS_rightLaneExists : 1|1@1+ (1,0) [0|0] "" NEO + SG_ DAS_virtualLaneWidth : 4|4@1+ (0.3125,2) [2|7] "m" NEO + SG_ DAS_virtualLaneViewRange : 8|8@1+ (1,0) [0|160] "m" NEO + SG_ DAS_virtualLaneC0 : 16|8@1+ (0.035,-3.5) [-3.5|3.5] "m" NEO + SG_ DAS_virtualLaneC1 : 24|8@1+ (0.0016,-0.2) [-0.2|0.2] "rad" NEO + SG_ DAS_virtualLaneC2 : 32|8@1+ (2E-05,-0.0025) [-0.0025|0.0025] "m-1" NEO + SG_ DAS_virtualLaneC3 : 40|8@1+ (2.4E-07,-3E-05) [-3E-05|3E-05] "m-2" NEO + SG_ DAS_leftLineUsage : 48|2@1+ (1,0) [0|3] "" NEO + SG_ DAS_rightLineUsage : 50|2@1+ (1,0) [0|3] "" NEO + SG_ DAS_leftFork : 52|2@1+ (1,0) [0|3] "" NEO + SG_ DAS_rightFork : 54|2@1+ (1,0) [0|3] "" NEO + SG_ DAS_lanesCounter : 60|4@1+ (1,0) [0|0] "" NEO + +BO_ 257 GTW_epasControl: 3 NEO + SG_ GTW_epasControlChecksum : 23|8@0+ (1,0) [0|255] "" NEO + SG_ GTW_epasControlCounter : 11|4@0+ (1,0) [0|15] "" NEO + SG_ GTW_epasControlType : 15|2@0+ (1,0) [-1|4] "" NEO + SG_ GTW_epasEmergencyOn : 7|1@0+ (1,0) [-1|2] "" NEO + SG_ GTW_epasLDWEnabled : 12|1@0+ (1,0) [-1|2] "" NEO + SG_ GTW_epasPowerMode : 6|4@0+ (1,0) [4|14] "" NEO + SG_ GTW_epasTuneRequest : 2|3@0+ (1,0) [-1|8] "" NEO + +BO_ 880 EPAS_sysStatus: 8 EPAS + SG_ EPAS_currentTuneMode : 7|4@0+ (1,0) [8|15] "" NEO + SG_ EPAS_eacErrorCode : 23|4@0+ (1,0) [-1|16] "" NEO + SG_ EPAS_eacStatus : 55|3@0+ (1,0) [5|7] "" NEO + SG_ EPAS_handsOnLevel : 39|2@0+ (1,0) [-1|4] "" NEO + SG_ EPAS_internalSAS : 37|14@0+ (0.1,-819.200012) [0|0] "deg" NEO + SG_ EPAS_steeringFault : 2|1@0+ (1,0) [-1|2] "" NEO + SG_ EPAS_steeringRackForce : 1|10@0+ (50,-25575) [0|0] "N" NEO + SG_ EPAS_steeringReduced : 3|1@0+ (1,0) [-1|2] "" NEO + SG_ EPAS_sysStatusChecksum : 63|8@0+ (1,0) [0|255] "" NEO + SG_ EPAS_sysStatusCounter : 51|4@0+ (1,0) [0|15] "" NEO + SG_ EPAS_torsionBarTorque : 19|12@0+ (0.01,-20.5) [0|0] "Nm" NEO + +BO_ 305 EPAS3P_sysStatus: 8 NEO + SG_ EPAS_currentTuneMode : 7|4@0+ (1,0) [0|0] "" NEO + SG_ EPAS_eacErrorCode : 23|4@0+ (1,0) [0|15] "" NEO + SG_ EPAS_eacStatus : 55|3@0+ (1,0) [0|7] "" NEO + SG_ EPAS_handsOnLevel : 39|2@0+ (1,0) [0|3] "" NEO + SG_ EPAS_internalSAS : 37|14@0+ (0.1,-819.2) [-819.2|819] "deg" NEO + SG_ EPAS_steeringFault : 2|1@0+ (1,0) [0|1] "" NEO + SG_ EPAS_steeringRackForce : 1|10@0+ (50,-25575) [-25575|25575] "N" NEO + SG_ EPAS_steeringReduced : 3|1@0+ (1,0) [0|1] "" NEO + SG_ EPAS_sysStatusChecksum : 63|8@0+ (1,0) [0|255] "" NEO + SG_ EPAS_sysStatusCounter : 51|4@0+ (1,0) [0|15] "" NEO + SG_ EPAS_torsionBarTorque : 19|12@0+ (0.01,-20.5) [-20.5|20.45] "Nm" NEO + +BO_ 3 STW_ANGL_STAT: 8 STW + SG_ StW_Angl : 5|14@0+ (0.5,-2048) [0|0] "deg" NEO + SG_ StW_AnglSpd : 21|14@0+ (0.5,-2048) [0|0] "/s" NEO + SG_ StW_AnglSens_Stat : 33|2@0+ (1,0) [-1|4] "" NEO + SG_ StW_AnglSens_Id : 35|2@0+ (1,0) [3|3] "" NEO + SG_ MC_STW_ANGL_STAT : 55|4@0+ (1,0) [0|15] "" NEO + SG_ CRC_STW_ANGL_STAT : 63|8@0+ (1,0) [0|255] "" NEO + +BO_ 14 STW_ANGLHP_STAT: 8 STW + SG_ StW_AnglHP : 5|14@0+ (0.1,-819.2) [-819.2|819] "deg" NEO + SG_ StW_AnglHP_Spd : 21|14@0+ (0.5,-4096) [-4096|4095.5] "deg/s" NEO + SG_ StW_AnglHP_Sens_Stat : 33|2@0+ (1,0) [0|0] "" NEO + SG_ StW_AnglHP_Sens_Id : 35|2@0+ (1,0) [0|0] "" NEO + SG_ MC_STW_ANGLHP_STAT : 55|4@0+ (1,0) [0|15] "" NEO + SG_ CRC_STW_ANGLHP_STAT : 63|8@0+ (1,0) [0|0] "" NEO + +BO_ 264 DI_torque1: 8 DI + SG_ DI_torqueDriver : 0|13@1- (0.25,0) [-750|750] "Nm" NEO + SG_ DI_torque1Counter : 13|3@1+ (1,0) [0|0] "" NEO + SG_ DI_torqueMotor : 16|13@1- (0.25,0) [-750|750] "Nm" NEO + SG_ DI_soptState : 29|3@1+ (1,0) [0|0] "" NEO + SG_ DI_motorRPM : 32|16@1- (1,0) [-17000|17000] "RPM" NEO + SG_ DI_pedalPos : 48|8@1+ (0.4,0) [0|100] "%" NEO + SG_ DI_torque1Checksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 280 DI_torque2: 6 DI + SG_ DI_torqueEstimate : 0|12@1- (0.5,0) [-750|750] "Nm" NEO + SG_ DI_gear : 12|3@1+ (1,0) [0|0] "" NEO + SG_ DI_brakePedal : 15|1@1+ (1,0) [0|0] "" NEO + SG_ DI_vehicleSpeed : 16|12@1+ (0.05,-25) [-25|179.75] "MPH" NEO + SG_ DI_gearRequest : 28|3@1+ (1,0) [0|0] "" NEO + SG_ DI_torqueInterfaceFailure : 31|1@1+ (1,0) [0|0] "" NEO + SG_ DI_torque2Counter : 32|4@1+ (1,0) [0|0] "" NEO + SG_ DI_brakePedalState : 36|2@1+ (1,0) [0|0] "" NEO + SG_ DI_epbParkRequest : 38|1@1+ (1,0) [0|0] "" NEO + SG_ DI_epbInterfaceReady : 39|1@1+ (1,0) [0|0] "" NEO + SG_ DI_torque2Checksum : 40|8@1+ (1,0) [0|0] "" NEO + +BO_ 309 ESP_135h: 5 ESP + SG_ ESP_135hChecksum : 23|8@0+ (1,0) [0|255] "" NEO + SG_ ESP_135hCounter : 11|4@0+ (1,0) [0|15] "" NEO + SG_ ESP_absBrakeEvent : 2|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_brakeDiscWipingActive : 4|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_brakeLamp : 3|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_espFaultLamp : 6|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_espLampFlash : 7|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_hillStartAssistActive : 1|2@0+ (1,0) [-1|4] "" NEO + SG_ ESP_messagePumpService : 24|1@0+ (1,0) [0|1] "" NEO + SG_ ESP_messagePumpFailure : 25|1@0+ (1,0) [0|1] "" NEO + SG_ ESP_messageEBDFailure : 26|1@0+ (1,0) [0|1] "" NEO + SG_ ESP_absFaultLamp : 27|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_tcDisabledByFault : 28|1@0+ (1,0) [0|1] "" NEO + SG_ ESP_messageDynoModeActive : 29|1@0+ (1,0) [0|1] "" NEO + SG_ ESP_hydraulicBoostEnabled : 30|1@0+ (1,0) [0|1] "" NEO + SG_ ESP_espOffLamp : 31|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_stabilityControlSts : 14|3@0+ (1,0) [6|7] "" NEO + SG_ ESP_tcLampFlash : 5|1@0+ (1,0) [-1|2] "" NEO + SG_ ESP_tcOffLamp : 15|1@0+ (1,0) [0|1] "" NEO + +BO_ 341 ESP_B: 8 ESP + SG_ ESP_BChecksum : 39|8@0+ (1,0) [0|255] "" NEO,EPAS + SG_ ESP_BCounter : 62|4@0+ (1,0) [1|15] "" NEO,EPAS + SG_ ESP_vehicleSpeed : 47|16@0+ (0.00999999978,0) [0|0] "kph" NEO,EPAS + SG_ ESP_vehicleSpeedQF : 57|2@0+ (1,0) [1|2] "" NEO,EPAS + SG_ ESP_wheelPulseCountFrL : 7|8@0+ (1,0) [0|254] "" NEO,EPAS + SG_ ESP_wheelPulseCountFrR : 15|8@0+ (1,0) [0|254] "" NEO,EPAS + SG_ ESP_wheelPulseCountReL : 23|8@0+ (1,0) [0|254] "" NEO,EPAS + SG_ ESP_wheelPulseCountReR : 31|8@0+ (1,0) [0|254] "" NEO,EPAS + +BO_ 513 SDM1: 5 GTW + SG_ SDM_bcklPassStatus : 3|2@0+ (1,0) [0|3] "" NEO + SG_ SDM_bcklDrivStatus : 5|2@0+ (1,0) [0|3] "" NEO + +BO_ 532 EPB_epasControl: 3 EPB + SG_ EPB_epasControlChecksum : 23|8@0+ (1,0) [0|255] "" NEO,EPAS + SG_ EPB_epasControlCounter : 11|4@0+ (1,0) [0|15] "" NEO,EPAS + SG_ EPB_epasEACAllow : 2|3@0+ (1,0) [4|7] "" NEO,EPAS + +BO_ 792 GTW_carState: 8 GTW + SG_ YEAR : 0|7@1+ (1,2000) [2000|2127] "Year" NEO + SG_ CERRD : 7|1@1+ (1,0) [0|1] "" NEO + SG_ MONTH : 8|4@1+ (1,0) [1|12] "Month" NEO + SG_ DOOR_STATE_FL : 12|2@1+ (1,0) [0|3] "" NEO + SG_ DOOR_STATE_FR : 14|2@1+ (1,0) [0|3] "" NEO + SG_ SECOND : 16|6@1+ (1,0) [0|59] "s" NEO + SG_ DOOR_STATE_RL : 22|2@1+ (1,0) [0|3] "" NEO + SG_ Hour : 24|5@1+ (1,0) [0|23] "h" NEO + SG_ DOOR_STATE_RR : 29|2@1+ (1,0) [0|3] "" NEO + SG_ DAY : 32|5@1+ (1,0) [0|31] "" NEO + SG_ MINUTE : 40|6@1+ (1,0) [0|59] "min" NEO + SG_ BOOT_STATE : 46|2@1+ (1,0) [0|3] "" NEO + SG_ GTW_updateInProgress : 48|2@1+ (1,0) [0|3] "" NEO + SG_ DOOR_STATE_FrontTrunk : 50|2@1+ (1,0) [0|3] "" NEO + SG_ MCU_factoryMode : 52|1@1+ (1,0) [0|1] "" NEO + SG_ MCU_transportModeOn : 53|1@0+ (1,0) [0|1] "" NEO + SG_ BC_headLightLStatus : 55|2@0+ (1,0) [0|3] "" NEO + SG_ BC_headLightRStatus : 57|2@0+ (1,0) [0|3] "" NEO + SG_ BC_indicatorLStatus : 59|2@0+ (1,0) [0|3] "" NEO + SG_ BC_indicatorRStatus : 61|2@0+ (1,0) [0|3] "" NEO + +BO_ 872 DI_state: 8 DI + SG_ DI_systemState : 0|3@1+ (1,0) [0|0] "" NEO + SG_ DI_vehicleHoldState : 3|3@1+ (1,0) [0|0] "" NEO + SG_ DI_proximity : 6|1@1+ (1,0) [0|0] "" NEO + SG_ DI_driveReady : 7|1@1+ (1,0) [0|0] "" NEO + SG_ DI_regenLight : 8|1@1+ (1,0) [0|0] "" NEO + SG_ DI_state : 9|3@1+ (1,0) [0|0] "" NEO + SG_ DI_cruiseState : 12|4@1+ (1,0) [0|0] "" NEO + SG_ DI_analogSpeed : 16|12@1+ (0.1,0) [0|150] "speed" NEO + SG_ DI_immobilizerState : 28|3@1+ (1,0) [0|0] "" NEO + SG_ DI_speedUnits : 31|1@1+ (1,0) [0|1] "" NEO + SG_ DI_cruiseSet : 32|9@1+ (0.5,0) [0|255.5] "speed" NEO + SG_ DI_aebState : 41|3@1+ (1,0) [0|0] "" NEO + SG_ DI_stateCounter : 44|4@1+ (1,0) [0|0] "" NEO + SG_ DI_digitalSpeed : 48|8@1+ (1,0) [0|250] "" NEO + SG_ DI_stateChecksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 109 SBW_RQ_SCCM: 4 STW + SG_ StW_Sw_Stat3 : 0|3@1+ (1,0) [0|0] "" NEO + SG_ MsgTxmtId : 6|2@1+ (1,0) [0|0] "" NEO + SG_ TSL_RND_Posn_StW : 8|4@1+ (1,0) [0|0] "" NEO + SG_ TSL_P_Psd_StW : 12|2@1+ (1,0) [0|0] "" NEO + SG_ MC_SBW_RQ_SCCM : 20|4@1+ (1,0) [0|15] "" NEO + SG_ CRC_SBW_RQ_SCCM : 24|8@1+ (1,0) [0|0] "" NEO + +BO_ 69 STW_ACTN_RQ: 8 STW + SG_ SpdCtrlLvr_Stat : 0|6@1+ (1,0) [0|0] "" NEO + SG_ VSL_Enbl_Rq : 6|1@1+ (1,0) [0|0] "" NEO + SG_ SpdCtrlLvrStat_Inv : 7|1@1+ (1,0) [0|0] "" NEO + SG_ DTR_Dist_Rq : 8|8@1+ (1,0) [0|200] "" NEO + SG_ TurnIndLvr_Stat : 16|2@1+ (1,0) [0|0] "" NEO + SG_ HiBmLvr_Stat : 18|2@1+ (1,0) [0|0] "" NEO + SG_ WprWashSw_Psd : 20|2@1+ (1,0) [0|0] "" NEO + SG_ WprWash_R_Sw_Posn_V2 : 22|2@1+ (1,0) [0|0] "" NEO + SG_ StW_Lvr_Stat : 24|3@1+ (1,0) [0|0] "" NEO + SG_ StW_Cond_Flt : 27|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Cond_Psd : 28|2@1+ (1,0) [0|0] "" NEO + SG_ HrnSw_Psd : 30|2@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw00_Psd : 32|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw01_Psd : 33|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw02_Psd : 34|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw03_Psd : 35|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw04_Psd : 36|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw05_Psd : 37|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw06_Psd : 38|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw07_Psd : 39|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw08_Psd : 40|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw09_Psd : 41|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw10_Psd : 42|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw11_Psd : 43|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw12_Psd : 44|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw13_Psd : 45|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw14_Psd : 46|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw15_Psd : 47|1@1+ (1,0) [0|0] "" NEO + SG_ WprSw6Posn : 48|3@1+ (1,0) [0|0] "" NEO + SG_ MC_STW_ACTN_RQ : 52|4@1+ (1,0) [0|15] "" NEO + SG_ CRC_STW_ACTN_RQ : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 643 BODY_R1: 8 GTW + SG_ AirTemp_Insd : 47|8@0+ (0.25,0) [0|63.5] "C" NEO + SG_ AirTemp_Outsd : 63|8@0+ (0.5,-40) [-40|86.5] "C" NEO + SG_ Bckl_Sw_RL_Stat_SAM_R : 49|2@0+ (1,0) [-1|4] "" NEO + SG_ Bckl_Sw_RM_Stat_SAM_R : 53|2@0+ (1,0) [-1|4] "" NEO + SG_ Bckl_Sw_RR_Stat_SAM_R : 51|2@0+ (1,0) [-1|4] "" NEO + SG_ DL_RLtch_Stat : 9|2@0+ (1,0) [-1|4] "" NEO + SG_ DrRLtch_FL_Stat : 1|2@0+ (1,0) [-1|4] "" NEO + SG_ DrRLtch_FR_Stat : 3|2@0+ (1,0) [-1|4] "" NEO + SG_ DrRLtch_RL_Stat : 5|2@0+ (1,0) [-1|4] "" NEO + SG_ DrRLtch_RR_Stat : 7|2@0+ (1,0) [-1|4] "" NEO + SG_ EngHd_Stat : 11|2@0+ (1,0) [-1|4] "" NEO + SG_ LoBm_On_Rq : 32|1@0+ (1,0) [0|1] "" NEO + SG_ HiBm_On : 33|1@0+ (1,0) [0|1] "" NEO + SG_ Hrn_On : 26|1@0+ (1,0) [0|1] "" NEO + SG_ IrLmp_D_Lt_Flt : 34|1@0+ (1,0) [0|1] "" NEO + SG_ IrLmp_P_Rt_Flt : 35|1@0+ (1,0) [0|1] "" NEO + SG_ LgtSens_Twlgt : 18|3@0+ (1,0) [0|7] "Steps" NEO + SG_ LgtSens_SNA : 19|1@0+ (1,0) [0|1] "" NEO + SG_ LgtSens_Tunnel : 20|1@0+ (1,0) [0|1] "" NEO + SG_ LgtSens_Flt : 21|1@0+ (1,0) [0|1] "" NEO + SG_ LgtSens_Night : 22|1@0+ (1,0) [-1|2] "" NEO + SG_ ADL_LoBm_On_Rq : 23|1@0+ (1,0) [0|1] "" NEO + SG_ LoBm_D_Lt_Flt : 36|1@0+ (1,0) [0|1] "" NEO + SG_ LoBm_P_Rt_Flt : 37|1@0+ (1,0) [0|1] "" NEO + SG_ MPkBrk_Stat : 28|1@0+ (1,0) [-1|2] "" NEO + SG_ RevGr_Engg : 39|2@0+ (1,0) [-1|4] "" NEO + SG_ StW_Cond_Stat : 55|2@0+ (1,0) [-1|4] "" NEO + SG_ Term54_Actv : 27|1@0+ (1,0) [0|1] "" NEO + SG_ Trlr_Stat : 25|2@0+ (1,0) [-1|4] "" NEO + SG_ VTA_Alm_Actv : 13|1@0+ (1,0) [0|1] "" NEO + SG_ WprOutsdPkPosn : 29|1@0+ (1,0) [0|1] "" NEO + +BO_ 760 UI_gpsVehicleSpeed: 8 GTW + SG_ UI_gpsHDOP : 0|8@1+ (0.1,0) [0|25.5] "1" DAS + SG_ UI_gpsVehicleHeading : 8|16@1+ (0.0078125,0) [0|511.9921875] "deg" DAS + SG_ UI_gpsVehicleSpeed : 24|16@1+ (0.00390625,0) [0|250.996] "km/hr" Vector__XXX + SG_ UI_userSpeedOffset : 40|6@1+ (1,-30) [-30|33] "kph/mph" DAS + SG_ UI_mapSpeedLimitUnits : 46|1@1+ (1,0) [0|1] "" DAS + SG_ UI_userSpeedOffsetUnits : 47|1@1+ (1,0) [0|1] "" DAS + SG_ UI_mppSpeedLimit : 48|5@1+ (5,0) [0|155] "kph/mph" DAS + SG_ UI_gpsNmeaMIA : 53|1@1+ (1,0) [0|0] "" DAS + +BO_ 536 MCU_chassisControl: 8 GTW + SG_ MCU_dasDebugEnable : 0|1@1+ (1,0) [0|0] "" NEO + SG_ MCU_parkBrakeRequest : 1|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_trailerModeCH : 3|1@1+ (1,0) [0|0] "" NEO + SG_ MCU_fcwSensitivity : 4|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_fcwEnable : 6|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_latControlEnable : 8|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_accOvertakeEnable : 10|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_ldwEnable : 12|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_aebEnable : 14|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_bsdEnable : 16|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_ahlbEnable : 18|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_parkSetting : 20|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_pedalSafetyEnable : 22|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_frontDefrostReq_das : 24|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_autoParkRequest : 26|4@1+ (1,0) [0|0] "" NEO + SG_ MCU_redLightStopSignEnable : 30|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_enableCreepTorqueCH : 32|1@1+ (1,0) [0|0] "" NEO + SG_ MCU_narrowGarages : 33|1@1+ (1,0) [0|0] "" NEO + SG_ MCU_rebootAutopilot : 34|1@1+ (1,0) [0|0] "" NEO + SG_ MCU_enableAutowipers : 35|1@1+ (1,0) [0|0] "" NEO + SG_ MCU_overPaintedUSS : 38|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_selfParkTune : 40|4@1+ (1,0) [0|15] "" NEO + SG_ MCU_towModeEnable : 44|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_zeroSpeedConfirmed : 46|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_aesEnable : 48|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_autoLaneChangeEnable : 50|2@1+ (1,0) [0|0] "" NEO + SG_ MCU_chassisControlCounter : 52|4@1+ (1,0) [0|0] "" NEO + SG_ MCU_chassisControlChecksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 904 MCU_clusterBacklightRequest: 3 NEO + SG_ MCU_clusterBacklightOn : 7|1@1+ (1,0) [0|1] "" NEO + SG_ MCU_clusterBrightnessLevel : 8|8@1+ (0.5,0) [0|127.5] "%" NEO + SG_ MCU_clusterReadyForDrive : 6|1@1+ (1,0) [-1|2] "" NEO + SG_ MCU_clusterReadyForPowerOff : 5|1@1+ (1,0) [0|1] "" NEO + +BO_ 984 MCU_locationStatus: 8 MCU + SG_ MCU_gpsAccuracy : 57|7@1+ (0.2,0) [0|0] "m" NEO + SG_ MCU_latitude : 0|28@1- (1E-06,0) [0|0] "deg" NEO + SG_ MCU_longitude : 28|29@1- (1E-06,0) [0|0] "deg" NEO + +BO_ 104 MCU_locationStatus2: 8 MCU + SG_ MCU_elevation : 0|32@1- (0.1,0) [0|0] "m" GTW + SG_ MCU_navigonExpectedSpeed : 32|7@1+ (1,0) [0|126] "mph" GTW + +BO_ 840 GTW_status: 8 GTW + SG_ GTW_accGoingDown : 6|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_accRailReq : 8|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_brakePressed : 1|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_driveGoingDown : 7|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_driveRailReq : 0|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_driverIsLeaving : 5|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_driverPresent : 2|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_hvacGoingDown : 11|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_hvacRailReq : 9|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_icPowerOff : 4|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_notEnough12VForDrive : 3|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_preconditionRequest : 10|1@0+ (1,0) [0|1] "" NEO + SG_ GTW_statusChecksum : 63|8@0+ (1,0) [0|255] "" NEO + SG_ GTW_statusCounter : 51|4@0+ (1,0) [0|15] "" NEO + +BO_ 920 GTW_carConfig: 8 GTW + SG_ GTW_performanceConfig : 2|3@0+ (1,0) [0|0] "" NEO + SG_ GTW_fourWheelDrive : 4|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_unknown1 : 5|1@0+ (1,0) [0|0] "" NEO + SG_ GTW_dasHw : 7|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_parkAssistInstalled : 9|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_forwardRadarHw : 11|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_airSuspensionInstalled : 14|3@0+ (1,0) [0|0] "" NEO + SG_ GTW_unknown2 : 15|1@0+ (1,0) [0|0] "" NEO + SG_ GTW_country : 23|16@0+ (1,0) [0|0] "" NEO + SG_ GTW_parkSensorGeometryType : 33|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_rhd : 34|1@0+ (1,0) [0|0] "" NEO + SG_ GTW_bodyControlsType : 35|1@0+ (1,0) [0|0] "" NEO + SG_ GTW_radarPosition : 39|4@0+ (1,0) [0|0] "" NEO + SG_ GTW_rearCornerRadarHw : 41|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_frontCornerRadarHw : 43|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_epasType : 45|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_chassisType : 47|2@0+ (1,0) [0|2] "" NEO + SG_ GTW_wheelType : 52|5@0+ (1,0) [0|0] "" NEO + SG_ GTW_rearSeatControllerMask : 55|3@0+ (1,0) [0|7] "" NEO + SG_ GTW_euVehicle : 56|1@0+ (1,0) [0|0] "" NEO + SG_ GTW_foldingMirrorsInstalled : 57|1@0+ (1,0) [0|0] "" NEO + SG_ GTW_brakeHwType : 59|2@0+ (1,0) [0|2] "" NEO + SG_ GTW_autopilot : 61|2@0+ (1,0) [0|0] "" NEO + SG_ GTW_unknown3 : 63|2@0+ (1,0) [0|0] "" NEO + +BO_ 1006 UI_autopilotControl: 8 GTW + SG_ UI_autopilotControlIndex M : 0|3@1+ (1,0) [0|7] "" APP,APS + SG_ UI_hovEnabled m0 : 3|1@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donDisableAutoWiperDuration m0 : 4|3@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donDisableOnAutoWiperSpeed m0 : 7|4@1+ (1,0) [0|0] "" APP,APS + SG_ UI_blindspotMinSpeed m0 : 11|4@1+ (1,0) [0|0] "" APP,APS + SG_ UI_blindspotDistance m0 : 15|3@1+ (1,0) [0|0] "" APP,APS + SG_ UI_blindspotTTC m0 : 18|3@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donStopEndOfRampBuffer m0 : 21|3@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donDisableCutin m0 : 24|1@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donMinGoreWidthForAbortMap m0 : 25|4@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donAlcProgGoreAbortThres m0 : 29|4@1+ (1,0) [0|0] "" APP,APS + SG_ UI_donMinGoreWidthForAbortNotMap m0 : 33|4@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcDisableUltrasonicCheck m0 : 37|1@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcUltrasonicDistance m0 : 38|4@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcUltrasonicWaitTime m0 : 42|3@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcEgoLeadingReactionAccel m0 : 48|2@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcMergIntervalRearDHyst m0 : 50|2@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcMergingIntervalHeadwayHyst m0 : 52|2@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcAssertivenessRate m0 : 54|2@1+ (1,0) [0|0] "" APP,APS + SG_ UI_alcViewRangeSensitivity m0 : 56|2@1+ (1,0) [0|0] "" APP,APS + SG_ UI_camBlockLaneCheckDisable m1 : 3|1@1+ (1,0) [0|0] "" APP,APS + SG_ UI_camBlockLaneCheckThreshold m1 : 4|6@1+ (0.01587,0) [0|1] "%" APP,APS + SG_ UI_camBlockBlurDisable m1 : 10|1@1+ (1,0) [0|0] "" APP,APS + SG_ UI_camBlockBlurThreshold m1 : 11|6@1+ (0.01587,0) [0|1] "%" APP,APS + +BO_ 728 UI_csaOfframpCurvature: 8 GTW + SG_ UI_csaOfframpCurvC2 : 0|16@1- (1E-06,0) [-0.032768|0.032767] "1/m" DAS + SG_ UI_csaOfframpCurvC3 : 16|16@1- (4E-09,0) [-0.000131072|0.000131068] "1/m2" DAS + SG_ UI_csaOfframpCurvRange : 32|8@1+ (2,0) [0|510] "m" DAS + SG_ UI_csaOfframpCurvCounter : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ UI_csaOfframpCurvUsingTspline : 48|1@1+ (1,0) [0|1] "" DAS + SG_ UI_csaOfframpCurvReserved : 49|7@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_csaOfframpCurvChecksum : 56|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 744 UI_csaRoadCurvature: 8 GTW + SG_ UI_csaRoadCurvC2 : 0|16@1- (1E-06,0) [-0.032768|0.032767] "1/m" DAS + SG_ UI_csaRoadCurvC3 : 16|16@1- (4E-09,0) [-0.000131072|0.000131068] "1/m2" DAS + SG_ UI_csaRoadCurvRange : 32|8@1+ (2,0) [0|510] "m" DAS + SG_ UI_csaRoadCurvCounter : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ UI_csaRoadCurvUsingTspline : 48|1@1+ (1,0) [0|1] "" DAS + SG_ UI_csaRoadCurvReserved : 49|7@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_csaRoadCurvChecksum : 56|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 1080 UI_driverAssistAnonDebugParams: 8 GTW + SG_ UI_anonDebugParam1 : 0|7@1+ (1,0) [0|100] "" DAS + SG_ UI_anonDebugFlag1 : 7|1@1+ (1,0) [0|0] "" DAS + SG_ UI_anonDebugParam2 : 8|7@1+ (1,0) [0|100] "" DAS + SG_ UI_anonDebugFlag2 : 15|1@1+ (1,0) [0|0] "" DAS + SG_ UI_anonDebugParam3 : 16|7@1+ (1,0) [0|100] "" DAS + SG_ UI_anonDebugFlag3 : 23|1@1+ (1,0) [0|0] "" DAS + SG_ UI_anonDebugParam4 : 24|7@1+ (1,0) [0|100] "" DAS + SG_ UI_anonDebugFlag4 : 31|1@1+ (1,0) [0|0] "" DAS + SG_ UI_anonDebugParam5 : 32|7@1+ (1,0) [0|100] "" DAS + SG_ UI_anonDebugParam6 : 40|7@1+ (1,0) [0|100] "" DAS + SG_ UI_anonDebugParam7 : 48|7@1+ (1,0) [0|100] "" DAS + SG_ UI_visionSpeedSlider : 56|7@1+ (1,0) [0|100] "" DAS + +BO_ 1000 UI_driverAssistControl: 8 GTW + SG_ UI_autopilotControlRequest : 0|1@1+ (1,0) [1|0] "" DAS + SG_ UI_ulcStalkConfirm : 1|1@1+ (1,0) [1|0] "" DAS + SG_ UI_summonHeartbeat : 2|2@1+ (1,0) [0|0] "" DAS + SG_ UI_curvSpeedAdaptDisable : 4|1@1+ (1,0) [0|0] "" DAS + SG_ UI_dasDeveloper : 5|1@1+ (1,0) [0|0] "" DAS + SG_ UI_enableVinAssociation : 6|1@1+ (1,0) [0|0] "" DAS + SG_ UI_lssLkaEnabled : 7|1@1+ (1,0) [0|0] "" DAS + SG_ UI_lssLdwEnabled : 8|1@1+ (1,0) [0|0] "" DAS + SG_ UI_autoSummonEnable : 10|1@1+ (1,0) [0|1] "" DAS + SG_ UI_exceptionListEnable : 11|1@1+ (1,0) [0|1] "" APP + SG_ UI_roadCheckDisable : 12|1@1+ (1,0) [0|0] "" DAS + SG_ UI_driveOnMapsEnable : 13|1@1+ (1,0) [0|0] "" DAS + SG_ UI_handsOnRequirementDisable : 14|1@1+ (1,0) [0|0] "" DAS + SG_ UI_forksEnable : 15|1@1+ (1,0) [0|0] "" DAS + SG_ UI_fuseLanesDisable : 16|1@1+ (1,0) [0|0] "" DAS + SG_ UI_fuseHPPDisable : 17|1@1+ (1,0) [0|0] "" DAS + SG_ UI_fuseVehiclesDisable : 18|1@1+ (1,0) [0|0] "" DAS + SG_ UI_enableNextGenACC : 19|1@1+ (1,0) [0|1] "" APP + SG_ UI_visionSpeedType : 20|2@1+ (1,0) [0|0] "" APP + SG_ UI_curvatureDatabaseOnly : 22|1@1+ (1,0) [0|0] "" DAS + SG_ UI_lssElkEnabled : 23|1@1+ (1,0) [0|0] "" DAS + SG_ UI_summonExitType : 24|2@1+ (1,0) [0|3] "" DAS + SG_ UI_summonEntryType : 26|2@1+ (1,0) [0|3] "" DAS + SG_ UI_selfParkRequest : 28|4@1+ (1,0) [0|15] "" DAS,PARK + SG_ UI_summonReverseDist : 32|6@1+ (1,0) [0|63] "" DAS + SG_ UI_undertakeAssistEnable : 38|1@1+ (1,0) [0|0] "" DAS + SG_ UI_adaptiveSetSpeedEnable : 39|1@1+ (1,0) [0|0] "" DAS + SG_ UI_drivingSide : 40|2@1+ (1,0) [0|3] "" DAS + SG_ UI_enableClipTelemetry : 42|1@1+ (1,0) [0|0] "" APP + SG_ UI_enableTripTelemetry : 43|1@1+ (1,0) [0|0] "" APP + SG_ UI_enableRoadSegmentTelemetry : 44|1@1+ (1,0) [0|0] "" APP + SG_ UI_followNavRouteEnable : 46|1@1+ (1,0) [0|0] "" APP + SG_ UI_ulcSpeedConfig : 48|2@1+ (1,0) [0|3] "" APP + SG_ UI_ulcBlindSpotConfig : 50|2@1+ (1,0) [0|3] "" APP + SG_ UI_autopilotAlwaysOn : 52|1@1+ (1,0) [0|1] "" APP + SG_ UI_accFromZero : 53|1@1+ (1,0) [0|1] "" APP + SG_ UI_alcOffHighwayEnable : 54|1@1+ (1,0) [0|1] "" APP + SG_ UI_validationLoop : 55|1@1+ (1,0) [0|1] "" APP + SG_ UI_ulcOffHighway : 56|1@1+ (1,0) [0|1] "" APP + SG_ UI_enableNavRouteCSA : 57|1@1+ (1,0) [0|1] "" APP + SG_ UI_enableCutinExperiments : 58|1@1+ (1,0) [0|1] "" APP + SG_ UI_source3D : 60|3@1+ (1,0) [0|7] "" APP + SG_ UI_enableVisionOnlyStops : 63|1@1+ (1,0) [0|1] "" APP + +BO_ 968 UI_driverAssistMapData: 8 GTW + SG_ UI_mapSpeedLimitDependency : 0|3@1+ (1,0) [0|0] "" DAS + SG_ UI_roadClass : 3|3@1+ (1,0) [0|0] "" DAS + SG_ UI_inSuperchargerGeofence : 6|1@1+ (1,0) [0|0] "" DAS + SG_ UI_mapSpeedUnits : 7|1@1+ (1,0) [0|0] "" DAS + SG_ UI_mapSpeedLimit : 8|5@1+ (1,0) [0|0] "" DAS + SG_ UI_mapSpeedLimitType : 13|3@1+ (1,0) [0|0] "" DAS + SG_ UI_countryCode : 16|10@1+ (1,0) [0|0] "" DAS + SG_ UI_streetCount : 26|2@1+ (1,0) [0|0] "" DAS + SG_ UI_gpsRoadMatch : 28|1@1+ (1,0) [0|0] "" DAS + SG_ UI_navRouteActive : 29|1@1+ (1,0) [0|0] "" DAS + SG_ UI_parallelAutoparkEnabled : 30|1@1+ (1,0) [0|1] "" DAS + SG_ UI_perpendicularAutoparkEnabled : 31|1@1+ (1,0) [0|1] "" DAS + SG_ UI_nextBranchDist : 32|5@1+ (10,0) [0|300] "m" DAS + SG_ UI_controlledAccess : 37|1@1+ (1,0) [0|0] "" DAS + SG_ UI_nextBranchLeftOffRamp : 38|1@1+ (1,0) [0|0] "" DAS + SG_ UI_nextBranchRightOffRamp : 39|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectLeftLane : 40|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectRightLane : 41|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectHPP : 42|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectNav : 43|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectLeftFreeSpace : 44|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectRightFreeSpace : 45|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectAutosteer : 46|1@1+ (1,0) [0|0] "" DAS + SG_ UI_rejectHandsOn : 47|1@1+ (1,0) [0|0] "" DAS + SG_ UI_acceptBottsDots : 48|1@1+ (1,0) [0|0] "" DAS + SG_ UI_autosteerRestricted : 49|1@1+ (1,0) [0|0] "" DAS + SG_ UI_pmmEnabled : 50|1@1+ (1,0) [0|0] "" DAS + SG_ UI_scaEnabled : 51|1@1+ (1,0) [0|0] "" DAS + SG_ UI_mapDataCounter : 52|4@1+ (1,0) [0|0] "" DAS + SG_ UI_mapDataChecksum : 56|8@1+ (1,0) [0|0] "" DAS + +BO_ 568 UI_driverAssistRoadSign: 8 GTW + SG_ UI_roadSign M : 0|8@1+ (1,0) [0|0] "" DAS + SG_ UI_splineLocConfidence : 40|7@1+ (1,0) [0|100] "" DAS + SG_ UI_splineID : 48|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ UI_roadSignCounter : 52|4@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_roadSignChecksum : 56|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_dummyData m0 : 8|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_stopSignStopLineDist m1 : 8|10@1+ (0.25,-8) [-8|247.5] "m" Vector__XXX + SG_ UI_stopSignStopLineConf m1 : 18|7@1+ (1,0) [0|100] "" Vector__XXX + SG_ UI_trafficLightStopLineDist m2 : 8|10@1+ (0.25,-8) [-8|247.5] "m" Vector__XXX + SG_ UI_trafficLightStopLineConf m2 : 18|7@1+ (1,0) [0|100] "" Vector__XXX + SG_ UI_baseMapSpeedLimitMPS m3 : 8|8@1+ (0.25,0) [0|63.75] "m/s" DAS + SG_ UI_bottomQrtlFleetSpeedMPS m3 : 16|8@1+ (0.25,0) [0|63.75] "m/s" DAS + SG_ UI_topQrtlFleetSpeedMPS m3 : 24|8@1+ (0.25,0) [0|63.75] "m/s" DAS + SG_ UI_meanFleetSplineSpeedMPS m4 : 8|8@1+ (0.25,0) [0|63.75] "m/s" DAS + SG_ UI_medianFleetSpeedMPS m4 : 16|8@1+ (0.25,0) [0|63.75] "m/s" DAS + SG_ UI_meanFleetSplineAccelMPS2 m4 : 24|8@1+ (0.05,-6.35) [-6.35|6.4] "m/s^2" DAS + SG_ UI_rampType m4 : 32|3@1+ (1,0) [0|7] "" DAS + SG_ UI_currSplineIdFull m5 : 8|32@1+ (1,0) [0|1] "" APP + + +BO_ 696 UI_radarMapData: 8 GTW + SG_ UI_radarTargetDx : 0|8@1+ (1,-95) [-95|160] "m" DAS + SG_ UI_radarTargetDxEnd : 8|8@1+ (1,0) [0|255] "m" DAS + SG_ UI_radarTargetTrustMap : 16|1@1+ (1,0) [0|1] "" DAS + SG_ UI_radarEnableBraking : 17|1@1+ (1,0) [0|1] "" DAS + SG_ UI_radarMapDataCounter : 52|4@1+ (1,0) [0|0] "" DAS + SG_ UI_radarMapDataChecksum : 56|8@1+ (1,0) [0|0] "" DAS + +BO_ 712 UI_roadCurvature: 8 GTW + SG_ UI_roadCurvC0 : 0|11@1- (0.02,0) [-20.48|20.46] "m" DAS + SG_ UI_roadCurvC1 : 11|10@1- (0.00075,0) [-0.384|0.38325] "1" DAS + SG_ UI_roadCurvC2 : 21|14@1- (7.5E-06,0) [-0.03072|0.03071625] "1/m" DAS + SG_ UI_roadCurvC3 : 35|13@1- (3E-08,0) [-0.00012288|0.00012285] "1/m2" DAS + SG_ UI_roadCurvRange : 48|6@1+ (4,0) [0|252] "m" DAS + SG_ UI_roadCurvHealth : 54|2@1+ (1,0) [0|0] "" DAS + SG_ UI_roadCurvChecksum : 56|8@1+ (1,0) [0|0] "" Vector__XXX + +BO_ 582 UI_solarData: 5 GTW + SG_ UI_solarAzimuthAngle : 0|16@1- (1,0) [0|360] "deg" APP + SG_ UI_solarAzimuthAngleCarRef : 16|9@1- (1,0) [-180|180] "deg" APP + SG_ UI_isSunUp : 25|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_solarElevationAngle : 32|8@1- (1,0) [-90|90] "deg" APP + +BO_ 824 UI_status: 8 GTW + SG_ UI_touchActive : 0|1@1+ (1,0) [0|0] "" IC + SG_ UI_audioActive : 1|1@1+ (1,0) [0|0] "" IC + SG_ UI_bluetoothActive : 2|1@1+ (1,0) [0|0] "" IC + SG_ UI_cellActive : 3|1@1+ (1,0) [0|0] "" IC + SG_ UI_displayReady : 4|1@1+ (1,0) [0|0] "" IC + SG_ UI_gpsActive : 5|1@1+ (1,0) [0|0] "" IC + SG_ UI_wifiConnected : 6|1@1+ (1,0) [0|0] "" IC,APP + SG_ UI_systemActive : 7|1@1+ (1,0) [0|0] "" IC + SG_ UI_xmActive : 8|1@1+ (1,0) [0|0] "" IC + SG_ UI_displayOn : 9|1@1+ (1,0) [0|0] "" IC,APP + SG_ UI_readyForDrive : 10|1@1+ (1,0) [0|0] "" IC + SG_ UI_cellConnected : 11|1@1+ (1,0) [0|0] "" IC,APP + SG_ UI_vpnActive : 12|1@1+ (1,0) [0|0] "" IC,APP + SG_ UI_wifiActive : 13|1@1+ (1,0) [0|0] "" IC + SG_ UI_cameraActive : 14|1@1+ (1,0) [0|0] "" IC,APP + SG_ UI_usbActive : 15|1@1+ (1,0) [0|0] "" IC + SG_ UI_screenshotActive : 16|1@1+ (1,0) [0|0] "" IC,APP + SG_ UI_monitorModemPower : 17|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_factoryReset : 18|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ UI_cellNetworkTechnology : 20|4@1+ (1,0) [0|15] "" APP + SG_ UI_tegraCoreTemperature : 24|8@1+ (1,-64) [0|0] "deg C" IC + SG_ UI_tegraAmbientTemperature : 32|8@1+ (1,-64) [0|0] "deg C" IC + SG_ UI_googleWifiUsages : 40|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_autopilotTrial : 48|2@1+ (1,0) [0|0] "" APP + SG_ UI_cellSignalBars : 50|3@1+ (1,0) [0|7] "" APP + SG_ UI_hardwareType : 53|2@1+ (1,0) [0|3] "" APP + SG_ UI_developmentCar : 55|1@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_cellReceiverPower : 56|8@1+ (1,-128) [-128|127] "dB" APP + +BO_ 1064 UI_telemetryControl: 8 GTW + SG_ UI_TCR_enable : 0|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_moveStateStanding : 1|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_moveStateStopped : 2|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_moveStateMoving : 3|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_moveStateIndeterm : 4|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_classConstElem : 5|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_classMovingPed : 6|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_classMovingTwoWheel : 7|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_classMovingFourWheel : 8|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_classUnknown : 9|1@1+ (1,0) [0|0] "" DAS + SG_ UI_TCR_downSampleFactor : 16|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ UI_TCR_wExist : 24|5@1+ (1,0) [0|31] "" Vector__XXX + SG_ UI_TCR_vehSpeed : 32|8@1+ (1,0) [0|0] "" Vector__XXX + SG_ UI_TCR_minRCS : 40|8@1+ (0.25,-14) [-14|49.75] "dB" Vector__XXX + SG_ UI_TCR_maxDy : 48|5@1+ (0.5,0) [0|15.5] "m" Vector__XXX + SG_ UI_TCR_maxObjects : 56|5@1+ (1,0) [0|31] "" Vector__XXX + SG_ UI_TCR_maxRoadClass : 61|3@1+ (1,0) [0|7] "" Vector__XXX + +BO_ 522 BrakeMessage: 8 XXX + SG_ driverBrakeStatus : 2|2@1+ (1,0) [0|3] "" XXX + +BO_ 921 AutopilotStatus: 8 XXX + SG_ autopilotStatus : 0|4@1+ (1,0) [0|0] "" XXX + SG_ DAS_blindSpotRearLeft : 4|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_blindSpotRearRight : 6|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_fusedSpeedLimit : 8|5@1+ (5,0) [0|150] "kph/mph" XXX + SG_ DAS_suppressSpeedWarning : 13|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_summonObstacle : 14|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_summonClearedGate : 15|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_visionOnlySpeedLimit : 16|5@1+ (5,0) [0|150] "kph/mph" XXX + SG_ DAS_heaterState : 21|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_forwardCollisionWarning : 22|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_autoparkReady : 24|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_autoParked : 25|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_autoparkWaitingForBrake : 26|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_summonFwdLeashReached : 28|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_summonRvsLeashReached : 29|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_sideCollisionAvoid : 30|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_sideCollisionWarning : 32|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_sideCollisionInhibit : 34|1@1+ (1,0) [0|0] "" XXX + SG_ DAS_csaState : 35|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_laneDepartureWarning : 37|3@1+ (1,0) [0|0] "" XXX + SG_ DAS_fleetSpeedState : 40|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_autopilotHandsOnState : 42|4@1+ (1,0) [0|0] "" XXX + SG_ DAS_autoLaneChangeState : 46|5@1+ (1,0) [0|0] "" XXX + SG_ DAS_summonAvailable : 51|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_statusCounter : 52|4@1+ (1,0) [0|0] "" XXX + SG_ DAS_statusChecksum : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 905 DAS_status2: 8 XXX + SG_ DAS_accSpeedLimit : 0|10@1+ (0.2,0) [0|204.6] "mph" XXX + SG_ DAS_pmmObstacleSeverity : 10|3@1+ (1,0) [0|7] "" XXX + SG_ DAS_pmmLoggingRequest : 13|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_activationFailureStatus : 14|2@1+ (1,0) [0|1] "" XXX + SG_ DAS_pmmUltrasonicsFaultReason : 16|3@1+ (1,0) [0|7] "" XXX + SG_ DAS_pmmRadarFaultReason : 19|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_pmmSysFaultReason : 21|3@1+ (1,0) [0|7] "" XXX + SG_ DAS_pmmCameraFaultReason : 24|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_ACC_report : 26|5@1+ (1,0) [0|0] "" XXX + SG_ DAS_lssState : 31|3@1+ (1,0) [0|0] "" XXX + SG_ DAS_radarTelemetry : 34|2@1+ (1,0) [0|0] "" XXX + SG_ DAS_robState : 36|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_driverInteractionLevel : 38|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_ppOffsetDesiredRamp : 40|8@1+ (0.01,-1.28) [-1.28|1.27] "m" XXX + SG_ DAS_longCollisionWarning : 48|4@1+ (1,0) [0|15] "" XXX + SG_ DAS_status2Counter : 52|4@1+ (1,0) [0|0] "" XXX + SG_ DAS_status2Checksum : 56|8@1+ (1,0) [0|0] "" XXX + +BO_ 1001 DAS_bodyControls: 8 XXX + SG_ DAS_headlightRequest : 0|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_hazardLightRequest : 2|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_wiperSpeed : 4|4@1+ (1,0) [0|15] "" XXX + SG_ DAS_turnIndicatorRequest : 8|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_highLowBeamDecision : 10|2@1+ (1,0) [0|3] "" XXX + SG_ DAS_highLowBeamOffReason : 12|3@1+ (1,0) [0|4] "" XXX + SG_ DAS_turnIndicatorRequestReason : 16|4@1+ (1,0) [0|15] "" XXX + SG_ DAS_bodyControlsCounter : 52|4@1+ (1,0) [0|15] "" XXX + SG_ DAS_bodyControlsChecksum : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 780 DriverSeat: 8 XXX + SG_ occupancyStatus : 16|3@1+ (1,0) [0|7] "" XXX + SG_ buckleStatus : 19|2@1+ (1,0) [0|3] "" XXX + +VAL_ 3 StW_Angl 16383 "SNA" ; +VAL_ 3 StW_AnglSens_Id 2 "MUST" 0 "PSBL" 1 "SELF" ; +VAL_ 3 StW_AnglSens_Stat 2 "ERR" 3 "ERR_INI" 1 "INI" 0 "OK" ; +VAL_ 3 StW_AnglSpd 16383 "SNA" ; +VAL_ 14 StW_AnglHP 16383 "SNA" ; +VAL_ 14 StW_AnglHP_Spd 16383 "SNA" ; +VAL_ 14 StW_AnglHP_Sens_Stat 3 "SNA" 2 "ERR" 1 "INI" 0 "OK" ; +VAL_ 14 StW_AnglHP_Sens_Id 3 "SNA" 2 "KOSTAL" 1 "DELPHI" 0 "TEST" ; +VAL_ 69 SpdCtrlLvr_Stat 32 "DN_1ST" 16 "UP_1ST" 8 "DN_2ND" 4 "UP_2ND" 2 "RWD" 1 "FWD" 0 "IDLE" ; +VAL_ 69 DTR_Dist_Rq 255 "SNA" 200 "ACC_DIST_7" 166 "ACC_DIST_6" 133 "ACC_DIST_5" 100 "ACC_DIST_4" 66 "ACC_DIST_3" 33 "ACC_DIST_2" 0 "ACC_DIST_1" ; +VAL_ 69 TurnIndLvr_Stat 3 "SNA" 2 "RIGHT" 1 "LEFT" 0 "IDLE" ; +VAL_ 69 HiBmLvr_Stat 3 "SNA" 2 "HIBM_FLSH_ON_PSD" 1 "HIBM_ON_PSD" 0 "IDLE" ; +VAL_ 69 WprWashSw_Psd 3 "SNA" 2 "WASH" 1 "TIPWIPE" 0 "NPSD" ; +VAL_ 69 WprWash_R_Sw_Posn_V2 3 "SNA" 2 "WASH" 1 "INTERVAL" 0 "OFF" ; +VAL_ 69 StW_Lvr_Stat 4 "STW_BACK" 3 "STW_FWD" 2 "STW_DOWN" 1 "STW_UP" 0 "NPSD" ; +VAL_ 69 StW_Cond_Psd 3 "SNA" 2 "DOWN" 1 "UP" 0 "NPSD" ; +VAL_ 69 HrnSw_Psd 3 "SNA" 2 "NDEF2" 1 "PSD" 0 "NPSD" ; +VAL_ 69 StW_Sw00_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 69 StW_Sw01_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 69 StW_Sw03_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 69 StW_Sw04_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 69 WprSw6Posn 7 "SNA" 6 "STAGE2" 5 "STAGE1" 4 "INTERVAL4" 3 "INTERVAL3" 2 "INTERVAL2" 1 "INTERVAL1" 0 "OFF" ; +VAL_ 257 GTW_epasControlType 0 "WITHOUT" 1 "WITH_ANGLE" 3 "WITH_BOTH" 2 "WITH_TORQUE" ; +VAL_ 109 StW_Sw_Stat3 7 "SNA" 6 "NDEF6" 5 "NDEF5" 4 "NDEF4" 3 "PLUS_MINUS" 2 "MINUS" 1 "PLUS" 0 "NPSD" ; +VAL_ 109 MsgTxmtId 3 "NDEF3" 2 "NDEF2" 1 "SCCM" 0 "EWM" ; +VAL_ 109 TSL_RND_Posn_StW 15 "SNA" 8 "D" 6 "INI" 4 "N_DOWN" 2 "N_UP" 1 "R" 0 "IDLE" ; +VAL_ 109 TSL_P_Psd_StW 3 "SNA" 2 "INI" 1 "PSD" 0 "IDLE" ; +VAL_ 257 GTW_epasEmergencyOn 1 "EMERGENCY_POWER" 0 "NONE" ; +VAL_ 257 GTW_epasLDWEnabled 1 "ALLOWED" 0 "INHIBITED" ; +VAL_ 257 GTW_epasPowerMode 0 "DRIVE_OFF" 1 "DRIVE_ON" 3 "LOAD_SHED" 2 "SHUTTING_DOWN" 15 "SNA" ; +VAL_ 257 GTW_epasTuneRequest 1 "DM_COMFORT" 3 "DM_SPORT" 2 "DM_STANDARD" 0 "FAIL_SAFE_DEFAULT" 4 "RWD_COMFORT" 6 "RWD_SPORT" 5 "RWD_STANDARD" 7 "SNA" ; +VAL_ 264 DI_torqueDriver -4096 "SNA" ; +VAL_ 264 DI_torqueMotor -4096 "SNA" ; +VAL_ 264 DI_soptState 7 "SOPT_TEST_SNA" 4 "SOPT_TEST_NOT_RUN" 3 "SOPT_TEST_PASSED" 2 "SOPT_TEST_FAILED" 1 "SOPT_TEST_IN_PROGRESS" 0 "SOPT_PRE_TEST" ; +VAL_ 264 DI_motorRPM -32768 "SNA" ; +VAL_ 264 DI_pedalPos 255 "SNA" ; +VAL_ 280 DI_torqueEstimate -2048 "SNA" ; +VAL_ 280 DI_gear 7 "DI_GEAR_SNA" 4 "DI_GEAR_D" 3 "DI_GEAR_N" 2 "DI_GEAR_R" 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" ; +VAL_ 280 DI_brakePedal 1 "Applied" 0 "Not_applied" ; +VAL_ 280 DI_vehicleSpeed 4095 "SNA" ; +VAL_ 280 DI_gearRequest 7 "DI_GEAR_SNA" 4 "DI_GEAR_D" 3 "DI_GEAR_N" 2 "DI_GEAR_R" 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" ; +VAL_ 280 DI_torqueInterfaceFailure 1 "TORQUE_INTERFACE_FAILED" 0 "TORQUE_INTERFACE_NORMAL" ; +VAL_ 280 DI_brakePedalState 3 "SNA" 2 "INVALID" 1 "ON" 0 "OFF" ; +VAL_ 280 DI_epbParkRequest 1 "Park_requested" 0 "No_request" ; +VAL_ 280 DI_epbInterfaceReady 1 "EPB_INTERFACE_READY" 0 "EPB_INTERFACE_NOT_READY" ; +VAL_ 309 ESP_absBrakeEvent 1 "ACTIVE" 0 "NOT_ACTIVE" ; +VAL_ 309 ESP_brakeDiscWipingActive 1 "ACTIVE" 0 "INACTIVE" ; +VAL_ 309 ESP_brakeLamp 0 "OFF" 1 "ON" ; +VAL_ 309 ESP_espFaultLamp 0 "OFF" 1 "ON" ; +VAL_ 309 ESP_espLampFlash 1 "FLASH" 0 "OFF" ; +VAL_ 309 ESP_hillStartAssistActive 1 "ACTIVE" 0 "INACTIVE" 2 "NOT_AVAILABLE" 3 "SNA" ; +VAL_ 309 ESP_absFaultLamp 0 "OFF" 1 "ON" ; +VAL_ 309 ESP_espOffLamp 0 "OFF" 1 "ON" ; +VAL_ 309 ESP_stabilityControlSts 2 "ENGAGED" 3 "FAULTED" 5 "INIT" 4 "NOT_CONFIGURED" 0 "OFF" 1 "ON" ; +VAL_ 309 ESP_tcLampFlash 1 "FLASH" 0 "OFF" ; +VAL_ 568 UI_mapSpeedLimit 31 "SNA" 30 "UNLIMITED" 29 "LESS_OR_EQ_160" 28 "LESS_OR_EQ_150" 27 "LESS_OR_EQ_140" 26 "LESS_OR_EQ_130" 25 "LESS_OR_EQ_120" 24 "LESS_OR_EQ_115" 23 "LESS_OR_EQ_110" 22 "LESS_OR_EQ_105" 21 "LESS_OR_EQ_100" 20 "LESS_OR_EQ_95" 19 "LESS_OR_EQ_90" 18 "LESS_OR_EQ_85" 17 "LESS_OR_EQ_80" 16 "LESS_OR_EQ_75" 15 "LESS_OR_EQ_70" 14 "LESS_OR_EQ_65" 13 "LESS_OR_EQ_60" 12 "LESS_OR_EQ_55" 11 "LESS_OR_EQ_50" 10 "LESS_OR_EQ_45" 9 "LESS_OR_EQ_40" 8 "LESS_OR_EQ_35" 7 "LESS_OR_EQ_30" 6 "LESS_OR_EQ_25" 5 "LESS_OR_EQ_20" 4 "LESS_OR_EQ_15" 3 "LESS_OR_EQ_10" 2 "LESS_OR_EQ_7" 1 "LESS_OR_EQ_5" 0 "UNKNOWN" ; +VAL_ 569 DAS_leftLineUsage 3 "BLACKLISTED" 2 "FUSED" 1 "AVAILABLE" 0 "REJECTED_UNAVAILABLE" ; +VAL_ 569 DAS_rightLineUsage 3 "BLACKLISTED" 2 "FUSED" 1 "AVAILABLE" 0 "REJECTED_UNAVAILABLE" ; +VAL_ 569 DAS_leftFork 3 "LEFT_FORK_UNAVAILABLE" 2 "LEFT_FORK_SELECTED" 1 "LEFT_FORK_AVAILABLE" 0 "LEFT_FORK_NONE" ; +VAL_ 569 DAS_rightFork 3 "RIGHT_FORK_UNAVAILABLE" 2 "RIGHT_FORK_SELECTED" 1 "RIGHT_FORK_AVAILABLE" 0 "RIGHT_FORK_NONE" ; +VAL_ 521 DAS_locMode 3 "DAS_LOC_DRIVERLESS" 2 "DAS_LOC_RESTRICTED" 1 "DAS_LOC_NORMAL" 0 "DAS_LOC_OFF" ; +VAL_ 521 DAS_locState 7 "DAS_LOC_FAULT_SNA" 6 "DAS_LOC_AEB_ACTIVE" 2 "DAS_LOC_CANCEL_SILENT" 1 "DAS_LOC_CANCEL_GENERIC" 0 "DAS_LOC_HEALTHY" ; +VAL_ 521 DAS_locRequest 4 "DAS_RQ_PARK" 3 "DAS_RQ_HOLD" 2 "DAS_RQ_BACKWARD" 1 "DAS_RQ_FORWARD" 0 "DAS_RQ_IDLE" ; +VAL_ 521 DAS_locJerkMin 255 "SNA" ; +VAL_ 521 DAS_locJerkMax 255 "SNA" ; +VAL_ 521 DAS_locSpeed 2047 "SNA" ; +VAL_ 521 DAS_locAccelMin 511 "SNA" ; +VAL_ 521 DAS_locAccelMax 511 "SNA" ; +VAL_ 522 driverBrakeStatus 2 "APPLIED" 1 "NOT_APPLIED" ; +VAL_ 760 UI_mapSpeedLimitUnits 1 "KPH" 0 "MPH" ; +VAL_ 760 UI_userSpeedOffsetUnits 1 "KPH" 0 "MPH" ; +VAL_ 643 AirTemp_Insd 255 "SNA" ; +VAL_ 643 AirTemp_Outsd 254 "INIT" 255 "SNA" ; +VAL_ 643 Bckl_Sw_RL_Stat_SAM_R 2 "FLT" 1 "NOT" 0 "OK" 3 "SNA" ; +VAL_ 643 Bckl_Sw_RM_Stat_SAM_R 2 "FLT" 1 "NOT" 0 "OK" 3 "SNA" ; +VAL_ 643 Bckl_Sw_RR_Stat_SAM_R 2 "FLT" 1 "NOT" 0 "OK" 3 "SNA" ; +VAL_ 643 DL_RLtch_Stat 1 "CLS" 0 "NDEF0" 2 "OPN" 3 "SNA" ; +VAL_ 643 DrRLtch_FL_Stat 1 "CLS" 0 "NDEF0" 2 "OPN" 3 "SNA" ; +VAL_ 643 DrRLtch_FR_Stat 1 "CLS" 0 "NDEF0" 2 "OPN" 3 "SNA" ; +VAL_ 643 DrRLtch_RL_Stat 1 "CLS" 0 "NDEF0" 2 "OPN" 3 "SNA" ; +VAL_ 643 DrRLtch_RR_Stat 1 "CLS" 0 "NDEF0" 2 "OPN" 3 "SNA" ; +VAL_ 643 EngHd_Stat 1 "CLS" 0 "NDEF0" 2 "OPN" 3 "SNA" ; +VAL_ 643 LgtSens_Night 0 "DAY" 1 "NIGHT" ; +VAL_ 643 MPkBrk_Stat 1 "ENGG" 0 "RELS" ; +VAL_ 643 RevGr_Engg 0 "DISENGG" 1 "ENGG" 2 "NDEF2" 3 "SNA" ; +VAL_ 643 StW_Cond_Stat 3 "BLINK" 1 "NDEF1" 0 "OFF" 2 "ON" ; +VAL_ 643 Trlr_Stat 2 "NDEF2" 0 "NONE" 1 "OK" 3 "SNA" ; +VAL_ 697 DAS_setSpeed 4095 "SNA" ; +VAL_ 697 DAS_accState 15 "FAULT_SNA" 13 "ACC_CANCEL_GENERIC_SILENT" 11 "APC_SELFPARK_START" 10 "APC_UNPARK_COMPLETE" 9 "APC_PAUSE" 8 "APC_ABORT" 7 "APC_COMPLETE" 6 "APC_FORWARD" 5 "APC_BACKWARD" 4 "ACC_ON" 3 "ACC_HOLD" 0 "ACC_CANCEL_GENERIC" ; +VAL_ 697 DAS_aebEvent 3 "AEB_SNA" 2 "AEB_FAULT" 1 "AEB_ACTIVE" 0 "AEB_NOT_ACTIVE" ; +VAL_ 697 DAS_jerkMin 511 "SNA" ; +VAL_ 697 DAS_jerkMax 255 "SNA" ; +VAL_ 697 DAS_accelMin 511 "SNA" ; +VAL_ 697 DAS_accelMax 511 "SNA" ; +VAL_ 780 occupancyStatus 1 "OCCUPIED" 0 "UNOCCUPIED" ; +VAL_ 780 buckleStatus 1 "LATCHED" 0 "UNLATCHED" ; +VAL_ 792 BOOT_STATE 2 "Init" 3 "SNA" 0 "closed" 1 "open" ; +VAL_ 792 CERRD 1 "CAN error detect" 0 "no Can error detected" ; +VAL_ 792 DAY 1 "Init" 0 "SNA" ; +VAL_ 792 DOOR_STATE_FL 2 "Init" 3 "SNA" 0 "closed" 1 "open" ; +VAL_ 792 DOOR_STATE_FR 2 "Init" 3 "SNA" 0 "closed" 1 "open" ; +VAL_ 792 DOOR_STATE_FrontTrunk 2 "Init" 3 "SNA" 0 "closed" 1 "open" ; +VAL_ 792 DOOR_STATE_RL 2 "Init" 3 "SNA" 0 "closed" 1 "open" ; +VAL_ 792 DOOR_STATE_RR 2 "Init" 3 "SNA" 0 "closed" 1 "open" ; +VAL_ 792 GTW_updateInProgress 1 "IN_PROGRESS" 2 "IN_PROGRESS_NOT_USED" 3 "IN_PROGRESS_SNA" 0 "NOT_IN_PROGRESS" ; +VAL_ 792 Hour 30 "Init" 31 "SNA" ; +VAL_ 792 MCU_factoryMode 1 "FACTORY_MODE" 0 "NORMAL_MODE" ; +VAL_ 792 MCU_transportModeOn 0 "NORMAL_MODE" ; +VAL_ 792 MINUTE 62 "Init" 63 "SNA" ; +VAL_ 792 MONTH 1 "Init" 15 "SNA" ; +VAL_ 792 SECOND 62 "Init" 63 "SNA" ; +VAL_ 792 YEAR 126 "Init" 127 "SNA" ; +VAL_ 872 DI_aebState 2 "ENABLED" 4 "FAULT" 7 "SNA" 1 "STANDBY" 3 "STANDSTILL" 0 "UNAVAILABLE" ; +VAL_ 872 DI_analogSpeed 4095 "SNA" ; +VAL_ 872 DI_cruiseState 2 "ENABLED" 5 "FAULT" 0 "OFF" 4 "OVERRIDE" 7 "PRE_CANCEL" 6 "PRE_FAULT" 1 "STANDBY" 3 "STANDSTILL" ; +VAL_ 872 DI_digitalSpeed 255 "SNA" ; +VAL_ 872 DI_immobilizerState 2 "AUTHENTICATING" 3 "DISARMED" 6 "FAULT" 4 "IDLE" 0 "INIT_SNA" 1 "REQUEST" 5 "RESET" ; +VAL_ 872 DI_speedUnits 1 "KPH" 0 "MPH" ; +VAL_ 872 DI_state 3 "ABORT" 4 "ENABLE" 2 "FAULT" 1 "STANDBY" 0 "UNAVAILABLE" ; +VAL_ 872 DI_systemState 3 "ABORT" 4 "ENABLE" 2 "FAULT" 1 "STANDBY" 0 "UNAVAILABLE" ; +VAL_ 872 DI_vehicleHoldState 2 "BLEND_IN" 4 "BLEND_OUT" 6 "FAULT" 7 "INIT" 5 "PARK" 1 "STANDBY" 3 "STANDSTILL" 0 "UNAVAILABLE" ; +VAL_ 880 EPAS_currentTuneMode 1 "DM_COMFORT" 3 "DM_SPORT" 2 "DM_STANDARD" 0 "FAIL_SAFE_DEFAULT" 4 "RWD_COMFORT" 6 "RWD_SPORT" 5 "RWD_STANDARD" 7 "UNAVAILABLE" ; +VAL_ 880 EPAS_eacErrorCode 14 "EAC_ERROR_EPB_INHIBIT" 3 "EAC_ERROR_HANDS_ON" 7 "EAC_ERROR_HIGH_ANGLE_RATE_REQ" 9 "EAC_ERROR_HIGH_ANGLE_RATE_SAFETY" 6 "EAC_ERROR_HIGH_ANGLE_REQ" 8 "EAC_ERROR_HIGH_ANGLE_SAFETY" 10 "EAC_ERROR_HIGH_MMOT_SAFETY" 11 "EAC_ERROR_HIGH_TORSION_SAFETY" 0 "EAC_ERROR_IDLE" 12 "EAC_ERROR_LOW_ASSIST" 2 "EAC_ERROR_MAX_SPEED" 1 "EAC_ERROR_MIN_SPEED" 13 "EAC_ERROR_PINION_VEL_DIFF" 4 "EAC_ERROR_TMP_FAULT" 5 "EAR_ERROR_MAX_STEER_DELTA" 15 "SNA" ; +VAL_ 880 EPAS_eacStatus 2 "EAC_ACTIVE" 1 "EAC_AVAILABLE" 3 "EAC_FAULT" 0 "EAC_INHIBITED" 4 "SNA" ; +VAL_ 880 EPAS_handsOnLevel 0 "0" 1 "1" 2 "2" 3 "3" ; +VAL_ 880 EPAS_steeringFault 1 "FAULT" 0 "NO_FAULT" ; +VAL_ 880 EPAS_steeringRackForce 1022 "NOT_IN_SPEC" 1023 "SNA" ; +VAL_ 880 EPAS_steeringReduced 0 "NORMAL_ASSIST" 1 "REDUCED_ASSIST" ; +VAL_ 880 EPAS_torsionBarTorque 0 "SEE_SPECIFICATION" 4095 "SNA" 4094 "UNDEFINABLE_DATA" ; +VAL_ 904 MCU_clusterReadyForDrive 0 "NO_SNA" 1 "YES" ; +VAL_ 905 DAS_accSpeedLimit 1023 "SNA" 0 "NONE" ; +VAL_ 905 DAS_pmmObstacleSeverity 7 "PMM_SNA" 6 "PMM_ACCEL_LIMIT" 5 "PMM_CRASH_FRONT" 4 "PMM_CRASH_REAR" 3 "PMM_BRAKE_REQUEST" 2 "PMM_IMMINENT_FRONT" 1 "PMM_IMMINENT_REAR" 0 "PMM_NONE" ; +VAL_ 905 DAS_pmmLoggingRequest 1 "TRUE" 0 "FALSE" ; +VAL_ 905 DAS_activationFailureStatus 2 "LC_ACTIVATION_FAILED_2" 1 "LC_ACTIVATION_FAILED_1" 0 "LC_ACTIVATION_IDLE" ; +VAL_ 905 DAS_pmmUltrasonicsFaultReason 4 "PMM_ULTRASONICS_INVALID_MIA" 3 "PMM_ULTRASONICS_BLOCKED_BOTH" 2 "PMM_ULTRASONICS_BLOCKED_REAR" 1 "PMM_ULTRASONICS_BLOCKED_FRONT" 0 "PMM_ULTRASONICS_NO_FAULT" ; +VAL_ 905 DAS_pmmRadarFaultReason 2 "PMM_RADAR_INVALID_MIA" 1 "PMM_RADAR_BLOCKED_FRONT" 0 "PMM_RADAR_NO_FAULT" ; +VAL_ 905 DAS_pmmSysFaultReason 7 "PMM_FAULT_BRAKE_PEDAL_INHIBIT" 6 "PMM_FAULT_ROAD_TYPE" 5 "PMM_FAULT_DISABLED_BY_USER" 4 "PMM_FAULT_STEERING_ANGLE_RATE" 3 "PMM_FAULT_DI_FAULT" 2 "PMM_FAULT_SPEED" 1 "PMM_FAULT_DAS_DISABLED" 0 "PMM_FAULT_NONE" ; +VAL_ 905 DAS_pmmCameraFaultReason 2 "PMM_CAMERA_INVALID_MIA" 1 "PMM_CAMERA_BLOCKED_FRONT" 0 "PMM_CAMERA_NO_FAULT" ; +VAL_ 905 DAS_ACC_report 24 "ACC_REPORT_BEHAVIOR_REPORT" 23 "ACC_REPORT_CAMERA_ONLY" 22 "ACC_REPORT_RADAR_OBJ_FIVE" 21 "ACC_REPORT_CIPV_CUTTING_OUT" 20 "ACC_REPORT_MCVLR_IN_PATH" 19 "ACC_REPORT_MCVLR_DPP" 18 "ACC_REPORT_FLEET_SPEEDS" 17 "ACC_REPORT_TARGET_MCP" 16 "ACC_REPORT_RADAR_OBJ_TWO" 15 "ACC_REPORT_RADAR_OBJ_ONE" 14 "ACC_REPORT_LC_EXTERNAL_STATE_ACTIVE_RESTRICTED" 13 "ACC_REPORT_LC_EXTERNAL_STATE_ABORTED" 12 "ACC_REPORT_LC_EXTERNAL_STATE_ABORTING" 11 "ACC_REPORT_LC_HANDS_ON_REQD_STRUCK_OUT" 10 "ACC_REPORT_CSA" 9 "ACC_REPORT_TARGET_TYPE_FAULT" 8 "ACC_REPORT_TARGET_TYPE_IPSO" 7 "ACC_REPORT_TARGET_TYPE_TRAFFIC_LIGHT" 6 "ACC_REPORT_TARGET_TYPE_STOP_SIGN" 5 "ACC_REPORT_TARGET_CUTIN" 4 "ACC_REPORT_TARGET_MCVR" 3 "ACC_REPORT_TARGET_MCVL" 2 "ACC_REPORT_TARGET_IN_FRONT_OF_CIPV" 1 "ACC_REPORT_TARGET_CIPV" 0 "ACC_REPORT_TARGET_NONE" ; +VAL_ 905 DAS_lssState 7 "LSS_STATE_OFF" 6 "LSS_STATE_ABORT" 5 "LSS_STATE_BLINDSPOT" 4 "LSS_STATE_MONITOR" 3 "LSS_STATE_ELK" 2 "LSS_STATE_LKA" 1 "LSS_STATE_LDW" 0 "LSS_STATE_FAULT" ; +VAL_ 905 DAS_radarTelemetry 2 "RADAR_TELEMETRY_URGENT" 1 "RADAR_TELEMETRY_NORMAL" 0 "RADAR_TELEMETRY_IDLE" ; +VAL_ 905 DAS_robState 3 "ROB_STATE_MAPLESS" 2 "ROB_STATE_ACTIVE" 1 "ROB_STATE_MEASURE" 0 "ROB_STATE_INHIBITED" ; +VAL_ 905 DAS_driverInteractionLevel 2 "CONTINUED_DRIVER_NOT_INTERACTING" 1 "DRIVER_NOT_INTERACTING" 0 "DRIVER_INTERACTING" ; +VAL_ 905 DAS_ppOffsetDesiredRamp 128 "PP_NO_OFFSET" ; +VAL_ 905 DAS_longCollisionWarning 15 "FCM_LONG_COLLISION_WARNING_SNA" 12 "FCM_LONG_COLLISION_WARNING_VEHICLE_CIPV2" 11 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVR2" 10 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVR" 9 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVL2" 8 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVL" 7 "FCM_LONG_COLLISION_WARNING_VEHICLE_CUTIN" 6 "FCM_LONG_COLLISION_WARNING_VEHICLE_CIPV" 5 "FCM_LONG_COLLISION_WARNING_TFL_STOPLINE" 4 "FCM_LONG_COLLISION_WARNING_STOPSIGN_STOPLINE" 3 "FCM_LONG_COLLISION_WARNING_IPSO" 2 "FCM_LONG_COLLISION_WARNING_PEDESTRIAN" 1 "FCM_LONG_COLLISION_WARNING_VEHICLE_UNKNOWN" 0 "FCM_LONG_COLLISION_WARNING_NONE" ; +VAL_ 921 autopilotStatus 5 "ACTIVE_NAVIGATE_ON_AUTOPILOT" 4 "ACTIVE_2" 3 "ACTIVE_1" 2 "AVAILABLE" 1 "UNAVAILABLE" 0 "DISABLED" ; +VAL_ 921 DAS_blindSpotRearLeft 3 "SNA" 2 "WARNING_LEVEL_2" 1 "WARNING_LEVEL_1" 0 "NO_WARNING" ; +VAL_ 921 DAS_blindSpotRearRight 3 "SNA" 2 "WARNING_LEVEL_2" 1 "WARNING_LEVEL_1" 0 "NO_WARNING" ; +VAL_ 921 DAS_fusedSpeedLimit 31 "NONE" 0 "UNKNOWN_SNA" ; +VAL_ 921 DAS_suppressSpeedWarning 1 "Suppress_Speed_Warning" 0 "Do_Not_Suppress" ; +VAL_ 921 DAS_visionOnlySpeedLimit 31 "NONE" 0 "UNKNOWN_SNA" ; +VAL_ 921 DAS_heaterState 1 "HEATER_ON" 0 "HEATER_OFF_SNA" ; +VAL_ 921 DAS_forwardCollisionWarning 3 "SNA" 1 "FORWARD_COLLISION_WARNING" 0 "NONE" ; +VAL_ 921 DAS_autoparkReady 1 "AUTOPARK_READY" 0 "AUTOPARK_UNAVAILABLE" ; +VAL_ 921 DAS_sideCollisionAvoid 3 "SNA" 2 "AVOID_RIGHT" 1 "AVOID_LEFT" 0 "NONE" ; +VAL_ 921 DAS_sideCollisionWarning 3 "WARN_LEFT_RIGHT" 2 "WARN_RIGHT" 1 "WARN_LEFT" 0 "NONE" ; +VAL_ 921 DAS_sideCollisionInhibit 1 "INHIBIT" 0 "NO_INHIBIT" ; +VAL_ 921 DAS_csaState 3 "CSA_EXTERNAL_STATE_HOLD" 2 "CSA_EXTERNAL_STATE_ENABLE" 1 "CSA_EXTERNAL_STATE_AVAILABLE" 0 "CSA_EXTERNAL_STATE_UNAVAILABLE" ; +VAL_ 921 DAS_laneDepartureWarning 5 "SNA" 4 "RIGHT_WARNING_SEVERE" 3 "LEFT_WARNING_SEVERE" 2 "RIGHT_WARNING" 1 "LEFT_WARNING" 0 "NONE" ; +VAL_ 921 DAS_fleetSpeedState 3 "FLEETSPEED_HOLD" 2 "FLEETSPEED_ACTIVE" 1 "FLEETSPEED_AVAILABLE" 0 "FLEETSPEED_UNAVAILABLE" ; +VAL_ 921 DAS_autopilotHandsOnState 15 "LC_HANDS_ON_SNA" 8 "LC_HANDS_ON_SUSPENDED" 7 "LC_HANDS_ON_REQD_STRUCK_OUT" 5 "LC_HANDS_ON_REQD_CHIME_2" 4 "LC_HANDS_ON_REQD_CHIME_1" 3 "LC_HANDS_ON_REQD_VISUAL" 2 "LC_HANDS_ON_REQD_NOT_DETECTED" 1 "LC_HANDS_ON_REQD_DETECTED" 0 "LC_HANDS_ON_NOT_REQD" ; +VAL_ 921 DAS_autoLaneChangeState 31 "ALC_SNA" 30 "ALC_ABORT_MISSION_PLAN_INVALID" 29 "ALC_ABORT_TIMEOUT" 28 "ALC_WAITING_HANDS_ON" 27 "ALC_BLOCKED_LANE_TYPE_R" 26 "ALC_BLOCKED_LANE_TYPE_L" 25 "ALC_BLOCKED_VEH_TTC_AND_USS_R" 24 "ALC_BLOCKED_VEH_TTC_R" 23 "ALC_BLOCKED_VEH_TTC_AND_USS_L" 22 "ALC_BLOCKED_VEH_TTC_L" 21 "ALC_UNAVAILABLE_SOLID_LANE_LINE" 20 "ALC_ABORT_OTHER_REASON" 19 "ALC_ABORT_BLINKER_TURNED_OFF" 18 "ALC_ABORT_LC_HEALTH_BAD" 17 "ALC_ABORT_POOR_VIEW_RANGE" 16 "ALC_ABORT_SIDE_OBSTACLE_PRESENT_R" 15 "ALC_ABORT_SIDE_OBSTACLE_PRESENT_L" 14 "ALC_WAITING_FOR_FWD_OBST_TO_PASS_R" 13 "ALC_WAITING_FOR_FWD_OBST_TO_PASS_L" 12 "ALC_WAITING_FOR_SIDE_OBST_TO_PASS_R" 11 "ALC_WAITING_FOR_SIDE_OBST_TO_PASS_L" 10 "ALC_IN_PROGRESS_R" 9 "ALC_IN_PROGRESS_L" 8 "ALC_AVAILABLE_BOTH" 7 "ALC_AVAILABLE_ONLY_R" 6 "ALC_AVAILABLE_ONLY_L" 5 "ALC_UNAVAILABLE_VEHICLE_SPEED" 4 "ALC_UNAVAILABLE_EXITING_HIGHWAY" 3 "ALC_UNAVAILABLE_TP_FOLLOW" 2 "ALC_UNAVAILABLE_SONICS_INVALID" 1 "ALC_UNAVAILABLE_NO_LANES" 0 "ALC_UNAVAILABLE_DISABLED" ; +VAL_ 1001 DAS_headlightRequest 3 "DAS_HEADLIGHT_REQUEST_INVALID" 1 "DAS_HEADLIGHT_REQUEST_ON" 0 "DAS_HEADLIGHT_REQUEST_OFF" ; +VAL_ 1001 DAS_hazardLightRequest 3 "DAS_REQUEST_HAZARDS_SNA" 2 "DAS_REQUEST_HAZARDS_UNUSED" 1 "DAS_REQUEST_HAZARDS_ON" 0 "DAS_REQUEST_HAZARDS_OFF" ; +VAL_ 1001 DAS_wiperSpeed 15 "DAS_WIPER_SPEED_INVALID" 14 "DAS_WIPER_SPEED_14" 13 "DAS_WIPER_SPEED_13" 12 "DAS_WIPER_SPEED_12" 11 "DAS_WIPER_SPEED_11" 10 "DAS_WIPER_SPEED_10" 9 "DAS_WIPER_SPEED_9" 8 "DAS_WIPER_SPEED_8" 7 "DAS_WIPER_SPEED_7" 6 "DAS_WIPER_SPEED_6" 5 "DAS_WIPER_SPEED_5" 4 "DAS_WIPER_SPEED_4" 3 "DAS_WIPER_SPEED_3" 2 "DAS_WIPER_SPEED_2" 1 "DAS_WIPER_SPEED_1" 0 "DAS_WIPER_SPEED_OFF" ; +VAL_ 1001 DAS_turnIndicatorRequest 3 "DAS_TURN_INDICATOR_CANCEL" 2 "DAS_TURN_INDICATOR_RIGHT" 1 "DAS_TURN_INDICATOR_LEFT" 0 "DAS_TURN_INDICATOR_NONE" ; +VAL_ 1001 DAS_highLowBeamDecision 3 "DAS_HIGH_BEAM_SNA" 2 "DAS_HIGH_BEAM_ON" 1 "DAS_HIGH_BEAM_OFF" 0 "DAS_HIGH_BEAM_UNDECIDED" ; +VAL_ 1001 DAS_highLowBeamOffReason 5 "HIGH_BEAM_OFF_REASON_SNA" 4 "HIGH_BEAM_OFF_REASON_HEAD_LIGHT" 3 "HIGH_BEAM_OFF_REASON_AMBIENT_LIGHT" 2 "HIGH_BEAM_OFF_REASON_MOVING_RADAR_TARGET" 1 "HIGH_BEAM_OFF_REASON_MOVING_VISION_TARGET" 0 "HIGH_BEAM_ON" ; +VAL_ 1001 DAS_turnIndicatorRequestReason 6 "DAS_ACTIVE_COMMANDED_LANE_CHANGE" 5 "DAS_CANCEL_FORK" 4 "DAS_CANCEL_LANE_CHANGE" 3 "DAS_ACTIVE_FORK" 2 "DAS_ACTIVE_SPEED_LANE_CHANGE" 1 "DAS_ACTIVE_NAV_LANE_CHANGE" 0 "DAS_NONE" ; +VAL_ 1160 DAS_steeringAngleRequest 16384 "ZERO_ANGLE" ; +VAL_ 1160 DAS_steeringControlType 1 "ANGLE_CONTROL" 3 "DISABLED" 0 "NONE" 2 "RESERVED" ; +VAL_ 1160 DAS_steeringHapticRequest 1 "ACTIVE" 0 "IDLE" ; + + diff --git a/opendbc_repo/opendbc/dbc/tesla_model3_party.dbc b/opendbc_repo/opendbc/dbc/tesla_model3_party.dbc new file mode 100644 index 0000000000..5fd94c2008 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/tesla_model3_party.dbc @@ -0,0 +1,488 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: CH DIPF DIPR ETH FC HVI HVS PARTY SDCV VEH VIRT + + +BO_ 905 DAS_status2: 8 PARTY + SG_ DAS_status2Checksum : 56|8@1+ (1,0) [0|255] "" aps + SG_ DAS_status2Counter : 52|4@1+ (1,0) [0|15] "" aps + SG_ DAS_longCollisionWarning : 48|4@1+ (1,0) [0|15] "" aps + SG_ DAS_ppOffsetDesiredRamp : 40|8@1+ (0.01,-1.28) [-1.28|1.27] "m" aps + SG_ DAS_driverInteractionLevel : 38|2@1+ (1,0) [0|2] "" aps + SG_ DAS_robState : 36|2@1+ (1,0) [0|3] "" aps + SG_ DAS_radarTelemetry : 34|2@1+ (1,0) [0|2] "" aps + SG_ DAS_lssState : 31|3@1+ (1,0) [0|7] "" aps + SG_ DAS_ACC_report : 26|5@1+ (1,0) [0|24] "" aps + SG_ DAS_pmmCameraFaultReason : 24|2@1+ (1,0) [0|2] "" aps + SG_ DAS_pmmSysFaultReason : 21|3@1+ (1,0) [0|7] "" aps + SG_ DAS_pmmRadarFaultReason : 19|2@1+ (1,0) [0|2] "" aps + SG_ DAS_pmmUltrasonicsFaultReason : 16|3@1+ (1,0) [0|4] "" aps + SG_ DAS_activationFailureStatus : 14|2@1+ (1,0) [0|2] "" aps + SG_ DAS_pmmLoggingRequest : 13|1@1+ (1,0) [0|1] "" aps + SG_ DAS_pmmObstacleSeverity : 10|3@1+ (1,0) [0|7] "" aps + SG_ DAS_accSpeedLimit : 0|10@1+ (0.4,0) [0|204.6] "mph" aps + +BO_ 264 DI_torque: 8 PARTY + SG_ DI_axleSpeed : 40|16@1- (0.1,0.0) [-2750|2750] "RPM" epas3s + SG_ DI_torqueActual : 27|13@1- (2,0) [-7500|7500] "Nm" X + SG_ DI_torqueCommand : 12|13@1- (2,0) [-7500|7500] "Nm" X + SG_ DI_torqueCounter : 8|4@1+ (1,0) [0|15] "" epas3s + SG_ DI_torqueChecksum : 0|8@1+ (1,0) [0|255] "" epas3s + +BO_ 585 SCCM_leftStalk: 3 PARTY + SG_ SCCM_leftStalkReserved1 : 19|5@1+ (1,0) [0|31] "" X + SG_ SCCM_turnIndicatorStalkStatus : 16|3@1+ (1,0) [0|5] "" park + SG_ SCCM_washWipeButtonStatus : 14|2@1+ (1,0) [0|3] "" X + SG_ SCCM_highBeamStalkStatus : 12|2@1+ (1,0) [0|3] "" X + SG_ SCCM_leftStalkCounter : 8|4@1+ (1,0) [0|15] "" X + SG_ SCCM_leftStalkCrc : 0|8@1+ (1,0) [0|255] "" X + +BO_ 280 DI_systemStatus: 8 PARTY + SG_ DI_trackModeState : 48|2@1+ (1,0) [0|2] "" X + SG_ DI_keepAliveRequest : 47|1@1+ (1,0) [0|1] "" X + SG_ DI_proximity : 46|1@1+ (1,0) [0|1] "" X + SG_ DI_epbRequest : 44|2@1+ (1,0) [0|2] "" X + SG_ DI_tractionControlMode : 40|3@1+ (1,0) [0|5] "" X + SG_ DI_accelPedalPos : 32|8@1+ (0.4,0) [0|100] "%" X + SG_ DI_immobilizerState : 27|3@1+ (1,0) [0|6] "" X + SG_ DI_regenLight : 26|1@1+ (1,0) [0|1] "" X + SG_ DI_gear : 21|3@1+ (1,0) [0|7] "" park + SG_ DI_brakePedalState : 19|2@1+ (1,0) [0|2] "" X + SG_ DI_systemState : 16|3@1+ (1,0) [0|5] "" X + SG_ DI_systemStatusCounter : 8|4@1+ (1,0) [0|15] "" X + SG_ DI_systemStatusChecksum : 0|8@1+ (1,0) [0|255] "" X + +BO_ 697 DAS_control: 8 PARTY + SG_ DAS_controlChecksum : 56|8@1+ (1,0) [0|255] "" aps + SG_ DAS_controlCounter : 53|3@1+ (1,0) [0|7] "" aps + SG_ DAS_accelMax : 44|9@1+ (0.04,-15) [-15|5.44] "m/s^2" aps + SG_ DAS_accelMin : 35|9@1+ (0.04,-15) [-15|5.44] "m/s^2" aps + SG_ DAS_jerkMax : 27|8@1+ (0.034,0) [0|8.67] "m/s^3" aps + SG_ DAS_jerkMin : 18|9@1+ (0.018,-9.1) [-9.1|0.097999999999999] "m/s^3" aps + SG_ DAS_aebEvent : 16|2@1+ (1,0) [0|3] "" aps + SG_ DAS_accState : 12|4@1+ (1,0) [0|15] "" aps + SG_ DAS_setSpeed : 0|12@1+ (0.1,0) [0|409.4] "kph" aps + +BO_ 341 ESP_B: 8 PARTY + SG_ ESP_wheelRotationChecksum : 56|8@1+ (1,0) [0|255] "" app + SG_ ESP_wheelRotationCounter : 52|4@1+ (1,0) [0|15] "" app + SG_ ESP_vehicleSpeed : 42|10@1+ (0.5,0) [0|511] "kph" app + SG_ ESP_vehicleStandstillSts : 41|1@1+ (1,0) [0|1] "" park + SG_ ESP_wheelSpeedsQF : 40|1@1+ (1,0) [0|1] "" epas3s + SG_ ESP_WheelRotationFrL : 38|2@1+ (1,0) [0|3] "" aps + SG_ ESP_WheelRotationFrR : 36|2@1+ (1,0) [0|3] "" aps + SG_ ESP_WheelRotationReL : 34|2@1+ (1,0) [0|3] "" aps + SG_ ESP_WheelRotationReR : 32|2@1+ (1,0) [0|3] "" aps + SG_ ESP_wheelPulseCountReR : 24|8@1+ (1,0) [0|254] "1" das + SG_ ESP_wheelPulseCountReL : 16|8@1+ (1,0) [0|254] "1" das + SG_ ESP_wheelPulseCountFrR : 8|8@1+ (1,0) [0|254] "1" app + SG_ ESP_wheelPulseCountFrL : 0|8@1+ (1,0) [0|254] "1" app + +BO_ 373 ESP_wheelSpeeds: 8 CH + SG_ ESP_wheelSpeedsChecksum : 56|8@1+ (1,0) [0|255] "" das + SG_ ESP_wheelSpeedsCounter : 52|4@1+ (1,0) [0|15] "" das + SG_ ESP_wheelSpeedReR : 39|13@1+ (0.04,0) [0|327.64] "km/h" das + SG_ ESP_wheelSpeedReL : 26|13@1+ (0.04,0) [0|327.64] "km/h" das + SG_ ESP_wheelSpeedFrR : 13|13@1+ (0.04,0) [0|327.64] "km/h" das + SG_ ESP_wheelSpeedFrL : 0|13@1+ (0.04,0) [0|327.64] "km/h" das + +BO_ 969 APS_status: 4 PARTY + SG_ APS_statusCounter : 22|4@1+ (1,0) [0|15] "" X + SG_ APS_apbGpioState : 20|2@1+ (1,0) [0|3] "" gtw + SG_ APS_apbStatusMonitorState : 16|3@1+ (1,0) [0|7] "" gtw + SG_ APS_switchState : 15|1@1+ (1,0) [0|1] "" X + SG_ APS_eacInternalState : 12|3@1+ (1,0) [0|7] "" gtw + SG_ APS_appGpioState : 10|2@1+ (1,0) [0|3] "" gtw + SG_ APS_canMaster : 8|2@1+ (1,0) [0|3] "" gtw + SG_ APS_vehBehaviorState : 4|3@1+ (1,0) [0|7] "" gtw + SG_ APS_appStatusMonitorState : 0|3@1+ (1,0) [0|7] "" gtw + +BO_ 925 IBST_status: 5 PARTY + SG_ IBST_sInputRodDriver : 21|12@1+ (0.015625,-5) [-5|47] "mm" gtw + SG_ IBST_internalState : 18|3@1+ (1,0) [0|6] "" gtw + SG_ IBST_driverBrakeApply : 16|2@1+ (1,0) [0|3] "" gtw + SG_ IBST_iBoosterStatus : 12|3@1+ (1,0) [0|6] "" gtw + SG_ IBST_statusCounter : 8|4@1+ (1,0) [0|15] "" X + SG_ IBST_statusChecksum : 0|8@1+ (1,0) [0|255] "" X + +BO_ 880 EPAS3S_sysStatus: 8 PARTY + SG_ EPAS3S_sysStatusChecksum : 56|8@1+ (1,0) [0|255] "" park + SG_ EPAS3S_sysStatusCounter : 48|4@1+ (1,0) [0|15] "" gtw + SG_ EPAS3S_eacStatus : 55|3@0+ (1,0) [0|7] "" das + SG_ EPAS3S_internalSAS : 37|14@0+ (0.1,-819.2) [-819.2|819] "deg" das + SG_ EPAS3S_handsOnLevel : 39|2@0+ (1,0) [0|3] "" das + SG_ EPAS3S_torsionBarTorque : 19|12@0+ (0.01,-20.5) [-20.5|20.45] "Nm" das + SG_ EPAS3S_eacErrorCode : 23|4@0+ (1,0) [0|15] "" das + SG_ EPAS3S_steeringRackForce : 1|10@0+ (50,-25575) [-25575|25575] "N" gtw + SG_ EPAS3S_steeringFault : 2|1@0+ (1,0) [0|1] "" das + SG_ EPAS3S_steeringReduced : 3|1@0+ (1,0) [0|1] "" das + SG_ EPAS3S_internalSASQF : 4|1@0+ (1,0) [0|1] "" gtw + SG_ EPAS3S_currentTuneMode : 7|3@0+ (1,0) [0|5] "" gtw + +BO_ 637 APS_eacMonitor: 3 PARTY + SG_ APS_eacAllow : 0|2@1+ (1,0) [0|0] "" X + SG_ APS_eacMonitorChecksum : 16|8@1+ (1,0) [0|0] "" X + SG_ APS_eacMonitorCounter : 8|4@1+ (1,0) [0|0] "" X + +BO_ 545 VCFRONT_LVPowerState: 8 CH + SG_ VCFRONT_LVPowerStateChecksum : 56|8@1+ (1,0) [0|255] "" ibst + SG_ VCFRONT_LVPowerStateCounter : 52|4@1+ (1,0) [0|15] "" ibst + SG_ VCFRONT_uiAudioLVState m0 : 50|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_uiHiCurrentLVState m0 : 48|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_vcrightHiCurrentLVState m0 : 46|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_vcleftHiCurrentLVState m0 : 44|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_ocsLVRequest m0 : 42|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_oilPumpRearLVRequest m0 : 40|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_oilPumpFrontLVState m0 : 38|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_disLVState m0 : 36|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_diLVRequest m0 : 34|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_das2HighCurrentLVState m0 : 32|2@1+ (1,0) [0|3] "" das + SG_ VCFRONT_das1HighCurrentLVState m0 : 30|2@1+ (1,0) [0|3] "" das + SG_ VCFRONT_amplifierLVRequest m0 : 28|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_tunerLVRequest m0 : 26|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_iBoosterLVState m0 : 24|2@1+ (1,0) [0|3] "" ibst + SG_ VCFRONT_rcmLVRequest m0 : 22|2@1+ (1,0) [0|3] "" rcm + SG_ VCFRONT_tpmsLVRequest m0 : 20|2@1+ (1,0) [0|3] "" tpms + SG_ VCFRONT_sccmLVRequest m0 : 18|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_pcsLVState m1 : 16|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_ptcLVRequest m0 : 16|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_hvacCompLVState m0 : 14|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_tasLVState m1 : 14|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_hvcLVRequest m1 : 12|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_radcLVState m0 : 12|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_epasLVState m1 : 10|2@1+ (1,0) [0|3] "" epas3s + SG_ VCFRONT_espLVState m0 : 10|2@1+ (1,0) [0|3] "" ibst + SG_ VCFRONT_parkLVState m0 : 8|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_cpLVRequest m1 : 8|2@1+ (1,0) [0|3] "" X + SG_ VCFRONT_vehiclePowerState : 5|2@1+ (1,0) [0|3] "" park + SG_ VCFRONT_LVPowerStateIndex M : 0|5@1+ (1,0) [0|1] "" epas3s + +BO_ 599 DI_speed: 8 PARTY + SG_ DI_uiSpeedUnits : 32|1@1+ (1,0) [0|1] "" das + SG_ DI_uiSpeed : 24|8@1+ (1,0) [0|254] "" das + SG_ DI_vehicleSpeed : 12|12@1+ (0.08,-40) [-40|285] "kph" park + SG_ DI_speedCounter : 8|4@1+ (1,0) [0|15] "" park + SG_ DI_speedChecksum : 0|8@1+ (1,0) [0|255] "" park + +BO_ 605 DAS_road: 6 XXX + SG_ DAS_stopLineDist : 16|8@1+ (0.5,0) [0|127.5] "m" XXX + SG_ DAS_trafficLightColor : 26|3@0+ (1,0) [0|7] "" XXX + +BO_ 1160 DAS_steeringControl: 4 PARTY + SG_ DAS_steeringControlChecksum : 24|8@1+ (1,0) [0|255] "" aps + SG_ DAS_steeringControlCounter : 16|4@1+ (1,0) [0|15] "" aps + SG_ DAS_steeringControlType : 23|2@0+ (1,0) [0|3] "" aps + SG_ DAS_steeringAngleRequest : 6|15@0+ (0.1,-1638.35) [-1638.35|1638.35] "deg" aps + SG_ DAS_steeringHapticRequest : 7|1@0+ (1,0) [0|1] "" aps + +BO_ 297 SCCM_steeringAngleSensor: 8 PARTY + SG_ SCCM_steeringAngleSensorReservd3 : 56|8@1+ (1,0) [0|255] "" X + SG_ SCCM_steeringAngleSensorReservd2 : 48|8@1+ (1,0) [0|255] "" X + SG_ SCCM_steeringAngleSensorReservd1 : 46|2@1+ (1,0) [0|3] "" X + SG_ SCCM_steeringAngleSpeed : 32|14@1+ (0.5,-4096) [-4096|4095.5] "deg/s" park + SG_ SCCM_steeringAngleValidity : 30|2@1+ (1,0) [0|3] "" park + SG_ SCCM_steeringAngle : 16|14@1+ (0.1,-819.2) [-819.2|819] "deg" epas3s + SG_ SCCM_steeringAngleSensorStatus : 14|2@1+ (1,0) [0|3] "" epas3s + SG_ SCCM_supplierID : 12|2@1+ (1,0) [0|3] "" park + SG_ SCCM_steeringAngleCounter : 8|4@1+ (1,0) [0|15] "" epas3s + SG_ SCCM_steeringAngleCrc : 0|8@1+ (1,0) [0|255] "" epas3s + +BO_ 646 DI_state: 8 ETH + SG_ DI_summonInPanic : 48|1@1+ (1,0) [0|0] "" X + SG_ DI_rollPreventionState : 45|3@1+ (1,0) [0|0] "" X + SG_ DI_vehicleHoldState : 42|3@1+ (1,0) [0|0] "" X + SG_ DI_pmmStatus : 40|2@1+ (1,0) [0|0] "" X + SG_ DI_aebState : 37|3@1+ (1,0) [0|0] "" X + SG_ DI_autopilotRequest : 36|1@1+ (1,0) [0|0] "" X + SG_ DI_parkBrakeState : 32|4@1+ (1,0) [0|0] "" X + SG_ DI_autoparkState : 25|4@1+ (1,0) [0|0] "" X + SG_ DI_speedUnits : 24|1@1+ (1,0) [0|0] "" X + SG_ DI_digitalSpeed : 15|9@1+ (0.5,0) [0|0] "speed" X + SG_ DI_cruiseState : 12|3@1+ (1,0) [0|0] "" X + SG_ DI_locStatusCounter : 8|4@1+ (1,0) [0|0] "" X + SG_ DI_locStatusChecksum : 0|8@1+ (1,0) [0|0] "" X + +BO_ 659 DAS_settings: 8 XXX + SG_ DAS_driverSteeringWeight : 1|2@0+ (1,0) [0|255] "" XXX + SG_ DAS_slipStart : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DAS_offRoadAssist : 3|2@1+ (1,0) [0|63] "" XXX + SG_ DAS_distanceUnits : 13|1@1+ (1,0) [0|255] "" XXX + SG_ DAS_aebEnabled : 18|1@0+ (1,0) [0|255] "" XXX + SG_ DAS_adaptiveHeadlights : 22|1@1+ (1,0) [0|31] "" XXX + SG_ DAS_autosteerEnabled2 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ DAS_fcwEnabled : 34|1@0+ (1,0) [0|1] "" XXX + SG_ DAS_fcwSensitivity : 37|2@0+ (1,0) [0|63] "" XXX + SG_ DAS_autosteerEnabled : 38|1@0+ (1,0) [0|1] "" XXX + SG_ DAS_obstacleAwareAcceleration : 42|1@0+ (1,0) [0|1] "" XXX + SG_ DAS_driverAccelerationMode : 44|1@1+ (1,0) [0|127] "" XXX + SG_ DAS_settingCounter : 52|4@1+ (1,0) [0|15] "" XXX + SG_ DAS_settingChecksum : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 785 UI_warning: 7 XXX + SG_ buckleStatus : 13|1@0+ (1,0) [0|1] "" XXX + SG_ scrollWheelPressed : 21|1@0+ (1,0) [0|1] "" XXX + SG_ leftBlinkerOn : 22|1@0+ (1,0) [0|1] "" XXX + SG_ rightBlinkerOn : 23|1@0+ (1,0) [0|1] "" XXX + SG_ leftBlinkerBlinking : 25|2@0+ (1,0) [0|3] "" XXX + SG_ rightBlinkerBlinking : 26|2@1+ (1,0) [0|15] "" XXX + SG_ anyDoorOpen : 28|1@0+ (1,0) [0|1] "" XXX + SG_ wiperSettings : 39|8@0+ (1,0) [0|255] "" XXX + SG_ highBeam : 50|1@0+ (1,0) [0|1] "" XXX + SG_ UI_warningCounter : 8|4@1+ (1,0) [0|15] "" XXX + SG_ UI_warningChecksum : 0|8@1+ (1,0) [0|255] "" XXX + +BO_ 923 DAS_status: 8 PARTY + SG_ DAS_statusChecksum : 56|8@1+ (1,0) [0|255] "" aps + SG_ DAS_statusCounter : 52|4@1+ (1,0) [0|15] "" aps + SG_ DAS_summonAvailable : 51|1@1+ (1,0) [0|1] "" aps + SG_ DAS_autoLaneChangeState : 46|5@1+ (1,0) [0|31] "" aps + SG_ DAS_autopilotHandsOnState : 42|4@1+ (1,0) [0|15] "" aps + SG_ DAS_fleetSpeedState : 40|2@1+ (1,0) [0|3] "" aps + SG_ DAS_laneDepartureWarning : 37|3@1+ (1,0) [0|5] "" aps + SG_ DAS_csaState : 35|2@1+ (1,0) [0|3] "" aps + SG_ DAS_sideCollisionInhibit : 34|1@1+ (1,0) [0|1] "" aps + SG_ DAS_sideCollisionWarning : 32|2@1+ (1,0) [0|3] "" aps + SG_ DAS_sideCollisionAvoid : 30|2@1+ (1,0) [0|3] "" aps + SG_ DAS_summonRvsLeashReached : 29|1@1+ (1,0) [0|1] "" aps + SG_ DAS_summonFwdLeashReached : 28|1@1+ (1,0) [0|1] "" aps + SG_ DAS_autoparkWaitingForBrake : 26|1@1+ (1,0) [0|1] "" gtw + SG_ DAS_autoParked : 25|1@1+ (1,0) [0|1] "" aps + SG_ DAS_autoparkReady : 24|1@1+ (1,0) [0|1] "" aps + SG_ DAS_forwardCollisionWarning : 22|2@1+ (1,0) [0|3] "" aps + SG_ DAS_heaterState : 21|1@1+ (1,0) [0|1] "" gtw + SG_ DAS_visionOnlySpeedLimit : 16|5@1+ (5,0) [0|150] "kph/mph" aps + SG_ DAS_summonClearedGate : 15|1@1+ (1,0) [0|1] "" aps + SG_ DAS_summonObstacle : 14|1@1+ (1,0) [0|1] "" aps + SG_ DAS_suppressSpeedWarning : 13|1@1+ (1,0) [0|1] "" aps + SG_ DAS_fusedSpeedLimit : 8|5@1+ (5,0) [0|150] "kph/mph" aps + SG_ DAS_blindSpotRearRight : 6|2@1+ (1,0) [0|3] "" aps + SG_ DAS_blindSpotRearLeft : 4|2@1+ (1,0) [0|3] "" aps + SG_ DAS_autopilotState : 0|4@1+ (1,0) [0|15] "" aps + +BO_ 325 ESP_status: 8 PARTY + SG_ ESP_absBrakeEvent2 : 22|2@1+ (1,0) [0|0] "" X + SG_ ESP_absFaultLamp : 17|1@1+ (1,0) [0|0] "" X + SG_ ESP_brakeApply : 31|1@1+ (1,0) [0|0] "" X + SG_ ESP_brakeDiscWipingActive : 28|1@1+ (1,0) [0|0] "" X + SG_ ESP_brakeLamp : 21|1@1+ (1,0) [0|0] "" X + SG_ ESP_brakeTorqueTarget : 51|13@1+ (2,0) [0|0] "Nm" X + SG_ ESP_btcTargetState : 38|2@1+ (1,0) [0|0] "" X + SG_ ESP_cdpStatus : 34|2@1+ (1,0) [0|0] "" X + SG_ ESP_driverBrakeApply : 29|2@1+ (1,0) [0|0] "" X + SG_ ESP_ebdFaultLamp : 16|1@1+ (1,0) [0|0] "" X + SG_ ESP_ebrStandstillSkid : 48|1@1+ (1,0) [0|0] "" X + SG_ ESP_ebrStatus : 49|2@1+ (1,0) [0|0] "" X + SG_ ESP_espFaultLamp : 18|1@1+ (1,0) [0|0] "" X + SG_ ESP_espLampFlash : 20|1@1+ (1,0) [0|0] "" X + SG_ ESP_espModeActive : 12|2@1+ (1,0) [0|0] "" X + SG_ ESP_hydraulicBoostEnabled : 19|1@1+ (1,0) [0|0] "" X + SG_ ESP_lateralAccelQF : 25|1@1+ (1,0) [0|0] "" X + SG_ ESP_longitudinalAccelQF : 24|1@1+ (1,0) [0|0] "" X + SG_ ESP_ptcTargetState : 36|2@1+ (1,0) [0|0] "" X + SG_ ESP_stabilityControlSts2 : 14|2@1+ (1,0) [0|0] "" X + SG_ ESP_statusChecksum : 0|8@1+ (1,0) [0|0] "" X + SG_ ESP_statusCounter : 8|4@1+ (1,0) [0|0] "" X + SG_ ESP_steeringAngleQF : 27|1@1+ (1,0) [0|0] "" X + SG_ ESP_yawRateQF : 26|1@1+ (1,0) [0|0] "" X + +CM_ BO_ 605 "Bytes change when toggling between FSD and AP, as well as Traffic Light and Stop Sign Control in TACC"; + +CM_ SG_ 659 DAS_autosteerEnabled "1 if Autosteer or FSD is enabled, 0 otherwise"; +CM_ SG_ 785 leftBlinkerOn "only describes stalk position if half pressed without auto-cancel blinkers. otherwise acts as expected"; +CM_ SG_ 785 rightBlinkerOn "only describes stalk position if half pressed without auto-cancel blinkers. otherwise acts as expected"; +CM_ SG_ 785 scrollWheelPressed "captures either scroll wheel left, right or down press"; + +VAL_ 545 VCFRONT_uiAudioLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_uiHiCurrentLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_vcrightHiCurrentLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_vcleftHiCurrentLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_ocsLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_oilPumpRearLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_oilPumpFrontLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_disLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_diLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_das2HighCurrentLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_das1HighCurrentLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_amplifierLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_tunerLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_iBoosterLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_rcmLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_tpmsLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_sccmLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_pcsLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_ptcLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_hvacCompLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_tasLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_hvcLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_radcLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_epasLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_espLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_parkLVState 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_cpLVRequest 1 "LV_ON" 2 "LV_GOING_DOWN" 3 "LV_FAULT" 0 "LV_OFF" ; +VAL_ 545 VCFRONT_vehiclePowerState 3 "VEHICLE_POWER_STATE_DRIVE" 1 "VEHICLE_POWER_STATE_CONDITIONING" 2 "VEHICLE_POWER_STATE_ACCESSORY" 0 "VEHICLE_POWER_STATE_OFF" ; +VAL_ 545 VCFRONT_LVPowerStateIndex 0 "Mux0" 1 "Mux1" ; +VAL_ 905 DAS_longCollisionWarning 7 "FCM_LONG_COLLISION_WARNING_VEHICLE_CUTIN" 0 "FCM_LONG_COLLISION_WARNING_NONE" 4 "FCM_LONG_COLLISION_WARNING_STOPSIGN_STOPLINE" 9 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVL2" 15 "FCM_LONG_COLLISION_WARNING_SNA" 8 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVL" 5 "FCM_LONG_COLLISION_WARNING_TFL_STOPLINE" 2 "FCM_LONG_COLLISION_WARNING_PEDESTRIAN" 12 "FCM_LONG_COLLISION_WARNING_VEHICLE_CIPV2" 6 "FCM_LONG_COLLISION_WARNING_VEHICLE_CIPV" 10 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVR" 3 "FCM_LONG_COLLISION_WARNING_IPSO" 1 "FCM_LONG_COLLISION_WARNING_VEHICLE_UNKNOWN" 11 "FCM_LONG_COLLISION_WARNING_VEHICLE_MCVR2" ; +VAL_ 905 DAS_ppOffsetDesiredRamp 128 "PP_NO_OFFSET" ; +VAL_ 905 DAS_driverInteractionLevel 0 "DRIVER_INTERACTING" 1 "DRIVER_NOT_INTERACTING" 2 "CONTINUED_DRIVER_NOT_INTERACTING" ; +VAL_ 905 DAS_robState 0 "ROB_STATE_INHIBITED" 2 "ROB_STATE_ACTIVE" 3 "ROB_STATE_MAPLESS" 1 "ROB_STATE_MEASURE" ; +VAL_ 905 DAS_radarTelemetry 0 "RADAR_TELEMETRY_IDLE" 1 "RADAR_TELEMETRY_NORMAL" 2 "RADAR_TELEMETRY_URGENT" ; +VAL_ 905 DAS_lssState 7 "LSS_STATE_OFF" 1 "LSS_STATE_LDW" 4 "LSS_STATE_MONITOR" 2 "LSS_STATE_LKA" 3 "LSS_STATE_ELK" 0 "LSS_STATE_FAULT" 5 "LSS_STATE_BLINDSPOT" 6 "LSS_STATE_ABORT" ; +VAL_ 905 DAS_ACC_report 12 "ACC_REPORT_LC_EXTERNAL_STATE_ABORTING" 17 "ACC_REPORT_TARGET_MCP" 11 "ACC_REPORT_LC_HANDS_ON_REQD_STRUCK_OUT" 19 "ACC_REPORT_MCVLR_DPP" 1 "ACC_REPORT_TARGET_CIPV" 15 "ACC_REPORT_RADAR_OBJ_ONE" 16 "ACC_REPORT_RADAR_OBJ_TWO" 14 "ACC_REPORT_LC_EXTERNAL_STATE_ACTIVE_RESTRICTED" 4 "ACC_REPORT_TARGET_MCVR" 20 "ACC_REPORT_MCVLR_IN_PATH" 10 "ACC_REPORT_CSA" 5 "ACC_REPORT_TARGET_CUTIN" 9 "ACC_REPORT_TARGET_TYPE_FAULT" 7 "ACC_REPORT_TARGET_TYPE_TRAFFIC_LIGHT" 6 "ACC_REPORT_TARGET_TYPE_STOP_SIGN" 24 "ACC_REPORT_BEHAVIOR_REPORT" 18 "ACC_REPORT_FLEET_SPEEDS" 2 "ACC_REPORT_TARGET_IN_FRONT_OF_CIPV" 23 "ACC_REPORT_CAMERA_ONLY" 3 "ACC_REPORT_TARGET_MCVL" 22 "ACC_REPORT_RADAR_OBJ_FIVE" 0 "ACC_REPORT_TARGET_NONE" 8 "ACC_REPORT_TARGET_TYPE_IPSO" 21 "ACC_REPORT_CIPV_CUTTING_OUT" 13 "ACC_REPORT_LC_EXTERNAL_STATE_ABORTED" ; +VAL_ 905 DAS_pmmCameraFaultReason 1 "PMM_CAMERA_BLOCKED_FRONT" 2 "PMM_CAMERA_INVALID_MIA" 0 "PMM_CAMERA_NO_FAULT" ; +VAL_ 905 DAS_pmmSysFaultReason 4 "PMM_FAULT_STEERING_ANGLE_RATE" 6 "PMM_FAULT_ROAD_TYPE" 5 "PMM_FAULT_DISABLED_BY_USER" 0 "PMM_FAULT_NONE" 1 "PMM_FAULT_DAS_DISABLED" 3 "PMM_FAULT_DI_FAULT" 2 "PMM_FAULT_SPEED" 7 "PMM_FAULT_BRAKE_PEDAL_INHIBIT" ; +VAL_ 905 DAS_pmmRadarFaultReason 2 "PMM_RADAR_INVALID_MIA" 1 "PMM_RADAR_BLOCKED_FRONT" 0 "PMM_RADAR_NO_FAULT" ; +VAL_ 905 DAS_pmmUltrasonicsFaultReason 2 "PMM_ULTRASONICS_BLOCKED_REAR" 0 "PMM_ULTRASONICS_NO_FAULT" 1 "PMM_ULTRASONICS_BLOCKED_FRONT" 3 "PMM_ULTRASONICS_BLOCKED_BOTH" 4 "PMM_ULTRASONICS_INVALID_MIA" ; +VAL_ 905 DAS_activationFailureStatus 0 "LC_ACTIVATION_IDLE" 2 "LC_ACTIVATION_FAILED_2" 1 "LC_ACTIVATION_FAILED_1" ; +VAL_ 905 DAS_pmmLoggingRequest 0 "FALSE" 1 "TRUE" ; +VAL_ 905 DAS_pmmObstacleSeverity 5 "PMM_CRASH_FRONT" 0 "PMM_NONE" 2 "PMM_IMMINENT_FRONT" 4 "PMM_CRASH_REAR" 1 "PMM_IMMINENT_REAR" 6 "PMM_ACCEL_LIMIT" 7 "PMM_SNA" 3 "PMM_BRAKE_REQUEST" ; +VAL_ 905 DAS_accSpeedLimit 1023 "SNA" 0 "NONE" ; +VAL_ 264 DI_axleSpeed -32768 "SNA" ; +VAL_ 264 DI_torqueActual -4096 "SNA" ; +VAL_ 264 DI_torqueCommand -4096 "SNA" ; +VAL_ 585 SCCM_turnIndicatorStalkStatus 3 "DOWN_1" 5 "SNA" 0 "IDLE" 1 "UP_1" 4 "DOWN_2" 2 "UP_2" ; +VAL_ 585 SCCM_washWipeButtonStatus 3 "SNA" 0 "NOT_PRESSED" 2 "2ND_DETENT" 1 "1ST_DETENT" ; +VAL_ 585 SCCM_highBeamStalkStatus 3 "SNA" 0 "IDLE" 1 "PULL" 2 "PUSH" ; +VAL_ 280 DI_trackModeState 0 "TRACK_MODE_UNAVAILABLE" 1 "TRACK_MODE_AVAILABLE" 2 "TRACK_MODE_ON" ; +VAL_ 280 DI_keepAliveRequest 1 "KEEP_ALIVE" 0 "NO_REQUEST" ; +VAL_ 280 DI_epbRequest 0 "DI_EPBREQUEST_NO_REQUEST" 1 "DI_EPBREQUEST_PARK" 2 "DI_EPBREQUEST_UNPARK" ; +VAL_ 280 DI_tractionControlMode 0 "TC_NORMAL" 1 "TC_SLIP_START" 4 "TC_ROLLS_MODE" 2 "TC_DEV_MODE_1" 5 "TC_DYNO_MODE" 3 "TC_DEV_MODE_2" ; +VAL_ 280 DI_accelPedalPos 255 "SNA" ; +VAL_ 280 DI_immobilizerState 2 "DI_IMM_STATE_AUTHENTICATING" 0 "DI_IMM_STATE_INIT_SNA" 3 "DI_IMM_STATE_DISARMED" 4 "DI_IMM_STATE_IDLE" 6 "DI_IMM_STATE_FAULT" 1 "DI_IMM_STATE_REQUEST" 5 "DI_IMM_STATE_RESET" ; +VAL_ 280 DI_gear 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" 7 "DI_GEAR_SNA" 2 "DI_GEAR_R" 3 "DI_GEAR_N" 4 "DI_GEAR_D" ; +VAL_ 280 DI_brakePedalState 2 "INVALID" 0 "OFF" 1 "ON" ; +VAL_ 280 DI_systemState 5 "DI_SYS_ENABLE" 1 "DI_SYS_IDLE" 2 "DI_SYS_STANDBY" 0 "DI_SYS_UNAVAILABLE" 3 "DI_SYS_FAULT" 4 "DI_SYS_ABORT" ; +VAL_ 605 DAS_trafficLightColor 0 "NONE" 1 "RED" 2 "GREEN" 3 "YELLOW" ; +VAL_ 697 DAS_accelMax 511 "SNA" ; +VAL_ 697 DAS_accelMin 511 "SNA" ; +VAL_ 697 DAS_jerkMax 255 "SNA" ; +VAL_ 697 DAS_jerkMin 511 "SNA" ; +VAL_ 697 DAS_aebEvent 2 "AEB_FAULT" 0 "AEB_NOT_ACTIVE" 3 "AEB_SNA" 1 "AEB_ACTIVE" ; +VAL_ 697 DAS_accState 4 "ACC_ON" 9 "APC_PAUSE" 14 "ACC_CANCEL_OUT_OF_CALIBRATION" 10 "APC_UNPARK_COMPLETE" 6 "APC_FORWARD" 3 "ACC_HOLD" 2 "ACC_CANCEL_RADAR_BLIND" 7 "APC_COMPLETE" 1 "ACC_CANCEL_CAMERA_BLIND" 8 "APC_ABORT" 13 "ACC_CANCEL_GENERIC_SILENT" 5 "APC_BACKWARD" 11 "APC_SELFPARK_START" 0 "ACC_CANCEL_GENERIC" 12 "ACC_CANCEL_PATH_NOT_CLEAR" 15 "FAULT_SNA" ; +VAL_ 697 DAS_setSpeed 4095 "SNA" ; +VAL_ 341 ESP_vehicleSpeed 1023 "ESP_VEHICLE_SPEED_SNA" ; +VAL_ 341 ESP_vehicleStandstillSts 1 "STANDSTILL" 0 "NOT_STANDSTILL" ; +VAL_ 341 ESP_wheelSpeedsQF 0 "ONE_OR_MORE_WSS_INVALID" 1 "ALL_WSS_VALID" ; +VAL_ 341 ESP_WheelRotationFrL 1 "WR_BACKWARD" 0 "WR_FORWARD" 3 "WR_NOT_DEFINABLE" 2 "WR_STANDSTILL" ; +VAL_ 341 ESP_WheelRotationFrR 1 "WR_BACKWARD" 0 "WR_FORWARD" 3 "WR_NOT_DEFINABLE" 2 "WR_STANDSTILL" ; +VAL_ 341 ESP_WheelRotationReL 1 "WR_BACKWARD" 0 "WR_FORWARD" 3 "WR_NOT_DEFINABLE" 2 "WR_STANDSTILL" ; +VAL_ 341 ESP_WheelRotationReR 1 "WR_BACKWARD" 0 "WR_FORWARD" 3 "WR_NOT_DEFINABLE" 2 "WR_STANDSTILL" ; +VAL_ 341 ESP_wheelPulseCountReR 255 "SNA" ; +VAL_ 341 ESP_wheelPulseCountReL 255 "SNA" ; +VAL_ 341 ESP_wheelPulseCountFrR 255 "SNA" ; +VAL_ 341 ESP_wheelPulseCountFrL 255 "SNA" ; +VAL_ 969 APS_apbGpioState 0 "AP_GPIO_STATE_PWR_DOWN_REBOOT" 3 "AP_GPIO_STATE_HEALTHY" 1 "AP_GPIO_STATE_DISABLED" 2 "AP_GPIO_STATE_CRITICAL" ; +VAL_ 969 APS_apbStatusMonitorState 1 "STATUS_MONITOR_STATE_PWR_OFF" 2 "STATUS_MONITOR_STATE_INIT" 7 "STATUS_MONITOR_NUM_STATES" 0 "STATUS_MONITOR_STATE_UNKNOWN" 4 "STATUS_MONITOR_STATE_CRITICAL" 6 "STATUS_MONITOR_STATE_RECOVERY" 5 "STATUS_MONITOR_STATE_SHUTTING_DOWN" 3 "STATUS_MONITOR_STATE_NOMINAL" ; +VAL_ 969 APS_eacInternalState 1 "APS_EAC_STATE_MOMENTARY" 3 "APS_EAC_STATE_AUTOPARK" 5 "APS_EAC_STATE_OVERRIDE" 4 "APS_EAC_STATE_INHIBIT" 0 "APS_EAC_STATE_INIT" 2 "APS_EAC_STATE_CONTINUOUS" 7 "APS_EAC_NUM_STATES" 6 "APS_EAC_STATE_LSS" ; +VAL_ 969 APS_appGpioState 0 "AP_GPIO_STATE_PWR_DOWN_REBOOT" 3 "AP_GPIO_STATE_HEALTHY" 1 "AP_GPIO_STATE_DISABLED" 2 "AP_GPIO_STATE_CRITICAL" ; +VAL_ 969 APS_canMaster 0 "CAN_MASTER_APS" 2 "CAN_MASTER_APB" 3 "CAN_MASTER_SNA" 1 "CAN_MASTER_APP" ; +VAL_ 969 APS_vehBehaviorState 0 "VEH_BEHAVIOR_STATE_UNKNOWN" 3 "VEH_BEHAVIOR_STATE_APS_BRIDGE_APP" 1 "VEH_BEHAVIOR_STATE_APS_AVAILABLE" 5 "VEH_BEHAVIOR_STATE_APS_FAIL_SAFE" 7 "VEH_BEHAVIOR_NUM_STATES" 2 "VEH_BEHAVIOR_STATE_APS_CONTROL" 6 "VEH_BEHAVIOR_STATE_APS_OVERRIDE" 4 "VEH_BEHAVIOR_STATE_APS_BRIDGE_APB" ; +VAL_ 969 APS_appStatusMonitorState 1 "STATUS_MONITOR_STATE_PWR_OFF" 2 "STATUS_MONITOR_STATE_INIT" 7 "STATUS_MONITOR_NUM_STATES" 0 "STATUS_MONITOR_STATE_UNKNOWN" 4 "STATUS_MONITOR_STATE_CRITICAL" 6 "STATUS_MONITOR_STATE_RECOVERY" 5 "STATUS_MONITOR_STATE_SHUTTING_DOWN" 3 "STATUS_MONITOR_STATE_NOMINAL" ; +VAL_ 925 IBST_internalState 5 "TRANSITION_TO_IDLE" 0 "NO_MODE_ACTIVE" 4 "DIAGNOSTIC" 6 "POST_DRIVE_CHECK" 1 "PRE_DRIVE_CHECK" 3 "EXTERNAL_BRAKE_REQUEST" 2 "LOCAL_BRAKE_REQUEST" ; +VAL_ 925 IBST_driverBrakeApply 1 "BRAKES_NOT_APPLIED" 2 "DRIVER_APPLYING_BRAKES" 3 "FAULT" 0 "NOT_INIT_OR_OFF" ; +VAL_ 925 IBST_iBoosterStatus 6 "IBOOSTER_ACTUATION" 4 "IBOOSTER_ACTIVE_GOOD_CHECK" 2 "IBOOSTER_FAILURE" 5 "IBOOSTER_READY" 3 "IBOOSTER_DIAGNOSTIC" 0 "IBOOSTER_OFF" 1 "IBOOSTER_INIT" ; +VAL_ 880 EPAS3S_eacStatus 7 "SNA" 2 "EAC_ACTIVE" 4 "LANE_KEEP_ASSIST" 3 "EAC_FAULT" 1 "EAC_AVAILABLE" 5 "EMERGENCY_LANE_KEEP" 0 "EAC_INHIBITED" ; +VAL_ 880 EPAS3S_handsOnLevel 1 "LEVEL_1" 0 "LEVEL_0" 3 "LEVEL_3" 2 "LEVEL_2" ; +VAL_ 880 EPAS3S_torsionBarTorque 4095 "SNA" 4094 "UNDEFINABLE_DATA" ; +VAL_ 880 EPAS3S_eacErrorCode 15 "SNA" 11 "EAC_ERROR_HIGH_TORSION_SAFETY" 4 "EAC_ERROR_TMP_FAULT" 2 "EAC_ERROR_MAX_SPEED" 7 "EAC_ERROR_HIGH_ANGLE_RATE_REQ" 0 "EAC_ERROR_IDLE" 10 "EAC_ERROR_HIGH_MMOT_SAFETY" 6 "EAC_ERROR_HIGH_ANGLE_REQ" 8 "EAC_ERROR_HIGH_ANGLE_SAFETY" 5 "EAR_ERROR_MAX_STEER_DELTA" 13 "EAC_ERROR_PINION_VEL_DIFF" 1 "EAC_ERROR_MIN_SPEED" 14 "EAC_EXTERNAL_MONITOR_INHIBIT" 12 "EAC_ERROR_LOW_ASSIST" 9 "EAC_ERROR_HIGH_ANGLE_RATE_SAFETY" 3 "EAC_ERROR_HANDS_ON" ; +VAL_ 880 EPAS3S_steeringRackForce 1023 "SNA" 1022 "NOT_IN_SPEC" ; +VAL_ 880 EPAS3S_steeringFault 0 "NO_FAULT" 1 "FAULT" ; +VAL_ 880 EPAS3S_steeringReduced 0 "NORMAL_ASSIST" 1 "REDUCED_ASSIST" ; +VAL_ 880 EPAS3S_internalSASQF 1 "IN_SPEC" 0 "UNDEFINABLE_ACCURACY" ; +VAL_ 880 EPAS3S_currentTuneMode 3 "STEERING_TUNE_RWD_COMFORT" 1 "STEERING_TUNE_DM_STANDARD" 5 "STEERING_TUNE_RWD_SPORT" 0 "STEERING_TUNE_DM_COMFORT" 4 "STEERING_TUNE_RWD_STANDARD" 2 "STEERING_TUNE_DM_SPORT" ; +VAL_ 599 DI_uiSpeedUnits 0 "DI_SPEED_MPH" 1 "DI_SPEED_KPH" ; +VAL_ 599 DI_uiSpeed 255 "DI_UI_SPEED_SNA" ; +VAL_ 599 DI_vehicleSpeed 4095 "SNA" ; +VAL_ 637 APS_eacAllow 0 "INHIBIT" 1 "ALLOW" 2 "RESERVED" 3 "SNA"; +VAL_ 1160 DAS_steeringControlType 2 "LANE_KEEP_ASSIST" 0 "NONE" 1 "ANGLE_CONTROL" 3 "EMERGENCY_LANE_KEEP" ; +VAL_ 1160 DAS_steeringAngleRequest 16384 "ZERO_ANGLE" ; +VAL_ 297 SCCM_steeringAngleValidity 3 "SNA" 2 "INIT" 0 "INVALID" 1 "VALID" ; +VAL_ 297 SCCM_steeringAngleSensorStatus 0 "OK" 1 "INIT" 2 "ERROR" 3 "ERROR_INIT" ; +VAL_ 646 DI_rollPreventionState 0 "UNAVAILABLE" 1 "STANDBY" 2 "READY" 3 "BUILD" 4 "HOLD" 5 "PARK" 6 "FAULT" 7 "INIT" ; +VAL_ 646 DI_vehicleHoldState 0 "UNAVAILABLE" 1 "STANDBY" 2 "BLEND_IN" 3 "STANDSTILL" 4 "BLEND_OUT" 5 "PARK" 6 "FAULT" 7 "INIT" ; +VAL_ 646 DI_pmmStatus 0 "INACTIVE" 1 "ACTIVE" 2 "LOGGING_ACTIVE" 3 "SNA" ; +VAL_ 646 DI_aebState 0 "UNAVAILABLE" 1 "STANDBY" 2 "ENABLED" 3 "STANDSTILL" 4 "FAULT" 7 "SNA" ; +VAL_ 646 DI_autopilotRequest 0 "IDLE" 1 "ACTIVATE" ; +VAL_ 646 DI_parkBrakeState 0 "UNAVAILABLE" 1 "RELEASED" 2 "REQUESTED" 3 "APPLIED" 4 "FAULTED" 5 "PANIC_EPB" 6 "PANIC_SKID" 7 "RELEASING" 15 "SNA" ; +VAL_ 646 DI_autoparkState 0 "UNAVAILABLE" 1 "STANDBY" 2 "STARTED" 3 "ACTIVE" 4 "COMPLETE" 5 "PAUSED" 6 "ABORTED" 7 "RESUMED" 8 "UNPARK_COMPLETE" 9 "SELFPARK_STARTED" 15 "SNA" ; +VAL_ 646 DI_speedUnits 0 "MPH" 1 "KPH" ; +VAL_ 646 DI_cruiseState 0 "UNAVAILABLE" 1 "STANDBY" 2 "ENABLED" 3 "STANDSTILL" 4 "OVERRIDE" 5 "FAULT" 6 "PRE_FAULT" 7 "PRE_CANCEL" ; +VAL_ 659 DAS_driverSteeringWeight 0 "light" 1 "standard" 2 "heavy"; +VAL_ 659 DAS_offRoadAssist 0 "disabled" 3 "enabled"; +VAL_ 659 DAS_distanceUnits 1 "miles" 0 "kilometers"; +VAL_ 659 DAS_fcwSensitivity 0 "early" 1 "medium" 2 "late" 3 "off"; +VAL_ 659 DAS_driverAccelerationMode 0 "chill" 1 "standard"; +VAL_ 785 buckleStatus 1 "LATCHED" 0 "UNLATCHED" ; +VAL_ 785 anyDoorOpen 1 "OPEN" 0 "CLOSED" ; +VAL_ 785 leftBlinkerBlinking 0 "off" 1 "blinking, off" 2 "blinking, on"; +VAL_ 785 rightBlinkerBlinking 0 "off" 1 "blinking, off" 2 "blinking, on"; +VAL_ 923 DAS_autoLaneChangeState 5 "ALC_UNAVAILABLE_VEHICLE_SPEED" 17 "ALC_ABORT_POOR_VIEW_RANGE" 23 "ALC_BLOCKED_VEH_TTC_AND_USS_L" 0 "ALC_UNAVAILABLE_DISABLED" 26 "ALC_BLOCKED_LANE_TYPE_L" 29 "ALC_ABORT_TIMEOUT" 9 "ALC_IN_PROGRESS_L" 4 "ALC_UNAVAILABLE_EXITING_HIGHWAY" 22 "ALC_BLOCKED_VEH_TTC_L" 12 "ALC_WAITING_FOR_SIDE_OBST_TO_PASS_R" 18 "ALC_ABORT_LC_HEALTH_BAD" 28 "ALC_WAITING_HANDS_ON" 8 "ALC_AVAILABLE_BOTH" 11 "ALC_WAITING_FOR_SIDE_OBST_TO_PASS_L" 3 "ALC_UNAVAILABLE_TP_FOLLOW" 2 "ALC_UNAVAILABLE_SONICS_INVALID" 21 "ALC_UNAVAILABLE_SOLID_LANE_LINE" 24 "ALC_BLOCKED_VEH_TTC_R" 1 "ALC_UNAVAILABLE_NO_LANES" 25 "ALC_BLOCKED_VEH_TTC_AND_USS_R" 30 "ALC_ABORT_MISSION_PLAN_INVALID" 27 "ALC_BLOCKED_LANE_TYPE_R" 19 "ALC_ABORT_BLINKER_TURNED_OFF" 31 "ALC_SNA" 13 "ALC_WAITING_FOR_FWD_OBST_TO_PASS_L" 16 "ALC_ABORT_SIDE_OBSTACLE_PRESENT_R" 6 "ALC_AVAILABLE_ONLY_L" 20 "ALC_ABORT_OTHER_REASON" 15 "ALC_ABORT_SIDE_OBSTACLE_PRESENT_L" 7 "ALC_AVAILABLE_ONLY_R" 14 "ALC_WAITING_FOR_FWD_OBST_TO_PASS_R" 10 "ALC_IN_PROGRESS_R" ; +VAL_ 923 DAS_autopilotHandsOnState 8 "LC_HANDS_ON_SUSPENDED" 15 "LC_HANDS_ON_SNA" 7 "LC_HANDS_ON_REQD_STRUCK_OUT" 3 "LC_HANDS_ON_REQD_VISUAL" 4 "LC_HANDS_ON_REQD_CHIME_1" 6 "LC_HANDS_ON_REQD_SLOWING" 1 "LC_HANDS_ON_REQD_DETECTED" 2 "LC_HANDS_ON_REQD_NOT_DETECTED" 5 "LC_HANDS_ON_REQD_CHIME_2" 0 "LC_HANDS_ON_NOT_REQD" ; +VAL_ 923 DAS_fleetSpeedState 0 "FLEETSPEED_UNAVAILABLE" 1 "FLEETSPEED_AVAILABLE" 2 "FLEETSPEED_ACTIVE" 3 "FLEETSPEED_HOLD" ; +VAL_ 923 DAS_laneDepartureWarning 5 "SNA" 0 "NONE" 2 "RIGHT_WARNING" 4 "RIGHT_WARNING_SEVERE" 3 "LEFT_WARNING_SEVERE" 1 "LEFT_WARNING" ; +VAL_ 923 DAS_csaState 1 "CSA_EXTERNAL_STATE_AVAILABLE" 3 "CSA_EXTERNAL_STATE_HOLD" 2 "CSA_EXTERNAL_STATE_ENABLE" 0 "CSA_EXTERNAL_STATE_UNAVAILABLE" ; +VAL_ 923 DAS_sideCollisionInhibit 0 "NO_INHIBIT" 1 "INHIBIT" ; +VAL_ 923 DAS_sideCollisionWarning 0 "NONE" 2 "WARN_RIGHT" 1 "WARN_LEFT" 3 "WARN_LEFT_RIGHT" ; +VAL_ 923 DAS_sideCollisionAvoid 3 "SNA" 0 "NONE" 1 "AVOID_LEFT" 2 "AVOID_RIGHT" ; +VAL_ 923 DAS_autoparkReady 0 "AUTOPARK_UNAVAILABLE" 1 "AUTOPARK_READY" ; +VAL_ 923 DAS_forwardCollisionWarning 3 "SNA" 0 "NONE" 1 "FORWARD_COLLISION_WARNING" ; +VAL_ 923 DAS_heaterState 0 "HEATER_OFF_SNA" 1 "HEATER_ON" ; +VAL_ 923 DAS_visionOnlySpeedLimit 31 "NONE" 0 "UNKNOWN_SNA" ; +VAL_ 923 DAS_suppressSpeedWarning 1 "Suppress_Speed_Warning" 0 "Do_Not_Suppress" ; +VAL_ 923 DAS_fusedSpeedLimit 31 "NONE" 0 "UNKNOWN_SNA" ; +VAL_ 923 DAS_blindSpotRearRight 3 "SNA" 0 "NO_WARNING" 1 "WARNING_LEVEL_1" 2 "WARNING_LEVEL_2" ; +VAL_ 923 DAS_blindSpotRearLeft 3 "SNA" 0 "NO_WARNING" 1 "WARNING_LEVEL_1" 2 "WARNING_LEVEL_2" ; +VAL_ 923 DAS_autopilotState 15 "SNA" 8 "ABORTING" 3 "ACTIVE_NOMINAL" 0 "DISABLED" 4 "ACTIVE_RESTRICTED" 5 "ACTIVE_NAV" 14 "FAULT" 1 "UNAVAILABLE" 9 "ABORTED" 2 "AVAILABLE" ; +VAL_ 325 ESP_absBrakeEvent2 0 "NOT_ACTIVE" 1 "ACTIVE_FRONT_REAR" 2 "ACTIVE_FRONT" 3 "ACTIVE_REAR"; +VAL_ 325 ESP_absFaultLamp 0 "OFF" 1 "ON"; +VAL_ 325 ESP_brakeApply 0 "INACTIVE" 1 "ACTIVE"; +VAL_ 325 ESP_brakeDiscWipingActive 0 "INACTIVE" 1 "ACTIVE"; +VAL_ 325 ESP_brakeLamp 0 "OFF" 1 "ON"; +VAL_ 325 ESP_brakeTorqueTarget 8191 "SNA"; +VAL_ 325 ESP_btcTargetState 0 "OFF" 1 "BACKUP" 2 "ON" 3 "SNA"; +VAL_ 325 ESP_cdpStatus 0 "CDP_IS_NOT_AVAILABLE" 1 "CDP_IS_AVAILABLE" 2 "ACTUATING_EPB_CDP" 3 "CDP_COMMAND_INVALID"; +VAL_ 325 ESP_driverBrakeApply 0 "NotInit_orOff" 1 "Not_Applied" 2 "Driver_applying_brakes" 3 "Faulty_SNA"; +VAL_ 325 ESP_ebdFaultLamp 0 "OFF" 1 "ON"; +VAL_ 325 ESP_ebrStandstillSkid 0 "NO_STANDSTILL_SKID" 1 "STANDSTILL_SKID_DETECTED"; +VAL_ 325 ESP_ebrStatus 0 "EBR_IS_NOT_AVAILABLE" 1 "EBR_IS_AVAILABLE" 2 "ACTUATING_DI_EBR" 3 "EBR_COMMAND_INVALID"; +VAL_ 325 ESP_espFaultLamp 0 "OFF" 1 "ON"; +VAL_ 325 ESP_espLampFlash 0 "OFF" 1 "FLASH"; +VAL_ 325 ESP_espModeActive 0 "00_NORMAL" 1 "01" 2 "02" 3 "03"; +VAL_ 325 ESP_lateralAccelQF 0 "UNDEFINABLE_ACCURACY" 1 "IN_SPEC"; +VAL_ 325 ESP_longitudinalAccelQF 0 "UNDEFINABLE_ACCURACY" 1 "IN_SPEC"; +VAL_ 325 ESP_ptcTargetState 0 "FAULT" 1 "BACKUP" 2 "ON" 3 "SNA"; +VAL_ 325 ESP_stabilityControlSts2 0 "INIT" 1 "ON" 2 "ENGAGED" 3 "FAULTED"; +VAL_ 325 ESP_steeringAngleQF 0 "UNDEFINABLE_ACCURACY" 1 "IN_SPEC"; +VAL_ 325 ESP_yawRateQF 0 "UNDEFINABLE_ACCURACY" 1 "IN_SPEC"; diff --git a/opendbc_repo/opendbc/dbc/tesla_model3_vehicle.dbc b/opendbc_repo/opendbc/dbc/tesla_model3_vehicle.dbc new file mode 100644 index 0000000000..604db8fe27 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/tesla_model3_vehicle.dbc @@ -0,0 +1,339 @@ +VERSION "" + + +BU_: CH DIPF DIPR ETH FC HVI HVS PARTY SDCV VEH VIRT + + +BO_ 962 VCLEFT_switchStatus: 8 VEH + SG_ VCLEFT_frontBuckleSwitch m0: 48|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_btnWindowSwPackUpLF m0: 32|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_frontSeatTrackBack m0: 8|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoDownLF m0: 35|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackDownRR m0: 46|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoUpRR m0: 45|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoDownRR m0: 47|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_rightMirrorTilt m0: 5|3@1+ (1,0) [0|4] "" vcright + SG_ VCLEFT_btnWindowSwPackUpRR m0: 44|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_frontOccupancySwitch m0: 50|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_swcRightTiltLeft m1: 8|2@1+ (1,0) [0|3] "" das + SG_ VCLEFT_rearRightOccupancySwitch m0: 58|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_btnWindowSwPackDownLF m0: 34|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoUpLF m0: 33|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_swcLeftTiltRight m1: 3|2@1+ (1,0) [0|3] "" das + SG_ VCLEFT_frontSeatBackrestForward m0: 22|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_swcRightTiltRight m1: 10|2@1+ (1,0) [0|3] "" das + SG_ VCLEFT_swcLeftScrollTicks m1: 16|6@1- (1,0) [-32|31] "" das + SG_ VCLEFT_btnWindowUpLR m1: 32|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowAutoDownLR m1: 35|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackDownRF m0: 42|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoUpRF m0: 41|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_frontSeatLumbarIn m0: 28|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_frontSeatLiftUp m0: 18|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_btnWindowSwPackDownLR m0: 38|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoUpLR m0: 37|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_frontSeatLumbarDown m0: 24|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_driverPresent m0: 4|1@1+ (1,0) [0|1] "" das + SG_ VCLEFT_frontSeatTiltDown m0: 12|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_frontSeatTrackForward m0: 10|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_rearLeftBuckleSwitch m0: 52|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_hazardButtonPressed m0: 3|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_swcRightScrollTicks m1: 24|6@1- (1,0) [-32|31] "" das + SG_ VCLEFT_swcRightPressed m1: 12|2@1+ (1,0) [0|3] "" das + SG_ VCLEFT_frontSeatLumbarOut m0: 30|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_brakePressed m0: 60|1@1+ (1,0) [0|1] "" di + SG_ VCLEFT_swcLeftTiltLeft m1: 14|2@1+ (1,0) [0|3] "" das + SG_ VCLEFT_swcLeftPressed m1: 5|2@1+ (1,0) [0|3] "" das + SG_ VCLEFT_btnWindowSwPackUpLR m0: 36|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_frontSeatTiltUp m0: 14|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_rearLeftOccupancySwitch m0: 56|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_frontSeatBackrestBack m0: 20|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoDownLR m0: 39|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_rearCenterOccupancySwitch m0: 54|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_frontSeatLumbarUp m0: 26|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_frontSeatLiftDown m0: 16|2@1+ (1,0) [0|3] "" gtw + SG_ VCLEFT_hornSwitchPressed m0: 2|1@1+ (1,0) [0|1] "" app + SG_ VCLEFT_btnWindowSwPackUpRF m0: 40|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowAutoUpLR m1: 33|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_btnWindowSwPackAutoDownRF m0: 43|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_switchStatusIndex M: 0|2@1+ (1,0) [0|2] "" X + SG_ VCLEFT_btnWindowDownLR m1: 34|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_rearHVACButtonPressed m0: 61|1@1+ (1,0) [0|1] "" gtw + +BO_ 259 VCRIGHT_doorStatus: 8 VEH + SG_ VCRIGHT_reservedForBackCompat : 28|2@1+ (1,0) [0|3] "" X + SG_ VCRIGHT_trunkLatchStatus : 56|4@1+ (1,0) [0|8] "" di + SG_ VCRIGHT_mirrorFoldState : 52|3@1+ (1,0) [0|4] "" gtw + SG_ VCRIGHT_rearLatchStatus : 4|4@1+ (1,0) [0|8] "" aps + SG_ VCRIGHT_mirrorTiltYPosition : 41|8@1+ (0.02,0) [0|5] "V" gtw + SG_ VCRIGHT_frontRelActuatorSwitch : 12|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_mirrorRecallState : 60|3@1+ (1,0) [0|5] "" gtw + SG_ VCRIGHT_frontIntSwitchPressed : 31|1@1+ (1,0) [0|1] "" aps + SG_ VCRIGHT_mirrorState : 49|3@1+ (1,0) [0|4] "" gtw + SG_ VCRIGHT_rearRelActuatorSwitch : 13|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_frontHandlePulledPersist : 30|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_mirrorTiltXPosition : 33|8@1+ (0.02,0) [0|5] "V" gtw + SG_ VCRIGHT_mirrorDipped : 63|1@1+ (1,0) [0|1] "" X + SG_ VCRIGHT_frontHandlePulled : 10|1@1+ (1,0) [0|1] "" aps + SG_ VCRIGHT_frontLatchStatus : 0|4@1+ (1,0) [0|8] "" aps + SG_ VCRIGHT_rearHandlePulled : 11|1@1+ (1,0) [0|1] "" aps + SG_ VCRIGHT_frontHandlePWM : 14|7@1+ (1,0) [0|100] "%" X + SG_ VCRIGHT_frontLatchSwitch : 8|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_rearLatchSwitch : 9|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_rearHandlePWM : 21|7@1+ (1,0) [0|100] "%" X + SG_ VCRIGHT_rearIntSwitchPressed : 32|1@1+ (1,0) [0|1] "" aps + +BO_ 585 SCCM_leftStalk: 3 VEH + SG_ SCCM_leftStalkCounter : 8|4@1+ (1,0) [0|15] "" X + SG_ SCCM_washWipeButtonStatus : 14|2@1+ (1,0) [0|3] "" das + SG_ SCCM_turnIndicatorStalkStatus : 16|3@1+ (1,0) [0|5] "" das + SG_ SCCM_leftStalkCrc : 0|8@1+ (1,0) [0|255] "" X + SG_ SCCM_leftStalkReserved1 : 19|5@1+ (1,0) [0|31] "" X + SG_ SCCM_highBeamStalkStatus : 12|2@1+ (1,0) [0|3] "" das + +BO_ 280 DI_systemStatus: 8 VEH + SG_ DI_epbRequest : 44|2@1+ (1,0) [0|2] "" epbl + SG_ DI_systemStatusCounter : 8|4@1+ (1,0) [0|15] "" X + SG_ DI_proximity : 46|1@1+ (1,0) [0|1] "" bms + SG_ DI_keepAliveRequest : 47|1@1+ (1,0) [0|1] "" bms + SG_ DI_accelPedalPos : 32|8@1+ (0.4,0) [0|100] "%" vcfront + SG_ DI_gear : 21|3@1+ (1,0) [0|7] "" gtw + SG_ DI_tractionControlMode : 40|3@1+ (1,0) [0|5] "" X + SG_ DI_trackModeState : 48|2@1+ (1,0) [0|2] "" gtw + SG_ DI_regenLight : 26|1@1+ (1,0) [0|1] "" vcleft + SG_ DI_systemState : 16|3@1+ (1,0) [0|5] "" epbl + SG_ DI_immobilizerState : 27|3@1+ (1,0) [0|6] "" X + SG_ DI_systemStatusChecksum : 0|8@1+ (1,0) [0|255] "" X + SG_ DI_brakePedalState : 19|2@1+ (1,0) [0|2] "" vcleft + +BO_ 835 VCRIGHT_status: 8 VEH + SG_ VCRIGHT_5AVoltage : 18|10@1+ (0.005443676098,0) [0|5.56888] "V" gtw + SG_ VCRIGHT_loadShedPriority : 0|8@1+ (1,0) [0|255] "" X + SG_ VCRIGHT_rearDefrostState : 11|3@1+ (1,0) [0|4] "" gtw + SG_ VCRIGHT_vbatProt : 28|12@1+ (0.005443676098,0) [0|22.29185] "V" gtw + SG_ VCRIGHT_vehiclePowerStateDBG : 8|2@1+ (1,0) [0|3] "" gtw + SG_ VCRIGHT_swEnStatus : 10|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_mirrorHeatState : 14|3@1+ (1,0) [0|4] "" X + SG_ VCRIGHT_OTAState : 17|1@1+ (1,0) [0|1] "" gtw + SG_ VCRIGHT_footwellLightCurrent : 40|12@1- (0.1,0) [-204.8|204.7] "mA" X + SG_ VCRIGHT_pcbaTemperature : 52|11@1+ (0.125,-40) [-40|150] "degC" gtw + +BO_ 553 SCCM_rightStalk: 3 VEH + SG_ SCCM_rightStalkCounter : 8|4@1+ (1,0) [0|15] "" X + SG_ SCCM_rightStalkCrc : 0|8@1+ (1,0) [0|255] "" X + SG_ SCCM_rightStalkReserved1 : 15|1@1+ (1,0) [0|1] "" X + SG_ SCCM_parkButtonStatus : 16|2@1+ (1,0) [0|3] "" das + SG_ SCCM_rightStalkReserved2 : 18|6@1+ (1,0) [0|63] "" X + SG_ SCCM_rightStalkStatus : 12|3@1+ (1,0) [0|6] "" das + +BO_ 297 SCCM_steeringAngleSensor: 8 VEH + SG_ SCCM_steeringAngleValidity : 30|2@1+ (1,0) [0|3] "" gtw + SG_ SCCM_supplierID : 12|2@1+ (1,0) [0|3] "" gtw + SG_ SCCM_steeringAngleSensorReservd1 : 46|2@1+ (1,0) [0|3] "" X + SG_ SCCM_steeringAngleCrc : 0|8@1+ (1,0) [0|255] "" gtw + SG_ SCCM_steeringAngleSensorStatus : 14|2@1+ (1,0) [0|3] "" aps + SG_ SCCM_steeringAngleSpeed : 32|14@1+ (0.5,-4096) [-4096|4095.5] "deg/s" das + SG_ SCCM_steeringAngle : 16|14@1+ (0.1,-819.2) [-819.2|819] "deg" aps + SG_ SCCM_steeringAngleSensorReservd2 : 48|8@1+ (1,0) [0|255] "" X + SG_ SCCM_steeringAngleCounter : 8|4@1+ (1,0) [0|15] "" gtw + SG_ SCCM_steeringAngleSensorReservd3 : 56|8@1+ (1,0) [0|255] "" X + +BO_ 258 VCLEFT_doorStatus: 8 VEH + SG_ VCLEFT_mirrorDipped : 61|1@1+ (1,0) [0|1] "" X + SG_ VCLEFT_frontHandlePulledPersist : 62|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_mirrorRecallState : 55|3@1+ (1,0) [0|5] "" gtw + SG_ VCLEFT_rearIntSwitchPressed : 32|1@1+ (1,0) [0|1] "" aps + SG_ VCLEFT_rearLatchSwitch : 9|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_rearHandlePWM : 24|7@1+ (1,0) [0|100] "%" X + SG_ VCLEFT_frontLatchSwitch : 8|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_frontHandlePWM : 16|7@1+ (1,0) [0|100] "%" X + SG_ VCLEFT_rearHandlePulled : 11|1@1+ (1,0) [0|1] "" aps + SG_ VCLEFT_rearLatchStatus : 4|4@1+ (1,0) [0|8] "" aps + SG_ VCLEFT_frontHandlePulled : 10|1@1+ (1,0) [0|1] "" aps + SG_ VCLEFT_mirrorTiltXPosition : 33|8@1+ (0.02,0) [0|5] "V" gtw + SG_ VCLEFT_mirrorState : 49|3@1+ (1,0) [0|4] "" gtw + SG_ VCLEFT_frontIntSwitchPressed : 31|1@1+ (1,0) [0|1] "" aps + SG_ VCLEFT_rearRelActuatorSwitch : 13|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_mirrorHeatState : 58|3@1+ (1,0) [0|4] "" X + SG_ VCLEFT_frontRelActuatorSwitch : 12|1@1+ (1,0) [0|1] "" gtw + SG_ VCLEFT_mirrorTiltYPosition : 41|8@1+ (0.02,0) [0|5] "V" gtw + SG_ VCLEFT_frontLatchStatus : 0|4@1+ (1,0) [0|8] "" aps + SG_ VCLEFT_mirrorFoldState : 52|3@1+ (1,0) [0|4] "" gtw + + +BO_ 568 STW_ACTN_RQ: 8 STW + SG_ SpdCtrlLvr_Stat : 0|6@1+ (1,0) [0|0] "" NEO + SG_ VSL_Enbl_Rq : 6|1@1+ (1,0) [0|0] "" NEO + SG_ SpdCtrlLvrStat_Inv : 7|1@1+ (1,0) [0|0] "" NEO + SG_ DTR_Dist_Rq : 8|8@1+ (1,0) [0|200] "" NEO + SG_ TurnIndLvr_Stat : 16|2@1+ (1,0) [0|0] "" NEO + SG_ HiBmLvr_Stat : 18|2@1+ (1,0) [0|0] "" NEO + SG_ WprWashSw_Psd : 20|2@1+ (1,0) [0|0] "" NEO + SG_ WprWash_R_Sw_Posn_V2 : 22|2@1+ (1,0) [0|0] "" NEO + SG_ StW_Lvr_Stat : 24|3@1+ (1,0) [0|0] "" NEO + SG_ StW_Cond_Flt : 27|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Cond_Psd : 28|2@1+ (1,0) [0|0] "" NEO + SG_ HrnSw_Psd : 30|2@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw00_Psd : 32|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw01_Psd : 33|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw02_Psd : 34|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw03_Psd : 35|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw04_Psd : 36|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw05_Psd : 37|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw06_Psd : 38|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw07_Psd : 39|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw08_Psd : 40|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw09_Psd : 41|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw10_Psd : 42|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw11_Psd : 43|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw12_Psd : 44|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw13_Psd : 45|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw14_Psd : 46|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw15_Psd : 47|1@1+ (1,0) [0|0] "" NEO + SG_ WprSw6Posn : 48|3@1+ (1,0) [0|0] "" NEO + SG_ MC_STW_ACTN_RQ : 52|4@1+ (1,0) [0|15] "" NEO + SG_ CRC_STW_ACTN_RQ : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 1001 DAS_bodyControls: 8 VEH + SG_ DAS_headlightRequest : 0|2@1+ (1,0) [0|3] "" aps + SG_ DAS_hazardLightRequest : 2|2@1+ (1,0) [0|3] "" aps + SG_ DAS_wiperSpeed : 4|4@1+ (1,0) [0|15] "" aps + SG_ DAS_turnIndicatorRequest : 8|2@1+ (1,0) [0|3] "" aps + SG_ DAS_highLowBeamDecision : 10|2@1+ (1,0) [0|3] "" aps + SG_ DAS_heaterRequest : 12|2@1+ (1,0) [0|2] "" aps + SG_ DAS_turnIndicatorRequestReason : 17|4@1+ (1,0) [0|8] "" aps + SG_ DAS_autopilotActive : 24|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_accActive : 29|1@1+ (1,0) [0|1] "" XXX + SG_ DAS_bodyControlsCounter : 52|4@1+ (1,0) [0|15] "" aps + SG_ DAS_bodyControlsChecksum : 56|8@1+ (1,0) [0|255] "" aps + +BO_ 1013 ID3F5VCFRONT_lighting: 8 VEH + SG_ VCFRONT_lowBeamsCalibrated : 62|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_lowBeamsOnForDRL : 61|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_simLatchingStalk : 59|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_highBeamSwitchActive : 58|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_parkRightStatus : 56|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_parkLeftStatus : 54|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_turnSignalRightStatus : 52|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_turnSignalLeftStatus : 50|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_sideRepeaterRightStatus : 48|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_sideRepeaterLeftStatus : 46|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_sideMarkersStatus : 44|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_fogRightStatus : 42|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_fogLeftStatus : 40|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_DRLRightStatus : 38|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_DRLLeftStatus : 36|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_highBeamRightStatus : 34|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_highBeamLeftStatus : 32|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_lowBeamRightStatus : 30|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_lowBeamLeftStatus : 28|2@1+ (1,0) [0|3] "" Receiver + SG_ VCFRONT_hazardSwitchBacklight : 27|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_seeYouHomeLightingReq : 26|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_approachLightingRequest : 25|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_courtesyLightingRequest : 24|1@1+ (1,0) [0|1] "" Receiver + SG_ VCFRONT_switchLightingBrightness : 16|8@1+ (0.5,0) [0|127] "%" Receiver + SG_ VCFRONT_ambientLightingBrightnes : 8|8@1+ (0.5,0) [0|127] "%" Receiver + SG_ VCFRONT_hazardLightRequest : 4|4@1+ (1,0) [0|8] "" Receiver + SG_ VCFRONT_indicatorRightRequest : 2|2@1+ (1,0) [0|2] "" Receiver + SG_ VCFRONT_indicatorLeftRequest : 0|2@1+ (1,0) [0|2] "" Receiver + +VAL_ 568 SpdCtrlLvr_Stat 32 "DN_1ST" 16 "UP_1ST" 8 "DN_2ND" 4 "UP_2ND" 2 "RWD" 1 "FWD" 0 "IDLE" ; +VAL_ 568 DTR_Dist_Rq 255 "SNA" 200 "ACC_DIST_7" 166 "ACC_DIST_6" 133 "ACC_DIST_5" 100 "ACC_DIST_4" 66 "ACC_DIST_3" 33 "ACC_DIST_2" 0 "ACC_DIST_1" ; +VAL_ 568 TurnIndLvr_Stat 3 "SNA" 2 "RIGHT" 1 "LEFT" 0 "IDLE" ; +VAL_ 568 HiBmLvr_Stat 3 "SNA" 2 "HIBM_FLSH_ON_PSD" 1 "HIBM_ON_PSD" 0 "IDLE" ; +VAL_ 568 WprWashSw_Psd 3 "SNA" 2 "WASH" 1 "TIPWIPE" 0 "NPSD" ; +VAL_ 568 WprWash_R_Sw_Posn_V2 3 "SNA" 2 "WASH" 1 "INTERVAL" 0 "OFF" ; +VAL_ 568 StW_Lvr_Stat 4 "STW_BACK" 3 "STW_FWD" 2 "STW_DOWN" 1 "STW_UP" 0 "NPSD" ; +VAL_ 568 StW_Cond_Psd 3 "SNA" 2 "DOWN" 1 "UP" 0 "NPSD" ; +VAL_ 568 HrnSw_Psd 3 "SNA" 2 "NDEF2" 1 "PSD" 0 "NPSD" ; +VAL_ 568 StW_Sw00_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 StW_Sw01_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 StW_Sw03_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 StW_Sw04_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 WprSw6Posn 7 "SNA" 6 "STAGE2" 5 "STAGE1" 4 "INTERVAL4" 3 "INTERVAL3" 2 "INTERVAL2" 1 "INTERVAL1" 0 "OFF" ; + +VAL_ 1001 DAS_headlightRequest 3 "DAS_HEADLIGHT_REQUEST_INVALID" 1 "DAS_HEADLIGHT_REQUEST_ON" 0 "DAS_HEADLIGHT_REQUEST_OFF"; +VAL_ 1001 DAS_hazardLightRequest 3 "DAS_REQUEST_HAZARDS_SNA" 2 "DAS_REQUEST_HAZARDS_UNUSED" 0 "DAS_REQUEST_HAZARDS_OFF" 1 "DAS_REQUEST_HAZARDS_ON"; +VAL_ 1001 DAS_wiperSpeed 3 "DAS_WIPER_SPEED_3" 12 "DAS_WIPER_SPEED_12" 8 "DAS_WIPER_SPEED_8" 14 "DAS_WIPER_SPEED_14" 5 "DAS_WIPER_SPEED_5" 13 "DAS_WIPER_SPEED_13" 2 "DAS_WIPER_SPEED_2" 0 "DAS_WIPER_SPEED_OFF" 4 "DAS_WIPER_SPEED_4" 1 "DAS_WIPER_SPEED_1" 15 "DAS_WIPER_SPEED_INVALID" 10 "DAS_WIPER_SPEED_10" 11 "DAS_WIPER_SPEED_11" 7 "DAS_WIPER_SPEED_7" 9 "DAS_WIPER_SPEED_9" 6 "DAS_WIPER_SPEED_6"; +VAL_ 1001 DAS_turnIndicatorRequest 0 "DAS_TURN_INDICATOR_NONE" 2 "DAS_TURN_INDICATOR_RIGHT" 3 "DAS_TURN_INDICATOR_CANCEL" 1 "DAS_TURN_INDICATOR_LEFT"; +VAL_ 1001 DAS_highLowBeamDecision 2 "DAS_HIGH_BEAM_ON" 1 "DAS_HIGH_BEAM_OFF" 3 "DAS_HIGH_BEAM_SNA" 0 "DAS_HIGH_BEAM_UNDECIDED"; +VAL_ 1001 DAS_heaterRequest 0 "DAS_HEATER_SNA" 2 "DAS_HEATER_ON" 1 "DAS_HEATER_OFF"; +VAL_ 1001 DAS_turnIndicatorRequestReason 8 "DAS_ACTIVE_COMMANDED_LANE_CHANGE" 4 "DAS_CANCEL_LANE_CHANGE" 6 "DAS_ACTIVE_MERGE" 2 "DAS_ACTIVE_SPEED_LANE_CHANGE" 5 "DAS_CANCEL_FORK" 0 "DAS_NONE" 3 "DAS_ACTIVE_FORK" 7 "DAS_CANCEL_MERGE" 1 "DAS_ACTIVE_NAV_LANE_CHANGE"; + +VAL_ 1013 VCFRONT_DRLLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_DRLRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_ambientLightingBrightnes 255 "SNA" ; +VAL_ 1013 VCFRONT_fogLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_fogRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_hazardLightRequest 1 "HAZARD_REQUEST_BUTTON" 6 "HAZARD_REQUEST_CAR_ALARM" 5 "HAZARD_REQUEST_CRASH" 7 "HAZARD_REQUEST_DAS" 2 "HAZARD_REQUEST_LOCK" 4 "HAZARD_REQUEST_MISLOCK" 0 "HAZARD_REQUEST_NONE" 8 "HAZARD_REQUEST_UDS" 3 "HAZARD_REQUEST_UNLOCK" ; +VAL_ 1013 VCFRONT_highBeamLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_highBeamRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_indicatorLeftRequest 2 "TURN_SIGNAL_ACTIVE_HIGH" 1 "TURN_SIGNAL_ACTIVE_LOW" 0 "TURN_SIGNAL_OFF" ; +VAL_ 1013 VCFRONT_indicatorRightRequest 2 "TURN_SIGNAL_ACTIVE_HIGH" 1 "TURN_SIGNAL_ACTIVE_LOW" 0 "TURN_SIGNAL_OFF" ; +VAL_ 1013 VCFRONT_lowBeamLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_lowBeamRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_parkLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_parkRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_sideMarkersStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_sideRepeaterLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_sideRepeaterRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_simLatchingStalk 0 "SIMULATED_LATCHING_STALK_IDLE" 1 "SIMULATED_LATCHING_STALK_LEFT" 2 "SIMULATED_LATCHING_STALK_RIGHT" 3 "SIMULATED_LATCHING_STALK_SNA" ; +VAL_ 1013 VCFRONT_switchLightingBrightness 255 "SNA" ; +VAL_ 1013 VCFRONT_turnSignalLeftStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 1013 VCFRONT_turnSignalRightStatus 2 "LIGHT_FAULT" 0 "LIGHT_OFF" 1 "LIGHT_ON" 3 "LIGHT_SNA" ; +VAL_ 962 VCLEFT_frontBuckleSwitch 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatTrackBack 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_rightMirrorTilt 4 "MIRROR_TILT_LEFT" 2 "MIRROR_TILT_UP" 3 "MIRROR_TILT_RIGHT" 0 "MIRROR_TILT_STOP" 1 "MIRROR_TILT_DOWN"; +VAL_ 962 VCLEFT_frontOccupancySwitch 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_swcRightTiltLeft 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_rearRightOccupancySwitch 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_swcLeftTiltRight 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatBackrestForward 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_swcRightTiltRight 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatLumbarIn 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatLiftUp 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatLumbarDown 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatTiltDown 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatTrackForward 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_rearLeftBuckleSwitch 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_swcRightPressed 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatLumbarOut 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_swcLeftTiltLeft 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_swcLeftPressed 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatTiltUp 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_rearLeftOccupancySwitch 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatBackrestBack 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_rearCenterOccupancySwitch 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatLumbarUp 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_frontSeatLiftDown 2 "SWITCH_ON" 0 "SWITCH_SNA" 3 "SWITCH_FAULT" 1 "SWITCH_OFF"; +VAL_ 962 VCLEFT_switchStatusIndex 1 "VCLEFT_SWITCH_STATUS_INDEX_1" 2 "VCLEFT_SWITCH_STATUS_INDEX_INVALID" 0 "VCLEFT_SWITCH_STATUS_INDEX_0"; +VAL_ 259 VCRIGHT_trunkLatchStatus 8 "LATCH_FAULT" 2 "LATCH_CLOSED" 1 "LATCH_OPENED" 3 "LATCH_CLOSING" 7 "LATCH_DEFAULT" 4 "LATCH_OPENING" 5 "LATCH_AJAR" 6 "LATCH_TIMEOUT" 0 "LATCH_SNA"; +VAL_ 259 VCRIGHT_mirrorFoldState 4 "MIRROR_FOLD_STATE_UNFOLDING" 1 "MIRROR_FOLD_STATE_FOLDED" 3 "MIRROR_FOLD_STATE_FOLDING" 0 "MIRROR_FOLD_STATE_UNKNOWN" 2 "MIRROR_FOLD_STATE_UNFOLDED"; +VAL_ 259 VCRIGHT_rearLatchStatus 8 "LATCH_FAULT" 2 "LATCH_CLOSED" 1 "LATCH_OPENED" 3 "LATCH_CLOSING" 7 "LATCH_DEFAULT" 4 "LATCH_OPENING" 5 "LATCH_AJAR" 6 "LATCH_TIMEOUT" 0 "LATCH_SNA"; +VAL_ 259 VCRIGHT_mirrorRecallState 5 "MIRROR_RECALL_STATE_RECALLING_STOPPED" 2 "MIRROR_RECALL_STATE_RECALLING_AXIS_2" 0 "MIRROR_RECALL_STATE_INIT" 3 "MIRROR_RECALL_STATE_RECALLING_COMPLETE" 4 "MIRROR_RECALL_STATE_RECALLING_FAILED" 1 "MIRROR_RECALL_STATE_RECALLING_AXIS_1"; +VAL_ 259 VCRIGHT_mirrorState 3 "MIRROR_STATE_FOLD_UNFOLD" 1 "MIRROR_STATE_TILT_X" 0 "MIRROR_STATE_IDLE" 2 "MIRROR_STATE_TILT_Y" 4 "MIRROR_STATE_RECALL"; +VAL_ 259 VCRIGHT_frontLatchStatus 8 "LATCH_FAULT" 2 "LATCH_CLOSED" 1 "LATCH_OPENED" 3 "LATCH_CLOSING" 7 "LATCH_DEFAULT" 4 "LATCH_OPENING" 5 "LATCH_AJAR" 6 "LATCH_TIMEOUT" 0 "LATCH_SNA"; +VAL_ 585 SCCM_washWipeButtonStatus 3 "SNA" 0 "NOT_PRESSED" 2 "2ND_DETENT" 1 "1ST_DETENT"; +VAL_ 585 SCCM_turnIndicatorStalkStatus 3 "DOWN_1" 5 "SNA" 0 "IDLE" 1 "UP_1" 4 "DOWN_2" 2 "UP_2"; +VAL_ 585 SCCM_highBeamStalkStatus 3 "SNA" 0 "IDLE" 1 "PULL" 2 "PUSH"; +VAL_ 280 DI_epbRequest 0 "DI_EPBREQUEST_NO_REQUEST" 1 "DI_EPBREQUEST_PARK" 2 "DI_EPBREQUEST_UNPARK"; +VAL_ 280 DI_keepAliveRequest 1 "KEEP_ALIVE" 0 "NO_REQUEST"; +VAL_ 280 DI_accelPedalPos 255 "SNA"; +VAL_ 280 DI_gear 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" 7 "DI_GEAR_SNA" 2 "DI_GEAR_R" 3 "DI_GEAR_N" 4 "DI_GEAR_D"; +VAL_ 280 DI_tractionControlMode 0 "TC_NORMAL" 1 "TC_SLIP_START" 4 "TC_ROLLS_MODE" 2 "TC_DEV_MODE_1" 5 "TC_DYNO_MODE" 3 "TC_DEV_MODE_2"; +VAL_ 280 DI_trackModeState 0 "TRACK_MODE_UNAVAILABLE" 1 "TRACK_MODE_AVAILABLE" 2 "TRACK_MODE_ON"; +VAL_ 280 DI_systemState 5 "DI_SYS_ENABLE" 1 "DI_SYS_IDLE" 2 "DI_SYS_STANDBY" 0 "DI_SYS_UNAVAILABLE" 3 "DI_SYS_FAULT" 4 "DI_SYS_ABORT"; +VAL_ 280 DI_immobilizerState 2 "DI_IMM_STATE_AUTHENTICATING" 0 "DI_IMM_STATE_INIT_SNA" 3 "DI_IMM_STATE_DISARMED" 4 "DI_IMM_STATE_IDLE" 6 "DI_IMM_STATE_FAULT" 1 "DI_IMM_STATE_REQUEST" 5 "DI_IMM_STATE_RESET"; +VAL_ 280 DI_brakePedalState 2 "INVALID" 0 "OFF" 1 "ON"; +VAL_ 835 VCRIGHT_rearDefrostState 2 "HEATER_STATE_OFF" 4 "HEATER_STATE_FAULT" 1 "HEATER_STATE_ON" 0 "HEATER_STATE_SNA" 3 "HEATER_STATE_OFF_UNAVAILABLE"; +VAL_ 835 VCRIGHT_vehiclePowerStateDBG 3 "VEHICLE_POWER_STATE_DRIVE" 1 "VEHICLE_POWER_STATE_CONDITIONING" 2 "VEHICLE_POWER_STATE_ACCESSORY" 0 "VEHICLE_POWER_STATE_OFF"; +VAL_ 835 VCRIGHT_mirrorHeatState 2 "HEATER_STATE_OFF" 4 "HEATER_STATE_FAULT" 1 "HEATER_STATE_ON" 0 "HEATER_STATE_SNA" 3 "HEATER_STATE_OFF_UNAVAILABLE"; +VAL_ 553 SCCM_parkButtonStatus 3 "SNA" 0 "NOT_PRESSED" 2 "INIT" 1 "PRESSED"; +VAL_ 553 SCCM_rightStalkStatus 3 "DOWN_1" 6 "SNA" 0 "IDLE" 5 "INIT" 1 "UP_1" 4 "DOWN_2" 2 "UP_2"; +VAL_ 297 SCCM_steeringAngleValidity 3 "SNA" 2 "INIT" 0 "INVALID" 1 "VALID"; +VAL_ 297 SCCM_steeringAngleSensorStatus 0 "OK" 1 "INIT" 2 "ERROR" 3 "ERROR_INIT"; +VAL_ 258 VCLEFT_mirrorRecallState 5 "MIRROR_RECALL_STATE_RECALLING_STOPPED" 2 "MIRROR_RECALL_STATE_RECALLING_AXIS_2" 0 "MIRROR_RECALL_STATE_INIT" 3 "MIRROR_RECALL_STATE_RECALLING_COMPLETE" 4 "MIRROR_RECALL_STATE_RECALLING_FAILED" 1 "MIRROR_RECALL_STATE_RECALLING_AXIS_1"; +VAL_ 258 VCLEFT_rearLatchStatus 8 "LATCH_FAULT" 2 "LATCH_CLOSED" 1 "LATCH_OPENED" 3 "LATCH_CLOSING" 7 "LATCH_DEFAULT" 4 "LATCH_OPENING" 5 "LATCH_AJAR" 6 "LATCH_TIMEOUT" 0 "LATCH_SNA"; +VAL_ 258 VCLEFT_mirrorState 3 "MIRROR_STATE_FOLD_UNFOLD" 1 "MIRROR_STATE_TILT_X" 0 "MIRROR_STATE_IDLE" 2 "MIRROR_STATE_TILT_Y" 4 "MIRROR_STATE_RECALL"; +VAL_ 258 VCLEFT_mirrorHeatState 2 "HEATER_STATE_OFF" 4 "HEATER_STATE_FAULT" 1 "HEATER_STATE_ON" 0 "HEATER_STATE_SNA" 3 "HEATER_STATE_OFF_UNAVAILABLE"; +VAL_ 258 VCLEFT_frontLatchStatus 8 "LATCH_FAULT" 2 "LATCH_CLOSED" 1 "LATCH_OPENED" 3 "LATCH_CLOSING" 7 "LATCH_DEFAULT" 4 "LATCH_OPENING" 5 "LATCH_AJAR" 6 "LATCH_TIMEOUT" 0 "LATCH_SNA"; +VAL_ 258 VCLEFT_mirrorFoldState 4 "MIRROR_FOLD_STATE_UNFOLDING" 1 "MIRROR_FOLD_STATE_FOLDED" 3 "MIRROR_FOLD_STATE_FOLDING" 0 "MIRROR_FOLD_STATE_UNKNOWN" 2 "MIRROR_FOLD_STATE_UNFOLDED"; diff --git a/opendbc_repo/opendbc/dbc/tesla_powertrain.dbc b/opendbc_repo/opendbc/dbc/tesla_powertrain.dbc new file mode 100644 index 0000000000..8572ee20f4 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/tesla_powertrain.dbc @@ -0,0 +1,179 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: + NEO + MCU + GTW + EPAS + DI + ESP + SBW + STW + APP + DAS + XXX + +BO_ 262 DI_torque1: 8 DI + SG_ DI_torqueDriver : 0|13@1- (0.25,0) [-750|750] "Nm" NEO + SG_ DI_torque1Counter : 13|3@1+ (1,0) [0|0] "" NEO + SG_ DI_torqueMotor : 16|13@1- (0.25,0) [-750|750] "Nm" NEO + SG_ DI_soptState : 29|3@1+ (1,0) [0|0] "" NEO + SG_ DI_motorRPM : 32|16@1- (1,0) [-17000|17000] "RPM" NEO + SG_ DI_pedalPos : 48|8@1+ (0.4,0) [0|100] "%" NEO + SG_ DI_torque1Checksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 278 DI_torque2: 6 DI + SG_ DI_torqueEstimate : 0|12@1- (0.5,0) [-750|750] "Nm" NEO + SG_ DI_gear : 12|3@1+ (1,0) [0|0] "" NEO + SG_ DI_brakePedal : 15|1@1+ (1,0) [0|0] "" NEO + SG_ DI_vehicleSpeed : 16|12@1+ (0.05,-25) [-25|179.75] "MPH" NEO + SG_ DI_gearRequest : 28|3@1+ (1,0) [0|0] "" NEO + SG_ DI_torqueInterfaceFailure : 31|1@1+ (1,0) [0|0] "" NEO + SG_ DI_torque2Counter : 32|4@1+ (1,0) [0|0] "" NEO + SG_ DI_brakePedalState : 36|2@1+ (1,0) [0|0] "" NEO + SG_ DI_epbParkRequest : 38|1@1+ (1,0) [0|0] "" NEO + SG_ DI_epbInterfaceReady : 39|1@1+ (1,0) [0|0] "" NEO + SG_ DI_torque2Checksum : 40|8@1+ (1,0) [0|0] "" NEO + +BO_ 504 BrakeMessage: 8 XXX + SG_ driverBrakeStatus : 2|2@1+ (1,0) [0|3] "" XXX + +BO_ 568 STW_ACTN_RQ: 8 STW + SG_ SpdCtrlLvr_Stat : 0|6@1+ (1,0) [0|0] "" NEO + SG_ VSL_Enbl_Rq : 6|1@1+ (1,0) [0|0] "" NEO + SG_ SpdCtrlLvrStat_Inv : 7|1@1+ (1,0) [0|0] "" NEO + SG_ DTR_Dist_Rq : 8|8@1+ (1,0) [0|200] "" NEO + SG_ TurnIndLvr_Stat : 16|2@1+ (1,0) [0|0] "" NEO + SG_ HiBmLvr_Stat : 18|2@1+ (1,0) [0|0] "" NEO + SG_ WprWashSw_Psd : 20|2@1+ (1,0) [0|0] "" NEO + SG_ WprWash_R_Sw_Posn_V2 : 22|2@1+ (1,0) [0|0] "" NEO + SG_ StW_Lvr_Stat : 24|3@1+ (1,0) [0|0] "" NEO + SG_ StW_Cond_Flt : 27|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Cond_Psd : 28|2@1+ (1,0) [0|0] "" NEO + SG_ HrnSw_Psd : 30|2@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw00_Psd : 32|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw01_Psd : 33|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw02_Psd : 34|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw03_Psd : 35|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw04_Psd : 36|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw05_Psd : 37|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw06_Psd : 38|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw07_Psd : 39|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw08_Psd : 40|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw09_Psd : 41|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw10_Psd : 42|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw11_Psd : 43|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw12_Psd : 44|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw13_Psd : 45|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw14_Psd : 46|1@1+ (1,0) [0|0] "" NEO + SG_ StW_Sw15_Psd : 47|1@1+ (1,0) [0|0] "" NEO + SG_ WprSw6Posn : 48|3@1+ (1,0) [0|0] "" NEO + SG_ MC_STW_ACTN_RQ : 52|4@1+ (1,0) [0|15] "" NEO + SG_ CRC_STW_ACTN_RQ : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 598 DI_state: 8 DI + SG_ DI_systemState : 0|3@1+ (1,0) [0|0] "" NEO + SG_ DI_vehicleHoldState : 3|3@1+ (1,0) [0|0] "" NEO + SG_ DI_proximity : 6|1@1+ (1,0) [0|0] "" NEO + SG_ DI_driveReady : 7|1@1+ (1,0) [0|0] "" NEO + SG_ DI_regenLight : 8|1@1+ (1,0) [0|0] "" NEO + SG_ DI_state : 9|3@1+ (1,0) [0|0] "" NEO + SG_ DI_cruiseState : 12|4@1+ (1,0) [0|0] "" NEO + SG_ DI_analogSpeed : 16|12@1+ (0.1,0) [0|150] "speed" NEO + SG_ DI_immobilizerState : 28|3@1+ (1,0) [0|0] "" NEO + SG_ DI_speedUnits : 31|1@1+ (1,0) [0|1] "" NEO + SG_ DI_cruiseSet : 32|9@1+ (0.5,0) [0|255.5] "speed" NEO + SG_ DI_aebState : 41|3@1+ (1,0) [0|0] "" NEO + SG_ DI_stateCounter : 44|4@1+ (1,0) [0|0] "" NEO + SG_ DI_digitalSpeed : 48|8@1+ (1,0) [0|250] "" NEO + SG_ DI_stateChecksum : 56|8@1+ (1,0) [0|0] "" NEO + +BO_ 703 DAS_control: 8 GTW + SG_ DAS_setSpeed : 0|12@1+ (0.1,0) [0|409.4] "kph" DI,PM,APS + SG_ DAS_accState : 12|4@1+ (1,0) [0|0] "" DI,PM,APS + SG_ DAS_aebEvent : 16|2@1+ (1,0) [0|3] "" DI,PM,APS + SG_ DAS_jerkMin : 18|9@1+ (0.03,-15.232) [-15.232|0.098] "m/s^3" DI,PM,APS + SG_ DAS_jerkMax : 27|8@1+ (0.059,0) [0|15.045] "m/s^3" DI,PM,APS + SG_ DAS_accelMin : 35|9@1+ (0.04,-15) [-15|5.44] "m/s^2" DI,PM,APS + SG_ DAS_accelMax : 44|9@1+ (0.04,-15) [-15|5.44] "m/s^2" DI,PM,APS + SG_ DAS_controlCounter : 53|3@1+ (1,0) [0|0] "" DI,PM,APS + SG_ DAS_controlChecksum : 56|8@1+ (1,0) [0|0] "" DI,PM,APS + +VAL_ 262 DI_torqueDriver -4096 "SNA" ; +VAL_ 262 DI_torqueMotor -4096 "SNA" ; +VAL_ 262 DI_soptState 7 "SOPT_TEST_SNA" 4 "SOPT_TEST_NOT_RUN" 3 "SOPT_TEST_PASSED" 2 "SOPT_TEST_FAILED" 1 "SOPT_TEST_IN_PROGRESS" 0 "SOPT_PRE_TEST" ; +VAL_ 262 DI_motorRPM -32768 "SNA" ; +VAL_ 262 DI_pedalPos 255 "SNA" ; +VAL_ 278 DI_torqueEstimate -2048 "SNA" ; +VAL_ 278 DI_gear 7 "DI_GEAR_SNA" 4 "DI_GEAR_D" 3 "DI_GEAR_N" 2 "DI_GEAR_R" 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" ; +VAL_ 278 DI_brakePedal 1 "Applied" 0 "Not_applied" ; +VAL_ 278 DI_vehicleSpeed 4095 "SNA" ; +VAL_ 278 DI_gearRequest 7 "DI_GEAR_SNA" 4 "DI_GEAR_D" 3 "DI_GEAR_N" 2 "DI_GEAR_R" 1 "DI_GEAR_P" 0 "DI_GEAR_INVALID" ; +VAL_ 278 DI_torqueInterfaceFailure 1 "TORQUE_INTERFACE_FAILED" 0 "TORQUE_INTERFACE_NORMAL" ; +VAL_ 278 DI_brakePedalState 3 "SNA" 2 "INVALID" 1 "ON" 0 "OFF" ; +VAL_ 278 DI_epbParkRequest 1 "Park_requested" 0 "No_request" ; +VAL_ 278 DI_epbInterfaceReady 1 "EPB_INTERFACE_READY" 0 "EPB_INTERFACE_NOT_READY" ; +VAL_ 504 driverBrakeStatus 2 "APPLIED" 1 "NOT_APPLIED" ; +VAL_ 568 SpdCtrlLvr_Stat 32 "DN_1ST" 16 "UP_1ST" 8 "DN_2ND" 4 "UP_2ND" 2 "RWD" 1 "FWD" 0 "IDLE" ; +VAL_ 568 DTR_Dist_Rq 255 "SNA" 200 "ACC_DIST_7" 166 "ACC_DIST_6" 133 "ACC_DIST_5" 100 "ACC_DIST_4" 66 "ACC_DIST_3" 33 "ACC_DIST_2" 0 "ACC_DIST_1" ; +VAL_ 568 TurnIndLvr_Stat 3 "SNA" 2 "RIGHT" 1 "LEFT" 0 "IDLE" ; +VAL_ 568 HiBmLvr_Stat 3 "SNA" 2 "HIBM_FLSH_ON_PSD" 1 "HIBM_ON_PSD" 0 "IDLE" ; +VAL_ 568 WprWashSw_Psd 3 "SNA" 2 "WASH" 1 "TIPWIPE" 0 "NPSD" ; +VAL_ 568 WprWash_R_Sw_Posn_V2 3 "SNA" 2 "WASH" 1 "INTERVAL" 0 "OFF" ; +VAL_ 568 StW_Lvr_Stat 4 "STW_BACK" 3 "STW_FWD" 2 "STW_DOWN" 1 "STW_UP" 0 "NPSD" ; +VAL_ 568 StW_Cond_Psd 3 "SNA" 2 "DOWN" 1 "UP" 0 "NPSD" ; +VAL_ 568 HrnSw_Psd 3 "SNA" 2 "NDEF2" 1 "PSD" 0 "NPSD" ; +VAL_ 568 StW_Sw00_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 StW_Sw01_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 StW_Sw03_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 StW_Sw04_Psd 1 "PRESSED" 0 "NOT_PRESSED_SNA" ; +VAL_ 568 WprSw6Posn 7 "SNA" 6 "STAGE2" 5 "STAGE1" 4 "INTERVAL4" 3 "INTERVAL3" 2 "INTERVAL2" 1 "INTERVAL1" 0 "OFF" ; +VAL_ 598 DI_aebState 2 "ENABLED" 4 "FAULT" 7 "SNA" 1 "STANDBY" 3 "STANDSTILL" 0 "UNAVAILABLE" ; +VAL_ 598 DI_analogSpeed 4095 "SNA" ; +VAL_ 598 DI_cruiseState 2 "ENABLED" 5 "FAULT" 0 "OFF" 4 "OVERRIDE" 7 "PRE_CANCEL" 6 "PRE_FAULT" 1 "STANDBY" 3 "STANDSTILL" ; +VAL_ 598 DI_digitalSpeed 255 "SNA" ; +VAL_ 598 DI_immobilizerState 2 "AUTHENTICATING" 3 "DISARMED" 6 "FAULT" 4 "IDLE" 0 "INIT_SNA" 1 "REQUEST" 5 "RESET" ; +VAL_ 598 DI_speedUnits 1 "KPH" 0 "MPH" ; +VAL_ 598 DI_state 3 "ABORT" 4 "ENABLE" 2 "FAULT" 1 "STANDBY" 0 "UNAVAILABLE" ; +VAL_ 598 DI_systemState 3 "ABORT" 4 "ENABLE" 2 "FAULT" 1 "STANDBY" 0 "UNAVAILABLE" ; +VAL_ 598 DI_vehicleHoldState 2 "BLEND_IN" 4 "BLEND_OUT" 6 "FAULT" 7 "INIT" 5 "PARK" 1 "STANDBY" 3 "STANDSTILL" 0 "UNAVAILABLE" ; +VAL_ 703 DAS_setSpeed 4095 "SNA" ; +VAL_ 703 DAS_accState 15 "FAULT_SNA" 13 "ACC_CANCEL_GENERIC_SILENT" 11 "APC_SELFPARK_START" 10 "APC_UNPARK_COMPLETE" 9 "APC_PAUSE" 8 "APC_ABORT" 7 "APC_COMPLETE" 6 "APC_FORWARD" 5 "APC_BACKWARD" 4 "ACC_ON" 3 "ACC_HOLD" 0 "ACC_CANCEL_GENERIC" ; +VAL_ 703 DAS_aebEvent 3 "AEB_SNA" 2 "AEB_FAULT" 1 "AEB_ACTIVE" 0 "AEB_NOT_ACTIVE" ; +VAL_ 703 DAS_jerkMin 511 "SNA" ; +VAL_ 703 DAS_jerkMax 255 "SNA" ; +VAL_ 703 DAS_accelMin 511 "SNA" ; +VAL_ 703 DAS_accelMax 511 "SNA" ; \ No newline at end of file diff --git a/opendbc_repo/opendbc/dbc/toyota_2017_ref_pt.dbc b/opendbc_repo/opendbc/dbc/toyota_2017_ref_pt.dbc new file mode 100644 index 0000000000..17cd8f1b36 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/toyota_2017_ref_pt.dbc @@ -0,0 +1,1638 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: AFS BSR CGW CSR DS1 FCM FRD KSS MAV SCS Vector__XXX + + +BO_ 1196 ABG1D50: 8 CGW + SG_ DRABG01 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG02 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG03 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG04 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG05 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG06 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG07 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG08 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1212 ABG1D51: 8 CGW + SG_ DRABG09 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG10 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG11 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG12 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG13 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG14 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG15 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRABG16 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 945 ABG1S01: 8 CGW + SG_ CDT : 22|3@0+ (1,0) [0|0] "" DS1 + SG_ AB : 19|2@0+ (1,0) [0|0] "" DS1 + SG_ DBKLAB : 17|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PODT : 27|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PBKLAB : 25|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ EDRTRG : 44|2@0+ (1,0) [0|0] "" DS1 + +BO_ 836 ACC1F01: 8 DS1 + SG_ DSS1GDRV : 7|10@0- (0.1,0) [0|0] "m/s^2" Vector__XXX + SG_ DS1STAT2 : 13|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ DS1STBK2 : 10|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSWAR : 18|1@0+ (1,0) [0|0] "" FCM + SG_ PCSALM : 17|1@0+ (1,0) [0|0] "" FCM + SG_ PCSOPR : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSABK : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PBATRGR : 30|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PPTRGR : 28|1@0+ (1,0) [0|0] "" FCM + SG_ IBTRGR : 27|1@0+ (1,0) [0|0] "" FCM + SG_ CLEXTRGR : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ IRLT_REQ : 25|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRKHLD : 37|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVSTRGR : 36|1@0+ (1,0) [0|0] "" SCS + SG_ VGRSTRGR : 35|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PREFILL : 33|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PBRTRGR : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSDIS : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PBPREPMP : 40|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCF01SM : 63|8@0+ (1,0) [0|0] "" FCM + +BO_ 1227 ACC1N01: 8 DS1 + SG_ ACCNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ ACCSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ ACCSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ ACCREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 835 ACC1S03: 8 DS1 + SG_ ATACC2 : 7|16@0- (0.001,0) [0|0] "m/s^2" Vector__XXX + SG_ ACCTYPE : 23|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ XTRGT2 : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XLTMD2 : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LCDT2 : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LCNG : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SMC : 17|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ STOKJD : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PMTBRKG : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LVSTP : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LCCWOK : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LCBW2 : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACC : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ AT_RAW : 47|8@0- (0.05,0) [0|0] "m/s^2" Vector__XXX + SG_ ACC03SUM : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 896 ACN1S01: 8 CGW + SG_ R_AC2 : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_HTR : 5|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECOSW : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_EGON : 1|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ BLWON : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SCAC : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CGIH : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FAN_AC : 22|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACHI : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACMAX : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_VSCUS : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_SHTR : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_PTC : 29|2@0+ (1,0) [0|0] "piece" Vector__XXX + SG_ GNRTIH : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_COL_TM : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_HET_TM : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TAMOUT : 55|8@0- (0.625,0) [0|0] "" Vector__XXX + +BO_ 897 ACN1S04: 8 CGW + SG_ R_ACCALL : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_AC_WNG : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_SW_CON : 5|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_BEEP : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_RA_AUT : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_RA_AC : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_RA_LO : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_RA_HI : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_AUTO_D : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_AUTO_P : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_DEF : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_RRDEF : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_RFAUT : 11|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_REC : 10|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_FRS : 9|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_AC : 8|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_MHTR : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_WIPD : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_DUSY : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_SWNG : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_BLW_F : 19|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_OAUT_D : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_OLET_D : 30|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_OAUT_P : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_OLET_P : 26|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ ST_BMN_F : 39|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_AIRPR : 47|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_O2 : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_PLSM : 45|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_KAFUN : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_SAFS : 42|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_ACOFF : 41|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_ONSCRN : 40|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 944 ACN1S07: 6 CGW + SG_ RDEF : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MHTR : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TR_TEMP : 15|8@0+ (0.25,-6.5) [0|0] "" Vector__XXX + SG_ ACN_AMB : 31|8@0+ (1,0) [0|0] "" CSR,DS1,FCM + SG_ AC_AMB05 : 44|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AC_MODE : 43|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1250 AFS1N01: 8 AFS + SG_ AFSNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ AFSSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ AFSSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ AFSREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 913 AFS1S01: 8 AFS + SG_ HLLI : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AZB_ADV : 5|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ HEDH_AZB : 3|1@0+ (1,0) [0|0] "" FCM + SG_ AZB_IND : 13|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ AZB_HIND : 11|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AZB_PRE : 10|1@0+ (1,0) [0|0] "" FCM + SG_ LED_HLI : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LPECU_PR : 24|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 845 AFS1S02: 5 AFS + SG_ AHRR : 17|10@0+ (0.0048828125,0) [0|0] "V" Vector__XXX + SG_ AHVLD : 39|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AHFAIL : 38|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1044 AHB1S01: 8 FCM + SG_ AHB_DUTY : 47|8@0+ (0.5,0) [0|0] "%" Vector__XXX + SG_ F_AHB : 55|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_AHB : 51|4@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 900 AVN1S01: 6 CGW + SG_ RDC : 7|4@0+ (1,0) [0|0] "" SCS + SG_ CONFID01 : 3|2@0+ (1,0) [0|0] "" SCS + SG_ CONF : 1|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LYT : 15|4@0+ (1,0) [0|0] "" SCS + SG_ DRVW : 9|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MWMP : 8|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GRAD : 23|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ HARSHID : 19|4@0+ (1,0) [0|0] "" SCS + SG_ BRANCH : 27|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ HARSH : 35|2@0+ (1,0) [0|0] "" SCS + SG_ TOLLGATE : 33|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TUNL : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LEAVEOUT : 47|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MRGLANE : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LVLANE : 45|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 902 AVN1S03: 6 CGW + SG_ ANS : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CRS1 : 15|1@0+ (1,0) [0|0] "" SCS + SG_ RQAC : 14|7@0+ (0.02,0) [0|0] "G" Vector__XXX + SG_ GUID : 23|1@0+ (1,0) [0|0] "" SCS + SG_ GYRO : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ NCRN : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CRN6 : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CRN5 : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CRN3 : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CRN2 : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CRN1 : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CONFID03 : 31|2@0+ (1,0) [0|0] "" SCS + SG_ CURV : 29|2@0+ (1,0) [0|0] "" SCS + SG_ CVST : 27|1@0+ (1,0) [0|0] "" SCS + SG_ NAVI_STR : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MIND : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ONOFF : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HWPB : 39|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RAD : 38|7@0+ (5,0) [0|0] "m" SCS + SG_ AFS_SW : 41|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVS_SW : 40|1@0+ (1,0) [0|0] "" SCS + +BO_ 911 AVN1S07: 8 CGW + SG_ TOFC_RST : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SL_CSTM : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SL_RMDG : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ST_RTCOM : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVN07VLD : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ST_UCST : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSCOM51 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSCOM52 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSCOM53 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSCOM54 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSCOM55 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSCOM56 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 905 AVN1S08: 8 CGW + SG_ VVSW : 7|3@0+ (1,0) [0|0] "" CSR + SG_ BZV : 4|3@0+ (1,0) [0|0] "" CSR + SG_ DFS : 1|2@0+ (1,0) [0|0] "" CSR + SG_ BZ_M_SW : 15|1@0+ (1,0) [0|0] "" CSR + SG_ VOL_SW : 14|1@0+ (1,0) [0|0] "" CSR + SG_ BM : 13|1@0+ (1,0) [0|0] "" CSR + SG_ DOFR : 12|1@0+ (1,0) [0|0] "" CSR + SG_ RDSW : 11|1@0+ (1,0) [0|0] "" CSR + SG_ FDSW : 10|1@0+ (1,0) [0|0] "" CSR + SG_ RBSW : 9|1@0+ (1,0) [0|0] "" CSR + SG_ FBSW : 8|1@0+ (1,0) [0|0] "" CSR + SG_ NVDP_OK : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DEVICE : 22|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ DISPSIZE : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HPTCSW_L : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HPTCSW_R : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HPTCSW_E : 28|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_MODE : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VARBGM : 26|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ WBGM : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ X_LL : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Y_LL : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ X_RH : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ Y_RH : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 998 AVN1S11: 5 CGW + SG_ SENSPFM : 7|3@0+ (1,0) [0|0] "" SCS + SG_ SENSFAIL : 4|3@0+ (1,0) [0|0] "" SCS + SG_ CONFID11 : 1|2@0+ (1,0) [0|0] "" SCS + SG_ CONFMMC : 15|8@0+ (1,0) [0|0] "" SCS + SG_ DISTERR : 23|8@0+ (1,0) [0|0] "" SCS + SG_ CONFLANE : 31|8@0+ (1,0) [0|0] "" SCS + SG_ CONFDIR : 39|8@0+ (1,0) [0|0] "" SCS + +BO_ 933 AVN1S13: 8 CGW + SG_ HUD_DISP : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRVSIDE : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DT_GP : 5|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ DT_UNIT : 15|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ DIR_TURN : 12|5@0+ (11.25,0) [0|0] "degree" Vector__XXX + SG_ ROTARY : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ROAD_TP1 : 22|15@0+ (1,0) [0|0] "" Vector__XXX + SG_ ROAD_TP2 : 39|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ N_H_UP : 55|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ COMPASS : 54|6@0+ (11.25,0) [0|0] "degree" Vector__XXX + SG_ DIR : 63|6@0+ (11.25,0) [0|0] "degree" Vector__XXX + +BO_ 936 AVN1S16: 5 CGW + SG_ NDADVSRY : 7|5@0+ (1,0) [0|0] "" Vector__XXX + SG_ NDCAUTON : 15|5@0+ (1,0) [0|0] "" Vector__XXX + SG_ NDSSLCT : 23|5@0+ (1,0) [0|0] "" Vector__XXX + SG_ NDCNFDID : 18|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ NDINDST : 25|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVN16SUM : 39|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 999 AVN1S17: 7 CGW + SG_ AVN17VLD : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANEID17 : 6|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRVLANE : 3|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRV_SIDE : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE_NS : 11|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE1FLG : 23|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE2FLG : 19|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE1DIR : 31|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE2DIR : 47|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1000 AVN1S18: 8 CGW + SG_ AVN18VLD : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANEID18 : 6|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE3FLG : 3|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE4FLG : 15|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE5FLG : 11|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE3DIR : 23|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE4DIR : 39|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE5DIR : 55|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1001 AVN1S19: 8 CGW + SG_ AVN19VLD : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANEID19 : 6|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE6FLG : 3|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE7FLG : 15|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE8FLG : 11|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE6DIR : 23|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE7DIR : 39|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ LANE8DIR : 55|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1076 AVN1S20: 8 CGW + SG_ A_LNG_ST : 7|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LANG : 5|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB1 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB2 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB3 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB4 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB5 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB6 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGDB7 : 63|7@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_LNGCHG : 56|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1077 AVN1S21: 8 CGW + SG_ A_OPEN_S : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OPENCHG : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CAPSW_S : 5|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_CLR_S : 3|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ DISP_BRT : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DISP_CNT : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MM_CLOCK : 31|11@0+ (1,0) [0|0] "" Vector__XXX + SG_ CLK_OFST : 36|4@0- (5,0) [0|0] "min" Vector__XXX + SG_ DST : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CLK_TYP : 47|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_UNTTMP : 45|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_UNTSP : 43|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_UNTDST : 41|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_UNTCSP : 55|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_CLRCHG : 52|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_TMPCHG : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_SPCHG : 50|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_DSTCHG : 49|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_CSPCHG : 48|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ A_SPLM : 63|6@0+ (5,0) [0|0] "" Vector__XXX + SG_ A_UTSPLM : 57|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1043 AVN1S31: 8 CGW + SG_ GPSTM_Y : 7|8@0+ (1,0) [0|0] "year" Vector__XXX + SG_ GPSTM_MO : 15|8@0+ (1,0) [0|0] "month" Vector__XXX + SG_ GPSTM_D : 23|8@0+ (1,0) [0|0] "day" Vector__XXX + SG_ GPSTM_H : 31|8@0+ (1,0) [0|0] "hour" Vector__XXX + SG_ GPSTM_MI : 39|8@0+ (1,0) [0|0] "minute" Vector__XXX + SG_ GMT_DIFF : 55|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GMTDIF_H : 54|4@0+ (1,0) [0|0] "hour" Vector__XXX + SG_ GMTDIF_M : 50|6@0+ (1,0) [0|0] "minute" Vector__XXX + SG_ SUMMERTM : 60|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075054137 BDB1F01_14: 8 CGW + SG_ BDBF01ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDBF01IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ SALR : 23|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ HDCY_BDB : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AARE_B : 31|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ I_SEN_B : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ INTSET_B : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ INCSET_B : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ISSD_BDB : 39|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SEID : 37|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ WS_ID : 44|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ WS_SWON : 41|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ WS_DATA : 55|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075185211 BDB1F03_16: 8 CGW + SG_ BDBF03ID : 7|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ BDBF03IF : 15|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ TRIP_CNT : 23|16@0+ (1,0) [0|0] "trip" AFS,BSR,CSR,DS1,FCM,MAV + SG_ TIME_CNT : 39|32@0+ (100,0) [0|0] "ms" AFS,BSR,CSR,DS1,FCM,MAV + +BO_ 1074791968 BDB1S01_10: 8 CGW + SG_ BDB01_ID : 7|8@0+ (1,0) [0|0] "" FCM,MAV + SG_ BDB01_IF : 15|8@0+ (1,0) [0|0] "" FCM + SG_ LX : 23|16@0+ (0.2,0) [0|0] "ms" FCM + SG_ ADIM : 39|2@0+ (1,0) [0|0] "" AFS,BSR,CSR + SG_ IG_BDB : 37|1@0+ (1,0) [0|0] "" AFS,MAV + SG_ ACC_BDB : 36|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SKSW : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DCTY : 45|1@0+ (1,0) [0|0] "" FCM,MAV,SCS + SG_ PCTY : 44|1@0+ (1,0) [0|0] "" MAV,SCS + SG_ RRCY : 43|1@0+ (1,0) [0|0] "" MAV,SCS + SG_ RLCY : 42|1@0+ (1,0) [0|0] "" MAV,SCS + SG_ BCTY : 41|1@0+ (1,0) [0|0] "" MAV,SCS + SG_ PSW : 51|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SRBZ : 49|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DBKL : 63|2@0+ (1,0) [0|0] "" FCM + SG_ PKB_BDB : 60|1@0+ (1,0) [0|0] "" CSR + SG_ SREXIST : 59|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SRPOS : 58|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1074857505 BDB1S02_11: 8 CGW + SG_ BDB02_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB02_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ LUD : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRNKOPN : 45|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1074923042 BDB1S03_12: 8 CGW + SG_ BDB03_ID : 7|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ BDB03_IF : 15|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ LTS : 23|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ PANL : 19|1@0+ (1,0) [0|0] "" BSR,CSR + SG_ UDRL : 31|1@0+ (1,0) [0|0] "" AFS + SG_ HEDH : 30|1@0+ (1,0) [0|0] "" AFS,DS1,FCM + SG_ HEDL : 29|1@0+ (1,0) [0|0] "" AFS,DS1 + SG_ TAIL : 28|1@0+ (1,0) [0|0] "" AFS,BSR,CSR,DS1 + SG_ FFOG : 27|1@0+ (1,0) [0|0] "" DS1 + SG_ RFOG : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SB_IND : 39|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SB_OK : 37|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RTRRQ : 35|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SRWARN : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PWWARN : 50|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ WEL_REQ : 48|1@0+ (1,0) [0|0] "" AFS + SG_ DRPBZ_R : 62|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075381795 BDB1S04_19: 8 CGW + SG_ BDB04_ID : 7|8@0+ (1,0) [0|0] "" MAV + SG_ BDB04_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MRMV_R : 23|2@0+ (1,0) [0|0] "" MAV + SG_ RSEL : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LSEL : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MHR : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MHL : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MVU : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MVD : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GHSW : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GCTY : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GHOPN : 42|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ ABIF : 55|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ FLSHRQ : 63|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SB_ADV : 60|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1074988600 BDB1S05_13: 8 CGW + SG_ BDB05_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB05_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ PARK : 23|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSWB : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LSWD : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LSWP : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LSWR : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LSWL : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LSWB : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRVKS_R : 31|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ PWDRD : 39|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PWDRP : 37|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PWDRR : 35|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PWDRL : 33|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ DKLS : 43|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ BKLS : 54|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ KIDSCN_R : 51|7@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075250736 BDB1S06_17: 8 CGW + SG_ BDB06_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB06_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TBSW : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ WBZF : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ WVOL : 42|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075316273 BDB1S07_18: 8 CGW + SG_ BDB07_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB07_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ WCD : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ W1D : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ W2D : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ W3D : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB7SUM1 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB7SUM2 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075447332 BDB1S08_1A: 8 CGW + SG_ BDB08_ID : 7|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ BDB08_IF : 15|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ DEST_BDB : 23|8@0+ (1,0) [0|0] "" AFS,BSR,CSR,DS1,FCM,MAV + SG_ DS_PACK1 : 31|8@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM,MAV + SG_ DS_PACK2 : 39|8@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM,MAV + SG_ STRG_WHL : 47|2@0+ (1,0) [0|0] "" AFS,CSR,DS1,FCM,MAV + SG_ DEICER : 40|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ KEYPLATE : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DBLLCK : 62|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ U2OP_CST : 61|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ U2OP_DFT : 60|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075643943 BDB1S11_1D: 8 CGW + SG_ BDB11_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB11_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDBREQ11 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDBREQ12 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1083704892 BDB1S17_98: 8 CGW + SG_ BDB17_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB17_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ CHABASE1 : 23|8@0+ (1,0) [0|0] "" AFS + SG_ CHABASE2 : 31|8@0+ (1,0) [0|0] "" AFS + SG_ CHABASE3 : 39|8@0+ (1,0) [0|0] "" AFS + SG_ CHA_NO1 : 47|4@0+ (1,0) [0|0] "" AFS + SG_ CHA_NO2 : 43|4@0+ (1,0) [0|0] "" AFS + SG_ CHA_NO3 : 55|4@0+ (1,0) [0|0] "" AFS + SG_ SP_BODY : 63|5@0+ (1,0) [0|0] "" AFS + +BO_ 1083770429 BDB1S18_99: 8 CGW + SG_ BDB18_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB18_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ POP_NAME : 23|8@0+ (1,0) [0|0] "" AFS + SG_ BODY : 31|8@0+ (1,0) [0|0] "" AFS + SG_ GEAR : 39|8@0+ (1,0) [0|0] "" AFS + SG_ GRADE : 47|8@0+ (1,0) [0|0] "" AFS + SG_ ENGINE : 55|8@0+ (1,0) [0|0] "" AFS + +BO_ 1020 BDB1S19: 8 CGW + SG_ SOLAR_R : 23|9@0+ (100,0) [0|0] "" Vector__XXX + SG_ SOLAR_L : 39|9@0+ (100,0) [0|0] "" Vector__XXX + SG_ N_LX : 55|13@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1083835966 BDB1S20_9A: 8 CGW + SG_ BDB20_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB20_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RNBDYC : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RNBDYD : 39|32@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1083901503 BDB1S21_9B: 8 CGW + SG_ BDB21_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BDB21_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ RFOG_SW : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FFOG_SW : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HF_SW : 20|1@0+ (1,0) [0|0] "" AFS + SG_ HU_SW : 19|1@0+ (1,0) [0|0] "" AFS + SG_ AUTO_SW : 18|1@0+ (1,0) [0|0] "" AFS + SG_ HEAD_SW : 17|1@0+ (1,0) [0|0] "" AFS + SG_ TAIL_SW : 16|1@0+ (1,0) [0|0] "" AFS + SG_ DRL_OFF : 24|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1005 BGM1S01: 2 CGW + SG_ WCAA : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ R_DISP : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BGM_BEEP : 11|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ BGM_MODE : 9|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1237 BSR1N01: 8 BSR + SG_ BSRNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ BSRSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ BSRSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ BSRREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 1014 BSR1S01: 8 BSR + SG_ BSD_STAT : 7|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ BSD_SW : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BSD_BUZ : 23|1@0+ (1,0) [0|0] "" CSR + +BO_ 1114 CGW1N02: 8 CGW + SG_ CGW2REV : 7|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1228 CSR1N01: 8 CSR + SG_ CSRNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ CSRSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ CSRSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ CSRREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 918 CSR1S01: 7 CSR + SG_ CSV : 7|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ CSSR : 4|2@0+ (1,0) [0|0] "" MAV + SG_ CSD : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CSME : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CSIN : 0|1@0+ (1,0) [0|0] "" MAV + SG_ FL_INFO : 15|4@0+ (1,0) [0|0] "" MAV + SG_ FR_INFO : 11|4@0+ (1,0) [0|0] "" MAV + SG_ RB_INFO : 23|4@0+ (1,0) [0|0] "" MAV + SG_ FC_INFO : 19|4@0+ (1,0) [0|0] "" MAV + SG_ RL_INFO : 31|4@0+ (1,0) [0|0] "" MAV + SG_ RR_INFO : 27|4@0+ (1,0) [0|0] "" MAV + SG_ CZV : 39|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ VOT : 47|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ FCZD : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RCZD : 42|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FCDD : 41|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RCDD : 40|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VOL : 55|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ CDG : 52|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ MUTE : 49|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BZ_OFF : 48|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1087768273 DMS1S02_D6: 8 CGW + SG_ SS_MODE : 25|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 869 DS11D70: 7 DS1 + SG_ D_TRGJDG : 7|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_RESSW : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_SETSW : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_CANSW : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_MAINSW : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_VMCC : 15|8@0+ (1,0) [0|0] "km/h" Vector__XXX + SG_ D_VNCC : 23|8@0+ (1,0) [0|0] "km/h" Vector__XXX + SG_ D_CCREQ : 31|8@0+ (100,-12800) [0|0] "N" Vector__XXX + SG_ D_TGTDST : 39|8@0+ (1,0) [0|0] "m" Vector__XXX + SG_ D_VRCC : 47|8@0- (1,0) [0|0] "km/h" Vector__XXX + SG_ D_WSTL : 55|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_DSW : 54|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_FDJDG : 52|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ D_DSSJDG : 51|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 870 DS11D71: 7 DS1 + SG_ XREQALM : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XREQABK : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TGT_DIST : 5|14@0+ (0.01,0) [0|0] "m" Vector__XXX + SG_ XREQPBA : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XREQFPB : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XREQPB : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XREQEXT : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XREQPSB : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TGT_VGAP : 18|11@0+ (0.025,-51.175) [0|0] "m/s" Vector__XXX + SG_ PCSDISP : 39|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ XPCSRDY : 35|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TGT_NUMB : 34|3@0+ (1,1) [0|0] "" Vector__XXX + SG_ TGT_POSX : 47|8@0- (0.04,0) [0|0] "m" Vector__XXX + +BO_ 871 DS11D72: 2 FCM + SG_ LKADRTRG : 7|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKADRSHR : 5|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKADRSLK : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKADRSLD : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKADRCC : 2|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKADRTUR : 15|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKADRINV : 13|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 643 DS11F01: 7 DS1 + SG_ DSCOUNT : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DSLCCW1 : 15|1@0+ (1,0) [0|0] "" FCM + SG_ DSSTPBZ : 14|1@0+ (1,0) [0|0] "" FCM + SG_ PBRTRGR2 : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DSSFTRQD : 11|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ DSS1FDRV : 23|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ DSS1STBK : 39|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ DSS1STAT : 36|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ DSBHOK : 33|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PPTRGR2 : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DSRQBH : 47|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ IBTRGR2 : 45|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSABK2 : 44|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSNOCHG : 41|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ DS1F01SM : 55|8@0+ (1,0) [0|0] "" FCM + +BO_ 1041 DS12F02: 8 DS1 + SG_ PCSINDI : 7|2@0+ (1,0) [0|0] "" FCM + SG_ PCSWM : 5|2@0+ (1,0) [0|0] "" FCM + SG_ PCSFCT : 3|1@0+ (1,0) [0|0] "" FCM + SG_ PCSTUCT : 2|1@0+ (1,0) [0|0] "" FCM + SG_ DS1LCCK : 1|2@0+ (1,0) [0|0] "" FCM + SG_ PBTUCT : 14|1@0+ (1,0) [0|0] "" FCM + SG_ PCSEXIST : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSWDUCT : 11|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSWD : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSDW : 39|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSDSRF : 36|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSTEMP : 35|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSDUST : 34|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSLCCK : 33|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSPEDW : 47|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSPVSN : 44|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCTEMP2 : 42|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSDUST2 : 41|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSOFFS : 40|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSWDS : 55|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ FRDADJ : 53|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1042 DS12F03: 8 FCM + SG_ LKAINDI : 7|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKAWLSL : 5|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKAWLSR : 3|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKAFCT : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKATUCT : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKACAMT : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LDWEXIST : 10|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKASPCND : 23|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKAWTCS : 18|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKASAUT : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LDWBZ : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LDAFCVB : 47|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LDARDA : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SWSSENSD : 45|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SWSSWD : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SWSRAD : 55|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SWSFLD : 53|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SWSBUZ : 50|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1207 ECO1D50: 8 CGW + SG_ DRECO01 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO02 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO03 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO04 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO05 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO06 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO07 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECO08 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 355 ECO1S01: 5 CGW + SG_ ECOSTAON : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECOMODE : 18|3@0+ (1,0) [0|0] "" KSS,SCS + SG_ FCREQ : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SSVMREQ : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ E2MRXMK : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BPHLDRQ : 36|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BPHLDRQ2 : 35|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECOEGSTP : 33|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 922 ECO1S90: 8 CGW + SG_ ECOBZR : 23|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECOLMP : 21|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ TESTECO : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OPLMPMSK : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MSTART : 28|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECOMODE3 : 27|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ INFSSCOP : 39|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ INFSSSTL : 36|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECLMP : 34|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ AUTOSTA : 47|1@0+ (1,0) [0|0] "" SCS + SG_ INFSSFAL : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ INFSSINH : 45|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ SSACMODE : 52|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ INFSSADV : 50|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1182 ECT1D50: 8 CGW + SG_ DRECT01 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT02 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT03 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT04 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT05 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT06 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT07 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT08 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1183 ECT1D51: 8 CGW + SG_ DRECT11 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT12 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT13 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT14 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT15 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT16 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT17 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT18 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1200 ECT1D52: 8 CGW + SG_ DRECT21 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT22 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT23 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT24 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT25 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT26 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT27 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT28 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1201 ECT1D53: 8 CGW + SG_ DRECT31 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT32 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT33 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT34 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT35 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT36 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT37 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT38 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1202 ECT1D54: 8 CGW + SG_ DRECT41 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT42 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT43 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT44 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT45 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT46 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT47 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT48 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1203 ECT1D55: 8 CGW + SG_ DRECT51 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT52 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT53 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT54 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT55 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT56 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT57 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRECT58 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 464 ECT1F03: 8 CGW + SG_ NT : 7|16@0- (0.390625,0) [0|0] "rpm" Vector__XXX + SG_ ACT : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XDMET : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XNTSW : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XNMET : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XRMET : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XPMET : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SFTOUT_S : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ X3MET : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ X2MET : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XLOMET : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ L4SW : 38|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SNOW : 36|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XFSFT : 35|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SFTOUT : 34|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ HSSLWN : 55|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HSINH : 54|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CLTMODBK : 53|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ LUOUT : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LUKG : 50|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ FBCOA : 48|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ECTF03SM : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 725 ECT1S10: 2 CGW + SG_ VTORATIO : 7|16@0+ (0.0009765625,0) [0|0] "" Vector__XXX + +BO_ 956 ECT1S92: 8 CGW + SG_ B_OILW : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_OILMD : 5|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_ISNW : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_RJTB : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_WNDL : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_LMULRJ : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_P : 13|1@0+ (1,0) [0|0] "" AFS,CSR,MAV + SG_ B_R : 12|1@0+ (1,0) [0|0] "" AFS,BSR,CSR,DS1,FCM,MAV + SG_ B_N : 11|1@0+ (1,0) [0|0] "" AFS,CSR,MAV + SG_ B_ISPTM : 10|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ BV_THOCL : 23|16@0+ (0.625,-50) [0|0] "" Vector__XXX + SG_ B_GEAR : 39|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_SMDE : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_D : 47|1@0+ (1,0) [0|0] "" AFS,CSR,DS1,MAV + SG_ B_ECOMI : 40|1@0+ (1,0) [0|0] "" DS1 + SG_ B_SPTMI : 55|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_PWRM : 54|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_OILWM : 51|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_SPTMS : 49|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_DMODE : 61|3@0+ (1,0) [0|0] "" SCS + +BO_ 1176 ENG1D50: 8 CGW + SG_ DRENG01 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG02 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG03 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG04 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG05 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG06 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG07 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG08 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1177 ENG1D51: 8 CGW + SG_ DRENG11 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG12 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG13 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG14 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG15 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG16 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG17 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG18 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1178 ENG1D52: 8 CGW + SG_ DRENG21 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG22 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG23 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG24 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG25 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG26 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG27 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG28 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1179 ENG1D53: 8 CGW + SG_ DRENG31 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG32 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG33 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG34 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG35 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG36 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG37 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG38 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1180 ENG1D54: 8 CGW + SG_ DRENG41 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG42 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG43 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG44 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG45 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG46 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG47 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG48 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1181 ENG1D55: 8 CGW + SG_ DRENG51 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG52 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG53 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG54 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG55 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG56 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG57 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG58 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1192 ENG1D56: 8 CGW + SG_ DRENG61 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG62 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG63 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG64 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG65 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG66 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG67 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG68 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1191 ENG1D57: 8 CGW + SG_ DRENG71 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG72 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG73 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG74 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG75 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG76 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG77 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG78 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1197 ENG1D58: 8 CGW + SG_ DRENG81 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG82 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG83 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG84 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG85 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG86 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG87 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG88 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1198 ENG1D59: 8 CGW + SG_ DRENG91 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG92 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG93 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG94 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG95 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG96 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG97 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG98 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1199 ENG1D60: 8 CGW + SG_ DRENG101 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG102 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG103 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG104 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG105 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG106 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG107 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRENG108 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1017 ENG1F03: 8 CGW + SG_ VARENG1 : 7|4@0+ (1,0) [0|0] "" AFS,SCS + SG_ VARENG2 : 3|4@0+ (1,0) [0|0] "" AFS,SCS + SG_ VARENG3 : 15|4@0+ (1,0) [0|0] "" AFS,SCS + SG_ VARENG4 : 11|1@0+ (1,0) [0|0] "" AFS,SCS + SG_ HVFLAG : 10|1@0+ (1,0) [0|0] "" AFS,BSR,FCM,SCS + SG_ VARTRM1 : 23|4@0+ (1,0) [0|0] "" AFS,CSR,FCM,MAV,SCS + SG_ GEARINF : 19|4@0+ (1,0) [0|0] "" SCS + SG_ DVINF : 31|2@0+ (1,0) [0|0] "" AFS,DS1,FCM,SCS + SG_ OBDINF : 27|4@0+ (1,0) [0|0] "" BSR,DS1,FCM,SCS + SG_ ECOFLAG : 39|1@0+ (1,0) [0|0] "" FCM + SG_ CDYMD : 38|2@0+ (1,0) [0|0] "" DS1,FCM + SG_ ENGF03SM : 63|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + +BO_ 452 ENG1F07: 8 CGW + SG_ NE1 : 7|16@0- (0.78125,0) [0|0] "rpm" SCS + SG_ THA1 : 23|8@0+ (2.5,-40) [0|0] "" Vector__XXX + SG_ THWX : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ EGF : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ T2ERXF : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ T2ERXMK : 28|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ASTEFI : 27|1@0+ (1,0) [0|0] "" AFS + SG_ B2ERXMK : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PDLF : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ENTCAL2 : 39|8@0+ (12.5,0) [0|0] "rpm" Vector__XXX + SG_ EGFB : 46|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ PTFB : 45|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MILREQ : 43|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_ECOL : 55|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_IECOCR : 53|6@0+ (2,0) [0|0] "" Vector__XXX + SG_ ENGF07SM : 63|8@0+ (1,0) [0|0] "" AFS,DS1,FCM + +BO_ 114 ENG1F43: 5 CGW + SG_ FAVLMCHL : 7|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ FAVLMONL : 23|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ ENGF43SM : 39|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 705 ENG1S01: 8 CGW + SG_ ETCSFB : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ETCSF : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSCTH : 5|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ THF : 4|1@0+ (1,0) [0|0] "" DS1 + SG_ IDL1 : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XCCACT2 : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ STPSWF : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ WTC : 0|1@0+ (1,0) [0|0] "" KSS,SCS + SG_ ETQLVSC : 15|16@0- (0.03125,0) [0|0] "Nm" Vector__XXX + SG_ ETQREAL : 31|16@0- (0.03125,0) [0|0] "Nm" SCS + SG_ ETQISC : 47|8@0+ (1,-192) [0|0] "Nm" Vector__XXX + SG_ EACCP : 55|8@0+ (0.5,0) [0|0] "%" DS1,FCM + SG_ ENG01SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 961 ENG1S23: 3 CGW + SG_ EKLSM : 7|8@0+ (0.625,0) [0|0] "%" Vector__XXX + SG_ GATHW : 15|16@0- (0.625,0) [0|0] "" Vector__XXX + +BO_ 979 ENG1S28: 2 CGW + SG_ B_FC : 7|16@0+ (0.0005,0) [0|0] "ml" Vector__XXX + +BO_ 1408 ENG1S51: 8 CGW + SG_ VIN_1 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_2 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_3 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_4 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_5 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_6 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_7 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_8 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1409 ENG1S52: 8 CGW + SG_ VIN_9 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_10 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_11 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_12 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_13 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_14 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_15 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VIN_16 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1410 ENG1S54: 8 CGW + SG_ VIN_17 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ VC : 52|5@0+ (1,0) [0|0] "" Vector__XXX + SG_ TES : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 955 ENG1S92: 8 CGW + SG_ B_ST : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_TC : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_GLOW : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_STPE : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_OMWI : 15|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_SILUP : 13|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_SILDN : 12|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_WSTP : 11|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_LOUT : 10|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_OILPL : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_TMP : 23|8@0+ (0.5,0) [0|0] "" Vector__XXX + SG_ OGENETCS : 30|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_DPFW : 28|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ BOSLAMP : 37|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ BOSMINF : 34|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ GOSLAMP : 45|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ GOSMINF : 42|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 921 ENG1S95: 8 CGW + SG_ B_LLSP2 : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TLSTBZ : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_ASLBZ2 : 5|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_SPU2 : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACASID1 : 3|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACASID2 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_LSP2 : 31|8@0+ (1,0) [0|0] "km/h Emph" Vector__XXX + SG_ B_ASLSP2 : 39|8@0+ (1,0) [0|0] "km/h Emph" Vector__XXX + SG_ CACCTRN : 47|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCINF : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCFR2 : 45|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCFR1 : 44|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCFLD : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCCM3 : 42|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCCM2 : 41|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CACCCM1 : 40|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 238 ENG2F01: 4 CGW + SG_ STOFOK : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GROWIND : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_TMP3 : 15|8@0+ (0.5,0) [0|0] "" Vector__XXX + SG_ IMMINJST : 23|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 466 ENG2F04: 8 CGW + SG_ XLDR : 7|1@0+ (1,0) [0|0] "" DS1 + SG_ XACCACTV : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XACCACT : 5|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ XPAIDLV : 4|1@0+ (1,0) [0|0] "" DS1 + SG_ XPAIDL : 3|1@0+ (1,0) [0|0] "" DS1 + SG_ BHOK : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RQBH : 1|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCSTAT : 15|3@0+ (1,0) [0|0] "" DS1 + SG_ ACCSTBK : 12|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ STPBZ : 9|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ PLOCKF : 8|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ACCREQ : 23|16@0- (0.0009765625,0) [0|0] "m/s^2" DS1 + SG_ ACCAVL : 39|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ SPDSTAT : 55|4@0+ (1,0) [0|0] "" DS1 + SG_ SSTOK : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CANREQ : 49|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FCACT : 48|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SM1D2 : 63|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 467 ENG2F05: 8 CGW + SG_ LCCW2 : 4|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ WSTL2 : 3|1@0+ (1,0) [0|0] "" DS1 + SG_ LCCHK : 2|3@0+ (1,0) [0|0] "" DS1 + SG_ XCCOK2 : 15|1@0+ (1,0) [0|0] "" DS1 + SG_ SLTACC : 14|2@0+ (1,0) [0|0] "" DS1 + SG_ LTME2 : 12|2@0+ (1,0) [0|0] "" DS1 + SG_ STPSWF2 : 10|1@0+ (1,0) [0|0] "" DS1 + SG_ CCSF : 9|1@0+ (1,0) [0|0] "" DS1 + SG_ CCSNG : 8|1@0+ (1,0) [0|0] "" DS1 + SG_ VM : 23|16@0+ (0.00390625,0) [0|0] "km/h" DS1 + SG_ INTG : 39|8@0- (0.04,0) [0|0] "m/s^2" DS1 + SG_ D2PRXMK : 47|1@0+ (1,0) [0|0] "" DS1 + SG_ SM1D3 : 63|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 119 ENG2F41: 6 CGW + SG_ FDRV : 7|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ FDRVREAL : 23|13@0- (10,0) [0|0] "N" Vector__XXX + SG_ XAECT : 39|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ XFDRVCOL : 38|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FDRVSELP : 34|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ ENG2F41S : 47|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 120 ENG2F42: 4 CGW + SG_ FAVLMCHH : 7|16@0- (2,0) [0|0] "N" Vector__XXX + SG_ CCRNG : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FDRVTYPD : 22|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ GEARHD : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ENG2F42S : 31|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 916 EPS1S90: 1 CGW + SG_ B_WPS0 : 1|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1235 FCM1N01: 8 FCM + SG_ FCMNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ FCMSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ FCMSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ FCMREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 1161 FCM1S10: 8 FCM + SG_ TSGN1 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNGRY1 : 12|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNHLT1 : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPDVAL1 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPLSGN1 : 31|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPLSGN2 : 27|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGN2 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNGRY2 : 44|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNHLT2 : 41|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPDVAL2 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ BZRRQ_P : 63|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ BZRRQ_A : 61|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SYNCID1 : 59|4@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1162 FCM1S11: 8 FCM + SG_ TSGN3 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNGRY3 : 12|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNHLT3 : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPLSGN3 : 31|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPLSGN4 : 27|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGN4 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNGRY4 : 44|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSGNHLT4 : 41|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ DPSGNREQ : 54|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SGNNUMP : 53|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SGNNUMA : 50|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SPDUNT : 63|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSRWMSG : 61|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ SYNCID2 : 59|4@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1163 FCM1S12: 8 FCM + SG_ TSREQPD : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSRMSW : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OTSGNNTM : 5|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ NTLVLSPD : 3|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ OVSPNTM : 1|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ OVSPVALL : 11|4@0+ (1,-5) [0|0] "" Vector__XXX + SG_ OVSPVALM : 19|4@0+ (1,-5) [0|0] "" Vector__XXX + SG_ OVSPVALH : 27|4@0+ (1,-5) [0|0] "" Vector__XXX + SG_ TSRSPU : 33|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1279 FRD1N01: 8 FRD + SG_ FRDNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ FRDSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ FRDSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ FRDREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 737 FWM1S01: 2 CGW + SG_ ACTHLF : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MOT4WD : 6|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CCANCEL : 5|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AI4WD : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LOW4 : 3|1@0+ (1,0) [0|0] "" MAV,SCS + SG_ DLOCK : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RDLOCK : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HLN : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ F_SP4WD : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RQ_SP4WD : 14|7@0+ (1,73) [0|0] "km/h" Vector__XXX + +BO_ 1082263092 IDT1S03_82: 8 CGW + SG_ IDT03_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ IDT03_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ CO_IDT : 23|16@0+ (1,0) [0|0] "" Vector__XXX + SG_ UACK : 39|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ WRT : 38|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RSTP : 37|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1082328629 IDT1S04_83: 8 CGW + SG_ IDT04_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ IDT04_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ OSID : 47|16@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1257 KSS1N01: 8 KSS + SG_ KSSNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ KSSSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ KSSSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ KSSREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 927 KSS1S90: 1 KSS + SG_ LKSS0 : 1|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1263 MAV1N01: 8 MAV + SG_ MAVNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ MAVSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ MAVSPF : 23|16@0+ (1,0) [0|0] "" CGW + +BO_ 1075840528 MET1S01_20: 8 CGW + SG_ MET01_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET01_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET_SPD : 23|8@0+ (1,0) [0|0] "km/h" CSR + SG_ RHEOSTAT : 30|7@0+ (1,0) [0|0] "%" Vector__XXX + SG_ TAIL_CN : 39|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ILL_OF : 37|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ UNIT_TMP : 33|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ IN_FC : 47|16@0+ (0.1,0) [0|0] "Note" Vector__XXX + SG_ UNIT_0 : 63|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SP_TL : 60|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET_TC : 56|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075906065 MET1S02_21: 8 CGW + SG_ MET02_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET02_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET_DEST : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ ODO_UNIT : 29|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ OMRS : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ UNIT_CH : 26|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ ODO : 39|32@0+ (1,0) [0|0] "km/mile" Vector__XXX + +BO_ 1076037145 MET1S04_23: 8 CGW + SG_ MET04_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET04_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ AF_FC : 23|16@0+ (0.1,0) [0|0] "Note" Vector__XXX + SG_ UNIT_3 : 39|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ RANGE : 47|16@0+ (1,0) [0|0] "Note" Vector__XXX + SG_ UNIT_4 : 63|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1076102682 MET1S05_24: 8 CGW + SG_ MET05_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET05_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TO_SP : 23|16@0+ (0.1,0) [0|0] "km/h,MPH" Vector__XXX + SG_ UNIT_5 : 39|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ TO_FC : 47|16@0+ (0.1,0) [0|0] "MPG Ekm/l El/100km Ekm/gallon" Vector__XXX + SG_ UNIT_6 : 63|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1076299282 MET1S08_27: 8 CGW + SG_ MET08_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET08_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ TO_DT : 23|16@0+ (1,0) [0|0] "km,mile" Vector__XXX + SG_ UNIT_10 : 39|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1076364819 MET1S09_28: 8 CGW + SG_ MET09_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET09_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ WASH : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BLVW : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_CW : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ENGW : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ABSW : 28|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSCW : 27|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OPW : 37|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OLW : 36|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LW : 35|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FSRS : 33|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ HALW : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRW : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TIRW : 42|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FWW : 40|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SUSW : 53|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LKAW : 61|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET_PCSW : 59|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ WTPW : 57|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1076430356 MET1S10_29: 8 CGW + SG_ MET10_ID : 7|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ MET10_IF : 15|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ OM_MLG : 23|7@0+ (100,0) [0|0] "miles" Vector__XXX + SG_ PR_OM_FL : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TNS : 29|2@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM + SG_ HZS : 27|1@0+ (1,0) [0|0] "" AFS,FCM + +BO_ 1076495893 MET1S11_2A: 8 CGW + SG_ MET11_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET11_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ UNIT_CH2 : 23|2@0+ (1,0) [0|0] "" FCM + SG_ TOLER_A : 21|6@0+ (0.002,0.94) [0|0] "" FCM + SG_ CDISP_EX : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TOLER_B : 29|6@0- (0.2,0) [0|0] "km/h" FCM + SG_ TRIP_B : 39|32@0+ (0.1,0) [0|0] "km/MILE" Vector__XXX + +BO_ 1076561430 MET1S12_2B: 8 CGW + SG_ MET12_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ MET12_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ ESLW : 19|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CSOW : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LHLW : 37|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SMBW : 33|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ KDSW : 32|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ OMRW : 46|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BSDW : 54|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ MTSW : 48|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ ATSW : 63|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 992 MET1S18: 8 CGW + SG_ M_LANG : 7|6@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNG_ST : 1|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB1 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB2 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB3 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB4 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB5 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB6 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ M_LNGDB7 : 63|7@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1075840755 MET1S22_20: 8 CGW + SG_ ID6F320 : 7|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ IF6F320 : 15|8@0+ (1,0) [0|0] "" DS1,FCM + SG_ TSR_OSM : 22|2@0+ (1,0) [0|0] "" FCM + SG_ TSR_OSL : 20|2@0+ (1,0) [0|0] "" FCM + SG_ TSR_SNM : 18|2@0+ (1,0) [0|0] "" FCM + SG_ TSR_MAIN : 16|1@0+ (1,0) [0|0] "" FCM + SG_ LDAMCUS : 31|2@0+ (1,0) [0|0] "" FCM + SG_ LDAMSW : 29|2@0+ (1,0) [0|0] "" FCM + SG_ FCMUSER : 27|1@0+ (1,0) [0|0] "" FCM + SG_ FCMMCUS : 26|2@0+ (1,0) [0|0] "" FCM + SG_ FCMMSW : 24|1@0+ (1,0) [0|0] "" FCM + SG_ BSMMSW : 37|1@0+ (1,0) [0|0] "" BSR + SG_ CSRMSW : 34|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSMCUS : 41|1@0+ (1,0) [0|0] "" DS1 + SG_ PCSMSW : 40|1@0+ (1,0) [0|0] "" DS1 + SG_ LKACTCSW : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ LDA_SFB : 50|3@0+ (1,0) [0|0] "" FCM + +BO_ 1088685760 PMN1F03_E4: 8 CGW + SG_ PMNF03ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ PMNF03IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ PSSW_PMN : 17|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PSW_PMN : 31|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ KCC_PMN : 29|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PMOD_PMN : 27|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ MOD_EIG : 39|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SWBZ_EIG : 36|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1193 SCS1D50: 8 SCS + SG_ DRSCS01 : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS02 : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS03 : 23|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS04 : 31|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS05 : 39|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS06 : 47|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS07 : 55|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ DRSCS08 : 63|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1226 SCS1N01: 8 SCS + SG_ SCSNID : 7|8@0+ (1,0) [0|0] "" CGW + SG_ SCSSNG : 15|1@0+ (1,0) [0|0] "" CGW + SG_ SCSSPF : 23|16@0+ (1,0) [0|0] "" CGW + SG_ SCSREV : 39|32@0+ (1,0) [0|0] "" CGW + +BO_ 744 SCS1S01: 8 SCS + SG_ SELECTOR : 3|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVS_MD : 63|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 815 SCS1S06: 5 SCS + SG_ RRVH : 23|8@0- (1,0) [0|0] "mm" AFS + SG_ RLVH : 31|8@0- (1,0) [0|0] "mm" AFS + SG_ SCECOINH : 35|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 917 SCS1S90: 4 SCS + SG_ B_LSUS6 : 7|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_LSUS4 : 5|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_LSUS2 : 3|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_LSUS8 : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ DLR_HSID : 23|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LAR_HS : 18|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ AVSNI : 16|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 37 STR1S01: 8 CGW + SG_ STS3 : 7|1@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM,MAV + SG_ STS2 : 6|1@0+ (1,0) [0|0] "" AFS,DS1,FCM,KSS,MAV,SCS + SG_ STS1 : 5|1@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM,KSS,MAV,SCS + SG_ STS0 : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ SSA : 3|12@0- (1.5,0) [0|0] "deg" AFS,BSR,DS1,FCM,KSS,MAV,SCS + SG_ SAZS : 23|1@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM + SG_ SFRZ : 22|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ SSAZ : 19|12@0- (1.5,0) [0|0] "deg" AFS,BSR,DS1,FCM + SG_ SSAS : 39|4@0- (0.1,0) [0|0] "deg" FCM,KSS,SCS + SG_ SSAV : 35|12@0- (1,0) [0|0] "deg/s" FCM,KSS,SCS + SG_ STDID : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ STR01SUM : 63|8@0+ (1,0) [0|0] "" AFS,DS1,FCM,MAV + +BO_ 1059 STR1S02: 1 CGW + SG_ SFR : 5|1@0+ (1,0) [0|0] "" MAV + SG_ STRWVG : 4|1@0+ (1,0) [0|0] "" AFS,BSR,DS1,FCM + +BO_ 170 VSC1F01: 8 CGW + SG_ VXFREF : 7|1@0+ (1,0) [0|0] "" AFS,FCM,MAV + SG_ VXFR : 6|15@0+ (0.01,-67.67) [0|0] "km/h" AFS,BSR,DS1,FCM,KSS,MAV,SCS + SG_ VXFLEF : 23|1@0+ (1,0) [0|0] "" AFS,FCM,MAV + SG_ VXFL : 22|15@0+ (0.01,-67.67) [0|0] "km/h" AFS,BSR,DS1,FCM,KSS,MAV,SCS + SG_ VXRREF : 39|1@0+ (1,0) [0|0] "" AFS,FCM,MAV + SG_ VXRR : 38|15@0+ (0.01,-67.67) [0|0] "km/h" AFS,BSR,DS1,FCM,KSS,MAV,SCS + SG_ VXRLEF : 55|1@0+ (1,0) [0|0] "" AFS,FCM,MAV + SG_ VXRL : 54|15@0+ (0.01,-67.67) [0|0] "km/h" AFS,BSR,DS1,FCM,KSS,MAV,SCS + +BO_ 426 VSC1F02: 6 CGW + SG_ VXFRF : 7|1@0+ (1,0) [0|0] "" AFS,BSR,FCM,MAV + SG_ VXFRIGS : 6|1@0+ (1,0) [0|0] "" BSR,DS1,FCM,MAV + SG_ VXFRHDS : 5|1@0+ (1,0) [0|0] "" FCM,KSS,MAV,SCS + SG_ VXFLF : 2|1@0+ (1,0) [0|0] "" AFS,BSR,FCM,MAV + SG_ VXFLIGS : 1|1@0+ (1,0) [0|0] "" BSR,DS1,FCM,MAV + SG_ VXFLHDS : 0|1@0+ (1,0) [0|0] "" FCM,KSS,MAV,SCS + SG_ VXRRF : 13|1@0+ (1,0) [0|0] "" AFS,BSR,FCM,MAV + SG_ VXRRIGS : 12|1@0+ (1,0) [0|0] "" BSR,DS1,FCM,MAV + SG_ VXRRHDS : 11|1@0+ (1,0) [0|0] "" FCM,KSS,MAV,SCS + SG_ VXRLF : 8|1@0+ (1,0) [0|0] "" AFS,BSR,FCM,MAV + SG_ VXRLIGS : 23|1@0+ (1,0) [0|0] "" BSR,DS1,FCM,MAV + SG_ VXRLHDS : 22|1@0+ (1,0) [0|0] "" FCM,KSS,MAV,SCS + SG_ VSCF02SM : 47|8@0+ (1,0) [0|0] "" AFS,DS1,FCM,MAV + +BO_ 550 VSC1F06: 8 CGW + SG_ VSCF01FG : 7|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ AHCURQ : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PMCF : 3|1@0+ (1,0) [0|0] "" DS1 + SG_ PMCS : 2|1@0+ (1,0) [0|0] "" DS1 + SG_ PMC : 1|10@0+ (0.02,0) [0|0] "Mpa" DS1 + SG_ ECOEN : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ CCS : 22|1@0+ (1,0) [0|0] "" DS1 + SG_ FBA : 21|1@0+ (1,0) [0|0] "" DS1 + SG_ TRBRKSYS : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TS : 38|1@0+ (1,0) [0|0] "" KSS,SCS + SG_ WSTP : 37|1@0+ (1,0) [0|0] "" DS1,KSS,SCS + SG_ VSCACT : 36|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ BAEX : 35|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TEM : 34|3@0+ (1,0) [0|0] "" SCS + SG_ FSTP : 60|1@0+ (1,0) [0|0] "" DS1 + SG_ ABSACT : 59|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + +BO_ 180 VSC1S03: 8 CGW + SG_ SP1P : 39|6@0+ (1,0) [0|0] "" DS1,FCM + SG_ SP1S : 33|1@0+ (1,0) [0|0] "" BSR,DS1,FCM,MAV + SG_ SP1 : 47|16@0- (0.01,0) [0|0] "km/h" BSR,DS1,FCM,MAV + SG_ VSC03SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + +BO_ 800 VSC1S07: 8 CGW + SG_ FBKRLY : 6|1@0+ (1,0) [0|0] "" DS1 + SG_ FVSCM : 4|1@0+ (1,0) [0|0] "" DS1 + SG_ FVSCSFT : 3|1@0+ (1,0) [0|0] "" DS1 + SG_ FABS : 2|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ TSVSC : 1|1@0+ (1,0) [0|0] "" DS1 + SG_ FVSCL : 0|1@0+ (1,0) [0|0] "" DS1 + SG_ RQCSTBKB : 15|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PSBSTBY : 14|1@0+ (1,0) [0|0] "" DS1 + SG_ P2BRXMK : 13|1@0+ (1,0) [0|0] "" DS1 + SG_ MCC : 11|1@0+ (1,0) [0|0] "" DS1 + SG_ RQBKB : 10|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRSTOP : 9|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ BRKON : 8|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ ASLP : 23|8@0- (1,0) [0|0] "deg" DS1 + SG_ BRTYPACC : 31|2@0+ (1,0) [0|0] "" DS1 + SG_ BRKABT3 : 26|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRKABT2 : 25|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRKABT1 : 24|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ GVC : 39|8@0- (0.04,0) [0|0] "m/s^2" DS1 + SG_ XGVCINV : 43|1@0+ (1,0) [0|0] "" DS1 + SG_ S07CNT : 52|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ PCSBRSTA : 50|2@0+ (1,0) [0|0] "" DS1 + SG_ VSC07SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 1056 VSC1S08: 8 CGW + SG_ YR1Z : 7|16@0- (1,0) [0|0] "rad/s" DS1,FCM,MAV + SG_ YR2Z : 23|16@0- (1,0) [0|0] "rad/s" DS1,FCM,MAV + SG_ GL1Z : 39|8@0- (0.0359,0) [0|0] "m/s^2" DS1,FCM,KSS,MAV,SCS + SG_ GL2Z : 47|8@0- (0.0359,0) [0|0] "m/s^2" DS1,FCM,KSS,MAV,SCS + SG_ YRGSDIR : 55|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,SCS + SG_ GLZS : 51|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ YRZF : 50|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRZS : 49|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRZKS : 48|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ VSC08SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + +BO_ 186 VSC1S12: 4 CGW + SG_ HAC2ESRQ : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FHACHOLD : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSC12SUM : 31|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 562 VSC1S14: 6 CGW + SG_ VWPSUMFR : 7|8@0+ (1,0) [0|0] "" MAV + SG_ VWPSUMFL : 15|8@0+ (1,0) [0|0] "" MAV + SG_ VWPFRPM : 23|1@0+ (1,0) [0|0] "" MAV + SG_ VWPFLPM : 22|1@0+ (1,0) [0|0] "" MAV + SG_ S14CNT : 21|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ VWPFRPMS : 18|1@0+ (1,0) [0|0] "" MAV + SG_ VWPFLPMS : 17|1@0+ (1,0) [0|0] "" MAV + SG_ VWPSUMRR : 31|8@0+ (1,0) [0|0] "" MAV + SG_ VWPSUMRL : 39|8@0+ (1,0) [0|0] "" MAV + SG_ VSC14SUM : 47|8@0+ (1,0) [0|0] "" MAV + +BO_ 552 VSC1S29: 4 CGW + SG_ ICBACT : 7|1@0+ (1,0) [0|0] "" DS1 + SG_ DVS0PCS : 6|15@0- (0.001,0) [0|0] "m/s^2" DS1 + SG_ SM228 : 31|8@0+ (1,0) [0|0] "" DS1 + +BO_ 1168 VSC1S92: 1 CGW + SG_ C_DCMOD1 : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_DCMOD2 : 6|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ C_DCMOD3 : 3|4@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 951 VSC1S95: 8 CGW + SG_ B_BRKW : 7|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_ABS : 5|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_BRLV : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRCOFF : 13|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ VSCOFF : 12|2@0+ (1,0) [0|0] "" DS1,FCM + SG_ SLP_WL : 10|3@0+ (1,0) [0|0] "" MAV + SG_ B_MCST : 19|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_BUZZER : 31|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_ALSD : 27|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_DACIND : 25|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ OGENVSC : 37|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_ATRC : 47|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_STRC : 46|3@0+ (1,0) [0|0] "" MAV + SG_ B_HZD : 43|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSCSWIH : 51|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ STRCDISP : 50|3@0+ (1,0) [0|0] "" Vector__XXX + SG_ STRCDSP2 : 60|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSCEXIST : 59|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1063 VSC1S96: 8 CGW + SG_ MTS_DISP : 5|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ B_MTS : 1|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRCCONRL : 11|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRCCONRR : 10|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRCCONFL : 9|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRCCONFR : 8|1@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 545 VSC2F05: 5 CGW + SG_ TQER : 7|16@0- (0.03125,0) [0|0] "Nm" Vector__XXX + SG_ REQC : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ REQ2 : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ REQ1 : 21|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ AIDWI : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ RTD : 19|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ LOMUSFT : 31|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSC2F05S : 39|8@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 544 VSC2F07: 4 CGW + SG_ FSROT : 7|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRK2 : 4|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ BRK1 : 3|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ FCNG : 1|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TSLP : 0|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ TRCACT : 15|1@0+ (1,0) [0|0] "" DS1,FCM + SG_ ABSSLP : 14|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ VDMACT : 13|1@0+ (1,0) [0|0] "" FCM + SG_ DAC_CND : 9|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ VSC2F07S : 31|8@0+ (1,0) [0|0] "" DS1,FCM + +BO_ 36 YGS1S03: 8 CGW + SG_ YRS11S : 7|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRS14S : 6|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRS21S : 5|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YRS24S : 4|1@0+ (1,0) [0|0] "" DS1,FCM,MAV + SG_ YGS1 : 3|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ YGS0 : 2|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR : 1|10@0+ (0.244,-125) [0|0] "deg/sec" DS1,FCM,MAV + SG_ YR_CPUMN : 23|4@0+ (1,0) [0|0] "" Vector__XXX + SG_ GS4S : 19|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ GS1S : 18|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ GL1X : 17|10@0+ (0.03589,-18.375) [0|0] "m/s^2" DS1,FCM,KSS,MAV,SCS + SG_ YG_ID : 39|4@0+ (1,0) [0|0] "" DS1,FCM,KSS,SCS + SG_ GS5S : 35|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ GS2S : 34|1@0+ (1,0) [0|0] "" DS1,FCM,KSS,MAV,SCS + SG_ GL2Y : 33|10@0+ (0.03589,-18.375) [0|0] "m/s^2" DS1,FCM,KSS,MAV,SCS + SG_ YR_DIF : 55|8@0+ (0.244,-31) [0|0] "deg/sec" DS1,FCM,MAV + SG_ YGS03SUM : 63|8@0+ (1,0) [0|0] "" DS1,FCM,MAV + +BO_ 1073743490 YGW1S01_0: 8 CGW + SG_ YGW01_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ YGW01_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_STSW : 22|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_EGST : 20|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_DRLK : 18|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_KLEG : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_HZRD : 26|3@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1073743491 YGW1S02_0: 8 CGW + SG_ YGW02_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ YGW02_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_DEFOG : 19|2@0+ (1,0) [0|0] "" Vector__XXX + SG_ YR_ARCON : 17|2@0+ (1,0) [0|0] "" Vector__XXX + +BO_ 1073743494 YGW1S05_0: 8 CGW + SG_ YGW05_ID : 7|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ YGW05_IF : 15|8@0+ (1,0) [0|0] "" Vector__XXX + SG_ YI_IMO_E : 23|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YI_UREQ : 16|1@0+ (1,0) [0|0] "" Vector__XXX + SG_ YI_RE : 47|16@0+ (1,0) [0|0] "" Vector__XXX diff --git a/opendbc_repo/opendbc/dbc/toyota_adas.dbc b/opendbc_repo/opendbc/dbc/toyota_adas.dbc new file mode 100644 index 0000000000..4aae65aa40 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/toyota_adas.dbc @@ -0,0 +1,276 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + +BO_ 528 TRACK_A_0: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 529 TRACK_A_1: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 530 TRACK_A_2: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 531 TRACK_A_3: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 532 TRACK_A_4: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 533 TRACK_A_5: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 534 TRACK_A_6: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 535 TRACK_A_7: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 536 TRACK_A_8: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 537 TRACK_A_9: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 538 TRACK_A_10: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 539 TRACK_A_11: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 540 TRACK_A_12: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 541 TRACK_A_13: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 542 TRACK_A_14: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 543 TRACK_A_15: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 544 TRACK_B_0: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 545 TRACK_B_1: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 546 TRACK_B_2: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 547 TRACK_B_3: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 548 TRACK_B_4: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 549 TRACK_B_5: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 550 TRACK_B_6: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 551 TRACK_B_7: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 552 TRACK_B_8: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 553 TRACK_B_9: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 554 TRACK_B_10: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 555 TRACK_B_11: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 556 TRACK_B_12: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 557 TRACK_B_13: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 558 TRACK_B_14: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 559 TRACK_B_15: 6 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 47|8@0+ (1,0) [0|255] "" XXX diff --git a/opendbc_repo/opendbc/dbc/toyota_iQ_2009_can.dbc b/opendbc_repo/opendbc/dbc/toyota_iQ_2009_can.dbc new file mode 100644 index 0000000000..2213e1ade2 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/toyota_iQ_2009_can.dbc @@ -0,0 +1,196 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + +BO_ 1552 CONTAINS_LRES_SPEED: 8 XXX + SG_ SPEED_LOWRES : 16|8@1+ (1,0) [0|255] "km/h?" XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 452 ENGINE: 8 XXX + SG_ ENGINE_RPM : 7|16@0+ (1,0) [0|65535] "rpm" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ DIFFERENT_EACH_RIDE : 23|8@0+ (1,0) [0|255] "" XXX + SG_ A_DECREASING_VALUE : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 37 STEERING: 8 XXX + SG_ STEER_DIRECTION : 3|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 42|2@0- (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 44|2@0- (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 46|2@0- (1,0) [0|3] "" XXX + SG_ STEER_ANGLE : 2|11@0- (1,0) [-350|350] "" XXX + +BO_ 36 ACCELERATIONS: 8 XXX + SG_ ACC_LAT_CLEAN : 2|11@0- (1,0) [0|255] "" XXX + SG_ ACC_LATERAL : 63|8@0- (1,0) [0|255] "" XXX + SG_ ACC_FRONT_BACK_1 : 31|8@0- (1,0) [0|255] "" XXX + SG_ ACC_FRONT_BACK_2 : 47|8@0- (1,0) [0|255] "" XXX + +BO_ 947 LOW_RES_INDICATORS: 8 XXX + SG_ LOW_RES_ACC_PEDAL : 23|7@0+ (1,0) [0|63] "" XXX + SG_ LOW_RES_RPM : 7|16@0+ (1,0) [0|255] "rpm" XXX + +BO_ 955 BRAKING_PLUS_OTHER: 8 XXX + SG_ IS_BRAKING_2 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ENGINE_TEMPERATURE : 23|8@0+ (1,0) [0|255] "" XXX + SG_ MAYBE_CLUTCH : 13|1@0+ (1,0) [0|1] "" XXX + +BO_ 1595 CONTAINS_TIME: 8 XXX + SG_ TIME_ON : 55|16@0+ (0.1,0) [0|65535] "s" XXX + SG_ BETWEEN_RIDES : 7|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 170 WHEELS_SPEEDS: 8 XXX + SG_ FRONT_LEFT_WHEEL_SPEED : 23|16@0+ (0.01,-67.67) [0|65535] "km/h" XXX + SG_ REAR_RIGHT_WHEEL_SPEED : 39|16@0+ (0.01,-67.67) [0|65535] "km/h" XXX + SG_ REAR_LEFT_WHEEL_SPEED : 55|16@0+ (0.01,-67.67) [0|65535] "km/h" XXX + SG_ FRONT_RIGHT_WHEEL_SPEED : 7|16@0+ (0.01,-67.67) [0|65535] "km/h" XXX + +BO_ 180 VEHICLE_DYNAMICS: 8 XXX + SG_ WIERD_STUFF : 8|2@1+ (1,0) [0|3] "" XXX + SG_ VEHICLE_SPEED : 47|16@0+ (0.01,0) [0|255] "km/h" XXX + SG_ SPEED_MOD_256 : 63|8@0- (1,0) [0|255] "" XXX + SG_ MAYBE_DISTANCE_MOD_256 : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 186 NEW_MSG_9: 8 XXX + SG_ NEW_SIGNAL_2 : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 426 NEW_MSG_5: 8 XXX + SG_ CONSTANT : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 906 BOOLS: 8 XXX + SG_ MAY_CONTAIN_LIGHTS : 7|4@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_1 : 3|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ MOVEMENT_START_TRIGGER : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 979 LOW_RES_ACCELERATOR: 8 XXX + SG_ VERY_LRES_ACC : 7|16@0+ (1,0) [0|65535] "" XXX + +BO_ 1600 SLOW_VARIABLE_INFOS: 8 XXX + SG_ CHANGES_EACH_RIDE : 31|8@0+ (1,0) [0|255] "" XXX + SG_ INCREASING_VALUE_FUEL : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 1568 DOORS: 8 XXX + SG_ KEY_ACC : 36|1@0+ (1,0) [0|1] "" XXX + SG_ KEY_ON : 37|1@0+ (1,0) [0|1] "" XXX + SG_ KEY_INSERT : 46|1@0+ (1,0) [0|1] "" XXX + SG_ NOT_ON : 63|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_RIGHT : 44|1@0+ (1,0) [0|3] "" XXX + SG_ DOOR_TRUNK : 41|1@1+ (1,0) [0|3] "" XXX + SG_ DOOR_LEFT : 45|1@0+ (1,0) [0|255] "" XXX + SG_ HANDBRAKE : 60|1@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_1 : 4|1@0+ (1,0) [0|1] "" XXX + SG_ DRIVER_SEATBELT : 62|1@0+ (1,0) [0|1] "" XXX + SG_ TRIGGER_BOOL : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 705 COMMAND: 8 XXX + SG_ NOT_ACCELERATING_PEDAL : 3|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_PEDAL_SENSOR : 55|16@0+ (1,0) [0|65535] "" XXX + SG_ ACC_COMMAND : 31|16@0- (1,0) [0|7] "" XXX + SG_ ACC_PEDAL_MEAN : 15|16@0- (1,0) [0|255] "" XXX + SG_ NEGATIVE_COMMAND_OFFSET : 47|8@0- (1,0) [0|255] "" XXX + +BO_ 928 STEER2_MAYBE: 8 XXX + SG_ NEW_SIGNAL_1 : 13|6@0+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_2 : 60|5@0+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_4 : 5|6@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 46|7@0+ (1,0) [0|15] "" XXX + +BO_ 896 LONG_TERM_2: 8 XXX + SG_ NEW_SIGNAL_1 : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 944 LONG_TERM_MSG: 8 XXX + SG_ LONG_TERM_SIGN : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 1553 TOTAL_DIST: 8 XXX + SG_ TOTAL_DISTANCE : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 1572 WHY_THESE_VALUES: 8 XXX + +BO_ 1555 BETWEEN_RIDES_CHANGE_1: 8 XXX + SG_ BETWEEN_RIDES : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 1090 ASYNC_MSG_ACK: 8 XXX + SG_ NEW_SIGNAL_1 : 13|2@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 1592 NEW_MSG_14: 8 XXX + SG_ DOORS_LOCKED2 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ DOORS_LOCKED1 : 16|1@0+ (1,0) [0|1] "" XXX + +BO_ 608 NEW_MSG_6: 8 XXX + SG_ VERY_SMALL_SIGNAL2 : 56|1@0+ (1,0) [0|255] "" XXX + SG_ VERY_SMALL_SIGNAL1 : 0|1@0+ (1,0) [0|1] "" XXX + +BO_ 945 BETWEEN_RIDES_CHANGES_2: 8 XXX + SG_ BETWEEN_RIDES : 24|1@0+ (1,0) [0|65535] "" XXX + + + + +CM_ SG_ 1552 SPEED_LOWRES "Negative values to check"; +CM_ SG_ 452 CHECKSUM "Follows path of RPMs but more precise & 1 byte only"; +CM_ SG_ 452 A_DECREASING_VALUE "stabilizes to 62 after ~10 mins"; +CM_ SG_ 37 STEER_DIRECTION "Could be intended as 12 bit steering angle"; +CM_ SG_ 37 STEER_ANGLE "can convert to degrees (imprecise) or percentage of max amplitude"; +CM_ SG_ 36 ACC_FRONT_BACK_1 "more likely up-down"; +CM_ SG_ 36 ACC_FRONT_BACK_2 "more likely front-back"; +CM_ SG_ 947 LOW_RES_ACC_PEDAL "Follows rather closely other acceleration commands"; +CM_ SG_ 947 LOW_RES_RPM "Maybe used for onboard display?"; +CM_ SG_ 955 MAYBE_CLUTCH "might be related to shifting gears"; +CM_ SG_ 1595 TIME_ON "Time since last ignition, tenth of seconds"; +CM_ SG_ 1595 BETWEEN_RIDES "the fourth byte (at least) changes between rides"; +CM_ SG_ 180 WIERD_STUFF "Might be a signed value on the whole two bytes (sometimes all set)"; +CM_ SG_ 180 VEHICLE_SPEED "Roughly 2 seconds before wheel speeds"; +CM_ SG_ 180 SPEED_MOD_256 "One byte speed, a bit before vehicle speed"; +CM_ SG_ 180 MAYBE_DISTANCE_MOD_256 "Looks like measure for distance or wheel angle"; +CM_ SG_ 906 MOVEMENT_START_TRIGGER "trigger of when speed becomes != 0"; +CM_ SG_ 979 VERY_LRES_ACC "Power used by engine? moves alongside speed, very low res, goes from 0 to 9 max?"; +CM_ SG_ 1600 CHANGES_EACH_RIDE "Small decrementation during some rides, possibly long term fuel"; +CM_ SG_ 1600 INCREASING_VALUE_FUEL "Fuel/distance? Average fuel consumption?"; +CM_ SG_ 705 NOT_ACCELERATING_PEDAL "Looks like opposite of accelerating bit"; +CM_ SG_ 705 ACC_PEDAL_SENSOR "similar to pedal sensor maybe checksum."; +CM_ SG_ 705 ACC_COMMAND "Similar to other pedal indicator., cleaner, must be sent back to engine"; +CM_ SG_ 705 ACC_PEDAL_MEAN "Actual sensor for pedal (works when engine off)"; +CM_ SG_ 705 NEGATIVE_COMMAND_OFFSET "Mysterious for now"; +CM_ SG_ 928 NEW_SIGNAL_1 "Very slow changing noisy value, 45-49 in 10 min"; +CM_ SG_ 928 NEW_SIGNAL_2 "Other very slow changing 24-26 in 10 min"; +CM_ SG_ 928 NEW_SIGNAL_4 "Inconsistent across rides"; +CM_ SG_ 896 NEW_SIGNAL_1 "there is a difference at the beginning of 2017-10-31--12-04-05"; +CM_ SG_ 1553 TOTAL_DISTANCE "Probably also contains the previous/two previous bytes but can't confirm"; +CM_ SG_ 945 BETWEEN_RIDES "Might be others in the same message. at least this one"; + diff --git a/opendbc_repo/opendbc/dbc/toyota_prius_2010_pt.dbc b/opendbc_repo/opendbc/dbc/toyota_prius_2010_pt.dbc new file mode 100644 index 0000000000..5c7df7d18b --- /dev/null +++ b/opendbc_repo/opendbc/dbc/toyota_prius_2010_pt.dbc @@ -0,0 +1,203 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX DSU HCU EPS IPAS + + +BO_ 36 KINEMATICS: 8 XXX + SG_ ACCEL_Y : 33|10@0+ (1,-512) [0|65535] "" XXX + SG_ STEERING_TORQUE : 17|10@0+ (1,-512) [0|65535] "" XXX + SG_ YAW_RATE : 1|10@0+ (1,-512) [0|65535] "" XXX + +BO_ 166 BRAKE: 8 XXX + SG_ BRAKE_AMOUNT : 7|8@0+ (1,0) [0|255] "" XXX + SG_ BRAKE_PEDAL : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 170 WHEEL_SPEEDS: 8 XXX + SG_ WHEEL_SPEED_FR : 7|16@0+ (0.0062,-67.67) [0|250] "mph" XXX + SG_ WHEEL_SPEED_FL : 23|16@0+ (0.0062,-67.67) [0|250] "mph" XXX + SG_ WHEEL_SPEED_RR : 39|16@0+ (0.0062,-67.67) [0|250] "mph" XXX + SG_ WHEEL_SPEED_RL : 55|16@0+ (0.0062,-67.67) [0|250] "mph" XXX + +BO_ 180 SPEED: 8 XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ SPEED : 47|16@0+ (0.0062,0) [0|115] "mph" XXX + SG_ ENCODER : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 295 GEAR_PACKET: 8 XXX + SG_ CAR_MOVEMENT : 39|8@0- (1,0) [0|255] "" XXX + SG_ COUNTER : 55|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + SG_ GEAR : 47|4@0+ (1,0) [0|15] "" XXX + +BO_ 466 PCM_CRUISE: 8 XXX + SG_ GAS_RELEASED : 4|1@0+ (1,0) [0|1] "" XXX + SG_ ACCEL_NET : 23|16@0- (0.001,0) [-20|20] "m/s2" XXX + SG_ CRUISE_STATE : 55|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 550 BRAKE_MODULE: 8 XXX + SG_ BRAKE_PRESSURE : 0|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_POSITION : 16|9@0+ (1,0) [0|511] "" XXX + SG_ BRAKE_PRESSED : 37|1@0+ (1,0) [0|1] "" XXX + +BO_ 552 ACCELEROMETER: 8 XXX + SG_ ACCEL_Z : 22|15@0- (1,0) [0|32767] "" XXX + SG_ ACCEL_X : 6|15@0- (0.001,0) [-20|20] "m/s2" XXX + +BO_ 560 BRAKE_MODULE2: 8 XXX + SG_ BRAKE_LIGHTS : 26|1@0+ (1,0) [0|1] "" XXX + +BO_ 581 GAS_PEDAL: 8 XXX + SG_ GAS_PEDAL : 23|8@0+ (0.005,0) [0|1] "" XXX + +BO_ 608 STEER_TORQUE_SENSOR: 8 XXX + SG_ STEER_TORQUE_EPS : 47|16@0- (0.66,0) [-20000|20000] "" XXX + SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX + SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 610 EPS_STATUS: 5 EPS + SG_ STATE : 3|4@0+ (1,0) [0|15] "" XXX + SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 614 STEERING_IPAS: 8 IPAS + SG_ STATE : 7|4@0+ (1,0) [0|15] "" XXX + SG_ ANGLE : 3|12@0- (1,0) [0|16777215] "" XXX + SG_ SET_ME_X10 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ SET_ME_X00_1 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ DIRECTION_CMD : 38|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 643 PRE_COLLISION: 8 XXX + +BO_ 740 STEERING_LKA: 8 XXX + SG_ LKA_STATE : 31|8@0+ (1,0) [0|255] "" XXX + SG_ CHECKSUM : 39|8@0+ (1,0) [0|255] "" XXX + SG_ STEER_REQUEST : 0|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 6|6@0+ (1,0) [0|63] "" XXX + SG_ SET_ME_1 : 7|1@0+ (1,0) [0|1] "" XXX + SG_ STEER_TORQUE_CMD : 15|16@0- (1,0) [0|65535] "" XXX + +BO_ 742 LEAD_INFO: 8 DSU + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" HCU + SG_ LEAD_REL_SPEED : 23|12@0- (0.025,0) [-100|100] "m/s" HCU + SG_ LEAD_LONG_DIST : 7|13@0+ (0.05,0) [0|300] "m" HCU + +BO_ 835 ACC_CONTROL: 8 DSU + SG_ ACCEL_CMD : 7|16@0- (0.001,0) [-20|20] "m/s2" HCU + +BO_ 1556 STEERING_LEVERS: 8 XXX + SG_ TURN_SIGNALS : 29|2@0+ (1,0) [0|3] "" XXX + +BO_ 37 STEER_ANGLE_SENSOR: 8 XXX + SG_ STEER_ANGLE : 3|12@0- (1.5,0) [-500|500] "deg" XXX + SG_ STEER_FRACTION : 39|4@0- (0.1,0) [-0.7|0.7] "deg" XXX + SG_ STEER_RATE : 35|12@0- (1,0) [-2000|2000] "deg/s" XXX + +BO_ 467 PCM_CRUISE_2: 8 XXX + SG_ MAIN_ON : 15|1@0+ (1,0) [0|1] "" XXX + SG_ LOW_SPEED_LOCKOUT : 14|2@0+ (1,0) [0|3] "kph" XXX + SG_ SET_SPEED : 23|8@0+ (1,0) [0|255] "kph" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 921 PCM_CRUISE_SM: 8 XXX + SG_ MAIN_ON : 4|1@0+ (1,0) [0|1] "" XXX + SG_ CRUISE_CONTROL_STATE : 11|4@0+ (1,0) [0|15] "" XXX + SG_ UI_SET_SPEED : 31|8@0+ (1,0) [0|255] "" XXX + +BO_ 951 ESP_CONTROL: 8 ESP + SG_ TC_DISABLED : 13|1@0+ (1,0) [0|1] "" XXX + +BO_ 1042 LKAS_HUD: 8 XXX + SG_ BARRIERS : 1|2@0+ (1,0) [0|3] "" XXX + SG_ RIGHT_LINE : 3|2@0+ (1,0) [0|3] "" XXX + SG_ LEFT_LINE : 5|2@0+ (1,0) [0|3] "" XXX + SG_ SET_ME_1 : 7|2@0+ (1,0) [0|3] "" XXX + SG_ LDA_ALERT : 9|2@0+ (1,0) [0|3] "" XXX + SG_ TWO_BEEPS : 12|1@0+ (1,0) [0|1] "" XXX + SG_ ADJUSTING_CAMERA : 13|1@0+ (1,0) [0|1] "" XXX + SG_ LDA_MALFUNCTION : 15|1@0+ (1,0) [0|1] "" XXX + +BO_ 1553 UI_SEETING: 8 XXX + SG_ UNITS : 26|2@0+ (1,0) [0|3] "" XXX + +BO_ 1568 SEATS_DOORS: 8 XXX + SG_ SEATBELT_DRIVER_UNLATCHED : 62|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FL : 45|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RL : 42|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_RR : 43|1@0+ (1,0) [0|1] "" XXX + SG_ DOOR_OPEN_FR : 44|1@0+ (1,0) [0|1] "" XXX + +BO_ 452 POWERTRAIN: 8 XXX + SG_ ENGINE_RPM : 7|16@0+ (1,0) [0|65535] "rpm" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + + + + +CM_ SG_ 36 ACCEL_Y "unit is tbd"; +CM_ SG_ 36 STEERING_TORQUE "does not seem the steer torque, tbd"; +CM_ SG_ 36 YAW_RATE "verify"; +CM_ SG_ 466 ACCEL_NET "net acceleration produced by the system, given ACCEL_CMD, road grade and other factors"; +CM_ SG_ 466 CRUISE_STATE "Active state is 8, if standstill is requested will switch to state 11(3 sec timer), after timer is elapsed will switch into state 7(standstill). If plus button was pressed - status 9, minus button pressed - status 10"; +CM_ SG_ 550 BRAKE_PRESSURE "seems prop to pedal force"; +CM_ SG_ 550 BRAKE_POSITION "seems proportional to pedal displacement, unclear the max value of 0x1c8"; +CM_ SG_ 560 BRAKE_LIGHTS "double check"; +CM_ SG_ 581 GAS_PEDAL "it seems slightly filtered"; +CM_ SG_ 608 STEER_TORQUE_DRIVER "driver torque"; +CM_ SG_ 608 STEER_OVERRIDE "set when driver torque exceeds a certain value"; +CM_ SG_ 614 ANGLE "set to measured angle when ipas control isn't active"; +CM_ SG_ 37 STEER_FRACTION "1/15th of the signal STEER_ANGLE, which is 1.5 deg; note that 0x8 is never set"; +CM_ SG_ 37 STEER_RATE "factor is tbd"; +CM_ SG_ 467 LOW_SPEED_LOCKOUT "in low speed lockout, system would always disengage below 28mph"; +CM_ SG_ 467 SET_SPEED "43 kph are shown as 28mph, so conversion isn't perfect"; +CM_ SG_ 921 UI_SET_SPEED "set speed shown in UI with user set unit"; +CM_ SG_ 1042 SET_ME_1 "unclear what this is, nut it's always 1 in drive traces"; +VAL_ 295 GEAR 0 "P" 1 "R" 2 "N" 3 "D" 4 "B" ; +VAL_ 466 CRUISE_STATE 11 "timer_3sec" 10 "setspeeddown" 9 "setspeedup" 8 "active" 7 "standstill" 1 "off" 0 "off"; +VAL_ 610 STATE 5 "override" 3 "enabled" 1 "disabled" ; +VAL_ 610 LKA_STATE 50 "temporary_fault" ; +VAL_ 614 STATE 3 "enabled" 1 "disabled" ; +VAL_ 614 DIRECTION_CMD 3 "right" 2 "center" 1 "left" ; +VAL_ 1556 TURN_SIGNALS 3 "none" 2 "right" 1 "left" ; +VAL_ 467 LOW_SPEED_LOCKOUT 2 "low speed locked" 1 "ok" ; +VAL_ 921 CRUISE_CONTROL_STATE 2 "disabled" 11 "hold" 10 "hold_waiting_user_cmd" 6 "enabled" 5 "faulted" ; +VAL_ 1042 BARRIERS 3 "both" 2 "right" 1 "left" 0 "none" ; +VAL_ 1042 RIGHT_LINE 3 "orange" 2 "double" 1 "solid" 0 "none" ; +VAL_ 1042 LEFT_LINE 3 "orange" 2 "double" 1 "solid" 0 "none" ; +VAL_ 1042 LDA_ALERT 3 "hold with continuous beep" 2 "LDA unavailable" 1 "hold" 0 "none" ; +VAL_ 1553 UNITS 1 "km" 2 "miles" ; diff --git a/opendbc_repo/opendbc/dbc/toyota_radar_dsu_tssp.dbc b/opendbc_repo/opendbc/dbc/toyota_radar_dsu_tssp.dbc new file mode 100644 index 0000000000..168e589136 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/toyota_radar_dsu_tssp.dbc @@ -0,0 +1,194 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX RADAR + +BO_ 768 BUTTONS: 8 RADAR + SG_ LKAS_PRESS : 2|1@0+ (1,0) [0|1] "" XXX + SG_ DISTANCE_PRESS : 5|1@0+ (1,0) [0|1] "" XXX + +BO_ 769 OBJECT_0: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 771 OBJECT_1: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 773 OBJECT_2: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 775 OBJECT_3: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 777 OBJECT_4: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 779 OBJECT_5: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 781 OBJECT_6: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 783 OBJECT_7: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 785 OBJECT_8: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 787 OBJECT_9: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 789 OBJECT_10: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 791 OBJECT_11: 8 RADAR + SG_ ID : 5|6@0+ (1,0) [0|255] "" XXX + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|65535] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.018,0) [0|15] "" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "Front target" +BO_ 1664 CLUSTER_F: 8 RADAR + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|255] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.015,0) [-20|20] "m" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ ID : 0|6@1+ (1,0) [0|63] "" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "Front target ahead" +BO_ 1665 CLUSTER_F_A: 8 RADAR + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|255] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.015,0) [-20|20] "m" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ ID : 0|6@1+ (1,0) [0|63] "" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "Left target" +BO_ 1666 CLUSTER_L: 8 RADAR + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|255] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.015,0) [-20|20] "m" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ VALID : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ID : 0|6@1+ (1,0) [0|63] "" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "Right target" +BO_ 1667 CLUSTER_R: 8 RADAR + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|255] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.015,0) [-20|20] "m" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ VALID : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ID : 0|6@1+ (1,0) [0|63] "" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "Left target ahead" +BO_ 1668 CLUSTER_L_A: 8 RADAR + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|255] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.015,0) [-20|20] "m" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ VALID : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ID : 0|6@1+ (1,0) [0|63] "" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ "Right target ahead" +BO_ 1669 CLUSTER_R_A: 8 RADAR + SG_ LONG_DIST : 7|13@1+ (0.03,0) [0|255] "m" XXX + SG_ LAT_DIST : 20|11@1- (0.015,0) [-20|20] "m" XXX + SG_ SPEED : 31|10@1- (0.06944444444,0) [0|71] "m/s" XXX + SG_ VALID : 6|1@0+ (1,0) [0|1] "" XXX + SG_ ID : 0|6@1+ (1,0) [0|63] "" XXX + SG_ LAT_SPEED : 48|7@1- (0.1,0) [0|127] "m/s" XXX + SG_ RCS : 63|8@0+ (1,0) [0|255] "" XXX diff --git a/opendbc_repo/opendbc/dbc/toyota_tss2_adas.dbc b/opendbc_repo/opendbc/dbc/toyota_tss2_adas.dbc new file mode 100644 index 0000000000..d472debd61 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/toyota_tss2_adas.dbc @@ -0,0 +1,285 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX + + +BO_ 384 TRACK_A_0: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 385 TRACK_A_1: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 386 TRACK_A_2: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 387 TRACK_A_3: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 388 TRACK_A_4: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 389 TRACK_A_5: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 390 TRACK_A_6: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 391 TRACK_A_7: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 392 TRACK_A_8: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 393 TRACK_A_9: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 394 TRACK_A_10: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 395 TRACK_A_11: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 396 TRACK_A_12: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 397 TRACK_A_13: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 398 TRACK_A_14: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 399 TRACK_A_15: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ LAT_DIST : 31|11@0- (0.04,0) [-50|50] "m" XXX + SG_ LONG_DIST : 15|13@0+ (0.04,0) [0|300] "m" XXX + SG_ NEW_TRACK : 36|1@0+ (1,0) [0|1] "" XXX + SG_ REL_SPEED : 47|12@0- (0.025,0) [-100|100] "m/s" XXX + SG_ VALID : 48|1@0+ (1,0) [0|1] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 400 TRACK_B_0: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 401 TRACK_B_1: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 402 TRACK_B_2: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 403 TRACK_B_3: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 404 TRACK_B_4: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 405 TRACK_B_5: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 406 TRACK_B_6: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 407 TRACK_B_7: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 408 TRACK_B_8: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 409 TRACK_B_9: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 410 TRACK_B_10: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 411 TRACK_B_11: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 412 TRACK_B_12: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 413 TRACK_B_13: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 414 TRACK_B_14: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 415 TRACK_B_15: 8 XXX + SG_ COUNTER : 7|8@0+ (1,0) [0|255] "" XXX + SG_ REL_ACCEL : 15|7@0- (1,0) [-64|63] "" XXX + SG_ SCORE : 23|8@0+ (1,0) [0|100] "" XXX + SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 576 NEW_MSG_1: 8 XXX + SG_ NEW_SIGNAL_1 : 15|7@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_2 : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 577 NEW_MSG_2: 8 XXX + SG_ NEW_SIGNAL_1 : 15|7@0+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_2 : 23|8@0+ (1,0) [0|255] "" XXX diff --git a/opendbc_repo/opendbc/dbc/volvo_v40_2017_pt.dbc b/opendbc_repo/opendbc/dbc/volvo_v40_2017_pt.dbc new file mode 100644 index 0000000000..c5f533d601 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/volvo_v40_2017_pt.dbc @@ -0,0 +1,363 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX BCM CEM CVM DIM ECM FSM PSCM SAS SRS TCM + +BO_ 8 SAS0: 8 SAS + SG_ SteeringDirection : 42|1@0+ (1,0) [0|1] "" XXX + SG_ RelativeTurnDirection : 43|1@0+ (1,0) [0|1] "" XXX + SG_ SteeringAngle : 53|14@0+ (0.04395,0) [0|65535] "degrees" XXX + SG_ NEW_SIGNAL_1 : 47|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 39|4@0+ (1,0) [0|15] "" XXX + SG_ AngleRate : 21|14@0+ (0.075,0) [0|1500] "deg/S" XXX + +BO_ 16 CCButtons: 8 CEM + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|5@0+ (1,0) [0|31] "" XXX + SG_ B7b0 : 56|1@0+ (1,0) [0|1] "" XXX + SG_ B7b1 : 57|1@0+ (1,0) [0|1] "" XXX + SG_ B7b6 : 62|1@0+ (1,0) [0|1] "" XXX + SG_ ACCOnOffBtn : 58|1@0+ (1,0) [0|1] "" XXX + SG_ ACCSetBtn : 63|1@0+ (1,0) [0|1] "" XXX + SG_ ACCStopBtn : 60|1@0+ (1,0) [0|1] "" XXX + SG_ ACCResumeBtn : 61|1@0+ (1,0) [0|1] "" XXX + SG_ ACCMinusBtn : 48|1@0+ (1,0) [0|1] "" XXX + SG_ TimeGapIncreaseBtn : 49|1@0+ (1,0) [0|1] "" XXX + SG_ TimeGapDecreaseBtn : 50|1@0+ (1,0) [0|1] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ B7b3 : 59|1@0+ (1,0) [0|1] "" XXX + +BO_ 48 FSM0: 8 FSM + SG_ ACCStatusTracking : 56|1@0+ (1,0) [0|1] "" XXX + SG_ ACCStatusOnOff : 57|1@0+ (1,0) [0|1] "" XXX + SG_ ACCStatusActive : 58|1@0+ (1,0) [0|1] "" XXX + SG_ FCWSomething : 25|3@0+ (1,0) [0|3] "" XXX + SG_ StatusSomething : 55|8@0+ (1,0) [0|255] "" XXX + +BO_ 64 TCM0: 8 TCM + SG_ RPMSomething : 42|11@0+ (1,0) [0|2047] "" XXX + SG_ GearShifter : 46|2@0+ (1,0) [0|3] "" XXX + +BO_ 85 PedalandBrake: 8 ECM + SG_ AccPedal : 9|10@0+ (0.1,0) [0|1023] "%" XXX + SG_ BrakePedalActive2 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 35|12@0+ (1,0) [0|4095] "" XXX + SG_ BrakePedalActive : 38|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 101 EngineInfo: 8 XXX + SG_ NEW_SIGNAL_1 : 17|10@0+ (1,-512) [0|1023] "" XXX + SG_ EngineSpeed : 52|13@0+ (1,0) [0|1023] "" XXX + +BO_ 112 NEW_MSG_4: 8 XXX + SG_ NEW_SIGNAL_1 : 39|8@0+ (1,0) [0|255] "" XXX + +BO_ 114 ECM1: 8 ECM1 + SG_ NEW_SIGNAL_1 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ ECM_ACC_ONOFF_INV : 43|1@0+ (1,0) [0|1] "" XXX + SG_ ECM_ACC_RESUME_INV : 45|1@0+ (1,0) [0|1] "" XXX + SG_ ECM_ACC_SET_INV : 47|1@0+ (1,0) [0|1] "" XXX + SG_ ECM_ACC_TIMEGAP_INC_INV : 33|1@0+ (1,0) [0|1] "" XXX + SG_ ECM_ACC_DEC_INV : 32|1@0+ (1,0) [0|1] "" XXX + SG_ ECM_ACC_TIMEGAP_DEC_INV : 34|1@0+ (1,0) [0|1] "" XXX + +BO_ 117 ECM1_2: 8 ECM + +BO_ 128 NEW_MSG_5: 8 XXX + SG_ NEW_SIGNAL_2 : 26|11@0+ (1,0) [0|2047] "" XXX + SG_ NEW_SIGNAL_1 : 52|13@0+ (1,0) [0|8191] "" XXX + +BO_ 176 ECM2: 8 ECM + SG_ NEW_SIGNAL_1 : 50|11@0+ (1,0) [0|2047] "" XXX + SG_ NEW_SIGNAL_2 : 47|8@0+ (1,0) [0|63] "" XXX + +BO_ 192 Gear: 8 XXX + SG_ TransmissionGear : 36|3@0+ (1,1) [0|7] "" XXX + +BO_ 208 FSM1: 8 FSM + SG_ SET_X_E3 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SET_X_B4 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ SET_X_08 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ TrqLim : 31|8@0+ (1,-128) [0|255] "" XXX + SG_ Checksum : 55|8@0+ (1,0) [0|255] "" XXX + SG_ LKASteerDirection : 57|2@0+ (1,0) [0|2] "" XXX + SG_ SET_X_25 : 63|6@0+ (1,0) [0|63] "" XXX + SG_ LKAAngleReq : 37|14@0+ (0.04395,-360.0384) [-360.0384|359.99445] "degrees" XXX + SG_ SET_X_02 : 39|2@0+ (1,0) [0|3] "" XXX + +BO_ 224 PSCM0: 8 PSCM + SG_ NEW_SIGNAL_2 : 12|5@0+ (1,0) [0|31] "" XXX + SG_ counter_07 : 15|3@0+ (1,0) [0|7] "" XXX + SG_ counter2_07 : 37|3@0+ (1,0) [0|16383] "" XXX + SG_ rate_of_something : 46|7@0+ (1,0) [0|62] "" XXX + SG_ OneDuringDriving : 49|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 245 wheelspeed0: 8 BCM + SG_ counter1 : 21|6@0+ (1,0) [0|65535] "" XXX + SG_ counter0 : 7|16@0+ (1,0) [0|65535] "" XXX + SG_ WhlSpdLF : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ WhlSpdRF : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 272 SpeedSignal0: 8 XXX + SG_ VehicleSpeedSignal : 55|16@0+ (0.01,0) [0|65535] "" XXX + +BO_ 288 wheel_speed1: 8 BCM + SG_ WhlSpdLR : 39|16@0+ (1,0) [0|65535] "" XXX + SG_ WhlSpdRR : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 293 PSCM1: 8 PSCM + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + SG_ LKATorque : 11|12@0+ (1,-2000) [0|4095] "" XXX + SG_ SteeringAngleServo : 47|16@0+ (0.04395,-1440.1536) [0|65535] "deg" XXX + SG_ LKAActive : 15|4@0+ (1,0) [0|15] "" XXX + +BO_ 304 VehicleSpeed0: 8 BCM + SG_ NEW_SIGNAL_2 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ VehicleSpeed : 31|16@0+ (0.01,0) [0|65535] "km/h" XXX + SG_ NEW_SIGNAL_1 : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 325 ECM3: 8 ECM + +BO_ 336 VehicleSpeed1: 8 BCM + SG_ NEW_SIGNAL_2 : 31|16@0+ (1,0) [0|65535] "" XXX + SG_ NEW_SIGNAL_1 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ VehicleSpeed : 55|16@0+ (0.01,0) [0|65535] "" XXX + +BO_ 352 FSM2: 8 FSM + SG_ LkaDimLine : 51|2@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_2 : 56|7@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 55|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 7|24@0+ (1,0) [0|16777215] "" XXX + SG_ NEW_SIGNAL_4 : 36|5@0+ (1,0) [0|31] "" XXX + +BO_ 432 BrakeMessages: 8 BCM + SG_ BrakePress0 : 1|10@0+ (1,0) [0|1023] "" XXX + SG_ BrakePress1 : 33|10@0+ (1,0) [0|1023] "" XXX + SG_ BrakeStatus : 18|3@0+ (1,0) [0|7] "" XXX + +BO_ 464 DIM0: 8 DIM + +BO_ 480 BCM0: 8 BCM + +BO_ 528 CEM0: 8 CEM + +BO_ 608 CVM0: 8 CVM + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 15|5@0+ (1,0) [0|32] "" XXX + SG_ Distance : 10|11@0+ (1,0) [0|2048] "" XXX + +BO_ 624 FSM3: 8 FSM + SG_ NEW_SIGNAL_1 : 23|8@0+ (1,0) [0|255] "" XXX + +BO_ 640 FSM4: 8 FSM + SG_ SpeedTarget : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_1 : 49|10@0+ (1,0) [0|255] "" XXX + +BO_ 648 SRS0: 8 SRS + +BO_ 652 ECM4: 8 ECM + +BO_ 656 ECM5: 8 ECM + +BO_ 657 ECM6: 8 ECM + +BO_ 681 MiscCarInfo: 8 CEM + SG_ TurnSignal : 1|2@0+ (1,0) [0|3] "" XXX + SG_ HighBeamOn : 52|1@0+ (1,0) [0|1] "" XX + +BO_ 693 ECM7: 8 ECM + +BO_ 709 ACC: 8 ECM + SG_ SpeedTargetACC : 0|9@0+ (0.5,0) [0|511] "" XXX + +BO_ 853 FSM5: 8 FSM + SG_ TargetSpeedOdo : 23|8@0+ (1,0) [0|63] "kph" XXX + SG_ SpeedSign : 36|5@0+ (5,0) [0|32] "" XXX + SG_ TextUnderSign : 37|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 39|3@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ LaneMarkingsOdo : 15|4@0+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_2 : 11|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_4 : 55|16@0+ (1,0) [0|65535] "" XXX + +BO_ 864 CEM1: 8 CEM + +BO_ 912 DIM1: 8 DIM + +BO_ 968 SRS1: 8 SRS + SG_ PassengerSeatBelt : 22|1@0+ (1,0) [0|1] "" XXX + SG_ DriverSeatBelt : 19|1@0+ (1,0) [0|1] "" XXX + +BO_ 1029 CEMBCM0: 8 CEM + +BO_ 1344 NEW_MSG_1: 8 XXX + SG_ NEW_SIGNAL_1 : 4|13@0+ (1,0) [0|8191] "" XXX + +BO_ 1830 diagCEMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1838 diagCEMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1840 diagPSCMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1848 diagPSCMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1892 diagFSMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1900 diagFSMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1939 diagCVMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1947 diagCVMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2015 diagGlobalReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + + + + +CM_ SG_ 85 BrakePedalActive2 "Active during braking"; +CM_ SG_ 85 NEW_SIGNAL_1 "Not yet figured out."; +CM_ SG_ 85 BrakePedalActive "Brake pedal pushed"; +CM_ SG_ 8 SteeringDirection "1=Right turn, 0=Left turn. Steering wheel pointing left or right from center (0 deg)."; +CM_ SG_ 8 RelativeTurnDirection "1=Right turn, 0=Left turn. Steering wheel currently turning the way."; +CM_ SG_ 101 NEW_SIGNAL_1 "Rate of something?"; +CM_ SG_ 192 TransmissionGear "0 = 1st gear, 1= 2nd gear..."; +CM_ SG_ 681 TurnSignal "0 = Nothing, 1= Left, 3=Right"; +CM_ SG_ 681 HighBeamOn "1=HighBeam On, 0=HighBeam Off"; +CM_ SG_ 48 ACCStatusTracking "ACC Tracking vehicle, distance control."; +CM_ SG_ 48 ACCStatusOnOff "Turns one after pressing on/off button on steering wheel"; +CM_ SG_ 48 ACCStatusActive "ACC Active"; +CM_ SG_ 48 FCWSomething "All bit set during fcw"; +CM_ SG_ 48 StatusSomething "Some status changes when zeroing DTCs"; +CM_ SG_ 208 TrqLim "Used in checksum calculation, Limit directional torque based on the number."; +CM_ SG_ 208 Checksum "Checksum calculated as a one-complement addition of LKAAngleRequest+LKADirection+Unkown, Zeros used to pad missing bits."; +CM_ SG_ 208 SET_X_02 "Bit 0 = Vibrate steering wheel., Bit 1 = Heartbeat"; +CM_ SG_ 352 LkaDimLine "Not true, but follows lka steer direction."; +CM_ SG_ 352 NEW_SIGNAL_1 "Turned one. Got LKA service needed can this be the one?"; +CM_ SG_ 640 SpeedTarget "SpeedTarget ACC (noisy bf starting acc Jumps from 0->252->0)"; +CM_ SG_ 853 TargetSpeedOdo "Probably target speed odo"; +CM_ SG_ 853 LaneMarkingsOdo "Bit 3=Left lane, Bit 2=Right lane, Bit 1=LKA on?, Bit 0=?"; +CM_ SG_ 709 SpeedTargetACC "SpeedTargetACC"; +CM_ SG_ 224 rate_of_something "Seems to be some kind of torque rather than rate."; +CM_ SG_ 224 OneDuringDriving "Set to 1 when vehicle is rolling."; +CM_ SG_ 293 byte7 "Bit0=0 when gearshift in park, else 1"; +CM_ SG_ 293 LKAActive "Bit0=0 when gear in park otherwise =1, Bit1=1 when LKA Active, 0 when not active. Bit2=? Bit3=?"; +CM_ SG_ 16 ACCOnOffBtn "Cruise control on/off button pressed"; +CM_ SG_ 16 ACCSetBtn "Acc Set button (+) pressed"; +CM_ SG_ 16 ACCStopBtn "ACC Stop button pressed"; +CM_ SG_ 16 ACCResumeBtn "ACC Resume button pressed"; +CM_ SG_ 16 ACCMinusBtn "ACC Minus (-) button pressed"; +CM_ SG_ 16 TimeGapIncreaseBtn "Increase the time gap on ACC"; +CM_ SG_ 16 TimeGapDecreaseBtn "Decrease the time gap on ACC"; +CM_ SG_ 245 counter0 "Speed based counter"; +CM_ SG_ 245 WhlSpdLF "Wheel speed left front"; +CM_ SG_ 245 WhlSpdRF "Wheel speed right front"; +CM_ SG_ 288 WhlSpdLR "Wheel speed left rear"; +CM_ SG_ 288 WhlSpdRR "Wheel speed right rear"; +CM_ SG_ 64 RPMSomething "TransmissionOutput?"; +CM_ SG_ 64 GearShifter "P=0, R=1, N=2, D=3"; +CM_ SG_ 272 VehicleSpeedSignal "km/h"; +CM_ SG_ 432 BrakePress0 "Brake being pressed"; +CM_ SG_ 432 BrakePress1 "Brake being pressed"; +CM_ SG_ 432 BrakeStatus "ACC brake?"; +CM_ SG_ 437 Counter0 "Related to braking? Maybe one per wheel?"; +CM_ SG_ 437 Counter1 "Related to braking? Maybe one per wheel?"; +CM_ SG_ 437 Counter2 "Related to braking? Maybe one per wheel?"; +CM_ SG_ 437 Counter3 "Related to braking? Maybe one per wheel?"; +CM_ SG_ 114 NEW_SIGNAL_1 "Jumped from 0 -> 120 during start. Makes triangle from time to time"; +CM_ SG_ 608 NEW_SIGNAL_1 "Status?"; +CM_ SG_ 608 NEW_SIGNAL_2 "Classification of object?"; +CM_ SG_ 608 Distance "Distance to object in front."; +CM_ SG_ 968 PassengerSeatBelt "1 = Seatbelt latched"; +CM_ SG_ 968 DriverSeatBelt "1=Seatbelt latched"; +VAL_ 64 GearShifter 0 "P" 1 "R" 2 "N" 3 "D" ; diff --git a/opendbc_repo/opendbc/dbc/volvo_v60_2015_pt.dbc b/opendbc_repo/opendbc/dbc/volvo_v60_2015_pt.dbc new file mode 100644 index 0000000000..d2b58fdd01 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/volvo_v60_2015_pt.dbc @@ -0,0 +1,298 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: XXX BCM CEM FSM PSCM SAS + +BO_ 16 SAS0: 8 SAS + SG_ Counter0 : 3|8@0+ (1,0) [0|511] "" XXX + SG_ SteeringDirection : 6|1@0+ (1,0) [0|1] "" XXX + SG_ SteeringRateOfChange2 : 22|15@0+ (1,0) [0|32767] "" XXX + SG_ SteeringPressureOnIt : 23|1@0+ (1,0) [0|1] "" XXX + SG_ SteeringRateOfChange : 39|16@0+ (1,-32768) [0|65535] "" XXX + SG_ SteeringAngle : 53|14@0+ (0.0445,0) [0|65535] "degrees" XXX + +BO_ 32 AccPedal: 8 XXX + SG_ AccPedal : 17|10@0+ (0.1,0) [0|100.0] "%" XXX + +BO_ 81 FSM0: 8 FSM + SG_ ACCStatus : 18|3@0+ (1,0) [0|7] "" XXX + +BO_ 277 NEW_MSG_7: 8 XXX + SG_ NEW_SIGNAL_1 : 39|16@0+ (1,0) [0|65535] "" XXX + +BO_ 295 CCButtons: 8 CEM + SG_ ACCMinusBtnInv : 32|1@0+ (1,0) [0|1] "" XXX + SG_ TimeGapIncreaseBtnInv : 33|1@0+ (1,0) [0|1] "" XXX + SG_ TimeGapDecreaseBtnInv : 34|1@0+ (1,0) [0|1] "" XXX + SG_ ACCOnOffBtnInv : 43|1@0+ (1,0) [0|1] "" XXX + SG_ ACCResumeBtnInv : 45|1@0+ (1,0) [0|1] "" XXX + SG_ ACCSetBtnInv : 47|1@0+ (1,0) [0|1] "" XXX + SG_ ACCMinusBtn : 48|1@0+ (1,0) [0|1] "" XXX + SG_ TimeGapIncreaseBtn : 49|1@0+ (1,0) [0|1] "" XXX + SG_ TimeGapDecreaseBtn : 50|1@0+ (1,0) [0|1] "" XXX + SG_ ACCOnOffBtn : 59|1@0+ (1,0) [0|1] "" XXX + SG_ ACCResumeBtn : 61|1@0+ (1,0) [0|1] "" XXX + SG_ ACCSetBtn : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 298 EngineData: 8 XXX + SG_ NEW_SIGNAL_1 : 1|10@0+ (1,0) [0|1023] "" XXX + SG_ BrakePressed2 : 2|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 25|2@0+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 33|10@0- (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_3 : 34|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 35|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 36|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 37|1@0+ (1,0) [0|1] "" XXX + SG_ BrakePressed : 38|1@0+ (1,0) [0|1] "" XXX + SG_ EngineRpm : 52|13@0+ (1,0) [0|8000] "" XXX + +BO_ 307 NEW_MSG_133: 8 XXX + SG_ Brake : 14|7@0+ (1,0) [0|127] "" XXX + +BO_ 328 VehicleSpeed1: 8 XXX + SG_ BrakePressure2 : 33|10@0+ (1,0) [0|63] "" XXX + SG_ COUNTER : 37|4@0+ (1,0) [0|15] "" XXX + SG_ VehicleSpeed : 55|16@0+ (0.01,0) [0|65535] "" XXX + +BO_ 336 NEW_MSG_8: 8 XXX + SG_ NEW_SIGNAL_1 : 3|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_2 : 19|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_3 : 35|12@0+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_4 : 51|12@0+ (1,0) [0|4095] "" XXX + +BO_ 359 ACC_Speed: 8 XXX + SG_ ACC_Speed : 0|8@0+ (1,0) [0|255] "km/h" XXX + SG_ GasPedal : 51|12@0- (1,0) [0|255] "" XXX + SG_ GasPressed : 52|1@0+ (1,0) [0|1] "" XXX + +BO_ 384 Accessories_02: 8 XXX + SG_ Park_Assist_State : 42|1@0+ (1,0) [0|1] "" XXX + SG_ StartStop_Inv : 44|1@0+ (1,0) [0|1] "" XXX + +BO_ 465 NEW_MSG_4: 8 XXX + SG_ BrakePressedInv : 3|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 55|16@0+ (1,0) [0|4095] "" XXX + +BO_ 522 Brake_Info: 8 XXX + SG_ NEW_SIGNAL_2 : 1|1@0+ (1,0) [0|1] "" XXX + SG_ COUNTER : 11|4@0+ (1,0) [0|15] "" XXX + SG_ BrakeCmd : 13|1@0+ (1,0) [0|1] "" XXX + SG_ BrakePressure : 17|10@0+ (1,0) [0|255] "" XXX + SG_ BrakePedal : 19|2@0+ (1,0) [0|3] "" XXX + SG_ BrakePedal2 : 33|2@0+ (1,0) [0|3] "" XXX + SG_ CHECKSUM : 39|4@0+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 544 wheelspeed1: 8 BCM + SG_ WhlSpdRR : 39|16@0+ (0.01,-327.68) [0|65535] "" XXX + SG_ WhlSpdLR : 55|16@0+ (0.01,-327.68) [0|65535] "" XXX + +BO_ 565 wheelspeed0: 8 BCM + SG_ WhlSpdRF : 39|16@0+ (0.01,-327.68) [0|65535] "" XXX + SG_ WhlSpdLF : 55|16@0+ (0.01,-327.68) [0|65535] "" XXX + +BO_ 582 PSCM1: 8 PSCM + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ SteeringWheelRateOfChange : 15|8@0+ (1,0) [0|255] "" XXX + SG_ SteeringAngleServo : 23|16@0+ (0.0447,-1464.8) [0|65535] "deg" XXX + SG_ LKATorque : 35|12@0+ (1,-2000) [0|65535] "" XXX + SG_ byte4 : 39|4@0+ (1,0) [0|15] "" XXX + SG_ LKAActive : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 608 FSM1: 8 FSM + SG_ ACC_Distance : 7|8@0+ (1,0) [0|255] "" XXX + +BO_ 609 fromWhere: 8 XXX + SG_ COUNTER : 3|4@0+ (1,0) [0|15] "" XXX + SG_ CHECKSUM : 15|4@0+ (1,0) [0|15] "" XXX + SG_ SteeringAngle : 21|14@0+ (0.1,-1021) [0|65535] "deg" XXX + +BO_ 610 FSM2: 8 FSM + SG_ SET_X_22 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ TrqLim : 23|8@0+ (1,-128) [0|255] "" PSCM + SG_ LKAAngleReq : 29|14@0+ (0.04,-327.68) [0|16383] "" PSCM + SG_ SET_X_02 : 31|2@0+ (1,0) [0|3] "" XXX + SG_ LKASteerDirection : 41|2@0+ (1,0) [0|3] "" PSCM + SG_ SET_X_10 : 47|6@0+ (1,0) [0|63] "" XXX + SG_ Checksum : 55|8@0+ (1,0) [0|255] "" PSCM + SG_ SET_X_A4 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 612 Accessories_03: 8 XXX + SG_ Park_Assist_Button : 60|1@0+ (1,0) [0|1] "" XXX + +BO_ 624 FSM3: 8 FSM + SG_ ACC_Standstill : 0|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Check : 2|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_AccelDecel : 15|8@0+ (1,0) [0|255] "" XXX + SG_ ACC_Some : 17|10@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 47|8@0+ (1,0) [0|255] "" XXX + +BO_ 648 BrakePedal: 8 XXX + SG_ Counter : 0|3@1+ (1,0) [0|6] "" XXX + SG_ BrakePressure : 17|10@0+ (1,0) [0|1023] "" XXX + +BO_ 750 HandBrake: 8 XXX + SG_ Hand_Brake_Button : 33|2@0+ (1,0) [0|3] "" XXX + SG_ Hand_Brake_State : 44|4@0+ (1,0) [0|15] "" XXX + +BO_ 794 FSM4: 8 FSM + SG_ ACC_LeadSpeed : 31|8@0+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_2 : 32|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 47|16@0+ (1,-46090) [0|16383] "" XXX + +BO_ 802 StartStop: 8 XXX + SG_ StartStop : 8|1@0+ (1,0) [0|1] "" XXX + +BO_ 923 Accessories_01: 8 XXX + SG_ NEW_SIGNAL_1 : 15|16@0+ (1,0) [0|65535] "" XXX + SG_ Wipers : 38|2@0+ (1,0) [0|3] "" XXX + +BO_ 1006 Doors: 8 XXX + SG_ DriverDoorClosed : 8|1@0+ (1,0) [0|1] "" XXX + SG_ PassengerDoorClosed : 9|1@0+ (1,0) [0|1] "" XXX + +BO_ 1021 FSM5: 8 FSM + SG_ TSR_Speed : 25|4@1+ (10,0) [0|15] "km/h" XXX + +BO_ 1024 NEW_MSG_400: 8 XXX + SG_ NEW_SIGNAL_1 : 25|8@0+ (1,0) [0|255] "" XXX + +BO_ 1039 MiscCarInfo: 8 XXX + SG_ TurnSignal : 33|2@0+ (1,0) [0|3] "" XXX + +BO_ 1174 Lights: 8 XXX + SG_ High_Beam : 23|1@0+ (1,0) [0|1] "" XXX + +BO_ 1279 PSCM3: 8 PSCM + +BO_ 1830 diagCEMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1838 diagCEMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1840 diagPSCMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1848 diagPSCMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1892 diagFSMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1900 diagFSMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 1939 diagCVMReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +BO_ 1947 diagCVMResp: 8 XXX + SG_ byte03 : 7|32@0+ (1,0) [0|4294967295] "" XXX + SG_ byte47 : 39|32@0+ (1,0) [0|4294967295] "" XXX + +BO_ 2015 diagGlobalReq: 8 XXX + SG_ byte0 : 7|8@0+ (1,0) [0|255] "" XXX + SG_ byte1 : 15|8@0+ (1,0) [0|255] "" XXX + SG_ byte2 : 23|8@0+ (1,0) [0|255] "" XXX + SG_ byte3 : 31|8@0+ (1,0) [0|255] "" XXX + SG_ byte4 : 39|8@0+ (1,0) [0|255] "" XXX + SG_ byte5 : 47|8@0+ (1,0) [0|255] "" XXX + SG_ byte6 : 55|8@0+ (1,0) [0|255] "" XXX + SG_ byte7 : 63|8@0+ (1,0) [0|255] "" XXX + +CM_ SG_ 16 SteeringDirection "0 = CCW, 1=CW (turning left or right of center)"; +CM_ SG_ 16 SteeringRateOfChange "Rate of change? Torque?"; +CM_ SG_ 81 ACCStatus "0=Acc Unavailable, 1=???, 2=Acc Ready, 3,4=???, 6= Acc Active, 7=Acc active tracking object (probably)"; +CM_ SG_ 295 ACCMinusBtnInv "Active zero when button pressed."; +CM_ SG_ 295 TimeGapIncreaseBtnInv "Active zero when button pressed."; +CM_ SG_ 295 TimeGapDecreaseBtnInv "Active zero when button pressed."; +CM_ SG_ 295 ACCOnOffBtnInv "Active zero when button pressed."; +CM_ SG_ 295 ACCResumeBtnInv "Active zero when button pressed."; +CM_ SG_ 295 ACCSetBtnInv "Active zero when button pressed."; +CM_ SG_ 295 ACCMinusBtn "ACC Minus (-) button pressed"; +CM_ SG_ 295 TimeGapIncreaseBtn "Increase the time gap on ACC"; +CM_ SG_ 295 TimeGapDecreaseBtn "Decrease the time gap on ACC"; +CM_ SG_ 295 ACCOnOffBtn "Cruise control on/off button pressed"; +CM_ SG_ 295 ACCResumeBtn "ACC Resume button pressed"; +CM_ SG_ 295 ACCSetBtn "Acc Set button (+) pressed"; +CM_ SG_ 298 NEW_SIGNAL_4 "related to gas pedal"; +CM_ SG_ 298 NEW_SIGNAL_5 "related to ACCStatus"; +CM_ SG_ 298 NEW_SIGNAL_6 "went high at same time as ACCStatus >= 2"; +CM_ SG_ 298 BrakePressed "driver"; +CM_ SG_ 298 EngineRpm "Might be engine rpm. But behaves a bit weird."; +CM_ SG_ 582 byte0 "0=CCW, 1=CW, bit 2,"; +CM_ SG_ 582 SteeringWheelRateOfChange "Some rate of change for steering wheel? Torque?"; +CM_ SG_ 582 byte4 "High nibble"; +CM_ SG_ 582 LKAActive "Bit 1, 1 When LKA Active, Bit 3, 1 When denying?"; +CM_ SG_ 608 ACC_Distance "Seems to track distance, or speed of vehicle in front."; +CM_ SG_ 610 SET_X_22 "0x20 Heartbeat, VEgo <58kph = 0x03, VEgo >65kph = 0x04, 0x05"; +CM_ SG_ 624 ACC_AccelDecel "Might be some acc speed, moved a bit after activating acc"; +CM_ SG_ 624 ACC_Some "Jumps to life after activating ACC, 0 when not active"; +CM_ SG_ 648 Counter "counts 0 to 6"; +CM_ SG_ 1021 TSR_Speed "Traffic Sign Recognition speed"; +CM_ SG_ 1039 TurnSignal "0 = Nothing, 1= Left, 3=Right"; +VAL_ 522 BrakePedal 1 "Not Pressed" 2 "Pressed"; diff --git a/opendbc_repo/opendbc/dbc/vw_meb.dbc b/opendbc_repo/opendbc/dbc/vw_meb.dbc new file mode 100644 index 0000000000..98125aaa69 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/vw_meb.dbc @@ -0,0 +1,3408 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: BAP_Tester BedienDisp_vo BedienSG_hi CGS DDA Gateway Gateway_PAG GurtMikrofon OTA_FC ZR_High ZR_LIMU ZR_MIB_TOP_ab_Gen3 ZR_Standard + + +BO_ 64 Airbag_01: 8 Gateway + SG_ Airbag_01_CRC : 0|8@1+ (1,0) [0|255] "" AWC,BMC_MLBevo,BMS_NV,DCDC_800V_PAG,DCDC_HV,DCDC_HV_02,DCDC_IHEV,FCU_MLBevo_FCEV,Ladegeraet_2,Ladegeraet_Konzern,Sub_Gateway + SG_ Airbag_01_BZ : 8|4@1+ (1,0) [0|15] "" AWC,BMC_MLBevo,BMS_NV,DCDC_800V_PAG,DCDC_HV,DCDC_HV_02,DCDC_IHEV,FCU_MLBevo_FCEV,Ladegeraet_2,Ladegeraet_Konzern,Sub_Gateway + SG_ AB_RGS_Anst : 12|4@1+ (1,0) [0|15] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Front_Crash : 16|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Heck_Crash : 17|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_SF_Crash : 18|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_SB_Crash : 19|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Rollover_Crash : 20|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Crash_Int : 21|3@1+ (1,0) [0|7] "" FCU_MLBevo_FCEV,Sub_Gateway,TME + SG_ AB_Lampe : 24|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Deaktiviert : 25|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_VB_deaktiviert : 26|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Systemfehler : 27|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Diagnose : 28|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Stellgliedtest : 29|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway,TME + SG_ AB_Erh_Auf_VB : 30|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Gurtwarn_VF : 32|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Gurtwarn_VB : 33|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Anzeige_Fussg : 34|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Texte_AKS : 36|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_MKB_gueltig : 39|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_MKB_Anforderung : 40|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Versorgungsspannung : 41|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Deaktivierung_HV : 42|3@1+ (1,0) [0|7] "" AWC,BMC_MLBevo,BMS_NV,DCDC_800V_PAG,DCDC_HV,DCDC_HV_02,DCDC_IHEV,FCU_MLBevo_FCEV,Ladegeraet_2,Ladegeraet_Konzern,Sub_Gateway,TME + SG_ AB_EDR_Trigger : 45|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ AB_Belegung_VF : 47|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ SC_Masterzeit_Offset : 53|2@1+ (5.08,0) [0|15.24] "Unit_Secon" FCU_MLBevo_FCEV,Sub_Gateway + SG_ SC_LowSpeedCrashErkannt : 55|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV,Sub_Gateway + SG_ SC_Masterzeit : 57|7@1+ (0.04,0) [0|5.04] "Unit_Secon" FCU_MLBevo_FCEV,Sub_Gateway + +BO_ 134 LWI_01: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ LWI_Sensorstatus : 12|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ LWI_QBit_Sub_Daten : 13|1@1+ (1,0) [0|1] "" ZR_High + SG_ LWI_MFL_Abschaltung : 14|1@1+ (1,0) [0|1] "" ZR_High + SG_ LWI_QBit_Lenkradwinkel : 15|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ LWI_Lenkradwinkel : 16|13@1+ (0.0843,0) [0|800] "Unit_DegreOfArc" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ LWI_VZ_Lenkradwinkel : 29|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ LWI_VZ_Lenkradw_Geschw : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ LWI_Lenkradw_Geschw : 31|9@1+ (5,0) [0|2500] "Unit_DegreOfArcPerSecon" OTA_FC,ZR_High + SG_ LWI_Sub_Daten : 40|16@1+ (1,0) [0|65535] "" Vector__XXX + +BO_ 159 LH_EPS_03: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_DSR_Status : 12|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_Berechneter_LW : 16|12@1+ (0.15,0) [0|613.95] "Unit_DegreOfArc" XXX + SG_ EPS_BLW_QBit : 30|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_VZ_BLW : 31|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_HCA_Status : 32|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_Lenkmoment : 40|10@1+ (1,0) [0|8] "Unit_centiNewtoMeter" XXX + SG_ EPS_Lenkmoment_QBit : 54|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_VZ_Lenkmoment : 55|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_Lenkungstyp : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 167 Motor_11: 8 Motor_Diesel_MQB + SG_ Motor_11_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ Motor_11_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Soll_Roh : 12|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Ist_Summe : 22|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,SAK_MQB + SG_ MO_Mom_Traegheit_Summe : 32|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Soll_gefiltert : 42|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Schub : 52|9@1+ (1,-509) [-509|0] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Status_Normalbetrieb_01 : 61|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_erste_Ungenauschwelle : 62|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_QBit_Motormomente : 63|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 168 Motor_12: 8 Motor_Diesel_MQB + SG_ Motor_12_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ Motor_12_BZ : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Mom_neg_verfuegbar : 12|9@1+ (1,-509) [-509|0] "Unit_NewtoMeter" Gateway_MQB + SG_ MO_Mom_Begr_stat : 21|9@1+ (1,0) [0|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Begr_dyn : 30|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB + SG_ MO_Momentenintegral_02 : 40|7@1+ (1,0) [0|100] "Unit_PerCent" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Drehzahl_01 : 47|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Drehzahl_01 : 48|16@1+ (0.25,0) [0|16383] "Unit_MinutInver" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,SAK_MQB + +BO_ 173 Getriebe_11: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ GE_MMom_Soll_02 : 12|10@1+ (1,-509) [-509|509] "" Vector__XXX + SG_ GE_MMom_Vorhalt_02 : 22|10@1+ (1,-509) [-509|509] "" Vector__XXX + SG_ GE_Uefkt : 32|10@1+ (0.1,0) [0|102.2] "" Vector__XXX + SG_ GE_Fahrstufe : 42|4@1+ (1,0) [0|15] "" DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ GE_reserv_Fahrstufe : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GE_Schaltablauf : 47|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ GE_Uefkt_unplausibel : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GE_MMom_Status_02 : 50|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ GE_Status_Kraftschluss : 53|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ GE_MMom_Status : 56|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ GE_Freig_MMom_Vorhalt : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GE_Verbot_Ausblendung : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GE_Zielgang : 60|4@1+ (1,0) [0|15] "" OTA_FC,ZR_High + +BO_ 184 EM1_HYB_13: 8 Gateway + SG_ EM1_Freigabe_Info_WFS : 12|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_Sperr_Info_WFS : 13|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_AR_aktiv : 14|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_Eta_Sys : 15|9@1+ (0.2,0) [0|101.8] "Unit_PerCent" Sub_Gateway + SG_ EM1_IstStrom : 24|11@1+ (1,-1023) [-1023|1022] "Unit_Amper" Sub_Gateway + SG_ EM1_Fehler_ElAntriebFreilauf_Anf : 35|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_Abregelung_Temperatur : 36|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_AnlernenElMotor_Anf : 43|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_Moment_HVVerbraucher : 44|10@1+ (1,-511) [-511|511] "Unit_NewtoMeter" Sub_Gateway + SG_ EM1_Freigabe_Verfallsinfo_WFS : 55|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ EM1_Parken_WFS_Status : 56|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ EM1_HV_betriebsbereit : 58|1@1+ (1,0) [0|1] "" Sub_Gateway + +BO_ 190 MEB_HVEM_01: 48 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CNT : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Engine_RPM_Max : 12|14@1+ (2,-9658) [0|15] "RPM" XXX + SG_ Engine_RPM_Min : 26|14@1+ (2,-10300) [0|63] "RPM" XXX + SG_ In_Motion_04 : 48|3@1+ (1,0) [0|7] "" XXX + SG_ In_Motion_03 : 52|1@0+ (1,0) [0|1] "" XXX + SG_ In_Motion_02 : 54|1@0+ (1,0) [0|1] "" XXX + SG_ Engine_Power : 56|12@1+ (0.5,-1023) [0|255] "kW" XXX + SG_ In_Motion : 68|1@1+ (1,0) [0|3] "" XXX + SG_ Standstill : 71|1@0+ (1,0) [0|1] "" XXX + SG_ Unknown_04 : 72|10@1+ (1,0) [0|255] "" XXX + SG_ Battery_Voltage : 86|12@1+ (0.2,0) [0|3] "Volt" XXX + SG_ Unknown_01 : 100|9@1+ (1,0) [0|7] "" XXX + SG_ Battery_Voltage_02 : 113|11@1+ (0.24,0) [0|127] "Volt" XXX + SG_ Engine_Status : 296|2@1+ (1,0) [0|3] "" XXX + SG_ Inactive : 300|1@0+ (1,0) [0|1] "" XXX + SG_ Inactive_02 : 303|1@0+ (1,0) [0|1] "" XXX + +BO_ 192 EM1_01: 32 XXX + SG_ Schubbetrieb : 79|1@0+ (1,0) [0|1] "" XXX + +BO_ 219 AWV_03: 48 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ FCW_Active : 64|1@0+ (1,0) [0|1] "" XXX + SG_ Pre_Brake_Fill : 76|1@0+ (1,0) [0|1] "" XXX + +BO_ 247 MEB_HVEM_02: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CNT : 8|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_3 : 44|10@1+ (1,0) [0|7] "" XXX + SG_ NEW_SIGNAL_2 : 54|7@1+ (1,0) [0|3] "" XXX + +BO_ 252 ESC_51: 48 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ AEB_Breaking_01 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ AEB_Breaking_02 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ Accelerator_Higher_Speed : 40|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_Pressure : 42|9@1+ (0.195,0) [0|100] "Unit_Percent" XXX + SG_ HL_Radgeschw : 64|16@1+ (0.0075,0) [0|491.5125] "Unit_KilometerPerHour" XXX + SG_ HR_Radgeschw : 80|16@1+ (0.0075,0) [0|491.5125] "Unit_KilometerPerHour" XXX + SG_ VL_Radgeschw : 96|16@1+ (0.0075,0) [0|491.5125] "Unit_KilometerPerHour" XXX + SG_ VR_Radgeschw : 112|16@1+ (0.0075,0) [0|491.5125] "Unit_KilometerPerHour" XXX + SG_ HL_Brake_Pressure : 152|8@1+ (1,0) [0|100] "" XXX + SG_ HR_Brake_Pressure : 160|8@1+ (1,0) [0|100] "" XXX + SG_ VL_Brake_Pressure : 168|8@1+ (1,0) [0|100] "" XXX + SG_ VR_Brake_Pressure : 176|8@1+ (1,0) [0|100] "" XXX + SG_ Steering_Wheel_CW : 184|8@1+ (1.67,0) [0|255] "" XXX + SG_ Steering_Wheel_CCW : 192|8@1+ (1.67,0) [0|255] "" XXX + +BO_ 253 ESP_21: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BR_Eingriffsmoment : 12|10@1+ (1,-509) [-509|509] "" Vector__XXX + SG_ ESP_Diagnose : 23|1@1+ (1,0) [0|1] "" ZR_High + SG_ ESC_v_Signal_Qualifier_High_Low : 24|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ ESP_Vorsteuerung : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ OBD_Schlechtweg : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ OBD_QBit_Schlechtweg : 31|1@1+ (1,0) [0|1] "" ZR_High + SG_ ESP_v_Signal : 32|16@1+ (0.01,0) [0|655.32] "Unit_KiloMeterPerHour" BedienSG_hi,DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ASR_Tastung_passiv : 48|1@1+ (1,0) [0|1] "" OTA_FC + SG_ ESP_Tastung_passiv : 49|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ ESP_Systemstatus : 50|1@1+ (1,0) [0|1] "" OTA_FC + SG_ ASR_Schalteingriff : 51|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_QBit_v_Signal : 55|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ABS_Bremsung : 56|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ ASR_Anf : 57|1@1+ (1,0) [0|1] "" ZR_High + SG_ MSR_Anf : 58|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ EBV_Eingriff : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EDS_Eingriff : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingriff : 61|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ ESP_ASP : 62|1@1+ (1,0) [0|1] "" ZR_High + SG_ ESC_Neutralschaltung : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 258 ESC_50: 48 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Lateral_Accel : 16|8@1+ (0.15,-18.9) [0|255] "Unit_MeterPerSquareSecond" XXX + SG_ Longitudinal_Accel : 24|10@1+ (0.03125,-16) [0|255] "Unit_MeterPerSquareSecond" XXX + SG_ Yaw_Rate : 40|14@1+ (0.01,0) [0|16383] "Unit_DegreePerSecond" XXX + SG_ Yaw_Rate_Sign : 54|1@0+ (1,0) [0|1] "" XXX + SG_ Regen_Braking : 123|1@1+ (1,0) [0|7] "" XXX + SG_ Standstill : 171|1@0+ (1,0) [0|1] "" XXX + SG_ Longitudinal_Speed : 181|10@1+ (0.25,0) [0|255] "Unit_KilometerPerHour" XXX + +BO_ 261 VMM_01: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CNT : 8|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 13|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 40|2@1+ (1,0) [0|3] "" XXX + SG_ Brake : 53|7@1+ (1,0) [0|3] "" XXX + +BO_ 267 Motor_51: 32 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Accel_Pedal_Pressure : 12|9@1+ (0.4,0) [0|255] "" XXX + SG_ Accel_Low_Pressed_Support : 21|1@1+ (1,0) [0|7] "" XXX + SG_ TSK_Status : 88|3@1+ (1,0) [0|7] "" XXX + SG_ TSK_Limiter_ausgewaehlt : 95|1@1+ (1,0) [0|3] "" XXX + +BO_ 278 ESP_10: 8 Gateway_MQB + SG_ ESP_10_CRC : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_10_BZ : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_VL : 12|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_VR : 13|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_HL : 14|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_HR : 15|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_VL : 16|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_VR : 26|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_HL : 36|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_HR : 46|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VL_Fahrtrichtung : 56|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VR_Fahrtrichtung : 58|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HL_Fahrtrichtung : 60|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HR_Fahrtrichtung : 62|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 285 LH_EPS_02: 8 Gateway_D4C7 + SG_ EPS_02_CRC : 0|8@1+ (1,0) [0|255] "" SCU_D4 + SG_ EPS_02_BZ : 8|4@1+ (1,0) [0|15] "" SCU_D4 + SG_ EPS_Notlauf : 12|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ EPS_Lastinfo : 16|8@1+ (1,0) [0|253] "Unit_Amper" Vector__XXX + SG_ EPS_Unterstuetzungsleistung : 24|8@1+ (0.5,0) [0|100] "Unit_PerCent" SCU_D4 + SG_ EPS_Drehzahlreserve : 32|7@1+ (10,0) [0|1000] "Unit_DegreOfArcPerSecon" SCU_D4 + SG_ EPS_VZ_Drehzahlreserve : 39|1@1+ (1,0) [0|1] "" SCU_D4 + SG_ EPS_Leistungsanforderung : 40|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 294 HCA_01: 8 Frontsensorik + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HCA_01_Vib_Freq : 12|4@1+ (1,15) [18|30] "Unit_Hertz" Vector__XXX + SG_ HCA_01_LM_Offset : 16|9@1+ (1,0) [0|511] "Unit_centiNewtoMeter" Vector__XXX + SG_ EA_ACC_Sollstatus : 25|2@1+ (1,0) [0|3] "" Frontradar + SG_ EA_Ruckprofil : 27|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ HCA_01_Enable : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_LM_OffSign : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_Available : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_Standby : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_Request : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_Vib_Amp : 36|4@1+ (0.2,0) [0|3] "Unit_NewtoMeter" Vector__XXX + SG_ EA_Ruckfreigabe : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EA_ACC_Wunschgeschwindigkeit : 41|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" Frontradar + +BO_ 299 GRA_ACC_01: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ GRA_Hauptschalter : 12|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Abbrechen : 13|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Typ_Hauptschalter : 14|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Limiter : 15|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Tip_Setzen : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Tip_Hoch : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Tip_Runter : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Tip_Wiederaufnahme : 19|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Verstellung_Zeitluecke : 20|2@1+ (1,0) [0|3] "" ZR_High + SG_ GRA_Codierung : 22|2@1+ (1,0) [0|3] "" ZR_High + SG_ GRA_Fehler : 24|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_LIM_Taste_verfuegbar : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_Tip_Stufe_2 : 26|1@1+ (1,0) [0|1] "" ZR_High + SG_ GRA_ButtonTypeInfo : 27|3@1+ (1,0) [0|7] "" ZR_High + SG_ GRA_TravelAssist : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GRA_reserveByte4 : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GRA_reserveByte5 : 32|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ GRA_reserveByte6 : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ GRA_reserveByte7 : 48|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ GRA_reserveByte8 : 56|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 312 IPA_01: 32 XXX + +BO_ 313 VMM_02: 32 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Brake_Pressed_1 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_Pressed_2 : 27|1@0+ (1,0) [0|1] "" XXX + SG_ AEB_Active : 31|1@0+ (1,0) [0|1] "" XXX + SG_ ESP_Hold : 35|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_Pressed_3 : 48|1@0+ (1,0) [0|1] "" XXX + SG_ FCW_Active : 56|1@1+ (1,0) [0|1] "" XXX + SG_ Brake_Pressure : 76|11@1+ (1,0) [0|100] "" XXX + +BO_ 317 QFK_01: 32 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_5 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_9 : 14|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_8 : 16|1@0+ (1,0) [0|1] "" XXX + SG_ LatCon_HCA_Accept : 17|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_2 : 19|1@0+ (1,0) [0|1] "" XXX + SG_ LatCon_HCA_Status : 20|3@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 23|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_10 : 24|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 30|3@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_7 : 34|3@0+ (1,0) [0|1] "" XXX + SG_ Steering_Angle_VZ : 36|1@0+ (1,0) [0|1] "" XXX + SG_ Curvature : 40|15@1+ (6.7e-06,0) [0|65535] "" XXX + SG_ Curvature_VZ : 55|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 56|7@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_4 : 63|1@0+ (1,0) [0|1] "" XXX + SG_ Steering_Angle : 76|17@1+ (0.00906,0) [0|32767] "" XXX + +BO_ 319 PreCrash_02: 8 Gateway + SG_ PreCrash_02_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ PreCrash_02_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PreCrash_Charisma_FahrPr : 12|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PreCrash_Charisma_Status : 16|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ PreCrash_Schiebedach_schliessen : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PreCrash_Fenster_schliessen : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PreCrash_Blinken : 20|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ SC_PreSense_FCWP : 23|1@1+ (1,0) [0|1] "" NightVision + SG_ PreCrash_Tueren_Verriegeln : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PreCrash_Anforderung_AFR : 26|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ SC_PreCrash_LED : 29|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ PreCrash_FS_Pneumatik_ansteuern : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PreCrash_BFS_Pneumatik_ansteuern : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PreCrash_Fo_Pneumatik_ansteuern : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PreCrash_FS_Sitzlehne_verfahren : 34|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ PreCrash_BFS_Sitzlehne_verfahren : 37|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ PreCrash_Fo_Sitzlehne_verfahren : 40|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ PreCrash_FS_KSV_verfahren : 43|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PreCrash_BFS_KSV_verfahren : 47|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PreCrash_Fo_KSV_verfahren : 51|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ SC_PreCrash_Warnung : 56|4@1+ (1,0) [0|15] "" NightVision + SG_ SC_PreCrash_Texte : 60|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 332 Motor_54: 32 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Accelerator_Pressure : 175|8@0+ (0.391,-14.467) [0|100] "Unit_Percent" XXX + +BO_ 333 ACC_18: 32 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_limitierte_Anfahrdyn : 12|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_nachtr_Stopp_Anf : 13|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_DynErhoehung : 14|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Freilaufstrategie_TSK : 15|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_zul_Regelabw_unten : 16|6@1+ (0.024,0) [0|1.512] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_StartStopp_Info : 22|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Sollbeschleunigung_02 : 24|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_zul_Regelabw_oben : 35|5@1+ (0.0625,0) [0|1.9375] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_neg_Sollbeschl_Grad_02 : 40|8@1+ (0.05,0) [0|12.75] "Unit_MeterPerCubicSecon" XXX + SG_ ACC_pos_Sollbeschl_Grad_02 : 48|8@1+ (0.05,0) [0|12.75] "Unit_MeterPerCubicSecon" XXX + SG_ ACC_Anfahren : 56|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Anhalten : 57|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ : 58|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Status_ACC : 60|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Minimale_Bremsung : 63|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Anhalteweg : 64|11@1+ (0.01,0) [0|2046] "" XXX + SG_ ACC_Anforderung_HMS : 77|3@1+ (1,0) [0|7] "" XXX + SG_ SET_ME_0XFE : 80|8@1+ (1,0) [0|255] "" XXX + SG_ ACC_AKTIV_regelt : 90|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_0X1 : 92|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_0X9 : 232|4@1+ (1,0) [0|15] "" XXX + SG_ Speed : 236|11@1+ (0.1,0) [0|15] "" XXX + SG_ Accel_Boost : 248|6@1+ (1,0) [0|3] "" XXX + SG_ Reversing : 254|1@0+ (1,0) [0|1] "" XXX + +BO_ 339 MSG_HYB_30: 8 Gateway + SG_ MSG_HYB_30_CRC : 0|8@1+ (1,0) [0|255] "" Ladegeraet_Konzern + SG_ MSG_HYB_30_BZ : 8|4@1+ (1,0) [0|15] "" Ladegeraet_Konzern + SG_ MO_HVEM_Eskalation : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_ErwGrenzen_Anf : 13|1@1+ (1,0) [0|1] "" BMC_MLBevo + SG_ MO_Fehler_Notentladung_Anf : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_HVEM_MaxLeistung : 15|9@1+ (50,0) [0|25450] "Unit_Watt" Vector__XXX + SG_ MO_HVK_EmIstzustand : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ MO_HVK_AntriebFehlerstatus : 37|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_MVK_Bordnetz_Anf : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_HVK_AntriebZustand : 41|3@1+ (1,0) [0|7] "" TME + SG_ MO_HVK_EmFehlerstatus : 44|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_MVK_AntriebFehlerstatus : 47|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_MVK_AntriebZustand : 50|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_MVK_EmFehlerstatus : 53|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_MVK_EmIstzustand : 56|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 387 MEB_Camera_01: 64 XXX + SG_ NEW_SIGNAL_1 : 191|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 200|9@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 209|9@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_9 : 218|6@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_10 : 224|8@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_4 : 232|9@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_5 : 241|9@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_8 : 250|6@1+ (1,0) [0|63] "" XXX + SG_ Lane_Center_Offset : 256|12@1+ (0.001,-2.5) [0|255] "Unit_Meter" XXX + SG_ NEW_SIGNAL_6 : 268|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_7 : 280|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_11 : 292|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_12 : 304|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_13 : 320|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_14 : 332|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_15 : 344|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_16 : 356|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_17 : 368|10@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_18 : 384|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_19 : 396|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_20 : 408|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_21 : 420|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_22 : 432|5@1+ (1,0) [0|31] "" XXX + SG_ NEW_SIGNAL_23 : 448|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_24 : 460|12@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_25 : 472|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_26 : 484|12@1+ (1,0) [0|15] "" XXX + +BO_ 420 EA_01: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ EA_Parken_beibehalten_HMS : 12|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EA_Warnruckprofil : 28|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ EA_eCall_Anf : 31|2@1+ (1,0) [0|3] "" ZR_High + SG_ EA_Funktionsstatus : 40|4@1+ (1,0) [0|15] "" ZR_High + SG_ EA_Gurtstraffer_Anf : 44|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EA_Anforderung_HMS : 48|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ EA_Sollbeschleunigung : 53|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" Vector__XXX + +BO_ 496 EA_02: 8 Gateway + SG_ EA_02_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ EA_02_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ EA_Texte : 12|4@1+ (1,0) [0|15] "" ZR_High + SG_ ACF_Lampe_Hands_Off : 16|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EA_Infotainment_Anf : 22|2@1+ (1,0) [0|3] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ EA_Tueren_Anf : 24|1@1+ (1,0) [0|1] "" ZR_High + SG_ EA_Innenraumlicht_Anf : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ zFAS_Warnblinken : 26|2@1+ (1,0) [0|3] "" ZR_High + SG_ STP_Primaeranz : 28|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ EA_Bremslichtblinken : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EA_Blinken : 32|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ EA_Unknown : 60|3@0+ (1,0) [0|7] "" XXX + +BO_ 517 SAM_01: 8 XXX + SG_ Brake_Light : 36|1@0+ (1,0) [0|1] "" XXX + SG_ Left_Blinker : 37|1@0+ (1,0) [0|1] "" XXX + SG_ Right_Blinker : 38|1@0+ (1,0) [0|1] "" XXX + +BO_ 518 Parken_01: 24 XXX + SG_ CHK : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CNT : 8|4@1+ (1,0) [0|15] "" XXX + SG_ AEB_Active : 16|1@0+ (1,0) [0|1] "" XXX + +BO_ 522 EML_06: 64 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Yaw_Rate_VZ : 33|1@1+ (1,0) [0|1] "" XXX + SG_ Yaw_Rate : 200|16@1+ (0.007,-229.34) [0|255] "" XXX + +BO_ 564 MEB_Camera_02: 64 XXX + SG_ NEW_SIGNAL_1 : 12|6@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_2 : 18|6@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_3 : 24|6@1+ (1,0) [0|63] "" XXX + SG_ NEW_SIGNAL_4 : 30|6@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_7 : 178|13@1+ (1,0) [0|127] "" XXX + SG_ NEW_SIGNAL_6 : 192|12@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_8 : 286|9@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_5 : 295|9@1+ (1,0) [0|255] "" XXX + +BO_ 588 MEB_Side_Assist_01: 16 XXX + SG_ Blind_Spot_Right : 12|7@1+ (1,0) [0|15] "" XXX + SG_ Blind_Spot_Left : 19|7@1+ (1,0) [0|15] "" XXX + SG_ Blind_Spot_Info_Right : 26|1@0+ (1,0) [0|1] "" XXX + SG_ Blind_Spot_Warn_Right : 27|1@0+ (1,0) [0|1] "" XXX + SG_ Blind_Spot_Info_Left : 29|1@0+ (1,0) [0|1] "" XXX + SG_ Blind_Spot_Warn_Left : 30|1@0+ (1,0) [0|1] "" XXX + SG_ Lower_Speed_01 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ Higher_Speed_01 : 33|1@0+ (1,0) [0|1] "" XXX + SG_ Higher_Speed_02 : 83|1@0+ (1,0) [0|1] "" XXX + SG_ Lower_Speed_02 : 84|1@0+ (1,0) [0|1] "" XXX + SG_ Standstill : 86|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 98|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_6 : 119|1@0+ (1,0) [0|1] "" XXX + +BO_ 589 MEB_Side_Assist_02: 64 XXX + SG_ Unknown_01 : 100|3@0+ (1,0) [0|7] "" XXX + SG_ Unknown_02 : 108|3@0+ (1,0) [0|7] "" XXX + +BO_ 591 MEB_Distance_01: 64 XXX + SG_ Unknown_01 : 12|1@0+ (1,0) [0|1] "" XXX + SG_ Distance_Status : 13|2@1+ (1,0) [0|3] "" XXX + SG_ Same_Lane_01_ObjectID : 16|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX + SG_ Left_Lane_01_ObjectID : 22|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX + SG_ Right_Lane_01_ObjectID : 28|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX + SG_ Same_Lane_02_ObjectID : 34|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX + SG_ Left_Lane_02_ObjectID : 40|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX + SG_ Right_Lane_02_ObjectID : 46|6@1+ (1,0) [0|63] "Unit_ObjectID" XXX + SG_ Unknown_02 : 52|2@1+ (1,0) [0|3] "" XXX + SG_ Unknown_03 : 54|10@1+ (1,0) [0|3] "" XXX + SG_ Same_Lane_01_Long_Distance : 64|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX + SG_ Same_Lane_01_Lat_Distance : 76|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX + SG_ Same_Lane_01_Rel_Velo : 86|10@1+ (0.25,-128) [-100|100] "Unit_MeterPerSecond" XXX + SG_ Left_Lane_01_Long_Distance : 96|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX + SG_ Left_Lane_01_Lat_Distance : 108|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX + SG_ Left_Lane_01_Rel_Velo : 118|10@1+ (0.25,-128) [-100|100] "Unit_MeterPerSecond" XXX + SG_ Right_Lane_01_Long_Distance : 128|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX + SG_ Right_Lane_01_Lat_Distance : 140|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX + SG_ Right_Lane_01_Rel_Velo : 150|10@1+ (0.25,-128) [-100|100] "Unit_MeterPerSecond" XXX + SG_ Same_Lane_02_Long_Distance : 160|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX + SG_ Same_Lane_02_Lat_Distance : 172|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX + SG_ Same_Lane_02_Rel_Velo : 182|10@1+ (0.25,-128) [-100|100] "Unit_MeterPerSecond" XXX + SG_ Left_Lane_02_Long_Distance : 192|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX + SG_ Left_Lane_02_Lat_Distance : 204|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX + SG_ Left_Lane_02_Rel_Velo : 214|10@1+ (0.25,-128) [-100|100] "Unit_MeterPerSecond" XXX + SG_ Right_Lane_02_Long_Distance : 224|12@1+ (0.07,-6) [0|300] "Unit_Meter" XXX + SG_ Right_Lane_02_Lat_Distance : 236|10@1+ (0.065,-33.28) [-50|50] "Unit_Meter" XXX + SG_ Right_Lane_02_Rel_Velo : 246|10@1+ (0.25,-128) [-100|100] "Unit_MeterPerSecond" XXX + SG_ Unknown_04 : 256|8@1+ (1,-128) [0|31] "" XXX + SG_ Unknown_05 : 264|6@1+ (1,-15) [0|31] "" XXX + SG_ Unknown_06 : 270|6@1+ (1,0) [0|127] "" XXX + SG_ Unknown_07 : 277|6@1+ (1,0) [0|7] "" XXX + SG_ Unknown_08 : 284|6@1+ (1,0) [0|1] "" XXX + +BO_ 605 KLR_01: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ KLR_Fehler : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KLR_ResponseError : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KLR_Lokalaktiv : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KLR_Fehler_Codierung : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KLR_Touchintensitaet_1 : 16|8@1+ (1,0) [0|250] "Unit_None" Vector__XXX + SG_ KLR_Touchintensitaet_2 : 24|8@1+ (1,0) [0|250] "Unit_None" Vector__XXX + SG_ KLR_Touchintensitaet_3 : 32|8@1+ (1,0) [0|250] "Unit_None" Vector__XXX + SG_ KLR_Touchauswertung : 40|4@1+ (1,0) [0|15] "" ZR_High + +BO_ 619 TA_01: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Travel_Assist_Status : 13|3@1+ (1,0) [0|3] "" XXX + SG_ Travel_Assist_Request : 19|3@1+ (1,0) [0|7] "" XXX + SG_ Travel_Assist_Available : 23|1@1+ (1,0) [0|1] "" XXX + +BO_ 695 RCTA_01: 8 XXX + SG_ RCTA_01_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ RCTA_01_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 706 Motor_41: 8 Gateway + SG_ MO_Anzeige_StSt_Text : 12|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MO_Anzeige_StSt_Symbol : 16|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_ADR_Status : 19|2@1+ (1,0) [0|3] "" ZR_High + SG_ MO_AGA_Sound_Texte : 21|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_Anzeige_FMAus_Text : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Fehler_MSpG : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PEA_Texte : 25|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ TSK_Ueberstimmt_vMax_FahrerInfo : 28|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_Avus_Motorschutz : 30|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_Rekuperationsstufe : 32|3@1+ (1,0) [0|7] "" OTA_FC + SG_ TSK_Einheit_vMax_FahrerInfo : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TSK_Status_vMax_FahrerInfo : 36|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_Red_Fahrleistung : 38|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_Anz_Kuehlerluefter : 47|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_im_Leerlauf : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Enable_Oeldr_Motor : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_OelMessung_Dauer : 52|4@1+ (15,15) [15|225] "Unit_Secon" Vector__XXX + SG_ TSK_vMax_FahrerInfo : 56|8@1+ (1,15) [16|270] "" Vector__XXX + +BO_ 768 MEB_ACC_01: 48 XXX + SG_ ACC_Tempolimit : 64|5@1+ (1,0) [0|31] "" OTA_FC + SG_ ACC_Wunschgeschw_Farbe : 69|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ACC_Warnung_Verkehrszeichen_1 : 70|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ACA_Querfuehrung : 71|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ Unknown_02 : 73|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Regelung_AIO : 75|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ ACC_Wunschgeschw_02 : 76|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" Vector__XXX + SG_ ACC_Abstandsindex_02 : 86|10@1+ (1,0) [1|1021] "" Vector__XXX + SG_ ACC_Display_Prio : 96|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ACC_rel_Objekt_Zusatzanz : 98|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ACC_Gesetzte_Zeitluecke : 101|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ ACC_Optischer_Fahrerhinweis : 104|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ACC_Warnhinweis : 105|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ACC_EGO_Fahrzeug : 106|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ ACC_Relevantes_Objekt_02 : 109|2@1+ (1,0) [0|3] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ ACC_Wunschgeschw_erreicht : 112|1@1+ (1,0) [0|1] "" OTA_FC + SG_ ACC_Anzeige_Zeitluecke : 113|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ACC_Texte_Primaeranz_02 : 114|6@1+ (1,0) [0|63] "" Vector__XXX + SG_ ACC_Texte_Zusatzanz_02 : 120|6@1+ (1,0) [0|63] "" Vector__XXX + SG_ STA_Primaeranz : 126|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ SET_ME_0X3FF : 140|10@1+ (1,0) [0|15] "" XXX + SG_ Heartbeat : 150|9@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_0XFFFF : 160|16@1+ (1,0) [0|65535] "" XXX + SG_ ACC_Enabled : 186|1@0+ (1,0) [0|1] "" XXX + SG_ Zeitluecke_Farbe : 189|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_0X1 : 199|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Status_ACC : 208|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Akustischer_Fahrerhinweis : 211|2@1+ (1,0) [0|1] "" XXX + SG_ Unknown_08 : 224|1@0+ (1,0) [0|1] "" XXX + SG_ Unknown_01 : 225|1@0+ (1,0) [0|1] "" XXX + SG_ Unknown_06 : 226|1@0+ (1,0) [0|1] "" XXX + SG_ Unknown_07 : 228|1@0+ (1,0) [0|1] "" XXX + SG_ SET_ME_0X7FFF : 240|16@1+ (1,0) [0|65535] "" XXX + SG_ Unknown_09 : 262|1@0+ (1,0) [0|3] "" XXX + SG_ Lead_Type_Detected : 265|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Standby_Override : 266|1@0+ (1,0) [0|1] "" XXX + SG_ Street_Color : 267|1@0+ (1,0) [0|1] "" XXX + SG_ ACC_Limiter_Mode : 268|1@0+ (1,0) [0|1] "" XXX + SG_ Lead_Brightness : 269|4@1+ (1,0) [0|7] "" XXX + SG_ SET_ME_0X6A : 273|8@1+ (1,0) [0|7] "" XXX + SG_ Lead_Type : 287|3@1+ (1,0) [0|3] "" XXX + SG_ Lead_Distance : 290|10@1+ (0.2,0) [0|7] "Unit_Meter" XXX + SG_ ACC_Events : 332|4@0+ (1,0) [0|3] "Unit_Meter" XXX + SG_ Zeitluecke_1 : 334|9@1+ (0.171,0) [0|100] "Unit_Meter" XXX + SG_ Zeitluecke_2 : 344|9@1+ (0.171,0) [0|100] "Unit_Meter" XXX + SG_ Zeitluecke_3 : 354|9@1+ (0.171,0) [0|100] "Unit_Meter" XXX + SG_ Zeitluecke_4 : 364|9@1+ (0.171,0) [0|100] "Unit_Meter" XXX + SG_ Zeitluecke_5 : 374|9@1+ (0.171,0) [0|100] "Unit_Meter" XXX + +BO_ 771 HCA_03: 24 XXX + SG_ RequestStatus : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Power : 16|8@1+ (0.4,0) [0.0|100.0] "percent" XXX + SG_ Curvature : 24|15@1+ (6.7e-06,0) [0|0.219] "Unit_rad/m" XXX + SG_ Curvature_VZ : 39|1@1+ (1,0) [0|1] "" XXX + SG_ Unknown_01 : 53|1@0+ (1,0) [0|1] "" XXX + SG_ Vibration : 56|1@0+ (1,0) [0|1] "" XXX + SG_ HighSendRate : 66|1@1+ (1,0) [0|1] "" XXX + +BO_ 792 MEB_Camera_03: 8 XXX + +BO_ 795 ESP_24: 8 Gateway + SG_ ESP_Lampe : 12|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ABS_Lampe : 13|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ BK_Lampe_02 : 14|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ TC_Lampe : 16|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ESP_m_Raddrehz : 17|15@1+ (0.002,0) [0|65.278] "Unit_Hertz" Sub_Gateway + SG_ ESP_Textanzeigen_03 : 32|5@1+ (1,0) [0|31] "" Sub_Gateway + SG_ ESP_Meldungen : 37|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ ESP_Wegimp_VA : 40|11@1+ (1,0) [0|2047] "" Sub_Gateway + SG_ ESP_Fehlerstatus_Wegimp : 51|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ESP_Wegimp_Ueberlauf : 52|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ESP_QBit_Wegimp_VA : 53|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ESP_HDC_Geschw_Farbe : 54|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ESP_Off_Lampe : 55|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ ESP_HDC_Regelgeschw : 56|7@1+ (0.32,0) [0.32|39.68] "Unit_KiloMeterPerHour" Sub_Gateway + SG_ ESP_BKV_Warnung : 63|1@1+ (1,0) [0|1] "" Sub_Gateway + +BO_ 817 MFL_01: 8 Gateway + SG_ MFL_Zaehler : 0|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Toggle : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MFL_Lokalaktiv : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MFL_M_Taste : 6|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Paddle_Verbau : 7|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Tastencode_1 : 8|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ MFL_Tastencode_2 : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ MFL_Eventcode_1 : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Eventcode_2 : 28|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Marke : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Variante : 36|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Dummy_0_Signal_1 : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ MFL_Tip_Down : 48|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Tip_Up : 49|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_SatModul_links_Err : 50|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_SatModul_rechts_Err : 51|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Dummy_0_Signal_2 : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MFL_Dummy_0_Signal_3 : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MFL_LR_HZG_Status : 54|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_LR_HZG_Err : 55|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Signalhorn : 56|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ MFL_Signalhorn_Err : 57|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Tip_links_Err : 58|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Tip_rechts_Err : 59|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Taste_links_Err : 60|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Taste_rechts_Err : 61|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_ECU_Err : 62|1@1+ (1,0) [0|1] "" ZR_High + SG_ MFL_Response_Err : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 850 Parken_SM_03: 8 Gateway + SG_ Parken_SM_03_MUX M : 0|3@1+ (1,0) [0|7] "" DDA + SG_ Parken_SM_03_Traj_Trans_ID_00 m0 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P1_Pos_X m0 : 7|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P1_Pos_Y m0 : 20|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P1_Tangent m0 : 33|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_Traj_P2_Pos_X m0 : 43|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_SM_03_Traj_Trans_ID_01 m1 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P2_Pos_Y m1 : 7|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P2_Tangent m1 : 20|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_Traj_P3_Pos_X m1 : 30|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P3_Pos_Y m1 : 43|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_SM_03_Traj_Trans_ID_02 m2 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P3_Tangent m2 : 7|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_Traj_P4_Pos_X m2 : 17|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P4_Pos_Y m2 : 30|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P4_Tangent m2 : 43|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_SM_03_Traj_Trans_ID_03 m3 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P5_Pos_X m3 : 7|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P5_Pos_Y m3 : 20|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P5_Tangent m3 : 33|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_Traj_P6_Pos_X m3 : 43|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_SM_03_Traj_Trans_ID_04 m4 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P6_Pos_Y m4 : 7|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P6_Tangent m4 : 20|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_Traj_P7_Pos_X m4 : 30|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P7_Pos_Y m4 : 43|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_SM_03_Traj_Trans_ID_05 m5 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P7_Tangent m5 : 7|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_Traj_P8_Pos_X m5 : 17|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P8_Pos_Y m5 : 30|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P8_Tangent m5 : 43|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + SG_ Parken_SM_03_Traj_Trans_ID_06 m6 : 3|4@1+ (1,0) [0|15] "" DDA + SG_ Parken_Traj_P9_Pos_X m6 : 7|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P9_Pos_Y m6 : 20|13@1+ (0.5,-2047.5) [-2047.5|2048] "Unit_Centimeter" DDA + SG_ Parken_Traj_P9_Tangent m6 : 33|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" DDA + +BO_ 869 NVEM_05: 8 Gateway + SG_ NVEM_05_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NVEM_05_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ NVEM_Pilot_Info : 12|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ NVEM_P_Generator_Status : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BEM_P_Generator : 16|8@1+ (50,0) [0|12700] "Unit_Watt" Vector__XXX + SG_ BEM_n_LLA : 24|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BEM_Anf_KL : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BEM_StartStopp_Info : 30|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BEM_DFM : 32|5@1+ (3.225,0.025) [0.025|100] "" Vector__XXX + SG_ BEM_Batt_Ab : 38|1@1+ (1,0) [0|1] "" DCDC_800V_PAG,DCDC_IHEV + SG_ BEM_Hybrid_Info : 44|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ NVEM_Red_KL : 46|2@1+ (1,0) [0|3] "" TME + SG_ NVEM_Freilauf_Info : 48|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BEM_HYB_DC_uSollLV : 50|6@1+ (0.1,10.6) [10.6|16] "Unit_Volt" DCDC_800V_PAG,DCDC_HV,LE_MLBevo + SG_ BEM_HYB_DC_uMinLV : 56|8@1+ (0.1,0) [0|25.3] "Unit_Volt" Vector__XXX + +BO_ 870 Blinkmodi_02: 8 Gateway + SG_ BM_ZV_auf : 12|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_ZV_zu : 13|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_DWA_ein : 14|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_DWA_Alarm : 15|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Crash : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Panik : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Not_Bremsung : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_GDO : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BM_Warnblinken : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Taxi_Notalarm : 21|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Telematik : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_links : 23|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_rechts : 24|1@1+ (1,0) [0|1] "" ZR_High + SG_ Blinken_li_Fzg_Takt : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ Blinken_re_Fzg_Takt : 26|1@1+ (1,0) [0|1] "" ZR_High + SG_ Blinken_li_Kombi_Takt : 27|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ Blinken_re_Kombi_Takt : 28|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ BM_NBA_n_codiert_n_aktiv : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BM_NBA_Status : 30|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BM_WBT_Beleuchtung : 32|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_HD_Oeffnung_angelernt : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BM_Autobahn : 34|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ BM_Rollenmodus_Blinken : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BM_Recas : 36|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Wischblinken : 37|1@1+ (1,0) [0|1] "" ZR_High + SG_ BM_Telematik_Abbruchgrund : 38|6@1+ (1,0) [0|63] "" Vector__XXX + SG_ BM_PiloPa : 44|1@1+ (1,0) [0|1] "" ZR_High + SG_ DWA_Alarmquelle : 59|5@1+ (1,0) [0|31] "" ZR_High + +BO_ 888 GNSS_04: 8 Gateway + SG_ GNSS_Nachrichtenpaket_ID4 : 0|2@1+ (1,0) [0|3] "Unit_Bit" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Ortung_Zeit_in_GPSWoche : 2|30@1+ (1,0) [0|604800001] "Unit_MilliSecon" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Ortung_Hoehe : 32|12@1+ (2,-500) [-500|7686] "Unit_Meter" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + +BO_ 891 GNSS_05: 8 Gateway + SG_ GNSS_UTC_Zeit : 0|32@1+ (1,0) [1|4294967295] "Unit_Secon" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Empfaenger_Status : 32|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_GPS_in_Nutzung : 33|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_GLONASS_in_Nutzung : 34|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Empfangbare_Satelliten : 35|5@1+ (1,0) [1|30] "Unit_None" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Sichtbare_Satelliten : 40|5@1+ (1,0) [1|30] "Unit_None" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Genutzte_Satelliten : 45|5@1+ (1,0) [1|30] "Unit_None" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GNSS_Nachrichtenpaket_ID5 : 50|2@1+ (1,0) [0|3] "Unit_Bit" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + +BO_ 896 APS_Master: 8 XXX + SG_ Active : 54|1@0+ (1,0) [0|1] "" XXX + SG_ Distance : 55|9@1+ (1,0) [0|255] "" XXX + +BO_ 916 WBA_03: 8 Gateway + SG_ WBA_03_CRC : 0|8@1+ (1,0) [0|255] "" Sub_Gateway + SG_ WBA_03_BZ : 8|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ WBA_Fahrstufe_02 : 12|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ WBA_ZielFahrstufe : 16|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ WBA_GE_Warnung_02 : 20|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ WBA_eing_Gang_02 : 24|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ WBA_GE_Texte : 28|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ WBA_Segeln_aktiv : 31|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ WBA_Schaltschema : 32|5@1+ (1,0) [0|31] "" Sub_Gateway + SG_ WBA_GE_Zusatzwarnungen : 37|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ GE_Sollgang : 40|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ GE_Tipschaltempf_verfuegbar : 44|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ WBA_GE_Texte_02 : 45|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ WBA_GE_Texte_03 : 48|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ WBA_Blinken : 54|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Wiederstart_Anz_Std : 55|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_01 : 56|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_02 : 57|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_03 : 58|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_04 : 59|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_05 : 60|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_06 : 61|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_07 : 62|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ GE_Stoppverbot_Anz_Std : 63|1@1+ (1,0) [0|1] "" Sub_Gateway + +BO_ 919 LDW_02: 8 XXX + SG_ LDW_Gong : 12|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_SW_Warnung_links : 14|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_SW_Warnung_rechts : 15|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Texte : 16|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Seite_DLCTLC : 20|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Lernmodus : 21|3@1+ (1,0) [0|7] "" XXX + SG_ LDW_Anlaufsp_VLR : 24|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Vib_Amp_VLR : 28|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Anlaufzeit_VLR : 32|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Lernmodus_rechts : 36|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Lernmodus_links : 38|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_DLC : 40|8@1+ (0.01,-1.25) [-1.25|1.25] "Unit_Meter" XXX + SG_ LDW_TLC : 48|5@1+ (0.1,0) [0|3] "Unit_Secon" XXX + SG_ LDW_Warnung_links : 56|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Warnung_rechts : 57|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Codierinfo_fuer_VLR : 58|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Frontscheibenheizung_aktiv : 60|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Status_LED_gelb : 61|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Status_LED_gruen : 62|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_KD_Fehler : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 949 Klima_11: 8 Gateway + SG_ KL_Drehz_Anh : 0|1@1+ (1,0) [0|1] "" TME + SG_ KL_Vorwarn_Komp_ein : 1|1@1+ (1,0) [0|1] "" TME + SG_ KL_AC_Schalter : 2|1@1+ (1,0) [0|1] "" TME + SG_ KL_Komp_Moment_alt : 3|1@1+ (1,0) [0|1] "" TME + SG_ KL_Vorwarn_Zuheizer_ein : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Zustand : 7|1@1+ (1,0) [0|1] "" TME + SG_ KL_Kompressorkupplung_linear : 8|8@1+ (20,0) [0|4000] "Unit_MilliAmper" Vector__XXX + SG_ KL_Charisma_FahrPr : 16|4@1+ (1,0) [0|15] "" TME + SG_ KL_Charisma_Status : 20|2@1+ (1,0) [0|3] "" TME + SG_ KL_nachtr_Stopp_Anf : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_T_Charge : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Last_Kompr : 24|8@1+ (0.25,0) [0|63.5] "Unit_NewtoMeter" TME + SG_ KL_Spannungs_Anf : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Thermomanagement : 34|2@1+ (1,0) [0|3] "" TME + SG_ KL_StartStopp_Info : 36|2@1+ (1,0) [0|3] "" TME + SG_ KL_Freilauf_Info : 38|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Anf_KL : 40|8@1+ (0.4,0) [0|101.6] "Unit_PerCent" TME + SG_ KL_el_Zuheizer_Stufe : 48|3@1+ (1,0) [0|7] "" TME + SG_ KL_Ausstattung_Klima : 51|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ KL_Variante_Standheizung : 54|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 958 Motor_14: 8 Gateway + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ MO_StartStopp_Status : 12|2@1+ (1,0) [0|3] "" Sub_Gateway,TME + SG_ MO_StartStopp_Wiederstart : 14|1@1+ (1,0) [0|1] "" BMS_NV,Sub_Gateway,TME + SG_ MO_StartStopp_Motorstopp : 15|1@1+ (1,0) [0|1] "" BMS_NV,Sub_Gateway,TME + SG_ MO_Freig_Reku : 16|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_Kl_75 : 18|1@1+ (1,0) [0|1] "" Sub_Gateway,TME + SG_ MO_Kl_50 : 19|1@1+ (1,0) [0|1] "" DCDC_IHEV,Ladegeraet_Konzern,Sub_Gateway + SG_ MO_Gangposition : 20|4@1+ (1,0) [0|15] "" AWC,Sub_Gateway,TME + SG_ MO_StartStopp_Fahrerwunsch : 24|2@1+ (1,0) [0|3] "" Sub_Gateway,TME + SG_ MO_HYB_Fahrbereitschaft : 26|1@1+ (1,0) [0|1] "" AWC,BMS_NV,Ladegeraet_Konzern,Sub_Gateway,TME + SG_ MO_Ext_E_Fahrt_aktiv : 27|1@1+ (1,0) [0|1] "" Sub_Gateway,TME + SG_ MO_Fahrer_bremst : 28|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_QBit_Fahrer_bremst : 29|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_BLS : 30|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Konsistenz_Bremsped : 31|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_KomFehler_ESP : 32|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Klima_Eingr : 33|2@1+ (1,0) [0|3] "" Sub_Gateway,TME + SG_ MO_Aussp_Anlass : 35|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Freig_Anlass : 36|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Kuppl_schalter : 37|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Interlock : 38|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Motor_laeuft : 39|1@1+ (1,0) [0|1] "" Sub_Gateway,TME + SG_ MO_Kickdown : 40|1@1+ (1,0) [0|1] "" Sub_Gateway,TME + SG_ MO_QBit_KL_75 : 41|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_EKlKomLeiRed : 42|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_Handshake_STH : 44|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_BKV_Unterdruckwarnung : 45|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Freigabe_Segeln : 46|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_PTC_Status : 47|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ MO_QBit_Gangposition : 50|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Signalquelle_Gangposition : 51|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Remotestart_Betrieb : 52|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Remotestart_moeglich : 53|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_FMAus_aktiv : 55|1@1+ (1,0) [0|1] "" BMS_NV,Sub_Gateway + SG_ MO_FMAus_Startvariante : 56|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_BMS_NV_Anf_stuetzen : 58|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Zylinderabschaltung : 59|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_HYB_VM_aktiv : 61|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_StartVorauss_erfuellt : 62|2@1+ (1,0) [0|3] "" AWC,Ladegeraet_Konzern,Sub_Gateway + +BO_ 960 Klemmen_Status_01: 4 Gateway + SG_ Klemmen_Status_01_CRC : 0|8@1+ (1,0) [0|255] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ Klemmen_Status_01_BZ : 8|4@1+ (1,0) [0|15] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ RSt_Fahrerhinweise : 12|4@1+ (1,0) [0|15] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZAS_Kl_S : 16|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,GurtMikrofon,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZAS_Kl_15 : 17|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,DDA,GurtMikrofon,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZAS_Kl_X : 18|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZAS_Kl_50_Startanforderung : 19|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ BCM_Remotestart_Betrieb : 20|1@1+ (1,0) [0|1] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZAS_Kl_Infotainment : 21|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ BCM_Remotestart_KL15_Anf : 22|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ BCM_Remotestart_MO_Start : 23|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Warn_P1_ZST_def : 24|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Warn_P2_ZST_def : 25|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Fahrerhinweis_1 : 26|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Fahrerhinweis_2 : 27|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ BCM_Ausparken_Betrieb : 28|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Fahrerhinweis_4 : 29|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Fahrerhinweis_5 : 30|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ KST_Fahrerhinweis_6 : 31|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + +BO_ 967 Motor_26: 8 Gateway + SG_ MO_Kuehlerluefter_MUX M : 0|1@1+ (1,0) [0|1] "" TME + SG_ MO_Kuehlerluefter_1 m0 : 1|7@1+ (1,0) [0|100] "Unit_PerCent" TME + SG_ MO_Kuehlerluefter_2 m1 : 1|7@1+ (1,0) [0|100] "Unit_PerCent" TME + SG_ MO_EFLEX_Lampe : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_KJS_nicht_bereit : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_ITM_Warnung_Pumpe : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Anzeige_aktiv : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Oelmin_Warn : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Sensorfehler : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Schieflage : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Oelstand : 16|4@1+ (12.5,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ MO_Zustand_HWP : 20|2@1+ (1,0) [0|3] "" TME + SG_ OLEV_Systemstoerung : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Oelwarnung_max : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Oelsystem_aktiv : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_nicht_betriebswarm : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Ueberfuell_Warn : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_laufender_Motor : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_E_Warnungen : 28|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MO_Text_Motorstart : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MO_E_Texte : 36|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ WIV_Oeldyn_avl : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Text_Partikelfil_Reg : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ OLEV_Oelstand_nicht_vorhanden : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Oelmenge : 43|5@1+ (125,0) [0|3875] "Unit_MilliLiter" Vector__XXX + SG_ MO_Systemlampe : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_OBD2_Lampe : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Heissleuchte : 50|1@1+ (1,0) [0|1] "" TME + SG_ MO_Partikel_Lampe : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_RedFahrleistung_Lampe : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Oelstand_nicht_vorhanden : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_nachfuellanzeige_ein : 54|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Ueberfuell_deaktiv : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Unterfuell_Warn : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Tankdeckel_Lampe : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Text_Tankdeckelwarn : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Vorglueh_Lampe : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WIV_Oeldr_Warn_Motor : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_E_Mode : 61|3@1+ (1,0) [0|7] "" Vector__XXX + +BO_ 974 TSG_HFS_01: 8 Gateway + SG_ HFS_Tuer_geoeffnet : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_verriegelt : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_gesafet : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Heckrollotaster_betaetigt : 3|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Tuerschloss_defekt : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Unlock_Taster : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Lock_Taster : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Sperrklinke : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_TAG_betaetigt : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_TIG_betaetigt : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_HBFS_AutoHoch : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_HBFS_AutoTief : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_HBFS_ManHoch : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_HBFS_ManTief : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Tuer_Status : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ HFS_SAD_Schalter : 16|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HFS_FH_S_ManHoch : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_AutoHoch : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_ManTief : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_S_AutoTief : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_Oeffnung : 24|8@1+ (0.5,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ HFS_FH_Bew_hoch : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_Bew_tief : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_Fang : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_Block : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_Thermo : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_UEKB_aktiviert : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Tueroeffnen_Warnung : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_FH_normiert : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ASW_Warnung_aktiv_HFS : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Zuziehhilfe_aktiv : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Seitenrollo_hoch : 42|1@1+ (1,0) [0|1] "" TME + SG_ HFS_Seitenrollo_tief : 43|1@1+ (1,0) [0|1] "" TME + SG_ HFS_Status_KiSi : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SSR_HFS_Pos_Unten : 45|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Oben_Block_erw : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Unten_Block_erw : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHFS_M_Taste : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHFS_Pos1 : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHFS_Pos2 : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHFS_Pos3 : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_MRollo_Schalter : 52|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ HFS_Lock_Taster_inv : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_Status_eTAG : 56|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ HFS_Tuer_Status_QBit : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HFS_TCR_Mode_aktiv : 59|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 975 TSG_HBFS_01: 8 Gateway + SG_ HBFS_Tuer_geoeffnet : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_verriegelt : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_gesafet : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Heckrollotaster_betaetigt : 3|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Tuerschloss_defekt : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Unlock_Taster : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Lock_Taster : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Sperrklinke : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_TAG_betaetigt : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_TIG_betaetigt : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_HFS_AutoHoch : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_HFS_AutoTief : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_HFS_ManHoch : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_HFS_ManTief : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Tuer_Status : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ HBFS_SAD_Schalter : 16|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HBFS_FH_S_ManHoch : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_AutoHoch : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_ManTief : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_S_AutoTief : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_Oeffnung : 24|8@1+ (0.5,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ HBFS_FH_Bew_hoch : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_Bew_tief : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_Fang : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_Block : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_Thermo : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_UEKB_aktiviert : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Tueroeffnen_Warnung : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_FH_normiert : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ASW_Warnung_aktiv_HBFS : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Zuziehhilfe_aktiv : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Seitenrollo_hoch : 42|1@1+ (1,0) [0|1] "" TME + SG_ HBFS_Seitenrollo_tief : 43|1@1+ (1,0) [0|1] "" TME + SG_ HBFS_Status_KiSi : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SSR_HBFS_Pos_Unten : 45|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Oben_Block_erw : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Unten_Block_erw : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHBFS_M_Taste : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHBFS_Pos1 : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHBFS_Pos2 : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MTHBFS_Pos3 : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_MRollo_Schalter : 52|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ HBFS_Lock_Taster_inv : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Status_KiSi_inv : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_Status_eTAG : 57|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ HBFS_Tuer_Status_QBit : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_TIG_betaetigt_schliessen : 60|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 976 TSG_FT_01: 8 Gateway + SG_ FT_Tuer_geoeffnet : 0|1@1+ (1,0) [0|1] "" Ladegeraet_Konzern,TME + SG_ FT_verriegelt : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_gesafet : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Schluesselschalter_auf : 3|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV + SG_ FT_Schluesselschalter_zu : 4|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV + SG_ FT_Unlock_Taster : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Lock_Taster : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Sperrklinke : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_TAG_betaetigt : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_TIG_betaetigt : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_IRUE_Taste : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_HD_Taste : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_TD_Taste_Fehler : 12|1@1+ (1,0) [0|1] "" Ladegeraet_Konzern + SG_ FT_TD_Taste : 13|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Ladegeraet_Konzern + SG_ SSR_Temp_Freigabe : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Sp_Heizung_Anf : 15|1@1+ (100,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ FT_HD_Taste_2 : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_TSG_hinten_verbaut : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Sp_Blk_def : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_S_ManHoch : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_S_AutoHoch : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_S_ManTief : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_S_AutoTief : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_Oeffnung : 24|8@1+ (0.5,0) [0|100] "Unit_PerCent" TME + SG_ FT_FH_Bew_hoch : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_Bew_tief : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_Fang : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_Block : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_Thermo : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_UEKB_aktiviert : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ASW_HMI_defekt : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_normiert : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Schliesstaster : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Zuziehhilfe_aktiv : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_SP_ausgerastet : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_SP_lr_aktiv : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_SP_ht_aktiv : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ASW_wakeup : 45|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Oben_Block_erw : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Unten_Block_erw : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Kisi_li_aktiv : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Kisi_re_aktiv : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Kisi_Taster_li : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Kisi_Taster_re : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_BFS_Fond_Freigabe : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Kisi_Fehler : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Daemmglas : 54|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_SP_Heizung_Status : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ASW_Warnung_aktiv_FS : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_FH_Pos_oben : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Tuerschloss_defekt : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_SWA_Taster : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_HMI_Diagnose : 60|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ FS_Status_eTAG : 62|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 980 SMLS_01: 8 Gateway + SG_ SMLS_01_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ SMLS_01_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BH_Blinker_li : 12|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ BH_Blinker_re : 13|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ BH_Lichthupe : 14|1@1+ (1,0) [0|1] "" ZR_High + SG_ BH_Fernlicht : 15|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_Tipwischen : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_Intervall : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_WischerStufe1 : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_WischerStufe2 : 19|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_Frontwaschen : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_Heckintervall : 21|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_Heckwaschen : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ WH_Intervallstufen : 23|4@1+ (1,0) [0|15] "" ZR_High + SG_ FAS_Taster : 27|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ FAS_Taster_Fehler : 28|1@1+ (1,0) [0|1] "" ZR_High + SG_ SMLS_Hupe : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LRH_On_Off : 30|2@1+ (1,0) [0|3] "" ZR_High + SG_ LRH_aktiv : 40|1@1+ (1,0) [0|1] "" ZR_High + SG_ SMLS_P_verriegelt_plausibel : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WH_SRA : 44|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ WH_Wischer_Fehler : 45|1@1+ (1,0) [0|1] "" ZR_High + SG_ BH_Blinker_Fehler : 46|1@1+ (1,0) [0|1] "" ZR_High + SG_ SMLS_PTT : 47|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ WH_Tipwischen_lang : 48|1@1+ (1,0) [0|1] "" ZR_High + +BO_ 981 Licht_Anf_01: 8 Gateway + SG_ Licht_Anf_01_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ Licht_Anf_01_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BCM1_Kurvenlicht_links_Anf : 12|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Kurvenlicht_rechts_Anf : 13|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Standlicht_Anf : 14|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Abblendlicht_Anf : 15|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ BCM1_Fernlicht_Anf : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Nebellicht_Anf : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Parklicht_li_Anf : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Parklicht_re_Anf : 19|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Nebelschluss_Ahg_Anf : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Nebelschluss_Fzg_Anf : 21|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Schlusslicht_Anf : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM_Rueckfahrlicht_Anf : 23|1@1+ (1,0) [0|1] "" ZR_High,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ BCM1_Signaturlicht_Anf : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Umfeldleuchten_Anf : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Tagfahrlicht_Anf : 26|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Regenlicht_Anf : 27|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Autobahnlicht_Anf : 28|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Touristen_Licht_Anf : 29|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_CH_aktiv : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_LH_aktiv : 31|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Gleitende_Leuchtw_Anf : 32|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_GLW_Fernlicht_Anf : 33|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Adaptive_Lichtvert_Anf : 34|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_FoD_Sperrung_WiBli : 35|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BCM1_FOD_Sperrung_Animationen_HL : 37|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BCM1_Animationssperrung : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_CH_LH_aktiv : 40|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Allwetterlicht_Anf : 41|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Schlusslicht_Signatur : 60|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 982 Licht_hinten_01: 8 Gateway + SG_ BCM2_Bremsl_durch_ECD : 5|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Aussenlicht_def : 7|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Standlicht_H_aktiv : 8|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Parklicht_HL_aktiv : 9|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Parklicht_HR_aktiv : 10|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Bremslicht_H_aktiv : 11|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Nebelschluss_aktiv : 12|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Rueckfahrlicht_aktiv : 13|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Blinker_HL_akt : 14|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Blinker_HR_akt : 15|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LH_Blinker_li_def : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Bremsl_li_def : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schlusslicht_li_def : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Rueckf_li_def : 19|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Nebel_li_def : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schluss_Brems_Nebel_li_def : 21|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schluss_Brems_Nebel_re_def : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Zusatzschlussl_def : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_li_def : 24|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schluss_Nebel_li_def : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_SL_BRL_BLK_li_def : 26|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Brems_Blk_li_def : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Diag_Status_re_def : 28|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Diag_Status_li_def : 29|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Diag_LED_li_def : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Diag_LED_re_def : 31|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Blinker_re_def : 32|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Bremsl_re_def : 33|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schlusslicht_re_def : 34|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Rueckf_re_def : 35|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Nebel_re_def : 36|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schluss_Brems_mi_def : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_re_def : 40|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schluss_Nebel_re_def : 41|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_SL_BRL_BLK_re_def : 42|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Brems_Blk_re_def : 43|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Kennzl_def : 48|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_3_Bremsl_def : 49|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Nebel_mi_def : 50|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Rueckf_mi_def : 51|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Schlusslicht_mi_def : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_mi_def : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_li_ges_def : 54|1@1+ (1,0) [0|1] "" ZR_High + SG_ LH_Bremsl_re_ges_def : 55|1@1+ (1,0) [0|1] "" ZR_High + +BO_ 987 Gateway_72: 8 Gateway_MQB + SG_ BCM_01_alt : 0|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ SMLS_01_alt : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ZV_02_alt : 2|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Wischer_01_alt : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Anhaenger_01_alt : 4|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ Klima_Sensor_02_alt : 5|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ VSG_01_alt : 6|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ Klima_01_alt : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_01_alt : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Licht_Anf_01_alt : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HFS_offen : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HBFS_offen : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ VS_VD_offen_ver : 22|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ VS_VD_zu_ver : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_BT_offen : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Rueckfahrlicht_Schalter : 25|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ZV_FT_offen : 26|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Wischer_vorne_aktiv : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Anhaenger_erkannt : 28|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ BCM1_MH_Schalter : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HD_offen : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Waschen_vorne_aktiv : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Thermomanagement : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ WFS_Schluessel_Fahrberecht : 34|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BCM1_RFahrlicht_Fzg_Anf : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_RFahrlicht_Ahg_Anf : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BH_Fernlicht : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BH_Blinker_li : 50|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BH_Blinker_re : 51|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_OBD_FStatus_ATemp : 52|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Aussen_Temp_ungef : 56|8@1+ (0.5,-50) [-50|76] "Unit_DegreCelsi" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 988 Gateway_73: 8 XXX + SG_ UNKNOWN_1 : 15|2@0+ (1,0) [0|3] "" XXX + SG_ GE_Fahrstufe : 40|4@1+ (1,0) [0|15] "" XXX + SG_ EPB_Status : 53|3@1+ (1,0) [0|7] "" XXX + SG_ UNKNOWN_2 : 58|3@0+ (1,0) [0|7] "" XXX + +BO_ 997 TSG_FT_02: 8 Gateway + SG_ TSG_FT_02_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ TSG_FT_02_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ FT_Tuer_Status : 12|2@1+ (1,0) [0|3] "" OTA_FC,ZR_High + SG_ FT_Tuer_Status_QBit : 14|1@1+ (1,0) [0|1] "" ZR_High + SG_ FT_Lock_Taster_02 : 15|1@1+ (1,0) [0|1] "" ZR_High + SG_ FT_Schluesselschalter_zu_02 : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ FT_BFS_Tuer_Status : 17|2@1+ (1,0) [0|3] "" ZR_High + SG_ FT_HBFS_Tuer_Status : 19|2@1+ (1,0) [0|3] "" ZR_High + SG_ FT_HFS_Tuer_Status : 21|2@1+ (1,0) [0|3] "" ZR_High + SG_ FT_Tueroeffnen_Warnung : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_SP_Heizung_ein : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FT_Kisi_Taster_li_02 : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ FT_Kisi_Taster_re_02 : 26|1@1+ (1,0) [0|1] "" ZR_High + SG_ FT_TD_Taste_Status : 27|2@1+ (1,0) [0|3] "" ZR_High + SG_ FT_TCR_Mode_aktiv : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FS_Push_Tuergriff : 36|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1004 MEB_TSK_01: 8 XXX + SG_ TSK_State : 53|3@1+ (1,0) [0|7] "" XXX + +BO_ 1031 PLA_04: 8 XXX + +BO_ 1122 PSD_04: 8 ZR_High + SG_ PSD_Segment_ID : 0|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Vorgaenger_Segment_ID : 6|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Segmentlaenge : 12|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG,OTA_FC + SG_ PSD_Strassenkategorie : 19|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG,OTA_FC + SG_ PSD_Endkruemmung : 22|8@1+ (1,0) [0|254] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Endkruemmung_Vorz : 30|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Idenditaets_ID : 31|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_ADAS_Qualitaet : 37|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_wahrscheinlichster_Pfad : 38|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Geradester_Pfad : 39|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Fahrspuren_Anzahl : 40|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG,OTA_FC + SG_ PSD_Bebauung : 43|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Segment_Komplett : 44|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Rampe : 45|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Anfangskruemmung : 47|8@1+ (1,0) [0|254] "" Gateway,Gateway_PAG + SG_ PSD_Anfangskruemmung_Vorz : 55|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Abzweigerichtung : 56|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Abzweigewinkel : 57|7@1+ (1.417323,0) [0|180.000021] "" Gateway,Gateway_PAG + +BO_ 1123 PSD_05: 8 ZR_High + SG_ PSD_Pos_Segment_ID : 0|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Pos_Segmentlaenge : 6|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Pos_Inhibitzeit : 13|5@1+ (10,0) [0|310] "Unit_MilliSecon" Gateway,Gateway_PAG + SG_ PSD_Pos_Standort_Eindeutig : 18|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Pos_Fehler_Laengsrichtung : 19|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Pos_Fahrspur : 22|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG,OTA_FC + SG_ PSD_Attribut_Segment_ID_05 : 25|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_1_ID : 31|5@1+ (1,0) [1|31] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_1_Wert : 36|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_1_Offset : 40|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Attribut_2_ID : 47|5@1+ (1,0) [1|31] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_2_Wert : 52|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_2_Offset : 56|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Attribute_Komplett_05 : 63|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + +BO_ 1124 PSD_06: 8 ZR_High + SG_ PSD_06_Mux M : 0|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Segment_ID m0 : 3|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Laendercode m0 : 9|8@1+ (1,0) [0|255] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Geschwindigkeit_Einheit m0 : 17|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Verkehrsrichtung m0 : 18|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Geometrieguete m0 : 19|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Mapmatchingguete m0 : 21|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Alter_Karte m0 : 23|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Zielfuehrung m0 : 26|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG,OTA_FC + SG_ PSD_Sys_US_State m0 : 27|6@1+ (1,0) [0|63] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_Geometrien m0 : 33|3@1+ (1,0) [0|7] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_Ortsinfo m0 : 36|2@1+ (1,0) [0|3] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_verfuegbar m0 : 38|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Zielfuehrung_geaendert m0 : 39|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Geometrieguete_erweitert m0 : 40|8@1+ (1,0) [0|255] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_sonstige_Attribute m0 : 48|3@1+ (1,0) [0|7] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_Steigungen m0 : 51|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_Strassenkennz m0 : 54|3@1+ (1,0) [0|7] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_Tempolimits m0 : 57|3@1+ (1,0) [0|7] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Sys_Quali_Vorfahrtsregelung m0 : 60|3@1+ (1,0) [0|7] "Unit_None" Gateway,Gateway_PAG + SG_ PSD_Attribut_Segment_ID m1 : 3|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_3_ID m1 : 9|5@1+ (1,0) [1|31] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_3_Offset m1 : 14|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Attribut_3_Wert m1 : 21|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_4_ID m1 : 25|5@1+ (1,0) [1|31] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_4_Wert m1 : 30|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_4_Offset m1 : 34|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Attribut_5_ID m1 : 41|5@1+ (1,0) [1|31] "" Gateway,Gateway_PAG + SG_ PSD_Attribut_5_Offset m1 : 46|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Attribut_5_Wert m1 : 53|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ PSD_Attribute_Komplett_06 m1 : 57|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Segment_ID m2 : 3|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Offset m2 : 9|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit m2 : 16|5@1+ (1,0) [0|31] "" Gateway,Gateway_PAG,OTA_FC + SG_ PSD_Ges_Typ m2 : 21|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Spur_Geschw_Begrenzung m2 : 23|6@1+ (1,0) [0|63] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit_Gespann m2 : 29|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit_Witter m2 : 31|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit_Tag_Anf m2 : 33|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit_Tag_Ende m2 : 36|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit_Std_Anf m2 : 39|5@1+ (1,0) [0|24] "Unit_Hours" Gateway,Gateway_PAG + SG_ PSD_Ges_Geschwindigkeit_Std_Ende m2 : 44|5@1+ (1,0) [0|24] "Unit_Hours" Gateway,Gateway_PAG + SG_ PSD_Ges_Ueberholverbot m2 : 49|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Wechselverkehrszeichen m2 : 51|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Wechselverkehrszeichen_Typ m2 : 54|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Gesetzlich_Kategorie m2 : 56|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Gesetzlich_Zusatz m2 : 59|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Verkehrszeichen_Quelle m2 : 61|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ PSD_Ges_Attribute_Komplett m2 : 63|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Baum_Laenge_VZ m3 : 3|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Baum_Laenge m3 : 4|25@1+ (1e-05,0) [0|180] "Unit_DegreOfArc" Gateway,Gateway_PAG + SG_ PSD_Baum_Breite_VZ m3 : 29|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Baum_Breite m3 : 30|24@1+ (1e-05,0) [0|90] "Unit_DegreOfArc" Gateway,Gateway_PAG + SG_ PSD_Baum_Ausrichtung m3 : 54|10@1+ (0.3515625,0) [0|359.6484375] "Unit_DegreOfArc" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_Segment_ID m4 : 3|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_A_Steigung m4 : 9|7@1+ (0.12,0) [0|15] "Unit_PerCent" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_A_Vorz m4 : 16|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_A_Offset m4 : 17|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_B_Steigung m4 : 24|7@1+ (0.12,0) [0|15] "Unit_PerCent" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_B_Vorz m4 : 31|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_B_Offset m4 : 32|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Steigung_1_Attribute_kompl m4 : 39|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Steigung_2_Segment_ID m4 : 40|6@1+ (1,0) [2|63] "" Gateway,Gateway_PAG + SG_ PSD_Steigung_2_Steigung m4 : 46|7@1+ (0.12,0) [0|15] "Unit_PerCent" Gateway,Gateway_PAG + SG_ PSD_Steigung_2_Vorz m4 : 53|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ PSD_Steigung_2_Offset m4 : 54|7@1+ (2,0) [0|254] "Unit_Meter" Gateway,Gateway_PAG + SG_ PSD_Steigung_2_Attribute_kompl m4 : 61|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + +BO_ 1153 MainUnit_01: 8 ZR_High + SG_ ZR_LoGeWa_Event_Kombiwarnung : 0|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ Nav_FoD_Status : 4|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ MIB_Tongenerator_PH_verfuegbar : 9|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ MMI_Counter_Bedienevent : 12|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ DSSS_Warning : 16|5@1+ (1,0) [0|31] "" Gateway,Gateway_PAG + SG_ ZR_Kindersicherung_RSE : 21|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ ZR_RSE_aktivieren : 22|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ MMI_SDS_aktiv : 23|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ MU_SecondDisplay : 24|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG + SG_ MMI_Telefon_aktiv : 27|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG + SG_ MMI_Gurt_Mic_ref : 28|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG,GurtMikrofon + SG_ ZR_Sta_Inszenierung : 29|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ MMI_Gauges_active : 31|1@1+ (1,0) [0|1] "" BedienDisp_vo,Gateway,Gateway_PAG + SG_ MU_Update_Time : 32|8@1+ (0.1,0) [0|25.5] "Unit_Hours" Gateway,Gateway_PAG + SG_ ZR_MXB_Manoever_Ansage : 42|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ ZR_LAPP_Sondermodus_Status : 44|2@1+ (1,0) [0|3] "" DDA,Gateway,Gateway_PAG + SG_ MMI_StartStopp_Info : 46|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG + SG_ ZR_Parken_Sondermodus : 48|4@1+ (1,0) [0|15] "" DDA,Gateway,Gateway_PAG + SG_ ZR_Rundenbewertung : 52|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG + SG_ ZR_Rundenfortschritt : 56|8@1+ (0.5,0) [0|100] "Unit_PerCent" Gateway,Gateway_PAG + +BO_ 1155 Motor_Hybrid_06: 8 Gateway + SG_ Mo_Powermeter_Grenze : 0|12@1+ (1,0) [0|4092] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ MO_Text_Aktivierung_Antrieb : 12|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MO_Powermeter_Inszenierung_aktiv : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Powermeter_Charge_Grenze : 18|10@1+ (1,0) [0|1021] "Unit_None" Vector__XXX + SG_ MO_Powermeter_Grenze_strategisch : 28|12@1+ (1,0) [0|4093] "Unit_None" Vector__XXX + SG_ MO_Powermeter_untere_E_Grenze : 40|12@1+ (1,0) [0|4093] "Unit_None" Vector__XXX + SG_ MO_Powermeter_obere_E_Grenze : 52|12@1+ (1,0) [0|4093] "Unit_None" Vector__XXX + +BO_ 1163 BEM_06: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CHK : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 1175 Parkhilfe_01: 8 Gateway + SG_ PH_Visualisierung : 0|3@1+ (1,0) [0|7] "" AWC + SG_ PDC_Tonausgabe_Front : 4|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PDC_Tonausgabe_Heck : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_nachtr_Stopp_Anf : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Abschaltursache : 13|3@1+ (1,0) [0|7] "" AWC + SG_ PH_Opt_Anzeige_V_ein : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Opt_Anzeige_H_ein : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Opt_Anz_V_Hindernis : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Opt_Anz_H_Hindernis : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Tongeber_V_aktiv : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Tongeber_H_aktiv : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Tongeber_mute : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Anf_Audioabsenkung : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Tongeber_H_verfuegbar : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PLA_Anf_Aufschaltung_RVC : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Taster : 28|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ PH_Anf_Verdeck : 30|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ PH_Frequenz_hinten : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_Lautstaerke_hinten : 36|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_Frequenz_vorn : 40|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_Lautstaerke_vorn : 44|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_StartStopp_Info : 49|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ PH_Stoermeldung : 52|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_defekt : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_gestoert : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ PH_Systemzustand : 58|3@1+ (1,0) [0|7] "" AWC + SG_ PH_Display_Kundenwunsch : 61|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1283 HVK_01: 8 Gateway + SG_ HVK_01_CRC : 0|8@1+ (1,0) [0|255] "" BMC_MLBevo,DCDC_800V_PAG,DCDC_HV,DCDC_HV_02,FCU_MLBevo_FCEV,Ladegeraet_2,Ladegeraet_Konzern,LE1,LE2,LE_MLBevo,TME + SG_ HVK_01_BZ : 8|4@1+ (1,0) [0|15] "" BMC_MLBevo,DCDC_800V_PAG,DCDC_HV,DCDC_HV_02,FCU_MLBevo_FCEV,Ladegeraet_2,Ladegeraet_Konzern,LE1,LE2,LE_MLBevo,TME + SG_ HVK_Istmodus_Anf : 12|1@1+ (1,0) [0|1] "" BMC_MLBevo,DCDC_HV,FCU_MLBevo_FCEV,Ladegeraet_2,Ladegeraet_Konzern,LE1,LE2,LE_MLBevo + SG_ HVK_TN1_Sollmodus : 13|2@1+ (1,0) [0|3] "" DCDC_HV_02,FCU_MLBevo_FCEV + SG_ HVK_MO_EmSollzustand : 16|8@1+ (1,0) [0|255] "" FCU_MLBevo_FCEV + SG_ HVK_BMS_Sollmodus : 24|3@1+ (1,0) [0|7] "" BMC_MLBevo,FCU_MLBevo_FCEV + SG_ HVK_DCDC_Sollmodus : 27|3@1+ (1,0) [0|7] "" DCDC_800V_PAG,DCDC_HV,FCU_MLBevo_FCEV,LE_MLBevo + SG_ HVK_EKK_Sollmodus : 30|3@1+ (1,0) [0|7] "" FCU_MLBevo_FCEV,TME + SG_ HVK_HVPTC_Sollmodus : 33|3@1+ (1,0) [0|7] "" FCU_MLBevo_FCEV,TME + SG_ HVK_HVLM_Sollmodus : 36|3@1+ (1,0) [0|7] "" DCDC_HV_02,FCU_MLBevo_FCEV,Ladegeraet_Konzern + SG_ HVK_HV_Netz_Warnungen : 39|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV + SG_ HV_Bordnetz_aktiv : 41|1@1+ (1,0) [0|1] "" DCDC_HV_02,FCU_MLBevo_FCEV,Ladegeraet_Konzern,LE1,LE2,LE_MLBevo + SG_ HV_Bordnetz_Fehler : 42|1@1+ (1,0) [0|1] "" FCU_MLBevo_FCEV,Ladegeraet_Konzern,TME + SG_ HVK_Gesamtst_Spgfreiheit : 43|2@1+ (1,0) [0|3] "" FCU_MLBevo_FCEV + SG_ HVK_AktiveEntladung_Anf : 45|1@1+ (1,0) [0|1] "" DCDC_800V_PAG,DCDC_HV,DCDC_HV_02,FCU_MLBevo_FCEV,LE1,LE2,LE_MLBevo + SG_ HVK_Iso_Messung_Start : 50|3@1+ (1,0) [0|7] "" BMC_MLBevo,FCU_MLBevo_FCEV + SG_ HVK_DCDC_EKK_Sollmodus : 62|2@1+ (1,0) [0|3] "" DCDC_800V_PAG,FCU_MLBevo_FCEV + +BO_ 1312 Airbag_02: 8 Gateway + SG_ LoGeWa_Event_Kombiwarnung : 12|4@1+ (1,0) [0|15] "" ZR_High + SG_ AB_Anforderung_eCall : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ AB_Anprall_Seite_Beifahrer : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Anprall_Rollover : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Anprall_FGS : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Anprall_Front_Beifahrer : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Anprall_Front_Fahrer : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Anprall_Heck_Beifahrer : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Anprall_Heck_Fahrer : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AB_Wickelklappung_Reihe2_MI : 24|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AB_Belegung_VB : 26|2@1+ (1,0) [0|3] "" BedienSG_hi,GurtMikrofon,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ AB_Abschaltanf_SIH_BF : 28|1@1+ (1,0) [0|1] "" ZR_High + SG_ AB_Anprall_Seite_Fahrer : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SC_PAO_Schriftzug_Anf : 30|2@1+ (1,0) [0|3] "" ZR_High + SG_ SC_PAO_ON_Anf : 32|2@1+ (1,0) [0|3] "" ZR_High + SG_ SC_PAO_OFF_Anf : 34|2@1+ (1,0) [0|3] "" ZR_High + SG_ AB_Crashschwere : 36|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ AB_Anforderung_USM : 39|1@1+ (1,0) [0|1] "" ZR_Standard + SG_ AB_Gurtschloss_FA : 40|2@1+ (1,0) [0|3] "" BedienSG_hi,GurtMikrofon,ZR_High + SG_ AB_Gurtschloss_BF : 42|2@1+ (1,0) [0|3] "" BedienSG_hi,GurtMikrofon,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ AB_Gurtschloss_Reihe2_FA : 44|2@1+ (1,0) [0|3] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ AB_Gurtschloss_Reihe2_MI : 46|2@1+ (1,0) [0|3] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ AB_Gurtschloss_Reihe2_BF : 48|2@1+ (1,0) [0|3] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ AB_Gurtschloss_Reihe3_FA : 50|2@1+ (1,0) [0|3] "" BedienSG_hi,ZR_High + SG_ AB_Gurtschloss_Reihe3_MI : 52|2@1+ (1,0) [0|3] "" BedienSG_hi,ZR_High + SG_ AB_Gurtschloss_Reihe3_BF : 54|2@1+ (1,0) [0|3] "" BedienSG_hi,ZR_High + SG_ AB_Sitzpos_Sens_FA : 56|2@1+ (1,0) [0|3] "" ZR_High + SG_ AB_Sitzpos_Sens_BF : 58|2@1+ (1,0) [0|3] "" ZR_High + SG_ AB_Wickelklappung_Reihe2_BF : 60|2@1+ (1,0) [0|3] "" ZR_High + SG_ AB_Wickelklappung_Reihe2_FA : 62|2@1+ (1,0) [0|3] "" ZR_High + +BO_ 1349 Airbag_04: 8 Gateway + SG_ AB_Gurtwarn_Reihe2_FA : 20|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AB_Gurtwarn_Reihe2_BF : 22|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AbstWarn_MV_FAS_Fkt_Status : 24|2@1+ (1,0) [0|3] "" ZR_High + SG_ WarnBrems_Charisma_Status : 26|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ WarnBrems_Charisma_FahrPr : 28|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ AB_Gurtwarn_Reihe2_MI : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AB_Gurtwarn_Reihe3_FA : 34|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AB_Gurtwarn_Reihe3_MI : 36|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AB_Gurtwarn_Reihe3_BF : 38|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ LGI_FAS_Fkt_Status : 40|2@1+ (1,0) [0|3] "" ZR_High + SG_ PreCrash_FAS_Fkt_Status : 42|3@1+ (1,0) [0|7] "" ZR_High + SG_ AB_SBR_hinten_verbau : 48|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AWV_Einstellung_System_ASG : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Einstellung_Warnung_ASG : 52|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ SC_PreSense_Modus_Warnung_NV : 55|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ SC_PreSense_Modus_Warnung_MV : 58|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ SC_PreSense_Modus_System_MV : 61|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SC_PreSense_Modus_System_NV : 62|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SC_PreSense_Modus_System_KAS : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1355 Parkhilfe_04: 8 Gateway + SG_ PH_Verschmutzungsmeldung : 12|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ PH_Aufschaltursache : 16|5@1+ (1,0) [0|31] "" AWC + SG_ PH_Ton_Ausgabe : 21|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ PH_Ton_Pausenlaenge : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ PH_Ton_Richtung : 49|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ PH_Ton_Lautstaerke : 52|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ BCM_WAH_Meldung : 55|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ PDC_Charisma_Status : 58|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ PDC_Charisma_FahrPr : 60|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 1361 WFS_01: 8 Gateway + SG_ WFS_Schluessel_Fahrberecht : 0|4@1+ (1,0) [0|15] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ WFS_ID_Geb_autorisiert : 5|1@1+ (1,0) [0|1] "" ZR_High + SG_ WFS_ID_Geb_autorisiert_in_Kl15 : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_ID_Geb_steckt : 7|1@1+ (1,0) [0|1] "" ZR_High + SG_ WFS_Schluessel_Soll : 8|4@1+ (1,0) [0|15] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ WFS_Schluessel_Ist : 12|4@1+ (1,0) [0|15] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ WFS_Safe : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_LZ : 17|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ WFS_ELV_authorisiert : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_LF_Aktiv : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_Betrieb_Lesespule : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_Klemmenfreigabe : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_Fahrerhinweise : 34|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ WFS_Parken_Status : 36|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1385 MEB_HVEM_03: 8 XXX + SG_ NEW_SIGNAL_12 : 0|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_1 : 1|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_10 : 3|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 4|2@1+ (1,0) [0|3] "" XXX + SG_ PTC_ON : 7|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 25|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_13 : 32|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_4 : 33|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_11 : 35|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_5 : 36|2@1+ (1,0) [0|3] "" XXX + SG_ NEW_SIGNAL_6 : 38|1@0+ (1,0) [0|1] "" XXX + SG_ PTC_ein_02 : 39|1@0+ (1,0) [0|1] "" XXX + SG_ PTC_ein_03 : 57|1@0+ (1,0) [0|1] "" XXX + SG_ PTC_ein_04 : 59|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_9 : 61|2@1+ (1,0) [0|3] "" XXX + +BO_ 1411 ZV_02: 8 Gateway + SG_ BCM_FH_Freigabe : 12|1@1+ (1,0) [0|1] "" BedienDisp_vo + SG_ BCM_Komfortfkt_Freigabe : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_HSK_Freigabe : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Verdeck_Freigabe : 15|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_verriegelt_intern_ist : 16|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High + SG_ ZV_verriegelt_extern_ist : 17|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High + SG_ ZV_verriegelt_intern_soll : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_verriegelt_extern_soll : 19|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZV_gesafet_extern_ist : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_gesafet_extern_soll : 21|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3 + SG_ ZV_Einzeltuerentriegelung : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_Heckeinzelentriegelung : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_FT_offen : 24|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZV_BT_offen : 25|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZV_HFS_offen : 26|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZV_HBFS_offen : 27|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZV_HD_offen : 28|1@1+ (1,0) [0|1] "" DDA,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ ZV_HS_offen : 29|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ IRUE_aktiv : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ DWA_aktiv : 31|1@1+ (1,0) [0|1] "" ZR_High + SG_ HD_Hauptraste : 32|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ HD_Vorraste : 33|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ FFB_CarFinder : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FFB_Komfortoeffnen : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ FFB_Komfortschliessen : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_Schluessel_Zugang : 42|4@1+ (1,0) [0|15] "" ZR_High + SG_ ZV_SafeFunktion_aktiv : 46|1@1+ (1,0) [0|1] "" ZR_High + SG_ FBS_Warn_Schluessel_Batt : 47|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_Oeffnungsmodus : 48|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ HFS_verriegelt : 50|1@1+ (1,0) [0|1] "" OTA_FC + SG_ HFS_gesafet : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HBFS_verriegelt : 52|1@1+ (1,0) [0|1] "" OTA_FC + SG_ HBFS_gesafet : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_ist_Zustand_verfuegbar : 54|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ IRUE_Taster_Fkts_LED : 55|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_Tankklappe_offen : 56|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_Rollo_auf : 57|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_Rollo_zu : 58|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_SAD_auf : 59|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_SAD_zu : 60|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM_Tankklappensteller_Fehler : 61|1@1+ (1,0) [0|1] "" ZR_High + SG_ ZV_verriegelt_soll : 62|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1413 Systeminfo_01: 8 Gateway + SG_ SI_Sammel_SG_Fehler : 0|6@1+ (1,0) [0|60] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_Diagnose_Aktiv : 7|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_QRS_Mode : 8|1@1+ (1,0) [0|1] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_T_Mode : 9|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,DDA,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_NWDF : 10|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,DDA,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_NWDF_gueltig : 11|1@1+ (1,0) [0|1] "" BedienDisp_vo,BedienSG_hi,DDA,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_Sammelfehler : 12|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ GW_KD_Fehler : 13|1@1+ (1,0) [0|1] "" ZR_High,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_T_Schutz : 14|1@1+ (1,0) [0|1] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_01 : 16|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_02 : 17|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_03 : 18|1@1+ (1,0) [0|1] "" BedienSG_hi,DDA,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_04 : 19|1@1+ (1,0) [0|1] "" BedienSG_hi,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_05 : 20|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_06 : 21|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_07 : 22|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_08 : 23|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_09 : 24|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_10 : 25|1@1+ (1,0) [0|1] "" BedienSG_hi,DDA,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_11 : 26|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_12 : 27|1@1+ (1,0) [0|1] "" DDA,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_13 : 28|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_14 : 29|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_BUS_15 : 30|1@1+ (1,0) [0|1] "" ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_Bus_Identifikation : 32|8@1+ (1,0) [0|255] "" OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + SG_ SI_CAB : 40|24@1+ (1,0) [0|16777215] "" BedienSG_hi,OTA_FC,ZR_High,ZR_LIMU,ZR_MIB_TOP_ab_Gen3,ZR_Standard + +BO_ 1420 Klemmen_Steuerung_01: 8 Gateway + SG_ Klemmen_Steuerung_01_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ Klemmen_Steuerung_01_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ KST_Txt_P_Gang : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KST_Txt_Panikabschaltung : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KST_Anf_Klemmenfreigabe_ELV : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KST_Txt_Komfortabschaltung : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KST_ZAT_betaetigt : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ KST_Unterdr_Zuendungsmeldung : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KST_aut_Abschaltung_Zuendung : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KST_Anf_ZV_Verriegelung : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Relais_VoKo_angesteuert : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ RSt_Anforderung_HMS : 26|3@1+ (1,0) [0|7] "" Vector__XXX + +BO_ 1426 Kessy_04: 8 XXX + +BO_ 1440 RLS_01: 8 Gateway + SG_ LS_Helligkeit_IR : 0|8@1+ (400,0) [0|101200] "Unit_Lux" ZR_High + SG_ LS_Helligkeit_FW : 8|10@1+ (6,0) [0|6126] "Unit_Lux" ZR_High + SG_ LS_defekt : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ LS_Verbau : 23|1@1+ (1,0) [0|1] "" ZR_High + SG_ RS_Regenmenge : 24|4@1+ (10,0) [0|100] "Unit_PerCent" OTA_FC,ZR_High + SG_ RS_Verbau : 29|1@1+ (1,0) [0|1] "" ZR_High + SG_ RS_Verglasung_schliessen : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ RS_defekt : 31|1@1+ (1,0) [0|1] "" ZR_High + SG_ RS_Wischergeschwindigkeit : 32|3@1+ (1,0) [0|7] "" OTA_FC,ZR_High + SG_ RLS_Vorfeldhelligkeit_Boost : 35|4@1+ (1,0) [0|15] "" ZR_High + +BO_ 1442 BMS_04: 8 BMC_MLBevo + SG_ BMS_04_CRC : 0|8@1+ (1,0) [0|255] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ BMS_04_BZ : 8|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ BMS_Status_ServiceDisconnect : 13|1@1+ (1,0) [0|1] "" DCDC_800V_PAG,DCDC_HV,Gateway,Gateway_PAG,Sub_Gateway + SG_ BMS_Status_Spgfreiheit : 14|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ BMS_OBD_Lampe_Anf : 16|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ BMS_IstModus : 17|3@1+ (1,0) [0|7] "" AWC,Gateway,Gateway_PAG,Ladegeraet_Konzern,LE1,LE2,LE2_3_MLBevo_LB,Sub_Gateway,TME + SG_ BMS_Fehlerstatus : 20|3@1+ (1,0) [0|7] "" AWC,DCDC_800V_PAG,DCDC_HV,Gateway,Gateway_PAG,Ladegeraet_Konzern,Sub_Gateway + SG_ BMS_Kapazitaet_02 : 23|11@1+ (0.2,0) [0|409.2] "Unit_AmperHour" Gateway,Gateway_PAG,Ladegeraet_Konzern,Sub_Gateway + SG_ BMS_Soll_SOC_HiRes : 53|11@1+ (0.05,0) [0|100] "Unit_PerCent" Gateway,Gateway_PAG,Sub_Gateway + +BO_ 1447 TM_01: 8 Gateway + SG_ TM_Spiegel_Anklappen : 47|1@1+ (1,0) [0|1] "" ZR_High + SG_ TM_Nur_Hupen : 48|1@1+ (1,0) [0|1] "" ZR_High + SG_ TM_Door_Lock : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TM_Door_Unlock : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TM_Warnblinken : 51|1@1+ (1,0) [0|1] "" ZR_High + SG_ TM_Panik_Alarm : 52|1@1+ (1,0) [0|1] "" ZR_High + SG_ TM_ZV_Signatur : 53|11@1+ (1,0) [1|2047] "Unit_None" Vector__XXX + +BO_ 1452 HVEM_02: 8 Gateway + SG_ HVEM_IstStrom_HVVerbraucher : 0|12@1+ (0.1,-204.7) [-204.7|204.6] "Unit_Amper" Vector__XXX + SG_ HVEM_Energie_Klima_Vorgabe_HighR : 12|3@1+ (10,0) [0|50] "Unit_WattHour" TME + SG_ HVEM_IstLeistungNA : 15|9@1+ (50,0) [0|25450] "Unit_Watt" Vector__XXX + SG_ HVEM_Leistung_Klima_Vorgabe : 24|8@1+ (50,0) [0|12650] "Unit_Watt" TME + SG_ HVEM_Nutzbare_Energie : 32|11@1+ (50,0) [0|102200] "Unit_WattHour" Ladegeraet_Konzern + SG_ HVEM_Energie_Klima_Vorgabe : 43|8@1+ (50,0) [0|12650] "Unit_WattHour" TME + SG_ HVEM_MO_MaxLeistungIgnoriert : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1485 DCDC_03: 8 DCDC_800V_PAG + SG_ DCDC_03_CRC : 0|8@1+ (1,0) [0|255] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ DCDC_03_BZ : 8|4@1+ (1,0) [0|15] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ DC_Fehlerstatus : 16|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ DC_Peakstrom_verfuegbar : 19|1@1+ (1,0) [0|1] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ DC_Abregelung_Temperatur : 20|1@1+ (1,0) [0|1] "" Gateway_PAG,Sub_Gateway,TME + SG_ DC_IstModus_02 : 21|3@1+ (1,0) [0|7] "" DCDC_HV_02,Gateway,Gateway_PAG,Ladegeraet_Konzern,Sub_Gateway,TME + SG_ DC_HV_EKK_IstModus : 28|3@1+ (1,0) [0|7] "" Gateway,Gateway_PAG,Sub_Gateway,TME + SG_ DC_Status_Spgfreiheit_HV : 46|2@1+ (1,0) [0|3] "" Gateway,Gateway_PAG,Sub_Gateway + SG_ DC_IstSpannung_EKK_HV : 48|8@1+ (2,0) [0|508] "Unit_Volt" Gateway,Gateway_PAG,Sub_Gateway + SG_ DC_Temperatur : 56|8@1+ (1,-40) [-40|213] "Unit_DegreCelsi" Gateway,Gateway_PAG,Sub_Gateway,TME + +BO_ 1505 Klima_Sensor_02: 8 Gateway + SG_ BCM1_Aussen_Temp_ungef : 0|8@1+ (0.5,-50) [-50|76] "Unit_DegreCelsi" BMC_MLBevo,BMS_NV,FCU_MLBevo_FCEV,Ladegeraet_Konzern,TME + SG_ BCM_Heizungsabsperrventil_Status : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BCM_Heizungspumpe_Status : 10|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BCM_Kompressorkupplung_Status : 12|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BCM1_PTC_stufig_Status : 28|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ BCM1_FStatus_Aussentemp_ungef : 31|1@1+ (1,0) [0|1] "" TME + SG_ BCM1_Kompressorstrom_ist : 32|8@1+ (4,0) [0|1000] "Unit_MilliAmper" Vector__XXX + SG_ BCM1_OBD_FStatus_ATemp : 44|4@1+ (1,0) [0|15] "" BMC_MLBevo,Ladegeraet_Konzern,TME + +BO_ 1513 Klima_Sensor_04: 8 Gateway + SG_ DS_Kaeltemittel_P : 8|11@1+ (0.0161,0) [0|32.9245] "Unit_Bar" TME + SG_ DS_Status : 19|2@1+ (1,0) [0|3] "" TME + SG_ ION_Status : 21|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ION_Status_LED : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAU_Geblaese : 24|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ ION_Status_Taster : 31|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1520 Dimmung_01: 8 Gateway_MQB + SG_ DI_KL_58xd : 0|8@1+ (1,0) [0|253] "" Airbag_MQB + SG_ DI_KL_58xs : 8|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ DI_Display_Nachtdesign : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ DI_KL_58xt : 16|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ DI_Fotosensor : 24|16@1+ (1,0) [0|65535] "" Vector__XXX + +BO_ 1524 Innenlicht_11: 8 Gateway + SG_ IL_Dimmung_V_Tuerkontur : 0|8@1+ (1,0) [0|100] "Unit_PerCent" ZR_High + SG_ IL_Dimmung_H_Tuerkontur : 8|8@1+ (1,0) [0|100] "Unit_PerCent" ZR_High + SG_ IL_Dimmung_Tuerinnengriff : 16|8@1+ (1,0) [0|100] "Unit_PerCent" ZR_High + SG_ IL_Dimmung_Umfeldbel : 24|8@1+ (1,0) [0|100] "Unit_PerCent" ZR_High + SG_ IL_Bel_FS_Ausstieg : 32|1@1+ (1,0) [0|1] "" ZR_High + SG_ IL_Bel_BFS_Ausstieg : 33|1@1+ (1,0) [0|1] "" ZR_High + SG_ IL_Bel_HFS_Ausstieg : 34|1@1+ (1,0) [0|1] "" ZR_High + SG_ IL_Bel_HBFS_Ausstieg : 35|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Innenlicht_gedimmt_V : 36|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Innenlicht_gedimmt_H : 37|1@1+ (1,0) [0|1] "" ZR_High + SG_ IL_Innenlicht_aktiv : 38|1@1+ (1,0) [0|1] "" ZR_High + SG_ IL_Klemme_30G_aktiv : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_DI_Rampe_Innenlicht : 40|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_DI_Rampe_Leselicht : 41|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Innenlicht_H : 42|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Innenlicht_V : 43|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Leselicht_Anf_hl : 44|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Leselicht_Anf_hr : 45|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Leselicht_Anf_vl : 46|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Leselicht_Anf_vr : 47|1@1+ (1,0) [0|1] "" ZR_High + SG_ BCM1_Leuchten_Aus : 48|1@1+ (1,0) [0|1] "" ZR_High + SG_ AMB_Charisma_FahrPr : 49|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ AMB_Charisma_Status : 53|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ IL_Dimmung_Lautspr : 56|8@1+ (1,0) [0|100] "Unit_PerCent" ZR_High + +BO_ 1600 Motor_07: 8 Motor_Diesel_MQB + SG_ MO_QBit_Ansaugluft_Temp : 0|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_QBit_Oel_Temp : 1|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Kuehlmittel_Temp : 2|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Stellgliedtest_Soundaktuator : 3|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Fehler_HV_Netz : 4|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_aktives_Getriebeheizen : 5|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Absperrventil_oeffnen : 6|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Ansaugluft_Temp : 8|8@1+ (0.75,-48) [-48|141.75] "Unit_DegreCelsi" Gateway_MQB + SG_ MO_Oel_Temp : 16|8@1+ (1,-60) [-60|192] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kuehlmittel_Temp : 24|8@1+ (0.75,-48) [-48|141.75] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Hoeheninfo : 32|8@1+ (0.00781,0) [0|1.98374] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kennfeldk : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Versionsinfo : 41|6@1+ (1,0) [0|63] "" Gateway_MQB + SG_ MO_Getriebe_kuehlen : 47|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Traegheit_02 : 48|5@1+ (0.01,0) [0|0.31] "Unit_KiloGramMeterSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Heizungspumpenansteuerung : 53|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ MO_SpannungsAnf : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Nachlaufzeit_Heizungspumpe : 58|6@1+ (15,0) [0|945] "Unit_Secon" Gateway_MQB + +BO_ 1601 Motor_Code_01: 8 Motor_Diesel_MQB + SG_ Motor_Code_01_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ Motor_Code_01_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Faktor_Momente_02 : 12|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Hybridfahrzeug : 14|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Code : 16|8@1+ (1,0) [0|255] "" Gateway_MQB,SAK_MQB + SG_ MO_Getriebe_Code : 24|6@1+ (1,0) [0|63] "" Gateway_MQB + SG_ MO_StartStopp_Codiert : 30|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Anzahl_Zyl : 32|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Kraftstoffart : 36|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Hubraum : 40|7@1+ (0.1,0) [0|12.7] "Unit_Liter" Gateway_MQB + SG_ MO_Ansaugsystem : 47|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Leistung : 48|9@1+ (1,0) [0|511] "Unit_KiloWatt" Gateway_MQB + SG_ MO_Abgastyp_EOBD : 57|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ MO_Abgastyp_OBD : 58|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ MO_DPF_verbaut : 59|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_Codierung : 60|3@1+ (1,0) [0|7] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Einspritzart : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 1603 Einheiten_01: 8 Gateway + SG_ KBI_Einheit_Datum : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Druck : 2|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Streckenanz : 4|1@1+ (1,0) [0|1] "" Ladegeraet_Konzern + SG_ KBI_MFA_v_Einheit_02 : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Temp : 6|1@1+ (1,0) [0|1] "" TME + SG_ KBI_Einheit_Uhrzeit : 7|1@1+ (1,0) [0|1] "" Ladegeraet_Konzern + SG_ KBI_Einheit_Verbrauch : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Volumen : 10|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Verbrauch_elektr : 12|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ KBI_Einheit_Sprache : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KBI_Einheit_Verbrauch_Gas : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ KBI_Einheit_Masse : 28|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1622 ELV_01: 8 Gateway + SG_ ELV_01_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ ELV_01_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ ELV_Anf_Klemme_S : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Anf_Klemme_15 : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Anf_Klemme_50 : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_01_Sendestatus : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Verriegelt : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ ELV_Entriegelt : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ ELV_ZAT_betaetigt : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Lebenszustand : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Anlernmodus : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Klemmenfreigabe : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Abbruch_Anf_Klemmenfreigabe : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_LED_Rot : 24|1@1+ (1,0) [0|1] "" ZR_High + SG_ ELV_LED_Gelb : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Txt_Panikabschaltung : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Txt_Lkg_Bewegen : 28|1@1+ (1,0) [0|1] "" ZR_High + SG_ ELV_Txt_Werkstatt : 29|1@1+ (1,0) [0|1] "" ZR_High + SG_ ELV_Txt_Defekt : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ ELV_Txt_P_Gang : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Txt_PN_Gang : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Txt_Kupplung : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_Txt_Bremse : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ELV_P_verriegelt : 35|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1624 Licht_vorne_01: 8 Gateway + SG_ Licht_Vorne_01_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ Licht_Vorne_01_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ LV_Standlicht_Anzeige : 12|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Abblendlicht_Anzeige : 13|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Fernlicht_Anzeige : 14|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Nebellicht_Anzeige : 15|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Nebelschlusslicht_Anzeige : 16|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Tagfahrlicht_Anzeige : 17|1@1+ (1,0) [0|1] "" BedienSG_hi,OTA_FC,ZR_High + SG_ LV_AFL_aktiv_Anzeige : 18|1@1+ (1,0) [0|1] "" BedienSG_hi,OTA_FC,ZR_High + SG_ LV_AFL_defekt : 19|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Blinker_li_def : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Standlicht_li_def : 21|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abblendlicht_li_def : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Fernlicht_li_def : 23|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Nebellicht_li_def : 24|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Blk_li_Seite_def : 25|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Tagfahrlicht_li_def : 26|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_FLA_aktiv_Anzeige : 27|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_FLA_defekt : 28|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_FLA_Sensor_blockiert : 29|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Blinker_re_def : 30|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Standlicht_re_def : 31|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abblendlicht_re_def : 32|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Fernlicht_re_def : 33|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Nebellicht_re_def : 34|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Blk_re_Seite_def : 35|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Tagfahrlicht_re_def : 36|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Aussenlicht_def : 37|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abblendlicht_TFL_li_def : 38|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Nebellicht_TFL_li_def : 39|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Standlicht_TFL_li_def : 40|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abblend_Fernlicht_li_def : 41|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abblendlicht_TFL_re_def : 42|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Nebellicht_TFL_re_def : 43|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Standlicht_TFL_re_def : 44|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abblend_Fernlicht_re_def : 45|1@1+ (1,0) [0|1] "" ZR_High + SG_ LV_Abbiegelicht_li_def : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LV_Abbiegelicht_re_def : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Linksverkehr : 48|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ BCM1_Licht_Dunkelheit_aktiv : 49|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_LED_Scheinwerfer_li_def : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LV_LED_Scheinwerfer_re_def : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LV_Blinker_VL_aktiv : 52|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_Blinker_VR_aktiv : 53|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ LV_MXB_Status_Anzeige : 54|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1629 ESP_20: 8 Gateway + SG_ ESP_20_CRC : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ ESP_20_BZ : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BR_Systemart : 12|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_SpannungsAnf_02 : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_Zaehnezahl : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ ESP_Charisma_FahrPr : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ ESP_Charisma_Status : 28|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_Wiederstart_Anz_01 : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Wiederstart_Anz_02 : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Wiederstart_Anz_03 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Wiederstart_Anz_04 : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_01 : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_02 : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_03 : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_04 : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_05 : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_06 : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_07 : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_Std : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Dachrelingsensor : 42|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_Stoppverbot_Anz_08 : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HDC_Charisma_FahrPr : 45|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HDC_Charisma_Status : 49|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BR_QBit_Reifenumfang : 51|1@1+ (1,0) [0|1] "" AWC + SG_ BR_Reifenumfang : 52|12@1+ (1,0) [0|4095] "Unit_MilliMeter" AWC + +BO_ 1631 Motor_16: 8 Gateway + SG_ TSK_Grundmasse : 0|8@1+ (32,0) [0|8128] "Unit_KiloGram" ZR_High + SG_ TSK_QBit_Steigung : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TSK_QBit_Fahrzeugmasse : 13|1@1+ (1,0) [0|1] "" ZR_High + SG_ MO_SpannungsAnf_02 : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_DPF_reg : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ MO_Heizstrom_EKAT : 17|7@1+ (1,0) [0|126] "Unit_Amper" Vector__XXX + SG_ MO_Heizstrom_SCR : 24|6@1+ (1,0) [0|62] "Unit_Amper" Vector__XXX + SG_ MO_Anzeige_Kaltleuchte : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_P_Generator_ungefiltert_Anf : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TSK_Getriebeinfo : 34|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ MO_Energieinhalt_BMS : 36|12@1+ (25,0) [0|102325] "Unit_WattHour" Vector__XXX + SG_ TSK_Fahrzeugmasse_02 : 48|8@1+ (32,0) [0|8128] "Unit_KiloGram" OTA_FC,ZR_High + SG_ TSK_Steigung_02 : 56|8@1+ (0.8,-101.6) [-100.8|101.6] "Unit_PerCent" OTA_FC + +BO_ 1640 Klima_12: 8 Gateway + SG_ KL_LRH_Taster : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_LRH_Stufe : 1|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ HSH_Taster : 3|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ FSH_Taster : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Zuheizer_Freigabe : 6|1@1+ (1,0) [0|1] "" TME + SG_ KL_Beschlagsgefahr : 7|1@1+ (1,0) [0|1] "" TME + SG_ KL_SIH_Soll_li : 8|3@1+ (1,0) [0|7] "" TME + SG_ KL_SIH_Soll_re : 11|3@1+ (1,0) [0|7] "" TME + SG_ KRH_Soll_li : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_SIL_Soll_li : 16|3@1+ (1,0) [0|7] "" TME + SG_ KL_SIL_Soll_re : 19|3@1+ (1,0) [0|7] "" TME + SG_ KRH_Soll_re : 22|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Geblspng_Soll : 24|8@1+ (0.05,1.45) [1.5|14] "Unit_Volt" Vector__XXX + SG_ KL_Geblspng_Fond_Soll : 32|8@1+ (0.05,1.45) [1.5|14] "Unit_Volt" Vector__XXX + SG_ KL_I_Geblaese : 40|8@1+ (0.25,0) [0|63.5] "Unit_Amper" Vector__XXX + SG_ KL_Kompressorstrom_soll : 48|10@1+ (1,0) [0|1021] "" TME + SG_ KL_Umluftklappe_Status : 58|4@1+ (1,0) [0|15] "" TME + SG_ KL_PTC_Verbauinfo : 62|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1648 Motor_18: 8 Gateway + SG_ MO_max_Ladedruck : 0|6@1+ (0.1,0) [0|6.3] "Unit_Bar" Sub_Gateway + SG_ MO_ANC_Kennfeld_Anf : 6|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_Bremslicht_Reku : 8|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_StartStopp_PopUp : 9|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO1_Sperr_Info_WFS : 11|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO1_Freigabe_Info_WFS : 12|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_EPCL : 13|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ MO_Zylabsch_Texte_02 : 16|4@1+ (1,0) [0|15] "" Sub_Gateway + SG_ MO_Fahrzeugtyp : 20|3@1+ (1,0) [0|7] "" BMS_NV,Sub_Gateway + SG_ MO_NMAX_Schaltanzeige : 23|9@1+ (25,0) [0|12775] "Unit_MinutInver" Sub_Gateway + SG_ MO_Abstellzeit : 32|8@1+ (8,0) [0|2024] "Unit_Minut" BMS_NV,Sub_Gateway,TME + SG_ MO_Abstellzeit_Status : 40|2@1+ (1,0) [0|3] "" BMS_NV,Sub_Gateway,TME + SG_ MO1_Freigabe_Verfallsinfo_WFS : 42|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_Hybrid_StartStopp_LED : 43|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_Fehler_Zylabsch : 45|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_Anzahl_Abgesch_Zyl : 47|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ MO_Zylabsch_Texte : 50|2@1+ (1,0) [0|3] "" Sub_Gateway + SG_ MO_Ethanol_BS_Texte : 52|3@1+ (1,0) [0|7] "" Sub_Gateway + SG_ MO_Drehzahl_Warnung : 55|1@1+ (1,0) [0|1] "" Sub_Gateway + SG_ MO_obere_Drehzahlgrenze : 56|8@1+ (50,0) [50|12750] "Unit_MinutInver" Sub_Gateway + +BO_ 1710 Spiegel_01: 8 Gateway + SG_ SP_FT_oben : 0|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_FT_unten : 1|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_FT_links : 2|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_FT_rechts : 3|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_BT_oben : 4|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_BT_unten : 5|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_BT_links : 6|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_BT_rechts : 7|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_abklappen : 8|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_anklappen : 9|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_normieren : 10|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_Hzg_Taster : 12|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ SP_S_oben : 16|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_S_unten : 17|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_S_links : 18|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_S_rechts : 19|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_Auswahl_li : 20|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_Auswahl_re : 21|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_ARA_Status : 22|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_S_Klappen : 23|1@1+ (1,0) [0|1] "" ZR_High + SG_ SP_Verstellschalter_Fehler : 24|1@1+ (1,0) [0|1] "" ZR_High + +BO_ 1711 Rear_View_01: 8 Gateway + SG_ RV_Video_on : 0|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ RV_Dark_Screen : 1|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ RV_HMI_Mode : 2|2@1+ (1,0) [0|3] "" ZR_High,ZR_Standard + SG_ RV_GL_side : 4|2@1+ (1,0) [0|3] "" ZR_High,ZR_Standard + SG_ RV_System_aktiv : 6|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ RV_Reinigung_Anf : 7|1@1+ (1,0) [0|1] "" OTA_FC,ZR_High + SG_ RV_Settings_enabled : 8|1@1+ (1,0) [0|1] "" ZR_High + SG_ RV_Menu_Item : 9|2@1+ (1,0) [0|3] "" ZR_High + SG_ SV_Video_on : 11|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ RV_Calib_Fehler : 12|1@1+ (1,0) [0|1] "" ZR_High + SG_ RV_GL_Trailer_connect : 13|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ RV_GL_Trunk_open : 14|1@1+ (1,0) [0|1] "" ZR_High,ZR_Standard + SG_ RV_GL_LWS_Fehler : 15|1@1+ (1,0) [0|1] "" ZR_High + SG_ RV_Helligkeit : 16|7@1+ (1,0) [0|100] "Unit_PerCent" ZR_High,ZR_Standard + SG_ ZFAS_Umfeldbeleuchtung_Anf : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ RV_Kontrast : 24|7@1+ (1,0) [0|100] "Unit_PerCent" ZR_High,ZR_Standard + SG_ RV_Farbe : 32|7@1+ (1,0) [0|100] "Unit_PerCent" ZR_High,ZR_Standard + +BO_ 1714 Diagnose_01: 8 Gateway_MQB + SG_ DGN_Verlernzaehler : 0|8@1+ (1,0) [0|254] "" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,SAK_MQB + SG_ KBI_Kilometerstand : 8|20@1+ (1,0) [0|1048573] "Unit_KiloMeter" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Jahr : 28|7@1+ (1,2000) [2000|2127] "Unit_Year" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Monat : 35|4@1+ (1,0) [1|12] "Unit_Month" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Tag : 39|5@1+ (1,0) [1|31] "Unit_Day" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Stunde : 44|5@1+ (1,0) [0|23] "Unit_Hours" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Minute : 49|6@1+ (1,0) [0|59] "Unit_Minut" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Sekunde : 55|6@1+ (1,0) [0|59] "Unit_Secon" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ Kombi_02_alt : 62|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,LEH_MQB + SG_ Uhrzeit_01_alt : 63|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,LEH_MQB + +BO_ 1716 VIN_01: 8 Gateway_MQB + SG_ VIN_01_MUX M : 0|2@1+ (1,0) [0|3] "" Airbag_MQB + SG_ KS_Geheimnis_1 m0 : 8|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KS_Geheimnis_2 m0 : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KS_Geheimnis_3 m0 : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KS_Geheimnis_4 m0 : 32|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ VIN_1 m0 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_2 m0 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_3 m0 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_4 m1 : 8|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_5 m1 : 16|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_6 m1 : 24|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_7 m1 : 32|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_8 m1 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_9 m1 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_10 m1 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_11 m2 : 8|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_12 m2 : 16|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_13 m2 : 24|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_14 m2 : 32|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_15 m2 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_16 m2 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_17 m2 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + +BO_ 316495015 MEB_Camera_04: 32 XXX + +BO_ 316495049 SAL_01: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CNT : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Brake_Unknown : 18|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_Light_01 : 20|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_2 : 22|1@0+ (1,0) [0|1] "" XXX + SG_ Right_Blinker : 25|1@0+ (1,0) [0|1] "" XXX + SG_ Left_Blinker : 26|1@1+ (1,0) [0|3] "" XXX + SG_ Reverse_Light : 27|1@0+ (1,0) [0|1] "" XXX + SG_ Brake_Light_02 : 30|1@0+ (1,0) [0|1] "" XXX + SG_ Right_Blinker_02 : 44|1@1+ (1,0) [0|3] "" XXX + SG_ Left_Blinker_02 : 45|1@0+ (1,0) [0|1] "" XXX + SG_ NEW_SIGNAL_3 : 52|8@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_4 : 63|1@0+ (1,0) [0|1] "" XXX + +BO_ 316495081 MEB_Camera_05: 8 XXX + +BO_ 316495106 AAA_01: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CHK : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 316495140 MEB_Camera_06: 64 XXX + +BO_ 316495165 HVL_01: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CHK : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 380195935 IPA_02: 8 XXX + +BO_ 380196019 MEB_Camera_07: 16 XXX + +BO_ 380196036 MEB_Camera_08: 8 XXX + +BO_ 389241616 MEB_Camera_09: 8 XXX + +BO_ 389241617 MEB_Camera_10: 8 XXX + +BO_ 401604687 MEB_Camera_11: 8 XXX + +BO_ 402522959 MEB_Camera_14: 8 XXX + +BO_ 441800001 EML_02: 8 XXX + SG_ CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ CHK : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 441800082 MEB_Camera_12: 8 XXX + +BO_ 452984911 MEB_Camera_13: 8 XXX + +CM_ BO_ 184 "Motorsteuergerät"; +CM_ BO_ 192 "Motorsteuergerät"; +CM_ BO_ 317 "Lenkungssteuergerät"; +CM_ BO_ 517 "Steuergerät für Motorstart"; +CM_ BO_ 522 "Steuergerät für Fahrzeugbewegung"; +CM_ BO_ 1622 "Steuergerät für Lenkungsverriegelung"; +CM_ BO_ 316495165 "Steuergerät ICAS1"; +CM_ BO_ 441800001 "Steuergerät für Fahrzeugbewegung"; +VAL_ 64 AB_RGS_Anst 4 "aktiv_Niveau_1" 5 "aktiv_Niveau_2" 6 "aktiv_Niveau_3" 7 "aktiv_Niveau_4" 8 "deaktiviert"; +VAL_ 64 AB_Front_Crash 0 "kein_Front_Crash" 1 "Front_Crash"; +VAL_ 64 AB_Heck_Crash 0 "kein_Heck_Crash" 1 "Heck_Crash"; +VAL_ 64 AB_SF_Crash 0 "kein_Seiten_Crash_Fahrer" 1 "Seiten_Crash_Fahrer"; +VAL_ 64 AB_SB_Crash 0 "kein_Seiten_Crash_Beifahrer" 1 "Seiten_Crash_Beifahrer"; +VAL_ 64 AB_Rollover_Crash 0 "kein_Rollover" 1 "Rollover"; +VAL_ 64 AB_Crash_Int 0 "kein_Crash" 1 "Crash_Intensitaet_1" 2 "Crash_Intensitaet_2_(nur_Stellgliedtest_MLB_B8)" 3 "Crash_Intensitaet_2_(nur_D4_C7_Colorado_NF_PAG__Crash_im_MLB_B8)" 4 "Crash_Intensitaet_3_(alt_VW/AUDI__Stellgliedtest_MLB_B8)" 5 "Crash_Intensitaet_3_(alt_PAG)" 7 "Crash_Intensitaet_3"; +VAL_ 64 AB_Lampe 0 "Aus" 1 "Ein"; +VAL_ 64 AB_Deaktiviert 0 "aktiv" 1 "deaktiviert"; +VAL_ 64 AB_VB_deaktiviert 0 "Beifahrerairbag_aktiv" 1 "Beifahrerairbag_deaktiviert"; +VAL_ 64 AB_Systemfehler 0 "kein_Fehler" 1 "Airbag_Systemfehler"; +VAL_ 64 AB_Diagnose 0 "nicht_in_Diagnose" 1 "in_Diagnose"; +VAL_ 64 AB_Stellgliedtest 0 "nicht_im_Stellgliedtest" 1 "Airbag_im_Stellgliedtest"; +VAL_ 64 AB_Erh_Auf_VB 0 "keine_Anzeige" 1 "Beifahrerairbag_deaktiviert" 2 "Beifahrerairbag_aktiviert" 3 "nicht_definiert"; +VAL_ 64 AB_Gurtwarn_VF 0 "keine_Warnung" 1 "Gurtwarnung_ausloesen"; +VAL_ 64 AB_Gurtwarn_VB 0 "keine_Warnung" 1 "Gurtwarnung_ausloesen"; +VAL_ 64 AB_Anzeige_Fussg 0 "keine_FSG_Aktion_ausgeloest" 1 "Motorhaube_offen" 2 "Systemfehler"; +VAL_ 64 AB_Texte_AKS 0 "keine_AKS_Ausloesung" 1 "AKS_ausgeloest" 2 "AKS_Systemfehler"; +VAL_ 64 AB_MKB_gueltig 0 "Multikollisionsbremsung_nicht_freigeschaltet" 1 "Multikollisionsbremsung_freigeschaltet"; +VAL_ 64 AB_MKB_Anforderung 0 "Multikollisionsbremsung_nicht_angefordert" 1 "Multikollisionsbremsung_angefordert"; +VAL_ 64 AB_Versorgungsspannung 0 "plausibel" 1 "unplausibel"; +VAL_ 64 AB_Deaktivierung_HV 0 "keine_Deaktivierung" 1 "Deaktivierung_1" 2 "Deaktivierung_2" 3 "Deaktivierung_3" 4 "Deaktivierung_4" 5 "Deaktivierung_5" 6 "Deaktivierung_6" 7 "Fehler"; +VAL_ 64 AB_EDR_Trigger 0 "No_Event" 1 "Start_Event" 2 "NonDeployment_Event" 3 "Deployment_Event"; +VAL_ 64 AB_Belegung_VF 0 "nicht_verfuegbar" 1 "Fehler" 2 "nicht_belegt" 3 "belegt"; +VAL_ 64 SC_LowSpeedCrashErkannt 0 "kein_Crash_erkannt" 1 "Crash_Frontbereich_erkannt" 2 "Crash_Heckbereich_erkannt" 3 "Crash_Front_und_Heckbereich_erkannt"; +VAL_ 64 SC_Masterzeit 127 "Init"; +VAL_ 134 LWI_Sensorstatus 0 "iO" 1 "nicht kalibriert"; +VAL_ 134 LWI_QBit_Sub_Daten 0 "LWS-Subinfo real (Lenkradwinkelinformation ADS-tauglich)" 1 "LWS-Subinfo simuliert (Lenkradwinkelinformation nicht ADS-tauglich )"; +VAL_ 134 LWI_MFL_Abschaltung 0 "inaktiv" 1 "aktiv"; +VAL_ 134 LWI_QBit_Lenkradwinkel 0 "gültiger Wert" 1 "ausserhalb der Spezifikation"; +VAL_ 134 LWI_Lenkradwinkel 8190 "Init" 8191 "Fehler"; +VAL_ 134 LWI_VZ_Lenkradwinkel 0 "positiv_links_von_der_Nullstellung" 1 "negativ"; +VAL_ 134 LWI_VZ_Lenkradw_Geschw 0 "positiv_links_von_der_Nullstellung" 1 "negativ"; +VAL_ 134 LWI_Lenkradw_Geschw 510 "Init" 511 "Fehler"; +VAL_ 159 EPS_HCA_Status 0 "disabled" 1 "initializing" 2 "fault" 3 "ready" 4 "rejected" 5 "active" 8 "preempted"; +VAL_ 167 MO_Mom_Soll_Roh 1022 "Init"; +VAL_ 167 MO_Mom_Ist_Summe 1022 "Init"; +VAL_ 167 MO_Mom_Traegheit_Summe 1022 "Init"; +VAL_ 167 MO_Mom_Soll_gefiltert 1022 "Init"; +VAL_ 167 MO_Mom_Schub 510 "Init"; +VAL_ 167 MO_Status_Normalbetrieb_01 0 "kein_Normalbetrieb" 1 "Normalbetrieb_erreicht"; +VAL_ 167 MO_erste_Ungenauschwelle 0 "genau" 1 "Momente ungenauer >8%"; +VAL_ 167 MO_QBit_Motormomente 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 168 MO_Mom_neg_verfuegbar 510 "Init" 511 "Fehler"; +VAL_ 168 MO_Mom_Begr_stat 510 "Init"; +VAL_ 168 MO_Mom_Begr_dyn 1022 "Init"; +VAL_ 168 MO_QBit_Drehzahl_01 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 173 GE_MMom_Soll_02 1022 "keine_Anforderung_Init" 1023 "Fehler"; +VAL_ 173 GE_MMom_Vorhalt_02 1022 "Init" 1023 "Fehler"; +VAL_ 173 GE_Uefkt 1023 "Fehler"; +VAL_ 173 GE_Fahrstufe 0 "Zwischenstellung" 1 "Init" 5 "P" 6 "R" 7 "N" 8 "D" 9 "D" 10 "E" 13 "T" 14 "T" 15 "Fehler"; +VAL_ 173 GE_Schaltablauf 0 "keine_Schaltung" 1 "Momentenueberschneidung" 2 "Befuellphase" 3 "Drehzahlueberfuehrung"; +VAL_ 173 GE_Uefkt_unplausibel 0 "Uefkt_plausibel" 1 "Uefkt_unplausibel"; +VAL_ 173 GE_MMom_Status_02 0 "kein_Eingriff" 1 "abs_reduzierender_Eingriff_auf_Gesamt_Antrieb_nur_schneller_Pfad" 2 "abs_erhoehender_Eingriff_auf_Gesamt_Antrieb" 3 "relativer_Eingriff_auf_Gesamt_Antrieb" 4 "relativer_Eingriff_auf_E_Maschine" 5 "abs_red_Eingr_auf_Gesamt_Antrieb_nur_Luftpfad" 6 "abs_red_Eingr_auf_Gesamt_Antrieb_Luft-_und_schnellen_Pfad" 7 "abs_Eingriff_auf_Gesamtantrieb_erhoehend_und_reduzierend"; +VAL_ 173 GE_Status_Kraftschluss 0 "offen_kein_Kraftschluss" 1 "offen_mit_Kraftschluss" 2 "schlupfend_geregelt" 3 "abgesichert_offen_kein_Kraftschl" 4 "geschlossen_mit_Mikroschlupf" 5 "geschlossen_mit_Ueberanpressung" 6 "sonstige_Fehler" 7 "fehlerhaft_geschlossen"; +VAL_ 173 GE_MMom_Status 0 "keine Anforderung" 1 "reduzierender Getriebeeingriff" 2 "erhöhender Getriebeeingriff" 3 "Įderung mit Sprung"; +VAL_ 173 GE_Freig_MMom_Vorhalt 0 "nicht_freigegeben" 1 "freigegeben"; +VAL_ 173 GE_Verbot_Ausblendung 0 "kein_Verbot" 1 "Verbot"; +VAL_ 173 GE_Zielgang 0 "Gang P/N (ausgekuppelt)" 1 "Gang 1" 2 "Gang 2" 3 "Gang 3" 4 "Gang 4" 5 "Gang 5" 6 "Gang 6" 7 "Gang 7" 8 "Gang R" 11 "Gang 8" 12 "Gang 9" 13 "Gang10" 14 "Istgang nicht definiert" 15 "Fehler"; +VAL_ 184 EM1_Freigabe_Info_WFS 0 "ungueltig" 1 "gueltig"; +VAL_ 184 EM1_Sperr_Info_WFS 0 "nicht_gesperrt" 1 "gesperrt"; +VAL_ 184 EM1_AR_aktiv 0 "Init" 1 "Ruckeldaempfer_aktiv"; +VAL_ 184 EM1_Eta_Sys 510 "Init" 511 "Fehler"; +VAL_ 184 EM1_IstStrom 2046 "Init" 2047 "Fehler"; +VAL_ 184 EM1_Fehler_ElAntriebFreilauf_Anf 0 "Init" 1 "Fehler_EM_im_Freilauf"; +VAL_ 184 EM1_Abregelung_Temperatur 0 "Init" 1 "Abregelung_Temperatur"; +VAL_ 184 EM1_AnlernenElMotor_Anf 0 "kein_Diagnose_Request" 1 "Diagnose_Request"; +VAL_ 184 EM1_Moment_HVVerbraucher 1023 "Init"; +VAL_ 184 EM1_Freigabe_Verfallsinfo_WFS 0 "Aus" 1 "Ein"; +VAL_ 184 EM1_Parken_WFS_Status 0 "Limitierung_Inaktiv" 1 "Limitierung_Aktiv" 2 "Abbruch"; +VAL_ 184 EM1_HV_betriebsbereit 0 "Init" 1 "Ready_HV"; +VAL_ 190 Engine_Status 1 "Ready" 2 "Online"; +VAL_ 253 BR_Eingriffsmoment 1022 "Init" 1023 "Fehler"; +VAL_ 253 ESP_Diagnose 0 "ESP_nicht_in_Diagnose" 1 "ESP_in_Diagnose"; +VAL_ 253 ESC_v_Signal_Qualifier_High_Low 0 "Gueteschwelle_kleiner_1kmh" 1 "Gueteschwelle_kleiner_3kmh" 2 "Gueteschwelle_kleiner_5kmh" 3 "Gueteschwelle_kleiner_10kmh" 4 "Gueteschwelle_kleiner_20kmh" 5 "Gueteschwelle_groessergleich_20kmh" 6 "Init" 7 "Fehler"; +VAL_ 253 ESP_Vorsteuerung 0 "keine_Vorsteuerung_aktiv" 1 "Vorsteuerung_aktiv"; +VAL_ 253 OBD_Schlechtweg 0 "kein_Schlechtweg_erkannt" 1 "Schlechtweg_erkannt"; +VAL_ 253 OBD_QBit_Schlechtweg 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 253 ESP_v_Signal 65533 "Unterspannung" 65534 "Init" 65535 "Fehler"; +VAL_ 253 ASR_Tastung_passiv 0 "ASR_aktiviert" 1 "ASR_passiv_getastet_oder_Schwellen_geaendert"; +VAL_ 253 ESP_Tastung_passiv 0 "ESP_aktiviert" 1 "ESP_passiv_getastet_oder_Schwellen_geaendert"; +VAL_ 253 ESP_Systemstatus 0 "iO" 1 "Fehler"; +VAL_ 253 ASR_Schalteingriff 0 "keine_Anforderung" 1 "ASR_Schaltkennfeld" 2 "Rueckschaltung" 3 "Schaltverbot"; +VAL_ 253 ESP_QBit_v_Signal 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 253 ABS_Bremsung 0 "keine_ABS_Regelung" 1 "ABS_Regelung_aktiv"; +VAL_ 253 ASR_Anf 0 "keine_Anforderung" 1 "ASR_Anforderung"; +VAL_ 253 MSR_Anf 0 "keine Anfoderung" 1 "MSR-Anforderung"; +VAL_ 253 EBV_Eingriff 0 "kein_EBV_Eingriff" 1 "EBV_Eingriff"; +VAL_ 253 EDS_Eingriff 0 "kein_EDS_Eingriff" 1 "EDS_Eingriff"; +VAL_ 253 ESP_Eingriff 0 "kein_ESP_Eingriff" 1 "ESP_Eingriff_aktiv"; +VAL_ 253 ESP_ASP 0 "inaktiv" 1 "aktiv"; +VAL_ 253 ESC_Neutralschaltung 0 "keine_Anforderung" 1 "Neutralschaltung_angefordert"; +VAL_ 267 TSK_Status 0 "init" 1 "disabled" 2 "enabled" 3 "regulating" 4 "accel_pedal_override" 5 "brake_only" 6 "temp_fault" 7 "perm_fault"; +VAL_ 278 ESP_QBit_Wegimpuls_VL 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 278 ESP_QBit_Wegimpuls_VR 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 278 ESP_QBit_Wegimpuls_HL 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 278 ESP_QBit_Wegimpuls_HR 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 278 ESP_Wegimpuls_VL 1021 "Init" 1022 "Unterspannung" 1023 "Fehler"; +VAL_ 278 ESP_Wegimpuls_VR 1021 "Init" 1022 "Unterspannung" 1023 "Fehler"; +VAL_ 278 ESP_Wegimpuls_HL 1021 "Init" 1022 "Unterspannung" 1023 "Fehler"; +VAL_ 278 ESP_Wegimpuls_HR 1021 "Init" 1022 "Unterspannung" 1023 "Fehler"; +VAL_ 278 ESP_VL_Fahrtrichtung 0 "Vorwaerts" 1 "Rueckwaerts" 2 "Init" 3 "ungueltig_oder_nicht_verbaut"; +VAL_ 278 ESP_VR_Fahrtrichtung 0 "Vorwaerts" 1 "Rueckwaerts" 2 "Init" 3 "ungueltig_oder_nicht_verbaut"; +VAL_ 278 ESP_HL_Fahrtrichtung 0 "Vorwaerts" 1 "Rueckwaerts" 2 "Init" 3 "ungueltig_oder_nicht_verbaut"; +VAL_ 278 ESP_HR_Fahrtrichtung 0 "Vorwaerts" 1 "Rueckwaerts" 2 "Init" 3 "ungueltig_oder_nicht_verbaut"; +VAL_ 299 GRA_Hauptschalter 0 "Hauptschalter_aus__Taster_nicht_betaetigt" 1 "Hauptschalter_ein__Taster_betaetigt"; +VAL_ 299 GRA_Abbrechen 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 299 GRA_Typ_Hauptschalter 0 "gerasteter_Lenkstockschalter" 1 "getasteter_Lenkstockschalter"; +VAL_ 299 GRA_Limiter 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 299 GRA_Tip_Setzen 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 299 GRA_Tip_Hoch 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 299 GRA_Tip_Runter 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 299 GRA_Tip_Wiederaufnahme 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 299 GRA_Verstellung_Zeitluecke 0 "Taste_nicht_betaetigt" 1 "Dist_minus_1" 2 "Dist_plus_1" 3 "Dist_Toggle"; +VAL_ 299 GRA_Codierung 0 "kein_Hebel" 1 "GRA_Hebel" 2 "ACC_Hebel" 3 "Limiter_Only"; +VAL_ 299 GRA_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 299 GRA_LIM_Taste_verfuegbar 0 "Limiter_Taste_nicht_vorhanden" 1 "Limiter_Taste_vorhanden"; +VAL_ 299 GRA_Tip_Stufe_2 0 "Tip_Stufe_1__keine_Betaetigung" 1 "Tip_Stufe_2"; +VAL_ 299 GRA_TravelAssist 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 317 LatCon_HCA_Status 0 "disabled" 1 "initializing" 2 "ready" 3 "fault" 4 "active" 5 "preempted" 6 "fault" 7 "rejected"; +VAL_ 319 PreCrash_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 319 PreCrash_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 319 PreCrash_Schiebedach_schliessen 0 "keine_Schliessung" 1 "Schliessung_angefordert"; +VAL_ 319 PreCrash_Fenster_schliessen 0 "keine_Schliessung" 1 "Schliessung_angefordert"; +VAL_ 319 PreCrash_Blinken 0 "keine_Blinkanforderung" 1 "Warnblinken" 2 "RECAS_Blinken" 3 "Notbremsblinken"; +VAL_ 319 SC_PreSense_FCWP 0 "Warnung_gilt_fuer_Objekte" 1 "Warnung_gitl_fuer_Fussgaenger"; +VAL_ 319 PreCrash_Tueren_Verriegeln 0 "keine_Anforderung" 1 "Tueren_Verriegeln"; +VAL_ 319 PreCrash_Anforderung_AFR 0 "keine_Anforderung" 1 "linke_Seite" 2 "rechte_Seite" 3 "Vorderachse" 4 "Hinterachse" 5 "Vorwarnung" 7 "Init"; +VAL_ 319 SC_PreCrash_LED 0 "keine_Anzeige" 1 "Stufe_1_glimmen" 2 "Stufe_2_leuchten" 3 "Stufe_3_blinken"; +VAL_ 319 PreCrash_FS_Pneumatik_ansteuern 0 "keine_Anforderung" 1 "Pneumatik_ansteuern"; +VAL_ 319 PreCrash_BFS_Pneumatik_ansteuern 0 "keine_Anforderung" 1 "Pneumatik_ansteuern"; +VAL_ 319 PreCrash_Fo_Pneumatik_ansteuern 0 "keine_Anforderung" 1 "Pneumatik_ansteuern"; +VAL_ 319 PreCrash_FS_Sitzlehne_verfahren 0 "keine_Anforderung" 1 "Sitzlehne_in_pos_x-Richtung_verfahren(vor)" 2 "Sitzlehne_in_neg_x-Richtung_verfahren(zurueck)" 3 "Sitzlehnenkopf_in_pos_x-Richtung_verfahren(vor)" 4 "Sitzlehnenkopf_in_neg_x-Richtung_verfahren(zurueck)" 6 "Lehnenverstellung_ansteuern" 7 "Lehnenkopfverstellung_ansteuern"; +VAL_ 319 PreCrash_BFS_Sitzlehne_verfahren 0 "keine_Anforderung" 1 "Sitzlehne_in_pos_x-Richtung_verfahren(vor)" 2 "Sitzlehne_in_neg_x-Richtung_verfahren(zurueck)" 3 "Sitzlehnenkopf_in_pos_x-Richtung_verfahren(vor)" 4 "Sitzlehnenkopf_in_neg_x-Richtung_verfahren(zurueck)" 6 "Lehnenverstellung_ansteuern" 7 "Lehnenkopfverstellung_ansteuern"; +VAL_ 319 PreCrash_Fo_Sitzlehne_verfahren 0 "keine_Anforderung" 1 "Sitzlehne_in_pos_x-Richtung_verfahren(vor)" 2 "Sitzlehne_in_neg_x-Richtung_verfahren(zurueck)" 3 "Sitzlehnenkopf_in_pos_x-Richtung_verfahren(vor)" 4 "Sitzlehnenkopf_in_neg_x-Richtung_verfahren(zurueck)"; +VAL_ 319 PreCrash_FS_KSV_verfahren 0 "keine_Anforderung" 1 "in_pos_x-Richtung_verfahren" 2 "in_neg_x-Richung_verfahren" 3 "in_pos_z-Richtung_verfahren" 4 "in_neg_z-Richtung_verfahren" 5 "in_pos_x-Richtung_und_neg_z-Richtung_verfahren" 6 "in_pos_x_Richtung_und_pos_z-Richtung_verfahren" 7 "in_neg_x-Richtung_und_neg_z-Richtung_verfahren" 8 "in_neg_x-Richtung_und_pos_z-Richtung_verfahren" 9 "Kopfstuetze_ansteuern"; +VAL_ 319 PreCrash_BFS_KSV_verfahren 0 "keine_Anforderung" 1 "in_pos_x-Richtung_verfahren" 2 "in_neg_x-Richung_verfahren" 3 "in_pos_z-Richtung_verfahren" 4 "in_neg_z-Richtung_verfahren" 5 "in_pos_x-Richtung_und_neg_z-Richtung_verfahren" 6 "in_pos_x_Richtung_und_pos_z-Richtung_verfahren" 7 "in_neg_x-Richtung_und_neg_z-Richtung_verfahren" 8 "in_neg_x-Richtung_und_pos_z-Richtung_verfahren" 9 "Kopfstuetze_ansteuern"; +VAL_ 319 PreCrash_Fo_KSV_verfahren 0 "keine_Anforderung" 1 "in_pos_x-Richtung_verfahren" 2 "in_neg_x-Richung_verfahren" 3 "in_pos_z-Richtung_verfahren" 4 "in_neg_z-Richtung_verfahren" 5 "in_pos_x-Richtung_und_neg_z-Richtung_verfahren" 6 "in_pos_x_Richtung_und_pos_z-Richtung_verfahren" 7 "in_neg_x-Richtung_und_neg_z-Richtung_verfahren" 8 "in_neg_x-Richtung_und_pos_z-Richtung_verfahren"; +VAL_ 319 SC_PreCrash_Warnung 0 "keine_Anzeige" 1 "latente_Vorwarnung" 2 "Vorwarnung" 3 "Akutwarnung" 4 "Eingriff" 5 "Fahreruebernahmeaufforderung" 6 "Abbiegewarnung" 7 "Basiseingriff" 8 "Heckeingriff"; +VAL_ 319 SC_PreCrash_Texte 0 "keine_Anzeige" 1 "Systemstoerung" 2 "keine_Sensorsicht" 3 "Demomodus" 4 "System_aus" 5 "Anhaengerbetrieb" 6 "ESC_aus" 7 "zurzeit_eingeschraenkt" 8 "zurzeit_eingeschraenkt_ESP_Aus" 9 "Initialisierung"; +VAL_ 333 ACC_limitierte_Anfahrdyn 0 "keine_Limitierung" 1 "Limitierung_Anfahrdynamik_angefordert"; +VAL_ 333 ACC_nachtr_Stopp_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 333 ACC_StartStopp_Info 0 "Motorlauf_langfristig_nicht_notwendig_Stoppfreigabe" 1 "Motoranlauf_nicht_zwingend_notwendig_Stoppverbot_keine_Startanforderung" 2 "Motoranlauf_zwingend_notwendig_Startanforderung" 3 "Systemfehler"; +VAL_ 333 ACC_Sollbeschleunigung_02 2046 "Neutralwert" 2047 "Fehler"; +VAL_ 333 ACC_Anfahren 0 "keine_Anforderung_Anfahren" 1 "Anforderung_Anfahren"; +VAL_ 333 ACC_Anhalten 0 "kein_Anhalten_gewuenscht" 1 "Anhalten_gewuenscht"; +VAL_ 333 ACC_Typ 0 "Basis_ACC" 1 "ACC_mit_FollowToStop" 2 "ACC_mit_StopAndGo" 3 "ACC_nicht_codiert"; +VAL_ 333 ACC_Status_ACC 0 "ACC_OFF_Hauptschalter_aus" 1 "ACC_INIT" 2 "ACC_STANDBY" 3 "ACC_AKTIV_regelt" 4 "ACC_OVERRIDE" 5 "ACC_Abschaltreaktion" 6 "reversibler_Fehler_im_ACC_System" 7 "irreversibler_Fehler_im_ACC_System"; +VAL_ 333 ACC_Minimale_Bremsung 0 "Anforderung_Minimale_Bremsung_nicht_aktiv" 1 "Anforderung_Minimale_Bremsung_aktiv"; +VAL_ 333 ACC_Anhalteweg 2046 "Neutralwert" 2047 "Fehler"; +VAL_ 333 ACC_Anforderung_HMS 0 "keine_Anforderung" 1 "halten" 2 "parken" 3 "halten_Standby" 4 "anfahren" 5 "Loesen_ueber_Rampe"; +VAL_ 333 Accel_Boost 3 "Driving" 0 "Stop" 2 "Driving" 1 "Driving"; +VAL_ 339 MO_HVEM_Eskalation 0 "keine_Eskalation_HVEM" 1 "Eskalation_HVEM"; +VAL_ 339 MO_ErwGrenzen_Anf 0 "normal" 1 "erweitert"; +VAL_ 339 MO_Fehler_Notentladung_Anf 0 "Init"; +VAL_ 339 MO_HVEM_MaxLeistung 510 "Init"; +VAL_ 339 MO_HVK_EmIstzustand 0 "HvOff" 1 "HvStbyReq" 2 "HvStbyOk" 3 "HvBattOnReq" 4 "HvBattOnOk" 10 "HvOnIdle" 18 "HvOnDrvReq" 19 "HvOnDrvOk" 20 "HvOnDrvRdy" 28 "HvStepUpReq" 29 "HvStepUpOk" 30 "HvStepUp" 38 "HvStepDownReq" 39 "HvStepDownOk" 40 "HvStepDown" 46 "HvAcChPreReq" 47 "HvAcChPreOk" 48 "HvAcChReq" 49 "HvAcChOk" 50 "HvAcCh" 56 "HvDcChPreReq" 57 "HvDcChPreOk" 58 "HvDcChReq" 59 "HvDcChOk" 60 "HvDcCh" 67 "HvChOffReq" 68 "HvChOffOk" 69 "HvOnIdleReq" 70 "HvOnIdleOk" 96 "HvCpntOffReq" 97 "HvCpntOffOk" 98 "HvBattOffReq" 99 "HvBattOffOk" 109 "HvDcDcFailOffReq" 110 "HvDcDcFail" 119 "HvElmOffReq" 120 "HvElmOff" 126 "HvFailCpntOffReq" 127 "HvFailCpntOffOk" 128 "HvFailBattOffReq" 129 "HvFailBattOffOk" 130 "HvFailBattOff" 138 "HvFailUCtlReq" 139 "HvFailUCtlOk" 140 "HvFailUCtl" 150 "HvEmgcyOff" 255 "Init"; +VAL_ 339 MO_HVK_AntriebFehlerstatus 0 "Komponente_IO" 6 "Keine_Komponentenfunktion" 7 "Init"; +VAL_ 339 MO_MVK_Bordnetz_Anf 0 "keine_Anforderung" 1 "Bordnetzaktivitaet_gefordert"; +VAL_ 339 MO_HVK_AntriebZustand 0 "Antrieb_AUS" 1 "Antrieb_Startphase" 2 "E_Fahren" 3 "Hybrid_Fahren" 7 "Init"; +VAL_ 339 MO_HVK_EmFehlerstatus 0 "Komponente_IO" 1 "Eingeschr_KompFkt_Teilbetrieb" 3 "Eingeschr_KompFkt_Interlock" 6 "Keine_Komponentenfunktion" 7 "Init"; +VAL_ 339 MO_MVK_AntriebFehlerstatus 0 "Komponente_IO" 6 "Keine_Komponentenfunktion" 7 "Init"; +VAL_ 339 MO_MVK_AntriebZustand 0 "Antrieb_AUS" 1 "Antrieb_Startphase" 2 "FreilaufMotorAus" 7 "Init"; +VAL_ 339 MO_MVK_EmFehlerstatus 0 "Komponente_IO" 1 "Eingeschr_KompFkt_Teilbetrieb" 6 "Keine_Komponentenfunktion" 7 "Init"; +VAL_ 339 MO_MVK_EmIstzustand 0 "MvOff" 1 "MvStbyReq" 2 "MvStbyOk" 3 "MvBattOnReq" 4 "MvBattOnOk" 10 "MvOnIdle" 18 "MvOnDrvReq" 19 "MvOnDrvOk" 20 "MvOnDrv" 28 "MvStepUpReq" 29 "MvStepUpOk" 30 "MvStepUp" 38 "MvStepDownReq" 39 "MvStepDownOk" 40 "MvStepDown" 96 "MvCpntOffReq" 97 "MvCpntOffOk" 98 "MvBattOffReq" 99 "MvBattOffOk" 109 "MvDcDcFailOffReq" 110 "MvDcDcFail" 119 "MvElmFailOffReq" 120 "MvElmFail" 126 "MvFailCpntOffReq" 127 "MvFailCpntOffOk" 128 "MvFailBattOffReq" 129 "MvFailBattOffOk" 130 "MvFailBattOff" 138 "MvFailUCtlReq" 139 "MvFailUCtlOk" 140 "MvFailUCtl" 150 "MvEmgcyOff" 255 "Init"; +VAL_ 420 EA_Parken_beibehalten_HMS 0 "Parken_nicht_beibehalten" 1 "Parken_beibehalten" 2 "Init" 3 "Fehler"; +VAL_ 420 EA_Warnruckprofil 0 "keine_Ruckanforderung" 1 "Profil_1" 2 "Profil_2" 3 "Profil_3" 4 "Profil_4" 5 "Profil_5" 6 "Profil_6" 7 "Profil_7"; +VAL_ 420 EA_eCall_Anf 0 "Keine_Anforderung" 1 "Ausloesen_eCall"; +VAL_ 420 EA_Funktionsstatus 0 "EA_INIT" 1 "EA_OFF" 2 "EA_STANDBY" 3 "EA_PHASE0_AKTIV" 4 "EA_PHASE1_AKTIV" 5 "EA_PHASE2_AKTIV" 6 "EA_PHASE3_AKTIV" 7 "EA_REVERSIBLER_FEHLER" 8 "EA_IRREVERSIBLER_FEHLER"; +VAL_ 420 EA_Gurtstraffer_Anf 0 "Keine_Anforderung" 1 "Haptik_1" 2 "Haptik_2" 3 "Haptik_3"; +VAL_ 420 EA_Anforderung_HMS 0 "keine_Anforderung" 1 "halten" 2 "parken" 3 "halten_Standby" 4 "anfahren" 5 "Loesen_ueber_Rampe" 6 "Parken_mit_P"; +VAL_ 420 EA_Sollbeschleunigung 2046 "Neutralwert" 2047 "Fehler"; +VAL_ 496 EA_Texte 0 "keine_Anzeige" 1 "Nothalteassistent_fehlende_Fahreraktivitaet" 2 "Nothalteassistent_aktiv_Fahrzeugfuehrung_uebernehmen" 3 "Nothalteassistent_automatischer_Nothalt_wird_durchgefuehrt" 4 "Nothalteassistent_automatischer_Nothalt_durchgefuehrt" 5 "Nothalteassistent_Verbindung_zum_Notruf_wird_aufgebaut" 6 "Nothalteassistent_deaktiviert" 7 "Nothalteassistent_Eingriff_abgebrochen" 8 "Nothalteassistent_fehlende_Fahreraktivitaet_2" 9 "Sekundenschlaf_erkannt" 10 "LaneAssist_Lenkung_uebernehmen" 11 "ACA_Fahrzeugfuehrung_uebernehmen" 12 "EA_Fahr_Standstreifenwechsel" 14 "Nothalteassistent_nicht_verfuegbar_reversibel" 15 "Nothalteassistent_Stoerung_irreversibel"; +VAL_ 496 ACF_Lampe_Hands_Off 0 "keine_Anzeige" 1 "Hands_Off_erkannt"; +VAL_ 496 EA_Infotainment_Anf 0 "Init" 1 "Keine_Absenkung" 2 "Absenkung" 3 "Mute"; +VAL_ 496 EA_Tueren_Anf 0 "Keine_Anforderung" 1 "Tueren_entriegeln"; +VAL_ 496 EA_Innenraumlicht_Anf 0 "Innenraumbeleuchtung_ausschalten" 1 "Innenraumbeleuchtung_einschalten"; +VAL_ 496 zFAS_Warnblinken 0 "Aus" 1 "Statisch" 2 "Taster" 3 "Statisch_ohne_WBT"; +VAL_ 496 STP_Primaeranz 0 "keine_Anzeige" 1 "Verfuegbar" 2 "Aktiv" 3 "Uebernahme" 4 "Aktiv_Warnung" 5 "Nicht_Verfuegbar"; +VAL_ 496 EA_Bremslichtblinken 0 "kein_Blinken" 1 "Anforderung_Bremslichtblinken"; +VAL_ 496 EA_Blinken 0 "Kein_Blinken" 1 "Wechselblinken_links" 2 "Wechselblinken_rechts" 3 "Warnblinken" 4 "Warnblinken_Taster"; +VAL_ 591 Distance_Status 0 "Valid" 3 "Invalid"; +VAL_ 619 Travel_Assist_Status 4 "enabled" 0 "disabled" 2 "ready" 3 "pre_ready"; +VAL_ 619 Travel_Assist_Request 4 "enable" 3 "disable" 0 "no_request" 1 "error"; +VAL_ 619 Travel_Assist_Available 0 "not_available" 1 "available"; +VAL_ 706 MO_Anzeige_StSt_Text 0 "keine_Anzeige" 1 "Systemfehler" 2 "Motor_manuell_starten" 3 "Rueckmeldung_durch_Fahrstufe_einlegen" 4 "Zuendungsabschaltwarnung_Timerstart" 5 "Zum_Motorstart_Bremse_treten" 6 "StSt_Aktivierung_nicht_moeglich_auf_Grund_Fahrprogramm"; +VAL_ 706 MO_Anzeige_StSt_Symbol 0 "keine_Anzeige" 1 "StSt_aktiv" 2 "Motorlauf_noetig" 3 "Fahrer_temporaer_abwesend" 4 "Fahrer_vielleicht_anwesend"; +VAL_ 706 MO_ADR_Status 0 "nicht_aktiv" 1 "ADR_angefordert" 2 "ADR_aktiv" 3 "ADR_Fehler"; +VAL_ 706 MO_AGA_Sound_Texte 0 "keine_Anzeige" 1 "Sound_off" 2 "Sound_on"; +VAL_ 706 MO_Anzeige_FMAus_Text 0 "keine_Anzeige" 1 "FMAus_Systemfehler"; +VAL_ 706 MO_Fehler_MSpG 0 "i.O." 1 "Gebl䳥 defekt oder Motorraumtemp. zu hoch"; +VAL_ 706 PEA_Texte 0 "Keine_Anzeige" 1 "PEA_Fahreruebernahme_noetig" 2 "PEA_Reku_nicht_verfuegbar"; +VAL_ 706 TSK_Ueberstimmt_vMax_FahrerInfo 0 "nicht_ueberstimmbar" 1 "ueberstimmbar" 2 "ueberstimmt"; +VAL_ 706 MO_Avus_Motorschutz 0 "keine Warnung" 1 "Drehzahlwarnung Stufe 1" 2 "Drehzahlwarnung Stufe 2" 3 "Drehzahlwarnung Stufe 3"; +VAL_ 706 MO_Rekuperationsstufe 0 "keine_Anzeige" 1 "Rekuperationsstufe_1" 2 "Rekuperationsstufe_2" 3 "Rekuperationsstufe_3" 4 "Rekuperationsstufe_4" 5 "Rekuperationsstufe_5" 6 "Rekuperationsstufe_auto" 7 "Init"; +VAL_ 706 TSK_Einheit_vMax_FahrerInfo 0 "km_h" 1 "mph"; +VAL_ 706 TSK_Status_vMax_FahrerInfo 0 "keine_Anzeige" 1 "Anzeige_im_Fahrzeugstatus" 2 "PopUp_ohne_Gong__Eintrag_FhzStat" 3 "PopUp_mit_Gong__Eintrag_FhzStat"; +VAL_ 706 MO_Red_Fahrleistung 0 "keine_Anzeige" 1 "kleine_Red" 2 "mittlere_Red_temp" 3 "mittlere_Red" 4 "grosse_Red_temp" 5 "grosse_Red"; +VAL_ 706 MO_Anz_Kuehlerluefter 0 "Kein_KuehlerluefterNachlauf" 1 "Text_Luefternachlauf_aktiv" 2 "Text_Luefternachlauf_DPF_aktiv" 3 "Platzhalter_weitere_Signale" 4 "Platzhalter_weitere_Signale" 5 "Platzhalter_weitere_Signale" 6 "Platzhalter_weitere_Signale" 7 "Platzhalter_weitere_Signale"; +VAL_ 706 MO_im_Leerlauf 0 "nicht_im_Leerlauf" 1 "im_Leerlauf"; +VAL_ 706 WIV_Enable_Oeldr_Motor 0 "Oeldruckauswertung_im_Kombi" 1 "Oeldruckauswertung_im_MSG"; +VAL_ 706 MO_OelMessung_Dauer 15 "keine_Messung_aktiv"; +VAL_ 706 TSK_vMax_FahrerInfo 0 "Init___kein_Wert"; +VAL_ 768 ACC_Tempolimit 0 "keine_Anzeige" 1 "5_zulHoechstgeschw" 2 "7_zulHoechstgeschw" 3 "10_zulHoechstgeschw" 4 "15_zulHoechstgeschw" 5 "20_zulHoechstgeschw" 6 "25_zulHoechstgeschw" 7 "30_zulHoechstgeschw" 8 "35_zulHoechstgeschw" 9 "40_zulHoechstgeschw" 10 "45_zulHoechstgeschw" 11 "50_zulHoechstgeschw" 12 "55_zulHoechstgeschw" 13 "60_zulHoechstgeschw" 14 "65_zulHoechstgeschw" 15 "70_zulHoechstgeschw" 16 "75_zulHoechstgeschw" 17 "80_zulHoechstgeschw" 18 "85_zulHoechstgeschw" 19 "90_zulHoechstgeschw" 20 "95_zulHoechstgeschw" 21 "100_zulHoechstgeschw" 22 "110_zulHoechstgeschw" 23 "120_zulHoechstgeschw" 24 "130_zulHoechstgeschw" 25 "140_zulHoechstgeschw" 26 "150_zulHoechstgeschw" 27 "160_zulHoechstgeschw" 28 "200_zulHoechstgeschw" 30 "250_zulHoechstgeschw" 31 "Ende_zulHoechstgeschw"; +VAL_ 768 ACC_Wunschgeschw_Farbe 0 "Grundfarbe" 1 "Farbe_1"; +VAL_ 768 ACC_Warnung_Verkehrszeichen_1 0 "keine_Warnung_Initialwert" 1 "Warnung"; +VAL_ 768 ACA_Querfuehrung 0 "keine_Anzeige_oder_init" 1 "passiv" 2 "aktiv" 3 "Warnung"; +VAL_ 768 ACC_Regelung_AIO 0 "Regelung_Ampel_nicht_aktiv" 1 "Regelung_Ampel_aktiv"; +VAL_ 768 ACC_Wunschgeschw_02 1023 "keine_Anzeige"; +VAL_ 768 ACC_Abstandsindex_02 0 "Audi (Init), VW (passiv/aktiv_Freifahrt)" 1022 "aus_passiv" 1023 "aktiv_Freifahrt"; +VAL_ 768 ACC_Display_Prio 0 "hoechste_Prio" 1 "mittlere_Prio" 2 "geringe_Prio" 3 "keine_Prio"; +VAL_ 768 ACC_rel_Objekt_Zusatzanz 0 "keine Anzeige" 1 "Relevantes_Objekt_erkannt" 2 "Relevantes_Objekt_Abstandswarnung"; +VAL_ 768 ACC_Gesetzte_Zeitluecke 0 "keine_Anzeige" 1 "Zeitluecke_1" 2 "Zeitluecke_2" 3 "Zeitluecke_3" 4 "Zeitluecke_4" 5 "Zeitluecke_5" 6 "nicht_definiert" 7 "nicht_definiert"; +VAL_ 768 ACC_Optischer_Fahrerhinweis 0 "optischer_Fahrerhinweis_AUS" 1 "optischer_Fahrerhinweis_EIN"; +VAL_ 768 ACC_Warnhinweis 0 "kein_Warnhinweis" 1 "Warnhinweis"; +VAL_ 768 ACC_EGO_Fahrzeug 0 "keine_Anzeige" 1 "aktiv" 2 "Warnung" 3 "aktiv_stop" 4 "passiv"; +VAL_ 768 ACC_Relevantes_Objekt_02 0 "keine_Anzeige" 1 "Relevantes_Objekt_erkannt" 2 "Relevantes_Objekt_Warnung" 3 "passiv"; +VAL_ 768 ACC_Wunschgeschw_erreicht 0 "Wunschgeschwindigkeit_nicht_erreicht" 1 "Wunschgeschwindigkeit_erreicht"; +VAL_ 768 ACC_Anzeige_Zeitluecke 0 "Anzeige_Zeitluecke_nicht_angefordert" 1 "Anzeige_Zeitluecke_angefordert"; +VAL_ 768 ACC_Texte_Primaeranz_02 0 "keine Anzeige" 1 "VDA_ACC_Symbol_YYY_kmh_mph" 2 "Kurven_Symbol_YYY_kmh_mph" 3 "Tempolimit_Symbol_YYY_kmh_mph" 4 "ACC_anfahrbereit" 5 "eingestellte_Zeitluecke" 6 "Tuer offen !" 7 "Stehendes Objekt voraus" 8 "o o o" 9 "ACC aus" 10 "ACC startet" 11 "ACC Sensor Sicht !" 12 "ACC nicht verfuegbar" 13 "ACC Fehler" 14 "ESP Eingriff" 15 "ESP PASSIV !" 16 "Parkbremse !" 17 "Geschwindigkeitsgrenze" 18 "Waehlhebelposition !" 19 "Fahrer Gurtschloss offen !" 20 "Schalthebelposition !" 21 "Drehzahl !" 22 "HDC aktiv" 23 "Kupplung betaetigt" 24 "Gang einlegen !" 25 "Bremse ueberhitzt !" 26 "Steigung_Gefaelle_zu_gross" 27 "ABSTAND" 28 "Rechtsueberholen_verhindert" 29 "Linksueberholen_verhindert" 30 "Kreuzungs_Symbol" 31 "Kreisverkehr_Symbol" 32 "Gefaelle_Symbol" 33 "Tempolimit_Kurvenassistent_ein" 34 "Kurvenassistent_ein" 35 "Tempolimitassistent_ein" 36 "Achtung_Geschwindigkeitsueberschreitung" 37 "Tempolimit_und_Kurvenassistent_nicht_verfuegbar" 38 "Tempolimit_nicht_verfuegbar" 39 "Kurvenassistent_nicht_verfuegbar" 40 "Autobahnausfahrt_Symbol" 41 "Stauende_Symbol" 42 "Engstelle_Symbol" 43 "STP_verfuegbar" 44 "Ampel_vertikal" 45 "Ampel_horizontal" 46 "STA_verfuegbar"; +VAL_ 768 ACC_Texte_Zusatzanz_02 0 "keine_Anzeige" 1 "ACC_AUS" 2 "Standby" 3 "UEBERTRETEN" 4 "ABSTAND" 5 "DISTANZ_1" 6 "DISTANZ_2" 7 "DISTANZ_3" 8 "DISTANZ_4" 9 "DISTANZ_5" 10 "DISTANZ_1__dyn" 11 "DISTANZ_2__dyn" 12 "DISTANZ_3__dyn" 13 "DISTANZ_4__dyn" 14 "DISTANZ_5__dyn" 15 "DISTANZ_1__comf" 16 "DISTANZ_2__comf" 17 "DISTANZ_3__comf" 18 "DISTANZ_4__comf" 19 "DISTANZ_5__comf" 20 "DISTANZ_1__efficiency" 21 "DISTANZ_2__efficiency" 22 "DISTANZ_3__efficiency" 23 "DISTANZ_4__efficiency" 24 "DISTANZ_5__efficiency" 25 "DISTANZ_1__Stau" 26 "DISTANZ_2__Stau" 27 "DISTANZ_3__Stau" 28 "DISTANZ_4__Stau" 29 "DISTANZ_5__Stau" 30 "ACHTUNG" 31 "Abstandsanzeige" 32 "Abstandsanzeige_Warnung_aktiviert" 33 "STA_verfuegbar" 34 "Engstelle" 35 "RUV_aktiv_Rechtsverkehr" 36 "RUV_aktiv_Linksverkehr" 37 "STP_Verfuegbar" 38 "AW_Warnschwelle_1" 39 "AW_Warnschwelle_2" 40 "AW_Warnschwelle_3" 41 "AW_Warnung_1" 42 "AW_Warnung_2" 43 "AW_Warnung_3"; +VAL_ 768 STA_Primaeranz 0 "keine_Anzeige" 1 "STA_standby" 2 "STA_aktiv" 3 "STA_Warnung"; +VAL_ 768 Heartbeat 1 "ACC_Init_Low" 420 "ACC_Init_High" 221 "ACC_Available_Low" 360 "ACC_Available_High"; +VAL_ 768 ACC_Status_ACC 0 "ACC_OFF_Hauptschalter_aus" 1 "ACC_INIT" 2 "ACC_STANDBY" 3 "ACC_AKTIV_regelt" 4 "ACC_OVERRIDE" 5 "ACC_Abschaltreaktion" 6 "reversibler_Fehler_im_ACC_System" 7 "irreversibler_Fehler_im_ACC_System"; +VAL_ 768 Lead_Type_Detected 1 "Lead_Detected" 0 "No_Lead_Detected"; +VAL_ 768 Lead_Type 5 "Bicycle" 3 "Car" 0 "None" 2 "Truck" 4 "Motorcycle"; +VAL_ 768 ACC_Events 3 "Starting_Available" 0 "None" 5 "Speed_Limit_Camera" 9 "Street_Type" 4 "Speed_Limit_in_Nav"; +VAL_ 768 Zeitluecke_1 0 "keine Anzeige"; +VAL_ 768 Zeitluecke_2 0 "keine Anzeige" 32 "Minimum"; +VAL_ 768 Zeitluecke_3 0 "keine Anzeige"; +VAL_ 768 Zeitluecke_4 0 "keine Anzeige" 40 "Minimum"; +VAL_ 768 Zeitluecke_5 0 "keine Anzeige"; +VAL_ 795 ESP_Lampe 0 "Aus" 1 "Ein"; +VAL_ 795 ABS_Lampe 0 "Aus" 1 "Ein"; +VAL_ 795 BK_Lampe_02 0 "aus" 1 "ein_statisch" 3 "Warnung"; +VAL_ 795 TC_Lampe 0 "Aus" 1 "Ein"; +VAL_ 795 ESP_m_Raddrehz 32765 "Unterspannung" 32766 "Init" 32767 "Fehler"; +VAL_ 795 ESP_Textanzeigen_03 0 "kein_Text" 1 "ESP_Stoerung" 2 "ABS_Stoerung" 3 "ESP_ABS_Stoerung" 4 "Werkstatt_Bremse" 5 "ASR_Stoerung" 6 "ESP_switched_off" 7 "ASR_off" 8 "ESP_ASR_on" 10 "keine_Bremskraftverstaerkung" 11 "ASR_aktiviert" 12 "ABS_ASR_Stoerung" 15 "ESP_offroad" 17 "ESP_sport" 18 "ESP_Zwangsaktivierung" 19 "ESP_Taster_Info" 20 "TC_aktiv" 21 "reserviert_fuer_Verlwarn" 22 "TC_switched_off" 23 "Verlwarn_akt_Rollsicher_inakt" 24 "ESP_SuperSport" 25 "ESP_Offroad_nicht_verfuegbar"; +VAL_ 795 ESP_Meldungen 0 "keine_Anzeige" 1 "Autohold_Hinweis_1" 2 "Stoerung_Autohold" 3 "Stoerung_Hillholder" 4 "Uebernehmen" 5 "Autohold_aus" 6 "Autohold_Hinweis_2"; +VAL_ 795 ESP_Fehlerstatus_Wegimp 0 "Wegimpulse_iO" 1 "Fehler"; +VAL_ 795 ESP_Wegimp_Ueberlauf 0 "Reset_und_kein_Ueberlauf" 1 "mindestens_1x_Ueberlauf"; +VAL_ 795 ESP_QBit_Wegimp_VA 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 795 ESP_HDC_Geschw_Farbe 0 "Standard_Farbe" 1 "abweichende_Farbe"; +VAL_ 795 ESP_Off_Lampe 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 795 ESP_HDC_Regelgeschw 0 "nicht_verbaut" 125 "HDC_Standby" 126 "Init" 127 "Fehler"; +VAL_ 795 ESP_BKV_Warnung 0 "keine_Anzeige" 1 "keine_Bremskraftverstaerkung"; +VAL_ 817 MFL_Lokalaktiv 0 "war_nicht_lokal_aktiv" 1 "war_lokal_aktiv"; +VAL_ 817 MFL_M_Taste 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 817 MFL_Paddle_Verbau 0 "verbaut" 1 "nicht_verbaut"; +VAL_ 817 MFL_Tastencode_1 0 "Key_Released__No_Key" 1 "Context_Menu" 2 "Menu_Up__Next_Screen" 3 "Menu_Down__Previous_Screen" 4 "Up" 5 "Down" 6 "Up__Down_ThumbWheel" 7 "OK__ThumbWheel_Button" 8 "Cancel__Escape" 9 "Main_Menu" 10 "Side_Menu_left" 11 "Side_Menu_right" 12 "FAS_Menu" 13 "Left__Right_ThumbWheel" 14 "FAS_Menu_ThumbWheel" 16 "Volume_Up" 17 "Volume_Down" 18 "Volume_Up__Down_ThumbWheel" 19 "Volume_ThumbWheel_Button" 20 "Audio_Source" 21 "Arrow_A_Up__Right" 22 "Arrow_A_Down__Left" 23 "Arrow_B_Up__Right" 24 "Arrow_B_Down__Left" 25 "PTT__PushToTalk" 26 "PTT_Cancel" 27 "Route_Info" 28 "Hook" 29 "Hang_Up" 30 "Off_Hook" 31 "Light_On__Off" 32 "Mute" 33 "Joker1" 34 "Joker2" 35 "View" 36 "Arrow_A_Up__Down_ThumbWheel" 37 "Lenkradheizung" 38 "Rekuperation" 39 "Tube_Toggle" 40 "DRS_Drag_Reduction_System" 41 "Stopwatch_Start_Stop" 42 "Stopwatch_Nextlap" 100 "MAP" 101 "MAP_Boost" 102 "Turn_signal_left" 103 "Turn_signal_right" 104 "Turn_signal_off" 105 "Flashlight" 106 "Highbeam" 107 "Washer_button" 108 "Wiper_button_left" 109 "Wiper_button_right" 110 "Wiper_button_cancel" 111 "Exhaust_Sound" 112 "Drive_Select_button" 113 "Sport_button" 114 "ESP_Drift_Selection_ThumbWheel" 115 "PTT_special_vehicle" 116 "TravelAssist" 117 "Launch_Control" 118 "Drift_Mode_Button_Increase" 119 "Drift_Mode_Button_Decrease" 120 "Drift_Mode_Button_Select" 121 "Drive_Mode_Button_Increase" 122 "Drive_Mode_Button_Decrease" 123 "Drive_Mode_Button_Select" 124 "E_Boost_Button_Increase" 125 "E_Boost_Button_Decrease" 126 "E_Boost_Button_Select" 127 "PerformanceHybridButton_Increase" 128 "PerformanceHybridButton_Decrease" 129 "EV_Mode_Button" 130 "HUD_Button" 131 "PASM_Wheel" 132 "PASM_Button" 133 "PTV_Wheel" 134 "PTV_Button" 135 "TC_ESC_Wheel" 136 "TC_ESC_Button" 240 "Startup_Reset" 241 "Initialization"; +VAL_ 817 MFL_Tastencode_2 0 "Key_Released__No_Key" 1 "Context_Menu" 2 "Menu_Up__Next_Screen" 3 "Menu_Down__Previous_Screen" 4 "Up" 5 "Down" 6 "Up__Down_ThumbWheel" 7 "OK__ThumbWheel_Button" 8 "Cancel__Escape" 9 "Main_Menu" 10 "Side_Menu_left" 11 "Side_Menu_right" 12 "FAS_Menu" 13 "Left__Right_ThumbWheel" 14 "FAS_Menu_ThumbWheel" 16 "Volume_Up" 17 "Volume_Down" 18 "Volume_Up__Down_ThumbWheel" 19 "Volume_ThumbWheel_Button" 20 "Audio_Source" 21 "Arrow_A_Up__Right" 22 "Arrow_A_Down__Left" 23 "Arrow_B_Up__Right" 24 "Arrow_B_Down__Left" 25 "PTT__PushToTalk" 26 "PTT_Cancel" 27 "Route_Info" 28 "Hook" 29 "Hang_Up" 30 "Off_Hook" 31 "Light_On__Off" 32 "Mute" 33 "Joker1" 34 "Joker2" 35 "View" 36 "Arrow_A_Up_Right_Down_Left_ThumbWheel" 37 "Lenkradheizung" 38 "Rekuperation" 39 "Tube_Toggle" 40 "DRS_Drag_Reduction_System" 41 "Stopwatch_Start_Stop" 42 "Stopwatch_Nextlap" 100 "MAP" 101 "MAP_Boost" 102 "Turn_signal_left" 103 "Turn_signal_right" 104 "Turn_signal_off" 105 "Flashlight" 106 "Highbeam" 107 "Washer_button" 108 "Wiper_button_left" 109 "Wiper_button_right" 110 "Wiper_button_cancel" 111 "Exhaust_Sound" 112 "Drive_Select_button" 113 "Sport_button" 114 "ESP_Drift_Selection_ThumbWheel" 115 "PTT_special_vehicle" 116 "TravelAssist" 117 "Launch_Control" 118 "Drift_Mode_Button_Increase" 119 "Drift_Mode_Button_Decrease" 120 "Drift_Mode_Button_Select" 121 "Drive_Mode_Button_Increase" 122 "Drive_Mode_Button_Decrease" 123 "Drive_Mode_Button_Select" 124 "E_Boost_Button_Increase" 125 "E_Boost_Button_Decrease" 126 "E_Boost_Button_Select" 127 "PerformanceHybridButton_Increase" 128 "PerformanceHybridButton_Decrease" 129 "EV_Mode_Button" 130 "HUD_Button" 131 "PASM_Wheel" 132 "PASM_Button" 133 "PTV_Wheel" 134 "PTV_Button" 135 "TC_ESC_Wheel" 136 "TC_ESC_Button" 240 "Startup_Reset" 241 "Initialization"; +VAL_ 817 MFL_Eventcode_1 0 "W_no_event____T_no_event" 1 "W_1_Tick_up__T_pressed_normal" 2 "W_2_Ticks_up__T_touched" 3 "W_3_Ticks_up__T_double_click_nor" 4 "W_4_Ticks_up__T_long_press_nor_1" 5 "W_5_Ticks_up__T_long_press_nor_2" 6 "W_6_Ticks_up__T_long_press_nor_3" 7 "W_7_Ticks_up" 9 "W_7_Ticks_dn__T_pressed_strong" 10 "W_6_Ticks_dn" 11 "W_5_Ticks_dn__T_double_click_str" 12 "W_4_Ticks_dn__T_long_press_str_1" 13 "W_3_Ticks_dn__T_long_press_str_2" 14 "W_2_Ticks_dn__T_long_press_str_3" 15 "W_1_Tick_dn"; +VAL_ 817 MFL_Eventcode_2 0 "W_no_event____T_no_event" 1 "W_1_Tick_up__T_pressed_normal" 2 "W_2_Ticks_up__T_touched" 3 "W_3_Ticks_up__T_double_click_nor" 4 "W_4_Ticks_up__T_long_press_nor_1" 5 "W_5_Ticks_up__T_long_press_nor_2" 6 "W_6_Ticks_up__T_long_press_nor_3" 7 "W_7_Ticks_up" 9 "W_7_Ticks_dn__T_pressed_strong" 10 "W_6_Ticks_dn" 11 "W_5_Ticks_dn__T_double_click_str" 12 "W_4_Ticks_dn__T_long_press_str_1" 13 "W_3_Ticks_dn__T_long_press_str_2" 14 "W_2_Ticks_dn__T_long_press_str_3" 15 "W_1_Tick_dn"; +VAL_ 817 MFL_Marke 0 "VW" 1 "Audi" 2 "Seat" 3 "Skoda" 4 "VW_Nutzf" 5 "Bugatti" 6 "Lamborghini" 7 "Bentley" 8 "Rolls Royce" 9 "Quattro" 10 "kein_Hersteller_1" 11 "kein_Hersteller_2" 12 "kein_Hersteller_3" 13 "kein_Hersteller_4" 14 "Ford" 15 "Porsche"; +VAL_ 817 MFL_Tip_Down 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 817 MFL_Tip_Up 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 817 MFL_SatModul_links_Err 0 "kein_Fehler" 1 "Fehler"; +VAL_ 817 MFL_SatModul_rechts_Err 0 "kein_Fehler" 1 "Fehler"; +VAL_ 817 MFL_LR_HZG_Status 0 "inaktiv" 1 "aktiv"; +VAL_ 817 MFL_LR_HZG_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_Signalhorn 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 817 MFL_Signalhorn_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_Tip_links_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_Tip_rechts_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_Taste_links_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_Taste_rechts_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_ECU_Err 0 "normal" 1 "Fehler"; +VAL_ 817 MFL_Response_Err 0 "normal" 1 "Fehler"; +VAL_ 850 Parken_SM_03_MUX 0 "MUX_Gruppe_Punktinfo_0" 1 "MUX_Gruppe_Punktinfo_1" 2 "MUX_Gruppe_Punktinfo_2" 3 "MUX_Gruppe_Punktinfo_3" 4 "MUX_Gruppe_Punktinfo_4" 5 "MUX_Gruppe_Punktinfo_5" 6 "MUX_Gruppe_Punktinfo_6"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_00 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_01 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_02 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_03 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_04 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_05 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 850 Parken_SM_03_Traj_Trans_ID_06 0 "Transaktions_ID_0" 1 "Transaktions_ID_1" 2 "Transaktions_ID_2" 3 "Transaktions_ID_3" 4 "Transaktions_ID_4" 5 "Transaktions_ID_5" 6 "Transaktions_ID_6" 7 "Transaktions_ID_7" 8 "Transaktions_ID_8" 9 "Transaktions_ID_9" 10 "Transaktions_ID_10" 11 "Transaktions_ID_11" 12 "Transaktions_ID_12" 13 "Transaktions_ID_13" 14 "Transaktions_ID_14" 15 "Transaktions_ID_15"; +VAL_ 869 NVEM_Pilot_Info 0 "Init" 1 "keine_Einschraenkung" 2 "Veto_1" 3 "Veto_2"; +VAL_ 869 NVEM_P_Generator_Status 0 "gefiltert" 1 "ungefiltert"; +VAL_ 869 BEM_P_Generator 255 "Fehler"; +VAL_ 869 BEM_n_LLA 0 "keine_Erhoehung" 1 "Stufe_1" 2 "Stufe_2" 3 "Stufe_3"; +VAL_ 869 BEM_Anf_KL 0 "keine Anforderung" 1 "Anforderung Kühlerlüfter Ansteuerung"; +VAL_ 869 BEM_StartStopp_Info 0 "Motorlauf_nicht_notwendig_(Stoppfreigabe)" 1 "Motoranlauf_nicht_zwingend_notwendig_(Stoppverbot,keine_Startanforderung)" 2 "Motoranlauf_zwingend_notwendig_(Startanforderung)" 3 "Systemfehler"; +VAL_ 869 BEM_Batt_Ab 0 "verbunden" 1 "nicht_verbunden"; +VAL_ 869 BEM_Hybrid_Info 0 "keine_Einschraenkung_durch_Energiemanagement" 1 "Motorstart_ueber_12V_Starter_nur_bei_0kmh_moeglich" 2 "kein_Motorstart_ueber_12V_Starter_nach_el_Fahrtbetrieb" 3 "Systemfehler"; +VAL_ 869 NVEM_Red_KL 0 "Init" 1 "Abschaltung_KL" 2 "Reduzierung_KL"; +VAL_ 869 NVEM_Freilauf_Info 0 "Freilauf_freigegeben" 1 "Weiches_Veto_uebertippbar" 2 "Hartes_Veto_Abbruch" 3 "Freilauf_Anforderung"; +VAL_ 869 BEM_HYB_DC_uMinLV 254 "Init" 255 "Fehler"; +VAL_ 870 BM_ZV_auf 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_ZV_zu 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_DWA_ein 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_DWA_Alarm 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Crash 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Panik 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Not_Bremsung 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_GDO 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Warnblinken 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Taxi_Notalarm 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Telematik 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_links 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_rechts 0 "inaktiv" 1 "aktiv"; +VAL_ 870 Blinken_li_Fzg_Takt 0 "Blinker_links_ausgeschaltet" 1 "Blinker_links_eingeschaltet"; +VAL_ 870 Blinken_re_Fzg_Takt 0 "Blinker_rechts_ausgeschaltet" 1 "Blinker_rechts_eingeschaltet"; +VAL_ 870 Blinken_li_Kombi_Takt 0 "Blinkerkontrolllampe_links_ausgeschaltet" 1 "Blinkerkontrolllampe_links_eingeschaltet"; +VAL_ 870 Blinken_re_Kombi_Takt 0 "Blinkerkontrolllampe_rechts_ausgeschaltet" 1 "Blinkerkontrolllampe_rechts_eingeschaltet"; +VAL_ 870 BM_NBA_n_codiert_n_aktiv 0 "codiert_AND_kein_Fehler" 1 "nicht_codiert_OR_Fehler_erkannt"; +VAL_ 870 BM_NBA_Status 0 "NBA_nicht_aktiv" 1 "BRL_Dunkelphase" 3 "BRL_Hellphase"; +VAL_ 870 BM_WBT_Beleuchtung 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_HD_Oeffnung_angelernt 0 "keine_Quittierung" 1 "Quittierung"; +VAL_ 870 BM_Autobahn 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Rollenmodus_Blinken 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Recas 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Wischblinken 0 "inaktiv" 1 "aktiv"; +VAL_ 870 BM_Telematik_Abbruchgrund 0 "Init" 1 "speed_out_of_range" 2 "defect" 3 "clamp_s_on" 4 "clamp_15_on" 5 "door_open" 6 "engine_hood_open" 7 "trunk_open" 8 "convertible_top_not_locked" 9 "horn_activated_by_user" 10 "Higher_Prioritiy_Function_active" 11 "Central_Lock_status_changed" 12 "Request_Dropped_by_Requester" 13 "Service_Duration_Expired" 14 "not_possible_due_to_coding" 15 "no_reason_or_unknown_timeout"; +VAL_ 870 BM_PiloPa 0 "PiloPa_Blinkerquittierung_inaktiv" 1 "PiloPa_Blinkerquittierung_aktiv"; +VAL_ 870 DWA_Alarmquelle 0 "kein_Ausloesegrund" 1 "Tuerkontakt_Fahrertuer" 2 "Tuerkontakt_Beifahrertuer" 3 "Tuerkontakt_hinten_links" 4 "Tuerkontakt_hinten_rechts" 5 "Motorhaubenkontakt_vorne" 6 "Kofferraum_hinten" 7 "Masseschleife_der_Heckscheibe" 8 "Innenraumueberwachung" 9 "Alarm_durch_Noteinstieg" 10 "Sounder" 11 "Neigungssensor" 12 "TSG_FT_am_CAN_Bus" 13 "TSG_BT_am_CAN_Bus" 14 "TSG_HFS_am_CAN_Bus" 15 "TSG_HBFS_am_CAN_Bus" 16 "Klemme_15" 17 "Klemme_15sig" 18 "frei" 19 "Anhaengerueberwachung" 20 "Scheinwerferueberwachung_links" 21 "Scheinwerferueberwachung_rechts" 22 "Handschuhkasten" 23 "Verdeckueberwachung" 24 "OBD_Alarm" 25 "Power_on_Reset" 30 "Init" 31 "Fehler"; +VAL_ 888 GNSS_Ortung_Hoehe 4094 "Init" 4095 "Fehler"; +VAL_ 891 GNSS_UTC_Zeit 0 "Init"; +VAL_ 891 GNSS_Empfaenger_Status 0 "Backup_Mode" 1 "Live"; +VAL_ 891 GNSS_GPS_in_Nutzung 0 "unbenutzt" 1 "benutzt"; +VAL_ 891 GNSS_GLONASS_in_Nutzung 0 "unbenutzt" 1 "benutzt"; +VAL_ 891 GNSS_Empfangbare_Satelliten 0 "Init" 31 "31_oder_mehr"; +VAL_ 891 GNSS_Sichtbare_Satelliten 0 "Init" 31 "31_oder_mehr"; +VAL_ 891 GNSS_Genutzte_Satelliten 0 "Init" 31 "31_oder_mehr"; +VAL_ 916 WBA_Fahrstufe_02 0 "Zwischenstellung_keine_Position" 1 "Position_P" 2 "Position_R" 3 "Position_N" 4 "Position_D" 5 "Position_S" 6 "Position_M_Tippfunktion" 7 "Kurzzeit_M" 8 "Position_E" 9 "Position_MS" 10 "Position_S_Plus" 11 "Position_MS_Plus" 12 "Position_Offroad" 13 "Position_B"; +VAL_ 916 WBA_ZielFahrstufe 0 "keine_Gangempfehlung_kein_Gang_eingelegt" 1 "Pfeil_nach_S" 2 "Pfeil_nach_D" 3 "Pfeil_nach_M" 4 "Pfeil_nach_E"; +VAL_ 916 WBA_GE_Warnung_02 0 "keine_Anzeige" 1 "Fehlereskalationsstufe_I" 2 "Fehlereskalationsstufe_II" 3 "Weiterfahrt_nur_eingeschraenkt_moeglich__Kein_R_Gang" 4 "Getriebefehler_Weiterfahrt_nur_in_D_moeglich__P_bei_Motor_aus" 5 "Wegrollgefahr__P_nicht_moeglich" 6 "Paddlenotbetrieb_Schema+Warnung" 7 "Paddlenotbetrieb_Schema" 8 "Geschwindigkeitsbegrenzung_Notlauf" 9 "Fehlereskalationsst_o_Einschr" 10 "Fehlereskalationsstufe_v_Limit" 11 "Parksperre_Infostufe" 12 "Parksperre_Warnstufe_I" 13 "Parksperre_Warnstufe_II"; +VAL_ 916 WBA_eing_Gang_02 0 "keine_Ganganzeige" 1 "Gang_1" 2 "Gang_2" 3 "Gang_3" 4 "Gang_4" 5 "Gang_5" 6 "Gang_6" 7 "Gang_7" 8 "Gang_8" 9 "Gang_9" 10 "Funktion_Ganganzeigeunterdrueckung" 11 "Gang_10"; +VAL_ 916 WBA_GE_Texte 0 "keine_Anzeige" 1 "zum_Einlegen_einer_Fahrstufe_Fussbremse_betaetigen__ShiftLock_Information" 2 "zum_Einlegen_von_R_N_D_Fussbremse_betaetigen_und_Motor_starten" 3 "Wegrollgefahr_bitte_P_einlegen" 4 "Achtung_Zeitueberschreitung_P_wird_eingelegt" 5 "Wiederanmeldeprozedur_Bremse_betaetigen" 6 "P_nur_im_Stillstand_moeglich" 7 "Rennstart_aktiv"; +VAL_ 916 WBA_Segeln_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 916 WBA_Schaltschema 0 "kein_Schaltschema" 1 "xxxD(S)" 2 "xxxD_S" 3 "xxxS(D)" 4 "xxxS_D" 5 "xxxM(D)" 6 "xxxM_D" 7 "xxxM(S)" 8 "xxxM_S" 9 "xxxE(D)" 10 "xxxE_D" 11 "xxxE(S)" 12 "xxxE_S" 13 "xxxE(M)" 14 "xxxE_M"; +VAL_ 916 WBA_GE_Zusatzwarnungen 0 "keine_Anzeige" 1 "Getriebeueberhitzung_Warnstufe_I" 2 "Getriebeueberhitzung_Warnstufe_II" 3 "Getriebefehler_Bitte_anhalten_und_P_einlegen"; +VAL_ 916 GE_Sollgang 0 "keine_Empfehlung" 1 "Gang_1" 2 "Gang_2" 3 "Gang_3" 4 "Gang_4" 5 "Gang_5" 6 "Gang_6" 7 "Gang_7" 8 "Gang_8" 9 "Gang_9" 11 "Gang_10"; +VAL_ 916 GE_Tipschaltempf_verfuegbar 0 "nicht_verfuegbar" 1 "verfuegbar"; +VAL_ 916 WBA_GE_Texte_02 0 "Keine_Anzeige" 1 "Fahrtrichtungswechsel_nur_nach_Stillstandt" 2 "Ladestecker_gesteckt" 3 "zusaetzlicher_Service_erforderlich" 4 "eLaunch_Aktiv" 5 "eLaunch_nicht_moeglich" 6 "WH_S_nicht_moeglich_Offroad" 7 "WH_S_nicht_moeglich_RangeMode"; +VAL_ 916 WBA_GE_Texte_03 0 "init" 1 "LC_not_available" 2 "LCperformance_not_possible" 3 "LCperformance_possible" 4 "LCperformance_armed" 5 "LCperformance_preparation" 6 "LCperformance_launch" 7 "LCperformance_aborted" 8 "LCsmoke_not_possible" 9 "LCsmoke_possible" 10 "LCsmoke_armed" 11 "LCsmoke_launch" 12 "LCsmoke_aborted" 15 "Fehler"; +VAL_ 916 WBA_Blinken 0 "kein_WBA_Blinken" 1 "WBA_Blinken"; +VAL_ 916 GE_Wiederstart_Anz_Std 0 "keine_Anzeige" 1 "Standard_Wiederstartgrund"; +VAL_ 916 GE_Stoppverbot_Anz_01 0 "keine_Anzeige" 1 "Temperaturbedingung"; +VAL_ 916 GE_Stoppverbot_Anz_02 0 "keine_Anzeige" 1 "Drucksensorausfall"; +VAL_ 916 GE_Stoppverbot_Anz_03 0 "keine_Anzeige" 1 "Grundeinstellung"; +VAL_ 916 GE_Stoppverbot_Anz_04 0 "keine_Anzeige" 1 "Demontagestellung"; +VAL_ 916 GE_Stoppverbot_Anz_05 0 "keine_Anzeige" 1 "Eingeschraenkte_Fahrfunktion_Notlauf_Liegenbleiber"; +VAL_ 916 GE_Stoppverbot_Anz_06 0 "keine_Anzeige" 1 "Stoppverbot_ueber_Applikation"; +VAL_ 916 GE_Stoppverbot_Anz_07 0 "keine_Anzeige" 1 "Schaltung_aktiv"; +VAL_ 916 GE_Stoppverbot_Anz_Std 0 "keine_Anzeige" 1 "Standard_Stoppvetogrund"; +VAL_ 919 LDW_Gong 1 "Chime" 2 "Beep" 0 "None"; +VAL_ 919 LDW_Texte 8 "laneAssistTakeOver" 4 "laneAssistTakeOverUrgent" 0 "none"; +VAL_ 949 KL_Drehz_Anh 0 "keine_Anhebung" 1 "Drehzahlanhebung_vom_Motor_angefordert"; +VAL_ 949 KL_Vorwarn_Komp_ein 0 "Init" 1 "Vorwarnung_Kompressor_ein"; +VAL_ 949 KL_AC_Schalter 0 "aus" 1 "ein"; +VAL_ 949 KL_Komp_Moment_alt 1 "veraltet_bzw_Ermittlung_des_Moments_nicht_moeglich__zB_keine_Drehzahl_kein_Kaeltemitteldruck"; +VAL_ 949 KL_Vorwarn_Zuheizer_ein 0 "keine_Vorwarnung" 1 "Vorwarnung_Zuheizer_ein"; +VAL_ 949 KL_Zustand 0 "Aus" 1 "Ein"; +VAL_ 949 KL_Kompressorkupplung_linear 253 "volle_Ansteuerung" 254 "Init__nicht_bedient"; +VAL_ 949 KL_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 949 KL_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 949 KL_nachtr_Stopp_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 949 KL_T_Charge 0 "Taster_nicht_betaetigt" 1 "Taster_betaetigt"; +VAL_ 949 KL_Last_Kompr 255 "Fehler"; +VAL_ 949 KL_Spannungs_Anf 0 "keine_Anforderung" 1 "Anforderung_Stufe_1" 2 "Anforderung_Stufe_2" 3 "Anforderung_Stufe_3"; +VAL_ 949 KL_Thermomanagement 0 "keine_Freigabe_TMM__max_Heizbedarf" 1 "kleine_Freigabe_TMM" 2 "mittlere_Freigabe_TMM" 3 "volle_Freigabe_TMM__kein_Heizbedarf"; +VAL_ 949 KL_StartStopp_Info 0 "Motorlauf_nicht_notwendig_(Stoppfreigabe)" 1 "Motoranlauf_nicht_zwingend_notwendig_(Stoppverbot,keine_Startanforderung)" 2 "Motoranlauf_zwingend_notwendig_(Startanforderung)" 3 "Systemfehler"; +VAL_ 949 KL_Freilauf_Info 0 "Freilauf_freigegeben" 1 "Uebergang_in_Freilauf_unzulaessig" 2 "Freilauf_nicht_freigegeben_Abbruch" 3 "Freilauf_Anforderung"; +VAL_ 949 KL_Anf_KL 255 "Fehler"; +VAL_ 949 KL_el_Zuheizer_Stufe 0 "Aus" 1 "Stufe_1" 2 "Stufe_2" 3 "Stufe_3"; +VAL_ 949 KL_Ausstattung_Klima 0 "Heizung_elektrisch" 1 "Klimamanuell_elektrisch" 2 "Climatic__1_Zone" 3 "Climatronic__1_Zone" 4 "Climatronic__2_Zonen" 5 "Climatronic__3_Zonen" 6 "Climatronic__4_Zonen" 7 "reserviert"; +VAL_ 949 KL_Variante_Standheizung 0 "Wasserstandheizung_60_min_Laufzeit" 1 "Luftstandheizung_120_min_Laufzeit" 2 "Wasserstandheizung_120_min_Laufzeit" 3 "Wasser_und_Luftstandheizung_120_min_Laufzeit"; +VAL_ 958 MO_StartStopp_Status 0 "System_in_diesem_KL15_Zyklus_nicht_verfuegbar" 1 "System_aktiv_keine_Freigabe_durch_StartStop_Koordinator" 2 "System_aktiv_alle_Freigaben_liegen_vor" 3 "System_aktiv_mindestens_eine_Freigabe_fehlt"; +VAL_ 958 MO_StartStopp_Wiederstart 0 "Wiederstart_inaktiv" 1 "Wiederstart_aktiv"; +VAL_ 958 MO_StartStopp_Motorstopp 0 "Motor_Stop_inaktiv" 1 "Motor_Stop_aktiv"; +VAL_ 958 MO_Freig_Reku 0 "Rekuperations-Modus aus" 1 "Empfehlung Spannungsanhebung" 2 "Empfehlung Spannungsabsenkung" 3 "Rekuperationsmodus aktiv, Spannungsvariation nicht notwendig"; +VAL_ 958 MO_Kl_75 0 "Aus" 1 "Ein"; +VAL_ 958 MO_Kl_50 0 "aus" 1 "KL50_ein_Startausfuehrung_Fahrer"; +VAL_ 958 MO_Gangposition 0 "Gang_N" 1 "Gang_1" 2 "Gang_2" 3 "Gang_3" 4 "Gang_4" 5 "Gang_5" 6 "Gang_6" 7 "Gang_7" 8 "Gang_8" 9 "Automat_P" 10 "Automat_Vorwaerts_S" 11 "Automat_Vorwaerts_D/E" 12 "Zwischenstellung" 13 "Gang_R" 14 "Istgang_nicht_definiert" 15 "Fehler"; +VAL_ 958 MO_StartStopp_Fahrerwunsch 0 "Init" 1 "Stoppverbot_durch_Fahrer" 2 "Stoppfreigabe_durch_Fahrer" 3 "Stoppanforderung_durch_Fahrer"; +VAL_ 958 MO_HYB_Fahrbereitschaft 0 "keine_Fahrbereitschaft" 1 "Fahrbereitschaft"; +VAL_ 958 MO_Ext_E_Fahrt_aktiv 0 "Rueckmeldung_E_Taster_aus" 1 "Rueckmeldung_E_Taster_ein"; +VAL_ 958 MO_Fahrer_bremst 0 "kein_Bremsen" 1 "Bremse_betaetigt"; +VAL_ 958 MO_QBit_Fahrer_bremst 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 958 MO_BLS 0 "kein_Bremsen" 1 "Bremse_betaetigt"; +VAL_ 958 MO_Konsistenz_Bremsped 0 "Bremspedalinformation_plausibel" 1 "Bremspedalinformation_unplausibel"; +VAL_ 958 MO_KomFehler_ESP 0 "kein_Fehler" 1 "Fehler"; +VAL_ 958 MO_Klima_Eingr 0 "kein Eingriff" 1 "Klimakompressor ausschalten" 2 "Klimakompressor Leistungsreduzierung" 3 "Klimakompressor aufgrund der Heissleuchtenvorwarnung ausschalten"; +VAL_ 958 MO_Aussp_Anlass 0 "Anlasser_darf_angesteuert_werden" 1 "Anlasser_ausspuren__Ansteuerung_nicht_moeglich"; +VAL_ 958 MO_Freig_Anlass 0 "Start_nicht_zulaessig" 1 "Startfreigabe"; +VAL_ 958 MO_Kuppl_schalter 0 "Schalter_sagt_ausgekuppelt" 1 "Schalter_sagt_eingekuppelt"; +VAL_ 958 MO_Interlock 0 "Interlockschalter_nicht_betaetigt" 1 "Interlockschalter_betaetigt"; +VAL_ 958 MO_Motor_laeuft 0 "Motor_laeuft_nicht" 1 "Motor_laeuft_autark_und_stabil_und_darf_mechanisch_belastet_werden"; +VAL_ 958 MO_Kickdown 0 "kein_Kickdown" 1 "Kickdown"; +VAL_ 958 MO_QBit_KL_75 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 958 MO_EKlKomLeiRed 0 "keine_Leistungsbegr" 1 "Leistungsbegr_75" 2 "Leistungsbegr_50" 3 "Leistungsbegr_25"; +VAL_ 958 MO_Handshake_STH 0 "keine EKP-Ansteuerung durch STH-Anforderung" 1 "EKP-Ansteuerung durch STH-Anforderung"; +VAL_ 958 MO_BKV_Unterdruckwarnung 0 "Unterdruckhaushalt_iO" 1 "Unterdruckhaushalt_niO"; +VAL_ 958 MO_Freigabe_Segeln 0 "Segelbetrieb_nicht_freigegeben" 1 "Segelbetrieb_freigegeben"; +VAL_ 958 MO_PTC_Status 0 "nicht_unterstuetzt" 1 "Stufe_0" 2 "Stufe_1" 3 "Stufe_2" 4 "Stufe_3" 7 "PTC_am_BCM"; +VAL_ 958 MO_QBit_Gangposition 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 958 MO_Signalquelle_Gangposition 0 "Sensorsignal" 1 "Modellsignal"; +VAL_ 958 MO_Remotestart_Betrieb 0 "MSG_nicht_bereit_fuer_RS_Betrieb" 1 "MSG_bereit_fuer_oder_im_RS_Betrieb"; +VAL_ 958 MO_Remotestart_moeglich 0 "Remotestart_nicht_moeglich" 1 "Remotestart_moeglich"; +VAL_ 958 MO_FMAus_aktiv 0 "inaktiv" 1 "Segeln_mit_Motor_aus_aktiv"; +VAL_ 958 MO_FMAus_Startvariante 0 "kein_Motorstart" 1 "Motorstart_elektrischer_Starter" 2 "GetriebeAnschleppstart" 3 "GetriebeNotAnschleppstart"; +VAL_ 958 MO_BMS_NV_Anf_stuetzen 0 "nicht_notwendig" 1 "notwendig"; +VAL_ 958 MO_Zylinderabschaltung 0 "Vollmotorbetrieb_VMB" 1 "Uebergang_HMB_in_VMB" 2 "Uebergang_VMB_in_HMB" 3 "Halbmotorbetrieb_HMB"; +VAL_ 958 MO_HYB_VM_aktiv 0 "VM_nicht_aktiv" 1 "VM_aktiv"; +VAL_ 958 MO_StartVorauss_erfuellt 0 "Signal_nicht_bedient" 1 "StartVorauss_nicht_ueberpruefbar" 2 "StartVorauss_nicht_erfuellt" 3 "StartVorauss_erfuellt"; +VAL_ 960 RSt_Fahrerhinweise 0 "Init" 1 "Fahreruebernahme_Hinweis_ZAT_Automat_ohne_Gong" 2 "Fahreruebernahme_Hinweis_ZAT_Automat_mit_Gong" 3 "Fahreruebernahme_Hinweis_ZAT_Handschalter_ohne_Gong" 4 "Fahreruebernahme_Hinweis_ZAT_Handschalter_mit_Gong" 5 "Fahreruebernahme_Hinweis_ZAS_Automat_ohne_Gong" 6 "Fahreruebernahme_Hinweis_ZAS_Automat_mit_Gong" 7 "Fahreruebernahme_Hinweis_ZAS_Handschalter_ohne_Gong" 8 "Fahreruebernahme_Hinweis_ZAS_Handschalter_mit_Gong" 9 "RemoteStart_aktiv_ohne_Gong" 10 "RemoteStart_aktiv_mit_Gong" 11 "void" 12 "void" 13 "void" 14 "void" 15 "void"; +VAL_ 960 ZAS_Kl_S 0 "aus" 1 "S_Kontakt_ein"; +VAL_ 960 ZAS_Kl_15 0 "aus" 1 "ein"; +VAL_ 960 ZAS_Kl_X 0 "aus" 1 "ein"; +VAL_ 960 ZAS_Kl_50_Startanforderung 0 "aus" 1 "KL50_ein_Startwunsch_Fahrer"; +VAL_ 960 BCM_Remotestart_Betrieb 0 "kein_RS_Betrieb" 1 "RS_Betrieb"; +VAL_ 960 ZAS_Kl_Infotainment 0 "inaktiv" 1 "aktiv"; +VAL_ 960 BCM_Remotestart_KL15_Anf 0 "inaktiv" 1 "aktiv"; +VAL_ 960 BCM_Remotestart_MO_Start 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 960 KST_Warn_P1_ZST_def 0 "nicht_defekt" 1 "defekt"; +VAL_ 960 KST_Warn_P2_ZST_def 0 "nicht_defekt" 1 "defekt"; +VAL_ 960 KST_Fahrerhinweis_1 0 "inaktiv" 1 "aktiv"; +VAL_ 960 KST_Fahrerhinweis_2 0 "inaktiv" 1 "aktiv"; +VAL_ 960 BCM_Ausparken_Betrieb 0 "kein_Betrieb" 1 "Ausparkvorgang_aktiv"; +VAL_ 960 KST_Fahrerhinweis_4 0 "inaktiv" 1 "aktiv"; +VAL_ 960 KST_Fahrerhinweis_5 0 "inaktiv" 1 "aktiv"; +VAL_ 960 KST_Fahrerhinweis_6 0 "inaktiv" 1 "aktiv"; +VAL_ 967 MO_Kuehlerluefter_MUX 0 "Kuehlerluefter_1" 1 "Kuehlerluefter_2"; +VAL_ 967 MO_Kuehlerluefter_1 126 "Init" 127 "Fehler"; +VAL_ 967 MO_Kuehlerluefter_2 126 "Init" 127 "Fehler"; +VAL_ 967 MO_EFLEX_Lampe 0 "Lampe_aus" 1 "Lampe_ein" 2 "Lampe_blinkend" 3 "Lampe_blinkend_mit_Akustik"; +VAL_ 967 MO_KJS_nicht_bereit 0 "kein_Fehler" 1 "Fehler"; +VAL_ 967 MO_ITM_Warnung_Pumpe 0 "keine_Warnung" 1 "ITM_Warnung"; +VAL_ 967 WIV_Anzeige_aktiv 0 "Anzeige aus" 1 "WIV Anzeige aktiv"; +VAL_ 967 WIV_Oelmin_Warn 0 "in_Ordnung" 1 "Warnung"; +VAL_ 967 WIV_Sensorfehler 0 "in_Ordnung" 1 "Sensor_defekt"; +VAL_ 967 WIV_Schieflage 0 "Fahrzeug_gerade" 1 "Fahrzeug_in_Schieflage"; +VAL_ 967 MO_Zustand_HWP 0 "HWP_nicht_schaltbar" 1 "HWP_foerdert_nicht" 2 "HWP_foerdert" 3 "reserviert"; +VAL_ 967 OLEV_Systemstoerung 0 "֬system i.O." 1 "Systemstörung ֬system"; +VAL_ 967 MO_Oelwarnung_max 0 "keine_Warnung" 1 "Warnfall_aktiv"; +VAL_ 967 WIV_Oelsystem_aktiv 0 "Anzeige_aus" 1 "Anzeige_aktiv"; +VAL_ 967 WIV_nicht_betriebswarm 0 "Motor_warm" 1 "Motor_nicht_betriebswarm"; +VAL_ 967 WIV_Ueberfuell_Warn 0 "in_Ordnung" 1 "Ueberfuellwarnung"; +VAL_ 967 WIV_laufender_Motor 0 "Messung_moeglich" 1 "Messung_nicht_moeglich"; +VAL_ 967 MO_E_Warnungen 0 "keine_Anzeige" 1 "Fehler_Elektrosystem_Anhalten" 2 "Fehler_Elektrosystem_Werkstatt" 3 "Elektrosystem_ueberhitzt_Stopp" 4 "Fehler_Hybridsystem_Anhalten" 5 "Fehler_Hybridsystem_Werkstatt" 6 "Fehler_Wasserstoffsystem_Anhalte" 7 "Fehler_Wasserstoffsystem_Werksta" 8 "reserviert_keine_Anzeige" 9 "reserviert_keine_Anzeige" 10 "reserviert_keine_Anzeige" 11 "reserviert_keine_Anzeige" 12 "reserviert_keine_Anzeige" 13 "reserviert_keine_Anzeige" 14 "reserviert_keine_Anzeige" 15 "reserviert_keine_Anzeige"; +VAL_ 967 MO_Text_Motorstart 0 "keine_Anzeige" 1 "Motor_im_Stoppbetrieb" 2 "StartStopp_sicherheitsbedingt_deaktiviert" 3 "System_fordert_Wiederstart" 4 "Aufforderung_Motorstart" 5 "Motorlauf_noetig" 6 "Motorlaufwarnung" 9 "Unerwuenschter_Motorstillstand" 10 "Motorstart_nicht_moeglich" 11 "Fehler_Kupplungsschalter" 12 "Motor_startet" 13 "Kupplung_betaetigen" 14 "Waehlhebel_in_PN_Position" 15 "Bremse_treten"; +VAL_ 967 MO_E_Texte 0 "keine_Anzeige" 1 "Batterie_fast_leer" 2 "Ladestecker_nicht_fahrbereit" 3 "VM_Betrieb_erforderlich" 4 "Batterie_laedt_Nicht_ausschalten" 5 "Bitte_Bremse_treten" 6 "manueller_Neustart_erforderlich" 7 "Stopp_Fahrzeug_nicht_abschleppen" 8 "kein_Neustart_Haube_nicht_oeffnen" 9 "Motorstart_im_naechsten_Zyklus" 10 "VM_erforderlich_EVMode_abwaehlen" 11 "laengerer_VMBetrieb_Bordbuch" 12 "Tank_leer_VM_nicht_verfuegbar" 13 "Bitte_warten_Motor_startet" 14 "kein_Start_Batterietemperatur" 15 "Ende_elektrische_Reichweite_erreicht"; +VAL_ 967 WIV_Oeldyn_avl 0 "Oeldyn_nicht_vorhanden" 1 "Oeldyn_vorhanden"; +VAL_ 967 OLEV_Oelstand_nicht_vorhanden 0 "֬stand vorhanden" 1 "֬stand nicht vorhanden"; +VAL_ 967 MO_Systemlampe 0 "Lampe aus" 1 "Lampe ein"; +VAL_ 967 MO_OBD2_Lampe 0 "Lampe aus" 1 "Lampe ein"; +VAL_ 967 MO_Heissleuchte 0 "Lampe aus" 1 "Lampe ein"; +VAL_ 967 MO_Partikel_Lampe 0 "Lampe aus" 1 "Lampe ein"; +VAL_ 967 MO_RedFahrleistung_Lampe 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 967 WIV_Oelstand_nicht_vorhanden 0 "֬stand vorhanden" 1 "֬stand nicht vorhanden"; +VAL_ 967 WIV_nachfuellanzeige_ein 0 "keine_Nachfuellanzeige" 1 "Nachfuellanzeige"; +VAL_ 967 WIV_Ueberfuell_deaktiv 0 "Ueberfuellwarnung_am_Kombi_aktiv" 1 "Ueberfuellwarnung_am_Kombi_deaktiv"; +VAL_ 967 WIV_Unterfuell_Warn 0 "in_Ordnung" 1 "Unterfuellwarnung"; +VAL_ 967 MO_Tankdeckel_Lampe 0 "Lampe aus" 1 "Lampe ein"; +VAL_ 967 MO_Text_Tankdeckelwarn 0 "kein_Text" 1 "Anzeige_Text_Tankdeckelwarnung_im_Kombi"; +VAL_ 967 MO_Vorglueh_Lampe 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 967 WIV_Oeldr_Warn_Motor 0 "keine_Warnung" 1 "niedrige_Oeldruckstufe_nicht_erreicht"; +VAL_ 967 MO_E_Mode 0 "keine_Anzeige" 1 "E_Mode_passiv" 2 "E_Mode_aktiv" 3 "E_Mode_inaktiv_nicht_verfuegbar" 4 "E_Mode_aktiv_nicht_verfuegbar" 5 "reserviert_keine_Anzeige" 6 "reserviert_keine_Anzeige" 7 "reserviert_keine_Anzeige"; +VAL_ 974 HFS_Tuer_geoeffnet 0 "geschlossen" 1 "offen"; +VAL_ 974 HFS_verriegelt 0 "nicht_verriegelt" 1 "verriegelt"; +VAL_ 974 HFS_gesafet 0 "nicht_gesafet" 1 "gesafet"; +VAL_ 974 HFS_Heckrollotaster_betaetigt 0 "keine_Verfahranweisung_in_Richtung_Hoch" 1 "In_Richtung_Hoch_Verfahren"; +VAL_ 974 HFS_Tuerschloss_defekt 0 "Tuerschloss_funktionsfaehig" 1 "Tuerschloss_defekt"; +VAL_ 974 HFS_Unlock_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_Lock_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_Sperrklinke 0 "Schloss_in_Vorraste_und_Hauptraste" 1 "Tuer_auf_oder_Tuer_Position_zwischen_Vor_und_Hauptraste"; +VAL_ 974 HFS_TAG_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_TIG_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_FH_S_HBFS_AutoHoch 0 "keine_Bedienung" 1 "Automatiklauf_Angefordert"; +VAL_ 974 HFS_FH_S_HBFS_AutoTief 0 "keine_Bedienung" 1 "Automatiklauf_Angefordert"; +VAL_ 974 HFS_FH_S_HBFS_ManHoch 0 "keine_Bedienung" 1 "Manueller_Lauf_Angefordert"; +VAL_ 974 HFS_FH_S_HBFS_ManTief 0 "keine_Bedienung" 1 "Manueller_Lauf_Angefordert"; +VAL_ 974 HFS_Tuer_Status 0 "Init" 1 "Tuer_geschlossen" 2 "Tuer_offen" 3 "Fehler"; +VAL_ 974 HFS_SAD_Schalter 0 "nicht_betaetigt" 5 "AUF_manuell" 6 "AUF_automatik" 7 "ZU_manuell" 8 "ZU_automatik" 13 "nicht_verfuegbar" 14 "Init" 15 "Fehler"; +VAL_ 974 HFS_FH_S_ManHoch 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_FH_S_AutoHoch 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_FH_S_ManTief 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_FH_S_AutoTief 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_FH_Bew_hoch 0 "inaktiv" 1 "aktiv"; +VAL_ 974 HFS_FH_Bew_tief 0 "inaktiv" 1 "aktiv"; +VAL_ 974 HFS_FH_Fang 0 "ausserhalb_Fangbereich" 1 "innerhalb_Fangbereich"; +VAL_ 974 HFS_FH_Block 0 "inaktiv" 1 "aktiv"; +VAL_ 974 HFS_FH_Thermo 0 "inaktiv" 1 "aktiv"; +VAL_ 974 HFS_UEKB_aktiviert 0 "inaktiv" 1 "aktiv"; +VAL_ 974 HFS_Tueroeffnen_Warnung 0 "Tuerwarnung_nicht_aktiv" 1 "Tuerwarnung_aktiv"; +VAL_ 974 HFS_FH_normiert 0 "inaktiv" 1 "aktiv"; +VAL_ 974 ASW_Warnung_aktiv_HFS 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 974 HFS_Zuziehhilfe_aktiv 0 "Init" 1 "Zuziehhilfe_aktiv"; +VAL_ 974 HFS_Seitenrollo_hoch 1 "Seitenrollo_in_Bewegung_hoch"; +VAL_ 974 HFS_Seitenrollo_tief 1 "Seitenrollo_in_Bewegung_tief"; +VAL_ 974 HFS_Status_KiSi 0 "inaktiv" 1 "aktiv"; +VAL_ 974 SSR_HFS_Pos_Unten 0 "SSR_Oben" 1 "SSR_Unten"; +VAL_ 974 HFS_Oben_Block_erw 0 "Fensterheber_nicht_in_Blockerwar" 1 "Fensterheber_in_Blockerwartung_o"; +VAL_ 974 HFS_Unten_Block_erw 0 "Fensterheber_nicht_in_Blockerwar" 1 "Fensterheber_in_Blockerwartung_u"; +VAL_ 974 MTHFS_M_Taste 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 MTHFS_Pos1 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 MTHFS_Pos2 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 MTHFS_Pos3 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 974 HFS_MRollo_Schalter 0 "nicht_betaetigt" 1 "ZU_manuell" 2 "ZU_automatik" 3 "AUF_manuell" 4 "AUF_automatik" 5 "nicht_verfuegbar" 6 "Init" 7 "Fehler"; +VAL_ 974 HFS_Lock_Taster_inv 0 "Lock Taster bet䴧it" 1 "Lock Taster nicht bet䴩gt"; +VAL_ 974 HFS_Status_eTAG 0 "Init" 1 "Griff_ausgefahren" 2 "Griff_eingefahren" 3 "Fehler"; +VAL_ 974 HFS_Tuer_Status_QBit 0 "Status_Tuerkontakt_sicher" 1 "Status_Tuerkontakt_unsicher"; +VAL_ 974 HFS_TCR_Mode_aktiv 0 "TCR_Mode_deaktiv" 1 "TCR_Mode_aktiv"; +VAL_ 975 HBFS_Tuer_geoeffnet 0 "geschlossen" 1 "offen"; +VAL_ 975 HBFS_verriegelt 0 "nicht_verriegelt" 1 "verriegelt"; +VAL_ 975 HBFS_gesafet 0 "nicht_gesafet" 1 "gesafet"; +VAL_ 975 HBFS_Heckrollotaster_betaetigt 0 "keine_Verfahranweisung_in_Richtung_Hoch" 1 "In_Richtung_Hoch_Verfahren"; +VAL_ 975 HBFS_Tuerschloss_defekt 0 "Tuerschloss_funktionsfaehig" 1 "Tuerschloss_defekt"; +VAL_ 975 HBFS_Unlock_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_Lock_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_Sperrklinke 0 "Schloss_in_Vorraste_und_Hauptraste" 1 "Tuer_auf_oder_Tuer_Position_zwischen_Vor_und_Hauptraste"; +VAL_ 975 HBFS_TAG_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_TIG_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_FH_S_HFS_AutoHoch 0 "keine_Bedienung" 1 "Automatiklauf_Angefordert"; +VAL_ 975 HBFS_FH_S_HFS_AutoTief 0 "keine_Bedienung" 1 "Automatiklauf_Angefordert"; +VAL_ 975 HBFS_FH_S_HFS_ManHoch 0 "keine_Bedienung" 1 "Manueller_Lauf_Angefordert"; +VAL_ 975 HBFS_FH_S_HFS_ManTief 0 "keine_Bedienung" 1 "Manueller_Lauf_Angefordert"; +VAL_ 975 HBFS_Tuer_Status 0 "Init" 1 "Tuer_geschlossen" 2 "Tuer_offen" 3 "Fehler"; +VAL_ 975 HBFS_SAD_Schalter 0 "nicht_betaetigt" 5 "AUF_manuell" 6 "AUF_automatik" 7 "ZU_manuell" 8 "ZU_automatik" 13 "nicht_verfuegbar" 14 "Init" 15 "Fehler"; +VAL_ 975 HBFS_FH_S_ManHoch 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_FH_S_AutoHoch 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_FH_S_ManTief 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_FH_S_AutoTief 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_FH_Bew_hoch 0 "inaktiv" 1 "aktiv"; +VAL_ 975 HBFS_FH_Bew_tief 0 "inaktiv" 1 "aktiv"; +VAL_ 975 HBFS_FH_Fang 0 "ausserhalb_Fangbereich" 1 "innerhalb_Fangbereich"; +VAL_ 975 HBFS_FH_Block 0 "inaktiv" 1 "aktiv"; +VAL_ 975 HBFS_FH_Thermo 0 "inaktiv" 1 "aktiv"; +VAL_ 975 HBFS_UEKB_aktiviert 0 "inaktiv" 1 "aktiv"; +VAL_ 975 HBFS_Tueroeffnen_Warnung 0 "Tuerwarnung_nicht_aktiv" 1 "Tuerwarnung_aktiv"; +VAL_ 975 HBFS_FH_normiert 0 "inaktiv" 1 "aktiv"; +VAL_ 975 ASW_Warnung_aktiv_HBFS 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 975 HBFS_Zuziehhilfe_aktiv 0 "Init" 1 "Zuziehhilfe_aktiv"; +VAL_ 975 HBFS_Seitenrollo_hoch 1 "Seitenrollo_in_Bewegung_hoch"; +VAL_ 975 HBFS_Seitenrollo_tief 1 "Seitenrollo_in_Bewegung_tief"; +VAL_ 975 HBFS_Status_KiSi 0 "inaktiv" 1 "aktiv"; +VAL_ 975 SSR_HBFS_Pos_Unten 0 "SSR_Oben" 1 "SSR_Unten"; +VAL_ 975 HBFS_Oben_Block_erw 0 "Fensterheber_nicht_in_Blockerwar" 1 "Fensterheber_in_Blockerwartung_o"; +VAL_ 975 HBFS_Unten_Block_erw 0 "Fensterheber_nicht_in_Blockerwar" 1 "Fensterheber_in_Blockerwartung_u"; +VAL_ 975 MTHBFS_M_Taste 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 MTHBFS_Pos1 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 MTHBFS_Pos2 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 MTHBFS_Pos3 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 975 HBFS_MRollo_Schalter 0 "nicht_betaetigt" 1 "ZU_manuell" 2 "ZU_automatik" 3 "AUF_manuell" 4 "AUF_automatik" 5 "nicht_verfuegbar" 6 "Init" 7 "Fehler"; +VAL_ 975 HBFS_Lock_Taster_inv 0 "Lock Taster bet䴧it" 1 "Lock Taster nicht bet䴩gt"; +VAL_ 975 HBFS_Status_KiSi_inv 0 "aktiv" 1 "inaktiv"; +VAL_ 975 HBFS_Status_eTAG 0 "Init" 1 "Griff_ausgefahren" 2 "Griff_eingefahren" 3 "Fehler"; +VAL_ 975 HBFS_Tuer_Status_QBit 0 "Status_Tuerkontakt_sicher" 1 "Status_Tuerkontakt_unsicher"; +VAL_ 975 HBFS_TIG_betaetigt_schliessen 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 976 FT_Tuer_geoeffnet 0 "Init" 1 "Tuer offen"; +VAL_ 976 FT_verriegelt 0 "Init" 1 "verriegelt"; +VAL_ 976 FT_gesafet 0 "Init" 1 "gesafet"; +VAL_ 976 FT_Schluesselschalter_auf 0 "Init" 1 "Schluesselschalter_auf_betaetigt"; +VAL_ 976 FT_Schluesselschalter_zu 1 "Schluesselschalter zu betaetigt"; +VAL_ 976 FT_Unlock_Taster 0 "Init" 1 "Unlock_Taster_betaetigt"; +VAL_ 976 FT_Lock_Taster 0 "Init" 1 "Lock_Taster_betaetigt"; +VAL_ 976 FT_Sperrklinke 0 "Schloss_in_Vorraste_und_Hauptraste" 1 "Tuer_auf_oder_Tuer_Position_zwischen_Vor_und_Hauptraste"; +VAL_ 976 FT_TAG_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 976 FT_TIG_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 976 FT_IRUE_Taste 0 "Init" 1 "IRUE_Taste_betaetigt"; +VAL_ 976 FT_HD_Taste 0 "Init" 1 "Heckdeckel_oeffnen"; +VAL_ 976 FT_TD_Taste_Fehler 0 "iO" 1 "defekt"; +VAL_ 976 FT_TD_Taste 1 "Tankdeckelentriegelungs Taster gedrückt"; +VAL_ 976 SSR_Temp_Freigabe 0 "SSR_Deaktiviert" 1 "SSR_Freigegeben"; +VAL_ 976 FT_HD_Taste_2 0 "Taste_nicht_gedrueckt" 1 "Taste_gedrueckt"; +VAL_ 976 FT_TSG_hinten_verbaut 0 "nicht verbaut" 1 "verbaut"; +VAL_ 976 FT_Sp_Blk_def 0 "iO" 1 "defekt"; +VAL_ 976 FT_FH_S_ManHoch 0 "Init" 1 "FH_Schalter_man_hoch_betaetigt"; +VAL_ 976 FT_FH_S_AutoHoch 0 "Init" 1 "FH_Schalter_auto_hoch_betaetigt"; +VAL_ 976 FT_FH_S_ManTief 0 "Init" 1 "FH_Schalter_man_tief_betaetigt"; +VAL_ 976 FT_FH_S_AutoTief 0 "Init" 1 "FH_Schalter_auto_tief_betaetigt"; +VAL_ 976 FT_FH_Bew_hoch 0 "Init" 1 "FH_in_Bewegung_hoch"; +VAL_ 976 FT_FH_Bew_tief 0 "Init" 1 "FH_in_Bewegung_tief"; +VAL_ 976 FT_FH_Fang 0 "ausserhalb_Fangbereich" 1 "innerhalb_Fangbereich"; +VAL_ 976 FT_FH_Block 0 "Init" 1 "Fenster_Block"; +VAL_ 976 FT_FH_Thermo 0 "Init" 1 "Thermoschutz_aktiv"; +VAL_ 976 FT_UEKB_aktiviert 0 "Init" 1 "UEKB_aktiv"; +VAL_ 976 ASW_HMI_defekt 0 "iO" 1 "defekt"; +VAL_ 976 FT_FH_normiert 0 "Init" 1 "Fenster_normiert"; +VAL_ 976 FT_Schliesstaster 1 "Schliesstaster_betaetigt"; +VAL_ 976 FT_Zuziehhilfe_aktiv 0 "Init" 1 "Zuziehilfe_aktiv"; +VAL_ 976 FT_SP_ausgerastet 0 "Init" 1 "Spiegel_ausgerastet"; +VAL_ 976 FT_SP_lr_aktiv 0 "Init" 1 "Spiegel_xAchse_aktiv"; +VAL_ 976 FT_SP_ht_aktiv 0 "Init" 1 "Spiegel_yAchse_aktiv"; +VAL_ 976 ASW_wakeup 0 "Sleep" 1 "Wakeup"; +VAL_ 976 FT_Oben_Block_erw 0 "Fensterheber_nicht_in_Blockerwar" 1 "Fensterheber_in_Blockerwartung_o"; +VAL_ 976 FT_Unten_Block_erw 0 "Fensterheber_nicht_in_Blockerwar" 1 "Fensterheber_in_Blockerwartung_u"; +VAL_ 976 FT_Kisi_li_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 976 FT_Kisi_re_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 976 FT_Kisi_Taster_li 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 976 FT_Kisi_Taster_re 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 976 FT_BFS_Fond_Freigabe 0 "Init" 1 "Freigabe_fuer_Fondbedienung_BFS"; +VAL_ 976 FT_Kisi_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 976 FT_Daemmglas 0 "Normalglas_verbaut" 1 "Daemmglas_verbaut"; +VAL_ 976 FT_SP_Heizung_Status 0 "Init" 1 "Status_Spiegelheizung_ein"; +VAL_ 976 ASW_Warnung_aktiv_FS 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 976 FT_FH_Pos_oben 1 "Scheibe oben (nach Absenken auf Position)"; +VAL_ 976 FT_Tuerschloss_defekt 0 "Tuerschloss_funktionsfaehig" 1 "Tuerschloss_defekt"; +VAL_ 976 FT_SWA_Taster 0 "Taster_nicht_betaetigt" 1 "Taster_betaetigt"; +VAL_ 976 SWA_HMI_Diagnose 0 "kein_Fehler_erkannt" 1 "Fehler_Taster_erkannt" 2 "Fehler_LED_erkannt" 3 "Fehler_LED_und_Taster_erkannt"; +VAL_ 976 FS_Status_eTAG 0 "Init" 1 "Griff_ausgefahren" 2 "Griff_eingefahren" 3 "Fehler"; +VAL_ 980 BH_Blinker_li 0 "nicht_betaetigt" 1 "Blinkerhebel_Pos_li_betaetigt"; +VAL_ 980 BH_Blinker_re 0 "nicht_betaetigt" 1 "Blinkerhebel_Pos_re_betaetigt"; +VAL_ 980 BH_Lichthupe 0 "nicht_betaetigt" 1 "Blinkerhebel in Richtung Lichthupe betaetigt"; +VAL_ 980 BH_Fernlicht 0 "nicht_betaetigt" 1 "Blinkerhebel_in_Richtung_Fernlicht_betaetigt"; +VAL_ 980 WH_Tipwischen 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 980 WH_Intervall 0 "aus" 1 "Wischerhebel in Stellung Intervall"; +VAL_ 980 WH_WischerStufe1 0 "aus" 1 "Wischerhebel in Stufe Wischen 1"; +VAL_ 980 WH_WischerStufe2 0 "aus" 1 "Wischerhebel in Stufe Wischen 2"; +VAL_ 980 WH_Frontwaschen 0 "aus" 1 "Wischerhebel in Stellung Wisch Wasch vorne"; +VAL_ 980 WH_Heckintervall 0 "nicht_betaetigt" 1 "Wischerhebel in Stellung Heckintervall"; +VAL_ 980 WH_Heckwaschen 0 "nicht_betaetigt" 1 "Wischerhebel in Stellung Wisch Wasch hinten"; +VAL_ 980 WH_Intervallstufen 0 "Init / Default" 1 "Intervallstufe 1" 5 "Intervallstufe 2" 9 "Intervallstufe 3" 13 "Intervallstufe 4" 15 "Fehler"; +VAL_ 980 FAS_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 980 FAS_Taster_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 980 SMLS_Hupe 0 "nicht_betaetigt" 1 "Hupe_gedrueckt"; +VAL_ 980 LRH_On_Off 0 "LRH_aus__keine Anzeige" 1 "LRH_aus" 2 "LRH_ein" 3 "Fehler"; +VAL_ 980 LRH_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 980 SMLS_P_verriegelt_plausibel 0 "unplausibel" 1 "plausibel"; +VAL_ 980 WH_SRA 0 "SRA_Aus" 1 "SRA_Ein"; +VAL_ 980 WH_Wischer_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 980 BH_Blinker_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 980 SMLS_PTT 0 "nicht_betaetigt" 1 "PTT_gedrueckt"; +VAL_ 980 WH_Tipwischen_lang 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 981 BCM1_Kurvenlicht_links_Anf 0 "linkes_Kurvenlicht/Abbiegelicht_durch_BCM1_nicht_angesteuert" 1 "linkes_Kurven/Abbiegelicht_durch_BCM1_angesteuert"; +VAL_ 981 BCM1_Kurvenlicht_rechts_Anf 0 "rechtes_Kurvenlicht/Abbiegelicht_durch_BCM1_nicht_angesteuert" 1 "rechtes_Kurvenlicht/Abbiegelicht_durch_BCM1_angesteuert"; +VAL_ 981 BCM1_Standlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Abblendlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Fernlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Nebellicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Parklicht_li_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Parklicht_re_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Nebelschluss_Ahg_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Nebelschluss_Fzg_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Schlusslicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM_Rueckfahrlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht_angefordert"; +VAL_ 981 BCM1_Signaturlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht_ist_einzuschalten"; +VAL_ 981 BCM1_Umfeldleuchten_Anf 0 "Licht_nicht_angefordert" 1 "Licht_ist_einzuschalten"; +VAL_ 981 BCM1_Tagfahrlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Regenlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Autobahnlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht ist einzuschalten"; +VAL_ 981 BCM1_Touristen_Licht_Anf 0 "Licht_nicht_angefordert" 1 "Anforderung von Touristenlicht"; +VAL_ 981 BCM1_CH_aktiv 0 "Inaktiv" 1 "Aktiv"; +VAL_ 981 BCM1_LH_aktiv 0 "Inaktiv" 1 "Aktiv"; +VAL_ 981 BCM1_Gleitende_Leuchtw_Anf 0 "Aus" 1 "Ein"; +VAL_ 981 BCM1_GLW_Fernlicht_Anf 0 "Aus" 1 "Ein"; +VAL_ 981 BCM1_Adaptive_Lichtvert_Anf 0 "Aus" 1 "Ein"; +VAL_ 981 BCM1_FoD_Sperrung_WiBli 0 "Freigabe_WiBli" 1 "Sperrung_WiBli" 2 "Init"; +VAL_ 981 BCM1_FOD_Sperrung_Animationen_HL 0 "Freigabe_Animationen" 1 "Sperrung_Animationen" 2 "Init"; +VAL_ 981 BCM1_Animationssperrung 0 "keine_Sperrung" 1 "Sperrung"; +VAL_ 981 BCM1_CH_LH_aktiv 0 "Comming_Home_Bzw._Leaving_Home_nicht_aktiv" 1 "Comming Home bzw. Leaving Home aktiv"; +VAL_ 981 BCM1_Allwetterlicht_Anf 0 "Licht_nicht_angefordert" 1 "Licht_ist_einzuschalten"; +VAL_ 981 BCM1_Schlusslicht_Signatur 0 "keine_Signatur" 1 "Signatur_1" 2 "Signatur_2" 3 "Signatur_3" 4 "Signatur_4" 5 "Signatur_5" 6 "Signatur_6" 7 "Signatur_7" 8 "Signatur_8" 9 "Signatur_9" 10 "Signatur_10" 11 "Signatur_11" 12 "Signatur_12" 13 "Signatur_13" 14 "Signatur_14" 15 "Signatur_15"; +VAL_ 982 BCM2_Bremsl_durch_ECD 0 "Bremslicht_ist_aus" 1 "Bremslicht_durch_ECD_aktiv"; +VAL_ 982 LH_Aussenlicht_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Standlicht_H_aktiv 1 "Standlicht hinten aktiv"; +VAL_ 982 LH_Parklicht_HL_aktiv 0 "nicht aktiv" 1 "Parklicht hinten links aktiv"; +VAL_ 982 LH_Parklicht_HR_aktiv 0 "nicht aktiv" 1 "Parklicht hinten rechts aktiv"; +VAL_ 982 LH_Bremslicht_H_aktiv 1 "Bremslicht hinten aktiv"; +VAL_ 982 LH_Nebelschluss_aktiv 0 "nicht aktiv" 1 "aktiv"; +VAL_ 982 LH_Rueckfahrlicht_aktiv 0 "nicht aktiv" 1 "aktiv"; +VAL_ 982 LH_Blinker_HL_akt 1 "Blinker hinten links aktiv"; +VAL_ 982 LH_Blinker_HR_akt 1 "Blinker hinten rechts aktiv"; +VAL_ 982 LH_Blinker_li_def 0 "OK" 1 "Blinker hinten links defekt"; +VAL_ 982 LH_Bremsl_li_def 0 "OK" 1 "mindestens ein Bremslicht hinten links defekt"; +VAL_ 982 LH_Schlusslicht_li_def 0 "OK" 1 "mindestens ein Schlusslicht hinten links defekt"; +VAL_ 982 LH_Rueckf_li_def 0 "OK" 1 "Rückfahrlicht hinten links defekt"; +VAL_ 982 LH_Nebel_li_def 0 "OK" 1 "Nebelschlusslicht hinten links defekt"; +VAL_ 982 LH_Schluss_Brems_Nebel_li_def 0 "iO" 1 "defekt"; +VAL_ 982 LH_Schluss_Brems_Nebel_re_def 0 "iO" 1 "defekt"; +VAL_ 982 LH_Zusatzschlussl_def 0 "OK" 1 "mindestens_ein_Zusatzschlusslicht_defekt"; +VAL_ 982 LH_Schluss_Brems_li_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Schluss_Nebel_li_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_SL_BRL_BLK_li_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Brems_Blk_li_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Diag_Status_re_def 0 "OK" 1 "Aussenlict_Diagnose_Systemstoerung_rechts"; +VAL_ 982 LH_Diag_Status_li_def 0 "OK" 1 "Aussenlicht_Diagnose_Systemstoerung_links"; +VAL_ 982 LH_Diag_LED_li_def 0 "OK" 1 "Heckleuchte_links_defekt"; +VAL_ 982 LH_Diag_LED_re_def 0 "OK" 1 "Heckleuchte_rechts_defekt"; +VAL_ 982 LH_Blinker_re_def 0 "OK" 1 "Blinker hinten rechts defekt"; +VAL_ 982 LH_Bremsl_re_def 0 "OK" 1 "mindestens ein Bremslicht hinten rechts defekt"; +VAL_ 982 LH_Schlusslicht_re_def 0 "OK" 1 "mindestens ein Schlusslicht hinten rechts defekt"; +VAL_ 982 LH_Rueckf_re_def 0 "OK" 1 "Rückfahrlicht hinten rechts defekt"; +VAL_ 982 LH_Nebel_re_def 0 "OK" 1 "Nebelschlusslicht hinten rechts defekt"; +VAL_ 982 LH_Schluss_Brems_mi_def 0 "OK" 1 "Defekt"; +VAL_ 982 LH_Schluss_Brems_re_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Schluss_Nebel_re_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_SL_BRL_BLK_re_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Brems_Blk_re_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Kennzl_def 0 "OK" 1 "Kennzeichenbeleuchtung hinten defekt"; +VAL_ 982 LH_3_Bremsl_def 0 "OK" 1 "hochgesetzte Bremsleuchte defekt"; +VAL_ 982 LH_Nebel_mi_def 0 "OK" 1 "Nebelschlusslicht hinten Mitte defekt"; +VAL_ 982 LH_Rueckf_mi_def 0 "OK" 1 "Rückfahllicht Mitte defekt"; +VAL_ 982 LH_Schlusslicht_mi_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Bremsl_mi_def 0 "OK" 1 "defekt"; +VAL_ 982 LH_Bremsl_li_ges_def 0 "OK" 1 "Alle Bremslichter hinten links defekt"; +VAL_ 982 LH_Bremsl_re_ges_def 0 "OK" 1 "Alle Bremslichter hinten rechts defekt"; +VAL_ 988 EPB_Status 0 "offen" 1 "geschlossen_Parken" 2 "teilgespannt_Halten" 3 "im_Lauf_oeffnen" 4 "im_Lauf_schliessen" 5 "tbd" 6 "Init" 7 "unbekannt"; +VAL_ 988 GE_Fahrstufe 0 "Zwischenstellung" 1 "Init" 5 "P" 6 "R" 7 "N" 8 "D" 9 "D" 10 "E" 13 "T" 14 "T" 15 "Fehler"; +VAL_ 997 FT_Tuer_Status 0 "Init" 1 "Tuer_geschlossen" 2 "Tuer_offen" 3 "Fehler"; +VAL_ 997 FT_Tuer_Status_QBit 0 "Status_Tuerkontakt_sicher" 1 "Status_Tuerkontakt_unsicher"; +VAL_ 997 FT_Lock_Taster_02 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 997 FT_Schluesselschalter_zu_02 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 997 FT_BFS_Tuer_Status 0 "Init" 1 "Tuer_geschlossen" 2 "Tuer_offen" 3 "Fehler"; +VAL_ 997 FT_HBFS_Tuer_Status 0 "Init" 1 "Tuer_geschlossen" 2 "Tuer_offen" 3 "Fehler"; +VAL_ 997 FT_HFS_Tuer_Status 0 "Init" 1 "Tuer_geschlossen" 2 "Tuer_offen" 3 "Fehler"; +VAL_ 997 FT_Tueroeffnen_Warnung 0 "Tuerwarnung_nicht_aktiv" 1 "Tuerwarnung_aktiv"; +VAL_ 997 FT_SP_Heizung_ein 0 "Aus" 1 "Ein"; +VAL_ 997 FT_Kisi_Taster_li_02 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 997 FT_Kisi_Taster_re_02 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 997 FT_TD_Taste_Status 0 "kein_Fehler" 1 "Kurzschluss_nach_Minus" 2 "Kurzschluss_nach_Plus" 3 "Leitungsunterbrechung"; +VAL_ 997 FT_TCR_Mode_aktiv 0 "TCR_Mode_deaktiv" 1 "TCR_Mode_aktiv"; +VAL_ 997 FS_Push_Tuergriff 0 "nicht_erkannt" 1 "erkannt"; +VAL_ 1004 TSK_State 0 "init" 1 "disabled" 2 "enabled" 3 "regulating" 4 "accel_pedal_override" 5 "brake_only" 6 "temp_fault" 7 "perm_fault"; +VAL_ 1122 PSD_Segment_ID 0 "keine Segmentinformationen vorhanden" 1 "Fehlerwert"; +VAL_ 1122 PSD_Vorgaenger_Segment_ID 0 "keine Segmentinformation vorhanden" 1 "Fehlerwert"; +VAL_ 1122 PSD_Strassenkategorie 0 "Rest_Feldweg_Schotterweg_Privatweg" 1 "Ortsstraߥ" 2 "Kreisstraߥ" 3 "Landstraߥ" 4 "Bundesstraߥ" 5 "Autobahn" 7 "Init"; +VAL_ 1122 PSD_Endkruemmung 255 "Gerade"; +VAL_ 1122 PSD_Endkruemmung_Vorz 0 "Kruemmung_positiv" 1 "Kruemmung_negativ"; +VAL_ 1122 PSD_Idenditaets_ID 0 "keine_Segment_Informationen_vorhanden" 1 "Fehler"; +VAL_ 1122 PSD_ADAS_Qualitaet 0 "keine_ADAS_Qualitaet" 1 "ADAS_Qualitaet"; +VAL_ 1122 PSD_wahrscheinlichster_Pfad 0 "Pfad_mit_geringer_Wahrscheinlichkeit" 1 "wahrscheinlichster_Pfad"; +VAL_ 1122 PSD_Geradester_Pfad 0 "nicht_geradester_PFad" 1 "geradester_Pfad"; +VAL_ 1122 PSD_Fahrspuren_Anzahl 0 "Einbahnstrasse_in_falsche_Richtung" 1 "eine_Fahrspur" 2 "zwei_Fahrspuren" 3 "drei_Fahrspuren" 4 "vier_Fahrspuren" 5 "fuenf_Fahrspuren" 6 "sechs_Fahrspuren" 7 "mehr_als_sechs_Fahrspuren"; +VAL_ 1122 PSD_Bebauung 0 "ausserhalb_bebauten_Gebietes" 1 "innerhalb_bebauten_Gebietes"; +VAL_ 1122 PSD_Segment_Komplett 0 "Segment_Attribute_nicht_komplett" 1 "Segment_Attribute_komplett"; +VAL_ 1122 PSD_Rampe 0 "Strasse_mit_Gegenverkehr" 1 "Auffahrt_Einbahnstr" 2 "Abfahrt_Einbahnstr" 3 "Einbahnstrasse"; +VAL_ 1122 PSD_Anfangskruemmung 255 "Gerade"; +VAL_ 1122 PSD_Anfangskruemmung_Vorz 0 "positiv" 1 "negativ"; +VAL_ 1122 PSD_Abzweigerichtung 0 "rects_abzweigende_Strasse" 1 "links_abzweigende_Strasse"; +VAL_ 1123 PSD_Pos_Segment_ID 0 "keine Position gegeben" 1 "Fehlerwert"; +VAL_ 1123 PSD_Pos_Standort_Eindeutig 0 "mehrdeutiger_Standort" 1 "eindeutiger_Standort"; +VAL_ 1123 PSD_Pos_Fehler_Laengsrichtung 0 "Init" 1 "< 2m" 2 "< 5m" 3 "< 10m" 4 "< 20m" 5 "< 50m" 6 "> 50m" 7 "Off-Road"; +VAL_ 1123 PSD_Pos_Fahrspur 0 "unbekannt" 1 "Erste_Spur_von_rechts" 2 "Zweite_Spur_von_rechts" 3 "Dritte_Spur_von_rechts" 4 "Vierte_Spur_von_rechts" 5 "Fuenfte_Spur_von_rechts" 6 "Sechte_Spur_von_rechts" 7 "Siebte_oder_weitere_Spur_von_rechts"; +VAL_ 1123 PSD_Attribut_Segment_ID_05 0 "keine_Segment_Information" 1 "Fehler"; +VAL_ 1123 PSD_Attribut_1_ID 0 "keine_Information"; +VAL_ 1123 PSD_Attribut_2_ID 0 "keine_Information"; +VAL_ 1123 PSD_Attribute_Komplett_05 0 "Attribute_nicht_komplett" 1 "Attribute_komplett"; +VAL_ 1124 PSD_06_Mux 0 "Init"; +VAL_ 1124 PSD_Sys_Segment_ID 0 "keine Segmentinformationen vorhanden" 1 "nicht zulaessig"; +VAL_ 1124 PSD_Sys_Geschwindigkeit_Einheit 0 "km/h" 1 "mph"; +VAL_ 1124 PSD_Sys_Verkehrsrichtung 0 "Rechtsverkehr" 1 "Linksverkehr"; +VAL_ 1124 PSD_Sys_Geometrieguete 0 "Geringe_Guete" 1 "tbd" 2 "tbd" 3 "Hohe_Guete"; +VAL_ 1124 PSD_Sys_Mapmatchingguete 0 "geringe_Guete" 1 "res" 2 "res" 3 "hohe_Guete"; +VAL_ 1124 PSD_Sys_Alter_Karte 0 "kleiner_1_Jahr" 1 "1_Jahr" 2 "2_Jahre" 3 "3_Jahre" 4 "4_Jahre" 5 "5_Jahre" 6 "6_Jahre" 7 "groesser_7_Jahre"; +VAL_ 1124 PSD_Sys_Zielfuehrung 0 "Zielfuehrung nicht aktiv" 1 "Zielfuehrung aktiv"; +VAL_ 1124 PSD_Sys_US_State 0 "kein_US_State" 1 "Alabama" 2 "Alaska" 3 "Arkansas" 4 "Arizona" 5 "California" 6 "Colorado" 7 "Conneticut" 8 "District_of_Columbia" 9 "Delaware" 10 "Florida" 11 "Georgia" 12 "Hawaii" 13 "Idaho" 14 "Illinois" 15 "Iowa" 16 "Indiana" 17 "Kansas" 18 "Kentucky" 19 "Louisiana" 20 "Massachusetts" 21 "Maryland" 22 "Maine" 23 "Michigan" 24 "Minnesota" 25 "Missouri" 26 "Mississippi" 27 "Montana" 28 "North_Carolina" 29 "North_Dakota" 30 "Nebraska" 31 "Nevada" 32 "New_Hampshire" 33 "New_Jersey" 34 "New_Mexico" 35 "New_York" 36 "Ohio" 37 "Oklahoma" 38 "Oregon" 39 "Pennsylvania" 40 "Puerto_Rico" 41 "Rhode_Island" 42 "South_Carolina" 43 "South_Dakota" 44 "Tennessee" 45 "Texas" 46 "Utah" 47 "Virginia" 48 "Virgin_Islands" 49 "Vermont" 50 "Washington" 51 "Wisconsin" 52 "West_Virginia" 53 "Wyoming"; +VAL_ 1124 PSD_Sys_Quali_verfuegbar 0 "Qualitaetskriterien_nicht_verfuegbar" 1 "Qualitaetskriterien_verfuegbar"; +VAL_ 1124 PSD_Sys_Zielfuehrung_geaendert 0 "Zielfuehrung_nicht_geaendert" 1 "Zielfuehrung_geaendert"; +VAL_ 1124 PSD_Sys_Geometrieguete_erweitert 0 "Init"; +VAL_ 1124 PSD_Attribut_Segment_ID 0 "keine_Segment_Information_vorhanden" 1 "Fehler"; +VAL_ 1124 PSD_Attribut_3_ID 0 "keine_Information"; +VAL_ 1124 PSD_Attribut_4_ID 0 "keine_Information"; +VAL_ 1124 PSD_Attribut_5_ID 0 "keine_Information"; +VAL_ 1124 PSD_Attribute_Komplett_06 0 "Attribute_nicht_komplett" 1 "Attribute_komplett"; +VAL_ 1124 PSD_Ges_Segment_ID 0 "keine Segmentinformationen vorhanden" 1 "nicht zulaessig"; +VAL_ 1124 PSD_Ges_Geschwindigkeit 0 "Kein Geschwindigkeitsgebot" 1 "0 km/h < v_max < 5 km/h" 2 "5 km/h < v_max < 10km/h" 3 "10 km/h < v_max < 15 km/h" 4 "15 km/h < v_max < 20 km/h" 5 "20 km/h < v_max < 25 km/h" 6 "25 km/h < v_max < 30 km/h" 7 "30 km/h < v_max < 35 km/h" 8 "35 km/h < v_max < 40 km/h" 9 "40 km/h < v_max < 45 km/h" 10 "45 km/h < v_max < 50 km/h" 11 "50 km/h < v_max < 60 km/h" 12 "60 km/h < v_max < 70 km/h" 13 "70 km/h < v_max < 80 km/h" 14 "80 km/h < v_max < 90 km/h" 15 "90 km/h < v_max < 100 km/h" 16 "100 km/h < v_max < 110 km/h" 17 "110 km/h < v_max < 120 km/h" 18 "120 km/h < v_max < 130 km/h" 19 "130 km/h < v_max < 140 km/h" 20 "140 km/h < v_max < 150 km/h" 21 "150 km/h < v_max < 160 km/h" 22 "160 km/h < v_max" 23 "Geschwindigkeitsgebot aufgehoben" 24 "..0x1F ungültig"; +VAL_ 1124 PSD_Ges_Typ 0 "Geschw_Klasse_des_Kartendatensuppliers" 1 "Explizit_abgeleiteten_Begrenzung" 2 "Durch_Gesetzg_vorgeg_allgem_Gebot_fuer_uebertr_Rahmenbed" 3 "Init"; +VAL_ 1124 PSD_Ges_Spur_Geschw_Begrenzung 0 "Gebot_fuer_alle_spuren_gueltig"; +VAL_ 1124 PSD_Ges_Geschwindigkeit_Gespann 0 "alle Fahrzeuge" 1 "PKW mit Gespann" 2 "LKW, Busse, etc."; +VAL_ 1124 PSD_Ges_Geschwindigkeit_Witter 0 "Witterungsunabh䮧ig" 1 "N䳳e, Regen, Niederschlag" 2 "Gl䴴e" 3 "Nebel"; +VAL_ 1124 PSD_Ges_Geschwindigkeit_Tag_Anf 0 "kein Beginn definiert" 1 "Montag" 2 "Dienstag" 3 "Mittwoch" 4 "Donnerstag" 5 "Freitag" 6 "Samstag" 7 "Sonntag"; +VAL_ 1124 PSD_Ges_Geschwindigkeit_Tag_Ende 0 "kein Ende definiert" 1 "Montag" 2 "Dienstag" 3 "Mittwoch" 4 "Donnerstag" 5 "Freitag" 6 "Samstag" 7 "Sonntag"; +VAL_ 1124 PSD_Ges_Geschwindigkeit_Std_Anf 25 "kein Beginn für stundenweise Einschr䮫ungen"; +VAL_ 1124 PSD_Ges_Geschwindigkeit_Std_Ende 25 "kein Ende für stundenweise Einschr䮫ungen"; +VAL_ 1124 PSD_Ges_Ueberholverbot 0 "kein ܢerholverbot" 1 "alle Fahrzeuge" 2 "ܢerholverbot für PKW mit Gespann" 3 "ܢerholverbot für LKW, Busse, etc."; +VAL_ 1124 PSD_Ges_Wechselverkehrszeichen 0 "Kein Wechselverkehrszeichen" 1 "Wechselverkehrszeichen links" 2 "Wechselverkehrszeichen rechts" 3 "Wechselverkehrszeichen links und rechts" 4 "Wechselverkerhszeichen über der Fahrbahn"; +VAL_ 1124 PSD_Wechselverkehrszeichen_Typ 0 "kein_Wechselverkehrszeichen" 1 "LED_Wechselverkehrszeichen" 2 "nicht_LED_Wechselverkehrszeichen"; +VAL_ 1124 PSD_Ges_Gesetzlich_Kategorie 0 "kein_legales_Verbot" 1 "innerorts" 2 "ausserorts" 3 "Autobahn"; +VAL_ 1124 PSD_Ges_Gesetzlich_Zusatz 0 "kein_Zusatz_zu_legalem_Gebot" 1 "Anhaenger_Klasse_1" 2 "Anhaenger_Klasse_2"; +VAL_ 1124 PSD_Ges_Verkehrszeichen_Quelle 0 "VZA_kein_Onlinedienst" 1 "nur_VZA" 2 "nur_VZO" 3 "VZA_und_VZO"; +VAL_ 1124 PSD_Ges_Attribute_Komplett 0 "Attribute_nicht_komplett" 1 "Attribute_komplett"; +VAL_ 1124 PSD_Baum_Laenge_VZ 0 "Ost" 1 "West"; +VAL_ 1124 PSD_Baum_Breite_VZ 0 "Nord" 1 "Sued"; +VAL_ 1124 PSD_Steigung_1_Segment_ID 0 "keine_Segment_Information_vorhanden" 1 "Fehler"; +VAL_ 1124 PSD_Steigung_1_A_Steigung 126 "mehr_als_15_Prozent" 127 "Steigung_unbekannt"; +VAL_ 1124 PSD_Steigung_1_A_Vorz 0 "Gefaelle" 1 "Steigung"; +VAL_ 1124 PSD_Steigung_1_B_Steigung 126 "mehr_als_15_Prozent" 127 "Steigung_unbekannt"; +VAL_ 1124 PSD_Steigung_1_B_Vorz 0 "Gefaelle" 1 "Steigung"; +VAL_ 1124 PSD_Steigung_1_Attribute_kompl 0 "Steigungen_nicht_komplett" 1 "Steigungen_komplett"; +VAL_ 1124 PSD_Steigung_2_Segment_ID 0 "keine_Segment_Information_vorhanden" 1 "Fehler"; +VAL_ 1124 PSD_Steigung_2_Steigung 126 "mehr_als_15_Prozent" 127 "Steigung_unbekannt"; +VAL_ 1124 PSD_Steigung_2_Vorz 0 "Gefaelle" 1 "Steigung"; +VAL_ 1124 PSD_Steigung_2_Attribute_kompl 0 "Steigungen_nicht_komplett" 1 "Steigungen_komplett"; +VAL_ 1153 ZR_LoGeWa_Event_Kombiwarnung 0 "Init" 1 "Unfall" 2 "Traktionsverlust" 3 "Panne" 4 "Sichtbehinderung" 5 "Aquaplaning" 6 "EEBL" 7 "SEF_stat" 8 "SEF_dyn_allgemein" 9 "SEF_dyn_vorne" 10 "SEF_dyn_hinten" 11 "SEF_dyn_links" 12 "SEF_dyn_rechts" 13 "Stauende"; +VAL_ 1153 Nav_FoD_Status 0 "Init" 1 "Nav_permanently_available" 2 "FoD_Nav_not_activated" 3 "FoD_Nav_activated" 4 "R4N_Nav_not_activated"; +VAL_ 1153 MIB_Tongenerator_PH_verfuegbar 0 "Tongenerator_nicht_verfuegbar" 1 "Tongenerator_vorne_verfuegbar" 2 "Tongenerator_hinten_verfuegbar" 3 "Tongenerator_gesamt_verfuegbar" 4 "Tongenerator_im_AMP"; +VAL_ 1153 DSSS_Warning 0 "No_Warning" 1 "Red_traffic_light_guidance" 2 "Stop_sign_warning" 3 "Rear_end_collision_avoidance_warning" 4 "Intersection_collision_avoidance_warning_right" 5 "Intersection_collision_avoidance_warning_left" 6 "turn_right_collision_avoidance" 7 "turn_left_collision_avoidance" 8 "pedestrian_crossing_right" 9 "pedestrian_crossing_left" 10 "bicycle_collision_right" 11 "bicycle_collision_left"; +VAL_ 1153 ZR_Kindersicherung_RSE 0 "inaktiv" 1 "aktiv"; +VAL_ 1153 ZR_RSE_aktivieren 0 "inaktiv" 1 "aktiv"; +VAL_ 1153 MMI_SDS_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1153 MU_SecondDisplay 0 "Init" 1 "gueltige_Karte" 2 "ungueltiges_Signal" 3 "Nicht_Verbaut"; +VAL_ 1153 MMI_Telefon_aktiv 0 "Telefongespraech_nicht_aktiv" 1 "Telefongespraech_aktiv"; +VAL_ 1153 MMI_Gurt_Mic_ref 0 "Downlink_inaktiv" 1 "Downlink_aktiv"; +VAL_ 1153 ZR_Sta_Inszenierung 0 "Init" 1 "Inszenierung_deaktiviert" 2 "Inszenierung_Start" 3 "Inszenierung_Stop"; +VAL_ 1153 MMI_Gauges_active 0 "gauges_inactive" 1 "gauges_active"; +VAL_ 1153 ZR_MXB_Manoever_Ansage 0 "keine_Ansage" 1 "Ansage_ohne_Richtung" 2 "Ansage_rechte_Richtung" 3 "Ansage_linke_Richtung"; +VAL_ 1153 ZR_LAPP_Sondermodus_Status 0 "keine_Anforderung" 1 "Sondermodus_aktiv" 2 "Aktivierung_nicht_moeglich"; +VAL_ 1153 MMI_StartStopp_Info 0 "Stoppfreigabe" 1 "Stoppverbot" 2 "Startanforderung" 3 "Fehler"; +VAL_ 1153 ZR_Parken_Sondermodus 0 "Init" 1 "Sondermodus_aktiv" 2 "Sondermodus_nicht_verfuegbar" 3 "WLAN_aus" 4 "WLAN_auscodiert" 15 "keine_WLAN_HW"; +VAL_ 1153 ZR_Rundenbewertung 0 "Bewertung_nicht_aktiv" 1 "langsamer" 2 "gleich_schnell" 3 "schneller" 4 "reserviert" 5 "reserviert" 6 "reserviert" 7 "reserviert" 8 "reserviert" 9 "reserviert" 10 "reserviert" 11 "reserviert" 12 "reserviert" 13 "reserviert" 14 "Init" 15 "Funktion_nicht_verbaut"; +VAL_ 1153 ZR_Rundenfortschritt 254 "Init" 255 "Funktion_nicht_verbaut"; +VAL_ 1155 Mo_Powermeter_Grenze 4093 "OFF"; +VAL_ 1155 MO_Text_Aktivierung_Antrieb 0 "keine_Anzeige" 1 "Ladestecker_nicht_fahrbereit" 2 "erneute_Aktivierung_erforderlich" 3 "Warten_Antrieb_wird_aktiviert" 4 "zum_Fahren_Bremse_und_Fahrstufe" 5 "h2_Tankklappe_nicht_fahrbereit" 6 "zum_Starten_Bremse_treten" 7 "zum_Starten_Kupplung_treten" 15 "Init"; +VAL_ 1155 MO_Powermeter_Inszenierung_aktiv 0 "keine_Anzeige" 1 "Inszenierung_aktiv"; +VAL_ 1155 MO_Powermeter_Charge_Grenze 1022 "Init" 1023 "Fehler"; +VAL_ 1155 MO_Powermeter_Grenze_strategisch 4094 "Init" 4095 "Fehler"; +VAL_ 1155 MO_Powermeter_untere_E_Grenze 4094 "Init" 4095 "Fehler"; +VAL_ 1155 MO_Powermeter_obere_E_Grenze 4094 "Init" 4095 "Fehler"; +VAL_ 1175 PH_Visualisierung 0 "Aus" 1 "Angefragt" 2 "InAnzeige" 3 "Abgefordert" 6 "Init" 7 "Fehler"; +VAL_ 1175 PDC_Tonausgabe_Front 0 "kein_Ton" 1 "Intervallton_1" 2 "Intervallton_2" 3 "Intervallton_3" 4 "Intervallton_4" 5 "Intervallton_5" 6 "Dauerton" 7 "Fehlerton" 8 "RCTATon"; +VAL_ 1175 PDC_Tonausgabe_Heck 0 "kein_Ton" 1 "Intervallton_1" 2 "Intervallton_2" 3 "Intervallton_3" 4 "Intervallton_4" 5 "Intervallton_5" 6 "Dauerton" 7 "Fehlerton" 8 "Erstwarnton_hinten" 9 "RCTATon"; +VAL_ 1175 PH_nachtr_Stopp_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 1175 PH_Abschaltursache 0 "keine, bzw. System aktiv" 1 "Abschaltung durch Herausnahme R-Gang" 2 "Abschaltung ueber Geschwindigkeit" 3 "Abschaltung ueber PDC-Taster" 4 "Abschaltung wegen PLA" 5 "Abschaltung durch KL 15 Bit = 0" 6 "tbd." 7 "Fehler-/gestört Zustand, System noch aktiv"; +VAL_ 1175 PH_Opt_Anzeige_V_ein 0 "optische Anzeige vorne nicht aktiv" 1 "optische Anzeige vorne aktiviert"; +VAL_ 1175 PH_Opt_Anzeige_H_ein 0 "Optische Anzeige aus" 1 "optische Anzeige hinten aktiviert"; +VAL_ 1175 PH_Opt_Anz_V_Hindernis 0 "optische Anzeige vorne meldet kein Hindernis" 1 "optische Anzeige vorne meldet Hindernis im Warnbereich"; +VAL_ 1175 PH_Opt_Anz_H_Hindernis 0 "optische Anzeige hinten meldet kein Hindernis" 1 "optische Anzeige hinten meldet Hindernis im Warnbereich"; +VAL_ 1175 PH_Tongeber_V_aktiv 0 "Tongeber vorne nicht aktiv" 1 "Tongeber vorne aktiv"; +VAL_ 1175 PH_Tongeber_H_aktiv 0 "Tongeber hinten nicht aktiv" 1 "Tongeber hinten aktiv"; +VAL_ 1175 PH_Tongeber_mute 0 "Tongeber nicht stummgeschaltet" 1 "Tongeber stummgeschaltet"; +VAL_ 1175 PH_Anf_Audioabsenkung 0 "Keine_Audioabsenkung" 1 "Anforderung_Audioabsenkung"; +VAL_ 1175 PH_Tongeber_H_verfuegbar 0 "nicht verfügbar" 1 "verfügbar"; +VAL_ 1175 PLA_Anf_Aufschaltung_RVC 0 "Keine_RVC_Aufschalteanf" 1 "RVC_Aufschalteanforderung"; +VAL_ 1175 PH_Taster 0 "Taster_nicht_gedrueckt" 1 "Taster_gedrueckt" 2 "reserviert" 3 "Fehler"; +VAL_ 1175 PH_Anf_Verdeck 0 "Verdeckbetrieb_freigegeben" 1 "Verdeckbetrieb_sperren" 2 "reserviert" 3 "reserviert"; +VAL_ 1175 PH_StartStopp_Info 0 "Motorlauf_nicht_notwendig_(Stoppfreigabe)" 1 "Motoranlauf_nicht_zwingend_notwendig_(Stoppverbot,keine_Startanforderung)" 2 "Motoranlauf_zwingend_notwendig_(Startanforderung)" 3 "Systemfehler"; +VAL_ 1175 PH_Stoermeldung 0 "keine_Anzeige_kein_Gong" 1 "Textmeldung_PDC_hinten_gestoert_mit_Gong" 2 "Textmeldung_PDC_hinten_gestoert_ohne_Gong" 3 "Textmeldung_PDC_vorn_gestoert_mit_Gong" 4 "Textmeldung_PDC_vorn_gestoert_ohne_Gong" 5 "Textmeldung_PDC_gestoert_mit_Gong" 6 "Textmeldung_PDC_gestoert_ohne_Gong" 7 "Textmeldung_PDC_seitlich_gestoert_mit_Gong" 8 "Textmeldung_PDC_seitlich_gestoert_ohne_Gong"; +VAL_ 1175 PH_defekt 0 "PH aktiv" 1 "PH wurde aufgrund eines Defektes deaktiviert"; +VAL_ 1175 PH_gestoert 0 "PH aktiv" 1 "PH wurde auf Grund einer Stoerung tempraer deaktiviert"; +VAL_ 1175 PH_Systemzustand 0 "Anlage aus" 1 "Anlage durch einlegen R-Gang aktiviert" 2 "Anlage manuell durch Taster aktiviert" 3 "Anlage automatisch aktiviert" 4 "Anlage durch ARA aktiviert" 6 "Init - Initialisierungsphase nach Kl. 15 ein / Reset" 7 "Fehler-/gestört Zustand, System noch aktiv"; +VAL_ 1175 PH_Display_Kundenwunsch 0 "Anzeige aus" 1 "Grafik" 2 "Rear View" 3 "automatisch"; +VAL_ 1283 HVK_Istmodus_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 1283 HVK_TN1_Sollmodus 0 "HV_Off" 1 "HV_On" 2 "reserviert" 3 "Initialisierung"; +VAL_ 1283 HVK_MO_EmSollzustand 0 "HvOff" 1 "HvStbyReq" 2 "HvStbyWait" 3 "HvBattOnReq" 4 "HvBattOnWait" 10 "HvOnIdle" 18 "HvOnDrvReq" 19 "HvOnDrvWait" 20 "HvOnDrvRdy" 28 "HvStepUpReq" 29 "HvStepUpWait" 30 "HvStepUp" 38 "HvStepDownReq" 39 "HvStepDownWait" 40 "HvStepDown" 46 "HvAcChPreReq" 47 "HvAcChPreWait" 48 "HvAcChReq" 49 "HvAcChWait" 50 "HvAcCh" 56 "HvDcChPreReq" 57 "HvDcChPreWait" 58 "HvDcChReq" 59 "HvDcChWait" 60 "HvDcCh" 67 "HvChOffReq" 68 "HvChOffWait" 69 "HvOnIdleReq" 70 "HvOnIdleWait" 96 "HvCpntOffReq" 97 "HvCpntOffWait" 98 "HvBattOffReq" 99 "HvBattOffWait" 109 "HvDcDcFailOffReq" 110 "HvDcDcFail" 119 "HvElmOffReq" 120 "HvElmOff" 126 "HvFailCpntOffReq" 127 "HvFailCpntOffWait" 128 "HvFailBattOffReq" 129 "HvFailBattOffWait" 130 "HvFailBattOff" 138 "HvFailUCtlReq" 139 "HvFailUCtlWait" 140 "HvFailUCtl" 150 "HvEmgcyOff" 255 "Init"; +VAL_ 1283 HVK_BMS_Sollmodus 0 "HV_Off" 1 "HV_On" 3 "AC_Laden_erw" 4 "AC_Laden" 6 "DC_Laden" 7 "Init"; +VAL_ 1283 HVK_DCDC_Sollmodus 0 "Standby" 1 "HV_On_Vorladen" 2 "Tiefsetzen" 3 "Hochsetzen" 4 "Pruefpuls_12V" 7 "Initialisierung"; +VAL_ 1283 HVK_EKK_Sollmodus 0 "Keine_Freigabe" 1 "Freigabe" 2 "Freigabe_ausgesetzt" 7 "Init"; +VAL_ 1283 HVK_HVPTC_Sollmodus 0 "Keine_Freigabe" 1 "Freigabe" 2 "Freigabe_ausgesetzt" 7 "Init"; +VAL_ 1283 HVK_HVLM_Sollmodus 0 "keine_Freigabe" 1 "Freigabe_Lademanager" 2 "Vorladung_AC_Pfad" 7 "Init"; +VAL_ 1283 HVK_HV_Netz_Warnungen 0 "Keine_Warnung" 1 "Warntext_HV_Netz_Anf" 2 "Fehlertext_HV_Netz_Anf" 3 "Warnung_Kein_Wiederstart_moeglich"; +VAL_ 1283 HV_Bordnetz_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1283 HV_Bordnetz_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 1283 HVK_Gesamtst_Spgfreiheit 0 "Funktion_Init__ohne_Funktion" 1 "HV_System_spannungsfrei" 2 "HV_System_nicht_spannungsfrei" 3 "Fehler"; +VAL_ 1283 HVK_AktiveEntladung_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 1283 HVK_Iso_Messung_Start 0 "keine_Messung" 1 "Messung_HV_Netz_1" 2 "Messung_HV_Netz_2" 4 "deaktiviert"; +VAL_ 1283 HVK_DCDC_EKK_Sollmodus 0 "aus" 1 "ein" 2 "reserviert" 3 "Init"; +VAL_ 1312 LoGeWa_Event_Kombiwarnung 0 "Init" 1 "Unfall" 2 "Traktionsverlust" 3 "Panne" 4 "Sichtbehinderung" 5 "Aquaplaning"; +VAL_ 1312 AB_Anforderung_eCall 0 "keine_Anforderung" 1 "Anforderung"; +VAL_ 1312 AB_Anprall_Seite_Beifahrer 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Anprall_Rollover 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Anprall_FGS 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Anprall_Front_Beifahrer 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Anprall_Front_Fahrer 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Anprall_Heck_Beifahrer 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Anprall_Heck_Fahrer 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 AB_Wickelklappung_Reihe2_MI 0 "nicht_verbaut" 1 "nicht_verfuegbar__Fehler_oder_Init" 2 "nicht_verriegelt" 3 "verriegelt"; +VAL_ 1312 AB_Belegung_VB 0 "nicht_verfuegbar" 1 "Fehler" 2 "nicht_belegt" 3 "belegt"; +VAL_ 1312 AB_Abschaltanf_SIH_BF 0 "Normalbetrieb" 1 "Abschaltung_angefordert"; +VAL_ 1312 AB_Anprall_Seite_Fahrer 0 "kein_Anprall" 1 "Anprall_erkannt"; +VAL_ 1312 SC_PAO_Schriftzug_Anf 0 "LED aus" 1 "LED an" 2 "LED blinken" 3 "reserviert"; +VAL_ 1312 SC_PAO_ON_Anf 0 "LED aus" 1 "LED an" 2 "LED blinken" 3 "reserviert"; +VAL_ 1312 SC_PAO_OFF_Anf 0 "LED aus" 1 "LED an" 2 "LED blinken" 3 "reserviert"; +VAL_ 1312 AB_Crashschwere 0 "kein_Ereignis" 1 "Crashschwere_1" 2 "Crashschwere_2" 3 "Crashschwere_3" 4 "Crashschwere_4" 5 "Crashschwere_5" 6 "Crashschwere_2_bis_5" 7 "Fehler"; +VAL_ 1312 AB_Anforderung_USM 0 "keine_Anforderung" 1 "Anforderung"; +VAL_ 1312 AB_Gurtschloss_FA 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_BF 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_Reihe2_FA 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_Reihe2_MI 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_Reihe2_BF 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_Reihe3_FA 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_Reihe3_MI 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Gurtschloss_Reihe3_BF 0 "nicht_verbaut" 1 "nicht_verfügbar (Fehler oder Init)" 2 "nicht_gesteckt" 3 "gesteckt"; +VAL_ 1312 AB_Sitzpos_Sens_FA 0 "nicht verfügbar" 1 "Fehler" 2 "Sitz nicht vorne" 3 "Sitz vorne"; +VAL_ 1312 AB_Sitzpos_Sens_BF 0 "nicht verfügbar" 1 "Fehler" 2 "Sitz nicht vorne" 3 "Sitz vorne"; +VAL_ 1312 AB_Wickelklappung_Reihe2_BF 0 "nicht_verbaut" 1 "nicht_verfuegbar__Fehler_oder_Init" 2 "nicht_verriegelt" 3 "verriegelt"; +VAL_ 1312 AB_Wickelklappung_Reihe2_FA 0 "nicht_verbaut" 1 "nicht_verfuegbar__Fehler_oder_Init" 2 "nicht_verriegelt" 3 "verriegelt"; +VAL_ 1349 AB_Gurtwarn_Reihe2_FA 0 "nicht_verbaut" 1 "keine_Gurtwarnung_Sitz_leer" 2 "keine_Gurtwarnung_Sitz_belegt" 3 "Gurtwarnung_Sitz_belegt"; +VAL_ 1349 AB_Gurtwarn_Reihe2_BF 0 "nicht_verbaut" 1 "keine_Gurtwarnung_Sitz_leer" 2 "keine_Gurtwarnung_Sitz_belegt" 3 "Gurtwarnung_Sitz_belegt"; +VAL_ 1349 AbstWarn_MV_FAS_Fkt_Status 0 "Init" 1 "Funktion_Ist_Ein" 2 "Funktion_Ist_Aus" 3 "Fehler"; +VAL_ 1349 WarnBrems_Charisma_Status 0 "Init" 1 "verfügbar" 2 "nicht verfügbar" 3 "asynchron durch Fahrerwunsch"; +VAL_ 1349 WarnBrems_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 1349 AB_Gurtwarn_Reihe2_MI 0 "nicht_verbaut" 1 "keine_Gurtwarnung_Sitz_leer" 2 "keine_Gurtwarnung_Sitz_belegt" 3 "Gurtwarnung_Sitz_belegt"; +VAL_ 1349 AB_Gurtwarn_Reihe3_FA 0 "nicht_verbaut" 1 "keine_Gurtwarnung_Sitz_leer" 2 "keine_Gurtwarnung_Sitz_belegt" 3 "Gurtwarnung_Sitz_belegt"; +VAL_ 1349 AB_Gurtwarn_Reihe3_MI 0 "nicht_verbaut" 1 "keine_Gurtwarnung_Sitz_leer" 2 "keine_Gurtwarnung_Sitz_belegt" 3 "Gurtwarnung_Sitz_belegt"; +VAL_ 1349 AB_Gurtwarn_Reihe3_BF 0 "nicht_verbaut" 1 "keine_Gurtwarnung_Sitz_leer" 2 "keine_Gurtwarnung_Sitz_belegt" 3 "Gurtwarnung_Sitz_belegt"; +VAL_ 1349 LGI_FAS_Fkt_Status 0 "Init" 1 "Funktion_Ist_Ein" 2 "Funktion_Ist_Aus" 3 "Fehler"; +VAL_ 1349 PreCrash_FAS_Fkt_Status 0 "Init" 1 "Funktion_Ist_Ein" 2 "Funktion_Ist_Aus" 3 "Fehler"; +VAL_ 1349 AB_SBR_hinten_verbau 0 "ohne_SBR_hinten" 1 "mit_SBR_hinten" 2 "nicht_definiert" 3 "Init"; +VAL_ 1349 AWV_Einstellung_System_ASG 0 "deaktiviert" 1 "aktiviert"; +VAL_ 1349 AWV_Einstellung_Warnung_ASG 0 "Aus" 1 "Setting_2" 2 "Setting_3" 3 "Setting_4" 4 "Setting_5" 5 "Ein"; +VAL_ 1349 SC_PreSense_Modus_Warnung_NV 0 "Aus" 1 "Setting_2" 2 "Setting_3" 3 "Setting_4" 4 "Setting_5" 5 "Ein"; +VAL_ 1349 SC_PreSense_Modus_Warnung_MV 0 "Aus" 1 "Setting_2" 2 "Setting_3" 3 "Setting_4" 4 "Setting_5" 5 "Ein"; +VAL_ 1349 SC_PreSense_Modus_System_MV 0 "deaktiviert" 1 "aktiviert"; +VAL_ 1349 SC_PreSense_Modus_System_NV 0 "deaktiviert" 1 "aktiviert"; +VAL_ 1349 SC_PreSense_Modus_System_KAS 0 "deaktiviert" 1 "aktiviert"; +VAL_ 1355 PH_Verschmutzungsmeldung 0 "keine_Anzeige_kein_Gong" 1 "Textmeldung_PDC_hinten_verschmutzt_mit_Gong" 2 "Textmeldung_PDC_hinten_verschmutzt_ohne_Gong" 3 "Textmeldung_PDC_vorn_verschmutzt_mit_Gong" 4 "Textmeldung_PDC_vorn_verschmutzt_ohne_Gong" 5 "Textmeldung_PDC_verschmutzt_mit_Gong" 6 "Textmeldung_PDC_verschmutzt_ohne_Gong" 7 "Textmeldung_PDC_seitlich_verschmutzt_mit_Gong" 8 "Textmeldung_PDC_seitlich_verschmutzt_ohne_Gong"; +VAL_ 1355 PH_Aufschaltursache 0 "Anlage aus" 1 "Anlage durch einlegen R-Gang aktiviert" 2 "Anlage manuell durch Taster aktiviert" 3 "Anlage automatisch aktiviert" 4 "Anlage durch ARA aktiviert" 5 "Rueckwaertsrollen" 6 "Anlage_durch_PLA_aktiviert" 7 "Anlage_durch_IPA_aktiviert" 8 "Anlage_durch_FA_aktiviert" 9 "Anlage_durch_RBF_oder_MA_aktiviert" 10 "Anlage_durch_Smartphone_aktiviert" 11 "Anlage_durch_Jokertaste_aktiviert" 12 "Anlage_durch_Favoritentasten_aktiviert" 13 "Anlage_durch_SideViewTaster_aktiviert" 14 "Anlage_durch_RCTA_aktiviert" 15 "Anlage_durch_KAS_aktiviert" 16 "Anlage_durch_AWC_aktiviert" 30 "Init_Initialisierungsphase_nach_Kl_15_ein_oder_Reset" 31 "Fehler_gestoerter_Zustand_System_noch_aktiv"; +VAL_ 1355 PH_Ton_Ausgabe 0 "Init" 1 "Intervallton_vorne" 2 "Intervallton_hinten" 3 "Dauerton_vorne" 4 "Dauerton_hinten" 5 "Quittierungston" 6 "Reserviert" 7 "Fehler"; +VAL_ 1355 PH_Ton_Pausenlaenge 0 "Init" 1 "Pause_5ms" 2 "Pause_10ms" 3 "Pause_15ms" 100 "Pause_500ms" 101 "Reserviert" 126 "Reserviert" 127 "Fehler"; +VAL_ 1355 PH_Ton_Richtung 0 "vorne" 1 "vorne_rechts" 2 "rechts" 3 "rechts_hinten" 4 "hinten" 5 "hinten_links" 6 "links" 7 "vorne_links"; +VAL_ 1355 PH_Ton_Lautstaerke 0 "Minimallautstaerke" 1 "Lautstaerke_1" 2 "Lautstaerke_2" 3 "Lautstaerke_3" 4 "Lautstaerke_4" 5 "Lautstaerke_5" 6 "Lautstaerke_6" 7 "Maximallautstaerke"; +VAL_ 1355 BCM_WAH_Meldung 0 "Init" 1 "Fehlermeldung_bei_Nichtverfuegbarkeit_mit_Gong" 2 "Fehlermeldung_bei_Nichtverfuegbarkeit_ohne_Gong" 3 "Anzeige_dass_Fahrzeug_erkannt_wurde_und_Funktion_aktiv_ist" 4 "Wiederanfahrhinweis_mit_Gong" 5 "Wiederanfahrhinweis_ohne_Gong"; +VAL_ 1355 PDC_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 1355 PDC_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 1361 WFS_Schluessel_Fahrberecht 0 "kein authorisierter Schluessel erkannt" 1 "aktive_Funkschluessel_Nr_01" 2 "aktive_Funkschluessel_Nr_02" 3 "aktive_Funkschluessel_Nr_03" 4 "aktive_Funkschluessel_Nr_04" 5 "aktive_Funkschluessel_Nr_05" 6 "aktive_Funkschluessel_Nr_06" 7 "aktive_Funkschluessel_Nr_07" 8 "aktive_Funkschluessel_Nr_08" 9 "ungueltig_09" 10 "ungueltig_10" 11 "ungueltig_11" 12 "ungueltig_12" 13 "ungueltig_13" 14 "ungueltig_14" 15 "digitaler_Schluessel_aktiv"; +VAL_ 1361 WFS_ID_Geb_autorisiert 0 "Schluessel_nicht_authorisiert" 1 "Schluessel authorisiert"; +VAL_ 1361 WFS_ID_Geb_autorisiert_in_Kl15 0 "nicht_authorisiert_in_Kl15" 1 "authorisiert_in_Kl15"; +VAL_ 1361 WFS_ID_Geb_steckt 0 "kein_Schluessel_im_Zuendschloss" 1 "Schluessel steckt im Zuendschloss"; +VAL_ 1361 WFS_Schluessel_Soll 0 "Init"; +VAL_ 1361 WFS_Schluessel_Ist 0 "Init"; +VAL_ 1361 WFS_Safe 0 "Init" 1 "WFS nicht deaktiviert"; +VAL_ 1361 WFS_LZ 0 "nicht def." 1 "LZ 1" 2 "LZ 2" 3 "LZ 3"; +VAL_ 1361 WFS_ELV_authorisiert 0 "ELV_nicht_authorisiert" 1 "ELV_authorisiert"; +VAL_ 1361 WFS_LF_Aktiv 0 "Funktempfang_nicht_aktiv" 1 "LF_Funkempfang_aktiv"; +VAL_ 1361 WFS_Betrieb_Lesespule 0 "keine_Schluesselkomm_Lesespule" 1 "Schluesselkomm_Lesespule"; +VAL_ 1361 WFS_Klemmenfreigabe 0 "keine_Freigabe" 1 "Freigabe"; +VAL_ 1361 WFS_Fahrerhinweise 0 "Keine_Anzeigeanforderung" 1 "Schuessel_Auth_niO" 2 "Notlauf_aktiv" 3 "Schluessel_Kessy_nicht_gefunden"; +VAL_ 1361 WFS_Parken_Status 0 "Limitierung_inaktiv" 1 "Limitierung_aktiv" 2 "Abbruch"; +VAL_ 1411 BCM_FH_Freigabe 1 "Funktionsfreigabe Fensterheber"; +VAL_ 1411 BCM_Komfortfkt_Freigabe 0 "Komfortfunktion gesperrt" 1 "globale Freigabe der Komfortfunktion erteilt"; +VAL_ 1411 BCM_HSK_Freigabe 0 "erlauben" 1 "sperren"; +VAL_ 1411 BCM_Verdeck_Freigabe 0 "Verdeckbetrieb nicht erlaubt" 1 "Verdeckbetrieb erlaubt"; +VAL_ 1411 ZV_verriegelt_intern_ist 1 "Fahrzeug innen verriegelt; Istzustand"; +VAL_ 1411 ZV_verriegelt_extern_ist 1 "Fahrzeug_aussen_verriegelt_Istzustand"; +VAL_ 1411 ZV_verriegelt_intern_soll 1 "Fahrzeug verriegelt intern; Sollzusstand"; +VAL_ 1411 ZV_verriegelt_extern_soll 1 "Fahrzeug verriegelt extern; Sollzusstand"; +VAL_ 1411 ZV_gesafet_extern_ist 1 "Fahrzeug aussen gesafet; Istzustand"; +VAL_ 1411 ZV_gesafet_extern_soll 1 "Fahrzeug_aussen_gesafet_Sollzustand"; +VAL_ 1411 ZV_Einzeltuerentriegelung 1 "Fahrzeug an Einzeltuer entriegelt"; +VAL_ 1411 ZV_Heckeinzelentriegelung 1 "Heckdeckeleinzelentriegelung"; +VAL_ 1411 ZV_FT_offen 0 "FT_geschlossen" 1 "FT_geoeffnet"; +VAL_ 1411 ZV_BT_offen 0 "BT_geschlossen" 1 "BT_geoeffnet"; +VAL_ 1411 ZV_HFS_offen 0 "geschlossen" 1 "offen"; +VAL_ 1411 ZV_HBFS_offen 0 "geschlossen" 1 "offen"; +VAL_ 1411 ZV_HD_offen 1 "Heckdeckel_auf"; +VAL_ 1411 ZV_HS_offen 0 "Heckscheibe_geschlossen" 1 "Heckscheibe auf"; +VAL_ 1411 IRUE_aktiv 0 "unscharf" 1 "scharf"; +VAL_ 1411 DWA_aktiv 0 "unscharf" 1 "scharf"; +VAL_ 1411 HD_Hauptraste 0 "geschlossen" 1 "offen"; +VAL_ 1411 HD_Vorraste 0 "geschlossen" 1 "offen"; +VAL_ 1411 FFB_CarFinder 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1411 FFB_Komfortoeffnen 0 "kein_Komfortoeffnen_empfangen" 1 "Komfortoeffnen ueber Funk empfangen"; +VAL_ 1411 FFB_Komfortschliessen 0 "kein_Komfortschliessen_empfangen" 1 "Komfortschliessen ueber Funk empfangen"; +VAL_ 1411 ZV_Schluessel_Zugang 0 "kein_auth_Schluessel_erkannt" 1 "aktive_Funkschluessel_Nr_01" 2 "aktive_Funkschluessel_Nr_02" 3 "aktive_Funkschluessel_Nr_03" 4 "aktive_Funkschluessel_Nr_04" 5 "aktive_Funkschluessel_Nr_05" 6 "aktive_Funkschluessel_Nr_06" 7 "aktive_Funkschluessel_Nr_07" 8 "aktive_Funkschluessel_Nr_08" 9 "ungueltig_09" 10 "ungueltig_10" 11 "ungueltig_11" 12 "ungueltig_12" 13 "ungueltig_13" 14 "ungueltig_14" 15 "ungueltig_15"; +VAL_ 1411 ZV_SafeFunktion_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1411 FBS_Warn_Schluessel_Batt 0 "i.O." 1 "defekt"; +VAL_ 1411 ZV_Oeffnungsmodus 0 "globale_Oeffnung" 1 "ZV_mit_Einzeltuerentr" 2 "ZV_individuell_selektiv" 3 "ZV_seitenselektiv"; +VAL_ 1411 HFS_verriegelt 0 "nicht_verriegelt" 1 "verriegelt"; +VAL_ 1411 HFS_gesafet 0 "nicht_gesafet" 1 "gesafet"; +VAL_ 1411 HBFS_verriegelt 0 "nicht_verriegelt" 1 "verriegelt"; +VAL_ 1411 HBFS_gesafet 0 "nicht_gesafet" 1 "gesafet"; +VAL_ 1411 ZV_ist_Zustand_verfuegbar 0 "nicht_verfuegbar" 1 "verfuegbar_alle_TSGs_am_Bus"; +VAL_ 1411 IRUE_Taster_Fkts_LED 0 "LED_aus" 1 "LED_ein"; +VAL_ 1411 ZV_Tankklappe_offen 0 "Tankklappe_geschlossen" 1 "Tankklappe_offen"; +VAL_ 1411 ZV_Rollo_auf 0 "inaktiv" 1 "aktiv"; +VAL_ 1411 ZV_Rollo_zu 0 "inaktiv" 1 "aktiv"; +VAL_ 1411 ZV_SAD_auf 0 "inaktiv" 1 "aktiv"; +VAL_ 1411 ZV_SAD_zu 0 "inaktiv" 1 "aktiv"; +VAL_ 1411 BCM_Tankklappensteller_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 1411 ZV_verriegelt_soll 0 "Init" 1 "nicht_verriegelt" 2 "verriegelt"; +VAL_ 1413 SI_Sammel_SG_Fehler 61 "Reserviert" 62 "Overflow" 63 "ungueltig"; +VAL_ 1413 SI_Diagnose_Aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1413 SI_QRS_Mode 0 "QRS_Messmodus_nicht_aktiv" 1 "QRS_Messmodus_aktiv"; +VAL_ 1413 SI_T_Mode 0 "Transportmodus_nicht_aktiv" 1 "Transportmodus_aktiv"; +VAL_ 1413 SI_NWDF 0 "Ueberwachung_nicht_freigegeben" 1 "Ueberwachung_freigegeben"; +VAL_ 1413 SI_NWDF_gueltig 0 "NWDF_wird_nicht_unterstuetzt" 1 "NWDF_wird_unterstuetzt"; +VAL_ 1413 SI_Sammelfehler 0 "kein_Sammelfehler" 1 "Sammelfehler"; +VAL_ 1413 GW_KD_Fehler 0 "kein_KD_Fehler" 1 "KD_Fehler"; +VAL_ 1413 SI_T_Schutz 0 "Transportschutz_nicht_aktiv" 1 "Transportschutz_aktiv"; +VAL_ 1413 SI_BUS_01 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_02 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_03 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_04 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_05 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_06 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_07 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_08 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_09 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_10 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_11 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_12 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_13 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_14 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_BUS_15 0 "keine_Busruhe" 1 "Busruhe"; +VAL_ 1413 SI_Bus_Identifikation 16 "CAN_Diagnose" 17 "CAN_Antrieb" 18 "CAN_Komfort" 19 "CAN_Infotainment" 20 "CAN_Fahrwerk" 21 "CAN_Extended" 22 "CAN_Hybrid" 23 "CAN_Lade" 24 "CAN_Kombi" 25 "CAN_Komfort_2" 26 "CAN_AFS" 33 "CAN_FahrerAssistenzSysteme" 34 "CAN_Migration" 35 "CAN_Connect" 36 "CAN_AnzeigeBedienung" 37 "CAN_ElectricalVehicle" 40 "CAN_Telematik" 41 "CAN_MFL" 42 "CAN_FahrerAssistenzSysteme_2" 48 "FlexRay_A" 49 "FlexRay_B" 97 "VLAN_FAS" 98 "VLAN_Infotainment" 99 "VLAN_Connect" 100 "VLAN_Komfort" 101 "VLAN_Antrieb" 102 "VLAN_Diagnose" 103 "VLAN_Internet" 104 "VLAN_Gateway" 105 "VLAN_Remote_FC" 106 "VLAN_Connect_2" 107 "VLAN_Licht" 108 "VLAN_Charge" 109 "VLAN_Cockpit" 176 "HCP1_CANFD01" 177 "HCP1_CANFD02" 178 "HCP1_CANFD03" 179 "HCP1_CANFD04" 180 "HCP1_CANFD05" 181 "HCP1_CANFD06" 182 "HCP1_CANFD07" 183 "HCP1_CANFD08" 186 "HCP4_CANFD03" 187 "HCP4_CANFD04" 188 "HCP1_CANFD09" 189 "HCP4_CANFD06" 190 "HCP4_CANFD07" 191 "HCP4_CANFD08" 192 "HCP4_CANFD09" 193 "HCP4_CANFD10" 194 "HCP1_CANFD10" 195 "ICAS1_CANFD2_HCP5_CANFD02" 196 "HCP1_CANFD11" 197 "WU_HCP1_CANFD" 198 "WU_HCP2_1_CANFD" 199 "WU_HCP_2_CANFD" 200 "WU_HCP_3_CANFD" 201 "WU_HCP4_CANFD" 202 "WU_HCP3_CANFD02" 204 "ESC_CANFD" 205 "HCP4_CANFD11" 206 "HCP4_CANFD12" 207 "HCP5_CANFD04" 208 "HCP5_CANFD05" 212 "WU_ConMod_CANFD" 213 "WU_PASD_CANFD"; +VAL_ 1413 SI_CAB 0 "inaktiv" 1 "CAB_01__Tueren" 2 "CAB_02__Anhaenger" 4 "CAB_03__Nightvision" 8 "CAB_04__Sitzverstellung" 16 "CAB_05__Klappen" 32 "CAB_06__Infotainment" 64 "CAB_07__Sub_Infotainment" 128 "CAB_08__Anzeige" 256 "CAB_09__Laden" 512 "CAB_10__Klima" 1024 "CAB_11__FlexRay" 262144 "CAB_19_VLAN_Remote_FC" 524288 "CAB_20_VLAN_Komfort"; +VAL_ 1420 KST_Txt_P_Gang 0 "Aus" 1 "Ein"; +VAL_ 1420 KST_Txt_Panikabschaltung 0 "Aus" 1 "Ein"; +VAL_ 1420 KST_Anf_Klemmenfreigabe_ELV 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 1420 KST_Txt_Komfortabschaltung 0 "inaktiv" 1 "aktiv"; +VAL_ 1420 KST_ZAT_betaetigt 0 "Aus" 1 "Ein"; +VAL_ 1420 KST_Unterdr_Zuendungsmeldung 0 "keine_Unterdr_der_Zuendungsmeldung" 1 "Unterdr_der_Zuendungsmeldung_aktiv"; +VAL_ 1420 KST_aut_Abschaltung_Zuendung 0 "Zuendung_wird_bei_Verl_nicht_deaktiviert" 1 "Zuendung_wird_bei_Verl_deaktiviert"; +VAL_ 1420 KST_Anf_ZV_Verriegelung 0 "inaktiv" 1 "aktiv"; +VAL_ 1420 Relais_VoKo_angesteuert 0 "nicht_angesteuert" 1 "angesteuert"; +VAL_ 1420 RSt_Anforderung_HMS 0 "keine_Anforderung" 1 "halten" 2 "parken" 3 "halten_Standby" 4 "anfahren" 5 "Loesen_ueber_Rampe" 6 "Parken_mit_P"; +VAL_ 1440 LS_Helligkeit_IR 254 "Init" 255 "Fehler"; +VAL_ 1440 LS_Helligkeit_FW 1022 "Init" 1023 "Fehler"; +VAL_ 1440 LS_defekt 0 "OK" 1 "defekt"; +VAL_ 1440 LS_Verbau 0 "Init" 1 "Lichtsensor_verbaut"; +VAL_ 1440 RS_Regenmenge 14 "Init" 15 "Fehler"; +VAL_ 1440 RS_Verbau 0 "Init" 1 "Regensensor verbaut"; +VAL_ 1440 RS_Verglasung_schliessen 0 "Verglasung nicht schliessen" 1 "Verglasung schliessen"; +VAL_ 1440 RS_defekt 0 "OK" 1 "defekt"; +VAL_ 1440 RS_Wischergeschwindigkeit 0 "kein Wischen" 1 "42 Huebe/min" 2 "45 Huebe/min" 3 "48 Huebe/min" 4 "51 Huebe/min" 5 "54 Huebe/min" 6 "57 Huebe/min" 7 "60 Huebe/min"; +VAL_ 1440 RLS_Vorfeldhelligkeit_Boost 0 "groesser_24413_Lux" 1 "bis_24413_Lux" 2 "bis_22193_Lux" 3 "bis_20176_Lux" 4 "bis_18342_Lux" 5 "bis_16647_Lux" 6 "bis_15158_Lux" 7 "bis_13780_Lux" 8 "bis_12527_Lux" 9 "bis_11388_Lux" 10 "bis_10353_Lux" 11 "bis_9412_Lux" 12 "bis_8556_Lux" 13 "bis_7778_Lux" 14 "bis_7071_Lux" 15 "bis_6428_Lux"; +VAL_ 1442 BMS_Status_ServiceDisconnect 0 "gesteckt" 1 "gezogen"; +VAL_ 1442 BMS_Status_Spgfreiheit 0 "Init" 1 "HV_Komponente_spannungsfrei" 2 "HV_Komp_nicht_spannungsfrei" 3 "Fehler_nicht_spannungsfrei"; +VAL_ 1442 BMS_OBD_Lampe_Anf 0 "kein_MIL_Request" 1 "MIL_Request"; +VAL_ 1442 BMS_IstModus 0 "HV_inaktiv" 1 "Fahren_HV_aktiv" 2 "stBalancing" 3 "externes_Laden" 4 "AC_Laden" 5 "Error_Batt" 6 "DC_Laden" 7 "Init"; +VAL_ 1442 BMS_Fehlerstatus 0 "Komponente_IO" 1 "Eingeschr_KompFkt_Isofehler_I" 2 "Eingeschr_KompFkt_Isofehler_II" 3 "Eingeschr_KompFkt_Interlock" 4 "Eingeschr_KompFkt_SD" 5 "Eingeschr_KompFkt_Leistungsred" 6 "Keine_Komponentenfunktion" 7 "Init"; +VAL_ 1442 BMS_Kapazitaet_02 2047 "Init"; +VAL_ 1442 BMS_Soll_SOC_HiRes 2046 "Init" 2047 "Fehler"; +VAL_ 1447 TM_Spiegel_Anklappen 0 "Init" 1 "Spiegel_anklappen"; +VAL_ 1447 TM_Nur_Hupen 0 "inaktiv" 1 "aktiv"; +VAL_ 1447 TM_Door_Lock 0 "Init" 1 "door_lock"; +VAL_ 1447 TM_Door_Unlock 0 "Init" 1 "door_unlock"; +VAL_ 1447 TM_Warnblinken 0 "Init" 1 "Warnblinken_on"; +VAL_ 1447 TM_Panik_Alarm 0 "Init" 1 "panik_alarm_on"; +VAL_ 1447 TM_ZV_Signatur 0 "Init"; +VAL_ 1452 HVEM_IstStrom_HVVerbraucher 4094 "Init" 4095 "Fehler"; +VAL_ 1452 HVEM_Energie_Klima_Vorgabe_HighR 6 "Init" 7 "Fehler"; +VAL_ 1452 HVEM_IstLeistungNA 510 "Init" 511 "Fehler"; +VAL_ 1452 HVEM_Leistung_Klima_Vorgabe 254 "Init" 255 "Fehler"; +VAL_ 1452 HVEM_Nutzbare_Energie 2045 "Max" 2046 "Init" 2047 "Fehler"; +VAL_ 1452 HVEM_Energie_Klima_Vorgabe 254 "Init" 255 "Fehler"; +VAL_ 1452 HVEM_MO_MaxLeistungIgnoriert 0 "Max_Leistung_nicht_ignoriert" 1 "Max_Leistung_ignoriert"; +VAL_ 1485 DC_Fehlerstatus 0 "Komponente_IO" 1 "Eingeschr_KompFkt_Entlad_defekt" 3 "Eingeschr_KompFkt_Interlock" 6 "Keine_Komponentenfunktion" 7 "Init"; +VAL_ 1485 DC_Peakstrom_verfuegbar 0 "Peakstrom_nicht_verfuegbar" 1 "Peakstrom_verfuegbar"; +VAL_ 1485 DC_Abregelung_Temperatur 0 "keine_Abregelung" 1 "Abregelung_Temp"; +VAL_ 1485 DC_IstModus_02 0 "Standby" 1 "HV_On_Vorladen" 2 "Tiefsetzen" 3 "Hochsetzen" 4 "Pruefimpuls_12V" 5 "Fehler" 7 "Initialisierung"; +VAL_ 1485 DC_HV_EKK_IstModus 0 "Standby" 2 "Tiefsetzen" 3 "Hochsetzen" 5 "Fehler" 7 "Initialisierung"; +VAL_ 1485 DC_Status_Spgfreiheit_HV 0 "Init" 1 "HV_Komponente_spannungsfrei" 2 "HV_Komp_nicht_spannungsfrei" 3 "Fehler_nicht_spannungsfrei"; +VAL_ 1485 DC_IstSpannung_EKK_HV 255 "Init"; +VAL_ 1485 DC_Temperatur 254 "Init" 255 "Fehler"; +VAL_ 1505 BCM1_Aussen_Temp_ungef 253 "nicht_verbaut" 254 "Initwert" 255 "Fehler"; +VAL_ 1505 BCM_Heizungsabsperrventil_Status 0 "HAV_offen" 1 "HAV_geschlossen" 2 "Init_oder_nicht_verbaut" 3 "Fehler"; +VAL_ 1505 BCM_Heizungspumpe_Status 0 "Pumpe_aus" 1 "Pumpe_aktiv_und_Stauts_iO" 2 "Init_oder_nicht_verbaut" 3 "Fehler"; +VAL_ 1505 BCM_Kompressorkupplung_Status 0 "Kupplung_offen" 1 "Kupplung_geschlossen" 2 "Init_oder_nicht_verbaut" 3 "Fehler"; +VAL_ 1505 BCM1_PTC_stufig_Status 0 "Aus" 1 "Stufe_1_aktiv" 2 "Stufe_2_aktiv" 3 "Stufe_3_aktiv" 6 "Init_oder_nicht_verbaut" 7 "Fehler"; +VAL_ 1505 BCM1_FStatus_Aussentemp_ungef 0 "iO" 1 "niO"; +VAL_ 1505 BCM1_Kompressorstrom_ist 254 "Init, bzw. nicht verfuegbar" 255 "Fehler"; +VAL_ 1505 BCM1_OBD_FStatus_ATemp 0 "kein Fehler / Init / nicht verbaut" 1 "KS- (Kurzschluss nach minus)" 2 "KS+ (Kurzschluss nach plus)" 3 "OC (Leitungsunterbrechung)" 4 "OOR+ (Signal zu gross)" 5 "OOR- (Signal zu klein)" 6 "RC+ (Signal unplausibel zu gross)" 7 "RC- (Signal unplausibel zu klein)" 8 "KS+/OC (Kurzschluss nach plus/Unterbrechung)" 9 "KS-/OC (Kurzschluss nach minus/Unterbrechung)" 10 "KS-/KS+ (Kurzschluss nach minus/plus)" 11 "KS-/KS+/OC (Kurzschluss nach minus/plus/Unterbrechung)" 12 "frei" 13 "frei" 14 "frei" 15 "frei"; +VAL_ 1513 DS_Kaeltemittel_P 2046 "Init" 2047 "Fehler"; +VAL_ 1513 DS_Status 0 "i.O." 1 "t.b.d." 2 "Init bzw. nicht verfügbar" 3 "Fehler"; +VAL_ 1513 ION_Status 0 "Hochspannung_ausgeschaltet" 1 "Hochspannung_eingeschaltet" 2 "Init"; +VAL_ 1513 ION_Status_LED 0 "Aus" 1 "Ein"; +VAL_ 1513 AAU_Geblaese 126 "Init" 127 "Fehler"; +VAL_ 1513 ION_Status_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1520 DI_KL_58xd 254 "Init" 255 "Fehler"; +VAL_ 1520 DI_KL_58xs 126 "Init" 127 "Fehler"; +VAL_ 1520 DI_KL_58xt 126 "Init" 127 "Fehler"; +VAL_ 1524 IL_Bel_FS_Ausstieg 0 "inaktiv" 1 "aktiv"; +VAL_ 1524 IL_Bel_BFS_Ausstieg 0 "inaktiv" 1 "aktiv"; +VAL_ 1524 IL_Bel_HFS_Ausstieg 0 "inaktiv" 1 "aktiv"; +VAL_ 1524 IL_Bel_HBFS_Ausstieg 0 "inaktiv" 1 "aktiv"; +VAL_ 1524 BCM1_Innenlicht_gedimmt_V 0 "100% Innenlicht" 1 "gedimmtes Innenlicht"; +VAL_ 1524 BCM1_Innenlicht_gedimmt_H 0 "100% Innenlicht" 1 "gedimmtes Innenlicht"; +VAL_ 1524 IL_Innenlicht_aktiv 0 "Innenlicht inaktiv" 1 "Innenlicht aktiv"; +VAL_ 1524 IL_Klemme_30G_aktiv 0 "Kl_30G_abgeschaltet" 1 "eingeschaltet"; +VAL_ 1524 BCM1_DI_Rampe_Innenlicht 0 "Dimmrampe 0" 1 "Dimmrampe 1"; +VAL_ 1524 BCM1_DI_Rampe_Leselicht 0 "Dimmrampe 0" 1 "Dimmrampe 1"; +VAL_ 1524 BCM1_Innenlicht_H 0 "Aus" 1 "Ein"; +VAL_ 1524 BCM1_Innenlicht_V 0 "Aus" 1 "Ein"; +VAL_ 1524 BCM1_Leselicht_Anf_hl 0 "Aus" 1 "Ein"; +VAL_ 1524 BCM1_Leselicht_Anf_hr 0 "Aus" 1 "Ein"; +VAL_ 1524 BCM1_Leselicht_Anf_vl 0 "Aus" 1 "Ein"; +VAL_ 1524 BCM1_Leselicht_Anf_vr 0 "Aus" 1 "Ein"; +VAL_ 1524 BCM1_Leuchten_Aus 0 "keine Aenderung" 1 "Aus"; +VAL_ 1524 AMB_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 1524 AMB_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 1600 MO_QBit_Ansaugluft_Temp 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1600 MO_QBit_Oel_Temp 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1600 MO_QBit_Kuehlmittel_Temp 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1600 MO_HYB_Fehler_HV_Netz 0 "i_O" 1 "kein_generatorischer_Betrieb_moeglich"; +VAL_ 1600 MO_aktives_Getriebeheizen 0 "kein_Ventil_ansteuern" 1 "Ventil_muss_angesteuert_werden"; +VAL_ 1600 MO_Absperrventil_oeffnen 0 "nicht_verfuegbar" 1 "Ansteuerung_Ventil_zulaessig" 2 "Ventil_oeffnen_oder_geoeffnet" 3 "Ventil_schliessen_oder_geschlossen"; +VAL_ 1600 MO_Ansaugluft_Temp 254 "Init" 255 "Fehler"; +VAL_ 1600 MO_Oel_Temp 253 "nicht_verbaut" 254 "Init" 255 "Fehler"; +VAL_ 1600 MO_Kuehlmittel_Temp 254 "Init" 255 "Fehler"; +VAL_ 1600 MO_Hoeheninfo 255 "Fehler"; +VAL_ 1600 MO_Kennfeldk 0 "keine Kennfeldkühlung vorhanden" 1 "Kennfeldkühlung vorhanden"; +VAL_ 1600 MO_Getriebe_kuehlen 0 "nicht_kuehlen" 1 "kuehlen"; +VAL_ 1600 MO_Heizungspumpenansteuerung 13 "Fehler" 14 "Init" 15 "nicht_verbaut"; +VAL_ 1600 MO_SpannungsAnf 0 "keine_Anforderung" 1 "Anforderung"; +VAL_ 1601 MO_Faktor_Momente_02 0 "nicht_belegt"; +VAL_ 1601 MO_Hybridfahrzeug 0 "kein_Hybridfahrzeug" 1 "Mild_Hybrid" 2 "Full_Hybrid" 3 "PlugIn_Hybrid"; +VAL_ 1601 MO_Getriebe_Code 0 "Init" 2 "DL501" 3 "DL800" 4 "VL381" 5 "DL382_Front" 6 "DL382_Allrad" 7 "DL702" 8 "AL552_Allrad" 9 "AL552_Front" 10 "AL651" 11 "AL551__AL951__AL1000_8A" 12 "PDK_PAG" 13 "AL551_Hybrid" 15 "Handschalter_konventionell" 16 "AQ250_160" 17 "AQ450" 18 "DQ200" 19 "DQ250" 20 "DQ500" 21 "SQ100" 22 "SQ200" 23 "DQ400E" 24 "DQ381" 25 "AL550" 26 "AQ300" 31 "DL800E" 32 "Single_Gear__ohne_GSG_WH_am_MSG" 33 "EQ550_2P"; +VAL_ 1601 MO_StartStopp_Codiert 0 "Start_Stopp_nicht_verbaut" 1 "Start_Stopp_verbaut"; +VAL_ 1601 MO_Anzahl_Zyl 0 "kein_Zylinder" 1 "1_Zylinder" 2 "2_Zylinder" 3 "3_Zylinder" 4 "4_Zylinder" 5 "5_Zylinder" 6 "6_Zylinder" 7 "7_Zylinder" 8 "8_Zylinder" 9 "9_Zylinder" 10 "10_Zylinder" 11 "11_Zylinder" 12 "12_Zylinder" 13 "15_Zylinder" 14 "16_Zylinder" 15 "18_Zylinder"; +VAL_ 1601 MO_Kraftstoffart 0 "Diesel" 1 "Benzin_inkl_E25_E85" 2 "CNG" 3 "LPG" 4 "Wasserstoff" 5 "E100_Ethanol" 15 "kein_Verbrennungskraftstoff"; +VAL_ 1601 MO_Ansaugsystem 0 "Turbo" 1 "Sauger"; +VAL_ 1601 MO_DPF_verbaut 0 "kein_DPF_verbaut" 1 "DPF_verbaut"; +VAL_ 1601 TSK_Codierung 0 "kein_Fahrgeschwindigkeitsregler" 1 "GRA" 2 "GRA_Plus" 3 "Basis_ACC" 4 "ACC_Follow_to_Stop" 5 "ACC_Stop_and_Go" 7 "Codierung_in_Plausibilisierungsphase"; +VAL_ 1603 KBI_Einheit_Datum 0 "Tag/Monat/Jahr" 1 "Monat/Tag/Jahr" 2 "Jahr/Monat/Tag" 3 "reserviert"; +VAL_ 1603 KBI_Einheit_Druck 0 "Druckangabe in bar" 1 "Druckangabe in psi" 2 "Druckangabe in kPa" 3 "tbd."; +VAL_ 1603 KBI_Einheit_Streckenanz 0 "Kilometer" 1 "Meilen"; +VAL_ 1603 KBI_MFA_v_Einheit_02 0 "kmh" 1 "mph"; +VAL_ 1603 KBI_Einheit_Temp 0 "Grad Celsius °C" 1 "Grad Fahrenheit °F"; +VAL_ 1603 KBI_Einheit_Uhrzeit 0 "24h" 1 "12h AM/PM"; +VAL_ 1603 KBI_Einheit_Verbrauch 0 "mpg UK" 1 "mpg USA" 2 "Liter/100km" 3 "km/Liter"; +VAL_ 1603 KBI_Einheit_Volumen 0 "Liter" 1 "Gallonen UK" 2 "Gallonen USA" 3 "reserviert"; +VAL_ 1603 KBI_Einheit_Verbrauch_elektr 0 "kWh_pro_100km" 1 "km_pro_kWh" 2 "kWh_pro_100mls" 3 "mls_pro_kWh" 4 "MPGe"; +VAL_ 1603 KBI_Einheit_Verbrauch_Gas 0 "kg_per_100km" 1 "km_per_kg" 2 "m3_per_100km" 3 "km_per_m3" 4 "miles_per_lbs" 5 "miles_per_yard3" 6 "miles_per_kg" 7 "miles_per_m3" 8 "miles_per_gallon_equivalent_US"; +VAL_ 1603 KBI_Einheit_Masse 0 "kg" 1 "lbs" 2 "reserviert"; +VAL_ 1622 ELV_Anf_Klemme_S 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Anf_Klemme_15 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Anf_Klemme_50 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_01_Sendestatus 0 "ELV_sendet_mit_1000ms" 1 "ELV_sendet_mit_50ms"; +VAL_ 1622 ELV_Verriegelt 0 "nicht_verriegelt" 1 "verriegelt"; +VAL_ 1622 ELV_Entriegelt 0 "ELV_nicht_entriegelt" 1 "ELV_entriegelt"; +VAL_ 1622 ELV_ZAT_betaetigt 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1622 ELV_Lebenszustand 0 "Lebenszustand_0" 1 "Lebenszustand_4"; +VAL_ 1622 ELV_Anlernmodus 0 "Normalbetrieb" 1 "Anlernmodus"; +VAL_ 1622 ELV_Klemmenfreigabe 0 "keine_Freigabe" 1 "Freigabe"; +VAL_ 1622 ELV_Abbruch_Anf_Klemmenfreigabe 0 "kein_Abbruch" 1 "Abbruch"; +VAL_ 1622 ELV_LED_Rot 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_LED_Gelb 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_Panikabschaltung 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_Lkg_Bewegen 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_Werkstatt 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_Defekt 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_P_Gang 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_PN_Gang 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_Kupplung 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_Txt_Bremse 0 "Aus" 1 "Ein"; +VAL_ 1622 ELV_P_verriegelt 0 "nicht_verriegelt" 1 "verriegelt"; +VAL_ 1624 LV_Standlicht_Anzeige 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1624 LV_Abblendlicht_Anzeige 0 "inaktiv" 1 "aktiv"; +VAL_ 1624 LV_Fernlicht_Anzeige 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1624 LV_Nebellicht_Anzeige 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1624 LV_Nebelschlusslicht_Anzeige 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1624 LV_Tagfahrlicht_Anzeige 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1624 LV_AFL_aktiv_Anzeige 0 "nicht aktiv" 1 "aktiv"; +VAL_ 1624 LV_AFL_defekt 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Blinker_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Standlicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abblendlicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Fernlicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Nebellicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Blk_li_Seite_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Tagfahrlicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_FLA_aktiv_Anzeige 0 "aus" 1 "ein"; +VAL_ 1624 LV_FLA_defekt 0 "i.O." 1 "FLA defekt"; +VAL_ 1624 LV_FLA_Sensor_blockiert 0 "i.O." 1 "FLA-Sensor blockiert"; +VAL_ 1624 LV_Blinker_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Standlicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abblendlicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Fernlicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Nebellicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Blk_re_Seite_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Tagfahrlicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Aussenlicht_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abblendlicht_TFL_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Nebellicht_TFL_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Standlicht_TFL_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abblend_Fernlicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abblendlicht_TFL_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Nebellicht_TFL_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Standlicht_TFL_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abblend_Fernlicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abbiegelicht_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Abbiegelicht_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 BCM1_Linksverkehr 0 "Rechtsverkehr" 1 "Linksverkehr"; +VAL_ 1624 BCM1_Licht_Dunkelheit_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1624 LV_LED_Scheinwerfer_li_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_LED_Scheinwerfer_re_def 0 "OK" 1 "defekt"; +VAL_ 1624 LV_Blinker_VL_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1624 LV_Blinker_VR_aktiv 0 "inaktiv" 1 "aktiv"; +VAL_ 1624 LV_MXB_Status_Anzeige 0 "MXB_aus" 1 "MXB_regelt" 2 "MXB_volles_Fernlicht" 3 "MXB_und_Laser_aktiv"; +VAL_ 1629 BR_Systemart 0 "ABS" 1 "ABS_ASR" 2 "ESP" 3 "ESP_mit_integrierter_EPB"; +VAL_ 1629 ESP_SpannungsAnf_02 0 "keine_Anforderung" 1 "Anforderung_Stufe1" 2 "Anforderung_Stufe2" 3 "Anforderung_Stufe3"; +VAL_ 1629 ESP_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 1629 ESP_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 1629 ESP_Wiederstart_Anz_01 0 "keine_Anzeige" 1 "Rueckwaertsrollen"; +VAL_ 1629 ESP_Wiederstart_Anz_02 0 "keine_Anzeige" 1 "Autohold_Rutschen"; +VAL_ 1629 ESP_Wiederstart_Anz_03 0 "keine_Anzeige" 1 "Offroad_HDC"; +VAL_ 1629 ESP_Wiederstart_Anz_04 0 "keine_Anzeige" 1 "ESC_Off"; +VAL_ 1629 ESP_Stoppverbot_Anz_01 0 "keine_Anzeige" 1 "Notbremsung_aktiv"; +VAL_ 1629 ESP_Stoppverbot_Anz_02 0 "keine_Anzeige" 1 "Autohold_AVH_Rutschen"; +VAL_ 1629 ESP_Stoppverbot_Anz_03 0 "keine_Anzeige" 1 "Rueckwaertsrollen"; +VAL_ 1629 ESP_Stoppverbot_Anz_04 0 "keine_Anzeige" 1 "ESP_Pumpenlauf"; +VAL_ 1629 ESP_Stoppverbot_Anz_05 0 "keine_Anzeige" 1 "ESP_OFF"; +VAL_ 1629 ESP_Stoppverbot_Anz_06 0 "keine_Anzeige" 1 "Offroad_HDC"; +VAL_ 1629 ESP_Stoppverbot_Anz_07 0 "keine_Anzeige" 1 "ESP_Haltefunktion_nicht_verfuegbar"; +VAL_ 1629 ESP_Stoppverbot_Anz_Std 0 "keine_Anzeige" 1 "Standard_Stoppvetogrund"; +VAL_ 1629 ESP_Dachrelingsensor 0 "Sensor_nicht_verbaut" 1 "Quertraeger_montiert" 2 "Quertraeger_nicht_montiert" 3 "Fehler"; +VAL_ 1629 ESP_Stoppverbot_Anz_08 0 "keine_Anzeige" 1 "Neigungsbegrenzung"; +VAL_ 1629 HDC_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 1629 HDC_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 1629 BR_QBit_Reifenumfang 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1631 TSK_QBit_Steigung 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1631 TSK_QBit_Fahrzeugmasse 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1631 MO_SpannungsAnf_02 0 "keine_Anforderung" 1 "Anforderung_Stufe_1" 2 "Anforderung_Stufe_2" 3 "Anforderung_Stufe_3"; +VAL_ 1631 MO_DPF_reg 0 "DPF_regeneriert_nicht" 1 "DPF_regeneriert"; +VAL_ 1631 MO_Heizstrom_EKAT 127 "Fehler"; +VAL_ 1631 MO_Heizstrom_SCR 63 "Fehler"; +VAL_ 1631 MO_Anzeige_Kaltleuchte 0 "Lampe_aus" 1 "Lampe_an"; +VAL_ 1631 MO_P_Generator_ungefiltert_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 1631 TSK_Getriebeinfo 0 "Handschalter" 1 "AL_AQ_Getriebe" 2 "DL_DQ_Getriebe" 3 "CVT_Getriebe"; +VAL_ 1631 MO_Energieinhalt_BMS 4094 "Init" 4095 "Fehler"; +VAL_ 1631 TSK_Fahrzeugmasse_02 255 "Fehler"; +VAL_ 1631 TSK_Steigung_02 0 "Init_oder_nicht_verbaut" 255 "Fehler"; +VAL_ 1640 KL_LRH_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1640 KL_LRH_Stufe 0 "Stufe_niedrig" 1 "Stufe_mittel" 2 "Stufe_hoch" 3 "AUS"; +VAL_ 1640 HSH_Taster 0 "nicht_betaetigt" 1 "short_push" 2 "long_push" 3 "tbd"; +VAL_ 1640 FSH_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1640 KL_Zuheizer_Freigabe 0 "keine_Freigabe_Zuheizer" 1 "Zuheizerfreigabe"; +VAL_ 1640 KL_Beschlagsgefahr 0 "keine_Beschlagsgefahr" 1 "Beschlagsgefahr"; +VAL_ 1640 KRH_Soll_li 0 "aus" 1 "Stufe_1" 2 "Stufe_2" 3 "Stufe_3"; +VAL_ 1640 KRH_Soll_re 0 "aus" 1 "Stufe_1" 2 "Stufe_2" 3 "Stufe_3"; +VAL_ 1640 KL_Geblspng_Soll 0 "0V_Motorspannung" 252 "0V_sofort_Abschalten" 253 "0V_senken_mit_Rampe" 254 "reserviert" 255 "Fehler"; +VAL_ 1640 KL_Geblspng_Fond_Soll 0 "0V_Motorspannung" 252 "0V_sofort_Abschalten" 253 "0V_senken_mit_Rampe" 254 "reserviert" 255 "Fehler"; +VAL_ 1640 KL_I_Geblaese 255 "Fehler"; +VAL_ 1640 KL_Kompressorstrom_soll 1022 "Init" 1023 "Fehler"; +VAL_ 1640 KL_Umluftklappe_Status 0 "Frischluft" 1 "Teilumluft_10" 2 "Teilumluft_20" 3 "Teilumluft_30" 4 "Teilumluft_40" 5 "Teilumluft_50" 6 "Teilumluft_60" 7 "Teilumluft_70" 8 "Teilumluft_80" 9 "Teilumluft_90" 10 "Umluft" 14 "Init" 15 "Fehler"; +VAL_ 1640 KL_PTC_Verbauinfo 0 "kein_PTC" 1 "600W_geschaltet" 2 "1000W_geschaltet" 3 "1400W_LIN"; +VAL_ 1648 MO_ANC_Kennfeld_Anf 0 "Kennfeld_1" 1 "Uebergang_Kennfeld_2_nach_1" 2 "Uebergang_Kennfeld_1_nach_2" 3 "Kennfeld_2"; +VAL_ 1648 MO_Bremslicht_Reku 0 "Aus" 1 "Ein"; +VAL_ 1648 MO_StartStopp_PopUp 0 "Statuswechsel_ohne_Taster (Init)" 1 "StSt_per_Taster_deaktiviert" 2 "StSt_per_Taster_aktiviert" 3 "nicht verwendet"; +VAL_ 1648 MO1_Sperr_Info_WFS 0 "nicht_gesperrt" 1 "gesperrt"; +VAL_ 1648 MO1_Freigabe_Info_WFS 0 "ungueltig" 1 "gueltig"; +VAL_ 1648 MO_EPCL 0 "EPCL_aus_kein_Text" 1 "EPCL_gelb_Stoerung" 2 "EPCL_gelb_Leistungsbeschraenkung" 3 "EPCL_rot_Fzg_sicher_abstellen"; +VAL_ 1648 MO_Zylabsch_Texte_02 0 "ein_ZAS_generell_keine_ZAS_Anzeigen" 1 "ZAS_im_VMB" 2 "ZAS_im_ASB_1_Zyl_aktiv" 3 "ZAS_im_ASB_2_Zyl_aktiv" 4 "ZAS_im_ASB_3_Zyl_aktiv" 5 "ZAS_im_ASB_4_Zyl_aktiv" 6 "ZAS_im_ASB_5_Zyl_aktiv" 7 "ZAS_im_ASB_6_Zyl_aktiv" 8 "ZAS_im_ASB_8_Zyl_aktiv" 9 "ZAS_im_ASB_12_Zyl_aktiv" 13 "Uebergangsbetrieb" 14 "keine_ZAS_Anzeige_ggf_Stopp_Schub_Betrieb" 15 "ZAS_Stoerungs_Anzeige"; +VAL_ 1648 MO_Fahrzeugtyp 0 "Verbrenner_Fahrzeug" 1 "Hybrid" 2 "E_Fahrzeug" 3 "E_Fahrzeug_mit_Range_Extender" 4 "Brennstoffzellenfahrzeug" 5 "tbd" 6 "tbd" 7 "tbd"; +VAL_ 1648 MO_Abstellzeit 254 "Init" 255 "reserviert"; +VAL_ 1648 MO_Abstellzeit_Status 0 "Abstellzeit_nicht_berechnet" 1 "Abstellzeit_berechnet" 2 "Abstellzeit_Minimalwert" 3 "Abstellzeit_ungueltig"; +VAL_ 1648 MO1_Freigabe_Verfallsinfo_WFS 0 "verfaellt_nicht" 1 "verfaellt"; +VAL_ 1648 MO_Hybrid_StartStopp_LED 0 "LED_aus_und_Blinken_aus" 1 "LED_ein_und_Blinken_aus" 2 "LED_ein_und_Blinken_ein_50_percent" 3 "reserviert"; +VAL_ 1648 MO_Fehler_Zylabsch 0 "kein_Fehler" 1 "Notlauf_Vollmotorbetrieb" 2 "Notlauf_mindestens_einem_abgesch_Zylinder"; +VAL_ 1648 MO_Anzahl_Abgesch_Zyl 0 "Vollmotorbetrieb" 1 "1_Zylinder_abgeschaltet" 2 "2_Zylinder_abgeschaltet" 3 "3_Zylinder_abgeschaltet" 4 "4_Zylinder_abgeschaltet" 5 "5_Zylinder_abgeschaltet" 6 "6_Zylinder_abgeschaltet" 7 "8_Zylinder_abgeschaltet"; +VAL_ 1648 MO_Zylabsch_Texte 0 "keine_Texte" 1 "Zylinderabschaltung_deaktivieren" 2 "Zylinderabschaltung_aktivieren" 3 "Zylinderabschaltung_unruhig"; +VAL_ 1648 MO_Ethanol_BS_Texte 0 "kein_Text" 1 "E85_Warm_Up" 2 "FlexFuel_Warnung_Stufe_3" 3 "Warmfahrempfehlung_MQB__FlexFuel_Warnung_Stufe_1" 4 "FlexFuel_Warnung_Stufe_2" 5 "FlexFuel_Warnung_Stufe_4" 6 "E25_Warm_Up"; +VAL_ 1648 MO_Drehzahl_Warnung 0 "keinen_Warnhinweis_anzeigen" 1 "Warnhinweis_anzeigen"; +VAL_ 1648 MO_obere_Drehzahlgrenze 0 "Init"; +VAL_ 1710 SP_FT_oben 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_FT_unten 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_FT_links 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_FT_rechts 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_BT_oben 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_BT_unten 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_BT_links 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_BT_rechts 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_abklappen 0 "Spiegel_abklappen_nicht_aktiv" 1 "Spiegel_abklappen_aktiv"; +VAL_ 1710 SP_anklappen 0 "Spiegle_anklappen_nicht_aktiv" 1 "Spiegel_anklappen_aktiv"; +VAL_ 1710 SP_normieren 0 "Spiegel_nicht_normiert" 1 "Spiegel_normiert"; +VAL_ 1710 SP_Hzg_Taster 0 "nicht_betaetigt" 1 "betaetigt"; +VAL_ 1710 SP_S_oben 1 "Spiegelschalter in Stellung oben"; +VAL_ 1710 SP_S_unten 1 "Spiegelschalter in Stellung unten"; +VAL_ 1710 SP_S_links 1 "Spiegelschalter in Stellung links"; +VAL_ 1710 SP_S_rechts 1 "Spiegelschalter in Stellung rechts"; +VAL_ 1710 SP_Auswahl_li 1 "Spiegelschalter in Stellung Auswahl links"; +VAL_ 1710 SP_Auswahl_re 1 "Spiegelschalter in Stellung Auswahl rechts"; +VAL_ 1710 SP_ARA_Status 0 "TSG nicht im ARA-Modus" 1 "TSG im ARA-Modus"; +VAL_ 1710 SP_S_Klappen 1 "Spiegelschalter in Stellung Klappen"; +VAL_ 1710 SP_Verstellschalter_Fehler 0 "kein_Fehler" 1 "Fehler"; +VAL_ 1711 RV_Video_on 0 "Kamerabild wird nicht angezeigt" 1 "Kamerabild wird angezeigt"; +VAL_ 1711 RV_Dark_Screen 0 "Kamerabild nicht verdunkeln" 1 "Kamerabild verdunkeln"; +VAL_ 1711 RV_HMI_Mode 0 "Parkluecke (Modus 1)" 1 "Parallel zur Straߥ (Modus 2)" 2 "reserviert" 3 "Kalibrierung (nur Diagnose)"; +VAL_ 1711 RV_GL_side 0 "Guidelines_abgeschaltet" 1 "Guidelines_Anzeige_rechte_Seite" 2 "Guiedelines_Anzeige_linke_Seite" 3 "Guiedelines_Anzeige_beide_Seiten"; +VAL_ 1711 RV_System_aktiv 0 "System nicht betriebsbereit" 1 "System betriebsbereit"; +VAL_ 1711 RV_Reinigung_Anf 0 "nicht_reinigen" 1 "reinigen"; +VAL_ 1711 RV_Settings_enabled 0 "Menu 'Einstellungen' nicht aktiviert" 1 "Menu 'Einstellungen' aktiviert"; +VAL_ 1711 RV_Menu_Item 0 "HMI Mode als ausgewaehlt markiert" 1 "Helligkeit als ausgewaehlt markiert" 2 "Kontrast als ausgewaehlt markiert" 3 "Farbsaettigung als ausgewaehlt markiert"; +VAL_ 1711 SV_Video_on 0 "SideView_aus_/_nicht_verbaut" 1 "SideView_an"; +VAL_ 1711 RV_Calib_Fehler 0 "Kalibrierung_i.O." 1 "RearView_nicht_kalibriert"; +VAL_ 1711 RV_GL_Trailer_connect 0 "Guidelines_werden_angezeigt" 1 "Guidelines_wegen_angekoppeltem_Anh䮧er_deaktiviert"; +VAL_ 1711 RV_GL_Trunk_open 0 "Guidelines_werden_angezeigt" 1 "Guidelines_wegen_geöffneter_Heckklappe_deaktiviert"; +VAL_ 1711 RV_GL_LWS_Fehler 0 "Guidelines_werden_angezeigt" 1 "Guidelines_wegen_nicht_kalibriertem_Lenkwinkelsensor_deaktiviert"; +VAL_ 1711 ZFAS_Umfeldbeleuchtung_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 1714 DGN_Verlernzaehler 255 "ungültiger Z䨬erstand oder kein gültiger Fahrzyklus"; +VAL_ 1714 UH_Monat 0 "Init" 14 "Relatives_Datum" 15 "Fehler"; +VAL_ 1714 UH_Tag 0 "Init"; +VAL_ 1714 Kombi_02_alt 0 "aktuell" 1 "veraltet"; +VAL_ 1714 Uhrzeit_01_alt 0 "aktuell" 1 "veraltet"; diff --git a/opendbc_repo/opendbc/dbc/vw_mqb.dbc b/opendbc_repo/opendbc/dbc/vw_mqb.dbc new file mode 100644 index 0000000000..effe4c5bfd --- /dev/null +++ b/opendbc_repo/opendbc/dbc/vw_mqb.dbc @@ -0,0 +1,1805 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + BO_TX_BU_ + BA_DEF_REL_ + BA_REL_ + BA_DEF_DEF_REL_ + BU_SG_REL_ + BU_EV_REL_ + BU_BO_REL_ + SG_MUL_VAL_ + +BS_: + +BU_: Airbag_MQB BAP_Tester_MQB BMS_MQB Datenlogger_MQB Gateway_MQB Getriebe_DQ_Hybrid_MQB Getriebe_DQ_MQB LEH_MQB Motor_Diesel_MQB Motor_Hybrid_MQB Motor_Otto_MQB SAK_MQB Waehlhebel_MQB Vector__XXX l c i XXX + + +BO_ 290 ACC_06: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_limitierte_Anfahrdyn : 12|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_nachtr_Stopp_Anf : 13|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_DynErhoehung : 14|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ACC_Freilaufstrategie_TSK : 15|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ACC_zul_Regelabw_unten : 16|6@1+ (0.024,0) [0|1.512] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_StartStopp_Info : 22|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Sollbeschleunigung_02 : 24|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_zul_Regelabw_oben : 35|5@1+ (0.0625,0) [0|1.9375] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_neg_Sollbeschl_Grad_02 : 40|8@1+ (0.05,0) [0|12.75] "Unit_MeterPerCubicSecon" XXX + SG_ ACC_pos_Sollbeschl_Grad_02 : 48|8@1+ (0.05,0) [0|12.75] "Unit_MeterPerCubicSecon" XXX + SG_ ACC_Anfahren : 56|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Anhalten : 57|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ : 58|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Status_ACC : 60|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Minimale_Bremsung : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 279 ACC_10: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ AWV1_Anf_Prefill : 16|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_CM_Info : 17|1@1+ (1,0) [0|1] "" XXX + SG_ AWV2_Freigabe : 18|1@1+ (1,0) [0|1] "" XXX + SG_ AWV1_HBA_Param : 19|2@1+ (1,0) [0|3] "" XXX + SG_ AWV2_Ruckprofil : 21|3@1+ (1,0) [0|7] "" XXX + SG_ AWV2_Priowarnung : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_CM_Anforderung : 25|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Info_Teilbremsung : 26|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Notfallblinken : 27|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Teilbremsung_Freigabe : 28|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Zielbrems_Teilbrems_Verz_Anf : 29|10@1+ (0.024,-20.016) [-20.016|4.536] "Unit_MeterPerSeconSquar" XXX + SG_ ANB_Zielbremsung_Freigabe : 39|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_Vorstufe : 40|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_Halten : 41|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_CityANB_Auspraegung : 42|1@1+ (1,0) [0|1] "" XXX + SG_ PCF_Freigabe : 43|1@1+ (1,0) [0|1] "" XXX + SG_ AWV1_ECD_Anlauf : 44|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_AWA_VZ_Anf_Lenkmomoffset : 46|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ AWV_AWA_Anf_Lenkmomoffset : 47|9@1+ (0.01,0) [0.00|5.11] "Unit_NewtoMeter" XXX + SG_ PCF_Time_to_collision : 56|8@1+ (0.01,0) [0|2.5] "Unit_Secon" XXX + +BO_ 304 PLA_01: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ PLA_Status_PLA_ESP : 12|4@1+ (1.0,0.0) [0.0|15] "" XXX + SG_ PLA_LW_Soll : 16|13@1+ (0.1,0) [0.0|819.1] "Unit_DegreOfArc" XXX + SG_ PLA_VZ_LW_Soll : 31|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ PLA_Status_PLA_EPS : 32|4@1+ (1.0,0.0) [0.0|15] "" XXX + SG_ PLA_Bremsmoment : 36|13@1+ (4,0) [0|32760] "Unit_NewtoMeter" XXX + SG_ PLA_Bremsverzoegerung : 36|7@1+ (0.1,0) [0.0|12.0] "Unit_MeterPerSeconSquar" XXX + SG_ PLA_Anf_Bremsverzoegerung : 43|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ PLA_BremsMom_Verzoeg : 50|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ PLA_Anhalten : 51|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ PLA_Anhalteweg : 52|11@1+ (0.01,0) [0.01|20.45] "Unit_Meter" XXX + SG_ PLA_01_Signal_red_cyclic : 63|1@1+ (1.0,0.0) [0.0|1] "" XXX + +BO_ 679 ACC_13: 8 XXX + SG_ ACC_Regelgeschw : 12|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" XXX + SG_ ACC_Einheit_maxSetzgeschw : 22|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_maxSetzgeschw : 23|9@1+ (1,0) [0|510] "" XXX + SG_ ACC_minRegelgeschw : 32|8@1+ (0.32,0) [0|81.28] "Unit_KiloMeterPerHour" XXX + SG_ ACC_maxRegelgeschw : 40|8@1+ (0.32,0) [0|81.28] "Unit_KiloMeterPerHour" XXX + SG_ ACC_Tempolimitassistent : 48|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Kurvenassistent : 52|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_RUV : 56|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Tachokranz : 58|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ_Tachokranz_unten : 59|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_ENG_Texte : 60|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_ADAPTIVE : 63|2@0+ (1,0) [0|3] "" XXX + +BO_ 681 ACC_15: 8 XXX + SG_ AWV_Warnung : 16|3@1+ (1,0) [0|7] "" XXX + SG_ AWV_Texte : 24|3@1+ (1,0) [0|7] "" XXX + SG_ AWV_Status_Anzeige : 32|2@1+ (1,0) [0|3] "" XXX + SG_ AWV_Einstellung_System_FSG : 34|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_Einstellung_Warnung_FSG : 36|3@1+ (1,0) [0|7] "" XXX + SG_ AWV_Warnlevel : 58|6@1+ (1,0) [0|63] "" XXX + +BO_ 64 Airbag_01: 8 Airbag_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" BMS_MQB,Gateway_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Gateway_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AB_RGS_Anst : 12|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ AB_Front_Crash : 16|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Heck_Crash : 17|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_SF_Crash : 18|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_SB_Crash : 19|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Rollover_Crash : 20|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Crash_Int : 21|3@1+ (1,0) [0|7] "" BMS_MQB,Gateway_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AB_Lampe : 24|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Deaktiviert : 25|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_VB_deaktiviert : 26|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Systemfehler : 27|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ AB_Diagnose : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Stellgliedtest : 29|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AB_Erh_Auf_VB : 30|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtwarn_VF : 32|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Gurtwarn_VB : 33|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Anzeige_Fussg : 34|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Texte_AKS : 36|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_PAO_Leuchte_Anf : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_MKB_gueltig : 39|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_MKB_Anforderung : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Versorgungsspannung : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Deaktivierung_HV : 42|3@1+ (1.0,0.0) [0.0|7] "" BMS,Gateway_MQB,LEH_MQB,Motor_Hybrid_MQB + SG_ AB_EDR_Trigger : 45|2@1+ (1.0,0.0) [0.0|3] "" Gateway_MQB + SG_ AB_Gurtwarn_HFS : 47|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ AB_Gurtwarn_HBFS : 48|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ SC_Masterzeit_Offset : 53|2@1+ (5.08,0) [0.00|15.24] "Unit_Secon" Gateway_MQB + SG_ SC_Masterzeit : 57|7@1+ (0.04,0) [0.00|5.04] "Unit_Secon" Gateway_MQB + +BO_ 1312 Airbag_02: 8 Airbag_MQB + SG_ AB_Belegung_VB : 26|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_FA : 40|2@1+ (1,0) [0|3] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Otto_MQB + SG_ AB_Gurtschloss_BF : 42|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe2_FA : 44|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe2_MI : 46|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe2_BF : 48|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe3_FA : 50|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe3_MI : 52|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe3_BF : 54|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Sitzpos_Sens_FA : 56|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Sitzpos_Sens_BF : 58|2@1+ (1,0) [0|3] "" Gateway_MQB + +BO_ 65 Airbag_03: 8 Airbag_MQB + SG_ Airbag_03_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ Airbag_03_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ AB_MKB_Safing : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 1633 Anhaenger_01: 8 Gateway_MQB + SG_ AAG_BZ : 0|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Bremsl_durch_ECD : 5|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Anhaenger_abgesteckt : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_NSL_aktiv : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Anhaenger_erkannt : 8|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Blinker_H_aktiv : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Blinker_HL_def : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Blinker_HR_def : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Bremslicht_H_def : 12|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Schlusslicht_HL_def : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Schlusslicht_HR_def : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_AVS_Fehler_02 : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_AVS_Stati : 20|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 1626 BCM_01: 8 Gateway_MQB + SG_ BCM_Bremsbelag_Sensor : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Bremsfluessigkeit_Sensor : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Licht_Warn : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Waschwasser_Sensor : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Kuehlmittel_Sensor : 16|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_Kl_15_HW_erkannt : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Eis_Offroad_Taste : 18|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ZZH_Endlage_oben : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZZH_Endlage_unten : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZZH_Endlage_unplausibel : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM2_EZS_gedrueckt : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM2_SST_gedrueckt : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Hybrid_StartStopp_Taste : 24|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Warnblink_Taster : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Valet_Parking_Taster : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Remotestart_Betrieb : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_HSK_Taster : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Heckrollo_Taster : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Rueckfahrlicht_Schalter : 30|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_MH_Schalter : 31|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_MH_WIV_Schalter : 32|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM_Eco_Charisma_Taste : 33|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ BCM_Thermomanagement : 34|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM_Thermomanagement_Fehler : 36|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM_Thermomanagement_gueltig : 37|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Lichtwarn_Texte : 38|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 869 BEM_05: 8 Gateway_MQB + SG_ BEM_P_Generator : 16|8@1+ (50,0) [0|12700] "Unit_Watt" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_n_LLA : 24|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_01_Abschaltstufen : 26|3@1+ (1,0) [0|7] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_Anf_KL : 29|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_StartStopp_Info : 30|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BEM_DFM : 32|5@1+ (3.225,0.025) [0.025|100] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_EMLIN_ungueltig : 37|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_Batt_Ab : 38|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_Segel_Info : 48|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_HYB_DC_uSollLV : 50|6@1+ (0.1,10.6) [10.6|16] "Unit_Volt" LEH_MQB + SG_ BEM_HYB_DC_uMinLV : 56|8@1+ (0.1,0) [0|25.3] "Unit_Volt" LEH_MQB + +BO_ 1628 BMS_Hybrid_01: 8 BMS_MQB + SG_ BMS_HYB_ASV_hinten_Status : 13|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_ASV_vorne_Status : 14|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_KD_Fehler : 15|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_BattFanSpd : 16|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ BMS_HYB_VentilationReq : 20|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_Spuelbetrieb_Status : 21|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_Kuehlung_Anf : 22|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ BMS_HYB_Temp_vor_Verd : 24|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_HYB_Temp_nach_Verd : 32|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_Temperatur : 40|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_Temperatur_Ansaugluft : 48|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_IstSpannung_HV : 56|8@1+ (1,100) [100|350] "Unit_Volt" Gateway_MQB + +BO_ 901 Charisma_01: 8 Gateway_MQB + SG_ CHA_Ziel_FahrPr_ALR : 0|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_ESP : 4|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_FL : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Fahrer_Umschaltung : 14|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ CHA_Ziel_FahrPr_MO : 16|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ CHA_Ziel_FahrPr_GE : 20|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ CHA_Ziel_FahrPr_ST : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_SCU : 28|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_DR : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_QS : 36|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_AFS : 40|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_RGS : 44|4@1+ (1,0) [0|15] "" Airbag_MQB + SG_ CHA_Ziel_FahrPr_EPS : 48|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_ACC : 52|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_SAK : 56|4@1+ (1,0) [0|15] "" SAK_MQB + SG_ CHA_Ziel_FahrPr_MStSt : 60|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 945 DC_Hybrid_01: 8 LEH_MQB + SG_ DC_HYB_iAktLV : 12|10@1+ (1,-511) [-511|510] "Unit_Amper" Gateway_MQB + SG_ DC_HYB_iAktReserveLV : 22|10@1+ (1,-511) [-511|510] "Unit_Amper" Gateway_MQB + SG_ DC_HYB_uAktLV : 32|8@1+ (0.1,0) [0|25.3] "Unit_Volt" Gateway_MQB + SG_ DC_HYB_LangsRegelung : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Abregelung_Temperatur : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Fehler_RedLeistung : 42|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Fehler_intern : 43|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Fehler_Spannung : 44|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Auslastungsgrad : 56|8@1+ (0.4,0) [0|100] "Unit_PerCent" Gateway_MQB + +BO_ 1714 Diagnose_01: 8 Gateway_MQB + SG_ DGN_Verlernzaehler : 0|8@1+ (1,0) [0|254] "" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,SAK_MQB + SG_ KBI_Kilometerstand : 8|20@1+ (1,0) [0|1048573] "Unit_KiloMeter" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Jahr : 28|7@1+ (1,2000) [2000|2127] "Unit_Year" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Monat : 35|4@1+ (1,0) [1|12] "Unit_Month" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Tag : 39|5@1+ (1,0) [1|31] "Unit_Day" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Stunde : 44|5@1+ (1,0) [0|23] "Unit_Hours" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Minute : 49|6@1+ (1,0) [0|59] "Unit_Minut" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Sekunde : 55|6@1+ (1,0) [0|59] "Unit_Secon" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ Kombi_02_alt : 62|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,LEH_MQB + SG_ Uhrzeit_01_alt : 63|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,LEH_MQB + +BO_ 1520 Dimmung_01: 8 Gateway_MQB + SG_ DI_KL_58xd : 0|8@1+ (1,0) [0|253] "" Airbag_MQB + SG_ DI_KL_58xs : 8|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ DI_Display_Nachtdesign : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ DI_KL_58xt : 16|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ DI_Fotosensor : 24|16@1+ (1,0) [0|65535] "" Vector__XXX + +BO_ 1603 Einheiten_01: 8 Gateway_MQB + SG_ KBI_Einheit_Datum : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Druck : 2|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Streckenanz : 4|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB + SG_ KBI_MFA_v_Einheit_02 : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Temp : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Uhrzeit : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Verbrauch : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Volumen : 10|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Sprache : 16|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 260 EPB_01: 8 Gateway_MQB + SG_ EPB_01_CRC : 0|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_01_BZ : 8|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_QBit_Laengsbeschleunigung : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_QBit_Pedalweg_Kuppl : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_BCM2_Motor_Wakeup : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_Freig_Verzoeg_Anf : 15|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_Verzoeg_Anf : 16|8@1+ (0.048,-7.968) [-7.968|4.224] "Unit_MeterPerSeconSquar" Vector__XXX + SG_ EPB_Laengsbeschleunigung : 24|8@1+ (1,-128) [-128|126] "Unit_PerCentOfForceOfGravi" Vector__XXX + SG_ EPB_Pedalweg_Kuppl : 32|8@1+ (0.4,0) [8|92] "Unit_PerCent" Vector__XXX + SG_ EPB_Anfahrwunsch_erkannt : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_DAA_Randbed_erf : 49|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ EPB_Fehlerstatus : 50|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EPB_Schalterposition : 52|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_QBit_Schalterpos : 54|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_Konsistenz_ACC : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_Spannkraft : 56|5@1+ (1,0) [0|29] "Unit_KiloNewto" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ EPB_Status : 61|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 257 ESP_02: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Gierrate : 12|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_QBit_Laengsbeschl : 13|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Querb : 14|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Stillstandsflag : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Querbeschleunigung : 16|8@1+ (0.01,-1.27) [-1.27|1.27] "Unit_ForceOfGravi" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Laengsbeschl : 24|10@1+ (0.03125,-16) [-16|15.90625] "Unit_MeterPerSeconSquar" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Verteil_Wankmom : 34|5@1+ (0.1,-1) [-1|1] "" Vector__XXX + SG_ ESP_QBit_Anf_Vert_Wank : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Gierrate : 40|14@1+ (0.01,0) [0|163.82] "Unit_DegreOfArcPerSecon" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_VZ_Gierrate : 54|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_Notbremsanzeige : 55|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESP_SpannungsAnf : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_PLA_Abbruch : 57|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ ESP_Status_ESP_PLA : 60|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 262 ESP_05: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Bremsdruck : 12|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Fahrer_bremst : 13|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Schwelle_Unterdruck : 14|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Bremsdruck : 16|10@1+ (0.3,-30) [-30|276.6] "Unit_Bar" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Fahrer_bremst : 26|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Verz_TSK_aktiv : 27|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Lenkeingriff_ADS : 28|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Konsistenz_TSK : 29|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Bremsruck_AWV2 : 30|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Konsistenz_AWV2 : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ECD_Fehler : 32|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ECD_nicht_verfuegbar : 33|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Status_Bremsentemp : 34|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Autohold_Standby : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_HDC_Standby : 36|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_HBA_aktiv : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Prefill_ausgeloest : 38|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Rueckwaertsfahrt_erkannt : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Status_Anfahrhilfe : 40|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HDC_aktiv : 41|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_StartStopp_Info : 42|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ESP_Eingr_HL : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingr_HR : 45|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingr_VL : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingr_VR : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_BKV_Unterdruck : 48|8@1+ (4,0) [0|1012] "Unit_MilliBar" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Autohold_aktiv : 56|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_FStatus_Anfahrhilfe : 57|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_Verz_EPB_aktiv : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ECD_Bremslicht : 59|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Verzoeg_EPB_verf : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Status_Bremsdruck : 61|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Anforderung_EPB : 62|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 914 ESP_07: 8 Gateway_MQB + SG_ ESP_07_CRC : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_07_BZ : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_ACC_LDE : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Quattro_Antrieb : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Codierung_ADS : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_RTA_HL : 16|8@1+ (0.048828125,-6.20117) [-6.20117|6.152345625] "Unit_PerCent" Vector__XXX + SG_ ESP_RTA_HR : 24|8@1+ (0.048828125,-6.20117) [-6.20117|6.152345625] "Unit_PerCent" Vector__XXX + SG_ ESP_RTA_VR : 32|8@1+ (0.048828125,-6.20117) [-6.20117|6.152345625] "Unit_PerCent" Vector__XXX + SG_ OBD_Fehler_Radsensor_HL : 40|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_Fehler_Radsensor_HR : 44|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_Fehler_Radsensor_VL : 48|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_Fehler_Radsensor_VR : 52|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Qualifizierung_Antriebsart : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Offroad_Modus : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_MKB_ausloesbar : 58|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESP_MKB_Status : 59|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESP_CM_Variante : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_OBD_Status : 61|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 278 ESP_10: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_VL : 12|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_VR : 13|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_HL : 14|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_HR : 15|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_VL : 16|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_VR : 26|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_HL : 36|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_HR : 46|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VL_Fahrtrichtung : 56|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VR_Fahrtrichtung : 58|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HL_Fahrtrichtung : 60|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HR_Fahrtrichtung : 62|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 178 ESP_19: 8 Gateway_MQB + SG_ ESP_HL_Radgeschw_02 : 0|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HR_Radgeschw_02 : 16|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VL_Radgeschw_02 : 32|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VR_Radgeschw_02 : 48|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 1629 ESP_20: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ BR_Systemart : 12|2@1+ (1,0) [0|3] "" XXX + SG_ ESP_SpannungsAnf_02 : 14|2@1+ (1,0) [0|3] "" XXX + SG_ ESP_Zaehnezahl : 16|8@1+ (1,0) [0|255] "" XXX + SG_ ESP_Charisma_FahrPr : 24|4@1+ (1,0) [0|15] "" XXX + SG_ ESP_Charisma_Status : 28|2@1+ (1,0) [0|3] "" XXX + SG_ ESP_Wiederstart_Anz_01 : 30|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Wiederstart_Anz_02 : 31|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Wiederstart_Anz_03 : 32|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Wiederstart_Anz_04 : 33|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_01 : 34|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_02 : 35|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_03 : 36|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_04 : 37|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_05 : 38|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_06 : 39|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_07 : 40|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stoppverbot_Anz_Std : 41|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Dachrelingsensor : 42|2@1+ (1,0) [0|3] "" XXX + SG_ ESP_Stoppverbot_Anz_08 : 44|1@1+ (1,0) [0|1] "" XXX + SG_ HDC_Charisma_FahrPr : 45|4@1+ (1,0) [0|15] "" XXX + SG_ HDC_Charisma_Status : 49|2@1+ (1,0) [0|3] "" XXX + SG_ BR_QBit_Reifenumfang : 51|1@1+ (1,0) [0|1] "" XXX + SG_ BR_Reifenumfang : 52|12@1+ (1,0) [0|4095] "Unit_MilliMeter" XXX + +BO_ 253 ESP_21: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ BR_Eingriffsmoment : 12|10@1+ (1,-509) [-509|509] "" XXX + SG_ ESP_PLA_Bremseingriff : 22|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Diagnose : 23|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESC_Reku_Freigabe : 24|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESC_v_Signal_Qualifier_High_Low : 25|3@1+ (1.0,0.0) [0.0|7] "" XXX + SG_ ESP_Vorsteuerung : 28|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_AWV3_Brems_aktiv : 29|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ OBD_Schlechtweg : 30|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ OBD_QBit_Schlechtweg : 31|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_v_Signal : 32|16@1+ (0.01,0) [0.00|655.32] "Unit_KiloMeterPerHour" XXX + SG_ ASR_Tastung_passiv : 48|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Tastung_passiv : 49|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Systemstatus : 50|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ASR_Schalteingriff : 51|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ ESP_Haltebestaetigung : 53|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_MKB_Abbruch_Geschw : 54|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_QBit_v_Signal : 55|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ABS_Bremsung : 56|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ASR_Anf : 57|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MSR_Anf : 58|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ EBV_Eingriff : 59|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ EDS_Eingriff : 60|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Eingriff : 61|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_ASP : 62|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Anhaltevorgang_ACC_aktiv : 63|1@1+ (1.0,0.0) [0.0|1] "" XXX + +BO_ 987 Gateway_72: 8 Gateway_MQB + SG_ BCM_01_alt : 0|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ SMLS_01_alt : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ZV_02_alt : 2|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Wischer_01_alt : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Anhaenger_01_alt : 4|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ Klima_Sensor_02_alt : 5|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ VSG_01_alt : 6|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ Klima_01_alt : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_01_alt : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Licht_Anf_01_alt : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HFS_offen : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HBFS_offen : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ VS_VD_offen_ver : 22|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ VS_VD_zu_ver : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_BT_offen : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Rueckfahrlicht_Schalter : 25|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ZV_FT_offen : 26|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Wischer_vorne_aktiv : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Anhaenger_erkannt : 28|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ BCM1_MH_Schalter : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HD_offen : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Waschen_vorne_aktiv : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Thermomanagement : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ WFS_Schluessel_Fahrberecht : 34|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BCM1_RFahrlicht_Fzg_Anf : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_RFahrlicht_Ahg_Anf : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BH_Fernlicht : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BH_Blinker_li : 50|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BH_Blinker_re : 51|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_OBD_FStatus_ATemp : 52|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Aussen_Temp_ungef : 56|8@1+ (0.5,-50) [-50|76] "Unit_DegreCelsi" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 989 Gateway_74: 8 Gateway_MQB + SG_ LH_EPS_01_alt : 0|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB + SG_ Kessy_04_alt : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ LIN_2_alt : 2|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MFG_01_alt : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ GW_74_va_14 : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Klima_02_alt : 5|1@1+ (1,0) [0|1] "" BMS_MQB + SG_ Parkhilfe_01_alt : 6|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ELV_01_alt : 7|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KY_StartStopp_Info : 16|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ PH_StartStopp_Info : 18|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ EPS_Lenkerposition : 20|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB + SG_ ELV_Anf_Klemme_50 : 22|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ MF_StartStopp_Info : 25|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ KL_Geblaesespannung_Soll : 40|8@1+ (0.05,0.5) [2|13] "Unit_Volt" BMS_MQB + SG_ KL_Umluftklappe_Status : 48|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Tip_Down : 56|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MFL_Tip_Up : 57|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ LS_Tiptronic_Fehler : 58|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 296 Getriebe_06: 3 Getriebe_DQ_Hybrid_MQB + SG_ GE_WH_Sperre : 0|1@1+ (1,0) [0|1] "" Waehlhebel_MQB + SG_ GE_Ausleuchtungsmode : 1|1@1+ (1,0) [0|1] "" Waehlhebel_MQB + SG_ GE_Test_Freigabe : 2|1@1+ (1,0) [0|1] "" Waehlhebel_MQB + SG_ GE_Ist_Fahrstufe : 4|4@1+ (1,0) [0|15] "" Waehlhebel_MQB + SG_ GE_Testparameter_1 : 8|8@1+ (1,0) [0|255] "" Waehlhebel_MQB + SG_ GE_Testparameter_2 : 16|8@1+ (1,0) [0|255] "" Waehlhebel_MQB + +BO_ 173 Getriebe_11: 8 Getriebe_DQ_Hybrid_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER_DISABLED : 8|4@1+ (1,0) [0|15] "" XXX + SG_ GE_MMom_Soll_02 : 12|10@1+ (1,-509) [-509|509] "" XXX + SG_ GE_MMom_Vorhalt_02 : 22|10@1+ (1,-509) [-509|509] "" XXX + SG_ GE_Uefkt : 32|10@1+ (0.1,0) [0|102.2] "" XXX + SG_ GE_Fahrstufe : 42|4@1+ (1,0) [0|15] "" XXX + SG_ GE_reserv_Fahrstufe : 46|1@1+ (1,0) [0|1] "" XXX + SG_ GE_Schaltablauf : 47|2@1+ (1,0) [0|3] "" XXX + SG_ GE_Uefkt_unplausibel : 49|1@1+ (1,0) [0|1] "" XXX + SG_ GE_MMom_Status_02 : 50|3@1+ (1,0) [0|7] "" XXX + SG_ GE_Status_Kraftschluss : 53|3@1+ (1,0) [0|7] "" XXX + SG_ GE_MMom_Status : 56|2@1+ (1,0) [0|3] "" XXX + SG_ GE_Freig_MMom_Vorhalt : 58|1@1+ (1,0) [0|1] "" XXX + SG_ GE_Verbot_Ausblendung : 59|1@1+ (1,0) [0|1] "" XXX + SG_ GE_Zielgang : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 174 Getriebe_12: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_12_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Getriebe_12_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Drehzahlmesser_Daempfung : 12|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Schubabschalt_Unt : 13|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freigabe_Synchro : 14|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Synchro_Wunschdrehz : 15|9@1+ (25,0) [0|12750] "Unit_MinutInver" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Synchro_Zeit : 24|8@1+ (20,0) [0|5080] "Unit_MilliSecon" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Mom_Begr_Gradient : 32|8@1+ (10,0) [0|2540] "Unit_NewtoMeterPerSecon" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Anheb_Solldrehz_Leerlauf : 40|8@1+ (10,0) [0|2540] "Unit_MinutInver" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Aufnahmemoment : 48|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Anf_Zylabsch : 58|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ GE_HYB_DZ_Eingriff : 62|2@1+ (1,0) [0|3] "" Motor_Hybrid_MQB + +BO_ 301 Getriebe_13: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_13_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Getriebe_13_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_StartStopp_Info : 12|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ GE_Langfr_Schutzmom_02 : 14|9@1+ (1,0) [0|509] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Eingangsdrehz : 48|14@1+ (1,0) [0|16381] "Unit_MinutInver" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Notlauf : 62|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freig_Langfr_Schutzmom : 63|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 968 Getriebe_14: 8 Getriebe_DQ_Hybrid_MQB + SG_ GE_OBD_AbsperrVent : 12|4@1+ (1,0) [0|15] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_amax_moeglich : 16|9@1+ (0.024,-2.016) [-2.016|10.224] "Unit_MeterPerSeconSquar" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Charisma_FahrPr : 25|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ GE_Charisma_Status : 29|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ GE_Verlustmoment : 32|8@1+ (1,0) [0|254] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freigabe_Verfallsinfo_WFS : 49|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ GE_Codierung_MSG : 50|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ GE_LaunchControl : 51|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ GE_Heizwunsch : 52|2@1+ (1,0) [0|3] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_OBD_Status : 54|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_LFR_Adaption : 55|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Sumpftemperatur : 56|8@1+ (1,-58) [-58|196] "Unit_DegreCelsi" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 158 Getriebe_Hybrid_01: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_Hybrid_01_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Hybrid_MQB + SG_ Getriebe_Hybrid_01_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB + SG_ GE_HYB_Fehlerstatus : 12|2@1+ (1,0) [0|3] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freigabe_K0 : 16|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freigabe_LL_Reg : 17|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freig_sSchl_K0 : 18|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freig_VM_EM_Stop : 19|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Wiederstart : 20|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Filt_MomAufbau : 21|3@1+ (1,0) [0|7] "" Motor_Hybrid_MQB + SG_ GE_HYB_nK0 : 24|8@1+ (25,0) [0|6350] "Unit_MinutInver" Vector__XXX + SG_ GE_HYB_MomEingriff_EM : 32|6@1+ (0.5,0) [0|31.5] "Unit_NewtoMeter" LEH_MQB + SG_ GE_HYB_VZ_MomEingriff_EM : 38|1@1+ (1,0) [0|1] "" LEH_MQB + SG_ GE_HYB_Sportfaktor : 56|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB + SG_ GE_HYB_VM_akt_halten : 61|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_StartAnf : 62|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_VM_Startkontr : 63|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + +BO_ 299 GRA_ACC_01: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Hauptschalter : 12|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Abbrechen : 13|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Typ_Hauptschalter : 14|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Limiter : 15|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Setzen : 16|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Hoch : 17|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Runter : 18|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Wiederaufnahme : 19|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Verstellung_Zeitluecke : 20|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Codierung : 22|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Fehler : 24|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Typ468 : 25|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Stufe_2 : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_ButtonTypeInfo : 28|2@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 960 Klemmen_Status_01: 4 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,BMS_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,BMS_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ZAS_Kl_S : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZAS_Kl_15 : 17|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ZAS_Kl_X : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZAS_Kl_50 : 19|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 949 Klima_11: 8 Gateway_MQB + SG_ KL_Drehz_Anh : 0|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Vorwarn_Komp_ein : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_AC_Schalter : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Komp_Moment_alt : 3|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Zonen : 4|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Vorwarn_Zuheizer_ein : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Zustand : 7|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Comp_rev_rq : 8|8@1+ (50,0) [0|8600] "Unit_MinutInver" Vector__XXX + SG_ KL_Charisma_FahrPr : 16|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ KL_Charisma_Status : 20|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Comp_enable : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Last_Kompr : 24|8@1+ (0.25,0) [0|63.5] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Spannungs_Anf : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Thermomanagement : 34|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_StartStopp_Info : 36|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ KL_Anf_KL : 40|8@1+ (0.4,0) [0|101.6] "Unit_PerCent" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_el_Zuheizer_Stufe : 48|3@1+ (1,0) [0|7] "" Motor_Diesel_MQB + +BO_ 1625 Klimakomp_01: 8 Gateway_MQB + SG_ EKL_KD_Fehler : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EKL_Comp_SCI_com_stat : 16|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_output_stat : 18|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_main_stat : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EKL_Comp_ovld_stat : 21|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ EKL_Comp_Inv_stat : 24|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_photo_temp_stat : 30|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_photo_temp : 32|8@1+ (1,0) [0|254] "Unit_DegreCelsi" Vector__XXX + SG_ EKL_Comp_current : 40|8@1+ (0.1,0) [0|25.4] "Unit_Amper" Motor_Hybrid_MQB + SG_ EKL_Comp_rev_stat : 48|8@1+ (50,0) [0|8600] "Unit_MinutInver" Vector__XXX + +BO_ 2549088277 KN_Airbag_01: 8 Airbag_MQB + SG_ Airbag_01_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Airbag_01_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ AB_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088380 KN_EMotor_01: 8 LEH_MQB + SG_ EMotor_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EMotor_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ EM_HYB_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088375 KN_Getriebe_01: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Getriebe_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ GE_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088379 KN_Hybrid_01: 8 BMS_MQB + SG_ Hybrid_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Hybrid_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ BMS_HYB_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088374 KN_MO_01: 8 Motor_Diesel_MQB + SG_ Motor_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Motor_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088284 KN_SAK: 8 SAK_MQB + SG_ SAK_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SAK_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ SAK_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 779 Kombi_01: 8 Gateway_MQB + SG_ KBI_ABS_Lampe : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_ESP_Lampe : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_BKL_Lampe : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Airbag_Lampe : 3|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ KBI_SILA_gueltig : 4|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ KBI_Lenkung_Lampe : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Vorglueh_System_Lampe : 6|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB + SG_ KBI_NV_in_Anzeige : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Kombi_01_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Anzeigestatus_ACC : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigestatus_GRA : 13|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Oeldruck_Schalter : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Tankwarnung : 16|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_MFA_v_Einheit_01 : 17|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_im_Stellgliedtest : 18|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ KBI_Anzeigefehler_LDW : 19|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Variante_USA : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Oeldruckwarnung : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Handbremse : 23|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ KBI_V_Digital : 24|9@1+ (1,0) [0|511] "" Vector__XXX + SG_ KBI_PLA_in_Anzeige : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigefehler_NV : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigestatus_LIM : 35|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_angez_Geschw : 48|10@1+ (0.32,0) [0|325.12] "Unit_KiloMeterPerHour" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Einheit_Tacho : 58|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Konsistenz_ACC : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Fehler_Anzeige_ACC : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigefehler_SWA : 61|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1719 Kombi_02: 8 Gateway_MQB + SG_ KBI_Kilometerstand : 0|20@1+ (1,0) [0|1048573] "Unit_KiloMeter" Vector__XXX + SG_ KBI_Standzeit_02 : 20|17@1+ (1,0) [0|131068] "Unit_Secon" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Inhalt_Tank : 40|7@1+ (1,0) [0|125] "Unit_Liter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_FStatus_Tank : 47|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_QBit_Aussen_Temp_gef : 55|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Aussen_Temp_gef : 56|8@1+ (0.5,-50) [-50|75] "Unit_DegreCelsi" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 982 Licht_hinten_01: 8 Gateway_MQB + SG_ Licht_hinten_01_BZ : 0|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM2_Bremsl_durch_ECD : 5|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LH_Aussenlicht_def : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Standlicht_H_aktiv : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Parklicht_HL_aktiv : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Parklicht_HR_aktiv : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremslicht_H_aktiv : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Nebelschluss_aktiv : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckfahrlicht_aktiv : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_HL_akt : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_HR_akt : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_li_def : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_li_def : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schlusslicht_li_def : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckf_li_def : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Nebel_li_def : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_Nebel_li_def : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_Nebel_re_def : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_li_def : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Nebel_li_def : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_SL_BRL_BLK_li_def : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Brems_Blk_li_def : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_re_def : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_re_def : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schlusslicht_re_def : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckf_re_def : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Nebel_re_def : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_re_def : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Nebel_re_def : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_SL_BRL_BLK_re_def : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Brems_Blk_re_def : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Kennzl_def : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_3_Bremsl_def : 49|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LH_Nebel_mi_def : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckf_mi_def : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_li_ges_def : 54|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LH_Bremsl_re_ges_def : 55|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 134 LWI_01: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_Sensorstatus : 12|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_QBit_Sub_Daten : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LWI_QBit_Lenkradwinkel : 15|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_Lenkradwinkel : 16|13@1+ (0.1,0) [0|800] "Unit_DegreOfArc" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_VZ_Lenkradwinkel : 29|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_VZ_Lenkradw_Geschw : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LWI_Lenkradw_Geschw : 31|9@1+ (5,0) [0|2500] "Unit_DegreOfArcPerSecon" Vector__XXX + SG_ LWI_Sub_Daten : 40|16@1+ (1,0) [0|65535] "" Vector__XXX + +BO_ 263 Motor_04: 8 Motor_Diesel_MQB + SG_ MO_Istgang : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Sollgang : 12|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Oeldruck : 16|8@1+ (0.04,0) [0|10] "Unit_Bar" Gateway_MQB + SG_ MO_Anzeigedrehz : 24|12@1+ (3,0) [0|12282] "Unit_MinutInver" Gateway_MQB + SG_ MO_Schaltempf_verfbar : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Ladedruck : 39|9@1+ (0.01,0) [0|5.1] "Unit_Bar" Gateway_MQB + SG_ MO_KVS : 48|15@1+ (1,0) [0|32767] "Unit_MicroLiter" Gateway_MQB + SG_ MO_KVS_Ueberlauf : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 1600 Motor_07: 8 Motor_Diesel_MQB + SG_ MO_QBit_Ansaugluft_Temp : 0|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_QBit_Oel_Temp : 1|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Kuehlmittel_Temp : 2|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Stellgliedtest_Soundaktuator : 3|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Fehler_HV_Netz : 4|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_aktives_Getriebeheizen : 5|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Absperrventil_oeffnen : 6|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Ansaugluft_Temp : 8|8@1+ (0.75,-48) [-48|141.75] "Unit_DegreCelsi" Gateway_MQB + SG_ MO_Oel_Temp : 16|8@1+ (1,-60) [-60|192] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kuehlmittel_Temp : 24|8@1+ (0.75,-48) [-48|141.75] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Hoeheninfo : 32|8@1+ (0.00781,0) [0|1.98374] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kennfeldk : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Versionsinfo : 41|6@1+ (1,0) [0|63] "" Gateway_MQB + SG_ MO_Getriebe_kuehlen : 47|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Traegheit_02 : 48|5@1+ (0.01,0) [0|0.31] "Unit_KiloGramMeterSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Heizungspumpenansteuerung : 53|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ MO_SpannungsAnf : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Nachlaufzeit_Heizungspumpe : 58|6@1+ (15,0) [0|945] "Unit_Secon" Gateway_MQB + +BO_ 1607 Motor_09: 8 Motor_Diesel_MQB + SG_ MO_ITM_Kuehlmittel_Temp : 0|8@1+ (0.75,-48) [-45.75|143.25] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_E85_Sensor : 8|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ SCR_Anz_Motorstarts : 12|4@1+ (1,0) [0|8] "" Gateway_MQB + SG_ SCR_Reichweite : 16|15@1+ (1,0) [0|32766] "" Gateway_MQB + SG_ SCR_Warnstufe_1 : 32|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Warnstufe_2 : 33|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Text : 34|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ SCR_Akustik : 37|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Kraftstofffilter_Wasser : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Systemfehler : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Inducement_Strategie : 42|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_CO2_Faktor : 44|12@1+ (1,0) [1|4094] "Unit_GramPerLiter" Gateway_MQB + +BO_ 167 Motor_11: 8 Motor_Diesel_MQB + SG_ Motor_11_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ Motor_11_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Soll_Roh : 12|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Ist_Summe : 22|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,SAK_MQB + SG_ MO_Mom_Traegheit_Summe : 32|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Soll_gefiltert : 42|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Schub : 52|9@1+ (1,-509) [-509|0] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Status_Normalbetrieb_01 : 61|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_erste_Ungenauschwelle : 62|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_QBit_Motormomente : 63|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 168 Motor_12: 8 Motor_Diesel_MQB + SG_ Motor_12_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ Motor_12_BZ : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Mom_neg_verfuegbar : 12|9@1+ (1,-509) [-509|0] "Unit_NewtoMeter" Gateway_MQB + SG_ MO_Mom_Begr_stat : 21|9@1+ (1,0) [0|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Begr_dyn : 30|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB + SG_ MO_Momentenintegral_02 : 40|7@1+ (1,0) [0|100] "Unit_PerCent" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Drehzahl_01 : 47|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Drehzahl_01 : 48|16@1+ (0.25,0) [0|16383] "Unit_MinutInver" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,SAK_MQB + +BO_ 958 Motor_14: 8 Motor_Diesel_MQB + SG_ MO_StartStopp_Status : 12|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_StartStopp_Wiederstart : 14|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_StartStopp_Motorstopp : 15|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Freig_Reku : 16|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Kl_75 : 18|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Kl_50 : 19|1@1+ (1,0) [0|1] "" Gateway_MQB,LEH_MQB + SG_ MO_Gangposition : 20|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_StartStopp_Fahrerwunsch : 24|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_HYB_Fahrbereitschaft : 26|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB + SG_ MO_Ext_E_Fahrt_aktiv : 27|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Fahrer_bremst : 28|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Fahrer_bremst : 29|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_BLS : 30|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Konsistenz_Bremsped : 31|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Timeout_ESP : 32|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Klima_Eingr : 33|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Aussp_Anlass : 35|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Freig_Anlass : 36|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Kuppl_schalter : 37|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Interlock : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Motor_laeuft : 39|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kickdown : 40|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Status_Zylabschalt_01 : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_EKlKomLeiRed : 42|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Handshake_STH : 44|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_BKV_Unterdruckwarnung : 45|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Freigabe_Segeln : 46|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_PTC_Status : 47|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ MO_QBit_Gangposition : 50|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Signalquelle_Gangposition : 51|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Remotestart_Betrieb : 52|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 1631 Motor_16: 8 Motor_Diesel_MQB + SG_ TSK_QBit_Steigung : 12|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_QBit_Fahrzeugmasse : 13|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_SpannungsAnf_02 : 14|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_DPF_reg : 16|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Heizstrom_EKAT : 17|7@1+ (1,0) [0|126] "Unit_Amper" Gateway_MQB + SG_ MO_Heizstrom_SCR : 24|6@1+ (1,0) [0|62] "Unit_Amper" Gateway_MQB + SG_ TSK_Fahrzeugmasse_02 : 48|8@1+ (32,0) [0|8128] "Unit_KiloGram" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Steigung : 56|8@1+ (0.8,-101.6) [-101.6|101.6] "Unit_PerCent" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 812 Motor_17: 8 Motor_Diesel_MQB + SG_ MO_Prio_MAX_Wunschdrehzahl : 12|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Prio_MIN_Wunschdrehzahl : 13|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Luftpfad_aktiv : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_v_Begrenz_Aktivierbar : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Drehzahlbeeinflussung : 16|8@1+ (0.39,0) [0|99.45] "Unit_PerCent" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_MIN_Wunschdrehzahl : 24|8@1+ (25,0) [0|6350] "Unit_MinutInver" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_MAX_Wunschdrehzahl : 32|9@1+ (25,0) [0|12750] "Unit_MinutInver" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Charisma_FahrPr : 41|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Charisma_Status : 45|2@1+ (1,0) [0|3] "" Gateway_MQB + +BO_ 1648 Motor_18: 8 Motor_Diesel_MQB + SG_ MO_Hybrid_StartStopp_LED : 43|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Eis_Offroad_LED : 45|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Anzahl_Abgesch_Zyl : 47|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ MO_Zylabsch_Texte : 50|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_E85_BS_Texte : 52|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ MO_Drehzahl_Warnung : 55|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_obere_Drehzahlgrenze : 56|8@1+ (50,0) [50|12750] "Unit_MinutInver" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 289 Motor_20: 8 Motor_Diesel_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|255] "" XXX + SG_ MO_Fahrpedalrohwert_01 : 12|8@1+ (0.4,0) [0.0|101.6] "Unit_PerCent" XXX + SG_ MO_QBit_Fahrpedalwerte_01 : 20|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Fahrpedalgradient : 21|8@1+ (25,0) [0|6350] "Unit_PerCentPerSecon" XXX + SG_ MO_Sig_Fahrpedalgradient : 29|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_rel_Saugrohrdruck : 30|6@1+ (18,0) [0|1116] "Unit_MilliBar" XXX + SG_ MO_rel_Saugrohrdruck_gem_err : 36|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Moment_im_Leerlauf : 37|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Schubabschaltung : 38|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_StartStopp_StoppVorbereitung : 39|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Solldrehz_Leerlauf : 40|8@1+ (10,0) [0|2540] "Unit_MinutInver" XXX + SG_ MO_Entkopplung_Sollschlupf : 48|7@1+ (20,0) [0|2480] "Unit_MinutInver" XXX + SG_ MO_temporaere_Fahrerabwesenheit : 55|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ TSK_a_Soll_gradientenbegrenzt : 57|7@1+ (0.1,-7.2) [-7.2|5.4] "Unit_MeterPerSeconSquar" XXX + +BO_ 967 Motor_26: 8 Motor_Diesel_MQB + SG_ MO_HYB_Status_HV_Ladung : 8|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ WIV_Anzeige_aktiv : 12|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oelmin_Warn : 13|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Sensorfehler : 14|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Schieflage : 15|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oelstand : 16|4@1+ (12.5,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ MO_Zustand_HWP : 20|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ WIV_Oelsystem_aktiv : 24|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_nicht_betriebswarm : 25|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Ueberfuell_Warn : 26|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_laufender_Motor : 27|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_1 : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_2 : 29|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_3 : 30|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_4 : 31|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Text_Motorstart : 32|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_HYB_Text_5 : 36|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_6 : 37|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_7 : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Text_Partikelfil_Reg : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oelmenge : 43|5@1+ (125,0) [0|3875] "Unit_MilliLiter" Gateway_MQB + SG_ MO_Systemlampe : 48|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_OBD2_Lampe : 49|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Heissleuchte : 50|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Partikel_Lampe : 51|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Winterfahrprog : 52|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WIV_Oelstand_nicht_vorhanden : 53|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_nachfuellanzeige_ein : 54|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Ueberfuell_deaktiv : 55|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Unterfuell_Warn : 56|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Tankdeckel_Lampe : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Text_Tankdeckelwarn : 58|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oeldr_Warn_Motor : 60|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 1601 Motor_Code_01: 8 Motor_Diesel_MQB + SG_ Motor_Code_01_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ Motor_Code_01_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Faktor_Momente_02 : 12|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Hybridfahrzeug : 14|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Code : 16|8@1+ (1,0) [0|255] "" Gateway_MQB,SAK_MQB + SG_ MO_Getriebe_Code : 24|6@1+ (1,0) [0|63] "" Gateway_MQB + SG_ MO_StartStopp_Codiert : 30|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Anzahl_Zyl : 32|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Kraftstoffart : 36|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Hubraum : 40|7@1+ (0.1,0) [0|12.7] "Unit_Liter" Gateway_MQB + SG_ MO_Ansaugsystem : 47|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Leistung : 48|9@1+ (1,0) [0|511] "Unit_KiloWatt" Gateway_MQB + SG_ MO_Abgastyp_EOBD : 57|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ MO_Abgastyp_OBD : 58|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ MO_DPF_verbaut : 59|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_Codierung : 60|3@1+ (1,0) [0|7] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Einspritzart : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 157 Motor_Hybrid_01: 8 Motor_Hybrid_MQB + SG_ Motor_Hybrid_01_CRC : 0|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB + SG_ Motor_Hybrid_01_BZ : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_IstStatusK0 : 12|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_max_ind_VM_Mom : 16|10@1+ (1,0) [0|1021] "Unit_NewtoMeter" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Zielzustand : 26|3@1+ (1,0) [0|7] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Startmodus : 29|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_HYB_Startmodus_PQ3x : 32|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Stoppmodus : 33|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_VM_Mom_oE : 40|10@1+ (1,-100) [-100|922] "Unit_NewtoMeter" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_VM_aktiv : 50|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Schaltverhinderung : 51|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + +BO_ 811 Motor_Hybrid_02: 8 Motor_Hybrid_MQB + SG_ MO_HYB_E_Faktor : 12|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Drehzahl_VM : 16|16@1+ (0.25,0) [0|16256] "Unit_MinutInver" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_LowSpeedModus : 32|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + +BO_ 2600468501 NMH_Airbag_01: 8 Airbag_MQB + SG_ NM_Airbag_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Airbag_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Airbag_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_Airbag_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Airbag_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Airbag_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Airbag_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Airbag_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468604 NMH_EMotor_01: 8 LEH_MQB + SG_ NM_EMotor_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_EMotor_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_EMotor_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_EMotor_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_EMotor_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_NL_Daten_EEPROM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468496 NMH_Gateway: 8 Gateway_MQB + SG_ NM_Gateway_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Gateway_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Gateway_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Gateway_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_ACAN_Aktivitaet : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_FCAN_Aktivitaet : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_KCAN_Aktivitaet : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_ICAN_Aktivitaet : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_DiagCAN_Aktivitaet : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_ECAN_Aktivitaet : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_Energie_LIN_Aktivi000 : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_Bedien_LIN_Aktivitaet : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_EM_Aktivitaet : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_EM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_Shutdown : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_Spg_Messung : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_Wakeup_Monitor : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468599 NMH_Getriebe_01: 8 Getriebe_DQ_Hybrid_MQB + SG_ NM_Getriebe_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Getriebe_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Getriebe_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_Getriebe_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_v_gr_0 : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Pos_Erk : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Umg_Bed : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NL_Daten_EEPROM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468603 NMH_Hybrid_01: 8 BMS_MQB + SG_ NM_Hybrid_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Hybrid_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Hybrid_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_Hybrid_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Hybrid_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NL_Daten_EEPROM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NL_Luefter : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468598 NMH_MO_01: 8 Motor_Diesel_MQB + SG_ NM_MO_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_MO_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_MO_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_MO_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_HV_Abschaltung : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_EKP_Vorlauf : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_STH_Betrieb : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_Kuehlerluefter : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_Diagnose : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_WFS : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_EEPROM : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_Sonstige : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 913 OBD_01: 8 Motor_Diesel_MQB + SG_ OBD_Calc_Load_Val : 0|8@1+ (0.39215686275,0) [0|100] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Eng_Cool_Temp : 8|8@1+ (1,-40) [-40|215] "Unit_DegreCelsi" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Abs_Throttle_Pos : 16|8@1+ (0.39215686275,0) [0|100] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Abs_Load_Val : 24|16@1+ (0.39215686275,0) [0|25700] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Abs_Pedal_Pos : 40|8@1+ (0.39215686275,0) [0|100] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Kaltstart_Denominator : 59|1@1+ (1,0) [0|1] "" BMS_MQB,LEH_MQB + SG_ OBD_Minimum_Trip : 60|1@1+ (1,0) [0|1] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Driving_Cycle : 61|1@1+ (1,0) [0|1] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Warm_Up_Cycle : 62|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Normed_Trip : 63|1@1+ (1,0) [0|1] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + +BO_ 1630 OBD_Tankgeber_01: 8 Gateway_MQB + SG_ OBD_TG_F_Status_1 : 0|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_F_Status_2 : 4|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_F_Status_3 : 8|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_F_Status_4 : 12|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_1 : 16|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_2 : 28|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_3 : 40|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_4 : 52|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 1437 Remotestart_FFB: 8 Gateway_MQB + SG_ RSF_Tastencode_1 : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ RSF_Tastencode_2 : 8|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ RSF_Tastencode_Maske : 16|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Otto_MQB + +BO_ 984 RGS_VL_01: 8 Airbag_MQB + SG_ RGS_VL_Texte : 12|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ RGS_VL_Charisma_FahrPr : 14|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ RGS_VL_Charisma_Status : 18|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ RGS_VL_aktiv : 21|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Sitz : 25|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Schiebedach : 26|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Fenster : 27|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Warnblinken : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_Precrash_Basis : 32|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ RGS_VL_Precrash_Front : 40|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ RGS_VL_Precrash_Rear : 48|8@1+ (1,0) [0|255] "" Gateway_MQB + +BO_ 1528 SAK_01: 8 SAK_MQB + SG_ SAK_Charisma_FahrPr : 16|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ SAK_Charisma_Status : 20|2@1+ (1,0) [0|3] "" Gateway_MQB + +BO_ 1313 STH_01: 8 Gateway_MQB + SG_ STH_Funk_ein : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Funk_aus : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Zusatzheizung : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_LED : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_Pumpe_ein : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Geblaese : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_EKP_Anst : 6|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_Start_folgt : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Ventiloeffnungszeit : 8|6@1+ (1,0) [0|63] "Unit_Minut" Vector__XXX + SG_ STH_Ventil_Status : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Waermeeintrag : 16|6@1+ (1,0) [0|63] "" Vector__XXX + SG_ STH_KVS : 24|13@1+ (1,0) [0|8191] "Unit_MilliLiter" Vector__XXX + SG_ STH_Fehlerstatus : 37|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ STH_Heizleistung : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ STH_Wassertemp : 48|8@1+ (0.75,-40) [-40|142.25] "Unit_DegreCelsi" Vector__XXX + SG_ STH_Motorvorwaermung : 59|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_Servicemode : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_war_aktiv : 61|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_KVS_Ueberlauf : 62|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1172 STS_01: 8 Gateway_MQB + SG_ STS_01_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STS_01_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STS_Car_not_under_theft : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Car_under_theft : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Anlassersperre : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Typencodierung : 16|5@1+ (1,0) [0|31] "" Vector__XXX + SG_ STS_LIN_aktiv : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Standlicht : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Fahrlicht : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Alarm_still : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Texte : 27|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ STS_Laderelais : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Summer : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Alarm_Blinker : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Notstart : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Signalhorn : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Leerlaufschaltung : 56|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 1413 Systeminfo_01: 8 Gateway_MQB + SG_ SI_Sammel_SG_Fehler : 0|6@1+ (1,0) [0|60] "" Vector__XXX + SG_ SI_Rollenmode : 6|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ SI_QRS_Mode : 8|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ SI_T_Mode : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_NWDF : 10|1@1+ (1,0) [0|1] "" SAK_MQB + SG_ SI_NWDF_gueltig : 11|1@1+ (1,0) [0|1] "" SAK_MQB + SG_ SI_Sammelfehler : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GW_KD_Fehler : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_01 : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_02 : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_03 : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_04 : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_05 : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_06 : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_07 : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_08 : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_09 : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_10 : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_11 : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_12 : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_13 : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_14 : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_15 : 30|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 288 TSK_06: 8 Motor_Diesel_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Radbremsmom : 12|12@1+ (8,0) [0|32760] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Status : 24|3@1+ (1,0) [0|7] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_v_Begrenzung_aktiv : 27|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Standby_Anf_ESP : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_Freig_WU : 29|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ TSK_Freig_Verzoeg_Anf : 30|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Limiter_ausgewaehlt : 31|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Wunsch_Uebersetz : 32|10@1+ (0.0245,0) [0.0245|25.0635] "" Gateway_MQB + SG_ TSK_Hauptschalter_GRA_ACC : 42|2@1+ (1.0,0.0) [0.0|3] "" Gateway_MQB + SG_ TSK_SRBM_Anf_ASIL : 44|3@1+ (1.0,0.0) [0.0|7] "" Gateway_MQB + SG_ TSK_ax_Getriebe_02 : 48|9@1+ (0.024,-2.016) [-2.016|10.224] "Unit_MeterPerSeconSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Zwangszusch_ESP : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_zul_Regelabw : 58|6@1+ (0.024,0) [0|1.512] "Unit_MeterPerSeconSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 798 TSK_07: 8 Motor_Diesel_MQB + SG_ TSK_07_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_AQ + SG_ TSK_07_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_AQ + SG_ TSK_Wunschgeschw : 12|10@1+ (0.32,0) [0.00|326.72] "Unit_KiloMeterPerHour" Gateway_MQB,Getriebe_AQ + SG_ TSK_Texte : 40|5@1+ (1.0,0.0) [0.0|31] "" Gateway_MQB + SG_ TSK_Akustik : 45|3@1+ (1.0,0.0) [0.0|7] "" Gateway_MQB + SG_ TSK_Texte_Primaeranz : 48|5@1+ (1.0,0.0) [0.0|31] "" Gateway_MQB + SG_ TSK_Limiter_Fahrerinfo : 53|2@1+ (1.0,0.0) [0.0|3] "" Gateway_MQB + SG_ TSK_Limiter_Anzeige : 55|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ TSK_Fahrzeugstatus_GRA : 56|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ TSK_Fahrzeugstatus_Limiter : 57|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ MO_Motorlaufwarnung : 58|1@1+ (1.0,0.0) [0.0|1] "" Gateway_MQB + SG_ TSK_Status_Anzeige : 61|3@1+ (1.0,0.0) [0.0|7] "" Gateway_MQB + +BO_ 346 TSK_08: 8 Motor_Diesel_MQB + SG_ TSK_08_CRC : 0|8@1+ (1,0) [0|255] "" Frontradar + SG_ TSK_08_BZ : 8|4@1+ (1,0) [0|15] "" Frontradar + SG_ MO_Anforderung_HMS : 12|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ TSK_Status_EA : 32|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ TSK_vMax_Fahrerassistenz : 40|9@1+ (1,0) [0|510] "" Frontradar + SG_ TSK_Einheit_vMax_Fahrerassistenz : 49|1@1+ (1,0) [0|1] "" Frontradar + SG_ TSK_Status_PLA : 50|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ TSK_aktives_System : 53|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ TSK_erhoehter_Fahrwiderstand : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TSK_Anf_Antriebsmoment : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ TSK_Status_ARA : 58|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ TSK_Status_IPA : 61|3@1+ (1,0) [0|7] "" Vector__XXX + +BO_ 1716 VIN_01: 8 Gateway_MQB + SG_ VIN_01_MUX M : 0|2@1+ (1,0) [0|3] "" Airbag_MQB + SG_ KS_Geheimnis_1 m0 : 8|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ VIN_4 m1 : 8|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_11 m2 : 8|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ KS_Geheimnis_2 m0 : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ VIN_5 m1 : 16|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_12 m2 : 16|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ KS_Geheimnis_3 m0 : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ VIN_6 m1 : 24|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_13 m2 : 24|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ KS_Geheimnis_4 m0 : 32|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ VIN_7 m1 : 32|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_14 m2 : 32|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_1 m0 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_8 m1 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_15 m2 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_2 m0 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_9 m1 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_16 m2 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_3 m0 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_10 m1 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_17 m2 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + +BO_ 175 Waehlhebel_03: 4 Waehlhebel_MQB + SG_ WH_Status_Sperre : 0|3@1+ (1,0) [0|7] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Initialisierung : 3|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_SensorPos_roh : 4|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_03_BZ : 8|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_SensorPos_roh_inv : 12|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Testergebnis : 16|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Test_Aktiv : 24|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Status : 25|7@1+ (1,0) [0|127] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 916 WBA_03: 8 Getriebe_DQ_Hybrid_MQB + SG_ WBA_03_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ WBA_03_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_Fahrstufe_02 : 12|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_ZielFahrstufe : 16|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_GE_Warnung_02 : 20|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_eing_Gang_02 : 24|4@1+ (1,0) [0|15] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Otto_MQB + SG_ WBA_GE_Texte : 28|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ WBA_Segeln_aktiv : 31|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WBA_Schaltschema : 32|5@1+ (1,0) [0|31] "" Gateway_MQB + +BO_ 1602 WIV_01: 8 Motor_Diesel_MQB + SG_ WIV_Verschleissindex : 0|16@1+ (2e-8,0) [0|0.00131068] "" Gateway_MQB + SG_ WIV_Russindex : 16|16@1+ (2e-8,0) [0|0.00131068] "" Gateway_MQB + SG_ WIV_t_min : 32|6@1+ (1,0) [0|63] "Unit_Month" Gateway_MQB + SG_ WIV_t_max : 40|6@1+ (1,0) [0|63] "Unit_Month" Gateway_MQB + SG_ WIV_W_min : 48|7@1+ (1000,0) [0|127000] "Unit_KiloMeter" Gateway_MQB + SG_ WIV_W_max : 56|7@1+ (1000,0) [0|127000] "Unit_KiloMeter" Gateway_MQB + +BO_ 294 HCA_01: 8 Frontsensorik + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HCA_01_Vib_Freq : 12|4@1+ (1,15) [15|30] "Unit_Hertz" Vector__XXX + SG_ HCA_01_LM_Offset : 16|9@1+ (1,0) [0|511] "Unit_centiNewtoMeter" Vector__XXX + SG_ EA_ACC_Sollstatus : 25|2@1+ (1,0) [0|3] "" Frontradar + SG_ EA_Ruckprofil : 27|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ HCA_01_Sendestatus : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_LM_OffSign : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_Status_HCA : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HCA_01_Vib_Amp : 36|4@1+ (0.2,0) [0|3] "Unit_NewtoMeter" Vector__XXX + SG_ EA_Ruckfreigabe : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EA_ACC_Wunschgeschwindigkeit : 41|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" Frontradar + +BO_ 810 LH_EPS_01: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_SpannungsAnf : 12|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ EPS_Endanschlag : 14|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ EPS_Akustiksignal : 16|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ EPS_Fehlerlampe : 17|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ EPS_Warnungen : 19|3@1+ (1.0,0.0) [0.0|7] "" XXX + SG_ EPS_PLA_Abbruch : 22|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_PLA_Fehler : 26|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_PLA_Status : 30|4@1+ (1.0,0.0) [0.0|15] "" XXX + SG_ EPS_Charisma_FahrPr : 34|4@1+ (1.0,0.0) [0.0|15] "" XXX + SG_ EPS_Charisma_Status : 38|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ EPS_Lenkerposition : 41|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ EPS_Anf_KL : 43|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ EPS_ARA_Status : 44|4@1+ (1.0,0.0) [0.0|15] "" XXX + +BO_ 159 LH_EPS_03: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_DSR_Status : 12|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_Berechneter_LW : 16|12@1+ (0.15,0) [0|613.95] "Unit_DegreOfArc" XXX + SG_ EPS_BLW_QBit : 30|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_VZ_BLW : 31|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_HCA_Status : 32|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_Lenkmoment : 40|10@1+ (1,0) [0|8] "Unit_centiNewtoMeter" XXX + SG_ EPS_Lenkmoment_QBit : 54|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_VZ_Lenkmoment : 55|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_Lenkungstyp : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 286 ESP_08: 8 Gateway_MQB + SG_ ESP_08_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ ESP_08_BZ : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ESP_ANB_CM_Rueckk_Umsetz : 12|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Konsistenz_ACC_Botschaft : 13|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Stillstandsphase_erschoepft : 14|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_ZT_Rueckk_Umsetz : 15|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Tuerkontakt_Fahrertuer : 16|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Abrutschen_Stillstand : 18|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_Fahrer_tritt_ZBR_Schw : 19|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_QBit_v_ref : 41|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ ESP_v_ref_Fahrtrichtung : 42|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ ESC_Bremsdruckgradient : 44|8@1+ (10,0) [0|2500] "Unit_BarPerSecon" XXX + SG_ ESP_v_ref : 52|12@1+ (0.125,0) [0.000|511.500] "Unit_KiloMeterPerHour" XXX + +BO_ 919 LDW_02: 8 XXX + SG_ LDW_Gong : 12|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_SW_Warnung_links : 14|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_SW_Warnung_rechts : 15|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Texte : 16|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Seite_DLCTLC : 20|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Lernmodus : 21|3@1+ (1,0) [0|7] "" XXX + SG_ LDW_Anlaufsp_VLR : 24|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Vib_Amp_VLR : 28|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Anlaufzeit_VLR : 32|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Lernmodus_rechts : 36|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Lernmodus_links : 38|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_DLC : 40|8@1+ (0.01,-1.25) [-1.25|1.25] "Unit_Meter" XXX + SG_ LDW_TLC : 48|5@1+ (0.1,0) [0|3] "Unit_Secon" XXX + SG_ LDW_Warnung_links : 56|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Warnung_rechts : 57|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Codierinfo_fuer_VLR : 58|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Frontscheibenheizung_aktiv : 60|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Status_LED_gelb : 61|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Status_LED_gruen : 62|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_KD_Fehler : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 780 ACC_02: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Wunschgeschw_02 : 12|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" XXX + SG_ ACC_Status_Prim_Anz : 22|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Abstandsindex : 24|10@1+ (1,0) [1|1021] "" XXX + SG_ ACC_Akustik_02 : 34|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Warnung_Verkehrszeichen_1 : 36|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Gesetzte_Zeitluecke : 37|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Optischer_Fahrerhinweis : 40|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ_Tachokranz : 41|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Anzeige_Zeitluecke : 42|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Tachokranz : 43|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Display_Prio : 44|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Relevantes_Objekt : 46|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Texte_Primaeranz : 48|7@1+ (1,0) [0|127] "" XXX + SG_ ACC_Wunschgeschw_erreicht : 55|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ_Tachokranz_unten : 60|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Status_Anzeige : 61|3@1+ (1,0) [0|7] "" XXX + +BO_ 302 ACC_07: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Anhalteweg : 12|11@1+ (0.01,0) [0|20.45] "Unit_Meter" XXX + SG_ ACC_Anhalten : 23|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Boost_Anf : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Freilauf_Anf : 25|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Freilauf_Info : 26|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Anforderung_HMS : 28|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Anfahren : 31|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Folgebeschl : 32|8@1+ (0.03,-4.6) [-4.6|2.99] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_Sollbeschleunigung_02 : 53|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" XXX + +BO_ 264 Fahrwerk_01: 8 XXX + SG_ Fahrwerk_01_BZ : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Fahrwerk_01_CRC : 0|8@1+ (1,0) [0|255] "" XXX + +BO_ 695 RCTA_01: 8 XXX + SG_ RCTA_01_BZ : 8|4@1+ (1,0) [0|15] "" XXX + SG_ RCTA_01_CRC : 0|8@1+ (1,0) [0|255] "" XXX + +BO_ 783 SWA_01: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ SWA_Anzeigen : 12|4@1+ (1,0) [0|15] "" XXX + SG_ SWA_Blindheit_erkannt : 16|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_rel_Nichtverf : 17|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_rel_Fehler : 18|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Sta_aktiv : 19|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Sta_passiv : 20|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_FT_RueckLED : 21|1@1+ (1,0) [0|1] "" XXX + SG_ ASW_Status : 22|2@1+ (1,0) [0|3] "" XXX + SG_ SWA_Standziele_li : 24|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Kolonne_li : 25|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Infostufe_SWA_li : 26|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Warnung_SWA_li : 27|1@1+ (1,0) [0|1] "" XXX + SG_ ASW_Warnung_FS : 28|1@1+ (1,0) [0|1] "" XXX + SG_ ASW_Warnung_BFS : 29|1@1+ (1,0) [0|1] "" XXX + SG_ ASW_Kombitexte : 30|3@1+ (1,0) [0|7] "" XXX + SG_ SWA_Kolonne_mi : 33|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Standziele_re : 40|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Kolonne_re : 41|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Infostufe_SWA_re : 42|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Warnung_SWA_re : 43|1@1+ (1,0) [0|1] "" XXX + SG_ HRE_Anzeigetexte : 44|4@1+ (1,0) [0|15] "" XXX + SG_ SWA_Gischtzaehler : 48|7@1+ (1,0) [0|100] "Unit_PerCent" XXX + SG_ Heckradar_Kombitexte : 56|5@1+ (1,0) [0|31] "" XXX + SG_ RCTA_Kombitexte : 61|3@1+ (1,0) [0|7] "" XXX + +BO_ 804 ACC_04: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Texte_Sekundaeranz : 12|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Texte_Zusatzanz : 16|6@1+ (1,0) [0|63] "" XXX + SG_ ACC_Status_Zusatzanz : 22|5@1+ (1,0) [0|31] "" XXX + SG_ ACC_Texte : 27|5@1+ (1,0) [0|31] "" XXX + SG_ ACC_Texte_braking_guard : 32|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Warnhinweis : 35|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Zeitluecke_Abstandswarner : 36|6@1+ (0.1,0) [0|6] "Unit_Secon" XXX + SG_ ACC_Abstand_Abstandswarner : 42|9@1+ (1,0) [0|508] "" XXX + SG_ ACC_Tempolimit : 51|5@1+ (1,0) [0|31] "" XXX + SG_ ACC_Charisma_FahrPr : 56|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Charisma_Status : 60|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Texte_Abstandswarner : 62|2@1+ (1,0) [0|3] "" XXX + +BO_ 917 LWR_AFS_01: 8 XXX + +BO_ 991 Gateway_76: 8 XXX + +BO_ 997 TSG_FT_02: 8 XXX + SG_ TSG_FT_02_BZ : 8|4@1+ (1,0) [0|15] "" XXX + SG_ TSG_FT_02_CRC : 0|8@1+ (1,0) [0|255] "" XXX + +BO_ 1175 Parkhilfe_01: 8 XXX + +BO_ 427 ESP_33: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_AHW_aktiv : 12|3@1+ (1,0) [0|7] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_AHW_nicht_verfuegbar : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_ANB_CM_aktiv : 16|2@1+ (1,0) [0|3] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_ANB_CM_nicht_verfuegbar : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Warnruck_aktiv : 19|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Warnruck_nicht_verfuegbar : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Prefill_aktiv : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Prefill_nicht_verfuegbar : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_HBA_aktiv : 26|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESC_HBA_nicht_verfuegbar : 27|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESC_TSK_SRBM_Anf : 28|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_TSK_SRBM_nicht_verfuegbar : 29|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Verz_Reg_aktiv : 30|4@1+ (1,0) [0|15] "" Airbag_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Verz_Reg_nicht_verfuegbar : 34|1@1+ (1,0) [0|1] "" Airbag_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Verz_Reg_TB_nicht_verfuegbar : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Verz_Reg_ZB_nicht_verfuegbar : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Bremslicht_unplausibel : 37|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Konsistenz_ACC : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_AWV : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_ARA : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_IPA : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_FCW : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_NV : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_RCTA : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_TSK : 45|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Konsistenz_vFGS : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_STA : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Fahrer_Bremsdruck_bestimmend : 48|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Konsistenz_EA : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_BFF : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_MKB : 51|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESC_Verz_ASIL_Verfuegbarkeit : 52|3@1+ (1,0) [0|7] "" Airbag_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESC_Pumpenanlauf_aktiv : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_AGW : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_KAS : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_PCF : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_FAS_VK : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Verz_Begrenzung : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESC_Konsistenz_AWA : 61|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 418 ESP_15: 8 XXX + SG_ ESP_15_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ ESP_15_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 1122 PSD_04: 8 XXX + SG_ PSD_Object_Index : 0|6@1+ (1,0) [0|63] "" XXX + +BO_ 1123 PSD_05: 8 XXX + SG_ PSD_Current_Route_Index : 0|6@1+ (1,0) [0|63] "" XXX + SG_ Route_Distance_Remaining : 8|5@1+ (1,0) [0|31] "" XXX + +BO_ 1124 PSD_06: 8 XXX + +BO_ 988 Gateway_73: 8 XXX + SG_ UNKNOWN_1 : 15|2@0+ (1,0) [0|3] "" XXX + SG_ GE_Fahrstufe : 40|4@1+ (1,0) [0|15] "" XXX + SG_ EPB_Status : 53|3@1+ (1,0) [0|7] "" XXX + SG_ UNKNOWN_2 : 58|3@0+ (1,0) [0|7] "" XXX + +BO_ 792 Kamera_Status: 8 XXX + +BO_ 981 Licht_Anf_01: 8 Vector__XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BCM1_Kurvenlicht_links_Anf : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Kurvenlicht_rechts_Anf : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Standlicht_Anf : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Abblendlicht_Anf : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Fernlicht_Anf : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Nebellicht_Anf : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Parklicht_li_Anf : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Parklicht_re_Anf : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Nebelschluss_Ahg_Anf : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Nebelschluss_Fzg_Anf : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Schlusslicht_Anf : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Rueckfahrlicht_Anf : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Signaturlicht_Anf : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Umfeldleuchten_Anf : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Tagfahrlicht_Anf : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Regenlicht_Anf : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Autobahnlicht_Anf : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Touristen_Licht_Anf : 29|1@1+ (1,0) [0|1] "" Frontradar + SG_ BCM1_CH_aktiv : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_LH_aktiv : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Gleitende_Leuchtw_Anf : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_GLW_Fernlicht_Anf : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Adaptive_Lichtvert_Anf : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_CH_LH_aktiv : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Allwetterlicht_Anf : 41|1@1+ (1,0) [0|1] "" Frontradar + +BO_ 1440 RLS_01: 8 XXX + +BO_ 870 Blinkmodi_02: 8 XXX + SG_ Hazard_Switch : 20|1@1+ (1,0) [0|1] "" XXX + SG_ Comfort_Signal_Left : 23|1@1+ (1,0) [0|1] "" XXX + SG_ Comfort_Signal_Right : 24|1@1+ (1,0) [0|1] "" XXX + SG_ Left_Turn_Exterior_Bulb_1 : 25|1@1+ (1,0) [0|1] "" XXX + SG_ Right_Turn_Exterior_Bulb_1 : 26|1@1+ (1,0) [0|1] "" XXX + SG_ Left_Turn_Exterior_Bulb_2 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Right_Turn_Exterior_Bulb_2 : 28|1@1+ (1,0) [0|1] "" XXX + SG_ Fast_Send_Rate_Active : 37|1@1+ (1,0) [0|1] "" XXX + +BO_ 1385 HVEM_04: 8 XXX + +BO_ 1605 FLA_01: 8 XXX + +BO_ 1624 Licht_vorne_01: 8 XXX + +BO_ 1646 Klima_03: 8 XXX + +BO_ 1720 Kombi_03: 8 XXX + SG_ KBI_Reifenumfang : 0|12@1+ (1,0) [0|4095] "Unit_MilliMeter" XXX + SG_ KBI_Variante_USA : 12|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ KBI_Variante : 13|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ KBI_BCmE_aktiv : 16|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ KBI_Sparhinweis_quittiert : 17|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ KBI_Tankfuellstand_Prozent : 18|7@1+ (1,0) [0|100] "Unit_PerCent" XXX + SG_ KBI_Nachtanken_erkannt : 25|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ KBI_Tankinhalt_hochaufl : 26|14@1+ (0.01,0) [0.00|163.81] "Unit_Liter" XXX + SG_ KBI_Max_Tankinhalt : 40|8@1+ (0.5,0) [0.0|126.5] "" XXX + SG_ KBI_Reifenumfang_Sekundaer : 48|12@1+ (1,0) [0|4095] "Unit_MilliMeter" XXX + +BO_ 391 Motor_EV_01: 8 Motor_MQB_BEV + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EV_Rekuperationsstufe : 12|3@1+ (1.0,0.0) [0.0|7] "" XXX + SG_ HV_Bordnetz_aktiv : 15|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Waehlpos : 16|3@1+ (1.0,0.0) [0.0|7] "" XXX + SG_ MO_Fehler_NTKreis : 19|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Fehler_Notabschaltung_Klima : 20|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ MO_KLE_FStatus : 22|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ MO_WH_Texte : 24|3@1+ (1.0,0.0) [0.0|7] "" XXX + SG_ MO_Drehzahl_VM : 32|16@1+ (0.25,0) [0.00|16383.00] "Unit_MinutInver" XXX + SG_ HV_Bordnetz_Fehler : 48|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_Tankbereitschaft_Status : 49|3@1+ (1.0,0.0) [0.0|7] "" XXX + SG_ MO_Tankklappensteuerung : 52|2@1+ (1.0,0.0) [0.0|3] "" XXX + SG_ MO_HVEM_Eskalation : 54|1@1+ (1.0,0.0) [0.0|1] "" XXX + SG_ MO_HVEM_MaxLeistung : 55|9@1+ (50,0) [0|25450] "Unit_Watt" XXX + +CM_ SG_ 134 LWI_Lenkradwinkel "Steering angle WITH variable ratio effect included"; +CM_ SG_ 159 EPS_HCA_Status "Status of Heading Control Assist feature"; +CM_ SG_ 159 EPS_Lenkmoment "Steering input by driver, torque"; +CM_ SG_ 159 EPS_VZ_Lenkmoment "Steering input by driver, direction"; +CM_ SG_ 159 EPS_Berechneter_LW "Raw steering angle, degrees"; +CM_ SG_ 159 EPS_VZ_BLW "Raw steering angle, direction"; +CM_ SG_ 173 COUNTER_DISABLED "Message not renamed to COUNTER because J533 rate-limiting makes it look like messages are being lost"; +CM_ SG_ 294 HCA_01_Vib_Freq "Frequenz der Lenkradvibration"; +CM_ SG_ 294 HCA_01_LM_Offset "Von HCA angefordertes Lenkmoment (Betrag)"; +CM_ SG_ 294 EA_ACC_Sollstatus "Status-Anforderung ACC von Emergency Alert. Statuswechsel bei Flanke. Solange Wert=1, wird EA_ACC_Wunschgeschwindigkeit übernommen. Wert=2 führt zu Zustand ¿ACC_GRA_passiv¿"; +CM_ SG_ 294 EA_Ruckprofil "Emergency Alert Anforderung an ESP, welcher Ruck verwendet werden soll. Eine Umsetzung der Ruckanforderung im ESP erfolgt nur mit gesetztem Bit 'EA_Ruckfreigabe'."; +CM_ SG_ 294 HCA_01_Sendestatus "Gibt den Sendestatus der HCA_01 an (notwendig für IL-Unterstützung)"; +CM_ SG_ 294 HCA_01_LM_OffSign "Vorzeichen des HCA-Lenkmoments"; +CM_ SG_ 294 HCA_01_Status_HCA "Statusinformation vom HCA und Manoevrierassistent für Handshakemechanismus mit der Lenkung"; +CM_ SG_ 294 HCA_01_Vib_Amp "Momentenamplitude der Lenkradvibration"; +CM_ SG_ 294 EA_Ruckfreigabe "Emergency Alert Freigabit für die Warnruck-Anforderung an das ESP"; +CM_ SG_ 294 EA_ACC_Wunschgeschwindigkeit "Emergency Alert Anforderung neue Wunschgeschwindigkeit"; +CM_ SG_ 302 ACC_Hold_Request "Active request for ABS brake hold in ACC_Hold_Type"; +CM_ SG_ 302 ACC_Boost_Request "Hybrid engine start related"; +CM_ SG_ 302 ACC_Freewheel_Request "Active request for DSG sailing/coasting in ACC_Freewheel_Type"; +CM_ SG_ 302 ACC_Hold_Release "Request to ABS to release brake hold"; +CM_ SG_ 302 ACC_Accel_Secondary "Target acceleration of the secondary controller"; +CM_ SG_ 302 ACC_Accel_TSK "Mirror of request to TSK to implement a target acceleration"; +CM_ SG_ 870 Hazard_Switch "Four-way flashers active"; +CM_ SG_ 870 Comfort_Signal_Left "Comfort turn signal active, left"; +CM_ SG_ 870 Comfort_Signal_Right "Comfort turn signal active, right"; +CM_ SG_ 870 Left_Turn_Exterior_Bulb_1 "Probably front"; +CM_ SG_ 870 Right_Turn_Exterior_Bulb_1 "Probably front"; +CM_ SG_ 870 Left_Turn_Exterior_Bulb_2 "Probably rear"; +CM_ SG_ 870 Right_Turn_Exterior_Bulb_2 "Probably rear"; +CM_ SG_ 870 Fast_Send_Rate_Active "CAN message send rate"; +CM_ SG_ 919 LDW_DLC "Probable DLC (distance to line crossing)"; +CM_ SG_ 919 LDW_TLC "Probable TLC (time to line crossing)"; +CM_ SG_ 919 LDW_Unknown "Might be a steering pressed / driver active flag"; +CM_ SG_ 919 Alert_Message "Static table of alert messages to be invoked in the instrument cluster, some with or without beeps, 0 = no current message"; +CM_ SG_ 919 LDW_Direction "Left/right indicator for DLC and TLC"; +CM_ SG_ 919 Right_Lane_Status "Display brightness range, 0 = no lane, 3 = full brightness"; +CM_ SG_ 919 Left_Lane_Status "Display brightness range, 0 = no lane, 3 = full brightness"; +CM_ SG_ 919 Kombi_Lamp_Orange "Enables orange LDW light in instrument cluster"; +CM_ SG_ 919 Kombi_Lamp_Green "Enables green LDW light in instrument cluster"; +CM_ SG_ 780 Folgefahrt "Following another vehicle"; +CM_ SG_ 780 SetAbstand "Set following distance"; +CM_ SG_ 780 Abstand "Following distance"; +CM_ SG_ 780 SetSpeed "ACC set speed"; +CM_ SG_ 391 MO_Waehlpos "Traditional PRND plus B-mode aggressive regen, B-mode mapped to Drive"; +CM_ SG_ 679 ACC_ADAPTIVE "TSK_06.TSK_Limiter_ausgewaehlt seems to take precedence"; +CM_ SG_ 960 ZAS_Kl_15 "Indicates ignition on"; +CM_ SG_ 1720 KBI_BCmE_aktiv "Anzeige BCmE aktiv (BCmE-Screen oder Einsparhinweis in der Anzeige)"; +CM_ SG_ 1720 KBI_Max_Tankinhalt "Mitteilung des maximalen Tankinhalts an das Reichweitenmodul"; +CM_ SG_ 1720 KBI_Nachtanken_erkannt "Statusinformation Nachtankmodus"; +CM_ SG_ 1720 KBI_Reifenumfang "Mittlerer Radumfang aus der K-Zahl gerechnet in Millimeter. Byte 2 Bit 5,4 reserviert, Byte 2 Bit 3..0 und Byte 1 Bit 7..0; Wertebereich 0..4096 mm +"; +CM_ SG_ 1720 KBI_Reifenumfang_Sekundaer "Fahrzeuge mit unterschiedlichen Reifenumfängen Vorderachse / Hinterachse: + +Primärachse: KBI_Reifenumfang +Sekundärachse: KBI_Reifenumfang_Sekundaer +"; +CM_ SG_ 1720 KBI_Sparhinweis_quittiert "angezeigter Sparhinweis ist quittiert. Signal wird nach zwei Sendebotschaften wieder auf '0' gesetzt."; +CM_ SG_ 1720 KBI_Tankfuellstand_Prozent "Tankfüllstand in %"; +CM_ SG_ 1720 KBI_Tankinhalt_hochaufl "angezeigter Tankinhalt hochauflösend zur Restreichweitenberechnung"; +CM_ SG_ 1720 KBI_Variante "Zeigt an ob es sich um ein konventionelles Zeiger-Kombiinstrument handelt oder um eine Volldisplay-Kombiinstrument"; +CM_ SG_ 1720 KBI_Variante_USA "In diesem Signal wird die HW-Variante des Kombis ausgegeben, ACC plausibilisiert auf dieses Signal hin seine US-Codierung"; + + +VAL_ 159 EPS_HCA_Status 0 "disabled" 1 "initializing" 2 "fault" 3 "ready" 4 "rejected" 5 "active" 8 "preempted" ; +VAL_ 173 GE_Fahrstufe 5 "P" 6 "R" 7 "N" 8 "D" 9 "S" 10 "E" 13 "T" 14 "T" ; +VAL_ 288 TSK_Status 0 "init" 1 "disabled" 2 "enabled" 3 "regulating" 4 "accel_pedal_override" 5 "brake_only" 6 "temp_fault" 7 "perm_fault" ; +VAL_ 288 TSK_v_Begrenzung_aktiv 0 "inaktiv" 1 "aktiv" ; +VAL_ 288 TSK_Standby_Anf_ESP 0 "keine_Standby_Anforderung" 1 "Standby_Anforderung" ; +VAL_ 288 TSK_Freig_WU 0 "TSK_Uebersetzungswunsch_nicht_freigegeben" 1 "TSK_Uebersetzungswunsch_freigegeben" ; +VAL_ 288 TSK_Freig_Verzoeg_Anf 0 "Verzoegerungsanforderung_nicht_freigegeben" 1 "Verzoegerungsanforderung_freigegeben" ; +VAL_ 288 TSK_Limiter_ausgewaehlt 0 "kein_Limiter_ausgewaehlt" 1 "Limiter_ausgewaehlt" ; +VAL_ 288 TSK_Wunsch_Uebersetz 0 "Init" ; +VAL_ 288 TSK_Hauptschalter_GRA_ACC 0 "Init" 1 "Aus" 2 "Ein" 3 "Fehler" ; +VAL_ 288 TSK_ax_Getriebe_02 511 "Neutralwert" ; +VAL_ 288 TSK_Zwangszusch_ESP 0 "keine_ESP_ASR_Beeinflussung" 1 "ESP_ASR_Beeinflussung" ; +VAL_ 294 EA_ACC_Sollstatus 0 "Init" 1 "ACC_aktivieren" 2 "ACC_deaktivieren" ; +VAL_ 294 EA_Ruckprofil 0 "Init" 1 "Profil_1" 2 "Profil_2" 3 "Profil_3" 4 "Profil_4" 5 "Profil_5" 6 "Profil_6" 7 "Profil_7" ; +VAL_ 294 HCA_01_Sendestatus 0 "HCA_sendet_mit_1000ms" 1 "HCA_sendet_mit_20ms" ; +VAL_ 294 HCA_01_LM_OffSign 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen" ; +VAL_ 294 HCA_01_Status_HCA 0 "deaktiviert" 1 "reserviert" 2 "reserviert" 3 "funktionsbereit" 4 "reserviert" 5 "HCA_Momenteneingriff_1" 6 "MA_Aktiv" 7 "HCA_Momenteneingriff_2" 8 "reserviert" 9 "reserviert" 10 "reserviert" 11 "reserviert" 12 "reserviert" 13 "reserviert" 14 "reserviert" 15 "reserviert" ; +VAL_ 294 EA_Ruckfreigabe 0 "keine_Freigabe" 1 "Freigabe" ; +VAL_ 294 EA_ACC_Wunschgeschwindigkeit 1023 "Init" ; +VAL_ 346 MO_Anforderung_HMS 0 "keine_Anforderung" 1 "halten" 2 "parken" 3 "halten_Standby" 4 "anfahren" 5 "Loesen_ueber_Rampe" ; +VAL_ 346 TSK_Status_EA 0 "Aus" 1 "Init_oder_nicht_verbaut" 3 "Aktiv" 4 "Uebertreten" 5 "Abschaltung_laeuft" 6 "Reversibel_aus" 7 "Irreversibel_Aus" ; +VAL_ 346 TSK_vMax_Fahrerassistenz 511 "Init_ungueltig_keine_Beschraenkung" ; +VAL_ 346 TSK_Einheit_vMax_Fahrerassistenz 0 "kmh" 1 "mph" ; +VAL_ 346 TSK_Status_PLA 0 "Aus_Funktionsbereit" 1 "Init_oder_nicht_verbaut" 2 "aktivierbar" 3 "aktiv" 5 "Abschaltung_laeuft" 6 "reversibel_aus" 7 "Fehler" ; +VAL_ 346 TSK_aktives_System 0 "keine_Funktion_aktiv" 1 "GRA_ACC" 2 "ARA" 3 "Speedlimiter" 4 "IPA" 5 "PLA" 6 "PEA_Ausrollassistent" 7 "EA" ; +VAL_ 346 TSK_erhoehter_Fahrwiderstand 0 "kein_erhoehter_Fahrwiderstand" 1 "erhoehter_Fahrwiderstand" ; +VAL_ 346 TSK_Anf_Antriebsmoment 0 "keine_Anforderung" 1 "Anforderung_aktiv" ; +VAL_ 346 TSK_Status_ARA 0 "Aus" 1 "Init_oder_nicht_verbaut" 2 "aktivierbar" 3 "aktiv" 5 "abschaltung_laeuft" 6 "reversibel_aus" 7 "Fehler" ; +VAL_ 346 TSK_Status_IPA 0 "Aus_Funktionsbereit" 1 "Init_oder_nicht_verbaut" 2 "aktivierbar" 3 "aktiv" 5 "Abschaltung_laueft" 6 "reversibel_aus" 7 "Fehler" ; +VAL_ 798 TSK_Wunschgeschw 1022 "keine_Anzeige" 1023 "kein_Wert_im_Speicher" ; +VAL_ 798 TSK_Texte 0 "kein_Text" 1 "GRA_Modus_ausgewaehlt" 2 "ACC_Modus_ausgewaehlt" 3 "Lim_Modus_ausgewaehlt" 4 "Lim_nicht_verfuegbar_ESC_passiv" 5 "GRA_nicht_verfuegbar_ESC_passiv" 6 "Lim_nicht_verfuegbar_Charisma" 7 "GRA_nicht_verfuegbar_Charisma" 8 "Lim_nicht_verfuegbar_HDC" 9 "GRA_nicht_verfuegbar_HDC" ; +VAL_ 798 TSK_Akustik 0 "keine_Akustik" 1 "einzelner_Warnton" 2 "dauerhafter_Warnton" ; +VAL_ 798 TSK_Texte_Primaeranz 0 "keine_Anzeige" 1 "GRA_Symbol_passiv_xxx_kmh_mph" 2 "GRA_Symbol_aktiv_xxx_kmh_mph" 3 "Bremse_ueberhitzt" 4 "Limiter_Modus_aktiviert" 5 "GRA_Modus_aktiviert" 6 "ACC_Modus_aktiviert" 7 "Opt_Geschwindigkeitswarnung" 8 "Opt_und_akustische_GeschwWarnung" 9 "Opt_GeschwWarnung_dauerhaft_mit_einmal_Akustik" 10 "Limiter_passiv_mit_Akustik" 11 "Limiter_Fehler_mit_Akustik" 12 "Limiter_Symbol_passiv_xxx_kmh_mph" 13 "Limiter_Symbol_aktiv_xxx_kmh_mph" 14 "Popup_Geschw_zu_hoch__Resume_unzulaessig" ; +VAL_ 798 TSK_Limiter_Fahrerinfo 0 "keine_Info" 1 "Limit_erreicht" 2 "Ueberschritten" 3 "Vom_Fahrer_Ueberstimmt" ; +VAL_ 798 TSK_Limiter_Anzeige 0 "Display_Anzeige_GRA_ACC" 1 "Display_Anzeige_Limiter" ; +VAL_ 798 TSK_Fahrzeugstatus_GRA 0 "GRA_verfuegbar" 1 "GRA_nicht_verfuegbar" ; +VAL_ 798 TSK_Fahrzeugstatus_Limiter 0 "Limiter_verfuegbar" 1 "Limiter_nicht_verfuegbar" ; +VAL_ 798 MO_Motorlaufwarnung 0 "keine_Anzeige" 1 "Anforderung_Motorlaufwarnung" ; +VAL_ 798 TSK_Status_Anzeige 0 "Hauptschalter_aus" 1 "Init" 2 "passiv" 3 "aktiv" 4 "Uebertreten" 5 "Limitiierung_aktiv" 6 "reversibel_aus" 7 "irreversibel_aus" ; +VAL_ 780 ACC_Wunschgeschw_02 1023 "keine_Anzeige" ; +VAL_ 780 ACC_Status_Prim_Anz 0 "Symbol nicht beleuchtet" 1 "Farbe 1 (typisch 'gruen')" 2 "Farbe 2 (typisch 'rot')" 3 "Farbe 3 (typisch 'gelb')" ; +VAL_ 780 ACC_Abstandsindex 0 "Sonderanzeige_graue_Fahrbahn" 1022 "Sonderanzeige_graue_Fahrbahn" 1023 "Sonderanzeige_Fahrbahn_mit_gruenem_roten_Bereich" ; +VAL_ 780 ACC_Akustik_02 0 "keine_Akustik" 1 "hochpriore_Akustik" 2 "niederpriore_Akustik" 3 "hochpriore_Dauerakustik" ; +VAL_ 780 ACC_Warnung_Verkehrszeichen_1 0 "keine_Warnung_Initialwert" 1 "Warnung" ; +VAL_ 780 ACC_Gesetzte_Zeitluecke 0 "keine_Anzeige" 1 "Zeitluecke_1" 2 "Zeitluecke_2" 3 "Zeitluecke_3" 4 "Zeitluecke_4" 5 "Zeitluecke_5" 6 "nicht_definiert" 7 "nicht_definiert" ; +VAL_ 780 ACC_Optischer_Fahrerhinweis 0 "optischer_Fahrerhinweis_AUS" 1 "optischer_Fahrerhinweis_EIN" ; +VAL_ 780 ACC_Typ_Tachokranz 0 "Tachokranz_lang" 1 "Tachokranz_kurz" ; +VAL_ 780 ACC_Anzeige_Zeitluecke 0 "Anzeige_Zeitluecke_nicht_angefordert" 1 "Anzeige_Zeitluecke_angefordert" ; +VAL_ 780 ACC_Tachokranz 0 "Tachokranz_nicht_beleuchtet" 1 "Tachokranz_beleuchtet" ; +VAL_ 780 ACC_Display_Prio 0 "hoechste_Prio" 1 "mittlere_Prio" 2 "geringe_Prio" 3 "keine_Prio" ; +VAL_ 780 ACC_Relevantes_Objekt 0 "Symbol_nicht_beleuchtet" 1 "Farbe_1_typisch_gruen" 2 "Farbe_2_typisch_rot" 3 "Farbe_3_typisch_gelb" ; +VAL_ 780 ACC_Texte_Primaeranz 0 "keine Anzeige" 1 "ACC nicht verfuegbar !" 2 "Auto_Auto_ _ _" 3 "Auto_ _Auto_ _" 4 "Auto_ _ _Auto_" 5 "Auto_ _ _ _Auto" 6 "Auto_Auto_ _ _ Gong (durchgestrichen)" 7 "Auto_ _Auto_ _ Gong (durchgestrichen)" 8 "Auto_ _ _Auto_ Gong (durchgestrichen)" 9 "Auto_ _ _ _Auto Gong (durchgestrichen)" 10 "ACC bereit" 11 "keine Abstandsregelung" 12 "ACC Sensor Sicht !" 13 "ACC nicht verfuegbar" 14 "o o o" 15 "Hochschalten" 16 "ESP Eingriff" 17 "Herunterschalten" 18 "Parkbremse !" 19 "Geschwindigkeitsgrenze" 20 "Waehlhebelposition !" 21 "VDA ACC-Symbol YYY km/h / mph" 22 "Tempolimit XXX km/h / mph" 23 "Kurve XXX km/h / mph" 24 "ACC Abschaltung" 25 "Symbol 'Eieruhr'" 26 "!" 27 "--- km/h / mph" 28 "XXX km/h / mph (Schriftart 2)" 29 "Lenkradwinkel" 30 "Anfahren bestaetigen" 31 "Fahrzeug verloren" 32 "Im Stand nicht moeglich" 33 "Ungueltiger Anfahrbefehl" 34 "Tuer offen !" 35 "Fahrer Gurtschloss offen !" 36 "Schalthebelposition !" 37 "Drehzahl !" 38 "Kurvenassistent aus" 39 "Tempolimit aus" 40 "Abbiegeassistent" 41 "Ortsanfang XXX km/h / mph" 42 "Ortsende XXX km/h / mph" 43 "Tempolimit Ende XXX km/h / mph" 44 "HDC aktiv" 45 "braking guard Bremsruck" 46 "braking guard aus" 47 "braking guard aus" 48 "Uebernehmen !" 49 "Steigung zu gross" 50 "Stehendes Objekt voraus" 51 "SET / 'GRA Symbol'___xxx km/h / mph" 52 "SET / 'GRA Symbol' xxx km/h / mph" 53 "ACC aus" 54 "ACC startet" 55 "ACC reinigen" 56 "ACC Fehler" 57 "ACC haelt an !" 58 "Bremse betaetigen !" 59 "Kupplung betaetigt" 60 "LIM AUS" 61 "LIM AKTIV" 62 "LIM PASSIV" 63 "LIM FEHLER" 64 "Bremse ueberhitzt !" 65 "Bremse haelt !" 66 "ESP PASSIV !" 67 "ACC_anfahrbereit" 68 "Gang_einlegen" 69 "Rechtsueberholen_verhindert" 70 "Linksueberholen_verhindert" 71 "Achtung_Geschwindigkeitsueberschreitung" 72 "Tempolimit_und_Kurvenassistent_nicht_verfuegbar" ; +VAL_ 780 ACC_Wunschgeschw_erreicht 0 "Wunschgeschwindigkeit_nicht_erreicht" 1 "Wunschgeschwindigkeit_erreicht" ; +VAL_ 780 ACC_Typ_Tachokranz_unten 0 "LEDs_an" 1 "LEDs_aus" ; +VAL_ 780 ACC_Status_Anzeige 0 "ACC_GRA_Hauptschalter_aus" 1 "ACC_in_Init_nicht_bei_GRA" 2 "ACC_GRA_passiv" 3 "ACC_GRA_aktiv" 4 "ACC_GRA_im_Hintergrund_uebertreten" 5 "ACC_GRA_Abschaltreaktion" 6 "ACC_reversibel_aus_nicht_bei_GRA" 7 "ACC_GRA_irreversibel_aus" ; +VAL_ 804 ACC_Texte_Sekundaeranz 0 "keine_Anzeige" 1 "Zielfahrzeug_erkannt" 2 "Rechtskurve_voraus" 3 "Linkskurve_voraus" 4 "Tempolimit_voraus" 5 "Sensorsicht" 6 "Anfahrbereit" 7 "Tempolimit_erkannt" 8 "Kreuzung_voraus" 9 "Kreisverkehr_voraus" ; +VAL_ 804 ACC_Texte_Zusatzanz 0 "keine_Anzeige" 1 "ACC_AUS" 2 "ACC_BEREIT" 3 "UEBERTRETEN" 4 "ABSTAND" 5 "DISTANZ_1" 6 "DISTANZ_2" 7 "DISTANZ_3" 8 "DISTANZ_4" 9 "DISTANZ_1__dyn" 10 "DISTANZ_2__dyn" 11 "DISTANZ_3__dyn" 12 "DISTANZ_4__dyn" 13 "DISTANZ_1__stand" 14 "DISTANZ_2__stand" 15 "DISTANZ_3__stand" 16 "DISTANZ_4__stand" 17 "DISTANZ_1__comf" 18 "DISTANZ_2__comf" 19 "DISTANZ_3__comf" 20 "DISTANZ_4__comf" 21 "DISTANZ_1__efficiency" 22 "DISTANZ_2__efficiency" 23 "DISTANZ_3__efficiency" 24 "DISTANZ_4__efficiency" 25 "DISTANZ_5" 26 "DISTANZ_5__dyn" 27 "DISTANZ_5__stand" 28 "DISTANZ_5__comf" 29 "DISTANZ_5__efficiency" 30 "ACHTUNG" 31 "Abstandsanzeige" 32 "Abstandsanz_Warnung_aktiviert" ; +VAL_ 804 ACC_Status_Zusatzanz 0 "keine Anzeige" 1 "Bild 1 (Fzg. Silhouette, typ. farblos)" 2 "Bild 2 (Fzg. Farbe 1, typ. grau)" 3 "Bild 3 (Fzg. Farbe 2, typ. rot)" 4 "Bild 4 (Symbol 1 ACCplus, typ. Doppelfzg. gelb)" 5 "Bild 5 (Symbol 2 ACCplus, typ. Doppelfzg. grau)" 6 "Bild 6 (Fzg. Farbe 2, typ. rot) mit Priorität im Kombi (Pop-up)" ; +VAL_ 804 ACC_Texte 0 "keine_Anzeige" 1 "ACC_nicht_verfuegbar" 2 "ACC_und_AWV_nicht_verfuegbar" 3 "ACC_keine_Sensorsicht" 4 "ACC_und_AWV_keine_Sensorsicht" 5 "ACC_Steigung_zu_gross" 6 "ACC_nur_in_Fahrstufe_verfuegbar" 7 "ACC_Parkbremse_betaetigt" 8 "ACC_ESP_Eingriff" 9 "ACC_Bitte_uebernehmen" 10 "ACC_HDC_betaetigt" 11 "ACC_Geschwindigkeitsgrenze" 12 "ACC_Schalthebelposition" 13 "ACC_Drehzahl" 14 "ACC_Kupplung_betaetigt" 15 "ACC_Aktivierverhinderung" 16 "ACC_Abschaltung" 17 "ACC_Parkassistent_aktiv" 18 "ACC_ESC_aus" 19 "ACC_Charisma_Modus_inkompatibel" 20 "ACC_Stehendes_Objekt_voraus" 21 "ACA_Fahreruebernahme" 22 "ACA_Querfuehrung_nicht_verfuegbar" ; +VAL_ 804 ACC_Texte_braking_guard 0 "keine_Anzeige" 1 "AWV_aus" 2 "AWV_Warnung" 3 "AWV_Demomodus" 4 "AWV_Systemstoerung" 5 "AWV_Eingriff" 6 "AWV_Vorwarnung_aus" 7 "AWV_keine_Sensorsicht" ; +VAL_ 804 ACC_Warnhinweis 0 "kein_Warnhinweis" 1 "Warnhinweis" ; +VAL_ 804 ACC_Zeitluecke_Abstandswarner 61 "Freifahrt" 62 "nicht_definiert" 63 "keine_Anzeige" ; +VAL_ 804 ACC_Abstand_Abstandswarner 509 "Freifahrt" 510 "nicht_definiert" 511 "keine_Anzeige" ; +VAL_ 804 ACC_Tempolimit 0 "keine_Anzeige" 1 "5_zulHoechstgeschw" 2 "7_zulHoechstgeschw" 3 "10_zulHoechstgeschw" 4 "15_zulHoechstgeschw" 5 "20_zulHoechstgeschw" 6 "25_zulHoechstgeschw" 7 "30_zulHoechstgeschw" 8 "35_zulHoechstgeschw" 9 "40_zulHoechstgeschw" 10 "45_zulHoechstgeschw" 11 "50_zulHoechstgeschw" 12 "55_zulHoechstgeschw" 13 "60_zulHoechstgeschw" 14 "65_zulHoechstgeschw" 15 "70_zulHoechstgeschw" 16 "75_zulHoechstgeschw" 17 "80_zulHoechstgeschw" 18 "85_zulHoechstgeschw" 19 "90_zulHoechstgeschw" 20 "95_zulHoechstgeschw" 21 "100_zulHoechstgeschw" 22 "110_zulHoechstgeschw" 23 "120_zulHoechstgeschw" 24 "130_zulHoechstgeschw" 25 "140_zulHoechstgeschw" 26 "150_zulHoechstgeschw" 27 "160_zulHoechstgeschw" 28 "200_zulHoechstgeschw" 30 "250_zulHoechstgeschw" 31 "Ende_zulHoechstgeschw" ; +VAL_ 804 ACC_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15" ; +VAL_ 804 ACC_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch" ; +VAL_ 804 ACC_Texte_Abstandswarner 0 "keine_Anzeige" 1 "Systemstoerung" 2 "keine_Sensorsicht" 3 "zurzeit_eingeschraenkt" ; +VAL_ 290 ACC_limitierte_Anfahrdyn 0 "keine_Limitierung" 1 "Limitierung_Anfahrdynamik_angefordert" ; +VAL_ 290 ACC_nachtr_Stopp_Anf 0 "nicht_angefordert" 1 "angefordert" ; +VAL_ 290 ACC_StartStopp_Info 0 "Motorlauf_langfristig_nicht_notwendig_Stoppfreigabe" 1 "Motoranlauf_nicht_zwingend_notwendig_Stoppverbot_keine_Startanforderung" 2 "Motoranlauf_zwingend_notwendig_Startanforderung" 3 "Systemfehler" ; +VAL_ 290 ACC_Sollbeschleunigung_02 2046 "Neutralwert" 2047 "Fehler" ; +VAL_ 290 ACC_Anfahren 0 "keine_Anforderung_Anfahren" 1 "Anforderung_Anfahren" ; +VAL_ 290 ACC_Anhalten 0 "kein_Anhalten_gewuenscht" 1 "Anhalten_gewuenscht" ; +VAL_ 290 ACC_Typ 0 "Basis_ACC" 1 "ACC_mit_FollowToStop" 2 "ACC_mit_StopAndGo" 3 "ACC_nicht_codiert" ; +VAL_ 290 ACC_Status_ACC 0 "ACC_OFF_Hauptschalter_aus" 1 "ACC_INIT" 2 "ACC_STANDBY" 3 "ACC_AKTIV_regelt" 4 "ACC_OVERRIDE" 5 "ACC_Abschaltreaktion" 6 "reversibler_Fehler_im_ACC_System" 7 "irreversibler_Fehler_im_ACC_System" ; +VAL_ 290 ACC_Minimale_Bremsung 0 "Anforderung_Minimale_Bremsung_nicht_aktiv" 1 "Anforderung_Minimale_Bremsung_aktiv" ; +VAL_ 302 ACC_Anhalteweg 2046 "Neutralwert" 2047 "Fehler" ; +VAL_ 302 ACC_Anhalten 0 "kein_Anhalten_gewuenscht" 1 "Anhalten_gewuenscht" ; +VAL_ 302 ACC_Freilauf_Anf 0 "keine Freilauf-Anforderung" 1 "Freilauf-Anforderung" ; +VAL_ 302 ACC_Freilauf_Info 0 "Freilauf_freigegeben" 1 "kein_Uebergang_in_Freilauf_zulaessig" 2 "Freilauf_nicht_freigegeben" 3 "Freilauf_Anforderung" ; +VAL_ 302 ACC_Anforderung_HMS 0 "keine_Anforderung" 1 "halten" 2 "parken" 3 "halten_Standby" 4 "anfahren" 5 "Loesen_ueber_Rampe" ; +VAL_ 302 ACC_Anfahren 0 "keine_Anforderung_Anfahren" 1 "Anforderung_Anfahren" ; +VAL_ 302 ACC_Folgebeschl 254 "Neutralwert" ; +VAL_ 302 ACC_Sollbeschleunigung_02 2046 "Neutralwert" 2047 "Fehler" ; +VAL_ 279 AWV1_Anf_Prefill 0 "Prefill_nicht_aktivieren" 1 "Prefill_aktivieren" ; +VAL_ 279 ANB_CM_Info 0 "Standard" 1 "Erweitert" ; +VAL_ 279 AWV2_Freigabe 0 "keine_Freigabe" 1 "Freigabe" ; +VAL_ 279 AWV1_HBA_Param 0 "Defaultparametersatz" 1 "Parametersatz_mit_leicht_erhoehter_Empfindlichkeit" 2 "Parametersatz_mit_erhoehter_Empfindlichkeit" 3 "Parametersatz_mit_hoechster_Empfindlichkeit" ; +VAL_ 279 AWV2_Priowarnung 0 "Anzeige_Verlassen_der_Fahrspur_wird_nicht_unterdrueckt" 1 "Anzeige_Verlassen_der_Fahrspur_wird_unterdrueckt" ; +VAL_ 279 ANB_CM_Anforderung 0 "keine_Anforderung" 1 "Anforderung_aktiv" ; +VAL_ 279 ANB_Info_Teilbremsung 0 "Auspraegung_Standard" 1 "Auspraegung_Erweitert" ; +VAL_ 279 ANB_Notfallblinken 0 "kein_ANB_Notfallblinken" 1 "Notfallblinken_ANB_angefordert" ; +VAL_ 279 ANB_Teilbremsung_Freigabe 0 "Teilbremsung_nicht_freigegeben" 1 "Teilbremsung_freigegeben" ; +VAL_ 279 ANB_Zielbremsung_Freigabe 0 "Zielbremsung_nicht_freigegeben" 1 "Zielbremsung_freigegeben" ; +VAL_ 279 AWV_Vorstufe 0 "keine_Notbremsung_erwartet" 1 "Notbremsung_in_Kuerze" ; +VAL_ 279 AWV_Halten 0 "keine_Anforderung" 1 "Anforderung_das_Fzg_im_Stillstand_zu_halten" ; +VAL_ 279 AWV_CityANB_Auspraegung 0 "autom_Bremsung_im_ges_vBereich" 1 "autom_Bremsung_im_def_vBereich" ; +VAL_ 279 PCF_Freigabe 0 "keine_Freigabe_PreCrashFront" 1 "Freigabe_PreCrashFront" ; +VAL_ 279 AWV1_ECD_Anlauf 0 "ECD_Anlauf_nicht_aktivieren" 1 "ECD_Anlauf_aktivieren" ; +VAL_ 279 PCF_Time_to_collision 255 "Objektstatus=0x0__oder_berechneter_TTC_Wert_groesser_als_Maximalwert" ; +VAL_ 679 ACC_Regelgeschw 1023 "keine_Anzeige" ; +VAL_ 679 ACC_Einheit_maxSetzgeschw 0 "kmh" 1 "mph" ; +VAL_ 679 ACC_maxSetzgeschw 511 "Init_Neutralwert" ; +VAL_ 679 ACC_minRegelgeschw 255 "keine_Anzeige" ; +VAL_ 679 ACC_maxRegelgeschw 255 "keine_Anzeige" ; +VAL_ 679 ACC_Tempolimitassistent 0 "keine_Anzeige" 1 "Tempolimitassistent_aktiv" 2 "Tempolimitassistent_nicht_verfuegbar" 3 "Tempolimitassistent_Fahreruebernahme" ; +VAL_ 679 ACC_Kurvenassistent 0 "keine_Anzeige" 1 "Kreuzung" 2 "Rechtskurve" 3 "Linkskurve" 4 "Kreisverkehr" ; +VAL_ 679 ACC_RUV 0 "keine_Anzeige" 1 "RUV_aktiv_Rechtsverkehr" 2 "RUV_aktiv_Linksverkehr" ; +VAL_ 679 ACC_Tachokranz 0 "Tachokranz_nicht_beleuchtet" 1 "Tachokranz_beleuchtet" ; +VAL_ 679 ACC_Typ_Tachokranz_unten 0 "LEDs_an" 1 "LEDs_aus" ; +VAL_ 679 ACC_ENG_Texte 0 "keine_Anzeige" 1 "keine_Laenderverfuegbarkeit" 2 "nicht_verfuegbar" 3 "Geschwindigkeitsgrenze" ; +VAL_ 679 ACC_ADAPTIVE 1 "adaptive" 2 "non-adaptive" ; +VAL_ 681 AWV_Warnung 0 "keine_Anzeige" 1 "latente_Vorwarnung" 2 "Vorwarnung" 3 "Akutwarnung" 4 "Eingriff" 5 "Fahreruebernahmeaufforderung" 6 "Abbiegewarnung" ; +VAL_ 681 AWV_Texte 0 "keine_Anzeige" 1 "Systemstoerung" 2 "keine_Sensorsicht" 3 "Demomodus" 4 "System_aus" 5 "nicht_definiert" 6 "ESC_aus" 7 "zurzeit_eingeschraenkt" ; +VAL_ 681 AWV_Status_Anzeige 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" ; +VAL_ 681 AWV_Einstellung_System_FSG 0 "deaktiviert" 1 "aktiviert" ; +VAL_ 681 AWV_Einstellung_Warnung_FSG 0 "Aus" 1 "Setting_2" 2 "Setting_3" 3 "Setting_4" 4 "Setting_5" 5 "Ein" ; +VAL_ 681 AWV_Warnlevel 0 "keine_Gefaehrdung" 63 "max_Gefaehrdung" ; +VAL_ 391 MO_Waehlpos 2 "P" 3 "R" 4 "N" 5 "D" 6 "D" ; +VAL_ 391 EV_Rekuperationsstufe 0 "default" 1 "B1" 2 "B2" 3 "B3" ; +VAL_ 870 Fast_Send_Rate_Active 0 "1 Hz" 1 "50 Hz" ; +VAL_ 988 EPB_Status 0 "offen" 1 "geschlossen_Parken" 2 "teilgespannt_Halten" 3 "im_Lauf_oeffnen" 4 "im_Lauf_schliessen" 5 "tbd" 6 "Init" 7 "unbekannt"; +VAL_ 988 GE_Fahrstufe 0 "Zwischenstellung" 1 "Init" 5 "P" 6 "R" 7 "N" 8 "D" 9 "D" 10 "E" 13 "T" 14 "T" 15 "Fehler"; +VAL_ 1720 KBI_Variante_USA 0 "keine USA-Variante" 1 "USA-Variante" ; +VAL_ 1720 KBI_Variante 0 "Zeiger Kombiinstrument" 1 "Volldisplay Kombiinstrument" ; +VAL_ 1720 KBI_BCmE_aktiv 0 "Anzeige_nicht_aktiv" 1 "Anzeige_aktiv" ; +VAL_ 1720 KBI_Sparhinweis_quittiert 0 "nicht_quittiert" 1 "quittiert" ; +VAL_ 1720 KBI_Tankfuellstand_Prozent 126 "Init" 127 "Fehler" ; +VAL_ 1720 KBI_Nachtanken_erkannt 0 "Geberbetrieb" 1 "Nachtankmodus" ; +VAL_ 1720 KBI_Tankinhalt_hochaufl 16382 "Init" 16383 "Fehler" ; +VAL_ 1720 KBI_Max_Tankinhalt 254 "Init" 255 "Fehler" ; diff --git a/opendbc_repo/opendbc/dbc/vw_mqbevo.dbc b/opendbc_repo/opendbc/dbc/vw_mqbevo.dbc new file mode 100644 index 0000000000..91be4a2465 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/vw_mqbevo.dbc @@ -0,0 +1,1612 @@ +BO_ 64 Airbag_01: 8 Airbag_MQB + SG_ Airbag_01_CRC : 0|8@1+ (1,0) [0|255] "" BMS_MQB,Gateway_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Airbag_01_BZ : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Gateway_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AB_RGS_Anst : 12|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ AB_Front_Crash : 16|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Heck_Crash : 17|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_SF_Crash : 18|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_SB_Crash : 19|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Rollover_Crash : 20|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Crash_Int : 21|3@1+ (1,0) [0|7] "" BMS_MQB,Gateway_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AB_Lampe : 24|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Deaktiviert : 25|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_VB_deaktiviert : 26|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Systemfehler : 27|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ AB_Diagnose : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Stellgliedtest : 29|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AB_Erh_Auf_VB : 30|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtwarn_VF : 32|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Gurtwarn_VB : 33|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Anzeige_Fussg : 34|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Texte_AKS : 36|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_PAO_Leuchte_Anf : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_MKB_gueltig : 39|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_MKB_Anforderung : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ AB_Versorgungsspannung : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 65 Airbag_03: 8 Airbag_MQB + SG_ Airbag_03_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ Airbag_03_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ AB_MKB_Safing : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 134 LWI_01: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_Sensorstatus : 12|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_QBit_Sub_Daten : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LWI_QBit_Lenkradwinkel : 15|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_Lenkradwinkel : 16|13@1+ (0.1,0) [0|800] "Unit_DegreOfArc" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_VZ_Lenkradwinkel : 29|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LWI_VZ_Lenkradw_Geschw : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LWI_Lenkradw_Geschw : 31|9@1+ (5,0) [0|2500] "Unit_DegreOfArcPerSecon" Vector__XXX + SG_ LWI_Sub_Daten : 40|16@1+ (1,0) [0|65535] "" Vector__XXX + +BO_ 157 Motor_Hybrid_01: 8 Motor_Hybrid_MQB + SG_ Motor_Hybrid_01_CRC : 0|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB + SG_ Motor_Hybrid_01_BZ : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_IstStatusK0 : 12|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_max_ind_VM_Mom : 16|10@1+ (1,0) [0|1021] "Unit_NewtoMeter" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Zielzustand : 26|3@1+ (1,0) [0|7] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Startmodus : 29|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ MO_HYB_Startmodus_PQ3x : 32|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Stoppmodus : 33|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_VM_Mom_oE : 40|10@1+ (1,-100) [-100|922] "Unit_NewtoMeter" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_VM_aktiv : 50|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Schaltverhinderung : 51|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + +BO_ 158 Getriebe_Hybrid_01: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_Hybrid_01_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Hybrid_MQB + SG_ Getriebe_Hybrid_01_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB + SG_ GE_HYB_Fehlerstatus : 12|2@1+ (1,0) [0|3] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freigabe_K0 : 16|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freigabe_LL_Reg : 17|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freig_sSchl_K0 : 18|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Freig_VM_EM_Stop : 19|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Wiederstart : 20|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_Filt_MomAufbau : 21|3@1+ (1,0) [0|7] "" Motor_Hybrid_MQB + SG_ GE_HYB_nK0 : 24|8@1+ (25,0) [0|6350] "Unit_MinutInver" Vector__XXX + SG_ GE_HYB_MomEingriff_EM : 32|6@1+ (0.5,0) [0|31.5] "Unit_NewtoMeter" LEH_MQB + SG_ GE_HYB_VZ_MomEingriff_EM : 38|1@1+ (1,0) [0|1] "" LEH_MQB + SG_ GE_HYB_Sportfaktor : 56|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB + SG_ GE_HYB_VM_akt_halten : 61|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_StartAnf : 62|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + SG_ GE_HYB_VM_Startkontr : 63|1@1+ (1,0) [0|1] "" Motor_Hybrid_MQB + +BO_ 159 LH_EPS_03: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_DSR_Status : 12|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_Berechneter_LW : 16|12@1+ (0.15,0) [0|613.95] "Unit_DegreOfArc" XXX + SG_ EPS_BLW_QBit : 30|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_VZ_BLW : 31|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_HCA_Status : 32|4@1+ (1,0) [0|15] "" XXX + SG_ EPS_Lenkmoment : 40|10@1+ (1,0) [0|8] "Unit_centiNewtoMeter" XXX + SG_ EPS_Lenkmoment_QBit : 54|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_VZ_Lenkmoment : 55|1@1+ (1,0) [0|1] "" XXX + SG_ EPS_Lenkungstyp : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 167 Motor_11: 8 Motor_Diesel_MQB + SG_ Motor_11_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ Motor_11_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Soll_Roh : 12|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Ist_Summe : 22|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,SAK_MQB + SG_ MO_Mom_Traegheit_Summe : 32|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Soll_gefiltert : 42|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Schub : 52|9@1+ (1,-509) [-509|0] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Status_Normalbetrieb_01 : 61|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_erste_Ungenauschwelle : 62|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_QBit_Motormomente : 63|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 168 Motor_12: 8 Motor_Diesel_MQB + SG_ Motor_12_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ Motor_12_BZ : 8|4@1+ (1,0) [0|15] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Mom_neg_verfuegbar : 12|9@1+ (1,-509) [-509|0] "Unit_NewtoMeter" Gateway_MQB + SG_ MO_Mom_Begr_stat : 21|9@1+ (1,0) [0|509] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Begr_dyn : 30|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB + SG_ MO_Momentenintegral_02 : 40|7@1+ (1,0) [0|100] "Unit_PerCent" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Drehzahl_01 : 47|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Drehzahl_01 : 48|16@1+ (0.25,0) [0|16383] "Unit_MinutInver" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,SAK_MQB + +BO_ 173 Getriebe_11: 8 Getriebe_DQ_Hybrid_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTERXX : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_MMom_Soll_02 : 12|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_MMom_Vorhalt_02 : 22|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Uefkt : 32|10@1+ (0.1,0) [0|102.2] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Fahrstufe : 42|5@1+ (1,0) [0|31] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Schaltvorgang : 47|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Status_Kupplung : 54|2@1+ (1,0) [0|3] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_MMom_Status : 56|2@1+ (1,0) [0|3] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freig_MMom_Vorhalt : 58|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Verbot_Ausblendung : 59|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Zielgang : 60|4@1+ (1,0) [0|15] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 174 Getriebe_12: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_12_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Getriebe_12_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Drehzahlmesser_Daempfung : 12|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Schubabschalt_Unt : 13|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freigabe_Synchro : 14|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Synchro_Wunschdrehz : 15|9@1+ (25,0) [0|12750] "Unit_MinutInver" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Synchro_Zeit : 24|8@1+ (20,0) [0|5080] "Unit_MilliSecon" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Mom_Begr_Gradient : 32|8@1+ (10,0) [0|2540] "Unit_NewtoMeterPerSecon" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Anheb_Solldrehz_Leerlauf : 40|8@1+ (10,0) [0|2540] "Unit_MinutInver" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Aufnahmemoment : 48|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Anf_Zylabsch : 58|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ GE_HYB_DZ_Eingriff : 62|2@1+ (1,0) [0|3] "" Motor_Hybrid_MQB + +BO_ 175 Waehlhebel_03: 4 Waehlhebel_MQB + SG_ WH_Status_Sperre : 0|3@1+ (1,0) [0|7] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Initialisierung : 3|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_SensorPos_roh : 4|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_03_BZ : 8|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_SensorPos_roh_inv : 12|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Testergebnis : 16|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Test_Aktiv : 24|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WH_Status : 25|7@1+ (1,0) [0|127] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 178 ESP_19: 8 Gateway_MQB + SG_ ESP_HL_Radgeschw_02 : 0|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HR_Radgeschw_02 : 16|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VL_Radgeschw_02 : 32|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VR_Radgeschw_02 : 48|16@1+ (0.0075,0) [0|491.49] "Unit_KiloMeterPerHour" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 252 ESP_NEW_1: 48 XXX + SG_ XCHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ WHEEL_SPEED_RL : 64|16@1+ (0.0075,0) [0|65535] "" XXX + SG_ WHEEL_SPEED_RR : 80|16@1+ (0.0075,0) [0|65535] "" XXX + SG_ WHEEL_SPEED_FL : 96|16@1+ (0.0075,0) [0|65535] "" XXX + SG_ WHEEL_SPEED_FR : 112|16@1+ (0.0075,0) [0|65535] "" XXX + +BO_ 253 ESP_21: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BR_Eingriffsmoment : 12|10@1+ (1,-509) [-509|509] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_v_Signal : 32|16@1+ (0.01,0) [0|655.32] "Unit_KiloMeterPerHour" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ ASR_Tastung_passiv : 48|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Tastung_passiv : 49|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Systemstatus : 50|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ASR_Schalteingriff : 51|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_Haltebestaetigung : 53|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_v_Signal : 55|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ABS_Bremsung : 56|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ASR_Anf : 57|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ MSR_Anf : 58|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EBV_Eingriff : 59|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EDS_Eingriff : 60|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Eingriff : 61|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_ASP : 62|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Anhaltevorgang_ACC_aktiv : 63|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 257 ESP_02: 8 Gateway_MQB + SG_ ESP_02_CRC : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_02_BZ : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Gierrate : 12|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_QBit_Laengsbeschl : 13|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Querb : 14|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Stillstandsflag : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Querbeschleunigung : 16|8@1+ (0.01,-1.27) [-1.27|1.27] "Unit_ForceOfGravi" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Laengsbeschl : 24|10@1+ (0.03125,-16) [-16|15.90625] "Unit_MeterPerSeconSquar" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Verteil_Wankmom : 34|5@1+ (0.1,-1) [-1|1] "" Vector__XXX + SG_ ESP_QBit_Anf_Vert_Wank : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Gierrate : 40|14@1+ (0.01,0) [0|163.82] "Unit_DegreOfArcPerSecon" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_VZ_Gierrate : 54|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_Notbremsanzeige : 55|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESP_SpannungsAnf : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_PLA_Abbruch : 57|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ ESP_Status_ESP_PLA : 60|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 258 ESP_NEW_2: 48 XXX + SG_ LATERAL_ACCEL : 16|8@1+ (1,0) [0|255] "" XXX + SG_ LONGITUDINAL_ACCEL : 24|8@1- (1,0) [0|255] "" XXX + SG_ YAW_RATE : 40|14@1+ (1,0) [0|16383] "" XXX + SG_ YAW_RATE_SIGN : 54|1@1+ (1,0) [0|1] "" XXX + +BO_ 260 EPB_01: 8 Gateway_MQB + SG_ EPB_01_CRC : 0|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_01_BZ : 8|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_QBit_Laengsbeschleunigung : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_QBit_Pedalweg_Kuppl : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_BCM2_Motor_Wakeup : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_Freig_Verzoeg_Anf : 15|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_Verzoeg_Anf : 16|8@1+ (0.048,-7.968) [-7.968|4.224] "Unit_MeterPerSeconSquar" Vector__XXX + SG_ EPB_Laengsbeschleunigung : 24|8@1+ (1,-128) [-128|126] "Unit_PerCentOfForceOfGravi" Vector__XXX + SG_ EPB_Pedalweg_Kuppl : 32|8@1+ (0.4,0) [8|92] "Unit_PerCent" Vector__XXX + SG_ EPB_Anfahrwunsch_erkannt : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_DAA_Randbed_erf : 49|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ EPB_Fehlerstatus : 50|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EPB_Schalterposition : 52|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_QBit_Schalterpos : 54|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ EPB_Konsistenz_ACC : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EPB_Spannkraft : 56|5@1+ (1,0) [0|29] "Unit_KiloNewto" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ EPB_Status : 61|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 262 ESP_05: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Bremsdruck : 12|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Fahrer_bremst : 13|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Schwelle_Unterdruck : 14|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Bremsdruck : 16|10@1+ (0.3,-30) [-30|276.6] "Unit_Bar" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Fahrer_bremst : 26|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Verz_TSK_aktiv : 27|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Lenkeingriff_ADS : 28|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Konsistenz_TSK : 29|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Bremsruck_AWV2 : 30|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Konsistenz_AWV2 : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ECD_Fehler : 32|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ECD_nicht_verfuegbar : 33|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Status_Bremsentemp : 34|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Autohold_Standby : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_HDC_Standby : 36|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_HBA_aktiv : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Prefill_ausgeloest : 38|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Rueckwaertsfahrt_erkannt : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Status_Anfahrhilfe : 40|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HDC_aktiv : 41|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_StartStopp_Info : 42|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ESP_Eingr_HL : 44|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingr_HR : 45|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingr_VL : 46|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Eingr_VR : 47|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_BKV_Unterdruck : 48|8@1+ (4,0) [0|1012] "Unit_MilliBar" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Autohold_aktiv : 56|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_FStatus_Anfahrhilfe : 57|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_Verz_EPB_aktiv : 58|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ECD_Bremslicht : 59|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Verzoeg_EPB_verf : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Status_Bremsdruck : 61|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Anforderung_EPB : 62|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 263 Motor_04: 8 Motor_Diesel_MQB + SG_ MO_Istgang : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Sollgang : 12|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Oeldruck : 16|8@1+ (0.04,0) [0|10] "Unit_Bar" Gateway_MQB + SG_ MO_Anzeigedrehz : 24|12@1+ (3,0) [0|12282] "Unit_MinutInver" Gateway_MQB + SG_ MO_Schaltempf_verfbar : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Ladedruck : 39|9@1+ (0.01,0) [0|5.1] "Unit_Bar" Gateway_MQB + SG_ MO_KVS : 48|15@1+ (1,0) [0|32767] "Unit_MicroLiter" Gateway_MQB + SG_ MO_KVS_Ueberlauf : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 264 Fahrwerk_01: 8 XXX + SG_ Fahrwerk_01_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ Fahrwerk_01_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 267 MOTOR_NEW_1: 32 XXX + SG_ XCHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACCEL_PEDAL : 12|8@1+ (0.4,0) [0|255] "" XXX + SG_ TSK_STATUS : 88|3@1+ (1,0) [0|7] "" XXX + +BO_ 278 ESP_10: 8 Gateway_MQB + SG_ ESP_10_CRC : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_10_BZ : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_VL : 12|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_VR : 13|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_HL : 14|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_QBit_Wegimpuls_HR : 15|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_VL : 16|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_VR : 26|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_HL : 36|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Wegimpuls_HR : 46|10@1+ (1,0) [0|1000] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VL_Fahrtrichtung : 56|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_VR_Fahrtrichtung : 58|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HL_Fahrtrichtung : 60|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_HR_Fahrtrichtung : 62|2@1+ (1,0) [0|3] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 279 ACC_10: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ AWV1_Anf_Prefill : 16|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_CM_Info : 17|1@1+ (1,0) [0|1] "" XXX + SG_ AWV2_Freigabe : 18|1@1+ (1,0) [0|1] "" XXX + SG_ AWV1_HBA_Param : 19|2@1+ (1,0) [0|3] "" XXX + SG_ AWV2_Ruckprofil : 21|3@1+ (1,0) [0|7] "" XXX + SG_ AWV2_Priowarnung : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_CM_Anforderung : 25|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Info_Teilbremsung : 26|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Notfallblinken : 27|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Teilbremsung_Freigabe : 28|1@1+ (1,0) [0|1] "" XXX + SG_ ANB_Zielbrems_Teilbrems_Verz_Anf : 29|10@1+ (0.024,-20.016) [-20.016|4.536] "Unit_MeterPerSeconSquar" XXX + SG_ ANB_Zielbremsung_Freigabe : 39|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_Vorstufe : 40|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_Halten : 41|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_CityANB_Auspraegung : 42|1@1+ (1,0) [0|1] "" XXX + SG_ PCF_Freigabe : 43|1@1+ (1,0) [0|1] "" XXX + SG_ AWV1_ECD_Anlauf : 44|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_AWA_VZ_Anf_Lenkmomoffset : 46|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_AWA_Anf_Lenkmomoffset : 47|9@1+ (0.01,0) [0|5.11] "Unit_NewtoMeter" XXX + SG_ PCF_Time_to_collision : 56|8@1+ (0.01,0) [0|2.5] "Unit_Secon" XXX + +BO_ 286 VehicleSpeed: 8 XXX + SG_ VehicleSpeed_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ VehicleSpeed_BZ : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Speed : 52|12@1+ (0.125,0) [0|1] "" XXX + +BO_ 288 TSK_06: 8 Motor_Diesel_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Radbremsmom : 12|12@1+ (8,0) [0|32760] "Unit_NewtoMeter" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Status : 24|3@1+ (1,0) [0|7] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_v_Begrenzung_aktiv : 27|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Standby_Anf_ESP : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_Freig_Verzoeg_Anf : 30|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Limiter_ausgewaehlt : 31|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_ax_Getriebe_02 : 48|9@1+ (0.024,-2.016) [-2.016|10.224] "Unit_MeterPerSeconSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Zwangszusch_ESP : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_zul_Regelabw : 58|6@1+ (0.024,0) [0|1.512] "Unit_MeterPerSeconSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 289 Motor_20: 8 Motor_Diesel_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|255] "" XXX + SG_ MO_Fahrpedalrohwert_01 : 12|8@1+ (0.4,0) [0|101.6] "Unit_PerCent" Airbag_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Fahrpedalwerte_01 : 20|1@1+ (1,0) [0|1] "" Airbag_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Fahrpedalgradient : 21|8@1+ (25,0) [0|6350] "Unit_PerCentPerSecon" Airbag_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Sig_Fahrpedalgradient : 29|1@1+ (1,0) [0|1] "" Airbag_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_rel_Saugrohrdruck : 30|6@1+ (18,0) [0|1116] "Unit_MilliBar" Gateway_MQB + SG_ MO_rel_Saugrohrdruck_gem_err : 36|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Moment_im_Leerlauf : 37|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Schubabschaltung : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Solldrehz_Leerlauf : 40|8@1+ (10,0) [0|2540] "Unit_MinutInver" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 290 ACC_06: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_limitierte_Anfahrdyn : 12|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_nachtr_Stopp_Anf : 13|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_DynErhoehung : 14|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Freilaufstrategie_TSK : 15|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_zul_Regelabw_unten : 16|6@1+ (0.024,0) [0|1.512] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_StartStopp_Info : 22|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Sollbeschleunigung_02 : 24|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_zul_Regelabw_oben : 35|5@1+ (0.0625,0) [0|1.9375] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_neg_Sollbeschl_Grad_02 : 40|8@1+ (0.05,0) [0|12.75] "Unit_MeterPerCubicSecon" XXX + SG_ ACC_pos_Sollbeschl_Grad_02 : 48|8@1+ (0.05,0) [0|12.75] "Unit_MeterPerCubicSecon" XXX + SG_ ACC_Anfahren : 56|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Anhalten : 57|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ : 58|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Status_ACC : 60|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Minimale_Bremsung : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 294 HCA_01: 8 Frontsensorik + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HCA_01_Vib_Freq : 12|4@1+ (1,15) [15|30] "Unit_Hertz" Vector__XXX + SG_ HCA_01_LM_Offset : 16|9@1+ (1,0) [0|511] "Unit_centiNewtoMeter" Vector__XXX + SG_ EA_ACC_Sollstatus : 25|2@1+ (1,0) [0|3] "" Frontradar + SG_ EA_Ruckprofil : 27|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ HCA_01_Sendestatus : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_LM_OffSign : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ HCA_01_Status_HCA : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ HCA_01_Vib_Amp : 36|4@1+ (0.2,0) [0|3] "Unit_NewtoMeter" Vector__XXX + SG_ EA_Ruckfreigabe : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EA_ACC_Wunschgeschwindigkeit : 41|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" Frontradar + +BO_ 296 Getriebe_06: 3 Getriebe_DQ_Hybrid_MQB + SG_ GE_WH_Sperre : 0|1@1+ (1,0) [0|1] "" Waehlhebel_MQB + SG_ GE_Ausleuchtungsmode : 1|1@1+ (1,0) [0|1] "" Waehlhebel_MQB + SG_ GE_Test_Freigabe : 2|1@1+ (1,0) [0|1] "" Waehlhebel_MQB + SG_ GE_Ist_Fahrstufe : 4|4@1+ (1,0) [0|15] "" Waehlhebel_MQB + SG_ GE_Testparameter_1 : 8|8@1+ (1,0) [0|255] "" Waehlhebel_MQB + SG_ GE_Testparameter_2 : 16|8@1+ (1,0) [0|255] "" Waehlhebel_MQB + +BO_ 299 GRA_ACC_01: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Hauptschalter : 12|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Abbrechen : 13|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Typ_Hauptschalter : 14|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Limiter : 15|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Setzen : 16|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Hoch : 17|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Runter : 18|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Wiederaufnahme : 19|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Verstellung_Zeitluecke : 20|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Codierung : 22|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Fehler : 24|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Typ468 : 25|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_Tip_Stufe_2 : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GRA_ButtonTypeInfo : 28|2@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ MAYBE_TRAVEL_ASSIST : 30|1@1+ (1,0) [0|1] "" XXX + +BO_ 301 Getriebe_13: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_13_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Getriebe_13_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_StartStopp_Info : 12|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ GE_Langfr_Schutzmom_02 : 14|9@1+ (1,0) [0|509] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Eingangsdrehz : 48|14@1+ (1,0) [0|16381] "Unit_MinutInver" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Notlauf : 62|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freig_Langfr_Schutzmom : 63|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 302 ACC_07: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Anhalteweg : 12|11@1+ (0.01,0) [0|20.45] "Unit_Meter" XXX + SG_ ACC_Anhalten : 23|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Boost_Anf : 24|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Freilauf_Anf : 25|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Freilauf_Info : 26|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Anforderung_HMS : 28|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Anfahren : 31|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Folgebeschl : 32|8@1+ (0.03,-4.6) [-4.6|2.99] "Unit_MeterPerSeconSquar" XXX + SG_ ACC_Sollbeschleunigung_02 : 53|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" XXX + +BO_ 313 ESP_NEW_3: 32 XXX + SG_ XCHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ BRAKE_PRESSED_1 : 16|1@1+ (1,0) [0|1] "" XXX + SG_ BRAKE_PRESSED_2 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ BRAKE_PRESSED_3 : 48|1@1+ (1,0) [0|1] "" XXX + SG_ BRAKE_PRESSURE : 76|10@1+ (1,0) [0|1023] "" XXX + +BO_ 317 MOTOR_NEW_2: 32 XXX + SG_ XCHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ NEW_SIGNAL_1 : 36|1@1+ (1,0) [0|1] "" XXX + SG_ UNKNOWN : 76|10@1+ (1,0) [0|1023] "" XXX + +BO_ 333 ACC_NEW_1: 32 XXX + SG_ NEW_SIGNAL_1 : 24|12@1+ (1,0) [0|4095] "" XXX + SG_ NEW_SIGNAL_2 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ NEW_SIGNAL_3 : 248|8@1+ (1,0) [0|255] "" XXX + +BO_ 387 CAMERA_NEW_3_HF: 64 XXX + SG_ NEW_SIGNAL_1 : 28|12@1+ (1,0) [0|15] "" XXX + +BO_ 391 EV_Gearshift: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ RegenBrakingMode : 12|2@1+ (1,0) [0|3] "" XXX + SG_ GearPosition : 16|4@1+ (1,0) [0|255] "" XXX + +BO_ 418 ESP_15: 8 XXX + SG_ ESP_15_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ ESP_15_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 420 CAMERA_NEW_11: 8 XXX + +BO_ 427 ESP_33: 8 XXX + SG_ ESP_33_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ ESP_33_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 496 CAMERA_NEW_10: 8 XXX + +BO_ 519 CAMERA_NEW_1_HF: 64 XXX + SG_ NEW_SIGNAL_2 : 36|11@1+ (1,0) [0|2047] "" XXX + SG_ NEW_SIGNAL_1 : 48|12@1+ (1,0) [0|4095] "" XXX + +BO_ 564 CAMERA_NEW_2_HF: 64 XXX + +BO_ 589 NEW_MSG_24D: 64 XXX + SG_ NEW_SIGNAL_1 : 24|12@1+ (1,0) [0|4095] "" XXX + +BO_ 619 CAMERA_NEW_5: 8 XXX + +BO_ 679 ACC_13: 8 XXX + SG_ ACC_Regelgeschw : 12|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" XXX + SG_ ACC_Einheit_maxSetzgeschw : 22|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_maxSetzgeschw : 23|9@1+ (1,0) [0|510] "" XXX + SG_ ACC_minRegelgeschw : 32|8@1+ (0.32,0) [0|81.28] "Unit_KiloMeterPerHour" XXX + SG_ ACC_maxRegelgeschw : 40|8@1+ (0.32,0) [0|81.28] "Unit_KiloMeterPerHour" XXX + SG_ ACC_Tempolimitassistent : 48|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Kurvenassistent : 52|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_RUV : 56|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Tachokranz : 58|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ_Tachokranz_unten : 59|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_ENG_Texte : 60|2@1+ (1,0) [0|3] "" XXX + +BO_ 681 ACC_15: 8 XXX + SG_ AWV_Warnung : 16|3@1+ (1,0) [0|7] "" XXX + SG_ AWV_Texte : 24|3@1+ (1,0) [0|7] "" XXX + SG_ AWV_Status_Anzeige : 32|2@1+ (1,0) [0|3] "" XXX + SG_ AWV_Einstellung_System_FSG : 34|1@1+ (1,0) [0|1] "" XXX + SG_ AWV_Einstellung_Warnung_FSG : 36|3@1+ (1,0) [0|7] "" XXX + SG_ AWV_Warnlevel : 58|6@1+ (1,0) [0|63] "" XXX + +BO_ 695 RCTA_01: 8 XXX + SG_ RCTA_01_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ RCTA_01_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 768 ACC_NEW_2: 48 XXX + SG_ SET_SPEED : 76|10@1+ (0.32,0) [0|163.51] "kmh" XXX + SG_ NEW_SIGNAL_2 : 86|10@1+ (1,0) [0|1023] "" XXX + SG_ NEW_SIGNAL_3 : 96|8@1+ (1,0) [0|255] "" XXX + +BO_ 771 HCA_NEW: 24 XXX + SG_ ENABLED_1 : 13|2@1+ (1,0) [0|3] "" XXX + SG_ SET_ME_0X54 : 16|7@1+ (1,0) [0|127] "" XXX + SG_ ASSIST_TORQUE : 24|10@1+ (1,0) [0|1023] "" XXX + SG_ ASSIST_DIRECTION : 39|1@1+ (1,0) [0|1] "" XXX + SG_ ENABLED_2 : 66|1@1+ (1,0) [0|1] "" XXX + +BO_ 779 Kombi_01: 8 Gateway_MQB + SG_ KBI_ABS_Lampe : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_ESP_Lampe : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_BKL_Lampe : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Airbag_Lampe : 3|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ KBI_SILA_gueltig : 4|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ KBI_Lenkung_Lampe : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Vorglueh_System_Lampe : 6|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB + SG_ KBI_NV_in_Anzeige : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Kombi_01_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Anzeigestatus_ACC : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigestatus_GRA : 13|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Oeldruck_Schalter : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Tankwarnung : 16|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_MFA_v_Einheit_01 : 17|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_im_Stellgliedtest : 18|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ KBI_Anzeigefehler_LDW : 19|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Variante_USA : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Oeldruckwarnung : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Handbremse : 23|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ KBI_V_Digital : 24|9@1+ (1,0) [0|511] "" Vector__XXX + SG_ KBI_PLA_in_Anzeige : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigefehler_NV : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigestatus_LIM : 35|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_angez_Geschw : 48|10@1+ (0.32,0) [0|325.12] "Unit_KiloMeterPerHour" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Einheit_Tacho : 58|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Konsistenz_ACC : 59|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Fehler_Anzeige_ACC : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Anzeigefehler_SWA : 61|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 780 ACC_02: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Wunschgeschw_02 : 12|10@1+ (0.32,0) [0|327.04] "Unit_KiloMeterPerHour" XXX + SG_ ACC_Status_Prim_Anz : 22|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Abstandsindex : 24|10@1+ (1,0) [1|1021] "" XXX + SG_ ACC_Akustik_02 : 34|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Warnung_Verkehrszeichen_1 : 36|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Gesetzte_Zeitluecke : 37|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Optischer_Fahrerhinweis : 40|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ_Tachokranz : 41|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Anzeige_Zeitluecke : 42|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Tachokranz : 43|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Display_Prio : 44|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Relevantes_Objekt : 46|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Texte_Primaeranz : 48|7@1+ (1,0) [0|127] "" XXX + SG_ ACC_Wunschgeschw_erreicht : 55|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Typ_Tachokranz_unten : 60|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Status_Anzeige : 61|3@1+ (1,0) [0|7] "" XXX + +BO_ 783 SWA_01: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ SWA_Anzeigen : 12|4@1+ (1,0) [0|15] "" Kombi_D4 + SG_ SWA_Blindheit_erkannt : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_rel_Nichtverf : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_rel_Fehler : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Sta_aktiv : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Sta_passiv : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Standziele_li : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Kolonne_li : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Infostufe_SWA_li : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Warnung_SWA_li : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Kolonne_mi : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Standziele_re : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Kolonne_re : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Infostufe_SWA_re : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Warnung_SWA_re : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SWA_Gischtzaehler : 48|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ SWA_KD_Fehler : 59|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 792 Kamera_Status: 8 XXX + +BO_ 798 TSK_07: 8 Motor_Diesel_MQB + SG_ TSK_07_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ TSK_07_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ TSK_Wunschgeschw : 12|10@1+ (0.32,0) [0|326.72] "Unit_KiloMeterPerHour" Gateway_MQB + SG_ TSK_Texte_Primaeranz : 48|5@1+ (1,0) [0|31] "" Gateway_MQB + SG_ TSK_Limiter_Anzeige : 55|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_Status_Anzeige : 61|3@1+ (1,0) [0|7] "" Gateway_MQB + +BO_ 804 ACC_04: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Texte_Sekundaeranz : 12|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Texte_Zusatzanz : 16|6@1+ (1,0) [0|63] "" XXX + SG_ ACC_Status_Zusatzanz : 22|5@1+ (1,0) [0|31] "" XXX + SG_ ACC_Texte : 27|5@1+ (1,0) [0|31] "" XXX + SG_ ACC_Texte_braking_guard : 32|3@1+ (1,0) [0|7] "" XXX + SG_ ACC_Warnhinweis : 35|1@1+ (1,0) [0|1] "" XXX + SG_ ACC_Zeitluecke_Abstandswarner : 36|6@1+ (0.1,0) [0|6] "Unit_Secon" XXX + SG_ ACC_Abstand_Abstandswarner : 42|9@1+ (1,0) [0|508] "" XXX + SG_ ACC_Tempolimit : 51|5@1+ (1,0) [0|31] "" XXX + SG_ ACC_Charisma_FahrPr : 56|4@1+ (1,0) [0|15] "" XXX + SG_ ACC_Charisma_Status : 60|2@1+ (1,0) [0|3] "" XXX + SG_ ACC_Texte_Abstandswarner : 62|2@1+ (1,0) [0|3] "" XXX + +BO_ 811 Motor_Hybrid_02: 8 Motor_Hybrid_MQB + SG_ MO_HYB_E_Faktor : 12|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_Drehzahl_VM : 16|16@1+ (0.25,0) [0|16256] "Unit_MinutInver" Getriebe_DQ_Hybrid_MQB + SG_ MO_HYB_LowSpeedModus : 32|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB + +BO_ 812 Motor_17: 8 Motor_Diesel_MQB + SG_ MO_Prio_MAX_Wunschdrehzahl : 12|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Prio_MIN_Wunschdrehzahl : 13|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Luftpfad_aktiv : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_v_Begrenz_Aktivierbar : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ MO_Drehzahlbeeinflussung : 16|8@1+ (0.39,0) [0|99.45] "Unit_PerCent" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_MIN_Wunschdrehzahl : 24|8@1+ (25,0) [0|6350] "Unit_MinutInver" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_MAX_Wunschdrehzahl : 32|9@1+ (25,0) [0|12750] "Unit_MinutInver" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Charisma_FahrPr : 41|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Charisma_Status : 45|2@1+ (1,0) [0|3] "" Gateway_MQB + +BO_ 869 BEM_05: 8 Gateway_MQB + SG_ BEM_P_Generator : 16|8@1+ (50,0) [0|12700] "Unit_Watt" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_n_LLA : 24|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_01_Abschaltstufen : 26|3@1+ (1,0) [0|7] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_Anf_KL : 29|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_StartStopp_Info : 30|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BEM_DFM : 32|5@1+ (3.225,0.025) [0.025|100] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_EMLIN_ungueltig : 37|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_Batt_Ab : 38|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_Segel_Info : 48|2@1+ (1,0) [0|3] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BEM_HYB_DC_uSollLV : 50|6@1+ (0.1,10.6) [10.6|16] "Unit_Volt" LEH_MQB + SG_ BEM_HYB_DC_uMinLV : 56|8@1+ (0.1,0) [0|25.3] "Unit_Volt" LEH_MQB + +BO_ 870 Blinkmodi_02: 8 XXX + SG_ Hazard_Switch : 20|1@1+ (1,0) [0|1] "" XXX + SG_ Comfort_Signal_Left : 23|1@1+ (1,0) [0|1] "" XXX + SG_ Comfort_Signal_Right : 24|1@1+ (1,0) [0|1] "" XXX + SG_ Left_Turn_Exterior_Bulb_1 : 25|1@1+ (1,0) [0|1] "" XXX + SG_ Right_Turn_Exterior_Bulb_1 : 26|1@1+ (1,0) [0|1] "" XXX + SG_ Left_Turn_Exterior_Bulb_2 : 27|1@1+ (1,0) [0|1] "" XXX + SG_ Right_Turn_Exterior_Bulb_2 : 28|1@1+ (1,0) [0|1] "" XXX + SG_ Fast_Send_Rate_Active : 37|1@1+ (1,0) [0|1] "" XXX + +BO_ 873 CAMERA_NEW_4: 8 XXX + +BO_ 901 Charisma_01: 8 Gateway_MQB + SG_ CHA_Ziel_FahrPr_ALR : 0|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_ESP : 4|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_FL : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Fahrer_Umschaltung : 14|1@1+ (1,0) [0|1] "" Airbag_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ CHA_Ziel_FahrPr_MO : 16|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ CHA_Ziel_FahrPr_GE : 20|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ CHA_Ziel_FahrPr_ST : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_SCU : 28|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_DR : 32|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_QS : 36|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_AFS : 40|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_RGS : 44|4@1+ (1,0) [0|15] "" Airbag_MQB + SG_ CHA_Ziel_FahrPr_EPS : 48|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_ACC : 52|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ CHA_Ziel_FahrPr_SAK : 56|4@1+ (1,0) [0|15] "" SAK_MQB + SG_ CHA_Ziel_FahrPr_MStSt : 60|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 913 OBD_01: 8 Motor_Diesel_MQB + SG_ OBD_Calc_Load_Val : 0|8@1+ (0.39215686275,0) [0|100] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Eng_Cool_Temp : 8|8@1+ (1,-40) [-40|215] "Unit_DegreCelsi" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Abs_Throttle_Pos : 16|8@1+ (0.39215686275,0) [0|100] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Abs_Load_Val : 24|16@1+ (0.39215686275,0) [0|25700] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Abs_Pedal_Pos : 40|8@1+ (0.39215686275,0) [0|100] "Unit_PerCent" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Kaltstart_Denominator : 59|1@1+ (1,0) [0|1] "" BMS_MQB,LEH_MQB + SG_ OBD_Minimum_Trip : 60|1@1+ (1,0) [0|1] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Driving_Cycle : 61|1@1+ (1,0) [0|1] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Warm_Up_Cycle : 62|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ OBD_Normed_Trip : 63|1@1+ (1,0) [0|1] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + +BO_ 914 ESP_07: 8 Gateway_MQB + SG_ ESP_07_CRC : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_07_BZ : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_ACC_LDE : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Quattro_Antrieb : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Codierung_ADS : 14|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_RTA_HL : 16|8@1+ (0.048828125,-6.20117) [-6.20117|6.152345625] "Unit_PerCent" Vector__XXX + SG_ ESP_RTA_HR : 24|8@1+ (0.048828125,-6.20117) [-6.20117|6.152345625] "Unit_PerCent" Vector__XXX + SG_ ESP_RTA_VR : 32|8@1+ (0.048828125,-6.20117) [-6.20117|6.152345625] "Unit_PerCent" Vector__XXX + SG_ OBD_Fehler_Radsensor_HL : 40|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_Fehler_Radsensor_HR : 44|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_Fehler_Radsensor_VL : 48|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_Fehler_Radsensor_VR : 52|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ESP_Qualifizierung_Antriebsart : 56|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_Offroad_Modus : 57|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_MKB_ausloesbar : 58|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESP_MKB_Status : 59|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ESP_CM_Variante : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ESP_OBD_Status : 61|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 916 WBA_03: 8 Getriebe_DQ_Hybrid_MQB + SG_ WBA_03_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ WBA_03_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_Fahrstufe_02 : 12|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_ZielFahrstufe : 16|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_GE_Warnung_02 : 20|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ WBA_eing_Gang_02 : 24|4@1+ (1,0) [0|15] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Otto_MQB + SG_ WBA_GE_Texte : 28|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ WBA_Segeln_aktiv : 31|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WBA_Schaltschema : 32|5@1+ (1,0) [0|31] "" Gateway_MQB + +BO_ 917 LWR_AFS_01: 8 XXX + +BO_ 919 LDW_02: 8 XXX + SG_ LDW_Gong : 12|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_SW_Warnung_links : 14|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_SW_Warnung_rechts : 15|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Texte : 16|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Seite_DLCTLC : 20|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Lernmodus : 21|3@1+ (1,0) [0|7] "" XXX + SG_ LDW_Anlaufsp_VLR : 24|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Vib_Amp_VLR : 28|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Anlaufzeit_VLR : 32|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Lernmodus_rechts : 36|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Lernmodus_links : 38|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_DLC : 40|8@1+ (0.01,-1.25) [-1.25|1.25] "Unit_Meter" XXX + SG_ LDW_TLC : 48|5@1+ (0.1,0) [0|3] "Unit_Secon" XXX + SG_ LDW_Warnung_links : 56|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Warnung_rechts : 57|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Codierinfo_fuer_VLR : 58|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Frontscheibenheizung_aktiv : 60|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Status_LED_gelb : 61|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Status_LED_gruen : 62|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_KD_Fehler : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 945 DC_Hybrid_01: 8 LEH_MQB + SG_ DC_HYB_iAktLV : 12|10@1+ (1,-511) [-511|510] "Unit_Amper" Gateway_MQB + SG_ DC_HYB_iAktReserveLV : 22|10@1+ (1,-511) [-511|510] "Unit_Amper" Gateway_MQB + SG_ DC_HYB_uAktLV : 32|8@1+ (0.1,0) [0|25.3] "Unit_Volt" Gateway_MQB + SG_ DC_HYB_LangsRegelung : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Abregelung_Temperatur : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Fehler_RedLeistung : 42|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Fehler_intern : 43|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Fehler_Spannung : 44|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ DC_HYB_Auslastungsgrad : 56|8@1+ (0.4,0) [0|100] "Unit_PerCent" Gateway_MQB + +BO_ 949 Klima_11: 8 Gateway_MQB + SG_ KL_Drehz_Anh : 0|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Vorwarn_Komp_ein : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_AC_Schalter : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Komp_Moment_alt : 3|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Zonen : 4|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Vorwarn_Zuheizer_ein : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Zustand : 7|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Comp_rev_rq : 8|8@1+ (50,0) [0|8600] "Unit_MinutInver" Vector__XXX + SG_ KL_Charisma_FahrPr : 16|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ KL_Charisma_Status : 20|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Comp_enable : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Last_Kompr : 24|8@1+ (0.25,0) [0|63.5] "Unit_NewtoMeter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_Spannungs_Anf : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KL_Thermomanagement : 34|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_StartStopp_Info : 36|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ KL_Anf_KL : 40|8@1+ (0.4,0) [0|101.6] "Unit_PerCent" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KL_el_Zuheizer_Stufe : 48|3@1+ (1,0) [0|7] "" Motor_Diesel_MQB + +BO_ 958 Motor_14: 8 Motor_Diesel_MQB + SG_ MO_StartStopp_Status : 12|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_StartStopp_Wiederstart : 14|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_StartStopp_Motorstopp : 15|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Freig_Reku : 16|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Kl_75 : 18|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Kl_50 : 19|1@1+ (1,0) [0|1] "" Gateway_MQB,LEH_MQB + SG_ MO_Gangposition : 20|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_StartStopp_Fahrerwunsch : 24|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_HYB_Fahrbereitschaft : 26|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB + SG_ MO_Ext_E_Fahrt_aktiv : 27|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Fahrer_bremst : 28|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Fahrer_bremst : 29|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_BLS : 30|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Konsistenz_Bremsped : 31|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Timeout_ESP : 32|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Klima_Eingr : 33|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Aussp_Anlass : 35|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Freig_Anlass : 36|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Kuppl_schalter : 37|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Interlock : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Motor_laeuft : 39|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kickdown : 40|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Status_Zylabschalt_01 : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_EKlKomLeiRed : 42|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Handshake_STH : 44|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_BKV_Unterdruckwarnung : 45|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Freigabe_Segeln : 46|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_PTC_Status : 47|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ MO_QBit_Gangposition : 50|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Signalquelle_Gangposition : 51|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Remotestart_Betrieb : 52|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 960 Klemmen_Status_01: 4 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Airbag_MQB,BMS_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Airbag_MQB,BMS_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ZAS_Kl_S : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZAS_Kl_15 : 17|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ ZAS_Kl_X : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZAS_Kl_50 : 19|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 967 Motor_26: 8 Motor_Diesel_MQB + SG_ MO_HYB_Status_HV_Ladung : 8|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ WIV_Anzeige_aktiv : 12|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oelmin_Warn : 13|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Sensorfehler : 14|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Schieflage : 15|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oelstand : 16|4@1+ (12.5,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ MO_Zustand_HWP : 20|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ WIV_Oelsystem_aktiv : 24|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_nicht_betriebswarm : 25|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Ueberfuell_Warn : 26|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_laufender_Motor : 27|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_1 : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_2 : 29|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_3 : 30|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_4 : 31|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Text_Motorstart : 32|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_HYB_Text_5 : 36|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_6 : 37|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Text_7 : 38|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Text_Partikelfil_Reg : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oelmenge : 43|5@1+ (125,0) [0|3875] "Unit_MilliLiter" Gateway_MQB + SG_ MO_Systemlampe : 48|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_OBD2_Lampe : 49|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Heissleuchte : 50|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Partikel_Lampe : 51|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Winterfahrprog : 52|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ WIV_Oelstand_nicht_vorhanden : 53|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_nachfuellanzeige_ein : 54|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Ueberfuell_deaktiv : 55|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Unterfuell_Warn : 56|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Tankdeckel_Lampe : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Text_Tankdeckelwarn : 58|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ WIV_Oeldr_Warn_Motor : 60|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 968 Getriebe_14: 8 Getriebe_DQ_Hybrid_MQB + SG_ GE_OBD_AbsperrVent : 12|4@1+ (1,0) [0|15] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_amax_moeglich : 16|9@1+ (0.024,-2.016) [-2.016|10.224] "Unit_MeterPerSeconSquar" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Charisma_FahrPr : 25|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ GE_Charisma_Status : 29|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ GE_Verlustmoment : 32|8@1+ (1,0) [0|254] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Freigabe_Verfallsinfo_WFS : 49|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ GE_Codierung_MSG : 50|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ GE_LaunchControl : 51|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ GE_Heizwunsch : 52|2@1+ (1,0) [0|3] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_OBD_Status : 54|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_LFR_Adaption : 55|1@1+ (1,0) [0|1] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ GE_Sumpftemperatur : 56|8@1+ (1,-58) [-58|196] "Unit_DegreCelsi" Gateway_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 981 Licht_Anf_01: 8 XXX + +BO_ 982 Licht_hinten_01: 8 Gateway_MQB + SG_ Licht_hinten_01_BZ : 0|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM2_Bremsl_durch_ECD : 5|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LH_Aussenlicht_def : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Standlicht_H_aktiv : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Parklicht_HL_aktiv : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Parklicht_HR_aktiv : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremslicht_H_aktiv : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Nebelschluss_aktiv : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckfahrlicht_aktiv : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_HL_akt : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_HR_akt : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_li_def : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_li_def : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schlusslicht_li_def : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckf_li_def : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Nebel_li_def : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_Nebel_li_def : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_Nebel_re_def : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_li_def : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Nebel_li_def : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_SL_BRL_BLK_li_def : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Brems_Blk_li_def : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Blinker_re_def : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_re_def : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schlusslicht_re_def : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckf_re_def : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Nebel_re_def : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Brems_re_def : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Schluss_Nebel_re_def : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_SL_BRL_BLK_re_def : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Brems_Blk_re_def : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Kennzl_def : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_3_Bremsl_def : 49|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LH_Nebel_mi_def : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Rueckf_mi_def : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ LH_Bremsl_li_ges_def : 54|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ LH_Bremsl_re_ges_def : 55|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 984 RGS_VL_01: 8 Airbag_MQB + SG_ RGS_VL_Texte : 12|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ RGS_VL_Charisma_FahrPr : 14|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ RGS_VL_Charisma_Status : 18|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ RGS_VL_aktiv : 21|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Sitz : 25|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Schiebedach : 26|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Fenster : 27|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_PC_Aktuator_Warnblinken : 28|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ RGS_VL_Precrash_Basis : 32|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ RGS_VL_Precrash_Front : 40|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ RGS_VL_Precrash_Rear : 48|8@1+ (1,0) [0|255] "" Gateway_MQB + +BO_ 987 Gateway_72: 8 Gateway_MQB + SG_ BCM_01_alt : 0|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ SMLS_01_alt : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ZV_02_alt : 2|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Wischer_01_alt : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Anhaenger_01_alt : 4|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ Klima_Sensor_02_alt : 5|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ VSG_01_alt : 6|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ Klima_01_alt : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ WFS_01_alt : 8|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Licht_Anf_01_alt : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HFS_offen : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HBFS_offen : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ VS_VD_offen_ver : 22|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ VS_VD_zu_ver : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_BT_offen : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Rueckfahrlicht_Schalter : 25|1@1+ (1,0) [0|1] "" Airbag_MQB + SG_ ZV_FT_offen : 26|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ Wischer_vorne_aktiv : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Anhaenger_erkannt : 28|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ BCM1_MH_Schalter : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZV_HD_offen : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Waschen_vorne_aktiv : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KL_Thermomanagement : 32|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ WFS_Schluessel_Fahrberecht : 34|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BCM1_RFahrlicht_Fzg_Anf : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_RFahrlicht_Ahg_Anf : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BH_Fernlicht : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BH_Blinker_li : 50|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BH_Blinker_re : 51|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_OBD_FStatus_ATemp : 52|4@1+ (1,0) [0|15] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Aussen_Temp_ungef : 56|8@1+ (0.5,-50) [-50|76] "Unit_DegreCelsi" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 988 Gateway_73: 8 XXX + +BO_ 989 Gateway_74: 8 Gateway_MQB + SG_ LH_EPS_01_alt : 0|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB + SG_ Kessy_04_alt : 1|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ LIN_2_alt : 2|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MFG_01_alt : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ GW_74_va_14 : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Klima_02_alt : 5|1@1+ (1,0) [0|1] "" BMS_MQB + SG_ Parkhilfe_01_alt : 6|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ELV_01_alt : 7|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KY_StartStopp_Info : 16|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ PH_StartStopp_Info : 18|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ EPS_Lenkerposition : 20|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB + SG_ ELV_Anf_Klemme_50 : 22|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ MF_StartStopp_Info : 25|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ KL_Geblaesespannung_Soll : 40|8@1+ (0.05,0.5) [2|13] "Unit_Volt" BMS_MQB + SG_ KL_Umluftklappe_Status : 48|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ MFL_Tip_Down : 56|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MFL_Tip_Up : 57|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ LS_Tiptronic_Fehler : 58|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 991 Gateway_76: 8 XXX + +BO_ 997 TSG_FT_02: 8 XXX + SG_ TSG_FT_02_CRC : 0|8@1+ (1,0) [0|255] "" XXX + SG_ TSG_FT_02_BZ : 8|4@1+ (1,0) [0|15] "" XXX + +BO_ 1122 PSD_04: 8 XXX + SG_ PSD_Object_Index : 0|6@1+ (1,0) [0|63] "" XXX + +BO_ 1123 PSD_05: 8 XXX + SG_ PSD_Current_Route_Index : 0|6@1+ (1,0) [0|63] "" XXX + SG_ Route_Distance_Remaining : 8|5@1+ (1,0) [0|31] "" XXX + +BO_ 1124 PSD_06: 8 XXX + +BO_ 1172 STS_01: 8 Gateway_MQB + SG_ STS_01_CRC : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STS_01_BZ : 8|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STS_Car_not_under_theft : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Car_under_theft : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Anlassersperre : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Typencodierung : 16|5@1+ (1,0) [0|31] "" Vector__XXX + SG_ STS_LIN_aktiv : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Standlicht : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Fahrlicht : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Alarm_still : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Texte : 27|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ STS_Laderelais : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Summer : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Alarm_Blinker : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Notstart : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Signalhorn : 55|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STS_Leerlaufschaltung : 56|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 1175 Parkhilfe_01: 8 XXX + +BO_ 1312 Airbag_02: 8 Airbag_MQB + SG_ AB_Belegung_VB : 26|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_FA : 40|2@1+ (1,0) [0|3] "" Gateway_MQB,Motor_Diesel_MQB,Motor_Otto_MQB + SG_ AB_Gurtschloss_BF : 42|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe2_FA : 44|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe2_MI : 46|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe2_BF : 48|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe3_FA : 50|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe3_MI : 52|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Gurtschloss_Reihe3_BF : 54|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Sitzpos_Sens_FA : 56|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ AB_Sitzpos_Sens_BF : 58|2@1+ (1,0) [0|3] "" Gateway_MQB + +BO_ 1313 STH_01: 8 Gateway_MQB + SG_ STH_Funk_ein : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Funk_aus : 1|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Zusatzheizung : 2|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_LED : 3|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_Pumpe_ein : 4|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Geblaese : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_EKP_Anst : 6|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_Start_folgt : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Ventiloeffnungszeit : 8|6@1+ (1,0) [0|63] "Unit_Minut" Vector__XXX + SG_ STH_Ventil_Status : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_Waermeeintrag : 16|6@1+ (1,0) [0|63] "" Vector__XXX + SG_ STH_KVS : 24|13@1+ (1,0) [0|8191] "Unit_MilliLiter" Vector__XXX + SG_ STH_Fehlerstatus : 37|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ STH_Heizleistung : 40|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ STH_Wassertemp : 48|8@1+ (0.75,-40) [-40|142.25] "Unit_DegreCelsi" Vector__XXX + SG_ STH_Motorvorwaermung : 59|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_Servicemode : 60|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_war_aktiv : 61|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ STH_KVS_Ueberlauf : 62|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ STH_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1385 HVEM_04: 8 XXX + +BO_ 1413 Systeminfo_01: 8 Gateway_MQB + SG_ SI_Sammel_SG_Fehler : 0|6@1+ (1,0) [0|60] "" Vector__XXX + SG_ SI_Rollenmode : 6|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ SI_QRS_Mode : 8|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ SI_T_Mode : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_NWDF : 10|1@1+ (1,0) [0|1] "" SAK_MQB + SG_ SI_NWDF_gueltig : 11|1@1+ (1,0) [0|1] "" SAK_MQB + SG_ SI_Sammelfehler : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ GW_KD_Fehler : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_01 : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_02 : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_03 : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_04 : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_05 : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_06 : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_07 : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_08 : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_09 : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_10 : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_11 : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_12 : 27|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_13 : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_14 : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SI_BUS_15 : 30|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 1437 Remotestart_FFB: 8 Gateway_MQB + SG_ RSF_Tastencode_1 : 0|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ RSF_Tastencode_2 : 8|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ RSF_Tastencode_Maske : 16|8@1+ (1,0) [0|255] "" Motor_Diesel_MQB,Motor_Otto_MQB + +BO_ 1440 RLS_01: 8 XXX + +BO_ 1520 Dimmung_01: 8 Gateway_MQB + SG_ DI_KL_58xd : 0|8@1+ (1,0) [0|253] "" Airbag_MQB + SG_ DI_KL_58xs : 8|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ DI_Display_Nachtdesign : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ DI_KL_58xt : 16|7@1+ (1,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ DI_Fotosensor : 24|16@1+ (1,0) [0|65535] "" Vector__XXX + +BO_ 1528 SAK_01: 8 SAK_MQB + SG_ SAK_Charisma_FahrPr : 16|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ SAK_Charisma_Status : 20|2@1+ (1,0) [0|3] "" Gateway_MQB + +BO_ 1600 Motor_07: 8 Motor_Diesel_MQB + SG_ MO_QBit_Ansaugluft_Temp : 0|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_QBit_Oel_Temp : 1|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_QBit_Kuehlmittel_Temp : 2|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Stellgliedtest_Soundaktuator : 3|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_HYB_Fehler_HV_Netz : 4|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_aktives_Getriebeheizen : 5|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Absperrventil_oeffnen : 6|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Ansaugluft_Temp : 8|8@1+ (0.75,-48) [-48|141.75] "Unit_DegreCelsi" Gateway_MQB + SG_ MO_Oel_Temp : 16|8@1+ (1,-60) [-60|192] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kuehlmittel_Temp : 24|8@1+ (0.75,-48) [-48|141.75] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB + SG_ MO_Hoeheninfo : 32|8@1+ (0.00781,0) [0|1.98374] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Kennfeldk : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Versionsinfo : 41|6@1+ (1,0) [0|63] "" Gateway_MQB + SG_ MO_Getriebe_kuehlen : 47|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Mom_Traegheit_02 : 48|5@1+ (0.01,0) [0|0.31] "Unit_KiloGramMeterSquar" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Heizungspumpenansteuerung : 53|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ MO_SpannungsAnf : 57|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Nachlaufzeit_Heizungspumpe : 58|6@1+ (15,0) [0|945] "Unit_Secon" Gateway_MQB + +BO_ 1601 Motor_Code_01: 8 Motor_Diesel_MQB + SG_ Motor_Code_01_CRC : 0|8@1+ (1,0) [0|255] "" Gateway_MQB + SG_ Motor_Code_01_BZ : 8|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Faktor_Momente_02 : 12|2@1+ (1,0) [0|3] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Hybridfahrzeug : 14|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Code : 16|8@1+ (1,0) [0|255] "" Gateway_MQB,SAK_MQB + SG_ MO_Getriebe_Code : 24|6@1+ (1,0) [0|63] "" Gateway_MQB + SG_ MO_StartStopp_Codiert : 30|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Anzahl_Zyl : 32|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_Kraftstoffart : 36|4@1+ (1,0) [0|15] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Hubraum : 40|7@1+ (0.1,0) [0|12.7] "Unit_Liter" Gateway_MQB + SG_ MO_Ansaugsystem : 47|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_Leistung : 48|9@1+ (1,0) [0|511] "Unit_KiloWatt" Gateway_MQB + SG_ MO_Abgastyp_EOBD : 57|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ MO_Abgastyp_OBD : 58|1@1+ (1,0) [0|1] "" BMS_MQB,Gateway_MQB,LEH_MQB + SG_ MO_DPF_verbaut : 59|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ TSK_Codierung : 60|3@1+ (1,0) [0|7] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Einspritzart : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 1602 WIV_01: 8 Motor_Diesel_MQB + SG_ WIV_Verschleissindex : 0|16@1+ (2e-08,0) [0|0.00131068] "" Gateway_MQB + SG_ WIV_Russindex : 16|16@1+ (2e-08,0) [0|0.00131068] "" Gateway_MQB + SG_ WIV_t_min : 32|6@1+ (1,0) [0|63] "Unit_Month" Gateway_MQB + SG_ WIV_t_max : 40|6@1+ (1,0) [0|63] "Unit_Month" Gateway_MQB + SG_ WIV_W_min : 48|7@1+ (1000,0) [0|127000] "Unit_KiloMeter" Gateway_MQB + SG_ WIV_W_max : 56|7@1+ (1000,0) [0|127000] "Unit_KiloMeter" Gateway_MQB + +BO_ 1603 Einheiten_01: 8 Gateway_MQB + SG_ KBI_Einheit_Datum : 0|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Druck : 2|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Streckenanz : 4|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB + SG_ KBI_MFA_v_Einheit_02 : 5|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Temp : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Uhrzeit : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ KBI_Einheit_Verbrauch : 8|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Volumen : 10|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ KBI_Einheit_Sprache : 16|8@1+ (1,0) [0|255] "" Vector__XXX + +BO_ 1605 FLA_01: 8 XXX + +BO_ 1607 Motor_09: 8 Motor_Diesel_MQB + SG_ MO_ITM_Kuehlmittel_Temp : 0|8@1+ (0.75,-48) [-45.75|143.25] "Unit_DegreCelsi" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_E85_Sensor : 8|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ SCR_Anz_Motorstarts : 12|4@1+ (1,0) [0|8] "" Gateway_MQB + SG_ SCR_Reichweite : 16|15@1+ (1,0) [0|32766] "" Gateway_MQB + SG_ SCR_Warnstufe_1 : 32|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Warnstufe_2 : 33|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Text : 34|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ SCR_Akustik : 37|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Kraftstofffilter_Wasser : 40|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Systemfehler : 41|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ SCR_Inducement_Strategie : 42|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_CO2_Faktor : 44|12@1+ (1,0) [1|4094] "Unit_GramPerLiter" Gateway_MQB + +BO_ 1624 Licht_vorne_01: 8 XXX + +BO_ 1625 Klimakomp_01: 8 Gateway_MQB + SG_ EKL_KD_Fehler : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EKL_Comp_SCI_com_stat : 16|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_output_stat : 18|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_main_stat : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EKL_Comp_ovld_stat : 21|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ EKL_Comp_Inv_stat : 24|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_photo_temp_stat : 30|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EKL_Comp_photo_temp : 32|8@1+ (1,0) [0|254] "Unit_DegreCelsi" Vector__XXX + SG_ EKL_Comp_current : 40|8@1+ (0.1,0) [0|25.4] "Unit_Amper" Motor_Hybrid_MQB + SG_ EKL_Comp_rev_stat : 48|8@1+ (50,0) [0|8600] "Unit_MinutInver" Vector__XXX + +BO_ 1626 BCM_01: 8 Gateway_MQB + SG_ BCM_Bremsbelag_Sensor : 12|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Bremsfluessigkeit_Sensor : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Licht_Warn : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Waschwasser_Sensor : 15|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Kuehlmittel_Sensor : 16|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_Kl_15_HW_erkannt : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Eis_Offroad_Taste : 18|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Otto_MQB + SG_ ZZH_Endlage_oben : 19|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZZH_Endlage_unten : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ZZH_Endlage_unplausibel : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM2_EZS_gedrueckt : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM2_SST_gedrueckt : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Hybrid_StartStopp_Taste : 24|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Warnblink_Taster : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Valet_Parking_Taster : 26|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM_Remotestart_Betrieb : 27|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_HSK_Taster : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Heckrollo_Taster : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ BCM1_Rueckfahrlicht_Schalter : 30|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_MH_Schalter : 31|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Otto_MQB + SG_ BCM1_MH_WIV_Schalter : 32|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM_Eco_Charisma_Taste : 33|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ BCM_Thermomanagement : 34|2@1+ (1,0) [0|3] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM_Thermomanagement_Fehler : 36|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM_Thermomanagement_gueltig : 37|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ BCM1_Lichtwarn_Texte : 38|2@1+ (1,0) [0|3] "" Vector__XXX + +BO_ 1628 BMS_Hybrid_01: 8 BMS_MQB + SG_ BMS_HYB_ASV_hinten_Status : 13|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_ASV_vorne_Status : 14|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_KD_Fehler : 15|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_BattFanSpd : 16|4@1+ (10,0) [0|100] "Unit_PerCent" Gateway_MQB + SG_ BMS_HYB_VentilationReq : 20|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_Spuelbetrieb_Status : 21|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ BMS_HYB_Kuehlung_Anf : 22|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ BMS_HYB_Temp_vor_Verd : 24|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_HYB_Temp_nach_Verd : 32|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_Temperatur : 40|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_Temperatur_Ansaugluft : 48|8@1+ (0.5,-40) [-40|86.5] "Unit_DegreCelsi" Gateway_MQB + SG_ BMS_IstSpannung_HV : 56|8@1+ (1,100) [100|350] "Unit_Volt" Gateway_MQB + +BO_ 1629 ESP_20: 8 Gateway_MQB + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ BR_Systemart : 12|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ ESP_Zaehnezahl : 16|8@1+ (1,0) [0|255] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ ESP_Charisma_FahrPr : 24|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ ESP_Charisma_Status : 28|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ BR_QBit_Reifenumfang : 51|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ BR_Reifenumfang : 52|12@1+ (1,0) [0|4095] "Unit_MilliMeter" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 1630 OBD_Tankgeber_01: 8 Gateway_MQB + SG_ OBD_TG_F_Status_1 : 0|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_F_Status_2 : 4|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_F_Status_3 : 8|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_F_Status_4 : 12|4@1+ (1,0) [0|15] "" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_1 : 16|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_2 : 28|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_3 : 40|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ OBD_TG_Sens_Rohwert_4 : 52|12@1+ (0.5,0) [0|2047.5] "Unit_Ohm" Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 1631 Motor_16: 8 Motor_Diesel_MQB + SG_ TSK_QBit_Steigung : 12|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_QBit_Fahrzeugmasse : 13|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_SpannungsAnf_02 : 14|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_DPF_reg : 16|1@1+ (1,0) [0|1] "" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ MO_Heizstrom_EKAT : 17|7@1+ (1,0) [0|126] "Unit_Amper" Gateway_MQB + SG_ MO_Heizstrom_SCR : 24|6@1+ (1,0) [0|62] "Unit_Amper" Gateway_MQB + SG_ TSK_Fahrzeugmasse_02 : 48|8@1+ (32,0) [0|8128] "Unit_KiloGram" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + SG_ TSK_Steigung : 56|8@1+ (0.8,-101.6) [-101.6|101.6] "Unit_PerCent" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 1633 Anhaenger_01: 8 Gateway_MQB + SG_ AAG_BZ : 0|4@1+ (1,0) [0|15] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Bremsl_durch_ECD : 5|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Anhaenger_abgesteckt : 6|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_NSL_aktiv : 7|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Anhaenger_erkannt : 8|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Blinker_H_aktiv : 9|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Blinker_HL_def : 10|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Blinker_HR_def : 11|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Bremslicht_H_def : 12|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ AAG_Schlusslicht_HL_def : 13|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_Schlusslicht_HR_def : 14|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_AVS_Fehler_02 : 18|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AAG_AVS_Stati : 20|4@1+ (1,0) [0|15] "" Vector__XXX + +BO_ 1646 Klima_03: 8 XXX + +BO_ 1648 Motor_18: 8 Motor_Diesel_MQB + SG_ MO_Hybrid_StartStopp_LED : 43|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Eis_Offroad_LED : 45|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_Anzahl_Abgesch_Zyl : 47|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ MO_Zylabsch_Texte : 50|2@1+ (1,0) [0|3] "" Gateway_MQB + SG_ MO_E85_BS_Texte : 52|3@1+ (1,0) [0|7] "" Gateway_MQB + SG_ MO_Drehzahl_Warnung : 55|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ MO_obere_Drehzahlgrenze : 56|8@1+ (50,0) [50|12750] "Unit_MinutInver" Gateway_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB + +BO_ 1714 Diagnose_01: 8 Gateway_MQB + SG_ DGN_Verlernzaehler : 0|8@1+ (1,0) [0|254] "" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,SAK_MQB + SG_ KBI_Kilometerstand : 8|20@1+ (1,0) [0|1048573] "Unit_KiloMeter" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Jahr : 28|7@1+ (1,2000) [2000|2127] "Unit_Year" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Monat : 35|4@1+ (1,0) [1|12] "Unit_Month" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Tag : 39|5@1+ (1,0) [1|31] "Unit_Day" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Stunde : 44|5@1+ (1,0) [0|23] "Unit_Hours" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Minute : 49|6@1+ (1,0) [0|59] "Unit_Minut" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ UH_Sekunde : 55|6@1+ (1,0) [0|59] "Unit_Secon" Airbag_MQB,BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB,SAK_MQB + SG_ Kombi_02_alt : 62|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,LEH_MQB + SG_ Uhrzeit_01_alt : 63|1@1+ (1,0) [0|1] "" Airbag_MQB,BMS_MQB,LEH_MQB + +BO_ 1716 VIN_01: 8 Gateway_MQB + SG_ VIN_01_MUX M : 0|2@1+ (1,0) [0|3] "" Airbag_MQB + SG_ KS_Geheimnis_1 m0 : 8|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KS_Geheimnis_2 m0 : 16|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KS_Geheimnis_3 m0 : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ KS_Geheimnis_4 m0 : 32|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ VIN_1 m0 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_2 m0 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_3 m0 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_4 m1 : 8|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_5 m1 : 16|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_6 m1 : 24|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_7 m1 : 32|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_8 m1 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_9 m1 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_10 m1 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_11 m2 : 8|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_12 m2 : 16|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_13 m2 : 24|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_14 m2 : 32|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_15 m2 : 40|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_16 m2 : 48|8@1+ (1,0) [0|255] "" Airbag_MQB + SG_ VIN_17 m2 : 56|8@1+ (1,0) [0|255] "" Airbag_MQB + +BO_ 1719 Kombi_02: 8 Gateway_MQB + SG_ KBI_Kilometerstand : 0|20@1+ (1,0) [0|1048573] "Unit_KiloMeter" Vector__XXX + SG_ KBI_Standzeit_02 : 20|17@1+ (1,0) [0|131068] "Unit_Secon" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Inhalt_Tank : 40|7@1+ (1,0) [0|125] "Unit_Liter" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_FStatus_Tank : 47|1@1+ (1,0) [0|1] "" Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_QBit_Aussen_Temp_gef : 55|1@1+ (1,0) [0|1] "" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ KBI_Aussen_Temp_gef : 56|8@1+ (0.5,-50) [-50|75] "Unit_DegreCelsi" Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + +BO_ 1720 Kombi_03: 8 XXX + SG_ KBI_Reifenumfang : 0|12@1+ (1,0) [0|4095] "Unit_MilliMeter" XXX + SG_ KBI_Variante_USA : 12|1@1+ (1,0) [0|1] "" XXX + SG_ KBI_Variante : 13|1@1+ (1,0) [0|1] "" XXX + SG_ KBI_BCmE_aktiv : 16|1@1+ (1,0) [0|1] "" XXX + SG_ KBI_Sparhinweis_quittiert : 17|1@1+ (1,0) [0|1] "" XXX + SG_ KBI_Tankfuellstand_Prozent : 18|7@1+ (1,0) [0|100] "Unit_PerCent" XXX + SG_ KBI_Nachtanken_erkannt : 25|1@1+ (1,0) [0|1] "" XXX + SG_ KBI_Tankinhalt_hochaufl : 26|14@1+ (0.01,0) [0|163.81] "Unit_Liter" XXX + SG_ KBI_Max_Tankinhalt : 40|8@1+ (0.5,0) [0|126.5] "" XXX + SG_ KBI_Reifenumfang_Sekundaer : 48|12@1+ (1,0) [0|4095] "Unit_MilliMeter" XXX + +BO_ 316495015 CAMERA_NEW_6: 32 XXX + +BO_ 380196019 CAMERA_NEW_16: 16 XXX + +BO_ 380196036 CAMERA_NEW_18: 8 XXX + +BO_ 389224720 CAMERA_NEW_13: 3 XXX + +BO_ 389226768 CAMERA_NEW_12: 2 XXX + +BO_ 389241616 CAMERA_NEW_14: 5 XXX + +BO_ 401604687 CAMERA_NEW_9: 8 XXX + +BO_ 441800082 CAMERA_NEW_15: 8 XXX + +BO_ 441800100 CAMERA_NEW_8: 64 XXX + +BO_ 441800101 CAMERA_NEW_7: 64 XXX + +BO_ 2549088277 KN_Airbag_01: 8 Airbag_MQB + SG_ Airbag_01_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Airbag_01_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ AB_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088284 KN_SAK: 8 SAK_MQB + SG_ SAK_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ SAK_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ SAK_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088374 KN_MO_01: 8 Motor_Diesel_MQB + SG_ Motor_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Motor_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ MO_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088375 KN_Getriebe_01: 8 Getriebe_DQ_Hybrid_MQB + SG_ Getriebe_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Getriebe_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ GE_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088379 KN_Hybrid_01: 8 BMS_MQB + SG_ Hybrid_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ Hybrid_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ BMS_HYB_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2549088380 KN_EMotor_01: 8 LEH_MQB + SG_ EMotor_KompSchutz : 0|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EMotor_Nachlauftyp : 4|4@1+ (1,0) [0|15] "" Gateway_MQB + SG_ EM_HYB_KD_Fehler : 63|1@1+ (1,0) [0|1] "" Gateway_MQB + +BO_ 2600468496 NMH_Gateway: 8 Gateway_MQB + SG_ NM_Gateway_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Gateway_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Gateway_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Gateway_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_ACAN_Aktivitaet : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_FCAN_Aktivitaet : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_KCAN_Aktivitaet : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_ICAN_Aktivitaet : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_DiagCAN_Aktivitaet : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_ECAN_Aktivitaet : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_Energie_LIN_Aktivi000 : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_Bedien_LIN_Aktivitaet : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_EM_Aktivitaet : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_EM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_Shutdown : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_Spg_Messung : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_NL_Wakeup_Monitor : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Gateway_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468501 NMH_Airbag_01: 8 Airbag_MQB + SG_ NM_Airbag_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Airbag_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Airbag_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_Airbag_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Airbag_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Airbag_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Airbag_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Airbag_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468598 NMH_MO_01: 8 Motor_Diesel_MQB + SG_ NM_MO_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_MO_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_MO_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_MO_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_HV_Abschaltung : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_EKP_Vorlauf : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NM_aktiv_STH_Betrieb : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_Kuehlerluefter : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_Diagnose : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_WFS : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_EEPROM : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_NL_Sonstige : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_MO_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468599 NMH_Getriebe_01: 8 Getriebe_DQ_Hybrid_MQB + SG_ NM_Getriebe_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Getriebe_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Getriebe_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_Getriebe_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_v_gr_0 : 35|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Pos_Erk : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NM_aktiv_Umg_Bed : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_NL_Daten_EEPROM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Getriebe_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468603 NMH_Hybrid_01: 8 BMS_MQB + SG_ NM_Hybrid_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Hybrid_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_Hybrid_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_Hybrid_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_Hybrid_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NL_Daten_EEPROM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_NL_Luefter : 49|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_Hybrid_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +BO_ 2600468604 NMH_EMotor_01: 8 LEH_MQB + SG_ NM_EMotor_01_SNI : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_EMotor_01_NM_State : 16|6@1+ (1,0) [0|63] "" BMS_MQB,Getriebe_DQ_Hybrid_MQB,Getriebe_DQ_MQB,LEH_MQB,Motor_Diesel_MQB,Motor_Hybrid_MQB,Motor_Otto_MQB + SG_ NM_EMotor_01_Car_Wakeup : 22|1@1+ (1,0) [0|1] "" Gateway_MQB + SG_ NM_EMotor_01_Wakeup : 24|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ NM_EMotor_01_NM_aktiv_KL15 : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_NM_aktiv_Diagnose : 33|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_NM_aktiv_Tmin : 34|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_NL_Daten_EEPROM : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ NM_EMotor_01_UDS_CC : 63|1@1+ (1,0) [0|1] "" Vector__XXX + +CM_ SG_ 134 LWI_Lenkradwinkel "Steering angle WITH variable ratio effect included"; +CM_ SG_ 159 EPS_Berechneter_LW "Raw steering angle, degrees"; +CM_ SG_ 159 EPS_VZ_BLW "Raw steering angle, direction"; +CM_ SG_ 159 EPS_HCA_Status "Status of Heading Control Assist feature"; +CM_ SG_ 159 EPS_Lenkmoment "Steering input by driver, torque"; +CM_ SG_ 159 EPS_VZ_Lenkmoment "Steering input by driver, direction"; +CM_ SG_ 173 COUNTERXX "Message not renamed to COUNTER because J533 rate-limiting makes it look like messages are being lost"; +CM_ SG_ 294 HCA_01_Vib_Freq "Frequenz der Lenkradvibration"; +CM_ SG_ 294 HCA_01_LM_Offset "Von HCA angefordertes Lenkmoment (Betrag)"; +CM_ SG_ 294 EA_ACC_Sollstatus "Status-Anforderung ACC von Emergency Alert. Statuswechsel bei Flanke. Solange Wert=1, wird EA_ACC_Wunschgeschwindigkeit übernommen. Wert=2 führt zu Zustand ¿ACC_GRA_passiv¿"; +CM_ SG_ 294 EA_Ruckprofil "Emergency Alert Anforderung an ESP, welcher Ruck verwendet werden soll. Eine Umsetzung der Ruckanforderung im ESP erfolgt nur mit gesetztem Bit 'EA_Ruckfreigabe'."; +CM_ SG_ 294 HCA_01_Sendestatus "Gibt den Sendestatus der HCA_01 an (notwendig für IL-Unterstützung)"; +CM_ SG_ 294 HCA_01_LM_OffSign "Vorzeichen des HCA-Lenkmoments"; +CM_ SG_ 294 HCA_01_Status_HCA "Statusinformation vom HCA und Manoevrierassistent für Handshakemechanismus mit der Lenkung"; +CM_ SG_ 294 HCA_01_Vib_Amp "Momentenamplitude der Lenkradvibration"; +CM_ SG_ 294 EA_Ruckfreigabe "Emergency Alert Freigabit für die Warnruck-Anforderung an das ESP"; +CM_ SG_ 294 EA_ACC_Wunschgeschwindigkeit "Emergency Alert Anforderung neue Wunschgeschwindigkeit"; +CM_ SG_ 391 GearPosition "Traditional PRND plus B-mode aggressive regen, B-mode mapped to Drive"; +CM_ SG_ 771 SET_ME_0X54 "Varies but not sure how, may indicate path or curvature"; +CM_ SG_ 870 Hazard_Switch "Four-way flashers active"; +CM_ SG_ 870 Comfort_Signal_Left "Comfort turn signal active, left"; +CM_ SG_ 870 Comfort_Signal_Right "Comfort turn signal active, right"; +CM_ SG_ 870 Left_Turn_Exterior_Bulb_1 "Probably front"; +CM_ SG_ 870 Right_Turn_Exterior_Bulb_1 "Probably front"; +CM_ SG_ 870 Left_Turn_Exterior_Bulb_2 "Probably rear"; +CM_ SG_ 870 Right_Turn_Exterior_Bulb_2 "Probably rear"; +CM_ SG_ 870 Fast_Send_Rate_Active "CAN message send rate"; +CM_ SG_ 919 LDW_DLC "Probable DLC (distance to line crossing)"; +CM_ SG_ 919 LDW_TLC "Probable TLC (time to line crossing)"; +CM_ SG_ 960 ZAS_Kl_15 "Indicates ignition on"; +CM_ SG_ 1720 KBI_Reifenumfang "Mittlerer Radumfang aus der K-Zahl gerechnet in Millimeter. Byte 2 Bit 5,4 reserviert, Byte 2 Bit 3..0 und Byte 1 Bit 7..0; Wertebereich 0..4096 mm"; +CM_ SG_ 1720 KBI_Variante_USA "In diesem Signal wird die HW-Variante des Kombis ausgegeben, ACC plausibilisiert auf dieses Signal hin seine US-Codierung"; +CM_ SG_ 1720 KBI_Variante "Zeigt an ob es sich um ein konventionelles Zeiger-Kombiinstrument handelt oder um eine Volldisplay-Kombiinstrument"; +CM_ SG_ 1720 KBI_BCmE_aktiv "Anzeige BCmE aktiv (BCmE-Screen oder Einsparhinweis in der Anzeige)"; +CM_ SG_ 1720 KBI_Sparhinweis_quittiert "angezeigter Sparhinweis ist quittiert. Signal wird nach zwei Sendebotschaften wieder auf '0' gesetzt."; +CM_ SG_ 1720 KBI_Tankfuellstand_Prozent "Tankfüllstand in %"; +CM_ SG_ 1720 KBI_Nachtanken_erkannt "Statusinformation Nachtankmodus"; +CM_ SG_ 1720 KBI_Tankinhalt_hochaufl "angezeigter Tankinhalt hochauflösend zur Restreichweitenberechnung"; +CM_ SG_ 1720 KBI_Max_Tankinhalt "Mitteilung des maximalen Tankinhalts an das Reichweitenmodul"; +CM_ SG_ 1720 KBI_Reifenumfang_Sekundaer "Fahrzeuge mit unterschiedlichen Reifenumfängen Vorderachse / Hinterachse: + +Primärachse: KBI_Reifenumfang +Sekundärachse: KBI_Reifenumfang_Sekundaer"; +VAL_ 159 EPS_HCA_Status 0 "disabled" 1 "initializing" 2 "fault" 3 "ready" 4 "rejected" 5 "active"; +VAL_ 173 GE_Fahrstufe 5 "P" 6 "R" 7 "N" 8 "D" 9 "S" 10 "E" 13 "T" 14 "T"; +VAL_ 279 AWV1_Anf_Prefill 0 "Prefill_nicht_aktivieren" 1 "Prefill_aktivieren"; +VAL_ 279 ANB_CM_Info 0 "Standard" 1 "Erweitert"; +VAL_ 279 AWV2_Freigabe 0 "keine_Freigabe" 1 "Freigabe"; +VAL_ 279 AWV1_HBA_Param 0 "Defaultparametersatz" 1 "Parametersatz_mit_leicht_erhoehter_Empfindlichkeit" 2 "Parametersatz_mit_erhoehter_Empfindlichkeit" 3 "Parametersatz_mit_hoechster_Empfindlichkeit"; +VAL_ 279 AWV2_Priowarnung 0 "Anzeige_Verlassen_der_Fahrspur_wird_nicht_unterdrueckt" 1 "Anzeige_Verlassen_der_Fahrspur_wird_unterdrueckt"; +VAL_ 279 ANB_CM_Anforderung 0 "keine_Anforderung" 1 "Anforderung_aktiv"; +VAL_ 279 ANB_Info_Teilbremsung 0 "Auspraegung_Standard" 1 "Auspraegung_Erweitert"; +VAL_ 279 ANB_Notfallblinken 0 "kein_ANB_Notfallblinken" 1 "Notfallblinken_ANB_angefordert"; +VAL_ 279 ANB_Teilbremsung_Freigabe 0 "Teilbremsung_nicht_freigegeben" 1 "Teilbremsung_freigegeben"; +VAL_ 279 ANB_Zielbremsung_Freigabe 0 "Zielbremsung_nicht_freigegeben" 1 "Zielbremsung_freigegeben"; +VAL_ 279 AWV_Vorstufe 0 "keine_Notbremsung_erwartet" 1 "Notbremsung_in_Kuerze"; +VAL_ 279 AWV_Halten 0 "keine_Anforderung" 1 "Anforderung_das_Fzg_im_Stillstand_zu_halten"; +VAL_ 279 AWV_CityANB_Auspraegung 0 "autom_Bremsung_im_ges_vBereich" 1 "autom_Bremsung_im_def_vBereich"; +VAL_ 279 PCF_Freigabe 0 "keine_Freigabe_PreCrashFront" 1 "Freigabe_PreCrashFront"; +VAL_ 279 AWV1_ECD_Anlauf 0 "ECD_Anlauf_nicht_aktivieren" 1 "ECD_Anlauf_aktivieren"; +VAL_ 279 PCF_Time_to_collision 255 "Objektstatus=0x0__oder_berechneter_TTC_Wert_groesser_als_Maximalwert"; +VAL_ 288 TSK_Status 0 "init" 1 "disabled" 2 "enabled" 3 "regulating" 4 "accel_pedal_override" 5 "brake_only" 6 "temp_fault" 7 "perm_fault"; +VAL_ 290 ACC_limitierte_Anfahrdyn 0 "keine_Limitierung" 1 "Limitierung_Anfahrdynamik_angefordert"; +VAL_ 290 ACC_nachtr_Stopp_Anf 0 "nicht_angefordert" 1 "angefordert"; +VAL_ 290 ACC_StartStopp_Info 0 "Motorlauf_langfristig_nicht_notwendig_Stoppfreigabe" 1 "Motoranlauf_nicht_zwingend_notwendig_Stoppverbot_keine_Startanforderung" 2 "Motoranlauf_zwingend_notwendig_Startanforderung" 3 "Systemfehler"; +VAL_ 290 ACC_Sollbeschleunigung_02 2046 "Neutralwert" 2047 "Fehler"; +VAL_ 290 ACC_Anfahren 0 "keine_Anforderung_Anfahren" 1 "Anforderung_Anfahren"; +VAL_ 290 ACC_Anhalten 0 "kein_Anhalten_gewuenscht" 1 "Anhalten_gewuenscht"; +VAL_ 290 ACC_Typ 0 "Basis_ACC" 1 "ACC_mit_FollowToStop" 2 "ACC_mit_StopAndGo" 3 "ACC_nicht_codiert"; +VAL_ 290 ACC_Status_ACC 0 "ACC_OFF_Hauptschalter_aus" 1 "ACC_INIT" 2 "ACC_STANDBY" 3 "ACC_AKTIV_regelt" 4 "ACC_OVERRIDE" 5 "ACC_Abschaltreaktion" 6 "reversibler_Fehler_im_ACC_System" 7 "irreversibler_Fehler_im_ACC_System"; +VAL_ 290 ACC_Minimale_Bremsung 0 "Anforderung_Minimale_Bremsung_nicht_aktiv" 1 "Anforderung_Minimale_Bremsung_aktiv"; +VAL_ 294 EA_ACC_Sollstatus 0 "Init" 1 "ACC_aktivieren" 2 "ACC_deaktivieren"; +VAL_ 294 EA_Ruckprofil 0 "Init" 1 "Profil_1" 2 "Profil_2" 3 "Profil_3" 4 "Profil_4" 5 "Profil_5" 6 "Profil_6" 7 "Profil_7"; +VAL_ 294 HCA_01_Sendestatus 0 "HCA_sendet_mit_1000ms" 1 "HCA_sendet_mit_20ms"; +VAL_ 294 HCA_01_LM_OffSign 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen"; +VAL_ 294 HCA_01_Status_HCA 0 "deaktiviert" 1 "reserviert" 2 "reserviert" 3 "funktionsbereit" 4 "reserviert" 5 "HCA_Momenteneingriff_1" 6 "MA_Aktiv" 7 "HCA_Momenteneingriff_2" 8 "reserviert" 9 "reserviert" 10 "reserviert" 11 "reserviert" 12 "reserviert" 13 "reserviert" 14 "reserviert" 15 "reserviert"; +VAL_ 294 EA_Ruckfreigabe 0 "keine_Freigabe" 1 "Freigabe"; +VAL_ 294 EA_ACC_Wunschgeschwindigkeit 1023 "Init"; +VAL_ 302 ACC_Anhalteweg 2046 "Neutralwert" 2047 "Fehler"; +VAL_ 302 ACC_Anhalten 0 "kein_Anhalten_gewuenscht" 1 "Anhalten_gewuenscht"; +VAL_ 302 ACC_Freilauf_Anf 0 "keine Freilauf-Anforderung" 1 "Freilauf-Anforderung"; +VAL_ 302 ACC_Freilauf_Info 0 "Freilauf_freigegeben" 1 "kein_Uebergang_in_Freilauf_zulaessig" 2 "Freilauf_nicht_freigegeben" 3 "Freilauf_Anforderung"; +VAL_ 302 ACC_Anforderung_HMS 0 "keine_Anforderung" 1 "halten" 2 "parken" 3 "halten_Standby" 4 "anfahren" 5 "Loesen_ueber_Rampe"; +VAL_ 302 ACC_Anfahren 0 "keine_Anforderung_Anfahren" 1 "Anforderung_Anfahren"; +VAL_ 302 ACC_Folgebeschl 254 "Neutralwert"; +VAL_ 302 ACC_Sollbeschleunigung_02 2046 "Neutralwert" 2047 "Fehler"; +VAL_ 391 RegenBrakingMode 0 "default" 1 "B1" 2 "B2" 3 "B3"; +VAL_ 391 GearPosition 2 "P" 3 "R" 4 "N" 5 "D" 6 "D"; +VAL_ 679 ACC_Regelgeschw 1023 "keine_Anzeige"; +VAL_ 679 ACC_Einheit_maxSetzgeschw 0 "kmh" 1 "mph"; +VAL_ 679 ACC_maxSetzgeschw 511 "Init_Neutralwert"; +VAL_ 679 ACC_minRegelgeschw 255 "keine_Anzeige"; +VAL_ 679 ACC_maxRegelgeschw 255 "keine_Anzeige"; +VAL_ 679 ACC_Tempolimitassistent 0 "keine_Anzeige" 1 "Tempolimitassistent_aktiv" 2 "Tempolimitassistent_nicht_verfuegbar" 3 "Tempolimitassistent_Fahreruebernahme"; +VAL_ 679 ACC_Kurvenassistent 0 "keine_Anzeige" 1 "Kreuzung" 2 "Rechtskurve" 3 "Linkskurve" 4 "Kreisverkehr"; +VAL_ 679 ACC_RUV 0 "keine_Anzeige" 1 "RUV_aktiv_Rechtsverkehr" 2 "RUV_aktiv_Linksverkehr"; +VAL_ 679 ACC_Tachokranz 0 "Tachokranz_nicht_beleuchtet" 1 "Tachokranz_beleuchtet"; +VAL_ 679 ACC_Typ_Tachokranz_unten 0 "LEDs_an" 1 "LEDs_aus"; +VAL_ 679 ACC_ENG_Texte 0 "keine_Anzeige" 1 "keine_Laenderverfuegbarkeit" 2 "nicht_verfuegbar" 3 "Geschwindigkeitsgrenze"; +VAL_ 681 AWV_Warnung 0 "keine_Anzeige" 1 "latente_Vorwarnung" 2 "Vorwarnung" 3 "Akutwarnung" 4 "Eingriff" 5 "Fahreruebernahmeaufforderung" 6 "Abbiegewarnung"; +VAL_ 681 AWV_Texte 0 "keine_Anzeige" 1 "Systemstoerung" 2 "keine_Sensorsicht" 3 "Demomodus" 4 "System_aus" 5 "nicht_definiert" 6 "ESC_aus" 7 "zurzeit_eingeschraenkt"; +VAL_ 681 AWV_Status_Anzeige 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar"; +VAL_ 681 AWV_Einstellung_System_FSG 0 "deaktiviert" 1 "aktiviert"; +VAL_ 681 AWV_Einstellung_Warnung_FSG 0 "Aus" 1 "Setting_2" 2 "Setting_3" 3 "Setting_4" 4 "Setting_5" 5 "Ein"; +VAL_ 681 AWV_Warnlevel 0 "keine_Gefaehrdung" 63 "max_Gefaehrdung"; +VAL_ 780 ACC_Wunschgeschw_02 1023 "keine_Anzeige"; +VAL_ 780 ACC_Status_Prim_Anz 0 "Symbol nicht beleuchtet" 1 "Farbe 1 (typisch 'gruen')" 2 "Farbe 2 (typisch 'rot')" 3 "Farbe 3 (typisch 'gelb')"; +VAL_ 780 ACC_Abstandsindex 0 "Sonderanzeige_graue_Fahrbahn" 1022 "Sonderanzeige_graue_Fahrbahn" 1023 "Sonderanzeige_Fahrbahn_mit_gruenem_roten_Bereich"; +VAL_ 780 ACC_Akustik_02 0 "keine_Akustik" 1 "hochpriore_Akustik" 2 "niederpriore_Akustik" 3 "hochpriore_Dauerakustik"; +VAL_ 780 ACC_Warnung_Verkehrszeichen_1 0 "keine_Warnung_Initialwert" 1 "Warnung"; +VAL_ 780 ACC_Gesetzte_Zeitluecke 0 "keine_Anzeige" 1 "Zeitluecke_1" 2 "Zeitluecke_2" 3 "Zeitluecke_3" 4 "Zeitluecke_4" 5 "Zeitluecke_5" 6 "nicht_definiert" 7 "nicht_definiert"; +VAL_ 780 ACC_Optischer_Fahrerhinweis 0 "optischer_Fahrerhinweis_AUS" 1 "optischer_Fahrerhinweis_EIN"; +VAL_ 780 ACC_Typ_Tachokranz 0 "Tachokranz_lang" 1 "Tachokranz_kurz"; +VAL_ 780 ACC_Anzeige_Zeitluecke 0 "Anzeige_Zeitluecke_nicht_angefordert" 1 "Anzeige_Zeitluecke_angefordert"; +VAL_ 780 ACC_Tachokranz 0 "Tachokranz_nicht_beleuchtet" 1 "Tachokranz_beleuchtet"; +VAL_ 780 ACC_Display_Prio 0 "hoechste_Prio" 1 "mittlere_Prio" 2 "geringe_Prio" 3 "keine_Prio"; +VAL_ 780 ACC_Relevantes_Objekt 0 "Symbol_nicht_beleuchtet" 1 "Farbe_1_typisch_gruen" 2 "Farbe_2_typisch_rot" 3 "Farbe_3_typisch_gelb"; +VAL_ 780 ACC_Texte_Primaeranz 0 "keine Anzeige" 1 "ACC nicht verfuegbar !" 2 "Auto_Auto_ _ _" 3 "Auto_ _Auto_ _" 4 "Auto_ _ _Auto_" 5 "Auto_ _ _ _Auto" 6 "Auto_Auto_ _ _ Gong (durchgestrichen)" 7 "Auto_ _Auto_ _ Gong (durchgestrichen)" 8 "Auto_ _ _Auto_ Gong (durchgestrichen)" 9 "Auto_ _ _ _Auto Gong (durchgestrichen)" 10 "ACC bereit" 11 "keine Abstandsregelung" 12 "ACC Sensor Sicht !" 13 "ACC nicht verfuegbar" 14 "o o o" 15 "Hochschalten" 16 "ESP Eingriff" 17 "Herunterschalten" 18 "Parkbremse !" 19 "Geschwindigkeitsgrenze" 20 "Waehlhebelposition !" 21 "VDA ACC-Symbol YYY km/h / mph" 22 "Tempolimit XXX km/h / mph" 23 "Kurve XXX km/h / mph" 24 "ACC Abschaltung" 25 "Symbol 'Eieruhr'" 26 "!" 27 "--- km/h / mph" 28 "XXX km/h / mph (Schriftart 2)" 29 "Lenkradwinkel" 30 "Anfahren bestaetigen" 31 "Fahrzeug verloren" 32 "Im Stand nicht moeglich" 33 "Ungueltiger Anfahrbefehl" 34 "Tuer offen !" 35 "Fahrer Gurtschloss offen !" 36 "Schalthebelposition !" 37 "Drehzahl !" 38 "Kurvenassistent aus" 39 "Tempolimit aus" 40 "Abbiegeassistent" 41 "Ortsanfang XXX km/h / mph" 42 "Ortsende XXX km/h / mph" 43 "Tempolimit Ende XXX km/h / mph" 44 "HDC aktiv" 45 "braking guard Bremsruck" 46 "braking guard aus" 47 "braking guard aus" 48 "Uebernehmen !" 49 "Steigung zu gross" 50 "Stehendes Objekt voraus" 51 "SET / 'GRA Symbol'___xxx km/h / mph" 52 "SET / 'GRA Symbol' xxx km/h / mph" 53 "ACC aus" 54 "ACC startet" 55 "ACC reinigen" 56 "ACC Fehler" 57 "ACC haelt an !" 58 "Bremse betaetigen !" 59 "Kupplung betaetigt" 60 "LIM AUS" 61 "LIM AKTIV" 62 "LIM PASSIV" 63 "LIM FEHLER" 64 "Bremse ueberhitzt !" 65 "Bremse haelt !" 66 "ESP PASSIV !" 67 "ACC_anfahrbereit" 68 "Gang_einlegen" 69 "Rechtsueberholen_verhindert" 70 "Linksueberholen_verhindert" 71 "Achtung_Geschwindigkeitsueberschreitung" 72 "Tempolimit_und_Kurvenassistent_nicht_verfuegbar"; +VAL_ 780 ACC_Wunschgeschw_erreicht 0 "Wunschgeschwindigkeit_nicht_erreicht" 1 "Wunschgeschwindigkeit_erreicht"; +VAL_ 780 ACC_Typ_Tachokranz_unten 0 "LEDs_an" 1 "LEDs_aus"; +VAL_ 780 ACC_Status_Anzeige 0 "ACC_GRA_Hauptschalter_aus" 1 "ACC_in_Init_nicht_bei_GRA" 2 "ACC_GRA_passiv" 3 "ACC_GRA_aktiv" 4 "ACC_GRA_im_Hintergrund_uebertreten" 5 "ACC_GRA_Abschaltreaktion" 6 "ACC_reversibel_aus_nicht_bei_GRA" 7 "ACC_GRA_irreversibel_aus"; +VAL_ 804 ACC_Texte_Sekundaeranz 0 "keine_Anzeige" 1 "Zielfahrzeug_erkannt" 2 "Rechtskurve_voraus" 3 "Linkskurve_voraus" 4 "Tempolimit_voraus" 5 "Sensorsicht" 6 "Anfahrbereit" 7 "Tempolimit_erkannt" 8 "Kreuzung_voraus" 9 "Kreisverkehr_voraus"; +VAL_ 804 ACC_Texte_Zusatzanz 0 "keine_Anzeige" 1 "ACC_AUS" 2 "ACC_BEREIT" 3 "UEBERTRETEN" 4 "ABSTAND" 5 "DISTANZ_1" 6 "DISTANZ_2" 7 "DISTANZ_3" 8 "DISTANZ_4" 9 "DISTANZ_1__dyn" 10 "DISTANZ_2__dyn" 11 "DISTANZ_3__dyn" 12 "DISTANZ_4__dyn" 13 "DISTANZ_1__stand" 14 "DISTANZ_2__stand" 15 "DISTANZ_3__stand" 16 "DISTANZ_4__stand" 17 "DISTANZ_1__comf" 18 "DISTANZ_2__comf" 19 "DISTANZ_3__comf" 20 "DISTANZ_4__comf" 21 "DISTANZ_1__efficiency" 22 "DISTANZ_2__efficiency" 23 "DISTANZ_3__efficiency" 24 "DISTANZ_4__efficiency" 25 "DISTANZ_5" 26 "DISTANZ_5__dyn" 27 "DISTANZ_5__stand" 28 "DISTANZ_5__comf" 29 "DISTANZ_5__efficiency" 30 "ACHTUNG" 31 "Abstandsanzeige" 32 "Abstandsanz_Warnung_aktiviert"; +VAL_ 804 ACC_Status_Zusatzanz 0 "keine Anzeige" 1 "Bild 1 (Fzg. Silhouette, typ. farblos)" 2 "Bild 2 (Fzg. Farbe 1, typ. grau)" 3 "Bild 3 (Fzg. Farbe 2, typ. rot)" 4 "Bild 4 (Symbol 1 ACCplus, typ. Doppelfzg. gelb)" 5 "Bild 5 (Symbol 2 ACCplus, typ. Doppelfzg. grau)" 6 "Bild 6 (Fzg. Farbe 2, typ. rot) mit Priorität im Kombi (Pop-up)"; +VAL_ 804 ACC_Texte 0 "keine_Anzeige" 1 "ACC_nicht_verfuegbar" 2 "ACC_und_AWV_nicht_verfuegbar" 3 "ACC_keine_Sensorsicht" 4 "ACC_und_AWV_keine_Sensorsicht" 5 "ACC_Steigung_zu_gross" 6 "ACC_nur_in_Fahrstufe_verfuegbar" 7 "ACC_Parkbremse_betaetigt" 8 "ACC_ESP_Eingriff" 9 "ACC_Bitte_uebernehmen" 10 "ACC_HDC_betaetigt" 11 "ACC_Geschwindigkeitsgrenze" 12 "ACC_Schalthebelposition" 13 "ACC_Drehzahl" 14 "ACC_Kupplung_betaetigt" 15 "ACC_Aktivierverhinderung" 16 "ACC_Abschaltung" 17 "ACC_Parkassistent_aktiv" 18 "ACC_ESC_aus" 19 "ACC_Charisma_Modus_inkompatibel" 20 "ACC_Stehendes_Objekt_voraus" 21 "ACA_Fahreruebernahme" 22 "ACA_Querfuehrung_nicht_verfuegbar"; +VAL_ 804 ACC_Texte_braking_guard 0 "keine_Anzeige" 1 "AWV_aus" 2 "AWV_Warnung" 3 "AWV_Demomodus" 4 "AWV_Systemstoerung" 5 "AWV_Eingriff" 6 "AWV_Vorwarnung_aus" 7 "AWV_keine_Sensorsicht"; +VAL_ 804 ACC_Warnhinweis 0 "kein_Warnhinweis" 1 "Warnhinweis"; +VAL_ 804 ACC_Zeitluecke_Abstandswarner 61 "Freifahrt" 62 "nicht_definiert" 63 "keine_Anzeige"; +VAL_ 804 ACC_Abstand_Abstandswarner 509 "Freifahrt" 510 "nicht_definiert" 511 "keine_Anzeige"; +VAL_ 804 ACC_Tempolimit 0 "keine_Anzeige" 1 "5_zulHoechstgeschw" 2 "7_zulHoechstgeschw" 3 "10_zulHoechstgeschw" 4 "15_zulHoechstgeschw" 5 "20_zulHoechstgeschw" 6 "25_zulHoechstgeschw" 7 "30_zulHoechstgeschw" 8 "35_zulHoechstgeschw" 9 "40_zulHoechstgeschw" 10 "45_zulHoechstgeschw" 11 "50_zulHoechstgeschw" 12 "55_zulHoechstgeschw" 13 "60_zulHoechstgeschw" 14 "65_zulHoechstgeschw" 15 "70_zulHoechstgeschw" 16 "75_zulHoechstgeschw" 17 "80_zulHoechstgeschw" 18 "85_zulHoechstgeschw" 19 "90_zulHoechstgeschw" 20 "95_zulHoechstgeschw" 21 "100_zulHoechstgeschw" 22 "110_zulHoechstgeschw" 23 "120_zulHoechstgeschw" 24 "130_zulHoechstgeschw" 25 "140_zulHoechstgeschw" 26 "150_zulHoechstgeschw" 27 "160_zulHoechstgeschw" 28 "200_zulHoechstgeschw" 30 "250_zulHoechstgeschw" 31 "Ende_zulHoechstgeschw"; +VAL_ 804 ACC_Charisma_FahrPr 0 "keine_Funktion" 1 "Programm_1" 2 "Programm_2" 3 "Programm_3" 4 "Programm_4" 5 "Programm_5" 6 "Programm_6" 7 "Programm_7" 8 "Programm_8" 9 "Programm_9" 10 "Programm_10" 11 "Programm_11" 12 "Programm_12" 13 "Programm_13" 14 "Programm_14" 15 "Programm_15"; +VAL_ 804 ACC_Charisma_Status 0 "Init" 1 "verfuegbar" 2 "nicht_verfuegbar" 3 "asynchron_durch_Fahrerwunsch"; +VAL_ 804 ACC_Texte_Abstandswarner 0 "keine_Anzeige" 1 "Systemstoerung" 2 "keine_Sensorsicht" 3 "zurzeit_eingeschraenkt"; +VAL_ 870 Fast_Send_Rate_Active 0 "1 Hz" 1 "50 Hz"; +VAL_ 1720 KBI_Variante_USA 0 "keine USA-Variante" 1 "USA-Variante"; +VAL_ 1720 KBI_Variante 0 "Zeiger Kombiinstrument" 1 "Volldisplay Kombiinstrument"; +VAL_ 1720 KBI_BCmE_aktiv 0 "Anzeige_nicht_aktiv" 1 "Anzeige_aktiv"; +VAL_ 1720 KBI_Sparhinweis_quittiert 0 "nicht_quittiert" 1 "quittiert"; +VAL_ 1720 KBI_Tankfuellstand_Prozent 126 "Init" 127 "Fehler"; +VAL_ 1720 KBI_Nachtanken_erkannt 0 "Geberbetrieb" 1 "Nachtankmodus"; +VAL_ 1720 KBI_Tankinhalt_hochaufl 16382 "Init" 16383 "Fehler"; +VAL_ 1720 KBI_Max_Tankinhalt 254 "Init" 255 "Fehler"; diff --git a/opendbc_repo/opendbc/dbc/vw_pq.dbc b/opendbc_repo/opendbc/dbc/vw_pq.dbc new file mode 100644 index 0000000000..28a42a6471 --- /dev/null +++ b/opendbc_repo/opendbc/dbc/vw_pq.dbc @@ -0,0 +1,1828 @@ +VERSION "" + + +NS_ : + NS_DESC_ + CM_ + BA_DEF_ + BA_ + VAL_ + CAT_DEF_ + CAT_ + FILTER + BA_DEF_DEF_ + EV_DATA_ + ENVVAR_DATA_ + SGTYPE_ + SGTYPE_VAL_ + BA_DEF_SGTYPE_ + BA_SGTYPE_ + SIG_TYPE_REF_ + VAL_TABLE_ + SIG_GROUP_ + SIG_VALTYPE_ + SIGTYPE_VALTYPE_ + +BS_: + +BU_: XXX + + +BO_ 1394 ZAS_1: 2 XXX + SG_ Fehlerspeichereintrag__ZAS_ : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_ZAS_1_3 : 8|7@1+ (1,0) [0|0] "" XXX + SG_ Frei_ZAS_1_2 : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_15_SV : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_ZAS_1_1 : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_P__Parklichtstellung_ : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_50__Starten_ : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_X__Startvorgang_ : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_15__Z_ndung_ein_ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ S_Kontakt__Schl_ssel_steckt_ : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1336 Wischer_1: 2 XXX + SG_ Blockierung_Heckwischer_erkannt : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Wischer_1_2 : 12|3@1+ (1,0) [0|0] "" XXX + SG_ Fehlerspeichereintrag__Wischer_ : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Scheibenwischer_Hec : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Wascher_Heck : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Scheibenwischer_Heck_eingeschal : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Blockierung_Frontwischer_erkann : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Wischer_1_1 : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Status_Waschduesenheizung : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Parklage_Frontwischer : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Frontwischer_Schnel : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Frontwischer_Normal : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Wascher_Front : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Frontwischer__eingeschaltet : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1464 WFS_1: 2 XXX + SG_ WFS_Textbits : 8|8@1+ (1,0) [0|0] "" XXX + SG_ Frei_WFS_1_1 : 1|7@1+ (1,0) [0|0] "" XXX + SG_ WFS_LED : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1096 Waehlhebel_1: 4 XXX + SG_ Frei_Waehlhebel_1_1 : 29|3@1+ (1,0) [0|0] "" XXX + SG_ Test_aktiv_Flag : 28|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_Waehlhebel_1 : 24|4@1+ (1,0) [0|15] "" XXX + SG_ Waehlhebel_Testergebnis : 16|8@1+ (1,0) [0|255] "" XXX + SG_ Fehler_Waehlhebel : 8|8@1+ (1,0) [0|0] "" XXX + SG_ Waehlhebelposition : 4|4@1+ (1,0) [0|0] "" XXX + SG_ Waehlhebel_Initialisierung : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Shiftlock_Position : 0|3@1+ (1,0) [0|0] "" XXX + +BO_ 1496 Verbauliste_1: 8 XXX + SG_ TV_Tuner : 63|1@1+ (1,0) [0|0] "" XXX + SG_ DSP : 62|1@1+ (1,0) [0|0] "" XXX + SG_ CD_Wechsler : 61|1@1+ (1,0) [0|0] "" XXX + SG_ Spracheingabe : 60|1@1+ (1,0) [0|0] "" XXX + SG_ Telematik : 59|1@1+ (1,0) [0|0] "" XXX + SG_ Navigation : 58|1@1+ (1,0) [0|0] "" XXX + SG_ Telefon : 57|1@1+ (1,0) [0|0] "" XXX + SG_ Radio : 56|1@1+ (1,0) [0|0] "" XXX + SG_ MMI_vorne : 55|1@1+ (1,0) [0|0] "" XXX + SG_ MMI_hinten : 54|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Verbauliste_1_11 : 53|1@1+ (1,0) [0|0] "" XXX + SG_ Klimabedienteil_HL : 52|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Verbauliste_1_10 : 50|2@1+ (1,0) [0|0] "" XXX + SG_ Tankgeber : 49|1@1+ (1,0) [0|0] "" XXX + SG_ Assistenzfahrlicht : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Memory_hinter_Fahrer : 47|1@1+ (1,0) [0|0] "" XXX + SG_ Sitzmemory_hinten : 46|1@1+ (1,0) [0|0] "" XXX + SG_ Sitzmemory_Beifahrer : 45|1@1+ (1,0) [0|0] "" XXX + SG_ Anh_ngersteuergeraet : 44|1@1+ (1,0) [0|0] "" XXX + SG_ Energiemanagement : 43|1@1+ (1,0) [0|0] "" XXX + SG_ Wischermodul : 42|1@1+ (1,0) [0|0] "" XXX + SG_ EZS___Kessy__Komfort_ : 41|1@1+ (1,0) [0|0] "" XXX + SG_ Verdecksteuergeraet : 40|1@1+ (1,0) [0|0] "" XXX + SG_ Standheizung : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Verbauliste_1_9 : 38|1@1+ (1,0) [0|0] "" XXX + SG_ Einparkhilfe : 37|1@1+ (1,0) [0|0] "" XXX + SG_ Klimasteuergeraet_Komfort : 36|1@1+ (1,0) [0|0] "" XXX + SG_ Gateway : 35|1@1+ (1,0) [0|0] "" XXX + SG_ Lenksaeulenmodul : 34|1@1+ (1,0) [0|0] "" XXX + SG_ Reifendruck : 33|1@1+ (1,0) [0|0] "" XXX + SG_ Kombiinstrument_Komfort : 32|1@1+ (1,0) [0|0] "" XXX + SG_ Dachmodul : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Memory : 30|1@1+ (1,0) [0|0] "" XXX + SG_ TSG_HR : 29|1@1+ (1,0) [0|0] "" XXX + SG_ TSG_HL : 28|1@1+ (1,0) [0|0] "" XXX + SG_ TSG_BT : 27|1@1+ (1,0) [0|0] "" XXX + SG_ TSG_FT : 26|1@1+ (1,0) [0|0] "" XXX + SG_ ZKE : 25|1@1+ (1,0) [0|0] "" XXX + SG_ BSG_Komfort : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Verbauliste_1_8 : 19|5@1+ (1,0) [0|0] "" XXX + SG_ Stabi_Entkopplung : 18|1@1+ (1,0) [0|0] "" XXX + SG_ Waehlhebel : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Batteriemanager : 16|1@1+ (1,0) [0|0] "" XXX + SG_ Daempfer_SG : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Niveauregulierung : 14|1@1+ (1,0) [0|0] "" XXX + SG_ EZS___Kessy__Antrieb_ : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Bremsbooster : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Antrieb : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Einspritzpumpe : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkwinkel : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Allrad : 7|1@1+ (1,0) [0|0] "" XXX + SG_ BSG_Antrieb : 6|1@1+ (1,0) [0|0] "" XXX + SG_ ADR : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Airbag : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Climatronic_Antrieb : 3|1@1+ (1,0) [0|0] "" XXX + SG_ ABS : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Getriebesteuergeraet : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Motorsteuergeraet : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1488 Systeminfo_1: 6 XXX + SG_ CAN_Stand_4_1_Antrieb_Daten_Hau : 44|4@1+ (1,0) [0|15] "" XXX + SG_ CAN_Stand_4_1_Antrieb_Daten_Neb : 40|4@1+ (1,0) [0|15] "" XXX + SG_ CAN_Stand_4_1_Komfort_Daten_Hau : 36|4@1+ (1,0) [0|15] "" XXX + SG_ CAN_Stand_4_1_Komfort_Daten_Neb : 32|4@1+ (1,0) [0|15] "" XXX + SG_ Frei_Systeminfo_1_6 : 30|1@1+ (1,0) [0|0] "" XXX + SG_ Viertuerer : 29|1@1+ (1,0) [0|0] "" XXX + SG_ Rechtslenker : 28|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrzeug_Index : 24|4@1+ (1,0) [0|0] "" XXX + SG_ Fahrzeug_Generation : 20|4@1+ (1,0) [0|15] "" XXX + SG_ Fahrzeug_Derivat : 16|4@1+ (1,0) [0|15] "" XXX + SG_ Fahrzeug_Marke_2 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Fahrzeug_Klasse : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Verbauinformation_gueltig : 7|1@1+ (1,0) [0|0] "" XXX + SG_ CAN_Infotainment_verbaut : 6|1@1+ (1,0) [0|0] "" XXX + SG_ CAN_Infotainment_in_Diagnose : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Sleep_CAN_Infotainment : 4|1@1+ (1,0) [0|0] "" XXX + SG_ CAN_Komfort_in_Diagnose : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Sleep_CAN_Komfort : 2|1@1+ (1,0) [0|0] "" XXX + SG_ CAN_Antrieb_in_Diagnose : 1|1@1+ (1,0) [0|0] "" XXX + SG_ CAN_Extern_zugeschaltet : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 268 Slave_1: 8 XXX + SG_ Delta_reduziertes_Sollmoment : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Delta_Drosselklappenwinkel : 32|16@1+ (1,0) [0|0] "" XXX + SG_ Frei_Slave_1_1 : 25|7@1+ (1,0) [0|0] "" XXX + SG_ Delta_Zuendwinkelausgabe : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Ubat_Freigabe_DVE__Slave_ : 23|1@1+ (1,0) [0|0] "" XXX + SG_ Drosselklappe_Sollwertbegrenzun : 22|1@1+ (1,0) [0|0] "" XXX + SG_ Einspritzverbot_lernen__Slave_ : 21|1@1+ (1,0) [0|0] "" XXX + SG_ Master_erkannt__Slave_ : 20|1@1+ (1,0) [0|0] "" XXX + SG_ Fehler_Momentenausgabe : 19|1@1+ (1,0) [0|0] "" XXX + SG_ Fehler_Getriebe_Moment : 18|1@1+ (1,0) [0|0] "" XXX + SG_ Fehler_Bremsenbotschaft : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Indiziertes_Istmoment__Slave_ : 0|16@1+ (0.0015259,0) [0|99.998] "%" XXX + SG_ Timeout_Bremsenbotschaft : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1332 Sitz_info: 2 XXX + SG_ Positionserkennung_Beifahrersit : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Beifahrersitz_im_vorderen_Dritt : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Positionserkennung_Fahrersitz_u : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrersitz_im_vorderen_Drittel : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_Sitzinfo : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Checksumme_Sitzinfo : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1810 PSG_3: 2 XXX + SG_ Selbsttestergebnis : 0|16@1+ (1,0) [0|0] "" XXX + +BO_ 1298 PSG_2: 8 XXX + SG_ RAM_Inhalt_4 : 48|16@1+ (1,0) [0|0] "" XXX + SG_ RAM_Inhalt_3 : 32|16@1+ (1,0) [0|0] "" XXX + SG_ RAM_Inhalt_2 : 16|16@1+ (1,0) [0|0] "" XXX + SG_ RAM_Inhalt_1 : 0|16@1+ (1,0) [0|0] "" XXX + +BO_ 274 PSG_1: 8 XXX + SG_ Pumpentemperatur__2_1_ : 48|16@1+ (0.0625,0) [0|4096] "K" XXX + SG_ Pumpentemperatur__3_2_2_ : 44|12@1+ (1,0) [0|0] "" XXX + SG_ Zylinderzaehler__3_2_2_ : 43|3@1+ (1,0) [1|8] "Zaehler" XXX + SG_ Ansteuerdauer__3_2_2_ : 32|11@1+ (0.0469,0) [0|96] "NW" XXX + SG_ Nockenwellendrehzahl__3_2_2_ : 20|12@1+ (4,0) [0|16380] "upm" XXX + SG_ Pumpen_Statuswort__3_2_2_ : 0|20@1+ (1,0) [0|0] "" XXX + +BO_ 1300 NOX_1: 8 XXX + SG_ OBD_fuer_NOX : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Frei_NOX1_4 : 53|3@1+ (1,0) [0|0] "" XXX + SG_ IP2 : 52|1@1+ (1,0) [0|0] "" XXX + SG_ IP1 : 51|1@1+ (1,0) [0|0] "" XXX + SG_ IP0 : 50|1@1+ (1,0) [0|0] "" XXX + SG_ Sondenheizung_NOX : 49|1@1+ (1,0) [0|0] "" XXX + SG_ Offsetkorrektur_NOX : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_NOX1_3 : 43|5@1+ (1,0) [0|0] "" XXX + SG_ Sauerstoff_binaer : 32|11@1+ (1,-200) [-200|1847] "mV" XXX + SG_ Frei_NOX1_2 : 27|5@1+ (1,0) [0|0] "" XXX + SG_ Sauerstoff_linear : 16|11@1+ (1,0) [0|2047] "1000/Lambd" XXX + SG_ Frei_NOX1_1 : 11|5@1+ (1,0) [0|0] "" XXX + SG_ NOX_Signal : 0|11@1+ (1,0) [0|2047] "ppm" XXX + +BO_ 1424 Niveau_1: 6 XXX + SG_ Beladungszustand : 40|8@1+ (1,0) [0|253] "Zuladung" XXX + SG_ Fehlerspeichereintrag__Niveau_1 : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Systemstatus__Niveau_1_ : 38|1@1+ (1,0) [0|0] "" XXX + SG_ Reserve_Fahrzeugart : 37|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrzeugart_Niveau : 36|1@1+ (1,0) [0|0] "" XXX + SG_ Textbits__Niveau_1_ : 32|4@1+ (1,0) [0|0] "" XXX + SG_ Verstellung_HL : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Verstellung_HR : 30|1@1+ (1,0) [0|0] "" XXX + SG_ Verstellung_VL : 29|1@1+ (1,0) [0|0] "" XXX + SG_ Verstellung_VR : 28|1@1+ (1,0) [0|0] "" XXX + SG_ Absenkung_Fahrzeug : 27|1@1+ (1,0) [0|0] "" XXX + SG_ Anhebung_Fahrzeug : 26|1@1+ (1,0) [0|0] "" XXX + SG_ Verstellung_aktiv : 25|1@1+ (1,0) [0|0] "" XXX + SG_ Kompressorlauf_in_Kuerze : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Niveau_1_5 : 23|1@1+ (1,0) [0|0] "" XXX + SG_ Taster_Niveau : 22|1@1+ (1,0) [0|0] "" XXX + SG_ Parkniveau : 21|1@1+ (1,0) [0|0] "" XXX + SG_ Zwischenniveau : 20|1@1+ (1,0) [0|0] "" XXX + SG_ Niveaustati : 16|4@1+ (1,0) [0|0] "" XXX + SG_ MSG_Einschraenkung : 15|1@1+ (1,0) [0|0] "" XXX + SG_ ESP_Beeinflussung : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Warnlampe_Niveau_1 : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Niveau_1_1 : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_Niveau_1 : 8|4@1+ (1,0) [0|15] "Zaehler" XXX + SG_ Checksumme_Niveau_1 : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1328 Navigation_1: 7 XXX + SG_ Kreuzungstyp : 54|2@1+ (1,0) [0|3] "" XXX + SG_ Entfernung_bis_Kreuzung : 48|6@1+ (5,0) [0|315] "m" XXX + SG_ Entfernung_bis_Kurvenanfang : 40|8@1+ (1,0) [0|255] "m" XXX + SG_ Voarusliegende_Kurvenrichtung : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Vorausliegender_Kurvenverlauf : 32|7@1+ (50,0) [0|6350] "m" XXX + SG_ Fehler_Navigation : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Anzahl_Fahrbahnen__0_ist_unguel : 28|3@1+ (1,0) [1|7] "" XXX + SG_ Strassentyp : 24|4@1+ (1,0) [0|15] "" XXX + SG_ Laenderkennung : 16|8@1+ (1,0) [0|0] "" XXX + SG_ Vorzeichen_Gierrate______ : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Gierratenfehler : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Gierrate : 0|14@1+ (0.01,0) [0|100] "deg/sek" XXX + +BO_ 1792 MSG_3: 3 XXX + SG_ MSG_Konfiguration : 16|8@1+ (1,0) [0|0] "" XXX + SG_ Lage_des_OT_Impuls : 0|16@1+ (0.01172,-384) [-384|384] "KW" XXX + +BO_ 1280 MSG_2: 8 XXX + SG_ RAM_Adresse_4 : 48|16@1+ (1,0) [0|0] "" XXX + SG_ RAM_Adresse_3 : 32|16@1+ (1,0) [0|0] "" XXX + SG_ RAM_Adresse_2 : 16|16@1+ (1,0) [0|0] "" XXX + SG_ Ram_Adresse_1 : 0|16@1+ (1,0) [0|0] "" XXX + +BO_ 256 MSG_1: 8 XXX + SG_ Kurbelwellendrehzahl__3_2_2_ : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Soll_Foerderbeginn_KW__3_2_2_ : 40|16@1+ (0.01172,-384) [-384|384] "KW" XXX + SG_ Soll_Foerderbeginn_NW__3_2_2_ : 28|12@1+ (0.01172,0) [0|768] "degNW" XXX + SG_ Soll_Voreinspritzung : 16|12@1+ (1,0) [0|0] "" XXX + SG_ Soll_Einspritzmenge : 0|16@1+ (0.03125,0) [0|2047] "mg/H" XXX + +BO_ 1796 Motor_NOX: 8 XXX + SG_ Frei_Motor_NOX_1_2 : 24|40@1+ (1,0) [0|0] "" XXX + SG_ Frei_Motor_NOX_1_1 : 19|5@1+ (1,0) [0|0] "" XXX + SG_ Heizleistungsanforderung : 18|1@1+ (1,0) [0|0] "" XXX + SG_ Offsetkorrektur_moeglich : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Betriebsbereich : 16|1@1+ (1,0) [0|0] "" XXX + SG_ Abgastemperatur_NOX : 8|8@1+ (5,-40) [-40|1230] "C" XXX + SG_ Abgasdruck_NOX : 0|8@1+ (5,600) [600|1870] "mbar" XXX + +BO_ 900 Motor_Momente: 8 XXX + SG_ Momentenangaben_ungenau__Moment : 35|2@1+ (1,0) [0|0] "" XXX + +BO_ 1408 Motor_Flexia: 8 XXX + SG_ Ansaugsystem m0 : 63|1@1+ (1,0) [0|0] "" XXX + SG_ Hubraum m0 : 56|7@1+ (0.1,0) [0|12.7] "l" XXX + SG_ Steigung_der_Befuellungskennlin m1 : 56|8@1+ (0.001,0) [0|0.255] "l/mm" XXX + SG_ Anzahl_Zylinder m0 : 52|4@1+ (1,0) [0|15] "Vent./Zyl." XXX + SG_ Bewertungsfaktor_Russindex_Turb m1 : 50|6@1+ (0.1,0) [0|6.3] "" XXX + SG_ Anzahl_Ventile m0 : 49|3@1+ (1,0) [0|7] "Vent./Zyl." XXX + SG_ Bewertungsfaktor_Verschleissind m1 : 44|6@1+ (0.1,0) [0|6.3] "" XXX + SG_ Hersteller_Code m1 : 40|4@1+ (1,0) [0|15] "" XXX + SG_ Motorleistung m0 : 40|9@1+ (1,0) [0|512] "KW" XXX + SG_ Max_Drehmoment m0 : 32|8@1+ (10,0) [0|2550] "Nm" XXX + SG_ Normierter_Verbrauch m1 : 32|8@1+ (10,0) [0|2550] "l/Zyl." XXX + SG_ Oelniveauschwelle m1 : 24|8@1+ (0.25,0) [0|63.75] "cm" XXX + SG_ Drehzahl_MaxNorm m0 : 24|8@1+ (100,0) [0|25500] "U/min" XXX + SG_ Verschleissindex : 16|8@1+ (1,0) [0|254] "" XXX + SG_ Russindex : 8|8@1+ (1,0) [0|254] "" XXX + SG_ Verbrennungsart : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Motor_Flexia_1 : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Warm_Up_Cycle : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Driving_Cycle : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_Motor_Flexia : 1|3@1+ (1,0) [0|15] "" XXX + SG_ Multiplex_Schalter_Motor_Flexia M : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1416 Motor_7: 8 XXX + SG_ Oltemperatur : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Frei_Motor_7_3 : 40|16@1+ (1,0) [0|0] "" XXX + SG_ Ladedruck : 32|8@1+ (0.01,0) [0|2.54] "bar" XXX + SG_ Vorzeichen_Motordrehzahlgradien : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Motordrehzahlgradient : 24|7@1+ (1,0) [0|126] "U/min" XXX + SG_ Hoeheninfo__Motor_7_ : 16|8@1+ (0.00787,0) [0|2] "" XXX + SG_ Klemme_DFM : 8|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ PTC___Gluehstifte_ausgeschaltet : 5|3@1+ (1,0) [0|0] "" XXX + SG_ Frei_Motor_7_1 : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerspeichereintrag__Motor_7_ : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Statusbit_Geschwindikeitsbegren : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Geschwindigkegrenzung_aktivierb : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Leerlauf_Solldrehzahl_auf_Max_W : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1160 Motor_6: 8 XXX + SG_ Zaehler_Motor_6 : 60|4@1+ (1,0) [0|15] "" XXX + SG_ Frei_Motor_6_4 : 58|2@1+ (1,0) [0|0] "" XXX + SG_ ltemperaturschutz : 57|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_Bremseingriff_Freigabe : 56|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Motor_6_3 : 48|8@1+ (1,0) [0|0] "" XXX + SG_ Ruckmeldung_Momenten : 40|8@1+ (0.39,0) [0|100] "" XXX + SG_ GRA_Sollbeschleunigung : 32|8@1+ (0.024,-3.984) [-3.984|2.112] "m/s2" XXX + SG_ Hoeheninfo__Motor_6_ : 24|8@1+ (0.00787,0) [0|2] "" XXX + SG_ Istmoment_f_r_Getriebe : 16|8@1+ (0.39,0) [0|99] "MDI" XXX + SG_ Sollmoment_f_r_Getriebe : 8|8@1+ (0.39,0) [0|99] "MDI" XXX + SG_ Checksumme_Motor_6 : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1152 Motor_5: 8 XXX + SG_ CHECKSUM : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Motortext_Bits__4_1_ : 52|4@1+ (1,0) [0|0] "" XXX + SG_ Doppelte_Momente : 51|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_Hauptschalter : 50|1@1+ (1,0) [0|0] "" XXX + SG_ Anlasser_Ausspuren : 49|1@1+ (1,0) [0|0] "" XXX + SG_ Anlasser_Freigabe : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Klimadrucksignal__Motor_5_ : 40|8@1+ (0.2,0) [0|50.8] "bar" XXX + SG_ K_hlerluefteransteuerung : 32|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ Verbrauch_Ueberlauf : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Kraftstoffverbrauchssignal : 16|15@1+ (1,0) [0|32767] "ul" XXX + SG_ Klimakompressor_Leistungsreduzi : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Kennfeldkuehlung : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Klimakompressor_aus__Motor_5_ : 13|1@1+ (1,0) [0|0] "" XXX + SG_ CAT_Warnung : 12|1@1+ (1,0) [0|0] "" XXX + SG_ OBD_2_Lampe : 11|1@1+ (1,0) [0|0] "" XXX + SG_ E_Gas_Lampe : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Vorgluehlampe__Motor_5_ : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Ladekontroll_Lampe : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Multiplex_Code M : 6|2@1+ (1,0) [0|0] "" XXX + SG_ Multiplex_Info_norm__Verbrauch m3 : 0|6@1+ (20,0) [0|1260] "l/Zyl" XXX + SG_ Multiplex_Info_Motortyp m2 : 0|6@1+ (1,0) [0|0] "" XXX + SG_ Multiplex_Info_Drehzahl_MD_Max m1 : 0|6@1+ (100,0) [0|6300] "U/min" XXX + SG_ Multiplex_Info_Max_Drehmoment m0 : 0|6@1+ (10,0) [0|630] "Nm" XXX + +BO_ 896 Motor_3: 8 XXX + SG_ Drosselklappenpoti : 56|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ Motor_Wunschdrehzahl : 48|8@1+ (25,0) [0|6350] "U/min" XXX + SG_ Motordrehzahlbeeinflussung : 40|8@1+ (0.392,0) [0|100] "%" XXX + SG_ Kein_Start_Stop : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Kein_E_Gas : 38|1@1+ (1,0) [0|0] "" XXX + SG_ Reserviert_Motor_3_1 : 37|1@1+ (1,0) [0|0] "" XXX + SG_ Vorzeichen_Rad_Wunschmoment : 36|1@1+ (1,0) [0|0] "" XXX + SG_ Rad_Wunschmoment : 24|12@1+ (0.39,0) [0|1597] "MDI" XXX + SG_ Fahrpedal_Rohsignal : 16|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ Ansauglufttemperatur : 8|8@1+ (0.75,-48) [-48|142.5] "" XXX + SG_ Fehlerstatus_Ansauglufttemperat : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Motorsteuerger_t_gesperrt : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Drosselklappenwinkel_ungenau : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrpedalwert_ungenau__Motor_3_ : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Motor_3_1 : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Motor_Wunschdrehzahl_Priorit_t : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Uebertemperaturschutz__Motor_3_ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Vorgluehmeldung : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 648 Motor_2: 8 Motor + SG_ MO2_Mp_Code m : 6|2@1+ (1,0) [0|3] "" Gateway + SG_ MO2_Getr_Code m2 : 0|6@1+ (1,0) [0|63] "" Gateway + SG_ MO2_max_Mo m3 : 0|6@1+ (10,0) [0|630] "Nm" Gateway + SG_ MO2_CAN_Vers m0 : 0|6@1+ (1,0) [0|63] "" Gateway + SG_ MO2_Motor_Code m1 : 0|6@1+ (1,0) [0|63] "" Gateway + SG_ MO2_Kuehlm_T : 8|8@1+ (0.75,-48) [-47.25|142.5] "°C" Gateway + SG_ MO2_BLS : 16|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_BTS : 17|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_Sta_Kuehlm : 18|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_Sta_Klima : 19|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_Sta_No_Bet : 20|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_Status_TSK : 21|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_Sta_GRA : 22|2@1+ (1,0) [0|3] "" ACC,GRA + SG_ TSK_Limiter_ausgewaehlt : 25|1@1+ (1,0) [0|1] "" ACC,GRA + SG_ MO2_GRAregelt : 26|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_Sport_Error : 27|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_OffRoad : 28|1@1+ (1,0) [0|1] "" Gateway + SG_ MO2_RME_Gehalt : 29|3@1+ (12.5,0) [0|75] "%" Gateway + SG_ MO2_GRA_Soll : 32|8@1+ (1.28,0) [0|325.12] "km/h" ACC,GRA + SG_ MO2_LL_Solldz : 40|8@1+ (10,0) [0|2540] "1/min" Gateway + SG_ MO2_Begr_Mo : 48|8@1+ (0.39,0) [0|99.06] "%" Gateway + SG_ MO2_Mo_ZWR : 56|8@1+ (0.39,0) [0|99.06] "%" Gateway + +BO_ 640 Motor_1: 8 XXX + SG_ Fahrerwunschmoment : 56|8@1+ (0.39,0) [0|99] "MDI" XXX + SG_ mechanisches_Motor_Verlustmomen : 48|8@1+ (0.39,0) [0|99] "MDI" XXX + SG_ Fahrpedalwert_oder_Drosselklapp : 40|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ inneres_Motor_Moment_ohne_exter : 32|8@1+ (0.39,0) [0|99] "MDI" XXX + SG_ Motordrehzahl : 16|16@1+ (0.25,0) [0|16256] "U/min" XXX + SG_ inneres_Motor_Moment : 8|8@1+ (0.39,0) [0|99] "MDI" XXX + SG_ Momentenangaben_ungenau : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Getriebe_Momentene : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Brems_Momenteneing : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Time_Out_Bremsen_Botschaft : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Kupplungsschalter : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Kickdownschalter : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrpedalwert_ungenau__Motor_1_ M : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Leergasinformation : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 262 Master_3: 8 XXX + SG_ Frei_Master_3_1 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Motortemperatur_linearisiert : 48|8@1+ (0.75,-48) [-48|143.25] "" XXX + SG_ Indiziertes_Sollmoment_f_r_Vmax : 32|16@1+ (0.0015259,0) [0|100] "%" XXX + SG_ Relative_Momentenanforderung_de : 16|16@1+ (0.003052,0) [0|200] "%" XXX + SG_ Delta_Motormoment_aus_Verlustmo : 0|16@1+ (0.003052,-100) [-100|100] "%" XXX + +BO_ 260 Master_2: 8 XXX + SG_ Ubat_Freigabe_DVE : 45|1@1+ (1,0) [0|0] "" XXX + SG_ DK_Sollwertbegrenzung : 44|1@1+ (1,0) [0|0] "" XXX + SG_ Einspritzverbot_DV_E_lernen : 43|1@1+ (1,0) [0|0] "" XXX + SG_ Master_erkannt : 42|1@1+ (1,0) [0|0] "" XXX + SG_ Vmax_Begrenzung_aktiv : 41|1@1+ (1,0) [0|0] "" XXX + SG_ SA_Verbot_von_FGR : 40|1@1+ (1,0) [0|0] "" XXX + SG_ Pedalwert_Komplement : 24|16@1+ (1,0) [0|0] "" XXX + SG_ Zaehler__Master_2_ : 16|8@1+ (1,0) [0|255] "" XXX + SG_ Normierter_Fahrpedalwinkel : 0|16@1+ (0.001526,0) [0|100] "%" XXX + +BO_ 258 Master_1: 8 XXX + SG_ Stationaere_Solldrehzahl : 56|8@1+ (10,0) [0|2550] "Umin" XXX + SG_ Drehmoment_LLR__I_Anteil_ : 40|16@1+ (0.003052,-100) [-100|100] "%" XXX + SG_ Drehmoment_LLR__PD_Anteil_ : 24|16@1+ (0.003052,-100) [-100|100] "%" XXX + SG_ Drehmoment_LLR__Luftpfad_ : 8|16@1+ (0.003052,-100) [-100|100] "%" XXX + SG_ Frei_Master_1_1 : 4|4@1+ (1,0) [0|0] "" XXX + SG_ LLR_ist_aktiv : 3|1@1+ (1,0) [0|0] "" XXX + SG_ I_Anteil_der_LLR_aktiv : 2|1@1+ (1,0) [0|0] "" XXX + SG_ PD_Anteil_der_LLR_aktiv : 1|1@1+ (1,0) [0|0] "" XXX + SG_ LLR_Freigabe_nach_Start : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1984 LWS_Kalibrierung: 2 XXX + SG_ Frei_LWS_Kalibrierung_1_1 : 15|1@1+ (1,0) [0|0] "" XXX + SG_ LWS_Identifier : 8|7@1+ (1,0) [0|0] "" XXX + SG_ Frei_LWS_Kalibrierung_1_2 : 4|4@1+ (1,0) [0|0] "" XXX + SG_ Command_Dode_Word : 0|4@1+ (1,0) [0|0] "" XXX + +BO_ 1986 Lenkwinkel_Init: 4 XXX + SG_ Kodierbytes : 8|24@1+ (1,0) [0|0] "" XXX + SG_ Identiifier_f_r_LWS_Init : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 192 Lenkwinkel_1__RB_: 2 XXX + SG_ Vorzeichen__RB_ : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkwinkel__RB_ : 5|10@1+ (2.5,-720) [-720|720] "" XXX + SG_ LWS_OK__RB_ : 4|1@1+ (1,0) [0|0] "" XXX + SG_ LWS_Abgleich__RB_ : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Lenkwinkel_1_1__RB_ : 2|1@1+ (1,0) [0|0] "" XXX + SG_ FINE_CHECK__RB_ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ COARSE_CHECK__RB_ : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 196 Lenkwinkel_1__ITT_: 2 XXX + SG_ Vorzeichen__ITT_ : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkwinkel__ITT_ : 5|10@1+ (1.5,-768) [-768|766.5] "" XXX + SG_ LWS_OK : 4|1@1+ (1,0) [0|0] "" XXX + SG_ LWS_Abgleich__ITT_ : 3|1@1+ (1,0) [0|0] "" XXX + SG_ LWS_Initialisierung__ITT_ : 2|1@1+ (1,0) [0|0] "" XXX + SG_ FINE_CHECK__ITT_ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ COARSE_CHECK__ITT_ : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 194 Lenkwinkel_1: 8 XXX + SG_ LW1_LRW : 0|15@1+ (0.04375,0) [0|1433.55625] "°Grad" Gateway,ESP,ABS + SG_ LW1_LRW_Sign : 15|1@1+ (1,0) [0|1] "" Gateway,ESP,ABS + SG_ LW1_Lenk_Gesch : 16|15@1+ (0.04375,0) [0|1433.55625] "°Grad/s" Gateway,ESP,ABS + SG_ LW1_Gesch_Sign : 31|1@1+ (1,0) [0|1] "" Gateway,ESP,ABS + SG_ LW1_ID : 32|8@1+ (1,0) [0|255] "" Gateway,ESP,ABS + SG_ LW1_Initquelle : 40|1@1+ (1,0) [0|1] "" Gateway,ESP,ABS + SG_ LW1_Status : 41|2@1+ (1,0) [0|3] "" Gateway,ESP,ABS + SG_ LW1_Sta_KL30 : 43|1@1+ (1,0) [0|1] "" Gateway,ESP,ABS + SG_ LW1_Zaehler : 44|4@1+ (1,0) [0|15] "" Gateway,ESP,ABS + SG_ LW1_Kodier : 48|8@1+ (1,0) [0|255] "" Gateway + SG_ LW1_CRC : 56|8@1+ (1,0) [0|255] "" Gateway,ESP,ABS + +BO_ 1502 Lenkhilfe_Fehler: 7 XXX + SG_ Werkstattcode : 48|8@1+ (1,0) [0|0] "" XXX + SG_ Multiplex_Signal : 45|3@1+ (1,0) [0|7] "" XXX + SG_ Sensorcodierung_Lenkhilfe : 44|1@1+ (1,0) [0|0] "" XXX + SG_ Kennliniencodierung_Lenkhilfe : 40|4@1+ (1,0) [0|15] "Kennlinie" XXX + SG_ Geber_f__Lenkw__Speicher_ausles : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Kombiinstr__Speicher_auslesen : 38|1@1+ (1,0) [0|0] "" XXX + SG_ Steuerger__Speicher_auslesen : 37|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Steuergeraet_defekt : 36|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Lenkhilfe_1_3 : 32|4@1+ (1,0) [0|0] "" XXX + SG_ Frei_Lenkhilfe_1_4 : 30|2@1+ (1,0) [0|0] "" XXX + SG_ Geber_f__Lenkwi__k__CAN_Komm_sp : 29|1@1+ (1,0) [0|0] "" XXX + SG_ Geber_f__Lenkwinkel_k__CAN_Komm : 28|1@1+ (1,0) [0|0] "" XXX + SG_ Kombiinstr__k__CAN_Kommunik__sp : 27|1@1+ (1,0) [0|0] "" XXX + SG_ Kombiinstrument_k__CAN_Kommunik : 26|1@1+ (1,0) [0|0] "" XXX + SG_ Steuergeraet_k__CAN_Kommunik__S : 25|1@1+ (1,0) [0|0] "" XXX + SG_ Steuergeraet_keine_CAN_Kommunik : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Spannung_Ks__nach_Mas : 23|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Spannung_Ks_nach_Mass : 22|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Spannung_Ks__nach___s : 21|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Spannung_Ks__nach__ : 20|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Temperaturschutz_sp_ : 19|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Temperaturschutz : 18|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Betrieb_unpl__Sig__sp : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfe_Betrieb_unpl__Signal : 16|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_k__Kommunik__sp : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_keine_Kommunik_ : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_defekt_sp_ : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_defekt : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_Unterbrechung_s : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_Unterbrechung : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhilfesensor_Ks_nach_Masse_s : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkhifesensor_Ks_nach_Masse : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Spannung_Kl_15_zu_klein_sp_ : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Spannung_Kl_15_zu_klein : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Lenkhilfe_1_5 : 4|2@1+ (1,0) [0|0] "" XXX + SG_ Spannung_Kl_30_zu_klein_sp_ : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Spannung_Kl_30_zu_klein : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Spannung_Kl_30_zu_gro__sp_ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Spannung_Kl_30_zu_gro_ : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 976 Lenkhilfe_1: 2 XXX + SG_ LH1_Lastinfo : 0|7@1+ (1,0) [0|127] "A" XXX + SG_ LH1_Fehler_LI : 7|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_Sicherheitslamp : 8|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_Fehlerlampe : 9|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_Textbits : 10|3@1+ (1,0) [0|7] "" XXX + SG_ LH1_Akustiksign : 13|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_SleepInd : 14|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_Fehlereintr : 15|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_EPS_Diagmode : 16|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_gue_ECU_Temp : 19|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_Kuehlung : 20|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_Mode_Hybrid : 21|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_Untersp : 24|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_Uebersp : 25|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_Uebertemp : 26|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_Sensor : 27|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_CAN_SS : 28|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_ECU : 29|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_Motor : 30|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_NL_LeistDichte : 31|1@1+ (1,0) [0|1] "" XXX + SG_ LH1_ULeistung : 32|8@1+ (0.5,0) [0|100] "%" XXX + SG_ LH1_ECU_Temp : 40|8@1+ (1,-70) [-70|185] "°C" XXX + +BO_ 1312 Kombi_3: 8 XXX + SG_ Frei_Kombi_3_2 : 60|4@1+ (1,0) [0|0] "" XXX + SG_ Kilometerstand : 40|20@1+ (1,0) [0|1000000] "km" XXX + SG_ Fehlerstatus_Standzeit : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Standzeit : 24|15@1+ (4,0) [0|131068] "sec" XXX + SG_ Frei_Kombi_3_1 : 20|4@1+ (1,0) [0|0] "" XXX + SG_ Schluesselinfo : 16|4@1+ (1,0) [0|15] "" XXX + SG_ Kombi_Multiplex_Code M : 14|2@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Niveauregulie m3 : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Marke m1 : 11|3@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Lenkhilfe m3 : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Dieselpumpe m3 : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Lenkwinkel m3 : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Baureihe m1 : 8|3@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Laendervariante m0 : 8|6@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Allrad m3 : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Bordnetz m3 : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_ACC m3 : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Airbag m3 : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Generation m1 : 4|4@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Klima m3 : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_ABS m3 : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Verbauliste_Motor m3 : 0|1@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Derivat m1 : 0|4@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Sprachvariante m0 : 0|8@1+ (1,0) [0|0] "" XXX + SG_ Kombi_Multiplex_Reifenumfang m2 : 0|12@1+ (1,0) [0|4095] "mm" XXX + +BO_ 1056 Kombi_2: 8 XXX + SG_ Frei_Kombi_2_2 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Kl__58_s : 55|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_58s__Kombi_2_ : 48|7@1+ (1,0) [0|100] "%" XXX + SG_ Fehlerstatus_Kl__58_d : 47|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_58d__Kombi_2_ : 40|7@1+ (1,0) [0|100] "%" XXX + SG_ Kuehlmitteltemp__4_1__Kombi_2_ : 32|8@1+ (0.75,-48) [-48|142.5] "C" XXX + SG_ Oeltemperatur_4_1 : 24|8@1+ (1,-60) [-60|194] "C" XXX + SG_ Aussentemp__ungefiltert_4_1__Ko : 16|8@1+ (0.5,-50) [-50|77] "C" XXX + SG_ Aussentemperatur_gefiltert : 8|8@1+ (0.5,-50) [-50|77] "C" XXX + SG_ Fehlerspeichereintrag__Kombi_ : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Kombi_2_1 : 4|3@1+ (1,0) [0|0] "" XXX + SG_ Anhaenger_erkannt : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerst__Kuehlmitteltemp__4_1 : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Oeltemperatur_4_1 : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Aussentemp__4_1 : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 800 Kombi_1: 8 XXX + SG_ Frei_Kombi_1_3 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Angezeigte_Geschwindigkeit : 46|10@1+ (0.32,0) [0|325] "km/h" XXX + SG_ Blinker_rechts_4_1 : 45|1@1+ (1,0) [0|0] "" XXX + SG_ Blinker_links_4_1 : 44|1@1+ (1,0) [0|0] "" XXX + SG_ Gesetzte_Zeitluecke__Kombi_1_ : 43|1@1+ (1,0) [0|0] "" XXX + SG_ ADR_Summer_abgeschaltet : 42|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Kombi_1_2 : 40|2@1+ (1,0) [0|0] "" XXX + SG_ Geschwindigkeit__Kombi_1_ : 25|15@1+ (0.01,0) [0|326] "km/h" XXX + SG_ Signalquelle_Geschwindigkeit_4_ : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Tankwarnung : 23|1@1+ (1,0) [0|0] "" XXX + SG_ Tankinhalt : 16|7@1+ (1,0) [0|126] "l" XXX + SG_ Tankstop : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Kombi_1_7 : 12|3@1+ (1,0) [0|0] "" XXX + SG_ Kombi_im_Stellgliedtest : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Ladekontroll_Lampe__Kombi_ : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Bremsinfo : 8|2@1+ (1,0) [0|0] "" XXX + SG_ Vorgluehlampe__Kombi_1_ : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Tankwarnlampe : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Heissleuchten_Vorwarnung : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Kuehlmittelmangel : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Dynamische_Oeldruckwarnung : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Oeldruck : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Tank : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrertuer_4_1 : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1504 Klima_1: 8 XXX + SG_ Aussentemp__ungef__Sto_f__4_1 : 56|8@1+ (0.5,-50) [-50|77] "C" XXX + SG_ Fehlerspeichereintrag__Klima_ : 55|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Klima_1_5 : 50|5@1+ (1,0) [0|0] "" XXX + SG_ AC_Schalter : 49|1@1+ (1,0) [0|0] "" XXX + SG_ Temperatureinheit : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Kuehlerluefteransteuerung__Klim : 40|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ Geblaeselast_4_1 : 32|8@1+ (0.4,0) [0|101.6] "%" XXX + SG_ Kompressorlast : 24|8@1+ (0.25,0) [0|63.5] "Nm" XXX + SG_ Klimadrucksignal__Klima_1_ : 16|8@1+ (0.2,0) [0|50.8] "bar" XXX + SG_ Aussentemp__ungef__4_1__Klima_1 : 8|8@1+ (0.5,-50) [-50|77] "C" XXX + SG_ Kaeltemitteldruck_veraltet : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Kompressormoment_veraltet_4_1 : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Keine_Heizleistg_gewuenscht_4_1 : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Kompressorzustand__4_1_ : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Heizbare_Frontscheibe : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Heizbare_Heckscheibe : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrerwunsch_Zuheizer : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Drehzahlanhebung : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 906 GRA_Neu: 4 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ GRA_Hauptschalt : 8|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Abbrechen : 9|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Down_kurz : 10|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Up_kurz : 11|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Down_lang : 12|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Up_lang : 13|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Fehler_Bed : 14|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Kodierinfo : 15|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Neu_Setzen : 16|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Recall : 17|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Sender : 18|2@1+ (1,0) [0|3] "" XXX + SG_ COUNTER : 20|4@1+ (1,0) [0|15] "" XXX + SG_ GRA_Tip_Down : 24|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Tip_Up : 25|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Zeitluecke : 26|2@1+ (1,0) [0|3] "" XXX + SG_ GRA_Sta_Limiter : 28|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Typ_Hauptschalt : 29|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Sportschalter : 30|1@1+ (1,0) [0|1] "" XXX + SG_ GRA_Fehler_Tip : 31|1@1+ (1,0) [0|1] "" XXX + +BO_ 904 GRA: 3 XXX + SG_ Checksumme_GRA_alt : 16|8@1+ (1,0) [0|0] "" XXX + SG_ Frei_GRA_alt : 15|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR_Bedienteil_Fehler : 14|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR_beschleunigen : 13|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR_verzoegern : 12|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR___Tipschalter__Wie : 11|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR___Tipschalter__Set : 10|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR___Tipschalter__Aus : 9|1@1+ (1,0) [0|0] "" XXX + SG_ GRA_alt__ADR___Hauptschalter : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_GRA_alt : 0|8@1+ (1,0) [0|255] "" XXX + +BO_ 1352 Getriebe_4: 3 XXX + SG_ Testparameter_2 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ Testparameter_1 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ Waehlhebelausleuchtung : 4|4@1+ (1,0) [0|0] "" XXX + SG_ Frei_Getriebe_4_1 : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Testfreigabeflag : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Handbremserinnerung_s_Lampe : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Shiftlock_Getriebe_4 : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1344 Getriebe_2: 8 XXX + SG_ eingelegte_Fahrstufe : 60|4@1+ (1,0) [0|0] "" XXX + SG_ Ganganzeige_Kombi___Getriebe_Va : 56|4@1+ (1,0) [0|15] "" XXX + SG_ Fehlerlampe_f_r_Kupplung_bei_VL : 55|1@1+ (1,0) [0|0] "" XXX + SG_ Anforderung_Kriechadaption : 54|1@1+ (1,0) [0|0] "" XXX + SG_ ECO_Anzeige__4_1_ : 53|1@1+ (1,0) [0|0] "" XXX + SG_ Shift_Lock_Lampe : 52|1@1+ (1,0) [0|0] "" XXX + SG_ Unterdrueckung_von_Warnungen : 51|1@1+ (1,0) [0|0] "" XXX + SG_ Gong : 50|1@1+ (1,0) [0|0] "" XXX + SG_ Starter_wird_angesteuert : 49|1@1+ (1,0) [0|0] "" XXX + SG_ Hochschaltlampe : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Synchronisationszeit : 40|8@1+ (20,0) [0|5080] "ms" XXX + SG_ invertierte_Synchronisations_Wu : 32|8@1+ (25,0) [0|6350] "U/min" XXX + SG_ Synchronisations_Wunschdrehzahl : 24|8@1+ (25,0) [0|6350] "U/min" XXX + SG_ Gradientenbegrenzung : 16|8@1+ (10,0) [0|2540] "Nm/s" XXX + SG_ Leerlaufsolldrehzahl__Getriebe : 8|8@1+ (10,0) [0|2540] "U/min" XXX + SG_ Zahler_Getriebe_2 : 4|4@1+ (1,0) [0|15] "" XXX + SG_ Zwischengasflag : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Ecomatic__4_1_ : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Schubabschaltunterstuetzung : 1|1@1+ (1,0) [0|0] "" XXX + SG_ LFR_Adaption_Freigabeflag : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1088 Getriebe_1: 8 XXX + SG_ Wandlerverlustmoment : 56|8@1+ (0.39,0) [0|99.06] "MDI" XXX + SG_ Fehlerspeichereintrag__Getriebe : 55|1@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 51|4@1+ (1,0) [0|15] "" XXX + SG_ Gang_eingelegt : 50|1@1+ (1,0) [0|0] "" XXX + SG_ Schaltabsicht : 49|1@1+ (1,0) [0|0] "" XXX + SG_ Motor_aus : 48|1@1+ (1,0) [0|0] "" XXX + SG_ OBD_Status__Getriebe_1___4_1_ : 46|2@1+ (1,0) [0|0] "" XXX + SG_ Kuehlleistung : 44|2@1+ (1,0) [0|0] "" XXX + SG_ Getriebe_Notlauf : 40|4@1+ (1,0) [0|0] "" XXX + SG_ Fahrwiderstandsindex : 32|8@1+ (0.249,-31.6) [-31.6|31.6] "" XXX + SG_ inneres_Soll_Motormoment : 24|8@1+ (0.39,0) [0|99.06] "MDI" XXX + SG_ Uebertragungsfunktion : 16|8@1+ (0.1,0) [0|25.4] "" XXX + SG_ Waehlhebelposition__Getriebe_1_ : 12|4@1+ (1,0) [0|0] "" XXX + SG_ Zielgang_oder_eingelegter_Gang : 8|4@1+ (1,0) [0|0] "" XXX + SG_ EGS_Anforderung : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Kodierung_im_MSG : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Leerlaufsolldrehzahlanhebung : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Wandlerkupplung : 3|2@1+ (1,0) [0|0] "" XXX + SG_ Klimakompressor_aus__Getriebe_1 : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Status_Getriebe_und_Wandlerschu : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Schaltung_aktiv__Getriebe_1_ : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 912 Gate_Komf_1: 8 XXX + SG_ GK1_Sta_RDK_Warn : 0|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Anhaen : 1|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Licht1 : 2|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Licht3 : 3|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Tuerkont : 4|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Li_vorn : 5|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_SleepAckn : 7|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_CharismaModus m1 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ GK1_SamFktNr M : 12|4@1+ (1,0) [0|15] "" XXX + SG_ GK1_Fa_Tuerkont : 16|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_RueckfahrSch : 17|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_ELV_verrieg : 18|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Kessy_2 : 19|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Stdhzg : 20|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_SH_Verbau : 21|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_ParkFrontWi : 22|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_KW_Warm : 23|1@1+ (1,0) [0|1] "" XXX + SG_ BCM_Remotestart_Betrieb : 24|1@1+ (1,0) [0|1] "" XXX + SG_ BSK_HL_geoeffnet : 26|1@1+ (1,0) [0|1] "" XXX + SG_ BSK_HR_geoeffnet : 27|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Rueckfahr : 28|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_BrLi_links : 29|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_BrLi_rechts : 30|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_BrLi_mitte : 31|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_BLS_ILM : 32|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_EDC_ILM : 33|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Blinker_li : 34|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Blinker_re : 35|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_def_P_verr : 36|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_LS1_Fernlicht : 37|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_Licht2 : 38|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_LSM : 39|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Count_Anhaen : 40|4@1+ (1,0) [0|15] "" XXX + SG_ BSK_BT_geoeffnet : 41|1@1+ (1,0) [0|1] "" XXX + SG_ BSK_HD_Hauptraste : 43|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_BLS_AAG : 44|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_EDC_AAG : 45|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Anhaenger : 46|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_BrLi_Anhaen : 47|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Abblendlicht : 48|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Fernlicht : 49|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Wischer_vorn : 50|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Sta_ILM_F_1 : 51|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Abbl_VL_def : 52|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Abbl_VR_def : 53|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Blink_Autob : 54|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Warnblk_Status : 55|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_SH_laeuft : 56|1@1+ (1,0) [0|1] "" XXX + SG_ SH1_ein_Wasserpumpe : 57|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Nebel_ein : 58|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Bremslicht : 59|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_Anh_abgesteckt : 60|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_AnhKonLamp : 61|1@1+ (1,0) [0|1] "" XXX + SG_ LDS_Stellung_AFL : 62|1@1+ (1,0) [0|1] "" XXX + SG_ GK1_SH_Zusatzfkt : 63|1@1+ (1,0) [0|1] "" XXX + + +BO_ 1340 Fahrwerk_1: 1 XXX + SG_ Frei_Fahrwerk_1_2 : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Fahrwerk_1_1 : 6|2@1+ (1,0) [0|0] "" XXX + SG_ Einstellung_Fahrwerkdaempfung_4 : 4|3@1+ (1,0) [0|7] "" XXX + SG_ Ansteuererung_Fahrzeugniveau : 0|4@1+ (1,0) [0|15] "" XXX + +BO_ 1472 EPB_1: 8 XXX + SG_ COUNTER : 0|4@1+ (1,0) [0|15] "" XXX + SG_ EP1_Fehler_Sta : 4|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ EP1_Sta_EPB : 6|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Sta_Schalter : 7|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Spannkraft : 8|5@1+ (1,0) [0|30] "Unit_KiloNewto" XXX + SG_ EP1_Schalterinfo : 13|2@1+ (1,0) [0|3] "" XXX + SG_ EP1_Sta_NWS : 15|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Neig_winkel : 16|8@1+ (1,-128) [-128|127] "Unit_PerCentOfForceOfGravi" XXX + SG_ EP1_Verzoegerung : 24|8@1+ (0.048,-7.968) [-7.968|4.224] "Unit_MeterPerSeconSquar" XXX + SG_ EP1_Fehlereintr : 32|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Freigabe_Ver : 33|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_AutoHold_zul : 34|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_AutoHold_aktiv : 35|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_SleepInd : 36|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Status_Kl_15 : 37|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Lampe_AutoP : 38|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Bremslicht : 39|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Warnton1 : 40|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Warnton2 : 41|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_AnfShLock : 42|1@1+ (1,0) [0|1] "" XXX + SG_ EPB_Autoholdlampe : 43|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_QualNeigWi : 44|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_KuppModBer : 45|2@1+ (1,0) [0|3] "" XXX + SG_ EP1_HydrHalten : 47|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Fkt_Lampe : 48|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EP1_Warnton : 49|1@1+ (1,0) [0|1] "" XXX + SG_ EP1_Fehler_BKL : 50|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ EP1_Fehler_gelb : 51|1@1+ (1,0) [0|1] "" XXX + SG_ EP1__Text : 52|4@1+ (1,0) [0|8] "" Vector__XXX + SG_ CHECKSUM : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 1326 Diag_Lenkhilfe: 3 XXX + SG_ Werkstattcode__Diag_ : 16|8@1+ (1,0) [0|0] "" XXX + SG_ Multiplex_Signal__Diag_ : 13|3@1+ (1,0) [0|7] "" XXX + SG_ Befehl_Sensorcodierung_Lenkhilf : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Befehl_Kennliniencodierung_Lenk : 8|4@1+ (1,0) [0|0] "" XXX + SG_ Befehl_Fehlerspeicher_loeschen : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1432 Daempfer_1: 2 XXX + SG_ Frei_Daempfer_1_4 : 12|4@1+ (1,0) [0|0] "" XXX + SG_ Textbits_Daempfer : 8|4@1+ (1,0) [0|0] "" XXX + SG_ Fehlerspeicherbit__Daempfer_1_ : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Systemstatus__Daempfer_1_ : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Daempfer_1_3 : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Status_CDC_Taster : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Daempfer_1_2 : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Status_Daempferregelung_4_1 : 0|3@1+ (1,0) [0|7] "" XXX + +BO_ 1392 BSG_Last: 4 XXX + SG_ Klimaanlage_abschalten : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Sitzbelueftung_abschalten : 30|1@1+ (1,0) [0|0] "" XXX + SG_ Wischwasserheizung_abschalten : 29|1@1+ (1,0) [0|0] "" XXX + SG_ Lenkradheizung_abschalten : 28|1@1+ (1,0) [0|0] "" XXX + SG_ Heizbare_Sitze_abschalten : 27|1@1+ (1,0) [0|0] "" XXX + SG_ Heizbare_Aussenspiegel_abschalt : 26|1@1+ (1,0) [0|0] "" XXX + SG_ Heizbare_Frontscheibe_abschalte : 25|1@1+ (1,0) [0|0] "" XXX + SG_ Heizbare_Heckscheibe_abschalten : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Batteriespannung_Bordnetzbatter : 16|8@1+ (0.05,5) [5|17.7] "V" XXX + SG_ Motorhaubenkontakt : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Leuchtweitenregulierung : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerspeichereintrag__BSG_Last : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Zustand_der_Starterbatterie : 11|2@1+ (1,0) [0|0] "" XXX + SG_ Zustand_der_Bordnetzbatterie : 9|2@1+ (1,0) [0|0] "" XXX + SG_ LL_Drehzahlanhebung : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_L : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_BSG_Last_1_1 : 4|3@1+ (1,0) [0|0] "" XXX + SG_ ZAS_Klemme_50 : 3|1@1+ (1,0) [0|0] "" XXX + SG_ ZAS_Klemme_X : 2|1@1+ (1,0) [0|0] "" XXX + SG_ ZAS_Klemme_15 : 1|1@1+ (1,0) [0|0] "" XXX + SG_ ZAS_Klemme_S : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1136 BSG_Kombi: 5 XXX + SG_ Frei_BSG_Kombi_1_3 : 36|4@1+ (1,0) [0|0] "" XXX + SG_ Ruecksitzlehne_HR_verr__4_1 : 35|1@1+ (1,0) [0|0] "" XXX + SG_ Ruecksitzlehne_HL_verr__4_1 : 34|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerlampe_Lenkhilfe_veraltet : 33|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerlampe_Lenkhilfe__BSG_Komb : 32|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Kl__58s : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_58s__BSG_Kombi_ : 24|7@1+ (1,0) [0|100] "%" XXX + SG_ Fehlerstatus_Kl__58d : 23|1@1+ (1,0) [0|0] "" XXX + SG_ Klemme_58d__BSG_Kombi_ : 16|7@1+ (1,0) [0|100] "%" XXX + SG_ Unterspannung : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_BSG_Kombi_1_2 : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Heckdeckel_geoeffnet : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Motorhaube_geoeffnet : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Tuer_hinten_rechts_geoeffnet : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Tuer_hinten_links_geoeffnet : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Beifahrertuer_geoeffnet : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Fahrertuer_geoeffnet : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Lade_Kontrollampe : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_BSG_Kombi_1_1 : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Rueckfahrlicht : 5|1@1+ (1,0) [0|0] "" XXX + SG_ DWA_Akku : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Warnblink_Mode : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Anhaenger_Kontrollampe : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Blinker_rechts_Kontrollampe : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Blinker_links_Kontrollampe : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 424 Bremse_6: 3 XXX + SG_ Checksumme_Bremse_6 : 16|8@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_Bremse_6 : 12|4@1+ (1,0) [0|15] "" XXX + SG_ Status_Bremsdruck__Bremse_6__du : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Bremse_6_1 : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Bremsdruck__Bremse_6_ : 0|10@1+ (0.3255,-40) [-40|293] "bar" XXX + +BO_ 1192 Bremse_5: 8 XXX + SG_ CHECKSUM : 56|8@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 52|4@1+ (1,0) [0|15] "" XXX + SG_ BR5_ECD_Lampe : 51|1@1+ (1,0) [0|0] "" XXX + SG_ BR5_ZT_Rueckk_Umsetz : 48|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Anhi_Sta : 40|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Rollenmodus_Deactiveieren : 34|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Sign_Druck : 31|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Sta_Druck : 30|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Druckvalid : 29|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Stillstand : 28|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Bremsdruck : 16|12@1+ (0.1,0) [0|250] "bar" XXX + SG_ BR5_Vorzeichen : 15|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Sta_Gierrate : 14|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Giergeschw : 0|14@1+ (0.01,0) [0|100] "Grad/sec" XXX + SG_ BR5_ANB_CM_Rueckk_Umsetz : 49|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_HDC_bereit : 50|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Stat_FallBack_eBKV : 35|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Anforderung_EPB : 36|2@1+ (1,0) [0|3] "" XXX + SG_ ESP_Autohold_active : 38|1@1+ (1,0) [0|1] "" XXX + SG_ ESP_Autohold_Standby : 39|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Anhi_akt : 41|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_v_Ueberw : 42|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Bremslicht : 43|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Notbremsung : 44|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_Fahrer_tritt_ZBR_Schw : 45|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_AWV2_Bremsruck : 46|1@1+ (1,0) [0|1] "" XXX + SG_ BR5_AWV2_Fehler : 47|1@1+ (1,0) [0|1] "" XXX + +BO_ 672 Bremse_4: 3 XXX + SG_ Frei_Bremse_4_1 : 17|7@1+ (1,0) [0|0] "" XXX + SG_ Einheit_Kupplungssteifigkeit : 16|1@1+ (1,0) [0|0] "" XXX + SG_ ABS_Vorgabewert_hinten_Kupplung : 8|8@1+ (0.7874,0) [0|100] "%" XXX + SG_ ABS_Vorgabewert_mitte_Kupplungs : 0|8@1+ (3,-381) [-381|378] "Nm/min" XXX + +BO_ 1184 Bremse_3: 8 XXX + SG_ Radgeschw__HR_4_1 : 49|15@1+ (0.01,0) [0|326] "km/h" XXX + SG_ Frei_Bremse_3_4 : 48|1@1+ (1,0) [0|0] "" XXX + SG_ Radgeschw__HL_4_1 : 33|15@1+ (0.01,0) [0|326] "km/h" XXX + SG_ Frei_Bremse_3_3 : 32|1@1+ (1,0) [0|0] "" XXX + SG_ Radgeschw__VR_4_1 : 17|15@1+ (0.01,0) [0|326] "km/h" XXX + SG_ Frei_Bremse_3_2 : 16|1@1+ (0.01,0) [0|325] "km/h" XXX + SG_ Radgeschw__VL_4_1 : 1|15@1+ (0.01,0) [0|326] "km/h" XXX + SG_ Frei_Bremse_3_1 : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1440 Bremse_2: 8 XXX + SG_ gemessene_Querbeschleunigung : 63|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Bremse_2_2 : 62|1@1+ (1,0) [0|0] "" XXX + SG_ Impulszahl : 56|6@1+ (1,0) [0|63] "" XXX + SG_ Fehlerstatus_Wegimpulse_4_1 : 55|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Bremse_2_5 : 54|1@1+ (1,0) [0|0] "" XXX + SG_ Warnlampe_DDS : 53|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerspeichereintrag_Bremse : 52|1@1+ (1,0) [0|0] "" XXX + SG_ Wegimpulszaehlerstatus : 51|1@1+ (1,0) [0|0] "" XXX + SG_ Wegimpulse_Vorderachse : 40|11@1+ (1,0) [0|2047] "" XXX + SG_ Zeitstempel : 24|16@1+ (1,0) [0|65535] "tics" XXX + SG_ mittlere_Raddrehzahl__Bremse_2 : 9|15@1+ (0.002,0) [0|65.278] "U/sec" XXX + SG_ Querbeschl__TimerTic M : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Timer m1 : 0|8@1+ (0.04,0) [0|10.2] "usec" XXX + SG_ Querbeschleunigung m0 : 0|8@1+ (0.01,-1.27) [-1.27|1.27] "g" XXX + +BO_ 416 Bremse_1: 8 ABS + SG_ BR1_ASR_Anf : 0|1@1+ (1,0) [0|1] "" Motor + SG_ BR1_MSR_Anf M : 1|1@1+ (1,0) [0|1] "" Motor + SG_ BR1_ABS_Brems : 2|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_EDS_Ongr : 3|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_ESP_Ongr : 4|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_ASR_Ongr : 5|2@1+ (1,0) [0|3] "" Transmission + SG_ BR1_EBV_Ongr : 7|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Lampe_ABS : 8|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Lampe_ASR : 9|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Lampe_BK : 10|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Lichtschalt : 11|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_StaDruckschw : 12|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_MAD : 13|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Sta_MAD : 14|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Diagnose : 15|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_BKV_active : 16|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Rad_kmh : 17|15@1+ (0.01,0) [0|326.39] "km/h" XXX + SG_ BR1_ASRMo_sl : 32|8@1+ (0.39,0) [0|99.06] "%" Motor + SG_ BR1_ASRMo_fa m0 : 40|8@1+ (0.39,0) [0|99.06] "%" Motor + SG_ BR1_MSR_Mo_inv m1 : 40|8@1+ (-0.39,99.45) [0|99.06] "%" Motor + SG_ BR1_MSR_Mo : 48|8@1+ (0.39,0) [0|99.06] "%" Motor + SG_ BR1_Zaehler : 56|4@1+ (1,0) [0|15] "" XXX + SG_ BR1_ASR_ESP : 60|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_ESPASR_passive : 61|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Sta_ESP : 62|1@1+ (1,0) [0|1] "" XXX + SG_ BR1_Ersatz_Kmh : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 680 Bremsbooster_1: 3 XXX + SG_ Fehlerspeichereintrag_Booster : 23|1@1+ (1,0) [0|0] "" XXX + SG_ Loseschalter_unplausibel_Boost : 22|1@1+ (1,0) [0|0] "" XXX + SG_ Position_Standby : 21|1@1+ (1,0) [0|0] "" XXX + SG_ ADR_Relais_ge_ffnet : 20|1@1+ (1,0) [0|0] "" XXX + SG_ Status_Bremsbooster_Steuerung : 19|1@1+ (1,0) [0|0] "" XXX + SG_ Bremsbooster_verf_gbar : 18|1@1+ (1,0) [0|0] "" XXX + SG_ Eingriff_Bremsbooster : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Bremseingriff_Fahrer : 16|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Bremsbooster_1_1 : 12|4@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_Booster_1 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Checksumme_Booster_1 : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1400 BatMan_1: 1 XXX + SG_ Fehlerspeichereintrag__BatMan_ : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Leistungsrelais : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Messung_Starterleitung : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Zustand_Starterleitung : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Umschaltrelais_Bordnetzbatterie : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Ladung_Starterbatterie : 1|2@1+ (1,0) [0|0] "" XXX + SG_ Startmodus : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 704 Allrad_1: 5 XXX + SG_ Kupplungssteifigkeit_Hinten__Is : 32|8@1+ (0.7874,0) [0|100] "%" XXX + SG_ Fehlerspeichereintrag_Allrad_1 : 31|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Allrad_1_1 : 26|5@1+ (1,0) [0|0] "" XXX + SG_ Schaltung_Vorwarnung : 25|1@1+ (1,0) [0|0] "" XXX + SG_ Schaltung_aktiv__Allrad_1_ : 24|1@1+ (1,0) [0|0] "" XXX + SG_ Ganginfo__PNG_ : 20|4@1+ (1,0) [0|0] "" XXX + SG_ PNG_Anzeige_blinkend : 19|1@1+ (1,0) [0|0] "" XXX + SG_ PNG_Status_4_1 : 16|3@1+ (1,0) [0|0] "" XXX + SG_ Kupplungssteifigkeit_Mitte__Ist : 8|8@1+ (3,-381) [-381|378] "Nm/min" XXX + SG_ Einheit_der_Kupplungssteifigkei : 7|1@1+ (1,0) [0|0] "" XXX + SG_ Geschwindigkeitsbegrenzung : 6|1@1+ (1,0) [0|0] "" XXX + SG_ Allrad_Warnlampe : 5|1@1+ (1,0) [0|0] "" XXX + SG_ Notlauf : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Kupplung_komplett_offen : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Fehlerstatus_Kupplungssteifigke : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Ubertemperaturschutz__Allrad_1_ : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Fehler_Allrad_Kupplung : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 1360 Airbag_2: 2 XXX + SG_ OOP_Beifahrer : 14|2@1+ (1,0) [0|0] "" XXX + SG_ OOP_Fahrer : 12|2@1+ (1,0) [0|0] "" XXX + SG_ Belegungserkennung_hinten_mitte : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Belegungserkennung_hinten_recht : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Belegungserkennung_hinten_links : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Belegungserkennung_Beifahrersit : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Checksumme_Airbag_2__reserviert : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 80 Airbag_1: 4 XXX + SG_ CHECKSUM : 24|8@1+ (1,0) [0|0] "" XXX + SG_ COUNTER : 20|4@1+ (1,0) [0|15] "" XXX + SG_ Fehlerspeichereintrag : 19|1@1+ (1,0) [0|0] "" XXX + SG_ Frei_Airbag_1_2 : 18|1@1+ (1,0) [0|0] "" XXX + SG_ Airbag_im_Stellgliedtest : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Airbag_in_Diagnose : 16|1@1+ (1,0) [0|0] "" XXX + SG_ Gurtwarnung_Beifahrer : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Gurtschalter_Beifahrer : 14|1@1+ (1,0) [0|0] "" XXX + SG_ Gurtwarnung_Fahrer : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Gurtschalter_Fahrer : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Airbag_Systemfehler : 11|1@1+ (1,0) [0|0] "" XXX + SG_ Kindersitzerkennung : 10|1@1+ (1,0) [0|0] "" XXX + SG_ Airbag_deaktiviert : 9|1@1+ (1,0) [0|0] "" XXX + SG_ Airbag_Lampe : 8|1@1+ (1,0) [0|0] "" XXX + SG_ Crash_Intensitaet : 5|3@1+ (1,0) [0|111] "B" XXX + SG_ Rollover : 4|1@1+ (1,0) [0|0] "" XXX + SG_ Seiten_Crash_Beifahrer : 3|1@1+ (1,0) [0|0] "" XXX + SG_ Seiten_Crash_Fahrer : 2|1@1+ (1,0) [0|0] "" XXX + SG_ Heck_Crash : 1|1@1+ (1,0) [0|0] "" XXX + SG_ Front_Crash : 0|1@1+ (1,0) [0|0] "" XXX + +BO_ 864 ADR_System: 8 XXX + SG_ S_Checksumme_ADR_1 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ S_Frei_ADR_1_1 : 52|4@1+ (1,0) [0|0] "" XXX + SG_ S_Zeitluecke_gemessen : 48|4@1+ (1,0) [0|15] "" XXX + SG_ S_Fehlerspeichereintrag_ADR : 47|1@1+ (1,0) [0|0] "" XXX + SG_ S_Fehlerspeichereintrag_Bremsbo : 46|1@1+ (1,0) [0|0] "" XXX + SG_ S_ADR_Relais_geoeffnet : 45|1@1+ (1,0) [0|0] "" XXX + SG_ S_Bremsbooster_Status : 43|2@1+ (1,0) [0|0] "" XXX + SG_ S_Eingriff_Bremsbooster : 42|1@1+ (1,0) [0|0] "" XXX + SG_ S_Loeseschalter_unplausibel : 41|1@1+ (1,0) [0|0] "" XXX + SG_ S_Bremseingriff_Fahrer : 40|1@1+ (1,0) [0|0] "" XXX + SG_ S_Anzeige_Sensor_blind : 39|1@1+ (1,0) [0|0] "" XXX + SG_ S_Ansteuerung_optischer_Fahrerh : 38|1@1+ (1,0) [0|0] "" XXX + SG_ S_Ansteuerung_Gong_2 : 37|1@1+ (1,0) [0|0] "" XXX + SG_ S_Ansteuerung_Gong_1 : 36|1@1+ (1,0) [0|0] "" XXX + SG_ S_Schaltaufforderung : 34|2@1+ (1,0) [0|0] "" XXX + SG_ S_Anzeige_Prioritaet : 33|1@1+ (1,0) [0|0] "" XXX + SG_ S_Anzeige_Zeitluecke : 32|1@1+ (1,0) [0|0] "" XXX + SG_ S_Wunschgeschwindigkeit : 24|8@1+ (1,0) [0|254] "km/h" XXX + SG_ S_Objekt_erfasst : 22|2@1+ (1,0) [0|0] "" XXX + SG_ S_Gesetzte_Zeitluecke__ADR_1_ : 18|4@1+ (1,0) [0|15] "" XXX + SG_ S_Synchronisation_Bremsbooster : 17|1@1+ (1,0) [0|0] "" XXX + SG_ S_Momentenanforderung_Freigabe : 16|1@1+ (1,0) [0|0] "" XXX + SG_ S_Verhinderung_Schubabschaltung : 15|1@1+ (1,0) [0|0] "" XXX + SG_ S_Status_ADR_1__S_ : 13|2@1+ (1,0) [0|0] "" XXX + SG_ S_Fehler_ADR_1__S_ : 12|1@1+ (1,0) [0|0] "" XXX + SG_ S_Zaehler_ADR_1 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ S_Momentenanforderung_ADR : 0|8@1+ (0.39,0) [0|99] "MDI" XXX + +BO_ 608 ADR_2: 4 XXX + SG_ Frei_ADR_2_2 : 27|5@1+ (1,0) [0|0] "" XXX + SG_ Anforderung_Bremsdruck : 16|11@1+ (0.0625,0) [0|127.9375] "bar" XXX + SG_ Frei_ADR_2_1 : 14|2@1+ (1,0) [0|0] "" XXX + SG_ Relais_Test_Fehler : 13|1@1+ (1,0) [0|0] "" XXX + SG_ Standby : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_ADR_2 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Checksumme_ADR_2 : 0|8@1+ (1,0) [0|0] "" XXX + +BO_ 1324 ADR_1: 8 XXX + SG_ Checksumme_ADR_1 : 56|8@1+ (1,0) [0|0] "" XXX + SG_ Frei_ADR_1_5 : 52|4@1+ (1,0) [0|0] "" XXX + SG_ Zeitluecke_gemessen : 48|4@1+ (1,0) [0|15] "" XXX + SG_ Fehlerspeichereintrag_ADR : 47|1@1+ (1,0) [0|0] "" XXX + SG_ Reserviert_ADR_1_1 : 40|7@1+ (1,0) [0|0] "" XXX + SG_ Anzeige_Sensor_blind : 39|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_optischer_Fahrerhin : 38|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Gong_2 : 37|1@1+ (1,0) [0|0] "" XXX + SG_ Ansteuerung_Gong_1 : 36|1@1+ (1,0) [0|0] "" XXX + SG_ Schaltaufforderung : 34|2@1+ (1,0) [0|0] "" XXX + SG_ Anzeige_Prioritaet : 33|1@1+ (1,0) [0|0] "" XXX + SG_ Anzeige_Zeitluecke : 32|1@1+ (1,0) [0|0] "" XXX + SG_ Wunschgeschwindigkeit : 24|8@1+ (1,0) [0|254] "km/h" XXX + SG_ Objekt_erfasst : 22|2@1+ (1,0) [0|0] "" XXX + SG_ Gesetzte_Zeitluecke__ADR_1_ : 18|4@1+ (1,0) [0|15] "" XXX + SG_ Synchronisation_Bremsbooster : 17|1@1+ (1,0) [0|0] "" XXX + SG_ Momentenanforderung_Freigabe : 16|1@1+ (1,0) [0|0] "" XXX + SG_ Verhinderung_Schubabschaltung : 15|1@1+ (1,0) [0|0] "" XXX + SG_ Status_ADR_1 : 13|2@1+ (1,0) [0|0] "" XXX + SG_ Fehler_ADR_1 : 12|1@1+ (1,0) [0|0] "" XXX + SG_ Zaehler_ADR_1 : 8|4@1+ (1,0) [0|15] "" XXX + SG_ Momentenanforderung_ADR : 0|8@1+ (0.39,0) [0|99] "MDI" XXX + +BO_ 1550 Einheiten_1: 2 XXX + SG_ MFA_v_Einheit_02 : 0|1@1+ (1,0) [0|1] "" XXX + +BO_ 872 ACC_System: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ ACS_Sta_ADR : 12|2@1+ (1,0) [0|3] "" XXX + SG_ ACS_ADR_Schub : 14|1@1+ (1,0) [0|1] "" XXX + SG_ ACS_Schubabsch : 15|1@1+ (1,0) [0|1] "" XXX + SG_ ACS_StSt_Info : 16|2@1+ (1,0) [0|3] "" XXX + SG_ ACS_MomEingriff : 18|1@1+ (1,0) [0|1] "" XXX + SG_ ACS_Typ_ACC : 19|2@1+ (1,0) [0|3] "" XXX + SG_ ACS_FreigSollB : 23|1@1+ (1,0) [0|1] "" XXX + SG_ ACS_Sollbeschl : 24|11@1+ (0.005,-7.22) [-7.22|3.005] "Unit_MeterPerSeconSquar" XXX + SG_ ACS_Anhaltewunsch : 38|1@1+ (1,0) [0|1] "" XXX + SG_ ACS_Fehler : 39|1@1+ (1,0) [0|1] "" XXX + SG_ ACS_zul_Regelabw : 40|8@1+ (0.005,0) [0|1.265] "Unit_MeterPerSeconSquar" XXX + SG_ ACS_max_AendGrad : 48|8@1+ (0.02,0) [0.02|5.06] "Unit_MeterPerSeconSquar" XXX + +BO_ 1386 ACC_GRA_Anzeige: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ ACA_StaACC : 8|3@1+ (1,0) [0|7] "" XXX + SG_ ACA_ID_StaACC : 11|5@1+ (1,0) [0|31] "" XXX + SG_ ACA_Fahrerhinw : 16|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_AnzDisplay : 17|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_Zeitluecke : 18|4@1+ (1,0) [0|15] "" XXX + SG_ ACA_V_Wunsch : 24|8@1+ (1,0) [0|255] "Unit_KiloMeterPerHour" XXX + SG_ ACA_kmh_mph : 32|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_Akustik1 : 33|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_Akustik2 : 34|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_PrioDisp : 35|2@1+ (1,0) [0|3] "" XXX + SG_ ACA_gemZeitl : 40|4@1+ (1,0) [0|15] "" XXX + SG_ ACA_ACC_Verz : 44|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_StaGRA : 48|3@1+ (1,0) [0|7] "" XXX + SG_ ACA_ID_StaGRA : 51|5@1+ (1,0) [0|31] "" XXX + SG_ ACA_Codierung : 56|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_Tachokranz : 57|1@1+ (1,0) [0|1] "" XXX + SG_ ACA_Aend_Zeitluecke : 58|1@1+ (1,0) [0|1] "" XXX + SG_ COUNTER : 60|4@1+ (1,0) [0|15] "" XXX + +BO_ 208 Lenkhilfe_3: 6 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ LH3_BS_Spiegel : 8|4@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 12|4@1+ (1,0) [0|15] "" XXX + SG_ LH3_LM : 16|10@1+ (1,0) [0|1023] "" XXX + SG_ LH3_LMSign : 26|1@1+ (1,0) [0|1] "" XXX + SG_ LH3_LMValid : 27|1@1+ (1,0) [0|1] "" XXX + SG_ LH3_Sta_DSR : 28|4@1+ (1,0) [0|15] "" XXX + SG_ LH3_BLW : 32|12@1+ (0.15,0) [0|615] "" XXX + SG_ LH3_BLWSign : 44|1@1+ (1,0) [0|1] "" XXX + SG_ LH3_BLWValid : 45|1@1+ (1,0) [0|1] "" XXX + SG_ LH3_Lenkungstyp : 46|2@1+ (1,0) [0|3] "" XXX + +BO_ 978 Lenkhilfe_2: 7 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ LH2_Geradeaus : 12|1@1+ (1,0) [0|1] "" XXX + SG_ LH2_Sta_Charisma : 13|3@1+ (1,0) [0|7] "" XXX + SG_ LH2_Sta_HCA : 16|4@1+ (1,0) [0|15] "" XXX + SG_ LH2_Ausg_LW1 : 20|1@1+ (1,0) [0|1] "" XXX + SG_ LH2_Ausg_LW1_gue : 21|1@1+ (1,0) [0|1] "" XXX + SG_ LH2_StatEPS_PLA : 24|4@1+ (1,0) [0|15] "" XXX + SG_ LH2_aktLenkeingriff : 32|8@1+ (1,0) [0|255] "" XXX + SG_ LH2_PLA_Err : 48|4@1+ (1,0) [0|15] "" XXX + SG_ LH2_PLA_Abbr : 52|4@1+ (1,0) [0|15] "" XXX + +BO_ 980 PLA_1: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ PL1_Status_EPS : 12|4@1+ (1,0) [0|15] "" XXX + SG_ PL1_ArcAngleReq : 16|15@1+ (0.04375,0) [0|1433.55625] "Unit_DegreeOfArc" XXX + SG_ PL1_AngleReqSign : 31|1@1+ (1,0) [0|1] "" XXX + SG_ PL1_Stat_PLA_ESP : 32|4@1+ (1,0) [0|10] "" Vector__XXX + SG_ PL1_Bremsmoment : 40|13@1+ (4,0) [0|32760] "Unit_NewtoMeter" Vector__XXX + SG_ PL1_void : 53|11@1+ (1,0) [0|2047] "" XXX + +BO_ 210 HCA_1: 5 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|15] "" XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" XXX + SG_ HCA_Status : 12|4@1+ (1,0) [0|15] "" XXX + SG_ LM_Offset : 16|15@1+ (0.03125,0) [0|300] "cNm" XXX + SG_ LM_OffSign : 31|1@1+ (1,0) [0|1] "" XXX + SG_ Vib_Freq : 32|4@1+ (4,0) [0|60] "Hz" XXX + SG_ Vib_Amp : 36|4@1+ (0.5,0) [0|7.5] "Nm" XXX + +BO_ 644 Motor_Bremse: 6 XXX + SG_ MOB_Standby : 12|1@1+ (1,0) [0|1] "" XXX + SG_ MOB_Freigabe : 14|1@1+ (1,0) [0|1] "" BCM_Gateway,Bremse_MK25AESP,Gateway_separat + SG_ MOB_Anhaltewunsch : 13|1@1+ (1,0) [0|1] "" Bremse_MK25AESP,Getriebe_DQ + SG_ MOB_CHECKSUM : 0|8@1+ (1,0) [0|255] "" Bremse_MK25AESP + SG_ MOB_COUNTER : 8|4@1+ (1,0) [0|15] "" Bremse_MK25AESP + SG_ TSK_v_Begrenzung_aktiv : 15|1@0+ (1,0) [0|1] "" XXX + SG_ TSK_ax_Getriebe_01 : 40|8@1+ (0.048,0) [0|255] "m/s2" XXX + SG_ MOB_Bremsstgr : 16|11@1+ (0.048852,0) [0|100] "Unit_PerCent" Vector__XXX + SG_ MOB_Bremsmom : 27|13@1+ (4,0) [0|32760] "Unit_NewtoMeter" Bremse_MK25AESP + +BO_ 870 AWV: 8 XXX + SG_ CHECKSUM : 0|8@1+ (1,0) [0|255] "" Vector__XXX + SG_ COUNTER : 8|4@1+ (1,0) [0|15] "" Vector__XXX + SG_ AWV_Text : 12|4@1+ (1,0) [0|14] "" Vector__XXX + SG_ AWV_1_Freigabe : 16|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_1_Prefill : 17|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_1_Parameter : 18|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AWV_only : 20|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_CityANB_Auspraegung : 21|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Halten : 22|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ANB_Teilbremsung_Freigabe : 23|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Status : 24|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Fehler : 25|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_SU_Warnzeit : 26|2@1+ (1,0) [0|3] "" Vector__XXX + SG_ AWV_2_SU_Bremsruck : 28|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_SU_Gong : 29|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_SU_Lampe : 30|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Umfeldwarn : 31|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Freigabe : 32|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Ruckprofil : 33|3@1+ (1,0) [0|7] "" Vector__XXX + SG_ AWV_2_Warnton : 36|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Warnsymbol : 37|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Infoton : 38|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Gurtstraffer : 39|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Konfiguration_Menueanf : 40|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Konfiguration_Vorw_Menueanf : 41|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Konfiguration_Status : 42|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_Konfiguration_Vorw_Status : 43|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ AWV_2_Abstandswarnung : 51|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ANB_Zielbremsung_Freigabe : 52|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ANB_CM_Anforderung : 53|1@1+ (1,0) [0|1] "" Vector__XXX + SG_ ANB_Ziel_Teilbrems_Verz_Anf : 54|10@1+ (0.024,-20.016) [0|1023] "Unit_MeterPerSeconSquar" Vector__XXX + +BO_ 1470 LDW_Status: 8 XXX + SG_ LDW_Lernmodus_rechts : 0|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Lernmodus_links : 2|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Lernmodus : 9|3@1+ (1,0) [0|3] "" XXX + SG_ LDW_Textbits : 12|4@1+ (1,0) [0|15] "" XXX + SG_ LDW_Gong : 16|2@1+ (1,0) [0|3] "" XXX + SG_ LDW_Kameratyp : 18|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Lampe_gelb : 19|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Lampe_gruen : 20|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_SW_Warnung_links : 21|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_SW_Warnung_rechts : 22|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_KD_Fehler : 23|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_DLC : 24|8@1+ (0.01,-1.25) [-1.25|1.25] "" XXX + SG_ LDW_TLC : 32|5@1+ (0.1,0) [0|3] "" XXX + SG_ LDW_Seite_DLCTLC : 37|1@1+ (1,0) [0|1] "" XXX + SG_ LDW_Frueh_Spaet : 38|2@1+ (1,0) [0|3] "" XXX + +BO_ 428 Bremse_8: 8 XXX + SG_ BR8_Checksumme : 0|8@1+ (1,0) [0|255] "" XXX + SG_ BR8_Zaehler : 8|4@1+ (1,0) [0|15] "" XXX + SG_ BR8_Sta_ACC_Anf : 12|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Verz_EPB_akt : 13|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Sta_Br_temp : 14|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Sta_Br_Druck : 15|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_TolAbgl_HL : 16|8@1+ (0.048828125,-6.201171875) [-6.201171875|6.15234375] "Unit_PerCent" XXX + SG_ BR8_TolAbgl_HR : 24|8@1+ (0.048828125,-6.201171875) [-6.201171875|6.15234375] "Unit_PerCent" XXX + SG_ BR8_Istbeschl : 32|9@1+ (0.02,-7.22) [-7.22|2.98] "Unit_MeterPerSeconSquar" XXX + SG_ BR8_Sta_HW_BLS : 41|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_QB_LBeschl : 42|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_ESC_Mode : 43|2@1+ (1,0) [0|3] "" XXX + SG_ BR8_aktBrSyst : 45|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Fa_bremst : 46|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_StaBrSyst : 47|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Laengsbeschl : 48|10@1+ (0.03125,-16) [-15.96875|15.9375] "Unit_MeterPerSeconSquar" XXX + SG_ BR8_Sta_ADR_BR : 58|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Quattro : 59|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Sta_VerzReg : 60|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Sta_BLS : 61|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Verz_EPB : 62|1@1+ (1,0) [0|1] "" XXX + SG_ BR8_Check_EPB : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 928 Bremse_10: 8 XXX + SG_ B10_Checksumme : 0|8@1+ (1,0) [0|255] "" XXX + SG_ B10_Zaehler : 8|4@1+ (1,0) [0|15] "" XXX + SG_ B10_QB_Wegimp_VL : 12|1@1+ (1,0) [0|1] "" XXX + SG_ B10_QB_Wegimp_VR : 13|1@1+ (1,0) [0|1] "" XXX + SG_ B10_QB_Wegimp_HL : 14|1@1+ (1,0) [0|1] "" XXX + SG_ B10_QB_Wegimp_HR : 15|1@1+ (1,0) [0|1] "" XXX + SG_ B10_Wegimp_VL : 16|10@1+ (1,0) [0|1000] "" XXX + SG_ B10_Wegimp_VR : 26|10@1+ (1,0) [0|1000] "" XXX + SG_ B10_Wegimp_HL : 36|10@1+ (1,0) [0|1000] "" XXX + SG_ B10_Wegimp_HR : 46|10@1+ (1,0) [0|1000] "" XXX + SG_ B10_QB_Fahrtr_VL : 56|1@1+ (1,0) [0|1] "" XXX + SG_ B10_QB_Fahrtr_VR : 57|1@1+ (1,0) [0|1] "" XXX + SG_ B10_QB_Fahrtr_HL : 58|1@1+ (1,0) [0|1] "" XXX + SG_ B10_QB_Fahrtr_HR : 59|1@1+ (1,0) [0|1] "" XXX + SG_ B10_Fahrtr_VL : 60|1@1+ (1,0) [0|1] "" XXX + SG_ B10_Fahrtr_VR : 61|1@1+ (1,0) [0|1] "" XXX + SG_ B10_Fahrtr_HL : 62|1@1+ (1,0) [0|1] "" XXX + SG_ B10_Fahrtr_HR : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 835 RDK_Status: 3 XXX + SG_ RKS_Reifen_VL : 0|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Reifen_VR : 1|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Reifen_HL : 2|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Reifen_HR : 3|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Reifen_RR : 4|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Warnung_2 : 5|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Warnung_1 : 6|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Systemfehler : 7|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Kalibrier_abgew : 8|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Druckdiff_Vorn : 9|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Druckdiff_Hinten : 10|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Befuellung_RR_low : 11|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Funkstoerung : 12|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_System_Aus : 13|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_KD_Fehler : 15|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Lampe : 16|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Ton : 17|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Gong : 18|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_RDK_Blinkbit : 19|1@1+ (1,0) [0|1] "" XXX + SG_ RKS_Teillast : 20|1@1+ (1,0) [0|1] "" XXX + +BO_ 914 Gate_Komf_2: 8 XXX + SG_ GK2_Sta_LSM : 0|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_Lichtsensor : 1|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_Licht1 : 2|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_VSG : 3|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_Schluessel : 4|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_Profil : 5|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_Clima2 : 6|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_BSG4 : 7|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Sta_Kessy_4 : 8|1@1+ (1,0) [0|1] "" XXX + SG_ BS4_Gleitende_Leuchtw_Anf : 9|1@1+ (1,0) [0|1] "" XXX + SG_ BS4_GLW_Fernlicht_Anf : 10|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Blk_L_Kontrolle : 11|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Blk_R_Kontrolle : 12|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_LS_KomFehler : 14|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_LS_def : 15|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Helligkeit : 16|3@1+ (714.286,0) [0|5000.002] "Unit_Lux" XXX + SG_ GK2_VD_zu_ver : 19|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_VD_entriegelt : 20|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_VD_offen_ver : 21|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Verdeck_Anf : 22|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_VDKD_auf : 23|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Schluessel : 24|4@1+ (1,0) [0|15] "" XXX + SG_ GK2_Hardtop : 28|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_AFL_Schalter : 29|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Nebelschluss : 30|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_EM_LIN_ungueltig : 31|1@1+ (1,0) [0|1] "" XXX + SG_ GK2_Profil : 32|4@1+ (1,0) [0|15] "" XXX + SG_ GK2_Kl_StSt_Info : 36|2@1+ (1,0) [0|3] "" XXX + SG_ GK2_BSG_StSt_Info : 38|2@1+ (1,0) [0|3] "" XXX + SG_ GK2_BEM_P_Generator : 40|8@1+ (50,0) [0|12700] "Unit_Watt" XXX + SG_ GK2_BEM_Abschaltstufen : 48|3@1+ (1,0) [0|7] "" XXX + SG_ GK2_BEM_DFM : 51|5@1+ (3.225,0.025) [0.025|100] "Unit_PerCent" XXX + SG_ GK2_Kessy_StSt_Info : 56|2@1+ (1,0) [0|3] "" XXX + SG_ GK2_BEM_StSt_Info : 58|2@1+ (1,0) [0|3] "" XXX + +BO_ 954 SWA_1: 8 SWA + SG_ SWA_Textbits : 12|4@1+ (1,0) [0|15] "" XXX + SG_ SWA_Gong : 16|2@1+ (1,0) [0|3] "" XXX + SG_ SWA_Sta_passiv : 19|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Sta_aktiv : 20|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Infostufe_SWA_li : 26|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Warnung_SWA_li : 27|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Infostufe_SWA_re : 42|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_Warnung_SWA_re : 43|1@1+ (1,0) [0|1] "" XXX + SG_ SWA_KD_Fehler : 59|1@1+ (1,0) [0|1] "" XXX + +BO_ 1175 Parkhilfe_01: 8 XXX + SG_ PH_Abschaltursache : 13|3@1+ (1,0) [0|7] "" XXX + SG_ PH_Opt_Anzeige_V_ein : 16|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Opt_Anzeige_H_ein : 17|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Opt_Anz_V_Hindernis : 18|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Opt_Anz_H_Hindernis : 19|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Tongeber_V_aktiv : 20|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Tongeber_H_aktiv : 21|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Tongeber_mute : 22|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Anf_Audioabsenkung : 23|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Frequenz_hinten : 32|4@1+ (1,0) [0|15] "" XXX + SG_ PH_Lautstaerke_hinten : 36|4@1+ (1,0) [0|15] "" XXX + SG_ PH_Frequenz_vorn : 40|4@1+ (1,0) [0|15] "" XXX + SG_ PH_Lautstaerke_vorn : 44|4@1+ (1,0) [0|15] "" XXX + SG_ PH_Trigger_Bildaufschaltung : 48|1@1+ (1,0) [0|1] "" XXX + SG_ PH_StartStopp_Info : 49|2@1+ (1,0) [0|3] "" XXX + SG_ PH_Aufbauten_erk : 51|1@1+ (1,0) [0|1] "" XXX + SG_ PH_BerErk_vorn : 52|2@1+ (1,0) [0|3] "" XXX + SG_ PH_BerErk_hinten : 54|2@1+ (1,0) [0|3] "" XXX + SG_ PH_defekt : 56|1@1+ (1,0) [0|1] "" XXX + SG_ PH_gestoert : 57|1@1+ (1,0) [0|1] "" XXX + SG_ PH_Systemzustand : 58|3@1+ (1,0) [0|7] "" XXX + SG_ PH_Display_Kundenwunsch : 61|2@1+ (1,0) [0|3] "" XXX + SG_ PH_KD_Fehler : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 1463 Bremse_11: 8 XXX + SG_ B11_HydHalten : 13|1@1+ (1,0) [0|1] "" XXX + SG_ B11_Br_StSt_Info : 14|2@1+ (1,0) [0|3] "" XXX + SG_ B11_OBD_Nib_VL : 16|4@1+ (1,0) [0|15] "" XXX + SG_ B11_OBD_Nib_VR : 20|4@1+ (1,0) [0|15] "" XXX + SG_ B11_OBD_Nib_HL : 24|4@1+ (1,0) [0|15] "" XXX + SG_ B11_OBD_Nib_HR : 28|4@1+ (1,0) [0|15] "" XXX + SG_ B11_EPB_Steller_akt : 32|1@1+ (1,0) [0|1] "" XXX + SG_ B11_EPB_Steller_gue : 33|1@1+ (1,0) [0|1] "" XXX + +BO_ 1500 Soll_Verbauliste_neu: 8 XXX + SG_ VL1_Motor_SG : 0|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Getr_SG : 1|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_ABS : 2|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Kombi : 3|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_LSM : 4|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Airbag : 5|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Lenkhilfe : 6|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_dyn_LWR : 7|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_res_08 : 8|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Allrad : 9|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_ADR : 10|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_ADR_getrennt : 11|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_EPB : 12|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_res_13 : 13|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Daempfer : 14|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Quersperre : 15|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_MotorSlave : 16|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_SWA : 17|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_HCA : 18|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_RKA_Plus : 19|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_PLA : 20|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_WFS_KBI : 21|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Kombi_KBI : 22|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Soll_eq_Ist : 23|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_BSG_Komf : 24|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_ZKE : 25|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_TSG_FT : 26|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_TSG_BT : 27|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_TSG_HL : 28|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_TSG_HR : 29|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Memory : 30|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Dachmodul_K : 31|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Zentralelektrik_II : 32|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_RDK : 33|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Lenksaeule : 34|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Gateway : 35|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Clima_Komf : 36|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Einparkhilfe : 37|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_PTC_Heizung : 38|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Standheiz : 39|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Verdeck : 40|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_RSE_I : 41|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_res_42 : 42|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_MDI_I : 43|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Anhaenger : 44|1@1+ (1,0) [0|1] "" SWA + SG_ VL1_Memory_BF : 45|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Easy_Entry_VF : 46|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Easy_Entry_VB : 47|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Heckdeckel : 48|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Rearview : 49|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Sonderfzg_SG : 50|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Tastenmodul : 51|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Kompass : 52|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_WFS_K : 53|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_GSM_Pager : 54|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_InfoElektronik : 55|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_DSP : 56|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_DAB : 57|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Telematik : 58|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Navigation : 59|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_TV_Tuner : 60|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Neigungsmodul_I : 61|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Radio : 62|1@1+ (1,0) [0|1] "" XXX + SG_ VL1_Telefon : 63|1@1+ (1,0) [0|1] "" XXX + +BO_ 1490 Ident: 8 XXX + SG_ IDT_Mux M : 0|2@1+ (1,0) [0|2] "" XXX + SG_ IDT_Geheimnis_1 m0 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_4 m1 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_11 m2 : 8|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_Geheimnis_2 m0 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_5 m1 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_12 m2 : 16|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_Geheimnis_3 m0 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_6 m1 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_13 m2 : 24|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_Geheimnis_4 m0 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_7 m1 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_14 m2 : 32|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_1 m0 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_8 m1 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_15 m2 : 40|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_2 m0 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_9 m1 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_16 m2 : 48|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_3 m0 : 56|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_10 m1 : 56|8@1+ (1,0) [0|255] "" XXX + SG_ IDT_VIN_17 m2 : 56|8@1+ (1,0) [0|255] "" XXX + +BO_ 2000 Diagnose_1: 8 XXX + SG_ DI1_VerlernZaehl : 0|8@1+ (1,0) [0|254] "" XXX + SG_ DI1_km_Stand : 8|20@1+ (1,0) [0|1048575] "Unit_KiloMeter" XXX + SG_ DI1_Jahr : 28|7@1+ (1,2000) [2000|2127] "Unit_Year" XXX + SG_ DI1_Monat : 35|4@1+ (1,0) [1|12] "Unit_Month" XXX + SG_ DI1_Tag : 39|5@1+ (1,0) [0|31] "Unit_Day" XXX + SG_ DI1_Stunde : 44|5@1+ (1,0) [0|23] "Unit_Hours" XXX + SG_ DI1_Minute : 49|6@1+ (1,0) [0|59] "Unit_Minut" XXX + SG_ DI1_Sekunde : 55|6@1+ (1,0) [0|59] "Unit_Secon" XXX + SG_ DI1_KM_Stand_alt : 62|1@1+ (1,0) [0|1] "" XXX + SG_ DI1_Zeit_alt : 63|1@1+ (1,0) [0|1] "" XXX + +CM_ SG_ 80 Checksumme_Airbag_1 "Checksum Airbag_1"; +CM_ SG_ 80 Zaehler_Airbag_1 "Counter Airbag_1"; + +CM_ BO_ 194 "Steering wheel angle message 1 - Contains steering angle, speed, and status information"; + +CM_ SG_ 194 LW1_LRW "Steering wheel angle (0 = straight ahead, 7FFFh = stop)"; +CM_ SG_ 194 LW1_LRW_Sign "Steering angle sign: 0=positive (left), 1=negative (right)"; +CM_ SG_ 194 LW1_Lenk_Gesch "Steering wheel angular velocity (0 = no movement, 7FFFh = max speed)"; +CM_ SG_ 194 LW1_Gesch_Sign "Angular velocity sign: 0=positive, 1=negative"; +CM_ SG_ 194 LW1_ID "Calibration ID - 0=not calibrated, 128=calibrated (PQ35/46/VW32x/VW411)"; +CM_ SG_ 194 LW1_Initquelle "Initialization source"; +CM_ SG_ 194 LW1_Status "Sensor status"; +CM_ SG_ 194 LW1_Sta_KL30 "Terminal 30 status (Kostal sensor)"; +CM_ SG_ 194 LW1_Zaehler "Free running message counter"; +CM_ SG_ 194 LW1_Kodier "Coding data (multiplex output depends on counter)"; +CM_ SG_ 194 LW1_CRC "Checksum - One's complement of 8-bit sum of bytes 1,2,3,4,6"; + +CM_ SG_ 210 LM_Offset "centiNewton-meters for ease of calculation without FP math in Panda"; +CM_ SG_ 210 Vib_Amp "Steering wheel haptic, amplitude"; +CM_ SG_ 210 Vib_Freq "Steering wheel haptic, frequency"; + +CM_ SG_ 416 BR1_ASR_Anf "ASR request to engine - requests in bytes 5 and 6 to be executed"; +CM_ SG_ 416 BR1_MSR_Anf "MSR request - when set, byte 6 contains inverse MSR torque"; +CM_ SG_ 416 BR1_ABS_Brems "ABS control active (including pressure reduction)"; +CM_ SG_ 416 BR1_EDS_Ongr "Electronic differential lock intervention"; +CM_ SG_ 416 BR1_ESP_Ongr "ESP driving dynamics control intervention"; +CM_ SG_ 416 BR1_ASR_Ongr "ASR transmission switching influence"; +CM_ SG_ 416 BR1_EBV_Ongr "Electronic brake force distribution intervention"; +CM_ SG_ 416 BR1_Lampe_ABS "ABS safety warning lamp"; +CM_ SG_ 416 BR1_Lampe_ASR "ASR/ESP lamp (including flashing info)"; +CM_ SG_ 416 BR1_Lampe_BK "Brake control lamp (red)"; +CM_ SG_ 416 BR1_Lichtschalt "Brake light switch / brake pressure threshold exceeded"; +CM_ SG_ 416 BR1_StaDruckschw "Brake test switch / pressure threshold status"; +CM_ SG_ 416 BR1_MAD "OBD rough road suppression"; +CM_ SG_ 416 BR1_Sta_MAD "Rough road suppression status"; +CM_ SG_ 416 BR1_Diagnose "ABS diagnosis mode active"; +CM_ SG_ 416 BR1_BKV_active "Active brake booster installed and not faulty"; +CM_ SG_ 416 BR1_Rad_kmh "Vehicle speed (mean of driven wheels or ABS reference)"; +CM_ SG_ 416 BR1_ASRMo_sl "ASR engagement torque slow (0-99.06%)"; +CM_ SG_ 416 BR1_ASRMo_fa "ASR engagement torque fast when MSR_Anf=0 (0-99.06%)"; +CM_ SG_ 416 BR1_MSR_Mo_inv "Inverse MSR torque when MSR_Anf=1 (99.06-0%)"; +CM_ SG_ 416 BR1_MSR_Mo "MSR engagement torque (0-99.06%)"; +CM_ SG_ 416 BR1_Zaehler "Message counter to mark intervention moment"; +CM_ SG_ 416 BR1_ASR_ESP "Control unit type: 0=ABS/EDS, 1=ASR/ESP/MABS"; +CM_ SG_ 416 BR1_ESPASR_passive "ESP/ASR passive or deactivated by driver"; +CM_ SG_ 416 BR1_Sta_ESP "ESP error status (fault memory entry)"; +CM_ SG_ 416 BR1_Ersatz_Kmh "Speed is substitute value (sensor defect)"; + +CM_ SG_ 640 inneres_Motor_Moment "Engine Indicated Torque"; +CM_ SG_ 640 Fahrerwunschmoment "Driver Requested Torque"; +CM_ SG_ 640 mechanisches_Motor_Verlustmomen "Mechanical Torque Loss"; +CM_ SG_ 640 Fahrpedalwert_oder_Drosselklapp "Accelerator Pedal or Throttle Position"; +CM_ SG_ 640 Motordrehzahl "Engine Speed"; +CM_ SG_ 640 Momentenangaben_ungenau "Approximate Torque Values"; +CM_ SG_ 640 inneres_Motor_Moment_ohne_exter "Inner torque without external"; + +CM_ SG_ 644 MOB_CHECKSUM "Checksum MOB"; +CM_ SG_ 644 MOB_COUNTER "Counter MOB"; + +CM_ BO_ 648 "Motor message 2 - Contains engine status, temperatures, and torque information"; +CM_ SG_ 648 MO2_Mp_Code "Multiplex code - switches after 4 transmissions"; +CM_ SG_ 648 MO2_Getr_Code "Transmission code (multiplex value when Mp_Code=2)"; +CM_ SG_ 648 MO2_max_Mo "Maximum torque MDI (multiplex value when Mp_Code=3)"; +CM_ SG_ 648 MO2_CAN_Vers "CAN version (multiplex value when Mp_Code=0)"; +CM_ SG_ 648 MO2_Motor_Code "Motor code (multiplex value when Mp_Code=1)"; +CM_ SG_ 648 MO2_Kuehlm_T "Engine coolant temperature or substitute value"; +CM_ SG_ 648 MO2_BLS "Brake light switch - unfiltered raw signal"; +CM_ SG_ 648 MO2_BTS "Brake test switch"; +CM_ SG_ 648 MO2_Sta_Kuehlm "Coolant temperature status - 0=OK, 1=Not OK"; +CM_ SG_ 648 MO2_Sta_Klima "Air conditioning compressor status"; +CM_ SG_ 648 MO2_Sta_No_Bet "Normal operation status (Terminal 15 on, init complete)"; +CM_ SG_ 648 MO2_Status_TSK "Drive train coordinator status"; +CM_ SG_ 648 MO2_Sta_GRA "GRA/ACC status"; +CM_ SG_ 648 TSK_Limiter_ausgewaehlt "Speed limiter selected"; +CM_ SG_ 648 MO2_GRAregelt "GRA regulating to displayed speed"; +CM_ SG_ 648 MO2_Sport_Error "Sport mode error (Porsche Cayenne)"; +CM_ SG_ 648 MO2_OffRoad "OffRoad mode active"; +CM_ SG_ 648 MO2_RME_Gehalt "Rapeseed oil methyl ester content (diesel)"; +CM_ SG_ 648 MO2_GRA_Soll "GRA target speed setpoint"; +CM_ SG_ 648 MO2_LL_Solldz "Idle target speed"; +CM_ SG_ 648 MO2_Begr_Mo "Limiting torque - max possible at speed"; +CM_ SG_ 648 MO2_Mo_ZWR "Minimum engine torque with ignition angle retardation"; + +CM_ SG_ 896 Drosselklappenpoti "Throttle Position"; +CM_ SG_ 896 Motor_Wunschdrehzahl "Desired engine speed"; +CM_ SG_ 896 Motordrehzahlbeeinflussung "Shift Target Influence"; +CM_ SG_ 896 Fahrpedal_Rohsignal "Accelerator Pedal Position"; +CM_ SG_ 896 Ansauglufttemperatur "Intake Air Temperature"; +CM_ SG_ 896 Kein_E_Gas "ETB flag"; +CM_ SG_ 896 Kein_Start_Stop "Start/stop flag"; +CM_ SG_ 896 Rad_Wunschmoment "Desired wheel torque"; + +CM_ SG_ 912 GK1_Fa_Tuerkont "Status of the driver's door rotary latch"; +CM_ SG_ 912 BSK_HL_geoeffnet "Status of the rear left door rotary latch"; +CM_ SG_ 912 BSK_HR_geoeffnet "Status of the rear right door rotary latch"; +CM_ SG_ 912 BSK_BT_geoeffnet "Status of the passenger door rotary latch"; +CM_ SG_ 912 BSK_HD_Hauptraste "Status of trunk lid main detent"; + +CM_ SG_ 1088 Zaehler_Getriebe_1 "Counter Getriebe_1"; +CM_ SG_ 1088 Waehlhebelposition__Getriebe_1_ "Gear Selector Position"; +CM_ SG_ 1088 inneres_Soll_Motormoment "Desired Inner Torque"; +CM_ SG_ 1088 Gang_eingelegt "Gear Engaged"; +CM_ SG_ 1088 Schaltabsicht "Shift Intent"; +CM_ SG_ 1088 Kuehlleistung "Cooling Power"; +CM_ SG_ 1088 Wandlerverlustmoment "Converter Torque Loss"; +CM_ SG_ 1088 Getriebe_Notlauf "Transmission_Notlauf"; +CM_ SG_ 1088 Zielgang_oder_eingelegter_Gang "target_gear_or_gear_in_engagement"; +CM_ SG_ 1088 Uebertragungsfunktion "transfer function"; +CM_ SG_ 1088 EGS_Anforderung "EGS Requirement"; +CM_ SG_ 1088 Schaltung_aktiv__Getriebe_1_ "Shift Activity"; + +CM_ SG_ 1056 Fehlerstatus_Aussentemp__4_1 "ambient temp error"; +CM_ SG_ 1056 Fehlerstatus_Oeltemperatur_4_1 "oil temp error"; +CM_ SG_ 1056 Fehlerst__Kuehlmitteltemp__4_1 "water temp error"; +CM_ SG_ 1056 Aussentemperatur_gefiltert "outside temp, filtered"; +CM_ SG_ 1056 Oeltemperatur_4_1 "kombi oil temperature"; +CM_ SG_ 1056 Kuehlmitteltemp__4_1__Kombi_2_ "kombi coolant temperature"; + +CM_ SG_ 1096 Zaehler_Waehlhebel_1 "Counter Waehlhebel_1"; + +CM_ SG_ 1152 CHECKSUM "Checksum Motor_5"; +CM_ SG_ 1152 Anlasser_Ausspuren "Starter Disable"; +CM_ SG_ 1152 Anlasser_Freigabe "Starter Release"; +CM_ SG_ 1152 Klimadrucksignal__Motor_5_ "Air conditioning pressure signal"; +CM_ SG_ 1152 Kraftstoffverbrauchssignal "Fuel consumption signal"; +CM_ SG_ 1152 K_hlerluefteransteuerung "Cooling fan control signal"; +CM_ SG_ 1152 Klimakompressor_Leistungsreduzi "Air conditioning compressor power reduction flag"; +CM_ SG_ 1152 Klimakompressor_aus__Motor_5_ "Air conditioning compressor"; +CM_ SG_ 1152 Anlasser_Freigabe "Starter release"; +CM_ SG_ 1152 OBD_2_Lampe "OBD light"; +CM_ SG_ 1152 E_Gas_Lampe "ETB light"; +CM_ SG_ 1152 Ladekontroll_Lampe "Charge light"; +CM_ SG_ 1152 Vorgluehlampe__Motor_5_ "Glow light"; + +CM_ SG_ 1160 Zaehler_Motor_6 "Counter Motor_6"; +CM_ SG_ 1160 Hoeheninfo__Motor_6_ "Altitude Correction"; +CM_ SG_ 1160 Istmoment_f_r_Getriebe "Actual torque for gear"; +CM_ SG_ 1160 Sollmoment_f_r_Getriebe "Target torque for gearbox"; +CM_ SG_ 1160 Checksumme_Motor_6 "Checksum Motor_6"; +CM_ SG_ 1160 GRA_Sollbeschleunigung "GRA target acceleration"; +CM_ SG_ 1160 Ruckmeldung_Momenten "Feedback torque-integral gear intervention"; + +CM_ SG_ 1344 Zahler_Getriebe_2 "Counter Getriebe_2"; +CM_ SG_ 1344 Hochschaltlampe "Upshift Flag"; + +CM_ SG_ 1386 ACA_V_Wunsch "255=unset"; + +CM_ SG_ 1408 Zaehler_Motor_Flexia "Counter Motor_Flexia"; +CM_ SG_ 1408 Verbrennungsart "Type of combustion"; +CM_ SG_ 1408 Max_Drehmoment "Maximum torque"; +CM_ SG_ 1408 Drehzahl_MaxNorm "RPM of maximum torque"; +CM_ SG_ 1408 Hubraum "Displacement"; +CM_ SG_ 1408 Anzahl_Zylinder "Number of cylinders"; +CM_ SG_ 1408 Anzahl_Ventile "Number of valves"; +CM_ SG_ 1408 Ansaugsystem "Induction System"; +CM_ SG_ 1408 Motorleistung "Maximum engine power"; + +CM_ SG_ 1416 Ladedruck "Boost Pressure"; +CM_ SG_ 1416 Motordrehzahlgradient "Engine speed gradient"; +CM_ SG_ 1416 Hoeheninfo__Motor_7_ "Altitude correction factor"; +CM_ SG_ 1416 Oltemperatur "Oil temperature"; + +CM_ SG_ 1470 LDW_Direction "0=right,1=left"; +CM_ SG_ 1470 XX_DLCORTLC1 "Might be DLC or TLC"; +CM_ SG_ 1470 XX_DLCORTLC2 "Might be DLC or TLC, might have wrong size"; + +CM_ SG_ 1550 MFA_v_Signal_02 "0=km/h, 1=mph"; + +SG_MUL_VAL_ 416 BR1_ASRMo_fa BR1_MSR_Anf 0-0; +SG_MUL_VAL_ 416 BR1_MSR_Mo_inv BR1_MSR_Anf 1-1; + +VAL_ 194 LW1_LRW_Sign 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen"; +VAL_ 194 LW1_Gesch_Sign 0 "positives_Vorzeichen" 1 "negatives_Vorzeichen"; +VAL_ 194 LW1_ID 0 "noch_not_kalibriert" 128 "kalibriert_nur_bei_PQ35_46_VW32x_VW411"; +VAL_ 194 LW1_Initquelle 0 "Bremse_3" 1 "EPS_Bit"; +VAL_ 194 LW1_Status 0 "OK" 1 "no_initial" 2 "sporadic_failure" 3 "permanent_failure"; +VAL_ 194 LW1_Sta_KL30 0 "ok" 1 "no_init_s"; + +VAL_ 416 BR1_ASR_Anf 0 "no_requirement" 1 "ASR_requirement"; +VAL_ 416 BR1_MSR_Anf 0 "no_requirement" 1 "MSR_requirement"; +VAL_ 416 BR1_ABS_Brems 0 "no_ABS_control" 1 "ABS_control"; +VAL_ 416 BR1_EDS_Ongr 0 "no_EDS_intervention" 1 "EDS_intervention"; +VAL_ 416 BR1_ESP_Ongr 0 "no_ESP_intervention" 1 "ESP_intervention"; +VAL_ 416 BR1_ASR_Ongr 0 "no_requirement" 1 "ASR_shift_map" 2 "Downshift" 3 "Switching_ban"; +VAL_ 416 BR1_EBV_Ongr 0 "no_EBV_intervention" 1 "EBV_intervention"; +VAL_ 416 BR1_Lampe_ABS 0 "Lamp_off" 1 "Lamp_on"; +VAL_ 416 BR1_Lampe_ASR 0 "Lamp_off" 1 "Lamp_on"; +VAL_ 416 BR1_Lampe_BK 0 "Lamp_off" 1 "Lamp_on"; +VAL_ 416 BR1_Lichtschalt 0 "no_Bremsen_Schw_unterschr" 1 "Bremse_betaetigt_Schw_ueberschr"; +VAL_ 416 BR1_StaDruckschw 0 "Sta_guel_BKV_n_angest_k_Br" 1 "Sta_n_verf_BKV_angest_Br"; +VAL_ 416 BR1_MAD 0 "no_Offblendung" 1 "Offblendung"; +VAL_ 416 BR1_Sta_MAD 0 "valid" 1 "invalid"; +VAL_ 416 BR1_Diagnose 0 "no" 1 "in_Diagnose"; +VAL_ 416 BR1_BKV_active 0 "BKV_not_installed_or_fault" 1 "BKV_installed_and_not_fault"; +VAL_ 416 BR1_ASR_ESP 0 "ABS_ABS_EDS" 1 "ASR_ESP_MABS"; +VAL_ 416 BR1_ESPASR_passive 0 "ESP_ASR_activated" 1 "ESP_oder_ASR_passive_get_oder_Fktumsch_oder_Rollenmodus"; +VAL_ 416 BR1_Sta_ESP 0 "ok" 1 "Failure"; +VAL_ 416 BR1_Ersatz_Kmh 0 "OK" 1 "Substitute_value"; + +SG_MUL_VAL_ 648 MO2_Getr_Code MO2_Mp_Code 2-2; +SG_MUL_VAL_ 648 MO2_max_Mo MO2_Mp_Code 3-3; +SG_MUL_VAL_ 648 MO2_CAN_Vers MO2_Mp_Code 0-0; +SG_MUL_VAL_ 648 MO2_Motor_Code MO2_Mp_Code 1-1; + +VAL_ 648 MO2_Mp_Code 0 "CAN_Stand" 1 "Motor_Kod" 2 "Getriebe_Kod" 3 "MDI_Max"; + +VAL_ 648 MO2_Getr_Code 0 "_5HP19" 1 "_5HP24" 2 "AG4" 3 "VL300" 4 "VQ250" 5 "VQ35" 6 "AG4_yestco" 7 "AG5_yestco" 8 "autom_Kupplung" 9 "autom_Kupplung_mit_ASG" 10 "AG6_yestco_ZF_6HP_AISIN" 11 "DQ500_DQ250_DQ200" 12 "SQ100_SQ200" 14 "AL1000_AL551_AL951_ZF8HPx" 15 "Handschalter_konv" 16 "DL800" 17 "E_Fahrzeug__Single_Gear"; + +VAL_ 648 MO2_BLS 0 "no_Bremsen" 1 "Bremse_betaetigt"; +VAL_ 648 MO2_BTS 0 "no_braking" 1 "Brake_activated"; +VAL_ 648 MO2_Sta_Kuehlm 0 "Temperature_ok" 1 "Temperature_not_ok"; +VAL_ 648 MO2_Sta_Klima 0 "Climate_off" 1 "Climate_on"; +VAL_ 648 MO2_Sta_No_Bet 0 "no_Normalbetrieb" 1 "Normalbetrieb"; +VAL_ 648 MO2_Status_TSK 0 "TSK_not_available" 1 "TSK_available"; +VAL_ 648 MO2_Sta_GRA 0 "ADR_GRA_off" 1 "gra_activated_lamp_on" 2 "gra_overdriven_lamp_on" 3 "ADR_gra_faulted"; +VAL_ 648 TSK_Limiter_ausgewaehlt 0 "no_limiter_selected" 1 "Limiter_Selected"; +VAL_ 648 MO2_GRAregelt 0 "no" 1 "yes"; +VAL_ 648 MO2_Sport_Error 0 "no_Failure" 1 "Failure"; +VAL_ 648 MO2_OffRoad 0 "not_active" 1 "active"; + +VAL_ 870 AWV_Text 0 "kein_Text" 1 "FrontAssist_aus" 2 "FrontAssist_startet" 3 "FrontAssist_Warnung" 4 "FrontAssist_Sens_reinig" 5 "FrontAssist_Failure" 6 "FrontAssist_Demo" 7 "Vorhalt" 8 "Bremsung_wird_gerade_durchgefuehrt" 9 "Sensor_not_verfuegbar" 10 "Sensor_reinigen" 11 "Service_notwendig_Failure" 12 "Funktion_vom_Fahrer_deactivated" 13 "Funktion_vom_Fahrer_activated" 14 "FrontAssist_zur_Zeit_not_verfuegbar__rev_Failure"; +VAL_ 870 AWV_1_Freigabe 0 "nicht_freigegeben" 1 "freigegeben"; +VAL_ 870 AWV_1_Prefill 0 "keine_Prefill_Anf" 1 "Prefill_Anf"; +VAL_ 870 AWV_1_Parameter 0 "Defaultparametersatz" 1 "Par_leicht_erh_Empf" 2 "Par_erh_Empf" 3 "Par_hoechster_Empf"; +VAL_ 870 AWV_only 0 "ACC_und_AWV_verbaut" 1 "AWV_ohne_ACC_verbaut"; +VAL_ 870 AWV_CityANB_Auspraegung 0 "autom_Bremsung_im_ges_vBereich" 1 "autom_Bremsung_im_def_vBereich"; +VAL_ 870 AWV_Halten 0 "keine_Anforderung" 1 "Anforderung_das_Fzg_im_Stillstand_zu_halten"; +VAL_ 870 ANB_Teilbremsung_Freigabe 0 "Teilbremsung_nicht_freigegeben" 1 "Teilbremsung_freigegeben"; +VAL_ 870 AWV_2_Status 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 870 AWV_2_Fehler 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 870 AWV_2_SU_Warnzeit 0 "frueh" 1 "normal" 2 "spaet" 3 "adaptiv"; +VAL_ 870 AWV_2_SU_Bremsruck 0 "Bremsruck_deaktiviert" 1 "Bremsruck_aktiviert"; +VAL_ 870 AWV_2_SU_Gong 0 "Gong_deaktiviert" 1 "Gong_aktiviert"; +VAL_ 870 AWV_2_SU_Lampe 0 "Lampe_deaktiviert" 1 "Lampe_aktiviert"; +VAL_ 870 AWV_2_Umfeldwarn 0 "keine_Warnung" 1 "Warnung"; +VAL_ 870 AWV_2_Freigabe 0 "keine_Ruckfreigabe" 1 "Ruckfreigabe"; +VAL_ 870 AWV_2_Ruckprofil 0 "kein_Ruck" 1 "Ruckprofil_1" 2 "Ruckprofil_2" 3 "Ruckprofil_3" 4 "Ruckprofil_4" 5 "Ruckprofil_5" 6 "not_erlaubt" 7 "not_erlaubt"; +VAL_ 870 AWV_2_Warnton 0 "Aus" 1 "Ein"; +VAL_ 870 AWV_2_Warnsymbol 0 "Aus" 1 "Ein"; +VAL_ 870 AWV_Infoton 0 "Aus" 1 "Ein"; +VAL_ 870 AWV_2_Gurtstraffer 0 "Gurt_not_straffen" 1 "Gurt_straffen"; +VAL_ 870 AWV_Konfiguration_Menueanf 0 "Menue_deaktivieren" 1 "Menue_aktivieren"; +VAL_ 870 AWV_Konfiguration_Vorw_Menueanf 0 "Menue_deaktivieren" 1 "Menue_aktivieren"; +VAL_ 870 AWV_Konfiguration_Status 0 "AWV_inaktiv" 1 "AWV_aktiv"; +VAL_ 870 AWV_Konfiguration_Vorw_Status 0 "AWV_Vorwarnung_inaktiv" 1 "AWV_Vorwarnung_aktiv"; +VAL_ 870 AWV_2_Abstandswarnung 0 "kein_Warnhinweis" 1 "Warnhinweis"; +VAL_ 870 ANB_Zielbremsung_Freigabe 0 "Zielbremsung_nicht_freigegeben" 1 "Zielbremsung_freigegeben"; +VAL_ 870 ANB_CM_Anforderung 0 "keine_Anforderung" 1 "Anforderung_aktiv"; + +VAL_ 872 ACS_Sta_ADR 2 "ADR_passiv" 0 "ADR_nicht_aktiv" 1 "ADR_aktiv" 3 "irrev_Fehler" ; +VAL_ 872 ACS_ADR_Schub 1 "Verz_begr_auf_Schub" 0 "Verz_nicht_begr_auf_Schub" ; +VAL_ 872 ACS_Schubabsch 1 "SA_nicht_zulaessig" 0 "SA_zulaessig" ; +VAL_ 872 ACS_StSt_Info 3 "Systemfehler" 0 "Motorlauf_nn" 1 "Stoppverbot_Motoranlauf_nn" 2 "Motoranlauf_notwendig" ; +VAL_ 872 ACS_MomEingriff 1 "MomEingr_verhindern" 0 "keine_Beeinfl_MomEingr_Mot" ; +VAL_ 872 ACS_Typ_ACC 0 "Basis_ACC" 1 "ACC_mit_FollowToStop" 3 "frei" 2 "frei" ; +VAL_ 872 ACS_FreigSollB 0 "Sollbeschl_nicht_freigeg" 1 "Sollbeschl_freigeg" ; +VAL_ 872 ACS_Sollbeschl 2046 "ADR_nicht_aktiv" 2047 "Fehler" ; +VAL_ 872 ACS_Anhaltewunsch 0 "kein_Haltewunsch" 1 "Fzg_haelt_an" ; +VAL_ 872 ACS_Fehler 1 "Fehlerspeichereintrag" 0 "kein_Fehlerspeichereintrag" ; +VAL_ 872 ACS_zul_Regelabw 254 "ADR_nicht_aktiv" 255 "Fehler" ; +VAL_ 872 ACS_max_AendGrad 254 "Neutralwert" 0 "Neutralwert" 255 "Fehler" ; + +VAL_ 978 LH2_Sta_HCA 0 "disabled" 1 "initializing" 2 "fault" 3 "ready" 4 "rejected" 5 "active" 7 "active"; +VAL_ 1088 Waehlhebelposition__Getriebe_1_ 8 "P" 7 "R" 6 "N" 5 "D" 9 "U" 12 "S" 14 "T" 10 "T" 11 "T"; + +VAL_ 1386 ACA_StaACC 6 "ACC_rev_aus" 0 "Hauptschalter_aus" 4 "ACC_im_Hintergrund" 3 "ACC_aktiv" 1 "Reserve" 2 "ACC_passiv" 7 "ACC_irrev_aus" 5 "frei" ; +VAL_ 1386 ACA_ID_StaACC 0 "keine_Anzeige" ; +VAL_ 1386 ACA_Fahrerhinw 1 "Ein" 0 "Aus" ; +VAL_ 1386 ACA_AnzDisplay 1 "Anzeige_erw" 0 "Anzeige_nicht_erw" ; +VAL_ 1386 ACA_Zeitluecke 3 "Zeitluecke3" 10 "Zeitluecke10" 4 "Zeitluecke4" 14 "Zeitluecke14" 11 "Zeitluecke11" 2 "Zeitluecke2" 13 "Zeitluecke13" 9 "Zeitluecke9" 1 "Zeitluecke1" 8 "Zeitluecke8" 5 "Zeitluecke5" 15 "Zeitluecke15" 0 "nicht_definiert" 12 "Zeitluecke12" 6 "Zeitluecke6" 7 "Zeitluecke7" ; +VAL_ 1386 ACA_V_Wunsch 255 "kein_Wert_im_Speicher" ; +VAL_ 1386 ACA_kmh_mph 0 "km_h" 1 "mph" ; +VAL_ 1386 ACA_Akustik1 0 "kein_Gong" 1 "Gong" ; +VAL_ 1386 ACA_Akustik2 0 "kein_Summer" 1 "Summer" ; +VAL_ 1386 ACA_PrioDisp 1 "mittlere_Prio" 3 "keine_Anzeige_Anf" 0 "hohe_Prio" 2 "niedrige_Prio" ; +VAL_ 1386 ACA_gemZeitl 6 "Zeitluecke6" 2 "Zeitluecke2" 7 "Zeitluecke7" 13 "Zeitluecke13" 11 "Zeitluecke11" 4 "Zeitluecke4" 8 "Zeitluecke8" 12 "Zeitluecke12" 10 "Zeitluecke10" 0 "Kein_Objekt_erfasst" 1 "Zeitluecke1" 3 "Zeitluecke3" 9 "Zeitluecke9" 15 "Zeitluecke15" 14 "Zeitluecke14" 5 "Zeitluecke5" ; +VAL_ 1386 ACA_ACC_Verz 0 "ACC_verzoegert_nicht" 1 "ACC_verzoegert" ; +VAL_ 1386 ACA_StaGRA 3 "GRA_aktiv" 4 "GRA_uebertreten" 2 "GRA_passiv" 0 "Hauptschalter_aus" 6 "frei" 7 "GRA_Fehler" 1 "Reserve" 5 "frei" ; +VAL_ 1386 ACA_ID_StaGRA 0 "keine_Anzeige" ; +VAL_ 1386 ACA_Codierung 0 "ACC" 1 "GRA" ; +VAL_ 1386 ACA_Tachokranz 0 "nicht_beleuchtet" 1 "beleuchtet" ; +VAL_ 1386 ACA_Aend_Zeitluecke 1 "Anzeige_angef" 0 "keine_Anzeige" ; + +VAL_ 1472 EP1_Fehler_Sta 0 "volle_Funktion" 1 "linke_Seite_fehlerhaft" 2 "rechte_Seite_fehlerhaft" 3 "beide_Seiten_fehlerhaft"; +VAL_ 1472 EP1_Sta_EPB 0 "Bremse_geoeffnet" 1 "Bremse_geschlossen"; +VAL_ 1472 EP1_Sta_Schalter 0 "volle_Funktion" 1 "Schalter_ausser_Funktion"; +VAL_ 1472 EP1_Spannkraft 31 "Fehler"; +VAL_ 1472 EP1_Schalterinfo 0 "keine_Fahreranforderung" 1 "Fahreranforderung_oeffnen" 2 "Fahreranforderung_schliessen" 3 "Schalterfehler"; +VAL_ 1472 EP1_Sta_NWS 0 "volle_Funktion" 1 "keine_Funktion"; +VAL_ 1472 EP1_Fehlereintr 0 "kein_Fehlerspeichereintrag" 1 "Fehlerspeichereintrag"; +VAL_ 1472 EP1_Freigabe_Ver 0 "Verzoegerungsanf_nicht_freigegeb" 1 "Verzoegerungsanf_freigegeben"; +VAL_ 1472 EP1_AutoHold_zul 0 "Pers_nicht_zulaessig" 1 "Pers_zulaessig"; +VAL_ 1472 EP1_AutoHold_aktiv 0 "nein" 1 "ja"; +VAL_ 1472 EP1_SleepInd 0 "CAN_wird_benoetigt" 1 "Sleep_bereit"; +VAL_ 1472 EP1_Status_Kl_15 0 "Kl_15_aus" 1 "Kl_15_ein"; +VAL_ 1472 EP1_Lampe_AutoP 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 1472 EP1_Bremslicht 0 "Aus" 1 "Ein"; +VAL_ 1472 EP1_Warnton1 0 "Aus" 1 "Ein"; +VAL_ 1472 EP1_Warnton2 0 "Aus" 1 "Ein"; +VAL_ 1472 EP1_AnfShLock 0 "Aus" 1 "Ein"; +VAL_ 1472 EPB_Autoholdlampe 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 1472 EP1_QualNeigWi 0 "gueltiger_Wert" 1 "Ersatz_Init_oder_Fehlerwert"; +VAL_ 1472 EP1_KuppModBer 0 "Kuppsensor_aus_Modbereich" 1 "Kupplsensor_im_Modbereich" 2 "Sensorsignal_ungenau" 3 "Sensor_defekt"; +VAL_ 1472 EP1_HydrHalten 0 "Fzg_nicht_hydr_geh" 1 "Fzg_hydr_geh"; +VAL_ 1472 EP1_Fkt_Lampe 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 1472 EP1_Warnton 0 "Warnton_aus" 1 "Warnton_an"; +VAL_ 1472 EP1_Fehler_BKL 0 "BKL_aus" 1 "BKL_an"; +VAL_ 1472 EP1_Fehler_gelb 0 "Lampe_aus" 1 "Lampe_ein"; +VAL_ 1472 EP1__Text 0 "kein_Text" 1 "Text_1" 2 "Text_2" 3 "Text_3" 4 "Text_4" 5 "Text_5" 6 "reserviert" 7 "reserviert" 8 "Text_8"; diff --git a/opendbc_repo/opendbc/safety/__init__.py b/opendbc_repo/opendbc/safety/__init__.py new file mode 100644 index 0000000000..5d4c2464d4 --- /dev/null +++ b/opendbc_repo/opendbc/safety/__init__.py @@ -0,0 +1,10 @@ +# constants from can.h +DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64] +LEN_TO_DLC = {length: dlc for (dlc, length) in enumerate(DLC_TO_LEN)} + + +class ALTERNATIVE_EXPERIENCE: + DEFAULT = 0 + DISABLE_STOCK_AEB = 2 + RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX = 8 + ALLOW_AEB = 16 diff --git a/opendbc_repo/opendbc/safety/can.h b/opendbc_repo/opendbc/safety/can.h new file mode 100644 index 0000000000..205ee3a2ab --- /dev/null +++ b/opendbc_repo/opendbc/safety/can.h @@ -0,0 +1,22 @@ +#pragma once + +static const unsigned char dlc_to_len[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U}; + +#define CANPACKET_HEAD_SIZE 6U // non-data portion of CANPacket_t +#define CANPACKET_DATA_SIZE_MAX 64U + +// bump this when changing the CAN packet +#define CAN_PACKET_VERSION 4 +typedef struct { + unsigned char fd : 1; + unsigned char bus : 3; + unsigned char data_len_code : 4; // lookup length with dlc_to_len + unsigned char rejected : 1; + unsigned char returned : 1; + unsigned char extended : 1; + unsigned int addr : 29; + unsigned char checksum; + unsigned char data[CANPACKET_DATA_SIZE_MAX]; +} __attribute__((packed, aligned(4))) CANPacket_t; + +#define GET_LEN(msg) (dlc_to_len[(msg)->data_len_code]) diff --git a/opendbc_repo/opendbc/safety/declarations.h b/opendbc_repo/opendbc/safety/declarations.h new file mode 100644 index 0000000000..31918c0467 --- /dev/null +++ b/opendbc_repo/opendbc/safety/declarations.h @@ -0,0 +1,342 @@ +#pragma once + +#include +#include + +// from cereal.car.CarParams.SafetyModel +#define SAFETY_SILENT 0U +#define SAFETY_HONDA_NIDEC 1U +#define SAFETY_TOYOTA 2U +#define SAFETY_ELM327 3U +#define SAFETY_GM 4U +#define SAFETY_HONDA_BOSCH_GIRAFFE 5U +#define SAFETY_FORD 6U +#define SAFETY_HYUNDAI 8U +#define SAFETY_CHRYSLER 9U +#define SAFETY_TESLA 10U +#define SAFETY_SUBARU 11U +#define SAFETY_MAZDA 13U +#define SAFETY_NISSAN 14U +#define SAFETY_VOLKSWAGEN_MQB 15U +#define SAFETY_ALLOUTPUT 17U +#define SAFETY_GM_ASCM 18U +#define SAFETY_NOOUTPUT 19U +#define SAFETY_HONDA_BOSCH 20U +#define SAFETY_VOLKSWAGEN_PQ 21U +#define SAFETY_SUBARU_PREGLOBAL 22U +#define SAFETY_HYUNDAI_LEGACY 23U +#define SAFETY_HYUNDAI_COMMUNITY 24U +#define SAFETY_STELLANTIS 25U +#define SAFETY_FAW 26U +#define SAFETY_BODY 27U +#define SAFETY_HYUNDAI_CANFD 28U +#define SAFETY_PSA 31U +#define SAFETY_RIVIAN 33U +#define SAFETY_VOLKSWAGEN_MEB 34U + +#define GET_BIT(msg, b) ((bool)!!(((msg)->data[((b) / 8U)] >> ((b) % 8U)) & 0x1U)) +#define GET_FLAG(value, mask) (((__typeof__(mask))(value) & (mask)) == (mask)) // cppcheck-suppress misra-c2012-1.2; allow __typeof__ + +#define BUILD_SAFETY_CFG(rx, tx) ((safety_config){(rx), (sizeof((rx)) / sizeof((rx)[0])), \ + (tx), (sizeof((tx)) / sizeof((tx)[0])), \ + false}) +#define SET_RX_CHECKS(rx, config) \ + do { \ + (config).rx_checks = (rx); \ + (config).rx_checks_len = sizeof((rx)) / sizeof((rx)[0]); \ + (config).disable_forwarding = false; \ + } while (0); + +#define SET_TX_MSGS(tx, config) \ + do { \ + (config).tx_msgs = (tx); \ + (config).tx_msgs_len = sizeof((tx)) / sizeof((tx)[0]); \ + (config).disable_forwarding = false; \ + } while (0); + +#define UPDATE_VEHICLE_SPEED(val_ms) (update_sample(&vehicle_speed, ROUND((val_ms) * VEHICLE_SPEED_FACTOR))) + +uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len); + +extern const int MAX_WRONG_COUNTERS; +#define MAX_ADDR_CHECK_MSGS 3U +#define MAX_SAMPLE_VALS 6 +// used to represent floating point vehicle speed in a sample_t +#define VEHICLE_SPEED_FACTOR 1000.0 +#define MAX_RT_INTERVAL 250000U + +// Conversions +#define KPH_TO_MS (1.0 / 3.6) + +// sample struct that keeps 6 samples in memory +struct sample_t { + int values[MAX_SAMPLE_VALS]; + int min; + int max; +}; + +// safety code requires floats +struct lookup_t { + float x[3]; + float y[3]; +}; + +typedef struct { + int addr; + unsigned int bus; + int len; + bool check_relay; // if true, trigger relay malfunction if existence on destination bus and block forwarding to destination bus + bool disable_static_blocking; // if true, static blocking is disabled so safety mode can dynamically handle it (e.g. selective AEB pass-through) +} CanMsg; + +typedef enum { + TorqueMotorLimited, // torque steering command, limited by EPS output torque + TorqueDriverLimited, // torque steering command, limited by driver's input torque +} SteeringControlType; + +typedef struct { + // torque cmd limits + const int max_torque; // this upper limit is always enforced + const bool dynamic_max_torque; // use max_torque_lookup to apply torque limit based on speed + const struct lookup_t max_torque_lookup; + + const int max_rate_up; + const int max_rate_down; + const int max_rt_delta; // max change in torque per 250ms interval (MAX_RT_INTERVAL) + + const SteeringControlType type; + + // driver torque limits + const int driver_torque_allowance; + const int driver_torque_multiplier; + + // motor torque limits + const int max_torque_error; + + // safety around steer req bit + const int min_valid_request_frames; + const int max_invalid_request_frames; + const uint32_t min_valid_request_rt_interval; + const bool has_steer_req_tolerance; +} TorqueSteeringLimits; + +typedef struct { + // angle cmd limits (also used by curvature control cars) + const int max_angle; + + const float angle_deg_to_can; + const struct lookup_t angle_rate_up_lookup; + const struct lookup_t angle_rate_down_lookup; + const int max_angle_error; // used to limit error between meas and cmd while enabled + const float angle_error_min_speed; // minimum speed to start limiting angle error + const uint32_t frequency; // Hz + + const bool angle_is_curvature; // if true, we can apply max lateral acceleration limits + const bool enforce_angle_error; // enables max_angle_error check + const bool inactive_angle_is_zero; // if false, enforces angle near meas when disabled (default) +} AngleSteeringLimits; + +// parameters for lateral accel/jerk angle limiting using a simple vehicle model +typedef struct { + const float slip_factor; + const float steer_ratio; + const float wheelbase; +} AngleSteeringParams; + +typedef struct { + // acceleration cmd limits + const int max_accel; + const int min_accel; + const int inactive_accel; + + // gas & brake cmd limits + // inactive and min gas are 0 on most safety modes + const int max_gas; + const int min_gas; + const int inactive_gas; + const int max_brake; + + // transmission rpm limits + const int max_transmission_rpm; + const int min_transmission_rpm; + const int inactive_transmission_rpm; + + // speed cmd limits + const int inactive_speed; +} LongitudinalLimits; + +typedef struct { + const int addr; + const unsigned int bus; + const int len; + const uint32_t frequency; // expected frequency of the message [Hz] + const bool ignore_checksum; // checksum check is not performed when set to true + const bool ignore_counter; // counter check is not performed when set to true + const uint8_t max_counter; // maximum value of the counter. 0 means that the counter check is skipped + const bool ignore_quality_flag; // true if quality flag check is skipped +} CanMsgCheck; + +typedef struct { + // dynamic flags, reset on safety mode init + bool msg_seen; + int index; // if multiple messages are allowed to be checked, this stores the index of the first one seen. only msg[msg_index] will be used + bool valid_checksum; // true if and only if checksum check is passed + int wrong_counters; // counter of wrong counters, saturated between 0 and MAX_WRONG_COUNTERS + bool valid_quality_flag; // true if the message's quality/health/status signals are valid + uint8_t last_counter; // last counter value + uint32_t last_timestamp; // micro-s + bool lagging; // true if and only if the time between updates is excessive +} RxStatus; + +// params and flags about checksum, counter and frequency checks for each monitored address +typedef struct { + const CanMsgCheck msg[MAX_ADDR_CHECK_MSGS]; // check either messages (e.g. honda steer) + RxStatus status; +} RxCheck; + +typedef struct { + RxCheck *rx_checks; + int rx_checks_len; + const CanMsg *tx_msgs; + int tx_msgs_len; + bool disable_forwarding; +} safety_config; + +typedef uint32_t (*get_checksum_t)(const CANPacket_t *msg); +typedef uint32_t (*compute_checksum_t)(const CANPacket_t *msg); +typedef uint8_t (*get_counter_t)(const CANPacket_t *msg); +typedef bool (*get_quality_flag_valid_t)(const CANPacket_t *msg); + +typedef safety_config (*safety_hook_init)(uint16_t param); +typedef void (*rx_hook)(const CANPacket_t *msg); +typedef bool (*tx_hook)(const CANPacket_t *msg); // returns true if the message is allowed +typedef bool (*fwd_hook)(int bus_num, int addr); // returns true if the message should be blocked from forwarding + +typedef struct { + safety_hook_init init; + rx_hook rx; + tx_hook tx; + fwd_hook fwd; + get_checksum_t get_checksum; + compute_checksum_t compute_checksum; + get_counter_t get_counter; + get_quality_flag_valid_t get_quality_flag_valid; +} safety_hooks; + +bool safety_rx_hook(const CANPacket_t *msg); +bool safety_tx_hook(CANPacket_t *msg); +int to_signed(int d, int bits); +void update_sample(struct sample_t *sample, int sample_new); +bool get_longitudinal_allowed(void); +int ROUND(float val); +void gen_crc_lookup_table_8(uint8_t poly, uint8_t crc_lut[]); +void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]); +bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueSteeringLimits limits); +bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits); +bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits, + const AngleSteeringParams params); +bool longitudinal_accel_checks(int desired_accel, const LongitudinalLimits limits); +bool longitudinal_speed_checks(int desired_speed, const LongitudinalLimits limits); +bool longitudinal_gas_checks(int desired_gas, const LongitudinalLimits limits); +bool longitudinal_transmission_rpm_checks(int desired_transmission_rpm, const LongitudinalLimits limits); +bool longitudinal_brake_checks(int desired_brake, const LongitudinalLimits limits); +void pcm_cruise_check(bool cruise_engaged); +void speed_mismatch_check(const float speed_2); + +void safety_tick(const safety_config *safety_config); + +// This can be set by the safety hooks +extern bool controls_allowed; +extern bool relay_malfunction; +extern bool gas_pressed; +extern bool gas_pressed_prev; +extern bool brake_pressed; +extern bool brake_pressed_prev; +extern bool regen_braking; +extern bool regen_braking_prev; +extern bool steering_disengage; +extern bool steering_disengage_prev; +extern bool cruise_engaged_prev; +extern struct sample_t vehicle_speed; +extern bool vehicle_moving; +extern bool acc_main_on; // referred to as "ACC off" in ISO 15622:2018 +extern int cruise_button_prev; +extern bool safety_rx_checks_invalid; + +// for safety modes with torque steering control +extern int desired_torque_last; // last desired steer torque +extern int rt_torque_last; // last desired torque for real time check +extern int valid_steer_req_count; // counter for steer request bit matching non-zero torque +extern int invalid_steer_req_count; // counter to allow multiple frames of mismatching torque request bit +extern struct sample_t torque_meas; // last 6 motor torques produced by the eps +extern struct sample_t torque_driver; // last 6 driver torques measured +extern uint32_t ts_torque_check_last; +extern uint32_t ts_steer_req_mismatch_last; // last timestamp steer req was mismatched with torque + +// state for controls_allowed timeout logic +extern bool heartbeat_engaged; // openpilot enabled, passed in heartbeat USB command +extern uint32_t heartbeat_engaged_mismatches; // count of mismatches between heartbeat_engaged and controls_allowed + +// for safety modes with angle steering control +extern uint32_t rt_angle_msgs; +extern uint32_t ts_angle_check_last; +extern int desired_angle_last; +extern struct sample_t angle_meas; // last 6 steer angles/curvatures + +// Alt experiences can be set with a USB command +// It enables features that allow alternative experiences, like not disengaging on gas press +// It is only either 0 or 1 on mainline comma.ai openpilot + +//#define ALT_EXP_DISABLE_DISENGAGE_ON_GAS 1 // not used anymore, but reserved + +// If using this flag, make sure to communicate to your users that a stock safety feature is now disabled. +#define ALT_EXP_DISABLE_STOCK_AEB 2 + +// If using this flag, be aware that harder braking is more likely to lead to rear endings, +// and that alone this flag doesn't make braking compliant because there's also a time element. +// Setting this flag is used for allowing the full -5.0 to +4.0 m/s^2 at lower speeds +// See ISO 15622:2018 for more information. +#define ALT_EXP_RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX 8 + +// This flag allows AEB to be commanded from openpilot. +#define ALT_EXP_ALLOW_AEB 16 + +extern int alternative_experience; + +// time since safety mode has been changed +extern uint32_t safety_mode_cnt; + +typedef struct { + uint16_t id; + const safety_hooks *hooks; +} safety_hook_config; + +extern uint16_t current_safety_mode; +extern uint16_t current_safety_param; +extern safety_config current_safety_config; + +int safety_fwd_hook(int bus_num, int addr); +int set_safety_hooks(uint16_t mode, uint16_t param); + +extern const safety_hooks body_hooks; +extern const safety_hooks chrysler_hooks; +extern const safety_hooks elm327_hooks; +extern const safety_hooks nooutput_hooks; +extern const safety_hooks alloutput_hooks; +extern const safety_hooks ford_hooks; +extern const safety_hooks gm_hooks; +extern const safety_hooks honda_nidec_hooks; +extern const safety_hooks honda_bosch_hooks; +extern const safety_hooks hyundai_canfd_hooks; +extern const safety_hooks hyundai_hooks; +extern const safety_hooks hyundai_legacy_hooks; +extern const safety_hooks mazda_hooks; +extern const safety_hooks nissan_hooks; +extern const safety_hooks subaru_hooks; +extern const safety_hooks subaru_preglobal_hooks; +extern const safety_hooks tesla_hooks; +extern const safety_hooks toyota_hooks; +extern const safety_hooks volkswagen_mqb_hooks; +extern const safety_hooks volkswagen_pq_hooks; +extern const safety_hooks rivian_hooks; +extern const safety_hooks psa_hooks; diff --git a/opendbc_repo/opendbc/safety/helpers.h b/opendbc_repo/opendbc/safety/helpers.h new file mode 100644 index 0000000000..9701028cdc --- /dev/null +++ b/opendbc_repo/opendbc/safety/helpers.h @@ -0,0 +1,68 @@ +#include "opendbc/safety/declarations.h" + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define SAFETY_MIN(a, b) ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + (_a < _b) ? _a : _b; \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define SAFETY_MAX(a, b) ({ \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + (_a > _b) ? _a : _b; \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define SAFETY_CLAMP(x, low, high) ({ \ + __typeof__(x) __x = (x); \ + __typeof__(low) __low = (low);\ + __typeof__(high) __high = (high);\ + (__x > __high) ? __high : ((__x < __low) ? __low : __x); \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define SAFETY_ABS(a) ({ \ + __typeof__(a) _a = (a); \ + (_a > 0) ? _a : (-_a); \ +}) + +#define SAFETY_UNUSED(x) ((void)(x)) + +// compute the time elapsed (in microseconds) from 2 counter samples +// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t +static inline uint32_t safety_get_ts_elapsed(uint32_t ts, uint32_t ts_last) { + return ts - ts_last; +} + +static bool safety_max_limit_check(int val, const int MAX_VAL, const int MIN_VAL) { + return (val > MAX_VAL) || (val < MIN_VAL); +} + +// interp function that holds extreme values +static float safety_interpolate(struct lookup_t xy, float x) { + int size = sizeof(xy.x) / sizeof(xy.x[0]); + float ret = xy.y[size - 1]; // default output is last point + + // x is lower than the first point in the x array. Return the first point + if (x <= xy.x[0]) { + ret = xy.y[0]; + + } else { + // find the index such that (xy.x[i] <= x < xy.x[i+1]) and linearly interp + for (int i=0; i < (size - 1); i++) { + if (x < xy.x[i+1]) { + float x0 = xy.x[i]; + float y0 = xy.y[i]; + float dx = xy.x[i+1] - x0; + float dy = xy.y[i+1] - y0; + // dx should not be zero as xy.x is supposed to be monotonic + dx = SAFETY_MAX(dx, 0.0001); + ret = (dy * (x - x0) / dx) + y0; + break; + } + } + } + return ret; +} diff --git a/opendbc_repo/opendbc/safety/lateral.h b/opendbc_repo/opendbc/safety/lateral.h new file mode 100644 index 0000000000..cfe15af36a --- /dev/null +++ b/opendbc_repo/opendbc/safety/lateral.h @@ -0,0 +1,353 @@ +#include "opendbc/safety/declarations.h" + +// ISO 11270 +static const float ISO_LATERAL_ACCEL = 3.0; // m/s^2 + +static const float EARTH_G = 9.81; +static const float AVERAGE_ROAD_ROLL = 0.06; // ~3.4 degrees, 6% superelevation + +// check that commanded torque value isn't too far from measured +static bool dist_to_meas_check(int val, int val_last, struct sample_t *val_meas, + const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR) { + + // *** val rate limit check *** + int highest_allowed_rl = SAFETY_MAX(val_last, 0) + MAX_RATE_UP; + int lowest_allowed_rl = SAFETY_MIN(val_last, 0) - MAX_RATE_UP; + + // if we've exceeded the meas val, we must start moving toward 0 + int highest_allowed = SAFETY_MIN(highest_allowed_rl, SAFETY_MAX(val_last - MAX_RATE_DOWN, SAFETY_MAX(val_meas->max, 0) + MAX_ERROR)); + int lowest_allowed = SAFETY_MAX(lowest_allowed_rl, SAFETY_MIN(val_last + MAX_RATE_DOWN, SAFETY_MIN(val_meas->min, 0) - MAX_ERROR)); + + // check for violation + return safety_max_limit_check(val, highest_allowed, lowest_allowed); +} + +// check that commanded value isn't fighting against driver +static bool driver_limit_check(int val, int val_last, const struct sample_t *val_driver, + const int MAX_VAL, const int MAX_RATE_UP, const int MAX_RATE_DOWN, + const int MAX_ALLOWANCE, const int DRIVER_FACTOR) { + + // torque delta/rate limits + int highest_allowed_rl = SAFETY_MAX(val_last, 0) + MAX_RATE_UP; + int lowest_allowed_rl = SAFETY_MIN(val_last, 0) - MAX_RATE_UP; + + // driver + int driver_max_limit = MAX_VAL + (MAX_ALLOWANCE + val_driver->max) * DRIVER_FACTOR; + int driver_min_limit = -MAX_VAL + (-MAX_ALLOWANCE + val_driver->min) * DRIVER_FACTOR; + + // if we've exceeded the applied torque, we must start moving toward 0 + int highest_allowed = SAFETY_MIN(highest_allowed_rl, SAFETY_MAX(val_last - MAX_RATE_DOWN, + SAFETY_MAX(driver_max_limit, 0))); + int lowest_allowed = SAFETY_MAX(lowest_allowed_rl, SAFETY_MIN(val_last + MAX_RATE_DOWN, + SAFETY_MIN(driver_min_limit, 0))); + + // check for violation + return safety_max_limit_check(val, highest_allowed, lowest_allowed); +} + +// real time check, mainly used for steer torque rate limiter +static bool rt_torque_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) { + + // *** torque real time rate limit check *** + int highest_val = SAFETY_MAX(val_last, 0) + MAX_RT_DELTA; + int lowest_val = SAFETY_MIN(val_last, 0) - MAX_RT_DELTA; + + // check for violation + return safety_max_limit_check(val, highest_val, lowest_val); +} + +// Safety checks for torque-based steering commands +bool steer_torque_cmd_checks(int desired_torque, int steer_req, const TorqueSteeringLimits limits) { + bool violation = false; + uint32_t ts = microsecond_timer_get(); + + if (controls_allowed) { + // Some safety models support variable torque limit based on vehicle speed + int max_torque = limits.max_torque; + if (limits.dynamic_max_torque) { + const float fudged_speed = (vehicle_speed.min / VEHICLE_SPEED_FACTOR) - 1.; + max_torque = safety_interpolate(limits.max_torque_lookup, fudged_speed) + 1; + max_torque = SAFETY_CLAMP(max_torque, -limits.max_torque, limits.max_torque); + } + + // *** global torque limit check *** + violation |= safety_max_limit_check(desired_torque, max_torque, -max_torque); + + // *** torque rate limit check *** + if (limits.type == TorqueDriverLimited) { + violation |= driver_limit_check(desired_torque, desired_torque_last, &torque_driver, + max_torque, limits.max_rate_up, limits.max_rate_down, + limits.driver_torque_allowance, limits.driver_torque_multiplier); + } else { + violation |= dist_to_meas_check(desired_torque, desired_torque_last, &torque_meas, + limits.max_rate_up, limits.max_rate_down, limits.max_torque_error); + } + desired_torque_last = desired_torque; + + // *** torque real time rate limit check *** + violation |= rt_torque_rate_limit_check(desired_torque, rt_torque_last, limits.max_rt_delta); + + // every RT_INTERVAL set the new limits + uint32_t ts_elapsed = safety_get_ts_elapsed(ts, ts_torque_check_last); + if (ts_elapsed > MAX_RT_INTERVAL) { + rt_torque_last = desired_torque; + ts_torque_check_last = ts; + } + } + + // no torque if controls is not allowed + if (!controls_allowed && (desired_torque != 0)) { + violation = true; + } + + // certain safety modes set their steer request bit low for one or more frame at a + // predefined max frequency to avoid steering faults in certain situations + bool steer_req_mismatch = (steer_req == 0) && (desired_torque != 0); + if (!limits.has_steer_req_tolerance) { + if (steer_req_mismatch) { + violation = true; + } + + } else { + if (steer_req_mismatch) { + if (invalid_steer_req_count == 0) { + // disallow torque cut if not enough recent matching steer_req messages + if (valid_steer_req_count < limits.min_valid_request_frames) { + violation = true; + } + + // or we've cut torque too recently in time + uint32_t ts_elapsed = safety_get_ts_elapsed(ts, ts_steer_req_mismatch_last); + if (ts_elapsed < limits.min_valid_request_rt_interval) { + violation = true; + } + } else { + // or we're cutting more frames consecutively than allowed + if (invalid_steer_req_count >= limits.max_invalid_request_frames) { + violation = true; + } + } + + valid_steer_req_count = 0; + ts_steer_req_mismatch_last = ts; + invalid_steer_req_count = SAFETY_MIN(invalid_steer_req_count + 1, limits.max_invalid_request_frames); + } else { + valid_steer_req_count = SAFETY_MIN(valid_steer_req_count + 1, limits.min_valid_request_frames); + invalid_steer_req_count = 0; + } + } + + // reset to 0 if either controls is not allowed or there's a violation + if (violation || !controls_allowed) { + valid_steer_req_count = 0; + invalid_steer_req_count = 0; + desired_torque_last = 0; + rt_torque_last = 0; + ts_torque_check_last = ts; + ts_steer_req_mismatch_last = ts; + } + + return violation; +} + +static bool rt_angle_rate_limit_check(AngleSteeringLimits limits) { + bool violation = false; + uint32_t ts = microsecond_timer_get(); + + // *** angle real time rate limit check *** + int max_rt_msgs = ((float)limits.frequency * MAX_RT_INTERVAL / 1e6 * 1.2) + 1; // 1.2x buffer + if ((int)rt_angle_msgs > max_rt_msgs) { + violation = true; + } + + rt_angle_msgs += 1U; + + // every RT_INTERVAL reset message counter + uint32_t ts_elapsed = safety_get_ts_elapsed(ts, ts_angle_check_last); + if (ts_elapsed >= MAX_RT_INTERVAL) { + rt_angle_msgs = 0; + ts_angle_check_last = ts; + } + + return violation; +} + +// Safety checks for angle-based steering commands +bool steer_angle_cmd_checks(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits) { + bool violation = false; + + if (controls_allowed && steer_control_enabled) { + // convert floating point angle rate limits to integers in the scale of the desired angle on CAN, + // add 1 to not false trigger the violation. also fudge the speed by 1 m/s so rate limits are + // always slightly above openpilot's in case we read an updated speed in between angle commands + // TODO: this speed fudge can be much lower, look at data to determine the lowest reasonable offset + const float fudged_speed = (vehicle_speed.min / VEHICLE_SPEED_FACTOR) - 1.; + int delta_angle_up = (safety_interpolate(limits.angle_rate_up_lookup, fudged_speed) * limits.angle_deg_to_can) + 1.; + int delta_angle_down = (safety_interpolate(limits.angle_rate_down_lookup, fudged_speed) * limits.angle_deg_to_can) + 1.; + + // allow down limits at zero since small floats from openpilot will be rounded to 0 + // TODO: openpilot should be cognizant of this and not send small floats + int highest_desired_angle = desired_angle_last + ((desired_angle_last > 0) ? delta_angle_up : delta_angle_down); + int lowest_desired_angle = desired_angle_last - ((desired_angle_last >= 0) ? delta_angle_down : delta_angle_up); + + // check that commanded angle value isn't too far from measured, used to limit torque for some safety modes + // ensure we start moving in direction of meas while respecting relaxed rate limits if error is exceeded + if (limits.enforce_angle_error && ((vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR) > limits.angle_error_min_speed)) { + // flipped fudge to avoid false positives + const float fudged_speed_error = (vehicle_speed.max / VEHICLE_SPEED_FACTOR) + 1.; + const int delta_angle_up_relaxed = (safety_interpolate(limits.angle_rate_up_lookup, fudged_speed_error) * limits.angle_deg_to_can) - 1.; + const int delta_angle_down_relaxed = (safety_interpolate(limits.angle_rate_down_lookup, fudged_speed_error) * limits.angle_deg_to_can) - 1.; + + // the minimum and maximum angle allowed based on the measured angle + const int lowest_desired_angle_error = angle_meas.min - limits.max_angle_error - 1; + const int highest_desired_angle_error = angle_meas.max + limits.max_angle_error + 1; + + // the MAX is to allow the desired angle to hit the edge of the bounds and not require going under it + if (desired_angle_last > highest_desired_angle_error) { + const int delta = (desired_angle_last >= 0) ? delta_angle_down_relaxed : delta_angle_up_relaxed; + highest_desired_angle = SAFETY_MAX(desired_angle_last - delta, highest_desired_angle_error); + + } else if (desired_angle_last < lowest_desired_angle_error) { + const int delta = (desired_angle_last <= 0) ? delta_angle_down_relaxed : delta_angle_up_relaxed; + lowest_desired_angle = SAFETY_MIN(desired_angle_last + delta, lowest_desired_angle_error); + + } else { + // already inside error boundary, don't allow commanding outside it + highest_desired_angle = SAFETY_MIN(highest_desired_angle, highest_desired_angle_error); + lowest_desired_angle = SAFETY_MAX(lowest_desired_angle, lowest_desired_angle_error); + } + + // don't enforce above the max steer + // TODO: this should always be done + lowest_desired_angle = SAFETY_CLAMP(lowest_desired_angle, -limits.max_angle, limits.max_angle); + highest_desired_angle = SAFETY_CLAMP(highest_desired_angle, -limits.max_angle, limits.max_angle); + } + + // check not above ISO 11270 lateral accel assuming worst case road roll + if (limits.angle_is_curvature) { + + // Limit to average banked road since safety doesn't have the roll + static const float MAX_LATERAL_ACCEL = ISO_LATERAL_ACCEL - (EARTH_G * AVERAGE_ROAD_ROLL); // ~2.4 m/s^2 + + // Allow small tolerance by using minimum speed and rounding curvature up + const float speed_lower = SAFETY_MAX(vehicle_speed.min / VEHICLE_SPEED_FACTOR, 1.0); + const float speed_upper = SAFETY_MAX(vehicle_speed.max / VEHICLE_SPEED_FACTOR, 1.0); + const int max_curvature_upper = (MAX_LATERAL_ACCEL / (speed_lower * speed_lower) * limits.angle_deg_to_can) + 1.; + const int max_curvature_lower = (MAX_LATERAL_ACCEL / (speed_upper * speed_upper) * limits.angle_deg_to_can) - 1.; + + // ensure that the curvature error doesn't try to enforce above this limit + if (desired_angle_last > 0) { + lowest_desired_angle = SAFETY_CLAMP(lowest_desired_angle, -max_curvature_lower, max_curvature_lower); + highest_desired_angle = SAFETY_CLAMP(highest_desired_angle, -max_curvature_upper, max_curvature_upper); + } else { + lowest_desired_angle = SAFETY_CLAMP(lowest_desired_angle, -max_curvature_upper, max_curvature_upper); + highest_desired_angle = SAFETY_CLAMP(highest_desired_angle, -max_curvature_lower, max_curvature_lower); + } + } + + // check for violation; + violation |= safety_max_limit_check(desired_angle, highest_desired_angle, lowest_desired_angle); + } + desired_angle_last = desired_angle; + + // Angle should either be 0 or same as current angle while not steering + if (!steer_control_enabled) { + if (limits.inactive_angle_is_zero) { + violation |= desired_angle != 0; + } else { + const int max_inactive_angle = SAFETY_CLAMP(angle_meas.max, -limits.max_angle, limits.max_angle) + 1; + const int min_inactive_angle = SAFETY_CLAMP(angle_meas.min, -limits.max_angle, limits.max_angle) - 1; + violation |= safety_max_limit_check(desired_angle, max_inactive_angle, min_inactive_angle); + } + } + + // No angle control allowed when controls are not allowed + if (!controls_allowed) { + violation |= steer_control_enabled; + } + + // reset to current angle if either controls is not allowed or there's a violation + if (violation || !controls_allowed) { + if (limits.inactive_angle_is_zero) { + desired_angle_last = 0; + } else { + desired_angle_last = SAFETY_CLAMP(angle_meas.values[0], -limits.max_angle, limits.max_angle); + } + } + + return violation; +} + +static float get_curvature_factor(const float speed, const AngleSteeringParams params) { + // Matches VehicleModel.curvature_factor() + return 1. / (1. - (params.slip_factor * (speed * speed))) / params.wheelbase; +} + +static float get_angle_from_curvature(const float curvature, const float curvature_factor, const AngleSteeringParams params) { + // Matches VehicleModel.get_steer_from_curvature() + static const float RAD_TO_DEG = 57.29577951308232; + return curvature * params.steer_ratio / curvature_factor * RAD_TO_DEG; +} + +bool steer_angle_cmd_checks_vm(int desired_angle, bool steer_control_enabled, const AngleSteeringLimits limits, + const AngleSteeringParams params) { + // This check uses a simple vehicle model to allow for constant lateral acceleration and jerk limits across all speeds. + // TODO: remove the inaccurate breakpoint angle limiting function above and always use this one + + // Highway curves are rolled in the direction of the turn, add tolerance to compensate + static const float MAX_LATERAL_ACCEL = ISO_LATERAL_ACCEL + (EARTH_G * AVERAGE_ROAD_ROLL); // ~3.6 m/s^2 + // Lower than ISO 11270 lateral jerk limit, which is 5.0 m/s^3 + static const float MAX_LATERAL_JERK = 3.0 + (EARTH_G * AVERAGE_ROAD_ROLL); // ~3.6 m/s^3 + + const float fudged_speed = SAFETY_MAX((vehicle_speed.min / VEHICLE_SPEED_FACTOR) - 1.0, 1.0); + const float curvature_factor = get_curvature_factor(fudged_speed, params); + + bool violation = false; + + if (controls_allowed && steer_control_enabled) { + // *** ISO lateral jerk limit *** + // calculate maximum angle rate per second + const float max_curvature_rate_sec = MAX_LATERAL_JERK / (fudged_speed * fudged_speed); + const float max_angle_rate_sec = get_angle_from_curvature(max_curvature_rate_sec, curvature_factor, params); + + // finally get max angle delta per frame + const float max_angle_delta = max_angle_rate_sec / (float)limits.frequency; + const int max_angle_delta_can = (max_angle_delta * limits.angle_deg_to_can) + 1.; + + // NOTE: symmetric up and down limits + const int highest_desired_angle = desired_angle_last + max_angle_delta_can; + const int lowest_desired_angle = desired_angle_last - max_angle_delta_can; + + violation |= safety_max_limit_check(desired_angle, highest_desired_angle, lowest_desired_angle); + + // *** ISO lateral accel limit *** + const float max_curvature = MAX_LATERAL_ACCEL / (fudged_speed * fudged_speed); + const float max_angle = get_angle_from_curvature(max_curvature, curvature_factor, params); + const int max_angle_can = (max_angle * limits.angle_deg_to_can) + 1.; + + violation |= safety_max_limit_check(desired_angle, max_angle_can, -max_angle_can); + + // *** angle real time rate limit check *** + violation |= rt_angle_rate_limit_check(limits); + } + desired_angle_last = desired_angle; + + // Angle should either be 0 or same as current angle while not steering + if (!steer_control_enabled) { + const int max_inactive_angle = SAFETY_CLAMP(angle_meas.max, -limits.max_angle, limits.max_angle) + 1; + const int min_inactive_angle = SAFETY_CLAMP(angle_meas.min, -limits.max_angle, limits.max_angle) - 1; + violation |= safety_max_limit_check(desired_angle, max_inactive_angle, min_inactive_angle); + } + + // No angle control allowed when controls are not allowed + if (!controls_allowed) { + violation |= steer_control_enabled; + } + + // reset to current angle if either controls is not allowed or there's a violation + if (violation || !controls_allowed) { + desired_angle_last = SAFETY_CLAMP(angle_meas.values[0], -limits.max_angle, limits.max_angle); + } + + return violation; +} diff --git a/opendbc_repo/opendbc/safety/longitudinal.h b/opendbc_repo/opendbc/safety/longitudinal.h new file mode 100644 index 0000000000..2810996092 --- /dev/null +++ b/opendbc_repo/opendbc/safety/longitudinal.h @@ -0,0 +1,35 @@ +#include "opendbc/safety/declarations.h" + +bool get_longitudinal_allowed(void) { + return controls_allowed && !gas_pressed_prev; +} + +// Safety checks for longitudinal actuation +bool longitudinal_accel_checks(int desired_accel, const LongitudinalLimits limits) { + bool accel_valid = get_longitudinal_allowed() && !safety_max_limit_check(desired_accel, limits.max_accel, limits.min_accel); + bool accel_inactive = desired_accel == limits.inactive_accel; + return !(accel_valid || accel_inactive); +} + +bool longitudinal_speed_checks(int desired_speed, const LongitudinalLimits limits) { + return !get_longitudinal_allowed() && (desired_speed != limits.inactive_speed); +} + +bool longitudinal_transmission_rpm_checks(int desired_transmission_rpm, const LongitudinalLimits limits) { + bool transmission_rpm_valid = get_longitudinal_allowed() && !safety_max_limit_check(desired_transmission_rpm, limits.max_transmission_rpm, limits.min_transmission_rpm); + bool transmission_rpm_inactive = desired_transmission_rpm == limits.inactive_transmission_rpm; + return !(transmission_rpm_valid || transmission_rpm_inactive); +} + +bool longitudinal_gas_checks(int desired_gas, const LongitudinalLimits limits) { + bool gas_valid = get_longitudinal_allowed() && !safety_max_limit_check(desired_gas, limits.max_gas, limits.min_gas); + bool gas_inactive = desired_gas == limits.inactive_gas; + return !(gas_valid || gas_inactive); +} + +bool longitudinal_brake_checks(int desired_brake, const LongitudinalLimits limits) { + bool violation = false; + violation |= !get_longitudinal_allowed() && (desired_brake != 0); + violation |= desired_brake > limits.max_brake; + return violation; +} diff --git a/opendbc_repo/opendbc/safety/modes/body.h b/opendbc_repo/opendbc/safety/modes/body.h new file mode 100644 index 0000000000..e3d5c212ca --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/body.h @@ -0,0 +1,45 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +static void body_rx_hook(const CANPacket_t *msg) { + if (msg->addr == 0x201U) { + controls_allowed = true; + } +} + +static bool body_tx_hook(const CANPacket_t *msg) { + bool tx = true; + + if (!controls_allowed && (msg->addr != 0x1U)) { + tx = false; + } + + // Allow going into CAN flashing mode even if controls are not allowed + bool flash_msg = (msg->addr == 0x250U) && (GET_LEN(msg) == 8U); + if (!controls_allowed && (GET_BYTES(msg, 0, 4) == 0xdeadfaceU) && (GET_BYTES(msg, 4, 4) == 0x0ab00b1eU) && flash_msg) { + tx = true; + } + + return tx; +} + +static safety_config body_init(uint16_t param) { + static RxCheck body_rx_checks[] = { + {.msg = {{0x201, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + static const CanMsg BODY_TX_MSGS[] = {{0x250, 0, 8, .check_relay = false}, {0x250, 0, 6, .check_relay = false}, {0x251, 0, 5, .check_relay = false}, // body + {0x1, 0, 8, .check_relay = false}}; // CAN flasher + + SAFETY_UNUSED(param); + safety_config ret = BUILD_SAFETY_CFG(body_rx_checks, BODY_TX_MSGS); + ret.disable_forwarding = true; + return ret; +} + +const safety_hooks body_hooks = { + .init = body_init, + .rx = body_rx_hook, + .tx = body_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/chrysler.h b/opendbc_repo/opendbc/safety/modes/chrysler.h new file mode 100644 index 0000000000..e8e2ac0ebb --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/chrysler.h @@ -0,0 +1,277 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +typedef struct { + const unsigned int EPS_2; + const unsigned int ESP_1; + const unsigned int ESP_8; + const unsigned int ECM_5; + const unsigned int DAS_3; + const unsigned int DAS_6; + const unsigned int LKAS_COMMAND; + const unsigned int CRUISE_BUTTONS; +} ChryslerAddrs; + +typedef enum { + CHRYSLER_RAM_DT, + CHRYSLER_RAM_HD, + CHRYSLER_PACIFICA, // plus Jeep +} ChryslerPlatform; +static ChryslerPlatform chrysler_platform; +static const ChryslerAddrs *chrysler_addrs; + +static uint32_t chrysler_get_checksum(const CANPacket_t *msg) { + int checksum_byte = GET_LEN(msg) - 1U; + return (uint8_t)(msg->data[checksum_byte]); +} + +static uint32_t chrysler_compute_checksum(const CANPacket_t *msg) { + // TODO: clean this up + // http://illmatics.com/Remote%20Car%20Hacking.pdf + uint8_t checksum = 0xFFU; + int len = GET_LEN(msg); + for (int j = 0; j < (len - 1); j++) { + uint8_t shift = 0x80U; + uint8_t curr = (uint8_t)msg->data[j]; + for (int i=0; i<8; i++) { + uint8_t bit_sum = curr & shift; + uint8_t temp_chk = checksum & 0x80U; + if (bit_sum != 0U) { + bit_sum = 0x1C; + if (temp_chk != 0U) { + bit_sum = 1; + } + checksum = checksum << 1; + temp_chk = checksum | 1U; + bit_sum ^= temp_chk; + } else { + if (temp_chk != 0U) { + bit_sum = 0x1D; + } + checksum = checksum << 1; + bit_sum ^= checksum; + } + checksum = bit_sum; + shift = shift >> 1; + } + } + return (uint8_t)(~checksum); +} + +static uint8_t chrysler_get_counter(const CANPacket_t *msg) { + return (uint8_t)(msg->data[6] >> 4); +} + +static void chrysler_rx_hook(const CANPacket_t *msg) { + // Measured EPS torque + if ((msg->bus == 0U) && (msg->addr == chrysler_addrs->EPS_2)) { + int torque_meas_new = ((msg->data[4] & 0x7U) << 8) + msg->data[5] - 1024U; + update_sample(&torque_meas, torque_meas_new); + } + + // enter controls on rising edge of ACC, exit controls on ACC off + const unsigned int das_3_bus = (chrysler_platform == CHRYSLER_PACIFICA) ? 0U : 2U; + if ((msg->bus == das_3_bus) && (msg->addr == chrysler_addrs->DAS_3)) { + bool cruise_engaged = GET_BIT(msg, 21U); + pcm_cruise_check(cruise_engaged); + } + + // TODO: use the same message for both + // update vehicle moving + if ((chrysler_platform != CHRYSLER_PACIFICA) && (msg->bus == 0U) && (msg->addr == chrysler_addrs->ESP_8)) { + vehicle_moving = ((msg->data[4] << 8) + msg->data[5]) != 0U; + } + if ((chrysler_platform == CHRYSLER_PACIFICA) && (msg->bus == 0U) && (msg->addr == 514U)) { + int speed_l = (msg->data[0] << 4) + (msg->data[1] >> 4); + int speed_r = (msg->data[2] << 4) + (msg->data[3] >> 4); + vehicle_moving = (speed_l != 0) || (speed_r != 0); + } + + // exit controls on rising edge of gas press + if ((msg->bus == 0U) && (msg->addr == chrysler_addrs->ECM_5)) { + gas_pressed = msg->data[0U] != 0U; + } + + // exit controls on rising edge of brake press + if ((msg->bus == 0U) && (msg->addr == chrysler_addrs->ESP_1)) { + brake_pressed = ((msg->data[0U] & 0xFU) >> 2U) == 1U; + } +} + +static bool chrysler_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits CHRYSLER_STEERING_LIMITS = { + .max_torque = 261, + .max_rt_delta = 112, + .max_rate_up = 3, + .max_rate_down = 3, + .max_torque_error = 80, + .type = TorqueMotorLimited, + }; + + const TorqueSteeringLimits CHRYSLER_RAM_DT_STEERING_LIMITS = { + .max_torque = 350, + .max_rt_delta = 112, + .max_rate_up = 6, + .max_rate_down = 6, + .max_torque_error = 80, + .type = TorqueMotorLimited, + }; + + const TorqueSteeringLimits CHRYSLER_RAM_HD_STEERING_LIMITS = { + .max_torque = 361, + .max_rt_delta = 182, + .max_rate_up = 14, + .max_rate_down = 14, + .max_torque_error = 80, + .type = TorqueMotorLimited, + }; + + bool tx = true; + + // STEERING + if (msg->addr == chrysler_addrs->LKAS_COMMAND) { + int start_byte = (chrysler_platform == CHRYSLER_PACIFICA) ? 0 : 1; + int desired_torque = ((msg->data[start_byte] & 0x7U) << 8) | msg->data[start_byte + 1]; + desired_torque -= 1024; + + const TorqueSteeringLimits limits = (chrysler_platform == CHRYSLER_PACIFICA) ? CHRYSLER_STEERING_LIMITS : + (chrysler_platform == CHRYSLER_RAM_DT) ? CHRYSLER_RAM_DT_STEERING_LIMITS : CHRYSLER_RAM_HD_STEERING_LIMITS; + + bool steer_req = (chrysler_platform == CHRYSLER_PACIFICA) ? GET_BIT(msg, 4U) : (msg->data[3] & 0x7U) == 2U; + if (steer_torque_cmd_checks(desired_torque, steer_req, limits)) { + tx = false; + } + } + + // FORCE CANCEL: only the cancel button press is allowed + if (msg->addr == chrysler_addrs->CRUISE_BUTTONS) { + const bool is_cancel = msg->data[0] == 1U; + const bool is_resume = msg->data[0] == 0x10U; + const bool allowed = is_cancel || (is_resume && controls_allowed); + if (!allowed) { + tx = false; + } + } + + return tx; +} + +static safety_config chrysler_init(uint16_t param) { + + const uint32_t CHRYSLER_PARAM_RAM_DT = 1U; // set for Ram DT platform + + // CAN messages for Chrysler/Jeep platforms + static const ChryslerAddrs CHRYSLER_ADDRS = { + .EPS_2 = 0x220, // EPS driver input torque + .ESP_1 = 0x140, // Brake pedal and vehicle speed + .ESP_8 = 0x11C, // Brake pedal and vehicle speed + .ECM_5 = 0x22F, // Throttle position sensor + .DAS_3 = 0x1F4, // ACC engagement states from DASM + .DAS_6 = 0x2A6, // LKAS HUD and auto headlight control from DASM + .LKAS_COMMAND = 0x292, // LKAS controls from DASM + .CRUISE_BUTTONS = 0x23B, // Cruise control buttons + }; + + // CAN messages for the 5th gen RAM DT platform + static const ChryslerAddrs CHRYSLER_RAM_DT_ADDRS = { + .EPS_2 = 0x31, // EPS driver input torque + .ESP_1 = 0x83, // Brake pedal and vehicle speed + .ESP_8 = 0x79, // Brake pedal and vehicle speed + .ECM_5 = 0x9D, // Throttle position sensor + .DAS_3 = 0x99, // ACC engagement states from DASM + .DAS_6 = 0xFA, // LKAS HUD and auto headlight control from DASM + .LKAS_COMMAND = 0xA6, // LKAS controls from DASM + .CRUISE_BUTTONS = 0xB1, // Cruise control buttons + }; + + static RxCheck chrysler_ram_dt_rx_checks[] = { + {.msg = {{CHRYSLER_RAM_DT_ADDRS.EPS_2, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_1, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_8, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_DT_ADDRS.ECM_5, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_DT_ADDRS.DAS_3, 2, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + static RxCheck chrysler_rx_checks[] = { + {.msg = {{CHRYSLER_ADDRS.EPS_2, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_ADDRS.ESP_1, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + //{.msg = {{ESP_8, 0, 8, .max_counter = 15U, .ignore_quality_flag = true, .frequency = 50U}}}, + {.msg = {{514, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_ADDRS.ECM_5, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_ADDRS.DAS_3, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + static const CanMsg CHRYSLER_TX_MSGS[] = { + {CHRYSLER_ADDRS.CRUISE_BUTTONS, 0, 3, .check_relay = false}, + {CHRYSLER_ADDRS.LKAS_COMMAND, 0, 6, .check_relay = true}, + {CHRYSLER_ADDRS.DAS_6, 0, 8, .check_relay = true}, + }; + + static const CanMsg CHRYSLER_RAM_DT_TX_MSGS[] = { + {CHRYSLER_RAM_DT_ADDRS.CRUISE_BUTTONS, 2, 3, .check_relay = false}, + {CHRYSLER_RAM_DT_ADDRS.LKAS_COMMAND, 0, 8, .check_relay = true}, + {CHRYSLER_RAM_DT_ADDRS.DAS_6, 0, 8, .check_relay = true}, + }; + +#ifdef ALLOW_DEBUG + // CAN messages for the 5th gen RAM HD platform + static const ChryslerAddrs CHRYSLER_RAM_HD_ADDRS = { + .EPS_2 = 0x220, // EPS driver input torque + .ESP_1 = 0x140, // Brake pedal and vehicle speed + .ESP_8 = 0x11C, // Brake pedal and vehicle speed + .ECM_5 = 0x22F, // Throttle position sensor + .DAS_3 = 0x1F4, // ACC engagement states from DASM + .DAS_6 = 0x275, // LKAS HUD and auto headlight control from DASM + .LKAS_COMMAND = 0x276, // LKAS controls from DASM + .CRUISE_BUTTONS = 0x23A, // Cruise control buttons + }; + + static RxCheck chrysler_ram_hd_rx_checks[] = { + {.msg = {{CHRYSLER_RAM_HD_ADDRS.EPS_2, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_1, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_8, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_HD_ADDRS.ECM_5, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{CHRYSLER_RAM_HD_ADDRS.DAS_3, 2, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + static const CanMsg CHRYSLER_RAM_HD_TX_MSGS[] = { + {CHRYSLER_RAM_HD_ADDRS.CRUISE_BUTTONS, 2, 3, .check_relay = false}, + {CHRYSLER_RAM_HD_ADDRS.LKAS_COMMAND, 0, 8, .check_relay = true}, + {CHRYSLER_RAM_HD_ADDRS.DAS_6, 0, 8, .check_relay = true}, + }; + + const uint32_t CHRYSLER_PARAM_RAM_HD = 2U; // set for Ram HD platform + bool enable_ram_hd = GET_FLAG(param, CHRYSLER_PARAM_RAM_HD); +#endif + + safety_config ret; + + bool enable_ram_dt = GET_FLAG(param, CHRYSLER_PARAM_RAM_DT); + + if (enable_ram_dt) { + chrysler_platform = CHRYSLER_RAM_DT; + chrysler_addrs = &CHRYSLER_RAM_DT_ADDRS; + ret = BUILD_SAFETY_CFG(chrysler_ram_dt_rx_checks, CHRYSLER_RAM_DT_TX_MSGS); +#ifdef ALLOW_DEBUG + } else if (enable_ram_hd) { + chrysler_platform = CHRYSLER_RAM_HD; + chrysler_addrs = &CHRYSLER_RAM_HD_ADDRS; + ret = BUILD_SAFETY_CFG(chrysler_ram_hd_rx_checks, CHRYSLER_RAM_HD_TX_MSGS); +#endif + } else { + chrysler_platform = CHRYSLER_PACIFICA; + chrysler_addrs = &CHRYSLER_ADDRS; + ret = BUILD_SAFETY_CFG(chrysler_rx_checks, CHRYSLER_TX_MSGS); + } + return ret; +} + +const safety_hooks chrysler_hooks = { + .init = chrysler_init, + .rx = chrysler_rx_hook, + .tx = chrysler_tx_hook, + .get_counter = chrysler_get_counter, + .get_checksum = chrysler_get_checksum, + .compute_checksum = chrysler_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/defaults.h b/opendbc_repo/opendbc/safety/modes/defaults.h new file mode 100644 index 0000000000..5f9d937613 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/defaults.h @@ -0,0 +1,51 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// GCOV_EXCL_START +// Unreachable by design (doesn't define any rx msgs) +void default_rx_hook(const CANPacket_t *msg) { + SAFETY_UNUSED(msg); +} +// GCOV_EXCL_STOP + +// *** no output safety mode *** + +static safety_config nooutput_init(uint16_t param) { + SAFETY_UNUSED(param); + return (safety_config){NULL, 0, NULL, 0, true}; // NOLINT(readability/braces) +} + +// GCOV_EXCL_START +// Unreachable by design (doesn't define any tx msgs) +static bool nooutput_tx_hook(const CANPacket_t *msg) { + SAFETY_UNUSED(msg); + return false; +} +// GCOV_EXCL_STOP + +const safety_hooks nooutput_hooks = { + .init = nooutput_init, + .rx = default_rx_hook, + .tx = nooutput_tx_hook, +}; + +// *** all output safety mode *** +static safety_config alloutput_init(uint16_t param) { + // Enables passthrough mode where relay is open and bus 0 gets forwarded to bus 2 and vice versa + const uint16_t ALLOUTPUT_PARAM_PASSTHROUGH = 1; + controls_allowed = true; + bool alloutput_passthrough = GET_FLAG(param, ALLOUTPUT_PARAM_PASSTHROUGH); + return (safety_config){NULL, 0, NULL, 0, !alloutput_passthrough}; // NOLINT(readability/braces) +} + +static bool alloutput_tx_hook(const CANPacket_t *msg) { + SAFETY_UNUSED(msg); + return true; +} + +const safety_hooks alloutput_hooks = { + .init = alloutput_init, + .rx = default_rx_hook, + .tx = alloutput_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/elm327.h b/opendbc_repo/opendbc/safety/modes/elm327.h new file mode 100644 index 0000000000..dbcc060120 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/elm327.h @@ -0,0 +1,40 @@ +#pragma once + +#include "opendbc/safety/declarations.h" +#include "opendbc/safety/modes/defaults.h" + +static bool elm327_tx_hook(const CANPacket_t *msg) { + const unsigned int GM_CAMERA_DIAG_ADDR = 0x24BU; + + bool tx = true; + int len = GET_LEN(msg); + + // All ISO 15765-4 messages must be 8 bytes long + if (len != 8) { + tx = false; + } + + // Check valid 29 bit send addresses for ISO 15765-4 + // Check valid 11 bit send addresses for ISO 15765-4 + if ((msg->addr != 0x18DB33F1U) && ((msg->addr & 0x1FFF00FFU) != 0x18DA00F1U) && + ((msg->addr & 0x1FFFFF00U) != 0x600U) && ((msg->addr & 0x1FFFFF00U) != 0x700U) && + (msg->addr != GM_CAMERA_DIAG_ADDR)) { + tx = false; + } + + // GM camera uses non-standard diagnostic address, this has no control message address collisions + if ((msg->addr == GM_CAMERA_DIAG_ADDR) && (len == 8)) { + // Only allow known frame types for ISO 15765-2 + if ((msg->data[0] & 0xF0U) > 0x30U) { + tx = false; + } + } + return tx; +} + +// If safety_param == 0, bus 1 is multiplexed to the OBD-II port +const safety_hooks elm327_hooks = { + .init = nooutput_init, + .rx = default_rx_hook, + .tx = elm327_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/ford.h b/opendbc_repo/opendbc/safety/modes/ford.h new file mode 100644 index 0000000000..4b35cf00f6 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/ford.h @@ -0,0 +1,362 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// Safety-relevant CAN messages for Ford vehicles. +#define FORD_EngBrakeData 0x165U // RX from PCM, for driver brake pedal and cruise state +#define FORD_EngVehicleSpThrottle 0x204U // RX from PCM, for driver throttle input +#define FORD_DesiredTorqBrk 0x213U // RX from ABS, for standstill state +#define FORD_BrakeSysFeatures 0x415U // RX from ABS, for vehicle speed +#define FORD_EngVehicleSpThrottle2 0x202U // RX from PCM, for second vehicle speed +#define FORD_Yaw_Data_FD1 0x91U // RX from RCM, for yaw rate +#define FORD_Steering_Data_FD1 0x083U // TX by OP, various driver switches and LKAS/CC buttons +#define FORD_ACCDATA 0x186U // TX by OP, ACC controls +#define FORD_ACCDATA_3 0x18AU // TX by OP, ACC/TJA user interface +#define FORD_Lane_Assist_Data1 0x3CAU // TX by OP, Lane Keep Assist +#define FORD_LateralMotionControl 0x3D3U // TX by OP, Lateral Control message +#define FORD_LateralMotionControl2 0x3D6U // TX by OP, alternate Lateral Control message +#define FORD_IPMA_Data 0x3D8U // TX by OP, IPMA and LKAS user interface + +// CAN bus numbers. +#define FORD_MAIN_BUS 0U +#define FORD_CAM_BUS 2U + +static uint8_t ford_get_counter(const CANPacket_t *msg) { + uint8_t cnt = 0; + if (msg->addr == FORD_BrakeSysFeatures) { + // Signal: VehVActlBrk_No_Cnt + cnt = (msg->data[2] >> 2) & 0xFU; + } else if (msg->addr == FORD_Yaw_Data_FD1) { + // Signal: VehRollYaw_No_Cnt + cnt = msg->data[5]; + } else { + } + return cnt; +} + +static uint32_t ford_get_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + if (msg->addr == FORD_BrakeSysFeatures) { + // Signal: VehVActlBrk_No_Cs + chksum = msg->data[3]; + } else if (msg->addr == FORD_Yaw_Data_FD1) { + // Signal: VehRollYawW_No_Cs + chksum = msg->data[4]; + } else { + } + return chksum; +} + +static uint32_t ford_compute_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + if (msg->addr == FORD_BrakeSysFeatures) { + chksum += msg->data[0] + msg->data[1]; // Veh_V_ActlBrk + chksum += msg->data[2] >> 6; // VehVActlBrk_D_Qf + chksum += (msg->data[2] >> 2) & 0xFU; // VehVActlBrk_No_Cnt + chksum = 0xFFU - chksum; + } else if (msg->addr == FORD_Yaw_Data_FD1) { + chksum += msg->data[0] + msg->data[1]; // VehRol_W_Actl + chksum += msg->data[2] + msg->data[3]; // VehYaw_W_Actl + chksum += msg->data[5]; // VehRollYaw_No_Cnt + chksum += msg->data[6] >> 6; // VehRolWActl_D_Qf + chksum += (msg->data[6] >> 4) & 0x3U; // VehYawWActl_D_Qf + chksum = 0xFFU - chksum; + } else { + } + return chksum; +} + +static bool ford_get_quality_flag_valid(const CANPacket_t *msg) { + bool valid = false; + if (msg->addr == FORD_BrakeSysFeatures) { + valid = (msg->data[2] >> 6) == 0x3U; // VehVActlBrk_D_Qf + } else if (msg->addr == FORD_EngVehicleSpThrottle2) { + valid = ((msg->data[4] >> 5) & 0x3U) == 0x3U; // VehVActlEng_D_Qf + } else if (msg->addr == FORD_Yaw_Data_FD1) { + valid = ((msg->data[6] >> 4) & 0x3U) == 0x3U; // VehYawWActl_D_Qf + } else { + } + return valid; +} + +#define FORD_INACTIVE_CURVATURE 1000U +#define FORD_INACTIVE_CURVATURE_RATE 4096U +#define FORD_INACTIVE_PATH_OFFSET 512U +#define FORD_INACTIVE_PATH_ANGLE 1000U + +#define FORD_CANFD_INACTIVE_CURVATURE_RATE 1024U + +// Curvature rate limits +#define FORD_LIMITS(limit_lateral_acceleration) { \ + .max_angle = 1000, /* 0.02 curvature */ \ + .angle_deg_to_can = 50000, /* 1 / (2e-5) rad to can */ \ + .max_angle_error = 100, /* 0.002 * FORD_STEERING_LIMITS.angle_deg_to_can */ \ + .angle_rate_up_lookup = { \ + {5., 25., 25.}, \ + {0.00045, 0.0001, 0.0001} \ + }, \ + .angle_rate_down_lookup = { \ + {5., 25., 25.}, \ + {0.00045, 0.00015, 0.00015} \ + }, \ + \ + /* no blending at low speed due to lack of torque wind-up and inaccurate current curvature */ \ + .angle_error_min_speed = 10.0, /* m/s */ \ + \ + .angle_is_curvature = (limit_lateral_acceleration), \ + .enforce_angle_error = true, \ + .inactive_angle_is_zero = true, \ +} + +static const AngleSteeringLimits FORD_STEERING_LIMITS = FORD_LIMITS(false); + +static void ford_rx_hook(const CANPacket_t *msg) { + if (msg->bus == FORD_MAIN_BUS) { + // Update in motion state from standstill signal + if (msg->addr == FORD_DesiredTorqBrk) { + // Signal: VehStop_D_Stat + vehicle_moving = ((msg->data[3] >> 3) & 0x3U) != 1U; + } + + // Update vehicle speed + if (msg->addr == FORD_BrakeSysFeatures) { + // Signal: Veh_V_ActlBrk + UPDATE_VEHICLE_SPEED(((msg->data[0] << 8) | msg->data[1]) * 0.01 * KPH_TO_MS); + } + + // Check vehicle speed against a second source + if (msg->addr == FORD_EngVehicleSpThrottle2) { + // Disable controls if speeds from ABS and PCM ECUs are too far apart. + // Signal: Veh_V_ActlEng + float filtered_pcm_speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01 * KPH_TO_MS; + speed_mismatch_check(filtered_pcm_speed); + } + + // Update vehicle yaw rate + if (msg->addr == FORD_Yaw_Data_FD1) { + // Signal: VehYaw_W_Actl + // TODO: we should use the speed which results in the closest angle measurement to the desired angle + float ford_yaw_rate = (((msg->data[2] << 8U) | msg->data[3]) * 0.0002) - 6.5; + float current_curvature = ford_yaw_rate / SAFETY_MAX(vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR, 0.1); + // convert current curvature into units on CAN for comparison with desired curvature + update_sample(&angle_meas, ROUND(current_curvature * FORD_STEERING_LIMITS.angle_deg_to_can)); + } + + // Update gas pedal + if (msg->addr == FORD_EngVehicleSpThrottle) { + // Pedal position: (0.1 * val) in percent + // Signal: ApedPos_Pc_ActlArb + gas_pressed = (((msg->data[0] & 0x03U) << 8) | msg->data[1]) > 0U; + } + + // Update brake pedal and cruise state + if (msg->addr == FORD_EngBrakeData) { + // Signal: BpedDrvAppl_D_Actl + brake_pressed = ((msg->data[0] >> 4) & 0x3U) == 2U; + + // Signal: CcStat_D_Actl + unsigned int cruise_state = msg->data[1] & 0x07U; + bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U); + pcm_cruise_check(cruise_engaged); + } + } +} + +static bool ford_tx_hook(const CANPacket_t *msg) { + const LongitudinalLimits FORD_LONG_LIMITS = { + // acceleration cmd limits (used for brakes) + // Signal: AccBrkTot_A_Rq + .max_accel = 5641, // 1.9999 m/s^s + .min_accel = 4231, // -3.4991 m/s^2 + .inactive_accel = 5128, // -0.0008 m/s^2 + + // gas cmd limits + // Signal: AccPrpl_A_Rq & AccPrpl_A_Pred + .max_gas = 700, // 2.0 m/s^2 + .min_gas = 450, // -0.5 m/s^2 + .inactive_gas = 0, // -5.0 m/s^2 + }; + + bool tx = true; + + // Safety check for ACCDATA accel and brake requests + if (msg->addr == FORD_ACCDATA) { + // Signal: AccPrpl_A_Rq + int gas = ((msg->data[6] & 0x3U) << 8) | msg->data[7]; + // Signal: AccPrpl_A_Pred + int gas_pred = ((msg->data[2] & 0x3U) << 8) | msg->data[3]; + // Signal: AccBrkTot_A_Rq + int accel = ((msg->data[0] & 0x1FU) << 8) | msg->data[1]; + // Signal: CmbbDeny_B_Actl + bool cmbb_deny = (msg->data[4] >> 5) & 1U; + + // Signal: AccBrkPrchg_B_Rq & AccBrkDecel_B_Rq + bool brake_actuation = ((msg->data[6] >> 6) & 1U) || ((msg->data[6] >> 7) & 1U); + + bool violation = false; + violation |= longitudinal_accel_checks(accel, FORD_LONG_LIMITS); + violation |= longitudinal_gas_checks(gas, FORD_LONG_LIMITS); + violation |= longitudinal_gas_checks(gas_pred, FORD_LONG_LIMITS); + + // Safety check for stock AEB + violation |= cmbb_deny; // do not prevent stock AEB actuation + + violation |= !get_longitudinal_allowed() && brake_actuation; + + if (violation) { + tx = false; + } + } + + // Safety check for Steering_Data_FD1 button signals + // Note: Many other signals in this message are not relevant to safety (e.g. blinkers, wiper switches, high beam) + // which we passthru in OP. + if (msg->addr == FORD_Steering_Data_FD1) { + // Violation if resume button is pressed while controls not allowed, or + // if cancel button is pressed when cruise isn't engaged. + bool violation = false; + violation |= ((msg->data[1] >> 0) & 1U) && !cruise_engaged_prev; // Signal: CcAslButtnCnclPress (cancel) + violation |= ((msg->data[3] >> 1) & 1U) && !controls_allowed; // Signal: CcAsllButtnResPress (resume) + + if (violation) { + tx = false; + } + } + + // Safety check for Lane_Assist_Data1 action + if (msg->addr == FORD_Lane_Assist_Data1) { + // Do not allow steering using Lane_Assist_Data1 (Lane-Departure Aid). + // This message must be sent for Lane Centering to work, and can include + // values such as the steering angle or lane curvature for debugging, + // but the action (LkaActvStats_D2_Req) must be set to zero. + unsigned int action = msg->data[0] >> 5; + if (action != 0U) { + tx = false; + } + } + + // Safety check for LateralMotionControl action + if (msg->addr == FORD_LateralMotionControl) { + // Signal: LatCtl_D_Rq + bool steer_control_enabled = ((msg->data[4] >> 2) & 0x7U) != 0U; + unsigned int raw_curvature = (msg->data[0] << 3) | (msg->data[1] >> 5); + unsigned int raw_curvature_rate = ((msg->data[1] & 0x1FU) << 8) | msg->data[2]; + unsigned int raw_path_angle = (msg->data[3] << 3) | (msg->data[4] >> 5); + unsigned int raw_path_offset = (msg->data[5] << 2) | (msg->data[6] >> 6); + + // These signals are not yet tested with the current safety limits + bool violation = (raw_curvature_rate != FORD_INACTIVE_CURVATURE_RATE) || (raw_path_angle != FORD_INACTIVE_PATH_ANGLE) || (raw_path_offset != FORD_INACTIVE_PATH_OFFSET); + + // Check angle error and steer_control_enabled + int desired_curvature = raw_curvature - FORD_INACTIVE_CURVATURE; // /FORD_STEERING_LIMITS.angle_deg_to_can to get real curvature + violation |= steer_angle_cmd_checks(desired_curvature, steer_control_enabled, FORD_STEERING_LIMITS); + + if (violation) { + tx = false; + } + } + + // Safety check for LateralMotionControl2 action + if (msg->addr == FORD_LateralMotionControl2) { + static const AngleSteeringLimits FORD_CANFD_STEERING_LIMITS = FORD_LIMITS(true); + + // Signal: LatCtl_D2_Rq + bool steer_control_enabled = ((msg->data[0] >> 4) & 0x7U) != 0U; + unsigned int raw_curvature = (msg->data[2] << 3) | (msg->data[3] >> 5); + unsigned int raw_curvature_rate = (msg->data[6] << 3) | (msg->data[7] >> 5); + unsigned int raw_path_angle = ((msg->data[3] & 0x1FU) << 6) | (msg->data[4] >> 2); + unsigned int raw_path_offset = ((msg->data[4] & 0x3U) << 8) | msg->data[5]; + + // These signals are not yet tested with the current safety limits + bool violation = (raw_curvature_rate != FORD_CANFD_INACTIVE_CURVATURE_RATE) || (raw_path_angle != FORD_INACTIVE_PATH_ANGLE) || (raw_path_offset != FORD_INACTIVE_PATH_OFFSET); + + // Check angle error and steer_control_enabled + int desired_curvature = raw_curvature - FORD_INACTIVE_CURVATURE; // /FORD_STEERING_LIMITS.angle_deg_to_can to get real curvature + violation |= steer_angle_cmd_checks(desired_curvature, steer_control_enabled, FORD_CANFD_STEERING_LIMITS); + + if (violation) { + tx = false; + } + } + + return tx; +} + +static safety_config ford_init(uint16_t param) { + // warning: quality flags are not yet checked in openpilot's CAN parser, + // this may be the cause of blocked messages + static RxCheck ford_rx_checks[] = { + {.msg = {{FORD_BrakeSysFeatures, 0, 8, 50U, .max_counter = 15U}, { 0 }, { 0 }}}, + // FORD_EngVehicleSpThrottle2 has a counter that either randomly skips or by 2, likely ECU bug + // Some hybrid models also experience a bug where this checksum mismatches for one or two frames under heavy acceleration with ACC + // It has been confirmed that the Bronco Sport's camera only disallows ACC for bad quality flags, not counters or checksums, so we match that + {.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true}, { 0 }, { 0 }}}, + {.msg = {{FORD_Yaw_Data_FD1, 0, 8, 100U, .max_counter = 255U}, { 0 }, { 0 }}}, + // These messages have no counter or checksum + {.msg = {{FORD_EngBrakeData, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{FORD_EngVehicleSpThrottle, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{FORD_DesiredTorqBrk, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + #define FORD_COMMON_TX_MSGS \ + {FORD_Steering_Data_FD1, 0, 8, .check_relay = false}, \ + {FORD_Steering_Data_FD1, 2, 8, .check_relay = false}, \ + {FORD_ACCDATA_3, 0, 8, .check_relay = true}, \ + {FORD_Lane_Assist_Data1, 0, 8, .check_relay = true}, \ + {FORD_IPMA_Data, 0, 8, .check_relay = true}, \ + + static const CanMsg FORD_CANFD_LONG_TX_MSGS[] = { + FORD_COMMON_TX_MSGS + {FORD_ACCDATA, 0, 8, .check_relay = true}, + {FORD_LateralMotionControl2, 0, 8, .check_relay = true}, + }; + + static const CanMsg FORD_CANFD_STOCK_TX_MSGS[] = { + FORD_COMMON_TX_MSGS + {FORD_LateralMotionControl2, 0, 8, .check_relay = true}, + }; + + static const CanMsg FORD_STOCK_TX_MSGS[] = { + FORD_COMMON_TX_MSGS + {FORD_LateralMotionControl, 0, 8, .check_relay = true}, + }; + + static const CanMsg FORD_LONG_TX_MSGS[] = { + FORD_COMMON_TX_MSGS + {FORD_ACCDATA, 0, 8, .check_relay = true}, + {FORD_LateralMotionControl, 0, 8, .check_relay = true}, + }; + + const uint16_t FORD_PARAM_CANFD = 2; + const bool ford_canfd = GET_FLAG(param, FORD_PARAM_CANFD); + + bool ford_longitudinal = false; + +#ifdef ALLOW_DEBUG + const uint16_t FORD_PARAM_LONGITUDINAL = 1; + ford_longitudinal = GET_FLAG(param, FORD_PARAM_LONGITUDINAL); +#endif + + // Longitudinal is the default for CAN, and optional for CAN FD w/ ALLOW_DEBUG + ford_longitudinal = !ford_canfd || ford_longitudinal; + + safety_config ret; + if (ford_canfd) { + ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_STOCK_TX_MSGS); + } else { + ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(ford_rx_checks, FORD_STOCK_TX_MSGS); + } + return ret; +} + +const safety_hooks ford_hooks = { + .init = ford_init, + .rx = ford_rx_hook, + .tx = ford_tx_hook, + .get_counter = ford_get_counter, + .get_checksum = ford_get_checksum, + .compute_checksum = ford_compute_checksum, + .get_quality_flag_valid = ford_get_quality_flag_valid, +}; diff --git a/opendbc_repo/opendbc/safety/modes/gm.h b/opendbc_repo/opendbc/safety/modes/gm.h new file mode 100644 index 0000000000..aa0cdac65c --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/gm.h @@ -0,0 +1,244 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// TODO: do checksum and counter checks. Add correct timestep, 0.1s for now. +#define GM_COMMON_RX_CHECKS \ + {.msg = {{0x184, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x34A, 0, 5, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x1E1, 0, 7, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0xBE, 0, 6, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, /* Volt, Silverado, Acadia Denali */ \ + {0xBE, 0, 7, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, /* Bolt EUV */ \ + {0xBE, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}}}, /* Escalade */ \ + {.msg = {{0x1C4, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0xC9, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +static const LongitudinalLimits *gm_long_limits; + +enum { + GM_BTN_UNPRESS = 1, + GM_BTN_RESUME = 2, + GM_BTN_SET = 3, + GM_BTN_CANCEL = 6, +}; + +typedef enum { + GM_ASCM, + GM_CAM +} GmHardware; +static GmHardware gm_hw = GM_ASCM; +static bool gm_pcm_cruise = false; + +static void gm_rx_hook(const CANPacket_t *msg) { + const int GM_STANDSTILL_THRSLD = 10; // 0.311kph + + if (msg->bus == 0U) { + if (msg->addr == 0x184U) { + int torque_driver_new = ((msg->data[6] & 0x7U) << 8) | msg->data[7]; + torque_driver_new = to_signed(torque_driver_new, 11); + // update array of samples + update_sample(&torque_driver, torque_driver_new); + } + + // sample rear wheel speeds + if (msg->addr == 0x34AU) { + int left_rear_speed = (msg->data[0] << 8) | msg->data[1]; + int right_rear_speed = (msg->data[2] << 8) | msg->data[3]; + vehicle_moving = (left_rear_speed > GM_STANDSTILL_THRSLD) || (right_rear_speed > GM_STANDSTILL_THRSLD); + } + + // ACC steering wheel buttons (GM_CAM is tied to the PCM) + if ((msg->addr == 0x1E1U) && !gm_pcm_cruise) { + int button = (msg->data[5] & 0x70U) >> 4; + + // enter controls on falling edge of set or rising edge of resume (avoids fault) + bool set = (button != GM_BTN_SET) && (cruise_button_prev == GM_BTN_SET); + bool res = (button == GM_BTN_RESUME) && (cruise_button_prev != GM_BTN_RESUME); + if (set || res) { + controls_allowed = true; + } + + // exit controls on cancel press + if (button == GM_BTN_CANCEL) { + controls_allowed = false; + } + + cruise_button_prev = button; + } + + // Reference for brake pressed signals: + // https://github.com/commaai/openpilot/blob/master/selfdrive/car/gm/carstate.py + if ((msg->addr == 0xBEU) && (gm_hw == GM_ASCM)) { + brake_pressed = msg->data[1] >= 8U; + } + + if ((msg->addr == 0xC9U) && (gm_hw == GM_CAM)) { + brake_pressed = GET_BIT(msg, 40U); + } + + if (msg->addr == 0x1C4U) { + gas_pressed = msg->data[5] != 0U; + + // enter controls on rising edge of ACC, exit controls when ACC off + if (gm_pcm_cruise) { + bool cruise_engaged = (msg->data[1] >> 5) != 0U; + pcm_cruise_check(cruise_engaged); + } + } + + if (msg->addr == 0xBDU) { + regen_braking = (msg->data[0] >> 4) != 0U; + } + } +} + +static bool gm_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits GM_STEERING_LIMITS = { + .max_torque = 300, + .max_rate_up = 10, + .max_rate_down = 15, + .driver_torque_allowance = 65, + .driver_torque_multiplier = 4, + .max_rt_delta = 128, + .type = TorqueDriverLimited, + }; + + bool tx = true; + + // BRAKE: safety check + if (msg->addr == 0x315U) { + int brake = ((msg->data[0] & 0xFU) << 8) + msg->data[1]; + brake = (0x1000 - brake) & 0xFFF; + if (longitudinal_brake_checks(brake, *gm_long_limits)) { + tx = false; + } + } + + // LKA STEER: safety check + if (msg->addr == 0x180U) { + int desired_torque = ((msg->data[0] & 0x7U) << 8) + msg->data[1]; + desired_torque = to_signed(desired_torque, 11); + + bool steer_req = GET_BIT(msg, 3U); + + if (steer_torque_cmd_checks(desired_torque, steer_req, GM_STEERING_LIMITS)) { + tx = false; + } + } + + // GAS/REGEN: safety check + if (msg->addr == 0x2CBU) { + bool apply = GET_BIT(msg, 0U); + // convert float CAN signal to an int for gas checks: 22534 / 0.125 = 180272 + int gas_regen = (((msg->data[1] & 0x7U) << 16) | (msg->data[2] << 8) | msg->data[3]) - 180272U; + + bool violation = false; + // Allow apply bit in pre-enabled and overriding states + violation |= !controls_allowed && apply; + violation |= longitudinal_gas_checks(gas_regen, *gm_long_limits); + + if (violation) { + tx = false; + } + } + + // BUTTONS: used for resume spamming and cruise cancellation with stock longitudinal + if ((msg->addr == 0x1E1U) && gm_pcm_cruise) { + int button = (msg->data[5] >> 4) & 0x7U; + + bool allowed_cancel = (button == 6) && cruise_engaged_prev; + if (!allowed_cancel) { + tx = false; + } + } + + return tx; +} + +static safety_config gm_init(uint16_t param) { + const uint16_t GM_PARAM_HW_CAM = 1; + const uint16_t GM_PARAM_EV = 4; + + // common safety checks assume unscaled integer values + static const int GM_GAS_TO_CAN = 8; // 1 / 0.125 + + static const LongitudinalLimits GM_ASCM_LONG_LIMITS = { + .max_gas = 1018 * GM_GAS_TO_CAN, + .min_gas = -650 * GM_GAS_TO_CAN, + .inactive_gas = -650 * GM_GAS_TO_CAN, + .max_brake = 400, + }; + + static const CanMsg GM_ASCM_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, {0x409, 0, 7, .check_relay = false}, {0x40A, 0, 7, .check_relay = false}, {0x2CB, 0, 8, .check_relay = true}, {0x370, 0, 6, .check_relay = false}, // pt bus + {0xA1, 1, 7, .check_relay = false}, {0x306, 1, 8, .check_relay = false}, {0x308, 1, 7, .check_relay = false}, {0x310, 1, 2, .check_relay = false}, // obs bus + {0x315, 2, 5, .check_relay = false}}; // ch bus + + + static const LongitudinalLimits GM_CAM_LONG_LIMITS = { + .max_gas = 1346 * GM_GAS_TO_CAN, + .min_gas = -540 * GM_GAS_TO_CAN, + .inactive_gas = -500 * GM_GAS_TO_CAN, + .max_brake = 400, + }; + + // block PSCMStatus (0x184); forwarded through openpilot to hide an alert from the camera + static const CanMsg GM_CAM_LONG_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, {0x315, 0, 5, .check_relay = true}, {0x2CB, 0, 8, .check_relay = true}, {0x370, 0, 6, .check_relay = true}, // pt bus + {0x184, 2, 8, .check_relay = true}}; // camera bus + + + static RxCheck gm_rx_checks[] = { + GM_COMMON_RX_CHECKS + }; + + static RxCheck gm_ev_rx_checks[] = { + GM_COMMON_RX_CHECKS + {.msg = {{0xBD, 0, 7, 40U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + static const CanMsg GM_CAM_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, // pt bus + {0x1E1, 2, 7, .check_relay = false}, {0x184, 2, 8, .check_relay = true}}; // camera bus + + gm_hw = GET_FLAG(param, GM_PARAM_HW_CAM) ? GM_CAM : GM_ASCM; + + if (gm_hw == GM_ASCM) { + gm_long_limits = &GM_ASCM_LONG_LIMITS; + } else if (gm_hw == GM_CAM) { + gm_long_limits = &GM_CAM_LONG_LIMITS; + } else { + } + + bool gm_cam_long = false; + +#ifdef ALLOW_DEBUG + const uint16_t GM_PARAM_HW_CAM_LONG = 2; + gm_cam_long = GET_FLAG(param, GM_PARAM_HW_CAM_LONG); +#endif + gm_pcm_cruise = (gm_hw == GM_CAM) && !gm_cam_long; + + safety_config ret; + if (gm_hw == GM_CAM) { + // FIXME: cppcheck thinks that gm_cam_long is always false. This is not true + // if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG + // cppcheck-suppress knownConditionTrueFalse + ret = gm_cam_long ? BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_LONG_TX_MSGS) : BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_TX_MSGS); + } else { + ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_ASCM_TX_MSGS); + } + + const bool gm_ev = GET_FLAG(param, GM_PARAM_EV); + if (gm_ev) { + SET_RX_CHECKS(gm_ev_rx_checks, ret); + } + + // ASCM does not forward any messages + if (gm_hw == GM_ASCM) { + ret.disable_forwarding = true; + } + return ret; +} + +const safety_hooks gm_hooks = { + .init = gm_init, + .rx = gm_rx_hook, + .tx = gm_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/honda.h b/opendbc_repo/opendbc/safety/modes/honda.h new file mode 100644 index 0000000000..9f49ef762c --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/honda.h @@ -0,0 +1,436 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// All common address checks except SCM_BUTTONS which isn't on one Nidec safety configuration +#define HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \ + {.msg = {{0x1A6, (pt_bus), 8, 25U, .max_counter = 3U, .ignore_quality_flag = true}, /* SCM_BUTTONS */ \ + {0x296, (pt_bus), 4, 25U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }}}, \ + {.msg = {{0x158, (pt_bus), 8, 100U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* ENGINE_DATA */ \ + {.msg = {{0x17C, (pt_bus), 8, 100U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* POWERTRAIN_DATA */ \ + +#define HONDA_COMMON_RX_CHECKS(pt_bus) \ + HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \ + {.msg = {{0x326, (pt_bus), 8, 10U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* SCM_FEEDBACK */ \ + +// Alternate brake message is used on some Honda Bosch, and Honda Bosch radarless (where PT bus is 0) +#define HONDA_ALT_BRAKE_ADDR_CHECK(pt_bus) \ + {.msg = {{0x1BE, (pt_bus), 3, 50U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, /* BRAKE_MODULE */ \ + +enum { + HONDA_BTN_NONE = 0, + HONDA_BTN_MAIN = 1, + HONDA_BTN_CANCEL = 2, + HONDA_BTN_SET = 3, + HONDA_BTN_RESUME = 4, +}; + +static int honda_brake = 0; +static bool honda_brake_switch_prev = false; +static bool honda_alt_brake_msg = false; +static bool honda_fwd_brake = false; +static bool honda_bosch_long = false; +static bool honda_bosch_radarless = false; +static bool honda_bosch_canfd = false; +typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw; +static HondaHw honda_hw = HONDA_NIDEC; + + +static unsigned int honda_get_pt_bus(void) { + return ((honda_hw == HONDA_BOSCH) && !honda_bosch_radarless && !honda_bosch_canfd) ? 1U : 0U; +} + +static uint32_t honda_get_checksum(const CANPacket_t *msg) { + int checksum_byte = GET_LEN(msg) - 1U; + return (uint8_t)(msg->data[checksum_byte]) & 0xFU; +} + +static uint32_t honda_compute_checksum(const CANPacket_t *msg) { + int len = GET_LEN(msg); + uint8_t checksum = 0U; + unsigned int addr = msg->addr; + while (addr > 0U) { + checksum += (uint8_t)(addr & 0xFU); addr >>= 4; + } + for (int j = 0; j < len; j++) { + uint8_t byte = msg->data[j]; + checksum += (uint8_t)(byte & 0xFU) + (byte >> 4U); + if (j == (len - 1)) { + checksum -= (byte & 0xFU); // remove checksum in message + } + } + return (uint8_t)((8U - checksum) & 0xFU); +} + +static uint8_t honda_get_counter(const CANPacket_t *msg) { + int counter_byte = GET_LEN(msg) - 1U; + return (msg->data[counter_byte] >> 4U) & 0x3U; +} + +static void honda_rx_hook(const CANPacket_t *msg) { + const bool pcm_cruise = ((honda_hw == HONDA_BOSCH) && !honda_bosch_long) || (honda_hw == HONDA_NIDEC); + unsigned int pt_bus = honda_get_pt_bus(); + + // sample speed + if (msg->addr == 0x158U) { + vehicle_moving = msg->data[0] | msg->data[1]; + } + + // check ACC main state + // 0x326 for all Bosch and some Nidec, 0x1A6 for some Nidec + if ((msg->addr == 0x326U) || (msg->addr == 0x1A6U)) { + acc_main_on = GET_BIT(msg, ((msg->addr == 0x326U) ? 28U : 47U)); + if (!acc_main_on) { + controls_allowed = false; + } + } + + // enter controls when PCM enters cruise state + if (pcm_cruise && (msg->addr == 0x17CU)) { + const bool cruise_engaged = GET_BIT(msg, 38U); + // engage on rising edge + if (cruise_engaged && !cruise_engaged_prev) { + controls_allowed = true; + } + + // Since some Nidec cars can brake down to 0 after the PCM disengages, + // we don't disengage when the PCM does. + if (!cruise_engaged && (honda_hw != HONDA_NIDEC)) { + controls_allowed = false; + } + cruise_engaged_prev = cruise_engaged; + } + + // state machine to enter and exit controls for button enabling + // 0x1A6 for the ILX, 0x296 for the Civic Touring + if (((msg->addr == 0x1A6U) || (msg->addr == 0x296U)) && (msg->bus == pt_bus)) { + int button = (msg->data[0] & 0xE0U) >> 5; + + // enter controls on the falling edge of set or resume + bool set = (button != HONDA_BTN_SET) && (cruise_button_prev == HONDA_BTN_SET); + bool res = (button != HONDA_BTN_RESUME) && (cruise_button_prev == HONDA_BTN_RESUME); + if (acc_main_on && !pcm_cruise && (set || res)) { + controls_allowed = true; + } + + // exit controls once main or cancel are pressed + if ((button == HONDA_BTN_MAIN) || (button == HONDA_BTN_CANCEL)) { + controls_allowed = false; + } + cruise_button_prev = button; + } + + // user brake signal on 0x17C reports applied brake from computer brake on accord + // and crv, which prevents the usual brake safety from working correctly. these + // cars have a signal on 0x1BE which only detects user's brake being applied so + // in these cases, this is used instead. + // most hondas: 0x17C + // accord, crv: 0x1BE + if (honda_alt_brake_msg) { + if (msg->addr == 0x1BEU) { + brake_pressed = GET_BIT(msg, 4U); + } + } else { + if (msg->addr == 0x17CU) { + // also if brake switch is 1 for two CAN frames, as brake pressed is delayed + const bool brake_switch = GET_BIT(msg, 32U); + brake_pressed = (GET_BIT(msg, 53U)) || (brake_switch && honda_brake_switch_prev); + honda_brake_switch_prev = brake_switch; + } + } + + if (msg->addr == 0x17CU) { + gas_pressed = msg->data[0] != 0U; + } + + // disable stock Honda AEB in alternative experience + if (!(alternative_experience & ALT_EXP_DISABLE_STOCK_AEB)) { + if ((msg->bus == 2U) && (msg->addr == 0x1FAU)) { + bool honda_stock_aeb = GET_BIT(msg, 29U); + int honda_stock_brake = (msg->data[0] << 2) | (msg->data[1] >> 6); + + // Forward AEB when stock braking is higher than openpilot braking + // only stop forwarding when AEB event is over + if (!honda_stock_aeb) { + honda_fwd_brake = false; + } else if (honda_stock_brake >= honda_brake) { + honda_fwd_brake = true; + } else { + // Leave Honda forward brake as is + } + } + } +} + +static bool honda_tx_hook(const CANPacket_t *msg) { + + const LongitudinalLimits HONDA_BOSCH_LONG_LIMITS = { + .max_accel = 200, // accel is used for brakes + .min_accel = -350, + + .max_gas = 2000, + .inactive_gas = -30000, + }; + + const LongitudinalLimits HONDA_NIDEC_LONG_LIMITS = { + .max_gas = 198, // 0xc6 + .max_brake = 255, + + .inactive_speed = 0, + }; + + bool tx = true; + + unsigned int bus_pt = honda_get_pt_bus(); + unsigned int bus_buttons = (honda_bosch_radarless) ? 2U : bus_pt; // the camera controls ACC on radarless Bosch cars + + // ACC_HUD: safety check (nidec w/o pedal) + if ((msg->addr == 0x30CU) && (msg->bus == bus_pt)) { + int pcm_speed = (msg->data[0] << 8) | msg->data[1]; + int pcm_gas = msg->data[2]; + + bool violation = false; + violation |= longitudinal_speed_checks(pcm_speed, HONDA_NIDEC_LONG_LIMITS); + violation |= longitudinal_gas_checks(pcm_gas, HONDA_NIDEC_LONG_LIMITS); + if (violation) { + tx = false; + } + } + + // BRAKE: safety check (nidec) + if ((msg->addr == 0x1FAU) && (msg->bus == bus_pt)) { + honda_brake = (msg->data[0] << 2) + ((msg->data[1] >> 6) & 0x3U); + if (longitudinal_brake_checks(honda_brake, HONDA_NIDEC_LONG_LIMITS)) { + tx = false; + } + if (honda_fwd_brake) { + tx = false; + } + } + + // BRAKE/GAS: safety check (bosch) + if ((msg->addr == 0x1DFU) && (msg->bus == bus_pt)) { + int accel = (msg->data[3] << 3) | ((msg->data[4] >> 5) & 0x7U); + accel = to_signed(accel, 11); + + int gas = (msg->data[0] << 8) | msg->data[1]; + gas = to_signed(gas, 16); + + bool violation = false; + violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); + violation |= longitudinal_gas_checks(gas, HONDA_BOSCH_LONG_LIMITS); + if (violation) { + tx = false; + } + } + + // ACCEL: safety check (radarless) + if ((msg->addr == 0x1C8U) && (msg->bus == bus_pt)) { + int accel = (msg->data[0] << 4) | (msg->data[1] >> 4); + accel = to_signed(accel, 12); + + bool violation = false; + violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); + if (violation) { + tx = false; + } + } + + // STEER: safety check + if ((msg->addr == 0xE4U) || (msg->addr == 0x194U)) { + if (!controls_allowed) { + bool steer_applied = msg->data[0] | msg->data[1]; + if (steer_applied) { + tx = false; + } + } + } + + // Bosch supplemental control check + if (msg->addr == 0xE5U) { + if ((GET_BYTES(msg, 0, 4) != 0x10800004U) || ((GET_BYTES(msg, 4, 4) & 0x00FFFFFFU) != 0x0U)) { + tx = false; + } + } + + // FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW + // ensuring that only the cancel button press is sent (VAL 2) when controls are off. + // This avoids unintended engagements while still allowing resume spam + if ((msg->addr == 0x296U) && !controls_allowed && (msg->bus == bus_buttons)) { + if (((msg->data[0] >> 5) & 0x7U) != 2U) { + tx = false; + } + } + + // Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address + if (msg->addr == 0x18DAB0F1U) { + if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + tx = false; + } + } + + return tx; +} + +static safety_config honda_nidec_init(uint16_t param) { + // 0x1FA is dynamically forwarded based on stock AEB + // 0xE4 is steering on all cars except CRV and RDX, 0x194 for CRV and RDX, + // 0x1FA is brake control, 0x30C is acc hud, 0x33D is lkas hud + static CanMsg HONDA_N_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x194, 0, 4, .check_relay = true}, {0x1FA, 0, 8, .check_relay = false}, + {0x30C, 0, 8, .check_relay = true}, {0x33D, 0, 5, .check_relay = true}}; + + const uint16_t HONDA_PARAM_NIDEC_ALT = 4; + + honda_hw = HONDA_NIDEC; + honda_brake = 0; + honda_brake_switch_prev = false; + honda_fwd_brake = false; + honda_alt_brake_msg = false; + honda_bosch_long = false; + honda_bosch_radarless = false; + honda_bosch_canfd = false; + + safety_config ret; + + bool enable_nidec_alt = GET_FLAG(param, HONDA_PARAM_NIDEC_ALT); + + if (enable_nidec_alt) { + // For Nidecs with main on signal on an alternate msg (missing 0x326) + static RxCheck honda_nidec_alt_rx_checks[] = { + HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(0) + {.msg = {{0x1FA, 2, 8, 50U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // BRAKE_COMMAND + }; + + SET_RX_CHECKS(honda_nidec_alt_rx_checks, ret); + } else { + // Nidec includes BRAKE_COMMAND + static RxCheck honda_nidec_common_rx_checks[] = { + HONDA_COMMON_RX_CHECKS(0) + {.msg = {{0x1FA, 2, 8, 50U, .max_counter = 3U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // BRAKE_COMMAND + }; + + SET_RX_CHECKS(honda_nidec_common_rx_checks, ret); + } + + SET_TX_MSGS(HONDA_N_TX_MSGS, ret); + + return ret; +} + +static safety_config honda_bosch_init(uint16_t param) { + static CanMsg HONDA_BOSCH_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0xE5, 0, 8, .check_relay = true}, {0x296, 1, 4, .check_relay = false}, + {0x33D, 0, 5, .check_relay = true}, {0x33D, 0, 8, .check_relay = true}, {0x33DA, 0, 5, .check_relay = true}, {0x33DB, 0, 8, .check_relay = true}}; // Bosch + + static CanMsg HONDA_BOSCH_LONG_TX_MSGS[] = {{0xE4, 1, 5, .check_relay = true}, {0x1DF, 1, 8, .check_relay = true}, {0x1EF, 1, 8, .check_relay = false}, + {0x1FA, 1, 8, .check_relay = false}, {0x30C, 1, 8, .check_relay = false}, {0x33D, 1, 5, .check_relay = true}, + {0x33DA, 1, 5, .check_relay = true}, {0x33DB, 1, 8, .check_relay = true}, {0x39F, 1, 8, .check_relay = false}, + {0x18DAB0F1, 1, 8, .check_relay = false}}; // Bosch w/ gas and brakes + + static CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 2, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; // Bosch radarless + + static CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x33D, 0, 8, .check_relay = true}, {0x1C8, 0, 8, .check_relay = true}, + {0x30C, 0, 8, .check_relay = true}}; // Bosch radarless w/ gas and brakes + + static CanMsg HONDA_CANFD_TX_MSGS[] = {{0xE4, 0, 5, .check_relay = true}, {0x296, 0, 4, .check_relay = false}, {0x33D, 0, 8, .check_relay = true}}; + + + const uint16_t HONDA_PARAM_ALT_BRAKE = 1; + const uint16_t HONDA_PARAM_RADARLESS = 8; + const uint16_t HONDA_PARAM_BOSCH_CANFD = 16; + + // Bosch radarless has the powertrain bus on bus 0 + static RxCheck honda_bosch_pt0_rx_checks[] = { + HONDA_COMMON_RX_CHECKS(0) + }; + + static RxCheck honda_bosch_pt0_alt_brake_rx_checks[] = { + HONDA_COMMON_RX_CHECKS(0) + HONDA_ALT_BRAKE_ADDR_CHECK(0) + }; + + // Bosch has powertrain on bus 1, verified 0x1A6 does not exist + static RxCheck honda_bosch_pt1_rx_checks[] = { + HONDA_COMMON_RX_CHECKS(1) + }; + + static RxCheck honda_bosch_pt1_alt_brake_rx_checks[] = { + HONDA_COMMON_RX_CHECKS(1) + HONDA_ALT_BRAKE_ADDR_CHECK(1) + }; + + honda_hw = HONDA_BOSCH; + honda_brake_switch_prev = false; + honda_bosch_radarless = GET_FLAG(param, HONDA_PARAM_RADARLESS); + honda_bosch_canfd = GET_FLAG(param, HONDA_PARAM_BOSCH_CANFD); + // Checking for alternate brake override from safety parameter + honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE); + + // radar disabled so allow gas/brakes +#ifdef ALLOW_DEBUG + const uint16_t HONDA_PARAM_BOSCH_LONG = 2; + honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG); +#endif + + safety_config ret; + if (honda_bosch_radarless || honda_bosch_canfd) { + if (honda_alt_brake_msg) { + SET_RX_CHECKS(honda_bosch_pt0_alt_brake_rx_checks, ret); + } else { + SET_RX_CHECKS(honda_bosch_pt0_rx_checks, ret); + } + } else { + if (honda_alt_brake_msg) { + SET_RX_CHECKS(honda_bosch_pt1_alt_brake_rx_checks, ret); + } else { + SET_RX_CHECKS(honda_bosch_pt1_rx_checks, ret); + } + } + + if (honda_bosch_radarless) { + if (honda_bosch_long) { + SET_TX_MSGS(HONDA_RADARLESS_LONG_TX_MSGS, ret); + } else { + SET_TX_MSGS(HONDA_RADARLESS_TX_MSGS, ret); + } + } else if (honda_bosch_canfd) { + SET_TX_MSGS(HONDA_CANFD_TX_MSGS, ret); + } else { + if (honda_bosch_long) { + SET_TX_MSGS(HONDA_BOSCH_LONG_TX_MSGS, ret); + } else { + SET_TX_MSGS(HONDA_BOSCH_TX_MSGS, ret); + } + } + return ret; +} + +static bool honda_nidec_fwd_hook(int bus_num, int addr) { + bool block_msg = false; + + if (bus_num == 2) { + // forwarded if stock AEB is active + bool is_brake_msg = addr == 0x1FA; + block_msg = is_brake_msg && !honda_fwd_brake; + } + + return block_msg; +} + +const safety_hooks honda_nidec_hooks = { + .init = honda_nidec_init, + .rx = honda_rx_hook, + .tx = honda_tx_hook, + .fwd = honda_nidec_fwd_hook, + .get_counter = honda_get_counter, + .get_checksum = honda_get_checksum, + .compute_checksum = honda_compute_checksum, +}; + +const safety_hooks honda_bosch_hooks = { + .init = honda_bosch_init, + .rx = honda_rx_hook, + .tx = honda_tx_hook, + .get_counter = honda_get_counter, + .get_checksum = honda_get_checksum, + .compute_checksum = honda_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/hyundai.h b/opendbc_repo/opendbc/safety/modes/hyundai.h new file mode 100644 index 0000000000..b867f1850a --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/hyundai.h @@ -0,0 +1,352 @@ +#pragma once + +#include "opendbc/safety/declarations.h" +#include "opendbc/safety/modes/hyundai_common.h" + +#define HYUNDAI_LIMITS(steer, rate_up, rate_down) { \ + .max_torque = (steer), \ + .max_rate_up = (rate_up), \ + .max_rate_down = (rate_down), \ + .max_rt_delta = 112, \ + .driver_torque_allowance = 50, \ + .driver_torque_multiplier = 2, \ + .type = TorqueDriverLimited, \ + /* the EPS faults when the steering angle is above a certain threshold for too long. to prevent this, */ \ + /* we allow setting CF_Lkas_ActToi bit to 0 while maintaining the requested torque value for two consecutive frames */ \ + .min_valid_request_frames = 89, \ + .max_invalid_request_frames = 2, \ + .min_valid_request_rt_interval = 810000, /* 810ms; a ~10% buffer on cutting every 90 frames */ \ + .has_steer_req_tolerance = true, \ +} + +extern const LongitudinalLimits HYUNDAI_LONG_LIMITS; +const LongitudinalLimits HYUNDAI_LONG_LIMITS = { + .max_accel = 200, // 1/100 m/s2 + .min_accel = -350, // 1/100 m/s2 +}; + +#define HYUNDAI_COMMON_TX_MSGS(scc_bus) \ + {0x340, 0, 8, .check_relay = true}, /* LKAS11 Bus 0 */ \ + {0x4F1, scc_bus, 4, .check_relay = false}, /* CLU11 Bus 0 (radar-SCC) or 2 (camera-SCC) */ \ + {0x485, 0, 4, .check_relay = true}, /* LFAHDA_MFC Bus 0 */ \ + +#define HYUNDAI_LONG_COMMON_TX_MSGS(scc_bus) \ + HYUNDAI_COMMON_TX_MSGS(scc_bus) \ + {0x420, 0, 8, .check_relay = true}, /* SCC11 Bus 0 */ \ + {0x421, 0, 8, .check_relay = true}, /* SCC12 Bus 0 */ \ + {0x50A, 0, 8, .check_relay = true}, /* SCC13 Bus 0 */ \ + {0x389, 0, 8, .check_relay = true}, /* SCC14 Bus 0 */ \ + {0x4A2, 0, 2, .check_relay = false}, /* FRT_RADAR11 Bus 0 */ \ + +#define HYUNDAI_COMMON_RX_CHECKS(legacy) \ + {.msg = {{0x260, 0, 8, 100U, .max_counter = 3U, .ignore_quality_flag = true}, \ + {0x371, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }}}, \ + {.msg = {{0x386, 0, 8, 100U, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x394, 0, 8, 100U, .ignore_checksum = (legacy), .ignore_counter = (legacy), .max_counter = (legacy) ? 0U : 7U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x251, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x4F1, 0, 4, 50U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +#define HYUNDAI_SCC12_ADDR_CHECK(scc_bus) \ + {.msg = {{0x421, (scc_bus), 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +#define HYUNDAI_FCEV_GAS_ADDR_CHECK \ + {.msg = {{0x91, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +static const CanMsg HYUNDAI_TX_MSGS[] = { + HYUNDAI_COMMON_TX_MSGS(0) +}; + +static bool hyundai_legacy = false; + +static uint8_t hyundai_get_counter(const CANPacket_t *msg) { + + uint8_t cnt = 0; + if (msg->addr == 0x260U) { + cnt = (msg->data[7] >> 4) & 0x3U; + } else if (msg->addr == 0x386U) { + cnt = ((msg->data[3] >> 6) << 2) | (msg->data[1] >> 6); + } else if (msg->addr == 0x394U) { + cnt = (msg->data[1] >> 5) & 0x7U; + } else if (msg->addr == 0x421U) { + cnt = msg->data[7] & 0xFU; + } else if (msg->addr == 0x4F1U) { + cnt = (msg->data[3] >> 4) & 0xFU; + } else { + } + return cnt; +} + +static uint32_t hyundai_get_checksum(const CANPacket_t *msg) { + + uint8_t chksum = 0; + if (msg->addr == 0x260U) { + chksum = msg->data[7] & 0xFU; + } else if (msg->addr == 0x386U) { + chksum = ((msg->data[7] >> 6) << 2) | (msg->data[5] >> 6); + } else if (msg->addr == 0x394U) { + chksum = msg->data[6] & 0xFU; + } else if (msg->addr == 0x421U) { + chksum = msg->data[7] >> 4; + } else { + } + return chksum; +} + +static uint32_t hyundai_compute_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + if (msg->addr == 0x386U) { + // count the bits + for (int i = 0; i < 8; i++) { + uint8_t b = msg->data[i]; + for (int j = 0; j < 8; j++) { + uint8_t bit = 0; + // exclude checksum and counter + if (((i != 1) || (j < 6)) && ((i != 3) || (j < 6)) && ((i != 5) || (j < 6)) && ((i != 7) || (j < 6))) { + bit = (b >> (uint8_t)j) & 1U; + } + chksum += bit; + } + } + chksum = (chksum ^ 9U) & 15U; + } else { + // sum of nibbles + for (int i = 0; i < 8; i++) { + if ((msg->addr == 0x394U) && (i == 7)) { + continue; // exclude + } + uint8_t b = msg->data[i]; + if (((msg->addr == 0x260U) && (i == 7)) || ((msg->addr == 0x394U) && (i == 6)) || ((msg->addr == 0x421U) && (i == 7))) { + b &= (msg->addr == 0x421U) ? 0x0FU : 0xF0U; // remove checksum + } + chksum += (b % 16U) + (b / 16U); + } + chksum = (16U - (chksum % 16U)) % 16U; + } + + return chksum; +} + +static void hyundai_rx_hook(const CANPacket_t *msg) { + + // SCC12 is on bus 2 for camera-based SCC cars, bus 0 on all others + if (msg->addr == 0x421U) { + if (((msg->bus == 0U) && !hyundai_camera_scc) || ((msg->bus == 2U) && hyundai_camera_scc)) { + // 2 bits: 13-14 + int cruise_engaged = (GET_BYTES(msg, 0, 4) >> 13) & 0x3U; + hyundai_common_cruise_state_check(cruise_engaged); + } + } + + if (msg->bus == 0U) { + if (msg->addr == 0x251U) { + int torque_driver_new = (GET_BYTES(msg, 0, 2) & 0x7ffU) - 1024U; + // update array of samples + update_sample(&torque_driver, torque_driver_new); + } + + // ACC steering wheel buttons + if (msg->addr == 0x4F1U) { + int cruise_button = msg->data[0] & 0x7U; + bool main_button = GET_BIT(msg, 3U); + hyundai_common_cruise_buttons_check(cruise_button, main_button); + } + + // gas press, different for EV, hybrid, and ICE models + if ((msg->addr == 0x371U) && hyundai_ev_gas_signal) { + gas_pressed = (((msg->data[4] & 0x7FU) << 1) | (msg->data[3] >> 7)) != 0U; + } else if ((msg->addr == 0x371U) && hyundai_hybrid_gas_signal) { + gas_pressed = msg->data[7] != 0U; + } else if ((msg->addr == 0x91U) && hyundai_fcev_gas_signal) { + gas_pressed = msg->data[6] != 0U; + } else if ((msg->addr == 0x260U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { + gas_pressed = (msg->data[7] >> 6) != 0U; + } else { + } + + // sample wheel speed, averaging opposite corners + if (msg->addr == 0x386U) { + uint32_t front_left_speed = GET_BYTES(msg, 0, 2) & 0x3FFFU; + uint32_t rear_right_speed = GET_BYTES(msg, 6, 2) & 0x3FFFU; + vehicle_moving = (front_left_speed > HYUNDAI_STANDSTILL_THRSLD) || (rear_right_speed > HYUNDAI_STANDSTILL_THRSLD); + } + + if (msg->addr == 0x394U) { + brake_pressed = ((msg->data[5] >> 5U) & 0x3U) == 0x2U; + } + } +} + +static bool hyundai_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS = HYUNDAI_LIMITS(384, 3, 7); + const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT = HYUNDAI_LIMITS(270, 2, 3); + const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT_2 = HYUNDAI_LIMITS(170, 2, 3); + + bool tx = true; + + // FCA11: Block any potential actuation + if (msg->addr == 0x38DU) { + int CR_VSM_DecCmd = msg->data[1]; + bool FCA_CmdAct = GET_BIT(msg, 20U); + bool CF_VSM_DecCmdAct = GET_BIT(msg, 31U); + + if ((CR_VSM_DecCmd != 0) || FCA_CmdAct || CF_VSM_DecCmdAct) { + tx = false; + } + } + + // ACCEL: safety check + if (msg->addr == 0x421U) { + int desired_accel_raw = (((msg->data[4] & 0x7U) << 8) | msg->data[3]) - 1023U; + int desired_accel_val = ((msg->data[5] << 3) | (msg->data[4] >> 5)) - 1023U; + + int aeb_decel_cmd = msg->data[2]; + bool aeb_req = GET_BIT(msg, 54U); + + bool violation = false; + + violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS); + violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS); + violation |= (aeb_decel_cmd != 0); + violation |= aeb_req; + + if (violation) { + tx = false; + } + } + + // LKA STEER: safety check + if (msg->addr == 0x340U) { + int desired_torque = ((GET_BYTES(msg, 0, 4) >> 16) & 0x7ffU) - 1024U; + bool steer_req = GET_BIT(msg, 27U); + + const TorqueSteeringLimits limits = hyundai_alt_limits_2 ? HYUNDAI_STEERING_LIMITS_ALT_2 : + hyundai_alt_limits ? HYUNDAI_STEERING_LIMITS_ALT : HYUNDAI_STEERING_LIMITS; + + if (steer_torque_cmd_checks(desired_torque, steer_req, limits)) { + tx = false; + } + } + + // UDS: Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address + if (msg->addr == 0x7D0U) { + if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + tx = false; + } + } + + // BUTTONS: used for resume spamming and cruise cancellation + if ((msg->addr == 0x4F1U) && !hyundai_longitudinal) { + int button = msg->data[0] & 0x7U; + + bool allowed_resume = (button == 1) && controls_allowed; + bool allowed_cancel = (button == 4) && cruise_engaged_prev; + if (!(allowed_resume || allowed_cancel)) { + tx = false; + } + } + + return tx; +} + +static safety_config hyundai_init(uint16_t param) { + static const CanMsg HYUNDAI_LONG_TX_MSGS[] = { + HYUNDAI_LONG_COMMON_TX_MSGS(0) + {0x38D, 0, 8, .check_relay = false}, // FCA11 Bus 0 + {0x483, 0, 8, .check_relay = false}, // FCA12 Bus 0 + {0x7D0, 0, 8, .check_relay = false}, // radar UDS TX addr Bus 0 (for radar disable) + }; + + static const CanMsg HYUNDAI_CAMERA_SCC_TX_MSGS[] = { + HYUNDAI_COMMON_TX_MSGS(2) + }; + + static const CanMsg HYUNDAI_CAMERA_SCC_LONG_TX_MSGS[] = { + HYUNDAI_LONG_COMMON_TX_MSGS(2) + }; + + hyundai_common_init(param); + hyundai_legacy = false; + + safety_config ret; + if (hyundai_longitudinal) { + // Use CLU11 (buttons) to manage controls allowed instead of SCC cruise state + static RxCheck hyundai_long_rx_checks[] = { + HYUNDAI_COMMON_RX_CHECKS(false) + }; + + static RxCheck hyundai_fcev_long_rx_checks[] = { + HYUNDAI_COMMON_RX_CHECKS(false) + HYUNDAI_FCEV_GAS_ADDR_CHECK + }; + + if (hyundai_fcev_gas_signal) { + SET_RX_CHECKS(hyundai_fcev_long_rx_checks, ret); + } else { + SET_RX_CHECKS(hyundai_long_rx_checks, ret); + } + if (hyundai_camera_scc) { + SET_TX_MSGS(HYUNDAI_CAMERA_SCC_LONG_TX_MSGS, ret); + } else { + SET_TX_MSGS(HYUNDAI_LONG_TX_MSGS, ret); + } + + } else if (hyundai_camera_scc) { + static RxCheck hyundai_cam_scc_rx_checks[] = { + HYUNDAI_COMMON_RX_CHECKS(false) + HYUNDAI_SCC12_ADDR_CHECK(2) + }; + + ret = BUILD_SAFETY_CFG(hyundai_cam_scc_rx_checks, HYUNDAI_CAMERA_SCC_TX_MSGS); + } else { + static RxCheck hyundai_rx_checks[] = { + HYUNDAI_COMMON_RX_CHECKS(false) + HYUNDAI_SCC12_ADDR_CHECK(0) + }; + + static RxCheck hyundai_fcev_rx_checks[] = { + HYUNDAI_COMMON_RX_CHECKS(false) + HYUNDAI_SCC12_ADDR_CHECK(0) + HYUNDAI_FCEV_GAS_ADDR_CHECK + }; + + SET_TX_MSGS(HYUNDAI_TX_MSGS, ret); + if (hyundai_fcev_gas_signal) { + SET_RX_CHECKS(hyundai_fcev_rx_checks, ret); + } else { + SET_RX_CHECKS(hyundai_rx_checks, ret); + } + } + return ret; +} + +static safety_config hyundai_legacy_init(uint16_t param) { + // older hyundai models have less checks due to missing counters and checksums + static RxCheck hyundai_legacy_rx_checks[] = { + HYUNDAI_COMMON_RX_CHECKS(true) + HYUNDAI_SCC12_ADDR_CHECK(0) + }; + + hyundai_common_init(param); + hyundai_legacy = true; + hyundai_longitudinal = false; + hyundai_camera_scc = false; + return BUILD_SAFETY_CFG(hyundai_legacy_rx_checks, HYUNDAI_TX_MSGS); +} + +const safety_hooks hyundai_hooks = { + .init = hyundai_init, + .rx = hyundai_rx_hook, + .tx = hyundai_tx_hook, + .get_counter = hyundai_get_counter, + .get_checksum = hyundai_get_checksum, + .compute_checksum = hyundai_compute_checksum, +}; + +const safety_hooks hyundai_legacy_hooks = { + .init = hyundai_legacy_init, + .rx = hyundai_rx_hook, + .tx = hyundai_tx_hook, + .get_counter = hyundai_get_counter, + .get_checksum = hyundai_get_checksum, + .compute_checksum = hyundai_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h new file mode 100644 index 0000000000..f25e267707 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h @@ -0,0 +1,382 @@ +#pragma once + +#include "opendbc/safety/declarations.h" +#include "opendbc/safety/modes/hyundai_common.h" + +#define HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(bus) \ + {0x1CF, bus, 8, .check_relay = false}, /* CRUISE_BUTTON */ \ + +#define HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(a_can, e_can) \ + HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \ + {0x50, a_can, 16, .check_relay = (a_can) == 0}, /* LKAS */ \ + {0x2A4, a_can, 24, .check_relay = (a_can) == 0}, /* CAM_0x2A4 */ \ + +#define HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(a_can, e_can) \ + HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \ + {0x110, a_can, 32, .check_relay = (a_can) == 0}, /* LKAS_ALT */ \ + {0x362, a_can, 32, .check_relay = (a_can) == 0}, /* CAM_0x362 */ \ + +#define HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(e_can) \ + {0x12A, e_can, 16, .check_relay = (e_can) == 0}, /* LFA */ \ + {0x1E0, e_can, 16, .check_relay = (e_can) == 0}, /* LFAHDA_CLUSTER */ \ + +#define HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(e_can, longitudinal) \ + {0x1A0, e_can, 32, .check_relay = (longitudinal)}, /* SCC_CONTROL */ \ + +// *** Addresses checked in rx hook *** +// EV, ICE, HYBRID: ACCELERATOR (0x35), ACCELERATOR_BRAKE_ALT (0x100), ACCELERATOR_ALT (0x105) +#define HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \ + {.msg = {{0x35, (pt_bus), 32, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, \ + {0x100, (pt_bus), 32, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, \ + {0x105, (pt_bus), 32, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}}}, \ + {.msg = {{0x175, (pt_bus), 24, 50U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0xa0, (pt_bus), 24, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0xea, (pt_bus), 24, 100U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +#define HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(pt_bus) \ + HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \ + {.msg = {{0x1cf, (pt_bus), 8, 50U, .ignore_checksum = true, .max_counter = 0xfU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +#define HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(pt_bus) \ + HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \ + {.msg = {{0x1aa, (pt_bus), 16, 50U, .ignore_checksum = true, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +// SCC_CONTROL (from ADAS unit or camera) +#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \ + {.msg = {{0x1a0, (scc_bus), 32, 50U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +static bool hyundai_canfd_alt_buttons = false; +static bool hyundai_canfd_lka_steering_alt = false; + +static unsigned int hyundai_canfd_get_lka_addr(void) { + return hyundai_canfd_lka_steering_alt ? 0x110U : 0x50U; +} + +static uint8_t hyundai_canfd_get_counter(const CANPacket_t *msg) { + uint8_t ret = 0; + if (GET_LEN(msg) == 8U) { + ret = msg->data[1] >> 4; + } else { + ret = msg->data[2]; + } + return ret; +} + +static uint32_t hyundai_canfd_get_checksum(const CANPacket_t *msg) { + uint32_t chksum = msg->data[0] | (msg->data[1] << 8); + return chksum; +} + +static void hyundai_canfd_rx_hook(const CANPacket_t *msg) { + + const unsigned pt_bus = hyundai_canfd_lka_steering ? 1U : 0U; + const unsigned int scc_bus = hyundai_camera_scc ? 2U : pt_bus; + + if (msg->bus == pt_bus) { + // driver torque + if (msg->addr == 0xeaU) { + int torque_driver_new = ((msg->data[11] & 0x1fU) << 8U) | msg->data[10]; + torque_driver_new -= 4095; + update_sample(&torque_driver, torque_driver_new); + } + + // cruise buttons + const unsigned int button_addr = hyundai_canfd_alt_buttons ? 0x1aaU : 0x1cfU; + if (msg->addr == button_addr) { + bool main_button = false; + int cruise_button = 0; + if (msg->addr == 0x1cfU) { + cruise_button = msg->data[2] & 0x7U; + main_button = GET_BIT(msg, 19U); + } else { + cruise_button = (msg->data[4] >> 4) & 0x7U; + main_button = GET_BIT(msg, 34U); + } + hyundai_common_cruise_buttons_check(cruise_button, main_button); + } + + // gas press, different for EV, hybrid, and ICE models + if ((msg->addr == 0x35U) && hyundai_ev_gas_signal) { + gas_pressed = msg->data[5] != 0U; + } else if ((msg->addr == 0x105U) && hyundai_hybrid_gas_signal) { + gas_pressed = GET_BIT(msg, 103U) || (msg->data[13] != 0U) || GET_BIT(msg, 112U); + } else if ((msg->addr == 0x100U) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { + gas_pressed = GET_BIT(msg, 176U); + } else { + } + + // brake press + if (msg->addr == 0x175U) { + brake_pressed = GET_BIT(msg, 81U); + } + + // vehicle moving + if (msg->addr == 0xa0U) { + uint32_t fl = (GET_BYTES(msg, 8, 2)) & 0x3FFFU; + uint32_t fr = (GET_BYTES(msg, 10, 2)) & 0x3FFFU; + uint32_t rl = (GET_BYTES(msg, 12, 2)) & 0x3FFFU; + uint32_t rr = (GET_BYTES(msg, 14, 2)) & 0x3FFFU; + vehicle_moving = (fl > HYUNDAI_STANDSTILL_THRSLD) || (fr > HYUNDAI_STANDSTILL_THRSLD) || + (rl > HYUNDAI_STANDSTILL_THRSLD) || (rr > HYUNDAI_STANDSTILL_THRSLD); + + // average of all 4 wheel speeds. Conversion: raw * 0.03125 / 3.6 = m/s + UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.03125 * KPH_TO_MS); + } + } + + if (msg->bus == scc_bus) { + // cruise state + if ((msg->addr == 0x1a0U) && !hyundai_longitudinal) { + // 1=enabled, 2=driver override + int cruise_status = ((msg->data[8] >> 4) & 0x7U); + bool cruise_engaged = (cruise_status == 1) || (cruise_status == 2); + hyundai_common_cruise_state_check(cruise_engaged); + } + } +} + +static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = { + .max_torque = 270, + .max_rt_delta = 112, + .max_rate_up = 2, + .max_rate_down = 3, + .driver_torque_allowance = 250, + .driver_torque_multiplier = 2, + .type = TorqueDriverLimited, + + // the EPS faults when the steering angle is above a certain threshold for too long. to prevent this, + // we allow setting torque actuation bit to 0 while maintaining the requested torque value for two consecutive frames + .min_valid_request_frames = 89, + .max_invalid_request_frames = 2, + .min_valid_request_rt_interval = 810000, // 810ms; a ~10% buffer on cutting every 90 frames + .has_steer_req_tolerance = true, + }; + + bool tx = true; + + // steering + const unsigned int steer_addr = (hyundai_canfd_lka_steering && !hyundai_longitudinal) ? hyundai_canfd_get_lka_addr() : 0x12aU; + if (msg->addr == steer_addr) { + int desired_torque = (((msg->data[6] & 0xFU) << 7U) | (msg->data[5] >> 1U)) - 1024U; + bool steer_req = GET_BIT(msg, 52U); + + if (steer_torque_cmd_checks(desired_torque, steer_req, HYUNDAI_CANFD_STEERING_LIMITS)) { + tx = false; + } + } + + // cruise buttons check + if (msg->addr == 0x1cfU) { + int button = msg->data[2] & 0x7U; + bool is_cancel = (button == HYUNDAI_BTN_CANCEL); + bool is_resume = (button == HYUNDAI_BTN_RESUME); + + bool allowed = (is_cancel && cruise_engaged_prev) || (is_resume && controls_allowed); + if (!allowed) { + tx = false; + } + } + + // UDS: only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address + if (((msg->addr == 0x730U) && hyundai_canfd_lka_steering) || ((msg->addr == 0x7D0U) && !hyundai_camera_scc)) { + if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) { + tx = false; + } + } + + // ACCEL: safety check + if (msg->addr == 0x1a0U) { + int desired_accel_raw = (((msg->data[17] & 0x7U) << 8) | msg->data[16]) - 1023U; + int desired_accel_val = ((msg->data[18] << 4) | (msg->data[17] >> 4)) - 1023U; + + bool violation = false; + + if (hyundai_longitudinal) { + violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS); + violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS); + } else { + // only used to cancel on here + const int acc_mode = (msg->data[8] >> 4) & 0x7U; + if (acc_mode != 4) { + violation = true; + } + + if ((desired_accel_raw != 0) || (desired_accel_val != 0)) { + violation = true; + } + } + + if (violation) { + tx = false; + } + } + + return tx; +} + +static safety_config hyundai_canfd_init(uint16_t param) { + const int HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT = 128; + const int HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32; + + static const CanMsg HYUNDAI_CANFD_LKA_STEERING_TX_MSGS[] = { + HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1) + }; + + static const CanMsg HYUNDAI_CANFD_LKA_STEERING_ALT_TX_MSGS[] = { + HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(0, 1) + }; + + static const CanMsg HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS[] = { + HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1) + HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(1) + HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(1, true) + {0x51, 0, 32, .check_relay = false}, // ADRV_0x51 + {0x730, 1, 8, .check_relay = false}, // tester present for ADAS ECU disable + {0x160, 1, 16, .check_relay = false}, // ADRV_0x160 + {0x1EA, 1, 32, .check_relay = false}, // ADRV_0x1ea + {0x200, 1, 8, .check_relay = false}, // ADRV_0x200 + {0x345, 1, 8, .check_relay = false}, // ADRV_0x345 + {0x1DA, 1, 32, .check_relay = false}, // ADRV_0x1da + }; + + static const CanMsg HYUNDAI_CANFD_LFA_STEERING_TX_MSGS[] = { + HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) + HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) + HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, false) + }; + + // ADRV_0x160 is checked for radar liveness + static const CanMsg HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS[] = { + HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) + HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) + HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, true) + {0x160, 0, 16, .check_relay = true}, // ADRV_0x160 + {0x7D0, 0, 8, .check_relay = false}, // tester present for radar ECU disable + }; + + // ADRV_0x160 is checked for relay malfunction +#define HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(longitudinal) \ + HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) \ + HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) \ + HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \ + {0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \ + + hyundai_common_init(param); + + gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut); + hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS); + hyundai_canfd_lka_steering_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT); + + safety_config ret; + if (hyundai_longitudinal) { + if (hyundai_canfd_lka_steering) { + static RxCheck hyundai_canfd_lka_steering_long_rx_checks[] = { + HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(1) + }; + + ret = BUILD_SAFETY_CFG(hyundai_canfd_lka_steering_long_rx_checks, HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS); + + } else { + // Longitudinal checks for LFA steering + static RxCheck hyundai_canfd_long_rx_checks[] = { + HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(0) + }; + + static RxCheck hyundai_canfd_alt_buttons_long_rx_checks[] = { + HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(0) + }; + + static CanMsg hyundai_canfd_lfa_steering_camera_scc_tx_msgs[] = { + HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(true) + }; + + if (hyundai_canfd_alt_buttons) { + SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret); + } else { + SET_RX_CHECKS(hyundai_canfd_long_rx_checks, ret); + } + + if (hyundai_camera_scc) { + SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret); + } else { + SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret); + } + } + + } else { + if (hyundai_canfd_lka_steering) { + // *** LKA steering checks *** + // E-CAN is on bus 1, SCC messages are sent on cars with ADRV ECU. + // Does not use the alt buttons message + static RxCheck hyundai_canfd_lka_steering_rx_checks[] = { + HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(1) + HYUNDAI_CANFD_SCC_ADDR_CHECK(1) + }; + + SET_RX_CHECKS(hyundai_canfd_lka_steering_rx_checks, ret); + if (hyundai_canfd_lka_steering_alt) { + SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_ALT_TX_MSGS, ret); + } else { + SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_TX_MSGS, ret); + } + + } else if (!hyundai_camera_scc) { + // Radar sends SCC messages on these cars instead of camera + static RxCheck hyundai_canfd_radar_scc_rx_checks[] = { + HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(0) + HYUNDAI_CANFD_SCC_ADDR_CHECK(0) + }; + + static RxCheck hyundai_canfd_alt_buttons_radar_scc_rx_checks[] = { + HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(0) + HYUNDAI_CANFD_SCC_ADDR_CHECK(0) + }; + + SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_TX_MSGS, ret); + + if (hyundai_canfd_alt_buttons) { + SET_RX_CHECKS(hyundai_canfd_alt_buttons_radar_scc_rx_checks, ret); + } else { + SET_RX_CHECKS(hyundai_canfd_radar_scc_rx_checks, ret); + } + + } else { + // *** LFA steering checks *** + // Camera sends SCC messages on LFA steering cars. + // Both button messages exist on some platforms, so we ensure we track the correct one using flag + static RxCheck hyundai_canfd_rx_checks[] = { + HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(0) + HYUNDAI_CANFD_SCC_ADDR_CHECK(2) + }; + + static RxCheck hyundai_canfd_alt_buttons_rx_checks[] = { + HYUNDAI_CANFD_ALT_BUTTONS_RX_CHECKS(0) + HYUNDAI_CANFD_SCC_ADDR_CHECK(2) + }; + + static CanMsg hyundai_canfd_lfa_steering_camera_scc_tx_msgs[] = { + HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false) + }; + + SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret); + + if (hyundai_canfd_alt_buttons) { + SET_RX_CHECKS(hyundai_canfd_alt_buttons_rx_checks, ret); + } else { + SET_RX_CHECKS(hyundai_canfd_rx_checks, ret); + } + } + } + + return ret; +} + +const safety_hooks hyundai_canfd_hooks = { + .init = hyundai_canfd_init, + .rx = hyundai_canfd_rx_hook, + .tx = hyundai_canfd_tx_hook, + .get_counter = hyundai_canfd_get_counter, + .get_checksum = hyundai_canfd_get_checksum, + .compute_checksum = hyundai_common_canfd_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_common.h b/opendbc_repo/opendbc/safety/modes/hyundai_common.h new file mode 100644 index 0000000000..bb2b951caf --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/hyundai_common.h @@ -0,0 +1,138 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +extern uint16_t hyundai_canfd_crc_lut[256]; +uint16_t hyundai_canfd_crc_lut[256]; + +static const uint8_t HYUNDAI_PREV_BUTTON_SAMPLES = 8; // roughly 160 ms + +extern const uint32_t HYUNDAI_STANDSTILL_THRSLD; +const uint32_t HYUNDAI_STANDSTILL_THRSLD = 12; // 0.375 kph + +enum { + HYUNDAI_BTN_NONE = 0, + HYUNDAI_BTN_RESUME = 1, + HYUNDAI_BTN_SET = 2, + HYUNDAI_BTN_CANCEL = 4, +}; + +// common state +extern bool hyundai_ev_gas_signal; +bool hyundai_ev_gas_signal = false; + +extern bool hyundai_hybrid_gas_signal; +bool hyundai_hybrid_gas_signal = false; + +extern bool hyundai_longitudinal; +bool hyundai_longitudinal = false; + +extern bool hyundai_camera_scc; +bool hyundai_camera_scc = false; + +extern bool hyundai_canfd_lka_steering; +bool hyundai_canfd_lka_steering = false; + +extern bool hyundai_alt_limits; +bool hyundai_alt_limits = false; + +extern bool hyundai_fcev_gas_signal; +bool hyundai_fcev_gas_signal = false; + +extern bool hyundai_alt_limits_2; +bool hyundai_alt_limits_2 = false; + +static uint8_t hyundai_last_button_interaction; // button messages since the user pressed an enable button + +void hyundai_common_init(uint16_t param) { + const int HYUNDAI_PARAM_EV_GAS = 1; + const int HYUNDAI_PARAM_HYBRID_GAS = 2; + const int HYUNDAI_PARAM_CAMERA_SCC = 8; + const int HYUNDAI_PARAM_CANFD_LKA_STEERING = 16; + const int HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags + const int HYUNDAI_PARAM_FCEV_GAS = 256; + const int HYUNDAI_PARAM_ALT_LIMITS_2 = 512; + + hyundai_ev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_EV_GAS); + hyundai_hybrid_gas_signal = !hyundai_ev_gas_signal && GET_FLAG(param, HYUNDAI_PARAM_HYBRID_GAS); + hyundai_camera_scc = GET_FLAG(param, HYUNDAI_PARAM_CAMERA_SCC); + hyundai_canfd_lka_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING); + hyundai_alt_limits = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS); + hyundai_fcev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_FCEV_GAS); + hyundai_alt_limits_2 = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS_2); + + hyundai_last_button_interaction = HYUNDAI_PREV_BUTTON_SAMPLES; + +#ifdef ALLOW_DEBUG + const int HYUNDAI_PARAM_LONGITUDINAL = 4; + hyundai_longitudinal = GET_FLAG(param, HYUNDAI_PARAM_LONGITUDINAL); +#else + hyundai_longitudinal = false; +#endif +} + +void hyundai_common_cruise_state_check(const bool cruise_engaged) { + // some newer HKG models can re-enable after spamming cancel button, + // so keep track of user button presses to deny engagement if no interaction + + // enter controls on rising edge of ACC and recent user button press, exit controls when ACC off + if (!hyundai_longitudinal) { + if (cruise_engaged && !cruise_engaged_prev && (hyundai_last_button_interaction < HYUNDAI_PREV_BUTTON_SAMPLES)) { + controls_allowed = true; + } + + if (!cruise_engaged) { + controls_allowed = false; + } + cruise_engaged_prev = cruise_engaged; + } +} + +void hyundai_common_cruise_buttons_check(const int cruise_button, const bool main_button) { + if ((cruise_button == HYUNDAI_BTN_RESUME) || (cruise_button == HYUNDAI_BTN_SET) || (cruise_button == HYUNDAI_BTN_CANCEL) || main_button) { + hyundai_last_button_interaction = 0U; + } else { + hyundai_last_button_interaction = SAFETY_MIN(hyundai_last_button_interaction + 1U, HYUNDAI_PREV_BUTTON_SAMPLES); + } + + if (hyundai_longitudinal) { + // enter controls on falling edge of resume or set + bool set = (cruise_button != HYUNDAI_BTN_SET) && (cruise_button_prev == HYUNDAI_BTN_SET); + bool res = (cruise_button != HYUNDAI_BTN_RESUME) && (cruise_button_prev == HYUNDAI_BTN_RESUME); + if (set || res) { + controls_allowed = true; + } + + // exit controls on cancel press + if (cruise_button == HYUNDAI_BTN_CANCEL) { + controls_allowed = false; + } + + cruise_button_prev = cruise_button; + } +} + +uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *msg) { + int len = GET_LEN(msg); + uint32_t address = msg->addr; + + uint16_t crc = 0; + + for (int i = 2; i < len; i++) { + crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ msg->data[i]]; + } + + // Add address to crc + crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ ((address >> 0U) & 0xFFU)]; + crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ ((address >> 8U) & 0xFFU)]; + + if (len == 24) { + crc ^= 0x819dU; + } else if (len == 32) { + crc ^= 0x9f5bU; + } else { + + } + + return crc; +} diff --git a/opendbc_repo/opendbc/safety/modes/mazda.h b/opendbc_repo/opendbc/safety/modes/mazda.h new file mode 100644 index 0000000000..f95cfaf878 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/mazda.h @@ -0,0 +1,105 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// CAN msgs we care about +#define MAZDA_LKAS 0x243U +#define MAZDA_LKAS_HUD 0x440U +#define MAZDA_CRZ_CTRL 0x21cU +#define MAZDA_CRZ_BTNS 0x09dU +#define MAZDA_STEER_TORQUE 0x240U +#define MAZDA_ENGINE_DATA 0x202U +#define MAZDA_PEDALS 0x165U + +// CAN bus numbers +#define MAZDA_MAIN 0 +#define MAZDA_CAM 2 + +// track msgs coming from OP so that we know what CAM msgs to drop and what to forward +static void mazda_rx_hook(const CANPacket_t *msg) { + if ((int)msg->bus == MAZDA_MAIN) { + if (msg->addr == MAZDA_ENGINE_DATA) { + // sample speed: scale by 0.01 to get kph + int speed = (msg->data[2] << 8) | msg->data[3]; + vehicle_moving = speed > 10; // moving when speed > 0.1 kph + } + + if (msg->addr == MAZDA_STEER_TORQUE) { + int torque_driver_new = msg->data[0] - 127U; + // update array of samples + update_sample(&torque_driver, torque_driver_new); + } + + // enter controls on rising edge of ACC, exit controls on ACC off + if (msg->addr == MAZDA_CRZ_CTRL) { + bool cruise_engaged = msg->data[0] & 0x8U; + pcm_cruise_check(cruise_engaged); + } + + if (msg->addr == MAZDA_ENGINE_DATA) { + gas_pressed = (msg->data[4] || (msg->data[5] & 0xF0U)); + } + + if (msg->addr == MAZDA_PEDALS) { + brake_pressed = (msg->data[0] & 0x10U); + } + } +} + +static bool mazda_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits MAZDA_STEERING_LIMITS = { + .max_torque = 800, + .max_rate_up = 10, + .max_rate_down = 25, + .max_rt_delta = 300, + .driver_torque_multiplier = 1, + .driver_torque_allowance = 15, + .type = TorqueDriverLimited, + }; + + bool tx = true; + // Check if msg is sent on the main BUS + if (msg->bus == (unsigned char)MAZDA_MAIN) { + // steer cmd checks + if (msg->addr == MAZDA_LKAS) { + int desired_torque = (((msg->data[0] & 0x0FU) << 8) | msg->data[1]) - 2048U; + + if (steer_torque_cmd_checks(desired_torque, -1, MAZDA_STEERING_LIMITS)) { + tx = false; + } + } + + // cruise buttons check + if (msg->addr == MAZDA_CRZ_BTNS) { + // allow resume spamming while controls allowed, but + // only allow cancel while controls not allowed + bool cancel_cmd = (msg->data[0] == 0x1U); + if (!controls_allowed && !cancel_cmd) { + tx = false; + } + } + } + + return tx; +} + +static safety_config mazda_init(uint16_t param) { + static const CanMsg MAZDA_TX_MSGS[] = {{MAZDA_LKAS, 0, 8, .check_relay = true}, {MAZDA_CRZ_BTNS, 0, 8, .check_relay = false}, {MAZDA_LKAS_HUD, 0, 8, .check_relay = true}}; + + static RxCheck mazda_rx_checks[] = { + {.msg = {{MAZDA_CRZ_CTRL, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MAZDA_CRZ_BTNS, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MAZDA_STEER_TORQUE, 0, 8, 83U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MAZDA_ENGINE_DATA, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MAZDA_PEDALS, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + SAFETY_UNUSED(param); + return BUILD_SAFETY_CFG(mazda_rx_checks, MAZDA_TX_MSGS); +} + +const safety_hooks mazda_hooks = { + .init = mazda_init, + .rx = mazda_rx_hook, + .tx = mazda_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/nissan.h b/opendbc_repo/opendbc/safety/modes/nissan.h new file mode 100644 index 0000000000..999d1090b5 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/nissan.h @@ -0,0 +1,137 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +static bool nissan_alt_eps = false; + +static void nissan_rx_hook(const CANPacket_t *msg) { + + if (msg->bus == (nissan_alt_eps ? 1U : 0U)) { + if (msg->addr == 0x2U) { + // Current steering angle + // Factor -0.1, little endian + int angle_meas_new = (GET_BYTES(msg, 0, 4) & 0xFFFFU); + // Multiply by -10 to match scale of LKAS angle + angle_meas_new = to_signed(angle_meas_new, 16) * -10; + + // update array of samples + update_sample(&angle_meas, angle_meas_new); + } + + if (msg->addr == 0x285U) { + // Get current speed and standstill + uint16_t right_rear = (msg->data[0] << 8) | (msg->data[1]); + uint16_t left_rear = (msg->data[2] << 8) | (msg->data[3]); + vehicle_moving = (right_rear | left_rear) != 0U; + UPDATE_VEHICLE_SPEED((right_rear + left_rear) / 2.0 * 0.005 * KPH_TO_MS); + } + + // X-Trail 0x15c, Leaf 0x239 + if ((msg->addr == 0x15cU) || (msg->addr == 0x239U)) { + if (msg->addr == 0x15cU){ + gas_pressed = ((msg->data[5] << 2) | ((msg->data[6] >> 6) & 0x3U)) > 3U; + } else { + gas_pressed = msg->data[0] > 3U; + } + } + + // X-trail 0x454, Leaf 0x239 + if ((msg->addr == 0x454U) || (msg->addr == 0x239U)) { + if (msg->addr == 0x454U){ + brake_pressed = (msg->data[2] & 0x80U) != 0U; + } else { + brake_pressed = ((msg->data[4] >> 5) & 1U) != 0U; + } + } + } + + // Handle cruise enabled + if ((msg->addr == 0x30fU) && (msg->bus == (nissan_alt_eps ? 1U : 2U))) { + bool cruise_engaged = (msg->data[0] >> 3) & 1U; + pcm_cruise_check(cruise_engaged); + } +} + + +static bool nissan_tx_hook(const CANPacket_t *msg) { + const AngleSteeringLimits NISSAN_STEERING_LIMITS = { + .max_angle = 60000, // 600 deg, reasonable limit + .angle_deg_to_can = 100, + .angle_rate_up_lookup = { + {0., 5., 15.}, + {5., .8, .15} + }, + .angle_rate_down_lookup = { + {0., 5., 15.}, + {5., 3.5, .4} + }, + }; + + bool tx = true; + bool violation = false; + + // steer cmd checks + if (msg->addr == 0x169U) { + int desired_angle = ((msg->data[0] << 10) | (msg->data[1] << 2) | ((msg->data[2] >> 6) & 0x3U)); + bool lka_active = (msg->data[6] >> 4) & 1U; + + // Factor is -0.01, offset is 1310. Flip to correct sign, but keep units in CAN scale + desired_angle = -desired_angle + (1310.0f * NISSAN_STEERING_LIMITS.angle_deg_to_can); + + if (steer_angle_cmd_checks(desired_angle, lka_active, NISSAN_STEERING_LIMITS)) { + violation = true; + } + } + + // acc button check, only allow cancel button to be sent + if (msg->addr == 0x20bU) { + // Violation of any button other than cancel is pressed + violation |= ((msg->data[1] & 0x3dU) > 0U); + } + + if (violation) { + tx = false; + } + + return tx; +} + + +static safety_config nissan_init(uint16_t param) { + static const CanMsg NISSAN_TX_MSGS[] = { + {0x169, 0, 8, .check_relay = true}, // LKAS + {0x2b1, 0, 8, .check_relay = true}, // PROPILOT_HUD + {0x4cc, 0, 8, .check_relay = true}, // PROPILOT_HUD_INFO_MSG + {0x20b, 2, 6, .check_relay = false}, // CRUISE_THROTTLE (X-Trail) + {0x20b, 1, 6, .check_relay = false}, // CRUISE_THROTTLE (Altima) + {0x280, 2, 8, .check_relay = true} // CANCEL_MSG (Leaf) + }; + + // Signals duplicated below due to the fact that these messages can come in on either CAN bus, depending on car model. + static RxCheck nissan_rx_checks[] = { + {.msg = {{0x2, 0, 5, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x2, 1, 5, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }}}, // STEER_ANGLE_SENSOR + {.msg = {{0x285, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x285, 1, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }}}, // WHEEL_SPEEDS_REAR + {.msg = {{0x30f, 2, 3, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x30f, 1, 3, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }}}, // CRUISE_STATE + {.msg = {{0x15c, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x15c, 1, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x239, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}}}, // GAS_PEDAL + {.msg = {{0x454, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x454, 1, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, + {0x1cc, 0, 4, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}}}, // DOORS_LIGHTS / BRAKE + }; + + // EPS Location. false = V-CAN, true = C-CAN + const int NISSAN_PARAM_ALT_EPS_BUS = 1; + + nissan_alt_eps = GET_FLAG(param, NISSAN_PARAM_ALT_EPS_BUS); + return BUILD_SAFETY_CFG(nissan_rx_checks, NISSAN_TX_MSGS); +} + +const safety_hooks nissan_hooks = { + .init = nissan_init, + .rx = nissan_rx_hook, + .tx = nissan_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/psa.h b/opendbc_repo/opendbc/safety/modes/psa.h new file mode 100644 index 0000000000..6bbd7b9c96 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/psa.h @@ -0,0 +1,151 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +#define PSA_STEERING 757U // RX from XXX, driver torque +#define PSA_STEERING_ALT 773U // RX from EPS, steering angle +#define PSA_DYN_CMM 520U // RX from CMM, gas pedal +#define PSA_HS2_DYN_ABR_38D 909U // RX from UC_FREIN, speed +#define PSA_HS2_DAT_MDD_CMD_452 1106U // RX from BSI, cruise state +#define PSA_DAT_BSI 1042U // RX from BSI, brake +#define PSA_LANE_KEEP_ASSIST 1010U // TX from OP, EPS + +// CAN bus +#define PSA_MAIN_BUS 0U +#define PSA_ADAS_BUS 1U +#define PSA_CAM_BUS 2U + +static uint8_t psa_get_counter(const CANPacket_t *msg) { + uint8_t cnt = 0; + if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { + cnt = (msg->data[3] >> 4) & 0xFU; + } else if (msg->addr == PSA_HS2_DYN_ABR_38D) { + cnt = (msg->data[5] >> 4) & 0xFU; + } else { + } + return cnt; +} + +static uint32_t psa_get_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { + chksum = msg->data[5] & 0xFU; + } else if (msg->addr == PSA_HS2_DYN_ABR_38D) { + chksum = msg->data[5] & 0xFU; + } else { + } + return chksum; +} + +static uint8_t _psa_compute_checksum(const CANPacket_t *msg, uint8_t chk_ini, int chk_pos) { + int len = GET_LEN(msg); + + uint8_t sum = 0; + for (int i = 0; i < len; i++) { + uint8_t b = msg->data[i]; + + if (i == chk_pos) { + // set checksum in low nibble to 0 + b &= 0xF0U; + } + sum += (b >> 4) + (b & 0xFU); + } + return (chk_ini - sum) & 0xFU; +} + +static uint32_t psa_compute_checksum(const CANPacket_t *msg) { + uint8_t chk = 0; + if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { + chk = _psa_compute_checksum(msg, 0x4, 5); + } else if (msg->addr == PSA_HS2_DYN_ABR_38D) { + chk = _psa_compute_checksum(msg, 0x7, 5); + } else { + } + return chk; +} + +static void psa_rx_hook(const CANPacket_t *msg) { + if (msg->bus == PSA_MAIN_BUS) { + if (msg->addr == PSA_DYN_CMM) { + gas_pressed = msg->data[3] > 0U; // P002_Com_rAPP + } + if (msg->addr == PSA_STEERING_ALT) { + int angle_meas_new = to_signed((msg->data[0] << 8) | msg->data[1], 16); // ANGLE + update_sample(&angle_meas, angle_meas_new); + } + if (msg->addr == PSA_HS2_DYN_ABR_38D) { + int speed = (msg->data[0] << 8) | msg->data[1]; + vehicle_moving = speed > 0; + UPDATE_VEHICLE_SPEED(speed * 0.01 * KPH_TO_MS); // VITESSE_VEHICULE_ROUES + } + } + + if (msg->bus == PSA_ADAS_BUS) { + if (msg->addr == PSA_HS2_DAT_MDD_CMD_452) { + pcm_cruise_check((msg->data[2U] >> 7U) & 1U); // RVV_ACC_ACTIVATION_REQ + } + } + + + if (msg->bus == PSA_CAM_BUS) { + if (msg->addr == PSA_DAT_BSI) { + brake_pressed = (msg->data[0U] >> 5U) & 1U; // P013_MainBrake + } + } +} + +static bool psa_tx_hook(const CANPacket_t *msg) { + bool tx = true; + static const AngleSteeringLimits PSA_STEERING_LIMITS = { + .max_angle = 3900, + .angle_deg_to_can = 10, + .angle_rate_up_lookup = { + {0., 5., 25.}, + {2.5, 1.5, .2}, + }, + .angle_rate_down_lookup = { + {0., 5., 25.}, + {5., 2., .3}, + }, + }; + + // Safety check for LKA + if (msg->addr == PSA_LANE_KEEP_ASSIST) { + // SET_ANGLE + int desired_angle = to_signed((msg->data[6] << 6) | ((msg->data[7] & 0xFCU) >> 2), 14); + // TORQUE_FACTOR + bool lka_active = ((msg->data[5] & 0xFEU) >> 1) == 100U; + + if (steer_angle_cmd_checks(desired_angle, lka_active, PSA_STEERING_LIMITS)) { + tx = false; + } + } + return tx; +} + +static safety_config psa_init(uint16_t param) { + SAFETY_UNUSED(param); + static const CanMsg PSA_TX_MSGS[] = { + {PSA_LANE_KEEP_ASSIST, PSA_MAIN_BUS, 8, .check_relay = true}, // EPS steering + }; + + static RxCheck psa_rx_checks[] = { + {.msg = {{PSA_HS2_DAT_MDD_CMD_452, PSA_ADAS_BUS, 6, 20U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // cruise state + {.msg = {{PSA_HS2_DYN_ABR_38D, PSA_MAIN_BUS, 8, 25U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // speed + {.msg = {{PSA_STEERING_ALT, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // steering angle + {.msg = {{PSA_STEERING, PSA_MAIN_BUS, 7, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // driver torque + {.msg = {{PSA_DYN_CMM, PSA_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // gas pedal + {.msg = {{PSA_DAT_BSI, PSA_CAM_BUS, 8, 20U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // brake + }; + + return BUILD_SAFETY_CFG(psa_rx_checks, PSA_TX_MSGS); +} + +const safety_hooks psa_hooks = { + .init = psa_init, + .rx = psa_rx_hook, + .tx = psa_tx_hook, + .get_counter = psa_get_counter, + .get_checksum = psa_get_checksum, + .compute_checksum = psa_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/rivian.h b/opendbc_repo/opendbc/safety/modes/rivian.h new file mode 100644 index 0000000000..35645b7c56 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/rivian.h @@ -0,0 +1,191 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +static uint8_t rivian_get_counter(const CANPacket_t *msg) { + uint8_t cnt = 0; + if ((msg->addr == 0x208U) || (msg->addr == 0x150U)) { + // Signal: ESP_Status_Counter, VDM_PropStatus_Counter + cnt = msg->data[1] & 0xFU; + } + return cnt; +} + +static uint32_t rivian_get_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + if ((msg->addr == 0x208U) || (msg->addr == 0x150U)) { + // Signal: ESP_Status_Checksum, VDM_PropStatus_Checksum + chksum = msg->data[0]; + } else { + } + return chksum; +} + +static uint8_t _rivian_compute_checksum(const CANPacket_t *msg, uint8_t poly, uint8_t xor_output) { + int len = GET_LEN(msg); + + uint8_t crc = 0; + // Skip the checksum byte + for (int i = 1; i < len; i++) { + crc ^= msg->data[i]; + for (int j = 0; j < 8; j++) { + if ((crc & 0x80U) != 0U) { + crc = (crc << 1) ^ poly; + } else { + crc <<= 1; + } + } + } + return crc ^ xor_output; +} + +static uint32_t rivian_compute_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + if (msg->addr == 0x208U) { + chksum = _rivian_compute_checksum(msg, 0x1D, 0xB1); + } else if (msg->addr == 0x150U) { + chksum = _rivian_compute_checksum(msg, 0x1D, 0x9A); + } else { + } + return chksum; +} + +static bool rivian_get_quality_flag_valid(const CANPacket_t *msg) { + bool valid = false; + if (msg->addr == 0x208U) { + valid = ((msg->data[3] >> 3) & 0x3U) == 0x1U; // ESP_Vehicle_Speed_Q + } else if (msg->addr == 0x150U) { + valid = (msg->data[1] >> 6) == 0x1U; // VDM_VehicleSpeedQ + } else { + } + return valid; +} + +static void rivian_rx_hook(const CANPacket_t *msg) { + + if (msg->bus == 0U) { + // Vehicle speed + if (msg->addr == 0x208U) { + float speed = ((msg->data[6] << 8) | msg->data[7]) * 0.01; + vehicle_moving = speed > 0.0; + UPDATE_VEHICLE_SPEED(speed * KPH_TO_MS); + } + + // Gas pressed and second speed source for variable torque limit + if (msg->addr == 0x150U) { + gas_pressed = msg->data[3] | (msg->data[4] & 0xC0U); + + // Disable controls if speeds from VDM and ESP ECUs are too far apart. + float vdm_speed = ((msg->data[5] << 8) | msg->data[6]) * 0.01 * KPH_TO_MS; + speed_mismatch_check(vdm_speed); + } + + // Driver torque + if (msg->addr == 0x380U) { + int torque_driver_new = (((msg->data[2] << 4) | (msg->data[3] >> 4))) - 2050U; + update_sample(&torque_driver, torque_driver_new); + } + + // Brake pressed + if (msg->addr == 0x38fU) { + brake_pressed = (msg->data[2] >> 7) & 1U; + } + } + + if (msg->bus == 2U) { + // Cruise state + if (msg->addr == 0x100U) { + const int feature_status = msg->data[2] >> 5U; + pcm_cruise_check(feature_status == 1); + } + } +} + +static bool rivian_tx_hook(const CANPacket_t *msg) { + // Rivian utilizes more torque at low speed to maintain the same lateral accel + const TorqueSteeringLimits RIVIAN_STEERING_LIMITS = { + .max_torque = 350, + .dynamic_max_torque = true, + .max_torque_lookup = { + {9., 17., 17.}, + {350, 250, 250}, + }, + .max_rate_up = 3, + .max_rate_down = 5, + .max_rt_delta = 125, + .driver_torque_multiplier = 2, + .driver_torque_allowance = 100, + .type = TorqueDriverLimited, + }; + + const LongitudinalLimits RIVIAN_LONG_LIMITS = { + .max_accel = 200, + .min_accel = -350, + .inactive_accel = 0, + }; + + bool tx = true; + + if (msg->bus == 0U) { + // Steering control + if (msg->addr == 0x120U) { + int desired_torque = ((msg->data[2] << 3U) | (msg->data[3] >> 5U)) - 1024U; + bool steer_req = (msg->data[3] >> 4) & 1U; + + if (steer_torque_cmd_checks(desired_torque, steer_req, RIVIAN_STEERING_LIMITS)) { + tx = false; + } + } + + // Longitudinal control + if (msg->addr == 0x160U) { + int raw_accel = ((msg->data[2] << 3) | (msg->data[3] >> 5)) - 1024U; + if (longitudinal_accel_checks(raw_accel, RIVIAN_LONG_LIMITS)) { + tx = false; + } + } + } + + return tx; +} + +static safety_config rivian_init(uint16_t param) { + // SCCM_WheelTouch: for hiding hold wheel alert + // VDM_AdasSts: for canceling stock ACC + // 0x120 = ACM_lkaHbaCmd, 0x321 = SCCM_WheelTouch, 0x162 = VDM_AdasSts + static const CanMsg RIVIAN_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x162, 2, 8, .check_relay = true}}; + // 0x160 = ACM_longitudinalRequest + static const CanMsg RIVIAN_LONG_TX_MSGS[] = {{0x120, 0, 8, .check_relay = true}, {0x321, 2, 7, .check_relay = true}, {0x160, 0, 5, .check_relay = true}}; + + static RxCheck rivian_rx_checks[] = { + {.msg = {{0x208, 0, 8, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // ESP_Status (speed) + {.msg = {{0x150, 0, 7, 50U, .max_counter = 14U}, { 0 }, { 0 }}}, // VDM_PropStatus (gas pedal & 2nd speed) + {.msg = {{0x380, 0, 5, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPAS_SystemStatus (driver torque) + {.msg = {{0x38f, 0, 6, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // iBESP2 (brakes) + {.msg = {{0x100, 2, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // ACM_Status (cruise state) + }; + + bool rivian_longitudinal = false; + + SAFETY_UNUSED(param); + #ifdef ALLOW_DEBUG + const int FLAG_RIVIAN_LONG_CONTROL = 1; + rivian_longitudinal = GET_FLAG(param, FLAG_RIVIAN_LONG_CONTROL); + #endif + + // FIXME: cppcheck thinks that rivian_longitudinal is always false. This is not true + // if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG + // cppcheck-suppress knownConditionTrueFalse + return rivian_longitudinal ? BUILD_SAFETY_CFG(rivian_rx_checks, RIVIAN_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(rivian_rx_checks, RIVIAN_TX_MSGS); +} + +const safety_hooks rivian_hooks = { + .init = rivian_init, + .rx = rivian_rx_hook, + .tx = rivian_tx_hook, + .get_counter = rivian_get_counter, + .get_checksum = rivian_get_checksum, + .compute_checksum = rivian_compute_checksum, + .get_quality_flag_valid = rivian_get_quality_flag_valid, +}; diff --git a/opendbc_repo/opendbc/safety/modes/subaru.h b/opendbc_repo/opendbc/safety/modes/subaru.h new file mode 100644 index 0000000000..9b01d39d63 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/subaru.h @@ -0,0 +1,263 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +#define SUBARU_STEERING_LIMITS_GENERATOR(steer_max, rate_up, rate_down) \ + { \ + .max_torque = (steer_max), \ + .max_rt_delta = 940, \ + .max_rate_up = (rate_up), \ + .max_rate_down = (rate_down), \ + .driver_torque_multiplier = 50, \ + .driver_torque_allowance = 60, \ + .type = TorqueDriverLimited, \ + /* the EPS will temporary fault if the steering rate is too high, so we cut the \ + the steering torque every 7 frames for 1 frame if the steering rate is high */ \ + .min_valid_request_frames = 7, \ + .max_invalid_request_frames = 1, \ + .min_valid_request_rt_interval = 144000, /* 10% tolerance */ \ + .has_steer_req_tolerance = true, \ + } + +#define MSG_SUBARU_Brake_Status 0x13cU +#define MSG_SUBARU_CruiseControl 0x240U +#define MSG_SUBARU_Throttle 0x40U +#define MSG_SUBARU_Steering_Torque 0x119U +#define MSG_SUBARU_Wheel_Speeds 0x13aU + +#define MSG_SUBARU_ES_LKAS 0x122U +#define MSG_SUBARU_ES_Brake 0x220U +#define MSG_SUBARU_ES_Distance 0x221U +#define MSG_SUBARU_ES_Status 0x222U +#define MSG_SUBARU_ES_DashStatus 0x321U +#define MSG_SUBARU_ES_LKAS_State 0x322U +#define MSG_SUBARU_ES_Infotainment 0x323U + +#define MSG_SUBARU_ES_UDS_Request 0x787U + +#define MSG_SUBARU_ES_HighBeamAssist 0x121U +#define MSG_SUBARU_ES_STATIC_1 0x22aU +#define MSG_SUBARU_ES_STATIC_2 0x325U + +#define SUBARU_MAIN_BUS 0U +#define SUBARU_ALT_BUS 1U +#define SUBARU_CAM_BUS 2U + +#define SUBARU_BASE_TX_MSGS(alt_bus, lkas_msg) \ + {lkas_msg, SUBARU_MAIN_BUS, 8, .check_relay = true}, \ + {MSG_SUBARU_ES_DashStatus, SUBARU_MAIN_BUS, 8, .check_relay = true}, \ + {MSG_SUBARU_ES_LKAS_State, SUBARU_MAIN_BUS, 8, .check_relay = true}, \ + {MSG_SUBARU_ES_Infotainment, SUBARU_MAIN_BUS, 8, .check_relay = true}, \ + +#define SUBARU_COMMON_TX_MSGS(alt_bus) \ + {MSG_SUBARU_ES_Distance, alt_bus, 8, .check_relay = false}, \ + +#define SUBARU_COMMON_LONG_TX_MSGS(alt_bus) \ + {MSG_SUBARU_ES_Distance, alt_bus, 8, .check_relay = true}, \ + {MSG_SUBARU_ES_Brake, alt_bus, 8, .check_relay = true}, \ + {MSG_SUBARU_ES_Status, alt_bus, 8, .check_relay = true}, \ + +#define SUBARU_GEN2_LONG_ADDITIONAL_TX_MSGS() \ + {MSG_SUBARU_ES_UDS_Request, SUBARU_CAM_BUS, 8, .check_relay = false}, \ + {MSG_SUBARU_ES_HighBeamAssist, SUBARU_MAIN_BUS, 8, .check_relay = false}, \ + {MSG_SUBARU_ES_STATIC_1, SUBARU_MAIN_BUS, 8, .check_relay = false}, \ + {MSG_SUBARU_ES_STATIC_2, SUBARU_MAIN_BUS, 8, .check_relay = false}, \ + +#define SUBARU_COMMON_RX_CHECKS(alt_bus) \ + {.msg = {{MSG_SUBARU_Throttle, SUBARU_MAIN_BUS, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{MSG_SUBARU_Steering_Torque, SUBARU_MAIN_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{MSG_SUBARU_Wheel_Speeds, alt_bus, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{MSG_SUBARU_Brake_Status, alt_bus, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{MSG_SUBARU_CruiseControl, alt_bus, 8, 20U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +static bool subaru_gen2 = false; +static bool subaru_longitudinal = false; + +static uint32_t subaru_get_checksum(const CANPacket_t *msg) { + return (uint8_t)msg->data[0]; +} + +static uint8_t subaru_get_counter(const CANPacket_t *msg) { + return (uint8_t)(msg->data[1] & 0xFU); +} + +static uint32_t subaru_compute_checksum(const CANPacket_t *msg) { + int len = GET_LEN(msg); + uint8_t checksum = (uint8_t)(msg->addr) + (uint8_t)((unsigned int)(msg->addr) >> 8U); + for (int i = 1; i < len; i++) { + checksum += (uint8_t)msg->data[i]; + } + return checksum; +} + +static void subaru_rx_hook(const CANPacket_t *msg) { + const unsigned int alt_main_bus = subaru_gen2 ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS; + + if ((msg->addr == MSG_SUBARU_Steering_Torque) && (msg->bus == SUBARU_MAIN_BUS)) { + int torque_driver_new; + torque_driver_new = ((GET_BYTES(msg, 0, 4) >> 16) & 0x7FFU); + torque_driver_new = -1 * to_signed(torque_driver_new, 11); + update_sample(&torque_driver, torque_driver_new); + + int angle_meas_new = (GET_BYTES(msg, 4, 2) & 0xFFFFU); + // convert Steering_Torque -> Steering_Angle to centidegrees, to match the ES_LKAS_ANGLE angle request units + angle_meas_new = ROUND(to_signed(angle_meas_new, 16) * -2.17); + update_sample(&angle_meas, angle_meas_new); + } + + // enter controls on rising edge of ACC, exit controls on ACC off + if ((msg->addr == MSG_SUBARU_CruiseControl) && (msg->bus == alt_main_bus)) { + bool cruise_engaged = (msg->data[5] >> 1) & 1U; + pcm_cruise_check(cruise_engaged); + } + + // update vehicle moving with any non-zero wheel speed + if ((msg->addr == MSG_SUBARU_Wheel_Speeds) && (msg->bus == alt_main_bus)) { + uint32_t fr = (GET_BYTES(msg, 1, 3) >> 4) & 0x1FFFU; + uint32_t rr = (GET_BYTES(msg, 3, 3) >> 1) & 0x1FFFU; + uint32_t rl = (GET_BYTES(msg, 4, 3) >> 6) & 0x1FFFU; + uint32_t fl = (GET_BYTES(msg, 6, 2) >> 3) & 0x1FFFU; + + vehicle_moving = (fr > 0U) || (rr > 0U) || (rl > 0U) || (fl > 0U); + + UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4.0 * 0.057 * KPH_TO_MS); + } + + if ((msg->addr == MSG_SUBARU_Brake_Status) && (msg->bus == alt_main_bus)) { + brake_pressed = (msg->data[7] >> 6) & 1U; + } + + if ((msg->addr == MSG_SUBARU_Throttle) && (msg->bus == SUBARU_MAIN_BUS)) { + gas_pressed = msg->data[4] != 0U; + } +} + +static bool subaru_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits SUBARU_STEERING_LIMITS = SUBARU_STEERING_LIMITS_GENERATOR(2047, 50, 70); + const TorqueSteeringLimits SUBARU_GEN2_STEERING_LIMITS = SUBARU_STEERING_LIMITS_GENERATOR(1000, 40, 40); + + const LongitudinalLimits SUBARU_LONG_LIMITS = { + .min_gas = 808, // appears to be engine braking + .max_gas = 3400, // approx 2 m/s^2 when maxing cruise_rpm and cruise_throttle + .inactive_gas = 1818, // this is zero acceleration + .max_brake = 600, // approx -3.5 m/s^2 + + .min_transmission_rpm = 0, + .max_transmission_rpm = 3600, + }; + + bool tx = true; + bool violation = false; + + // steer cmd checks + if (msg->addr == MSG_SUBARU_ES_LKAS) { + int desired_torque = ((GET_BYTES(msg, 0, 4) >> 16) & 0x1FFFU); + desired_torque = -1 * to_signed(desired_torque, 13); + + bool steer_req = (msg->data[3] >> 5) & 1U; + + const TorqueSteeringLimits limits = subaru_gen2 ? SUBARU_GEN2_STEERING_LIMITS : SUBARU_STEERING_LIMITS; + violation |= steer_torque_cmd_checks(desired_torque, steer_req, limits); + } + + // check es_brake brake_pressure limits + if (msg->addr == MSG_SUBARU_ES_Brake) { + int es_brake_pressure = GET_BYTES(msg, 2, 2); + violation |= longitudinal_brake_checks(es_brake_pressure, SUBARU_LONG_LIMITS); + } + + // check es_distance cruise_throttle limits + if (msg->addr == MSG_SUBARU_ES_Distance) { + int cruise_throttle = (GET_BYTES(msg, 2, 2) & 0x1FFFU); + bool cruise_cancel = (msg->data[7] >> 0) & 1U; + + if (subaru_longitudinal) { + violation |= longitudinal_gas_checks(cruise_throttle, SUBARU_LONG_LIMITS); + } else { + // If openpilot is not controlling long, only allow ES_Distance for cruise cancel requests, + // (when Cruise_Cancel is true, and Cruise_Throttle is inactive) + violation |= (cruise_throttle != SUBARU_LONG_LIMITS.inactive_gas); + violation |= (!cruise_cancel); + } + } + + // check es_status transmission_rpm limits + if (msg->addr == MSG_SUBARU_ES_Status) { + int transmission_rpm = (GET_BYTES(msg, 2, 2) & 0x1FFFU); + violation |= longitudinal_transmission_rpm_checks(transmission_rpm, SUBARU_LONG_LIMITS); + } + + if (msg->addr == MSG_SUBARU_ES_UDS_Request) { + // tester present ('\x02\x3E\x80\x00\x00\x00\x00\x00') is allowed for gen2 longitudinal to keep eyesight disabled + bool is_tester_present = (GET_BYTES(msg, 0, 4) == 0x00803E02U) && (GET_BYTES(msg, 4, 4) == 0x0U); + + // reading ES button data by identifier (b'\x03\x22\x11\x30\x00\x00\x00\x00') is also allowed (DID 0x1130) + bool is_button_rdbi = (GET_BYTES(msg, 0, 4) == 0x30112203U) && (GET_BYTES(msg, 4, 4) == 0x0U); + + violation |= !(is_tester_present || is_button_rdbi); + } + + if (violation){ + tx = false; + } + return tx; +} + +static safety_config subaru_init(uint16_t param) { + static const CanMsg SUBARU_TX_MSGS[] = { + SUBARU_BASE_TX_MSGS(SUBARU_MAIN_BUS, MSG_SUBARU_ES_LKAS) + SUBARU_COMMON_TX_MSGS(SUBARU_MAIN_BUS) + }; + + static const CanMsg SUBARU_LONG_TX_MSGS[] = { + SUBARU_BASE_TX_MSGS(SUBARU_MAIN_BUS, MSG_SUBARU_ES_LKAS) + SUBARU_COMMON_LONG_TX_MSGS(SUBARU_MAIN_BUS) + }; + + static const CanMsg SUBARU_GEN2_TX_MSGS[] = { + SUBARU_BASE_TX_MSGS(SUBARU_ALT_BUS, MSG_SUBARU_ES_LKAS) + SUBARU_COMMON_TX_MSGS(SUBARU_ALT_BUS) + }; + + static const CanMsg SUBARU_GEN2_LONG_TX_MSGS[] = { + SUBARU_BASE_TX_MSGS(SUBARU_ALT_BUS, MSG_SUBARU_ES_LKAS) + SUBARU_COMMON_LONG_TX_MSGS(SUBARU_ALT_BUS) + SUBARU_GEN2_LONG_ADDITIONAL_TX_MSGS() + }; + + static RxCheck subaru_rx_checks[] = { + SUBARU_COMMON_RX_CHECKS(SUBARU_MAIN_BUS) + }; + + static RxCheck subaru_gen2_rx_checks[] = { + SUBARU_COMMON_RX_CHECKS(SUBARU_ALT_BUS) + }; + + const uint16_t SUBARU_PARAM_GEN2 = 1; + + subaru_gen2 = GET_FLAG(param, SUBARU_PARAM_GEN2); + +#ifdef ALLOW_DEBUG + const uint16_t SUBARU_PARAM_LONGITUDINAL = 2; + subaru_longitudinal = GET_FLAG(param, SUBARU_PARAM_LONGITUDINAL); +#endif + + safety_config ret; + if (subaru_gen2) { + ret = subaru_longitudinal ? BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_GEN2_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_GEN2_TX_MSGS); + } else { + ret = subaru_longitudinal ? BUILD_SAFETY_CFG(subaru_rx_checks, SUBARU_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(subaru_rx_checks, SUBARU_TX_MSGS); + } + return ret; +} + +const safety_hooks subaru_hooks = { + .init = subaru_init, + .rx = subaru_rx_hook, + .tx = subaru_tx_hook, + .get_counter = subaru_get_counter, + .get_checksum = subaru_get_checksum, + .compute_checksum = subaru_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h b/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h new file mode 100644 index 0000000000..ecc8371334 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/subaru_preglobal.h @@ -0,0 +1,105 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// Preglobal platform +// 0x161 is ES_CruiseThrottle +// 0x164 is ES_LKAS + +#define MSG_SUBARU_PG_CruiseControl 0x144U +#define MSG_SUBARU_PG_Throttle 0x140U +#define MSG_SUBARU_PG_Wheel_Speeds 0xD4U +#define MSG_SUBARU_PG_Brake_Pedal 0xD1U +#define MSG_SUBARU_PG_ES_LKAS 0x164U +#define MSG_SUBARU_PG_ES_Distance 0x161U +#define MSG_SUBARU_PG_Steering_Torque 0x371U + +#define SUBARU_PG_MAIN_BUS 0U +#define SUBARU_PG_CAM_BUS 2U + +static bool subaru_pg_reversed_driver_torque = false; + +static void subaru_preglobal_rx_hook(const CANPacket_t *msg) { + if (msg->bus == SUBARU_PG_MAIN_BUS) { + if (msg->addr == MSG_SUBARU_PG_Steering_Torque) { + int torque_driver_new; + torque_driver_new = (msg->data[3] >> 5) + (msg->data[4] << 3); + torque_driver_new = to_signed(torque_driver_new, 11); + torque_driver_new = subaru_pg_reversed_driver_torque ? -torque_driver_new : torque_driver_new; + update_sample(&torque_driver, torque_driver_new); + } + + // enter controls on rising edge of ACC, exit controls on ACC off + if (msg->addr == MSG_SUBARU_PG_CruiseControl) { + bool cruise_engaged = (msg->data[6] >> 1) & 1U; + pcm_cruise_check(cruise_engaged); + } + + // update vehicle moving with any non-zero wheel speed + if (msg->addr == MSG_SUBARU_PG_Wheel_Speeds) { + vehicle_moving = ((GET_BYTES(msg, 0, 4) >> 12) != 0U) || (GET_BYTES(msg, 4, 4) != 0U); + } + + if (msg->addr == MSG_SUBARU_PG_Brake_Pedal) { + brake_pressed = ((GET_BYTES(msg, 0, 4) >> 16) & 0xFFU) > 0U; + } + + if (msg->addr == MSG_SUBARU_PG_Throttle) { + gas_pressed = msg->data[0] != 0U; + } + } +} + +static bool subaru_preglobal_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits SUBARU_PG_STEERING_LIMITS = { + .max_torque = 2047, + .max_rt_delta = 940, + .max_rate_up = 50, + .max_rate_down = 70, + .driver_torque_multiplier = 10, + .driver_torque_allowance = 75, + .type = TorqueDriverLimited, + }; + + bool tx = true; + + // steer cmd checks + if (msg->addr == MSG_SUBARU_PG_ES_LKAS) { + int desired_torque = ((GET_BYTES(msg, 0, 4) >> 8) & 0x1FFFU); + desired_torque = -1 * to_signed(desired_torque, 13); + + bool steer_req = (msg->data[3] >> 0) & 1U; + + if (steer_torque_cmd_checks(desired_torque, steer_req, SUBARU_PG_STEERING_LIMITS)) { + tx = false; + } + } + return tx; +} + +static safety_config subaru_preglobal_init(uint16_t param) { + static const CanMsg SUBARU_PG_TX_MSGS[] = { + {MSG_SUBARU_PG_ES_Distance, SUBARU_PG_MAIN_BUS, 8, .check_relay = true}, + {MSG_SUBARU_PG_ES_LKAS, SUBARU_PG_MAIN_BUS, 8, .check_relay = true} + }; + + // TODO: do checksum and counter checks after adding the signals to the outback dbc file + static RxCheck subaru_preglobal_rx_checks[] = { + {.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_SUBARU_PG_Wheel_Speeds, SUBARU_PG_MAIN_BUS, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_SUBARU_PG_Brake_Pedal, SUBARU_PG_MAIN_BUS, 4, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + const int SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE = 4; + + subaru_pg_reversed_driver_torque = GET_FLAG(param, SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE); + return BUILD_SAFETY_CFG(subaru_preglobal_rx_checks, SUBARU_PG_TX_MSGS); +} + +const safety_hooks subaru_preglobal_hooks = { + .init = subaru_preglobal_init, + .rx = subaru_preglobal_rx_hook, + .tx = subaru_preglobal_tx_hook, +}; diff --git a/opendbc_repo/opendbc/safety/modes/tesla.h b/opendbc_repo/opendbc/safety/modes/tesla.h new file mode 100644 index 0000000000..f91e2f9808 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/tesla.h @@ -0,0 +1,375 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +static bool tesla_longitudinal = false; +static bool tesla_stock_aeb = false; + +// Only rising edges while controls are not allowed are considered for these systems: +// TODO: Only LKAS (non-emergency) is currently supported since we've only seen it +static bool tesla_stock_lkas = false; +static bool tesla_stock_lkas_prev = false; + +// Only Summon is currently supported due to Autopark not setting Autopark state properly +static bool tesla_autopark = false; +static bool tesla_autopark_prev = false; + +static uint8_t tesla_get_counter(const CANPacket_t *msg) { + + uint8_t cnt = 0; + if (msg->addr == 0x2b9U) { + // Signal: DAS_controlCounter + cnt = msg->data[6] >> 5; + } else if (msg->addr == 0x488U) { + // Signal: DAS_steeringControlCounter + cnt = msg->data[2] & 0x0FU; + } else if ((msg->addr == 0x257U) || (msg->addr == 0x118U) || (msg->addr == 0x39dU) || (msg->addr == 0x286U) || (msg->addr == 0x311U)) { + // Signal: DI_speedCounter, DI_systemStatusCounter, IBST_statusCounter, DI_locStatusCounter, UI_warningCounter + cnt = msg->data[1] & 0x0FU; + } else if (msg->addr == 0x155U) { + // Signal: ESP_wheelRotationCounter + cnt = msg->data[6] >> 4; + } else if (msg->addr == 0x370U) { + // Signal: EPAS3S_sysStatusCounter + cnt = msg->data[6] & 0x0FU; + } else { + } + return cnt; +} + +static int _tesla_get_checksum_byte(const int addr) { + int checksum_byte = -1; + if ((addr == 0x370) || (addr == 0x2b9) || (addr == 0x155)) { + // Signal: EPAS3S_sysStatusChecksum, DAS_controlChecksum, ESP_wheelRotationChecksum + checksum_byte = 7; + } else if (addr == 0x488) { + // Signal: DAS_steeringControlChecksum + checksum_byte = 3; + } else if ((addr == 0x257) || (addr == 0x118) || (addr == 0x39d) || (addr == 0x286) || (addr == 0x311)) { + // Signal: DI_speedChecksum, DI_systemStatusChecksum, IBST_statusChecksum, DI_locStatusChecksum, UI_warningChecksum + checksum_byte = 0; + } else { + } + return checksum_byte; +} + +static uint32_t tesla_get_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + int checksum_byte = _tesla_get_checksum_byte(msg->addr); + if (checksum_byte != -1) { + chksum = msg->data[checksum_byte]; + } + return chksum; +} + +static uint32_t tesla_compute_checksum(const CANPacket_t *msg) { + uint8_t chksum = 0; + int checksum_byte = _tesla_get_checksum_byte(msg->addr); + + if (checksum_byte != -1) { + chksum = (uint8_t)((msg->addr & 0xFFU) + ((msg->addr >> 8) & 0xFFU)); + int len = GET_LEN(msg); + for (int i = 0; i < len; i++) { + if (i != checksum_byte) { + chksum += msg->data[i]; + } + } + } + return chksum; +} + +static bool tesla_get_quality_flag_valid(const CANPacket_t *msg) { + + bool valid = false; + if (msg->addr == 0x155U) { + valid = (msg->data[5] & 0x1U) == 0x1U; // ESP_wheelSpeedsQF + } else if (msg->addr == 0x39dU) { + int user_brake_status = msg->data[2] & 0x03U; + valid = (user_brake_status != 0) && (user_brake_status != 3); // IBST_driverBrakeApply=NOT_INIT_OR_OFF, FAULT + } else { + } + return valid; +} + +static void tesla_rx_hook(const CANPacket_t *msg) { + + if (msg->bus == 0U) { + // Steering angle: (0.1 * val) - 819.2 in deg. + if (msg->addr == 0x370U) { + // Store it 1/10 deg to match steering request + const int angle_meas_new = (((msg->data[4] & 0x3FU) << 8) | msg->data[5]) - 8192U; + update_sample(&angle_meas, angle_meas_new); + + const int hands_on_level = msg->data[4] >> 6; // EPAS3S_handsOnLevel + const int eac_status = msg->data[6] >> 5; // EPAS3S_eacStatus + const int eac_error_code = msg->data[2] >> 4; // EPAS3S_eacErrorCode + + // Disengage on normal user override, or if high angle rate fault from user overriding extremely quickly + steering_disengage = (hands_on_level >= 3) || ((eac_status == 0) && (eac_error_code == 9)); + } + + // Vehicle speed (DI_speed) + if (msg->addr == 0x257U) { + // Vehicle speed: ((val * 0.08) - 40) / MS_TO_KPH + float speed = ((((msg->data[2] << 4) | (msg->data[1] >> 4)) * 0.08) - 40.) * KPH_TO_MS; + UPDATE_VEHICLE_SPEED(speed); + } + + // 2nd vehicle speed (ESP_B) + if (msg->addr == 0x155U) { + // Disable controls if speeds from DI (Drive Inverter) and ESP ECUs are too far apart. + float esp_speed = (((msg->data[6] & 0x0FU) << 6) | (msg->data[5] >> 2)) * 0.5 * KPH_TO_MS; + speed_mismatch_check(esp_speed); + } + + // Gas pressed + if (msg->addr == 0x118U) { + gas_pressed = (msg->data[4] != 0U); + } + + // Brake pressed + if (msg->addr == 0x39dU) { + brake_pressed = (msg->data[2] & 0x03U) == 2U; + } + + // Cruise and Autopark/Summon state + if (msg->addr == 0x286U) { + // Autopark state + int autopark_state = (msg->data[3] >> 1) & 0x0FU; // DI_autoparkState + bool tesla_autopark_now = (autopark_state == 3) || // ACTIVE + (autopark_state == 4) || // COMPLETE + (autopark_state == 9); // SELFPARK_STARTED + + // Only consider rising edges while controls are not allowed + if (tesla_autopark_now && !tesla_autopark_prev && !cruise_engaged_prev) { + tesla_autopark = true; + } + if (!tesla_autopark_now) { + tesla_autopark = false; + } + tesla_autopark_prev = tesla_autopark_now; + + // Cruise state + int cruise_state = (msg->data[1] >> 4) & 0x07U; + bool cruise_engaged = (cruise_state == 2) || // ENABLED + (cruise_state == 3) || // STANDSTILL + (cruise_state == 4) || // OVERRIDE + (cruise_state == 6) || // PRE_FAULT + (cruise_state == 7); // PRE_CANCEL + cruise_engaged = cruise_engaged && !tesla_autopark; + + pcm_cruise_check(cruise_engaged); + } + + if (msg->addr == 0x155U) { + vehicle_moving = !GET_BIT(msg, 41U); // ESP_vehicleStandstillSts + } + } + + if (msg->bus == 2U) { + // DAS_control + if (msg->addr == 0x2b9U) { + // "AEB_ACTIVE" + tesla_stock_aeb = (msg->data[2] & 0x03U) == 1U; + } + + // DAS_steeringControl + if (msg->addr == 0x488U) { + int steering_control_type = msg->data[2] >> 6; + bool tesla_stock_lkas_now = steering_control_type == 2; // "LANE_KEEP_ASSIST" + + // Only consider rising edges while controls are not allowed + if (tesla_stock_lkas_now && !tesla_stock_lkas_prev && !controls_allowed) { + tesla_stock_lkas = true; + } + if (!tesla_stock_lkas_now) { + tesla_stock_lkas = false; + } + tesla_stock_lkas_prev = tesla_stock_lkas_now; + } + } +} + + +static bool tesla_tx_hook(const CANPacket_t *msg) { + const AngleSteeringLimits TESLA_STEERING_LIMITS = { + .max_angle = 3600, // 360 deg, EPAS faults above this + .angle_deg_to_can = 10, + .frequency = 50U, + }; + + // NOTE: based off TESLA_MODEL_Y to match openpilot + const AngleSteeringParams TESLA_STEERING_PARAMS = { + .slip_factor = -0.000580374383851451, // calc_slip_factor(VM) + .steer_ratio = 12., + .wheelbase = 2.89, + }; + + const LongitudinalLimits TESLA_LONG_LIMITS = { + .max_accel = 425, // 2 m/s^2 + .min_accel = 288, // -3.48 m/s^2 + .inactive_accel = 375, // 0. m/s^2 + }; + + bool tx = true; + bool violation = false; + + // Don't send any messages when Autopark is active + if (tesla_autopark) { + violation = true; + } + + // Steering control: (0.1 * val) - 1638.35 in deg. + if (msg->addr == 0x488U) { + // We use 1/10 deg as a unit here + int raw_angle_can = ((msg->data[0] & 0x7FU) << 8) | msg->data[1]; + int desired_angle = raw_angle_can - 16384; + int steer_control_type = msg->data[2] >> 6; + bool steer_control_enabled = steer_control_type == 1; // ANGLE_CONTROL + + if (steer_angle_cmd_checks_vm(desired_angle, steer_control_enabled, TESLA_STEERING_LIMITS, TESLA_STEERING_PARAMS)) { + violation = true; + } + + bool valid_steer_control_type = (steer_control_type == 0) || // NONE + (steer_control_type == 1); // ANGLE_CONTROL + if (!valid_steer_control_type) { + violation = true; + } + + if (tesla_stock_lkas) { + // Don't allow any steering commands when stock LKAS is active + violation = true; + } + } + + // DAS_control: longitudinal control message + if (msg->addr == 0x2b9U) { + // No AEB events may be sent by openpilot + int aeb_event = msg->data[2] & 0x03U; + if (aeb_event != 0) { + violation = true; + } + + // Don't send long/cancel messages when the stock AEB system is active + if (tesla_stock_aeb) { + violation = true; + } + + int raw_accel_max = ((msg->data[6] & 0x1FU) << 4) | (msg->data[5] >> 4); + int raw_accel_min = ((msg->data[5] & 0x0FU) << 5) | (msg->data[4] >> 3); + int acc_state = msg->data[1] >> 4; + + if (tesla_longitudinal) { + // Prevent both acceleration from being negative, as this could cause the car to reverse after coming to standstill + if ((raw_accel_max < TESLA_LONG_LIMITS.inactive_accel) && (raw_accel_min < TESLA_LONG_LIMITS.inactive_accel)) { + violation = true; + } + + // Don't allow any acceleration limits above the safety limits + violation |= longitudinal_accel_checks(raw_accel_max, TESLA_LONG_LIMITS); + violation |= longitudinal_accel_checks(raw_accel_min, TESLA_LONG_LIMITS); + } else { + // Can only send cancel longitudinal messages when not controlling longitudinal + if (acc_state != 13) { // ACC_CANCEL_GENERIC_SILENT + violation = true; + } + + // No actuation is allowed when not controlling longitudinal + if ((raw_accel_max != TESLA_LONG_LIMITS.inactive_accel) || (raw_accel_min != TESLA_LONG_LIMITS.inactive_accel)) { + violation = true; + } + } + } + + if (violation) { + tx = false; + } + + return tx; +} + +static bool tesla_fwd_hook(int bus_num, int addr) { + bool block_msg = false; + + if (bus_num == 2) { + if (!tesla_autopark) { + // APS_eacMonitor + if (addr == 0x27d) { + block_msg = true; + } + + // DAS_steeringControl + if ((addr == 0x488) && !tesla_stock_lkas) { + block_msg = true; + } + + // DAS_control + if (tesla_longitudinal && (addr == 0x2b9) && !tesla_stock_aeb) { + block_msg = true; + } + } + } + + return block_msg; +} + +static safety_config tesla_init(uint16_t param) { + + static const CanMsg TESLA_M3_Y_TX_MSGS[] = { + {0x488, 0, 4, .check_relay = true, .disable_static_blocking = true}, // DAS_steeringControl + {0x2b9, 0, 8, .check_relay = false}, // DAS_control (for cancel) + {0x27D, 0, 3, .check_relay = true, .disable_static_blocking = true}, // APS_eacMonitor + }; + + static const CanMsg TESLA_M3_Y_LONG_TX_MSGS[] = { + {0x488, 0, 4, .check_relay = true, .disable_static_blocking = true}, // DAS_steeringControl + {0x2b9, 0, 8, .check_relay = true, .disable_static_blocking = true}, // DAS_control + {0x27D, 0, 3, .check_relay = true, .disable_static_blocking = true}, // APS_eacMonitor + }; + + SAFETY_UNUSED(param); +#ifdef ALLOW_DEBUG + const int TESLA_FLAG_LONGITUDINAL_CONTROL = 1; + tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL); +#endif + + tesla_stock_aeb = false; + tesla_stock_lkas = false; + tesla_stock_lkas_prev = false; + // we need to assume Autopark/Summon on startup since DI_state is a low freq msg. + // this is so that we don't fault if starting while these systems are active + tesla_autopark = true; + tesla_autopark_prev = false; + + static RxCheck tesla_model3_y_rx_checks[] = { + {.msg = {{0x2b9, 2, 8, 25U, .max_counter = 7U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DAS_control + {.msg = {{0x488, 2, 4, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DAS_steeringControl + {.msg = {{0x257, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DI_speed (speed in kph) + {.msg = {{0x155, 0, 8, 50U, .max_counter = 15U}, { 0 }, { 0 }}}, // ESP_B (2nd speed in kph) + {.msg = {{0x370, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // EPAS3S_sysStatus (steering angle) + {.msg = {{0x118, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DI_systemStatus (gas pedal) + {.msg = {{0x39d, 0, 5, 25U, .max_counter = 15U}, { 0 }, { 0 }}}, // IBST_status (brakes) + {.msg = {{0x286, 0, 8, 10U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // DI_state (acc state) + {.msg = {{0x311, 0, 7, 10U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // UI_warning (blinkers, buckle switch & doors) + }; + + safety_config ret; + if (tesla_longitudinal) { + ret = BUILD_SAFETY_CFG(tesla_model3_y_rx_checks, TESLA_M3_Y_LONG_TX_MSGS); + } else { + ret = BUILD_SAFETY_CFG(tesla_model3_y_rx_checks, TESLA_M3_Y_TX_MSGS); + } + return ret; +} + +const safety_hooks tesla_hooks = { + .init = tesla_init, + .rx = tesla_rx_hook, + .tx = tesla_tx_hook, + .fwd = tesla_fwd_hook, + .get_counter = tesla_get_counter, + .get_checksum = tesla_get_checksum, + .compute_checksum = tesla_compute_checksum, + .get_quality_flag_valid = tesla_get_quality_flag_valid, +}; diff --git a/opendbc_repo/opendbc/safety/modes/toyota.h b/opendbc_repo/opendbc/safety/modes/toyota.h new file mode 100644 index 0000000000..37f77a8236 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/toyota.h @@ -0,0 +1,410 @@ +#pragma once + +#include "opendbc/safety/declarations.h" + +// Stock longitudinal +#define TOYOTA_BASE_TX_MSGS \ + {0x191, 0, 8, .check_relay = true}, {0x412, 0, 8, .check_relay = true}, {0x1D2, 0, 8, .check_relay = false}, /* LKAS + LTA + PCM cancel cmd */ \ + +#define TOYOTA_COMMON_TX_MSGS \ + TOYOTA_BASE_TX_MSGS \ + {0x2E4, 0, 5, .check_relay = true}, \ + {0x343, 0, 8, .check_relay = false}, /* ACC cancel cmd */ \ + +#define TOYOTA_COMMON_SECOC_TX_MSGS \ + TOYOTA_BASE_TX_MSGS \ + {0x2E4, 0, 8, .check_relay = true}, {0x131, 0, 8, .check_relay = true}, \ + {0x343, 0, 8, .check_relay = false}, /* ACC cancel cmd */ \ + +#define TOYOTA_COMMON_LONG_TX_MSGS \ + TOYOTA_COMMON_TX_MSGS \ + /* DSU bus 0 */ \ + {0x283, 0, 7, .check_relay = false}, {0x2E6, 0, 8, .check_relay = false}, {0x2E7, 0, 8, .check_relay = false}, {0x33E, 0, 7, .check_relay = false}, \ + {0x344, 0, 8, .check_relay = false}, {0x365, 0, 7, .check_relay = false}, {0x366, 0, 7, .check_relay = false}, {0x4CB, 0, 8, .check_relay = false}, \ + /* DSU bus 1 */ \ + {0x128, 1, 6, .check_relay = false}, {0x141, 1, 4, .check_relay = false}, {0x160, 1, 8, .check_relay = false}, {0x161, 1, 7, .check_relay = false}, \ + {0x470, 1, 4, .check_relay = false}, \ + /* PCS_HUD */ \ + {0x411, 0, 8, .check_relay = false}, \ + /* radar diagnostic address */ \ + {0x750, 0, 8, .check_relay = false}, \ + /* ACC */ \ + {0x343, 0, 8, .check_relay = true}, \ + +#define TOYOTA_COMMON_RX_CHECKS(lta) \ + {.msg = {{ 0xaa, 0, 8, 83U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x260, 0, 8, 50U, .ignore_counter = true, .ignore_quality_flag=!(lta)}, { 0 }, { 0 }}}, \ + +#define TOYOTA_RX_CHECKS(lta) \ + TOYOTA_COMMON_RX_CHECKS(lta) \ + {.msg = {{0x1D2, 0, 8, 33U, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x226, 0, 8, 40U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +#define TOYOTA_ALT_BRAKE_RX_CHECKS(lta) \ + TOYOTA_COMMON_RX_CHECKS(lta) \ + {.msg = {{0x1D2, 0, 8, 33U, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x224, 0, 8, 40U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +#define TOYOTA_SECOC_RX_CHECKS \ + TOYOTA_COMMON_RX_CHECKS(false) \ + {.msg = {{0x176, 0, 8, 32U, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x116, 0, 8, 42U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + {.msg = {{0x101, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \ + +static bool toyota_secoc = false; +static bool toyota_alt_brake = false; +static bool toyota_stock_longitudinal = false; +static bool toyota_lta = false; +static int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file + +static uint32_t toyota_compute_checksum(const CANPacket_t *msg) { + int len = GET_LEN(msg); + uint8_t checksum = (uint8_t)(msg->addr) + (uint8_t)((unsigned int)(msg->addr) >> 8U) + (uint8_t)(len); + for (int i = 0; i < (len - 1); i++) { + checksum += (uint8_t)msg->data[i]; + } + return checksum; +} + +static uint32_t toyota_get_checksum(const CANPacket_t *msg) { + int checksum_byte = GET_LEN(msg) - 1U; + return (uint8_t)(msg->data[checksum_byte]); +} + +static bool toyota_get_quality_flag_valid(const CANPacket_t *msg) { + + bool valid = false; + if (msg->addr == 0x260U) { + valid = !GET_BIT(msg, 3U); // STEER_ANGLE_INITIALIZING + } + return valid; +} + +static void toyota_rx_hook(const CANPacket_t *msg) { + if (msg->bus == 0U) { + + // get eps motor torque (0.66 factor in dbc) + if (msg->addr == 0x260U) { + int torque_meas_new = (msg->data[5] << 8) | msg->data[6]; + torque_meas_new = to_signed(torque_meas_new, 16); + + // scale by dbc_factor + torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100; + + // update array of sample + update_sample(&torque_meas, torque_meas_new); + + // increase torque_meas by 1 to be conservative on rounding + torque_meas.min--; + torque_meas.max++; + + // driver torque for angle limiting + int torque_driver_new = (msg->data[1] << 8) | msg->data[2]; + torque_driver_new = to_signed(torque_driver_new, 16); + update_sample(&torque_driver, torque_driver_new); + + // LTA request angle should match current angle while inactive, clipped to max accepted angle. + // note that angle can be relative to init angle on some TSS2 platforms, LTA has the same offset + bool steer_angle_initializing = GET_BIT(msg, 3U); + if (!steer_angle_initializing) { + int angle_meas_new = (msg->data[3] << 8U) | msg->data[4]; + angle_meas_new = to_signed(angle_meas_new, 16); + update_sample(&angle_meas, angle_meas_new); + } + } + + // enter controls on rising edge of ACC, exit controls on ACC off + // exit controls on rising edge of gas press, if not alternative experience + // exit controls on rising edge of brake press + if (toyota_secoc) { + if (msg->addr == 0x176U) { + bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE + pcm_cruise_check(cruise_engaged); + } + if (msg->addr == 0x116U) { + gas_pressed = msg->data[1] != 0U; // GAS_PEDAL.GAS_PEDAL_USER + } + if (msg->addr == 0x101U) { + brake_pressed = GET_BIT(msg, 3U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_rav4_prime_generated.dbc) + } + } else { + if (msg->addr == 0x1D2U) { + bool cruise_engaged = GET_BIT(msg, 5U); // PCM_CRUISE.CRUISE_ACTIVE + pcm_cruise_check(cruise_engaged); + gas_pressed = !GET_BIT(msg, 4U); // PCM_CRUISE.GAS_RELEASED + } + if (!toyota_alt_brake && (msg->addr == 0x226U)) { + brake_pressed = GET_BIT(msg, 37U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_nodsu_pt_generated.dbc) + } + if (toyota_alt_brake && (msg->addr == 0x224U)) { + brake_pressed = GET_BIT(msg, 5U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_new_mc_pt_generated.dbc) + } + } + + // sample speed + if (msg->addr == 0xaaU) { + int speed = 0; + // sum 4 wheel speeds. conversion: raw * 0.01 - 67.67 + for (uint8_t i = 0U; i < 8U; i += 2U) { + int wheel_speed = (msg->data[i] << 8U) | msg->data[(i + 1U)]; + speed += wheel_speed - 6767; + } + // check that all wheel speeds are at zero value + vehicle_moving = speed != 0; + + UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 * KPH_TO_MS); + } + } +} + +static bool toyota_tx_hook(const CANPacket_t *msg) { + const TorqueSteeringLimits TOYOTA_TORQUE_STEERING_LIMITS = { + .max_torque = 1500, + .max_rate_up = 15, // ramp up slow + .max_rate_down = 25, // ramp down fast + .max_torque_error = 350, // max torque cmd in excess of motor torque + .max_rt_delta = 450, // the real time limit is 1800/sec, a 20% buffer + .type = TorqueMotorLimited, + + // the EPS faults when the steering angle rate is above a certain threshold for too long. to prevent this, + // we allow setting STEER_REQUEST bit to 0 while maintaining the requested torque value for a single frame + .min_valid_request_frames = 18, + .max_invalid_request_frames = 1, + .min_valid_request_rt_interval = 171000, // 171ms; a ~10% buffer on cutting every 19 frames + .has_steer_req_tolerance = true, + }; + + static const AngleSteeringLimits TOYOTA_ANGLE_STEERING_LIMITS = { + // LTA angle limits + // factor for STEER_TORQUE_SENSOR->STEER_ANGLE and STEERING_LTA->STEER_ANGLE_CMD (1 / 0.0573) + .max_angle = 1657, // EPS only accepts up to 94.9461 + .angle_deg_to_can = 17.452007, + .angle_rate_up_lookup = { + {5., 25., 25.}, + {0.3, 0.15, 0.15} + }, + .angle_rate_down_lookup = { + {5., 25., 25.}, + {0.36, 0.26, 0.26} + }, + }; + + const int TOYOTA_LTA_MAX_MEAS_TORQUE = 1500; + const int TOYOTA_LTA_MAX_DRIVER_TORQUE = 150; + + // longitudinal limits + const LongitudinalLimits TOYOTA_LONG_LIMITS = { + .max_accel = 2000, // 2.0 m/s2 + .min_accel = -3500, // -3.5 m/s2 + }; + + bool tx = true; + + // Check if msg is sent on BUS 0 + if (msg->bus == 0U) { + // ACCEL: safety check on byte 1-2 + if (msg->addr == 0x343U) { + int desired_accel = (msg->data[0] << 8) | msg->data[1]; + desired_accel = to_signed(desired_accel, 16); + + bool violation = false; + violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); + + // only ACC messages that cancel are allowed when openpilot is not controlling longitudinal + if (toyota_stock_longitudinal) { + bool cancel_req = GET_BIT(msg, 24U); + if (!cancel_req) { + violation = true; + } + if (desired_accel != TOYOTA_LONG_LIMITS.inactive_accel) { + violation = true; + } + } + + if (violation) { + tx = false; + } + } + + // AEB: block all actuation. only used when DSU is unplugged + if (msg->addr == 0x283U) { + // only allow the checksum, which is the last byte + bool block = (GET_BYTES(msg, 0, 4) != 0U) || (msg->data[4] != 0U) || (msg->data[5] != 0U); + if (block) { + tx = false; + } + } + + // STEERING_LTA angle steering check + if (msg->addr == 0x191U) { + // check the STEER_REQUEST, STEER_REQUEST_2, TORQUE_WIND_DOWN, STEER_ANGLE_CMD signals + bool lta_request = GET_BIT(msg, 0U); + bool lta_request2 = GET_BIT(msg, 25U); + int torque_wind_down = msg->data[5]; + int lta_angle = (msg->data[1] << 8) | msg->data[2]; + lta_angle = to_signed(lta_angle, 16); + + bool steer_control_enabled = lta_request || lta_request2; + if (!toyota_lta) { + // using torque (LKA), block LTA msgs with actuation requests + if (steer_control_enabled || (lta_angle != 0) || (torque_wind_down != 0)) { + tx = false; + } + } else { + // check angle rate limits and inactive angle + if (steer_angle_cmd_checks(lta_angle, steer_control_enabled, TOYOTA_ANGLE_STEERING_LIMITS)) { + tx = false; + } + + if (lta_request != lta_request2) { + tx = false; + } + + // TORQUE_WIND_DOWN is gated on steer request + if (!steer_control_enabled && (torque_wind_down != 0)) { + tx = false; + } + + // TORQUE_WIND_DOWN can only be no or full torque + if ((torque_wind_down != 0) && (torque_wind_down != 100)) { + tx = false; + } + + // check if we should wind down torque + int driver_torque = SAFETY_MIN(SAFETY_ABS(torque_driver.min), SAFETY_ABS(torque_driver.max)); + if ((driver_torque > TOYOTA_LTA_MAX_DRIVER_TORQUE) && (torque_wind_down != 0)) { + tx = false; + } + + int eps_torque = SAFETY_MIN(SAFETY_ABS(torque_meas.min), SAFETY_ABS(torque_meas.max)); + if ((eps_torque > TOYOTA_LTA_MAX_MEAS_TORQUE) && (torque_wind_down != 0)) { + tx = false; + } + } + } + + // STEERING_LTA_2 angle steering check (SecOC) + if (toyota_secoc && (msg->addr == 0x131U)) { + // SecOC cars block any form of LTA actuation for now + bool lta_request = GET_BIT(msg, 3U); // STEERING_LTA_2.STEER_REQUEST + bool lta_request2 = GET_BIT(msg, 0U); // STEERING_LTA_2.STEER_REQUEST_2 + int lta_angle_msb = msg->data[2]; // STEERING_LTA_2.STEER_ANGLE_CMD (MSB) + int lta_angle_lsb = msg->data[3]; // STEERING_LTA_2.STEER_ANGLE_CMD (LSB) + + bool actuation = lta_request || lta_request2 || (lta_angle_msb != 0) || (lta_angle_lsb != 0); + if (actuation) { + tx = false; + } + } + + // STEER: safety check on bytes 2-3 + if (msg->addr == 0x2E4U) { + int desired_torque = (msg->data[1] << 8) | msg->data[2]; + desired_torque = to_signed(desired_torque, 16); + bool steer_req = GET_BIT(msg, 0U); + // When using LTA (angle control), assert no actuation on LKA message + if (!toyota_lta) { + if (steer_torque_cmd_checks(desired_torque, steer_req, TOYOTA_TORQUE_STEERING_LIMITS)) { + tx = false; + } + } else { + if ((desired_torque != 0) || steer_req) { + tx = false; + } + } + } + } + + // UDS: Only tester present ("\x0F\x02\x3E\x00\x00\x00\x00\x00") allowed on diagnostics address + if (msg->addr == 0x750U) { + // this address is sub-addressed. only allow tester present to radar (0xF) + bool invalid_uds_msg = (GET_BYTES(msg, 0, 4) != 0x003E020FU) || (GET_BYTES(msg, 4, 4) != 0x0U); + if (invalid_uds_msg) { + tx = 0; + } + } + + return tx; +} + +static safety_config toyota_init(uint16_t param) { + static const CanMsg TOYOTA_TX_MSGS[] = { + TOYOTA_COMMON_TX_MSGS + }; + + static const CanMsg TOYOTA_SECOC_TX_MSGS[] = { + TOYOTA_COMMON_SECOC_TX_MSGS + }; + + static const CanMsg TOYOTA_LONG_TX_MSGS[] = { + TOYOTA_COMMON_LONG_TX_MSGS + }; + + // safety param flags + // first byte is for EPS factor, second is for flags + const uint32_t TOYOTA_PARAM_OFFSET = 8U; + const uint32_t TOYOTA_EPS_FACTOR = (1UL << TOYOTA_PARAM_OFFSET) - 1U; + const uint32_t TOYOTA_PARAM_ALT_BRAKE = 1UL << TOYOTA_PARAM_OFFSET; + const uint32_t TOYOTA_PARAM_STOCK_LONGITUDINAL = 2UL << TOYOTA_PARAM_OFFSET; + const uint32_t TOYOTA_PARAM_LTA = 4UL << TOYOTA_PARAM_OFFSET; + +#ifdef ALLOW_DEBUG + const uint32_t TOYOTA_PARAM_SECOC = 8UL << TOYOTA_PARAM_OFFSET; + toyota_secoc = GET_FLAG(param, TOYOTA_PARAM_SECOC); +#endif + + toyota_alt_brake = GET_FLAG(param, TOYOTA_PARAM_ALT_BRAKE); + toyota_stock_longitudinal = GET_FLAG(param, TOYOTA_PARAM_STOCK_LONGITUDINAL); + toyota_lta = GET_FLAG(param, TOYOTA_PARAM_LTA); + toyota_dbc_eps_torque_factor = param & TOYOTA_EPS_FACTOR; + + safety_config ret; + if (toyota_stock_longitudinal) { + if (toyota_secoc) { + SET_TX_MSGS(TOYOTA_SECOC_TX_MSGS, ret); + } else { + SET_TX_MSGS(TOYOTA_TX_MSGS, ret); + } + } else { + SET_TX_MSGS(TOYOTA_LONG_TX_MSGS, ret); + } + + if (toyota_secoc) { + static RxCheck toyota_secoc_rx_checks[] = { + TOYOTA_SECOC_RX_CHECKS + }; + + SET_RX_CHECKS(toyota_secoc_rx_checks, ret); + } else if (toyota_lta) { + // Check the quality flag for angle measurement when using LTA, since it's not set on TSS-P cars + static RxCheck toyota_lta_rx_checks[] = { + TOYOTA_RX_CHECKS(true) + }; + + SET_RX_CHECKS(toyota_lta_rx_checks, ret); + } else { + static RxCheck toyota_lka_rx_checks[] = { + TOYOTA_RX_CHECKS(false) + }; + static RxCheck toyota_lka_alt_brake_rx_checks[] = { + TOYOTA_ALT_BRAKE_RX_CHECKS(false) + }; + + if (!toyota_alt_brake) { + SET_RX_CHECKS(toyota_lka_rx_checks, ret); + } else { + SET_RX_CHECKS(toyota_lka_alt_brake_rx_checks, ret); + } + } + + return ret; +} + +const safety_hooks toyota_hooks = { + .init = toyota_init, + .rx = toyota_rx_hook, + .tx = toyota_tx_hook, + .get_checksum = toyota_get_checksum, + .compute_checksum = toyota_compute_checksum, + .get_quality_flag_valid = toyota_get_quality_flag_valid, +}; diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_common.h b/opendbc_repo/opendbc/safety/modes/volkswagen_common.h new file mode 100644 index 0000000000..7792c1eb1b --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_common.h @@ -0,0 +1,70 @@ +#pragma once + +extern const uint16_t FLAG_VOLKSWAGEN_LONG_CONTROL; +const uint16_t FLAG_VOLKSWAGEN_LONG_CONTROL = 1; + +static uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR + +extern bool volkswagen_longitudinal; +bool volkswagen_longitudinal = false; + +extern bool volkswagen_set_button_prev; +bool volkswagen_set_button_prev = false; + +extern bool volkswagen_resume_button_prev; +bool volkswagen_resume_button_prev = false; + + +#define MSG_LH_EPS_03 0x09FU // RX from EPS, for driver steering torque +#define MSG_ESP_19 0x0B2U // RX from ABS, for wheel speeds +#define MSG_ESP_05 0x106U // RX from ABS, for brake switch state +#define MSG_TSK_06 0x120U // RX from ECU, for ACC status from drivetrain coordinator +#define MSG_MOTOR_20 0x121U // RX from ECU, for driver throttle input +#define MSG_ACC_06 0x122U // TX by OP, ACC control instructions to the drivetrain coordinator +#define MSG_HCA_01 0x126U // TX by OP, Heading Control Assist steering torque +#define MSG_GRA_ACC_01 0x12BU // TX by OP, ACC control buttons for cancel/resume +#define MSG_ACC_07 0x12EU // TX by OP, ACC control instructions to the drivetrain coordinator +#define MSG_ACC_02 0x30CU // TX by OP, ACC HUD data to the instrument cluster +#define MSG_LDW_02 0x397U // TX by OP, Lane line recognition and text alerts +#define MSG_MOTOR_14 0x3BEU // RX from ECU, for brake switch status + + +static uint32_t volkswagen_mqb_meb_get_checksum(const CANPacket_t *msg) { + return (uint8_t)msg->data[0]; +} + +static uint8_t volkswagen_mqb_meb_get_counter(const CANPacket_t *msg) { + // MQB/MEB message counters are consistently found at LSB 8. + return (uint8_t)msg->data[1] & 0xFU; +} + +static uint32_t volkswagen_mqb_meb_compute_crc(const CANPacket_t *msg) { + int len = GET_LEN(msg); + + // This is CRC-8H2F/AUTOSAR with a twist. See the opendbc/car/volkswagen/ implementation + // of this algorithm for a version with explanatory comments. + + uint8_t crc = 0xFFU; + for (int i = 1; i < len; i++) { + crc ^= (uint8_t)msg->data[i]; + crc = volkswagen_crc8_lut_8h2f[crc]; + } + + uint8_t counter = volkswagen_mqb_meb_get_counter(msg); + if (msg->addr == MSG_LH_EPS_03) { + crc ^= (uint8_t[]){0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF5}[counter]; + } else if (msg->addr == MSG_ESP_05) { + crc ^= (uint8_t[]){0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07}[counter]; + } else if (msg->addr == MSG_TSK_06) { + crc ^= (uint8_t[]){0xC4, 0xE2, 0x4F, 0xE4, 0xF8, 0x2F, 0x56, 0x81, 0x9F, 0xE5, 0x83, 0x44, 0x05, 0x3F, 0x97, 0xDF}[counter]; + } else if (msg->addr == MSG_MOTOR_20) { + crc ^= (uint8_t[]){0xE9, 0x65, 0xAE, 0x6B, 0x7B, 0x35, 0xE5, 0x5F, 0x4E, 0xC7, 0x86, 0xA2, 0xBB, 0xDD, 0xEB, 0xB4}[counter]; + } else if (msg->addr == MSG_GRA_ACC_01) { + crc ^= (uint8_t[]){0x6A, 0x38, 0xB4, 0x27, 0x22, 0xEF, 0xE1, 0xBB, 0xF8, 0x80, 0x84, 0x49, 0xC7, 0x9E, 0x1E, 0x2B}[counter]; + } else { + // Undefined CAN message, CRC check expected to fail + } + crc = volkswagen_crc8_lut_8h2f[crc]; + + return (uint8_t)(crc ^ 0xFFU); +} diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h b/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h new file mode 100644 index 0000000000..4bf12defc8 --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_mqb.h @@ -0,0 +1,208 @@ +#pragma once + +#include "opendbc/safety/declarations.h" +#include "opendbc/safety/modes/volkswagen_common.h" + +static bool volkswagen_mqb_brake_pedal_switch = false; +static bool volkswagen_mqb_brake_pressure_detected = false; + + +static safety_config volkswagen_mqb_init(uint16_t param) { + // Transmit of GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration + // MSG_LH_EPS_03: openpilot needs to replace apparent driver steering input torque to pacify VW Emergency Assist + static const CanMsg VOLKSWAGEN_MQB_STOCK_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_GRA_ACC_01, 0, 8, .check_relay = false}, {MSG_GRA_ACC_01, 2, 8, .check_relay = false}, + {MSG_LDW_02, 0, 8, .check_relay = true}, {MSG_LH_EPS_03, 2, 8, .check_relay = true}}; + + static const CanMsg VOLKSWAGEN_MQB_LONG_TX_MSGS[] = {{MSG_HCA_01, 0, 8, .check_relay = true}, {MSG_LDW_02, 0, 8, .check_relay = true}, {MSG_LH_EPS_03, 2, 8, .check_relay = true}, + {MSG_ACC_02, 0, 8, .check_relay = true}, {MSG_ACC_06, 0, 8, .check_relay = true}, {MSG_ACC_07, 0, 8, .check_relay = true}}; + + static RxCheck volkswagen_mqb_rx_checks[] = { + {.msg = {{MSG_ESP_19, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_LH_EPS_03, 0, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_ESP_05, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_TSK_06, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_20, 0, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_14, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_GRA_ACC_01, 0, 8, 33U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + SAFETY_UNUSED(param); + + volkswagen_set_button_prev = false; + volkswagen_resume_button_prev = false; + volkswagen_mqb_brake_pedal_switch = false; + volkswagen_mqb_brake_pressure_detected = false; + +#ifdef ALLOW_DEBUG + volkswagen_longitudinal = GET_FLAG(param, FLAG_VOLKSWAGEN_LONG_CONTROL); +#endif + gen_crc_lookup_table_8(0x2F, volkswagen_crc8_lut_8h2f); + return volkswagen_longitudinal ? BUILD_SAFETY_CFG(volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_STOCK_TX_MSGS); +} + +static void volkswagen_mqb_rx_hook(const CANPacket_t *msg) { + if (msg->bus == 0U) { + // Update in-motion state by sampling wheel speeds + if (msg->addr == MSG_ESP_19) { + // sum 4 wheel speeds + int speed = 0; + for (uint8_t i = 0U; i < 8U; i += 2U) { + int wheel_speed = msg->data[i] | (msg->data[i + 1U] << 8); + speed += wheel_speed; + } + // Check all wheel speeds for any movement + vehicle_moving = speed > 0; + } + + // Update driver input torque samples + // Signal: LH_EPS_03.EPS_Lenkmoment (absolute torque) + // Signal: LH_EPS_03.EPS_VZ_Lenkmoment (direction) + if (msg->addr == MSG_LH_EPS_03) { + int torque_driver_new = msg->data[5] | ((msg->data[6] & 0x1FU) << 8); + int sign = (msg->data[6] & 0x80U) >> 7; + if (sign == 1) { + torque_driver_new *= -1; + } + update_sample(&torque_driver, torque_driver_new); + } + + if (msg->addr == MSG_TSK_06) { + // When using stock ACC, enter controls on rising edge of stock ACC engage, exit on disengage + // Always exit controls on main switch off + // Signal: TSK_06.TSK_Status + int acc_status = (msg->data[3] & 0x7U); + bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5); + acc_main_on = cruise_engaged || (acc_status == 2); + + if (!volkswagen_longitudinal) { + pcm_cruise_check(cruise_engaged); + } + + if (!acc_main_on) { + controls_allowed = false; + } + } + + if (msg->addr == MSG_GRA_ACC_01) { + // If using openpilot longitudinal, enter controls on falling edge of Set or Resume with main switch on + // Signal: GRA_ACC_01.GRA_Tip_Setzen + // Signal: GRA_ACC_01.GRA_Tip_Wiederaufnahme + if (volkswagen_longitudinal) { + bool set_button = GET_BIT(msg, 16U); + bool resume_button = GET_BIT(msg, 19U); + if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { + controls_allowed = acc_main_on; + } + volkswagen_set_button_prev = set_button; + volkswagen_resume_button_prev = resume_button; + } + // Always exit controls on rising edge of Cancel + // Signal: GRA_ACC_01.GRA_Abbrechen + if (GET_BIT(msg, 13U)) { + controls_allowed = false; + } + } + + // Signal: Motor_20.MO_Fahrpedalrohwert_01 + if (msg->addr == MSG_MOTOR_20) { + gas_pressed = ((GET_BYTES(msg, 0, 4) >> 12) & 0xFFU) != 0U; + } + + // Signal: Motor_14.MO_Fahrer_bremst (ECU detected brake pedal switch F63) + if (msg->addr == MSG_MOTOR_14) { + volkswagen_mqb_brake_pedal_switch = (msg->data[3] & 0x10U) >> 4; + } + + // Signal: ESP_05.ESP_Fahrer_bremst (ESP detected driver brake pressure above platform specified threshold) + if (msg->addr == MSG_ESP_05) { + volkswagen_mqb_brake_pressure_detected = (msg->data[3] & 0x4U) >> 2; + } + + brake_pressed = volkswagen_mqb_brake_pedal_switch || volkswagen_mqb_brake_pressure_detected; + } +} + +static bool volkswagen_mqb_tx_hook(const CANPacket_t *msg) { + // lateral limits + const TorqueSteeringLimits VOLKSWAGEN_MQB_STEERING_LIMITS = { + .max_torque = 300, // 3.0 Nm (EPS side max of 3.0Nm with fault if violated) + .max_rt_delta = 75, // 4 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 50 ; 50 * 1.5 for safety pad = 75 + .max_rate_up = 4, // 2.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) + .max_rate_down = 10, // 5.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) + .driver_torque_allowance = 80, + .driver_torque_multiplier = 3, + .type = TorqueDriverLimited, + }; + + // longitudinal limits + // acceleration in m/s2 * 1000 to avoid floating point math + const LongitudinalLimits VOLKSWAGEN_MQB_LONG_LIMITS = { + .max_accel = 2000, + .min_accel = -3500, + .inactive_accel = 3010, // VW sends one increment above the max range when inactive + }; + + bool tx = true; + + // Safety check for HCA_01 Heading Control Assist torque + // Signal: HCA_01.HCA_01_LM_Offset (absolute torque) + // Signal: HCA_01.HCA_01_LM_OffSign (direction) + if (msg->addr == MSG_HCA_01) { + int desired_torque = msg->data[2] | ((msg->data[3] & 0x1U) << 8); + bool sign = GET_BIT(msg, 31U); + if (sign) { + desired_torque *= -1; + } + + bool steer_req = GET_BIT(msg, 30U); + + if (steer_torque_cmd_checks(desired_torque, steer_req, VOLKSWAGEN_MQB_STEERING_LIMITS)) { + tx = false; + } + } + + // Safety check for both ACC_06 and ACC_07 acceleration requests + // To avoid floating point math, scale upward and compare to pre-scaled safety m/s2 boundaries + if ((msg->addr == MSG_ACC_06) || (msg->addr == MSG_ACC_07)) { + bool violation = false; + int desired_accel = 0; + + if (msg->addr == MSG_ACC_06) { + // Signal: ACC_06.ACC_Sollbeschleunigung_02 (acceleration in m/s2, scale 0.005, offset -7.22) + desired_accel = ((((msg->data[4] & 0x7U) << 8) | msg->data[3]) * 5U) - 7220U; + } else { + // Signal: ACC_07.ACC_Folgebeschl (acceleration in m/s2, scale 0.03, offset -4.6) + int secondary_accel = (msg->data[4] * 30U) - 4600U; + violation |= (secondary_accel != 3020); // enforce always inactive (one increment above max range) at this time + // Signal: ACC_07.ACC_Sollbeschleunigung_02 (acceleration in m/s2, scale 0.005, offset -7.22) + desired_accel = (((msg->data[7] << 3) | ((msg->data[6] & 0xE0U) >> 5)) * 5U) - 7220U; + } + + violation |= longitudinal_accel_checks(desired_accel, VOLKSWAGEN_MQB_LONG_LIMITS); + + if (violation) { + tx = false; + } + } + + // FORCE CANCEL: ensuring that only the cancel button press is sent when controls are off. + // This avoids unintended engagements while still allowing resume spam + if ((msg->addr == MSG_GRA_ACC_01) && !controls_allowed) { + // disallow resume and set: bits 16 and 19 + if ((msg->data[2] & 0x9U) != 0U) { + tx = false; + } + } + + return tx; +} + +const safety_hooks volkswagen_mqb_hooks = { + .init = volkswagen_mqb_init, + .rx = volkswagen_mqb_rx_hook, + .tx = volkswagen_mqb_tx_hook, + .get_counter = volkswagen_mqb_meb_get_counter, + .get_checksum = volkswagen_mqb_meb_get_checksum, + .compute_checksum = volkswagen_mqb_meb_compute_crc, +}; diff --git a/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h b/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h new file mode 100644 index 0000000000..8d2637e83d --- /dev/null +++ b/opendbc_repo/opendbc/safety/modes/volkswagen_pq.h @@ -0,0 +1,220 @@ +#pragma once + +#include "opendbc/safety/declarations.h" +#include "opendbc/safety/modes/volkswagen_common.h" + +#define MSG_LENKHILFE_3 0x0D0U // RX from EPS, for steering angle and driver steering torque +#define MSG_HCA_1 0x0D2U // TX by OP, Heading Control Assist steering torque +#define MSG_BREMSE_1 0x1A0U // RX from ABS, for ego speed +#define MSG_MOTOR_2 0x288U // RX from ECU, for CC state and brake switch state +#define MSG_ACC_SYSTEM 0x368U // TX by OP, longitudinal acceleration controls +#define MSG_MOTOR_3 0x380U // RX from ECU, for driver throttle input +#define MSG_GRA_NEU 0x38AU // TX by OP, ACC control buttons for cancel/resume +#define MSG_MOTOR_5 0x480U // RX from ECU, for ACC main switch state +#define MSG_ACC_GRA_ANZEIGE 0x56AU // TX by OP, ACC HUD +#define MSG_LDW_1 0x5BEU // TX by OP, Lane line recognition and text alerts + +static uint32_t volkswagen_pq_get_checksum(const CANPacket_t *msg) { + return (uint32_t)msg->data[(msg->addr == MSG_MOTOR_5) ? 7 : 0]; +} + +static uint8_t volkswagen_pq_get_counter(const CANPacket_t *msg) { + uint8_t counter = 0U; + + if (msg->addr == MSG_LENKHILFE_3) { + counter = (uint8_t)(msg->data[1] & 0xF0U) >> 4; + } else if (msg->addr == MSG_GRA_NEU) { + counter = (uint8_t)(msg->data[2] & 0xF0U) >> 4; + } else { + } + + return counter; +} + +static uint32_t volkswagen_pq_compute_checksum(const CANPacket_t *msg) { + int len = GET_LEN(msg); + uint8_t checksum = 0U; + int checksum_byte = (msg->addr == MSG_MOTOR_5) ? 7 : 0; + + // Simple XOR over the payload, except for the byte where the checksum lives. + for (int i = 0; i < len; i++) { + if (i != checksum_byte) { + checksum ^= (uint8_t)msg->data[i]; + } + } + + return checksum; +} + +static safety_config volkswagen_pq_init(uint16_t param) { + // Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration + static const CanMsg VOLKSWAGEN_PQ_STOCK_TX_MSGS[] = {{MSG_HCA_1, 0, 5, .check_relay = true}, {MSG_LDW_1, 0, 8, .check_relay = true}, + {MSG_GRA_NEU, 0, 4, .check_relay = false}, {MSG_GRA_NEU, 2, 4, .check_relay = false}}; + + static const CanMsg VOLKSWAGEN_PQ_LONG_TX_MSGS[] = {{MSG_HCA_1, 0, 5, .check_relay = true}, {MSG_LDW_1, 0, 8, .check_relay = true}, + {MSG_ACC_SYSTEM, 0, 8, .check_relay = true}, {MSG_ACC_GRA_ANZEIGE, 0, 8, .check_relay = true}}; + + static RxCheck volkswagen_pq_rx_checks[] = { + {.msg = {{MSG_LENKHILFE_3, 0, 6, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_BREMSE_1, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_2, 0, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_3, 0, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_MOTOR_5, 0, 8, 50U, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + {.msg = {{MSG_GRA_NEU, 0, 4, 30U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, + }; + + SAFETY_UNUSED(param); + + volkswagen_set_button_prev = false; + volkswagen_resume_button_prev = false; + +#ifdef ALLOW_DEBUG + volkswagen_longitudinal = GET_FLAG(param, FLAG_VOLKSWAGEN_LONG_CONTROL); +#endif + return volkswagen_longitudinal ? BUILD_SAFETY_CFG(volkswagen_pq_rx_checks, VOLKSWAGEN_PQ_LONG_TX_MSGS) : \ + BUILD_SAFETY_CFG(volkswagen_pq_rx_checks, VOLKSWAGEN_PQ_STOCK_TX_MSGS); +} + +static void volkswagen_pq_rx_hook(const CANPacket_t *msg) { + if (msg->bus == 0U) { + // Update in-motion state from speed value. + // Signal: Bremse_1.Geschwindigkeit_neu__Bremse_1_ + if (msg->addr == MSG_BREMSE_1) { + int speed = ((msg->data[2] & 0xFEU) >> 1) | (msg->data[3] << 7); + vehicle_moving = speed > 0; + } + + // Update driver input torque samples + // Signal: Lenkhilfe_3.LH3_LM (absolute torque) + // Signal: Lenkhilfe_3.LH3_LMSign (direction) + if (msg->addr == MSG_LENKHILFE_3) { + int torque_driver_new = msg->data[2] | ((msg->data[3] & 0x3U) << 8); + int sign = (msg->data[3] & 0x4U) >> 2; + if (sign == 1) { + torque_driver_new *= -1; + } + update_sample(&torque_driver, torque_driver_new); + } + + if (volkswagen_longitudinal) { + if (msg->addr == MSG_MOTOR_5) { + // ACC main switch on is a prerequisite to enter controls, exit controls immediately on main switch off + // Signal: Motor_5.GRA_Hauptschalter + acc_main_on = GET_BIT(msg, 50U); + if (!acc_main_on) { + controls_allowed = false; + } + } + + if (msg->addr == MSG_GRA_NEU) { + // If ACC main switch is on, enter controls on falling edge of Set or Resume + // Signal: GRA_Neu.GRA_Neu_Setzen + // Signal: GRA_Neu.GRA_Neu_Recall + bool set_button = GET_BIT(msg, 16U); + bool resume_button = GET_BIT(msg, 17U); + if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { + controls_allowed = acc_main_on; + } + volkswagen_set_button_prev = set_button; + volkswagen_resume_button_prev = resume_button; + // Exit controls on rising edge of Cancel, override Set/Resume if present simultaneously + // Signal: GRA_ACC_01.GRA_Abbrechen + if (GET_BIT(msg, 9U)) { + controls_allowed = false; + } + } + } else { + if (msg->addr == MSG_MOTOR_2) { + // Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages + // Signal: Motor_2.GRA_Status + int acc_status = (msg->data[2] & 0xC0U) >> 6; + bool cruise_engaged = (acc_status == 1) || (acc_status == 2); + pcm_cruise_check(cruise_engaged); + } + } + + // Signal: Motor_3.Fahrpedal_Rohsignal + if (msg->addr == MSG_MOTOR_3) { + gas_pressed = (msg->data[2]); + } + + // Signal: Motor_2.Bremslichtschalter + if (msg->addr == MSG_MOTOR_2) { + brake_pressed = (msg->data[2] & 0x1U); + } + } +} + +static bool volkswagen_pq_tx_hook(const CANPacket_t *msg) { + // lateral limits + const TorqueSteeringLimits VOLKSWAGEN_PQ_STEERING_LIMITS = { + .max_torque = 300, // 3.0 Nm (EPS side max of 3.0Nm with fault if violated) + .max_rt_delta = 113, // 6 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 75 ; 125 * 1.5 for safety pad = 113 + .max_rate_up = 6, // 3.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) + .max_rate_down = 10, // 5.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) + .driver_torque_multiplier = 3, + .driver_torque_allowance = 80, + .type = TorqueDriverLimited, + }; + + // longitudinal limits + // acceleration in m/s2 * 1000 to avoid floating point math + const LongitudinalLimits VOLKSWAGEN_PQ_LONG_LIMITS = { + .max_accel = 2000, + .min_accel = -3500, + .inactive_accel = 3010, // VW sends one increment above the max range when inactive + }; + + bool tx = true; + + // Safety check for HCA_1 Heading Control Assist torque + // Signal: HCA_1.LM_Offset (absolute torque) + // Signal: HCA_1.LM_Offsign (direction) + if (msg->addr == MSG_HCA_1) { + int desired_torque = msg->data[2] | ((msg->data[3] & 0x7FU) << 8); + desired_torque = desired_torque / 32; // DBC scale from PQ network to centi-Nm + int sign = (msg->data[3] & 0x80U) >> 7; + if (sign == 1) { + desired_torque *= -1; + } + + uint32_t hca_status = ((msg->data[1] >> 4) & 0xFU); + bool steer_req = ((hca_status == 5U) || (hca_status == 7U)); + + if (steer_torque_cmd_checks(desired_torque, steer_req, VOLKSWAGEN_PQ_STEERING_LIMITS)) { + tx = false; + } + } + + // Safety check for acceleration commands + // To avoid floating point math, scale upward and compare to pre-scaled safety m/s2 boundaries + if (msg->addr == MSG_ACC_SYSTEM) { + // Signal: ACC_System.ACS_Sollbeschl (acceleration in m/s2, scale 0.005, offset -7.22) + int desired_accel = ((((msg->data[4] & 0x7U) << 8) | msg->data[3]) * 5U) - 7220U; + + if (longitudinal_accel_checks(desired_accel, VOLKSWAGEN_PQ_LONG_LIMITS)) { + tx = false; + } + } + + // FORCE CANCEL: ensuring that only the cancel button press is sent when controls are off. + // This avoids unintended engagements while still allowing resume spam + if ((msg->addr == MSG_GRA_NEU) && !controls_allowed) { + // Signal: GRA_Neu.GRA_Neu_Setzen + // Signal: GRA_Neu.GRA_Neu_Recall + if (GET_BIT(msg, 16U) || GET_BIT(msg, 17U)) { + tx = false; + } + } + + return tx; +} + +const safety_hooks volkswagen_pq_hooks = { + .init = volkswagen_pq_init, + .rx = volkswagen_pq_rx_hook, + .tx = volkswagen_pq_tx_hook, + .get_counter = volkswagen_pq_get_counter, + .get_checksum = volkswagen_pq_get_checksum, + .compute_checksum = volkswagen_pq_compute_checksum, +}; diff --git a/opendbc_repo/opendbc/safety/safety.h b/opendbc_repo/opendbc/safety/safety.h new file mode 100644 index 0000000000..d784bf5ffc --- /dev/null +++ b/opendbc_repo/opendbc/safety/safety.h @@ -0,0 +1,532 @@ +#pragma once + +#include "opendbc/safety/helpers.h" +#include "opendbc/safety/lateral.h" +#include "opendbc/safety/longitudinal.h" +#include "opendbc/safety/declarations.h" +#include "opendbc/safety/can.h" + +// all the safety modes +#include "opendbc/safety/modes/defaults.h" +#include "opendbc/safety/modes/honda.h" +#include "opendbc/safety/modes/toyota.h" +#include "opendbc/safety/modes/tesla.h" +#include "opendbc/safety/modes/gm.h" +#include "opendbc/safety/modes/ford.h" +#include "opendbc/safety/modes/hyundai.h" +#include "opendbc/safety/modes/chrysler.h" +#include "opendbc/safety/modes/rivian.h" +#include "opendbc/safety/modes/subaru.h" +#include "opendbc/safety/modes/subaru_preglobal.h" +#include "opendbc/safety/modes/mazda.h" +#include "opendbc/safety/modes/nissan.h" +#include "opendbc/safety/modes/volkswagen_mqb.h" +#include "opendbc/safety/modes/volkswagen_pq.h" +#include "opendbc/safety/modes/elm327.h" +#include "opendbc/safety/modes/body.h" +#include "opendbc/safety/modes/psa.h" +#include "opendbc/safety/modes/hyundai_canfd.h" + +uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) { + uint32_t ret = 0U; + for (int i = 0; i < len; i++) { + const uint32_t shift = i * 8; + ret |= (((uint32_t)msg->data[start + i]) << shift); + } + return ret; +} + +const int MAX_WRONG_COUNTERS = 5; + +// This can be set by the safety hooks +bool controls_allowed = false; +bool relay_malfunction = false; +bool gas_pressed = false; +bool gas_pressed_prev = false; +bool brake_pressed = false; +bool brake_pressed_prev = false; +bool regen_braking = false; +bool regen_braking_prev = false; +bool steering_disengage; +bool steering_disengage_prev; +bool cruise_engaged_prev = false; +struct sample_t vehicle_speed; +bool vehicle_moving = false; +bool acc_main_on = false; // referred to as "ACC off" in ISO 15622:2018 +int cruise_button_prev = 0; +bool safety_rx_checks_invalid = false; + +// for safety modes with torque steering control +int desired_torque_last = 0; // last desired steer torque +int rt_torque_last = 0; // last desired torque for real time check +int valid_steer_req_count = 0; // counter for steer request bit matching non-zero torque +int invalid_steer_req_count = 0; // counter to allow multiple frames of mismatching torque request bit +struct sample_t torque_meas; // last 6 motor torques produced by the eps +struct sample_t torque_driver; // last 6 driver torques measured +uint32_t ts_torque_check_last = 0; +uint32_t ts_steer_req_mismatch_last = 0; // last timestamp steer req was mismatched with torque + +// state for controls_allowed timeout logic +bool heartbeat_engaged = false; // openpilot enabled, passed in heartbeat USB command +uint32_t heartbeat_engaged_mismatches = 0; // count of mismatches between heartbeat_engaged and controls_allowed + +// for safety modes with angle steering control +uint32_t rt_angle_msgs = 0; +uint32_t ts_angle_check_last = 0; +int desired_angle_last = 0; +struct sample_t angle_meas; // last 6 steer angles/curvatures + + +int alternative_experience = 0; + +// time since safety mode has been changed +uint32_t safety_mode_cnt = 0U; + +uint16_t current_safety_mode = SAFETY_SILENT; +uint16_t current_safety_param = 0; +static const safety_hooks *current_hooks = &nooutput_hooks; +safety_config current_safety_config; + +static void generic_rx_checks(void); +static void stock_ecu_check(bool stock_ecu_detected); + +static bool is_msg_valid(RxCheck addr_list[], int index) { + bool valid = true; + if (index != -1) { + if (!addr_list[index].status.valid_checksum || !addr_list[index].status.valid_quality_flag || (addr_list[index].status.wrong_counters >= MAX_WRONG_COUNTERS)) { + valid = false; + controls_allowed = false; + } + } + return valid; +} + +static int get_addr_check_index(const CANPacket_t *msg, RxCheck addr_list[], const int len) { + int addr = msg->addr; + int length = GET_LEN(msg); + + int index = -1; + for (int i = 0; i < len; i++) { + // if multiple msgs are allowed, determine which one is present on the bus + if (!addr_list[i].status.msg_seen) { + for (uint8_t j = 0U; (j < MAX_ADDR_CHECK_MSGS) && (addr_list[i].msg[j].addr != 0); j++) { + if ((addr == addr_list[i].msg[j].addr) && (msg->bus == addr_list[i].msg[j].bus) && + (length == addr_list[i].msg[j].len)) { + addr_list[i].status.index = j; + addr_list[i].status.msg_seen = true; + break; + } + } + } + + if (addr_list[i].status.msg_seen) { + int idx = addr_list[i].status.index; + if ((addr == addr_list[i].msg[idx].addr) && (msg->bus == addr_list[i].msg[idx].bus) && + (length == addr_list[i].msg[idx].len)) { + index = i; + break; + } + } + } + return index; +} + +static void update_addr_timestamp(RxCheck addr_list[], int index) { + if (index != -1) { + uint32_t ts = microsecond_timer_get(); + addr_list[index].status.last_timestamp = ts; + } +} + +static void update_counter(RxCheck addr_list[], int index, uint8_t counter) { + if (index != -1) { + uint8_t expected_counter = (addr_list[index].status.last_counter + 1U) % (addr_list[index].msg[addr_list[index].status.index].max_counter + 1U); + addr_list[index].status.wrong_counters += (expected_counter == counter) ? -1 : 1; + addr_list[index].status.wrong_counters = SAFETY_CLAMP(addr_list[index].status.wrong_counters, 0, MAX_WRONG_COUNTERS); + addr_list[index].status.last_counter = counter; + } +} + +static bool rx_msg_safety_check(const CANPacket_t *msg, + const safety_config *cfg, + const safety_hooks *safety_hooks) { + + int index = get_addr_check_index(msg, cfg->rx_checks, cfg->rx_checks_len); + update_addr_timestamp(cfg->rx_checks, index); + + if (index != -1) { + // checksum check + if ((safety_hooks->get_checksum != NULL) && (safety_hooks->compute_checksum != NULL) && !cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_checksum) { + uint32_t checksum = safety_hooks->get_checksum(msg); + uint32_t checksum_comp = safety_hooks->compute_checksum(msg); + cfg->rx_checks[index].status.valid_checksum = checksum_comp == checksum; + } else { + cfg->rx_checks[index].status.valid_checksum = cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_checksum; + } + + // counter check + if ((safety_hooks->get_counter != NULL) && (cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].max_counter > 0U)) { + uint8_t counter = safety_hooks->get_counter(msg); + update_counter(cfg->rx_checks, index, counter); + } else { + cfg->rx_checks[index].status.wrong_counters = cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_counter ? 0 : MAX_WRONG_COUNTERS; + } + + // quality flag check + if ((safety_hooks->get_quality_flag_valid != NULL) && !cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_quality_flag) { + cfg->rx_checks[index].status.valid_quality_flag = safety_hooks->get_quality_flag_valid(msg); + } else { + cfg->rx_checks[index].status.valid_quality_flag = cfg->rx_checks[index].msg[cfg->rx_checks[index].status.index].ignore_quality_flag; + } + } + return is_msg_valid(cfg->rx_checks, index); +} + +bool safety_rx_hook(const CANPacket_t *msg) { + bool controls_allowed_prev = controls_allowed; + + bool valid = rx_msg_safety_check(msg, ¤t_safety_config, current_hooks); + bool whitelisted = get_addr_check_index(msg, current_safety_config.rx_checks, current_safety_config.rx_checks_len) != -1; + if (valid && whitelisted) { + current_hooks->rx(msg); + } + + // Handles gas, brake, and regen paddle + generic_rx_checks(); + + // the relay malfunction hook runs on all incoming rx messages. + // check all applicable tx msgs for liveness on sending bus. + // used to detect a relay malfunction or control messages from disabled ECUs like the radar + const int addr = msg->addr; + for (int i = 0; i < current_safety_config.tx_msgs_len; i++) { + const CanMsg *m = ¤t_safety_config.tx_msgs[i]; + if (m->check_relay) { + stock_ecu_check((m->addr == addr) && (m->bus == msg->bus)); + } + } + + // reset mismatches on rising edge of controls_allowed to avoid rare race condition + if (controls_allowed && !controls_allowed_prev) { + heartbeat_engaged_mismatches = 0; + } + + return valid; +} + +static bool tx_msg_safety_check(const CANPacket_t *msg, const CanMsg msg_list[], int len) { + int addr = msg->addr; + int length = GET_LEN(msg); + + bool whitelisted = false; + for (int i = 0; i < len; i++) { + if ((addr == msg_list[i].addr) && (msg->bus == msg_list[i].bus) && (length == msg_list[i].len)) { + whitelisted = true; + break; + } + } + return whitelisted; +} + +bool safety_tx_hook(CANPacket_t *msg) { + bool whitelisted = tx_msg_safety_check(msg, current_safety_config.tx_msgs, current_safety_config.tx_msgs_len); + if ((current_safety_mode == SAFETY_ALLOUTPUT) || (current_safety_mode == SAFETY_ELM327)) { + whitelisted = true; + } + + bool safety_allowed = false; + if (whitelisted) { + safety_allowed = current_hooks->tx(msg); + } + + return !relay_malfunction && whitelisted && safety_allowed; +} + +static int get_fwd_bus(int bus_num) { + int destination_bus; + if (bus_num == 0) { + destination_bus = 2; + } else if (bus_num == 2) { + destination_bus = 0; + } else { + destination_bus = -1; + } + return destination_bus; +} + +int safety_fwd_hook(int bus_num, int addr) { + bool blocked = relay_malfunction || current_safety_config.disable_forwarding; + + // Block messages that are being checked for relay malfunctions. Safety modes can opt out of this + // in the case of selective AEB forwarding + const int destination_bus = get_fwd_bus(bus_num); + if (!blocked) { + for (int i = 0; i < current_safety_config.tx_msgs_len; i++) { + const CanMsg *m = ¤t_safety_config.tx_msgs[i]; + if (m->check_relay && !m->disable_static_blocking && (m->addr == addr) && (m->bus == (unsigned int)destination_bus)) { + blocked = true; + break; + } + } + } + + if (!blocked && (current_hooks->fwd != NULL)) { + blocked = current_hooks->fwd(bus_num, addr); + } + + return blocked ? -1 : destination_bus; +} + +// Given a CRC-8 poly, generate a static lookup table to use with a fast CRC-8 +// algorithm. Called at init time for safety modes using CRC-8. +void gen_crc_lookup_table_8(uint8_t poly, uint8_t crc_lut[]) { + for (uint16_t i = 0U; i <= 0xFFU; i++) { + uint8_t crc = (uint8_t)i; + for (int j = 0; j < 8; j++) { + if ((crc & 0x80U) != 0U) { + crc = (uint8_t)((crc << 1) ^ poly); + } else { + crc <<= 1; + } + } + crc_lut[i] = crc; + } +} + +void gen_crc_lookup_table_16(uint16_t poly, uint16_t crc_lut[]) { + for (uint16_t i = 0; i < 256U; i++) { + uint16_t crc = i << 8U; + for (uint16_t j = 0; j < 8U; j++) { + if ((crc & 0x8000U) != 0U) { + crc = (uint16_t)((crc << 1) ^ poly); + } else { + crc <<= 1; + } + } + crc_lut[i] = crc; + } +} + +// 1Hz safety function called by main. Now just a check for lagging safety messages +void safety_tick(const safety_config *cfg) { + const uint8_t MAX_MISSED_MSGS = 10U; + bool rx_checks_invalid = false; + uint32_t ts = microsecond_timer_get(); + if (cfg != NULL) { + for (int i=0; i < cfg->rx_checks_len; i++) { + uint32_t elapsed_time = safety_get_ts_elapsed(ts, cfg->rx_checks[i].status.last_timestamp); + // lag threshold is max of: 1s and MAX_MISSED_MSGS * expected timestep. + // Quite conservative to not risk false triggers. + // 2s of lag is worse case, since the function is called at 1Hz + uint32_t timestep = 1e6 / cfg->rx_checks[i].msg[cfg->rx_checks[i].status.index].frequency; + bool lagging = elapsed_time > SAFETY_MAX(timestep * MAX_MISSED_MSGS, 1e6); + cfg->rx_checks[i].status.lagging = lagging; + if (lagging) { + controls_allowed = false; + } + + if (lagging || !is_msg_valid(cfg->rx_checks, i)) { + rx_checks_invalid = true; + } + } + } + + safety_rx_checks_invalid = rx_checks_invalid; +} + +static void relay_malfunction_set(void) { + relay_malfunction = true; +} + +static void generic_rx_checks(void) { + gas_pressed_prev = gas_pressed; + + // exit controls on rising edge of brake press + if (brake_pressed && (!brake_pressed_prev || vehicle_moving)) { + controls_allowed = false; + } + brake_pressed_prev = brake_pressed; + + // exit controls on rising edge of regen paddle + if (regen_braking && (!regen_braking_prev || vehicle_moving)) { + controls_allowed = false; + } + regen_braking_prev = regen_braking; + + // exit controls on rising edge of steering override/disengage + if (steering_disengage && !steering_disengage_prev) { + controls_allowed = false; + } + steering_disengage_prev = steering_disengage; +} + +static void stock_ecu_check(bool stock_ecu_detected) { + // allow 1s of transition timeout after relay changes state before assessing malfunctioning + const uint32_t RELAY_TRNS_TIMEOUT = 1U; + + // check if stock ECU is on bus broken by car harness + if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && stock_ecu_detected) { + relay_malfunction_set(); + } +} + +static void relay_malfunction_reset(void) { + relay_malfunction = false; +} + +// resets values and min/max for sample_t struct +static void reset_sample(struct sample_t *sample) { + for (int i = 0; i < MAX_SAMPLE_VALS; i++) { + sample->values[i] = 0; + } + update_sample(sample, 0); +} + +int set_safety_hooks(uint16_t mode, uint16_t param) { + const safety_hook_config safety_hook_registry[] = { + {SAFETY_SILENT, &nooutput_hooks}, + {SAFETY_HONDA_NIDEC, &honda_nidec_hooks}, + {SAFETY_TOYOTA, &toyota_hooks}, + {SAFETY_ELM327, &elm327_hooks}, + {SAFETY_GM, &gm_hooks}, + {SAFETY_HONDA_BOSCH, &honda_bosch_hooks}, + {SAFETY_HYUNDAI, &hyundai_hooks}, + {SAFETY_CHRYSLER, &chrysler_hooks}, + {SAFETY_SUBARU, &subaru_hooks}, + {SAFETY_VOLKSWAGEN_MQB, &volkswagen_mqb_hooks}, + {SAFETY_NISSAN, &nissan_hooks}, + {SAFETY_NOOUTPUT, &nooutput_hooks}, + {SAFETY_HYUNDAI_LEGACY, &hyundai_legacy_hooks}, + {SAFETY_MAZDA, &mazda_hooks}, + {SAFETY_BODY, &body_hooks}, + {SAFETY_FORD, &ford_hooks}, + {SAFETY_RIVIAN, &rivian_hooks}, + {SAFETY_TESLA, &tesla_hooks}, + {SAFETY_HYUNDAI_CANFD, &hyundai_canfd_hooks}, +#ifdef ALLOW_DEBUG + {SAFETY_PSA, &psa_hooks}, + {SAFETY_SUBARU_PREGLOBAL, &subaru_preglobal_hooks}, + {SAFETY_VOLKSWAGEN_PQ, &volkswagen_pq_hooks}, + {SAFETY_ALLOUTPUT, &alloutput_hooks}, +#endif + }; + + // reset state set by safety mode + safety_mode_cnt = 0U; + relay_malfunction = false; + gas_pressed = false; + gas_pressed_prev = false; + brake_pressed = false; + brake_pressed_prev = false; + regen_braking = false; + regen_braking_prev = false; + steering_disengage = false; + steering_disengage_prev = false; + cruise_engaged_prev = false; + vehicle_moving = false; + acc_main_on = false; + cruise_button_prev = 0; + desired_torque_last = 0; + rt_torque_last = 0; + rt_angle_msgs = 0; + ts_angle_check_last = 0; + desired_angle_last = 0; + ts_torque_check_last = 0; + ts_steer_req_mismatch_last = 0; + valid_steer_req_count = 0; + invalid_steer_req_count = 0; + + // reset samples + reset_sample(&vehicle_speed); + reset_sample(&torque_meas); + reset_sample(&torque_driver); + reset_sample(&angle_meas); + + controls_allowed = false; + relay_malfunction_reset(); + safety_rx_checks_invalid = false; + + current_safety_config.rx_checks = NULL; + current_safety_config.rx_checks_len = 0; + current_safety_config.tx_msgs = NULL; + current_safety_config.tx_msgs_len = 0; + current_safety_config.disable_forwarding = false; + + int set_status = -1; // not set + int hook_config_count = sizeof(safety_hook_registry) / sizeof(safety_hook_config); + for (int i = 0; i < hook_config_count; i++) { + if (safety_hook_registry[i].id == mode) { + current_hooks = safety_hook_registry[i].hooks; + current_safety_mode = mode; + current_safety_param = param; + set_status = 0; // set + } + } + if ((set_status == 0) && (current_hooks->init != NULL)) { + safety_config cfg = current_hooks->init(param); + current_safety_config.rx_checks = cfg.rx_checks; + current_safety_config.rx_checks_len = cfg.rx_checks_len; + current_safety_config.tx_msgs = cfg.tx_msgs; + current_safety_config.tx_msgs_len = cfg.tx_msgs_len; + current_safety_config.disable_forwarding = cfg.disable_forwarding; + // reset all dynamic fields in addr struct + for (int j = 0; j < current_safety_config.rx_checks_len; j++) { + current_safety_config.rx_checks[j].status = (RxStatus){0}; + } + } + return set_status; +} + +// convert a trimmed integer to signed 32 bit int +int to_signed(int d, int bits) { + int d_signed = d; + int max_value = (1 << SAFETY_MAX((bits - 1), 0)); + if (d >= max_value) { + d_signed = d - (1 << SAFETY_MAX(bits, 0)); + } + return d_signed; +} + +// given a new sample, update the sample_t struct +void update_sample(struct sample_t *sample, int sample_new) { + for (int i = MAX_SAMPLE_VALS - 1; i > 0; i--) { + sample->values[i] = sample->values[i-1]; + } + sample->values[0] = sample_new; + + // get the minimum and maximum measured samples + sample->min = sample->values[0]; + sample->max = sample->values[0]; + for (int i = 1; i < MAX_SAMPLE_VALS; i++) { + if (sample->values[i] < sample->min) { + sample->min = sample->values[i]; + } + if (sample->values[i] > sample->max) { + sample->max = sample->values[i]; + } + } +} + +int ROUND(float val) { + return val + ((val > 0.0) ? 0.5 : -0.5); +} + +void pcm_cruise_check(bool cruise_engaged) { + // Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages + if (!cruise_engaged) { + controls_allowed = false; + } + if (cruise_engaged && !cruise_engaged_prev) { + controls_allowed = true; + } + cruise_engaged_prev = cruise_engaged; +} + +void speed_mismatch_check(const float speed_2) { + // Disable controls if speeds from two sources are too far apart. + // For safety modes that use speed to adjust torque or angle limits + const float MAX_SPEED_DELTA = 2.0; // m/s + bool is_invalid_speed = SAFETY_ABS(speed_2 - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > MAX_SPEED_DELTA; + if (is_invalid_speed) { + controls_allowed = false; + } +} diff --git a/opendbc_repo/opendbc/safety/tests/__init__.py b/opendbc_repo/opendbc/safety/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/safety/tests/common.py b/opendbc_repo/opendbc/safety/tests/common.py new file mode 100644 index 0000000000..859d28b2f4 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/common.py @@ -0,0 +1,1126 @@ +import os +import abc +import math +import unittest +import importlib +import numpy as np +from collections.abc import Callable + +from opendbc.can import CANPacker +from opendbc.safety import ALTERNATIVE_EXPERIENCE +from opendbc.safety.tests.libsafety import libsafety_py + +MAX_WRONG_COUNTERS = 5 +MAX_SAMPLE_VALS = 6 +VEHICLE_SPEED_FACTOR = 1000 +RT_INTERVAL = 250000 # 250ms + +# Max allowed delta between car speeds +MAX_SPEED_DELTA = 2.0 # m/s + +MessageFunction = Callable[[float], libsafety_py.CANPacket] + + +def sign_of(a): + return 1 if a > 0 else -1 + + +def away_round(x): + # non-banker's/away from zero rounding, C++ CANParser uses this style + return math.floor(x + 0.5) if x >= 0 else math.ceil(x - 0.5) + + +def round_speed(v): + return round(v * VEHICLE_SPEED_FACTOR) / VEHICLE_SPEED_FACTOR + + +def make_msg(bus, addr, length=8, dat=None): + if dat is None: + dat = b'\x00' * length + return libsafety_py.make_CANPacket(addr, bus, dat) + + +class CANPackerSafety(CANPacker): + def make_can_msg_safety(self, name_or_addr, bus, values, fix_checksum=None): + msg = self.make_can_msg(name_or_addr, bus, values) + if fix_checksum is not None: + msg = fix_checksum(msg) + addr, dat, bus = msg + return libsafety_py.make_CANPacket(addr, bus, dat) + + +def add_regen_tests(cls): + """Dynamically adds regen tests for all user brake tests.""" + + # only rx/user brake tests, not brake command + found_tests = [func for func in dir(cls) if func.startswith("test_") and "user_brake" in func] + assert len(found_tests) >= 3, "Failed to detect known brake tests" + + for test in found_tests: + def _make_regen_test(brake_func): + def _regen_test(self): + # only for safety modes with a regen message + if self._user_regen_msg(0) is None: + raise unittest.SkipTest("Safety mode implements no _user_regen_msg") + + getattr(self, brake_func)(self._user_regen_msg, self.safety.get_regen_braking_prev) + return _regen_test + + setattr(cls, test.replace("brake", "regen"), _make_regen_test(test)) + + return cls + + +class SafetyTestBase(unittest.TestCase): + safety: libsafety_py.LibSafety + + @classmethod + def setUpClass(cls): + if cls.__name__ == "SafetyTestBase": + cls.safety = None + raise unittest.SkipTest + + def _reset_safety_hooks(self): + self.safety.set_safety_hooks(self.safety.get_current_safety_mode(), + self.safety.get_current_safety_param()) + + def _rx(self, msg): + return self.safety.safety_rx_hook(msg) + + def _tx(self, msg): + return self.safety.safety_tx_hook(msg) + + def _generic_limit_safety_check(self, msg_function: MessageFunction, min_allowed_value: float, max_allowed_value: float, + min_possible_value: float, max_possible_value: float, test_delta: float = 1, inactive_value: float = 0, + msg_allowed = True, additional_setup: Callable[[float], None] | None = None): + """ + Enforces that a signal within a message is only allowed to be sent within a specific range, min_allowed_value -> max_allowed_value. + Tests the range of min_possible_value -> max_possible_value with a delta of test_delta. + Message is also only allowed to be sent when controls_allowed is true, unless the value is equal to inactive_value. + Message is never allowed if msg_allowed is false, for example when stock longitudinal is enabled and you are sending acceleration requests. + additional_setup is used for extra setup before each _tx, ex: for setting the previous torque for rate limits + """ + + # Ensure that we at least test the allowed_value range + self.assertGreater(max_possible_value, max_allowed_value) + self.assertLessEqual(min_possible_value, min_allowed_value) + + for controls_allowed in [False, True]: + # enforce we don't skip over 0 or inactive + for v in np.concatenate((np.arange(min_possible_value, max_possible_value, test_delta), np.array([0, inactive_value]))): + v = round(v, 2) # floats might not hit exact boundary conditions without rounding + self.safety.set_controls_allowed(controls_allowed) + if additional_setup is not None: + additional_setup(v) + should_tx = controls_allowed and min_allowed_value <= v <= max_allowed_value + should_tx = (should_tx or v == inactive_value) and msg_allowed + self.assertEqual(self._tx(msg_function(v)), should_tx, (controls_allowed, should_tx, v)) + + def _common_measurement_test(self, msg_func: Callable, min_value: float, max_value: float, factor: float, + meas_min_func: Callable[[], int], meas_max_func: Callable[[], int]): + """Tests accurate measurement parsing, and that the struct is reset on safety mode init""" + for val in np.arange(min_value, max_value, 0.5): + for i in range(MAX_SAMPLE_VALS): + self.assertTrue(self._rx(msg_func(val + i * 0.1))) + + # assert close by one decimal place + self.assertAlmostEqual(meas_min_func() / factor, val, delta=0.1) + self.assertAlmostEqual(meas_max_func() / factor - 0.5, val, delta=0.1) + + # ensure sample_t is reset on safety init + self._reset_safety_hooks() + self.assertEqual(meas_min_func(), 0) + self.assertEqual(meas_max_func(), 0) + + +class LongitudinalAccelSafetyTest(SafetyTestBase, abc.ABC): + + LONGITUDINAL = True + MAX_ACCEL: float = 2.0 + MIN_ACCEL: float = -3.5 + INACTIVE_ACCEL: float = 0.0 + + @classmethod + def setUpClass(cls): + if cls.__name__ == "LongitudinalAccelSafetyTest": + cls.safety = None + raise unittest.SkipTest + + @abc.abstractmethod + def _accel_msg(self, accel: float): + pass + + def test_accel_limits_correct(self): + self.assertGreater(self.MAX_ACCEL, 0) + self.assertLess(self.MIN_ACCEL, 0) + + def test_accel_actuation_limits(self): + limits = ((self.MIN_ACCEL, self.MAX_ACCEL, ALTERNATIVE_EXPERIENCE.DEFAULT), + (self.MIN_ACCEL, self.MAX_ACCEL, ALTERNATIVE_EXPERIENCE.RAISE_LONGITUDINAL_LIMITS_TO_ISO_MAX)) + + for min_accel, max_accel, alternative_experience in limits: + # enforce we don't skip over 0 or inactive accel + for accel in np.concatenate((np.arange(min_accel - 1, max_accel + 1, 0.05), [0, self.INACTIVE_ACCEL])): + accel = round(accel, 2) # floats might not hit exact boundary conditions without rounding + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + self.safety.set_alternative_experience(alternative_experience) + if self.LONGITUDINAL: + should_tx = controls_allowed and min_accel <= accel <= max_accel + should_tx = should_tx or accel == self.INACTIVE_ACCEL + else: + should_tx = False + self.assertEqual(should_tx, self._tx(self._accel_msg(accel))) + + +class LongitudinalGasBrakeSafetyTest(SafetyTestBase, abc.ABC): + + MIN_BRAKE: int = 0 + MAX_BRAKE: int | None = None + MAX_POSSIBLE_BRAKE: int | None = None + + MIN_GAS: int = 0 + MAX_GAS: int | None = None + INACTIVE_GAS = 0 + MIN_POSSIBLE_GAS: int = 0. + MAX_POSSIBLE_GAS: int | None = None + + def test_gas_brake_limits_correct(self): + self.assertIsNotNone(self.MAX_POSSIBLE_BRAKE) + self.assertIsNotNone(self.MAX_POSSIBLE_GAS) + + self.assertGreater(self.MAX_BRAKE, self.MIN_BRAKE) + self.assertGreater(self.MAX_GAS, self.MIN_GAS) + + @abc.abstractmethod + def _send_gas_msg(self, gas: int): + pass + + @abc.abstractmethod + def _send_brake_msg(self, brake: int): + pass + + def test_brake_safety_check(self): + self._generic_limit_safety_check(self._send_brake_msg, self.MIN_BRAKE, self.MAX_BRAKE, 0, self.MAX_POSSIBLE_BRAKE, 1) + + def test_gas_safety_check(self): + self._generic_limit_safety_check(self._send_gas_msg, self.MIN_GAS, self.MAX_GAS, self.MIN_POSSIBLE_GAS, self.MAX_POSSIBLE_GAS, 1, self.INACTIVE_GAS) + + +class TorqueSteeringSafetyTestBase(SafetyTestBase, abc.ABC): + + MAX_RATE_UP = 0 + MAX_RATE_DOWN = 0 + MAX_TORQUE_LOOKUP: tuple[list[float], list[int]] = ([0], [0]) + DYNAMIC_MAX_TORQUE = False + MAX_RT_DELTA = 0 + + NO_STEER_REQ_BIT = False + + @classmethod + def setUpClass(cls): + if cls.__name__ == "TorqueSteeringSafetyTestBase": + cls.safety = None + raise unittest.SkipTest + + @property + def MAX_TORQUE(self): + return max(self.MAX_TORQUE_LOOKUP[1]) + + @property + def _torque_speed_range(self): + if not self.DYNAMIC_MAX_TORQUE: + return [0] + else: + # test with more precision inside breakpoint range + min_speed = min(self.MAX_TORQUE_LOOKUP[0]) + max_speed = max(self.MAX_TORQUE_LOOKUP[0]) + return np.concatenate([np.arange(0, min_speed, 5), np.arange(min_speed, max_speed, 0.5), np.arange(max_speed, 40, 5)]) + + def _get_max_torque(self, speed): + # matches safety fudge + torque = int(np.interp(speed - 1, self.MAX_TORQUE_LOOKUP[0], self.MAX_TORQUE_LOOKUP[1]) + 1) + return min(torque, self.MAX_TORQUE) + + @abc.abstractmethod + def _torque_cmd_msg(self, torque, steer_req=1): + pass + + @abc.abstractmethod + def _speed_msg(self, speed): + pass + + def _reset_speed_measurement(self, speed): + for _ in range(MAX_SAMPLE_VALS): + self._rx(self._speed_msg(speed)) + + def _set_prev_torque(self, t): + self.safety.set_desired_torque_last(t) + self.safety.set_rt_torque_last(t) + + def test_steer_safety_check(self): + for speed in self._torque_speed_range: + self._reset_speed_measurement(speed) + max_torque = self._get_max_torque(speed) + for enabled in [0, 1]: + for t in range(int(-max_torque * 1.5), int(max_torque * 1.5)): + self.safety.set_controls_allowed(enabled) + self._set_prev_torque(t) + if abs(t) > max_torque or (not enabled and abs(t) > 0): + self.assertFalse(self._tx(self._torque_cmd_msg(t))) + else: + self.assertTrue(self._tx(self._torque_cmd_msg(t))) + + def test_non_realtime_limit_up(self): + self.safety.set_controls_allowed(True) + + self._set_prev_torque(0) + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP))) + self._set_prev_torque(0) + self.assertTrue(self._tx(self._torque_cmd_msg(-self.MAX_RATE_UP))) + + self._set_prev_torque(0) + self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP + 1))) + self.safety.set_controls_allowed(True) + self._set_prev_torque(0) + self.assertFalse(self._tx(self._torque_cmd_msg(-self.MAX_RATE_UP - 1))) + + def test_steer_req_bit(self): + """Asserts all torque safety modes check the steering request bit""" + if self.NO_STEER_REQ_BIT: + raise unittest.SkipTest("No steering request bit") + + self.safety.set_controls_allowed(True) + self._set_prev_torque(self.MAX_TORQUE) + + # Send torque successfully, then only drop the request bit and ensure it stays blocked + for _ in range(10): + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, 1))) + + self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, 0))) + for _ in range(10): + self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, 1))) + + +class SteerRequestCutSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): + + @classmethod + def setUpClass(cls): + if cls.__name__ == "SteerRequestCutSafetyTest": + cls.safety = None + raise unittest.SkipTest + + # Safety around steering request bit mismatch tolerance + MIN_VALID_STEERING_FRAMES: int + MAX_INVALID_STEERING_FRAMES: int + STEER_STEP: int = 1 + + @property + def MIN_VALID_STEERING_RT_INTERVAL(self): + # a ~10% buffer + return int((self.MIN_VALID_STEERING_FRAMES + 1) * self.STEER_STEP * 10000 * 0.9) + + def test_steer_req_bit_frames(self): + """ + Certain safety modes implement some tolerance on their steer request bits matching the + requested torque to avoid a steering fault or lockout and maintain torque. This tests: + - We can't cut torque for more than one frame + - We can't cut torque until at least the minimum number of matching steer_req messages + - We can always recover from violations if steer_req=1 + """ + + for min_valid_steer_frames in range(self.MIN_VALID_STEERING_FRAMES * 2): + # Reset match count and rt timer to allow cut (valid_steer_req_count, ts_steer_req_mismatch_last) + self.safety.init_tests() + self.safety.set_timer(self.MIN_VALID_STEERING_RT_INTERVAL) + + # Allow torque cut + self.safety.set_controls_allowed(True) + self._set_prev_torque(self.MAX_TORQUE) + for _ in range(min_valid_steer_frames): + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=1))) + + # should tx if we've sent enough valid frames, and we're not cutting torque for too many frames consecutively + should_tx = min_valid_steer_frames >= self.MIN_VALID_STEERING_FRAMES + for idx in range(self.MAX_INVALID_STEERING_FRAMES * 2): + tx = self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0)) + self.assertEqual(should_tx and idx < self.MAX_INVALID_STEERING_FRAMES, tx) + + # Keep blocking after one steer_req mismatch + for _ in range(100): + self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) + + # Make sure we can recover + self.assertTrue(self._tx(self._torque_cmd_msg(0, steer_req=1))) + self._set_prev_torque(self.MAX_TORQUE) + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=1))) + + def test_steer_req_bit_multi_invalid(self): + """ + For safety modes allowing multiple consecutive invalid frames, this ensures that once a valid frame + is sent after an invalid frame (even without sending the max number of allowed invalid frames), + all counters are reset. + """ + for max_invalid_steer_frames in range(1, self.MAX_INVALID_STEERING_FRAMES * 2): + self.safety.init_tests() + self.safety.set_timer(self.MIN_VALID_STEERING_RT_INTERVAL) + + # Allow torque cut + self.safety.set_controls_allowed(True) + self._set_prev_torque(self.MAX_TORQUE) + for _ in range(self.MIN_VALID_STEERING_FRAMES): + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=1))) + + # Send partial amount of allowed invalid frames + for idx in range(max_invalid_steer_frames): + should_tx = idx < self.MAX_INVALID_STEERING_FRAMES + self.assertEqual(should_tx, self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) + + # Send one valid frame, and subsequent invalid should now be blocked + self._set_prev_torque(self.MAX_TORQUE) + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=1))) + for _ in range(self.MIN_VALID_STEERING_FRAMES + 1): + self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) + + def test_steer_req_bit_realtime(self): + """ + Realtime safety for cutting steer request bit. This tests: + - That we allow messages with mismatching steer request bit if time from last is >= MIN_VALID_STEERING_RT_INTERVAL + - That frame mismatch safety does not interfere with this test + """ + for rt_us in np.arange(self.MIN_VALID_STEERING_RT_INTERVAL - 50000, self.MIN_VALID_STEERING_RT_INTERVAL + 50000, 10000): + # Reset match count and rt timer (valid_steer_req_count, ts_steer_req_mismatch_last) + self.safety.init_tests() + + # Make sure valid_steer_req_count doesn't affect this test + self.safety.set_controls_allowed(True) + self._set_prev_torque(self.MAX_TORQUE) + for _ in range(self.MIN_VALID_STEERING_FRAMES): + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=1))) + + # Normally, sending MIN_VALID_STEERING_FRAMES valid frames should always allow + self.safety.set_timer(max(rt_us, 0)) + should_tx = rt_us >= self.MIN_VALID_STEERING_RT_INTERVAL + for _ in range(self.MAX_INVALID_STEERING_FRAMES): + self.assertEqual(should_tx, self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) + + # Keep blocking after one steer_req mismatch + for _ in range(100): + self.assertFalse(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=0))) + + # Make sure we can recover + self.assertTrue(self._tx(self._torque_cmd_msg(0, steer_req=1))) + self._set_prev_torque(self.MAX_TORQUE) + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_TORQUE, steer_req=1))) + + +class DriverTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): + + DRIVER_TORQUE_ALLOWANCE = 0 + DRIVER_TORQUE_FACTOR = 0 + + @classmethod + def setUpClass(cls): + if cls.__name__ == "DriverTorqueSteeringSafetyTest": + cls.safety = None + raise unittest.SkipTest + + @abc.abstractmethod + def _torque_driver_msg(self, torque): + pass + + def _reset_torque_driver_measurement(self, torque): + for _ in range(MAX_SAMPLE_VALS): + self._rx(self._torque_driver_msg(torque)) + + def test_non_realtime_limit_up(self): + self._reset_torque_driver_measurement(0) + super().test_non_realtime_limit_up() + + def test_against_torque_driver(self): + # Tests down limits and driver torque blending + self.safety.set_controls_allowed(True) + + for speed in self._torque_speed_range: + self._reset_speed_measurement(speed) + max_torque = self._get_max_torque(speed) + + # Cannot stay at MAX_TORQUE if above DRIVER_TORQUE_ALLOWANCE + for sign in [-1, 1]: + for driver_torque in np.arange(0, self.DRIVER_TORQUE_ALLOWANCE * 2, 1): + self._reset_torque_driver_measurement(-driver_torque * sign) + self._set_prev_torque(max_torque * sign) + should_tx = abs(driver_torque) <= self.DRIVER_TORQUE_ALLOWANCE + self.assertEqual(should_tx, self._tx(self._torque_cmd_msg(max_torque * sign))) + + # arbitrary high driver torque to ensure max steer torque is allowed + max_driver_torque = int(max_torque / self.DRIVER_TORQUE_FACTOR + self.DRIVER_TORQUE_ALLOWANCE + 1) + + # spot check some individual cases + for sign in [-1, 1]: + # Ensure we wind down factor units for every unit above allowance + driver_torque = (self.DRIVER_TORQUE_ALLOWANCE + 10) * sign + torque_desired = (max_torque - 10 * self.DRIVER_TORQUE_FACTOR) * sign + delta = 1 * sign + self._set_prev_torque(torque_desired) + self._reset_torque_driver_measurement(-driver_torque) + self.assertTrue(self._tx(self._torque_cmd_msg(torque_desired))) + self._set_prev_torque(torque_desired + delta) + self._reset_torque_driver_measurement(-driver_torque) + self.assertFalse(self._tx(self._torque_cmd_msg(torque_desired + delta))) + + # If we're well past the allowance, minimum wind down is MAX_RATE_DOWN + self._set_prev_torque(max_torque * sign) + self._reset_torque_driver_measurement(-max_driver_torque * sign) + self.assertTrue(self._tx(self._torque_cmd_msg((max_torque - self.MAX_RATE_DOWN) * sign))) + self._set_prev_torque(max_torque * sign) + self._reset_torque_driver_measurement(-max_driver_torque * sign) + self.assertTrue(self._tx(self._torque_cmd_msg(0))) + self._set_prev_torque(max_torque * sign) + self._reset_torque_driver_measurement(-max_driver_torque * sign) + self.assertFalse(self._tx(self._torque_cmd_msg((max_torque - self.MAX_RATE_DOWN + 1) * sign))) + + def test_realtime_limits(self): + self.safety.set_controls_allowed(True) + + for sign in [-1, 1]: + self.safety.init_tests() + self._set_prev_torque(0) + self._reset_torque_driver_measurement(0) + for t in np.arange(0, self.MAX_RT_DELTA, 1): + t *= sign + self.assertTrue(self._tx(self._torque_cmd_msg(t))) + self.assertFalse(self._tx(self._torque_cmd_msg(sign * (self.MAX_RT_DELTA + 1)))) + + self._set_prev_torque(0) + for t in np.arange(0, self.MAX_RT_DELTA, 1): + t *= sign + self.assertTrue(self._tx(self._torque_cmd_msg(t))) + + # Increase timer to update rt_torque_last + self.safety.set_timer(RT_INTERVAL + 1) + self.assertTrue(self._tx(self._torque_cmd_msg(sign * (self.MAX_RT_DELTA - 1)))) + self.assertTrue(self._tx(self._torque_cmd_msg(sign * (self.MAX_RT_DELTA + 1)))) + + def test_reset_driver_torque_measurements(self): + # Tests that the driver torque measurement sample_t is reset on safety mode init + for t in np.linspace(-self.MAX_TORQUE, self.MAX_TORQUE, MAX_SAMPLE_VALS): + self.assertTrue(self._rx(self._torque_driver_msg(t))) + + self.assertNotEqual(self.safety.get_torque_driver_min(), 0) + self.assertNotEqual(self.safety.get_torque_driver_max(), 0) + + self._reset_safety_hooks() + self.assertEqual(self.safety.get_torque_driver_min(), 0) + self.assertEqual(self.safety.get_torque_driver_max(), 0) + + +class MotorTorqueSteeringSafetyTest(TorqueSteeringSafetyTestBase, abc.ABC): + + MAX_TORQUE_ERROR = 0 + TORQUE_MEAS_TOLERANCE = 0 + + @classmethod + def setUpClass(cls): + if cls.__name__ == "MotorTorqueSteeringSafetyTest": + cls.safety = None + raise unittest.SkipTest + + @abc.abstractmethod + def _torque_meas_msg(self, torque): + pass + + def _set_prev_torque(self, t): + super()._set_prev_torque(t) + self.safety.set_torque_meas(t, t) + + def test_torque_absolute_limits(self): + for speed in self._torque_speed_range: + self._reset_speed_measurement(speed) + max_torque = self._get_max_torque(speed) + for controls_allowed in [True, False]: + for torque in np.arange(-max_torque - 1000, max_torque + 1000, self.MAX_RATE_UP): + self.safety.set_controls_allowed(controls_allowed) + self.safety.set_rt_torque_last(torque) + self.safety.set_torque_meas(torque, torque) + self.safety.set_desired_torque_last(torque - self.MAX_RATE_UP) + + if controls_allowed: + send = (-max_torque <= torque <= max_torque) + else: + send = torque == 0 + + self.assertEqual(send, self._tx(self._torque_cmd_msg(torque))) + + def test_non_realtime_limit_down(self): + self.safety.set_controls_allowed(True) + + for speed in self._torque_speed_range: + self._reset_speed_measurement(speed) + max_torque = self._get_max_torque(speed) + + torque_meas = max_torque - self.MAX_TORQUE_ERROR - 50 + + self.safety.set_rt_torque_last(max_torque) + self.safety.set_torque_meas(torque_meas, torque_meas) + self.safety.set_desired_torque_last(max_torque) + self.assertTrue(self._tx(self._torque_cmd_msg(max_torque - self.MAX_RATE_DOWN))) + + self.safety.set_rt_torque_last(max_torque) + self.safety.set_torque_meas(torque_meas, torque_meas) + self.safety.set_desired_torque_last(max_torque) + self.assertFalse(self._tx(self._torque_cmd_msg(max_torque - self.MAX_RATE_DOWN + 1))) + + def test_exceed_torque_sensor(self): + self.safety.set_controls_allowed(True) + + for sign in [-1, 1]: + self._set_prev_torque(0) + for t in np.arange(0, self.MAX_TORQUE_ERROR + 2, 2): # step needs to be smaller than MAX_TORQUE_ERROR + t *= sign + self.assertTrue(self._tx(self._torque_cmd_msg(t))) + + self.assertFalse(self._tx(self._torque_cmd_msg(sign * (self.MAX_TORQUE_ERROR + 2)))) + + def test_realtime_limit_up(self): + self.safety.set_controls_allowed(True) + + for sign in [-1, 1]: + self.safety.init_tests() + self._set_prev_torque(0) + for t in np.arange(0, self.MAX_RT_DELTA + 1, 1): + t *= sign + self.safety.set_torque_meas(t, t) + self.assertTrue(self._tx(self._torque_cmd_msg(t))) + self.assertFalse(self._tx(self._torque_cmd_msg(sign * (self.MAX_RT_DELTA + 1)))) + + self._set_prev_torque(0) + for t in np.arange(0, self.MAX_RT_DELTA + 1, 1): + t *= sign + self.safety.set_torque_meas(t, t) + self.assertTrue(self._tx(self._torque_cmd_msg(t))) + + # Increase timer to update rt_torque_last + self.safety.set_timer(RT_INTERVAL + 1) + self.assertTrue(self._tx(self._torque_cmd_msg(sign * self.MAX_RT_DELTA))) + self.assertTrue(self._tx(self._torque_cmd_msg(sign * (self.MAX_RT_DELTA + 1)))) + + def test_torque_measurements(self): + trq = 50 + for t in [trq, -trq, 0, 0, 0, 0]: + self._rx(self._torque_meas_msg(t)) + + max_range = range(trq, trq + self.TORQUE_MEAS_TOLERANCE + 1) + min_range = range(-(trq + self.TORQUE_MEAS_TOLERANCE), -trq + 1) + self.assertTrue(self.safety.get_torque_meas_min() in min_range) + self.assertTrue(self.safety.get_torque_meas_max() in max_range) + + max_range = range(self.TORQUE_MEAS_TOLERANCE + 1) + min_range = range(-(trq + self.TORQUE_MEAS_TOLERANCE), -trq + 1) + self._rx(self._torque_meas_msg(0)) + self.assertTrue(self.safety.get_torque_meas_min() in min_range) + self.assertTrue(self.safety.get_torque_meas_max() in max_range) + + max_range = range(self.TORQUE_MEAS_TOLERANCE + 1) + min_range = range(-self.TORQUE_MEAS_TOLERANCE, 0 + 1) + self._rx(self._torque_meas_msg(0)) + self.assertTrue(self.safety.get_torque_meas_min() in min_range) + self.assertTrue(self.safety.get_torque_meas_max() in max_range) + + def test_reset_torque_measurements(self): + # Tests that the torque measurement sample_t is reset on safety mode init + for t in np.linspace(-self.MAX_TORQUE, self.MAX_TORQUE, MAX_SAMPLE_VALS): + self.assertTrue(self._rx(self._torque_meas_msg(t))) + + self.assertNotEqual(self.safety.get_torque_meas_min(), 0) + self.assertNotEqual(self.safety.get_torque_meas_max(), 0) + + self._reset_safety_hooks() + self.assertEqual(self.safety.get_torque_meas_min(), 0) + self.assertEqual(self.safety.get_torque_meas_max(), 0) + + +class VehicleSpeedSafetyTest(SafetyTestBase): + @classmethod + def setUpClass(cls): + if cls.__name__ == "VehicleSpeedSafetyTest": + cls.safety = None + raise unittest.SkipTest + + @abc.abstractmethod + def _speed_msg(self, speed): + pass + + def test_vehicle_speed_measurements(self): + # TODO: lower tolerance on these tests + self._common_measurement_test(self._speed_msg, 0, 80, 1, self.safety.get_vehicle_speed_min, self.safety.get_vehicle_speed_max) + + +class AngleSteeringSafetyTest(VehicleSpeedSafetyTest): + + STEER_ANGLE_MAX: float = 300 + STEER_ANGLE_TEST_MAX: float = None + DEG_TO_CAN: float + ANGLE_RATE_BP: list[float] + ANGLE_RATE_UP: list[float] # windup limit + ANGLE_RATE_DOWN: list[float] # unwind limit + + # Real time limits + LATERAL_FREQUENCY: int = -1 # Hz + + @classmethod + def setUpClass(cls): + if cls.__name__ == "AngleSteeringSafetyTest": + cls.safety = None + raise unittest.SkipTest + + @abc.abstractmethod + def _angle_cmd_msg(self, angle: float, enabled: bool, increment_timer: bool = True): + pass + + @abc.abstractmethod + def _angle_meas_msg(self, angle: float): + pass + + def _get_steer_cmd_angle_max(self, speed): + return self.STEER_ANGLE_MAX + + def _set_prev_desired_angle(self, t): + t = round(t * self.DEG_TO_CAN) + self.safety.set_desired_angle_last(t) + + def _reset_angle_measurement(self, angle): + for _ in range(MAX_SAMPLE_VALS): + self._rx(self._angle_meas_msg(angle)) + + def _reset_speed_measurement(self, speed): + for _ in range(MAX_SAMPLE_VALS): + self._rx(self._speed_msg(speed)) + + def test_steering_angle_measurements(self): + self._common_measurement_test(self._angle_meas_msg, -self.STEER_ANGLE_MAX, self.STEER_ANGLE_MAX, self.DEG_TO_CAN, + self.safety.get_angle_meas_min, self.safety.get_angle_meas_max) + + def test_angle_cmd_when_enabled(self): + # when controls are allowed, angle cmd rate limit is enforced + speeds = [0., 1., 5., 10., 15., 50.] + # TODO: what should CANPacker do here? we should also have good coverage checks on this + if self.STEER_ANGLE_TEST_MAX is None: + self.STEER_ANGLE_TEST_MAX = self.STEER_ANGLE_MAX * 2 + angles = np.concatenate((np.arange(-self.STEER_ANGLE_TEST_MAX, self.STEER_ANGLE_TEST_MAX, 5), [0])) + for a in angles: + for s in speeds: + max_delta_up = np.interp(s, self.ANGLE_RATE_BP, self.ANGLE_RATE_UP) + max_delta_down = np.interp(s, self.ANGLE_RATE_BP, self.ANGLE_RATE_DOWN) + + # first test against false positives + self._reset_angle_measurement(a) + self._reset_speed_measurement(s) + + self._set_prev_desired_angle(a) + self.safety.set_controls_allowed(1) + + # Stay within limits + # Up + self.assertTrue(self._tx(self._angle_cmd_msg(a + sign_of(a) * max_delta_up, True))) + self.assertTrue(self.safety.get_controls_allowed()) + + # Don't change + self.assertTrue(self._tx(self._angle_cmd_msg(a, True))) + self.assertTrue(self.safety.get_controls_allowed()) + + # Down + self.assertTrue(self._tx(self._angle_cmd_msg(a - sign_of(a) * max_delta_down, True))) + self.assertTrue(self.safety.get_controls_allowed()) + + # Inject too high rates + # Up + self.assertFalse(self._tx(self._angle_cmd_msg(a + sign_of(a) * (max_delta_up + 1.1), True))) + + # Don't change + self.safety.set_controls_allowed(1) + self._set_prev_desired_angle(a) + self.assertTrue(self.safety.get_controls_allowed()) + self.assertTrue(self._tx(self._angle_cmd_msg(a, True))) + self.assertTrue(self.safety.get_controls_allowed()) + + # Down + self.assertFalse(self._tx(self._angle_cmd_msg(a - sign_of(a) * (max_delta_down + 1.1), True))) + + # Check desired steer should be the same as steer angle when controls are off + self.safety.set_controls_allowed(0) + should_tx = abs(a) <= abs(self.STEER_ANGLE_MAX) + self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(a, False))) + + def test_angle_cmd_when_disabled(self): + # Tests that only angles close to the meas are allowed while + # steer actuation bit is 0, regardless of controls allowed. + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + + for steer_control_enabled in (True, False): + for angle_meas in np.arange(-90, 91, 10): + self._reset_angle_measurement(angle_meas) + + for angle_cmd in np.arange(-90, 91, 10): + self._set_prev_desired_angle(angle_cmd) + + # controls_allowed is checked if actuation bit is 1, else the angle must be close to meas (inactive) + should_tx = controls_allowed if steer_control_enabled else angle_cmd == angle_meas + self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(angle_cmd, steer_control_enabled))) + + def test_angle_violation(self): + # If violation occurs, angle cmd is blocked until reset to 0. Matches behavior of torque safety modes + self.safety.set_controls_allowed(True) + + for speed in (0., 1., 5., 10., 15., 50.): + self._tx(self._angle_cmd_msg(0, True)) + self._reset_speed_measurement(speed) + + for _ in range(20): + self.assertFalse(self._tx(self._angle_cmd_msg(self._get_steer_cmd_angle_max(speed), True))) + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) + + def test_rt_limits(self): + # TODO: remove and check all safety modes + if self.LATERAL_FREQUENCY == -1: + raise unittest.SkipTest("No real time limits") + + # Angle safety enforces real time limits by checking the message send frequency in a 250ms time window + self.safety.set_timer(0) + self.safety.set_controls_allowed(True) + max_rt_msgs = int(self.LATERAL_FREQUENCY * RT_INTERVAL / 1e6 * 1.2 + 1) # 1.2x buffer + + for i in range(max_rt_msgs * 2): + should_tx = i <= max_rt_msgs + self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(0, True, increment_timer=False))) + + # One under RT interval should do nothing + self.safety.set_timer(RT_INTERVAL - 1) + for _ in range(5): + self.assertFalse(self._tx(self._angle_cmd_msg(0, True, increment_timer=False))) + + # Increment timer and send 1 message to reset RT window + self.safety.set_timer(RT_INTERVAL) + self.assertFalse(self._tx(self._angle_cmd_msg(0, True, increment_timer=False))) + for _ in range(5): + self.assertTrue(self._tx(self._angle_cmd_msg(0, True, increment_timer=False))) + + +class SafetyTest(SafetyTestBase): + TX_MSGS: list[list[int]] | None = None + SCANNED_ADDRS = [*range(0x800), # Entire 11-bit CAN address space + *range(0x18DA00F1, 0x18DB00F1, 0x100), # 29-bit UDS physical addressing + *range(0x18DB00F1, 0x18DC00F1, 0x100), # 29-bit UDS functional addressing + *range(0x3300, 0x3400)] # Honda + FWD_BLACKLISTED_ADDRS: dict[int, list[int]] = {} # {bus: [addr]} + FWD_BUS_LOOKUP: dict[int, int] = {0: 2, 2: 0} + + @classmethod + def setUpClass(cls): + if cls.__name__ == "SafetyTest" or cls.__name__.endswith('Base'): + cls.safety = None + raise unittest.SkipTest + + # ***** standard tests for all safety modes ***** + + def test_tx_msg_in_scanned_range(self): + # the relay malfunction, fwd hook, and spam can tests don't exhaustively + # scan the entire 29-bit address space, only some known important ranges + # make sure SCANNED_ADDRS stays up to date with car port TX_MSGS; new + # model ports should expand the range if needed + for msg in self.TX_MSGS: + self.assertTrue(msg[0] in self.SCANNED_ADDRS, f"{msg[0]=:#x}") + + def test_fwd_hook(self): + # some safety modes don't forward anything, while others blacklist msgs + for bus in range(3): + for addr in self.SCANNED_ADDRS: + # assume len 8 + fwd_bus = self.FWD_BUS_LOOKUP.get(bus, -1) + if bus in self.FWD_BLACKLISTED_ADDRS and addr in self.FWD_BLACKLISTED_ADDRS[bus]: + fwd_bus = -1 + self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(bus, addr), f"{addr=:#x} from {bus=} to {fwd_bus=}") + + def test_spam_can_buses(self): + for bus in range(4): + for addr in self.SCANNED_ADDRS: + if [addr, bus] not in self.TX_MSGS: + self.assertFalse(self._tx(make_msg(bus, addr, 8)), f"allowed TX {addr=} {bus=}") + + def test_default_controls_not_allowed(self): + self.assertFalse(self.safety.get_controls_allowed()) + + def test_manually_enable_controls_allowed(self): + self.safety.set_controls_allowed(1) + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.set_controls_allowed(0) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_tx_hook_on_wrong_safety_mode(self): + files = os.listdir(os.path.dirname(os.path.realpath(__file__))) + test_files = [f for f in files if f.startswith("test_") and f.endswith(".py")] + + current_test = self.__class__.__name__ + + all_tx = [] + for tf in test_files: + test = importlib.import_module("opendbc.safety.tests."+tf[:-3]) + for attr in dir(test): + if attr.startswith("Test") and attr != current_test: + tc = getattr(test, attr) + tx = tc.TX_MSGS + if tx is not None and not attr.endswith('Base'): + # No point in comparing different Tesla safety modes + if 'Tesla' in attr and 'Tesla' in current_test: + continue + # No point in comparing to ALLOUTPUT which allows all messages + if attr.startswith('TestAllOutput'): + continue + if attr.startswith('TestToyota') and current_test.startswith('TestToyota'): + continue + if attr.startswith('TestSubaruGen') and current_test.startswith('TestSubaruGen'): + continue + if attr.startswith('TestSubaruPreglobal') and current_test.startswith('TestSubaruPreglobal'): + continue + if {attr, current_test}.issubset({'TestVolkswagenPqSafety', 'TestVolkswagenPqStockSafety', 'TestVolkswagenPqLongSafety'}): + continue + if {attr, current_test}.issubset({'TestGmCameraSafety', 'TestGmCameraLongitudinalSafety', 'TestGmAscmSafety', + 'TestGmCameraEVSafety', 'TestGmCameraLongitudinalEVSafety', 'TestGmAscmEVSafety'}): + continue + if attr.startswith('TestFord') and current_test.startswith('TestFord'): + continue + if attr.startswith('TestHyundaiCanfd') and current_test.startswith('TestHyundaiCanfd'): + continue + if {attr, current_test}.issubset({'TestHyundaiLongitudinalSafety', 'TestHyundaiLongitudinalSafetyCameraSCC', 'TestHyundaiSafetyFCEVLong'}): + continue + if {attr, current_test}.issubset({'TestVolkswagenMqbSafety', 'TestVolkswagenMqbStockSafety', 'TestVolkswagenMqbLongSafety'}): + continue + + # overlapping TX addrs, but they're not actuating messages for either car + if attr == 'TestHyundaiCanfdLKASteeringLongEV' and current_test.startswith('TestToyota'): + tx = list(filter(lambda m: m[0] not in [0x160, ], tx)) + + # Volkswagen MQB longitudinal actuating message overlaps with the Subaru lateral actuating message + if attr == 'TestVolkswagenMqbLongSafety' and current_test.startswith('TestSubaru'): + tx = list(filter(lambda m: m[0] not in [0x122, ], tx)) + + # Volkswagen MQB and Honda Nidec ACC HUD messages overlap + if attr == 'TestVolkswagenMqbLongSafety' and current_test.startswith('TestHondaNidec'): + tx = list(filter(lambda m: m[0] not in [0x30c, ], tx)) + + # Volkswagen MQB and Honda Bosch Radarless ACC HUD messages overlap + if attr == 'TestVolkswagenMqbLongSafety' and current_test.startswith('TestHondaBoschRadarless'): + tx = list(filter(lambda m: m[0] not in [0x30c, ], tx)) + + # TODO: Temporary, should be fixed in panda firmware, safety_honda.h + if attr.startswith('TestHonda'): + # exceptions for common msgs across different hondas + tx = list(filter(lambda m: m[0] not in [0x1FA, 0x30C, 0x33D, 0x33DB], tx)) + + if attr.startswith('TestHyundaiLongitudinal'): + # exceptions for common msgs across different Hyundai CAN platforms + tx = list(filter(lambda m: m[0] not in [0x420, 0x50A, 0x389, 0x4A2], tx)) + all_tx.append([[m[0], m[1], attr] for m in tx]) + + # make sure we got all the msgs + self.assertTrue(len(all_tx) >= len(test_files)-1) + + for tx_msgs in all_tx: + for addr, bus, test_name in tx_msgs: + msg = make_msg(bus, addr) + self.safety.set_controls_allowed(1) + # TODO: this should be blocked + if current_test in ["TestNissanSafety", "TestNissanSafetyAltEpsBus", "TestNissanLeafSafety"] and [addr, bus] in self.TX_MSGS: + continue + self.assertFalse(self._tx(msg), f"transmit of {addr=:#x} {bus=} from {test_name} during {current_test} was allowed") + + +@add_regen_tests +class CarSafetyTest(SafetyTest): + STANDSTILL_THRESHOLD: float = 0.0 + GAS_PRESSED_THRESHOLD = 0 + RELAY_MALFUNCTION_ADDRS: dict[int, tuple[int, ...]] | None = None + + @classmethod + def setUpClass(cls): + if cls.__name__ == "CarSafetyTest" or cls.__name__.endswith('Base'): + cls.safety = None + raise unittest.SkipTest + + @abc.abstractmethod + def _user_brake_msg(self, brake): + pass + + def _user_regen_msg(self, regen): + pass + + @abc.abstractmethod + def _speed_msg(self, speed): + pass + + @abc.abstractmethod + def _speed_msg_2(self, speed: float): + pass + + # Safety modes can override if vehicle_moving is driven by a different message + def _vehicle_moving_msg(self, speed: float): + return self._speed_msg(speed) + + @abc.abstractmethod + def _user_gas_msg(self, gas): + pass + + @abc.abstractmethod + def _pcm_status_msg(self, enable): + pass + + # ***** standard tests for all car-specific safety modes ***** + + def test_relay_malfunction(self): + # each car has an addr that is used to detect relay malfunction + # if that addr is seen on specified bus, triggers the relay malfunction + # protection logic: both tx_hook and fwd_hook are expected to return failure + self.assertFalse(self.safety.get_relay_malfunction()) + for bus in range(3): + for addr in self.SCANNED_ADDRS: + self.safety.set_relay_malfunction(False) + self._rx(make_msg(bus, addr, 8)) + should_relay_malfunction = addr in self.RELAY_MALFUNCTION_ADDRS.get(bus, ()) + self.assertEqual(should_relay_malfunction, self.safety.get_relay_malfunction(), (bus, hex(addr))) + + # test relay malfunction protection logic + self.safety.set_relay_malfunction(True) + for bus in range(3): + for addr in self.SCANNED_ADDRS: + self.assertFalse(self._tx(make_msg(bus, addr, 8))) + self.assertEqual(-1, self.safety.safety_fwd_hook(bus, addr)) + + def test_prev_gas(self): + self.assertFalse(self.safety.get_gas_pressed_prev()) + for pressed in [self.GAS_PRESSED_THRESHOLD + 1, 0]: + self._rx(self._user_gas_msg(pressed)) + self.assertEqual(bool(pressed), self.safety.get_gas_pressed_prev()) + + def test_allow_engage_with_gas_pressed(self): + self._rx(self._user_gas_msg(1)) + self.safety.set_controls_allowed(True) + self._rx(self._user_gas_msg(1)) + self.assertTrue(self.safety.get_controls_allowed()) + self._rx(self._user_gas_msg(1)) + self.assertTrue(self.safety.get_controls_allowed()) + + def test_no_disengage_on_gas(self): + self._rx(self._user_gas_msg(0)) + self.safety.set_controls_allowed(True) + self._rx(self._user_gas_msg(self.GAS_PRESSED_THRESHOLD + 1)) + # Test we allow lateral, but not longitudinal + self.assertTrue(self.safety.get_controls_allowed()) + self.assertFalse(self.safety.get_longitudinal_allowed()) + # Make sure we can re-gain longitudinal actuation + self._rx(self._user_gas_msg(0)) + self.assertTrue(self.safety.get_longitudinal_allowed()) + + def test_prev_user_brake(self, _user_brake_msg=None, get_brake_pressed_prev=None): + if _user_brake_msg is None: + _user_brake_msg = self._user_brake_msg + get_brake_pressed_prev = self.safety.get_brake_pressed_prev + + self.assertFalse(get_brake_pressed_prev()) + for pressed in [True, False]: + self._rx(_user_brake_msg(not pressed)) + self.assertEqual(not pressed, get_brake_pressed_prev()) + self._rx(_user_brake_msg(pressed)) + self.assertEqual(pressed, get_brake_pressed_prev()) + + def test_enable_control_allowed_from_cruise(self): + self._rx(self._pcm_status_msg(False)) + self.assertFalse(self.safety.get_controls_allowed()) + self._rx(self._pcm_status_msg(True)) + self.assertTrue(self.safety.get_controls_allowed()) + + def test_disable_control_allowed_from_cruise(self): + self.safety.set_controls_allowed(1) + self._rx(self._pcm_status_msg(False)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_cruise_engaged_prev(self): + for engaged in [True, False]: + self._rx(self._pcm_status_msg(engaged)) + self.assertEqual(engaged, self.safety.get_cruise_engaged_prev()) + self._rx(self._pcm_status_msg(not engaged)) + self.assertEqual(not engaged, self.safety.get_cruise_engaged_prev()) + + def test_allow_user_brake_at_zero_speed(self, _user_brake_msg=None, get_brake_pressed_prev=None): + if _user_brake_msg is None: + _user_brake_msg = self._user_brake_msg + + # Brake was already pressed + self._rx(self._vehicle_moving_msg(0)) + self._rx(_user_brake_msg(1)) + self.safety.set_controls_allowed(1) + self._rx(_user_brake_msg(1)) + self.assertTrue(self.safety.get_controls_allowed()) + self.assertTrue(self.safety.get_longitudinal_allowed()) + self._rx(_user_brake_msg(0)) + self.assertTrue(self.safety.get_controls_allowed()) + self.assertTrue(self.safety.get_longitudinal_allowed()) + # rising edge of brake should disengage + self._rx(_user_brake_msg(1)) + self.assertFalse(self.safety.get_controls_allowed()) + self.assertFalse(self.safety.get_longitudinal_allowed()) + self._rx(_user_brake_msg(0)) # reset no brakes + + def test_not_allow_user_brake_when_moving(self, _user_brake_msg=None, get_brake_pressed_prev=None): + if _user_brake_msg is None: + _user_brake_msg = self._user_brake_msg + + # Brake was already pressed + self._rx(_user_brake_msg(1)) + self.safety.set_controls_allowed(1) + self._rx(self._vehicle_moving_msg(self.STANDSTILL_THRESHOLD)) + self._rx(_user_brake_msg(1)) + self.assertTrue(self.safety.get_controls_allowed()) + self.assertTrue(self.safety.get_longitudinal_allowed()) + self._rx(self._vehicle_moving_msg(self.STANDSTILL_THRESHOLD + 1)) + self._rx(_user_brake_msg(1)) + self.assertFalse(self.safety.get_controls_allowed()) + self.assertFalse(self.safety.get_longitudinal_allowed()) + self._rx(self._vehicle_moving_msg(0)) + + def test_vehicle_moving(self): + self.assertFalse(self.safety.get_vehicle_moving()) + + # not moving + self._rx(self._vehicle_moving_msg(0)) + self.assertFalse(self.safety.get_vehicle_moving()) + + # speed is at threshold + self._rx(self._vehicle_moving_msg(self.STANDSTILL_THRESHOLD)) + self.assertFalse(self.safety.get_vehicle_moving()) + + # past threshold + self._rx(self._vehicle_moving_msg(self.STANDSTILL_THRESHOLD + 1)) + self.assertTrue(self.safety.get_vehicle_moving()) + + def test_rx_hook_speed_mismatch(self): + if self._speed_msg_2(0) is None: + raise unittest.SkipTest("No second speed message for this safety mode") + + for speed in np.arange(0, 40, 0.5): + for speed_delta in np.arange(-5, 5, 0.1): + speed_2 = round(max(speed + speed_delta, 0), 1) + # Set controls allowed in between rx since first message can reset it + self._rx(self._speed_msg(speed)) + self.safety.set_controls_allowed(True) + self._rx(self._speed_msg_2(speed_2)) + + within_delta = abs(speed - speed_2) <= MAX_SPEED_DELTA + self.assertEqual(self.safety.get_controls_allowed(), within_delta) + + def test_safety_tick(self): + self.safety.set_timer(int(2e6)) + self.safety.set_controls_allowed(True) + self.safety.safety_tick_current_safety_config() + self.assertFalse(self.safety.get_controls_allowed()) + self.assertFalse(self.safety.safety_config_valid()) diff --git a/opendbc_repo/opendbc/safety/tests/hyundai_common.py b/opendbc_repo/opendbc/safety/tests/hyundai_common.py new file mode 100644 index 0000000000..5d79155aaf --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/hyundai_common.py @@ -0,0 +1,153 @@ +import unittest + +import opendbc.safety.tests.common as common +from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests.common import make_msg + + +class Buttons: + NONE = 0 + RESUME = 1 + SET = 2 + CANCEL = 4 + + +PREV_BUTTON_SAMPLES = 8 +ENABLE_BUTTONS = (Buttons.RESUME, Buttons.SET, Buttons.CANCEL) + + +class HyundaiButtonBase: + BUTTONS_TX_BUS = 0 # tx on this bus, rx on 0 + SCC_BUS = 0 # rx on this bus + + def test_button_sends(self): + """ + Only RES and CANCEL buttons are allowed + - RES allowed while controls allowed + - CANCEL allowed while cruise is enabled + """ + self.safety.set_controls_allowed(0) + self.assertFalse(self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS))) + self.assertFalse(self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS))) + + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(self._button_msg(Buttons.RESUME, bus=self.BUTTONS_TX_BUS))) + self.assertFalse(self._tx(self._button_msg(Buttons.SET, bus=self.BUTTONS_TX_BUS))) + + for enabled in (True, False): + self._rx(self._pcm_status_msg(enabled)) + self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL, bus=self.BUTTONS_TX_BUS))) + + def test_enable_control_allowed_from_cruise(self): + """ + Hyundai non-longitudinal only enables on PCM rising edge and recent button press. Tests PCM enabling with: + - disallowed: No buttons + - disallowed: Buttons that don't enable cruise + - allowed: Buttons that do enable cruise + - allowed: Main button with all above combinations + """ + for main_button in (0, 1): + for btn in range(8): + for _ in range(PREV_BUTTON_SAMPLES): # reset + self._rx(self._button_msg(Buttons.NONE)) + + self._rx(self._pcm_status_msg(False)) + self.assertFalse(self.safety.get_controls_allowed()) + self._rx(self._button_msg(btn, main_button=main_button)) + self._rx(self._pcm_status_msg(True)) + controls_allowed = btn in ENABLE_BUTTONS or main_button + self.assertEqual(controls_allowed, self.safety.get_controls_allowed()) + + def test_sampling_cruise_buttons(self): + """ + Test that we allow controls on recent button press, but not as button leaves sliding window + """ + self._rx(self._button_msg(Buttons.SET)) + for i in range(2 * PREV_BUTTON_SAMPLES): + self._rx(self._pcm_status_msg(False)) + self.assertFalse(self.safety.get_controls_allowed()) + self._rx(self._pcm_status_msg(True)) + controls_allowed = i < PREV_BUTTON_SAMPLES + self.assertEqual(controls_allowed, self.safety.get_controls_allowed()) + self._rx(self._button_msg(Buttons.NONE)) + + +class HyundaiLongitudinalBase(common.LongitudinalAccelSafetyTest): + + DISABLED_ECU_UDS_MSG: tuple[int, int] + DISABLED_ECU_ACTUATION_MSG: tuple[int, int] + + @classmethod + def setUpClass(cls): + if cls.__name__ == "HyundaiLongitudinalBase": + cls.safety = None + raise unittest.SkipTest + + # override these tests from CarSafetyTest, hyundai longitudinal uses button enable + def test_disable_control_allowed_from_cruise(self): + pass + + def test_enable_control_allowed_from_cruise(self): + pass + + def test_sampling_cruise_buttons(self): + pass + + def test_cruise_engaged_prev(self): + pass + + def test_button_sends(self): + pass + + def _pcm_status_msg(self, enable): + raise Exception + + def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): + raise NotImplementedError + + def test_set_resume_buttons(self): + """ + SET and RESUME enter controls allowed on their falling edge. + """ + for btn_prev in range(8): + for btn_cur in range(8): + self._rx(self._button_msg(Buttons.NONE)) + self.safety.set_controls_allowed(0) + for _ in range(10): + self._rx(self._button_msg(btn_prev)) + self.assertFalse(self.safety.get_controls_allowed()) + + # should enter controls allowed on falling edge and not transitioning to cancel + should_enable = btn_cur != btn_prev and \ + btn_cur != Buttons.CANCEL and \ + btn_prev in (Buttons.RESUME, Buttons.SET) + + self._rx(self._button_msg(btn_cur)) + self.assertEqual(should_enable, self.safety.get_controls_allowed()) + + def test_cancel_button(self): + self.safety.set_controls_allowed(1) + self._rx(self._button_msg(Buttons.CANCEL)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_tester_present_allowed(self, ecu_disable: bool = True): + """ + Ensure tester present diagnostic message is allowed to keep ECU knocked out + for longitudinal control. + """ + + addr, bus = self.DISABLED_ECU_UDS_MSG + for should_tx, msg in ((True, b"\x02\x3E\x80\x00\x00\x00\x00\x00"), + (False, b"\x03\xAA\xAA\x00\x00\x00\x00\x00")): + tester_present = libsafety_py.make_CANPacket(addr, bus, msg) + self.assertEqual(should_tx and ecu_disable, self._tx(tester_present)) + + def test_disabled_ecu_alive(self): + """ + If the ECU knockout failed, make sure the relay malfunction is shown + """ + + addr, bus = self.DISABLED_ECU_ACTUATION_MSG + self.assertFalse(self.safety.get_relay_malfunction()) + self._rx(make_msg(bus, addr, 8)) + self.assertTrue(self.safety.get_relay_malfunction()) diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/SConscript b/opendbc_repo/opendbc/safety/tests/libsafety/SConscript new file mode 100644 index 0000000000..7cab268aea --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/libsafety/SConscript @@ -0,0 +1,69 @@ +import platform + +CC = 'gcc' +system = platform.system() +mac_ver = platform.mac_ver() + +# gcc installed by homebrew has version suffix (e.g. gcc-12) in order to be +# distinguishable from system one - which acts as a symlink to clang +# clang works on macOS 15 and greater but has issues on earlier macOS versions. +# see: https://github.com/commaai/openpilot/issues/35093 +if system == 'Darwin' and mac_ver[0] and mac_ver[0] < '15': + CC += '-13' + +# standard env +env = Environment( + CC=CC, + CFLAGS=[ + '-Wall', + "-Wextra", + '-Werror', + '-nostdlib', + '-fno-builtin', + '-std=gnu11', + '-Wfatal-errors', + '-Wno-pointer-to-int-cast', + '-g', + '-O0', + '-fno-omit-frame-pointer', + '-fprofile-arcs', + '-ftest-coverage', + '-DALLOW_DEBUG', + ], + LINKFLAGS=[ + '-fprofile-arcs', + '-ftest-coverage', + ], + CPPPATH=["#", "../../board/"], + tools=["default", "compilation_db"], +) +if system == "Darwin": + env.PrependENVPath('PATH', '/opt/homebrew/bin') +if GetOption('ubsan'): + env.Prepend(LINKFLAGS=[ + "-fsanitize=undefined", + "-fno-sanitize-recover=undefined", + ]) + +# mutation env +menv = env.Clone() +menv['CC'] = 'clang-17' +flags = [ + '-fprofile-instr-generate', + '-fcoverage-mapping', + '-fpass-plugin=/usr/lib/mull-ir-frontend-17', + '-g', + '-grecord-command-line', +] +menv['CFLAGS'] += flags +menv['LINKFLAGS'] += flags + +for build_env, suffix in ((env, ""), (menv, "_mutation")): + # TODO: add macOS support + if (build_env == menv) and (system == "Darwin"): + continue + safety = env.SharedObject(f"safety{suffix}.os", "safety.c") + libsafety = env.SharedLibrary(f"libsafety{suffix}.so", [safety]) + + # GCC note file is generated by compiler, allow scons to clean it up + env.SideEffect("safety.gcno", safety) diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/__init__.py b/opendbc_repo/opendbc/safety/tests/libsafety/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/fake_stm.h b/opendbc_repo/opendbc/safety/tests/libsafety/fake_stm.h new file mode 100644 index 0000000000..1194843073 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/libsafety/fake_stm.h @@ -0,0 +1,12 @@ +#include +#include +#include + +#define ALLOW_DEBUG + +// TODO: time should just be passed into the hooks we expose +uint32_t timer_cnt = 0; +uint32_t microsecond_timer_get(void); +uint32_t microsecond_timer_get(void) { + return timer_cnt; +} diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py b/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py new file mode 100644 index 0000000000..ee314b6e12 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/libsafety/libsafety_py.py @@ -0,0 +1,93 @@ +import os +from cffi import FFI + +from opendbc.safety import LEN_TO_DLC + +libsafety_dir = os.path.dirname(os.path.abspath(__file__)) +libsafety_fn = os.path.join(libsafety_dir, "libsafety_mutation.so" if "MUTATION" in os.environ else "libsafety.so") + +ffi = FFI() + +ffi.cdef(""" +typedef struct { + unsigned char fd : 1; + unsigned char bus : 3; + unsigned char data_len_code : 4; + unsigned char rejected : 1; + unsigned char returned : 1; + unsigned char extended : 1; + unsigned int addr : 29; + unsigned char checksum; + unsigned char data[64]; +} CANPacket_t; +""", packed=True) +class CANPacket: + pass + +ffi.cdef(""" +bool safety_rx_hook(CANPacket_t *msg); +bool safety_tx_hook(CANPacket_t *msg); +int safety_fwd_hook(int bus_num, int addr); +int set_safety_hooks(uint16_t mode, uint16_t param); + +void set_controls_allowed(bool c); +bool get_controls_allowed(void); +bool get_longitudinal_allowed(void); +void set_alternative_experience(int mode); +int get_alternative_experience(void); +void set_relay_malfunction(bool c); +bool get_relay_malfunction(void); +bool get_gas_pressed_prev(void); +void set_gas_pressed_prev(bool); +bool get_brake_pressed_prev(void); +bool get_regen_braking_prev(void); +bool get_steering_disengage_prev(void); +bool get_acc_main_on(void); +float get_vehicle_speed_min(void); +float get_vehicle_speed_max(void); +int get_current_safety_mode(void); +int get_current_safety_param(void); + +void set_torque_meas(int min, int max); +int get_torque_meas_min(void); +int get_torque_meas_max(void); +void set_torque_driver(int min, int max); +int get_torque_driver_min(void); +int get_torque_driver_max(void); +void set_desired_torque_last(int t); +void set_rt_torque_last(int t); +void set_desired_angle_last(int t); +int get_desired_angle_last(); +void set_angle_meas(int min, int max); +int get_angle_meas_min(void); +int get_angle_meas_max(void); + +bool get_cruise_engaged_prev(void); +void set_cruise_engaged_prev(bool engaged); +bool get_vehicle_moving(void); +void set_timer(uint32_t t); + +void safety_tick_current_safety_config(); +bool safety_config_valid(); + +void init_tests(void); + +void set_honda_fwd_brake(bool c); +bool get_honda_fwd_brake(void); +void set_honda_alt_brake_msg(bool c); +void set_honda_bosch_long(bool c); +int get_honda_hw(void); +""") + +class LibSafety: + pass +libsafety: LibSafety = ffi.dlopen(libsafety_fn) + +def make_CANPacket(addr: int, bus: int, dat): + ret = ffi.new('CANPacket_t *') + ret[0].extended = 1 if addr >= 0x800 else 0 + ret[0].addr = addr + ret[0].data_len_code = LEN_TO_DLC[len(dat)] + ret[0].bus = bus + ret[0].data = bytes(dat) + return ret diff --git a/opendbc_repo/opendbc/safety/tests/libsafety/safety.c b/opendbc_repo/opendbc/safety/tests/libsafety/safety.c new file mode 100644 index 0000000000..afb7054448 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/libsafety/safety.c @@ -0,0 +1,204 @@ +#include +#include +#include + +// TODO: time should just be passed into the hooks we expose +uint32_t timer_cnt = 0; +uint32_t microsecond_timer_get(void); +uint32_t microsecond_timer_get(void) { + return timer_cnt; +} + +#include "opendbc/safety/can.h" +#include "opendbc/safety/safety.h" + +void safety_tick_current_safety_config() { + safety_tick(¤t_safety_config); +} + +bool safety_config_valid() { + if (current_safety_config.rx_checks_len <= 0) { + printf("missing RX checks\n"); + return false; + } + + for (int i = 0; i < current_safety_config.rx_checks_len; i++) { + const RxCheck addr = current_safety_config.rx_checks[i]; + bool valid = addr.status.msg_seen && !addr.status.lagging && addr.status.valid_checksum && (addr.status.wrong_counters < MAX_WRONG_COUNTERS) && addr.status.valid_quality_flag; + if (!valid) { + // printf("i %d seen %d lagging %d valid checksum %d wrong counters %d valid quality flag %d\n", i, addr.status.msg_seen, addr.status.lagging, addr.status.valid_checksum, addr.status.wrong_counters, addr.status.valid_quality_flag); + return false; + } + } + return true; +} + +void set_controls_allowed(bool c){ + controls_allowed = c; +} + +void set_alternative_experience(int mode){ + alternative_experience = mode; +} + +void set_relay_malfunction(bool c){ + relay_malfunction = c; +} + +bool get_controls_allowed(void){ + return controls_allowed; +} + +int get_alternative_experience(void){ + return alternative_experience; +} + +bool get_relay_malfunction(void){ + return relay_malfunction; +} + +bool get_gas_pressed_prev(void){ + return gas_pressed_prev; +} + +void set_gas_pressed_prev(bool c){ + gas_pressed_prev = c; +} + +bool get_brake_pressed_prev(void){ + return brake_pressed_prev; +} + +bool get_regen_braking_prev(void){ + return regen_braking_prev; +} + +bool get_steering_disengage_prev(void){ + return steering_disengage_prev; +} + +bool get_cruise_engaged_prev(void){ + return cruise_engaged_prev; +} + +void set_cruise_engaged_prev(bool engaged){ + cruise_engaged_prev = engaged; +} + +bool get_vehicle_moving(void){ + return vehicle_moving; +} + +bool get_acc_main_on(void){ + return acc_main_on; +} + +float get_vehicle_speed_min(void){ + return vehicle_speed.min / VEHICLE_SPEED_FACTOR; +} + +float get_vehicle_speed_max(void){ + return vehicle_speed.max / VEHICLE_SPEED_FACTOR; +} + +int get_current_safety_mode(void){ + return current_safety_mode; +} + +int get_current_safety_param(void){ + return current_safety_param; +} + +void set_timer(uint32_t t){ + timer_cnt = t; +} + +void set_torque_meas(int min, int max){ + torque_meas.min = min; + torque_meas.max = max; +} + +int get_torque_meas_min(void){ + return torque_meas.min; +} + +int get_torque_meas_max(void){ + return torque_meas.max; +} + +void set_torque_driver(int min, int max){ + torque_driver.min = min; + torque_driver.max = max; +} + +int get_torque_driver_min(void){ + return torque_driver.min; +} + +int get_torque_driver_max(void){ + return torque_driver.max; +} + +void set_rt_torque_last(int t){ + rt_torque_last = t; +} + +void set_desired_torque_last(int t){ + desired_torque_last = t; +} + +void set_desired_angle_last(int t){ + desired_angle_last = t; +} + +int get_desired_angle_last(void){ + return desired_angle_last; +} + +void set_angle_meas(int min, int max){ + angle_meas.min = min; + angle_meas.max = max; +} + +int get_angle_meas_min(void){ + return angle_meas.min; +} + +int get_angle_meas_max(void){ + return angle_meas.max; +} + + +// ***** car specific helpers ***** + +void set_honda_alt_brake_msg(bool c){ + honda_alt_brake_msg = c; +} + +void set_honda_bosch_long(bool c){ + honda_bosch_long = c; +} + +int get_honda_hw(void) { + return honda_hw; +} + +void set_honda_fwd_brake(bool c){ + honda_fwd_brake = c; +} + +bool get_honda_fwd_brake(void){ + return honda_fwd_brake; +} + +void init_tests(void){ + safety_mode_cnt = 2U; // avoid ignoring relay_malfunction logic + alternative_experience = 0; + set_timer(0); + ts_steer_req_mismatch_last = 0; + valid_steer_req_count = 0; + invalid_steer_req_count = 0; + + // assumes autopark on safety mode init to avoid a fault. get rid of that for testing + tesla_autopark = false; +} diff --git a/opendbc_repo/opendbc/safety/tests/misra/.gitignore b/opendbc_repo/opendbc/safety/tests/misra/.gitignore new file mode 100644 index 0000000000..fc9ac228cb --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/.gitignore @@ -0,0 +1,5 @@ +*.pdf +*.txt +.output.log +new_table +cppcheck/ diff --git a/opendbc_repo/opendbc/safety/tests/misra/checkers.txt b/opendbc_repo/opendbc/safety/tests/misra/checkers.txt new file mode 100644 index 0000000000..b3f1d5866d --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/checkers.txt @@ -0,0 +1,456 @@ +Cppcheck checkers list from test_misra.sh: + + + + + +TEST variant options: +--enable=all --enable=unusedFunction --addon=misra -DCANFD /opendbc/safety/main.c + + +Critical errors +--------------- +No critical errors encountered. +Note: There might still have been non-critical bailouts which might lead to false negatives. + + +Open source checkers +-------------------- +Yes Check64BitPortability::pointerassignment +Yes CheckAssert::assertWithSideEffects +Yes CheckAutoVariables::assignFunctionArg +Yes CheckAutoVariables::autoVariables +Yes CheckAutoVariables::checkVarLifetime +No CheckBool::checkAssignBoolToFloat require:style,c++ +Yes CheckBool::checkAssignBoolToPointer +No CheckBool::checkBitwiseOnBoolean require:style,inconclusive +Yes CheckBool::checkComparisonOfBoolExpressionWithInt +No CheckBool::checkComparisonOfBoolWithBool require:style,c++ +No CheckBool::checkComparisonOfBoolWithInt require:warning,c++ +No CheckBool::checkComparisonOfFuncReturningBool require:style,c++ +Yes CheckBool::checkIncrementBoolean +Yes CheckBool::pointerArithBool +Yes CheckBool::returnValueOfFunctionReturningBool +Yes CheckBufferOverrun::analyseWholeProgram +Yes CheckBufferOverrun::argumentSize +Yes CheckBufferOverrun::arrayIndex +Yes CheckBufferOverrun::arrayIndexThenCheck +Yes CheckBufferOverrun::bufferOverflow +Yes CheckBufferOverrun::negativeArraySize +Yes CheckBufferOverrun::objectIndex +Yes CheckBufferOverrun::pointerArithmetic +No CheckBufferOverrun::stringNotZeroTerminated require:warning,inconclusive +Yes CheckClass::analyseWholeProgram +No CheckClass::checkConst require:style,inconclusive +No CheckClass::checkConstructors require:style,warning +No CheckClass::checkCopyConstructors require:warning +No CheckClass::checkDuplInheritedMembers require:warning +No CheckClass::checkExplicitConstructors require:style +No CheckClass::checkMemset +No CheckClass::checkMissingOverride require:style,c++03 +No CheckClass::checkReturnByReference require:performance +No CheckClass::checkSelfInitialization +No CheckClass::checkThisUseAfterFree require:warning +No CheckClass::checkUnsafeClassRefMember require:warning,safeChecks +No CheckClass::checkUselessOverride require:style +No CheckClass::checkVirtualFunctionCallInConstructor require:warning +No CheckClass::initializationListUsage require:performance +No CheckClass::initializerListOrder require:style,inconclusive +No CheckClass::operatorEqRetRefThis require:style +No CheckClass::operatorEqToSelf require:warning +No CheckClass::privateFunctions require:style +No CheckClass::thisSubtraction require:warning +No CheckClass::virtualDestructor +Yes CheckCondition::alwaysTrueFalse +Yes CheckCondition::assignIf +Yes CheckCondition::checkAssignmentInCondition +Yes CheckCondition::checkBadBitmaskCheck +Yes CheckCondition::checkCompareValueOutOfTypeRange +Yes CheckCondition::checkDuplicateConditionalAssign +Yes CheckCondition::checkIncorrectLogicOperator +Yes CheckCondition::checkInvalidTestForOverflow +Yes CheckCondition::checkModuloAlwaysTrueFalse +Yes CheckCondition::checkPointerAdditionResultNotNull +Yes CheckCondition::clarifyCondition +Yes CheckCondition::comparison +Yes CheckCondition::duplicateCondition +Yes CheckCondition::multiCondition +Yes CheckCondition::multiCondition2 +No CheckExceptionSafety::checkCatchExceptionByValue require:style +No CheckExceptionSafety::checkRethrowCopy require:style +No CheckExceptionSafety::deallocThrow require:warning +No CheckExceptionSafety::destructors require:warning +No CheckExceptionSafety::nothrowThrows +No CheckExceptionSafety::rethrowNoCurrentException +No CheckExceptionSafety::unhandledExceptionSpecification require:style,inconclusive +Yes CheckFunctions::checkIgnoredReturnValue +Yes CheckFunctions::checkMathFunctions +Yes CheckFunctions::checkMissingReturn +Yes CheckFunctions::checkProhibitedFunctions +Yes CheckFunctions::invalidFunctionUsage +Yes CheckFunctions::memsetInvalid2ndParam +Yes CheckFunctions::memsetZeroBytes +No CheckFunctions::returnLocalStdMove require:performance,c++11 +Yes CheckFunctions::useStandardLibrary +No CheckIO::checkCoutCerrMisusage require:c +Yes CheckIO::checkFileUsage +Yes CheckIO::checkWrongPrintfScanfArguments +Yes CheckIO::invalidScanf +Yes CheckLeakAutoVar::check +No CheckMemoryLeakInClass::check +Yes CheckMemoryLeakInFunction::checkReallocUsage +Yes CheckMemoryLeakNoVar::check +No CheckMemoryLeakNoVar::checkForUnsafeArgAlloc +Yes CheckMemoryLeakStructMember::check +Yes CheckNullPointer::analyseWholeProgram +Yes CheckNullPointer::arithmetic +Yes CheckNullPointer::nullConstantDereference +Yes CheckNullPointer::nullPointer +No CheckOther::checkAccessOfMovedVariable require:c++11,warning +Yes CheckOther::checkCastIntToCharAndBack +Yes CheckOther::checkCharVariable +Yes CheckOther::checkComparePointers +Yes CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse +Yes CheckOther::checkConstPointer +No CheckOther::checkConstVariable require:style,c++ +No CheckOther::checkDuplicateBranch require:style,inconclusive +Yes CheckOther::checkDuplicateExpression +Yes CheckOther::checkEvaluationOrder +Yes CheckOther::checkFuncArgNamesDifferent +No CheckOther::checkIncompleteArrayFill require:warning,portability,inconclusive +Yes CheckOther::checkIncompleteStatement +No CheckOther::checkInterlockedDecrement require:windows-platform +Yes CheckOther::checkInvalidFree +Yes CheckOther::checkKnownArgument +Yes CheckOther::checkKnownPointerToBool +No CheckOther::checkMisusedScopedObject require:style,c++ +Yes CheckOther::checkModuloOfOne +Yes CheckOther::checkNanInArithmeticExpression +Yes CheckOther::checkNegativeBitwiseShift +Yes CheckOther::checkOverlappingWrite +No CheckOther::checkPassByReference require:performance,c++ +Yes CheckOther::checkRedundantAssignment +No CheckOther::checkRedundantCopy require:c++,performance,inconclusive +Yes CheckOther::checkRedundantPointerOp +Yes CheckOther::checkShadowVariables +Yes CheckOther::checkSignOfUnsignedVariable +No CheckOther::checkSuspiciousCaseInSwitch require:warning,inconclusive +No CheckOther::checkSuspiciousSemicolon require:warning,inconclusive +Yes CheckOther::checkUnreachableCode +Yes CheckOther::checkUnusedLabel +Yes CheckOther::checkVarFuncNullUB +Yes CheckOther::checkVariableScope +Yes CheckOther::checkZeroDivision +Yes CheckOther::clarifyCalculation +Yes CheckOther::clarifyStatement +Yes CheckOther::invalidPointerCast +Yes CheckOther::redundantBitwiseOperationInSwitch +Yes CheckOther::suspiciousFloatingPointCast +No CheckOther::warningOldStylePointerCast require:style,c++ +No CheckPostfixOperator::postfixOperator require:performance +Yes CheckSizeof::checkSizeofForArrayParameter +Yes CheckSizeof::checkSizeofForNumericParameter +Yes CheckSizeof::checkSizeofForPointerSize +Yes CheckSizeof::sizeofCalculation +Yes CheckSizeof::sizeofFunction +Yes CheckSizeof::sizeofVoid +Yes CheckSizeof::sizeofsizeof +No CheckSizeof::suspiciousSizeofCalculation require:warning,inconclusive +No CheckStl::checkDereferenceInvalidIterator require:warning +No CheckStl::checkDereferenceInvalidIterator2 +No CheckStl::checkFindInsert require:performance +No CheckStl::checkMutexes require:warning +No CheckStl::erase +No CheckStl::eraseIteratorOutOfBounds +No CheckStl::if_find require:warning,performance +No CheckStl::invalidContainer +No CheckStl::iterators +No CheckStl::knownEmptyContainer require:style +No CheckStl::misMatchingContainerIterator +No CheckStl::misMatchingContainers +No CheckStl::missingComparison require:warning +No CheckStl::negativeIndex +No CheckStl::outOfBounds +No CheckStl::outOfBoundsIndexExpression +No CheckStl::redundantCondition require:style +No CheckStl::size require:performance,c++03 +No CheckStl::stlBoundaries +No CheckStl::stlOutOfBounds +No CheckStl::string_c_str +No CheckStl::useStlAlgorithm require:style +No CheckStl::uselessCalls require:performance,warning +Yes CheckString::checkAlwaysTrueOrFalseStringCompare +Yes CheckString::checkIncorrectStringCompare +Yes CheckString::checkSuspiciousStringCompare +Yes CheckString::overlappingStrcmp +Yes CheckString::sprintfOverlappingData +Yes CheckString::strPlusChar +Yes CheckString::stringLiteralWrite +Yes CheckType::checkFloatToIntegerOverflow +Yes CheckType::checkIntegerOverflow +Yes CheckType::checkLongCast +Yes CheckType::checkSignConversion +Yes CheckType::checkTooBigBitwiseShift +Yes CheckUninitVar::analyseWholeProgram +Yes CheckUninitVar::check +Yes CheckUninitVar::valueFlowUninit +Yes CheckUnusedFunctions::check +Yes CheckUnusedVar::checkFunctionVariableUsage +Yes CheckUnusedVar::checkStructMemberUsage +Yes CheckVaarg::va_list_usage +Yes CheckVaarg::va_start_argument + + +Premium checkers +---------------- +Not available, Cppcheck Premium is not used + + +Autosar +------- +Not available, Cppcheck Premium is not used + + +Cert C +------ +Not available, Cppcheck Premium is not used + + +Cert C++ +-------- +Not available, Cppcheck Premium is not used + + +Misra C 2012 +------------ +No Misra C 2012: Dir 1.1 +No Misra C 2012: Dir 2.1 +No Misra C 2012: Dir 3.1 +No Misra C 2012: Dir 4.1 +No Misra C 2012: Dir 4.2 +No Misra C 2012: Dir 4.3 +No Misra C 2012: Dir 4.4 +No Misra C 2012: Dir 4.5 +No Misra C 2012: Dir 4.6 amendment:3 +No Misra C 2012: Dir 4.7 +No Misra C 2012: Dir 4.8 +No Misra C 2012: Dir 4.9 amendment:3 +No Misra C 2012: Dir 4.10 +No Misra C 2012: Dir 4.11 amendment:3 +No Misra C 2012: Dir 4.12 +No Misra C 2012: Dir 4.13 +No Misra C 2012: Dir 4.14 amendment:2 +No Misra C 2012: Dir 4.15 amendment:3 +No Misra C 2012: Dir 5.1 amendment:4 +No Misra C 2012: Dir 5.2 amendment:4 +No Misra C 2012: Dir 5.3 amendment:4 +Yes Misra C 2012: 1.1 +Yes Misra C 2012: 1.2 +Yes Misra C 2012: 1.3 +Yes Misra C 2012: 1.4 amendment:2 +No Misra C 2012: 1.5 amendment:3 require:premium +Yes Misra C 2012: 2.1 +Yes Misra C 2012: 2.2 +Yes Misra C 2012: 2.3 +Yes Misra C 2012: 2.4 +Yes Misra C 2012: 2.5 +Yes Misra C 2012: 2.6 +Yes Misra C 2012: 2.7 +Yes Misra C 2012: 2.8 +Yes Misra C 2012: 3.1 +Yes Misra C 2012: 3.2 +Yes Misra C 2012: 4.1 +Yes Misra C 2012: 4.2 +Yes Misra C 2012: 5.1 +Yes Misra C 2012: 5.2 +Yes Misra C 2012: 5.3 +Yes Misra C 2012: 5.4 +Yes Misra C 2012: 5.5 +Yes Misra C 2012: 5.6 +Yes Misra C 2012: 5.7 +Yes Misra C 2012: 5.8 +Yes Misra C 2012: 5.9 +Yes Misra C 2012: 6.1 +Yes Misra C 2012: 6.2 +No Misra C 2012: 6.3 +Yes Misra C 2012: 7.1 +Yes Misra C 2012: 7.2 +Yes Misra C 2012: 7.3 +Yes Misra C 2012: 7.4 +No Misra C 2012: 7.5 +No Misra C 2012: 7.6 +Yes Misra C 2012: 8.1 +Yes Misra C 2012: 8.2 +No Misra C 2012: 8.3 +Yes Misra C 2012: 8.4 +Yes Misra C 2012: 8.5 +Yes Misra C 2012: 8.6 +Yes Misra C 2012: 8.7 +Yes Misra C 2012: 8.8 +Yes Misra C 2012: 8.9 +Yes Misra C 2012: 8.10 +Yes Misra C 2012: 8.11 +Yes Misra C 2012: 8.12 +Yes Misra C 2012: 8.13 +Yes Misra C 2012: 8.14 +No Misra C 2012: 8.15 +No Misra C 2012: 8.16 +No Misra C 2012: 8.17 +Yes Misra C 2012: 9.1 +Yes Misra C 2012: 9.2 +Yes Misra C 2012: 9.3 +Yes Misra C 2012: 9.4 +Yes Misra C 2012: 9.5 +No Misra C 2012: 9.6 +No Misra C 2012: 9.7 +Yes Misra C 2012: 10.1 +Yes Misra C 2012: 10.2 +Yes Misra C 2012: 10.3 +Yes Misra C 2012: 10.4 +Yes Misra C 2012: 10.5 +Yes Misra C 2012: 10.6 +Yes Misra C 2012: 10.7 +Yes Misra C 2012: 10.8 +Yes Misra C 2012: 11.1 +Yes Misra C 2012: 11.2 +Yes Misra C 2012: 11.3 +Yes Misra C 2012: 11.4 +Yes Misra C 2012: 11.5 +Yes Misra C 2012: 11.6 +Yes Misra C 2012: 11.7 +Yes Misra C 2012: 11.8 +Yes Misra C 2012: 11.9 +No Misra C 2012: 11.10 +Yes Misra C 2012: 12.1 +Yes Misra C 2012: 12.2 +Yes Misra C 2012: 12.3 +Yes Misra C 2012: 12.4 +Yes Misra C 2012: 12.5 amendment:1 +No Misra C 2012: 12.6 amendment:4 require:premium +Yes Misra C 2012: 13.1 +No Misra C 2012: 13.2 +Yes Misra C 2012: 13.3 +Yes Misra C 2012: 13.4 +Yes Misra C 2012: 13.5 +Yes Misra C 2012: 13.6 +Yes Misra C 2012: 14.1 +Yes Misra C 2012: 14.2 +Yes Misra C 2012: 14.3 +Yes Misra C 2012: 14.4 +Yes Misra C 2012: 15.1 +Yes Misra C 2012: 15.2 +Yes Misra C 2012: 15.3 +Yes Misra C 2012: 15.4 +Yes Misra C 2012: 15.5 +Yes Misra C 2012: 15.6 +Yes Misra C 2012: 15.7 +Yes Misra C 2012: 16.1 +Yes Misra C 2012: 16.2 +Yes Misra C 2012: 16.3 +Yes Misra C 2012: 16.4 +Yes Misra C 2012: 16.5 +Yes Misra C 2012: 16.6 +Yes Misra C 2012: 16.7 +Yes Misra C 2012: 17.1 +Yes Misra C 2012: 17.2 +Yes Misra C 2012: 17.3 +No Misra C 2012: 17.4 +Yes Misra C 2012: 17.5 +Yes Misra C 2012: 17.6 +Yes Misra C 2012: 17.7 +Yes Misra C 2012: 17.8 +No Misra C 2012: 17.9 +No Misra C 2012: 17.10 +No Misra C 2012: 17.11 +No Misra C 2012: 17.12 +No Misra C 2012: 17.13 +Yes Misra C 2012: 18.1 +Yes Misra C 2012: 18.2 +Yes Misra C 2012: 18.3 +Yes Misra C 2012: 18.4 +Yes Misra C 2012: 18.5 +Yes Misra C 2012: 18.6 +Yes Misra C 2012: 18.7 +Yes Misra C 2012: 18.8 +No Misra C 2012: 18.9 +No Misra C 2012: 18.10 +Yes Misra C 2012: 19.1 +Yes Misra C 2012: 19.2 +Yes Misra C 2012: 20.1 +Yes Misra C 2012: 20.2 +Yes Misra C 2012: 20.3 +Yes Misra C 2012: 20.4 +Yes Misra C 2012: 20.5 +Yes Misra C 2012: 20.6 +Yes Misra C 2012: 20.7 +Yes Misra C 2012: 20.8 +Yes Misra C 2012: 20.9 +Yes Misra C 2012: 20.10 +Yes Misra C 2012: 20.11 +Yes Misra C 2012: 20.12 +Yes Misra C 2012: 20.13 +Yes Misra C 2012: 20.14 +Yes Misra C 2012: 21.1 +Yes Misra C 2012: 21.2 +Yes Misra C 2012: 21.3 +Yes Misra C 2012: 21.4 +Yes Misra C 2012: 21.5 +Yes Misra C 2012: 21.6 +Yes Misra C 2012: 21.7 +Yes Misra C 2012: 21.8 +Yes Misra C 2012: 21.9 +Yes Misra C 2012: 21.10 +Yes Misra C 2012: 21.11 +Yes Misra C 2012: 21.12 +Yes Misra C 2012: 21.13 amendment:1 +Yes Misra C 2012: 21.14 amendment:1 +Yes Misra C 2012: 21.15 amendment:1 +Yes Misra C 2012: 21.16 amendment:1 +Yes Misra C 2012: 21.17 amendment:1 +Yes Misra C 2012: 21.18 amendment:1 +Yes Misra C 2012: 21.19 amendment:1 +Yes Misra C 2012: 21.20 amendment:1 +Yes Misra C 2012: 21.21 amendment:3 +No Misra C 2012: 21.22 amendment:3 require:premium +No Misra C 2012: 21.23 amendment:3 require:premium +No Misra C 2012: 21.24 amendment:3 require:premium +No Misra C 2012: 21.25 amendment:4 require:premium +No Misra C 2012: 21.26 amendment:4 require:premium +Yes Misra C 2012: 22.1 +Yes Misra C 2012: 22.2 +Yes Misra C 2012: 22.3 +Yes Misra C 2012: 22.4 +Yes Misra C 2012: 22.5 +Yes Misra C 2012: 22.6 +Yes Misra C 2012: 22.7 amendment:1 +Yes Misra C 2012: 22.8 amendment:1 +Yes Misra C 2012: 22.9 amendment:1 +Yes Misra C 2012: 22.10 amendment:1 +No Misra C 2012: 22.11 amendment:4 require:premium +No Misra C 2012: 22.12 amendment:4 require:premium +No Misra C 2012: 22.13 amendment:4 require:premium +No Misra C 2012: 22.14 amendment:4 require:premium +No Misra C 2012: 22.15 amendment:4 require:premium +No Misra C 2012: 22.16 amendment:4 require:premium +No Misra C 2012: 22.17 amendment:4 require:premium +No Misra C 2012: 22.18 amendment:4 require:premium +No Misra C 2012: 22.19 amendment:4 require:premium +No Misra C 2012: 22.20 amendment:4 require:premium +No Misra C 2012: 23.1 amendment:3 require:premium +No Misra C 2012: 23.2 amendment:3 require:premium +No Misra C 2012: 23.3 amendment:3 require:premium +No Misra C 2012: 23.4 amendment:3 require:premium +No Misra C 2012: 23.5 amendment:3 require:premium +No Misra C 2012: 23.6 amendment:3 require:premium +No Misra C 2012: 23.7 amendment:3 require:premium +No Misra C 2012: 23.8 amendment:3 require:premium + + +Misra C++ 2008 +-------------- +Not available, Cppcheck Premium is not used + + +Misra C++ 2023 +-------------- +Not available, Cppcheck Premium is not used diff --git a/opendbc_repo/opendbc/safety/tests/misra/coverage_table b/opendbc_repo/opendbc/safety/tests/misra/coverage_table new file mode 100644 index 0000000000..0395aba0d6 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/coverage_table @@ -0,0 +1,156 @@ +1.1 +1.2 X (Addon) +1.3 X (Cppcheck) +2.1 X (Cppcheck) +2.2 X (Addon) +2.3 X (Addon) +2.4 X (Addon) +2.5 X (Addon) +2.6 X (Cppcheck) +2.7 X (Addon) +3.1 X (Addon) +3.2 X (Addon) +4.1 X (Addon) +4.2 X (Addon) +5.1 X (Addon) +5.2 X (Addon) +5.3 X (Cppcheck) +5.4 X (Addon) +5.5 X (Addon) +5.6 X (Addon) +5.7 X (Addon) +5.8 X (Addon) +5.9 X (Addon) +6.1 X (Addon) +6.2 X (Addon) +7.1 X (Addon) +7.2 X (Addon) +7.3 X (Addon) +7.4 X (Addon) +8.1 X (Addon) +8.2 X (Addon) +8.3 X (Cppcheck) +8.4 X (Addon) +8.5 X (Addon) +8.6 X (Addon) +8.7 X (Addon) +8.8 X (Addon) +8.9 X (Addon) +8.10 X (Addon) +8.11 X (Addon) +8.12 X (Addon) +8.13 X (Cppcheck) +8.14 X (Addon) +9.1 X (Cppcheck) +9.2 X (Addon) +9.3 X (Addon) +9.4 X (Addon) +9.5 X (Addon) +10.1 X (Addon) +10.2 X (Addon) +10.3 X (Addon) +10.4 X (Addon) +10.5 X (Addon) +10.6 X (Addon) +10.7 X (Addon) +10.8 X (Addon) +11.1 X (Addon) +11.2 X (Addon) +11.3 X (Addon) +11.4 X (Addon) +11.5 X (Addon) +11.6 X (Addon) +11.7 X (Addon) +11.8 X (Addon) +11.9 X (Addon) +12.1 X (Addon) +12.2 X (Addon) +12.3 X (Addon) +12.4 X (Addon) +13.1 X (Addon) +13.2 X (Cppcheck) +13.3 X (Addon) +13.4 X (Addon) +13.5 X (Addon) +13.6 X (Addon) +14.1 X (Addon) +14.2 X (Addon) +14.3 X (Cppcheck) +14.4 X (Addon) +15.1 X (Addon) +15.2 X (Addon) +15.3 X (Addon) +15.4 X (Addon) +15.5 X (Addon) +15.6 X (Addon) +15.7 X (Addon) +16.1 X (Addon) +16.2 X (Addon) +16.3 X (Addon) +16.4 X (Addon) +16.5 X (Addon) +16.6 X (Addon) +16.7 X (Addon) +17.1 X (Addon) +17.2 X (Addon) +17.3 X (Addon) +17.4 X (Cppcheck) +17.5 X (Cppcheck) +17.6 X (Addon) +17.7 X (Addon) +17.8 X (Addon) +18.1 X (Cppcheck) +18.2 X (Cppcheck) +18.3 X (Cppcheck) +18.4 X (Addon) +18.5 X (Addon) +18.6 X (Cppcheck) +18.7 X (Addon) +18.8 X (Addon) +19.1 X (Cppcheck) +19.2 X (Addon) +20.1 X (Addon) +20.2 X (Addon) +20.3 X (Addon) +20.4 X (Addon) +20.5 X (Addon) +20.6 X (Cppcheck) +20.7 X (Addon) +20.8 X (Addon) +20.9 X (Addon) +20.10 X (Addon) +20.11 X (Addon) +20.12 X (Addon) +20.13 X (Addon) +20.14 X (Addon) +21.1 X (Addon) +21.2 X (Addon) +21.3 X (Addon) +21.4 X (Addon) +21.5 X (Addon) +21.6 X (Addon) +21.7 X (Addon) +21.8 X (Addon) +21.9 X (Addon) +21.10 X (Addon) +21.11 X (Addon) +21.12 X (Addon) +21.13 X (Cppcheck) +21.14 X (Addon) +21.15 X (Addon) +21.16 X (Addon) +21.17 X (Cppcheck) +21.18 X (Cppcheck) +21.19 X (Addon) +21.20 X (Addon) +21.21 X (Addon) +22.1 X (Cppcheck) +22.2 X (Cppcheck) +22.3 X (Cppcheck) +22.4 X (Cppcheck) +22.5 X (Addon) +22.6 X (Cppcheck) +22.7 X (Addon) +22.8 X (Addon) +22.9 X (Addon) +22.10 X (Addon) diff --git a/opendbc_repo/opendbc/safety/tests/misra/install.sh b/opendbc_repo/opendbc/safety/tests/misra/install.sh new file mode 100755 index 0000000000..6e7b34deb8 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/install.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +: "${CPPCHECK_DIR:=$DIR/cppcheck/}" + +# skip if we're running in parallel with test_mutation.py +if [ ! -z "$OPENDBC_ROOT" ]; then + exit 0 +fi + +if [ ! -d "$CPPCHECK_DIR" ]; then + git clone https://github.com/danmar/cppcheck.git $CPPCHECK_DIR +fi + +cd $CPPCHECK_DIR + +VERS="2.17.1" +if [ "$(git describe --tags --always)" != "$VERS" ]; then + git fetch --all --tags --force + git checkout $VERS +fi + +#make clean +make MATCHCOMPILTER=yes CXXFLAGS="-O2" -j8 diff --git a/opendbc_repo/opendbc/safety/tests/misra/main.c b/opendbc_repo/opendbc/safety/tests/misra/main.c new file mode 100644 index 0000000000..70a88cf590 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/main.c @@ -0,0 +1,12 @@ +#include "opendbc/safety/safety.h" + +// this file is checked by cppcheck + +// Ignore misra-c2012-8.7 as these functions are only called from libsafety +SAFETY_UNUSED(heartbeat_engaged); + +SAFETY_UNUSED(safety_rx_hook); +SAFETY_UNUSED(safety_tx_hook); +SAFETY_UNUSED(safety_fwd_hook); +SAFETY_UNUSED(safety_tick); +SAFETY_UNUSED(set_safety_hooks); diff --git a/opendbc_repo/opendbc/safety/tests/misra/suppressions.txt b/opendbc_repo/opendbc/safety/tests/misra/suppressions.txt new file mode 100644 index 0000000000..4800a270bc --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/suppressions.txt @@ -0,0 +1,21 @@ +# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well +misra-c2012-11.4 +# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well +misra-c2012-11.5 +# Advisory: as stated in the Misra document, use of goto statements in accordance to 15.2 and 15.3 is ok +misra-c2012-15.1 +# Advisory: union types can be used +misra-c2012-19.2 +# Advisory: The # and ## preprocessor operators should not be used +misra-c2012-20.10 + +# needed since not all of these suppressions are applicable to all builds +unmatchedSuppression + +# All interrupt handlers are defined, including ones we don't use +unusedFunction:*/interrupt_handlers*.h + +# all of the below suppressions are from new checks introduced after updating +# cppcheck from 2.5 -> 2.13. they are listed here to separate the update from +# fixing the violations and all are intended to be removed soon after +misra-c2012-2.5 # unused macros. a few legit, rest aren't common between F4/H7 builds. should we do this in the unusedFunction pass? diff --git a/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh b/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh new file mode 100755 index 0000000000..a94d37d5db --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/test_misra.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +cd $DIR + +source ../../../../setup.sh + +GREEN="\e[1;32m" +YELLOW="\e[1;33m" +RED="\e[1;31m" +NC='\033[0m' + +: "${CPPCHECK_DIR:=$DIR/cppcheck/}" + +# ensure checked in coverage table is up to date +python3 $CPPCHECK_DIR/addons/misra.py -generate-table > coverage_table +if ! git diff --quiet coverage_table; then + echo -e "${YELLOW}MISRA coverage table doesn't match. Update and commit:${NC}" + exit 3 +fi + +cd $BASEDIR + +CHECKLIST=$(mktemp) +echo "Cppcheck checkers list from test_misra.sh:" > $CHECKLIST + +cppcheck() { + # get all gcc defines: arm-none-eabi-gcc -dM -E - < /dev/null + COMMON_DEFINES="-D__GNUC__=9" + + # note that cppcheck build cache results in inconsistent results as of v2.13.0 + OUTPUT=$(mktemp) + + echo -e "\n\n\n\n\nTEST variant options:" >> $CHECKLIST + echo -e ""${@//$BASEDIR/}"\n\n" >> $CHECKLIST # (absolute path removed) + + OPENDBC_ROOT=${OPENDBC_ROOT:-$BASEDIR} + $CPPCHECK_DIR/cppcheck --inline-suppr -I $OPENDBC_ROOT \ + -I "$(gcc -print-file-name=include)" --suppress=*:*gcc*include/* --suppress=*:*clang*include/* \ + --suppressions-list=$DIR/suppressions.txt \ + --error-exitcode=2 --check-level=exhaustive --safety \ + --platform=arm32-wchar_t4 $COMMON_DEFINES --checkers-report=$CHECKLIST.tmp \ + --std=c11 "$@" 2>&1 | tee $OUTPUT + + cat $CHECKLIST.tmp >> $CHECKLIST + rm $CHECKLIST.tmp + # cppcheck bug: some MISRA errors won't result in the error exit code, + # so check the output (https://trac.cppcheck.net/ticket/12440#no1) + if grep -e "misra violation" -e "error" -e "style: " $OUTPUT > /dev/null; then + printf "${RED}** FAILED: MISRA violations found!${NC}\n" + exit 1 + fi +} + +OPTS=" --enable=all --enable=unusedFunction --addon=misra" + +printf "\n${GREEN}** Safety **${NC}\n" +cppcheck $OPTS $BASEDIR/opendbc/safety/tests/misra/main.c + +printf "\n${GREEN}Success!${NC} took $SECONDS seconds\n" + +# ensure list of checkers is up to date +if [ -z "$OPENDBC_ROOT" ]; then + cd $DIR + if ! git diff --quiet $CHECKLIST; then + echo -e "\n${YELLOW}WARNING: Cppcheck checkers.txt report has changed. Review and commit...${NC}" + mv $CHECKLIST $DIR/checkers.txt + exit 4 + fi +fi diff --git a/opendbc_repo/opendbc/safety/tests/misra/test_mutation.py b/opendbc_repo/opendbc/safety/tests/misra/test_mutation.py new file mode 100644 index 0000000000..7c25ad862a --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/misra/test_mutation.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +import os +import glob +import pytest +import shutil +import subprocess +import tempfile +import random + +HERE = os.path.abspath(os.path.dirname(__file__)) +ROOT = os.path.join(HERE, "../../../../") + +IGNORED_PATHS = ( + 'opendbc/safety/main.c', + 'opendbc/safety/tests/', + 'opendbc/safety/board/', +) + +mutations = [ + # no mutation, should pass + (None, None, lambda s: s, False), +] + +patterns = [ + ("misra-c2012-10.3", lambda s: s + "\nvoid test(float len) { for (float j = 0; j < len; j++) {;} }\n"), + ("misra-c2012-13.3", lambda s: s + "\nvoid test(int tmp) { int tmp2 = tmp++ + 2; if (tmp2) {;}}\n"), + ("misra-c2012-13.4", lambda s: s + "\nint test(int x, int y) { return (x=2) && (y=2); }\n"), + ("misra-c2012-13.5", lambda s: s + "\nvoid test(int tmp) { if (true && tmp++) {;} }\n"), + ("misra-c2012-13.6", lambda s: s + "\nvoid test(int tmp) { if (sizeof(tmp++)) {;} }\n"), + ("misra-c2012-14.2", lambda s: s + "\nvoid test(int cnt) { for (cnt=0;;cnt++) {;} }\n"), + ("misra-c2012-14.4", lambda s: s + "\nvoid test(int len) { if (len - 8) {;} }\n"), + ("misra-c2012-16.4", lambda s: s + "\nvoid test(int temp) {switch (temp) { case 1: ; }}\n"), + ("misra-c2012-20.4", lambda s: s + "\n#define auto 1\n"), + ("misra-c2012-20.5", lambda s: s + "\n#define TEST 1\n#undef TEST\n"), +] + +all_files = glob.glob('opendbc/safety/**', root_dir=ROOT, recursive=True) +files = [f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(IGNORED_PATHS)] +assert len(files) > 20, files + +for p in patterns: + mutations.append((random.choice(files), *p, True)) + +mutations = random.sample(mutations, 2) # can remove this once cppcheck is faster + + +@pytest.mark.parametrize("fn, rule, transform, should_fail", mutations) +def test_misra_mutation(fn, rule, transform, should_fail): + with tempfile.TemporaryDirectory() as tmp: + shutil.copytree(ROOT, tmp, dirs_exist_ok=True, + ignore=shutil.ignore_patterns('.venv', 'cppcheck', '.git', '*.ctu-info', '.hypothesis')) + + # apply patch + if fn is not None: + with open(os.path.join(tmp, fn), 'r+') as f: + content = f.read() + f.seek(0) + f.write(transform(content)) + + # run test + r = subprocess.run(f"OPENDBC_ROOT={tmp} opendbc/safety/tests/misra/test_misra.sh", + stdout=subprocess.PIPE, cwd=ROOT, shell=True, encoding='utf8') + print(r.stdout) # helpful for debugging failures + failed = r.returncode != 0 + assert failed == should_fail + if should_fail: + assert rule in r.stdout, "MISRA test failed but not for the correct violation" \ No newline at end of file diff --git a/opendbc_repo/opendbc/safety/tests/mutation.sh b/opendbc_repo/opendbc/safety/tests/mutation.sh new file mode 100755 index 0000000000..29bca60170 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/mutation.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +source $DIR/../../../setup.sh + +GIT_REF="${GIT_REF:-origin/master}" +GIT_ROOT=$(git rev-parse --show-toplevel) +MULL_OPS="mutators: [cxx_increment, cxx_decrement, cxx_comparison, cxx_boundary, cxx_bitwise_assignment, cxx_bitwise, cxx_arithmetic_assignment, cxx_arithmetic, cxx_remove_negation]" +echo -e "$MULL_OPS" > $GIT_ROOT/mull.yml +scons -j$(nproc) -D +echo -e "timeout: 1000000\ngitDiffRef: $GIT_REF\ngitProjectRoot: $GIT_ROOT" >> $GIT_ROOT/mull.yml + +export MUTATION=1 +mull-runner-17 --ld-search-path /lib/x86_64-linux-gnu/ ./libsafety/libsafety_mutation.so -test-program=pytest -- -n8 --ignore-glob=misra/* diff --git a/opendbc_repo/opendbc/safety/tests/safety_replay/__init__.py b/opendbc_repo/opendbc/safety/tests/safety_replay/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/opendbc_repo/opendbc/safety/tests/safety_replay/helpers.py b/opendbc_repo/opendbc/safety/tests/safety_replay/helpers.py new file mode 100644 index 0000000000..4f91a9bf68 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/safety_replay/helpers.py @@ -0,0 +1,109 @@ +from opendbc.car.ford.values import FordSafetyFlags +from opendbc.car.hyundai.values import HyundaiSafetyFlags +from opendbc.car.toyota.values import ToyotaSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py + + +def to_signed(d, bits): + ret = d + if d >= (1 << (bits - 1)): + ret = d - (1 << bits) + return ret + + +def is_steering_msg(mode, param, addr): + ret = False + if mode in (CarParams.SafetyModel.hondaNidec, CarParams.SafetyModel.hondaBosch): + ret = (addr == 0xE4) or (addr == 0x194) or (addr == 0x33D) or (addr == 0x33DA) or (addr == 0x33DB) + elif mode == CarParams.SafetyModel.toyota: + ret = addr == (0x191 if param & ToyotaSafetyFlags.LTA else 0x2E4) + elif mode == CarParams.SafetyModel.gm: + ret = addr == 384 + elif mode in (CarParams.SafetyModel.hyundai, CarParams.SafetyModel.hyundaiLegacy): + ret = addr == 832 + elif mode == CarParams.SafetyModel.hyundaiCanfd: + ret = addr == (0x110 if param & HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT else + 0x50 if param & HyundaiSafetyFlags.CANFD_LKA_STEERING else + 0x12A) + elif mode == CarParams.SafetyModel.chrysler: + ret = addr == 0x292 + elif mode == CarParams.SafetyModel.subaru: + ret = addr == 0x122 + elif mode == CarParams.SafetyModel.ford: + ret = addr == 0x3d6 if param & FordSafetyFlags.CANFD else addr == 0x3d3 + elif mode == CarParams.SafetyModel.nissan: + ret = addr == 0x169 + elif mode == CarParams.SafetyModel.rivian: + ret = addr == 0x120 + elif mode == CarParams.SafetyModel.tesla: + ret = addr == 0x488 + return ret + + +def get_steer_value(mode, param, msg): + # TODO: use CANParser + torque, angle = 0, 0 + if mode in (CarParams.SafetyModel.hondaNidec, CarParams.SafetyModel.hondaBosch): + torque = (msg.data[0] << 8) | msg.data[1] + torque = to_signed(torque, 16) + elif mode == CarParams.SafetyModel.toyota: + if param & ToyotaSafetyFlags.LTA: + angle = (msg.data[1] << 8) | msg.data[2] + angle = to_signed(angle, 16) + else: + torque = (msg.data[1] << 8) | (msg.data[2]) + torque = to_signed(torque, 16) + elif mode == CarParams.SafetyModel.gm: + torque = ((msg.data[0] & 0x7) << 8) | msg.data[1] + torque = to_signed(torque, 11) + elif mode in (CarParams.SafetyModel.hyundai, CarParams.SafetyModel.hyundaiLegacy): + torque = (((msg.data[3] & 0x7) << 8) | msg.data[2]) - 1024 + elif mode == CarParams.SafetyModel.hyundaiCanfd: + torque = ((msg.data[5] >> 1) | (msg.data[6] & 0xF) << 7) - 1024 + elif mode == CarParams.SafetyModel.chrysler: + torque = (((msg.data[0] & 0x7) << 8) | msg.data[1]) - 1024 + elif mode == CarParams.SafetyModel.subaru: + torque = ((msg.data[3] & 0x1F) << 8) | msg.data[2] + torque = -to_signed(torque, 13) + elif mode == CarParams.SafetyModel.ford: + if param & FordSafetyFlags.CANFD: + angle = ((msg.data[2] << 3) | (msg.data[3] >> 5)) - 1000 + else: + angle = ((msg.data[0] << 3) | (msg.data[1] >> 5)) - 1000 + elif mode == CarParams.SafetyModel.nissan: + angle = (msg.data[0] << 10) | (msg.data[1] << 2) | (msg.data[2] >> 6) + angle = -angle + (1310 * 100) + elif mode == CarParams.SafetyModel.rivian: + torque = ((msg.data[2] << 3) | (msg.data[3] >> 5)) - 1024 + elif mode == CarParams.SafetyModel.tesla: + angle = (((msg.data[0] & 0x7F) << 8) | (msg.data[1])) - 16384 # ceil(1638.35/0.1) + return torque, angle + + +def package_can_msg(msg): + return libsafety_py.make_CANPacket(msg.address, msg.src % 4, msg.dat) + + +def init_segment(safety, msgs, mode, param): + sendcan = (msg for msg in msgs if msg.which() == 'sendcan') + steering_msgs = (can for msg in sendcan for can in msg.sendcan if is_steering_msg(mode, param, can.address)) + + msg = next(steering_msgs, None) + if msg is None: + print("no steering msgs found!") + return + + msg = package_can_msg(msg) + torque, angle = get_steer_value(mode, param, msg) + if torque != 0: + safety.set_controls_allowed(1) + safety.set_desired_torque_last(torque) + safety.set_rt_torque_last(torque) + safety.set_torque_meas(torque, torque) + safety.set_torque_driver(torque, torque) + elif angle != 0: + safety.set_controls_allowed(1) + safety.set_desired_angle_last(angle) + safety.set_angle_meas(angle, angle) + assert safety.safety_tx_hook(msg), "failed to initialize safety for segment" diff --git a/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py b/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py new file mode 100755 index 0000000000..c829cbc216 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/safety_replay/replay_drive.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +import argparse +from collections import Counter +from tqdm import tqdm + +from opendbc.car.carlog import carlog +from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests.safety_replay.helpers import package_can_msg, init_segment + + +# replay a drive to check for safety violations +def replay_drive(msgs, safety_mode, param, alternative_experience): + safety = libsafety_py.libsafety + msgs.sort(key=lambda m: m.logMonoTime) + + err = safety.set_safety_hooks(safety_mode, param) + assert err == 0, "invalid safety mode: %d" % safety_mode + safety.set_alternative_experience(alternative_experience) + + init_segment(safety, msgs, safety_mode, param) + + rx_tot, rx_invalid, tx_tot, tx_blocked, tx_controls, tx_controls_blocked = 0, 0, 0, 0, 0, 0 + safety_tick_rx_invalid = False + blocked_addrs = Counter() + invalid_addrs = set() + + can_msgs = [m for m in msgs if m.which() in ('can', 'sendcan')] + start_t = can_msgs[0].logMonoTime + end_t = can_msgs[-1].logMonoTime + for msg in tqdm(can_msgs): + safety.set_timer((msg.logMonoTime // 1000) % 0xFFFFFFFF) + + # skip start and end of route, warm up/down period + if msg.logMonoTime - start_t > 1e9 and end_t - msg.logMonoTime > 1e9: + safety.safety_tick_current_safety_config() + safety_tick_rx_invalid |= not safety.safety_config_valid() or safety_tick_rx_invalid + + if msg.which() == 'sendcan': + for canmsg in msg.sendcan: + _msg = package_can_msg(canmsg) + sent = safety.safety_tx_hook(_msg) + if not sent: + tx_blocked += 1 + tx_controls_blocked += safety.get_controls_allowed() + blocked_addrs[canmsg.address] += 1 + + carlog.debug("blocked bus %d msg %d at %f" % (canmsg.src, canmsg.address, (msg.logMonoTime - start_t) / 1e9)) + tx_controls += safety.get_controls_allowed() + tx_tot += 1 + elif msg.which() == 'can': + # ignore msgs we sent + for canmsg in filter(lambda m: m.src < 128, msg.can): + safety.safety_fwd_hook(canmsg.src, canmsg.address) + _msg = package_can_msg(canmsg) + recv = safety.safety_rx_hook(_msg) + if not recv: + rx_invalid += 1 + invalid_addrs.add(canmsg.address) + rx_tot += 1 + + print("\nRX") + print("total rx msgs:", rx_tot) + print("invalid rx msgs:", rx_invalid) + print("safety tick rx invalid:", safety_tick_rx_invalid) + print("invalid addrs:", invalid_addrs) + print("\nTX") + print("total openpilot msgs:", tx_tot) + print("total msgs with controls allowed:", tx_controls) + print("blocked msgs:", tx_blocked) + print("blocked with controls allowed:", tx_controls_blocked) + print("blocked addrs:", blocked_addrs) + + return tx_controls_blocked == 0 and rx_invalid == 0 and not safety_tick_rx_invalid + + +if __name__ == "__main__": + from openpilot.tools.lib.logreader import LogReader + + parser = argparse.ArgumentParser(description="Replay CAN messages from a route or segment through a safety mode", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("route_or_segment_name", nargs='+') + parser.add_argument("--mode", type=int, help="Override the safety mode from the log") + parser.add_argument("--param", type=int, help="Override the safety param from the log") + parser.add_argument("--alternative-experience", type=int, help="Override the alternative experience from the log") + args = parser.parse_args() + + lr = LogReader(args.route_or_segment_name[0]) + + if None in (args.mode, args.param, args.alternative_experience): + CP = lr.first('carParams') + if args.mode is None: + args.mode = CP.safetyConfigs[-1].safetyModel.raw + if args.param is None: + args.param = CP.safetyConfigs[-1].safetyParam + if args.alternative_experience is None: + args.alternative_experience = CP.alternativeExperience + + print(f"replaying {args.route_or_segment_name[0]} with safety mode {args.mode}, param {args.param}, alternative experience {args.alternative_experience}") + replay_drive(list(lr), args.mode, args.param, args.alternative_experience) diff --git a/opendbc_repo/opendbc/safety/tests/test.sh b/opendbc_repo/opendbc/safety/tests/test.sh new file mode 100755 index 0000000000..a5cc83a942 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +source ../../../setup.sh + +# reset coverage data and generate gcc note file +rm -f ./libsafety/*.gcda +if [ "$1" == "--ubsan" ]; then + scons -j$(nproc) -D --ubsan +else + scons -j$(nproc) -D +fi + +# run safety tests and generate coverage data +pytest -n8 --ignore-glob=misra/* + +# generate and open report +if [ "$1" == "--report" ]; then + mkdir -p coverage-out + gcovr -r ../ --html-nested coverage-out/index.html + sensible-browser coverage-out/index.html +fi + +# test coverage +GCOV="gcovr -r $DIR/../ -d --fail-under-line=100 -e ^libsafety -e ^../board" +if ! GCOV_OUTPUT="$($GCOV)"; then + echo -e "FAILED:\n$GCOV_OUTPUT" + exit 1 +else + echo "SUCCESS: All checked files have 100% coverage!" +fi diff --git a/opendbc_repo/opendbc/safety/tests/test_body.py b/opendbc_repo/opendbc/safety/tests/test_body.py new file mode 100755 index 0000000000..ae98712ce4 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_body.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.structs import CarParams +import opendbc.safety.tests.common as common +from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests.common import CANPackerSafety + + +class TestBody(common.SafetyTest): + TX_MSGS = [[0x250, 0], [0x251, 0], + [0x1, 0], [0x1, 1], [0x1, 2], [0x1, 3]] + FWD_BUS_LOOKUP = {} + + def setUp(self): + self.packer = CANPackerSafety("comma_body") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.body, 0) + self.safety.init_tests() + + def _motors_data_msg(self, speed_l, speed_r): + values = {"SPEED_L": speed_l, "SPEED_R": speed_r} + return self.packer.make_can_msg_safety("MOTORS_DATA", 0, values) + + def _torque_cmd_msg(self, torque_l, torque_r): + values = {"TORQUE_L": torque_l, "TORQUE_R": torque_r} + return self.packer.make_can_msg_safety("TORQUE_CMD", 0, values) + + def _max_motor_rpm_cmd_msg(self, max_rpm_l, max_rpm_r): + values = {"MAX_RPM_L": max_rpm_l, "MAX_RPM_R": max_rpm_r} + return self.packer.make_can_msg_safety("MAX_MOTOR_RPM_CMD", 0, values) + + def test_rx_hook(self): + self.assertFalse(self.safety.get_controls_allowed()) + + # controls allowed when we get MOTORS_DATA message + self.assertTrue(self._rx(self._torque_cmd_msg(0, 0))) + self.assertFalse(self.safety.get_controls_allowed()) + + self.assertTrue(self._rx(self._motors_data_msg(0, 0))) + self.assertTrue(self.safety.get_controls_allowed()) + + def test_tx_hook(self): + self.assertFalse(self._tx(self._torque_cmd_msg(0, 0))) + self.safety.set_controls_allowed(True) + self.assertTrue(self._tx(self._torque_cmd_msg(0, 0))) + + def test_can_flasher(self): + # CAN flasher always allowed + self.safety.set_controls_allowed(False) + self.assertTrue(self._tx(common.make_msg(0, 0x1, 8))) + + # 0xdeadfaceU allowed for CAN flashing mode + self.assertTrue(self._tx(common.make_msg(0, 0x250, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))) + self.assertFalse(self._tx(common.make_msg(0, 0x250, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0'))) # not correct data/len + self.assertFalse(self._tx(common.make_msg(0, 0x251, dat=b'\xce\xfa\xad\xde\x1e\x0b\xb0\x0a'))) # wrong address + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_chrysler.py b/opendbc_repo/opendbc/safety/tests/test_chrysler.py new file mode 100755 index 0000000000..daa585abf2 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_chrysler.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.chrysler.values import ChryslerSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + + +class TestChryslerSafety(common.CarSafetyTest, common.MotorTorqueSteeringSafetyTest): + TX_MSGS = [[0x23B, 0], [0x292, 0], [0x2A6, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x292, 0x2A6)} + FWD_BLACKLISTED_ADDRS = {2: [0x292, 0x2A6]} + + MAX_RATE_UP = 3 + MAX_RATE_DOWN = 3 + MAX_TORQUE_LOOKUP = [0], [261] + MAX_RT_DELTA = 112 + MAX_TORQUE_ERROR = 80 + + LKAS_ACTIVE_VALUE = 1 + + DAS_BUS = 0 + + def setUp(self): + self.packer = CANPackerSafety("chrysler_pacifica_2017_hybrid_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, 0) + self.safety.init_tests() + + def _button_msg(self, cancel=False, resume=False): + values = {"ACC_Cancel": cancel, "ACC_Resume": resume} + return self.packer.make_can_msg_safety("CRUISE_BUTTONS", self.DAS_BUS, values) + + def _pcm_status_msg(self, enable): + values = {"ACC_ACTIVE": enable} + return self.packer.make_can_msg_safety("DAS_3", self.DAS_BUS, values) + + def _speed_msg(self, speed): + values = {"SPEED_LEFT": speed, "SPEED_RIGHT": speed} + return self.packer.make_can_msg_safety("SPEED_1", 0, values) + + def _user_gas_msg(self, gas): + values = {"Accelerator_Position": gas} + return self.packer.make_can_msg_safety("ECM_5", 0, values) + + def _user_brake_msg(self, brake): + values = {"Brake_Pedal_State": 1 if brake else 0} + return self.packer.make_can_msg_safety("ESP_1", 0, values) + + def _torque_meas_msg(self, torque): + values = {"EPS_TORQUE_MOTOR": torque} + return self.packer.make_can_msg_safety("EPS_2", 0, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"STEERING_TORQUE": torque, "LKAS_CONTROL_BIT": self.LKAS_ACTIVE_VALUE if steer_req else 0} + return self.packer.make_can_msg_safety("LKAS_COMMAND", 0, values) + + def test_buttons(self): + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + + # resume only while controls allowed + self.assertEqual(controls_allowed, self._tx(self._button_msg(resume=True))) + + # can always cancel + self.assertTrue(self._tx(self._button_msg(cancel=True))) + + # only one button at a time + self.assertFalse(self._tx(self._button_msg(cancel=True, resume=True))) + self.assertFalse(self._tx(self._button_msg(cancel=False, resume=False))) + + +class TestChryslerRamDTSafety(TestChryslerSafety): + TX_MSGS = [[0xB1, 2], [0xA6, 0], [0xFA, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0xA6, 0xFA)} + FWD_BLACKLISTED_ADDRS = {2: [0xA6, 0xFA]} + + MAX_RATE_UP = 6 + MAX_RATE_DOWN = 6 + MAX_TORQUE_LOOKUP = [0], [350] + + DAS_BUS = 2 + + LKAS_ACTIVE_VALUE = 2 + + def setUp(self): + self.packer = CANPackerSafety("chrysler_ram_dt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, ChryslerSafetyFlags.RAM_DT) + self.safety.init_tests() + + def _speed_msg(self, speed): + values = {"Vehicle_Speed": speed} + return self.packer.make_can_msg_safety("ESP_8", 0, values) + + +class TestChryslerRamHDSafety(TestChryslerSafety): + TX_MSGS = [[0x275, 0], [0x276, 0], [0x23A, 2]] + RELAY_MALFUNCTION_ADDRS = {0: (0x276, 0x275)} + FWD_BLACKLISTED_ADDRS = {2: [0x275, 0x276]} + + MAX_TORQUE_LOOKUP = [0], [361] + MAX_RATE_UP = 14 + MAX_RATE_DOWN = 14 + MAX_RT_DELTA = 182 + + DAS_BUS = 2 + + LKAS_ACTIVE_VALUE = 2 + + def setUp(self): + self.packer = CANPackerSafety("chrysler_ram_hd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.chrysler, ChryslerSafetyFlags.RAM_HD) + self.safety.init_tests() + + def _speed_msg(self, speed): + values = {"Vehicle_Speed": speed} + return self.packer.make_can_msg_safety("ESP_8", 0, values) + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_defaults.py b/opendbc_repo/opendbc/safety/tests/test_defaults.py new file mode 100755 index 0000000000..4e5961544f --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_defaults.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +import unittest + +import opendbc.safety.tests.common as common +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py + + +class TestDefaultRxHookBase(common.SafetyTest): + FWD_BUS_LOOKUP = {} + + def test_rx_hook(self): + # default rx hook allows all msgs + for bus in range(4): + for addr in self.SCANNED_ADDRS: + self.assertTrue(self._rx(common.make_msg(bus, addr, 8)), f"failed RX {addr=}") + + +class TestNoOutput(TestDefaultRxHookBase): + TX_MSGS = [] + + def setUp(self): + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.noOutput, 0) + self.safety.init_tests() + + +class TestSilent(TestNoOutput): + """SILENT uses same hooks as NOOUTPUT""" + + def setUp(self): + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.silent, 0) + self.safety.init_tests() + + +class TestAllOutput(TestDefaultRxHookBase): + # Allow all messages + TX_MSGS = [[addr, bus] for addr in common.SafetyTest.SCANNED_ADDRS + for bus in range(4)] + + def setUp(self): + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.allOutput, 0) + self.safety.init_tests() + + def test_spam_can_buses(self): + # asserts tx allowed for all scanned addrs + for bus in range(4): + for addr in self.SCANNED_ADDRS: + should_tx = [addr, bus] in self.TX_MSGS + self.assertEqual(should_tx, self._tx(common.make_msg(bus, addr, 8)), f"allowed TX {addr=} {bus=}") + + def test_default_controls_not_allowed(self): + # controls always allowed + self.assertTrue(self.safety.get_controls_allowed()) + + def test_tx_hook_on_wrong_safety_mode(self): + # No point, since we allow all messages + pass + + +class TestAllOutputPassthrough(TestAllOutput): + FWD_BLACKLISTED_ADDRS = {} + FWD_BUS_LOOKUP = {0: 2, 2: 0} + + def setUp(self): + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.allOutput, 1) + self.safety.init_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_elm327.py b/opendbc_repo/opendbc/safety/tests/test_elm327.py new file mode 100755 index 0000000000..eb703e16db --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_elm327.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import unittest + +import opendbc.safety.tests.common as common +from opendbc.car.structs import CarParams +from opendbc.safety import DLC_TO_LEN +from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests.test_defaults import TestDefaultRxHookBase + +GM_CAMERA_DIAG_ADDR = 0x24B + + +class TestElm327(TestDefaultRxHookBase): + TX_MSGS = [[addr, bus] for addr in [GM_CAMERA_DIAG_ADDR, *range(0x600, 0x800), + *range(0x18DA00F1, 0x18DB00F1, 0x100), # 29-bit UDS physical addressing + *[0x18DB33F1], # 29-bit UDS functional address + ] for bus in range(4)] + FWD_BUS_LOOKUP = {} + + def setUp(self): + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.elm327, 0) + self.safety.init_tests() + + def test_tx_hook(self): + # ensure we can transmit arbitrary data on allowed addresses + for bus in range(4): + for addr in self.SCANNED_ADDRS: + should_tx = [addr, bus] in self.TX_MSGS + self.assertEqual(should_tx, self._tx(common.make_msg(bus, addr, 8))) + + # ELM only allows 8 byte UDS/KWP messages under ISO 15765-4 + for msg_len in DLC_TO_LEN: + should_tx = msg_len == 8 + self.assertEqual(should_tx, self._tx(common.make_msg(0, 0x700, msg_len))) + + # TODO: perform this check for all addresses + # 4 to 15 are reserved ISO-TP frame types (https://en.wikipedia.org/wiki/ISO_15765-2) + for byte in range(0xff): + should_tx = (byte >> 4) <= 3 + self.assertEqual(should_tx, self._tx(common.make_msg(0, GM_CAMERA_DIAG_ADDR, dat=bytes([byte] * 8)))) + + # test GM camera diagnostic address with malformed length + self.assertEqual(False, self._tx(common.make_msg(0, GM_CAMERA_DIAG_ADDR, dat=bytes([0x00] * 7)))) + + def test_tx_hook_on_wrong_safety_mode(self): + # No point, since we allow many diagnostic addresses + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_ford.py b/opendbc_repo/opendbc/safety/tests/test_ford.py new file mode 100755 index 0000000000..f8cc80e0cc --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_ford.py @@ -0,0 +1,498 @@ +#!/usr/bin/env python3 +import numpy as np +import random +import unittest + +import opendbc.safety.tests.common as common +from opendbc.car.ford.carcontroller import MAX_LATERAL_ACCEL +from opendbc.car.ford.values import FordSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +from opendbc.safety.tests.common import CANPackerSafety + +MSG_EngBrakeData = 0x165 # RX from PCM, for driver brake pedal and cruise state +MSG_EngVehicleSpThrottle = 0x204 # RX from PCM, for driver throttle input +MSG_BrakeSysFeatures = 0x415 # RX from ABS, for vehicle speed +MSG_EngVehicleSpThrottle2 = 0x202 # RX from PCM, for second vehicle speed +MSG_Yaw_Data_FD1 = 0x91 # RX from RCM, for yaw rate +MSG_Steering_Data_FD1 = 0x083 # TX by OP, various driver switches and LKAS/CC buttons +MSG_ACCDATA = 0x186 # TX by OP, ACC controls +MSG_ACCDATA_3 = 0x18A # TX by OP, ACC/TJA user interface +MSG_Lane_Assist_Data1 = 0x3CA # TX by OP, Lane Keep Assist +MSG_LateralMotionControl = 0x3D3 # TX by OP, Lateral Control message +MSG_LateralMotionControl2 = 0x3D6 # TX by OP, alternate Lateral Control message +MSG_IPMA_Data = 0x3D8 # TX by OP, IPMA and LKAS user interface + + +def checksum(msg): + addr, dat, bus = msg + ret = bytearray(dat) + + if addr == MSG_Yaw_Data_FD1: + chksum = dat[0] + dat[1] # VehRol_W_Actl + chksum += dat[2] + dat[3] # VehYaw_W_Actl + chksum += dat[5] # VehRollYaw_No_Cnt + chksum += dat[6] >> 6 # VehRolWActl_D_Qf + chksum += (dat[6] >> 4) & 0x3 # VehYawWActl_D_Qf + chksum = 0xff - (chksum & 0xff) + ret[4] = chksum + + elif addr == MSG_BrakeSysFeatures: + chksum = dat[0] + dat[1] # Veh_V_ActlBrk + chksum += (dat[2] >> 2) & 0xf # VehVActlBrk_No_Cnt + chksum += dat[2] >> 6 # VehVActlBrk_D_Qf + chksum = 0xff - (chksum & 0xff) + ret[3] = chksum + + elif addr == MSG_EngVehicleSpThrottle2: + chksum = (dat[2] >> 3) & 0xf # VehVActlEng_No_Cnt + chksum += (dat[4] >> 5) & 0x3 # VehVActlEng_D_Qf + chksum += dat[6] + dat[7] # Veh_V_ActlEng + chksum = 0xff - (chksum & 0xff) + ret[1] = chksum + + return addr, ret, bus + + +class Buttons: + CANCEL = 0 + RESUME = 1 + TJA_TOGGLE = 2 + + +# Ford safety has four different configurations tested here: +# * CAN with openpilot longitudinal +# * CAN FD with stock longitudinal +# * CAN FD with openpilot longitudinal + +class TestFordSafetyBase(common.CarSafetyTest): + STANDSTILL_THRESHOLD = 1 + RELAY_MALFUNCTION_ADDRS = {0: (MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl, + MSG_LateralMotionControl2, MSG_IPMA_Data)} + + FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl, + MSG_LateralMotionControl2, MSG_IPMA_Data]} + + STEER_MESSAGE = 0 + + # Curvature control limits + DEG_TO_CAN = 50000 # 1 / (2e-5) rad to can + MAX_CURVATURE = 0.02 + MAX_CURVATURE_ERROR = 0.002 + CURVATURE_ERROR_MIN_SPEED = 10.0 # m/s + + ANGLE_RATE_BP = [5., 25., 25.] + ANGLE_RATE_UP = [0.00045, 0.0001, 0.0001] # windup limit + ANGLE_RATE_DOWN = [0.00045, 0.00015, 0.00015] # unwind limit + + cnt_speed = 0 + cnt_speed_2 = 0 + cnt_yaw_rate = 0 + + packer: CANPackerSafety + safety: libsafety_py.LibSafety + + def get_canfd_curvature_limits(self, speed): + # Round it in accordance with the safety + curvature_accel_limit = MAX_LATERAL_ACCEL / (max(speed, 1) ** 2) + curvature_accel_limit_lower = int(curvature_accel_limit * self.DEG_TO_CAN - 1) / self.DEG_TO_CAN + curvature_accel_limit_upper = int(curvature_accel_limit * self.DEG_TO_CAN + 1) / self.DEG_TO_CAN + return curvature_accel_limit_lower, curvature_accel_limit_upper + + def _set_prev_desired_angle(self, t): + t = round(t * self.DEG_TO_CAN) + self.safety.set_desired_angle_last(t) + + def _reset_curvature_measurement(self, curvature, speed): + for _ in range(6): + self._rx(self._speed_msg(speed)) + self._rx(self._yaw_rate_msg(curvature, speed)) + + # Driver brake pedal + def _user_brake_msg(self, brake: bool): + # brake pedal and cruise state share same message, so we have to send + # the other signal too + enable = self.safety.get_controls_allowed() + values = { + "BpedDrvAppl_D_Actl": 2 if brake else 1, + "CcStat_D_Actl": 5 if enable else 0, + } + return self.packer.make_can_msg_safety("EngBrakeData", 0, values) + + # ABS vehicle speed + def _speed_msg(self, speed: float, quality_flag=True): + values = {"Veh_V_ActlBrk": speed * 3.6, "VehVActlBrk_D_Qf": 3 if quality_flag else 0, "VehVActlBrk_No_Cnt": self.cnt_speed % 16} + self.__class__.cnt_speed += 1 + return self.packer.make_can_msg_safety("BrakeSysFeatures", 0, values, fix_checksum=checksum) + + # PCM vehicle speed + def _speed_msg_2(self, speed: float, quality_flag=True): + # Ford relies on speed for driver curvature limiting, so it checks two sources + values = {"Veh_V_ActlEng": speed * 3.6, "VehVActlEng_D_Qf": 3 if quality_flag else 0, "VehVActlEng_No_Cnt": self.cnt_speed_2 % 16} + self.__class__.cnt_speed_2 += 1 + return self.packer.make_can_msg_safety("EngVehicleSpThrottle2", 0, values, fix_checksum=checksum) + + # Standstill state + def _vehicle_moving_msg(self, speed: float): + values = {"VehStop_D_Stat": 1 if speed <= self.STANDSTILL_THRESHOLD else random.choice((0, 2, 3))} + return self.packer.make_can_msg_safety("DesiredTorqBrk", 0, values) + + # Current curvature + def _yaw_rate_msg(self, curvature: float, speed: float, quality_flag=True): + values = {"VehYaw_W_Actl": curvature * speed, "VehYawWActl_D_Qf": 3 if quality_flag else 0, + "VehRollYaw_No_Cnt": self.cnt_yaw_rate % 256} + self.__class__.cnt_yaw_rate += 1 + return self.packer.make_can_msg_safety("Yaw_Data_FD1", 0, values, fix_checksum=checksum) + + # Drive throttle input + def _user_gas_msg(self, gas: float): + values = {"ApedPos_Pc_ActlArb": gas} + return self.packer.make_can_msg_safety("EngVehicleSpThrottle", 0, values) + + # Cruise status + def _pcm_status_msg(self, enable: bool): + # brake pedal and cruise state share same message, so we have to send + # the other signal too + brake = self.safety.get_brake_pressed_prev() + values = { + "BpedDrvAppl_D_Actl": 2 if brake else 1, + "CcStat_D_Actl": 5 if enable else 0, + } + return self.packer.make_can_msg_safety("EngBrakeData", 0, values) + + # LKAS command + def _lkas_command_msg(self, action: int): + values = { + "LkaActvStats_D2_Req": action, + } + return self.packer.make_can_msg_safety("Lane_Assist_Data1", 0, values) + + # LCA command + def _lat_ctl_msg(self, enabled: bool, path_offset: float, path_angle: float, curvature: float, curvature_rate: float): + if self.STEER_MESSAGE == MSG_LateralMotionControl: + values = { + "LatCtl_D_Rq": 1 if enabled else 0, + "LatCtlPathOffst_L_Actl": path_offset, # Path offset [-5.12|5.11] meter + "LatCtlPath_An_Actl": path_angle, # Path angle [-0.5|0.5235] radians + "LatCtlCurv_NoRate_Actl": curvature_rate, # Curvature rate [-0.001024|0.00102375] 1/meter^2 + "LatCtlCurv_No_Actl": curvature, # Curvature [-0.02|0.02094] 1/meter + } + return self.packer.make_can_msg_safety("LateralMotionControl", 0, values) + elif self.STEER_MESSAGE == MSG_LateralMotionControl2: + values = { + "LatCtl_D2_Rq": 1 if enabled else 0, + "LatCtlPathOffst_L_Actl": path_offset, # Path offset [-5.12|5.11] meter + "LatCtlPath_An_Actl": path_angle, # Path angle [-0.5|0.5235] radians + "LatCtlCrv_NoRate2_Actl": curvature_rate, # Curvature rate [-0.001024|0.001023] 1/meter^2 + "LatCtlCurv_No_Actl": curvature, # Curvature [-0.02|0.02094] 1/meter + } + return self.packer.make_can_msg_safety("LateralMotionControl2", 0, values) + + # Cruise control buttons + def _acc_button_msg(self, button: int, bus: int): + values = { + "CcAslButtnCnclPress": 1 if button == Buttons.CANCEL else 0, + "CcAsllButtnResPress": 1 if button == Buttons.RESUME else 0, + "TjaButtnOnOffPress": 1 if button == Buttons.TJA_TOGGLE else 0, + } + return self.packer.make_can_msg_safety("Steering_Data_FD1", bus, values) + + def test_rx_hook(self): + # checksum, counter, and quality flag checks + for quality_flag in [True, False]: + for msg_type in ["speed", "speed_2", "yaw"]: + self.safety.set_controls_allowed(True) + # send multiple times to verify counter checks + for _ in range(10): + if msg_type == "speed": + msg = self._speed_msg(0, quality_flag=quality_flag) + elif msg_type == "speed_2": + msg = self._speed_msg_2(0, quality_flag=quality_flag) + elif msg_type == "yaw": + msg = self._yaw_rate_msg(0, 0, quality_flag=quality_flag) + + self.assertEqual(quality_flag, self._rx(msg)) + self.assertEqual(quality_flag, self.safety.get_controls_allowed()) + + # Mess with checksum to make it fail, checksum is not checked for 2nd speed + msg[0].data[3] = 0 # Speed checksum & half of yaw signal + should_rx = msg_type == "speed_2" and quality_flag + self.assertEqual(should_rx, self._rx(msg)) + self.assertEqual(should_rx, self.safety.get_controls_allowed()) + + def test_angle_measurements(self): + """Tests rx hook correctly parses the curvature measurement from the vehicle speed and yaw rate""" + for speed in np.arange(0.5, 40, 0.5): + for curvature in np.arange(0, self.MAX_CURVATURE * 2, 2e-3): + self._rx(self._speed_msg(speed)) + for c in (curvature, -curvature, 0, 0, 0, 0): + self._rx(self._yaw_rate_msg(c, speed)) + + self.assertEqual(self.safety.get_angle_meas_min(), round(-curvature * self.DEG_TO_CAN)) + self.assertEqual(self.safety.get_angle_meas_max(), round(curvature * self.DEG_TO_CAN)) + + self._rx(self._yaw_rate_msg(0, speed)) + self.assertEqual(self.safety.get_angle_meas_min(), round(-curvature * self.DEG_TO_CAN)) + self.assertEqual(self.safety.get_angle_meas_max(), 0) + + self._rx(self._yaw_rate_msg(0, speed)) + self.assertEqual(self.safety.get_angle_meas_min(), 0) + self.assertEqual(self.safety.get_angle_meas_max(), 0) + + def test_max_lateral_acceleration(self): + # Ford CAN FD can achieve a higher max lateral acceleration than CAN so we limit curvature based on speed + for speed in np.arange(0, 40, 0.5): + # Clip so we test curvature limiting at low speed due to low max curvature + _, curvature_accel_limit_upper = self.get_canfd_curvature_limits(speed) + curvature_accel_limit_upper = np.clip(curvature_accel_limit_upper, -self.MAX_CURVATURE, self.MAX_CURVATURE) + + for sign in (-1, 1): + # Test above and below the lateral by 20%, max is clipped since + # max curvature at low speed is higher than the signal max + for curvature in np.arange(curvature_accel_limit_upper * 0.8, min(curvature_accel_limit_upper * 1.2, self.MAX_CURVATURE), 1 / self.DEG_TO_CAN): + curvature = sign * round(curvature * self.DEG_TO_CAN) / self.DEG_TO_CAN # fix np rounding errors + self.safety.set_controls_allowed(True) + self._set_prev_desired_angle(curvature) + self._reset_curvature_measurement(curvature, speed) + + should_tx = abs(curvature) <= curvature_accel_limit_upper + self.assertEqual(should_tx, self._tx(self._lat_ctl_msg(True, 0, 0, curvature, 0))) + + def test_steer_allowed(self): + path_offsets = np.arange(-5.12, 5.11, 2.5).round() + path_angles = np.arange(-0.5, 0.5235, 0.25).round(1) + curvature_rates = np.arange(-0.001024, 0.00102375, 0.001).round(3) + curvatures = np.arange(-0.02, 0.02094, 0.01).round(2) + + for speed in (self.CURVATURE_ERROR_MIN_SPEED - 1, + self.CURVATURE_ERROR_MIN_SPEED + 1): + _, curvature_accel_limit_upper = self.get_canfd_curvature_limits(speed) + for controls_allowed in (True, False): + for steer_control_enabled in (True, False): + for path_offset in path_offsets: + for path_angle in path_angles: + for curvature_rate in curvature_rates: + for curvature in curvatures: + self.safety.set_controls_allowed(controls_allowed) + self._set_prev_desired_angle(curvature) + self._reset_curvature_measurement(curvature, speed) + + should_tx = path_offset == 0 and path_angle == 0 and curvature_rate == 0 + # when request bit is 0, only allow curvature of 0 since the signal range + # is not large enough to enforce it tracking measured + should_tx = should_tx and (controls_allowed if steer_control_enabled else curvature == 0) + + # Only CAN FD has the max lateral acceleration limit + if self.STEER_MESSAGE == MSG_LateralMotionControl2: + should_tx = should_tx and abs(curvature) <= curvature_accel_limit_upper + + with self.subTest(controls_allowed=controls_allowed, steer_control_enabled=steer_control_enabled, + path_offset=float(path_offset), path_angle=float(path_angle), curvature_rate=float(curvature_rate), + curvature=float(curvature)): + self.assertEqual(should_tx, self._tx(self._lat_ctl_msg(steer_control_enabled, path_offset, path_angle, curvature, curvature_rate))) + + def test_curvature_rate_limits(self): + """ + When the curvature error is exceeded, commanded curvature must start moving towards meas respecting rate limits. + Since safety allows higher rate limits to avoid false positives, we need to allow a lower rate to move towards meas. + """ + self.safety.set_controls_allowed(True) + # safety fudges the speed (1 m/s) and rate limits (1 CAN unit) to avoid false positives + small_curvature = 1 / self.DEG_TO_CAN # significant small amount of curvature to cross boundary + + for speed in np.arange(0, 40, 0.5): + curvature_accel_limit_lower, curvature_accel_limit_upper = self.get_canfd_curvature_limits(speed) + limit_command = speed > self.CURVATURE_ERROR_MIN_SPEED + # ensure our limits match the safety's rounded limits + max_delta_up = int(np.interp(speed - 1, self.ANGLE_RATE_BP, self.ANGLE_RATE_UP) * self.DEG_TO_CAN + 1) / self.DEG_TO_CAN + max_delta_up_lower = int(np.interp(speed + 1, self.ANGLE_RATE_BP, self.ANGLE_RATE_UP) * self.DEG_TO_CAN - 1) / self.DEG_TO_CAN + + max_delta_down = int(np.interp(speed - 1, self.ANGLE_RATE_BP, self.ANGLE_RATE_DOWN) * self.DEG_TO_CAN + 1 + 1e-3) / self.DEG_TO_CAN + max_delta_down_lower = int(np.interp(speed + 1, self.ANGLE_RATE_BP, self.ANGLE_RATE_DOWN) * self.DEG_TO_CAN - 1 + 1e-3) / self.DEG_TO_CAN + + up_cases = (self.MAX_CURVATURE_ERROR * 2, [ + (not limit_command, 0, 0), + (not limit_command, 0, max_delta_up_lower - small_curvature), + (True, 1e-9, max_delta_down), # TODO: safety should not allow down limits at 0 + (not limit_command, 1e-9, max_delta_up_lower), # TODO: safety should not allow down limits at 0 + (True, 0, max_delta_up_lower), + (True, 0, max_delta_up), + (False, 0, max_delta_up + small_curvature), + # stay at boundary limit + (True, self.MAX_CURVATURE_ERROR - small_curvature, self.MAX_CURVATURE_ERROR - small_curvature), + # 1 unit below boundary limit + (not limit_command, self.MAX_CURVATURE_ERROR - small_curvature * 2, self.MAX_CURVATURE_ERROR - small_curvature * 2), + # shouldn't allow command to move outside the boundary limit if last was inside + (not limit_command, self.MAX_CURVATURE_ERROR - small_curvature, self.MAX_CURVATURE_ERROR - small_curvature * 2), + ]) + + down_cases = (self.MAX_CURVATURE - self.MAX_CURVATURE_ERROR * 2, [ + (not limit_command, self.MAX_CURVATURE, self.MAX_CURVATURE), + (not limit_command, self.MAX_CURVATURE, self.MAX_CURVATURE - max_delta_down_lower + small_curvature), + (True, self.MAX_CURVATURE, self.MAX_CURVATURE - max_delta_down_lower), + (True, self.MAX_CURVATURE, self.MAX_CURVATURE - max_delta_down), + (False, self.MAX_CURVATURE, self.MAX_CURVATURE - max_delta_down - small_curvature), + ]) + + for sign in (-1, 1): + for angle_meas, cases in (up_cases, down_cases): + self._reset_curvature_measurement(sign * angle_meas, speed) + for should_tx, initial_curvature, desired_curvature in cases: + + # Only CAN FD has the max lateral acceleration limit + if self.STEER_MESSAGE == MSG_LateralMotionControl2: + if should_tx: + # can not send if the curvature is above the max lateral acceleration + should_tx = should_tx and abs(desired_curvature) <= curvature_accel_limit_upper + else: + # if desired curvature violates driver curvature error, it can only send if + # the curvature is being limited by max lateral acceleration + should_tx = should_tx or curvature_accel_limit_lower <= abs(desired_curvature) <= curvature_accel_limit_upper + + # small curvature ensures we're using up limits. at 0, safety allows down limits to allow to account for rounding errors + curvature_offset = small_curvature if initial_curvature == 0 else 0 + self._set_prev_desired_angle(sign * (curvature_offset + initial_curvature)) + self.assertEqual(should_tx, self._tx(self._lat_ctl_msg(True, 0, 0, sign * (curvature_offset + desired_curvature), 0))) + + def test_prevent_lkas_action(self): + self.safety.set_controls_allowed(1) + self.assertFalse(self._tx(self._lkas_command_msg(1))) + + self.safety.set_controls_allowed(0) + self.assertFalse(self._tx(self._lkas_command_msg(1))) + + def test_acc_buttons(self): + for allowed in (0, 1): + self.safety.set_controls_allowed(allowed) + for enabled in (True, False): + self._rx(self._pcm_status_msg(enabled)) + self.assertTrue(self._tx(self._acc_button_msg(Buttons.TJA_TOGGLE, 2))) + + for allowed in (0, 1): + self.safety.set_controls_allowed(allowed) + for bus in (0, 2): + self.assertEqual(allowed, self._tx(self._acc_button_msg(Buttons.RESUME, bus))) + + for enabled in (True, False): + self._rx(self._pcm_status_msg(enabled)) + for bus in (0, 2): + self.assertEqual(enabled, self._tx(self._acc_button_msg(Buttons.CANCEL, bus))) + + +class TestFordCANFDStockSafety(TestFordSafetyBase): + STEER_MESSAGE = MSG_LateralMotionControl2 + + TX_MSGS = [ + [MSG_Steering_Data_FD1, 0], [MSG_Steering_Data_FD1, 2], [MSG_ACCDATA_3, 0], [MSG_Lane_Assist_Data1, 0], + [MSG_LateralMotionControl2, 0], [MSG_IPMA_Data, 0], + ] + RELAY_MALFUNCTION_ADDRS = {0: (MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl2, + MSG_IPMA_Data)} + + FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl2, + MSG_IPMA_Data]} + + def setUp(self): + self.packer = CANPackerSafety("ford_lincoln_base_pt") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.CANFD) + self.safety.init_tests() + + +class TestFordLongitudinalSafetyBase(TestFordSafetyBase): + MAX_ACCEL = 2.0 # accel is used for brakes, but openpilot can set positive values + MIN_ACCEL = -3.5 + INACTIVE_ACCEL = 0.0 + + MAX_GAS = 2.0 + MIN_GAS = -0.5 + INACTIVE_GAS = -5.0 + + # ACC command + def _acc_command_msg(self, gas: float, brake: float, brake_actuation: bool, cmbb_deny: bool = False): + values = { + "AccPrpl_A_Rq": gas, # [-5|5.23] m/s^2 + "AccPrpl_A_Pred": gas, # [-5|5.23] m/s^2 + "AccBrkTot_A_Rq": brake, # [-20|11.9449] m/s^2 + "AccBrkPrchg_B_Rq": 1 if brake_actuation else 0, # Pre-charge brake request: 0=No, 1=Yes + "AccBrkDecel_B_Rq": 1 if brake_actuation else 0, # Deceleration request: 0=Inactive, 1=Active + "CmbbDeny_B_Actl": 1 if cmbb_deny else 0, # [0|1] deny AEB actuation + } + return self.packer.make_can_msg_safety("ACCDATA", 0, values) + + def test_stock_aeb(self): + # Test that CmbbDeny_B_Actl is never 1, it prevents the ABS module from actuating AEB requests from ACCDATA_2 + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + for cmbb_deny in (True, False): + should_tx = not cmbb_deny + self.assertEqual(should_tx, self._tx(self._acc_command_msg(self.INACTIVE_GAS, self.INACTIVE_ACCEL, controls_allowed, cmbb_deny))) + should_tx = controls_allowed and not cmbb_deny + self.assertEqual(should_tx, self._tx(self._acc_command_msg(self.MAX_GAS, self.MAX_ACCEL, controls_allowed, cmbb_deny))) + + def test_gas_safety_check(self): + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + for gas in np.concatenate((np.arange(self.MIN_GAS - 2, self.MAX_GAS + 2, 0.05), [self.INACTIVE_GAS])): + gas = round(gas, 2) # floats might not hit exact boundary conditions without rounding + should_tx = (controls_allowed and self.MIN_GAS <= gas <= self.MAX_GAS) or gas == self.INACTIVE_GAS + self.assertEqual(should_tx, self._tx(self._acc_command_msg(gas, self.INACTIVE_ACCEL, controls_allowed))) + + def test_brake_safety_check(self): + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + for brake_actuation in (True, False): + for brake in np.arange(self.MIN_ACCEL - 2, self.MAX_ACCEL + 2, 0.05): + brake = round(brake, 2) # floats might not hit exact boundary conditions without rounding + should_tx = (controls_allowed and self.MIN_ACCEL <= brake <= self.MAX_ACCEL) or brake == self.INACTIVE_ACCEL + should_tx = should_tx and (controls_allowed or not brake_actuation) + self.assertEqual(should_tx, self._tx(self._acc_command_msg(self.INACTIVE_GAS, brake, brake_actuation))) + + +class TestFordLongitudinalSafety(TestFordLongitudinalSafetyBase): + STEER_MESSAGE = MSG_LateralMotionControl + + TX_MSGS = [ + [MSG_Steering_Data_FD1, 0], [MSG_Steering_Data_FD1, 2], [MSG_ACCDATA, 0], [MSG_ACCDATA_3, 0], [MSG_Lane_Assist_Data1, 0], + [MSG_LateralMotionControl, 0], [MSG_IPMA_Data, 0], + ] + RELAY_MALFUNCTION_ADDRS = {0: (MSG_ACCDATA, MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl, + MSG_IPMA_Data)} + + FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA, MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl, + MSG_IPMA_Data]} + + def setUp(self): + self.packer = CANPackerSafety("ford_lincoln_base_pt") + self.safety = libsafety_py.libsafety + # Make sure we enforce long safety even without long flag for CAN + self.safety.set_safety_hooks(CarParams.SafetyModel.ford, 0) + self.safety.init_tests() + + def test_max_lateral_acceleration(self): + # CAN does not limit curvature from lateral acceleration + pass + + +class TestFordCANFDLongitudinalSafety(TestFordLongitudinalSafetyBase): + STEER_MESSAGE = MSG_LateralMotionControl2 + + TX_MSGS = [ + [MSG_Steering_Data_FD1, 0], [MSG_Steering_Data_FD1, 2], [MSG_ACCDATA, 0], [MSG_ACCDATA_3, 0], [MSG_Lane_Assist_Data1, 0], + [MSG_LateralMotionControl2, 0], [MSG_IPMA_Data, 0], + ] + RELAY_MALFUNCTION_ADDRS = {0: (MSG_ACCDATA, MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl2, + MSG_IPMA_Data)} + + FWD_BLACKLISTED_ADDRS = {2: [MSG_ACCDATA, MSG_ACCDATA_3, MSG_Lane_Assist_Data1, MSG_LateralMotionControl2, + MSG_IPMA_Data]} + + def setUp(self): + self.packer = CANPackerSafety("ford_lincoln_base_pt") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.ford, FordSafetyFlags.LONG_CONTROL | FordSafetyFlags.CANFD) + self.safety.init_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_gm.py b/opendbc_repo/opendbc/safety/tests/test_gm.py new file mode 100755 index 0000000000..aae308f7e3 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_gm.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.gm.values import GMSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + + +class Buttons: + UNPRESS = 1 + RES_ACCEL = 2 + DECEL_SET = 3 + CANCEL = 6 + + +class GmLongitudinalBase(common.CarSafetyTest, common.LongitudinalGasBrakeSafetyTest): + + RELAY_MALFUNCTION_ADDRS = {0: (0x180, 0x2CB), 2: (0x184,)} # ASCMLKASteeringCmd, ASCMGasRegenCmd, PSCMStatus + + MAX_POSSIBLE_BRAKE = 2 ** 12 + MAX_BRAKE = 400 + + MAX_POSSIBLE_GAS = 4000 # reasonably excessive limits, not signal max + MIN_POSSIBLE_GAS = -4000 + + PCM_CRUISE = False # openpilot can control the PCM state if longitudinal + + def _send_brake_msg(self, brake): + values = {"FrictionBrakeCmd": -brake} + return self.packer_chassis.make_can_msg_safety("EBCMFrictionBrakeCmd", self.BRAKE_BUS, values) + + def _send_gas_msg(self, gas): + values = {"GasRegenCmd": gas} + return self.packer.make_can_msg_safety("ASCMGasRegenCmd", 0, values) + + # override these tests from CarSafetyTest, GM longitudinal uses button enable + def _pcm_status_msg(self, enable): + raise NotImplementedError + + def test_disable_control_allowed_from_cruise(self): + pass + + def test_enable_control_allowed_from_cruise(self): + pass + + def test_cruise_engaged_prev(self): + pass + + def test_set_resume_buttons(self): + """ + SET and RESUME enter controls allowed on their falling and rising edges, respectively. + """ + for btn_prev in range(8): + for btn_cur in range(8): + with self.subTest(btn_prev=btn_prev, btn_cur=btn_cur): + self._rx(self._button_msg(btn_prev)) + self.safety.set_controls_allowed(0) + for _ in range(10): + self._rx(self._button_msg(btn_cur)) + + should_enable = btn_cur != Buttons.DECEL_SET and btn_prev == Buttons.DECEL_SET + should_enable = should_enable or (btn_cur == Buttons.RES_ACCEL and btn_prev != Buttons.RES_ACCEL) + should_enable = should_enable and btn_cur != Buttons.CANCEL + self.assertEqual(should_enable, self.safety.get_controls_allowed()) + + def test_cancel_button(self): + self.safety.set_controls_allowed(1) + self._rx(self._button_msg(Buttons.CANCEL)) + self.assertFalse(self.safety.get_controls_allowed()) + + +class TestGmSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + STANDSTILL_THRESHOLD = 10 * 0.0311 + # Ensures ASCM is off on ASCM cars, and relay is not malfunctioning for camera-ACC cars + RELAY_MALFUNCTION_ADDRS = {0: (0x180,), 2: (0x184,)} # ASCMLKASteeringCmd, PSCMStatus + BUTTONS_BUS = 0 # rx or tx + BRAKE_BUS = 0 # tx only + + MAX_RATE_UP = 10 + MAX_RATE_DOWN = 15 + MAX_TORQUE_LOOKUP = [0], [300] + MAX_RT_DELTA = 128 + DRIVER_TORQUE_ALLOWANCE = 65 + DRIVER_TORQUE_FACTOR = 4 + + PCM_CRUISE = True # openpilot is tied to the PCM state if not longitudinal + + EXTRA_SAFETY_PARAM = 0 + + def setUp(self): + self.packer = CANPackerSafety("gm_global_a_powertrain_generated") + self.packer_chassis = CANPackerSafety("gm_global_a_chassis") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.gm, 0) + self.safety.init_tests() + + def _pcm_status_msg(self, enable): + if self.PCM_CRUISE: + values = {"CruiseState": enable} + return self.packer.make_can_msg_safety("AcceleratorPedal2", 0, values) + else: + raise NotImplementedError + + def _speed_msg(self, speed): + values = {"%sWheelSpd" % s: speed for s in ["RL", "RR"]} + return self.packer.make_can_msg_safety("EBCMWheelSpdRear", 0, values) + + def _user_brake_msg(self, brake): + # GM safety has a brake threshold of 8 + values = {"BrakePedalPos": 8 if brake else 0} + return self.packer.make_can_msg_safety("ECMAcceleratorPos", 0, values) + + def _user_gas_msg(self, gas): + values = {"AcceleratorPedal2": 1 if gas else 0} + if self.PCM_CRUISE: + # Fill CruiseState with expected value if the safety mode reads cruise state from gas msg + values["CruiseState"] = self.safety.get_controls_allowed() + return self.packer.make_can_msg_safety("AcceleratorPedal2", 0, values) + + def _torque_driver_msg(self, torque): + # Safety tests assume driver torque is an int, use DBC factor + values = {"LKADriverAppldTrq": torque * 0.01} + return self.packer.make_can_msg_safety("PSCMStatus", 0, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"LKASteeringCmd": torque, "LKASteeringCmdActive": steer_req} + return self.packer.make_can_msg_safety("ASCMLKASteeringCmd", 0, values) + + def _button_msg(self, buttons): + values = {"ACCButtons": buttons} + return self.packer.make_can_msg_safety("ASCMSteeringButton", self.BUTTONS_BUS, values) + + +class TestGmEVSafetyBase(TestGmSafetyBase): + EXTRA_SAFETY_PARAM = GMSafetyFlags.EV + + # existence of _user_regen_msg adds regen tests + def _user_regen_msg(self, regen): + values = {"RegenPaddle": 2 if regen else 0} + return self.packer.make_can_msg_safety("EBCMRegenPaddle", 0, values) + + +class TestGmAscmSafety(GmLongitudinalBase, TestGmSafetyBase): + TX_MSGS = [[0x180, 0], [0x409, 0], [0x40A, 0], [0x2CB, 0], [0x370, 0], # pt bus + [0xA1, 1], [0x306, 1], [0x308, 1], [0x310, 1], # obs bus + [0x315, 2]] # ch bus + FWD_BLACKLISTED_ADDRS: dict[int, list[int]] = {} + RELAY_MALFUNCTION_ADDRS = {0: (0x180, 0x2CB)} # ASCMLKASteeringCmd, ASCMGasRegenCmd + FWD_BUS_LOOKUP: dict[int, int] = {} + BRAKE_BUS = 2 + + MAX_GAS = 1018 + MIN_GAS = -650 # maximum regen + INACTIVE_GAS = -650 + + def setUp(self): + self.packer = CANPackerSafety("gm_global_a_powertrain_generated") + self.packer_chassis = CANPackerSafety("gm_global_a_chassis") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.gm, self.EXTRA_SAFETY_PARAM) + self.safety.init_tests() + + +class TestGmAscmEVSafety(TestGmAscmSafety, TestGmEVSafetyBase): + pass + + +class TestGmCameraSafetyBase(TestGmSafetyBase): + def _user_brake_msg(self, brake): + values = {"BrakePressed": brake} + return self.packer.make_can_msg_safety("ECMEngineStatus", 0, values) + + +class TestGmCameraSafety(TestGmCameraSafetyBase): + TX_MSGS = [[0x180, 0], # pt bus + [0x184, 2]] # camera bus + FWD_BLACKLISTED_ADDRS = {2: [0x180], 0: [0x184]} # block LKAS message and PSCMStatus + BUTTONS_BUS = 2 # tx only + + def setUp(self): + self.packer = CANPackerSafety("gm_global_a_powertrain_generated") + self.packer_chassis = CANPackerSafety("gm_global_a_chassis") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | self.EXTRA_SAFETY_PARAM) + self.safety.init_tests() + + def test_buttons(self): + # Only CANCEL button is allowed while cruise is enabled + self.safety.set_controls_allowed(0) + for btn in range(8): + self.assertFalse(self._tx(self._button_msg(btn))) + + self.safety.set_controls_allowed(1) + for btn in range(8): + self.assertFalse(self._tx(self._button_msg(btn))) + + for enabled in (True, False): + self._rx(self._pcm_status_msg(enabled)) + self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL))) + + +class TestGmCameraEVSafety(TestGmCameraSafety, TestGmEVSafetyBase): + pass + + +class TestGmCameraLongitudinalSafety(GmLongitudinalBase, TestGmCameraSafetyBase): + TX_MSGS = [[0x180, 0], [0x315, 0], [0x2CB, 0], [0x370, 0], # pt bus + [0x184, 2]] # camera bus + FWD_BLACKLISTED_ADDRS = {2: [0x180, 0x2CB, 0x370, 0x315], 0: [0x184]} # block LKAS, ACC messages and PSCMStatus + RELAY_MALFUNCTION_ADDRS = {0: (0x180, 0x2CB, 0x370, 0x315), 2: (0x184,)} + BUTTONS_BUS = 0 # rx only + + MAX_GAS = 1346 + MIN_GAS = -540 # maximum regen + INACTIVE_GAS = -500 + + def setUp(self): + self.packer = CANPackerSafety("gm_global_a_powertrain_generated") + self.packer_chassis = CANPackerSafety("gm_global_a_chassis") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | GMSafetyFlags.HW_CAM_LONG | self.EXTRA_SAFETY_PARAM) + self.safety.init_tests() + + +class TestGmCameraLongitudinalEVSafety(TestGmCameraLongitudinalSafety, TestGmEVSafetyBase): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_honda.py b/opendbc_repo/opendbc/safety/tests/test_honda.py new file mode 100755 index 0000000000..44220095aa --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_honda.py @@ -0,0 +1,602 @@ +#!/usr/bin/env python3 +import unittest +import numpy as np + +from opendbc.car.honda.values import HondaSafetyFlags +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.car.structs import CarParams +from opendbc.safety.tests.common import CANPackerSafety, MAX_WRONG_COUNTERS + +HONDA_N_COMMON_TX_MSGS = [[0xE4, 0], [0x194, 0], [0x1FA, 0], [0x30C, 0], [0x33D, 0]] + + +class Btn: + NONE = 0 + MAIN = 1 + CANCEL = 2 + SET = 3 + RESUME = 4 + +# Honda safety has several different configurations tested here: +# * Nidec +# * normal (PCM-enable) +# * alt SCM messages (PCM-enable) +# * Bosch +# * Bosch with Longitudinal Support +# * Bosch Radarless +# * Bosch Radarless with Longitudinal Support + + +class HondaButtonEnableBase(common.CarSafetyTest): + + # override these inherited tests since we're using button enable + def test_disable_control_allowed_from_cruise(self): + pass + + def test_enable_control_allowed_from_cruise(self): + pass + + def test_cruise_engaged_prev(self): + pass + + def test_buttons_with_main_off(self): + for btn in (Btn.SET, Btn.RESUME, Btn.CANCEL): + self.safety.set_controls_allowed(1) + self._rx(self._acc_state_msg(False)) + self._rx(self._button_msg(btn, main_on=False)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_set_resume_buttons(self): + """ + Both SET and RES should enter controls allowed on their falling edge. + """ + for main_on in (True, False): + self._rx(self._acc_state_msg(main_on)) + for btn_prev in range(8): + for btn_cur in range(8): + self._rx(self._button_msg(Btn.NONE)) + self.safety.set_controls_allowed(0) + for _ in range(10): + self._rx(self._button_msg(btn_prev)) + self.assertFalse(self.safety.get_controls_allowed()) + + # should enter controls allowed on falling edge and not transitioning to cancel or main + should_enable = (main_on and + btn_cur != btn_prev and + btn_prev in (Btn.RESUME, Btn.SET) and + btn_cur not in (Btn.CANCEL, Btn.MAIN)) + + self._rx(self._button_msg(btn_cur, main_on=main_on)) + self.assertEqual(should_enable, self.safety.get_controls_allowed(), msg=f"{main_on=} {btn_prev=} {btn_cur=}") + + def test_main_cancel_buttons(self): + """ + Both MAIN and CANCEL should exit controls immediately. + """ + for btn in (Btn.MAIN, Btn.CANCEL): + self.safety.set_controls_allowed(1) + self._rx(self._button_msg(btn, main_on=True)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_disengage_on_main(self): + self.safety.set_controls_allowed(1) + self._rx(self._acc_state_msg(True)) + self.assertTrue(self.safety.get_controls_allowed()) + self._rx(self._acc_state_msg(False)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_rx_hook(self): + + # TODO: move this test to common + # checksum checks + for msg_type in ["btn", "gas", "speed"]: + self.safety.set_controls_allowed(1) + if msg_type == "btn": + msg = self._button_msg(Btn.SET) + if msg_type == "gas": + msg = self._user_gas_msg(0) + if msg_type == "speed": + msg = self._speed_msg(0) + self.assertTrue(self._rx(msg)) + if msg_type != "btn": + msg[0].data[4] = 0 # invalidate checksum + msg[0].data[5] = 0 + msg[0].data[6] = 0 + msg[0].data[7] = 0 + self.assertFalse(self._rx(msg)) + self.assertFalse(self.safety.get_controls_allowed()) + + # counter + # reset wrong_counters to zero by sending valid messages + for i in range(MAX_WRONG_COUNTERS + 1): + self.__class__.cnt_speed += 1 + self.__class__.cnt_button += 1 + self.__class__.cnt_powertrain_data += 1 + if i < MAX_WRONG_COUNTERS: + self.safety.set_controls_allowed(1) + self._rx(self._button_msg(Btn.SET)) + self._rx(self._speed_msg(0)) + self._rx(self._user_gas_msg(0)) + else: + self.assertFalse(self._rx(self._button_msg(Btn.SET))) + self.assertFalse(self._rx(self._speed_msg(0))) + self.assertFalse(self._rx(self._user_gas_msg(0))) + self.assertFalse(self.safety.get_controls_allowed()) + + # restore counters for future tests with a couple of good messages + for _ in range(2): + self.safety.set_controls_allowed(1) + self._rx(self._button_msg(Btn.SET, main_on=True)) + self._rx(self._speed_msg(0)) + self._rx(self._user_gas_msg(0)) + self._rx(self._button_msg(Btn.SET, main_on=True)) + self.assertTrue(self.safety.get_controls_allowed()) + + +class HondaPcmEnableBase(common.CarSafetyTest): + + def test_buttons(self): + """ + Buttons should only cancel in this configuration, + since our state is tied to the PCM's cruise state. + """ + for controls_allowed in (True, False): + for main_on in (True, False): + # not a valid state + if controls_allowed and not main_on: + continue + + for btn in (Btn.SET, Btn.RESUME, Btn.CANCEL): + self.safety.set_controls_allowed(controls_allowed) + self._rx(self._acc_state_msg(main_on)) + + # btn + none for falling edge + self._rx(self._button_msg(btn, main_on=main_on)) + self._rx(self._button_msg(Btn.NONE, main_on=main_on)) + + if btn == Btn.CANCEL: + self.assertFalse(self.safety.get_controls_allowed()) + else: + self.assertEqual(controls_allowed, self.safety.get_controls_allowed()) + + +class HondaBase(common.CarSafetyTest): + MAX_BRAKE = 255 + PT_BUS: int | None = None # must be set when inherited + STEER_BUS: int | None = None # must be set when inherited + BUTTONS_BUS: int | None = None # must be set when inherited, tx on this bus, rx on PT_BUS + + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x194)} # STEERING_CONTROL + + cnt_speed = 0 + cnt_button = 0 + cnt_brake = 0 + cnt_powertrain_data = 0 + cnt_acc_state = 0 + + def _powertrain_data_msg(self, cruise_on=None, brake_pressed=None, gas_pressed=None): + # preserve the state + if cruise_on is None: + # or'd with controls allowed since the tests use it to "enable" cruise + cruise_on = self.safety.get_cruise_engaged_prev() or self.safety.get_controls_allowed() + if brake_pressed is None: + brake_pressed = self.safety.get_brake_pressed_prev() + if gas_pressed is None: + gas_pressed = self.safety.get_gas_pressed_prev() + + values = { + "ACC_STATUS": cruise_on, + "BRAKE_PRESSED": brake_pressed, + "PEDAL_GAS": gas_pressed, + "COUNTER": self.cnt_powertrain_data % 4 + } + self.__class__.cnt_powertrain_data += 1 + return self.packer.make_can_msg_safety("POWERTRAIN_DATA", self.PT_BUS, values) + + def _pcm_status_msg(self, enable): + return self._powertrain_data_msg(cruise_on=enable) + + def _speed_msg(self, speed): + values = {"XMISSION_SPEED": speed, "COUNTER": self.cnt_speed % 4} + self.__class__.cnt_speed += 1 + return self.packer.make_can_msg_safety("ENGINE_DATA", self.PT_BUS, values) + + def _acc_state_msg(self, main_on): + values = {"MAIN_ON": main_on, "COUNTER": self.cnt_acc_state % 4} + self.__class__.cnt_acc_state += 1 + return self.packer.make_can_msg_safety("SCM_FEEDBACK", self.PT_BUS, values) + + def _button_msg(self, buttons, main_on=False, bus=None): + bus = self.PT_BUS if bus is None else bus + values = {"CRUISE_BUTTONS": buttons, "COUNTER": self.cnt_button % 4} + self.__class__.cnt_button += 1 + return self.packer.make_can_msg_safety("SCM_BUTTONS", bus, values) + + def _user_brake_msg(self, brake): + return self._powertrain_data_msg(brake_pressed=brake) + + def _user_gas_msg(self, gas): + return self._powertrain_data_msg(gas_pressed=gas) + + def _send_steer_msg(self, steer): + values = {"STEER_TORQUE": steer} + return self.packer.make_can_msg_safety("STEERING_CONTROL", self.STEER_BUS, values) + + def _send_brake_msg(self, brake): + # must be implemented when inherited + raise NotImplementedError + + def test_disengage_on_brake(self): + self.safety.set_controls_allowed(1) + self._rx(self._user_brake_msg(1)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_steer_safety_check(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(self._send_steer_msg(0x0000))) + self.assertFalse(self._tx(self._send_steer_msg(0x1000))) + + +# ********************* Honda Nidec ********************** + + +class TestHondaNidecSafetyBase(HondaBase): + TX_MSGS = HONDA_N_COMMON_TX_MSGS + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D, 0x30C]} + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x194, 0x33D, 0x30C)} + + PT_BUS = 0 + STEER_BUS = 0 + BUTTONS_BUS = 0 + + MAX_GAS = 198 + + def setUp(self): + self.packer = CANPackerSafety("honda_civic_touring_2016_can_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, 0) + self.safety.init_tests() + + def _send_brake_msg(self, brake, aeb_req=0, bus=0): + values = {"COMPUTER_BRAKE": brake, "AEB_REQ_1": aeb_req} + return self.packer.make_can_msg_safety("BRAKE_COMMAND", bus, values) + + def _rx_brake_msg(self, brake, aeb_req=0): + return self._send_brake_msg(brake, aeb_req, bus=2) + + def _send_acc_hud_msg(self, pcm_gas, pcm_speed): + # Used to control ACC on Nidec without pedal + values = {"PCM_GAS": pcm_gas, "PCM_SPEED": pcm_speed} + return self.packer.make_can_msg_safety("ACC_HUD", 0, values) + + def test_acc_hud_safety_check(self): + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + for pcm_gas in range(255): + for pcm_speed in range(100): + send = (controls_allowed and pcm_gas <= self.MAX_GAS) or (pcm_gas == 0 and pcm_speed == 0) + self.assertEqual(send, self._tx(self._send_acc_hud_msg(pcm_gas, pcm_speed))) + + def test_fwd_hook(self): + # normal operation, not forwarding AEB + self.FWD_BLACKLISTED_ADDRS[2].append(0x1FA) + self.safety.set_honda_fwd_brake(False) + super().test_fwd_hook() + + # forwarding AEB brake signal + self.FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x194, 0x33D, 0x30C]} + self.safety.set_honda_fwd_brake(True) + super().test_fwd_hook() + + def test_honda_fwd_brake_latching(self): + # Shouldn't fwd stock Honda requesting brake without AEB + self.assertTrue(self._rx(self._rx_brake_msg(self.MAX_BRAKE, aeb_req=0))) + self.assertFalse(self.safety.get_honda_fwd_brake()) + + # Now allow controls and request some brake + openpilot_brake = round(self.MAX_BRAKE / 2.0) + self.safety.set_controls_allowed(True) + self.assertTrue(self._tx(self._send_brake_msg(openpilot_brake))) + + # Still shouldn't fwd stock Honda brake until it's more than openpilot's + for stock_honda_brake in range(self.MAX_BRAKE + 1): + self.assertTrue(self._rx(self._rx_brake_msg(stock_honda_brake, aeb_req=1))) + should_fwd_brake = stock_honda_brake >= openpilot_brake + self.assertEqual(should_fwd_brake, self.safety.get_honda_fwd_brake()) + + # Shouldn't stop fwding until AEB event is over + for stock_honda_brake in range(self.MAX_BRAKE + 1)[::-1]: + self.assertTrue(self._rx(self._rx_brake_msg(stock_honda_brake, aeb_req=1))) + self.assertTrue(self.safety.get_honda_fwd_brake()) + + self.assertTrue(self._rx(self._rx_brake_msg(0, aeb_req=0))) + self.assertFalse(self.safety.get_honda_fwd_brake()) + + def test_brake_safety_check(self): + for fwd_brake in [False, True]: + self.safety.set_honda_fwd_brake(fwd_brake) + for brake in np.arange(0, self.MAX_BRAKE + 10, 1): + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + if fwd_brake: + send = False # block openpilot brake msg when fwd'ing stock msg + elif controls_allowed: + send = self.MAX_BRAKE >= brake >= 0 + else: + send = brake == 0 + self.assertEqual(send, self._tx(self._send_brake_msg(brake))) + + +class TestHondaNidecPcmSafety(HondaPcmEnableBase, TestHondaNidecSafetyBase): + """ + Covers the Honda Nidec safety mode + """ + + # Nidec doesn't disengage on falling edge of cruise. See comment in safety_honda.h + def test_disable_control_allowed_from_cruise(self): + pass + + +class TestHondaNidecPcmAltSafety(TestHondaNidecPcmSafety): + """ + Covers the Honda Nidec safety mode with alt SCM messages + """ + def setUp(self): + self.packer = CANPackerSafety("acura_ilx_2016_can_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaNidec, HondaSafetyFlags.NIDEC_ALT) + self.safety.init_tests() + + def _acc_state_msg(self, main_on): + values = {"MAIN_ON": main_on, "COUNTER": self.cnt_acc_state % 4} + self.__class__.cnt_acc_state += 1 + return self.packer.make_can_msg_safety("SCM_BUTTONS", self.PT_BUS, values) + + def _button_msg(self, buttons, main_on=False, bus=None): + bus = self.PT_BUS if bus is None else bus + values = {"CRUISE_BUTTONS": buttons, "MAIN_ON": main_on, "COUNTER": self.cnt_button % 4} + self.__class__.cnt_button += 1 + return self.packer.make_can_msg_safety("SCM_BUTTONS", bus, values) + + +# ********************* Honda Bosch ********************** + + +class TestHondaBoschSafetyBase(HondaBase): + PT_BUS = 1 + STEER_BUS = 0 + BUTTONS_BUS = 1 + + TX_MSGS = [[0xE4, 0], [0xE5, 0], [0x296, 1], [0x33D, 0], [0x33DA, 0], [0x33DB, 0]] + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0xE5, 0x33D, 0x33DA, 0x33DB]} + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0xE5, 0x33D, 0x33DA, 0x33DB)} # STEERING_CONTROL, BOSCH_SUPPLEMENTAL_1 + + def setUp(self): + self.packer = CANPackerSafety("honda_civic_hatchback_ex_2017_can_generated") + self.safety = libsafety_py.libsafety + + def _alt_brake_msg(self, brake): + values = {"BRAKE_PRESSED": brake, "COUNTER": self.cnt_brake % 4} + self.__class__.cnt_brake += 1 + return self.packer.make_can_msg_safety("BRAKE_MODULE", self.PT_BUS, values) + + def _send_brake_msg(self, brake): + pass + + def test_spam_cancel_safety_check(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(self._button_msg(Btn.CANCEL, bus=self.BUTTONS_BUS))) + self.assertFalse(self._tx(self._button_msg(Btn.RESUME, bus=self.BUTTONS_BUS))) + self.assertFalse(self._tx(self._button_msg(Btn.SET, bus=self.BUTTONS_BUS))) + # do not block resume if we are engaged already + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(self._button_msg(Btn.RESUME, bus=self.BUTTONS_BUS))) + + +class TestHondaBoschAltBrakeSafetyBase(TestHondaBoschSafetyBase): + """ + Base Bosch safety test class with an alternate brake message + """ + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.ALT_BRAKE) + self.safety.init_tests() + + def _user_brake_msg(self, brake): + return self._alt_brake_msg(brake) + + def test_alt_brake_rx_hook(self): + self.safety.set_honda_alt_brake_msg(1) + self.safety.set_controls_allowed(1) + msg = self._alt_brake_msg(0) + self.assertTrue(self._rx(msg)) + msg[0].data[2] = msg[0].data[2] & 0xF0 # invalidate checksum + self.assertFalse(self._rx(msg)) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_alt_disengage_on_brake(self): + self.safety.set_honda_alt_brake_msg(1) + self.safety.set_controls_allowed(1) + self._rx(self._alt_brake_msg(1)) + self.assertFalse(self.safety.get_controls_allowed()) + + self.safety.set_honda_alt_brake_msg(0) + self.safety.set_controls_allowed(1) + self._rx(self._alt_brake_msg(1)) + self.assertTrue(self.safety.get_controls_allowed()) + + +class TestHondaBoschSafety(HondaPcmEnableBase, TestHondaBoschSafetyBase): + """ + Covers the Honda Bosch safety mode with stock longitudinal + """ + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, 0) + self.safety.init_tests() + + +class TestHondaBoschAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschAltBrakeSafetyBase): + """ + Covers the Honda Bosch safety mode with stock longitudinal and an alternate brake message + """ + + +class TestHondaBoschLongSafety(HondaButtonEnableBase, TestHondaBoschSafetyBase): + """ + Covers the Honda Bosch safety mode with longitudinal control + """ + NO_GAS = -30000 + MAX_GAS = 2000 + MAX_ACCEL = 2.0 # accel is used for brakes, but openpilot can set positive values + MIN_ACCEL = -3.5 + + STEER_BUS = 1 + TX_MSGS = [[0xE4, 1], [0x1DF, 1], [0x1EF, 1], [0x1FA, 1], [0x30C, 1], [0x33D, 1], [0x33DA, 1], [0x33DB, 1], [0x39F, 1], [0x18DAB0F1, 1]] + FWD_BLACKLISTED_ADDRS = {} + # 0x1DF is to test that radar is disabled + RELAY_MALFUNCTION_ADDRS = {1: (0xE4, 0x1DF, 0x33D, 0x33DA, 0x33DB)} # STEERING_CONTROL, ACC_CONTROL + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_LONG) + self.safety.init_tests() + + def _send_gas_brake_msg(self, gas, accel): + values = { + "GAS_COMMAND": gas, + "ACCEL_COMMAND": accel, + "BRAKE_REQUEST": accel < 0, + } + return self.packer.make_can_msg_safety("ACC_CONTROL", self.PT_BUS, values) + + # Longitudinal doesn't need to send buttons + def test_spam_cancel_safety_check(self): + pass + + def test_diagnostics(self): + tester_present = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x02\x3E\x80\x00\x00\x00\x00\x00") + self.assertTrue(self._tx(tester_present)) + + not_tester_present = libsafety_py.make_CANPacket(0x18DAB0F1, self.PT_BUS, b"\x03\xAA\xAA\x00\x00\x00\x00\x00") + self.assertFalse(self._tx(not_tester_present)) + + def test_gas_safety_check(self): + for controls_allowed in [True, False]: + for gas in np.arange(self.NO_GAS, self.MAX_GAS + 2000, 100): + accel = 0 if gas < 0 else gas / 1000 + self.safety.set_controls_allowed(controls_allowed) + send = (controls_allowed and 0 <= gas <= self.MAX_GAS) or gas == self.NO_GAS + self.assertEqual(send, self._tx(self._send_gas_brake_msg(gas, accel)), (controls_allowed, gas, accel)) + + def test_brake_safety_check(self): + for controls_allowed in [True, False]: + for accel in np.arange(self.MIN_ACCEL - 1, self.MAX_ACCEL + 1, 0.01): + accel = round(accel, 2) # floats might not hit exact boundary conditions without rounding + self.safety.set_controls_allowed(controls_allowed) + send = self.MIN_ACCEL <= accel <= self.MAX_ACCEL if controls_allowed else accel == 0 + self.assertEqual(send, self._tx(self._send_gas_brake_msg(self.NO_GAS, accel)), (controls_allowed, accel)) + + +class TestHondaBoschRadarlessSafetyBase(TestHondaBoschSafetyBase): + """Base class for radarless Honda Bosch""" + PT_BUS = 0 + STEER_BUS = 0 + BUTTONS_BUS = 2 # camera controls ACC, need to send buttons on bus 2 + + TX_MSGS = [[0xE4, 0], [0x296, 2], [0x33D, 0]] + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]} + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} # STEERING_CONTROL + + def setUp(self): + self.packer = CANPackerSafety("honda_bosch_radarless_generated") + self.safety = libsafety_py.libsafety + + +class TestHondaBoschRadarlessSafety(HondaPcmEnableBase, TestHondaBoschRadarlessSafetyBase): + """ + Covers the Honda Bosch Radarless safety mode with stock longitudinal + """ + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.RADARLESS) + self.safety.init_tests() + + +class TestHondaBoschRadarlessAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschRadarlessSafetyBase, TestHondaBoschAltBrakeSafetyBase): + """ + Covers the Honda Bosch Radarless safety mode with stock longitudinal and an alternate brake message + """ + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.RADARLESS | HondaSafetyFlags.ALT_BRAKE) + self.safety.init_tests() + + +class TestHondaBoschRadarlessLongSafety(common.LongitudinalAccelSafetyTest, HondaButtonEnableBase, + TestHondaBoschRadarlessSafetyBase): + """ + Covers the Honda Bosch Radarless safety mode with longitudinal control + """ + TX_MSGS = [[0xE4, 0], [0x33D, 0], [0x1C8, 0], [0x30C, 0]] + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D, 0x1C8, 0x30C]} + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x1C8, 0x30C, 0x33D)} + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.RADARLESS | HondaSafetyFlags.BOSCH_LONG) + self.safety.init_tests() + + def _accel_msg(self, accel): + values = { + "ACCEL_COMMAND": accel, + } + return self.packer.make_can_msg_safety("ACC_CONTROL", self.PT_BUS, values) + + # Longitudinal doesn't need to send buttons + def test_spam_cancel_safety_check(self): + pass + + +class TestHondaBoschCANFDSafetyBase(TestHondaBoschSafetyBase): + """Base class for CANFD Honda Bosch""" + PT_BUS = 0 + STEER_BUS = 0 + BUTTONS_BUS = 0 + + TX_MSGS = [[0xE4, 0], [0x296, 0], [0x33D, 0]] + FWD_BLACKLISTED_ADDRS = {2: [0xE4, 0x33D]} + RELAY_MALFUNCTION_ADDRS = {0: (0xE4, 0x33D)} + + def setUp(self): + self.packer = CANPackerSafety("honda_common_canfd_generated") + self.safety = libsafety_py.libsafety + + +class TestHondaBoschCANFDSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase): + """ + Covers the Honda Bosch CANFD safety mode with stock longitudinal + """ + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD) + self.safety.init_tests() + + +class TestHondaBoschCANFDAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschCANFDSafetyBase, TestHondaBoschAltBrakeSafetyBase): + """ + Covers the Honda Bosch CANFD safety mode with stock longitudinal and an alternate brake message + """ + + def setUp(self): + super().setUp() + self.safety.set_safety_hooks(CarParams.SafetyModel.hondaBosch, HondaSafetyFlags.BOSCH_CANFD | HondaSafetyFlags.ALT_BRAKE) + self.safety.init_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai.py b/opendbc_repo/opendbc/safety/tests/test_hyundai.py new file mode 100755 index 0000000000..fa08faede1 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai.py @@ -0,0 +1,283 @@ +#!/usr/bin/env python3 +import random +import unittest + +from opendbc.car.hyundai.values import HyundaiSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety +from opendbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase + + +# 4 bit checkusm used in some hyundai messages +# lives outside the can packer because we never send this msg +def checksum(msg): + addr, dat, bus = msg + + chksum = 0 + if addr == 0x386: + for i, b in enumerate(dat): + for j in range(8): + # exclude checksum and counter bits + if (i != 1 or j < 6) and (i != 3 or j < 6) and (i != 5 or j < 6) and (i != 7 or j < 6): + bit = (b >> j) & 1 + else: + bit = 0 + chksum += bit + chksum = (chksum ^ 9) & 0xF + ret = bytearray(dat) + ret[5] |= (chksum & 0x3) << 6 + ret[7] |= (chksum & 0xc) << 4 + else: + for i, b in enumerate(dat): + if addr in [0x260, 0x421] and i == 7: + b &= 0x0F if addr == 0x421 else 0xF0 + elif addr == 0x394 and i == 6: + b &= 0xF0 + elif addr == 0x394 and i == 7: + continue + chksum += sum(divmod(b, 16)) + chksum = (16 - chksum) % 16 + ret = bytearray(dat) + ret[6 if addr == 0x394 else 7] |= chksum << (4 if addr == 0x421 else 0) + + return addr, ret, bus + + +class TestHyundaiSafety(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): + TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0]] + STANDSTILL_THRESHOLD = 12 # 0.375 kph + RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485)} # LKAS11 + FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485]} + + MAX_RATE_UP = 3 + MAX_RATE_DOWN = 7 + MAX_TORQUE_LOOKUP = [0], [384] + MAX_RT_DELTA = 112 + DRIVER_TORQUE_ALLOWANCE = 50 + DRIVER_TORQUE_FACTOR = 2 + + # Safety around steering req bit + MIN_VALID_STEERING_FRAMES = 89 + MAX_INVALID_STEERING_FRAMES = 2 + + cnt_gas = 0 + cnt_speed = 0 + cnt_brake = 0 + cnt_cruise = 0 + cnt_button = 0 + + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, 0) + self.safety.init_tests() + + def _button_msg(self, buttons, main_button=0, bus=0): + values = {"CF_Clu_CruiseSwState": buttons, "CF_Clu_CruiseSwMain": main_button, "CF_Clu_AliveCnt1": self.cnt_button} + self.__class__.cnt_button += 1 + return self.packer.make_can_msg_safety("CLU11", bus, values) + + def _user_gas_msg(self, gas): + values = {"CF_Ems_AclAct": gas, "AliveCounter": self.cnt_gas % 4} + self.__class__.cnt_gas += 1 + return self.packer.make_can_msg_safety("EMS16", 0, values, fix_checksum=checksum) + + def _user_brake_msg(self, brake): + values = {"DriverOverride": 2 if brake else random.choice((0, 1, 3)), + "AliveCounterTCS": self.cnt_brake % 8} + self.__class__.cnt_brake += 1 + return self.packer.make_can_msg_safety("TCS13", 0, values, fix_checksum=checksum) + + def _speed_msg(self, speed): + # safety doesn't scale, so undo the scaling + values = {"WHL_SPD_%s" % s: speed * 0.03125 for s in ["FL", "FR", "RL", "RR"]} + values["WHL_SPD_AliveCounter_LSB"] = (self.cnt_speed % 16) & 0x3 + values["WHL_SPD_AliveCounter_MSB"] = (self.cnt_speed % 16) >> 2 + self.__class__.cnt_speed += 1 + return self.packer.make_can_msg_safety("WHL_SPD11", 0, values, fix_checksum=checksum) + + def _pcm_status_msg(self, enable): + values = {"ACCMode": enable, "CR_VSM_Alive": self.cnt_cruise % 16} + self.__class__.cnt_cruise += 1 + return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values, fix_checksum=checksum) + + def _torque_driver_msg(self, torque): + values = {"CR_Mdps_StrColTq": torque} + return self.packer.make_can_msg_safety("MDPS12", 0, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"CR_Lkas_StrToqReq": torque, "CF_Lkas_ActToi": steer_req} + return self.packer.make_can_msg_safety("LKAS11", 0, values) + + +class TestHyundaiSafetyAltLimits(TestHyundaiSafety): + MAX_RATE_UP = 2 + MAX_RATE_DOWN = 3 + MAX_TORQUE_LOOKUP = [0], [270] + + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS) + self.safety.init_tests() + + +class TestHyundaiSafetyAltLimits2(TestHyundaiSafety): + MAX_RATE_UP = 2 + MAX_RATE_DOWN = 3 + MAX_TORQUE_LOOKUP = [0], [170] + + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.ALT_LIMITS_2) + self.safety.init_tests() + + +class TestHyundaiSafetyCameraSCC(TestHyundaiSafety): + BUTTONS_TX_BUS = 2 # tx on 2, rx on 0 + SCC_BUS = 2 # rx on 2 + + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.CAMERA_SCC) + self.safety.init_tests() + + +class TestHyundaiSafetyFCEV(TestHyundaiSafety): + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.FCEV_GAS) + self.safety.init_tests() + + def _user_gas_msg(self, gas): + values = {"ACCELERATOR_PEDAL": gas} + return self.packer.make_can_msg_safety("FCEV_ACCELERATOR", 0, values) + + +class TestHyundaiLegacySafety(TestHyundaiSafety): + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, 0) + self.safety.init_tests() + + +class TestHyundaiLegacySafetyEV(TestHyundaiSafety): + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.EV_GAS) + self.safety.init_tests() + + def _user_gas_msg(self, gas): + values = {"Accel_Pedal_Pos": gas} + return self.packer.make_can_msg_safety("E_EMS11", 0, values, fix_checksum=checksum) + + +class TestHyundaiLegacySafetyHEV(TestHyundaiSafety): + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiLegacy, HyundaiSafetyFlags.HYBRID_GAS) + self.safety.init_tests() + + def _user_gas_msg(self, gas): + values = {"CR_Vcu_AccPedDep_Pos": gas} + return self.packer.make_can_msg_safety("E_EMS11", 0, values, fix_checksum=checksum) + + +class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety): + TX_MSGS = [[0x340, 0], [0x4F1, 0], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0], [0x38D, 0], [0x483, 0], [0x7D0, 0]] + + FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x421, 0x420, 0x50A, 0x389]} + + RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485, 0x421, 0x420, 0x50A, 0x389)} # LKAS11, LFAHDA_MFC, SCC12, SCC11, SCC13, SCC14 + + DISABLED_ECU_UDS_MSG = (0x7D0, 0) + DISABLED_ECU_ACTUATION_MSG = (0x421, 0) + + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG) + self.safety.init_tests() + + def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): + values = { + "aReqRaw": accel, + "aReqValue": accel, + "AEB_CmdAct": int(aeb_req), + "CR_VSM_DecCmd": aeb_decel, + } + return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values) + + def _fca11_msg(self, idx=0, vsm_aeb_req=False, fca_aeb_req=False, aeb_decel=0): + values = { + "CR_FCA_Alive": idx % 0xF, + "FCA_Status": 2, + "CR_VSM_DecCmd": aeb_decel, + "CF_VSM_DecCmdAct": int(vsm_aeb_req), + "FCA_CmdAct": int(fca_aeb_req), + } + return self.packer.make_can_msg_safety("FCA11", 0, values) + + def test_no_aeb_fca11(self): + self.assertTrue(self._tx(self._fca11_msg())) + self.assertFalse(self._tx(self._fca11_msg(vsm_aeb_req=True))) + self.assertFalse(self._tx(self._fca11_msg(fca_aeb_req=True))) + self.assertFalse(self._tx(self._fca11_msg(aeb_decel=1.0))) + + def test_no_aeb_scc12(self): + self.assertTrue(self._tx(self._accel_msg(0))) + self.assertFalse(self._tx(self._accel_msg(0, aeb_req=True))) + self.assertFalse(self._tx(self._accel_msg(0, aeb_decel=1.0))) + + +class TestHyundaiLongitudinalSafetyCameraSCC(HyundaiLongitudinalBase, TestHyundaiSafety): + TX_MSGS = [[0x340, 0], [0x4F1, 2], [0x485, 0], [0x420, 0], [0x421, 0], [0x50A, 0], [0x389, 0], [0x4A2, 0]] + + FWD_BLACKLISTED_ADDRS = {2: [0x340, 0x485, 0x420, 0x421, 0x50A, 0x389]} + RELAY_MALFUNCTION_ADDRS = {0: (0x340, 0x485, 0x421, 0x420, 0x50A, 0x389)} # LKAS11, LFAHDA_MFC, SCC12, SCC11, SCC13, SCC14 + + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CAMERA_SCC) + self.safety.init_tests() + + def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): + values = { + "aReqRaw": accel, + "aReqValue": accel, + "AEB_CmdAct": int(aeb_req), + "CR_VSM_DecCmd": aeb_decel, + } + return self.packer.make_can_msg_safety("SCC12", self.SCC_BUS, values) + + def test_no_aeb_scc12(self): + self.assertTrue(self._tx(self._accel_msg(0))) + self.assertFalse(self._tx(self._accel_msg(0, aeb_req=True))) + self.assertFalse(self._tx(self._accel_msg(0, aeb_decel=1.0))) + + def test_tester_present_allowed(self): + pass + + def test_disabled_ecu_alive(self): + pass + + +class TestHyundaiSafetyFCEVLong(TestHyundaiLongitudinalSafety, TestHyundaiSafetyFCEV): + def setUp(self): + self.packer = CANPackerSafety("hyundai_kia_generic") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, HyundaiSafetyFlags.FCEV_GAS | HyundaiSafetyFlags.LONG) + self.safety.init_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py new file mode 100755 index 0000000000..dd992f3379 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python3 +from parameterized import parameterized_class +import unittest + +from opendbc.car.hyundai.values import HyundaiSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety +from opendbc.safety.tests.hyundai_common import HyundaiButtonBase, HyundaiLongitudinalBase + +# All combinations of radar/camera-SCC and gas/hybrid/EV cars +ALL_GAS_EV_HYBRID_COMBOS = [ + # Radar SCC + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": 0}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS}, + # Camera SCC + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC}, +] + + +class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): + + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] + STANDSTILL_THRESHOLD = 12 # 0.375 kph + FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} + + MAX_RATE_UP = 2 + MAX_RATE_DOWN = 3 + MAX_TORQUE_LOOKUP = [0], [270] + + MAX_RT_DELTA = 112 + + DRIVER_TORQUE_ALLOWANCE = 250 + DRIVER_TORQUE_FACTOR = 2 + + # Safety around steering req bit + MIN_VALID_STEERING_FRAMES = 89 + MAX_INVALID_STEERING_FRAMES = 2 + + PT_BUS = 0 + SCC_BUS = 2 + STEER_BUS = 0 + STEER_MSG = "" + GAS_MSG = ("", "") + BUTTONS_TX_BUS = 1 + + def _torque_driver_msg(self, torque): + values = {"STEERING_COL_TORQUE": torque} + return self.packer.make_can_msg_safety("MDPS", self.PT_BUS, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"TORQUE_REQUEST": torque, "STEER_REQ": steer_req} + return self.packer.make_can_msg_safety(self.STEER_MSG, self.STEER_BUS, values) + + def _speed_msg(self, speed): + values = {f"WHL_Spd{pos}Val": speed * 0.03125 for pos in ["FL", "FR", "RL", "RR"]} + return self.packer.make_can_msg_safety("WHEEL_SPEEDS", self.PT_BUS, values) + + def _user_brake_msg(self, brake): + values = {"DriverBraking": brake} + return self.packer.make_can_msg_safety("TCS", self.PT_BUS, values) + + def _user_gas_msg(self, gas): + values = {self.GAS_MSG[1]: gas} + return self.packer.make_can_msg_safety(self.GAS_MSG[0], self.PT_BUS, values) + + def _pcm_status_msg(self, enable): + values = {"ACCMode": 1 if enable else 0} + return self.packer.make_can_msg_safety("SCC_CONTROL", self.SCC_BUS, values) + + def _button_msg(self, buttons, main_button=0, bus=None): + if bus is None: + bus = self.PT_BUS + values = { + "CRUISE_BUTTONS": buttons, + "ADAPTIVE_CRUISE_MAIN_BTN": main_button, + } + return self.packer.make_can_msg_safety("CRUISE_BUTTONS", bus, values) + + +class TestHyundaiCanfdLFASteeringBase(TestHyundaiCanfdBase): + + TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0)} # LFA, LFAHDA_CLUSTER + FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0]} + + STEER_MSG = "LFA" + BUTTONS_TX_BUS = 2 + SAFETY_PARAM: int + + @classmethod + def setUpClass(cls): + super().setUpClass() + if cls.__name__ in ("TestHyundaiCanfdLFASteering", "TestHyundaiCanfdLFASteeringAltButtons"): + cls.packer = None + cls.safety = None + raise unittest.SkipTest + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, self.SAFETY_PARAM) + self.safety.init_tests() + + +@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) +class TestHyundaiCanfdLFASteering(TestHyundaiCanfdLFASteeringBase): + pass + + +class TestHyundaiCanfdLFASteeringAltButtonsBase(TestHyundaiCanfdLFASteeringBase): + + SAFETY_PARAM: int + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM) + self.safety.init_tests() + + def _button_msg(self, buttons, main_button=0, bus=1): + values = { + "CRUISE_BUTTONS": buttons, + "ADAPTIVE_CRUISE_MAIN_BTN": main_button, + } + return self.packer.make_can_msg_safety("CRUISE_BUTTONS_ALT", self.PT_BUS, values) + + def _acc_cancel_msg(self, cancel, accel=0): + values = {"ACCMode": 4 if cancel else 0, "aReqRaw": accel, "aReqValue": accel} + return self.packer.make_can_msg_safety("SCC_CONTROL", self.PT_BUS, values) + + def test_button_sends(self): + """ + No button send allowed with alt buttons. + """ + for enabled in (True, False): + for btn in range(8): + self.safety.set_controls_allowed(enabled) + self.assertFalse(self._tx(self._button_msg(btn))) + + def test_acc_cancel(self): + # FIXME: the CANFD_ALT_BUTTONS cars are the only ones that use SCC_CONTROL to cancel, why can't we use buttons? + for enabled in (True, False): + self.safety.set_controls_allowed(enabled) + self.assertTrue(self._tx(self._acc_cancel_msg(True))) + self.assertFalse(self._tx(self._acc_cancel_msg(True, accel=1))) + self.assertFalse(self._tx(self._acc_cancel_msg(False))) + + +@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) +class TestHyundaiCanfdLFASteeringAltButtons(TestHyundaiCanfdLFASteeringAltButtonsBase): + pass + + +class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase): + + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4)} # LKAS, CAM_0x2A4 + FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} + + PT_BUS = 1 + SCC_BUS = 1 + STEER_MSG = "LKAS" + GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS) + self.safety.init_tests() + + +# TODO: Handle ICE and HEV configurations once we see cars that use the new messages +class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase): + + TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x110, 0x362)} # LKAS_ALT, CAM_0x362 + FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]} + + PT_BUS = 1 + SCC_BUS = 1 + STEER_MSG = "LKAS_ALT" + GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS | + HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT) + self.safety.init_tests() + + +class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdLKASteeringEV): + + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1], + [0x1e0, 1], [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]] + + RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4), 1: (0x1a0,)} # LKAS, CAM_0x2A4, SCC_CONTROL + + DISABLED_ECU_UDS_MSG = (0x730, 1) + DISABLED_ECU_ACTUATION_MSG = (0x1a0, 1) + + STEER_MSG = "LFA" + GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") + STEER_BUS = 1 + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | + HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.EV_GAS) + self.safety.init_tests() + + def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): + values = { + "aReqRaw": accel, + "aReqValue": accel, + } + return self.packer.make_can_msg_safety("SCC_CONTROL", 1, values) + + +# Tests longitudinal for ICE, hybrid, EV cars with LFA steering +class TestHyundaiCanfdLFASteeringLongBase(HyundaiLongitudinalBase, TestHyundaiCanfdLFASteeringBase): + + FWD_BLACKLISTED_ADDRS = {2: [0x12a, 0x1e0, 0x1a0, 0x160]} + + RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x1a0, 0x160)} # LFA, LFAHDA_CLUSTER, SCC_CONTROL, ADRV_0x160 + + DISABLED_ECU_UDS_MSG = (0x7D0, 0) + DISABLED_ECU_ACTUATION_MSG = (0x1a0, 0) + + @classmethod + def setUpClass(cls): + if cls.__name__ == "TestHyundaiCanfdLFASteeringLongBase": + cls.safety = None + raise unittest.SkipTest + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | self.SAFETY_PARAM) + self.safety.init_tests() + + def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): + values = { + "aReqRaw": accel, + "aReqValue": accel, + } + return self.packer.make_can_msg_safety("SCC_CONTROL", 0, values) + + def test_tester_present_allowed(self, ecu_disable: bool = True): + super().test_tester_present_allowed(ecu_disable=not self.SAFETY_PARAM & HyundaiSafetyFlags.CAMERA_SCC) + + +@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) +class TestHyundaiCanfdLFASteeringLong(TestHyundaiCanfdLFASteeringLongBase): + @classmethod + def setUpClass(cls): + if cls.__name__ == "TestHyundaiCanfdLFASteeringLong": + cls.safety = None + raise unittest.SkipTest + + +@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS) +class TestHyundaiCanfdLFASteeringLongAltButtons(TestHyundaiCanfdLFASteeringLongBase, TestHyundaiCanfdLFASteeringAltButtonsBase): + @classmethod + def setUpClass(cls): + if cls.__name__ == "TestHyundaiCanfdLFASteeringLongAltButtons": + cls.safety = None + raise unittest.SkipTest + + def setUp(self): + self.packer = CANPackerSafety("hyundai_canfd_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.CANFD_ALT_BUTTONS | self.SAFETY_PARAM) + self.safety.init_tests() + + def test_acc_cancel(self): + # Alt buttons does not use SCC_CONTROL to cancel if longitudinal + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_mazda.py b/opendbc_repo/opendbc/safety/tests/test_mazda.py new file mode 100755 index 0000000000..607edcbfda --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_mazda.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + + +class TestMazdaSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + + TX_MSGS = [[0x243, 0], [0x09d, 0], [0x440, 0]] + STANDSTILL_THRESHOLD = .1 + RELAY_MALFUNCTION_ADDRS = {0: (0x243, 0x440)} + FWD_BLACKLISTED_ADDRS = {2: [0x243, 0x440]} + + MAX_RATE_UP = 10 + MAX_RATE_DOWN = 25 + MAX_TORQUE_LOOKUP = [0], [800] + + MAX_RT_DELTA = 300 + + DRIVER_TORQUE_ALLOWANCE = 15 + DRIVER_TORQUE_FACTOR = 1 + + # Mazda actually does not set any bit when requesting torque + NO_STEER_REQ_BIT = True + + def setUp(self): + self.packer = CANPackerSafety("mazda_2017") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.mazda, 0) + self.safety.init_tests() + + def _torque_meas_msg(self, torque): + values = {"STEER_TORQUE_MOTOR": torque} + return self.packer.make_can_msg_safety("STEER_TORQUE", 0, values) + + def _torque_driver_msg(self, torque): + values = {"STEER_TORQUE_SENSOR": torque} + return self.packer.make_can_msg_safety("STEER_TORQUE", 0, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"LKAS_REQUEST": torque} + return self.packer.make_can_msg_safety("CAM_LKAS", 0, values) + + def _speed_msg(self, speed): + values = {"SPEED": speed} + return self.packer.make_can_msg_safety("ENGINE_DATA", 0, values) + + def _user_brake_msg(self, brake): + values = {"BRAKE_ON": brake} + return self.packer.make_can_msg_safety("PEDALS", 0, values) + + def _user_gas_msg(self, gas): + values = {"PEDAL_GAS": gas} + return self.packer.make_can_msg_safety("ENGINE_DATA", 0, values) + + def _pcm_status_msg(self, enable): + values = {"CRZ_ACTIVE": enable} + return self.packer.make_can_msg_safety("CRZ_CTRL", 0, values) + + def _button_msg(self, resume=False, cancel=False): + values = { + "CAN_OFF": cancel, + "CAN_OFF_INV": (cancel + 1) % 2, + "RES": resume, + "RES_INV": (resume + 1) % 2, + } + return self.packer.make_can_msg_safety("CRZ_BTNS", 0, values) + + def test_buttons(self): + # only cancel allows while controls not allowed + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(self._button_msg(cancel=True))) + self.assertFalse(self._tx(self._button_msg(resume=True))) + + # do not block resume if we are engaged already + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(self._button_msg(cancel=True))) + self.assertTrue(self._tx(self._button_msg(resume=True))) + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_nissan.py b/opendbc_repo/opendbc/safety/tests/test_nissan.py new file mode 100755 index 0000000000..8f034cd78a --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_nissan.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.nissan.values import NissanSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + + +class TestNissanSafety(common.CarSafetyTest, common.AngleSteeringSafetyTest): + + TX_MSGS = [[0x169, 0], [0x2b1, 0], [0x4cc, 0], [0x20b, 2], [0x280, 2]] + GAS_PRESSED_THRESHOLD = 3 + RELAY_MALFUNCTION_ADDRS = {0: (0x169, 0x2b1, 0x4cc), 2: (0x280,)} + FWD_BLACKLISTED_ADDRS = {0: [0x280], 2: [0x169, 0x2b1, 0x4cc]} + + EPS_BUS = 0 + CRUISE_BUS = 2 + + # Angle control limits + STEER_ANGLE_MAX = 600 # deg, reasonable limit + DEG_TO_CAN = 100 + + ANGLE_RATE_BP = [0., 5., 15.] + ANGLE_RATE_UP = [5., .8, .15] # windup limit + ANGLE_RATE_DOWN = [5., 3.5, .4] # unwind limit + + def setUp(self): + self.packer = CANPackerSafety("nissan_x_trail_2017_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.nissan, 0) + self.safety.init_tests() + + def _angle_cmd_msg(self, angle: float, enabled: bool): + values = {"DESIRED_ANGLE": angle, "LKA_ACTIVE": 1 if enabled else 0} + return self.packer.make_can_msg_safety("LKAS", 0, values) + + def _angle_meas_msg(self, angle: float): + values = {"STEER_ANGLE": angle} + return self.packer.make_can_msg_safety("STEER_ANGLE_SENSOR", self.EPS_BUS, values) + + def _pcm_status_msg(self, enable): + values = {"CRUISE_ENABLED": enable} + return self.packer.make_can_msg_safety("CRUISE_STATE", self.CRUISE_BUS, values) + + def _speed_msg(self, speed): + values = {"WHEEL_SPEED_%s" % s: speed * 3.6 for s in ["RR", "RL"]} + return self.packer.make_can_msg_safety("WHEEL_SPEEDS_REAR", self.EPS_BUS, values) + + def _user_brake_msg(self, brake): + values = {"USER_BRAKE_PRESSED": brake} + return self.packer.make_can_msg_safety("DOORS_LIGHTS", self.EPS_BUS, values) + + def _user_gas_msg(self, gas): + values = {"GAS_PEDAL": gas} + return self.packer.make_can_msg_safety("GAS_PEDAL", self.EPS_BUS, values) + + def _acc_button_cmd(self, cancel=0, propilot=0, flw_dist=0, _set=0, res=0): + no_button = not any([cancel, propilot, flw_dist, _set, res]) + values = {"CANCEL_BUTTON": cancel, "PROPILOT_BUTTON": propilot, + "FOLLOW_DISTANCE_BUTTON": flw_dist, "SET_BUTTON": _set, + "RES_BUTTON": res, "NO_BUTTON_PRESSED": no_button} + return self.packer.make_can_msg_safety("CRUISE_THROTTLE", 2, values) + + def test_acc_buttons(self): + btns = [ + ("cancel", True), + ("propilot", False), + ("flw_dist", False), + ("_set", False), + ("res", False), + (None, False), + ] + for controls_allowed in (True, False): + for btn, should_tx in btns: + self.safety.set_controls_allowed(controls_allowed) + args = {} if btn is None else {btn: 1} + tx = self._tx(self._acc_button_cmd(**args)) + self.assertEqual(tx, should_tx) + + +class TestNissanSafetyAltEpsBus(TestNissanSafety): + """Altima uses different buses""" + + EPS_BUS = 1 + CRUISE_BUS = 1 + + def setUp(self): + self.packer = CANPackerSafety("nissan_x_trail_2017_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.nissan, NissanSafetyFlags.ALT_EPS_BUS) + self.safety.init_tests() + + +class TestNissanLeafSafety(TestNissanSafety): + + def setUp(self): + self.packer = CANPackerSafety("nissan_leaf_2018_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.nissan, 0) + self.safety.init_tests() + + def _user_brake_msg(self, brake): + values = {"USER_BRAKE_PRESSED": brake} + return self.packer.make_can_msg_safety("CRUISE_THROTTLE", 0, values) + + def _user_gas_msg(self, gas): + values = {"GAS_PEDAL": gas} + return self.packer.make_can_msg_safety("CRUISE_THROTTLE", 0, values) + + # TODO: leaf should use its own safety param + def test_acc_buttons(self): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_psa.py b/opendbc_repo/opendbc/safety/tests/test_psa.py new file mode 100644 index 0000000000..ac45666304 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_psa.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + +LANE_KEEP_ASSIST = 0x3F2 + + +class TestPsaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest): + RELAY_MALFUNCTION_ADDRS = {0: (LANE_KEEP_ASSIST,)} + FWD_BLACKLISTED_ADDRS = {2: [LANE_KEEP_ASSIST]} + TX_MSGS = [[1010, 0]] + + MAIN_BUS = 0 + ADAS_BUS = 1 + CAM_BUS = 2 + + STEER_ANGLE_MAX = 390 + DEG_TO_CAN = 10 + + ANGLE_RATE_BP = [0., 5., 25.] + ANGLE_RATE_UP = [2.5, 1.5, .2] + ANGLE_RATE_DOWN = [5., 2., .3] + + def setUp(self): + self.packer = CANPackerSafety("psa_aee2010_r3") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.psa, 0) + self.safety.init_tests() + + def _angle_cmd_msg(self, angle: float, enabled: bool): + values = {"SET_ANGLE": angle, "TORQUE_FACTOR": 100 if enabled else 0} + return self.packer.make_can_msg_safety("LANE_KEEP_ASSIST", self.MAIN_BUS, values) + + def _angle_meas_msg(self, angle: float): + values = {"ANGLE": angle} + return self.packer.make_can_msg_safety("STEERING_ALT", self.MAIN_BUS, values) + + def _pcm_status_msg(self, enable): + values = {"RVV_ACC_ACTIVATION_REQ": enable} + return self.packer.make_can_msg_safety("HS2_DAT_MDD_CMD_452", self.ADAS_BUS, values) + + def _speed_msg(self, speed): + values = {"VITESSE_VEHICULE_ROUES": speed * 3.6} + return self.packer.make_can_msg_safety("HS2_DYN_ABR_38D", self.MAIN_BUS, values) + + def _user_brake_msg(self, brake): + values = {"P013_MainBrake": brake} + return self.packer.make_can_msg_safety("Dat_BSI", self.CAM_BUS, values) + + def _user_gas_msg(self, gas): + values = {"P002_Com_rAPP": int(gas * 100)} + return self.packer.make_can_msg_safety("Dyn_CMM", self.MAIN_BUS, values) + + def test_rx_hook(self): + # speed + for _ in range(10): + self.assertTrue(self._rx(self._speed_msg(0))) + msg = self._speed_msg(0) + # invalidate checksum + msg[0].data[5] = 0x00 + self.assertFalse(self._rx(msg)) + + # cruise + for _ in range(10): + self.assertTrue(self._rx(self._pcm_status_msg(0))) + msg = self._pcm_status_msg(0) + # invalidate checksum + msg[0].data[5] = 0x00 + self.assertFalse(self._rx(msg)) + msg = self._pcm_status_msg(0) + # write to unused payload byte + msg[0].data[6] = 0xAB + self.assertTrue(self._rx(msg)) + + +class TestPsaStockSafety(TestPsaSafetyBase): + + def setUp(self): + self.packer = CANPackerSafety("psa_aee2010_r3") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.psa, 0) + self.safety.init_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_rivian.py b/opendbc_repo/opendbc/safety/tests/test_rivian.py new file mode 100755 index 0000000000..f1393e605c --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_rivian.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety +from opendbc.car.rivian.values import RivianSafetyFlags +from opendbc.car.rivian.riviancan import checksum as _checksum + + +def checksum(msg): + addr, dat, bus = msg + ret = bytearray(dat) + + # ESP_Status + if addr == 0x208: + ret[0] = _checksum(ret[1:], 0x1D, 0xB1) + elif addr == 0x150: + ret[0] = _checksum(ret[1:], 0x1D, 0x9A) + + return addr, ret, bus + + +class TestRivianSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.LongitudinalAccelSafetyTest, + common.VehicleSpeedSafetyTest): + + TX_MSGS = [[0x120, 0], [0x321, 2], [0x162, 2]] + RELAY_MALFUNCTION_ADDRS = {0: (0x120,), 2: (0x321, 0x162)} + FWD_BLACKLISTED_ADDRS = {0: [0x321, 0x162], 2: [0x120]} + + MAX_TORQUE_LOOKUP = [9, 17], [350, 250] + DYNAMIC_MAX_TORQUE = True + MAX_RATE_UP = 3 + MAX_RATE_DOWN = 5 + + MAX_RT_DELTA = 125 + + DRIVER_TORQUE_ALLOWANCE = 100 + DRIVER_TORQUE_FACTOR = 2 + + cnt_speed = 0 + cnt_speed_2 = 0 + + def _torque_driver_msg(self, torque): + values = {"EPAS_TorsionBarTorque": torque / 100.0} + return self.packer.make_can_msg_safety("EPAS_SystemStatus", 0, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"ACM_lkaStrToqReq": torque, "ACM_lkaActToi": steer_req} + return self.packer.make_can_msg_safety("ACM_lkaHbaCmd", 0, values) + + def _speed_msg(self, speed, quality_flag=True): + values = {"ESP_Vehicle_Speed": speed * 3.6, "ESP_Status_Counter": self.cnt_speed % 15, + "ESP_Vehicle_Speed_Q": 1 if quality_flag else 0} + self.__class__.cnt_speed += 1 + return self.packer.make_can_msg_safety("ESP_Status", 0, values, fix_checksum=checksum) + + def _speed_msg_2(self, speed, quality_flag=True): + # Rivian has a dynamic max torque limit based on speed, so it checks two sources + return self._user_gas_msg(0, speed, quality_flag) + + def _user_brake_msg(self, brake): + values = {"iBESP2_BrakePedalApplied": brake} + return self.packer.make_can_msg_safety("iBESP2", 0, values) + + def _user_gas_msg(self, gas, speed=0, quality_flag=True): + values = {"VDM_AcceleratorPedalPosition": gas, "VDM_VehicleSpeed": speed * 3.6, + "VDM_PropStatus_Counter": self.cnt_speed_2 % 15, "VDM_VehicleSpeedQ": 1 if quality_flag else 0} + self.__class__.cnt_speed_2 += 1 + return self.packer.make_can_msg_safety("VDM_PropStatus", 0, values, fix_checksum=checksum) + + def _pcm_status_msg(self, enable): + values = {"ACM_FeatureStatus": enable, "ACM_Unkown1": 1} + return self.packer.make_can_msg_safety("ACM_Status", 2, values) + + def _accel_msg(self, accel: float): + values = {"ACM_AccelerationRequest": accel} + return self.packer.make_can_msg_safety("ACM_longitudinalRequest", 0, values) + + def test_wheel_touch(self): + # For hiding hold wheel alert on engage + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + values = { + "SCCM_WheelTouch_HandsOn": 1 if controls_allowed else 0, + "SCCM_WheelTouch_CapacitiveValue": 100 if controls_allowed else 0, + "SETME_X52": 100, + } + self.assertTrue(self._tx(self.packer.make_can_msg_safety("SCCM_WheelTouch", 2, values))) + + def test_rx_hook(self): + # checksum, counter, and quality flag checks + for quality_flag in (True, False): + for msg_type in ("speed", "speed_2"): + self.safety.set_controls_allowed(True) + # send multiple times to verify counter checks + for _ in range(10): + if msg_type == "speed": + msg = self._speed_msg(0, quality_flag=quality_flag) + elif msg_type == "speed_2": + msg = self._speed_msg_2(0, quality_flag=quality_flag) + + self.assertEqual(quality_flag, self._rx(msg)) + self.assertEqual(quality_flag, self.safety.get_controls_allowed()) + + # Mess with checksum to make it fail + msg[0].data[0] = 0xff + self.assertFalse(self._rx(msg)) + self.assertFalse(self.safety.get_controls_allowed()) + + +class TestRivianStockSafety(TestRivianSafetyBase): + + LONGITUDINAL = False + + def setUp(self): + self.packer = CANPackerSafety("rivian_primary_actuator") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.rivian, 0) + self.safety.init_tests() + + def test_adas_status(self): + # For canceling stock ACC + for controls_allowed in (True, False): + self.safety.set_controls_allowed(controls_allowed) + for interface_status in range(4): + values = {"VDM_AdasInterfaceStatus": interface_status} + self.assertTrue(self._tx(self.packer.make_can_msg_safety("VDM_AdasSts", 2, values))) + + +class TestRivianLongitudinalSafety(TestRivianSafetyBase): + + TX_MSGS = [[0x120, 0], [0x321, 2], [0x160, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x120, 0x160), 2: (0x321,)} + FWD_BLACKLISTED_ADDRS = {0: [0x321], 2: [0x120, 0x160]} + + def setUp(self): + self.packer = CANPackerSafety("rivian_primary_actuator") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.rivian, RivianSafetyFlags.LONG_CONTROL) + self.safety.init_tests() + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_subaru.py b/opendbc_repo/opendbc/safety/tests/test_subaru.py new file mode 100755 index 0000000000..a0ad42d8d6 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_subaru.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python3 +import enum +import unittest + +from opendbc.car.subaru.values import SubaruSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety +from functools import partial + + +class SubaruMsg(enum.IntEnum): + Brake_Status = 0x13c + CruiseControl = 0x240 + Throttle = 0x40 + Steering_Torque = 0x119 + Wheel_Speeds = 0x13a + ES_LKAS = 0x122 + ES_LKAS_ANGLE = 0x124 + ES_Brake = 0x220 + ES_Distance = 0x221 + ES_Status = 0x222 + ES_DashStatus = 0x321 + ES_LKAS_State = 0x322 + ES_Infotainment = 0x323 + ES_UDS_Request = 0x787 + ES_HighBeamAssist = 0x121 + ES_STATIC_1 = 0x22a + ES_STATIC_2 = 0x325 + + +SUBARU_MAIN_BUS = 0 +SUBARU_ALT_BUS = 1 +SUBARU_CAM_BUS = 2 + + +def lkas_tx_msgs(alt_bus, lkas_msg=SubaruMsg.ES_LKAS): + return [[lkas_msg, SUBARU_MAIN_BUS], + [SubaruMsg.ES_Distance, alt_bus], + [SubaruMsg.ES_DashStatus, SUBARU_MAIN_BUS], + [SubaruMsg.ES_LKAS_State, SUBARU_MAIN_BUS], + [SubaruMsg.ES_Infotainment, SUBARU_MAIN_BUS]] + + +def long_tx_msgs(alt_bus): + return [[SubaruMsg.ES_Brake, alt_bus], + [SubaruMsg.ES_Status, alt_bus]] + + +def gen2_long_additional_tx_msgs(): + return [[SubaruMsg.ES_UDS_Request, SUBARU_CAM_BUS], + [SubaruMsg.ES_HighBeamAssist, SUBARU_MAIN_BUS], + [SubaruMsg.ES_STATIC_1, SUBARU_MAIN_BUS], + [SubaruMsg.ES_STATIC_2, SUBARU_MAIN_BUS]] + + +def fwd_blacklisted_addr(lkas_msg=SubaruMsg.ES_LKAS): + return {SUBARU_CAM_BUS: [lkas_msg, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment]} + + +class TestSubaruSafetyBase(common.CarSafetyTest): + FLAGS = 0 + RELAY_MALFUNCTION_ADDRS = {SUBARU_MAIN_BUS: (SubaruMsg.ES_LKAS, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, + SubaruMsg.ES_Infotainment)} + FWD_BLACKLISTED_ADDRS = fwd_blacklisted_addr() + + MAX_RT_DELTA = 940 + + DRIVER_TORQUE_ALLOWANCE = 60 + DRIVER_TORQUE_FACTOR = 50 + + ALT_MAIN_BUS = SUBARU_MAIN_BUS + ALT_CAM_BUS = SUBARU_CAM_BUS + + DEG_TO_CAN = 100 + + INACTIVE_GAS = 1818 + + def setUp(self): + self.packer = CANPackerSafety("subaru_global_2017_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.subaru, self.FLAGS) + self.safety.init_tests() + + def _set_prev_torque(self, t): + self.safety.set_desired_torque_last(t) + self.safety.set_rt_torque_last(t) + + def _torque_driver_msg(self, torque): + values = {"Steer_Torque_Sensor": torque} + return self.packer.make_can_msg_safety("Steering_Torque", 0, values) + + def _speed_msg(self, speed): + values = {s: speed for s in ["FR", "FL", "RR", "RL"]} + return self.packer.make_can_msg_safety("Wheel_Speeds", self.ALT_MAIN_BUS, values) + + def _angle_meas_msg(self, angle): + values = {"Steering_Angle": angle} + return self.packer.make_can_msg_safety("Steering_Torque", 0, values) + + def _user_brake_msg(self, brake): + values = {"Brake": brake} + return self.packer.make_can_msg_safety("Brake_Status", self.ALT_MAIN_BUS, values) + + def _user_gas_msg(self, gas): + values = {"Throttle_Pedal": gas} + return self.packer.make_can_msg_safety("Throttle", 0, values) + + def _pcm_status_msg(self, enable): + values = {"Cruise_Activated": enable} + return self.packer.make_can_msg_safety("CruiseControl", self.ALT_MAIN_BUS, values) + + +class TestSubaruStockLongitudinalSafetyBase(TestSubaruSafetyBase): + def _cancel_msg(self, cancel, cruise_throttle=0): + values = {"Cruise_Cancel": cancel, "Cruise_Throttle": cruise_throttle} + return self.packer.make_can_msg_safety("ES_Distance", self.ALT_MAIN_BUS, values) + + def test_cancel_message(self): + # test that we can only send the cancel message (ES_Distance) with inactive throttle (1818) and Cruise_Cancel=1 + for cancel in [True, False]: + self._generic_limit_safety_check(partial(self._cancel_msg, cancel), self.INACTIVE_GAS, self.INACTIVE_GAS, 0, 2**12, 1, self.INACTIVE_GAS, cancel) + + +class TestSubaruLongitudinalSafetyBase(TestSubaruSafetyBase, common.LongitudinalGasBrakeSafetyTest): + MIN_GAS = 808 + MAX_GAS = 3400 + INACTIVE_GAS = 1818 + MAX_POSSIBLE_GAS = 2**13 + + MIN_BRAKE = 0 + MAX_BRAKE = 600 + MAX_POSSIBLE_BRAKE = 2**16 + + MIN_RPM = 0 + MAX_RPM = 3600 + MAX_POSSIBLE_RPM = 2**13 + + FWD_BLACKLISTED_ADDRS = {2: [SubaruMsg.ES_LKAS, SubaruMsg.ES_Brake, SubaruMsg.ES_Distance, + SubaruMsg.ES_Status, SubaruMsg.ES_DashStatus, + SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment]} + + def test_rpm_safety_check(self): + self._generic_limit_safety_check(self._send_rpm_msg, self.MIN_RPM, self.MAX_RPM, 0, self.MAX_POSSIBLE_RPM, 1) + + def _send_brake_msg(self, brake): + values = {"Brake_Pressure": brake} + return self.packer.make_can_msg_safety("ES_Brake", self.ALT_MAIN_BUS, values) + + def _send_gas_msg(self, gas): + values = {"Cruise_Throttle": gas} + return self.packer.make_can_msg_safety("ES_Distance", self.ALT_MAIN_BUS, values) + + def _send_rpm_msg(self, rpm): + values = {"Cruise_RPM": rpm} + return self.packer.make_can_msg_safety("ES_Status", self.ALT_MAIN_BUS, values) + + +class TestSubaruTorqueSafetyBase(TestSubaruSafetyBase, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): + MAX_RATE_UP = 50 + MAX_RATE_DOWN = 70 + MAX_TORQUE_LOOKUP = [0], [2047] + + # Safety around steering req bit + MIN_VALID_STEERING_FRAMES = 7 + MAX_INVALID_STEERING_FRAMES = 1 + STEER_STEP = 2 + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"LKAS_Output": torque, "LKAS_Request": steer_req} + return self.packer.make_can_msg_safety("ES_LKAS", SUBARU_MAIN_BUS, values) + + +class TestSubaruGen1TorqueStockLongitudinalSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruTorqueSafetyBase): + FLAGS = 0 + TX_MSGS = lkas_tx_msgs(SUBARU_MAIN_BUS) + + +class TestSubaruGen2TorqueSafetyBase(TestSubaruTorqueSafetyBase): + ALT_MAIN_BUS = SUBARU_ALT_BUS + ALT_CAM_BUS = SUBARU_ALT_BUS + + MAX_RATE_UP = 40 + MAX_RATE_DOWN = 40 + MAX_TORQUE_LOOKUP = [0], [1000] + + +class TestSubaruGen2TorqueStockLongitudinalSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruGen2TorqueSafetyBase): + FLAGS = SubaruSafetyFlags.GEN2 + TX_MSGS = lkas_tx_msgs(SUBARU_ALT_BUS) + + +class TestSubaruGen1LongitudinalSafety(TestSubaruLongitudinalSafetyBase, TestSubaruTorqueSafetyBase): + FLAGS = SubaruSafetyFlags.LONG + TX_MSGS = lkas_tx_msgs(SUBARU_MAIN_BUS) + long_tx_msgs(SUBARU_MAIN_BUS) + RELAY_MALFUNCTION_ADDRS = {SUBARU_MAIN_BUS: (SubaruMsg.ES_LKAS, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, + SubaruMsg.ES_Infotainment, SubaruMsg.ES_Brake, SubaruMsg.ES_Status, + SubaruMsg.ES_Distance)} + + +class TestSubaruGen2LongitudinalSafety(TestSubaruLongitudinalSafetyBase, TestSubaruGen2TorqueSafetyBase): + FLAGS = SubaruSafetyFlags.LONG | SubaruSafetyFlags.GEN2 + TX_MSGS = lkas_tx_msgs(SUBARU_ALT_BUS) + long_tx_msgs(SUBARU_ALT_BUS) + gen2_long_additional_tx_msgs() + FWD_BLACKLISTED_ADDRS = {2: [SubaruMsg.ES_LKAS, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, + SubaruMsg.ES_Infotainment]} + RELAY_MALFUNCTION_ADDRS = {SUBARU_MAIN_BUS: (SubaruMsg.ES_LKAS, SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, + SubaruMsg.ES_Infotainment), + SUBARU_ALT_BUS: (SubaruMsg.ES_Brake, SubaruMsg.ES_Status, SubaruMsg.ES_Distance)} + + def _rdbi_msg(self, did: int): + return b'\x03\x22' + did.to_bytes(2) + b'\x00\x00\x00\x00' + + def _es_uds_msg(self, msg: bytes): + return libsafety_py.make_CANPacket(SubaruMsg.ES_UDS_Request, 2, msg) + + def test_es_uds_message(self): + tester_present = b'\x02\x3E\x80\x00\x00\x00\x00\x00' + not_tester_present = b"\x03\xAA\xAA\x00\x00\x00\x00\x00" + + button_did = 0x1130 + + # Tester present is allowed for gen2 long to keep eyesight disabled + self.assertTrue(self._tx(self._es_uds_msg(tester_present))) + + # Non-Tester present is not allowed + self.assertFalse(self._tx(self._es_uds_msg(not_tester_present))) + + # Only button_did is allowed to be read via UDS + for did in range(0xFFFF): + should_tx = (did == button_did) + self.assertEqual(self._tx(self._es_uds_msg(self._rdbi_msg(did))), should_tx) + + # any other msg is not allowed + for sid in range(0xFF): + msg = b'\x03' + sid.to_bytes(1) + b'\x00' * 6 + self.assertFalse(self._tx(self._es_uds_msg(msg))) + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py b/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py new file mode 100755 index 0000000000..fb96de2489 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_subaru_preglobal.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.structs import CarParams +from opendbc.car.subaru.values import SubaruSafetyFlags +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + + +class TestSubaruPreglobalSafety(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + FLAGS = 0 + DBC = "subaru_outback_2015_generated" + TX_MSGS = [[0x161, 0], [0x164, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x164, 0x161)} + FWD_BLACKLISTED_ADDRS = {2: [0x161, 0x164]} + + MAX_RATE_UP = 50 + MAX_RATE_DOWN = 70 + MAX_TORQUE_LOOKUP = [0], [2047] + + MAX_RT_DELTA = 940 + + DRIVER_TORQUE_ALLOWANCE = 75 + DRIVER_TORQUE_FACTOR = 10 + + def setUp(self): + self.packer = CANPackerSafety(self.DBC) + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.subaruPreglobal, self.FLAGS) + self.safety.init_tests() + + def _set_prev_torque(self, t): + self.safety.set_desired_torque_last(t) + self.safety.set_rt_torque_last(t) + + def _torque_driver_msg(self, torque): + values = {"Steer_Torque_Sensor": torque} + return self.packer.make_can_msg_safety("Steering_Torque", 0, values) + + def _speed_msg(self, speed): + # subaru safety doesn't use the scaled value, so undo the scaling + values = {s: speed*0.0592 for s in ["FR", "FL", "RR", "RL"]} + return self.packer.make_can_msg_safety("Wheel_Speeds", 0, values) + + def _user_brake_msg(self, brake): + values = {"Brake_Pedal": brake} + return self.packer.make_can_msg_safety("Brake_Pedal", 0, values) + + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"LKAS_Command": torque, "LKAS_Active": steer_req} + return self.packer.make_can_msg_safety("ES_LKAS", 0, values) + + def _user_gas_msg(self, gas): + values = {"Throttle_Pedal": gas} + return self.packer.make_can_msg_safety("Throttle", 0, values) + + def _pcm_status_msg(self, enable): + values = {"Cruise_Activated": enable} + return self.packer.make_can_msg_safety("CruiseControl", 0, values) + + +class TestSubaruPreglobalReversedDriverTorqueSafety(TestSubaruPreglobalSafety): + FLAGS = SubaruSafetyFlags.PREGLOBAL_REVERSED_DRIVER_TORQUE + DBC = "subaru_outback_2019_generated" + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_tesla.py b/opendbc_repo/opendbc/safety/tests/test_tesla.py new file mode 100755 index 0000000000..52390f81aa --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_tesla.py @@ -0,0 +1,451 @@ +#!/usr/bin/env python3 +import random +import unittest +import numpy as np + +from opendbc.car.lateral import get_max_angle_delta_vm, get_max_angle_vm +from opendbc.car.tesla.values import CarControllerParams, TeslaSafetyFlags +from opendbc.car.tesla.carcontroller import get_safety_CP +from opendbc.car.structs import CarParams +from opendbc.car.vehicle_model import VehicleModel +from opendbc.can import CANDefine +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety, MAX_SPEED_DELTA, MAX_WRONG_COUNTERS, away_round, round_speed + +MSG_DAS_steeringControl = 0x488 +MSG_APS_eacMonitor = 0x27d +MSG_DAS_Control = 0x2b9 + + +def round_angle(apply_angle, can_offset=0): + apply_angle_can = (apply_angle + 1638.35) / 0.1 + can_offset + # 0.49999_ == 0.5 + rnd_offset = 1e-5 if apply_angle >= 0 else -1e-5 + return away_round(apply_angle_can + rnd_offset) * 0.1 - 1638.35 + + +class TestTeslaSafetyBase(common.CarSafetyTest, common.AngleSteeringSafetyTest, common.LongitudinalAccelSafetyTest): + RELAY_MALFUNCTION_ADDRS = {0: (MSG_DAS_steeringControl, MSG_APS_eacMonitor)} + FWD_BLACKLISTED_ADDRS = {2: [MSG_DAS_steeringControl, MSG_APS_eacMonitor]} + TX_MSGS = [[MSG_DAS_steeringControl, 0], [MSG_APS_eacMonitor, 0], [MSG_DAS_Control, 0]] + + STANDSTILL_THRESHOLD = 0.1 + GAS_PRESSED_THRESHOLD = 3 + + # Angle control limits + STEER_ANGLE_MAX = 360 # deg + DEG_TO_CAN = 10 + + # Tesla uses get_max_angle_delta_vm and get_max_angle_vm for real lateral accel and jerk limits + # TODO: integrate this into AngleSteeringSafetyTest + ANGLE_RATE_BP = None + ANGLE_RATE_UP = None + ANGLE_RATE_DOWN = None + + # Real time limits + LATERAL_FREQUENCY = 50 # Hz + + # Long control limits + MAX_ACCEL = 2.0 + MIN_ACCEL = -3.48 + INACTIVE_ACCEL = 0.0 + + cnt_epas = 0 + cnt_angle_cmd = 0 + + packer: CANPackerSafety + + def _get_steer_cmd_angle_max(self, speed): + return get_max_angle_vm(max(speed, 1), self.VM, CarControllerParams) + + def setUp(self): + self.VM = VehicleModel(get_safety_CP()) + self.packer = CANPackerSafety("tesla_model3_party") + self.define = CANDefine("tesla_model3_party") + self.acc_states = {d: v for v, d in self.define.dv["DAS_control"]["DAS_accState"].items()} + self.autopark_states = {d: v for v, d in self.define.dv["DI_state"]["DI_autoparkState"].items()} + self.active_autopark_states = [self.autopark_states[s] for s in ('ACTIVE', 'COMPLETE', 'SELFPARK_STARTED')] + + self.steer_control_types = {d: v for v, d in self.define.dv["DAS_steeringControl"]["DAS_steeringControlType"].items()} + + def _angle_cmd_msg(self, angle: float, state: bool | int, increment_timer: bool = True, bus: int = 0): + values = {"DAS_steeringAngleRequest": angle, "DAS_steeringControlType": state} + if increment_timer: + self.safety.set_timer(self.cnt_angle_cmd * int(1e6 / self.LATERAL_FREQUENCY)) + self.__class__.cnt_angle_cmd += 1 + return self.packer.make_can_msg_safety("DAS_steeringControl", bus, values) + + def _angle_meas_msg(self, angle: float, hands_on_level: int = 0, eac_status: int = 1, eac_error_code: int = 0): + values = {"EPAS3S_internalSAS": angle, "EPAS3S_handsOnLevel": hands_on_level, + "EPAS3S_eacStatus": eac_status, "EPAS3S_eacErrorCode": eac_error_code, + "EPAS3S_sysStatusCounter": self.cnt_epas % 16} + self.__class__.cnt_epas += 1 + return self.packer.make_can_msg_safety("EPAS3S_sysStatus", 0, values) + + def _user_brake_msg(self, brake, quality_flag: bool = True): + values = {"IBST_driverBrakeApply": 2 if brake else 1} + if not quality_flag: + values["IBST_driverBrakeApply"] = random.choice((0, 3)) # NOT_INIT_OR_OFF, FAULT + return self.packer.make_can_msg_safety("IBST_status", 0, values) + + def _speed_msg(self, speed): + values = {"DI_vehicleSpeed": speed * 3.6} + return self.packer.make_can_msg_safety("DI_speed", 0, values) + + def _speed_msg_2(self, speed, quality_flag=True): + values = {"ESP_vehicleSpeed": speed * 3.6, "ESP_wheelSpeedsQF": quality_flag} + return self.packer.make_can_msg_safety("ESP_B", 0, values) + + def _vehicle_moving_msg(self, speed: float, quality_flag=True): + values = {"ESP_vehicleStandstillSts": 1 if speed <= self.STANDSTILL_THRESHOLD else 0, + "ESP_wheelSpeedsQF": quality_flag} + return self.packer.make_can_msg_safety("ESP_B", 0, values) + + def _user_gas_msg(self, gas): + values = {"DI_accelPedalPos": gas} + return self.packer.make_can_msg_safety("DI_systemStatus", 0, values) + + def _pcm_status_msg(self, enable, autopark_state=0): + values = { + "DI_cruiseState": 2 if enable else 0, + "DI_autoparkState": autopark_state, + } + return self.packer.make_can_msg_safety("DI_state", 0, values) + + def _long_control_msg(self, set_speed, acc_state=0, jerk_limits=(0, 0), accel_limits=(0, 0), aeb_event=0, bus=0): + values = { + "DAS_setSpeed": set_speed, + "DAS_accState": acc_state, + "DAS_aebEvent": aeb_event, + "DAS_jerkMin": jerk_limits[0], + "DAS_jerkMax": jerk_limits[1], + "DAS_accelMin": accel_limits[0], + "DAS_accelMax": accel_limits[1], + } + return self.packer.make_can_msg_safety("DAS_control", bus, values) + + def _accel_msg(self, accel: float): + # For common.LongitudinalAccelSafetyTest + return self._long_control_msg(10, accel_limits=(accel, max(accel, 0))) + + def test_rx_hook(self): + # counter check + for msg_type in ("angle", "long", "speed", "speed_2"): + # send multiple times to verify counter checks + for i in range(10): + if msg_type == "angle": + msg = self._angle_cmd_msg(0, True, bus=2) + elif msg_type == "long": + msg = self._long_control_msg(0, bus=2) + elif msg_type == "speed": + msg = self._speed_msg(0) + elif msg_type == "speed_2": + msg = self._speed_msg_2(0) + + should_rx = i >= 5 + if not should_rx: + # mess with checksums + if msg_type == "angle": + msg[0].data[3] = 0 + elif msg_type == "long": + msg[0].data[7] = 0 + elif msg_type == "speed": + msg[0].data[0] = 0 + elif msg_type == "speed_2": + msg[0].data[7] = 0 + + self.safety.set_controls_allowed(True) + self.assertEqual(should_rx, self._rx(msg)) + self.assertEqual(should_rx, self.safety.get_controls_allowed()) + + # Send static counters + for i in range(MAX_WRONG_COUNTERS + 1): + should_rx = i + 1 < MAX_WRONG_COUNTERS + self.assertEqual(should_rx, self._rx(msg)) + self.assertEqual(should_rx, self.safety.get_controls_allowed()) + + def test_vehicle_speed_measurements(self): + # OVERRIDDEN: 79.1667 is the max speed in m/s + self._common_measurement_test(self._speed_msg, 0, 285 / 3.6, 1, + self.safety.get_vehicle_speed_min, self.safety.get_vehicle_speed_max) + + def test_rx_hook_speed_mismatch(self): + # TODO: overridden because of custom rounding + # Tesla relies on speed for lateral limits close to ISO 11270, so it checks two sources + for speed in np.arange(0, 40, 0.5): + # match signal rounding on CAN + speed = away_round(speed / 0.08 * 3.6) * 0.08 / 3.6 + for speed_delta in np.arange(-5, 5, 0.1): + speed_2 = max(speed + speed_delta, 0) + speed_2 = away_round(speed_2 * 2 * 3.6) / 2 / 3.6 + + # Set controls allowed in between rx since first message can reset it + self.assertTrue(self._rx(self._speed_msg(speed))) + self.safety.set_controls_allowed(True) + self.assertTrue(self._rx(self._speed_msg_2(speed_2))) + + within_delta = abs(speed - speed_2) <= MAX_SPEED_DELTA + self.assertEqual(self.safety.get_controls_allowed(), within_delta) + + # Test ESP_B quality flag + for quality_flag in (True, False): + self.safety.set_controls_allowed(True) + self.assertTrue(self._rx(self._speed_msg(0))) + self.assertEqual(quality_flag, self._rx(self._speed_msg_2(0, quality_flag=quality_flag))) + self.assertEqual(quality_flag, self.safety.get_controls_allowed()) + + def test_user_brake_quality_flag(self): + for quality_flag in (True, False): + msg = self._user_brake_msg(True, quality_flag=quality_flag) + self.assertEqual(quality_flag, self._rx(msg)) + + def test_steering_wheel_disengage(self): + # Tesla disengages when the user forcibly overrides the locked-in angle steering control + # Either when the hands on level is high, or if there is a high angle rate fault + for hands_on_level in range(4): + for eac_status in range(8): + for eac_error_code in range(16): + self.safety.set_controls_allowed(True) + + should_disengage = hands_on_level >= 3 or (eac_status == 0 and eac_error_code == 9) + self.assertTrue(self._rx(self._angle_meas_msg(0, hands_on_level=hands_on_level, eac_status=eac_status, + eac_error_code=eac_error_code))) + self.assertNotEqual(should_disengage, self.safety.get_controls_allowed()) + self.assertEqual(should_disengage, self.safety.get_steering_disengage_prev()) + + # Should not recover + self.assertTrue(self._rx(self._angle_meas_msg(0, hands_on_level=0, eac_status=1, eac_error_code=0))) + self.assertNotEqual(should_disengage, self.safety.get_controls_allowed()) + self.assertFalse(self.safety.get_steering_disengage_prev()) + + def test_autopark_summon_while_enabled(self): + # We should not respect Autopark that activates while controls are allowed + self._rx(self._pcm_status_msg(True, 0)) + + self._rx(self._pcm_status_msg(True, self.autopark_states["SELFPARK_STARTED"])) + self.assertTrue(self.safety.get_controls_allowed()) + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) + self.assertTrue(self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_CANCEL_GENERIC_SILENT"]))) + + # We should still not respect Autopark if we disengage cruise + self._rx(self._pcm_status_msg(False, self.autopark_states["SELFPARK_STARTED"])) + self.assertFalse(self.safety.get_controls_allowed()) + self.assertTrue(self._tx(self._angle_cmd_msg(0, False))) + self.assertTrue(self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_CANCEL_GENERIC_SILENT"]))) + + def test_autopark_summon_behavior(self): + for autopark_state in range(16): + self._rx(self._pcm_status_msg(False, 0)) + + # We shouldn't allow controls if Autopark is an active state + autopark_active = autopark_state in self.active_autopark_states + self._rx(self._pcm_status_msg(False, autopark_state)) + self._rx(self._pcm_status_msg(True, autopark_state)) + self.assertNotEqual(autopark_active, self.safety.get_controls_allowed()) + + # We should also start blocking all inactive/active openpilot msgs + self.assertNotEqual(autopark_active, self._tx(self._angle_cmd_msg(0, False))) + self.assertNotEqual(autopark_active, self._tx(self._angle_cmd_msg(0, True))) + self.assertNotEqual(autopark_active, self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_CANCEL_GENERIC_SILENT"]))) + self.assertNotEqual(autopark_active or not self.LONGITUDINAL, self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_ON"]))) + + # Regain controls when Autopark disables + self._rx(self._pcm_status_msg(True, 0)) + self.assertTrue(self.safety.get_controls_allowed()) + self.assertTrue(self._tx(self._angle_cmd_msg(0, False))) + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) + self.assertTrue(self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_CANCEL_GENERIC_SILENT"]))) + self.assertEqual(self.LONGITUDINAL, self._tx(self._long_control_msg(0, acc_state=self.acc_states["ACC_ON"]))) + + def test_steering_control_type(self): + # Only angle control is allowed (no LANE_KEEP_ASSIST or EMERGENCY_LANE_KEEP) + self.safety.set_controls_allowed(True) + for steer_control_type in range(4): + should_tx = steer_control_type in (self.steer_control_types["NONE"], + self.steer_control_types["ANGLE_CONTROL"]) + self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(0, state=steer_control_type))) + + def test_stock_lkas_passthrough(self): + # TODO: make these generic passthrough tests + no_lkas_msg = self._angle_cmd_msg(0, state=False) + no_lkas_msg_cam = self._angle_cmd_msg(0, state=True, bus=2) + lkas_msg_cam = self._angle_cmd_msg(0, state=self.steer_control_types['LANE_KEEP_ASSIST'], bus=2) + + # stock system sends no LKAS -> no forwarding, and OP is allowed to TX + self.assertEqual(1, self._rx(no_lkas_msg_cam)) + self.assertEqual(-1, self.safety.safety_fwd_hook(2, no_lkas_msg_cam.addr)) + self.assertTrue(self._tx(no_lkas_msg)) + + # stock system sends LKAS -> forwarding, and OP is not allowed to TX + self.assertEqual(1, self._rx(lkas_msg_cam)) + self.assertEqual(0, self.safety.safety_fwd_hook(2, lkas_msg_cam.addr)) + self.assertFalse(self._tx(no_lkas_msg)) + + def test_angle_cmd_when_enabled(self): + # We properly test lateral acceleration and jerk below + pass + + def test_lateral_accel_limit(self): + for speed in np.linspace(0, 40, 100): + speed = max(speed, 1) + # match DI_vehicleSpeed rounding on CAN + speed = round_speed(away_round(speed / 0.08 * 3.6) * 0.08 / 3.6) + for sign in (-1, 1): + self.safety.set_controls_allowed(True) + self._reset_speed_measurement(speed + 1) # safety fudges the speed + + # angle signal can't represent 0, so it biases one unit down + angle_unit_offset = -1 if sign == -1 else 0 + + # at limit (safety tolerance adds 1) + max_angle = round_angle(get_max_angle_vm(speed, self.VM, CarControllerParams), angle_unit_offset + 1) * sign + max_angle = np.clip(max_angle, -self.STEER_ANGLE_MAX, self.STEER_ANGLE_MAX) + self.safety.set_desired_angle_last(round(max_angle * self.DEG_TO_CAN)) + + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle, True))) + + # 1 unit above limit + max_angle_raw = round_angle(get_max_angle_vm(speed, self.VM, CarControllerParams), angle_unit_offset + 2) * sign + max_angle = np.clip(max_angle_raw, -self.STEER_ANGLE_MAX, self.STEER_ANGLE_MAX) + self._tx(self._angle_cmd_msg(max_angle, True)) + + # at low speeds max angle is above 360, so adding 1 has no effect + should_tx = abs(max_angle_raw) >= self.STEER_ANGLE_MAX + self.assertEqual(should_tx, self._tx(self._angle_cmd_msg(max_angle, True))) + + def test_lateral_jerk_limit(self): + for speed in np.linspace(0, 40, 100): + speed = max(speed, 1) + # match DI_vehicleSpeed rounding on CAN + speed = round_speed(away_round(speed / 0.08 * 3.6) * 0.08 / 3.6) + for sign in (-1, 1): # (-1, 1): + self.safety.set_controls_allowed(True) + self._reset_speed_measurement(speed + 1) # safety fudges the speed + self._tx(self._angle_cmd_msg(0, True)) + + # angle signal can't represent 0, so it biases one unit down + angle_unit_offset = 1 if sign == -1 else 0 + + # Stay within limits + # Up + max_angle_delta = round_angle(get_max_angle_delta_vm(speed, self.VM, CarControllerParams), angle_unit_offset) * sign + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Don't change + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Down + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) + + # Inject too high rates + # Up + max_angle_delta = round_angle(get_max_angle_delta_vm(speed, self.VM, CarControllerParams), angle_unit_offset + 1) * sign + self.assertFalse(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Don't change + self.safety.set_desired_angle_last(round(max_angle_delta * self.DEG_TO_CAN)) + self.assertTrue(self._tx(self._angle_cmd_msg(max_angle_delta, True))) + + # Down + self.assertFalse(self._tx(self._angle_cmd_msg(0, True))) + + # Recover + self.assertTrue(self._tx(self._angle_cmd_msg(0, True))) + + +class TestTeslaStockSafety(TestTeslaSafetyBase): + + LONGITUDINAL = False + + def setUp(self): + super().setUp() + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, 0) + self.safety.init_tests() + + def test_cancel(self): + for acc_state in range(16): + self.safety.set_controls_allowed(True) + should_tx = acc_state == self.acc_states["ACC_CANCEL_GENERIC_SILENT"] + self.assertFalse(self._tx(self._long_control_msg(0, acc_state=acc_state, accel_limits=(self.MIN_ACCEL, self.MAX_ACCEL)))) + self.assertEqual(should_tx, self._tx(self._long_control_msg(0, acc_state=acc_state))) + + def test_no_aeb(self): + for aeb_event in range(4): + should_tx = aeb_event == 0 + ret = self._tx(self._long_control_msg(10, acc_state=self.acc_states["ACC_CANCEL_GENERIC_SILENT"], aeb_event=aeb_event)) + self.assertEqual(ret, should_tx) + + def test_stock_aeb_no_cancel(self): + # No passthrough logic since we always forward DAS_control, + # but ensure we can't send cancel cmd while stock AEB is active + no_aeb_msg = self._long_control_msg(10, acc_state=self.acc_states["ACC_CANCEL_GENERIC_SILENT"], aeb_event=0) + no_aeb_msg_cam = self._long_control_msg(10, aeb_event=0, bus=2) + aeb_msg_cam = self._long_control_msg(10, aeb_event=1, bus=2) + + # stock system sends no AEB -> no forwarding, and OP is allowed to TX + self.assertEqual(1, self._rx(no_aeb_msg_cam)) + self.assertEqual(0, self.safety.safety_fwd_hook(2, no_aeb_msg_cam.addr)) + self.assertTrue(self._tx(no_aeb_msg)) + + # stock system sends AEB -> forwarding, and OP is not allowed to TX + self.assertEqual(1, self._rx(aeb_msg_cam)) + self.assertEqual(0, self.safety.safety_fwd_hook(2, aeb_msg_cam.addr)) + self.assertFalse(self._tx(no_aeb_msg)) + + +class TestTeslaLongitudinalSafety(TestTeslaSafetyBase): + RELAY_MALFUNCTION_ADDRS = {0: (MSG_DAS_steeringControl, MSG_APS_eacMonitor, MSG_DAS_Control)} + FWD_BLACKLISTED_ADDRS = {2: [MSG_DAS_steeringControl, MSG_APS_eacMonitor, MSG_DAS_Control]} + + def setUp(self): + super().setUp() + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.tesla, TeslaSafetyFlags.LONG_CONTROL) + self.safety.init_tests() + + def test_no_aeb(self): + for aeb_event in range(4): + self.assertEqual(self._tx(self._long_control_msg(10, aeb_event=aeb_event)), aeb_event == 0) + + def test_stock_aeb_passthrough(self): + no_aeb_msg = self._long_control_msg(10, aeb_event=0) + no_aeb_msg_cam = self._long_control_msg(10, aeb_event=0, bus=2) + aeb_msg_cam = self._long_control_msg(10, aeb_event=1, bus=2) + + # stock system sends no AEB -> no forwarding, and OP is allowed to TX + self.assertEqual(1, self._rx(no_aeb_msg_cam)) + self.assertEqual(-1, self.safety.safety_fwd_hook(2, no_aeb_msg_cam.addr)) + self.assertTrue(self._tx(no_aeb_msg)) + + # stock system sends AEB -> forwarding, and OP is not allowed to TX + self.assertEqual(1, self._rx(aeb_msg_cam)) + self.assertEqual(0, self.safety.safety_fwd_hook(2, aeb_msg_cam.addr)) + self.assertFalse(self._tx(no_aeb_msg)) + + def test_prevent_reverse(self): + # Note: Tesla can reverse while at a standstill if both accel_min and accel_max are negative. + self.safety.set_controls_allowed(True) + + # accel_min and accel_max are positive + self.assertTrue(self._tx(self._long_control_msg(set_speed=10, accel_limits=(1.1, 0.8)))) + self.assertTrue(self._tx(self._long_control_msg(set_speed=0, accel_limits=(1.1, 0.8)))) + + # accel_min and accel_max are both zero + self.assertTrue(self._tx(self._long_control_msg(set_speed=10, accel_limits=(0, 0)))) + self.assertTrue(self._tx(self._long_control_msg(set_speed=0, accel_limits=(0, 0)))) + + # accel_min and accel_max have opposing signs + self.assertTrue(self._tx(self._long_control_msg(set_speed=10, accel_limits=(-0.8, 1.3)))) + self.assertTrue(self._tx(self._long_control_msg(set_speed=0, accel_limits=(0.8, -1.3)))) + self.assertTrue(self._tx(self._long_control_msg(set_speed=0, accel_limits=(0, -1.3)))) + + # accel_min and accel_max are negative + self.assertFalse(self._tx(self._long_control_msg(set_speed=10, accel_limits=(-1.1, -0.6)))) + self.assertFalse(self._tx(self._long_control_msg(set_speed=0, accel_limits=(-0.6, -1.1)))) + self.assertFalse(self._tx(self._long_control_msg(set_speed=0, accel_limits=(-0.1, -0.1)))) + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_toyota.py b/opendbc_repo/opendbc/safety/tests/test_toyota.py new file mode 100755 index 0000000000..e38379d046 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_toyota.py @@ -0,0 +1,347 @@ +#!/usr/bin/env python3 +import numpy as np +import random +import unittest +import itertools + +from opendbc.car.toyota.values import ToyotaSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + +TOYOTA_COMMON_TX_MSGS = [[0x2E4, 0], [0x191, 0], [0x412, 0], [0x343, 0], [0x1D2, 0]] # LKAS + LTA + ACC & PCM cancel cmds +TOYOTA_SECOC_TX_MSGS = [[0x131, 0]] + TOYOTA_COMMON_TX_MSGS +TOYOTA_COMMON_LONG_TX_MSGS = [[0x283, 0], [0x2E6, 0], [0x2E7, 0], [0x33E, 0], [0x344, 0], [0x365, 0], [0x366, 0], [0x4CB, 0], # DSU bus 0 + [0x128, 1], [0x141, 1], [0x160, 1], [0x161, 1], [0x470, 1], # DSU bus 1 + [0x411, 0], # PCS_HUD + [0x750, 0]] # radar diagnostic address + + +class TestToyotaSafetyBase(common.CarSafetyTest, common.LongitudinalAccelSafetyTest): + + TX_MSGS = TOYOTA_COMMON_TX_MSGS + TOYOTA_COMMON_LONG_TX_MSGS + RELAY_MALFUNCTION_ADDRS = {0: (0x2E4, 0x191, 0x412, 0x343)} + FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x412, 0x191, 0x343]} + EPS_SCALE = 73 + + packer: CANPackerSafety + safety: libsafety_py.LibSafety + + def _torque_meas_msg(self, torque: int, driver_torque: int | None = None): + values = {"STEER_TORQUE_EPS": (torque / self.EPS_SCALE) * 100.} + if driver_torque is not None: + values["STEER_TORQUE_DRIVER"] = driver_torque + return self.packer.make_can_msg_safety("STEER_TORQUE_SENSOR", 0, values) + + # Both torque and angle safety modes test with each other's steering commands + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"STEER_TORQUE_CMD": torque, "STEER_REQUEST": steer_req} + return self.packer.make_can_msg_safety("STEERING_LKA", 0, values) + + def _angle_meas_msg(self, angle: float, steer_angle_initializing: bool = False): + # This creates a steering torque angle message. Not set on all platforms, + # relative to init angle on some older TSS2 platforms. Only to be used with LTA + values = {"STEER_ANGLE": angle, "STEER_ANGLE_INITIALIZING": int(steer_angle_initializing)} + return self.packer.make_can_msg_safety("STEER_TORQUE_SENSOR", 0, values) + + def _angle_cmd_msg(self, angle: float, enabled: bool): + return self._lta_msg(int(enabled), int(enabled), angle, torque_wind_down=100 if enabled else 0) + + def _lta_msg(self, req, req2, angle_cmd, torque_wind_down=100): + values = {"STEER_REQUEST": req, "STEER_REQUEST_2": req2, "STEER_ANGLE_CMD": angle_cmd, "TORQUE_WIND_DOWN": torque_wind_down} + return self.packer.make_can_msg_safety("STEERING_LTA", 0, values) + + def _accel_msg(self, accel, cancel_req=0): + values = {"ACCEL_CMD": accel, "CANCEL_REQ": cancel_req} + return self.packer.make_can_msg_safety("ACC_CONTROL", 0, values) + + def _speed_msg(self, speed): + values = {("WHEEL_SPEED_%s" % n): speed * 3.6 for n in ["FR", "FL", "RR", "RL"]} + return self.packer.make_can_msg_safety("WHEEL_SPEEDS", 0, values) + + def _user_brake_msg(self, brake): + values = {"BRAKE_PRESSED": brake} + return self.packer.make_can_msg_safety("BRAKE_MODULE", 0, values) + + def _user_gas_msg(self, gas): + cruise_active = self.safety.get_controls_allowed() + values = {"GAS_RELEASED": not gas, "CRUISE_ACTIVE": cruise_active} + return self.packer.make_can_msg_safety("PCM_CRUISE", 0, values) + + def _pcm_status_msg(self, enable): + values = {"CRUISE_ACTIVE": enable} + return self.packer.make_can_msg_safety("PCM_CRUISE", 0, values) + + def test_diagnostics(self, stock_longitudinal: bool = False): + for should_tx, msg in ((False, b"\x6D\x02\x3E\x00\x00\x00\x00\x00"), # fwdCamera tester present + (False, b"\x0F\x03\xAA\xAA\x00\x00\x00\x00"), # non-tester present + (True, b"\x0F\x02\x3E\x00\x00\x00\x00\x00")): + tester_present = libsafety_py.make_CANPacket(0x750, 0, msg) + self.assertEqual(should_tx and not stock_longitudinal, self._tx(tester_present)) + + def test_block_aeb(self, stock_longitudinal: bool = False): + for controls_allowed in (True, False): + for bad in (True, False): + for _ in range(10): + self.safety.set_controls_allowed(controls_allowed) + dat = [random.randint(1, 255) for _ in range(7)] + if not bad: + dat = [0]*6 + dat[-1:] + msg = libsafety_py.make_CANPacket(0x283, 0, bytes(dat)) + self.assertEqual(not bad and not stock_longitudinal, self._tx(msg)) + + # Only allow LTA msgs with no actuation + def test_lta_steer_cmd(self): + for engaged, req, req2, torque_wind_down, angle in itertools.product([True, False], + [0, 1], [0, 1], + [0, 50, 100], + np.linspace(-20, 20, 5)): + self.safety.set_controls_allowed(engaged) + + should_tx = not req and not req2 and angle == 0 and torque_wind_down == 0 + self.assertEqual(should_tx, self._tx(self._lta_msg(req, req2, angle, torque_wind_down)), + f"{req=} {req2=} {angle=} {torque_wind_down=}") + + def test_rx_hook(self): + # checksum checks + for msg in ["trq", "pcm"]: + self.safety.set_controls_allowed(1) + if msg == "trq": + msg = self._torque_meas_msg(0) + if msg == "pcm": + msg = self._pcm_status_msg(True) + self.assertTrue(self._rx(msg)) + msg[0].data[4] = 0 + msg[0].data[5] = 0 + msg[0].data[6] = 0 + msg[0].data[7] = 0 + self.assertFalse(self._rx(msg)) + self.assertFalse(self.safety.get_controls_allowed()) + + +class TestToyotaSafetyTorque(TestToyotaSafetyBase, common.MotorTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): + + MAX_RATE_UP = 15 + MAX_RATE_DOWN = 25 + MAX_TORQUE_LOOKUP = [0], [1500] + MAX_RT_DELTA = 450 + MAX_TORQUE_ERROR = 350 + TORQUE_MEAS_TOLERANCE = 1 # toyota safety adds one to be conservative for rounding + + # Safety around steering req bit + MIN_VALID_STEERING_FRAMES = 18 + MAX_INVALID_STEERING_FRAMES = 1 + + def setUp(self): + self.packer = CANPackerSafety("toyota_nodsu_pt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE) + self.safety.init_tests() + + +class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest): + + # Angle control limits + STEER_ANGLE_MAX = 94.9461 # deg + DEG_TO_CAN = 17.452007 # 1 / 0.0573 deg to can + + ANGLE_RATE_BP = [5., 25., 25.] + ANGLE_RATE_UP = [0.3, 0.15, 0.15] # windup limit + ANGLE_RATE_DOWN = [0.36, 0.26, 0.26] # unwind limit + + MAX_LTA_ANGLE = 94.9461 # PCS faults if commanding above this, deg + MAX_MEAS_TORQUE = 1500 # max allowed measured EPS torque before wind down + MAX_LTA_DRIVER_TORQUE = 150 # max allowed driver torque before wind down + + def setUp(self): + self.packer = CANPackerSafety("toyota_nodsu_pt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.LTA) + self.safety.init_tests() + + # Only allow LKA msgs with no actuation + def test_lka_steer_cmd(self): + for engaged, steer_req, torque in itertools.product([True, False], + [0, 1], + np.linspace(-1500, 1500, 7)): + self.safety.set_controls_allowed(engaged) + torque = int(torque) + self.safety.set_rt_torque_last(torque) + self.safety.set_torque_meas(torque, torque) + self.safety.set_desired_torque_last(torque) + + should_tx = not steer_req and torque == 0 + self.assertEqual(should_tx, self._tx(self._torque_cmd_msg(torque, steer_req))) + + def test_lta_steer_cmd(self): + """ + Tests the LTA steering command message + controls_allowed: + * STEER_REQUEST and STEER_REQUEST_2 do not mismatch + * TORQUE_WIND_DOWN is only set to 0 or 100 when STEER_REQUEST and STEER_REQUEST_2 are both 1 + * Full torque messages are blocked if either EPS torque or driver torque is above the threshold + + not controls_allowed: + * STEER_REQUEST, STEER_REQUEST_2, and TORQUE_WIND_DOWN are all 0 + """ + for controls_allowed in (True, False): + for angle in np.arange(-90, 90, 1): + self.safety.set_controls_allowed(controls_allowed) + self._reset_angle_measurement(angle) + self._set_prev_desired_angle(angle) + + self.assertTrue(self._tx(self._lta_msg(0, 0, angle, 0))) + if controls_allowed: + # Test the two steer request bits and TORQUE_WIND_DOWN torque wind down signal + for req, req2, torque_wind_down in itertools.product([0, 1], [0, 1], [0, 50, 100]): + mismatch = not (req or req2) and torque_wind_down != 0 + should_tx = req == req2 and (torque_wind_down in (0, 100)) and not mismatch + self.assertEqual(should_tx, self._tx(self._lta_msg(req, req2, angle, torque_wind_down))) + + # Test max EPS torque and driver override thresholds + cases = itertools.product( + (0, self.MAX_MEAS_TORQUE - 1, self.MAX_MEAS_TORQUE, self.MAX_MEAS_TORQUE + 1, self.MAX_MEAS_TORQUE * 2), + (0, self.MAX_LTA_DRIVER_TORQUE - 1, self.MAX_LTA_DRIVER_TORQUE, self.MAX_LTA_DRIVER_TORQUE + 1, self.MAX_LTA_DRIVER_TORQUE * 2) + ) + + for eps_torque, driver_torque in cases: + for sign in (-1, 1): + for _ in range(6): + self._rx(self._torque_meas_msg(sign * eps_torque, sign * driver_torque)) + + # Toyota adds 1 to EPS torque since it is rounded after EPS factor + should_tx = (eps_torque - 1) <= self.MAX_MEAS_TORQUE and driver_torque <= self.MAX_LTA_DRIVER_TORQUE + self.assertEqual(should_tx, self._tx(self._lta_msg(1, 1, angle, 100))) + self.assertTrue(self._tx(self._lta_msg(1, 1, angle, 0))) # should tx if we wind down torque + + else: + # Controls not allowed + for req, req2, torque_wind_down in itertools.product([0, 1], [0, 1], [0, 50, 100]): + should_tx = not (req or req2) and torque_wind_down == 0 + self.assertEqual(should_tx, self._tx(self._lta_msg(req, req2, angle, torque_wind_down))) + + def test_angle_measurements(self): + """ + * Tests angle meas quality flag dictates whether angle measurement is parsed, and if rx is valid + * Tests rx hook correctly clips the angle measurement, since it is to be compared to LTA cmd when inactive + """ + for steer_angle_initializing in (True, False): + for angle in np.arange(0, self.STEER_ANGLE_MAX * 2, 1): + # If init flag is set, do not rx or parse any angle measurements + for a in (angle, -angle, 0, 0, 0, 0): + self.assertEqual(not steer_angle_initializing, + self._rx(self._angle_meas_msg(a, steer_angle_initializing))) + + final_angle = 0 if steer_angle_initializing else round(angle * self.DEG_TO_CAN) + self.assertEqual(self.safety.get_angle_meas_min(), -final_angle) + self.assertEqual(self.safety.get_angle_meas_max(), final_angle) + + self._rx(self._angle_meas_msg(0)) + self.assertEqual(self.safety.get_angle_meas_min(), -final_angle) + self.assertEqual(self.safety.get_angle_meas_max(), 0) + + self._rx(self._angle_meas_msg(0)) + self.assertEqual(self.safety.get_angle_meas_min(), 0) + self.assertEqual(self.safety.get_angle_meas_max(), 0) + + +class TestToyotaAltBrakeSafety(TestToyotaSafetyTorque): + + def setUp(self): + self.packer = CANPackerSafety("toyota_new_mc_pt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.ALT_BRAKE) + self.safety.init_tests() + + def _user_brake_msg(self, brake): + values = {"BRAKE_PRESSED": brake} + return self.packer.make_can_msg_safety("BRAKE_MODULE", 0, values) + + # No LTA message in the DBC + def test_lta_steer_cmd(self): + pass + + +class TestToyotaStockLongitudinalBase(TestToyotaSafetyBase): + + TX_MSGS = TOYOTA_COMMON_TX_MSGS + # Base addresses minus ACC_CONTROL (0x343) + RELAY_MALFUNCTION_ADDRS = {0: (0x2E4, 0x191, 0x412)} + FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x412, 0x191]} + + LONGITUDINAL = False + + def test_diagnostics(self, stock_longitudinal: bool = True): + super().test_diagnostics(stock_longitudinal=stock_longitudinal) + + def test_block_aeb(self, stock_longitudinal: bool = True): + super().test_block_aeb(stock_longitudinal=stock_longitudinal) + + def test_acc_cancel(self): + """ + Regardless of controls allowed, never allow ACC_CONTROL if cancel bit isn't set + """ + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + for accel in np.arange(self.MIN_ACCEL - 1, self.MAX_ACCEL + 1, 0.1): + self.assertFalse(self._tx(self._accel_msg(accel))) + should_tx = np.isclose(accel, 0, atol=0.0001) + self.assertEqual(should_tx, self._tx(self._accel_msg(accel, cancel_req=1))) + + +class TestToyotaStockLongitudinalTorque(TestToyotaStockLongitudinalBase, TestToyotaSafetyTorque): + + def setUp(self): + self.packer = CANPackerSafety("toyota_nodsu_pt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL) + self.safety.init_tests() + + +class TestToyotaStockLongitudinalAngle(TestToyotaStockLongitudinalBase, TestToyotaSafetyAngle): + + def setUp(self): + self.packer = CANPackerSafety("toyota_nodsu_pt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, + self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.LTA) + self.safety.init_tests() + + +class TestToyotaSecOcSafety(TestToyotaStockLongitudinalBase): + + TX_MSGS = TOYOTA_SECOC_TX_MSGS + RELAY_MALFUNCTION_ADDRS = {0: (0x2E4, 0x191, 0x412, 0x131)} + FWD_BLACKLISTED_ADDRS = {2: [0x2E4, 0x191, 0x412, 0x131]} + + def setUp(self): + self.packer = CANPackerSafety("toyota_secoc_pt_generated") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.toyota, + self.EPS_SCALE | ToyotaSafetyFlags.STOCK_LONGITUDINAL | ToyotaSafetyFlags.SECOC) + self.safety.init_tests() + + # This platform also has alternate brake and PCM messages, but same naming in the DBC, so same packers work + + def _user_gas_msg(self, gas): + values = {"GAS_PEDAL_USER": gas} + return self.packer.make_can_msg_safety("GAS_PEDAL", 0, values) + + # This platform sends both STEERING_LTA (same as other Toyota) and STEERING_LTA_2 (SecOC signed) + # STEERING_LTA is checked for no-actuation by the base class, STEERING_LTA_2 is checked for no-actuation below + + def _lta_2_msg(self, req, req2, angle_cmd, torque_wind_down=100): + values = {"STEER_REQUEST": req, "STEER_REQUEST_2": req2, "STEER_ANGLE_CMD": angle_cmd} + return self.packer.make_can_msg_safety("STEERING_LTA_2", 0, values) + + def test_lta_2_steer_cmd(self): + for engaged, req, req2, angle in itertools.product([True, False], [0, 1], [0, 1], np.linspace(-20, 20, 5)): + self.safety.set_controls_allowed(engaged) + + should_tx = not req and not req2 and angle == 0 + self.assertEqual(should_tx, self._tx(self._lta_2_msg(req, req2, angle)), f"{req=} {req2=} {angle=}") + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py b/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py new file mode 100755 index 0000000000..47f77a8d09 --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_volkswagen_mqb.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 +import unittest +import numpy as np +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety +from opendbc.car.volkswagen.values import VolkswagenSafetyFlags + +MAX_ACCEL = 2.0 +MIN_ACCEL = -3.5 + +MSG_ESP_19 = 0xB2 # RX from ABS, for wheel speeds +MSG_LH_EPS_03 = 0x9F # RX from EPS, for driver steering torque +MSG_ESP_05 = 0x106 # RX from ABS, for brake light state +MSG_TSK_06 = 0x120 # RX from ECU, for ACC status from drivetrain coordinator +MSG_MOTOR_20 = 0x121 # RX from ECU, for driver throttle input +MSG_ACC_06 = 0x122 # TX by OP, ACC control instructions to the drivetrain coordinator +MSG_HCA_01 = 0x126 # TX by OP, Heading Control Assist steering torque +MSG_GRA_ACC_01 = 0x12B # TX by OP, ACC control buttons for cancel/resume +MSG_ACC_07 = 0x12E # TX by OP, ACC control instructions to the drivetrain coordinator +MSG_ACC_02 = 0x30C # TX by OP, ACC HUD data to the instrument cluster +MSG_LDW_02 = 0x397 # TX by OP, Lane line recognition and text alerts + + +class TestVolkswagenMqbSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_01, MSG_LDW_02), 2: (MSG_LH_EPS_03,)} + + MAX_RATE_UP = 4 + MAX_RATE_DOWN = 10 + MAX_TORQUE_LOOKUP = [0], [300] + MAX_RT_DELTA = 75 + + DRIVER_TORQUE_ALLOWANCE = 80 + DRIVER_TORQUE_FACTOR = 3 + + # Wheel speeds _esp_19_msg + def _speed_msg(self, speed): + values = {"ESP_%s_Radgeschw_02" % s: speed for s in ["HL", "HR", "VL", "VR"]} + return self.packer.make_can_msg_safety("ESP_19", 0, values) + + # Driver brake pressure over threshold + def _esp_05_msg(self, brake): + values = {"ESP_Fahrer_bremst": brake} + return self.packer.make_can_msg_safety("ESP_05", 0, values) + + # Brake pedal switch + def _motor_14_msg(self, brake): + values = {"MO_Fahrer_bremst": brake} + return self.packer.make_can_msg_safety("Motor_14", 0, values) + + def _user_brake_msg(self, brake): + return self._motor_14_msg(brake) + + # Driver throttle input + def _user_gas_msg(self, gas): + values = {"MO_Fahrpedalrohwert_01": gas} + return self.packer.make_can_msg_safety("Motor_20", 0, values) + + # ACC engagement status + def _tsk_status_msg(self, enable, main_switch=True): + if main_switch: + tsk_status = 3 if enable else 2 + else: + tsk_status = 0 + values = {"TSK_Status": tsk_status} + return self.packer.make_can_msg_safety("TSK_06", 0, values) + + def _pcm_status_msg(self, enable): + return self._tsk_status_msg(enable) + + # Driver steering input torque + def _torque_driver_msg(self, torque): + values = {"EPS_Lenkmoment": abs(torque), "EPS_VZ_Lenkmoment": torque < 0} + return self.packer.make_can_msg_safety("LH_EPS_03", 0, values) + + # openpilot steering output torque + def _torque_cmd_msg(self, torque, steer_req=1): + values = {"HCA_01_LM_Offset": abs(torque), "HCA_01_LM_OffSign": torque < 0, "HCA_01_Sendestatus": steer_req} + return self.packer.make_can_msg_safety("HCA_01", 0, values) + + # Cruise control buttons + def _gra_acc_01_msg(self, cancel=0, resume=0, _set=0, bus=2): + values = {"GRA_Abbrechen": cancel, "GRA_Tip_Setzen": _set, "GRA_Tip_Wiederaufnahme": resume} + return self.packer.make_can_msg_safety("GRA_ACC_01", bus, values) + + # Acceleration request to drivetrain coordinator + def _acc_06_msg(self, accel): + values = {"ACC_Sollbeschleunigung_02": accel} + return self.packer.make_can_msg_safety("ACC_06", 0, values) + + # Acceleration request to drivetrain coordinator + def _acc_07_msg(self, accel, secondary_accel=3.02): + values = {"ACC_Sollbeschleunigung_02": accel, "ACC_Folgebeschl": secondary_accel} + return self.packer.make_can_msg_safety("ACC_07", 0, values) + + # Verify brake_pressed is true if either the switch or pressure threshold signals are true + def test_redundant_brake_signals(self): + test_combinations = [(True, True, True), (True, True, False), (True, False, True), (False, False, False)] + for brake_pressed, motor_14_signal, esp_05_signal in test_combinations: + self._rx(self._motor_14_msg(False)) + self._rx(self._esp_05_msg(False)) + self.assertFalse(self.safety.get_brake_pressed_prev()) + self._rx(self._motor_14_msg(motor_14_signal)) + self._rx(self._esp_05_msg(esp_05_signal)) + self.assertEqual(brake_pressed, self.safety.get_brake_pressed_prev(), + f"expected {brake_pressed=} with {motor_14_signal=} and {esp_05_signal=}") + + def test_torque_measurements(self): + # TODO: make this test work with all cars + self._rx(self._torque_driver_msg(50)) + self._rx(self._torque_driver_msg(-50)) + self._rx(self._torque_driver_msg(0)) + self._rx(self._torque_driver_msg(0)) + self._rx(self._torque_driver_msg(0)) + self._rx(self._torque_driver_msg(0)) + + self.assertEqual(-50, self.safety.get_torque_driver_min()) + self.assertEqual(50, self.safety.get_torque_driver_max()) + + self._rx(self._torque_driver_msg(0)) + self.assertEqual(0, self.safety.get_torque_driver_max()) + self.assertEqual(-50, self.safety.get_torque_driver_min()) + + self._rx(self._torque_driver_msg(0)) + self.assertEqual(0, self.safety.get_torque_driver_max()) + self.assertEqual(0, self.safety.get_torque_driver_min()) + + +class TestVolkswagenMqbStockSafety(TestVolkswagenMqbSafetyBase): + TX_MSGS = [[MSG_HCA_01, 0], [MSG_LDW_02, 0], [MSG_LH_EPS_03, 2], [MSG_GRA_ACC_01, 0], [MSG_GRA_ACC_01, 2]] + FWD_BLACKLISTED_ADDRS = {0: [MSG_LH_EPS_03], 2: [MSG_HCA_01, MSG_LDW_02]} + + def setUp(self): + self.packer = CANPackerSafety("vw_mqb") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagen, 0) + self.safety.init_tests() + + def test_spam_cancel_safety_check(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(self._gra_acc_01_msg(cancel=1))) + self.assertFalse(self._tx(self._gra_acc_01_msg(resume=1))) + self.assertFalse(self._tx(self._gra_acc_01_msg(_set=1))) + # do not block resume if we are engaged already + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(self._gra_acc_01_msg(resume=1))) + + +class TestVolkswagenMqbLongSafety(TestVolkswagenMqbSafetyBase): + TX_MSGS = [[MSG_HCA_01, 0], [MSG_LDW_02, 0], [MSG_LH_EPS_03, 2], [MSG_ACC_02, 0], [MSG_ACC_06, 0], [MSG_ACC_07, 0]] + FWD_BLACKLISTED_ADDRS = {0: [MSG_LH_EPS_03], 2: [MSG_HCA_01, MSG_LDW_02, MSG_ACC_02, MSG_ACC_06, MSG_ACC_07]} + RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_01, MSG_LDW_02, MSG_ACC_02, MSG_ACC_06, MSG_ACC_07), 2: (MSG_LH_EPS_03,)} + INACTIVE_ACCEL = 3.01 + + def setUp(self): + self.packer = CANPackerSafety("vw_mqb") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagen, VolkswagenSafetyFlags.LONG_CONTROL) + self.safety.init_tests() + + # stock cruise controls are entirely bypassed under openpilot longitudinal control + def test_disable_control_allowed_from_cruise(self): + pass + + def test_enable_control_allowed_from_cruise(self): + pass + + def test_cruise_engaged_prev(self): + pass + + def test_set_and_resume_buttons(self): + for button in ["set", "resume"]: + # ACC main switch must be on, engage on falling edge + self.safety.set_controls_allowed(0) + self._rx(self._tsk_status_msg(False, main_switch=False)) + self._rx(self._gra_acc_01_msg(_set=(button == "set"), resume=(button == "resume"), bus=0)) + self.assertFalse(self.safety.get_controls_allowed(), f"controls allowed on {button} with main switch off") + self._rx(self._tsk_status_msg(False, main_switch=True)) + self._rx(self._gra_acc_01_msg(_set=(button == "set"), resume=(button == "resume"), bus=0)) + self.assertFalse(self.safety.get_controls_allowed(), f"controls allowed on {button} rising edge") + self._rx(self._gra_acc_01_msg(bus=0)) + self.assertTrue(self.safety.get_controls_allowed(), f"controls not allowed on {button} falling edge") + + def test_cancel_button(self): + # Disable on rising edge of cancel button + self._rx(self._tsk_status_msg(False, main_switch=True)) + self.safety.set_controls_allowed(1) + self._rx(self._gra_acc_01_msg(cancel=True, bus=0)) + self.assertFalse(self.safety.get_controls_allowed(), "controls allowed after cancel") + + def test_main_switch(self): + # Disable as soon as main switch turns off + self._rx(self._tsk_status_msg(False, main_switch=True)) + self.safety.set_controls_allowed(1) + self._rx(self._tsk_status_msg(False, main_switch=False)) + self.assertFalse(self.safety.get_controls_allowed(), "controls allowed after ACC main switch off") + + def test_accel_safety_check(self): + for controls_allowed in [True, False]: + # enforce we don't skip over 0 or inactive accel + for accel in np.concatenate((np.arange(MIN_ACCEL - 2, MAX_ACCEL + 2, 0.03), [0, self.INACTIVE_ACCEL])): + accel = round(accel, 2) # floats might not hit exact boundary conditions without rounding + is_inactive_accel = accel == self.INACTIVE_ACCEL + send = (controls_allowed and MIN_ACCEL <= accel <= MAX_ACCEL) or is_inactive_accel + self.safety.set_controls_allowed(controls_allowed) + # primary accel request used by ECU + self.assertEqual(send, self._tx(self._acc_06_msg(accel)), (controls_allowed, accel)) + # additional accel request used by ABS/ESP + self.assertEqual(send, self._tx(self._acc_07_msg(accel)), (controls_allowed, accel)) + # ensure the optional secondary accel field remains inactive for now + self.assertEqual(is_inactive_accel, self._tx(self._acc_07_msg(accel, secondary_accel=accel)), (controls_allowed, accel)) + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py b/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py new file mode 100755 index 0000000000..d19e389aaa --- /dev/null +++ b/opendbc_repo/opendbc/safety/tests/test_volkswagen_pq.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +import unittest + +from opendbc.car.volkswagen.values import VolkswagenSafetyFlags +from opendbc.car.structs import CarParams +from opendbc.safety.tests.libsafety import libsafety_py +import opendbc.safety.tests.common as common +from opendbc.safety.tests.common import CANPackerSafety + +MSG_LENKHILFE_3 = 0x0D0 # RX from EPS, for steering angle and driver steering torque +MSG_HCA_1 = 0x0D2 # TX by OP, Heading Control Assist steering torque +MSG_BREMSE_1 = 0x1A0 # RX from ABS, for ego speed +MSG_MOTOR_2 = 0x288 # RX from ECU, for CC state and brake switch state +MSG_ACC_SYSTEM = 0x368 # TX by OP, longitudinal acceleration controls +MSG_MOTOR_3 = 0x380 # RX from ECU, for driver throttle input +MSG_GRA_NEU = 0x38A # TX by OP, ACC control buttons for cancel/resume +MSG_MOTOR_5 = 0x480 # RX from ECU, for ACC main switch state +MSG_ACC_GRA_ANZEIGE = 0x56A # TX by OP, ACC HUD +MSG_LDW_1 = 0x5BE # TX by OP, Lane line recognition and text alerts + + +class TestVolkswagenPqSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest): + cruise_engaged = False + + RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_1, MSG_LDW_1)} + + MAX_RATE_UP = 6 + MAX_RATE_DOWN = 10 + MAX_TORQUE_LOOKUP = [0], [300] + MAX_RT_DELTA = 113 + + DRIVER_TORQUE_ALLOWANCE = 80 + DRIVER_TORQUE_FACTOR = 3 + + def _set_prev_torque(self, t): + self.safety.set_desired_torque_last(t) + self.safety.set_rt_torque_last(t) + + # Ego speed (Bremse_1) + def _speed_msg(self, speed): + values = {"BR1_Rad_kmh": speed} + return self.packer.make_can_msg_safety("Bremse_1", 0, values) + + # Brake light switch (shared message Motor_2) + def _user_brake_msg(self, brake): + # since this signal is used for engagement status, preserve current state + return self._motor_2_msg(brake_pressed=brake, cruise_engaged=self.safety.get_controls_allowed()) + + # ACC engaged status (shared message Motor_2) + def _pcm_status_msg(self, enable): + self.__class__.cruise_engaged = enable + return self._motor_2_msg(cruise_engaged=enable) + + # Acceleration request to drivetrain coordinator + def _accel_msg(self, accel): + values = {"ACS_Sollbeschl": accel} + return self.packer.make_can_msg_safety("ACC_System", 0, values) + + # Driver steering input torque + def _torque_driver_msg(self, torque): + values = {"LH3_LM": abs(torque), "LH3_LMSign": torque < 0} + return self.packer.make_can_msg_safety("Lenkhilfe_3", 0, values) + + # openpilot steering output torque + def _torque_cmd_msg(self, torque, steer_req=1, hca_status=5): + values = {"LM_Offset": abs(torque), "LM_OffSign": torque < 0, "HCA_Status": hca_status if steer_req else 3} + return self.packer.make_can_msg_safety("HCA_1", 0, values) + + # ACC engagement and brake light switch status + # Called indirectly for compatibility with common.py tests + def _motor_2_msg(self, brake_pressed=False, cruise_engaged=False): + values = {"MO2_BLS": brake_pressed, + "MO2_Sta_GRA": cruise_engaged} + return self.packer.make_can_msg_safety("Motor_2", 0, values) + + # ACC main switch status + def _motor_5_msg(self, main_switch=False): + values = {"GRA_Hauptschalter": main_switch} + return self.packer.make_can_msg_safety("Motor_5", 0, values) + + # Driver throttle input (Motor_3) + def _user_gas_msg(self, gas): + values = {"Fahrpedal_Rohsignal": gas} + return self.packer.make_can_msg_safety("Motor_3", 0, values) + + # Cruise control buttons (GRA_Neu) + def _button_msg(self, _set=False, resume=False, cancel=False, bus=2): + values = {"GRA_Neu_Setzen": _set, "GRA_Recall": resume, "GRA_Abbrechen": cancel} + return self.packer.make_can_msg_safety("GRA_Neu", bus, values) + + def test_torque_measurements(self): + # TODO: make this test work with all cars + self._rx(self._torque_driver_msg(50)) + self._rx(self._torque_driver_msg(-50)) + self._rx(self._torque_driver_msg(0)) + self._rx(self._torque_driver_msg(0)) + self._rx(self._torque_driver_msg(0)) + self._rx(self._torque_driver_msg(0)) + + self.assertEqual(-50, self.safety.get_torque_driver_min()) + self.assertEqual(50, self.safety.get_torque_driver_max()) + + self._rx(self._torque_driver_msg(0)) + self.assertEqual(0, self.safety.get_torque_driver_max()) + self.assertEqual(-50, self.safety.get_torque_driver_min()) + + self._rx(self._torque_driver_msg(0)) + self.assertEqual(0, self.safety.get_torque_driver_max()) + self.assertEqual(0, self.safety.get_torque_driver_min()) + + +class TestVolkswagenPqStockSafety(TestVolkswagenPqSafetyBase): + # Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration + TX_MSGS = [[MSG_HCA_1, 0], [MSG_GRA_NEU, 0], [MSG_GRA_NEU, 2], [MSG_LDW_1, 0]] + FWD_BLACKLISTED_ADDRS = {2: [MSG_HCA_1, MSG_LDW_1]} + + def setUp(self): + self.packer = CANPackerSafety("vw_pq") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenPq, 0) + self.safety.init_tests() + + def test_spam_cancel_safety_check(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(self._button_msg(cancel=True))) + self.assertFalse(self._tx(self._button_msg(resume=True))) + self.assertFalse(self._tx(self._button_msg(_set=True))) + # do not block resume if we are engaged already + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(self._button_msg(resume=True))) + + +class TestVolkswagenPqLongSafety(TestVolkswagenPqSafetyBase, common.LongitudinalAccelSafetyTest): + TX_MSGS = [[MSG_HCA_1, 0], [MSG_LDW_1, 0], [MSG_ACC_SYSTEM, 0], [MSG_ACC_GRA_ANZEIGE, 0]] + FWD_BLACKLISTED_ADDRS = {2: [MSG_HCA_1, MSG_LDW_1, MSG_ACC_SYSTEM, MSG_ACC_GRA_ANZEIGE]} + RELAY_MALFUNCTION_ADDRS = {0: (MSG_HCA_1, MSG_LDW_1, MSG_ACC_SYSTEM, MSG_ACC_GRA_ANZEIGE)} + INACTIVE_ACCEL = 3.01 + + def setUp(self): + self.packer = CANPackerSafety("vw_pq") + self.safety = libsafety_py.libsafety + self.safety.set_safety_hooks(CarParams.SafetyModel.volkswagenPq, VolkswagenSafetyFlags.LONG_CONTROL) + self.safety.init_tests() + + # stock cruise controls are entirely bypassed under openpilot longitudinal control + def test_disable_control_allowed_from_cruise(self): + pass + + def test_enable_control_allowed_from_cruise(self): + pass + + def test_cruise_engaged_prev(self): + pass + + def test_set_and_resume_buttons(self): + for button in ["set", "resume"]: + # ACC main switch must be on, engage on falling edge + self.safety.set_controls_allowed(0) + self._rx(self._motor_5_msg(main_switch=False)) + self._rx(self._button_msg(_set=(button == "set"), resume=(button == "resume"), bus=0)) + self._rx(self._button_msg(bus=0)) + self.assertFalse(self.safety.get_controls_allowed(), f"controls allowed on {button} with main switch off") + self._rx(self._motor_5_msg(main_switch=True)) + self._rx(self._button_msg(_set=(button == "set"), resume=(button == "resume"), bus=0)) + self.assertFalse(self.safety.get_controls_allowed(), f"controls allowed on {button} rising edge") + self._rx(self._button_msg(bus=0)) + self.assertTrue(self.safety.get_controls_allowed(), f"controls not allowed on {button} falling edge") + + def test_cancel_button(self): + # Disable on rising edge of cancel button + self._rx(self._motor_5_msg(main_switch=True)) + self.safety.set_controls_allowed(1) + self._rx(self._button_msg(cancel=True, bus=0)) + self.assertFalse(self.safety.get_controls_allowed(), "controls allowed after cancel") + + def test_main_switch(self): + # Disable as soon as main switch turns off + self._rx(self._motor_5_msg(main_switch=True)) + self.safety.set_controls_allowed(1) + self._rx(self._motor_5_msg(main_switch=False)) + self.assertFalse(self.safety.get_controls_allowed(), "controls allowed after ACC main switch off") + + def test_torque_cmd_enable_variants(self): + # The EPS rack accepts either 5 or 7 for an enabled status, with different low speed tuning behavior + self.safety.set_controls_allowed(1) + for enabled_status in (5, 7): + self.assertTrue(self._tx(self._torque_cmd_msg(self.MAX_RATE_UP, steer_req=1, hca_status=enabled_status)), + f"torque cmd rejected with {enabled_status=}") + + +if __name__ == "__main__": + unittest.main() diff --git a/opendbc_repo/pyproject.toml b/opendbc_repo/pyproject.toml new file mode 100644 index 0000000000..393fcb696c --- /dev/null +++ b/opendbc_repo/pyproject.toml @@ -0,0 +1,132 @@ +[project] +name = "opendbc" +version = "0.2.1" +description = "CAN bus databases and tools" +license = { file = "LICENSE" } +authors = [{ name = "Vehicle Researcher", email = "user@comma.ai" }] +readme = "README.md" +requires-python = ">=3.9,<3.13" # pycapnp doesn't work with 3.13 + +urls = { "homepage" = "https://github.com/commaai/opendbc" } + +dependencies = [ + "scons", + "numpy", + "crcmod", + "tqdm", + "pycapnp==2.1.0", + "pycryptodome", +] + +[project.optional-dependencies] +testing = [ + "cffi", + "gcovr", + "pytest", + "pytest-coverage", + "pytest-mock", + "pytest-randomly", + # https://github.com/pytest-dev/pytest-xdist/pull/1229 + "pytest-xdist @ git+https://github.com/sshane/pytest-xdist@2b4372bd62699fb412c4fe2f95bf9f01bd2018da", + "pytest-subtests", + "hypothesis==6.47.*", + "parameterized>=0.8,<0.9", + + # static analysis + "ruff", + "ty", + "lefthook", + "cpplint", + "codespell", +] +docs = [ + "Jinja2", + "natsort", +] +examples = [ + "inputs", + "matplotlib", +] + +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[tool.pytest.ini_options] +addopts = "-Werror --strict-config --strict-markers --durations=10 -n auto" +python_files = "test_*.py" +testpaths = [ + "opendbc" +] + +[tool.codespell] +quiet-level = 3 +ignore-words-list = "alo,ba,bu,deque,hda,grey,arange" +builtin = "clear,rare,informal,code,names,en-GB_to_en-US" +check-hidden = true + +[tool.mypy] +# helpful warnings +warn_redundant_casts=true +warn_unreachable=true +warn_unused_ignores=true + +# restrict dynamic typing +warn_return_any=true + +# allow implicit optionals for default args +implicit_optional = true + +explicit_package_bases=true + +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +line-length = 160 +indent-width = 2 +target-version="py311" + +[tool.ruff.lint] +preview = true +select = [ + "E", "F", "W", "PIE", "C4", "ISC", "A", "B", + "NPY", # numpy + "UP", # pyupgrade + "TRY203", "TRY400", "TRY401", # try/excepts + "RUF008", "RUF100", + "TID251", + "PLR1704", + "INP001", +] +ignore = [ + "E302", "E305", # too restrictive + "W292", + "E741", + "E402", + "C408", + "ISC003", + "B027", + "B024", + "UP031", + "NPY002", # new numpy random syntax is worse + "C420", + "E111", "E114", "E226", "E241", + "E221", "E265", "E266", "E261", + "E252", "E251", "E231", "E225", + "E262", "C419", +] +flake8-implicit-str-concat.allow-multiline=false + +[tool.ruff.lint.per-file-ignores] +"site_scons/*" = ["ALL"] + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" +"numpy.mean".msg = "Sum and divide. np.mean is slow" +# TODO: re-enable when all tests are converted to pytest +#"unittest".msg = "Use pytest" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools.package-data] +"opendbc.safety" = ["*.h", "board/*.h", "board/drivers/*.h", "modes/*.h"] diff --git a/opendbc_repo/setup.sh b/opendbc_repo/setup.sh new file mode 100755 index 0000000000..dce0a22648 --- /dev/null +++ b/opendbc_repo/setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +BASEDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" + +# TODO: why doesn't uv do this? +export PYTHONPATH=$BASEDIR + +# *** dependencies install *** +if [ "$(uname -s)" = "Linux" ]; then + # TODO: add macOS support + if ! command -v "mull-runner-17" > /dev/null 2>&1; then + sudo apt-get update && sudo apt-get install -y curl clang-17 + curl -1sLf 'https://dl.cloudsmith.io/public/mull-project/mull-stable/setup.deb.sh' | sudo -E bash + sudo apt-get update && sudo apt-get install -y mull-17 + fi +fi + +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh +fi + +export UV_PROJECT_ENVIRONMENT="$BASEDIR/.venv" +uv sync --all-extras +source "$PYTHONPATH/.venv/bin/activate" + +$BASEDIR/opendbc/safety/tests/misra/install.sh diff --git a/opendbc_repo/test.sh b/opendbc_repo/test.sh new file mode 100755 index 0000000000..d91afb0356 --- /dev/null +++ b/opendbc_repo/test.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +source ./setup.sh + +# *** build *** +scons -j8 + +# *** lint + test *** +lefthook run test + +# *** all done *** +GREEN='\033[0;32m' +NC='\033[0m' +printf "\n${GREEN}All good!${NC} Finished build, lint, and test in ${SECONDS}s\n" diff --git a/openpilot/__init__.py b/openpilot/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openpilot/common b/openpilot/common new file mode 120000 index 0000000000..60d3b0a6a8 --- /dev/null +++ b/openpilot/common @@ -0,0 +1 @@ +../common \ No newline at end of file diff --git a/openpilot/selfdrive b/openpilot/selfdrive new file mode 120000 index 0000000000..e005fd0d04 --- /dev/null +++ b/openpilot/selfdrive @@ -0,0 +1 @@ +../selfdrive/ \ No newline at end of file diff --git a/openpilot/system b/openpilot/system new file mode 120000 index 0000000000..16f8cc2b23 --- /dev/null +++ b/openpilot/system @@ -0,0 +1 @@ +../system/ \ No newline at end of file diff --git a/openpilot/third_party b/openpilot/third_party new file mode 120000 index 0000000000..d838c05a86 --- /dev/null +++ b/openpilot/third_party @@ -0,0 +1 @@ +../third_party \ No newline at end of file diff --git a/openpilot/tools b/openpilot/tools new file mode 120000 index 0000000000..4887d6e0c9 --- /dev/null +++ b/openpilot/tools @@ -0,0 +1 @@ +../tools \ No newline at end of file diff --git a/panda/.gitignore b/panda/.gitignore new file mode 100644 index 0000000000..612b14f74d --- /dev/null +++ b/panda/.gitignore @@ -0,0 +1,39 @@ +.venv +*.tmp +*.pyc +.*.swp +.*.swo +*.o +*.so +*.os +*.d +*.dump +a.out +*~ +.#* +dist/ +build/ +pandacan.egg-info/ +obj/ +examples/output.csv +.DS_Store +.vscode* +nosetests.xml +.mypy_cache/ +.sconsign.dblite +uv.lock +compile_commands.json + +# CTU info files generated by Cppcheck +*.*.ctu-info +cppcheck-addon-ctu-file-list + +# safety coverage-related files +*.gcda +*.gcno +tests/safety/coverage-out +tests/safety/coverage.info + +*.profraw +*.profdata +mull.yml diff --git a/panda/Dockerfile b/panda/Dockerfile new file mode 100644 index 0000000000..a8a80e97d0 --- /dev/null +++ b/panda/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:24.04 + +ENV WORKDIR=/tmp/panda/ +ENV PYTHONUNBUFFERED=1 +ENV PATH="$WORKDIR/.venv/bin:$PATH" + +WORKDIR $WORKDIR + +# deps install +COPY pyproject.toml __init__.py setup.sh $WORKDIR +RUN mkdir -p $WORKDIR/python/ && touch $WORKDIR/__init__.py +RUN apt-get update && apt-get install -y --no-install-recommends sudo && DEBIAN_FRONTEND=noninteractive $WORKDIR/setup.sh + +# second pass for the opendbc moving tag +ARG CACHEBUST=1 +RUN DEBIAN_FRONTEND=noninteractive $WORKDIR/setup.sh + +RUN git config --global --add safe.directory $WORKDIR/panda +COPY . $WORKDIR diff --git a/panda/Jenkinsfile b/panda/Jenkinsfile new file mode 100644 index 0000000000..d9b1c4647f --- /dev/null +++ b/panda/Jenkinsfile @@ -0,0 +1,144 @@ +def docker_run(String step_label, int timeout_mins, String cmd) { + timeout(time: timeout_mins, unit: 'MINUTES') { + sh script: "docker run --rm --privileged \ + --env PYTHONWARNINGS=error \ + --volume /dev/bus/usb:/dev/bus/usb \ + --volume /var/run/dbus:/var/run/dbus \ + --net host \ + ${env.DOCKER_IMAGE_TAG} \ + bash -c 'scons -j8 && ${cmd}'", \ + label: step_label + } +} + + +def phone(String ip, String step_label, String cmd) { + withCredentials([file(credentialsId: 'id_rsa', variable: 'key_file')]) { + def ssh_cmd = """ +ssh -tt -o StrictHostKeyChecking=no -i ${key_file} 'comma@${ip}' /usr/bin/bash <<'END' + +set -e + + +source ~/.bash_profile +if [ -f /etc/profile ]; then + source /etc/profile +fi + +export CI=1 +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 PYTHONPATH=${env.TEST_DIR}/../ +export PYTHONWARNINGS=error +export LOGLEVEL=debug +ln -sf /data/openpilot/opendbc_repo/opendbc /data/opendbc + +# TODO: this is an agnos issue +export PYTEST_ADDOPTS="-p no:asyncio" + +cd ${env.TEST_DIR} || true +${cmd} +exit 0 + +END""" + + sh script: ssh_cmd, label: step_label + } +} + +def phone_steps(String device_type, steps) { + lock(resource: "", label: device_type, inversePrecedence: true, variable: 'device_ip', quantity: 1) { + timeout(time: 20, unit: 'MINUTES') { + phone(device_ip, "git checkout", readFile("tests/setup_device_ci.sh"),) + steps.each { item -> + phone(device_ip, item[0], item[1]) + } + } + } +} + + + +pipeline { + agent any + environment { + CI = "1" + PYTHONWARNINGS= "error" + DOCKER_IMAGE_TAG = "panda:build-${env.GIT_COMMIT}" + + TEST_DIR = "/data/panda" + SOURCE_DIR = "/data/panda_source/" + } + options { + timeout(time: 3, unit: 'HOURS') + disableConcurrentBuilds(abortPrevious: env.BRANCH_NAME != 'master') + } + + stages { + stage ('Acquire resource locks') { + options { + lock(resource: "pandas") + } + stages { + stage('Build Docker Image') { + steps { + timeout(time: 20, unit: 'MINUTES') { + script { + dockerImage = docker.build("${env.DOCKER_IMAGE_TAG}", "--build-arg CACHEBUST=${env.GIT_COMMIT} .") + } + } + } + } + stage('jungle tests') { + steps { + script { + retry (3) { + docker_run("reset hardware", 3, "python3 ./tests/hitl/reset_jungles.py") + } + } + } + } + + stage('parallel tests') { + parallel { + stage('test cuatro') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + steps { + phone_steps("panda-cuatro", [ + ["build", "scons -j4"], + ["flash", "cd scripts/ && ./reflash_internal_panda.py"], + ["flash jungle", "cd board/jungle && ./flash.py --all"], + ["test", "cd tests/hitl && pytest --durations=0 2*.py [5-9]*.py"], + ]) + } + } + + stage('test tres') { + agent { docker { image 'ghcr.io/commaai/alpine-ssh'; args '--user=root' } } + steps { + phone_steps("panda-tres", [ + ["build", "scons -j4"], + ["flash", "cd scripts/ && ./reflash_internal_panda.py"], + ["flash jungle", "cd board/jungle && ./flash.py --all"], + ["test", "cd tests/hitl && pytest --durations=0 2*.py [5-9]*.py"], + ]) + } + } + + /* + stage('bootkick tests') { + steps { + script { + docker_run("test", 10, "pytest ./tests/som/test_bootkick.py") + } + } + } + */ + } + } + } + } + } +} diff --git a/panda/LICENSE b/panda/LICENSE new file mode 100644 index 0000000000..8a6c6976b7 --- /dev/null +++ b/panda/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2016, 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/panda/README.md b/panda/README.md new file mode 100644 index 0000000000..b66cca3a19 --- /dev/null +++ b/panda/README.md @@ -0,0 +1,91 @@ +# Welcome to panda + +panda speaks CAN and CAN FD, and it runs on the [STM32H725](https://www.st.com/resource/en/reference_manual/rm0468-stm32h723733-stm32h725735-and-stm32h730-value-line-advanced-armbased-32bit-mcus-stmicroelectronics.pdf). + +## Directory structure + +``` +. +├── board # Code that runs on the STM32 +├── drivers # Drivers (not needed for use with Python) +├── python # Python userspace library for interfacing with the panda +├── tests # Tests for panda +├── scripts # Miscellaneous used for panda development and debugging +├── examples # Example scripts for using a panda in a car +``` + +## Safety Model + +panda is compiled with safety firmware provided by [opendbc](https://github.com/commaai/opendbc). See details about the car safety models, safety testing, and code rigor in that repository. + +## Code Rigor + +The panda firmware is written for its use in conjunction with [openpilot](https://github.com/commaai/openpilot). The panda firmware, through its safety model, provides and enforces the +[openpilot safety](https://github.com/commaai/openpilot/blob/master/docs/SAFETY.md). Due to its critical function, it's important that the application code rigor within the `board` folder is held to high standards. + +These are the [CI regression tests](https://github.com/commaai/panda/actions) we have in place: +* A generic static code analysis is performed by [cppcheck](https://github.com/danmar/cppcheck/). +* In addition, [cppcheck](https://github.com/danmar/cppcheck/) has a specific addon to check for [MISRA C:2012](https://misra.org.uk/) violations. See [current coverage](https://github.com/commaai/panda/blob/master/tests/misra/coverage_table). +* Compiler options are relatively strict: the flags `-Wall -Wextra -Wstrict-prototypes -Werror` are enforced. +* The [safety logic](https://github.com/commaai/panda/tree/master/opendbc/safety) is tested and verified by [unit tests](https://github.com/commaai/panda/tree/master/opendbc/safety/tests) for each supported car variant. +to ensure that the behavior remains unchanged. +* A hardware-in-the-loop test verifies panda's functionalities on all active panda variants, including: + * additional safety model checks + * compiling and flashing the bootstub and app code + * receiving, sending, and forwarding CAN messages on all buses + * CAN loopback and latency tests through USB and SPI + +The above tests are themselves tested by: +* a [mutation test](tests/misra/test_mutation.py) on the MISRA coverage + +In addition, we run the [ruff linter](https://github.com/astral-sh/ruff) and [mypy](https://mypy-lang.org/) on panda's Python library. + +## Usage + +```bash +git clone https://github.com/commaai/panda.git +cd panda + +# setup your environment +./setup.sh + +# build fw + run the tests +./test.sh +``` + +See [the Panda class](https://github.com/commaai/panda/blob/master/python/__init__.py) for how to interact with the panda. + +For example, to receive CAN messages: +``` python +>>> from panda import Panda +>>> panda = Panda() +>>> panda.can_recv() +``` +And to send one on bus 0: +``` python +>>> from opendbc.car.structs import CarParams +>>> panda.set_safety_mode(CarParams.SafetyModel.allOutput) +>>> panda.can_send(0x1aa, b'message', 0) +``` +Note that you may have to setup [udev rules](https://github.com/commaai/panda/tree/master/drivers/linux) for Linux, such as +``` bash +sudo tee /etc/udev/rules.d/11-panda.rules < +#include + +// ******************** Prototypes ******************** +typedef enum { + BOOT_STANDBY, + BOOT_BOOTKICK, + BOOT_RESET, +} BootState; + +typedef void (*board_init)(void); +typedef void (*board_init_bootloader)(void); +typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled); +typedef void (*board_set_can_mode)(uint8_t mode); +typedef uint32_t (*board_read_voltage_mV)(void); +typedef uint32_t (*board_read_current_mA)(void); +typedef void (*board_set_ir_power)(uint8_t percentage); +typedef void (*board_set_fan_enabled)(bool enabled); +typedef void (*board_set_siren)(bool enabled); +typedef void (*board_set_bootkick)(BootState state); +typedef bool (*board_read_som_gpio)(void); +typedef void (*board_set_amp_enabled)(bool enabled); + +struct board { + harness_configuration *harness_config; + GPIO_TypeDef * const led_GPIO[3]; + const uint8_t led_pin[3]; + const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM + const bool has_spi; + const bool has_fan; + const uint16_t avdd_mV; + const uint8_t fan_enable_cooldown_time; + board_init init; + board_init_bootloader init_bootloader; + board_enable_can_transceiver enable_can_transceiver; + board_set_can_mode set_can_mode; + board_read_voltage_mV read_voltage_mV; + board_read_current_mA read_current_mA; + board_set_ir_power set_ir_power; + board_set_fan_enabled set_fan_enabled; + board_set_siren set_siren; + board_set_bootkick set_bootkick; + board_read_som_gpio read_som_gpio; + board_set_amp_enabled set_amp_enabled; +}; + +// ******************* Definitions ******************** +// These should match the enums in cereal/log.capnp and __init__.py +#define HW_TYPE_UNKNOWN 0U +#define HW_TYPE_RED_PANDA 7U +#define HW_TYPE_TRES 9U +#define HW_TYPE_CUATRO 10U + +// CAN modes +#define CAN_MODE_NORMAL 0U +#define CAN_MODE_OBD_CAN2 1U + +extern struct board board_tres; +extern struct board board_cuatro; +extern struct board board_red; diff --git a/panda/board/boards/cuatro.h b/panda/board/boards/cuatro.h new file mode 100644 index 0000000000..b6890f8320 --- /dev/null +++ b/panda/board/boards/cuatro.h @@ -0,0 +1,135 @@ +#pragma once + +#include "board_declarations.h" + +// ////////////////////////// // +// Cuatro (STM32H7) + Harness // +// ////////////////////////// // + +static void cuatro_enable_can_transceiver(uint8_t transceiver, bool enabled) { + switch (transceiver) { + case 1U: + set_gpio_output(GPIOB, 7, !enabled); + break; + case 2U: + set_gpio_output(GPIOB, 10, !enabled); + break; + case 3U: + set_gpio_output(GPIOD, 8, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 11, !enabled); + break; + default: + break; + } +} + +static uint32_t cuatro_read_voltage_mV(void) { + return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 8)) * 11U; +} + +static uint32_t cuatro_read_current_mA(void) { + return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 3)) * 2U; +} + +static void cuatro_set_fan_enabled(bool enabled) { + set_gpio_output(GPIOD, 3, !enabled); +} + +static void cuatro_set_bootkick(BootState state) { + set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK); +} + +static void cuatro_set_amp_enabled(bool enabled) { + set_gpio_output(GPIOB, 0, enabled); +} + +static void cuatro_init(void) { + common_init_gpio(); + + // open drain + set_gpio_output_type(GPIOD, 3, OUTPUT_TYPE_OPEN_DRAIN); // FAN_EN + set_gpio_output_type(GPIOC, 12, OUTPUT_TYPE_OPEN_DRAIN); // VBAT_EN + + // Power readout + set_gpio_mode(GPIOC, 5, MODE_ANALOG); + set_gpio_mode(GPIOA, 6, MODE_ANALOG); + + // CAN transceiver enables + set_gpio_pullup(GPIOB, 7, PULL_NONE); + set_gpio_mode(GPIOB, 7, MODE_OUTPUT); + set_gpio_pullup(GPIOD, 8, PULL_NONE); + set_gpio_mode(GPIOD, 8, MODE_OUTPUT); + + // FDCAN3, different pins on this package than the rest of the reds + set_gpio_pullup(GPIOD, 12, PULL_NONE); + set_gpio_alternate(GPIOD, 12, GPIO_AF5_FDCAN3); + set_gpio_pullup(GPIOD, 13, PULL_NONE); + set_gpio_alternate(GPIOD, 13, GPIO_AF5_FDCAN3); + + // C2: SOM GPIO used as input (fan control at boot) + set_gpio_mode(GPIOC, 2, MODE_INPUT); + set_gpio_pullup(GPIOC, 2, PULL_DOWN); + + // SOM bootkick + reset lines + cuatro_set_bootkick(BOOT_BOOTKICK); + + // SOM debugging UART + gpio_uart7_init(); + uart_init(&uart_ring_som_debug, 115200); + + // fan setup + set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3); + register_set_bits(&(GPIOC->OTYPER), GPIO_OTYPER_OT8); // open drain + + // Clock source + clock_source_init(true); + + // Sound codec + cuatro_set_amp_enabled(false); + set_gpio_alternate(GPIOA, 2, GPIO_AF8_SAI4); // SAI4_SCK_B + set_gpio_alternate(GPIOC, 0, GPIO_AF8_SAI4); // SAI4_FS_B + set_gpio_alternate(GPIOD, 11, GPIO_AF10_SAI4); // SAI4_SD_A + set_gpio_alternate(GPIOE, 3, GPIO_AF8_SAI4); // SAI4_SD_B + set_gpio_alternate(GPIOE, 4, GPIO_AF3_DFSDM1); // DFSDM1_DATIN3 + set_gpio_alternate(GPIOE, 9, GPIO_AF3_DFSDM1); // DFSDM1_CKOUT + set_gpio_alternate(GPIOE, 6, GPIO_AF10_SAI4); // SAI4_MCLK_B + sound_init(); +} + +static harness_configuration cuatro_harness_config = { + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOA, + .GPIO_relay_SBU1 = GPIOA, + .GPIO_relay_SBU2 = GPIOA, + .pin_SBU1 = 4, + .pin_SBU2 = 1, + .pin_relay_SBU1 = 9, + .pin_relay_SBU2 = 3, + .adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 4), + .adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 17) +}; + +board board_cuatro = { + .harness_config = &cuatro_harness_config, + .has_spi = true, + .has_fan = true, + .avdd_mV = 1800U, + .fan_enable_cooldown_time = 3U, + .init = cuatro_init, + .init_bootloader = unused_init_bootloader, + .enable_can_transceiver = cuatro_enable_can_transceiver, + .led_GPIO = {GPIOC, GPIOC, GPIOC}, + .led_pin = {6, 7, 9}, + .led_pwm_channels = {1, 2, 4}, + .set_can_mode = tres_set_can_mode, + .read_voltage_mV = cuatro_read_voltage_mV, + .read_current_mA = cuatro_read_current_mA, + .set_fan_enabled = cuatro_set_fan_enabled, + .set_ir_power = unused_set_ir_power, + .set_siren = unused_set_siren, + .set_bootkick = cuatro_set_bootkick, + .read_som_gpio = tres_read_som_gpio, + .set_amp_enabled = cuatro_set_amp_enabled +}; diff --git a/panda/board/boards/red.h b/panda/board/boards/red.h new file mode 100644 index 0000000000..761c2799ec --- /dev/null +++ b/panda/board/boards/red.h @@ -0,0 +1,134 @@ +#pragma once + +#include "board_declarations.h" + +// ///////////////////////////// // +// Red Panda (STM32H7) + Harness // +// ///////////////////////////// // + +static void red_enable_can_transceiver(uint8_t transceiver, bool enabled) { + switch (transceiver) { + case 1U: + set_gpio_output(GPIOG, 11, !enabled); + break; + case 2U: + set_gpio_output(GPIOB, 3, !enabled); + break; + case 3U: + set_gpio_output(GPIOD, 7, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 4, !enabled); + break; + default: + break; + } +} + +static void red_set_can_mode(uint8_t mode) { + red_enable_can_transceiver(2U, false); + red_enable_can_transceiver(4U, false); + switch (mode) { + case CAN_MODE_NORMAL: + case CAN_MODE_OBD_CAN2: + if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) { + // B12,B13: disable normal mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_mode(GPIOB, 12, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_mode(GPIOB, 13, MODE_ANALOG); + + // B5,B6: FDCAN2 mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + red_enable_can_transceiver(2U, true); + } else { + // B5,B6: disable normal mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_mode(GPIOB, 5, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_mode(GPIOB, 6, MODE_ANALOG); + // B12,B13: FDCAN2 mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2); + red_enable_can_transceiver(4U, true); + } + break; + default: + break; + } +} + +static uint32_t red_read_voltage_mV(void){ + return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 2)) * 11U; +} + +static void red_init(void) { + common_init_gpio(); + + // G11,B3,D7,B4: transceiver enable + set_gpio_pullup(GPIOG, 11, PULL_NONE); + set_gpio_mode(GPIOG, 11, MODE_OUTPUT); + + set_gpio_pullup(GPIOB, 3, PULL_NONE); + set_gpio_mode(GPIOB, 3, MODE_OUTPUT); + + set_gpio_pullup(GPIOD, 7, PULL_NONE); + set_gpio_mode(GPIOD, 7, MODE_OUTPUT); + + set_gpio_pullup(GPIOB, 4, PULL_NONE); + set_gpio_mode(GPIOB, 4, MODE_OUTPUT); + + //B1: 5VOUT_S + set_gpio_pullup(GPIOB, 1, PULL_NONE); + set_gpio_mode(GPIOB, 1, MODE_ANALOG); + + // B14: usb load switch, enabled by pull resistor on board, obsolete for red panda + set_gpio_output_type(GPIOB, 14, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_pullup(GPIOB, 14, PULL_UP); + set_gpio_mode(GPIOB, 14, MODE_OUTPUT); + set_gpio_output(GPIOB, 14, 1); +} + +static harness_configuration red_harness_config = { + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOA, + .GPIO_relay_SBU1 = GPIOC, + .GPIO_relay_SBU2 = GPIOC, + .pin_SBU1 = 4, + .pin_SBU2 = 1, + .pin_relay_SBU1 = 10, + .pin_relay_SBU2 = 11, + .adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 4), + .adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 17) +}; + +board board_red = { + .set_bootkick = unused_set_bootkick, + .harness_config = &red_harness_config, + .has_spi = false, + .has_fan = false, + .avdd_mV = 3300U, + .fan_enable_cooldown_time = 0U, + .init = red_init, + .init_bootloader = unused_init_bootloader, + .enable_can_transceiver = red_enable_can_transceiver, + .led_GPIO = {GPIOE, GPIOE, GPIOE}, + .led_pin = {4, 3, 2}, + .set_can_mode = red_set_can_mode, + .read_voltage_mV = red_read_voltage_mV, + .read_current_mA = unused_read_current, + .set_fan_enabled = unused_set_fan_enabled, + .set_ir_power = unused_set_ir_power, + .set_siren = unused_set_siren, + .read_som_gpio = unused_read_som_gpio, + .set_amp_enabled = unused_set_amp_enabled +}; diff --git a/panda/board/boards/tres.h b/panda/board/boards/tres.h new file mode 100644 index 0000000000..73675a989f --- /dev/null +++ b/panda/board/boards/tres.h @@ -0,0 +1,175 @@ +#pragma once + +#include "board_declarations.h" + +// /////////////////////////// +// Tres (STM32H7) + Harness // +// /////////////////////////// + +static bool tres_ir_enabled; +static bool tres_fan_enabled; +static void tres_update_fan_ir_power(void) { + set_gpio_output(GPIOD, 3, tres_ir_enabled || tres_fan_enabled); +} + +static void tres_set_ir_power(uint8_t percentage){ + tres_ir_enabled = (percentage > 0U); + tres_update_fan_ir_power(); + pwm_set(TIM3, 4, percentage); +} + +static void tres_set_bootkick(BootState state) { + set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK); + set_gpio_output(GPIOC, 12, state != BOOT_RESET); +} + +static void tres_set_fan_enabled(bool enabled) { + // NOTE: fan controller reset doesn't work on a tres if IR is enabled + tres_fan_enabled = enabled; + tres_update_fan_ir_power(); +} + +static void tres_enable_can_transceiver(uint8_t transceiver, bool enabled) { + static bool can0_enabled = false; + static bool can2_enabled = false; + + switch (transceiver) { + case 1U: + can0_enabled = enabled; + break; + case 2U: + set_gpio_output(GPIOB, 10, !enabled); + break; + case 3U: + can2_enabled = enabled; + break; + case 4U: + set_gpio_output(GPIOB, 11, !enabled); + break; + default: + break; + } + + // CAN0 and 2 are tied, so enable both if either is enabled + set_gpio_output(GPIOG, 11, !(can0_enabled || can2_enabled)); + set_gpio_output(GPIOD, 7, !(can0_enabled || can2_enabled)); +} + +static void tres_set_can_mode(uint8_t mode) { + current_board->enable_can_transceiver(2U, false); + current_board->enable_can_transceiver(4U, false); + switch (mode) { + case CAN_MODE_NORMAL: + case CAN_MODE_OBD_CAN2: + if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) { + // B12,B13: disable normal mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_mode(GPIOB, 12, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_mode(GPIOB, 13, MODE_ANALOG); + + // B5,B6: FDCAN2 mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + current_board->enable_can_transceiver(2U, true); + } else { + // B5,B6: disable normal mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_mode(GPIOB, 5, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_mode(GPIOB, 6, MODE_ANALOG); + // B12,B13: FDCAN2 mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2); + current_board->enable_can_transceiver(4U, true); + } + break; + default: + break; + } +} + +static bool tres_read_som_gpio (void) { + return (get_gpio_input(GPIOC, 2) != 0); +} + +static void tres_init(void) { + // Enable USB 3.3V LDO for USB block + register_set_bits(&(PWR->CR3), PWR_CR3_USBREGEN); + register_set_bits(&(PWR->CR3), PWR_CR3_USB33DEN); + while ((PWR->CR3 & PWR_CR3_USB33RDY) == 0U); + + common_init_gpio(); + + // C2: SOM GPIO used as input (fan control at boot) + set_gpio_mode(GPIOC, 2, MODE_INPUT); + set_gpio_pullup(GPIOC, 2, PULL_DOWN); + + // SOM bootkick + reset lines + // WARNING: make sure output state is set before configuring as output + tres_set_bootkick(BOOT_BOOTKICK); + set_gpio_mode(GPIOC, 12, MODE_OUTPUT); + + // SOM debugging UART + gpio_uart7_init(); + uart_init(&uart_ring_som_debug, 115200); + + // fan setup + set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3); + + // Initialize IR PWM and set to 0% + set_gpio_alternate(GPIOC, 9, GPIO_AF2_TIM3); + pwm_init(TIM3, 4); + tres_set_ir_power(0U); + + // Fake siren + set_gpio_alternate(GPIOC, 10, GPIO_AF4_I2C5); + set_gpio_alternate(GPIOC, 11, GPIO_AF4_I2C5); + register_set_bits(&(GPIOC->OTYPER), GPIO_OTYPER_OT10 | GPIO_OTYPER_OT11); // open drain + + // Clock source + clock_source_init(false); +} + +static harness_configuration tres_harness_config = { + .GPIO_SBU1 = GPIOC, + .GPIO_SBU2 = GPIOA, + .GPIO_relay_SBU1 = GPIOA, + .GPIO_relay_SBU2 = GPIOA, + .pin_SBU1 = 4, + .pin_SBU2 = 1, + .pin_relay_SBU1 = 8, + .pin_relay_SBU2 = 3, + .adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 4), + .adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 17) +}; + +board board_tres = { + .harness_config = &tres_harness_config, + .has_spi = true, + .has_fan = true, + .avdd_mV = 1800U, + .fan_enable_cooldown_time = 3U, + .init = tres_init, + .init_bootloader = unused_init_bootloader, + .enable_can_transceiver = tres_enable_can_transceiver, + .led_GPIO = {GPIOE, GPIOE, GPIOE}, + .led_pin = {4, 3, 2}, + .set_can_mode = tres_set_can_mode, + .read_voltage_mV = red_read_voltage_mV, + .read_current_mA = unused_read_current, + .set_fan_enabled = tres_set_fan_enabled, + .set_ir_power = tres_set_ir_power, + .set_siren = fake_siren_set, + .set_bootkick = tres_set_bootkick, + .read_som_gpio = tres_read_som_gpio, + .set_amp_enabled = unused_set_amp_enabled +}; diff --git a/panda/board/boards/unused_funcs.h b/panda/board/boards/unused_funcs.h new file mode 100644 index 0000000000..588cf63654 --- /dev/null +++ b/panda/board/boards/unused_funcs.h @@ -0,0 +1,32 @@ +#pragma once + +void unused_init_bootloader(void) { +} + +void unused_set_ir_power(uint8_t percentage) { + UNUSED(percentage); +} + +void unused_set_fan_enabled(bool enabled) { + UNUSED(enabled); +} + +void unused_set_siren(bool enabled) { + UNUSED(enabled); +} + +uint32_t unused_read_current(void) { + return 0U; +} + +void unused_set_bootkick(BootState state) { + UNUSED(state); +} + +bool unused_read_som_gpio(void) { + return false; +} + +void unused_set_amp_enabled(bool enabled) { + UNUSED(enabled); +} diff --git a/panda/board/bootstub.c b/panda/board/bootstub.c new file mode 100644 index 0000000000..a48f308ac7 --- /dev/null +++ b/panda/board/bootstub.c @@ -0,0 +1,85 @@ +#define VERS_TAG 0x53524556 +#define MIN_VERSION 2 + +// ********************* Includes ********************* +#include "board/config.h" + +#include "board/drivers/led.h" +#include "board/drivers/pwm.h" +#include "board/drivers/usb.h" + +#include "board/early_init.h" +#include "board/provision.h" + +#include "crypto/rsa.h" +#include "crypto/sha.h" + +#include "board/obj/cert.h" +#include "board/obj/gitversion.h" +#include "board/flasher.h" + +// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck +void __initialize_hardware_early(void) { + early_initialization(); +} + +void fail(void) { + soft_flasher_start(); +} + +// know where to sig check +extern void *_app_start[]; + +int main(void) { + // Init interrupt table + init_interrupts(true); + + disable_interrupts(); + clock_init(); + detect_board_type(); + +#ifdef PANDA_JUNGLE + current_board->set_panda_power(true); +#endif + + if (enter_bootloader_mode == ENTER_SOFTLOADER_MAGIC) { + enter_bootloader_mode = 0; + soft_flasher_start(); + } + + // validate length + int len = (int)_app_start[0]; + if ((len < 8) || (len > (0x1000000 - 0x4000 - 4 - RSANUMBYTES))) goto fail; + + // compute SHA hash + uint8_t digest[SHA_DIGEST_SIZE]; + SHA_hash(&_app_start[1], len-4, digest); + + // verify version, last bytes in the signed area + uint32_t vers[2] = {0}; + memcpy(&vers, ((void*)&_app_start[0]) + len - sizeof(vers), sizeof(vers)); + if (vers[0] != VERS_TAG || vers[1] < MIN_VERSION) { + goto fail; + } + + // verify RSA signature + if (RSA_verify(&release_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { + goto good; + } + + // allow debug if built from source +#ifdef ALLOW_DEBUG + if (RSA_verify(&debug_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) { + goto good; + } +#endif + +// here is a failure +fail: + fail(); + return 0; +good: + // jump to flash + ((void(*)(void)) _app_start[1])(); + return 0; +} diff --git a/panda/board/bootstub_declarations.h b/panda/board/bootstub_declarations.h new file mode 100644 index 0000000000..5cdec508e7 --- /dev/null +++ b/panda/board/bootstub_declarations.h @@ -0,0 +1,18 @@ +// ******************** Prototypes ******************** +void print(const char *a){ UNUSED(a); } +void puth(uint8_t i){ UNUSED(i); } +void puth2(uint8_t i){ UNUSED(i); } +void puth4(uint8_t i){ UNUSED(i); } +void hexdump(const void *a, int l){ UNUSED(a); UNUSED(l); } +typedef struct board board; +typedef struct harness_configuration harness_configuration; +void pwm_init(TIM_TypeDef *TIM, uint8_t channel); +void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage); +// No UART support in bootloader +typedef struct uart_ring {} uart_ring; +uart_ring uart_ring_som_debug; +void uart_init(uart_ring *q, int baud) { UNUSED(q); UNUSED(baud); } + +// ********************* Globals ********************** +uint8_t hw_type = 0; +board *current_board; diff --git a/panda/board/can.h b/panda/board/can.h new file mode 100644 index 0000000000..d6e360a043 --- /dev/null +++ b/panda/board/can.h @@ -0,0 +1,5 @@ +#pragma once + +#define PANDA_CAN_CNT 3U + +#include "opendbc/safety/can.h" diff --git a/panda/board/can_comms.h b/panda/board/can_comms.h new file mode 100644 index 0000000000..99ee968b0a --- /dev/null +++ b/panda/board/can_comms.h @@ -0,0 +1,122 @@ +/* + CAN transactions to and from the host come in the form of + a certain number of CANPacket_t. The transaction is split + into multiple transfers or chunks. + + * comms_can_read outputs this buffer in chunks of a specified length. + chunks are always the given length, except the last one. + * comms_can_write reads in this buffer in chunks. + * both functions maintain an overflow buffer for a partial CANPacket_t that + spans multiple transfers/chunks. + * the overflow buffers are reset by a dedicated control transfer handler, + which is sent by the host on each start of a connection. +*/ + +typedef struct { + uint32_t ptr; + uint32_t tail_size; + uint8_t data[72]; +} asm_buffer; + +static asm_buffer can_read_buffer = {.ptr = 0U, .tail_size = 0U}; + +int comms_can_read(uint8_t *data, uint32_t max_len) { + uint32_t pos = 0U; + + // Send tail of previous message if it is in buffer + if (can_read_buffer.ptr > 0U) { + uint32_t overflow_len = MIN(max_len - pos, can_read_buffer.ptr); + (void)memcpy(&data[pos], can_read_buffer.data, overflow_len); + pos += overflow_len; + (void)memcpy(can_read_buffer.data, &can_read_buffer.data[overflow_len], can_read_buffer.ptr - overflow_len); + can_read_buffer.ptr -= overflow_len; + } + + if (can_read_buffer.ptr == 0U) { + // Fill rest of buffer with new data + CANPacket_t can_packet; + while ((pos < max_len) && can_pop(&can_rx_q, &can_packet)) { + uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[can_packet.data_len_code]; + if ((pos + pckt_len) <= max_len) { + (void)memcpy(&data[pos], (uint8_t*)&can_packet, pckt_len); + pos += pckt_len; + } else { + (void)memcpy(&data[pos], (uint8_t*)&can_packet, max_len - pos); + can_read_buffer.ptr += pckt_len - (max_len - pos); + // cppcheck-suppress objectIndex + (void)memcpy(can_read_buffer.data, &((uint8_t*)&can_packet)[(max_len - pos)], can_read_buffer.ptr); + pos = max_len; + } + } + } + + return pos; +} + +static asm_buffer can_write_buffer = {.ptr = 0U, .tail_size = 0U}; + +// send on CAN +void comms_can_write(const uint8_t *data, uint32_t len) { + uint32_t pos = 0U; + + // Assembling can message with data from buffer + if (can_write_buffer.ptr != 0U) { + if (can_write_buffer.tail_size <= (len - pos)) { + // we have enough data to complete the buffer + CANPacket_t to_push = {0}; + (void)memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], can_write_buffer.tail_size); + can_write_buffer.ptr += can_write_buffer.tail_size; + pos += can_write_buffer.tail_size; + + // send out + (void)memcpy((uint8_t*)&to_push, can_write_buffer.data, can_write_buffer.ptr); + can_send(&to_push, to_push.bus, false); + + // reset overflow buffer + can_write_buffer.ptr = 0U; + can_write_buffer.tail_size = 0U; + } else { + // maybe next time + uint32_t data_size = len - pos; + (void) memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], data_size); + can_write_buffer.tail_size -= data_size; + can_write_buffer.ptr += data_size; + pos += data_size; + } + } + + // rest of the message + while (pos < len) { + uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[(data[pos] >> 4U)]; + if ((pos + pckt_len) <= len) { + CANPacket_t to_push = {0}; + (void)memcpy((uint8_t*)&to_push, &data[pos], pckt_len); + can_send(&to_push, to_push.bus, false); + pos += pckt_len; + } else { + (void)memcpy(can_write_buffer.data, &data[pos], len - pos); + can_write_buffer.ptr = len - pos; + can_write_buffer.tail_size = pckt_len - can_write_buffer.ptr; + pos += can_write_buffer.ptr; + } + } + + refresh_can_tx_slots_available(); +} + +void comms_can_reset(void) { + can_write_buffer.ptr = 0U; + can_write_buffer.tail_size = 0U; + can_read_buffer.ptr = 0U; + can_read_buffer.tail_size = 0U; +} + +// TODO: make this more general! +void refresh_can_tx_slots_available(void) { + if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_USB_BULK_TRANSFER)) { + can_tx_comms_resume_usb(); + } + if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_SPI_BULK_TRANSFER)) { + can_tx_comms_resume_spi(); + } +} diff --git a/panda/board/comms_definitions.h b/panda/board/comms_definitions.h new file mode 100644 index 0000000000..18a6d2f813 --- /dev/null +++ b/panda/board/comms_definitions.h @@ -0,0 +1,12 @@ +typedef struct { + uint8_t request; + uint16_t param1; + uint16_t param2; + uint16_t length; +} __attribute__((packed)) ControlPacket_t; + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp); +void comms_endpoint2_write(const uint8_t *data, uint32_t len); +void comms_can_write(const uint8_t *data, uint32_t len); +int comms_can_read(uint8_t *data, uint32_t max_len); +void comms_can_reset(void); diff --git a/panda/board/config.h b/panda/board/config.h new file mode 100644 index 0000000000..1b7d938cc8 --- /dev/null +++ b/panda/board/config.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +//#define DEBUG +//#define DEBUG_UART +//#define DEBUG_USB +//#define DEBUG_SPI +//#define DEBUG_FAULTS +//#define DEBUG_COMMS +//#define DEBUG_FAN + +#define CAN_INIT_TIMEOUT_MS 500U +#define USBPACKET_MAX_SIZE 0x40U +#define MAX_CAN_MSGS_PER_USB_BULK_TRANSFER 51U +#define MAX_CAN_MSGS_PER_SPI_BULK_TRANSFER 170U + +// USB definitions +#define USB_VID 0x3801U + +#ifdef PANDA_JUNGLE + #ifdef BOOTSTUB + #define USB_PID 0xDDEFU + #else + #define USB_PID 0xDDCFU + #endif +#else + #ifdef BOOTSTUB + #define USB_PID 0xDDEEU + #else + #define USB_PID 0xDDCCU + #endif +#endif + +// platform includes +#ifdef STM32H7 + #include "board/stm32h7/stm32h7_config.h" +#else + // TODO: uncomment this, cppcheck complains + // building for tests + //#include "fake_stm.h" +#endif diff --git a/panda/board/crc.h b/panda/board/crc.h new file mode 100644 index 0000000000..3e20fb0981 --- /dev/null +++ b/panda/board/crc.h @@ -0,0 +1,19 @@ +#pragma once + +uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) { + uint8_t crc = 0xFFU; + int i; + int j; + for (i = len - 1; i >= 0; i--) { + crc ^= dat[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80U) != 0U) { + crc = (uint8_t)((crc << 1) ^ poly); + } + else { + crc <<= 1; + } + } + } + return crc; +} diff --git a/panda/board/critical.h b/panda/board/critical.h new file mode 100644 index 0000000000..ae2d5c0a69 --- /dev/null +++ b/panda/board/critical.h @@ -0,0 +1,16 @@ +#include "critical_declarations.h" + +// ********************* Critical section helpers ********************* +uint8_t global_critical_depth = 0U; + +static volatile bool interrupts_enabled = false; + +void enable_interrupts(void) { + interrupts_enabled = true; + __enable_irq(); +} + +void disable_interrupts(void) { + interrupts_enabled = false; + __disable_irq(); +} diff --git a/panda/board/critical_declarations.h b/panda/board/critical_declarations.h new file mode 100644 index 0000000000..42211d46c3 --- /dev/null +++ b/panda/board/critical_declarations.h @@ -0,0 +1,17 @@ +#pragma once + +// ********************* Critical section helpers ********************* +void enable_interrupts(void); +void disable_interrupts(void); + +extern uint8_t global_critical_depth; + +#define ENTER_CRITICAL() \ + __disable_irq(); \ + global_critical_depth += 1U; + +#define EXIT_CRITICAL() \ + global_critical_depth -= 1U; \ + if ((global_critical_depth == 0U) && interrupts_enabled) { \ + __enable_irq(); \ + } diff --git a/panda/board/debug/README.md b/panda/board/debug/README.md new file mode 100644 index 0000000000..f6a7826a32 --- /dev/null +++ b/panda/board/debug/README.md @@ -0,0 +1,24 @@ +# In-circuit debugging using openocd and gdb + +## Hardware +Connect an ST-Link V2 programmer to the SWD pins on the board. The pins that need to be connected are: +- GND +- VTref +- SWDIO +- SWCLK +- NRST + +Make sure you're using a genuine one for boards that do not have a 3.3V panda power rail. For example, the tres runs at 1.8V, which is not supported by the clones. + +## Openocd +Install openocd. For Ubuntu 24.04, the one in the package manager works fine: `sudo apt install openocd`. + +## GDB +You need `gdb-multiarch`. + +Once openocd is running, you can connect from gdb as follows: +``` +$ gdb-multiarch +(gdb) target ext :3333 +``` +To reset and break, use `monitor reset halt`. diff --git a/panda/board/debug/debug_h7.sh b/panda/board/debug/debug_h7.sh new file mode 100755 index 0000000000..126a9c378c --- /dev/null +++ b/panda/board/debug/debug_h7.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e + +sudo openocd -f "interface/stlink.cfg" -c "transport select hla_swd" -f "target/stm32h7x.cfg" -c "init" diff --git a/panda/board/debug/dfu_util_h7.sh b/panda/board/debug/dfu_util_h7.sh new file mode 100755 index 0000000000..c39a24ec7b --- /dev/null +++ b/panda/board/debug/dfu_util_h7.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +scons -u -j$(nproc) + +PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true +sleep 1 +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08020000 -D obj/panda_h7.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda_h7.bin diff --git a/panda/board/debug/gdb.sh b/panda/board/debug/gdb.sh new file mode 100755 index 0000000000..aa695d6ab7 --- /dev/null +++ b/panda/board/debug/gdb.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +gdb-multiarch --eval-command="target extended-remote localhost:3333" diff --git a/panda/board/drivers/bootkick.h b/panda/board/drivers/bootkick.h new file mode 100644 index 0000000000..eab7da3ebc --- /dev/null +++ b/panda/board/drivers/bootkick.h @@ -0,0 +1,68 @@ +#include "bootkick_declarations.h" + +bool bootkick_reset_triggered = false; + +void bootkick_tick(bool ignition, bool recent_heartbeat) { + static uint16_t bootkick_last_serial_ptr = 0; + static uint8_t waiting_to_boot_countdown = 0; + static uint8_t boot_reset_countdown = 0; + static uint8_t bootkick_harness_status_prev = HARNESS_STATUS_NC; + static bool bootkick_ign_prev = false; + static BootState boot_state = BOOT_BOOTKICK; + BootState boot_state_prev = boot_state; + const bool harness_inserted = (harness.status != bootkick_harness_status_prev) && (harness.status != HARNESS_STATUS_NC); + + if ((ignition && !bootkick_ign_prev) || harness_inserted) { + // bootkick on rising edge of ignition or harness insertion + boot_state = BOOT_BOOTKICK; + } else if (recent_heartbeat) { + // disable bootkick once openpilot is up + boot_state = BOOT_STANDBY; + } else { + + } + + /* + Ensure SOM boots in case it goes into QDL mode. Reset behavior: + * shouldn't trigger on the first boot after power-on + * only try reset once per bootkick, i.e. don't keep trying until booted + * only try once per panda boot, since openpilot will reset panda on startup + * once BOOT_RESET is triggered, it stays until countdown is finished + */ + if (!bootkick_reset_triggered && (boot_state == BOOT_BOOTKICK) && (boot_state_prev == BOOT_STANDBY)) { + waiting_to_boot_countdown = 20U; + } + if (waiting_to_boot_countdown > 0U) { + bool serial_activity = uart_ring_som_debug.w_ptr_tx != bootkick_last_serial_ptr; + if (serial_activity || current_board->read_som_gpio() || (boot_state != BOOT_BOOTKICK)) { + waiting_to_boot_countdown = 0U; + } else { + // try a reset + if (waiting_to_boot_countdown == 1U) { + boot_reset_countdown = 5U; + } + } + } + + // handle reset state + if (boot_reset_countdown > 0U) { + boot_state = BOOT_RESET; + bootkick_reset_triggered = true; + } else { + if (boot_state == BOOT_RESET) { + boot_state = BOOT_BOOTKICK; + } + } + + // update state + bootkick_ign_prev = ignition; + bootkick_harness_status_prev = harness.status; + bootkick_last_serial_ptr = uart_ring_som_debug.w_ptr_tx; + if (waiting_to_boot_countdown > 0U) { + waiting_to_boot_countdown--; + } + if (boot_reset_countdown > 0U) { + boot_reset_countdown--; + } + current_board->set_bootkick(boot_state); +} diff --git a/panda/board/drivers/bootkick_declarations.h b/panda/board/drivers/bootkick_declarations.h new file mode 100644 index 0000000000..3b55b72ac6 --- /dev/null +++ b/panda/board/drivers/bootkick_declarations.h @@ -0,0 +1,5 @@ +#pragma once + +extern bool bootkick_reset_triggered; + +void bootkick_tick(bool ignition, bool recent_heartbeat); diff --git a/panda/board/drivers/can_common.h b/panda/board/drivers/can_common.h new file mode 100644 index 0000000000..35c6702e80 --- /dev/null +++ b/panda/board/drivers/can_common.h @@ -0,0 +1,257 @@ +#include "can_common_declarations.h" + +uint32_t safety_tx_blocked = 0; +uint32_t safety_rx_invalid = 0; +uint32_t tx_buffer_overflow = 0; +uint32_t rx_buffer_overflow = 0; + +can_health_t can_health[PANDA_CAN_CNT] = {{0}, {0}, {0}}; + +// Ignition detected from CAN meessages +bool ignition_can = false; +uint32_t ignition_can_cnt = 0U; + +bool can_silent = true; +bool can_loopback = false; + +// ********************* instantiate queues ********************* +#define can_buffer(x, size) \ + static CANPacket_t elems_##x[size]; \ + extern can_ring can_##x; \ + can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = (size), .elems = (CANPacket_t *)&(elems_##x) }; + +#define CAN_RX_BUFFER_SIZE 4096U +#define CAN_TX_BUFFER_SIZE 416U + +#ifdef STM32H7 +// ITCM RAM and DTCM RAM are the fastest for Cortex-M7 core access +__attribute__((section(".axisram"))) can_buffer(rx_q, CAN_RX_BUFFER_SIZE) +__attribute__((section(".itcmram"))) can_buffer(tx1_q, CAN_TX_BUFFER_SIZE) +__attribute__((section(".itcmram"))) can_buffer(tx2_q, CAN_TX_BUFFER_SIZE) +#else // kept for PC +can_buffer(rx_q, CAN_RX_BUFFER_SIZE) +can_buffer(tx1_q, CAN_TX_BUFFER_SIZE) +can_buffer(tx2_q, CAN_TX_BUFFER_SIZE) +#endif +can_buffer(tx3_q, CAN_TX_BUFFER_SIZE) + +// FIXME: +// cppcheck-suppress misra-c2012-9.3 +can_ring *can_queues[PANDA_CAN_CNT] = {&can_tx1_q, &can_tx2_q, &can_tx3_q}; + +// ********************* interrupt safe queue ********************* +bool can_pop(can_ring *q, CANPacket_t *elem) { + bool ret = 0; + + ENTER_CRITICAL(); + if (q->w_ptr != q->r_ptr) { + *elem = q->elems[q->r_ptr]; + if ((q->r_ptr + 1U) == q->fifo_size) { + q->r_ptr = 0; + } else { + q->r_ptr += 1U; + } + ret = 1; + } + EXIT_CRITICAL(); + + return ret; +} + +bool can_push(can_ring *q, const CANPacket_t *elem) { + bool ret = false; + uint32_t next_w_ptr; + + ENTER_CRITICAL(); + if ((q->w_ptr + 1U) == q->fifo_size) { + next_w_ptr = 0; + } else { + next_w_ptr = q->w_ptr + 1U; + } + if (next_w_ptr != q->r_ptr) { + q->elems[q->w_ptr] = *elem; + q->w_ptr = next_w_ptr; + ret = true; + } + EXIT_CRITICAL(); + if (!ret) { + #ifdef DEBUG + print("can_push to "); + if (q == &can_rx_q) { + print("can_rx_q"); + } else if (q == &can_tx1_q) { + print("can_tx1_q"); + } else if (q == &can_tx2_q) { + print("can_tx2_q"); + } else if (q == &can_tx3_q) { + print("can_tx3_q"); + } else { + print("unknown"); + } + print(" failed!\n"); + #endif + } + return ret; +} + +uint32_t can_slots_empty(const can_ring *q) { + uint32_t ret = 0; + + ENTER_CRITICAL(); + if (q->w_ptr >= q->r_ptr) { + ret = q->fifo_size - 1U - q->w_ptr + q->r_ptr; + } else { + ret = q->r_ptr - q->w_ptr - 1U; + } + EXIT_CRITICAL(); + + return ret; +} + +void can_clear(can_ring *q) { + ENTER_CRITICAL(); + q->w_ptr = 0; + q->r_ptr = 0; + EXIT_CRITICAL(); + // handle TX buffer full with zero ECUs awake on the bus + refresh_can_tx_slots_available(); +} + +// assign CAN numbering +// bus num: CAN Bus numbers in panda, sent to/from USB +// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) +// cans: Look up MCU can interface from bus number +// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc); +// bus_lookup: Translates from 'can number' to 'bus number'. +// can_num_lookup: Translates from 'bus number' to 'can number'. +// forwarding bus: If >= 0, forward all messages from this bus to the specified bus. + +// Helpers +// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3 +bus_config_t bus_config[PANDA_CAN_CNT] = { + { .bus_lookup = 0U, .can_num_lookup = 0U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, + { .bus_lookup = 1U, .can_num_lookup = 1U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, + { .bus_lookup = 2U, .can_num_lookup = 2U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, +}; + +void can_init_all(void) { + for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) { + bus_config[i].canfd_enabled = false; + can_clear(can_queues[i]); + (void)can_init(i); + } +} + +void can_set_orientation(bool flipped) { + bus_config[0].bus_lookup = flipped ? 2U : 0U; + bus_config[0].can_num_lookup = flipped ? 2U : 0U; + bus_config[2].bus_lookup = flipped ? 0U : 2U; + bus_config[2].can_num_lookup = flipped ? 0U : 2U; +} + +#ifdef PANDA_JUNGLE +void can_set_forwarding(uint8_t from, uint8_t to) { + bus_config[from].forwarding_bus = to; +} +#endif + +void ignition_can_hook(CANPacket_t *msg) { + if (msg->bus == 0U) { + int len = GET_LEN(msg); + + // GM exception + if ((msg->addr == 0x1F1U) && (len == 8)) { + // SystemPowerMode (2=Run, 3=Crank Request) + ignition_can = (msg->data[0] & 0x2U) != 0U; + ignition_can_cnt = 0U; + } + + // Rivian R1S/T GEN1 exception + if ((msg->addr == 0x152U) && (len == 8)) { + // 0x152 overlaps with Subaru pre-global which has this bit as the high beam + int counter = msg->data[1] & 0xFU; // max is only 14 + + static int prev_counter_rivian = -1; + if ((counter == ((prev_counter_rivian + 1) % 15)) && (prev_counter_rivian != -1)) { + // VDM_OutputSignals->VDM_EpasPowerMode + ignition_can = ((msg->data[7] >> 4U) & 0x3U) == 1U; // VDM_EpasPowerMode_Drive_On=1 + ignition_can_cnt = 0U; + } + prev_counter_rivian = counter; + } + + // Tesla Model 3/Y exception + if ((msg->addr == 0x221U) && (len == 8)) { + // 0x221 overlaps with Rivian which has random data on byte 0 + int counter = msg->data[6] >> 4; + + static int prev_counter_tesla = -1; + if ((counter == ((prev_counter_tesla + 1) % 16)) && (prev_counter_tesla != -1)) { + // VCFRONT_LVPowerState->VCFRONT_vehiclePowerState + int power_state = (msg->data[0] >> 5U) & 0x3U; + ignition_can = power_state == 0x3; // VEHICLE_POWER_STATE_DRIVE=3 + ignition_can_cnt = 0U; + } + prev_counter_tesla = counter; + } + + // Mazda exception + if ((msg->addr == 0x9EU) && (len == 8)) { + ignition_can = (msg->data[0] >> 5) == 0x6U; + ignition_can_cnt = 0U; + } + + } +} + +bool can_tx_check_min_slots_free(uint32_t min) { + return + (can_slots_empty(&can_tx1_q) >= min) && + (can_slots_empty(&can_tx2_q) >= min) && + (can_slots_empty(&can_tx3_q) >= min); +} + +uint8_t calculate_checksum(const uint8_t *dat, uint32_t len) { + uint8_t checksum = 0U; + for (uint32_t i = 0U; i < len; i++) { + checksum ^= dat[i]; + } + return checksum; +} + +void can_set_checksum(CANPacket_t *packet) { + packet->checksum = 0U; + packet->checksum = calculate_checksum((uint8_t *) packet, CANPACKET_HEAD_SIZE + GET_LEN(packet)); +} + +bool can_check_checksum(CANPacket_t *packet) { + return (calculate_checksum((uint8_t *) packet, CANPACKET_HEAD_SIZE + GET_LEN(packet)) == 0U); +} + +void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook) { + if (skip_tx_hook || safety_tx_hook(to_push) != 0) { + if (bus_number < PANDA_CAN_CNT) { + // add CAN packet to send queue + tx_buffer_overflow += can_push(can_queues[bus_number], to_push) ? 0U : 1U; + process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); + } + } else { + safety_tx_blocked += 1U; + to_push->returned = 0U; + to_push->rejected = 1U; + + // data changed + can_set_checksum(to_push); + rx_buffer_overflow += can_push(&can_rx_q, to_push) ? 0U : 1U; + } +} + +bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len) { + bool ret = false; + for (uint8_t i = 0U; i < len; i++) { + if (all_speeds[i] == speed) { + ret = true; + } + } + return ret; +} diff --git a/panda/board/drivers/can_common_declarations.h b/panda/board/drivers/can_common_declarations.h new file mode 100644 index 0000000000..75580b7b64 --- /dev/null +++ b/panda/board/drivers/can_common_declarations.h @@ -0,0 +1,70 @@ +#pragma once + +#include "board/can.h" + +typedef struct { + volatile uint32_t w_ptr; + volatile uint32_t r_ptr; + uint32_t fifo_size; + CANPacket_t *elems; +} can_ring; + +typedef struct { + uint8_t bus_lookup; + uint8_t can_num_lookup; + int8_t forwarding_bus; + uint32_t can_speed; + uint32_t can_data_speed; + bool canfd_auto; + bool canfd_enabled; + bool brs_enabled; + bool canfd_non_iso; +} bus_config_t; + +extern uint32_t safety_tx_blocked; +extern uint32_t safety_rx_invalid; +extern uint32_t tx_buffer_overflow; +extern uint32_t rx_buffer_overflow; + +extern can_health_t can_health[PANDA_CAN_CNT]; + +// Ignition detected from CAN meessages +extern bool ignition_can; +extern uint32_t ignition_can_cnt; + +extern bool can_silent; +extern bool can_loopback; + +// ******************* functions prototypes ********************* +bool can_init(uint8_t can_number); +void process_can(uint8_t can_number); + +// ********************* instantiate queues ********************* +extern can_ring *can_queues[PANDA_CAN_CNT]; + +// helpers +#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU) +#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U)) + +// ********************* interrupt safe queue ********************* +bool can_pop(can_ring *q, CANPacket_t *elem); +bool can_push(can_ring *q, const CANPacket_t *elem); +uint32_t can_slots_empty(const can_ring *q); +extern bus_config_t bus_config[PANDA_CAN_CNT]; + +#define CANIF_FROM_CAN_NUM(num) (cans[num]) +#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup) +#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup) + +void can_init_all(void); +void can_set_orientation(bool flipped); +#ifdef PANDA_JUNGLE +void can_set_forwarding(uint8_t from, uint8_t to); +#endif +void ignition_can_hook(CANPacket_t *to_push); +bool can_tx_check_min_slots_free(uint32_t min); +uint8_t calculate_checksum(const uint8_t *dat, uint32_t len); +void can_set_checksum(CANPacket_t *packet); +bool can_check_checksum(CANPacket_t *packet); +void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook); +bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len); diff --git a/panda/board/drivers/clock_source.h b/panda/board/drivers/clock_source.h new file mode 100644 index 0000000000..87d89ad063 --- /dev/null +++ b/panda/board/drivers/clock_source.h @@ -0,0 +1,44 @@ +#include "clock_source_declarations.h" + +void clock_source_set_timer_params(uint16_t param1, uint16_t param2) { + // Pulse length of each channel + register_set(&(TIM1->CCR1), (((param1 & 0xFF00U) >> 8U)*10U), 0xFFFFU); + register_set(&(TIM1->CCR2), ((param1 & 0x00FFU)*10U), 0xFFFFU); + register_set(&(TIM1->CCR3), (((param2 & 0xFF00U) >> 8U)*10U), 0xFFFFU); + // Timer period + register_set(&(TIM1->ARR), (((param2 & 0x00FFU)*10U) - 1U), 0xFFFFU); +} + +void clock_source_init(bool enable_channel1) { + // Setup timer + register_set(&(TIM1->PSC), ((APB2_TIMER_FREQ*100U)-1U), 0xFFFFU); // Tick on 0.1 ms + register_set(&(TIM1->ARR), ((CLOCK_SOURCE_PERIOD_MS*10U) - 1U), 0xFFFFU); // Period + register_set(&(TIM1->CCMR1), 0U, 0xFFFFU); // No output on compare + register_set(&(TIM1->CCER), TIM_CCER_CC1E, 0xFFFFU); // Enable compare 1 + register_set(&(TIM1->CCR1), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value + register_set(&(TIM1->CCR2), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value + register_set(&(TIM1->CCR3), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value + register_set_bits(&(TIM1->DIER), TIM_DIER_UIE | TIM_DIER_CC1IE); // Enable interrupts + register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU); // Enable timer + + // No interrupts + NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn); + NVIC_DisableIRQ(TIM1_CC_IRQn); + + // Set GPIO as timer channels + if (enable_channel1) { + set_gpio_alternate(GPIOA, 8, GPIO_AF1_TIM1); + } + set_gpio_alternate(GPIOB, 14, GPIO_AF1_TIM1); + set_gpio_alternate(GPIOB, 15, GPIO_AF1_TIM1); + + // Set PWM mode + register_set(&(TIM1->CCMR1), (0b110UL << TIM_CCMR1_OC1M_Pos) | (0b110UL << TIM_CCMR1_OC2M_Pos), 0xFFFFU); + register_set(&(TIM1->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos), 0xFFFFU); + + // Enable output + register_set(&(TIM1->BDTR), TIM_BDTR_MOE, 0xFFFFU); + + // Enable complementary compares + register_set_bits(&(TIM1->CCER), TIM_CCER_CC2NE | TIM_CCER_CC3NE); +} diff --git a/panda/board/drivers/clock_source_declarations.h b/panda/board/drivers/clock_source_declarations.h new file mode 100644 index 0000000000..d95eb961a0 --- /dev/null +++ b/panda/board/drivers/clock_source_declarations.h @@ -0,0 +1,7 @@ +#pragma once + +#define CLOCK_SOURCE_PERIOD_MS 50U +#define CLOCK_SOURCE_PULSE_LEN_MS 2U + +void clock_source_set_timer_params(uint16_t param1, uint16_t param2); +void clock_source_init(bool enable_channel1); diff --git a/panda/board/drivers/fake_siren.h b/panda/board/drivers/fake_siren.h new file mode 100644 index 0000000000..4bce95bd8d --- /dev/null +++ b/panda/board/drivers/fake_siren.h @@ -0,0 +1,84 @@ +#include "board/stm32h7/lli2c.h" + +#define CODEC_I2C_ADDR 0x10 + +void fake_siren_init(void); + +void fake_siren_codec_enable(bool enabled) { + if (enabled) { + bool success = true; + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x2B, (1U << 1)); // Left speaker mix from INA1 + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x2C, (1U << 1)); // Right speaker mix from INA1 + success &= i2c_set_reg_mask(I2C5, CODEC_I2C_ADDR, 0x3D, 0x17, 0b11111); // Left speaker volume + success &= i2c_set_reg_mask(I2C5, CODEC_I2C_ADDR, 0x3E, 0x17, 0b11111); // Right speaker volume + success &= i2c_set_reg_mask(I2C5, CODEC_I2C_ADDR, 0x37, 0b101, 0b111); // INA gain + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x4C, (1U << 7)); // Enable INA + success &= i2c_set_reg_bits(I2C5, CODEC_I2C_ADDR, 0x51, (1U << 7)); // Disable global shutdown + if (!success) { + print("Siren codec enable failed\n"); + fault_occurred(FAULT_SIREN_MALFUNCTION); + } + } else { + // Disable INA input. Make sure to retry a few times if the I2C bus is busy. + for (uint8_t i=0U; i<10U; i++) { + if (i2c_clear_reg_bits(I2C5, CODEC_I2C_ADDR, 0x4C, (1U << 7))) { + break; + } + } + } +} + + +void fake_siren_set(bool enabled) { + static bool initialized = false; + static bool fake_siren_enabled = false; + + if (!initialized) { + fake_siren_init(); + initialized = true; + } + + if (enabled != fake_siren_enabled) { + fake_siren_codec_enable(enabled); + } + + if (enabled) { + register_set_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } else { + register_clear_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } + fake_siren_enabled = enabled; +} + +void fake_siren_init(void) { + // 1Vpp sine wave with 1V offset + static const uint8_t fake_siren_lut[360] = { 134U, 135U, 137U, 138U, 139U, 140U, 141U, 143U, 144U, 145U, 146U, 148U, 149U, 150U, 151U, 152U, 154U, 155U, 156U, 157U, 158U, 159U, 160U, 162U, 163U, 164U, 165U, 166U, 167U, 168U, 169U, 170U, 171U, 172U, 174U, 175U, 176U, 177U, 177U, 178U, 179U, 180U, 181U, 182U, 183U, 184U, 185U, 186U, 186U, 187U, 188U, 189U, 190U, 190U, 191U, 192U, 193U, 193U, 194U, 195U, 195U, 196U, 196U, 197U, 197U, 198U, 199U, 199U, 199U, 200U, 200U, 201U, 201U, 202U, 202U, 202U, 203U, 203U, 203U, 203U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 205U, 205U, 205U, 205U, 205U, 205U, 205U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 203U, 203U, 203U, 203U, 202U, 202U, 202U, 201U, 201U, 200U, 200U, 199U, 199U, 199U, 198U, 197U, 197U, 196U, 196U, 195U, 195U, 194U, 193U, 193U, 192U, 191U, 190U, 190U, 189U, 188U, 187U, 186U, 186U, 185U, 184U, 183U, 182U, 181U, 180U, 179U, 178U, 177U, 177U, 176U, 175U, 174U, 172U, 171U, 170U, 169U, 168U, 167U, 166U, 165U, 164U, 163U, 162U, 160U, 159U, 158U, 157U, 156U, 155U, 154U, 152U, 151U, 150U, 149U, 148U, 146U, 145U, 144U, 143U, 141U, 140U, 139U, 138U, 137U, 135U, 134U, 133U, 132U, 130U, 129U, 128U, 127U, 125U, 124U, 123U, 122U, 121U, 119U, 118U, 117U, 116U, 115U, 113U, 112U, 111U, 110U, 109U, 108U, 106U, 105U, 104U, 103U, 102U, 101U, 100U, 99U, 98U, 97U, 96U, 95U, 94U, 93U, 92U, 91U, 90U, 89U, 88U, 87U, 86U, 85U, 84U, 83U, 82U, 82U, 81U, 80U, 79U, 78U, 78U, 77U, 76U, 76U, 75U, 74U, 74U, 73U, 72U, 72U, 71U, 71U, 70U, 70U, 69U, 69U, 68U, 68U, 67U, 67U, 67U, 66U, 66U, 66U, 65U, 65U, 65U, 65U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 63U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 65U, 65U, 65U, 65U, 66U, 66U, 66U, 67U, 67U, 67U, 68U, 68U, 69U, 69U, 70U, 70U, 71U, 71U, 72U, 72U, 73U, 74U, 74U, 75U, 76U, 76U, 77U, 78U, 78U, 79U, 80U, 81U, 82U, 82U, 83U, 84U, 85U, 86U, 87U, 88U, 89U, 90U, 91U, 92U, 93U, 94U, 95U, 96U, 97U, 98U, 99U, 100U, 101U, 102U, 103U, 104U, 105U, 106U, 108U, 109U, 110U, 111U, 112U, 113U, 115U, 116U, 117U, 118U, 119U, 121U, 122U, 123U, 124U, 125U, 127U, 128U, 129U, 130U, 132U, 133U }; + + // Init DAC + register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU); + register_set(&DAC1->CR, DAC_CR_TEN1 | (6U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU); + register_set_bits(&DAC1->CR, DAC_CR_EN1); + + // Setup DMAMUX (DAC_CH1_DMA as input) + register_set(&DMAMUX1_Channel1->CCR, 67U, DMAMUX_CxCR_DMAREQ_ID_Msk); + + // Setup DMA + register_set(&DMA1_Stream1->M0AR, (uint32_t) fake_siren_lut, 0xFFFFFFFFU); + register_set(&DMA1_Stream1->PAR, (uint32_t) &(DAC1->DHR8R1), 0xFFFFFFFFU); + DMA1_Stream1->NDTR = sizeof(fake_siren_lut); + register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U); + DMA1_Stream1->CR = (0b11UL << DMA_SxCR_PL_Pos); + DMA1_Stream1->CR |= DMA_SxCR_MINC | DMA_SxCR_CIRC | (1U << DMA_SxCR_DIR_Pos); + + // Init trigger timer (around 2.5kHz) + register_set(&TIM7->PSC, 0U, 0xFFFFU); + register_set(&TIM7->ARR, 133U, 0xFFFFU); + register_set(&TIM7->CR2, (0b10U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk); + register_set(&TIM7->CR1, TIM_CR1_ARPE | TIM_CR1_URS, 0x088EU); + TIM7->SR = 0U; + TIM7->CR1 |= TIM_CR1_CEN; + + // Enable the I2C to the codec + i2c_init(I2C5); + fake_siren_codec_enable(false); +} diff --git a/panda/board/drivers/fan.h b/panda/board/drivers/fan.h new file mode 100644 index 0000000000..f1041ce856 --- /dev/null +++ b/panda/board/drivers/fan.h @@ -0,0 +1,48 @@ +#include "fan_declarations.h" + +struct fan_state_t fan_state; + +static const uint8_t FAN_TICK_FREQ = 8U; + +void fan_set_power(uint8_t percentage) { + if (percentage > 0U) { + fan_state.power = CLAMP(percentage, 20U, 100U); + } else { + fan_state.power = 0U; + } +} + +void fan_init(void) { + fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ; + llfan_init(); +} + +// Call this at FAN_TICK_FREQ +void fan_tick(void) { + if (current_board->has_fan) { + // Measure fan RPM + uint16_t fan_rpm_fast = fan_state.tach_counter * (60U * FAN_TICK_FREQ / 4U); // 4 interrupts per rotation + fan_state.tach_counter = 0U; + fan_state.rpm = (fan_rpm_fast + (3U * fan_state.rpm)) / 4U; + + #ifdef DEBUG_FAN + puth(fan_state.target_rpm); + print(" "); puth(fan_rpm_fast); + print(" "); puth(fan_state.power); + print("\n"); + #endif + + // Cooldown counter to prevent noise on tachometer line. + if (fan_state.power > 0U) { + fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ; + } else { + if (fan_state.cooldown_counter > 0U) { + fan_state.cooldown_counter--; + } + } + + // Set PWM and enable line + pwm_set(TIM3, 3, fan_state.power); + current_board->set_fan_enabled((fan_state.power > 0U) || (fan_state.cooldown_counter > 0U)); + } +} diff --git a/panda/board/drivers/fan_declarations.h b/panda/board/drivers/fan_declarations.h new file mode 100644 index 0000000000..3dd3e7cfab --- /dev/null +++ b/panda/board/drivers/fan_declarations.h @@ -0,0 +1,16 @@ +#pragma once + +struct fan_state_t { + uint16_t tach_counter; + uint16_t rpm; + uint8_t power; + float error_integral; + uint8_t cooldown_counter; +}; +extern struct fan_state_t fan_state; + +void fan_set_power(uint8_t percentage); +void llfan_init(void); +void fan_init(void); +// Call this at FAN_TICK_FREQ +void fan_tick(void); diff --git a/panda/board/drivers/fdcan.h b/panda/board/drivers/fdcan.h new file mode 100644 index 0000000000..2aa64e97dc --- /dev/null +++ b/panda/board/drivers/fdcan.h @@ -0,0 +1,269 @@ +#include "fdcan_declarations.h" + +FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT] = {FDCAN1, FDCAN2, FDCAN3}; + +static bool can_set_speed(uint8_t can_number) { + bool ret = true; + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + + ret &= llcan_set_speed( + FDCANx, + bus_config[bus_number].can_speed, + bus_config[bus_number].can_data_speed, + bus_config[bus_number].canfd_non_iso, + can_loopback, + can_silent + ); + return ret; +} + +void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number) { + static uint32_t last_reset = 0U; + uint32_t time = microsecond_timer_get(); + + // Resetting CAN core is a slow blocking operation, limit frequency + if (get_ts_elapsed(time, last_reset) > 100000U) { // 10 Hz + can_health[can_number].can_core_reset_cnt += 1U; + can_health[can_number].total_tx_lost_cnt += (FDCAN_TX_FIFO_EL_CNT - (FDCANx->TXFQS & FDCAN_TXFQS_TFFL)); // TX FIFO msgs will be lost after reset + llcan_clear_send(FDCANx); + last_reset = time; + } +} + +void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) { + uint8_t can_irq_number[PANDA_CAN_CNT][2] = { + { FDCAN1_IT0_IRQn, FDCAN1_IT1_IRQn }, + { FDCAN2_IT0_IRQn, FDCAN2_IT1_IRQn }, + { FDCAN3_IT0_IRQn, FDCAN3_IT1_IRQn }, + }; + + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint32_t psr_reg = FDCANx->PSR; + uint32_t ecr_reg = FDCANx->ECR; + + can_health[can_number].bus_off = ((psr_reg & FDCAN_PSR_BO) >> FDCAN_PSR_BO_Pos); + can_health[can_number].bus_off_cnt += can_health[can_number].bus_off; + can_health[can_number].error_warning = ((psr_reg & FDCAN_PSR_EW) >> FDCAN_PSR_EW_Pos); + can_health[can_number].error_passive = ((psr_reg & FDCAN_PSR_EP) >> FDCAN_PSR_EP_Pos); + + can_health[can_number].last_error = ((psr_reg & FDCAN_PSR_LEC) >> FDCAN_PSR_LEC_Pos); + if ((can_health[can_number].last_error != 0U) && (can_health[can_number].last_error != 7U)) { + can_health[can_number].last_stored_error = can_health[can_number].last_error; + } + + can_health[can_number].last_data_error = ((psr_reg & FDCAN_PSR_DLEC) >> FDCAN_PSR_DLEC_Pos); + if ((can_health[can_number].last_data_error != 0U) && (can_health[can_number].last_data_error != 7U)) { + can_health[can_number].last_data_stored_error = can_health[can_number].last_data_error; + } + + can_health[can_number].receive_error_cnt = ((ecr_reg & FDCAN_ECR_REC) >> FDCAN_ECR_REC_Pos); + can_health[can_number].transmit_error_cnt = ((ecr_reg & FDCAN_ECR_TEC) >> FDCAN_ECR_TEC_Pos); + + can_health[can_number].irq0_call_rate = interrupts[can_irq_number[can_number][0]].call_rate; + can_health[can_number].irq1_call_rate = interrupts[can_irq_number[can_number][1]].call_rate; + + if (ir_reg != 0U) { + // Clear error interrupts + FDCANx->IR |= (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L); + can_health[can_number].total_error_cnt += 1U; + // Check for RX FIFO overflow + if ((ir_reg & (FDCAN_IR_RF0L)) != 0U) { + can_health[can_number].total_rx_lost_cnt += 1U; + } + // Cases: + // 1. while multiplexing between buses 1 and 3 we are getting ACK errors that overwhelm CAN core, by resetting it recovers faster + // 2. H7 gets stuck in bus off recovery state indefinitely + if ((((can_health[can_number].last_error == CAN_ACK_ERROR) || (can_health[can_number].last_data_error == CAN_ACK_ERROR)) && (can_health[can_number].transmit_error_cnt > 127U)) || + ((ir_reg & FDCAN_IR_BO) != 0U)) { + can_clear_send(FDCANx, can_number); + } + } +} + +// ***************************** CAN ***************************** +// FDFDCANx_IT1 IRQ Handler (TX) +void process_can(uint8_t can_number) { + if (can_number != 0xffU) { + ENTER_CRITICAL(); + + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + + FDCANx->IR |= FDCAN_IR_TFE; // Clear Tx FIFO Empty flag + + if ((FDCANx->TXFQS & FDCAN_TXFQS_TFQF) == 0U) { + CANPacket_t to_send; + if (can_pop(can_queues[bus_number], &to_send)) { + if (can_check_checksum(&to_send)) { + can_health[can_number].total_tx_cnt += 1U; + + uint32_t TxFIFOSA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET) + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE); + // get the index of the next TX FIFO element (0 to FDCAN_TX_FIFO_EL_CNT - 1) + uint32_t tx_index = (FDCANx->TXFQS >> FDCAN_TXFQS_TFQPI_Pos) & 0x1FU; + // only send if we have received a packet + canfd_fifo *fifo; + fifo = (canfd_fifo *)(TxFIFOSA + (tx_index * FDCAN_TX_FIFO_EL_SIZE)); + + fifo->header[0] = (to_send.extended << 30) | ((to_send.extended != 0U) ? (to_send.addr) : (to_send.addr << 18)); + + // If canfd_auto is set, outgoing packets will be automatically sent as CAN-FD if an incoming CAN-FD packet was seen + bool fd = bus_config[can_number].canfd_auto ? bus_config[can_number].canfd_enabled : (bool)(to_send.fd > 0U); + uint32_t canfd_enabled_header = fd ? (1UL << 21) : 0UL; + + uint32_t brs_enabled_header = bus_config[can_number].brs_enabled ? (1UL << 20) : 0UL; + fifo->header[1] = (to_send.data_len_code << 16) | canfd_enabled_header | brs_enabled_header; + + uint8_t data_len_w = (dlc_to_len[to_send.data_len_code] / 4U); + data_len_w += ((dlc_to_len[to_send.data_len_code] % 4U) > 0U) ? 1U : 0U; + for (unsigned int i = 0; i < data_len_w; i++) { + BYTE_ARRAY_TO_WORD(fifo->data_word[i], &to_send.data[i*4U]); + } + + FDCANx->TXBAR = (1UL << tx_index); + + // Send back to USB + CANPacket_t to_push; + + to_push.fd = fd; + to_push.returned = 1U; + to_push.rejected = 0U; + to_push.extended = to_send.extended; + to_push.addr = to_send.addr; + to_push.bus = bus_number; + to_push.data_len_code = to_send.data_len_code; + (void)memcpy(to_push.data, to_send.data, dlc_to_len[to_push.data_len_code]); + can_set_checksum(&to_push); + + rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U; + } else { + can_health[can_number].total_tx_checksum_error_cnt += 1U; + } + + refresh_can_tx_slots_available(); + } + } + EXIT_CRITICAL(); + } +} + +// FDFDCANx_IT0 IRQ Handler (RX and errors) +// blink blue when we are receiving CAN messages +void can_rx(uint8_t can_number) { + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + + uint32_t ir_reg = FDCANx->IR; + + // Clear all new messages from Rx FIFO 0 + FDCANx->IR |= FDCAN_IR_RF0N; + while ((FDCANx->RXF0S & FDCAN_RXF0S_F0FL) != 0U) { + can_health[can_number].total_rx_cnt += 1U; + // get the index of the next RX FIFO element (0 to FDCAN_RX_FIFO_0_EL_CNT - 1) + uint32_t rx_fifo_idx = (uint8_t)((FDCANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3FU); + + // Recommended to offset get index by at least +1 if RX FIFO is in overwrite mode and full (datasheet) + if ((FDCANx->RXF0S & FDCAN_RXF0S_F0F) == FDCAN_RXF0S_F0F) { + rx_fifo_idx = ((rx_fifo_idx + 1U) >= FDCAN_RX_FIFO_0_EL_CNT) ? 0U : (rx_fifo_idx + 1U); + can_health[can_number].total_rx_lost_cnt += 1U; // At least one message was lost + } + + uint32_t RxFIFO0SA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET); + CANPacket_t to_push; + canfd_fifo *fifo; + + // getting address + fifo = (canfd_fifo *)(RxFIFO0SA + (rx_fifo_idx * FDCAN_RX_FIFO_0_EL_SIZE)); + + bool canfd_frame = ((fifo->header[1] >> 21) & 0x1U); + bool brs_frame = ((fifo->header[1] >> 20) & 0x1U); + + to_push.fd = canfd_frame; + to_push.returned = 0U; + to_push.rejected = 0U; + to_push.extended = (fifo->header[0] >> 30) & 0x1U; + to_push.addr = ((to_push.extended != 0U) ? (fifo->header[0] & 0x1FFFFFFFU) : ((fifo->header[0] >> 18) & 0x7FFU)); + to_push.bus = bus_number; + to_push.data_len_code = ((fifo->header[1] >> 16) & 0xFU); + + uint8_t data_len_w = (dlc_to_len[to_push.data_len_code] / 4U); + data_len_w += ((dlc_to_len[to_push.data_len_code] % 4U) > 0U) ? 1U : 0U; + for (unsigned int i = 0; i < data_len_w; i++) { + WORD_TO_BYTE_ARRAY(&to_push.data[i*4U], fifo->data_word[i]); + } + can_set_checksum(&to_push); + + // forwarding (panda only) + int bus_fwd_num = safety_fwd_hook(bus_number, to_push.addr); + if (bus_fwd_num < 0) { + bus_fwd_num = bus_config[can_number].forwarding_bus; + } + if (bus_fwd_num != -1) { + CANPacket_t to_send; + + to_send.fd = to_push.fd; + to_send.returned = 0U; + to_send.rejected = 0U; + to_send.extended = to_push.extended; + to_send.addr = to_push.addr; + to_send.bus = to_push.bus; + to_send.data_len_code = to_push.data_len_code; + (void)memcpy(to_send.data, to_push.data, dlc_to_len[to_push.data_len_code]); + can_set_checksum(&to_send); + + can_send(&to_send, bus_fwd_num, true); + can_health[can_number].total_fwd_cnt += 1U; + } + + safety_rx_invalid += safety_rx_hook(&to_push) ? 0U : 1U; + ignition_can_hook(&to_push); + + led_set(LED_BLUE, true); + rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U; + + // Enable CAN FD and BRS if CAN FD message was received + if (!(bus_config[can_number].canfd_enabled) && (canfd_frame)) { + bus_config[can_number].canfd_enabled = true; + } + if (!(bus_config[can_number].brs_enabled) && (brs_frame)) { + bus_config[can_number].brs_enabled = true; + } + + // update read index + FDCANx->RXF0A = rx_fifo_idx; + } + + // Error handling + if ((ir_reg & (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L)) != 0U) { + update_can_health_pkt(can_number, ir_reg); + } +} + +static void FDCAN1_IT0_IRQ_Handler(void) { can_rx(0); } +static void FDCAN1_IT1_IRQ_Handler(void) { process_can(0); } + +static void FDCAN2_IT0_IRQ_Handler(void) { can_rx(1); } +static void FDCAN2_IT1_IRQ_Handler(void) { process_can(1); } + +static void FDCAN3_IT0_IRQ_Handler(void) { can_rx(2); } +static void FDCAN3_IT1_IRQ_Handler(void) { process_can(2); } + +bool can_init(uint8_t can_number) { + bool ret = false; + + REGISTER_INTERRUPT(FDCAN1_IT0_IRQn, FDCAN1_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1) + REGISTER_INTERRUPT(FDCAN1_IT1_IRQn, FDCAN1_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1) + REGISTER_INTERRUPT(FDCAN2_IT0_IRQn, FDCAN2_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2) + REGISTER_INTERRUPT(FDCAN2_IT1_IRQn, FDCAN2_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2) + REGISTER_INTERRUPT(FDCAN3_IT0_IRQn, FDCAN3_IT0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3) + REGISTER_INTERRUPT(FDCAN3_IT1_IRQn, FDCAN3_IT1_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3) + + if (can_number != 0xffU) { + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); + ret &= can_set_speed(can_number); + ret &= llcan_init(FDCANx); + // in case there are queued up messages + process_can(can_number); + } + return ret; +} diff --git a/panda/board/drivers/fdcan_declarations.h b/panda/board/drivers/fdcan_declarations.h new file mode 100644 index 0000000000..c77d1e3138 --- /dev/null +++ b/panda/board/drivers/fdcan_declarations.h @@ -0,0 +1,19 @@ +#pragma once + +#include "board/can.h" + +typedef struct { + volatile uint32_t header[2]; + volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U]; +} canfd_fifo; + +extern FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT]; + +#define CAN_ACK_ERROR 3U + +void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number); +void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg); + +void process_can(uint8_t can_number); +void can_rx(uint8_t can_number); +bool can_init(uint8_t can_number); diff --git a/panda/board/drivers/gpio.h b/panda/board/drivers/gpio.h new file mode 100644 index 0000000000..aea604254e --- /dev/null +++ b/panda/board/drivers/gpio.h @@ -0,0 +1,94 @@ +#define MODE_INPUT 0 +#define MODE_OUTPUT 1 +#define MODE_ALTERNATE 2 +#define MODE_ANALOG 3 + +#define PULL_NONE 0 +#define PULL_UP 1 +#define PULL_DOWN 2 + +#define OUTPUT_TYPE_PUSH_PULL 0U +#define OUTPUT_TYPE_OPEN_DRAIN 1U + +void set_gpio_mode(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) { + ENTER_CRITICAL(); + uint32_t tmp = GPIO->MODER; + tmp &= ~(3U << (pin * 2U)); + tmp |= (mode << (pin * 2U)); + register_set(&(GPIO->MODER), tmp, 0xFFFFFFFFU); + EXIT_CRITICAL(); +} + +void set_gpio_output(GPIO_TypeDef *GPIO, unsigned int pin, bool enabled) { + ENTER_CRITICAL(); + if (enabled) { + register_set_bits(&(GPIO->ODR), (1UL << pin)); + } else { + register_clear_bits(&(GPIO->ODR), (1UL << pin)); + } + set_gpio_mode(GPIO, pin, MODE_OUTPUT); + EXIT_CRITICAL(); +} + +void set_gpio_output_type(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int output_type){ + ENTER_CRITICAL(); + if(output_type == OUTPUT_TYPE_OPEN_DRAIN) { + register_set_bits(&(GPIO->OTYPER), (1UL << pin)); + } else { + register_clear_bits(&(GPIO->OTYPER), (1U << pin)); + } + EXIT_CRITICAL(); +} + +void set_gpio_alternate(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) { + ENTER_CRITICAL(); + uint32_t tmp = GPIO->AFR[pin >> 3U]; + tmp &= ~(0xFU << ((pin & 7U) * 4U)); + tmp |= mode << ((pin & 7U) * 4U); + register_set(&(GPIO->AFR[pin >> 3]), tmp, 0xFFFFFFFFU); + set_gpio_mode(GPIO, pin, MODE_ALTERNATE); + EXIT_CRITICAL(); +} + +void set_gpio_pullup(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) { + ENTER_CRITICAL(); + uint32_t tmp = GPIO->PUPDR; + tmp &= ~(3U << (pin * 2U)); + tmp |= (mode << (pin * 2U)); + register_set(&(GPIO->PUPDR), tmp, 0xFFFFFFFFU); + EXIT_CRITICAL(); +} + +int get_gpio_input(const GPIO_TypeDef *GPIO, unsigned int pin) { + return (GPIO->IDR & (1UL << pin)) == (1UL << pin); +} + +#ifdef PANDA_JUNGLE +typedef struct { + GPIO_TypeDef * const bank; + uint8_t pin; +} gpio_t; + +void gpio_set_all_output(gpio_t *pins, uint8_t num_pins, bool enabled) { + for (uint8_t i = 0; i < num_pins; i++) { + set_gpio_output(pins[i].bank, pins[i].pin, enabled); + } +} + +void gpio_set_bitmask(gpio_t *pins, uint8_t num_pins, uint32_t bitmask) { + for (uint8_t i = 0; i < num_pins; i++) { + set_gpio_output(pins[i].bank, pins[i].pin, (bitmask >> i) & 1U); + } +} +#endif + +// Detection with internal pullup +#define PULL_EFFECTIVE_DELAY 4096 +bool detect_with_pull(GPIO_TypeDef *GPIO, int pin, int mode) { + set_gpio_mode(GPIO, pin, MODE_INPUT); + set_gpio_pullup(GPIO, pin, mode); + for (volatile int i=0; iharness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !ignition_relay); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay); + } else { + set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !ignition_relay); + } + + if (!(drive_relay || ignition_relay)) { + harness.relay_driven = false; + } +} + +bool harness_check_ignition(void) { + bool ret = false; + + // wait until we're not reading the analog voltages anymore + while (harness.sbu_adc_lock) {} + + switch(harness.status){ + case HARNESS_STATUS_NORMAL: + ret = !get_gpio_input(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1); + break; + case HARNESS_STATUS_FLIPPED: + ret = !get_gpio_input(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2); + break; + default: + break; + } + return ret; +} + +static uint8_t harness_detect_orientation(void) { + uint8_t ret = harness.status; + + #ifndef BOOTSTUB + // We can't detect orientation if the relay is being driven + if (!harness.relay_driven) { + harness.sbu_adc_lock = true; + set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_ANALOG); + set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_ANALOG); + + harness.sbu1_voltage_mV = adc_get_mV(¤t_board->harness_config->adc_signal_SBU1); + harness.sbu2_voltage_mV = adc_get_mV(¤t_board->harness_config->adc_signal_SBU2); + uint16_t detection_threshold = current_board->avdd_mV / 2U; + + // Detect connection and orientation + if((harness.sbu1_voltage_mV < detection_threshold) || (harness.sbu2_voltage_mV < detection_threshold)){ + if (harness.sbu1_voltage_mV < harness.sbu2_voltage_mV) { + // orientation flipped (PANDA_SBU1->HARNESS_SBU1(relay), PANDA_SBU2->HARNESS_SBU2(ign)) + ret = HARNESS_STATUS_FLIPPED; + } else { + // orientation normal (PANDA_SBU2->HARNESS_SBU1(relay), PANDA_SBU1->HARNESS_SBU2(ign)) + // (SBU1->SBU2 is the normal orientation connection per USB-C cable spec) + ret = HARNESS_STATUS_NORMAL; + } + } else { + ret = HARNESS_STATUS_NC; + } + + // Pins are not 5V tolerant in ADC mode + set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_INPUT); + set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_INPUT); + harness.sbu_adc_lock = false; + } + #endif + + return ret; +} + +void harness_tick(void) { + harness.status = harness_detect_orientation(); +} + +void harness_init(void) { + // init OBD_SBUx_RELAY + set_gpio_output_type(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_output_type(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, OUTPUT_TYPE_OPEN_DRAIN); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, 1); + set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, 1); + + // detect initial orientation + harness.status = harness_detect_orientation(); + + // keep buses connected by default + set_intercept_relay(false, false); +} diff --git a/panda/board/drivers/harness_declarations.h b/panda/board/drivers/harness_declarations.h new file mode 100644 index 0000000000..6f4327aad9 --- /dev/null +++ b/panda/board/drivers/harness_declarations.h @@ -0,0 +1,33 @@ +#pragma once + +#define HARNESS_STATUS_NC 0U +#define HARNESS_STATUS_NORMAL 1U +#define HARNESS_STATUS_FLIPPED 2U + +struct harness_t { + uint8_t status; + uint16_t sbu1_voltage_mV; + uint16_t sbu2_voltage_mV; + bool relay_driven; + bool sbu_adc_lock; +}; +extern struct harness_t harness; + +struct harness_configuration { + GPIO_TypeDef * const GPIO_SBU1; + GPIO_TypeDef * const GPIO_SBU2; + GPIO_TypeDef * const GPIO_relay_SBU1; + GPIO_TypeDef * const GPIO_relay_SBU2; + const uint8_t pin_SBU1; + const uint8_t pin_SBU2; + const uint8_t pin_relay_SBU1; + const uint8_t pin_relay_SBU2; + const adc_signal_t adc_signal_SBU1; + const adc_signal_t adc_signal_SBU2; +}; + +// The ignition relay is only used for testing purposes +void set_intercept_relay(bool intercept, bool ignition_relay); +bool harness_check_ignition(void); +void harness_tick(void); +void harness_init(void); diff --git a/panda/board/drivers/interrupts.h b/panda/board/drivers/interrupts.h new file mode 100644 index 0000000000..1188a8ec07 --- /dev/null +++ b/panda/board/drivers/interrupts.h @@ -0,0 +1,81 @@ +#include "interrupts_declarations.h" + +void unused_interrupt_handler(void) { + // Something is wrong if this handler is called! + print("Unused interrupt handler called!\n"); + fault_occurred(FAULT_UNUSED_INTERRUPT_HANDLED); +} + +interrupt interrupts[NUM_INTERRUPTS]; + +static bool check_interrupt_rate = false; + +static uint32_t idle_time = 0U; +static uint32_t busy_time = 0U; +float interrupt_load = 0.0f; + +void handle_interrupt(IRQn_Type irq_type){ + static uint8_t interrupt_depth = 0U; + static uint32_t last_time = 0U; + ENTER_CRITICAL(); + if (interrupt_depth == 0U) { + uint32_t time = microsecond_timer_get(); + idle_time += get_ts_elapsed(time, last_time); + last_time = time; + } + interrupt_depth += 1U; + EXIT_CRITICAL(); + + interrupts[irq_type].call_counter++; + interrupts[irq_type].handler(); + + // Check that the interrupts don't fire too often + if (check_interrupt_rate && (interrupts[irq_type].call_counter > interrupts[irq_type].max_call_rate)) { + fault_occurred(interrupts[irq_type].call_rate_fault); + } + + ENTER_CRITICAL(); + interrupt_depth -= 1U; + if (interrupt_depth == 0U) { + uint32_t time = microsecond_timer_get(); + busy_time += get_ts_elapsed(time, last_time); + last_time = time; + } + EXIT_CRITICAL(); +} + +// Every second +void interrupt_timer_handler(void) { + if (INTERRUPT_TIMER->SR != 0U) { + for (uint16_t i = 0U; i < NUM_INTERRUPTS; i++) { + // Log IRQ call rate faults + if (check_interrupt_rate && (interrupts[i].call_counter > interrupts[i].max_call_rate)) { + print("Interrupt 0x"); puth(i); print(" fired too often (0x"); puth(interrupts[i].call_counter); print("/s)!\n"); + } + + // Reset interrupt counters + interrupts[i].call_rate = interrupts[i].call_counter; + interrupts[i].call_counter = 0U; + } + + // Calculate interrupt load + // The bootstub does not have the FPU enabled, so can't do float operations. +#if !defined(BOOTSTUB) + interrupt_load = ((busy_time + idle_time) > 0U) ? ((float) (((float) busy_time) / (busy_time + idle_time))) : 0.0f; +#endif + idle_time = 0U; + busy_time = 0U; + } + INTERRUPT_TIMER->SR = 0; +} + +void init_interrupts(bool check_rate_limit){ + check_interrupt_rate = check_rate_limit; + + for(uint16_t i=0U; iled_pwm_channels[color] != 0U) { + pwm_set(TIM3, current_board->led_pwm_channels[color], 100U - (enabled ? LED_PWM_POWER : 0U)); + } else { + set_gpio_output(current_board->led_GPIO[color], current_board->led_pin[color], !enabled); + } + } +} + +void led_init(void) { + for (uint8_t i = 0U; i<3U; i++){ + set_gpio_pullup(current_board->led_GPIO[i], current_board->led_pin[i], PULL_NONE); + set_gpio_output_type(current_board->led_GPIO[i], current_board->led_pin[i], OUTPUT_TYPE_OPEN_DRAIN); + + if (current_board->led_pwm_channels[i] != 0U) { + set_gpio_alternate(current_board->led_GPIO[i], current_board->led_pin[i], GPIO_AF2_TIM3); + pwm_init(TIM3, current_board->led_pwm_channels[i]); + } else { + set_gpio_mode(current_board->led_GPIO[i], current_board->led_pin[i], MODE_OUTPUT); + } + + led_set(i, false); + } +} diff --git a/panda/board/drivers/pwm.h b/panda/board/drivers/pwm.h new file mode 100644 index 0000000000..3d0d73efdc --- /dev/null +++ b/panda/board/drivers/pwm.h @@ -0,0 +1,56 @@ +#define PWM_COUNTER_OVERFLOW 4800U // To get ~25kHz + +// TODO: Implement for 32-bit timers + +void pwm_init(TIM_TypeDef *TIM, uint8_t channel){ + // Enable timer and auto-reload + register_set(&(TIM->CR1), TIM_CR1_CEN | TIM_CR1_ARPE, 0x3FU); + + // Set channel as PWM mode 1 and enable output + switch(channel){ + case 1U: + register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC1E); + break; + case 2U: + register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC2E); + break; + case 3U: + register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC3E); + break; + case 4U: + register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE)); + register_set_bits(&(TIM->CCER), TIM_CCER_CC4E); + break; + default: + break; + } + + // Set max counter value + register_set(&(TIM->ARR), PWM_COUNTER_OVERFLOW, 0xFFFFU); + + // Update registers and clear counter + TIM->EGR |= TIM_EGR_UG; +} + +void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage){ + uint16_t comp_value = (((uint16_t) percentage * PWM_COUNTER_OVERFLOW) / 100U); + switch(channel){ + case 1U: + register_set(&(TIM->CCR1), comp_value, 0xFFFFU); + break; + case 2U: + register_set(&(TIM->CCR2), comp_value, 0xFFFFU); + break; + case 3U: + register_set(&(TIM->CCR3), comp_value, 0xFFFFU); + break; + case 4U: + register_set(&(TIM->CCR4), comp_value, 0xFFFFU); + break; + default: + break; + } +} diff --git a/panda/board/drivers/registers.h b/panda/board/drivers/registers.h new file mode 100644 index 0000000000..ce4be14a92 --- /dev/null +++ b/panda/board/drivers/registers.h @@ -0,0 +1,68 @@ +#include "registers_declarations.h" + +static reg register_map[REGISTER_MAP_SIZE]; + +// Hash spread in first and second iterations seems to be reasonable. +// See: tests/development/register_hashmap_spread.py +// Also, check the collision warnings in the debug output, and minimize those. +static uint16_t hash_addr(uint32_t input){ + return (((input >> 16U) ^ ((((input + 1U) & 0xFFFFU) * HASHING_PRIME) & 0xFFFFU)) & REGISTER_MAP_SIZE); +} + +// Do not put bits in the check mask that get changed by the hardware +void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask){ + ENTER_CRITICAL() + // Set bits in register that are also in the mask + (*addr) = ((*addr) & (~mask)) | (val & mask); + + // Add these values to the map + uint16_t hash = hash_addr((uint32_t) addr); + uint16_t tries = REGISTER_MAP_SIZE; + while(CHECK_COLLISION(hash, addr) && (tries > 0U)) { hash = hash_addr((uint32_t) hash); tries--;} + if (tries != 0U){ + register_map[hash].address = addr; + register_map[hash].value = (register_map[hash].value & (~mask)) | (val & mask); + register_map[hash].check_mask |= mask; + } else { + #ifdef DEBUG_FAULTS + print("Hash collision: address 0x"); puth((uint32_t) addr); print("!\n"); + #endif + } + EXIT_CRITICAL() +} + +// Set individual bits. Also add them to the check_mask. +// Do not use this to change bits that get reset by the hardware +void register_set_bits(volatile uint32_t *addr, uint32_t val) { + register_set(addr, val, val); +} + +// Clear individual bits. Also add them to the check_mask. +// Do not use this to clear bits that get set by the hardware +void register_clear_bits(volatile uint32_t *addr, uint32_t val) { + register_set(addr, (~val), val); +} + +// To be called periodically +void check_registers(void){ + for(uint16_t i=0U; i wd_state.threshold) { + print("WD timeout 0x"); puth(et); print("\n"); + fault_occurred(wd_state.fault); + } + + wd_state.last_ts = ts; +} + +void simple_watchdog_init(uint32_t fault, uint32_t threshold) { + wd_state.fault = fault; + wd_state.threshold = threshold; + wd_state.last_ts = microsecond_timer_get(); +} diff --git a/panda/board/drivers/simple_watchdog_declarations.h b/panda/board/drivers/simple_watchdog_declarations.h new file mode 100644 index 0000000000..2bda71590b --- /dev/null +++ b/panda/board/drivers/simple_watchdog_declarations.h @@ -0,0 +1,10 @@ +#pragma once + +typedef struct simple_watchdog_state_t { + uint32_t fault; + uint32_t last_ts; + uint32_t threshold; +} simple_watchdog_state_t; + +void simple_watchdog_kick(void); +void simple_watchdog_init(uint32_t fault, uint32_t threshold); diff --git a/panda/board/drivers/spi.h b/panda/board/drivers/spi.h new file mode 100644 index 0000000000..d291fe06a8 --- /dev/null +++ b/panda/board/drivers/spi.h @@ -0,0 +1,230 @@ +#pragma once + +#include "board/drivers/spi_declarations.h" +#include "board/crc.h" + +uint8_t spi_buf_rx[SPI_BUF_SIZE]; +uint8_t spi_buf_tx[SPI_BUF_SIZE]; + +uint16_t spi_error_count = 0; + +static uint8_t spi_state = SPI_STATE_HEADER; +static uint16_t spi_data_len_mosi; +static bool spi_can_tx_ready = false; +static const unsigned char version_text[] = "VERSION"; + +static uint16_t spi_version_packet(uint8_t *out) { + // this protocol version request is a stable portion of + // the panda's SPI protocol. its contents match that of the + // panda USB descriptors and are sufficent to list/enumerate + // a panda, determine panda type, and bootstub status. + + // the response is: + // VERSION + 2 byte data length + data + CRC8 + + // echo "VERSION" + (void)memcpy(out, version_text, 7); + + // write response + uint16_t data_len = 0; + uint16_t data_pos = 7U + 2U; + + // write serial + (void)memcpy(&out[data_pos], ((uint8_t *)UID_BASE), 12); + data_len += 12U; + + // HW type + out[data_pos + data_len] = hw_type; + data_len += 1U; + + // bootstub + out[data_pos + data_len] = USB_PID & 0xFFU; + data_len += 1U; + + // SPI protocol version + out[data_pos + data_len] = 0x2; + data_len += 1U; + + // data length + out[7] = data_len & 0xFFU; + out[8] = (data_len >> 8) & 0xFFU; + + // CRC8 + uint16_t resp_len = data_pos + data_len; + out[resp_len] = crc_checksum(out, resp_len, 0xD5U); + resp_len += 1U; + + return resp_len; +} + +void spi_init(void) { + // platform init + llspi_init(); + + // Start the first packet! + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); +} + +static bool validate_checksum(const uint8_t *data, uint16_t len) { + // TODO: can speed this up by casting the bulk to uint32_t and xor-ing the bytes afterwards + uint8_t checksum = SPI_CHECKSUM_START; + for(uint16_t i = 0U; i < len; i++){ + checksum ^= data[i]; + } + return checksum == 0U; +} + +void spi_rx_done(void) { + uint16_t response_len = 0U; + uint8_t next_rx_state = SPI_STATE_HEADER_NACK; + bool checksum_valid = false; + static uint8_t spi_endpoint; + static uint16_t spi_data_len_miso; + + // parse header + spi_endpoint = spi_buf_rx[1]; + spi_data_len_mosi = (spi_buf_rx[3] << 8) | spi_buf_rx[2]; + spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; + + if (memcmp(spi_buf_rx, version_text, 7) == 0) { + response_len = spi_version_packet(spi_buf_tx); + next_rx_state = SPI_STATE_HEADER_NACK;; + } else if (spi_state == SPI_STATE_HEADER) { + checksum_valid = validate_checksum(spi_buf_rx, SPI_HEADER_SIZE); + if ((spi_buf_rx[0] == SPI_SYNC_BYTE) && checksum_valid) { + // response: ACK and start receiving data portion + spi_buf_tx[0] = SPI_HACK; + next_rx_state = SPI_STATE_HEADER_ACK; + response_len = 1U; + } else { + // response: NACK and reset state machine + #ifdef DEBUG_SPI + print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); + #endif + spi_buf_tx[0] = SPI_NACK; + next_rx_state = SPI_STATE_HEADER_NACK; + response_len = 1U; + } + } else if (spi_state == SPI_STATE_DATA_RX) { + // We got everything! Based on the endpoint specified, call the appropriate handler + bool response_ack = false; + checksum_valid = validate_checksum(&(spi_buf_rx[SPI_HEADER_SIZE]), spi_data_len_mosi + 1U); + if (checksum_valid) { + if (spi_endpoint == 0U) { + if (spi_data_len_mosi >= sizeof(ControlPacket_t)) { + ControlPacket_t ctrl = {0}; + (void)memcpy((uint8_t*)&ctrl, &spi_buf_rx[SPI_HEADER_SIZE], sizeof(ControlPacket_t)); + response_len = comms_control_handler(&ctrl, &spi_buf_tx[3]); + response_ack = true; + } else { + print("SPI: insufficient data for control handler\n"); + } + } else if ((spi_endpoint == 1U) || (spi_endpoint == 0x81U)) { + if (spi_data_len_mosi == 0U) { + response_len = comms_can_read(&(spi_buf_tx[3]), spi_data_len_miso); + response_ack = true; + } else { + print("SPI: did not expect data for can_read\n"); + } + } else if (spi_endpoint == 2U) { + comms_endpoint2_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); + response_ack = true; + } else if (spi_endpoint == 3U) { + if (spi_data_len_mosi > 0U) { + if (spi_can_tx_ready) { + spi_can_tx_ready = false; + comms_can_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); + response_ack = true; + } else { + response_ack = false; + print("SPI: CAN NACK\n"); + } + } else { + print("SPI: did expect data for can_write\n"); + } + } else if (spi_endpoint == 0xABU) { + // test endpoint: mimics panda -> device transfer + response_len = spi_data_len_miso; + response_ack = true; + } else if (spi_endpoint == 0xACU) { + // test endpoint: mimics device -> panda transfer (with NACK) + response_ack = false; + } else { + print("SPI: unexpected endpoint"); puth(spi_endpoint); print("\n"); + } + } else { + // Checksum was incorrect + response_ack = false; + #ifdef DEBUG_SPI + print("- incorrect data checksum "); + puth4(spi_data_len_mosi); + print("\n"); + hexdump(spi_buf_rx, SPI_HEADER_SIZE); + hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); + print("\n"); + #endif + } + + if (!response_ack) { + spi_buf_tx[0] = SPI_NACK; + next_rx_state = SPI_STATE_HEADER_NACK; + response_len = 1U; + } else { + // Setup response header + spi_buf_tx[0] = SPI_DACK; + spi_buf_tx[1] = response_len & 0xFFU; + spi_buf_tx[2] = (response_len >> 8) & 0xFFU; + + // Add checksum + uint8_t checksum = SPI_CHECKSUM_START; + for(uint16_t i = 0U; i < (response_len + 3U); i++) { + checksum ^= spi_buf_tx[i]; + } + spi_buf_tx[response_len + 3U] = checksum; + response_len += 4U; + + next_rx_state = SPI_STATE_DATA_TX; + } + } else { + print("SPI: RX unexpected state: "); puth(spi_state); print("\n"); + } + + // send out response + if (response_len == 0U) { + print("SPI: no response\n"); + spi_buf_tx[0] = SPI_NACK; + spi_state = SPI_STATE_HEADER_NACK; + response_len = 1U; + } + llspi_miso_dma(spi_buf_tx, response_len); + + spi_state = next_rx_state; + if (!checksum_valid) { + spi_error_count += 1U; + } +} + +void spi_tx_done(bool reset) { + if ((spi_state == SPI_STATE_HEADER_NACK) || reset) { + // Reset state + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + } else if (spi_state == SPI_STATE_HEADER_ACK) { + // ACK was sent, queue up the RX buf for the data + checksum + spi_state = SPI_STATE_DATA_RX; + llspi_mosi_dma(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi + 1U); + } else if (spi_state == SPI_STATE_DATA_TX) { + // Reset state + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + } else { + spi_state = SPI_STATE_HEADER; + llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + print("SPI: TX unexpected state: "); puth(spi_state); print("\n"); + } +} + +void can_tx_comms_resume_spi(void) { + spi_can_tx_ready = true; +} diff --git a/panda/board/drivers/spi_declarations.h b/panda/board/drivers/spi_declarations.h new file mode 100644 index 0000000000..23254f0e87 --- /dev/null +++ b/panda/board/drivers/spi_declarations.h @@ -0,0 +1,44 @@ +#pragma once + +#include "board/crc.h" + +#define SPI_TIMEOUT_US 10000U + +// got max rate from hitting a non-existent endpoint +// in a tight loop, plus some buffer +#define SPI_IRQ_RATE 16000U + +#define SPI_BUF_SIZE 4096U +// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2 +__attribute__((section(".sram12"))) extern uint8_t spi_buf_rx[SPI_BUF_SIZE]; +__attribute__((section(".sram12"))) extern uint8_t spi_buf_tx[SPI_BUF_SIZE]; + +#define SPI_CHECKSUM_START 0xABU +#define SPI_SYNC_BYTE 0x5AU +#define SPI_HACK 0x79U +#define SPI_DACK 0x85U +#define SPI_NACK 0x1FU + +// SPI states +enum { + SPI_STATE_HEADER, + SPI_STATE_HEADER_ACK, + SPI_STATE_HEADER_NACK, + SPI_STATE_DATA_RX, + SPI_STATE_DATA_RX_ACK, + SPI_STATE_DATA_TX +}; + +extern uint16_t spi_error_count; + +#define SPI_HEADER_SIZE 7U + +// low level SPI prototypes +void llspi_init(void); +void llspi_mosi_dma(uint8_t *addr, int len); +void llspi_miso_dma(uint8_t *addr, int len); + +void can_tx_comms_resume_spi(void); +void spi_init(void); +void spi_rx_done(void); +void spi_tx_done(bool reset); diff --git a/panda/board/drivers/timers.h b/panda/board/drivers/timers.h new file mode 100644 index 0000000000..4c046a2b49 --- /dev/null +++ b/panda/board/drivers/timers.h @@ -0,0 +1,31 @@ +static void timer_init(TIM_TypeDef *TIM, int psc) { + register_set(&(TIM->PSC), (psc-1), 0xFFFFU); + register_set(&(TIM->DIER), TIM_DIER_UIE, 0x5F5FU); + register_set(&(TIM->CR1), TIM_CR1_CEN, 0x3FU); + TIM->SR = 0; +} + +void microsecond_timer_init(void) { + MICROSECOND_TIMER->PSC = (APB1_TIMER_FREQ - 1U); + MICROSECOND_TIMER->CR1 = TIM_CR1_CEN; + MICROSECOND_TIMER->EGR = TIM_EGR_UG; +} + +uint32_t microsecond_timer_get(void) { + return MICROSECOND_TIMER->CNT; +} + +void interrupt_timer_init(void) { + enable_interrupt_timer(); + REGISTER_INTERRUPT(INTERRUPT_TIMER_IRQ, interrupt_timer_handler, 2U, FAULT_INTERRUPT_RATE_INTERRUPTS) + register_set(&(INTERRUPT_TIMER->PSC), ((uint16_t)(15.25*APB1_TIMER_FREQ)-1U), 0xFFFFU); + register_set(&(INTERRUPT_TIMER->DIER), TIM_DIER_UIE, 0x5F5FU); + register_set(&(INTERRUPT_TIMER->CR1), TIM_CR1_CEN, 0x3FU); + INTERRUPT_TIMER->SR = 0; + NVIC_EnableIRQ(INTERRUPT_TIMER_IRQ); +} + +void tick_timer_init(void) { + timer_init(TICK_TIMER, (uint16_t)((15.25*APB2_TIMER_FREQ)/8U)); + NVIC_EnableIRQ(TICK_TIMER_IRQ); +} diff --git a/panda/board/drivers/uart.h b/panda/board/drivers/uart.h new file mode 100644 index 0000000000..aeacf84b85 --- /dev/null +++ b/panda/board/drivers/uart.h @@ -0,0 +1,149 @@ +#include "uart_declarations.h" + +// ***************************** Definitions ***************************** + +#define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, overwrite_mode) \ + static uint8_t elems_rx_##x[size_rx]; \ + static uint8_t elems_tx_##x[size_tx]; \ + extern uart_ring uart_ring_##x; \ + uart_ring uart_ring_##x = { \ + .w_ptr_tx = 0, \ + .r_ptr_tx = 0, \ + .elems_tx = ((uint8_t *)&(elems_tx_##x)), \ + .tx_fifo_size = (size_tx), \ + .w_ptr_rx = 0, \ + .r_ptr_rx = 0, \ + .elems_rx = ((uint8_t *)&(elems_rx_##x)), \ + .rx_fifo_size = (size_rx), \ + .uart = (uart_ptr), \ + .callback = (callback_ptr), \ + .overwrite = (overwrite_mode) \ + }; + +// ******************************** UART buffers ******************************** + +// debug = USART2 +UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, true) + +// SOM debug = UART7 +UART_BUFFER(som_debug, FIFO_SIZE_INT, FIFO_SIZE_INT, UART7, NULL, true) + +uart_ring *get_ring_by_number(int a) { + uart_ring *ring = NULL; + switch(a) { + case 0: + ring = &uart_ring_debug; + break; + case 4: + ring = &uart_ring_som_debug; + break; + default: + ring = NULL; + break; + } + return ring; +} + +// ************************* Low-level buffer functions ************************* +bool get_char(uart_ring *q, char *elem) { + bool ret = false; + + ENTER_CRITICAL(); + if (q->w_ptr_rx != q->r_ptr_rx) { + if (elem != NULL) *elem = q->elems_rx[q->r_ptr_rx]; + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; + ret = true; + } + EXIT_CRITICAL(); + + return ret; +} + +bool injectc(uart_ring *q, char elem) { + int ret = false; + uint16_t next_w_ptr; + + ENTER_CRITICAL(); + next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size; + + if ((next_w_ptr == q->r_ptr_rx) && q->overwrite) { + // overwrite mode: drop oldest byte + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; + } + + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = elem; + q->w_ptr_rx = next_w_ptr; + ret = true; + } + EXIT_CRITICAL(); + + return ret; +} + +bool put_char(uart_ring *q, char elem) { + bool ret = false; + uint16_t next_w_ptr; + + ENTER_CRITICAL(); + next_w_ptr = (q->w_ptr_tx + 1U) % q->tx_fifo_size; + + if ((next_w_ptr == q->r_ptr_tx) && q->overwrite) { + // overwrite mode: drop oldest byte + q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; + } + + if (next_w_ptr != q->r_ptr_tx) { + q->elems_tx[q->w_ptr_tx] = elem; + q->w_ptr_tx = next_w_ptr; + ret = true; + } + EXIT_CRITICAL(); + + uart_tx_ring(q); + + return ret; +} + +// ************************ High-level debug functions ********************** +void putch(const char a) { + // misra-c2012-17.7: serial debug function, ok to ignore output + (void)injectc(&uart_ring_debug, a); +} + +void print(const char *a) { + for (const char *in = a; *in; in++) { + if (*in == '\n') putch('\r'); + putch(*in); + } +} + +void puthx(uint32_t i, uint8_t len) { + const char c[] = "0123456789abcdef"; + for (int pos = ((int)len * 4) - 4; pos > -4; pos -= 4) { + putch(c[(i >> (unsigned int)(pos)) & 0xFU]); + } +} + +void puth(unsigned int i) { + puthx(i, 8U); +} + +#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG) +static void puth4(unsigned int i) { + puthx(i, 4U); +} +#endif + +#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS) +static void hexdump(const void *a, int l) { + if (a != NULL) { + for (int i=0; i < l; i++) { + if ((i != 0) && ((i & 0xf) == 0)) print("\n"); + puthx(((const unsigned char*)a)[i], 2U); + print(" "); + } + } + print("\n"); +} +#endif diff --git a/panda/board/drivers/uart_declarations.h b/panda/board/drivers/uart_declarations.h new file mode 100644 index 0000000000..14ec26110f --- /dev/null +++ b/panda/board/drivers/uart_declarations.h @@ -0,0 +1,39 @@ +#pragma once + +// ***************************** Definitions ***************************** +#define FIFO_SIZE_INT 0x400U + +typedef struct uart_ring { + volatile uint16_t w_ptr_tx; + volatile uint16_t r_ptr_tx; + uint8_t *elems_tx; + uint32_t tx_fifo_size; + volatile uint16_t w_ptr_rx; + volatile uint16_t r_ptr_rx; + uint8_t *elems_rx; + uint32_t rx_fifo_size; + USART_TypeDef *uart; + void (*callback)(struct uart_ring*); + bool overwrite; +} uart_ring; + +// ***************************** Function prototypes ***************************** +void debug_ring_callback(uart_ring *ring); +void uart_tx_ring(uart_ring *q); +uart_ring *get_ring_by_number(int a); +// ************************* Low-level buffer functions ************************* +bool get_char(uart_ring *q, char *elem); +bool injectc(uart_ring *q, char elem); +bool put_char(uart_ring *q, char elem); +void clear_uart_buff(uart_ring *q); +// ************************ High-level debug functions ********************** +void putch(const char a); +void print(const char *a); +void puthx(uint32_t i, uint8_t len); +void puth(unsigned int i); +#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG) +static void puth4(unsigned int i); +#endif +#if defined(DEBUG_SPI) || defined(DEBUG_USB) || defined(DEBUG_COMMS) +static void hexdump(const void *a, int l); +#endif diff --git a/panda/board/drivers/usb.h b/panda/board/drivers/usb.h new file mode 100644 index 0000000000..1f715feef0 --- /dev/null +++ b/panda/board/drivers/usb.h @@ -0,0 +1,798 @@ +#include "usb_declarations.h" + +static uint8_t response[USBPACKET_MAX_SIZE]; + +// current packet +static USB_Setup_TypeDef setup; +static uint8_t* ep0_txdata = NULL; +static uint16_t ep0_txlen = 0; +static bool outep3_processing = false; + +// Store the current interface alt setting. +static int current_int0_alt_setting = 0; + +// packet read and write + +static void *USB_ReadPacket(void *dest, uint16_t len) { + uint32_t *dest_copy = (uint32_t *)dest; + uint32_t count32b = ((uint32_t)len + 3U) / 4U; + + for (uint32_t i = 0; i < count32b; i++) { + *dest_copy = USBx_DFIFO(0U); + dest_copy++; + } + return ((void *)dest_copy); +} + +static void USB_WritePacket(const void *src, uint16_t len, uint32_t ep) { + #ifdef DEBUG_USB + print("writing "); + hexdump(src, len); + #endif + + uint32_t numpacket = ((uint32_t)len + (USBPACKET_MAX_SIZE - 1U)) / USBPACKET_MAX_SIZE; + uint32_t count32b = 0; + count32b = ((uint32_t)len + 3U) / 4U; + + // TODO: revisit this + USBx_INEP(ep)->DIEPTSIZ = ((numpacket << 19) & USB_OTG_DIEPTSIZ_PKTCNT) | + (len & USB_OTG_DIEPTSIZ_XFRSIZ); + USBx_INEP(ep)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA); + + // load the FIFO + if (src != NULL) { + const uint32_t *src_copy = (const uint32_t *)src; + for (uint32_t i = 0; i < count32b; i++) { + USBx_DFIFO(ep) = *src_copy; + src_copy++; + } + } +} + +// IN EP 0 TX FIFO has a max size of 127 bytes (much smaller than the rest) +// so use TX FIFO empty interrupt to send larger amounts of data +static void USB_WritePacket_EP0(uint8_t *src, uint16_t len) { + #ifdef DEBUG_USB + print("writing "); + hexdump(src, len); + #endif + + uint16_t wplen = MIN(len, 0x40); + USB_WritePacket(src, wplen, 0); + + if (wplen < len) { + ep0_txdata = &src[wplen]; + ep0_txlen = len - wplen; + USBx_DEVICE->DIEPEMPMSK |= 1; + } else { + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } +} + +static void usb_reset(void) { + // unmask endpoint interrupts, so many sets + USBx_DEVICE->DAINT = 0xFFFFFFFFU; + USBx_DEVICE->DAINTMSK = 0xFFFFFFFFU; + //USBx_DEVICE->DOEPMSK = (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); + //USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM | USB_OTG_DIEPMSK_ITTXFEMSK); + //USBx_DEVICE->DIEPMSK = (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM); + + // all interrupts for debugging + USBx_DEVICE->DIEPMSK = 0xFFFFFFFFU; + USBx_DEVICE->DOEPMSK = 0xFFFFFFFFU; + + // clear interrupts + USBx_INEP(0U)->DIEPINT = 0xFF; + USBx_OUTEP(0U)->DOEPINT = 0xFF; + + // unset the address + USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD; + + // set up USB FIFOs + // RX start address is fixed to 0 + USBx->GRXFSIZ = 0x40; + + // 0x100 to offset past GRXFSIZ + USBx->DIEPTXF0_HNPTXFSIZ = (0x40UL << 16) | 0x40U; + + // EP1, massive + USBx->DIEPTXF[0] = (0x40UL << 16) | 0x80U; + + // flush TX fifo + USBx->GRSTCTL = USB_OTG_GRSTCTL_TXFFLSH | USB_OTG_GRSTCTL_TXFNUM_4; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + // flush RX FIFO + USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + // no global NAK + USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK; + + // ready to receive setup packets + USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (3U << 3); +} + +static char to_hex_char(uint8_t a) { + char ret; + if (a < 10U) { + ret = '0' + a; + } else { + ret = 'a' + (a - 10U); + } + return ret; +} + +static void usb_setup(void) { + static uint8_t device_desc[] = { + DSCR_DEVICE_LEN, USB_DESC_TYPE_DEVICE, //Length, Type + 0x10, 0x02, // bcdUSB max version of USB supported (2.1) + 0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size + TOUSBORDER(USB_VID), // idVendor + TOUSBORDER(USB_PID), // idProduct + 0x00, 0x00, // bcdDevice + 0x01, 0x02, // Manufacturer, Product + 0x03, 0x01 // Serial Number, Num Configurations + }; + + static uint8_t device_qualifier[] = { + 0x0a, USB_DESC_TYPE_DEVICE_QUALIFIER, //Length, Type + 0x10, 0x02, // bcdUSB max version of USB supported (2.1) + 0xFF, 0xFF, 0xFF, 0x40, // bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0 + 0x01, 0x00 // bNumConfigurations, bReserved + }; + + static uint8_t configuration_desc[] = { + DSCR_CONFIG_LEN, USB_DESC_TYPE_CONFIGURATION, // Length, Type, + TOUSBORDER(0x0045U), // Total Len (uint16) + 0x01, 0x01, STRING_OFFSET_ICONFIGURATION, // Num Interface, Config Value, Configuration + 0xc0, 0x32, // Attributes, Max Power + // interface 0 ALT 0 + DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type + 0x00, 0x00, 0x03, // Index, Alt Index idx, Endpoint count + 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol + 0x00, // Interface + // endpoint 1, read CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_RCV | 1, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval (NA) + // endpoint 2, send serial + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // endpoint 3, send CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // interface 0 ALT 1 + DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type + 0x00, 0x01, 0x03, // Index, Alt Index idx, Endpoint count + 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol + 0x00, // Interface + // endpoint 1, read CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_RCV | 1, ENDPOINT_TYPE_INT, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x05, // Polling Interval (5 frames) + // endpoint 2, send serial + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // endpoint 3, send CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + }; + + // STRING_DESCRIPTOR_HEADER is for uint16 string descriptors + // it takes in a string length, which is bytes/2 because unicode + static uint16_t string_language_desc[] = { + STRING_DESCRIPTOR_HEADER(1), + 0x0409 // american english + }; + + // these strings are all uint16's so that we don't need to spam ,0 after every character + static uint16_t string_manufacturer_desc[] = { + STRING_DESCRIPTOR_HEADER(8), + 'c', 'o', 'm', 'm', 'a', '.', 'a', 'i' + }; + + static uint16_t string_product_desc[] = { + STRING_DESCRIPTOR_HEADER(5), + 'p', 'a', 'n', 'd', 'a' + }; + + // a string containing the default configuration index + static uint16_t string_configuration_desc[] = { + STRING_DESCRIPTOR_HEADER(2), + '0', '1' // "01" + }; + + // WCID (auto install WinUSB driver) + // https://github.com/pbatard/libwdi/wiki/WCID-Devices + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file + // WinUSB 1.0 descriptors, this is mostly used by Windows XP + static uint8_t string_238_desc[] = { + 0x12, USB_DESC_TYPE_STRING, // bLength, bDescriptorType + 'M',0, 'S',0, 'F',0, 'T',0, '1',0, '0',0, '0',0, // qwSignature (MSFT100) + MS_VENDOR_CODE, 0x00 // bMS_VendorCode, bPad + }; + + static uint8_t winusb_ext_compatid_os_desc[] = { + 0x28, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x04, 0x00, // wIndex + 0x01, // bCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0x00, // bFirstInterfaceNumber + 0x00, // Reserved + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subcompatible ID (none) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved + }; + + static uint8_t winusb_ext_prop_os_desc[] = { + 0x8e, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x05, 0x00, // wIndex + 0x01, 0x00, // wCount + // first property + 0x84, 0x00, 0x00, 0x00, // dwSize + 0x01, 0x00, 0x00, 0x00, // dwPropertyDataType + 0x28, 0x00, // wPropertyNameLength + 'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0, // bPropertyName (DeviceInterfaceGUID) + 0x4e, 0x00, 0x00, 0x00, // dwPropertyDataLength + '{',0, 'c',0, 'c',0, 'e',0, '5',0, '2',0, '9',0, '1',0, 'c',0, '-',0, 'a',0, '6',0, '9',0, 'f',0, '-',0, '4',0 ,'9',0 ,'9',0 ,'5',0 ,'-',0, 'a',0, '4',0, 'c',0, '2',0, '-',0, '2',0, 'a',0, 'e',0, '5',0, '7',0, 'a',0, '5',0, '1',0, 'a',0, 'd',0, 'e',0, '9',0, '}',0, 0, 0, // bPropertyData ({CCE5291C-A69F-4995-A4C2-2AE57A51ADE9}) + }; + + /* + Binary Object Store descriptor used to expose WebUSB (and more WinUSB) metadata + comments are from the wicg spec + References used: + https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c + https://os.mbed.com/users/larsgk/code/USBDevice_WebUSB/file/1d8a6665d607/WebUSBDevice/ + */ + static uint8_t binary_object_store_desc[] = { + // BOS header + BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH, // bLength, this is only the length of the header + BINARY_OBJECT_STORE_DESCRIPTOR, // bDescriptorType + 0x39, 0x00, // wTotalLength (LSB, MSB) + 0x02, // bNumDeviceCaps (WebUSB + WinUSB) + + // ------------------------------------------------- + // WebUSB descriptor + // header + 0x18, // bLength, Size of this descriptor. Must be set to 24. + 0x10, // bDescriptorType, DEVICE CAPABILITY descriptor + 0x05, // bDevCapabilityType, PLATFORM capability + 0x00, // bReserved, This field is reserved and shall be set to zero. + + // PlatformCapabilityUUID, Must be set to {3408b638-09a9-47a0-8bfd-a0768815b665}. + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, 0xA0, 0x47, + 0x8B, 0xFD, 0xA0, 0x76, + 0x88, 0x15, 0xB6, 0x65, + // + + 0x00, 0x01, // bcdVersion, Protocol version supported. Must be set to 0x0100. + WEBUSB_VENDOR_CODE, // bVendorCode, bRequest value used for issuing WebUSB requests. + // there used to be a concept of "allowed origins", but it was removed from the spec + // it was intended to be a security feature, but then the entire security model relies on domain ownership + // https://github.com/WICG/webusb/issues/49 + // other implementations use various other indexed to leverate this no-longer-valid feature. we wont. + // the spec says we *must* reply to index 0x03 with the url, so we'll hint that that's the right index + 0x03, // iLandingPage, URL descriptor index of the device’s landing page. + + // ------------------------------------------------- + // WinUSB descriptor + // header + 0x1C, // Descriptor size (28 bytes) + 0x10, // Descriptor type (Device Capability) + 0x05, // Capability type (Platform) + 0x00, // Reserved + + // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F) + // Indicates the device supports the Microsoft OS 2.0 descriptor + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, 0xC7, 0x4C, + 0x9C, 0xD2, 0x65, 0x9D, + 0x9E, 0x64, 0x8A, 0x9F, + + 0x00, 0x00, 0x03, 0x06, // Windows version, currently set to 8.1 (0x06030000) + + WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // MS OS 2.0 descriptor size (word) + MS_VENDOR_CODE, 0x00 // vendor code, no alternate enumeration + }; + + // WinUSB 2.0 descriptor. This is what modern systems use + // https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c + // http://janaxelson.com/files/ms_os_20_descriptors.c + // https://books.google.com/books?id=pkefBgAAQBAJ&pg=PA353&lpg=PA353 + static uint8_t winusb_20_desc[WINUSB_PLATFORM_DESCRIPTOR_LENGTH] = { + // Microsoft OS 2.0 descriptor set header (table 10) + 0x0A, 0x00, // Descriptor size (10 bytes) + 0x00, 0x00, // MS OS 2.0 descriptor set header + + 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) + WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // Total size of MS OS 2.0 descriptor set + + // Microsoft OS 2.0 compatible ID descriptor + 0x14, 0x00, // Descriptor size (20 bytes) + 0x03, 0x00, // MS OS 2.0 compatible ID descriptor + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-compatible ID + + // Registry property descriptor + 0x80, 0x00, // Descriptor size (130 bytes) + 0x04, 0x00, // Registry Property descriptor + 0x01, 0x00, // Strings are null-terminated Unicode + 0x28, 0x00, // Size of Property Name (40 bytes) "DeviceInterfaceGUID" + + // bPropertyName (DeviceInterfaceGUID) + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, + 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, + 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, + + 0x4E, 0x00, // Size of Property Data (78 bytes) + + // Vendor-defined property data: {CCE5291C-A69F-4995-A4C2-2AE57A51ADE9} + '{', 0x00, 'c', 0x00, 'c', 0x00, 'e', 0x00, '5', 0x00, '2', 0x00, '9', 0x00, '1', 0x00, // 16 + 'c', 0x00, '-', 0x00, 'a', 0x00, '6', 0x00, '9', 0x00, 'f', 0x00, '-', 0x00, '4', 0x00, // 32 + '9', 0x00, '9', 0x00, '5', 0x00, '-', 0x00, 'a', 0x00, '4', 0x00, 'c', 0x00, '2', 0x00, // 48 + '-', 0x00, '2', 0x00, 'a', 0x00, 'e', 0x00, '5', 0x00, '7', 0x00, 'a', 0x00, '5', 0x00, // 64 + '1', 0x00, 'a', 0x00, 'd', 0x00, 'e', 0x00, '9', 0x00, '}', 0x00, 0x00, 0x00 // 78 bytes + }; + + int resp_len; + ControlPacket_t control_req; + + // setup packet is ready + switch (setup.b.bRequest) { + case USB_REQ_SET_CONFIGURATION: + // enable other endpoints, has to be here? + USBx_INEP(1U)->DIEPCTL = (0x40U & USB_OTG_DIEPCTL_MPSIZ) | (2UL << 18) | (1UL << 22) | + USB_OTG_DIEPCTL_SD0PID_SEVNFRM | USB_OTG_DIEPCTL_USBAEP; + USBx_INEP(1U)->DIEPINT = 0xFF; + + USBx_OUTEP(2U)->DOEPTSIZ = (1UL << 19) | 0x40U; + USBx_OUTEP(2U)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) | + USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP; + USBx_OUTEP(2U)->DOEPINT = 0xFF; + + USBx_OUTEP(3U)->DOEPTSIZ = (32UL << 19) | 0x800U; + USBx_OUTEP(3U)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2UL << 18) | + USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP; + USBx_OUTEP(3U)->DOEPINT = 0xFF; + + // mark ready to receive + USBx_OUTEP(2U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_REQ_SET_ADDRESS: + // set now? + USBx_DEVICE->DCFG |= ((setup.b.wValue.w & 0x7fU) << 4); + + #ifdef DEBUG_USB + print(" set address\n"); + #endif + + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + + break; + case USB_REQ_GET_DESCRIPTOR: + switch (setup.b.wValue.bw.lsb) { + case USB_DESC_TYPE_DEVICE: + //print(" writing device descriptor\n"); + + // set bcdDevice to hardware type + device_desc[13] = hw_type; + // setup transfer + USB_WritePacket(device_desc, MIN(sizeof(device_desc), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + + //print("D"); + break; + case USB_DESC_TYPE_CONFIGURATION: + USB_WritePacket(configuration_desc, MIN(sizeof(configuration_desc), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_DESC_TYPE_DEVICE_QUALIFIER: + USB_WritePacket(device_qualifier, MIN(sizeof(device_qualifier), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_DESC_TYPE_STRING: + switch (setup.b.wValue.bw.msb) { + case STRING_OFFSET_LANGID: + USB_WritePacket((uint8_t*)string_language_desc, MIN(sizeof(string_language_desc), setup.b.wLength.w), 0); + break; + case STRING_OFFSET_IMANUFACTURER: + USB_WritePacket((uint8_t*)string_manufacturer_desc, MIN(sizeof(string_manufacturer_desc), setup.b.wLength.w), 0); + break; + case STRING_OFFSET_IPRODUCT: + USB_WritePacket((uint8_t*)string_product_desc, MIN(sizeof(string_product_desc), setup.b.wLength.w), 0); + break; + case STRING_OFFSET_ISERIAL: + response[0] = 0x02 + (12 * 4); + response[1] = 0x03; + + // 96 bits = 12 bytes + for (int i = 0; i < 12; i++){ + uint8_t cc = ((uint8_t *)UID_BASE)[i]; + response[2 + (i * 4)] = to_hex_char((cc >> 4) & 0xFU); + response[2 + (i * 4) + 1] = '\0'; + response[2 + (i * 4) + 2] = to_hex_char((cc >> 0) & 0xFU); + response[2 + (i * 4) + 3] = '\0'; + } + + USB_WritePacket(response, MIN(response[0], setup.b.wLength.w), 0); + break; + case STRING_OFFSET_ICONFIGURATION: + USB_WritePacket((uint8_t*)string_configuration_desc, MIN(sizeof(string_configuration_desc), setup.b.wLength.w), 0); + break; + case 238: + USB_WritePacket((uint8_t*)string_238_desc, MIN(sizeof(string_238_desc), setup.b.wLength.w), 0); + break; + default: + // nothing + USB_WritePacket(0, 0, 0); + break; + } + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_DESC_TYPE_BINARY_OBJECT_STORE: + USB_WritePacket(binary_object_store_desc, MIN(sizeof(binary_object_store_desc), setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + default: + // nothing here? + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + } + break; + case USB_REQ_GET_STATUS: + // empty response? + response[0] = 0; + response[1] = 0; + USB_WritePacket((void*)&response, 2, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case USB_REQ_SET_INTERFACE: + // Store the alt setting number for IN EP behavior. + current_int0_alt_setting = setup.b.wValue.w; + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case WEBUSB_VENDOR_CODE: + // probably asking for allowed origins, which was removed from the spec + USB_WritePacket(0, 0, 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + break; + case MS_VENDOR_CODE: + switch (setup.b.wIndex.w) { + // winusb 2.0 descriptor from BOS + case WINUSB_REQ_GET_DESCRIPTOR: + USB_WritePacket_EP0((uint8_t*)winusb_20_desc, MIN(sizeof(winusb_20_desc), setup.b.wLength.w)); + break; + // Extended Compat ID OS Descriptor + case WINUSB_REQ_GET_COMPATID_DESCRIPTOR: + USB_WritePacket_EP0((uint8_t*)winusb_ext_compatid_os_desc, MIN(sizeof(winusb_ext_compatid_os_desc), setup.b.wLength.w)); + break; + // Extended Properties OS Descriptor + case WINUSB_REQ_GET_EXT_PROPS_OS: + USB_WritePacket_EP0((uint8_t*)winusb_ext_prop_os_desc, MIN(sizeof(winusb_ext_prop_os_desc), setup.b.wLength.w)); + break; + default: + USB_WritePacket_EP0(0, 0); + } + break; + default: + control_req.request = setup.b.bRequest; + control_req.param1 = setup.b.wValue.w; + control_req.param2 = setup.b.wIndex.w; + control_req.length = setup.b.wLength.w; + + resp_len = comms_control_handler(&control_req, response); + // response pending if -1 was returned + if (resp_len != -1) { + USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0); + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } + } +} + + + +// ***************************** USB port ***************************** + +void usb_irqhandler(void) { + //USBx->GINTMSK = 0; + static uint8_t usbdata[0x100] __attribute__((aligned(4))); + unsigned int gintsts = USBx->GINTSTS; + unsigned int gotgint = USBx->GOTGINT; + unsigned int daint = USBx_DEVICE->DAINT; + + // gintsts SUSPEND? 04008428 + #ifdef DEBUG_USB + puth(gintsts); + print(" "); + /*puth(USBx->GCCFG); + print(" ");*/ + puth(gotgint); + print(" ep "); + puth(daint); + print(" USB interrupt!\n"); + #endif + + if ((gintsts & USB_OTG_GINTSTS_CIDSCHG) != 0U) { + print("connector ID status change\n"); + } + + if ((gintsts & USB_OTG_GINTSTS_USBRST) != 0U) { + #ifdef DEBUG_USB + print("USB reset\n"); + #endif + usb_reset(); + } + + if ((gintsts & USB_OTG_GINTSTS_ENUMDNE) != 0U) { + #ifdef DEBUG_USB + print("enumeration done\n"); + #endif + // Full speed, ENUMSPD + //puth(USBx_DEVICE->DSTS); + } + + if ((gintsts & USB_OTG_GINTSTS_OTGINT) != 0U) { + #ifdef DEBUG_USB + print("OTG int:"); + puth(USBx->GOTGINT); + print("\n"); + #endif + + // getting ADTOCHG + //USBx->GOTGINT = USBx->GOTGINT; + } + + // RX FIFO first + if ((gintsts & USB_OTG_GINTSTS_RXFLVL) != 0U) { + // 1. Read the Receive status pop register + volatile unsigned int rxst = USBx->GRXSTSP; + int status = (rxst & USB_OTG_GRXSTSP_PKTSTS) >> 17; + + #ifdef DEBUG_USB + print(" RX FIFO:"); + puth(rxst); + print(" status: "); + puth(status); + print(" len: "); + puth((rxst & USB_OTG_GRXSTSP_BCNT) >> 4); + print("\n"); + #endif + + if (status == STS_DATA_UPDT) { + int endpoint = (rxst & USB_OTG_GRXSTSP_EPNUM); + int len = (rxst & USB_OTG_GRXSTSP_BCNT) >> 4; + (void)USB_ReadPacket(&usbdata, len); + #ifdef DEBUG_USB + print(" data "); + puth(len); + print("\n"); + hexdump(&usbdata, len); + #endif + + if (endpoint == 2) { + comms_endpoint2_write((uint8_t *) usbdata, len); + } + + if (endpoint == 3) { + outep3_processing = true; + comms_can_write(usbdata, len); + } + } else if (status == STS_SETUP_UPDT) { + (void)USB_ReadPacket(&setup, 8); + #ifdef DEBUG_USB + print(" setup "); + hexdump(&setup, 8); + print("\n"); + #endif + } else { + // status is neither STS_DATA_UPDT or STS_SETUP_UPDT, skip + } + } + + /*if (gintsts & USB_OTG_GINTSTS_HPRTINT) { + // host + print("HPRT:"); + puth(USBx_HOST_PORT->HPRT); + print("\n"); + if (USBx_HOST_PORT->HPRT & USB_OTG_HPRT_PCDET) { + USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PRST; + USBx_HOST_PORT->HPRT |= USB_OTG_HPRT_PCDET; + } + + }*/ + + if ((gintsts & USB_OTG_GINTSTS_BOUTNAKEFF) || (gintsts & USB_OTG_GINTSTS_GINAKEFF)) { + // no global NAK, why is this getting set? + #ifdef DEBUG_USB + print("GLOBAL NAK\n"); + #endif + USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK | USB_OTG_DCTL_CGINAK; + } + + if ((gintsts & USB_OTG_GINTSTS_SRQINT) != 0U) { + // we want to do "A-device host negotiation protocol" since we are the A-device + /*print("start request\n"); + puth(USBx->GOTGCTL); + print("\n");*/ + //USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + //USBx_HOST_PORT->HPRT = USB_OTG_HPRT_PPWR | USB_OTG_HPRT_PENA; + //USBx->GOTGCTL |= USB_OTG_GOTGCTL_SRQ; + } + + // out endpoint hit + if ((gintsts & USB_OTG_GINTSTS_OEPINT) != 0U) { + #ifdef DEBUG_USB + print(" 0:"); + puth(USBx_OUTEP(0U)->DOEPINT); + print(" 2:"); + puth(USBx_OUTEP(2U)->DOEPINT); + print(" 3:"); + puth(USBx_OUTEP(3U)->DOEPINT); + print(" "); + puth(USBx_OUTEP(3U)->DOEPCTL); + print(" 4:"); + puth(USBx_OUTEP(4)->DOEPINT); + print(" OUT ENDPOINT\n"); + #endif + + if ((USBx_OUTEP(2U)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0U) { + #ifdef DEBUG_USB + print(" OUT2 PACKET XFRC\n"); + #endif + USBx_OUTEP(2U)->DOEPTSIZ = (1UL << 19) | 0x40U; + USBx_OUTEP(2U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } + + if ((USBx_OUTEP(3U)->DOEPINT & USB_OTG_DOEPINT_XFRC) != 0U) { + #ifdef DEBUG_USB + print(" OUT3 PACKET XFRC\n"); + #endif + // NAK cleared by process_can (if tx buffers have room) + outep3_processing = false; + refresh_can_tx_slots_available(); + } else if ((USBx_OUTEP(3U)->DOEPINT & 0x2000U) != 0U) { + #ifdef DEBUG_USB + print(" OUT3 PACKET WTF\n"); + #endif + // if NAK was set trigger this, unknown interrupt + // TODO: why was this here? fires when TX buffers when we can't clear NAK + // USBx_OUTEP(3U)->DOEPTSIZ = (1U << 19) | 0x40U; + // USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } else if ((USBx_OUTEP(3U)->DOEPINT) != 0U) { + #ifdef DEBUG_USB + print("OUTEP3 error "); + puth(USBx_OUTEP(3U)->DOEPINT); + print("\n"); + #endif + } else { + // USBx_OUTEP(3U)->DOEPINT is 0, ok to skip + } + + if ((USBx_OUTEP(0U)->DOEPINT & USB_OTG_DIEPINT_XFRC) != 0U) { + // ready for next packet + USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (1U << 3); + } + + // respond to setup packets + if ((USBx_OUTEP(0U)->DOEPINT & USB_OTG_DOEPINT_STUP) != 0U) { + usb_setup(); + } + + USBx_OUTEP(0U)->DOEPINT = USBx_OUTEP(0U)->DOEPINT; + USBx_OUTEP(2U)->DOEPINT = USBx_OUTEP(2U)->DOEPINT; + USBx_OUTEP(3U)->DOEPINT = USBx_OUTEP(3U)->DOEPINT; + } + + // interrupt endpoint hit (Page 1221) + if ((gintsts & USB_OTG_GINTSTS_IEPINT) != 0U) { + #ifdef DEBUG_USB + print(" "); + puth(USBx_INEP(0U)->DIEPINT); + print(" "); + puth(USBx_INEP(1U)->DIEPINT); + print(" IN ENDPOINT\n"); + #endif + + // Should likely check the EP of the IN request even if there is + // only one IN endpoint. + + // No need to set NAK in OTG_DIEPCTL0 when nothing to send, + // Appears USB core automatically sets NAK. WritePacket clears it. + + // Handle the two interface alternate settings. Setting 0 has EP1 + // as bulk. Setting 1 has EP1 as interrupt. The code to handle + // these two EP variations are very similar and can be + // restructured for smaller code footprint. Keeping split out for + // now for clarity. + + //TODO add default case. Should it NAK? + switch (current_int0_alt_setting) { + case 0: ////// Bulk config + // *** IN token received when TxFIFO is empty + if ((USBx_INEP(1U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) { + #ifdef DEBUG_USB + print(" IN PACKET QUEUE\n"); + #endif + // TODO: always assuming max len, can we get the length? + USB_WritePacket((void *)response, comms_can_read(response, 0x40), 1); + } + break; + + case 1: ////// Interrupt config + // *** IN token received when TxFIFO is empty + if ((USBx_INEP(1U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) { + #ifdef DEBUG_USB + print(" IN PACKET QUEUE\n"); + #endif + // TODO: always assuming max len, can we get the length? + int len = comms_can_read(response, 0x40); + if (len > 0) { + USB_WritePacket((void *)response, len, 1); + } + } + break; + default: + print("current_int0_alt_setting value invalid\n"); + break; + } + + if ((USBx_INEP(0U)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) != 0U) { + #ifdef DEBUG_USB + print(" IN PACKET QUEUE\n"); + #endif + + if ((ep0_txlen != 0U) && ((USBx_INEP(0U)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40U)) { + uint16_t len = MIN(ep0_txlen, 0x40); + USB_WritePacket(ep0_txdata, len, 0); + ep0_txdata = &ep0_txdata[len]; + ep0_txlen -= len; + if (ep0_txlen == 0U) { + ep0_txdata = NULL; + USBx_DEVICE->DIEPEMPMSK &= ~1; + USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; + } + } + } + + // clear interrupts + USBx_INEP(0U)->DIEPINT = USBx_INEP(0U)->DIEPINT; // Why ep0? + USBx_INEP(1U)->DIEPINT = USBx_INEP(1U)->DIEPINT; + } + + // clear all interrupts we handled + USBx_DEVICE->DAINT = daint; + USBx->GOTGINT = gotgint; + USBx->GINTSTS = gintsts; + + //USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF); +} + +void can_tx_comms_resume_usb(void) { + ENTER_CRITICAL(); + if (!outep3_processing && (USBx_OUTEP(3U)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != 0U) { + USBx_OUTEP(3U)->DOEPTSIZ = (32UL << 19) | 0x800U; + USBx_OUTEP(3U)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK; + } + EXIT_CRITICAL(); +} diff --git a/panda/board/drivers/usb_declarations.h b/panda/board/drivers/usb_declarations.h new file mode 100644 index 0000000000..379b162feb --- /dev/null +++ b/panda/board/drivers/usb_declarations.h @@ -0,0 +1,111 @@ +#pragma once + +// IRQs: OTG_FS + +typedef union { + uint16_t w; + struct BW { + uint8_t msb; + uint8_t lsb; + } + bw; +} uint16_t_uint8_t; + +typedef union _USB_Setup { + uint32_t d8[2]; + struct _SetupPkt_Struc + { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t_uint8_t wValue; + uint16_t_uint8_t wIndex; + uint16_t_uint8_t wLength; + } b; +} USB_Setup_TypeDef; + +void usb_init(void); +void refresh_can_tx_slots_available(void); + +// **** supporting defines **** +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +#define USB_DESC_TYPE_DEVICE 0x01 +#define USB_DESC_TYPE_CONFIGURATION 0x02 +#define USB_DESC_TYPE_STRING 0x03 +#define USB_DESC_TYPE_INTERFACE 0x04 +#define USB_DESC_TYPE_ENDPOINT 0x05 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 +#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f + +// offsets for configuration strings +#define STRING_OFFSET_LANGID 0x00 +#define STRING_OFFSET_IMANUFACTURER 0x01 +#define STRING_OFFSET_IPRODUCT 0x02 +#define STRING_OFFSET_ISERIAL 0x03 +#define STRING_OFFSET_ICONFIGURATION 0x04 +#define STRING_OFFSET_IINTERFACE 0x05 + +// WebUSB requests +#define WEBUSB_REQ_GET_URL 0x02 + +// WebUSB types +#define WEBUSB_DESC_TYPE_URL 0x03 +#define WEBUSB_URL_SCHEME_HTTPS 0x01 +#define WEBUSB_URL_SCHEME_HTTP 0x00 + +// WinUSB requests +#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04 +#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05 +#define WINUSB_REQ_GET_DESCRIPTOR 0x07 + +#define STS_GOUT_NAK 1 +#define STS_DATA_UPDT 2 +#define STS_XFER_COMP 3 +#define STS_SETUP_COMP 4 +#define STS_SETUP_UPDT 6 + +// for the repeating interfaces +#define DSCR_INTERFACE_LEN 9 +#define DSCR_ENDPOINT_LEN 7 +#define DSCR_CONFIG_LEN 9 +#define DSCR_DEVICE_LEN 18 + +// endpoint types +#define ENDPOINT_TYPE_CONTROL 0 +#define ENDPOINT_TYPE_ISO 1 +#define ENDPOINT_TYPE_BULK 2 +#define ENDPOINT_TYPE_INT 3 + +// These are arbitrary values used in bRequest +#define MS_VENDOR_CODE 0x20 +#define WEBUSB_VENDOR_CODE 0x30 + +// BOS constants +#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05 +#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F +#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E + +// Convert machine byte order to USB byte order +#define TOUSBORDER(num)\ + ((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU) + +// take in string length and return the first 2 bytes of a string descriptor +#define STRING_DESCRIPTOR_HEADER(size)\ + (((((size) * 2) + 2) & 0xFF) | 0x0300) + +#define ENDPOINT_RCV 0x80 +#define ENDPOINT_SND 0x00 + +// ***************************** USB port ***************************** +void can_tx_comms_resume_usb(void); diff --git a/panda/board/early_init.h b/panda/board/early_init.h new file mode 100644 index 0000000000..d5131a42cf --- /dev/null +++ b/panda/board/early_init.h @@ -0,0 +1,64 @@ +// Early bringup +#define ENTER_BOOTLOADER_MAGIC 0xdeadbeefU +#define ENTER_SOFTLOADER_MAGIC 0xdeadc0deU +#define BOOT_NORMAL 0xdeadb111U + +extern void *g_pfnVectors; +extern uint32_t enter_bootloader_mode; + +typedef void (*bootloader_fcn)(void); +typedef bootloader_fcn *bootloader_fcn_ptr; + +static void jump_to_bootloader(void) { + // do enter bootloader + enter_bootloader_mode = 0; + + bootloader_fcn_ptr bootloader_ptr = (bootloader_fcn_ptr)BOOTLOADER_ADDRESS; + bootloader_fcn bootloader = *bootloader_ptr; + + // jump to bootloader + enable_interrupts(); + bootloader(); + + // reset on exit + enter_bootloader_mode = BOOT_NORMAL; + NVIC_SystemReset(); +} + +void early_initialization(void) { + // Reset global critical depth + disable_interrupts(); + global_critical_depth = 0; + + // Init register and interrupt tables + init_registers(); + + // after it's been in the bootloader, things are initted differently, so we reset + if ((enter_bootloader_mode != BOOT_NORMAL) && + (enter_bootloader_mode != ENTER_BOOTLOADER_MAGIC) && + (enter_bootloader_mode != ENTER_SOFTLOADER_MAGIC)) { + enter_bootloader_mode = BOOT_NORMAL; + NVIC_SystemReset(); + } + + // if wrong chip, reboot + volatile unsigned int id = DBGMCU->IDCODE; + if ((id & 0xFFFU) != MCU_IDCODE) { + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + } + + // setup interrupt table + SCB->VTOR = (uint32_t)&g_pfnVectors; + + // early GPIOs float everything + early_gpio_float(); + + detect_board_type(); + + if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) { + led_init(); + current_board->init_bootloader(); + led_set(LED_GREEN, 1); + jump_to_bootloader(); + } +} diff --git a/panda/board/fake_stm.h b/panda/board/fake_stm.h new file mode 100644 index 0000000000..febf0544b7 --- /dev/null +++ b/panda/board/fake_stm.h @@ -0,0 +1,33 @@ +// minimal code to fake a panda for tests +#include +#include +#include + +#include "utils.h" + +#define ALLOW_DEBUG + +#define ENTER_CRITICAL() 0 +#define EXIT_CRITICAL() 0 + +void print(const char *a) { + printf("%s", a); +} + +void puth(unsigned int i) { + printf("%u", i); +} + +typedef struct { + uint32_t CNT; +} TIM_TypeDef; + +TIM_TypeDef timer; +TIM_TypeDef *MICROSECOND_TIMER = &timer; +uint32_t microsecond_timer_get(void); + +uint32_t microsecond_timer_get(void) { + return MICROSECOND_TIMER->CNT; +} + +typedef uint32_t GPIO_TypeDef; diff --git a/panda/board/faults.h b/panda/board/faults.h new file mode 100644 index 0000000000..0fc9d2c5cf --- /dev/null +++ b/panda/board/faults.h @@ -0,0 +1,25 @@ +#include "faults_declarations.h" + +uint8_t fault_status = FAULT_STATUS_NONE; +uint32_t faults = 0U; + +void fault_occurred(uint32_t fault) { + if ((faults & fault) == 0U) { + if ((PERMANENT_FAULTS & fault) != 0U) { + print("Permanent fault occurred: 0x"); puth(fault); print("\n"); + fault_status = FAULT_STATUS_PERMANENT; + } else { + print("Temporary fault occurred: 0x"); puth(fault); print("\n"); + fault_status = FAULT_STATUS_TEMPORARY; + } + } + faults |= fault; +} + +void fault_recovered(uint32_t fault) { + if ((PERMANENT_FAULTS & fault) == 0U) { + faults &= ~fault; + } else { + print("Cannot recover from a permanent fault!\n"); + } +} diff --git a/panda/board/faults_declarations.h b/panda/board/faults_declarations.h new file mode 100644 index 0000000000..981e237566 --- /dev/null +++ b/panda/board/faults_declarations.h @@ -0,0 +1,34 @@ +#pragma once + +#define FAULT_STATUS_NONE 0U +#define FAULT_STATUS_TEMPORARY 1U +#define FAULT_STATUS_PERMANENT 2U + +// Fault types, matches cereal.log.PandaState.FaultType +#define FAULT_RELAY_MALFUNCTION (1UL << 0) +#define FAULT_UNUSED_INTERRUPT_HANDLED (1UL << 1) +#define FAULT_INTERRUPT_RATE_CAN_1 (1UL << 2) +#define FAULT_INTERRUPT_RATE_CAN_2 (1UL << 3) +#define FAULT_INTERRUPT_RATE_CAN_3 (1UL << 4) +#define FAULT_INTERRUPT_RATE_TACH (1UL << 5) +#define FAULT_INTERRUPT_RATE_INTERRUPTS (1UL << 7) +#define FAULT_INTERRUPT_RATE_SPI_DMA (1UL << 8) +#define FAULT_INTERRUPT_RATE_USB (1UL << 15) +#define FAULT_REGISTER_DIVERGENT (1UL << 18) +#define FAULT_INTERRUPT_RATE_CLOCK_SOURCE (1UL << 20) +#define FAULT_INTERRUPT_RATE_TICK (1UL << 21) +#define FAULT_INTERRUPT_RATE_EXTI (1UL << 22) +#define FAULT_INTERRUPT_RATE_SPI (1UL << 23) +#define FAULT_INTERRUPT_RATE_UART_7 (1UL << 24) +#define FAULT_SIREN_MALFUNCTION (1UL << 25) +#define FAULT_HEARTBEAT_LOOP_WATCHDOG (1UL << 26) +#define FAULT_INTERRUPT_RATE_SOUND_DMA (1UL << 27) + +// Permanent faults +#define PERMANENT_FAULTS 0U + +extern uint8_t fault_status; +extern uint32_t faults; + +void fault_occurred(uint32_t fault); +void fault_recovered(uint32_t fault); diff --git a/panda/board/flash.py b/panda/board/flash.py new file mode 100755 index 0000000000..3943814625 --- /dev/null +++ b/panda/board/flash.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import os +import subprocess +import argparse + +from panda import Panda + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--all", action="store_true", help="Recover all Panda devices") + args = parser.parse_args() + + subprocess.check_call(f"scons -C {board_path}/.. -j$(nproc) {board_path}", shell=True) + + if args.all: + serials = Panda.list() + print(f"found {len(serials)} panda(s) - {serials}") + else: + serials = [None] + + for s in serials: + with Panda(serial=s) as p: + print("flashing", p.get_usb_serial()) + p.flash() + exit(1 if len(serials) == 0 else 0) diff --git a/panda/board/flasher.h b/panda/board/flasher.h new file mode 100644 index 0000000000..34d935205a --- /dev/null +++ b/panda/board/flasher.h @@ -0,0 +1,152 @@ +// from the linker script +#define APP_START_ADDRESS 0x8020000U + +// flasher state variables +uint32_t *prog_ptr = NULL; +bool unlocked = false; + +void spi_init(void); + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { + int resp_len = 0; + + // flasher machine + memset(resp, 0, 4); + memcpy(resp+4, "\xde\xad\xd0\x0d", 4); + resp[0] = 0xff; + resp[2] = req->request; + resp[3] = ~req->request; + *((uint32_t **)&resp[8]) = prog_ptr; + resp_len = 0xc; + + int sec; + switch (req->request) { + // **** 0xb0: flasher echo + case 0xb0: + resp[1] = 0xff; + break; + // **** 0xb1: unlock flash + case 0xb1: + if (flash_is_locked()) { + flash_unlock(); + resp[1] = 0xff; + } + led_set(LED_GREEN, 1); + unlocked = true; + prog_ptr = (uint32_t *)APP_START_ADDRESS; + break; + // **** 0xb2: erase sector + case 0xb2: + sec = req->param1; + if (flash_erase_sector(sec, unlocked)) { + resp[1] = 0xff; + } + break; + // **** 0xc1: get hardware type + case 0xc1: + resp[0] = hw_type; + resp_len = 1; + break; + // **** 0xc3: fetch MCU UID + case 0xc3: + (void)memcpy(resp, ((uint8_t *)UID_BASE), 12); + resp_len = 12; + break; + // **** 0xd0: fetch serial number + case 0xd0: + // addresses are OTP + if (req->param1 == 1) { + memcpy(resp, (void *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } + break; + // **** 0xd1: enter bootloader mode + case 0xd1: + // this allows reflashing of the bootstub + switch (req->param1) { + case 0: + print("-> entering bootloader\n"); + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + break; + case 1: + print("-> entering softloader\n"); + enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; + NVIC_SystemReset(); + break; + } + break; + // **** 0xd6: get version + case 0xd6: + COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); + memcpy(resp, gitversion, sizeof(gitversion)); + resp_len = sizeof(gitversion); + break; + // **** 0xd8: reset ST + case 0xd8: + flush_write_buffer(); + NVIC_SystemReset(); + break; + } + return resp_len; +} + +void comms_can_write(const uint8_t *data, uint32_t len) { + UNUSED(data); + UNUSED(len); +} + +int comms_can_read(uint8_t *data, uint32_t max_len) { + UNUSED(data); + UNUSED(max_len); + return 0; +} + +void refresh_can_tx_slots_available(void) {} + +void comms_endpoint2_write(const uint8_t *data, uint32_t len) { + led_set(LED_RED, 0); + for (uint32_t i = 0; i < len/4; i++) { + flash_write_word(prog_ptr, *(uint32_t*)(data+(i*4))); + + //*(uint64_t*)(&spi_tx_buf[0x30+(i*4)]) = *prog_ptr; + prog_ptr++; + } + led_set(LED_RED, 1); +} + + +void soft_flasher_start(void) { + print("\n\n\n************************ FLASHER START ************************\n"); + + enter_bootloader_mode = 0; + + flasher_peripherals_init(); + + gpio_usart2_init(); + gpio_usb_init(); + led_init(); + + // enable comms + usb_init(); + if (current_board->has_spi) { + gpio_spi_init(); + spi_init(); + } + + // green LED on for flashing + led_set(LED_GREEN, 1); + + enable_interrupts(); + + for (;;) { + // blink the green LED fast + led_set(LED_GREEN, 0); + delay(500000); + led_set(LED_GREEN, 1); + delay(500000); + } +} diff --git a/panda/board/health.h b/panda/board/health.h new file mode 100644 index 0000000000..9040edf5a1 --- /dev/null +++ b/panda/board/health.h @@ -0,0 +1,60 @@ +// When changing these structs, python/__init__.py needs to be kept up to date! + +#define HEALTH_PACKET_VERSION 17 +struct __attribute__((packed)) health_t { + uint32_t uptime_pkt; + uint32_t voltage_pkt; + uint32_t current_pkt; + uint32_t safety_tx_blocked_pkt; + uint32_t safety_rx_invalid_pkt; + uint32_t tx_buffer_overflow_pkt; + uint32_t rx_buffer_overflow_pkt; + uint32_t faults_pkt; + uint8_t ignition_line_pkt; + uint8_t ignition_can_pkt; + uint8_t controls_allowed_pkt; + uint8_t car_harness_status_pkt; + uint8_t safety_mode_pkt; + uint16_t safety_param_pkt; + uint8_t fault_status_pkt; + uint8_t power_save_enabled_pkt; + uint8_t heartbeat_lost_pkt; + uint16_t alternative_experience_pkt; + float interrupt_load_pkt; + uint8_t fan_power; + uint8_t safety_rx_checks_invalid_pkt; + uint16_t spi_error_count_pkt; + uint16_t sbu1_voltage_mV; + uint16_t sbu2_voltage_mV; + uint8_t som_reset_triggered; +}; + +#define CAN_HEALTH_PACKET_VERSION 5 +typedef struct __attribute__((packed)) { + uint8_t bus_off; + uint32_t bus_off_cnt; + uint8_t error_warning; + uint8_t error_passive; + uint8_t last_error; // real time LEC value + uint8_t last_stored_error; // last LEC positive error code stored + uint8_t last_data_error; // DLEC (for CANFD only) + uint8_t last_data_stored_error; // last DLEC positive error code stored (for CANFD only) + uint8_t receive_error_cnt; // Actual state of the receive error counter, values between 0 and 127. FDCAN_ECR.REC + uint8_t transmit_error_cnt; // Actual state of the transmit error counter, values between 0 and 255. FDCAN_ECR.TEC + uint32_t total_error_cnt; // How many times any error interrupt was invoked + uint32_t total_tx_lost_cnt; // Tx event FIFO element lost + uint32_t total_rx_lost_cnt; // Rx FIFO 0 message lost due to FIFO full condition + uint32_t total_tx_cnt; + uint32_t total_rx_cnt; + uint32_t total_fwd_cnt; // Messages forwarded from one bus to another + uint32_t total_tx_checksum_error_cnt; + uint16_t can_speed; + uint16_t can_data_speed; + uint8_t canfd_enabled; + uint8_t brs_enabled; + uint8_t canfd_non_iso; + uint32_t irq0_call_rate; + uint32_t irq1_call_rate; + uint32_t irq2_call_rate; + uint32_t can_core_reset_cnt; +} can_health_t; diff --git a/panda/board/jungle/README.md b/panda/board/jungle/README.md new file mode 100644 index 0000000000..3fc645ad27 --- /dev/null +++ b/panda/board/jungle/README.md @@ -0,0 +1,26 @@ +Welcome to the jungle +====== + +Firmware for the Panda Jungle testing board. +Available for purchase at the [comma shop](https://comma.ai/shop/panda-jungle). + +## udev rules + +To make the jungle usable without root permissions, you might need to setup udev rules for it. +On ubuntu, this should do the trick: +``` bash +sudo tee /etc/udev/rules.d/12-panda_jungle.rules < bool: + dfu_serial = self.get_dfu_serial() + + if reset: + self.reset(enter_bootstub=True) + self.reset(enter_bootloader=True) + + if not self.wait_for_dfu(dfu_serial, timeout=timeout): + return False + + dfu = PandaJungleDFU(dfu_serial) + dfu.recover() + + # reflash after recover + self.connect(True, True) + self.flash() + return True + + def get_mcu_type(self) -> McuType: + hw_type = self.get_type() + if hw_type in PandaJungle.H7_DEVICES: + return McuType.H7 + raise ValueError(f"unknown HW type: {hw_type}") + + def up_to_date(self, fn=None) -> bool: + if fn is None: + fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn.replace("panda", "panda_jungle")) + return super().up_to_date(fn=fn) + + # ******************* health ******************* + + @ensure_jungle_health_packet_version + def health(self): + dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xd2, 0, 0, self.HEALTH_STRUCT.size) + a = self.HEALTH_STRUCT.unpack(dat) + return { + "uptime": a[0], + "ch1_power": a[1], + "ch2_power": a[2], + "ch3_power": a[3], + "ch4_power": a[4], + "ch5_power": a[5], + "ch6_power": a[6], + "ch1_sbu1_voltage": a[7] / 1000.0, + "ch1_sbu2_voltage": a[8] / 1000.0, + "ch2_sbu1_voltage": a[9] / 1000.0, + "ch2_sbu2_voltage": a[10] / 1000.0, + "ch3_sbu1_voltage": a[11] / 1000.0, + "ch3_sbu2_voltage": a[12] / 1000.0, + "ch4_sbu1_voltage": a[13] / 1000.0, + "ch4_sbu2_voltage": a[14] / 1000.0, + "ch5_sbu1_voltage": a[15] / 1000.0, + "ch5_sbu2_voltage": a[16] / 1000.0, + "ch6_sbu1_voltage": a[17] / 1000.0, + "ch6_sbu2_voltage": a[18] / 1000.0, + } + + # ******************* control ******************* + + # Returns tuple with health packet version and CAN packet/USB packet version + def get_packets_versions(self): + dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xdd, 0, 0, 3) + if dat and len(dat) == 3: + a = struct.unpack("BBB", dat) + return (a[0], a[1], a[2]) + return (-1, -1, -1) + + # ******************* jungle stuff ******************* + + def set_panda_power(self, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa0, int(enabled), 0, b'') + + def set_panda_individual_power(self, port, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa3, int(port), int(enabled), b'') + + def set_harness_orientation(self, mode): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa1, int(mode), 0, b'') + + def set_ignition(self, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa2, int(enabled), 0, b'') + + def set_can_silent(self, silent): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xf5, int(silent), 0, b'') + + def set_generated_can(self, enabled): + self._handle.controlWrite(PandaJungle.REQUEST_OUT, 0xa4, int(enabled), 0, b'') + + # ******************* serial ******************* + + def debug_read(self): + ret = [] + while 1: + lret = bytes(self._handle.controlRead(PandaJungle.REQUEST_IN, 0xe0, 0, 0, 0x40)) + if len(lret) == 0: + break + ret.append(lret) + return b''.join(ret) + + # ******************* header pins ******************* + + def set_header_pin(self, pin_num, enabled): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf7, int(pin_num), int(enabled), b'') diff --git a/panda/board/jungle/boards/board_declarations.h b/panda/board/jungle/boards/board_declarations.h new file mode 100644 index 0000000000..aad54dede7 --- /dev/null +++ b/panda/board/jungle/boards/board_declarations.h @@ -0,0 +1,60 @@ +// ******************** Prototypes ******************** +typedef void (*board_init)(void); +typedef void (*board_board_tick)(void); +typedef bool (*board_get_button)(void); +typedef void (*board_init_bootloader)(void); +typedef void (*board_set_panda_power)(bool enabled); +typedef void (*board_set_panda_individual_power)(uint8_t port_num, bool enabled); +typedef void (*board_set_ignition)(bool enabled); +typedef void (*board_set_individual_ignition)(uint8_t bitmask); +typedef void (*board_set_harness_orientation)(uint8_t orientation); +typedef void (*board_set_can_mode)(uint8_t mode); +typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled); +typedef void (*board_enable_header_pin)(uint8_t pin_num, bool enabled); +typedef float (*board_get_channel_power)(uint8_t channel); +typedef uint16_t (*board_get_sbu_mV)(uint8_t channel, uint8_t sbu); + +struct board { + GPIO_TypeDef * const led_GPIO[3]; + const uint8_t led_pin[3]; + const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM + const uint16_t avdd_mV; + board_init init; + board_board_tick board_tick; + board_get_button get_button; + board_init_bootloader init_bootloader; + board_set_panda_power set_panda_power; + board_set_panda_individual_power set_panda_individual_power; + board_set_ignition set_ignition; + board_set_individual_ignition set_individual_ignition; + board_set_harness_orientation set_harness_orientation; + board_set_can_mode set_can_mode; + board_enable_can_transceiver enable_can_transceiver; + board_enable_header_pin enable_header_pin; + board_get_channel_power get_channel_power; + board_get_sbu_mV get_sbu_mV; + + // TODO: shouldn't need these + bool has_spi; +}; + +// ******************* Definitions ******************** +#define HW_TYPE_UNKNOWN 0U +#define HW_TYPE_V2 2U + +// CAN modes +#define CAN_MODE_NORMAL 0U +#define CAN_MODE_OBD_CAN2 3U + +// Harness states +#define HARNESS_ORIENTATION_NONE 0U +#define HARNESS_ORIENTATION_1 1U +#define HARNESS_ORIENTATION_2 2U + +#define SBU1 0U +#define SBU2 1U + +// ********************* Globals ********************** +uint8_t harness_orientation = HARNESS_ORIENTATION_NONE; +uint8_t can_mode = CAN_MODE_NORMAL; +uint8_t ignition = 0U; diff --git a/panda/board/jungle/boards/board_v2.h b/panda/board/jungle/boards/board_v2.h new file mode 100644 index 0000000000..45f8fb9279 --- /dev/null +++ b/panda/board/jungle/boards/board_v2.h @@ -0,0 +1,308 @@ +// ///////////////////////// // +// Jungle board v2 (STM32H7) // +// ///////////////////////// // + +#define ADC_CHANNEL(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_810_CYCLES, .oversampling = OVERSAMPLING_1} + +gpio_t power_pins[] = { + {.bank = GPIOA, .pin = 0}, + {.bank = GPIOA, .pin = 1}, + {.bank = GPIOF, .pin = 12}, + {.bank = GPIOA, .pin = 5}, + {.bank = GPIOC, .pin = 5}, + {.bank = GPIOB, .pin = 2}, +}; + +gpio_t sbu1_ignition_pins[] = { + {.bank = GPIOD, .pin = 0}, + {.bank = GPIOD, .pin = 5}, + {.bank = GPIOD, .pin = 12}, + {.bank = GPIOD, .pin = 14}, + {.bank = GPIOE, .pin = 5}, + {.bank = GPIOE, .pin = 9}, +}; + +gpio_t sbu1_relay_pins[] = { + {.bank = GPIOD, .pin = 1}, + {.bank = GPIOD, .pin = 6}, + {.bank = GPIOD, .pin = 11}, + {.bank = GPIOD, .pin = 15}, + {.bank = GPIOE, .pin = 6}, + {.bank = GPIOE, .pin = 10}, +}; + +gpio_t sbu2_ignition_pins[] = { + {.bank = GPIOD, .pin = 3}, + {.bank = GPIOD, .pin = 8}, + {.bank = GPIOD, .pin = 9}, + {.bank = GPIOE, .pin = 0}, + {.bank = GPIOE, .pin = 7}, + {.bank = GPIOE, .pin = 11}, +}; + +gpio_t sbu2_relay_pins[] = { + {.bank = GPIOD, .pin = 4}, + {.bank = GPIOD, .pin = 10}, + {.bank = GPIOD, .pin = 13}, + {.bank = GPIOE, .pin = 1}, + {.bank = GPIOE, .pin = 8}, + {.bank = GPIOE, .pin = 12}, +}; + +const adc_signal_t sbu1_channels[] = { + ADC_CHANNEL(ADC3, 12), + ADC_CHANNEL(ADC3, 2), + ADC_CHANNEL(ADC3, 4), + ADC_CHANNEL(ADC3, 6), + ADC_CHANNEL(ADC3, 8), + ADC_CHANNEL(ADC3, 10), +}; + +const adc_signal_t sbu2_channels[] = { + ADC_CHANNEL(ADC1, 13), + ADC_CHANNEL(ADC3, 3), + ADC_CHANNEL(ADC3, 5), + ADC_CHANNEL(ADC3, 7), + ADC_CHANNEL(ADC3, 9), + ADC_CHANNEL(ADC3, 11), +}; + +void board_v2_set_harness_orientation(uint8_t orientation) { + switch (orientation) { + case HARNESS_ORIENTATION_NONE: + gpio_set_all_output(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), false); + harness_orientation = orientation; + break; + case HARNESS_ORIENTATION_1: + gpio_set_all_output(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), true); + gpio_set_bitmask(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), ignition); + gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), false); + harness_orientation = orientation; + break; + case HARNESS_ORIENTATION_2: + gpio_set_bitmask(sbu1_ignition_pins, sizeof(sbu1_ignition_pins) / sizeof(gpio_t), ignition); + gpio_set_all_output(sbu1_relay_pins, sizeof(sbu1_relay_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_ignition_pins, sizeof(sbu2_ignition_pins) / sizeof(gpio_t), false); + gpio_set_all_output(sbu2_relay_pins, sizeof(sbu2_relay_pins) / sizeof(gpio_t), true); + harness_orientation = orientation; + break; + default: + print("Tried to set an unsupported harness orientation: "); puth(orientation); print("\n"); + break; + } +} + +void board_v2_enable_can_transceiver(uint8_t transceiver, bool enabled) { + switch (transceiver) { + case 1U: + set_gpio_output(GPIOG, 11, !enabled); + break; + case 2U: + set_gpio_output(GPIOB, 3, !enabled); + break; + case 3U: + set_gpio_output(GPIOD, 7, !enabled); + break; + case 4U: + set_gpio_output(GPIOB, 4, !enabled); + break; + default: + print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n"); + break; + } +} + +void board_v2_enable_header_pin(uint8_t pin_num, bool enabled) { + if (pin_num < 8U) { + set_gpio_output(GPIOG, pin_num, enabled); + } else { + print("Invalid pin number ("); puth(pin_num); print("): enabling failed\n"); + } +} + +void board_v2_set_can_mode(uint8_t mode) { + board_v2_enable_can_transceiver(2U, false); + board_v2_enable_can_transceiver(4U, false); + switch (mode) { + case CAN_MODE_NORMAL: + // B12,B13: disable normal mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_mode(GPIOB, 12, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_mode(GPIOB, 13, MODE_ANALOG); + + // B5,B6: FDCAN2 mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + can_mode = CAN_MODE_NORMAL; + board_v2_enable_can_transceiver(2U, true); + break; + case CAN_MODE_OBD_CAN2: + // B5,B6: disable normal mode + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_mode(GPIOB, 5, MODE_ANALOG); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_mode(GPIOB, 6, MODE_ANALOG); + // B12,B13: FDCAN2 mode + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_alternate(GPIOB, 12, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 13, PULL_NONE); + set_gpio_alternate(GPIOB, 13, GPIO_AF9_FDCAN2); + can_mode = CAN_MODE_OBD_CAN2; + board_v2_enable_can_transceiver(4U, true); + break; + default: + break; + } +} + +bool panda_power = false; +uint8_t panda_power_bitmask = 0U; +void board_v2_set_panda_power(bool enable) { + panda_power = enable; + gpio_set_all_output(power_pins, sizeof(power_pins) / sizeof(gpio_t), enable); + if (enable) { + panda_power_bitmask = 0xFFU; + } else { + panda_power_bitmask = 0U; + } +} + +void board_v2_set_panda_individual_power(uint8_t port_num, bool enable) { + port_num -= 1U; + if (port_num < 6U) { + panda_power_bitmask &= ~(1U << port_num); + panda_power_bitmask |= (enable ? 1U : 0U) << port_num; + } else { + print("Invalid port number ("); puth(port_num); print("): enabling failed\n"); + } + gpio_set_bitmask(power_pins, sizeof(power_pins) / sizeof(gpio_t), (uint32_t)panda_power_bitmask); +} + +bool board_v2_get_button(void) { + return get_gpio_input(GPIOG, 15); +} + +void board_v2_set_ignition(bool enabled) { + ignition = enabled ? 0xFFU : 0U; + board_v2_set_harness_orientation(harness_orientation); +} + +void board_v2_set_individual_ignition(uint8_t bitmask) { + ignition = bitmask; + board_v2_set_harness_orientation(harness_orientation); +} + +float board_v2_get_channel_power(uint8_t channel) { + float ret = 0.0f; + if ((channel >= 1U) && (channel <= 6U)) { + uint16_t readout = adc_get_mV(&(const adc_signal_t) ADC_CHANNEL(ADC1, channel - 1U)); // these are mapped nicely in hardware + ret = (((float) readout / 33e6) - 0.8e-6) / 52e-6 * 12.0f; + } else { + print("Invalid channel ("); puth(channel); print(")\n"); + } + return ret; +} + +uint16_t board_v2_get_sbu_mV(uint8_t channel, uint8_t sbu) { + uint16_t ret = 0U; + if ((channel >= 1U) && (channel <= 6U)) { + switch(sbu){ + case SBU1: + ret = adc_get_mV(&sbu1_channels[channel - 1U]); + break; + case SBU2: + ret = adc_get_mV(&sbu2_channels[channel - 1U]); + break; + default: + print("Invalid SBU ("); puth(sbu); print(")\n"); + break; + } + } else { + print("Invalid channel ("); puth(channel); print(")\n"); + } + return ret; +} + +void board_v2_init(void) { + common_init_gpio(); + + // Normal CAN mode + board_v2_set_can_mode(CAN_MODE_NORMAL); + + // Enable CAN transceivers + for(uint8_t i = 1; i <= 4; i++) { + board_v2_enable_can_transceiver(i, true); + } + + // Set to no harness orientation + board_v2_set_harness_orientation(HARNESS_ORIENTATION_NONE); + + // Enable panda power by default + board_v2_set_panda_power(true); + + // Current monitor channels + adc_init(ADC1); + register_set_bits(&SYSCFG->PMCR, SYSCFG_PMCR_PA0SO | SYSCFG_PMCR_PA1SO); // open up analog switches for PA0_C and PA1_C + set_gpio_mode(GPIOF, 11, MODE_ANALOG); + set_gpio_mode(GPIOA, 6, MODE_ANALOG); + set_gpio_mode(GPIOC, 4, MODE_ANALOG); + set_gpio_mode(GPIOB, 1, MODE_ANALOG); + + // SBU channels + adc_init(ADC3); + set_gpio_mode(GPIOC, 2, MODE_ANALOG); + set_gpio_mode(GPIOC, 3, MODE_ANALOG); + set_gpio_mode(GPIOF, 9, MODE_ANALOG); + set_gpio_mode(GPIOF, 7, MODE_ANALOG); + set_gpio_mode(GPIOF, 5, MODE_ANALOG); + set_gpio_mode(GPIOF, 3, MODE_ANALOG); + set_gpio_mode(GPIOF, 10, MODE_ANALOG); + set_gpio_mode(GPIOF, 8, MODE_ANALOG); + set_gpio_mode(GPIOF, 6, MODE_ANALOG); + set_gpio_mode(GPIOF, 4, MODE_ANALOG); + set_gpio_mode(GPIOC, 0, MODE_ANALOG); + set_gpio_mode(GPIOC, 1, MODE_ANALOG); + + // Header pins + set_gpio_mode(GPIOG, 0, MODE_OUTPUT); + set_gpio_mode(GPIOG, 1, MODE_OUTPUT); + set_gpio_mode(GPIOG, 2, MODE_OUTPUT); + set_gpio_mode(GPIOG, 3, MODE_OUTPUT); + set_gpio_mode(GPIOG, 4, MODE_OUTPUT); + set_gpio_mode(GPIOG, 5, MODE_OUTPUT); + set_gpio_mode(GPIOG, 6, MODE_OUTPUT); + set_gpio_mode(GPIOG, 7, MODE_OUTPUT); +} + +void board_v2_tick(void) {} + +board board_v2 = { + .avdd_mV = 3300U, + .init = &board_v2_init, + .init_bootloader = &board_v2_tick, + .led_GPIO = {GPIOE, GPIOE, GPIOE}, + .led_pin = {4, 3, 2}, + .board_tick = &board_v2_tick, + .get_button = &board_v2_get_button, + .set_panda_power = &board_v2_set_panda_power, + .set_panda_individual_power = &board_v2_set_panda_individual_power, + .set_ignition = &board_v2_set_ignition, + .set_individual_ignition = &board_v2_set_individual_ignition, + .set_harness_orientation = &board_v2_set_harness_orientation, + .set_can_mode = &board_v2_set_can_mode, + .enable_can_transceiver = &board_v2_enable_can_transceiver, + .enable_header_pin = &board_v2_enable_header_pin, + .get_channel_power = &board_v2_get_channel_power, + .get_sbu_mV = &board_v2_get_sbu_mV, +}; diff --git a/panda/board/jungle/flash.py b/panda/board/jungle/flash.py new file mode 100755 index 0000000000..8378169e44 --- /dev/null +++ b/panda/board/jungle/flash.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import os +import subprocess +import argparse + +from panda import PandaJungle + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices") + args = parser.parse_args() + + subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True) + + if args.all: + serials = PandaJungle.list() + print(f"found {len(serials)} panda jungles(s) - {serials}") + else: + serials = [None] + + for s in serials: + with PandaJungle(serial=s) as p: + print("flashing", p.get_usb_serial()) + p.flash() + exit(1 if len(serials) == 0 else 0) diff --git a/panda/board/jungle/jungle_health.h b/panda/board/jungle/jungle_health.h new file mode 100644 index 0000000000..931ed3715e --- /dev/null +++ b/panda/board/jungle/jungle_health.h @@ -0,0 +1,24 @@ +// When changing these structs, python/__init__.py needs to be kept up to date! + +#define JUNGLE_HEALTH_PACKET_VERSION 1 +struct __attribute__((packed)) jungle_health_t { + uint32_t uptime_pkt; + float ch1_power; + float ch2_power; + float ch3_power; + float ch4_power; + float ch5_power; + float ch6_power; + uint16_t ch1_sbu1_mV; + uint16_t ch1_sbu2_mV; + uint16_t ch2_sbu1_mV; + uint16_t ch2_sbu2_mV; + uint16_t ch3_sbu1_mV; + uint16_t ch3_sbu2_mV; + uint16_t ch4_sbu1_mV; + uint16_t ch4_sbu2_mV; + uint16_t ch5_sbu1_mV; + uint16_t ch5_sbu2_mV; + uint16_t ch6_sbu1_mV; + uint16_t ch6_sbu2_mV; +}; diff --git a/panda/board/jungle/main.c b/panda/board/jungle/main.c new file mode 100644 index 0000000000..7bac6d751b --- /dev/null +++ b/panda/board/jungle/main.c @@ -0,0 +1,234 @@ +// ********************* Includes ********************* +#include "board/config.h" + +#include "opendbc/safety/safety.h" + +#include "board/drivers/led.h" +#include "board/drivers/pwm.h" +#include "board/drivers/usb.h" + +#include "board/early_init.h" +#include "board/provision.h" + +#include "board/health.h" +#include "board/jungle/jungle_health.h" + +#include "board/drivers/can_common.h" + +#include "board/drivers/fdcan.h" + +#include "board/obj/gitversion.h" + +#include "board/can_comms.h" +#include "board/jungle/main_comms.h" + + +// ********************* Serial debugging ********************* + +void debug_ring_callback(uart_ring *ring) { + char rcv; + while (get_char(ring, &rcv)) { + (void)injectc(ring, rcv); + } +} + +// ***************************** main code ***************************** + +// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck +void __initialize_hardware_early(void) { + early_initialization(); +} + +void __attribute__ ((noinline)) enable_fpu(void) { + // enable the FPU + SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U))); +} + +// called at 8Hz +uint32_t loop_counter = 0U; +uint16_t button_press_cnt = 0U; +void tick_handler(void) { + if (TICK_TIMER->SR != 0) { + if (generated_can_traffic) { + for (int i = 0; i < 3; i++) { + if (can_health[i].transmit_error_cnt >= 128) { + (void)llcan_init(CANIF_FROM_CAN_NUM(i)); + } + } + } + + // decimated to 1Hz + if ((loop_counter % 8) == 0U) { + #ifdef DEBUG + print("** blink "); + print("rx:"); puth4(can_rx_q.r_ptr); print("-"); puth4(can_rx_q.w_ptr); print(" "); + print("tx1:"); puth4(can_tx1_q.r_ptr); print("-"); puth4(can_tx1_q.w_ptr); print(" "); + print("tx2:"); puth4(can_tx2_q.r_ptr); print("-"); puth4(can_tx2_q.w_ptr); print(" "); + print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print("\n"); + #endif + + current_board->board_tick(); + + // check registers + check_registers(); + + // turn off the blue LED, turned on by CAN + led_set(LED_BLUE, false); + + // Blink and OBD CAN +#ifdef FINAL_PROVISIONING + current_board->set_can_mode(can_mode == CAN_MODE_NORMAL ? CAN_MODE_OBD_CAN2 : CAN_MODE_NORMAL); +#endif + + // on to the next one + uptime_cnt += 1U; + } + + // Check on button + bool current_button_status = current_board->get_button(); + + if (current_button_status && button_press_cnt == 10) { + current_board->set_panda_power(!panda_power); + } + +#ifdef FINAL_PROVISIONING + // Ignition blinking + uint8_t ignition_bitmask = 0U; + for (uint8_t i = 0U; i < 6U; i++) { + ignition_bitmask |= ((loop_counter % 12U) < ((uint32_t) i + 2U)) << i; + } + current_board->set_individual_ignition(ignition_bitmask); + + // SBU voltage reporting + for (uint8_t i = 0U; i < 6U; i++) { + CANPacket_t pkt = { 0 }; + pkt.data_len_code = 8U; + pkt.addr = 0x100U + i; + *(uint16_t *) &pkt.data[0] = current_board->get_sbu_mV(i + 1U, SBU1); + *(uint16_t *) &pkt.data[2] = current_board->get_sbu_mV(i + 1U, SBU2); + pkt.data[4] = (ignition_bitmask >> i) & 1U; + can_set_checksum(&pkt); + can_send(&pkt, 0U, false); + } +#else + // toggle ignition on button press + static bool prev_button_status = false; + if (!current_button_status && prev_button_status && button_press_cnt < 10){ + current_board->set_ignition(!ignition); + } + prev_button_status = current_button_status; +#endif + + button_press_cnt = current_button_status ? button_press_cnt + 1 : 0; + + loop_counter++; + } + TICK_TIMER->SR = 0; +} + + +int main(void) { + // Init interrupt table + init_interrupts(true); + + // shouldn't have interrupts here, but just in case + disable_interrupts(); + + // init early devices + clock_init(); + peripherals_init(); + detect_board_type(); + // red+green leds enabled until succesful USB init, as a debug indicator + led_set(LED_RED, true); + led_set(LED_GREEN, true); + + // print hello + print("\n\n\n************************ MAIN START ************************\n"); + + // check for non-supported board types + assert_fatal(hw_type != HW_TYPE_UNKNOWN, "Unsupported board type\n"); + + print("Config:\n"); + print(" Board type: 0x"); puth(hw_type); print("\n"); + + // init board + current_board->init(); + + // we have an FPU, let's use it! + enable_fpu(); + + microsecond_timer_init(); + + // 8Hz timer + REGISTER_INTERRUPT(TICK_TIMER_IRQ, tick_handler, 10U, FAULT_INTERRUPT_RATE_TICK) + tick_timer_init(); + +#ifdef DEBUG + print("DEBUG ENABLED\n"); +#endif + // enable USB (right before interrupts or enum can fail!) + usb_init(); + + led_set(LED_RED, false); + led_set(LED_GREEN, false); + + print("**** INTERRUPTS ON ****\n"); + enable_interrupts(); + + can_silent = false; + set_safety_hooks(SAFETY_ALLOUTPUT, 0U); + + can_init_all(); + current_board->set_harness_orientation(HARNESS_ORIENTATION_1); + +#ifdef FINAL_PROVISIONING + print("---- FINAL PROVISIONING BUILD ---- \n"); + can_set_forwarding(0, 2); + can_set_forwarding(1, 2); +#endif + + // LED should keep on blinking all the time + uint32_t cnt = 0; + for (cnt=0;;cnt++) { + if (generated_can_traffic) { + // fill up all the queues + can_ring *qs[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q}; + for (int j = 0; j < 3; j++) { + for (uint16_t n = 0U; n < can_slots_empty(qs[j]); n++) { + uint16_t i = cnt % 100U; + CANPacket_t to_send; + to_send.returned = 0U; + to_send.rejected = 0U; + to_send.extended = 0U; + to_send.addr = 0x200U + i; + to_send.bus = i % 3U; + to_send.data_len_code = i % 8U; + (void)memcpy(to_send.data, "\xff\xff\xff\xff\xff\xff\xff\xff", dlc_to_len[to_send.data_len_code]); + can_set_checksum(&to_send); + + can_send(&to_send, to_send.bus, true); + } + } + + delay(1000); + continue; + } + + // useful for debugging, fade breaks = panda is overloaded + for (uint32_t fade = 0U; fade < MAX_LED_FADE; fade += 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + + for (uint32_t fade = MAX_LED_FADE; fade > 0U; fade -= 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + } + + return 0; +} diff --git a/panda/board/jungle/main_comms.h b/panda/board/jungle/main_comms.h new file mode 100644 index 0000000000..b19f799ad9 --- /dev/null +++ b/panda/board/jungle/main_comms.h @@ -0,0 +1,261 @@ +extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used + +bool generated_can_traffic = false; + +int get_jungle_health_pkt(void *dat) { + COMPILE_TIME_ASSERT(sizeof(struct jungle_health_t) <= USBPACKET_MAX_SIZE); + struct jungle_health_t * health = (struct jungle_health_t*)dat; + + health->uptime_pkt = uptime_cnt; + health->ch1_power = current_board->get_channel_power(1U); + health->ch2_power = current_board->get_channel_power(2U); + health->ch3_power = current_board->get_channel_power(3U); + health->ch4_power = current_board->get_channel_power(4U); + health->ch5_power = current_board->get_channel_power(5U); + health->ch6_power = current_board->get_channel_power(6U); + + health->ch1_sbu1_mV = current_board->get_sbu_mV(1U, SBU1); + health->ch1_sbu2_mV = current_board->get_sbu_mV(1U, SBU2); + health->ch2_sbu1_mV = current_board->get_sbu_mV(2U, SBU1); + health->ch2_sbu2_mV = current_board->get_sbu_mV(2U, SBU2); + health->ch3_sbu1_mV = current_board->get_sbu_mV(3U, SBU1); + health->ch3_sbu2_mV = current_board->get_sbu_mV(3U, SBU2); + health->ch4_sbu1_mV = current_board->get_sbu_mV(4U, SBU1); + health->ch4_sbu2_mV = current_board->get_sbu_mV(4U, SBU2); + health->ch5_sbu1_mV = current_board->get_sbu_mV(5U, SBU1); + health->ch5_sbu2_mV = current_board->get_sbu_mV(5U, SBU2); + health->ch6_sbu1_mV = current_board->get_sbu_mV(6U, SBU1); + health->ch6_sbu2_mV = current_board->get_sbu_mV(6U, SBU2); + + return sizeof(*health); +} + +// send on serial, first byte to select the ring +void comms_endpoint2_write(const uint8_t *data, uint32_t len) { + UNUSED(data); + UNUSED(len); +} + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { + unsigned int resp_len = 0; + uint32_t time; + +#ifdef DEBUG_COMMS + print("raw control request: "); hexdump(req, sizeof(ControlPacket_t)); print("\n"); + print("- request "); puth(req->request); print("\n"); + print("- param1 "); puth(req->param1); print("\n"); + print("- param2 "); puth(req->param2); print("\n"); +#endif + + switch (req->request) { + // **** 0xa0: Set panda power. + case 0xa0: + current_board->set_panda_power((req->param1 == 1U)); + break; + // **** 0xa1: Set harness orientation. + case 0xa1: + current_board->set_harness_orientation(req->param1); + break; + // **** 0xa2: Set ignition. + case 0xa2: + current_board->set_ignition((req->param1 == 1U)); + break; + // **** 0xa3: Set panda power per channel by bitmask. + case 0xa3: + current_board->set_panda_individual_power(req->param1, (req->param2 > 0U)); + break; + // **** 0xa4: Enable generated CAN traffic. + case 0xa4: + generated_can_traffic = (req->param1 > 0U); + break; + // **** 0xa8: get microsecond timer + case 0xa8: + time = microsecond_timer_get(); + resp[0] = (time & 0x000000FFU); + resp[1] = ((time & 0x0000FF00U) >> 8U); + resp[2] = ((time & 0x00FF0000U) >> 16U); + resp[3] = ((time & 0xFF000000U) >> 24U); + resp_len = 4U; + break; + // **** 0xc0: reset communications + case 0xc0: + comms_can_reset(); + break; + // **** 0xc1: get hardware type + case 0xc1: + resp[0] = hw_type; + resp_len = 1; + break; + // **** 0xc2: CAN health stats + case 0xc2: + COMPILE_TIME_ASSERT(sizeof(can_health_t) <= USBPACKET_MAX_SIZE); + if (req->param1 < 3U) { + update_can_health_pkt(req->param1, 0U); + can_health[req->param1].can_speed = (bus_config[req->param1].can_speed / 10U); + can_health[req->param1].can_data_speed = (bus_config[req->param1].can_data_speed / 10U); + can_health[req->param1].canfd_enabled = bus_config[req->param1].canfd_enabled; + can_health[req->param1].brs_enabled = bus_config[req->param1].brs_enabled; + can_health[req->param1].canfd_non_iso = bus_config[req->param1].canfd_non_iso; + resp_len = sizeof(can_health[req->param1]); + (void)memcpy(resp, &can_health[req->param1], resp_len); + } + break; + // **** 0xc3: fetch MCU UID + case 0xc3: + (void)memcpy(resp, ((uint8_t *)UID_BASE), 12); + resp_len = 12; + break; + // **** 0xd0: fetch serial (aka the provisioned dongle ID) + case 0xd0: + // addresses are OTP + if (req->param1 == 1U) { + (void)memcpy(resp, (uint8_t *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } + break; + // **** 0xd1: enter bootloader mode + case 0xd1: + // this allows reflashing of the bootstub + switch (req->param1) { + case 0: + // only allow bootloader entry on debug builds + #ifdef ALLOW_DEBUG + print("-> entering bootloader\n"); + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + #endif + break; + case 1: + print("-> entering softloader\n"); + enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; + NVIC_SystemReset(); + break; + default: + print("Bootloader mode invalid\n"); + break; + } + break; + // **** 0xd2: get health packet + case 0xd2: + resp_len = get_jungle_health_pkt(resp); + break; + // **** 0xd3: get first 64 bytes of signature + case 0xd3: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len], resp_len); + } + break; + // **** 0xd4: get second 64 bytes of signature + case 0xd4: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len + 64], resp_len); + } + break; + // **** 0xd6: get version + case 0xd6: + COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); + (void)memcpy(resp, gitversion, sizeof(gitversion)); + resp_len = sizeof(gitversion) - 1U; + break; + // **** 0xd8: reset ST + case 0xd8: + NVIC_SystemReset(); + break; + // **** 0xdb: set OBD CAN multiplexing mode + case 0xdb: + if (req->param1 == 1U) { + // Enable OBD CAN + current_board->set_can_mode(CAN_MODE_OBD_CAN2); + } else { + // Disable OBD CAN + current_board->set_can_mode(CAN_MODE_NORMAL); + } + break; + // **** 0xdd: get healthpacket and CANPacket versions + case 0xdd: + resp[0] = JUNGLE_HEALTH_PACKET_VERSION; + resp[1] = CAN_PACKET_VERSION; + resp[2] = CAN_HEALTH_PACKET_VERSION; + resp_len = 3; + break; + // **** 0xde: set can bitrate + case 0xde: + if ((req->param1 < PANDA_CAN_CNT) && is_speed_valid(req->param2, speeds, sizeof(speeds)/sizeof(speeds[0]))) { + bus_config[req->param1].can_speed = req->param2; + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xe0: debug read + case 0xe0: + // read + while ((resp_len < MIN(req->length, USBPACKET_MAX_SIZE)) && get_char(get_ring_by_number(0), (char*)&resp[resp_len])) { + ++resp_len; + } + break; + // **** 0xe5: set CAN loopback (for testing) + case 0xe5: + can_loopback = (req->param1 > 0U); + can_init_all(); + break; + // **** 0xf1: Clear CAN ring buffer. + case 0xf1: + if (req->param1 == 0xFFFFU) { + print("Clearing CAN Rx queue\n"); + can_clear(&can_rx_q); + } else if (req->param1 < PANDA_CAN_CNT) { + print("Clearing CAN Tx queue\n"); + can_clear(can_queues[req->param1]); + } else { + print("Clearing CAN CAN ring buffer failed: wrong bus number\n"); + } + break; + // **** 0xf4: Set CAN transceiver enable pin + case 0xf4: + current_board->enable_can_transceiver(req->param1, req->param2 > 0U); + break; + // **** 0xf5: Set CAN silent mode + case 0xf5: + can_silent = (req->param1 > 0U); + can_init_all(); + break; + // **** 0xf7: enable/disable header pin by number + case 0xf7: + current_board->enable_header_pin(req->param1, req->param2 > 0U); + break; + // **** 0xf9: set CAN FD data bitrate + case 0xf9: + if ((req->param1 < PANDA_CAN_CNT) && + is_speed_valid(req->param2, data_speeds, sizeof(data_speeds)/sizeof(data_speeds[0]))) { + bus_config[req->param1].can_data_speed = req->param2; + bus_config[req->param1].canfd_enabled = (req->param2 >= bus_config[req->param1].can_speed); + bus_config[req->param1].brs_enabled = (req->param2 > bus_config[req->param1].can_speed); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xfc: set CAN FD non-ISO mode + case 0xfc: + if (req->param1 < PANDA_CAN_CNT) { + bus_config[req->param1].canfd_non_iso = (req->param2 != 0U); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + default: + print("NO HANDLER "); + puth(req->request); + print("\n"); + break; + } + return resp_len; +} diff --git a/panda/board/jungle/recover.py b/panda/board/jungle/recover.py new file mode 100755 index 0000000000..34c88e26ef --- /dev/null +++ b/panda/board/jungle/recover.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import os +import time +import subprocess +import argparse + +from panda import PandaJungle, PandaJungleDFU + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices") + args = parser.parse_args() + + subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True) + + serials = PandaJungle.list() if args.all else [None] + for s in serials: + with PandaJungle(serial=s) as p: + print(f"putting {p.get_usb_serial()} in DFU mode") + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + + # wait for reset panda jungles to come back up + time.sleep(1) + + dfu_serials = PandaJungleDFU.list() + print(f"found {len(dfu_serials)} panda jungle(s) in DFU - {dfu_serials}") + for s in dfu_serials: + print("flashing", s) + PandaJungleDFU(s).recover() + exit(1 if len(dfu_serials) == 0 else 0) diff --git a/panda/board/jungle/scripts/can_health.py b/panda/board/jungle/scripts/can_health.py new file mode 100755 index 0000000000..47efbb2e67 --- /dev/null +++ b/panda/board/jungle/scripts/can_health.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import time +import re +from panda import PandaJungle + +RED = '\033[91m' +GREEN = '\033[92m' + +def colorize_errors(value): + if isinstance(value, str): + if re.search(r'(?i)No error', value): + return f'{GREEN}{value}\033[0m' + elif re.search(r'(?i)(? 0.1: + dd = chr(27) + "[2J" + dd += "%5.2f\n" % (sec_since_boot() - start) + for (addr, bus), dat_log in sorted(all_msgs.items()): + dd += "%d: %s(%6d): %s\n" % (bus, "%04X(%4d)" % (addr, addr), len(dat_log), binascii.hexlify(dat_log[-1]).decode()) + print(dd) + lp = sec_since_boot() + +if __name__ == "__main__": + can_printer() diff --git a/panda/board/jungle/scripts/debug_console.py b/panda/board/jungle/scripts/debug_console.py new file mode 100755 index 0000000000..f35388796f --- /dev/null +++ b/panda/board/jungle/scripts/debug_console.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import os +import sys +import time + +from panda import PandaJungle + +setcolor = ["\033[1;32;40m", "\033[1;31;40m"] +unsetcolor = "\033[00m" + +if __name__ == "__main__": + while True: + try: + claim = os.getenv("CLAIM") is not None + + serials = PandaJungle.list() + if os.getenv("SERIAL"): + serials = [x for x in serials if x==os.getenv("SERIAL")] + + panda_jungles = [PandaJungle(x, claim=claim) for x in serials] + + if not len(panda_jungles): + sys.exit("no panda jungles found") + + while True: + for i, panda_jungle in enumerate(panda_jungles): + while True: + ret = panda_jungle.debug_read() + if len(ret) > 0: + sys.stdout.write(setcolor[i] + ret.decode('ascii') + unsetcolor) + sys.stdout.flush() + else: + break + time.sleep(0.01) + except Exception as e: + print(e) + print("panda jungle disconnected!") + time.sleep(0.5) diff --git a/panda/board/jungle/scripts/echo_loopback_test.py b/panda/board/jungle/scripts/echo_loopback_test.py new file mode 100755 index 0000000000..2cc523c8fa --- /dev/null +++ b/panda/board/jungle/scripts/echo_loopback_test.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +import os +import time +import contextlib +import random +from termcolor import cprint + +from panda import PandaJungle + +# This script is intended to be used in conjunction with the echo.py test script from panda. +# It sends messages on bus 0, 1, 2 and checks for a reversed response to be sent back. + +################################################################# +############################# UTILS ############################# +################################################################# +def print_colored(text, color): + cprint(text + " "*40, color, end="\r") + +def get_test_string(): + return b"test"+os.urandom(4) + +################################################################# +############################# TEST ############################## +################################################################# + +def test_loopback(): + for bus in range(3): + # Clear can + jungle.can_clear(bus) + # Send a random message + address = random.randint(1, 2000) + data = get_test_string() + jungle.can_send(address, data, bus) + time.sleep(0.1) + + # Make sure it comes back reversed + incoming = jungle.can_recv() + found = False + for message in incoming: + incomingAddress, incomingData, incomingBus = message + if incomingAddress == address and incomingData == data[::-1] and incomingBus == bus: + found = True + break + if not found: + cprint("\nFAILED", "red") + raise AssertionError + +################################################################# +############################# MAIN ############################## +################################################################# +jungle = None +counter = 0 + +if __name__ == "__main__": + # Connect to jungle silently + print_colored("Connecting to jungle", "blue") + with open(os.devnull, "w") as devnull: + with contextlib.redirect_stdout(devnull): + jungle = PandaJungle() + jungle.set_panda_power(True) + jungle.set_ignition(False) + + # Run test + while True: + jungle.can_clear(0xFFFF) + test_loopback() + counter += 1 + print_colored(str(counter) + " loopback cycles complete", "blue") diff --git a/panda/board/jungle/scripts/get_version.py b/panda/board/jungle/scripts/get_version.py new file mode 100755 index 0000000000..4fc9d30bef --- /dev/null +++ b/panda/board/jungle/scripts/get_version.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +from panda import PandaJungle + +if __name__ == "__main__": + for p in PandaJungle.list(): + pp = PandaJungle(p) + print(f"{pp.get_serial()[0]}: {pp.get_version()}") + + diff --git a/panda/board/jungle/scripts/health_test.py b/panda/board/jungle/scripts/health_test.py new file mode 100755 index 0000000000..039f840e0b --- /dev/null +++ b/panda/board/jungle/scripts/health_test.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import time +from pprint import pprint + +from panda import PandaJungle + +if __name__ == "__main__": + i = 0 + pi = 0 + + pj = PandaJungle() + while True: + st = time.monotonic() + while time.monotonic() - st < 1: + pj.health() + pj.can_health(0) + i += 1 + pprint(pj.health()) + print(f"Speed: {i - pi}Hz") + pi = i + diff --git a/panda/board/jungle/scripts/loopback_test.py b/panda/board/jungle/scripts/loopback_test.py new file mode 100755 index 0000000000..8bb571cd09 --- /dev/null +++ b/panda/board/jungle/scripts/loopback_test.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +import os +import time +import contextlib +import random +from termcolor import cprint + +from opendbc.car.structs import CarParams +from panda import Panda, PandaJungle + +NUM_PANDAS_PER_TEST = 1 +FOR_RELEASE_BUILDS = os.getenv("RELEASE") is not None # Release builds do not have ALLOUTPUT mode + +BUS_SPEEDS = [125, 500, 1000] + +################################################################# +############################# UTILS ############################# +################################################################# +# To suppress the connection text +def silent_panda_connect(serial): + with open(os.devnull, "w") as devnull: + with contextlib.redirect_stdout(devnull): + panda = Panda(serial) + return panda + +def print_colored(text, color): + cprint(text + " "*40, color, end="\r") + +def connect_to_pandas(): + print_colored("Connecting to pandas", "blue") + # Connect to pandas + pandas = [] + for serial in panda_serials: + pandas.append(silent_panda_connect(serial)) + print_colored("Connected", "blue") + +def start_with_orientation(orientation): + print_colored("Restarting pandas with orientation " + str(orientation), "blue") + jungle.set_panda_power(False) + jungle.set_harness_orientation(orientation) + time.sleep(4) + jungle.set_panda_power(True) + time.sleep(2) + connect_to_pandas() + +def can_loopback(sender): + receivers = list(filter((lambda p: (p != sender)), [jungle] + pandas)) + + for bus in range(4): + obd = False + if bus == 3: + obd = True + bus = 1 + + # Clear buses + for receiver in receivers: + receiver.set_obd(obd) + receiver.can_clear(bus) # TX + receiver.can_clear(0xFFFF) # RX + + # Send a random string + addr = 0x18DB33F1 if FOR_RELEASE_BUILDS else random.randint(1, 2000) + string = b"test"+os.urandom(4) + sender.set_obd(obd) + time.sleep(0.2) + sender.can_send(addr, string, bus) + time.sleep(0.2) + + # Check if all receivers have indeed received them in their receiving buffers + for receiver in receivers: + content = receiver.can_recv() + + # Check amount of messages + if len(content) != 1: + raise Exception("Amount of received CAN messages (" + str(len(content)) + ") does not equal 1. Bus: " + str(bus) +" OBD: " + str(obd)) + + # Check content + if content[0][0] != addr or content[0][1] != string: + raise Exception("Received CAN message content or address does not match") + + # Check bus + if content[0][2] != bus: + raise Exception("Received CAN message bus does not match") + +################################################################# +############################# TEST ############################## +################################################################# + +def test_loopback(): + # disable safety modes + for panda in pandas: + panda.set_safety_mode(CarParams.SafetyModel.elm327 if FOR_RELEASE_BUILDS else CarParams.SafetyModel.allOutput) + + # perform loopback with jungle as a sender + can_loopback(jungle) + + # perform loopback with each possible panda as a sender + for panda in pandas: + can_loopback(panda) + + # enable safety modes + for panda in pandas: + panda.set_safety_mode(CarParams.SafetyModel.silent) + +################################################################# +############################# MAIN ############################## +################################################################# +jungle = None +pandas = [] # type: ignore +panda_serials = [] +counter = 0 + +if __name__ == "__main__": + # Connect to jungle silently + print_colored("Connecting to jungle", "blue") + with open(os.devnull, "w") as devnull: + with contextlib.redirect_stdout(devnull): + jungle = PandaJungle() + jungle.set_panda_power(True) + jungle.set_ignition(False) + + # Connect to new pandas before starting tests + print_colored("Waiting for " + str(NUM_PANDAS_PER_TEST) + " pandas to be connected", "yellow") + while True: + connected_serials = Panda.list() + if len(connected_serials) == NUM_PANDAS_PER_TEST: + panda_serials = connected_serials + break + + start_with_orientation(PandaJungle.HARNESS_ORIENTATION_1) + + # Set bus speeds + for device in pandas + [jungle]: + for bus in range(len(BUS_SPEEDS)): + device.set_can_speed_kbps(bus, BUS_SPEEDS[bus]) + + # Run test + while True: + test_loopback() + counter += 1 + print_colored(str(counter) + " loopback cycles complete", "blue") diff --git a/panda/board/jungle/scripts/spam_can.py b/panda/board/jungle/scripts/spam_can.py new file mode 100755 index 0000000000..d2f50df3b9 --- /dev/null +++ b/panda/board/jungle/scripts/spam_can.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import os +import random +from opendbc.car.structs import CarParams +from panda import PandaJungle + +def get_test_string(): + return b"test" + os.urandom(10) + +if __name__ == "__main__": + p = PandaJungle() + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + print("Spamming all buses...") + while True: + at = random.randint(1, 2000) + st = get_test_string()[0:8] + bus = random.randint(0, 2) + p.can_send(at, st, bus) + # print("Sent message on bus: ", bus) diff --git a/panda/board/jungle/scripts/start.py b/panda/board/jungle/scripts/start.py new file mode 100755 index 0000000000..76afd14ac4 --- /dev/null +++ b/panda/board/jungle/scripts/start.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +import sys + +from panda import PandaJungle + +if __name__ == "__main__": + jungle = PandaJungle() + + # If first argument specified, it sets the ignition (0 or 1) + if len(sys.argv) > 1: + if sys.argv[1] == '1': + jungle.set_ignition(True) + else: + jungle.set_ignition(False) + jungle.set_harness_orientation(1) + jungle.set_panda_power(True) + + diff --git a/panda/board/jungle/stm32h7/board.h b/panda/board/jungle/stm32h7/board.h new file mode 100644 index 0000000000..760a70416a --- /dev/null +++ b/panda/board/jungle/stm32h7/board.h @@ -0,0 +1,9 @@ +#include "board/jungle/boards/board_declarations.h" + +#include "board/stm32h7/lladc.h" +#include "board/jungle/boards/board_v2.h" + +void detect_board_type(void) { + hw_type = HW_TYPE_V2; + current_board = &board_v2; +} diff --git a/panda/board/libc.h b/panda/board/libc.h new file mode 100644 index 0000000000..c5f0219350 --- /dev/null +++ b/panda/board/libc.h @@ -0,0 +1,77 @@ +// **** libc **** + +void delay(uint32_t a) { + volatile uint32_t i; + for (i = 0; i < a; i++); +} + +void assert_fatal(bool condition, const char *msg) { + if (!condition) { + print("ASSERT FAILED\n"); + print(msg); + while (1) { + // hang + } + } +} + +// cppcheck-suppress misra-c2012-21.2 +void *memset(void *str, int c, unsigned int n) { + uint8_t *s = str; + for (unsigned int i = 0; i < n; i++) { + *s = c; + s++; + } + return str; +} + +#define UNALIGNED(X, Y) \ + (((uint32_t)(X) & (sizeof(uint32_t) - 1U)) | ((uint32_t)(Y) & (sizeof(uint32_t) - 1U))) + +// cppcheck-suppress misra-c2012-21.2 +void *memcpy(void *dest, const void *src, unsigned int len) { + unsigned int n = len; + uint8_t *d8 = dest; + const uint8_t *s8 = src; + + if ((n >= 4U) && !UNALIGNED(s8, d8)) { + uint32_t *d32 = (uint32_t *)d8; // cppcheck-suppress misra-c2012-11.3 ; already checked that it's properly aligned + const uint32_t *s32 = (const uint32_t *)s8; // cppcheck-suppress misra-c2012-11.3 ; already checked that it's properly aligned + + while(n >= 16U) { + *d32 = *s32; d32++; s32++; + *d32 = *s32; d32++; s32++; + *d32 = *s32; d32++; s32++; + *d32 = *s32; d32++; s32++; + n -= 16U; + } + + while(n >= 4U) { + *d32 = *s32; d32++; s32++; + n -= 4U; + } + + d8 = (uint8_t *)d32; + s8 = (const uint8_t *)s32; + } + while (n-- > 0U) { + *d8 = *s8; d8++; s8++; + } + return dest; +} + +// cppcheck-suppress misra-c2012-21.2 +int memcmp(const void * ptr1, const void * ptr2, unsigned int num) { + int ret = 0; + const uint8_t *p1 = ptr1; + const uint8_t *p2 = ptr2; + for (unsigned int i = 0; i < num; i++) { + if (*p1 != *p2) { + ret = -1; + break; + } + p1++; + p2++; + } + return ret; +} diff --git a/panda/board/main.c b/panda/board/main.c new file mode 100644 index 0000000000..ac0fda9ba4 --- /dev/null +++ b/panda/board/main.c @@ -0,0 +1,378 @@ +// ********************* Includes ********************* +#include "board/config.h" + +#include "board/drivers/led.h" +#include "board/drivers/pwm.h" +#include "board/drivers/usb.h" +#include "board/drivers/simple_watchdog.h" +#include "board/drivers/bootkick.h" + +#include "board/early_init.h" +#include "board/provision.h" + +#include "opendbc/safety/safety.h" + +#include "board/health.h" + +#include "board/drivers/can_common.h" + +#include "board/drivers/fdcan.h" + +#include "board/power_saving.h" + +#include "board/obj/gitversion.h" + +#include "board/can_comms.h" +#include "board/main_comms.h" + + +// ********************* Serial debugging ********************* + +void debug_ring_callback(uart_ring *ring) { + char rcv; + while (get_char(ring, &rcv)) { + (void)put_char(ring, rcv); // misra-c2012-17.7: cast to void is ok: debug function + } +} + +// ****************************** safety mode ****************************** + +// this is the only way to leave silent mode +void set_safety_mode(uint16_t mode, uint16_t param) { + uint16_t mode_copy = mode; + int err = set_safety_hooks(mode_copy, param); + if (err == -1) { + print("Error: safety set mode failed. Falling back to SILENT\n"); + mode_copy = SAFETY_SILENT; + err = set_safety_hooks(mode_copy, 0U); + // TERMINAL ERROR: we can't continue if SILENT safety mode isn't succesfully set + assert_fatal(err == 0, "Error: Failed setting SILENT mode. Hanging\n"); + } + safety_tx_blocked = 0; + safety_rx_invalid = 0; + + switch (mode_copy) { + case SAFETY_SILENT: + set_intercept_relay(false, false); + current_board->set_can_mode(CAN_MODE_NORMAL); + can_silent = true; + break; + case SAFETY_NOOUTPUT: + set_intercept_relay(false, false); + current_board->set_can_mode(CAN_MODE_NORMAL); + can_silent = false; + break; + case SAFETY_ELM327: + set_intercept_relay(false, false); + heartbeat_counter = 0U; + heartbeat_lost = false; + + // Clear any pending messages in the can core (i.e. sending while comma power is unplugged) + // TODO: rewrite using hardware queues rather than fifo to cancel specific messages + can_clear_send(CANIF_FROM_CAN_NUM(1), 1); + if (param == 0U) { + current_board->set_can_mode(CAN_MODE_OBD_CAN2); + } else { + current_board->set_can_mode(CAN_MODE_NORMAL); + } + can_silent = false; + break; + default: + set_intercept_relay(true, false); + heartbeat_counter = 0U; + heartbeat_lost = false; + current_board->set_can_mode(CAN_MODE_NORMAL); + can_silent = false; + break; + } + can_init_all(); +} + +bool is_car_safety_mode(uint16_t mode) { + return (mode != SAFETY_SILENT) && + (mode != SAFETY_NOOUTPUT) && + (mode != SAFETY_ALLOUTPUT) && + (mode != SAFETY_ELM327); +} + +// ***************************** main code ***************************** + +// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck +// cppcheck-suppress misra-c2012-8.4 +void __initialize_hardware_early(void) { + early_initialization(); +} + +static void __attribute__ ((noinline)) enable_fpu(void) { + // enable the FPU + SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U))); +} + +// go into SILENT when heartbeat isn't received for this amount of seconds. +#define HEARTBEAT_IGNITION_CNT_ON 5U +#define HEARTBEAT_IGNITION_CNT_OFF 2U + +// called at 8Hz +static void tick_handler(void) { + static uint32_t siren_countdown = 0; // siren plays while countdown > 0 + static uint32_t controls_allowed_countdown = 0; + static uint8_t prev_harness_status = HARNESS_STATUS_NC; + static uint8_t loop_counter = 0U; + static bool relay_malfunction_prev = false; + + if (TICK_TIMER->SR != 0U) { + + // siren + current_board->set_siren((loop_counter & 1U) && (siren_enabled || (siren_countdown > 0U))); + + // tick drivers at 8Hz + fan_tick(); + harness_tick(); + simple_watchdog_kick(); + sound_tick(); + + if (relay_malfunction_prev != relay_malfunction) { + if (relay_malfunction) { + fault_occurred(FAULT_RELAY_MALFUNCTION); + } else { + fault_recovered(FAULT_RELAY_MALFUNCTION); + } + } + relay_malfunction_prev = relay_malfunction; + + // re-init everything that uses harness status + if (harness.status != prev_harness_status) { + prev_harness_status = harness.status; + can_set_orientation(harness.status == HARNESS_STATUS_FLIPPED); + + // re-init everything that uses harness status + can_init_all(); + set_safety_mode(current_safety_mode, current_safety_param); + set_power_save_state(power_save_status); + } + + // decimated to 1Hz + if (loop_counter == 0U) { + //puth(usart1_dma); print(" "); puth(DMA2_Stream5->M0AR); print(" "); puth(DMA2_Stream5->NDTR); print("\n"); + #ifdef DEBUG + print("** blink "); + print("rx:"); puth4(can_rx_q.r_ptr); print("-"); puth4(can_rx_q.w_ptr); print(" "); + print("tx1:"); puth4(can_tx1_q.r_ptr); print("-"); puth4(can_tx1_q.w_ptr); print(" "); + print("tx2:"); puth4(can_tx2_q.r_ptr); print("-"); puth4(can_tx2_q.w_ptr); print(" "); + print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print("\n"); + #endif + + // set green LED to be controls allowed + led_set(LED_GREEN, controls_allowed); + + // turn off the blue LED, turned on by CAN + // unless we are in power saving mode + led_set(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED)); + + const bool recent_heartbeat = heartbeat_counter == 0U; + + // tick drivers at 1Hz + bool started = harness_check_ignition() || ignition_can; + bootkick_tick(started, recent_heartbeat); + + // increase heartbeat counter and cap it at the uint32 limit + if (heartbeat_counter < UINT32_MAX) { + heartbeat_counter += 1U; + } + + // disabling heartbeat not allowed while in safety mode + if (is_car_safety_mode(current_safety_mode)) { + heartbeat_disabled = false; + } + + if (siren_countdown > 0U) { + siren_countdown -= 1U; + } + + if (controls_allowed || heartbeat_engaged) { + controls_allowed_countdown = 5U; + } else if (controls_allowed_countdown > 0U) { + controls_allowed_countdown -= 1U; + } else { + + } + + // exit controls allowed if unused by openpilot for a few seconds + if (controls_allowed && !heartbeat_engaged) { + heartbeat_engaged_mismatches += 1U; + if (heartbeat_engaged_mismatches >= 3U) { + controls_allowed = false; + } + } else { + heartbeat_engaged_mismatches = 0U; + } + + if (!heartbeat_disabled) { + // if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save + if (heartbeat_counter >= (started ? HEARTBEAT_IGNITION_CNT_ON : HEARTBEAT_IGNITION_CNT_OFF)) { + print("device hasn't sent a heartbeat for 0x"); + puth(heartbeat_counter); + print(" seconds. Safety is set to SILENT mode.\n"); + + if (controls_allowed_countdown > 0U) { + siren_countdown = 3U; + controls_allowed_countdown = 0U; + } + + // set flag to indicate the heartbeat was lost + if (is_car_safety_mode(current_safety_mode)) { + heartbeat_lost = true; + } + + // clear heartbeat engaged state + heartbeat_engaged = false; + + if (current_safety_mode != SAFETY_SILENT) { + set_safety_mode(SAFETY_SILENT, 0U); + } + + if (power_save_status != POWER_SAVE_STATUS_ENABLED) { + set_power_save_state(POWER_SAVE_STATUS_ENABLED); + } + + // Also disable IR when the heartbeat goes missing + current_board->set_ir_power(0U); + + // Run fan when device is up but not talking to us. + // The bootloader enables the SOM GPIO on boot. + fan_set_power(current_board->read_som_gpio() ? 30U : 0U); + } + } + + // check registers + check_registers(); + + // set ignition_can to false after 2s of no CAN seen + if (ignition_can_cnt > 2U) { + ignition_can = false; + } + + // on to the next one + uptime_cnt += 1U; + safety_mode_cnt += 1U; + ignition_can_cnt += 1U; + + // synchronous safety check + safety_tick(¤t_safety_config); + } + + loop_counter++; + loop_counter %= 8U; + } + TICK_TIMER->SR = 0; +} + +int main(void) { + // Init interrupt table + init_interrupts(true); + + // shouldn't have interrupts here, but just in case + disable_interrupts(); + + // init early devices + clock_init(); + peripherals_init(); + detect_board_type(); + led_init(); + // red+green leds enabled until succesful USB/SPI init, as a debug indicator + led_set(LED_RED, true); + led_set(LED_GREEN, true); + adc_init(ADC1); + + // print hello + print("\n\n\n************************ MAIN START ************************\n"); + + // check for non-supported board types + assert_fatal(hw_type != HW_TYPE_UNKNOWN, "Unsupported board type"); + + print("Config:\n"); + print(" Board type: 0x"); puth(hw_type); print("\n"); + + // init board + current_board->init(); + current_board->set_can_mode(CAN_MODE_NORMAL); + harness_init(); + + // panda has an FPU, let's use it! + enable_fpu(); + + microsecond_timer_init(); + + current_board->set_siren(false); + if (current_board->has_fan) { + fan_init(); + } + + // init to SILENT and can silent + set_safety_mode(SAFETY_SILENT, 0U); + + // enable CAN TXs + enable_can_transceivers(true); + + // init watchdog for heartbeat loop, fed at 8Hz + simple_watchdog_init(FAULT_HEARTBEAT_LOOP_WATCHDOG, (3U * 1000000U / 8U)); + + // 8Hz timer + REGISTER_INTERRUPT(TICK_TIMER_IRQ, tick_handler, 10U, FAULT_INTERRUPT_RATE_TICK) + tick_timer_init(); + +#ifdef DEBUG + print("DEBUG ENABLED\n"); +#endif + // enable USB (right before interrupts or enum can fail!) + usb_init(); + + if (current_board->has_spi) { + gpio_spi_init(); + spi_init(); + } + + led_set(LED_RED, false); + led_set(LED_GREEN, false); + led_set(LED_BLUE, false); + + print("**** INTERRUPTS ON ****\n"); + enable_interrupts(); + + // LED should keep on blinking all the time + while (true) { + if (power_save_status == POWER_SAVE_STATUS_DISABLED) { + #ifdef DEBUG_FAULTS + if (fault_status == FAULT_STATUS_NONE) { + #endif + // useful for debugging, fade breaks = panda is overloaded + for (uint32_t fade = 0U; fade < MAX_LED_FADE; fade += 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + + for (uint32_t fade = MAX_LED_FADE; fade > 0U; fade -= 1U) { + led_set(LED_RED, true); + delay(fade >> 4); + led_set(LED_RED, false); + delay((MAX_LED_FADE - fade) >> 4); + } + + #ifdef DEBUG_FAULTS + } else { + led_set(LED_RED, 1); + delay(512000U); + led_set(LED_RED, 0); + delay(512000U); + } + #endif + } else { + __WFI(); + SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; + } + } + + return 0; +} diff --git a/panda/board/main_comms.h b/panda/board/main_comms.h new file mode 100644 index 0000000000..ce61f625dd --- /dev/null +++ b/panda/board/main_comms.h @@ -0,0 +1,329 @@ +extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used + +// Prototypes +void set_safety_mode(uint16_t mode, uint16_t param); +bool is_car_safety_mode(uint16_t mode); + +static int get_health_pkt(void *dat) { + COMPILE_TIME_ASSERT(sizeof(struct health_t) <= USBPACKET_MAX_SIZE); + struct health_t * health = (struct health_t*)dat; + + health->uptime_pkt = uptime_cnt; + health->voltage_pkt = current_board->read_voltage_mV(); + health->current_pkt = current_board->read_current_mA(); + + health->ignition_line_pkt = (uint8_t)(harness_check_ignition()); + health->ignition_can_pkt = ignition_can; + + health->controls_allowed_pkt = controls_allowed; + health->safety_tx_blocked_pkt = safety_tx_blocked; + health->safety_rx_invalid_pkt = safety_rx_invalid; + health->tx_buffer_overflow_pkt = tx_buffer_overflow; + health->rx_buffer_overflow_pkt = rx_buffer_overflow; + health->car_harness_status_pkt = harness.status; + health->safety_mode_pkt = (uint8_t)(current_safety_mode); + health->safety_param_pkt = current_safety_param; + health->alternative_experience_pkt = alternative_experience; + health->power_save_enabled_pkt = power_save_status == POWER_SAVE_STATUS_ENABLED; + health->heartbeat_lost_pkt = heartbeat_lost; + health->safety_rx_checks_invalid_pkt = safety_rx_checks_invalid; + + health->spi_error_count_pkt = spi_error_count; + + health->fault_status_pkt = fault_status; + health->faults_pkt = faults; + + health->interrupt_load_pkt = interrupt_load; + + health->fan_power = fan_state.power; + + health->sbu1_voltage_mV = harness.sbu1_voltage_mV; + health->sbu2_voltage_mV = harness.sbu2_voltage_mV; + + health->som_reset_triggered = bootkick_reset_triggered; + + return sizeof(*health); +} + +// send on serial, first byte to select the ring +void comms_endpoint2_write(const uint8_t *data, uint32_t len) { + uart_ring *ur = get_ring_by_number(data[0]); + if ((len != 0U) && (ur != NULL)) { + if ((data[0] < 2U) || (data[0] >= 4U)) { + for (uint32_t i = 1; i < len; i++) { + while (!put_char(ur, data[i])) { + // wait + } + } + } + } +} + +int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { + unsigned int resp_len = 0; + uart_ring *ur = NULL; + uint32_t time; + +#ifdef DEBUG_COMMS + print("raw control request: "); hexdump(req, sizeof(ControlPacket_t)); print("\n"); + print("- request "); puth(req->request); print("\n"); + print("- param1 "); puth(req->param1); print("\n"); + print("- param2 "); puth(req->param2); print("\n"); +#endif + + switch (req->request) { + // **** 0xa8: get microsecond timer + case 0xa8: + time = microsecond_timer_get(); + resp[0] = (time & 0x000000FFU); + resp[1] = ((time & 0x0000FF00U) >> 8U); + resp[2] = ((time & 0x00FF0000U) >> 16U); + resp[3] = ((time & 0xFF000000U) >> 24U); + resp_len = 4U; + break; + // **** 0xb0: set IR power + case 0xb0: + current_board->set_ir_power(req->param1); + break; + // **** 0xb1: set fan power + case 0xb1: + fan_set_power(req->param1); + break; + // **** 0xb2: get fan rpm + case 0xb2: + resp[0] = (fan_state.rpm & 0x00FFU); + resp[1] = ((fan_state.rpm & 0xFF00U) >> 8U); + resp_len = 2; + break; + // **** 0xc0: reset communications state + case 0xc0: + comms_can_reset(); + break; + // **** 0xc1: get hardware type + case 0xc1: + resp[0] = hw_type; + resp_len = 1; + break; + // **** 0xc2: CAN health stats + case 0xc2: + COMPILE_TIME_ASSERT(sizeof(can_health_t) <= USBPACKET_MAX_SIZE); + if (req->param1 < 3U) { + update_can_health_pkt(req->param1, 0U); + can_health[req->param1].can_speed = (bus_config[req->param1].can_speed / 10U); + can_health[req->param1].can_data_speed = (bus_config[req->param1].can_data_speed / 10U); + can_health[req->param1].canfd_enabled = bus_config[req->param1].canfd_enabled; + can_health[req->param1].brs_enabled = bus_config[req->param1].brs_enabled; + can_health[req->param1].canfd_non_iso = bus_config[req->param1].canfd_non_iso; + resp_len = sizeof(can_health[req->param1]); + (void)memcpy(resp, (uint8_t*)(&can_health[req->param1]), resp_len); + } + break; + // **** 0xc3: fetch MCU UID + case 0xc3: + (void)memcpy(resp, ((uint8_t *)UID_BASE), 12); + resp_len = 12; + break; + // **** 0xc4: get interrupt call rate + case 0xc4: + if (req->param1 < NUM_INTERRUPTS) { + uint32_t load = interrupts[req->param1].call_rate; + resp[0] = (load & 0x000000FFU); + resp[1] = ((load & 0x0000FF00U) >> 8U); + resp[2] = ((load & 0x00FF0000U) >> 16U); + resp[3] = ((load & 0xFF000000U) >> 24U); + resp_len = 4U; + } + break; + // **** 0xc5: DEBUG: drive relay + case 0xc5: + set_intercept_relay((req->param1 & 0x1U), (req->param1 & 0x2U)); + break; + // **** 0xc6: DEBUG: read SOM GPIO + case 0xc6: + resp[0] = current_board->read_som_gpio(); + resp_len = 1; + break; + // **** 0xd0: fetch serial (aka the provisioned dongle ID) + case 0xd0: + // addresses are OTP + if (req->param1 == 1U) { + (void)memcpy(resp, (uint8_t *)DEVICE_SERIAL_NUMBER_ADDRESS, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } + break; + // **** 0xd1: enter bootloader mode + case 0xd1: + // this allows reflashing of the bootstub + switch (req->param1) { + case 0: + // only allow bootloader entry on debug builds + #ifdef ALLOW_DEBUG + print("-> entering bootloader\n"); + enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; + NVIC_SystemReset(); + #endif + break; + case 1: + print("-> entering softloader\n"); + enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; + NVIC_SystemReset(); + break; + default: + print("Bootloader mode invalid\n"); + break; + } + break; + // **** 0xd2: get health packet + case 0xd2: + resp_len = get_health_pkt(resp); + break; + // **** 0xd3: get first 64 bytes of signature + case 0xd3: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len], resp_len); + } + break; + // **** 0xd4: get second 64 bytes of signature + case 0xd4: + { + resp_len = 64; + char * code = (char*)_app_start; + int code_len = _app_start[0]; + (void)memcpy(resp, &code[code_len + 64], resp_len); + } + break; + // **** 0xd6: get version + case 0xd6: + COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); + (void)memcpy(resp, gitversion, sizeof(gitversion)); + resp_len = sizeof(gitversion) - 1U; + break; + // **** 0xd8: reset ST + case 0xd8: + NVIC_SystemReset(); + break; + // **** 0xdb: set OBD CAN multiplexing mode + case 0xdb: + current_board->set_can_mode((req->param1 == 1U) ? CAN_MODE_OBD_CAN2 : CAN_MODE_NORMAL); + break; + // **** 0xdc: set safety mode + case 0xdc: + set_safety_mode(req->param1, (uint16_t)req->param2); + break; + // **** 0xdd: get healthpacket and CANPacket versions + case 0xdd: + resp[0] = HEALTH_PACKET_VERSION; + resp[1] = CAN_PACKET_VERSION; + resp[2] = CAN_HEALTH_PACKET_VERSION; + resp_len = 3; + break; + // **** 0xde: set can bitrate + case 0xde: + if ((req->param1 < PANDA_CAN_CNT) && is_speed_valid(req->param2, speeds, sizeof(speeds)/sizeof(speeds[0]))) { + bus_config[req->param1].can_speed = req->param2; + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xdf: set alternative experience + case 0xdf: + // you can only set this if you are in a non car safety mode + if (!is_car_safety_mode(current_safety_mode)) { + alternative_experience = req->param1; + } + break; + // **** 0xe0: uart read + case 0xe0: + ur = get_ring_by_number(req->param1); + if (!ur) { + break; + } + + // read + uint16_t req_length = MIN(req->length, USBPACKET_MAX_SIZE); + while ((resp_len < req_length) && + get_char(ur, (char*)&resp[resp_len])) { + ++resp_len; + } + break; + // **** 0xe5: set CAN loopback (for testing) + case 0xe5: + can_loopback = req->param1 > 0U; + can_init_all(); + break; + // **** 0xe6: set custom clock source period and pulse length + case 0xe6: + clock_source_set_timer_params(req->param1, req->param2); + break; + // **** 0xe7: set power save state + case 0xe7: + set_power_save_state(req->param1); + break; + // **** 0xe8: set can-fd auto swithing mode + case 0xe8: + bus_config[req->param1].canfd_auto = req->param2 > 0U; + break; + // **** 0xf1: Clear CAN ring buffer. + case 0xf1: + if (req->param1 == 0xFFFFU) { + print("Clearing CAN Rx queue\n"); + can_clear(&can_rx_q); + } else if (req->param1 < PANDA_CAN_CNT) { + print("Clearing CAN Tx queue\n"); + can_clear(can_queues[req->param1]); + } else { + print("Clearing CAN CAN ring buffer failed: wrong bus number\n"); + } + break; + // **** 0xf3: Heartbeat. Resets heartbeat counter. + case 0xf3: + { + heartbeat_counter = 0U; + heartbeat_lost = false; + heartbeat_disabled = false; + heartbeat_engaged = (req->param1 == 1U); + break; + } + // **** 0xf6: set siren enabled + case 0xf6: + siren_enabled = (req->param1 != 0U); + break; + // **** 0xf8: disable heartbeat checks + case 0xf8: + if (!is_car_safety_mode(current_safety_mode)) { + heartbeat_disabled = true; + } + break; + // **** 0xf9: set CAN FD data bitrate + case 0xf9: + if ((req->param1 < PANDA_CAN_CNT) && + is_speed_valid(req->param2, data_speeds, sizeof(data_speeds)/sizeof(data_speeds[0]))) { + bus_config[req->param1].can_data_speed = req->param2; + bus_config[req->param1].canfd_enabled = (req->param2 >= bus_config[req->param1].can_speed); + bus_config[req->param1].brs_enabled = (req->param2 > bus_config[req->param1].can_speed); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + // **** 0xfc: set CAN FD non-ISO mode + case 0xfc: + if (req->param1 < PANDA_CAN_CNT) { + bus_config[req->param1].canfd_non_iso = (req->param2 != 0U); + bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1)); + UNUSED(ret); + } + break; + default: + print("NO HANDLER "); + puth(req->request); + print("\n"); + break; + } + return resp_len; +} diff --git a/panda/board/main_declarations.h b/panda/board/main_declarations.h new file mode 100644 index 0000000000..52aaa6c10d --- /dev/null +++ b/panda/board/main_declarations.h @@ -0,0 +1,22 @@ +#pragma once + +// ******************** Prototypes ******************** +void print(const char *a); +void puth(unsigned int i); +typedef struct board board; +typedef struct harness_configuration harness_configuration; +void pwm_init(TIM_TypeDef *TIM, uint8_t channel); +void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage); + +// ********************* Globals ********************** +extern uint8_t hw_type; +extern board *current_board; +extern uint32_t uptime_cnt; + +// heartbeat state +extern uint32_t heartbeat_counter; +extern bool heartbeat_lost; +extern bool heartbeat_disabled; + +// siren state +extern bool siren_enabled; diff --git a/panda/board/main_definitions.h b/panda/board/main_definitions.h new file mode 100644 index 0000000000..83c9109057 --- /dev/null +++ b/panda/board/main_definitions.h @@ -0,0 +1,14 @@ +#include "main_declarations.h" + +// ********************* Globals ********************** +uint8_t hw_type = 0; +board *current_board; +uint32_t uptime_cnt = 0; + +// heartbeat state +uint32_t heartbeat_counter = 0; +bool heartbeat_lost = false; +bool heartbeat_disabled = false; // set over USB + +// siren state +bool siren_enabled = false; diff --git a/panda/board/obj/.placeholder b/panda/board/obj/.placeholder new file mode 100644 index 0000000000..e69de29bb2 diff --git a/panda/board/power_saving.h b/panda/board/power_saving.h new file mode 100644 index 0000000000..1e95c95139 --- /dev/null +++ b/panda/board/power_saving.h @@ -0,0 +1,52 @@ +#include "power_saving_declarations.h" + +// WARNING: To stay in compliance with the SIL2 rules laid out in STM UM1840, we should never implement any of the available hardware low power modes. +// See rule: CoU_3 + +int power_save_status = POWER_SAVE_STATUS_DISABLED; + +void enable_can_transceivers(bool enabled) { + // Leave main CAN always on for CAN-based ignition detection + uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U; + for(uint8_t i=1U; i<=4U; i++){ + current_board->enable_can_transceiver(i, (i == main_bus) || enabled); + } +} + +void set_power_save_state(int state) { + bool is_valid_state = (state == POWER_SAVE_STATUS_ENABLED) || (state == POWER_SAVE_STATUS_DISABLED); + if (is_valid_state && (state != power_save_status)) { + bool enable = false; + if (state == POWER_SAVE_STATUS_ENABLED) { + print("enable power savings\n"); + + // Disable CAN interrupts + if (harness.status == HARNESS_STATUS_FLIPPED) { + llcan_irq_disable(cans[0]); + } else { + llcan_irq_disable(cans[2]); + } + llcan_irq_disable(cans[1]); + } else { + print("disable power savings\n"); + + if (harness.status == HARNESS_STATUS_FLIPPED) { + llcan_irq_enable(cans[0]); + } else { + llcan_irq_enable(cans[2]); + } + llcan_irq_enable(cans[1]); + + enable = true; + } + + enable_can_transceivers(enable); + + // Switch off IR when in power saving + if(!enable){ + current_board->set_ir_power(0U); + } + + power_save_status = state; + } +} diff --git a/panda/board/power_saving_declarations.h b/panda/board/power_saving_declarations.h new file mode 100644 index 0000000000..7a474a5594 --- /dev/null +++ b/panda/board/power_saving_declarations.h @@ -0,0 +1,11 @@ +#pragma once + +// WARNING: To stay in compliance with the SIL2 rules laid out in STM UM1840, we should never implement any of the available hardware low power modes. +// See rule: CoU_3 + +#define POWER_SAVE_STATUS_DISABLED 0 +#define POWER_SAVE_STATUS_ENABLED 1 + +extern int power_save_status; + +void set_power_save_state(int state); diff --git a/panda/board/provision.h b/panda/board/provision.h new file mode 100644 index 0000000000..d191e53f67 --- /dev/null +++ b/panda/board/provision.h @@ -0,0 +1,13 @@ +// this is where we manage the dongle ID assigned during our +// manufacturing. aside from this, there's a UID for the MCU + +#define PROVISION_CHUNK_LEN 0x20 + +void get_provision_chunk(uint8_t *resp) { + const unsigned char unprovisioned_text[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + + (void)memcpy(resp, (uint8_t *)PROVISION_CHUNK_ADDRESS, PROVISION_CHUNK_LEN); + if (memcmp(resp, unprovisioned_text, 0x20) == 0) { + (void)memcpy(resp, "unprovisioned\x00\x00\x00testing123\x00\x00\xa3\xa6\x99\xec", 0x20); + } +} diff --git a/panda/board/recover.py b/panda/board/recover.py new file mode 100755 index 0000000000..6268a07d96 --- /dev/null +++ b/panda/board/recover.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +import os +import time +import subprocess + +from panda import Panda, PandaDFU + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + subprocess.check_call(f"scons -C {board_path}/.. -j$(nproc) {board_path}", shell=True) + + for s in Panda.list(): + with Panda(serial=s) as p: + print(f"putting {p.get_usb_serial()} in DFU mode") + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + + # wait for reset pandas to come back up + time.sleep(1) + + dfu_serials = PandaDFU.list() + print(f"found {len(dfu_serials)} panda(s) in DFU - {dfu_serials}") + for s in dfu_serials: + print("flashing", s) + PandaDFU(s).recover() + exit(1 if len(dfu_serials) == 0 else 0) diff --git a/panda/board/stm32h7/board.h b/panda/board/stm32h7/board.h new file mode 100644 index 0000000000..04c4162d5b --- /dev/null +++ b/panda/board/stm32h7/board.h @@ -0,0 +1,49 @@ +// ///////////////////////////////////////////////////////////// // +// Hardware abstraction layer for all different supported boards // +// ///////////////////////////////////////////////////////////// // +#include "board/boards/board_declarations.h" +#include "board/boards/unused_funcs.h" + +// ///// Board definition and detection ///// // +#include "board/stm32h7/lladc.h" +#include "board/drivers/harness.h" +#include "board/drivers/fan.h" +#include "board/stm32h7/llfan.h" +#include "board/drivers/fake_siren.h" +#include "board/stm32h7/sound.h" +#include "board/drivers/clock_source.h" +#include "board/boards/red.h" +#include "board/boards/tres.h" +#include "board/boards/cuatro.h" + + +void detect_board_type(void) { + // On STM32H7 pandas, we use two different sets of pins. + const uint8_t id1 = detect_with_pull(GPIOF, 7, PULL_UP) | + (detect_with_pull(GPIOF, 8, PULL_UP) << 1U) | + (detect_with_pull(GPIOF, 9, PULL_UP) << 2U) | + (detect_with_pull(GPIOF, 10, PULL_UP) << 3U); + + const uint8_t id2 = detect_with_pull(GPIOD, 4, PULL_UP) | + (detect_with_pull(GPIOD, 5, PULL_UP) << 1U) | + (detect_with_pull(GPIOD, 6, PULL_UP) << 2U) | + (detect_with_pull(GPIOD, 7, PULL_UP) << 3U); + + if (id2 == 3U) { + hw_type = HW_TYPE_CUATRO; + current_board = &board_cuatro; + } else if (id1 == 0U) { + hw_type = HW_TYPE_RED_PANDA; + current_board = &board_red; + } else if (id1 == 1U) { + // deprecated + //hw_type = HW_TYPE_RED_PANDA_V2; + hw_type = HW_TYPE_UNKNOWN; + } else if (id1 == 2U) { + hw_type = HW_TYPE_TRES; + current_board = &board_tres; + } else { + hw_type = HW_TYPE_UNKNOWN; + print("Hardware type is UNKNOWN!\n"); + } +} diff --git a/panda/board/stm32h7/clock.h b/panda/board/stm32h7/clock.h new file mode 100644 index 0000000000..40ad06043e --- /dev/null +++ b/panda/board/stm32h7/clock.h @@ -0,0 +1,120 @@ +/* +HSE: 25MHz +PLL1Q: 80MHz (for FDCAN) +HSI48 enabled (for USB) +CPU: 240MHz +CPU Systick: 240MHz +AXI: 120MHz +HCLK3: 60MHz +APB3 per: 60MHz +AHB1,2 per: 120MHz +APB1 per: 60MHz +APB1 tim: 120MHz +APB2 per: 60MHz +APB2 tim: 120MHz +AHB4 per: 120MHz +APB4 per: 60MHz +PCLK1: 60MHz (for USART2,3,4,5,7,8) +*/ + +typedef enum { + PACKAGE_UNKNOWN = 0, + PACKAGE_WITH_SMPS = 1, + PACKAGE_WITHOUT_SMPS = 2, +} PackageSMPSType; + +// TODO: find a better way to distinguish between H725 (using SMPS) and H723 (lacking SMPS) +// The package will do for now, since we have only used TFBGA100 for H723 +static PackageSMPSType get_package_smps_type(void) { + PackageSMPSType ret; + RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; // make sure SYSCFG clock is enabled. does seem to read fine without too though + + switch(SYSCFG->PKGR & 0xFU) { + case 0b0001U: // TFBGA100 Legacy + case 0b0011U: // TFBGA100 + ret = PACKAGE_WITHOUT_SMPS; + break; + case 0b0101U: // LQFP144 Legacy + case 0b0111U: // LQFP144 Industrial + case 0b1000U: // UFBGA169 + ret = PACKAGE_WITH_SMPS; + break; + default: + ret = PACKAGE_UNKNOWN; + } + return ret; +} + +void clock_init(void) { + /* + WARNING: PWR->CR3's lower byte can only be written once + * subsequent writes will silently fail + * only cleared with a full power-on-reset, not soft reset or reset pin + * some H7 have a bootrom with a DFU routine that writes (and locks) CR3 + * if the CR3 config doesn't match the HW, the core will deadlock and require immediately going into DFU from a cold boot + + In a normal bootup, the bootstub will be the first to write this. The app section calls clock_init again, but the CR3 write will silently fail. This is fine for most cases, but caution should be taken that the bootstub and app always write the same config. + */ + + // Set power mode to direct SMPS power supply (depends on the board layout) + PackageSMPSType package_smps = get_package_smps_type(); + if (package_smps == PACKAGE_WITHOUT_SMPS) { + register_set(&(PWR->CR3), PWR_CR3_LDOEN, 0xFU); // no SMPS, so powered by LDO + } else if (package_smps == PACKAGE_WITH_SMPS) { + register_set(&(PWR->CR3), PWR_CR3_SMPSEN, 0xFU); // powered only by SMPS + } else { + while(true); // unknown package, let's hang here + } + + // Set VOS level (VOS3 to 170Mhz, VOS2 to 300Mhz, VOS1 to 400Mhz, VOS0 to 550Mhz) + register_set(&(PWR->D3CR), PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0, 0xC000U); //VOS1, needed for 80Mhz CAN FD + while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0U); + while ((PWR->CSR1 & PWR_CSR1_ACTVOS) != (PWR->D3CR & PWR_D3CR_VOS)); // check that VOS level was actually set + + // Configure Flash ACR register LATENCY and WRHIGHFREQ (VOS0 range!) + register_set(&(FLASH->ACR), FLASH_ACR_LATENCY_2WS | 0x20U, 0x3FU); // VOS2, AXI 100MHz-150MHz + // enable external oscillator HSE + register_set_bits(&(RCC->CR), RCC_CR_HSEON); + while ((RCC->CR & RCC_CR_HSERDY) == 0U); + // enable internal HSI48 for USB FS kernel + register_set_bits(&(RCC->CR), RCC_CR_HSI48ON); + while ((RCC->CR & RCC_CR_HSI48RDY) == 0U); + // Specify the frequency source for PLL1, divider for DIVM1, DIVM2, DIVM3 : HSE, 5, 5, 5 + register_set(&(RCC->PLLCKSELR), RCC_PLLCKSELR_PLLSRC_HSE | RCC_PLLCKSELR_DIVM1_0 | RCC_PLLCKSELR_DIVM1_2 | RCC_PLLCKSELR_DIVM2_0 | RCC_PLLCKSELR_DIVM2_2 | RCC_PLLCKSELR_DIVM3_0 | RCC_PLLCKSELR_DIVM3_2, 0x3F3F3F3U); + + // *** PLL1 start *** + // Specify multiplier N and dividers P, Q, R for PLL1 : 48, 1, 3, 2 (clock 240Mhz, PLL1Q 80Mhz for CAN FD) + register_set(&(RCC->PLL1DIVR), 0x102002FU, 0x7F7FFFFFU); + // Specify the input and output frequency ranges, enable dividers for PLL1 + register_set(&(RCC->PLLCFGR), RCC_PLLCFGR_PLL1RGE_2 | RCC_PLLCFGR_DIVP1EN | RCC_PLLCFGR_DIVQ1EN | RCC_PLLCFGR_DIVR1EN, 0x7000CU); + // Enable PLL1 + register_set_bits(&(RCC->CR), RCC_CR_PLL1ON); + while((RCC->CR & RCC_CR_PLL1RDY) == 0U); + // *** PLL1 end *** + + //////////////OTHER CLOCKS//////////////////// + // RCC HCLK Clock Source / RCC APB3 Clock Source / RCC SYS Clock Source + register_set(&(RCC->D1CFGR), RCC_D1CFGR_HPRE_DIV2 | RCC_D1CFGR_D1PPRE_DIV2 | RCC_D1CFGR_D1CPRE_DIV1, 0xF7FU); + // RCC APB1 Clock Source / RCC APB2 Clock Source + register_set(&(RCC->D2CFGR), RCC_D2CFGR_D2PPRE1_DIV2 | RCC_D2CFGR_D2PPRE2_DIV2, 0x770U); + // RCC APB4 Clock Source + register_set(&(RCC->D3CFGR), RCC_D3CFGR_D3PPRE_DIV2, 0x70U); + + // Set SysClock source to PLL + register_set(&(RCC->CFGR), RCC_CFGR_SW_PLL1, 0x7U); + while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL1); + //////////////END OTHER CLOCKS//////////////////// + + // Configure clock source for USB (HSI48) + register_set(&(RCC->D2CCIP2R), RCC_D2CCIP2R_USBSEL_1 | RCC_D2CCIP2R_USBSEL_0, RCC_D2CCIP2R_USBSEL); + // Configure clock source for FDCAN (PLL1Q at 80Mhz) + register_set(&(RCC->D2CCIP1R), RCC_D2CCIP1R_FDCANSEL_0, RCC_D2CCIP1R_FDCANSEL); + // Configure clock source for DFSDM1 + register_set_bits(&(RCC->D2CCIP1R), RCC_D2CCIP1R_DFSDM1SEL); + // Configure clock source for ADC1,2,3 (per_ck(currently HSE)) + register_set(&(RCC->D3CCIPR), RCC_D3CCIPR_ADCSEL_1, RCC_D3CCIPR_ADCSEL); + //Enable the Clock Security System + register_set_bits(&(RCC->CR), RCC_CR_CSSHSEON); + //Enable Vdd33usb supply level detector + register_set_bits(&(PWR->CR3), PWR_CR3_USB33DEN); +} diff --git a/panda/board/stm32h7/inc/cmsis_compiler.h b/panda/board/stm32h7/inc/cmsis_compiler.h new file mode 100644 index 0000000000..d0f39eef67 --- /dev/null +++ b/panda/board/stm32h7/inc/cmsis_compiler.h @@ -0,0 +1,284 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.1.0 + * @date 09. October 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6.6 LTM (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) + #include "cmsis_armclang_ltm.h" + + /* + * Arm Compiler above 6.10.1 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) + #include "cmsis_armclang.h" + + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #define __RESTRICT __restrict + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + + diff --git a/panda/board/stm32h7/inc/cmsis_gcc.h b/panda/board/stm32h7/inc/cmsis_gcc.h new file mode 100644 index 0000000000..2f68473f64 --- /dev/null +++ b/panda/board/stm32h7/inc/cmsis_gcc.h @@ -0,0 +1,2169 @@ +/**************************************************************************//** + * @file cmsis_gcc.h + * @brief CMSIS compiler GCC header file + * @version V5.2.0 + * @date 08. May 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_GCC_H +#define __CMSIS_GCC_H + +/* ignore some GCC warnings */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +/* Fallback for __has_builtin */ +#ifndef __has_builtin + #define __has_builtin(x) (0) +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpacked" + #pragma GCC diagnostic ignored "-Wattributes" + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma GCC diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START + +/** + \brief Initializes data and bss sections + \details This default implementations initialized all data and additional bss + sections relying on .copy.table and .zero.table specified properly + in the used linker script. + + */ +__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void) +{ + extern void _start(void) __NO_RETURN; + + typedef struct { + uint32_t const* src; + uint32_t* dest; + uint32_t wlen; + } __copy_table_t; + + typedef struct { + uint32_t* dest; + uint32_t wlen; + } __zero_table_t; + + extern const __copy_table_t __copy_table_start__; + extern const __copy_table_t __copy_table_end__; + extern const __zero_table_t __zero_table_start__; + extern const __zero_table_t __zero_table_end__; + + for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = pTable->src[i]; + } + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + for(uint32_t i=0u; iwlen; ++i) { + pTable->dest[i] = 0u; + } + } + + _start(); +} + +#define __PROGRAM_START __cmsis_start +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP __StackTop +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT __StackLimit +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute((used, section(".vectors"))) +#endif + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting the I-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory"); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting the F-bit in the CPSR. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_FORCEINLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_get_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + return __builtin_arm_get_fpscr(); +#else + uint32_t result; + + __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); + return(result); +#endif +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#if __has_builtin(__builtin_arm_set_fpscr) +// Re-enable using built-in when GCC has been fixed +// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2) + /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */ + __builtin_arm_set_fpscr(fpscr); +#else + __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory"); +#endif +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP() __ASM volatile ("nop") + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI() __ASM volatile ("wfi") + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE() __ASM volatile ("wfe") + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV() __ASM volatile ("sev") + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +__STATIC_FORCEINLINE void __ISB(void) +{ + __ASM volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __ASM volatile ("dsb 0xF":::"memory"); +} + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +__STATIC_FORCEINLINE void __DMB(void) +{ + __ASM volatile ("dmb 0xF":::"memory"); +} + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV(uint32_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + return __builtin_bswap32(value); +#else + uint32_t result; + + __ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +} + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE int16_t __REVSH(int16_t value) +{ +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + return (int16_t)__builtin_bswap16(value); +#else + int16_t result; + + __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return result; +#endif +} + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) + __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); +#else + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ +#endif + return result; +} + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexb %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrexh %0, %1" : "=r" (result) : "Q" (*addr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("ldrex %0, %1" : "=r" (result) : "Q" (*addr) ); + return(result); +} + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) +{ + uint32_t result; + + __ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) +{ + uint32_t result; + + __ASM volatile ("strex %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" (value) ); + return(result); +} + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +__STATIC_FORCEINLINE void __CLREX(void) +{ + __ASM volatile ("clrex" ::: "memory"); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT(ARG1,ARG2) \ +__extension__ \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] ARG1 Value to be saturated + \param [in] ARG2 Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT(ARG1,ARG2) \ + __extension__ \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + +#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); +#else + /* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not + accepted by assembler. So has to use following less efficient pattern. + */ + __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" ); +#endif + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) ); + return(result); +} + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + + +__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#define __SSAT16(ARG1,ARG2) \ +({ \ + int32_t __RES, __ARG1 = (ARG1); \ + __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +#define __USAT16(ARG1,ARG2) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1); \ + __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ + __RES; \ + }) + +__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1) +{ + uint32_t result; + + __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1)); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3) +{ + uint32_t result; + + __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc) +{ + union llreg_u{ + uint32_t w32[2]; + uint64_t w64; + } llr; + llr.w64 = acc; + +#ifndef __ARMEB__ /* Little endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) ); +#else /* Big endian */ + __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) ); +#endif + + return(llr.w64); +} + +__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2) +{ + uint32_t result; + + __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2) +{ + int32_t result; + + __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); + return(result); +} + +#if 0 +#define __PKHBT(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) + +#define __PKHTB(ARG1,ARG2,ARG3) \ +({ \ + uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \ + if (ARG3 == 0) \ + __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \ + else \ + __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \ + __RES; \ + }) +#endif + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#pragma GCC diagnostic pop + +#endif /* __CMSIS_GCC_H */ + diff --git a/panda/board/stm32h7/inc/cmsis_version.h b/panda/board/stm32h7/inc/cmsis_version.h new file mode 100644 index 0000000000..bf57cf3e80 --- /dev/null +++ b/panda/board/stm32h7/inc/cmsis_version.h @@ -0,0 +1,40 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.3 + * @date 24. June 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 3U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif + diff --git a/panda/board/stm32h7/inc/core_cm7.h b/panda/board/stm32h7/inc/core_cm7.h new file mode 100644 index 0000000000..3da3c43e40 --- /dev/null +++ b/panda/board/stm32h7/inc/core_cm7.h @@ -0,0 +1,2725 @@ +/**************************************************************************//** + * @file core_cm7.h + * @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File + * @version V5.1.1 + * @date 28. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM7_H_GENERIC +#define __CORE_CM7_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
    + Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
    + Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
    + Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M7 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM7 definitions */ +#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \ + __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (7U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions. +*/ +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) + #define __FPU_USED 1U + #else + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #define __FPU_USED 0U + #endif + #else + #define __FPU_USED 0U + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM7_H_DEPENDANT +#define __CORE_CM7_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM7_REV + #define __CM7_REV 0x0000U + #warning "__CM7_REV not defined in device header file; using default!" + #endif + + #ifndef __FPU_PRESENT + #define __FPU_PRESENT 0U + #warning "__FPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __ICACHE_PRESENT + #define __ICACHE_PRESENT 0U + #warning "__ICACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DCACHE_PRESENT + #define __DCACHE_PRESENT 0U + #warning "__DCACHE_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __DTCM_PRESENT + #define __DTCM_PRESENT 0U + #warning "__DTCM_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M7 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + - Core FPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + +#define APSR_GE_Pos 16U /*!< APSR: GE Position */ +#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */ + uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */ +#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t FPCA:1; /*!< bit: 2 FP extension active flag */ + uint32_t _reserved0:29; /*!< bit: 3..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */ +#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */ + +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ID_AFR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t ID_MFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ID_ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[1U]; + __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */ + __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */ + __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */ + __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */ + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ + uint32_t RESERVED3[93U]; + __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */ + uint32_t RESERVED4[15U]; + __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */ + uint32_t RESERVED5[1U]; + __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */ + uint32_t RESERVED6[1U]; + __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */ + __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */ + __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */ + __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */ + __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */ + __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */ + __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */ + __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */ + uint32_t RESERVED7[6U]; + __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */ + __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */ + __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */ + __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */ + __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */ + uint32_t RESERVED8[1U]; + __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: Branch prediction enable bit Position */ +#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: Branch prediction enable bit Mask */ + +#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: Instruction cache enable bit Position */ +#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: Instruction cache enable bit Mask */ + +#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: Cache enable bit Position */ +#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: Cache enable bit Mask */ + +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */ +#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */ +#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/* SCB Cache Level ID Register Definitions */ +#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */ +#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */ + +#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */ +#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */ + +/* SCB Cache Type Register Definitions */ +#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */ +#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */ + +#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */ +#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */ + +#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */ +#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */ + +#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */ +#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */ + +#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */ +#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */ + +/* SCB Cache Size ID Register Definitions */ +#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */ +#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */ + +#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */ +#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */ + +#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */ +#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */ + +#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */ +#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */ + +#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */ +#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */ + +#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */ +#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */ + +#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */ +#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */ + +/* SCB Cache Size Selection Register Definitions */ +#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */ +#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */ + +#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */ +#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */ + +/* SCB Software Triggered Interrupt Register Definitions */ +#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */ +#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */ + +/* SCB D-Cache Invalidate by Set-way Register Definitions */ +#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */ +#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */ + +#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */ +#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */ + +/* SCB D-Cache Clean by Set-way Register Definitions */ +#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */ +#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */ + +#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */ +#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */ + +/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */ +#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */ +#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */ + +#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */ +#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */ + +/* Instruction Tightly-Coupled Memory Control Register Definitions */ +#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */ +#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */ + +#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */ +#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */ + +#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */ +#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */ + +#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */ +#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */ + +/* Data Tightly-Coupled Memory Control Register Definitions */ +#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */ +#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */ + +#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */ +#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */ + +#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */ +#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */ + +#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */ +#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */ + +/* AHBP Control Register Definitions */ +#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */ +#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */ + +#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */ +#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */ + +/* L1 Cache Control Register Definitions */ +#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */ +#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */ + +#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */ +#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */ + +#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */ +#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */ + +/* AHBS Control Register Definitions */ +#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */ +#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */ + +#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */ +#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */ + +#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/ +#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */ + +/* Auxiliary Bus Fault Status Register Definitions */ +#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/ +#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */ + +#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/ +#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */ + +#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/ +#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */ + +#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/ +#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */ + +#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/ +#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */ + +#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/ +#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */ +#define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */ + +#define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */ +#define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */ + +#define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */ +#define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */ + +#define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */ +#define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */ + +#define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */ +#define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */ + +#define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */ +#define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */ + +#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */ +#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */ + +#define SCnSCB_ACTLR_DISRAMODE_Pos 11U /*!< ACTLR: DISRAMODE Position */ +#define SCnSCB_ACTLR_DISRAMODE_Msk (1UL << SCnSCB_ACTLR_DISRAMODE_Pos) /*!< ACTLR: DISRAMODE Mask */ + +#define SCnSCB_ACTLR_FPEXCODIS_Pos 10U /*!< ACTLR: FPEXCODIS Position */ +#define SCnSCB_ACTLR_FPEXCODIS_Msk (1UL << SCnSCB_ACTLR_FPEXCODIS_Pos) /*!< ACTLR: FPEXCODIS Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ + uint32_t RESERVED3[981U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( W) Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_FPU Floating Point Unit (FPU) + \brief Type definitions for the Floating Point Unit (FPU) + @{ + */ + +/** + \brief Structure type to access the Floating Point Unit (FPU). + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */ + __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */ + __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */ + __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */ + __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */ + __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */ +} FPU_Type; + +/* Floating-Point Context Control Register Definitions */ +#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */ +#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */ + +#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */ +#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */ + +#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */ +#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */ + +#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */ +#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */ + +#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */ +#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */ + +#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */ +#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */ + +#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */ +#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */ + +#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */ +#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */ + +#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */ +#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */ + +/* Floating-Point Context Address Register Definitions */ +#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */ +#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */ + +/* Floating-Point Default Status Control Register Definitions */ +#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */ +#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */ + +#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */ +#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */ + +#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */ +#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */ + +#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */ +#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */ + +/* Media and FP Feature Register 0 Definitions */ +#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */ +#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */ + +#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */ +#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */ + +#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */ +#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */ + +#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */ +#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */ + +#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */ +#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */ + +#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */ +#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */ + +#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */ +#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */ + +#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */ +#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */ + +/* Media and FP Feature Register 1 Definitions */ +#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */ +#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */ + +#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */ +#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */ + +#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */ +#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */ + +#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */ +#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */ + +/* Media and FP Feature Register 2 Definitions */ + +#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */ +#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */ + +/*@} end of group CMSIS_FPU */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */ +#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */ + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ +#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */ +#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector; + __DSB(); +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t vectors = (uint32_t )SCB->VTOR; + return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)); +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + uint32_t mvfr0; + + mvfr0 = SCB->MVFR0; + if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U) + { + return 2U; /* Double + Single precision FPU */ + } + else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U) + { + return 1U; /* Single precision FPU */ + } + else + { + return 0U; /* No FPU */ + } +} + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ########################## Cache functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_CacheFunctions Cache Functions + \brief Functions that configure Instruction and Data cache. + @{ + */ + +/* Cache Size ID Register Macros */ +#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos) +#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos ) + +#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ +#define __SCB_ICACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */ + +/** + \brief Enable I-Cache + \details Turns on I-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */ + + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable I-Cache + \details Turns off I-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */ + SCB->ICIALLU = 0UL; /* invalidate I-Cache */ + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate I-Cache + \details Invalidates I-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateICache (void) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + __DSB(); + __ISB(); + SCB->ICIALLU = 0UL; + __DSB(); + __ISB(); + #endif +} + + +/** + \brief I-Cache Invalidate by address + \details Invalidates I-Cache for the given address. + I-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + I-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] isize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateICache_by_Addr (void *addr, int32_t isize) +{ + #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + if ( isize > 0 ) { + int32_t op_size = isize + (((uint32_t)addr) & (__SCB_ICACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_ICACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->ICIMVAU = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_ICACHE_LINE_SIZE; + op_size -= __SCB_ICACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief Enable D-Cache + \details Turns on D-Cache + */ +__STATIC_FORCEINLINE void SCB_EnableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */ + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + __DSB(); + + SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Disable D-Cache + \details Turns off D-Cache + */ +__STATIC_FORCEINLINE void SCB_DisableDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Invalidate D-Cache + \details Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_InvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | + ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean D-Cache + \details Cleans D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCSW = (((sets << SCB_DCCSW_SET_Pos) & SCB_DCCSW_SET_Msk) | + ((ways << SCB_DCCSW_WAY_Pos) & SCB_DCCSW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief Clean & Invalidate D-Cache + \details Cleans and Invalidates D-Cache + */ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + uint32_t ccsidr; + uint32_t sets; + uint32_t ways; + + SCB->CSSELR = 0U; /* select Level 1 data cache */ + __DSB(); + + ccsidr = SCB->CCSIDR; + + /* clean & invalidate D-Cache */ + sets = (uint32_t)(CCSIDR_SETS(ccsidr)); + do { + ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); + do { + SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) | + ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk) ); + #if defined ( __CC_ARM ) + __schedule_barrier(); + #endif + } while (ways-- != 0U); + } while(sets-- != 0U); + + __DSB(); + __ISB(); + #endif +} + + +/** + \brief D-Cache Invalidate by address + \details Invalidates D-Cache for the given address. + D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are invalidated. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean by address + \details Cleans D-Cache for the given address + D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned. + \param[in] addr address + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + + +/** + \brief D-Cache Clean and Invalidate by address + \details Cleans and invalidates D_Cache for the given address + D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity. + D-Cache memory blocks which are part of given address + given size are cleaned and invalidated. + \param[in] addr address (aligned to 32-byte boundary) + \param[in] dsize size of memory block (in number of bytes) +*/ +__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize) +{ + #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + if ( dsize > 0 ) { + int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U)); + uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */; + + __DSB(); + + do { + SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */ + op_addr += __SCB_DCACHE_LINE_SIZE; + op_size -= __SCB_DCACHE_LINE_SIZE; + } while ( op_size > 0 ); + + __DSB(); + __ISB(); + } + #endif +} + +/*@} end of CMSIS_Core_CacheFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM7_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/panda/board/stm32h7/inc/mpu_armv7.h b/panda/board/stm32h7/inc/mpu_armv7.h new file mode 100644 index 0000000000..e72cc4623d --- /dev/null +++ b/panda/board/stm32h7/inc/mpu_armv7.h @@ -0,0 +1,273 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.1.0 + * @date 08. March 2019 + ******************************************************************************/ +/* + * Copyright (c) 2017-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if shareable) or 010b (if non-shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rsar Value for RSAR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcopy with strictly ordered memory access, e.g. for register targets. +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif + diff --git a/panda/board/stm32h7/inc/stm32h725xx.h b/panda/board/stm32h7/inc/stm32h725xx.h new file mode 100644 index 0000000000..0e0d4a9d62 --- /dev/null +++ b/panda/board/stm32h7/inc/stm32h725xx.h @@ -0,0 +1,24740 @@ +/** + ****************************************************************************** + * @file stm32h735xx.h + * @author MCD Application Team + * @brief CMSIS STM32H735xx Device Peripheral Access Layer Header File. + * + * This file contains: + * - Data structures and the address mapping for all peripherals + * - Peripheral's registers declarations and bits definition + * - Macros to access peripheral's registers hardware + * + ****************************************************************************** + * @attention + * + *

    © Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32h735xx + * @{ + */ + +#ifndef STM32H735xx_H +#define STM32H735xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32H7XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M Processor Exceptions Numbers *****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 4 Cortex-M Memory Management Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt ( wwdg1_it, wwdg2_it) */ + PVD_AVD_IRQn = 1, /*!< PVD/AVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1 and ADC2 global Interrupts */ + FDCAN1_IT0_IRQn = 19, /*!< FDCAN1 Interrupt line 0 */ + FDCAN2_IT0_IRQn = 20, /*!< FDCAN2 Interrupt line 0 */ + FDCAN1_IT1_IRQn = 21, /*!< FDCAN1 Interrupt line 1 */ + FDCAN2_IT1_IRQn = 22, /*!< FDCAN2 Interrupt line 1 */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + FDCAN_CAL_IRQn = 63, /*!< FDCAN Calibration unit Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_PSSI_IRQn = 78, /*!< DCMI and PSSI global interrupt */ + CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ + HASH_RNG_IRQn = 80, /*!< HASH and RNG global interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SPI6_IRQn = 86, /*!< SPI6 global Interrupt */ + SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ + LTDC_IRQn = 88, /*!< LTDC global Interrupt */ + LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */ + DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */ + OCTOSPI1_IRQn = 92, /*!< OCTOSPI1 global interrupt */ + LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */ + CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */ + I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */ + I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */ + SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */ + DMAMUX1_OVR_IRQn = 102, /*! + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC Interrupt and Status Register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC Interrupt Enable Register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC Configuration register, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x18 */ + __IO uint32_t PCSEL_RES0; /*!< Rserved for ADC3, ADC1/2 pre-channel selection, Address offset: 0x1C */ + __IO uint32_t LTR1_TR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */ + __IO uint32_t HTR1_TR2; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */ + __IO uint32_t RES1_TR3; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x02C */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC regular sequence register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x044 */ + uint32_t RESERVED4; /*!< Reserved, 0x048 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x050 - 0x05C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x070 - 0x07C */ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC Analog Watchdog 2 Configuration Register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC Analog Watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t LTR2_DIFSEL; /*!< ADC watchdog Lower threshold register 2, Difsel for ADC3, Address offset: 0xB0 */ + __IO uint32_t HTR2_CALFACT; /*!< ADC watchdog Higher threshold register 2, Calfact for ADC3, Address offset: 0xB4 */ + __IO uint32_t LTR3_RES10; /*!< ADC watchdog Lower threshold register 3, specific ADC1/2, Address offset: 0xB8 */ + __IO uint32_t HTR3_RES11; /*!< ADC watchdog Higher threshold register 3, specific ADC1/2, Address offset: 0xBC */ + __IO uint32_t DIFSEL_RES12; /*!< ADC Differential Mode Selection Register specific ADC1/2, Address offset: 0xC0 */ + __IO uint32_t CALFACT_RES13; /*!< ADC Calibration Factors specific ADC1/2, Address offset: 0xC4 */ + __IO uint32_t CALFACT2_RES14; /*!< ADC Linearity Calibration Factors specific ADC1/2, Address offset: 0xC8 */ +} ADC_TypeDef; + + +typedef struct +{ +__IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1/3 base address + 0x300 */ +uint32_t RESERVED; /*!< Reserved, ADC1/3 base address + 0x304 */ +__IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1/3 base address + 0x308 */ +__IO uint32_t CDR; /*!< ADC common regular data register for dual Address offset: ADC1/3 base address + 0x30C */ +__IO uint32_t CDR2; /*!< ADC common regular data register for 32-bit dual mode Address offset: ADC1/3 base address + 0x310 */ + +} ADC_Common_TypeDef; + + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< FDCAN Core Release register, Address offset: 0x000 */ + __IO uint32_t ENDN; /*!< FDCAN Endian register, Address offset: 0x004 */ + __IO uint32_t RESERVED1; /*!< Reserved, 0x008 */ + __IO uint32_t DBTP; /*!< FDCAN Data Bit Timing & Prescaler register, Address offset: 0x00C */ + __IO uint32_t TEST; /*!< FDCAN Test register, Address offset: 0x010 */ + __IO uint32_t RWD; /*!< FDCAN RAM Watchdog register, Address offset: 0x014 */ + __IO uint32_t CCCR; /*!< FDCAN CC Control register, Address offset: 0x018 */ + __IO uint32_t NBTP; /*!< FDCAN Nominal Bit Timing & Prescaler register, Address offset: 0x01C */ + __IO uint32_t TSCC; /*!< FDCAN Timestamp Counter Configuration register, Address offset: 0x020 */ + __IO uint32_t TSCV; /*!< FDCAN Timestamp Counter Value register, Address offset: 0x024 */ + __IO uint32_t TOCC; /*!< FDCAN Timeout Counter Configuration register, Address offset: 0x028 */ + __IO uint32_t TOCV; /*!< FDCAN Timeout Counter Value register, Address offset: 0x02C */ + __IO uint32_t RESERVED2[4]; /*!< Reserved, 0x030 - 0x03C */ + __IO uint32_t ECR; /*!< FDCAN Error Counter register, Address offset: 0x040 */ + __IO uint32_t PSR; /*!< FDCAN Protocol Status register, Address offset: 0x044 */ + __IO uint32_t TDCR; /*!< FDCAN Transmitter Delay Compensation register, Address offset: 0x048 */ + __IO uint32_t RESERVED3; /*!< Reserved, 0x04C */ + __IO uint32_t IR; /*!< FDCAN Interrupt register, Address offset: 0x050 */ + __IO uint32_t IE; /*!< FDCAN Interrupt Enable register, Address offset: 0x054 */ + __IO uint32_t ILS; /*!< FDCAN Interrupt Line Select register, Address offset: 0x058 */ + __IO uint32_t ILE; /*!< FDCAN Interrupt Line Enable register, Address offset: 0x05C */ + __IO uint32_t RESERVED4[8]; /*!< Reserved, 0x060 - 0x07C */ + __IO uint32_t GFC; /*!< FDCAN Global Filter Configuration register, Address offset: 0x080 */ + __IO uint32_t SIDFC; /*!< FDCAN Standard ID Filter Configuration register, Address offset: 0x084 */ + __IO uint32_t XIDFC; /*!< FDCAN Extended ID Filter Configuration register, Address offset: 0x088 */ + __IO uint32_t RESERVED5; /*!< Reserved, 0x08C */ + __IO uint32_t XIDAM; /*!< FDCAN Extended ID AND Mask register, Address offset: 0x090 */ + __IO uint32_t HPMS; /*!< FDCAN High Priority Message Status register, Address offset: 0x094 */ + __IO uint32_t NDAT1; /*!< FDCAN New Data 1 register, Address offset: 0x098 */ + __IO uint32_t NDAT2; /*!< FDCAN New Data 2 register, Address offset: 0x09C */ + __IO uint32_t RXF0C; /*!< FDCAN Rx FIFO 0 Configuration register, Address offset: 0x0A0 */ + __IO uint32_t RXF0S; /*!< FDCAN Rx FIFO 0 Status register, Address offset: 0x0A4 */ + __IO uint32_t RXF0A; /*!< FDCAN Rx FIFO 0 Acknowledge register, Address offset: 0x0A8 */ + __IO uint32_t RXBC; /*!< FDCAN Rx Buffer Configuration register, Address offset: 0x0AC */ + __IO uint32_t RXF1C; /*!< FDCAN Rx FIFO 1 Configuration register, Address offset: 0x0B0 */ + __IO uint32_t RXF1S; /*!< FDCAN Rx FIFO 1 Status register, Address offset: 0x0B4 */ + __IO uint32_t RXF1A; /*!< FDCAN Rx FIFO 1 Acknowledge register, Address offset: 0x0B8 */ + __IO uint32_t RXESC; /*!< FDCAN Rx Buffer/FIFO Element Size Configuration register, Address offset: 0x0BC */ + __IO uint32_t TXBC; /*!< FDCAN Tx Buffer Configuration register, Address offset: 0x0C0 */ + __IO uint32_t TXFQS; /*!< FDCAN Tx FIFO/Queue Status register, Address offset: 0x0C4 */ + __IO uint32_t TXESC; /*!< FDCAN Tx Buffer Element Size Configuration register, Address offset: 0x0C8 */ + __IO uint32_t TXBRP; /*!< FDCAN Tx Buffer Request Pending register, Address offset: 0x0CC */ + __IO uint32_t TXBAR; /*!< FDCAN Tx Buffer Add Request register, Address offset: 0x0D0 */ + __IO uint32_t TXBCR; /*!< FDCAN Tx Buffer Cancellation Request register, Address offset: 0x0D4 */ + __IO uint32_t TXBTO; /*!< FDCAN Tx Buffer Transmission Occurred register, Address offset: 0x0D8 */ + __IO uint32_t TXBCF; /*!< FDCAN Tx Buffer Cancellation Finished register, Address offset: 0x0DC */ + __IO uint32_t TXBTIE; /*!< FDCAN Tx Buffer Transmission Interrupt Enable register, Address offset: 0x0E0 */ + __IO uint32_t TXBCIE; /*!< FDCAN Tx Buffer Cancellation Finished Interrupt Enable register, Address offset: 0x0E4 */ + __IO uint32_t RESERVED6[2]; /*!< Reserved, 0x0E8 - 0x0EC */ + __IO uint32_t TXEFC; /*!< FDCAN Tx Event FIFO Configuration register, Address offset: 0x0F0 */ + __IO uint32_t TXEFS; /*!< FDCAN Tx Event FIFO Status register, Address offset: 0x0F4 */ + __IO uint32_t TXEFA; /*!< FDCAN Tx Event FIFO Acknowledge register, Address offset: 0x0F8 */ + __IO uint32_t RESERVED7; /*!< Reserved, 0x0FC */ +} FDCAN_GlobalTypeDef; + +/** + * @brief TTFD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t TTTMC; /*!< TT Trigger Memory Configuration register, Address offset: 0x100 */ + __IO uint32_t TTRMC; /*!< TT Reference Message Configuration register, Address offset: 0x104 */ + __IO uint32_t TTOCF; /*!< TT Operation Configuration register, Address offset: 0x108 */ + __IO uint32_t TTMLM; /*!< TT Matrix Limits register, Address offset: 0x10C */ + __IO uint32_t TURCF; /*!< TUR Configuration register, Address offset: 0x110 */ + __IO uint32_t TTOCN; /*!< TT Operation Control register, Address offset: 0x114 */ + __IO uint32_t TTGTP; /*!< TT Global Time Preset register, Address offset: 0x118 */ + __IO uint32_t TTTMK; /*!< TT Time Mark register, Address offset: 0x11C */ + __IO uint32_t TTIR; /*!< TT Interrupt register, Address offset: 0x120 */ + __IO uint32_t TTIE; /*!< TT Interrupt Enable register, Address offset: 0x124 */ + __IO uint32_t TTILS; /*!< TT Interrupt Line Select register, Address offset: 0x128 */ + __IO uint32_t TTOST; /*!< TT Operation Status register, Address offset: 0x12C */ + __IO uint32_t TURNA; /*!< TT TUR Numerator Actual register, Address offset: 0x130 */ + __IO uint32_t TTLGT; /*!< TT Local and Global Time register, Address offset: 0x134 */ + __IO uint32_t TTCTC; /*!< TT Cycle Time and Count register, Address offset: 0x138 */ + __IO uint32_t TTCPT; /*!< TT Capture Time register, Address offset: 0x13C */ + __IO uint32_t TTCSM; /*!< TT Cycle Sync Mark register, Address offset: 0x140 */ + __IO uint32_t RESERVED1[111]; /*!< Reserved, 0x144 - 0x2FC */ + __IO uint32_t TTTS; /*!< TT Trigger Select register, Address offset: 0x300 */ +} TTCAN_TypeDef; + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< Clock Calibration Unit Core Release register, Address offset: 0x00 */ + __IO uint32_t CCFG; /*!< Calibration Configuration register, Address offset: 0x04 */ + __IO uint32_t CSTAT; /*!< Calibration Status register, Address offset: 0x08 */ + __IO uint32_t CWD; /*!< Calibration Watchdog register, Address offset: 0x0C */ + __IO uint32_t IR; /*!< CCU Interrupt register, Address offset: 0x10 */ + __IO uint32_t IE; /*!< CCU Interrupt Enable register, Address offset: 0x14 */ +} FDCAN_ClockCalibrationUnit_TypeDef; + + +/** + * @brief Consumer Electronics Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ + __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ + __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ + __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ + __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ + __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ +}CEC_TypeDef; + +/** + * @brief COordincate Rotation DIgital Computer + */ +typedef struct +{ + __IO uint32_t CSR; /*!< CORDIC control and status register, Address offset: 0x00 */ + __IO uint32_t WDATA; /*!< CORDIC argument register, Address offset: 0x04 */ + __IO uint32_t RDATA; /*!< CORDIC result register, Address offset: 0x08 */ +} CORDIC_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint32_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + + +/** + * @brief Clock Recovery System + */ +typedef struct +{ +__IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */ +__IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */ +__IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */ +__IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */ +} CRS_TypeDef; + + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + uint32_t RESERVED4[11]; /*!< Reserved, Address offset: 0x08 */ + __IO uint32_t APB3FZ1; /*!< Debug MCU APB3FZ1 freeze register, Address offset: 0x34 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x38 */ + __IO uint32_t APB1LFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x3C */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x40 */ + __IO uint32_t APB1HFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x44 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t APB2FZ1; /*!< Debug MCU APB2FZ1 freeze register, Address offset: 0x4C */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0x50 */ + __IO uint32_t APB4FZ1; /*!< Debug MCU APB4FZ1 freeze register, Address offset: 0x54 */ + __IO uint32_t RESERVED9[990]; /*!< Reserved, Address offset: 0x58-0xFCC */ + __IO uint32_t PIDR4; /*!< Debug MCU peripheral identity register 4, Address offset: 0xFD0 */ + __IO uint32_t RESERVED10[3];/*!< Reserved, Address offset: 0xFD4-0xFDC */ + __IO uint32_t PIDR0; /*!< Debug MCU peripheral identity register 0, Address offset: 0xFE0 */ + __IO uint32_t PIDR1; /*!< Debug MCU peripheral identity register 1, Address offset: 0xFE4 */ + __IO uint32_t PIDR2; /*!< Debug MCU peripheral identity register 2, Address offset: 0xFE8 */ + __IO uint32_t PIDR3; /*!< Debug MCU peripheral identity register 3, Address offset: 0xFEC */ + __IO uint32_t CIDR0; /*!< Debug MCU component identity register 0, Address offset: 0xFF0 */ + __IO uint32_t CIDR1; /*!< Debug MCU component identity register 1, Address offset: 0xFF4 */ + __IO uint32_t CIDR2; /*!< Debug MCU component identity register 2, Address offset: 0xFF8 */ + __IO uint32_t CIDR3; /*!< Debug MCU component identity register 3, Address offset: 0xFFC */ +}DBGMCU_TypeDef; +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief PSSI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< PSSI control register 1, Address offset: 0x000 */ + __IO uint32_t SR; /*!< PSSI status register, Address offset: 0x004 */ + __IO uint32_t RIS; /*!< PSSI raw interrupt status register, Address offset: 0x008 */ + __IO uint32_t IER; /*!< PSSI interrupt enable register, Address offset: 0x00C */ + __IO uint32_t MIS; /*!< PSSI masked interrupt status register, Address offset: 0x010 */ + __IO uint32_t ICR; /*!< PSSI interrupt clear register, Address offset: 0x014 */ + __IO uint32_t RESERVED1[4]; /*!< Reserved, 0x018 - 0x024 */ + __IO uint32_t DR; /*!< PSSI data register, Address offset: 0x028 */ + __IO uint32_t RESERVED2[241]; /*!< Reserved, 0x02C - 0x3EC */ + __IO uint32_t HWCFGR; /*!< PSSI IP HW configuration register, Address offset: 0x3F0 */ + __IO uint32_t VERR; /*!< PSSI IP version register, Address offset: 0x3F4 */ + __IO uint32_t IPIDR; /*!< PSSI IP ID register, Address offset: 0x3F8 */ + __IO uint32_t SIDR; /*!< PSSI SIZE ID register, Address offset: 0x3FC */ +} PSSI_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CM0AR; /*!< DMA channel x memory 0 address register */ + __IO uint32_t CM1AR; /*!< DMA channel x memory 1 address register */ +} BDMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} BDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA Multiplexer Channel x Control Register */ +}DMAMUX_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< DMA Channel Status Register */ + __IO uint32_t CFR; /*!< DMA Channel Clear Flag Register */ +}DMAMUX_ChannelStatus_TypeDef; + +typedef struct +{ + __IO uint32_t RGCR; /*!< DMA Request Generator x Control Register */ +}DMAMUX_RequestGen_TypeDef; + +typedef struct +{ + __IO uint32_t RGSR; /*!< DMA Request Generator Status Register */ + __IO uint32_t RGCFR; /*!< DMA Request Generator Clear Flag Register */ +}DMAMUX_RequestGenStatus_TypeDef; + +/** + * @brief MDMA Controller + */ +typedef struct +{ + __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */ +}MDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */ + __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */ + __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */ + __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ + __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */ + __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */ + __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */ + __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */ + __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */ + __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */ + __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */ + uint32_t RESERVED0; /*!< Reserved, 0x6C */ + __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */ + __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */ +}MDMA_Channel_TypeDef; + +/** + * @brief DMA2D Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ + __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ + __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ + __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ + __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ + __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ + __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ + __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ + __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ + __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ + __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ + __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ + __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ + __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ + __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ + __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ + __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ + __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ + __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ + __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ + uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ + __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ + __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ +} DMA2D_TypeDef; + + +/** + * @brief Ethernet MAC + */ +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACECR; + __IO uint32_t MACPFR; + __IO uint32_t MACWTR; + __IO uint32_t MACHT0R; + __IO uint32_t MACHT1R; + uint32_t RESERVED1[14]; + __IO uint32_t MACVTR; + uint32_t RESERVED2; + __IO uint32_t MACVHTR; + uint32_t RESERVED3; + __IO uint32_t MACVIR; + __IO uint32_t MACIVIR; + uint32_t RESERVED4[2]; + __IO uint32_t MACTFCR; + uint32_t RESERVED5[7]; + __IO uint32_t MACRFCR; + uint32_t RESERVED6[7]; + __IO uint32_t MACISR; + __IO uint32_t MACIER; + __IO uint32_t MACRXTXSR; + uint32_t RESERVED7; + __IO uint32_t MACPCSR; + __IO uint32_t MACRWKPFR; + uint32_t RESERVED8[2]; + __IO uint32_t MACLCSR; + __IO uint32_t MACLTCR; + __IO uint32_t MACLETR; + __IO uint32_t MAC1USTCR; + uint32_t RESERVED9[12]; + __IO uint32_t MACVR; + __IO uint32_t MACDR; + uint32_t RESERVED10; + __IO uint32_t MACHWF0R; + __IO uint32_t MACHWF1R; + __IO uint32_t MACHWF2R; + uint32_t RESERVED11[54]; + __IO uint32_t MACMDIOAR; + __IO uint32_t MACMDIODR; + uint32_t RESERVED12[2]; + __IO uint32_t MACARPAR; + uint32_t RESERVED13[59]; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; + uint32_t RESERVED14[248]; + __IO uint32_t MMCCR; + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; + uint32_t RESERVED15[14]; + __IO uint32_t MMCTSCGPR; + __IO uint32_t MMCTMCGPR; + uint32_t RESERVED16[5]; + __IO uint32_t MMCTPCGR; + uint32_t RESERVED17[10]; + __IO uint32_t MMCRCRCEPR; + __IO uint32_t MMCRAEPR; + uint32_t RESERVED18[10]; + __IO uint32_t MMCRUPGR; + uint32_t RESERVED19[9]; + __IO uint32_t MMCTLPIMSTR; + __IO uint32_t MMCTLPITCR; + __IO uint32_t MMCRLPIMSTR; + __IO uint32_t MMCRLPITCR; + uint32_t RESERVED20[65]; + __IO uint32_t MACL3L4C0R; + __IO uint32_t MACL4A0R; + uint32_t RESERVED21[2]; + __IO uint32_t MACL3A0R0R; + __IO uint32_t MACL3A1R0R; + __IO uint32_t MACL3A2R0R; + __IO uint32_t MACL3A3R0R; + uint32_t RESERVED22[4]; + __IO uint32_t MACL3L4C1R; + __IO uint32_t MACL4A1R; + uint32_t RESERVED23[2]; + __IO uint32_t MACL3A0R1R; + __IO uint32_t MACL3A1R1R; + __IO uint32_t MACL3A2R1R; + __IO uint32_t MACL3A3R1R; + uint32_t RESERVED24[108]; + __IO uint32_t MACTSCR; + __IO uint32_t MACSSIR; + __IO uint32_t MACSTSR; + __IO uint32_t MACSTNR; + __IO uint32_t MACSTSUR; + __IO uint32_t MACSTNUR; + __IO uint32_t MACTSAR; + uint32_t RESERVED25; + __IO uint32_t MACTSSR; + uint32_t RESERVED26[3]; + __IO uint32_t MACTTSSNR; + __IO uint32_t MACTTSSSR; + uint32_t RESERVED27[2]; + __IO uint32_t MACACR; + uint32_t RESERVED28; + __IO uint32_t MACATSNR; + __IO uint32_t MACATSSR; + __IO uint32_t MACTSIACR; + __IO uint32_t MACTSEACR; + __IO uint32_t MACTSICNR; + __IO uint32_t MACTSECNR; + uint32_t RESERVED29[4]; + __IO uint32_t MACPPSCR; + uint32_t RESERVED30[3]; + __IO uint32_t MACPPSTTSR; + __IO uint32_t MACPPSTTNR; + __IO uint32_t MACPPSIR; + __IO uint32_t MACPPSWR; + uint32_t RESERVED31[12]; + __IO uint32_t MACPOCR; + __IO uint32_t MACSPI0R; + __IO uint32_t MACSPI1R; + __IO uint32_t MACSPI2R; + __IO uint32_t MACLMIR; + uint32_t RESERVED32[11]; + __IO uint32_t MTLOMR; + uint32_t RESERVED33[7]; + __IO uint32_t MTLISR; + uint32_t RESERVED34[55]; + __IO uint32_t MTLTQOMR; + __IO uint32_t MTLTQUR; + __IO uint32_t MTLTQDR; + uint32_t RESERVED35[8]; + __IO uint32_t MTLQICSR; + __IO uint32_t MTLRQOMR; + __IO uint32_t MTLRQMPOCR; + __IO uint32_t MTLRQDR; + uint32_t RESERVED36[177]; + __IO uint32_t DMAMR; + __IO uint32_t DMASBMR; + __IO uint32_t DMAISR; + __IO uint32_t DMADSR; + uint32_t RESERVED37[60]; + __IO uint32_t DMACCR; + __IO uint32_t DMACTCR; + __IO uint32_t DMACRCR; + uint32_t RESERVED38[2]; + __IO uint32_t DMACTDLAR; + uint32_t RESERVED39; + __IO uint32_t DMACRDLAR; + __IO uint32_t DMACTDTPR; + uint32_t RESERVED40; + __IO uint32_t DMACRDTPR; + __IO uint32_t DMACTDRLR; + __IO uint32_t DMACRDRLR; + __IO uint32_t DMACIER; + __IO uint32_t DMACRIWTR; +__IO uint32_t DMACSFCSR; + uint32_t RESERVED41; + __IO uint32_t DMACCATDR; + uint32_t RESERVED42; + __IO uint32_t DMACCARDR; + uint32_t RESERVED43; + __IO uint32_t DMACCATBR; + uint32_t RESERVED44; + __IO uint32_t DMACCARBR; + __IO uint32_t DMACSR; +uint32_t RESERVED45[2]; +__IO uint32_t DMACMFCR; +}ETH_TypeDef; +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ +__IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register, Address offset: 0x00 */ +__IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register, Address offset: 0x04 */ +__IO uint32_t SWIER1; /*!< EXTI Software interrupt event register, Address offset: 0x08 */ +__IO uint32_t D3PMR1; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR1) Address offset: 0x0C */ +__IO uint32_t D3PCR1L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR1L) Address offset: 0x10 */ +__IO uint32_t D3PCR1H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR1H) Address offset: 0x14 */ +uint32_t RESERVED1[2]; /*!< Reserved, 0x18 to 0x1C */ +__IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register, Address offset: 0x20 */ +__IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register, Address offset: 0x24 */ +__IO uint32_t SWIER2; /*!< EXTI Software interrupt event register, Address offset: 0x28 */ +__IO uint32_t D3PMR2; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR2) Address offset: 0x2C */ +__IO uint32_t D3PCR2L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR2L) Address offset: 0x30 */ +__IO uint32_t D3PCR2H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR2H) Address offset: 0x34 */ +uint32_t RESERVED2[2]; /*!< Reserved, 0x38 to 0x3C */ +__IO uint32_t RTSR3; /*!< EXTI Rising trigger selection register, Address offset: 0x40 */ +__IO uint32_t FTSR3; /*!< EXTI Falling trigger selection register, Address offset: 0x44 */ +__IO uint32_t SWIER3; /*!< EXTI Software interrupt event register, Address offset: 0x48 */ +__IO uint32_t D3PMR3; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR3) Address offset: 0x4C */ +__IO uint32_t D3PCR3L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR3L) Address offset: 0x50 */ +__IO uint32_t D3PCR3H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR3H) Address offset: 0x54 */ +uint32_t RESERVED3[10]; /*!< Reserved, 0x58 to 0x7C */ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x80 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x84 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x88 */ +uint32_t RESERVED4; /*!< Reserved, 0x8C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x90 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x94 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x98 */ +uint32_t RESERVED5; /*!< Reserved, 0x9C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0xA0 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0xA4 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0xA8 */ +}EXTI_TypeDef; + +/** + * @brief This structure registers corresponds to EXTI_Typdef CPU1/CPU2 registers subset (IMRx, EMRx and PRx), allowing to define EXTI_D1/EXTI_D2 + * with rapid/common access to these IMRx, EMRx, PRx registers for CPU1 and CPU2. + * Note that EXTI_D1 and EXTI_D2 bases addresses are calculated to point to CPUx first register: + * IMR1 in case of EXTI_D1 that is addressing CPU1 (Coretx-M7) + * C2IMR1 in case of EXTI_D2 that is addressing CPU2 (Coretx-M4) + * Note: EXTI_D2 and corresponding C2IMRx, C2EMRx and C2PRx registers are available for Dual Core devices only + */ + +typedef struct +{ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x04 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x08 */ +uint32_t RESERVED1; /*!< Reserved, 0x0C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x10 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x14 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x18 */ +uint32_t RESERVED2; /*!< Reserved, 0x1C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0x20 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0x24 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0x28 */ +}EXTI_Core_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR1; /*!< Flash Key Register for bank1, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< Flash Option Key Register, Address offset: 0x08 */ + __IO uint32_t CR1; /*!< Flash Control Register for bank1, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< Flash Status Register for bank1, Address offset: 0x10 */ + __IO uint32_t CCR1; /*!< Flash Control Register for bank1, Address offset: 0x14 */ + __IO uint32_t OPTCR; /*!< Flash Option Control Register, Address offset: 0x18 */ + __IO uint32_t OPTSR_CUR; /*!< Flash Option Status Current Register, Address offset: 0x1C */ + __IO uint32_t OPTSR_PRG; /*!< Flash Option Status to Program Register, Address offset: 0x20 */ + __IO uint32_t OPTCCR; /*!< Flash Option Clear Control Register, Address offset: 0x24 */ + __IO uint32_t PRAR_CUR1; /*!< Flash Current Protection Address Register for bank1, Address offset: 0x28 */ + __IO uint32_t PRAR_PRG1; /*!< Flash Protection Address to Program Register for bank1, Address offset: 0x2C */ + __IO uint32_t SCAR_CUR1; /*!< Flash Current Secure Address Register for bank1, Address offset: 0x30 */ + __IO uint32_t SCAR_PRG1; /*!< Flash Secure Address to Program Register for bank1, Address offset: 0x34 */ + __IO uint32_t WPSN_CUR1; /*!< Flash Current Write Protection Register on bank1, Address offset: 0x38 */ + __IO uint32_t WPSN_PRG1; /*!< Flash Write Protection to Program Register on bank1, Address offset: 0x3C */ + __IO uint32_t BOOT_CUR; /*!< Flash Current Boot Address for Pelican Core Register, Address offset: 0x40 */ + __IO uint32_t BOOT_PRG; /*!< Flash Boot Address to Program for Pelican Core Register, Address offset: 0x44 */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x48 to 0x4C */ + __IO uint32_t CRCCR1; /*!< Flash CRC Control register For Bank1 Register , Address offset: 0x50 */ + __IO uint32_t CRCSADD1; /*!< Flash CRC Start Address Register for Bank1 , Address offset: 0x54 */ + __IO uint32_t CRCEADD1; /*!< Flash CRC End Address Register for Bank1 , Address offset: 0x58 */ + __IO uint32_t CRCDATA; /*!< Flash CRC Data Register for Bank1 , Address offset: 0x5C */ + __IO uint32_t ECC_FA1; /*!< Flash ECC Fail Address For Bank1 Register , Address offset: 0x60 */ + uint32_t RESERVED[3]; /*!< Reserved, 0x64 to 0x6C */ + __IO uint32_t OPTSR2_CUR; /*!< Flash Option Status Current Register 2, Address offset: 0x70 */ + __IO uint32_t OPTSR2_PRG; /*!< Flash Option Status to Program Register 2, Address offset: 0x74 */ +} FLASH_TypeDef; + +/** + * @brief Filter and Mathematical ACcelerator + */ +typedef struct +{ + __IO uint32_t X1BUFCFG; /*!< FMAC X1 Buffer Configuration register, Address offset: 0x00 */ + __IO uint32_t X2BUFCFG; /*!< FMAC X2 Buffer Configuration register, Address offset: 0x04 */ + __IO uint32_t YBUFCFG; /*!< FMAC Y Buffer Configuration register, Address offset: 0x08 */ + __IO uint32_t PARAM; /*!< FMAC Parameter register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FMAC Control register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< FMAC Status register, Address offset: 0x14 */ + __IO uint32_t WDATA; /*!< FMAC Write Data register, Address offset: 0x18 */ + __IO uint32_t RDATA; /*!< FMAC Read Data register, Address offset: 0x1C */ +} FMAC_TypeDef; + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank2 + */ + +typedef struct +{ + __IO uint32_t PCR2; /*!< NAND Flash control register 2, Address offset: 0x60 */ + __IO uint32_t SR2; /*!< NAND Flash FIFO status and interrupt register 2, Address offset: 0x64 */ + __IO uint32_t PMEM2; /*!< NAND Flash Common memory space timing register 2, Address offset: 0x68 */ + __IO uint32_t PATT2; /*!< NAND Flash Attribute memory space timing register 2, Address offset: 0x6C */ + uint32_t RESERVED0; /*!< Reserved, 0x70 */ + __IO uint32_t ECCR2; /*!< NAND Flash ECC result registers 2, Address offset: 0x74 */ +} FMC_Bank2_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register 3, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register 3, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register 3, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register 3, Address offset: 0x8C */ + uint32_t RESERVED; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers 3, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief Flexible Memory Controller Bank5 and 6 + */ + + +typedef struct +{ + __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */ + __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */ + __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */ + __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */ + __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */ +} FMC_Bank5_6_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t HSOTR; /*!< OPAMP offset trimming register for high speed mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x00 */ + __IO uint32_t PMCR; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t CFGR; /*!< SYSCFG configuration registers, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t CCCSR; /*!< SYSCFG compensation cell control/status register, Address offset: 0x20 */ + __IO uint32_t CCVR; /*!< SYSCFG compensation cell value register, Address offset: 0x24 */ + __IO uint32_t CCCR; /*!< SYSCFG compensation cell code register, Address offset: 0x28 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t ADC2ALT; /*!< ADC2 internal input alternate connection register, Address offset: 0x30 */ + uint32_t RESERVED4[60]; /*!< Reserved, 0x34-0x120 */ + __IO uint32_t PKGR; /*!< SYSCFG package register, Address offset: 0x124 */ + uint32_t RESERVED5[118]; /*!< Reserved, 0x128-0x2FC */ + __IO uint32_t UR0; /*!< SYSCFG user register 0, Address offset: 0x300 */ + __IO uint32_t UR1; /*!< SYSCFG user register 1, Address offset: 0x304 */ + __IO uint32_t UR2; /*!< SYSCFG user register 2, Address offset: 0x308 */ + __IO uint32_t UR3; /*!< SYSCFG user register 3, Address offset: 0x30C */ + __IO uint32_t UR4; /*!< SYSCFG user register 4, Address offset: 0x310 */ + __IO uint32_t UR5; /*!< SYSCFG user register 5, Address offset: 0x314 */ + __IO uint32_t UR6; /*!< SYSCFG user register 6, Address offset: 0x318 */ + __IO uint32_t UR7; /*!< SYSCFG user register 7, Address offset: 0x31C */ + uint32_t RESERVED6[3]; /*!< Reserved, Address offset: 0x320-0x328 */ + __IO uint32_t UR11; /*!< SYSCFG user register 11, Address offset: 0x32C */ + __IO uint32_t UR12; /*!< SYSCFG user register 12, Address offset: 0x330 */ + __IO uint32_t UR13; /*!< SYSCFG user register 13, Address offset: 0x334 */ + __IO uint32_t UR14; /*!< SYSCFG user register 14, Address offset: 0x338 */ + __IO uint32_t UR15; /*!< SYSCFG user register 15, Address offset: 0x33C */ + __IO uint32_t UR16; /*!< SYSCFG user register 16, Address offset: 0x340 */ + __IO uint32_t UR17; /*!< SYSCFG user register 17, Address offset: 0x344 */ + __IO uint32_t UR18; /*!< SYSCFG user register 18, Address offset: 0x348 */ + +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + + +/** + * @brief LCD-TFT Display Controller + */ + +typedef struct +{ + uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */ + __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */ + __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */ + __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */ + __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */ + __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */ + __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */ + uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */ + __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */ + uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */ + __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */ + __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */ + __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */ + __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */ + __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */ + __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */ +} LTDC_TypeDef; + +/** + * @brief LCD-TFT Display layer x Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */ + __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */ + __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */ + __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */ + __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */ + __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */ + __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */ + __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */ + uint32_t RESERVED0[2]; /*!< Reserved */ + __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */ + __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */ + __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */ + uint32_t RESERVED1[3]; /*!< Reserved */ + __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */ + +} LTDC_Layer_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CSR1; /*!< PWR power control status register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x0C */ + __IO uint32_t CPUCR; /*!< PWR CPU control register, Address offset: 0x10 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D3CR; /*!< PWR D3 domain control register, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t WKUPCR; /*!< PWR wakeup clear register, Address offset: 0x20 */ + __IO uint32_t WKUPFR; /*!< PWR wakeup flag register, Address offset: 0x24 */ + __IO uint32_t WKUPEPR; /*!< PWR wakeup enable and polarity register, Address offset: 0x28 */ +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t HSICFGR; /*!< HSI Clock Calibration Register, Address offset: 0x04 */ + __IO uint32_t CRRCR; /*!< Clock Recovery RC Register, Address offset: 0x08 */ + __IO uint32_t CSICFGR; /*!< CSI Clock Calibration Register, Address offset: 0x0C */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D1CFGR; /*!< RCC Domain 1 configuration register, Address offset: 0x18 */ + __IO uint32_t D2CFGR; /*!< RCC Domain 2 configuration register, Address offset: 0x1C */ + __IO uint32_t D3CFGR; /*!< RCC Domain 3 configuration register, Address offset: 0x20 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t PLLCKSELR; /*!< RCC PLLs Clock Source Selection Register, Address offset: 0x28 */ + __IO uint32_t PLLCFGR; /*!< RCC PLLs Configuration Register, Address offset: 0x2C */ + __IO uint32_t PLL1DIVR; /*!< RCC PLL1 Dividers Configuration Register, Address offset: 0x30 */ + __IO uint32_t PLL1FRACR; /*!< RCC PLL1 Fractional Divider Configuration Register, Address offset: 0x34 */ + __IO uint32_t PLL2DIVR; /*!< RCC PLL2 Dividers Configuration Register, Address offset: 0x38 */ + __IO uint32_t PLL2FRACR; /*!< RCC PLL2 Fractional Divider Configuration Register, Address offset: 0x3C */ + __IO uint32_t PLL3DIVR; /*!< RCC PLL3 Dividers Configuration Register, Address offset: 0x40 */ + __IO uint32_t PLL3FRACR; /*!< RCC PLL3 Fractional Divider Configuration Register, Address offset: 0x44 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t D1CCIPR; /*!< RCC Domain 1 Kernel Clock Configuration Register Address offset: 0x4C */ + __IO uint32_t D2CCIP1R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x50 */ + __IO uint32_t D2CCIP2R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x54 */ + __IO uint32_t D3CCIPR; /*!< RCC Domain 3 Kernel Clock Configuration Register Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x5C */ + __IO uint32_t CIER; /*!< RCC Clock Source Interrupt Enable Register Address offset: 0x60 */ + __IO uint32_t CIFR; /*!< RCC Clock Source Interrupt Flag Register Address offset: 0x64 */ + __IO uint32_t CICR; /*!< RCC Clock Source Interrupt Clear Register Address offset: 0x68 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x6C */ + __IO uint32_t BDCR; /*!< RCC Vswitch Backup Domain Control Register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x78 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x7C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x80 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x84 */ + __IO uint32_t AHB4RSTR; /*!< RCC AHB4 peripheral reset register, Address offset: 0x88 */ + __IO uint32_t APB3RSTR; /*!< RCC APB3 peripheral reset register, Address offset: 0x8C */ + __IO uint32_t APB1LRSTR; /*!< RCC APB1 peripheral reset Low Word register, Address offset: 0x90 */ + __IO uint32_t APB1HRSTR; /*!< RCC APB1 peripheral reset High Word register, Address offset: 0x94 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x98 */ + __IO uint32_t APB4RSTR; /*!< RCC APB4 peripheral reset register, Address offset: 0x9C */ + __IO uint32_t GCR; /*!< RCC RCC Global Control Register, Address offset: 0xA0 */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0xA4 */ + __IO uint32_t D3AMR; /*!< RCC Domain 3 Autonomous Mode Register, Address offset: 0xA8 */ + uint32_t RESERVED11[9]; /*!< Reserved, 0xAC-0xCC Address offset: 0xAC */ + __IO uint32_t RSR; /*!< RCC Reset status register, Address offset: 0xD0 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0xD4 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0xD8 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0xDC */ + __IO uint32_t AHB4ENR; /*!< RCC AHB4 peripheral clock register, Address offset: 0xE0 */ + __IO uint32_t APB3ENR; /*!< RCC APB3 peripheral clock register, Address offset: 0xE4 */ + __IO uint32_t APB1LENR; /*!< RCC APB1 peripheral clock Low Word register, Address offset: 0xE8 */ + __IO uint32_t APB1HENR; /*!< RCC APB1 peripheral clock High Word register, Address offset: 0xEC */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock register, Address offset: 0xF0 */ + __IO uint32_t APB4ENR; /*!< RCC APB4 peripheral clock register, Address offset: 0xF4 */ + uint32_t RESERVED12; /*!< Reserved, Address offset: 0xF8 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral sleep clock register, Address offset: 0xFC */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral sleep clock register, Address offset: 0x100 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral sleep clock register, Address offset: 0x104 */ + __IO uint32_t AHB4LPENR; /*!< RCC AHB4 peripheral sleep clock register, Address offset: 0x108 */ + __IO uint32_t APB3LPENR; /*!< RCC APB3 peripheral sleep clock register, Address offset: 0x10C */ + __IO uint32_t APB1LLPENR; /*!< RCC APB1 peripheral sleep clock Low Word register, Address offset: 0x110 */ + __IO uint32_t APB1HLPENR; /*!< RCC APB1 peripheral sleep clock High Word register, Address offset: 0x114 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral sleep clock register, Address offset: 0x118 */ + __IO uint32_t APB4LPENR; /*!< RCC APB4 peripheral sleep clock register, Address offset: 0x11C */ + uint32_t RESERVED13[4]; /*!< Reserved, 0x120-0x12C Address offset: 0x120 */ + +} RCC_TypeDef; + + +/** + * @brief Real-Time Clock + */ +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ + uint32_t RESERVED0[16]; /*!< Reserved, 0x04 - 0x43 */ + __IO uint32_t PDMCR; /*!< SAI PDM control register, Address offset: 0x44 */ + __IO uint32_t PDMDLY; /*!< SAI PDM delay register, Address offset: 0x48 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + +/** + * @brief SPDIF-RX Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */ + __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */ + __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */ + __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */ + __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1A */ +} SPDIFRX_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgement timer register, Address offset: 0x40 */ + uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */ + __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */ + __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */ + __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */ + __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */ + uint32_t RESERVED1[8]; /*!< Reserved, 0x60-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ + uint32_t RESERVED2[222]; /*!< Reserved, 0x84-0x3F8 */ + __IO uint32_t IPVR; /*!< SDMMC data FIFO register, Address offset: 0x3FC */ +} SDMMC_TypeDef; + + +/** + * @brief Delay Block DLYB + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DELAY BLOCK control register, Address offset: 0x00 */ + __IO uint32_t CFGR; /*!< DELAY BLOCK configuration register, Address offset: 0x04 */ +} DLYB_TypeDef; + +/** + * @brief HW Semaphore HSEM + */ + +typedef struct +{ + __IO uint32_t R[32]; /*!< 2-step write lock and read back registers, Address offset: 00h-7Ch */ + __IO uint32_t RLR[32]; /*!< 1-step read lock registers, Address offset: 80h-FCh */ + __IO uint32_t C1IER; /*!< HSEM Interrupt enable register , Address offset: 100h */ + __IO uint32_t C1ICR; /*!< HSEM Interrupt clear register , Address offset: 104h */ + __IO uint32_t C1ISR; /*!< HSEM Interrupt Status register , Address offset: 108h */ + __IO uint32_t C1MISR; /*!< HSEM Interrupt Masked Status register , Address offset: 10Ch */ + uint32_t Reserved[12]; /* Reserved Address offset: 110h-13Ch */ + __IO uint32_t CR; /*!< HSEM Semaphore clear register , Address offset: 140h */ + __IO uint32_t KEYR; /*!< HSEM Semaphore clear key register , Address offset: 144h */ + +} HSEM_TypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< HSEM interrupt enable register , Address offset: 0h */ + __IO uint32_t ICR; /*!< HSEM interrupt clear register , Address offset: 4h */ + __IO uint32_t ISR; /*!< HSEM interrupt status register , Address offset: 8h */ + __IO uint32_t MISR; /*!< HSEM masked interrupt status register , Address offset: Ch */ +} HSEM_Common_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI/I2S Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t CFG1; /*!< SPI Configuration register 1, Address offset: 0x08 */ + __IO uint32_t CFG2; /*!< SPI Configuration register 2, Address offset: 0x0C */ + __IO uint32_t IER; /*!< SPI/I2S Interrupt Enable register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< SPI/I2S Status register, Address offset: 0x14 */ + __IO uint32_t IFCR; /*!< SPI/I2S Interrupt/Status flags clear register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t TXDR; /*!< SPI/I2S Transmit data register, Address offset: 0x20 */ + uint32_t RESERVED1[3]; /*!< Reserved, 0x24-0x2C */ + __IO uint32_t RXDR; /*!< SPI/I2S Receive data register, Address offset: 0x30 */ + uint32_t RESERVED2[3]; /*!< Reserved, 0x34-0x3C */ + __IO uint32_t CRCPOLY; /*!< SPI CRC Polynomial register, Address offset: 0x40 */ + __IO uint32_t TXCRC; /*!< SPI Transmitter CRC register, Address offset: 0x44 */ + __IO uint32_t RXCRC; /*!< SPI Receiver CRC register, Address offset: 0x48 */ + __IO uint32_t UDRDR; /*!< SPI Underrun data register, Address offset: 0x4C */ + __IO uint32_t I2SCFGR; /*!< I2S Configuration register, Address offset: 0x50 */ + +} SPI_TypeDef; + +/** + * @brief DTS + */ +typedef struct +{ + __IO uint32_t CFGR1; /*!< DTS configuration register, Address offset: 0x00 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x04 */ + __IO uint32_t T0VALR1; /*!< DTS T0 Value register, Address offset: 0x08 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x0C */ + __IO uint32_t RAMPVALR; /*!< DTS Ramp value register, Address offset: 0x10 */ + __IO uint32_t ITR1; /*!< DTS Interrupt threshold register, Address offset: 0x14 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t DR; /*!< DTS data register, Address offset: 0x1C */ + __IO uint32_t SR; /*!< DTS status register Address offset: 0x20 */ + __IO uint32_t ITENR; /*!< DTS Interrupt enable register, Address offset: 0x24 */ + __IO uint32_t ICIFR; /*!< DTS Clear Interrupt flag register, Address offset: 0x28 */ + __IO uint32_t OR; /*!< DTS option register 1, Address offset: 0x2C */ +} +DTS_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + uint32_t RESERVED1; /*!< Reserved, 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t AF1; /*!< TIM alternate function option register 1, Address offset: 0x60 */ + __IO uint32_t AF2; /*!< TIM alternate function option register 2, Address offset: 0x64 */ + __IO uint32_t TISEL; /*!< TIM Input Selection register, Address offset: 0x68 */ +} TIM_TypeDef; + +/** + * @brief LPTIMIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + uint32_t RESERVED1; /*!< Reserved, 0x20 */ + __IO uint32_t CFGR2; /*!< LPTIM Configuration register, Address offset: 0x24 */ +} LPTIM_TypeDef; + +/** + * @brief Comparator + */ +typedef struct +{ + __IO uint32_t SR; /*!< Comparator status register, Address offset: 0x00 */ + __IO uint32_t ICFR; /*!< Comparator interrupt clear flag register, Address offset: 0x04 */ + __IO uint32_t OR; /*!< Comparator option register, Address offset: 0x08 */ +} COMPOPT_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< Comparator configuration register , Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + __IO uint32_t PRESC; /*!< USART clock Prescaler register, Address offset: 0x2C */ +} USART_TypeDef; + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + + +/** + * @brief RAM_ECC_Specific_Registers + */ +typedef struct +{ + __IO uint32_t CR; /*!< RAMECC monitor configuration register */ + __IO uint32_t SR; /*!< RAMECC monitor status register */ + __IO uint32_t FAR; /*!< RAMECC monitor failing address register */ + __IO uint32_t FDRL; /*!< RAMECC monitor failing data low register */ + __IO uint32_t FDRH; /*!< RAMECC monitor failing data high register */ + __IO uint32_t FECR; /*!< RAMECC monitor failing ECC error code register */ +} RAMECC_MonitorTypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< RAMECC interrupt enable register */ +} RAMECC_TypeDef; +/** + * @} + */ + + +/** + * @brief Crypto Processor + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CRYP control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< CRYP status register, Address offset: 0x04 */ + __IO uint32_t DIN; /*!< CRYP data input register, Address offset: 0x08 */ + __IO uint32_t DOUT; /*!< CRYP data output register, Address offset: 0x0C */ + __IO uint32_t DMACR; /*!< CRYP DMA control register, Address offset: 0x10 */ + __IO uint32_t IMSCR; /*!< CRYP interrupt mask set/clear register, Address offset: 0x14 */ + __IO uint32_t RISR; /*!< CRYP raw interrupt status register, Address offset: 0x18 */ + __IO uint32_t MISR; /*!< CRYP masked interrupt status register, Address offset: 0x1C */ + __IO uint32_t K0LR; /*!< CRYP key left register 0, Address offset: 0x20 */ + __IO uint32_t K0RR; /*!< CRYP key right register 0, Address offset: 0x24 */ + __IO uint32_t K1LR; /*!< CRYP key left register 1, Address offset: 0x28 */ + __IO uint32_t K1RR; /*!< CRYP key right register 1, Address offset: 0x2C */ + __IO uint32_t K2LR; /*!< CRYP key left register 2, Address offset: 0x30 */ + __IO uint32_t K2RR; /*!< CRYP key right register 2, Address offset: 0x34 */ + __IO uint32_t K3LR; /*!< CRYP key left register 3, Address offset: 0x38 */ + __IO uint32_t K3RR; /*!< CRYP key right register 3, Address offset: 0x3C */ + __IO uint32_t IV0LR; /*!< CRYP initialization vector left-word register 0, Address offset: 0x40 */ + __IO uint32_t IV0RR; /*!< CRYP initialization vector right-word register 0, Address offset: 0x44 */ + __IO uint32_t IV1LR; /*!< CRYP initialization vector left-word register 1, Address offset: 0x48 */ + __IO uint32_t IV1RR; /*!< CRYP initialization vector right-word register 1, Address offset: 0x4C */ + __IO uint32_t CSGCMCCM0R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 0, Address offset: 0x50 */ + __IO uint32_t CSGCMCCM1R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 1, Address offset: 0x54 */ + __IO uint32_t CSGCMCCM2R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 2, Address offset: 0x58 */ + __IO uint32_t CSGCMCCM3R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 3, Address offset: 0x5C */ + __IO uint32_t CSGCMCCM4R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 4, Address offset: 0x60 */ + __IO uint32_t CSGCMCCM5R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 5, Address offset: 0x64 */ + __IO uint32_t CSGCMCCM6R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 6, Address offset: 0x68 */ + __IO uint32_t CSGCMCCM7R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 7, Address offset: 0x6C */ + __IO uint32_t CSGCM0R; /*!< CRYP GCM/GMAC context swap register 0, Address offset: 0x70 */ + __IO uint32_t CSGCM1R; /*!< CRYP GCM/GMAC context swap register 1, Address offset: 0x74 */ + __IO uint32_t CSGCM2R; /*!< CRYP GCM/GMAC context swap register 2, Address offset: 0x78 */ + __IO uint32_t CSGCM3R; /*!< CRYP GCM/GMAC context swap register 3, Address offset: 0x7C */ + __IO uint32_t CSGCM4R; /*!< CRYP GCM/GMAC context swap register 4, Address offset: 0x80 */ + __IO uint32_t CSGCM5R; /*!< CRYP GCM/GMAC context swap register 5, Address offset: 0x84 */ + __IO uint32_t CSGCM6R; /*!< CRYP GCM/GMAC context swap register 6, Address offset: 0x88 */ + __IO uint32_t CSGCM7R; /*!< CRYP GCM/GMAC context swap register 7, Address offset: 0x8C */ +} CRYP_TypeDef; + +/** + * @brief HASH + */ + +typedef struct +{ + __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ + __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ + __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ + __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ + __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ + __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ + uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ + __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ +} HASH_TypeDef; + +/** + * @brief HASH_DIGEST + */ + +typedef struct +{ + __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ +} HASH_DIGEST_TypeDef; + + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ + uint32_t RESERVED; + __IO uint32_t HTCR; /*!< RNG health test configuration register, Address offset: 0x10 */ +} RNG_TypeDef; + +/** + * @brief MDIOS + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t WRFR; + __IO uint32_t CWRFR; + __IO uint32_t RDFR; + __IO uint32_t CRDFR; + __IO uint32_t SR; + __IO uint32_t CLRFR; + uint32_t RESERVED[57]; + __IO uint32_t DINR0; + __IO uint32_t DINR1; + __IO uint32_t DINR2; + __IO uint32_t DINR3; + __IO uint32_t DINR4; + __IO uint32_t DINR5; + __IO uint32_t DINR6; + __IO uint32_t DINR7; + __IO uint32_t DINR8; + __IO uint32_t DINR9; + __IO uint32_t DINR10; + __IO uint32_t DINR11; + __IO uint32_t DINR12; + __IO uint32_t DINR13; + __IO uint32_t DINR14; + __IO uint32_t DINR15; + __IO uint32_t DINR16; + __IO uint32_t DINR17; + __IO uint32_t DINR18; + __IO uint32_t DINR19; + __IO uint32_t DINR20; + __IO uint32_t DINR21; + __IO uint32_t DINR22; + __IO uint32_t DINR23; + __IO uint32_t DINR24; + __IO uint32_t DINR25; + __IO uint32_t DINR26; + __IO uint32_t DINR27; + __IO uint32_t DINR28; + __IO uint32_t DINR29; + __IO uint32_t DINR30; + __IO uint32_t DINR31; + __IO uint32_t DOUTR0; + __IO uint32_t DOUTR1; + __IO uint32_t DOUTR2; + __IO uint32_t DOUTR3; + __IO uint32_t DOUTR4; + __IO uint32_t DOUTR5; + __IO uint32_t DOUTR6; + __IO uint32_t DOUTR7; + __IO uint32_t DOUTR8; + __IO uint32_t DOUTR9; + __IO uint32_t DOUTR10; + __IO uint32_t DOUTR11; + __IO uint32_t DOUTR12; + __IO uint32_t DOUTR13; + __IO uint32_t DOUTR14; + __IO uint32_t DOUTR15; + __IO uint32_t DOUTR16; + __IO uint32_t DOUTR17; + __IO uint32_t DOUTR18; + __IO uint32_t DOUTR19; + __IO uint32_t DOUTR20; + __IO uint32_t DOUTR21; + __IO uint32_t DOUTR22; + __IO uint32_t DOUTR23; + __IO uint32_t DOUTR24; + __IO uint32_t DOUTR25; + __IO uint32_t DOUTR26; + __IO uint32_t DOUTR27; + __IO uint32_t DOUTR28; + __IO uint32_t DOUTR29; + __IO uint32_t DOUTR30; + __IO uint32_t DOUTR31; +} MDIOS_TypeDef; + + +/** + * @brief USB_OTG_Core_Registers + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + __IO uint32_t GPWRDN; /*!< Power Down Register 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 60Ch */ + uint32_t Reserved43[39]; /*!< Reserved 058h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ + __IO uint32_t DCTL; /*!< dev Control Register 804h */ + __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved9; /*!< Reserved 824h */ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ + uint32_t Reserved40; /*!< dedicated EP mask 840h */ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ +} USB_OTG_DeviceTypeDef; + + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ +} USB_OTG_INEndpointTypeDef; + + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ +} USB_OTG_OUTEndpointTypeDef; + + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ + __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ + __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ + __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ + __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ + __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ + uint32_t Reserved[2]; /*!< Reserved */ +} USB_OTG_HostChannelTypeDef; +/** + * @} + */ + +/** + * @brief OCTO Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI Control register, Address offset: 0x000 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x004 */ + __IO uint32_t DCR1; /*!< OCTOSPI Device Configuration register 1, Address offset: 0x008 */ + __IO uint32_t DCR2; /*!< OCTOSPI Device Configuration register 2, Address offset: 0x00C */ + __IO uint32_t DCR3; /*!< OCTOSPI Device Configuration register 3, Address offset: 0x010 */ + __IO uint32_t DCR4; /*!< OCTOSPI Device Configuration register 4, Address offset: 0x014 */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x018-0x01C */ + __IO uint32_t SR; /*!< OCTOSPI Status register, Address offset: 0x020 */ + __IO uint32_t FCR; /*!< OCTOSPI Flag Clear register, Address offset: 0x024 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x028-0x03C */ + __IO uint32_t DLR; /*!< OCTOSPI Data Length register, Address offset: 0x040 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x044 */ + __IO uint32_t AR; /*!< OCTOSPI Address register, Address offset: 0x048 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x04C */ + __IO uint32_t DR; /*!< OCTOSPI Data register, Address offset: 0x050 */ + uint32_t RESERVED5[11]; /*!< Reserved, Address offset: 0x054-0x07C */ + __IO uint32_t PSMKR; /*!< OCTOSPI Polling Status Mask register, Address offset: 0x080 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x084 */ + __IO uint32_t PSMAR; /*!< OCTOSPI Polling Status Match register, Address offset: 0x088 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x08C */ + __IO uint32_t PIR; /*!< OCTOSPI Polling Interval register, Address offset: 0x090 */ + uint32_t RESERVED8[27]; /*!< Reserved, Address offset: 0x094-0x0FC */ + __IO uint32_t CCR; /*!< OCTOSPI Communication Configuration register, Address offset: 0x100 */ + uint32_t RESERVED9; /*!< Reserved, Address offset: 0x104 */ + __IO uint32_t TCR; /*!< OCTOSPI Timing Configuration register, Address offset: 0x108 */ + uint32_t RESERVED10; /*!< Reserved, Address offset: 0x10C */ + __IO uint32_t IR; /*!< OCTOSPI Instruction register, Address offset: 0x110 */ + uint32_t RESERVED11[3]; /*!< Reserved, Address offset: 0x114-0x11C */ + __IO uint32_t ABR; /*!< OCTOSPI Alternate Bytes register, Address offset: 0x120 */ + uint32_t RESERVED12[3]; /*!< Reserved, Address offset: 0x124-0x12C */ + __IO uint32_t LPTR; /*!< OCTOSPI Low Power Timeout register, Address offset: 0x130 */ + uint32_t RESERVED13[3]; /*!< Reserved, Address offset: 0x134-0x13C */ + __IO uint32_t WPCCR; /*!< OCTOSPI Wrap Communication Configuration register, Address offset: 0x140 */ + uint32_t RESERVED14; /*!< Reserved, Address offset: 0x144 */ + __IO uint32_t WPTCR; /*!< OCTOSPI Wrap Timing Configuration register, Address offset: 0x148 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x14C */ + __IO uint32_t WPIR; /*!< OCTOSPI Wrap Instruction register, Address offset: 0x150 */ + uint32_t RESERVED16[3]; /*!< Reserved, Address offset: 0x154-0x15C */ + __IO uint32_t WPABR; /*!< OCTOSPI Wrap Alternate Bytes register, Address offset: 0x160 */ + uint32_t RESERVED17[7]; /*!< Reserved, Address offset: 0x164-0x17C */ + __IO uint32_t WCCR; /*!< OCTOSPI Write Communication Configuration register, Address offset: 0x180 */ + uint32_t RESERVED18; /*!< Reserved, Address offset: 0x184 */ + __IO uint32_t WTCR; /*!< OCTOSPI Write Timing Configuration register, Address offset: 0x188 */ + uint32_t RESERVED19; /*!< Reserved, Address offset: 0x18C */ + __IO uint32_t WIR; /*!< OCTOSPI Write Instruction register, Address offset: 0x190 */ + uint32_t RESERVED20[3]; /*!< Reserved, Address offset: 0x194-0x19C */ + __IO uint32_t WABR; /*!< OCTOSPI Write Alternate Bytes register, Address offset: 0x1A0 */ + uint32_t RESERVED21[23]; /*!< Reserved, Address offset: 0x1A4-0x1FC */ + __IO uint32_t HLCR; /*!< OCTOSPI Hyperbus Latency Configuration register, Address offset: 0x200 */ + uint32_t RESERVED22[122]; /*!< Reserved, Address offset: 0x204-0x3EC */ + __IO uint32_t HWCFGR; /*!< OCTOSPI HW Configuration register, Address offset: 0x3F0 */ + __IO uint32_t VER; /*!< OCTOSPI Version register, Address offset: 0x3F4 */ + __IO uint32_t ID; /*!< OCTOSPI Identification register, Address offset: 0x3F8 */ + __IO uint32_t MID; /*!< OCTOPSI HW Magic ID register, Address offset: 0x3FC */ +} OCTOSPI_TypeDef; + +/** + * @} + */ +/** + * @brief OCTO Serial Peripheral Interface IO Manager + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI IO Manager Control register, Address offset: 0x00 */ + __IO uint32_t PCR[3]; /*!< OCTOSPI IO Manager Port[1:3] Configuration register, Address offset: 0x04-0x20 */ +} OCTOSPIM_TypeDef; + +/** + * @} + */ + +/** + * @brief OTFD register + */ +typedef struct +{ + __IO uint32_t REG_CONFIGR; + __IO uint32_t REG_START_ADDR; + __IO uint32_t REG_END_ADDR; + __IO uint32_t REG_NONCER0; + __IO uint32_t REG_NONCER1; + __IO uint32_t REG_KEYR0; + __IO uint32_t REG_KEYR1; + __IO uint32_t REG_KEYR2; + __IO uint32_t REG_KEYR3; +} OTFDEC_Region_TypeDef; + +typedef struct +{ + __IO uint32_t CR; + uint32_t RESERVED1[191]; + __IO uint32_t ISR; + __IO uint32_t ICR; + __IO uint32_t IER; + uint32_t RESERVED2[56]; + __IO uint32_t HWCFGR2; + __IO uint32_t HWCFGR1; + __IO uint32_t VERR; + __IO uint32_t IPIDR; + __IO uint32_t SIDR; +} OTFDEC_TypeDef; +/** + * @} + */ + +/** + * @brief Global Programmer View + */ + +typedef struct +{ + uint32_t RESERVED0[2036]; /*!< Reserved, Address offset: 0x00-0x1FCC */ + __IO uint32_t AXI_PERIPH_ID_4; /*!< AXI interconnect - peripheral ID4 register, Address offset: 0x1FD0 */ + uint32_t AXI_PERIPH_ID_5; /*!< Reserved, Address offset: 0x1FD4 */ + uint32_t AXI_PERIPH_ID_6; /*!< Reserved, Address offset: 0x1FD8 */ + uint32_t AXI_PERIPH_ID_7; /*!< Reserved, Address offset: 0x1FDC */ + __IO uint32_t AXI_PERIPH_ID_0; /*!< AXI interconnect - peripheral ID0 register, Address offset: 0x1FE0 */ + __IO uint32_t AXI_PERIPH_ID_1; /*!< AXI interconnect - peripheral ID1 register, Address offset: 0x1FE4 */ + __IO uint32_t AXI_PERIPH_ID_2; /*!< AXI interconnect - peripheral ID2 register, Address offset: 0x1FE8 */ + __IO uint32_t AXI_PERIPH_ID_3; /*!< AXI interconnect - peripheral ID3 register, Address offset: 0x1FEC */ + __IO uint32_t AXI_COMP_ID_0; /*!< AXI interconnect - component ID0 register, Address offset: 0x1FF0 */ + __IO uint32_t AXI_COMP_ID_1; /*!< AXI interconnect - component ID1 register, Address offset: 0x1FF4 */ + __IO uint32_t AXI_COMP_ID_2; /*!< AXI interconnect - component ID2 register, Address offset: 0x1FF8 */ + __IO uint32_t AXI_COMP_ID_3; /*!< AXI interconnect - component ID3 register, Address offset: 0x1FFC */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x2000-0x2004 */ + __IO uint32_t AXI_TARG1_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 1 bus matrix issuing functionality register, Address offset: 0x2008 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x200C-0x2020 */ + __IO uint32_t AXI_TARG1_FN_MOD2; /*!< AXI interconnect - TARG 1 bus matrix functionality 2 register, Address offset: 0x2024 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2028 */ + __IO uint32_t AXI_TARG1_FN_MOD_LB; /*!< AXI interconnect - TARG 1 long burst functionality modification register, Address offset: 0x202C */ + uint32_t RESERVED4[54]; /*!< Reserved, Address offset: 0x2030-0x2104 */ + __IO uint32_t AXI_TARG1_FN_MOD; /*!< AXI interconnect - TARG 1 issuing functionality modification register, Address offset: 0x2108 */ + uint32_t RESERVED5[959]; /*!< Reserved, Address offset: 0x210C-0x3004 */ + __IO uint32_t AXI_TARG2_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 2 bus matrix issuing functionality register, Address offset: 0x3008 */ + uint32_t RESERVED6[6]; /*!< Reserved, Address offset: 0x300C-0x3020 */ + __IO uint32_t AXI_TARG2_FN_MOD2; /*!< AXI interconnect - TARG 2 bus matrix functionality 2 register, Address offset: 0x3024 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x3028 */ + __IO uint32_t AXI_TARG2_FN_MOD_LB; /*!< AXI interconnect - TARG 2 long burst functionality modification register, Address offset: 0x302C */ + uint32_t RESERVED8[54]; /*!< Reserved, Address offset: 0x3030-0x3104 */ + __IO uint32_t AXI_TARG2_FN_MOD; /*!< AXI interconnect - TARG 2 issuing functionality modification register, Address offset: 0x3108 */ + uint32_t RESERVED9[959]; /*!< Reserved, Address offset: 0x310C-0x4004 */ + __IO uint32_t AXI_TARG3_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 3 bus matrix issuing functionality register, Address offset: 0x4008 */ + uint32_t RESERVED10[1023]; /*!< Reserved, Address offset: 0x400C-0x5004 */ + __IO uint32_t AXI_TARG4_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 4 bus matrix issuing functionality register, Address offset: 0x5008 */ + uint32_t RESERVED11[1023]; /*!< Reserved, Address offset: 0x500C-0x6004 */ + __IO uint32_t AXI_TARG5_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 5 bus matrix issuing functionality register, Address offset: 0x6008 */ + uint32_t RESERVED12[1023]; /*!< Reserved, Address offset: 0x600C-0x7004 */ + __IO uint32_t AXI_TARG6_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 6 bus matrix issuing functionality register, Address offset: 0x7008 */ + uint32_t RESERVED13[1023]; /*!< Reserved, Address offset: 0x700C-0x8004 */ + __IO uint32_t AXI_TARG7_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 7 bus matrix issuing functionality register, Address offset: 0x8008 */ + uint32_t RESERVED14[6]; /*!< Reserved, Address offset: 0x800C-0x8020 */ + __IO uint32_t AXI_TARG7_FN_MOD2; /*!< AXI interconnect - TARG 7 bus matrix functionality 2 register, Address offset: 0x8024 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x8028 */ + __IO uint32_t AXI_TARG7_FN_MOD_LB; /*!< AXI interconnect - TARG 7 long burst functionality modification register, Address offset: 0x802C */ + uint32_t RESERVED16[54]; /*!< Reserved, Address offset: 0x8030-0x8104 */ + __IO uint32_t AXI_TARG7_FN_MOD; /*!< AXI interconnect - TARG 7 issuing functionality modification register, Address offset: 0x8108 */ + uint32_t RESERVED17[959]; /*!< Reserved, Address offset: 0x810C-0x9004 */ + __IO uint32_t AXI_TARG8_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 8 bus matrix issuing functionality register, Address offset: 0x9008 */ + uint32_t RESERVED117[6]; /*!< Reserved, Address offset: 0x900C-0x9020 */ + __IO uint32_t AXI_TARG8_FN_MOD2; /*!< AXI interconnect - TARG 8 bus matrix functionality 2 register, Address offset: 0x9024 */ + uint32_t RESERVED118[56]; /*!< Reserved, Address offset: 0x9028-0x9104 */ + __IO uint32_t AXI_TARG8_FN_MOD; /*!< AXI interconnect - TARG 8 issuing functionality modification register, Address offset: 0x9108 */ + uint32_t RESERVED119[58310]; /*!< Reserved, Address offset: 0x910C-0x42020 */ + __IO uint32_t AXI_INI1_FN_MOD2; /*!< AXI interconnect - INI 1 functionality modification 2 register, Address offset: 0x42024 */ + __IO uint32_t AXI_INI1_FN_MOD_AHB; /*!< AXI interconnect - INI 1 AHB functionality modification register, Address offset: 0x42028 */ + uint32_t RESERVED18[53]; /*!< Reserved, Address offset: 0x4202C-0x420FC */ + __IO uint32_t AXI_INI1_READ_QOS; /*!< AXI interconnect - INI 1 read QoS register, Address offset: 0x42100 */ + __IO uint32_t AXI_INI1_WRITE_QOS; /*!< AXI interconnect - INI 1 write QoS register, Address offset: 0x42104 */ + __IO uint32_t AXI_INI1_FN_MOD; /*!< AXI interconnect - INI 1 issuing functionality modification register, Address offset: 0x42108 */ + uint32_t RESERVED19[1021]; /*!< Reserved, Address offset: 0x4210C-0x430FC */ + __IO uint32_t AXI_INI2_READ_QOS; /*!< AXI interconnect - INI 2 read QoS register, Address offset: 0x43100 */ + __IO uint32_t AXI_INI2_WRITE_QOS; /*!< AXI interconnect - INI 2 write QoS register, Address offset: 0x43104 */ + __IO uint32_t AXI_INI2_FN_MOD; /*!< AXI interconnect - INI 2 issuing functionality modification register, Address offset: 0x43108 */ + uint32_t RESERVED20[966]; /*!< Reserved, Address offset: 0x4310C-0x44020 */ + __IO uint32_t AXI_INI3_FN_MOD2; /*!< AXI interconnect - INI 3 functionality modification 2 register, Address offset: 0x44024 */ + __IO uint32_t AXI_INI3_FN_MOD_AHB; /*!< AXI interconnect - INI 3 AHB functionality modification register, Address offset: 0x44028 */ + uint32_t RESERVED21[53]; /*!< Reserved, Address offset: 0x4402C-0x440FC */ + __IO uint32_t AXI_INI3_READ_QOS; /*!< AXI interconnect - INI 3 read QoS register, Address offset: 0x44100 */ + __IO uint32_t AXI_INI3_WRITE_QOS; /*!< AXI interconnect - INI 3 write QoS register, Address offset: 0x44104 */ + __IO uint32_t AXI_INI3_FN_MOD; /*!< AXI interconnect - INI 3 issuing functionality modification register, Address offset: 0x44108 */ + uint32_t RESERVED22[1021]; /*!< Reserved, Address offset: 0x4410C-0x450FC */ + __IO uint32_t AXI_INI4_READ_QOS; /*!< AXI interconnect - INI 4 read QoS register, Address offset: 0x45100 */ + __IO uint32_t AXI_INI4_WRITE_QOS; /*!< AXI interconnect - INI 4 write QoS register, Address offset: 0x45104 */ + __IO uint32_t AXI_INI4_FN_MOD; /*!< AXI interconnect - INI 4 issuing functionality modification register, Address offset: 0x45108 */ + uint32_t RESERVED23[1021]; /*!< Reserved, Address offset: 0x4510C-0x460FC */ + __IO uint32_t AXI_INI5_READ_QOS; /*!< AXI interconnect - INI 5 read QoS register, Address offset: 0x46100 */ + __IO uint32_t AXI_INI5_WRITE_QOS; /*!< AXI interconnect - INI 5 write QoS register, Address offset: 0x46104 */ + __IO uint32_t AXI_INI5_FN_MOD; /*!< AXI interconnect - INI 5 issuing functionality modification register, Address offset: 0x46108 */ + uint32_t RESERVED24[1021]; /*!< Reserved, Address offset: 0x4610C-0x470FC */ + __IO uint32_t AXI_INI6_READ_QOS; /*!< AXI interconnect - INI 6 read QoS register, Address offset: 0x47100 */ + __IO uint32_t AXI_INI6_WRITE_QOS; /*!< AXI interconnect - INI 6 write QoS register, Address offset: 0x47104 */ + __IO uint32_t AXI_INI6_FN_MOD; /*!< AXI interconnect - INI 6 issuing functionality modification register, Address offset: 0x47108 */ + +} GPV_TypeDef; + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define D1_ITCMRAM_BASE (0x00000000UL) /*!< Base address of : 64KB RAM reserved for CPU execution/instruction accessible over ITCM */ +#define D1_ITCMICP_BASE (0x00100000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over ITCM */ +#define D1_DTCMRAM_BASE (0x20000000UL) /*!< Base address of : 128KB system data RAM accessible over DTCM */ +#define D1_AXIFLASH_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */ +#define D1_AXIICP_BASE (0x1FF00000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over AXI */ +#define D1_AXISRAM1_BASE (0x24000000UL) /*!< Base address of : (up to 128KB) system data RAM1 accessible over over AXI */ +#define D1_AXISRAM2_BASE (0x24020000UL) /*!< Base address of : (up to 192KB) system data RAM2 accessible over over AXI to be shared with ITCM (64K granularity) */ +#define D1_AXISRAM_BASE D1_AXISRAM1_BASE /*!< Base address of : (up to 320KB) system data RAM1/2 accessible over over AXI */ + +#define D2_AHBSRAM1_BASE (0x30000000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM2_BASE (0x30004000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM_BASE D2_AHBSRAM1_BASE /*!< Base address of : (up to 32KB) system data RAM1/2 accessible over over AXI->AHB Bridge */ + +#define D3_BKPSRAM_BASE (0x38800000UL) /*!< Base address of : Backup SRAM(4 KB) over AXI->AHB Bridge */ +#define D3_SRAM_BASE (0x38000000UL) /*!< Base address of : Backup SRAM(16 KB) over AXI->AHB Bridge */ + +#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */ +#define OCTOSPI1_BASE (0x90000000UL) /*!< Base address of : OCTOSPI1 memories accessible over AXI */ +#define OCTOSPI2_BASE (0x70000000UL) /*!< Base address of : OCTOSPI2 memories accessible over AXI */ + +#define FLASH_BANK1_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) Flash Bank1 accessible over AXI */ +#define FLASH_END (0x080FFFFFUL) /*!< FLASH end address */ + + +/* Legacy define */ +#define FLASH_BASE FLASH_BANK1_BASE + +/*!< Device electronic signature memory map */ +#define UID_BASE (0x1FF1E800UL) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE (0x1FF1E880UL) /*!< FLASH Size register base address */ + + +/*!< Peripheral memory map */ +#define D2_APB1PERIPH_BASE PERIPH_BASE +#define D2_APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define D2_AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define D2_AHB2PERIPH_BASE (PERIPH_BASE + 0x08020000UL) + +#define D1_APB1PERIPH_BASE (PERIPH_BASE + 0x10000000UL) +#define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000UL) + +#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL) +#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000UL) + +/*!< Legacy Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL) + + +/*!< D1_AHB1PERIPH peripherals */ + +#define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2D_BASE (D1_AHB1PERIPH_BASE + 0x1000UL) +#define FLASH_R_BASE (D1_AHB1PERIPH_BASE + 0x2000UL) +#define FMC_R_BASE (D1_AHB1PERIPH_BASE + 0x4000UL) +#define OCTOSPI1_R_BASE (D1_AHB1PERIPH_BASE + 0x5000UL) +#define DLYB_OCTOSPI1_BASE (D1_AHB1PERIPH_BASE + 0x6000UL) +#define SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x7000UL) +#define DLYB_SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x8000UL) +#define RAMECC1_BASE (D1_AHB1PERIPH_BASE + 0x9000UL) +#define OCTOSPI2_R_BASE (D1_AHB1PERIPH_BASE + 0xA000UL) +#define DLYB_OCTOSPI2_BASE (D1_AHB1PERIPH_BASE + 0xB000UL) +#define OCTOSPIM_BASE (D1_AHB1PERIPH_BASE + 0xB400UL) + +#define OTFDEC1_BASE (D1_AHB1PERIPH_BASE + 0xB800UL) +#define OTFDEC1_REGION1_BASE (OTFDEC1_BASE + 0x20UL) +#define OTFDEC1_REGION2_BASE (OTFDEC1_BASE + 0x50UL) +#define OTFDEC1_REGION3_BASE (OTFDEC1_BASE + 0x80UL) +#define OTFDEC1_REGION4_BASE (OTFDEC1_BASE + 0xB0UL) +#define OTFDEC2_BASE (D1_AHB1PERIPH_BASE + 0xBC00UL) +#define OTFDEC2_REGION1_BASE (OTFDEC2_BASE + 0x20UL) +#define OTFDEC2_REGION2_BASE (OTFDEC2_BASE + 0x50UL) +#define OTFDEC2_REGION3_BASE (OTFDEC2_BASE + 0x80UL) +#define OTFDEC2_REGION4_BASE (OTFDEC2_BASE + 0xB0UL) + +/*!< D2_AHB1PERIPH peripherals */ + +#define DMA1_BASE (D2_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2_BASE (D2_AHB1PERIPH_BASE + 0x0400UL) +#define DMAMUX1_BASE (D2_AHB1PERIPH_BASE + 0x0800UL) +#define ADC1_BASE (D2_AHB1PERIPH_BASE + 0x2000UL) +#define ADC2_BASE (D2_AHB1PERIPH_BASE + 0x2100UL) +#define ADC12_COMMON_BASE (D2_AHB1PERIPH_BASE + 0x2300UL) +#define ETH_BASE (D2_AHB1PERIPH_BASE + 0x8000UL) +#define ETH_MAC_BASE (ETH_BASE) + +/*!< USB registers base address */ +#define USB1_OTG_HS_PERIPH_BASE (0x40040000UL) +#define USB_OTG_GLOBAL_BASE (0x000UL) +#define USB_OTG_DEVICE_BASE (0x800UL) +#define USB_OTG_IN_ENDPOINT_BASE (0x900UL) +#define USB_OTG_OUT_ENDPOINT_BASE (0xB00UL) +#define USB_OTG_EP_REG_SIZE (0x20UL) +#define USB_OTG_HOST_BASE (0x400UL) +#define USB_OTG_HOST_PORT_BASE (0x440UL) +#define USB_OTG_HOST_CHANNEL_BASE (0x500UL) +#define USB_OTG_HOST_CHANNEL_SIZE (0x20UL) +#define USB_OTG_PCGCCTL_BASE (0xE00UL) +#define USB_OTG_FIFO_BASE (0x1000UL) +#define USB_OTG_FIFO_SIZE (0x1000UL) + +/*!< D2_AHB2PERIPH peripherals */ + +#define DCMI_BASE (D2_AHB2PERIPH_BASE + 0x0000UL) +#define PSSI_BASE (D2_AHB2PERIPH_BASE + 0x0400UL) +#define CRYP_BASE (D2_AHB2PERIPH_BASE + 0x1000UL) +#define HASH_BASE (D2_AHB2PERIPH_BASE + 0x1400UL) +#define HASH_DIGEST_BASE (D2_AHB2PERIPH_BASE + 0x1710UL) +#define RNG_BASE (D2_AHB2PERIPH_BASE + 0x1800UL) +#define SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2400UL) +#define DLYB_SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2800UL) +#define RAMECC2_BASE (D2_AHB2PERIPH_BASE + 0x3000UL) +#define FMAC_BASE (D2_AHB2PERIPH_BASE + 0x4000UL) +#define CORDIC_BASE (D2_AHB2PERIPH_BASE + 0x4400UL) + +/*!< D3_AHB1PERIPH peripherals */ +#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (D3_AHB1PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (D3_AHB1PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (D3_AHB1PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (D3_AHB1PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (D3_AHB1PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (D3_AHB1PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (D3_AHB1PERIPH_BASE + 0x1C00UL) +#define GPIOJ_BASE (D3_AHB1PERIPH_BASE + 0x2400UL) +#define GPIOK_BASE (D3_AHB1PERIPH_BASE + 0x2800UL) +#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) +#define PWR_BASE (D3_AHB1PERIPH_BASE + 0x4800UL) +#define CRC_BASE (D3_AHB1PERIPH_BASE + 0x4C00UL) +#define BDMA_BASE (D3_AHB1PERIPH_BASE + 0x5400UL) +#define DMAMUX2_BASE (D3_AHB1PERIPH_BASE + 0x5800UL) +#define ADC3_BASE (D3_AHB1PERIPH_BASE + 0x6000UL) +#define ADC3_COMMON_BASE (D3_AHB1PERIPH_BASE + 0x6300UL) +#define HSEM_BASE (D3_AHB1PERIPH_BASE + 0x6400UL) +#define RAMECC3_BASE (D3_AHB1PERIPH_BASE + 0x7000UL) + +/*!< D1_APB1PERIPH peripherals */ +#define LTDC_BASE (D1_APB1PERIPH_BASE + 0x1000UL) +#define LTDC_Layer1_BASE (LTDC_BASE + 0x84UL) +#define LTDC_Layer2_BASE (LTDC_BASE + 0x104UL) +#define WWDG1_BASE (D1_APB1PERIPH_BASE + 0x3000UL) + +/*!< D2_APB1PERIPH peripherals */ +#define TIM2_BASE (D2_APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (D2_APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (D2_APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (D2_APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (D2_APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (D2_APB1PERIPH_BASE + 0x1400UL) +#define TIM12_BASE (D2_APB1PERIPH_BASE + 0x1800UL) +#define TIM13_BASE (D2_APB1PERIPH_BASE + 0x1C00UL) +#define TIM14_BASE (D2_APB1PERIPH_BASE + 0x2000UL) +#define LPTIM1_BASE (D2_APB1PERIPH_BASE + 0x2400UL) + + +#define SPI2_BASE (D2_APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (D2_APB1PERIPH_BASE + 0x3C00UL) +#define SPDIFRX_BASE (D2_APB1PERIPH_BASE + 0x4000UL) +#define USART2_BASE (D2_APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (D2_APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (D2_APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (D2_APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (D2_APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (D2_APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (D2_APB1PERIPH_BASE + 0x5C00UL) +#define I2C5_BASE (D2_APB1PERIPH_BASE + 0x6400UL) +#define CEC_BASE (D2_APB1PERIPH_BASE + 0x6C00UL) +#define DAC1_BASE (D2_APB1PERIPH_BASE + 0x7400UL) +#define UART7_BASE (D2_APB1PERIPH_BASE + 0x7800UL) +#define UART8_BASE (D2_APB1PERIPH_BASE + 0x7C00UL) +#define CRS_BASE (D2_APB1PERIPH_BASE + 0x8400UL) +#define SWPMI1_BASE (D2_APB1PERIPH_BASE + 0x8800UL) +#define OPAMP_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP1_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP2_BASE (D2_APB1PERIPH_BASE + 0x9010UL) +#define MDIOS_BASE (D2_APB1PERIPH_BASE + 0x9400UL) +#define FDCAN1_BASE (D2_APB1PERIPH_BASE + 0xA000UL) +#define FDCAN2_BASE (D2_APB1PERIPH_BASE + 0xA400UL) +#define FDCAN_CCU_BASE (D2_APB1PERIPH_BASE + 0xA800UL) +#define SRAMCAN_BASE (D2_APB1PERIPH_BASE + 0xAC00UL) +#define FDCAN3_BASE (D2_APB1PERIPH_BASE + 0xD400UL) +#define TIM23_BASE (D2_APB1PERIPH_BASE + 0xE000UL) +#define TIM24_BASE (D2_APB1PERIPH_BASE + 0xE400UL) + +/*!< D2_APB2PERIPH peripherals */ + +#define TIM1_BASE (D2_APB2PERIPH_BASE + 0x0000UL) +#define TIM8_BASE (D2_APB2PERIPH_BASE + 0x0400UL) +#define USART1_BASE (D2_APB2PERIPH_BASE + 0x1000UL) +#define USART6_BASE (D2_APB2PERIPH_BASE + 0x1400UL) +#define UART9_BASE (D2_APB2PERIPH_BASE + 0x1800UL) +#define USART10_BASE (D2_APB2PERIPH_BASE + 0x1C00UL) +#define SPI1_BASE (D2_APB2PERIPH_BASE + 0x3000UL) +#define SPI4_BASE (D2_APB2PERIPH_BASE + 0x3400UL) +#define TIM15_BASE (D2_APB2PERIPH_BASE + 0x4000UL) +#define TIM16_BASE (D2_APB2PERIPH_BASE + 0x4400UL) +#define TIM17_BASE (D2_APB2PERIPH_BASE + 0x4800UL) +#define SPI5_BASE (D2_APB2PERIPH_BASE + 0x5000UL) +#define SAI1_BASE (D2_APB2PERIPH_BASE + 0x5800UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) +#define DFSDM1_BASE (D2_APB2PERIPH_BASE + 0x7800UL) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00UL) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20UL) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40UL) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60UL) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80UL) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0UL) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0UL) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0UL) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100UL) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180UL) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200UL) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280UL) + + +/*!< D3_APB1PERIPH peripherals */ +#define EXTI_BASE (D3_APB1PERIPH_BASE + 0x0000UL) +#define EXTI_D1_BASE (EXTI_BASE + 0x0080UL) +#define EXTI_D2_BASE (EXTI_BASE + 0x00C0UL) +#define SYSCFG_BASE (D3_APB1PERIPH_BASE + 0x0400UL) +#define LPUART1_BASE (D3_APB1PERIPH_BASE + 0x0C00UL) +#define SPI6_BASE (D3_APB1PERIPH_BASE + 0x1400UL) +#define I2C4_BASE (D3_APB1PERIPH_BASE + 0x1C00UL) +#define LPTIM2_BASE (D3_APB1PERIPH_BASE + 0x2400UL) +#define LPTIM3_BASE (D3_APB1PERIPH_BASE + 0x2800UL) +#define LPTIM4_BASE (D3_APB1PERIPH_BASE + 0x2C00UL) +#define LPTIM5_BASE (D3_APB1PERIPH_BASE + 0x3000UL) +#define COMP12_BASE (D3_APB1PERIPH_BASE + 0x3800UL) +#define COMP1_BASE (COMP12_BASE + 0x0CUL) +#define COMP2_BASE (COMP12_BASE + 0x10UL) +#define VREFBUF_BASE (D3_APB1PERIPH_BASE + 0x3C00UL) +#define RTC_BASE (D3_APB1PERIPH_BASE + 0x4000UL) +#define IWDG1_BASE (D3_APB1PERIPH_BASE + 0x4800UL) + + +#define SAI4_BASE (D3_APB1PERIPH_BASE + 0x5400UL) +#define SAI4_Block_A_BASE (SAI4_BASE + 0x004UL) +#define SAI4_Block_B_BASE (SAI4_BASE + 0x024UL) + +#define DTS_BASE (D3_APB1PERIPH_BASE + 0x6800UL) + + + +#define BDMA_Channel0_BASE (BDMA_BASE + 0x0008UL) +#define BDMA_Channel1_BASE (BDMA_BASE + 0x001CUL) +#define BDMA_Channel2_BASE (BDMA_BASE + 0x0030UL) +#define BDMA_Channel3_BASE (BDMA_BASE + 0x0044UL) +#define BDMA_Channel4_BASE (BDMA_BASE + 0x0058UL) +#define BDMA_Channel5_BASE (BDMA_BASE + 0x006CUL) +#define BDMA_Channel6_BASE (BDMA_BASE + 0x0080UL) +#define BDMA_Channel7_BASE (BDMA_BASE + 0x0094UL) + +#define DMAMUX2_Channel0_BASE (DMAMUX2_BASE) +#define DMAMUX2_Channel1_BASE (DMAMUX2_BASE + 0x0004UL) +#define DMAMUX2_Channel2_BASE (DMAMUX2_BASE + 0x0008UL) +#define DMAMUX2_Channel3_BASE (DMAMUX2_BASE + 0x000CUL) +#define DMAMUX2_Channel4_BASE (DMAMUX2_BASE + 0x0010UL) +#define DMAMUX2_Channel5_BASE (DMAMUX2_BASE + 0x0014UL) +#define DMAMUX2_Channel6_BASE (DMAMUX2_BASE + 0x0018UL) +#define DMAMUX2_Channel7_BASE (DMAMUX2_BASE + 0x001CUL) + +#define DMAMUX2_RequestGenerator0_BASE (DMAMUX2_BASE + 0x0100UL) +#define DMAMUX2_RequestGenerator1_BASE (DMAMUX2_BASE + 0x0104UL) +#define DMAMUX2_RequestGenerator2_BASE (DMAMUX2_BASE + 0x0108UL) +#define DMAMUX2_RequestGenerator3_BASE (DMAMUX2_BASE + 0x010CUL) +#define DMAMUX2_RequestGenerator4_BASE (DMAMUX2_BASE + 0x0110UL) +#define DMAMUX2_RequestGenerator5_BASE (DMAMUX2_BASE + 0x0114UL) +#define DMAMUX2_RequestGenerator6_BASE (DMAMUX2_BASE + 0x0118UL) +#define DMAMUX2_RequestGenerator7_BASE (DMAMUX2_BASE + 0x011CUL) + +#define DMAMUX2_ChannelStatus_BASE (DMAMUX2_BASE + 0x0080UL) +#define DMAMUX2_RequestGenStatus_BASE (DMAMUX2_BASE + 0x0140UL) + +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) + +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) + +#define DMAMUX1_Channel0_BASE (DMAMUX1_BASE) +#define DMAMUX1_Channel1_BASE (DMAMUX1_BASE + 0x0004UL) +#define DMAMUX1_Channel2_BASE (DMAMUX1_BASE + 0x0008UL) +#define DMAMUX1_Channel3_BASE (DMAMUX1_BASE + 0x000CUL) +#define DMAMUX1_Channel4_BASE (DMAMUX1_BASE + 0x0010UL) +#define DMAMUX1_Channel5_BASE (DMAMUX1_BASE + 0x0014UL) +#define DMAMUX1_Channel6_BASE (DMAMUX1_BASE + 0x0018UL) +#define DMAMUX1_Channel7_BASE (DMAMUX1_BASE + 0x001CUL) +#define DMAMUX1_Channel8_BASE (DMAMUX1_BASE + 0x0020UL) +#define DMAMUX1_Channel9_BASE (DMAMUX1_BASE + 0x0024UL) +#define DMAMUX1_Channel10_BASE (DMAMUX1_BASE + 0x0028UL) +#define DMAMUX1_Channel11_BASE (DMAMUX1_BASE + 0x002CUL) +#define DMAMUX1_Channel12_BASE (DMAMUX1_BASE + 0x0030UL) +#define DMAMUX1_Channel13_BASE (DMAMUX1_BASE + 0x0034UL) +#define DMAMUX1_Channel14_BASE (DMAMUX1_BASE + 0x0038UL) +#define DMAMUX1_Channel15_BASE (DMAMUX1_BASE + 0x003CUL) + +#define DMAMUX1_RequestGenerator0_BASE (DMAMUX1_BASE + 0x0100UL) +#define DMAMUX1_RequestGenerator1_BASE (DMAMUX1_BASE + 0x0104UL) +#define DMAMUX1_RequestGenerator2_BASE (DMAMUX1_BASE + 0x0108UL) +#define DMAMUX1_RequestGenerator3_BASE (DMAMUX1_BASE + 0x010CUL) +#define DMAMUX1_RequestGenerator4_BASE (DMAMUX1_BASE + 0x0110UL) +#define DMAMUX1_RequestGenerator5_BASE (DMAMUX1_BASE + 0x0114UL) +#define DMAMUX1_RequestGenerator6_BASE (DMAMUX1_BASE + 0x0118UL) +#define DMAMUX1_RequestGenerator7_BASE (DMAMUX1_BASE + 0x011CUL) + +#define DMAMUX1_ChannelStatus_BASE (DMAMUX1_BASE + 0x0080UL) +#define DMAMUX1_RequestGenStatus_BASE (DMAMUX1_BASE + 0x0140UL) + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) +#define FMC_Bank2_R_BASE (FMC_R_BASE + 0x0060UL) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) +#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE (0x5C001000UL) + +#define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040UL) +#define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080UL) +#define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0UL) +#define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100UL) +#define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140UL) +#define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180UL) +#define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0UL) +#define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200UL) +#define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240UL) +#define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280UL) +#define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0UL) +#define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300UL) +#define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340UL) +#define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380UL) +#define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0UL) +#define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400UL) + +#define RAMECC1_Monitor1_BASE (RAMECC1_BASE + 0x20UL) +#define RAMECC1_Monitor2_BASE (RAMECC1_BASE + 0x40UL) +#define RAMECC1_Monitor3_BASE (RAMECC1_BASE + 0x60UL) +#define RAMECC1_Monitor4_BASE (RAMECC1_BASE + 0x80UL) +#define RAMECC1_Monitor5_BASE (RAMECC1_BASE + 0xA0UL) +#define RAMECC1_Monitor6_BASE (RAMECC1_BASE + 0xC0UL) + +#define RAMECC2_Monitor1_BASE (RAMECC2_BASE + 0x20UL) +#define RAMECC2_Monitor2_BASE (RAMECC2_BASE + 0x40UL) +#define RAMECC2_Monitor3_BASE (RAMECC2_BASE + 0x60UL) + +#define RAMECC3_Monitor1_BASE (RAMECC3_BASE + 0x20UL) +#define RAMECC3_Monitor2_BASE (RAMECC3_BASE + 0x40UL) + + + +#define GPV_BASE (PERIPH_BASE + 0x11000000UL) /*!< GPV_BASE (PERIPH_BASE + 0x11000000UL) */ + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG1 ((WWDG_TypeDef *) WWDG1_BASE) + + +#define IWDG1 ((IWDG_TypeDef *) IWDG1_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define SPI6 ((SPI_TypeDef *) SPI6_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define USART10 ((USART_TypeDef *) USART10_BASE) +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define UART9 ((USART_TypeDef *) UART9_BASE) +#define CRS ((CRS_TypeDef *) CRS_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define I2C4 ((I2C_TypeDef *) I2C4_BASE) +#define I2C5 ((I2C_TypeDef *) I2C5_BASE) +#define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) +#define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE) +#define FDCAN_CCU ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE) +#define FDCAN3 ((FDCAN_GlobalTypeDef *) FDCAN3_BASE) +#define TIM23 ((TIM_TypeDef *) TIM23_BASE) +#define TIM24 ((TIM_TypeDef *) TIM24_BASE) +#define CEC ((CEC_TypeDef *) CEC_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) +#define LPTIM3 ((LPTIM_TypeDef *) LPTIM3_BASE) +#define DTS ((DTS_TypeDef *) DTS_BASE) +#define LPTIM4 ((LPTIM_TypeDef *) LPTIM4_BASE) +#define LPTIM5 ((LPTIM_TypeDef *) LPTIM5_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define COMP12 ((COMPOPT_TypeDef *) COMP12_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) + + +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define EXTI_D1 ((EXTI_Core_TypeDef *) EXTI_D1_BASE) +#define EXTI_D2 ((EXTI_Core_TypeDef *) EXTI_D2_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI4 ((SAI_TypeDef *) SAI4_BASE) +#define SAI4_Block_A ((SAI_Block_TypeDef *)SAI4_Block_A_BASE) +#define SAI4_Block_B ((SAI_Block_TypeDef *)SAI4_Block_B_BASE) + +#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +#define DMA2D ((DMA2D_TypeDef *) DMA2D_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define PSSI ((PSSI_TypeDef *) PSSI_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE) +#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE) + +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC3_COMMON ((ADC_Common_TypeDef *) ADC3_COMMON_BASE) +#define ADC12_COMMON ((ADC_Common_TypeDef *) ADC12_COMMON_BASE) + +#define CRYP ((CRYP_TypeDef *) CRYP_BASE) +#define HASH ((HASH_TypeDef *) HASH_BASE) +#define HASH_DIGEST ((HASH_DIGEST_TypeDef *) HASH_DIGEST_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define SDMMC2 ((SDMMC_TypeDef *) SDMMC2_BASE) +#define DLYB_SDMMC2 ((DLYB_TypeDef *) DLYB_SDMMC2_BASE) +#define FMAC ((FMAC_TypeDef *) FMAC_BASE) +#define CORDIC ((CORDIC_TypeDef *) CORDIC_BASE) + +#define BDMA ((BDMA_TypeDef *) BDMA_BASE) +#define BDMA_Channel0 ((BDMA_Channel_TypeDef *) BDMA_Channel0_BASE) +#define BDMA_Channel1 ((BDMA_Channel_TypeDef *) BDMA_Channel1_BASE) +#define BDMA_Channel2 ((BDMA_Channel_TypeDef *) BDMA_Channel2_BASE) +#define BDMA_Channel3 ((BDMA_Channel_TypeDef *) BDMA_Channel3_BASE) +#define BDMA_Channel4 ((BDMA_Channel_TypeDef *) BDMA_Channel4_BASE) +#define BDMA_Channel5 ((BDMA_Channel_TypeDef *) BDMA_Channel5_BASE) +#define BDMA_Channel6 ((BDMA_Channel_TypeDef *) BDMA_Channel6_BASE) +#define BDMA_Channel7 ((BDMA_Channel_TypeDef *) BDMA_Channel7_BASE) + +#define RAMECC1 ((RAMECC_TypeDef *)RAMECC1_BASE) +#define RAMECC1_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor1_BASE) +#define RAMECC1_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor2_BASE) +#define RAMECC1_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor3_BASE) +#define RAMECC1_Monitor4 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor4_BASE) +#define RAMECC1_Monitor5 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor5_BASE) +#define RAMECC1_Monitor6 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor6_BASE) + +#define RAMECC2 ((RAMECC_TypeDef *)RAMECC2_BASE) +#define RAMECC2_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor1_BASE) +#define RAMECC2_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor2_BASE) +#define RAMECC2_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor3_BASE) + +#define RAMECC3 ((RAMECC_TypeDef *)RAMECC3_BASE) +#define RAMECC3_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor1_BASE) +#define RAMECC3_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor2_BASE) + +#define DMAMUX2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_BASE) +#define DMAMUX2_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel0_BASE) +#define DMAMUX2_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel1_BASE) +#define DMAMUX2_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel2_BASE) +#define DMAMUX2_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel3_BASE) +#define DMAMUX2_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel4_BASE) +#define DMAMUX2_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel5_BASE) +#define DMAMUX2_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel6_BASE) +#define DMAMUX2_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel7_BASE) + + +#define DMAMUX2_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator0_BASE) +#define DMAMUX2_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator1_BASE) +#define DMAMUX2_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator2_BASE) +#define DMAMUX2_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator3_BASE) +#define DMAMUX2_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator4_BASE) +#define DMAMUX2_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator5_BASE) +#define DMAMUX2_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator6_BASE) +#define DMAMUX2_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator7_BASE) + +#define DMAMUX2_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX2_ChannelStatus_BASE) +#define DMAMUX2_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX2_RequestGenStatus_BASE) + +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) + +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) + + +#define DMAMUX1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_BASE) +#define DMAMUX1_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel0_BASE) +#define DMAMUX1_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel1_BASE) +#define DMAMUX1_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel2_BASE) +#define DMAMUX1_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel3_BASE) +#define DMAMUX1_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel4_BASE) +#define DMAMUX1_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel5_BASE) +#define DMAMUX1_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel6_BASE) +#define DMAMUX1_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel7_BASE) +#define DMAMUX1_Channel8 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel8_BASE) +#define DMAMUX1_Channel9 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel9_BASE) +#define DMAMUX1_Channel10 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel10_BASE) +#define DMAMUX1_Channel11 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel11_BASE) +#define DMAMUX1_Channel12 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel12_BASE) +#define DMAMUX1_Channel13 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel13_BASE) +#define DMAMUX1_Channel14 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel14_BASE) +#define DMAMUX1_Channel15 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel15_BASE) + +#define DMAMUX1_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator0_BASE) +#define DMAMUX1_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator1_BASE) +#define DMAMUX1_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator2_BASE) +#define DMAMUX1_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator3_BASE) +#define DMAMUX1_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator4_BASE) +#define DMAMUX1_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator5_BASE) +#define DMAMUX1_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator6_BASE) +#define DMAMUX1_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator7_BASE) + +#define DMAMUX1_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX1_ChannelStatus_BASE) +#define DMAMUX1_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX1_RequestGenStatus_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank2_R ((FMC_Bank2_TypeDef *) FMC_Bank2_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) +#define FMC_Bank5_6_R ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE) + +#define OCTOSPI1 ((OCTOSPI_TypeDef *) OCTOSPI1_R_BASE) +#define DLYB_OCTOSPI1 ((DLYB_TypeDef *) DLYB_OCTOSPI1_BASE) +#define OCTOSPI2 ((OCTOSPI_TypeDef *) OCTOSPI2_R_BASE) +#define DLYB_OCTOSPI2 ((DLYB_TypeDef *) DLYB_OCTOSPI2_BASE) +#define OCTOSPIM ((OCTOSPIM_TypeDef *) OCTOSPIM_BASE) + +#define OTFDEC1 ((OTFDEC_TypeDef *) OTFDEC1_BASE) +#define OTFDEC1_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION1_BASE) +#define OTFDEC1_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION2_BASE) +#define OTFDEC1_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION3_BASE) +#define OTFDEC1_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION4_BASE) + +#define OTFDEC2 ((OTFDEC_TypeDef *) OTFDEC2_BASE) +#define OTFDEC2_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION1_BASE) +#define OTFDEC2_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION2_BASE) +#define OTFDEC2_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION3_BASE) +#define OTFDEC2_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION4_BASE) + +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define DLYB_SDMMC1 ((DLYB_TypeDef *) DLYB_SDMMC1_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define HSEM ((HSEM_TypeDef *) HSEM_BASE) +#define HSEM_COMMON ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x100UL)) + +#define LTDC ((LTDC_TypeDef *)LTDC_BASE) +#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE) +#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE) + +#define MDIOS ((MDIOS_TypeDef *) MDIOS_BASE) + +#define ETH ((ETH_TypeDef *)ETH_BASE) +#define MDMA ((MDMA_TypeDef *)MDMA_BASE) +#define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE) +#define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE) +#define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE) +#define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE) +#define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE) +#define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE) +#define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE) +#define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE) +#define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE) +#define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE) +#define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE) +#define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE) +#define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE) +#define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE) +#define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE) +#define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE) + + +#define USB1_OTG_HS ((USB_OTG_GlobalTypeDef *) USB1_OTG_HS_PERIPH_BASE) + +/* Legacy defines */ +#define USB_OTG_HS USB1_OTG_HS +#define USB_OTG_HS_PERIPH_BASE USB1_OTG_HS_PERIPH_BASE + +#define GPV ((GPV_TypeDef *) GPV_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ +/******************************* ADC VERSION ********************************/ +#define ADC_VER_V5_V90 +/******************** Bit definition for ADC_ISR register ********************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC Ready (ADRDY) flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC End of Sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC End of Regular Conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC End of Regular sequence of Conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC End of Injected Conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC End of Injected sequence of Conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC Analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC Analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC Analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC Injected Context Queue Overflow flag */ +#define ADC_ISR_LDORDY_Pos (12U) +#define ADC_ISR_LDORDY_Msk (0x1UL << ADC_ISR_LDORDY_Pos) /*!< 0x00001000 */ +#define ADC_ISR_LDORDY ADC_ISR_LDORDY_Msk /*!< ADC LDO Ready (LDORDY) flag */ + +/******************** Bit definition for ADC_IER register ********************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC Ready (ADRDY) interrupt source */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC End of Sampling interrupt source */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC End of Regular Conversion interrupt source */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC End of Regular sequence of Conversions interrupt source */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC overrun interrupt source */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC End of Injected Conversion interrupt source */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC End of Injected sequence of Conversions interrupt source */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC Analog watchdog 1 interrupt source */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC Analog watchdog 2 interrupt source */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC Analog watchdog 3 interrupt source */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC Injected Context Queue Overflow interrupt source */ + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC Enable control */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC Disable command */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC Start of Regular conversion */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC Start of injected conversion */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC Stop of Regular conversion */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC Stop of injected conversion */ +#define ADC_CR_BOOST_Pos (8U) +#define ADC_CR_BOOST_Msk (0x3UL << ADC_CR_BOOST_Pos) /*!< 0x00000300 */ +#define ADC_CR_BOOST ADC_CR_BOOST_Msk /*!< ADC Boost Mode configuration */ +#define ADC_CR_BOOST_0 (0x1UL << ADC_CR_BOOST_Pos) /*!< 0x00000100 */ +#define ADC_CR_BOOST_1 (0x2UL << ADC_CR_BOOST_Pos) /*!< 0x00000200 */ +#define ADC_CR_ADCALLIN_Pos (16U) +#define ADC_CR_ADCALLIN_Msk (0x1UL << ADC_CR_ADCALLIN_Pos) /*!< 0x00010000 */ +#define ADC_CR_ADCALLIN ADC_CR_ADCALLIN_Msk /*!< ADC Linearity calibration */ +#define ADC_CR_LINCALRDYW1_Pos (22U) +#define ADC_CR_LINCALRDYW1_Msk (0x1UL << ADC_CR_LINCALRDYW1_Pos) /*!< 0x00400000 */ +#define ADC_CR_LINCALRDYW1 ADC_CR_LINCALRDYW1_Msk /*!< ADC Linearity calibration ready Word 1 */ +#define ADC_CR_LINCALRDYW2_Pos (23U) +#define ADC_CR_LINCALRDYW2_Msk (0x1UL << ADC_CR_LINCALRDYW2_Pos) /*!< 0x00800000 */ +#define ADC_CR_LINCALRDYW2 ADC_CR_LINCALRDYW2_Msk /*!< ADC Linearity calibration ready Word 2 */ +#define ADC_CR_LINCALRDYW3_Pos (24U) +#define ADC_CR_LINCALRDYW3_Msk (0x1UL << ADC_CR_LINCALRDYW3_Pos) /*!< 0x01000000 */ +#define ADC_CR_LINCALRDYW3 ADC_CR_LINCALRDYW3_Msk /*!< ADC Linearity calibration ready Word 3 */ +#define ADC_CR_LINCALRDYW4_Pos (25U) +#define ADC_CR_LINCALRDYW4_Msk (0x1UL << ADC_CR_LINCALRDYW4_Pos) /*!< 0x02000000 */ +#define ADC_CR_LINCALRDYW4 ADC_CR_LINCALRDYW4_Msk /*!< ADC Linearity calibration ready Word 4 */ +#define ADC_CR_LINCALRDYW5_Pos (26U) +#define ADC_CR_LINCALRDYW5_Msk (0x1UL << ADC_CR_LINCALRDYW5_Pos) /*!< 0x04000000 */ +#define ADC_CR_LINCALRDYW5 ADC_CR_LINCALRDYW5_Msk /*!< ADC Linearity calibration ready Word 5 */ +#define ADC_CR_LINCALRDYW6_Pos (27U) +#define ADC_CR_LINCALRDYW6_Msk (0x1UL << ADC_CR_LINCALRDYW6_Pos) /*!< 0x08000000 */ +#define ADC_CR_LINCALRDYW6 ADC_CR_LINCALRDYW6_Msk /*!< ADC Linearity calibration ready Word 6 */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC Voltage regulator Enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC Deep power down Enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC Differential Mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC Calibration */ + +/******************** Bit definition for ADC_CFGR register ********************/ +#define ADC_CFGR_DMNGT_Pos (0U) +#define ADC_CFGR_DMNGT_Msk (0x3UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000003 */ +#define ADC_CFGR_DMNGT ADC_CFGR_DMNGT_Msk /*!< ADC Data Management configuration */ +#define ADC_CFGR_DMNGT_0 (0x1UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMNGT_1 (0x2UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000002 */ + +#define ADC_CFGR_RES_Pos (2U) +#define ADC_CFGR_RES_Msk (0x7UL << ADC_CFGR_RES_Pos) /*!< 0x0000001C */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC Data resolution */ +#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000004 */ +#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_2 (0x4UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_EXTSEL_Pos (5U) +#define ADC_CFGR_EXTSEL_Msk (0x1FUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003E0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC External trigger selection for regular group */ +#define ADC_CFGR_EXTSEL_0 (0x01UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_EXTSEL_1 (0x02UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_2 (0x04UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_3 (0x08UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_4 (0x10UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC External trigger enable and polarity selection for regular channels */ +#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC overrun mode */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC Single/continuous conversion mode for regular conversion */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC Delayed conversion mode */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC Discontinuous mode for regular channels */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC Discontinuous mode channel count */ +#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC Discontinuous mode on injected channels */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC JSQR Queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< Enable the watchdog 1 on a single channel or on all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC Analog watchdog 1 enable on regular Channels */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC Analog watchdog 1 enable on injected Channels */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC Automatic injected group conversion */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC Analog watchdog 1 Channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC Injected queue disable */ + +#define ADC3_CFGR_DMAEN_Pos (0U) +#define ADC3_CFGR_DMAEN_Msk (0x1UL << ADC3_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC3_CFGR_DMAEN ADC3_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC3_CFGR_DMACFG_Pos (1U) +#define ADC3_CFGR_DMACFG_Msk (0x1UL << ADC3_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC3_CFGR_DMACFG ADC3_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC3_CFGR_RES_Pos (3U) +#define ADC3_CFGR_RES_Msk (0x3UL << ADC3_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC3_CFGR_RES ADC3_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC3_CFGR_RES_0 (0x1UL << ADC3_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR_RES_1 (0x2UL << ADC3_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR_ALIGN_Pos (15U) +#define ADC3_CFGR_ALIGN_Msk (0x1UL << ADC3_CFGR_ALIGN_Pos) /*!< 0x00008000 */ +#define ADC3_CFGR_ALIGN ADC3_CFGR_ALIGN_Msk /*!< ADC data alignment */ +/******************** Bit definition for ADC_CFGR2 register ********************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC Regular group oversampler enable */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC Injected group oversampler enable */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC Regular Oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC Triggered regular Oversampling */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC Regular oversampling mode */ + +#define ADC_CFGR2_RSHIFT1_Pos (11U) +#define ADC_CFGR2_RSHIFT1_Msk (0x1UL << ADC_CFGR2_RSHIFT1_Pos) /*!< 0x00000800 */ +#define ADC_CFGR2_RSHIFT1 ADC_CFGR2_RSHIFT1_Msk /*!< ADC Right-shift data after Offset 1 correction */ +#define ADC_CFGR2_RSHIFT2_Pos (12U) +#define ADC_CFGR2_RSHIFT2_Msk (0x1UL << ADC_CFGR2_RSHIFT2_Pos) /*!< 0x00001000 */ +#define ADC_CFGR2_RSHIFT2 ADC_CFGR2_RSHIFT2_Msk /*!< ADC Right-shift data after Offset 2 correction */ +#define ADC_CFGR2_RSHIFT3_Pos (13U) +#define ADC_CFGR2_RSHIFT3_Msk (0x1UL << ADC_CFGR2_RSHIFT3_Pos) /*!< 0x00002000 */ +#define ADC_CFGR2_RSHIFT3 ADC_CFGR2_RSHIFT3_Msk /*!< ADC Right-shift data after Offset 3 correction */ +#define ADC_CFGR2_RSHIFT4_Pos (14U) +#define ADC_CFGR2_RSHIFT4_Msk (0x1UL << ADC_CFGR2_RSHIFT4_Pos) /*!< 0x00004000 */ +#define ADC_CFGR2_RSHIFT4 ADC_CFGR2_RSHIFT4_Msk /*!< ADC Right-shift data after Offset 4 correction */ + +#define ADC_CFGR2_OVSR_Pos (16U) +#define ADC_CFGR2_OVSR_Msk (0x3FFUL << ADC_CFGR2_OVSR_Pos) /*!< 0x03FF0000 */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling Ratio */ +#define ADC_CFGR2_OVSR_0 (0x001UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00010000 */ +#define ADC_CFGR2_OVSR_1 (0x002UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00020000 */ +#define ADC_CFGR2_OVSR_2 (0x004UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00040000 */ +#define ADC_CFGR2_OVSR_3 (0x008UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00080000 */ +#define ADC_CFGR2_OVSR_4 (0x010UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00100000 */ +#define ADC_CFGR2_OVSR_5 (0x020UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00200000 */ +#define ADC_CFGR2_OVSR_6 (0x040UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00400000 */ +#define ADC_CFGR2_OVSR_7 (0x080UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00800000 */ +#define ADC_CFGR2_OVSR_8 (0x100UL << ADC_CFGR2_OVSR_Pos) /*!< 0x01000000 */ +#define ADC_CFGR2_OVSR_9 (0x200UL << ADC_CFGR2_OVSR_Pos) /*!< 0x02000000 */ + +#define ADC_CFGR2_LSHIFT_Pos (28U) +#define ADC_CFGR2_LSHIFT_Msk (0xFUL << ADC_CFGR2_LSHIFT_Pos) /*!< 0xF0000000 */ +#define ADC_CFGR2_LSHIFT ADC_CFGR2_LSHIFT_Msk /*!< ADC Left shift factor */ +#define ADC_CFGR2_LSHIFT_0 (0x1UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x10000000 */ +#define ADC_CFGR2_LSHIFT_1 (0x2UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x20000000 */ +#define ADC_CFGR2_LSHIFT_2 (0x4UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x40000000 */ +#define ADC_CFGR2_LSHIFT_3 (0x8UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x80000000 */ + +#define ADC3_CFGR2_OVSR_Pos (2U) +#define ADC3_CFGR2_OVSR_Msk (0x7UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC3_CFGR2_OVSR ADC3_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC3_CFGR2_OVSR_0 (0x1UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC3_CFGR2_OVSR_1 (0x2UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR2_OVSR_2 (0x4UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR2_SWTRIG_Pos (25U) +#define ADC3_CFGR2_SWTRIG_Msk (0x1UL << ADC3_CFGR2_SWTRIG_Pos) /*!< 0x02000000 */ +#define ADC3_CFGR2_SWTRIG ADC3_CFGR2_SWTRIG_Msk /*!< ADC Software Trigger Bit for Sample time control trigger mode */ +#define ADC3_CFGR2_BULB_Pos (26U) +#define ADC3_CFGR2_BULB_Msk (0x1UL << ADC3_CFGR2_BULB_Pos) /*!< 0x04000000 */ +#define ADC3_CFGR2_BULB ADC3_CFGR2_BULB_Msk /*!< ADC Bulb sampling mode */ +#define ADC3_CFGR2_SMPTRIG_Pos (27U) +#define ADC3_CFGR2_SMPTRIG_Msk (0x1UL << ADC3_CFGR2_SMPTRIG_Pos) /*!< 0x08000000 */ +#define ADC3_CFGR2_SMPTRIG ADC3_CFGR2_SMPTRIG_Msk /*!< ADC Sample Time Control Trigger mode */ +/******************** Bit definition for ADC_SMPR1 register ********************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC Channel 0 Sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC Channel 1 Sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC Channel 2 Sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC Channel 3 Sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC Channel 4 Sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC Channel 5 Sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC Channel 6 Sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC Channel 7 Sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC Channel 8 Sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC Channel 9 Sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_SMPR2 register ********************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC Channel 10 Sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC Channel 11 Sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC Channel 12 Sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC Channel 13 Sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC Channel 14 Sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC Channel 15 Sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC Channel 16 Sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC Channel 17 Sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC Channel 18 Sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR2_SMP19_Pos (27U) +#define ADC_SMPR2_SMP19_Msk (0x7UL << ADC_SMPR2_SMP19_Pos) /*!< 0x38000000 */ +#define ADC_SMPR2_SMP19 ADC_SMPR2_SMP19_Msk /*!< ADC Channel 19 Sampling time selection */ +#define ADC_SMPR2_SMP19_0 (0x1UL << ADC_SMPR2_SMP19_Pos) /*!< 0x08000000 */ +#define ADC_SMPR2_SMP19_1 (0x2UL << ADC_SMPR2_SMP19_Pos) /*!< 0x10000000 */ +#define ADC_SMPR2_SMP19_2 (0x4UL << ADC_SMPR2_SMP19_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_PCSEL register ********************/ +#define ADC_PCSEL_PCSEL_Pos (0U) +#define ADC_PCSEL_PCSEL_Msk (0xFFFFFUL << ADC_PCSEL_PCSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_PCSEL_PCSEL ADC_PCSEL_PCSEL_Msk /*!< ADC pre channel selection */ +#define ADC_PCSEL_PCSEL_0 (0x00001UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000001 */ +#define ADC_PCSEL_PCSEL_1 (0x00002UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000002 */ +#define ADC_PCSEL_PCSEL_2 (0x00004UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000004 */ +#define ADC_PCSEL_PCSEL_3 (0x00008UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000008 */ +#define ADC_PCSEL_PCSEL_4 (0x00010UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000010 */ +#define ADC_PCSEL_PCSEL_5 (0x00020UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000020 */ +#define ADC_PCSEL_PCSEL_6 (0x00040UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000040 */ +#define ADC_PCSEL_PCSEL_7 (0x00080UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000080 */ +#define ADC_PCSEL_PCSEL_8 (0x00100UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000100 */ +#define ADC_PCSEL_PCSEL_9 (0x00200UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000200 */ +#define ADC_PCSEL_PCSEL_10 (0x00400UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000400 */ +#define ADC_PCSEL_PCSEL_11 (0x00800UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000800 */ +#define ADC_PCSEL_PCSEL_12 (0x01000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00001000 */ +#define ADC_PCSEL_PCSEL_13 (0x02000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00002000 */ +#define ADC_PCSEL_PCSEL_14 (0x04000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00004000 */ +#define ADC_PCSEL_PCSEL_15 (0x08000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00008000 */ +#define ADC_PCSEL_PCSEL_16 (0x10000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00010000 */ +#define ADC_PCSEL_PCSEL_17 (0x20000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00020000 */ +#define ADC_PCSEL_PCSEL_18 (0x40000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00040000 */ +#define ADC_PCSEL_PCSEL_19 (0x80000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00080000 */ + +/***************** Bit definition for ADC_LTR1, 2, 3 registers *****************/ +#define ADC_LTR_LT_Pos (0U) +#define ADC_LTR_LT_Msk (0x3FFFFFFUL << ADC_LTR_LT_Pos) /*!< 0x03FFFFFF */ +#define ADC_LTR_LT ADC_LTR_LT_Msk /*!< ADC Analog watchdog 1, 2 and 3 lower threshold */ + +/***************** Bit definition for ADC_HTR1, 2, 3 registers ****************/ +#define ADC_HTR_HT_Pos (0U) +#define ADC_HTR_HT_Msk (0x3FFFFFFUL << ADC_HTR_HT_Pos) /*!< 0x03FFFFFF */ +#define ADC_HTR_HT ADC_HTR_HT_Msk /*!< ADC Analog watchdog 1,2 and 3 higher threshold */ + +/******************** Bit definition for ADC3_TR1 register *******************/ +#define ADC3_TR1_LT1_Pos (0U) +#define ADC3_TR1_LT1_Msk (0xFFFUL << ADC3_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC3_TR1_LT1 ADC3_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ + +#define ADC3_TR1_AWDFILT_Pos (12U) +#define ADC3_TR1_AWDFILT_Msk (0x7UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00007000 */ +#define ADC3_TR1_AWDFILT ADC3_TR1_AWDFILT_Msk /*!< ADC analog watchdog filtering parameter */ +#define ADC3_TR1_AWDFILT_0 (0x1UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00001000 */ +#define ADC3_TR1_AWDFILT_1 (0x2UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00002000 */ +#define ADC3_TR1_AWDFILT_2 (0x4UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00004000 */ + +#define ADC3_TR1_HT1_Pos (16U) +#define ADC3_TR1_HT1_Msk (0xFFFUL << ADC3_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC3_TR1_HT1 ADC3_TR1_HT1_Msk /*!< ADC analog watchdog 1 threshold high */ + +/******************** Bit definition for ADC3_TR2 register *******************/ +#define ADC3_TR2_LT2_Pos (0U) +#define ADC3_TR2_LT2_Msk (0xFFUL << ADC3_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC3_TR2_LT2 ADC3_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ + +#define ADC3_TR2_HT2_Pos (16U) +#define ADC3_TR2_HT2_Msk (0xFFUL << ADC3_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR2_HT2 ADC3_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ + +/******************** Bit definition for ADC3_TR3 register *******************/ +#define ADC3_TR3_LT3_Pos (0U) +#define ADC3_TR3_LT3_Msk (0xFFUL << ADC3_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC3_TR3_LT3 ADC3_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ + +#define ADC3_TR3_HT3_Pos (16U) +#define ADC3_TR3_HT3_Msk (0xFFUL << ADC3_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR3_HT3 ADC3_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ + +/******************** Bit definition for ADC_SQR1 register ********************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC regular channel sequence length */ +#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC 1st conversion in regular sequence */ +#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC 2nd conversion in regular sequence */ +#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC 3rd conversion in regular sequence */ +#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10UL << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC 4th conversion in regular sequence */ +#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ********************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC 5th conversion in regular sequence */ +#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC 6th conversion in regular sequence */ +#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ********************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC 10th conversion in regular sequence */ +#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC 11th conversion in regular sequence */ +#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC 12th conversion in regular sequence */ +#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC 13th conversion in regular sequence */ +#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC 14th conversion in regular sequence */ +#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ********************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC 15th conversion in regular sequence */ +#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC 16th conversion in regular sequence */ +#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFFFFFUL << ADC_DR_RDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC regular Data converted */ + +/******************** Bit definition for ADC_JSQR register ********************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC injected channel sequence length */ +#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0x1FUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000007C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC external trigger selection for injected group */ +#define ADC_JSQR_JEXTSEL_0 (0x01UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x02UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x04UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x08UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_JSQR_JEXTSEL_4 (0x10UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000040 */ + +#define ADC_JSQR_JEXTEN_Pos (7U) +#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000180 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC external trigger enable and polarity selection for injected channels */ +#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ +#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000100 */ + +#define ADC_JSQR_JSQ1_Pos (9U) +#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00003E00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ +#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00002000 */ + +#define ADC_JSQR_JSQ2_Pos (15U) +#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x000F8000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ +#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00080000 */ + +#define ADC_JSQR_JSQ3_Pos (21U) +#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x03E00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ +#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x02000000 */ + +#define ADC_JSQR_JSQ4_Pos (27U) +#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0xF8000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ +#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_OFR1 register ********************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0x3FFFFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ +#define ADC_OFR1_OFFSET1_0 (0x0000001UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x0000002UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x0000004UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x0000008UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x0000010UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x0000020UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x0000040UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x0000080UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x0000100UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x0000200UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x0000400UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x0000800UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ +#define ADC_OFR1_OFFSET1_12 (0x0001000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00001000 */ +#define ADC_OFR1_OFFSET1_13 (0x0002000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00002000 */ +#define ADC_OFR1_OFFSET1_14 (0x0004000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00004000 */ +#define ADC_OFR1_OFFSET1_15 (0x0008000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00008000 */ +#define ADC_OFR1_OFFSET1_16 (0x0010000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00010000 */ +#define ADC_OFR1_OFFSET1_17 (0x0020000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00020000 */ +#define ADC_OFR1_OFFSET1_18 (0x0040000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00040000 */ +#define ADC_OFR1_OFFSET1_19 (0x0080000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00080000 */ +#define ADC_OFR1_OFFSET1_20 (0x0100000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00100000 */ +#define ADC_OFR1_OFFSET1_21 (0x0200000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00200000 */ +#define ADC_OFR1_OFFSET1_22 (0x0400000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00400000 */ +#define ADC_OFR1_OFFSET1_23 (0x0800000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00800000 */ +#define ADC_OFR1_OFFSET1_24 (0x1000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x01000000 */ +#define ADC_OFR1_OFFSET1_25 (0x2000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x02000000 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC Channel selection for the data offset 1 */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_SSATE_Pos (31U) +#define ADC_OFR1_SSATE_Msk (0x1UL << ADC_OFR1_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_SSATE ADC_OFR1_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR1_OFFSET1_Pos (0U) +#define ADC3_OFR1_OFFSET1_Msk (0xFFFUL << ADC3_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR1_OFFSET1 ADC3_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR1_OFFSETPOS_Pos (24U) +#define ADC3_OFR1_OFFSETPOS_Msk (0x1UL << ADC3_OFR1_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR1_OFFSETPOS ADC3_OFR1_OFFSETPOS_Msk /*!< ADC offset number 1 positive */ +#define ADC3_OFR1_SATEN_Pos (25U) +#define ADC3_OFR1_SATEN_Msk (0x1UL << ADC3_OFR1_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR1_SATEN ADC3_OFR1_SATEN_Msk /*!< ADC offset number 1 saturation enable */ + +#define ADC3_OFR1_OFFSET1_EN_Pos (31U) +#define ADC3_OFR1_OFFSET1_EN_Msk (0x1UL << ADC3_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR1_OFFSET1_EN ADC3_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ********************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0x3FFFFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET2_CH[4:0] */ +#define ADC_OFR2_OFFSET2_0 (0x0000001UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x0000002UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x0000004UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x0000008UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x0000010UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x0000020UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x0000040UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x0000080UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x0000100UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x0000200UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x0000400UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x0000800UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ +#define ADC_OFR2_OFFSET2_12 (0x0001000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00001000 */ +#define ADC_OFR2_OFFSET2_13 (0x0002000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00002000 */ +#define ADC_OFR2_OFFSET2_14 (0x0004000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00004000 */ +#define ADC_OFR2_OFFSET2_15 (0x0008000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00008000 */ +#define ADC_OFR2_OFFSET2_16 (0x0010000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00010000 */ +#define ADC_OFR2_OFFSET2_17 (0x0020000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00020000 */ +#define ADC_OFR2_OFFSET2_18 (0x0040000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00040000 */ +#define ADC_OFR2_OFFSET2_19 (0x0080000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00080000 */ +#define ADC_OFR2_OFFSET2_20 (0x0100000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00100000 */ +#define ADC_OFR2_OFFSET2_21 (0x0200000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00200000 */ +#define ADC_OFR2_OFFSET2_22 (0x0400000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00400000 */ +#define ADC_OFR2_OFFSET2_23 (0x0800000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00800000 */ +#define ADC_OFR2_OFFSET2_24 (0x1000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x01000000 */ +#define ADC_OFR2_OFFSET2_25 (0x2000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x02000000 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC Channel selection for the data offset 2 */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_SSATE_Pos (31U) +#define ADC_OFR2_SSATE_Msk (0x1UL << ADC_OFR2_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_SSATE ADC_OFR2_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR2_OFFSET2_Pos (0U) +#define ADC3_OFR2_OFFSET2_Msk (0xFFFUL << ADC3_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR2_OFFSET2 ADC3_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR2_OFFSETPOS_Pos (24U) +#define ADC3_OFR2_OFFSETPOS_Msk (0x1UL << ADC3_OFR2_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR2_OFFSETPOS ADC3_OFR2_OFFSETPOS_Msk /*!< ADC offset number 2 positive */ +#define ADC3_OFR2_SATEN_Pos (25U) +#define ADC3_OFR2_SATEN_Msk (0x1UL << ADC3_OFR2_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR2_SATEN ADC3_OFR2_SATEN_Msk /*!< ADC offset number 2 saturation enable */ + +#define ADC3_OFR2_OFFSET2_EN_Pos (31U) +#define ADC3_OFR2_OFFSET2_EN_Msk (0x1UL << ADC3_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR2_OFFSET2_EN ADC3_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ********************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0x3FFFFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET3_CH[4:0] */ +#define ADC_OFR3_OFFSET3_0 (0x0000001UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x0000002UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x0000004UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x0000008UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x0000010UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x0000020UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x0000040UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x0000080UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x0000100UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x0000200UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x0000400UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x0000800UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ +#define ADC_OFR3_OFFSET3_12 (0x0001000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00001000 */ +#define ADC_OFR3_OFFSET3_13 (0x0002000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00002000 */ +#define ADC_OFR3_OFFSET3_14 (0x0004000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00004000 */ +#define ADC_OFR3_OFFSET3_15 (0x0008000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00008000 */ +#define ADC_OFR3_OFFSET3_16 (0x0010000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00010000 */ +#define ADC_OFR3_OFFSET3_17 (0x0020000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00020000 */ +#define ADC_OFR3_OFFSET3_18 (0x0040000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00040000 */ +#define ADC_OFR3_OFFSET3_19 (0x0080000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00080000 */ +#define ADC_OFR3_OFFSET3_20 (0x0100000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00100000 */ +#define ADC_OFR3_OFFSET3_21 (0x0200000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00200000 */ +#define ADC_OFR3_OFFSET3_22 (0x0400000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00400000 */ +#define ADC_OFR3_OFFSET3_23 (0x0800000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00800000 */ +#define ADC_OFR3_OFFSET3_24 (0x1000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x01000000 */ +#define ADC_OFR3_OFFSET3_25 (0x2000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x02000000 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC Channel selection for the data offset 3 */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_SSATE_Pos (31U) +#define ADC_OFR3_SSATE_Msk (0x1UL << ADC_OFR3_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_SSATE ADC_OFR3_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR3_OFFSET3_Pos (0U) +#define ADC3_OFR3_OFFSET3_Msk (0xFFFUL << ADC3_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR3_OFFSET3 ADC3_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR3_OFFSETPOS_Pos (24U) +#define ADC3_OFR3_OFFSETPOS_Msk (0x1UL << ADC3_OFR3_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR3_OFFSETPOS ADC3_OFR3_OFFSETPOS_Msk /*!< ADC offset number 3 positive */ +#define ADC3_OFR3_SATEN_Pos (25U) +#define ADC3_OFR3_SATEN_Msk (0x1UL << ADC3_OFR3_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR3_SATEN ADC3_OFR3_SATEN_Msk /*!< ADC offset number 3 saturation enable */ + +#define ADC3_OFR3_OFFSET3_EN_Pos (31U) +#define ADC3_OFR3_OFFSET3_EN_Msk (0x1UL << ADC3_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR3_OFFSET3_EN ADC3_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ********************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0x3FFFFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET4_CH[4:0] */ +#define ADC_OFR4_OFFSET4_0 (0x0000001UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x0000002UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x0000004UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x0000008UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x0000010UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x0000020UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x0000040UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x0000080UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x0000100UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x0000200UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x0000400UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x0000800UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ +#define ADC_OFR4_OFFSET4_12 (0x0001000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00001000 */ +#define ADC_OFR4_OFFSET4_13 (0x0002000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00002000 */ +#define ADC_OFR4_OFFSET4_14 (0x0004000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00004000 */ +#define ADC_OFR4_OFFSET4_15 (0x0008000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00008000 */ +#define ADC_OFR4_OFFSET4_16 (0x0010000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00010000 */ +#define ADC_OFR4_OFFSET4_17 (0x0020000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00020000 */ +#define ADC_OFR4_OFFSET4_18 (0x0040000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00040000 */ +#define ADC_OFR4_OFFSET4_19 (0x0080000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00080000 */ +#define ADC_OFR4_OFFSET4_20 (0x0100000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00100000 */ +#define ADC_OFR4_OFFSET4_21 (0x0200000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00200000 */ +#define ADC_OFR4_OFFSET4_22 (0x0400000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00400000 */ +#define ADC_OFR4_OFFSET4_23 (0x0800000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00800000 */ +#define ADC_OFR4_OFFSET4_24 (0x1000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x01000000 */ +#define ADC_OFR4_OFFSET4_25 (0x2000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x02000000 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC Channel selection for the data offset 4 */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_SSATE_Pos (31U) +#define ADC_OFR4_SSATE_Msk (0x1UL << ADC_OFR4_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_SSATE ADC_OFR4_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR4_OFFSET4_Pos (0U) +#define ADC3_OFR4_OFFSET4_Msk (0xFFFUL << ADC3_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR4_OFFSET4 ADC3_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR4_OFFSETPOS_Pos (24U) +#define ADC3_OFR4_OFFSETPOS_Msk (0x1UL << ADC3_OFR4_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR4_OFFSETPOS ADC3_OFR4_OFFSETPOS_Msk /*!< ADC offset number 4 positive */ +#define ADC3_OFR4_SATEN_Pos (25U) +#define ADC3_OFR4_SATEN_Msk (0x1UL << ADC3_OFR4_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR4_SATEN ADC3_OFR4_SATEN_Msk /*!< ADC offset number 4 saturation enable */ + +#define ADC3_OFR4_OFFSET4_EN_Pos (31U) +#define ADC3_OFR4_OFFSET4_EN_Msk (0x1UL << ADC3_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR4_OFFSET4_EN ADC3_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ********************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR1_JDATA_0 (0x00000001UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x00000002UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x00000004UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x00000008UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x00000010UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x00000020UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x00000040UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x00000080UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x00000100UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x00000200UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x00000400UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x00000800UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x00001000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x00002000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x00004000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x00008000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR1_JDATA_16 (0x00010000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR1_JDATA_17 (0x00020000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR1_JDATA_18 (0x00040000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR1_JDATA_19 (0x00080000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR1_JDATA_20 (0x00100000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR1_JDATA_21 (0x00200000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR1_JDATA_22 (0x00400000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR1_JDATA_23 (0x00800000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR1_JDATA_24 (0x01000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR1_JDATA_25 (0x02000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR1_JDATA_26 (0x04000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR1_JDATA_27 (0x08000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR1_JDATA_28 (0x10000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR1_JDATA_29 (0x20000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR1_JDATA_30 (0x40000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR1_JDATA_31 (0x80000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR2 register ********************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR2_JDATA_0 (0x00000001UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x00000002UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x00000004UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x00000008UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x00000010UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x00000020UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x00000040UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x00000080UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x00000100UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x00000200UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x00000400UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x00000800UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x00001000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x00002000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x00004000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x00008000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR2_JDATA_16 (0x00010000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR2_JDATA_17 (0x00020000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR2_JDATA_18 (0x00040000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR2_JDATA_19 (0x00080000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR2_JDATA_20 (0x00100000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR2_JDATA_21 (0x00200000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR2_JDATA_22 (0x00400000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR2_JDATA_23 (0x00800000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR2_JDATA_24 (0x01000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR2_JDATA_25 (0x02000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR2_JDATA_26 (0x04000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR2_JDATA_27 (0x08000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR2_JDATA_28 (0x10000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR2_JDATA_29 (0x20000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR2_JDATA_30 (0x40000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR2_JDATA_31 (0x80000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR3 register ********************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR3_JDATA_0 (0x00000001UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x00000002UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x00000004UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x00000008UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x00000010UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x00000020UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x00000040UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x00000080UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x00000100UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x00000200UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x00000400UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x00000800UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x00001000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x00002000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x00004000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x00008000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR3_JDATA_16 (0x00010000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR3_JDATA_17 (0x00020000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR3_JDATA_18 (0x00040000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR3_JDATA_19 (0x00080000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR3_JDATA_20 (0x00100000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR3_JDATA_21 (0x00200000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR3_JDATA_22 (0x00400000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR3_JDATA_23 (0x00800000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR3_JDATA_24 (0x01000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR3_JDATA_25 (0x02000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR3_JDATA_26 (0x04000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR3_JDATA_27 (0x08000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR3_JDATA_28 (0x10000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR3_JDATA_29 (0x20000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR3_JDATA_30 (0x40000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR3_JDATA_31 (0x80000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR4 register ********************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR4_JDATA_0 (0x00000001UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x00000002UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x00000004UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x00000008UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x00000010UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x00000020UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x00000040UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x00000080UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x00000100UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x00000200UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x00000400UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x00000800UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x00001000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x00002000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x00004000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x00008000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR4_JDATA_16 (0x00010000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR4_JDATA_17 (0x00020000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR4_JDATA_18 (0x00040000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR4_JDATA_19 (0x00080000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR4_JDATA_20 (0x00100000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR4_JDATA_21 (0x00200000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR4_JDATA_22 (0x00400000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR4_JDATA_23 (0x00800000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR4_JDATA_24 (0x01000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR4_JDATA_25 (0x02000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR4_JDATA_26 (0x04000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR4_JDATA_27 (0x08000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR4_JDATA_28 (0x10000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR4_JDATA_29 (0x20000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR4_JDATA_30 (0x40000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR4_JDATA_31 (0x80000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_AWD2CR register ********************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0xFFFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD2CR_AWD2CH_19 (0x80000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_AWD3CR register ********************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0xFFFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD3CR_AWD3CH_19 (0x80000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_DIFSEL register ********************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0xFFFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC differential modes for channels 1 to 18 */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ +#define ADC_DIFSEL_DIFSEL_19 (0x80000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_CALFACT register ********************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FFUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x000007FF */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factors in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x001UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x002UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x004UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x008UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x010UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x020UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x040UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT_CALFACT_S_7 (0x080UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT_CALFACT_S_8 (0x100UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT_CALFACT_S_9 (0x200UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT_CALFACT_S_10 (0x400UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FFUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x07FF0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factors in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x001UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x002UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x004UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x008UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x010UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x020UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x040UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT_CALFACT_D_7 (0x080UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT_CALFACT_D_8 (0x100UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT_CALFACT_D_9 (0x200UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT_CALFACT_D_10 (0x400UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_CALFACT2 register ********************/ +#define ADC_CALFACT2_LINCALFACT_Pos (0U) +#define ADC_CALFACT2_LINCALFACT_Msk (0x3FFFFFFFUL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x3FFFFFFF */ +#define ADC_CALFACT2_LINCALFACT ADC_CALFACT2_LINCALFACT_Msk /*!< ADC Linearity calibration factors */ +#define ADC_CALFACT2_LINCALFACT_0 (0x00000001UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT2_LINCALFACT_1 (0x00000002UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT2_LINCALFACT_2 (0x00000004UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT2_LINCALFACT_3 (0x00000008UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT2_LINCALFACT_4 (0x00000010UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT2_LINCALFACT_5 (0x00000020UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT2_LINCALFACT_6 (0x00000040UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT2_LINCALFACT_7 (0x00000080UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT2_LINCALFACT_8 (0x00000100UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT2_LINCALFACT_9 (0x00000200UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT2_LINCALFACT_10 (0x00000400UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT2_LINCALFACT_11 (0x00000800UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000800 */ +#define ADC_CALFACT2_LINCALFACT_12 (0x00001000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00001000 */ +#define ADC_CALFACT2_LINCALFACT_13 (0x00002000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00002000 */ +#define ADC_CALFACT2_LINCALFACT_14 (0x00004000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00004000 */ +#define ADC_CALFACT2_LINCALFACT_15 (0x00008000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00008000 */ +#define ADC_CALFACT2_LINCALFACT_16 (0x00010000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT2_LINCALFACT_17 (0x00020000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT2_LINCALFACT_18 (0x00040000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT2_LINCALFACT_19 (0x00080000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT2_LINCALFACT_20 (0x00100000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT2_LINCALFACT_21 (0x00200000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT2_LINCALFACT_22 (0x00400000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT2_LINCALFACT_23 (0x00800000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT2_LINCALFACT_24 (0x01000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT2_LINCALFACT_25 (0x02000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT2_LINCALFACT_26 (0x04000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x04000000 */ +#define ADC_CALFACT2_LINCALFACT_27 (0x08000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x08000000 */ +#define ADC_CALFACT2_LINCALFACT_28 (0x10000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x10000000 */ +#define ADC_CALFACT2_LINCALFACT_29 (0x20000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x20000000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register ********************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< Master ADC ready */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< End of sampling phase flag of the master ADC */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< End of regular conversion of the master ADC */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< End of regular sequence flag of the master ADC */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< Overrun flag of the master ADC */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< End of injected conversion of the master ADC */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< End of injected sequence flag of the master ADC */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< Analog watchdog 1 flag of the master ADC */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< Analog watchdog 2 flag of the master ADC */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< Analog watchdog 3 flag of the master ADC */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< Injected context queue overflow flag of the master ADC */ +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< Slave ADC ready */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< End of sampling phase flag of the slave ADC */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< End of regular conversion of the slave ADC */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< End of regular sequence flag of the slave ADC */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< Overrun flag of the slave ADC */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< End of injected conversion of the slave ADC */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< End of injected sequence flag of the slave ADC */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< Analog watchdog 1 flag of the slave ADC */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< Analog watchdog 2 flag of the slave ADC */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< Analog watchdog 3 flag of the slave ADC */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< Injected context queue overflow flag of the slave ADC */ + +/******************** Bit definition for ADC_CCR register ********************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< Dual ADC mode selection */ +#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< Delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + + +#define ADC_CCR_DAMDF_Pos (14U) +#define ADC_CCR_DAMDF_Msk (0x3UL << ADC_CCR_DAMDF_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_DAMDF ADC_CCR_DAMDF_Msk /*!< Dual ADC mode Data format */ +#define ADC_CCR_DAMDF_0 (0x1UL << ADC_CCR_DAMDF_Pos) /*!< 0x00004000 */ +#define ADC_CCR_DAMDF_1 (0x2UL << ADC_CCR_DAMDF_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC clock mode */ +#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC prescaler */ +#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< VREFINT enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1UL << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< Temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1UL << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< VBAT enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ + +/******************** Bit definition for ADC_CDR2 register ******************/ +#define ADC_CDR2_RDATA_ALT_Pos (0U) +#define ADC_CDR2_RDATA_ALT_Msk (0xFFFFFFFFUL << ADC_CDR2_RDATA_ALT_Pos) /*!< 0xFFFFFFFF */ +#define ADC_CDR2_RDATA_ALT ADC_CDR2_RDATA_ALT_Msk /*!< Regular data of the master/slave alternated ADCs */ + + +/******************************************************************************/ +/* */ +/* VREFBUF */ +/* */ +/******************************************************************************/ +/******************* Bit definition for VREFBUF_CSR register ****************/ +#define VREFBUF_CSR_ENVR_Pos (0U) +#define VREFBUF_CSR_ENVR_Msk (0x1UL << VREFBUF_CSR_ENVR_Pos) /*!< 0x00000001 */ +#define VREFBUF_CSR_ENVR VREFBUF_CSR_ENVR_Msk /*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!
    © Copyright (c) 2019 STMicroelectronics. + * All rights reserved.
    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS_Device + * @{ + */ + +/** @addtogroup stm32h735xx + * @{ + */ + +#ifndef STM32H735xx_H +#define STM32H735xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Peripheral_interrupt_number_definition + * @{ + */ + +/** + * @brief STM32H7XX Interrupt Number Definition, according to the selected device + * in @ref Library_configuration_section + */ +typedef enum +{ +/****** Cortex-M Processor Exceptions Numbers *****************************************************************/ + NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /*!< 4 Cortex-M Memory Management Interrupt */ + MemoryManagement_IRQn = -12, /*!< 4 Cortex-M Memory Management Interrupt */ + BusFault_IRQn = -11, /*!< 5 Cortex-M Bus Fault Interrupt */ + UsageFault_IRQn = -10, /*!< 6 Cortex-M Usage Fault Interrupt */ + SVCall_IRQn = -5, /*!< 11 Cortex-M SV Call Interrupt */ + DebugMonitor_IRQn = -4, /*!< 12 Cortex-M Debug Monitor Interrupt */ + PendSV_IRQn = -2, /*!< 14 Cortex-M Pend SV Interrupt */ + SysTick_IRQn = -1, /*!< 15 Cortex-M System Tick Interrupt */ +/****** STM32 specific Interrupt Numbers **********************************************************************/ + WWDG_IRQn = 0, /*!< Window WatchDog Interrupt ( wwdg1_it, wwdg2_it) */ + PVD_AVD_IRQn = 1, /*!< PVD/AVD through EXTI Line detection Interrupt */ + TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */ + RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */ + FLASH_IRQn = 4, /*!< FLASH global Interrupt */ + RCC_IRQn = 5, /*!< RCC global Interrupt */ + EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */ + EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */ + EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */ + EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */ + EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */ + DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */ + DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */ + DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */ + DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */ + DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */ + DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */ + DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ + ADC_IRQn = 18, /*!< ADC1 and ADC2 global Interrupts */ + FDCAN1_IT0_IRQn = 19, /*!< FDCAN1 Interrupt line 0 */ + FDCAN2_IT0_IRQn = 20, /*!< FDCAN2 Interrupt line 0 */ + FDCAN1_IT1_IRQn = 21, /*!< FDCAN1 Interrupt line 1 */ + FDCAN2_IT1_IRQn = 22, /*!< FDCAN2 Interrupt line 1 */ + EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */ + TIM1_BRK_IRQn = 24, /*!< TIM1 Break Interrupt */ + TIM1_UP_IRQn = 25, /*!< TIM1 Update Interrupt */ + TIM1_TRG_COM_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt */ + TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */ + TIM2_IRQn = 28, /*!< TIM2 global Interrupt */ + TIM3_IRQn = 29, /*!< TIM3 global Interrupt */ + TIM4_IRQn = 30, /*!< TIM4 global Interrupt */ + I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */ + I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */ + I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */ + I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */ + SPI1_IRQn = 35, /*!< SPI1 global Interrupt */ + SPI2_IRQn = 36, /*!< SPI2 global Interrupt */ + USART1_IRQn = 37, /*!< USART1 global Interrupt */ + USART2_IRQn = 38, /*!< USART2 global Interrupt */ + USART3_IRQn = 39, /*!< USART3 global Interrupt */ + EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */ + RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */ + TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */ + TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */ + TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */ + TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */ + DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */ + FMC_IRQn = 48, /*!< FMC global Interrupt */ + SDMMC1_IRQn = 49, /*!< SDMMC1 global Interrupt */ + TIM5_IRQn = 50, /*!< TIM5 global Interrupt */ + SPI3_IRQn = 51, /*!< SPI3 global Interrupt */ + UART4_IRQn = 52, /*!< UART4 global Interrupt */ + UART5_IRQn = 53, /*!< UART5 global Interrupt */ + TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */ + TIM7_IRQn = 55, /*!< TIM7 global interrupt */ + DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */ + DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */ + DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */ + DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */ + DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ + ETH_IRQn = 61, /*!< Ethernet global Interrupt */ + ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */ + FDCAN_CAL_IRQn = 63, /*!< FDCAN Calibration unit Interrupt */ + DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */ + DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */ + DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */ + USART6_IRQn = 71, /*!< USART6 global interrupt */ + I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */ + I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */ + OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */ + OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */ + OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */ + OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */ + DCMI_PSSI_IRQn = 78, /*!< DCMI and PSSI global interrupt */ + CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */ + HASH_RNG_IRQn = 80, /*!< HASH and RNG global interrupt */ + FPU_IRQn = 81, /*!< FPU global interrupt */ + UART7_IRQn = 82, /*!< UART7 global interrupt */ + UART8_IRQn = 83, /*!< UART8 global interrupt */ + SPI4_IRQn = 84, /*!< SPI4 global Interrupt */ + SPI5_IRQn = 85, /*!< SPI5 global Interrupt */ + SPI6_IRQn = 86, /*!< SPI6 global Interrupt */ + SAI1_IRQn = 87, /*!< SAI1 global Interrupt */ + LTDC_IRQn = 88, /*!< LTDC global Interrupt */ + LTDC_ER_IRQn = 89, /*!< LTDC Error global Interrupt */ + DMA2D_IRQn = 90, /*!< DMA2D global Interrupt */ + OCTOSPI1_IRQn = 92, /*!< OCTOSPI1 global interrupt */ + LPTIM1_IRQn = 93, /*!< LP TIM1 interrupt */ + CEC_IRQn = 94, /*!< HDMI-CEC global Interrupt */ + I2C4_EV_IRQn = 95, /*!< I2C4 Event Interrupt */ + I2C4_ER_IRQn = 96, /*!< I2C4 Error Interrupt */ + SPDIF_RX_IRQn = 97, /*!< SPDIF-RX global Interrupt */ + DMAMUX1_OVR_IRQn = 102, /*! + +/** @addtogroup Peripheral_registers_structures + * @{ + */ + +/** + * @brief Analog to Digital Converter + */ + +typedef struct +{ + __IO uint32_t ISR; /*!< ADC Interrupt and Status Register, Address offset: 0x00 */ + __IO uint32_t IER; /*!< ADC Interrupt Enable Register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< ADC control register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< ADC Configuration register, Address offset: 0x0C */ + __IO uint32_t CFGR2; /*!< ADC Configuration register 2, Address offset: 0x10 */ + __IO uint32_t SMPR1; /*!< ADC sample time register 1, Address offset: 0x14 */ + __IO uint32_t SMPR2; /*!< ADC sample time register 2, Address offset: 0x18 */ + __IO uint32_t PCSEL_RES0; /*!< Rserved for ADC3, ADC1/2 pre-channel selection, Address offset: 0x1C */ + __IO uint32_t LTR1_TR1; /*!< ADC watchdog Lower threshold register 1, Address offset: 0x20 */ + __IO uint32_t HTR1_TR2; /*!< ADC watchdog higher threshold register 1, Address offset: 0x24 */ + __IO uint32_t RES1_TR3; /*!< Rserved for ADC1/2, ADC3 threshold register, Address offset: 0x28 */ + uint32_t RESERVED2; /*!< Reserved, 0x02C */ + __IO uint32_t SQR1; /*!< ADC regular sequence register 1, Address offset: 0x30 */ + __IO uint32_t SQR2; /*!< ADC regular sequence register 2, Address offset: 0x34 */ + __IO uint32_t SQR3; /*!< ADC regular sequence register 3, Address offset: 0x38 */ + __IO uint32_t SQR4; /*!< ADC regular sequence register 4, Address offset: 0x3C */ + __IO uint32_t DR; /*!< ADC regular data register, Address offset: 0x40 */ + uint32_t RESERVED3; /*!< Reserved, 0x044 */ + uint32_t RESERVED4; /*!< Reserved, 0x048 */ + __IO uint32_t JSQR; /*!< ADC injected sequence register, Address offset: 0x4C */ + uint32_t RESERVED5[4]; /*!< Reserved, 0x050 - 0x05C */ + __IO uint32_t OFR1; /*!< ADC offset register 1, Address offset: 0x60 */ + __IO uint32_t OFR2; /*!< ADC offset register 2, Address offset: 0x64 */ + __IO uint32_t OFR3; /*!< ADC offset register 3, Address offset: 0x68 */ + __IO uint32_t OFR4; /*!< ADC offset register 4, Address offset: 0x6C */ + uint32_t RESERVED6[4]; /*!< Reserved, 0x070 - 0x07C */ + __IO uint32_t JDR1; /*!< ADC injected data register 1, Address offset: 0x80 */ + __IO uint32_t JDR2; /*!< ADC injected data register 2, Address offset: 0x84 */ + __IO uint32_t JDR3; /*!< ADC injected data register 3, Address offset: 0x88 */ + __IO uint32_t JDR4; /*!< ADC injected data register 4, Address offset: 0x8C */ + uint32_t RESERVED7[4]; /*!< Reserved, 0x090 - 0x09C */ + __IO uint32_t AWD2CR; /*!< ADC Analog Watchdog 2 Configuration Register, Address offset: 0xA0 */ + __IO uint32_t AWD3CR; /*!< ADC Analog Watchdog 3 Configuration Register, Address offset: 0xA4 */ + uint32_t RESERVED8; /*!< Reserved, 0x0A8 */ + uint32_t RESERVED9; /*!< Reserved, 0x0AC */ + __IO uint32_t LTR2_DIFSEL; /*!< ADC watchdog Lower threshold register 2, Difsel for ADC3, Address offset: 0xB0 */ + __IO uint32_t HTR2_CALFACT; /*!< ADC watchdog Higher threshold register 2, Calfact for ADC3, Address offset: 0xB4 */ + __IO uint32_t LTR3_RES10; /*!< ADC watchdog Lower threshold register 3, specific ADC1/2, Address offset: 0xB8 */ + __IO uint32_t HTR3_RES11; /*!< ADC watchdog Higher threshold register 3, specific ADC1/2, Address offset: 0xBC */ + __IO uint32_t DIFSEL_RES12; /*!< ADC Differential Mode Selection Register specific ADC1/2, Address offset: 0xC0 */ + __IO uint32_t CALFACT_RES13; /*!< ADC Calibration Factors specific ADC1/2, Address offset: 0xC4 */ + __IO uint32_t CALFACT2_RES14; /*!< ADC Linearity Calibration Factors specific ADC1/2, Address offset: 0xC8 */ +} ADC_TypeDef; + + +typedef struct +{ +__IO uint32_t CSR; /*!< ADC Common status register, Address offset: ADC1/3 base address + 0x300 */ +uint32_t RESERVED; /*!< Reserved, ADC1/3 base address + 0x304 */ +__IO uint32_t CCR; /*!< ADC common control register, Address offset: ADC1/3 base address + 0x308 */ +__IO uint32_t CDR; /*!< ADC common regular data register for dual Address offset: ADC1/3 base address + 0x30C */ +__IO uint32_t CDR2; /*!< ADC common regular data register for 32-bit dual mode Address offset: ADC1/3 base address + 0x310 */ + +} ADC_Common_TypeDef; + + +/** + * @brief VREFBUF + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< VREFBUF control and status register, Address offset: 0x00 */ + __IO uint32_t CCR; /*!< VREFBUF calibration and control register, Address offset: 0x04 */ +} VREFBUF_TypeDef; + + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< FDCAN Core Release register, Address offset: 0x000 */ + __IO uint32_t ENDN; /*!< FDCAN Endian register, Address offset: 0x004 */ + __IO uint32_t RESERVED1; /*!< Reserved, 0x008 */ + __IO uint32_t DBTP; /*!< FDCAN Data Bit Timing & Prescaler register, Address offset: 0x00C */ + __IO uint32_t TEST; /*!< FDCAN Test register, Address offset: 0x010 */ + __IO uint32_t RWD; /*!< FDCAN RAM Watchdog register, Address offset: 0x014 */ + __IO uint32_t CCCR; /*!< FDCAN CC Control register, Address offset: 0x018 */ + __IO uint32_t NBTP; /*!< FDCAN Nominal Bit Timing & Prescaler register, Address offset: 0x01C */ + __IO uint32_t TSCC; /*!< FDCAN Timestamp Counter Configuration register, Address offset: 0x020 */ + __IO uint32_t TSCV; /*!< FDCAN Timestamp Counter Value register, Address offset: 0x024 */ + __IO uint32_t TOCC; /*!< FDCAN Timeout Counter Configuration register, Address offset: 0x028 */ + __IO uint32_t TOCV; /*!< FDCAN Timeout Counter Value register, Address offset: 0x02C */ + __IO uint32_t RESERVED2[4]; /*!< Reserved, 0x030 - 0x03C */ + __IO uint32_t ECR; /*!< FDCAN Error Counter register, Address offset: 0x040 */ + __IO uint32_t PSR; /*!< FDCAN Protocol Status register, Address offset: 0x044 */ + __IO uint32_t TDCR; /*!< FDCAN Transmitter Delay Compensation register, Address offset: 0x048 */ + __IO uint32_t RESERVED3; /*!< Reserved, 0x04C */ + __IO uint32_t IR; /*!< FDCAN Interrupt register, Address offset: 0x050 */ + __IO uint32_t IE; /*!< FDCAN Interrupt Enable register, Address offset: 0x054 */ + __IO uint32_t ILS; /*!< FDCAN Interrupt Line Select register, Address offset: 0x058 */ + __IO uint32_t ILE; /*!< FDCAN Interrupt Line Enable register, Address offset: 0x05C */ + __IO uint32_t RESERVED4[8]; /*!< Reserved, 0x060 - 0x07C */ + __IO uint32_t GFC; /*!< FDCAN Global Filter Configuration register, Address offset: 0x080 */ + __IO uint32_t SIDFC; /*!< FDCAN Standard ID Filter Configuration register, Address offset: 0x084 */ + __IO uint32_t XIDFC; /*!< FDCAN Extended ID Filter Configuration register, Address offset: 0x088 */ + __IO uint32_t RESERVED5; /*!< Reserved, 0x08C */ + __IO uint32_t XIDAM; /*!< FDCAN Extended ID AND Mask register, Address offset: 0x090 */ + __IO uint32_t HPMS; /*!< FDCAN High Priority Message Status register, Address offset: 0x094 */ + __IO uint32_t NDAT1; /*!< FDCAN New Data 1 register, Address offset: 0x098 */ + __IO uint32_t NDAT2; /*!< FDCAN New Data 2 register, Address offset: 0x09C */ + __IO uint32_t RXF0C; /*!< FDCAN Rx FIFO 0 Configuration register, Address offset: 0x0A0 */ + __IO uint32_t RXF0S; /*!< FDCAN Rx FIFO 0 Status register, Address offset: 0x0A4 */ + __IO uint32_t RXF0A; /*!< FDCAN Rx FIFO 0 Acknowledge register, Address offset: 0x0A8 */ + __IO uint32_t RXBC; /*!< FDCAN Rx Buffer Configuration register, Address offset: 0x0AC */ + __IO uint32_t RXF1C; /*!< FDCAN Rx FIFO 1 Configuration register, Address offset: 0x0B0 */ + __IO uint32_t RXF1S; /*!< FDCAN Rx FIFO 1 Status register, Address offset: 0x0B4 */ + __IO uint32_t RXF1A; /*!< FDCAN Rx FIFO 1 Acknowledge register, Address offset: 0x0B8 */ + __IO uint32_t RXESC; /*!< FDCAN Rx Buffer/FIFO Element Size Configuration register, Address offset: 0x0BC */ + __IO uint32_t TXBC; /*!< FDCAN Tx Buffer Configuration register, Address offset: 0x0C0 */ + __IO uint32_t TXFQS; /*!< FDCAN Tx FIFO/Queue Status register, Address offset: 0x0C4 */ + __IO uint32_t TXESC; /*!< FDCAN Tx Buffer Element Size Configuration register, Address offset: 0x0C8 */ + __IO uint32_t TXBRP; /*!< FDCAN Tx Buffer Request Pending register, Address offset: 0x0CC */ + __IO uint32_t TXBAR; /*!< FDCAN Tx Buffer Add Request register, Address offset: 0x0D0 */ + __IO uint32_t TXBCR; /*!< FDCAN Tx Buffer Cancellation Request register, Address offset: 0x0D4 */ + __IO uint32_t TXBTO; /*!< FDCAN Tx Buffer Transmission Occurred register, Address offset: 0x0D8 */ + __IO uint32_t TXBCF; /*!< FDCAN Tx Buffer Cancellation Finished register, Address offset: 0x0DC */ + __IO uint32_t TXBTIE; /*!< FDCAN Tx Buffer Transmission Interrupt Enable register, Address offset: 0x0E0 */ + __IO uint32_t TXBCIE; /*!< FDCAN Tx Buffer Cancellation Finished Interrupt Enable register, Address offset: 0x0E4 */ + __IO uint32_t RESERVED6[2]; /*!< Reserved, 0x0E8 - 0x0EC */ + __IO uint32_t TXEFC; /*!< FDCAN Tx Event FIFO Configuration register, Address offset: 0x0F0 */ + __IO uint32_t TXEFS; /*!< FDCAN Tx Event FIFO Status register, Address offset: 0x0F4 */ + __IO uint32_t TXEFA; /*!< FDCAN Tx Event FIFO Acknowledge register, Address offset: 0x0F8 */ + __IO uint32_t RESERVED7; /*!< Reserved, 0x0FC */ +} FDCAN_GlobalTypeDef; + +/** + * @brief TTFD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t TTTMC; /*!< TT Trigger Memory Configuration register, Address offset: 0x100 */ + __IO uint32_t TTRMC; /*!< TT Reference Message Configuration register, Address offset: 0x104 */ + __IO uint32_t TTOCF; /*!< TT Operation Configuration register, Address offset: 0x108 */ + __IO uint32_t TTMLM; /*!< TT Matrix Limits register, Address offset: 0x10C */ + __IO uint32_t TURCF; /*!< TUR Configuration register, Address offset: 0x110 */ + __IO uint32_t TTOCN; /*!< TT Operation Control register, Address offset: 0x114 */ + __IO uint32_t TTGTP; /*!< TT Global Time Preset register, Address offset: 0x118 */ + __IO uint32_t TTTMK; /*!< TT Time Mark register, Address offset: 0x11C */ + __IO uint32_t TTIR; /*!< TT Interrupt register, Address offset: 0x120 */ + __IO uint32_t TTIE; /*!< TT Interrupt Enable register, Address offset: 0x124 */ + __IO uint32_t TTILS; /*!< TT Interrupt Line Select register, Address offset: 0x128 */ + __IO uint32_t TTOST; /*!< TT Operation Status register, Address offset: 0x12C */ + __IO uint32_t TURNA; /*!< TT TUR Numerator Actual register, Address offset: 0x130 */ + __IO uint32_t TTLGT; /*!< TT Local and Global Time register, Address offset: 0x134 */ + __IO uint32_t TTCTC; /*!< TT Cycle Time and Count register, Address offset: 0x138 */ + __IO uint32_t TTCPT; /*!< TT Capture Time register, Address offset: 0x13C */ + __IO uint32_t TTCSM; /*!< TT Cycle Sync Mark register, Address offset: 0x140 */ + __IO uint32_t RESERVED1[111]; /*!< Reserved, 0x144 - 0x2FC */ + __IO uint32_t TTTS; /*!< TT Trigger Select register, Address offset: 0x300 */ +} TTCAN_TypeDef; + +/** + * @brief FD Controller Area Network + */ + +typedef struct +{ + __IO uint32_t CREL; /*!< Clock Calibration Unit Core Release register, Address offset: 0x00 */ + __IO uint32_t CCFG; /*!< Calibration Configuration register, Address offset: 0x04 */ + __IO uint32_t CSTAT; /*!< Calibration Status register, Address offset: 0x08 */ + __IO uint32_t CWD; /*!< Calibration Watchdog register, Address offset: 0x0C */ + __IO uint32_t IR; /*!< CCU Interrupt register, Address offset: 0x10 */ + __IO uint32_t IE; /*!< CCU Interrupt Enable register, Address offset: 0x14 */ +} FDCAN_ClockCalibrationUnit_TypeDef; + + +/** + * @brief Consumer Electronics Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CEC control register, Address offset:0x00 */ + __IO uint32_t CFGR; /*!< CEC configuration register, Address offset:0x04 */ + __IO uint32_t TXDR; /*!< CEC Tx data register , Address offset:0x08 */ + __IO uint32_t RXDR; /*!< CEC Rx Data Register, Address offset:0x0C */ + __IO uint32_t ISR; /*!< CEC Interrupt and Status Register, Address offset:0x10 */ + __IO uint32_t IER; /*!< CEC interrupt enable register, Address offset:0x14 */ +}CEC_TypeDef; + +/** + * @brief COordincate Rotation DIgital Computer + */ +typedef struct +{ + __IO uint32_t CSR; /*!< CORDIC control and status register, Address offset: 0x00 */ + __IO uint32_t WDATA; /*!< CORDIC argument register, Address offset: 0x04 */ + __IO uint32_t RDATA; /*!< CORDIC result register, Address offset: 0x08 */ +} CORDIC_TypeDef; + +/** + * @brief CRC calculation unit + */ + +typedef struct +{ + __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ + __IO uint32_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ + uint32_t RESERVED2; /*!< Reserved, 0x0C */ + __IO uint32_t INIT; /*!< Initial CRC value register, Address offset: 0x10 */ + __IO uint32_t POL; /*!< CRC polynomial register, Address offset: 0x14 */ +} CRC_TypeDef; + + +/** + * @brief Clock Recovery System + */ +typedef struct +{ +__IO uint32_t CR; /*!< CRS ccontrol register, Address offset: 0x00 */ +__IO uint32_t CFGR; /*!< CRS configuration register, Address offset: 0x04 */ +__IO uint32_t ISR; /*!< CRS interrupt and status register, Address offset: 0x08 */ +__IO uint32_t ICR; /*!< CRS interrupt flag clear register, Address offset: 0x0C */ +} CRS_TypeDef; + + +/** + * @brief Digital to Analog Converter + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DAC control register, Address offset: 0x00 */ + __IO uint32_t SWTRIGR; /*!< DAC software trigger register, Address offset: 0x04 */ + __IO uint32_t DHR12R1; /*!< DAC channel1 12-bit right-aligned data holding register, Address offset: 0x08 */ + __IO uint32_t DHR12L1; /*!< DAC channel1 12-bit left aligned data holding register, Address offset: 0x0C */ + __IO uint32_t DHR8R1; /*!< DAC channel1 8-bit right aligned data holding register, Address offset: 0x10 */ + __IO uint32_t DHR12R2; /*!< DAC channel2 12-bit right aligned data holding register, Address offset: 0x14 */ + __IO uint32_t DHR12L2; /*!< DAC channel2 12-bit left aligned data holding register, Address offset: 0x18 */ + __IO uint32_t DHR8R2; /*!< DAC channel2 8-bit right-aligned data holding register, Address offset: 0x1C */ + __IO uint32_t DHR12RD; /*!< Dual DAC 12-bit right-aligned data holding register, Address offset: 0x20 */ + __IO uint32_t DHR12LD; /*!< DUAL DAC 12-bit left aligned data holding register, Address offset: 0x24 */ + __IO uint32_t DHR8RD; /*!< DUAL DAC 8-bit right aligned data holding register, Address offset: 0x28 */ + __IO uint32_t DOR1; /*!< DAC channel1 data output register, Address offset: 0x2C */ + __IO uint32_t DOR2; /*!< DAC channel2 data output register, Address offset: 0x30 */ + __IO uint32_t SR; /*!< DAC status register, Address offset: 0x34 */ + __IO uint32_t CCR; /*!< DAC calibration control register, Address offset: 0x38 */ + __IO uint32_t MCR; /*!< DAC mode control register, Address offset: 0x3C */ + __IO uint32_t SHSR1; /*!< DAC Sample and Hold sample time register 1, Address offset: 0x40 */ + __IO uint32_t SHSR2; /*!< DAC Sample and Hold sample time register 2, Address offset: 0x44 */ + __IO uint32_t SHHR; /*!< DAC Sample and Hold hold time register, Address offset: 0x48 */ + __IO uint32_t SHRR; /*!< DAC Sample and Hold refresh time register, Address offset: 0x4C */ +} DAC_TypeDef; + +/** + * @brief DFSDM module registers + */ +typedef struct +{ + __IO uint32_t FLTCR1; /*!< DFSDM control register1, Address offset: 0x100 */ + __IO uint32_t FLTCR2; /*!< DFSDM control register2, Address offset: 0x104 */ + __IO uint32_t FLTISR; /*!< DFSDM interrupt and status register, Address offset: 0x108 */ + __IO uint32_t FLTICR; /*!< DFSDM interrupt flag clear register, Address offset: 0x10C */ + __IO uint32_t FLTJCHGR; /*!< DFSDM injected channel group selection register, Address offset: 0x110 */ + __IO uint32_t FLTFCR; /*!< DFSDM filter control register, Address offset: 0x114 */ + __IO uint32_t FLTJDATAR; /*!< DFSDM data register for injected group, Address offset: 0x118 */ + __IO uint32_t FLTRDATAR; /*!< DFSDM data register for regular group, Address offset: 0x11C */ + __IO uint32_t FLTAWHTR; /*!< DFSDM analog watchdog high threshold register, Address offset: 0x120 */ + __IO uint32_t FLTAWLTR; /*!< DFSDM analog watchdog low threshold register, Address offset: 0x124 */ + __IO uint32_t FLTAWSR; /*!< DFSDM analog watchdog status register Address offset: 0x128 */ + __IO uint32_t FLTAWCFR; /*!< DFSDM analog watchdog clear flag register Address offset: 0x12C */ + __IO uint32_t FLTEXMAX; /*!< DFSDM extreme detector maximum register, Address offset: 0x130 */ + __IO uint32_t FLTEXMIN; /*!< DFSDM extreme detector minimum register Address offset: 0x134 */ + __IO uint32_t FLTCNVTIMR; /*!< DFSDM conversion timer, Address offset: 0x138 */ +} DFSDM_Filter_TypeDef; + +/** + * @brief DFSDM channel configuration registers + */ +typedef struct +{ + __IO uint32_t CHCFGR1; /*!< DFSDM channel configuration register1, Address offset: 0x00 */ + __IO uint32_t CHCFGR2; /*!< DFSDM channel configuration register2, Address offset: 0x04 */ + __IO uint32_t CHAWSCDR; /*!< DFSDM channel analog watchdog and + short circuit detector register, Address offset: 0x08 */ + __IO uint32_t CHWDATAR; /*!< DFSDM channel watchdog filter data register, Address offset: 0x0C */ + __IO uint32_t CHDATINR; /*!< DFSDM channel data input register, Address offset: 0x10 */ +} DFSDM_Channel_TypeDef; + +/** + * @brief Debug MCU + */ +typedef struct +{ + __IO uint32_t IDCODE; /*!< MCU device ID code, Address offset: 0x00 */ + __IO uint32_t CR; /*!< Debug MCU configuration register, Address offset: 0x04 */ + uint32_t RESERVED4[11]; /*!< Reserved, Address offset: 0x08 */ + __IO uint32_t APB3FZ1; /*!< Debug MCU APB3FZ1 freeze register, Address offset: 0x34 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x38 */ + __IO uint32_t APB1LFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x3C */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x40 */ + __IO uint32_t APB1HFZ1; /*!< Debug MCU APB1LFZ1 freeze register, Address offset: 0x44 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t APB2FZ1; /*!< Debug MCU APB2FZ1 freeze register, Address offset: 0x4C */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0x50 */ + __IO uint32_t APB4FZ1; /*!< Debug MCU APB4FZ1 freeze register, Address offset: 0x54 */ + __IO uint32_t RESERVED9[990]; /*!< Reserved, Address offset: 0x58-0xFCC */ + __IO uint32_t PIDR4; /*!< Debug MCU peripheral identity register 4, Address offset: 0xFD0 */ + __IO uint32_t RESERVED10[3];/*!< Reserved, Address offset: 0xFD4-0xFDC */ + __IO uint32_t PIDR0; /*!< Debug MCU peripheral identity register 0, Address offset: 0xFE0 */ + __IO uint32_t PIDR1; /*!< Debug MCU peripheral identity register 1, Address offset: 0xFE4 */ + __IO uint32_t PIDR2; /*!< Debug MCU peripheral identity register 2, Address offset: 0xFE8 */ + __IO uint32_t PIDR3; /*!< Debug MCU peripheral identity register 3, Address offset: 0xFEC */ + __IO uint32_t CIDR0; /*!< Debug MCU component identity register 0, Address offset: 0xFF0 */ + __IO uint32_t CIDR1; /*!< Debug MCU component identity register 1, Address offset: 0xFF4 */ + __IO uint32_t CIDR2; /*!< Debug MCU component identity register 2, Address offset: 0xFF8 */ + __IO uint32_t CIDR3; /*!< Debug MCU component identity register 3, Address offset: 0xFFC */ +}DBGMCU_TypeDef; +/** + * @brief DCMI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */ + __IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */ + __IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */ + __IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */ + __IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */ + __IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */ + __IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */ + __IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */ + __IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */ + __IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */ + __IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */ +} DCMI_TypeDef; + +/** + * @brief PSSI + */ + +typedef struct +{ + __IO uint32_t CR; /*!< PSSI control register 1, Address offset: 0x000 */ + __IO uint32_t SR; /*!< PSSI status register, Address offset: 0x004 */ + __IO uint32_t RIS; /*!< PSSI raw interrupt status register, Address offset: 0x008 */ + __IO uint32_t IER; /*!< PSSI interrupt enable register, Address offset: 0x00C */ + __IO uint32_t MIS; /*!< PSSI masked interrupt status register, Address offset: 0x010 */ + __IO uint32_t ICR; /*!< PSSI interrupt clear register, Address offset: 0x014 */ + __IO uint32_t RESERVED1[4]; /*!< Reserved, 0x018 - 0x024 */ + __IO uint32_t DR; /*!< PSSI data register, Address offset: 0x028 */ + __IO uint32_t RESERVED2[241]; /*!< Reserved, 0x02C - 0x3EC */ + __IO uint32_t HWCFGR; /*!< PSSI IP HW configuration register, Address offset: 0x3F0 */ + __IO uint32_t VERR; /*!< PSSI IP version register, Address offset: 0x3F4 */ + __IO uint32_t IPIDR; /*!< PSSI IP ID register, Address offset: 0x3F8 */ + __IO uint32_t SIDR; /*!< PSSI SIZE ID register, Address offset: 0x3FC */ +} PSSI_TypeDef; + +/** + * @brief DMA Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA stream x configuration register */ + __IO uint32_t NDTR; /*!< DMA stream x number of data register */ + __IO uint32_t PAR; /*!< DMA stream x peripheral address register */ + __IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */ + __IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */ + __IO uint32_t FCR; /*!< DMA stream x FIFO control register */ +} DMA_Stream_TypeDef; + +typedef struct +{ + __IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */ + __IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */ + __IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */ + __IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */ +} DMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA channel x configuration register */ + __IO uint32_t CNDTR; /*!< DMA channel x number of data register */ + __IO uint32_t CPAR; /*!< DMA channel x peripheral address register */ + __IO uint32_t CM0AR; /*!< DMA channel x memory 0 address register */ + __IO uint32_t CM1AR; /*!< DMA channel x memory 1 address register */ +} BDMA_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t ISR; /*!< DMA interrupt status register, Address offset: 0x00 */ + __IO uint32_t IFCR; /*!< DMA interrupt flag clear register, Address offset: 0x04 */ +} BDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CCR; /*!< DMA Multiplexer Channel x Control Register */ +}DMAMUX_Channel_TypeDef; + +typedef struct +{ + __IO uint32_t CSR; /*!< DMA Channel Status Register */ + __IO uint32_t CFR; /*!< DMA Channel Clear Flag Register */ +}DMAMUX_ChannelStatus_TypeDef; + +typedef struct +{ + __IO uint32_t RGCR; /*!< DMA Request Generator x Control Register */ +}DMAMUX_RequestGen_TypeDef; + +typedef struct +{ + __IO uint32_t RGSR; /*!< DMA Request Generator Status Register */ + __IO uint32_t RGCFR; /*!< DMA Request Generator Clear Flag Register */ +}DMAMUX_RequestGenStatus_TypeDef; + +/** + * @brief MDMA Controller + */ +typedef struct +{ + __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */ +}MDMA_TypeDef; + +typedef struct +{ + __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */ + __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */ + __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */ + __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ + __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */ + __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */ + __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */ + __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */ + __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */ + __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */ + __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */ + uint32_t RESERVED0; /*!< Reserved, 0x6C */ + __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */ + __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */ +}MDMA_Channel_TypeDef; + +/** + * @brief DMA2D Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ + __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ + __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ + __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ + __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ + __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ + __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ + __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ + __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ + __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ + __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ + __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ + __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ + __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ + __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ + __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ + __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ + __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ + __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ + __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ + uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ + __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ + __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ +} DMA2D_TypeDef; + + +/** + * @brief Ethernet MAC + */ +typedef struct +{ + __IO uint32_t MACCR; + __IO uint32_t MACECR; + __IO uint32_t MACPFR; + __IO uint32_t MACWTR; + __IO uint32_t MACHT0R; + __IO uint32_t MACHT1R; + uint32_t RESERVED1[14]; + __IO uint32_t MACVTR; + uint32_t RESERVED2; + __IO uint32_t MACVHTR; + uint32_t RESERVED3; + __IO uint32_t MACVIR; + __IO uint32_t MACIVIR; + uint32_t RESERVED4[2]; + __IO uint32_t MACTFCR; + uint32_t RESERVED5[7]; + __IO uint32_t MACRFCR; + uint32_t RESERVED6[7]; + __IO uint32_t MACISR; + __IO uint32_t MACIER; + __IO uint32_t MACRXTXSR; + uint32_t RESERVED7; + __IO uint32_t MACPCSR; + __IO uint32_t MACRWKPFR; + uint32_t RESERVED8[2]; + __IO uint32_t MACLCSR; + __IO uint32_t MACLTCR; + __IO uint32_t MACLETR; + __IO uint32_t MAC1USTCR; + uint32_t RESERVED9[12]; + __IO uint32_t MACVR; + __IO uint32_t MACDR; + uint32_t RESERVED10; + __IO uint32_t MACHWF0R; + __IO uint32_t MACHWF1R; + __IO uint32_t MACHWF2R; + uint32_t RESERVED11[54]; + __IO uint32_t MACMDIOAR; + __IO uint32_t MACMDIODR; + uint32_t RESERVED12[2]; + __IO uint32_t MACARPAR; + uint32_t RESERVED13[59]; + __IO uint32_t MACA0HR; + __IO uint32_t MACA0LR; + __IO uint32_t MACA1HR; + __IO uint32_t MACA1LR; + __IO uint32_t MACA2HR; + __IO uint32_t MACA2LR; + __IO uint32_t MACA3HR; + __IO uint32_t MACA3LR; + uint32_t RESERVED14[248]; + __IO uint32_t MMCCR; + __IO uint32_t MMCRIR; + __IO uint32_t MMCTIR; + __IO uint32_t MMCRIMR; + __IO uint32_t MMCTIMR; + uint32_t RESERVED15[14]; + __IO uint32_t MMCTSCGPR; + __IO uint32_t MMCTMCGPR; + uint32_t RESERVED16[5]; + __IO uint32_t MMCTPCGR; + uint32_t RESERVED17[10]; + __IO uint32_t MMCRCRCEPR; + __IO uint32_t MMCRAEPR; + uint32_t RESERVED18[10]; + __IO uint32_t MMCRUPGR; + uint32_t RESERVED19[9]; + __IO uint32_t MMCTLPIMSTR; + __IO uint32_t MMCTLPITCR; + __IO uint32_t MMCRLPIMSTR; + __IO uint32_t MMCRLPITCR; + uint32_t RESERVED20[65]; + __IO uint32_t MACL3L4C0R; + __IO uint32_t MACL4A0R; + uint32_t RESERVED21[2]; + __IO uint32_t MACL3A0R0R; + __IO uint32_t MACL3A1R0R; + __IO uint32_t MACL3A2R0R; + __IO uint32_t MACL3A3R0R; + uint32_t RESERVED22[4]; + __IO uint32_t MACL3L4C1R; + __IO uint32_t MACL4A1R; + uint32_t RESERVED23[2]; + __IO uint32_t MACL3A0R1R; + __IO uint32_t MACL3A1R1R; + __IO uint32_t MACL3A2R1R; + __IO uint32_t MACL3A3R1R; + uint32_t RESERVED24[108]; + __IO uint32_t MACTSCR; + __IO uint32_t MACSSIR; + __IO uint32_t MACSTSR; + __IO uint32_t MACSTNR; + __IO uint32_t MACSTSUR; + __IO uint32_t MACSTNUR; + __IO uint32_t MACTSAR; + uint32_t RESERVED25; + __IO uint32_t MACTSSR; + uint32_t RESERVED26[3]; + __IO uint32_t MACTTSSNR; + __IO uint32_t MACTTSSSR; + uint32_t RESERVED27[2]; + __IO uint32_t MACACR; + uint32_t RESERVED28; + __IO uint32_t MACATSNR; + __IO uint32_t MACATSSR; + __IO uint32_t MACTSIACR; + __IO uint32_t MACTSEACR; + __IO uint32_t MACTSICNR; + __IO uint32_t MACTSECNR; + uint32_t RESERVED29[4]; + __IO uint32_t MACPPSCR; + uint32_t RESERVED30[3]; + __IO uint32_t MACPPSTTSR; + __IO uint32_t MACPPSTTNR; + __IO uint32_t MACPPSIR; + __IO uint32_t MACPPSWR; + uint32_t RESERVED31[12]; + __IO uint32_t MACPOCR; + __IO uint32_t MACSPI0R; + __IO uint32_t MACSPI1R; + __IO uint32_t MACSPI2R; + __IO uint32_t MACLMIR; + uint32_t RESERVED32[11]; + __IO uint32_t MTLOMR; + uint32_t RESERVED33[7]; + __IO uint32_t MTLISR; + uint32_t RESERVED34[55]; + __IO uint32_t MTLTQOMR; + __IO uint32_t MTLTQUR; + __IO uint32_t MTLTQDR; + uint32_t RESERVED35[8]; + __IO uint32_t MTLQICSR; + __IO uint32_t MTLRQOMR; + __IO uint32_t MTLRQMPOCR; + __IO uint32_t MTLRQDR; + uint32_t RESERVED36[177]; + __IO uint32_t DMAMR; + __IO uint32_t DMASBMR; + __IO uint32_t DMAISR; + __IO uint32_t DMADSR; + uint32_t RESERVED37[60]; + __IO uint32_t DMACCR; + __IO uint32_t DMACTCR; + __IO uint32_t DMACRCR; + uint32_t RESERVED38[2]; + __IO uint32_t DMACTDLAR; + uint32_t RESERVED39; + __IO uint32_t DMACRDLAR; + __IO uint32_t DMACTDTPR; + uint32_t RESERVED40; + __IO uint32_t DMACRDTPR; + __IO uint32_t DMACTDRLR; + __IO uint32_t DMACRDRLR; + __IO uint32_t DMACIER; + __IO uint32_t DMACRIWTR; +__IO uint32_t DMACSFCSR; + uint32_t RESERVED41; + __IO uint32_t DMACCATDR; + uint32_t RESERVED42; + __IO uint32_t DMACCARDR; + uint32_t RESERVED43; + __IO uint32_t DMACCATBR; + uint32_t RESERVED44; + __IO uint32_t DMACCARBR; + __IO uint32_t DMACSR; +uint32_t RESERVED45[2]; +__IO uint32_t DMACMFCR; +}ETH_TypeDef; +/** + * @brief External Interrupt/Event Controller + */ + +typedef struct +{ +__IO uint32_t RTSR1; /*!< EXTI Rising trigger selection register, Address offset: 0x00 */ +__IO uint32_t FTSR1; /*!< EXTI Falling trigger selection register, Address offset: 0x04 */ +__IO uint32_t SWIER1; /*!< EXTI Software interrupt event register, Address offset: 0x08 */ +__IO uint32_t D3PMR1; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR1) Address offset: 0x0C */ +__IO uint32_t D3PCR1L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR1L) Address offset: 0x10 */ +__IO uint32_t D3PCR1H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR1H) Address offset: 0x14 */ +uint32_t RESERVED1[2]; /*!< Reserved, 0x18 to 0x1C */ +__IO uint32_t RTSR2; /*!< EXTI Rising trigger selection register, Address offset: 0x20 */ +__IO uint32_t FTSR2; /*!< EXTI Falling trigger selection register, Address offset: 0x24 */ +__IO uint32_t SWIER2; /*!< EXTI Software interrupt event register, Address offset: 0x28 */ +__IO uint32_t D3PMR2; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR2) Address offset: 0x2C */ +__IO uint32_t D3PCR2L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR2L) Address offset: 0x30 */ +__IO uint32_t D3PCR2H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR2H) Address offset: 0x34 */ +uint32_t RESERVED2[2]; /*!< Reserved, 0x38 to 0x3C */ +__IO uint32_t RTSR3; /*!< EXTI Rising trigger selection register, Address offset: 0x40 */ +__IO uint32_t FTSR3; /*!< EXTI Falling trigger selection register, Address offset: 0x44 */ +__IO uint32_t SWIER3; /*!< EXTI Software interrupt event register, Address offset: 0x48 */ +__IO uint32_t D3PMR3; /*!< EXTI D3 Pending mask register, (same register as to SRDPMR3) Address offset: 0x4C */ +__IO uint32_t D3PCR3L; /*!< EXTI D3 Pending clear selection register low, (same register as to SRDPCR3L) Address offset: 0x50 */ +__IO uint32_t D3PCR3H; /*!< EXTI D3 Pending clear selection register High, (same register as to SRDPCR3H) Address offset: 0x54 */ +uint32_t RESERVED3[10]; /*!< Reserved, 0x58 to 0x7C */ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x80 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x84 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x88 */ +uint32_t RESERVED4; /*!< Reserved, 0x8C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x90 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x94 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x98 */ +uint32_t RESERVED5; /*!< Reserved, 0x9C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0xA0 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0xA4 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0xA8 */ +}EXTI_TypeDef; + +/** + * @brief This structure registers corresponds to EXTI_Typdef CPU1/CPU2 registers subset (IMRx, EMRx and PRx), allowing to define EXTI_D1/EXTI_D2 + * with rapid/common access to these IMRx, EMRx, PRx registers for CPU1 and CPU2. + * Note that EXTI_D1 and EXTI_D2 bases addresses are calculated to point to CPUx first register: + * IMR1 in case of EXTI_D1 that is addressing CPU1 (Coretx-M7) + * C2IMR1 in case of EXTI_D2 that is addressing CPU2 (Coretx-M4) + * Note: EXTI_D2 and corresponding C2IMRx, C2EMRx and C2PRx registers are available for Dual Core devices only + */ + +typedef struct +{ +__IO uint32_t IMR1; /*!< EXTI Interrupt mask register, Address offset: 0x00 */ +__IO uint32_t EMR1; /*!< EXTI Event mask register, Address offset: 0x04 */ +__IO uint32_t PR1; /*!< EXTI Pending register, Address offset: 0x08 */ +uint32_t RESERVED1; /*!< Reserved, 0x0C */ +__IO uint32_t IMR2; /*!< EXTI Interrupt mask register, Address offset: 0x10 */ +__IO uint32_t EMR2; /*!< EXTI Event mask register, Address offset: 0x14 */ +__IO uint32_t PR2; /*!< EXTI Pending register, Address offset: 0x18 */ +uint32_t RESERVED2; /*!< Reserved, 0x1C */ +__IO uint32_t IMR3; /*!< EXTI Interrupt mask register, Address offset: 0x20 */ +__IO uint32_t EMR3; /*!< EXTI Event mask register, Address offset: 0x24 */ +__IO uint32_t PR3; /*!< EXTI Pending register, Address offset: 0x28 */ +}EXTI_Core_TypeDef; + + +/** + * @brief FLASH Registers + */ + +typedef struct +{ + __IO uint32_t ACR; /*!< FLASH access control register, Address offset: 0x00 */ + __IO uint32_t KEYR1; /*!< Flash Key Register for bank1, Address offset: 0x04 */ + __IO uint32_t OPTKEYR; /*!< Flash Option Key Register, Address offset: 0x08 */ + __IO uint32_t CR1; /*!< Flash Control Register for bank1, Address offset: 0x0C */ + __IO uint32_t SR1; /*!< Flash Status Register for bank1, Address offset: 0x10 */ + __IO uint32_t CCR1; /*!< Flash Control Register for bank1, Address offset: 0x14 */ + __IO uint32_t OPTCR; /*!< Flash Option Control Register, Address offset: 0x18 */ + __IO uint32_t OPTSR_CUR; /*!< Flash Option Status Current Register, Address offset: 0x1C */ + __IO uint32_t OPTSR_PRG; /*!< Flash Option Status to Program Register, Address offset: 0x20 */ + __IO uint32_t OPTCCR; /*!< Flash Option Clear Control Register, Address offset: 0x24 */ + __IO uint32_t PRAR_CUR1; /*!< Flash Current Protection Address Register for bank1, Address offset: 0x28 */ + __IO uint32_t PRAR_PRG1; /*!< Flash Protection Address to Program Register for bank1, Address offset: 0x2C */ + __IO uint32_t SCAR_CUR1; /*!< Flash Current Secure Address Register for bank1, Address offset: 0x30 */ + __IO uint32_t SCAR_PRG1; /*!< Flash Secure Address to Program Register for bank1, Address offset: 0x34 */ + __IO uint32_t WPSN_CUR1; /*!< Flash Current Write Protection Register on bank1, Address offset: 0x38 */ + __IO uint32_t WPSN_PRG1; /*!< Flash Write Protection to Program Register on bank1, Address offset: 0x3C */ + __IO uint32_t BOOT_CUR; /*!< Flash Current Boot Address for Pelican Core Register, Address offset: 0x40 */ + __IO uint32_t BOOT_PRG; /*!< Flash Boot Address to Program for Pelican Core Register, Address offset: 0x44 */ + uint32_t RESERVED0[2]; /*!< Reserved, 0x48 to 0x4C */ + __IO uint32_t CRCCR1; /*!< Flash CRC Control register For Bank1 Register , Address offset: 0x50 */ + __IO uint32_t CRCSADD1; /*!< Flash CRC Start Address Register for Bank1 , Address offset: 0x54 */ + __IO uint32_t CRCEADD1; /*!< Flash CRC End Address Register for Bank1 , Address offset: 0x58 */ + __IO uint32_t CRCDATA; /*!< Flash CRC Data Register for Bank1 , Address offset: 0x5C */ + __IO uint32_t ECC_FA1; /*!< Flash ECC Fail Address For Bank1 Register , Address offset: 0x60 */ + uint32_t RESERVED[3]; /*!< Reserved, 0x64 to 0x6C */ + __IO uint32_t OPTSR2_CUR; /*!< Flash Option Status Current Register 2, Address offset: 0x70 */ + __IO uint32_t OPTSR2_PRG; /*!< Flash Option Status to Program Register 2, Address offset: 0x74 */ +} FLASH_TypeDef; + +/** + * @brief Filter and Mathematical ACcelerator + */ +typedef struct +{ + __IO uint32_t X1BUFCFG; /*!< FMAC X1 Buffer Configuration register, Address offset: 0x00 */ + __IO uint32_t X2BUFCFG; /*!< FMAC X2 Buffer Configuration register, Address offset: 0x04 */ + __IO uint32_t YBUFCFG; /*!< FMAC Y Buffer Configuration register, Address offset: 0x08 */ + __IO uint32_t PARAM; /*!< FMAC Parameter register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< FMAC Control register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< FMAC Status register, Address offset: 0x14 */ + __IO uint32_t WDATA; /*!< FMAC Write Data register, Address offset: 0x18 */ + __IO uint32_t RDATA; /*!< FMAC Read Data register, Address offset: 0x1C */ +} FMAC_TypeDef; + +/** + * @brief Flexible Memory Controller + */ + +typedef struct +{ + __IO uint32_t BTCR[8]; /*!< NOR/PSRAM chip-select control register(BCR) and chip-select timing register(BTR), Address offset: 0x00-1C */ +} FMC_Bank1_TypeDef; + +/** + * @brief Flexible Memory Controller Bank1E + */ + +typedef struct +{ + __IO uint32_t BWTR[7]; /*!< NOR/PSRAM write timing registers, Address offset: 0x104-0x11C */ +} FMC_Bank1E_TypeDef; + +/** + * @brief Flexible Memory Controller Bank2 + */ + +typedef struct +{ + __IO uint32_t PCR2; /*!< NAND Flash control register 2, Address offset: 0x60 */ + __IO uint32_t SR2; /*!< NAND Flash FIFO status and interrupt register 2, Address offset: 0x64 */ + __IO uint32_t PMEM2; /*!< NAND Flash Common memory space timing register 2, Address offset: 0x68 */ + __IO uint32_t PATT2; /*!< NAND Flash Attribute memory space timing register 2, Address offset: 0x6C */ + uint32_t RESERVED0; /*!< Reserved, 0x70 */ + __IO uint32_t ECCR2; /*!< NAND Flash ECC result registers 2, Address offset: 0x74 */ +} FMC_Bank2_TypeDef; + +/** + * @brief Flexible Memory Controller Bank3 + */ + +typedef struct +{ + __IO uint32_t PCR; /*!< NAND Flash control register 3, Address offset: 0x80 */ + __IO uint32_t SR; /*!< NAND Flash FIFO status and interrupt register 3, Address offset: 0x84 */ + __IO uint32_t PMEM; /*!< NAND Flash Common memory space timing register 3, Address offset: 0x88 */ + __IO uint32_t PATT; /*!< NAND Flash Attribute memory space timing register 3, Address offset: 0x8C */ + uint32_t RESERVED; /*!< Reserved, 0x90 */ + __IO uint32_t ECCR; /*!< NAND Flash ECC result registers 3, Address offset: 0x94 */ +} FMC_Bank3_TypeDef; + +/** + * @brief Flexible Memory Controller Bank5 and 6 + */ + + +typedef struct +{ + __IO uint32_t SDCR[2]; /*!< SDRAM Control registers , Address offset: 0x140-0x144 */ + __IO uint32_t SDTR[2]; /*!< SDRAM Timing registers , Address offset: 0x148-0x14C */ + __IO uint32_t SDCMR; /*!< SDRAM Command Mode register, Address offset: 0x150 */ + __IO uint32_t SDRTR; /*!< SDRAM Refresh Timer register, Address offset: 0x154 */ + __IO uint32_t SDSR; /*!< SDRAM Status register, Address offset: 0x158 */ +} FMC_Bank5_6_TypeDef; + +/** + * @brief General Purpose I/O + */ + +typedef struct +{ + __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ + __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ + __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ + __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ + __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ + __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ + __IO uint32_t BSRR; /*!< GPIO port bit set/reset, Address offset: 0x18 */ + __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ + __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ +} GPIO_TypeDef; + +/** + * @brief Operational Amplifier (OPAMP) + */ + +typedef struct +{ + __IO uint32_t CSR; /*!< OPAMP control/status register, Address offset: 0x00 */ + __IO uint32_t OTR; /*!< OPAMP offset trimming register for normal mode, Address offset: 0x04 */ + __IO uint32_t HSOTR; /*!< OPAMP offset trimming register for high speed mode, Address offset: 0x08 */ +} OPAMP_TypeDef; + +/** + * @brief System configuration controller + */ + +typedef struct +{ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x00 */ + __IO uint32_t PMCR; /*!< SYSCFG peripheral mode configuration register, Address offset: 0x04 */ + __IO uint32_t EXTICR[4]; /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */ + __IO uint32_t CFGR; /*!< SYSCFG configuration registers, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t CCCSR; /*!< SYSCFG compensation cell control/status register, Address offset: 0x20 */ + __IO uint32_t CCVR; /*!< SYSCFG compensation cell value register, Address offset: 0x24 */ + __IO uint32_t CCCR; /*!< SYSCFG compensation cell code register, Address offset: 0x28 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2C */ + __IO uint32_t ADC2ALT; /*!< ADC2 internal input alternate connection register, Address offset: 0x30 */ + uint32_t RESERVED4[60]; /*!< Reserved, 0x34-0x120 */ + __IO uint32_t PKGR; /*!< SYSCFG package register, Address offset: 0x124 */ + uint32_t RESERVED5[118]; /*!< Reserved, 0x128-0x2FC */ + __IO uint32_t UR0; /*!< SYSCFG user register 0, Address offset: 0x300 */ + __IO uint32_t UR1; /*!< SYSCFG user register 1, Address offset: 0x304 */ + __IO uint32_t UR2; /*!< SYSCFG user register 2, Address offset: 0x308 */ + __IO uint32_t UR3; /*!< SYSCFG user register 3, Address offset: 0x30C */ + __IO uint32_t UR4; /*!< SYSCFG user register 4, Address offset: 0x310 */ + __IO uint32_t UR5; /*!< SYSCFG user register 5, Address offset: 0x314 */ + __IO uint32_t UR6; /*!< SYSCFG user register 6, Address offset: 0x318 */ + __IO uint32_t UR7; /*!< SYSCFG user register 7, Address offset: 0x31C */ + uint32_t RESERVED6[3]; /*!< Reserved, Address offset: 0x320-0x328 */ + __IO uint32_t UR11; /*!< SYSCFG user register 11, Address offset: 0x32C */ + __IO uint32_t UR12; /*!< SYSCFG user register 12, Address offset: 0x330 */ + __IO uint32_t UR13; /*!< SYSCFG user register 13, Address offset: 0x334 */ + __IO uint32_t UR14; /*!< SYSCFG user register 14, Address offset: 0x338 */ + __IO uint32_t UR15; /*!< SYSCFG user register 15, Address offset: 0x33C */ + __IO uint32_t UR16; /*!< SYSCFG user register 16, Address offset: 0x340 */ + __IO uint32_t UR17; /*!< SYSCFG user register 17, Address offset: 0x344 */ + __IO uint32_t UR18; /*!< SYSCFG user register 18, Address offset: 0x348 */ + +} SYSCFG_TypeDef; + +/** + * @brief Inter-integrated Circuit Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< I2C Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< I2C Control register 2, Address offset: 0x04 */ + __IO uint32_t OAR1; /*!< I2C Own address 1 register, Address offset: 0x08 */ + __IO uint32_t OAR2; /*!< I2C Own address 2 register, Address offset: 0x0C */ + __IO uint32_t TIMINGR; /*!< I2C Timing register, Address offset: 0x10 */ + __IO uint32_t TIMEOUTR; /*!< I2C Timeout register, Address offset: 0x14 */ + __IO uint32_t ISR; /*!< I2C Interrupt and status register, Address offset: 0x18 */ + __IO uint32_t ICR; /*!< I2C Interrupt clear register, Address offset: 0x1C */ + __IO uint32_t PECR; /*!< I2C PEC register, Address offset: 0x20 */ + __IO uint32_t RXDR; /*!< I2C Receive data register, Address offset: 0x24 */ + __IO uint32_t TXDR; /*!< I2C Transmit data register, Address offset: 0x28 */ +} I2C_TypeDef; + +/** + * @brief Independent WATCHDOG + */ + +typedef struct +{ + __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ + __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ + __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ + __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ + __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ +} IWDG_TypeDef; + + +/** + * @brief LCD-TFT Display Controller + */ + +typedef struct +{ + uint32_t RESERVED0[2]; /*!< Reserved, 0x00-0x04 */ + __IO uint32_t SSCR; /*!< LTDC Synchronization Size Configuration Register, Address offset: 0x08 */ + __IO uint32_t BPCR; /*!< LTDC Back Porch Configuration Register, Address offset: 0x0C */ + __IO uint32_t AWCR; /*!< LTDC Active Width Configuration Register, Address offset: 0x10 */ + __IO uint32_t TWCR; /*!< LTDC Total Width Configuration Register, Address offset: 0x14 */ + __IO uint32_t GCR; /*!< LTDC Global Control Register, Address offset: 0x18 */ + uint32_t RESERVED1[2]; /*!< Reserved, 0x1C-0x20 */ + __IO uint32_t SRCR; /*!< LTDC Shadow Reload Configuration Register, Address offset: 0x24 */ + uint32_t RESERVED2[1]; /*!< Reserved, 0x28 */ + __IO uint32_t BCCR; /*!< LTDC Background Color Configuration Register, Address offset: 0x2C */ + uint32_t RESERVED3[1]; /*!< Reserved, 0x30 */ + __IO uint32_t IER; /*!< LTDC Interrupt Enable Register, Address offset: 0x34 */ + __IO uint32_t ISR; /*!< LTDC Interrupt Status Register, Address offset: 0x38 */ + __IO uint32_t ICR; /*!< LTDC Interrupt Clear Register, Address offset: 0x3C */ + __IO uint32_t LIPCR; /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */ + __IO uint32_t CPSR; /*!< LTDC Current Position Status Register, Address offset: 0x44 */ + __IO uint32_t CDSR; /*!< LTDC Current Display Status Register, Address offset: 0x48 */ +} LTDC_TypeDef; + +/** + * @brief LCD-TFT Display layer x Controller + */ + +typedef struct +{ + __IO uint32_t CR; /*!< LTDC Layerx Control Register Address offset: 0x84 */ + __IO uint32_t WHPCR; /*!< LTDC Layerx Window Horizontal Position Configuration Register Address offset: 0x88 */ + __IO uint32_t WVPCR; /*!< LTDC Layerx Window Vertical Position Configuration Register Address offset: 0x8C */ + __IO uint32_t CKCR; /*!< LTDC Layerx Color Keying Configuration Register Address offset: 0x90 */ + __IO uint32_t PFCR; /*!< LTDC Layerx Pixel Format Configuration Register Address offset: 0x94 */ + __IO uint32_t CACR; /*!< LTDC Layerx Constant Alpha Configuration Register Address offset: 0x98 */ + __IO uint32_t DCCR; /*!< LTDC Layerx Default Color Configuration Register Address offset: 0x9C */ + __IO uint32_t BFCR; /*!< LTDC Layerx Blending Factors Configuration Register Address offset: 0xA0 */ + uint32_t RESERVED0[2]; /*!< Reserved */ + __IO uint32_t CFBAR; /*!< LTDC Layerx Color Frame Buffer Address Register Address offset: 0xAC */ + __IO uint32_t CFBLR; /*!< LTDC Layerx Color Frame Buffer Length Register Address offset: 0xB0 */ + __IO uint32_t CFBLNR; /*!< LTDC Layerx ColorFrame Buffer Line Number Register Address offset: 0xB4 */ + uint32_t RESERVED1[3]; /*!< Reserved */ + __IO uint32_t CLUTWR; /*!< LTDC Layerx CLUT Write Register Address offset: 0x144 */ + +} LTDC_Layer_TypeDef; + +/** + * @brief Power Control + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< PWR power control register 1, Address offset: 0x00 */ + __IO uint32_t CSR1; /*!< PWR power control status register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< PWR power control register 2, Address offset: 0x08 */ + __IO uint32_t CR3; /*!< PWR power control register 3, Address offset: 0x0C */ + __IO uint32_t CPUCR; /*!< PWR CPU control register, Address offset: 0x10 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D3CR; /*!< PWR D3 domain control register, Address offset: 0x18 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x1C */ + __IO uint32_t WKUPCR; /*!< PWR wakeup clear register, Address offset: 0x20 */ + __IO uint32_t WKUPFR; /*!< PWR wakeup flag register, Address offset: 0x24 */ + __IO uint32_t WKUPEPR; /*!< PWR wakeup enable and polarity register, Address offset: 0x28 */ +} PWR_TypeDef; + +/** + * @brief Reset and Clock Control + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ + __IO uint32_t HSICFGR; /*!< HSI Clock Calibration Register, Address offset: 0x04 */ + __IO uint32_t CRRCR; /*!< Clock Recovery RC Register, Address offset: 0x08 */ + __IO uint32_t CSICFGR; /*!< CSI Clock Calibration Register, Address offset: 0x0C */ + __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x10 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x14 */ + __IO uint32_t D1CFGR; /*!< RCC Domain 1 configuration register, Address offset: 0x18 */ + __IO uint32_t D2CFGR; /*!< RCC Domain 2 configuration register, Address offset: 0x1C */ + __IO uint32_t D3CFGR; /*!< RCC Domain 3 configuration register, Address offset: 0x20 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x24 */ + __IO uint32_t PLLCKSELR; /*!< RCC PLLs Clock Source Selection Register, Address offset: 0x28 */ + __IO uint32_t PLLCFGR; /*!< RCC PLLs Configuration Register, Address offset: 0x2C */ + __IO uint32_t PLL1DIVR; /*!< RCC PLL1 Dividers Configuration Register, Address offset: 0x30 */ + __IO uint32_t PLL1FRACR; /*!< RCC PLL1 Fractional Divider Configuration Register, Address offset: 0x34 */ + __IO uint32_t PLL2DIVR; /*!< RCC PLL2 Dividers Configuration Register, Address offset: 0x38 */ + __IO uint32_t PLL2FRACR; /*!< RCC PLL2 Fractional Divider Configuration Register, Address offset: 0x3C */ + __IO uint32_t PLL3DIVR; /*!< RCC PLL3 Dividers Configuration Register, Address offset: 0x40 */ + __IO uint32_t PLL3FRACR; /*!< RCC PLL3 Fractional Divider Configuration Register, Address offset: 0x44 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x48 */ + __IO uint32_t D1CCIPR; /*!< RCC Domain 1 Kernel Clock Configuration Register Address offset: 0x4C */ + __IO uint32_t D2CCIP1R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x50 */ + __IO uint32_t D2CCIP2R; /*!< RCC Domain 2 Kernel Clock Configuration Register Address offset: 0x54 */ + __IO uint32_t D3CCIPR; /*!< RCC Domain 3 Kernel Clock Configuration Register Address offset: 0x58 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x5C */ + __IO uint32_t CIER; /*!< RCC Clock Source Interrupt Enable Register Address offset: 0x60 */ + __IO uint32_t CIFR; /*!< RCC Clock Source Interrupt Flag Register Address offset: 0x64 */ + __IO uint32_t CICR; /*!< RCC Clock Source Interrupt Clear Register Address offset: 0x68 */ + uint32_t RESERVED5; /*!< Reserved, Address offset: 0x6C */ + __IO uint32_t BDCR; /*!< RCC Vswitch Backup Domain Control Register, Address offset: 0x70 */ + __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x78 */ + __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x7C */ + __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x80 */ + __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x84 */ + __IO uint32_t AHB4RSTR; /*!< RCC AHB4 peripheral reset register, Address offset: 0x88 */ + __IO uint32_t APB3RSTR; /*!< RCC APB3 peripheral reset register, Address offset: 0x8C */ + __IO uint32_t APB1LRSTR; /*!< RCC APB1 peripheral reset Low Word register, Address offset: 0x90 */ + __IO uint32_t APB1HRSTR; /*!< RCC APB1 peripheral reset High Word register, Address offset: 0x94 */ + __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x98 */ + __IO uint32_t APB4RSTR; /*!< RCC APB4 peripheral reset register, Address offset: 0x9C */ + __IO uint32_t GCR; /*!< RCC RCC Global Control Register, Address offset: 0xA0 */ + uint32_t RESERVED8; /*!< Reserved, Address offset: 0xA4 */ + __IO uint32_t D3AMR; /*!< RCC Domain 3 Autonomous Mode Register, Address offset: 0xA8 */ + uint32_t RESERVED11[9]; /*!< Reserved, 0xAC-0xCC Address offset: 0xAC */ + __IO uint32_t RSR; /*!< RCC Reset status register, Address offset: 0xD0 */ + __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0xD4 */ + __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0xD8 */ + __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0xDC */ + __IO uint32_t AHB4ENR; /*!< RCC AHB4 peripheral clock register, Address offset: 0xE0 */ + __IO uint32_t APB3ENR; /*!< RCC APB3 peripheral clock register, Address offset: 0xE4 */ + __IO uint32_t APB1LENR; /*!< RCC APB1 peripheral clock Low Word register, Address offset: 0xE8 */ + __IO uint32_t APB1HENR; /*!< RCC APB1 peripheral clock High Word register, Address offset: 0xEC */ + __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock register, Address offset: 0xF0 */ + __IO uint32_t APB4ENR; /*!< RCC APB4 peripheral clock register, Address offset: 0xF4 */ + uint32_t RESERVED12; /*!< Reserved, Address offset: 0xF8 */ + __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral sleep clock register, Address offset: 0xFC */ + __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral sleep clock register, Address offset: 0x100 */ + __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral sleep clock register, Address offset: 0x104 */ + __IO uint32_t AHB4LPENR; /*!< RCC AHB4 peripheral sleep clock register, Address offset: 0x108 */ + __IO uint32_t APB3LPENR; /*!< RCC APB3 peripheral sleep clock register, Address offset: 0x10C */ + __IO uint32_t APB1LLPENR; /*!< RCC APB1 peripheral sleep clock Low Word register, Address offset: 0x110 */ + __IO uint32_t APB1HLPENR; /*!< RCC APB1 peripheral sleep clock High Word register, Address offset: 0x114 */ + __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral sleep clock register, Address offset: 0x118 */ + __IO uint32_t APB4LPENR; /*!< RCC APB4 peripheral sleep clock register, Address offset: 0x11C */ + uint32_t RESERVED13[4]; /*!< Reserved, 0x120-0x12C Address offset: 0x120 */ + +} RCC_TypeDef; + + +/** + * @brief Real-Time Clock + */ +typedef struct +{ + __IO uint32_t TR; /*!< RTC time register, Address offset: 0x00 */ + __IO uint32_t DR; /*!< RTC date register, Address offset: 0x04 */ + __IO uint32_t CR; /*!< RTC control register, Address offset: 0x08 */ + __IO uint32_t ISR; /*!< RTC initialization and status register, Address offset: 0x0C */ + __IO uint32_t PRER; /*!< RTC prescaler register, Address offset: 0x10 */ + __IO uint32_t WUTR; /*!< RTC wakeup timer register, Address offset: 0x14 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t ALRMAR; /*!< RTC alarm A register, Address offset: 0x1C */ + __IO uint32_t ALRMBR; /*!< RTC alarm B register, Address offset: 0x20 */ + __IO uint32_t WPR; /*!< RTC write protection register, Address offset: 0x24 */ + __IO uint32_t SSR; /*!< RTC sub second register, Address offset: 0x28 */ + __IO uint32_t SHIFTR; /*!< RTC shift control register, Address offset: 0x2C */ + __IO uint32_t TSTR; /*!< RTC time stamp time register, Address offset: 0x30 */ + __IO uint32_t TSDR; /*!< RTC time stamp date register, Address offset: 0x34 */ + __IO uint32_t TSSSR; /*!< RTC time-stamp sub second register, Address offset: 0x38 */ + __IO uint32_t CALR; /*!< RTC calibration register, Address offset: 0x3C */ + __IO uint32_t TAMPCR; /*!< RTC tamper configuration register, Address offset: 0x40 */ + __IO uint32_t ALRMASSR; /*!< RTC alarm A sub second register, Address offset: 0x44 */ + __IO uint32_t ALRMBSSR; /*!< RTC alarm B sub second register, Address offset: 0x48 */ + __IO uint32_t OR; /*!< RTC option register, Address offset: 0x4C */ + __IO uint32_t BKP0R; /*!< RTC backup register 0, Address offset: 0x50 */ + __IO uint32_t BKP1R; /*!< RTC backup register 1, Address offset: 0x54 */ + __IO uint32_t BKP2R; /*!< RTC backup register 2, Address offset: 0x58 */ + __IO uint32_t BKP3R; /*!< RTC backup register 3, Address offset: 0x5C */ + __IO uint32_t BKP4R; /*!< RTC backup register 4, Address offset: 0x60 */ + __IO uint32_t BKP5R; /*!< RTC backup register 5, Address offset: 0x64 */ + __IO uint32_t BKP6R; /*!< RTC backup register 6, Address offset: 0x68 */ + __IO uint32_t BKP7R; /*!< RTC backup register 7, Address offset: 0x6C */ + __IO uint32_t BKP8R; /*!< RTC backup register 8, Address offset: 0x70 */ + __IO uint32_t BKP9R; /*!< RTC backup register 9, Address offset: 0x74 */ + __IO uint32_t BKP10R; /*!< RTC backup register 10, Address offset: 0x78 */ + __IO uint32_t BKP11R; /*!< RTC backup register 11, Address offset: 0x7C */ + __IO uint32_t BKP12R; /*!< RTC backup register 12, Address offset: 0x80 */ + __IO uint32_t BKP13R; /*!< RTC backup register 13, Address offset: 0x84 */ + __IO uint32_t BKP14R; /*!< RTC backup register 14, Address offset: 0x88 */ + __IO uint32_t BKP15R; /*!< RTC backup register 15, Address offset: 0x8C */ + __IO uint32_t BKP16R; /*!< RTC backup register 16, Address offset: 0x90 */ + __IO uint32_t BKP17R; /*!< RTC backup register 17, Address offset: 0x94 */ + __IO uint32_t BKP18R; /*!< RTC backup register 18, Address offset: 0x98 */ + __IO uint32_t BKP19R; /*!< RTC backup register 19, Address offset: 0x9C */ + __IO uint32_t BKP20R; /*!< RTC backup register 20, Address offset: 0xA0 */ + __IO uint32_t BKP21R; /*!< RTC backup register 21, Address offset: 0xA4 */ + __IO uint32_t BKP22R; /*!< RTC backup register 22, Address offset: 0xA8 */ + __IO uint32_t BKP23R; /*!< RTC backup register 23, Address offset: 0xAC */ + __IO uint32_t BKP24R; /*!< RTC backup register 24, Address offset: 0xB0 */ + __IO uint32_t BKP25R; /*!< RTC backup register 25, Address offset: 0xB4 */ + __IO uint32_t BKP26R; /*!< RTC backup register 26, Address offset: 0xB8 */ + __IO uint32_t BKP27R; /*!< RTC backup register 27, Address offset: 0xBC */ + __IO uint32_t BKP28R; /*!< RTC backup register 28, Address offset: 0xC0 */ + __IO uint32_t BKP29R; /*!< RTC backup register 29, Address offset: 0xC4 */ + __IO uint32_t BKP30R; /*!< RTC backup register 30, Address offset: 0xC8 */ + __IO uint32_t BKP31R; /*!< RTC backup register 31, Address offset: 0xCC */ +} RTC_TypeDef; + +/** + * @brief Serial Audio Interface + */ + +typedef struct +{ + __IO uint32_t GCR; /*!< SAI global configuration register, Address offset: 0x00 */ + uint32_t RESERVED0[16]; /*!< Reserved, 0x04 - 0x43 */ + __IO uint32_t PDMCR; /*!< SAI PDM control register, Address offset: 0x44 */ + __IO uint32_t PDMDLY; /*!< SAI PDM delay register, Address offset: 0x48 */ +} SAI_TypeDef; + +typedef struct +{ + __IO uint32_t CR1; /*!< SAI block x configuration register 1, Address offset: 0x04 */ + __IO uint32_t CR2; /*!< SAI block x configuration register 2, Address offset: 0x08 */ + __IO uint32_t FRCR; /*!< SAI block x frame configuration register, Address offset: 0x0C */ + __IO uint32_t SLOTR; /*!< SAI block x slot register, Address offset: 0x10 */ + __IO uint32_t IMR; /*!< SAI block x interrupt mask register, Address offset: 0x14 */ + __IO uint32_t SR; /*!< SAI block x status register, Address offset: 0x18 */ + __IO uint32_t CLRFR; /*!< SAI block x clear flag register, Address offset: 0x1C */ + __IO uint32_t DR; /*!< SAI block x data register, Address offset: 0x20 */ +} SAI_Block_TypeDef; + +/** + * @brief SPDIF-RX Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< Control register, Address offset: 0x00 */ + __IO uint32_t IMR; /*!< Interrupt mask register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< Status register, Address offset: 0x08 */ + __IO uint32_t IFCR; /*!< Interrupt Flag Clear register, Address offset: 0x0C */ + __IO uint32_t DR; /*!< Data input register, Address offset: 0x10 */ + __IO uint32_t CSR; /*!< Channel Status register, Address offset: 0x14 */ + __IO uint32_t DIR; /*!< Debug Information register, Address offset: 0x18 */ + uint32_t RESERVED2; /*!< Reserved, 0x1A */ +} SPDIFRX_TypeDef; + + +/** + * @brief Secure digital input/output Interface + */ + +typedef struct +{ + __IO uint32_t POWER; /*!< SDMMC power control register, Address offset: 0x00 */ + __IO uint32_t CLKCR; /*!< SDMMC clock control register, Address offset: 0x04 */ + __IO uint32_t ARG; /*!< SDMMC argument register, Address offset: 0x08 */ + __IO uint32_t CMD; /*!< SDMMC command register, Address offset: 0x0C */ + __I uint32_t RESPCMD; /*!< SDMMC command response register, Address offset: 0x10 */ + __I uint32_t RESP1; /*!< SDMMC response 1 register, Address offset: 0x14 */ + __I uint32_t RESP2; /*!< SDMMC response 2 register, Address offset: 0x18 */ + __I uint32_t RESP3; /*!< SDMMC response 3 register, Address offset: 0x1C */ + __I uint32_t RESP4; /*!< SDMMC response 4 register, Address offset: 0x20 */ + __IO uint32_t DTIMER; /*!< SDMMC data timer register, Address offset: 0x24 */ + __IO uint32_t DLEN; /*!< SDMMC data length register, Address offset: 0x28 */ + __IO uint32_t DCTRL; /*!< SDMMC data control register, Address offset: 0x2C */ + __I uint32_t DCOUNT; /*!< SDMMC data counter register, Address offset: 0x30 */ + __I uint32_t STA; /*!< SDMMC status register, Address offset: 0x34 */ + __IO uint32_t ICR; /*!< SDMMC interrupt clear register, Address offset: 0x38 */ + __IO uint32_t MASK; /*!< SDMMC mask register, Address offset: 0x3C */ + __IO uint32_t ACKTIME; /*!< SDMMC Acknowledgement timer register, Address offset: 0x40 */ + uint32_t RESERVED0[3]; /*!< Reserved, 0x44 - 0x4C - 0x4C */ + __IO uint32_t IDMACTRL; /*!< SDMMC DMA control register, Address offset: 0x50 */ + __IO uint32_t IDMABSIZE; /*!< SDMMC DMA buffer size register, Address offset: 0x54 */ + __IO uint32_t IDMABASE0; /*!< SDMMC DMA buffer 0 base address register, Address offset: 0x58 */ + __IO uint32_t IDMABASE1; /*!< SDMMC DMA buffer 1 base address register, Address offset: 0x5C */ + uint32_t RESERVED1[8]; /*!< Reserved, 0x60-0x7C */ + __IO uint32_t FIFO; /*!< SDMMC data FIFO register, Address offset: 0x80 */ + uint32_t RESERVED2[222]; /*!< Reserved, 0x84-0x3F8 */ + __IO uint32_t IPVR; /*!< SDMMC data FIFO register, Address offset: 0x3FC */ +} SDMMC_TypeDef; + + +/** + * @brief Delay Block DLYB + */ + +typedef struct +{ + __IO uint32_t CR; /*!< DELAY BLOCK control register, Address offset: 0x00 */ + __IO uint32_t CFGR; /*!< DELAY BLOCK configuration register, Address offset: 0x04 */ +} DLYB_TypeDef; + +/** + * @brief HW Semaphore HSEM + */ + +typedef struct +{ + __IO uint32_t R[32]; /*!< 2-step write lock and read back registers, Address offset: 00h-7Ch */ + __IO uint32_t RLR[32]; /*!< 1-step read lock registers, Address offset: 80h-FCh */ + __IO uint32_t C1IER; /*!< HSEM Interrupt enable register , Address offset: 100h */ + __IO uint32_t C1ICR; /*!< HSEM Interrupt clear register , Address offset: 104h */ + __IO uint32_t C1ISR; /*!< HSEM Interrupt Status register , Address offset: 108h */ + __IO uint32_t C1MISR; /*!< HSEM Interrupt Masked Status register , Address offset: 10Ch */ + uint32_t Reserved[12]; /* Reserved Address offset: 110h-13Ch */ + __IO uint32_t CR; /*!< HSEM Semaphore clear register , Address offset: 140h */ + __IO uint32_t KEYR; /*!< HSEM Semaphore clear key register , Address offset: 144h */ + +} HSEM_TypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< HSEM interrupt enable register , Address offset: 0h */ + __IO uint32_t ICR; /*!< HSEM interrupt clear register , Address offset: 4h */ + __IO uint32_t ISR; /*!< HSEM interrupt status register , Address offset: 8h */ + __IO uint32_t MISR; /*!< HSEM masked interrupt status register , Address offset: Ch */ +} HSEM_Common_TypeDef; + +/** + * @brief Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< SPI/I2S Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< SPI Control register 2, Address offset: 0x04 */ + __IO uint32_t CFG1; /*!< SPI Configuration register 1, Address offset: 0x08 */ + __IO uint32_t CFG2; /*!< SPI Configuration register 2, Address offset: 0x0C */ + __IO uint32_t IER; /*!< SPI/I2S Interrupt Enable register, Address offset: 0x10 */ + __IO uint32_t SR; /*!< SPI/I2S Status register, Address offset: 0x14 */ + __IO uint32_t IFCR; /*!< SPI/I2S Interrupt/Status flags clear register, Address offset: 0x18 */ + uint32_t RESERVED0; /*!< Reserved, 0x1C */ + __IO uint32_t TXDR; /*!< SPI/I2S Transmit data register, Address offset: 0x20 */ + uint32_t RESERVED1[3]; /*!< Reserved, 0x24-0x2C */ + __IO uint32_t RXDR; /*!< SPI/I2S Receive data register, Address offset: 0x30 */ + uint32_t RESERVED2[3]; /*!< Reserved, 0x34-0x3C */ + __IO uint32_t CRCPOLY; /*!< SPI CRC Polynomial register, Address offset: 0x40 */ + __IO uint32_t TXCRC; /*!< SPI Transmitter CRC register, Address offset: 0x44 */ + __IO uint32_t RXCRC; /*!< SPI Receiver CRC register, Address offset: 0x48 */ + __IO uint32_t UDRDR; /*!< SPI Underrun data register, Address offset: 0x4C */ + __IO uint32_t I2SCFGR; /*!< I2S Configuration register, Address offset: 0x50 */ + +} SPI_TypeDef; + +/** + * @brief DTS + */ +typedef struct +{ + __IO uint32_t CFGR1; /*!< DTS configuration register, Address offset: 0x00 */ + uint32_t RESERVED0; /*!< Reserved, Address offset: 0x04 */ + __IO uint32_t T0VALR1; /*!< DTS T0 Value register, Address offset: 0x08 */ + uint32_t RESERVED1; /*!< Reserved, Address offset: 0x0C */ + __IO uint32_t RAMPVALR; /*!< DTS Ramp value register, Address offset: 0x10 */ + __IO uint32_t ITR1; /*!< DTS Interrupt threshold register, Address offset: 0x14 */ + uint32_t RESERVED2; /*!< Reserved, Address offset: 0x18 */ + __IO uint32_t DR; /*!< DTS data register, Address offset: 0x1C */ + __IO uint32_t SR; /*!< DTS status register Address offset: 0x20 */ + __IO uint32_t ITENR; /*!< DTS Interrupt enable register, Address offset: 0x24 */ + __IO uint32_t ICIFR; /*!< DTS Clear Interrupt flag register, Address offset: 0x28 */ + __IO uint32_t OR; /*!< DTS option register 1, Address offset: 0x2C */ +} +DTS_TypeDef; + +/** + * @brief TIM + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */ + __IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ + __IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ + __IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ + __IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ + __IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ + __IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ + __IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ + __IO uint32_t CNT; /*!< TIM counter register, Address offset: 0x24 */ + __IO uint32_t PSC; /*!< TIM prescaler, Address offset: 0x28 */ + __IO uint32_t ARR; /*!< TIM auto-reload register, Address offset: 0x2C */ + __IO uint32_t RCR; /*!< TIM repetition counter register, Address offset: 0x30 */ + __IO uint32_t CCR1; /*!< TIM capture/compare register 1, Address offset: 0x34 */ + __IO uint32_t CCR2; /*!< TIM capture/compare register 2, Address offset: 0x38 */ + __IO uint32_t CCR3; /*!< TIM capture/compare register 3, Address offset: 0x3C */ + __IO uint32_t CCR4; /*!< TIM capture/compare register 4, Address offset: 0x40 */ + __IO uint32_t BDTR; /*!< TIM break and dead-time register, Address offset: 0x44 */ + __IO uint32_t DCR; /*!< TIM DMA control register, Address offset: 0x48 */ + __IO uint32_t DMAR; /*!< TIM DMA address for full transfer, Address offset: 0x4C */ + uint32_t RESERVED1; /*!< Reserved, 0x50 */ + __IO uint32_t CCMR3; /*!< TIM capture/compare mode register 3, Address offset: 0x54 */ + __IO uint32_t CCR5; /*!< TIM capture/compare register5, Address offset: 0x58 */ + __IO uint32_t CCR6; /*!< TIM capture/compare register6, Address offset: 0x5C */ + __IO uint32_t AF1; /*!< TIM alternate function option register 1, Address offset: 0x60 */ + __IO uint32_t AF2; /*!< TIM alternate function option register 2, Address offset: 0x64 */ + __IO uint32_t TISEL; /*!< TIM Input Selection register, Address offset: 0x68 */ +} TIM_TypeDef; + +/** + * @brief LPTIMIMER + */ +typedef struct +{ + __IO uint32_t ISR; /*!< LPTIM Interrupt and Status register, Address offset: 0x00 */ + __IO uint32_t ICR; /*!< LPTIM Interrupt Clear register, Address offset: 0x04 */ + __IO uint32_t IER; /*!< LPTIM Interrupt Enable register, Address offset: 0x08 */ + __IO uint32_t CFGR; /*!< LPTIM Configuration register, Address offset: 0x0C */ + __IO uint32_t CR; /*!< LPTIM Control register, Address offset: 0x10 */ + __IO uint32_t CMP; /*!< LPTIM Compare register, Address offset: 0x14 */ + __IO uint32_t ARR; /*!< LPTIM Autoreload register, Address offset: 0x18 */ + __IO uint32_t CNT; /*!< LPTIM Counter register, Address offset: 0x1C */ + uint32_t RESERVED1; /*!< Reserved, 0x20 */ + __IO uint32_t CFGR2; /*!< LPTIM Configuration register, Address offset: 0x24 */ +} LPTIM_TypeDef; + +/** + * @brief Comparator + */ +typedef struct +{ + __IO uint32_t SR; /*!< Comparator status register, Address offset: 0x00 */ + __IO uint32_t ICFR; /*!< Comparator interrupt clear flag register, Address offset: 0x04 */ + __IO uint32_t OR; /*!< Comparator option register, Address offset: 0x08 */ +} COMPOPT_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< Comparator configuration register , Address offset: 0x00 */ +} COMP_TypeDef; + +typedef struct +{ + __IO uint32_t CFGR; /*!< COMP control and status register, used for bits common to several COMP instances, Address offset: 0x00 */ +} COMP_Common_TypeDef; +/** + * @brief Universal Synchronous Asynchronous Receiver Transmitter + */ + +typedef struct +{ + __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ + __IO uint32_t CR2; /*!< USART Control register 2, Address offset: 0x04 */ + __IO uint32_t CR3; /*!< USART Control register 3, Address offset: 0x08 */ + __IO uint32_t BRR; /*!< USART Baud rate register, Address offset: 0x0C */ + __IO uint32_t GTPR; /*!< USART Guard time and prescaler register, Address offset: 0x10 */ + __IO uint32_t RTOR; /*!< USART Receiver Time Out register, Address offset: 0x14 */ + __IO uint32_t RQR; /*!< USART Request register, Address offset: 0x18 */ + __IO uint32_t ISR; /*!< USART Interrupt and status register, Address offset: 0x1C */ + __IO uint32_t ICR; /*!< USART Interrupt flag Clear register, Address offset: 0x20 */ + __IO uint32_t RDR; /*!< USART Receive Data register, Address offset: 0x24 */ + __IO uint32_t TDR; /*!< USART Transmit Data register, Address offset: 0x28 */ + __IO uint32_t PRESC; /*!< USART clock Prescaler register, Address offset: 0x2C */ +} USART_TypeDef; + +/** + * @brief Single Wire Protocol Master Interface SPWMI + */ +typedef struct +{ + __IO uint32_t CR; /*!< SWPMI Configuration/Control register, Address offset: 0x00 */ + __IO uint32_t BRR; /*!< SWPMI bitrate register, Address offset: 0x04 */ + uint32_t RESERVED1; /*!< Reserved, 0x08 */ + __IO uint32_t ISR; /*!< SWPMI Interrupt and Status register, Address offset: 0x0C */ + __IO uint32_t ICR; /*!< SWPMI Interrupt Flag Clear register, Address offset: 0x10 */ + __IO uint32_t IER; /*!< SWPMI Interrupt Enable register, Address offset: 0x14 */ + __IO uint32_t RFL; /*!< SWPMI Receive Frame Length register, Address offset: 0x18 */ + __IO uint32_t TDR; /*!< SWPMI Transmit data register, Address offset: 0x1C */ + __IO uint32_t RDR; /*!< SWPMI Receive data register, Address offset: 0x20 */ + __IO uint32_t OR; /*!< SWPMI Option register, Address offset: 0x24 */ +} SWPMI_TypeDef; + +/** + * @brief Window WATCHDOG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< WWDG Control register, Address offset: 0x00 */ + __IO uint32_t CFR; /*!< WWDG Configuration register, Address offset: 0x04 */ + __IO uint32_t SR; /*!< WWDG Status register, Address offset: 0x08 */ +} WWDG_TypeDef; + + +/** + * @brief RAM_ECC_Specific_Registers + */ +typedef struct +{ + __IO uint32_t CR; /*!< RAMECC monitor configuration register */ + __IO uint32_t SR; /*!< RAMECC monitor status register */ + __IO uint32_t FAR; /*!< RAMECC monitor failing address register */ + __IO uint32_t FDRL; /*!< RAMECC monitor failing data low register */ + __IO uint32_t FDRH; /*!< RAMECC monitor failing data high register */ + __IO uint32_t FECR; /*!< RAMECC monitor failing ECC error code register */ +} RAMECC_MonitorTypeDef; + +typedef struct +{ + __IO uint32_t IER; /*!< RAMECC interrupt enable register */ +} RAMECC_TypeDef; +/** + * @} + */ + + +/** + * @brief Crypto Processor + */ + +typedef struct +{ + __IO uint32_t CR; /*!< CRYP control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< CRYP status register, Address offset: 0x04 */ + __IO uint32_t DIN; /*!< CRYP data input register, Address offset: 0x08 */ + __IO uint32_t DOUT; /*!< CRYP data output register, Address offset: 0x0C */ + __IO uint32_t DMACR; /*!< CRYP DMA control register, Address offset: 0x10 */ + __IO uint32_t IMSCR; /*!< CRYP interrupt mask set/clear register, Address offset: 0x14 */ + __IO uint32_t RISR; /*!< CRYP raw interrupt status register, Address offset: 0x18 */ + __IO uint32_t MISR; /*!< CRYP masked interrupt status register, Address offset: 0x1C */ + __IO uint32_t K0LR; /*!< CRYP key left register 0, Address offset: 0x20 */ + __IO uint32_t K0RR; /*!< CRYP key right register 0, Address offset: 0x24 */ + __IO uint32_t K1LR; /*!< CRYP key left register 1, Address offset: 0x28 */ + __IO uint32_t K1RR; /*!< CRYP key right register 1, Address offset: 0x2C */ + __IO uint32_t K2LR; /*!< CRYP key left register 2, Address offset: 0x30 */ + __IO uint32_t K2RR; /*!< CRYP key right register 2, Address offset: 0x34 */ + __IO uint32_t K3LR; /*!< CRYP key left register 3, Address offset: 0x38 */ + __IO uint32_t K3RR; /*!< CRYP key right register 3, Address offset: 0x3C */ + __IO uint32_t IV0LR; /*!< CRYP initialization vector left-word register 0, Address offset: 0x40 */ + __IO uint32_t IV0RR; /*!< CRYP initialization vector right-word register 0, Address offset: 0x44 */ + __IO uint32_t IV1LR; /*!< CRYP initialization vector left-word register 1, Address offset: 0x48 */ + __IO uint32_t IV1RR; /*!< CRYP initialization vector right-word register 1, Address offset: 0x4C */ + __IO uint32_t CSGCMCCM0R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 0, Address offset: 0x50 */ + __IO uint32_t CSGCMCCM1R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 1, Address offset: 0x54 */ + __IO uint32_t CSGCMCCM2R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 2, Address offset: 0x58 */ + __IO uint32_t CSGCMCCM3R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 3, Address offset: 0x5C */ + __IO uint32_t CSGCMCCM4R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 4, Address offset: 0x60 */ + __IO uint32_t CSGCMCCM5R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 5, Address offset: 0x64 */ + __IO uint32_t CSGCMCCM6R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 6, Address offset: 0x68 */ + __IO uint32_t CSGCMCCM7R; /*!< CRYP GCM/GMAC or CCM/CMAC context swap register 7, Address offset: 0x6C */ + __IO uint32_t CSGCM0R; /*!< CRYP GCM/GMAC context swap register 0, Address offset: 0x70 */ + __IO uint32_t CSGCM1R; /*!< CRYP GCM/GMAC context swap register 1, Address offset: 0x74 */ + __IO uint32_t CSGCM2R; /*!< CRYP GCM/GMAC context swap register 2, Address offset: 0x78 */ + __IO uint32_t CSGCM3R; /*!< CRYP GCM/GMAC context swap register 3, Address offset: 0x7C */ + __IO uint32_t CSGCM4R; /*!< CRYP GCM/GMAC context swap register 4, Address offset: 0x80 */ + __IO uint32_t CSGCM5R; /*!< CRYP GCM/GMAC context swap register 5, Address offset: 0x84 */ + __IO uint32_t CSGCM6R; /*!< CRYP GCM/GMAC context swap register 6, Address offset: 0x88 */ + __IO uint32_t CSGCM7R; /*!< CRYP GCM/GMAC context swap register 7, Address offset: 0x8C */ +} CRYP_TypeDef; + +/** + * @brief HASH + */ + +typedef struct +{ + __IO uint32_t CR; /*!< HASH control register, Address offset: 0x00 */ + __IO uint32_t DIN; /*!< HASH data input register, Address offset: 0x04 */ + __IO uint32_t STR; /*!< HASH start register, Address offset: 0x08 */ + __IO uint32_t HR[5]; /*!< HASH digest registers, Address offset: 0x0C-0x1C */ + __IO uint32_t IMR; /*!< HASH interrupt enable register, Address offset: 0x20 */ + __IO uint32_t SR; /*!< HASH status register, Address offset: 0x24 */ + uint32_t RESERVED[52]; /*!< Reserved, 0x28-0xF4 */ + __IO uint32_t CSR[54]; /*!< HASH context swap registers, Address offset: 0x0F8-0x1CC */ +} HASH_TypeDef; + +/** + * @brief HASH_DIGEST + */ + +typedef struct +{ + __IO uint32_t HR[8]; /*!< HASH digest registers, Address offset: 0x310-0x32C */ +} HASH_DIGEST_TypeDef; + + +/** + * @brief RNG + */ + +typedef struct +{ + __IO uint32_t CR; /*!< RNG control register, Address offset: 0x00 */ + __IO uint32_t SR; /*!< RNG status register, Address offset: 0x04 */ + __IO uint32_t DR; /*!< RNG data register, Address offset: 0x08 */ + uint32_t RESERVED; + __IO uint32_t HTCR; /*!< RNG health test configuration register, Address offset: 0x10 */ +} RNG_TypeDef; + +/** + * @brief MDIOS + */ + +typedef struct +{ + __IO uint32_t CR; + __IO uint32_t WRFR; + __IO uint32_t CWRFR; + __IO uint32_t RDFR; + __IO uint32_t CRDFR; + __IO uint32_t SR; + __IO uint32_t CLRFR; + uint32_t RESERVED[57]; + __IO uint32_t DINR0; + __IO uint32_t DINR1; + __IO uint32_t DINR2; + __IO uint32_t DINR3; + __IO uint32_t DINR4; + __IO uint32_t DINR5; + __IO uint32_t DINR6; + __IO uint32_t DINR7; + __IO uint32_t DINR8; + __IO uint32_t DINR9; + __IO uint32_t DINR10; + __IO uint32_t DINR11; + __IO uint32_t DINR12; + __IO uint32_t DINR13; + __IO uint32_t DINR14; + __IO uint32_t DINR15; + __IO uint32_t DINR16; + __IO uint32_t DINR17; + __IO uint32_t DINR18; + __IO uint32_t DINR19; + __IO uint32_t DINR20; + __IO uint32_t DINR21; + __IO uint32_t DINR22; + __IO uint32_t DINR23; + __IO uint32_t DINR24; + __IO uint32_t DINR25; + __IO uint32_t DINR26; + __IO uint32_t DINR27; + __IO uint32_t DINR28; + __IO uint32_t DINR29; + __IO uint32_t DINR30; + __IO uint32_t DINR31; + __IO uint32_t DOUTR0; + __IO uint32_t DOUTR1; + __IO uint32_t DOUTR2; + __IO uint32_t DOUTR3; + __IO uint32_t DOUTR4; + __IO uint32_t DOUTR5; + __IO uint32_t DOUTR6; + __IO uint32_t DOUTR7; + __IO uint32_t DOUTR8; + __IO uint32_t DOUTR9; + __IO uint32_t DOUTR10; + __IO uint32_t DOUTR11; + __IO uint32_t DOUTR12; + __IO uint32_t DOUTR13; + __IO uint32_t DOUTR14; + __IO uint32_t DOUTR15; + __IO uint32_t DOUTR16; + __IO uint32_t DOUTR17; + __IO uint32_t DOUTR18; + __IO uint32_t DOUTR19; + __IO uint32_t DOUTR20; + __IO uint32_t DOUTR21; + __IO uint32_t DOUTR22; + __IO uint32_t DOUTR23; + __IO uint32_t DOUTR24; + __IO uint32_t DOUTR25; + __IO uint32_t DOUTR26; + __IO uint32_t DOUTR27; + __IO uint32_t DOUTR28; + __IO uint32_t DOUTR29; + __IO uint32_t DOUTR30; + __IO uint32_t DOUTR31; +} MDIOS_TypeDef; + + +/** + * @brief USB_OTG_Core_Registers + */ +typedef struct +{ + __IO uint32_t GOTGCTL; /*!< USB_OTG Control and Status Register 000h */ + __IO uint32_t GOTGINT; /*!< USB_OTG Interrupt Register 004h */ + __IO uint32_t GAHBCFG; /*!< Core AHB Configuration Register 008h */ + __IO uint32_t GUSBCFG; /*!< Core USB Configuration Register 00Ch */ + __IO uint32_t GRSTCTL; /*!< Core Reset Register 010h */ + __IO uint32_t GINTSTS; /*!< Core Interrupt Register 014h */ + __IO uint32_t GINTMSK; /*!< Core Interrupt Mask Register 018h */ + __IO uint32_t GRXSTSR; /*!< Receive Sts Q Read Register 01Ch */ + __IO uint32_t GRXSTSP; /*!< Receive Sts Q Read & POP Register 020h */ + __IO uint32_t GRXFSIZ; /*!< Receive FIFO Size Register 024h */ + __IO uint32_t DIEPTXF0_HNPTXFSIZ; /*!< EP0 / Non Periodic Tx FIFO Size Register 028h */ + __IO uint32_t HNPTXSTS; /*!< Non Periodic Tx FIFO/Queue Sts reg 02Ch */ + uint32_t Reserved30[2]; /*!< Reserved 030h */ + __IO uint32_t GCCFG; /*!< General Purpose IO Register 038h */ + __IO uint32_t CID; /*!< User ID Register 03Ch */ + __IO uint32_t GSNPSID; /* USB_OTG core ID 040h*/ + __IO uint32_t GHWCFG1; /* User HW config1 044h*/ + __IO uint32_t GHWCFG2; /* User HW config2 048h*/ + __IO uint32_t GHWCFG3; /*!< User HW config3 04Ch */ + uint32_t Reserved6; /*!< Reserved 050h */ + __IO uint32_t GLPMCFG; /*!< LPM Register 054h */ + __IO uint32_t GPWRDN; /*!< Power Down Register 058h */ + __IO uint32_t GDFIFOCFG; /*!< DFIFO Software Config Register 05Ch */ + __IO uint32_t GADPCTL; /*!< ADP Timer, Control and Status Register 60Ch */ + uint32_t Reserved43[39]; /*!< Reserved 058h-0FFh */ + __IO uint32_t HPTXFSIZ; /*!< Host Periodic Tx FIFO Size Reg 100h */ + __IO uint32_t DIEPTXF[0x0F]; /*!< dev Periodic Transmit FIFO */ +} USB_OTG_GlobalTypeDef; + + +/** + * @brief USB_OTG_device_Registers + */ +typedef struct +{ + __IO uint32_t DCFG; /*!< dev Configuration Register 800h */ + __IO uint32_t DCTL; /*!< dev Control Register 804h */ + __IO uint32_t DSTS; /*!< dev Status Register (RO) 808h */ + uint32_t Reserved0C; /*!< Reserved 80Ch */ + __IO uint32_t DIEPMSK; /*!< dev IN Endpoint Mask 810h */ + __IO uint32_t DOEPMSK; /*!< dev OUT Endpoint Mask 814h */ + __IO uint32_t DAINT; /*!< dev All Endpoints Itr Reg 818h */ + __IO uint32_t DAINTMSK; /*!< dev All Endpoints Itr Mask 81Ch */ + uint32_t Reserved20; /*!< Reserved 820h */ + uint32_t Reserved9; /*!< Reserved 824h */ + __IO uint32_t DVBUSDIS; /*!< dev VBUS discharge Register 828h */ + __IO uint32_t DVBUSPULSE; /*!< dev VBUS Pulse Register 82Ch */ + __IO uint32_t DTHRCTL; /*!< dev threshold 830h */ + __IO uint32_t DIEPEMPMSK; /*!< dev empty msk 834h */ + __IO uint32_t DEACHINT; /*!< dedicated EP interrupt 838h */ + __IO uint32_t DEACHMSK; /*!< dedicated EP msk 83Ch */ + uint32_t Reserved40; /*!< dedicated EP mask 840h */ + __IO uint32_t DINEP1MSK; /*!< dedicated EP mask 844h */ + uint32_t Reserved44[15]; /*!< Reserved 844-87Ch */ + __IO uint32_t DOUTEP1MSK; /*!< dedicated EP msk 884h */ +} USB_OTG_DeviceTypeDef; + + +/** + * @brief USB_OTG_IN_Endpoint-Specific_Register + */ +typedef struct +{ + __IO uint32_t DIEPCTL; /*!< dev IN Endpoint Control Reg 900h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved 900h + (ep_num * 20h) + 04h */ + __IO uint32_t DIEPINT; /*!< dev IN Endpoint Itr Reg 900h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved 900h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DIEPTSIZ; /*!< IN Endpoint Txfer Size 900h + (ep_num * 20h) + 10h */ + __IO uint32_t DIEPDMA; /*!< IN Endpoint DMA Address Reg 900h + (ep_num * 20h) + 14h */ + __IO uint32_t DTXFSTS; /*!< IN Endpoint Tx FIFO Status Reg 900h + (ep_num * 20h) + 18h */ + uint32_t Reserved18; /*!< Reserved 900h+(ep_num*20h)+1Ch-900h+ (ep_num * 20h) + 1Ch */ +} USB_OTG_INEndpointTypeDef; + + +/** + * @brief USB_OTG_OUT_Endpoint-Specific_Registers + */ +typedef struct +{ + __IO uint32_t DOEPCTL; /*!< dev OUT Endpoint Control Reg B00h + (ep_num * 20h) + 00h */ + uint32_t Reserved04; /*!< Reserved B00h + (ep_num * 20h) + 04h */ + __IO uint32_t DOEPINT; /*!< dev OUT Endpoint Itr Reg B00h + (ep_num * 20h) + 08h */ + uint32_t Reserved0C; /*!< Reserved B00h + (ep_num * 20h) + 0Ch */ + __IO uint32_t DOEPTSIZ; /*!< dev OUT Endpoint Txfer Size B00h + (ep_num * 20h) + 10h */ + __IO uint32_t DOEPDMA; /*!< dev OUT Endpoint DMA Address B00h + (ep_num * 20h) + 14h */ + uint32_t Reserved18[2]; /*!< Reserved B00h + (ep_num * 20h) + 18h - B00h + (ep_num * 20h) + 1Ch */ +} USB_OTG_OUTEndpointTypeDef; + + +/** + * @brief USB_OTG_Host_Mode_Register_Structures + */ +typedef struct +{ + __IO uint32_t HCFG; /*!< Host Configuration Register 400h */ + __IO uint32_t HFIR; /*!< Host Frame Interval Register 404h */ + __IO uint32_t HFNUM; /*!< Host Frame Nbr/Frame Remaining 408h */ + uint32_t Reserved40C; /*!< Reserved 40Ch */ + __IO uint32_t HPTXSTS; /*!< Host Periodic Tx FIFO/ Queue Status 410h */ + __IO uint32_t HAINT; /*!< Host All Channels Interrupt Register 414h */ + __IO uint32_t HAINTMSK; /*!< Host All Channels Interrupt Mask 418h */ +} USB_OTG_HostTypeDef; + +/** + * @brief USB_OTG_Host_Channel_Specific_Registers + */ +typedef struct +{ + __IO uint32_t HCCHAR; /*!< Host Channel Characteristics Register 500h */ + __IO uint32_t HCSPLT; /*!< Host Channel Split Control Register 504h */ + __IO uint32_t HCINT; /*!< Host Channel Interrupt Register 508h */ + __IO uint32_t HCINTMSK; /*!< Host Channel Interrupt Mask Register 50Ch */ + __IO uint32_t HCTSIZ; /*!< Host Channel Transfer Size Register 510h */ + __IO uint32_t HCDMA; /*!< Host Channel DMA Address Register 514h */ + uint32_t Reserved[2]; /*!< Reserved */ +} USB_OTG_HostChannelTypeDef; +/** + * @} + */ + +/** + * @brief OCTO Serial Peripheral Interface + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI Control register, Address offset: 0x000 */ + uint32_t RESERVED; /*!< Reserved, Address offset: 0x004 */ + __IO uint32_t DCR1; /*!< OCTOSPI Device Configuration register 1, Address offset: 0x008 */ + __IO uint32_t DCR2; /*!< OCTOSPI Device Configuration register 2, Address offset: 0x00C */ + __IO uint32_t DCR3; /*!< OCTOSPI Device Configuration register 3, Address offset: 0x010 */ + __IO uint32_t DCR4; /*!< OCTOSPI Device Configuration register 4, Address offset: 0x014 */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x018-0x01C */ + __IO uint32_t SR; /*!< OCTOSPI Status register, Address offset: 0x020 */ + __IO uint32_t FCR; /*!< OCTOSPI Flag Clear register, Address offset: 0x024 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x028-0x03C */ + __IO uint32_t DLR; /*!< OCTOSPI Data Length register, Address offset: 0x040 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x044 */ + __IO uint32_t AR; /*!< OCTOSPI Address register, Address offset: 0x048 */ + uint32_t RESERVED4; /*!< Reserved, Address offset: 0x04C */ + __IO uint32_t DR; /*!< OCTOSPI Data register, Address offset: 0x050 */ + uint32_t RESERVED5[11]; /*!< Reserved, Address offset: 0x054-0x07C */ + __IO uint32_t PSMKR; /*!< OCTOSPI Polling Status Mask register, Address offset: 0x080 */ + uint32_t RESERVED6; /*!< Reserved, Address offset: 0x084 */ + __IO uint32_t PSMAR; /*!< OCTOSPI Polling Status Match register, Address offset: 0x088 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x08C */ + __IO uint32_t PIR; /*!< OCTOSPI Polling Interval register, Address offset: 0x090 */ + uint32_t RESERVED8[27]; /*!< Reserved, Address offset: 0x094-0x0FC */ + __IO uint32_t CCR; /*!< OCTOSPI Communication Configuration register, Address offset: 0x100 */ + uint32_t RESERVED9; /*!< Reserved, Address offset: 0x104 */ + __IO uint32_t TCR; /*!< OCTOSPI Timing Configuration register, Address offset: 0x108 */ + uint32_t RESERVED10; /*!< Reserved, Address offset: 0x10C */ + __IO uint32_t IR; /*!< OCTOSPI Instruction register, Address offset: 0x110 */ + uint32_t RESERVED11[3]; /*!< Reserved, Address offset: 0x114-0x11C */ + __IO uint32_t ABR; /*!< OCTOSPI Alternate Bytes register, Address offset: 0x120 */ + uint32_t RESERVED12[3]; /*!< Reserved, Address offset: 0x124-0x12C */ + __IO uint32_t LPTR; /*!< OCTOSPI Low Power Timeout register, Address offset: 0x130 */ + uint32_t RESERVED13[3]; /*!< Reserved, Address offset: 0x134-0x13C */ + __IO uint32_t WPCCR; /*!< OCTOSPI Wrap Communication Configuration register, Address offset: 0x140 */ + uint32_t RESERVED14; /*!< Reserved, Address offset: 0x144 */ + __IO uint32_t WPTCR; /*!< OCTOSPI Wrap Timing Configuration register, Address offset: 0x148 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x14C */ + __IO uint32_t WPIR; /*!< OCTOSPI Wrap Instruction register, Address offset: 0x150 */ + uint32_t RESERVED16[3]; /*!< Reserved, Address offset: 0x154-0x15C */ + __IO uint32_t WPABR; /*!< OCTOSPI Wrap Alternate Bytes register, Address offset: 0x160 */ + uint32_t RESERVED17[7]; /*!< Reserved, Address offset: 0x164-0x17C */ + __IO uint32_t WCCR; /*!< OCTOSPI Write Communication Configuration register, Address offset: 0x180 */ + uint32_t RESERVED18; /*!< Reserved, Address offset: 0x184 */ + __IO uint32_t WTCR; /*!< OCTOSPI Write Timing Configuration register, Address offset: 0x188 */ + uint32_t RESERVED19; /*!< Reserved, Address offset: 0x18C */ + __IO uint32_t WIR; /*!< OCTOSPI Write Instruction register, Address offset: 0x190 */ + uint32_t RESERVED20[3]; /*!< Reserved, Address offset: 0x194-0x19C */ + __IO uint32_t WABR; /*!< OCTOSPI Write Alternate Bytes register, Address offset: 0x1A0 */ + uint32_t RESERVED21[23]; /*!< Reserved, Address offset: 0x1A4-0x1FC */ + __IO uint32_t HLCR; /*!< OCTOSPI Hyperbus Latency Configuration register, Address offset: 0x200 */ + uint32_t RESERVED22[122]; /*!< Reserved, Address offset: 0x204-0x3EC */ + __IO uint32_t HWCFGR; /*!< OCTOSPI HW Configuration register, Address offset: 0x3F0 */ + __IO uint32_t VER; /*!< OCTOSPI Version register, Address offset: 0x3F4 */ + __IO uint32_t ID; /*!< OCTOSPI Identification register, Address offset: 0x3F8 */ + __IO uint32_t MID; /*!< OCTOPSI HW Magic ID register, Address offset: 0x3FC */ +} OCTOSPI_TypeDef; + +/** + * @} + */ +/** + * @brief OCTO Serial Peripheral Interface IO Manager + */ + +typedef struct +{ + __IO uint32_t CR; /*!< OCTOSPI IO Manager Control register, Address offset: 0x00 */ + __IO uint32_t PCR[3]; /*!< OCTOSPI IO Manager Port[1:3] Configuration register, Address offset: 0x04-0x20 */ +} OCTOSPIM_TypeDef; + +/** + * @} + */ + +/** + * @brief OTFD register + */ +typedef struct +{ + __IO uint32_t REG_CONFIGR; + __IO uint32_t REG_START_ADDR; + __IO uint32_t REG_END_ADDR; + __IO uint32_t REG_NONCER0; + __IO uint32_t REG_NONCER1; + __IO uint32_t REG_KEYR0; + __IO uint32_t REG_KEYR1; + __IO uint32_t REG_KEYR2; + __IO uint32_t REG_KEYR3; +} OTFDEC_Region_TypeDef; + +typedef struct +{ + __IO uint32_t CR; + uint32_t RESERVED1[191]; + __IO uint32_t ISR; + __IO uint32_t ICR; + __IO uint32_t IER; + uint32_t RESERVED2[56]; + __IO uint32_t HWCFGR2; + __IO uint32_t HWCFGR1; + __IO uint32_t VERR; + __IO uint32_t IPIDR; + __IO uint32_t SIDR; +} OTFDEC_TypeDef; +/** + * @} + */ + +/** + * @brief Global Programmer View + */ + +typedef struct +{ + uint32_t RESERVED0[2036]; /*!< Reserved, Address offset: 0x00-0x1FCC */ + __IO uint32_t AXI_PERIPH_ID_4; /*!< AXI interconnect - peripheral ID4 register, Address offset: 0x1FD0 */ + uint32_t AXI_PERIPH_ID_5; /*!< Reserved, Address offset: 0x1FD4 */ + uint32_t AXI_PERIPH_ID_6; /*!< Reserved, Address offset: 0x1FD8 */ + uint32_t AXI_PERIPH_ID_7; /*!< Reserved, Address offset: 0x1FDC */ + __IO uint32_t AXI_PERIPH_ID_0; /*!< AXI interconnect - peripheral ID0 register, Address offset: 0x1FE0 */ + __IO uint32_t AXI_PERIPH_ID_1; /*!< AXI interconnect - peripheral ID1 register, Address offset: 0x1FE4 */ + __IO uint32_t AXI_PERIPH_ID_2; /*!< AXI interconnect - peripheral ID2 register, Address offset: 0x1FE8 */ + __IO uint32_t AXI_PERIPH_ID_3; /*!< AXI interconnect - peripheral ID3 register, Address offset: 0x1FEC */ + __IO uint32_t AXI_COMP_ID_0; /*!< AXI interconnect - component ID0 register, Address offset: 0x1FF0 */ + __IO uint32_t AXI_COMP_ID_1; /*!< AXI interconnect - component ID1 register, Address offset: 0x1FF4 */ + __IO uint32_t AXI_COMP_ID_2; /*!< AXI interconnect - component ID2 register, Address offset: 0x1FF8 */ + __IO uint32_t AXI_COMP_ID_3; /*!< AXI interconnect - component ID3 register, Address offset: 0x1FFC */ + uint32_t RESERVED1[2]; /*!< Reserved, Address offset: 0x2000-0x2004 */ + __IO uint32_t AXI_TARG1_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 1 bus matrix issuing functionality register, Address offset: 0x2008 */ + uint32_t RESERVED2[6]; /*!< Reserved, Address offset: 0x200C-0x2020 */ + __IO uint32_t AXI_TARG1_FN_MOD2; /*!< AXI interconnect - TARG 1 bus matrix functionality 2 register, Address offset: 0x2024 */ + uint32_t RESERVED3; /*!< Reserved, Address offset: 0x2028 */ + __IO uint32_t AXI_TARG1_FN_MOD_LB; /*!< AXI interconnect - TARG 1 long burst functionality modification register, Address offset: 0x202C */ + uint32_t RESERVED4[54]; /*!< Reserved, Address offset: 0x2030-0x2104 */ + __IO uint32_t AXI_TARG1_FN_MOD; /*!< AXI interconnect - TARG 1 issuing functionality modification register, Address offset: 0x2108 */ + uint32_t RESERVED5[959]; /*!< Reserved, Address offset: 0x210C-0x3004 */ + __IO uint32_t AXI_TARG2_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 2 bus matrix issuing functionality register, Address offset: 0x3008 */ + uint32_t RESERVED6[6]; /*!< Reserved, Address offset: 0x300C-0x3020 */ + __IO uint32_t AXI_TARG2_FN_MOD2; /*!< AXI interconnect - TARG 2 bus matrix functionality 2 register, Address offset: 0x3024 */ + uint32_t RESERVED7; /*!< Reserved, Address offset: 0x3028 */ + __IO uint32_t AXI_TARG2_FN_MOD_LB; /*!< AXI interconnect - TARG 2 long burst functionality modification register, Address offset: 0x302C */ + uint32_t RESERVED8[54]; /*!< Reserved, Address offset: 0x3030-0x3104 */ + __IO uint32_t AXI_TARG2_FN_MOD; /*!< AXI interconnect - TARG 2 issuing functionality modification register, Address offset: 0x3108 */ + uint32_t RESERVED9[959]; /*!< Reserved, Address offset: 0x310C-0x4004 */ + __IO uint32_t AXI_TARG3_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 3 bus matrix issuing functionality register, Address offset: 0x4008 */ + uint32_t RESERVED10[1023]; /*!< Reserved, Address offset: 0x400C-0x5004 */ + __IO uint32_t AXI_TARG4_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 4 bus matrix issuing functionality register, Address offset: 0x5008 */ + uint32_t RESERVED11[1023]; /*!< Reserved, Address offset: 0x500C-0x6004 */ + __IO uint32_t AXI_TARG5_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 5 bus matrix issuing functionality register, Address offset: 0x6008 */ + uint32_t RESERVED12[1023]; /*!< Reserved, Address offset: 0x600C-0x7004 */ + __IO uint32_t AXI_TARG6_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 6 bus matrix issuing functionality register, Address offset: 0x7008 */ + uint32_t RESERVED13[1023]; /*!< Reserved, Address offset: 0x700C-0x8004 */ + __IO uint32_t AXI_TARG7_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 7 bus matrix issuing functionality register, Address offset: 0x8008 */ + uint32_t RESERVED14[6]; /*!< Reserved, Address offset: 0x800C-0x8020 */ + __IO uint32_t AXI_TARG7_FN_MOD2; /*!< AXI interconnect - TARG 7 bus matrix functionality 2 register, Address offset: 0x8024 */ + uint32_t RESERVED15; /*!< Reserved, Address offset: 0x8028 */ + __IO uint32_t AXI_TARG7_FN_MOD_LB; /*!< AXI interconnect - TARG 7 long burst functionality modification register, Address offset: 0x802C */ + uint32_t RESERVED16[54]; /*!< Reserved, Address offset: 0x8030-0x8104 */ + __IO uint32_t AXI_TARG7_FN_MOD; /*!< AXI interconnect - TARG 7 issuing functionality modification register, Address offset: 0x8108 */ + uint32_t RESERVED17[959]; /*!< Reserved, Address offset: 0x810C-0x9004 */ + __IO uint32_t AXI_TARG8_FN_MOD_ISS_BM; /*!< AXI interconnect - TARG 8 bus matrix issuing functionality register, Address offset: 0x9008 */ + uint32_t RESERVED117[6]; /*!< Reserved, Address offset: 0x900C-0x9020 */ + __IO uint32_t AXI_TARG8_FN_MOD2; /*!< AXI interconnect - TARG 8 bus matrix functionality 2 register, Address offset: 0x9024 */ + uint32_t RESERVED118[56]; /*!< Reserved, Address offset: 0x9028-0x9104 */ + __IO uint32_t AXI_TARG8_FN_MOD; /*!< AXI interconnect - TARG 8 issuing functionality modification register, Address offset: 0x9108 */ + uint32_t RESERVED119[58310]; /*!< Reserved, Address offset: 0x910C-0x42020 */ + __IO uint32_t AXI_INI1_FN_MOD2; /*!< AXI interconnect - INI 1 functionality modification 2 register, Address offset: 0x42024 */ + __IO uint32_t AXI_INI1_FN_MOD_AHB; /*!< AXI interconnect - INI 1 AHB functionality modification register, Address offset: 0x42028 */ + uint32_t RESERVED18[53]; /*!< Reserved, Address offset: 0x4202C-0x420FC */ + __IO uint32_t AXI_INI1_READ_QOS; /*!< AXI interconnect - INI 1 read QoS register, Address offset: 0x42100 */ + __IO uint32_t AXI_INI1_WRITE_QOS; /*!< AXI interconnect - INI 1 write QoS register, Address offset: 0x42104 */ + __IO uint32_t AXI_INI1_FN_MOD; /*!< AXI interconnect - INI 1 issuing functionality modification register, Address offset: 0x42108 */ + uint32_t RESERVED19[1021]; /*!< Reserved, Address offset: 0x4210C-0x430FC */ + __IO uint32_t AXI_INI2_READ_QOS; /*!< AXI interconnect - INI 2 read QoS register, Address offset: 0x43100 */ + __IO uint32_t AXI_INI2_WRITE_QOS; /*!< AXI interconnect - INI 2 write QoS register, Address offset: 0x43104 */ + __IO uint32_t AXI_INI2_FN_MOD; /*!< AXI interconnect - INI 2 issuing functionality modification register, Address offset: 0x43108 */ + uint32_t RESERVED20[966]; /*!< Reserved, Address offset: 0x4310C-0x44020 */ + __IO uint32_t AXI_INI3_FN_MOD2; /*!< AXI interconnect - INI 3 functionality modification 2 register, Address offset: 0x44024 */ + __IO uint32_t AXI_INI3_FN_MOD_AHB; /*!< AXI interconnect - INI 3 AHB functionality modification register, Address offset: 0x44028 */ + uint32_t RESERVED21[53]; /*!< Reserved, Address offset: 0x4402C-0x440FC */ + __IO uint32_t AXI_INI3_READ_QOS; /*!< AXI interconnect - INI 3 read QoS register, Address offset: 0x44100 */ + __IO uint32_t AXI_INI3_WRITE_QOS; /*!< AXI interconnect - INI 3 write QoS register, Address offset: 0x44104 */ + __IO uint32_t AXI_INI3_FN_MOD; /*!< AXI interconnect - INI 3 issuing functionality modification register, Address offset: 0x44108 */ + uint32_t RESERVED22[1021]; /*!< Reserved, Address offset: 0x4410C-0x450FC */ + __IO uint32_t AXI_INI4_READ_QOS; /*!< AXI interconnect - INI 4 read QoS register, Address offset: 0x45100 */ + __IO uint32_t AXI_INI4_WRITE_QOS; /*!< AXI interconnect - INI 4 write QoS register, Address offset: 0x45104 */ + __IO uint32_t AXI_INI4_FN_MOD; /*!< AXI interconnect - INI 4 issuing functionality modification register, Address offset: 0x45108 */ + uint32_t RESERVED23[1021]; /*!< Reserved, Address offset: 0x4510C-0x460FC */ + __IO uint32_t AXI_INI5_READ_QOS; /*!< AXI interconnect - INI 5 read QoS register, Address offset: 0x46100 */ + __IO uint32_t AXI_INI5_WRITE_QOS; /*!< AXI interconnect - INI 5 write QoS register, Address offset: 0x46104 */ + __IO uint32_t AXI_INI5_FN_MOD; /*!< AXI interconnect - INI 5 issuing functionality modification register, Address offset: 0x46108 */ + uint32_t RESERVED24[1021]; /*!< Reserved, Address offset: 0x4610C-0x470FC */ + __IO uint32_t AXI_INI6_READ_QOS; /*!< AXI interconnect - INI 6 read QoS register, Address offset: 0x47100 */ + __IO uint32_t AXI_INI6_WRITE_QOS; /*!< AXI interconnect - INI 6 write QoS register, Address offset: 0x47104 */ + __IO uint32_t AXI_INI6_FN_MOD; /*!< AXI interconnect - INI 6 issuing functionality modification register, Address offset: 0x47108 */ + +} GPV_TypeDef; + +/** @addtogroup Peripheral_memory_map + * @{ + */ +#define D1_ITCMRAM_BASE (0x00000000UL) /*!< Base address of : 64KB RAM reserved for CPU execution/instruction accessible over ITCM */ +#define D1_ITCMICP_BASE (0x00100000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over ITCM */ +#define D1_DTCMRAM_BASE (0x20000000UL) /*!< Base address of : 128KB system data RAM accessible over DTCM */ +#define D1_AXIFLASH_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) embedded FLASH memory accessible over AXI */ +#define D1_AXIICP_BASE (0x1FF00000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over AXI */ +#define D1_AXISRAM1_BASE (0x24000000UL) /*!< Base address of : (up to 128KB) system data RAM1 accessible over over AXI */ +#define D1_AXISRAM2_BASE (0x24020000UL) /*!< Base address of : (up to 192KB) system data RAM2 accessible over over AXI to be shared with ITCM (64K granularity) */ +#define D1_AXISRAM_BASE D1_AXISRAM1_BASE /*!< Base address of : (up to 320KB) system data RAM1/2 accessible over over AXI */ + +#define D2_AHBSRAM1_BASE (0x30000000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM2_BASE (0x30004000UL) /*!< Base address of : (up to 16KB) system data RAM accessible over over AXI->AHB Bridge */ +#define D2_AHBSRAM_BASE D2_AHBSRAM1_BASE /*!< Base address of : (up to 32KB) system data RAM1/2 accessible over over AXI->AHB Bridge */ + +#define D3_BKPSRAM_BASE (0x38800000UL) /*!< Base address of : Backup SRAM(4 KB) over AXI->AHB Bridge */ +#define D3_SRAM_BASE (0x38000000UL) /*!< Base address of : Backup SRAM(16 KB) over AXI->AHB Bridge */ + +#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */ +#define OCTOSPI1_BASE (0x90000000UL) /*!< Base address of : OCTOSPI1 memories accessible over AXI */ +#define OCTOSPI2_BASE (0x70000000UL) /*!< Base address of : OCTOSPI2 memories accessible over AXI */ + +#define FLASH_BANK1_BASE (0x08000000UL) /*!< Base address of : (up to 1 MB) Flash Bank1 accessible over AXI */ +#define FLASH_END (0x080FFFFFUL) /*!< FLASH end address */ + + +/* Legacy define */ +#define FLASH_BASE FLASH_BANK1_BASE + +/*!< Device electronic signature memory map */ +#define UID_BASE (0x1FF1E800UL) /*!< Unique device ID register base address */ +#define FLASHSIZE_BASE (0x1FF1E880UL) /*!< FLASH Size register base address */ + + +/*!< Peripheral memory map */ +#define D2_APB1PERIPH_BASE PERIPH_BASE +#define D2_APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define D2_AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define D2_AHB2PERIPH_BASE (PERIPH_BASE + 0x08020000UL) + +#define D1_APB1PERIPH_BASE (PERIPH_BASE + 0x10000000UL) +#define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000UL) + +#define D3_APB1PERIPH_BASE (PERIPH_BASE + 0x18000000UL) +#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000UL) + +/*!< Legacy Peripheral memory map */ +#define APB1PERIPH_BASE PERIPH_BASE +#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000UL) +#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) +#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000UL) + + +/*!< D1_AHB1PERIPH peripherals */ + +#define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2D_BASE (D1_AHB1PERIPH_BASE + 0x1000UL) +#define FLASH_R_BASE (D1_AHB1PERIPH_BASE + 0x2000UL) +#define FMC_R_BASE (D1_AHB1PERIPH_BASE + 0x4000UL) +#define OCTOSPI1_R_BASE (D1_AHB1PERIPH_BASE + 0x5000UL) +#define DLYB_OCTOSPI1_BASE (D1_AHB1PERIPH_BASE + 0x6000UL) +#define SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x7000UL) +#define DLYB_SDMMC1_BASE (D1_AHB1PERIPH_BASE + 0x8000UL) +#define RAMECC1_BASE (D1_AHB1PERIPH_BASE + 0x9000UL) +#define OCTOSPI2_R_BASE (D1_AHB1PERIPH_BASE + 0xA000UL) +#define DLYB_OCTOSPI2_BASE (D1_AHB1PERIPH_BASE + 0xB000UL) +#define OCTOSPIM_BASE (D1_AHB1PERIPH_BASE + 0xB400UL) + +#define OTFDEC1_BASE (D1_AHB1PERIPH_BASE + 0xB800UL) +#define OTFDEC1_REGION1_BASE (OTFDEC1_BASE + 0x20UL) +#define OTFDEC1_REGION2_BASE (OTFDEC1_BASE + 0x50UL) +#define OTFDEC1_REGION3_BASE (OTFDEC1_BASE + 0x80UL) +#define OTFDEC1_REGION4_BASE (OTFDEC1_BASE + 0xB0UL) +#define OTFDEC2_BASE (D1_AHB1PERIPH_BASE + 0xBC00UL) +#define OTFDEC2_REGION1_BASE (OTFDEC2_BASE + 0x20UL) +#define OTFDEC2_REGION2_BASE (OTFDEC2_BASE + 0x50UL) +#define OTFDEC2_REGION3_BASE (OTFDEC2_BASE + 0x80UL) +#define OTFDEC2_REGION4_BASE (OTFDEC2_BASE + 0xB0UL) + +/*!< D2_AHB1PERIPH peripherals */ + +#define DMA1_BASE (D2_AHB1PERIPH_BASE + 0x0000UL) +#define DMA2_BASE (D2_AHB1PERIPH_BASE + 0x0400UL) +#define DMAMUX1_BASE (D2_AHB1PERIPH_BASE + 0x0800UL) +#define ADC1_BASE (D2_AHB1PERIPH_BASE + 0x2000UL) +#define ADC2_BASE (D2_AHB1PERIPH_BASE + 0x2100UL) +#define ADC12_COMMON_BASE (D2_AHB1PERIPH_BASE + 0x2300UL) +#define ETH_BASE (D2_AHB1PERIPH_BASE + 0x8000UL) +#define ETH_MAC_BASE (ETH_BASE) + +/*!< USB registers base address */ +#define USB1_OTG_HS_PERIPH_BASE (0x40040000UL) +#define USB_OTG_GLOBAL_BASE (0x000UL) +#define USB_OTG_DEVICE_BASE (0x800UL) +#define USB_OTG_IN_ENDPOINT_BASE (0x900UL) +#define USB_OTG_OUT_ENDPOINT_BASE (0xB00UL) +#define USB_OTG_EP_REG_SIZE (0x20UL) +#define USB_OTG_HOST_BASE (0x400UL) +#define USB_OTG_HOST_PORT_BASE (0x440UL) +#define USB_OTG_HOST_CHANNEL_BASE (0x500UL) +#define USB_OTG_HOST_CHANNEL_SIZE (0x20UL) +#define USB_OTG_PCGCCTL_BASE (0xE00UL) +#define USB_OTG_FIFO_BASE (0x1000UL) +#define USB_OTG_FIFO_SIZE (0x1000UL) + +/*!< D2_AHB2PERIPH peripherals */ + +#define DCMI_BASE (D2_AHB2PERIPH_BASE + 0x0000UL) +#define PSSI_BASE (D2_AHB2PERIPH_BASE + 0x0400UL) +#define CRYP_BASE (D2_AHB2PERIPH_BASE + 0x1000UL) +#define HASH_BASE (D2_AHB2PERIPH_BASE + 0x1400UL) +#define HASH_DIGEST_BASE (D2_AHB2PERIPH_BASE + 0x1710UL) +#define RNG_BASE (D2_AHB2PERIPH_BASE + 0x1800UL) +#define SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2400UL) +#define DLYB_SDMMC2_BASE (D2_AHB2PERIPH_BASE + 0x2800UL) +#define RAMECC2_BASE (D2_AHB2PERIPH_BASE + 0x3000UL) +#define FMAC_BASE (D2_AHB2PERIPH_BASE + 0x4000UL) +#define CORDIC_BASE (D2_AHB2PERIPH_BASE + 0x4400UL) + +/*!< D3_AHB1PERIPH peripherals */ +#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000UL) +#define GPIOB_BASE (D3_AHB1PERIPH_BASE + 0x0400UL) +#define GPIOC_BASE (D3_AHB1PERIPH_BASE + 0x0800UL) +#define GPIOD_BASE (D3_AHB1PERIPH_BASE + 0x0C00UL) +#define GPIOE_BASE (D3_AHB1PERIPH_BASE + 0x1000UL) +#define GPIOF_BASE (D3_AHB1PERIPH_BASE + 0x1400UL) +#define GPIOG_BASE (D3_AHB1PERIPH_BASE + 0x1800UL) +#define GPIOH_BASE (D3_AHB1PERIPH_BASE + 0x1C00UL) +#define GPIOJ_BASE (D3_AHB1PERIPH_BASE + 0x2400UL) +#define GPIOK_BASE (D3_AHB1PERIPH_BASE + 0x2800UL) +#define RCC_BASE (D3_AHB1PERIPH_BASE + 0x4400UL) +#define PWR_BASE (D3_AHB1PERIPH_BASE + 0x4800UL) +#define CRC_BASE (D3_AHB1PERIPH_BASE + 0x4C00UL) +#define BDMA_BASE (D3_AHB1PERIPH_BASE + 0x5400UL) +#define DMAMUX2_BASE (D3_AHB1PERIPH_BASE + 0x5800UL) +#define ADC3_BASE (D3_AHB1PERIPH_BASE + 0x6000UL) +#define ADC3_COMMON_BASE (D3_AHB1PERIPH_BASE + 0x6300UL) +#define HSEM_BASE (D3_AHB1PERIPH_BASE + 0x6400UL) +#define RAMECC3_BASE (D3_AHB1PERIPH_BASE + 0x7000UL) + +/*!< D1_APB1PERIPH peripherals */ +#define LTDC_BASE (D1_APB1PERIPH_BASE + 0x1000UL) +#define LTDC_Layer1_BASE (LTDC_BASE + 0x84UL) +#define LTDC_Layer2_BASE (LTDC_BASE + 0x104UL) +#define WWDG1_BASE (D1_APB1PERIPH_BASE + 0x3000UL) + +/*!< D2_APB1PERIPH peripherals */ +#define TIM2_BASE (D2_APB1PERIPH_BASE + 0x0000UL) +#define TIM3_BASE (D2_APB1PERIPH_BASE + 0x0400UL) +#define TIM4_BASE (D2_APB1PERIPH_BASE + 0x0800UL) +#define TIM5_BASE (D2_APB1PERIPH_BASE + 0x0C00UL) +#define TIM6_BASE (D2_APB1PERIPH_BASE + 0x1000UL) +#define TIM7_BASE (D2_APB1PERIPH_BASE + 0x1400UL) +#define TIM12_BASE (D2_APB1PERIPH_BASE + 0x1800UL) +#define TIM13_BASE (D2_APB1PERIPH_BASE + 0x1C00UL) +#define TIM14_BASE (D2_APB1PERIPH_BASE + 0x2000UL) +#define LPTIM1_BASE (D2_APB1PERIPH_BASE + 0x2400UL) + + +#define SPI2_BASE (D2_APB1PERIPH_BASE + 0x3800UL) +#define SPI3_BASE (D2_APB1PERIPH_BASE + 0x3C00UL) +#define SPDIFRX_BASE (D2_APB1PERIPH_BASE + 0x4000UL) +#define USART2_BASE (D2_APB1PERIPH_BASE + 0x4400UL) +#define USART3_BASE (D2_APB1PERIPH_BASE + 0x4800UL) +#define UART4_BASE (D2_APB1PERIPH_BASE + 0x4C00UL) +#define UART5_BASE (D2_APB1PERIPH_BASE + 0x5000UL) +#define I2C1_BASE (D2_APB1PERIPH_BASE + 0x5400UL) +#define I2C2_BASE (D2_APB1PERIPH_BASE + 0x5800UL) +#define I2C3_BASE (D2_APB1PERIPH_BASE + 0x5C00UL) +#define I2C5_BASE (D2_APB1PERIPH_BASE + 0x6400UL) +#define CEC_BASE (D2_APB1PERIPH_BASE + 0x6C00UL) +#define DAC1_BASE (D2_APB1PERIPH_BASE + 0x7400UL) +#define UART7_BASE (D2_APB1PERIPH_BASE + 0x7800UL) +#define UART8_BASE (D2_APB1PERIPH_BASE + 0x7C00UL) +#define CRS_BASE (D2_APB1PERIPH_BASE + 0x8400UL) +#define SWPMI1_BASE (D2_APB1PERIPH_BASE + 0x8800UL) +#define OPAMP_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP1_BASE (D2_APB1PERIPH_BASE + 0x9000UL) +#define OPAMP2_BASE (D2_APB1PERIPH_BASE + 0x9010UL) +#define MDIOS_BASE (D2_APB1PERIPH_BASE + 0x9400UL) +#define FDCAN1_BASE (D2_APB1PERIPH_BASE + 0xA000UL) +#define FDCAN2_BASE (D2_APB1PERIPH_BASE + 0xA400UL) +#define FDCAN_CCU_BASE (D2_APB1PERIPH_BASE + 0xA800UL) +#define SRAMCAN_BASE (D2_APB1PERIPH_BASE + 0xAC00UL) +#define FDCAN3_BASE (D2_APB1PERIPH_BASE + 0xD400UL) +#define TIM23_BASE (D2_APB1PERIPH_BASE + 0xE000UL) +#define TIM24_BASE (D2_APB1PERIPH_BASE + 0xE400UL) + +/*!< D2_APB2PERIPH peripherals */ + +#define TIM1_BASE (D2_APB2PERIPH_BASE + 0x0000UL) +#define TIM8_BASE (D2_APB2PERIPH_BASE + 0x0400UL) +#define USART1_BASE (D2_APB2PERIPH_BASE + 0x1000UL) +#define USART6_BASE (D2_APB2PERIPH_BASE + 0x1400UL) +#define UART9_BASE (D2_APB2PERIPH_BASE + 0x1800UL) +#define USART10_BASE (D2_APB2PERIPH_BASE + 0x1C00UL) +#define SPI1_BASE (D2_APB2PERIPH_BASE + 0x3000UL) +#define SPI4_BASE (D2_APB2PERIPH_BASE + 0x3400UL) +#define TIM15_BASE (D2_APB2PERIPH_BASE + 0x4000UL) +#define TIM16_BASE (D2_APB2PERIPH_BASE + 0x4400UL) +#define TIM17_BASE (D2_APB2PERIPH_BASE + 0x4800UL) +#define SPI5_BASE (D2_APB2PERIPH_BASE + 0x5000UL) +#define SAI1_BASE (D2_APB2PERIPH_BASE + 0x5800UL) +#define SAI1_Block_A_BASE (SAI1_BASE + 0x004UL) +#define SAI1_Block_B_BASE (SAI1_BASE + 0x024UL) +#define DFSDM1_BASE (D2_APB2PERIPH_BASE + 0x7800UL) +#define DFSDM1_Channel0_BASE (DFSDM1_BASE + 0x00UL) +#define DFSDM1_Channel1_BASE (DFSDM1_BASE + 0x20UL) +#define DFSDM1_Channel2_BASE (DFSDM1_BASE + 0x40UL) +#define DFSDM1_Channel3_BASE (DFSDM1_BASE + 0x60UL) +#define DFSDM1_Channel4_BASE (DFSDM1_BASE + 0x80UL) +#define DFSDM1_Channel5_BASE (DFSDM1_BASE + 0xA0UL) +#define DFSDM1_Channel6_BASE (DFSDM1_BASE + 0xC0UL) +#define DFSDM1_Channel7_BASE (DFSDM1_BASE + 0xE0UL) +#define DFSDM1_Filter0_BASE (DFSDM1_BASE + 0x100UL) +#define DFSDM1_Filter1_BASE (DFSDM1_BASE + 0x180UL) +#define DFSDM1_Filter2_BASE (DFSDM1_BASE + 0x200UL) +#define DFSDM1_Filter3_BASE (DFSDM1_BASE + 0x280UL) + + +/*!< D3_APB1PERIPH peripherals */ +#define EXTI_BASE (D3_APB1PERIPH_BASE + 0x0000UL) +#define EXTI_D1_BASE (EXTI_BASE + 0x0080UL) +#define EXTI_D2_BASE (EXTI_BASE + 0x00C0UL) +#define SYSCFG_BASE (D3_APB1PERIPH_BASE + 0x0400UL) +#define LPUART1_BASE (D3_APB1PERIPH_BASE + 0x0C00UL) +#define SPI6_BASE (D3_APB1PERIPH_BASE + 0x1400UL) +#define I2C4_BASE (D3_APB1PERIPH_BASE + 0x1C00UL) +#define LPTIM2_BASE (D3_APB1PERIPH_BASE + 0x2400UL) +#define LPTIM3_BASE (D3_APB1PERIPH_BASE + 0x2800UL) +#define LPTIM4_BASE (D3_APB1PERIPH_BASE + 0x2C00UL) +#define LPTIM5_BASE (D3_APB1PERIPH_BASE + 0x3000UL) +#define COMP12_BASE (D3_APB1PERIPH_BASE + 0x3800UL) +#define COMP1_BASE (COMP12_BASE + 0x0CUL) +#define COMP2_BASE (COMP12_BASE + 0x10UL) +#define VREFBUF_BASE (D3_APB1PERIPH_BASE + 0x3C00UL) +#define RTC_BASE (D3_APB1PERIPH_BASE + 0x4000UL) +#define IWDG1_BASE (D3_APB1PERIPH_BASE + 0x4800UL) + + +#define SAI4_BASE (D3_APB1PERIPH_BASE + 0x5400UL) +#define SAI4_Block_A_BASE (SAI4_BASE + 0x004UL) +#define SAI4_Block_B_BASE (SAI4_BASE + 0x024UL) + +#define DTS_BASE (D3_APB1PERIPH_BASE + 0x6800UL) + + + +#define BDMA_Channel0_BASE (BDMA_BASE + 0x0008UL) +#define BDMA_Channel1_BASE (BDMA_BASE + 0x001CUL) +#define BDMA_Channel2_BASE (BDMA_BASE + 0x0030UL) +#define BDMA_Channel3_BASE (BDMA_BASE + 0x0044UL) +#define BDMA_Channel4_BASE (BDMA_BASE + 0x0058UL) +#define BDMA_Channel5_BASE (BDMA_BASE + 0x006CUL) +#define BDMA_Channel6_BASE (BDMA_BASE + 0x0080UL) +#define BDMA_Channel7_BASE (BDMA_BASE + 0x0094UL) + +#define DMAMUX2_Channel0_BASE (DMAMUX2_BASE) +#define DMAMUX2_Channel1_BASE (DMAMUX2_BASE + 0x0004UL) +#define DMAMUX2_Channel2_BASE (DMAMUX2_BASE + 0x0008UL) +#define DMAMUX2_Channel3_BASE (DMAMUX2_BASE + 0x000CUL) +#define DMAMUX2_Channel4_BASE (DMAMUX2_BASE + 0x0010UL) +#define DMAMUX2_Channel5_BASE (DMAMUX2_BASE + 0x0014UL) +#define DMAMUX2_Channel6_BASE (DMAMUX2_BASE + 0x0018UL) +#define DMAMUX2_Channel7_BASE (DMAMUX2_BASE + 0x001CUL) + +#define DMAMUX2_RequestGenerator0_BASE (DMAMUX2_BASE + 0x0100UL) +#define DMAMUX2_RequestGenerator1_BASE (DMAMUX2_BASE + 0x0104UL) +#define DMAMUX2_RequestGenerator2_BASE (DMAMUX2_BASE + 0x0108UL) +#define DMAMUX2_RequestGenerator3_BASE (DMAMUX2_BASE + 0x010CUL) +#define DMAMUX2_RequestGenerator4_BASE (DMAMUX2_BASE + 0x0110UL) +#define DMAMUX2_RequestGenerator5_BASE (DMAMUX2_BASE + 0x0114UL) +#define DMAMUX2_RequestGenerator6_BASE (DMAMUX2_BASE + 0x0118UL) +#define DMAMUX2_RequestGenerator7_BASE (DMAMUX2_BASE + 0x011CUL) + +#define DMAMUX2_ChannelStatus_BASE (DMAMUX2_BASE + 0x0080UL) +#define DMAMUX2_RequestGenStatus_BASE (DMAMUX2_BASE + 0x0140UL) + +#define DMA1_Stream0_BASE (DMA1_BASE + 0x010UL) +#define DMA1_Stream1_BASE (DMA1_BASE + 0x028UL) +#define DMA1_Stream2_BASE (DMA1_BASE + 0x040UL) +#define DMA1_Stream3_BASE (DMA1_BASE + 0x058UL) +#define DMA1_Stream4_BASE (DMA1_BASE + 0x070UL) +#define DMA1_Stream5_BASE (DMA1_BASE + 0x088UL) +#define DMA1_Stream6_BASE (DMA1_BASE + 0x0A0UL) +#define DMA1_Stream7_BASE (DMA1_BASE + 0x0B8UL) + +#define DMA2_Stream0_BASE (DMA2_BASE + 0x010UL) +#define DMA2_Stream1_BASE (DMA2_BASE + 0x028UL) +#define DMA2_Stream2_BASE (DMA2_BASE + 0x040UL) +#define DMA2_Stream3_BASE (DMA2_BASE + 0x058UL) +#define DMA2_Stream4_BASE (DMA2_BASE + 0x070UL) +#define DMA2_Stream5_BASE (DMA2_BASE + 0x088UL) +#define DMA2_Stream6_BASE (DMA2_BASE + 0x0A0UL) +#define DMA2_Stream7_BASE (DMA2_BASE + 0x0B8UL) + +#define DMAMUX1_Channel0_BASE (DMAMUX1_BASE) +#define DMAMUX1_Channel1_BASE (DMAMUX1_BASE + 0x0004UL) +#define DMAMUX1_Channel2_BASE (DMAMUX1_BASE + 0x0008UL) +#define DMAMUX1_Channel3_BASE (DMAMUX1_BASE + 0x000CUL) +#define DMAMUX1_Channel4_BASE (DMAMUX1_BASE + 0x0010UL) +#define DMAMUX1_Channel5_BASE (DMAMUX1_BASE + 0x0014UL) +#define DMAMUX1_Channel6_BASE (DMAMUX1_BASE + 0x0018UL) +#define DMAMUX1_Channel7_BASE (DMAMUX1_BASE + 0x001CUL) +#define DMAMUX1_Channel8_BASE (DMAMUX1_BASE + 0x0020UL) +#define DMAMUX1_Channel9_BASE (DMAMUX1_BASE + 0x0024UL) +#define DMAMUX1_Channel10_BASE (DMAMUX1_BASE + 0x0028UL) +#define DMAMUX1_Channel11_BASE (DMAMUX1_BASE + 0x002CUL) +#define DMAMUX1_Channel12_BASE (DMAMUX1_BASE + 0x0030UL) +#define DMAMUX1_Channel13_BASE (DMAMUX1_BASE + 0x0034UL) +#define DMAMUX1_Channel14_BASE (DMAMUX1_BASE + 0x0038UL) +#define DMAMUX1_Channel15_BASE (DMAMUX1_BASE + 0x003CUL) + +#define DMAMUX1_RequestGenerator0_BASE (DMAMUX1_BASE + 0x0100UL) +#define DMAMUX1_RequestGenerator1_BASE (DMAMUX1_BASE + 0x0104UL) +#define DMAMUX1_RequestGenerator2_BASE (DMAMUX1_BASE + 0x0108UL) +#define DMAMUX1_RequestGenerator3_BASE (DMAMUX1_BASE + 0x010CUL) +#define DMAMUX1_RequestGenerator4_BASE (DMAMUX1_BASE + 0x0110UL) +#define DMAMUX1_RequestGenerator5_BASE (DMAMUX1_BASE + 0x0114UL) +#define DMAMUX1_RequestGenerator6_BASE (DMAMUX1_BASE + 0x0118UL) +#define DMAMUX1_RequestGenerator7_BASE (DMAMUX1_BASE + 0x011CUL) + +#define DMAMUX1_ChannelStatus_BASE (DMAMUX1_BASE + 0x0080UL) +#define DMAMUX1_RequestGenStatus_BASE (DMAMUX1_BASE + 0x0140UL) + +/*!< FMC Banks registers base address */ +#define FMC_Bank1_R_BASE (FMC_R_BASE + 0x0000UL) +#define FMC_Bank1E_R_BASE (FMC_R_BASE + 0x0104UL) +#define FMC_Bank2_R_BASE (FMC_R_BASE + 0x0060UL) +#define FMC_Bank3_R_BASE (FMC_R_BASE + 0x0080UL) +#define FMC_Bank5_6_R_BASE (FMC_R_BASE + 0x0140UL) + +/* Debug MCU registers base address */ +#define DBGMCU_BASE (0x5C001000UL) + +#define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040UL) +#define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080UL) +#define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0UL) +#define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100UL) +#define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140UL) +#define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180UL) +#define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0UL) +#define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200UL) +#define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240UL) +#define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280UL) +#define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0UL) +#define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300UL) +#define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340UL) +#define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380UL) +#define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0UL) +#define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400UL) + +#define RAMECC1_Monitor1_BASE (RAMECC1_BASE + 0x20UL) +#define RAMECC1_Monitor2_BASE (RAMECC1_BASE + 0x40UL) +#define RAMECC1_Monitor3_BASE (RAMECC1_BASE + 0x60UL) +#define RAMECC1_Monitor4_BASE (RAMECC1_BASE + 0x80UL) +#define RAMECC1_Monitor5_BASE (RAMECC1_BASE + 0xA0UL) +#define RAMECC1_Monitor6_BASE (RAMECC1_BASE + 0xC0UL) + +#define RAMECC2_Monitor1_BASE (RAMECC2_BASE + 0x20UL) +#define RAMECC2_Monitor2_BASE (RAMECC2_BASE + 0x40UL) +#define RAMECC2_Monitor3_BASE (RAMECC2_BASE + 0x60UL) + +#define RAMECC3_Monitor1_BASE (RAMECC3_BASE + 0x20UL) +#define RAMECC3_Monitor2_BASE (RAMECC3_BASE + 0x40UL) + + + +#define GPV_BASE (PERIPH_BASE + 0x11000000UL) /*!< GPV_BASE (PERIPH_BASE + 0x11000000UL) */ + +/** + * @} + */ + +/** @addtogroup Peripheral_declaration + * @{ + */ +#define TIM2 ((TIM_TypeDef *) TIM2_BASE) +#define TIM3 ((TIM_TypeDef *) TIM3_BASE) +#define TIM4 ((TIM_TypeDef *) TIM4_BASE) +#define TIM5 ((TIM_TypeDef *) TIM5_BASE) +#define TIM6 ((TIM_TypeDef *) TIM6_BASE) +#define TIM7 ((TIM_TypeDef *) TIM7_BASE) +#define TIM13 ((TIM_TypeDef *) TIM13_BASE) +#define TIM14 ((TIM_TypeDef *) TIM14_BASE) +#define VREFBUF ((VREFBUF_TypeDef *) VREFBUF_BASE) +#define RTC ((RTC_TypeDef *) RTC_BASE) +#define WWDG1 ((WWDG_TypeDef *) WWDG1_BASE) + + +#define IWDG1 ((IWDG_TypeDef *) IWDG1_BASE) +#define SPI2 ((SPI_TypeDef *) SPI2_BASE) +#define SPI3 ((SPI_TypeDef *) SPI3_BASE) +#define SPI4 ((SPI_TypeDef *) SPI4_BASE) +#define SPI5 ((SPI_TypeDef *) SPI5_BASE) +#define SPI6 ((SPI_TypeDef *) SPI6_BASE) +#define USART2 ((USART_TypeDef *) USART2_BASE) +#define USART3 ((USART_TypeDef *) USART3_BASE) +#define USART6 ((USART_TypeDef *) USART6_BASE) +#define USART10 ((USART_TypeDef *) USART10_BASE) +#define UART7 ((USART_TypeDef *) UART7_BASE) +#define UART8 ((USART_TypeDef *) UART8_BASE) +#define UART9 ((USART_TypeDef *) UART9_BASE) +#define CRS ((CRS_TypeDef *) CRS_BASE) +#define UART4 ((USART_TypeDef *) UART4_BASE) +#define UART5 ((USART_TypeDef *) UART5_BASE) +#define I2C1 ((I2C_TypeDef *) I2C1_BASE) +#define I2C2 ((I2C_TypeDef *) I2C2_BASE) +#define I2C3 ((I2C_TypeDef *) I2C3_BASE) +#define I2C4 ((I2C_TypeDef *) I2C4_BASE) +#define I2C5 ((I2C_TypeDef *) I2C5_BASE) +#define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) +#define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE) +#define FDCAN_CCU ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE) +#define FDCAN3 ((FDCAN_GlobalTypeDef *) FDCAN3_BASE) +#define TIM23 ((TIM_TypeDef *) TIM23_BASE) +#define TIM24 ((TIM_TypeDef *) TIM24_BASE) +#define CEC ((CEC_TypeDef *) CEC_BASE) +#define LPTIM1 ((LPTIM_TypeDef *) LPTIM1_BASE) +#define PWR ((PWR_TypeDef *) PWR_BASE) +#define DAC1 ((DAC_TypeDef *) DAC1_BASE) +#define LPUART1 ((USART_TypeDef *) LPUART1_BASE) +#define SWPMI1 ((SWPMI_TypeDef *) SWPMI1_BASE) +#define LPTIM2 ((LPTIM_TypeDef *) LPTIM2_BASE) +#define LPTIM3 ((LPTIM_TypeDef *) LPTIM3_BASE) +#define DTS ((DTS_TypeDef *) DTS_BASE) +#define LPTIM4 ((LPTIM_TypeDef *) LPTIM4_BASE) +#define LPTIM5 ((LPTIM_TypeDef *) LPTIM5_BASE) + +#define SYSCFG ((SYSCFG_TypeDef *) SYSCFG_BASE) +#define COMP12 ((COMPOPT_TypeDef *) COMP12_BASE) +#define COMP1 ((COMP_TypeDef *) COMP1_BASE) +#define COMP2 ((COMP_TypeDef *) COMP2_BASE) +#define COMP12_COMMON ((COMP_Common_TypeDef *) COMP2_BASE) +#define OPAMP ((OPAMP_TypeDef *) OPAMP_BASE) +#define OPAMP1 ((OPAMP_TypeDef *) OPAMP1_BASE) +#define OPAMP2 ((OPAMP_TypeDef *) OPAMP2_BASE) + + +#define EXTI ((EXTI_TypeDef *) EXTI_BASE) +#define EXTI_D1 ((EXTI_Core_TypeDef *) EXTI_D1_BASE) +#define EXTI_D2 ((EXTI_Core_TypeDef *) EXTI_D2_BASE) +#define TIM1 ((TIM_TypeDef *) TIM1_BASE) +#define SPI1 ((SPI_TypeDef *) SPI1_BASE) +#define TIM8 ((TIM_TypeDef *) TIM8_BASE) +#define USART1 ((USART_TypeDef *) USART1_BASE) +#define TIM12 ((TIM_TypeDef *) TIM12_BASE) +#define TIM15 ((TIM_TypeDef *) TIM15_BASE) +#define TIM16 ((TIM_TypeDef *) TIM16_BASE) +#define TIM17 ((TIM_TypeDef *) TIM17_BASE) +#define SAI1 ((SAI_TypeDef *) SAI1_BASE) +#define SAI1_Block_A ((SAI_Block_TypeDef *)SAI1_Block_A_BASE) +#define SAI1_Block_B ((SAI_Block_TypeDef *)SAI1_Block_B_BASE) +#define SAI4 ((SAI_TypeDef *) SAI4_BASE) +#define SAI4_Block_A ((SAI_Block_TypeDef *)SAI4_Block_A_BASE) +#define SAI4_Block_B ((SAI_Block_TypeDef *)SAI4_Block_B_BASE) + +#define SPDIFRX ((SPDIFRX_TypeDef *) SPDIFRX_BASE) +#define DFSDM1_Channel0 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel0_BASE) +#define DFSDM1_Channel1 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel1_BASE) +#define DFSDM1_Channel2 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel2_BASE) +#define DFSDM1_Channel3 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel3_BASE) +#define DFSDM1_Channel4 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel4_BASE) +#define DFSDM1_Channel5 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel5_BASE) +#define DFSDM1_Channel6 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel6_BASE) +#define DFSDM1_Channel7 ((DFSDM_Channel_TypeDef *) DFSDM1_Channel7_BASE) +#define DFSDM1_Filter0 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter0_BASE) +#define DFSDM1_Filter1 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter1_BASE) +#define DFSDM1_Filter2 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter2_BASE) +#define DFSDM1_Filter3 ((DFSDM_Filter_TypeDef *) DFSDM1_Filter3_BASE) +#define DMA2D ((DMA2D_TypeDef *) DMA2D_BASE) +#define DCMI ((DCMI_TypeDef *) DCMI_BASE) +#define PSSI ((PSSI_TypeDef *) PSSI_BASE) +#define RCC ((RCC_TypeDef *) RCC_BASE) +#define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) +#define CRC ((CRC_TypeDef *) CRC_BASE) + +#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE) +#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) +#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE) +#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE) +#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) +#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) +#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE) +#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE) +#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE) +#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE) + +#define ADC1 ((ADC_TypeDef *) ADC1_BASE) +#define ADC2 ((ADC_TypeDef *) ADC2_BASE) +#define ADC3 ((ADC_TypeDef *) ADC3_BASE) +#define ADC3_COMMON ((ADC_Common_TypeDef *) ADC3_COMMON_BASE) +#define ADC12_COMMON ((ADC_Common_TypeDef *) ADC12_COMMON_BASE) + +#define CRYP ((CRYP_TypeDef *) CRYP_BASE) +#define HASH ((HASH_TypeDef *) HASH_BASE) +#define HASH_DIGEST ((HASH_DIGEST_TypeDef *) HASH_DIGEST_BASE) +#define RNG ((RNG_TypeDef *) RNG_BASE) +#define SDMMC2 ((SDMMC_TypeDef *) SDMMC2_BASE) +#define DLYB_SDMMC2 ((DLYB_TypeDef *) DLYB_SDMMC2_BASE) +#define FMAC ((FMAC_TypeDef *) FMAC_BASE) +#define CORDIC ((CORDIC_TypeDef *) CORDIC_BASE) + +#define BDMA ((BDMA_TypeDef *) BDMA_BASE) +#define BDMA_Channel0 ((BDMA_Channel_TypeDef *) BDMA_Channel0_BASE) +#define BDMA_Channel1 ((BDMA_Channel_TypeDef *) BDMA_Channel1_BASE) +#define BDMA_Channel2 ((BDMA_Channel_TypeDef *) BDMA_Channel2_BASE) +#define BDMA_Channel3 ((BDMA_Channel_TypeDef *) BDMA_Channel3_BASE) +#define BDMA_Channel4 ((BDMA_Channel_TypeDef *) BDMA_Channel4_BASE) +#define BDMA_Channel5 ((BDMA_Channel_TypeDef *) BDMA_Channel5_BASE) +#define BDMA_Channel6 ((BDMA_Channel_TypeDef *) BDMA_Channel6_BASE) +#define BDMA_Channel7 ((BDMA_Channel_TypeDef *) BDMA_Channel7_BASE) + +#define RAMECC1 ((RAMECC_TypeDef *)RAMECC1_BASE) +#define RAMECC1_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor1_BASE) +#define RAMECC1_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor2_BASE) +#define RAMECC1_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor3_BASE) +#define RAMECC1_Monitor4 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor4_BASE) +#define RAMECC1_Monitor5 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor5_BASE) +#define RAMECC1_Monitor6 ((RAMECC_MonitorTypeDef *)RAMECC1_Monitor6_BASE) + +#define RAMECC2 ((RAMECC_TypeDef *)RAMECC2_BASE) +#define RAMECC2_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor1_BASE) +#define RAMECC2_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor2_BASE) +#define RAMECC2_Monitor3 ((RAMECC_MonitorTypeDef *)RAMECC2_Monitor3_BASE) + +#define RAMECC3 ((RAMECC_TypeDef *)RAMECC3_BASE) +#define RAMECC3_Monitor1 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor1_BASE) +#define RAMECC3_Monitor2 ((RAMECC_MonitorTypeDef *)RAMECC3_Monitor2_BASE) + +#define DMAMUX2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_BASE) +#define DMAMUX2_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel0_BASE) +#define DMAMUX2_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel1_BASE) +#define DMAMUX2_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel2_BASE) +#define DMAMUX2_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel3_BASE) +#define DMAMUX2_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel4_BASE) +#define DMAMUX2_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel5_BASE) +#define DMAMUX2_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel6_BASE) +#define DMAMUX2_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX2_Channel7_BASE) + + +#define DMAMUX2_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator0_BASE) +#define DMAMUX2_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator1_BASE) +#define DMAMUX2_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator2_BASE) +#define DMAMUX2_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator3_BASE) +#define DMAMUX2_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator4_BASE) +#define DMAMUX2_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator5_BASE) +#define DMAMUX2_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator6_BASE) +#define DMAMUX2_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX2_RequestGenerator7_BASE) + +#define DMAMUX2_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX2_ChannelStatus_BASE) +#define DMAMUX2_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX2_RequestGenStatus_BASE) + +#define DMA2 ((DMA_TypeDef *) DMA2_BASE) +#define DMA2_Stream0 ((DMA_Stream_TypeDef *) DMA2_Stream0_BASE) +#define DMA2_Stream1 ((DMA_Stream_TypeDef *) DMA2_Stream1_BASE) +#define DMA2_Stream2 ((DMA_Stream_TypeDef *) DMA2_Stream2_BASE) +#define DMA2_Stream3 ((DMA_Stream_TypeDef *) DMA2_Stream3_BASE) +#define DMA2_Stream4 ((DMA_Stream_TypeDef *) DMA2_Stream4_BASE) +#define DMA2_Stream5 ((DMA_Stream_TypeDef *) DMA2_Stream5_BASE) +#define DMA2_Stream6 ((DMA_Stream_TypeDef *) DMA2_Stream6_BASE) +#define DMA2_Stream7 ((DMA_Stream_TypeDef *) DMA2_Stream7_BASE) + +#define DMA1 ((DMA_TypeDef *) DMA1_BASE) +#define DMA1_Stream0 ((DMA_Stream_TypeDef *) DMA1_Stream0_BASE) +#define DMA1_Stream1 ((DMA_Stream_TypeDef *) DMA1_Stream1_BASE) +#define DMA1_Stream2 ((DMA_Stream_TypeDef *) DMA1_Stream2_BASE) +#define DMA1_Stream3 ((DMA_Stream_TypeDef *) DMA1_Stream3_BASE) +#define DMA1_Stream4 ((DMA_Stream_TypeDef *) DMA1_Stream4_BASE) +#define DMA1_Stream5 ((DMA_Stream_TypeDef *) DMA1_Stream5_BASE) +#define DMA1_Stream6 ((DMA_Stream_TypeDef *) DMA1_Stream6_BASE) +#define DMA1_Stream7 ((DMA_Stream_TypeDef *) DMA1_Stream7_BASE) + + +#define DMAMUX1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_BASE) +#define DMAMUX1_Channel0 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel0_BASE) +#define DMAMUX1_Channel1 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel1_BASE) +#define DMAMUX1_Channel2 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel2_BASE) +#define DMAMUX1_Channel3 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel3_BASE) +#define DMAMUX1_Channel4 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel4_BASE) +#define DMAMUX1_Channel5 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel5_BASE) +#define DMAMUX1_Channel6 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel6_BASE) +#define DMAMUX1_Channel7 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel7_BASE) +#define DMAMUX1_Channel8 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel8_BASE) +#define DMAMUX1_Channel9 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel9_BASE) +#define DMAMUX1_Channel10 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel10_BASE) +#define DMAMUX1_Channel11 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel11_BASE) +#define DMAMUX1_Channel12 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel12_BASE) +#define DMAMUX1_Channel13 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel13_BASE) +#define DMAMUX1_Channel14 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel14_BASE) +#define DMAMUX1_Channel15 ((DMAMUX_Channel_TypeDef *) DMAMUX1_Channel15_BASE) + +#define DMAMUX1_RequestGenerator0 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator0_BASE) +#define DMAMUX1_RequestGenerator1 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator1_BASE) +#define DMAMUX1_RequestGenerator2 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator2_BASE) +#define DMAMUX1_RequestGenerator3 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator3_BASE) +#define DMAMUX1_RequestGenerator4 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator4_BASE) +#define DMAMUX1_RequestGenerator5 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator5_BASE) +#define DMAMUX1_RequestGenerator6 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator6_BASE) +#define DMAMUX1_RequestGenerator7 ((DMAMUX_RequestGen_TypeDef *) DMAMUX1_RequestGenerator7_BASE) + +#define DMAMUX1_ChannelStatus ((DMAMUX_ChannelStatus_TypeDef *) DMAMUX1_ChannelStatus_BASE) +#define DMAMUX1_RequestGenStatus ((DMAMUX_RequestGenStatus_TypeDef *) DMAMUX1_RequestGenStatus_BASE) + + +#define FMC_Bank1_R ((FMC_Bank1_TypeDef *) FMC_Bank1_R_BASE) +#define FMC_Bank1E_R ((FMC_Bank1E_TypeDef *) FMC_Bank1E_R_BASE) +#define FMC_Bank2_R ((FMC_Bank2_TypeDef *) FMC_Bank2_R_BASE) +#define FMC_Bank3_R ((FMC_Bank3_TypeDef *) FMC_Bank3_R_BASE) +#define FMC_Bank5_6_R ((FMC_Bank5_6_TypeDef *) FMC_Bank5_6_R_BASE) + +#define OCTOSPI1 ((OCTOSPI_TypeDef *) OCTOSPI1_R_BASE) +#define DLYB_OCTOSPI1 ((DLYB_TypeDef *) DLYB_OCTOSPI1_BASE) +#define OCTOSPI2 ((OCTOSPI_TypeDef *) OCTOSPI2_R_BASE) +#define DLYB_OCTOSPI2 ((DLYB_TypeDef *) DLYB_OCTOSPI2_BASE) +#define OCTOSPIM ((OCTOSPIM_TypeDef *) OCTOSPIM_BASE) + +#define OTFDEC1 ((OTFDEC_TypeDef *) OTFDEC1_BASE) +#define OTFDEC1_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION1_BASE) +#define OTFDEC1_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION2_BASE) +#define OTFDEC1_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION3_BASE) +#define OTFDEC1_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC1_REGION4_BASE) + +#define OTFDEC2 ((OTFDEC_TypeDef *) OTFDEC2_BASE) +#define OTFDEC2_REGION1 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION1_BASE) +#define OTFDEC2_REGION2 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION2_BASE) +#define OTFDEC2_REGION3 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION3_BASE) +#define OTFDEC2_REGION4 ((OTFDEC_Region_TypeDef *) OTFDEC2_REGION4_BASE) + +#define SDMMC1 ((SDMMC_TypeDef *) SDMMC1_BASE) +#define DLYB_SDMMC1 ((DLYB_TypeDef *) DLYB_SDMMC1_BASE) + +#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) + +#define HSEM ((HSEM_TypeDef *) HSEM_BASE) +#define HSEM_COMMON ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x100UL)) + +#define LTDC ((LTDC_TypeDef *)LTDC_BASE) +#define LTDC_Layer1 ((LTDC_Layer_TypeDef *)LTDC_Layer1_BASE) +#define LTDC_Layer2 ((LTDC_Layer_TypeDef *)LTDC_Layer2_BASE) + +#define MDIOS ((MDIOS_TypeDef *) MDIOS_BASE) + +#define ETH ((ETH_TypeDef *)ETH_BASE) +#define MDMA ((MDMA_TypeDef *)MDMA_BASE) +#define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE) +#define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE) +#define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE) +#define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE) +#define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE) +#define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE) +#define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE) +#define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE) +#define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE) +#define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE) +#define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE) +#define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE) +#define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE) +#define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE) +#define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE) +#define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE) + + +#define USB1_OTG_HS ((USB_OTG_GlobalTypeDef *) USB1_OTG_HS_PERIPH_BASE) + +/* Legacy defines */ +#define USB_OTG_HS USB1_OTG_HS +#define USB_OTG_HS_PERIPH_BASE USB1_OTG_HS_PERIPH_BASE + +#define GPV ((GPV_TypeDef *) GPV_BASE) + +/** + * @} + */ + +/** @addtogroup Exported_constants + * @{ + */ + + /** @addtogroup Peripheral_Registers_Bits_Definition + * @{ + */ + +/******************************************************************************/ +/* Peripheral Registers_Bits_Definition */ +/******************************************************************************/ + +/******************************************************************************/ +/* */ +/* Analog to Digital Converter */ +/* */ +/******************************************************************************/ +/******************************* ADC VERSION ********************************/ +#define ADC_VER_V5_V90 +/******************** Bit definition for ADC_ISR register ********************/ +#define ADC_ISR_ADRDY_Pos (0U) +#define ADC_ISR_ADRDY_Msk (0x1UL << ADC_ISR_ADRDY_Pos) /*!< 0x00000001 */ +#define ADC_ISR_ADRDY ADC_ISR_ADRDY_Msk /*!< ADC Ready (ADRDY) flag */ +#define ADC_ISR_EOSMP_Pos (1U) +#define ADC_ISR_EOSMP_Msk (0x1UL << ADC_ISR_EOSMP_Pos) /*!< 0x00000002 */ +#define ADC_ISR_EOSMP ADC_ISR_EOSMP_Msk /*!< ADC End of Sampling flag */ +#define ADC_ISR_EOC_Pos (2U) +#define ADC_ISR_EOC_Msk (0x1UL << ADC_ISR_EOC_Pos) /*!< 0x00000004 */ +#define ADC_ISR_EOC ADC_ISR_EOC_Msk /*!< ADC End of Regular Conversion flag */ +#define ADC_ISR_EOS_Pos (3U) +#define ADC_ISR_EOS_Msk (0x1UL << ADC_ISR_EOS_Pos) /*!< 0x00000008 */ +#define ADC_ISR_EOS ADC_ISR_EOS_Msk /*!< ADC End of Regular sequence of Conversions flag */ +#define ADC_ISR_OVR_Pos (4U) +#define ADC_ISR_OVR_Msk (0x1UL << ADC_ISR_OVR_Pos) /*!< 0x00000010 */ +#define ADC_ISR_OVR ADC_ISR_OVR_Msk /*!< ADC overrun flag */ +#define ADC_ISR_JEOC_Pos (5U) +#define ADC_ISR_JEOC_Msk (0x1UL << ADC_ISR_JEOC_Pos) /*!< 0x00000020 */ +#define ADC_ISR_JEOC ADC_ISR_JEOC_Msk /*!< ADC End of Injected Conversion flag */ +#define ADC_ISR_JEOS_Pos (6U) +#define ADC_ISR_JEOS_Msk (0x1UL << ADC_ISR_JEOS_Pos) /*!< 0x00000040 */ +#define ADC_ISR_JEOS ADC_ISR_JEOS_Msk /*!< ADC End of Injected sequence of Conversions flag */ +#define ADC_ISR_AWD1_Pos (7U) +#define ADC_ISR_AWD1_Msk (0x1UL << ADC_ISR_AWD1_Pos) /*!< 0x00000080 */ +#define ADC_ISR_AWD1 ADC_ISR_AWD1_Msk /*!< ADC Analog watchdog 1 flag */ +#define ADC_ISR_AWD2_Pos (8U) +#define ADC_ISR_AWD2_Msk (0x1UL << ADC_ISR_AWD2_Pos) /*!< 0x00000100 */ +#define ADC_ISR_AWD2 ADC_ISR_AWD2_Msk /*!< ADC Analog watchdog 2 flag */ +#define ADC_ISR_AWD3_Pos (9U) +#define ADC_ISR_AWD3_Msk (0x1UL << ADC_ISR_AWD3_Pos) /*!< 0x00000200 */ +#define ADC_ISR_AWD3 ADC_ISR_AWD3_Msk /*!< ADC Analog watchdog 3 flag */ +#define ADC_ISR_JQOVF_Pos (10U) +#define ADC_ISR_JQOVF_Msk (0x1UL << ADC_ISR_JQOVF_Pos) /*!< 0x00000400 */ +#define ADC_ISR_JQOVF ADC_ISR_JQOVF_Msk /*!< ADC Injected Context Queue Overflow flag */ +#define ADC_ISR_LDORDY_Pos (12U) +#define ADC_ISR_LDORDY_Msk (0x1UL << ADC_ISR_LDORDY_Pos) /*!< 0x00001000 */ +#define ADC_ISR_LDORDY ADC_ISR_LDORDY_Msk /*!< ADC LDO Ready (LDORDY) flag */ + +/******************** Bit definition for ADC_IER register ********************/ +#define ADC_IER_ADRDYIE_Pos (0U) +#define ADC_IER_ADRDYIE_Msk (0x1UL << ADC_IER_ADRDYIE_Pos) /*!< 0x00000001 */ +#define ADC_IER_ADRDYIE ADC_IER_ADRDYIE_Msk /*!< ADC Ready (ADRDY) interrupt source */ +#define ADC_IER_EOSMPIE_Pos (1U) +#define ADC_IER_EOSMPIE_Msk (0x1UL << ADC_IER_EOSMPIE_Pos) /*!< 0x00000002 */ +#define ADC_IER_EOSMPIE ADC_IER_EOSMPIE_Msk /*!< ADC End of Sampling interrupt source */ +#define ADC_IER_EOCIE_Pos (2U) +#define ADC_IER_EOCIE_Msk (0x1UL << ADC_IER_EOCIE_Pos) /*!< 0x00000004 */ +#define ADC_IER_EOCIE ADC_IER_EOCIE_Msk /*!< ADC End of Regular Conversion interrupt source */ +#define ADC_IER_EOSIE_Pos (3U) +#define ADC_IER_EOSIE_Msk (0x1UL << ADC_IER_EOSIE_Pos) /*!< 0x00000008 */ +#define ADC_IER_EOSIE ADC_IER_EOSIE_Msk /*!< ADC End of Regular sequence of Conversions interrupt source */ +#define ADC_IER_OVRIE_Pos (4U) +#define ADC_IER_OVRIE_Msk (0x1UL << ADC_IER_OVRIE_Pos) /*!< 0x00000010 */ +#define ADC_IER_OVRIE ADC_IER_OVRIE_Msk /*!< ADC overrun interrupt source */ +#define ADC_IER_JEOCIE_Pos (5U) +#define ADC_IER_JEOCIE_Msk (0x1UL << ADC_IER_JEOCIE_Pos) /*!< 0x00000020 */ +#define ADC_IER_JEOCIE ADC_IER_JEOCIE_Msk /*!< ADC End of Injected Conversion interrupt source */ +#define ADC_IER_JEOSIE_Pos (6U) +#define ADC_IER_JEOSIE_Msk (0x1UL << ADC_IER_JEOSIE_Pos) /*!< 0x00000040 */ +#define ADC_IER_JEOSIE ADC_IER_JEOSIE_Msk /*!< ADC End of Injected sequence of Conversions interrupt source */ +#define ADC_IER_AWD1IE_Pos (7U) +#define ADC_IER_AWD1IE_Msk (0x1UL << ADC_IER_AWD1IE_Pos) /*!< 0x00000080 */ +#define ADC_IER_AWD1IE ADC_IER_AWD1IE_Msk /*!< ADC Analog watchdog 1 interrupt source */ +#define ADC_IER_AWD2IE_Pos (8U) +#define ADC_IER_AWD2IE_Msk (0x1UL << ADC_IER_AWD2IE_Pos) /*!< 0x00000100 */ +#define ADC_IER_AWD2IE ADC_IER_AWD2IE_Msk /*!< ADC Analog watchdog 2 interrupt source */ +#define ADC_IER_AWD3IE_Pos (9U) +#define ADC_IER_AWD3IE_Msk (0x1UL << ADC_IER_AWD3IE_Pos) /*!< 0x00000200 */ +#define ADC_IER_AWD3IE ADC_IER_AWD3IE_Msk /*!< ADC Analog watchdog 3 interrupt source */ +#define ADC_IER_JQOVFIE_Pos (10U) +#define ADC_IER_JQOVFIE_Msk (0x1UL << ADC_IER_JQOVFIE_Pos) /*!< 0x00000400 */ +#define ADC_IER_JQOVFIE ADC_IER_JQOVFIE_Msk /*!< ADC Injected Context Queue Overflow interrupt source */ + +/******************** Bit definition for ADC_CR register ********************/ +#define ADC_CR_ADEN_Pos (0U) +#define ADC_CR_ADEN_Msk (0x1UL << ADC_CR_ADEN_Pos) /*!< 0x00000001 */ +#define ADC_CR_ADEN ADC_CR_ADEN_Msk /*!< ADC Enable control */ +#define ADC_CR_ADDIS_Pos (1U) +#define ADC_CR_ADDIS_Msk (0x1UL << ADC_CR_ADDIS_Pos) /*!< 0x00000002 */ +#define ADC_CR_ADDIS ADC_CR_ADDIS_Msk /*!< ADC Disable command */ +#define ADC_CR_ADSTART_Pos (2U) +#define ADC_CR_ADSTART_Msk (0x1UL << ADC_CR_ADSTART_Pos) /*!< 0x00000004 */ +#define ADC_CR_ADSTART ADC_CR_ADSTART_Msk /*!< ADC Start of Regular conversion */ +#define ADC_CR_JADSTART_Pos (3U) +#define ADC_CR_JADSTART_Msk (0x1UL << ADC_CR_JADSTART_Pos) /*!< 0x00000008 */ +#define ADC_CR_JADSTART ADC_CR_JADSTART_Msk /*!< ADC Start of injected conversion */ +#define ADC_CR_ADSTP_Pos (4U) +#define ADC_CR_ADSTP_Msk (0x1UL << ADC_CR_ADSTP_Pos) /*!< 0x00000010 */ +#define ADC_CR_ADSTP ADC_CR_ADSTP_Msk /*!< ADC Stop of Regular conversion */ +#define ADC_CR_JADSTP_Pos (5U) +#define ADC_CR_JADSTP_Msk (0x1UL << ADC_CR_JADSTP_Pos) /*!< 0x00000020 */ +#define ADC_CR_JADSTP ADC_CR_JADSTP_Msk /*!< ADC Stop of injected conversion */ +#define ADC_CR_BOOST_Pos (8U) +#define ADC_CR_BOOST_Msk (0x3UL << ADC_CR_BOOST_Pos) /*!< 0x00000300 */ +#define ADC_CR_BOOST ADC_CR_BOOST_Msk /*!< ADC Boost Mode configuration */ +#define ADC_CR_BOOST_0 (0x1UL << ADC_CR_BOOST_Pos) /*!< 0x00000100 */ +#define ADC_CR_BOOST_1 (0x2UL << ADC_CR_BOOST_Pos) /*!< 0x00000200 */ +#define ADC_CR_ADCALLIN_Pos (16U) +#define ADC_CR_ADCALLIN_Msk (0x1UL << ADC_CR_ADCALLIN_Pos) /*!< 0x00010000 */ +#define ADC_CR_ADCALLIN ADC_CR_ADCALLIN_Msk /*!< ADC Linearity calibration */ +#define ADC_CR_LINCALRDYW1_Pos (22U) +#define ADC_CR_LINCALRDYW1_Msk (0x1UL << ADC_CR_LINCALRDYW1_Pos) /*!< 0x00400000 */ +#define ADC_CR_LINCALRDYW1 ADC_CR_LINCALRDYW1_Msk /*!< ADC Linearity calibration ready Word 1 */ +#define ADC_CR_LINCALRDYW2_Pos (23U) +#define ADC_CR_LINCALRDYW2_Msk (0x1UL << ADC_CR_LINCALRDYW2_Pos) /*!< 0x00800000 */ +#define ADC_CR_LINCALRDYW2 ADC_CR_LINCALRDYW2_Msk /*!< ADC Linearity calibration ready Word 2 */ +#define ADC_CR_LINCALRDYW3_Pos (24U) +#define ADC_CR_LINCALRDYW3_Msk (0x1UL << ADC_CR_LINCALRDYW3_Pos) /*!< 0x01000000 */ +#define ADC_CR_LINCALRDYW3 ADC_CR_LINCALRDYW3_Msk /*!< ADC Linearity calibration ready Word 3 */ +#define ADC_CR_LINCALRDYW4_Pos (25U) +#define ADC_CR_LINCALRDYW4_Msk (0x1UL << ADC_CR_LINCALRDYW4_Pos) /*!< 0x02000000 */ +#define ADC_CR_LINCALRDYW4 ADC_CR_LINCALRDYW4_Msk /*!< ADC Linearity calibration ready Word 4 */ +#define ADC_CR_LINCALRDYW5_Pos (26U) +#define ADC_CR_LINCALRDYW5_Msk (0x1UL << ADC_CR_LINCALRDYW5_Pos) /*!< 0x04000000 */ +#define ADC_CR_LINCALRDYW5 ADC_CR_LINCALRDYW5_Msk /*!< ADC Linearity calibration ready Word 5 */ +#define ADC_CR_LINCALRDYW6_Pos (27U) +#define ADC_CR_LINCALRDYW6_Msk (0x1UL << ADC_CR_LINCALRDYW6_Pos) /*!< 0x08000000 */ +#define ADC_CR_LINCALRDYW6 ADC_CR_LINCALRDYW6_Msk /*!< ADC Linearity calibration ready Word 6 */ +#define ADC_CR_ADVREGEN_Pos (28U) +#define ADC_CR_ADVREGEN_Msk (0x1UL << ADC_CR_ADVREGEN_Pos) /*!< 0x10000000 */ +#define ADC_CR_ADVREGEN ADC_CR_ADVREGEN_Msk /*!< ADC Voltage regulator Enable */ +#define ADC_CR_DEEPPWD_Pos (29U) +#define ADC_CR_DEEPPWD_Msk (0x1UL << ADC_CR_DEEPPWD_Pos) /*!< 0x20000000 */ +#define ADC_CR_DEEPPWD ADC_CR_DEEPPWD_Msk /*!< ADC Deep power down Enable */ +#define ADC_CR_ADCALDIF_Pos (30U) +#define ADC_CR_ADCALDIF_Msk (0x1UL << ADC_CR_ADCALDIF_Pos) /*!< 0x40000000 */ +#define ADC_CR_ADCALDIF ADC_CR_ADCALDIF_Msk /*!< ADC Differential Mode for calibration */ +#define ADC_CR_ADCAL_Pos (31U) +#define ADC_CR_ADCAL_Msk (0x1UL << ADC_CR_ADCAL_Pos) /*!< 0x80000000 */ +#define ADC_CR_ADCAL ADC_CR_ADCAL_Msk /*!< ADC Calibration */ + +/******************** Bit definition for ADC_CFGR register ********************/ +#define ADC_CFGR_DMNGT_Pos (0U) +#define ADC_CFGR_DMNGT_Msk (0x3UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000003 */ +#define ADC_CFGR_DMNGT ADC_CFGR_DMNGT_Msk /*!< ADC Data Management configuration */ +#define ADC_CFGR_DMNGT_0 (0x1UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000001 */ +#define ADC_CFGR_DMNGT_1 (0x2UL << ADC_CFGR_DMNGT_Pos) /*!< 0x00000002 */ + +#define ADC_CFGR_RES_Pos (2U) +#define ADC_CFGR_RES_Msk (0x7UL << ADC_CFGR_RES_Pos) /*!< 0x0000001C */ +#define ADC_CFGR_RES ADC_CFGR_RES_Msk /*!< ADC Data resolution */ +#define ADC_CFGR_RES_0 (0x1UL << ADC_CFGR_RES_Pos) /*!< 0x00000004 */ +#define ADC_CFGR_RES_1 (0x2UL << ADC_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC_CFGR_RES_2 (0x4UL << ADC_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC_CFGR_EXTSEL_Pos (5U) +#define ADC_CFGR_EXTSEL_Msk (0x1FUL << ADC_CFGR_EXTSEL_Pos) /*!< 0x000003E0 */ +#define ADC_CFGR_EXTSEL ADC_CFGR_EXTSEL_Msk /*!< ADC External trigger selection for regular group */ +#define ADC_CFGR_EXTSEL_0 (0x01UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_CFGR_EXTSEL_1 (0x02UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000040 */ +#define ADC_CFGR_EXTSEL_2 (0x04UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000080 */ +#define ADC_CFGR_EXTSEL_3 (0x08UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000100 */ +#define ADC_CFGR_EXTSEL_4 (0x10UL << ADC_CFGR_EXTSEL_Pos) /*!< 0x00000200 */ + +#define ADC_CFGR_EXTEN_Pos (10U) +#define ADC_CFGR_EXTEN_Msk (0x3UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000C00 */ +#define ADC_CFGR_EXTEN ADC_CFGR_EXTEN_Msk /*!< ADC External trigger enable and polarity selection for regular channels */ +#define ADC_CFGR_EXTEN_0 (0x1UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000400 */ +#define ADC_CFGR_EXTEN_1 (0x2UL << ADC_CFGR_EXTEN_Pos) /*!< 0x00000800 */ + +#define ADC_CFGR_OVRMOD_Pos (12U) +#define ADC_CFGR_OVRMOD_Msk (0x1UL << ADC_CFGR_OVRMOD_Pos) /*!< 0x00001000 */ +#define ADC_CFGR_OVRMOD ADC_CFGR_OVRMOD_Msk /*!< ADC overrun mode */ +#define ADC_CFGR_CONT_Pos (13U) +#define ADC_CFGR_CONT_Msk (0x1UL << ADC_CFGR_CONT_Pos) /*!< 0x00002000 */ +#define ADC_CFGR_CONT ADC_CFGR_CONT_Msk /*!< ADC Single/continuous conversion mode for regular conversion */ +#define ADC_CFGR_AUTDLY_Pos (14U) +#define ADC_CFGR_AUTDLY_Msk (0x1UL << ADC_CFGR_AUTDLY_Pos) /*!< 0x00004000 */ +#define ADC_CFGR_AUTDLY ADC_CFGR_AUTDLY_Msk /*!< ADC Delayed conversion mode */ + +#define ADC_CFGR_DISCEN_Pos (16U) +#define ADC_CFGR_DISCEN_Msk (0x1UL << ADC_CFGR_DISCEN_Pos) /*!< 0x00010000 */ +#define ADC_CFGR_DISCEN ADC_CFGR_DISCEN_Msk /*!< ADC Discontinuous mode for regular channels */ + +#define ADC_CFGR_DISCNUM_Pos (17U) +#define ADC_CFGR_DISCNUM_Msk (0x7UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x000E0000 */ +#define ADC_CFGR_DISCNUM ADC_CFGR_DISCNUM_Msk /*!< ADC Discontinuous mode channel count */ +#define ADC_CFGR_DISCNUM_0 (0x1UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00020000 */ +#define ADC_CFGR_DISCNUM_1 (0x2UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00040000 */ +#define ADC_CFGR_DISCNUM_2 (0x4UL << ADC_CFGR_DISCNUM_Pos) /*!< 0x00080000 */ + +#define ADC_CFGR_JDISCEN_Pos (20U) +#define ADC_CFGR_JDISCEN_Msk (0x1UL << ADC_CFGR_JDISCEN_Pos) /*!< 0x00100000 */ +#define ADC_CFGR_JDISCEN ADC_CFGR_JDISCEN_Msk /*!< ADC Discontinuous mode on injected channels */ +#define ADC_CFGR_JQM_Pos (21U) +#define ADC_CFGR_JQM_Msk (0x1UL << ADC_CFGR_JQM_Pos) /*!< 0x00200000 */ +#define ADC_CFGR_JQM ADC_CFGR_JQM_Msk /*!< ADC JSQR Queue mode */ +#define ADC_CFGR_AWD1SGL_Pos (22U) +#define ADC_CFGR_AWD1SGL_Msk (0x1UL << ADC_CFGR_AWD1SGL_Pos) /*!< 0x00400000 */ +#define ADC_CFGR_AWD1SGL ADC_CFGR_AWD1SGL_Msk /*!< Enable the watchdog 1 on a single channel or on all channels */ +#define ADC_CFGR_AWD1EN_Pos (23U) +#define ADC_CFGR_AWD1EN_Msk (0x1UL << ADC_CFGR_AWD1EN_Pos) /*!< 0x00800000 */ +#define ADC_CFGR_AWD1EN ADC_CFGR_AWD1EN_Msk /*!< ADC Analog watchdog 1 enable on regular Channels */ +#define ADC_CFGR_JAWD1EN_Pos (24U) +#define ADC_CFGR_JAWD1EN_Msk (0x1UL << ADC_CFGR_JAWD1EN_Pos) /*!< 0x01000000 */ +#define ADC_CFGR_JAWD1EN ADC_CFGR_JAWD1EN_Msk /*!< ADC Analog watchdog 1 enable on injected Channels */ +#define ADC_CFGR_JAUTO_Pos (25U) +#define ADC_CFGR_JAUTO_Msk (0x1UL << ADC_CFGR_JAUTO_Pos) /*!< 0x02000000 */ +#define ADC_CFGR_JAUTO ADC_CFGR_JAUTO_Msk /*!< ADC Automatic injected group conversion */ + +#define ADC_CFGR_AWD1CH_Pos (26U) +#define ADC_CFGR_AWD1CH_Msk (0x1FUL << ADC_CFGR_AWD1CH_Pos) /*!< 0x7C000000 */ +#define ADC_CFGR_AWD1CH ADC_CFGR_AWD1CH_Msk /*!< ADC Analog watchdog 1 Channel selection */ +#define ADC_CFGR_AWD1CH_0 (0x01UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x04000000 */ +#define ADC_CFGR_AWD1CH_1 (0x02UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x08000000 */ +#define ADC_CFGR_AWD1CH_2 (0x04UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x10000000 */ +#define ADC_CFGR_AWD1CH_3 (0x08UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x20000000 */ +#define ADC_CFGR_AWD1CH_4 (0x10UL << ADC_CFGR_AWD1CH_Pos) /*!< 0x40000000 */ + +#define ADC_CFGR_JQDIS_Pos (31U) +#define ADC_CFGR_JQDIS_Msk (0x1UL << ADC_CFGR_JQDIS_Pos) /*!< 0x80000000 */ +#define ADC_CFGR_JQDIS ADC_CFGR_JQDIS_Msk /*!< ADC Injected queue disable */ + +#define ADC3_CFGR_DMAEN_Pos (0U) +#define ADC3_CFGR_DMAEN_Msk (0x1UL << ADC3_CFGR_DMAEN_Pos) /*!< 0x00000001 */ +#define ADC3_CFGR_DMAEN ADC3_CFGR_DMAEN_Msk /*!< ADC DMA transfer enable */ +#define ADC3_CFGR_DMACFG_Pos (1U) +#define ADC3_CFGR_DMACFG_Msk (0x1UL << ADC3_CFGR_DMACFG_Pos) /*!< 0x00000002 */ +#define ADC3_CFGR_DMACFG ADC3_CFGR_DMACFG_Msk /*!< ADC DMA transfer configuration */ + +#define ADC3_CFGR_RES_Pos (3U) +#define ADC3_CFGR_RES_Msk (0x3UL << ADC3_CFGR_RES_Pos) /*!< 0x00000018 */ +#define ADC3_CFGR_RES ADC3_CFGR_RES_Msk /*!< ADC data resolution */ +#define ADC3_CFGR_RES_0 (0x1UL << ADC3_CFGR_RES_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR_RES_1 (0x2UL << ADC3_CFGR_RES_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR_ALIGN_Pos (15U) +#define ADC3_CFGR_ALIGN_Msk (0x1UL << ADC3_CFGR_ALIGN_Pos) /*!< 0x00008000 */ +#define ADC3_CFGR_ALIGN ADC3_CFGR_ALIGN_Msk /*!< ADC data alignment */ +/******************** Bit definition for ADC_CFGR2 register ********************/ +#define ADC_CFGR2_ROVSE_Pos (0U) +#define ADC_CFGR2_ROVSE_Msk (0x1UL << ADC_CFGR2_ROVSE_Pos) /*!< 0x00000001 */ +#define ADC_CFGR2_ROVSE ADC_CFGR2_ROVSE_Msk /*!< ADC Regular group oversampler enable */ +#define ADC_CFGR2_JOVSE_Pos (1U) +#define ADC_CFGR2_JOVSE_Msk (0x1UL << ADC_CFGR2_JOVSE_Pos) /*!< 0x00000002 */ +#define ADC_CFGR2_JOVSE ADC_CFGR2_JOVSE_Msk /*!< ADC Injected group oversampler enable */ + +#define ADC_CFGR2_OVSS_Pos (5U) +#define ADC_CFGR2_OVSS_Msk (0xFUL << ADC_CFGR2_OVSS_Pos) /*!< 0x000001E0 */ +#define ADC_CFGR2_OVSS ADC_CFGR2_OVSS_Msk /*!< ADC Regular Oversampling shift */ +#define ADC_CFGR2_OVSS_0 (0x1UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000020 */ +#define ADC_CFGR2_OVSS_1 (0x2UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000040 */ +#define ADC_CFGR2_OVSS_2 (0x4UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000080 */ +#define ADC_CFGR2_OVSS_3 (0x8UL << ADC_CFGR2_OVSS_Pos) /*!< 0x00000100 */ + +#define ADC_CFGR2_TROVS_Pos (9U) +#define ADC_CFGR2_TROVS_Msk (0x1UL << ADC_CFGR2_TROVS_Pos) /*!< 0x00000200 */ +#define ADC_CFGR2_TROVS ADC_CFGR2_TROVS_Msk /*!< ADC Triggered regular Oversampling */ +#define ADC_CFGR2_ROVSM_Pos (10U) +#define ADC_CFGR2_ROVSM_Msk (0x1UL << ADC_CFGR2_ROVSM_Pos) /*!< 0x00000400 */ +#define ADC_CFGR2_ROVSM ADC_CFGR2_ROVSM_Msk /*!< ADC Regular oversampling mode */ + +#define ADC_CFGR2_RSHIFT1_Pos (11U) +#define ADC_CFGR2_RSHIFT1_Msk (0x1UL << ADC_CFGR2_RSHIFT1_Pos) /*!< 0x00000800 */ +#define ADC_CFGR2_RSHIFT1 ADC_CFGR2_RSHIFT1_Msk /*!< ADC Right-shift data after Offset 1 correction */ +#define ADC_CFGR2_RSHIFT2_Pos (12U) +#define ADC_CFGR2_RSHIFT2_Msk (0x1UL << ADC_CFGR2_RSHIFT2_Pos) /*!< 0x00001000 */ +#define ADC_CFGR2_RSHIFT2 ADC_CFGR2_RSHIFT2_Msk /*!< ADC Right-shift data after Offset 2 correction */ +#define ADC_CFGR2_RSHIFT3_Pos (13U) +#define ADC_CFGR2_RSHIFT3_Msk (0x1UL << ADC_CFGR2_RSHIFT3_Pos) /*!< 0x00002000 */ +#define ADC_CFGR2_RSHIFT3 ADC_CFGR2_RSHIFT3_Msk /*!< ADC Right-shift data after Offset 3 correction */ +#define ADC_CFGR2_RSHIFT4_Pos (14U) +#define ADC_CFGR2_RSHIFT4_Msk (0x1UL << ADC_CFGR2_RSHIFT4_Pos) /*!< 0x00004000 */ +#define ADC_CFGR2_RSHIFT4 ADC_CFGR2_RSHIFT4_Msk /*!< ADC Right-shift data after Offset 4 correction */ + +#define ADC_CFGR2_OVSR_Pos (16U) +#define ADC_CFGR2_OVSR_Msk (0x3FFUL << ADC_CFGR2_OVSR_Pos) /*!< 0x03FF0000 */ +#define ADC_CFGR2_OVSR ADC_CFGR2_OVSR_Msk /*!< ADC oversampling Ratio */ +#define ADC_CFGR2_OVSR_0 (0x001UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00010000 */ +#define ADC_CFGR2_OVSR_1 (0x002UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00020000 */ +#define ADC_CFGR2_OVSR_2 (0x004UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00040000 */ +#define ADC_CFGR2_OVSR_3 (0x008UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00080000 */ +#define ADC_CFGR2_OVSR_4 (0x010UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00100000 */ +#define ADC_CFGR2_OVSR_5 (0x020UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00200000 */ +#define ADC_CFGR2_OVSR_6 (0x040UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00400000 */ +#define ADC_CFGR2_OVSR_7 (0x080UL << ADC_CFGR2_OVSR_Pos) /*!< 0x00800000 */ +#define ADC_CFGR2_OVSR_8 (0x100UL << ADC_CFGR2_OVSR_Pos) /*!< 0x01000000 */ +#define ADC_CFGR2_OVSR_9 (0x200UL << ADC_CFGR2_OVSR_Pos) /*!< 0x02000000 */ + +#define ADC_CFGR2_LSHIFT_Pos (28U) +#define ADC_CFGR2_LSHIFT_Msk (0xFUL << ADC_CFGR2_LSHIFT_Pos) /*!< 0xF0000000 */ +#define ADC_CFGR2_LSHIFT ADC_CFGR2_LSHIFT_Msk /*!< ADC Left shift factor */ +#define ADC_CFGR2_LSHIFT_0 (0x1UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x10000000 */ +#define ADC_CFGR2_LSHIFT_1 (0x2UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x20000000 */ +#define ADC_CFGR2_LSHIFT_2 (0x4UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x40000000 */ +#define ADC_CFGR2_LSHIFT_3 (0x8UL << ADC_CFGR2_LSHIFT_Pos) /*!< 0x80000000 */ + +#define ADC3_CFGR2_OVSR_Pos (2U) +#define ADC3_CFGR2_OVSR_Msk (0x7UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x0000001C */ +#define ADC3_CFGR2_OVSR ADC3_CFGR2_OVSR_Msk /*!< ADC oversampling ratio */ +#define ADC3_CFGR2_OVSR_0 (0x1UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000004 */ +#define ADC3_CFGR2_OVSR_1 (0x2UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000008 */ +#define ADC3_CFGR2_OVSR_2 (0x4UL << ADC3_CFGR2_OVSR_Pos) /*!< 0x00000010 */ + +#define ADC3_CFGR2_SWTRIG_Pos (25U) +#define ADC3_CFGR2_SWTRIG_Msk (0x1UL << ADC3_CFGR2_SWTRIG_Pos) /*!< 0x02000000 */ +#define ADC3_CFGR2_SWTRIG ADC3_CFGR2_SWTRIG_Msk /*!< ADC Software Trigger Bit for Sample time control trigger mode */ +#define ADC3_CFGR2_BULB_Pos (26U) +#define ADC3_CFGR2_BULB_Msk (0x1UL << ADC3_CFGR2_BULB_Pos) /*!< 0x04000000 */ +#define ADC3_CFGR2_BULB ADC3_CFGR2_BULB_Msk /*!< ADC Bulb sampling mode */ +#define ADC3_CFGR2_SMPTRIG_Pos (27U) +#define ADC3_CFGR2_SMPTRIG_Msk (0x1UL << ADC3_CFGR2_SMPTRIG_Pos) /*!< 0x08000000 */ +#define ADC3_CFGR2_SMPTRIG ADC3_CFGR2_SMPTRIG_Msk /*!< ADC Sample Time Control Trigger mode */ +/******************** Bit definition for ADC_SMPR1 register ********************/ +#define ADC_SMPR1_SMP0_Pos (0U) +#define ADC_SMPR1_SMP0_Msk (0x7UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000007 */ +#define ADC_SMPR1_SMP0 ADC_SMPR1_SMP0_Msk /*!< ADC Channel 0 Sampling time selection */ +#define ADC_SMPR1_SMP0_0 (0x1UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000001 */ +#define ADC_SMPR1_SMP0_1 (0x2UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000002 */ +#define ADC_SMPR1_SMP0_2 (0x4UL << ADC_SMPR1_SMP0_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR1_SMP1_Pos (3U) +#define ADC_SMPR1_SMP1_Msk (0x7UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000038 */ +#define ADC_SMPR1_SMP1 ADC_SMPR1_SMP1_Msk /*!< ADC Channel 1 Sampling time selection */ +#define ADC_SMPR1_SMP1_0 (0x1UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000008 */ +#define ADC_SMPR1_SMP1_1 (0x2UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000010 */ +#define ADC_SMPR1_SMP1_2 (0x4UL << ADC_SMPR1_SMP1_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR1_SMP2_Pos (6U) +#define ADC_SMPR1_SMP2_Msk (0x7UL << ADC_SMPR1_SMP2_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR1_SMP2 ADC_SMPR1_SMP2_Msk /*!< ADC Channel 2 Sampling time selection */ +#define ADC_SMPR1_SMP2_0 (0x1UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000040 */ +#define ADC_SMPR1_SMP2_1 (0x2UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000080 */ +#define ADC_SMPR1_SMP2_2 (0x4UL << ADC_SMPR1_SMP2_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR1_SMP3_Pos (9U) +#define ADC_SMPR1_SMP3_Msk (0x7UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR1_SMP3 ADC_SMPR1_SMP3_Msk /*!< ADC Channel 3 Sampling time selection */ +#define ADC_SMPR1_SMP3_0 (0x1UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000200 */ +#define ADC_SMPR1_SMP3_1 (0x2UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000400 */ +#define ADC_SMPR1_SMP3_2 (0x4UL << ADC_SMPR1_SMP3_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR1_SMP4_Pos (12U) +#define ADC_SMPR1_SMP4_Msk (0x7UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00007000 */ +#define ADC_SMPR1_SMP4 ADC_SMPR1_SMP4_Msk /*!< ADC Channel 4 Sampling time selection */ +#define ADC_SMPR1_SMP4_0 (0x1UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00001000 */ +#define ADC_SMPR1_SMP4_1 (0x2UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00002000 */ +#define ADC_SMPR1_SMP4_2 (0x4UL << ADC_SMPR1_SMP4_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR1_SMP5_Pos (15U) +#define ADC_SMPR1_SMP5_Msk (0x7UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00038000 */ +#define ADC_SMPR1_SMP5 ADC_SMPR1_SMP5_Msk /*!< ADC Channel 5 Sampling time selection */ +#define ADC_SMPR1_SMP5_0 (0x1UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00008000 */ +#define ADC_SMPR1_SMP5_1 (0x2UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00010000 */ +#define ADC_SMPR1_SMP5_2 (0x4UL << ADC_SMPR1_SMP5_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR1_SMP6_Pos (18U) +#define ADC_SMPR1_SMP6_Msk (0x7UL << ADC_SMPR1_SMP6_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR1_SMP6 ADC_SMPR1_SMP6_Msk /*!< ADC Channel 6 Sampling time selection */ +#define ADC_SMPR1_SMP6_0 (0x1UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00040000 */ +#define ADC_SMPR1_SMP6_1 (0x2UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00080000 */ +#define ADC_SMPR1_SMP6_2 (0x4UL << ADC_SMPR1_SMP6_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR1_SMP7_Pos (21U) +#define ADC_SMPR1_SMP7_Msk (0x7UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR1_SMP7 ADC_SMPR1_SMP7_Msk /*!< ADC Channel 7 Sampling time selection */ +#define ADC_SMPR1_SMP7_0 (0x1UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00200000 */ +#define ADC_SMPR1_SMP7_1 (0x2UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00400000 */ +#define ADC_SMPR1_SMP7_2 (0x4UL << ADC_SMPR1_SMP7_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR1_SMP8_Pos (24U) +#define ADC_SMPR1_SMP8_Msk (0x7UL << ADC_SMPR1_SMP8_Pos) /*!< 0x07000000 */ +#define ADC_SMPR1_SMP8 ADC_SMPR1_SMP8_Msk /*!< ADC Channel 8 Sampling time selection */ +#define ADC_SMPR1_SMP8_0 (0x1UL << ADC_SMPR1_SMP8_Pos) /*!< 0x01000000 */ +#define ADC_SMPR1_SMP8_1 (0x2UL << ADC_SMPR1_SMP8_Pos) /*!< 0x02000000 */ +#define ADC_SMPR1_SMP8_2 (0x4UL << ADC_SMPR1_SMP8_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR1_SMP9_Pos (27U) +#define ADC_SMPR1_SMP9_Msk (0x7UL << ADC_SMPR1_SMP9_Pos) /*!< 0x38000000 */ +#define ADC_SMPR1_SMP9 ADC_SMPR1_SMP9_Msk /*!< ADC Channel 9 Sampling time selection */ +#define ADC_SMPR1_SMP9_0 (0x1UL << ADC_SMPR1_SMP9_Pos) /*!< 0x08000000 */ +#define ADC_SMPR1_SMP9_1 (0x2UL << ADC_SMPR1_SMP9_Pos) /*!< 0x10000000 */ +#define ADC_SMPR1_SMP9_2 (0x4UL << ADC_SMPR1_SMP9_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_SMPR2 register ********************/ +#define ADC_SMPR2_SMP10_Pos (0U) +#define ADC_SMPR2_SMP10_Msk (0x7UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000007 */ +#define ADC_SMPR2_SMP10 ADC_SMPR2_SMP10_Msk /*!< ADC Channel 10 Sampling time selection */ +#define ADC_SMPR2_SMP10_0 (0x1UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000001 */ +#define ADC_SMPR2_SMP10_1 (0x2UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000002 */ +#define ADC_SMPR2_SMP10_2 (0x4UL << ADC_SMPR2_SMP10_Pos) /*!< 0x00000004 */ + +#define ADC_SMPR2_SMP11_Pos (3U) +#define ADC_SMPR2_SMP11_Msk (0x7UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000038 */ +#define ADC_SMPR2_SMP11 ADC_SMPR2_SMP11_Msk /*!< ADC Channel 11 Sampling time selection */ +#define ADC_SMPR2_SMP11_0 (0x1UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000008 */ +#define ADC_SMPR2_SMP11_1 (0x2UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000010 */ +#define ADC_SMPR2_SMP11_2 (0x4UL << ADC_SMPR2_SMP11_Pos) /*!< 0x00000020 */ + +#define ADC_SMPR2_SMP12_Pos (6U) +#define ADC_SMPR2_SMP12_Msk (0x7UL << ADC_SMPR2_SMP12_Pos) /*!< 0x000001C0 */ +#define ADC_SMPR2_SMP12 ADC_SMPR2_SMP12_Msk /*!< ADC Channel 12 Sampling time selection */ +#define ADC_SMPR2_SMP12_0 (0x1UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000040 */ +#define ADC_SMPR2_SMP12_1 (0x2UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000080 */ +#define ADC_SMPR2_SMP12_2 (0x4UL << ADC_SMPR2_SMP12_Pos) /*!< 0x00000100 */ + +#define ADC_SMPR2_SMP13_Pos (9U) +#define ADC_SMPR2_SMP13_Msk (0x7UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000E00 */ +#define ADC_SMPR2_SMP13 ADC_SMPR2_SMP13_Msk /*!< ADC Channel 13 Sampling time selection */ +#define ADC_SMPR2_SMP13_0 (0x1UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000200 */ +#define ADC_SMPR2_SMP13_1 (0x2UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000400 */ +#define ADC_SMPR2_SMP13_2 (0x4UL << ADC_SMPR2_SMP13_Pos) /*!< 0x00000800 */ + +#define ADC_SMPR2_SMP14_Pos (12U) +#define ADC_SMPR2_SMP14_Msk (0x7UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00007000 */ +#define ADC_SMPR2_SMP14 ADC_SMPR2_SMP14_Msk /*!< ADC Channel 14 Sampling time selection */ +#define ADC_SMPR2_SMP14_0 (0x1UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00001000 */ +#define ADC_SMPR2_SMP14_1 (0x2UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00002000 */ +#define ADC_SMPR2_SMP14_2 (0x4UL << ADC_SMPR2_SMP14_Pos) /*!< 0x00004000 */ + +#define ADC_SMPR2_SMP15_Pos (15U) +#define ADC_SMPR2_SMP15_Msk (0x7UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00038000 */ +#define ADC_SMPR2_SMP15 ADC_SMPR2_SMP15_Msk /*!< ADC Channel 15 Sampling time selection */ +#define ADC_SMPR2_SMP15_0 (0x1UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00008000 */ +#define ADC_SMPR2_SMP15_1 (0x2UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00010000 */ +#define ADC_SMPR2_SMP15_2 (0x4UL << ADC_SMPR2_SMP15_Pos) /*!< 0x00020000 */ + +#define ADC_SMPR2_SMP16_Pos (18U) +#define ADC_SMPR2_SMP16_Msk (0x7UL << ADC_SMPR2_SMP16_Pos) /*!< 0x001C0000 */ +#define ADC_SMPR2_SMP16 ADC_SMPR2_SMP16_Msk /*!< ADC Channel 16 Sampling time selection */ +#define ADC_SMPR2_SMP16_0 (0x1UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00040000 */ +#define ADC_SMPR2_SMP16_1 (0x2UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00080000 */ +#define ADC_SMPR2_SMP16_2 (0x4UL << ADC_SMPR2_SMP16_Pos) /*!< 0x00100000 */ + +#define ADC_SMPR2_SMP17_Pos (21U) +#define ADC_SMPR2_SMP17_Msk (0x7UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00E00000 */ +#define ADC_SMPR2_SMP17 ADC_SMPR2_SMP17_Msk /*!< ADC Channel 17 Sampling time selection */ +#define ADC_SMPR2_SMP17_0 (0x1UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00200000 */ +#define ADC_SMPR2_SMP17_1 (0x2UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00400000 */ +#define ADC_SMPR2_SMP17_2 (0x4UL << ADC_SMPR2_SMP17_Pos) /*!< 0x00800000 */ + +#define ADC_SMPR2_SMP18_Pos (24U) +#define ADC_SMPR2_SMP18_Msk (0x7UL << ADC_SMPR2_SMP18_Pos) /*!< 0x07000000 */ +#define ADC_SMPR2_SMP18 ADC_SMPR2_SMP18_Msk /*!< ADC Channel 18 Sampling time selection */ +#define ADC_SMPR2_SMP18_0 (0x1UL << ADC_SMPR2_SMP18_Pos) /*!< 0x01000000 */ +#define ADC_SMPR2_SMP18_1 (0x2UL << ADC_SMPR2_SMP18_Pos) /*!< 0x02000000 */ +#define ADC_SMPR2_SMP18_2 (0x4UL << ADC_SMPR2_SMP18_Pos) /*!< 0x04000000 */ + +#define ADC_SMPR2_SMP19_Pos (27U) +#define ADC_SMPR2_SMP19_Msk (0x7UL << ADC_SMPR2_SMP19_Pos) /*!< 0x38000000 */ +#define ADC_SMPR2_SMP19 ADC_SMPR2_SMP19_Msk /*!< ADC Channel 19 Sampling time selection */ +#define ADC_SMPR2_SMP19_0 (0x1UL << ADC_SMPR2_SMP19_Pos) /*!< 0x08000000 */ +#define ADC_SMPR2_SMP19_1 (0x2UL << ADC_SMPR2_SMP19_Pos) /*!< 0x10000000 */ +#define ADC_SMPR2_SMP19_2 (0x4UL << ADC_SMPR2_SMP19_Pos) /*!< 0x20000000 */ + +/******************** Bit definition for ADC_PCSEL register ********************/ +#define ADC_PCSEL_PCSEL_Pos (0U) +#define ADC_PCSEL_PCSEL_Msk (0xFFFFFUL << ADC_PCSEL_PCSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_PCSEL_PCSEL ADC_PCSEL_PCSEL_Msk /*!< ADC pre channel selection */ +#define ADC_PCSEL_PCSEL_0 (0x00001UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000001 */ +#define ADC_PCSEL_PCSEL_1 (0x00002UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000002 */ +#define ADC_PCSEL_PCSEL_2 (0x00004UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000004 */ +#define ADC_PCSEL_PCSEL_3 (0x00008UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000008 */ +#define ADC_PCSEL_PCSEL_4 (0x00010UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000010 */ +#define ADC_PCSEL_PCSEL_5 (0x00020UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000020 */ +#define ADC_PCSEL_PCSEL_6 (0x00040UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000040 */ +#define ADC_PCSEL_PCSEL_7 (0x00080UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000080 */ +#define ADC_PCSEL_PCSEL_8 (0x00100UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000100 */ +#define ADC_PCSEL_PCSEL_9 (0x00200UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000200 */ +#define ADC_PCSEL_PCSEL_10 (0x00400UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000400 */ +#define ADC_PCSEL_PCSEL_11 (0x00800UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00000800 */ +#define ADC_PCSEL_PCSEL_12 (0x01000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00001000 */ +#define ADC_PCSEL_PCSEL_13 (0x02000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00002000 */ +#define ADC_PCSEL_PCSEL_14 (0x04000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00004000 */ +#define ADC_PCSEL_PCSEL_15 (0x08000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00008000 */ +#define ADC_PCSEL_PCSEL_16 (0x10000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00010000 */ +#define ADC_PCSEL_PCSEL_17 (0x20000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00020000 */ +#define ADC_PCSEL_PCSEL_18 (0x40000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00040000 */ +#define ADC_PCSEL_PCSEL_19 (0x80000UL << ADC_PCSEL_PCSEL_Pos) /*!< 0x00080000 */ + +/***************** Bit definition for ADC_LTR1, 2, 3 registers *****************/ +#define ADC_LTR_LT_Pos (0U) +#define ADC_LTR_LT_Msk (0x3FFFFFFUL << ADC_LTR_LT_Pos) /*!< 0x03FFFFFF */ +#define ADC_LTR_LT ADC_LTR_LT_Msk /*!< ADC Analog watchdog 1, 2 and 3 lower threshold */ + +/***************** Bit definition for ADC_HTR1, 2, 3 registers ****************/ +#define ADC_HTR_HT_Pos (0U) +#define ADC_HTR_HT_Msk (0x3FFFFFFUL << ADC_HTR_HT_Pos) /*!< 0x03FFFFFF */ +#define ADC_HTR_HT ADC_HTR_HT_Msk /*!< ADC Analog watchdog 1,2 and 3 higher threshold */ + +/******************** Bit definition for ADC3_TR1 register *******************/ +#define ADC3_TR1_LT1_Pos (0U) +#define ADC3_TR1_LT1_Msk (0xFFFUL << ADC3_TR1_LT1_Pos) /*!< 0x00000FFF */ +#define ADC3_TR1_LT1 ADC3_TR1_LT1_Msk /*!< ADC analog watchdog 1 threshold low */ + +#define ADC3_TR1_AWDFILT_Pos (12U) +#define ADC3_TR1_AWDFILT_Msk (0x7UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00007000 */ +#define ADC3_TR1_AWDFILT ADC3_TR1_AWDFILT_Msk /*!< ADC analog watchdog filtering parameter */ +#define ADC3_TR1_AWDFILT_0 (0x1UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00001000 */ +#define ADC3_TR1_AWDFILT_1 (0x2UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00002000 */ +#define ADC3_TR1_AWDFILT_2 (0x4UL << ADC3_TR1_AWDFILT_Pos) /*!< 0x00004000 */ + +#define ADC3_TR1_HT1_Pos (16U) +#define ADC3_TR1_HT1_Msk (0xFFFUL << ADC3_TR1_HT1_Pos) /*!< 0x0FFF0000 */ +#define ADC3_TR1_HT1 ADC3_TR1_HT1_Msk /*!< ADC analog watchdog 1 threshold high */ + +/******************** Bit definition for ADC3_TR2 register *******************/ +#define ADC3_TR2_LT2_Pos (0U) +#define ADC3_TR2_LT2_Msk (0xFFUL << ADC3_TR2_LT2_Pos) /*!< 0x000000FF */ +#define ADC3_TR2_LT2 ADC3_TR2_LT2_Msk /*!< ADC analog watchdog 2 threshold low */ + +#define ADC3_TR2_HT2_Pos (16U) +#define ADC3_TR2_HT2_Msk (0xFFUL << ADC3_TR2_HT2_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR2_HT2 ADC3_TR2_HT2_Msk /*!< ADC analog watchdog 2 threshold high */ + +/******************** Bit definition for ADC3_TR3 register *******************/ +#define ADC3_TR3_LT3_Pos (0U) +#define ADC3_TR3_LT3_Msk (0xFFUL << ADC3_TR3_LT3_Pos) /*!< 0x000000FF */ +#define ADC3_TR3_LT3 ADC3_TR3_LT3_Msk /*!< ADC analog watchdog 3 threshold low */ + +#define ADC3_TR3_HT3_Pos (16U) +#define ADC3_TR3_HT3_Msk (0xFFUL << ADC3_TR3_HT3_Pos) /*!< 0x00FF0000 */ +#define ADC3_TR3_HT3 ADC3_TR3_HT3_Msk /*!< ADC analog watchdog 3 threshold high */ + +/******************** Bit definition for ADC_SQR1 register ********************/ +#define ADC_SQR1_L_Pos (0U) +#define ADC_SQR1_L_Msk (0xFUL << ADC_SQR1_L_Pos) /*!< 0x0000000F */ +#define ADC_SQR1_L ADC_SQR1_L_Msk /*!< ADC regular channel sequence length */ +#define ADC_SQR1_L_0 (0x1UL << ADC_SQR1_L_Pos) /*!< 0x00000001 */ +#define ADC_SQR1_L_1 (0x2UL << ADC_SQR1_L_Pos) /*!< 0x00000002 */ +#define ADC_SQR1_L_2 (0x4UL << ADC_SQR1_L_Pos) /*!< 0x00000004 */ +#define ADC_SQR1_L_3 (0x8UL << ADC_SQR1_L_Pos) /*!< 0x00000008 */ + +#define ADC_SQR1_SQ1_Pos (6U) +#define ADC_SQR1_SQ1_Msk (0x1FUL << ADC_SQR1_SQ1_Pos) /*!< 0x000007C0 */ +#define ADC_SQR1_SQ1 ADC_SQR1_SQ1_Msk /*!< ADC 1st conversion in regular sequence */ +#define ADC_SQR1_SQ1_0 (0x01UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000040 */ +#define ADC_SQR1_SQ1_1 (0x02UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000080 */ +#define ADC_SQR1_SQ1_2 (0x04UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000100 */ +#define ADC_SQR1_SQ1_3 (0x08UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000200 */ +#define ADC_SQR1_SQ1_4 (0x10UL << ADC_SQR1_SQ1_Pos) /*!< 0x00000400 */ + +#define ADC_SQR1_SQ2_Pos (12U) +#define ADC_SQR1_SQ2_Msk (0x1FUL << ADC_SQR1_SQ2_Pos) /*!< 0x0001F000 */ +#define ADC_SQR1_SQ2 ADC_SQR1_SQ2_Msk /*!< ADC 2nd conversion in regular sequence */ +#define ADC_SQR1_SQ2_0 (0x01UL << ADC_SQR1_SQ2_Pos) /*!< 0x00001000 */ +#define ADC_SQR1_SQ2_1 (0x02UL << ADC_SQR1_SQ2_Pos) /*!< 0x00002000 */ +#define ADC_SQR1_SQ2_2 (0x04UL << ADC_SQR1_SQ2_Pos) /*!< 0x00004000 */ +#define ADC_SQR1_SQ2_3 (0x08UL << ADC_SQR1_SQ2_Pos) /*!< 0x00008000 */ +#define ADC_SQR1_SQ2_4 (0x10UL << ADC_SQR1_SQ2_Pos) /*!< 0x00010000 */ + +#define ADC_SQR1_SQ3_Pos (18U) +#define ADC_SQR1_SQ3_Msk (0x1FUL << ADC_SQR1_SQ3_Pos) /*!< 0x007C0000 */ +#define ADC_SQR1_SQ3 ADC_SQR1_SQ3_Msk /*!< ADC 3rd conversion in regular sequence */ +#define ADC_SQR1_SQ3_0 (0x01UL << ADC_SQR1_SQ3_Pos) /*!< 0x00040000 */ +#define ADC_SQR1_SQ3_1 (0x02UL << ADC_SQR1_SQ3_Pos) /*!< 0x00080000 */ +#define ADC_SQR1_SQ3_2 (0x04UL << ADC_SQR1_SQ3_Pos) /*!< 0x00100000 */ +#define ADC_SQR1_SQ3_3 (0x08UL << ADC_SQR1_SQ3_Pos) /*!< 0x00200000 */ +#define ADC_SQR1_SQ3_4 (0x10UL << ADC_SQR1_SQ3_Pos) /*!< 0x00400000 */ + +#define ADC_SQR1_SQ4_Pos (24U) +#define ADC_SQR1_SQ4_Msk (0x1FUL << ADC_SQR1_SQ4_Pos) /*!< 0x1F000000 */ +#define ADC_SQR1_SQ4 ADC_SQR1_SQ4_Msk /*!< ADC 4th conversion in regular sequence */ +#define ADC_SQR1_SQ4_0 (0x01UL << ADC_SQR1_SQ4_Pos) /*!< 0x01000000 */ +#define ADC_SQR1_SQ4_1 (0x02UL << ADC_SQR1_SQ4_Pos) /*!< 0x02000000 */ +#define ADC_SQR1_SQ4_2 (0x04UL << ADC_SQR1_SQ4_Pos) /*!< 0x04000000 */ +#define ADC_SQR1_SQ4_3 (0x08UL << ADC_SQR1_SQ4_Pos) /*!< 0x08000000 */ +#define ADC_SQR1_SQ4_4 (0x10UL << ADC_SQR1_SQ4_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR2 register ********************/ +#define ADC_SQR2_SQ5_Pos (0U) +#define ADC_SQR2_SQ5_Msk (0x1FUL << ADC_SQR2_SQ5_Pos) /*!< 0x0000001F */ +#define ADC_SQR2_SQ5 ADC_SQR2_SQ5_Msk /*!< ADC 5th conversion in regular sequence */ +#define ADC_SQR2_SQ5_0 (0x01UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000001 */ +#define ADC_SQR2_SQ5_1 (0x02UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000002 */ +#define ADC_SQR2_SQ5_2 (0x04UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000004 */ +#define ADC_SQR2_SQ5_3 (0x08UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000008 */ +#define ADC_SQR2_SQ5_4 (0x10UL << ADC_SQR2_SQ5_Pos) /*!< 0x00000010 */ + +#define ADC_SQR2_SQ6_Pos (6U) +#define ADC_SQR2_SQ6_Msk (0x1FUL << ADC_SQR2_SQ6_Pos) /*!< 0x000007C0 */ +#define ADC_SQR2_SQ6 ADC_SQR2_SQ6_Msk /*!< ADC 6th conversion in regular sequence */ +#define ADC_SQR2_SQ6_0 (0x01UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000040 */ +#define ADC_SQR2_SQ6_1 (0x02UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000080 */ +#define ADC_SQR2_SQ6_2 (0x04UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000100 */ +#define ADC_SQR2_SQ6_3 (0x08UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000200 */ +#define ADC_SQR2_SQ6_4 (0x10UL << ADC_SQR2_SQ6_Pos) /*!< 0x00000400 */ + +#define ADC_SQR2_SQ7_Pos (12U) +#define ADC_SQR2_SQ7_Msk (0x1FUL << ADC_SQR2_SQ7_Pos) /*!< 0x0001F000 */ +#define ADC_SQR2_SQ7 ADC_SQR2_SQ7_Msk /*!< ADC 7th conversion in regular sequence */ +#define ADC_SQR2_SQ7_0 (0x01UL << ADC_SQR2_SQ7_Pos) /*!< 0x00001000 */ +#define ADC_SQR2_SQ7_1 (0x02UL << ADC_SQR2_SQ7_Pos) /*!< 0x00002000 */ +#define ADC_SQR2_SQ7_2 (0x04UL << ADC_SQR2_SQ7_Pos) /*!< 0x00004000 */ +#define ADC_SQR2_SQ7_3 (0x08UL << ADC_SQR2_SQ7_Pos) /*!< 0x00008000 */ +#define ADC_SQR2_SQ7_4 (0x10UL << ADC_SQR2_SQ7_Pos) /*!< 0x00010000 */ + +#define ADC_SQR2_SQ8_Pos (18U) +#define ADC_SQR2_SQ8_Msk (0x1FUL << ADC_SQR2_SQ8_Pos) /*!< 0x007C0000 */ +#define ADC_SQR2_SQ8 ADC_SQR2_SQ8_Msk /*!< ADC 8th conversion in regular sequence */ +#define ADC_SQR2_SQ8_0 (0x01UL << ADC_SQR2_SQ8_Pos) /*!< 0x00040000 */ +#define ADC_SQR2_SQ8_1 (0x02UL << ADC_SQR2_SQ8_Pos) /*!< 0x00080000 */ +#define ADC_SQR2_SQ8_2 (0x04UL << ADC_SQR2_SQ8_Pos) /*!< 0x00100000 */ +#define ADC_SQR2_SQ8_3 (0x08UL << ADC_SQR2_SQ8_Pos) /*!< 0x00200000 */ +#define ADC_SQR2_SQ8_4 (0x10UL << ADC_SQR2_SQ8_Pos) /*!< 0x00400000 */ + +#define ADC_SQR2_SQ9_Pos (24U) +#define ADC_SQR2_SQ9_Msk (0x1FUL << ADC_SQR2_SQ9_Pos) /*!< 0x1F000000 */ +#define ADC_SQR2_SQ9 ADC_SQR2_SQ9_Msk /*!< ADC 9th conversion in regular sequence */ +#define ADC_SQR2_SQ9_0 (0x01UL << ADC_SQR2_SQ9_Pos) /*!< 0x01000000 */ +#define ADC_SQR2_SQ9_1 (0x02UL << ADC_SQR2_SQ9_Pos) /*!< 0x02000000 */ +#define ADC_SQR2_SQ9_2 (0x04UL << ADC_SQR2_SQ9_Pos) /*!< 0x04000000 */ +#define ADC_SQR2_SQ9_3 (0x08UL << ADC_SQR2_SQ9_Pos) /*!< 0x08000000 */ +#define ADC_SQR2_SQ9_4 (0x10UL << ADC_SQR2_SQ9_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR3 register ********************/ +#define ADC_SQR3_SQ10_Pos (0U) +#define ADC_SQR3_SQ10_Msk (0x1FUL << ADC_SQR3_SQ10_Pos) /*!< 0x0000001F */ +#define ADC_SQR3_SQ10 ADC_SQR3_SQ10_Msk /*!< ADC 10th conversion in regular sequence */ +#define ADC_SQR3_SQ10_0 (0x01UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000001 */ +#define ADC_SQR3_SQ10_1 (0x02UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000002 */ +#define ADC_SQR3_SQ10_2 (0x04UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000004 */ +#define ADC_SQR3_SQ10_3 (0x08UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000008 */ +#define ADC_SQR3_SQ10_4 (0x10UL << ADC_SQR3_SQ10_Pos) /*!< 0x00000010 */ + +#define ADC_SQR3_SQ11_Pos (6U) +#define ADC_SQR3_SQ11_Msk (0x1FUL << ADC_SQR3_SQ11_Pos) /*!< 0x000007C0 */ +#define ADC_SQR3_SQ11 ADC_SQR3_SQ11_Msk /*!< ADC 11th conversion in regular sequence */ +#define ADC_SQR3_SQ11_0 (0x01UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000040 */ +#define ADC_SQR3_SQ11_1 (0x02UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000080 */ +#define ADC_SQR3_SQ11_2 (0x04UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000100 */ +#define ADC_SQR3_SQ11_3 (0x08UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000200 */ +#define ADC_SQR3_SQ11_4 (0x10UL << ADC_SQR3_SQ11_Pos) /*!< 0x00000400 */ + +#define ADC_SQR3_SQ12_Pos (12U) +#define ADC_SQR3_SQ12_Msk (0x1FUL << ADC_SQR3_SQ12_Pos) /*!< 0x0001F000 */ +#define ADC_SQR3_SQ12 ADC_SQR3_SQ12_Msk /*!< ADC 12th conversion in regular sequence */ +#define ADC_SQR3_SQ12_0 (0x01UL << ADC_SQR3_SQ12_Pos) /*!< 0x00001000 */ +#define ADC_SQR3_SQ12_1 (0x02UL << ADC_SQR3_SQ12_Pos) /*!< 0x00002000 */ +#define ADC_SQR3_SQ12_2 (0x04UL << ADC_SQR3_SQ12_Pos) /*!< 0x00004000 */ +#define ADC_SQR3_SQ12_3 (0x08UL << ADC_SQR3_SQ12_Pos) /*!< 0x00008000 */ +#define ADC_SQR3_SQ12_4 (0x10UL << ADC_SQR3_SQ12_Pos) /*!< 0x00010000 */ + +#define ADC_SQR3_SQ13_Pos (18U) +#define ADC_SQR3_SQ13_Msk (0x1FUL << ADC_SQR3_SQ13_Pos) /*!< 0x007C0000 */ +#define ADC_SQR3_SQ13 ADC_SQR3_SQ13_Msk /*!< ADC 13th conversion in regular sequence */ +#define ADC_SQR3_SQ13_0 (0x01UL << ADC_SQR3_SQ13_Pos) /*!< 0x00040000 */ +#define ADC_SQR3_SQ13_1 (0x02UL << ADC_SQR3_SQ13_Pos) /*!< 0x00080000 */ +#define ADC_SQR3_SQ13_2 (0x04UL << ADC_SQR3_SQ13_Pos) /*!< 0x00100000 */ +#define ADC_SQR3_SQ13_3 (0x08UL << ADC_SQR3_SQ13_Pos) /*!< 0x00200000 */ +#define ADC_SQR3_SQ13_4 (0x10UL << ADC_SQR3_SQ13_Pos) /*!< 0x00400000 */ + +#define ADC_SQR3_SQ14_Pos (24U) +#define ADC_SQR3_SQ14_Msk (0x1FUL << ADC_SQR3_SQ14_Pos) /*!< 0x1F000000 */ +#define ADC_SQR3_SQ14 ADC_SQR3_SQ14_Msk /*!< ADC 14th conversion in regular sequence */ +#define ADC_SQR3_SQ14_0 (0x01UL << ADC_SQR3_SQ14_Pos) /*!< 0x01000000 */ +#define ADC_SQR3_SQ14_1 (0x02UL << ADC_SQR3_SQ14_Pos) /*!< 0x02000000 */ +#define ADC_SQR3_SQ14_2 (0x04UL << ADC_SQR3_SQ14_Pos) /*!< 0x04000000 */ +#define ADC_SQR3_SQ14_3 (0x08UL << ADC_SQR3_SQ14_Pos) /*!< 0x08000000 */ +#define ADC_SQR3_SQ14_4 (0x10UL << ADC_SQR3_SQ14_Pos) /*!< 0x10000000 */ + +/******************** Bit definition for ADC_SQR4 register ********************/ +#define ADC_SQR4_SQ15_Pos (0U) +#define ADC_SQR4_SQ15_Msk (0x1FUL << ADC_SQR4_SQ15_Pos) /*!< 0x0000001F */ +#define ADC_SQR4_SQ15 ADC_SQR4_SQ15_Msk /*!< ADC 15th conversion in regular sequence */ +#define ADC_SQR4_SQ15_0 (0x01UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000001 */ +#define ADC_SQR4_SQ15_1 (0x02UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000002 */ +#define ADC_SQR4_SQ15_2 (0x04UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000004 */ +#define ADC_SQR4_SQ15_3 (0x08UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000008 */ +#define ADC_SQR4_SQ15_4 (0x10UL << ADC_SQR4_SQ15_Pos) /*!< 0x00000010 */ + +#define ADC_SQR4_SQ16_Pos (6U) +#define ADC_SQR4_SQ16_Msk (0x1FUL << ADC_SQR4_SQ16_Pos) /*!< 0x000007C0 */ +#define ADC_SQR4_SQ16 ADC_SQR4_SQ16_Msk /*!< ADC 16th conversion in regular sequence */ +#define ADC_SQR4_SQ16_0 (0x01UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000040 */ +#define ADC_SQR4_SQ16_1 (0x02UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000080 */ +#define ADC_SQR4_SQ16_2 (0x04UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000100 */ +#define ADC_SQR4_SQ16_3 (0x08UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000200 */ +#define ADC_SQR4_SQ16_4 (0x10UL << ADC_SQR4_SQ16_Pos) /*!< 0x00000400 */ +/******************** Bit definition for ADC_DR register ********************/ +#define ADC_DR_RDATA_Pos (0U) +#define ADC_DR_RDATA_Msk (0xFFFFFFFFUL << ADC_DR_RDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_DR_RDATA ADC_DR_RDATA_Msk /*!< ADC regular Data converted */ + +/******************** Bit definition for ADC_JSQR register ********************/ +#define ADC_JSQR_JL_Pos (0U) +#define ADC_JSQR_JL_Msk (0x3UL << ADC_JSQR_JL_Pos) /*!< 0x00000003 */ +#define ADC_JSQR_JL ADC_JSQR_JL_Msk /*!< ADC injected channel sequence length */ +#define ADC_JSQR_JL_0 (0x1UL << ADC_JSQR_JL_Pos) /*!< 0x00000001 */ +#define ADC_JSQR_JL_1 (0x2UL << ADC_JSQR_JL_Pos) /*!< 0x00000002 */ + +#define ADC_JSQR_JEXTSEL_Pos (2U) +#define ADC_JSQR_JEXTSEL_Msk (0x1FUL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x0000007C */ +#define ADC_JSQR_JEXTSEL ADC_JSQR_JEXTSEL_Msk /*!< ADC external trigger selection for injected group */ +#define ADC_JSQR_JEXTSEL_0 (0x01UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000004 */ +#define ADC_JSQR_JEXTSEL_1 (0x02UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000008 */ +#define ADC_JSQR_JEXTSEL_2 (0x04UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000010 */ +#define ADC_JSQR_JEXTSEL_3 (0x08UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000020 */ +#define ADC_JSQR_JEXTSEL_4 (0x10UL << ADC_JSQR_JEXTSEL_Pos) /*!< 0x00000040 */ + +#define ADC_JSQR_JEXTEN_Pos (7U) +#define ADC_JSQR_JEXTEN_Msk (0x3UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000180 */ +#define ADC_JSQR_JEXTEN ADC_JSQR_JEXTEN_Msk /*!< ADC external trigger enable and polarity selection for injected channels */ +#define ADC_JSQR_JEXTEN_0 (0x1UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000080 */ +#define ADC_JSQR_JEXTEN_1 (0x2UL << ADC_JSQR_JEXTEN_Pos) /*!< 0x00000100 */ + +#define ADC_JSQR_JSQ1_Pos (9U) +#define ADC_JSQR_JSQ1_Msk (0x1FUL << ADC_JSQR_JSQ1_Pos) /*!< 0x00003E00 */ +#define ADC_JSQR_JSQ1 ADC_JSQR_JSQ1_Msk /*!< ADC 1st conversion in injected sequence */ +#define ADC_JSQR_JSQ1_0 (0x01UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000200 */ +#define ADC_JSQR_JSQ1_1 (0x02UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000400 */ +#define ADC_JSQR_JSQ1_2 (0x04UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00000800 */ +#define ADC_JSQR_JSQ1_3 (0x08UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00001000 */ +#define ADC_JSQR_JSQ1_4 (0x10UL << ADC_JSQR_JSQ1_Pos) /*!< 0x00002000 */ + +#define ADC_JSQR_JSQ2_Pos (15U) +#define ADC_JSQR_JSQ2_Msk (0x1FUL << ADC_JSQR_JSQ2_Pos) /*!< 0x000F8000 */ +#define ADC_JSQR_JSQ2 ADC_JSQR_JSQ2_Msk /*!< ADC 2nd conversion in injected sequence */ +#define ADC_JSQR_JSQ2_0 (0x01UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00008000 */ +#define ADC_JSQR_JSQ2_1 (0x02UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00010000 */ +#define ADC_JSQR_JSQ2_2 (0x04UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00020000 */ +#define ADC_JSQR_JSQ2_3 (0x08UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00040000 */ +#define ADC_JSQR_JSQ2_4 (0x10UL << ADC_JSQR_JSQ2_Pos) /*!< 0x00080000 */ + +#define ADC_JSQR_JSQ3_Pos (21U) +#define ADC_JSQR_JSQ3_Msk (0x1FUL << ADC_JSQR_JSQ3_Pos) /*!< 0x03E00000 */ +#define ADC_JSQR_JSQ3 ADC_JSQR_JSQ3_Msk /*!< ADC 3rd conversion in injected sequence */ +#define ADC_JSQR_JSQ3_0 (0x01UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00200000 */ +#define ADC_JSQR_JSQ3_1 (0x02UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00400000 */ +#define ADC_JSQR_JSQ3_2 (0x04UL << ADC_JSQR_JSQ3_Pos) /*!< 0x00800000 */ +#define ADC_JSQR_JSQ3_3 (0x08UL << ADC_JSQR_JSQ3_Pos) /*!< 0x01000000 */ +#define ADC_JSQR_JSQ3_4 (0x10UL << ADC_JSQR_JSQ3_Pos) /*!< 0x02000000 */ + +#define ADC_JSQR_JSQ4_Pos (27U) +#define ADC_JSQR_JSQ4_Msk (0x1FUL << ADC_JSQR_JSQ4_Pos) /*!< 0xF8000000 */ +#define ADC_JSQR_JSQ4 ADC_JSQR_JSQ4_Msk /*!< ADC 4th conversion in injected sequence */ +#define ADC_JSQR_JSQ4_0 (0x01UL << ADC_JSQR_JSQ4_Pos) /*!< 0x08000000 */ +#define ADC_JSQR_JSQ4_1 (0x02UL << ADC_JSQR_JSQ4_Pos) /*!< 0x10000000 */ +#define ADC_JSQR_JSQ4_2 (0x04UL << ADC_JSQR_JSQ4_Pos) /*!< 0x20000000 */ +#define ADC_JSQR_JSQ4_3 (0x08UL << ADC_JSQR_JSQ4_Pos) /*!< 0x40000000 */ +#define ADC_JSQR_JSQ4_4 (0x10UL << ADC_JSQR_JSQ4_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_OFR1 register ********************/ +#define ADC_OFR1_OFFSET1_Pos (0U) +#define ADC_OFR1_OFFSET1_Msk (0x3FFFFFFUL << ADC_OFR1_OFFSET1_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR1_OFFSET1 ADC_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ +#define ADC_OFR1_OFFSET1_0 (0x0000001UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000001 */ +#define ADC_OFR1_OFFSET1_1 (0x0000002UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000002 */ +#define ADC_OFR1_OFFSET1_2 (0x0000004UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000004 */ +#define ADC_OFR1_OFFSET1_3 (0x0000008UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000008 */ +#define ADC_OFR1_OFFSET1_4 (0x0000010UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000010 */ +#define ADC_OFR1_OFFSET1_5 (0x0000020UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000020 */ +#define ADC_OFR1_OFFSET1_6 (0x0000040UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000040 */ +#define ADC_OFR1_OFFSET1_7 (0x0000080UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000080 */ +#define ADC_OFR1_OFFSET1_8 (0x0000100UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000100 */ +#define ADC_OFR1_OFFSET1_9 (0x0000200UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000200 */ +#define ADC_OFR1_OFFSET1_10 (0x0000400UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000400 */ +#define ADC_OFR1_OFFSET1_11 (0x0000800UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00000800 */ +#define ADC_OFR1_OFFSET1_12 (0x0001000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00001000 */ +#define ADC_OFR1_OFFSET1_13 (0x0002000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00002000 */ +#define ADC_OFR1_OFFSET1_14 (0x0004000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00004000 */ +#define ADC_OFR1_OFFSET1_15 (0x0008000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00008000 */ +#define ADC_OFR1_OFFSET1_16 (0x0010000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00010000 */ +#define ADC_OFR1_OFFSET1_17 (0x0020000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00020000 */ +#define ADC_OFR1_OFFSET1_18 (0x0040000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00040000 */ +#define ADC_OFR1_OFFSET1_19 (0x0080000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00080000 */ +#define ADC_OFR1_OFFSET1_20 (0x0100000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00100000 */ +#define ADC_OFR1_OFFSET1_21 (0x0200000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00200000 */ +#define ADC_OFR1_OFFSET1_22 (0x0400000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00400000 */ +#define ADC_OFR1_OFFSET1_23 (0x0800000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x00800000 */ +#define ADC_OFR1_OFFSET1_24 (0x1000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x01000000 */ +#define ADC_OFR1_OFFSET1_25 (0x2000000UL << ADC_OFR1_OFFSET1_Pos) /*!< 0x02000000 */ + +#define ADC_OFR1_OFFSET1_CH_Pos (26U) +#define ADC_OFR1_OFFSET1_CH_Msk (0x1FUL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR1_OFFSET1_CH ADC_OFR1_OFFSET1_CH_Msk /*!< ADC Channel selection for the data offset 1 */ +#define ADC_OFR1_OFFSET1_CH_0 (0x01UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR1_OFFSET1_CH_1 (0x02UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR1_OFFSET1_CH_2 (0x04UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR1_OFFSET1_CH_3 (0x08UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR1_OFFSET1_CH_4 (0x10UL << ADC_OFR1_OFFSET1_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR1_SSATE_Pos (31U) +#define ADC_OFR1_SSATE_Msk (0x1UL << ADC_OFR1_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR1_SSATE ADC_OFR1_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR1_OFFSET1_Pos (0U) +#define ADC3_OFR1_OFFSET1_Msk (0xFFFUL << ADC3_OFR1_OFFSET1_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR1_OFFSET1 ADC3_OFR1_OFFSET1_Msk /*!< ADC data offset 1 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR1_OFFSETPOS_Pos (24U) +#define ADC3_OFR1_OFFSETPOS_Msk (0x1UL << ADC3_OFR1_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR1_OFFSETPOS ADC3_OFR1_OFFSETPOS_Msk /*!< ADC offset number 1 positive */ +#define ADC3_OFR1_SATEN_Pos (25U) +#define ADC3_OFR1_SATEN_Msk (0x1UL << ADC3_OFR1_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR1_SATEN ADC3_OFR1_SATEN_Msk /*!< ADC offset number 1 saturation enable */ + +#define ADC3_OFR1_OFFSET1_EN_Pos (31U) +#define ADC3_OFR1_OFFSET1_EN_Msk (0x1UL << ADC3_OFR1_OFFSET1_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR1_OFFSET1_EN ADC3_OFR1_OFFSET1_EN_Msk /*!< ADC offset number 1 enable */ + +/******************** Bit definition for ADC_OFR2 register ********************/ +#define ADC_OFR2_OFFSET2_Pos (0U) +#define ADC_OFR2_OFFSET2_Msk (0x3FFFFFFUL << ADC_OFR2_OFFSET2_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR2_OFFSET2 ADC_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET2_CH[4:0] */ +#define ADC_OFR2_OFFSET2_0 (0x0000001UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000001 */ +#define ADC_OFR2_OFFSET2_1 (0x0000002UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000002 */ +#define ADC_OFR2_OFFSET2_2 (0x0000004UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000004 */ +#define ADC_OFR2_OFFSET2_3 (0x0000008UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000008 */ +#define ADC_OFR2_OFFSET2_4 (0x0000010UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000010 */ +#define ADC_OFR2_OFFSET2_5 (0x0000020UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000020 */ +#define ADC_OFR2_OFFSET2_6 (0x0000040UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000040 */ +#define ADC_OFR2_OFFSET2_7 (0x0000080UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000080 */ +#define ADC_OFR2_OFFSET2_8 (0x0000100UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000100 */ +#define ADC_OFR2_OFFSET2_9 (0x0000200UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000200 */ +#define ADC_OFR2_OFFSET2_10 (0x0000400UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000400 */ +#define ADC_OFR2_OFFSET2_11 (0x0000800UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00000800 */ +#define ADC_OFR2_OFFSET2_12 (0x0001000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00001000 */ +#define ADC_OFR2_OFFSET2_13 (0x0002000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00002000 */ +#define ADC_OFR2_OFFSET2_14 (0x0004000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00004000 */ +#define ADC_OFR2_OFFSET2_15 (0x0008000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00008000 */ +#define ADC_OFR2_OFFSET2_16 (0x0010000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00010000 */ +#define ADC_OFR2_OFFSET2_17 (0x0020000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00020000 */ +#define ADC_OFR2_OFFSET2_18 (0x0040000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00040000 */ +#define ADC_OFR2_OFFSET2_19 (0x0080000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00080000 */ +#define ADC_OFR2_OFFSET2_20 (0x0100000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00100000 */ +#define ADC_OFR2_OFFSET2_21 (0x0200000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00200000 */ +#define ADC_OFR2_OFFSET2_22 (0x0400000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00400000 */ +#define ADC_OFR2_OFFSET2_23 (0x0800000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x00800000 */ +#define ADC_OFR2_OFFSET2_24 (0x1000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x01000000 */ +#define ADC_OFR2_OFFSET2_25 (0x2000000UL << ADC_OFR2_OFFSET2_Pos) /*!< 0x02000000 */ + +#define ADC_OFR2_OFFSET2_CH_Pos (26U) +#define ADC_OFR2_OFFSET2_CH_Msk (0x1FUL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR2_OFFSET2_CH ADC_OFR2_OFFSET2_CH_Msk /*!< ADC Channel selection for the data offset 2 */ +#define ADC_OFR2_OFFSET2_CH_0 (0x01UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR2_OFFSET2_CH_1 (0x02UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR2_OFFSET2_CH_2 (0x04UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR2_OFFSET2_CH_3 (0x08UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR2_OFFSET2_CH_4 (0x10UL << ADC_OFR2_OFFSET2_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR2_SSATE_Pos (31U) +#define ADC_OFR2_SSATE_Msk (0x1UL << ADC_OFR2_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR2_SSATE ADC_OFR2_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR2_OFFSET2_Pos (0U) +#define ADC3_OFR2_OFFSET2_Msk (0xFFFUL << ADC3_OFR2_OFFSET2_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR2_OFFSET2 ADC3_OFR2_OFFSET2_Msk /*!< ADC data offset 2 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR2_OFFSETPOS_Pos (24U) +#define ADC3_OFR2_OFFSETPOS_Msk (0x1UL << ADC3_OFR2_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR2_OFFSETPOS ADC3_OFR2_OFFSETPOS_Msk /*!< ADC offset number 2 positive */ +#define ADC3_OFR2_SATEN_Pos (25U) +#define ADC3_OFR2_SATEN_Msk (0x1UL << ADC3_OFR2_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR2_SATEN ADC3_OFR2_SATEN_Msk /*!< ADC offset number 2 saturation enable */ + +#define ADC3_OFR2_OFFSET2_EN_Pos (31U) +#define ADC3_OFR2_OFFSET2_EN_Msk (0x1UL << ADC3_OFR2_OFFSET2_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR2_OFFSET2_EN ADC3_OFR2_OFFSET2_EN_Msk /*!< ADC offset number 2 enable */ + +/******************** Bit definition for ADC_OFR3 register ********************/ +#define ADC_OFR3_OFFSET3_Pos (0U) +#define ADC_OFR3_OFFSET3_Msk (0x3FFFFFFUL << ADC_OFR3_OFFSET3_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR3_OFFSET3 ADC_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET3_CH[4:0] */ +#define ADC_OFR3_OFFSET3_0 (0x0000001UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000001 */ +#define ADC_OFR3_OFFSET3_1 (0x0000002UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000002 */ +#define ADC_OFR3_OFFSET3_2 (0x0000004UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000004 */ +#define ADC_OFR3_OFFSET3_3 (0x0000008UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000008 */ +#define ADC_OFR3_OFFSET3_4 (0x0000010UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000010 */ +#define ADC_OFR3_OFFSET3_5 (0x0000020UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000020 */ +#define ADC_OFR3_OFFSET3_6 (0x0000040UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000040 */ +#define ADC_OFR3_OFFSET3_7 (0x0000080UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000080 */ +#define ADC_OFR3_OFFSET3_8 (0x0000100UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000100 */ +#define ADC_OFR3_OFFSET3_9 (0x0000200UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000200 */ +#define ADC_OFR3_OFFSET3_10 (0x0000400UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000400 */ +#define ADC_OFR3_OFFSET3_11 (0x0000800UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00000800 */ +#define ADC_OFR3_OFFSET3_12 (0x0001000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00001000 */ +#define ADC_OFR3_OFFSET3_13 (0x0002000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00002000 */ +#define ADC_OFR3_OFFSET3_14 (0x0004000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00004000 */ +#define ADC_OFR3_OFFSET3_15 (0x0008000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00008000 */ +#define ADC_OFR3_OFFSET3_16 (0x0010000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00010000 */ +#define ADC_OFR3_OFFSET3_17 (0x0020000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00020000 */ +#define ADC_OFR3_OFFSET3_18 (0x0040000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00040000 */ +#define ADC_OFR3_OFFSET3_19 (0x0080000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00080000 */ +#define ADC_OFR3_OFFSET3_20 (0x0100000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00100000 */ +#define ADC_OFR3_OFFSET3_21 (0x0200000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00200000 */ +#define ADC_OFR3_OFFSET3_22 (0x0400000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00400000 */ +#define ADC_OFR3_OFFSET3_23 (0x0800000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x00800000 */ +#define ADC_OFR3_OFFSET3_24 (0x1000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x01000000 */ +#define ADC_OFR3_OFFSET3_25 (0x2000000UL << ADC_OFR3_OFFSET3_Pos) /*!< 0x02000000 */ + +#define ADC_OFR3_OFFSET3_CH_Pos (26U) +#define ADC_OFR3_OFFSET3_CH_Msk (0x1FUL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR3_OFFSET3_CH ADC_OFR3_OFFSET3_CH_Msk /*!< ADC Channel selection for the data offset 3 */ +#define ADC_OFR3_OFFSET3_CH_0 (0x01UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR3_OFFSET3_CH_1 (0x02UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR3_OFFSET3_CH_2 (0x04UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR3_OFFSET3_CH_3 (0x08UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR3_OFFSET3_CH_4 (0x10UL << ADC_OFR3_OFFSET3_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR3_SSATE_Pos (31U) +#define ADC_OFR3_SSATE_Msk (0x1UL << ADC_OFR3_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR3_SSATE ADC_OFR3_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR3_OFFSET3_Pos (0U) +#define ADC3_OFR3_OFFSET3_Msk (0xFFFUL << ADC3_OFR3_OFFSET3_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR3_OFFSET3 ADC3_OFR3_OFFSET3_Msk /*!< ADC data offset 3 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR3_OFFSETPOS_Pos (24U) +#define ADC3_OFR3_OFFSETPOS_Msk (0x1UL << ADC3_OFR3_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR3_OFFSETPOS ADC3_OFR3_OFFSETPOS_Msk /*!< ADC offset number 3 positive */ +#define ADC3_OFR3_SATEN_Pos (25U) +#define ADC3_OFR3_SATEN_Msk (0x1UL << ADC3_OFR3_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR3_SATEN ADC3_OFR3_SATEN_Msk /*!< ADC offset number 3 saturation enable */ + +#define ADC3_OFR3_OFFSET3_EN_Pos (31U) +#define ADC3_OFR3_OFFSET3_EN_Msk (0x1UL << ADC3_OFR3_OFFSET3_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR3_OFFSET3_EN ADC3_OFR3_OFFSET3_EN_Msk /*!< ADC offset number 3 enable */ + +/******************** Bit definition for ADC_OFR4 register ********************/ +#define ADC_OFR4_OFFSET4_Pos (0U) +#define ADC_OFR4_OFFSET4_Msk (0x3FFFFFFUL << ADC_OFR4_OFFSET4_Pos) /*!< 0x03FFFFFF */ +#define ADC_OFR4_OFFSET4 ADC_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET4_CH[4:0] */ +#define ADC_OFR4_OFFSET4_0 (0x0000001UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000001 */ +#define ADC_OFR4_OFFSET4_1 (0x0000002UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000002 */ +#define ADC_OFR4_OFFSET4_2 (0x0000004UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000004 */ +#define ADC_OFR4_OFFSET4_3 (0x0000008UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000008 */ +#define ADC_OFR4_OFFSET4_4 (0x0000010UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000010 */ +#define ADC_OFR4_OFFSET4_5 (0x0000020UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000020 */ +#define ADC_OFR4_OFFSET4_6 (0x0000040UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000040 */ +#define ADC_OFR4_OFFSET4_7 (0x0000080UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000080 */ +#define ADC_OFR4_OFFSET4_8 (0x0000100UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000100 */ +#define ADC_OFR4_OFFSET4_9 (0x0000200UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000200 */ +#define ADC_OFR4_OFFSET4_10 (0x0000400UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000400 */ +#define ADC_OFR4_OFFSET4_11 (0x0000800UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00000800 */ +#define ADC_OFR4_OFFSET4_12 (0x0001000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00001000 */ +#define ADC_OFR4_OFFSET4_13 (0x0002000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00002000 */ +#define ADC_OFR4_OFFSET4_14 (0x0004000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00004000 */ +#define ADC_OFR4_OFFSET4_15 (0x0008000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00008000 */ +#define ADC_OFR4_OFFSET4_16 (0x0010000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00010000 */ +#define ADC_OFR4_OFFSET4_17 (0x0020000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00020000 */ +#define ADC_OFR4_OFFSET4_18 (0x0040000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00040000 */ +#define ADC_OFR4_OFFSET4_19 (0x0080000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00080000 */ +#define ADC_OFR4_OFFSET4_20 (0x0100000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00100000 */ +#define ADC_OFR4_OFFSET4_21 (0x0200000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00200000 */ +#define ADC_OFR4_OFFSET4_22 (0x0400000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00400000 */ +#define ADC_OFR4_OFFSET4_23 (0x0800000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x00800000 */ +#define ADC_OFR4_OFFSET4_24 (0x1000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x01000000 */ +#define ADC_OFR4_OFFSET4_25 (0x2000000UL << ADC_OFR4_OFFSET4_Pos) /*!< 0x02000000 */ + +#define ADC_OFR4_OFFSET4_CH_Pos (26U) +#define ADC_OFR4_OFFSET4_CH_Msk (0x1FUL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x7C000000 */ +#define ADC_OFR4_OFFSET4_CH ADC_OFR4_OFFSET4_CH_Msk /*!< ADC Channel selection for the data offset 4 */ +#define ADC_OFR4_OFFSET4_CH_0 (0x01UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x04000000 */ +#define ADC_OFR4_OFFSET4_CH_1 (0x02UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x08000000 */ +#define ADC_OFR4_OFFSET4_CH_2 (0x04UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x10000000 */ +#define ADC_OFR4_OFFSET4_CH_3 (0x08UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x20000000 */ +#define ADC_OFR4_OFFSET4_CH_4 (0x10UL << ADC_OFR4_OFFSET4_CH_Pos) /*!< 0x40000000 */ + +#define ADC_OFR4_SSATE_Pos (31U) +#define ADC_OFR4_SSATE_Msk (0x1UL << ADC_OFR4_SSATE_Pos) /*!< 0x80000000 */ +#define ADC_OFR4_SSATE ADC_OFR4_SSATE_Msk /*!< ADC Signed saturation Enable */ + +#define ADC3_OFR4_OFFSET4_Pos (0U) +#define ADC3_OFR4_OFFSET4_Msk (0xFFFUL << ADC3_OFR4_OFFSET4_Pos) /*!< 0x00000FFF */ +#define ADC3_OFR4_OFFSET4 ADC3_OFR4_OFFSET4_Msk /*!< ADC data offset 4 for channel programmed into bits OFFSET1_CH[4:0] */ + +#define ADC3_OFR4_OFFSETPOS_Pos (24U) +#define ADC3_OFR4_OFFSETPOS_Msk (0x1UL << ADC3_OFR4_OFFSETPOS_Pos) /*!< 0x01000000 */ +#define ADC3_OFR4_OFFSETPOS ADC3_OFR4_OFFSETPOS_Msk /*!< ADC offset number 4 positive */ +#define ADC3_OFR4_SATEN_Pos (25U) +#define ADC3_OFR4_SATEN_Msk (0x1UL << ADC3_OFR4_SATEN_Pos) /*!< 0x02000000 */ +#define ADC3_OFR4_SATEN ADC3_OFR4_SATEN_Msk /*!< ADC offset number 4 saturation enable */ + +#define ADC3_OFR4_OFFSET4_EN_Pos (31U) +#define ADC3_OFR4_OFFSET4_EN_Msk (0x1UL << ADC3_OFR4_OFFSET4_EN_Pos) /*!< 0x80000000 */ +#define ADC3_OFR4_OFFSET4_EN ADC3_OFR4_OFFSET4_EN_Msk /*!< ADC offset number 4 enable */ + +/******************** Bit definition for ADC_JDR1 register ********************/ +#define ADC_JDR1_JDATA_Pos (0U) +#define ADC_JDR1_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR1_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR1_JDATA ADC_JDR1_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR1_JDATA_0 (0x00000001UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR1_JDATA_1 (0x00000002UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR1_JDATA_2 (0x00000004UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR1_JDATA_3 (0x00000008UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR1_JDATA_4 (0x00000010UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR1_JDATA_5 (0x00000020UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR1_JDATA_6 (0x00000040UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR1_JDATA_7 (0x00000080UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR1_JDATA_8 (0x00000100UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR1_JDATA_9 (0x00000200UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR1_JDATA_10 (0x00000400UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR1_JDATA_11 (0x00000800UL << ADC_JDR1_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR1_JDATA_12 (0x00001000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR1_JDATA_13 (0x00002000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR1_JDATA_14 (0x00004000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR1_JDATA_15 (0x00008000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR1_JDATA_16 (0x00010000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR1_JDATA_17 (0x00020000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR1_JDATA_18 (0x00040000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR1_JDATA_19 (0x00080000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR1_JDATA_20 (0x00100000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR1_JDATA_21 (0x00200000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR1_JDATA_22 (0x00400000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR1_JDATA_23 (0x00800000UL << ADC_JDR1_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR1_JDATA_24 (0x01000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR1_JDATA_25 (0x02000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR1_JDATA_26 (0x04000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR1_JDATA_27 (0x08000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR1_JDATA_28 (0x10000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR1_JDATA_29 (0x20000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR1_JDATA_30 (0x40000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR1_JDATA_31 (0x80000000UL << ADC_JDR1_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR2 register ********************/ +#define ADC_JDR2_JDATA_Pos (0U) +#define ADC_JDR2_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR2_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR2_JDATA ADC_JDR2_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR2_JDATA_0 (0x00000001UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR2_JDATA_1 (0x00000002UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR2_JDATA_2 (0x00000004UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR2_JDATA_3 (0x00000008UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR2_JDATA_4 (0x00000010UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR2_JDATA_5 (0x00000020UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR2_JDATA_6 (0x00000040UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR2_JDATA_7 (0x00000080UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR2_JDATA_8 (0x00000100UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR2_JDATA_9 (0x00000200UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR2_JDATA_10 (0x00000400UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR2_JDATA_11 (0x00000800UL << ADC_JDR2_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR2_JDATA_12 (0x00001000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR2_JDATA_13 (0x00002000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR2_JDATA_14 (0x00004000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR2_JDATA_15 (0x00008000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR2_JDATA_16 (0x00010000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR2_JDATA_17 (0x00020000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR2_JDATA_18 (0x00040000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR2_JDATA_19 (0x00080000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR2_JDATA_20 (0x00100000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR2_JDATA_21 (0x00200000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR2_JDATA_22 (0x00400000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR2_JDATA_23 (0x00800000UL << ADC_JDR2_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR2_JDATA_24 (0x01000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR2_JDATA_25 (0x02000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR2_JDATA_26 (0x04000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR2_JDATA_27 (0x08000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR2_JDATA_28 (0x10000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR2_JDATA_29 (0x20000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR2_JDATA_30 (0x40000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR2_JDATA_31 (0x80000000UL << ADC_JDR2_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR3 register ********************/ +#define ADC_JDR3_JDATA_Pos (0U) +#define ADC_JDR3_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR3_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR3_JDATA ADC_JDR3_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR3_JDATA_0 (0x00000001UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR3_JDATA_1 (0x00000002UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR3_JDATA_2 (0x00000004UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR3_JDATA_3 (0x00000008UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR3_JDATA_4 (0x00000010UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR3_JDATA_5 (0x00000020UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR3_JDATA_6 (0x00000040UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR3_JDATA_7 (0x00000080UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR3_JDATA_8 (0x00000100UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR3_JDATA_9 (0x00000200UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR3_JDATA_10 (0x00000400UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR3_JDATA_11 (0x00000800UL << ADC_JDR3_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR3_JDATA_12 (0x00001000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR3_JDATA_13 (0x00002000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR3_JDATA_14 (0x00004000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR3_JDATA_15 (0x00008000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR3_JDATA_16 (0x00010000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR3_JDATA_17 (0x00020000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR3_JDATA_18 (0x00040000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR3_JDATA_19 (0x00080000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR3_JDATA_20 (0x00100000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR3_JDATA_21 (0x00200000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR3_JDATA_22 (0x00400000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR3_JDATA_23 (0x00800000UL << ADC_JDR3_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR3_JDATA_24 (0x01000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR3_JDATA_25 (0x02000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR3_JDATA_26 (0x04000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR3_JDATA_27 (0x08000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR3_JDATA_28 (0x10000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR3_JDATA_29 (0x20000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR3_JDATA_30 (0x40000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR3_JDATA_31 (0x80000000UL << ADC_JDR3_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_JDR4 register ********************/ +#define ADC_JDR4_JDATA_Pos (0U) +#define ADC_JDR4_JDATA_Msk (0xFFFFFFFFUL << ADC_JDR4_JDATA_Pos) /*!< 0xFFFFFFFF */ +#define ADC_JDR4_JDATA ADC_JDR4_JDATA_Msk /*!< ADC Injected DATA */ +#define ADC_JDR4_JDATA_0 (0x00000001UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000001 */ +#define ADC_JDR4_JDATA_1 (0x00000002UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000002 */ +#define ADC_JDR4_JDATA_2 (0x00000004UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000004 */ +#define ADC_JDR4_JDATA_3 (0x00000008UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000008 */ +#define ADC_JDR4_JDATA_4 (0x00000010UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000010 */ +#define ADC_JDR4_JDATA_5 (0x00000020UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000020 */ +#define ADC_JDR4_JDATA_6 (0x00000040UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000040 */ +#define ADC_JDR4_JDATA_7 (0x00000080UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000080 */ +#define ADC_JDR4_JDATA_8 (0x00000100UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000100 */ +#define ADC_JDR4_JDATA_9 (0x00000200UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000200 */ +#define ADC_JDR4_JDATA_10 (0x00000400UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000400 */ +#define ADC_JDR4_JDATA_11 (0x00000800UL << ADC_JDR4_JDATA_Pos) /*!< 0x00000800 */ +#define ADC_JDR4_JDATA_12 (0x00001000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00001000 */ +#define ADC_JDR4_JDATA_13 (0x00002000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00002000 */ +#define ADC_JDR4_JDATA_14 (0x00004000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00004000 */ +#define ADC_JDR4_JDATA_15 (0x00008000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00008000 */ +#define ADC_JDR4_JDATA_16 (0x00010000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00010000 */ +#define ADC_JDR4_JDATA_17 (0x00020000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00020000 */ +#define ADC_JDR4_JDATA_18 (0x00040000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00040000 */ +#define ADC_JDR4_JDATA_19 (0x00080000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00080000 */ +#define ADC_JDR4_JDATA_20 (0x00100000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00100000 */ +#define ADC_JDR4_JDATA_21 (0x00200000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00200000 */ +#define ADC_JDR4_JDATA_22 (0x00400000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00400000 */ +#define ADC_JDR4_JDATA_23 (0x00800000UL << ADC_JDR4_JDATA_Pos) /*!< 0x00800000 */ +#define ADC_JDR4_JDATA_24 (0x01000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x01000000 */ +#define ADC_JDR4_JDATA_25 (0x02000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x02000000 */ +#define ADC_JDR4_JDATA_26 (0x04000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x04000000 */ +#define ADC_JDR4_JDATA_27 (0x08000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x08000000 */ +#define ADC_JDR4_JDATA_28 (0x10000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x10000000 */ +#define ADC_JDR4_JDATA_29 (0x20000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x20000000 */ +#define ADC_JDR4_JDATA_30 (0x40000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x40000000 */ +#define ADC_JDR4_JDATA_31 (0x80000000UL << ADC_JDR4_JDATA_Pos) /*!< 0x80000000 */ + +/******************** Bit definition for ADC_AWD2CR register ********************/ +#define ADC_AWD2CR_AWD2CH_Pos (0U) +#define ADC_AWD2CR_AWD2CH_Msk (0xFFFFFUL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD2CR_AWD2CH ADC_AWD2CR_AWD2CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD2CR_AWD2CH_0 (0x00001UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD2CR_AWD2CH_1 (0x00002UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD2CR_AWD2CH_2 (0x00004UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD2CR_AWD2CH_3 (0x00008UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD2CR_AWD2CH_4 (0x00010UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD2CR_AWD2CH_5 (0x00020UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD2CR_AWD2CH_6 (0x00040UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD2CR_AWD2CH_7 (0x00080UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD2CR_AWD2CH_8 (0x00100UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD2CR_AWD2CH_9 (0x00200UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD2CR_AWD2CH_10 (0x00400UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD2CR_AWD2CH_11 (0x00800UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD2CR_AWD2CH_12 (0x01000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD2CR_AWD2CH_13 (0x02000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD2CR_AWD2CH_14 (0x04000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD2CR_AWD2CH_15 (0x08000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD2CR_AWD2CH_16 (0x10000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD2CR_AWD2CH_17 (0x20000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD2CR_AWD2CH_18 (0x40000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD2CR_AWD2CH_19 (0x80000UL << ADC_AWD2CR_AWD2CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_AWD3CR register ********************/ +#define ADC_AWD3CR_AWD3CH_Pos (0U) +#define ADC_AWD3CR_AWD3CH_Msk (0xFFFFFUL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x000FFFFF */ +#define ADC_AWD3CR_AWD3CH ADC_AWD3CR_AWD3CH_Msk /*!< ADC Analog watchdog 2 channel selection */ +#define ADC_AWD3CR_AWD3CH_0 (0x00001UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000001 */ +#define ADC_AWD3CR_AWD3CH_1 (0x00002UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000002 */ +#define ADC_AWD3CR_AWD3CH_2 (0x00004UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000004 */ +#define ADC_AWD3CR_AWD3CH_3 (0x00008UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000008 */ +#define ADC_AWD3CR_AWD3CH_4 (0x00010UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000010 */ +#define ADC_AWD3CR_AWD3CH_5 (0x00020UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000020 */ +#define ADC_AWD3CR_AWD3CH_6 (0x00040UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000040 */ +#define ADC_AWD3CR_AWD3CH_7 (0x00080UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000080 */ +#define ADC_AWD3CR_AWD3CH_8 (0x00100UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000100 */ +#define ADC_AWD3CR_AWD3CH_9 (0x00200UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000200 */ +#define ADC_AWD3CR_AWD3CH_10 (0x00400UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000400 */ +#define ADC_AWD3CR_AWD3CH_11 (0x00800UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00000800 */ +#define ADC_AWD3CR_AWD3CH_12 (0x01000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00001000 */ +#define ADC_AWD3CR_AWD3CH_13 (0x02000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00002000 */ +#define ADC_AWD3CR_AWD3CH_14 (0x04000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00004000 */ +#define ADC_AWD3CR_AWD3CH_15 (0x08000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00008000 */ +#define ADC_AWD3CR_AWD3CH_16 (0x10000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00010000 */ +#define ADC_AWD3CR_AWD3CH_17 (0x20000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00020000 */ +#define ADC_AWD3CR_AWD3CH_18 (0x40000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00040000 */ +#define ADC_AWD3CR_AWD3CH_19 (0x80000UL << ADC_AWD3CR_AWD3CH_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_DIFSEL register ********************/ +#define ADC_DIFSEL_DIFSEL_Pos (0U) +#define ADC_DIFSEL_DIFSEL_Msk (0xFFFFFUL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x000FFFFF */ +#define ADC_DIFSEL_DIFSEL ADC_DIFSEL_DIFSEL_Msk /*!< ADC differential modes for channels 1 to 18 */ +#define ADC_DIFSEL_DIFSEL_0 (0x00001UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000001 */ +#define ADC_DIFSEL_DIFSEL_1 (0x00002UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000002 */ +#define ADC_DIFSEL_DIFSEL_2 (0x00004UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000004 */ +#define ADC_DIFSEL_DIFSEL_3 (0x00008UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000008 */ +#define ADC_DIFSEL_DIFSEL_4 (0x00010UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000010 */ +#define ADC_DIFSEL_DIFSEL_5 (0x00020UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000020 */ +#define ADC_DIFSEL_DIFSEL_6 (0x00040UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000040 */ +#define ADC_DIFSEL_DIFSEL_7 (0x00080UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000080 */ +#define ADC_DIFSEL_DIFSEL_8 (0x00100UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000100 */ +#define ADC_DIFSEL_DIFSEL_9 (0x00200UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000200 */ +#define ADC_DIFSEL_DIFSEL_10 (0x00400UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000400 */ +#define ADC_DIFSEL_DIFSEL_11 (0x00800UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00000800 */ +#define ADC_DIFSEL_DIFSEL_12 (0x01000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00001000 */ +#define ADC_DIFSEL_DIFSEL_13 (0x02000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00002000 */ +#define ADC_DIFSEL_DIFSEL_14 (0x04000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00004000 */ +#define ADC_DIFSEL_DIFSEL_15 (0x08000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00008000 */ +#define ADC_DIFSEL_DIFSEL_16 (0x10000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00010000 */ +#define ADC_DIFSEL_DIFSEL_17 (0x20000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00020000 */ +#define ADC_DIFSEL_DIFSEL_18 (0x40000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00040000 */ +#define ADC_DIFSEL_DIFSEL_19 (0x80000UL << ADC_DIFSEL_DIFSEL_Pos) /*!< 0x00080000 */ + +/******************** Bit definition for ADC_CALFACT register ********************/ +#define ADC_CALFACT_CALFACT_S_Pos (0U) +#define ADC_CALFACT_CALFACT_S_Msk (0x7FFUL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x000007FF */ +#define ADC_CALFACT_CALFACT_S ADC_CALFACT_CALFACT_S_Msk /*!< ADC calibration factors in single-ended mode */ +#define ADC_CALFACT_CALFACT_S_0 (0x001UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT_CALFACT_S_1 (0x002UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT_CALFACT_S_2 (0x004UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT_CALFACT_S_3 (0x008UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT_CALFACT_S_4 (0x010UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT_CALFACT_S_5 (0x020UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT_CALFACT_S_6 (0x040UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT_CALFACT_S_7 (0x080UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT_CALFACT_S_8 (0x100UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT_CALFACT_S_9 (0x200UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT_CALFACT_S_10 (0x400UL << ADC_CALFACT_CALFACT_S_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT_CALFACT_D_Pos (16U) +#define ADC_CALFACT_CALFACT_D_Msk (0x7FFUL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x07FF0000 */ +#define ADC_CALFACT_CALFACT_D ADC_CALFACT_CALFACT_D_Msk /*!< ADC calibration factors in differential mode */ +#define ADC_CALFACT_CALFACT_D_0 (0x001UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT_CALFACT_D_1 (0x002UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT_CALFACT_D_2 (0x004UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT_CALFACT_D_3 (0x008UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT_CALFACT_D_4 (0x010UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT_CALFACT_D_5 (0x020UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT_CALFACT_D_6 (0x040UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT_CALFACT_D_7 (0x080UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT_CALFACT_D_8 (0x100UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT_CALFACT_D_9 (0x200UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT_CALFACT_D_10 (0x400UL << ADC_CALFACT_CALFACT_D_Pos) /*!< 0x04000000 */ + +/******************** Bit definition for ADC_CALFACT2 register ********************/ +#define ADC_CALFACT2_LINCALFACT_Pos (0U) +#define ADC_CALFACT2_LINCALFACT_Msk (0x3FFFFFFFUL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x3FFFFFFF */ +#define ADC_CALFACT2_LINCALFACT ADC_CALFACT2_LINCALFACT_Msk /*!< ADC Linearity calibration factors */ +#define ADC_CALFACT2_LINCALFACT_0 (0x00000001UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000001 */ +#define ADC_CALFACT2_LINCALFACT_1 (0x00000002UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000002 */ +#define ADC_CALFACT2_LINCALFACT_2 (0x00000004UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000004 */ +#define ADC_CALFACT2_LINCALFACT_3 (0x00000008UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000008 */ +#define ADC_CALFACT2_LINCALFACT_4 (0x00000010UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000010 */ +#define ADC_CALFACT2_LINCALFACT_5 (0x00000020UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000020 */ +#define ADC_CALFACT2_LINCALFACT_6 (0x00000040UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000040 */ +#define ADC_CALFACT2_LINCALFACT_7 (0x00000080UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000080 */ +#define ADC_CALFACT2_LINCALFACT_8 (0x00000100UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000100 */ +#define ADC_CALFACT2_LINCALFACT_9 (0x00000200UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000200 */ +#define ADC_CALFACT2_LINCALFACT_10 (0x00000400UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000400 */ +#define ADC_CALFACT2_LINCALFACT_11 (0x00000800UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00000800 */ +#define ADC_CALFACT2_LINCALFACT_12 (0x00001000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00001000 */ +#define ADC_CALFACT2_LINCALFACT_13 (0x00002000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00002000 */ +#define ADC_CALFACT2_LINCALFACT_14 (0x00004000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00004000 */ +#define ADC_CALFACT2_LINCALFACT_15 (0x00008000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00008000 */ +#define ADC_CALFACT2_LINCALFACT_16 (0x00010000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00010000 */ +#define ADC_CALFACT2_LINCALFACT_17 (0x00020000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00020000 */ +#define ADC_CALFACT2_LINCALFACT_18 (0x00040000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00040000 */ +#define ADC_CALFACT2_LINCALFACT_19 (0x00080000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00080000 */ +#define ADC_CALFACT2_LINCALFACT_20 (0x00100000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00100000 */ +#define ADC_CALFACT2_LINCALFACT_21 (0x00200000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00200000 */ +#define ADC_CALFACT2_LINCALFACT_22 (0x00400000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00400000 */ +#define ADC_CALFACT2_LINCALFACT_23 (0x00800000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x00800000 */ +#define ADC_CALFACT2_LINCALFACT_24 (0x01000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x01000000 */ +#define ADC_CALFACT2_LINCALFACT_25 (0x02000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x02000000 */ +#define ADC_CALFACT2_LINCALFACT_26 (0x04000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x04000000 */ +#define ADC_CALFACT2_LINCALFACT_27 (0x08000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x08000000 */ +#define ADC_CALFACT2_LINCALFACT_28 (0x10000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x10000000 */ +#define ADC_CALFACT2_LINCALFACT_29 (0x20000000UL << ADC_CALFACT2_LINCALFACT_Pos) /*!< 0x20000000 */ + +/************************* ADC Common registers *****************************/ +/******************** Bit definition for ADC_CSR register ********************/ +#define ADC_CSR_ADRDY_MST_Pos (0U) +#define ADC_CSR_ADRDY_MST_Msk (0x1UL << ADC_CSR_ADRDY_MST_Pos) /*!< 0x00000001 */ +#define ADC_CSR_ADRDY_MST ADC_CSR_ADRDY_MST_Msk /*!< Master ADC ready */ +#define ADC_CSR_EOSMP_MST_Pos (1U) +#define ADC_CSR_EOSMP_MST_Msk (0x1UL << ADC_CSR_EOSMP_MST_Pos) /*!< 0x00000002 */ +#define ADC_CSR_EOSMP_MST ADC_CSR_EOSMP_MST_Msk /*!< End of sampling phase flag of the master ADC */ +#define ADC_CSR_EOC_MST_Pos (2U) +#define ADC_CSR_EOC_MST_Msk (0x1UL << ADC_CSR_EOC_MST_Pos) /*!< 0x00000004 */ +#define ADC_CSR_EOC_MST ADC_CSR_EOC_MST_Msk /*!< End of regular conversion of the master ADC */ +#define ADC_CSR_EOS_MST_Pos (3U) +#define ADC_CSR_EOS_MST_Msk (0x1UL << ADC_CSR_EOS_MST_Pos) /*!< 0x00000008 */ +#define ADC_CSR_EOS_MST ADC_CSR_EOS_MST_Msk /*!< End of regular sequence flag of the master ADC */ +#define ADC_CSR_OVR_MST_Pos (4U) +#define ADC_CSR_OVR_MST_Msk (0x1UL << ADC_CSR_OVR_MST_Pos) /*!< 0x00000010 */ +#define ADC_CSR_OVR_MST ADC_CSR_OVR_MST_Msk /*!< Overrun flag of the master ADC */ +#define ADC_CSR_JEOC_MST_Pos (5U) +#define ADC_CSR_JEOC_MST_Msk (0x1UL << ADC_CSR_JEOC_MST_Pos) /*!< 0x00000020 */ +#define ADC_CSR_JEOC_MST ADC_CSR_JEOC_MST_Msk /*!< End of injected conversion of the master ADC */ +#define ADC_CSR_JEOS_MST_Pos (6U) +#define ADC_CSR_JEOS_MST_Msk (0x1UL << ADC_CSR_JEOS_MST_Pos) /*!< 0x00000040 */ +#define ADC_CSR_JEOS_MST ADC_CSR_JEOS_MST_Msk /*!< End of injected sequence flag of the master ADC */ +#define ADC_CSR_AWD1_MST_Pos (7U) +#define ADC_CSR_AWD1_MST_Msk (0x1UL << ADC_CSR_AWD1_MST_Pos) /*!< 0x00000080 */ +#define ADC_CSR_AWD1_MST ADC_CSR_AWD1_MST_Msk /*!< Analog watchdog 1 flag of the master ADC */ +#define ADC_CSR_AWD2_MST_Pos (8U) +#define ADC_CSR_AWD2_MST_Msk (0x1UL << ADC_CSR_AWD2_MST_Pos) /*!< 0x00000100 */ +#define ADC_CSR_AWD2_MST ADC_CSR_AWD2_MST_Msk /*!< Analog watchdog 2 flag of the master ADC */ +#define ADC_CSR_AWD3_MST_Pos (9U) +#define ADC_CSR_AWD3_MST_Msk (0x1UL << ADC_CSR_AWD3_MST_Pos) /*!< 0x00000200 */ +#define ADC_CSR_AWD3_MST ADC_CSR_AWD3_MST_Msk /*!< Analog watchdog 3 flag of the master ADC */ +#define ADC_CSR_JQOVF_MST_Pos (10U) +#define ADC_CSR_JQOVF_MST_Msk (0x1UL << ADC_CSR_JQOVF_MST_Pos) /*!< 0x00000400 */ +#define ADC_CSR_JQOVF_MST ADC_CSR_JQOVF_MST_Msk /*!< Injected context queue overflow flag of the master ADC */ +#define ADC_CSR_ADRDY_SLV_Pos (16U) +#define ADC_CSR_ADRDY_SLV_Msk (0x1UL << ADC_CSR_ADRDY_SLV_Pos) /*!< 0x00010000 */ +#define ADC_CSR_ADRDY_SLV ADC_CSR_ADRDY_SLV_Msk /*!< Slave ADC ready */ +#define ADC_CSR_EOSMP_SLV_Pos (17U) +#define ADC_CSR_EOSMP_SLV_Msk (0x1UL << ADC_CSR_EOSMP_SLV_Pos) /*!< 0x00020000 */ +#define ADC_CSR_EOSMP_SLV ADC_CSR_EOSMP_SLV_Msk /*!< End of sampling phase flag of the slave ADC */ +#define ADC_CSR_EOC_SLV_Pos (18U) +#define ADC_CSR_EOC_SLV_Msk (0x1UL << ADC_CSR_EOC_SLV_Pos) /*!< 0x00040000 */ +#define ADC_CSR_EOC_SLV ADC_CSR_EOC_SLV_Msk /*!< End of regular conversion of the slave ADC */ +#define ADC_CSR_EOS_SLV_Pos (19U) +#define ADC_CSR_EOS_SLV_Msk (0x1UL << ADC_CSR_EOS_SLV_Pos) /*!< 0x00080000 */ +#define ADC_CSR_EOS_SLV ADC_CSR_EOS_SLV_Msk /*!< End of regular sequence flag of the slave ADC */ +#define ADC_CSR_OVR_SLV_Pos (20U) +#define ADC_CSR_OVR_SLV_Msk (0x1UL << ADC_CSR_OVR_SLV_Pos) /*!< 0x00100000 */ +#define ADC_CSR_OVR_SLV ADC_CSR_OVR_SLV_Msk /*!< Overrun flag of the slave ADC */ +#define ADC_CSR_JEOC_SLV_Pos (21U) +#define ADC_CSR_JEOC_SLV_Msk (0x1UL << ADC_CSR_JEOC_SLV_Pos) /*!< 0x00200000 */ +#define ADC_CSR_JEOC_SLV ADC_CSR_JEOC_SLV_Msk /*!< End of injected conversion of the slave ADC */ +#define ADC_CSR_JEOS_SLV_Pos (22U) +#define ADC_CSR_JEOS_SLV_Msk (0x1UL << ADC_CSR_JEOS_SLV_Pos) /*!< 0x00400000 */ +#define ADC_CSR_JEOS_SLV ADC_CSR_JEOS_SLV_Msk /*!< End of injected sequence flag of the slave ADC */ +#define ADC_CSR_AWD1_SLV_Pos (23U) +#define ADC_CSR_AWD1_SLV_Msk (0x1UL << ADC_CSR_AWD1_SLV_Pos) /*!< 0x00800000 */ +#define ADC_CSR_AWD1_SLV ADC_CSR_AWD1_SLV_Msk /*!< Analog watchdog 1 flag of the slave ADC */ +#define ADC_CSR_AWD2_SLV_Pos (24U) +#define ADC_CSR_AWD2_SLV_Msk (0x1UL << ADC_CSR_AWD2_SLV_Pos) /*!< 0x01000000 */ +#define ADC_CSR_AWD2_SLV ADC_CSR_AWD2_SLV_Msk /*!< Analog watchdog 2 flag of the slave ADC */ +#define ADC_CSR_AWD3_SLV_Pos (25U) +#define ADC_CSR_AWD3_SLV_Msk (0x1UL << ADC_CSR_AWD3_SLV_Pos) /*!< 0x02000000 */ +#define ADC_CSR_AWD3_SLV ADC_CSR_AWD3_SLV_Msk /*!< Analog watchdog 3 flag of the slave ADC */ +#define ADC_CSR_JQOVF_SLV_Pos (26U) +#define ADC_CSR_JQOVF_SLV_Msk (0x1UL << ADC_CSR_JQOVF_SLV_Pos) /*!< 0x04000000 */ +#define ADC_CSR_JQOVF_SLV ADC_CSR_JQOVF_SLV_Msk /*!< Injected context queue overflow flag of the slave ADC */ + +/******************** Bit definition for ADC_CCR register ********************/ +#define ADC_CCR_DUAL_Pos (0U) +#define ADC_CCR_DUAL_Msk (0x1FUL << ADC_CCR_DUAL_Pos) /*!< 0x0000001F */ +#define ADC_CCR_DUAL ADC_CCR_DUAL_Msk /*!< Dual ADC mode selection */ +#define ADC_CCR_DUAL_0 (0x01UL << ADC_CCR_DUAL_Pos) /*!< 0x00000001 */ +#define ADC_CCR_DUAL_1 (0x02UL << ADC_CCR_DUAL_Pos) /*!< 0x00000002 */ +#define ADC_CCR_DUAL_2 (0x04UL << ADC_CCR_DUAL_Pos) /*!< 0x00000004 */ +#define ADC_CCR_DUAL_3 (0x08UL << ADC_CCR_DUAL_Pos) /*!< 0x00000008 */ +#define ADC_CCR_DUAL_4 (0x10UL << ADC_CCR_DUAL_Pos) /*!< 0x00000010 */ + +#define ADC_CCR_DELAY_Pos (8U) +#define ADC_CCR_DELAY_Msk (0xFUL << ADC_CCR_DELAY_Pos) /*!< 0x00000F00 */ +#define ADC_CCR_DELAY ADC_CCR_DELAY_Msk /*!< Delay between 2 sampling phases */ +#define ADC_CCR_DELAY_0 (0x1UL << ADC_CCR_DELAY_Pos) /*!< 0x00000100 */ +#define ADC_CCR_DELAY_1 (0x2UL << ADC_CCR_DELAY_Pos) /*!< 0x00000200 */ +#define ADC_CCR_DELAY_2 (0x4UL << ADC_CCR_DELAY_Pos) /*!< 0x00000400 */ +#define ADC_CCR_DELAY_3 (0x8UL << ADC_CCR_DELAY_Pos) /*!< 0x00000800 */ + + +#define ADC_CCR_DAMDF_Pos (14U) +#define ADC_CCR_DAMDF_Msk (0x3UL << ADC_CCR_DAMDF_Pos) /*!< 0x0000C000 */ +#define ADC_CCR_DAMDF ADC_CCR_DAMDF_Msk /*!< Dual ADC mode Data format */ +#define ADC_CCR_DAMDF_0 (0x1UL << ADC_CCR_DAMDF_Pos) /*!< 0x00004000 */ +#define ADC_CCR_DAMDF_1 (0x2UL << ADC_CCR_DAMDF_Pos) /*!< 0x00008000 */ + +#define ADC_CCR_CKMODE_Pos (16U) +#define ADC_CCR_CKMODE_Msk (0x3UL << ADC_CCR_CKMODE_Pos) /*!< 0x00030000 */ +#define ADC_CCR_CKMODE ADC_CCR_CKMODE_Msk /*!< ADC clock mode */ +#define ADC_CCR_CKMODE_0 (0x1UL << ADC_CCR_CKMODE_Pos) /*!< 0x00010000 */ +#define ADC_CCR_CKMODE_1 (0x2UL << ADC_CCR_CKMODE_Pos) /*!< 0x00020000 */ + +#define ADC_CCR_PRESC_Pos (18U) +#define ADC_CCR_PRESC_Msk (0xFUL << ADC_CCR_PRESC_Pos) /*!< 0x003C0000 */ +#define ADC_CCR_PRESC ADC_CCR_PRESC_Msk /*!< ADC prescaler */ +#define ADC_CCR_PRESC_0 (0x1UL << ADC_CCR_PRESC_Pos) /*!< 0x00040000 */ +#define ADC_CCR_PRESC_1 (0x2UL << ADC_CCR_PRESC_Pos) /*!< 0x00080000 */ +#define ADC_CCR_PRESC_2 (0x4UL << ADC_CCR_PRESC_Pos) /*!< 0x00100000 */ +#define ADC_CCR_PRESC_3 (0x8UL << ADC_CCR_PRESC_Pos) /*!< 0x00200000 */ + +#define ADC_CCR_VREFEN_Pos (22U) +#define ADC_CCR_VREFEN_Msk (0x1UL << ADC_CCR_VREFEN_Pos) /*!< 0x00400000 */ +#define ADC_CCR_VREFEN ADC_CCR_VREFEN_Msk /*!< VREFINT enable */ +#define ADC_CCR_TSEN_Pos (23U) +#define ADC_CCR_TSEN_Msk (0x1UL << ADC_CCR_TSEN_Pos) /*!< 0x00800000 */ +#define ADC_CCR_TSEN ADC_CCR_TSEN_Msk /*!< Temperature sensor enable */ +#define ADC_CCR_VBATEN_Pos (24U) +#define ADC_CCR_VBATEN_Msk (0x1UL << ADC_CCR_VBATEN_Pos) /*!< 0x01000000 */ +#define ADC_CCR_VBATEN ADC_CCR_VBATEN_Msk /*!< VBAT enable */ + +/******************** Bit definition for ADC_CDR register *******************/ +#define ADC_CDR_RDATA_MST_Pos (0U) +#define ADC_CDR_RDATA_MST_Msk (0xFFFFUL << ADC_CDR_RDATA_MST_Pos) /*!< 0x0000FFFF */ +#define ADC_CDR_RDATA_MST ADC_CDR_RDATA_MST_Msk /*!< ADC multimode master group regular conversion data */ + +#define ADC_CDR_RDATA_SLV_Pos (16U) +#define ADC_CDR_RDATA_SLV_Msk (0xFFFFUL << ADC_CDR_RDATA_SLV_Pos) /*!< 0xFFFF0000 */ +#define ADC_CDR_RDATA_SLV ADC_CDR_RDATA_SLV_Msk /*!< ADC multimode slave group regular conversion data */ + +/******************** Bit definition for ADC_CDR2 register ******************/ +#define ADC_CDR2_RDATA_ALT_Pos (0U) +#define ADC_CDR2_RDATA_ALT_Msk (0xFFFFFFFFUL << ADC_CDR2_RDATA_ALT_Pos) /*!< 0xFFFFFFFF */ +#define ADC_CDR2_RDATA_ALT ADC_CDR2_RDATA_ALT_Msk /*!< Regular data of the master/slave alternated ADCs */ + + +/******************************************************************************/ +/* */ +/* VREFBUF */ +/* */ +/******************************************************************************/ +/******************* Bit definition for VREFBUF_CSR register ****************/ +#define VREFBUF_CSR_ENVR_Pos (0U) +#define VREFBUF_CSR_ENVR_Msk (0x1UL << VREFBUF_CSR_ENVR_Pos) /*!< 0x00000001 */ +#define VREFBUF_CSR_ENVR VREFBUF_CSR_ENVR_Msk /*!*/ +#define DAC_CR_CEN1_Pos (14U) +#define DAC_CR_CEN1_Msk (0x1UL << DAC_CR_CEN1_Pos) /*!< 0x00004000 */ +#define DAC_CR_CEN1 DAC_CR_CEN1_Msk /*!*/ + +#define DAC_CR_EN2_Pos (16U) +#define DAC_CR_EN2_Msk (0x1UL << DAC_CR_EN2_Pos) /*!< 0x00010000 */ +#define DAC_CR_EN2 DAC_CR_EN2_Msk /*!*/ +#define DAC_CR_CEN2_Pos (30U) +#define DAC_CR_CEN2_Msk (0x1UL << DAC_CR_CEN2_Pos) /*!< 0x40000000 */ +#define DAC_CR_CEN2 DAC_CR_CEN2_Msk /*!*/ + +/***************** Bit definition for DAC_SWTRIGR register ******************/ +#define DAC_SWTRIGR_SWTRIG1_Pos (0U) +#define DAC_SWTRIGR_SWTRIG1_Msk (0x1UL << DAC_SWTRIGR_SWTRIG1_Pos) /*!< 0x00000001 */ +#define DAC_SWTRIGR_SWTRIG1 DAC_SWTRIGR_SWTRIG1_Msk /*!
    © Copyright (c) 2017 STMicroelectronics. + * All rights reserved.
    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32h7xx + * @{ + */ + +#ifndef STM32H7xx_H +#define STM32H7xx_H + +#ifdef __cplusplus + extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Library_configuration_section + * @{ + */ + +/** + * @brief STM32 Family + */ +#if !defined (STM32H7) +#define STM32H7 +#endif /* STM32H7 */ + + +/* Uncomment the line below according to the target STM32H7 device used in your + application + */ + +/* #if !defined (STM32H743xx) && !defined (STM32H753xx) && !defined (STM32H750xx) && !defined (STM32H742xx) && \ + !defined (STM32H745xx) && !defined (STM32H755xx) && !defined (STM32H747xx) && !defined (STM32H757xx) && \ + !defined (STM32H7A3xx) && !defined (STM32H7A3xxQ) && !defined (STM32H7B3xx) && !defined (STM32H7B3xxQ) && !defined (STM32H7B0xx) && !defined (STM32H7B0xxQ) && \ + !defined (STM32H735xx) && !defined (STM32H733xx) && !defined (STM32H730xx) && !defined (STM32H730xxQ) && !defined (STM32H725xx) && !defined (STM32H723xx) */ + /* #define STM32H742xx */ /*!< STM32H742VI, STM32H742ZI, STM32H742AI, STM32H742II, STM32H742BI, STM32H742XI Devices */ + /* #define STM32H743xx */ /*!< STM32H743VI, STM32H743ZI, STM32H743AI, STM32H743II, STM32H743BI, STM32H743XI Devices */ + /* #define STM32H753xx */ /*!< STM32H753VI, STM32H753ZI, STM32H753AI, STM32H753II, STM32H753BI, STM32H753XI Devices */ + /* #define STM32H750xx */ /*!< STM32H750V, STM32H750I, STM32H750X Devices */ + /* #define STM32H747xx */ /*!< STM32H747ZI, STM32H747AI, STM32H747II, STM32H747BI, STM32H747XI Devices */ + /* #define STM32H757xx */ /*!< STM32H757ZI, STM32H757AI, STM32H757II, STM32H757BI, STM32H757XI Devices */ + /* #define STM32H745xx */ /*!< STM32H745ZI, STM32H745II, STM32H745BI, STM32H745XI Devices */ + /* #define STM32H755xx */ /*!< STM32H755ZI, STM32H755II, STM32H755BI, STM32H755XI Devices */ + /* #define STM32H7B0xx */ /*!< STM32H7B0ABIxQ, STM32H7B0IBTx, STM32H7B0RBTx, STM32H7B0VBTx, STM32H7B0ZBTx, STM32H7B0IBKxQ */ + /* #define STM32H7A3xx */ /*!< STM32H7A3IIK6, STM32H7A3IIT6, STM32H7A3NIH6, STM32H7A3RIT6, STM32H7A3VIH6, STM32H7A3VIT6, STM32H7A3ZIT6 */ + /* #define STM32H7A3xxQ */ /*!< STM32H7A3QIY6Q, STM32H7A3IIK6Q, STM32H7A3IIT6Q, STM32H7A3LIH6Q, STM32H7A3VIH6Q, STM32H7A3VIT6Q, STM32H7A3AII6Q, STM32H7A3ZIT6Q */ + /* #define STM32H7B3xx */ /*!< STM32H7B3IIK6, STM32H7B3IIT6, STM32H7B3NIH6, STM32H7B3RIT6, STM32H7B3VIH6, STM32H7B3VIT6, STM32H7B3ZIT6 */ + /* #define STM32H7B3xxQ */ /*!< STM32H7B3QIY6Q, STM32H7B3IIK6Q, STM32H7B3IIT6Q, STM32H7B3LIH6Q, STM32H7B3VIH6Q, STM32H7B3VIT6Q, STM32H7B3AII6Q, STM32H7B3ZIT6Q */ + /* #define STM32H735xx */ /*!< STM32H735AGI6, STM32H735IGK6, STM32H735RGV6, STM32H735VGT6, STM32H735VGY6, STM32H735ZGT6 Devices */ + /* #define STM32H733xx */ /*!< STM32H733VGH6, STM32H733VGT6, STM32H733ZGI6, STM32H733ZGT6, Devices */ + /* #define STM32H730xx */ /*!< STM32H730VBH6, STM32H730VBT6, STM32H730ZBT6, STM32H730ZBI6 Devices */ + /* #define STM32H730xxQ */ /*!< STM32H730IBT6Q, STM32H730ABI6Q, STM32H730IBK6Q Devices */ + /* #define STM32H725xx */ /*!< STM32H725AGI6, STM32H725IGK6, STM32H725IGT6, STM32H725RGV6, STM32H725VGT6, STM32H725VGY6, STM32H725ZGT6, STM32H725REV6, SM32H725VET6, STM32H725ZET6, STM32H725AEI6, STM32H725IET6, STM32H725IEK6 Devices */ + /* #define STM32H723xx */ /*!< STM32H723VGH6, STM32H723VGT6, STM32H723ZGI6, STM32H723ZGT6, STM32H723VET6, STM32H723VEH6, STM32H723ZET6, STM32H723ZEI6 Devices */ +/* #endif */ + +/* Tip: To avoid modifying this file each time you need to switch between these + devices, you can define the device in your toolchain compiler preprocessor. + */ + +#if defined(DUAL_CORE) && !defined(CORE_CM4) && !defined(CORE_CM7) + #error "Dual core device, please select CORE_CM4 or CORE_CM7" +#endif + +#if !defined (USE_HAL_DRIVER) +/** + * @brief Comment the line below if you will not use the peripherals drivers. + In this case, these drivers will not be included and the application code will + be based on direct access to peripherals registers + */ + /*#define USE_HAL_DRIVER */ +#endif /* USE_HAL_DRIVER */ + +/** + * @brief CMSIS Device version number V1.10.0 + */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_MAIN (0x01) /*!< [31:24] main version */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 (0x0A) /*!< [23:16] sub1 version */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 (0x00) /*!< [15:8] sub2 version */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION_RC (0x00) /*!< [7:0] release candidate */ +#define __STM32H7xx_CMSIS_DEVICE_VERSION ((__STM32H7xx_CMSIS_DEVICE_VERSION_MAIN << 24)\ + |(__STM32H7xx_CMSIS_DEVICE_VERSION_SUB1 << 16)\ + |(__STM32H7xx_CMSIS_DEVICE_VERSION_SUB2 << 8 )\ + |(__STM32H7xx_CMSIS_DEVICE_VERSION_RC)) + +/** + * @} + */ + +/** @addtogroup Device_Included + * @{ + */ + +#if defined(STM32H743xx) + #include "stm32h743xx.h" +// #elif defined(STM32H753xx) +// #include "stm32h753xx.h" +// #elif defined(STM32H750xx) +// #include "stm32h750xx.h" +// #elif defined(STM32H742xx) +// #include "stm32h742xx.h" +// #elif defined(STM32H745xx) +// #include "stm32h745xx.h" +// #elif defined(STM32H755xx) +// #include "stm32h755xx.h" +// #elif defined(STM32H747xx) +// #include "stm32h747xx.h" +// #elif defined(STM32H757xx) +// #include "stm32h757xx.h" +// #elif defined(STM32H7B0xx) +// #include "stm32h7b0xx.h" +// #elif defined(STM32H7B0xxQ) +// #include "stm32h7b0xxq.h" +// #elif defined(STM32H7A3xx) +// #include "stm32h7a3xx.h" +// #elif defined(STM32H7B3xx) +// #include "stm32h7b3xx.h" +// #elif defined(STM32H7A3xxQ) +// #include "stm32h7a3xxq.h" +// #elif defined(STM32H7B3xxQ) +// #include "stm32h7b3xxq.h" +#elif defined(STM32H735xx) + #include "stm32h735xx.h" +// #elif defined(STM32H733xx) +// #include "stm32h733xx.h" +// #elif defined(STM32H730xx) +// #include "stm32h730xx.h" +// #elif defined(STM32H730xxQ) +// #include "stm32h730xxq.h" +#elif defined(STM32H725xx) + #include "stm32h725xx.h" +// #elif defined(STM32H723xx) +// #include "stm32h723xx.h" +#else + #error "Please select first the target STM32H7xx device used in your application (in stm32h7xx.h file)" +#endif + +/** + * @} + */ + +/** @addtogroup Exported_types + * @{ + */ +typedef enum +{ + RESET = 0, + SET = !RESET +} FlagStatus, ITStatus; + +typedef enum +{ + DISABLE = 0, + ENABLE = !DISABLE +} FunctionalState; +#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE)) + +typedef enum +{ + SUCCESS = 0, + ERROR = !SUCCESS +} ErrorStatus; + +/** + * @} + */ + + +/** @addtogroup Exported_macros + * @{ + */ +#define SET_BIT(REG, BIT) ((REG) |= (BIT)) + +#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) + +#define READ_BIT(REG, BIT) ((REG) & (BIT)) + +#define CLEAR_REG(REG) ((REG) = (0x0)) + +#define WRITE_REG(REG, VAL) ((REG) = (VAL)) + +#define READ_REG(REG) ((REG)) + +#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) + +#define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) + + +/** + * @} + */ + +#if defined (USE_HAL_DRIVER) + #include "stm32h7xx_hal.h" +#endif /* USE_HAL_DRIVER */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* STM32H7xx_H */ +/** + * @} + */ + +/** + * @} + */ + + + + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda/board/stm32h7/inc/stm32h7xx_hal_def.h b/panda/board/stm32h7/inc/stm32h7xx_hal_def.h new file mode 100644 index 0000000000..3854b1cd39 --- /dev/null +++ b/panda/board/stm32h7/inc/stm32h7xx_hal_def.h @@ -0,0 +1,221 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_def.h + * @author MCD Application Team + * @brief This file contains HAL common defines, enumeration, macros and + * structures definitions. + ****************************************************************************** + * @attention + * + *

    © Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7xx_HAL_DEF +#define STM32H7xx_HAL_DEF + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx.h" +//#include "Legacy/stm32_hal_legacy.h" +//#include +//#include + +/* Exported types ------------------------------------------------------------*/ + +/** + * @brief HAL Status structures definition + */ +typedef enum +{ + HAL_OK = 0x00, + HAL_ERROR = 0x01, + HAL_BUSY = 0x02, + HAL_TIMEOUT = 0x03 +} HAL_StatusTypeDef; + +/** + * @brief HAL Lock structures definition + */ +typedef enum +{ + HAL_UNLOCKED = 0x00, + HAL_LOCKED = 0x01 +} HAL_LockTypeDef; + +/* Exported macro ------------------------------------------------------------*/ + +#define HAL_MAX_DELAY 0xFFFFFFFFU + +#define HAL_IS_BIT_SET(REG, BIT) (((REG) & (BIT)) == (BIT)) +#define HAL_IS_BIT_CLR(REG, BIT) (((REG) & (BIT)) == 0U) + +#define __HAL_LINKDMA(__HANDLE__, __PPP_DMA_FIELD__, __DMA_HANDLE__) \ + do{ \ + (__HANDLE__)->__PPP_DMA_FIELD__ = &(__DMA_HANDLE__); \ + (__DMA_HANDLE__).Parent = (__HANDLE__); \ + } while(0) + +#define UNUSED(x) ((void)(x)) + +/** @brief Reset the Handle's State field. + * @param __HANDLE__: specifies the Peripheral Handle. + * @note This macro can be used for the following purpose: + * - When the Handle is declared as local variable; before passing it as parameter + * to HAL_PPP_Init() for the first time, it is mandatory to use this macro + * to set to 0 the Handle's "State" field. + * Otherwise, "State" field may have any random value and the first time the function + * HAL_PPP_Init() is called, the low level hardware initialization will be missed + * (i.e. HAL_PPP_MspInit() will not be executed). + * - When there is a need to reconfigure the low level hardware: instead of calling + * HAL_PPP_DeInit() then HAL_PPP_Init(), user can make a call to this macro then HAL_PPP_Init(). + * In this later function, when the Handle's "State" field is set to 0, it will execute the function + * HAL_PPP_MspInit() which will reconfigure the low level hardware. + * @retval None + */ +#define __HAL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = 0) + +#if (USE_RTOS == 1) + #error " USE_RTOS should be 0 in the current HAL release " +#else + #define __HAL_LOCK(__HANDLE__) \ + do{ \ + if((__HANDLE__)->Lock == HAL_LOCKED) \ + { \ + return HAL_BUSY; \ + } \ + else \ + { \ + (__HANDLE__)->Lock = HAL_LOCKED; \ + } \ + }while (0) + + #define __HAL_UNLOCK(__HANDLE__) \ + do{ \ + (__HANDLE__)->Lock = HAL_UNLOCKED; \ + }while (0) +#endif /* USE_RTOS */ + + +#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ + #ifndef __weak + #define __weak __attribute__((weak)) + #endif + #ifndef __packed + #define __packed __attribute__((packed)) + #endif +#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __weak + #define __weak __attribute__((weak)) + #endif /* __weak */ + #ifndef __packed + #define __packed __attribute__((__packed__)) + #endif /* __packed */ +#endif /* __GNUC__ */ + + +/* Macro to get variable aligned on 4-bytes, for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */ +#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 */ + #ifndef __ALIGN_BEGIN + #define __ALIGN_BEGIN + #endif + #ifndef __ALIGN_END + #define __ALIGN_END __attribute__ ((aligned (4))) + #endif +#elif defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + #ifndef __ALIGN_END + #define __ALIGN_END __attribute__ ((aligned (4))) + #endif /* __ALIGN_END */ + #ifndef __ALIGN_BEGIN + #define __ALIGN_BEGIN + #endif /* __ALIGN_BEGIN */ +#else + #ifndef __ALIGN_END + #define __ALIGN_END + #endif /* __ALIGN_END */ + #ifndef __ALIGN_BEGIN + #if defined (__CC_ARM) /* ARM Compiler V5 */ + #define __ALIGN_BEGIN __align(4) + #elif defined (__ICCARM__) /* IAR Compiler */ + #define __ALIGN_BEGIN + #endif /* __CC_ARM */ + #endif /* __ALIGN_BEGIN */ +#endif /* __GNUC__ */ + +/* Macro to get variable aligned on 32-bytes,needed for cache maintenance purpose */ +#if defined (__GNUC__) /* GNU Compiler */ + #define ALIGN_32BYTES(buf) buf __attribute__ ((aligned (32))) +#elif defined (__ICCARM__) /* IAR Compiler */ + #define ALIGN_32BYTES(buf) _Pragma("data_alignment=32") buf +#elif defined (__CC_ARM) /* ARM Compiler */ + #define ALIGN_32BYTES(buf) __align(32) buf +#endif + +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) +/* ARM Compiler V4/V5 and V6 + -------------------------- + RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate source module. + Using the 'Options for File' dialog you can simply change the 'Code / Const' + area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the 'Options for Target' + dialog. +*/ +#define __RAM_FUNC + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC __attribute__((section(".RamFunc"))) + +#endif + +/** + * @brief __NOINLINE definition + */ +#if defined ( __CC_ARM ) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) || defined ( __GNUC__ ) +/* ARM V4/V5 and V6 & GNU Compiler + ------------------------------- +*/ +#define __NOINLINE __attribute__ ( (noinline) ) + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- +*/ +#define __NOINLINE _Pragma("optimize = no_inline") + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7xx_HAL_DEF */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda/board/stm32h7/inc/stm32h7xx_hal_gpio_ex.h b/panda/board/stm32h7/inc/stm32h7xx_hal_gpio_ex.h new file mode 100644 index 0000000000..14f576a424 --- /dev/null +++ b/panda/board/stm32h7/inc/stm32h7xx_hal_gpio_ex.h @@ -0,0 +1,489 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_gpio_ex.h + * @author MCD Application Team + * @brief Header file of GPIO HAL Extension module. + ****************************************************************************** + * @attention + * + *

    © COPYRIGHT(c) 2017 STMicroelectronics. + * All rights reserved.

    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7xx_HAL_GPIO_EX_H +#define STM32H7xx_HAL_GPIO_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal_def.h" + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +/** @addtogroup GPIOEx GPIOEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Constants GPIO Exported Constants + * @{ + */ + +/** @defgroup GPIO_Alternate_function_selection GPIO Alternate Function Selection + * @{ + */ + +/** + * @brief AF 0 selection + */ +#define GPIO_AF0_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */ +#define GPIO_AF0_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */ +#define GPIO_AF0_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */ +#define GPIO_AF0_LCDBIAS ((uint8_t)0x00) /* LCDBIAS Alternate Function mapping */ +#define GPIO_AF0_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */ +#if defined (PWR_CPUCR_PDDS_D2) /* PWR D1 and D2 domains exists */ +#define GPIO_AF0_C1DSLEEP ((uint8_t)0x00) /* Cortex-M7 Deep Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_C1SLEEP ((uint8_t)0x00) /* Cortex-M7 Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_D1PWREN ((uint8_t)0x00) /* Domain 1 PWR enable Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_D2PWREN ((uint8_t)0x00) /* Domain 2 PWR enable Alternate Function mapping : available on STM32H7 Rev.B and above */ +#if defined(DUAL_CORE) +#define GPIO_AF0_C2DSLEEP ((uint8_t)0x00) /* Cortex-M4 Deep Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#define GPIO_AF0_C2SLEEP ((uint8_t)0x00) /* Cortex-M4 Sleep Alternate Function mapping : available on STM32H7 Rev.B and above */ +#endif /* DUAL_CORE */ +#endif /* PWR_CPUCR_PDDS_D2 */ + +/** + * @brief AF 1 selection + */ +#define GPIO_AF1_TIM1 ((uint8_t)0x01) /* TIM1 Alternate Function mapping */ +#define GPIO_AF1_TIM2 ((uint8_t)0x01) /* TIM2 Alternate Function mapping */ +#define GPIO_AF1_TIM16 ((uint8_t)0x01) /* TIM16 Alternate Function mapping */ +#define GPIO_AF1_TIM17 ((uint8_t)0x01) /* TIM17 Alternate Function mapping */ +#define GPIO_AF1_LPTIM1 ((uint8_t)0x01) /* LPTIM1 Alternate Function mapping */ +#if defined(HRTIM1) +#define GPIO_AF1_HRTIM1 ((uint8_t)0x01) /* HRTIM1 Alternate Function mapping */ +#endif /* HRTIM1 */ +#if defined(SAI4) +#define GPIO_AF1_SAI4 ((uint8_t)0x01) /* SAI4 Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ +#endif /* SAI4 */ +#define GPIO_AF1_FMC ((uint8_t)0x01) /* FMC Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ + + +/** + * @brief AF 2 selection + */ +#define GPIO_AF2_TIM3 ((uint8_t)0x02) /* TIM3 Alternate Function mapping */ +#define GPIO_AF2_TIM4 ((uint8_t)0x02) /* TIM4 Alternate Function mapping */ +#define GPIO_AF2_TIM5 ((uint8_t)0x02) /* TIM5 Alternate Function mapping */ +#define GPIO_AF2_TIM12 ((uint8_t)0x02) /* TIM12 Alternate Function mapping */ +#define GPIO_AF2_SAI1 ((uint8_t)0x02) /* SAI1 Alternate Function mapping */ +#if defined(HRTIM1) +#define GPIO_AF2_HRTIM1 ((uint8_t)0x02) /* HRTIM1 Alternate Function mapping */ +#endif /* HRTIM1 */ +#define GPIO_AF2_TIM15 ((uint8_t)0x02) /* TIM15 Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#if defined(FDCAN3) +#define GPIO_AF2_FDCAN3 ((uint8_t)0x02) /* FDCAN3 Alternate Function mapping */ +#endif /*FDCAN3*/ + +/** + * @brief AF 3 selection + */ +#define GPIO_AF3_TIM8 ((uint8_t)0x03) /* TIM8 Alternate Function mapping */ +#define GPIO_AF3_LPTIM2 ((uint8_t)0x03) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF3_DFSDM1 ((uint8_t)0x03) /* DFSDM Alternate Function mapping */ +#define GPIO_AF3_LPTIM3 ((uint8_t)0x03) /* LPTIM3 Alternate Function mapping */ +#define GPIO_AF3_LPTIM4 ((uint8_t)0x03) /* LPTIM4 Alternate Function mapping */ +#define GPIO_AF3_LPTIM5 ((uint8_t)0x03) /* LPTIM5 Alternate Function mapping */ +#define GPIO_AF3_LPUART ((uint8_t)0x03) /* LPUART Alternate Function mapping */ +#if defined(OCTOSPIM) +#define GPIO_AF3_OCTOSPIM_P1 ((uint8_t)0x03) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF3_OCTOSPIM_P2 ((uint8_t)0x03) /* OCTOSPI Manager Port 2 Alternate Function mapping */ +#endif /* OCTOSPIM */ +#if defined(HRTIM1) +#define GPIO_AF3_HRTIM1 ((uint8_t)0x03) /* HRTIM1 Alternate Function mapping */ +#endif /* HRTIM1 */ +#define GPIO_AF3_LTDC ((uint8_t)0x03) /* LTDC Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ + +/** + * @brief AF 4 selection + */ +#define GPIO_AF4_I2C1 ((uint8_t)0x04) /* I2C1 Alternate Function mapping */ +#define GPIO_AF4_I2C2 ((uint8_t)0x04) /* I2C2 Alternate Function mapping */ +#define GPIO_AF4_I2C3 ((uint8_t)0x04) /* I2C3 Alternate Function mapping */ +#define GPIO_AF4_I2C4 ((uint8_t)0x04) /* I2C4 Alternate Function mapping */ +#if defined(I2C5) +#define GPIO_AF4_I2C5 ((uint8_t)0x04) /* I2C5 Alternate Function mapping */ +#endif /* I2C5*/ +#define GPIO_AF4_TIM15 ((uint8_t)0x04) /* TIM15 Alternate Function mapping */ +#define GPIO_AF4_CEC ((uint8_t)0x04) /* CEC Alternate Function mapping */ +#define GPIO_AF4_LPTIM2 ((uint8_t)0x04) /* LPTIM2 Alternate Function mapping */ +#define GPIO_AF4_USART1 ((uint8_t)0x04) /* USART1 Alternate Function mapping */ +#if defined(USART10) +#define GPIO_AF4_USART10 ((uint8_t)0x04) /* USART10 Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ +#endif /*USART10*/ +#define GPIO_AF4_DFSDM1 ((uint8_t)0x04) /* DFSDM Alternate Function mapping */ +#if defined(DFSDM2_BASE) +#define GPIO_AF4_DFSDM2 ((uint8_t)0x04) /* DFSDM2 Alternate Function mapping */ +#endif /* DFSDM2_BASE */ +#define GPIO_AF4_DCMI ((uint8_t)0x04) /* DCMI Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#if defined(PSSI) +#define GPIO_AF4_PSSI ((uint8_t)0x04) /* PSSI Alternate Function mapping */ +#endif /* PSSI */ +#if defined(OCTOSPIM) +#define GPIO_AF4_OCTOSPIM_P1 ((uint8_t)0x04) /* OCTOSPI Manager Port 1 Alternate Function mapping : available on STM32H72xxx/STM32H73xxx */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 5 selection + */ +#define GPIO_AF5_SPI1 ((uint8_t)0x05) /* SPI1 Alternate Function mapping */ +#define GPIO_AF5_SPI2 ((uint8_t)0x05) /* SPI2 Alternate Function mapping */ +#define GPIO_AF5_SPI3 ((uint8_t)0x05) /* SPI3 Alternate Function mapping */ +#define GPIO_AF5_SPI4 ((uint8_t)0x05) /* SPI4 Alternate Function mapping */ +#define GPIO_AF5_SPI5 ((uint8_t)0x05) /* SPI5 Alternate Function mapping */ +#define GPIO_AF5_SPI6 ((uint8_t)0x05) /* SPI6 Alternate Function mapping */ +#define GPIO_AF5_CEC ((uint8_t)0x05) /* CEC Alternate Function mapping */ +#if defined(FDCAN3) +#define GPIO_AF5_FDCAN3 ((uint8_t)0x05) /* FDCAN3 Alternate Function mapping */ +#endif /*FDCAN3*/ + +/** + * @brief AF 6 selection + */ +#define GPIO_AF6_SPI2 ((uint8_t)0x06) /* SPI2 Alternate Function mapping */ +#define GPIO_AF6_SPI3 ((uint8_t)0x06) /* SPI3 Alternate Function mapping */ +#define GPIO_AF6_SAI1 ((uint8_t)0x06) /* SAI1 Alternate Function mapping */ +#define GPIO_AF6_I2C4 ((uint8_t)0x06) /* I2C4 Alternate Function mapping */ +#if defined(I2C5) +#define GPIO_AF6_I2C5 ((uint8_t)0x06) /* I2C5 Alternate Function mapping */ +#endif /* I2C5*/ +#define GPIO_AF6_DFSDM1 ((uint8_t)0x06) /* DFSDM Alternate Function mapping */ +#define GPIO_AF6_UART4 ((uint8_t)0x06) /* UART4 Alternate Function mapping */ +#if defined(DFSDM2_BASE) +#define GPIO_AF6_DFSDM2 ((uint8_t)0x06) /* DFSDM2 Alternate Function mapping */ +#endif /* DFSDM2_BASE */ +#if defined(SAI3) +#define GPIO_AF6_SAI3 ((uint8_t)0x06) /* SAI3 Alternate Function mapping */ +#endif /* SAI3 */ +#if defined(OCTOSPIM) +#define GPIO_AF6_OCTOSPIM_P1 ((uint8_t)0x06) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 7 selection + */ +#define GPIO_AF7_SPI2 ((uint8_t)0x07) /* SPI2 Alternate Function mapping */ +#define GPIO_AF7_SPI3 ((uint8_t)0x07) /* SPI3 Alternate Function mapping */ +#define GPIO_AF7_SPI6 ((uint8_t)0x07) /* SPI6 Alternate Function mapping */ +#define GPIO_AF7_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */ +#define GPIO_AF7_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */ +#define GPIO_AF7_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */ +#define GPIO_AF7_USART6 ((uint8_t)0x07) /* USART6 Alternate Function mapping */ +#define GPIO_AF7_UART7 ((uint8_t)0x07) /* UART7 Alternate Function mapping */ +#define GPIO_AF7_SDMMC1 ((uint8_t)0x07) /* SDMMC1 Alternate Function mapping */ + +/** + * @brief AF 8 selection + */ +#define GPIO_AF8_SPI6 ((uint8_t)0x08) /* SPI6 Alternate Function mapping */ +#if defined(SAI2) +#define GPIO_AF8_SAI2 ((uint8_t)0x08) /* SAI2 Alternate Function mapping */ +#endif /*SAI2*/ +#define GPIO_AF8_UART4 ((uint8_t)0x08) /* UART4 Alternate Function mapping */ +#define GPIO_AF8_UART5 ((uint8_t)0x08) /* UART5 Alternate Function mapping */ +#define GPIO_AF8_UART8 ((uint8_t)0x08) /* UART8 Alternate Function mapping */ +#define GPIO_AF8_SPDIF ((uint8_t)0x08) /* SPDIF Alternate Function mapping */ +#define GPIO_AF8_LPUART ((uint8_t)0x08) /* LPUART Alternate Function mapping */ +#define GPIO_AF8_SDMMC1 ((uint8_t)0x08) /* SDMMC1 Alternate Function mapping */ +#if defined(SAI4) +#define GPIO_AF8_SAI4 ((uint8_t)0x08) /* SAI4 Alternate Function mapping */ +#endif /* SAI4 */ + +/** + * @brief AF 9 selection + */ +#define GPIO_AF9_FDCAN1 ((uint8_t)0x09) /* FDCAN1 Alternate Function mapping */ +#define GPIO_AF9_FDCAN2 ((uint8_t)0x09) /* FDCAN2 Alternate Function mapping */ +#define GPIO_AF9_TIM13 ((uint8_t)0x09) /* TIM13 Alternate Function mapping */ +#define GPIO_AF9_TIM14 ((uint8_t)0x09) /* TIM14 Alternate Function mapping */ +#define GPIO_AF9_SDMMC2 ((uint8_t)0x09) /* SDMMC2 Alternate Function mapping */ +#define GPIO_AF9_LTDC ((uint8_t)0x09) /* LTDC Alternate Function mapping */ +#define GPIO_AF9_SPDIF ((uint8_t)0x09) /* SPDIF Alternate Function mapping */ +#define GPIO_AF9_FMC ((uint8_t)0x09) /* FMC Alternate Function mapping */ +#if defined(QUADSPI) +#define GPIO_AF9_QUADSPI ((uint8_t)0x09) /* QUADSPI Alternate Function mapping */ +#endif /* QUADSPI */ +#if defined(SAI4) +#define GPIO_AF9_SAI4 ((uint8_t)0x09) /* SAI4 Alternate Function mapping */ +#endif /* SAI4 */ +#if defined(OCTOSPIM) +#define GPIO_AF9_OCTOSPIM_P1 ((uint8_t)0x09) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#define GPIO_AF9_OCTOSPIM_P2 ((uint8_t)0x09) /* OCTOSPI Manager Port 2 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 10 selection + */ +#if defined(SAI2) +#define GPIO_AF10_SAI2 ((uint8_t)0x0A) /* SAI2 Alternate Function mapping */ +#endif /*SAI2*/ +#define GPIO_AF10_SDMMC2 ((uint8_t)0x0A) /* SDMMC2 Alternate Function mapping */ +#if defined(USB2_OTG_FS) +#define GPIO_AF10_OTG2_FS ((uint8_t)0x0A) /* OTG2_FS Alternate Function mapping */ +#endif /*USB2_OTG_FS*/ +#define GPIO_AF10_COMP1 ((uint8_t)0x0A) /* COMP1 Alternate Function mapping */ +#define GPIO_AF10_COMP2 ((uint8_t)0x0A) /* COMP2 Alternate Function mapping */ +#if defined(LTDC) +#define GPIO_AF10_LTDC ((uint8_t)0x0A) /* LTDC Alternate Function mapping */ +#endif /*LTDC*/ +#define GPIO_AF10_CRS_SYNC ((uint8_t)0x0A) /* CRS Sync Alternate Function mapping : available on STM32H7 Rev.B and above */ +#if defined(QUADSPI) +#define GPIO_AF10_QUADSPI ((uint8_t)0x0A) /* QUADSPI Alternate Function mapping */ +#endif /* QUADSPI */ +#if defined(SAI4) +#define GPIO_AF10_SAI4 ((uint8_t)0x0A) /* SAI4 Alternate Function mapping */ +#endif /* SAI4 */ +#if !defined(USB2_OTG_FS) +#define GPIO_AF10_OTG1_FS ((uint8_t)0x0A) /* OTG1_FS Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#endif /* !USB2_OTG_FS */ +#define GPIO_AF10_OTG1_HS ((uint8_t)0x0A) /* OTG1_HS Alternate Function mapping */ +#if defined(OCTOSPIM) +#define GPIO_AF10_OCTOSPIM_P1 ((uint8_t)0x0A) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ +#define GPIO_AF10_TIM8 ((uint8_t)0x0A) /* TIM8 Alternate Function mapping */ +#define GPIO_AF10_FMC ((uint8_t)0x0A) /* FMC Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ + +/** + * @brief AF 11 selection + */ +#define GPIO_AF11_SWP ((uint8_t)0x0B) /* SWP Alternate Function mapping */ +#define GPIO_AF11_MDIOS ((uint8_t)0x0B) /* MDIOS Alternate Function mapping */ +#define GPIO_AF11_UART7 ((uint8_t)0x0B) /* UART7 Alternate Function mapping */ +#define GPIO_AF11_SDMMC2 ((uint8_t)0x0B) /* SDMMC2 Alternate Function mapping */ +#define GPIO_AF11_DFSDM1 ((uint8_t)0x0B) /* DFSDM1 Alternate Function mapping */ +#define GPIO_AF11_COMP1 ((uint8_t)0x0B) /* COMP1 Alternate Function mapping */ +#define GPIO_AF11_COMP2 ((uint8_t)0x0B) /* COMP2 Alternate Function mapping */ +#define GPIO_AF11_TIM1 ((uint8_t)0x0B) /* TIM1 Alternate Function mapping */ +#define GPIO_AF11_TIM8 ((uint8_t)0x0B) /* TIM8 Alternate Function mapping */ +#define GPIO_AF11_I2C4 ((uint8_t)0x0B) /* I2C4 Alternate Function mapping */ +#if defined(DFSDM2_BASE) +#define GPIO_AF11_DFSDM2 ((uint8_t)0x0B) /* DFSDM2 Alternate Function mapping */ +#endif /* DFSDM2_BASE */ +#if defined(USART10) +#define GPIO_AF11_USART10 ((uint8_t)0x0B) /* USART10 Alternate Function mapping */ +#endif /* USART10 */ +#if defined(UART9) +#define GPIO_AF11_UART9 ((uint8_t)0x0B) /* UART9 Alternate Function mapping */ +#endif /* UART9 */ +#if defined(ETH) +#define GPIO_AF11_ETH ((uint8_t)0x0B) /* ETH Alternate Function mapping */ +#endif /* ETH */ +#if defined(LTDC) +#define GPIO_AF11_LTDC ((uint8_t)0x0B) /* LTDC Alternate Function mapping : available on STM32H7A3xxx/STM32H7B3xxx/STM32H7B0xxx and STM32H72xxx/STM32H73xxx */ +#endif /*LTDC*/ +#if defined(OCTOSPIM) +#define GPIO_AF11_OCTOSPIM_P1 ((uint8_t)0x0B) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 12 selection + */ +#define GPIO_AF12_FMC ((uint8_t)0x0C) /* FMC Alternate Function mapping */ +#define GPIO_AF12_SDMMC1 ((uint8_t)0x0C) /* SDMMC1 Alternate Function mapping */ +#define GPIO_AF12_MDIOS ((uint8_t)0x0C) /* MDIOS Alternate Function mapping */ +#define GPIO_AF12_COMP1 ((uint8_t)0x0C) /* COMP1 Alternate Function mapping */ +#define GPIO_AF12_COMP2 ((uint8_t)0x0C) /* COMP2 Alternate Function mapping */ +#define GPIO_AF12_TIM1 ((uint8_t)0x0C) /* TIM1 Alternate Function mapping */ +#define GPIO_AF12_TIM8 ((uint8_t)0x0C) /* TIM8 Alternate Function mapping */ +#if defined(LTDC) +#define GPIO_AF12_LTDC ((uint8_t)0x0C) /* LTDC Alternate Function mapping */ +#endif /*LTDC*/ +#if defined(USB2_OTG_FS) +#define GPIO_AF12_OTG1_FS ((uint8_t)0x0C) /* OTG1_FS Alternate Function mapping */ +#endif /* USB2_OTG_FS */ +#if defined(OCTOSPIM) +#define GPIO_AF12_OCTOSPIM_P1 ((uint8_t)0x0C) /* OCTOSPI Manager Port 1 Alternate Function mapping */ +#endif /* OCTOSPIM */ + +/** + * @brief AF 13 selection + */ +#define GPIO_AF13_DCMI ((uint8_t)0x0D) /* DCMI Alternate Function mapping */ +#define GPIO_AF13_COMP1 ((uint8_t)0x0D) /* COMP1 Alternate Function mapping */ +#define GPIO_AF13_COMP2 ((uint8_t)0x0D) /* COMP2 Alternate Function mapping */ +#if defined(LTDC) +#define GPIO_AF13_LTDC ((uint8_t)0x0D) /* LTDC Alternate Function mapping */ +#endif /*LTDC*/ +#if defined(DSI) +#define GPIO_AF13_DSI ((uint8_t)0x0D) /* DSI Alternate Function mapping */ +#endif /* DSI */ +#if defined(PSSI) +#define GPIO_AF13_PSSI ((uint8_t)0x0D) /* PSSI Alternate Function mapping */ +#endif /* PSSI */ +#define GPIO_AF13_TIM1 ((uint8_t)0x0D) /* TIM1 Alternate Function mapping */ +#if defined(TIM23) +#define GPIO_AF13_TIM23 ((uint8_t)0x0D) /* TIM23 Alternate Function mapping */ +#endif /*TIM23*/ + +/** + * @brief AF 14 selection + */ +#define GPIO_AF14_LTDC ((uint8_t)0x0E) /* LTDC Alternate Function mapping */ +#define GPIO_AF14_UART5 ((uint8_t)0x0E) /* UART5 Alternate Function mapping */ +#if defined(TIM24) +#define GPIO_AF14_TIM24 ((uint8_t)0x0E) /* TIM24 Alternate Function mapping */ +#endif /*TIM24*/ + +/** + * @brief AF 15 selection + */ +#define GPIO_AF15_EVENTOUT ((uint8_t)0x0F) /* EVENTOUT Alternate Function mapping */ + +#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x0F) + + + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Macros GPIO Exported Macros + * @{ + */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup GPIOEx_Exported_Functions GPIO Exported Functions + * @{ + */ +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Constants GPIO Private Constants + * @{ + */ + +/** + * @brief GPIO pin available on the platform + */ +/* Defines the available pins per GPIOs */ +#define GPIOA_PIN_AVAILABLE GPIO_PIN_All +#define GPIOB_PIN_AVAILABLE GPIO_PIN_All +#define GPIOC_PIN_AVAILABLE GPIO_PIN_All +#define GPIOD_PIN_AVAILABLE GPIO_PIN_All +#define GPIOE_PIN_AVAILABLE GPIO_PIN_All +#define GPIOF_PIN_AVAILABLE GPIO_PIN_All +#define GPIOG_PIN_AVAILABLE GPIO_PIN_All +#if defined(GPIOI) +#define GPIOI_PIN_AVAILABLE GPIO_PIN_All +#endif /*GPIOI*/ +#if defined(GPIOI) +#define GPIOJ_PIN_AVAILABLE GPIO_PIN_All +#else +#define GPIOJ_PIN_AVAILABLE (GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 ) +#endif /* GPIOI */ +#define GPIOH_PIN_AVAILABLE GPIO_PIN_All +#if defined(GPIOI) +#define GPIOK_PIN_AVAILABLE (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | \ + GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7) +#else +#define GPIOK_PIN_AVAILABLE (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 ) +#endif /* GPIOI */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Macros GPIO Private Macros + * @{ + */ +/** @defgroup GPIOEx_Get_Port_Index GPIO Get Port Index + * @{ + */ +#if defined(GPIOI) +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0UL :\ + ((__GPIOx__) == (GPIOB))? 1UL :\ + ((__GPIOx__) == (GPIOC))? 2UL :\ + ((__GPIOx__) == (GPIOD))? 3UL :\ + ((__GPIOx__) == (GPIOE))? 4UL :\ + ((__GPIOx__) == (GPIOF))? 5UL :\ + ((__GPIOx__) == (GPIOG))? 6UL :\ + ((__GPIOx__) == (GPIOH))? 7UL :\ + ((__GPIOx__) == (GPIOI))? 8UL :\ + ((__GPIOx__) == (GPIOJ))? 9UL : 10UL) +#else +#define GPIO_GET_INDEX(__GPIOx__) (((__GPIOx__) == (GPIOA))? 0UL :\ + ((__GPIOx__) == (GPIOB))? 1UL :\ + ((__GPIOx__) == (GPIOC))? 2UL :\ + ((__GPIOx__) == (GPIOD))? 3UL :\ + ((__GPIOx__) == (GPIOE))? 4UL :\ + ((__GPIOx__) == (GPIOF))? 5UL :\ + ((__GPIOx__) == (GPIOG))? 6UL :\ + ((__GPIOx__) == (GPIOH))? 7UL :\ + ((__GPIOx__) == (GPIOJ))? 9UL : 10UL) +#endif /* GPIOI */ + +/** + * @} + */ + +/** @defgroup GPIOEx_IS_Alternat_function_selection GPIO Check Alternate Function + * @{ + */ +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup GPIOEx_Private_Functions GPIO Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7xx_HAL_GPIO_EX_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda/board/stm32h7/inc/system_stm32h7xx.h b/panda/board/stm32h7/inc/system_stm32h7xx.h new file mode 100644 index 0000000000..dd75af67ff --- /dev/null +++ b/panda/board/stm32h7/inc/system_stm32h7xx.h @@ -0,0 +1,105 @@ +/** + ****************************************************************************** + * @file system_stm32h7xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-Mx Device System Source File for STM32H7xx devices. + ****************************************************************************** + * @attention + * + *

    © Copyright (c) 2017 STMicroelectronics. + * All rights reserved.

    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32h7xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#ifndef SYSTEM_STM32H7XX_H +#define SYSTEM_STM32H7XX_H + +#ifdef __cplusplus + extern "C" { +#endif + +/** @addtogroup STM32H7xx_System_Includes + * @{ + */ + +/** + * @} + */ + + +/** @addtogroup STM32H7xx_System_Exported_types + * @{ + */ + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetSysClockFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ +extern uint32_t SystemCoreClock; /*!< System Domain1 Clock Frequency */ +extern uint32_t SystemD2Clock; /*!< System Domain2 Clock Frequency */ +extern const uint8_t D1CorePrescTable[16] ; /*!< D1CorePrescTable prescalers table values */ + +/** + * @} + */ + +/** @addtogroup STM32H7xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32H7xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32H7xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_STM32H7XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/panda/board/stm32h7/interrupt_handlers.h b/panda/board/stm32h7/interrupt_handlers.h new file mode 100644 index 0000000000..8148021d69 --- /dev/null +++ b/panda/board/stm32h7/interrupt_handlers.h @@ -0,0 +1,143 @@ +// ********************* Bare interrupt handlers ********************* +// Interrupts for STM32H7x5 + +void WWDG_IRQHandler(void) {handle_interrupt(WWDG_IRQn);} +void PVD_AVD_IRQHandler(void) {handle_interrupt(PVD_AVD_IRQn);} +void TAMP_STAMP_IRQHandler(void) {handle_interrupt(TAMP_STAMP_IRQn);} +void RTC_WKUP_IRQHandler(void) {handle_interrupt(RTC_WKUP_IRQn);} +void FLASH_IRQHandler(void) {handle_interrupt(FLASH_IRQn);} +void RCC_IRQHandler(void) {handle_interrupt(RCC_IRQn);} +void EXTI0_IRQHandler(void) {handle_interrupt(EXTI0_IRQn);} +void EXTI1_IRQHandler(void) {handle_interrupt(EXTI1_IRQn);} +void EXTI2_IRQHandler(void) {handle_interrupt(EXTI2_IRQn);} +void EXTI3_IRQHandler(void) {handle_interrupt(EXTI3_IRQn);} +void EXTI4_IRQHandler(void) {handle_interrupt(EXTI4_IRQn);} +void DMA1_Stream0_IRQHandler(void) {handle_interrupt(DMA1_Stream0_IRQn);} +void DMA1_Stream1_IRQHandler(void) {handle_interrupt(DMA1_Stream1_IRQn);} +void DMA1_Stream2_IRQHandler(void) {handle_interrupt(DMA1_Stream2_IRQn);} +void DMA1_Stream3_IRQHandler(void) {handle_interrupt(DMA1_Stream3_IRQn);} +void DMA1_Stream4_IRQHandler(void) {handle_interrupt(DMA1_Stream4_IRQn);} +void DMA1_Stream5_IRQHandler(void) {handle_interrupt(DMA1_Stream5_IRQn);} +void DMA1_Stream6_IRQHandler(void) {handle_interrupt(DMA1_Stream6_IRQn);} +void ADC_IRQHandler(void) {handle_interrupt(ADC_IRQn);} +void FDCAN1_IT0_IRQHandler(void) {handle_interrupt(FDCAN1_IT0_IRQn);} +void FDCAN2_IT0_IRQHandler(void) {handle_interrupt(FDCAN2_IT0_IRQn);} +void FDCAN1_IT1_IRQHandler(void) {handle_interrupt(FDCAN1_IT1_IRQn);} +void FDCAN2_IT1_IRQHandler(void) {handle_interrupt(FDCAN2_IT1_IRQn);} +void EXTI9_5_IRQHandler(void) {handle_interrupt(EXTI9_5_IRQn);} +void TIM1_BRK_IRQHandler(void) {handle_interrupt(TIM1_BRK_IRQn);} +void TIM1_UP_TIM10_IRQHandler(void) {handle_interrupt(TIM1_UP_TIM10_IRQn);} +void TIM1_TRG_COM_IRQHandler(void) {handle_interrupt(TIM1_TRG_COM_IRQn);} +void TIM1_CC_IRQHandler(void) {handle_interrupt(TIM1_CC_IRQn);} +void TIM2_IRQHandler(void) {handle_interrupt(TIM2_IRQn);} +void TIM3_IRQHandler(void) {handle_interrupt(TIM3_IRQn);} +void TIM4_IRQHandler(void) {handle_interrupt(TIM4_IRQn);} +void I2C1_EV_IRQHandler(void) {handle_interrupt(I2C1_EV_IRQn);} +void I2C1_ER_IRQHandler(void) {handle_interrupt(I2C1_ER_IRQn);} +void I2C2_EV_IRQHandler(void) {handle_interrupt(I2C2_EV_IRQn);} +void I2C2_ER_IRQHandler(void) {handle_interrupt(I2C2_ER_IRQn);} +void SPI1_IRQHandler(void) {handle_interrupt(SPI1_IRQn);} +void SPI2_IRQHandler(void) {handle_interrupt(SPI2_IRQn);} +void USART1_IRQHandler(void) {handle_interrupt(USART1_IRQn);} +void USART2_IRQHandler(void) {handle_interrupt(USART2_IRQn);} +void USART3_IRQHandler(void) {handle_interrupt(USART3_IRQn);} +void EXTI15_10_IRQHandler(void) {handle_interrupt(EXTI15_10_IRQn);} +void RTC_Alarm_IRQHandler(void) {handle_interrupt(RTC_Alarm_IRQn);} +void TIM8_BRK_TIM12_IRQHandler(void) {handle_interrupt(TIM8_BRK_TIM12_IRQn);} +void TIM8_UP_TIM13_IRQHandler(void) {handle_interrupt(TIM8_UP_TIM13_IRQn);} +void TIM8_TRG_COM_TIM14_IRQHandler(void) {handle_interrupt(TIM8_TRG_COM_TIM14_IRQn);} +void TIM8_CC_IRQHandler(void) {handle_interrupt(TIM8_CC_IRQn);} +void DMA1_Stream7_IRQHandler(void) {handle_interrupt(DMA1_Stream7_IRQn);} +void FMC_IRQHandler(void) {handle_interrupt(FMC_IRQn);} +void SDMMC1_IRQHandler(void) {handle_interrupt(SDMMC1_IRQn);} +void TIM5_IRQHandler(void) {handle_interrupt(TIM5_IRQn);} +void SPI3_IRQHandler(void) {handle_interrupt(SPI3_IRQn);} +void UART4_IRQHandler(void) {handle_interrupt(UART4_IRQn);} +void UART5_IRQHandler(void) {handle_interrupt(UART5_IRQn);} +void TIM6_DAC_IRQHandler(void) {handle_interrupt(TIM6_DAC_IRQn);} +void TIM7_IRQHandler(void) {handle_interrupt(TIM7_IRQn);} +void DMA2_Stream0_IRQHandler(void) {handle_interrupt(DMA2_Stream0_IRQn);} +void DMA2_Stream1_IRQHandler(void) {handle_interrupt(DMA2_Stream1_IRQn);} +void DMA2_Stream2_IRQHandler(void) {handle_interrupt(DMA2_Stream2_IRQn);} +void DMA2_Stream3_IRQHandler(void) {handle_interrupt(DMA2_Stream3_IRQn);} +void DMA2_Stream4_IRQHandler(void) {handle_interrupt(DMA2_Stream4_IRQn);} +void ETH_IRQHandler(void) {handle_interrupt(ETH_IRQn);} +void ETH_WKUP_IRQHandler(void) {handle_interrupt(ETH_WKUP_IRQn);} +void FDCAN_CAL_IRQHandler(void) {handle_interrupt(FDCAN_CAL_IRQn);} +void DMA2_Stream5_IRQHandler(void) {handle_interrupt(DMA2_Stream5_IRQn);} +void DMA2_Stream6_IRQHandler(void) {handle_interrupt(DMA2_Stream6_IRQn);} +void DMA2_Stream7_IRQHandler(void) {handle_interrupt(DMA2_Stream7_IRQn);} +void USART6_IRQHandler(void) {handle_interrupt(USART6_IRQn);} +void I2C3_EV_IRQHandler(void) {handle_interrupt(I2C3_EV_IRQn);} +void I2C3_ER_IRQHandler(void) {handle_interrupt(I2C3_ER_IRQn);} +void OTG_HS_EP1_OUT_IRQHandler(void) {handle_interrupt(OTG_HS_EP1_OUT_IRQn);} +void OTG_HS_EP1_IN_IRQHandler(void) {handle_interrupt(OTG_HS_EP1_IN_IRQn);} +void OTG_HS_WKUP_IRQHandler(void) {handle_interrupt(OTG_HS_WKUP_IRQn);} +void OTG_HS_IRQHandler(void) {handle_interrupt(OTG_HS_IRQn);} +void DCMI_PSSI_IRQHandler(void) {handle_interrupt(DCMI_PSSI_IRQn);} +void CRYP_IRQHandler(void) {handle_interrupt(CRYP_IRQn);} +void HASH_RNG_IRQHandler(void) {handle_interrupt(HASH_RNG_IRQn);} +void FPU_IRQHandler(void) {handle_interrupt(FPU_IRQn);} +void UART7_IRQHandler(void) {handle_interrupt(UART7_IRQn);} +void UART8_IRQHandler(void) {handle_interrupt(UART8_IRQn);} +void SPI4_IRQHandler(void) {handle_interrupt(SPI4_IRQn);} +void SPI5_IRQHandler(void) {handle_interrupt(SPI5_IRQn);} +void SPI6_IRQHandler(void) {handle_interrupt(SPI6_IRQn);} +void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);} +void LTDC_IRQHandler(void) {handle_interrupt(LTDC_IRQn);} +void LTDC_ER_IRQHandler(void) {handle_interrupt(LTDC_ER_IRQn);} +void DMA2D_IRQHandler(void) {handle_interrupt(DMA2D_IRQn);} +void OCTOSPI1_IRQHandler(void) {handle_interrupt(OCTOSPI1_IRQn);} +void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);} +void CEC_IRQHandler(void) {handle_interrupt(CEC_IRQn);} +void I2C4_EV_IRQHandler(void) {handle_interrupt(I2C4_EV_IRQn);} +void I2C4_ER_IRQHandler(void) {handle_interrupt(I2C4_ER_IRQn);} +void SPDIF_RX_IRQHandler(void) {handle_interrupt(SPDIF_RX_IRQn);} +void DMAMUX1_OVR_IRQHandler(void) {handle_interrupt(DMAMUX1_OVR_IRQn);} +void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);} +void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);} +void DFSDM1_FLT2_IRQHandler(void) {handle_interrupt(DFSDM1_FLT2_IRQn);} +void DFSDM1_FLT3_IRQHandler(void) {handle_interrupt(DFSDM1_FLT3_IRQn);} +void SWPMI1_IRQHandler(void) {handle_interrupt(SWPMI1_IRQn);} +void TIM15_IRQHandler(void) {handle_interrupt(TIM15_IRQn);} +void TIM16_IRQHandler(void) {handle_interrupt(TIM16_IRQn);} +void TIM17_IRQHandler(void) {handle_interrupt(TIM17_IRQn);} +void MDIOS_WKUP_IRQHandler(void) {handle_interrupt(MDIOS_WKUP_IRQn);} +void MDIOS_IRQHandler(void) {handle_interrupt(MDIOS_IRQn);} +void MDMA_IRQHandler(void) {handle_interrupt(MDMA_IRQn);} +void SDMMC2_IRQHandler(void) {handle_interrupt(SDMMC2_IRQn);} +void HSEM1_IRQHandler(void) {handle_interrupt(HSEM1_IRQn);} +void ADC3_IRQHandler(void) {handle_interrupt(ADC3_IRQn);} +void DMAMUX2_OVR_IRQHandler(void) {handle_interrupt(DMAMUX2_OVR_IRQn);} +void BDMA_Channel0_IRQHandler(void) {handle_interrupt(BDMA_Channel0_IRQn);} +void BDMA_Channel1_IRQHandler(void) {handle_interrupt(BDMA_Channel1_IRQn);} +void BDMA_Channel2_IRQHandler(void) {handle_interrupt(BDMA_Channel2_IRQn);} +void BDMA_Channel3_IRQHandler(void) {handle_interrupt(BDMA_Channel3_IRQn);} +void BDMA_Channel4_IRQHandler(void) {handle_interrupt(BDMA_Channel4_IRQn);} +void BDMA_Channel5_IRQHandler(void) {handle_interrupt(BDMA_Channel5_IRQn);} +void BDMA_Channel6_IRQHandler(void) {handle_interrupt(BDMA_Channel6_IRQn);} +void BDMA_Channel7_IRQHandler(void) {handle_interrupt(BDMA_Channel7_IRQn);} +void COMP_IRQHandler(void) {handle_interrupt(COMP_IRQn);} +void LPTIM2_IRQHandler(void) {handle_interrupt(LPTIM2_IRQn);} +void LPTIM3_IRQHandler(void) {handle_interrupt(LPTIM3_IRQn);} +void LPTIM4_IRQHandler(void) {handle_interrupt(LPTIM4_IRQn);} +void LPTIM5_IRQHandler(void) {handle_interrupt(LPTIM5_IRQn);} +void LPUART1_IRQHandler(void) {handle_interrupt(LPUART1_IRQn);} +void CRS_IRQHandler(void) {handle_interrupt(CRS_IRQn);} +void ECC_IRQHandler(void) {handle_interrupt(ECC_IRQn);} +void SAI4_IRQHandler(void) {handle_interrupt(SAI4_IRQn);} +void DTS_IRQHandler(void) {handle_interrupt(DTS_IRQn);} +void WAKEUP_PIN_IRQHandler(void) {handle_interrupt(WAKEUP_PIN_IRQn);} +void OCTOSPI2_IRQHandler(void) {handle_interrupt(OCTOSPI2_IRQn);} +void OTFDEC1_IRQHandler(void) {handle_interrupt(OTFDEC1_IRQn);} +void OTFDEC2_IRQHandler(void) {handle_interrupt(OTFDEC2_IRQn);} +void FMAC_IRQHandler(void) {handle_interrupt(FMAC_IRQn);} +void CORDIC_IRQHandler(void) {handle_interrupt(CORDIC_IRQn);} +void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);} +void USART10_IRQHandler(void) {handle_interrupt(USART10_IRQn);} +void I2C5_EV_IRQHandler(void) {handle_interrupt(I2C5_EV_IRQn);} +void I2C5_ER_IRQHandler(void) {handle_interrupt(I2C5_ER_IRQn);} +void FDCAN3_IT0_IRQHandler(void) {handle_interrupt(FDCAN3_IT0_IRQn);} +void FDCAN3_IT1_IRQHandler(void) {handle_interrupt(FDCAN3_IT1_IRQn);} +void TIM23_IRQHandler(void) {handle_interrupt(TIM23_IRQn);} +void TIM24_IRQHandler(void) {handle_interrupt(TIM24_IRQn);} diff --git a/panda/board/stm32h7/lladc.h b/panda/board/stm32h7/lladc.h new file mode 100644 index 0000000000..0a7e983c9e --- /dev/null +++ b/panda/board/stm32h7/lladc.h @@ -0,0 +1,80 @@ +#include "lladc_declarations.h" + +static uint32_t adc_avdd_mV = 0U; + +void adc_init(ADC_TypeDef *adc) { + adc->CR &= ~(ADC_CR_ADEN); // Disable ADC + adc->CR &= ~(ADC_CR_DEEPPWD); // Reset deep-power-down mode + adc->CR |= ADC_CR_ADVREGEN; // Enable ADC regulator + while(!(adc->ISR & ADC_ISR_LDORDY) && (adc != ADC3)); + + if (adc != ADC3) { + adc->CR &= ~(ADC_CR_ADCALDIF); // Choose single-ended calibration + adc->CR |= ADC_CR_ADCALLIN; // Lineriality calibration + } + adc->CR |= ADC_CR_ADCAL; // Start calibration + while((adc->CR & ADC_CR_ADCAL) != 0U); + + adc->ISR |= ADC_ISR_ADRDY; + adc->CR |= ADC_CR_ADEN; + while(!(adc->ISR & ADC_ISR_ADRDY)); +} + +uint16_t adc_get_raw(const adc_signal_t *signal) { + signal->adc->SQR1 &= ~(ADC_SQR1_L); + signal->adc->SQR1 = ((uint32_t) signal->channel << 6U); + + // sample time + if (signal->channel < 10U) { + signal->adc->SMPR1 = ((uint32_t) signal->sample_time << (signal->channel * 3U)); + } else { + signal->adc->SMPR2 = ((uint32_t) signal->sample_time << ((signal->channel - 10U) * 3U)); + } + + // select channel + signal->adc->PCSEL_RES0 = (0x1UL << signal->channel); + + // oversampling + signal->adc->CFGR2 = (((1U << (uint32_t) signal->oversampling) - 1U) << ADC_CFGR2_OVSR_Pos) | ((uint32_t) signal->oversampling << ADC_CFGR2_OVSS_Pos); + signal->adc->CFGR2 |= (signal->oversampling != OVERSAMPLING_1) ? ADC_CFGR2_ROVSE : 0U; + + // start conversion + signal->adc->CR |= ADC_CR_ADSTART; + while (!(signal->adc->ISR & ADC_ISR_EOC)); + + uint16_t res = signal->adc->DR; + + while (!(signal->adc->ISR & ADC_ISR_EOS)); + signal->adc->ISR |= ADC_ISR_EOS; + + return res; +} + +static void adc_calibrate_vdda(void) { + // ADC2 used for calibration + adc_init(ADC2); + + // enable VREFINT channel + ADC3_COMMON->CCR |= ADC_CCR_VREFEN; + SYSCFG->ADC2ALT |= SYSCFG_ADC2ALT_ADC2_ROUT1; + + // measure VREFINT and derive AVDD + uint16_t raw_vrefint = adc_get_raw(&(adc_signal_t){.adc = ADC2, .channel = 17U, .sample_time = SAMPLETIME_810_CYCLES, .oversampling = OVERSAMPLING_256}); + adc_avdd_mV = (uint32_t) *VREFINT_CAL_ADDR * 16U * 3300U / raw_vrefint; + print(" AVDD: 0x"); puth(adc_avdd_mV); print(" mV\n"); +} + +uint16_t adc_get_mV(const adc_signal_t *signal) { + uint16_t ret = 0; + + if (adc_avdd_mV == 0U) { + adc_calibrate_vdda(); + } + + if ((signal->adc == ADC1) || (signal->adc == ADC2)) { + ret = (adc_get_raw(signal) * adc_avdd_mV) / 65535U; + } else if (signal->adc == ADC3) { + ret = (adc_get_raw(signal) * adc_avdd_mV) / 4095U; + } else {} + return ret; +} diff --git a/panda/board/stm32h7/lladc_declarations.h b/panda/board/stm32h7/lladc_declarations.h new file mode 100644 index 0000000000..979919c8c9 --- /dev/null +++ b/panda/board/stm32h7/lladc_declarations.h @@ -0,0 +1,37 @@ +#pragma once + +typedef enum { + SAMPLETIME_1_CYCLE = 0, + SAMPLETIME_2_CYCLES = 1, + SAMPLETIME_8_CYCLES = 2, + SAMPLETIME_16_CYCLES = 3, + SAMPLETIME_32_CYCLES = 4, + SAMPLETIME_64_CYCLES = 5, + SAMPLETIME_387_CYCLES = 6, + SAMPLETIME_810_CYCLES = 7 +} adc_sample_time_t; + +typedef enum { + OVERSAMPLING_1 = 0, + OVERSAMPLING_2 = 1, + OVERSAMPLING_4 = 2, + OVERSAMPLING_8 = 3, + OVERSAMPLING_16 = 4, + OVERSAMPLING_32 = 5, + OVERSAMPLING_64 = 6, + OVERSAMPLING_128 = 7, + OVERSAMPLING_256 = 8, + OVERSAMPLING_512 = 9, + OVERSAMPLING_1024 = 10 +} adc_oversampling_t; + +typedef struct { + ADC_TypeDef *adc; + uint8_t channel; + adc_sample_time_t sample_time; + adc_oversampling_t oversampling; +} adc_signal_t; + +#define ADC_CHANNEL_DEFAULT(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_32_CYCLES, .oversampling = OVERSAMPLING_64} + +#define VREFINT_CAL_ADDR ((uint16_t *)0x1FF1E860UL) diff --git a/panda/board/stm32h7/llfan.h b/panda/board/stm32h7/llfan.h new file mode 100644 index 0000000000..06309d0633 --- /dev/null +++ b/panda/board/stm32h7/llfan.h @@ -0,0 +1,23 @@ +// TACH interrupt handler +static void EXTI2_IRQ_Handler(void) { + volatile unsigned int pr = EXTI->PR1 & (1U << 2); + if ((pr & (1U << 2)) != 0U) { + fan_state.tach_counter++; + } + EXTI->PR1 = (1U << 2); +} + +void llfan_init(void) { + // 12000RPM * 4 tach edges / 60 seconds + REGISTER_INTERRUPT(EXTI2_IRQn, EXTI2_IRQ_Handler, 1000U, FAULT_INTERRUPT_RATE_TACH) + + // Init PWM speed control + pwm_init(TIM3, 3); + + // Init TACH interrupt + register_set(&(SYSCFG->EXTICR[0]), SYSCFG_EXTICR1_EXTI2_PD, 0xF00U); + register_set_bits(&(EXTI->IMR1), (1U << 2)); + register_set_bits(&(EXTI->RTSR1), (1U << 2)); + register_set_bits(&(EXTI->FTSR1), (1U << 2)); + NVIC_EnableIRQ(EXTI2_IRQn); +} diff --git a/panda/board/stm32h7/llfdcan.h b/panda/board/stm32h7/llfdcan.h new file mode 100644 index 0000000000..64a40bd072 --- /dev/null +++ b/panda/board/stm32h7/llfdcan.h @@ -0,0 +1,227 @@ +#include "llfdcan_declarations.h" + +// kbps multiplied by 10 +const uint32_t speeds[SPEEDS_ARRAY_SIZE] = {100U, 200U, 500U, 1000U, 1250U, 2500U, 5000U, 10000U}; +const uint32_t data_speeds[DATA_SPEEDS_ARRAY_SIZE] = {100U, 200U, 500U, 1000U, 1250U, 2500U, 5000U, 10000U, 20000U, 50000U}; + +static bool fdcan_request_init(FDCAN_GlobalTypeDef *FDCANx) { + bool ret = true; + // Exit from sleep mode + FDCANx->CCCR &= ~(FDCAN_CCCR_CSR); + while ((FDCANx->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA); + + // Request init + uint32_t timeout_counter = 0U; + FDCANx->CCCR |= FDCAN_CCCR_INIT; + while ((FDCANx->CCCR & FDCAN_CCCR_INIT) == 0U) { + // Delay for about 1ms + delay(10000); + timeout_counter++; + + if (timeout_counter >= CAN_INIT_TIMEOUT_MS){ + ret = false; + break; + } + } + return ret; +} + +static bool fdcan_exit_init(FDCAN_GlobalTypeDef *FDCANx) { + bool ret = true; + + FDCANx->CCCR &= ~(FDCAN_CCCR_INIT); + uint32_t timeout_counter = 0U; + while ((FDCANx->CCCR & FDCAN_CCCR_INIT) != 0U) { + // Delay for about 1ms + delay(10000); + timeout_counter++; + + if (timeout_counter >= CAN_INIT_TIMEOUT_MS) { + ret = false; + break; + } + } + return ret; +} + +bool llcan_set_speed(FDCAN_GlobalTypeDef *FDCANx, uint32_t speed, uint32_t data_speed, bool non_iso, bool loopback, bool silent) { + UNUSED(speed); + bool ret = fdcan_request_init(FDCANx); + + if (ret) { + // Enable config change + FDCANx->CCCR |= FDCAN_CCCR_CCE; + + //Reset operation mode to Normal + FDCANx->CCCR &= ~(FDCAN_CCCR_TEST); + FDCANx->TEST &= ~(FDCAN_TEST_LBCK); + FDCANx->CCCR &= ~(FDCAN_CCCR_MON); + FDCANx->CCCR &= ~(FDCAN_CCCR_ASM); + FDCANx->CCCR &= ~(FDCAN_CCCR_NISO); + + // TODO: add as a separate safety mode + // Enable ASM restricted operation(for debug or automatic bitrate switching) + //FDCANx->CCCR |= FDCAN_CCCR_ASM; + + uint8_t prescaler = BITRATE_PRESCALER; + if (speed < 2500U) { + // The only way to support speeds lower than 250Kbit/s (down to 10Kbit/s) + prescaler = BITRATE_PRESCALER * 16U; + } + + // Set the nominal bit timing values + uint32_t tq = CAN_QUANTA(speed, prescaler); + uint32_t sp = CAN_SP_NOMINAL; + uint32_t seg1 = CAN_SEG1(tq, sp); + uint32_t seg2 = CAN_SEG2(tq, sp); + uint8_t sjw = MIN(127U, seg2); + + FDCANx->NBTP = (((sjw & 0x7FUL)-1U)<DBTP = (((sjw & 0xFUL)-1U)<CCCR |= FDCAN_CCCR_NISO; + } + + // Silent loopback is known as internal loopback in the docs + if (loopback) { + FDCANx->CCCR |= FDCAN_CCCR_TEST; + FDCANx->TEST |= FDCAN_TEST_LBCK; + FDCANx->CCCR |= FDCAN_CCCR_MON; + } + // Silent is known as bus monitoring in the docs + if (silent) { + FDCANx->CCCR |= FDCAN_CCCR_MON; + } + ret = fdcan_exit_init(FDCANx); + if (!ret) { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" set_speed timed out! (2)\n"); + } + } else { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" set_speed timed out! (1)\n"); + } + return ret; +} + +void llcan_irq_disable(const FDCAN_GlobalTypeDef *FDCANx) { + if (FDCANx == FDCAN1) { + NVIC_DisableIRQ(FDCAN1_IT0_IRQn); + NVIC_DisableIRQ(FDCAN1_IT1_IRQn); + } else if (FDCANx == FDCAN2) { + NVIC_DisableIRQ(FDCAN2_IT0_IRQn); + NVIC_DisableIRQ(FDCAN2_IT1_IRQn); + } else if (FDCANx == FDCAN3) { + NVIC_DisableIRQ(FDCAN3_IT0_IRQn); + NVIC_DisableIRQ(FDCAN3_IT1_IRQn); + } else { + } +} + +void llcan_irq_enable(const FDCAN_GlobalTypeDef *FDCANx) { + if (FDCANx == FDCAN1) { + NVIC_EnableIRQ(FDCAN1_IT0_IRQn); + NVIC_EnableIRQ(FDCAN1_IT1_IRQn); + } else if (FDCANx == FDCAN2) { + NVIC_EnableIRQ(FDCAN2_IT0_IRQn); + NVIC_EnableIRQ(FDCAN2_IT1_IRQn); + } else if (FDCANx == FDCAN3) { + NVIC_EnableIRQ(FDCAN3_IT0_IRQn); + NVIC_EnableIRQ(FDCAN3_IT1_IRQn); + } else { + } +} + +bool llcan_init(FDCAN_GlobalTypeDef *FDCANx) { + uint32_t can_number = CAN_NUM_FROM_CANIF(FDCANx); + bool ret = fdcan_request_init(FDCANx); + + if (ret) { + // Enable config change + FDCANx->CCCR |= FDCAN_CCCR_CCE; + // Enable automatic retransmission + FDCANx->CCCR &= ~(FDCAN_CCCR_DAR); + // Enable transmission pause feature + FDCANx->CCCR |= FDCAN_CCCR_TXP; + // Disable protocol exception handling + FDCANx->CCCR |= FDCAN_CCCR_PXHD; + // FD with BRS + FDCANx->CCCR |= (FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE); + + // Set TX mode to FIFO + FDCANx->TXBC &= ~(FDCAN_TXBC_TFQM); + // Configure TX element data size + FDCANx->TXESC |= 0x7U << FDCAN_TXESC_TBDS_Pos; // 64 bytes + //Configure RX FIFO0 element data size + FDCANx->RXESC |= 0x7U << FDCAN_RXESC_F0DS_Pos; + // Disable filtering, accept all valid frames received + FDCANx->XIDFC &= ~(FDCAN_XIDFC_LSE); // No extended filters + FDCANx->SIDFC &= ~(FDCAN_SIDFC_LSS); // No standard filters + FDCANx->GFC &= ~(FDCAN_GFC_RRFE); // Accept extended remote frames + FDCANx->GFC &= ~(FDCAN_GFC_RRFS); // Accept standard remote frames + FDCANx->GFC &= ~(FDCAN_GFC_ANFE); // Accept extended frames to FIFO 0 + FDCANx->GFC &= ~(FDCAN_GFC_ANFS); // Accept standard frames to FIFO 0 + + uint32_t RxFIFO0SA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET); + uint32_t TxFIFOSA = RxFIFO0SA + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE); + + // RX FIFO 0 + FDCANx->RXF0C |= (FDCAN_RX_FIFO_0_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_RXF0C_F0SA_Pos; + FDCANx->RXF0C |= FDCAN_RX_FIFO_0_EL_CNT << FDCAN_RXF0C_F0S_Pos; + // RX FIFO 0 switch to non-blocking (overwrite) mode + FDCANx->RXF0C |= FDCAN_RXF0C_F0OM; + + // TX FIFO (mode set earlier) + FDCANx->TXBC |= (FDCAN_TX_FIFO_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_TXBC_TBSA_Pos; + FDCANx->TXBC |= FDCAN_TX_FIFO_EL_CNT << FDCAN_TXBC_TFQS_Pos; + + // Flush allocated RAM + uint32_t EndAddress = TxFIFOSA + (FDCAN_TX_FIFO_EL_CNT * FDCAN_TX_FIFO_EL_SIZE); + for (uint32_t RAMcounter = RxFIFO0SA; RAMcounter < EndAddress; RAMcounter += 4U) { + *(uint32_t *)(RAMcounter) = 0x00000000; + } + + // Enable both interrupts for each module + FDCANx->ILE = (FDCAN_ILE_EINT0 | FDCAN_ILE_EINT1); + + FDCANx->IE &= 0x0U; // Reset all interrupts + // Messages for INT0 + FDCANx->IE |= FDCAN_IE_RF0NE; // Rx FIFO 0 new message + FDCANx->IE |= FDCAN_IE_PEDE | FDCAN_IE_PEAE | FDCAN_IE_BOE | FDCAN_IE_EPE | FDCAN_IE_RF0LE; + + // Messages for INT1 (Only TFE works??) + FDCANx->ILS |= FDCAN_ILS_TFEL; + FDCANx->IE |= FDCAN_IE_TFEE; // Tx FIFO empty + + ret = fdcan_exit_init(FDCANx); + if(!ret) { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" llcan_init timed out (2)!\n"); + } + + llcan_irq_enable(FDCANx); + + } else { + print(CAN_NAME_FROM_CANIF(FDCANx)); print(" llcan_init timed out (1)!\n"); + } + return ret; +} + +void llcan_clear_send(FDCAN_GlobalTypeDef *FDCANx) { + // from datasheet: "Transmit cancellation is not intended for Tx FIFO operation." + // so we need to clear pending transmission manually by resetting FDCAN core + FDCANx->IR |= 0x3FCFFFFFU; // clear all interrupts + bool ret = llcan_init(FDCANx); + UNUSED(ret); +} diff --git a/panda/board/stm32h7/llfdcan_declarations.h b/panda/board/stm32h7/llfdcan_declarations.h new file mode 100644 index 0000000000..793849011e --- /dev/null +++ b/panda/board/stm32h7/llfdcan_declarations.h @@ -0,0 +1,53 @@ +#pragma once + +// SAE J2284-4 document specifies a bus-line network running at 2 Mbit/s +// SAE J2284-5 document specifies a point-to-point communication running at 5 Mbit/s + +#define CAN_PCLK 80000U // KHz, sourced from PLL1Q +#define BITRATE_PRESCALER 2U // Valid from 250Kbps to 5Mbps with 80Mhz clock +#define CAN_SP_NOMINAL 80U // 80% for both SAE J2284-4 and SAE J2284-5 +#define CAN_SP_DATA_2M 80U // 80% for SAE J2284-4 +#define CAN_SP_DATA_5M 75U // 75% for SAE J2284-5 +#define CAN_QUANTA(speed, prescaler) (CAN_PCLK / ((speed) / 10U * (prescaler))) +#define CAN_SEG1(tq, sp) (((tq) * (sp) / 100U)- 1U) +#define CAN_SEG2(tq, sp) ((tq) * (100U - (sp)) / 100U) + +// FDCAN core settings +#define FDCAN_START_ADDRESS 0x4000AC00UL +#define FDCAN_OFFSET 3384UL // bytes for each FDCAN module, equally +#define FDCAN_OFFSET_W 846UL // words for each FDCAN module, equally + +// FDCAN_RX_FIFO_0_EL_CNT + FDCAN_TX_FIFO_EL_CNT can't exceed 47 elements (47 * 72 bytes = 3,384 bytes) per FDCAN module + +// RX FIFO 0 +#define FDCAN_RX_FIFO_0_EL_CNT 46UL +#define FDCAN_RX_FIFO_0_HEAD_SIZE 8UL // bytes +#define FDCAN_RX_FIFO_0_DATA_SIZE 64UL // bytes +#define FDCAN_RX_FIFO_0_EL_SIZE (FDCAN_RX_FIFO_0_HEAD_SIZE + FDCAN_RX_FIFO_0_DATA_SIZE) +#define FDCAN_RX_FIFO_0_EL_W_SIZE (FDCAN_RX_FIFO_0_EL_SIZE / 4UL) +#define FDCAN_RX_FIFO_0_OFFSET 0UL + +// TX FIFO +#define FDCAN_TX_FIFO_EL_CNT 1UL +#define FDCAN_TX_FIFO_HEAD_SIZE 8UL // bytes +#define FDCAN_TX_FIFO_DATA_SIZE 64UL // bytes +#define FDCAN_TX_FIFO_EL_SIZE (FDCAN_TX_FIFO_HEAD_SIZE + FDCAN_TX_FIFO_DATA_SIZE) +#define FDCAN_TX_FIFO_OFFSET (FDCAN_RX_FIFO_0_OFFSET + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_W_SIZE)) + +#define CAN_NAME_FROM_CANIF(CAN_DEV) (((CAN_DEV)==FDCAN1) ? "FDCAN1" : (((CAN_DEV) == FDCAN2) ? "FDCAN2" : "FDCAN3")) +#define CAN_NUM_FROM_CANIF(CAN_DEV) (((CAN_DEV)==FDCAN1) ? 0UL : (((CAN_DEV) == FDCAN2) ? 1UL : 2UL)) + + +void print(const char *a); + +// kbps multiplied by 10 +#define SPEEDS_ARRAY_SIZE 8 +extern const uint32_t speeds[SPEEDS_ARRAY_SIZE]; +#define DATA_SPEEDS_ARRAY_SIZE 10 +extern const uint32_t data_speeds[DATA_SPEEDS_ARRAY_SIZE]; + +bool llcan_set_speed(FDCAN_GlobalTypeDef *FDCANx, uint32_t speed, uint32_t data_speed, bool non_iso, bool loopback, bool silent); +void llcan_irq_disable(const FDCAN_GlobalTypeDef *FDCANx); +void llcan_irq_enable(const FDCAN_GlobalTypeDef *FDCANx); +bool llcan_init(FDCAN_GlobalTypeDef *FDCANx); +void llcan_clear_send(FDCAN_GlobalTypeDef *FDCANx); diff --git a/panda/board/stm32h7/llflash.h b/panda/board/stm32h7/llflash.h new file mode 100644 index 0000000000..b95011a9ed --- /dev/null +++ b/panda/board/stm32h7/llflash.h @@ -0,0 +1,33 @@ +bool flash_is_locked(void) { + return (FLASH->CR1 & FLASH_CR_LOCK); +} + +void flash_unlock(void) { + FLASH->KEYR1 = 0x45670123; + FLASH->KEYR1 = 0xCDEF89AB; +} + +bool flash_erase_sector(uint8_t sector, bool unlocked) { + // don't erase the bootloader(sector 0) + if (sector != 0 && sector < 8 && unlocked) { + FLASH->CR1 = (sector << 8) | FLASH_CR_SER; + FLASH->CR1 |= FLASH_CR_START; + while (FLASH->SR1 & FLASH_SR_QW); + return true; + } + return false; +} + +void flash_write_word(void *prog_ptr, uint32_t data) { + uint32_t *pp = prog_ptr; + FLASH->CR1 |= FLASH_CR_PG; + *pp = data; + while (FLASH->SR1 & FLASH_SR_QW); +} + +void flush_write_buffer(void) { + if (FLASH->SR1 & FLASH_SR_WBNE) { + FLASH->CR1 |= FLASH_CR_FW; + while (FLASH->SR1 & FLASH_CR_FW); + } +} diff --git a/panda/board/stm32h7/lli2c.h b/panda/board/stm32h7/lli2c.h new file mode 100644 index 0000000000..5d79beb653 --- /dev/null +++ b/panda/board/stm32h7/lli2c.h @@ -0,0 +1,167 @@ +// TODO: this driver relies heavily on polling, +// if we want it to be more async, we should use interrupts + +#define I2C_RETRY_COUNT 10U +#define I2C_TIMEOUT_US 100000U + +bool i2c_status_wait(const volatile uint32_t *reg, uint32_t mask, uint32_t val) { + uint32_t start_time = microsecond_timer_get(); + while(((*reg & mask) != val) && (get_ts_elapsed(microsecond_timer_get(), start_time) < I2C_TIMEOUT_US)); + return ((*reg & mask) == val); +} + +void i2c_reset(I2C_TypeDef *I2C) { + // peripheral reset + register_clear_bits(&I2C->CR1, I2C_CR1_PE); + while ((I2C->CR1 & I2C_CR1_PE) != 0U); + register_set_bits(&I2C->CR1, I2C_CR1_PE); +} + +bool i2c_write_reg(I2C_TypeDef *I2C, uint8_t addr, uint8_t reg, uint8_t value) { + bool ret = false; + + // Setup transfer and send START + addr + for (uint32_t i = 0U; i < I2C_RETRY_COUNT; i++) { + register_clear_bits(&I2C->CR2, I2C_CR2_ADD10); + I2C->CR2 = ((uint32_t)addr << 1U) & I2C_CR2_SADD_Msk; + register_clear_bits(&I2C->CR2, I2C_CR2_RD_WRN); + register_set_bits(&I2C->CR2, I2C_CR2_AUTOEND); + I2C->CR2 |= 2UL << I2C_CR2_NBYTES_Pos; + + I2C->CR2 |= I2C_CR2_START; + if(!i2c_status_wait(&I2C->CR2, I2C_CR2_START, 0U)) { + continue; + } + + // check if we lost arbitration + if ((I2C->ISR & I2C_ISR_ARLO) != 0U) { + register_set_bits(&I2C->ICR, I2C_ICR_ARLOCF); + } else { + ret = true; + break; + } + } + + if (!ret) { + goto end; + } + + // Send data + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_TXIS, I2C_ISR_TXIS); + if(!ret) { + goto end; + } + I2C->TXDR = reg; + + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_TXIS, I2C_ISR_TXIS); + if(!ret) { + goto end; + } + I2C->TXDR = value; + +end: + return ret; +} + +bool i2c_read_reg(I2C_TypeDef *I2C, uint8_t addr, uint8_t reg, uint8_t *value) { + bool ret = false; + + // Setup transfer and send START + addr + for (uint32_t i = 0U; i < I2C_RETRY_COUNT; i++) { + register_clear_bits(&I2C->CR2, I2C_CR2_ADD10); + I2C->CR2 = ((uint32_t)addr << 1U) & I2C_CR2_SADD_Msk; + register_clear_bits(&I2C->CR2, I2C_CR2_RD_WRN); + register_clear_bits(&I2C->CR2, I2C_CR2_AUTOEND); + I2C->CR2 |= 1UL << I2C_CR2_NBYTES_Pos; + + I2C->CR2 |= I2C_CR2_START; + if(!i2c_status_wait(&I2C->CR2, I2C_CR2_START, 0U)) { + continue; + } + + // check if we lost arbitration + if ((I2C->ISR & I2C_ISR_ARLO) != 0U) { + register_set_bits(&I2C->ICR, I2C_ICR_ARLOCF); + } else { + ret = true; + break; + } + } + + if (!ret) { + goto end; + } + + // Send data + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_TXIS, I2C_ISR_TXIS); + if(!ret) { + goto end; + } + I2C->TXDR = reg; + + // Restart + I2C->CR2 = (((addr << 1) | 0x1U) & I2C_CR2_SADD_Msk) | (1UL << I2C_CR2_NBYTES_Pos) | I2C_CR2_RD_WRN | I2C_CR2_START; + ret = i2c_status_wait(&I2C->CR2, I2C_CR2_START, 0U); + if(!ret) { + goto end; + } + + // check if we lost arbitration + if ((I2C->ISR & I2C_ISR_ARLO) != 0U) { + register_set_bits(&I2C->ICR, I2C_ICR_ARLOCF); + ret = false; + goto end; + } + + // Read data + ret = i2c_status_wait(&I2C->ISR, I2C_ISR_RXNE, I2C_ISR_RXNE); + if(!ret) { + goto end; + } + *value = I2C->RXDR; + + // Stop + I2C->CR2 |= I2C_CR2_STOP; + +end: + + if (!ret) { + i2c_reset(I2C); + } + + return ret; +} + +bool i2c_set_reg_bits(I2C_TypeDef *I2C, uint8_t address, uint8_t regis, uint8_t bits) { + uint8_t value; + bool ret = i2c_read_reg(I2C, address, regis, &value); + if(ret) { + ret = i2c_write_reg(I2C, address, regis, value | bits); + } + return ret; +} + +bool i2c_clear_reg_bits(I2C_TypeDef *I2C, uint8_t address, uint8_t regis, uint8_t bits) { + uint8_t value; + bool ret = i2c_read_reg(I2C, address, regis, &value); + if (ret) { + ret = i2c_write_reg(I2C, address, regis, value & (uint8_t) (~bits)); + } + return ret; +} + +bool i2c_set_reg_mask(I2C_TypeDef *I2C, uint8_t address, uint8_t regis, uint8_t value, uint8_t mask) { + uint8_t old_value; + bool ret = i2c_read_reg(I2C, address, regis, &old_value); + if(ret) { + ret = i2c_write_reg(I2C, address, regis, (old_value & (uint8_t) (~mask)) | (value & mask)); + } + return ret; +} + +void i2c_init(I2C_TypeDef *I2C) { + // 100kHz clock speed + I2C->TIMINGR = 0x107075B0; + + i2c_reset(I2C); +} diff --git a/panda/board/stm32h7/llspi.h b/panda/board/stm32h7/llspi.h new file mode 100644 index 0000000000..05f8e22f9a --- /dev/null +++ b/panda/board/stm32h7/llspi.h @@ -0,0 +1,107 @@ +// master -> panda DMA start +void llspi_mosi_dma(uint8_t *addr, int len) { + // disable DMA + SPI + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + DMA2_Stream2->CR &= ~DMA_SxCR_EN; + register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); + + // drain the bus + while ((SPI4->SR & SPI_SR_RXP) != 0U) { + volatile uint8_t dat = SPI4->RXDR; + (void)dat; + } + + // clear all pending + SPI4->IFCR |= (0x1FFU << 3U); + register_set(&(SPI4->IER), 0, 0x3FFU); + + // setup destination and length + register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + DMA2_Stream2->NDTR = len; + + // enable DMA + SPI + DMA2_Stream2->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); +} + +// panda -> master DMA start +void llspi_miso_dma(uint8_t *addr, int len) { + // disable DMA + SPI + DMA2_Stream3->CR &= ~DMA_SxCR_EN; + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); + + // setup source and length + register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + DMA2_Stream3->NDTR = len; + + // clear under-run while we were reading + SPI4->IFCR |= (0x1FFU << 3U); + + // setup interrupt on TXC + register_set(&(SPI4->IER), (1U << SPI_IER_EOTIE_Pos), 0x3FFU); + + // enable DMA + SPI + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + DMA2_Stream3->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); +} + +static bool spi_tx_dma_done = false; +// master -> panda DMA finished +static void DMA2_Stream2_IRQ_Handler(void) { + // Clear interrupt flag + DMA2->LIFCR = DMA_LIFCR_CTCIF2; + + spi_rx_done(); +} + +// panda -> master DMA finished +static void DMA2_Stream3_IRQ_Handler(void) { + ENTER_CRITICAL(); + + DMA2->LIFCR = DMA_LIFCR_CTCIF3; + spi_tx_dma_done = true; + + EXIT_CRITICAL(); +} + +// panda TX finished +static void SPI4_IRQ_Handler(void) { + // clear flag + SPI4->IFCR |= (0x1FFU << 3U); + + if (spi_tx_dma_done && ((SPI4->SR & SPI_SR_TXC) != 0U)) { + spi_tx_dma_done = false; + spi_tx_done(false); + } +} + + +void llspi_init(void) { + REGISTER_INTERRUPT(SPI4_IRQn, SPI4_IRQ_Handler, (SPI_IRQ_RATE * 2U), FAULT_INTERRUPT_RATE_SPI) + REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) + REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) + + // Setup MOSI DMA + register_set(&(DMAMUX1_Channel10->CCR), 83U, 0xFFFFFFFFU); + register_set(&(DMA2_Stream2->CR), (DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI4->RXDR), 0xFFFFFFFFU); + + // Setup MISO DMA, memory -> peripheral + register_set(&(DMAMUX1_Channel11->CCR), 84U, 0xFFFFFFFFU); + register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); + + // Enable SPI + register_set(&(SPI4->IER), 0, 0x3FFU); + register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); + register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging + register_set(&(SPI4->CR1), SPI_CR1_SPE, 0xFFFFU); + register_set(&(SPI4->CR2), 0, 0xFFFFU); + + NVIC_EnableIRQ(DMA2_Stream2_IRQn); + NVIC_EnableIRQ(DMA2_Stream3_IRQn); + NVIC_EnableIRQ(SPI4_IRQn); +} diff --git a/panda/board/stm32h7/lluart.h b/panda/board/stm32h7/lluart.h new file mode 100644 index 0000000000..e18f1e9f6f --- /dev/null +++ b/panda/board/stm32h7/lluart.h @@ -0,0 +1,102 @@ +static void uart_rx_ring(uart_ring *q){ + // Do not read out directly if DMA enabled + ENTER_CRITICAL(); + + // Read out RX buffer + uint8_t c = q->uart->RDR; // This read after reading SR clears a bunch of interrupts + + uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size; + + if ((next_w_ptr == q->r_ptr_rx) && q->overwrite) { + // overwrite mode: drop oldest byte + q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size; + } + + // Do not overwrite buffer data + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = c; + q->w_ptr_rx = next_w_ptr; + if (q->callback != NULL) { + q->callback(q); + } + } + + EXIT_CRITICAL(); +} + +void uart_tx_ring(uart_ring *q){ + ENTER_CRITICAL(); + // Send out next byte of TX buffer + if (q->w_ptr_tx != q->r_ptr_tx) { + // Only send if transmit register is empty (aka last byte has been sent) + if ((q->uart->ISR & USART_ISR_TXE_TXFNF) != 0U) { + q->uart->TDR = q->elems_tx[q->r_ptr_tx]; // This clears TXE + q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size; + } + + // Enable TXE interrupt if there is still data to be sent + if(q->r_ptr_tx != q->w_ptr_tx){ + q->uart->CR1 |= USART_CR1_TXEIE; + } else { + q->uart->CR1 &= ~USART_CR1_TXEIE; + } + } + EXIT_CRITICAL(); +} + +// This read after reading ISR clears all error interrupts. We don't want compiler warnings, nor optimizations +#define UART_READ_RDR(uart) volatile uint8_t t = (uart)->RDR; UNUSED(t); + +static void uart_interrupt_handler(uart_ring *q) { + ENTER_CRITICAL(); + + // Read UART status. This is also the first step necessary in clearing most interrupts + uint32_t status = q->uart->ISR; + + // If RXFNE is set, perform a read. This clears RXFNE, ORE, IDLE, NF and FE + if((status & USART_ISR_RXNE_RXFNE) != 0U){ + uart_rx_ring(q); + } + + // Detect errors and clear them + uint32_t err = (status & USART_ISR_ORE) | (status & USART_ISR_NE) | (status & USART_ISR_FE) | (status & USART_ISR_PE); + if(err != 0U){ + #ifdef DEBUG_UART + print("Encountered UART error: "); puth(err); print("\n"); + #endif + UART_READ_RDR(q->uart) + } + + if ((err & USART_ISR_ORE) != 0U) { + q->uart->ICR |= USART_ICR_ORECF; + } else if ((err & USART_ISR_NE) != 0U) { + q->uart->ICR |= USART_ICR_NECF; + } else if ((err & USART_ISR_FE) != 0U) { + q->uart->ICR |= USART_ICR_FECF; + } else if ((err & USART_ISR_PE) != 0U) { + q->uart->ICR |= USART_ICR_PECF; + } else {} + + // Send if necessary + uart_tx_ring(q); + + EXIT_CRITICAL(); +} + +static void UART7_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_som_debug); } + +void uart_init(uart_ring *q, unsigned int baud) { + if (q->uart == UART7) { + REGISTER_INTERRUPT(UART7_IRQn, UART7_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_7) + + // UART7 is connected to APB1 at 60MHz + q->uart->BRR = 60000000U / baud; + q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; + + // Enable interrupt on RX not empty + q->uart->CR1 |= USART_CR1_RXNEIE; + + // Enable UART interrupts + NVIC_EnableIRQ(UART7_IRQn); + } +} diff --git a/panda/board/stm32h7/llusb.h b/panda/board/stm32h7/llusb.h new file mode 100644 index 0000000000..f1bcf16ad5 --- /dev/null +++ b/panda/board/stm32h7/llusb.h @@ -0,0 +1,79 @@ +#include "llusb_declarations.h" + +USB_OTG_GlobalTypeDef *USBx = USB_OTG_HS; + +static void OTG_HS_IRQ_Handler(void) { + NVIC_DisableIRQ(OTG_HS_IRQn); + usb_irqhandler(); + NVIC_EnableIRQ(OTG_HS_IRQn); +} + +void usb_init(void) { + REGISTER_INTERRUPT(OTG_HS_IRQn, OTG_HS_IRQ_Handler, 1500000U, FAULT_INTERRUPT_RATE_USB) // TODO: Find out a better rate limit for USB. Now it's the 1.5MB/s rate + + // Disable global interrupt + USBx->GAHBCFG &= ~(USB_OTG_GAHBCFG_GINT); + // Select FS Embedded PHY + USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; + // Force device mode + USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD); + USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD; + delay(250000); // Wait for about 25ms (explicitly stated in H7 ref manual) + // Wait for AHB master IDLE state. + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U); + // Core Soft Reset + USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST); + // Activate the USB Transceiver + USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN; + + for (uint8_t i = 0U; i < 15U; i++) { + USBx->DIEPTXF[i] = 0U; + } + + // VBUS Sensing setup + USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS; + // Deactivate VBUS Sensing B + USBx->GCCFG &= ~(USB_OTG_GCCFG_VBDEN); + // B-peripheral session valid override enable + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; + // Restart the Phy Clock + USBx_PCGCCTL = 0U; + // Device mode configuration + USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80; + USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK; + + // Flush FIFOs + USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (0x10U << 6)); + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH); + + USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH; + while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH); + + // Clear all pending Device Interrupts + USBx_DEVICE->DIEPMSK = 0U; + USBx_DEVICE->DOEPMSK = 0U; + USBx_DEVICE->DAINTMSK = 0U; + USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM); + + // Disable all interrupts. + USBx->GINTMSK = 0U; + // Clear any pending interrupts + USBx->GINTSTS = 0xBFFFFFFFU; + // Enable interrupts matching to the Device mode ONLY + USBx->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT | + USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM | + USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | + USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM; + + // Set USB Turnaround time + USBx->GUSBCFG |= ((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT); + // Enables the controller's Global Int in the AHB Config reg + USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT; + // Soft disconnect disable: + USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_SDIS); + + // enable the IRQ + NVIC_EnableIRQ(OTG_HS_IRQn); +} diff --git a/panda/board/stm32h7/llusb_declarations.h b/panda/board/stm32h7/llusb_declarations.h new file mode 100644 index 0000000000..a11d3f52c6 --- /dev/null +++ b/panda/board/stm32h7/llusb_declarations.h @@ -0,0 +1,16 @@ +#pragma once + +extern USB_OTG_GlobalTypeDef *USBx; + +#define USBx_DEVICE ((USB_OTG_DeviceTypeDef *)((uint32_t)USBx + USB_OTG_DEVICE_BASE)) +#define USBx_INEP(i) ((USB_OTG_INEndpointTypeDef *)((uint32_t)USBx + USB_OTG_IN_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) +#define USBx_OUTEP(i) ((USB_OTG_OUTEndpointTypeDef *)((uint32_t)USBx + USB_OTG_OUT_ENDPOINT_BASE + ((i) * USB_OTG_EP_REG_SIZE))) +#define USBx_DFIFO(i) *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_FIFO_BASE + ((i) * USB_OTG_FIFO_SIZE)) +#define USBx_PCGCCTL *(__IO uint32_t *)((uint32_t)USBx + USB_OTG_PCGCCTL_BASE) + +#define USBD_FS_TRDT_VALUE 6UL +#define USB_OTG_SPEED_FULL 3U +#define DCFG_FRAME_INTERVAL_80 0U + +void usb_irqhandler(void); +void usb_init(void); diff --git a/panda/board/stm32h7/peripherals.h b/panda/board/stm32h7/peripherals.h new file mode 100644 index 0000000000..8eb384307f --- /dev/null +++ b/panda/board/stm32h7/peripherals.h @@ -0,0 +1,135 @@ +#ifdef BOOTSTUB +void gpio_usb_init(void) { +#else +static void gpio_usb_init(void) { +#endif + // A11,A12: USB + set_gpio_alternate(GPIOA, 11, GPIO_AF10_OTG1_FS); + set_gpio_alternate(GPIOA, 12, GPIO_AF10_OTG1_FS); + GPIOA->OSPEEDR = GPIO_OSPEEDR_OSPEED11 | GPIO_OSPEEDR_OSPEED12; +} + +void gpio_spi_init(void) { + set_gpio_alternate(GPIOE, 11, GPIO_AF5_SPI4); + set_gpio_alternate(GPIOE, 12, GPIO_AF5_SPI4); + set_gpio_alternate(GPIOE, 13, GPIO_AF5_SPI4); + set_gpio_alternate(GPIOE, 14, GPIO_AF5_SPI4); + register_set_bits(&(GPIOE->OSPEEDR), GPIO_OSPEEDR_OSPEED11 | GPIO_OSPEEDR_OSPEED12 | GPIO_OSPEEDR_OSPEED13 | GPIO_OSPEEDR_OSPEED14); +} + +#ifdef BOOTSTUB +void gpio_usart2_init(void) { + // A2,A3: USART 2 for debugging + set_gpio_alternate(GPIOA, 2, GPIO_AF7_USART2); + set_gpio_alternate(GPIOA, 3, GPIO_AF7_USART2); +} +#endif + +void gpio_uart7_init(void) { + // E7,E8: UART 7 for debugging + set_gpio_alternate(GPIOE, 7, GPIO_AF7_UART7); + set_gpio_alternate(GPIOE, 8, GPIO_AF7_UART7); +} + +// Common GPIO initialization +void common_init_gpio(void) { + //F11: VOLT_S + set_gpio_pullup(GPIOF, 11, PULL_NONE); + set_gpio_mode(GPIOF, 11, MODE_ANALOG); + + gpio_usb_init(); + + // B8,B9: FDCAN1 + set_gpio_pullup(GPIOB, 8, PULL_NONE); + set_gpio_alternate(GPIOB, 8, GPIO_AF9_FDCAN1); + + set_gpio_pullup(GPIOB, 9, PULL_NONE); + set_gpio_alternate(GPIOB, 9, GPIO_AF9_FDCAN1); + + // B5,B6 (mplex to B12,B13): FDCAN2 + set_gpio_pullup(GPIOB, 12, PULL_NONE); + set_gpio_pullup(GPIOB, 13, PULL_NONE); + + set_gpio_pullup(GPIOB, 5, PULL_NONE); + set_gpio_alternate(GPIOB, 5, GPIO_AF9_FDCAN2); + + set_gpio_pullup(GPIOB, 6, PULL_NONE); + set_gpio_alternate(GPIOB, 6, GPIO_AF9_FDCAN2); + + // G9,G10: FDCAN3 + set_gpio_pullup(GPIOG, 9, PULL_NONE); + set_gpio_alternate(GPIOG, 9, GPIO_AF2_FDCAN3); + + set_gpio_pullup(GPIOG, 10, PULL_NONE); + set_gpio_alternate(GPIOG, 10, GPIO_AF2_FDCAN3); +} + +#ifdef BOOTSTUB +void flasher_peripherals_init(void) { + RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSEN; + + // SPI + DMA + RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; + + // LED PWM + RCC->APB1LENR |= RCC_APB1LENR_TIM3EN; +} +#endif + +// Peripheral initialization +void peripherals_init(void) { + // enable GPIO(A,B,C,D,E,F,G,H) + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOBEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOCEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIODEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOEEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOFEN; + RCC->AHB4ENR |= RCC_AHB4ENR_GPIOGEN; + + // Enable CPU access to SRAMs for DMA + RCC->AHB2ENR |= RCC_AHB2ENR_SRAM1EN | RCC_AHB2ENR_SRAM2EN; + + // Supplemental + RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // DAC DMA + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // SPI DMA + RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; + RCC->AHB4ENR |= RCC_AHB4ENR_BDMAEN; // Audio DMA + + // Connectivity + RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; // SPI + RCC->APB1LENR |= RCC_APB1LENR_I2C5EN; // codec I2C + RCC->AHB1ENR |= RCC_AHB1ENR_USB1OTGHSEN; // USB + RCC->AHB1LPENR |= RCC_AHB1LPENR_USB1OTGHSLPEN; // USB LP needed for CSleep state(__WFI()) + RCC->AHB1LPENR &= ~(RCC_AHB1LPENR_USB1OTGHSULPILPEN); // disable USB ULPI + RCC->APB1LENR |= RCC_APB1LENR_UART7EN; // SOM uart + RCC->APB1HENR |= RCC_APB1HENR_FDCANEN; // FDCAN core enable + + // Analog + RCC->AHB1ENR |= RCC_AHB1ENR_ADC12EN; // Enable ADC12 clocks + RCC->AHB4ENR |= RCC_AHB4ENR_ADC3EN; // Enable ADC3 clocks + RCC->APB1LENR |= RCC_APB1LENR_DAC12EN; // DAC + + // Audio + RCC->APB2ENR |= RCC_APB2ENR_DFSDM1EN; // D/S demodulator for mic + RCC->APB4ENR |= RCC_APB4ENR_SAI4EN; // SAI4 + + // Timers + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // clock source timer + RCC->APB1LENR |= RCC_APB1LENR_TIM2EN; // main counter + RCC->APB1LENR |= RCC_APB1LENR_TIM3EN; // fan + led pwm + RCC->APB1LENR |= RCC_APB1LENR_TIM6EN; // interrupt timer + RCC->APB1LENR |= RCC_APB1LENR_TIM7EN; // DMA trigger timer + RCC->APB2ENR |= RCC_APB2ENR_TIM8EN; // tick timer + RCC->APB1LENR |= RCC_APB1LENR_TIM12EN; // slow loop + RCC->APB1LENR |= RCC_APB1LENR_TIM5EN; // sound trigger timer + +#ifdef PANDA_JUNGLE + RCC->AHB3ENR |= RCC_AHB3ENR_SDMMC1EN; // SDMMC +#endif +} + +void enable_interrupt_timer(void) { + register_set_bits(&(RCC->APB1LENR), RCC_APB1LENR_TIM6EN); // Enable interrupt timer peripheral +} diff --git a/panda/board/stm32h7/sound.h b/panda/board/stm32h7/sound.h new file mode 100644 index 0000000000..aeee2c71f4 --- /dev/null +++ b/panda/board/stm32h7/sound.h @@ -0,0 +1,184 @@ +#define SOUND_RX_BUF_SIZE 1000U +#define SOUND_TX_BUF_SIZE (SOUND_RX_BUF_SIZE/2U) +#define MIC_RX_BUF_SIZE 512U +#define MIC_TX_BUF_SIZE (MIC_RX_BUF_SIZE * 2U) +__attribute__((section(".sram4"))) static uint16_t sound_rx_buf[2][SOUND_RX_BUF_SIZE]; +__attribute__((section(".sram4"))) static uint16_t sound_tx_buf[2][SOUND_TX_BUF_SIZE]; +__attribute__((section(".sram4"))) static uint32_t mic_rx_buf[2][MIC_RX_BUF_SIZE]; + +#define SOUND_IDLE_TIMEOUT 4U +static uint8_t sound_idle_count; +static uint8_t mic_idle_count; + +void sound_tick(void) { + if (sound_idle_count > 0U) { + sound_idle_count--; + if (sound_idle_count == 0U) { + current_board->set_amp_enabled(false); + register_clear_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } + } + + if (mic_idle_count > 0U) { + mic_idle_count--; + if (mic_idle_count == 0U) { + register_clear_bits(&DFSDM1_Channel0->CHCFGR1, DFSDM_CHCFGR1_DFSDMEN); + } + } +} + +// Recording processing +static void DMA1_Stream0_IRQ_Handler(void) { + __attribute__((section(".sram4"))) static uint16_t tx_buf[MIC_TX_BUF_SIZE]; + + DMA1->LIFCR |= 0x7D; // clear flags + + // process samples + uint8_t buf_idx = (((DMA1_Stream0->CR & DMA_SxCR_CT) >> DMA_SxCR_CT_Pos) == 1U) ? 0U : 1U; + for (uint16_t i=0U; i < MIC_RX_BUF_SIZE; i++) { + tx_buf[2U*i] = ((mic_rx_buf[buf_idx][i] >> 16U) & 0xFFFFU); + tx_buf[(2U*i)+1U] = tx_buf[2U*i]; + } + + BDMA->IFCR |= BDMA_IFCR_CGIF1; + BDMA_Channel1->CCR &= ~BDMA_CCR_EN; + register_set(&BDMA_Channel1->CM0AR, (uint32_t) tx_buf, 0xFFFFFFFFU); + BDMA_Channel1->CNDTR = MIC_TX_BUF_SIZE; + BDMA_Channel1->CCR |= BDMA_CCR_EN; +} + +// Playback processing +static void BDMA_Channel0_IRQ_Handler(void) { + static uint8_t playback_buf = 0U; + + BDMA->IFCR |= BDMA_IFCR_CGIF0; // clear flag + + uint8_t rx_buf_idx = (((BDMA_Channel0->CCR & BDMA_CCR_CT) >> BDMA_CCR_CT_Pos) == 1U) ? 0U : 1U; + playback_buf = 1U - playback_buf; + + // wait until we're done playing the current buf + for (uint32_t timeout_counter = 100000U; timeout_counter > 0U; timeout_counter--){ + uint8_t playing_buf = (DMA1_Stream1->CR & DMA_SxCR_CT) >> DMA_SxCR_CT_Pos; + if ((playing_buf != playback_buf) || (!(DMA1_Stream1->CR & DMA_SxCR_EN))) { + break; + } + } + + // process samples (shift to 12b and bias to be unsigned) + bool sound_playing = false; + for (uint16_t i=0U; i < SOUND_RX_BUF_SIZE; i += 2U) { + // since we are playing mono and receiving stereo, we take every other sample + sound_tx_buf[playback_buf][i/2U] = ((sound_rx_buf[rx_buf_idx][i] + (1UL << 14)) >> 3); + if (sound_rx_buf[rx_buf_idx][i] > 0U) { + sound_playing = true; + } + } + + // manage amp state + if (sound_playing) { + if (sound_idle_count == 0U) { + current_board->set_amp_enabled(true); + + // empty the other buf and start playing that + for (uint16_t i=0U; i < SOUND_TX_BUF_SIZE; i++) { + sound_tx_buf[1U - playback_buf][i] = (1UL << 11); + } + register_clear_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + DMA1_Stream1->CR = (DMA1_Stream1->CR & ~DMA_SxCR_CT_Msk) | ((1UL - playback_buf) << DMA_SxCR_CT_Pos); + register_set_bits(&DMA1_Stream1->CR, DMA_SxCR_EN); + } + sound_idle_count = SOUND_IDLE_TIMEOUT; + } + + // manage mic state + if (mic_idle_count == 0U) { + register_set_bits(&DFSDM1_Channel0->CHCFGR1, DFSDM_CHCFGR1_DFSDMEN); + DFSDM1_Filter0->FLTCR1 |= DFSDM_FLTCR1_RSWSTART; + } + mic_idle_count = SOUND_IDLE_TIMEOUT; + + sound_tick(); +} + +void sound_init(void) { + REGISTER_INTERRUPT(BDMA_Channel0_IRQn, BDMA_Channel0_IRQ_Handler, 128U, FAULT_INTERRUPT_RATE_SOUND_DMA) + REGISTER_INTERRUPT(DMA1_Stream0_IRQn, DMA1_Stream0_IRQ_Handler, 128U, FAULT_INTERRUPT_RATE_SOUND_DMA) + + // Init DAC + DAC1->DHR12R1 = (1UL << 11); + DAC1->DHR12R2 = (1UL << 11); + register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU); + register_set(&DAC1->CR, DAC_CR_TEN1 | (4U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU); + register_set_bits(&DAC1->CR, DAC_CR_EN1 | DAC_CR_EN2); + + // Setup DMAMUX (DAC_CH1_DMA as input) + register_set(&DMAMUX1_Channel1->CCR, 67U, DMAMUX_CxCR_DMAREQ_ID_Msk); + + // Setup DMA + register_set(&DMA1_Stream1->PAR, (uint32_t) &(DAC1->DHR12R1), 0xFFFFFFFFU); + register_set(&DMA1_Stream1->M0AR, (uint32_t) sound_tx_buf[0], 0xFFFFFFFFU); + register_set(&DMA1_Stream1->M1AR, (uint32_t) sound_tx_buf[1], 0xFFFFFFFFU); + register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U); + DMA1_Stream1->NDTR = SOUND_TX_BUF_SIZE; + DMA1_Stream1->CR = DMA_SxCR_DBM | (0b11UL << DMA_SxCR_PL_Pos) | (0b01UL << DMA_SxCR_MSIZE_Pos) | (0b01UL << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | (1U << DMA_SxCR_DIR_Pos); + + // Init trigger timer (little slower than 48kHz, pulled in sync by SAI4_FS_B) + register_set(&TIM5->PSC, 2600U, 0xFFFFU); + register_set(&TIM5->ARR, 100U, 0xFFFFFFFFU); // not important + register_set(&TIM5->AF1, (0b0010UL << TIM5_AF1_ETRSEL_Pos), TIM5_AF1_ETRSEL_Msk); + register_set(&TIM5->CR2, (0b010U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk); + register_set(&TIM5->SMCR, TIM_SMCR_ECE | (0b00111UL << TIM_SMCR_TS_Pos)| (0b0100UL << TIM_SMCR_SMS_Pos), 0x31FFF7U); + TIM5->CNT = 0U; TIM5->SR = 0U; + TIM5->CR1 |= TIM_CR1_CEN; + + // sync both SAIs + register_set(&SAI4->GCR, (0b10UL << SAI_GCR_SYNCOUT_Pos), SAI_GCR_SYNCIN_Msk | SAI_GCR_SYNCOUT_Msk); + + // stereo audio in + register_set(&SAI4_Block_B->CR1, SAI_xCR1_DMAEN | (0b00UL << SAI_xCR1_SYNCEN_Pos) | (0b100U << SAI_xCR1_DS_Pos) | (0b11U << SAI_xCR1_MODE_Pos), 0x0FFB3FEFU); + register_set(&SAI4_Block_B->CR2, (0b001U << SAI_xCR2_FTH_Pos), 0xFFFBU); + register_set(&SAI4_Block_B->FRCR, (31U << SAI_xFRCR_FRL_Pos), 0x7FFFFU); + register_set(&SAI4_Block_B->SLOTR, (0b11UL << SAI_xSLOTR_SLOTEN_Pos) | (1UL << SAI_xSLOTR_NBSLOT_Pos) | (0b01UL << SAI_xSLOTR_SLOTSZ_Pos), 0xFFFF0FDFU); // NBSLOT definition is vague + + // init sound DMA (SAI4_B -> memory, double buffers) + register_set(&BDMA_Channel0->CPAR, (uint32_t) &(SAI4_Block_B->DR), 0xFFFFFFFFU); + register_set(&BDMA_Channel0->CM0AR, (uint32_t) sound_rx_buf[0], 0xFFFFFFFFU); + register_set(&BDMA_Channel0->CM1AR, (uint32_t) sound_rx_buf[1], 0xFFFFFFFFU); + BDMA_Channel0->CNDTR = SOUND_RX_BUF_SIZE; + register_set(&BDMA_Channel0->CCR, BDMA_CCR_DBM | (0b01UL << BDMA_CCR_MSIZE_Pos) | (0b01UL << BDMA_CCR_PSIZE_Pos) | BDMA_CCR_MINC | BDMA_CCR_CIRC | BDMA_CCR_TCIE, 0xFFFFU); + register_set(&DMAMUX2_Channel0->CCR, 16U, DMAMUX_CxCR_DMAREQ_ID_Msk); // SAI4_B_DMA + register_set_bits(&BDMA_Channel0->CCR, BDMA_CCR_EN); + + // mic output + register_set(&SAI4_Block_A->CR1, SAI_xCR1_DMAEN | (0b01UL << SAI_xCR1_SYNCEN_Pos) | (0b100UL << SAI_xCR1_DS_Pos) | (0b10UL << SAI_xCR1_MODE_Pos), 0x0FFB3FEFU); + register_set(&SAI4_Block_A->CR2, 0U, 0xFFFBU); + register_set(&SAI4_Block_A->FRCR, (31U << SAI_xFRCR_FRL_Pos), 0x7FFFFU); + register_set(&SAI4_Block_A->SLOTR, (0b11UL << SAI_xSLOTR_SLOTEN_Pos) | (1UL << SAI_xSLOTR_NBSLOT_Pos) | (0b01U << SAI_xSLOTR_SLOTSZ_Pos), 0xFFFF0FDFU); // NBSLOT definition is vague + + // init DFSDM for PDM mic + register_set(&DFSDM1_Channel0->CHCFGR1, (76UL << DFSDM_CHCFGR1_CKOUTDIV_Pos) | DFSDM_CHCFGR1_CHEN, 0xC0FFF1EFU); // CH0 controls the clock + register_set(&DFSDM1_Channel3->CHCFGR1, (0b01UL << DFSDM_CHCFGR1_SPICKSEL_Pos) | (0b00U << DFSDM_CHCFGR1_SITP_Pos) | DFSDM_CHCFGR1_CHEN, 0x0000F1EFU); // SITP determines sample edge + register_set(&DFSDM1_Filter0->FLTFCR, (0U << DFSDM_FLTFCR_IOSR_Pos) | (64UL << DFSDM_FLTFCR_FOSR_Pos) | (4UL << DFSDM_FLTFCR_FORD_Pos), 0xE3FF00FFU); + register_set(&DFSDM1_Filter0->FLTCR1, DFSDM_FLTCR1_FAST | (3UL << DFSDM_FLTCR1_RCH_Pos) | DFSDM_FLTCR1_RDMAEN | DFSDM_FLTCR1_RCONT | DFSDM_FLTCR1_DFEN, 0x672E7F3BU); + + // DMA (DFSDM1 -> memory) + register_set(&DMA1_Stream0->PAR, (uint32_t) &DFSDM1_Filter0->FLTRDATAR, 0xFFFFFFFFU); + register_set(&DMA1_Stream0->M0AR, (uint32_t)mic_rx_buf[0], 0xFFFFFFFFU); + register_set(&DMA1_Stream0->M1AR, (uint32_t)mic_rx_buf[1], 0xFFFFFFFFU); + DMA1_Stream0->NDTR = MIC_RX_BUF_SIZE; + register_set(&DMA1_Stream0->CR, DMA_SxCR_DBM | (0b10UL << DMA_SxCR_MSIZE_Pos) | (0b10UL << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE, 0x01F7FFFFU); + register_set(&DMAMUX1_Channel0->CCR, 101U, DMAMUX_CxCR_DMAREQ_ID_Msk); // DFSDM1_DMA0 + register_set_bits(&DMA1_Stream0->CR, DMA_SxCR_EN); + DMA1->LIFCR |= 0x7D; // clear flags + + // DMA (memory -> SAI4) + register_set(&BDMA_Channel1->CPAR, (uint32_t) &(SAI4_Block_A->DR), 0xFFFFFFFFU); + register_set(&BDMA_Channel1->CCR, (0b01UL << BDMA_CCR_MSIZE_Pos) | (0b01UL << BDMA_CCR_PSIZE_Pos) | BDMA_CCR_MINC | (0b1U << BDMA_CCR_DIR_Pos), 0xFFFEU); + register_set(&DMAMUX2_Channel1->CCR, 15U, DMAMUX_CxCR_DMAREQ_ID_Msk); // SAI4_A_DMA + + // enable all initted blocks + register_set_bits(&SAI4_Block_A->CR1, SAI_xCR1_SAIEN); + register_set_bits(&SAI4_Block_B->CR1, SAI_xCR1_SAIEN); + NVIC_EnableIRQ(BDMA_Channel0_IRQn); + NVIC_EnableIRQ(DMA1_Stream0_IRQn); +} diff --git a/panda/board/stm32h7/startup_stm32h7x5xx.s b/panda/board/stm32h7/startup_stm32h7x5xx.s new file mode 100644 index 0000000000..15015a1132 --- /dev/null +++ b/panda/board/stm32h7/startup_stm32h7x5xx.s @@ -0,0 +1,767 @@ +/** + ****************************************************************************** + * @file startup_stm32h735xx.s + * @author MCD Application Team + * @brief STM32H735xx Devices vector table for GCC based toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

    © Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

    + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m7 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss +/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ + +/** + * @brief This is the code that gets called when the processor first + * starts execution following a reset event. Only the absolutely + * necessary set is performed, after which the application + * supplied main() routine is called. + * @param None + * @retval : None +*/ + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr sp, =_estack /* set stack pointer */ + bl __initialize_hardware_early + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + /* bl SystemInit */ +/* Call static constructors */ + /* bl __libc_init_array */ +/* Call the application's entry point.*/ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * @param None + * @retval None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +*******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + + .word NMI_Handler + .word HardFault_Handler + .word MemManage_Handler + .word BusFault_Handler + .word UsageFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word DebugMon_Handler + .word 0 + .word PendSV_Handler + .word SysTick_Handler + + /* External Interrupts */ + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_AVD_IRQHandler /* PVD/AVD through EXTI Line detection */ + .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */ + .word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_IRQHandler /* RCC */ + .word EXTI0_IRQHandler /* EXTI Line0 */ + .word EXTI1_IRQHandler /* EXTI Line1 */ + .word EXTI2_IRQHandler /* EXTI Line2 */ + .word EXTI3_IRQHandler /* EXTI Line3 */ + .word EXTI4_IRQHandler /* EXTI Line4 */ + .word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */ + .word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */ + .word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */ + .word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */ + .word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */ + .word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */ + .word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */ + .word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */ + .word FDCAN1_IT0_IRQHandler /* FDCAN1 interrupt line 0 */ + .word FDCAN2_IT0_IRQHandler /* FDCAN2 interrupt line 0 */ + .word FDCAN1_IT1_IRQHandler /* FDCAN1 interrupt line 1 */ + .word FDCAN2_IT1_IRQHandler /* FDCAN2 interrupt line 1 */ + .word EXTI9_5_IRQHandler /* External Line[9:5]s */ + .word TIM1_BRK_IRQHandler /* TIM1 Break interrupt */ + .word TIM1_UP_IRQHandler /* TIM1 Update interrupt */ + .word TIM1_TRG_COM_IRQHandler /* TIM1 Trigger and Commutation interrupt */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM4_IRQHandler /* TIM4 */ + .word I2C1_EV_IRQHandler /* I2C1 Event */ + .word I2C1_ER_IRQHandler /* I2C1 Error */ + .word I2C2_EV_IRQHandler /* I2C2 Event */ + .word I2C2_ER_IRQHandler /* I2C2 Error */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_IRQHandler /* USART3 */ + .word EXTI15_10_IRQHandler /* External Line[15:10]s */ + .word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */ + .word 0 /* Reserved */ + .word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */ + .word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */ + .word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */ + .word TIM8_CC_IRQHandler /* TIM8 Capture Compare */ + .word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */ + .word FMC_IRQHandler /* FMC */ + .word SDMMC1_IRQHandler /* SDMMC1 */ + .word TIM5_IRQHandler /* TIM5 */ + .word SPI3_IRQHandler /* SPI3 */ + .word UART4_IRQHandler /* UART4 */ + .word UART5_IRQHandler /* UART5 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */ + .word TIM7_IRQHandler /* TIM7 */ + .word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */ + .word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */ + .word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */ + .word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */ + .word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */ + .word ETH_IRQHandler /* Ethernet */ + .word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */ + .word FDCAN_CAL_IRQHandler /* FDCAN calibration unit interrupt*/ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */ + .word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */ + .word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */ + .word USART6_IRQHandler /* USART6 */ + .word I2C3_EV_IRQHandler /* I2C3 event */ + .word I2C3_ER_IRQHandler /* I2C3 error */ + .word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */ + .word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */ + .word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */ + .word OTG_HS_IRQHandler /* USB OTG HS */ + .word DCMI_PSSI_IRQHandler /* DCMI, PSSI */ + .word CRYP_IRQHandler /* CRYP */ + .word HASH_RNG_IRQHandler /* Hash and Rng */ + .word FPU_IRQHandler /* FPU */ + .word UART7_IRQHandler /* UART7 */ + .word UART8_IRQHandler /* UART8 */ + .word SPI4_IRQHandler /* SPI4 */ + .word SPI5_IRQHandler /* SPI5 */ + .word SPI6_IRQHandler /* SPI6 */ + .word SAI1_IRQHandler /* SAI1 */ + .word LTDC_IRQHandler /* LTDC */ + .word LTDC_ER_IRQHandler /* LTDC error */ + .word DMA2D_IRQHandler /* DMA2D */ + .word 0 /* Reserved */ + .word OCTOSPI1_IRQHandler /* OCTOSPI1 */ + .word LPTIM1_IRQHandler /* LPTIM1 */ + .word CEC_IRQHandler /* HDMI_CEC */ + .word I2C4_EV_IRQHandler /* I2C4 Event */ + .word I2C4_ER_IRQHandler /* I2C4 Error */ + .word SPDIF_RX_IRQHandler /* SPDIF_RX */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DMAMUX1_OVR_IRQHandler /* DMAMUX1 Overrun interrupt */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word DFSDM1_FLT0_IRQHandler /* DFSDM Filter0 Interrupt */ + .word DFSDM1_FLT1_IRQHandler /* DFSDM Filter1 Interrupt */ + .word DFSDM1_FLT2_IRQHandler /* DFSDM Filter2 Interrupt */ + .word DFSDM1_FLT3_IRQHandler /* DFSDM Filter3 Interrupt */ + .word 0 /* Reserved */ + .word SWPMI1_IRQHandler /* Serial Wire Interface 1 global interrupt */ + .word TIM15_IRQHandler /* TIM15 global Interrupt */ + .word TIM16_IRQHandler /* TIM16 global Interrupt */ + .word TIM17_IRQHandler /* TIM17 global Interrupt */ + .word MDIOS_WKUP_IRQHandler /* MDIOS Wakeup Interrupt */ + .word MDIOS_IRQHandler /* MDIOS global Interrupt */ + .word 0 /* Reserved */ + .word MDMA_IRQHandler /* MDMA global Interrupt */ + .word 0 /* Reserved */ + .word SDMMC2_IRQHandler /* SDMMC2 global Interrupt */ + .word HSEM1_IRQHandler /* HSEM1 global Interrupt */ + .word 0 /* Reserved */ + .word ADC3_IRQHandler /* ADC3 global Interrupt */ + .word DMAMUX2_OVR_IRQHandler /* DMAMUX Overrun interrupt */ + .word BDMA_Channel0_IRQHandler /* BDMA Channel 0 global Interrupt */ + .word BDMA_Channel1_IRQHandler /* BDMA Channel 1 global Interrupt */ + .word BDMA_Channel2_IRQHandler /* BDMA Channel 2 global Interrupt */ + .word BDMA_Channel3_IRQHandler /* BDMA Channel 3 global Interrupt */ + .word BDMA_Channel4_IRQHandler /* BDMA Channel 4 global Interrupt */ + .word BDMA_Channel5_IRQHandler /* BDMA Channel 5 global Interrupt */ + .word BDMA_Channel6_IRQHandler /* BDMA Channel 6 global Interrupt */ + .word BDMA_Channel7_IRQHandler /* BDMA Channel 7 global Interrupt */ + .word COMP1_IRQHandler /* COMP1 global Interrupt */ + .word LPTIM2_IRQHandler /* LP TIM2 global interrupt */ + .word LPTIM3_IRQHandler /* LP TIM3 global interrupt */ + .word LPTIM4_IRQHandler /* LP TIM4 global interrupt */ + .word LPTIM5_IRQHandler /* LP TIM5 global interrupt */ + .word LPUART1_IRQHandler /* LP UART1 interrupt */ + .word 0 /* Reserved */ + .word CRS_IRQHandler /* Clock Recovery Global Interrupt */ + .word ECC_IRQHandler /* ECC diagnostic Global Interrupt */ + .word SAI4_IRQHandler /* SAI4 global interrupt */ + .word DTS_IRQHandler /* Digital Temperature Sensor interrupt */ + .word 0 /* Reserved */ + .word WAKEUP_PIN_IRQHandler /* Interrupt for all 6 wake-up pins */ + .word OCTOSPI2_IRQHandler /* OCTOSPI2 Interrupt */ + .word OTFDEC1_IRQHandler /* OTFDEC1 Interrupt */ + .word OTFDEC2_IRQHandler /* OTFDEC2 Interrupt */ + .word FMAC_IRQHandler /* FMAC Interrupt */ + .word CORDIC_IRQHandler /* CORDIC Interrupt */ + .word UART9_IRQHandler /* UART9 Interrupt */ + .word USART10_IRQHandler /* UART10 Interrupt */ + .word I2C5_EV_IRQHandler /* I2C5 Event Interrupt */ + .word I2C5_ER_IRQHandler /* I2C5 Error Interrupt */ + .word FDCAN3_IT0_IRQHandler /* FDCAN3 interrupt line 0 */ + .word FDCAN3_IT1_IRQHandler /* FDCAN3 interrupt line 1 */ + .word TIM23_IRQHandler /* TIM23 global interrupt */ + .word TIM24_IRQHandler /* TIM24 global interrupt */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_AVD_IRQHandler + .thumb_set PVD_AVD_IRQHandler,Default_Handler + + .weak TAMP_STAMP_IRQHandler + .thumb_set TAMP_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_IRQHandler + .thumb_set RCC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA1_Stream0_IRQHandler + .thumb_set DMA1_Stream0_IRQHandler,Default_Handler + + .weak DMA1_Stream1_IRQHandler + .thumb_set DMA1_Stream1_IRQHandler,Default_Handler + + .weak DMA1_Stream2_IRQHandler + .thumb_set DMA1_Stream2_IRQHandler,Default_Handler + + .weak DMA1_Stream3_IRQHandler + .thumb_set DMA1_Stream3_IRQHandler,Default_Handler + + .weak DMA1_Stream4_IRQHandler + .thumb_set DMA1_Stream4_IRQHandler,Default_Handler + + .weak DMA1_Stream5_IRQHandler + .thumb_set DMA1_Stream5_IRQHandler,Default_Handler + + .weak DMA1_Stream6_IRQHandler + .thumb_set DMA1_Stream6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak FDCAN1_IT0_IRQHandler + .thumb_set FDCAN1_IT0_IRQHandler,Default_Handler + + .weak FDCAN2_IT0_IRQHandler + .thumb_set FDCAN2_IT0_IRQHandler,Default_Handler + + .weak FDCAN1_IT1_IRQHandler + .thumb_set FDCAN1_IT1_IRQHandler,Default_Handler + + .weak FDCAN2_IT1_IRQHandler + .thumb_set FDCAN2_IT1_IRQHandler,Default_Handler + + .weak EXTI9_5_IRQHandler + .thumb_set EXTI9_5_IRQHandler,Default_Handler + + .weak TIM1_BRK_IRQHandler + .thumb_set TIM1_BRK_IRQHandler,Default_Handler + + .weak TIM1_UP_IRQHandler + .thumb_set TIM1_UP_IRQHandler,Default_Handler + + .weak TIM1_TRG_COM_IRQHandler + .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM4_IRQHandler + .thumb_set TIM4_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI15_10_IRQHandler + .thumb_set EXTI15_10_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak TIM8_BRK_TIM12_IRQHandler + .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler + + .weak TIM8_UP_TIM13_IRQHandler + .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler + + .weak TIM8_TRG_COM_TIM14_IRQHandler + .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler + + .weak TIM8_CC_IRQHandler + .thumb_set TIM8_CC_IRQHandler,Default_Handler + + .weak DMA1_Stream7_IRQHandler + .thumb_set DMA1_Stream7_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak SDMMC1_IRQHandler + .thumb_set SDMMC1_IRQHandler,Default_Handler + + .weak TIM5_IRQHandler + .thumb_set TIM5_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak UART5_IRQHandler + .thumb_set UART5_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak DMA2_Stream0_IRQHandler + .thumb_set DMA2_Stream0_IRQHandler,Default_Handler + + .weak DMA2_Stream1_IRQHandler + .thumb_set DMA2_Stream1_IRQHandler,Default_Handler + + .weak DMA2_Stream2_IRQHandler + .thumb_set DMA2_Stream2_IRQHandler,Default_Handler + + .weak DMA2_Stream3_IRQHandler + .thumb_set DMA2_Stream3_IRQHandler,Default_Handler + + .weak DMA2_Stream4_IRQHandler + .thumb_set DMA2_Stream4_IRQHandler,Default_Handler + + .weak ETH_IRQHandler + .thumb_set ETH_IRQHandler,Default_Handler + + .weak ETH_WKUP_IRQHandler + .thumb_set ETH_WKUP_IRQHandler,Default_Handler + + .weak FDCAN_CAL_IRQHandler + .thumb_set FDCAN_CAL_IRQHandler,Default_Handler + + .weak DMA2_Stream5_IRQHandler + .thumb_set DMA2_Stream5_IRQHandler,Default_Handler + + .weak DMA2_Stream6_IRQHandler + .thumb_set DMA2_Stream6_IRQHandler,Default_Handler + + .weak DMA2_Stream7_IRQHandler + .thumb_set DMA2_Stream7_IRQHandler,Default_Handler + + .weak USART6_IRQHandler + .thumb_set USART6_IRQHandler,Default_Handler + + .weak I2C3_EV_IRQHandler + .thumb_set I2C3_EV_IRQHandler,Default_Handler + + .weak I2C3_ER_IRQHandler + .thumb_set I2C3_ER_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_OUT_IRQHandler + .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler + + .weak OTG_HS_EP1_IN_IRQHandler + .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler + + .weak OTG_HS_WKUP_IRQHandler + .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler + + .weak OTG_HS_IRQHandler + .thumb_set OTG_HS_IRQHandler,Default_Handler + + .weak DCMI_PSSI_IRQHandler + .thumb_set DCMI_PSSI_IRQHandler,Default_Handler + + .weak CRYP_IRQHandler + .thumb_set CRYP_IRQHandler,Default_Handler + + .weak HASH_RNG_IRQHandler + .thumb_set HASH_RNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak UART8_IRQHandler + .thumb_set UART8_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak SPI6_IRQHandler + .thumb_set SPI6_IRQHandler,Default_Handler + + .weak SAI1_IRQHandler + .thumb_set SAI1_IRQHandler,Default_Handler + + .weak LTDC_IRQHandler + .thumb_set LTDC_IRQHandler,Default_Handler + + .weak LTDC_ER_IRQHandler + .thumb_set LTDC_ER_IRQHandler,Default_Handler + + .weak DMA2D_IRQHandler + .thumb_set DMA2D_IRQHandler,Default_Handler + + .weak OCTOSPI1_IRQHandler + .thumb_set OCTOSPI1_IRQHandler,Default_Handler + + .weak LPTIM1_IRQHandler + .thumb_set LPTIM1_IRQHandler,Default_Handler + + .weak CEC_IRQHandler + .thumb_set CEC_IRQHandler,Default_Handler + + .weak I2C4_EV_IRQHandler + .thumb_set I2C4_EV_IRQHandler,Default_Handler + + .weak I2C4_ER_IRQHandler + .thumb_set I2C4_ER_IRQHandler,Default_Handler + + .weak SPDIF_RX_IRQHandler + .thumb_set SPDIF_RX_IRQHandler,Default_Handler + + .weak DMAMUX1_OVR_IRQHandler + .thumb_set DMAMUX1_OVR_IRQHandler,Default_Handler + + .weak DFSDM1_FLT0_IRQHandler + .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler + + .weak DFSDM1_FLT1_IRQHandler + .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler + + .weak DFSDM1_FLT2_IRQHandler + .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler + + .weak DFSDM1_FLT3_IRQHandler + .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler + + .weak SWPMI1_IRQHandler + .thumb_set SWPMI1_IRQHandler,Default_Handler + + .weak TIM15_IRQHandler + .thumb_set TIM15_IRQHandler,Default_Handler + + .weak TIM16_IRQHandler + .thumb_set TIM16_IRQHandler,Default_Handler + + .weak TIM17_IRQHandler + .thumb_set TIM17_IRQHandler,Default_Handler + + .weak MDIOS_WKUP_IRQHandler + .thumb_set MDIOS_WKUP_IRQHandler,Default_Handler + + .weak MDIOS_IRQHandler + .thumb_set MDIOS_IRQHandler,Default_Handler + + .weak MDMA_IRQHandler + .thumb_set MDMA_IRQHandler,Default_Handler + + .weak SDMMC2_IRQHandler + .thumb_set SDMMC2_IRQHandler,Default_Handler + + .weak HSEM1_IRQHandler + .thumb_set HSEM1_IRQHandler,Default_Handler + + .weak ADC3_IRQHandler + .thumb_set ADC3_IRQHandler,Default_Handler + + .weak DMAMUX2_OVR_IRQHandler + .thumb_set DMAMUX2_OVR_IRQHandler,Default_Handler + + .weak BDMA_Channel0_IRQHandler + .thumb_set BDMA_Channel0_IRQHandler,Default_Handler + + .weak BDMA_Channel1_IRQHandler + .thumb_set BDMA_Channel1_IRQHandler,Default_Handler + + .weak BDMA_Channel2_IRQHandler + .thumb_set BDMA_Channel2_IRQHandler,Default_Handler + + .weak BDMA_Channel3_IRQHandler + .thumb_set BDMA_Channel3_IRQHandler,Default_Handler + + .weak BDMA_Channel4_IRQHandler + .thumb_set BDMA_Channel4_IRQHandler,Default_Handler + + .weak BDMA_Channel5_IRQHandler + .thumb_set BDMA_Channel5_IRQHandler,Default_Handler + + .weak BDMA_Channel6_IRQHandler + .thumb_set BDMA_Channel6_IRQHandler,Default_Handler + + .weak BDMA_Channel7_IRQHandler + .thumb_set BDMA_Channel7_IRQHandler,Default_Handler + + .weak COMP1_IRQHandler + .thumb_set COMP1_IRQHandler,Default_Handler + + .weak LPTIM2_IRQHandler + .thumb_set LPTIM2_IRQHandler,Default_Handler + + .weak LPTIM3_IRQHandler + .thumb_set LPTIM3_IRQHandler,Default_Handler + + .weak LPTIM4_IRQHandler + .thumb_set LPTIM4_IRQHandler,Default_Handler + + .weak LPTIM5_IRQHandler + .thumb_set LPTIM5_IRQHandler,Default_Handler + + .weak LPUART1_IRQHandler + .thumb_set LPUART1_IRQHandler,Default_Handler + + .weak CRS_IRQHandler + .thumb_set CRS_IRQHandler,Default_Handler + + .weak ECC_IRQHandler + .thumb_set ECC_IRQHandler,Default_Handler + + .weak SAI4_IRQHandler + .thumb_set SAI4_IRQHandler,Default_Handler + + .weak DTS_IRQHandler + .thumb_set DTS_IRQHandler,Default_Handler + + .weak WAKEUP_PIN_IRQHandler + .thumb_set WAKEUP_PIN_IRQHandler,Default_Handler + + .weak OCTOSPI2_IRQHandler + .thumb_set OCTOSPI2_IRQHandler,Default_Handler + + .weak OTFDEC1_IRQHandler + .thumb_set OTFDEC1_IRQHandler,Default_Handler + + .weak OTFDEC2_IRQHandler + .thumb_set OTFDEC2_IRQHandler,Default_Handler + + .weak FMAC_IRQHandler + .thumb_set FMAC_IRQHandler,Default_Handler + + .weak CORDIC_IRQHandler + .thumb_set CORDIC_IRQHandler,Default_Handler + + .weak UART9_IRQHandler + .thumb_set UART9_IRQHandler,Default_Handler + + .weak USART10_IRQHandler + .thumb_set USART10_IRQHandler,Default_Handler + + .weak I2C5_EV_IRQHandler + .thumb_set I2C5_EV_IRQHandler,Default_Handler + + .weak I2C5_ER_IRQHandler + .thumb_set I2C5_ER_IRQHandler,Default_Handler + + .weak FDCAN3_IT0_IRQHandler + .thumb_set FDCAN3_IT0_IRQHandler,Default_Handler + + .weak FDCAN3_IT1_IRQHandler + .thumb_set FDCAN3_IT1_IRQHandler,Default_Handler + + .weak TIM23_IRQHandler + .thumb_set TIM23_IRQHandler,Default_Handler + + .weak TIM24_IRQHandler + .thumb_set TIM24_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/panda/board/stm32h7/stm32h7_config.h b/panda/board/stm32h7/stm32h7_config.h new file mode 100644 index 0000000000..5e7dcb0c75 --- /dev/null +++ b/panda/board/stm32h7/stm32h7_config.h @@ -0,0 +1,95 @@ +#include "stm32h7xx.h" +#include "stm32h7xx_hal_gpio_ex.h" +#define MCU_IDCODE 0x483U + +#define CORE_FREQ 240U // in Mhz +//APB1 - 120Mhz, APB2 - 120Mhz +#define APB1_FREQ (CORE_FREQ/4U) +#define APB1_TIMER_FREQ (APB1_FREQ*2U) // APB1 is multiplied by 2 for the timer peripherals +#define APB2_FREQ (CORE_FREQ/4U) +#define APB2_TIMER_FREQ (APB2_FREQ*2U) // APB2 is multiplied by 2 for the timer peripherals + +#define BOOTLOADER_ADDRESS 0x1FF09804U + +/* +An IRQ is received on message RX/TX (or RX errors), with +separate IRQs for RX and TX. + +0-byte CAN FD frame as the worst case: +- 17 slow bits = SOF + 11 ID + R1 + IDE + EDL + R0 + BRS +- 23 fast bits = ESI + 4 DLC + 0 DATA + 17 CRC + CRC delimeter +- 12 slow bits = ACK + DEL + 7 EOF + 3 IFS +- all currently supported cars are 0.5 Mbps / 2 Mbps + +1 / ((29 bits / 0.5Mbps) + (23 bits / 2Mbps)) = 14388Hz +*/ +#define CAN_INTERRUPT_RATE 16000U + +#define MAX_LED_FADE 10240U + +// There are 163 external interrupt sources (see stm32f735xx.h) +#define NUM_INTERRUPTS 163U + +#define TICK_TIMER_IRQ TIM8_BRK_TIM12_IRQn +#define TICK_TIMER TIM12 + +#define MICROSECOND_TIMER TIM2 + +#define INTERRUPT_TIMER_IRQ TIM6_DAC_IRQn +#define INTERRUPT_TIMER TIM6 + +#define IND_WDG IWDG1 + +#define PROVISION_CHUNK_ADDRESS 0x080FFFE0U +#define DEVICE_SERIAL_NUMBER_ADDRESS 0x080FFFC0U + +#include "board/can.h" +#include "board/comms_definitions.h" + +#ifndef BOOTSTUB + #include "board/main_definitions.h" +#else + #include "board/bootstub_declarations.h" +#endif + +#include "board/libc.h" +#include "board/critical.h" +#include "board/faults.h" +#include "board/utils.h" + +#include "board/drivers/registers.h" +#include "board/drivers/interrupts.h" +#include "board/drivers/gpio.h" +#include "board/stm32h7/peripherals.h" +#include "board/stm32h7/interrupt_handlers.h" +#include "board/drivers/timers.h" + +#if !defined(BOOTSTUB) + #include "board/drivers/uart.h" + #include "board/stm32h7/lluart.h" +#endif + +#ifdef PANDA_JUNGLE +#include "board/jungle/stm32h7/board.h" +#else +#include "board/stm32h7/board.h" +#endif +#include "board/stm32h7/clock.h" + +#ifdef BOOTSTUB + #include "board/stm32h7/llflash.h" +#else + #include "board/stm32h7/llfdcan.h" +#endif + +#include "board/stm32h7/llusb.h" + +#include "board/drivers/spi.h" +#include "board/stm32h7/llspi.h" + +void early_gpio_float(void) { + RCC->AHB4ENR = RCC_AHB4ENR_GPIOAEN | RCC_AHB4ENR_GPIOBEN | RCC_AHB4ENR_GPIOCEN | RCC_AHB4ENR_GPIODEN | RCC_AHB4ENR_GPIOEEN | RCC_AHB4ENR_GPIOFEN | RCC_AHB4ENR_GPIOGEN | RCC_AHB4ENR_GPIOHEN; + GPIOA->MODER = 0xAB000000U; GPIOB->MODER = 0; GPIOC->MODER = 0; GPIOD->MODER = 0; GPIOE->MODER = 0; GPIOF->MODER = 0; GPIOG->MODER = 0; GPIOH->MODER = 0; + GPIOA->ODR = 0; GPIOB->ODR = 0; GPIOC->ODR = 0; GPIOD->ODR = 0; GPIOE->ODR = 0; GPIOF->ODR = 0; GPIOG->ODR = 0; GPIOH->ODR = 0; + GPIOA->PUPDR = 0; GPIOB->PUPDR = 0; GPIOC->PUPDR = 0; GPIOD->PUPDR = 0; GPIOE->PUPDR = 0; GPIOF->PUPDR = 0; GPIOG->PUPDR = 0; GPIOH->PUPDR = 0; +} diff --git a/panda/board/stm32h7/stm32h7x5_flash.ld b/panda/board/stm32h7/stm32h7x5_flash.ld new file mode 100644 index 0000000000..3b6eee5dd0 --- /dev/null +++ b/panda/board/stm32h7/stm32h7x5_flash.ld @@ -0,0 +1,221 @@ +/* +****************************************************************************** +** + +** File : LinkerScript.ld +** +** Author : Auto-generated by System Workbench for STM32 +** +** Abstract : Linker script for STM32H735ZGTx series +** 1024Kbytes FLASH and 560Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed “as is,” without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +**

    © COPYRIGHT(c) 2019 STMicroelectronics

    +** +** Redistribution and use in source and binary forms, with or without modification, +** are permitted provided that the following conditions are met: +** 1. Redistributions of source code must retain the above copyright notice, +** this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright notice, +** this list of conditions and the following disclaimer in the documentation +** and/or other materials provided with the distribution. +** 3. Neither the name of STMicroelectronics nor the names of its contributors +** may be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +enter_bootloader_mode = 0x38001FFC; +_estack = 0x20020000; /* end of RAM */ +_app_start = 0x08020000; /* Reserve Sector 0(128K) for bootloader */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +/* RAM */ +BACKUP_SRAM (xrw) : ORIGIN = 0x38800000, LENGTH = 4K /* Backup SRAM(4kb) */ +SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 16K /* SRAM4(16kb) best for BDMA and SDMMC1*/ +SRAM12 (xrw) : ORIGIN = 0x30000000, LENGTH = 32K /* SRAM1(16kb) + SRAM2(16kb), not for BDMA or SDMMC1 */ +AXISRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 320K /* AXI SRAM */ +DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* DTCM */ + +/* Code */ +SYSTEM (rx) : ORIGIN = 0x1FF00000, LENGTH = 128K /* System memory */ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >DTCMRAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >DTCMRAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >DTCMRAM + + .itcmram (NOLOAD) : + { + . = ALIGN(4); + *(.itcmram*) + } >ITCMRAM + + .axisram (NOLOAD) : + { + . = ALIGN(4); + *(.axisram*) + } >AXISRAM + + .sram12 (NOLOAD) : + { + . = ALIGN(4); + *(.sram12*) + } >SRAM12 + + .sram4 (NOLOAD) : + { + . = ALIGN(4); + *(.sram4*) + } >SRAM4 + + .backup_sram (NOLOAD) : + { + . = ALIGN(4); + *(.backup_sram*) + } >BACKUP_SRAM + + .ARM.attributes 0 : { *(.ARM.attributes) } +} + + diff --git a/panda/board/utils.h b/panda/board/utils.h new file mode 100644 index 0000000000..f355ce8c2f --- /dev/null +++ b/panda/board/utils.h @@ -0,0 +1,47 @@ +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define MIN(a, b) ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + (_a < _b) ? _a : _b; \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define MAX(a, b) ({ \ + __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + (_a > _b) ? _a : _b; \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define CLAMP(x, low, high) ({ \ + __typeof__(x) __x = (x); \ + __typeof__(low) __low = (low);\ + __typeof__(high) __high = (high);\ + (__x > __high) ? __high : ((__x < __low) ? __low : __x); \ +}) + +// cppcheck-suppress-macro misra-c2012-1.2; allow __typeof__ extension +#define ABS(a) ({ \ + __typeof__ (a) _a = (a); \ + (_a > 0) ? _a : (-_a); \ +}) + +#ifndef NULL +// this just provides a standard implementation of NULL +// in lieu of including libc in the panda build +// cppcheck-suppress [misra-c2012-21.1] +#define NULL ((void*)0) +#endif + +// STM32 HAL defines this +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) +#endif + +#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * (!(pred) ? 1 : 0))])) + +// compute the time elapsed (in microseconds) from 2 counter samples +// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t +uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) { + return ts - ts_last; +} diff --git a/panda/certs/debug b/panda/certs/debug new file mode 100644 index 0000000000..39864b6b1a --- /dev/null +++ b/panda/certs/debug @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQC948lnRo4x44Rd7Y8bQAML4aKDC4XRx958fHV8K6+FbCaP1Z42 +U2kX0yygak0LjoDutpgObmGHZA+Iz3HeUD6VGjr/teN24vPk+A95cRsjt8rgmGQ9 +6HNjaNgjR+gl1F9XxFimMzir82Xpl1ekTueJNXa7ia5HVH1nFdiksOKHGQIDAQAB +AoGAQuPw2I6EHJLW1/eNB75e1FqhUqRGeYV8nEGDaUBCTi+wzc4kM2LijF/5QnDv +vvht9qkfm0XK2VSoHDtnEzcVM/l1ksb68n4R/1nUooAWY6cQI7dCSk/A6yS1EJFg +BXsgGbT/65khw9pzBW2zVtMVcVNWFayqfCO1I9WcDdA1x1kCQQDfrhoZTZNoDEUE +JKM4fiUdWr1h3Aw8KLJFFexSWeGDwo+qqnujYcKWkHa9qaH1RG5x8Kir9s9Oi4Js +mzKwov8fAkEA2VPJPWxJ4vVQpXle6wC1nyoL7s739yxMWFcabvkzDDhlIVBNdVJd +gZKsFWV7QnVNdDMjn9D27FwKu3i2D+kKxwJBANp1SMojqO765MEKI1t+YDNONx6H +cm+i85Fjuv4nCIjOEdCGVuCYDxtMFpxgO2y3HAMuHx5sm8XDnWsDHLvFRdMCQD7V +XqWHnYUk8AAnqy2+ssQl3/VXmZG5GQmhhV74Za3u0C5ljT+SZL6FrYMyKAT67T3f +WzllrT6BDglNyTWoZxkCQQCt0XSoGM3603GGYNt6AUlGSgtXSo/2Px7odGUtQoKA +FH9q6FVMYpQJ38spZxIGufZJmLP8LLg6YIWJj1F+akxr +-----END RSA PRIVATE KEY----- diff --git a/panda/certs/debug.pub b/panda/certs/debug.pub new file mode 100644 index 0000000000..00e219d7bb --- /dev/null +++ b/panda/certs/debug.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC948lnRo4x44Rd7Y8bQAML4aKDC4XRx958fHV8K6+FbCaP1Z42U2kX0yygak0LjoDutpgObmGHZA+Iz3HeUD6VGjr/teN24vPk+A95cRsjt8rgmGQ96HNjaNgjR+gl1F9XxFimMzir82Xpl1ekTueJNXa7ia5HVH1nFdiksOKHGQ== batman@y840 diff --git a/panda/certs/release.pub b/panda/certs/release.pub new file mode 100644 index 0000000000..19066e29a7 --- /dev/null +++ b/panda/certs/release.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDGN9GU2nOc0kKq6vdZI5qUMzHt234ngqofrgCFFxL0D2Whex0zACp9gar0HZp+bvtpoSgU/Ev8wexNKr+A9QTradljiuxi5ctrOra9k+wxqNj63Wrcu4+wU5UnJEVf/buV4jCOFffMT8z3PO4imt8LzHuEIC/m/ASKVYyvuvBRQQ== batman@y840 diff --git a/panda/crypto/hash-internal.h b/panda/crypto/hash-internal.h new file mode 100644 index 0000000000..05ec3ec9fd --- /dev/null +++ b/panda/crypto/hash-internal.h @@ -0,0 +1,63 @@ +/* + * Copyright 2007 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ +#define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ + +#include "stdint.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct HASH_CTX; // forward decl + +typedef struct HASH_VTAB { + void (* const init)(struct HASH_CTX*); + void (* const update)(struct HASH_CTX*, const void*, int); + const uint8_t* (* const final)(struct HASH_CTX*); + const uint8_t* (* const hash)(const void*, int, uint8_t*); + int size; +} HASH_VTAB; + +typedef struct HASH_CTX { + const HASH_VTAB * f; + uint64_t count; + uint8_t buf[64]; + uint32_t state[8]; // upto SHA2 +} HASH_CTX; + +#define HASH_init(ctx) (ctx)->f->init(ctx) +#define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) +#define HASH_final(ctx) (ctx)->f->final(ctx) +#define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest) +#define HASH_size(ctx) (ctx)->f->size + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ diff --git a/panda/crypto/rsa.c b/panda/crypto/rsa.c new file mode 100644 index 0000000000..24171e8790 --- /dev/null +++ b/panda/crypto/rsa.c @@ -0,0 +1,294 @@ +/* rsa.c +** +** Copyright 2012, The Android Open Source Project +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of Google Inc. nor the names of its contributors may +** be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "rsa.h" +#include "sha.h" + +// a[] -= mod +static void subM(const RSAPublicKey* key, + uint32_t* a) { + int64_t A = 0; + int i; + for (i = 0; i < key->len; ++i) { + A += (uint64_t)a[i] - key->n[i]; + a[i] = (uint32_t)A; + A >>= 32; + } +} + +// return a[] >= mod +static int geM(const RSAPublicKey* key, + const uint32_t* a) { + int i; + for (i = key->len; i;) { + --i; + if (a[i] < key->n[i]) return 0; + if (a[i] > key->n[i]) return 1; + } + return 1; // equal +} + +// montgomery c[] += a * b[] / R % mod +static void montMulAdd(const RSAPublicKey* key, + uint32_t* c, + const uint32_t a, + const uint32_t* b) { + uint64_t A = (uint64_t)a * b[0] + c[0]; + uint32_t d0 = (uint32_t)A * key->n0inv; + uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A; + int i; + + for (i = 1; i < key->len; ++i) { + A = (A >> 32) + (uint64_t)a * b[i] + c[i]; + B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A; + c[i - 1] = (uint32_t)B; + } + + A = (A >> 32) + (B >> 32); + + c[i - 1] = (uint32_t)A; + + if (A >> 32) { + subM(key, c); + } +} + +// montgomery c[] = a[] * b[] / R % mod +static void montMul(const RSAPublicKey* key, + uint32_t* c, + const uint32_t* a, + const uint32_t* b) { + int i; + for (i = 0; i < key->len; ++i) { + c[i] = 0; + } + for (i = 0; i < key->len; ++i) { + montMulAdd(key, c, a[i], b); + } +} + +// In-place public exponentiation. +// Input and output big-endian byte array in inout. +static void modpow(const RSAPublicKey* key, + uint8_t* inout) { + uint32_t a[RSANUMWORDS]; + uint32_t aR[RSANUMWORDS]; + uint32_t aaR[RSANUMWORDS]; + uint32_t* aaa = 0; + int i; + + // Convert from big endian byte array to little endian word array. + for (i = 0; i < key->len; ++i) { + uint32_t tmp = + (inout[((key->len - 1 - i) * 4) + 0] << 24) | + (inout[((key->len - 1 - i) * 4) + 1] << 16) | + (inout[((key->len - 1 - i) * 4) + 2] << 8) | + (inout[((key->len - 1 - i) * 4) + 3] << 0); + a[i] = tmp; + } + + if (key->exponent == 65537) { + aaa = aaR; // Re-use location. + montMul(key, aR, a, key->rr); // aR = a * RR / R mod M + for (i = 0; i < 16; i += 2) { + montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M + montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M + } + montMul(key, aaa, aR, a); // aaa = aR * a / R mod M + } else if (key->exponent == 3) { + aaa = aR; // Re-use location. + montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */ + montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ + montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */ + } + + // Make sure aaa < mod; aaa is at most 1x mod too large. + if (geM(key, aaa)) { + subM(key, aaa); + } + + // Convert to bigendian byte array + for (i = key->len - 1; i >= 0; --i) { + uint32_t tmp = aaa[i]; + *inout++ = tmp >> 24; + *inout++ = tmp >> 16; + *inout++ = tmp >> 8; + *inout++ = tmp >> 0; + } +} + +// Expected PKCS1.5 signature padding bytes, for a keytool RSA signature. +// Has the 0-length optional parameter encoded in the ASN1 (as opposed to the +// other flavor which omits the optional parameter entirely). This code does not +// accept signatures without the optional parameter. + +/* +static const uint8_t sha_padding[RSANUMBYTES] = { + 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30, + 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, + 0x05, 0x00, 0x04, 0x14, + + // 20 bytes of hash go here. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; +*/ + +static const uint8_t sha_padding_1024[RSANUMBYTES] = { + 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, + + // 20 bytes of hash go here. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + +// SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above. +// At the location of the bytes of the hash all 00 are hashed. +/*static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = { + 0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e, + 0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68, + 0x7c, 0xfb, 0xf1, 0x67 +};*/ + +// Verify a 2048-bit RSA PKCS1.5 signature against an expected hash. +// Both e=3 and e=65537 are supported. hash_len may be +// SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or +// SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other +// values are supported. +// +// Returns 1 on successful verification, 0 on failure. +int RSA_verify(const RSAPublicKey *key, + const uint8_t *signature, + const int len, + const uint8_t *hash, + const int hash_len) { + uint8_t buf[RSANUMBYTES]; + int i; + //const uint8_t* padding_hash; + + if (key->len != RSANUMWORDS) { + return 0; // Wrong key passed in. + } + + if (len != sizeof(buf)) { + return 0; // Wrong input length. + } + + if (hash_len != SHA_DIGEST_SIZE) { + return 0; // Unsupported hash. + } + + if (key->exponent != 3 && key->exponent != 65537) { + return 0; // Unsupported exponent. + } + + for (i = 0; i < len; ++i) { // Copy input to local workspace. + buf[i] = signature[i]; + } + + modpow(key, buf); // In-place exponentiation. + +#ifdef TEST_RSA + printf("sig\n"); + for (i=0;i + +#ifdef __cplusplus +extern "C" { +#endif + +#define RSANUMBYTES 128 /* 1024 bit key length */ +#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t)) + +typedef struct RSAPublicKey { + int len; /* Length of n[] in number of uint32_t */ + uint32_t n0inv; /* -1 / n[0] mod 2^32 */ + uint32_t n[RSANUMWORDS]; /* modulus as little endian array */ + uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */ + int exponent; /* 3 or 65537 */ +} RSAPublicKey; + +int RSA_verify(const RSAPublicKey *key, + const uint8_t* signature, + const int len, + const uint8_t* hash, + const int hash_len); + +#ifdef __cplusplus +} +#endif + +#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ diff --git a/panda/crypto/sha.c b/panda/crypto/sha.c new file mode 100644 index 0000000000..a13162c5fa --- /dev/null +++ b/panda/crypto/sha.c @@ -0,0 +1,179 @@ +/* sha.c +** +** Copyright 2013, The Android Open Source Project +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of Google Inc. nor the names of its contributors may +** be used to endorse or promote products derived from this software +** without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +// Optimized for minimal code size. + +void *memcpy(void *str1, const void *str2, unsigned int n); + +#include "sha.h" + +#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +static void SHA1_Transform(SHA_CTX* ctx) { + uint32_t W[80]; + uint32_t A, B, C, D, E; + uint8_t* p = ctx->buf; + int t; + + for(t = 0; t < 16; ++t) { + uint32_t tmp = *p++ << 24; + tmp |= *p++ << 16; + tmp |= *p++ << 8; + tmp |= *p++; + W[t] = tmp; + } + + for(; t < 80; t++) { + W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + + for(t = 0; t < 80; t++) { + uint32_t tmp = rol(5,A) + E + W[t]; + + if (t < 20) + tmp += (D^(B&(C^D))) + 0x5A827999; + else if ( t < 40) + tmp += (B^C^D) + 0x6ED9EBA1; + else if ( t < 60) + tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC; + else + tmp += (B^C^D) + 0xCA62C1D6; + + E = D; + D = C; + C = rol(30,B); + B = A; + A = tmp; + } + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +static const HASH_VTAB SHA_VTAB = { + SHA_init, + SHA_update, + SHA_final, + SHA_hash, + SHA_DIGEST_SIZE +}; + +void SHA_init(SHA_CTX* ctx) { + ctx->f = &SHA_VTAB; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->count = 0; +} + + +void SHA_update(SHA_CTX* ctx, const void* data, int len) { + int i = (int) (ctx->count & 63); + const uint8_t* p = (const uint8_t*)data; + + ctx->count += len; + + while (len--) { + ctx->buf[i++] = *p++; + if (i == 64) { + SHA1_Transform(ctx); + i = 0; + } + } +} + + +const uint8_t* SHA_final(SHA_CTX* ctx) { + uint8_t *p = ctx->buf; + uint64_t cnt = ctx->count * 8; + int i; + + SHA_update(ctx, (uint8_t*)"\x80", 1); + while ((ctx->count & 63) != 56) { + SHA_update(ctx, (uint8_t*)"\0", 1); + } + + /* Hack - right shift operator with non const argument requires + * libgcc.a which is missing in EON + * thus expanding for loop from + + for (i = 0; i < 8; ++i) { + uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8)); + SHA_update(ctx, &tmp, 1); + } + + to + */ + + uint8_t tmp = 0; + tmp = (uint8_t) (cnt >> ((7 - 0) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 1) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 2) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 3) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 4) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 5) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 6) * 8)); + SHA_update(ctx, &tmp, 1); + tmp = (uint8_t) (cnt >> ((7 - 7) * 8)); + SHA_update(ctx, &tmp, 1); + + for (i = 0; i < 5; i++) { + uint32_t tmp = ctx->state[i]; + *p++ = tmp >> 24; + *p++ = tmp >> 16; + *p++ = tmp >> 8; + *p++ = tmp >> 0; + } + + return ctx->buf; +} + +/* Convenience function */ +const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) { + SHA_CTX ctx; + SHA_init(&ctx); + SHA_update(&ctx, data, len); + memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); + return digest; +} diff --git a/panda/crypto/sha.h b/panda/crypto/sha.h new file mode 100644 index 0000000000..4b51a531bf --- /dev/null +++ b/panda/crypto/sha.h @@ -0,0 +1,51 @@ +/* + * Copyright 2005 The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ +#define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ + +#include "hash-internal.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef HASH_CTX SHA_CTX; + +void SHA_init(SHA_CTX* ctx); +void SHA_update(SHA_CTX* ctx, const void* data, int len); +const uint8_t* SHA_final(SHA_CTX* ctx); + +// Convenience method. Returns digest address. +// NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes. +const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest); + +#define SHA_DIGEST_SIZE 20 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ diff --git a/panda/crypto/sign.py b/panda/crypto/sign.py new file mode 100755 index 0000000000..daea38630c --- /dev/null +++ b/panda/crypto/sign.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import os +import sys +import struct +import hashlib +from Crypto.PublicKey import RSA +import binascii + +# increment this to make new hardware not run old versions +VERSION = 2 + +if __name__ == "__main__": + with open(sys.argv[3]) as k: + rsa = RSA.importKey(k.read()) + + with open(sys.argv[1], "rb") as f: + dat = f.read() + + print("signing", len(dat), "bytes") + + with open(sys.argv[2], "wb") as f: + if os.getenv("SETLEN") is not None: + # add the version at the end + dat += b"VERS" + struct.pack("I", VERSION) + # add the length at the beginning + x = struct.pack("I", len(dat)) + dat[4:] + # mock signature of dat[4:] + dd = hashlib.sha1(dat[4:]).digest() + else: + x = dat + dd = hashlib.sha1(dat).digest() + + print("hash:", str(binascii.hexlify(dd), "utf-8")) + dd = b"\x00\x01" + b"\xff" * 0x69 + b"\x00" + dd + rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa.d, rsa.n) + sig = (hex(rsa_out)[2:].rjust(0x100, '0')) + x += binascii.unhexlify(sig) + f.write(x) diff --git a/panda/docs/CANPacket_structure.png b/panda/docs/CANPacket_structure.png new file mode 100644 index 0000000000..7dd1343161 Binary files /dev/null and b/panda/docs/CANPacket_structure.png differ diff --git a/panda/docs/USB_packet_structure.png b/panda/docs/USB_packet_structure.png new file mode 100644 index 0000000000..30e848c3f6 Binary files /dev/null and b/panda/docs/USB_packet_structure.png differ diff --git a/panda/drivers/spi/.gitignore b/panda/drivers/spi/.gitignore new file mode 100644 index 0000000000..49dc09d89f --- /dev/null +++ b/panda/drivers/spi/.gitignore @@ -0,0 +1,7 @@ +spidev.c +*.ko +*.cmd +*.mod +*.symvers +*.order +*.mod.c diff --git a/panda/drivers/spi/Makefile b/panda/drivers/spi/Makefile new file mode 100644 index 0000000000..9a2a0abf67 --- /dev/null +++ b/panda/drivers/spi/Makefile @@ -0,0 +1,14 @@ +obj-m += spidev_panda.o + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +# GCC9 bug, apply kernel patch instead? +# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0b999ae3614d09d97a1575936bcee884f912b10e +ccflags-y := -Wno-missing-attributes + +default: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean diff --git a/panda/drivers/spi/load.sh b/panda/drivers/spi/load.sh new file mode 100755 index 0000000000..910ac87282 --- /dev/null +++ b/panda/drivers/spi/load.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +make -j8 + +sudo su -c "echo spi0.0 > /sys/bus/spi/drivers/spidev/unbind" || true + +sudo dmesg -C + +#sudo rmmod -f spidev_panda +sudo rmmod spidev_panda || true +sudo insmod spidev_panda.ko + +sudo su -c "echo 'file $DIR/spidev_panda.c +p' > /sys/kernel/debug/dynamic_debug/control" +sudo su -c "echo 'file $DIR/spi_panda.h +p' > /sys/kernel/debug/dynamic_debug/control" + +sudo lsmod + +echo "loaded" +ls -la /dev/spi* +sudo chmod 666 /dev/spi* +ipython -c "from panda import Panda; print(Panda.list())" +KERN=1 ipython -c "from panda import Panda; print(Panda.list())" +dmesg diff --git a/panda/drivers/spi/patch b/panda/drivers/spi/patch new file mode 100644 index 0000000000..a146303424 --- /dev/null +++ b/panda/drivers/spi/patch @@ -0,0 +1,33 @@ +53c53,54 +< #define SPIDEV_MAJOR 153 /* assigned */ +--- +> int SPIDEV_MAJOR = 0; +> //#define SPIDEV_MAJOR 153 /* assigned */ +354a356,358 +> +> #include "spi_panda.h" +> +413,414c417,419 +< retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, +< (__u8 __user *)arg); +--- +> retval = panda_transfer(spidev, spi, arg); +> //retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, +> // (__u8 __user *)arg); +697,698d701 +< { .compatible = "rohm,dh2228fv" }, +< { .compatible = "lineartechnology,ltc2488" }, +831c834 +< .name = "spidev", +--- +> .name = "spidev_panda", +856c859 +< status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); +--- +> status = register_chrdev(0, "spi", &spidev_fops); +860c863,865 +< spidev_class = class_create(THIS_MODULE, "spidev"); +--- +> SPIDEV_MAJOR = status; +> +> spidev_class = class_create(THIS_MODULE, "spidev_panda"); diff --git a/panda/drivers/spi/pull-src.sh b/panda/drivers/spi/pull-src.sh new file mode 100755 index 0000000000..64dac9bca0 --- /dev/null +++ b/panda/drivers/spi/pull-src.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +rm -f spidev.c +wget https://raw.githubusercontent.com/commaai/agnos-kernel-sdm845/master/drivers/spi/spidev.c + +# diff spidev.c spidev_panda.c > patch +# git diff --no-index spidev.c spidev_panda.c +patch -o spidev_panda.c spidev.c -i patch diff --git a/panda/drivers/spi/spi_panda.h b/panda/drivers/spi/spi_panda.h new file mode 100644 index 0000000000..c7da681fc2 --- /dev/null +++ b/panda/drivers/spi/spi_panda.h @@ -0,0 +1,160 @@ +#include +#include +#include + +#define SPI_SYNC 0x5AU +#define SPI_HACK 0x79U +#define SPI_DACK 0x85U +#define SPI_NACK 0x1FU +#define SPI_CHECKSUM_START 0xABU + +struct __attribute__((packed)) spi_header { + u8 sync; + u8 endpoint; + uint16_t tx_len; + uint16_t max_rx_len; +}; + +struct spi_panda_transfer { + __u64 rx_buf; + __u64 tx_buf; + __u32 tx_length; + __u32 rx_length_max; + __u32 timeout; + __u8 endpoint; + __u8 expect_disconnect; +}; + +static u8 panda_calc_checksum(u8 *buf, u16 length) { + int i; + u8 checksum = SPI_CHECKSUM_START; + for (i = 0U; i < length; i++) { + checksum ^= buf[i]; + } + return checksum; +} + +static long panda_wait_for_ack(struct spidev_data *spidev, u8 ack_val, u8 length) { + int i; + int ret; + for (i = 0; i < 1000; i++) { + ret = spidev_sync_read(spidev, length); + if (ret < 0) { + return ret; + } + + if (spidev->rx_buffer[0] == ack_val) { + return 0; + } else if (spidev->rx_buffer[0] == SPI_NACK) { + return -2; + } + if (i > 20) usleep_range(10, 20); + } + return -1; +} + +static long panda_transfer_raw(struct spidev_data *spidev, struct spi_device *spi, unsigned long arg) { + u16 rx_len; + long retval = -1; + struct spi_header header; + struct spi_panda_transfer pt; + + struct spi_transfer t = { + .len = 0, + .tx_buf = spidev->tx_buffer, + .rx_buf = spidev->rx_buffer, + .speed_hz = spidev->spi->max_speed_hz, + }; + + struct spi_message m; + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + // read struct from user + if (!access_ok(VERIFY_WRITE, arg, sizeof(pt))) { + return -1; + } + if (copy_from_user(&pt, (void __user *)arg, sizeof(pt))) { + return -1; + } + dev_dbg(&spi->dev, "ep: %d, tx len: %d\n", pt.endpoint, pt.tx_length); + + // send header + header.sync = 0x5a; + header.endpoint = pt.endpoint; + header.tx_len = pt.tx_length; + header.max_rx_len = pt.rx_length_max; + memcpy(spidev->tx_buffer, &header, sizeof(header)); + spidev->tx_buffer[sizeof(header)] = panda_calc_checksum(spidev->tx_buffer, sizeof(header)); + + t.len = sizeof(header) + 1; + retval = spidev_sync(spidev, &m); + if (retval < 0) { + dev_dbg(&spi->dev, "spi xfer failed %ld\n", retval); + return retval; + } + + // wait for ACK + retval = panda_wait_for_ack(spidev, SPI_HACK, 1); + if (retval < 0) { + dev_dbg(&spi->dev, "no header ack %ld\n", retval); + return retval; + } + + // send data + dev_dbg(&spi->dev, "sending data\n"); + retval = copy_from_user(spidev->tx_buffer, (const u8 __user *)(uintptr_t)pt.tx_buf, pt.tx_length); + spidev->tx_buffer[pt.tx_length] = panda_calc_checksum(spidev->tx_buffer, pt.tx_length); + t.len = pt.tx_length + 1; + retval = spidev_sync(spidev, &m); + + if (pt.expect_disconnect) { + return 0; + } + + // wait for ACK + retval = panda_wait_for_ack(spidev, SPI_DACK, 3); + if (retval < 0) { + dev_dbg(&spi->dev, "no data ack\n"); + return retval; + } + + // get response + t.rx_buf = spidev->rx_buffer + 3; + rx_len = (spidev->rx_buffer[2] << 8) | (spidev->rx_buffer[1]); + dev_dbg(&spi->dev, "rx len %u\n", rx_len); + if (rx_len > pt.rx_length_max) { + dev_dbg(&spi->dev, "RX len greater than max\n"); + return -1; + } + + // do the read + t.len = rx_len + 1; + retval = spidev_sync(spidev, &m); + if (retval < 0) { + dev_dbg(&spi->dev, "spi xfer failed %ld\n", retval); + return retval; + } + if (panda_calc_checksum(spidev->rx_buffer, 3 + rx_len + 1) != 0) { + dev_dbg(&spi->dev, "bad checksum\n"); + return -1; + } + + retval = copy_to_user((u8 __user *)(uintptr_t)pt.rx_buf, spidev->rx_buffer + 3, rx_len); + + return rx_len; +} + +static long panda_transfer(struct spidev_data *spidev, struct spi_device *spi, unsigned long arg) { + int i; + int ret; + dev_dbg(&spi->dev, "=== XFER start ===\n"); + for (i = 0; i < 20; i++) { + ret = panda_transfer_raw(spidev, spi, arg); + if (ret >= 0) { + break; + } + } + dev_dbg(&spi->dev, "took %d tries\n", i+1); + return ret; +} diff --git a/panda/drivers/spi/spidev_panda.c b/panda/drivers/spi/spidev_panda.c new file mode 100644 index 0000000000..f21fe3387b --- /dev/null +++ b/panda/drivers/spi/spidev_panda.c @@ -0,0 +1,891 @@ +/* + * Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +/* + * This supports access to SPI devices using normal userspace I/O calls. + * Note that while traditional UNIX/POSIX I/O semantics are half duplex, + * and often mask message boundaries, full SPI support requires full duplex + * transfers. There are several kinds of internal message boundaries to + * handle chipselect management and other protocol options. + * + * SPI has a character major number assigned. We allocate minor numbers + * dynamically using a bitmask. You must use hotplug tools, such as udev + * (or mdev with busybox) to create and destroy the /dev/spidevB.C device + * nodes, since there is no fixed association of minor numbers with any + * particular SPI bus or device. + */ +int SPIDEV_MAJOR = 0; +//#define SPIDEV_MAJOR 153 /* assigned */ +#define N_SPI_MINORS 32 /* ... up to 256 */ + +static DECLARE_BITMAP(minors, N_SPI_MINORS); + + +/* Bit masks for spi_device.mode management. Note that incorrect + * settings for some settings can cause *lots* of trouble for other + * devices on a shared bus: + * + * - CS_HIGH ... this device will be active when it shouldn't be + * - 3WIRE ... when active, it won't behave as it should + * - NO_CS ... there will be no explicit message boundaries; this + * is completely incompatible with the shared bus model + * - READY ... transfers may proceed when they shouldn't. + * + * REVISIT should changing those flags be privileged? + */ +#define SPI_MODE_MASK (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \ + | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \ + | SPI_NO_CS | SPI_READY | SPI_TX_DUAL \ + | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD) + +struct spidev_data { + dev_t devt; + spinlock_t spi_lock; + struct spi_device *spi; + struct list_head device_entry; + + /* TX/RX buffers are NULL unless this device is open (users > 0) */ + struct mutex buf_lock; + unsigned users; + u8 *tx_buffer; + u8 *rx_buffer; + u32 speed_hz; +}; + +static LIST_HEAD(device_list); +static DEFINE_MUTEX(device_list_lock); + +static unsigned bufsiz = 4096; +module_param(bufsiz, uint, S_IRUGO); +MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message"); + +/*-------------------------------------------------------------------------*/ + +static ssize_t +spidev_sync(struct spidev_data *spidev, struct spi_message *message) +{ + DECLARE_COMPLETION_ONSTACK(done); + int status; + struct spi_device *spi; + + spin_lock_irq(&spidev->spi_lock); + spi = spidev->spi; + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + status = -ESHUTDOWN; + else + status = spi_sync(spi, message); + + if (status == 0) + status = message->actual_length; + + return status; +} + +static inline ssize_t +spidev_sync_write(struct spidev_data *spidev, size_t len) +{ + struct spi_transfer t = { + .tx_buf = spidev->tx_buffer, + .len = len, + .speed_hz = spidev->speed_hz, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spidev_sync(spidev, &m); +} + +static inline ssize_t +spidev_sync_read(struct spidev_data *spidev, size_t len) +{ + struct spi_transfer t = { + .rx_buf = spidev->rx_buffer, + .len = len, + .speed_hz = spidev->speed_hz, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spidev_sync(spidev, &m); +} + +/*-------------------------------------------------------------------------*/ + +/* Read-only message with current device setup */ +static ssize_t +spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + struct spidev_data *spidev; + ssize_t status = 0; + + /* chipselect only toggles at start or end of operation */ + if (count > bufsiz) + return -EMSGSIZE; + + spidev = filp->private_data; + + mutex_lock(&spidev->buf_lock); + status = spidev_sync_read(spidev, count); + if (status > 0) { + unsigned long missing; + + missing = copy_to_user(buf, spidev->rx_buffer, status); + if (missing == status) + status = -EFAULT; + else + status = status - missing; + } + mutex_unlock(&spidev->buf_lock); + + return status; +} + +/* Write-only message with current device setup */ +static ssize_t +spidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + struct spidev_data *spidev; + ssize_t status = 0; + unsigned long missing; + + /* chipselect only toggles at start or end of operation */ + if (count > bufsiz) + return -EMSGSIZE; + + spidev = filp->private_data; + + mutex_lock(&spidev->buf_lock); + missing = copy_from_user(spidev->tx_buffer, buf, count); + if (missing == 0) + status = spidev_sync_write(spidev, count); + else + status = -EFAULT; + mutex_unlock(&spidev->buf_lock); + + return status; +} + +static int spidev_message(struct spidev_data *spidev, + struct spi_ioc_transfer *u_xfers, unsigned n_xfers) +{ + struct spi_message msg; + struct spi_transfer *k_xfers; + struct spi_transfer *k_tmp; + struct spi_ioc_transfer *u_tmp; + unsigned n, total, tx_total, rx_total; + u8 *tx_buf, *rx_buf; + int status = -EFAULT; + + spi_message_init(&msg); + k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL); + if (k_xfers == NULL) + return -ENOMEM; + + /* Construct spi_message, copying any tx data to bounce buffer. + * We walk the array of user-provided transfers, using each one + * to initialize a kernel version of the same transfer. + */ + tx_buf = spidev->tx_buffer; + rx_buf = spidev->rx_buffer; + total = 0; + tx_total = 0; + rx_total = 0; + for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; + n; + n--, k_tmp++, u_tmp++) { + k_tmp->len = u_tmp->len; + + total += k_tmp->len; + /* Since the function returns the total length of transfers + * on success, restrict the total to positive int values to + * avoid the return value looking like an error. Also check + * each transfer length to avoid arithmetic overflow. + */ + if (total > INT_MAX || k_tmp->len > INT_MAX) { + status = -EMSGSIZE; + goto done; + } + + if (u_tmp->rx_buf) { + /* this transfer needs space in RX bounce buffer */ + rx_total += k_tmp->len; + if (rx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } + k_tmp->rx_buf = rx_buf; + if (!access_ok(VERIFY_WRITE, (u8 __user *) + (uintptr_t) u_tmp->rx_buf, + u_tmp->len)) + goto done; + rx_buf += k_tmp->len; + } + if (u_tmp->tx_buf) { + /* this transfer needs space in TX bounce buffer */ + tx_total += k_tmp->len; + if (tx_total > bufsiz) { + status = -EMSGSIZE; + goto done; + } + k_tmp->tx_buf = tx_buf; + if (copy_from_user(tx_buf, (const u8 __user *) + (uintptr_t) u_tmp->tx_buf, + u_tmp->len)) + goto done; + tx_buf += k_tmp->len; + } + + k_tmp->cs_change = !!u_tmp->cs_change; + k_tmp->tx_nbits = u_tmp->tx_nbits; + k_tmp->rx_nbits = u_tmp->rx_nbits; + k_tmp->bits_per_word = u_tmp->bits_per_word; + k_tmp->delay_usecs = u_tmp->delay_usecs; + k_tmp->speed_hz = u_tmp->speed_hz; + if (!k_tmp->speed_hz) + k_tmp->speed_hz = spidev->speed_hz; +#ifdef VERBOSE + dev_dbg(&spidev->spi->dev, + " xfer len %u %s%s%s%dbits %u usec %uHz\n", + u_tmp->len, + u_tmp->rx_buf ? "rx " : "", + u_tmp->tx_buf ? "tx " : "", + u_tmp->cs_change ? "cs " : "", + u_tmp->bits_per_word ? : spidev->spi->bits_per_word, + u_tmp->delay_usecs, + u_tmp->speed_hz ? : spidev->spi->max_speed_hz); +#endif + spi_message_add_tail(k_tmp, &msg); + } + + status = spidev_sync(spidev, &msg); + if (status < 0) + goto done; + + /* copy any rx data out of bounce buffer */ + rx_buf = spidev->rx_buffer; + for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { + if (u_tmp->rx_buf) { + if (__copy_to_user((u8 __user *) + (uintptr_t) u_tmp->rx_buf, rx_buf, + u_tmp->len)) { + status = -EFAULT; + goto done; + } + rx_buf += u_tmp->len; + } + } + status = total; + +done: + kfree(k_xfers); + return status; +} + +static struct spi_ioc_transfer * +spidev_get_ioc_message(unsigned int cmd, struct spi_ioc_transfer __user *u_ioc, + unsigned *n_ioc) +{ + struct spi_ioc_transfer *ioc; + u32 tmp; + + /* Check type, command number and direction */ + if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC + || _IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) + || _IOC_DIR(cmd) != _IOC_WRITE) + return ERR_PTR(-ENOTTY); + + tmp = _IOC_SIZE(cmd); + if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) + return ERR_PTR(-EINVAL); + *n_ioc = tmp / sizeof(struct spi_ioc_transfer); + if (*n_ioc == 0) + return NULL; + + /* copy into scratch area */ + ioc = kmalloc(tmp, GFP_KERNEL); + if (!ioc) + return ERR_PTR(-ENOMEM); + if (__copy_from_user(ioc, u_ioc, tmp)) { + kfree(ioc); + return ERR_PTR(-EFAULT); + } + return ioc; +} + + +#include "spi_panda.h" + +static long +spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int err = 0; + int retval = 0; + struct spidev_data *spidev; + struct spi_device *spi; + u32 tmp; + unsigned n_ioc; + struct spi_ioc_transfer *ioc; + + /* Check type and command number */ + if (_IOC_TYPE(cmd) != SPI_IOC_MAGIC) + return -ENOTTY; + + /* Check access direction once here; don't repeat below. + * IOC_DIR is from the user perspective, while access_ok is + * from the kernel perspective; so they look reversed. + */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, + (void __user *)arg, _IOC_SIZE(cmd)); + if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, + (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* guard against device removal before, or while, + * we issue this ioctl. + */ + spidev = filp->private_data; + spin_lock_irq(&spidev->spi_lock); + spi = spi_dev_get(spidev->spi); + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + return -ESHUTDOWN; + + /* use the buffer lock here for triple duty: + * - prevent I/O (from us) so calling spi_setup() is safe; + * - prevent concurrent SPI_IOC_WR_* from morphing + * data fields while SPI_IOC_RD_* reads them; + * - SPI_IOC_MESSAGE needs the buffer locked "normally". + */ + mutex_lock(&spidev->buf_lock); + + switch (cmd) { + /* read requests */ + case SPI_IOC_RD_MODE: + retval = __put_user(spi->mode & SPI_MODE_MASK, + (__u8 __user *)arg); + break; + case SPI_IOC_RD_MODE32: + retval = __put_user(spi->mode & SPI_MODE_MASK, + (__u32 __user *)arg); + break; + case SPI_IOC_RD_LSB_FIRST: + retval = panda_transfer(spidev, spi, arg); + //retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, + // (__u8 __user *)arg); + break; + case SPI_IOC_RD_BITS_PER_WORD: + retval = __put_user(spi->bits_per_word, (__u8 __user *)arg); + break; + case SPI_IOC_RD_MAX_SPEED_HZ: + retval = __put_user(spidev->speed_hz, (__u32 __user *)arg); + break; + + /* write requests */ + case SPI_IOC_WR_MODE: + case SPI_IOC_WR_MODE32: + if (cmd == SPI_IOC_WR_MODE) + retval = __get_user(tmp, (u8 __user *)arg); + else + retval = __get_user(tmp, (u32 __user *)arg); + if (retval == 0) { + u32 save = spi->mode; + + if (tmp & ~SPI_MODE_MASK) { + retval = -EINVAL; + break; + } + + tmp |= spi->mode & ~SPI_MODE_MASK; + spi->mode = (u16)tmp; + retval = spi_setup(spi); + if (retval < 0) + spi->mode = save; + else + dev_dbg(&spi->dev, "spi mode %x\n", tmp); + } + break; + case SPI_IOC_WR_LSB_FIRST: + retval = __get_user(tmp, (__u8 __user *)arg); + if (retval == 0) { + u32 save = spi->mode; + + if (tmp) + spi->mode |= SPI_LSB_FIRST; + else + spi->mode &= ~SPI_LSB_FIRST; + retval = spi_setup(spi); + if (retval < 0) + spi->mode = save; + else + dev_dbg(&spi->dev, "%csb first\n", + tmp ? 'l' : 'm'); + } + break; + case SPI_IOC_WR_BITS_PER_WORD: + retval = __get_user(tmp, (__u8 __user *)arg); + if (retval == 0) { + u8 save = spi->bits_per_word; + + spi->bits_per_word = tmp; + retval = spi_setup(spi); + if (retval < 0) + spi->bits_per_word = save; + else + dev_dbg(&spi->dev, "%d bits per word\n", tmp); + } + break; + case SPI_IOC_WR_MAX_SPEED_HZ: + retval = __get_user(tmp, (__u32 __user *)arg); + if (retval == 0) { + u32 save = spi->max_speed_hz; + + spi->max_speed_hz = tmp; + retval = spi_setup(spi); + if (retval >= 0) + spidev->speed_hz = tmp; + else + dev_dbg(&spi->dev, "%d Hz (max)\n", tmp); + spi->max_speed_hz = save; + } + break; + + default: + /* segmented and/or full-duplex I/O request */ + /* Check message and copy into scratch area */ + ioc = spidev_get_ioc_message(cmd, + (struct spi_ioc_transfer __user *)arg, &n_ioc); + if (IS_ERR(ioc)) { + retval = PTR_ERR(ioc); + break; + } + if (!ioc) + break; /* n_ioc is also 0 */ + + /* translate to spi_message, execute */ + retval = spidev_message(spidev, ioc, n_ioc); + kfree(ioc); + break; + } + + mutex_unlock(&spidev->buf_lock); + spi_dev_put(spi); + return retval; +} + +#ifdef CONFIG_COMPAT +static long +spidev_compat_ioc_message(struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct spi_ioc_transfer __user *u_ioc; + int retval = 0; + struct spidev_data *spidev; + struct spi_device *spi; + unsigned n_ioc, n; + struct spi_ioc_transfer *ioc; + + u_ioc = (struct spi_ioc_transfer __user *) compat_ptr(arg); + if (!access_ok(VERIFY_READ, u_ioc, _IOC_SIZE(cmd))) + return -EFAULT; + + /* guard against device removal before, or while, + * we issue this ioctl. + */ + spidev = filp->private_data; + spin_lock_irq(&spidev->spi_lock); + spi = spi_dev_get(spidev->spi); + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + return -ESHUTDOWN; + + /* SPI_IOC_MESSAGE needs the buffer locked "normally" */ + mutex_lock(&spidev->buf_lock); + + /* Check message and copy into scratch area */ + ioc = spidev_get_ioc_message(cmd, u_ioc, &n_ioc); + if (IS_ERR(ioc)) { + retval = PTR_ERR(ioc); + goto done; + } + if (!ioc) + goto done; /* n_ioc is also 0 */ + + /* Convert buffer pointers */ + for (n = 0; n < n_ioc; n++) { + ioc[n].rx_buf = (uintptr_t) compat_ptr(ioc[n].rx_buf); + ioc[n].tx_buf = (uintptr_t) compat_ptr(ioc[n].tx_buf); + } + + /* translate to spi_message, execute */ + retval = spidev_message(spidev, ioc, n_ioc); + kfree(ioc); + +done: + mutex_unlock(&spidev->buf_lock); + spi_dev_put(spi); + return retval; +} + +static long +spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + if (_IOC_TYPE(cmd) == SPI_IOC_MAGIC + && _IOC_NR(cmd) == _IOC_NR(SPI_IOC_MESSAGE(0)) + && _IOC_DIR(cmd) == _IOC_WRITE) + return spidev_compat_ioc_message(filp, cmd, arg); + + return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#else +#define spidev_compat_ioctl NULL +#endif /* CONFIG_COMPAT */ + +static int spidev_open(struct inode *inode, struct file *filp) +{ + struct spidev_data *spidev; + int status = -ENXIO; + + mutex_lock(&device_list_lock); + + list_for_each_entry(spidev, &device_list, device_entry) { + if (spidev->devt == inode->i_rdev) { + status = 0; + break; + } + } + + if (status) { + pr_debug("spidev: nothing for minor %d\n", iminor(inode)); + goto err_find_dev; + } + + if (!spidev->tx_buffer) { + spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL); + if (!spidev->tx_buffer) { + dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); + status = -ENOMEM; + goto err_find_dev; + } + } + + if (!spidev->rx_buffer) { + spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL); + if (!spidev->rx_buffer) { + dev_dbg(&spidev->spi->dev, "open/ENOMEM\n"); + status = -ENOMEM; + goto err_alloc_rx_buf; + } + } + + spidev->users++; + filp->private_data = spidev; + nonseekable_open(inode, filp); + + mutex_unlock(&device_list_lock); + return 0; + +err_alloc_rx_buf: + kfree(spidev->tx_buffer); + spidev->tx_buffer = NULL; +err_find_dev: + mutex_unlock(&device_list_lock); + return status; +} + +static int spidev_release(struct inode *inode, struct file *filp) +{ + struct spidev_data *spidev; + + mutex_lock(&device_list_lock); + spidev = filp->private_data; + filp->private_data = NULL; + + /* last close? */ + spidev->users--; + if (!spidev->users) { + int dofree; + + kfree(spidev->tx_buffer); + spidev->tx_buffer = NULL; + + kfree(spidev->rx_buffer); + spidev->rx_buffer = NULL; + + spin_lock_irq(&spidev->spi_lock); + if (spidev->spi) + spidev->speed_hz = spidev->spi->max_speed_hz; + + /* ... after we unbound from the underlying device? */ + dofree = (spidev->spi == NULL); + spin_unlock_irq(&spidev->spi_lock); + + if (dofree) + kfree(spidev); + } + mutex_unlock(&device_list_lock); + + return 0; +} + +static const struct file_operations spidev_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .write = spidev_write, + .read = spidev_read, + .unlocked_ioctl = spidev_ioctl, + .compat_ioctl = spidev_compat_ioctl, + .open = spidev_open, + .release = spidev_release, + .llseek = no_llseek, +}; + +/*-------------------------------------------------------------------------*/ + +/* The main reason to have this class is to make mdev/udev create the + * /dev/spidevB.C character device nodes exposing our userspace API. + * It also simplifies memory management. + */ + +static struct class *spidev_class; + +#ifdef CONFIG_OF +static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "commaai,panda" }, + {}, +}; +MODULE_DEVICE_TABLE(of, spidev_dt_ids); +#endif + +#ifdef CONFIG_ACPI + +/* Dummy SPI devices not to be used in production systems */ +#define SPIDEV_ACPI_DUMMY 1 + +static const struct acpi_device_id spidev_acpi_ids[] = { + /* + * The ACPI SPT000* devices are only meant for development and + * testing. Systems used in production should have a proper ACPI + * description of the connected peripheral and they should also use + * a proper driver instead of poking directly to the SPI bus. + */ + { "SPT0001", SPIDEV_ACPI_DUMMY }, + { "SPT0002", SPIDEV_ACPI_DUMMY }, + { "SPT0003", SPIDEV_ACPI_DUMMY }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, spidev_acpi_ids); + +static void spidev_probe_acpi(struct spi_device *spi) +{ + const struct acpi_device_id *id; + + if (!has_acpi_companion(&spi->dev)) + return; + + id = acpi_match_device(spidev_acpi_ids, &spi->dev); + if (WARN_ON(!id)) + return; + + if (id->driver_data == SPIDEV_ACPI_DUMMY) + dev_warn(&spi->dev, "do not use this driver in production systems!\n"); +} +#else +static inline void spidev_probe_acpi(struct spi_device *spi) {} +#endif + +/*-------------------------------------------------------------------------*/ + +static int spidev_probe(struct spi_device *spi) +{ + struct spidev_data *spidev; + int status; + unsigned long minor; + + /* + * spidev should never be referenced in DT without a specific + * compatible string, it is a Linux implementation thing + * rather than a description of the hardware. + */ + if (spi->dev.of_node && !of_match_device(spidev_dt_ids, &spi->dev)) { + dev_err(&spi->dev, "buggy DT: spidev listed directly in DT\n"); + WARN_ON(spi->dev.of_node && + !of_match_device(spidev_dt_ids, &spi->dev)); + } + + spidev_probe_acpi(spi); + + /* Allocate driver data */ + spidev = kzalloc(sizeof(*spidev), GFP_KERNEL); + if (!spidev) + return -ENOMEM; + + /* Initialize the driver data */ + spidev->spi = spi; + spin_lock_init(&spidev->spi_lock); + mutex_init(&spidev->buf_lock); + + INIT_LIST_HEAD(&spidev->device_entry); + + /* If we can allocate a minor number, hook up this device. + * Reusing minors is fine so long as udev or mdev is working. + */ + mutex_lock(&device_list_lock); + minor = find_first_zero_bit(minors, N_SPI_MINORS); + if (minor < N_SPI_MINORS) { + struct device *dev; + + spidev->devt = MKDEV(SPIDEV_MAJOR, minor); + dev = device_create(spidev_class, &spi->dev, spidev->devt, + spidev, "spidev%d.%d", + spi->master->bus_num, spi->chip_select); + status = PTR_ERR_OR_ZERO(dev); + } else { + dev_dbg(&spi->dev, "no minor number available!\n"); + status = -ENODEV; + } + if (status == 0) { + set_bit(minor, minors); + list_add(&spidev->device_entry, &device_list); + } + mutex_unlock(&device_list_lock); + + spidev->speed_hz = spi->max_speed_hz; + + if (status == 0) + spi_set_drvdata(spi, spidev); + else + kfree(spidev); + + return status; +} + +static int spidev_remove(struct spi_device *spi) +{ + struct spidev_data *spidev = spi_get_drvdata(spi); + + /* make sure ops on existing fds can abort cleanly */ + spin_lock_irq(&spidev->spi_lock); + spidev->spi = NULL; + spin_unlock_irq(&spidev->spi_lock); + + /* prevent new opens */ + mutex_lock(&device_list_lock); + list_del(&spidev->device_entry); + device_destroy(spidev_class, spidev->devt); + clear_bit(MINOR(spidev->devt), minors); + if (spidev->users == 0) + kfree(spidev); + mutex_unlock(&device_list_lock); + + return 0; +} + +static struct spi_driver spidev_spi_driver = { + .driver = { + .name = "spidev_panda", + .of_match_table = of_match_ptr(spidev_dt_ids), + .acpi_match_table = ACPI_PTR(spidev_acpi_ids), + }, + .probe = spidev_probe, + .remove = spidev_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init spidev_init(void) +{ + int status; + + /* Claim our 256 reserved device numbers. Then register a class + * that will key udev/mdev to add/remove /dev nodes. Last, register + * the driver which manages those device numbers. + */ + BUILD_BUG_ON(N_SPI_MINORS > 256); + status = register_chrdev(0, "spi", &spidev_fops); + if (status < 0) + return status; + + SPIDEV_MAJOR = status; + + spidev_class = class_create(THIS_MODULE, "spidev_panda"); + if (IS_ERR(spidev_class)) { + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); + return PTR_ERR(spidev_class); + } + + status = spi_register_driver(&spidev_spi_driver); + if (status < 0) { + class_destroy(spidev_class); + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); + } + return status; +} +module_init(spidev_init); + +static void __exit spidev_exit(void) +{ + spi_unregister_driver(&spidev_spi_driver); + class_destroy(spidev_class); + unregister_chrdev(SPIDEV_MAJOR, spidev_spi_driver.driver.name); +} +module_exit(spidev_exit); + +MODULE_AUTHOR("Andrea Paterniani, "); +MODULE_DESCRIPTION("User mode SPI device interface"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:spidev"); diff --git a/panda/examples/__init__.py b/panda/examples/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/panda/examples/can_bit_transition.md b/panda/examples/can_bit_transition.md new file mode 100644 index 0000000000..fa0a6c6bb3 --- /dev/null +++ b/panda/examples/can_bit_transition.md @@ -0,0 +1,25 @@ +# How to use can_bit_transition.py to reverse engineer a single bit field + +Let's say our goal is to find a brake pedal signal (caused by your foot pressing the brake pedal vs adaptive cruise control braking). + +The following process will allow you to quickly find bits that are always 0 during a period of time (when you know you were not pressing the brake with your foot) and always 1 in a different period of time (when you know you were pressing the brake with your foot). + +Open up a drive in cabana where you can find a place you used the brake pedal and another place where you did not use the brake pedal (and you can identify when you were on the brake pedal and when you were not). You may want to go out for a drive and put something in front of the camera after you put your foot on the brake and take it away before you take your foot off the brake so you can easily identify exactly when you had your foot on the brake based on the video in cabana. This is critical because this script needs the brake signal to always be high the entire time for one of the time frames. A 10 second time frame worked well for me. + +I found a drive where I knew I was not pressing the brake between timestamp 50.0 thru 65.0 and I was pressing the brake between timestamp 69.0 thru 79.0. Determine what the timestamps are in cabana by plotting any message and putting your mouse over the plot at the location you want to discover the timestamp. The tool tip on mouse hover has the format: timestamp: value + +Now download the log from cabana (Save Log button) and run the script passing in the timestamps +(replace csv file name with cabana log you downloaded and time ranges with your own) +``` +./can_bit_transition.py ./honda_crv_ex_2017_can-1520354796875.csv 50.0-65.0 69.0-79.0 +``` + +The script will output bits that were always low in the first time range and always high in the second time range (and vice versa) +``` +id 17c 0 -> 1 at byte 4 bitmask 1 +id 17c 0 -> 1 at byte 6 bitmask 32 +id 221 1 -> 0 at byte 0 bitmask 4 +id 1be 0 -> 1 at byte 0 bitmask 16 +``` + +Now I go back to cabana and graph the above bits by searching for the message by id, double clicking on the appropriate bit, and then selecting "show plot". I already knew that message id 0x17c is both user brake and adaptive cruise control braking combined, so I plotted one of those signals along side 0x221 and 0x1be. By replaying a drive I could see that 0x221 was not a brake signal (when high at random times that did not correspond to braking). Next I looked at 0x1be and I found it was the brake pedal signal I was looking for (went high whenever I pressed the brake pedal and did not go high when adaptive cruise control was braking). \ No newline at end of file diff --git a/panda/examples/can_bit_transition.py b/panda/examples/can_bit_transition.py new file mode 100755 index 0000000000..1e7bad54e7 --- /dev/null +++ b/panda/examples/can_bit_transition.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +import csv +import sys + +CSV_KEYS = { + "logger": { + "time": "Time", + "message_id": "MessageID", + "data": "Message", + "bus": "Bus" + }, + "cabana": { + "time": "time", + "message_id": "addr", + "data": "data", + "bus": "bus" + } +} + + +class Message(): + """Details about a specific message ID.""" + + def __init__(self, message_id): + self.message_id = message_id + self.ones = [0] * 64 # bit set if 1 is always seen + self.zeros = [0] * 64 # bit set if 0 is always seen + + def printBitDiff(self, other): + """Prints bits that transition from always zero to always 1 and vice versa.""" + for i in range(len(self.ones)): + zero_to_one = other.zeros[i] & self.ones[i] + if zero_to_one: + print('id %s 0 -> 1 at byte %d bitmask %d' % (self.message_id, i, zero_to_one)) + one_to_zero = other.ones[i] & self.zeros[i] + if one_to_zero: + print('id %s 1 -> 0 at byte %d bitmask %d' % (self.message_id, i, one_to_zero)) + + +class Info(): + """A collection of Messages.""" + + def __init__(self): + self.messages = {} # keyed by MessageID + + def load(self, filename, start, end): + """Given a CSV file, adds information about message IDs and their values.""" + with open(filename, newline='') as inp: + reader = csv.DictReader(inp) + dtype = None + for row in reader: + if not len(row): + continue + if dtype is None: + dtype = "logger" if "Bus" in row else "cabana" + + time = float(row[CSV_KEYS[dtype]["time"]]) + bus = int(row[CSV_KEYS[dtype]["bus"]]) + if time < start or bus > 127: + continue + elif time > end: + break + + message_id = row[CSV_KEYS[dtype]["message_id"]] + if message_id.startswith('0x'): + message_id = message_id[2:] # remove leading '0x' + else: + message_id = hex(int(message_id))[2:] # old message IDs are in decimal + message_id = f'{bus}:{message_id}' + + data = row[CSV_KEYS[dtype]["data"]] + if data.startswith('0x'): + data = data[2:] # remove leading '0x' + else: + data = data + new_message = False + if message_id not in self.messages: + self.messages[message_id] = Message(message_id) + new_message = True + message = self.messages[message_id] + bts = bytearray.fromhex(data) + for i in range(len(bts)): + ones = int(bts[i]) + message.ones[i] = ones if new_message else message.ones[i] & ones + # Inverts the data and masks it to a byte to get the zeros as ones. + zeros = (~int(bts[i])) & 0xff + message.zeros[i] = zeros if new_message else message.zeros[i] & zeros + +def PrintUnique(log_file, low_range, high_range): + # find messages with bits that are always low + start, end = list(map(float, low_range.split('-'))) + low = Info() + low.load(log_file, start, end) + # find messages with bits that are always high + start, end = list(map(float, high_range.split('-'))) + high = Info() + high.load(log_file, start, end) + # print messages that go from low to high + found = False + for message_id in sorted(high.messages, key=lambda x: int(x.split(':')[1], 16)): + if message_id in low.messages: + high.messages[message_id].printBitDiff(low.messages[message_id]) + found = True + if not found: + print('No messages that transition from always low to always high found!') + +if __name__ == "__main__": + if len(sys.argv) < 4: + print('Usage:\n%s log.csv - -' % sys.argv[0]) + sys.exit(0) + PrintUnique(sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/panda/examples/can_logger.py b/panda/examples/can_logger.py new file mode 100755 index 0000000000..2bf4359cac --- /dev/null +++ b/panda/examples/can_logger.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import csv +import time +from panda import Panda + +def can_logger(): + p = Panda() + + try: + outputfile = open('output.csv', 'w') + csvwriter = csv.writer(outputfile) + # Write Header + csvwriter.writerow(['Bus', 'MessageID', 'Message', 'MessageLength', 'Time']) + print("Writing csv file output.csv. Press Ctrl-C to exit...\n") + + bus0_msg_cnt = 0 + bus1_msg_cnt = 0 + bus2_msg_cnt = 0 + + start_time = time.time() + while True: + can_recv = p.can_recv() + + for address, dat, src in can_recv: + csvwriter.writerow( + [str(src), str(hex(address)), f"0x{dat.hex()}", len(dat), str(time.time() - start_time)]) + + if src == 0: + bus0_msg_cnt += 1 + elif src == 1: + bus1_msg_cnt += 1 + elif src == 2: + bus2_msg_cnt += 1 + + print(f"Message Counts... Bus 0: {bus0_msg_cnt} Bus 1: {bus1_msg_cnt} Bus 2: {bus2_msg_cnt}", end='\r') + + except KeyboardInterrupt: + print(f"\nNow exiting. Final message Counts... Bus 0: {bus0_msg_cnt} Bus 1: {bus1_msg_cnt} Bus 2: {bus2_msg_cnt}") + outputfile.close() + +if __name__ == "__main__": + can_logger() diff --git a/panda/examples/can_unique.md b/panda/examples/can_unique.md new file mode 100644 index 0000000000..4d8ac460e4 --- /dev/null +++ b/panda/examples/can_unique.md @@ -0,0 +1,103 @@ +# How to use can_unique.py to reverse engineer a single bit field + +Let's say our goal is to find the CAN message indicating that the driver's door is either open or closed. +The following process is great for simple single-bit messages. +However for frequently changing values, such as RPM or speed, Cabana's graphical plots are probably better to use. + + +First record a few minutes of background CAN messages with all the doors closed and save it in background.csv: +``` +./can_logger.py +mv output.csv background.csv +``` +Then run can_logger.py for a few seconds while performing the action you're interested, such as opening and then closing the +front-left door and save it as door-fl-1.csv +Repeat the process and save it as door-f1-2.csv to have an easy way to confirm any suspicions. + +Now we'll use can_unique.py to look for unique bits: +``` +$ ./can_unique.py door-fl-1.csv background* +id 820 new one at byte 2 bitmask 2 +id 520 new one at byte 3 bitmask 7 +id 520 new zero at byte 3 bitmask 8 +id 520 new one at byte 5 bitmask 6 +id 520 new zero at byte 5 bitmask 9 +id 559 new zero at byte 6 bitmask 4 +id 804 new one at byte 5 bitmask 2 +id 804 new zero at byte 5 bitmask 1 + +$ ./can_unique.py door-fl-2.csv background* +id 672 new one at byte 3 bitmask 3 +id 820 new one at byte 2 bitmask 2 +id 520 new one at byte 3 bitmask 7 +id 520 new zero at byte 3 bitmask 8 +id 520 new one at byte 5 bitmask 6 +id 520 new zero at byte 5 bitmask 9 +id 559 new zero at byte 6 bitmask 4 +``` + +One of these bits hopefully indicates that the driver's door is open. +Let's go through each message ID to figure out which one is correct. +We expect any correct bits to have changed in both runs. +We can rule out 804 because it only occurred in the first run. +We can rule out 672 because it only occurred in the second run. +That leaves us with these message IDs: 820, 520, 559. Let's take a closer look at each one. + +``` +$ fgrep ,559, door-fl-1.csv |head +0,559,00ff0000000024f0 +0,559,00ff000000004464 +0,559,00ff0000000054a9 +0,559,00ff0000000064e3 +0,559,00ff00000000742e +0,559,00ff000000008451 +0,559,00ff00000000949c +0,559,00ff00000000a4d6 +0,559,00ff00000000b41b +0,559,00ff00000000c442 +``` +Message ID 559 looks like an incrementing value, so it's not what we're looking for. + +``` +$ fgrep ,520, door-fl-2.csv +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +0,520,26ff00f8a2890000 +0,520,26ff00f8a1890000 +``` +Message ID 520 oscillates between two values. However I only opened and closed the door once, so this is probably not it. + +``` +$ fgrep ,820, door-fl-1.csv +0,820,44000100a500c802 +0,820,44000100a500c803 +0,820,44000300a500c803 +0,820,44000300a500c802 +0,820,44000300a500c802 +0,820,44000300a500c802 +0,820,44000100a500c802 +0,820,44000100a500c802 +0,820,44000100a500c802 +``` +Message ID 820 looks promising! It starts off at 44000100a500c802 when the door is closed. +When the door is open it goes to 44000300a500c802. +Then when the door is closed again, it goes back to 44000100a500c802. +Let's confirm by looking at the data from our other run: +``` +$ fgrep ,820, door-fl-2.csv +0,820,44000100a500c802 +0,820,44000300a500c802 +0,820,44000100a500c802 +``` +Perfect! We now know that message id 820 at byte 2 bitmask 2 is set if the driver's door is open. +If we repeat the process with the front passenger's door, +then we'll find that message id 820 at byte 2 bitmask 4 is set if the front-right door is open. +This confirms our finding because it's common for similar signals to be near each other. diff --git a/panda/examples/can_unique.py b/panda/examples/can_unique.py new file mode 100755 index 0000000000..05977afb0a --- /dev/null +++ b/panda/examples/can_unique.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# Given an interesting CSV file of CAN messages and a list of background CAN +# messages, print which bits in the interesting file have never appeared +# in the background files. + +# Expects the CSV file to be in one of the following formats: + +# can_logger.py +# Bus,MessageID,Message,MessageLength +# 0,0x292,0x040000001068,6 + +# The old can_logger.py format is also supported: +# Bus,MessageID,Message +# 0,344,c000c00000000000 + +# Cabana "Save Log" format +# time,addr,bus,data +# 240.47911496100002,53,0,0acc0ade0074bf9e + + +import csv +import sys + +class Message(): + """Details about a specific message ID.""" + + def __init__(self, message_id): + self.message_id = message_id + self.data = {} # keyed by hex string encoded message data + self.ones = [0] * 64 # bit set if 1 is seen + self.zeros = [0] * 64 # bit set if 0 has been seen + + def printBitDiff(self, other): + """Prints bits that are set or cleared compared to other background.""" + for i in range(len(self.ones)): + new_ones = ((~other.ones[i]) & 0xff) & self.ones[i] + if new_ones: + print('id %s new one at byte %d bitmask %d' % ( + self.message_id, i, new_ones)) + new_zeros = ((~other.zeros[i]) & 0xff) & self.zeros[i] + if new_zeros: + print('id %s new zero at byte %d bitmask %d' % ( + self.message_id, i, new_zeros)) + + +class Info(): + """A collection of Messages.""" + + def __init__(self): + self.messages = {} # keyed by MessageID + + def load(self, filename): + """Given a CSV file, adds information about message IDs and their values.""" + with open(filename) as inp: + reader = csv.reader(inp) + header = next(reader, None) + if header[0] == 'time': + self.cabana(reader) + else: + self.logger(reader) + + def cabana(self, reader): + for row in reader: + bus = row[2] + message_id = hex(int(row[1]))[2:] + message_id = f'{bus}:{message_id}' + data = row[3] + self.store(message_id, data) + + def logger(self, reader): + for row in reader: + bus = row[0] + if row[1].startswith('0x'): + message_id = row[1][2:] # remove leading '0x' + else: + message_id = hex(int(row[1]))[2:] # old message IDs are in decimal + message_id = f'{bus}:{message_id}' + if row[1].startswith('0x'): + data = row[2][2:] # remove leading '0x' + else: + data = row[2] + self.store(message_id, data) + + def store(self, message_id, data): + if message_id not in self.messages: + self.messages[message_id] = Message(message_id) + message = self.messages[message_id] + if data not in self.messages[message_id].data: + message.data[data] = True + bts = bytearray.fromhex(data) + for i in range(len(bts)): + message.ones[i] = message.ones[i] | int(bts[i]) + # Inverts the data and masks it to a byte to get the zeros as ones. + message.zeros[i] = message.zeros[i] | ((~int(bts[i])) & 0xff) + + +def PrintUnique(interesting_file, background_files): + background = Info() + for background_file in background_files: + background.load(background_file) + interesting = Info() + interesting.load(interesting_file) + for message_id in sorted(interesting.messages): + if message_id not in background.messages: + print('New message_id: %s' % message_id) + else: + interesting.messages[message_id].printBitDiff( + background.messages[message_id]) + + +if __name__ == "__main__": + if len(sys.argv) < 3: + print('Usage:\n%s interesting.csv background*.csv' % sys.argv[0]) + sys.exit(0) + PrintUnique(sys.argv[1], sys.argv[2:]) diff --git a/panda/examples/query_fw_versions.py b/panda/examples/query_fw_versions.py new file mode 100755 index 0000000000..67807d5a3d --- /dev/null +++ b/panda/examples/query_fw_versions.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +import argparse +from tqdm import tqdm +from opendbc.car.carlog import carlog +from opendbc.car.uds import UdsClient, MessageTimeoutError, NegativeResponseError, InvalidSubAddressError, \ + SESSION_TYPE, DATA_IDENTIFIER_TYPE +from opendbc.car.structs import CarParams +from panda import Panda + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--rxoffset", default="") + parser.add_argument("--nonstandard", action="store_true") + parser.add_argument("--no-obd", action="store_true", help="Bus 1 will not be multiplexed to the OBD-II port") + parser.add_argument("--no-29bit", action="store_true", help="29 bit addresses will not be queried") + parser.add_argument("--debug", action="store_true") + parser.add_argument("--addr") + parser.add_argument("--sub_addr", "--subaddr", help="A hex sub-address or `scan` to scan the full sub-address range") + parser.add_argument("--bus") + parser.add_argument('-s', '--serial', help="Serial number of panda to use") + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + if args.addr: + addrs = [int(args.addr, base=16)] + else: + addrs = [0x700 + i for i in range(256)] + if not args.no_29bit: + addrs += [0x18da0000 + (i << 8) + 0xf1 for i in range(256)] + results = {} + + sub_addrs: list[int | None] = [None] + if args.sub_addr: + if args.sub_addr == "scan": + sub_addrs = list(range(0xff + 1)) + else: + sub_addrs = [int(args.sub_addr, base=16)] + if sub_addrs[0] > 0xff: # type: ignore + print(f"Invalid sub-address: 0x{sub_addrs[0]:X}, needs to be in range 0x0 to 0xff") + parser.print_help() + exit() + + uds_data_ids = {} + for std_id in DATA_IDENTIFIER_TYPE: + uds_data_ids[std_id.value] = std_id.name + if args.nonstandard: + for uds_id in range(0xf100, 0xf180): + uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_VEHICLE_MANUFACTURER_SPECIFIC_DATA_IDENTIFIER" + for uds_id in range(0xf1a0, 0xf1f0): + uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_VEHICLE_MANUFACTURER_SPECIFIC" + for uds_id in range(0xf1f0, 0xf200): + uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_SYSTEM_SUPPLIER_SPECIFIC" + + panda_serials = Panda.list() + if args.serial is None and len(panda_serials) > 1: + print("\nMultiple pandas found, choose one:") + for serial in panda_serials: + with Panda(serial) as panda: + print(f" {serial}: internal={panda.is_internal()}") + print() + parser.print_help() + exit() + + panda = Panda(serial=args.serial) + panda.set_safety_mode(CarParams.SafetyModel.elm327, 1 if args.no_obd else 0) + print("querying addresses ...") + with tqdm(addrs) as t: + for addr in t: + # skip functional broadcast addrs + if addr == 0x7df or addr == 0x18db33f1: + continue + + if args.bus: + bus = int(args.bus) + else: + bus = 1 + rx_addr = addr + int(args.rxoffset, base=16) if args.rxoffset else None + + # Try all sub-addresses for addr. By default, this is None + for sub_addr in sub_addrs: + sub_addr_str = hex(sub_addr) if sub_addr is not None else None + t.set_description(f"{hex(addr)}, {sub_addr_str}") + uds_client = UdsClient(panda, addr, rx_addr, bus, sub_addr=sub_addr, timeout=0.2) + # Check for anything alive at this address, and switch to the highest + # available diagnostic session without security access + try: + uds_client.tester_present() + uds_client.diagnostic_session_control(SESSION_TYPE.DEFAULT) + uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) + except NegativeResponseError: + pass + except MessageTimeoutError: + continue + except InvalidSubAddressError as e: + print(f'*** Skipping address {hex(addr)}: {e}') + break + + # Run queries against all standard UDS data identifiers, plus selected + # non-standardized identifier ranges if requested + resp = {} + for uds_data_id in sorted(uds_data_ids): + try: + data = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE(uds_data_id)) + if data: + resp[uds_data_id] = data + except (NegativeResponseError, MessageTimeoutError, InvalidSubAddressError): + pass + + if resp.keys(): + results[(addr, sub_addr)] = resp + + if len(results.items()): + for (addr, sub_addr), resp in results.items(): + sub_addr_str = f", sub-address 0x{sub_addr:X}" if sub_addr is not None else "" + print(f"\n\n*** Results for address 0x{addr:X}{sub_addr_str} ***\n\n") + for rid, dat in resp.items(): + print(f"0x{rid:02X} {uds_data_ids[rid]}: {dat}") + else: + print("no fw versions found!") diff --git a/panda/examples/query_vin_and_stats.py b/panda/examples/query_vin_and_stats.py new file mode 100755 index 0000000000..4408e11f6f --- /dev/null +++ b/panda/examples/query_vin_and_stats.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +import time +import struct +from opendbc.car.structs import CarParams +from panda import Panda +from hexdump import hexdump +from opendbc.car.isotp import isotp_send, isotp_recv + +# 0x7e0 = Toyota +# 0x18DB33F1 for Honda? + + +def get_current_data_for_pid(pid): + # 01 xx = Show current data + isotp_send(panda, b"\x01" + bytes([pid]), 0x7e0) + return isotp_recv(panda, 0x7e8) + +def get_supported_pids(): + ret = [] + pid = 0 + while 1: + supported = struct.unpack(">I", get_current_data_for_pid(pid)[2:])[0] + for i in range(1 + pid, 0x21 + pid): + if supported & 0x80000000: + ret.append(i) + supported <<= 1 + pid += 0x20 + if pid not in ret: + break + return ret + +if __name__ == "__main__": + panda = Panda() + panda.set_safety_mode(CarParams.SafetyModel.elm327) + panda.can_clear(0) + + # 09 02 = Get VIN + isotp_send(panda, b"\x09\x02", 0x7df) + ret = isotp_recv(panda, 0x7e8) + hexdump(ret) + print("VIN: %s" % "".join(map(chr, ret[:2]))) + + # 03 = get DTCS + isotp_send(panda, b"\x03", 0x7e0) + dtcs = isotp_recv(panda, 0x7e8) + print("DTCs:", "".join(map(chr, dtcs[:2]))) + + supported_pids = get_supported_pids() + print("Supported PIDs:", supported_pids) + + while 1: + speed = struct.unpack(">B", get_current_data_for_pid(13)[2:])[0] # kph + rpm = struct.unpack(">H", get_current_data_for_pid(12)[2:])[0] / 4.0 # revs + throttle = struct.unpack(">B", get_current_data_for_pid(17)[2:])[0] / 255.0 * 100 # percent + temp = struct.unpack(">B", get_current_data_for_pid(5)[2:])[0] - 40 # degrees C + load = struct.unpack(">B", get_current_data_for_pid(4)[2:])[0] / 255.0 * 100 # percent + print("%d KPH, %d RPM, %.1f%% Throttle, %d deg C, %.1f%% load" % (speed, rpm, throttle, temp, load)) + time.sleep(0.2) diff --git a/panda/examples/tesla_tester.py b/panda/examples/tesla_tester.py new file mode 100755 index 0000000000..72f8a14358 --- /dev/null +++ b/panda/examples/tesla_tester.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import binascii +from opendbc.car.structs import CarParams +from panda import Panda + +def tesla_tester(): + p = Panda() + + body_bus_speed = 125 # Tesla Body busses (B, BF) are 125kbps, rest are 500kbps + body_bus_num = 1 # My TDC to OBD adapter has PT on bus0 BDY on bus1 and CH on bus2 + p.set_can_speed_kbps(body_bus_num, body_bus_speed) + + # Now set the panda from its default of SAFETY_SILENT (read only) to SAFETY_ALLOUTPUT + # Careful, as this will let us send any CAN messages we want (which could be very bad!) + print("Setting Panda to output mode...") + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + # BDY 0x248 is the MCU_commands message, which includes folding mirrors, opening the trunk, frunk, setting the cars lock state and more. + # For our test, we will edit the 3rd byte, which is MCU_lockRequest. 0x01 will lock, 0x02 will unlock: + print("Unlocking Tesla...") + p.can_send(0x248, b"\x00\x00\x02\x00\x00\x00\x00\x00", body_bus_num) + + #Or, we can set the first byte, MCU_frontHoodCommand + MCU_liftgateSwitch, to 0x01 to pop the frunk, or 0x04 to open/close the trunk (0x05 should open both) + print("Opening Frunk...") + p.can_send(0x248, b"\x01\x00\x00\x00\x00\x00\x00\x00", body_bus_num) + + #Back to safety... + print("Disabling output on Panda...") + p.set_safety_mode(CarParams.SafetyModel.silent) + + print("Reading VIN from 0x568. This is painfully slow and can take up to 3 minutes (1 minute per message; 3 messages needed for full VIN)...") + + vin = {} + while True: + #Read the VIN + can_recv = p.can_recv() + for address, dat, src in can_recv: + if src == body_bus_num: + if address == 1384: # 0x568 is VIN + vin_index = int(binascii.hexlify(dat)[:2]) # first byte is the index, 00, 01, 02 + vin_string = binascii.hexlify(dat)[2:] # rest of the string is the actual VIN data + vin[vin_index] = vin_string.decode("hex") + print("Got VIN index " + str(vin_index) + " data " + vin[vin_index]) + #if we have all 3 parts of the VIN, print it and break out of our while loop + if 0 in vin and 1 in vin and 2 in vin: + print("VIN: " + vin[0] + vin[1] + vin[2][:3]) + break + +if __name__ == "__main__": + tesla_tester() diff --git a/panda/pyproject.toml b/panda/pyproject.toml new file mode 100644 index 0000000000..660fc3e63e --- /dev/null +++ b/panda/pyproject.toml @@ -0,0 +1,76 @@ +[project] +name = "pandacan" +version = "0.0.10" +description = "Code powering the comma.ai panda" +readme = "README.md" +requires-python = ">=3.11,<3.13" # macOS doesn't work with 3.13 due to pycapnp from opendbc +license = {text = "MIT"} +authors = [{name = "comma.ai"}] +classifiers = [ + "Natural Language :: English", + "Programming Language :: Python :: 3", + "Topic :: System :: Hardware", +] +dependencies = [ + "libusb1", + "opendbc @ git+https://github.com/commaai/opendbc.git@master#egg=opendbc", +] + +[project.optional-dependencies] +dev = [ + "scons", + "pycryptodome >= 3.9.8", + "cffi", + "flaky", + "pytest", + "pytest-mock", + "pytest-timeout", + "pytest-randomly", + "ruff", + "mypy", + "setuptools", + "spidev; platform_system == 'Linux'", + "spidev2; platform_system == 'Linux'", +] + +[build-system] +requires = ["setuptools>=61", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["panda"] + +[tool.setuptools.package-dir] +panda = "." + +[tool.mypy] +# third-party packages +ignore_missing_imports = true + +# helpful warnings +warn_redundant_casts = true +warn_unreachable = true +warn_unused_ignores = true + +# restrict dynamic typing +warn_return_any = true + +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +line-length = 160 +target-version="py311" + +[tool.ruff.lint] +select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF100", "A"] +ignore = ["W292", "E741", "E402", "C408", "ISC003"] +flake8-implicit-str-concat.allow-multiline=false + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" + +[tool.pytest.ini_options] +addopts = "-Werror --strict-config --strict-markers --durations=10 --ignore-glob='*.sh' --ignore=tests/misra --ignore=tests/som --ignore=tests/hitl" +python_files = "test_*.py" +testpaths = [ + "tests/" +] \ No newline at end of file diff --git a/panda/python/__init__.py b/panda/python/__init__.py new file mode 100644 index 0000000000..aa5f49dd6f --- /dev/null +++ b/panda/python/__init__.py @@ -0,0 +1,805 @@ +# python library to interface with panda +import os +import sys +import time +import usb1 +import struct +import hashlib +import binascii +from functools import wraps, partial +from itertools import accumulate + +from opendbc.car.structs import CarParams + +from .base import BaseHandle +from .constants import FW_PATH, McuType +from .dfu import PandaDFU +from .spi import PandaSpiHandle, PandaSpiException, PandaProtocolMismatch +from .usb import PandaUsbHandle +from .utils import logger + +__version__ = '0.0.10' + +CANPACKET_HEAD_SIZE = 0x6 +DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64] +LEN_TO_DLC = {length: dlc for (dlc, length) in enumerate(DLC_TO_LEN)} +PANDA_CAN_CNT = 3 + + +def calculate_checksum(data): + res = 0 + for b in data: + res ^= b + return res + +def pack_can_buffer(arr, chunk=False, fd=False): + snds = [bytearray(), ] + for address, dat, bus in arr: + extended = 1 if address >= 0x800 else 0 + data_len_code = LEN_TO_DLC[len(dat)] + header = bytearray(CANPACKET_HEAD_SIZE) + word_4b = (address << 3) | (extended << 2) + header[0] = (data_len_code << 4) | (bus << 1) | int(fd) + header[1] = word_4b & 0xFF + header[2] = (word_4b >> 8) & 0xFF + header[3] = (word_4b >> 16) & 0xFF + header[4] = (word_4b >> 24) & 0xFF + header[5] = calculate_checksum(header[:5] + dat) + + snds[-1].extend(header) + snds[-1].extend(dat) + if chunk and len(snds[-1]) > 256: + snds.append(bytearray()) + + return snds + +def unpack_can_buffer(dat): + ret = [] + + while len(dat) >= CANPACKET_HEAD_SIZE: + data_len = DLC_TO_LEN[(dat[0]>>4)] + + header = dat[:CANPACKET_HEAD_SIZE] + + bus = (header[0] >> 1) & 0x7 + address = (header[4] << 24 | header[3] << 16 | header[2] << 8 | header[1]) >> 3 + + if (header[1] >> 1) & 0x1: + # returned + bus += 128 + if header[1] & 0x1: + # rejected + bus += 192 + + # we need more from the next transfer + if data_len > len(dat) - CANPACKET_HEAD_SIZE: + break + + assert calculate_checksum(dat[:(CANPACKET_HEAD_SIZE+data_len)]) == 0, "CAN packet checksum incorrect" + + data = dat[CANPACKET_HEAD_SIZE:(CANPACKET_HEAD_SIZE+data_len)] + dat = dat[(CANPACKET_HEAD_SIZE+data_len):] + + ret.append((address, data, bus)) + + return (ret, dat) + + +def ensure_version(desc, lib_field, panda_field, fn): + @wraps(fn) + def wrapper(self, *args, **kwargs): + lib_version = getattr(self, lib_field) + panda_version = getattr(self, panda_field) + if lib_version != panda_version: + raise RuntimeError(f"{desc} packet version mismatch: panda's firmware v{panda_version}, library v{lib_version}. Reflash panda.") + return fn(self, *args, **kwargs) + return wrapper +ensure_can_packet_version = partial(ensure_version, "CAN", "CAN_PACKET_VERSION", "can_version") +ensure_can_health_packet_version = partial(ensure_version, "CAN health", "CAN_HEALTH_PACKET_VERSION", "can_health_version") +ensure_health_packet_version = partial(ensure_version, "health", "HEALTH_PACKET_VERSION", "health_version") + + + +class Panda: + + SERIAL_DEBUG = 0 + SERIAL_SOM_DEBUG = 4 + + USB_VIDS = (0xbbaa, 0x3801) # 0x3801 is comma's registered VID + USB_PIDS = (0xddee, 0xddcc) + REQUEST_IN = usb1.ENDPOINT_IN | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE + REQUEST_OUT = usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE + + # from https://github.com/commaai/openpilot/blob/103b4df18cbc38f4129555ab8b15824d1a672bdf/cereal/log.capnp#L648 + HW_TYPE_UNKNOWN = b'\x00' + HW_TYPE_WHITE = b'\x01' + HW_TYPE_BLACK = b'\x03' + HW_TYPE_RED_PANDA = b'\x07' + HW_TYPE_TRES = b'\x09' + HW_TYPE_CUATRO = b'\x0a' + + CAN_PACKET_VERSION = 4 + HEALTH_PACKET_VERSION = 17 + CAN_HEALTH_PACKET_VERSION = 5 + HEALTH_STRUCT = struct.Struct(" 0: + print("INFO: some attached pandas are in DFU mode.") + + pandas = self.list() + if len(pandas) == 0: + print("INFO: panda not available") + return None + if len(pandas) == 1: + print(f"INFO: connecting to panda {pandas[0]}") + return pandas[0] + while True: + print("Multiple pandas available:") + pandas.sort() + for idx, serial in enumerate(pandas): + print(f"{[idx]}: {serial}") + try: + choice = int(input("Choose serial [0]:") or "0") + return pandas[choice] + except (ValueError, IndexError): + print("Enter a valid index.") + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def close(self): + if self._handle_open: + self._handle.close() + self._handle_open = False + if self._context is not None: + self._context.close() + + def connect(self, claim=True, wait=False): + self.close() + + self._handle = None + while self._handle is None: + # try USB first, then SPI + self._context, self._handle, serial, self.bootstub = self.usb_connect(self._connect_serial, claim=claim, no_error=wait) + if self._handle is None: + self._context, self._handle, serial, self.bootstub = self.spi_connect(self._connect_serial) + if not wait: + break + + if self._handle is None: + raise Exception("failed to connect to panda") + + self._serial = serial + self._connect_serial = serial + self._handle_open = True + self._mcu_type = self.get_mcu_type() + self.health_version, self.can_version, self.can_health_version = self.get_packets_versions() + logger.debug("connected") + + hw_type = self.get_type() + if hw_type not in self.SUPPORTED_DEVICES: + print("WARNING: Using deprecated HW") + + # disable openpilot's heartbeat checks + if self._disable_checks: + self.set_heartbeat_disabled() + self.set_power_save(0) + + # reset comms + self.can_reset_communications() + + # disable automatic CAN-FD switching + for bus in range(PANDA_CAN_CNT): + self.set_canfd_auto(bus, False) + + # set CAN speed + for bus in range(PANDA_CAN_CNT): + self.set_can_speed_kbps(bus, self._can_speed_kbps) + + @property + def spi(self) -> bool: + return isinstance(self._handle, PandaSpiHandle) + + @classmethod + def spi_connect(cls, serial, ignore_version=False): + try: + handle = PandaSpiHandle() + dat = handle.get_protocol_version() + except PandaSpiException: + return None, None, None, False + + spi_serial = binascii.hexlify(dat[:12]).decode() + pid = dat[13] + if pid not in (0xcc, 0xee): + raise PandaProtocolMismatch(f"invalid bootstub status ({pid=}). reflash panda") + bootstub = pid == 0xee + spi_version = dat[14] + + # did we get the right panda? + if serial is not None and spi_serial != serial: + return None, None, None, False + + # ensure our protocol version matches the panda + if (not ignore_version) and spi_version != handle.PROTOCOL_VERSION: + raise PandaProtocolMismatch(f"panda protocol mismatch: expected {handle.PROTOCOL_VERSION}, got {spi_version}. reflash panda") + + # got a device and all good + return None, handle, spi_serial, bootstub + + @classmethod + def usb_connect(cls, serial, claim=True, no_error=False): + handle, usb_serial, bootstub = None, None, None + context = usb1.USBContext() + context.open() + try: + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() in cls.USB_VIDS and device.getProductID() in cls.USB_PIDS: + try: + this_serial = device.getSerialNumber() + except Exception: + # Allow to ignore errors on reconnect. USB hubs need some time to initialize after panda reset + if not no_error: + logger.exception("failed to get serial number of panda") + continue + + if serial is None or this_serial == serial: + logger.debug("opening device %s %s", this_serial, hex(device.getProductID())) + + usb_serial = this_serial + bootstub = (device.getProductID() & 0xF0) == 0xe0 + handle = device.open() + if sys.platform not in ("win32", "cygwin", "msys", "darwin"): + handle.setAutoDetachKernelDriver(True) + if claim: + handle.claimInterface(0) + # handle.setInterfaceAltSetting(0, 0) # Issue in USB stack + + break + except Exception: + logger.exception("USB connect error") + + usb_handle = None + if handle is not None: + usb_handle = PandaUsbHandle(handle) + else: + context.close() + + return context, usb_handle, usb_serial, bootstub + + def is_connected_spi(self): + return isinstance(self._handle, PandaSpiHandle) + + def is_connected_usb(self): + return isinstance(self._handle, PandaUsbHandle) + + @classmethod + def list(cls, usb_only: bool = False): + ret = cls.usb_list() + if not usb_only: + ret += cls.spi_list() + return list(set(ret)) + + @classmethod + def usb_list(cls): + ret = [] + try: + with usb1.USBContext() as context: + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() in cls.USB_VIDS and device.getProductID() in cls.USB_PIDS: + try: + serial = device.getSerialNumber() + if len(serial) == 24: + ret.append(serial) + else: + logger.warning(f"found device with panda descriptors but invalid serial: {serial}", RuntimeWarning) + except Exception: + logger.exception("error connecting to panda") + except Exception: + logger.exception("exception while listing pandas") + return ret + + @classmethod + def spi_list(cls): + _, _, serial, _ = cls.spi_connect(None, ignore_version=True) + if serial is not None: + return [serial, ] + return [] + + def reset(self, enter_bootstub=False, enter_bootloader=False, reconnect=True): + # no response is expected since it resets right away + timeout = 5000 if isinstance(self._handle, PandaSpiHandle) else 15000 + try: + if enter_bootloader: + self._handle.controlWrite(Panda.REQUEST_IN, 0xd1, 0, 0, b'', timeout=timeout, expect_disconnect=True) + else: + if enter_bootstub: + self._handle.controlWrite(Panda.REQUEST_IN, 0xd1, 1, 0, b'', timeout=timeout, expect_disconnect=True) + else: + self._handle.controlWrite(Panda.REQUEST_IN, 0xd8, 0, 0, b'', timeout=timeout, expect_disconnect=True) + except Exception: + pass + + self.close() + if not enter_bootloader and reconnect: + self.reconnect() + + @property + def connected(self) -> bool: + return self._handle_open + + def reconnect(self): + if self._handle_open: + self.close() + + success = False + # wait up to 15 seconds + for _ in range(15*10): + try: + self.connect(claim=False, wait=True) + success = True + break + except Exception: + pass + time.sleep(0.1) + if not success: + raise Exception("reconnect failed") + + @staticmethod + def flasher_present(handle: BaseHandle) -> bool: + fr = handle.controlRead(Panda.REQUEST_IN, 0xb0, 0, 0, 0xc) + return fr[4:8] == b"\xde\xad\xd0\x0d" + + @staticmethod + def flash_static(handle, code, mcu_type): + assert mcu_type is not None, "must set valid mcu_type to flash" + + # confirm flasher is present + assert Panda.flasher_present(handle) + + # determine sectors to erase + apps_sectors_cumsum = accumulate(mcu_type.config.sector_sizes[1:]) + last_sector = next((i + 1 for i, v in enumerate(apps_sectors_cumsum) if v > len(code)), -1) + assert last_sector >= 1, "Binary too small? No sector to erase." + assert last_sector < 7, "Binary too large! Risk of overwriting provisioning chunk." + + # unlock flash + logger.info("flash: unlocking") + handle.controlWrite(Panda.REQUEST_IN, 0xb1, 0, 0, b'') + + # erase sectors + logger.info(f"flash: erasing sectors 1 - {last_sector}") + for i in range(1, last_sector + 1): + handle.controlWrite(Panda.REQUEST_IN, 0xb2, i, 0, b'') + + # flash over EP2 + STEP = 0x200 + logger.info("flash: flashing") + for i in range(0, len(code), STEP): + handle.bulkWrite(2, code[i:i + STEP]) + + # reset + logger.info("flash: resetting") + try: + handle.controlWrite(Panda.REQUEST_IN, 0xd8, 0, 0, b'', expect_disconnect=True) + except Exception: + pass + + def flash(self, fn=None, code=None, reconnect=True): + if self.up_to_date(fn=fn): + logger.info("flash: already up to date") + return + + hw_type = self.get_type() + if hw_type not in self.SUPPORTED_DEVICES: + raise RuntimeError(f"HW type {hw_type.hex()} is deprecated and can no longer be flashed.") + + if not fn: + fn = os.path.join(FW_PATH, self._mcu_type.config.app_fn) + assert os.path.isfile(fn) + logger.debug("flash: main version is %s", self.get_version()) + if not self.bootstub: + self.reset(enter_bootstub=True) + assert(self.bootstub) + + if code is None: + with open(fn, "rb") as f: + code = f.read() + + # get version + logger.debug("flash: bootstub version is %s", self.get_version()) + + # do flash + Panda.flash_static(self._handle, code, mcu_type=self._mcu_type) + + # reconnect + if reconnect: + self.reconnect() + + def recover(self, timeout: int | None = 60, reset: bool = True) -> bool: + dfu_serial = self.get_dfu_serial() + + if reset: + self.reset(enter_bootstub=True) + self.reset(enter_bootloader=True) + + if not self.wait_for_dfu(dfu_serial, timeout=timeout): + return False + + dfu = PandaDFU(dfu_serial) + dfu.recover() + + # reflash after recover + self.connect(True, True) + self.flash() + return True + + @staticmethod + def wait_for_dfu(dfu_serial: str | None, timeout: int | None = None) -> bool: + t_start = time.monotonic() + dfu_list = PandaDFU.list() + while (dfu_serial is None and len(dfu_list) == 0) or (dfu_serial is not None and dfu_serial not in dfu_list): + logger.debug("waiting for DFU...") + time.sleep(0.1) + if timeout is not None and (time.monotonic() - t_start) > timeout: + return False + dfu_list = PandaDFU.list() + return True + + @classmethod + def wait_for_panda(cls, serial: str | None, timeout: int) -> bool: + t_start = time.monotonic() + serials = cls.list() + while (serial is None and len(serials) == 0) or (serial is not None and serial not in serials): + logger.debug("waiting for panda...") + time.sleep(0.1) + if timeout is not None and (time.monotonic() - t_start) > timeout: + return False + serials = cls.list() + return True + + def up_to_date(self, fn=None) -> bool: + current = self.get_signature() + if fn is None: + fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn) + expected = Panda.get_signature_from_firmware(fn) + return (current == expected) + + def call_control_api(self, msg): + self._handle.controlWrite(Panda.REQUEST_OUT, msg, 0, 0, b'') + + # ******************* health ******************* + + @ensure_health_packet_version + def health(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, self.HEALTH_STRUCT.size) + a = self.HEALTH_STRUCT.unpack(dat) + return { + "uptime": a[0], + "voltage": a[1], + "current": a[2], + "safety_tx_blocked": a[3], + "safety_rx_invalid": a[4], + "tx_buffer_overflow": a[5], + "rx_buffer_overflow": a[6], + "faults": a[7], + "ignition_line": a[8], + "ignition_can": a[9], + "controls_allowed": a[10], + "car_harness_status": a[11], + "safety_mode": a[12], + "safety_param": a[13], + "fault_status": a[14], + "power_save_enabled": a[15], + "heartbeat_lost": a[16], + "alternative_experience": a[17], + "interrupt_load": a[18], + "fan_power": a[19], + "safety_rx_checks_invalid": a[20], + "spi_error_count": a[21], + "sbu1_voltage_mV": a[22], + "sbu2_voltage_mV": a[23], + "som_reset_triggered": a[24], + } + + @ensure_can_health_packet_version + def can_health(self, can_number): + LEC_ERROR_CODE = { + 0: "No error", + 1: "Stuff error", + 2: "Form error", + 3: "AckError", + 4: "Bit1Error", + 5: "Bit0Error", + 6: "CRCError", + 7: "NoChange", + } + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc2, int(can_number), 0, self.CAN_HEALTH_STRUCT.size) + a = self.CAN_HEALTH_STRUCT.unpack(dat) + return { + "bus_off": a[0], + "bus_off_cnt": a[1], + "error_warning": a[2], + "error_passive": a[3], + "last_error": LEC_ERROR_CODE[a[4]], + "last_stored_error": LEC_ERROR_CODE[a[5]], + "last_data_error": LEC_ERROR_CODE[a[6]], + "last_data_stored_error": LEC_ERROR_CODE[a[7]], + "receive_error_cnt": a[8], + "transmit_error_cnt": a[9], + "total_error_cnt": a[10], + "total_tx_lost_cnt": a[11], + "total_rx_lost_cnt": a[12], + "total_tx_cnt": a[13], + "total_rx_cnt": a[14], + "total_fwd_cnt": a[15], + "total_tx_checksum_error_cnt": a[16], + "can_speed": a[17], + "can_data_speed": a[18], + "canfd_enabled": a[19], + "brs_enabled": a[20], + "canfd_non_iso": a[21], + "irq0_call_rate": a[22], + "irq1_call_rate": a[23], + "irq2_call_rate": a[24], + "can_core_reset_count": a[25], + } + + # ******************* control ******************* + + def get_version(self): + return self._handle.controlRead(Panda.REQUEST_IN, 0xd6, 0, 0, 0x40).decode('utf8') + + @staticmethod + def get_signature_from_firmware(fn) -> bytes: + with open(fn, 'rb') as f: + f.seek(-128, 2) # Seek from end of file + return f.read(128) + + def get_signature(self) -> bytes: + part_1 = self._handle.controlRead(Panda.REQUEST_IN, 0xd3, 0, 0, 0x40) + part_2 = self._handle.controlRead(Panda.REQUEST_IN, 0xd4, 0, 0, 0x40) + return bytes(part_1 + part_2) + + def get_type(self): + return self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40) + + # Returns tuple with health packet version and CAN packet/USB packet version + def get_packets_versions(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xdd, 0, 0, 3) + if dat and len(dat) == 3: + a = struct.unpack("BBB", dat) + return (a[0], a[1], a[2]) + else: + return (0, 0, 0) + + def get_mcu_type(self) -> McuType: + hw_type = self.get_type() + if hw_type in Panda.H7_DEVICES: + return McuType.H7 + raise ValueError(f"unknown HW type: {hw_type}") + + def is_internal(self): + return self.get_type() in Panda.INTERNAL_DEVICES + + def get_serial(self): + """ + Returns the comma-issued dongle ID from our provisioning + """ + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 0, 0, 0x20) + hashsig, calc_hash = dat[0x1c:], hashlib.sha1(dat[0:0x1c]).digest()[0:4] + assert(hashsig == calc_hash) + return [dat[0:0x10].decode("utf8"), dat[0x10:0x10 + 10].decode("utf8")] + + def get_usb_serial(self): + """ + Returns the serial number reported from the USB descriptor; + matches the MCU UID + """ + return self._serial + + def get_dfu_serial(self): + return PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type) + + def get_uid(self): + """ + Returns the UID from the MCU + """ + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc3, 0, 0, 12) + return binascii.hexlify(dat).decode() + + def get_secret(self): + return self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 1, 0, 0x10) + + def get_interrupt_call_rate(self, irqnum): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc4, int(irqnum), 0, 4) + return struct.unpack("I", dat)[0] + + # ******************* configuration ******************* + + def set_alternative_experience(self, alternative_experience): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xdf, int(alternative_experience), 0, b'') + + def set_power_save(self, power_save_enabled=0): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe7, int(power_save_enabled), 0, b'') + + def set_safety_mode(self, mode=CarParams.SafetyModel.silent, param=0): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xdc, mode, param, b'') + + def set_obd(self, obd): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xdb, int(obd), 0, b'') + + def set_can_loopback(self, enable): + # set can loopback mode for all buses + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'') + + def set_can_enable(self, bus_num, enable): + # sets the can transceiver enable pin + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf4, int(bus_num), int(enable), b'') + + def set_can_speed_kbps(self, bus, speed): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xde, bus, int(speed * 10), b'') + + def set_can_data_speed_kbps(self, bus, speed): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf9, bus, int(speed * 10), b'') + + def set_canfd_non_iso(self, bus, non_iso): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xfc, bus, int(non_iso), b'') + + def set_canfd_auto(self, bus, auto): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe8, bus, int(auto), b'') + + def set_uart_baud(self, uart, rate): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, int(rate / 300), b'') + + def set_uart_parity(self, uart, parity): + # parity, 0=off, 1=even, 2=odd + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe2, uart, parity, b'') + + def set_uart_callback(self, uart, install): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe3, uart, int(install), b'') + + # ******************* can ******************* + + # The panda will NAK CAN writes when there is CAN congestion. + # libusb will try to send it again, with a max timeout. + # Timeout is in ms. If set to 0, the timeout is infinite. + CAN_SEND_TIMEOUT_MS = 10 + + def can_reset_communications(self): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xc0, 0, 0, b'') + + @ensure_can_packet_version + def can_send_many(self, arr, *, fd=False, timeout=CAN_SEND_TIMEOUT_MS): + snds = pack_can_buffer(arr, chunk=(not self.spi), fd=fd) + for tx in snds: + while len(tx) > 0: + bs = self._handle.bulkWrite(3, tx, timeout=timeout) + tx = tx[bs:] + + def can_send(self, addr, dat, bus, *, fd=False, timeout=CAN_SEND_TIMEOUT_MS): + self.can_send_many([[addr, dat, bus]], fd=fd, timeout=timeout) + + @ensure_can_packet_version + def can_recv(self): + dat = bytearray() + while True: + try: + dat = self._handle.bulkRead(1, 16384) # Max receive batch size + 2 extra reserve frames + break + except (usb1.USBErrorIO, usb1.USBErrorOverflow): + logger.error("CAN: BAD RECV, RETRYING") + time.sleep(0.1) + msgs, self.can_rx_overflow_buffer = unpack_can_buffer(self.can_rx_overflow_buffer + dat) + return msgs + + def can_clear(self, bus): + """Clears all messages from the specified internal CAN ringbuffer as + though it were drained. + + Args: + bus (int): can bus number to clear a tx queue, or 0xFFFF to clear the + global can rx queue. + + """ + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf1, bus, 0, b'') + + # ******************* serial ******************* + + def serial_read(self, port_number): + ret = [] + while 1: + lret = bytes(self._handle.controlRead(Panda.REQUEST_IN, 0xe0, port_number, 0, 0x40)) + if len(lret) == 0: + break + ret.append(lret) + return b''.join(ret) + + def serial_write(self, port_number, ln): + ret = 0 + if isinstance(ln, str): + ln = bytes(ln, 'utf-8') + for i in range(0, len(ln), 0x20): + ret += self._handle.bulkWrite(2, struct.pack("B", port_number) + ln[i:i + 0x20]) + return ret + + def send_heartbeat(self, engaged=True): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf3, engaged, 0, b'') + + # disable heartbeat checks for use outside of openpilot + # sending a heartbeat will reenable the checks + def set_heartbeat_disabled(self): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf8, 0, 0, b'') + + # ****************** Timer ***************** + def get_microsecond_timer(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xa8, 0, 0, 4) + return struct.unpack("I", dat)[0] + + # ******************* IR ******************* + def set_ir_power(self, percentage): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xb0, int(percentage), 0, b'') + + # ******************* Fan ****************** + def set_fan_power(self, percentage): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xb1, int(percentage), 0, b'') + + def get_fan_rpm(self): + dat = self._handle.controlRead(Panda.REQUEST_IN, 0xb2, 0, 0, 2) + a = struct.unpack("H", dat) + return a[0] + + # ****************** Siren ***************** + def set_siren(self, enabled): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf6, int(enabled), 0, b'') + + # ****************** Debug ***************** + + # arr: timer period + # ccrN: channel N pulse length + def set_clock_source_timer_params(self, arr, ccr1, ccr2, ccr3): + param1 = ((ccr1 & 0xFF) << 8) | (ccr2 & 0xFF) + param2 = ((ccr3 & 0xFF) << 8) | (arr & 0xFF) + self._handle.controlWrite(Panda.REQUEST_OUT, 0xe6, param1, param2, b'') + + def force_relay_drive(self, intercept_relay_drive, ignition_relay_drive): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xc5, (int(intercept_relay_drive) | int(ignition_relay_drive) << 1), 0, b'') + + def read_som_gpio(self) -> bool: + r = self._handle.controlRead(Panda.REQUEST_IN, 0xc6, 0, 0, 1) + return r[0] == 1 diff --git a/panda/python/base.py b/panda/python/base.py new file mode 100644 index 0000000000..ffe9353d62 --- /dev/null +++ b/panda/python/base.py @@ -0,0 +1,61 @@ +from abc import ABC, abstractmethod + +from .constants import McuType + +TIMEOUT = int(15 * 1e3) # default timeout, in milliseconds + +class BaseHandle(ABC): + """ + A handle to talk to a panda. + Borrows heavily from the libusb1 handle API. + """ + + @abstractmethod + def close(self) -> None: + ... + + @abstractmethod + def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT, expect_disconnect: bool = False): + ... + + @abstractmethod + def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT) -> bytes: + ... + + @abstractmethod + def bulkWrite(self, endpoint: int, data: bytes, timeout: int = TIMEOUT) -> int: + ... + + @abstractmethod + def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes: + ... + + +class BaseSTBootloaderHandle(ABC): + """ + A handle to talk to a panda while it's in the STM32 bootloader. + """ + + @abstractmethod + def get_mcu_type(self) -> McuType: + ... + + @abstractmethod + def close(self) -> None: + ... + + @abstractmethod + def clear_status(self) -> None: + ... + + @abstractmethod + def program(self, address: int, dat: bytes) -> None: + ... + + @abstractmethod + def erase_sector(self, sector: int) -> None: + ... + + @abstractmethod + def jump(self, address: int) -> None: + ... diff --git a/panda/python/constants.py b/panda/python/constants.py new file mode 100644 index 0000000000..5d1457a280 --- /dev/null +++ b/panda/python/constants.py @@ -0,0 +1,51 @@ +import os +import enum +from typing import NamedTuple + +BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../") +FW_PATH = os.path.join(BASEDIR, "board/obj/") + +USBPACKET_MAX_SIZE = 0x40 + +class McuConfig(NamedTuple): + mcu: str + mcu_idcode: int + sector_sizes: list[int] + sector_count: int # total sector count, used for MCU identification in DFU mode + uid_address: int + block_size: int + serial_number_address: int + app_address: int + app_fn: str + bootstub_address: int + bootstub_fn: str + + def sector_address(self, i): + # assume bootstub is in sector 0 + return self.bootstub_address + sum(self.sector_sizes[:i]) + + +H7Config = McuConfig( + "STM32H7", + 0x483, + [0x20000 for _ in range(7)], + 8, + 0x1FF1E800, + 0x400, + # there is an 8th sector, but we use that for the provisioning chunk, so don't program over that! + 0x080FFFC0, + 0x8020000, + "panda_h7.bin.signed", + 0x8000000, + "bootstub.panda_h7.bin", +) + +@enum.unique +class McuType(enum.Enum): + H7 = H7Config + + @property + def config(self): + return self.value + +MCU_TYPE_BY_IDCODE = {m.config.mcu_idcode: m for m in McuType} diff --git a/panda/python/dfu.py b/panda/python/dfu.py new file mode 100644 index 0000000000..624530cb20 --- /dev/null +++ b/panda/python/dfu.py @@ -0,0 +1,137 @@ +import os +import usb1 +import struct +import binascii + +from .base import BaseSTBootloaderHandle +from .spi import STBootloaderSPIHandle, PandaSpiException +from .usb import STBootloaderUSBHandle +from .constants import FW_PATH, McuType + + +class PandaDFU: + def __init__(self, dfu_serial: str | None): + # try USB, then SPI + handle: BaseSTBootloaderHandle | None + self._context, handle = PandaDFU.usb_connect(dfu_serial) + if handle is None: + self._context, handle = PandaDFU.spi_connect(dfu_serial) + + if handle is None: + raise Exception(f"failed to open DFU device {dfu_serial}") + + self._handle: BaseSTBootloaderHandle = handle + self._mcu_type: McuType = self._handle.get_mcu_type() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def close(self): + if self._handle is not None: + self._handle.close() + self._handle = None + if self._context is not None: + self._context.close() + + @staticmethod + def usb_connect(dfu_serial: str | None): + handle = None + context = usb1.USBContext() + context.open() + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11: + try: + this_dfu_serial = device.open().getASCIIStringDescriptor(3) + except Exception: + continue + + if this_dfu_serial == dfu_serial or dfu_serial is None: + handle = STBootloaderUSBHandle(device, device.open()) + break + + return context, handle + + @staticmethod + def spi_connect(dfu_serial: str | None): + handle = None + this_dfu_serial = None + + try: + handle = STBootloaderSPIHandle() + this_dfu_serial = PandaDFU.st_serial_to_dfu_serial(handle.get_uid(), handle.get_mcu_type()) + except PandaSpiException: + handle = None + + if dfu_serial is not None and dfu_serial != this_dfu_serial: + handle = None + + return None, handle + + @staticmethod + def usb_list() -> list[str]: + dfu_serials = [] + try: + with usb1.USBContext() as context: + for device in context.getDeviceList(skip_on_error=True): + if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11: + try: + dfu_serials.append(device.open().getASCIIStringDescriptor(3)) + except Exception: + pass + except Exception: + pass + return dfu_serials + + @staticmethod + def spi_list() -> list[str]: + try: + _, h = PandaDFU.spi_connect(None) + if h is not None: + dfu_serial = PandaDFU.st_serial_to_dfu_serial(h.get_uid(), h.get_mcu_type()) + return [dfu_serial, ] + except PandaSpiException: + pass + return [] + + @staticmethod + def st_serial_to_dfu_serial(st: str, mcu_type: McuType = McuType.H7): + if st is None or st == "none": + return None + try: + uid_base = struct.unpack("H" * 6, bytes.fromhex(st)) + if mcu_type == McuType.H7: + return binascii.hexlify(struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4], uid_base[3])).upper().decode("utf-8") + except struct.error: + return None + + def get_mcu_type(self) -> McuType: + return self._mcu_type + + def reset(self): + self._handle.jump(self._mcu_type.config.bootstub_address) + + def program_bootstub(self, code_bootstub): + self._handle.clear_status() + + # erase bootstub + app sectors + for i in (0, 1): + self._handle.erase_sector(i) + + # write bootstub + self._handle.program(self._mcu_type.config.bootstub_address, code_bootstub) + + def recover(self): + fn = os.path.join(FW_PATH, self._mcu_type.config.bootstub_fn) + with open(fn, "rb") as f: + code = f.read() + self.program_bootstub(code) + self.reset() + + @staticmethod + def list() -> list[str]: + ret = PandaDFU.usb_list() + ret += PandaDFU.spi_list() + return list(set(ret)) diff --git a/panda/python/serial.py b/panda/python/serial.py new file mode 100644 index 0000000000..c2e965b76c --- /dev/null +++ b/panda/python/serial.py @@ -0,0 +1,35 @@ +# mimic a python serial port +class PandaSerial: + def __init__(self, panda, port, baud): + self.panda = panda + self.port = port + self.panda.set_uart_parity(self.port, 0) + self._baudrate = baud + self.panda.set_uart_baud(self.port, baud) + self.buf = b"" + + def read(self, l=1): + tt = self.panda.serial_read(self.port) + if len(tt) > 0: + self.buf += tt + ret = self.buf[0:l] + self.buf = self.buf[l:] + return ret + + def write(self, dat): + return self.panda.serial_write(self.port, dat) + + def close(self): + pass + + def flush(self): + pass + + @property + def baudrate(self): + return self._baudrate + + @baudrate.setter + def baudrate(self, value): + self.panda.set_uart_baud(self.port, value) + self._baudrate = value diff --git a/panda/python/socketpanda.py b/panda/python/socketpanda.py new file mode 100644 index 0000000000..b80f1b1b20 --- /dev/null +++ b/panda/python/socketpanda.py @@ -0,0 +1,96 @@ +import socket +import struct + +# /** +# * struct canfd_frame - CAN flexible data rate frame structure +# * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition +# * @len: frame payload length in byte (0 .. CANFD_MAX_DLEN) +# * @flags: additional flags for CAN FD +# * @__res0: reserved / padding +# * @__res1: reserved / padding +# * @data: CAN FD frame payload (up to CANFD_MAX_DLEN byte) +# */ +# struct canfd_frame { +# canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ +# __u8 len; /* frame payload length in byte */ +# __u8 flags; /* additional flags for CAN FD */ +# __u8 __res0; /* reserved / padding */ +# __u8 __res1; /* reserved / padding */ +# __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8))); +# }; +CAN_HEADER_FMT = "=IBB2x" +CAN_HEADER_LEN = struct.calcsize(CAN_HEADER_FMT) +CAN_MAX_DLEN = 8 +CANFD_MAX_DLEN = 64 + +CANFD_BRS = 0x01 # bit rate switch (second bitrate for payload data) +CANFD_FDF = 0x04 # mark CAN FD for dual use of struct canfd_frame + +# socket.SO_RXQ_OVFL is missing +# https://github.com/torvalds/linux/blob/47ac09b91befbb6a235ab620c32af719f8208399/include/uapi/asm-generic/socket.h#L61 +SO_RXQ_OVFL = 40 + +import typing +@typing.no_type_check # mypy struggles with macOS here... +def create_socketcan(interface:str, recv_buffer_size:int, fd:bool) -> socket.socket: + # settings mostly from https://github.com/linux-can/can-utils/blob/master/candump.c + socketcan = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW) + if fd: + socketcan.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_FD_FRAMES, 1) + socketcan.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, recv_buffer_size) + # TODO: why is it always 2x the requested size? + assert socketcan.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF) == recv_buffer_size * 2 + # TODO: how to dectect and alert on buffer overflow? + socketcan.setsockopt(socket.SOL_SOCKET, SO_RXQ_OVFL, 1) + socketcan.bind((interface,)) + return socketcan + +# Panda class substitute for socketcan device (to support using the uds/iso-tp/xcp/ccp library) +class SocketPanda(): + def __init__(self, interface:str="can0", bus:int=0, fd:bool=False, recv_buffer_size:int=212992) -> None: + self.interface = interface + self.bus = bus + self.fd = fd + self.flags = CANFD_BRS | CANFD_FDF if fd else 0 + self.data_len = CANFD_MAX_DLEN if fd else CAN_MAX_DLEN + self.recv_buffer_size = recv_buffer_size + self.socket = create_socketcan(interface, recv_buffer_size, fd) + + def __del__(self): + self.socket.close() + + def get_serial(self) -> tuple[int, int]: + return (0, 0) # TODO: implemented in panda socketcan driver + + def get_version(self) -> int: + return 0 # TODO: implemented in panda socketcan driver + + def can_clear(self, bus:int) -> None: + # TODO: implemented in panda socketcan driver + self.socket.close() + self.socket = create_socketcan(self.interface, self.recv_buffer_size, self.fd) + + def set_safety_mode(self, mode:int, param=0) -> None: + pass # TODO: implemented in panda socketcan driver + + def has_obd(self) -> bool: + return False # TODO: implemented in panda socketcan driver + + def can_send(self, addr, dat, bus=0, timeout=0) -> None: + msg_len = len(dat) + msg_dat = dat.ljust(self.data_len, b'\x00') + can_frame = struct.pack(CAN_HEADER_FMT, addr, msg_len, self.flags) + msg_dat + self.socket.sendto(can_frame, (self.interface,)) + + def can_recv(self) -> list[tuple[int, bytes, int]]: + msgs = list() + while True: + try: + dat, _ = self.socket.recvfrom(self.recv_buffer_size, socket.MSG_DONTWAIT) + assert len(dat) == CAN_HEADER_LEN + self.data_len, f"ERROR: received {len(dat)} bytes" + can_id, msg_len, _ = struct.unpack(CAN_HEADER_FMT, dat[:CAN_HEADER_LEN]) + msg_dat = dat[CAN_HEADER_LEN:CAN_HEADER_LEN+msg_len] + msgs.append((can_id, msg_dat, self.bus)) + except BlockingIOError: + break # buffered data exhausted + return msgs diff --git a/panda/python/spi.py b/panda/python/spi.py new file mode 100644 index 0000000000..8ee5aecb9e --- /dev/null +++ b/panda/python/spi.py @@ -0,0 +1,468 @@ +import binascii +import os +import fcntl +import math +import time +import struct +import threading +from contextlib import contextmanager +from functools import reduce + +from .base import BaseHandle, BaseSTBootloaderHandle, TIMEOUT +from .constants import McuType, MCU_TYPE_BY_IDCODE, USBPACKET_MAX_SIZE +from .utils import logger + +try: + import spidev +except ImportError: + spidev = None +try: + import spidev2 +except ImportError: + spidev2 = None + +# Constants +SYNC = 0x5A +HACK = 0x79 +DACK = 0x85 +NACK = 0x1F +CHECKSUM_START = 0xAB + +MIN_ACK_TIMEOUT_MS = 100 +MAX_XFER_RETRY_COUNT = 5 + +SPI_BUF_SIZE = 4096 # from panda/board/drivers/spi.h +XFER_SIZE = SPI_BUF_SIZE - 0x40 # give some room for SPI protocol overhead + +DEV_PATH = "/dev/spidev0.0" + + +def crc8(data): + crc = 0xFF # standard init value + poly = 0xD5 # standard crc8: x8+x7+x6+x4+x2+1 + size = len(data) + for i in range(size - 1, -1, -1): + crc ^= data[i] + for _ in range(8): + if ((crc & 0x80) != 0): + crc = ((crc << 1) ^ poly) & 0xFF + else: + crc <<= 1 + return crc + + +class PandaSpiException(Exception): + pass + +class PandaProtocolMismatch(PandaSpiException): + pass + +class PandaSpiUnavailable(PandaSpiException): + pass + +class PandaSpiNackResponse(PandaSpiException): + pass + +class PandaSpiMissingAck(PandaSpiException): + pass + +class PandaSpiBadChecksum(PandaSpiException): + pass + +class PandaSpiTransferFailed(PandaSpiException): + pass + + +SPI_LOCK = threading.Lock() +SPI_DEVICES = {} +class SpiDevice: + """ + Provides locked, thread-safe access to a panda's SPI interface. + """ + + MAX_SPEED = 50000000 # max of the SDM845 + + def __init__(self, speed=MAX_SPEED): + assert speed <= self.MAX_SPEED + + if not os.path.exists(DEV_PATH): + raise PandaSpiUnavailable(f"SPI device not found: {DEV_PATH}") + if spidev is None: + raise PandaSpiUnavailable("spidev is not installed") + + with SPI_LOCK: + if speed not in SPI_DEVICES: + SPI_DEVICES[speed] = spidev.SpiDev() + SPI_DEVICES[speed].open(0, 0) + SPI_DEVICES[speed].max_speed_hz = speed + self._spidev = SPI_DEVICES[speed] + + @contextmanager + def acquire(self): + try: + SPI_LOCK.acquire() + fcntl.flock(self._spidev, fcntl.LOCK_EX) + yield self._spidev + finally: + fcntl.flock(self._spidev, fcntl.LOCK_UN) + SPI_LOCK.release() + + def close(self): + pass + + +class PandaSpiHandle(BaseHandle): + """ + A class that mimics a libusb1 handle for panda SPI communications. + """ + + PROTOCOL_VERSION = 2 + HEADER = struct.Struct(" None: + self.dev = SpiDevice() + if spidev2 is not None and "SPI2" in os.environ: + self._spi2 = spidev2.SPIBus("/dev/spidev0.0", "w+b", bits_per_word=8, speed_hz=50_000_000) + + # helpers + def _calc_checksum(self, data: bytes) -> int: + cksum = CHECKSUM_START + for b in data: + cksum ^= b + return cksum + + def _wait_for_ack(self, spi, ack_val: int, timeout: int, tx: int, length: int = 1) -> bytes: + timeout_s = max(MIN_ACK_TIMEOUT_MS, timeout) * 1e-3 + + start = time.monotonic() + while (timeout == 0) or ((time.monotonic() - start) < timeout_s): + dat = spi.xfer2([tx, ] * length) + if dat[0] == ack_val: + return bytes(dat) + elif dat[0] == NACK: + raise PandaSpiNackResponse + + raise PandaSpiMissingAck + + def _transfer_spidev(self, spi, endpoint: int, data, timeout: int, max_rx_len: int = 1000, expect_disconnect: bool = False) -> bytes: + max_rx_len = max(USBPACKET_MAX_SIZE, max_rx_len) + + logger.debug("- send header") + packet = self.HEADER.pack(SYNC, endpoint, len(data), max_rx_len) + packet += bytes([self._calc_checksum(packet), ]) + spi.xfer2(packet) + + logger.debug("- waiting for header ACK") + self._wait_for_ack(spi, HACK, MIN_ACK_TIMEOUT_MS, 0x11) + + logger.debug("- sending data") + packet = bytes([*data, self._calc_checksum(data)]) + spi.xfer2(packet) + + if expect_disconnect: + logger.debug("- expecting disconnect, returning") + return b"" + else: + logger.debug("- waiting for data ACK") + preread_len = USBPACKET_MAX_SIZE + 1 # read enough for a controlRead + dat = self._wait_for_ack(spi, DACK, timeout, 0x13, length=3 + preread_len) + + # get response length, then response + response_len = struct.unpack(" max_rx_len: + raise PandaSpiException(f"response length greater than max ({max_rx_len} {response_len})") + + # read rest + remaining = (response_len + 1) - preread_len + if remaining > 0: + dat += bytes(spi.readbytes(remaining)) + + dat = dat[:3 + response_len + 1] + if self._calc_checksum(dat) != 0: + raise PandaSpiBadChecksum + + return dat[3:-1] + + def _transfer_spidev2(self, spi, endpoint: int, data, timeout: int, max_rx_len: int = USBPACKET_MAX_SIZE, expect_disconnect: bool = False) -> bytes: + max_rx_len = max(USBPACKET_MAX_SIZE, max_rx_len) + + header = self.HEADER.pack(SYNC, endpoint, len(data), max_rx_len) + + header_ack = bytearray(1) + + # ACK + <2 bytes for response length> + data + checksum + data_rx = bytearray(3+max_rx_len+1) + + self._spi2.submitTransferList(spidev2.SPITransferList(( + # header + {'tx_buf': header + bytes([self._calc_checksum(header), ]), 'delay_usecs': 0, 'cs_change': True}, + {'rx_buf': header_ack, 'delay_usecs': 0, 'cs_change': True}, + + # send data + {'tx_buf': bytes([*data, self._calc_checksum(data)]), 'delay_usecs': 0, 'cs_change': True}, + {'rx_buf': data_rx, 'delay_usecs': 0, 'cs_change': True}, + ))) + + if header_ack[0] != HACK: + raise PandaSpiMissingAck + + if expect_disconnect: + logger.debug("- expecting disconnect, returning") + return b"" + else: + dat = bytes(data_rx) + if dat[0] != DACK: + if dat[0] == NACK: + raise PandaSpiNackResponse + + print("trying again") + dat = self._wait_for_ack(spi, DACK, timeout, 0x13, length=3 + max_rx_len) + + # get response length, then response + response_len = struct.unpack(" max_rx_len: + raise PandaSpiException(f"response length greater than max ({max_rx_len} {response_len})") + + dat = dat[:3 + response_len + 1] + if self._calc_checksum(dat) != 0: + raise PandaSpiBadChecksum + + return dat[3:-1] + + def _transfer(self, endpoint: int, data, timeout: int, max_rx_len: int = 1000, expect_disconnect: bool = False) -> bytes: + logger.debug("starting transfer: endpoint=%d, max_rx_len=%d", endpoint, max_rx_len) + logger.debug("==============================================") + + n = 0 + start_time = time.monotonic() + exc = PandaSpiException() + while (timeout == 0) or (time.monotonic() - start_time) < timeout*1e-3: + n += 1 + logger.debug("\ntry #%d", n) + with self.dev.acquire() as spi: + try: + fn = self._transfer_spidev + #fn = self._transfer_spidev2 + return fn(spi, endpoint, data, timeout, max_rx_len, expect_disconnect) + except PandaSpiException as e: + exc = e + logger.debug("SPI transfer failed, retrying", exc_info=True) + + # ensure slave is in a consistent state and ready for the next transfer + # (e.g. slave TX buffer isn't stuck full) + nack_cnt = 0 + attempts = 5 + while (nack_cnt <= 3) and (attempts > 0): + attempts -= 1 + try: + self._wait_for_ack(spi, NACK, MIN_ACK_TIMEOUT_MS, 0x11, length=XFER_SIZE//2) + nack_cnt += 1 + except PandaSpiException: + nack_cnt = 0 + + raise exc + + def get_protocol_version(self) -> bytes: + vers_str = b"VERSION" + def _get_version(spi) -> bytes: + spi.writebytes(vers_str) + + logger.debug("- waiting for echo") + start = time.monotonic() + while True: + version_bytes = spi.readbytes(len(vers_str) + 2) + if bytes(version_bytes).startswith(vers_str): + break + if (time.monotonic() - start) > 0.001: + raise PandaSpiMissingAck + + rlen = struct.unpack(" 1000: + raise PandaSpiException("response length greater than max") + + # get response + dat = spi.readbytes(rlen + 1) + resp = dat[:-1] + calculated_crc = crc8(bytes(version_bytes + resp)) + if calculated_crc != dat[-1]: + raise PandaSpiBadChecksum + return bytes(resp) + + exc = PandaSpiException() + with self.dev.acquire() as spi: + for _ in range(10): + try: + return _get_version(spi) + except PandaSpiException as e: + exc = e + logger.debug("SPI get protocol version failed, retrying", exc_info=True) + raise exc + + # libusb1 functions + def close(self): + self.dev.close() + + def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT, expect_disconnect: bool = False): + return self._transfer(0, struct.pack(" int: + mv = memoryview(data) + for x in range(math.ceil(len(data) / XFER_SIZE)): + self._transfer(endpoint, mv[XFER_SIZE*x:XFER_SIZE*(x+1)], timeout) + return len(data) + + def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes: + ret = b"" + for _ in range(math.ceil(length / XFER_SIZE)): + d = self._transfer(endpoint, [], timeout, max_rx_len=XFER_SIZE) + ret += d + if len(d) < XFER_SIZE: + break + return ret + + +class STBootloaderSPIHandle(BaseSTBootloaderHandle): + """ + Implementation of the STM32 SPI bootloader protocol described in: + https://www.st.com/resource/en/application_note/an4286-spi-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf + + NOTE: the bootloader's state machine is fragile and immediately gets into a bad state when + sending any junk, e.g. when using the panda SPI protocol. + """ + + SYNC = 0x5A + ACK = 0x79 + NACK = 0x1F + + def __init__(self): + self.dev = SpiDevice(speed=1000000) + + # say hello + try: + with self.dev.acquire() as spi: + spi.xfer([self.SYNC, ]) + try: + self._get_ack(spi, 0.1) + except (PandaSpiNackResponse, PandaSpiMissingAck): + # NACK ok here, will only ACK the first time + pass + + self._mcu_type = MCU_TYPE_BY_IDCODE[self.get_chip_id()] + except PandaSpiException: + raise PandaSpiException("failed to connect to panda") from None + + def _get_ack(self, spi, timeout=1.0): + data = 0x00 + start_time = time.monotonic() + while data not in (self.ACK, self.NACK) and (time.monotonic() - start_time < timeout): + data = spi.xfer([0x00, ])[0] + time.sleep(0) + spi.xfer([self.ACK, ]) + + if data == self.NACK: + raise PandaSpiNackResponse + elif data != self.ACK: + raise PandaSpiMissingAck + + def _cmd_no_retry(self, cmd: int, data: list[bytes] | None = None, read_bytes: int = 0, predata=None) -> bytes: + ret = b"" + with self.dev.acquire() as spi: + # sync + command + spi.xfer([self.SYNC, ]) + spi.xfer([cmd, cmd ^ 0xFF]) + self._get_ack(spi, timeout=0.01) + + # "predata" - for commands that send the first data without a checksum + if predata is not None: + spi.xfer(predata) + self._get_ack(spi) + + # send data + if data is not None: + for d in data: + if predata is not None: + spi.xfer(d + self._checksum(predata + d)) + else: + spi.xfer(d + self._checksum(d)) + self._get_ack(spi, timeout=20) + + # receive + if read_bytes > 0: + ret = spi.xfer([0x00, ]*(read_bytes + 1))[1:] + if data is None or len(data) == 0: + self._get_ack(spi) + + return bytes(ret) + + def _cmd(self, cmd: int, data: list[bytes] | None = None, read_bytes: int = 0, predata=None) -> bytes: + exc = PandaSpiException() + for n in range(MAX_XFER_RETRY_COUNT): + try: + return self._cmd_no_retry(cmd, data, read_bytes, predata) + except PandaSpiException as e: + exc = e + logger.debug("SPI transfer failed, %d retries left", MAX_XFER_RETRY_COUNT - n - 1, exc_info=True) + raise exc + + def _checksum(self, data: bytes) -> bytes: + if len(data) == 1: + ret = data[0] ^ 0xFF + else: + ret = reduce(lambda a, b: a ^ b, data) + return bytes([ret, ]) + + # *** Bootloader commands *** + + def read(self, address: int, length: int): + data = [struct.pack('>I', address), struct.pack('B', length - 1)] + return self._cmd(0x11, data=data, read_bytes=length) + + def get_bootloader_id(self): + return self.read(0x1FF1E7FE, 1) + + def get_chip_id(self) -> int: + r = self._cmd(0x02, read_bytes=3) + if r[0] != 1: # response length - 1 + raise PandaSpiException("incorrect response length") + return ((r[1] << 8) + r[2]) + + def go_cmd(self, address: int) -> None: + self._cmd(0x21, data=[struct.pack('>I', address), ]) + + # *** helpers *** + + def get_uid(self): + dat = self.read(McuType.H7.config.uid_address, 12) + return binascii.hexlify(dat).decode() + + def erase_sector(self, sector: int): + p = struct.pack('>H', 0) # number of sectors to erase + d = struct.pack('>H', sector) + self._cmd(0x44, data=[d, ], predata=p) + + # *** PandaDFU API *** + + def get_mcu_type(self): + return self._mcu_type + + def clear_status(self): + pass + + def close(self): + self.dev.close() + + def program(self, address, dat): + bs = 256 # max block size for writing to flash over SPI + dat += b"\xFF" * ((bs - len(dat)) % bs) + for i in range(len(dat) // bs): + block = dat[i * bs:(i + 1) * bs] + self._cmd(0x31, data=[ + struct.pack('>I', address + i*bs), + bytes([len(block) - 1]) + block, + ]) + + def jump(self, address): + self.go_cmd(self._mcu_type.config.bootstub_address) diff --git a/panda/python/usb.py b/panda/python/usb.py new file mode 100644 index 0000000000..0a012896be --- /dev/null +++ b/panda/python/usb.py @@ -0,0 +1,98 @@ +import struct + +from .base import BaseHandle, BaseSTBootloaderHandle, TIMEOUT +from .constants import McuType + +class PandaUsbHandle(BaseHandle): + def __init__(self, libusb_handle): + self._libusb_handle = libusb_handle + + def close(self): + self._libusb_handle.close() + + def controlWrite(self, request_type: int, request: int, value: int, index: int, data, timeout: int = TIMEOUT, expect_disconnect: bool = False): + return self._libusb_handle.controlWrite(request_type, request, value, index, data, timeout) + + def controlRead(self, request_type: int, request: int, value: int, index: int, length: int, timeout: int = TIMEOUT): + return self._libusb_handle.controlRead(request_type, request, value, index, length, timeout) + + def bulkWrite(self, endpoint: int, data: bytes, timeout: int = TIMEOUT) -> int: + return self._libusb_handle.bulkWrite(endpoint, data, timeout) # type: ignore + + def bulkRead(self, endpoint: int, length: int, timeout: int = TIMEOUT) -> bytes: + return self._libusb_handle.bulkRead(endpoint, length, timeout) # type: ignore + + + +class STBootloaderUSBHandle(BaseSTBootloaderHandle): + DFU_DNLOAD = 1 + DFU_UPLOAD = 2 + DFU_GETSTATUS = 3 + DFU_CLRSTATUS = 4 + DFU_ABORT = 6 + + def __init__(self, libusb_device, libusb_handle): + self._libusb_handle = libusb_handle + + # example from F4: lsusb -v | grep Flash + # iInterface 4 @Internal Flash /0x08000000/04*016Kg,01*064Kg,011*128Kg + for i in range(20): + desc = libusb_handle.getStringDescriptor(i, 0) + if desc is not None and desc.startswith("@Internal Flash"): + sector_count = sum([int(s.split('*')[0]) for s in desc.split('/')[-1].split(',')]) + break + mcu_by_sector_count = {m.config.sector_count: m for m in McuType} + assert sector_count in mcu_by_sector_count, f"Unkown MCU: {sector_count=}" + self._mcu_type = mcu_by_sector_count[sector_count] + + def _status(self) -> None: + while 1: + dat = self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6) + if dat[1] == 0: + break + + def _erase_page_address(self, address: int) -> None: + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 0, 0, b"\x41" + struct.pack("I", address)) + self._status() + + def get_mcu_type(self): + return self._mcu_type + + def erase_sector(self, sector: int): + self._erase_page_address(self._mcu_type.config.sector_address(sector)) + + def clear_status(self): + # Clear status + stat = self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6) + if stat[4] == 0xa: + self._libusb_handle.controlRead(0x21, self.DFU_CLRSTATUS, 0, 0, 0) + elif stat[4] == 0x9: + self._libusb_handle.controlWrite(0x21, self.DFU_ABORT, 0, 0, b"") + self._status() + stat = str(self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6)) + + def close(self): + self._libusb_handle.close() + + def program(self, address, dat): + # Set Address Pointer + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", address)) + self._status() + + # Program + bs = min(len(dat), self._mcu_type.config.block_size) + dat += b"\xFF" * ((bs - len(dat)) % bs) + for i in range(len(dat) // bs): + ldat = dat[i * bs:(i + 1) * bs] + print("programming %d with length %d" % (i, len(ldat))) + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 2 + i, 0, ldat) + self._status() + + def jump(self, address): + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", address)) + self._status() + try: + self._libusb_handle.controlWrite(0x21, self.DFU_DNLOAD, 2, 0, b"") + _ = str(self._libusb_handle.controlRead(0x21, self.DFU_GETSTATUS, 0, 0, 6)) + except Exception: + pass diff --git a/panda/python/utils.py b/panda/python/utils.py new file mode 100644 index 0000000000..55181e08b1 --- /dev/null +++ b/panda/python/utils.py @@ -0,0 +1,11 @@ +import os +import logging + +# set up logging +LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper() +logger = logging.getLogger('panda') +logger.setLevel(LOGLEVEL) + +handler = logging.StreamHandler() +handler.setFormatter(logging.Formatter('%(message)s')) +logger.addHandler(handler) diff --git a/panda/scripts/benchmark.py b/panda/scripts/benchmark.py new file mode 100755 index 0000000000..6063380479 --- /dev/null +++ b/panda/scripts/benchmark.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +import io +import os +import time +import pstats +import cProfile +from contextlib import contextmanager + +from panda import Panda, PandaDFU +from panda.tests.hitl.helpers import get_random_can_messages + + +PROFILE = "PROFILE" in os.environ + +@contextmanager +def print_time(desc): + if PROFILE: + pr = cProfile.Profile() + pr.enable() + start = time.perf_counter() + yield + end = time.perf_counter() + print(f"{end - start:.3f}s - {desc}") + if PROFILE: + pr.disable() + s = io.StringIO() + ps = pstats.Stats(pr, stream=s).sort_stats("cumtime") + ps.print_stats() + print(s.getvalue()) + + +if __name__ == "__main__": + with print_time("Panda()"): + p = Panda() + + with print_time("PandaDFU.list()"): + PandaDFU.list() + + fxn = [ + 'reset', + 'reconnect', + 'up_to_date', + 'health', + #'flash', + ] + for f in fxn: + with print_time(f"Panda.{f}()"): + getattr(p, f)() + + p.set_can_loopback(True) + + for n in range(6): + msgs = get_random_can_messages(int(10**n)) + with print_time(f"Panda.can_send_many() - {len(msgs)} msgs"): + p.can_send_many(msgs) + + with print_time("Panda.can_recv()"): + m = p.can_recv() diff --git a/panda/scripts/bulk_write_test.py b/panda/scripts/bulk_write_test.py new file mode 100755 index 0000000000..cc93be5578 --- /dev/null +++ b/panda/scripts/bulk_write_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +import os +import time +import threading +from typing import Any + +from opendbc.car.structs import CarParams +from panda import Panda + +JUNGLE = "JUNGLE" in os.environ +if JUNGLE: + from panda import PandaJungle + +# The TX buffers on pandas is 0x100 in length. +NUM_MESSAGES_PER_BUS = 10000 + +def flood_tx(panda): + print('Sending!') + msg = b"\xaa" * 4 + packet = [[0xaa, msg, 0], [0xaa, msg, 1], [0xaa, msg, 2]] * NUM_MESSAGES_PER_BUS + panda.can_send_many(packet, timeout=10000) + print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!") + +if __name__ == "__main__": + serials = Panda.list() + if JUNGLE: + sender = Panda() + receiver = PandaJungle() + else: + if len(serials) != 2: + raise Exception("Connect two pandas to perform this test!") + sender = Panda(serials[0]) + receiver = Panda(serials[1]) # type: ignore + receiver.set_safety_mode(CarParams.SafetyModel.allOutput) + + sender.set_safety_mode(CarParams.SafetyModel.allOutput) + + # Start transmisson + threading.Thread(target=flood_tx, args=(sender,)).start() + + # Receive as much as we can in a few second time period + rx: list[Any] = [] + old_len = 0 + start_time = time.time() + while time.time() - start_time < 3 or len(rx) > old_len: + old_len = len(rx) + print(old_len) + rx.extend(receiver.can_recv()) + print(f"Received {len(rx)} messages") diff --git a/panda/scripts/can_health.py b/panda/scripts/can_health.py new file mode 100755 index 0000000000..26de9cdab1 --- /dev/null +++ b/panda/scripts/can_health.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import time +import re +from panda import Panda + +RED = '\033[91m' +GREEN = '\033[92m' + +def colorize_errors(value): + if isinstance(value, str): + if re.search(r'(?i)No error', value): + return f'{GREEN}{value}\033[0m' + elif re.search(r'(?i)(? 0.1: + dd = chr(27) + "[2J" + dd += "%5.2f\n" % (sec_since_boot() - start) + for (addr, bus), dat_log in sorted(all_msgs.items()): + dd += "%d: %s(%6d): %s\n" % (bus, "%04X(%4d)" % (addr, addr), len(dat_log), binascii.hexlify(dat_log[-1]).decode()) + print(dd) + lp = sec_since_boot() + +if __name__ == "__main__": + can_printer() diff --git a/panda/scripts/check_fw_size.py b/panda/scripts/check_fw_size.py new file mode 100755 index 0000000000..03f78be20b --- /dev/null +++ b/panda/scripts/check_fw_size.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +import subprocess +from collections import defaultdict + + +def check_space(file, mcu): + MCUS = { + "H7": { + ".flash": 1024*1024, # FLASH + ".dtcmram": 128*1024, # DTCMRAM + ".itcmram": 64*1024, # ITCMRAM + ".axisram": 320*1024, # AXI SRAM + ".sram12": 32*1024, # SRAM1(16kb) + SRAM2(16kb) + ".sram4": 16*1024, # SRAM4 + ".backup_sram": 4*1024, # SRAM4 + }, + } + IGNORE_LIST = [ + ".ARM.attributes", + ".comment", + ".debug_line", + ".debug_info", + ".debug_abbrev", + ".debug_aranges", + ".debug_str", + ".debug_ranges", + ".debug_loc", + ".debug_frame", + ".debug_line_str", + ".debug_rnglists", + ".debug_loclists", + ] + FLASH = [ + ".isr_vector", + ".text", + ".rodata", + ".data" + ] + RAM = [ + ".data", + ".bss", + "._user_heap_stack" # _user_heap_stack considered free? + ] + + result = {} + calcs = defaultdict(int) + + output = str(subprocess.check_output(f"arm-none-eabi-size -x --format=sysv {file}", shell=True), 'utf-8') + + for row in output.split('\n'): + pop = False + line = row.split() + if len(line) == 3 and line[0].startswith('.'): + if line[0] in IGNORE_LIST: + continue + result[line[0]] = [line[1], line[2]] + if line[0] in FLASH: + calcs[".flash"] += int(line[1], 16) + pop = True + if line[0] in RAM: + calcs[".dtcmram"] += int(line[1], 16) + pop = True + if pop: + result.pop(line[0]) + + if len(result): + for line in result: + calcs[line] += int(result[line][0], 16) + + print(f"=======SUMMARY FOR {mcu} FILE {file}=======") + for line in calcs: + if line in MCUS[mcu]: + used_percent = (100 - (MCUS[mcu][line] - calcs[line]) / MCUS[mcu][line] * 100) + print(f"SECTION: {line} size: {MCUS[mcu][line]} USED: {calcs[line]}({used_percent:.2f}%) FREE: {MCUS[mcu][line] - calcs[line]}") + else: + print(line, calcs[line]) + print() + + +if __name__ == "__main__": + # red panda + check_space("../board/obj/bootstub.panda_h7.elf", "H7") + check_space("../board/obj/panda_h7.elf", "H7") + # jungle v2 + check_space("../board/jungle/obj/bootstub.panda_jungle_h7.elf", "H7") + check_space("../board/jungle/obj/panda_jungle_h7.elf", "H7") diff --git a/panda/scripts/debug_console.py b/panda/scripts/debug_console.py new file mode 100755 index 0000000000..8755be1498 --- /dev/null +++ b/panda/scripts/debug_console.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +import os +import sys +import time +import select +import codecs + +from panda import Panda + +setcolor = ["\033[1;32;40m", "\033[1;31;40m"] +unsetcolor = "\033[00m" + +port_number = int(os.getenv("PORT", "0")) +claim = os.getenv("CLAIM") is not None +no_color = os.getenv("NO_COLOR") is not None +no_reconnect = os.getenv("NO_RECONNECT") is not None + +if __name__ == "__main__": + while True: + try: + serials = Panda.list() + if os.getenv("SERIAL"): + serials = [x for x in serials if x == os.getenv("SERIAL")] + + pandas = [Panda(x, claim=claim) for x in serials] + decoders = [codecs.getincrementaldecoder('utf-8')() for _ in pandas] + + if not len(pandas): + print("no pandas found") + if no_reconnect: + sys.exit(0) + time.sleep(1) + continue + + if os.getenv("BAUD") is not None: + for panda in pandas: + panda.set_uart_baud(port_number, int(os.getenv("BAUD"))) # type: ignore + + while True: + for i, panda in enumerate(pandas): + while True: + ret = panda.serial_read(port_number) + if len(ret) > 0: + decoded = decoders[i].decode(ret) + if no_color: + sys.stdout.write(decoded) + else: + sys.stdout.write(setcolor[i] + decoded + unsetcolor) + sys.stdout.flush() + else: + break + if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): + ln = sys.stdin.readline() + if claim: + panda.serial_write(port_number, ln) + time.sleep(0.01) + except KeyboardInterrupt: + break + except Exception: + print("panda disconnected!") + time.sleep(0.5) diff --git a/panda/scripts/development/register_hashmap_spread.py b/panda/scripts/development/register_hashmap_spread.py new file mode 100755 index 0000000000..854ddd1401 --- /dev/null +++ b/panda/scripts/development/register_hashmap_spread.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import matplotlib.pyplot as plt + +HASHING_PRIME = 23 +REGISTER_MAP_SIZE = 0x3FF +BYTES_PER_REG = 4 + +# From ST32F413 datasheet +REGISTER_ADDRESS_REGIONS = [ + (0x40000000, 0x40007FFF), + (0x40010000, 0x400107FF), + (0x40011000, 0x400123FF), + (0x40012C00, 0x40014BFF), + (0x40015000, 0x400153FF), + (0x40015800, 0x40015BFF), + (0x40016000, 0x400167FF), + (0x40020000, 0x40021FFF), + (0x40023000, 0x400233FF), + (0x40023800, 0x40023FFF), + (0x40026000, 0x400267FF), + (0x50000000, 0x5003FFFF), + (0x50060000, 0x500603FF), + (0x50060800, 0x50060BFF), + (0x50060800, 0x50060BFF), + (0xE0000000, 0xE00FFFFF) +] + +def _hash(reg_addr): + return (((reg_addr >> 16) ^ ((((reg_addr + 1) & 0xFFFF) * HASHING_PRIME) & 0xFFFF)) & REGISTER_MAP_SIZE) + +# Calculate hash for each address +hashes = [] +double_hashes = [] +for (start_addr, stop_addr) in REGISTER_ADDRESS_REGIONS: + for addr in range(start_addr, stop_addr + 1, BYTES_PER_REG): + h = _hash(addr) + hashes.append(h) + double_hashes.append(_hash(h)) + +# Make histograms +plt.subplot(2, 1, 1) +plt.hist(hashes, bins=REGISTER_MAP_SIZE) +plt.title("Number of collisions per _hash") +plt.xlabel("Address") + +plt.subplot(2, 1, 2) +plt.hist(double_hashes, bins=REGISTER_MAP_SIZE) +plt.title("Number of collisions per double _hash") +plt.xlabel("Address") +plt.show() diff --git a/panda/scripts/echo.py b/panda/scripts/echo.py new file mode 100755 index 0000000000..0b27041254 --- /dev/null +++ b/panda/scripts/echo.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +from opendbc.car.structs import CarParams +from panda import Panda + +# This script is intended to be used in conjunction with the echo_loopback_test.py test script from panda jungle. +# It sends a reversed response back for every message received containing b"test". +if __name__ == "__main__": + p = Panda() + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_power_save(False) + + while True: + incoming = p.can_recv() + for message in incoming: + address, data, bus = message + if b'test' in data: + p.can_send(address, data[::-1], bus) diff --git a/panda/scripts/fan/fan_test.py b/panda/scripts/fan/fan_test.py new file mode 100755 index 0000000000..36a11715b3 --- /dev/null +++ b/panda/scripts/fan/fan_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +import time + +from panda import Panda + +if __name__ == "__main__": + p = Panda() + power = 0 + while True: + p.set_fan_power(power) + time.sleep(5) + print("Power: ", power, "RPM:", str(p.get_fan_rpm()), "Expected:", int(6500 * power / 100)) + power += 10 + power %= 110 diff --git a/panda/scripts/fan/fan_tuning.py b/panda/scripts/fan/fan_tuning.py new file mode 100755 index 0000000000..60ec72ec36 --- /dev/null +++ b/panda/scripts/fan/fan_tuning.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +import json +import time +import threading + +from panda import Panda + +def drain_serial(p): + ret = [] + while True: + d = p.serial_read(0) + if len(d) == 0: + break + ret.append(d) + return ret + + +fan_cmd = 0. + +def logger(event): + # requires a build with DEBUG_FAN + with Panda(claim=False) as p, open('/tmp/fan_log', 'w') as f: + power = None + target_rpm = None + rpm_fast = None + t = time.monotonic() + + drain_serial(p) + while not event.is_set(): + p.set_fan_power(fan_cmd) + + for l in drain_serial(p)[::-1]: + ns = l.decode('utf8').strip().split(' ') + if len(ns) == 4: + target_rpm, rpm_fast, power = (int(n, 16) for n in ns) + break + + dat = { + 't': time.monotonic() - t, + 'cmd_power': fan_cmd, + 'pwm_power': power, + 'target_rpm': target_rpm, + 'rpm_fast': rpm_fast, + 'rpm': p.get_fan_rpm(), + } + f.write(json.dumps(dat) + '\n') + time.sleep(1/16.) + p.set_fan_power(0) + +def get_overshoot_rpm(p, power): + global fan_cmd + + # make sure the fan is stopped completely + fan_cmd = 0. + while p.get_fan_rpm() > 100: + time.sleep(0.1) + time.sleep(3) + + # set it to 30% power to mimic going onroad + fan_cmd = power + max_rpm = 0 + max_power = 0 + for _ in range(70): + max_rpm = max(max_rpm, p.get_fan_rpm()) + max_power = max(max_power, p.health()['fan_power']) + time.sleep(0.1) + + # tolerate 10% overshoot + expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100 + overshoot = (max_rpm / expected_rpm) - 1 + + return overshoot, max_rpm, max_power + + +if __name__ == "__main__": + event = threading.Event() + threading.Thread(target=logger, args=(event, )).start() + + try: + p = Panda() + for power in range(10, 101, 10): + overshoot, max_rpm, max_power = get_overshoot_rpm(p, power) + print(f"Fan power {power}%: overshoot {overshoot:.2%}, Max RPM {max_rpm}, Max power {max_power}%") + finally: + event.set() diff --git a/panda/scripts/get_version.py b/panda/scripts/get_version.py new file mode 100755 index 0000000000..a0138122ba --- /dev/null +++ b/panda/scripts/get_version.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +from panda import Panda + +if __name__ == "__main__": + for p in Panda.list(): + pp = Panda(p) + print(f"{pp.get_serial()[0]}: {pp.get_version()}") diff --git a/panda/scripts/health_test.py b/panda/scripts/health_test.py new file mode 100755 index 0000000000..1195c2d7f2 --- /dev/null +++ b/panda/scripts/health_test.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import time +from panda import Panda + +if __name__ == "__main__": + i = 0 + pi = 0 + + panda = Panda() + while True: + st = time.monotonic() + while time.monotonic() - st < 1: + panda.health() + i += 1 + print(i, panda.health(), "\n") + print(f"Speed: {i - pi}Hz") + pi = i + diff --git a/panda/scripts/ir_test.py b/panda/scripts/ir_test.py new file mode 100755 index 0000000000..e41decf255 --- /dev/null +++ b/panda/scripts/ir_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +import time + +from panda import Panda + +power = 0 +if __name__ == "__main__": + p = Panda() + while True: + p.set_ir_power(power) + print("Power: ", str(power)) + time.sleep(1) + power += 10 + power %= 100 diff --git a/panda/scripts/loopback_test.py b/panda/scripts/loopback_test.py new file mode 100755 index 0000000000..0d446125c1 --- /dev/null +++ b/panda/scripts/loopback_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +import os +import time +import random +import argparse +from itertools import permutations + +from opendbc.car.structs import CarParams +from panda import Panda + +def get_test_string(): + return b"test" + os.urandom(10) + +def run_test(sleep_duration): + pandas = Panda.list() + print(pandas) + + if len(pandas) < 2: + raise Exception("Minimum two pandas are needed for test") + + run_test_w_pandas(pandas, sleep_duration) + +def run_test_w_pandas(pandas, sleep_duration): + h = [Panda(x) for x in pandas] + print("H", h) + + for hh in h: + hh.set_safety_mode(CarParams.SafetyModel.allOutput) + + # test both directions + for ho in permutations(list(range(len(h))), r=2): + print("***************** TESTING", ho) + + panda0, panda1 = h[ho[0]], h[ho[1]] + + # **** test health packet **** + print("health", ho[0], h[ho[0]].health()) + + # **** test can line loopback **** + for bus, obd in [(0, False), (1, False), (2, False), (1, True), (2, True)]: + print("\ntest can", bus) + # flush + cans_echo = panda0.can_recv() + cans_loop = panda1.can_recv() + + panda0.set_obd(None) + panda1.set_obd(None) + + if obd is True: + panda0.set_obd(bus) + panda1.set_obd(bus) + bus = 3 + + # send the characters + at = random.randint(1, 2000) + st = get_test_string()[0:8] + panda0.can_send(at, st, bus) + time.sleep(0.1) + + # check for receive + cans_echo = panda0.can_recv() + cans_loop = panda1.can_recv() + + print("Bus", bus, "echo", cans_echo, "loop", cans_loop) + + assert len(cans_echo) == 1 + assert len(cans_loop) == 1 + + assert cans_echo[0][0] == at + assert cans_loop[0][0] == at + + assert cans_echo[0][1] == st + assert cans_loop[0][1] == st + + assert cans_echo[0][2] == 0x80 | bus + if cans_loop[0][2] != bus: + print("EXPECTED %d GOT %d" % (bus, cans_loop[0][2])) + assert cans_loop[0][2] == bus + + print("CAN pass", bus, ho) + time.sleep(sleep_duration) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-n", type=int, help="Number of test iterations to run") + parser.add_argument("-sleep", type=int, help="Sleep time between tests", default=0) + args = parser.parse_args() + + if args.n is None: + while True: + run_test(sleep_duration=args.sleep) + else: + for _ in range(args.n): + run_test(sleep_duration=args.sleep) diff --git a/panda/scripts/make_release.sh b/panda/scripts/make_release.sh new file mode 100755 index 0000000000..cfecac3a16 --- /dev/null +++ b/panda/scripts/make_release.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +export CERT=/home/batman/xx/pandaextra/certs/release + +if [ ! -f "$CERT" ]; then + echo "No release cert found, cannot build release." + echo "You probably aren't looking to do this anyway." + exit +fi + +export RELEASE=1 +export BUILDER=DEV + +cd $DIR/../board +scons -u -c +rm obj/* +scons -u +cd obj +RELEASE_NAME=$(awk '{print $1}' version) +zip -j ../../release/panda-$RELEASE_NAME.zip version panda.bin.signed bootstub.panda.bin panda_h7.bin.signed bootstub.panda_h7.bin diff --git a/panda/scripts/message_drop_test.py b/panda/scripts/message_drop_test.py new file mode 100755 index 0000000000..c93074d051 --- /dev/null +++ b/panda/scripts/message_drop_test.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +import os +import usb1 +import time +import struct +import itertools +import threading +from typing import Any + +from opendbc.car.structs import CarParams +from panda import Panda + +JUNGLE = "JUNGLE" in os.environ +if JUNGLE: + from panda import PandaJungle + +# Generate unique messages +NUM_MESSAGES_PER_BUS = 10000 +messages = [bytes(struct.pack("Q", i)) for i in range(NUM_MESSAGES_PER_BUS)] +tx_messages = list(itertools.chain.from_iterable([[0xaa, msg, 0], [0xaa, msg, 1], [0xaa, msg, 2]] for msg in messages)) + +def flood_tx(panda): + print('Sending!') + transferred = 0 + while True: + try: + print(f"Sending block {transferred}-{len(tx_messages)}: ", end="") + panda.can_send_many(tx_messages[transferred:], timeout=10) + print("OK") + break + except usb1.USBErrorTimeout as e: + transferred += (e.transferred // 16) + print("timeout, transferred: ", transferred) + + print(f"Done sending {3*NUM_MESSAGES_PER_BUS} messages!") + +if __name__ == "__main__": + serials = Panda.list() + receiver: Panda | PandaJungle + if JUNGLE: + sender = Panda() + receiver = PandaJungle() + else: + if len(serials) != 2: + raise Exception("Connect two pandas to perform this test!") + sender = Panda(serials[0]) + receiver = Panda(serials[1]) + receiver.set_safety_mode(CarParams.SafetyModel.allOutput) + + sender.set_safety_mode(CarParams.SafetyModel.allOutput) + + # Start transmisson + threading.Thread(target=flood_tx, args=(sender,)).start() + + # Receive as much as we can, and stop when there hasn't been anything for a second + rx: list[Any] = [] + old_len = 0 + last_change = time.monotonic() + while time.monotonic() - last_change < 1: + if old_len < len(rx): + last_change = time.monotonic() + old_len = len(rx) + + rx.extend(receiver.can_recv()) + print(f"Received {len(rx)} messages") + + # Check if we received everything + for bus in range(3): + received_msgs = {bytes(m[1]) for m in filter(lambda m, b=bus: m[2] == b, rx)} # type: ignore + dropped_msgs = set(messages).difference(received_msgs) + print(f"Bus {bus} dropped msgs: {len(list(dropped_msgs))} / {len(messages)}") diff --git a/panda/scripts/read_flash_spi.py b/panda/scripts/read_flash_spi.py new file mode 100755 index 0000000000..133062be71 --- /dev/null +++ b/panda/scripts/read_flash_spi.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +from panda import Panda, PandaDFU + +if __name__ == "__main__": + try: + from openpilot.system.hardware import HARDWARE + HARDWARE.recover_internal_panda() + Panda.wait_for_dfu(None, 5) + except Exception: + pass + + p = PandaDFU(None) + cfg = p.get_mcu_type().config + + def readmem(addr, length, fn): + print(f"reading {hex(addr)} {hex(length)} bytes to {fn}") + max_size = 255 + with open(fn, "wb") as f: + to_read = length + while to_read > 0: + l = min(to_read, max_size) + dat = p._handle.read(addr, l) + assert len(dat) == l + f.write(dat) + + to_read -= len(dat) + addr += len(dat) + + addr = cfg.bootstub_address + for i, sector_size in enumerate(cfg.sector_sizes): + readmem(addr, sector_size, f"sector_{i}.bin") + addr += sector_size diff --git a/panda/scripts/read_st_flash.sh b/panda/scripts/read_st_flash.sh new file mode 100755 index 0000000000..65b0709f6c --- /dev/null +++ b/panda/scripts/read_st_flash.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +rm -f /tmp/dump_bootstub +rm -f /tmp/dump_main +dfu-util -a 0 -s 0x08000000 -U /tmp/dump_bootstub +dfu-util -a 0 -s 0x08004000 -U /tmp/dump_main + diff --git a/panda/scripts/reflash_internal_panda.py b/panda/scripts/reflash_internal_panda.py new file mode 100755 index 0000000000..e892faf876 --- /dev/null +++ b/panda/scripts/reflash_internal_panda.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +import time +from panda import Panda, PandaDFU + +class GPIO: + STM_RST_N = 124 + STM_BOOT0 = 134 + + +def gpio_init(pin, output): + with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f: + f.write(b"out" if output else b"in") + +def gpio_set(pin, high): + with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f: + f.write(b"1" if high else b"0") + + +if __name__ == "__main__": + for pin in (GPIO.STM_RST_N, GPIO.STM_BOOT0): + gpio_init(pin, True) + + # flash bootstub + print("resetting into DFU") + gpio_set(GPIO.STM_RST_N, 1) + gpio_set(GPIO.STM_BOOT0, 1) + time.sleep(0.2) + gpio_set(GPIO.STM_RST_N, 0) + gpio_set(GPIO.STM_BOOT0, 0) + + # bootstub flash takes 2s and is limited by the 255 byte flashing chunk size + print("flashing bootstub") + assert Panda.wait_for_dfu(None, 5) + PandaDFU(None).recover() + + print("flashing app") + assert Panda.wait_for_panda(None, 5) + p = Panda() + assert p.bootstub + p.flash() diff --git a/panda/scripts/relay_test.py b/panda/scripts/relay_test.py new file mode 100755 index 0000000000..f8dd1b2244 --- /dev/null +++ b/panda/scripts/relay_test.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +import time +from opendbc.car.structs import CarParams +from panda import Panda + +p = Panda() + +while True: + p.set_safety_mode(CarParams.SafetyModel.toyota) + p.send_heartbeat() + print("ON") + time.sleep(1) + p.set_safety_mode(CarParams.SafetyModel.noOutput) + p.send_heartbeat() + print("OFF") + time.sleep(1) + diff --git a/panda/scripts/restore_flash_spi.py b/panda/scripts/restore_flash_spi.py new file mode 100755 index 0000000000..c23b298289 --- /dev/null +++ b/panda/scripts/restore_flash_spi.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +from panda import Panda, PandaDFU, STBootloaderSPIHandle + +if __name__ == "__main__": + try: + from openpilot.system.hardware import HARDWARE + HARDWARE.recover_internal_panda() + Panda.wait_for_dfu(None, 5) + except Exception: + pass + + p = PandaDFU(None) + assert isinstance(p._handle, STBootloaderSPIHandle) + cfg = p.get_mcu_type().config + + print("restoring from backup...") + addr = cfg.bootstub_address + for i, sector_size in enumerate(cfg.sector_sizes): + print(f"- sector #{i}") + p._handle.erase_sector(i) + with open(f"sector_{i}.bin", "rb") as f: + dat = f.read() + assert len(dat) == sector_size + p._handle.program(addr, dat) + addr += len(dat) + + p.reset() diff --git a/panda/scripts/som_debug.sh b/panda/scripts/som_debug.sh new file mode 100755 index 0000000000..6f0a86537c --- /dev/null +++ b/panda/scripts/som_debug.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +PYTHONUNBUFFERED=1 NO_COLOR=1 CLAIM=1 PORT=4 ./debug_console.py diff --git a/panda/scripts/spam_can.py b/panda/scripts/spam_can.py new file mode 100755 index 0000000000..337859ffcb --- /dev/null +++ b/panda/scripts/spam_can.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import os +import random + +from opendbc.car.structs import CarParams +from panda import Panda + +def get_test_string(): + return b"test" + os.urandom(10) + +if __name__ == "__main__": + p = Panda() + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + print("Spamming all buses...") + while True: + at = random.randint(1, 2000) + st = get_test_string()[0:8] + bus = random.randint(0, 2) + p.can_send(at, st, bus) + # print("Sent message on bus: ", bus) diff --git a/panda/scripts/standalone_test.py b/panda/scripts/standalone_test.py new file mode 100755 index 0000000000..528c21cc9e --- /dev/null +++ b/panda/scripts/standalone_test.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import struct +import time + +from opendbc.car.structs import CarParams +from panda import Panda + +if __name__ == "__main__": + p = Panda() + print(p.get_serial()) + print(p.health()) + + t1 = time.time() + for _ in range(100): + p.get_serial() + t2 = time.time() + print("100 requests took %.2f ms" % ((t2 - t1) * 1000)) + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + a = 0 + while True: + # flood + msg = b"\xaa" * 4 + struct.pack("I", a) + p.can_send(0xaa, msg, 0) + p.can_send(0xaa, msg, 1) + p.can_send(0xaa, msg, 4) + time.sleep(0.01) + + dat = p.can_recv() + if len(dat) > 0: + print(dat) + a += 1 diff --git a/panda/scripts/test_canfd.py b/panda/scripts/test_canfd.py new file mode 100755 index 0000000000..ee61e8c30e --- /dev/null +++ b/panda/scripts/test_canfd.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +import os +import time +import random +from collections import defaultdict +from opendbc.car.structs import CarParams +from panda import Panda, calculate_checksum, DLC_TO_LEN +from panda import PandaJungle +from panda.tests.hitl.helpers import time_many_sends + +H7_HW_TYPES = [Panda.HW_TYPE_RED_PANDA, Panda.HW_TYPE_RED_PANDA_V2] +JUNGLE_SERIAL = os.getenv("JUNGLE") +H7_PANDAS_EXCLUDE = [] # type: ignore +if os.getenv("H7_PANDAS_EXCLUDE"): + H7_PANDAS_EXCLUDE = os.getenv("H7_PANDAS_EXCLUDE").strip().split(" ") # type: ignore + +def panda_reset(): + panda_serials = [] + + panda_jungle = PandaJungle(JUNGLE_SERIAL) + panda_jungle.set_can_silent(True) + panda_jungle.set_panda_power(False) + time.sleep(1) + panda_jungle.set_panda_power(True) + time.sleep(4) + + for serial in Panda.list(): + if serial not in H7_PANDAS_EXCLUDE: + with Panda(serial=serial) as p: + if p.get_type() in H7_HW_TYPES: + p.reset() + panda_serials.append(serial) + + print("test pandas", panda_serials) + assert len(panda_serials) == 2, "Two H7 pandas required" + + return panda_serials + +def panda_init(serial, enable_canfd=False, enable_non_iso=False): + p = Panda(serial=serial) + p.set_power_save(False) + for bus in range(3): + p.set_can_speed_kbps(0, 500) + if enable_canfd: + p.set_can_data_speed_kbps(bus, 2000) + if enable_non_iso: + p.set_canfd_non_iso(bus, True) + p.set_safety_mode(CarParams.SafetyModel.allOutput) + return p + +def test_canfd_throughput(p, p_recv=None): + two_pandas = p_recv is not None + p.set_safety_mode(CarParams.SafetyModel.allOutput) + if two_pandas: + p_recv.set_safety_mode(CarParams.SafetyModel.allOutput) + # enable output mode + else: + p.set_can_loopback(True) + + tests = [ + [500, 1000, 2000], # speeds + [93, 87, 78], # saturation thresholds + ] + + for i in range(len(tests[0])): + # set bus 0 data speed to speed + p.set_can_data_speed_kbps(0, tests[0][i]) + if p_recv is not None: + p_recv.set_can_data_speed_kbps(0, tests[0][i]) + time.sleep(0.05) + + comp_kbps = time_many_sends(p, 0, p_recv=p_recv, msg_count=400, two_pandas=two_pandas, msg_len=64) + + # bit count from https://en.wikipedia.org/wiki/CAN_bus + saturation_pct = (comp_kbps / tests[0][i]) * 100.0 + assert saturation_pct > tests[1][i] + assert saturation_pct < 100 + +def canfd_test(p_send, p_recv): + for n in range(100): + sent_msgs = defaultdict(set) + to_send = [] + for _ in range(200): + bus = random.randrange(3) + for dlc in range(len(DLC_TO_LEN)): + address = random.randrange(1, 1<<29) + data = bytearray(random.getrandbits(8) for _ in range(DLC_TO_LEN[dlc])) + if len(data) >= 2: + data[0] = calculate_checksum(data[1:] + bytes(str(address), encoding="utf-8")) + to_send.append([address, data, bus]) + sent_msgs[bus].add((address, bytes(data))) + + p_send.can_send_many(to_send, timeout=0) + + start_time = time.monotonic() + while (time.monotonic() - start_time < 1) and any(len(x) > 0 for x in sent_msgs.values()): + incoming = p_recv.can_recv() + for msg in incoming: + address, data, bus = msg + if len(data) >= 2: + assert calculate_checksum(data[1:] + bytes(str(address), encoding="utf-8")) == data[0] + k = (address, bytes(data)) + assert k in sent_msgs[bus], f"message {k} was never sent on bus {bus}" + sent_msgs[bus].discard(k) + + for bus in range(3): + assert not len(sent_msgs[bus]), f"loop {n}: bus {bus} missing {len(sent_msgs[bus])} messages" + +def setup_test(enable_non_iso=False): + panda_serials = panda_reset() + + p_send = panda_init(panda_serials[0], enable_canfd=False, enable_non_iso=enable_non_iso) + p_recv = panda_init(panda_serials[1], enable_canfd=True, enable_non_iso=enable_non_iso) + + # Check that sending panda CAN FD and BRS are turned off + for bus in range(3): + health = p_send.can_health(bus) + assert not health["canfd_enabled"] + assert not health["brs_enabled"] + assert health["canfd_non_iso"] == enable_non_iso + + # Receiving panda sends dummy CAN FD message that should enable CAN FD on sender side + for bus in range(3): + p_recv.can_send(0x200, b"dummymessage", bus) + p_recv.can_recv() + p_send.can_recv() + + # Check if all tested buses on sending panda have swithed to CAN FD with BRS + for bus in range(3): + health = p_send.can_health(bus) + assert health["canfd_enabled"] + assert health["brs_enabled"] + assert health["canfd_non_iso"] == enable_non_iso + + return p_send, p_recv + +def main(): + print("[TEST CAN-FD]") + p_send, p_recv = setup_test() + canfd_test(p_send, p_recv) + + print("[TEST CAN-FD non-ISO]") + p_send, p_recv = setup_test(enable_non_iso=True) + canfd_test(p_send, p_recv) + + print("[TEST CAN-FD THROUGHPUT]") + panda_serials = panda_reset() + p_send = panda_init(panda_serials[0], enable_canfd=True) + p_recv = panda_init(panda_serials[1], enable_canfd=True) + test_canfd_throughput(p_send, p_recv) + +if __name__ == "__main__": + main() diff --git a/panda/setup.sh b/panda/setup.sh new file mode 100755 index 0000000000..042b4978af --- /dev/null +++ b/panda/setup.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +PLATFORM=$(uname -s) + +echo "installing dependencies" +if [[ $PLATFORM == "Darwin" ]]; then + export HOMEBREW_NO_AUTO_UPDATE=1 + brew install --cask gcc-arm-embedded + brew install python3 gcc@13 +elif [[ $PLATFORM == "Linux" ]]; then + # for AGNOS since we clear the apt lists + if [[ ! -d /"var/lib/apt/" ]]; then + sudo apt update + fi + + sudo apt-get install -y --no-install-recommends \ + curl ca-certificates \ + make g++ git libnewlib-arm-none-eabi \ + libusb-1.0-0 \ + gcc-arm-none-eabi \ + python3-dev python3-pip python3-venv +else + echo "WARNING: unsupported platform. skipping apt/brew install." +fi + +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh + + # doesn't require sourcing on all platforms + set +e + source $HOME/.local/bin/env + set -e +fi + +export UV_PROJECT_ENVIRONMENT="$DIR/.venv" +uv sync --all-extras --upgrade +source "$DIR/.venv/bin/activate" diff --git a/panda/test.sh b/panda/test.sh new file mode 100755 index 0000000000..6412ce74bb --- /dev/null +++ b/panda/test.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +# *** env setup *** +source ./setup.sh + +# *** build *** +scons -j8 + +# *** lint *** +ruff check . +mypy python/ + + +# *** test *** + +# TODO: make randomly work +pytest --randomly-dont-reorganize tests/ diff --git a/panda/tests/hitl/1_program.py b/panda/tests/hitl/1_program.py new file mode 100644 index 0000000000..09c8b86744 --- /dev/null +++ b/panda/tests/hitl/1_program.py @@ -0,0 +1,95 @@ +import os +import time +import pytest + +from panda import Panda, PandaDFU, McuType, BASEDIR + + +def check_signature(p): + assert not p.bootstub, "Flashed firmware not booting. Stuck in bootstub." + assert p.up_to_date() + + +def test_dfu(p): + app_mcu_type = p.get_mcu_type() + dfu_serial = p.get_dfu_serial() + + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + assert Panda.wait_for_dfu(dfu_serial, timeout=19), "failed to enter DFU" + + dfu = PandaDFU(dfu_serial) + assert dfu.get_mcu_type() == app_mcu_type + + assert dfu_serial in PandaDFU.list() + + dfu._handle.clear_status() + dfu.reset() + p.reconnect() + +# TODO: make more comprehensive bootstub tests and run on a few production ones + current +# TODO: also test release-signed app +@pytest.mark.timeout(30) +def test_known_bootstub(p): + """ + Test that compiled app can work with known production bootstub + """ + known_bootstubs = { + McuType.H7: ["bootstub.panda_h7.bin"], + } + + for kb in known_bootstubs[p.get_mcu_type()]: + app_ids = (p.get_mcu_type(), p.get_usb_serial()) + assert None not in app_ids + + p.reset(enter_bootstub=True) + p.reset(enter_bootloader=True) + + dfu_serial = p.get_dfu_serial() + assert Panda.wait_for_dfu(dfu_serial, timeout=30) + + dfu = PandaDFU(dfu_serial) + with open(os.path.join(BASEDIR, "tests/hitl/known_bootstub", kb), "rb") as f: + code = f.read() + + dfu.program_bootstub(code) + dfu.reset() + + p.connect(claim=False, wait=True) + + # check for MCU or serial mismatch + with Panda(p._serial, claim=False) as np: + bootstub_ids = (np.get_mcu_type(), np.get_usb_serial()) + assert app_ids == bootstub_ids + + # ensure we can flash app and it jumps to app + p.flash() + check_signature(p) + assert not p.bootstub + +@pytest.mark.timeout(25) +def test_recover(p): + assert p.recover(timeout=30) + check_signature(p) + +@pytest.mark.timeout(25) +def test_flash(p): + # test flash from bootstub + serial = p._serial + assert serial is not None + p.reset(enter_bootstub=True) + p.close() + time.sleep(2) + + with Panda(serial) as np: + assert np.bootstub + assert np._serial == serial + np.flash() + + p.reconnect() + p.reset() + check_signature(p) + + # test flash from app + p.flash() + check_signature(p) diff --git a/panda/tests/hitl/2_health.py b/panda/tests/hitl/2_health.py new file mode 100644 index 0000000000..8fac3e9603 --- /dev/null +++ b/panda/tests/hitl/2_health.py @@ -0,0 +1,65 @@ +import time + +from opendbc.car.hyundai.values import HyundaiSafetyFlags +from opendbc.car.structs import CarParams +from panda import Panda + + +def test_voltage(p): + for _ in range(10): + voltage = p.health()['voltage'] + assert ((voltage > 11000) and (voltage < 13000)) + time.sleep(0.1) + +def test_hw_type(p): + """ + hw type should be same in bootstub as application + """ + + hw_type = p.get_type() + mcu_type = p.get_mcu_type() + assert mcu_type is not None + + app_uid = p.get_uid() + usb_serial = p.get_usb_serial() + assert app_uid == usb_serial + + p.reset(enter_bootstub=True, reconnect=True) + p.close() + time.sleep(3) + with Panda(p.get_usb_serial()) as pp: + assert pp.bootstub + assert pp.get_type() == hw_type, "Bootstub and app hw type mismatch" + assert pp.get_mcu_type() == mcu_type, "Bootstub and app MCU type mismatch" + assert pp.get_uid() == app_uid + +def test_heartbeat(p, panda_jungle): + panda_jungle.set_ignition(True) + # TODO: add more cases here once the tests aren't super slow + p.set_safety_mode(mode=CarParams.SafetyModel.hyundai, param=HyundaiSafetyFlags.LONG) + p.send_heartbeat() + assert p.health()['safety_mode'] == CarParams.SafetyModel.hyundai + assert p.health()['safety_param'] == HyundaiSafetyFlags.LONG + + # shouldn't do anything once we're in a car safety mode + p.set_heartbeat_disabled() + + time.sleep(6.) + + h = p.health() + assert h['heartbeat_lost'] + assert h['safety_mode'] == CarParams.SafetyModel.silent + assert h['safety_param'] == 0 + assert h['controls_allowed'] == 0 + +def test_microsecond_timer(p): + start_time = p.get_microsecond_timer() + time.sleep(1) + end_time = p.get_microsecond_timer() + + # account for uint32 overflow + if end_time < start_time: + end_time += 2**32 + + time_diff = (end_time - start_time) / 1e6 + assert 0.98 < time_diff < 1.02, f"Timer not running at the correct speed! (got {time_diff:.2f}s instead of 1.0s)" diff --git a/panda/tests/hitl/3_usb.py b/panda/tests/hitl/3_usb.py new file mode 100644 index 0000000000..f3ae43e2c1 --- /dev/null +++ b/panda/tests/hitl/3_usb.py @@ -0,0 +1,92 @@ +import time +import pytest +from flaky import flaky + +from opendbc.car.structs import CarParams +from panda import Panda +from panda.tests.hitl.helpers import time_many_sends + +pytestmark = [ + pytest.mark.test_panda_types((Panda.HW_TYPE_RED_PANDA, )) +] + +def test_can_loopback(p): + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + + for bus in (0, 1, 2): + # set bus 0 speed to 5000 + p.set_can_speed_kbps(bus, 500) + + # send a message on bus 0 + p.can_send(0x1aa, b"message", bus) + + # confirm receive both on loopback and send receipt + time.sleep(0.05) + r = p.can_recv() + sr = [x for x in r if x[2] == 0x80 | bus] + lb = [x for x in r if x[2] == bus] + assert len(sr) == 1 + assert len(lb) == 1 + + # confirm data is correct + assert 0x1aa == sr[0][0] == lb[0][0] + assert b"message" == sr[0][1] == lb[0][1] + +def test_reliability(p): + MSG_COUNT = 100 + + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + p.set_can_speed_kbps(0, 1000) + + addrs = list(range(100, 100 + MSG_COUNT)) + ts = [(j, b"\xaa" * 8, 0) for j in addrs] + + for _ in range(100): + st = time.monotonic() + + p.can_send_many(ts) + + r = [] + while len(r) < 200 and (time.monotonic() - st) < 0.5: + r.extend(p.can_recv()) + + sent_echo = [x for x in r if x[2] == 0x80] + loopback_resp = [x for x in r if x[2] == 0] + + assert sorted([x[0] for x in loopback_resp]) == addrs + assert sorted([x[0] for x in sent_echo]) == addrs + assert len(r) == 200 + + # take sub 20ms + et = (time.monotonic() - st) * 1000.0 + assert et < 20 + +@flaky(max_runs=6, min_passes=1) +def test_throughput(p): + # enable output mode + p.set_safety_mode(CarParams.SafetyModel.allOutput) + + # enable CAN loopback mode + p.set_can_loopback(True) + + for speed in [10, 20, 50, 100, 125, 250, 500, 1000]: + # set bus 0 speed to speed + p.set_can_speed_kbps(0, speed) + time.sleep(0.05) + + comp_kbps = time_many_sends(p, 0) + + # bit count from https://en.wikipedia.org/wiki/CAN_bus + saturation_pct = (comp_kbps / speed) * 100.0 + assert saturation_pct > 80 + assert saturation_pct < 100 + + print("loopback 100 messages at speed %d, comp speed is %.2f, percent %.2f" % (speed, comp_kbps, saturation_pct)) + +# this will fail if you have hardware serial connected +def test_serial_debug(p): + _ = p.serial_read(Panda.SERIAL_DEBUG) # junk + p.call_control_api(0x01) + assert p.serial_read(Panda.SERIAL_DEBUG).startswith(b"NO HANDLER") diff --git a/panda/tests/hitl/4_can_loopback.py b/panda/tests/hitl/4_can_loopback.py new file mode 100644 index 0000000000..63fce9d968 --- /dev/null +++ b/panda/tests/hitl/4_can_loopback.py @@ -0,0 +1,200 @@ +import os +import time +import pytest +import random +import threading +from flaky import flaky +from collections import defaultdict + +from opendbc.car.structs import CarParams +from panda.tests.hitl.helpers import time_many_sends, get_random_can_messages, clear_can_buffers + +@flaky(max_runs=3, min_passes=1) +@pytest.mark.timeout(35) +def test_send_recv(p, panda_jungle): + def test(p_send, p_recv): + for bus in (0, 1, 2): + for speed in (10, 20, 50, 100, 125, 250, 500, 1000): + clear_can_buffers(p_send, speed) + clear_can_buffers(p_recv, speed) + + comp_kbps = time_many_sends(p_send, bus, p_recv, two_pandas=True) + + saturation_pct = (comp_kbps / speed) * 100.0 + assert 80 < saturation_pct < 100 + + print(f"two pandas bus {bus}, 100 messages at speed {speed:4d}, comp speed is {comp_kbps:7.2f}, {saturation_pct:6.2f}%") + + # Run tests in both directions + p.set_safety_mode(CarParams.SafetyModel.allOutput) + test(p, panda_jungle) + test(panda_jungle, p) + + +@flaky(max_runs=6, min_passes=1) +@pytest.mark.timeout(30) +def test_latency(p, panda_jungle): + def test(p_send, p_recv): + for bus in (0, 1, 2): + for speed in (10, 20, 50, 100, 125, 250, 500, 1000): + clear_can_buffers(p_send, speed) + clear_can_buffers(p_recv, speed) + + latencies = [] + comp_kbps_list = [] + saturation_pcts = [] + + num_messages = 100 + + for _ in range(num_messages): + st = time.monotonic() + p_send.can_send(0x1ab, b"message", bus) + r = [] + while len(r) < 1 and (time.monotonic() - st) < 5: + r = p_recv.can_recv() + et = time.monotonic() + r_echo = [] + while len(r_echo) < 1 and (time.monotonic() - st) < 10: + r_echo = p_send.can_recv() + + if len(r) == 0 or len(r_echo) == 0: + print(f"r: {r}, r_echo: {r_echo}") + + assert len(r) == 1 + assert len(r_echo) == 1 + + et = (et - st) * 1000.0 + comp_kbps = (1 + 11 + 1 + 1 + 1 + 4 + 8 * 8 + 15 + 1 + 1 + 1 + 7) / et + latency = et - ((1 + 11 + 1 + 1 + 1 + 4 + 8 * 8 + 15 + 1 + 1 + 1 + 7) / speed) + + assert latency < 5.0 + + saturation_pct = (comp_kbps / speed) * 100.0 + latencies.append(latency) + comp_kbps_list.append(comp_kbps) + saturation_pcts.append(saturation_pct) + + average_latency = sum(latencies) / num_messages + assert average_latency < 1.0 + average_comp_kbps = sum(comp_kbps_list) / num_messages + average_saturation_pct = sum(saturation_pcts) / num_messages + + print("two pandas bus {}, {} message average at speed {:4d}, latency is {:5.3f}ms, comp speed is {:7.2f}, percent {:6.2f}" + .format(bus, num_messages, speed, average_latency, average_comp_kbps, average_saturation_pct)) + + # Run tests in both directions + p.set_safety_mode(CarParams.SafetyModel.allOutput) + test(p, panda_jungle) + test(panda_jungle, p) + + +@pytest.mark.panda_expect_can_error +def test_gen2_loopback(p, panda_jungle): + def test(p_send, p_recv, address=None): + for bus in range(4): + obd = False + if bus == 3: + obd = True + bus = 1 + + # Clear buses + clear_can_buffers(p_send) + clear_can_buffers(p_recv) + + # Send a random string + addr = address if address else random.randint(1, 2000) + string = b"test" + os.urandom(4) + p_send.set_obd(obd) + p_recv.set_obd(obd) + time.sleep(0.2) + p_send.can_send(addr, string, bus) + time.sleep(0.2) + + content = p_recv.can_recv() + + # Check amount of messages + assert len(content) == 1 + + # Check content + assert content[0][0] == addr and content[0][1] == string + + # Check bus + assert content[0][2] == bus + + print("Bus:", bus, "address:", addr, "OBD:", obd, "OK") + + # Run tests in both directions + p.set_safety_mode(CarParams.SafetyModel.allOutput) + test(p, panda_jungle) + test(panda_jungle, p) + + # Test extended frame address with ELM327 mode + p.set_safety_mode(CarParams.SafetyModel.elm327) + test(p, panda_jungle, 0x18DB33F1) + test(panda_jungle, p, 0x18DB33F1) + + # TODO: why it's not being reset by fixtures reinit? + p.set_obd(False) + panda_jungle.set_obd(False) + +def test_bulk_write(p, panda_jungle): + # The TX buffers on pandas is 0x100 in length. + NUM_MESSAGES_PER_BUS = 10000 + + def flood_tx(panda): + print('Sending!') + msg = b"\xaa" * 8 + packet = [] + # start with many messages on a single bus (higher contention for single TX ring buffer) + packet += [[0xaa, msg, 0]] * NUM_MESSAGES_PER_BUS + # end with many messages on multiple buses + packet += [[0xaa, msg, 0], [0xaa, msg, 1], [0xaa, msg, 2]] * NUM_MESSAGES_PER_BUS + + # Disable timeout + panda.set_safety_mode(CarParams.SafetyModel.allOutput) + panda.can_send_many(packet, timeout=0) + print(f"Done sending {4 * NUM_MESSAGES_PER_BUS} messages!", time.monotonic()) + print(panda.health()) + + # Start transmisson + threading.Thread(target=flood_tx, args=(p,)).start() + + # Receive as much as we can in a few second time period + rx = [] + old_len = 0 + start_time = time.monotonic() + while time.monotonic() - start_time < 5 or len(rx) > old_len: + old_len = len(rx) + rx.extend(panda_jungle.can_recv()) + print(f"Received {len(rx)} messages", time.monotonic()) + + # All messages should have been received + if len(rx) != 4 * NUM_MESSAGES_PER_BUS: + raise Exception("Did not receive all messages!") + +def test_message_integrity(p): + p.set_safety_mode(CarParams.SafetyModel.allOutput) + p.set_can_loopback(True) + for i in range(250): + sent_msgs = defaultdict(set) + for _ in range(random.randrange(10)): + to_send = get_random_can_messages(random.randrange(100)) + for m in to_send: + sent_msgs[m[2]].add((m[0], m[1])) + p.can_send_many(to_send, timeout=0) + + start_time = time.monotonic() + while time.monotonic() - start_time < 2 and any(len(sent_msgs[bus]) for bus in range(3)): + recvd = p.can_recv() + for msg in recvd: + if msg[2] >= 128: + k = (msg[0], bytes(msg[1])) + bus = msg[2]-128 + assert k in sent_msgs[bus], f"message {k} was never sent on bus {bus}" + sent_msgs[msg[2]-128].discard(k) + + # if a set isn't empty, messages got dropped + for bus in range(3): + assert not len(sent_msgs[bus]), f"loop {i}: bus {bus} missing {len(sent_msgs[bus])} messages" + + print("Got all messages intact") diff --git a/panda/tests/hitl/5_spi.py b/panda/tests/hitl/5_spi.py new file mode 100644 index 0000000000..106a1c7d4b --- /dev/null +++ b/panda/tests/hitl/5_spi.py @@ -0,0 +1,81 @@ +import binascii +import pytest +import random +from unittest.mock import patch + +from panda import Panda +from panda.python.spi import PandaProtocolMismatch, PandaSpiNackResponse + + +class TestSpi: + def _ping(self, mocker, panda): + # should work with no retries + spy = mocker.spy(panda._handle, '_wait_for_ack') + panda.health() + assert spy.call_count == 2 + mocker.stop(spy) + + def test_protocol_version_check(self, p): + for bootstub in (False, True): + p.reset(enter_bootstub=bootstub) + with patch('panda.python.spi.PandaSpiHandle.PROTOCOL_VERSION', return_value="abc"): + # list should still work with wrong version + assert p._serial in Panda.list() + + # connect but raise protocol error + with pytest.raises(PandaProtocolMismatch): + Panda(p._serial) + + def test_protocol_version_data(self, p): + for bootstub in (False, True): + p.reset(enter_bootstub=bootstub) + v = p._handle.get_protocol_version() + + uid = binascii.hexlify(v[:12]).decode() + assert uid == p.get_uid() + + hwtype = v[12] + assert hwtype == ord(p.get_type()) + + bstub = v[13] + assert bstub == (0xEE if bootstub else 0xCC) + + def test_all_comm_types(self, mocker, p): + spy = mocker.spy(p._handle, '_wait_for_ack') + + # controlRead + controlWrite + p.health() + p.can_clear(0) + assert spy.call_count == 2*2 + + # bulkRead + bulkWrite + p.can_recv() + p.can_send(0x123, b"somedata", 0) + assert spy.call_count == 2*4 + + def test_bad_header(self, mocker, p): + with patch('panda.python.spi.SYNC', return_value=0): + with pytest.raises(PandaSpiNackResponse): + p._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, p.HEALTH_STRUCT.size, timeout=50) + self._ping(mocker, p) + + def test_bad_checksum(self, mocker, p): + cnt = p.health()['spi_error_count'] + with patch('panda.python.spi.PandaSpiHandle._calc_checksum', return_value=0): + with pytest.raises(PandaSpiNackResponse): + p._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, p.HEALTH_STRUCT.size, timeout=50) + self._ping(mocker, p) + assert (p.health()['spi_error_count'] - cnt) > 0 + + def test_non_existent_endpoint(self, mocker, p): + for _ in range(10): + ep = random.randint(4, 20) + with pytest.raises(PandaSpiNackResponse): + p._handle.bulkRead(ep, random.randint(1, 1000), timeout=50) + + self._ping(mocker, p) + + with pytest.raises(PandaSpiNackResponse): + p._handle.bulkWrite(ep, b"abc", timeout=50) + + self._ping(mocker, p) diff --git a/panda/tests/hitl/6_safety.py b/panda/tests/hitl/6_safety.py new file mode 100644 index 0000000000..0688456f8b --- /dev/null +++ b/panda/tests/hitl/6_safety.py @@ -0,0 +1,18 @@ +import time + +from opendbc.car.structs import CarParams + + +def test_safety_nooutput(p): + p.set_safety_mode(CarParams.SafetyModel.silent) + p.set_can_loopback(True) + + # send a message on bus 0 + p.can_send(0x1aa, b"message", 0) + + # confirm receive nothing + time.sleep(0.05) + r = p.can_recv() + # bus 192 is messages blocked by TX safety hook on bus 0 + assert len([x for x in r if x[2] != 192]) == 0 + assert len([x for x in r if x[2] == 192]) == 1 diff --git a/panda/tests/hitl/7_internal.py b/panda/tests/hitl/7_internal.py new file mode 100644 index 0000000000..47c24a47c6 --- /dev/null +++ b/panda/tests/hitl/7_internal.py @@ -0,0 +1,39 @@ +import time +import pytest + +from panda import Panda + +pytestmark = [ + pytest.mark.test_panda_types(Panda.INTERNAL_DEVICES), + pytest.mark.test_panda_types([Panda.HW_TYPE_TRES]) +] + +@pytest.mark.timeout(2*60) +def test_fan_curve(p): + # ensure fan curve is (roughly) linear + + for power in (30, 50, 80, 100): + p.set_fan_power(0) + while p.get_fan_rpm() > 0: + time.sleep(0.1) + + # wait until fan spins up, then wait a bit more for the RPM to converge + p.set_fan_power(power) + for _ in range(20): + time.sleep(1) + if p.get_fan_rpm() > 1000: + break + time.sleep(5) + + expected_rpm = Panda.MAX_FAN_RPMs[bytes(p.get_type())] * power / 100 + assert 0.75 * expected_rpm <= p.get_fan_rpm() <= 1.25 * expected_rpm + +def test_fan_cooldown(p): + # if the fan cooldown doesn't work, we get high frequency noise on the tach line + # while the rotor spins down. this makes sure it never goes beyond the expected max RPM + p.set_fan_power(100) + time.sleep(3) + p.set_fan_power(0) + for _ in range(5): + assert p.get_fan_rpm() <= Panda.MAX_FAN_RPMs[bytes(p.get_type())] + time.sleep(0.5) diff --git a/panda/tests/hitl/8_misc.py b/panda/tests/hitl/8_misc.py new file mode 100644 index 0000000000..3c47ed492b --- /dev/null +++ b/panda/tests/hitl/8_misc.py @@ -0,0 +1,13 @@ +import time + +from panda import Panda + +def test_boot_time(p): + # boot time should be instant + st = time.monotonic() + p.reset(reconnect=False) + assert Panda.wait_for_panda(p.get_usb_serial(), timeout=3.0) + + # USB enumeration is slow, so SPI is faster + assert time.monotonic() - st < (1.0 if p.spi else 5.0) + diff --git a/panda/tests/hitl/9_harness.py b/panda/tests/hitl/9_harness.py new file mode 100644 index 0000000000..ddd3516e4d --- /dev/null +++ b/panda/tests/hitl/9_harness.py @@ -0,0 +1,76 @@ +import time +import pytest +import itertools + +from opendbc.car.structs import CarParams +from panda import Panda + +# TODO: test relay + +@pytest.mark.panda_expect_can_error +def test_harness_status(p, panda_jungle): + # map from jungle orientations to panda orientations + orientation_map = { + Panda.HARNESS_STATUS_NC: Panda.HARNESS_STATUS_NC, + } + + # this shouldn't be parameterized since we don't want the panda to be reset + # between the tests. + for ignition, orientation in itertools.product([True, False], [Panda.HARNESS_STATUS_NC, Panda.HARNESS_STATUS_NORMAL, Panda.HARNESS_STATUS_FLIPPED]): + print() + p.set_safety_mode(CarParams.SafetyModel.elm327) + panda_jungle.set_harness_orientation(orientation) + panda_jungle.set_ignition(ignition) + + # wait for orientation detection + time.sleep(0.25) + + health = p.health() + detected_orientation = health['car_harness_status'] + print(f"orientation set: {orientation} detected: {detected_orientation}") + + if detected_orientation not in orientation_map: + assert detected_orientation != Panda.HARNESS_STATUS_NC + other = {Panda.HARNESS_STATUS_NORMAL: Panda.HARNESS_STATUS_FLIPPED, Panda.HARNESS_STATUS_FLIPPED: Panda.HARNESS_STATUS_NORMAL} + orientation_map.update({ + orientation: detected_orientation, + other[orientation]: other[detected_orientation], + }) + + # Orientation + assert orientation_map[detected_orientation] == orientation + + # Line ignition + assert health['ignition_line'] == (False if orientation == Panda.HARNESS_STATUS_NC else ignition) + + # CAN traffic + if orientation != Panda.HARNESS_STATUS_NC: + for bus in range(3): + panda_jungle.can_send(0x123, f"{bus}".encode(), bus) + time.sleep(0.5) + + msgs = p.can_recv() + buses = {int(dat): bus for _, dat, bus in msgs if bus <= 3} + print(msgs) + + # jungle doesn't actually switch buses when switching orientation + flipped = orientation == Panda.HARNESS_STATUS_FLIPPED + assert buses[0] == (2 if flipped else 0) + assert buses[2] == (0 if flipped else 2) + + # SBU voltages + supply_voltage_mV = 1800 if p.get_type() in [Panda.HW_TYPE_TRES, Panda.HW_TYPE_CUATRO] else 3300 + + if orientation == Panda.HARNESS_STATUS_NC: + assert health['sbu1_voltage_mV'] > 0.9 * supply_voltage_mV + assert health['sbu2_voltage_mV'] > 0.9 * supply_voltage_mV + else: + relay_line = 'sbu1_voltage_mV' if (detected_orientation == Panda.HARNESS_STATUS_FLIPPED) else 'sbu2_voltage_mV' + ignition_line = 'sbu2_voltage_mV' if (detected_orientation == Panda.HARNESS_STATUS_FLIPPED) else 'sbu1_voltage_mV' + + assert health[relay_line] < 0.1 * supply_voltage_mV + assert health[ignition_line] > health[relay_line] + if ignition: + assert health[ignition_line] < 0.3 * supply_voltage_mV + else: + assert health[ignition_line] > 0.9 * supply_voltage_mV diff --git a/panda/tests/hitl/__init__.py b/panda/tests/hitl/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/panda/tests/hitl/conftest.py b/panda/tests/hitl/conftest.py new file mode 100644 index 0000000000..ecc3a455c8 --- /dev/null +++ b/panda/tests/hitl/conftest.py @@ -0,0 +1,165 @@ +import os +import pytest + +from panda import Panda, PandaDFU, PandaJungle +from panda.tests.hitl.helpers import clear_can_buffers + +SPEED_NORMAL = 500 +BUS_SPEEDS = [(0, SPEED_NORMAL), (1, SPEED_NORMAL), (2, SPEED_NORMAL)] + +# test options +NO_JUNGLE = os.environ.get("NO_JUNGLE", "0") == "1" + +# Find all pandas connected +_panda_jungle = None +_panda_type = None +_panda_serial = None +def init_devices(): + if not NO_JUNGLE: + global _panda_jungle + _panda_jungle = PandaJungle() + _panda_jungle.set_panda_power(True) + + with Panda(serial=None, claim=False) as p: + global _panda_type + global _panda_serial + _panda_serial = p.get_usb_serial() + _panda_type = bytes(p.get_type()) + assert _panda_serial is not None, "No panda found!" +init_devices() + +def init_jungle(): + if _panda_jungle is None: + return + clear_can_buffers(_panda_jungle) + _panda_jungle.set_panda_power(True) + _panda_jungle.set_can_loopback(False) + _panda_jungle.set_obd(False) + _panda_jungle.set_harness_orientation(PandaJungle.HARNESS_ORIENTATION_1) + for bus, speed in BUS_SPEEDS: + _panda_jungle.set_can_speed_kbps(bus, speed) + + # ensure FW hasn't changed + assert _panda_jungle.up_to_date() + + +def pytest_configure(config): + config.addinivalue_line( + "markers", "test_panda_types(name): whitelist a test for specific panda types" + ) + config.addinivalue_line( + "markers", "skip_panda_types(name): blacklist panda types from a test" + ) + config.addinivalue_line( + "markers", "panda_expect_can_error: mark test to ignore CAN health errors" + ) + +@pytest.hookimpl(tryfirst=True) +def pytest_collection_modifyitems(items): + for item in items: + if item.get_closest_marker('timeout') is None: + item.add_marker(pytest.mark.timeout(60)) + + needs_jungle = "panda_jungle" in item.fixturenames + if needs_jungle and NO_JUNGLE: + item.add_marker(pytest.mark.skip(reason="skipping tests that requires a jungle")) + +@pytest.fixture(name='panda_jungle', scope='function') +def fixture_panda_jungle(request): + init_jungle() + return _panda_jungle + +@pytest.fixture(name='p', scope='function') +def func_fixture_panda(request, module_panda): + # *** Setup *** + + p = module_panda + + # Check if test is applicable to this panda + mark = request.node.get_closest_marker('test_panda_types') + if mark: + assert len(mark.args) > 0, "Missing panda types argument in mark" + test_types = mark.args[0] + if _panda_type not in test_types: + pytest.skip(f"Not applicable, {test_types} pandas only") + + mark = request.node.get_closest_marker('skip_panda_types') + if mark: + assert len(mark.args) > 0, "Missing panda types argument in mark" + skip_types = mark.args[0] + if _panda_type in skip_types: + pytest.skip(f"Not applicable to {skip_types}") + + # this is 2+ seconds on USB pandas due to slow + # enumeration on the host side + p.reset() + + # ensure FW hasn't changed + assert p.up_to_date() + + # *** Run test *** + yield p + + # *** Teardown *** + + # reconnect + if p.get_dfu_serial() in PandaDFU.list(): + PandaDFU(p.get_dfu_serial()).reset() + p.reconnect() + if not p.connected: + p.reconnect() + if p.bootstub: + p.reset() + + assert not p.bootstub + + # TODO: would be nice to make these common checks in the teardown + # show up as failed tests instead of "errors" + + # Check for faults + assert p.health()['faults'] == 0 + assert p.health()['fault_status'] == 0 + + # Check for SPI errors + #assert p.health()['spi_error_count'] == 0 + + # Check health of each CAN core after test, normal to fail for test_gen2_loopback on OBD bus, so skipping + mark = request.node.get_closest_marker('panda_expect_can_error') + expect_can_error = mark is not None + if not expect_can_error: + for i in range(3): + can_health = p.can_health(i) + assert can_health['bus_off_cnt'] == 0 + assert can_health['receive_error_cnt'] < 127 + assert can_health['transmit_error_cnt'] < 255 + assert can_health['error_passive'] == 0 + assert can_health['error_warning'] == 0 + assert can_health['total_rx_lost_cnt'] == 0 + assert can_health['total_tx_lost_cnt'] == 0 + assert can_health['total_error_cnt'] == 0 + assert can_health['total_tx_checksum_error_cnt'] == 0 + +@pytest.fixture(name='module_panda', scope='module') +def fixture_panda_setup(request): + """ + Clean up panda + jungle and return the panda under test. + """ + # init jungle + init_jungle() + + # init panda + p = Panda(serial=_panda_serial) + p.reset(reconnect=True) + + p.set_can_loopback(False) + p.set_power_save(False) + for bus, speed in BUS_SPEEDS: + p.set_can_speed_kbps(bus, speed) + clear_can_buffers(p) + p.set_power_save(False) + + # run test + yield p + + # teardown + p.close() diff --git a/panda/tests/hitl/helpers.py b/panda/tests/hitl/helpers.py new file mode 100644 index 0000000000..d465671309 --- /dev/null +++ b/panda/tests/hitl/helpers.py @@ -0,0 +1,71 @@ +import time +import random + + +def get_random_can_messages(n): + m = [] + for _ in range(n): + bus = random.randrange(3) + addr = random.randrange(1 << 29) + dat = bytes([random.getrandbits(8) for _ in range(random.randrange(1, 9))]) + m.append([addr, dat, bus]) + return m + + +def time_many_sends(p, bus, p_recv=None, msg_count=100, two_pandas=False, msg_len=8): + if p_recv is None: + p_recv = p + if p == p_recv and two_pandas: + raise ValueError("Cannot have two pandas that are the same panda") + + msg_id = random.randint(0x100, 0x200) + to_send = [(msg_id, b"\xaa" * msg_len, bus)] * msg_count + + start_time = time.monotonic() + p.can_send_many(to_send) + r = [] + r_echo = [] + r_len_expected = msg_count if two_pandas else msg_count * 2 + r_echo_len_exected = msg_count if two_pandas else 0 + + while len(r) < r_len_expected and (time.monotonic() - start_time) < 5: + r.extend(p_recv.can_recv()) + end_time = time.monotonic() + if two_pandas: + while len(r_echo) < r_echo_len_exected and (time.monotonic() - start_time) < 10: + r_echo.extend(p.can_recv()) + + sent_echo = [x for x in r if x[2] == 0x80 | bus and x[0] == msg_id] + sent_echo.extend([x for x in r_echo if x[2] == 0x80 | bus and x[0] == msg_id]) + resp = [x for x in r if x[2] == bus and x[0] == msg_id] + + leftovers = [x for x in r if (x[2] != 0x80 | bus and x[2] != bus) or x[0] != msg_id] + assert len(leftovers) == 0 + + assert len(resp) == msg_count + assert len(sent_echo) == msg_count + + end_time = (end_time - start_time) * 1000.0 + comp_kbps = (1 + 11 + 1 + 1 + 1 + 4 + (msg_len * 8) + 15 + 1 + 1 + 1 + 7) * msg_count / end_time + + return comp_kbps + + +def clear_can_buffers(panda, speed: int | None = None): + if speed is not None: + for bus in range(3): + panda.set_can_speed_kbps(bus, speed) + + # clear tx buffers + for i in range(4): + panda.can_clear(i) + + # clear rx buffers + panda.can_clear(0xFFFF) + r = [1] + st = time.monotonic() + while len(r) > 0: + r = panda.can_recv() + time.sleep(0.05) + if (time.monotonic() - st) > 10: + raise Exception("Unable to clear can buffers for panda ", panda.get_serial()) diff --git a/panda/tests/hitl/known_bootstub/bootstub.panda_h7.bin b/panda/tests/hitl/known_bootstub/bootstub.panda_h7.bin new file mode 100755 index 0000000000..a6d856bd2c Binary files /dev/null and b/panda/tests/hitl/known_bootstub/bootstub.panda_h7.bin differ diff --git a/panda/tests/hitl/reset_jungles.py b/panda/tests/hitl/reset_jungles.py new file mode 100755 index 0000000000..09bd04ad9a --- /dev/null +++ b/panda/tests/hitl/reset_jungles.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +import concurrent.futures + +from panda import PandaJungle, PandaJungleDFU, McuType +from panda.tests.libs.resetter import Resetter + +SERIALS = { + '180019001451313236343430', # jungle v2 +} + +def recover(s): + with PandaJungleDFU(s) as pd: + pd.recover() + +def flash(s): + with PandaJungle(s) as p: + p.flash() + return p.get_mcu_type() + +# Reset + flash all CI hardware to get it into a consistent state +# * port 1: jungles-under-test +# * port 2: USB hubs +# * port 3: HITL pandas and their jungles +if __name__ == "__main__": + with Resetter() as r: + # everything off + for i in range(1, 4): + r.enable_power(i, 0) + r.cycle_power(ports=[1, 2], dfu=True) + for s in SERIALS: + assert PandaJungle.wait_for_dfu(PandaJungleDFU.st_serial_to_dfu_serial(s, McuType.H7), timeout=10) + dfu_serials = PandaJungleDFU.list() + assert len(dfu_serials) == len(SERIALS) + + with concurrent.futures.ProcessPoolExecutor(max_workers=len(dfu_serials)) as exc: + list(exc.map(recover, dfu_serials, timeout=30)) + + # power cycle for H7 bootloader bug + r.cycle_power(ports=[1, 2]) + + # wait for them to come back up + for s in SERIALS: + assert PandaJungle.wait_for_panda(s, timeout=10) + assert set(PandaJungle.list()) >= SERIALS + mcu_types = list(exc.map(flash, SERIALS, timeout=20)) + assert set(mcu_types) == {McuType.H7, } diff --git a/panda/tests/libpanda/SConscript b/panda/tests/libpanda/SConscript new file mode 100644 index 0000000000..a5bdd7ce74 --- /dev/null +++ b/panda/tests/libpanda/SConscript @@ -0,0 +1,38 @@ +import opendbc +import platform + +CC = 'gcc' +system = platform.system() +mac_ver = platform.mac_ver() + +# gcc installed by homebrew has version suffix (e.g. gcc-12) in order to be +# distinguishable from system one - which acts as a symlink to clang +# clang works on macOS 15 and greater but has issues on earlier macOS versions. +# see: https://github.com/commaai/openpilot/issues/35093 +if system == 'Darwin' and mac_ver[0] and mac_ver[0] < '15': + CC += '-13' + +env = Environment( + CC=CC, + CFLAGS=[ + '-nostdlib', + '-fno-builtin', + '-std=gnu11', + '-Wfatal-errors', + '-Wno-pointer-to-int-cast', + ], + CPPPATH=[".", "../../", "../../board/", opendbc.INCLUDE_PATH], +) +if system == "Darwin": + env.PrependENVPath('PATH', '/opt/homebrew/bin') + +if GetOption('ubsan'): + flags = [ + "-fsanitize=undefined", + "-fno-sanitize-recover=undefined", + ] + env['CFLAGS'] += flags + env['LINKFLAGS'] += flags + +panda = env.SharedObject("panda.os", "panda.c") +libpanda = env.SharedLibrary("libpanda.so", [panda]) diff --git a/panda/tests/libpanda/libpanda_py.py b/panda/tests/libpanda/libpanda_py.py new file mode 100644 index 0000000000..eef722c06a --- /dev/null +++ b/panda/tests/libpanda/libpanda_py.py @@ -0,0 +1,87 @@ +import os +from cffi import FFI +from typing import Any, Protocol + +from panda import LEN_TO_DLC + +libpanda_dir = os.path.dirname(os.path.abspath(__file__)) +libpanda_fn = os.path.join(libpanda_dir, "libpanda.so") + +ffi = FFI() + +ffi.cdef(""" +typedef struct { + unsigned char fd : 1; + unsigned char bus : 3; + unsigned char data_len_code : 4; + unsigned char rejected : 1; + unsigned char returned : 1; + unsigned char extended : 1; + unsigned int addr : 29; + unsigned char checksum; + unsigned char data[64]; +} CANPacket_t; +""", packed=True) + +ffi.cdef(""" +int set_safety_hooks(uint16_t mode, uint16_t param); +""") + +ffi.cdef(""" +typedef struct { + volatile uint32_t w_ptr; + volatile uint32_t r_ptr; + uint32_t fifo_size; + CANPacket_t *elems; +} can_ring; + +extern can_ring *rx_q; +extern can_ring *tx1_q; +extern can_ring *tx2_q; +extern can_ring *tx3_q; + +bool can_pop(can_ring *q, CANPacket_t *elem); +bool can_push(can_ring *q, CANPacket_t *elem); +void can_set_checksum(CANPacket_t *packet); +int comms_can_read(uint8_t *data, uint32_t max_len); +void comms_can_write(uint8_t *data, uint32_t len); +void comms_can_reset(void); +uint32_t can_slots_empty(can_ring *q); +""") + +class CANPacket: + reserved: int + bus: int + data_len_code: int + rejected: int + returned: int + extended: int + addr: int + data: list[int] + +class Panda(Protocol): + # CAN + tx1_q: Any + tx2_q: Any + tx3_q: Any + def can_set_checksum(self, p: CANPacket) -> None: ... + + # safety + def set_safety_hooks(self, mode: int, param: int) -> int: ... + + +libpanda: Panda = ffi.dlopen(libpanda_fn) + + +# helpers + +def make_CANPacket(addr: int, bus: int, dat): + ret = ffi.new('CANPacket_t *') + ret[0].extended = 1 if addr >= 0x800 else 0 + ret[0].addr = addr + ret[0].data_len_code = LEN_TO_DLC[len(dat)] + ret[0].bus = bus + ret[0].data = bytes(dat) + libpanda.can_set_checksum(ret) + + return ret diff --git a/panda/tests/libpanda/panda.c b/panda/tests/libpanda/panda.c new file mode 100644 index 0000000000..2d17d64e34 --- /dev/null +++ b/panda/tests/libpanda/panda.c @@ -0,0 +1,28 @@ +#include "fake_stm.h" +#include "config.h" +#include "can.h" + +bool can_init(uint8_t can_number) { return true; } +void process_can(uint8_t can_number) { } +//int safety_tx_hook(CANPacket_t *to_send) { return 1; } + +typedef struct harness_configuration harness_configuration; +void refresh_can_tx_slots_available(void); +void can_tx_comms_resume_usb(void) { }; +void can_tx_comms_resume_spi(void) { }; + +#include "health.h" +#include "faults.h" +#include "libc.h" +#include "boards/board_declarations.h" +#include "opendbc/safety/safety.h" +#include "main_definitions.h" +#include "drivers/can_common.h" + +can_ring *rx_q = &can_rx_q; +can_ring *tx1_q = &can_tx1_q; +can_ring *tx2_q = &can_tx2_q; +can_ring *tx3_q = &can_tx3_q; + +#include "comms_definitions.h" +#include "can_comms.h" diff --git a/panda/tests/libs/resetter.py b/panda/tests/libs/resetter.py new file mode 100644 index 0000000000..52c44e4245 --- /dev/null +++ b/panda/tests/libs/resetter.py @@ -0,0 +1,58 @@ +import time +import usb1 + + +class Resetter(): + def __init__(self): + self._handle = None + self.connect() + + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + + def close(self): + self._handle.close() + self._context.close() + self._handle = None + + def connect(self): + if self._handle: + self.close() + + self._handle = None + + self._context = usb1.USBContext() + self._context.open() + for device in self._context.getDeviceList(skip_on_error=True): + if device.getVendorID() == 0xbbaa and device.getProductID() == 0xddc0: + try: + self._handle = device.open() + self._handle.claimInterface(0) + break + except Exception as e: + print(e) + assert self._handle + + def enable_power(self, port, enabled): + self._handle.controlWrite((usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE), 0xff, port, enabled, b'') + + def enable_boot(self, enabled): + self._handle.controlWrite((usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE), 0xff, 0, enabled, b'') + + def cycle_power(self, dfu=False, ports=None): + if ports is None: + ports = [1, 2, 3] + + self.enable_boot(dfu) + for port in ports: + self.enable_power(port, False) + time.sleep(0.05) + + for port in ports: + self.enable_power(port, True) + time.sleep(0.05) + self.enable_boot(False) + time.sleep(0.12) # takes the kernel this long to detect the disconnect diff --git a/panda/tests/misra/.gitignore b/panda/tests/misra/.gitignore new file mode 100644 index 0000000000..fc9ac228cb --- /dev/null +++ b/panda/tests/misra/.gitignore @@ -0,0 +1,5 @@ +*.pdf +*.txt +.output.log +new_table +cppcheck/ diff --git a/panda/tests/misra/checkers.txt b/panda/tests/misra/checkers.txt new file mode 100644 index 0000000000..44e6aa13f3 --- /dev/null +++ b/panda/tests/misra/checkers.txt @@ -0,0 +1,456 @@ +Cppcheck checkers list from test_misra.sh: + + + + + +TEST variant options: +--enable=all --disable=unusedFunction --addon=misra -DSTM32H7 -DSTM32H725xx -I /board/stm32h7/inc/ /board/main.c + + +Critical errors +--------------- +No critical errors encountered. +Note: There might still have been non-critical bailouts which might lead to false negatives. + + +Open source checkers +-------------------- +Yes Check64BitPortability::pointerassignment +Yes CheckAssert::assertWithSideEffects +Yes CheckAutoVariables::assignFunctionArg +Yes CheckAutoVariables::autoVariables +Yes CheckAutoVariables::checkVarLifetime +No CheckBool::checkAssignBoolToFloat require:style,c++ +Yes CheckBool::checkAssignBoolToPointer +No CheckBool::checkBitwiseOnBoolean require:style,inconclusive +Yes CheckBool::checkComparisonOfBoolExpressionWithInt +No CheckBool::checkComparisonOfBoolWithBool require:style,c++ +No CheckBool::checkComparisonOfBoolWithInt require:warning,c++ +No CheckBool::checkComparisonOfFuncReturningBool require:style,c++ +Yes CheckBool::checkIncrementBoolean +Yes CheckBool::pointerArithBool +Yes CheckBool::returnValueOfFunctionReturningBool +No CheckBoost::checkBoostForeachModification +Yes CheckBufferOverrun::analyseWholeProgram +Yes CheckBufferOverrun::argumentSize +Yes CheckBufferOverrun::arrayIndex +Yes CheckBufferOverrun::arrayIndexThenCheck +Yes CheckBufferOverrun::bufferOverflow +Yes CheckBufferOverrun::negativeArraySize +Yes CheckBufferOverrun::objectIndex +Yes CheckBufferOverrun::pointerArithmetic +No CheckBufferOverrun::stringNotZeroTerminated require:warning,inconclusive +Yes CheckClass::analyseWholeProgram +No CheckClass::checkConst require:style,inconclusive +No CheckClass::checkConstructors require:style,warning +No CheckClass::checkCopyConstructors require:warning +No CheckClass::checkDuplInheritedMembers require:warning +No CheckClass::checkExplicitConstructors require:style +No CheckClass::checkMemset +No CheckClass::checkMissingOverride require:style,c++03 +No CheckClass::checkReturnByReference require:performance +No CheckClass::checkSelfInitialization +No CheckClass::checkThisUseAfterFree require:warning +No CheckClass::checkUnsafeClassRefMember require:warning,safeChecks +No CheckClass::checkUselessOverride require:style +No CheckClass::checkVirtualFunctionCallInConstructor require:warning +No CheckClass::initializationListUsage require:performance +No CheckClass::initializerListOrder require:style,inconclusive +No CheckClass::operatorEqRetRefThis require:style +No CheckClass::operatorEqToSelf require:warning +No CheckClass::privateFunctions require:style +No CheckClass::thisSubtraction require:warning +No CheckClass::virtualDestructor +Yes CheckCondition::alwaysTrueFalse +Yes CheckCondition::assignIf +Yes CheckCondition::checkAssignmentInCondition +Yes CheckCondition::checkBadBitmaskCheck +Yes CheckCondition::checkCompareValueOutOfTypeRange +Yes CheckCondition::checkDuplicateConditionalAssign +Yes CheckCondition::checkIncorrectLogicOperator +Yes CheckCondition::checkInvalidTestForOverflow +Yes CheckCondition::checkModuloAlwaysTrueFalse +Yes CheckCondition::checkPointerAdditionResultNotNull +Yes CheckCondition::clarifyCondition +Yes CheckCondition::comparison +Yes CheckCondition::duplicateCondition +Yes CheckCondition::multiCondition +Yes CheckCondition::multiCondition2 +No CheckExceptionSafety::checkCatchExceptionByValue require:style +No CheckExceptionSafety::checkRethrowCopy require:style +No CheckExceptionSafety::deallocThrow require:warning +No CheckExceptionSafety::destructors require:warning +No CheckExceptionSafety::nothrowThrows +No CheckExceptionSafety::rethrowNoCurrentException +No CheckExceptionSafety::unhandledExceptionSpecification require:style,inconclusive +Yes CheckFunctions::checkIgnoredReturnValue +Yes CheckFunctions::checkMathFunctions +Yes CheckFunctions::checkMissingReturn +Yes CheckFunctions::checkProhibitedFunctions +Yes CheckFunctions::invalidFunctionUsage +Yes CheckFunctions::memsetInvalid2ndParam +Yes CheckFunctions::memsetZeroBytes +No CheckFunctions::returnLocalStdMove require:performance,c++11 +Yes CheckFunctions::useStandardLibrary +No CheckIO::checkCoutCerrMisusage require:c +Yes CheckIO::checkFileUsage +Yes CheckIO::checkWrongPrintfScanfArguments +Yes CheckIO::invalidScanf +Yes CheckLeakAutoVar::check +No CheckMemoryLeakInClass::check +Yes CheckMemoryLeakInFunction::checkReallocUsage +Yes CheckMemoryLeakNoVar::check +No CheckMemoryLeakNoVar::checkForUnsafeArgAlloc +Yes CheckMemoryLeakStructMember::check +Yes CheckNullPointer::analyseWholeProgram +Yes CheckNullPointer::arithmetic +Yes CheckNullPointer::nullConstantDereference +Yes CheckNullPointer::nullPointer +No CheckOther::checkAccessOfMovedVariable require:c++11,warning +Yes CheckOther::checkCastIntToCharAndBack +Yes CheckOther::checkCharVariable +Yes CheckOther::checkComparePointers +Yes CheckOther::checkComparisonFunctionIsAlwaysTrueOrFalse +Yes CheckOther::checkConstPointer +No CheckOther::checkConstVariable require:style,c++ +No CheckOther::checkDuplicateBranch require:style,inconclusive +Yes CheckOther::checkDuplicateExpression +Yes CheckOther::checkEvaluationOrder +Yes CheckOther::checkFuncArgNamesDifferent +No CheckOther::checkIncompleteArrayFill require:warning,portability,inconclusive +Yes CheckOther::checkIncompleteStatement +No CheckOther::checkInterlockedDecrement require:windows-platform +Yes CheckOther::checkInvalidFree +Yes CheckOther::checkKnownArgument +Yes CheckOther::checkKnownPointerToBool +No CheckOther::checkMisusedScopedObject require:style,c++ +Yes CheckOther::checkModuloOfOne +Yes CheckOther::checkNanInArithmeticExpression +Yes CheckOther::checkNegativeBitwiseShift +Yes CheckOther::checkOverlappingWrite +No CheckOther::checkPassByReference require:performance,c++ +Yes CheckOther::checkRedundantAssignment +No CheckOther::checkRedundantCopy require:c++,performance,inconclusive +Yes CheckOther::checkRedundantPointerOp +Yes CheckOther::checkShadowVariables +Yes CheckOther::checkSignOfUnsignedVariable +No CheckOther::checkSuspiciousCaseInSwitch require:warning,inconclusive +No CheckOther::checkSuspiciousSemicolon require:warning,inconclusive +Yes CheckOther::checkUnreachableCode +Yes CheckOther::checkUnusedLabel +Yes CheckOther::checkVarFuncNullUB +Yes CheckOther::checkVariableScope +Yes CheckOther::checkZeroDivision +Yes CheckOther::clarifyCalculation +Yes CheckOther::clarifyStatement +Yes CheckOther::invalidPointerCast +Yes CheckOther::redundantBitwiseOperationInSwitch +Yes CheckOther::suspiciousFloatingPointCast +No CheckOther::warningOldStylePointerCast require:style,c++ +No CheckPostfixOperator::postfixOperator require:performance +Yes CheckSizeof::checkSizeofForArrayParameter +Yes CheckSizeof::checkSizeofForNumericParameter +Yes CheckSizeof::checkSizeofForPointerSize +Yes CheckSizeof::sizeofCalculation +Yes CheckSizeof::sizeofFunction +Yes CheckSizeof::sizeofVoid +Yes CheckSizeof::sizeofsizeof +No CheckSizeof::suspiciousSizeofCalculation require:warning,inconclusive +No CheckStl::checkDereferenceInvalidIterator require:warning +No CheckStl::checkDereferenceInvalidIterator2 +No CheckStl::checkFindInsert require:performance +No CheckStl::checkMutexes require:warning +No CheckStl::erase +No CheckStl::eraseIteratorOutOfBounds +No CheckStl::if_find require:warning,performance +No CheckStl::invalidContainer +No CheckStl::iterators +No CheckStl::knownEmptyContainer require:style +No CheckStl::misMatchingContainerIterator +No CheckStl::misMatchingContainers +No CheckStl::missingComparison require:warning +No CheckStl::negativeIndex +No CheckStl::outOfBounds +No CheckStl::outOfBoundsIndexExpression +No CheckStl::redundantCondition require:style +No CheckStl::size require:performance,c++03 +No CheckStl::stlBoundaries +No CheckStl::stlOutOfBounds +No CheckStl::string_c_str +No CheckStl::useStlAlgorithm require:style +No CheckStl::uselessCalls require:performance,warning +Yes CheckString::checkAlwaysTrueOrFalseStringCompare +Yes CheckString::checkIncorrectStringCompare +Yes CheckString::checkSuspiciousStringCompare +Yes CheckString::overlappingStrcmp +Yes CheckString::sprintfOverlappingData +Yes CheckString::strPlusChar +Yes CheckString::stringLiteralWrite +Yes CheckType::checkFloatToIntegerOverflow +Yes CheckType::checkIntegerOverflow +Yes CheckType::checkLongCast +Yes CheckType::checkSignConversion +Yes CheckType::checkTooBigBitwiseShift +Yes CheckUninitVar::check +Yes CheckUninitVar::valueFlowUninit +No CheckUnusedFunctions::check require:unusedFunction +Yes CheckUnusedVar::checkFunctionVariableUsage +Yes CheckUnusedVar::checkStructMemberUsage +Yes CheckVaarg::va_list_usage +Yes CheckVaarg::va_start_argument + + +Premium checkers +---------------- +Not available, Cppcheck Premium is not used + + +Autosar +------- +Not available, Cppcheck Premium is not used + + +Cert C +------ +Not available, Cppcheck Premium is not used + + +Cert C++ +-------- +Not available, Cppcheck Premium is not used + + +Misra C 2012 +------------ +No Misra C 2012: Dir 1.1 +No Misra C 2012: Dir 2.1 +No Misra C 2012: Dir 3.1 +No Misra C 2012: Dir 4.1 +No Misra C 2012: Dir 4.2 +No Misra C 2012: Dir 4.3 +No Misra C 2012: Dir 4.4 +No Misra C 2012: Dir 4.5 +No Misra C 2012: Dir 4.6 amendment:3 +No Misra C 2012: Dir 4.7 +No Misra C 2012: Dir 4.8 +No Misra C 2012: Dir 4.9 amendment:3 +No Misra C 2012: Dir 4.10 +No Misra C 2012: Dir 4.11 amendment:3 +No Misra C 2012: Dir 4.12 +No Misra C 2012: Dir 4.13 +No Misra C 2012: Dir 4.14 amendment:2 +No Misra C 2012: Dir 4.15 amendment:3 +No Misra C 2012: Dir 5.1 amendment:4 +No Misra C 2012: Dir 5.2 amendment:4 +No Misra C 2012: Dir 5.3 amendment:4 +Yes Misra C 2012: 1.1 +Yes Misra C 2012: 1.2 +Yes Misra C 2012: 1.3 +Yes Misra C 2012: 1.4 amendment:2 +No Misra C 2012: 1.5 amendment:3 require:premium +Yes Misra C 2012: 2.1 +Yes Misra C 2012: 2.2 +Yes Misra C 2012: 2.3 +Yes Misra C 2012: 2.4 +Yes Misra C 2012: 2.5 +Yes Misra C 2012: 2.6 +Yes Misra C 2012: 2.7 +Yes Misra C 2012: 2.8 +Yes Misra C 2012: 3.1 +Yes Misra C 2012: 3.2 +Yes Misra C 2012: 4.1 +Yes Misra C 2012: 4.2 +Yes Misra C 2012: 5.1 +Yes Misra C 2012: 5.2 +Yes Misra C 2012: 5.3 +Yes Misra C 2012: 5.4 +Yes Misra C 2012: 5.5 +Yes Misra C 2012: 5.6 +Yes Misra C 2012: 5.7 +Yes Misra C 2012: 5.8 +Yes Misra C 2012: 5.9 +Yes Misra C 2012: 6.1 +Yes Misra C 2012: 6.2 +No Misra C 2012: 6.3 +Yes Misra C 2012: 7.1 +Yes Misra C 2012: 7.2 +Yes Misra C 2012: 7.3 +Yes Misra C 2012: 7.4 +No Misra C 2012: 7.5 +No Misra C 2012: 7.6 +Yes Misra C 2012: 8.1 +Yes Misra C 2012: 8.2 +No Misra C 2012: 8.3 +Yes Misra C 2012: 8.4 +Yes Misra C 2012: 8.5 +Yes Misra C 2012: 8.6 +Yes Misra C 2012: 8.7 +Yes Misra C 2012: 8.8 +Yes Misra C 2012: 8.9 +Yes Misra C 2012: 8.10 +Yes Misra C 2012: 8.11 +Yes Misra C 2012: 8.12 +Yes Misra C 2012: 8.13 +Yes Misra C 2012: 8.14 +No Misra C 2012: 8.15 +No Misra C 2012: 8.16 +No Misra C 2012: 8.17 +Yes Misra C 2012: 9.1 +Yes Misra C 2012: 9.2 +Yes Misra C 2012: 9.3 +Yes Misra C 2012: 9.4 +Yes Misra C 2012: 9.5 +No Misra C 2012: 9.6 +No Misra C 2012: 9.7 +Yes Misra C 2012: 10.1 +Yes Misra C 2012: 10.2 +Yes Misra C 2012: 10.3 +Yes Misra C 2012: 10.4 +Yes Misra C 2012: 10.5 +Yes Misra C 2012: 10.6 +Yes Misra C 2012: 10.7 +Yes Misra C 2012: 10.8 +Yes Misra C 2012: 11.1 +Yes Misra C 2012: 11.2 +Yes Misra C 2012: 11.3 +Yes Misra C 2012: 11.4 +Yes Misra C 2012: 11.5 +Yes Misra C 2012: 11.6 +Yes Misra C 2012: 11.7 +Yes Misra C 2012: 11.8 +Yes Misra C 2012: 11.9 +No Misra C 2012: 11.10 +Yes Misra C 2012: 12.1 +Yes Misra C 2012: 12.2 +Yes Misra C 2012: 12.3 +Yes Misra C 2012: 12.4 +Yes Misra C 2012: 12.5 amendment:1 +No Misra C 2012: 12.6 amendment:4 require:premium +Yes Misra C 2012: 13.1 +No Misra C 2012: 13.2 +Yes Misra C 2012: 13.3 +Yes Misra C 2012: 13.4 +Yes Misra C 2012: 13.5 +Yes Misra C 2012: 13.6 +Yes Misra C 2012: 14.1 +Yes Misra C 2012: 14.2 +Yes Misra C 2012: 14.3 +Yes Misra C 2012: 14.4 +Yes Misra C 2012: 15.1 +Yes Misra C 2012: 15.2 +Yes Misra C 2012: 15.3 +Yes Misra C 2012: 15.4 +Yes Misra C 2012: 15.5 +Yes Misra C 2012: 15.6 +Yes Misra C 2012: 15.7 +Yes Misra C 2012: 16.1 +Yes Misra C 2012: 16.2 +Yes Misra C 2012: 16.3 +Yes Misra C 2012: 16.4 +Yes Misra C 2012: 16.5 +Yes Misra C 2012: 16.6 +Yes Misra C 2012: 16.7 +Yes Misra C 2012: 17.1 +Yes Misra C 2012: 17.2 +Yes Misra C 2012: 17.3 +No Misra C 2012: 17.4 +Yes Misra C 2012: 17.5 +Yes Misra C 2012: 17.6 +Yes Misra C 2012: 17.7 +Yes Misra C 2012: 17.8 +No Misra C 2012: 17.9 +No Misra C 2012: 17.10 +No Misra C 2012: 17.11 +No Misra C 2012: 17.12 +No Misra C 2012: 17.13 +Yes Misra C 2012: 18.1 +Yes Misra C 2012: 18.2 +Yes Misra C 2012: 18.3 +Yes Misra C 2012: 18.4 +Yes Misra C 2012: 18.5 +Yes Misra C 2012: 18.6 +Yes Misra C 2012: 18.7 +Yes Misra C 2012: 18.8 +No Misra C 2012: 18.9 +No Misra C 2012: 18.10 +Yes Misra C 2012: 19.1 +Yes Misra C 2012: 19.2 +Yes Misra C 2012: 20.1 +Yes Misra C 2012: 20.2 +Yes Misra C 2012: 20.3 +Yes Misra C 2012: 20.4 +Yes Misra C 2012: 20.5 +Yes Misra C 2012: 20.6 +Yes Misra C 2012: 20.7 +Yes Misra C 2012: 20.8 +Yes Misra C 2012: 20.9 +Yes Misra C 2012: 20.10 +Yes Misra C 2012: 20.11 +Yes Misra C 2012: 20.12 +Yes Misra C 2012: 20.13 +Yes Misra C 2012: 20.14 +Yes Misra C 2012: 21.1 +Yes Misra C 2012: 21.2 +Yes Misra C 2012: 21.3 +Yes Misra C 2012: 21.4 +Yes Misra C 2012: 21.5 +Yes Misra C 2012: 21.6 +Yes Misra C 2012: 21.7 +Yes Misra C 2012: 21.8 +Yes Misra C 2012: 21.9 +Yes Misra C 2012: 21.10 +Yes Misra C 2012: 21.11 +Yes Misra C 2012: 21.12 +Yes Misra C 2012: 21.13 amendment:1 +Yes Misra C 2012: 21.14 amendment:1 +Yes Misra C 2012: 21.15 amendment:1 +Yes Misra C 2012: 21.16 amendment:1 +Yes Misra C 2012: 21.17 amendment:1 +Yes Misra C 2012: 21.18 amendment:1 +Yes Misra C 2012: 21.19 amendment:1 +Yes Misra C 2012: 21.20 amendment:1 +Yes Misra C 2012: 21.21 amendment:3 +No Misra C 2012: 21.22 amendment:3 require:premium +No Misra C 2012: 21.23 amendment:3 require:premium +No Misra C 2012: 21.24 amendment:3 require:premium +No Misra C 2012: 21.25 amendment:4 require:premium +No Misra C 2012: 21.26 amendment:4 require:premium +Yes Misra C 2012: 22.1 +Yes Misra C 2012: 22.2 +Yes Misra C 2012: 22.3 +Yes Misra C 2012: 22.4 +Yes Misra C 2012: 22.5 +Yes Misra C 2012: 22.6 +Yes Misra C 2012: 22.7 amendment:1 +Yes Misra C 2012: 22.8 amendment:1 +Yes Misra C 2012: 22.9 amendment:1 +Yes Misra C 2012: 22.10 amendment:1 +No Misra C 2012: 22.11 amendment:4 require:premium +No Misra C 2012: 22.12 amendment:4 require:premium +No Misra C 2012: 22.13 amendment:4 require:premium +No Misra C 2012: 22.14 amendment:4 require:premium +No Misra C 2012: 22.15 amendment:4 require:premium +No Misra C 2012: 22.16 amendment:4 require:premium +No Misra C 2012: 22.17 amendment:4 require:premium +No Misra C 2012: 22.18 amendment:4 require:premium +No Misra C 2012: 22.19 amendment:4 require:premium +No Misra C 2012: 22.20 amendment:4 require:premium +No Misra C 2012: 23.1 amendment:3 require:premium +No Misra C 2012: 23.2 amendment:3 require:premium +No Misra C 2012: 23.3 amendment:3 require:premium +No Misra C 2012: 23.4 amendment:3 require:premium +No Misra C 2012: 23.5 amendment:3 require:premium +No Misra C 2012: 23.6 amendment:3 require:premium +No Misra C 2012: 23.7 amendment:3 require:premium +No Misra C 2012: 23.8 amendment:3 require:premium + + +Misra C++ 2008 +-------------- +Not available, Cppcheck Premium is not used + + +Misra C++ 2023 +-------------- +Not available, Cppcheck Premium is not used diff --git a/panda/tests/misra/coverage_table b/panda/tests/misra/coverage_table new file mode 100644 index 0000000000..0395aba0d6 --- /dev/null +++ b/panda/tests/misra/coverage_table @@ -0,0 +1,156 @@ +1.1 +1.2 X (Addon) +1.3 X (Cppcheck) +2.1 X (Cppcheck) +2.2 X (Addon) +2.3 X (Addon) +2.4 X (Addon) +2.5 X (Addon) +2.6 X (Cppcheck) +2.7 X (Addon) +3.1 X (Addon) +3.2 X (Addon) +4.1 X (Addon) +4.2 X (Addon) +5.1 X (Addon) +5.2 X (Addon) +5.3 X (Cppcheck) +5.4 X (Addon) +5.5 X (Addon) +5.6 X (Addon) +5.7 X (Addon) +5.8 X (Addon) +5.9 X (Addon) +6.1 X (Addon) +6.2 X (Addon) +7.1 X (Addon) +7.2 X (Addon) +7.3 X (Addon) +7.4 X (Addon) +8.1 X (Addon) +8.2 X (Addon) +8.3 X (Cppcheck) +8.4 X (Addon) +8.5 X (Addon) +8.6 X (Addon) +8.7 X (Addon) +8.8 X (Addon) +8.9 X (Addon) +8.10 X (Addon) +8.11 X (Addon) +8.12 X (Addon) +8.13 X (Cppcheck) +8.14 X (Addon) +9.1 X (Cppcheck) +9.2 X (Addon) +9.3 X (Addon) +9.4 X (Addon) +9.5 X (Addon) +10.1 X (Addon) +10.2 X (Addon) +10.3 X (Addon) +10.4 X (Addon) +10.5 X (Addon) +10.6 X (Addon) +10.7 X (Addon) +10.8 X (Addon) +11.1 X (Addon) +11.2 X (Addon) +11.3 X (Addon) +11.4 X (Addon) +11.5 X (Addon) +11.6 X (Addon) +11.7 X (Addon) +11.8 X (Addon) +11.9 X (Addon) +12.1 X (Addon) +12.2 X (Addon) +12.3 X (Addon) +12.4 X (Addon) +13.1 X (Addon) +13.2 X (Cppcheck) +13.3 X (Addon) +13.4 X (Addon) +13.5 X (Addon) +13.6 X (Addon) +14.1 X (Addon) +14.2 X (Addon) +14.3 X (Cppcheck) +14.4 X (Addon) +15.1 X (Addon) +15.2 X (Addon) +15.3 X (Addon) +15.4 X (Addon) +15.5 X (Addon) +15.6 X (Addon) +15.7 X (Addon) +16.1 X (Addon) +16.2 X (Addon) +16.3 X (Addon) +16.4 X (Addon) +16.5 X (Addon) +16.6 X (Addon) +16.7 X (Addon) +17.1 X (Addon) +17.2 X (Addon) +17.3 X (Addon) +17.4 X (Cppcheck) +17.5 X (Cppcheck) +17.6 X (Addon) +17.7 X (Addon) +17.8 X (Addon) +18.1 X (Cppcheck) +18.2 X (Cppcheck) +18.3 X (Cppcheck) +18.4 X (Addon) +18.5 X (Addon) +18.6 X (Cppcheck) +18.7 X (Addon) +18.8 X (Addon) +19.1 X (Cppcheck) +19.2 X (Addon) +20.1 X (Addon) +20.2 X (Addon) +20.3 X (Addon) +20.4 X (Addon) +20.5 X (Addon) +20.6 X (Cppcheck) +20.7 X (Addon) +20.8 X (Addon) +20.9 X (Addon) +20.10 X (Addon) +20.11 X (Addon) +20.12 X (Addon) +20.13 X (Addon) +20.14 X (Addon) +21.1 X (Addon) +21.2 X (Addon) +21.3 X (Addon) +21.4 X (Addon) +21.5 X (Addon) +21.6 X (Addon) +21.7 X (Addon) +21.8 X (Addon) +21.9 X (Addon) +21.10 X (Addon) +21.11 X (Addon) +21.12 X (Addon) +21.13 X (Cppcheck) +21.14 X (Addon) +21.15 X (Addon) +21.16 X (Addon) +21.17 X (Cppcheck) +21.18 X (Cppcheck) +21.19 X (Addon) +21.20 X (Addon) +21.21 X (Addon) +22.1 X (Cppcheck) +22.2 X (Cppcheck) +22.3 X (Cppcheck) +22.4 X (Cppcheck) +22.5 X (Addon) +22.6 X (Cppcheck) +22.7 X (Addon) +22.8 X (Addon) +22.9 X (Addon) +22.10 X (Addon) diff --git a/panda/tests/misra/install.sh b/panda/tests/misra/install.sh new file mode 100755 index 0000000000..9c8fd385c8 --- /dev/null +++ b/panda/tests/misra/install.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +: "${CPPCHECK_DIR:=$DIR/cppcheck/}" + +if [ ! -d "$CPPCHECK_DIR" ]; then + git clone https://github.com/danmar/cppcheck.git $CPPCHECK_DIR +fi + +cd $CPPCHECK_DIR + +VERS="2.16.0" +git fetch --all --tags --force +git checkout $VERS + +#make clean +make MATCHCOMPILTER=yes CXXFLAGS="-O2" -j8 diff --git a/panda/tests/misra/suppressions.txt b/panda/tests/misra/suppressions.txt new file mode 100644 index 0000000000..4800a270bc --- /dev/null +++ b/panda/tests/misra/suppressions.txt @@ -0,0 +1,21 @@ +# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well +misra-c2012-11.4 +# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well +misra-c2012-11.5 +# Advisory: as stated in the Misra document, use of goto statements in accordance to 15.2 and 15.3 is ok +misra-c2012-15.1 +# Advisory: union types can be used +misra-c2012-19.2 +# Advisory: The # and ## preprocessor operators should not be used +misra-c2012-20.10 + +# needed since not all of these suppressions are applicable to all builds +unmatchedSuppression + +# All interrupt handlers are defined, including ones we don't use +unusedFunction:*/interrupt_handlers*.h + +# all of the below suppressions are from new checks introduced after updating +# cppcheck from 2.5 -> 2.13. they are listed here to separate the update from +# fixing the violations and all are intended to be removed soon after +misra-c2012-2.5 # unused macros. a few legit, rest aren't common between F4/H7 builds. should we do this in the unusedFunction pass? diff --git a/panda/tests/misra/test_misra.sh b/panda/tests/misra/test_misra.sh new file mode 100755 index 0000000000..d7b9c6efdf --- /dev/null +++ b/panda/tests/misra/test_misra.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +PANDA_DIR=$(realpath $DIR/../../) +OPENDBC_ROOT=$(python3 -c "import opendbc; print(opendbc.INCLUDE_PATH)") + +GREEN="\e[1;32m" +YELLOW="\e[1;33m" +RED="\e[1;31m" +NC='\033[0m' + +: "${CPPCHECK_DIR:=$DIR/cppcheck/}" + +# install cppcheck if missing +if [ -z "${SKIP_CPPCHECK_INSTALL}" ]; then + $DIR/install.sh +fi + +# ensure checked in coverage table is up to date +cd $DIR +if [ -z "$SKIP_TABLES_DIFF" ]; then + python3 $CPPCHECK_DIR/addons/misra.py -generate-table > coverage_table + if ! git diff --quiet coverage_table; then + echo -e "${YELLOW}MISRA coverage table doesn't match. Update and commit:${NC}" + exit 3 + fi +fi + +cd $PANDA_DIR +if [ -z "${SKIP_BUILD}" ]; then + scons -j8 +fi + +CHECKLIST=$DIR/checkers.txt +echo "Cppcheck checkers list from test_misra.sh:" > $CHECKLIST + +cppcheck() { + # get all gcc defines: arm-none-eabi-gcc -dM -E - < /dev/null + COMMON_DEFINES="-D__GNUC__=9 -UCMSIS_NVIC_VIRTUAL -UCMSIS_VECTAB_VIRTUAL -UPANDA_JUNGLE -UBOOTSTUB" + + # note that cppcheck build cache results in inconsistent results as of v2.13.0 + OUTPUT=$DIR/.output.log + + echo -e "\n\n\n\n\nTEST variant options:" >> $CHECKLIST + echo -e ""${@//$PANDA_DIR/}"\n\n" >> $CHECKLIST # (absolute path removed) + + $CPPCHECK_DIR/cppcheck --inline-suppr \ + -I $PANDA_DIR \ + -I "$(arm-none-eabi-gcc -print-file-name=include)" \ + -I $OPENDBC_ROOT \ + --suppressions-list=$DIR/suppressions.txt --suppress=*:*inc/* \ + --suppress=*:*include/* --error-exitcode=2 --check-level=exhaustive --safety \ + --platform=arm32-wchar_t4 $COMMON_DEFINES --checkers-report=$CHECKLIST.tmp \ + --std=c11 "$@" 2>&1 | tee $OUTPUT + + cat $CHECKLIST.tmp >> $CHECKLIST + rm $CHECKLIST.tmp + # cppcheck bug: some MISRA errors won't result in the error exit code, + # so check the output (https://trac.cppcheck.net/ticket/12440#no1) + if grep -e "misra violation" -e "error" -e "style: " $OUTPUT > /dev/null; then + printf "${RED}** FAILED: MISRA violations found!${NC}\n" + exit 1 + fi +} + +PANDA_OPTS="--enable=all --disable=unusedFunction --addon=misra" + +printf "\n${GREEN}** PANDA H7 CODE **${NC}\n" +cppcheck $PANDA_OPTS -DSTM32H7 -DSTM32H725xx -I $PANDA_DIR/board/stm32h7/inc/ $PANDA_DIR/board/main.c + +# unused needs to run globally +#printf "\n${GREEN}** UNUSED ALL CODE **${NC}\n" +#cppcheck --enable=unusedFunction --quiet $PANDA_DIR/board/ + +printf "\n${GREEN}Success!${NC} took $SECONDS seconds\n" + +# ensure list of checkers is up to date +cd $DIR +if [ -z "$SKIP_TABLES_DIFF" ] && ! git diff --quiet $CHECKLIST; then + echo -e "\n${YELLOW}WARNING: Cppcheck checkers.txt report has changed. Review and commit...${NC}" + exit 4 +fi diff --git a/panda/tests/misra/test_mutation.py b/panda/tests/misra/test_mutation.py new file mode 100755 index 0000000000..762ab852c7 --- /dev/null +++ b/panda/tests/misra/test_mutation.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +import os +import glob +import pytest +import shutil +import subprocess +import tempfile +import random + +HERE = os.path.abspath(os.path.dirname(__file__)) +ROOT = os.path.join(HERE, "../../") + +IGNORED_PATHS = ( + 'board/obj', + 'board/jungle', + 'board/stm32h7/inc', + 'board/fake_stm.h', + + # bootstub only files + 'board/flasher.h', + 'board/bootstub.c', + 'board/bootstub_declarations.h', + 'board/stm32h7/llflash.h', +) + +mutations = [ + (None, None, False), # no mods, should pass + ("board/stm32h7/llfdcan.h", "s/return ret;/if (true) { return ret; } else { return false; }/g", True), +] + +patterns = [ + # misra-c2012-13.3 + "$a void test(int tmp) { int tmp2 = tmp++ + 2; if (tmp2) {;}}", + # misra-c2012-13.4 + "$a int test(int x, int y) { return (x=2) && (y=2); }", + # misra-c2012-13.5 + "$a void test(int tmp) { if (true && tmp++) {;} }", + # misra-c2012-13.6 + "$a void test(int tmp) { if (sizeof(tmp++)) {;} }", + # misra-c2012-14.1 + "$a void test(float len) { for (float j = 0; j < len; j++) {;} }", + # misra-c2012-14.4 + "$a void test(int len) { if (len - 8) {;} }", + # misra-c2012-16.4 + r"$a void test(int temp) {switch (temp) { case 1: ; }}\n", + # misra-c2012-17.8 + "$a void test(int cnt) { for (cnt=0;;cnt++) {;} }", + # misra-c2012-20.4 + r"$a #define auto 1\n", + # misra-c2012-20.5 + r"$a #define TEST 1\n#undef TEST\n", +] + +all_files = glob.glob('board/**', root_dir=ROOT, recursive=True) +files = [f for f in all_files if f.endswith(('.c', '.h')) and not f.startswith(IGNORED_PATHS)] +assert len(files) > 50, all(d in files for d in ('board/main.c', 'board/stm32h7/llfdcan.h')) + +for p in patterns: + mutations.append((random.choice(files), p, True)) + +# TODO: remove sampling once test_misra.sh is faster +mutations = random.sample(mutations, 2) + +@pytest.mark.parametrize("fn, patch, should_fail", mutations) +def test_misra_mutation(fn, patch, should_fail): + with tempfile.TemporaryDirectory() as tmp: + shutil.copytree(ROOT, tmp + "/panda", dirs_exist_ok=True) + + # apply patch + if fn is not None: + r = os.system(f"cd {tmp}/panda && sed -i '{patch}' {fn}") + assert r == 0 + + # run test + r = subprocess.run("SKIP_TABLES_DIFF=1 panda/tests/misra/test_misra.sh", cwd=tmp, shell=True) + failed = r.returncode != 0 + assert failed == should_fail diff --git a/panda/tests/setup_device_ci.sh b/panda/tests/setup_device_ci.sh new file mode 100755 index 0000000000..fe28b8612c --- /dev/null +++ b/panda/tests/setup_device_ci.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +set -e + +if [ -z "$SOURCE_DIR" ]; then + echo "SOURCE_DIR must be set" + exit 1 +fi + +if [ -z "$GIT_COMMIT" ]; then + echo "GIT_COMMIT must be set" + exit 1 +fi + +if [ -z "$TEST_DIR" ]; then + echo "TEST_DIR must be set" + exit 1 +fi + +CONTINUE_PATH="/data/continue.sh" +tee $CONTINUE_PATH << EOF +#!/usr/bin/env bash + +sudo abctl --set_success + +# patch sshd config +sudo mount -o rw,remount / +sudo sed -i "s,/data/params/d/GithubSshKeys,/usr/comma/setup_keys," /etc/ssh/sshd_config +sudo systemctl daemon-reload +sudo systemctl restart ssh +sudo systemctl disable ssh-param-watcher.path +sudo systemctl disable ssh-param-watcher.service +sudo mount -o ro,remount / + +sudo systemctl stop power_monitor + +while true; do + if ! sudo systemctl is-active -q ssh; then + sudo systemctl start ssh + fi + sleep 5s +done + +sleep infinity +EOF +chmod +x $CONTINUE_PATH + + +# set up environment +if [ ! -d "$SOURCE_DIR" ]; then + git clone https://github.com/commaai/panda.git $SOURCE_DIR +fi + +# setup device/SOM state +SOM_ST_IO=49 +echo $SOM_ST_IO > /sys/class/gpio/export || true +echo out > /sys/class/gpio/gpio${SOM_ST_IO}/direction +echo 1 > /sys/class/gpio/gpio${SOM_ST_IO}/value + +# checkout panda commit +cd $SOURCE_DIR + +rm -f .git/index.lock +git reset --hard +git fetch --no-tags --no-recurse-submodules -j4 --verbose --depth 1 origin $GIT_COMMIT +find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \; +git reset --hard $GIT_COMMIT +git checkout $GIT_COMMIT +git clean -xdff + +echo "git checkout done, t=$SECONDS" +du -hs $SOURCE_DIR $SOURCE_DIR/.git + +rsync -a --delete $SOURCE_DIR $TEST_DIR + +echo "$TEST_DIR synced with $GIT_COMMIT, t=$SECONDS" diff --git a/panda/tests/som/on-device.py b/panda/tests/som/on-device.py new file mode 100755 index 0000000000..aa432efee8 --- /dev/null +++ b/panda/tests/som/on-device.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import os +import time + +from opendbc.car.structs import CarParams +from panda import Panda + + +if __name__ == "__main__": + flag_set = False + while True: + try: + with Panda(disable_checks=False) as p: + if not flag_set: + p.set_heartbeat_disabled() + p.set_safety_mode(CarParams.SafetyModel.elm327, 30) + flag_set = True + + # shutdown when told + ch = p.can_health(0) + if ch['can_data_speed'] == 1000: + os.system("sudo poweroff") + except Exception as e: + print(str(e)) + time.sleep(0.5) diff --git a/panda/tests/som/test_bootkick.py b/panda/tests/som/test_bootkick.py new file mode 100644 index 0000000000..497cfd8132 --- /dev/null +++ b/panda/tests/som/test_bootkick.py @@ -0,0 +1,154 @@ +import time +import pytest + +from opendbc.car.structs import CarParams +from panda import Panda, PandaJungle + +PANDA_SERIAL = "300008001851333037333932" +JUNGLE_SERIAL = "26001c001451313236343430" + +OBDC_PORT = 1 + +@pytest.fixture(autouse=True, scope="function") +def pj(): + jungle = PandaJungle(JUNGLE_SERIAL) + jungle.flash() + + jungle.reset() + jungle.set_ignition(False) + + yield jungle + + #jungle.set_panda_power(False) + jungle.close() + +@pytest.fixture(scope="function") +def p(pj): + # note that the 3X's panda lib isn't updated, which + # shold be fine since it only uses stable APIs + pj.set_panda_power(True) + assert Panda.wait_for_panda(PANDA_SERIAL, 10) + p = Panda(PANDA_SERIAL) + p.flash() + p.reset() + yield p + p.close() + +def setup_state(panda, jungle, state): + jungle.set_panda_power(0) + + if state == "off": + wait_for_full_poweroff(jungle) + elif state == "normal boot": + jungle.set_panda_individual_power(OBDC_PORT, 1) + elif state == "QDL": + time.sleep(0.5) + jungle.set_panda_individual_power(OBDC_PORT, 1) + elif state == "ready to bootkick": + wait_for_full_poweroff(jungle) + jungle.set_panda_individual_power(OBDC_PORT, 1) + wait_for_boot(panda, jungle) + set_som_shutdown_flag(panda) + panda.set_safety_mode(CarParams.SafetyModel.silent) + panda.send_heartbeat() + wait_for_som_shutdown(panda, jungle) + else: + raise ValueError(f"unkown state: {state}") + + +def wait_for_som_shutdown(panda, jungle): + st = time.monotonic() + while panda.read_som_gpio(): + # can take a while for the SOM to fully shutdown + if time.monotonic() - st > 120: + raise Exception("SOM didn't shutdown in time") + if check_som_boot_flag(panda): + raise Exception(f"SOM rebooted instead of shutdown: {time.monotonic() - st}s") + time.sleep(0.5) + dt = time.monotonic() - st + print("waiting for shutdown", round(dt)) + dt = time.monotonic() - st + print(f"took {dt:.2f}s for SOM to shutdown") + +def wait_for_full_poweroff(jungle, timeout=30): + st = time.monotonic() + + time.sleep(15) + while PANDA_SERIAL in Panda.list(): + if time.monotonic() - st > timeout: + raise Exception("took too long for device to turn off") + + health = jungle.health() + assert all(health[f"ch{i}_power"] < 0.1 for i in range(1, 7)) + +def check_som_boot_flag(panda): + h = panda.health() + return h['safety_mode'] == CarParams.SafetyModel.elm327 and h['safety_param'] == 30 + +def set_som_shutdown_flag(panda): + panda.set_can_data_speed_kbps(0, 1000) + +def wait_for_boot(panda, jungle, reset_expected=False, bootkick=False, timeout=120): + st = time.monotonic() + + Panda.wait_for_panda(PANDA_SERIAL, timeout) + panda.reconnect() + if bootkick: + assert panda.health()['uptime'] > 20 + else: + assert panda.health()['uptime'] < 3 + + for i in range(3): + assert not check_som_boot_flag(panda) + time.sleep(1) + + # wait for SOM to bootup + while not check_som_boot_flag(panda): + if time.monotonic() - st > timeout: + raise Exception("SOM didn't boot in time") + time.sleep(1.0) + + assert panda.health()['som_reset_triggered'] == reset_expected + +def test_cold_boot(p, pj): + setup_state(p, pj, "off") + setup_state(p, pj, "normal boot") + wait_for_boot(p, pj) + +def test_bootkick_ignition_line(p, pj): + setup_state(p, pj, "ready to bootkick") + pj.set_ignition(True) + wait_for_boot(p, pj, bootkick=True) + +@pytest.mark.skip("test isn't reliable yet") +def test_bootkick_can_ignition(p, pj): + setup_state(p, pj, "ready to bootkick") + for _ in range(10): + # Mazda ignition signal + pj.can_send(0x9E, b'\xc0\x00\x00\x00\x00\x00\x00\x00', 0) + time.sleep(0.5) + wait_for_boot(p, pj, bootkick=True) + +def test_recovery_from_qdl(p, pj): + setup_state(p, pj, "ready to bootkick") + + # put into QDL using the FORCE_USB_BOOT pin + for i in range(10): + pj.set_header_pin(i, 1) + + # try to boot + time.sleep(1) + pj.set_ignition(True) + time.sleep(3) + + # release FORCE_USB_BOOT + for i in range(10): + pj.set_header_pin(i, 0) + + # normally, this GPIO is set immediately since it's first enabled in the ABL + for i in range(17): + assert not p.read_som_gpio() + time.sleep(1) + + # should boot after 45s + wait_for_boot(p, pj, reset_expected=True, bootkick=True, timeout=120) diff --git a/panda/tests/usbprotocol/test_comms.py b/panda/tests/usbprotocol/test_comms.py new file mode 100755 index 0000000000..446a134119 --- /dev/null +++ b/panda/tests/usbprotocol/test_comms.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +import random +import unittest + +from opendbc.car.structs import CarParams +from panda import DLC_TO_LEN, USBPACKET_MAX_SIZE, pack_can_buffer, unpack_can_buffer +from panda.tests.libpanda import libpanda_py + +lpp = libpanda_py.libpanda + +CHUNK_SIZE = USBPACKET_MAX_SIZE +TX_QUEUES = (lpp.tx1_q, lpp.tx2_q, lpp.tx3_q) + + +def unpackage_can_msg(pkt): + dat_len = DLC_TO_LEN[pkt[0].data_len_code] + dat = bytes(pkt[0].data[0:dat_len]) + return pkt[0].addr, dat, pkt[0].bus + + +def random_can_messages(n, bus=None): + msgs = [] + for _ in range(n): + if bus is None: + bus = random.randint(0, 3) + address = random.randint(1, (1 << 29) - 1) + data = bytes([random.getrandbits(8) for _ in range(DLC_TO_LEN[random.randrange(0, len(DLC_TO_LEN))])]) + msgs.append((address, data, bus)) + return msgs + + +class TestPandaComms(unittest.TestCase): + def setUp(self): + lpp.comms_can_reset() + + def test_tx_queues(self): + for bus in range(len(TX_QUEUES)): + message = (0x100, b"test", bus) + + can_pkt_tx = libpanda_py.make_CANPacket(message[0], message[2], message[1]) + can_pkt_rx = libpanda_py.ffi.new('CANPacket_t *') + + assert lpp.can_push(TX_QUEUES[bus], can_pkt_tx), "CAN push failed" + assert lpp.can_pop(TX_QUEUES[bus], can_pkt_rx), "CAN pop failed" + + assert unpackage_can_msg(can_pkt_rx) == message + + def test_comms_reset_rx(self): + # store some test messages in the queue + test_msg = (0x100, b"test", 0) + for _ in range(100): + can_pkt_tx = libpanda_py.make_CANPacket(test_msg[0], test_msg[2], test_msg[1]) + lpp.can_push(lpp.rx_q, can_pkt_tx) + + # read a small chunk such that we have some overflow + TINY_CHUNK_SIZE = 6 + dat = libpanda_py.ffi.new(f"uint8_t[{TINY_CHUNK_SIZE}]") + rx_len = lpp.comms_can_read(dat, TINY_CHUNK_SIZE) + assert rx_len == TINY_CHUNK_SIZE, "comms_can_read returned too little data" + + _, overflow = unpack_can_buffer(bytes(dat)) + assert len(overflow) > 0, "overflow buffer should not be empty" + + # reset the comms to clear the overflow buffer on the panda side + lpp.comms_can_reset() + + # read a large chunk, which should now contain valid messages + LARGE_CHUNK_SIZE = 512 + dat = libpanda_py.ffi.new(f"uint8_t[{LARGE_CHUNK_SIZE}]") + rx_len = lpp.comms_can_read(dat, LARGE_CHUNK_SIZE) + assert rx_len == LARGE_CHUNK_SIZE, "comms_can_read returned too little data" + + msgs, _ = unpack_can_buffer(bytes(dat)) + assert len(msgs) > 0, "message buffer should not be empty" + for m in msgs: + assert m == test_msg, "message buffer should contain valid test messages" + + def test_comms_reset_tx(self): + # store some test messages in the queue + test_msg = (0x100, b"test", 0) + packed = pack_can_buffer([test_msg for _ in range(100)], chunk=True) + + # write a small chunk such that we have some overflow + TINY_CHUNK_SIZE = 6 + lpp.comms_can_write(bytes(packed[0][:TINY_CHUNK_SIZE]), TINY_CHUNK_SIZE) + + # reset the comms to clear the overflow buffer on the panda side + lpp.comms_can_reset() + + # write a full valid chunk, which should now contain valid messages + lpp.comms_can_write(bytes(packed[1]), len(packed[1])) + + # read the messages from the queue and make sure they're valid + queue_msgs = [] + pkt = libpanda_py.ffi.new('CANPacket_t *') + while lpp.can_pop(TX_QUEUES[0], pkt): + queue_msgs.append(unpackage_can_msg(pkt)) + + assert len(queue_msgs) > 0, "message buffer should not be empty" + for m in queue_msgs: + assert m == test_msg, "message buffer should contain valid test messages" + + + def test_can_send_usb(self): + lpp.set_safety_hooks(CarParams.SafetyModel.allOutput, 0) + + for bus in range(3): + with self.subTest(bus=bus): + for _ in range(100): + msgs = random_can_messages(200, bus=bus) + packed = pack_can_buffer(msgs) + + # Simulate USB bulk chunks + for buf in packed: + for i in range(0, len(buf), CHUNK_SIZE): + chunk_len = min(CHUNK_SIZE, len(buf) - i) + lpp.comms_can_write(bytes(buf[i:i+chunk_len]), chunk_len) + + # Check that they ended up in the right buffers + queue_msgs = [] + pkt = libpanda_py.ffi.new('CANPacket_t *') + while lpp.can_pop(TX_QUEUES[bus], pkt): + queue_msgs.append(unpackage_can_msg(pkt)) + + self.assertEqual(len(queue_msgs), len(msgs)) + self.assertEqual(queue_msgs, msgs) + + def test_can_receive_usb(self): + msgs = random_can_messages(50000) + packets = [libpanda_py.make_CANPacket(m[0], m[2], m[1]) for m in msgs] + + rx_msgs = [] + overflow_buf = b"" + while len(packets) > 0: + # Push into queue + while lpp.can_slots_empty(lpp.rx_q) > 0 and len(packets) > 0: + lpp.can_push(lpp.rx_q, packets.pop(0)) + + # Simulate USB bulk IN chunks + MAX_TRANSFER_SIZE = 16384 + dat = libpanda_py.ffi.new(f"uint8_t[{CHUNK_SIZE}]") + while True: + buf = b"" + while len(buf) < MAX_TRANSFER_SIZE: + max_size = min(CHUNK_SIZE, MAX_TRANSFER_SIZE - len(buf)) + rx_len = lpp.comms_can_read(dat, max_size) + buf += bytes(dat[0:rx_len]) + if rx_len < max_size: + break + + if len(buf) == 0: + break + unpacked_msgs, overflow_buf = unpack_can_buffer(overflow_buf + buf) + rx_msgs.extend(unpacked_msgs) + + self.assertEqual(len(rx_msgs), len(msgs)) + self.assertEqual(rx_msgs, msgs) + + +if __name__ == "__main__": + unittest.main() diff --git a/panda/tests/usbprotocol/test_pandalib.py b/panda/tests/usbprotocol/test_pandalib.py new file mode 100755 index 0000000000..ef725948c7 --- /dev/null +++ b/panda/tests/usbprotocol/test_pandalib.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import random +import unittest + +from panda import pack_can_buffer, unpack_can_buffer, DLC_TO_LEN + +class PandaTestPackUnpack(unittest.TestCase): + def test_panda_lib_pack_unpack(self): + overflow_buf = b'' + + to_pack = [] + for _ in range(10000): + address = random.randint(1, (1 << 29) - 1) + data = bytes([random.getrandbits(8) for _ in range(DLC_TO_LEN[random.randrange(0, len(DLC_TO_LEN))])]) + to_pack.append((address, data, 0)) + + packed = pack_can_buffer(to_pack) + unpacked = [] + for dat in packed: + msgs, overflow_buf = unpack_can_buffer(overflow_buf + dat) + unpacked.extend(msgs) + + self.assertEqual(unpacked, to_pack) + +if __name__ == "__main__": + unittest.main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..9a8de2b746 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,274 @@ +[project] +name = "openpilot" +requires-python = ">= 3.11, < 3.13" +license = {text = "MIT License"} +version = "0.1.0" +description = "an open source driver assistance system" +authors = [ + {name ="Vehicle Researcher", email="user@comma.ai"} +] + +dependencies = [ + # multiple users + "sounddevice", # micd + soundd + "pyserial", # pigeond + qcomgpsd + "requests", # many one-off uses + "sympy", # rednose + friends + "crcmod", # cars + qcomgpsd + "tqdm", # cars (fw_versions.py) on start + many one-off uses + + # hardwared + "smbus2", # configuring amp + + # core + "cffi", + "scons", + "pycapnp==2.1.0", + "Cython", + "setuptools", + "numpy >=2.0", + + # body / webrtcd + "aiohttp", + "aiortc", + # aiortc does not put an upper bound on pyopenssl and is now incompatible + # with the latest release + "pyopenssl < 24.3.0", + "pyaudio", + + # ubloxd (TODO: just use struct) + "kaitaistruct", + + # panda + "libusb1", + "spidev; platform_system == 'Linux'", + + # modeld + "onnx >= 1.14.0", + + # logging + "pyzmq", + "sentry-sdk", + "xattr", # used in place of 'os.getxattr' for macos compatibility + + # athena + "PyJWT", + "json-rpc", + "websocket_client", + + # acados deps + "casadi >=3.6.6", # 3.12 fixed in 3.6.6 + "future-fstrings", + + # joystickd + "inputs", + + # these should be removed + "psutil", + "pycryptodome", # used in updated/casync, panda, body, and a test + "setproctitle", + + # logreader + "zstandard", + + # ui + "qrcode", +] + +[project.optional-dependencies] +docs = [ + "Jinja2", + "natsort", + "mkdocs", +] + +testing = [ + "hypothesis ==6.47.*", + "mypy", + "pytest", + "pytest-cpp", + "pytest-subtests", + # https://github.com/pytest-dev/pytest-xdist/pull/1229 + "pytest-xdist @ git+https://github.com/sshane/pytest-xdist@2b4372bd62699fb412c4fe2f95bf9f01bd2018da", + "pytest-timeout", + "pytest-randomly", + "pytest-asyncio", + "pytest-mock", + "pytest-repeat", + "ruff", + "codespell", + "pre-commit-hooks", +] + +dev = [ + "av", + "azure-identity", + "azure-storage-blob", + "dbus-next", # TODO: remove once we moved everything to jeepney + "dictdiffer", + "jeepney", + "matplotlib", + "opencv-python-headless", + "parameterized >=0.8, <0.9", + "pyautogui", + "pygame", + "pyopencl; platform_machine != 'aarch64'", # broken on arm64 + "pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version + "pywinctl", + "pyprof2calltree", + "tabulate", + "types-requests", + "types-tabulate", + "raylib < 5.5.0.3", # TODO: unpin when they fix https://github.com/electronstudio/raylib-python-cffi/issues/186 +] + +tools = [ + "metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl ; (platform_machine != 'aarch64')", + "dearpygui>=2.1.0", +] + +[project.urls] +Homepage = "https://github.com/commaai/openpilot" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.wheel] +packages = [ "." ] + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.pytest.ini_options] +minversion = "6.0" +addopts = "--ignore=openpilot/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup" +cpp_files = "test_*" +cpp_harness = "selfdrive/test/cpp_harness.py" +python_files = "test_*.py" +asyncio_default_fixture_loop_scope = "function" +#timeout = "30" # you get this long by default +markers = [ + "slow: tests that take awhile to run and can be skipped with -m 'not slow'", + "tici: tests that are only meant to run on the C3/C3X", + "skip_tici_setup: mark test to skip tici setup fixture" +] +testpaths = [ + "common", + "selfdrive", + "system/manager", + "system/updated", + "system/athena", + "system/camerad", + "system/hardware", + "system/loggerd", + "system/tests", + "system/ubloxd", + "system/webrtc", + "tools/lib/tests", + "tools/replay", + "tools/cabana", + "cereal/messaging/tests", +] + +[tool.codespell] +quiet-level = 3 +# if you've got a short variable name that's getting flagged, add it here +ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite" +builtin = "clear,rare,informal,code,names,en-GB_to_en-US" +skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.ts, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*" + +[tool.mypy] +python_version = "3.11" +exclude = [ + "cereal/", + "msgq/", + "msgq_repo/", + "opendbc/", + "opendbc_repo/", + "panda/", + "rednose/", + "rednose_repo/", + "tinygrad/", + "tinygrad_repo/", + "teleoprtc/", + "teleoprtc_repo/", + "third_party/", +] + +# third-party packages +ignore_missing_imports=true + +# helpful warnings +warn_redundant_casts=true +warn_unreachable=true +warn_unused_ignores=true + +# restrict dynamic typing +warn_return_any=true + +# allow implicit optionals for default args +implicit_optional = true + +local_partial_types=true +explicit_package_bases=true +disable_error_code = "annotation-unchecked" + +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +indent-width = 2 +lint.select = [ + "E", "F", "W", "PIE", "C4", "ISC", "A", "B", + "NPY", # numpy + "UP", # pyupgrade + "TRY203", "TRY400", "TRY401", # try/excepts + "RUF008", "RUF100", + "TID251", + "PLR1704", +] +lint.ignore = [ + "E741", + "E402", + "C408", + "ISC003", + "B027", + "B024", + "NPY002", # new numpy random syntax is worse + "UP038", # (x, y) -> x|y for isinstance +] +line-length = 160 +target-version ="py311" +exclude = [ + "body", + "cereal", + "panda", + "opendbc", + "opendbc_repo", + "rednose_repo", + "tinygrad_repo", + "teleoprtc", + "teleoprtc_repo", + "third_party", + "*.ipynb", + "generated", +] +lint.flake8-implicit-str-concat.allow-multiline = false + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"selfdrive".msg = "Use openpilot.selfdrive" +"common".msg = "Use openpilot.common" +"system".msg = "Use openpilot.system" +"third_party".msg = "Use openpilot.third_party" +"tools".msg = "Use openpilot.tools" +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" +"unittest".msg = "Use pytest" +"time.time".msg = "Use time.monotonic" + +# raylib banned APIs +"pyray.measure_text_ex".msg = "Use openpilot.system.ui.lib.text_measure" +"pyray.is_mouse_button_pressed".msg = "This can miss events. Use Widget._handle_mouse_press" +"pyray.is_mouse_button_released".msg = "This can miss events. Use Widget._handle_mouse_release" +"pyray.draw_text".msg = "Use a function (such as rl.draw_font_ex) that takes font as an argument" + +[tool.ruff.format] +quote-style = "preserve" diff --git a/rednose b/rednose new file mode 120000 index 0000000000..674cfec35f --- /dev/null +++ b/rednose @@ -0,0 +1 @@ +rednose_repo/rednose \ No newline at end of file diff --git a/rednose_repo/.dockerignore b/rednose_repo/.dockerignore new file mode 100644 index 0000000000..5b2d46270d --- /dev/null +++ b/rednose_repo/.dockerignore @@ -0,0 +1 @@ +.sconsign.dblite diff --git a/rednose_repo/.editorconfig b/rednose_repo/.editorconfig new file mode 100644 index 0000000000..e0da061025 --- /dev/null +++ b/rednose_repo/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[{*.py, *.pyx, *pxd}] +charset = utf-8 +indent_style = space +indent_size = 2 diff --git a/rednose_repo/.gitignore b/rednose_repo/.gitignore new file mode 100644 index 0000000000..bf2b50d221 --- /dev/null +++ b/rednose_repo/.gitignore @@ -0,0 +1,151 @@ +generated/ +.sconsign.dblite +*.swp +*.tmp + +# Cython intermediates +*_pyx.cpp +*_pyx.h +*_pyx_api.h +*.os + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.a +*.o +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/rednose_repo/.pre-commit-config.yaml b/rednose_repo/.pre-commit-config.yaml new file mode 100644 index 0000000000..b908de2968 --- /dev/null +++ b/rednose_repo/.pre-commit-config.yaml @@ -0,0 +1,21 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: check-ast + - id: check-json + - id: check-xml + - id: check-yaml + - id: check-merge-conflict + - id: check-symlinks + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.4.0 + hooks: + - id: mypy + additional_dependencies: ['numpy'] +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.2 + hooks: + - id: ruff diff --git a/rednose_repo/Dockerfile b/rednose_repo/Dockerfile new file mode 100644 index 0000000000..57bd4c1ea4 --- /dev/null +++ b/rednose_repo/Dockerfile @@ -0,0 +1,14 @@ +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y capnproto libcapnp-dev clang wget git autoconf libtool curl make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-openssl libeigen3-dev python3-pip python3-dev + +WORKDIR /project + +ENV PYTHONPATH=/project + +COPY . . +RUN rm -rf .git +RUN pip3 install --break-system-packages --no-cache-dir -r requirements.txt +RUN python3 setup.py install +RUN scons -c && scons -j$(nproc) diff --git a/rednose_repo/LICENSE b/rednose_repo/LICENSE new file mode 100644 index 0000000000..6f1774f1d9 --- /dev/null +++ b/rednose_repo/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 comma.ai + +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/rednose_repo/README.md b/rednose_repo/README.md new file mode 100644 index 0000000000..264958bfcd --- /dev/null +++ b/rednose_repo/README.md @@ -0,0 +1,51 @@ +## Introduction +The kalman filter framework described here is an incredibly powerful tool for any optimization problem, +but particularly for visual odometry, sensor fusion localization or SLAM. It is designed to provide very +accurate results, work online or offline, be fairly computationally efficient, be easy to design filters with in +python. + +![](examples/kinematic_kf.png) + + +## Feature walkthrough + +### Extended Kalman Filter with symbolic Jacobian computation +Most dynamic systems can be described as a Hidden Markov Process. To estimate the state of such a system with noisy +measurements one can use a Recursive Bayesian estimator. For a linear Markov Process a regular linear Kalman filter is optimal. +Unfortunately, a lot of systems are non-linear. Extended Kalman Filters can model systems by linearizing the non-linear +system at every step, this provides a close to optimal estimator when the linearization is good enough. If the linearization +introduces too much noise, one can use an Iterated Extended Kalman Filter, Unscented Kalman Filter or a Particle Filter. For +most applications those estimators are overkill. They add a lot of complexity and require a lot of additional compute. + +Conventionally Extended Kalman Filters are implemented by writing the system's dynamic equations and then manually symbolically +calculating the Jacobians for the linearization. For complex systems this is time consuming and very prone to calculation errors. +This library symbolically computes the Jacobians using sympy to simplify the system's definition and remove the possibility of introducing calculation errors. + +### Error State Kalman Filter +3D localization algorithms usually also require estimating orientation of an object in 3D. Orientation is generally represented +with euler angles or quaternions. + +Euler angles have several problems, there are multiple ways to represent the same orientation, +gimbal lock can cause the loss of a degree of freedom and lastly their behaviour is very non-linear when errors are large. +Quaternions with one strictly positive dimension don't suffer from these issues, but have another set of problems. +Quaternions need to be normalized otherwise they will grow unbounded, but this cannot be cleanly enforced in a kalman filter. +Most importantly though a quaternion has 4 dimensions, but only represents 3 degrees of freedom, so there is one redundant dimension. + +Kalman filters are designed to minimize the error of the system's state. It is possible to have a kalman filter where state and the error of the state are represented in a different space. As long as there is an error function that can compute the error based on the true state and estimated state. It is problematic to have redundant dimensions in the error of the kalman filter, but not in the state. A good compromise then, is to use the quaternion to represent the system's attitude state and use euler angles to describe the error in attitude. This library supports and defining an arbitrary error that is in a different space than the state. [Joan Solà](https://arxiv.org/abs/1711.02508) has written a comprehensive description of using ESKFs for robust 3D orientation estimation. + +### Multi-State Constraint Kalman Filter +How do you integrate feature-based visual odometry with a Kalman filter? The problem is that one cannot write an observation equation for 2D feature observations in image space for a localization kalman filter. One needs to give the feature observation a depth so it has a 3D position, then one can write an obvervation equation in the kalman filter. This is possible by tracking the feature across frames and then estimating the depth. However, the solution is not that simple, the depth estimated by tracking the feature across frames depends on the location of the camera at those frames, and thus the state of the kalman filter. This creates a positive feedback loop where the kalman filter wrongly gains confidence in it's position because the feature position updates reinforce it. + +The solution is to use an [MSCKF](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.437.1085&rep=rep1&type=pdf), which this library fully supports. + +### Rauch–Tung–Striebel smoothing +When doing offline estimation with a kalman filter there can be an initialization period where states are badly estimated. +Global estimators don't suffer from this, to make our kalman filter competitive with global optimizers we can run the filter +backwards using an RTS smoother. Those combined with potentially multiple forward and backwards passes of the data should make +performance very close to global optimization. + +### Mahalanobis distance outlier rejector +A lot of measurements do not come from a Gaussian distribution and as such have outliers that do not fit the statistical model +of the Kalman filter. This can cause a lot of performance issues if not dealt with. This library allows the use of a mahalanobis +distance statistical test on the incoming measurements to deal with this. Note that good initialization is critical to prevent +good measurements from being rejected. diff --git a/rednose_repo/SConstruct b/rednose_repo/SConstruct new file mode 100644 index 0000000000..c668d1befa --- /dev/null +++ b/rednose_repo/SConstruct @@ -0,0 +1,59 @@ +import os +import subprocess +import sysconfig +import numpy as np + +arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() + +common = '' + +python_path = sysconfig.get_paths()['include'] +cpppath = [ + '#', + '#rednose', + '#rednose/examples/generated', + '/usr/lib/include', + python_path, + np.get_include(), +] + +env = Environment( + ENV=os.environ, + CC='clang', + CXX='clang++', + CCFLAGS=[ + "-g", + "-fPIC", + "-O2", + "-Werror=implicit-function-declaration", + "-Werror=incompatible-pointer-types", + "-Werror=int-conversion", + "-Werror=return-type", + "-Werror=format-extra-args", + "-Wshadow", + ], + LIBPATH=["#rednose/examples/generated"], + CFLAGS="-std=gnu11", + CXXFLAGS="-std=c++1z", + CPPPATH=cpppath, + REDNOSE_ROOT=Dir("#").abspath, + tools=["default", "cython", "rednose_filter"], +) + +# Cython build enviroment +envCython = env.Clone() +envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-shadow", "-Wno-deprecated-declarations"] + +envCython["LIBS"] = [] +if arch == "Darwin": + envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] +elif arch == "aarch64": + envCython["LINKFLAGS"] = ["-shared"] + envCython["LIBS"] = [os.path.basename(python_path)] +else: + envCython["LINKFLAGS"] = ["-pthread", "-shared"] + +Export('env', 'envCython', 'common') + +SConscript(['#rednose/SConscript']) +SConscript(['#examples/SConscript']) diff --git a/rednose_repo/examples/SConscript b/rednose_repo/examples/SConscript new file mode 100644 index 0000000000..3d178ade1c --- /dev/null +++ b/rednose_repo/examples/SConscript @@ -0,0 +1,19 @@ +Import('env') + +gen_dir = Dir('generated/').abspath + +env.RednoseCompileFilter( + target="live", + filter_gen_script="live_kf.py", + output_dir=gen_dir, +) +env.RednoseCompileFilter( + target="kinematic", + filter_gen_script="kinematic_kf.py", + output_dir=gen_dir, +) +env.RednoseCompileFilter( + target="compare", + filter_gen_script="test_compare.py", + output_dir=gen_dir, +) diff --git a/rednose_repo/examples/__init__.py b/rednose_repo/examples/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/rednose_repo/examples/kinematic_kf.png b/rednose_repo/examples/kinematic_kf.png new file mode 100644 index 0000000000..acb0e442c0 Binary files /dev/null and b/rednose_repo/examples/kinematic_kf.png differ diff --git a/rednose_repo/examples/kinematic_kf.py b/rednose_repo/examples/kinematic_kf.py new file mode 100755 index 0000000000..29049a7b98 --- /dev/null +++ b/rednose_repo/examples/kinematic_kf.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +import sys + +import numpy as np +import sympy as sp + +from rednose.helpers.kalmanfilter import KalmanFilter + +if __name__ == '__main__': # generating sympy code + from rednose.helpers.ekf_sym import gen_code +else: + from rednose.helpers.ekf_sym_pyx import EKF_sym_pyx # pylint: disable=no-name-in-module + + +class ObservationKind(): + UNKNOWN = 0 + NO_OBSERVATION = 1 + POSITION = 1 + + names = [ + 'Unknown', + 'No observation', + 'Position' + ] + + @classmethod + def to_string(cls, kind): + return cls.names[kind] + + +class States(): + POSITION = slice(0, 1) + VELOCITY = slice(1, 2) + + +class KinematicKalman(KalmanFilter): + name = 'kinematic' + + initial_x = np.array([0.5, 0.0]) + + # state covariance + initial_P_diag = np.array([1.0**2, 1.0**2]) + + # process noise + Q = np.diag([0.1**2, 2.0**2]) + + obs_noise = {ObservationKind.POSITION: np.atleast_2d(0.1**2)} + + @staticmethod + def generate_code(generated_dir): + name = KinematicKalman.name + dim_state = KinematicKalman.initial_x.shape[0] + + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + + position = state[States.POSITION, :][0,:] + velocity = state[States.VELOCITY, :][0,:] + + dt = sp.Symbol('dt') + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.POSITION.start, 0] = velocity + f_sym = state + dt * state_dot + + obs_eqs = [ + [sp.Matrix([position]), ObservationKind.POSITION, None], + ] + + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state) + + def __init__(self, generated_dir): + dim_state = self.initial_x.shape[0] + dim_state_err = self.initial_P_diag.shape[0] + + # init filter + self.filter = EKF_sym_pyx(generated_dir, self.name, self.Q, self.initial_x, np.diag(self.initial_P_diag), dim_state, dim_state_err) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + KinematicKalman.generate_code(generated_dir) diff --git a/rednose_repo/examples/live_kf.py b/rednose_repo/examples/live_kf.py new file mode 100755 index 0000000000..6e3c21d93e --- /dev/null +++ b/rednose_repo/examples/live_kf.py @@ -0,0 +1,342 @@ +#!/usr/bin/env python3 +import sys +import numpy as np + +from rednose.helpers import KalmanError + +if __name__ == '__main__': # Generating sympy + import sympy as sp + from rednose.helpers.sympy_helpers import euler_rotate, quat_matrix_r, quat_rotate + from rednose.helpers.ekf_sym import gen_code +else: + from rednose.helpers.ekf_sym_pyx import EKF_sym_pyx # pylint: disable=no-name-in-module + +EARTH_GM = 3.986005e14 # m^3/s^2 (gravitational constant * mass of earth) + + +class ObservationKind(): + UNKNOWN = 0 + NO_OBSERVATION = 1 + GPS_NED = 2 + ODOMETRIC_SPEED = 3 + PHONE_GYRO = 4 + GPS_VEL = 5 + PSEUDORANGE_GPS = 6 + PSEUDORANGE_RATE_GPS = 7 + SPEED = 8 + NO_ROT = 9 + PHONE_ACCEL = 10 + ORB_POINT = 11 + ECEF_POS = 12 + CAMERA_ODO_TRANSLATION = 13 + CAMERA_ODO_ROTATION = 14 + ORB_FEATURES = 15 + MSCKF_TEST = 16 + FEATURE_TRACK_TEST = 17 + LANE_PT = 18 + IMU_FRAME = 19 + PSEUDORANGE_GLONASS = 20 + PSEUDORANGE_RATE_GLONASS = 21 + PSEUDORANGE = 22 + PSEUDORANGE_RATE = 23 + + names = [ + 'Unknown', + 'No observation', + 'GPS NED', + 'Odometric speed', + 'Phone gyro', + 'GPS velocity', + 'GPS pseudorange', + 'GPS pseudorange rate', + 'Speed', + 'No rotation', + 'Phone acceleration', + 'ORB point', + 'ECEF pos', + 'camera odometric translation', + 'camera odometric rotation', + 'ORB features', + 'MSCKF test', + 'Feature track test', + 'Lane ecef point', + 'imu frame eulers', + 'GLONASS pseudorange', + 'GLONASS pseudorange rate', + ] + + @classmethod + def to_string(cls, kind): + return cls.names[kind] + + +class States(): + ECEF_POS = slice(0, 3) # x, y and z in ECEF in meters + ECEF_ORIENTATION = slice(3, 7) # quat for pose of phone in ecef + ECEF_VELOCITY = slice(7, 10) # ecef velocity in m/s + ANGULAR_VELOCITY = slice(10, 13) # roll, pitch and yaw rates in device frame in radians/s + GYRO_BIAS = slice(13, 16) # roll, pitch and yaw biases + ODO_SCALE = slice(16, 17) # odometer scale + ACCELERATION = slice(17, 20) # Acceleration in device frame in m/s**2 + IMU_OFFSET = slice(20, 23) # imu offset angles in radians + + # Error-state has different slices because it is an ESKF + ECEF_POS_ERR = slice(0, 3) + ECEF_ORIENTATION_ERR = slice(3, 6) # euler angles for orientation error + ECEF_VELOCITY_ERR = slice(6, 9) + ANGULAR_VELOCITY_ERR = slice(9, 12) + GYRO_BIAS_ERR = slice(12, 15) + ODO_SCALE_ERR = slice(15, 16) + ACCELERATION_ERR = slice(16, 19) + IMU_OFFSET_ERR = slice(19, 22) + + +class LiveKalman(): + name = 'live' + + initial_x = np.array([-2.7e6, 4.2e6, 3.8e6, + 1, 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 1, + 0, 0, 0, + 0, 0, 0]) + + # state covariance + initial_P_diag = np.array([10000**2, 10000**2, 10000**2, + 10**2, 10**2, 10**2, + 10**2, 10**2, 10**2, + 1**2, 1**2, 1**2, + 0.05**2, 0.05**2, 0.05**2, + 0.02**2, + 1**2, 1**2, 1**2, + (0.01)**2, (0.01)**2, (0.01)**2]) + + # process noise + Q = np.diag([0.03**2, 0.03**2, 0.03**2, + 0.0**2, 0.0**2, 0.0**2, + 0.0**2, 0.0**2, 0.0**2, + 0.1**2, 0.1**2, 0.1**2, + (0.005 / 100)**2, (0.005 / 100)**2, (0.005 / 100)**2, + (0.02 / 100)**2, + 3**2, 3**2, 3**2, + (0.05 / 60)**2, (0.05 / 60)**2, (0.05 / 60)**2]) + + @staticmethod + def generate_code(generated_dir): + name = LiveKalman.name + dim_state = LiveKalman.initial_x.shape[0] + dim_state_err = LiveKalman.initial_P_diag.shape[0] + + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + x, y, z = state[States.ECEF_POS, :] + q = state[States.ECEF_ORIENTATION, :] + v = state[States.ECEF_VELOCITY, :] + vx, vy, vz = v + omega = state[States.ANGULAR_VELOCITY, :] + vroll, vpitch, vyaw = omega + roll_bias, pitch_bias, yaw_bias = state[States.GYRO_BIAS, :] + odo_scale = state[States.ODO_SCALE, :][0,:] + acceleration = state[States.ACCELERATION, :] + imu_angles = state[States.IMU_OFFSET, :] + + dt = sp.Symbol('dt') + + # calibration and attitude rotation matrices + quat_rot = quat_rotate(*q) + + # Got the quat predict equations from here + # A New Quaternion-Based Kalman Filter for + # Real-Time Attitude Estimation Using the Two-Step + # Geometrically-Intuitive Correction Algorithm + A = 0.5 * sp.Matrix([[0, -vroll, -vpitch, -vyaw], + [vroll, 0, vyaw, -vpitch], + [vpitch, -vyaw, 0, vroll], + [vyaw, vpitch, -vroll, 0]]) + q_dot = A * q + + # Time derivative of the state as a function of state + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.ECEF_POS, :] = v + state_dot[States.ECEF_ORIENTATION, :] = q_dot + state_dot[States.ECEF_VELOCITY, 0] = quat_rot * acceleration + + # Basic descretization, 1st order intergrator + # Can be pretty bad if dt is big + f_sym = state + dt * state_dot + + state_err_sym = sp.MatrixSymbol('state_err', dim_state_err, 1) + state_err = sp.Matrix(state_err_sym) + quat_err = state_err[States.ECEF_ORIENTATION_ERR, :] + v_err = state_err[States.ECEF_VELOCITY_ERR, :] + omega_err = state_err[States.ANGULAR_VELOCITY_ERR, :] + acceleration_err = state_err[States.ACCELERATION_ERR, :] + + # Time derivative of the state error as a function of state error and state + quat_err_matrix = euler_rotate(quat_err[0], quat_err[1], quat_err[2]) + q_err_dot = quat_err_matrix * quat_rot * (omega + omega_err) + state_err_dot = sp.Matrix(np.zeros((dim_state_err, 1))) + state_err_dot[States.ECEF_POS_ERR, :] = v_err + state_err_dot[States.ECEF_ORIENTATION_ERR, :] = q_err_dot + state_err_dot[States.ECEF_VELOCITY_ERR, :] = quat_err_matrix * quat_rot * (acceleration + acceleration_err) + f_err_sym = state_err + dt * state_err_dot + + # Observation matrix modifier + H_mod_sym = sp.Matrix(np.zeros((dim_state, dim_state_err))) + H_mod_sym[States.ECEF_POS, States.ECEF_POS_ERR] = np.eye(States.ECEF_POS.stop - States.ECEF_POS.start) + H_mod_sym[States.ECEF_ORIENTATION, States.ECEF_ORIENTATION_ERR] = 0.5 * quat_matrix_r(state[3:7])[:, 1:] + H_mod_sym[States.ECEF_ORIENTATION.stop:, States.ECEF_ORIENTATION_ERR.stop:] = np.eye(dim_state - States.ECEF_ORIENTATION.stop) + + # these error functions are defined so that say there + # is a nominal x and true x: + # true x = err_function(nominal x, delta x) + # delta x = inv_err_function(nominal x, true x) + nom_x = sp.MatrixSymbol('nom_x', dim_state, 1) + true_x = sp.MatrixSymbol('true_x', dim_state, 1) + delta_x = sp.MatrixSymbol('delta_x', dim_state_err, 1) + + err_function_sym = sp.Matrix(np.zeros((dim_state, 1))) + delta_quat = sp.Matrix(np.ones(4)) + delta_quat[1:, :] = sp.Matrix(0.5 * delta_x[States.ECEF_ORIENTATION_ERR, :]) + err_function_sym[States.ECEF_POS, :] = sp.Matrix(nom_x[States.ECEF_POS, :] + delta_x[States.ECEF_POS_ERR, :]) + err_function_sym[States.ECEF_ORIENTATION, 0] = quat_matrix_r(nom_x[States.ECEF_ORIENTATION, 0]) * delta_quat + err_function_sym[States.ECEF_ORIENTATION.stop:, :] = sp.Matrix(nom_x[States.ECEF_ORIENTATION.stop:, :] + delta_x[States.ECEF_ORIENTATION_ERR.stop:, :]) + + inv_err_function_sym = sp.Matrix(np.zeros((dim_state_err, 1))) + inv_err_function_sym[States.ECEF_POS_ERR, 0] = sp.Matrix(-nom_x[States.ECEF_POS, 0] + true_x[States.ECEF_POS, 0]) + delta_quat = quat_matrix_r(nom_x[States.ECEF_ORIENTATION, 0]).T * true_x[States.ECEF_ORIENTATION, 0] + inv_err_function_sym[States.ECEF_ORIENTATION_ERR, 0] = sp.Matrix(2 * delta_quat[1:]) + inv_err_function_sym[States.ECEF_ORIENTATION_ERR.stop:, 0] = sp.Matrix(-nom_x[States.ECEF_ORIENTATION.stop:, 0] + true_x[States.ECEF_ORIENTATION.stop:, 0]) + + eskf_params = [[err_function_sym, nom_x, delta_x], + [inv_err_function_sym, nom_x, true_x], + H_mod_sym, f_err_sym, state_err_sym] + # + # Observation functions + # + imu_rot = euler_rotate(*imu_angles) + h_gyro_sym = imu_rot * sp.Matrix([vroll + roll_bias, + vpitch + pitch_bias, + vyaw + yaw_bias]) + + pos = sp.Matrix([x, y, z]) + gravity = quat_rot.T * ((EARTH_GM / ((x**2 + y**2 + z**2)**(3.0 / 2.0))) * pos) + h_acc_sym = imu_rot * (gravity + acceleration) + h_phone_rot_sym = sp.Matrix([vroll, vpitch, vyaw]) + + speed = sp.sqrt(vx**2 + vy**2 + vz**2) + h_speed_sym = sp.Matrix([speed * odo_scale]) + + h_pos_sym = sp.Matrix([x, y, z]) + h_imu_frame_sym = sp.Matrix(imu_angles) + + h_relative_motion = sp.Matrix(quat_rot.T * v) + + obs_eqs = [[h_speed_sym, ObservationKind.ODOMETRIC_SPEED, None], + [h_gyro_sym, ObservationKind.PHONE_GYRO, None], + [h_phone_rot_sym, ObservationKind.NO_ROT, None], + [h_acc_sym, ObservationKind.PHONE_ACCEL, None], + [h_pos_sym, ObservationKind.ECEF_POS, None], + [h_relative_motion, ObservationKind.CAMERA_ODO_TRANSLATION, None], + [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None], + [h_imu_frame_sym, ObservationKind.IMU_FRAME, None]] + + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state_err, eskf_params) + + def __init__(self, generated_dir): + self.dim_state = self.initial_x.shape[0] + self.dim_state_err = self.initial_P_diag.shape[0] + + self.obs_noise = {ObservationKind.ODOMETRIC_SPEED: np.atleast_2d(0.2**2), + ObservationKind.PHONE_GYRO: np.diag([0.025**2, 0.025**2, 0.025**2]), + ObservationKind.PHONE_ACCEL: np.diag([.5**2, .5**2, .5**2]), + ObservationKind.CAMERA_ODO_ROTATION: np.diag([0.05**2, 0.05**2, 0.05**2]), + ObservationKind.IMU_FRAME: np.diag([0.05**2, 0.05**2, 0.05**2]), + ObservationKind.NO_ROT: np.diag([0.00025**2, 0.00025**2, 0.00025**2]), + ObservationKind.ECEF_POS: np.diag([5**2, 5**2, 5**2])} + + # init filter + self.filter = EKF_sym_pyx(generated_dir, self.name, self.Q, self.initial_x, np.diag(self.initial_P_diag), self.dim_state, self.dim_state_err) + + @property + def x(self): + return self.filter.state() + + @property + def t(self): + return self.filter.filter_time + + @property + def P(self): + return self.filter.covs() + + def rts_smooth(self, estimates): + return self.filter.rts_smooth(estimates, norm_quats=True) + + def init_state(self, state, covs_diag=None, covs=None, filter_time=None): + if covs_diag is not None: + P = np.diag(covs_diag) + elif covs is not None: + P = covs + else: + P = self.filter.covs() + self.filter.init_state(state, P, filter_time) + + def predict_and_observe(self, t, kind, data): + if len(data) > 0: + data = np.atleast_2d(data) + if kind == ObservationKind.CAMERA_ODO_TRANSLATION: + r = self.predict_and_update_odo_trans(data, t, kind) + elif kind == ObservationKind.CAMERA_ODO_ROTATION: + r = self.predict_and_update_odo_rot(data, t, kind) + elif kind == ObservationKind.ODOMETRIC_SPEED: + r = self.predict_and_update_odo_speed(data, t, kind) + else: + r = self.filter.predict_and_update_batch(t, kind, data, self.get_R(kind, len(data))) + + # Normalize quats + quat_norm = np.linalg.norm(self.filter.x[3:7, 0]) + + # Should not continue if the quats behave this weirdly + if not (0.1 < quat_norm < 10): + raise KalmanError("Kalman filter quaternions unstable") + + self.filter.x[States.ECEF_ORIENTATION, 0] = self.filter.x[States.ECEF_ORIENTATION, 0] / quat_norm + + return r + + def get_R(self, kind, n): + obs_noise = self.obs_noise[kind] + dim = obs_noise.shape[0] + R = np.zeros((n, dim, dim)) + for i in range(n): + R[i, :, :] = obs_noise + return R + + def predict_and_update_odo_speed(self, speed, t, kind): + z = np.array(speed) + R = np.zeros((len(speed), 1, 1)) + for i, _ in enumerate(z): + R[i, :, :] = np.diag([0.2**2]) + return self.filter.predict_and_update_batch(t, kind, z, R) + + def predict_and_update_odo_trans(self, trans, t, kind): + z = trans[:, :3] + R = np.zeros((len(trans), 3, 3)) + for i, _ in enumerate(z): + R[i, :, :] = np.diag(trans[i, 3:]**2) + return self.filter.predict_and_update_batch(t, kind, z, R) + + def predict_and_update_odo_rot(self, rot, t, kind): + z = rot[:, :3] + R = np.zeros((len(rot), 3, 3)) + for i, _ in enumerate(z): + R[i, :, :] = np.diag(rot[i, 3:]**2) + return self.filter.predict_and_update_batch(t, kind, z, R) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + LiveKalman.generate_code(generated_dir) diff --git a/rednose_repo/examples/test_compare.py b/rednose_repo/examples/test_compare.py new file mode 100755 index 0000000000..291f29e826 --- /dev/null +++ b/rednose_repo/examples/test_compare.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import pytest +import os +import sys +import sympy as sp +import numpy as np + +if __name__ == '__main__': # generating sympy code + from rednose.helpers.ekf_sym import gen_code +else: + from rednose.helpers.ekf_sym_pyx import EKF_sym_pyx # pylint: disable=no-name-in-module + from rednose.helpers.ekf_sym import EKF_sym as EKF_sym2 + + +GENERATED_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'generated')) + + +class ObservationKind: + UNKNOWN = 0 + NO_OBSERVATION = 1 + POSITION = 1 + + names = [ + 'Unknown', + 'No observation', + 'Position' + ] + + @classmethod + def to_string(cls, kind): + return cls.names[kind] + + +class States: + POSITION = slice(0, 1) + VELOCITY = slice(1, 2) + + +class CompareFilter: + name = "compare" + + initial_x = np.array([0.5, 0.0]) + initial_P_diag = np.array([1.0**2, 1.0**2]) + Q = np.diag([0.1**2, 2.0**2]) + obs_noise = {ObservationKind.POSITION: np.atleast_2d(0.1**2)} + + @staticmethod + def generate_code(generated_dir): + name = CompareFilter.name + dim_state = CompareFilter.initial_x.shape[0] + + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + + position = state[States.POSITION, :][0,:] + velocity = state[States.VELOCITY, :][0,:] + + dt = sp.Symbol('dt') + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.POSITION.start, 0] = velocity + f_sym = state + dt * state_dot + + obs_eqs = [ + [sp.Matrix([position]), ObservationKind.POSITION, None], + ] + + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state) + + def __init__(self, generated_dir): + dim_state = self.initial_x.shape[0] + dim_state_err = self.initial_P_diag.shape[0] + + # init filter + self.filter_py = EKF_sym_pyx(generated_dir, self.name, self.Q, self.initial_x, np.diag(self.initial_P_diag), dim_state, dim_state_err) + self.filter_pyx = EKF_sym2(generated_dir, self.name, self.Q, self.initial_x, np.diag(self.initial_P_diag), dim_state, dim_state_err) + + def get_R(self, kind, n): + obs_noise = self.obs_noise[kind] + dim = obs_noise.shape[0] + R = np.zeros((n, dim, dim)) + for i in range(n): + R[i, :, :] = obs_noise + return R + + +class TestCompare: + def test_compare(self): + np.random.seed(0) + + kf = CompareFilter(GENERATED_DIR) + + # Simple simulation + dt = 0.01 + ts = np.arange(0, 5, step=dt) + xs = np.empty(ts.shape) + + # Simulate + x = 0.0 + for i, v in enumerate(np.sin(ts * 5)): + xs[i] = x + x += v * dt + + # insert late observation + switch = (20, 40) + ts[switch[0]], ts[switch[1]] = ts[switch[1]], ts[switch[0]] + xs[switch[0]], xs[switch[1]] = xs[switch[1]], xs[switch[0]] + + for t, x in zip(ts, xs): + # get measurement + meas = np.random.normal(x, 0.1) + z = np.array([[meas]]) + R = kf.get_R(ObservationKind.POSITION, 1) + + # Update kf + kf.filter_py.predict_and_update_batch(t, ObservationKind.POSITION, z, R) + kf.filter_pyx.predict_and_update_batch(t, ObservationKind.POSITION, z, R) + + assert kf.filter_py.get_filter_time() == pytest.approx(kf.filter_pyx.get_filter_time()) + assert np.allclose(kf.filter_py.state(), kf.filter_pyx.state()) + assert np.allclose(kf.filter_py.covs(), kf.filter_pyx.covs()) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + CompareFilter.generate_code(generated_dir) diff --git a/rednose_repo/examples/test_kinematic_kf.py b/rednose_repo/examples/test_kinematic_kf.py new file mode 100644 index 0000000000..05d4d3efd0 --- /dev/null +++ b/rednose_repo/examples/test_kinematic_kf.py @@ -0,0 +1,82 @@ +import pytest +import os +import numpy as np + +from .kinematic_kf import KinematicKalman, ObservationKind, States + +GENERATED_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'generated')) + +class TestKinematic: + def test_kinematic_kf(self): + np.random.seed(0) + + kf = KinematicKalman(GENERATED_DIR) + + # Simple simulation + dt = 0.01 + ts = np.arange(0, 5, step=dt) + vs = np.sin(ts * 5) + + x = 0.0 + xs = [] + + xs_meas = [] + + xs_kf = [] + vs_kf = [] + + xs_kf_std = [] + vs_kf_std = [] + + for t, v in zip(ts, vs): + xs.append(x) + + # Update kf + meas = np.random.normal(x, 0.1) + xs_meas.append(meas) + kf.predict_and_observe(t, ObservationKind.POSITION, [meas]) + + # Retrieve kf values + state = kf.x + xs_kf.append(float(state[States.POSITION].item())) + vs_kf.append(float(state[States.VELOCITY].item())) + std = np.sqrt(kf.P) + xs_kf_std.append(float(std[States.POSITION, States.POSITION].item())) + vs_kf_std.append(float(std[States.VELOCITY, States.VELOCITY].item())) + + # Update simulation + x += v * dt + + xs, xs_meas, xs_kf, vs_kf, xs_kf_std, vs_kf_std = (np.asarray(a) for a in (xs, xs_meas, xs_kf, vs_kf, xs_kf_std, vs_kf_std)) + + assert xs_kf[-1] == pytest.approx(-0.010866289677966417) + assert xs_kf_std[-1] == pytest.approx(0.04477103863330089) + assert vs_kf[-1] == pytest.approx(-0.8553720537261753) + assert vs_kf_std[-1] == pytest.approx(0.6695762270974388) + + if "PLOT" in os.environ: + import matplotlib.pyplot as plt # pylint: disable=import-error + plt.figure() + plt.subplot(2, 1, 1) + plt.plot(ts, xs, 'k', label='Simulation') + plt.plot(ts, xs_meas, 'k.', label='Measurements') + plt.plot(ts, xs_kf, label='KF') + ax = plt.gca() + ax.fill_between(ts, xs_kf - xs_kf_std, xs_kf + xs_kf_std, alpha=.2, color='C0') + + plt.xlabel("Time [s]") + plt.ylabel("Position [m]") + plt.legend() + + plt.subplot(2, 1, 2) + plt.plot(ts, vs, 'k', label='Simulation') + plt.plot(ts, vs_kf, label='KF') + + ax = plt.gca() + ax.fill_between(ts, vs_kf - vs_kf_std, vs_kf + vs_kf_std, alpha=.2, color='C0') + + plt.xlabel("Time [s]") + plt.ylabel("Velocity [m/s]") + plt.legend() + + plt.show() diff --git a/rednose_repo/pyproject.toml b/rednose_repo/pyproject.toml new file mode 100644 index 0000000000..fa6ae11d1c --- /dev/null +++ b/rednose_repo/pyproject.toml @@ -0,0 +1,16 @@ +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +line-length = 160 +target-version="py311" + +[tool.ruff.lint] +select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF100", "A"] +ignore = ["W292", "E741", "E402", "C408", "ISC003"] +flake8-implicit-str-concat.allow-multiline=false + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" +"unittest".msg = "Use pytest" + +[tool.pytest.ini_options] +addopts = "--durations=10 -n auto" diff --git a/rednose_repo/rednose/.gitignore b/rednose_repo/rednose/.gitignore new file mode 100644 index 0000000000..d771ae6010 --- /dev/null +++ b/rednose_repo/rednose/.gitignore @@ -0,0 +1,5 @@ +# Cython intermediates +*_pyx.cpp +*_pyx.h +*_pyx_api.h +*.os diff --git a/rednose_repo/rednose/SConscript b/rednose_repo/rednose/SConscript new file mode 100644 index 0000000000..52e36e06f4 --- /dev/null +++ b/rednose_repo/rednose/SConscript @@ -0,0 +1,17 @@ +Import('env', 'envCython', 'common') + +cc_sources = [ + "helpers/ekf_load.cc", + "helpers/ekf_sym.cc", +] +libs = ["dl"] +if common != "": + # for SWAGLOG support + libs += [common, 'zmq'] + +ekf_objects = env.SharedObject(cc_sources) +rednose = env.Library("helpers/ekf_sym", ekf_objects, LIBS=libs) +rednose_python = envCython.Program("helpers/ekf_sym_pyx.so", ["helpers/ekf_sym_pyx.pyx", ekf_objects], + LIBS=libs + envCython["LIBS"]) + +Export('rednose', 'rednose_python') diff --git a/rednose_repo/rednose/__init__.py b/rednose_repo/rednose/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/rednose_repo/rednose/helpers/__init__.py b/rednose_repo/rednose/helpers/__init__.py new file mode 100644 index 0000000000..3acc14afff --- /dev/null +++ b/rednose_repo/rednose/helpers/__init__.py @@ -0,0 +1,35 @@ +import os +import platform +from cffi import FFI + +TEMPLATE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'templates')) + + +def write_code(folder, name, code, header): + if not os.path.exists(folder): + os.mkdir(folder) + + with open(os.path.join(folder, f"{name}.cpp"), 'w', encoding='utf-8') as f: + f.write(code) + with open(os.path.join(folder, f"{name}.h"), 'w', encoding='utf-8') as f: + f.write(header) + + +def load_code(folder, name): + shared_ext = "dylib" if platform.system() == "Darwin" else "so" + shared_fn = os.path.join(folder, f"lib{name}.{shared_ext}") + header_fn = os.path.join(folder, f"{name}.h") + + with open(header_fn, encoding='utf-8') as f: + header = f.read() + + # is the only thing that can be parsed by cffi + header = "\n".join([line for line in header.split("\n") if line.startswith("void ")]) + + ffi = FFI() + ffi.cdef(header) + return (ffi, ffi.dlopen(shared_fn)) + + +class KalmanError(Exception): + pass diff --git a/rednose_repo/rednose/helpers/chi2_lookup.py b/rednose_repo/rednose/helpers/chi2_lookup.py new file mode 100644 index 0000000000..e22cc97299 --- /dev/null +++ b/rednose_repo/rednose/helpers/chi2_lookup.py @@ -0,0 +1,22 @@ +import os + +import numpy as np + + +def gen_chi2_ppf_lookup(max_dim=200): + from scipy.stats import chi2 + table = np.zeros((max_dim, 98)) + for dim in range(1, max_dim): + table[dim] = chi2.ppf(np.arange(.01, .99, .01), dim) + + np.save('chi2_lookup_table', table) + + +def chi2_ppf(p, dim): + table = np.load(os.path.dirname(os.path.realpath(__file__)) + '/chi2_lookup_table.npy') + result = np.interp(p, np.arange(.01, .99, .01), table[dim]) + return result + + +if __name__ == "__main__": + gen_chi2_ppf_lookup() diff --git a/rednose_repo/rednose/helpers/chi2_lookup_table.npy b/rednose_repo/rednose/helpers/chi2_lookup_table.npy new file mode 100644 index 0000000000..6f1bd959c1 Binary files /dev/null and b/rednose_repo/rednose/helpers/chi2_lookup_table.npy differ diff --git a/rednose_repo/rednose/helpers/ekf.h b/rednose_repo/rednose/helpers/ekf.h new file mode 100644 index 0000000000..2afe6dd2b6 --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef void (*extra_routine_t)(double *, double *); + +struct EKF { + std::string name; + std::vector kinds; + std::vector feature_kinds; + + void (*f_fun)(double *, double, double *); + void (*F_fun)(double *, double, double *); + void (*err_fun)(double *, double *, double *); + void (*inv_err_fun)(double *, double *, double *); + void (*H_mod_fun)(double *, double *); + void (*predict)(double *, double *, double *, double); + std::unordered_map hs = {}; + std::unordered_map Hs = {}; + std::unordered_map updates = {}; + std::unordered_map Hes = {}; + std::unordered_map sets = {}; + std::unordered_map extra_routines = {}; +}; + +#define ekf_lib_init(ekf) \ +extern "C" void* ekf_get() { \ + return (void*) &ekf; \ +} \ +extern void __attribute__((weak)) ekf_register(const EKF* ptr); \ +static void __attribute__((constructor)) do_ekf_init_ ## ekf(void) { \ + if (ekf_register) ekf_register(&ekf); \ +} diff --git a/rednose_repo/rednose/helpers/ekf_load.cc b/rednose_repo/rednose/helpers/ekf_load.cc new file mode 100644 index 0000000000..882b0b4a61 --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf_load.cc @@ -0,0 +1,39 @@ +#include "ekf_load.h" +#include + +std::vector& ekf_get_all() { + static std::vector vec; + return vec; +} + +void ekf_register(const EKF* ekf) { + ekf_get_all().push_back(ekf); +} + +const EKF* ekf_lookup(const std::string& ekf_name) { + for (const auto& ekfi : ekf_get_all()) { + if (ekf_name == ekfi->name) { + return ekfi; + } + } + return NULL; +} + +void ekf_load_and_register(const std::string& ekf_directory, const std::string& ekf_name) { + if (ekf_lookup(ekf_name)) { + return; + } + +#ifdef __APPLE__ + std::string dylib_ext = ".dylib"; +#else + std::string dylib_ext = ".so"; +#endif + std::string ekf_path = ekf_directory + "/lib" + ekf_name + dylib_ext; + void* handle = dlopen(ekf_path.c_str(), RTLD_NOW); + assert(handle); + void* (*ekf_get)() = (void*(*)())dlsym(handle, "ekf_get"); + assert(ekf_get != NULL); + const EKF* ekf = (const EKF*)ekf_get(); + ekf_register(ekf); +} diff --git a/rednose_repo/rednose/helpers/ekf_load.h b/rednose_repo/rednose/helpers/ekf_load.h new file mode 100644 index 0000000000..89180b8028 --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf_load.h @@ -0,0 +1,9 @@ +#include +#include + +#include "ekf.h" + +std::vector& ekf_get_all(); +const EKF* ekf_lookup(const std::string& ekf_name); +void ekf_register(const EKF* ekf); +void ekf_load_and_register(const std::string& ekf_directory, const std::string& ekf_name); diff --git a/rednose_repo/rednose/helpers/ekf_sym.cc b/rednose_repo/rednose/helpers/ekf_sym.cc new file mode 100644 index 0000000000..38d419d07f --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf_sym.cc @@ -0,0 +1,223 @@ +#include "ekf_sym.h" +#include "logger/logger.h" + +using namespace EKFS; +using namespace Eigen; + +EKFSym::EKFSym(std::string name, Map Q, Map x_initial, Map P_initial, int dim_main, + int dim_main_err, int N, int dim_augment, int dim_augment_err, std::vector maha_test_kinds, + std::vector quaternion_idxs, std::vector global_vars, double max_rewind_age) +{ + // TODO: add logger + this->ekf = ekf_lookup(name); + assert(this->ekf); + + this->msckf = N > 0; + this->N = N; + this->dim_augment = dim_augment; + this->dim_augment_err = dim_augment_err; + this->dim_main = dim_main; + this->dim_main_err = dim_main_err; + + this->dim_x = x_initial.rows(); + this->dim_err = P_initial.rows(); + + assert(dim_main + dim_augment * N == dim_x); + assert(dim_main_err + dim_augment_err * N == this->dim_err); + assert(Q.rows() == P_initial.rows() && Q.cols() == P_initial.cols()); + + // kinds that should get mahalanobis distance + // tested for outlier rejection + this->maha_test_kinds = maha_test_kinds; + + // quaternions need normalization + this->quaternion_idxs = quaternion_idxs; + + this->global_vars = global_vars; + + // Process noise + this->Q = Q; + + this->max_rewind_age = max_rewind_age; + this->init_state(x_initial, P_initial, NAN); +} + +void EKFSym::init_state(Map state, Map covs, double init_filter_time) { + this->x = state; + this->P = covs; + this->filter_time = init_filter_time; + this->augment_times = VectorXd::Zero(this->N); + this->reset_rewind(); +} + +VectorXd EKFSym::state() { + return this->x; +} + +MatrixXdr EKFSym::covs() { + return this->P; +} + +void EKFSym::set_filter_time(double t) { + this->filter_time = t; +} + +double EKFSym::get_filter_time() { + return this->filter_time; +} + +void EKFSym::normalize_quaternions() { + for(std::size_t i = 0; i < this->quaternion_idxs.size(); ++i) { + this->normalize_slice(this->quaternion_idxs[i], this->quaternion_idxs[i] + 4); + } +} + +void EKFSym::normalize_slice(int slice_start, int slice_end_ex) { + this->x.block(slice_start, 0, slice_end_ex - slice_start, this->x.cols()).normalize(); +} + +void EKFSym::set_global(std::string global_var, double val) { + this->ekf->sets.at(global_var)(val); +} + +std::optional EKFSym::predict_and_update_batch(double t, int kind, std::vector> z_map, + std::vector> R_map, std::vector> extra_args, bool augment) +{ + // TODO handle rewinding at this level + + std::deque rewound; + if (!std::isnan(this->filter_time) && t < this->filter_time) { + if (this->rewind_t.empty() || t < this->rewind_t.front() || t < this->rewind_t.back() - this->max_rewind_age) { + LOGD("observation too old at %f with filter at %f, ignoring!", t, this->filter_time); + return std::nullopt; + } + rewound = this->rewind(t); + } + + Observation obs; + obs.t = t; + obs.kind = kind; + obs.extra_args = extra_args; + for (Map zi : z_map) { + obs.z.push_back(zi); + } + for (Map Ri : R_map) { + obs.R.push_back(Ri); + } + + std::optional res = std::make_optional(this->predict_and_update_batch(obs, augment)); + + // optional fast forward + while (!rewound.empty()) { + this->predict_and_update_batch(rewound.front(), false); + rewound.pop_front(); + } + + return res; +} + +void EKFSym::reset_rewind() { + this->rewind_obscache.clear(); + this->rewind_t.clear(); + this->rewind_states.clear(); +} + +std::deque EKFSym::rewind(double t) { + std::deque rewound; + + // rewind observations until t is after previous observation + while (this->rewind_t.back() > t) { + rewound.push_front(this->rewind_obscache.back()); + this->rewind_t.pop_back(); + this->rewind_states.pop_back(); + this->rewind_obscache.pop_back(); + } + + // set the state to the time right before that + this->filter_time = this->rewind_t.back(); + this->x = this->rewind_states.back().first; + this->P = this->rewind_states.back().second; + + return rewound; +} + +void EKFSym::checkpoint(Observation& obs) { + // push to rewinder + this->rewind_t.push_back(this->filter_time); + this->rewind_states.push_back(std::make_pair(this->x, this->P)); + this->rewind_obscache.push_back(obs); + + // only keep a certain number around + if (this->rewind_t.size() > REWIND_TO_KEEP) { + this->rewind_t.pop_front(); + this->rewind_states.pop_front(); + this->rewind_obscache.pop_front(); + } +} + +Estimate EKFSym::predict_and_update_batch(Observation& obs, bool augment) { + assert(obs.z.size() == obs.R.size()); + assert(obs.z.size() == obs.extra_args.size()); + + this->predict(obs.t); + + Estimate res; + res.t = obs.t; + res.kind = obs.kind; + res.z = obs.z; + res.extra_args = obs.extra_args; + res.xk1 = this->x; + res.Pk1 = this->P; + + // update batch + std::vector y; + for (int i = 0; i < obs.z.size(); i++) { + assert(obs.z[i].rows() == obs.R[i].rows()); + assert(obs.z[i].rows() == obs.R[i].cols()); + + // update state + y.push_back(this->update(obs.kind, obs.z[i], obs.R[i], obs.extra_args[i])); + } + + res.xk = this->x; + res.Pk = this->P; + res.y = y; + + assert(!augment); // TODO + // if (augment) { + // this->augment(); + // } + + this->checkpoint(obs); + + return res; +} + +void EKFSym::predict(double t) { + // initialize time + if (std::isnan(this->filter_time)) { + this->filter_time = t; + } + + // predict + double dt = t - this->filter_time; + assert(dt >= 0.0); + + this->ekf->predict(this->x.data(), this->P.data(), this->Q.data(), dt); + this->normalize_quaternions(); + this->filter_time = t; +} + +VectorXd EKFSym::update(int kind, VectorXd z, MatrixXdr R, std::vector extra_args) { + this->ekf->updates.at(kind)(this->x.data(), this->P.data(), z.data(), R.data(), extra_args.data()); + this->normalize_quaternions(); + + if (this->msckf && std::find(this->feature_track_kinds.begin(), this->feature_track_kinds.end(), kind) != this->feature_track_kinds.end()) { + return z.head(z.rows() - extra_args.size()); + } + return z; +} + +extra_routine_t EKFSym::get_extra_routine(const std::string& routine) { + return this->ekf->extra_routines.at(routine); +} diff --git a/rednose_repo/rednose/helpers/ekf_sym.h b/rednose_repo/rednose/helpers/ekf_sym.h new file mode 100644 index 0000000000..b83d7f3a12 --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf_sym.h @@ -0,0 +1,113 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ekf.h" +#include "ekf_load.h" + +#define REWIND_TO_KEEP 512 + +namespace EKFS { + +typedef Eigen::Matrix MatrixXdr; + +typedef struct Observation { + double t; + int kind; + std::vector z; + std::vector R; + std::vector> extra_args; +} Observation; + +typedef struct Estimate { + Eigen::VectorXd xk1; + Eigen::VectorXd xk; + MatrixXdr Pk1; + MatrixXdr Pk; + double t; + int kind; + std::vector y; + std::vector z; + std::vector> extra_args; +} Estimate; + +class EKFSym { +public: + EKFSym(std::string name, Eigen::Map Q, Eigen::Map x_initial, + Eigen::Map P_initial, int dim_main, int dim_main_err, int N = 0, int dim_augment = 0, + int dim_augment_err = 0, std::vector maha_test_kinds = std::vector(), + std::vector quaternion_idxs = std::vector(), + std::vector global_vars = std::vector(), double max_rewind_age = 1.0); + void init_state(Eigen::Map state, Eigen::Map covs, double filter_time); + + Eigen::VectorXd state(); + MatrixXdr covs(); + void set_filter_time(double t); + double get_filter_time(); + void normalize_quaternions(); + void normalize_slice(int slice_start, int slice_end_ex); + void set_global(std::string global_var, double val); + void reset_rewind(); + + void predict(double t); + std::optional predict_and_update_batch(double t, int kind, std::vector> z, + std::vector> R, std::vector> extra_args = {{}}, bool augment = false); + + extra_routine_t get_extra_routine(const std::string& routine); + +private: + std::deque rewind(double t); + void checkpoint(Observation& obs); + + Estimate predict_and_update_batch(Observation& obs, bool augment); + Eigen::VectorXd update(int kind, Eigen::VectorXd z, MatrixXdr R, std::vector extra_args); + + // stuct with linked sympy generated functions + const EKF *ekf = NULL; + + Eigen::VectorXd x; // state + MatrixXdr P; // covs + + bool msckf; + int N; + int dim_augment; + int dim_augment_err; + int dim_main; + int dim_main_err; + + // state + int dim_x; + int dim_err; + + double filter_time; + + std::vector maha_test_kinds; + std::vector quaternion_idxs; + + std::vector global_vars; + + // process noise + MatrixXdr Q; + + // rewind stuff + double max_rewind_age; + std::deque rewind_t; + std::deque> rewind_states; + std::deque rewind_obscache; + + Eigen::VectorXd augment_times; + + std::vector feature_track_kinds; +}; + +} diff --git a/rednose_repo/rednose/helpers/ekf_sym.py b/rednose_repo/rednose/helpers/ekf_sym.py new file mode 100644 index 0000000000..9dffe50e1d --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf_sym.py @@ -0,0 +1,690 @@ +import os +import logging +from bisect import bisect_right + +import numpy as np +import sympy as sp +from numpy import dot + +from rednose.helpers.sympy_helpers import sympy_into_c +from rednose.helpers import TEMPLATE_DIR, load_code +from rednose.helpers.chi2_lookup import chi2_ppf + + +def solve(a, b): + if a.shape[0] == 1 and a.shape[1] == 1: + return b / a[0][0] + else: + return np.linalg.solve(a, b) + + +def null(H, eps=1e-12): + _, s, vh = np.linalg.svd(H) + padding = max(0, np.shape(H)[1] - np.shape(s)[0]) + null_mask = np.concatenate(((s <= eps), np.ones((padding,), dtype=bool)), axis=0) + null_space = np.compress(null_mask, vh, axis=0) + return np.transpose(null_space) + + +def gen_code(folder, name, f_sym, dt_sym, x_sym, obs_eqs, dim_x, dim_err, eskf_params=None, msckf_params=None, # pylint: disable=dangerous-default-value + maha_test_kinds=[], quaternion_idxs=[], global_vars=None, extra_routines=[]): + # optional state transition matrix, H modifier + # and err_function if an error-state kalman filter (ESKF) + # is desired. Best described in "Quaternion kinematics + # for the error-state Kalman filter" by Joan Sola + + if eskf_params: + err_eqs = eskf_params[0] + inv_err_eqs = eskf_params[1] + H_mod_sym = eskf_params[2] + f_err_sym = eskf_params[3] + x_err_sym = eskf_params[4] + else: + nom_x = sp.MatrixSymbol('nom_x', dim_x, 1) + true_x = sp.MatrixSymbol('true_x', dim_x, 1) + delta_x = sp.MatrixSymbol('delta_x', dim_x, 1) + err_function_sym = sp.Matrix(nom_x + delta_x) + inv_err_function_sym = sp.Matrix(true_x - nom_x) + err_eqs = [err_function_sym, nom_x, delta_x] + inv_err_eqs = [inv_err_function_sym, nom_x, true_x] + + H_mod_sym = sp.Matrix(np.eye(dim_x)) + f_err_sym = f_sym + x_err_sym = x_sym + + # This configures the multi-state augmentation + # needed for EKF-SLAM with MSCKF (Mourikis et al 2007) + if msckf_params: + msckf = True + dim_main = msckf_params[0] # size of the main state + dim_augment = msckf_params[1] # size of one augment state chunk + dim_main_err = msckf_params[2] + dim_augment_err = msckf_params[3] + N = msckf_params[4] + feature_track_kinds = msckf_params[5] + assert dim_main + dim_augment * N == dim_x + assert dim_main_err + dim_augment_err * N == dim_err + else: + msckf = False + dim_main = dim_x + dim_augment = 0 + dim_main_err = dim_err + dim_augment_err = 0 + N = 0 + + # linearize with jacobians + F_sym = f_err_sym.jacobian(x_err_sym) + + if eskf_params: + for sym in x_err_sym: + F_sym = F_sym.subs(sym, 0) + + assert dt_sym in F_sym.free_symbols + + for i in range(len(obs_eqs)): + obs_eqs[i].append(obs_eqs[i][0].jacobian(x_sym)) + if msckf and obs_eqs[i][1] in feature_track_kinds: + obs_eqs[i].append(obs_eqs[i][0].jacobian(obs_eqs[i][2])) + else: + obs_eqs[i].append(None) + + # collect sympy functions + sympy_functions = [] + + # extra routines + sympy_functions += extra_routines + + # error functions + sympy_functions.append(('err_fun', err_eqs[0], [err_eqs[1], err_eqs[2]])) + sympy_functions.append(('inv_err_fun', inv_err_eqs[0], [inv_err_eqs[1], inv_err_eqs[2]])) + + # H modifier for ESKF updates + sympy_functions.append(('H_mod_fun', H_mod_sym, [x_sym])) + + # state propagation function + sympy_functions.append(('f_fun', f_sym, [x_sym, dt_sym])) + sympy_functions.append(('F_fun', F_sym, [x_sym, dt_sym])) + + # observation functions + for h_sym, kind, ea_sym, H_sym, He_sym in obs_eqs: + sympy_functions.append(('h_%d' % kind, h_sym, [x_sym, ea_sym])) + sympy_functions.append(('H_%d' % kind, H_sym, [x_sym, ea_sym])) + if msckf and kind in feature_track_kinds: + sympy_functions.append(('He_%d' % kind, He_sym, [x_sym, ea_sym])) + + # Generate and wrap all th c code + sympy_header, code = sympy_into_c(sympy_functions, global_vars) + + header = "#pragma once\n" + header += "#include \"rednose/helpers/ekf.h\"\n" + header += "extern \"C\" {\n" + + pre_code = f"#include \"{name}.h\"\n" + pre_code += "\nnamespace {\n" + pre_code += "#define DIM %d\n" % dim_x + pre_code += "#define EDIM %d\n" % dim_err + pre_code += "#define MEDIM %d\n" % dim_main_err + pre_code += "typedef void (*Hfun)(double *, double *, double *);\n" + + if global_vars is not None: + for var in global_vars: + pre_code += f"\ndouble {var.name};\n" + pre_code += f"\nvoid set_{var.name}(double x){{ {var.name} = x;}}\n" + + post_code = "\n}\n" # namespace + post_code += "extern \"C\" {\n\n" + + for h_sym, kind, ea_sym, H_sym, He_sym in obs_eqs: + if msckf and kind in feature_track_kinds: + He_str = 'He_%d' % kind + # ea_dim = ea_sym.shape[0] + else: + He_str = 'NULL' + # ea_dim = 1 # not really dim of ea but makes c function work + maha_thresh = chi2_ppf(0.95, int(h_sym.shape[0])) # mahalanobis distance for outlier detection + maha_test = kind in maha_test_kinds + + pre_code += f"const static double MAHA_THRESH_{kind} = {maha_thresh};\n" + + header += f"void {name}_update_{kind}(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea);\n" + post_code += f"void {name}_update_{kind}(double *in_x, double *in_P, double *in_z, double *in_R, double *in_ea) {{\n" + post_code += f" update<{h_sym.shape[0]}, 3, {int(maha_test)}>(in_x, in_P, h_{kind}, H_{kind}, {He_str}, in_z, in_R, in_ea, MAHA_THRESH_{kind});\n" + post_code += "}\n" + + # For ffi loading of specific functions + for line in sympy_header.split("\n"): + if line.startswith("void "): # sympy functions + func_call = line[5: line.index(')') + 1] + header += f"void {name}_{func_call};\n" + post_code += f"void {name}_{func_call} {{\n" + post_code += f" {func_call.replace('double *', '').replace('double', '')};\n" + post_code += "}\n" + header += f"void {name}_predict(double *in_x, double *in_P, double *in_Q, double dt);\n" + post_code += f"void {name}_predict(double *in_x, double *in_P, double *in_Q, double dt) {{\n" + post_code += " predict(in_x, in_P, in_Q, dt);\n" + post_code += "}\n" + if global_vars is not None: + for var in global_vars: + header += f"void {name}_set_{var.name}(double x);\n" + post_code += f"void {name}_set_{var.name}(double x) {{\n" + post_code += f" set_{var.name}(x);\n" + post_code += "}\n" + + post_code += "}\n\n" # extern c + + funcs = ['f_fun', 'F_fun', 'err_fun', 'inv_err_fun', 'H_mod_fun', 'predict'] + func_lists = { + 'h': [kind for _, kind, _, _, _ in obs_eqs], + 'H': [kind for _, kind, _, _, _ in obs_eqs], + 'update': [kind for _, kind, _, _, _ in obs_eqs], + 'He': [kind for _, kind, _, _, _ in obs_eqs if msckf and kind in feature_track_kinds], + 'set': [var.name for var in global_vars] if global_vars is not None else [], + } + func_extra = [x[0] for x in extra_routines] + + # For dynamic loading of specific functions + post_code += f"const EKF {name} = {{\n" + post_code += f" .name = \"{name}\",\n" + post_code += f" .kinds = {{ {', '.join([str(kind) for _, kind, _, _, _ in obs_eqs])} }},\n" + post_code += f" .feature_kinds = {{ {', '.join([str(kind) for _, kind, _, _, _ in obs_eqs if msckf and kind in feature_track_kinds])} }},\n" + for func in funcs: + post_code += f" .{func} = {name}_{func},\n" + for group, kinds in func_lists.items(): + post_code += f" .{group}s = {{\n" + for kind in kinds: + str_kind = f"\"{kind}\"" if isinstance(kind, str) else kind + post_code += f" {{ {str_kind}, {name}_{group}_{kind} }},\n" + post_code += " },\n" + post_code += " .extra_routines = {\n" + for f in func_extra: + post_code += f" {{ \"{f}\", {name}_{f} }},\n" + post_code += " },\n" + post_code += "};\n\n" + post_code += f"ekf_lib_init({name})\n" + + # merge code blocks + header += "}" + with open(os.path.join(TEMPLATE_DIR, "ekf_c.c"), encoding='utf-8') as f: + code = "\n".join([pre_code, code, f.read(), post_code]) + + # write to file + if not os.path.exists(folder): + os.mkdir(folder) + + with open(os.path.join(folder, f"{name}.h"), 'w', encoding='utf-8') as f: + f.write(header) # header is used for ffi import + with open(os.path.join(folder, f"{name}.cpp"), 'w', encoding='utf-8') as f: + f.write(code) + + +class EKF_sym(): + def __init__(self, folder, name, Q, x_initial, P_initial, dim_main, dim_main_err, # pylint: disable=dangerous-default-value + N=0, dim_augment=0, dim_augment_err=0, maha_test_kinds=[], quaternion_idxs=[], global_vars=None, max_rewind_age=1.0, logger=logging): + """Generates process function and all observation functions for the kalman filter.""" + self.msckf = N > 0 + self.N = N + self.dim_augment = dim_augment + self.dim_augment_err = dim_augment_err + self.dim_main = dim_main + self.dim_main_err = dim_main_err + + self.logger = logger + + # state + x_initial = x_initial.reshape((-1, 1)) + self.dim_x = x_initial.shape[0] + self.dim_err = P_initial.shape[0] + assert dim_main + dim_augment * N == self.dim_x + assert dim_main_err + dim_augment_err * N == self.dim_err + assert Q.shape == P_initial.shape + + # kinds that should get mahalanobis distance + # tested for outlier rejection + self.maha_test_kinds = maha_test_kinds + + # quaternions need normalization + self.quaternion_idxs = quaternion_idxs + + # process noise + self.Q = Q + + # rewind stuff + self.max_rewind_age = max_rewind_age + self.rewind_t = [] + self.rewind_states = [] + self.rewind_obscache = [] + self.init_state(x_initial, P_initial, None) + + ffi, lib = load_code(folder, name) + kinds, self.feature_track_kinds = [], [] + for func in dir(lib): + if func[:len(name) + 3] == f'{name}_h_': + kinds.append(int(func[len(name) + 3:])) + if func[:len(name) + 4] == f'{name}_He_': + self.feature_track_kinds.append(int(func[len(name) + 4:])) + + # wrap all the sympy functions + def wrap_1lists(func_name): + func = eval(f"lib.{name}_{func_name}", {"lib": lib}) # pylint: disable=eval-used + + def ret(lst1, out): + func(ffi.cast("double *", lst1.ctypes.data), + ffi.cast("double *", out.ctypes.data)) + return ret + + def wrap_2lists(func_name): + func = eval(f"lib.{name}_{func_name}", {"lib": lib}) # pylint: disable=eval-used + + def ret(lst1, lst2, out): + func(ffi.cast("double *", lst1.ctypes.data), + ffi.cast("double *", lst2.ctypes.data), + ffi.cast("double *", out.ctypes.data)) + return ret + + def wrap_1list_1float(func_name): + func = eval(f"lib.{name}_{func_name}", {"lib": lib}) # pylint: disable=eval-used + + def ret(lst1, fl, out): + func(ffi.cast("double *", lst1.ctypes.data), + ffi.cast("double", fl), + ffi.cast("double *", out.ctypes.data)) + return ret + + self.f = wrap_1list_1float("f_fun") + self.F = wrap_1list_1float("F_fun") + + self.err_function = wrap_2lists("err_fun") + self.inv_err_function = wrap_2lists("inv_err_fun") + self.H_mod = wrap_1lists("H_mod_fun") + + self.hs, self.Hs, self.Hes = {}, {}, {} + for kind in kinds: + self.hs[kind] = wrap_2lists(f"h_{kind}") + self.Hs[kind] = wrap_2lists(f"H_{kind}") + if self.msckf and kind in self.feature_track_kinds: + self.Hes[kind] = wrap_2lists(f"He_{kind}") + + self.set_globals = {} + if global_vars is not None: + for global_var in global_vars: + self.set_globals[global_var] = getattr(lib, f"{name}_set_{global_var}") + + # wrap the C++ predict function + def _predict_blas(x, P, dt): + func = eval(f"lib.{name}_predict", {"lib": lib}) # pylint: disable=eval-used + func(ffi.cast("double *", x.ctypes.data), + ffi.cast("double *", P.ctypes.data), + ffi.cast("double *", self.Q.ctypes.data), + ffi.cast("double", dt)) + return x, P + + # wrap the C++ update function + def fun_wrapper(f, kind): + f = eval(f"lib.{name}_{f}", {"lib": lib}) # pylint: disable=eval-used + + def _update_inner_blas(x, P, z, R, extra_args): + f(ffi.cast("double *", x.ctypes.data), + ffi.cast("double *", P.ctypes.data), + ffi.cast("double *", z.ctypes.data), + ffi.cast("double *", R.ctypes.data), + ffi.cast("double *", extra_args.ctypes.data)) + if self.msckf and kind in self.feature_track_kinds: + y = z[:-len(extra_args)] + else: + y = z + return x, P, y + return _update_inner_blas + + self._updates = {} + for kind in kinds: + self._updates[kind] = fun_wrapper("update_%d" % kind, kind) + + def _update_blas(x, P, kind, z, R, extra_args=[]): # pylint: disable=dangerous-default-value + return self._updates[kind](x, P, z, R, extra_args) + + # assign the functions + self._predict = _predict_blas + # self._predict = self._predict_python + self._update = _update_blas + # self._update = self._update_python + + def init_state(self, state, covs, filter_time): + self.x = np.array(state.reshape((-1, 1))).astype(np.float64) + self.P = np.array(covs).astype(np.float64) + self.filter_time = filter_time + self.augment_times = [0] * self.N + self.rewind_obscache = [] + self.rewind_t = [] + self.rewind_states = [] + + def reset_rewind(self): + self.rewind_obscache = [] + self.rewind_t = [] + self.rewind_states = [] + + def augment(self): + # TODO this is not a generalized way of doing this and implies that the augmented states + # are simply the first (dim_augment_state) elements of the main state. + assert self.msckf + d1 = self.dim_main + d2 = self.dim_main_err + d3 = self.dim_augment + d4 = self.dim_augment_err + + # push through augmented states + self.x[d1:-d3] = self.x[d1 + d3:] + self.x[-d3:] = self.x[:d3] + assert self.x.shape == (self.dim_x, 1) + + # push through augmented covs + assert self.P.shape == (self.dim_err, self.dim_err) + P_reduced = self.P + P_reduced = np.delete(P_reduced, np.s_[d2:d2 + d4], axis=1) + P_reduced = np.delete(P_reduced, np.s_[d2:d2 + d4], axis=0) + assert P_reduced.shape == (self.dim_err - d4, self.dim_err - d4) + to_mult = np.zeros((self.dim_err, self.dim_err - d4)) + to_mult[:-d4, :] = np.eye(self.dim_err - d4) + to_mult[-d4:, :d4] = np.eye(d4) + self.P = to_mult.dot(P_reduced.dot(to_mult.T)) + self.augment_times = self.augment_times[1:] + self.augment_times.append(self.filter_time) + assert self.P.shape == (self.dim_err, self.dim_err) + + def state(self): + return np.array(self.x).flatten() + + def covs(self): + return self.P + + def set_filter_time(self, t): + self.filter_time = t + + def get_filter_time(self): + return self.filter_time + + def normalize_quaternions(self): + for idx in self.quaternion_idxs: + self.normalize_slice(idx, idx+4) + + def normalize_slice(self, slice_start, slice_end_ex): + self.x[slice_start:slice_end_ex] /= np.linalg.norm(self.x[slice_start:slice_end_ex]) + + def get_augment_times(self): + return self.augment_times + + def set_global(self, global_var, val): + self.set_globals[global_var](val) + + def rewind(self, t): + # find where we are rewinding to + idx = bisect_right(self.rewind_t, t) + assert self.rewind_t[idx - 1] <= t + assert self.rewind_t[idx] > t # must be true, or rewind wouldn't be called + + # set the state to the time right before that + self.filter_time = self.rewind_t[idx - 1] + self.x[:] = self.rewind_states[idx - 1][0] + self.P[:] = self.rewind_states[idx - 1][1] + + # return the observations we rewound over for fast forwarding + ret = self.rewind_obscache[idx:] + + # throw away the old future + # TODO: is this making a copy? + self.rewind_t = self.rewind_t[:idx] + self.rewind_states = self.rewind_states[:idx] + self.rewind_obscache = self.rewind_obscache[:idx] + + return ret + + def checkpoint(self, obs): + # push to rewinder + self.rewind_t.append(self.filter_time) + self.rewind_states.append((np.copy(self.x), np.copy(self.P))) + self.rewind_obscache.append(obs) + + # only keep a certain number around + REWIND_TO_KEEP = 512 + self.rewind_t = self.rewind_t[-REWIND_TO_KEEP:] + self.rewind_states = self.rewind_states[-REWIND_TO_KEEP:] + self.rewind_obscache = self.rewind_obscache[-REWIND_TO_KEEP:] + + def predict(self, t): + # initialize time + if self.filter_time is None: + self.filter_time = t + + # predict + dt = t - self.filter_time + assert dt >= 0 + self.x, self.P = self._predict(self.x, self.P, dt) + self.normalize_quaternions() + self.filter_time = t + + def predict_and_update_batch(self, t, kind, z, R, extra_args=[[]], augment=False): # pylint: disable=dangerous-default-value + # TODO handle rewinding at this level" + + # rewind + if self.filter_time is not None and t < self.filter_time: + if len(self.rewind_t) == 0 or t < self.rewind_t[0] or t < self.rewind_t[-1] - self.max_rewind_age: + self.logger.error(f"observation too old at {t:.3f} with filter at {self.filter_time:.3f}, ignoring") + return None + rewound = self.rewind(t) + else: + rewound = [] + + ret = self._predict_and_update_batch(t, kind, z, R, extra_args, augment) + + # optional fast forward + for r in rewound: + self._predict_and_update_batch(*r) + + return ret + + def _predict_and_update_batch(self, t, kind, z, R, extra_args, augment=False): + """The main kalman filter function + Predicts the state and then updates a batch of observations + dim_x: dimensionality of the state space + dim_z: dimensionality of the observation and depends on kind + n: number of observations + Args: + t (float): Time of observation + kind (int): Type of observation + z (vec [n,dim_z]): Measurements + R (mat [n,dim_z, dim_z]): Measurement Noise + extra_args (list, [n]): Values used in H computations + """ + assert z.shape[0] == R.shape[0] + assert z.shape[1] == R.shape[1] + assert z.shape[1] == R.shape[2] + + # initialize time + if self.filter_time is None: + self.filter_time = t + + # predict + dt = t - self.filter_time + assert dt >= 0 + self.x, self.P = self._predict(self.x, self.P, dt) + self.filter_time = t + xk_km1, Pk_km1 = np.copy(self.x).flatten(), np.copy(self.P) + + # update batch + y = [] + for i in range(len(z)): + # these are from the user, so we canonicalize them + z_i = np.array(z[i], dtype=np.float64, order='F') + R_i = np.array(R[i], dtype=np.float64, order='F') + extra_args_i = np.array(extra_args[i], dtype=np.float64, order='F') + # update + self.x, self.P, y_i = self._update(self.x, self.P, kind, z_i, R_i, extra_args=extra_args_i) + self.normalize_quaternions() + y.append(y_i) + xk_k, Pk_k = np.copy(self.x).flatten(), np.copy(self.P) + + if augment: + self.augment() + + # checkpoint + self.checkpoint((t, kind, z, R, extra_args)) + + return xk_km1, xk_k, Pk_km1, Pk_k, t, kind, y, z, extra_args + + def _predict_python(self, x, P, dt): + x_new = np.zeros(x.shape, dtype=np.float64) + self.f(x, dt, x_new) + + F = np.zeros(P.shape, dtype=np.float64) + self.F(x, dt, F) + + if not self.msckf: + P = dot(dot(F, P), F.T) + else: + # Update the predicted state covariance: + # Pk+1|k = |F*Pii*FT + Q*dt F*Pij | + # |PijT*FT Pjj | + # Where F is the jacobian of the main state + # predict function, Pii is the main state's + # covariance and Q its process noise. Pij + # is the covariance between the augmented + # states and the main state. + # + d2 = self.dim_main_err # known at compile time + F_curr = F[:d2, :d2] + P[:d2, :d2] = (F_curr.dot(P[:d2, :d2])).dot(F_curr.T) + P[:d2, d2:] = F_curr.dot(P[:d2, d2:]) + P[d2:, :d2] = P[d2:, :d2].dot(F_curr.T) + + P += dt * self.Q + return x_new, P + + def _update_python(self, x, P, kind, z, R, extra_args=[]): # pylint: disable=dangerous-default-value + # init vars + z = z.reshape((-1, 1)) + h = np.zeros(z.shape, dtype=np.float64) + H = np.zeros((z.shape[0], self.dim_x), dtype=np.float64) + + # C functions + self.hs[kind](x, extra_args, h) + self.Hs[kind](x, extra_args, H) + + # y is the "loss" + y = z - h + + # *** same above this line *** + + if self.msckf and kind in self.Hes: + # Do some algebraic magic to decorrelate + He = np.zeros((z.shape[0], len(extra_args)), dtype=np.float64) + self.Hes[kind](x, extra_args, He) + + # TODO: Don't call a function here, do projection locally + A = null(He.T) + + y = A.T.dot(y) + H = A.T.dot(H) + R = A.T.dot(R.dot(A)) + + # TODO If nullspace isn't the dimension we want + if A.shape[1] + He.shape[1] != A.shape[0]: + self.logger.warning('Warning: null space projection failed, measurement ignored') + return x, P, np.zeros(A.shape[0] - He.shape[1]) + + # if using eskf + H_mod = np.zeros((x.shape[0], P.shape[0]), dtype=np.float64) + self.H_mod(x, H_mod) + H = H.dot(H_mod) + + # Do mahalobis distance test + # currently just runs on msckf observations + # could run on anything if needed + if self.msckf and kind in self.maha_test_kinds: + a = np.linalg.inv(H.dot(P).dot(H.T) + R) + maha_dist = y.T.dot(a.dot(y)) + if maha_dist > chi2_ppf(0.95, y.shape[0]): + R = 10e16 * R + + # *** same below this line *** + + # Outlier resilient weighting as described in: + # "A Kalman Filter for Robust Outlier Detection - Jo-Anne Ting, ..." + weight = 1 # (1.5)/(1 + np.sum(y**2)/np.sum(R)) + + S = dot(dot(H, P), H.T) + R / weight + K = solve(S, dot(H, P.T)).T + I_KH = np.eye(P.shape[0]) - dot(K, H) + + # update actual state + delta_x = dot(K, y) + P = dot(dot(I_KH, P), I_KH.T) + dot(dot(K, R), K.T) + + # inject observed error into state + x_new = np.zeros(x.shape, dtype=np.float64) + self.err_function(x, delta_x, x_new) + return x_new, P, y.flatten() + + def maha_test(self, x, P, kind, z, R, extra_args=[], maha_thresh=0.95): # pylint: disable=dangerous-default-value + # init vars + z = z.reshape((-1, 1)) + h = np.zeros(z.shape, dtype=np.float64) + H = np.zeros((z.shape[0], self.dim_x), dtype=np.float64) + + # C functions + self.hs[kind](x, extra_args, h) + self.Hs[kind](x, extra_args, H) + + # y is the "loss" + y = z - h + + # if using eskf + H_mod = np.zeros((x.shape[0], P.shape[0]), dtype=np.float64) + self.H_mod(x, H_mod) + H = H.dot(H_mod) + + a = np.linalg.inv(H.dot(P).dot(H.T) + R) + maha_dist = y.T.dot(a.dot(y)) + if maha_dist > chi2_ppf(maha_thresh, y.shape[0]): + return False + else: + return True + + def rts_smooth(self, estimates, norm_quats=False): + ''' + Returns rts smoothed results of + kalman filter estimates + If the kalman state is augmented with + old states only the main state is smoothed + ''' + xk_n = estimates[-1][0] + Pk_n = estimates[-1][2] + Fk_1 = np.zeros(Pk_n.shape, dtype=np.float64) + + states_smoothed = [xk_n] + covs_smoothed = [Pk_n] + for k in range(len(estimates) - 2, -1, -1): + xk1_n = xk_n + if norm_quats: + xk1_n[3:7] /= np.linalg.norm(xk1_n[3:7]) + Pk1_n = Pk_n + + xk1_k, _, Pk1_k, _, t2, _, _, _, _ = estimates[k + 1] + _, xk_k, _, Pk_k, t1, _, _, _, _ = estimates[k] + dt = t2 - t1 + self.F(xk_k, dt, Fk_1) + + d1 = self.dim_main + d2 = self.dim_main_err + Ck = np.linalg.solve(Pk1_k[:d2, :d2], Fk_1[:d2, :d2].dot(Pk_k[:d2, :d2].T)).T + xk_n = xk_k + delta_x = np.zeros((Pk_n.shape[0], 1), dtype=np.float64) + self.inv_err_function(xk1_k, xk1_n, delta_x) + delta_x[:d2] = Ck.dot(delta_x[:d2]) + x_new = np.zeros((xk_n.shape[0], 1), dtype=np.float64) + self.err_function(xk_k, delta_x, x_new) + xk_n[:d1] = x_new[:d1, 0] + Pk_n = Pk_k + Pk_n[:d2, :d2] = Pk_k[:d2, :d2] + Ck.dot(Pk1_n[:d2, :d2] - Pk1_k[:d2, :d2]).dot(Ck.T) + states_smoothed.append(xk_n) + covs_smoothed.append(Pk_n) + + return np.flipud(np.vstack(states_smoothed)), np.stack(covs_smoothed, 0)[::-1] diff --git a/rednose_repo/rednose/helpers/ekf_sym_pyx.pyx b/rednose_repo/rednose/helpers/ekf_sym_pyx.pyx new file mode 100644 index 0000000000..f552ea7354 --- /dev/null +++ b/rednose_repo/rednose/helpers/ekf_sym_pyx.pyx @@ -0,0 +1,195 @@ +# cython: language_level=3 +# cython: profile=True +# distutils: language = c++ + +cimport cython + +from libcpp.string cimport string +from libcpp.vector cimport vector +from libcpp cimport bool +cimport numpy as np + +import numpy as np + + +cdef extern from "" namespace "std" nogil: + cdef cppclass optional[T]: + ctypedef T value_type + bool has_value() + T& value() + +cdef extern from "rednose/helpers/ekf_load.h": + cdef void ekf_load_and_register(string directory, string name) + +cdef extern from "rednose/helpers/ekf_sym.h" namespace "EKFS": + cdef cppclass MapVectorXd "Eigen::Map": + MapVectorXd(double*, int) + + cdef cppclass MapMatrixXdr "Eigen::Map >": + MapMatrixXdr(double*, int, int) + + cdef cppclass VectorXd "Eigen::VectorXd": + VectorXd() + double* data() + int rows() + + cdef cppclass MatrixXdr "Eigen::Matrix": + MatrixXdr() + double* data() + int rows() + int cols() + + ctypedef struct Estimate: + VectorXd xk1 + VectorXd xk + MatrixXdr Pk1 + MatrixXdr Pk + double t + int kind + vector[VectorXd] y + vector[VectorXd] z + vector[vector[double]] extra_args + + cdef cppclass EKFSym: + EKFSym(string name, MapMatrixXdr Q, MapVectorXd x_initial, MapMatrixXdr P_initial, int dim_main, + int dim_main_err, int N, int dim_augment, int dim_augment_err, vector[int] maha_test_kinds, + vector[int] quaternion_idxs, vector[string] global_vars, double max_rewind_age) + void init_state(MapVectorXd state, MapMatrixXdr covs, double filter_time) + + VectorXd state() + MatrixXdr covs() + void set_filter_time(double t) + double get_filter_time() + void set_global(string name, double val) + void reset_rewind() + + void predict(double t) + optional[Estimate] predict_and_update_batch(double t, int kind, vector[MapVectorXd] z, vector[MapMatrixXdr] z, + vector[vector[double]] extra_args, bool augment) + +# Functions like `numpy_to_matrix` are not possible, cython requires default +# constructor for return variable types which aren't available with Eigen::Map + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef np.ndarray[np.float64_t, ndim=2, mode="c"] matrix_to_numpy(MatrixXdr arr): + cdef double[:,:] mem_view = arr.data() + return np.copy(np.asarray(mem_view, dtype=np.double, order="C")) + +@cython.wraparound(False) +@cython.boundscheck(False) +cdef np.ndarray[np.float64_t, ndim=1, mode="c"] vector_to_numpy(VectorXd arr): + cdef double[:] mem_view = arr.data() + return np.copy(np.asarray(mem_view, dtype=np.double, order="C")) + +cdef class EKF_sym_pyx: + cdef EKFSym* ekf + def __cinit__(self, str gen_dir, str name, np.ndarray[np.float64_t, ndim=2] Q, + np.ndarray[np.float64_t, ndim=1] x_initial, np.ndarray[np.float64_t, ndim=2] P_initial, int dim_main, + int dim_main_err, int N=0, int dim_augment=0, int dim_augment_err=0, list maha_test_kinds=[], + list quaternion_idxs=[], list global_vars=[], double max_rewind_age=1.0, logger=None): + # TODO logger + ekf_load_and_register(gen_dir.encode('utf8'), name.encode('utf8')) + + cdef np.ndarray[np.float64_t, ndim=2, mode='c'] Q_b = np.ascontiguousarray(Q, dtype=np.double) + cdef np.ndarray[np.float64_t, ndim=1, mode='c'] x_initial_b = np.ascontiguousarray(x_initial, dtype=np.double) + cdef np.ndarray[np.float64_t, ndim=2, mode='c'] P_initial_b = np.ascontiguousarray(P_initial, dtype=np.double) + self.ekf = new EKFSym( + name.encode('utf8'), + MapMatrixXdr( Q_b.data, Q.shape[0], Q.shape[1]), + MapVectorXd( x_initial_b.data, x_initial.shape[0]), + MapMatrixXdr( P_initial_b.data, P_initial.shape[0], P_initial.shape[1]), + dim_main, + dim_main_err, + N, + dim_augment, + dim_augment_err, + maha_test_kinds, + quaternion_idxs, + [x.encode('utf8') for x in global_vars], + max_rewind_age + ) + + def init_state(self, np.ndarray[np.float64_t, ndim=1] state, np.ndarray[np.float64_t, ndim=2] covs, filter_time): + cdef np.ndarray[np.float64_t, ndim=1, mode='c'] state_b = np.ascontiguousarray(state, dtype=np.double) + cdef np.ndarray[np.float64_t, ndim=2, mode='c'] covs_b = np.ascontiguousarray(covs, dtype=np.double) + self.ekf.init_state( + MapVectorXd( state_b.data, state.shape[0]), + MapMatrixXdr( covs_b.data, covs.shape[0], covs.shape[1]), + np.nan if filter_time is None else filter_time + ) + + def state(self): + cdef np.ndarray res = vector_to_numpy(self.ekf.state()) + return res + + def covs(self): + return matrix_to_numpy(self.ekf.covs()) + + def set_filter_time(self, double t): + self.ekf.set_filter_time(t) + + def get_filter_time(self): + return self.ekf.get_filter_time() + + def set_global(self, str global_var, double val): + self.ekf.set_global(global_var.encode('utf8'), val) + + def reset_rewind(self): + self.ekf.reset_rewind() + + def predict(self, double t): + self.ekf.predict(t) + + def predict_and_update_batch(self, double t, int kind, z, R, extra_args=[[]], bool augment=False): + cdef vector[MapVectorXd] z_map + cdef np.ndarray[np.float64_t, ndim=1, mode='c'] zi_b + for zi in z: + zi_b = np.ascontiguousarray(zi, dtype=np.double) + z_map.push_back(MapVectorXd( zi_b.data, zi.shape[0])) + + cdef vector[MapMatrixXdr] R_map + cdef np.ndarray[np.float64_t, ndim=2, mode='c'] Ri_b + for Ri in R: + Ri_b = np.ascontiguousarray(Ri, dtype=np.double) + R_map.push_back(MapMatrixXdr( Ri_b.data, Ri.shape[0], Ri.shape[1])) + + cdef vector[vector[double]] extra_args_map + cdef vector[double] args_map + for args in extra_args: + args_map.clear() + for a in args: + args_map.push_back(a) + extra_args_map.push_back(args_map) + + cdef optional[Estimate] res = self.ekf.predict_and_update_batch(t, kind, z_map, R_map, extra_args_map, augment) + if not res.has_value(): + return None + + cdef VectorXd tmpvec + return ( + vector_to_numpy(res.value().xk1), + vector_to_numpy(res.value().xk), + matrix_to_numpy(res.value().Pk1), + matrix_to_numpy(res.value().Pk), + res.value().t, + res.value().kind, + [vector_to_numpy(tmpvec) for tmpvec in res.value().y], + z, # TODO: take return values? + extra_args, + ) + + def augment(self): + raise NotImplementedError() # TODO + + def get_augment_times(self): + raise NotImplementedError() # TODO + + def rts_smooth(self, estimates, norm_quats=False): + raise NotImplementedError() # TODO + + def maha_test(self, x, P, kind, z, R, extra_args=[], maha_thresh=0.95): + raise NotImplementedError() # TODO + + def __dealloc__(self): + del self.ekf diff --git a/rednose_repo/rednose/helpers/kalmanfilter.py b/rednose_repo/rednose/helpers/kalmanfilter.py new file mode 100644 index 0000000000..fc9fd2bf3b --- /dev/null +++ b/rednose_repo/rednose/helpers/kalmanfilter.py @@ -0,0 +1,52 @@ +from typing import Any + +import numpy as np + + +class KalmanFilter: + name = "" + initial_x = np.zeros((0, 0)) + initial_P_diag = np.zeros((0, 0)) + Q = np.zeros((0, 0)) + obs_noise: dict[int, Any] = {} + + # Should be initialized when initializating a KalmanFilter implementation + filter = None + + @property + def x(self): + return self.filter.state() + + @property + def t(self): + return self.filter.get_filter_time() + + @property + def P(self): + return self.filter.covs() + + def init_state(self, state, covs_diag=None, covs=None, filter_time=None): + if covs_diag is not None: + P = np.diag(covs_diag) + elif covs is not None: + P = covs + else: + P = self.filter.covs() + self.filter.init_state(state, P, filter_time) + + def get_R(self, kind, n): + obs_noise = self.obs_noise[kind] + dim = obs_noise.shape[0] + R = np.zeros((n, dim, dim)) + for i in range(n): + R[i, :, :] = obs_noise + return R + + def predict_and_observe(self, t, kind, data, R=None): + if len(data) > 0: + data = np.atleast_2d(data) + + if R is None: + R = self.get_R(kind, len(data)) + + self.filter.predict_and_update_batch(t, kind, data, R) diff --git a/rednose_repo/rednose/helpers/sympy_helpers.py b/rednose_repo/rednose/helpers/sympy_helpers.py new file mode 100644 index 0000000000..7f8813e8a6 --- /dev/null +++ b/rednose_repo/rednose/helpers/sympy_helpers.py @@ -0,0 +1,162 @@ +import sympy as sp +import numpy as np + +# TODO: remove code duplication between openpilot.common.orientation +def quat2rot(quats): + quats = np.array(quats) + input_shape = quats.shape + quats = np.atleast_2d(quats) + Rs = np.zeros((quats.shape[0], 3, 3)) + q0 = quats[:, 0] + q1 = quats[:, 1] + q2 = quats[:, 2] + q3 = quats[:, 3] + Rs[:, 0, 0] = q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3 + Rs[:, 0, 1] = 2 * (q1 * q2 - q0 * q3) + Rs[:, 0, 2] = 2 * (q0 * q2 + q1 * q3) + Rs[:, 1, 0] = 2 * (q1 * q2 + q0 * q3) + Rs[:, 1, 1] = q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3 + Rs[:, 1, 2] = 2 * (q2 * q3 - q0 * q1) + Rs[:, 2, 0] = 2 * (q1 * q3 - q0 * q2) + Rs[:, 2, 1] = 2 * (q0 * q1 + q2 * q3) + Rs[:, 2, 2] = q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3 + + if len(input_shape) < 2: + return Rs[0] + else: + return Rs + + +def euler2quat(eulers): + eulers = np.array(eulers) + if len(eulers.shape) > 1: + output_shape = (-1,4) + else: + output_shape = (4,) + eulers = np.atleast_2d(eulers) + gamma, theta, psi = eulers[:,0], eulers[:,1], eulers[:,2] + + q0 = np.cos(gamma / 2) * np.cos(theta / 2) * np.cos(psi / 2) + \ + np.sin(gamma / 2) * np.sin(theta / 2) * np.sin(psi / 2) + q1 = np.sin(gamma / 2) * np.cos(theta / 2) * np.cos(psi / 2) - \ + np.cos(gamma / 2) * np.sin(theta / 2) * np.sin(psi / 2) + q2 = np.cos(gamma / 2) * np.sin(theta / 2) * np.cos(psi / 2) + \ + np.sin(gamma / 2) * np.cos(theta / 2) * np.sin(psi / 2) + q3 = np.cos(gamma / 2) * np.cos(theta / 2) * np.sin(psi / 2) - \ + np.sin(gamma / 2) * np.sin(theta / 2) * np.cos(psi / 2) + + quats = np.array([q0, q1, q2, q3]).T + for i in range(len(quats)): + if quats[i,0] < 0: # pylint: disable=unsubscriptable-object + quats[i] = -quats[i] # pylint: disable=unsupported-assignment-operation,unsubscriptable-object + return quats.reshape(output_shape) + + +def euler2rot(eulers): + return quat2rot(euler2quat(eulers)) + + +rotations_from_quats = quat2rot + + +def cross(x): + ret = sp.Matrix(np.zeros((3, 3))) + ret[0, 1], ret[0, 2] = -x[2], x[1] + ret[1, 0], ret[1, 2] = x[2], -x[0] + ret[2, 0], ret[2, 1] = -x[1], x[0] + return ret + + +def rot_to_euler(R): + gamma = sp.atan2(R[2, 1], R[2, 2]) + theta = sp.asin(-R[2, 0]) + psi = sp.atan2(R[1, 0], R[0, 0]) + return sp.Matrix([gamma, theta, psi]) + + +def rot_matrix(roll, pitch, yaw): + cr, sr = np.cos(roll), np.sin(roll) + cp, sp = np.cos(pitch), np.sin(pitch) + cy, sy = np.cos(yaw), np.sin(yaw) + rr = np.array([[1,0,0],[0, cr,-sr],[0, sr, cr]]) + rp = np.array([[cp,0,sp],[0, 1,0],[-sp, 0, cp]]) + ry = np.array([[cy,-sy,0],[sy, cy,0],[0, 0, 1]]) + return ry.dot(rp.dot(rr)) + + +def euler_rotate(roll, pitch, yaw): + # make symbolic rotation matrix from eulers + matrix_roll = sp.Matrix([[1, 0, 0], + [0, sp.cos(roll), -sp.sin(roll)], + [0, sp.sin(roll), sp.cos(roll)]]) + matrix_pitch = sp.Matrix([[sp.cos(pitch), 0, sp.sin(pitch)], + [0, 1, 0], + [-sp.sin(pitch), 0, sp.cos(pitch)]]) + matrix_yaw = sp.Matrix([[sp.cos(yaw), -sp.sin(yaw), 0], + [sp.sin(yaw), sp.cos(yaw), 0], + [0, 0, 1]]) + return matrix_yaw * matrix_pitch * matrix_roll + + +def quat_rotate(q0, q1, q2, q3): + # make symbolic rotation matrix from quat + return sp.Matrix([[q0**2 + q1**2 - q2**2 - q3**2, 2 * (q1 * q2 + q0 * q3), 2 * (q1 * q3 - q0 * q2)], + [2 * (q1 * q2 - q0 * q3), q0**2 - q1**2 + q2**2 - q3**2, 2 * (q2 * q3 + q0 * q1)], + [2 * (q1 * q3 + q0 * q2), 2 * (q2 * q3 - q0 * q1), q0**2 - q1**2 - q2**2 + q3**2]]).T + + +def quat_matrix_l(p): + return sp.Matrix([[p[0], -p[1], -p[2], -p[3]], + [p[1], p[0], -p[3], p[2]], + [p[2], p[3], p[0], -p[1]], + [p[3], -p[2], p[1], p[0]]]) + + +def quat_matrix_r(p): + return sp.Matrix([[p[0], -p[1], -p[2], -p[3]], + [p[1], p[0], p[3], -p[2]], + [p[2], -p[3], p[0], p[1]], + [p[3], p[2], -p[1], p[0]]]) + + +def sympy_into_c(sympy_functions, global_vars=None): + from sympy.utilities import codegen + routines = [] + for name, expr, args in sympy_functions: + r = codegen.make_routine(name, expr, language="C99", global_vars=global_vars) + + # argument ordering input to sympy is broken with function with output arguments + nargs = [] + + # reorder the input arguments + for aa in args: + if aa is None: + nargs.append(codegen.InputArgument(sp.Symbol('unused'), dimensions=[1, 1])) + continue + found = False + for a in r.arguments: + if str(aa.name) == str(a.name): + nargs.append(a) + found = True + break + if not found: + # [1,1] is a hack for Matrices + nargs.append(codegen.InputArgument(aa, dimensions=[1, 1])) + + # add the output arguments + for a in r.arguments: + if type(a) == codegen.OutputArgument: + nargs.append(a) + + # assert len(r.arguments) == len(args)+1 + r.arguments = nargs + + # add routine to list + routines.append(r) + + [(_, c_code), (_, c_header)] = codegen.get_code_generator('C', 'ekf', 'C99').write(routines, "ekf") + c_header = '\n'.join(x for x in c_header.split("\n") if len(x) > 0 and x[0] != '#') + + c_code = '\n'.join(x for x in c_code.split("\n") if len(x) > 0 and x[0] != '#') + + return c_header, c_code diff --git a/rednose_repo/rednose/logger/logger.h b/rednose_repo/rednose/logger/logger.h new file mode 100644 index 0000000000..8f541a2b44 --- /dev/null +++ b/rednose_repo/rednose/logger/logger.h @@ -0,0 +1,20 @@ +#pragma once + +#ifdef SWAGLOG +#include SWAGLOG +#else + +#define CLOUDLOG_DEBUG 10 +#define CLOUDLOG_INFO 20 +#define CLOUDLOG_WARNING 30 +#define CLOUDLOG_ERROR 40 +#define CLOUDLOG_CRITICAL 50 + +#define cloudlog(lvl, fmt, ...) printf(fmt "\n", ## __VA_ARGS__) + +#define LOGD(fmt, ...) cloudlog(CLOUDLOG_DEBUG, fmt, ## __VA_ARGS__) +#define LOG(fmt, ...) cloudlog(CLOUDLOG_INFO, fmt, ## __VA_ARGS__) +#define LOGW(fmt, ...) cloudlog(CLOUDLOG_WARNING, fmt, ## __VA_ARGS__) +#define LOGE(fmt, ...) cloudlog(CLOUDLOG_ERROR, fmt, ## __VA_ARGS__) + +#endif diff --git a/rednose_repo/rednose/templates/compute_pos.c b/rednose_repo/rednose/templates/compute_pos.c new file mode 100644 index 0000000000..742c7d6187 --- /dev/null +++ b/rednose_repo/rednose/templates/compute_pos.c @@ -0,0 +1,52 @@ +#include +#include +#include + +typedef Eigen::Matrix R3M; +typedef Eigen::Matrix R1M; +typedef Eigen::Matrix O1M; +typedef Eigen::Matrix M3D; + +void gauss_newton(double *in_x, double *in_poses, double *in_img_positions) { + + double res[KDIM*2] = {0}; + double jac[KDIM*6] = {0}; + + O1M x(in_x); + O1M delta; + int counter = 0; + while ((delta.squaredNorm() > 0.0001 and counter < 30) or counter == 0){ + res_fun(in_x, in_poses, in_img_positions, res); + jac_fun(in_x, in_poses, in_img_positions, jac); + R1M E(res); R3M J(jac); + delta = (J.transpose()*J).inverse() * J.transpose() * E; + x = x - delta; + memcpy(in_x, x.data(), 3 * sizeof(double)); + counter = counter + 1; + } +} + + +void compute_pos(double *to_c, double *poses, double *img_positions, double *param, double *pos) { + param[0] = img_positions[KDIM*2-2]; + param[1] = img_positions[KDIM*2-1]; + param[2] = 0.1; + gauss_newton(param, poses, img_positions); + + Eigen::Quaterniond q; + q.w() = poses[KDIM*7-4]; + q.x() = poses[KDIM*7-3]; + q.y() = poses[KDIM*7-2]; + q.z() = poses[KDIM*7-1]; + M3D RC(to_c); + Eigen::Matrix3d R = q.normalized().toRotationMatrix(); + Eigen::Matrix3d rot = R * RC.transpose(); + + pos[0] = param[0]/param[2]; + pos[1] = param[1]/param[2]; + pos[2] = 1.0/param[2]; + O1M ecef_offset(poses + KDIM*7-7); + O1M ecef_output(pos); + ecef_output = rot*ecef_output + ecef_offset; + memcpy(pos, ecef_output.data(), 3 * sizeof(double)); +} diff --git a/rednose_repo/rednose/templates/ekf_c.c b/rednose_repo/rednose/templates/ekf_c.c new file mode 100644 index 0000000000..3b4acdfe3c --- /dev/null +++ b/rednose_repo/rednose/templates/ekf_c.c @@ -0,0 +1,123 @@ +#include +#include + +typedef Eigen::Matrix DDM; +typedef Eigen::Matrix EEM; +typedef Eigen::Matrix DEM; + +void predict(double *in_x, double *in_P, double *in_Q, double dt) { + typedef Eigen::Matrix RRM; + + double nx[DIM] = {0}; + double in_F[EDIM*EDIM] = {0}; + + // functions from sympy + f_fun(in_x, dt, nx); + F_fun(in_x, dt, in_F); + + + EEM F(in_F); + EEM P(in_P); + EEM Q(in_Q); + + RRM F_main = F.topLeftCorner(MEDIM, MEDIM); + P.topLeftCorner(MEDIM, MEDIM) = (F_main * P.topLeftCorner(MEDIM, MEDIM)) * F_main.transpose(); + P.topRightCorner(MEDIM, EDIM - MEDIM) = F_main * P.topRightCorner(MEDIM, EDIM - MEDIM); + P.bottomLeftCorner(EDIM - MEDIM, MEDIM) = P.bottomLeftCorner(EDIM - MEDIM, MEDIM) * F_main.transpose(); + + P = P + dt*Q; + + // copy out state + memcpy(in_x, nx, DIM * sizeof(double)); + memcpy(in_P, P.data(), EDIM * EDIM * sizeof(double)); +} + +// note: extra_args dim only correct when null space projecting +// otherwise 1 +template +void update(double *in_x, double *in_P, Hfun h_fun, Hfun H_fun, Hfun Hea_fun, double *in_z, double *in_R, double *in_ea, double MAHA_THRESHOLD) { + typedef Eigen::Matrix ZZM; + typedef Eigen::Matrix ZDM; + typedef Eigen::Matrix XEM; + //typedef Eigen::Matrix EZM; + typedef Eigen::Matrix X1M; + typedef Eigen::Matrix XXM; + + double in_hx[ZDIM] = {0}; + double in_H[ZDIM * DIM] = {0}; + double in_H_mod[EDIM * DIM] = {0}; + double delta_x[EDIM] = {0}; + double x_new[DIM] = {0}; + + + // state x, P + Eigen::Matrix z(in_z); + EEM P(in_P); + ZZM pre_R(in_R); + + // functions from sympy + h_fun(in_x, in_ea, in_hx); + H_fun(in_x, in_ea, in_H); + ZDM pre_H(in_H); + + // get y (y = z - hx) + Eigen::Matrix pre_y(in_hx); pre_y = z - pre_y; + X1M y; XXM H; XXM R; + if (Hea_fun){ + typedef Eigen::Matrix ZAM; + double in_Hea[ZDIM * EADIM] = {0}; + Hea_fun(in_x, in_ea, in_Hea); + ZAM Hea(in_Hea); + XXM A = Hea.transpose().fullPivLu().kernel(); + + + y = A.transpose() * pre_y; + H = A.transpose() * pre_H; + R = A.transpose() * pre_R * A; + } else { + y = pre_y; + H = pre_H; + R = pre_R; + } + // get modified H + H_mod_fun(in_x, in_H_mod); + DEM H_mod(in_H_mod); + XEM H_err = H * H_mod; + + // Do mahalobis distance test + if (MAHA_TEST){ + XXM a = (H_err * P * H_err.transpose() + R).inverse(); + double maha_dist = y.transpose() * a * y; + if (maha_dist > MAHA_THRESHOLD){ + R = 1.0e16 * R; + } + } + + // Outlier resilient weighting + double weight = 1;//(1.5)/(1 + y.squaredNorm()/R.sum()); + + // kalman gains and I_KH + XXM S = ((H_err * P) * H_err.transpose()) + R/weight; + XEM KT = S.fullPivLu().solve(H_err * P.transpose()); + //EZM K = KT.transpose(); TODO: WHY DOES THIS NOT COMPILE? + //EZM K = S.fullPivLu().solve(H_err * P.transpose()).transpose(); + //std::cout << "Here is the matrix rot:\n" << K << std::endl; + EEM I_KH = Eigen::Matrix::Identity() - (KT.transpose() * H_err); + + // update state by injecting dx + Eigen::Matrix dx(delta_x); + dx = (KT.transpose() * y); + memcpy(delta_x, dx.data(), EDIM * sizeof(double)); + err_fun(in_x, delta_x, x_new); + Eigen::Matrix x(x_new); + + // update cov + P = ((I_KH * P) * I_KH.transpose()) + ((KT.transpose() * R) * KT); + + // copy out state + memcpy(in_x, x.data(), DIM * sizeof(double)); + memcpy(in_P, P.data(), EDIM * EDIM * sizeof(double)); + memcpy(in_z, y.data(), y.rows() * sizeof(double)); +} + + diff --git a/rednose_repo/rednose/templates/feature_handler.c b/rednose_repo/rednose/templates/feature_handler.c new file mode 100644 index 0000000000..9c580c2eac --- /dev/null +++ b/rednose_repo/rednose/templates/feature_handler.c @@ -0,0 +1,56 @@ +bool sane(double track [K + 1][5]) { + double diffs_x [K-1]; + double diffs_y [K-1]; + int i; + for (i = 0; i < K-1; i++) { + diffs_x[i] = fabs(track[i+2][2] - track[i+1][2]); + diffs_y[i] = fabs(track[i+2][3] - track[i+1][3]); + } + for (i = 1; i < K-1; i++) { + if (((diffs_x[i] > 0.05 or diffs_x[i-1] > 0.05) and + (diffs_x[i] > 2*diffs_x[i-1] or + diffs_x[i] < .5*diffs_x[i-1])) or + ((diffs_y[i] > 0.05 or diffs_y[i-1] > 0.05) and + (diffs_y[i] > 2*diffs_y[i-1] or + diffs_y[i] < .5*diffs_y[i-1]))){ + return false; + } + } + return true; +} + +void merge_features(double *tracks, double *features, long long *empty_idxs) { + double feature_arr [3000][5]; + memcpy(feature_arr, features, 3000 * 5 * sizeof(double)); + double track_arr [6000][K + 1][5]; + memcpy(track_arr, tracks, (K+1) * 6000 * 5 * sizeof(double)); + int match; + int empty_idx = 0; + int idx; + for (int i = 0; i < 3000; i++) { + match = feature_arr[i][4]; + if (track_arr[match][0][1] == match and track_arr[match][0][2] == 0){ + track_arr[match][0][0] = track_arr[match][0][0] + 1; + track_arr[match][0][1] = feature_arr[i][1]; + track_arr[match][0][2] = 1; + idx = track_arr[match][0][0]; + memcpy(track_arr[match][idx], feature_arr[i], 5 * sizeof(double)); + if (idx == K){ + // label complete + track_arr[match][0][3] = 1; + if (sane(track_arr[match])){ + // label valid + track_arr[match][0][4] = 1; + } + } + } else { + // gen new track with this feature + track_arr[empty_idxs[empty_idx]][0][0] = 1; + track_arr[empty_idxs[empty_idx]][0][1] = feature_arr[i][1]; + track_arr[empty_idxs[empty_idx]][0][2] = 1; + memcpy(track_arr[empty_idxs[empty_idx]][1], feature_arr[i], 5 * sizeof(double)); + empty_idx = empty_idx + 1; + } + } + memcpy(tracks, track_arr, (K+1) * 6000 * 5 * sizeof(double)); +} diff --git a/rednose_repo/requirements.txt b/rednose_repo/requirements.txt new file mode 100644 index 0000000000..3077a329a8 --- /dev/null +++ b/rednose_repo/requirements.txt @@ -0,0 +1,10 @@ +ruff +sympy +numpy +scipy +cffi +scons +pre-commit +Cython +pytest +pytest-xdist diff --git a/rednose_repo/setup.py b/rednose_repo/setup.py new file mode 100644 index 0000000000..4157104e12 --- /dev/null +++ b/rednose_repo/setup.py @@ -0,0 +1,29 @@ +import os +from setuptools import setup, find_packages + +here = os.path.abspath(os.path.dirname(__file__)) + +setup( + name='rednose', + version='0.0.1', + url='https://github.com/commaai/rednose', + author='comma.ai', + author_email='harald@comma.ai', + packages=find_packages(), + platforms='any', + license='MIT', + package_data={'': ['helpers/chi2_lookup_table.npy', 'templates/*']}, + install_requires=[ + 'numpy', + 'cffi', + 'sympy', + ], + extras_require={ + 'dev': [ + 'scipy', + ], + }, + ext_modules=[], + description="Kalman filter library", + long_description='See https://github.com/commaai/rednose', +) diff --git a/rednose_repo/site_scons/site_tools/cython.py b/rednose_repo/site_scons/site_tools/cython.py new file mode 100644 index 0000000000..c291475533 --- /dev/null +++ b/rednose_repo/site_scons/site_tools/cython.py @@ -0,0 +1,72 @@ +import re +import SCons +from SCons.Action import Action +from SCons.Scanner import Scanner + +pyx_from_import_re = re.compile(r'^from\s+(\S+)\s+cimport', re.M) +pyx_import_re = re.compile(r'^cimport\s+(\S+)', re.M) +cdef_import_re = re.compile(r'^cdef extern from\s+.(\S+).:', re.M) + + +def pyx_scan(node, env, path, arg=None): + contents = node.get_text_contents() + + # from cimport ... + matches = pyx_from_import_re.findall(contents) + # cimport + matches += pyx_import_re.findall(contents) + + # Modules can be either .pxd or .pyx files + files = [m.replace('.', '/') + '.pxd' for m in matches] + files += [m.replace('.', '/') + '.pyx' for m in matches] + + # cdef extern from + files += cdef_import_re.findall(contents) + + # Handle relative imports + cur_dir = str(node.get_dir()) + files = [cur_dir + f if f.startswith('/') else f for f in files] + + # Filter out non-existing files (probably system imports) + files = [f for f in files if env.File(f).exists()] + return env.File(files) + + +pyxscanner = Scanner(function=pyx_scan, skeys=['.pyx', '.pxd'], recursive=True) +cythonAction = Action("$CYTHONCOM") + + +def create_builder(env): + try: + cython = env['BUILDERS']['Cython'] + except KeyError: + cython = SCons.Builder.Builder( + action=cythonAction, + emitter={}, + suffix=cython_suffix_emitter, + single_source=1 + ) + env.Append(SCANNERS=pyxscanner) + env['BUILDERS']['Cython'] = cython + return cython + +def cython_suffix_emitter(env, source): + return "$CYTHONCFILESUFFIX" + +def generate(env): + env["CYTHON"] = "cythonize" + env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS $SOURCE" + env["CYTHONCFILESUFFIX"] = ".cpp" + + c_file, _ = SCons.Tool.createCFileBuilders(env) + + c_file.suffix['.pyx'] = cython_suffix_emitter + c_file.add_action('.pyx', cythonAction) + + c_file.suffix['.py'] = cython_suffix_emitter + c_file.add_action('.py', cythonAction) + + create_builder(env) + +def exists(env): + return True diff --git a/rednose_repo/site_scons/site_tools/rednose_filter.py b/rednose_repo/site_scons/site_tools/rednose_filter.py new file mode 100644 index 0000000000..1a26a3b966 --- /dev/null +++ b/rednose_repo/site_scons/site_tools/rednose_filter.py @@ -0,0 +1,48 @@ +import platform + +from SCons.Script import Dir, File + + +def compile_single_filter(env, target, filter_gen_script, output_dir, extra_gen_artifacts, script_deps): + generated_src_files = [File(f) for f in [f'{output_dir}/{target}.cpp', f'{output_dir}/{target}.h']] + extra_generated_files = [File(f'{output_dir}/{x}') for x in extra_gen_artifacts] + generator_file = File(filter_gen_script) + + env.Command(generated_src_files + extra_generated_files, + [generator_file] + script_deps, f"{File(generator_file).relpath} {target} {Dir(output_dir).relpath}") + + generated_cc_file = File(generated_src_files[:1]) + + return generated_cc_file + + +class BaseRednoseCompileMethod: + def __init__(self, base_py_deps, base_cc_deps): + self.base_py_deps = base_py_deps + self.base_cc_deps = base_cc_deps + + +class CompileFilterMethod(BaseRednoseCompileMethod): + def __call__(self, env, target, filter_gen_script, output_dir, extra_gen_artifacts=[], gen_script_deps=[]): + objects = compile_single_filter(env, target, filter_gen_script, output_dir, extra_gen_artifacts, self.base_py_deps + gen_script_deps) + linker_flags = env.get("LINKFLAGS", []) + if platform.system() == "Darwin": + linker_flags = ["-undefined", "dynamic_lookup"] + lib_target = env.SharedLibrary(f'{output_dir}/{target}', [self.base_cc_deps, objects], LINKFLAGS=linker_flags) + + return lib_target + + +def generate(env): + templates = env.Glob("$REDNOSE_ROOT/rednose/templates/*") + sympy_helpers = env.File("$REDNOSE_ROOT/rednose/helpers/sympy_helpers.py") + ekf_sym = env.File("$REDNOSE_ROOT/rednose/helpers/ekf_sym.py") + + gen_script_deps = templates + [sympy_helpers, ekf_sym] + filter_lib_deps = [] + + env.AddMethod(CompileFilterMethod(gen_script_deps, filter_lib_deps), "RednoseCompileFilter") + + +def exists(env): + return True diff --git a/release/README.md b/release/README.md new file mode 100644 index 0000000000..fb651fa05a --- /dev/null +++ b/release/README.md @@ -0,0 +1,36 @@ +# openpilot releases + +``` +## release checklist + +### Go to staging +- [ ] make a GitHub issue to track release +- [ ] create release master branch +- [ ] update RELEASES.md +- [ ] bump version on master: `common/version.h` and `RELEASES.md` +- [ ] build new userdata partition from `release3-staging` +- [ ] post on Discord, tag `@release crew` + +Updating staging: +1. either rebase on master or cherry-pick changes +2. run this to update: `BRANCH=devel-staging release/build_devel.sh` +3. build new userdata partition from `release3-staging` + +### Go to release +- [ ] before going to release, test the following: + - [ ] update from previous release -> new release + - [ ] update from new release -> previous release + - [ ] fresh install with `openpilot-test.comma.ai` + - [ ] drive on fresh install + - [ ] no submodules or LFS + - [ ] check sentry, MTBF, etc. + - [ ] stress test passes in production +- [ ] publish the blog post +- [ ] `git reset --hard origin/release3-staging` +- [ ] tag the release: `git tag v0.X.X && git push origin v0.X.X` +- [ ] create GitHub release +- [ ] final test install on `openpilot.comma.ai` +- [ ] update factory provisioning +- [ ] close out milestone and issue +- [ ] post on Discord, X, etc. +``` diff --git a/release/build_release.sh b/release/build_release.sh new file mode 100755 index 0000000000..220da05c17 --- /dev/null +++ b/release/build_release.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +set -e +set -x + +# git diff --name-status origin/release3-staging | grep "^A" | less + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" + +cd $DIR + +BUILD_DIR=/data/openpilot +SOURCE_DIR="$(git rev-parse --show-toplevel)" + +if [ -z "$RELEASE_BRANCH" ]; then + echo "RELEASE_BRANCH is not set" + exit 1 +fi + + +# set git identity +source $DIR/identity.sh + +echo "[-] Setting up repo T=$SECONDS" +rm -rf $BUILD_DIR +mkdir -p $BUILD_DIR +cd $BUILD_DIR +git init +git remote add origin git@github.com:commaai/openpilot.git +git checkout --orphan $RELEASE_BRANCH + +# do the files copy +echo "[-] copying files T=$SECONDS" +cd $SOURCE_DIR +cp -pR --parents $(./release/release_files.py) $BUILD_DIR/ + +# in the directory +cd $BUILD_DIR + +rm -f panda/board/obj/panda.bin.signed +rm -f panda/board/obj/panda_h7.bin.signed + +VERSION=$(cat common/version.h | awk -F[\"-] '{print $2}') +echo "[-] committing version $VERSION T=$SECONDS" +git add -f . +git commit -a -m "openpilot v$VERSION release" + +# Build +export PYTHONPATH="$BUILD_DIR" +scons -j$(nproc) --minimal + +if [ -z "$PANDA_DEBUG_BUILD" ]; then + # release panda fw + CERT=/data/pandaextra/certs/release RELEASE=1 scons -j$(nproc) panda/ +else + # build with ALLOW_DEBUG=1 to enable features like experimental longitudinal + scons -j$(nproc) panda/ +fi + +# Ensure no submodules in release +if test "$(git submodule--helper list | wc -l)" -gt "0"; then + echo "submodules found:" + git submodule--helper list + exit 1 +fi +git submodule status + +# Cleanup +find . -name '*.a' -delete +find . -name '*.o' -delete +find . -name '*.os' -delete +find . -name '*.pyc' -delete +find . -name 'moc_*' -delete +find . -name '__pycache__' -delete +rm -rf .sconsign.dblite Jenkinsfile release/ +rm selfdrive/modeld/models/driving_vision.onnx +rm selfdrive/modeld/models/driving_policy.onnx + +find third_party/ -name '*x86*' -exec rm -r {} + +find third_party/ -name '*Darwin*' -exec rm -r {} + + + +# Restore third_party +git checkout third_party/ + +# Mark as prebuilt release +touch prebuilt + +# Add built files to git +git add -f . +git commit --amend -m "openpilot v$VERSION" + +# Run tests +cd $BUILD_DIR +RELEASE=1 pytest -n0 -s selfdrive/test/test_onroad.py +#pytest selfdrive/car/tests/test_car_interfaces.py + +if [ ! -z "$RELEASE_BRANCH" ]; then + echo "[-] pushing release T=$SECONDS" + git push -f origin $RELEASE_BRANCH:$RELEASE_BRANCH +fi + +echo "[-] done T=$SECONDS" diff --git a/release/build_stripped.sh b/release/build_stripped.sh new file mode 100755 index 0000000000..6f1a568c25 --- /dev/null +++ b/release/build_stripped.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +set -ex + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" + +SOURCE_DIR="$(git -C $DIR rev-parse --show-toplevel)" +if [ -z "$TARGET_DIR" ]; then + TARGET_DIR="$(mktemp -d)" +fi + +# set git identity +source $DIR/identity.sh + +echo "[-] Setting up target repo T=$SECONDS" + +rm -rf $TARGET_DIR +mkdir -p $TARGET_DIR +cd $TARGET_DIR +cp -r $SOURCE_DIR/.git $TARGET_DIR + +echo "[-] setting up stripped branch sync T=$SECONDS" +cd $TARGET_DIR + +# tmp branch +git checkout --orphan tmp + +# remove everything except .git +echo "[-] erasing old openpilot T=$SECONDS" +git submodule deinit -f --all +git rm -rf --cached . +find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \; + +# cleanup before the copy +cd $SOURCE_DIR +git clean -xdff +git submodule foreach --recursive git clean -xdff + +# do the files copy +echo "[-] copying files T=$SECONDS" +cd $SOURCE_DIR +cp -pR --parents $(./release/release_files.py) $TARGET_DIR/ + +# in the directory +cd $TARGET_DIR +rm -rf .git/modules/ +rm -f panda/board/obj/panda.bin.signed + +# include source commit hash and build date in commit +GIT_HASH=$(git --git-dir=$SOURCE_DIR/.git rev-parse HEAD) +GIT_COMMIT_DATE=$(git --git-dir=$SOURCE_DIR/.git show --no-patch --format='%ct %ci' HEAD) +DATETIME=$(date '+%Y-%m-%dT%H:%M:%S') +VERSION=$(cat $SOURCE_DIR/common/version.h | awk -F\" '{print $2}') + +echo -n "$GIT_HASH" > git_src_commit +echo -n "$GIT_COMMIT_DATE" > git_src_commit_date + +echo "[-] committing version $VERSION T=$SECONDS" +git add -f . +git status +git commit -a -m "openpilot v$VERSION release + +date: $DATETIME +master commit: $GIT_HASH +" + +# should be no submodules or LFS files +git submodule status +if [ ! -z "$(git lfs ls-files)" ]; then + echo "LFS files detected!" + exit 1 +fi + +# ensure files are within GitHub's limit +BIG_FILES="$(find . -type f -not -path './.git/*' -size +95M)" +if [ ! -z "$BIG_FILES" ]; then + printf '\n\n\n' + echo "Found files exceeding GitHub's 100MB limit:" + echo "$BIG_FILES" + exit 1 +fi + +if [ ! -z "$BRANCH" ]; then + echo "[-] Pushing to $BRANCH T=$SECONDS" + git push -f origin tmp:$BRANCH +fi + +echo "[-] done T=$SECONDS, ready at $TARGET_DIR" diff --git a/release/check-dirty.sh b/release/check-dirty.sh new file mode 100755 index 0000000000..ac049970cf --- /dev/null +++ b/release/check-dirty.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd $DIR + +if [ ! -z "$(git status --porcelain)" ]; then + echo "Dirty working tree after build:" + git status --porcelain + exit 1 +fi diff --git a/release/check-submodules.sh b/release/check-submodules.sh new file mode 100755 index 0000000000..93869a7403 --- /dev/null +++ b/release/check-submodules.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +while read hash submodule ref; do + if [ "$submodule" = "tinygrad_repo" ]; then + echo "Skipping $submodule" + continue + fi + + git -C $submodule fetch --depth 100 origin master + git -C $submodule branch -r --contains $hash | grep "origin/master" + if [ "$?" -eq 0 ]; then + echo "$submodule ok" + else + echo "$submodule: $hash is not on master" + exit 1 + fi +done <<< $(git submodule status --recursive) diff --git a/release/identity.sh b/release/identity.sh new file mode 100644 index 0000000000..c699c94650 --- /dev/null +++ b/release/identity.sh @@ -0,0 +1,4 @@ +export GIT_COMMITTER_NAME="Vehicle Researcher" +export GIT_COMMITTER_EMAIL="user@comma.ai" +export GIT_AUTHOR_NAME="Vehicle Researcher" +export GIT_AUTHOR_EMAIL="user@comma.ai" diff --git a/release/pack.py b/release/pack.py new file mode 100755 index 0000000000..1cb1a47a48 --- /dev/null +++ b/release/pack.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import importlib +import shutil +import sys +import tempfile +import zipapp +from argparse import ArgumentParser +from pathlib import Path + +from openpilot.common.basedir import BASEDIR + + +DIRS = ['cereal', 'openpilot'] +EXTS = ['.png', '.py', '.ttf', '.capnp'] +INTERPRETER = '/usr/bin/env python3' + + +def copy(src, dest): + if any(src.endswith(ext) for ext in EXTS): + shutil.copy2(src, dest, follow_symlinks=True) + + +if __name__ == '__main__': + parser = ArgumentParser(prog='pack.py', description="package script into a portable executable", epilog='comma.ai') + parser.add_argument('-e', '--entrypoint', help="function to call in module, default is 'main'", default='main') + parser.add_argument('-o', '--output', help='output file') + parser.add_argument('module', help="the module to target, e.g. 'openpilot.system.ui.spinner'") + args = parser.parse_args() + + if not args.output: + args.output = args.module + + try: + mod = importlib.import_module(args.module) + except ModuleNotFoundError: + print(f'{args.module} not found, typo?') + sys.exit(1) + + if not hasattr(mod, args.entrypoint): + print(f'{args.module} does not have a {args.entrypoint}() function, typo?') + sys.exit(1) + + with tempfile.TemporaryDirectory() as tmp: + for directory in DIRS: + shutil.copytree(BASEDIR + '/' + directory, tmp + '/' + directory, symlinks=False, dirs_exist_ok=True, copy_function=copy) + entry = f'{args.module}:{args.entrypoint}' + zipapp.create_archive(tmp, target=args.output, interpreter=INTERPRETER, main=entry) + + print(f'created executable {Path(args.output).resolve()}') diff --git a/release/release_files.py b/release/release_files.py new file mode 100755 index 0000000000..36910293a4 --- /dev/null +++ b/release/release_files.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import os +import re +from pathlib import Path + +HERE = os.path.abspath(os.path.dirname(__file__)) +ROOT = HERE + "/.." + +blacklist = [ + ".git/", + ".github/workflows/", + + "matlab.*.md", + + # no LFS or submodules in release + ".lfsconfig", + ".gitattributes", + ".git$", + ".gitmodules", +] + +# gets you through the blacklist +whitelist: list[str] = [ +] + +if __name__ == "__main__": + for f in Path(ROOT).rglob("**/*"): + if not (f.is_file() or f.is_symlink()): + continue + + rf = str(f.relative_to(ROOT)) + blacklisted = any(re.search(p, rf) for p in blacklist) + whitelisted = any(re.search(p, rf) for p in whitelist) + if blacklisted and not whitelisted: + continue + + print(rf) diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/apply-pr.sh b/scripts/apply-pr.sh new file mode 100755 index 0000000000..ad0af46b49 --- /dev/null +++ b/scripts/apply-pr.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if [ $# -eq 0 ]; then + echo "usage: $0 " + exit 1 +fi + +BASE="https://github.com/commaai/openpilot/pull/" +PR_NUM="$(echo $1 | grep -o -E '[0-9]+')" + +curl -L $BASE/$PR_NUM.patch | git apply -3 diff --git a/scripts/cell.sh b/scripts/cell.sh new file mode 100755 index 0000000000..310a9694fd --- /dev/null +++ b/scripts/cell.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +nmcli connection modify --temporary esim ipv4.route-metric 1 ipv6.route-metric 1 +nmcli con up esim diff --git a/scripts/checkout-pr.sh b/scripts/checkout-pr.sh new file mode 100755 index 0000000000..eeba816d88 --- /dev/null +++ b/scripts/checkout-pr.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e + +if [ $# -eq 0 ]; then + echo "usage: $0 " + exit 1 +fi + +BASE="https://github.com/commaai/openpilot/pull/" +PR_NUM="$(echo $1 | grep -o -E '[0-9]+')" +BRANCH=tmp-pr${PR_NUM} + +git branch -D -f $BRANCH || true +git fetch -u -f origin pull/$PR_NUM/head:$BRANCH +git switch $BRANCH +git reset --hard FETCH_HEAD diff --git a/scripts/disable-powersave.py b/scripts/disable-powersave.py new file mode 100755 index 0000000000..367b4108b0 --- /dev/null +++ b/scripts/disable-powersave.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +from openpilot.system.hardware import HARDWARE + +if __name__ == "__main__": + HARDWARE.set_power_save(False) diff --git a/scripts/jenkins_loop_test.sh b/scripts/jenkins_loop_test.sh new file mode 100755 index 0000000000..8073f4668c --- /dev/null +++ b/scripts/jenkins_loop_test.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash +set -e + +YELLOW='\033[0;33m' +GREEN='\033[0;32m' +UNDERLINE='\033[4m' +BOLD='\033[1m' +NC='\033[0m' + +BRANCH="master" +RUNS="20" + +COOKIE_JAR=/tmp/cookies +CRUMB=$(curl -s --cookie-jar $COOKIE_JAR 'https://jenkins.comma.life/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)') + +FIRST_LOOP=1 + +function loop() { + JENKINS_BRANCH="__jenkins_loop_${BRANCH}_$(date +%s)" + API_ROUTE="https://jenkins.comma.life/job/openpilot/job/$JENKINS_BRANCH" + + for run in $(seq 1 $((RUNS / 2))); do + + N=2 + + if [[ $FIRST_LOOP ]]; then + TEMP_DIR=$(mktemp -d) + GIT_LFS_SKIP_SMUDGE=1 git clone --quiet -b $BRANCH --depth=1 --no-tags git@github.com:commaai/openpilot $TEMP_DIR + git -C $TEMP_DIR checkout --quiet -b $JENKINS_BRANCH + echo "TESTING: $(date)" >> $TEMP_DIR/testing_jenkins + git -C $TEMP_DIR add testing_jenkins + git -C $TEMP_DIR commit --quiet -m "testing" + git -C $TEMP_DIR push --quiet -f origin $JENKINS_BRANCH + rm -rf $TEMP_DIR + FIRST_BUILD=1 + echo '' + echo 'waiting on Jenkins...' + echo '' + sleep 90 + FIRST_LOOP="" + fi + + FIRST_BUILD=$(curl -s $API_ROUTE/api/json | jq .nextBuildNumber) + LAST_BUILD=$((FIRST_BUILD+N-1)) + TEST_BUILDS=( $(seq $FIRST_BUILD $LAST_BUILD) ) + + # Start N new builds + for i in ${TEST_BUILDS[@]}; + do + echo "Starting build $i" + curl -s --output /dev/null --cookie $COOKIE_JAR -H "$CRUMB" -X POST $API_ROUTE/build?delay=0sec + sleep 5 + done + echo "" + + # Wait for all builds to end + while true; do + sleep 30 + + count=0 + for i in ${TEST_BUILDS[@]}; + do + RES=$(curl -s -w "\n%{http_code}" --cookie $COOKIE_JAR -H "$CRUMB" $API_ROUTE/$i/api/json) + HTTP_CODE=$(tail -n1 <<< "$RES") + JSON=$(sed '$ d' <<< "$RES") + + if [[ $HTTP_CODE == "200" ]]; then + STILL_RUNNING=$(echo $JSON | jq .inProgress) + if [[ $STILL_RUNNING == "true" ]]; then + echo -e "Build $i: ${YELLOW}still running${NC}" + continue + else + count=$((count+1)) + echo -e "Build $i: ${GREEN}done${NC}" + fi + else + echo "No status for build $i" + fi + done + echo "See live results: ${API_ROUTE}/buildTimeTrend" + echo "" + + if [[ $count -ge $N ]]; then + break + fi + done + + done +} + +function usage() { + echo "" + echo "Run the Jenkins tests multiple times on a specific branch" + echo "" + echo -e "${BOLD}${UNDERLINE}Options:${NC}" + echo -e " ${BOLD}-n, --n${NC}" + echo -e " Specify how many runs to do (default to ${BOLD}20${NC})" + echo -e " ${BOLD}-b, --branch${NC}" + echo -e " Specify which branch to run the tests against (default to ${BOLD}master${NC})" + echo "" +} + +function _looper() { + if [[ $# -eq 0 ]]; then + usage + exit 0 + fi + + # parse Options + while [[ $# -gt 0 ]]; do + case $1 in + -n | --n ) shift 1; RUNS="$1"; shift 1 ;; + -b | --b | --branch | -branch ) shift 1; BRANCH="$1"; shift 1 ;; + * ) usage; exit 0 ;; + esac + done + + echo "" + echo -e "You are about to start $RUNS Jenkins builds against the $BRANCH branch." + echo -e "If you expect this to run overnight, ${UNDERLINE}${BOLD}unplug the cold reboot power switch${NC} from the testing closet before." + echo "" + read -p "Press (y/Y) to confirm: " choice + if [[ "$choice" == "y" || "$choice" == "Y" ]]; then + loop + fi + +} + +_looper $@ diff --git a/scripts/launch_corolla.sh b/scripts/launch_corolla.sh new file mode 100755 index 0000000000..926569a1e0 --- /dev/null +++ b/scripts/launch_corolla.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" + +export FINGERPRINT="TOYOTA_COROLLA_TSS2" +export SKIP_FW_QUERY="1" +$DIR/../launch_openpilot.sh diff --git a/scripts/lint/check_nomerge_comments.sh b/scripts/lint/check_nomerge_comments.sh new file mode 100755 index 0000000000..6737d62a20 --- /dev/null +++ b/scripts/lint/check_nomerge_comments.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +FAIL=0 + +if grep -n '\(#\|//\)\([[:space:]]*\)NOMERGE' $@; then + echo -e "NOMERGE comments found! Remove them before merging\n" + FAIL=1 +fi + +exit $FAIL diff --git a/scripts/lint/check_raylib_includes.sh b/scripts/lint/check_raylib_includes.sh new file mode 100755 index 0000000000..e3be73a489 --- /dev/null +++ b/scripts/lint/check_raylib_includes.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +FAIL=0 + +if grep -n '#include "third_party/raylib/include/raylib\.h"' $@ | grep -v '^system/ui/raylib/raylib\.h'; then + echo -e "Bad raylib include found! Use '#include \"system/ui/raylib/raylib.h\"' instead\n" + FAIL=1 +fi + +exit $FAIL diff --git a/scripts/lint/check_shebang_format.sh b/scripts/lint/check_shebang_format.sh new file mode 100755 index 0000000000..89b95d5929 --- /dev/null +++ b/scripts/lint/check_shebang_format.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +FAIL=0 + +if grep '^#!.*python' $@ | grep -v '#!/usr/bin/env python3$'; then + echo -e "Invalid shebang! Must use '#!/usr/bin/env python3'\n" + FAIL=1 +fi + +if grep '^#!.*bash' $@ | grep -v '#!/usr/bin/env bash$'; then + echo -e "Invalid shebang! Must use '#!/usr/bin/env bash'" + FAIL=1 +fi + +exit $FAIL diff --git a/scripts/lint/lint.sh b/scripts/lint/lint.sh new file mode 100755 index 0000000000..578c63cd18 --- /dev/null +++ b/scripts/lint/lint.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash +set -e + +RED='\033[0;31m' +GREEN='\033[0;32m' +UNDERLINE='\033[4m' +BOLD='\033[1m' +NC='\033[0m' + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +ROOT="$DIR/../../" +cd $ROOT + +FAILED=0 + +IGNORED_FILES="uv\.lock|docs\/CARS.md" +IGNORED_DIRS="^third_party.*|^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*" + +function run() { + shopt -s extglob + case $1 in + $SKIP | $RUN ) return 0 ;; + esac + + echo -en "$1" + + for ((i=0; i<$((50 - ${#1})); i++)); do + echo -n "." + done + + shift 1; + CMD="$@" + + set +e + log="$((eval "$CMD" ) 2>&1)" + + if [[ $? -eq 0 ]]; then + echo -e "[${GREEN}✔${NC}]" + else + echo -e "[${RED}✗${NC}]" + echo "$log" + FAILED=1 + fi + set -e +} + +function run_tests() { + ALL_FILES=$1 + PYTHON_FILES=$2 + + run "ruff" ruff check $ROOT --quiet + run "check_added_large_files" python3 -m pre_commit_hooks.check_added_large_files --enforce-all $ALL_FILES --maxkb=120 + run "check_shebang_scripts_are_executable" python3 -m pre_commit_hooks.check_shebang_scripts_are_executable $ALL_FILES + run "check_shebang_format" $DIR/check_shebang_format.sh $ALL_FILES + run "check_nomerge_comments" $DIR/check_nomerge_comments.sh $ALL_FILES + + if [[ -z "$FAST" ]]; then + run "mypy" mypy $PYTHON_FILES + run "codespell" codespell $ALL_FILES + fi + + return $FAILED +} + +function help() { + echo "A fast linter" + echo "" + echo -e "${BOLD}${UNDERLINE}Usage:${NC} op lint [TESTS] [OPTIONS]" + echo "" + echo -e "${BOLD}${UNDERLINE}Tests:${NC}" + echo -e " ${BOLD}ruff${NC}" + echo -e " ${BOLD}mypy${NC}" + echo -e " ${BOLD}codespell${NC}" + echo -e " ${BOLD}check_added_large_files${NC}" + echo -e " ${BOLD}check_shebang_scripts_are_executable${NC}" + echo "" + echo -e "${BOLD}${UNDERLINE}Options:${NC}" + echo -e " ${BOLD}-f, --fast${NC}" + echo " Skip slow tests" + echo -e " ${BOLD}-s, --skip${NC}" + echo " Specify tests to skip separated by spaces" + echo "" + echo -e "${BOLD}${UNDERLINE}Examples:${NC}" + echo " op lint mypy ruff" + echo " Only run the mypy and ruff tests" + echo "" + echo " op lint --skip mypy ruff" + echo " Skip the mypy and ruff tests" + echo "" + echo " op lint" + echo " Run all the tests" +} + +SKIP="" +RUN="" +while [[ $# -gt 0 ]]; do + case $1 in + -f | --fast ) shift 1; FAST="1" ;; + -s | --skip ) shift 1; SKIP=" " ;; + -h | --help | -help | --h ) help; exit 0 ;; + * ) if [[ -n $SKIP ]]; then SKIP+="$1 "; else RUN+="$1 "; fi; shift 1 ;; + esac +done + +RUN=$([ -z "$RUN" ] && echo "" || echo "!($(echo $RUN | sed 's/ /|/g'))") +SKIP="@($(echo $SKIP | sed 's/ /|/g'))" + +GIT_FILES="$(git ls-files | sed -E "s/$IGNORED_FILES|$IGNORED_DIRS//g")" +ALL_FILES="" +for f in $GIT_FILES; do + if [[ -f $f ]]; then + ALL_FILES+="$f"$'\n' + fi +done +PYTHON_FILES=$(echo "$ALL_FILES" | grep --color=never '.py$' || true) + +run_tests "$ALL_FILES" "$PYTHON_FILES" diff --git a/scripts/post-commit b/scripts/post-commit new file mode 100755 index 0000000000..f9964639de --- /dev/null +++ b/scripts/post-commit @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e +if [[ -f .git/hooks/post-commit.d/post-commit ]]; then + .git/hooks/post-commit.d/post-commit +fi +tools/op.sh lint --fast +echo "" diff --git a/scripts/reporter.py b/scripts/reporter.py new file mode 100755 index 0000000000..903fcc8911 --- /dev/null +++ b/scripts/reporter.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import os +import glob +import onnx + +BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")) +MASTER_PATH = os.getenv("MASTER_PATH", BASEDIR) +MODEL_PATH = "/selfdrive/modeld/models/" + +def get_checkpoint(f): + model = onnx.load(f) + metadata = {prop.key: prop.value for prop in model.metadata_props} + return metadata['model_checkpoint'].split('/')[0] + +if __name__ == "__main__": + print("| | master | PR branch |") + print("|-| ----- | --------- |") + + for f in glob.glob(BASEDIR + MODEL_PATH + "/*.onnx"): + # TODO: add checkpoint to DM + if "dmonitoring" in f: + continue + + fn = os.path.basename(f) + master = get_checkpoint(MASTER_PATH + MODEL_PATH + fn) + pr = get_checkpoint(BASEDIR + MODEL_PATH + fn) + print( + "|", fn, "|", + f"[{master}](https://reporter.comma.life/experiment/{master})", "|", + f"[{pr}](https://reporter.comma.life/experiment/{pr})", "|" + ) diff --git a/scripts/retry.sh b/scripts/retry.sh new file mode 100755 index 0000000000..23501d7559 --- /dev/null +++ b/scripts/retry.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +function fail { + echo $1 >&2 + exit 1 +} + +function retry { + local n=1 + local max=3 # 3 retries before failure + local delay=5 # delay between retries, 5 seconds + while true; do + echo "Running command '$@' with retry, attempt $n/$max" + "$@" && break || { + if [[ $n -lt $max ]]; then + ((n++)) + sleep $delay; + else + fail "The command has failed after $n attempts." + fi + } + done +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + retry "$@" +fi diff --git a/scripts/stop_updater.sh b/scripts/stop_updater.sh new file mode 100755 index 0000000000..703b363928 --- /dev/null +++ b/scripts/stop_updater.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +# Stop updater +pkill -2 -f system.updated.updated + +# Remove pending update +rm -f /data/safe_staging/finalized/.overlay_consistent diff --git a/scripts/update_now.sh b/scripts/update_now.sh new file mode 100755 index 0000000000..c34228976a --- /dev/null +++ b/scripts/update_now.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env sh + +# Send SIGHUP to updater +pkill -1 -f system.updated diff --git a/scripts/usb.sh b/scripts/usb.sh new file mode 100755 index 0000000000..5796cfa028 --- /dev/null +++ b/scripts/usb.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# testing the GPU box + +export XDG_CACHE_HOME=/data/tinycache +mkdir -p $XDG_CACHE_HOME + +cd /data/openpilot/tinygrad_repo/examples +while true; do + AMD=1 AMD_IFACE=usb python ./beautiful_cartpole.py + sleep 1 +done diff --git a/scripts/waste.c b/scripts/waste.c new file mode 100644 index 0000000000..2e492916a7 --- /dev/null +++ b/scripts/waste.c @@ -0,0 +1,89 @@ +// gcc -O2 waste.c -lpthread -owaste +// gcc -O2 waste.c -lpthread -owaste -DMEM + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../common/timing.h" + +int get_nprocs(void); +double *ttime, *oout; + +void waste(int pid) { + cpu_set_t my_set; + CPU_ZERO(&my_set); + CPU_SET(pid, &my_set); + int ret = sched_setaffinity(0, sizeof(cpu_set_t), &my_set); + printf("set affinity to %d: %d\n", pid, ret); + + // 128 MB + float32x4_t *tmp = (float32x4_t *)malloc(0x800000*sizeof(float32x4_t)); + + // comment out the memset for CPU only and not RAM + // otherwise we need this to avoid the zero page +#ifdef MEM + memset(tmp, 0xaa, 0x800000*sizeof(float32x4_t)); +#endif + + float32x4_t out; + + double sec = seconds_since_boot(); + while (1) { + for (int i = 0; i < 0x10; i++) { + for (int j = 0; j < 0x800000; j+=0x20) { + out = vmlaq_f32(out, tmp[j+0], tmp[j+1]); + out = vmlaq_f32(out, tmp[j+2], tmp[j+3]); + out = vmlaq_f32(out, tmp[j+4], tmp[j+5]); + out = vmlaq_f32(out, tmp[j+6], tmp[j+7]); + out = vmlaq_f32(out, tmp[j+8], tmp[j+9]); + out = vmlaq_f32(out, tmp[j+10], tmp[j+11]); + out = vmlaq_f32(out, tmp[j+12], tmp[j+13]); + out = vmlaq_f32(out, tmp[j+14], tmp[j+15]); + out = vmlaq_f32(out, tmp[j+16], tmp[j+17]); + out = vmlaq_f32(out, tmp[j+18], tmp[j+19]); + out = vmlaq_f32(out, tmp[j+20], tmp[j+21]); + out = vmlaq_f32(out, tmp[j+22], tmp[j+23]); + out = vmlaq_f32(out, tmp[j+24], tmp[j+25]); + out = vmlaq_f32(out, tmp[j+26], tmp[j+27]); + out = vmlaq_f32(out, tmp[j+28], tmp[j+29]); + out = vmlaq_f32(out, tmp[j+30], tmp[j+31]); + } + } + double nsec = seconds_since_boot(); + ttime[pid] = nsec-sec; + oout[pid] = out[0] + out[1] + out[2] + out[3]; + sec = nsec; + } +} + +int main() { + int CORES = get_nprocs(); + ttime = (double *)malloc(CORES*sizeof(double)); + oout = (double *)malloc(CORES*sizeof(double)); + + pthread_t waster[CORES]; + for (long i = 0; i < CORES; i++) { + ttime[i] = NAN; + pthread_create(&waster[i], NULL, (void *(*)(void *))waste, (void*)i); + } + while (1) { + double avg = 0.0; + double iavg = 0.0; + for (int i = 0; i < CORES; i++) { + avg += ttime[i]; + iavg += 1/ttime[i]; + printf("%4.2f ", ttime[i]); + } + double mb_per_sec = (16.*0x800000/(1024*1024))*sizeof(float32x4_t)*iavg; + printf("-- %4.2f -- %.2f MB/s \n", avg/CORES, mb_per_sec); + sleep(1); + } +} + diff --git a/scripts/waste.py b/scripts/waste.py new file mode 100755 index 0000000000..bdee09d3f6 --- /dev/null +++ b/scripts/waste.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +import os +import time +import numpy as np +from multiprocessing import Process +from setproctitle import setproctitle + +def waste(core): + os.sched_setaffinity(0, [core,]) + + m1 = np.zeros((200, 200)) + 0.8 + m2 = np.zeros((200, 200)) + 1.2 + + i = 1 + st = time.monotonic() + j = 0 + while 1: + if (i % 100) == 0: + setproctitle(f"{core:3d}: {i:8d}") + lt = time.monotonic() + print(f"{core:3d}: {i:8d} {lt-st:f} {j:.2f}") + st = lt + i += 1 + j = np.sum(np.matmul(m1, m2)) + +def main(gctx=None): + print("1-2 seconds is baseline") + for i in range(os.cpu_count()): + p = Process(target=waste, args=(i,)) + p.start() + +if __name__ == "__main__": + main() diff --git a/selfdrive/SConscript b/selfdrive/SConscript new file mode 100644 index 0000000000..0b49e69116 --- /dev/null +++ b/selfdrive/SConscript @@ -0,0 +1,6 @@ +SConscript(['pandad/SConscript']) +SConscript(['controls/lib/lateral_mpc_lib/SConscript']) +SConscript(['controls/lib/longitudinal_mpc_lib/SConscript']) +SConscript(['locationd/SConscript']) +SConscript(['modeld/SConscript']) +SConscript(['ui/SConscript']) \ No newline at end of file diff --git a/selfdrive/__init__.py b/selfdrive/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/assets/.gitignore b/selfdrive/assets/.gitignore new file mode 100644 index 0000000000..1f90a2a932 --- /dev/null +++ b/selfdrive/assets/.gitignore @@ -0,0 +1,2 @@ +*.cc +translations_assets.qrc diff --git a/selfdrive/assets/assets.qrc b/selfdrive/assets/assets.qrc new file mode 100644 index 0000000000..26a7d998ed --- /dev/null +++ b/selfdrive/assets/assets.qrc @@ -0,0 +1,20 @@ + + + ../../third_party/bootstrap/bootstrap-icons.svg + images/button_continue_triangle.svg + icons/circled_check.svg + icons/circled_slash.svg + icons/eye_open.svg + icons/eye_closed.svg + icons/close.svg + icons/lock_closed.svg + icons/checkmark.svg + icons/warning.png + icons/wifi_strength_low.svg + icons/wifi_strength_medium.svg + icons/wifi_strength_high.svg + icons/wifi_strength_full.svg + + ../ui/translations/languages.json + + diff --git a/selfdrive/assets/body/awake.gif b/selfdrive/assets/body/awake.gif new file mode 100644 index 0000000000..7ec67055dd Binary files /dev/null and b/selfdrive/assets/body/awake.gif differ diff --git a/selfdrive/assets/body/sleep.gif b/selfdrive/assets/body/sleep.gif new file mode 100644 index 0000000000..469cc80338 Binary files /dev/null and b/selfdrive/assets/body/sleep.gif differ diff --git a/selfdrive/assets/compress-images.sh b/selfdrive/assets/compress-images.sh new file mode 100755 index 0000000000..de59099bd1 --- /dev/null +++ b/selfdrive/assets/compress-images.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +echo "compressing training guide images" +optipng -o7 -strip all training/* + +# This can sometimes provide smaller images +# mogrify -quality 100 -format jpg training/* diff --git a/selfdrive/assets/fonts/Inter-Black.ttf b/selfdrive/assets/fonts/Inter-Black.ttf new file mode 100644 index 0000000000..5653757735 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-Black.ttf differ diff --git a/selfdrive/assets/fonts/Inter-Bold.ttf b/selfdrive/assets/fonts/Inter-Bold.ttf new file mode 100644 index 0000000000..e98b84ce87 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-Bold.ttf differ diff --git a/selfdrive/assets/fonts/Inter-ExtraBold.ttf b/selfdrive/assets/fonts/Inter-ExtraBold.ttf new file mode 100644 index 0000000000..7f16a0f0f5 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-ExtraBold.ttf differ diff --git a/selfdrive/assets/fonts/Inter-ExtraLight.ttf b/selfdrive/assets/fonts/Inter-ExtraLight.ttf new file mode 100644 index 0000000000..69426a3eb5 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-ExtraLight.ttf differ diff --git a/selfdrive/assets/fonts/Inter-Light.ttf b/selfdrive/assets/fonts/Inter-Light.ttf new file mode 100644 index 0000000000..a5f073690d Binary files /dev/null and b/selfdrive/assets/fonts/Inter-Light.ttf differ diff --git a/selfdrive/assets/fonts/Inter-Medium.ttf b/selfdrive/assets/fonts/Inter-Medium.ttf new file mode 100644 index 0000000000..721147d831 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-Medium.ttf differ diff --git a/selfdrive/assets/fonts/Inter-Regular.ttf b/selfdrive/assets/fonts/Inter-Regular.ttf new file mode 100644 index 0000000000..96fd6a12d0 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-Regular.ttf differ diff --git a/selfdrive/assets/fonts/Inter-SemiBold.ttf b/selfdrive/assets/fonts/Inter-SemiBold.ttf new file mode 100644 index 0000000000..ddb279290b Binary files /dev/null and b/selfdrive/assets/fonts/Inter-SemiBold.ttf differ diff --git a/selfdrive/assets/fonts/Inter-Thin.ttf b/selfdrive/assets/fonts/Inter-Thin.ttf new file mode 100644 index 0000000000..76be6252b9 Binary files /dev/null and b/selfdrive/assets/fonts/Inter-Thin.ttf differ diff --git a/selfdrive/assets/fonts/JetBrainsMono-Medium.ttf b/selfdrive/assets/fonts/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000000..a6ba5529af Binary files /dev/null and b/selfdrive/assets/fonts/JetBrainsMono-Medium.ttf differ diff --git a/selfdrive/assets/fonts/NotoColorEmoji-Regular.ttf b/selfdrive/assets/fonts/NotoColorEmoji-Regular.ttf new file mode 100644 index 0000000000..5d7a86f3c6 Binary files /dev/null and b/selfdrive/assets/fonts/NotoColorEmoji-Regular.ttf differ diff --git a/selfdrive/assets/icons/arrow-right.png b/selfdrive/assets/icons/arrow-right.png new file mode 100644 index 0000000000..7040293836 Binary files /dev/null and b/selfdrive/assets/icons/arrow-right.png differ diff --git a/selfdrive/assets/icons/backspace.png b/selfdrive/assets/icons/backspace.png new file mode 100644 index 0000000000..0de132aab5 Binary files /dev/null and b/selfdrive/assets/icons/backspace.png differ diff --git a/selfdrive/assets/icons/calibration.png b/selfdrive/assets/icons/calibration.png new file mode 100644 index 0000000000..c4ee0d63d4 Binary files /dev/null and b/selfdrive/assets/icons/calibration.png differ diff --git a/selfdrive/assets/icons/capslock-fill.png b/selfdrive/assets/icons/capslock-fill.png new file mode 100644 index 0000000000..e52f3ec2f0 Binary files /dev/null and b/selfdrive/assets/icons/capslock-fill.png differ diff --git a/selfdrive/assets/icons/checkmark.png b/selfdrive/assets/icons/checkmark.png new file mode 100644 index 0000000000..c1886defdc Binary files /dev/null and b/selfdrive/assets/icons/checkmark.png differ diff --git a/selfdrive/assets/icons/checkmark.svg b/selfdrive/assets/icons/checkmark.svg new file mode 100644 index 0000000000..bb04a2b12e --- /dev/null +++ b/selfdrive/assets/icons/checkmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/icons/chevron_right.png b/selfdrive/assets/icons/chevron_right.png new file mode 100644 index 0000000000..a3aaa76486 Binary files /dev/null and b/selfdrive/assets/icons/chevron_right.png differ diff --git a/selfdrive/assets/icons/chffr_wheel.png b/selfdrive/assets/icons/chffr_wheel.png new file mode 100644 index 0000000000..3f09a35a79 Binary files /dev/null and b/selfdrive/assets/icons/chffr_wheel.png differ diff --git a/selfdrive/assets/icons/circled_check.png b/selfdrive/assets/icons/circled_check.png new file mode 100644 index 0000000000..a29a613bff Binary files /dev/null and b/selfdrive/assets/icons/circled_check.png differ diff --git a/selfdrive/assets/icons/circled_check.svg b/selfdrive/assets/icons/circled_check.svg new file mode 100644 index 0000000000..03cc81109b --- /dev/null +++ b/selfdrive/assets/icons/circled_check.svg @@ -0,0 +1,4 @@ + + + + diff --git a/selfdrive/assets/icons/circled_slash.png b/selfdrive/assets/icons/circled_slash.png new file mode 100644 index 0000000000..cf22b9c192 Binary files /dev/null and b/selfdrive/assets/icons/circled_slash.png differ diff --git a/selfdrive/assets/icons/circled_slash.svg b/selfdrive/assets/icons/circled_slash.svg new file mode 100644 index 0000000000..5f22233ef6 --- /dev/null +++ b/selfdrive/assets/icons/circled_slash.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/icons/close.png b/selfdrive/assets/icons/close.png new file mode 100644 index 0000000000..9c39fce89d Binary files /dev/null and b/selfdrive/assets/icons/close.png differ diff --git a/selfdrive/assets/icons/close.svg b/selfdrive/assets/icons/close.svg new file mode 100644 index 0000000000..6927cede05 --- /dev/null +++ b/selfdrive/assets/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/icons/close2.png b/selfdrive/assets/icons/close2.png new file mode 100644 index 0000000000..055a2970ff Binary files /dev/null and b/selfdrive/assets/icons/close2.png differ diff --git a/selfdrive/assets/icons/close2.svg b/selfdrive/assets/icons/close2.svg new file mode 100644 index 0000000000..be1385848f --- /dev/null +++ b/selfdrive/assets/icons/close2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/selfdrive/assets/icons/couch.png b/selfdrive/assets/icons/couch.png new file mode 100644 index 0000000000..bde02c0b7e Binary files /dev/null and b/selfdrive/assets/icons/couch.png differ diff --git a/selfdrive/assets/icons/couch.svg b/selfdrive/assets/icons/couch.svg new file mode 100644 index 0000000000..6317cf92f3 --- /dev/null +++ b/selfdrive/assets/icons/couch.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/icons/disengage_on_accelerator.png b/selfdrive/assets/icons/disengage_on_accelerator.png new file mode 100644 index 0000000000..181491c05d Binary files /dev/null and b/selfdrive/assets/icons/disengage_on_accelerator.png differ diff --git a/selfdrive/assets/icons/disengage_on_accelerator.svg b/selfdrive/assets/icons/disengage_on_accelerator.svg new file mode 100644 index 0000000000..d90ba8ca5f --- /dev/null +++ b/selfdrive/assets/icons/disengage_on_accelerator.svg @@ -0,0 +1,4 @@ + + + + diff --git a/selfdrive/assets/icons/driver_face.png b/selfdrive/assets/icons/driver_face.png new file mode 100644 index 0000000000..e2d943e537 Binary files /dev/null and b/selfdrive/assets/icons/driver_face.png differ diff --git a/selfdrive/assets/icons/experimental.png b/selfdrive/assets/icons/experimental.png new file mode 100644 index 0000000000..fcb1e086ab Binary files /dev/null and b/selfdrive/assets/icons/experimental.png differ diff --git a/selfdrive/assets/icons/experimental.svg b/selfdrive/assets/icons/experimental.svg new file mode 100644 index 0000000000..2be14b8084 --- /dev/null +++ b/selfdrive/assets/icons/experimental.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/selfdrive/assets/icons/experimental_grey.png b/selfdrive/assets/icons/experimental_grey.png new file mode 100644 index 0000000000..9be4bd720b Binary files /dev/null and b/selfdrive/assets/icons/experimental_grey.png differ diff --git a/selfdrive/assets/icons/experimental_grey.svg b/selfdrive/assets/icons/experimental_grey.svg new file mode 100644 index 0000000000..0f77bb008e --- /dev/null +++ b/selfdrive/assets/icons/experimental_grey.svg @@ -0,0 +1,4 @@ + + + + diff --git a/selfdrive/assets/icons/experimental_white.png b/selfdrive/assets/icons/experimental_white.png new file mode 100644 index 0000000000..4751ee5276 Binary files /dev/null and b/selfdrive/assets/icons/experimental_white.png differ diff --git a/selfdrive/assets/icons/experimental_white.svg b/selfdrive/assets/icons/experimental_white.svg new file mode 100644 index 0000000000..d5052e9d20 --- /dev/null +++ b/selfdrive/assets/icons/experimental_white.svg @@ -0,0 +1,4 @@ + + + + diff --git a/selfdrive/assets/icons/eye_closed.png b/selfdrive/assets/icons/eye_closed.png new file mode 100644 index 0000000000..910363f752 Binary files /dev/null and b/selfdrive/assets/icons/eye_closed.png differ diff --git a/selfdrive/assets/icons/eye_closed.svg b/selfdrive/assets/icons/eye_closed.svg new file mode 100644 index 0000000000..47410a035c --- /dev/null +++ b/selfdrive/assets/icons/eye_closed.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/selfdrive/assets/icons/eye_open.png b/selfdrive/assets/icons/eye_open.png new file mode 100644 index 0000000000..55b5056586 Binary files /dev/null and b/selfdrive/assets/icons/eye_open.png differ diff --git a/selfdrive/assets/icons/eye_open.svg b/selfdrive/assets/icons/eye_open.svg new file mode 100644 index 0000000000..16d34f0802 --- /dev/null +++ b/selfdrive/assets/icons/eye_open.svg @@ -0,0 +1,4 @@ + + + + diff --git a/selfdrive/assets/icons/link.png b/selfdrive/assets/icons/link.png new file mode 100644 index 0000000000..218c03a986 Binary files /dev/null and b/selfdrive/assets/icons/link.png differ diff --git a/selfdrive/assets/icons/lock_closed.png b/selfdrive/assets/icons/lock_closed.png new file mode 100644 index 0000000000..05afcaef97 Binary files /dev/null and b/selfdrive/assets/icons/lock_closed.png differ diff --git a/selfdrive/assets/icons/lock_closed.svg b/selfdrive/assets/icons/lock_closed.svg new file mode 100644 index 0000000000..923344f758 --- /dev/null +++ b/selfdrive/assets/icons/lock_closed.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/icons/menu.png b/selfdrive/assets/icons/menu.png new file mode 100644 index 0000000000..837cf5831c Binary files /dev/null and b/selfdrive/assets/icons/menu.png differ diff --git a/selfdrive/assets/icons/metric.png b/selfdrive/assets/icons/metric.png new file mode 100644 index 0000000000..eaa2438fa3 Binary files /dev/null and b/selfdrive/assets/icons/metric.png differ diff --git a/selfdrive/assets/icons/microphone.png b/selfdrive/assets/icons/microphone.png new file mode 100644 index 0000000000..787ad86e04 Binary files /dev/null and b/selfdrive/assets/icons/microphone.png differ diff --git a/selfdrive/assets/icons/minus.png b/selfdrive/assets/icons/minus.png new file mode 100644 index 0000000000..e5327c0d3b Binary files /dev/null and b/selfdrive/assets/icons/minus.png differ diff --git a/selfdrive/assets/icons/monitoring.png b/selfdrive/assets/icons/monitoring.png new file mode 100644 index 0000000000..05f78811e2 Binary files /dev/null and b/selfdrive/assets/icons/monitoring.png differ diff --git a/selfdrive/assets/icons/network.png b/selfdrive/assets/icons/network.png new file mode 100644 index 0000000000..3236924f4d Binary files /dev/null and b/selfdrive/assets/icons/network.png differ diff --git a/selfdrive/assets/icons/road.png b/selfdrive/assets/icons/road.png new file mode 100644 index 0000000000..5868ed1ccc Binary files /dev/null and b/selfdrive/assets/icons/road.png differ diff --git a/selfdrive/assets/icons/settings.png b/selfdrive/assets/icons/settings.png new file mode 100644 index 0000000000..d0c90a620d Binary files /dev/null and b/selfdrive/assets/icons/settings.png differ diff --git a/selfdrive/assets/icons/shell.png b/selfdrive/assets/icons/shell.png new file mode 100644 index 0000000000..f1d655416a Binary files /dev/null and b/selfdrive/assets/icons/shell.png differ diff --git a/selfdrive/assets/icons/shift-fill.png b/selfdrive/assets/icons/shift-fill.png new file mode 100644 index 0000000000..7cf0d25274 Binary files /dev/null and b/selfdrive/assets/icons/shift-fill.png differ diff --git a/selfdrive/assets/icons/shift.png b/selfdrive/assets/icons/shift.png new file mode 100644 index 0000000000..5847339e68 Binary files /dev/null and b/selfdrive/assets/icons/shift.png differ diff --git a/selfdrive/assets/icons/speed_limit.png b/selfdrive/assets/icons/speed_limit.png new file mode 100644 index 0000000000..0aa7038f90 Binary files /dev/null and b/selfdrive/assets/icons/speed_limit.png differ diff --git a/selfdrive/assets/icons/triangle.png b/selfdrive/assets/icons/triangle.png new file mode 100644 index 0000000000..86f9156ce4 Binary files /dev/null and b/selfdrive/assets/icons/triangle.png differ diff --git a/selfdrive/assets/icons/triangle.svg b/selfdrive/assets/icons/triangle.svg new file mode 100644 index 0000000000..ef10e16e29 --- /dev/null +++ b/selfdrive/assets/icons/triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/icons/warning.png b/selfdrive/assets/icons/warning.png new file mode 100644 index 0000000000..50fe821127 Binary files /dev/null and b/selfdrive/assets/icons/warning.png differ diff --git a/selfdrive/assets/icons/wifi_strength_full.png b/selfdrive/assets/icons/wifi_strength_full.png new file mode 100644 index 0000000000..58d3feedc6 Binary files /dev/null and b/selfdrive/assets/icons/wifi_strength_full.png differ diff --git a/selfdrive/assets/icons/wifi_strength_full.svg b/selfdrive/assets/icons/wifi_strength_full.svg new file mode 100644 index 0000000000..96af037992 --- /dev/null +++ b/selfdrive/assets/icons/wifi_strength_full.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/selfdrive/assets/icons/wifi_strength_high.png b/selfdrive/assets/icons/wifi_strength_high.png new file mode 100644 index 0000000000..327a75b2a3 Binary files /dev/null and b/selfdrive/assets/icons/wifi_strength_high.png differ diff --git a/selfdrive/assets/icons/wifi_strength_high.svg b/selfdrive/assets/icons/wifi_strength_high.svg new file mode 100644 index 0000000000..63fc8bc0bc --- /dev/null +++ b/selfdrive/assets/icons/wifi_strength_high.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/selfdrive/assets/icons/wifi_strength_low.png b/selfdrive/assets/icons/wifi_strength_low.png new file mode 100644 index 0000000000..5464acfd2b Binary files /dev/null and b/selfdrive/assets/icons/wifi_strength_low.png differ diff --git a/selfdrive/assets/icons/wifi_strength_low.svg b/selfdrive/assets/icons/wifi_strength_low.svg new file mode 100644 index 0000000000..5bc67bed5c --- /dev/null +++ b/selfdrive/assets/icons/wifi_strength_low.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/selfdrive/assets/icons/wifi_strength_medium.png b/selfdrive/assets/icons/wifi_strength_medium.png new file mode 100644 index 0000000000..5340423e58 Binary files /dev/null and b/selfdrive/assets/icons/wifi_strength_medium.png differ diff --git a/selfdrive/assets/icons/wifi_strength_medium.svg b/selfdrive/assets/icons/wifi_strength_medium.svg new file mode 100644 index 0000000000..9030dbc568 --- /dev/null +++ b/selfdrive/assets/icons/wifi_strength_medium.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/selfdrive/assets/icons/wifi_uploading.png b/selfdrive/assets/icons/wifi_uploading.png new file mode 100644 index 0000000000..e0aa598fba Binary files /dev/null and b/selfdrive/assets/icons/wifi_uploading.png differ diff --git a/selfdrive/assets/icons/wifi_uploading.svg b/selfdrive/assets/icons/wifi_uploading.svg new file mode 100644 index 0000000000..1c1c9af45e --- /dev/null +++ b/selfdrive/assets/icons/wifi_uploading.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/selfdrive/assets/images/button_continue_triangle.png b/selfdrive/assets/images/button_continue_triangle.png new file mode 100644 index 0000000000..eeacfeb830 Binary files /dev/null and b/selfdrive/assets/images/button_continue_triangle.png differ diff --git a/selfdrive/assets/images/button_continue_triangle.svg b/selfdrive/assets/images/button_continue_triangle.svg new file mode 100644 index 0000000000..814b36c4b0 --- /dev/null +++ b/selfdrive/assets/images/button_continue_triangle.svg @@ -0,0 +1,3 @@ + + + diff --git a/selfdrive/assets/images/button_flag.png b/selfdrive/assets/images/button_flag.png new file mode 100644 index 0000000000..cac4db6d4c Binary files /dev/null and b/selfdrive/assets/images/button_flag.png differ diff --git a/selfdrive/assets/images/button_home.png b/selfdrive/assets/images/button_home.png new file mode 100644 index 0000000000..9f52faf9e2 Binary files /dev/null and b/selfdrive/assets/images/button_home.png differ diff --git a/selfdrive/assets/images/button_settings.png b/selfdrive/assets/images/button_settings.png new file mode 100644 index 0000000000..e04262b887 Binary files /dev/null and b/selfdrive/assets/images/button_settings.png differ diff --git a/selfdrive/assets/images/spinner_comma.png b/selfdrive/assets/images/spinner_comma.png new file mode 100644 index 0000000000..16109557f8 Binary files /dev/null and b/selfdrive/assets/images/spinner_comma.png differ diff --git a/selfdrive/assets/images/spinner_track.png b/selfdrive/assets/images/spinner_track.png new file mode 100644 index 0000000000..931c17e836 Binary files /dev/null and b/selfdrive/assets/images/spinner_track.png differ diff --git a/selfdrive/assets/offroad/fcc.html b/selfdrive/assets/offroad/fcc.html new file mode 100644 index 0000000000..960a7a06cb --- /dev/null +++ b/selfdrive/assets/offroad/fcc.html @@ -0,0 +1,55 @@ + + +

    Supplier's Declaration of Conformity: 47 CFR § 2.1077 Compliance Information

    + +

    Unique Identifier

    +

    comma three

    + +

    Authorized Components

    + +
    Thundersoft TurboX D845 SOM
    +

    FCC ID: 2AOHHTURBOXSOMD845

    + +
    Quectel/EG25-G
    +

    FCC ID: XMR201903EG25G

    +

    This device complies with Part 15 of the FCC Rules.

    +

    Operation is subject to the following two conditions:

    + +

    (1) this device may not cause harmful interference, and

    +

    (2) this device must accept any interference received, including interference that may cause undesired operation.

    + + The following test reports are subject to this declaration: + Test report number: HR20191001605 + Issue date: 2019-2-21 + + The following manufacturer/importer/entity (located in the USA) is responsible for this declaration: + Company name: Quectel Wireless Solutions Co., Ltd. + Name/Title (legal representative): Yin JiXiong + Address: 7th Floor, Hongye Building, No.1801 Hongmei Road, Xuhui District, Shanghai 200233, China + Phone: +8602150086326 Extension: 800 + Fax: +862153253668 + E-mail: johnny.xiang@quectel.com +

    + +

    Responsible Party - U.S. Contact Information

    +

    comma.ai

    +

    501 W Broadway St

    +

    STE A #403

    +

    San Diego, California

    +

    92101

    +

    United States

    +

    support@comma.ai

    + +

    FCC Compliance Statement

    +

    This device complies with part 15 of the FCC Rules. Operation is subject to the following two conditions: (1) This device may not cause harmful interference, and (2) this device must accept any interference received, including interference that may cause undesired operation. Note: This equipment has been tested and found to comply with the limits for a Class B digital device, pursuant to part 15 of the FCC Rules. These limits are designed to provide reasonable protection against harmful interference in a residential installation.

    +

    This equipment generates, uses, and can radiate radio frequency energy and, if not installed and used in accordance with the instructions, may cause harmful interference to radio communications. However, there is no guarantee that interference will not occur in a particular installation.

    +

    If this equipment does cause harmful interference to radio or television reception, which can be determined by turning the equipment off and on, the user is encouraged to try to correct the interference by one or more of the following measures:

    +

    Reorient or relocate the receiving antenna.

    +

    Increase the separation between the equipment and receiver.

    +

    Connect the equipment to an outlet on a circuit different from that to which the receiver is connected.

    +

    Consult the dealer or an experienced radio/TV technician for help.

    +

    Changes or modifications to this product not expressly approved by the party responsible for compliance could void the electromagnetic compatibility (EMC) and wireless compliance and negate your authority to operate the product.

    +

    This product has demonstrated EMC compliance under conditions that included the use of compliant peripheral devices and shielded cables between system components. It is important that you use compliant peripheral devices and shielded cables between system components to reduce the possibility of causing interference to radios, televisions, and other electronic devices.

    +

    The radiated output power of this device meets the limits of FCC/IC radio frequency exposure limits. This device should be operated with a minimum separation distance of 20 cm (8 inches) between the equipment and a person's body.

    + + diff --git a/selfdrive/assets/prep-svg.sh b/selfdrive/assets/prep-svg.sh new file mode 100755 index 0000000000..2332cd25c5 --- /dev/null +++ b/selfdrive/assets/prep-svg.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +ICONS_DIR="$DIR/icons" +BOOTSTRAP_SVG="$DIR/../../third_party/bootstrap/bootstrap-icons.svg" + +ICON_IDS=( + arrow-right + backspace + capslock-fill + shift + shift-fill +) +ICON_FILL_COLOR="#fff" + +# extract bootstrap icons +for id in "${ICON_IDS[@]}"; do + svg="${ICONS_DIR}/${id}.svg" + perl -0777 -ne "print \$& if /]*id=\"$id\"[^>]*>.*?<\/symbol>/s" "$BOOTSTRAP_SVG" \ + | sed "s//<\/svg>/" > "$svg" +done + +# sudo apt install inkscape + +for svg in $(find $DIR -type f | grep svg$); do + bunx svgo $svg --multipass --pretty --indent 2 + + # convert to PNG + png="${svg%.svg}.png" + width=$(inkscape --query-width "$svg") + height=$(inkscape --query-height "$svg") + if (( $(echo "$width > $height" | bc -l) )); then + export_dim="--export-width=512" + else + export_dim="--export-height=512" + fi + inkscape "$svg" --export-filename="$png" "$export_dim" + + optipng -o7 -strip all "$png" +done + +# cleanup bootstrap SVGs +for id in "${ICON_IDS[@]}"; do + rm "${ICONS_DIR}/${id}.svg" +done diff --git a/selfdrive/assets/sounds/disengage.wav b/selfdrive/assets/sounds/disengage.wav new file mode 100644 index 0000000000..ba583c41f3 Binary files /dev/null and b/selfdrive/assets/sounds/disengage.wav differ diff --git a/selfdrive/assets/sounds/engage.wav b/selfdrive/assets/sounds/engage.wav new file mode 100644 index 0000000000..41e9b2d588 Binary files /dev/null and b/selfdrive/assets/sounds/engage.wav differ diff --git a/selfdrive/assets/sounds/prompt.wav b/selfdrive/assets/sounds/prompt.wav new file mode 100644 index 0000000000..1ae77051eb Binary files /dev/null and b/selfdrive/assets/sounds/prompt.wav differ diff --git a/selfdrive/assets/sounds/prompt_distracted.wav b/selfdrive/assets/sounds/prompt_distracted.wav new file mode 100644 index 0000000000..c3d4475caa Binary files /dev/null and b/selfdrive/assets/sounds/prompt_distracted.wav differ diff --git a/selfdrive/assets/sounds/refuse.wav b/selfdrive/assets/sounds/refuse.wav new file mode 100644 index 0000000000..0e80f7d127 Binary files /dev/null and b/selfdrive/assets/sounds/refuse.wav differ diff --git a/selfdrive/assets/sounds/warning_immediate.wav b/selfdrive/assets/sounds/warning_immediate.wav new file mode 100644 index 0000000000..b1815a9586 Binary files /dev/null and b/selfdrive/assets/sounds/warning_immediate.wav differ diff --git a/selfdrive/assets/sounds/warning_soft.wav b/selfdrive/assets/sounds/warning_soft.wav new file mode 100644 index 0000000000..261c7e1376 Binary files /dev/null and b/selfdrive/assets/sounds/warning_soft.wav differ diff --git a/selfdrive/assets/training/step0.png b/selfdrive/assets/training/step0.png new file mode 100644 index 0000000000..3c2c5c72a0 Binary files /dev/null and b/selfdrive/assets/training/step0.png differ diff --git a/selfdrive/assets/training/step1.png b/selfdrive/assets/training/step1.png new file mode 100644 index 0000000000..0857893118 Binary files /dev/null and b/selfdrive/assets/training/step1.png differ diff --git a/selfdrive/assets/training/step10.png b/selfdrive/assets/training/step10.png new file mode 100644 index 0000000000..2941316d17 Binary files /dev/null and b/selfdrive/assets/training/step10.png differ diff --git a/selfdrive/assets/training/step11.png b/selfdrive/assets/training/step11.png new file mode 100644 index 0000000000..7a7c72e3df Binary files /dev/null and b/selfdrive/assets/training/step11.png differ diff --git a/selfdrive/assets/training/step12.png b/selfdrive/assets/training/step12.png new file mode 100644 index 0000000000..0d6f64eb84 Binary files /dev/null and b/selfdrive/assets/training/step12.png differ diff --git a/selfdrive/assets/training/step13.png b/selfdrive/assets/training/step13.png new file mode 100644 index 0000000000..565e02fa3f Binary files /dev/null and b/selfdrive/assets/training/step13.png differ diff --git a/selfdrive/assets/training/step14.png b/selfdrive/assets/training/step14.png new file mode 100644 index 0000000000..225231cbaa Binary files /dev/null and b/selfdrive/assets/training/step14.png differ diff --git a/selfdrive/assets/training/step15.png b/selfdrive/assets/training/step15.png new file mode 100644 index 0000000000..929c759b26 Binary files /dev/null and b/selfdrive/assets/training/step15.png differ diff --git a/selfdrive/assets/training/step16.png b/selfdrive/assets/training/step16.png new file mode 100644 index 0000000000..161af863aa Binary files /dev/null and b/selfdrive/assets/training/step16.png differ diff --git a/selfdrive/assets/training/step17.png b/selfdrive/assets/training/step17.png new file mode 100644 index 0000000000..1b0cdb6fbc Binary files /dev/null and b/selfdrive/assets/training/step17.png differ diff --git a/selfdrive/assets/training/step18.png b/selfdrive/assets/training/step18.png new file mode 100644 index 0000000000..0e3b64bab5 Binary files /dev/null and b/selfdrive/assets/training/step18.png differ diff --git a/selfdrive/assets/training/step2.png b/selfdrive/assets/training/step2.png new file mode 100644 index 0000000000..55814b8ef9 Binary files /dev/null and b/selfdrive/assets/training/step2.png differ diff --git a/selfdrive/assets/training/step3.png b/selfdrive/assets/training/step3.png new file mode 100644 index 0000000000..831095b0ae Binary files /dev/null and b/selfdrive/assets/training/step3.png differ diff --git a/selfdrive/assets/training/step4.png b/selfdrive/assets/training/step4.png new file mode 100644 index 0000000000..5433034939 Binary files /dev/null and b/selfdrive/assets/training/step4.png differ diff --git a/selfdrive/assets/training/step5.png b/selfdrive/assets/training/step5.png new file mode 100644 index 0000000000..7191b63a0c Binary files /dev/null and b/selfdrive/assets/training/step5.png differ diff --git a/selfdrive/assets/training/step6.png b/selfdrive/assets/training/step6.png new file mode 100644 index 0000000000..8eafd4a198 Binary files /dev/null and b/selfdrive/assets/training/step6.png differ diff --git a/selfdrive/assets/training/step7.png b/selfdrive/assets/training/step7.png new file mode 100644 index 0000000000..502f5f1b2e Binary files /dev/null and b/selfdrive/assets/training/step7.png differ diff --git a/selfdrive/assets/training/step8.png b/selfdrive/assets/training/step8.png new file mode 100644 index 0000000000..77ff9d7368 Binary files /dev/null and b/selfdrive/assets/training/step8.png differ diff --git a/selfdrive/assets/training/step9.png b/selfdrive/assets/training/step9.png new file mode 100644 index 0000000000..84eae3a066 Binary files /dev/null and b/selfdrive/assets/training/step9.png differ diff --git a/selfdrive/car/CARS_template.md b/selfdrive/car/CARS_template.md new file mode 100644 index 0000000000..463683fd3c --- /dev/null +++ b/selfdrive/car/CARS_template.md @@ -0,0 +1,74 @@ +{% set footnote_tag = '[{}](#footnotes)' %} +{% set star_icon = '[![star](assets/icon-star-{}.svg)](##)' %} +{% set video_icon = '' %} +{# Force hardware column wider by using a blank image with max width. #} +{% set width_tag = '%s
     ' %} +{% set hardware_col_name = 'Hardware Needed' %} +{% set wide_hardware_col_name = width_tag|format(hardware_col_name) -%} + + + +# Supported Cars + +A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified. + +# {{all_car_docs | selectattr('support_type', 'eq', SupportType.UPSTREAM) | list | length}} Supported Cars + +|{{Column | map(attribute='value') | join('|') | replace(hardware_col_name, wide_hardware_col_name)}}| +|---|---|---|{% for _ in range((Column | length) - 3) %}{{':---:|'}}{% endfor +%} +{% for car_docs in all_car_docs | selectattr('support_type', 'eq', SupportType.UPSTREAM) %} +|{% for column in Column %}{{car_docs.get_column(column, star_icon, video_icon, footnote_tag)}}|{% endfor %} + +{% endfor %} + +### Footnotes +{% for footnote in footnotes %} +{{loop.index}}{{footnote | replace('
    ', '')}}
    +{% endfor %} + +## Community Maintained Cars +Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/). + +# Don't see your car here? + +**openpilot can support many more cars than it currently does.** There are a few reasons your car may not be supported. +If your car doesn't fit into any of the incompatibility criteria here, then there's a good chance it can be supported! We're adding support for new cars all the time. **We don't have a roadmap for car support**, and in fact, most car support comes from users like you! + +### Which cars are able to be supported? + +openpilot uses the existing steering, gas, and brake interfaces in your car. If your car lacks any one of these interfaces, openpilot will not be able to control the car. If your car has [ACC](https://en.wikipedia.org/wiki/Adaptive_cruise_control) and any form of [LKAS](https://en.wikipedia.org/wiki/Automated_Lane_Keeping_Systems)/[LCA](https://en.wikipedia.org/wiki/Lane_centering), then it almost certainly has these interfaces. These features generally started shipping on cars around 2016. Note that manufacturers will often make their own [marketing terms](https://en.wikipedia.org/wiki/Adaptive_cruise_control#Vehicle_models_supporting_adaptive_cruise_control) for these features, such as Hyundai's "Smart Cruise Control" branding of Adaptive Cruise Control. + +If your car has the following packages or features, then it's a good candidate for support. + +| Make | Required Package/Features | +| ---- | ------------------------- | +| Acura | Any car with AcuraWatch Plus will work. AcuraWatch Plus comes standard on many newer models. | +| Ford | Any car with Lane Centering will likely work. | +| Honda | Any car with Honda Sensing will work. Honda Sensing comes standard on many newer models. | +| Subaru | Any car with EyeSight will work. EyeSight comes standard on many newer models. | +| Nissan | Any car with ProPILOT will likely work. | +| Toyota & Lexus | Any car that has Toyota/Lexus Safety Sense with "Lane Departure Alert with Steering Assist (LDA w/SA)" and/or "Lane Tracing Assist (LTA)" will work. Note that LDA without Steering Assist will not work. These features come standard on most newer models. | +| Hyundai, Kia, & Genesis | Any car with Smart Cruise Control (SCC) and Lane Following Assist (LFA) or Lane Keeping Assist (LKAS) will work. LKAS/LFA comes standard on most newer models. Any form of SCC will work, such as NSCC. | +| Chrysler, Jeep, & Ram | Any car with LaneSense and Adaptive Cruise Control will likely work. These come standard on many newer models. | + +### FlexRay + +All the cars that openpilot supports use a [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) for communication between all the car's computers, however a CAN bus isn't the only way that the computers in your car can communicate. Most, if not all, vehicles from the following manufacturers use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) instead of a CAN bus: **BMW, Mercedes, Audi, Land Rover, and some Volvo**. These cars may one day be supported, but we have no immediate plans to support FlexRay. + +### Toyota Security + +openpilot does not yet support these Toyota models due to a new message authentication method. +[Vote](https://comma.ai/shop#toyota-security) if you'd like to see openpilot support on these models. + +* Toyota RAV4 Prime 2021+ +* Toyota Sienna 2021+ +* Toyota Venza 2021+ +* Toyota Sequoia 2023+ +* Toyota Tundra 2022+ +* Toyota Highlander 2024+ +* Toyota Corolla Cross 2022+ (only US model) +* Toyota Camry 2025+ +* Lexus NX 2022+ +* Toyota bZ4x 2023+ +* Subaru Solterra 2023+ + diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/car/car_specific.py b/selfdrive/car/car_specific.py new file mode 100644 index 0000000000..5319d286b0 --- /dev/null +++ b/selfdrive/car/car_specific.py @@ -0,0 +1,217 @@ +from cereal import car, log +import cereal.messaging as messaging +from opendbc.car import DT_CTRL, structs +from opendbc.car.interfaces import MAX_CTRL_SPEED + +from openpilot.selfdrive.selfdrived.events import Events + +ButtonType = structs.CarState.ButtonEvent.Type +GearShifter = structs.CarState.GearShifter +EventName = log.OnroadEvent.EventName +NetworkLocation = structs.CarParams.NetworkLocation + + +# TODO: the goal is to abstract this file into the CarState struct and make events generic +class MockCarState: + def __init__(self): + self.sm = messaging.SubMaster(['gpsLocation', 'gpsLocationExternal']) + + def update(self, CS: car.CarState): + self.sm.update(0) + gps_sock = 'gpsLocationExternal' if self.sm.recv_frame['gpsLocationExternal'] > 1 else 'gpsLocation' + + CS.vEgo = self.sm[gps_sock].speed + CS.vEgoRaw = self.sm[gps_sock].speed + + return CS + + +class CarSpecificEvents: + def __init__(self, CP: structs.CarParams): + self.CP = CP + + self.steering_unpressed = 0 + self.low_speed_alert = False + self.no_steer_warning = False + self.silent_steer_warning = True + + def update(self, CS: car.CarState, CS_prev: car.CarState, CC: car.CarControl): + if self.CP.brand in ('body', 'mock'): + events = Events() + + elif self.CP.brand == 'ford': + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.low, GearShifter.manumatic]) + + elif self.CP.brand == 'nissan': + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.brake]) + + elif self.CP.brand == 'chrysler': + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.low]) + + # Low speed steer alert hysteresis logic + if self.CP.minSteerSpeed > 0. and CS.vEgo < (self.CP.minSteerSpeed + 0.5): + self.low_speed_alert = True + elif CS.vEgo > (self.CP.minSteerSpeed + 1.): + self.low_speed_alert = False + if self.low_speed_alert: + events.add(EventName.belowSteerSpeed) + + elif self.CP.brand == 'honda': + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.sport], pcm_enable=False) + + if self.CP.pcmCruise and CS.vEgo < self.CP.minEnableSpeed: + events.add(EventName.belowEngageSpeed) + + if self.CP.pcmCruise: + # we engage when pcm is active (rising edge) + if CS.cruiseState.enabled and not CS_prev.cruiseState.enabled: + events.add(EventName.pcmEnable) + elif not CS.cruiseState.enabled and (CC.actuators.accel >= 0. or not self.CP.openpilotLongitudinalControl): + # it can happen that car cruise disables while comma system is enabled: need to + # keep braking if needed or if the speed is very low + if CS.vEgo < self.CP.minEnableSpeed + 2.: + # non loud alert if cruise disables below 25mph as expected (+ a little margin) + events.add(EventName.speedTooLow) + else: + events.add(EventName.cruiseDisabled) + if self.CP.minEnableSpeed > 0 and CS.vEgo < 0.001: + events.add(EventName.manualRestart) + + elif self.CP.brand == 'toyota': + # TODO: when we check for unexpected disengagement, check gear not S1, S2, S3 + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.sport]) + + if self.CP.openpilotLongitudinalControl: + if CS.cruiseState.standstill and not CS.brakePressed: + events.add(EventName.resumeRequired) + if CS.vEgo < self.CP.minEnableSpeed: + events.add(EventName.belowEngageSpeed) + if CC.actuators.accel > 0.3: + # some margin on the actuator to not false trigger cancellation while stopping + events.add(EventName.speedTooLow) + if CS.vEgo < 0.001: + # while in standstill, send a user alert + events.add(EventName.manualRestart) + + elif self.CP.brand == 'gm': + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.sport, GearShifter.low, + GearShifter.eco, GearShifter.manumatic], + pcm_enable=self.CP.pcmCruise) + + # Enabling at a standstill with brake is allowed + # TODO: verify 17 Volt can enable for the first time at a stop and allow for all GMs + if CS.vEgo < self.CP.minEnableSpeed and not (CS.standstill and CS.brake >= 20 and + self.CP.networkLocation == NetworkLocation.fwdCamera): + events.add(EventName.belowEngageSpeed) + if CS.cruiseState.standstill: + events.add(EventName.resumeRequired) + + elif self.CP.brand == 'volkswagen': + events = self.create_common_events(CS, CS_prev, extra_gears=[GearShifter.eco, GearShifter.sport, GearShifter.manumatic], + pcm_enable=self.CP.pcmCruise) + + if self.CP.openpilotLongitudinalControl: + if CS.vEgo < self.CP.minEnableSpeed + 0.5: + events.add(EventName.belowEngageSpeed) + if CC.enabled and CS.vEgo < self.CP.minEnableSpeed: + events.add(EventName.speedTooLow) + + # TODO: this needs to be implemented generically in carState struct + # if CC.eps_timer_soft_disable_alert: # type: ignore[attr-defined] + # events.add(EventName.steerTimeLimit) + + elif self.CP.brand == 'hyundai': + events = self.create_common_events(CS, CS_prev, extra_gears=(GearShifter.sport, GearShifter.manumatic), + pcm_enable=self.CP.pcmCruise, allow_button_cancel=False) + + else: + events = self.create_common_events(CS, CS_prev) + + return events + + def create_common_events(self, CS: structs.CarState, CS_prev: car.CarState, extra_gears=None, pcm_enable=True, + allow_button_cancel=True): + events = Events() + + if CS.doorOpen: + events.add(EventName.doorOpen) + if CS.seatbeltUnlatched: + events.add(EventName.seatbeltNotLatched) + if CS.gearShifter != GearShifter.drive and (extra_gears is None or + CS.gearShifter not in extra_gears): + events.add(EventName.wrongGear) + if CS.gearShifter == GearShifter.reverse: + events.add(EventName.reverseGear) + if not CS.cruiseState.available: + events.add(EventName.wrongCarMode) + if CS.espDisabled: + events.add(EventName.espDisabled) + if CS.espActive: + events.add(EventName.espActive) + if CS.stockFcw: + events.add(EventName.stockFcw) + if CS.stockAeb: + events.add(EventName.stockAeb) + if CS.vEgo > MAX_CTRL_SPEED: + events.add(EventName.speedTooHigh) + if CS.cruiseState.nonAdaptive: + events.add(EventName.wrongCruiseMode) + if CS.brakeHoldActive and self.CP.openpilotLongitudinalControl: + events.add(EventName.brakeHold) + if CS.parkingBrake: + events.add(EventName.parkBrake) + if CS.accFaulted: + events.add(EventName.accFaulted) + if CS.steeringPressed: + events.add(EventName.steerOverride) + if CS.steeringDisengage and not CS_prev.steeringDisengage: + events.add(EventName.steerDisengage) + if CS.brakePressed and CS.standstill: + events.add(EventName.preEnableStandstill) + if CS.gasPressed: + events.add(EventName.gasPressedOverride) + if CS.vehicleSensorsInvalid: + events.add(EventName.vehicleSensorsInvalid) + if CS.invalidLkasSetting: + events.add(EventName.invalidLkasSetting) + if CS.lowSpeedAlert: + events.add(EventName.belowSteerSpeed) + if CS.buttonEnable: + events.add(EventName.buttonEnable) + + # Handle cancel button presses + for b in CS.buttonEvents: + # Disable on rising and falling edge of cancel for both stock and OP long + # TODO: only check the cancel button with openpilot longitudinal on all brands to match panda safety + if b.type == ButtonType.cancel and (allow_button_cancel or not self.CP.pcmCruise): + events.add(EventName.buttonCancel) + + # Handle permanent and temporary steering faults + self.steering_unpressed = 0 if CS.steeringPressed else self.steering_unpressed + 1 + if CS.steerFaultTemporary: + if CS.steeringPressed and (not CS_prev.steerFaultTemporary or self.no_steer_warning): + self.no_steer_warning = True + else: + self.no_steer_warning = False + + # if the user overrode recently, show a less harsh alert + if self.silent_steer_warning or CS.standstill or self.steering_unpressed < int(1.5 / DT_CTRL): + self.silent_steer_warning = True + events.add(EventName.steerTempUnavailableSilent) + else: + events.add(EventName.steerTempUnavailable) + else: + self.no_steer_warning = False + self.silent_steer_warning = False + if CS.steerFaultPermanent: + events.add(EventName.steerUnavailable) + + # we engage when pcm is active (rising edge) + # enabling can optionally be blocked by the car interface + if pcm_enable: + if CS.cruiseState.enabled and not CS_prev.cruiseState.enabled and not CS.blockPcmEnable: + events.add(EventName.pcmEnable) + elif not CS.cruiseState.enabled: + events.add(EventName.pcmDisable) + + return events diff --git a/selfdrive/car/card.py b/selfdrive/car/card.py new file mode 100755 index 0000000000..27b04ae65e --- /dev/null +++ b/selfdrive/car/card.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 +import os +import time +import threading + +import cereal.messaging as messaging + +from cereal import car, log + +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper +from openpilot.common.swaglog import cloudlog, ForwardingHandler + +from opendbc.car import DT_CTRL, structs +from opendbc.car.can_definitions import CanData, CanRecvCallable, CanSendCallable +from opendbc.car.carlog import carlog +from opendbc.car.fw_versions import ObdCallback +from opendbc.car.car_helpers import get_car, interfaces +from opendbc.car.interfaces import CarInterfaceBase, RadarInterfaceBase +from openpilot.selfdrive.pandad import can_capnp_to_list, can_list_to_can_capnp +from openpilot.selfdrive.car.cruise import VCruiseHelper +from openpilot.selfdrive.car.car_specific import MockCarState + +REPLAY = "REPLAY" in os.environ + +EventName = log.OnroadEvent.EventName + +# forward +carlog.addHandler(ForwardingHandler(cloudlog)) + + +def obd_callback(params: Params) -> ObdCallback: + def set_obd_multiplexing(obd_multiplexing: bool): + if params.get_bool("ObdMultiplexingEnabled") != obd_multiplexing: + cloudlog.warning(f"Setting OBD multiplexing to {obd_multiplexing}") + params.remove("ObdMultiplexingChanged") + params.put_bool("ObdMultiplexingEnabled", obd_multiplexing) + params.get_bool("ObdMultiplexingChanged", block=True) + cloudlog.warning("OBD multiplexing set successfully") + return set_obd_multiplexing + + +def can_comm_callbacks(logcan: messaging.SubSocket, sendcan: messaging.PubSocket) -> tuple[CanRecvCallable, CanSendCallable]: + def can_recv(wait_for_one: bool = False) -> list[list[CanData]]: + """ + wait_for_one: wait the normal logcan socket timeout for a CAN packet, may return empty list if nothing comes + + Returns: CAN packets comprised of CanData objects for easy access + """ + ret = [] + for can in messaging.drain_sock(logcan, wait_for_one=wait_for_one): + ret.append([CanData(msg.address, msg.dat, msg.src) for msg in can.can]) + return ret + + def can_send(msgs: list[CanData]) -> None: + sendcan.send(can_list_to_can_capnp(msgs, msgtype='sendcan')) + + return can_recv, can_send + + +class Car: + CI: CarInterfaceBase + RI: RadarInterfaceBase + CP: car.CarParams + + def __init__(self, CI=None, RI=None) -> None: + self.can_sock = messaging.sub_sock('can', timeout=20) + self.sm = messaging.SubMaster(['pandaStates', 'carControl', 'onroadEvents']) + self.pm = messaging.PubMaster(['sendcan', 'carState', 'carParams', 'carOutput', 'liveTracks']) + + self.can_rcv_cum_timeout_counter = 0 + + self.CC_prev = car.CarControl.new_message() + self.CS_prev = car.CarState.new_message() + self.initialized_prev = False + + self.last_actuators_output = structs.CarControl.Actuators() + + self.params = Params() + + self.can_callbacks = can_comm_callbacks(self.can_sock, self.pm.sock['sendcan']) + + is_release = self.params.get_bool("IsReleaseBranch") + + if CI is None: + # wait for one pandaState and one CAN packet + print("Waiting for CAN messages...") + while True: + can = messaging.recv_one_retry(self.can_sock) + if len(can.can) > 0: + break + + alpha_long_allowed = self.params.get_bool("AlphaLongitudinalEnabled") + num_pandas = len(messaging.recv_one_retry(self.sm.sock['pandaStates']).pandaStates) + + cached_params = None + cached_params_raw = self.params.get("CarParamsCache") + if cached_params_raw is not None: + with car.CarParams.from_bytes(cached_params_raw) as _cached_params: + cached_params = _cached_params + + self.CI = get_car(*self.can_callbacks, obd_callback(self.params), alpha_long_allowed, is_release, num_pandas, cached_params) + self.RI = interfaces[self.CI.CP.carFingerprint].RadarInterface(self.CI.CP) + self.CP = self.CI.CP + + # continue onto next fingerprinting step in pandad + self.params.put_bool("FirmwareQueryDone", True) + else: + self.CI, self.CP = CI, CI.CP + self.RI = RI + + self.CP.alternativeExperience = 0 + openpilot_enabled_toggle = self.params.get_bool("OpenpilotEnabledToggle") + controller_available = self.CI.CC is not None and openpilot_enabled_toggle and not self.CP.dashcamOnly + self.CP.passive = not controller_available or self.CP.dashcamOnly + if self.CP.passive: + safety_config = structs.CarParams.SafetyConfig() + safety_config.safetyModel = structs.CarParams.SafetyModel.noOutput + self.CP.safetyConfigs = [safety_config] + + if self.CP.secOcRequired and not is_release: + # Copy user key if available + try: + with open("/cache/params/SecOCKey") as f: + user_key = f.readline().strip() + if len(user_key) == 32: + self.params.put("SecOCKey", user_key) + except Exception: + pass + + secoc_key = self.params.get("SecOCKey") + if secoc_key is not None: + saved_secoc_key = bytes.fromhex(secoc_key.strip()) + if len(saved_secoc_key) == 16: + self.CP.secOcKeyAvailable = True + self.CI.CS.secoc_key = saved_secoc_key + if controller_available: + self.CI.CC.secoc_key = saved_secoc_key + else: + cloudlog.warning("Saved SecOC key is invalid") + + # Write previous route's CarParams + prev_cp = self.params.get("CarParamsPersistent") + if prev_cp is not None: + self.params.put("CarParamsPrevRoute", prev_cp) + + # Write CarParams for controls and radard + cp_bytes = self.CP.to_bytes() + self.params.put("CarParams", cp_bytes) + self.params.put_nonblocking("CarParamsCache", cp_bytes) + self.params.put_nonblocking("CarParamsPersistent", cp_bytes) + + self.mock_carstate = MockCarState() + self.v_cruise_helper = VCruiseHelper(self.CP) + + self.is_metric = self.params.get_bool("IsMetric") + self.experimental_mode = self.params.get_bool("ExperimentalMode") + + # card is driven by can recv, expected at 100Hz + self.rk = Ratekeeper(100, print_delay_threshold=None) + + def state_update(self) -> tuple[car.CarState, structs.RadarDataT | None]: + """carState update loop, driven by can""" + + can_strs = messaging.drain_sock_raw(self.can_sock, wait_for_one=True) + can_list = can_capnp_to_list(can_strs) + + # Update carState from CAN + CS = self.CI.update(can_list) + if self.CP.brand == 'mock': + CS = self.mock_carstate.update(CS) + + # Update radar tracks from CAN + RD: structs.RadarDataT | None = self.RI.update(can_list) + + self.sm.update(0) + + can_rcv_valid = len(can_strs) > 0 + + # Check for CAN timeout + if not can_rcv_valid: + self.can_rcv_cum_timeout_counter += 1 + + if can_rcv_valid and REPLAY: + self.can_log_mono_time = messaging.log_from_bytes(can_strs[0]).logMonoTime + + self.v_cruise_helper.update_v_cruise(CS, self.sm['carControl'].enabled, self.is_metric) + if self.sm['carControl'].enabled and not self.CC_prev.enabled: + # Use CarState w/ buttons from the step selfdrived enables on + self.v_cruise_helper.initialize_v_cruise(self.CS_prev, self.experimental_mode) + + # TODO: mirror the carState.cruiseState struct? + CS.vCruise = float(self.v_cruise_helper.v_cruise_kph) + CS.vCruiseCluster = float(self.v_cruise_helper.v_cruise_cluster_kph) + + return CS, RD + + def state_publish(self, CS: car.CarState, RD: structs.RadarDataT | None): + """carState and carParams publish loop""" + + # carParams - logged every 50 seconds (> 1 per segment) + if self.sm.frame % int(50. / DT_CTRL) == 0: + cp_send = messaging.new_message('carParams') + cp_send.valid = True + cp_send.carParams = self.CP + self.pm.send('carParams', cp_send) + + # publish new carOutput + co_send = messaging.new_message('carOutput') + co_send.valid = self.sm.all_checks(['carControl']) + co_send.carOutput.actuatorsOutput = self.last_actuators_output + self.pm.send('carOutput', co_send) + + # kick off controlsd step while we actuate the latest carControl packet + cs_send = messaging.new_message('carState') + cs_send.valid = CS.canValid + cs_send.carState = CS + cs_send.carState.canErrorCounter = self.can_rcv_cum_timeout_counter + cs_send.carState.cumLagMs = -self.rk.remaining * 1000. + self.pm.send('carState', cs_send) + + if RD is not None: + tracks_msg = messaging.new_message('liveTracks') + tracks_msg.valid = not any(RD.errors.to_dict().values()) + tracks_msg.liveTracks = RD + self.pm.send('liveTracks', tracks_msg) + + def controls_update(self, CS: car.CarState, CC: car.CarControl): + """control update loop, driven by carControl""" + + if not self.initialized_prev: + # Initialize CarInterface, once controls are ready + # TODO: this can make us miss at least a few cycles when doing an ECU knockout + self.CI.init(self.CP, *self.can_callbacks) + # signal pandad to switch to car safety mode + self.params.put_bool_nonblocking("ControlsReady", True) + + if self.sm.all_alive(['carControl']): + # send car controls over can + now_nanos = self.can_log_mono_time if REPLAY else int(time.monotonic() * 1e9) + self.last_actuators_output, can_sends = self.CI.apply(CC, now_nanos) + self.pm.send('sendcan', can_list_to_can_capnp(can_sends, msgtype='sendcan', valid=CS.canValid)) + + self.CC_prev = CC + + def step(self): + CS, RD = self.state_update() + + self.state_publish(CS, RD) + + initialized = (not any(e.name == EventName.selfdriveInitializing for e in self.sm['onroadEvents']) and + self.sm.seen['onroadEvents']) + if not self.CP.passive and initialized: + self.controls_update(CS, self.sm['carControl']) + + self.initialized_prev = initialized + self.CS_prev = CS + + def params_thread(self, evt): + while not evt.is_set(): + self.is_metric = self.params.get_bool("IsMetric") + self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl + time.sleep(0.1) + + def card_thread(self): + e = threading.Event() + t = threading.Thread(target=self.params_thread, args=(e, )) + try: + t.start() + while True: + self.step() + self.rk.monitor_time() + finally: + e.set() + t.join() + + +def main(): + config_realtime_process(4, Priority.CTRL_HIGH) + car = Car() + car.card_thread() + + +if __name__ == "__main__": + main() diff --git a/selfdrive/car/cruise.py b/selfdrive/car/cruise.py new file mode 100644 index 0000000000..0d761844b5 --- /dev/null +++ b/selfdrive/car/cruise.py @@ -0,0 +1,138 @@ +import math +import numpy as np + +from cereal import car +from openpilot.common.constants import CV + + +# WARNING: this value was determined based on the model's training distribution, +# model predictions above this speed can be unpredictable +# V_CRUISE's are in kph +V_CRUISE_MIN = 8 +V_CRUISE_MAX = 145 +V_CRUISE_UNSET = 255 +V_CRUISE_INITIAL = 40 +V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 105 +IMPERIAL_INCREMENT = round(CV.MPH_TO_KPH, 1) # round here to avoid rounding errors incrementing set speed + +ButtonEvent = car.CarState.ButtonEvent +ButtonType = car.CarState.ButtonEvent.Type +CRUISE_LONG_PRESS = 50 +CRUISE_NEAREST_FUNC = { + ButtonType.accelCruise: math.ceil, + ButtonType.decelCruise: math.floor, +} +CRUISE_INTERVAL_SIGN = { + ButtonType.accelCruise: +1, + ButtonType.decelCruise: -1, +} + + +class VCruiseHelper: + def __init__(self, CP): + self.CP = CP + self.v_cruise_kph = V_CRUISE_UNSET + self.v_cruise_cluster_kph = V_CRUISE_UNSET + self.v_cruise_kph_last = 0 + self.button_timers = {ButtonType.decelCruise: 0, ButtonType.accelCruise: 0} + self.button_change_states = {btn: {"standstill": False, "enabled": False} for btn in self.button_timers} + + @property + def v_cruise_initialized(self): + return self.v_cruise_kph != V_CRUISE_UNSET + + def update_v_cruise(self, CS, enabled, is_metric): + self.v_cruise_kph_last = self.v_cruise_kph + + if CS.cruiseState.available: + if not self.CP.pcmCruise: + # if stock cruise is completely disabled, then we can use our own set speed logic + self._update_v_cruise_non_pcm(CS, enabled, is_metric) + self.v_cruise_cluster_kph = self.v_cruise_kph + self.update_button_timers(CS, enabled) + else: + self.v_cruise_kph = CS.cruiseState.speed * CV.MS_TO_KPH + self.v_cruise_cluster_kph = CS.cruiseState.speedCluster * CV.MS_TO_KPH + if CS.cruiseState.speed == 0: + self.v_cruise_kph = V_CRUISE_UNSET + self.v_cruise_cluster_kph = V_CRUISE_UNSET + elif CS.cruiseState.speed == -1: + self.v_cruise_kph = -1 + self.v_cruise_cluster_kph = -1 + else: + self.v_cruise_kph = V_CRUISE_UNSET + self.v_cruise_cluster_kph = V_CRUISE_UNSET + + def _update_v_cruise_non_pcm(self, CS, enabled, is_metric): + # handle button presses. TODO: this should be in state_control, but a decelCruise press + # would have the effect of both enabling and changing speed is checked after the state transition + if not enabled: + return + + long_press = False + button_type = None + + v_cruise_delta = 1. if is_metric else IMPERIAL_INCREMENT + + for b in CS.buttonEvents: + if b.type.raw in self.button_timers and not b.pressed: + if self.button_timers[b.type.raw] > CRUISE_LONG_PRESS: + return # end long press + button_type = b.type.raw + break + else: + for k, timer in self.button_timers.items(): + if timer and timer % CRUISE_LONG_PRESS == 0: + button_type = k + long_press = True + break + + if button_type is None: + return + + # Don't adjust speed when pressing resume to exit standstill + cruise_standstill = self.button_change_states[button_type]["standstill"] or CS.cruiseState.standstill + if button_type == ButtonType.accelCruise and cruise_standstill: + return + + # Don't adjust speed if we've enabled since the button was depressed (some ports enable on rising edge) + if not self.button_change_states[button_type]["enabled"]: + return + + v_cruise_delta = v_cruise_delta * (5 if long_press else 1) + if long_press and self.v_cruise_kph % v_cruise_delta != 0: # partial interval + self.v_cruise_kph = CRUISE_NEAREST_FUNC[button_type](self.v_cruise_kph / v_cruise_delta) * v_cruise_delta + else: + self.v_cruise_kph += v_cruise_delta * CRUISE_INTERVAL_SIGN[button_type] + + # If set is pressed while overriding, clip cruise speed to minimum of vEgo + if CS.gasPressed and button_type in (ButtonType.decelCruise, ButtonType.setCruise): + self.v_cruise_kph = max(self.v_cruise_kph, CS.vEgo * CV.MS_TO_KPH) + + self.v_cruise_kph = np.clip(round(self.v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX) + + def update_button_timers(self, CS, enabled): + # increment timer for buttons still pressed + for k in self.button_timers: + if self.button_timers[k] > 0: + self.button_timers[k] += 1 + + for b in CS.buttonEvents: + if b.type.raw in self.button_timers: + # Start/end timer and store current state on change of button pressed + self.button_timers[b.type.raw] = 1 if b.pressed else 0 + self.button_change_states[b.type.raw] = {"standstill": CS.cruiseState.standstill, "enabled": enabled} + + def initialize_v_cruise(self, CS, experimental_mode: bool) -> None: + # initializing is handled by the PCM + if self.CP.pcmCruise: + return + + initial = V_CRUISE_INITIAL_EXPERIMENTAL_MODE if experimental_mode else V_CRUISE_INITIAL + + if any(b.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for b in CS.buttonEvents) and self.v_cruise_initialized: + self.v_cruise_kph = self.v_cruise_kph_last + else: + self.v_cruise_kph = int(round(np.clip(CS.vEgo * CV.MS_TO_KPH, initial, V_CRUISE_MAX))) + + self.v_cruise_cluster_kph = self.v_cruise_kph diff --git a/selfdrive/car/docs.py b/selfdrive/car/docs.py new file mode 100755 index 0000000000..f807fc320e --- /dev/null +++ b/selfdrive/car/docs.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +import argparse +import os + +from openpilot.common.basedir import BASEDIR +from opendbc.car.docs import get_all_car_docs, generate_cars_md + +CARS_MD_OUT = os.path.join(BASEDIR, "docs", "CARS.md") +CARS_MD_TEMPLATE = os.path.join(BASEDIR, "selfdrive", "car", "CARS_template.md") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Auto generates supported cars documentation", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("--template", default=CARS_MD_TEMPLATE, help="Override default template filename") + parser.add_argument("--out", default=CARS_MD_OUT, help="Override default generated filename") + args = parser.parse_args() + + with open(args.out, 'w') as f: + f.write(generate_cars_md(get_all_car_docs(), args.template)) + print(f"Generated and written to {args.out}") diff --git a/selfdrive/car/tests/.gitignore b/selfdrive/car/tests/.gitignore new file mode 100644 index 0000000000..192fb0945e --- /dev/null +++ b/selfdrive/car/tests/.gitignore @@ -0,0 +1 @@ +*.bz2 diff --git a/selfdrive/car/tests/__init__.py b/selfdrive/car/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/car/tests/big_cars_test.sh b/selfdrive/car/tests/big_cars_test.sh new file mode 100755 index 0000000000..863b8bead0 --- /dev/null +++ b/selfdrive/car/tests/big_cars_test.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +SCRIPT_DIR=$(dirname "$0") +BASEDIR=$(realpath "$SCRIPT_DIR/../../../") +cd $BASEDIR + +export MAX_EXAMPLES=300 +export INTERNAL_SEG_CNT=300 +export FILEREADER_CACHE=1 +export INTERNAL_SEG_LIST=selfdrive/car/tests/test_models_segs.txt + +cd selfdrive/car/tests && pytest test_models.py test_car_interfaces.py diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py new file mode 100644 index 0000000000..c40443d7e7 --- /dev/null +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -0,0 +1,61 @@ +import os +import hypothesis.strategies as st +from hypothesis import Phase, given, settings +from parameterized import parameterized + +from cereal import car +from opendbc.car import DT_CTRL +from opendbc.car.structs import CarParams +from opendbc.car.tests.test_car_interfaces import get_fuzzy_car_interface +from opendbc.car.mock.values import CAR as MOCK +from opendbc.car.values import PLATFORMS +from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle +from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID +from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque +from openpilot.selfdrive.controls.lib.longcontrol import LongControl +from openpilot.selfdrive.test.fuzzy_generation import FuzzyGenerator + +MAX_EXAMPLES = int(os.environ.get('MAX_EXAMPLES', '60')) + + +class TestCarInterfaces: + # FIXME: Due to the lists used in carParams, Phase.target is very slow and will cause + # many generated examples to overrun when max_examples > ~20, don't use it + @parameterized.expand([(car,) for car in sorted(PLATFORMS)] + [MOCK.MOCK]) + @settings(max_examples=MAX_EXAMPLES, deadline=None, + phases=(Phase.reuse, Phase.generate, Phase.shrink)) + @given(data=st.data()) + def test_car_interfaces(self, car_name, data): + car_interface = get_fuzzy_car_interface(car_name, data.draw) + car_params = car_interface.CP.as_reader() + + cc_msg = FuzzyGenerator.get_random_msg(data.draw, car.CarControl, real_floats=True) + # Run car interface + now_nanos = 0 + CC = car.CarControl.new_message(**cc_msg) + CC = CC.as_reader() + for _ in range(10): + car_interface.update([]) + car_interface.apply(CC, now_nanos) + now_nanos += DT_CTRL * 1e9 # 10 ms + + CC = car.CarControl.new_message(**cc_msg) + CC.enabled = True + CC.latActive = True + CC.longActive = True + CC = CC.as_reader() + for _ in range(10): + car_interface.update([]) + car_interface.apply(CC, now_nanos) + now_nanos += DT_CTRL * 1e9 # 10ms + + # Test controller initialization + # TODO: wait until card refactor is merged to run controller a few times, + # hypothesis also slows down significantly with just one more message draw + LongControl(car_params) + if car_params.steerControlType == CarParams.SteerControlType.angle: + LatControlAngle(car_params, car_interface) + elif car_params.lateralTuning.which() == 'pid': + LatControlPID(car_params, car_interface) + elif car_params.lateralTuning.which() == 'torque': + LatControlTorque(car_params, car_interface) diff --git a/selfdrive/car/tests/test_cruise_speed.py b/selfdrive/car/tests/test_cruise_speed.py new file mode 100644 index 0000000000..aa70e49f5d --- /dev/null +++ b/selfdrive/car/tests/test_cruise_speed.py @@ -0,0 +1,151 @@ +import pytest +import itertools +import numpy as np + +from parameterized import parameterized_class +from cereal import log +from openpilot.selfdrive.car.cruise import VCruiseHelper, V_CRUISE_MIN, V_CRUISE_MAX, V_CRUISE_INITIAL, IMPERIAL_INCREMENT +from cereal import car +from openpilot.common.constants import CV +from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver + +ButtonEvent = car.CarState.ButtonEvent +ButtonType = car.CarState.ButtonEvent.Type + + +def run_cruise_simulation(cruise, e2e, personality, t_end=20.): + man = Maneuver( + '', + duration=t_end, + initial_speed=max(cruise - 1., 0.0), + lead_relevancy=True, + initial_distance_lead=100, + cruise_values=[cruise], + prob_lead_values=[0.0], + breakpoints=[0.], + e2e=e2e, + personality=personality, + ) + valid, output = man.evaluate() + assert valid + return output[-1, 3] + + +@parameterized_class(("e2e", "personality", "speed"), itertools.product( + [True, False], # e2e + log.LongitudinalPersonality.schema.enumerants, # personality + [5,35])) # speed +class TestCruiseSpeed: + def test_cruise_speed(self): + print(f'Testing {self.speed} m/s') + cruise_speed = float(self.speed) + + simulation_steady_state = run_cruise_simulation(cruise_speed, self.e2e, self.personality) + assert simulation_steady_state == pytest.approx(cruise_speed, abs=.01), f'Did not reach {self.speed} m/s' + + +# TODO: test pcmCruise +@parameterized_class(('pcm_cruise',), [(False,)]) +class TestVCruiseHelper: + def setup_method(self): + self.CP = car.CarParams(pcmCruise=self.pcm_cruise) + self.v_cruise_helper = VCruiseHelper(self.CP) + self.reset_cruise_speed_state() + + def reset_cruise_speed_state(self): + # Two resets previous cruise speed + for _ in range(2): + self.v_cruise_helper.update_v_cruise(car.CarState(cruiseState={"available": False}), enabled=False, is_metric=False) + + def enable(self, v_ego, experimental_mode): + # Simulates user pressing set with a current speed + self.v_cruise_helper.initialize_v_cruise(car.CarState(vEgo=v_ego), experimental_mode) + + def test_adjust_speed(self): + """ + Asserts speed changes on falling edges of buttons. + """ + + self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False) + + for btn in (ButtonType.accelCruise, ButtonType.decelCruise): + for pressed in (True, False): + CS = car.CarState(cruiseState={"available": True}) + CS.buttonEvents = [ButtonEvent(type=btn, pressed=pressed)] + + self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=False) + assert pressed == (self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last) + + def test_rising_edge_enable(self): + """ + Some car interfaces may enable on rising edge of a button, + ensure we don't adjust speed if enabled changes mid-press. + """ + + # NOTE: enabled is always one frame behind the result from button press in controlsd + for enabled, pressed in ((False, False), + (False, True), + (True, False)): + CS = car.CarState(cruiseState={"available": True}) + CS.buttonEvents = [ButtonEvent(type=ButtonType.decelCruise, pressed=pressed)] + self.v_cruise_helper.update_v_cruise(CS, enabled=enabled, is_metric=False) + if pressed: + self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False) + + # Expected diff on enabling. Speed should not change on falling edge of pressed + assert not pressed == self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last + + def test_resume_in_standstill(self): + """ + Asserts we don't increment set speed if user presses resume/accel to exit cruise standstill. + """ + + self.enable(0, False) + + for standstill in (True, False): + for pressed in (True, False): + CS = car.CarState(cruiseState={"available": True, "standstill": standstill}) + CS.buttonEvents = [ButtonEvent(type=ButtonType.accelCruise, pressed=pressed)] + self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=False) + + # speed should only update if not at standstill and button falling edge + should_equal = standstill or pressed + assert should_equal == (self.v_cruise_helper.v_cruise_kph == self.v_cruise_helper.v_cruise_kph_last) + + def test_set_gas_pressed(self): + """ + Asserts pressing set while enabled with gas pressed sets + the speed to the maximum of vEgo and current cruise speed. + """ + + for v_ego in np.linspace(0, 100, 101): + self.reset_cruise_speed_state() + self.enable(V_CRUISE_INITIAL * CV.KPH_TO_MS, False) + + # first decrement speed, then perform gas pressed logic + expected_v_cruise_kph = self.v_cruise_helper.v_cruise_kph - IMPERIAL_INCREMENT + expected_v_cruise_kph = max(expected_v_cruise_kph, v_ego * CV.MS_TO_KPH) # clip to min of vEgo + expected_v_cruise_kph = float(np.clip(round(expected_v_cruise_kph, 1), V_CRUISE_MIN, V_CRUISE_MAX)) + + CS = car.CarState(vEgo=float(v_ego), gasPressed=True, cruiseState={"available": True}) + CS.buttonEvents = [ButtonEvent(type=ButtonType.decelCruise, pressed=False)] + self.v_cruise_helper.update_v_cruise(CS, enabled=True, is_metric=False) + + # TODO: fix skipping first run due to enabled on rising edge exception + if v_ego == 0.0: + continue + assert expected_v_cruise_kph == self.v_cruise_helper.v_cruise_kph + + def test_initialize_v_cruise(self): + """ + Asserts allowed cruise speeds on enabling with SET. + """ + + for experimental_mode in (True, False): + for v_ego in np.linspace(0, 100, 101): + self.reset_cruise_speed_state() + assert not self.v_cruise_helper.v_cruise_initialized + + self.enable(float(v_ego), experimental_mode) + assert V_CRUISE_INITIAL <= self.v_cruise_helper.v_cruise_kph <= V_CRUISE_MAX + assert self.v_cruise_helper.v_cruise_initialized diff --git a/selfdrive/car/tests/test_docs.py b/selfdrive/car/tests/test_docs.py new file mode 100644 index 0000000000..6e13d55b29 --- /dev/null +++ b/selfdrive/car/tests/test_docs.py @@ -0,0 +1,22 @@ +import os + +from openpilot.common.basedir import BASEDIR +from opendbc.car.docs import generate_cars_md, get_all_car_docs +from openpilot.selfdrive.debug.dump_car_docs import dump_car_docs +from openpilot.selfdrive.debug.print_docs_diff import print_car_docs_diff +from openpilot.selfdrive.car.docs import CARS_MD_TEMPLATE + + +class TestCarDocs: + @classmethod + def setup_class(cls): + cls.all_cars = get_all_car_docs() + + def test_generator(self): + generate_cars_md(self.all_cars, CARS_MD_TEMPLATE) + + def test_docs_diff(self): + dump_path = os.path.join(BASEDIR, "selfdrive", "car", "tests", "cars_dump") + dump_car_docs(dump_path) + print_car_docs_diff(dump_path) + os.remove(dump_path) diff --git a/selfdrive/car/tests/test_models.py b/selfdrive/car/tests/test_models.py new file mode 100644 index 0000000000..8996ad6460 --- /dev/null +++ b/selfdrive/car/tests/test_models.py @@ -0,0 +1,475 @@ +import time +import os +import pytest +import random +import unittest # noqa: TID251 +from collections import defaultdict, Counter +import hypothesis.strategies as st +from hypothesis import Phase, given, settings +from parameterized import parameterized_class + +from opendbc.car import DT_CTRL, gen_empty_fingerprint, structs +from opendbc.car.can_definitions import CanData +from opendbc.car.car_helpers import FRAME_FINGERPRINT, interfaces +from opendbc.car.fingerprints import MIGRATION +from opendbc.car.honda.values import CAR as HONDA, HondaFlags +from opendbc.car.structs import car +from opendbc.car.tests.routes import non_tested_cars, routes, CarTestRoute +from opendbc.car.values import Platform, PLATFORMS +from opendbc.safety.tests.libsafety import libsafety_py +from openpilot.common.basedir import BASEDIR +from openpilot.selfdrive.pandad import can_capnp_to_list +from openpilot.selfdrive.test.helpers import read_segment_list +from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT +from openpilot.tools.lib.logreader import LogReader, LogsUnavailable, openpilotci_source, internal_source, comma_api_source +from openpilot.tools.lib.route import SegmentName + +SafetyModel = car.CarParams.SafetyModel +SteerControlType = structs.CarParams.SteerControlType + +NUM_JOBS = int(os.environ.get("NUM_JOBS", "1")) +JOB_ID = int(os.environ.get("JOB_ID", "0")) +INTERNAL_SEG_LIST = os.environ.get("INTERNAL_SEG_LIST", "") +INTERNAL_SEG_CNT = int(os.environ.get("INTERNAL_SEG_CNT", "0")) +MAX_EXAMPLES = int(os.environ.get("MAX_EXAMPLES", "300")) +CI = os.environ.get("CI", None) is not None + + +def get_test_cases() -> list[tuple[str, CarTestRoute | None]]: + # build list of test cases + test_cases = [] + if not len(INTERNAL_SEG_LIST): + routes_by_car = defaultdict(set) + for r in routes: + routes_by_car[str(r.car_model)].add(r) + + for i, c in enumerate(sorted(PLATFORMS)): + if i % NUM_JOBS == JOB_ID: + test_cases.extend(sorted((c, r) for r in routes_by_car.get(c, (None,)))) + + else: + segment_list = read_segment_list(os.path.join(BASEDIR, INTERNAL_SEG_LIST)) + segment_list = random.sample(segment_list, INTERNAL_SEG_CNT or len(segment_list)) + for platform, segment in segment_list: + platform = MIGRATION.get(platform, platform) + segment_name = SegmentName(segment) + test_cases.append((platform, CarTestRoute(segment_name.route_name.canonical_name, platform, + segment=segment_name.segment_num))) + return test_cases + + +@pytest.mark.slow +@pytest.mark.shared_download_cache +class TestCarModelBase(unittest.TestCase): + platform: Platform | None = None + test_route: CarTestRoute | None = None + + can_msgs: list[tuple[int, list[CanData]]] + fingerprint: dict[int, dict[int, int]] + elm_frame: int | None + car_safety_mode_frame: int | None + + @classmethod + def get_testing_data_from_logreader(cls, lr): + car_fw = [] + can_msgs = [] + cls.elm_frame = None + cls.car_safety_mode_frame = None + cls.fingerprint = gen_empty_fingerprint() + alpha_long = False + for msg in lr: + if msg.which() == "can": + can = can_capnp_to_list((msg.as_builder().to_bytes(),))[0] + can_msgs.append((can[0], [CanData(*can) for can in can[1]])) + if len(can_msgs) <= FRAME_FINGERPRINT: + for m in msg.can: + if m.src < 64: + cls.fingerprint[m.src][m.address] = len(m.dat) + + elif msg.which() == "carParams": + car_fw = msg.carParams.carFw + if msg.carParams.openpilotLongitudinalControl: + alpha_long = True + if cls.platform is None: + live_fingerprint = msg.carParams.carFingerprint + cls.platform = MIGRATION.get(live_fingerprint, live_fingerprint) + + # Log which can frame the panda safety mode left ELM327, for CAN validity checks + elif msg.which() == 'pandaStates': + for ps in msg.pandaStates: + if cls.elm_frame is None and ps.safetyModel != SafetyModel.elm327: + cls.elm_frame = len(can_msgs) + if cls.car_safety_mode_frame is None and ps.safetyModel not in \ + (SafetyModel.elm327, SafetyModel.noOutput): + cls.car_safety_mode_frame = len(can_msgs) + + elif msg.which() == 'pandaStateDEPRECATED': + if cls.elm_frame is None and msg.pandaStateDEPRECATED.safetyModel != SafetyModel.elm327: + cls.elm_frame = len(can_msgs) + if cls.car_safety_mode_frame is None and msg.pandaStateDEPRECATED.safetyModel not in \ + (SafetyModel.elm327, SafetyModel.noOutput): + cls.car_safety_mode_frame = len(can_msgs) + + assert len(can_msgs) > int(50 / DT_CTRL), "no can data found" + return car_fw, can_msgs, alpha_long + + @classmethod + def get_testing_data(cls): + test_segs = (2, 1, 0) + if cls.test_route.segment is not None: + test_segs = (cls.test_route.segment,) + + for seg in test_segs: + segment_range = f"{cls.test_route.route}/{seg}" + + try: + sources = [internal_source] if len(INTERNAL_SEG_LIST) else [openpilotci_source, comma_api_source] + lr = LogReader(segment_range, sources=sources, sort_by_time=True) + return cls.get_testing_data_from_logreader(lr) + except (LogsUnavailable, AssertionError): + pass + + raise Exception(f"Route: {repr(cls.test_route.route)} with segments: {test_segs} not found or no CAN msgs found. Is it uploaded and public?") + + + @classmethod + def setUpClass(cls): + if cls.__name__ == 'TestCarModel' or cls.__name__.endswith('Base'): + raise unittest.SkipTest + + if cls.test_route is None: + if cls.platform in non_tested_cars: + print(f"Skipping tests for {cls.platform}: missing route") + raise unittest.SkipTest + raise Exception(f"missing test route for {cls.platform}") + + car_fw, cls.can_msgs, alpha_long = cls.get_testing_data() + + # if relay is expected to be open in the route + cls.openpilot_enabled = cls.car_safety_mode_frame is not None + + cls.CarInterface = interfaces[cls.platform] + cls.CP = cls.CarInterface.get_params(cls.platform, cls.fingerprint, car_fw, alpha_long, False, docs=False) + assert cls.CP + assert cls.CP.carFingerprint == cls.platform + + os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT + + @classmethod + def tearDownClass(cls): + del cls.can_msgs + + def setUp(self): + self.CI = self.CarInterface(self.CP.copy()) + assert self.CI + + # TODO: check safetyModel is in release panda build + self.safety = libsafety_py.libsafety + + cfg = self.CP.safetyConfigs[-1] + set_status = self.safety.set_safety_hooks(cfg.safetyModel.raw, cfg.safetyParam) + self.assertEqual(0, set_status, f"failed to set safetyModel {cfg}") + self.safety.init_tests() + + def test_car_params(self): + if self.CP.dashcamOnly: + self.skipTest("no need to check carParams for dashcamOnly") + + # make sure car params are within a valid range + self.assertGreater(self.CP.mass, 1) + + if self.CP.steerControlType != SteerControlType.angle: + tuning = self.CP.lateralTuning.which() + if tuning == 'pid': + self.assertTrue(len(self.CP.lateralTuning.pid.kpV)) + elif tuning == 'torque': + self.assertTrue(self.CP.lateralTuning.torque.kf > 0) + else: + raise Exception("unknown tuning") + + def test_car_interface(self): + # TODO: also check for checksum violations from can parser + can_invalid_cnt = 0 + CC = structs.CarControl().as_reader() + + for i, msg in enumerate(self.can_msgs): + CS = self.CI.update(msg) + self.CI.apply(CC, msg[0]) + + # wait max of 2s for low frequency msgs to be seen + if i > 250: + can_invalid_cnt += not CS.canValid + + self.assertEqual(can_invalid_cnt, 0) + + def test_radar_interface(self): + RI = self.CarInterface.RadarInterface(self.CP) + assert RI + + # Since OBD port is multiplexed to bus 1 (commonly radar bus) while fingerprinting, + # start parsing CAN messages after we've left ELM mode and can expect CAN traffic + error_cnt = 0 + for i, msg in enumerate(self.can_msgs[self.elm_frame:]): + rr: structs.RadarData | None = RI.update(msg) + if rr is not None and i > 50: + error_cnt += rr.errors.canError + self.assertEqual(error_cnt, 0) + + def test_panda_safety_rx_checks(self): + if self.CP.dashcamOnly: + self.skipTest("no need to check panda safety for dashcamOnly") + + start_ts = self.can_msgs[0][0] + + failed_addrs = Counter() + for can in self.can_msgs: + # update panda timer + t = (can[0] - start_ts) / 1e3 + self.safety.set_timer(int(t)) + + # run all msgs through the safety RX hook + for msg in can[1]: + if msg.src >= 64: + continue + + to_send = libsafety_py.make_CANPacket(msg.address, msg.src % 4, msg.dat) + if self.safety.safety_rx_hook(to_send) != 1: + failed_addrs[hex(msg.address)] += 1 + + # ensure all msgs defined in the addr checks are valid + self.safety.safety_tick_current_safety_config() + if t > 1e6: + self.assertTrue(self.safety.safety_config_valid()) + + # Don't check relay malfunction on disabled routes (relay closed), + # or before fingerprinting is done (elm327 and noOutput) + if self.openpilot_enabled and t / 1e4 > self.car_safety_mode_frame: + self.assertFalse(self.safety.get_relay_malfunction()) + else: + self.safety.set_relay_malfunction(False) + + self.assertFalse(len(failed_addrs), f"panda safety RX check failed: {failed_addrs}") + + # ensure RX checks go invalid after small time with no traffic + self.safety.set_timer(int(t + (2*1e6))) + self.safety.safety_tick_current_safety_config() + self.assertFalse(self.safety.safety_config_valid()) + + def test_panda_safety_tx_cases(self, data=None): + """Asserts we can tx common messages""" + if self.CP.dashcamOnly: + self.skipTest("no need to check panda safety for dashcamOnly") + + if self.CP.notCar: + self.skipTest("Skipping test for notCar") + + def test_car_controller(car_control): + now_nanos = 0 + msgs_sent = 0 + CI = self.CarInterface(self.CP) + for _ in range(round(10.0 / DT_CTRL)): # make sure we hit the slowest messages + CI.update([]) + _, sendcan = CI.apply(car_control, now_nanos) + + now_nanos += DT_CTRL * 1e9 + msgs_sent += len(sendcan) + for addr, dat, bus in sendcan: + to_send = libsafety_py.make_CANPacket(addr, bus % 4, dat) + self.assertTrue(self.safety.safety_tx_hook(to_send), (addr, dat, bus)) + + # Make sure we attempted to send messages + self.assertGreater(msgs_sent, 50) + + # Make sure we can send all messages while inactive + CC = structs.CarControl() + test_car_controller(CC.as_reader()) + + # Test cancel + general messages (controls_allowed=False & cruise_engaged=True) + self.safety.set_cruise_engaged_prev(True) + CC = structs.CarControl(cruiseControl=structs.CarControl.CruiseControl(cancel=True)) + test_car_controller(CC.as_reader()) + + # Test resume + general messages (controls_allowed=True & cruise_engaged=True) + self.safety.set_controls_allowed(True) + CC = structs.CarControl(cruiseControl=structs.CarControl.CruiseControl(resume=True)) + test_car_controller(CC.as_reader()) + + # Skip stdout/stderr capture with pytest, causes elevated memory usage + @pytest.mark.nocapture + @settings(max_examples=MAX_EXAMPLES, deadline=None, + phases=(Phase.reuse, Phase.generate, Phase.shrink)) + @given(data=st.data()) + def test_panda_safety_carstate_fuzzy(self, data): + """ + For each example, pick a random CAN message on the bus and fuzz its data, + checking for panda state mismatches. + """ + + if self.CP.dashcamOnly: + self.skipTest("no need to check panda safety for dashcamOnly") + + valid_addrs = [(addr, bus, size) for bus, addrs in self.fingerprint.items() for addr, size in addrs.items()] + address, bus, size = data.draw(st.sampled_from(valid_addrs)) + + msg_strategy = st.binary(min_size=size, max_size=size) + msgs = data.draw(st.lists(msg_strategy, min_size=20)) + + vehicle_speed_seen = self.CP.steerControlType == SteerControlType.angle and not self.CP.notCar + + for n, dat in enumerate(msgs): + # due to panda updating state selectively, only edges are expected to match + # TODO: warm up CarState with real CAN messages to check edge of both sources + # (eg. toyota's gasPressed is the inverse of a signal being set) + prev_panda_gas = self.safety.get_gas_pressed_prev() + prev_panda_brake = self.safety.get_brake_pressed_prev() + prev_panda_regen_braking = self.safety.get_regen_braking_prev() + prev_panda_steering_disengage = self.safety.get_steering_disengage_prev() + prev_panda_vehicle_moving = self.safety.get_vehicle_moving() + prev_panda_vehicle_speed_min = self.safety.get_vehicle_speed_min() + prev_panda_vehicle_speed_max = self.safety.get_vehicle_speed_max() + prev_panda_cruise_engaged = self.safety.get_cruise_engaged_prev() + prev_panda_acc_main_on = self.safety.get_acc_main_on() + + to_send = libsafety_py.make_CANPacket(address, bus, dat) + self.safety.safety_rx_hook(to_send) + + can = [(int(time.monotonic() * 1e9), [CanData(address=address, dat=dat, src=bus)])] + CS = self.CI.update(can) + if n < 5: # CANParser warmup time + continue + + if self.safety.get_gas_pressed_prev() != prev_panda_gas: + self.assertEqual(CS.gasPressed, self.safety.get_gas_pressed_prev()) + + if self.safety.get_brake_pressed_prev() != prev_panda_brake: + # TODO: remove this exception once this mismatch is resolved + brake_pressed = CS.brakePressed + if CS.brakePressed and not self.safety.get_brake_pressed_prev(): + if self.CP.carFingerprint in (HONDA.HONDA_PILOT, HONDA.HONDA_RIDGELINE) and CS.brake > 0.05: + brake_pressed = False + + self.assertEqual(brake_pressed, self.safety.get_brake_pressed_prev()) + + if self.safety.get_regen_braking_prev() != prev_panda_regen_braking: + self.assertEqual(CS.regenBraking, self.safety.get_regen_braking_prev()) + + if self.safety.get_steering_disengage_prev() != prev_panda_steering_disengage: + self.assertEqual(CS.steeringDisengage, self.safety.get_steering_disengage_prev()) + + if self.safety.get_vehicle_moving() != prev_panda_vehicle_moving and not self.CP.notCar: + self.assertEqual(not CS.standstill, self.safety.get_vehicle_moving()) + + # check vehicle speed if angle control car or available + if self.safety.get_vehicle_speed_min() > 0 or self.safety.get_vehicle_speed_max() > 0: + vehicle_speed_seen = True + + if vehicle_speed_seen and (self.safety.get_vehicle_speed_min() != prev_panda_vehicle_speed_min or + self.safety.get_vehicle_speed_max() != prev_panda_vehicle_speed_max): + v_ego_raw = CS.vEgoRaw / self.CP.wheelSpeedFactor + self.assertFalse(v_ego_raw > (self.safety.get_vehicle_speed_max() + 1e-3) or + v_ego_raw < (self.safety.get_vehicle_speed_min() - 1e-3)) + + if not (self.CP.brand == "honda" and not (self.CP.flags & HondaFlags.BOSCH)): + if self.safety.get_cruise_engaged_prev() != prev_panda_cruise_engaged: + self.assertEqual(CS.cruiseState.enabled, self.safety.get_cruise_engaged_prev()) + + if self.CP.brand == "honda": + if self.safety.get_acc_main_on() != prev_panda_acc_main_on: + self.assertEqual(CS.cruiseState.available, self.safety.get_acc_main_on()) + + def test_panda_safety_carstate(self): + """ + Assert that panda safety matches openpilot's carState + """ + if self.CP.dashcamOnly: + self.skipTest("no need to check panda safety for dashcamOnly") + + # warm up pass, as initial states may be different + for can in self.can_msgs[:300]: + self.CI.update(can) + for msg in filter(lambda m: m.src < 64, can[1]): + to_send = libsafety_py.make_CANPacket(msg.address, msg.src % 4, msg.dat) + self.safety.safety_rx_hook(to_send) + + controls_allowed_prev = False + CS_prev = car.CarState.new_message() + checks = defaultdict(int) + vehicle_speed_seen = self.CP.steerControlType == SteerControlType.angle and not self.CP.notCar + for idx, can in enumerate(self.can_msgs): + CS = self.CI.update(can).as_reader() + for msg in filter(lambda m: m.src < 64, can[1]): + to_send = libsafety_py.make_CANPacket(msg.address, msg.src % 4, msg.dat) + ret = self.safety.safety_rx_hook(to_send) + self.assertEqual(1, ret, f"safety rx failed ({ret=}): {(msg.address, msg.src % 4)}") + + # Skip first frame so CS_prev is properly initialized + if idx == 0: + CS_prev = CS + # Button may be left pressed in warm up period + if not self.CP.pcmCruise: + self.safety.set_controls_allowed(0) + continue + + # TODO: check rest of panda's carstate (steering, ACC main on, etc.) + + checks['gasPressed'] += CS.gasPressed != self.safety.get_gas_pressed_prev() + checks['standstill'] += (CS.standstill == self.safety.get_vehicle_moving()) and not self.CP.notCar + + # check vehicle speed if angle control car or available + if self.safety.get_vehicle_speed_min() > 0 or self.safety.get_vehicle_speed_max() > 0: + vehicle_speed_seen = True + + if vehicle_speed_seen: + v_ego_raw = CS.vEgoRaw / self.CP.wheelSpeedFactor + checks['vEgoRaw'] += (v_ego_raw > (self.safety.get_vehicle_speed_max() + 1e-3) or + v_ego_raw < (self.safety.get_vehicle_speed_min() - 1e-3)) + + # TODO: remove this exception once this mismatch is resolved + brake_pressed = CS.brakePressed + if CS.brakePressed and not self.safety.get_brake_pressed_prev(): + if self.CP.carFingerprint in (HONDA.HONDA_PILOT, HONDA.HONDA_RIDGELINE) and CS.brake > 0.05: + brake_pressed = False + checks['brakePressed'] += brake_pressed != self.safety.get_brake_pressed_prev() + checks['regenBraking'] += CS.regenBraking != self.safety.get_regen_braking_prev() + checks['steeringDisengage'] += CS.steeringDisengage != self.safety.get_steering_disengage_prev() + + if self.CP.pcmCruise: + # On most pcmCruise cars, openpilot's state is always tied to the PCM's cruise state. + # On Honda Nidec, we always engage on the rising edge of the PCM cruise state, but + # openpilot brakes to zero even if the min ACC speed is non-zero (i.e. the PCM disengages). + if self.CP.brand == "honda" and not (self.CP.flags & HondaFlags.BOSCH): + # only the rising edges are expected to match + if CS.cruiseState.enabled and not CS_prev.cruiseState.enabled: + checks['controlsAllowed'] += not self.safety.get_controls_allowed() + else: + checks['controlsAllowed'] += not CS.cruiseState.enabled and self.safety.get_controls_allowed() + + # TODO: fix notCar mismatch + if not self.CP.notCar: + checks['cruiseState'] += CS.cruiseState.enabled != self.safety.get_cruise_engaged_prev() + else: + # Check for user button enable on rising edge of controls allowed + button_enable = CS.buttonEnable and (not CS.brakePressed or CS.standstill) + mismatch = button_enable != (self.safety.get_controls_allowed() and not controls_allowed_prev) + checks['controlsAllowed'] += mismatch + controls_allowed_prev = self.safety.get_controls_allowed() + if button_enable and not mismatch: + self.safety.set_controls_allowed(False) + + if self.CP.brand == "honda": + checks['mainOn'] += CS.cruiseState.available != self.safety.get_acc_main_on() + + CS_prev = CS + + failed_checks = {k: v for k, v in checks.items() if v > 0} + self.assertFalse(len(failed_checks), f"panda safety doesn't agree with openpilot: {failed_checks}") + + +@parameterized_class(('platform', 'test_route'), get_test_cases()) +@pytest.mark.xdist_group_class_property('test_route') +class TestCarModel(TestCarModelBase): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/selfdrive/car/tests/test_models_segs.txt b/selfdrive/car/tests/test_models_segs.txt new file mode 100644 index 0000000000..d805ce7d83 --- /dev/null +++ b/selfdrive/car/tests/test_models_segs.txt @@ -0,0 +1,3884 @@ +# HONDA ODYSSEY 2018 +0ffff9faf2699ebc|2023-06-15--14-19-40--3 +# HONDA ODYSSEY 2018 +0c21c391abd382af|2023-07-17--19-49-46--12 +# HONDA ODYSSEY 2018 +0c23034a3a1e7bf4|2023-07-22--12-15-36--37 +# HONDA ODYSSEY 2018 +1b83b62ce1e15374|2023-07-24--16-56-02--166 +# HONDA ODYSSEY 2018 +0494ab1688baf0d1|2023-07-12--12-59-45--18 +# HONDA ODYSSEY 2018 +10702b68bb2db4f7|2023-07-12--09-09-08--24 +# HONDA ODYSSEY 2018 +349a10da75da84b3|2023-07-12--05-20-10--17 +# HONDA ODYSSEY 2018 +3eb25233bf8777b2|2023-08-03--12-55-23--19 +# HONDA ODYSSEY 2018 +4480efadd4e5e9b0|2023-07-31--18-14-01--20 +# HONDA ODYSSEY 2018 +568f8a1ce998fe8c|2023-05-15--18-09-35--3 +# HONDA ODYSSEY 2018 +564e1c4005971631|2023-07-15--21-26-58--9 +# HONDA ODYSSEY 2018 +5a28fb7518234651|2023-07-16--10-05-04--20 +# HONDA ODYSSEY 2018 +5de06f504727ef4e|2023-05-16--13-44-26--76 +# HONDA ODYSSEY 2018 +6da2ceb7bf6a818c|2023-05-24--16-27-24--38 +# HONDA ODYSSEY 2018 +6d3b5e3ce824a6be|2023-07-21--09-19-25--2 +# HONDA ODYSSEY 2018 +7074dfeeffbb7f3b|2023-08-07--08-42-57--3 +# HONDA ODYSSEY 2018 +761e1503448b32d5|2023-07-04--15-25-15--9 +# HONDA ODYSSEY 2018 +76b6bcf9925e9293|2023-07-15--10-36-05--31 +# HONDA ODYSSEY 2018 +7a7eba6f9ce36254|2023-07-16--16-28-27--7 +# HONDA ODYSSEY 2018 +772b833c28f493b5|2023-06-04--10-39-28--23 +# HONDA ODYSSEY 2018 +8906faebfc695953|2023-07-01--10-35-06--1 +# HONDA ODYSSEY 2018 +89ae461c07c586a3|2023-07-21--12-55-44--4 +# HONDA ODYSSEY 2018 +8eb3d1f10274ac44|2023-05-10--05-26-26--28 +# HONDA ODYSSEY 2018 +9954025f3a2aec2d|2023-06-16--14-15-08--2 +# HONDA ODYSSEY 2018 +a3636d74d9353700|2023-08-05--11-59-10--56 +# HONDA ODYSSEY 2018 +a27fe4e91d6e73c8|2023-05-31--20-34-59--2 +# HONDA ODYSSEY 2018 +aa7176d108cb2f97|2023-05-17--11-01-55--1 +# HONDA ODYSSEY 2018 +b288b21f47092c68|2023-06-23--21-09-10--7 +# HONDA ODYSSEY 2018 +b95acf45b72e104d|2023-07-10--08-01-29--11 +# HONDA ODYSSEY 2018 +b83fc39362bdde40|2023-05-15--09-42-06--9 +# HONDA ODYSSEY 2018 +bdc4ffbeb0ae5239|2023-05-11--17-52-21--3 +# HONDA ODYSSEY 2018 +c57d8a1adaecd30e|2023-07-09--21-29-19--70 +# HONDA ODYSSEY 2018 +c7fa6fb6f4d42407|2023-07-30--21-31-47--3 +# HONDA ODYSSEY 2018 +d0d197a10408c839|2023-05-13--16-17-45--67 +# HONDA ODYSSEY 2018 +e1aa4eae17f7b626|2023-06-06--16-12-33--1 +# HONDA ODYSSEY 2018 +e462034ac9e0c71d|2023-07-28--16-31-10--37 +# HONDA ODYSSEY 2018 +e67fa35fcc6db9d5|2023-07-22--17-19-19--28 +# HONDA ODYSSEY 2018 +f30eee173ffa893d|2023-05-16--19-43-43--31 +# HONDA ODYSSEY 2018 +f77dffd74248543d|2023-06-05--21-15-01--39 +# HONDA ODYSSEY 2018 +fa0bfc645891d426|2023-06-19--15-41-01--10 +# SUBARU FORESTER 2019 +1589151a309c433c|2023-05-24--17-23-34--51 +# SUBARU FORESTER 2019 +2caa16bfdc10557f|2023-07-17--06-33-02--17 +# SUBARU FORESTER 2019 +382f4ac8109f707f|2023-06-02--17-38-42--2 +# SUBARU FORESTER 2019 +8fc4e96c0d82e152|2023-08-03--07-28-17--6 +# SUBARU FORESTER 2019 +9227902ca7eb7bba|2023-07-31--13-51-49--118 +# SUBARU FORESTER 2019 +9a3079fb5c491ea5|2023-07-24--06-10-15--22 +# SUBARU FORESTER 2019 +a447729c1d15ff89|2023-07-31--06-59-17--2 +# SUBARU FORESTER 2019 +a752a19628873b10|2023-06-23--06-07-53--7 +# SUBARU FORESTER 2019 +ace607260543d257|2023-06-25--16-30-06--38 +# SUBARU FORESTER 2019 +fe3d890194b380ae|2023-06-01--19-39-37--120 +# TOYOTA RAV4 2019 +2308c55920b6c000|2023-07-01--18-34-43--21 +# TOYOTA RAV4 2019 +23562c9692a54321|2023-06-26--20-58-17--5 +# TOYOTA RAV4 2019 +1df2464a11c3caa7|2023-07-27--11-55-45--2 +# TOYOTA RAV4 2019 +1da6142d55922568|2023-05-21--19-08-27--17 +# TOYOTA RAV4 2019 +1930f57e827a5277|2023-06-18--09-30-23--7 +# TOYOTA RAV4 2019 +1c05783affe6641f|2023-05-28--09-51-01--28 +# TOYOTA RAV4 2019 +12913b66ea1ba32c|2023-08-02--12-35-55--14 +# TOYOTA RAV4 2019 +17e30e35ce70aa27|2023-06-12--05-53-27--13 +# TOYOTA RAV4 2019 +0559b34634b98e40|2023-05-26--19-07-54--10 +# TOYOTA RAV4 2019 +1523b70b49465492|2023-07-07--15-35-52--26 +# TOYOTA RAV4 2019 +131b0198e811cbaf|2023-05-10--19-45-30--1 +# TOYOTA RAV4 2019 +1aa9f62e2da571ae|2023-06-06--16-15-53--12 +# TOYOTA RAV4 2019 +06c6a866f247ccd3|2023-07-11--17-20-33--1 +# TOYOTA RAV4 2019 +1ca69541b8d83867|2023-07-18--13-20-11--63 +# TOYOTA RAV4 2019 +1c063541db21a08a|2023-05-18--20-01-46--158 +# TOYOTA RAV4 2019 +222b4aa34efc150b|2023-07-06--07-11-01--18 +# TOYOTA RAV4 2019 +25c96345c4ae0f5f|2023-05-28--13-48-48--44 +# TOYOTA RAV4 2019 +183ed80ffd5de6df|2023-05-19--09-54-02--108 +# TOYOTA RAV4 2019 +0835a20d4c688b4b|2023-05-21--21-06-46--101 +# TOYOTA RAV4 2019 +294c4257370dcd7f|2023-07-16--22-03-45--55 +# TOYOTA RAV4 2019 +013d89e3119a61fa|2023-07-27--19-28-55--1 +# TOYOTA RAV4 2019 +0111bbc17b5fc829|2023-07-22--15-33-17--3 +# TOYOTA RAV4 2019 +27fbf8f57ad1ed35|2023-07-25--03-04-13--5 +# TOYOTA RAV4 2019 +11e905ad4a26f7cf|2023-07-19--17-16-34--2 +# TOYOTA RAV4 2019 +076e5dea58433d1b|2023-05-30--14-28-07--99 +# TOYOTA RAV4 2019 +2d76c29b8aa236f4|2023-05-10--20-14-29--5 +# TOYOTA RAV4 2019 +31a0911d03035419|2023-06-11--16-24-31--3 +# TOYOTA RAV4 2019 +33c48660a967984c|2023-07-15--12-09-46--27 +# TOYOTA RAV4 2019 +334cffe17908547f|2023-07-05--19-08-58--175 +# TOYOTA RAV4 2019 +3550e1127d042e0c|2023-05-20--07-41-42--17 +# TOYOTA RAV4 2019 +3d77767f8c063017|2023-07-26--08-07-41--3 +# TOYOTA RAV4 2019 +3ecc8a00642fb457|2023-07-07--15-00-35--1 +# TOYOTA RAV4 2019 +4031a71d2f2bbf41|2023-06-24--21-44-33--19 +# TOYOTA RAV4 2019 +3dc04fa00e9b54d4|2023-07-10--20-45-54--20 +# TOYOTA RAV4 2019 +41f0e37bcb089214|2023-05-15--16-06-13--7 +# TOYOTA RAV4 2019 +4501ab837e09a1c6|2023-07-29--10-06-44--27 +# TOYOTA RAV4 2019 +430cfb7ed591a94b|2023-05-11--09-51-06--4 +# TOYOTA RAV4 2019 +43d464c559ee7b80|2023-08-02--09-27-58--26 +# TOYOTA RAV4 2019 +45bd1475c3f373bf|2023-07-17--07-09-41--42 +# TOYOTA RAV4 2019 +4d059401f47cf0b3|2023-05-13--12-01-17--9 +# TOYOTA RAV4 2019 +59e0e393764bc46b|2023-07-02--13-33-24--40 +# TOYOTA RAV4 2019 +595291c68fb8e6ea|2023-06-08--09-48-19--28 +# TOYOTA RAV4 2019 +5a62b93c7f9af2c9|2023-06-14--20-12-16--5 +# TOYOTA RAV4 2019 +5a9c05e4b4e221ba|2023-06-30--07-08-38--33 +# TOYOTA RAV4 2019 +5ac3d4195844832a|2023-05-11--08-10-51--15 +# TOYOTA RAV4 2019 +5ce8412c1359aee9|2023-06-04--01-23-21--11 +# TOYOTA RAV4 2019 +628fd36bec15e0fb|2023-06-27--07-40-01--6 +# TOYOTA RAV4 2019 +66ec82e487f41877|2023-06-08--07-57-18--2 +# TOYOTA RAV4 2019 +643e2c33f76301ed|2023-07-13--11-28-53--1 +# TOYOTA RAV4 2019 +734696450d800618|2023-08-04--23-17-18--8 +# TOYOTA RAV4 2019 +7ca260f9516f6b11|2023-05-28--11-43-26--193 +# TOYOTA RAV4 2019 +80c09a7a12eeea03|2023-05-27--12-27-44--10 +# TOYOTA RAV4 2019 +81ef68582345921f|2023-06-18--14-19-57--13 +# TOYOTA RAV4 2019 +7a6d59eb02cb9e4f|2023-08-04--07-49-50--2 +# TOYOTA RAV4 2019 +87d791b5f816cb1a|2023-07-17--12-47-30--6 +# TOYOTA RAV4 2019 +850119b3a36f6308|2023-05-28--16-46-06--10 +# TOYOTA RAV4 2019 +8a111c9611f505e8|2023-05-14--17-09-37--3 +# TOYOTA RAV4 2019 +8a7d3987605d80d7|2023-07-11--22-11-11--98 +# TOYOTA RAV4 2019 +904ef86637af3549|2023-06-29--21-07-54--12 +# TOYOTA RAV4 2019 +8bb58ef0f2d612b7|2023-07-24--05-57-12--18 +# TOYOTA RAV4 2019 +9145fe2119f27d86|2023-05-31--08-42-48--13 +# TOYOTA RAV4 2019 +9508cd0cab46a905|2023-06-14--16-43-42--10 +# TOYOTA RAV4 2019 +95768af0ae83525e|2023-07-21--15-19-36--83 +# TOYOTA RAV4 2019 +96a8957593166ea1|2023-06-19--12-15-04--6 +# TOYOTA RAV4 2019 +973311a7d6c7d753|2023-06-13--14-17-32--108 +# TOYOTA RAV4 2019 +9c52118646f93f97|2023-07-04--23-02-46--17 +# TOYOTA RAV4 2019 +9cbbc22dbfb7be88|2023-05-30--17-24-35--18 +# TOYOTA RAV4 2019 +9b6a2386fd03ae08|2023-07-13--12-22-52--3 +# TOYOTA RAV4 2019 +9a2bcd25135b821b|2023-07-08--10-55-13--13 +# TOYOTA RAV4 2019 +97799676cedffbe5|2023-06-14--18-24-55--19 +# TOYOTA RAV4 2019 +a08761c412401005|2023-05-23--19-01-36--12 +# TOYOTA RAV4 2019 +a27c12e2a2a70e31|2023-05-16--07-59-59--4 +# TOYOTA RAV4 2019 +9d5333455b91ee89|2023-07-07--19-32-53--2 +# TOYOTA RAV4 2019 +a158f766c4caa342|2023-05-13--12-27-56--97 +# TOYOTA RAV4 2019 +a8e906dda0b7438b|2023-06-08--11-06-31--14 +# TOYOTA RAV4 2019 +a919bd078978c0ab|2023-07-28--07-52-04--11 +# TOYOTA RAV4 2019 +a9aa5c6455c86571|2023-06-20--13-48-37--9 +# TOYOTA RAV4 2019 +ad00cbe5074c4fab|2023-07-26--15-06-11--76 +# TOYOTA RAV4 2019 +a7f1bfccea36b5eb|2023-07-14--15-30-38--5 +# TOYOTA RAV4 2019 +aeeec17f13cb4cef|2023-05-30--13-12-13--23 +# TOYOTA RAV4 2019 +af355970e532a9db|2023-06-11--15-19-23--60 +# TOYOTA RAV4 2019 +b303e820b96a73e9|2023-07-19--13-45-57--11 +# TOYOTA RAV4 2019 +b86cfd7190536fee|2023-06-04--19-32-09--1 +# TOYOTA RAV4 2019 +bc0ebfc25d121b5b|2023-07-08--17-31-57--3 +# TOYOTA RAV4 2019 +b740f7b3cb9bce43|2023-07-17--07-37-05--63 +# TOYOTA RAV4 2019 +c0a876c347ffbbe9|2023-05-11--08-40-32--7 +# TOYOTA RAV4 2019 +c98b94fb47ef8195|2023-07-21--16-10-23--62 +# TOYOTA RAV4 2019 +cea26252c5847413|2023-06-19--21-03-38--21 +# TOYOTA RAV4 2019 +ccc74bf50752879f|2023-06-16--15-04-07--14 +# TOYOTA RAV4 2019 +cd79e21eac267227|2023-05-28--19-05-31--24 +# TOYOTA RAV4 2019 +ce997a6490dec120|2023-05-24--10-21-17--28 +# TOYOTA RAV4 2019 +d3cd2946dfd5c271|2023-07-10--18-33-33--17 +# TOYOTA RAV4 2019 +d66e301c2c7277e1|2023-05-10--19-31-45--2 +# TOYOTA RAV4 2019 +dc49ffbba8a3b9dc|2023-06-08--18-18-49--24 +# TOYOTA RAV4 2019 +dc25f84f7b307cc9|2023-06-17--11-51-25--13 +# TOYOTA RAV4 2019 +df79933372901026|2023-07-06--18-03-06--16 +# TOYOTA RAV4 2019 +e15949cf8f8d7249|2023-07-31--22-54-31--10 +# TOYOTA RAV4 2019 +e1f6a3b4e19955a7|2023-07-09--17-04-05--15 +# TOYOTA RAV4 2019 +e461efc72ee56215|2023-07-01--11-14-35--138 +# TOYOTA RAV4 2019 +e87a90b4e7d2cbf6|2023-05-24--14-38-43--13 +# TOYOTA RAV4 2019 +e4bc15da1e30e125|2023-06-19--14-52-41--2 +# TOYOTA RAV4 2019 +e999ea6601c35fad|2023-06-06--21-56-30--1 +# TOYOTA RAV4 2019 +eb04174d0d305a32|2023-06-14--18-34-40--2 +# TOYOTA RAV4 2019 +e2fac89340529432|2023-05-12--21-16-54--33 +# TOYOTA RAV4 2019 +edb8ec2edf00089e|2023-07-11--14-36-05--31 +# TOYOTA RAV4 2019 +e9a117016fec049d|2023-07-23--10-19-20--2 +# TOYOTA RAV4 2019 +ed70a3fe1c252cfa|2023-07-03--11-18-29--6 +# TOYOTA RAV4 2019 +f0c3362708e50e2d|2023-07-29--17-46-22--5 +# TOYOTA RAV4 2019 +f3384252b57fdfe9|2023-08-08--01-57-06--18 +# TOYOTA RAV4 2019 +ef69d3afc3c6db45|2023-07-04--12-23-05--8 +# TOYOTA RAV4 2019 +f3b7f7fe759fbfee|2023-07-09--18-08-17--1 +# TOYOTA RAV4 2019 +f43f8cf5f35d1c68|2023-05-15--12-02-55--19 +# TOYOTA RAV4 2019 +f9fcd2ad910e89db|2023-08-06--11-26-36--12 +# TOYOTA RAV4 2019 +f7fb88eece6ec686|2023-06-29--13-16-55--8 +# TOYOTA RAV4 2019 +fe70bc78933fe382|2023-06-26--13-08-03--243 +# TOYOTA RAV4 HYBRID 2017 +260738525c081f84|2023-06-07--15-56-35--13 +# TOYOTA RAV4 HYBRID 2017 +0fd770798a15a939|2023-06-29--07-57-15--19 +# TOYOTA RAV4 HYBRID 2017 +054808dce11e7aa0|2023-08-01--18-13-07--8 +# TOYOTA RAV4 HYBRID 2017 +0ae1be4d5f71ec38|2023-05-17--17-16-12--1 +# TOYOTA RAV4 HYBRID 2017 +39e928c1da9fa3d5|2023-06-15--11-58-12--24 +# TOYOTA RAV4 HYBRID 2017 +5c556eaf4a001e29|2023-06-06--08-53-51--17 +# TOYOTA RAV4 HYBRID 2017 +602b5e96b65d4762|2023-07-10--17-55-55--150 +# TOYOTA RAV4 HYBRID 2017 +694d657526334832|2023-06-11--18-18-58--9 +# TOYOTA RAV4 HYBRID 2017 +6967b97d12f377fc|2023-07-29--14-23-52--19 +# TOYOTA RAV4 HYBRID 2017 +731520c68c728363|2023-06-27--19-28-08--5 +# TOYOTA RAV4 HYBRID 2017 +76654637ecd7a147|2023-05-10--20-08-10--59 +# TOYOTA RAV4 HYBRID 2017 +71f1afdb4ec3b211|2023-05-12--09-32-27--15 +# TOYOTA RAV4 HYBRID 2017 +8db44088260c7e81|2023-08-02--19-23-22--5 +# TOYOTA RAV4 HYBRID 2017 +a809df548b49a68b|2023-07-09--18-05-37--9 +# TOYOTA RAV4 HYBRID 2017 +b4069565beef1091|2023-07-12--09-05-40--1 +# TOYOTA RAV4 HYBRID 2017 +c0ca616eaa24d73b|2023-07-21--17-29-37--65 +# TOYOTA RAV4 HYBRID 2017 +d243dcf7caee6052|2023-06-25--17-19-26--1 +# TOYOTA RAV4 HYBRID 2017 +d32dd4e182d86a39|2023-05-15--18-11-23--18 +# TOYOTA RAV4 HYBRID 2017 +fa0e4850a023f361|2023-06-14--07-46-06--19 +# HONDA ACCORD 2018 +0750f87f2b569f15|2023-07-21--22-10-13--6 +# HONDA ACCORD 2018 +2911ec305fa73239|2023-05-16--13-29-47--27 +# HONDA ACCORD 2018 +1ada25c684c79c9f|2023-06-23--19-30-03--7 +# HONDA ACCORD 2018 +03ae79f182fff0a3|2023-05-17--20-02-41--10 +# HONDA ACCORD 2018 +0c871d574e333eeb|2023-06-02--09-32-01--21 +# HONDA ACCORD 2018 +24207e2d7868334c|2023-06-29--17-12-39--9 +# HONDA ACCORD 2018 +1a74e8bc1353f9eb|2023-06-01--00-25-52--7 +# HONDA ACCORD 2018 +20761ff63dc0e2c1|2023-05-10--19-03-20--1 +# HONDA ACCORD 2018 +066f9f7cf3c7c459|2023-07-17--17-13-44--5 +# HONDA ACCORD 2018 +21c578cf98555ce9|2023-05-11--13-46-23--58 +# HONDA ACCORD 2018 +69689c771ec57486|2023-07-11--11-36-10--27 +# HONDA ACCORD 2018 +80e02967896fde0a|2023-07-23--12-04-28--20 +# HONDA ACCORD 2018 +abcb019b84d10680|2023-05-26--20-13-32--16 +# HONDA ACCORD 2018 +bbcdb91eec4efb11|2023-08-04--10-51-09--24 +# HONDA ACCORD 2018 +c40b5785213bcb5d|2023-07-07--12-22-36--15 +# HONDA ACCORD 2018 +c7d2ba6fdcf69eef|2023-07-28--14-53-45--55 +# HONDA ACCORD 2018 +e3ddeba86ad8eb59|2023-05-11--12-48-12--3 +# HONDA ACCORD 2018 +e84b9e1ed3e077d2|2023-06-15--17-59-02--30 +# HONDA ACCORD 2018 +e961d6edc8ee01d7|2023-05-26--15-23-15--10 +# HONDA ACCORD 2018 +f54b4ab5f24eb9d7|2023-07-31--10-38-00--22 +# HONDA ACCORD 2018 +f4696dfe648b7d20|2023-06-26--07-31-46--7 +# HONDA ACCORD 2018 +f68a86aa6ba710d5|2023-07-13--19-29-03--53 +# HYUNDAI SONATA 2020 +145908dabb729ad9|2023-05-14--09-50-20--3 +# HYUNDAI SONATA 2020 +053bf385cdad1079|2023-06-02--15-48-36--24 +# HYUNDAI SONATA 2020 +10b8dcf2fb80bf56|2023-08-06--02-07-08--86 +# HYUNDAI SONATA 2020 +026e1eb462c28560|2023-07-29--09-58-52--430 +# HYUNDAI SONATA 2020 +14118dc2aced6462|2023-05-15--21-05-33--13 +# HYUNDAI SONATA 2020 +12f39c1bf68b56eb|2023-07-27--17-00-21--1 +# HYUNDAI SONATA 2020 +1edd7a8340016f2c|2023-05-26--10-01-21--1 +# HYUNDAI SONATA 2020 +310cf131d28b30d8|2023-06-08--10-57-46--24 +# HYUNDAI SONATA 2020 +3f796d94e84349fd|2023-06-10--14-30-13--5 +# HYUNDAI SONATA 2020 +40812bc457628b70|2023-07-01--12-06-20--38 +# HYUNDAI SONATA 2020 +4df896aa825bd9b3|2023-08-01--19-18-48--15 +# HYUNDAI SONATA 2020 +4a612c47eb83412a|2023-05-30--18-36-08--53 +# HYUNDAI SONATA 2020 +4960a9f1dd71aad1|2023-06-07--08-42-19--2 +# HYUNDAI SONATA 2020 +4b157737c2154617|2023-07-04--12-35-21--22 +# HYUNDAI SONATA 2020 +5c49984c8efb9c9c|2023-07-21--21-41-27--22 +# HYUNDAI SONATA 2020 +5b337c203559c300|2023-07-29--15-56-17--28 +# HYUNDAI SONATA 2020 +63f7cda2244f2338|2023-06-20--10-53-16--10 +# HYUNDAI SONATA 2020 +67cafbae8ee7f156|2023-05-15--21-35-53--57 +# HYUNDAI SONATA 2020 +67cc68f0290328c2|2023-07-25--01-33-25--14 +# HYUNDAI SONATA 2020 +700d37ccd12315cf|2023-06-01--16-13-43--68 +# HYUNDAI SONATA 2020 +7dd1f8f7f731715a|2023-05-29--20-33-34--28 +# HYUNDAI SONATA 2020 +7ef7d92481ec0ace|2023-05-20--11-58-25--6 +# HYUNDAI SONATA 2020 +89f56aec25cccf29|2023-05-31--16-32-32--12 +# HYUNDAI SONATA 2020 +895ddc214c42abea|2023-07-02--18-54-14--96 +# HYUNDAI SONATA 2020 +87aed74d45ea588f|2023-07-12--10-02-13--1 +# HYUNDAI SONATA 2020 +8d162f50f95b7128|2023-08-06--22-34-03--67 +# HYUNDAI SONATA 2020 +9ea4578ee2b1abcb|2023-05-26--07-04-55--18 +# HYUNDAI SONATA 2020 +a15bf814a6e3acc1|2023-07-26--14-52-00--4 +# HYUNDAI SONATA 2020 +a8078ee810ef83d6|2023-08-06--14-35-34--6 +# HYUNDAI SONATA 2020 +aaf2f8e95bfb437f|2023-08-05--23-38-18--38 +# HYUNDAI SONATA 2020 +ad68728bc42b1357|2023-07-10--22-22-02--27 +# HYUNDAI SONATA 2020 +b0af2fff166d80fe|2023-06-10--11-51-40--1 +# HYUNDAI SONATA 2020 +c86ea37c4a66ea6e|2023-07-27--12-27-23--22 +# HYUNDAI SONATA 2020 +cb7eee5264754a21|2023-08-07--09-30-49--3 +# HYUNDAI SONATA 2020 +c22d16eacdaf890d|2023-07-16--18-51-06--49 +# HYUNDAI SONATA 2020 +d9855ccd97606ca8|2023-05-28--12-12-29--1 +# HYUNDAI SONATA 2020 +d63936f7ce28d591|2023-05-24--16-36-34--63 +# HYUNDAI SONATA 2020 +d4958b8ee5ef5cb3|2023-06-02--16-39-43--2 +# HYUNDAI SONATA 2020 +e7369387e5ed2414|2023-05-11--08-24-27--74 +# HYUNDAI SONATA 2020 +e5904ea020532291|2023-07-22--12-16-02--17 +# HYUNDAI SONATA 2020 +e8b1f9ef35c46678|2023-07-27--17-16-47--5 +# HYUNDAI SONATA 2020 +ffce4a1d578827ee|2023-06-28--06-38-06--12 +# LEXUS RX 2020 +06a5dec26667d10e|2023-07-25--17-17-48--6 +# LEXUS RX 2020 +09ca5f224952b7f6|2023-07-19--19-40-11--12 +# LEXUS RX 2020 +08c881f7590e2420|2023-07-30--13-09-14--10 +# LEXUS RX 2020 +cc988c4ab06633fb|2023-05-12--21-16-33--41 +# TOYOTA PRIUS 2017 +167e954cba293640|2023-05-21--13-46-18--149 +# TOYOTA PRIUS 2017 +0c84cb73d1fb3a8b|2023-07-26--07-13-06--13 +# TOYOTA PRIUS 2017 +07387c2cc03c9b81|2023-06-22--16-56-50--5 +# TOYOTA PRIUS 2017 +0069f91b2663b892|2023-07-22--00-39-50--24 +# TOYOTA PRIUS 2017 +201dc5bb0067f5f2|2023-05-19--12-48-00--25 +# TOYOTA PRIUS 2017 +1e5629342e716c0a|2023-07-17--06-38-37--3 +# TOYOTA PRIUS 2017 +17c6857c5789af97|2023-07-21--19-51-17--6 +# TOYOTA PRIUS 2017 +232dd0fe26a73c53|2023-05-30--18-12-34--10 +# TOYOTA PRIUS 2017 +25d5c0772e79f4db|2023-08-03--13-54-36--17 +# TOYOTA PRIUS 2017 +0028c4ef0c8f6c30|2023-05-30--09-22-40--10 +# TOYOTA PRIUS 2017 +19e0a2420a8751bf|2023-07-16--09-41-33--9 +# TOYOTA PRIUS 2017 +1f5701894610dcd1|2023-05-13--09-02-34--6 +# TOYOTA PRIUS 2017 +15b5e12b452a992e|2023-06-13--00-02-42--12 +# TOYOTA PRIUS 2017 +0cb8c50b9ee4f5ea|2023-05-12--21-04-13--3 +# TOYOTA PRIUS 2017 +0ef0d6b0644cd7a6|2023-06-09--14-40-33--1 +# TOYOTA PRIUS 2017 +21dfd2256ee0a693|2023-07-20--13-06-55--36 +# TOYOTA PRIUS 2017 +26805bfeb242559b|2023-05-14--17-59-27--12 +# TOYOTA PRIUS 2017 +2f8790e5ac2b13e0|2023-07-22--11-03-25--5 +# TOYOTA PRIUS 2017 +2f155ba65825554f|2023-07-02--11-55-59--1 +# TOYOTA PRIUS 2017 +2eab2aa4530e03ba|2023-05-13--08-48-32--3 +# TOYOTA PRIUS 2017 +2ff4529579d6e1dc|2023-06-25--21-06-34--17 +# TOYOTA PRIUS 2017 +34faeeba08c3cc97|2023-07-30--13-22-33--14 +# TOYOTA PRIUS 2017 +3684fea792cff931|2023-08-01--20-59-40--20 +# TOYOTA PRIUS 2017 +39d749cf71d12a8e|2023-08-04--22-54-18--1 +# TOYOTA PRIUS 2017 +3f559b9878a7ccad|2023-06-21--07-22-48--15 +# TOYOTA PRIUS 2017 +457cc6df3c5f2ee1|2023-07-09--12-28-54--22 +# TOYOTA PRIUS 2017 +46b651928e9cda0f|2023-07-12--17-19-44--3 +# TOYOTA PRIUS 2017 +451e03ec9ff02db4|2023-05-27--11-30-37--8 +# TOYOTA PRIUS 2017 +4ae18286107b36b0|2023-06-07--14-03-47--2 +# TOYOTA PRIUS 2017 +4617eff9ed63ea3f|2023-07-19--17-39-20--36 +# TOYOTA PRIUS 2017 +4e36531fa34978a9|2023-05-31--15-32-40--2 +# TOYOTA PRIUS 2017 +4aa5341890583ca0|2023-05-29--11-13-49--92 +# TOYOTA PRIUS 2017 +4f2e3cebc8f3c715|2023-06-01--11-51-40--21 +# TOYOTA PRIUS 2017 +4eb29c14f8b26ba3|2023-07-25--14-09-36--8 +# TOYOTA PRIUS 2017 +52f69098ec1f801b|2023-05-16--16-10-28--3 +# TOYOTA PRIUS 2017 +51898c9b8a83d1d9|2023-07-30--23-27-13--22 +# TOYOTA PRIUS 2017 +5548e173b952a76b|2023-07-28--20-16-50--14 +# TOYOTA PRIUS 2017 +55cbd4260394fa17|2023-06-25--13-33-59--11 +# TOYOTA PRIUS 2017 +553ad02d6e7fa60e|2023-07-31--17-43-57--7 +# TOYOTA PRIUS 2017 +5e5d69c771e74940|2023-06-07--12-21-34--13 +# TOYOTA PRIUS 2017 +5a466bb77d1d0050|2023-05-12--11-49-47--9 +# TOYOTA PRIUS 2017 +5f4043fdfdd41dd5|2023-05-15--16-56-34--31 +# TOYOTA PRIUS 2017 +6318c59fa2535f38|2023-06-04--08-04-19--1 +# TOYOTA PRIUS 2017 +6371ff697bb4c045|2023-08-07--03-18-49--28 +# TOYOTA PRIUS 2017 +667087bd361ef7b1|2023-06-09--13-28-53--15 +# TOYOTA PRIUS 2017 +675c0d0c13fea348|2023-07-30--21-42-40--14 +# TOYOTA PRIUS 2017 +6925b5e1f713c09a|2023-05-19--12-25-25--4 +# TOYOTA PRIUS 2017 +754d115c7e89ca90|2023-07-07--16-40-57--4 +# TOYOTA PRIUS 2017 +718c2708b8bc1078|2023-07-18--08-32-40--14 +# TOYOTA PRIUS 2017 +748cc5e00e00d2f8|2023-07-14--11-13-29--122 +# TOYOTA PRIUS 2017 +7897d61fcfd64f73|2023-08-04--22-00-59--19 +# TOYOTA PRIUS 2017 +771fcc78f0aa53f0|2023-07-05--15-37-38--35 +# TOYOTA PRIUS 2017 +7ff274e2d6e08599|2023-08-04--20-03-11--4 +# TOYOTA PRIUS 2017 +7efdefad37338f74|2023-06-21--11-35-24--6 +# TOYOTA PRIUS 2017 +8347883441d02d13|2023-07-31--09-57-00--16 +# TOYOTA PRIUS 2017 +823d9d53d4e86649|2023-07-18--11-02-27--10 +# TOYOTA PRIUS 2017 +88f9ec172917bb98|2023-07-14--05-46-09--87 +# TOYOTA PRIUS 2017 +8df89195cd79c215|2023-06-23--13-51-00--12 +# TOYOTA PRIUS 2017 +84e716ed147ae3d7|2023-07-23--13-26-35--3 +# TOYOTA PRIUS 2017 +8c753fb54c2ad8d8|2023-07-27--17-51-39--39 +# TOYOTA PRIUS 2017 +903ac8da1aa52026|2023-08-01--17-00-11--20 +# TOYOTA PRIUS 2017 +973137405a15dccb|2023-06-04--11-13-45--13 +# TOYOTA PRIUS 2017 +9ad0cccf33247e18|2023-06-22--20-29-34--2 +# TOYOTA PRIUS 2017 +982b88e8363dc93b|2023-06-04--11-23-29--34 +# TOYOTA PRIUS 2017 +a074a62144234949|2023-07-08--18-35-42--1 +# TOYOTA PRIUS 2017 +a1206dd4a0d4d083|2023-07-19--12-54-21--52 +# TOYOTA PRIUS 2017 +a0ca4450fae65c5e|2023-06-08--07-07-25--29 +# TOYOTA PRIUS 2017 +a3b7335f488f53c2|2023-05-14--12-06-21--6 +# TOYOTA PRIUS 2017 +9f913ea6594100bf|2023-06-09--10-21-06--2 +# TOYOTA PRIUS 2017 +a55e88a02483439c|2023-07-19--12-11-58--57 +# TOYOTA PRIUS 2017 +a750926c99e2b60b|2023-05-31--15-00-56--5 +# TOYOTA PRIUS 2017 +ac11bb2bc0f2a7f7|2023-08-06--16-12-30--23 +# TOYOTA PRIUS 2017 +b222271cbe10254d|2023-07-03--10-37-50--17 +# TOYOTA PRIUS 2017 +b54d8a1ef1c820d3|2023-07-05--10-17-32--7 +# TOYOTA PRIUS 2017 +afc64e738cb8a1be|2023-06-11--16-26-28--28 +# TOYOTA PRIUS 2017 +b0b65204fa492a96|2023-05-13--11-31-33--18 +# TOYOTA PRIUS 2017 +bb94f981f4431981|2023-07-03--03-15-39--2 +# TOYOTA PRIUS 2017 +ba01e1864cd4ac61|2023-07-31--19-28-56--4 +# TOYOTA PRIUS 2017 +b68db0665d641d74|2023-07-08--16-56-57--123 +# TOYOTA PRIUS 2017 +ba94ba717fccb2f0|2023-07-11--07-47-11--1 +# TOYOTA PRIUS 2017 +bb5708908e46bcba|2023-07-12--09-08-55--10 +# TOYOTA PRIUS 2017 +bef5f54503850405|2023-06-04--10-32-31--66 +# TOYOTA PRIUS 2017 +c0c02897f03b7c7b|2023-06-23--08-31-50--10 +# TOYOTA PRIUS 2017 +c155b927e07113ad|2023-07-14--20-14-18--103 +# TOYOTA PRIUS 2017 +c38f860d281bcc5e|2023-06-09--20-09-02--17 +# TOYOTA PRIUS 2017 +c67dbd0e8b4cc29d|2023-06-05--20-53-34--9 +# TOYOTA PRIUS 2017 +c02c848a64d5177c|2023-07-06--08-45-28--13 +# TOYOTA PRIUS 2017 +cc2b9c9f221f1812|2023-07-31--17-15-47--11 +# TOYOTA PRIUS 2017 +cd0e6154e0cb0484|2023-08-05--15-28-19--1 +# TOYOTA PRIUS 2017 +c848c39dfb2de30f|2023-06-23--22-44-03--1 +# TOYOTA PRIUS 2017 +d68f8916cb7adfdf|2023-06-21--06-37-56--11 +# TOYOTA PRIUS 2017 +d67f123a82aaf50e|2023-05-12--13-49-59--2 +# TOYOTA PRIUS 2017 +e057838a043251cf|2023-07-27--14-13-22--5 +# TOYOTA PRIUS 2017 +e15020c852627a0a|2023-07-26--20-49-08--4 +# TOYOTA PRIUS 2017 +e206ddb85e53cc0d|2023-07-31--11-28-07--10 +# TOYOTA PRIUS 2017 +dd311669c55d1ccf|2023-06-25--16-57-05--1 +# TOYOTA PRIUS 2017 +e31072835e1cdc73|2023-05-20--21-59-30--69 +# TOYOTA PRIUS 2017 +ea43e1e2911e37e5|2023-07-07--03-34-54--1 +# TOYOTA PRIUS 2017 +e8cb87d767f608dd|2023-07-14--19-23-30--16 +# TOYOTA PRIUS 2017 +f1c69863517027e8|2023-07-29--12-47-02--17 +# TOYOTA PRIUS 2017 +f4b656c4aaf63360|2023-06-28--18-52-46--99 +# TOYOTA PRIUS 2017 +f8046cede9c720b1|2023-08-06--18-46-48--4 +# TOYOTA PRIUS 2017 +f8e3dfca6df16c7e|2023-05-15--11-33-42--7 +# TOYOTA PRIUS 2017 +f921646c299a6d36|2023-07-01--17-16-09--119 +# TOYOTA PRIUS 2017 +ff634b088ec2db2d|2023-06-16--15-14-04--39 +# HONDA RIDGELINE 2017 +0ddc5f974851a022|2023-06-11--18-08-25--104 +# HONDA RIDGELINE 2017 +1551280de648df83|2023-06-27--19-23-19--5 +# HONDA RIDGELINE 2017 +24187316e568f2ec|2023-07-25--10-57-53--1 +# HONDA RIDGELINE 2017 +1ce42f7a69e4b11c|2023-07-03--13-09-36--28 +# HONDA RIDGELINE 2017 +263d65b0fd18f5c4|2023-07-18--16-42-57--44 +# HONDA RIDGELINE 2017 +19fe0c3f46444eeb|2023-06-12--20-07-52--1 +# HONDA RIDGELINE 2017 +3aa992e52b91bf8f|2023-07-28--15-22-10--5 +# HONDA RIDGELINE 2017 +6acf79c245a32eb3|2023-07-08--17-40-23--17 +# HONDA RIDGELINE 2017 +6e2f19b5263c9d65|2023-07-16--09-56-19--23 +# HONDA RIDGELINE 2017 +701b7d276e45a7bf|2023-07-31--15-17-26--28 +# HONDA RIDGELINE 2017 +715416e4439e555e|2023-08-03--14-53-14--1 +# HONDA RIDGELINE 2017 +732c29f8108b54a9|2023-07-30--10-59-07--35 +# HONDA RIDGELINE 2017 +758cfd09da38d125|2023-07-24--11-45-13--1 +# HONDA RIDGELINE 2017 +7fe0389b26adfb30|2023-05-12--13-55-02--3 +# HONDA RIDGELINE 2017 +7f498d0d7b378766|2023-06-08--15-18-05--47 +# HONDA RIDGELINE 2017 +805f226ab2a8b1d7|2023-07-05--14-03-54--10 +# HONDA RIDGELINE 2017 +9824e24dd1574abc|2023-06-09--19-55-12--14 +# HONDA RIDGELINE 2017 +9b29873dd03e9357|2023-05-30--10-10-24--4 +# HONDA RIDGELINE 2017 +9bdc08e34137d504|2023-05-28--13-07-50--10 +# HONDA RIDGELINE 2017 +a9648fa1431cf7a8|2023-05-13--18-40-53--33 +# HONDA RIDGELINE 2017 +aaa226a738d37659|2023-05-19--11-59-08--5 +# HONDA RIDGELINE 2017 +a7252f38a01fc213|2023-06-20--16-17-58--2 +# HONDA RIDGELINE 2017 +adbbce5339634eae|2023-08-03--17-35-47--8 +# HONDA RIDGELINE 2017 +ac97f88de8b23b6b|2023-06-26--11-44-14--6 +# HONDA RIDGELINE 2017 +b3c88ee6c378a66e|2023-07-24--08-47-23--6 +# HONDA RIDGELINE 2017 +bf0fac55013ab937|2023-07-10--10-23-24--17 +# HONDA RIDGELINE 2017 +c5e0d17adaaefd82|2023-07-22--16-12-30--58 +# HONDA RIDGELINE 2017 +d169250d735e1346|2023-06-08--16-35-51--9 +# HONDA RIDGELINE 2017 +d084ea2309575a71|2023-05-18--17-25-07--14 +# HONDA RIDGELINE 2017 +d5dd26679a932af9|2023-07-04--09-39-08--18 +# HONDA RIDGELINE 2017 +e52c055a77cac84c|2023-06-05--17-27-17--17 +# HONDA RIDGELINE 2017 +e51512df42d845d0|2023-06-05--14-27-56--53 +# HONDA RIDGELINE 2017 +e4bcdeea7c6f1fd3|2023-07-10--11-47-50--17 +# HONDA RIDGELINE 2017 +f53658bd0c1ccf07|2023-07-28--19-28-13--12 +# TOYOTA RAV4 2019 +135e1e376668a393|2023-06-25--19-00-07--36 +# TOYOTA RAV4 2019 +0de4f23a490a8502|2023-07-19--17-54-03--7 +# TOYOTA RAV4 2019 +01a8bd5caab4a678|2023-06-15--10-36-38--2 +# TOYOTA RAV4 2019 +0dcc1daec4a26b89|2023-06-12--12-15-52--4 +# TOYOTA RAV4 2019 +180ea5df0f0b4db9|2023-07-18--22-50-24--6 +# TOYOTA RAV4 2019 +28de01246b5d6401|2023-06-19--16-24-29--8 +# TOYOTA RAV4 2019 +166ed2b12f634fb7|2023-06-05--19-15-04--13 +# TOYOTA RAV4 2019 +1f623af84e701b2a|2023-06-29--16-42-01--3 +# TOYOTA RAV4 2019 +1ccd70c07ff29d9f|2023-05-17--20-26-06--5 +# TOYOTA RAV4 2019 +1199c1d31bb3a214|2023-06-13--14-23-39--16 +# TOYOTA RAV4 2019 +24b7eef92acb725c|2023-06-25--14-09-20--9 +# TOYOTA RAV4 2019 +1ab6dacda17ac28a|2023-05-22--18-38-12--11 +# TOYOTA RAV4 2019 +1da1a0519b1669c3|2023-07-01--22-29-45--18 +# TOYOTA RAV4 2019 +0f8a92e2122ea309|2023-07-26--10-46-14--3 +# TOYOTA RAV4 2019 +0f60d680150676d0|2023-06-27--05-57-53--2 +# TOYOTA RAV4 2019 +166a8fc9c484866b|2023-07-26--08-14-07--12 +# TOYOTA RAV4 2019 +2a2249f498ddc22c|2023-07-04--13-41-52--3 +# TOYOTA RAV4 2019 +28947140cc79e4cf|2023-08-05--12-17-34--41 +# TOYOTA RAV4 2019 +028a208d08a11420|2023-07-22--15-41-34--60 +# TOYOTA RAV4 2019 +336f33d84fa8d5db|2023-07-29--16-59-09--6 +# TOYOTA RAV4 2019 +3ae010558239929d|2023-05-31--19-06-35--19 +# TOYOTA RAV4 2019 +395fe23cc0a51896|2023-06-25--10-15-45--48 +# TOYOTA RAV4 2019 +3f3a48346848df21|2023-07-26--16-15-13--1 +# TOYOTA RAV4 2019 +40f6907c6b554368|2023-06-17--05-51-38--66 +# TOYOTA RAV4 2019 +41f4ae6d3b79a9b1|2023-08-03--09-20-24--6 +# TOYOTA RAV4 2019 +45edf064d369bff9|2023-06-09--12-21-08--11 +# TOYOTA RAV4 2019 +4a389c94e0a137cc|2023-05-17--17-52-33--4 +# TOYOTA RAV4 2019 +4dfda86b67cad08f|2023-08-01--12-25-44--1 +# TOYOTA RAV4 2019 +4d0c6516a05013a1|2023-05-10--17-14-40--59 +# TOYOTA RAV4 2019 +4e4a768f20ae1e96|2023-06-06--10-43-02--36 +# TOYOTA RAV4 2019 +5175d97daef0d2ce|2023-07-02--12-18-55--8 +# TOYOTA RAV4 2019 +4a4e7f053b5730d9|2023-05-31--17-00-07--20 +# TOYOTA RAV4 2019 +523a062b170f5402|2023-05-24--15-37-42--23 +# TOYOTA RAV4 2019 +4857e763b605484d|2023-07-12--15-33-09--27 +# TOYOTA RAV4 2019 +601862be98f8db50|2023-08-06--01-03-26--37 +# TOYOTA RAV4 2019 +615671030be02e4e|2023-05-23--15-20-04--21 +# TOYOTA RAV4 2019 +5f70a3bed42b7932|2023-08-06--19-00-39--2 +# TOYOTA RAV4 2019 +628ea5913838ecc2|2023-05-23--21-38-48--3 +# TOYOTA RAV4 2019 +60093534d6d04cd2|2023-06-14--12-21-58--40 +# TOYOTA RAV4 2019 +6adb1b2f007ef2e0|2023-08-03--15-57-43--8 +# TOYOTA RAV4 2019 +672d2d359ba20275|2023-08-05--22-39-34--84 +# TOYOTA RAV4 2019 +666f3e6d7f7f02ab|2023-07-21--05-45-19--3 +# TOYOTA RAV4 2019 +6b0a418312ab1345|2023-08-07--06-41-16--1 +# TOYOTA RAV4 2019 +6f74e02218e61a6d|2023-07-22--09-59-20--8 +# TOYOTA RAV4 2019 +715bdc3654d57eb0|2023-07-23--19-41-44--8 +# TOYOTA RAV4 2019 +74ef295ef2f668fd|2023-06-14--22-25-34--27 +# TOYOTA RAV4 2019 +82d5f13f2a583c11|2023-07-01--09-18-28--21 +# TOYOTA RAV4 2019 +8074c8663302e56c|2023-06-08--20-59-32--61 +# TOYOTA RAV4 2019 +8610459df75c5ac1|2023-05-20--10-16-13--14 +# TOYOTA RAV4 2019 +890069284dace3bf|2023-07-22--11-08-46--45 +# TOYOTA RAV4 2019 +8da230f47b0fef44|2023-06-09--20-19-37--27 +# TOYOTA RAV4 2019 +8aad58f199ab2bed|2023-06-08--13-17-02--3 +# TOYOTA RAV4 2019 +8e29ec646f62a1d2|2023-08-04--14-40-06--2 +# TOYOTA RAV4 2019 +84e20ddfaf4c56d8|2023-07-25--07-10-21--12 +# TOYOTA RAV4 2019 +8d99fb063bc66a26|2023-06-02--19-49-30--27 +# TOYOTA RAV4 2019 +91f940f4a03e5406|2023-08-02--12-44-05--3 +# TOYOTA RAV4 2019 +8efd4729c72a4da9|2023-06-02--16-40-33--8 +# TOYOTA RAV4 2019 +9837fffee4d677f5|2023-06-16--21-35-16--30 +# TOYOTA RAV4 2019 +96b6b95903a330a4|2023-07-08--15-45-40--19 +# TOYOTA RAV4 2019 +9d96018bfdd9ac61|2023-06-13--15-55-43--10 +# TOYOTA RAV4 2019 +9d3747d13e211f85|2023-07-04--17-51-45--1 +# TOYOTA RAV4 2019 +a28a6e3882c1cdf1|2023-05-19--12-34-50--19 +# TOYOTA RAV4 2019 +a61651a726f6bf4d|2023-06-23--12-49-05--47 +# TOYOTA RAV4 2019 +b18225558cb35a1e|2023-07-17--15-46-21--14 +# TOYOTA RAV4 2019 +add7bff9cfb270ba|2023-05-18--22-26-57--11 +# TOYOTA RAV4 2019 +b6508eacf6f008df|2023-05-21--17-31-08--3 +# TOYOTA RAV4 2019 +b97486b552c1f5e3|2023-07-30--15-17-31--26 +# TOYOTA RAV4 2019 +be98421ae126bf91|2023-06-02--16-52-56--13 +# TOYOTA RAV4 2019 +c49a105de4a54ea1|2023-07-07--21-29-40--199 +# TOYOTA RAV4 2019 +d05aaa4d42d7c441|2023-06-05--22-11-24--3 +# TOYOTA RAV4 2019 +ca9194f601494b20|2023-05-24--17-40-49--23 +# TOYOTA RAV4 2019 +d3d6397ff2e7052e|2023-05-29--15-57-39--24 +# TOYOTA RAV4 2019 +cca5f152e7f637f0|2023-05-22--11-01-03--43 +# TOYOTA RAV4 2019 +d3e27ee09a40d1fd|2023-08-02--18-21-22--7 +# TOYOTA RAV4 2019 +d935e25b7e6c725f|2023-07-15--07-36-42--45 +# TOYOTA RAV4 2019 +e1905174a6abbc3c|2023-07-18--07-13-51--2 +# TOYOTA RAV4 2019 +e7cd4ae3bee72b52|2023-07-05--20-45-50--29 +# TOYOTA RAV4 2019 +e7571e0b3674d663|2023-06-23--21-10-27--1 +# TOYOTA RAV4 2019 +e712b42b94578404|2023-05-24--11-21-11--2 +# TOYOTA RAV4 2019 +ebe4b1a7667f231a|2023-06-27--15-23-46--3 +# TOYOTA RAV4 2019 +f30a29d40aa4a4f9|2023-05-17--16-55-57--66 +# TOYOTA RAV4 2019 +f6695ef06f916f23|2023-06-09--17-44-36--14 +# TOYOTA RAV4 2019 +fbff49b354d8a801|2023-07-21--13-52-37--2 +# TOYOTA RAV4 2019 +fc6c359e0e92884f|2023-05-14--13-50-56--9 +# TOYOTA RAV4 2017 +204be5d78daf7006|2023-06-15--07-35-31--11 +# TOYOTA RAV4 2017 +1cbdc1fbae86b49f|2023-06-09--16-31-47--10 +# TOYOTA RAV4 2017 +0655a3f86baf711f|2023-05-17--18-09-14--5 +# TOYOTA RAV4 2017 +28ca2ff434583ddc|2023-06-03--10-49-10--3 +# TOYOTA RAV4 2017 +23940cdb2383e639|2023-07-07--13-06-17--19 +# TOYOTA RAV4 2017 +3932cd29d3fe4a4b|2023-07-27--13-26-25--1 +# TOYOTA RAV4 2017 +2e5de09806977462|2023-07-01--02-13-50--2 +# TOYOTA RAV4 2017 +4a0de7e463e259ef|2023-08-03--14-16-49--2 +# TOYOTA RAV4 2017 +5e9be1efcd6ca25c|2023-07-19--15-05-58--38 +# TOYOTA RAV4 2017 +5d76166971f7ee03|2023-05-22--21-51-32--24 +# TOYOTA RAV4 2017 +6c5718d5c35b6aa8|2023-07-14--23-33-06--40 +# TOYOTA RAV4 2017 +6cd3f6f236b89cbb|2023-06-04--20-29-13--1 +# TOYOTA RAV4 2017 +829a18f6611a0593|2023-07-19--17-06-18--25 +# TOYOTA RAV4 2017 +8ab2027f3c00b364|2023-07-03--15-21-24--114 +# TOYOTA RAV4 2017 +8bf48c046a7750ec|2023-06-08--13-30-25--2 +# TOYOTA RAV4 2017 +98f88292bbae4624|2023-07-21--15-07-11--90 +# TOYOTA RAV4 2017 +a099e968ef197bc0|2023-05-24--06-36-30--2 +# TOYOTA RAV4 2017 +aa332893d92ff60a|2023-07-04--22-48-05--7 +# TOYOTA RAV4 2017 +ade7b7b6f44ba9ea|2023-08-04--16-52-21--34 +# TOYOTA RAV4 2017 +c62d83d70a8ae2b3|2023-06-06--21-39-21--43 +# TOYOTA RAV4 2017 +c9d0e3690e929c02|2023-07-06--20-22-25--25 +# TOYOTA RAV4 2017 +ceacc4d097850b24|2023-05-19--00-11-34--2 +# TOYOTA RAV4 2017 +c84e969db16a7821|2023-07-04--18-50-40--1 +# TOYOTA RAV4 2017 +dccc846a6d7f0198|2023-08-04--13-38-05--6 +# TOYOTA RAV4 2017 +e54de504cefdd500|2023-05-26--13-30-47--14 +# TOYOTA RAV4 2017 +fbc6e1316bac1a40|2023-07-30--18-48-20--18 +# CHRYSLER PACIFICA HYBRID 2018 +00d247a9bb1f9196|2023-06-25--00-50-52--16 +# CHRYSLER PACIFICA HYBRID 2018 +0f53b336851e1384|2023-07-06--20-48-35--28 +# CHRYSLER PACIFICA HYBRID 2018 +19657d9411ef4f1c|2023-06-19--15-37-12--16 +# CHRYSLER PACIFICA HYBRID 2018 +05a30afc5c891372|2023-07-29--13-14-28--1 +# CHRYSLER PACIFICA HYBRID 2018 +268be6212ca01164|2023-05-26--10-55-29--20 +# CHRYSLER PACIFICA HYBRID 2018 +2fc676162569f5f0|2023-05-27--21-30-31--6 +# CHRYSLER PACIFICA HYBRID 2018 +34a660c3c3aa6310|2023-06-09--16-51-25--7 +# CHRYSLER PACIFICA HYBRID 2018 +6480130cc87ac628|2023-07-30--19-17-09--13 +# CHRYSLER PACIFICA HYBRID 2018 +796aba999d046d7d|2023-07-12--14-19-33--5 +# CHRYSLER PACIFICA HYBRID 2018 +7620ad20d3cefc64|2023-05-19--08-49-37--5 +# CHRYSLER PACIFICA HYBRID 2018 +80d3ea3484ea9cfd|2023-05-27--15-01-03--101 +# CHRYSLER PACIFICA HYBRID 2018 +ba0a98377680c14d|2023-07-19--19-00-32--2 +# CHRYSLER PACIFICA HYBRID 2018 +f87ec6de63679cb6|2023-05-29--13-01-37--1 +# LEXUS NX 2018 +21b5c2189fb5972e|2023-07-12--12-15-44--4 +# LEXUS NX 2018 +22feb9142bcc73c9|2023-08-01--17-37-30--60 +# LEXUS NX 2018 +6bd8524bfd558e75|2023-06-30--14-15-54--4 +# LEXUS NX 2018 +83ae8304745fad7e|2023-05-17--20-16-52--148 +# JEEP GRAND CHEROKEE V6 2018 +15afba6e8f2a793d|2023-07-02--09-47-25--36 +# JEEP GRAND CHEROKEE V6 2018 +0448d4c7552b98c6|2023-07-15--14-01-58--1 +# JEEP GRAND CHEROKEE V6 2018 +044cbaf7278c5761|2023-05-15--18-58-25--11 +# JEEP GRAND CHEROKEE V6 2018 +326edad388d0a5e2|2023-07-01--19-19-08--2 +# JEEP GRAND CHEROKEE V6 2018 +37f25823e3b0d3e2|2023-07-08--15-07-03--8 +# JEEP GRAND CHEROKEE V6 2018 +5ec00346ae32f57f|2023-08-01--05-39-55--26 +# JEEP GRAND CHEROKEE V6 2018 +641d9bfd161cccd7|2023-06-29--17-52-45--7 +# JEEP GRAND CHEROKEE V6 2018 +900dfa83b4addfe6|2023-05-11--15-01-42--45 +# JEEP GRAND CHEROKEE V6 2018 +9db428338427dec2|2023-07-12--21-25-15--26 +# JEEP GRAND CHEROKEE V6 2018 +aed0854cefa55533|2023-07-07--21-01-07--4 +# JEEP GRAND CHEROKEE V6 2018 +c692ccc84342a478|2023-06-24--16-40-17--14 +# JEEP GRAND CHEROKEE V6 2018 +d50ada8ee55a5e74|2023-07-03--19-45-11--9 +# JEEP GRAND CHEROKEE V6 2018 +e56b1d3147b6a8f0|2023-07-30--12-51-42--38 +# KIA NIRO EV 2020 +05b1a2556c5bc638|2023-08-07--12-47-27--7 +# KIA NIRO EV 2020 +180ead4c4c126f9d|2023-06-08--20-02-58--6 +# KIA NIRO EV 2020 +36abc44c4f296c7a|2023-05-19--16-15-28--3 +# KIA NIRO EV 2020 +400c0f76b5a1aa90|2023-06-03--21-47-52--15 +# KIA NIRO EV 2020 +561e5f3991916e4b|2023-08-05--15-06-08--15 +# KIA NIRO EV 2020 +6d2b75c2e67bf314|2023-07-29--10-55-10--16 +# KIA NIRO EV 2020 +70a73b2fbd820de4|2023-07-31--16-50-14--17 +# KIA NIRO EV 2020 +89c7460182ce76eb|2023-06-07--22-19-13--63 +# KIA NIRO EV 2020 +9b052af2986bbe3c|2023-08-07--20-11-53--9 +# KIA NIRO EV 2020 +b382b3c7a6e6c4a3|2023-05-14--12-40-13--2 +# KIA NIRO EV 2020 +b576d2ff8a193b4a|2023-07-30--17-49-23--16 +# KIA NIRO EV 2020 +b5cebe8c56d710c5|2023-05-10--20-26-44--26 +# KIA NIRO EV 2020 +c04b1653edb84818|2023-05-16--23-20-13--17 +# KIA NIRO EV 2020 +c8f86b163152d2c5|2023-05-28--10-13-22--2 +# KIA NIRO EV 2020 +d5f923604b1b2f75|2023-05-24--07-29-50--14 +# KIA NIRO EV 2020 +dbda33c67462b907|2023-05-13--12-03-22--21 +# KIA NIRO EV 2020 +e81862333a36d2f7|2023-07-13--09-59-47--19 +# KIA NIRO EV 2020 +fc4cfe20b331a575|2023-07-31--10-34-38--1 +# HONDA CIVIC 2016 +0d922f5798ae65ed|2023-08-01--14-56-54--14 +# HONDA CIVIC 2016 +20994bc5331f98c0|2023-07-26--19-09-06--4 +# HONDA CIVIC 2016 +123dce2cbb7370cd|2023-06-08--20-14-38--19 +# HONDA CIVIC 2016 +1230ef5ea53311d6|2023-05-16--22-44-05--2 +# HONDA CIVIC 2016 +242b33685ed4e03a|2023-08-02--09-29-10--7 +# HONDA CIVIC 2016 +35ca75966798efba|2023-05-23--18-42-57--18 +# HONDA CIVIC 2016 +3e1e2b62f3f2ac3d|2023-07-12--18-23-44--5 +# HONDA CIVIC 2016 +429b106d0b800755|2023-06-03--22-13-41--2 +# HONDA CIVIC 2016 +4a080fe908e25eb2|2023-05-12--20-21-48--18 +# HONDA CIVIC 2016 +52534ebb0e145937|2023-07-14--11-40-16--5 +# HONDA CIVIC 2016 +5cfa1ad8f35779d0|2023-05-10--13-31-39--7 +# HONDA CIVIC 2016 +5dfdb608ac9bc838|2023-05-22--16-58-36--43 +# HONDA CIVIC 2016 +5dedd0807e354b45|2023-08-03--16-29-27--32 +# HONDA CIVIC 2016 +675bf95ba0ce21b7|2023-06-25--12-39-50--1 +# HONDA CIVIC 2016 +7528525a29a9d9e6|2023-07-23--01-21-59--24 +# HONDA CIVIC 2016 +7496d76ba25de13f|2023-07-22--10-48-35--5 +# HONDA CIVIC 2016 +79b03b378a603ec8|2023-05-23--05-02-29--8 +# HONDA CIVIC 2016 +8d80c16a8485aaf3|2023-05-18--21-35-54--75 +# HONDA CIVIC 2016 +9098b6df85df4bab|2023-07-12--19-32-41--22 +# HONDA CIVIC 2016 +a182b0586ed5197f|2023-07-27--19-50-29--3 +# HONDA CIVIC 2016 +a3f025079c99dde7|2023-06-11--19-51-19--6 +# HONDA CIVIC 2016 +ae5111c66432dc8d|2023-07-24--14-16-50--4 +# HONDA CIVIC 2016 +b029c0f4cf2064e7|2023-07-19--07-02-46--37 +# HONDA CIVIC 2016 +b1c832ad56b6bc9d|2023-05-28--19-00-21--6 +# HONDA CIVIC 2016 +b7107213450829d2|2023-07-25--19-57-40--42 +# HONDA CIVIC 2016 +d313e54d1691a342|2023-06-20--16-22-23--37 +# HONDA CIVIC 2016 +dfae8f89bc63acf4|2023-05-21--18-14-46--6 +# VOLKSWAGEN GOLF 7TH GEN +1f032f5173c8ad99|2023-07-25--07-06-28--2 +# VOLKSWAGEN GOLF 7TH GEN +063f36154faa4921|2023-07-04--13-42-41--69 +# VOLKSWAGEN GOLF 7TH GEN +2cdded3a5da75b6a|2023-07-29--16-03-09--21 +# VOLKSWAGEN GOLF 7TH GEN +3a12e8c9983fb961|2023-06-29--16-29-48--21 +# VOLKSWAGEN GOLF 7TH GEN +3cfdec54aa035f3f|2023-07-30--16-55-43--25 +# VOLKSWAGEN GOLF 7TH GEN +434df3000c5d36ff|2023-08-07--08-16-23--15 +# VOLKSWAGEN GOLF 7TH GEN +4aa5d874f367adbc|2023-05-12--17-55-23--3 +# VOLKSWAGEN GOLF 7TH GEN +59658f79475526e4|2023-05-10--14-12-23--21 +# VOLKSWAGEN GOLF 7TH GEN +77db91ca5676dfd9|2023-05-11--12-32-36--18 +# VOLKSWAGEN GOLF 7TH GEN +7b6a4fdf7c484d0c|2023-06-02--20-28-47--1 +# VOLKSWAGEN GOLF 7TH GEN +8906f6f8c8052728|2023-07-30--17-49-47--16 +# VOLKSWAGEN GOLF 7TH GEN +8fe9ced03c94e256|2023-05-16--09-40-38--11 +# VOLKSWAGEN GOLF 7TH GEN +9806e7635acbfc4e|2023-07-30--08-52-18--4 +# VOLKSWAGEN GOLF 7TH GEN +9dfef26e8c734ff1|2023-07-21--21-17-53--12 +# VOLKSWAGEN GOLF 7TH GEN +a5ca9217d833ec9f|2023-06-03--12-07-06--1 +# VOLKSWAGEN GOLF 7TH GEN +a61c85c75dbf1c22|2023-07-03--10-14-01--9 +# VOLKSWAGEN GOLF 7TH GEN +ba232e71d028199a|2023-06-19--15-48-13--83 +# VOLKSWAGEN GOLF 7TH GEN +c2317d8d52490584|2023-05-20--15-01-59--4 +# VOLKSWAGEN GOLF 7TH GEN +dd154b34dc4d8c52|2023-07-03--20-13-03--63 +# VOLKSWAGEN GOLF 7TH GEN +e4221d4d60b6d43e|2023-05-11--18-57-30--33 +# VOLKSWAGEN GOLF 7TH GEN +e55f210ede806fde|2023-06-09--21-52-53--21 +# TOYOTA COROLLA TSS2 2019 +2526d4fd82f82868|2023-06-16--18-16-26--14 +# TOYOTA COROLLA TSS2 2019 +01febfaac7572f25|2023-06-06--19-08-52--2 +# TOYOTA COROLLA TSS2 2019 +0ba864f7f238934a|2023-07-07--15-45-46--3 +# TOYOTA COROLLA TSS2 2019 +13aa844538f5f3ea|2023-07-28--20-37-12--12 +# TOYOTA COROLLA TSS2 2019 +117fd309156bb38b|2023-07-08--19-26-59--3 +# TOYOTA COROLLA TSS2 2019 +08a1ee03695f6a19|2023-07-12--06-56-22--37 +# TOYOTA COROLLA TSS2 2019 +1febe902238e07e7|2023-07-04--11-40-53--19 +# TOYOTA COROLLA TSS2 2019 +0976603847a63139|2023-05-24--13-04-43--69 +# TOYOTA COROLLA TSS2 2019 +1d430ad170e95d66|2023-05-10--13-47-49--3 +# TOYOTA COROLLA TSS2 2019 +10f64136dcc9e6cf|2023-07-22--12-54-01--1 +# TOYOTA COROLLA TSS2 2019 +066f132fea612a43|2023-06-18--20-06-31--9 +# TOYOTA COROLLA TSS2 2019 +230649810f83e032|2023-07-24--22-23-09--21 +# TOYOTA COROLLA TSS2 2019 +13a296d002fe988d|2023-08-05--16-55-23--10 +# TOYOTA COROLLA TSS2 2019 +0ffb338268a7f57b|2023-07-08--17-15-25--71 +# TOYOTA COROLLA TSS2 2019 +2edc2c12fbb3cc34|2023-06-12--16-21-43--15 +# TOYOTA COROLLA TSS2 2019 +2653b4b309780e1a|2023-05-15--12-33-26--32 +# TOYOTA COROLLA TSS2 2019 +2ea9a9a47b4d658b|2023-08-03--17-08-37--18 +# TOYOTA COROLLA TSS2 2019 +2cd916ec939a0cdb|2023-07-29--20-09-03--29 +# TOYOTA COROLLA TSS2 2019 +36f5b57e4202d677|2023-07-19--16-07-41--20 +# TOYOTA COROLLA TSS2 2019 +375f6b7dcfa712bb|2023-07-29--00-25-41--3 +# TOYOTA COROLLA TSS2 2019 +3cb092b934c1321a|2023-07-12--14-19-10--1 +# TOYOTA COROLLA TSS2 2019 +42ff158c63048ad3|2023-06-19--12-40-18--12 +# TOYOTA COROLLA TSS2 2019 +3c755ae77207f5e6|2023-07-07--06-56-53--26 +# TOYOTA COROLLA TSS2 2019 +479477500279ec91|2023-07-15--15-08-01--13 +# TOYOTA COROLLA TSS2 2019 +4955b33f42f814ec|2023-06-19--18-19-33--10 +# TOYOTA COROLLA TSS2 2019 +4f871d414c69c6ba|2023-05-26--01-44-47--1 +# TOYOTA COROLLA TSS2 2019 +4ecfcac756318cbf|2023-05-26--09-11-43--16 +# TOYOTA COROLLA TSS2 2019 +51e32fb50a64250a|2023-07-07--20-50-11--51 +# TOYOTA COROLLA TSS2 2019 +48590e272587fc49|2023-06-02--08-36-54--48 +# TOYOTA COROLLA TSS2 2019 +4ccbc0d42d611d6e|2023-06-06--19-48-02--3 +# TOYOTA COROLLA TSS2 2019 +50c35b8d29fd7574|2023-07-12--19-36-54--2 +# TOYOTA COROLLA TSS2 2019 +51b1e5305ed717c2|2023-07-04--08-50-02--3 +# TOYOTA COROLLA TSS2 2019 +4c833174af1f11d9|2023-06-27--21-28-20--36 +# TOYOTA COROLLA TSS2 2019 +575626d3c2c61bc3|2023-07-18--17-06-03--46 +# TOYOTA COROLLA TSS2 2019 +59bbf0ec138e1bc4|2023-07-30--19-20-22--8 +# TOYOTA COROLLA TSS2 2019 +567e47e503b36408|2023-05-11--13-24-46--8 +# TOYOTA COROLLA TSS2 2019 +5d2be9f6c9bb6d59|2023-07-14--18-20-52--31 +# TOYOTA COROLLA TSS2 2019 +636f850472924d8b|2023-07-27--05-38-09--139 +# TOYOTA COROLLA TSS2 2019 +66235d23ccedf22b|2023-06-19--15-16-34--3 +# TOYOTA COROLLA TSS2 2019 +6c15cf37ba9e13af|2023-05-10--07-18-08--33 +# TOYOTA COROLLA TSS2 2019 +6439fb08910d24cb|2023-06-15--14-26-45--42 +# TOYOTA COROLLA TSS2 2019 +7472c18ac7ee970a|2023-07-30--01-05-28--2 +# TOYOTA COROLLA TSS2 2019 +7065b7a287ca6bfd|2023-06-21--16-08-50--4 +# TOYOTA COROLLA TSS2 2019 +7037f9c72bc6f964|2023-06-12--16-02-49--2 +# TOYOTA COROLLA TSS2 2019 +75e2a892240ca11a|2023-07-22--09-18-55--5 +# TOYOTA COROLLA TSS2 2019 +796a1c5804476c3f|2023-06-26--19-24-19--7 +# TOYOTA COROLLA TSS2 2019 +7848680077bfdcdc|2023-07-24--18-38-50--3 +# TOYOTA COROLLA TSS2 2019 +742af4a6e6eaa03a|2023-06-27--13-07-41--44 +# TOYOTA COROLLA TSS2 2019 +744a7144504b6e2e|2023-08-02--13-28-51--7 +# TOYOTA COROLLA TSS2 2019 +7a2f01307609c158|2023-08-06--17-30-48--12 +# TOYOTA COROLLA TSS2 2019 +772e65c4f149b380|2023-05-20--04-14-17--1 +# TOYOTA COROLLA TSS2 2019 +86d675e9d797d210|2023-05-21--21-53-30--21 +# TOYOTA COROLLA TSS2 2019 +8730608053a8d3af|2023-06-26--17-05-48--18 +# TOYOTA COROLLA TSS2 2019 +89d53004921bd239|2023-07-22--15-00-53--38 +# TOYOTA COROLLA TSS2 2019 +90a0f4e5ad469fb7|2023-08-04--11-48-13--1 +# TOYOTA COROLLA TSS2 2019 +927ee6ce294e2f25|2023-07-29--08-22-53--1 +# TOYOTA COROLLA TSS2 2019 +9285a03a79895178|2023-07-04--23-14-40--16 +# TOYOTA COROLLA TSS2 2019 +9670ceb56ecf4d79|2023-07-10--07-55-49--14 +# TOYOTA COROLLA TSS2 2019 +99846616e03e1162|2023-07-30--12-59-13--2 +# TOYOTA COROLLA TSS2 2019 +98d3152d30060750|2023-05-20--15-57-05--17 +# TOYOTA COROLLA TSS2 2019 +990a1b5f50ca3d5c|2023-05-17--10-17-05--1 +# TOYOTA COROLLA TSS2 2019 +9afac539f787a200|2023-06-30--15-05-48--14 +# TOYOTA COROLLA TSS2 2019 +9a2505595b2a3554|2023-08-07--14-46-21--59 +# TOYOTA COROLLA TSS2 2019 +a1459329fb4cd970|2023-06-28--15-44-03--19 +# TOYOTA COROLLA TSS2 2019 +a2a0ccea32023010|2023-07-26--17-19-33--11 +# TOYOTA COROLLA TSS2 2019 +9f65d75230c64fb4|2023-06-19--12-28-55--95 +# TOYOTA COROLLA TSS2 2019 +a43409b966c53d15|2023-06-29--10-11-49--4 +# TOYOTA COROLLA TSS2 2019 +a4446d3a8ae1e324|2023-06-06--11-49-40--17 +# TOYOTA COROLLA TSS2 2019 +9d5c10b6f66f736a|2023-06-18--10-48-03--191 +# TOYOTA COROLLA TSS2 2019 +a2804476419fd4f3|2023-05-30--14-13-10--2 +# TOYOTA COROLLA TSS2 2019 +ac7fa8ccceee8fe4|2023-07-21--13-50-12--14 +# TOYOTA COROLLA TSS2 2019 +ad27b5fb54426e8a|2023-07-12--16-32-18--9 +# TOYOTA COROLLA TSS2 2019 +b46ac14e96fa047d|2023-05-26--13-10-23--9 +# TOYOTA COROLLA TSS2 2019 +b292d45117041581|2023-06-22--20-59-15--34 +# TOYOTA COROLLA TSS2 2019 +b135d4bbc0ace012|2023-07-28--08-46-43--5 +# TOYOTA COROLLA TSS2 2019 +b2a420a551c95f61|2023-06-10--13-52-14--2 +# TOYOTA COROLLA TSS2 2019 +b27aabf96cf81189|2023-07-20--17-59-53--9 +# TOYOTA COROLLA TSS2 2019 +ba2c31fbceccf0a2|2023-05-26--08-28-50--19 +# TOYOTA COROLLA TSS2 2019 +b8e73c4b855918a4|2023-06-23--22-09-47--5 +# TOYOTA COROLLA TSS2 2019 +b4cce6e306466c3a|2023-06-09--13-01-32--3 +# TOYOTA COROLLA TSS2 2019 +bc30537149678ec5|2023-07-16--09-33-33--4 +# TOYOTA COROLLA TSS2 2019 +bcb2e59018be5f0e|2023-05-22--14-41-32--295 +# TOYOTA COROLLA TSS2 2019 +bb6bc8e6ac2190dc|2023-05-31--16-10-00--53 +# TOYOTA COROLLA TSS2 2019 +b7440708a5e2c796|2023-06-21--19-37-36--9 +# TOYOTA COROLLA TSS2 2019 +c0023418edc8ed7b|2023-06-04--21-14-16--36 +# TOYOTA COROLLA TSS2 2019 +c33e7ea5e01511d3|2023-07-13--12-05-30--1 +# TOYOTA COROLLA TSS2 2019 +c9315a5b08fabfb4|2023-05-17--15-45-13--7 +# TOYOTA COROLLA TSS2 2019 +d02240bb0738ae9d|2023-07-04--19-59-49--37 +# TOYOTA COROLLA TSS2 2019 +d0bef3e100712fce|2023-05-23--07-58-05--3 +# TOYOTA COROLLA TSS2 2019 +d1830450c4c43463|2023-06-24--21-57-32--2 +# TOYOTA COROLLA TSS2 2019 +cf0bbb6c86836b73|2023-07-08--18-37-43--28 +# TOYOTA COROLLA TSS2 2019 +d2a3925946654cd3|2023-06-12--16-19-24--3 +# TOYOTA COROLLA TSS2 2019 +da803e391542cb10|2023-05-29--13-49-28--35 +# TOYOTA COROLLA TSS2 2019 +dcefbc5933b0e410|2023-06-14--19-00-09--3 +# TOYOTA COROLLA TSS2 2019 +e0601ce36770a765|2023-07-25--09-12-36--55 +# TOYOTA COROLLA TSS2 2019 +dfb993cc43ba69dc|2023-06-06--06-52-08--2 +# TOYOTA COROLLA TSS2 2019 +e5bbae6d1c740ba1|2023-06-19--12-57-23--14 +# TOYOTA COROLLA TSS2 2019 +e5bfe3f909216ef6|2023-07-25--18-03-22--7 +# TOYOTA COROLLA TSS2 2019 +e514e647fc5e28d0|2023-07-10--16-11-35--1 +# TOYOTA COROLLA TSS2 2019 +e01d990b9fafc7c7|2023-06-26--04-53-20--24 +# TOYOTA COROLLA TSS2 2019 +ead14b5ba31cdb4d|2023-08-05--21-07-24--107 +# TOYOTA COROLLA TSS2 2019 +e9b1885ec511d838|2023-05-15--09-35-44--42 +# TOYOTA COROLLA TSS2 2019 +e305dea90c599b82|2023-06-20--19-39-01--6 +# TOYOTA COROLLA TSS2 2019 +e8d19bce0da0148f|2023-07-28--16-53-43--13 +# TOYOTA COROLLA TSS2 2019 +f1c4e2a016e4de93|2023-07-19--21-27-01--3 +# TOYOTA COROLLA TSS2 2019 +f1b3bb0340f9b560|2023-07-26--09-19-02--22 +# TOYOTA COROLLA TSS2 2019 +eb7ac6daa55e0823|2023-06-10--19-14-01--4 +# TOYOTA COROLLA TSS2 2019 +f5695afee48c4efe|2023-05-12--08-12-59--21 +# TOYOTA COROLLA TSS2 2019 +feee8fadcb368355|2023-07-22--21-12-52--25 +# TOYOTA COROLLA TSS2 2019 +f82bb7e095cdd66f|2023-05-10--05-19-59--9 +# TOYOTA COROLLA TSS2 2019 +fe18f736cb0d7813|2023-05-24--19-43-43--10 +# CHRYSLER PACIFICA HYBRID 2019 +0e99ed1796cf0796|2023-07-01--13-12-55--14 +# CHRYSLER PACIFICA HYBRID 2019 +1943b3d682b7f11d|2023-07-09--13-56-25--20 +# CHRYSLER PACIFICA HYBRID 2019 +120a432f63cb0de2|2023-06-24--13-48-30--7 +# CHRYSLER PACIFICA HYBRID 2019 +1a10807c60c127fd|2023-06-05--18-28-54--44 +# CHRYSLER PACIFICA HYBRID 2019 +2b964a897363fb8d|2023-07-07--16-03-35--35 +# CHRYSLER PACIFICA HYBRID 2019 +2f6f39e4b14298b8|2023-05-28--18-25-37--43 +# CHRYSLER PACIFICA HYBRID 2019 +35176353a674cbdc|2023-06-04--18-26-00--52 +# CHRYSLER PACIFICA HYBRID 2019 +37004be1e4d06893|2023-08-04--00-57-55--1 +# CHRYSLER PACIFICA HYBRID 2019 +3e5d2ea720b2ade6|2023-05-18--20-54-26--14 +# CHRYSLER PACIFICA HYBRID 2019 +4395faadf0a373f2|2023-05-13--16-36-01--12 +# CHRYSLER PACIFICA HYBRID 2019 +4b17c71e7787e92f|2023-05-16--21-51-11--12 +# CHRYSLER PACIFICA HYBRID 2019 +63b6ad8d485e56a3|2023-07-17--09-57-27--20 +# CHRYSLER PACIFICA HYBRID 2019 +644df7356b2e465d|2023-06-10--21-35-04--90 +# CHRYSLER PACIFICA HYBRID 2019 +6244bf059e173e99|2023-07-30--09-14-03--15 +# CHRYSLER PACIFICA HYBRID 2019 +6d3ff8fbb8417635|2023-07-11--18-41-27--2 +# CHRYSLER PACIFICA HYBRID 2019 +7251ba2e0f80add1|2023-05-21--20-49-01--94 +# CHRYSLER PACIFICA HYBRID 2019 +7494bdf484b714e7|2023-05-15--22-44-48--48 +# CHRYSLER PACIFICA HYBRID 2019 +86deeb65f10c3129|2023-06-08--09-04-59--1 +# CHRYSLER PACIFICA HYBRID 2019 +8b4a62384ce1dbda|2023-07-10--20-20-58--8 +# CHRYSLER PACIFICA HYBRID 2019 +91190f5999463dd8|2023-06-12--11-38-07--3 +# CHRYSLER PACIFICA HYBRID 2019 +94586e8449ef012b|2023-06-08--14-38-27--5 +# CHRYSLER PACIFICA HYBRID 2019 +a3b4d4b4cb18bdad|2023-06-11--16-20-07--62 +# CHRYSLER PACIFICA HYBRID 2019 +aadbd1a661fb4da3|2023-08-03--13-56-56--2 +# CHRYSLER PACIFICA HYBRID 2019 +acb4cd444864d759|2023-05-12--22-57-05--9 +# CHRYSLER PACIFICA HYBRID 2019 +b398a1af9eea479f|2023-06-11--19-48-36--36 +# CHRYSLER PACIFICA HYBRID 2019 +cf10bbff2c1d2c6b|2023-07-10--08-53-44--2 +# CHRYSLER PACIFICA HYBRID 2019 +d8c9e6bde1d2900f|2023-06-15--10-51-56--3 +# CHRYSLER PACIFICA HYBRID 2019 +de666a40633d13fe|2023-07-28--14-19-44--12 +# CHRYSLER PACIFICA HYBRID 2019 +e51816839229e7c6|2023-07-08--13-44-57--1 +# CHRYSLER PACIFICA HYBRID 2019 +ec62067436775681|2023-07-19--18-28-32--26 +# CHRYSLER PACIFICA HYBRID 2019 +ed624dae6fed0e6b|2023-07-16--09-21-32--35 +# CHRYSLER PACIFICA HYBRID 2019 +ef47e9b061fba593|2023-05-13--21-59-33--5 +# CHRYSLER PACIFICA HYBRID 2019 +ede4a914fcc6fb6d|2023-08-02--14-13-23--3 +# CHRYSLER PACIFICA HYBRID 2019 +f421e8c2744fed7f|2023-06-30--13-10-52--24 +# CHRYSLER PACIFICA HYBRID 2019 +f6f46c9092a35916|2023-07-15--16-38-00--3 +# CHRYSLER PACIFICA HYBRID 2019 +f800ed88a5f7fa19|2023-07-11--11-16-38--5 +# CHRYSLER PACIFICA HYBRID 2019 +fe0f36c1b6573659|2023-07-19--15-06-52--7 +# CHEVROLET BOLT EUV 2022 +2334b466b5ba9cab|2023-05-31--17-06-45--9 +# CHEVROLET BOLT EUV 2022 +276dfdea5c6a45e0|2023-05-16--11-15-03--5 +# CHEVROLET BOLT EUV 2022 +186ece45c5f7730a|2023-06-05--12-57-13--5 +# CHEVROLET BOLT EUV 2022 +0def4a390f6fe5c0|2023-06-07--20-34-57--34 +# CHEVROLET BOLT EUV 2022 +161c32b370ac8d0f|2023-07-23--09-03-44--2 +# CHEVROLET BOLT EUV 2022 +1829f1c500a2c163|2023-07-27--16-07-15--11 +# CHEVROLET BOLT EUV 2022 +0ff88cd04a49e0b8|2023-06-06--21-03-24--4 +# CHEVROLET BOLT EUV 2022 +1ad81494603f8450|2023-06-15--16-34-30--8 +# CHEVROLET BOLT EUV 2022 +10b00eb757360a96|2023-06-30--10-31-18--19 +# CHEVROLET BOLT EUV 2022 +135b91dcfd6b31b1|2023-06-17--21-01-23--3 +# CHEVROLET BOLT EUV 2022 +297302e607039e23|2023-06-06--20-28-40--9 +# CHEVROLET BOLT EUV 2022 +18dbdce81b2402b0|2023-08-07--07-34-34--7 +# CHEVROLET BOLT EUV 2022 +2b4118b61e62995e|2023-07-15--15-17-08--10 +# CHEVROLET BOLT EUV 2022 +2d6490f23b2f8592|2023-08-07--10-00-17--12 +# CHEVROLET BOLT EUV 2022 +2fd7f5f47f793c9c|2023-05-21--12-19-26--15 +# CHEVROLET BOLT EUV 2022 +3140e1c6195c880e|2023-05-10--00-08-11--8 +# CHEVROLET BOLT EUV 2022 +36abd7f7160a9a75|2023-07-05--14-20-25--13 +# CHEVROLET BOLT EUV 2022 +3b68b660a77fd80e|2023-07-16--01-08-43--11 +# CHEVROLET BOLT EUV 2022 +446478f0404c86d3|2023-07-30--11-24-22--14 +# CHEVROLET BOLT EUV 2022 +43f2df44eba11325|2023-07-02--18-10-34--1 +# CHEVROLET BOLT EUV 2022 +43d44eef740e247b|2023-07-30--16-49-25--7 +# CHEVROLET BOLT EUV 2022 +45bcfa6a1dab12b2|2023-07-03--16-44-59--1 +# CHEVROLET BOLT EUV 2022 +4fe3129b0fc9aed8|2023-06-24--12-06-07--2 +# CHEVROLET BOLT EUV 2022 +50d49a7246b883d5|2023-06-20--09-05-14--47 +# CHEVROLET BOLT EUV 2022 +4c85a75ef10f7a6a|2023-07-31--11-57-04--42 +# CHEVROLET BOLT EUV 2022 +555d4087cf86aa91|2023-05-12--15-16-07--34 +# CHEVROLET BOLT EUV 2022 +583b1612bef234ed|2023-07-22--14-24-44--10 +# CHEVROLET BOLT EUV 2022 +63a62077852a6194|2023-07-31--12-11-15--14 +# CHEVROLET BOLT EUV 2022 +63cd6284b07989a9|2023-07-07--19-48-05--7 +# CHEVROLET BOLT EUV 2022 +6b654cb3eaade30b|2023-08-01--08-12-37--16 +# CHEVROLET BOLT EUV 2022 +6afbe9126b0b488e|2023-07-29--15-32-54--1 +# CHEVROLET BOLT EUV 2022 +715792adb472e791|2023-08-07--16-02-30--19 +# CHEVROLET BOLT EUV 2022 +77360d8b4b0aa355|2023-06-09--17-54-25--24 +# CHEVROLET BOLT EUV 2022 +79c2ed37b4345620|2023-07-08--22-23-27--4 +# CHEVROLET BOLT EUV 2022 +80c623f72cae73bb|2023-06-01--21-46-15--3 +# CHEVROLET BOLT EUV 2022 +82a90d8103afed98|2023-06-12--07-52-31--23 +# CHEVROLET BOLT EUV 2022 +8490e1e599660163|2023-05-15--06-17-33--1 +# CHEVROLET BOLT EUV 2022 +894c916ba5d876c1|2023-06-06--06-55-07--15 +# CHEVROLET BOLT EUV 2022 +8ed03d21b3c15090|2023-06-22--22-10-54--33 +# CHEVROLET BOLT EUV 2022 +93fbf2642ce58ddf|2023-06-27--15-39-36--5 +# CHEVROLET BOLT EUV 2022 +988fdc2a62b72489|2023-06-29--22-43-31--15 +# CHEVROLET BOLT EUV 2022 +986c6ba7f7118db8|2023-07-03--15-12-47--7 +# CHEVROLET BOLT EUV 2022 +989d9a23ae4cbc76|2023-06-03--21-50-50--4 +# CHEVROLET BOLT EUV 2022 +9e27a5ad608f9b5d|2023-07-28--19-22-22--5 +# CHEVROLET BOLT EUV 2022 +9d07b85adb1c7959|2023-07-24--19-16-41--12 +# CHEVROLET BOLT EUV 2022 +a1c6fc5f9e1c0641|2023-07-26--18-20-50--2 +# CHEVROLET BOLT EUV 2022 +a40f0130fa3d0aaf|2023-07-25--10-57-51--89 +# CHEVROLET BOLT EUV 2022 +a8632896bc8c451f|2023-05-21--10-22-51--3 +# CHEVROLET BOLT EUV 2022 +aea39a07b9a7343f|2023-07-09--17-06-28--8 +# CHEVROLET BOLT EUV 2022 +b7709c9bd2bb88fd|2023-06-18--12-43-53--46 +# CHEVROLET BOLT EUV 2022 +b79a39df75584415|2023-07-04--22-01-28--21 +# CHEVROLET BOLT EUV 2022 +bd059400a5cde994|2023-07-04--16-14-42--4 +# CHEVROLET BOLT EUV 2022 +bf073985dfe87f7a|2023-08-04--14-12-05--11 +# CHEVROLET BOLT EUV 2022 +be4060e17a23ffdd|2023-05-20--14-36-48--3 +# CHEVROLET BOLT EUV 2022 +c401b4043ba9000a|2023-08-03--14-48-07--29 +# CHEVROLET BOLT EUV 2022 +b9a4ef3d6f3df97b|2023-08-03--05-45-23--35 +# CHEVROLET BOLT EUV 2022 +c6d15839fd14a490|2023-05-12--07-40-52--16 +# CHEVROLET BOLT EUV 2022 +d061de08f31aeed7|2023-05-30--14-22-41--75 +# CHEVROLET BOLT EUV 2022 +d1f071678ccb1920|2023-07-11--15-10-34--2 +# CHEVROLET BOLT EUV 2022 +d08af0cf79acfd74|2023-07-19--05-13-02--2 +# CHEVROLET BOLT EUV 2022 +d4dfed34943b6c7e|2023-07-20--08-10-21--20 +# CHEVROLET BOLT EUV 2022 +dbc1d04685612ecc|2023-05-15--17-57-58--3 +# CHEVROLET BOLT EUV 2022 +da4d62ee196295d4|2023-07-28--19-30-36--29 +# CHEVROLET BOLT EUV 2022 +da4f7891ae804737|2023-07-06--14-28-22--12 +# CHEVROLET BOLT EUV 2022 +dc50076c39d4257c|2023-06-01--20-16-39--1 +# CHEVROLET BOLT EUV 2022 +dda7599351b213bc|2023-06-13--05-36-42--5 +# CHEVROLET BOLT EUV 2022 +dc2696502990ee07|2023-08-05--06-27-00--8 +# CHEVROLET BOLT EUV 2022 +e340670ab48ba88a|2023-07-29--21-21-49--8 +# CHEVROLET BOLT EUV 2022 +ea4cb0f25db44a80|2023-06-14--05-18-10--19 +# CHEVROLET BOLT EUV 2022 +ed9dc2d827252019|2023-07-27--06-22-48--42 +# CHEVROLET BOLT EUV 2022 +f1ed193b05fe93b0|2023-05-11--18-47-03--3 +# CHEVROLET BOLT EUV 2022 +ef91b5c6792c0a7a|2023-07-31--20-36-50--1 +# CHEVROLET BOLT EUV 2022 +f89a0a966e54f7ff|2023-07-15--20-44-12--8 +# CHEVROLET BOLT EUV 2022 +fc55aed7a9efb49c|2023-06-08--08-01-19--23 +# TOYOTA CAMRY 2021 +093be653a841c345|2023-05-10--19-37-55--15 +# TOYOTA CAMRY 2021 +0a7615a819224eab|2023-05-18--17-00-34--181 +# TOYOTA CAMRY 2021 +1f9891d5a64661ef|2023-06-02--17-00-36--19 +# TOYOTA CAMRY 2021 +2307361bfeefee69|2023-06-08--17-48-28--70 +# TOYOTA CAMRY 2021 +06a5dbcee3ab12f1|2023-07-26--07-57-11--1 +# TOYOTA CAMRY 2021 +037c07a9b40d78a2|2023-05-18--22-31-50--21 +# TOYOTA CAMRY 2021 +3cf34a46abd8addd|2023-07-25--10-03-16--16 +# TOYOTA CAMRY 2021 +470698275bafef42|2023-07-31--06-34-13--8 +# TOYOTA CAMRY 2021 +5231cc88de0139ab|2023-06-14--13-33-32--7 +# TOYOTA CAMRY 2021 +528789e4391481cf|2023-07-27--15-16-03--16 +# TOYOTA CAMRY 2021 +552129078b970cd3|2023-07-25--09-41-30--20 +# TOYOTA CAMRY 2021 +5d4b81649a4bce56|2023-08-01--12-01-18--2 +# TOYOTA CAMRY 2021 +6f26453738f35634|2023-05-21--13-32-12--13 +# TOYOTA CAMRY 2021 +73088e067b2fb9d4|2023-05-12--08-24-31--25 +# TOYOTA CAMRY 2021 +8acd130e9e5d0cf8|2023-06-13--12-05-18--35 +# TOYOTA CAMRY 2021 +8c8ab5e2b14c51c9|2023-05-26--18-37-04--33 +# TOYOTA CAMRY 2021 +876a156a1191834d|2023-07-13--18-37-18--7 +# TOYOTA CAMRY 2021 +a092c3532573731f|2023-08-02--14-19-03--2 +# TOYOTA CAMRY 2021 +a7244a988251077d|2023-05-20--08-40-16--2 +# TOYOTA CAMRY 2021 +b7f21591ba459403|2023-06-02--18-32-59--20 +# TOYOTA CAMRY 2021 +b4f83330b2d59205|2023-05-16--18-20-35--9 +# TOYOTA CAMRY 2021 +bae56b301710cdf0|2023-05-30--07-44-31--23 +# TOYOTA CAMRY 2021 +c70d69b11bfb697d|2023-06-17--18-51-02--8 +# TOYOTA CAMRY 2021 +cc7c8c846c338570|2023-07-10--08-37-46--26 +# TOYOTA CAMRY 2021 +c4e9230919b74f75|2023-06-20--17-57-36--20 +# TOYOTA CAMRY 2021 +d45c4dcf8ea2f5d4|2023-07-18--12-10-14--71 +# TOYOTA CAMRY 2021 +d9d5a5d9f4ae2ad6|2023-05-27--10-56-51--7 +# TOYOTA CAMRY 2021 +f47661feccc29204|2023-05-13--19-57-58--11 +# TOYOTA CAMRY 2018 +043c1d59829f98e1|2023-05-15--16-39-19--18 +# TOYOTA CAMRY 2018 +2f37fc0d2ebb8cfe|2023-07-28--10-38-40--40 +# TOYOTA CAMRY 2018 +67f3731c5f3afaa2|2023-06-05--20-19-00--15 +# TOYOTA CAMRY 2018 +8dd5cd20feef7daf|2023-05-31--15-48-11--2 +# TOYOTA CAMRY 2018 +8eb7ff2f26051984|2023-05-17--10-07-44--23 +# TOYOTA CAMRY 2018 +aae51b841b955820|2023-05-21--00-01-38--3 +# TOYOTA CAMRY 2018 +b00f418d2b66cfa2|2023-05-27--16-36-37--129 +# TOYOTA CAMRY 2018 +b711d49263f20146|2023-06-23--17-30-14--137 +# TOYOTA CAMRY 2018 +c5827e54d59bdcc2|2023-08-03--18-40-21--1 +# TOYOTA CAMRY 2018 +c6503f6534bf811a|2023-08-07--14-05-15--1 +# TOYOTA CAMRY 2018 +eddf8030d2c0fbd8|2023-05-17--07-20-36--18 +# TOYOTA CAMRY 2018 +ef6bd990e34920b1|2023-07-25--08-53-09--1 +# CHEVROLET SILVERADO 1500 2020 +1092d371df987f78|2023-07-11--08-18-42--1 +# CHEVROLET SILVERADO 1500 2020 +2a3958b34246e3b7|2023-07-09--16-52-48--23 +# CHEVROLET SILVERADO 1500 2020 +25a42ae6068112ed|2023-07-19--08-46-57--6 +# CHEVROLET SILVERADO 1500 2020 +34d4e668268e0cc8|2023-06-24--18-00-35--12 +# CHEVROLET SILVERADO 1500 2020 +38aa7da107d5d252|2023-06-03--23-00-13--7 +# CHEVROLET SILVERADO 1500 2020 +3c760901e7b30fe2|2023-07-24--10-35-18--2 +# CHEVROLET SILVERADO 1500 2020 +5085c761395d1fe6|2023-05-26--18-54-08--17 +# CHEVROLET SILVERADO 1500 2020 +602051db17fb6945|2023-06-11--14-11-45--16 +# CHEVROLET SILVERADO 1500 2020 +b83dd25fd69d185a|2023-07-09--11-11-25--13 +# CHEVROLET SILVERADO 1500 2020 +c5762c796866f52b|2023-06-01--11-09-58--40 +# CHEVROLET SILVERADO 1500 2020 +cc2c095689982e90|2023-06-16--15-19-12--15 +# CHEVROLET SILVERADO 1500 2020 +d89ba4ef9ca61255|2023-06-05--20-19-55--1 +# CHEVROLET SILVERADO 1500 2020 +f04339ee7d0a4f4f|2023-07-06--12-12-45--1 +# CHEVROLET SILVERADO 1500 2020 +f1a814b2d113041b|2023-06-14--20-39-56--46 +# CHEVROLET SILVERADO 1500 2020 +f4ff60e509c0efad|2023-07-17--08-45-55--10 +# CHEVROLET SILVERADO 1500 2020 +fe80a4e1cedec853|2023-07-26--19-16-06--9 +# CHRYSLER PACIFICA 2018 +2137b01aa0ca63f9|2023-06-19--16-31-25--12 +# CHRYSLER PACIFICA 2018 +0a3e89f78b1d0071|2023-07-04--13-44-33--37 +# CHRYSLER PACIFICA 2018 +2900033dd47fa445|2023-07-19--10-02-00--5 +# CHRYSLER PACIFICA 2018 +0d67197945512e16|2023-06-02--18-33-08--186 +# CHRYSLER PACIFICA 2018 +454c31a132f2c003|2023-06-24--19-40-37--208 +# CHRYSLER PACIFICA 2018 +53f2206925c37581|2023-05-20--11-40-22--4 +# CHRYSLER PACIFICA 2018 +6732a0b0508ffc0e|2023-05-11--09-02-51--1 +# CHRYSLER PACIFICA 2018 +8363f866866f25e7|2023-05-10--06-55-11--26 +# CHRYSLER PACIFICA 2018 +87caf137ebd1c6f6|2023-07-05--12-13-27--4 +# CHRYSLER PACIFICA 2018 +89e4d9d4b8ec175c|2023-08-07--13-07-13--128 +# CHRYSLER PACIFICA 2018 +8fc6a1b72c8b1357|2023-07-31--06-08-43--18 +# CHRYSLER PACIFICA 2018 +e13cd4efc12b3ed9|2023-06-02--23-27-54--10 +# HYUNDAI SANTA FE 2019 +124457b31149107e|2023-06-11--17-33-36--39 +# HYUNDAI SANTA FE 2019 +0b2b36cf5a0789db|2023-05-30--21-15-07--17 +# HYUNDAI SANTA FE 2019 +2febc4fb44b77feb|2023-06-19--10-18-04--12 +# HYUNDAI SANTA FE 2019 +45a8ffd448481ce2|2023-06-11--11-43-42--69 +# HYUNDAI SANTA FE 2019 +47ba5e6f0490d659|2023-05-19--13-11-38--21 +# HYUNDAI SANTA FE 2019 +6af67ee8ad45b46d|2023-06-09--12-43-30--3 +# HYUNDAI SANTA FE 2019 +7effea3e618a7eff|2023-07-02--14-51-45--20 +# HYUNDAI SANTA FE 2019 +9ebc35731309da40|2023-05-15--20-55-46--5 +# HYUNDAI SANTA FE 2019 +ac34a01eff94e7d2|2023-06-09--11-20-45--1 +# HYUNDAI SANTA FE 2019 +dae9868756e02256|2023-05-24--21-02-45--14 +# HYUNDAI SANTA FE 2019 +e8a6a6776c51a45c|2023-05-14--14-07-00--6 +# HYUNDAI SANTA FE 2019 +ea9d3b13a4799604|2023-05-19--19-43-27--31 +# HYUNDAI SANTA FE 2019 +fddc8d2cbb48ec6f|2023-06-02--17-35-08--16 +# HONDA ACCORD 2018 +190b11018a714a28|2023-07-12--17-54-06--29 +# HONDA ACCORD 2018 +17a3b6806ff8e041|2023-05-19--16-04-06--24 +# HONDA ACCORD 2018 +0dacabc563f7e7d7|2023-06-04--21-45-33--4 +# HONDA ACCORD 2018 +10d6a69109431519|2023-05-28--14-21-19--19 +# HONDA ACCORD 2018 +05bcd2ee65199207|2023-07-19--18-22-21--6 +# HONDA ACCORD 2018 +0c676e287b251a20|2023-07-28--06-19-37--105 +# HONDA ACCORD 2018 +0793ebd391c355da|2023-07-20--06-35-32--19 +# HONDA ACCORD 2018 +005d4e7ceb089cfd|2023-07-13--07-22-49--18 +# HONDA ACCORD 2018 +214a25adc54636fc|2023-05-18--10-45-47--1 +# HONDA ACCORD 2018 +1ebe446c9f466f50|2023-05-16--03-37-24--1 +# HONDA ACCORD 2018 +0bbb933eda8ae17c|2023-07-01--20-27-36--179 +# HONDA ACCORD 2018 +2e08aac41ed464a6|2023-07-31--14-35-02--3 +# HONDA ACCORD 2018 +2ca8270fc59b50f3|2023-06-23--07-59-23--5 +# HONDA ACCORD 2018 +39ac3639fcffc102|2023-07-20--21-06-28--268 +# HONDA ACCORD 2018 +37b721607b521682|2023-07-20--15-09-59--25 +# HONDA ACCORD 2018 +3d151bec9fd04d09|2023-07-25--16-06-41--8 +# HONDA ACCORD 2018 +3b417dee7be1d8dd|2023-07-06--06-11-05--26 +# HONDA ACCORD 2018 +49c7b83d348197ed|2023-07-24--21-19-42--2 +# HONDA ACCORD 2018 +4ff67da1be2f4f43|2023-05-12--21-10-12--12 +# HONDA ACCORD 2018 +5e7e1a7c1d61b456|2023-06-19--19-36-24--60 +# HONDA ACCORD 2018 +69db8ee3bf677945|2023-07-24--21-17-32--74 +# HONDA ACCORD 2018 +73dbd685214c0e03|2023-06-01--12-47-34--67 +# HONDA ACCORD 2018 +7dde4489ff0a6c80|2023-06-07--20-10-09--6 +# HONDA ACCORD 2018 +82d1e3d3c754bf2a|2023-05-16--08-21-26--2 +# HONDA ACCORD 2018 +80d45cf838f8c716|2023-07-17--16-29-49--6 +# HONDA ACCORD 2018 +889163fc61871a68|2023-05-16--17-18-58--5 +# HONDA ACCORD 2018 +8b22d387ab08c5db|2023-07-15--21-35-09--2 +# HONDA ACCORD 2018 +8aaa7ccc2fc68822|2023-07-09--20-09-02--1 +# HONDA ACCORD 2018 +90d95c7fd3fa748a|2023-06-16--14-04-08--61 +# HONDA ACCORD 2018 +9d8f86b8b11b65c9|2023-06-30--19-33-48--156 +# HONDA ACCORD 2018 +a33e427bbd337300|2023-07-12--09-54-45--12 +# HONDA ACCORD 2018 +a3669d37d7fe28c2|2023-06-01--17-08-16--2 +# HONDA ACCORD 2018 +a85202e1dca5afaf|2023-06-21--11-46-10--20 +# HONDA ACCORD 2018 +a454b11d7910c242|2023-06-14--16-11-49--25 +# HONDA ACCORD 2018 +aca10b5acd89289d|2023-07-12--20-03-23--4 +# HONDA ACCORD 2018 +b3a1a214664b7d31|2023-07-28--16-21-31--23 +# HONDA ACCORD 2018 +b9028def8e733ee6|2023-05-16--18-34-52--7 +# HONDA ACCORD 2018 +bf887c016d27cca5|2023-07-31--12-34-34--1 +# HONDA ACCORD 2018 +c642bd29f2858d75|2023-06-27--08-21-19--9 +# HONDA ACCORD 2018 +c2143a4f3723576c|2023-06-21--12-51-06--16 +# HONDA ACCORD 2018 +cfb71d30183708f8|2023-07-30--12-40-33--6 +# HONDA ACCORD 2018 +d09c814b908913a2|2023-06-13--19-19-07--16 +# HONDA ACCORD 2018 +d37dc158651867ca|2023-06-03--16-03-15--2 +# HONDA ACCORD 2018 +d83010e83c7f87ea|2023-05-24--15-15-58--20 +# HONDA ACCORD 2018 +d8f44985fa82e7f5|2023-05-10--22-40-13--4 +# HONDA ACCORD 2018 +eb6f3ff143d0fac5|2023-05-23--10-51-44--7 +# HONDA ACCORD 2018 +ee1874709eb8b485|2023-05-11--17-10-40--183 +# HONDA ACCORD 2018 +ef6f577d770521e4|2023-05-10--07-44-14--32 +# TOYOTA COROLLA 2017 +00acf2e4c8c6b549|2023-07-01--20-25-46--8 +# TOYOTA COROLLA 2017 +053f594b05527a80|2023-07-26--01-47-44--33 +# TOYOTA COROLLA 2017 +16a9664d939d9efe|2023-06-24--20-10-27--5 +# TOYOTA COROLLA 2017 +364bb492aa33d7df|2023-06-06--07-47-54--23 +# TOYOTA COROLLA 2017 +39932c340e596ead|2023-06-29--21-47-38--11 +# TOYOTA COROLLA 2017 +3c3ea5134c90308a|2023-06-22--22-11-10--4 +# TOYOTA COROLLA 2017 +5a596be432c5fe53|2023-06-11--17-10-36--38 +# TOYOTA COROLLA 2017 +728c59e1123e2cf7|2023-05-16--16-05-22--9 +# TOYOTA COROLLA 2017 +718042f01647e90e|2023-06-21--22-29-28--10 +# TOYOTA COROLLA 2017 +7d48b40fb8782bda|2023-08-05--13-16-29--23 +# TOYOTA COROLLA 2017 +7ec9410b593c7d5a|2023-06-29--17-29-56--19 +# TOYOTA COROLLA 2017 +869558002728e30b|2023-08-02--14-19-46--6 +# TOYOTA COROLLA 2017 +887e76d536c1841e|2023-07-06--07-17-09--12 +# TOYOTA COROLLA 2017 +993aa9f1c1e81499|2023-07-14--19-08-45--10 +# TOYOTA COROLLA 2017 +975cdde87029652a|2023-07-04--17-39-43--4 +# TOYOTA COROLLA 2017 +a152dad3c3368320|2023-05-19--14-16-10--47 +# TOYOTA COROLLA 2017 +a61d43139939b1ac|2023-05-29--11-20-51--3 +# TOYOTA COROLLA 2017 +adb85c50d47ac0a9|2023-05-14--20-29-11--1 +# TOYOTA COROLLA 2017 +b86a9aad74db6ec7|2023-07-14--16-25-56--7 +# TOYOTA COROLLA 2017 +b9fc453e3021b7ff|2023-05-23--15-16-18--3 +# TOYOTA COROLLA 2017 +bc7a33f454ca54e8|2023-06-13--22-23-55--10 +# TOYOTA COROLLA 2017 +d29979b337e5381c|2023-06-22--21-45-44--6 +# TOYOTA COROLLA 2017 +d3faefc00d1e3660|2023-06-02--19-59-19--30 +# TOYOTA COROLLA 2017 +d1e714006749bfa5|2023-06-02--14-50-02--2 +# TOYOTA COROLLA 2017 +cf700d069c05bba8|2023-07-13--16-25-32--1 +# TOYOTA COROLLA 2017 +d9abb1b68b7289ae|2023-07-21--18-47-15--1 +# TOYOTA COROLLA 2017 +d4c10d06c1bb7800|2023-07-16--21-41-26--54 +# TOYOTA COROLLA 2017 +d89badbe085c52c1|2023-05-13--22-32-35--16 +# TOYOTA COROLLA 2017 +ea53462ef36d4315|2023-05-13--10-56-42--8 +# TOYOTA COROLLA 2017 +e831c4e62fba9a0f|2023-07-16--18-27-58--109 +# TOYOTA COROLLA 2017 +f74a24ad37ed9773|2023-06-02--17-56-50--2 +# TOYOTA COROLLA 2017 +f467e0cd91910513|2023-07-12--14-53-24--7 +# TOYOTA COROLLA 2017 +fb0d04ba394c06f2|2023-05-21--17-58-49--9 +# NISSAN LEAF 2018 +0b17985326a570c4|2023-07-24--17-13-53--44 +# NISSAN LEAF 2018 +1dd434bd0ea8aaa4|2023-05-17--06-25-44--11 +# NISSAN LEAF 2018 +29a1b6293b68f2a9|2023-05-28--14-39-04--3 +# NISSAN LEAF 2018 +02cd1b196ec17045|2023-07-25--10-07-20--55 +# NISSAN LEAF 2018 +289d318fded3221a|2023-06-18--09-36-51--109 +# NISSAN LEAF 2018 +39bf496887ea52e5|2023-05-12--07-00-53--34 +# NISSAN LEAF 2018 +4a9d0cf499314bec|2023-05-25--08-01-49--6 +# NISSAN LEAF 2018 +4ed383d0670d4b71|2023-06-18--13-09-17--29 +# NISSAN LEAF 2018 +6b51011199473e01|2023-08-04--14-10-11--7 +# NISSAN LEAF 2018 +7605de164f235364|2023-07-10--16-02-26--2 +# NISSAN LEAF 2018 +9299dd7dadb9007e|2023-06-22--14-05-43--71 +# NISSAN LEAF 2018 +962c4e8ab4396060|2023-06-24--10-43-41--5 +# NISSAN LEAF 2018 +969dd380d52937c6|2023-07-18--21-02-34--1 +# NISSAN LEAF 2018 +ba9225dd390fe75e|2023-05-27--14-19-20--12 +# NISSAN LEAF 2018 +bc12abb1f8ec2243|2023-05-23--16-17-37--4 +# NISSAN LEAF 2018 +c0516da831df9eaf|2023-07-14--16-54-04--3 +# NISSAN LEAF 2018 +bd349df2aad3c6fc|2023-07-11--08-00-00--25 +# NISSAN LEAF 2018 +b9a45053d2ded48b|2023-07-27--05-17-46--16 +# NISSAN LEAF 2018 +d045889f89a2b9a5|2023-07-21--12-27-36--13 +# ACURA RDX 2020 +1943107bbdc1070e|2023-05-14--20-02-24--108 +# ACURA RDX 2020 +23846edb2f7988e3|2023-06-09--21-02-00--65 +# ACURA RDX 2020 +9d3a5a3049d6c50d|2023-05-23--14-03-48--4 +# ACURA RDX 2020 +f8d72ec3768bc1f1|2023-07-19--19-05-48--11 +# ACURA RDX 2020 +fd5000ecde671462|2023-06-06--18-03-06--19 +# TOYOTA HIGHLANDER 2020 +144a496ccff4a0b4|2023-07-25--16-51-08--13 +# TOYOTA HIGHLANDER 2020 +0d44dc6722628b26|2023-06-19--09-17-31--8 +# TOYOTA HIGHLANDER 2020 +29e4d80dc9a37da5|2023-07-14--08-52-21--6 +# TOYOTA HIGHLANDER 2020 +2378eb8397a2b782|2023-05-13--18-10-35--48 +# TOYOTA HIGHLANDER 2020 +24bef3a2265d4af2|2023-06-05--08-39-30--4 +# TOYOTA HIGHLANDER 2020 +004e41c4761b3bf6|2023-05-11--16-02-55--15 +# TOYOTA HIGHLANDER 2020 +343e82c046c8f6dc|2023-05-30--16-07-55--21 +# TOYOTA HIGHLANDER 2020 +3ffc7b8fd385a504|2023-06-18--13-55-18--3 +# TOYOTA HIGHLANDER 2020 +41860f9bcb6f44b8|2023-07-09--12-52-21--24 +# TOYOTA HIGHLANDER 2020 +3d51bfc7ff880232|2023-05-11--17-34-52--13 +# TOYOTA HIGHLANDER 2020 +4d9d41e34fd9dd71|2023-06-18--13-21-37--15 +# TOYOTA HIGHLANDER 2020 +521a0922e3a04935|2023-05-13--18-45-20--44 +# TOYOTA HIGHLANDER 2020 +55c9f8b884d1db87|2023-06-24--09-58-10--4 +# TOYOTA HIGHLANDER 2020 +5c87f40f937ed46e|2023-06-17--23-40-13--16 +# TOYOTA HIGHLANDER 2020 +5fe239629c1a6cc6|2023-05-25--10-35-55--5 +# TOYOTA HIGHLANDER 2020 +597a8b0eb0c8853b|2023-07-12--12-38-41--2 +# TOYOTA HIGHLANDER 2020 +68863076c79b6e46|2023-07-18--18-27-05--2 +# TOYOTA HIGHLANDER 2020 +68dfa9ee803399d1|2023-06-16--16-12-34--62 +# TOYOTA HIGHLANDER 2020 +6c4eb3920653c33f|2023-06-11--17-26-48--38 +# TOYOTA HIGHLANDER 2020 +709398cb20ec2c8d|2023-07-31--11-04-29--1 +# TOYOTA HIGHLANDER 2020 +702527f5122b8600|2023-07-04--21-51-58--32 +# TOYOTA HIGHLANDER 2020 +71b0f13abdc777f0|2023-06-25--12-30-46--1 +# TOYOTA HIGHLANDER 2020 +75157fa04b7760e2|2023-06-18--14-13-08--8 +# TOYOTA HIGHLANDER 2020 +7332469da3c215b9|2023-06-30--16-06-09--23 +# TOYOTA HIGHLANDER 2020 +7a8dc1b623ec968b|2023-06-26--13-19-39--46 +# TOYOTA HIGHLANDER 2020 +7aead72b15132868|2023-08-07--15-32-55--22 +# TOYOTA HIGHLANDER 2020 +82d9c4c8a45c33d3|2023-07-16--10-29-19--6 +# TOYOTA HIGHLANDER 2020 +85f0cc9d2a7783e5|2023-07-06--15-06-13--2 +# TOYOTA HIGHLANDER 2020 +8527a913671bf82b|2023-07-29--11-52-54--36 +# TOYOTA HIGHLANDER 2020 +84050035bc8a4693|2023-06-14--09-20-16--27 +# TOYOTA HIGHLANDER 2020 +878a25353867b7e1|2023-06-04--19-13-19--5 +# TOYOTA HIGHLANDER 2020 +91eefbd00e06a375|2023-05-21--13-02-56--149 +# TOYOTA HIGHLANDER 2020 +8efd012fc8bc01ed|2023-05-13--13-33-26--16 +# TOYOTA HIGHLANDER 2020 +962482e363d8db53|2023-06-13--15-07-46--189 +# TOYOTA HIGHLANDER 2020 +9ef0941be9f8057d|2023-07-11--17-55-34--1 +# TOYOTA HIGHLANDER 2020 +a2c22070a4a86296|2023-05-17--20-50-51--1 +# TOYOTA HIGHLANDER 2020 +9dce1db48e723a7d|2023-05-22--20-05-34--4 +# TOYOTA HIGHLANDER 2020 +b39c8956c329f098|2023-07-01--15-32-06--8 +# TOYOTA HIGHLANDER 2020 +b67488601fc02963|2023-06-09--13-23-41--20 +# TOYOTA HIGHLANDER 2020 +b75bae9b9bde6210|2023-07-30--08-16-42--46 +# TOYOTA HIGHLANDER 2020 +ba14fa06ffd18df7|2023-06-10--21-16-42--6 +# TOYOTA HIGHLANDER 2020 +bf17b81eba9bf96e|2023-06-09--12-08-11--4 +# TOYOTA HIGHLANDER 2020 +b42bff5ee5d24c72|2023-08-07--17-03-15--29 +# TOYOTA HIGHLANDER 2020 +c006eb73d0b11b29|2023-07-30--12-03-27--62 +# TOYOTA HIGHLANDER 2020 +ce24faef3afe2803|2023-05-17--14-50-24--31 +# TOYOTA HIGHLANDER 2020 +d45a24d7a5a78a2f|2023-05-18--19-16-17--42 +# TOYOTA HIGHLANDER 2020 +d13b3d6d7d5529cf|2023-06-02--17-59-00--7 +# TOYOTA HIGHLANDER 2020 +e0001dc12a80b287|2023-07-05--08-10-47--31 +# TOYOTA HIGHLANDER 2020 +ec46c46b25ceac9c|2023-05-17--09-09-32--10 +# TOYOTA HIGHLANDER 2020 +eda8da0edd1c99c9|2023-07-23--13-03-07--9 +# TOYOTA HIGHLANDER 2020 +f2a06f696f9517b3|2023-07-06--13-58-37--7 +# TOYOTA HIGHLANDER 2020 +f5e4b280d1756282|2023-07-18--09-58-12--7 +# TOYOTA HIGHLANDER 2020 +f50cf090ee700251|2023-08-02--15-21-29--5 +# TOYOTA HIGHLANDER 2020 +f96a58a51695b2ce|2023-06-23--20-54-30--18 +# TOYOTA HIGHLANDER 2020 +f60c2e0e7fd95935|2023-05-15--10-15-08--2 +# TOYOTA HIGHLANDER 2020 +f9ea0ffa53d5759a|2023-06-28--10-59-17--5 +# TOYOTA HIGHLANDER 2020 +fd23445cb8537751|2023-07-30--13-32-59--17 +# TOYOTA COROLLA TSS2 2019 +09469776862f3ab8|2023-07-16--15-55-22--17 +# TOYOTA COROLLA TSS2 2019 +075b133b6181e058|2023-07-28--20-07-44--3 +# TOYOTA COROLLA TSS2 2019 +0fbfcf01e4882a83|2023-05-30--15-16-34--6 +# TOYOTA COROLLA TSS2 2019 +0e12554bfe8687d3|2023-07-04--11-36-31--2 +# TOYOTA COROLLA TSS2 2019 +0921b5e7de3ae0b5|2023-05-24--11-51-14--13 +# TOYOTA COROLLA TSS2 2019 +14a8b23f850f4d11|2023-06-12--15-23-21--34 +# TOYOTA COROLLA TSS2 2019 +0fe5135182d67910|2023-05-19--15-08-54--9 +# TOYOTA COROLLA TSS2 2019 +213b44717a9bc58e|2023-07-18--17-09-13--17 +# TOYOTA COROLLA TSS2 2019 +08d7726c5efb3caa|2023-08-01--09-27-21--20 +# TOYOTA COROLLA TSS2 2019 +182caf5dcf20ca16|2023-05-21--15-13-55--226 +# TOYOTA COROLLA TSS2 2019 +0a4445a705516261|2023-06-23--19-18-06--1 +# TOYOTA COROLLA TSS2 2019 +1d0e096df3cecedd|2023-05-31--17-44-20--25 +# TOYOTA COROLLA TSS2 2019 +21788d8d115dfff4|2023-06-02--21-11-27--18 +# TOYOTA COROLLA TSS2 2019 +2b967c9ee4146686|2023-07-04--12-18-13--76 +# TOYOTA COROLLA TSS2 2019 +2ddc8f97834a7e52|2023-06-17--13-56-27--150 +# TOYOTA COROLLA TSS2 2019 +376abd6a7d6c6fa0|2023-08-05--22-10-41--14 +# TOYOTA COROLLA TSS2 2019 +33833d235dea00c8|2023-05-10--15-37-53--27 +# TOYOTA COROLLA TSS2 2019 +39977e9eacdfebb6|2023-07-31--13-31-52--4 +# TOYOTA COROLLA TSS2 2019 +3eb4c34a2a663c37|2023-07-20--11-54-00--36 +# TOYOTA COROLLA TSS2 2019 +3d9c00d3509fd1a5|2023-05-17--12-46-23--1 +# TOYOTA COROLLA TSS2 2019 +3d2b038d1276f564|2023-07-09--12-35-09--14 +# TOYOTA COROLLA TSS2 2019 +421d8e266db99689|2023-08-07--21-14-05--17 +# TOYOTA COROLLA TSS2 2019 +4f50e44908cc46b8|2023-07-28--11-21-40--6 +# TOYOTA COROLLA TSS2 2019 +54a0066de4f6aa53|2023-05-11--07-56-38--15 +# TOYOTA COROLLA TSS2 2019 +60dcd78f23ffcb45|2023-05-31--20-57-42--216 +# TOYOTA COROLLA TSS2 2019 +669372fc0cdbad34|2023-06-22--16-48-24--69 +# TOYOTA COROLLA TSS2 2019 +6ca6cd014b18339b|2023-06-09--20-14-34--30 +# TOYOTA COROLLA TSS2 2019 +6c7b3c70cde5154a|2023-08-08--08-49-34--8 +# TOYOTA COROLLA TSS2 2019 +77bc3a1ef88b0f8c|2023-05-10--13-34-25--3 +# TOYOTA COROLLA TSS2 2019 +7fa981d6c0f04ab5|2023-05-11--07-24-47--15 +# TOYOTA COROLLA TSS2 2019 +80e58d853114e409|2023-06-21--18-02-42--11 +# TOYOTA COROLLA TSS2 2019 +8d23badbf0a9ea4b|2023-07-08--16-39-30--11 +# TOYOTA COROLLA TSS2 2019 +885386596e3eeb9d|2023-08-01--12-35-23--329 +# TOYOTA COROLLA TSS2 2019 +9d7fa9fa4e27966b|2023-07-09--06-25-37--20 +# TOYOTA COROLLA TSS2 2019 +a9e171cea6aa8261|2023-08-04--19-47-40--278 +# TOYOTA COROLLA TSS2 2019 +acd2094a4e29a830|2023-05-23--07-47-56--1 +# TOYOTA COROLLA TSS2 2019 +b4776f404cd487b0|2023-06-30--19-23-05--54 +# TOYOTA COROLLA TSS2 2019 +b0a7a22dea55a1cd|2023-05-28--12-39-18--29 +# TOYOTA COROLLA TSS2 2019 +b49892b434816269|2023-05-16--06-38-31--74 +# TOYOTA COROLLA TSS2 2019 +b41c77a268a0a16f|2023-06-11--11-51-19--2 +# TOYOTA COROLLA TSS2 2019 +bf8377a19ba31955|2023-06-10--16-34-28--28 +# TOYOTA COROLLA TSS2 2019 +c188b4341879aa18|2023-07-12--19-49-05--19 +# TOYOTA COROLLA TSS2 2019 +c1c8b3b7eaef25cc|2023-05-30--16-59-41--5 +# TOYOTA COROLLA TSS2 2019 +bb3106a9271328e3|2023-07-05--10-13-36--2 +# TOYOTA COROLLA TSS2 2019 +c7400d04331ac3ee|2023-05-26--18-06-31--74 +# TOYOTA COROLLA TSS2 2019 +c8aa3fdad5cec446|2023-05-16--12-07-55--12 +# TOYOTA COROLLA TSS2 2019 +cc379727a2ad9378|2023-07-22--19-16-50--38 +# TOYOTA COROLLA TSS2 2019 +cd34344665bc1a4a|2023-05-17--15-03-28--11 +# TOYOTA COROLLA TSS2 2019 +d20ec114453feac2|2023-05-16--17-39-43--7 +# TOYOTA COROLLA TSS2 2019 +e0aaaef2be9cd155|2023-05-25--21-22-33--63 +# TOYOTA COROLLA TSS2 2019 +edf29b3d6d15be9a|2023-06-12--20-14-03--5 +# TOYOTA COROLLA TSS2 2019 +ecebb0b63434e2f2|2023-07-06--12-35-59--76 +# TOYOTA COROLLA TSS2 2019 +f4d4cc62cc517acd|2023-06-17--12-14-02--3 +# TOYOTA RAV4 2022 +1e0487c8a03931a1|2023-07-17--17-11-07--14 +# TOYOTA RAV4 2022 +1c16ee70deee2972|2023-07-30--07-37-27--18 +# TOYOTA RAV4 2022 +23e0360acaefab4d|2023-06-22--08-05-05--44 +# TOYOTA RAV4 2022 +34fd9fa52bd9065f|2023-07-24--03-59-34--30 +# TOYOTA RAV4 2022 +3ab818cfeff024c4|2023-07-01--13-12-38--75 +# TOYOTA RAV4 2022 +3af132f650bd6b72|2023-06-02--17-34-32--33 +# TOYOTA RAV4 2022 +4d13f4feeb6a3d94|2023-07-01--11-24-38--34 +# TOYOTA RAV4 2022 +6228706487b4b0ea|2023-06-10--21-21-52--23 +# TOYOTA RAV4 2022 +6a2f4f5164a97fcd|2023-08-06--13-16-57--9 +# TOYOTA RAV4 2022 +7ac1ec97ce175121|2023-06-20--17-31-53--11 +# TOYOTA RAV4 2022 +868f770ac624c5dd|2023-06-27--09-15-06--67 +# TOYOTA RAV4 2022 +a5c341bb250ca2f0|2023-06-29--20-25-11--20 +# TOYOTA RAV4 2022 +dfb11f122b6fa282|2023-06-12--18-21-56--11 +# TOYOTA RAV4 2022 +f0a34b105563fa46|2023-08-01--15-32-05--14 +# TOYOTA RAV4 2022 +fa92d93019ed70bd|2023-07-07--01-12-37--17 +# HYUNDAI SANTA FE HYBRID 2022 +129db7c75bce8445|2023-08-05--17-41-16--24 +# HYUNDAI SANTA FE HYBRID 2022 +34397231b0958def|2023-06-10--12-21-46--18 +# HYUNDAI SANTA FE HYBRID 2022 +826b9eb4ac54a1c2|2023-07-08--19-03-34--4 +# TOYOTA HIGHLANDER 2020 +15af9b43bd0c5c76|2023-05-31--09-50-40--92 +# TOYOTA HIGHLANDER 2020 +0bf0ea192bb9cb3c|2023-07-19--13-04-59--24 +# TOYOTA HIGHLANDER 2020 +1c7b969c6660a3dd|2023-05-17--08-13-27--12 +# TOYOTA HIGHLANDER 2020 +29320b5f71353a26|2023-05-14--14-02-25--172 +# TOYOTA HIGHLANDER 2020 +2194b752a88786ac|2023-06-28--09-49-00--9 +# TOYOTA HIGHLANDER 2020 +0e9cc31bf324bed7|2023-07-16--15-18-39--110 +# TOYOTA HIGHLANDER 2020 +27444eac005fc311|2023-08-06--10-13-53--30 +# TOYOTA HIGHLANDER 2020 +2d823e45e0ba7a60|2023-07-11--17-55-38--4 +# TOYOTA HIGHLANDER 2020 +2f831f2ea3eff892|2023-07-17--18-59-16--21 +# TOYOTA HIGHLANDER 2020 +2ee40dc08b5c8680|2023-06-30--18-47-36--52 +# TOYOTA HIGHLANDER 2020 +2f475f484c7e48a4|2023-08-02--09-30-22--2 +# TOYOTA HIGHLANDER 2020 +333605df930e96c4|2023-05-27--12-18-04--1 +# TOYOTA HIGHLANDER 2020 +339a81aefecd3618|2023-08-02--07-10-36--28 +# TOYOTA HIGHLANDER 2020 +368455a0f08f4fec|2023-06-12--16-57-54--4 +# TOYOTA HIGHLANDER 2020 +3dca779f9f65c640|2023-07-26--17-31-54--19 +# TOYOTA HIGHLANDER 2020 +4868775dfada5a32|2023-06-07--09-36-34--4 +# TOYOTA HIGHLANDER 2020 +4a90db58c3f57afa|2023-07-29--17-34-55--42 +# TOYOTA HIGHLANDER 2020 +4e4e4789d5691a95|2023-07-28--18-47-17--8 +# TOYOTA HIGHLANDER 2020 +5647a5fa25085f0d|2023-08-07--14-10-54--13 +# TOYOTA HIGHLANDER 2020 +5f040438a009d6cb|2023-06-22--16-24-51--4 +# TOYOTA HIGHLANDER 2020 +6f6f526b4932d88b|2023-07-02--16-24-30--58 +# TOYOTA HIGHLANDER 2020 +6d0254ba44b664b0|2023-07-08--14-38-16--6 +# TOYOTA HIGHLANDER 2020 +76ced8f2f99250a6|2023-06-02--10-26-47--6 +# TOYOTA HIGHLANDER 2020 +8c1b23fe1568c036|2023-05-19--08-29-02--17 +# TOYOTA HIGHLANDER 2020 +9179d81377e52625|2023-06-30--16-49-47--109 +# TOYOTA HIGHLANDER 2020 +a474346bf635c3de|2023-06-10--17-49-02--17 +# TOYOTA HIGHLANDER 2020 +a023b41cc944b482|2023-06-25--08-55-36--4 +# TOYOTA HIGHLANDER 2020 +b557c584db633c06|2023-08-02--18-49-35--2 +# TOYOTA HIGHLANDER 2020 +b60de7fd1272d92c|2023-06-18--09-59-29--18 +# TOYOTA HIGHLANDER 2020 +b5e1be1336e936f9|2023-08-07--17-15-34--11 +# TOYOTA HIGHLANDER 2020 +caef64381b29fb3d|2023-07-19--17-27-45--3 +# TOYOTA HIGHLANDER 2020 +c21d5b4c2d8ac085|2023-06-29--07-51-21--1 +# TOYOTA HIGHLANDER 2020 +c7ae3dc86bba4525|2023-08-03--07-29-09--7 +# TOYOTA HIGHLANDER 2020 +ce3075423a164945|2023-05-27--10-28-48--4 +# TOYOTA HIGHLANDER 2020 +d173f04200e837a9|2023-05-13--12-34-10--4 +# TOYOTA HIGHLANDER 2020 +cf748e7031d411c8|2023-05-26--12-43-40--9 +# TOYOTA HIGHLANDER 2020 +d1fd12becb0bf3e2|2023-07-24--16-10-54--96 +# TOYOTA HIGHLANDER 2020 +d5d0b683a9a2ddf2|2023-07-24--18-36-30--9 +# TOYOTA HIGHLANDER 2020 +dc11867167a958d8|2023-06-09--18-49-38--50 +# TOYOTA HIGHLANDER 2020 +dc0f8f4f52442d48|2023-08-01--23-46-46--75 +# TOYOTA HIGHLANDER 2020 +df6ed1e430d585cc|2023-05-15--09-23-49--1 +# TOYOTA HIGHLANDER 2020 +e2ac4cd64bc32dd3|2023-07-31--20-24-01--27 +# TOYOTA HIGHLANDER 2020 +e3cf2794859fd8ea|2023-08-06--10-07-23--28 +# TOYOTA HIGHLANDER 2020 +e6f4a2f13554c77d|2023-05-19--14-17-11--3 +# TOYOTA HIGHLANDER 2020 +e01d0ee44be108b3|2023-05-16--12-17-48--9 +# TOYOTA HIGHLANDER 2020 +e8805c57d88ac65c|2023-06-26--15-03-36--47 +# TOYOTA HIGHLANDER 2020 +ea1b20c0286cb3e4|2023-07-12--09-14-26--34 +# TOYOTA HIGHLANDER 2020 +f20c2d8da930c25a|2023-07-02--16-03-24--33 +# TOYOTA HIGHLANDER 2020 +f57250843256cc1a|2023-05-24--18-01-00--2 +# TOYOTA HIGHLANDER 2020 +f5f17136be17692e|2023-05-30--14-50-39--6 +# TOYOTA HIGHLANDER 2020 +f7edb4b24e3b7321|2023-07-11--11-56-56--3 +# TOYOTA HIGHLANDER 2020 +ffe6475c53d1e78c|2023-07-11--17-56-32--55 +# TOYOTA HIGHLANDER 2020 +fe9f9a84fe26591c|2023-07-06--12-31-05--1 +# MAZDA CX-5 2022 +066b8ed7a80184fb|2023-06-13--23-33-37--62 +# MAZDA CX-5 2022 +1e11e59030d4757d|2023-07-17--12-16-44--1 +# MAZDA CX-5 2022 +05012d5566bf5275|2023-07-29--21-00-17--99 +# MAZDA CX-5 2022 +42ff4de626f8559b|2023-08-01--10-29-15--12 +# MAZDA CX-5 2022 +3b44bbb84058328a|2023-07-16--09-32-09--65 +# MAZDA CX-5 2022 +4ed535dd3ff18b2a|2023-06-05--16-36-49--3 +# MAZDA CX-5 2022 +76c17043c9df3064|2023-07-27--13-58-55--6 +# MAZDA CX-5 2022 +8c807f60018507d4|2023-07-26--09-20-15--16 +# MAZDA CX-5 2022 +8a9dac95d24c4e8d|2023-08-04--09-40-07--7 +# MAZDA CX-5 2022 +aa38b396675f5215|2023-06-28--08-47-57--8 +# MAZDA CX-5 2022 +b36f9b30a01c8521|2023-07-24--17-51-06--5 +# MAZDA CX-5 2022 +bdbbb819d8dc38ac|2023-06-09--07-48-08--63 +# MAZDA CX-5 2022 +c3ab14088c43bdf8|2023-06-30--21-42-12--1 +# MAZDA CX-5 2022 +c76c695d1b0485fe|2023-07-14--18-14-34--37 +# SUBARU IMPREZA SPORT 2020 +17250a2717728fb9|2023-07-20--07-38-29--18 +# SUBARU IMPREZA SPORT 2020 +22f2f49bcbecd829|2023-05-30--21-25-08--5 +# SUBARU IMPREZA SPORT 2020 +59755a6574d9ac67|2023-05-30--16-37-55--7 +# SUBARU IMPREZA SPORT 2020 +6024cc6844765678|2023-07-27--15-11-43--16 +# SUBARU IMPREZA SPORT 2020 +7be3f6b12cd49e4b|2023-06-20--13-50-03--93 +# SUBARU IMPREZA SPORT 2020 +d9df6f87e8feff94|2023-07-04--19-58-51--18 +# SUBARU IMPREZA SPORT 2020 +f900fccd457f495a|2023-05-26--20-18-12--36 +# HYUNDAI PALISADE 2020 +0cc137ccd450204c|2023-06-22--11-38-48--3 +# HYUNDAI PALISADE 2020 +1c5b0ef6f666062d|2023-06-02--08-57-58--2 +# HYUNDAI PALISADE 2020 +1336b7c61f4fba8b|2023-07-27--07-31-12--1 +# HYUNDAI PALISADE 2020 +2c63cbbbba450ba0|2023-06-18--23-59-14--24 +# HYUNDAI PALISADE 2020 +2f1f45af65b7b314|2023-05-30--19-30-46--12 +# HYUNDAI PALISADE 2020 +34ea9dfc9b0f9bbe|2023-05-21--12-38-47--7 +# HYUNDAI PALISADE 2020 +39070cb41aafdfc1|2023-07-05--23-15-41--2 +# HYUNDAI PALISADE 2020 +4c6b27a2c49c555e|2023-06-18--09-37-44--7 +# HYUNDAI PALISADE 2020 +4e5d75a1f3df3ae2|2023-06-09--02-25-39--74 +# HYUNDAI PALISADE 2020 +562a098bb9c7b922|2023-07-12--16-46-17--1 +# HYUNDAI PALISADE 2020 +628935d7d3e5f4f7|2023-05-24--19-48-58--8 +# HYUNDAI PALISADE 2020 +67a711f176acbbbf|2023-08-03--09-05-39--8 +# HYUNDAI PALISADE 2020 +7272d111d521a7bc|2023-05-22--09-21-09--1 +# HYUNDAI PALISADE 2020 +7b5a53e99b76e8d9|2023-06-14--14-55-32--15 +# HYUNDAI PALISADE 2020 +829fc01ecb03f524|2023-08-06--12-29-40--71 +# HYUNDAI PALISADE 2020 +7a6617bb650ac5f3|2023-06-02--14-13-59--31 +# HYUNDAI PALISADE 2020 +967360f5aae838e5|2023-05-18--23-59-21--1 +# HYUNDAI PALISADE 2020 +98025ffdb4d0d3ea|2023-06-03--02-55-53--33 +# HYUNDAI PALISADE 2020 +9a22857aff5535d8|2023-06-20--17-40-57--4 +# HYUNDAI PALISADE 2020 +9e7951200bd89ca3|2023-06-07--20-31-01--3 +# HYUNDAI PALISADE 2020 +a6e13aa41cb46ac4|2023-07-18--10-56-20--7 +# HYUNDAI PALISADE 2020 +c5f915f8d3049fd4|2023-07-15--09-57-02--1 +# HYUNDAI PALISADE 2020 +c502b178b93bcc57|2023-06-08--16-22-33--12 +# HYUNDAI PALISADE 2020 +c7d0d7dde77d49ce|2023-07-15--17-08-23--35 +# HYUNDAI PALISADE 2020 +d3bd16e6fc80062c|2023-05-11--10-24-46--4 +# HYUNDAI PALISADE 2020 +e0c6f1daf613f27e|2023-06-19--17-55-55--15 +# HYUNDAI PALISADE 2020 +ebdfcd4184611cfd|2023-08-04--12-56-10--1 +# HYUNDAI PALISADE 2020 +f4132dc91ccfa36a|2023-05-21--06-05-05--2 +# HYUNDAI PALISADE 2020 +fb3784f688906f36|2023-05-12--17-22-59--32 +# HONDA CR-V 2017 +1dd5f02533643f14|2023-06-03--12-17-36--8 +# HONDA CR-V 2017 +008d92ddb9798681|2023-06-18--12-41-21--8 +# HONDA CR-V 2017 +1b7349c28512586d|2023-07-14--18-42-54--26 +# HONDA CR-V 2017 +272caf9f22b2c59b|2023-06-18--12-51-26--22 +# HONDA CR-V 2017 +1069cd145e996003|2023-05-17--22-53-14--7 +# HONDA CR-V 2017 +2d03366246293eae|2023-05-31--17-40-01--9 +# HONDA CR-V 2017 +365b09442064886e|2023-07-24--10-34-12--9 +# HONDA CR-V 2017 +3bf8dc045bc9e677|2023-07-27--19-14-11--8 +# HONDA CR-V 2017 +40c808560e92c311|2023-07-19--17-39-48--5 +# HONDA CR-V 2017 +43e1963f8d94b15a|2023-07-15--18-32-25--8 +# HONDA CR-V 2017 +45fa8a98dc3bc264|2023-07-11--08-22-54--7 +# HONDA CR-V 2017 +50b4e56518f71489|2023-07-31--05-28-30--14 +# HONDA CR-V 2017 +562834cee8a360c0|2023-07-08--08-56-37--53 +# HONDA CR-V 2017 +5a3959d85bbde304|2023-07-18--17-04-29--31 +# HONDA CR-V 2017 +6b185836ee698c26|2023-07-07--20-52-24--7 +# HONDA CR-V 2017 +84b8b497d5e13b6a|2023-07-30--13-30-24--17 +# HONDA CR-V 2017 +846e6ba1cb8c5f85|2023-07-04--11-51-25--35 +# HONDA CR-V 2017 +89583b784eacd386|2023-06-24--23-32-36--1 +# HONDA CR-V 2017 +8faf799674fa044b|2023-07-18--19-49-14--15 +# HONDA CR-V 2017 +9732dc4fef24cf7a|2023-08-04--18-18-13--9 +# HONDA CR-V 2017 +a3fc26a4da829bb9|2023-05-28--14-21-54--39 +# HONDA CR-V 2017 +a9a580bdb154bb4d|2023-06-29--16-21-57--17 +# HONDA CR-V 2017 +b4f79d4e97360586|2023-07-29--16-32-40--16 +# HONDA CR-V 2017 +c40202b70807d4aa|2023-07-01--16-09-28--15 +# HONDA CR-V 2017 +c3d7cef4d9450951|2023-07-29--11-39-57--72 +# HONDA CR-V 2017 +c390b60ad96d2ff2|2023-07-10--16-40-16--5 +# HONDA CR-V 2017 +d33bc6acf39eb0d5|2023-08-04--10-30-07--18 +# HONDA CR-V 2017 +d360e36bf258dcd8|2023-07-20--18-11-51--29 +# HONDA CR-V 2017 +d26e907f37fcd37d|2023-06-29--07-04-20--2 +# HONDA CR-V 2017 +dcb2ee34f8c4c2be|2023-05-14--16-35-57--7 +# HONDA CR-V 2017 +e22ac98f691884e1|2023-08-02--17-22-36--3 +# HONDA CR-V 2017 +e69f2a903ed82e49|2023-06-27--19-39-46--8 +# HONDA CR-V 2017 +e8a630b87b2b0b7c|2023-07-21--16-31-16--12 +# HONDA CR-V 2017 +f1d6758277a8e2c3|2023-06-23--17-38-10--2 +# HONDA CR-V 2017 +f369374ecb30d9ad|2023-06-02--13-22-03--1 +# HONDA CR-V 2017 +ffa76986ec8e871e|2023-06-08--17-30-25--31 +# TOYOTA SIENNA 2018 +15141c10c47e840c|2023-08-06--19-46-46--2 +# TOYOTA SIENNA 2018 +033adba45e0f9e9e|2023-06-22--17-20-48--17 +# TOYOTA SIENNA 2018 +08aee1fd12dbcec9|2023-07-08--11-52-25--1 +# TOYOTA SIENNA 2018 +0401ca905fe1e3c9|2023-06-30--08-37-39--8 +# TOYOTA SIENNA 2018 +1bbce2b3aadea8fc|2023-07-04--21-48-31--12 +# TOYOTA SIENNA 2018 +13fbff4f559b022f|2023-07-28--12-53-45--76 +# TOYOTA SIENNA 2018 +336f30f83810c50a|2023-07-03--10-36-11--16 +# TOYOTA SIENNA 2018 +40a8bdeaeef71f2e|2023-07-12--09-25-54--4 +# TOYOTA SIENNA 2018 +4bd71e1011d03cb0|2023-07-31--15-09-23--8 +# TOYOTA SIENNA 2018 +5a2b996389025b8b|2023-07-09--20-07-13--168 +# TOYOTA SIENNA 2018 +66253de0fd139602|2023-08-03--17-10-18--12 +# TOYOTA SIENNA 2018 +6aa41b3f53b8dfbb|2023-07-16--11-13-32--15 +# TOYOTA SIENNA 2018 +6c4a3e1fb283f169|2023-06-15--16-59-16--2 +# TOYOTA SIENNA 2018 +78c139899b6152e7|2023-06-29--22-20-41--1 +# TOYOTA SIENNA 2018 +8624c343dda64ca1|2023-07-15--16-06-24--68 +# TOYOTA SIENNA 2018 +8c995b0a7884acaa|2023-06-01--12-29-57--40 +# TOYOTA SIENNA 2018 +96f32ba699f695d0|2023-08-02--13-17-17--9 +# TOYOTA SIENNA 2018 +a001f23b71be2971|2023-07-14--12-10-15--14 +# TOYOTA SIENNA 2018 +a5b340427848f1e3|2023-05-31--17-33-24--14 +# TOYOTA SIENNA 2018 +a8d3b0c452c29da7|2023-07-01--22-59-20--40 +# TOYOTA SIENNA 2018 +a7fde1302557afb0|2023-05-24--10-07-00--1 +# TOYOTA SIENNA 2018 +bd1e8f178842c492|2023-07-15--15-33-04--19 +# TOYOTA SIENNA 2018 +c793f2377f82673d|2023-06-10--15-19-02--5 +# TOYOTA SIENNA 2018 +ce728cfb301d0987|2023-07-23--16-23-48--38 +# TOYOTA SIENNA 2018 +dc352a2d23789b45|2023-07-19--14-12-21--106 +# TOYOTA SIENNA 2018 +e77aa024ac711986|2023-07-29--18-37-34--1 +# TOYOTA SIENNA 2018 +e7ada7e863132190|2023-06-07--11-54-54--25 +# TOYOTA SIENNA 2018 +e7831e2f6a8a1279|2023-07-18--20-20-56--10 +# TOYOTA SIENNA 2018 +efa518043b8f287e|2023-08-06--19-55-03--156 +# TOYOTA SIENNA 2018 +f258933135d07fc2|2023-07-08--12-05-44--5 +# TOYOTA SIENNA 2018 +f2a49af4f4758050|2023-08-06--08-52-58--22 +# TOYOTA SIENNA 2018 +ff4fdad9a9b183c2|2023-07-30--20-55-31--39 +# FORD EXPLORER 6TH GEN +0b91b433b9332780|2023-07-13--14-51-21--126 +# FORD EXPLORER 6TH GEN +4458bd61cf193dab|2023-07-28--12-22-12--435 +# FORD EXPLORER 6TH GEN +8e1bab39e558e773|2023-06-30--18-11-15--11 +# FORD EXPLORER 6TH GEN +f0709d2bc6ca451f|2023-05-24--12-29-22--31 +# FORD EXPLORER 6TH GEN +f166567f78fad32f|2023-06-23--22-48-43--23 +# TOYOTA HIGHLANDER 2017 +0a140f06ff5e5751|2023-06-22--17-41-43--18 +# TOYOTA HIGHLANDER 2017 +0e6f1a230ecf5dc9|2023-05-22--15-16-37--1 +# TOYOTA HIGHLANDER 2017 +1213650a719d1429|2023-08-06--16-21-48--16 +# TOYOTA HIGHLANDER 2017 +297518c3eb259e70|2023-05-15--13-27-34--2 +# TOYOTA HIGHLANDER 2017 +3a2ae9ef81244966|2023-07-20--15-56-17--65 +# TOYOTA HIGHLANDER 2017 +467419fc069b553e|2023-05-23--13-38-56--6 +# TOYOTA HIGHLANDER 2017 +4814b507cb35653c|2023-06-28--17-59-25--4 +# TOYOTA HIGHLANDER 2017 +4829a5573c5de536|2023-08-01--21-06-48--13 +# TOYOTA HIGHLANDER 2017 +4c486ce35e8dd3b4|2023-05-30--18-52-10--46 +# TOYOTA HIGHLANDER 2017 +6dabe682c1a8d437|2023-07-07--14-25-46--9 +# TOYOTA HIGHLANDER 2017 +7c8bb6201903618b|2023-07-08--08-18-26--22 +# TOYOTA HIGHLANDER 2017 +7bd25a6c7427cd3c|2023-08-06--10-56-19--20 +# TOYOTA HIGHLANDER 2017 +832d14f92ad84eb6|2023-05-17--10-51-58--18 +# TOYOTA HIGHLANDER 2017 +8a2f77d0f2d45965|2023-06-14--16-51-15--52 +# TOYOTA HIGHLANDER 2017 +8b9d7d2d35e6118c|2023-08-04--15-19-14--2 +# TOYOTA HIGHLANDER 2017 +92e13d6c269f512d|2023-05-13--19-58-04--1 +# TOYOTA HIGHLANDER 2017 +9cea9d0468eb3e96|2023-06-22--22-20-21--6 +# TOYOTA HIGHLANDER 2017 +9a6357ba59f0bc3d|2023-06-10--09-52-06--4 +# TOYOTA HIGHLANDER 2017 +a6f5c094b5b7fb33|2023-06-16--07-29-15--1 +# TOYOTA HIGHLANDER 2017 +ad8f2bf6b31dce85|2023-07-29--17-39-45--16 +# TOYOTA HIGHLANDER 2017 +aa7ed46cc8131f89|2023-05-29--07-13-22--9 +# TOYOTA HIGHLANDER 2017 +d886ae895cef77ef|2023-08-02--12-36-12--19 +# TOYOTA HIGHLANDER 2017 +d481bf9699bde1ee|2023-07-06--01-52-18--2 +# TOYOTA HIGHLANDER 2017 +dca9566a6850e4bf|2023-05-14--17-12-55--5 +# TOYOTA HIGHLANDER 2017 +dfe7ead74bb47dc8|2023-08-07--10-26-51--6 +# TOYOTA HIGHLANDER 2017 +e521d97f331b2e34|2023-07-12--13-42-10--33 +# TOYOTA HIGHLANDER 2017 +f01b5b7d7f4c5309|2023-07-01--01-34-34--23 +# TOYOTA HIGHLANDER 2017 +fe99b3a8c9ab61b9|2023-06-18--14-21-37--5 +# TOYOTA PRIUS TSS2 2021 +10a42f77b05a401f|2023-06-23--17-30-35--8 +# TOYOTA PRIUS TSS2 2021 +1a35342c8a1b558e|2023-06-26--21-28-43--18 +# TOYOTA PRIUS TSS2 2021 +0377091bf159038d|2023-06-18--17-04-20--23 +# TOYOTA PRIUS TSS2 2021 +135321a6baf43ec3|2023-07-19--06-07-57--21 +# TOYOTA PRIUS TSS2 2021 +0e511ea80aaf4931|2023-06-05--05-54-38--3 +# TOYOTA PRIUS TSS2 2021 +2061c2bef508176e|2023-06-20--17-00-45--2 +# TOYOTA PRIUS TSS2 2021 +1128edc391bf47c1|2023-05-19--18-10-40--14 +# TOYOTA PRIUS TSS2 2021 +233ef9dcd57e63d9|2023-07-27--15-19-23--10 +# TOYOTA PRIUS TSS2 2021 +1531d4305c9ebbf0|2023-05-18--14-52-53--31 +# TOYOTA PRIUS TSS2 2021 +115345214029cb8b|2023-06-25--14-58-20--2 +# TOYOTA PRIUS TSS2 2021 +283695e2bd4b03db|2023-07-18--22-52-41--5 +# TOYOTA PRIUS TSS2 2021 +305006f2b633be2d|2023-07-16--12-48-12--4 +# TOYOTA PRIUS TSS2 2021 +39a1e6521e802f2f|2023-05-24--17-16-54--1 +# TOYOTA PRIUS TSS2 2021 +3aea2f5376c16768|2023-07-17--05-21-08--25 +# TOYOTA PRIUS TSS2 2021 +449ac093304ba731|2023-05-11--11-14-03--40 +# TOYOTA PRIUS TSS2 2021 +451be4fe585fdac0|2023-06-16--16-08-55--5 +# TOYOTA PRIUS TSS2 2021 +45937213b62ce5ed|2023-05-23--15-56-35--166 +# TOYOTA PRIUS TSS2 2021 +53ecc962c9d86d50|2023-07-30--10-26-25--2 +# TOYOTA PRIUS TSS2 2021 +5b12a3ea4e95c4a5|2023-06-22--17-16-55--37 +# TOYOTA PRIUS TSS2 2021 +656a02ec772a7a4d|2023-06-30--01-33-46--34 +# TOYOTA PRIUS TSS2 2021 +60f3f8039fafd263|2023-05-18--17-30-08--16 +# TOYOTA PRIUS TSS2 2021 +698cf41e2173752f|2023-06-30--12-01-37--12 +# TOYOTA PRIUS TSS2 2021 +67344e48576a3ac2|2023-07-21--14-44-32--18 +# TOYOTA PRIUS TSS2 2021 +6ba67d5a83d831a8|2023-06-06--18-34-35--1 +# TOYOTA PRIUS TSS2 2021 +714dd3f9e708f73c|2023-06-14--14-51-51--6 +# TOYOTA PRIUS TSS2 2021 +716a982c6d0c5547|2023-07-25--11-17-26--30 +# TOYOTA PRIUS TSS2 2021 +6e90fb55f908940a|2023-05-10--17-32-34--3 +# TOYOTA PRIUS TSS2 2021 +8550ea8a4e07f761|2023-06-24--06-29-29--4 +# TOYOTA PRIUS TSS2 2021 +868ec8b032712e8c|2023-05-17--10-32-22--36 +# TOYOTA PRIUS TSS2 2021 +9048498ebc1297b3|2023-05-22--20-36-01--6 +# TOYOTA PRIUS TSS2 2021 +91ec51ef841d0fe5|2023-08-01--09-03-49--4 +# TOYOTA PRIUS TSS2 2021 +a0adc8b389da9563|2023-07-16--17-39-14--1 +# TOYOTA PRIUS TSS2 2021 +a2e5f1439e2cdf9e|2023-05-26--08-13-31--13 +# TOYOTA PRIUS TSS2 2021 +a8fec02c41697f7c|2023-07-12--16-54-45--7 +# TOYOTA PRIUS TSS2 2021 +a883325ac00c65f9|2023-05-28--18-17-32--18 +# TOYOTA PRIUS TSS2 2021 +aaf71ff1348f4b42|2023-06-09--09-09-07--4 +# TOYOTA PRIUS TSS2 2021 +a74cb70b7a19e427|2023-06-11--13-12-21--62 +# TOYOTA PRIUS TSS2 2021 +ac1a320cbefd424a|2023-06-20--15-09-25--12 +# TOYOTA PRIUS TSS2 2021 +aedf9ebed7828264|2023-05-16--18-52-09--5 +# TOYOTA PRIUS TSS2 2021 +b8622cf559d979f9|2023-06-09--14-40-58--2 +# TOYOTA PRIUS TSS2 2021 +b4ce4d1721db5c94|2023-06-18--13-33-24--32 +# TOYOTA PRIUS TSS2 2021 +bf3057bccc689886|2023-05-10--14-25-33--4 +# TOYOTA PRIUS TSS2 2021 +c1a2ba00c8f7e9d8|2023-07-31--14-06-34--2 +# TOYOTA PRIUS TSS2 2021 +ba7f87150ae0bbeb|2023-06-21--13-33-28--12 +# TOYOTA PRIUS TSS2 2021 +c363f25afff8d58e|2023-05-16--14-35-12--8 +# TOYOTA PRIUS TSS2 2021 +c3834a2fe82b632b|2023-07-18--18-50-19--8 +# TOYOTA PRIUS TSS2 2021 +cbe57b408a885627|2023-07-09--11-00-32--5 +# TOYOTA PRIUS TSS2 2021 +ccda673780fb737f|2023-05-21--12-39-40--2 +# TOYOTA PRIUS TSS2 2021 +c4e58bbe953ef5c9|2023-07-27--10-23-32--13 +# TOYOTA PRIUS TSS2 2021 +cf8446aa9d2793e8|2023-06-04--22-02-12--14 +# TOYOTA PRIUS TSS2 2021 +d2bfce9a4caff67f|2023-07-12--15-21-04--55 +# TOYOTA PRIUS TSS2 2021 +d083dc54dae836f0|2023-05-23--05-01-18--24 +# TOYOTA PRIUS TSS2 2021 +d653e1fe9aced0bb|2023-05-19--16-19-28--10 +# TOYOTA PRIUS TSS2 2021 +d67fb9ab2b635dc9|2023-05-12--21-49-32--13 +# TOYOTA PRIUS TSS2 2021 +dd39308405abab68|2023-06-03--08-04-58--51 +# TOYOTA PRIUS TSS2 2021 +e65253687b3999e0|2023-07-02--08-32-02--2 +# TOYOTA PRIUS TSS2 2021 +e921feb7a05eb6b2|2023-08-06--14-08-10--53 +# TOYOTA PRIUS TSS2 2021 +ef4fae77e5d45d9d|2023-07-23--13-18-02--4 +# TOYOTA PRIUS TSS2 2021 +f0a29b63232a3fbd|2023-07-20--07-10-56--30 +# TOYOTA PRIUS TSS2 2021 +faf6d8bcab5ae3a1|2023-07-05--16-00-03--6 +# TOYOTA PRIUS TSS2 2021 +fe2feb102f0b3824|2023-07-31--15-55-42--88 +# TOYOTA PRIUS TSS2 2021 +fed47dc1d49625ca|2023-06-11--13-37-17--5 +# TOYOTA RAV4 2022 +170e10c2cb0432dd|2023-05-17--11-35-52--52 +# TOYOTA RAV4 2022 +0dbef6854d19f908|2023-05-14--16-48-10--34 +# TOYOTA RAV4 2022 +2475fb3eb2ffcc2e|2023-08-05--15-20-42--48 +# TOYOTA RAV4 2022 +08583cb7cd02965d|2023-07-13--14-00-59--23 +# TOYOTA RAV4 2022 +255d0a53069b33c7|2023-05-16--07-12-07--33 +# TOYOTA RAV4 2022 +3507bf7e7573d50b|2023-08-05--15-18-07--44 +# TOYOTA RAV4 2022 +4c7c30edb6dffa5f|2023-08-04--18-14-42--46 +# TOYOTA RAV4 2022 +4e9c8dcbfedefc48|2023-08-07--19-19-04--1 +# TOYOTA RAV4 2022 +58138d1ad389f4d0|2023-07-24--19-33-45--11 +# TOYOTA RAV4 2022 +5374d1774eac5197|2023-06-14--11-26-16--3 +# TOYOTA RAV4 2022 +558928e2034bcef7|2023-06-09--14-26-37--14 +# TOYOTA RAV4 2022 +5bf05f6701c98d32|2023-06-30--13-01-19--22 +# TOYOTA RAV4 2022 +617492c124a692ef|2023-07-20--14-19-10--6 +# TOYOTA RAV4 2022 +6bd14dfc84131769|2023-06-22--13-55-05--82 +# TOYOTA RAV4 2022 +6fe3baa907616d50|2023-05-22--17-36-04--9 +# TOYOTA RAV4 2022 +73f49c9e89a98ff9|2023-06-03--21-51-04--5 +# TOYOTA RAV4 2022 +77f07def1eec9d4e|2023-05-20--12-35-38--58 +# TOYOTA RAV4 2022 +773c6c0313a36828|2023-08-01--12-10-22--4 +# TOYOTA RAV4 2022 +825c2be1679633af|2023-06-08--14-27-04--24 +# TOYOTA RAV4 2022 +8547882d5a9638ed|2023-05-20--16-46-23--40 +# TOYOTA RAV4 2022 +8a6df5e317cdb0f1|2023-06-22--11-48-00--7 +# TOYOTA RAV4 2022 +8c3afba96b7a5db6|2023-05-20--15-33-13--12 +# TOYOTA RAV4 2022 +91a5f9bc5181e3ba|2023-07-17--13-12-48--3 +# TOYOTA RAV4 2022 +932fa1fa23f936dd|2023-07-03--14-05-29--29 +# TOYOTA RAV4 2022 +98b8395bda1abb3d|2023-07-15--15-39-42--1 +# TOYOTA RAV4 2022 +9af9456fb41cefdc|2023-06-08--16-48-49--25 +# TOYOTA RAV4 2022 +9f7a308d4490eb77|2023-05-11--16-59-21--3 +# TOYOTA RAV4 2022 +9fd2e1d2322620c1|2023-06-22--08-20-30--149 +# TOYOTA RAV4 2022 +bc1fe643a3929103|2023-07-17--19-45-52--8 +# TOYOTA RAV4 2022 +d8117083fe3d623d|2023-07-29--18-25-35--2 +# TOYOTA RAV4 2022 +dd2ff62df396c1fc|2023-05-21--18-40-13--120 +# TOYOTA RAV4 2022 +e16e4f4ef04a4ab3|2023-07-06--07-30-04--15 +# TOYOTA RAV4 2022 +eee593d3239d7c3c|2023-07-20--07-09-40--2 +# TOYOTA RAV4 2022 +f5a63eb328699685|2023-07-02--19-58-47--1 +# TOYOTA RAV4 2022 +f2188129ca0904e2|2023-05-21--17-35-49--8 +# TOYOTA RAV4 2022 +f60772e6acef55c4|2023-06-22--20-18-39--47 +# TOYOTA RAV4 2022 +fa323424d809e22a|2023-05-13--20-15-51--24 +# TOYOTA CAMRY 2018 +06362e6a7f0b400b|2023-07-17--15-01-53--27 +# TOYOTA CAMRY 2018 +0066f60689e612ed|2023-07-26--10-32-30--15 +# TOYOTA CAMRY 2018 +098b070a8ea9766b|2023-06-16--15-23-49--11 +# TOYOTA CAMRY 2018 +02a10fdbba41d6c4|2023-05-11--05-10-43--4 +# TOYOTA CAMRY 2018 +22331374d2858074|2023-06-15--11-27-50--2 +# TOYOTA CAMRY 2018 +071f13e1cf591bd8|2023-06-09--21-07-21--30 +# TOYOTA CAMRY 2018 +1b07ad9af1629f61|2023-05-18--11-54-09--41 +# TOYOTA CAMRY 2018 +27f66d238e2daff2|2023-07-26--13-16-24--8 +# TOYOTA CAMRY 2018 +30d4248ac12fd57c|2023-05-25--11-28-46--3 +# TOYOTA CAMRY 2018 +2f37c007683e85ba|2023-05-10--18-35-29--12 +# TOYOTA CAMRY 2018 +36ad47227a8b6e0d|2023-07-11--15-03-35--16 +# TOYOTA CAMRY 2018 +3b69a15335041c72|2023-05-14--01-32-08--4 +# TOYOTA CAMRY 2018 +3cc72445faf2b595|2023-06-23--13-50-08--20 +# TOYOTA CAMRY 2018 +3f4d8c6e1329405c|2023-07-24--20-49-51--5 +# TOYOTA CAMRY 2018 +5a518984e4caef1d|2023-08-01--19-47-13--1 +# TOYOTA CAMRY 2018 +7ebcdd800f653ec4|2023-07-23--14-28-06--4 +# TOYOTA CAMRY 2018 +9a052d2d382b6896|2023-07-12--21-24-54--9 +# TOYOTA CAMRY 2018 +9c86ed5c7284733c|2023-07-29--17-35-37--8 +# TOYOTA CAMRY 2018 +a000cb5ab7ef5223|2023-05-31--21-24-48--10 +# TOYOTA CAMRY 2018 +b34be3bf345f0f5e|2023-07-12--23-12-39--124 +# TOYOTA CAMRY 2018 +b4057b71f56d1191|2023-07-31--16-16-57--4 +# TOYOTA CAMRY 2018 +b7b58a594926fa23|2023-07-27--23-28-50--4 +# TOYOTA CAMRY 2018 +ba0844983cdec847|2023-08-04--11-47-17--7 +# TOYOTA CAMRY 2018 +ba4a94169bf12f32|2023-05-11--16-50-56--4 +# TOYOTA CAMRY 2018 +be8ed458ac4879c8|2023-07-10--20-19-35--10 +# TOYOTA CAMRY 2018 +c2c9a0e4f71e20e6|2023-05-30--14-48-23--38 +# TOYOTA CAMRY 2018 +ce4328694fa2cca9|2023-05-13--02-19-59--4 +# TOYOTA CAMRY 2018 +cd42d2594be938f7|2023-07-25--07-06-01--16 +# TOYOTA CAMRY 2018 +cca80b7bda70c17a|2023-05-25--17-06-27--34 +# TOYOTA CAMRY 2018 +d76803d2dfa3a00e|2023-07-17--00-53-09--7 +# TOYOTA CAMRY 2018 +e27a03030a436e84|2023-06-20--09-23-41--117 +# TOYOTA CAMRY 2018 +ebc7fb7dfd3839d9|2023-06-14--06-06-07--10 +# TOYOTA CAMRY 2018 +ec7de7d250fdcd1d|2023-07-31--17-55-49--1 +# TOYOTA CAMRY 2018 +f71b4f559fb531ad|2023-05-10--16-47-20--31 +# AUDI A3 3RD GEN +200c952f826a6447|2023-07-02--11-55-50--7 +# AUDI A3 3RD GEN +359bcd3ea48092f6|2023-06-03--07-32-15--3 +# AUDI A3 3RD GEN +3ac7029f79711ca5|2023-06-30--07-41-35--5 +# AUDI A3 3RD GEN +76b48b05df10f05e|2023-07-08--16-05-11--4 +# AUDI A3 3RD GEN +a973e9182bc96a2c|2023-06-28--11-02-10--11 +# VOLKSWAGEN ATLAS 1ST GEN +16758e226aa2f747|2023-07-28--15-30-42--3 +# VOLKSWAGEN ATLAS 1ST GEN +16e8546287ecaada|2023-06-26--17-34-08--3 +# VOLKSWAGEN ATLAS 1ST GEN +2bbad62414dc6d9b|2023-08-05--18-02-38--9 +# VOLKSWAGEN ATLAS 1ST GEN +3174d252cec3bf6f|2023-07-04--09-24-03--11 +# VOLKSWAGEN ATLAS 1ST GEN +3737f89a2e0db063|2023-07-19--08-01-06--7 +# VOLKSWAGEN ATLAS 1ST GEN +4048de296d5207fb|2023-07-28--23-35-13--9 +# VOLKSWAGEN ATLAS 1ST GEN +58d4dfb7f4fee11d|2023-08-06--15-55-59--11 +# VOLKSWAGEN ATLAS 1ST GEN +793830b37089fe1d|2023-07-19--17-08-52--1 +# VOLKSWAGEN ATLAS 1ST GEN +d8e893cc7739f7d5|2023-06-20--09-35-18--10 +# VOLKSWAGEN ATLAS 1ST GEN +d7251ede344ff957|2023-07-21--16-32-02--61 +# VOLKSWAGEN ATLAS 1ST GEN +e415c44c77c17e15|2023-05-10--07-55-50--2 +# VOLKSWAGEN ATLAS 1ST GEN +e80066d826c705a9|2023-08-07--15-23-13--7 +# VOLKSWAGEN ATLAS 1ST GEN +f4971592598fa9a3|2023-06-10--11-08-36--7 +# VOLKSWAGEN ATLAS 1ST GEN +ffdd12beb96d5b54|2023-07-30--19-09-47--62 +# LEXUS RX 2016 +1786eaa4cc844889|2023-06-30--13-53-39--91 +# LEXUS RX 2016 +0cf857b1b13bd7cd|2023-07-28--22-10-53--3 +# LEXUS RX 2016 +0229eb43387cef7a|2023-06-15--18-47-25--11 +# LEXUS RX 2016 +2a566b7f69eb2a77|2023-05-18--18-12-09--12 +# LEXUS RX 2016 +592ae47bcb1a6658|2023-06-28--03-11-52--3 +# LEXUS RX 2016 +62b4af07ac90a8e5|2023-07-30--18-53-41--116 +# LEXUS RX 2016 +80ea6c1ff7648289|2023-07-25--18-31-23--9 +# LEXUS RX 2016 +8b196fa003fe55c9|2023-07-06--13-59-02--1 +# LEXUS RX 2016 +b04a5e7ac1c97127|2023-06-11--21-03-22--14 +# LEXUS RX 2016 +bba0a7d99d07b4d0|2023-07-17--10-47-12--16 +# LEXUS RX 2016 +c318581fb51199e6|2023-06-21--09-08-17--47 +# LEXUS RX 2016 +c8d3dd7cfe3c2bef|2023-05-16--07-49-03--21 +# LEXUS RX 2016 +d93ff944f9757e06|2023-07-04--00-28-00--4 +# LEXUS RX 2016 +e3792885a81edc65|2023-05-10--08-26-43--30 +# LEXUS RX 2016 +ea93dc40fbf84c96|2023-06-10--18-26-40--5 +# LEXUS ES 2019 +24f960aeabdd0b45|2023-07-22--22-56-58--9 +# LEXUS ES 2019 +221780419969efb8|2023-06-03--14-00-10--24 +# LEXUS ES 2019 +43000f0e5e058b22|2023-08-03--16-55-17--56 +# LEXUS ES 2019 +47724a191e0f4d9e|2023-06-24--20-39-39--28 +# LEXUS ES 2019 +5aa51c7df8ce288d|2023-07-14--07-31-51--14 +# LEXUS ES 2019 +5c0038031497257b|2023-07-11--16-58-54--45 +# LEXUS ES 2019 +5ad3c8116ceedf0e|2023-06-09--10-48-08--4 +# LEXUS ES 2019 +6d867424dc48c01b|2023-07-21--20-19-27--19 +# LEXUS ES 2019 +89c10c27e1a41814|2023-06-05--21-45-17--47 +# LEXUS ES 2019 +b9c9b1d4e4277fec|2023-07-09--10-55-55--3 +# LEXUS ES 2019 +eebb9787e66670b1|2023-06-09--13-43-21--22 +# HYUNDAI SANTA FE 2022 +1ad7728ce54a161d|2023-06-27--16-42-41--38 +# HYUNDAI SANTA FE 2022 +2d394786f239cd0d|2023-07-16--12-34-58--17 +# HYUNDAI SANTA FE 2022 +305cf2a0bda0e51c|2023-07-20--17-07-34--1 +# HYUNDAI SANTA FE 2022 +2fcc9a43453b10de|2023-06-30--10-25-43--12 +# HYUNDAI SANTA FE 2022 +782fcdb3a42ca1fa|2023-05-26--02-02-12--1 +# HYUNDAI SANTA FE 2022 +7a6ba99ba49954c0|2023-06-01--11-46-54--55 +# HYUNDAI SANTA FE 2022 +cc2f3c4ab6d7758b|2023-07-17--10-14-06--18 +# HYUNDAI SANTA FE 2022 +e37432b18654a7cc|2023-06-29--15-51-04--50 +# TOYOTA CAMRY 2021 +080fffcdcdf847e2|2023-06-17--22-09-54--16 +# TOYOTA CAMRY 2021 +256b964e662f0e39|2023-08-02--15-53-58--33 +# TOYOTA CAMRY 2021 +2422760916ecd3ed|2023-07-30--00-10-14--43 +# TOYOTA CAMRY 2021 +017772face80c94f|2023-06-22--17-04-43--15 +# TOYOTA CAMRY 2021 +1916f6660fdef56b|2023-05-22--16-31-45--50 +# TOYOTA CAMRY 2021 +171516dbc8965a98|2023-08-08--11-12-03--7 +# TOYOTA CAMRY 2021 +289cbd8c4e814c92|2023-07-24--16-08-08--60 +# TOYOTA CAMRY 2021 +2ec957d01038234b|2023-07-19--18-44-13--28 +# TOYOTA CAMRY 2021 +3ba061cbb7a708c3|2023-07-11--11-36-38--4 +# TOYOTA CAMRY 2021 +3ff411160b72e90e|2023-06-11--17-08-09--13 +# TOYOTA CAMRY 2021 +52682dee0263bc9e|2023-07-11--21-46-17--2 +# TOYOTA CAMRY 2021 +51f386982b6e8a77|2023-07-08--20-11-27--27 +# TOYOTA CAMRY 2021 +542e88ffeabefde6|2023-07-13--15-57-13--4 +# TOYOTA CAMRY 2021 +893ae4414cc33177|2023-07-17--16-27-47--44 +# TOYOTA CAMRY 2021 +914f01e43165ff12|2023-06-16--15-13-48--15 +# TOYOTA CAMRY 2021 +b8c0e1ef3bae2ae8|2023-07-06--15-56-32--1 +# TOYOTA CAMRY 2021 +bfd59919af7a9183|2023-05-22--17-06-38--3 +# TOYOTA CAMRY 2021 +c152e86589f67fa8|2023-06-09--11-26-31--8 +# TOYOTA CAMRY 2021 +ec21b3b2491e1d5b|2023-05-21--20-10-40--54 +# TOYOTA CAMRY 2021 +f56e1b6b8d3d4326|2023-06-16--16-40-59--19 +# LEXUS RX 2020 +14bae1f3b3778de2|2023-07-29--08-59-05--1 +# LEXUS RX 2020 +221bc8e55b068d8c|2023-07-22--14-09-28--5 +# LEXUS RX 2020 +284aa7812f549210|2023-07-17--13-43-52--15 +# LEXUS RX 2020 +02b50dc00776ca3c|2023-06-04--21-14-16--6 +# LEXUS RX 2020 +12f5389d0abdd2b0|2023-07-16--03-22-06--191 +# LEXUS RX 2020 +34091e43a35e6b0c|2023-07-28--15-25-20--9 +# LEXUS RX 2020 +4adbcf7b0056b7eb|2023-07-28--19-57-42--1 +# LEXUS RX 2020 +5706cbe0f8b82a15|2023-05-21--09-36-28--7 +# LEXUS RX 2020 +5eaac34b077defa9|2023-07-03--09-52-29--17 +# LEXUS RX 2020 +75b3f01a07557b7d|2023-06-14--18-57-50--7 +# LEXUS RX 2020 +b32bbd31c710d41c|2023-06-30--13-28-18--5 +# LEXUS RX 2020 +b0d686668fb49a0b|2023-07-08--14-38-02--30 +# LEXUS RX 2020 +c5c8fc431bbe68e5|2023-08-07--19-45-43--8 +# LEXUS RX 2020 +d61540bf6f3ff5fd|2023-05-26--11-18-58--4 +# TOYOTA AVALON 2022 +14f1b241a8c4e210|2023-05-14--17-14-36--75 +# TOYOTA AVALON 2022 +5cee358519141338|2023-07-31--14-50-56--15 +# TOYOTA AVALON 2022 +c417be6e8e4be4c6|2023-07-11--13-17-09--19 +# KIA EV6 2022 +2466dbded40ee302|2023-07-19--07-57-59--5 +# KIA EV6 2022 +150033b3d34ddfa3|2023-08-08--12-23-52--18 +# KIA EV6 2022 +21bbb80f61096b25|2023-05-21--05-23-18--24 +# KIA EV6 2022 +83cd83d9569526f1|2023-06-30--00-21-30--7 +# KIA EV6 2022 +879ccc014c30dbf9|2023-07-23--18-45-39--24 +# KIA EV6 2022 +b3a670efbd147ef7|2023-06-15--13-26-07--30 +# KIA EV6 2022 +cb06ac355b38798f|2023-06-11--20-29-07--30 +# KIA EV6 2022 +ff07367edd52b0d0|2023-08-06--01-47-15--51 +# CHRYSLER PACIFICA 2020 +12208e5acdc97eb3|2023-06-15--14-42-11--5 +# CHRYSLER PACIFICA 2020 +20665f9a424ada41|2023-07-31--17-11-31--8 +# CHRYSLER PACIFICA 2020 +1d59b9e6ca471788|2023-06-11--16-36-39--1 +# CHRYSLER PACIFICA 2020 +42ccfd732446a8e3|2023-05-18--08-53-58--1 +# CHRYSLER PACIFICA 2020 +5fc1717be83fc0da|2023-07-27--13-49-58--50 +# CHRYSLER PACIFICA 2020 +75564b71f403c136|2023-06-25--14-16-12--8 +# CHRYSLER PACIFICA 2020 +9cad19e0efce3650|2023-06-07--20-40-39--25 +# CHRYSLER PACIFICA 2020 +af014367f8fd3384|2023-06-04--08-57-55--5 +# CHRYSLER PACIFICA 2020 +c1feb10d20626c65|2023-06-11--15-14-18--64 +# CHRYSLER PACIFICA 2020 +f0b1085e8e45dc63|2023-05-31--17-25-38--7 +# LEXUS ES 2019 +1678ac13bc9877c8|2023-07-09--20-07-48--29 +# LEXUS ES 2019 +2844efe905d33fbd|2023-07-02--12-10-43--44 +# LEXUS ES 2019 +6ed275339186a130|2023-07-21--06-40-44--32 +# LEXUS ES 2019 +7a63be41f9cead58|2023-05-11--09-03-37--14 +# LEXUS ES 2019 +a0dc5a8ca1a5786a|2023-07-04--09-29-52--7 +# LEXUS ES 2019 +cf071db973993448|2023-07-29--18-58-05--13 +# LEXUS ES 2019 +db1c55738e630599|2023-06-09--21-03-38--3 +# LEXUS ES 2019 +ea4add78b3d29a5f|2023-05-25--06-41-18--50 +# TOYOTA AVALON 2019 +1cdab90d23115dc2|2023-05-27--21-27-46--9 +# TOYOTA AVALON 2019 +2aeb6689ee609d86|2023-05-25--17-51-03--14 +# TOYOTA AVALON 2019 +57ea94b88445973c|2023-05-24--18-27-06--7 +# TOYOTA AVALON 2019 +dfe129aad2e701b6|2023-05-11--21-08-54--3 +# TOYOTA AVALON 2019 +f02bf3c0f2ec038e|2023-07-17--12-52-56--4 +# TOYOTA AVALON 2019 +f7d1a944dc6e8789|2023-06-02--15-00-46--64 +# VOLKSWAGEN TIGUAN 2ND GEN +07ddd23c582b8e2a|2023-06-10--13-32-49--1 +# VOLKSWAGEN TIGUAN 2ND GEN +4aadfdcf6846d356|2023-07-10--20-22-59--1 +# VOLKSWAGEN TIGUAN 2ND GEN +4e144f64a2535890|2023-05-27--15-30-51--3 +# VOLKSWAGEN TIGUAN 2ND GEN +88b9fa8e179f87d8|2023-07-12--17-01-50--11 +# VOLKSWAGEN TIGUAN 2ND GEN +b08418a961021457|2023-05-15--10-51-25--4 +# VOLKSWAGEN TIGUAN 2ND GEN +c78c1972adfa10df|2023-05-20--13-11-13--8 +# VOLKSWAGEN TIGUAN 2ND GEN +d5eb604aa6ae46b7|2023-08-01--16-13-48--5 +# VOLKSWAGEN TIGUAN 2ND GEN +deb9a2546658c0ec|2023-08-07--14-53-50--1 +# VOLKSWAGEN TIGUAN 2ND GEN +f3dfef1528797a29|2023-05-25--20-36-07--8 +# HYUNDAI SONATA HYBRID 2021 +01d4ba35f8288743|2023-07-30--11-19-09--14 +# HYUNDAI SONATA HYBRID 2021 +1d08ecde44f58620|2023-06-08--19-12-14--2 +# HYUNDAI SONATA HYBRID 2021 +077309a26bf98013|2023-07-01--14-11-42--1 +# HYUNDAI SONATA HYBRID 2021 +2fdb3b00e818dfd7|2023-07-31--02-50-23--12 +# HYUNDAI SONATA HYBRID 2021 +49734429dda9bbe7|2023-07-10--14-53-29--38 +# HYUNDAI SONATA HYBRID 2021 +61ef897671a29f5c|2023-07-18--10-19-18--10 +# HYUNDAI SONATA HYBRID 2021 +6f322e987d684501|2023-07-27--17-11-53--14 +# HYUNDAI SONATA HYBRID 2021 +7a629f5c75f83fa7|2023-05-20--22-20-36--7 +# HYUNDAI SONATA HYBRID 2021 +a6c2adb491991166|2023-07-16--09-55-40--4 +# HYUNDAI SONATA HYBRID 2021 +b5374bdeea21f5ce|2023-07-15--19-31-57--13 +# HYUNDAI SONATA HYBRID 2021 +be44434f27731ff8|2023-07-02--08-00-08--240 +# HYUNDAI SONATA HYBRID 2021 +cc820fd0720354e1|2023-06-08--14-57-24--37 +# HYUNDAI SONATA HYBRID 2021 +df2433ef9f6dcaa5|2023-07-27--20-19-04--2 +# VOLKSWAGEN POLO 6TH GEN +0bbe367c98fa1538|2023-07-01--19-42-26--7 +# LEXUS NX 2020 +14f9b413ca9c2962|2023-06-30--12-09-53--5 +# LEXUS NX 2020 +436b3762e7406d9d|2023-05-28--19-54-45--18 +# LEXUS NX 2020 +9b42a9940cfd5fda|2023-06-17--19-17-40--53 +# LEXUS NX 2020 +c7a06a775d4a0b29|2023-05-16--10-36-19--1 +# LEXUS NX 2020 +e4b558dc139f76e1|2023-06-26--17-19-48--5 +# LEXUS NX 2018 +09d58cd27c493c29|2023-05-26--07-56-26--9 +# LEXUS NX 2018 +6179fc02b5ed871f|2023-06-26--15-38-35--4 +# LEXUS NX 2018 +b8dd7a23d04c522f|2023-06-15--15-43-11--33 +# HONDA CR-V HYBRID 2019 +11fa019479471a0a|2023-06-19--16-40-40--18 +# HONDA CR-V HYBRID 2019 +8f3f4683d7cfda74|2023-05-27--15-40-52--4 +# HONDA CR-V HYBRID 2019 +d6c98b1ebf9916b9|2023-07-20--09-04-29--20 +# SUBARU IMPREZA LIMITED 2019 +0744286ead2fbb96|2023-05-19--20-52-49--110 +# SUBARU IMPREZA LIMITED 2019 +283bc259f3c0fec9|2023-06-23--18-44-24--2 +# SUBARU IMPREZA LIMITED 2019 +45d40901dd17481d|2023-06-30--19-57-56--20 +# SUBARU IMPREZA LIMITED 2019 +5c3a4dc9bd0b2eaa|2023-05-16--16-43-44--22 +# SUBARU IMPREZA LIMITED 2019 +6f35adacf2529520|2023-08-01--09-20-18--12 +# SUBARU IMPREZA LIMITED 2019 +7a4ef9e9f44480ee|2023-06-17--09-29-32--3 +# SUBARU IMPREZA LIMITED 2019 +7d1607ec8698af97|2023-06-21--20-38-47--2 +# SUBARU IMPREZA LIMITED 2019 +8de015561e1ea4a0|2023-05-15--17-20-39--2 +# SUBARU IMPREZA LIMITED 2019 +9dedbd672d57fd88|2023-07-27--14-29-54--6 +# SUBARU IMPREZA LIMITED 2019 +d96660307a3000e2|2023-06-17--20-29-31--43 +# HYUNDAI IONIQ HYBRID 2017-2019 +0e13ee2b821302f4|2023-07-09--15-44-35--3 +# HYUNDAI IONIQ HYBRID 2017-2019 +8dc7b1ff3d3ce73d|2023-07-13--21-49-58--3 +# HYUNDAI GENESIS 2015-2016 +06353521b1f136dd|2023-05-12--19-40-35--48 +# HYUNDAI GENESIS 2015-2016 +61b3de3cce404316|2023-07-05--19-47-46--17 +# HYUNDAI GENESIS 2015-2016 +b6bb1d6e9e76d5c0|2023-06-26--06-28-25--4 +# KIA NIRO HYBRID 2021 +1ea7eb816544f6c0|2023-07-31--19-13-44--1 +# KIA NIRO HYBRID 2021 +92daf576a7eab465|2023-07-18--12-15-16--63 +# HONDA PILOT 2017 +11bfdda7cffeb882|2023-05-26--13-25-27--7 +# HONDA PILOT 2017 +1c8910b52e443f18|2023-05-21--20-31-29--44 +# HONDA PILOT 2017 +18bbbb7606cddb6a|2023-05-21--13-13-06--110 +# HONDA PILOT 2017 +30bdd852020fbd54|2023-06-07--09-05-51--22 +# HONDA PILOT 2017 +31e47fc2fc02c165|2023-06-02--13-31-29--13 +# HONDA PILOT 2017 +35b4e5307cce2504|2023-05-20--10-05-14--2 +# HONDA PILOT 2017 +34ff4137044da8fa|2023-05-10--22-40-43--12 +# HONDA PILOT 2017 +695826b02fd8fe16|2023-06-21--13-30-12--9 +# HONDA PILOT 2017 +83ccc4c48741b67a|2023-05-25--15-12-07--15 +# HONDA PILOT 2017 +8a9bfee29c5a277a|2023-06-01--09-20-21--70 +# HONDA PILOT 2017 +9cb432f9376cfa89|2023-05-16--16-25-22--6 +# HONDA PILOT 2017 +9bac7575fac62395|2023-05-17--06-24-54--11 +# HONDA PILOT 2017 +ad1b9150af890d9e|2023-07-31--09-13-55--15 +# HONDA PILOT 2017 +b4f429568ea81f21|2023-06-17--11-05-51--112 +# HONDA PILOT 2017 +bd80a1c23664b3b7|2023-06-12--16-44-33--4 +# HONDA PILOT 2017 +d53a9253d19264e5|2023-07-03--00-53-05--3 +# HONDA PILOT 2017 +da7d4c7c00a25e08|2023-06-22--19-20-41--15 +# HONDA PILOT 2017 +d9c43a383a53494b|2023-07-25--09-03-56--2 +# HONDA PILOT 2017 +f4e5206d7968b785|2023-06-24--22-50-01--1 +# HONDA PILOT 2017 +fff9af2c280cebe7|2023-07-15--09-10-37--5 +# HONDA CIVIC (BOSCH) 2019 +220bd1ec52459628|2023-05-14--13-38-23--117 +# HONDA CIVIC (BOSCH) 2019 +1cea7c17bf903d1d|2023-06-05--17-05-26--41 +# HONDA CIVIC (BOSCH) 2019 +2872a60fdd6a85a5|2023-06-07--23-37-19--139 +# HONDA CIVIC (BOSCH) 2019 +5123f2e42bc5c2fb|2023-07-04--17-34-47--16 +# HONDA CIVIC (BOSCH) 2019 +4ea994afc80a04cf|2023-07-01--19-47-55--2 +# HONDA CIVIC (BOSCH) 2019 +8506a4cbf74a6519|2023-06-30--12-05-04--14 +# HONDA CIVIC (BOSCH) 2019 +8c63e6150f08c5cc|2023-07-30--20-05-40--62 +# HONDA CIVIC (BOSCH) 2019 +90d56ac785678835|2023-05-28--17-28-04--1 +# HONDA CIVIC (BOSCH) 2019 +930ad2d3aa9a7438|2023-07-10--15-57-07--5 +# HONDA CIVIC (BOSCH) 2019 +9c9e7b7cb9a2d507|2023-06-16--22-18-46--8 +# HONDA CIVIC (BOSCH) 2019 +a341d8f71913b7c6|2023-07-03--11-08-08--9 +# HONDA CIVIC (BOSCH) 2019 +a9a11ee77c895117|2023-05-31--20-56-14--1 +# HONDA CIVIC (BOSCH) 2019 +addf4f63ee4758f3|2023-06-12--13-17-03--10 +# HONDA CIVIC (BOSCH) 2019 +c6d9941315763063|2023-05-26--18-06-58--47 +# HONDA CIVIC (BOSCH) 2019 +ced18df2ecb5eccd|2023-06-26--16-09-36--15 +# HONDA CIVIC (BOSCH) 2019 +d4c8df785ce7f3c5|2023-07-14--15-46-41--12 +# HONDA CIVIC (BOSCH) 2019 +dbd8a2d9977de5f5|2023-06-14--07-23-48--17 +# HONDA CIVIC (BOSCH) 2019 +e4f4282867c6a6b9|2023-07-21--11-37-55--7 +# HONDA CIVIC (BOSCH) 2019 +ee87fe694c837822|2023-07-22--10-02-27--10 +# HONDA CIVIC (BOSCH) 2019 +f27a5518b5be94da|2023-07-21--18-09-53--4 +# HONDA CIVIC (BOSCH) 2019 +f1c58b2efb96589f|2023-07-20--09-38-55--107 +# HONDA CIVIC (BOSCH) 2019 +f99ab12043ad3219|2023-07-19--17-07-43--2 +# HYUNDAI KONA ELECTRIC 2019 +15e5d08be3f89aeb|2023-05-10--05-05-16--1 +# HYUNDAI KONA ELECTRIC 2019 +39ff090a42469a72|2023-05-15--16-18-09--6 +# HYUNDAI KONA ELECTRIC 2019 +c9508b688d2009f6|2023-05-23--12-24-07--21 +# LEXUS RX 2016 +1124e8ae07941ba9|2023-06-05--15-45-48--9 +# LEXUS RX 2016 +2daa07741d66050b|2023-05-21--15-59-39--3 +# LEXUS RX 2016 +4424ddad7f805c10|2023-05-14--13-50-39--147 +# LEXUS RX 2016 +42132726c7467377|2023-07-08--17-03-46--83 +# LEXUS RX 2016 +6ecec1e8fd327774|2023-07-26--10-46-54--13 +# LEXUS RX 2016 +77cb7310f7b0e1d1|2023-05-28--20-12-02--95 +# LEXUS RX 2016 +89ee528b1eb135ed|2023-05-12--20-05-25--5 +# LEXUS RX 2016 +9cd71f2c46d99533|2023-08-02--20-53-42--17 +# LEXUS RX 2016 +ca71d21f2c04ff8e|2023-07-17--08-16-56--83 +# LEXUS RX 2016 +f4c7fca20721d4c1|2023-07-25--18-15-24--18 +# LEXUS RX 2016 +f2defa60d751d031|2023-05-17--15-27-40--91 +# JEEP GRAND CHEROKEE 2019 +06d01b4518df02ff|2023-07-05--06-29-47--46 +# JEEP GRAND CHEROKEE 2019 +2d9b6425552c52c1|2023-05-14--18-18-54--20 +# JEEP GRAND CHEROKEE 2019 +2f123609bbddbe0c|2023-07-18--17-46-35--16 +# JEEP GRAND CHEROKEE 2019 +626791454319848b|2023-07-06--02-13-50--169 +# JEEP GRAND CHEROKEE 2019 +76ec661ac0d18569|2023-08-05--16-58-53--42 +# JEEP GRAND CHEROKEE 2019 +e1dfba62a4e33f7b|2023-05-10--14-17-59--4 +# JEEP GRAND CHEROKEE 2019 +fdcd19f4434cea9d|2023-05-10--17-10-38--2 +# CHEVROLET VOLT PREMIER 2017 +20cb801701fc8237|2023-06-07--17-41-26--12 +# CHEVROLET VOLT PREMIER 2017 +08924d6a5ba4ab32|2023-07-04--06-56-44--30 +# CHEVROLET VOLT PREMIER 2017 +216776dc641516cc|2023-07-23--16-40-47--76 +# CHEVROLET VOLT PREMIER 2017 +255403b2bd0acb75|2023-05-12--08-44-56--19 +# CHEVROLET VOLT PREMIER 2017 +3189708ff522bc3a|2023-06-08--11-42-29--37 +# CHEVROLET VOLT PREMIER 2017 +3725c590ce069e78|2023-06-25--07-44-44--18 +# CHEVROLET VOLT PREMIER 2017 +3ddd64a934be4c23|2023-06-27--07-52-32--5 +# CHEVROLET VOLT PREMIER 2017 +4bd7be56a56eecaf|2023-05-10--18-17-26--7 +# CHEVROLET VOLT PREMIER 2017 +524ca9dc97ddd9a3|2023-07-25--21-32-28--5 +# CHEVROLET VOLT PREMIER 2017 +5617d19d0841b38c|2023-05-24--12-29-35--113 +# CHEVROLET VOLT PREMIER 2017 +67b9beb7b4d31cf8|2023-05-23--12-50-32--15 +# CHEVROLET VOLT PREMIER 2017 +73a06f3c204cb47a|2023-05-21--15-37-47--6 +# CHEVROLET VOLT PREMIER 2017 +90678d1470cad364|2023-06-03--14-10-34--15 +# CHEVROLET VOLT PREMIER 2017 +a3e8ad84037083ca|2023-06-02--17-10-25--13 +# CHEVROLET VOLT PREMIER 2017 +af9fc6047bf1dae2|2023-08-01--05-28-32--25 +# CHEVROLET VOLT PREMIER 2017 +b24f78641f62dd3c|2023-06-06--18-18-45--13 +# CHEVROLET VOLT PREMIER 2017 +c12c0f43a6c65515|2023-05-23--10-31-56--6 +# CHEVROLET VOLT PREMIER 2017 +d0aa4a8f195675a9|2023-06-20--19-35-14--33 +# CHEVROLET VOLT PREMIER 2017 +d44c5c17d2380d53|2023-07-27--20-23-18--9 +# CHEVROLET VOLT PREMIER 2017 +d2ccdcf33e62cfa0|2023-06-01--20-42-39--58 +# CHEVROLET VOLT PREMIER 2017 +dcaf04bb53a1f9df|2023-06-02--10-08-55--1 +# CHEVROLET VOLT PREMIER 2017 +e69bcbc2c84de4d2|2023-06-27--17-12-00--14 +# CHEVROLET VOLT PREMIER 2017 +e2b25f39da040caa|2023-07-23--12-59-47--49 +# CHEVROLET VOLT PREMIER 2017 +e4b91b0282619c79|2023-07-30--15-57-39--1 +# TOYOTA ALPHARD 2020 +09c50095f46f96cd|2023-05-21--10-27-44--20 +# TOYOTA ALPHARD 2020 +5ffe5d6678eaefb2|2023-07-04--17-18-33--96 +# HYUNDAI IONIQ PHEV 2020 +201c5aaced09a24a|2023-05-20--12-39-01--15 +# HYUNDAI IONIQ PHEV 2020 +4bcc377663bc541a|2023-05-24--14-59-59--219 +# HYUNDAI IONIQ PHEV 2020 +78fdfacf4a805561|2023-07-17--11-54-45--73 +# HYUNDAI IONIQ PHEV 2020 +93882bc7bea8b476|2023-07-30--19-56-22--7 +# HYUNDAI IONIQ PHEV 2020 +b28e9dbe4004e915|2023-06-11--19-55-28--2 +# HYUNDAI IONIQ PHEV 2020 +c447f3983314c453|2023-05-14--17-17-24--158 +# RAM 1500 5TH GEN +17fc16d840fe9d21|2023-05-18--19-28-17--11 +# VOLKSWAGEN ARTEON 1ST GEN +0662797832aac2eb|2023-07-13--09-33-52--73 +# VOLKSWAGEN ARTEON 1ST GEN +5ac586afbb236b5d|2023-07-17--22-52-19--5 +# VOLKSWAGEN ARTEON 1ST GEN +c34ef43981b6d888|2023-06-01--07-50-41--7 +# HONDA INSIGHT 2019 +0ac79efcae392b39|2023-06-29--10-57-45--8 +# HONDA INSIGHT 2019 +acdb227003c7aee1|2023-05-30--17-06-35--9 +# HONDA INSIGHT 2019 +baeb84fd6ad76707|2023-07-26--06-13-05--45 +# HONDA INSIGHT 2019 +ba9a88a070809873|2023-05-14--13-34-35--32 +# HONDA INSIGHT 2019 +bfde60a60008c36d|2023-05-24--16-51-16--24 +# HONDA INSIGHT 2019 +f7d92a003486dc37|2023-06-10--16-17-23--48 +# TOYOTA MIRAI 2021 +2611ca299b6b5939|2023-07-12--19-27-34--1 +# TOYOTA MIRAI 2021 +390a85b0f0d7a93b|2023-07-02--17-09-06--13 +# TOYOTA MIRAI 2021 +d2bd3cb8241c253c|2023-05-30--18-34-40--2 +# TOYOTA MIRAI 2021 +f4ee9d3ae1d656fb|2023-08-03--17-47-32--15 +# TOYOTA AVALON 2019 +1cf68ce8c78d6246|2023-07-02--22-42-04--9 +# TOYOTA AVALON 2019 +3e1100294929fd5f|2023-06-19--20-05-45--6 +# TOYOTA AVALON 2019 +7879897f0af9ed09|2023-07-21--12-35-20--1 +# LEXUS NX 2020 +01f31237627e0cc3|2023-08-08--09-32-39--10 +# KIA STINGER GT2 2018 +2ba5946fb25bfc1f|2023-07-29--22-48-54--40 +# KIA STINGER GT2 2018 +5ccb50cda9fba8b7|2023-07-02--12-59-48--2 +# KIA STINGER GT2 2018 +724f06bcdb81bc8e|2023-07-01--08-24-30--25 +# KIA STINGER GT2 2018 +8efe830da0568792|2023-07-07--12-21-04--14 +# KIA STINGER GT2 2018 +b5768b7348113531|2023-07-29--20-29-19--1 +# SKODA KODIAQ 1ST GEN +2696aa4107f3a534|2023-06-12--17-35-02--1 +# SKODA KODIAQ 1ST GEN +2ca49a03c8084514|2023-08-04--07-24-41--13 +# SKODA KODIAQ 1ST GEN +89b596c5edcb6dba|2023-07-15--15-38-29--1 +# SKODA KODIAQ 1ST GEN +8a5da7c1d1783730|2023-06-08--17-33-34--2 +# SKODA KODIAQ 1ST GEN +cd4c3e2031f01e61|2023-07-03--11-19-29--1 +# SKODA KODIAQ 1ST GEN +dafb0cb9e28e0249|2023-05-31--15-55-44--1 +# HONDA HRV 2019 +09c457a021a641e7|2023-07-24--20-02-45--3 +# HONDA HRV 2019 +6e9442a1c18f2abd|2023-05-26--12-52-43--4 +# HONDA HRV 2019 +78edb6a9a06e891d|2023-06-25--19-42-26--2 +# HONDA HRV 2019 +7c72f43a732e77ce|2023-07-26--21-44-12--10 +# HONDA HRV 2019 +a9203d77468a98a3|2023-05-11--21-05-37--10 +# GENESIS G80 2017 +2dcea2872df6d423|2023-06-06--19-13-28--50 +# GENESIS G80 2017 +450774a9a3ffe4c8|2023-08-05--15-07-10--11 +# GENESIS G80 2017 +a99d0d0edbedad89|2023-07-04--21-21-06--4 +# VOLKSWAGEN PASSAT 8TH GEN +2d7d87433a67c925|2023-05-14--17-05-12--21 +# VOLKSWAGEN PASSAT 8TH GEN +37e3253d2ac7c823|2023-05-30--16-09-30--26 +# VOLKSWAGEN PASSAT 8TH GEN +40443218782e5709|2023-07-11--10-44-37--14 +# VOLKSWAGEN PASSAT 8TH GEN +5405cac0c9d58c3d|2023-06-13--18-00-38--5 +# VOLKSWAGEN PASSAT 8TH GEN +7e069ec96c2da3a2|2023-07-08--14-06-11--23 +# VOLKSWAGEN PASSAT 8TH GEN +fd81eb7cc97ce831|2023-05-13--14-22-35--55 +# AUDI Q3 2ND GEN +2a7eeed5627fe50f|2023-05-26--16-00-32--42 +# AUDI Q3 2ND GEN +cdc1627feb1c82d3|2023-07-23--16-49-24--6 +# TOYOTA HIGHLANDER 2017 +30f476405b31e063|2023-07-23--11-27-50--4 +# TOYOTA HIGHLANDER 2017 +335da7758ecaf9b8|2023-06-07--06-45-19--6 +# TOYOTA HIGHLANDER 2017 +3dfa699819714d88|2023-05-23--10-21-28--15 +# TOYOTA HIGHLANDER 2017 +443fc6ac84d80c7e|2023-06-09--10-38-02--5 +# TOYOTA HIGHLANDER 2017 +69310bd073c5381d|2023-05-25--11-21-15--7 +# TOYOTA HIGHLANDER 2017 +7ebef57bc42d0ffd|2023-05-15--09-33-53--32 +# TOYOTA HIGHLANDER 2017 +90e19871a5f0753d|2023-05-30--19-41-28--30 +# TOYOTA HIGHLANDER 2017 +a2153ee04e30ac3c|2023-05-28--15-46-53--20 +# TOYOTA HIGHLANDER 2017 +a68647f2ba7092a3|2023-06-09--11-50-44--12 +# TOYOTA HIGHLANDER 2017 +d4f786dae36655f1|2023-07-08--11-46-59--31 +# TOYOTA HIGHLANDER 2017 +eb3a11981a924f0f|2023-07-29--12-16-21--12 +# CHRYSLER PACIFICA HYBRID 2017 +328eb791948dc4c4|2023-07-28--20-13-00--12 +# CHRYSLER PACIFICA HYBRID 2017 +57409982aa4a348b|2023-07-17--19-19-22--13 +# CHRYSLER PACIFICA HYBRID 2017 +62bde7c16381d8b2|2023-05-21--20-35-27--17 +# CHRYSLER PACIFICA HYBRID 2017 +949ce31b8c38095a|2023-07-11--19-03-33--37 +# TOYOTA AVALON 2022 +301800decccd6669|2023-06-10--12-18-42--12 +# TOYOTA AVALON 2022 +caa859705cd01362|2023-07-20--08-41-27--1 +# SUBARU OUTBACK 6TH GEN +33f86ddb06a656dd|2023-07-30--19-36-09--38 +# SUBARU OUTBACK 6TH GEN +46009c83d4595279|2023-07-10--18-04-48--49 +# SUBARU OUTBACK 6TH GEN +781b0068b313214f|2023-07-24--09-46-42--1 +# SUBARU OUTBACK 6TH GEN +83ce0f0dcdc42a2d|2023-07-12--11-37-21--5 +# SUBARU OUTBACK 6TH GEN +8a0a42036c8cd285|2023-07-15--12-20-41--251 +# SUBARU OUTBACK 6TH GEN +a0a54ab26674dbb9|2023-05-10--17-52-42--11 +# SUBARU OUTBACK 6TH GEN +bad6ae3584ece5b5|2023-06-06--20-47-16--1 +# SUBARU OUTBACK 6TH GEN +c726b2698bd24c5e|2023-07-22--11-45-38--2 +# SUBARU OUTBACK 6TH GEN +db94c35b2fc49a1d|2023-06-29--15-34-53--3 +# SUBARU OUTBACK 6TH GEN +eac0312bb7d371ef|2023-06-23--09-53-10--3 +# VOLKSWAGEN PASSAT NMS +398d43ca7e0c8e34|2023-06-07--21-05-24--3 +# LEXUS IS 2018 +3776c9b10eb2ab37|2023-07-17--19-38-03--12 +# LEXUS IS 2018 +5d64b83564cf5d9a|2023-07-23--15-00-46--12 +# LEXUS IS 2018 +a52787c41eced8a8|2023-07-28--00-12-38--4 +# LEXUS IS 2018 +c8c2f75d1782de03|2023-06-26--23-05-18--17 +# KIA SORENTO 4TH GEN +3c492c4530c6ad7f|2023-07-25--12-52-04--8 +# KIA SORENTO 4TH GEN +fd067a3a06f7bb3f|2023-07-18--19-05-41--2 +# HONDA CIVIC 2022 +35c004509e3057f2|2023-05-22--06-15-04--15 +# HONDA CIVIC 2022 +5130484aa8069bad|2023-05-20--17-37-41--2 +# HONDA CIVIC 2022 +8fcafab4167b8c6c|2023-06-24--15-42-50--55 +# KIA OPTIMA 4TH GEN FACELIFT +3d96bd05b5513638|2023-06-09--16-14-40--8 +# KIA OPTIMA 4TH GEN FACELIFT +fec0d754d02e943e|2023-06-19--14-54-54--144 +# HYUNDAI ELANTRA 2021 +3ea622c3c0ec3055|2023-06-22--18-40-28--15 +# HYUNDAI ELANTRA 2021 +449474d0a79c14aa|2023-07-30--15-41-03--10 +# HYUNDAI ELANTRA 2021 +5c9daa3b70d6f706|2023-08-05--15-56-10--2 +# HYUNDAI ELANTRA 2021 +5a4405495d2750ef|2023-05-13--21-13-20--16 +# HYUNDAI ELANTRA 2021 +be0bb3add22aeed0|2023-07-12--16-05-59--8 +# HYUNDAI ELANTRA 2021 +d8cd6e5e3998d306|2023-06-26--20-55-03--7 +# SKODA OCTAVIA 3RD GEN +3fa7570f2fcace3d|2023-08-02--14-13-00--2 +# SKODA OCTAVIA 3RD GEN +f5392228324cda8d|2023-07-19--09-22-26--1 +# KIA CARNIVAL 4TH GEN +409c9409979a8abc|2023-07-30--17-05-09--41 +# HYUNDAI IONIQ HYBRID 2020-2022 +452f244b23a48e9b|2023-07-19--18-49-50--5 +# KIA STINGER 2022 +47d09720bb2ccdf9|2023-06-05--20-25-36--6 +# COMMA BODY +4ae6d7a23dc12ee9|2023-07-22--18-04-32--2 +# COMMA BODY +8fb3c185d81fc85e|2023-08-06--14-57-51--5 +# COMMA BODY +efdf9af95e71cd84|2023-06-28--17-25-55--12 +# TOYOTA C-HR 2018 +482ce47555b39e90|2023-07-14--18-51-41--7 +# TOYOTA C-HR 2018 +4ff60f3f7178368b|2023-05-11--08-32-46--13 +# TOYOTA C-HR 2018 +fdf1eae234f98180|2023-05-24--09-19-26--1 +# TOYOTA AVALON 2016 +4bc88417168295f0|2023-07-28--18-04-07--71 +# TOYOTA AVALON 2016 +fe56ef3e908ceadc|2023-08-01--13-17-58--29 +# HONDA FIT 2018 +48536bafa6cabe3e|2023-06-14--14-50-06--6 +# HONDA FIT 2018 +8085a4d3c9416184|2023-07-27--15-31-59--9 +# HONDA FIT 2018 +a6883439bbd3d975|2023-05-30--17-28-13--26 +# HONDA FIT 2018 +e56002a2b1eeed4d|2023-07-04--13-32-44--4 +# MAZDA CX-9 2021 +51ffb2084fa16e13|2023-06-27--18-32-54--1 +# MAZDA CX-9 2021 +629c4aced073d15a|2023-06-13--12-03-56--5 +# MAZDA CX-9 2021 +ab2ef769ce18b0b2|2023-05-10--16-48-57--21 +# MAZDA CX-9 2021 +f04622e57618f6b8|2023-06-08--17-14-27--32 +# FORD BRONCO SPORT 1ST GEN +54827bf84c38b14f|2023-05-10--22-15-37--2 +# HYUNDAI IONIQ 5 2022 +5608f42aaece1463|2023-07-08--12-56-57--10 +# HYUNDAI IONIQ 5 2022 +57f8e21bb63728ed|2023-07-17--17-56-04--20 +# HYUNDAI IONIQ 5 2022 +534e3360c3936247|2023-08-03--10-30-38--6 +# HYUNDAI IONIQ 5 2022 +6c5e2106ca45c09f|2023-05-29--20-39-58--57 +# HYUNDAI IONIQ 5 2022 +8014970252341f77|2023-08-01--19-53-30--21 +# HYUNDAI IONIQ 5 2022 +81817870e9d2dc12|2023-06-24--21-37-09--23 +# HYUNDAI IONIQ 5 2022 +8379b28e51ceb3b1|2023-05-13--21-53-54--5 +# HYUNDAI IONIQ 5 2022 +8a53aa70d88313f1|2023-07-14--16-06-11--34 +# HYUNDAI IONIQ 5 2022 +94fb5be27a4b67b0|2023-07-02--21-38-55--55 +# HYUNDAI IONIQ 5 2022 +9a8af592c6b6b617|2023-05-18--07-24-13--121 +# HYUNDAI IONIQ 5 2022 +b70b56b76a6217f2|2023-06-02--14-53-42--63 +# HYUNDAI IONIQ 5 2022 +cb8f2450d9bc2438|2023-07-07--14-26-13--22 +# HYUNDAI IONIQ 5 2022 +cdc004f72f0192de|2023-06-20--17-46-52--10 +# HYUNDAI IONIQ 5 2022 +d172a844d3da91a4|2023-05-22--16-14-11--4 +# HYUNDAI IONIQ 5 2022 +dab2ee943375ae1f|2023-07-29--13-07-45--11 +# HYUNDAI IONIQ 5 2022 +db2f545ea314b36d|2023-07-05--16-54-15--19 +# HYUNDAI IONIQ 5 2022 +e42931599f753d96|2023-05-24--20-20-26--13 +# HYUNDAI IONIQ 5 2022 +f2a5efadd1dbf33f|2023-05-22--17-54-44--3 +# GENESIS GV70 1ST GEN +573d0052724c316d|2023-07-04--11-33-32--1 +# GENESIS GV70 1ST GEN +5d327dec6ec07b6e|2023-06-16--15-56-30--5 +# GENESIS GV70 1ST GEN +60c76f368ee05a23|2023-06-07--13-34-57--22 +# GENESIS GV70 1ST GEN +ca4de5b12321bd98|2023-05-10--08-48-48--7 +# KIA SPORTAGE 5TH GEN +5780f2cf75339e9f|2023-05-26--23-35-00--8 +# KIA SPORTAGE 5TH GEN +ce72415f25bcbf6f|2023-07-15--10-04-48--6 +# VOLKSWAGEN JETTA 7TH GEN +632ceb5cc1d7e3f3|2023-07-11--17-49-31--53 +# VOLKSWAGEN JETTA 7TH GEN +cf3717f55f9ff6bb|2023-05-21--23-17-16--13 +# TOYOTA C-HR 2021 +6719965b0e1d1737|2023-07-29--17-09-47--4 +# SKODA SUPERB 3RD GEN +6a6d9303aecc1e97|2023-07-12--09-56-43--13 +# SKODA SUPERB 3RD GEN +a7adec1fdbb46a1c|2023-07-31--22-39-06--2 +# SKODA SUPERB 3RD GEN +cd047d573cc78c34|2023-06-29--13-39-09--7 +# SKODA SUPERB 3RD GEN +d22f3f42780f2874|2023-07-11--17-43-18--45 +# NISSAN ALTIMA 2020 +62b0735d47268ec7|2023-06-23--18-44-12--11 +# NISSAN ALTIMA 2020 +742442ec7a49776d|2023-07-07--09-12-19--43 +# NISSAN ALTIMA 2020 +78daf6341d75cffb|2023-06-19--16-00-54--12 +# NISSAN ALTIMA 2020 +894145c25ba0328a|2023-06-24--14-39-55--18 +# NISSAN ALTIMA 2020 +92511c3b877c7215|2023-06-18--14-47-27--26 +# KIA SORENTO GT LINE 2018 +6b111e8e45cc2d07|2023-06-07--22-09-58--6 +# KIA SORENTO GT LINE 2018 +b78a19b557b991ab|2023-05-10--20-56-53--33 +# HYUNDAI TUCSON 4TH GEN +7173fdb19bf459f5|2023-06-02--20-50-49--14 +# HYUNDAI TUCSON 4TH GEN +8426de28ebdc65a2|2023-05-27--14-51-28--13 +# HYUNDAI TUCSON 4TH GEN +f7f6cc634ee443a9|2023-05-23--20-33-04--2 +# HYUNDAI ELANTRA 2017 +734ef96182ddf940|2023-07-12--14-31-45--34 +# SUBARU ASCENT LIMITED 2019 +72df1a0f641d5d4f|2023-06-30--17-17-26--7 +# SUBARU ASCENT LIMITED 2019 +91192c3ff5b51b64|2023-08-06--15-20-27--3 +# SUBARU ASCENT LIMITED 2019 +9936b4bbf75a5fe4|2023-05-12--14-23-02--16 +# SUBARU ASCENT LIMITED 2019 +cb9e6a98fd925948|2023-06-07--09-49-57--32 +# TESLA AP2 MODEL S +7277bddf4748e615|2023-05-10--10-30-06--11 +# HYUNDAI ELANTRA HYBRID 2021 +786fc028c014be71|2023-06-13--10-49-03--2 +# HYUNDAI ELANTRA HYBRID 2021 +8d49af2b041f8c5c|2023-07-06--17-34-04--36 +# HYUNDAI ELANTRA HYBRID 2021 +9b1bd7e1e54c6a37|2023-05-26--08-29-15--1 +# HYUNDAI ELANTRA HYBRID 2021 +d66b12aeb4ac1750|2023-08-04--14-14-48--5 +# HYUNDAI ELANTRA HYBRID 2021 +e33e369bf0cac9f5|2023-06-08--21-38-37--1 +# HYUNDAI ELANTRA HYBRID 2021 +eb5a50f9e98f50b9|2023-06-22--14-06-36--106 +# HYUNDAI ELANTRA HYBRID 2021 +f22818fb0dbd850d|2023-06-07--16-37-27--6 +# HYUNDAI SONATA 2019 +7ae1c131629d96e5|2023-06-01--18-40-26--18 +# HYUNDAI SONATA 2019 +c1fc13c1b806e536|2023-05-24--19-57-19--17 +# HYUNDAI SONATA 2019 +e3500498d01af116|2023-07-19--13-08-43--85 +# HYUNDAI TUCSON 4TH GEN +8afcf4c5d5b6d061|2023-05-14--20-29-14--9 +# HYUNDAI TUCSON 4TH GEN +a1f50efb97003e30|2023-05-17--20-13-07--1 +# HYUNDAI TUCSON 4TH GEN +c5956193b4fde1a3|2023-07-06--20-47-58--24 +# GENESIS GV60 ELECTRIC 1ST GEN +94542b2d06f7a9a6|2023-07-21--11-23-43--28 +# GENESIS GV60 ELECTRIC 1ST GEN +c9ccc00f8d7e00d2|2023-05-18--16-29-54--33 +# GENESIS G70 2018 +9238d5ce084d695e|2023-06-23--19-26-28--12 +# KIA SPORTAGE 5TH GEN +965a780ebeeed150|2023-07-25--07-16-08--40 +# KIA K5 2021 +9d4fa1c83653b90b|2023-07-10--07-30-25--14 +# ACURA RDX 2018 +a00bae406fe65d1c|2023-06-01--21-30-27--11 +# ACURA RDX 2018 +9f98fcb1aa88d319|2023-05-10--12-35-18--17 +# ACURA RDX 2018 +f41a6f453a4beb95|2023-06-25--07-00-46--23 +# FORD ESCAPE 4TH GEN +a4218e6416dfd978|2023-08-02--12-04-45--22 +# SEAT ATECA 1ST GEN +a4455cb22fa944d9|2023-05-19--16-54-51--6 +# VOLKSWAGEN TRANSPORTER T6.1 +a459f4556782eba1|2023-06-05--13-08-21--1 +# NISSAN ROGUE 2019 +ae2babeed1fe011f|2023-08-02--21-28-28--20 +# NISSAN ROGUE 2019 +b7287535e2a23992|2023-07-20--20-17-53--1 +# NISSAN ROGUE 2019 +dff9db8e8d8601f8|2023-05-14--18-00-16--30 +# KIA NIRO EV 2ND GEN +b153671049a867b3|2023-07-12--19-25-18--6 +# KIA NIRO HYBRID 2ND GEN +b1b094b91c2ceafd|2023-06-15--20-30-37--18 +# KIA NIRO HYBRID 2ND GEN +d250f6ef680e703d|2023-07-07--13-31-18--30 +# KIA NIRO HYBRID 2ND GEN +de8fc10be8a79842|2023-06-09--00-59-50--10 +# KIA NIRO HYBRID 2ND GEN +df54ba658aedc57c|2023-06-01--05-27-17--48 +# SEAT LEON 3RD GEN +aef9c04d6ec5cd57|2023-07-15--16-49-38--12 +# HYUNDAI SANTA CRUZ 1ST GEN +c00a40383605f531|2023-05-21--13-08-03--11 +# HONDA CR-V 2016 +bd96755604115d4c|2023-06-27--10-34-55--33 +# TOYOTA RAV4 2023 +c5e5740d799f017f|2023-08-08--13-23-41--7 +# FORD MAVERICK 1ST GEN +c72c220ce1de786f|2023-07-17--15-49-45--5 +# FORD MAVERICK 1ST GEN +c845bd8c366e6f3d|2023-06-29--19-03-50--12 +# CADILLAC ESCALADE 2017 +defd7f8491ad9254|2023-06-18--02-03-57--5 +# CADILLAC ESCALADE 2017 +ef8f2185104d862e|2023-07-29--18-02-25--18 +# TOYOTA C-HR 2021 +ea8fbe72b96a185c|2023-06-08--12-35-07--3 +# HYUNDAI KONA ELECTRIC 2022 +ecb854b94fdfa4d5|2023-05-27--00-04-01--45 +# KIA SORENTO HYBRID 4TH GEN +e8c813df1056766a|2023-05-26--19-01-03--34 +# NISSAN X-TRAIL 2017 +fa9224be239005c7|2023-07-30--14-28-52--18 +# NISSAN LEAF 2018 Instrument Cluster +fc10e0bf7dc6c892|2023-07-09--18-47-05--50 diff --git a/selfdrive/controls/.gitignore b/selfdrive/controls/.gitignore new file mode 100644 index 0000000000..22a371d8ff --- /dev/null +++ b/selfdrive/controls/.gitignore @@ -0,0 +1,2 @@ +calibration_param +traces diff --git a/selfdrive/controls/__init__.py b/selfdrive/controls/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py new file mode 100755 index 0000000000..029d16e59e --- /dev/null +++ b/selfdrive/controls/controlsd.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python3 +import math +from numbers import Number + +from cereal import car, log +import cereal.messaging as messaging +from openpilot.common.constants import CV +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper +from openpilot.common.swaglog import cloudlog + +from opendbc.car.car_helpers import interfaces +from opendbc.car.vehicle_model import VehicleModel +from openpilot.selfdrive.controls.lib.drive_helpers import clip_curvature +from openpilot.selfdrive.controls.lib.latcontrol import LatControl +from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID +from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle, STEER_ANGLE_SATURATION_THRESHOLD +from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque +from openpilot.selfdrive.controls.lib.longcontrol import LongControl +from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose + +State = log.SelfdriveState.OpenpilotState +LaneChangeState = log.LaneChangeState +LaneChangeDirection = log.LaneChangeDirection + +ACTUATOR_FIELDS = tuple(car.CarControl.Actuators.schema.fields.keys()) + + +class Controls: + def __init__(self) -> None: + self.params = Params() + cloudlog.info("controlsd is waiting for CarParams") + self.CP = messaging.log_from_bytes(self.params.get("CarParams", block=True), car.CarParams) + cloudlog.info("controlsd got CarParams") + + self.CI = interfaces[self.CP.carFingerprint](self.CP) + + self.sm = messaging.SubMaster(['liveParameters', 'liveTorqueParameters', 'modelV2', 'selfdriveState', + 'liveCalibration', 'livePose', 'longitudinalPlan', 'carState', 'carOutput', + 'driverMonitoringState', 'onroadEvents', 'driverAssistance'], poll='selfdriveState') + self.pm = messaging.PubMaster(['carControl', 'controlsState']) + + self.steer_limited_by_safety = False + self.curvature = 0.0 + self.desired_curvature = 0.0 + + self.pose_calibrator = PoseCalibrator() + self.calibrated_pose: Pose | None = None + + self.LoC = LongControl(self.CP) + self.VM = VehicleModel(self.CP) + self.LaC: LatControl + if self.CP.steerControlType == car.CarParams.SteerControlType.angle: + self.LaC = LatControlAngle(self.CP, self.CI) + elif self.CP.lateralTuning.which() == 'pid': + self.LaC = LatControlPID(self.CP, self.CI) + elif self.CP.lateralTuning.which() == 'torque': + self.LaC = LatControlTorque(self.CP, self.CI) + + def update(self): + self.sm.update(15) + if self.sm.updated["liveCalibration"]: + self.pose_calibrator.feed_live_calib(self.sm['liveCalibration']) + if self.sm.updated["livePose"]: + device_pose = Pose.from_live_pose(self.sm['livePose']) + self.calibrated_pose = self.pose_calibrator.build_calibrated_pose(device_pose) + + def state_control(self): + CS = self.sm['carState'] + + # Update VehicleModel + lp = self.sm['liveParameters'] + x = max(lp.stiffnessFactor, 0.1) + sr = max(lp.steerRatio, 0.1) + self.VM.update_params(x, sr) + + steer_angle_without_offset = math.radians(CS.steeringAngleDeg - lp.angleOffsetDeg) + self.curvature = -self.VM.calc_curvature(steer_angle_without_offset, CS.vEgo, lp.roll) + + # Update Torque Params + if self.CP.lateralTuning.which() == 'torque': + torque_params = self.sm['liveTorqueParameters'] + if self.sm.all_checks(['liveTorqueParameters']) and torque_params.useParams: + self.LaC.update_live_torque_params(torque_params.latAccelFactorFiltered, torque_params.latAccelOffsetFiltered, + torque_params.frictionCoefficientFiltered) + + long_plan = self.sm['longitudinalPlan'] + model_v2 = self.sm['modelV2'] + + CC = car.CarControl.new_message() + CC.enabled = self.sm['selfdriveState'].enabled + + # Check which actuators can be enabled + standstill = abs(CS.vEgo) <= max(self.CP.minSteerSpeed, 0.3) or CS.standstill + CC.latActive = self.sm['selfdriveState'].active and not CS.steerFaultTemporary and not CS.steerFaultPermanent and \ + (not standstill or self.CP.steerAtStandstill) + CC.longActive = CC.enabled and not any(e.overrideLongitudinal for e in self.sm['onroadEvents']) and self.CP.openpilotLongitudinalControl + + actuators = CC.actuators + actuators.longControlState = self.LoC.long_control_state + + # Enable blinkers while lane changing + if model_v2.meta.laneChangeState != LaneChangeState.off: + CC.leftBlinker = model_v2.meta.laneChangeDirection == LaneChangeDirection.left + CC.rightBlinker = model_v2.meta.laneChangeDirection == LaneChangeDirection.right + + if not CC.latActive: + self.LaC.reset() + if not CC.longActive: + self.LoC.reset() + + # accel PID loop + pid_accel_limits = self.CI.get_pid_accel_limits(self.CP, CS.vEgo, CS.vCruise * CV.KPH_TO_MS) + actuators.accel = float(self.LoC.update(CC.longActive, CS, long_plan.aTarget, long_plan.shouldStop, pid_accel_limits)) + + # Steering PID loop and lateral MPC + # Reset desired curvature to current to avoid violating the limits on engage + new_desired_curvature = model_v2.action.desiredCurvature if CC.latActive else self.curvature + self.desired_curvature, curvature_limited = clip_curvature(CS.vEgo, self.desired_curvature, new_desired_curvature, lp.roll) + + actuators.curvature = self.desired_curvature + steer, steeringAngleDeg, lac_log = self.LaC.update(CC.latActive, CS, self.VM, lp, + self.steer_limited_by_safety, self.desired_curvature, + curvature_limited) # TODO what if not available + actuators.torque = float(steer) + actuators.steeringAngleDeg = float(steeringAngleDeg) + # Ensure no NaNs/Infs + for p in ACTUATOR_FIELDS: + attr = getattr(actuators, p) + if not isinstance(attr, Number): + continue + + if not math.isfinite(attr): + cloudlog.error(f"actuators.{p} not finite {actuators.to_dict()}") + setattr(actuators, p, 0.0) + + return CC, lac_log + + def publish(self, CC, lac_log): + CS = self.sm['carState'] + + # Orientation and angle rates can be useful for carcontroller + # Only calibrated (car) frame is relevant for the carcontroller + CC.currentCurvature = self.curvature + if self.calibrated_pose is not None: + CC.orientationNED = self.calibrated_pose.orientation.xyz.tolist() + CC.angularVelocity = self.calibrated_pose.angular_velocity.xyz.tolist() + + CC.cruiseControl.override = CC.enabled and not CC.longActive and self.CP.openpilotLongitudinalControl + CC.cruiseControl.cancel = CS.cruiseState.enabled and (not CC.enabled or not self.CP.pcmCruise) + CC.cruiseControl.resume = CC.enabled and CS.cruiseState.standstill and not self.sm['longitudinalPlan'].shouldStop + + hudControl = CC.hudControl + hudControl.setSpeed = float(CS.vCruiseCluster * CV.KPH_TO_MS) + hudControl.speedVisible = CC.enabled + hudControl.lanesVisible = CC.enabled + hudControl.leadVisible = self.sm['longitudinalPlan'].hasLead + hudControl.leadDistanceBars = self.sm['selfdriveState'].personality.raw + 1 + hudControl.visualAlert = self.sm['selfdriveState'].alertHudVisual + + hudControl.rightLaneVisible = True + hudControl.leftLaneVisible = True + if self.sm.valid['driverAssistance']: + hudControl.leftLaneDepart = self.sm['driverAssistance'].leftLaneDeparture + hudControl.rightLaneDepart = self.sm['driverAssistance'].rightLaneDeparture + + if self.sm['selfdriveState'].active: + CO = self.sm['carOutput'] + if self.CP.steerControlType == car.CarParams.SteerControlType.angle: + self.steer_limited_by_safety = abs(CC.actuators.steeringAngleDeg - CO.actuatorsOutput.steeringAngleDeg) > \ + STEER_ANGLE_SATURATION_THRESHOLD + else: + self.steer_limited_by_safety = abs(CC.actuators.torque - CO.actuatorsOutput.torque) > 1e-2 + + # TODO: both controlsState and carControl valids should be set by + # sm.all_checks(), but this creates a circular dependency + + # controlsState + dat = messaging.new_message('controlsState') + dat.valid = CS.canValid + cs = dat.controlsState + + cs.curvature = self.curvature + cs.longitudinalPlanMonoTime = self.sm.logMonoTime['longitudinalPlan'] + cs.lateralPlanMonoTime = self.sm.logMonoTime['modelV2'] + cs.desiredCurvature = self.desired_curvature + cs.longControlState = self.LoC.long_control_state + cs.upAccelCmd = float(self.LoC.pid.p) + cs.uiAccelCmd = float(self.LoC.pid.i) + cs.ufAccelCmd = float(self.LoC.pid.f) + cs.forceDecel = bool((self.sm['driverMonitoringState'].awarenessStatus < 0.) or + (self.sm['selfdriveState'].state == State.softDisabling)) + + lat_tuning = self.CP.lateralTuning.which() + if self.CP.steerControlType == car.CarParams.SteerControlType.angle: + cs.lateralControlState.angleState = lac_log + elif lat_tuning == 'pid': + cs.lateralControlState.pidState = lac_log + elif lat_tuning == 'torque': + cs.lateralControlState.torqueState = lac_log + + self.pm.send('controlsState', dat) + + # carControl + cc_send = messaging.new_message('carControl') + cc_send.valid = CS.canValid + cc_send.carControl = CC + self.pm.send('carControl', cc_send) + + def run(self): + rk = Ratekeeper(100, print_delay_threshold=None) + while True: + self.update() + CC, lac_log = self.state_control() + self.publish(CC, lac_log) + rk.monitor_time() + + +def main(): + config_realtime_process(4, Priority.CTRL_HIGH) + controls = Controls() + controls.run() + + +if __name__ == "__main__": + main() diff --git a/selfdrive/controls/lib/__init__.py b/selfdrive/controls/lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/controls/lib/desire_helper.py b/selfdrive/controls/lib/desire_helper.py new file mode 100644 index 0000000000..ee4567f1e9 --- /dev/null +++ b/selfdrive/controls/lib/desire_helper.py @@ -0,0 +1,119 @@ +from cereal import log +from openpilot.common.constants import CV +from openpilot.common.realtime import DT_MDL + +LaneChangeState = log.LaneChangeState +LaneChangeDirection = log.LaneChangeDirection + +LANE_CHANGE_SPEED_MIN = 20 * CV.MPH_TO_MS +LANE_CHANGE_TIME_MAX = 10. + +DESIRES = { + LaneChangeDirection.none: { + LaneChangeState.off: log.Desire.none, + LaneChangeState.preLaneChange: log.Desire.none, + LaneChangeState.laneChangeStarting: log.Desire.none, + LaneChangeState.laneChangeFinishing: log.Desire.none, + }, + LaneChangeDirection.left: { + LaneChangeState.off: log.Desire.none, + LaneChangeState.preLaneChange: log.Desire.none, + LaneChangeState.laneChangeStarting: log.Desire.laneChangeLeft, + LaneChangeState.laneChangeFinishing: log.Desire.laneChangeLeft, + }, + LaneChangeDirection.right: { + LaneChangeState.off: log.Desire.none, + LaneChangeState.preLaneChange: log.Desire.none, + LaneChangeState.laneChangeStarting: log.Desire.laneChangeRight, + LaneChangeState.laneChangeFinishing: log.Desire.laneChangeRight, + }, +} + + +class DesireHelper: + def __init__(self): + self.lane_change_state = LaneChangeState.off + self.lane_change_direction = LaneChangeDirection.none + self.lane_change_timer = 0.0 + self.lane_change_ll_prob = 1.0 + self.keep_pulse_timer = 0.0 + self.prev_one_blinker = False + self.desire = log.Desire.none + + @staticmethod + def get_lane_change_direction(CS): + return LaneChangeDirection.left if CS.leftBlinker else LaneChangeDirection.right + + def update(self, carstate, lateral_active, lane_change_prob): + v_ego = carstate.vEgo + one_blinker = carstate.leftBlinker != carstate.rightBlinker + below_lane_change_speed = v_ego < LANE_CHANGE_SPEED_MIN + + if not lateral_active or self.lane_change_timer > LANE_CHANGE_TIME_MAX: + self.lane_change_state = LaneChangeState.off + self.lane_change_direction = LaneChangeDirection.none + else: + # LaneChangeState.off + if self.lane_change_state == LaneChangeState.off and one_blinker and not self.prev_one_blinker and not below_lane_change_speed: + self.lane_change_state = LaneChangeState.preLaneChange + self.lane_change_ll_prob = 1.0 + # Initialize lane change direction to prevent UI alert flicker + self.lane_change_direction = self.get_lane_change_direction(carstate) + + # LaneChangeState.preLaneChange + elif self.lane_change_state == LaneChangeState.preLaneChange: + # Update lane change direction + self.lane_change_direction = self.get_lane_change_direction(carstate) + + torque_applied = carstate.steeringPressed and \ + ((carstate.steeringTorque > 0 and self.lane_change_direction == LaneChangeDirection.left) or + (carstate.steeringTorque < 0 and self.lane_change_direction == LaneChangeDirection.right)) + + blindspot_detected = ((carstate.leftBlindspot and self.lane_change_direction == LaneChangeDirection.left) or + (carstate.rightBlindspot and self.lane_change_direction == LaneChangeDirection.right)) + + if not one_blinker or below_lane_change_speed: + self.lane_change_state = LaneChangeState.off + self.lane_change_direction = LaneChangeDirection.none + elif torque_applied and not blindspot_detected: + self.lane_change_state = LaneChangeState.laneChangeStarting + + # LaneChangeState.laneChangeStarting + elif self.lane_change_state == LaneChangeState.laneChangeStarting: + # fade out over .5s + self.lane_change_ll_prob = max(self.lane_change_ll_prob - 2 * DT_MDL, 0.0) + + # 98% certainty + if lane_change_prob < 0.02 and self.lane_change_ll_prob < 0.01: + self.lane_change_state = LaneChangeState.laneChangeFinishing + + # LaneChangeState.laneChangeFinishing + elif self.lane_change_state == LaneChangeState.laneChangeFinishing: + # fade in laneline over 1s + self.lane_change_ll_prob = min(self.lane_change_ll_prob + DT_MDL, 1.0) + + if self.lane_change_ll_prob > 0.99: + self.lane_change_direction = LaneChangeDirection.none + if one_blinker: + self.lane_change_state = LaneChangeState.preLaneChange + else: + self.lane_change_state = LaneChangeState.off + + if self.lane_change_state in (LaneChangeState.off, LaneChangeState.preLaneChange): + self.lane_change_timer = 0.0 + else: + self.lane_change_timer += DT_MDL + + self.prev_one_blinker = one_blinker + + self.desire = DESIRES[self.lane_change_direction][self.lane_change_state] + + # Send keep pulse once per second during LaneChangeStart.preLaneChange + if self.lane_change_state in (LaneChangeState.off, LaneChangeState.laneChangeStarting): + self.keep_pulse_timer = 0.0 + elif self.lane_change_state == LaneChangeState.preLaneChange: + self.keep_pulse_timer += DT_MDL + if self.keep_pulse_timer > 1.0: + self.keep_pulse_timer = 0.0 + elif self.desire in (log.Desire.keepLeft, log.Desire.keepRight): + self.desire = log.Desire.none diff --git a/selfdrive/controls/lib/drive_helpers.py b/selfdrive/controls/lib/drive_helpers.py new file mode 100644 index 0000000000..e28fa3021c --- /dev/null +++ b/selfdrive/controls/lib/drive_helpers.py @@ -0,0 +1,65 @@ +import numpy as np +from openpilot.common.constants import ACCELERATION_DUE_TO_GRAVITY +from openpilot.common.realtime import DT_CTRL, DT_MDL + +MIN_SPEED = 1.0 +CONTROL_N = 17 +CAR_ROTATION_RADIUS = 0.0 +# This is a turn radius smaller than most cars can achieve +MAX_CURVATURE = 0.2 +MAX_VEL_ERR = 5.0 # m/s + +# EU guidelines +MAX_LATERAL_JERK = 5.0 # m/s^3 +MAX_LATERAL_ACCEL_NO_ROLL = 3.0 # m/s^2 + + +def clamp(val, min_val, max_val): + clamped_val = float(np.clip(val, min_val, max_val)) + return clamped_val, clamped_val != val + +def smooth_value(val, prev_val, tau, dt=DT_MDL): + alpha = 1 - np.exp(-dt/tau) if tau > 0 else 1 + return alpha * val + (1 - alpha) * prev_val + +def clip_curvature(v_ego, prev_curvature, new_curvature, roll): + # This function respects ISO lateral jerk and acceleration limits + a max curvature + v_ego = max(v_ego, MIN_SPEED) + max_curvature_rate = MAX_LATERAL_JERK / (v_ego ** 2) # inexact calculation, check https://github.com/commaai/openpilot/pull/24755 + new_curvature = np.clip(new_curvature, + prev_curvature - max_curvature_rate * DT_CTRL, + prev_curvature + max_curvature_rate * DT_CTRL) + + roll_compensation = roll * ACCELERATION_DUE_TO_GRAVITY + max_lat_accel = MAX_LATERAL_ACCEL_NO_ROLL + roll_compensation + min_lat_accel = -MAX_LATERAL_ACCEL_NO_ROLL + roll_compensation + new_curvature, limited_accel = clamp(new_curvature, min_lat_accel / v_ego ** 2, max_lat_accel / v_ego ** 2) + + new_curvature, limited_max_curv = clamp(new_curvature, -MAX_CURVATURE, MAX_CURVATURE) + return float(new_curvature), limited_accel or limited_max_curv + + +def get_accel_from_plan(speeds, accels, t_idxs, action_t=DT_MDL, vEgoStopping=0.05): + if len(speeds) == len(t_idxs): + v_now = speeds[0] + a_now = accels[0] + v_target = np.interp(action_t, t_idxs, speeds) + a_target = 2 * (v_target - v_now) / (action_t) - a_now + v_target_1sec = np.interp(action_t + 1.0, t_idxs, speeds) + else: + v_target = 0.0 + v_target_1sec = 0.0 + a_target = 0.0 + should_stop = (v_target < vEgoStopping and + v_target_1sec < vEgoStopping) + return a_target, should_stop + +def curv_from_psis(psi_target, psi_rate, vego, action_t): + vego = np.clip(vego, MIN_SPEED, np.inf) + curv_from_psi = psi_target / (vego * action_t) + return 2*curv_from_psi - psi_rate / vego + +def get_curvature_from_plan(yaws, yaw_rates, t_idxs, vego, action_t): + psi_target = np.interp(action_t, t_idxs, yaws) + psi_rate = yaw_rates[0] + return curv_from_psis(psi_target, psi_rate, vego, action_t) diff --git a/selfdrive/controls/lib/latcontrol.py b/selfdrive/controls/lib/latcontrol.py new file mode 100644 index 0000000000..2a8b873e2e --- /dev/null +++ b/selfdrive/controls/lib/latcontrol.py @@ -0,0 +1,31 @@ +import numpy as np +from abc import abstractmethod, ABC + +from openpilot.common.realtime import DT_CTRL + + +class LatControl(ABC): + def __init__(self, CP, CI): + self.sat_count_rate = 1.0 * DT_CTRL + self.sat_limit = CP.steerLimitTimer + self.sat_count = 0. + self.sat_check_min_speed = 10. + + # we define the steer torque scale as [-1.0...1.0] + self.steer_max = 1.0 + + @abstractmethod + def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, calibrated_pose, curvature_limited): + pass + + def reset(self): + self.sat_count = 0. + + def _check_saturation(self, saturated, CS, steer_limited_by_safety, curvature_limited): + # Saturated only if control output is not being limited by car torque/angle rate limits + if (saturated or curvature_limited) and CS.vEgo > self.sat_check_min_speed and not steer_limited_by_safety and not CS.steeringPressed: + self.sat_count += self.sat_count_rate + else: + self.sat_count -= self.sat_count_rate + self.sat_count = np.clip(self.sat_count, 0.0, self.sat_limit) + return self.sat_count > (self.sat_limit - 1e-3) diff --git a/selfdrive/controls/lib/latcontrol_angle.py b/selfdrive/controls/lib/latcontrol_angle.py new file mode 100644 index 0000000000..ac35151487 --- /dev/null +++ b/selfdrive/controls/lib/latcontrol_angle.py @@ -0,0 +1,37 @@ +import math + +from cereal import log +from openpilot.selfdrive.controls.lib.latcontrol import LatControl + +# TODO This is speed dependent +STEER_ANGLE_SATURATION_THRESHOLD = 2.5 # Degrees + + +class LatControlAngle(LatControl): + def __init__(self, CP, CI): + super().__init__(CP, CI) + self.sat_check_min_speed = 5. + self.use_steer_limited_by_safety = CP.brand == "tesla" + + def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, curvature_limited): + angle_log = log.ControlsState.LateralAngleState.new_message() + + if not active: + angle_log.active = False + angle_steers_des = float(CS.steeringAngleDeg) + else: + angle_log.active = True + angle_steers_des = math.degrees(VM.get_steer_from_curvature(-desired_curvature, CS.vEgo, params.roll)) + angle_steers_des += params.angleOffsetDeg + + if self.use_steer_limited_by_safety: + # these cars' carcontrollers calculate max lateral accel and jerk, so we can rely on carOutput for saturation + angle_control_saturated = steer_limited_by_safety + else: + # for cars which use a method of limiting torque such as a torque signal (Nissan and Toyota) + # or relying on EPS (Ford Q3), carOutput does not capture maxing out torque # TODO: this can be improved + angle_control_saturated = abs(angle_steers_des - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD + angle_log.saturated = bool(self._check_saturation(angle_control_saturated, CS, False, curvature_limited)) + angle_log.steeringAngleDeg = float(CS.steeringAngleDeg) + angle_log.steeringAngleDesiredDeg = angle_steers_des + return 0, float(angle_steers_des), angle_log diff --git a/selfdrive/controls/lib/latcontrol_pid.py b/selfdrive/controls/lib/latcontrol_pid.py new file mode 100644 index 0000000000..00a083509f --- /dev/null +++ b/selfdrive/controls/lib/latcontrol_pid.py @@ -0,0 +1,48 @@ +import math + +from cereal import log +from openpilot.selfdrive.controls.lib.latcontrol import LatControl +from openpilot.common.pid import PIDController + + +class LatControlPID(LatControl): + def __init__(self, CP, CI): + super().__init__(CP, CI) + self.pid = PIDController((CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV), + (CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV), + k_f=CP.lateralTuning.pid.kf, pos_limit=self.steer_max, neg_limit=-self.steer_max) + self.get_steer_feedforward = CI.get_steer_feedforward_function() + + def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, curvature_limited): + pid_log = log.ControlsState.LateralPIDState.new_message() + pid_log.steeringAngleDeg = float(CS.steeringAngleDeg) + pid_log.steeringRateDeg = float(CS.steeringRateDeg) + + angle_steers_des_no_offset = math.degrees(VM.get_steer_from_curvature(-desired_curvature, CS.vEgo, params.roll)) + angle_steers_des = angle_steers_des_no_offset + params.angleOffsetDeg + error = angle_steers_des - CS.steeringAngleDeg + + pid_log.steeringAngleDesiredDeg = angle_steers_des + pid_log.angleError = error + if not active: + output_torque = 0.0 + pid_log.active = False + + else: + # offset does not contribute to resistive torque + ff = self.get_steer_feedforward(angle_steers_des_no_offset, CS.vEgo) + freeze_integrator = steer_limited_by_safety or CS.steeringPressed or CS.vEgo < 5 + + output_torque = self.pid.update(error, + feedforward=ff, + speed=CS.vEgo, + freeze_integrator=freeze_integrator) + + pid_log.active = True + pid_log.p = float(self.pid.p) + pid_log.i = float(self.pid.i) + pid_log.f = float(self.pid.f) + pid_log.output = float(output_torque) + pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_safety, curvature_limited)) + + return output_torque, angle_steers_des, pid_log diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py new file mode 100644 index 0000000000..5a2814e089 --- /dev/null +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -0,0 +1,90 @@ +import math +import numpy as np + +from cereal import log +from opendbc.car.lateral import FRICTION_THRESHOLD, get_friction +from openpilot.common.constants import ACCELERATION_DUE_TO_GRAVITY +from openpilot.selfdrive.controls.lib.latcontrol import LatControl +from openpilot.common.pid import PIDController + +# At higher speeds (25+mph) we can assume: +# Lateral acceleration achieved by a specific car correlates to +# torque applied to the steering rack. It does not correlate to +# wheel slip, or to speed. + +# This controller applies torque to achieve desired lateral +# accelerations. To compensate for the low speed effects we +# use a LOW_SPEED_FACTOR in the error. Additionally, there is +# friction in the steering wheel that needs to be overcome to +# move it at all, this is compensated for too. + +LOW_SPEED_X = [0, 10, 20, 30] +LOW_SPEED_Y = [15, 13, 10, 5] + + +class LatControlTorque(LatControl): + def __init__(self, CP, CI): + super().__init__(CP, CI) + self.torque_params = CP.lateralTuning.torque.as_builder() + self.torque_from_lateral_accel = CI.torque_from_lateral_accel() + self.lateral_accel_from_torque = CI.lateral_accel_from_torque() + self.pid = PIDController(self.torque_params.kp, self.torque_params.ki, + k_f=self.torque_params.kf) + self.update_limits() + self.steering_angle_deadzone_deg = self.torque_params.steeringAngleDeadzoneDeg + + def update_live_torque_params(self, latAccelFactor, latAccelOffset, friction): + self.torque_params.latAccelFactor = latAccelFactor + self.torque_params.latAccelOffset = latAccelOffset + self.torque_params.friction = friction + self.update_limits() + + def update_limits(self): + self.pid.set_limits(self.lateral_accel_from_torque(self.steer_max, self.torque_params), + self.lateral_accel_from_torque(-self.steer_max, self.torque_params)) + + def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, curvature_limited): + pid_log = log.ControlsState.LateralTorqueState.new_message() + if not active: + output_torque = 0.0 + pid_log.active = False + else: + actual_curvature = -VM.calc_curvature(math.radians(CS.steeringAngleDeg - params.angleOffsetDeg), CS.vEgo, params.roll) + roll_compensation = params.roll * ACCELERATION_DUE_TO_GRAVITY + curvature_deadzone = abs(VM.calc_curvature(math.radians(self.steering_angle_deadzone_deg), CS.vEgo, 0.0)) + + desired_lateral_accel = desired_curvature * CS.vEgo ** 2 + actual_lateral_accel = actual_curvature * CS.vEgo ** 2 + lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 + + low_speed_factor = np.interp(CS.vEgo, LOW_SPEED_X, LOW_SPEED_Y)**2 + setpoint = desired_lateral_accel + low_speed_factor * desired_curvature + measurement = actual_lateral_accel + low_speed_factor * actual_curvature + gravity_adjusted_lateral_accel = desired_lateral_accel - roll_compensation + + # do error correction in lateral acceleration space, convert at end to handle non-linear torque responses correctly + pid_log.error = float(setpoint - measurement) + ff = gravity_adjusted_lateral_accel + # latAccelOffset corrects roll compensation bias from device roll misalignment relative to car roll + ff -= self.torque_params.latAccelOffset + ff += get_friction(desired_lateral_accel - actual_lateral_accel, lateral_accel_deadzone, FRICTION_THRESHOLD, self.torque_params) + + freeze_integrator = steer_limited_by_safety or CS.steeringPressed or CS.vEgo < 5 + output_lataccel = self.pid.update(pid_log.error, + feedforward=ff, + speed=CS.vEgo, + freeze_integrator=freeze_integrator) + output_torque = self.torque_from_lateral_accel(output_lataccel, self.torque_params) + + pid_log.active = True + pid_log.p = float(self.pid.p) + pid_log.i = float(self.pid.i) + pid_log.d = float(self.pid.d) + pid_log.f = float(self.pid.f) + pid_log.output = float(-output_torque) # TODO: log lat accel? + pid_log.actualLateralAccel = float(actual_lateral_accel) + pid_log.desiredLateralAccel = float(desired_lateral_accel) + pid_log.saturated = bool(self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited_by_safety, curvature_limited)) + + # TODO left is positive in this convention + return -output_torque, 0.0, pid_log diff --git a/selfdrive/controls/lib/lateral_mpc_lib/.gitignore b/selfdrive/controls/lib/lateral_mpc_lib/.gitignore new file mode 100644 index 0000000000..aff2eb082b --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc_lib/.gitignore @@ -0,0 +1,2 @@ +acados_ocp_lat.json +c_generated_code/ diff --git a/selfdrive/controls/lib/lateral_mpc_lib/SConscript b/selfdrive/controls/lib/lateral_mpc_lib/SConscript new file mode 100644 index 0000000000..c9ebf89207 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc_lib/SConscript @@ -0,0 +1,97 @@ +Import('env', 'envCython', 'arch', 'msgq_python', 'common_python', 'np_version') + +gen = "c_generated_code" + +casadi_model = [ + f'{gen}/lat_model/lat_expl_ode_fun.c', + f'{gen}/lat_model/lat_expl_vde_forw.c', +] + +casadi_cost_y = [ + f'{gen}/lat_cost/lat_cost_y_fun.c', + f'{gen}/lat_cost/lat_cost_y_fun_jac_ut_xt.c', + f'{gen}/lat_cost/lat_cost_y_hess.c', +] + +casadi_cost_e = [ + f'{gen}/lat_cost/lat_cost_y_e_fun.c', + f'{gen}/lat_cost/lat_cost_y_e_fun_jac_ut_xt.c', + f'{gen}/lat_cost/lat_cost_y_e_hess.c', +] + +casadi_cost_0 = [ + f'{gen}/lat_cost/lat_cost_y_0_fun.c', + f'{gen}/lat_cost/lat_cost_y_0_fun_jac_ut_xt.c', + f'{gen}/lat_cost/lat_cost_y_0_hess.c', +] + +build_files = [f'{gen}/acados_solver_lat.c'] + casadi_model + casadi_cost_y + casadi_cost_e + casadi_cost_0 + +# extra generated files used to trigger a rebuild +generated_files = [ + f'{gen}/Makefile', + + f'{gen}/main_lat.c', + f'{gen}/main_sim_lat.c', + f'{gen}/acados_solver_lat.h', + f'{gen}/acados_sim_solver_lat.h', + f'{gen}/acados_sim_solver_lat.c', + f'{gen}/acados_solver.pxd', + + f'{gen}/lat_model/lat_expl_vde_adj.c', + + f'{gen}/lat_model/lat_model.h', + f'{gen}/lat_constraints/lat_constraints.h', + f'{gen}/lat_cost/lat_cost.h', +] + build_files + +acados_dir = '#third_party/acados' +acados_templates_dir = '#third_party/acados/acados_template/c_templates_tera' + +source_list = ['lat_mpc.py', + '#selfdrive/modeld/constants.py', + f'{acados_dir}/include/acados_c/ocp_nlp_interface.h', + f'{acados_templates_dir}/acados_solver.in.c', +] + +lenv = env.Clone() +acados_rel_path = Dir(gen).rel_path(Dir(f"#third_party/acados/{arch}/lib")) +lenv["RPATH"] += [lenv.Literal(f'\\$$ORIGIN/{acados_rel_path}')] +lenv.Clean(generated_files, Dir(gen)) + +generated_lat = lenv.Command(generated_files, + source_list, + f"cd {Dir('.').abspath} && python3 lat_mpc.py") +lenv.Depends(generated_lat, [msgq_python, common_python]) + +lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES") +lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES") +lenv["CCFLAGS"].append("-Wno-unused") +if arch != "Darwin": + lenv["LINKFLAGS"].append("-Wl,--disable-new-dtags") +else: + lenv["LINKFLAGS"].append("-Wl,-install_name,@loader_path/libacados_ocp_solver_lat.dylib") + lenv["LINKFLAGS"].append(f"-Wl,-rpath,@loader_path/{acados_rel_path}") +lib_solver = lenv.SharedLibrary(f"{gen}/acados_ocp_solver_lat", + build_files, + LIBS=['m', 'acados', 'hpipm', 'blasfeo', 'qpOASES_e']) + +# generate cython stuff +acados_ocp_solver_pyx = File("#third_party/acados/acados_template/acados_ocp_solver_pyx.pyx") +acados_ocp_solver_common = File("#third_party/acados/acados_template/acados_solver_common.pxd") +libacados_ocp_solver_pxd = File(f'{gen}/acados_solver.pxd') +libacados_ocp_solver_c = File(f'{gen}/acados_ocp_solver_pyx.c') + +lenv2 = envCython.Clone() +lenv2["LIBPATH"] += [lib_solver[0].dir.abspath] +lenv2["RPATH"] += [lenv2.Literal('\\$$ORIGIN')] +lenv2.Command(libacados_ocp_solver_c, + [acados_ocp_solver_pyx, acados_ocp_solver_common, libacados_ocp_solver_pxd], + f'cython' + \ + f' -o {libacados_ocp_solver_c.get_labspath()}' + \ + f' -I {libacados_ocp_solver_pxd.get_dir().get_labspath()}' + \ + f' -I {acados_ocp_solver_common.get_dir().get_labspath()}' + \ + f' {acados_ocp_solver_pyx.get_labspath()}') +lib_cython = lenv2.Program(f'{gen}/acados_ocp_solver_pyx.so', [libacados_ocp_solver_c], LIBS=['acados_ocp_solver_lat']) +lenv2.Depends(lib_cython, lib_solver) +lenv2.Depends(libacados_ocp_solver_c, np_version) diff --git a/selfdrive/controls/lib/lateral_mpc_lib/__init__.py b/selfdrive/controls/lib/lateral_mpc_lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py b/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py new file mode 100755 index 0000000000..ad60861088 --- /dev/null +++ b/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +import os +import time +import numpy as np + +from casadi import SX, vertcat, sin, cos +# WARNING: imports outside of constants will not trigger a rebuild +from openpilot.selfdrive.modeld.constants import ModelConstants + +if __name__ == '__main__': # generating code + from openpilot.third_party.acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver +else: + from openpilot.selfdrive.controls.lib.lateral_mpc_lib.c_generated_code.acados_ocp_solver_pyx import AcadosOcpSolverCython + +LAT_MPC_DIR = os.path.dirname(os.path.abspath(__file__)) +EXPORT_DIR = os.path.join(LAT_MPC_DIR, "c_generated_code") +JSON_FILE = os.path.join(LAT_MPC_DIR, "acados_ocp_lat.json") +X_DIM = 4 +P_DIM = 2 +COST_E_DIM = 3 +COST_DIM = COST_E_DIM + 2 +SPEED_OFFSET = 10.0 +MODEL_NAME = 'lat' +ACADOS_SOLVER_TYPE = 'SQP_RTI' +N = 32 + +def gen_lat_model(): + model = AcadosModel() + model.name = MODEL_NAME + + # set up states & controls + x_ego = SX.sym('x_ego') + y_ego = SX.sym('y_ego') + psi_ego = SX.sym('psi_ego') + psi_rate_ego = SX.sym('psi_rate_ego') + model.x = vertcat(x_ego, y_ego, psi_ego, psi_rate_ego) + + # parameters + v_ego = SX.sym('v_ego') + rotation_radius = SX.sym('rotation_radius') + model.p = vertcat(v_ego, rotation_radius) + + # controls + psi_accel_ego = SX.sym('psi_accel_ego') + model.u = vertcat(psi_accel_ego) + + # xdot + x_ego_dot = SX.sym('x_ego_dot') + y_ego_dot = SX.sym('y_ego_dot') + psi_ego_dot = SX.sym('psi_ego_dot') + psi_rate_ego_dot = SX.sym('psi_rate_ego_dot') + + model.xdot = vertcat(x_ego_dot, y_ego_dot, psi_ego_dot, psi_rate_ego_dot) + + # dynamics model + f_expl = vertcat(v_ego * cos(psi_ego) - rotation_radius * sin(psi_ego) * psi_rate_ego, + v_ego * sin(psi_ego) + rotation_radius * cos(psi_ego) * psi_rate_ego, + psi_rate_ego, + psi_accel_ego) + model.f_impl_expr = model.xdot - f_expl + model.f_expl_expr = f_expl + return model + + +def gen_lat_ocp(): + ocp = AcadosOcp() + ocp.model = gen_lat_model() + + Tf = np.array(ModelConstants.T_IDXS)[N] + + # set dimensions + ocp.dims.N = N + + # set cost module + ocp.cost.cost_type = 'NONLINEAR_LS' + ocp.cost.cost_type_e = 'NONLINEAR_LS' + + Q = np.diag(np.zeros(COST_E_DIM)) + QR = np.diag(np.zeros(COST_DIM)) + + ocp.cost.W = QR + ocp.cost.W_e = Q + + y_ego, psi_ego, psi_rate_ego = ocp.model.x[1], ocp.model.x[2], ocp.model.x[3] + psi_rate_ego_dot = ocp.model.u[0] + v_ego = ocp.model.p[0] + + ocp.parameter_values = np.zeros((P_DIM, )) + + ocp.cost.yref = np.zeros((COST_DIM, )) + ocp.cost.yref_e = np.zeros((COST_E_DIM, )) + # Add offset to smooth out low speed control + # TODO unclear if this right solution long term + v_ego_offset = v_ego + SPEED_OFFSET + # TODO there are two costs on psi_rate_ego_dot, one + # is correlated to jerk the other to steering wheel movement + # the steering wheel movement cost is added to prevent excessive + # wheel movements + ocp.model.cost_y_expr = vertcat(y_ego, + v_ego_offset * psi_ego, + v_ego_offset * psi_rate_ego, + v_ego_offset * psi_rate_ego_dot, + psi_rate_ego_dot / (v_ego + 0.1)) + ocp.model.cost_y_expr_e = vertcat(y_ego, + v_ego_offset * psi_ego, + v_ego_offset * psi_rate_ego) + + # set constraints + ocp.constraints.constr_type = 'BGH' + ocp.constraints.idxbx = np.array([2,3]) + ocp.constraints.ubx = np.array([np.radians(90), np.radians(50)]) + ocp.constraints.lbx = np.array([-np.radians(90), -np.radians(50)]) + x0 = np.zeros((X_DIM,)) + ocp.constraints.x0 = x0 + + ocp.solver_options.qp_solver = 'PARTIAL_CONDENSING_HPIPM' + ocp.solver_options.hessian_approx = 'GAUSS_NEWTON' + ocp.solver_options.integrator_type = 'ERK' + ocp.solver_options.nlp_solver_type = ACADOS_SOLVER_TYPE + ocp.solver_options.qp_solver_iter_max = 1 + ocp.solver_options.qp_solver_cond_N = 1 + + # set prediction horizon + ocp.solver_options.tf = Tf + ocp.solver_options.shooting_nodes = np.array(ModelConstants.T_IDXS)[:N+1] + + ocp.code_export_directory = EXPORT_DIR + return ocp + + +class LateralMpc: + def __init__(self, x0=None): + if x0 is None: + x0 = np.zeros(X_DIM) + self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N) + self.reset(x0) + + def reset(self, x0=None): + if x0 is None: + x0 = np.zeros(X_DIM) + self.x_sol = np.zeros((N+1, X_DIM)) + self.u_sol = np.zeros((N, 1)) + self.yref = np.zeros((N+1, COST_DIM)) + for i in range(N): + self.solver.cost_set(i, "yref", self.yref[i]) + self.solver.cost_set(N, "yref", self.yref[N][:COST_E_DIM]) + + # Somehow needed for stable init + for i in range(N+1): + self.solver.set(i, 'x', np.zeros(X_DIM)) + self.solver.set(i, 'p', np.zeros(P_DIM)) + self.solver.constraints_set(0, "lbx", x0) + self.solver.constraints_set(0, "ubx", x0) + self.solver.solve() + self.solution_status = 0 + self.solve_time = 0.0 + self.cost = 0 + + def set_weights(self, path_weight, heading_weight, + lat_accel_weight, lat_jerk_weight, + steering_rate_weight): + W = np.asfortranarray(np.diag([path_weight, heading_weight, + lat_accel_weight, lat_jerk_weight, + steering_rate_weight])) + for i in range(N): + self.solver.cost_set(i, 'W', W) + self.solver.cost_set(N, 'W', W[:COST_E_DIM,:COST_E_DIM]) + + def run(self, x0, p, y_pts, heading_pts, yaw_rate_pts): + x0_cp = np.copy(x0) + p_cp = np.copy(p) + self.solver.constraints_set(0, "lbx", x0_cp) + self.solver.constraints_set(0, "ubx", x0_cp) + self.yref[:,0] = y_pts + v_ego = p_cp[0, 0] + # rotation_radius = p_cp[1] + self.yref[:,1] = heading_pts * (v_ego + SPEED_OFFSET) + self.yref[:,2] = yaw_rate_pts * (v_ego + SPEED_OFFSET) + for i in range(N): + self.solver.cost_set(i, "yref", self.yref[i]) + self.solver.set(i, "p", p_cp[i]) + self.solver.set(N, "p", p_cp[N]) + self.solver.cost_set(N, "yref", self.yref[N][:COST_E_DIM]) + + t = time.monotonic() + self.solution_status = self.solver.solve() + self.solve_time = time.monotonic() - t + + for i in range(N+1): + self.x_sol[i] = self.solver.get(i, 'x') + for i in range(N): + self.u_sol[i] = self.solver.get(i, 'u') + self.cost = self.solver.get_cost() + + +if __name__ == "__main__": + ocp = gen_lat_ocp() + AcadosOcpSolver.generate(ocp, json_file=JSON_FILE) + # AcadosOcpSolver.build(ocp.code_export_directory, with_cython=True) diff --git a/selfdrive/controls/lib/ldw.py b/selfdrive/controls/lib/ldw.py new file mode 100644 index 0000000000..78a6d6cf6e --- /dev/null +++ b/selfdrive/controls/lib/ldw.py @@ -0,0 +1,41 @@ +from cereal import log +from openpilot.common.realtime import DT_CTRL +from openpilot.common.constants import CV + + +CAMERA_OFFSET = 0.04 +LDW_MIN_SPEED = 31 * CV.MPH_TO_MS +LANE_DEPARTURE_THRESHOLD = 0.1 + +class LaneDepartureWarning: + def __init__(self): + self.left = False + self.right = False + self.last_blinker_frame = 0 + + def update(self, frame, modelV2, CS, CC): + if CS.leftBlinker or CS.rightBlinker: + self.last_blinker_frame = frame + + recent_blinker = (frame - self.last_blinker_frame) * DT_CTRL < 5.0 # 5s blinker cooldown + ldw_allowed = CS.vEgo > LDW_MIN_SPEED and not recent_blinker and not CC.latActive + + desire_prediction = modelV2.meta.desirePrediction + if len(desire_prediction) and ldw_allowed: + right_lane_visible = modelV2.laneLineProbs[2] > 0.5 + left_lane_visible = modelV2.laneLineProbs[1] > 0.5 + l_lane_change_prob = desire_prediction[log.Desire.laneChangeLeft] + r_lane_change_prob = desire_prediction[log.Desire.laneChangeRight] + + lane_lines = modelV2.laneLines + l_lane_close = left_lane_visible and (lane_lines[1].y[0] > -(1.08 + CAMERA_OFFSET)) + r_lane_close = right_lane_visible and (lane_lines[2].y[0] < (1.08 - CAMERA_OFFSET)) + + self.left = bool(l_lane_change_prob > LANE_DEPARTURE_THRESHOLD and l_lane_close) + self.right = bool(r_lane_change_prob > LANE_DEPARTURE_THRESHOLD and r_lane_close) + else: + self.left, self.right = False, False + + @property + def warning(self) -> bool: + return bool(self.left or self.right) diff --git a/selfdrive/controls/lib/longcontrol.py b/selfdrive/controls/lib/longcontrol.py new file mode 100644 index 0000000000..6d4f922461 --- /dev/null +++ b/selfdrive/controls/lib/longcontrol.py @@ -0,0 +1,88 @@ +import numpy as np +from cereal import car +from openpilot.common.realtime import DT_CTRL +from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N +from openpilot.common.pid import PIDController +from openpilot.selfdrive.modeld.constants import ModelConstants + +CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] + +LongCtrlState = car.CarControl.Actuators.LongControlState + + +def long_control_state_trans(CP, active, long_control_state, v_ego, + should_stop, brake_pressed, cruise_standstill): + stopping_condition = should_stop + starting_condition = (not should_stop and + not cruise_standstill and + not brake_pressed) + started_condition = v_ego > CP.vEgoStarting + + if not active: + long_control_state = LongCtrlState.off + + else: + if long_control_state == LongCtrlState.off: + if not starting_condition: + long_control_state = LongCtrlState.stopping + else: + if starting_condition and CP.startingState: + long_control_state = LongCtrlState.starting + else: + long_control_state = LongCtrlState.pid + + elif long_control_state == LongCtrlState.stopping: + if starting_condition and CP.startingState: + long_control_state = LongCtrlState.starting + elif starting_condition: + long_control_state = LongCtrlState.pid + + elif long_control_state in [LongCtrlState.starting, LongCtrlState.pid]: + if stopping_condition: + long_control_state = LongCtrlState.stopping + elif started_condition: + long_control_state = LongCtrlState.pid + return long_control_state + +class LongControl: + def __init__(self, CP): + self.CP = CP + self.long_control_state = LongCtrlState.off + self.pid = PIDController((CP.longitudinalTuning.kpBP, CP.longitudinalTuning.kpV), + (CP.longitudinalTuning.kiBP, CP.longitudinalTuning.kiV), + k_f=CP.longitudinalTuning.kf, rate=1 / DT_CTRL) + self.last_output_accel = 0.0 + + def reset(self): + self.pid.reset() + + def update(self, active, CS, a_target, should_stop, accel_limits): + """Update longitudinal control. This updates the state machine and runs a PID loop""" + self.pid.neg_limit = accel_limits[0] + self.pid.pos_limit = accel_limits[1] + + self.long_control_state = long_control_state_trans(self.CP, active, self.long_control_state, CS.vEgo, + should_stop, CS.brakePressed, + CS.cruiseState.standstill) + if self.long_control_state == LongCtrlState.off: + self.reset() + output_accel = 0. + + elif self.long_control_state == LongCtrlState.stopping: + output_accel = self.last_output_accel + if output_accel > self.CP.stopAccel: + output_accel = min(output_accel, 0.0) + output_accel -= self.CP.stoppingDecelRate * DT_CTRL + self.reset() + + elif self.long_control_state == LongCtrlState.starting: + output_accel = self.CP.startAccel + self.reset() + + else: # LongCtrlState.pid + error = a_target - CS.aEgo + output_accel = self.pid.update(error, speed=CS.vEgo, + feedforward=a_target) + + self.last_output_accel = np.clip(output_accel, accel_limits[0], accel_limits[1]) + return self.last_output_accel diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/.gitignore b/selfdrive/controls/lib/longitudinal_mpc_lib/.gitignore new file mode 100644 index 0000000000..6f09b1aa0c --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/.gitignore @@ -0,0 +1,2 @@ +acados_ocp_long.json +c_generated_code/ diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript new file mode 100644 index 0000000000..164b965142 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript @@ -0,0 +1,102 @@ +Import('env', 'envCython', 'arch', 'msgq_python', 'common_python', 'pandad_python', 'np_version') + +gen = "c_generated_code" + +casadi_model = [ + f'{gen}/long_model/long_expl_ode_fun.c', + f'{gen}/long_model/long_expl_vde_forw.c', +] + +casadi_cost_y = [ + f'{gen}/long_cost/long_cost_y_fun.c', + f'{gen}/long_cost/long_cost_y_fun_jac_ut_xt.c', + f'{gen}/long_cost/long_cost_y_hess.c', +] + +casadi_cost_e = [ + f'{gen}/long_cost/long_cost_y_e_fun.c', + f'{gen}/long_cost/long_cost_y_e_fun_jac_ut_xt.c', + f'{gen}/long_cost/long_cost_y_e_hess.c', +] + +casadi_cost_0 = [ + f'{gen}/long_cost/long_cost_y_0_fun.c', + f'{gen}/long_cost/long_cost_y_0_fun_jac_ut_xt.c', + f'{gen}/long_cost/long_cost_y_0_hess.c', +] + +casadi_constraints = [ + f'{gen}/long_constraints/long_constr_h_fun.c', + f'{gen}/long_constraints/long_constr_h_fun_jac_uxt_zt.c', +] + +build_files = [f'{gen}/acados_solver_long.c'] + casadi_model + casadi_cost_y + casadi_cost_e + \ + casadi_cost_0 + casadi_constraints + +# extra generated files used to trigger a rebuild +generated_files = [ + f'{gen}/Makefile', + + f'{gen}/main_long.c', + f'{gen}/main_sim_long.c', + f'{gen}/acados_solver_long.h', + f'{gen}/acados_sim_solver_long.h', + f'{gen}/acados_sim_solver_long.c', + f'{gen}/acados_solver.pxd', + + f'{gen}/long_model/long_expl_vde_adj.c', + + f'{gen}/long_model/long_model.h', + f'{gen}/long_constraints/long_constraints.h', + f'{gen}/long_cost/long_cost.h', +] + build_files + +acados_dir = '#third_party/acados' +acados_templates_dir = '#third_party/acados/acados_template/c_templates_tera' + +source_list = ['long_mpc.py', + '#selfdrive/modeld/constants.py', + f'{acados_dir}/include/acados_c/ocp_nlp_interface.h', + f'{acados_templates_dir}/acados_solver.in.c', +] + +lenv = env.Clone() +acados_rel_path = Dir(gen).rel_path(Dir(f"#third_party/acados/{arch}/lib")) +lenv["RPATH"] += [lenv.Literal(f'\\$$ORIGIN/{acados_rel_path}')] +lenv.Clean(generated_files, Dir(gen)) +generated_long = lenv.Command(generated_files, + source_list, + f"cd {Dir('.').abspath} && python3 long_mpc.py") +lenv.Depends(generated_long, [msgq_python, common_python, pandad_python]) + +lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES") +lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES") +lenv["CCFLAGS"].append("-Wno-unused") +if arch != "Darwin": + lenv["LINKFLAGS"].append("-Wl,--disable-new-dtags") +else: + lenv["LINKFLAGS"].append("-Wl,-install_name,@loader_path/libacados_ocp_solver_long.dylib") + lenv["LINKFLAGS"].append(f"-Wl,-rpath,@loader_path/{acados_rel_path}") +lib_solver = lenv.SharedLibrary(f"{gen}/acados_ocp_solver_long", + build_files, + LIBS=['m', 'acados', 'hpipm', 'blasfeo', 'qpOASES_e']) + +# generate cython stuff +acados_ocp_solver_pyx = File("#third_party/acados/acados_template/acados_ocp_solver_pyx.pyx") +acados_ocp_solver_common = File("#third_party/acados/acados_template/acados_solver_common.pxd") +libacados_ocp_solver_pxd = File(f'{gen}/acados_solver.pxd') +libacados_ocp_solver_c = File(f'{gen}/acados_ocp_solver_pyx.c') + +lenv2 = envCython.Clone() +lenv2["LIBPATH"] += [lib_solver[0].dir.abspath] +lenv2["RPATH"] += [lenv2.Literal('\\$$ORIGIN')] +lenv2.Command(libacados_ocp_solver_c, + [acados_ocp_solver_pyx, acados_ocp_solver_common, libacados_ocp_solver_pxd], + f'cython' + \ + f' -o {libacados_ocp_solver_c.get_labspath()}' + \ + f' -I {libacados_ocp_solver_pxd.get_dir().get_labspath()}' + \ + f' -I {acados_ocp_solver_common.get_dir().get_labspath()}' + \ + f' {acados_ocp_solver_pyx.get_labspath()}') +lib_cython = lenv2.Program(f'{gen}/acados_ocp_solver_pyx.so', [libacados_ocp_solver_c], LIBS=['acados_ocp_solver_long']) +lenv2.Depends(lib_cython, lib_solver) +lenv2.Depends(libacados_ocp_solver_c, np_version) diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/__init__.py b/selfdrive/controls/lib/longitudinal_mpc_lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py new file mode 100755 index 0000000000..3f9d8245bd --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @@ -0,0 +1,457 @@ +#!/usr/bin/env python3 +import os +import time +import numpy as np +from cereal import log +from opendbc.car.interfaces import ACCEL_MIN, ACCEL_MAX +from openpilot.common.realtime import DT_MDL +from openpilot.common.swaglog import cloudlog +# WARNING: imports outside of constants will not trigger a rebuild +from openpilot.selfdrive.modeld.constants import index_function +from openpilot.selfdrive.controls.radard import _LEAD_ACCEL_TAU + +if __name__ == '__main__': # generating code + from openpilot.third_party.acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver +else: + from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.c_generated_code.acados_ocp_solver_pyx import AcadosOcpSolverCython + +from casadi import SX, vertcat + +MODEL_NAME = 'long' +LONG_MPC_DIR = os.path.dirname(os.path.abspath(__file__)) +EXPORT_DIR = os.path.join(LONG_MPC_DIR, "c_generated_code") +JSON_FILE = os.path.join(LONG_MPC_DIR, "acados_ocp_long.json") + +SOURCES = ['lead0', 'lead1', 'cruise', 'e2e'] + +X_DIM = 3 +U_DIM = 1 +PARAM_DIM = 6 +COST_E_DIM = 5 +COST_DIM = COST_E_DIM + 1 +CONSTR_DIM = 4 + +X_EGO_OBSTACLE_COST = 3. +X_EGO_COST = 0. +V_EGO_COST = 0. +A_EGO_COST = 0. +J_EGO_COST = 5.0 +A_CHANGE_COST = 200. +DANGER_ZONE_COST = 100. +CRASH_DISTANCE = .25 +LEAD_DANGER_FACTOR = 0.75 +LIMIT_COST = 1e6 +ACADOS_SOLVER_TYPE = 'SQP_RTI' + + +# Fewer timestamps don't hurt performance and lead to +# much better convergence of the MPC with low iterations +N = 12 +MAX_T = 10.0 +T_IDXS_LST = [index_function(idx, max_val=MAX_T, max_idx=N) for idx in range(N+1)] + +T_IDXS = np.array(T_IDXS_LST) +FCW_IDXS = T_IDXS < 5.0 +T_DIFFS = np.diff(T_IDXS, prepend=[0.]) +COMFORT_BRAKE = 2.5 +STOP_DISTANCE = 6.0 +CRUISE_MIN_ACCEL = -1.2 +CRUISE_MAX_ACCEL = 1.6 + +def get_jerk_factor(personality=log.LongitudinalPersonality.standard): + if personality==log.LongitudinalPersonality.relaxed: + return 1.0 + elif personality==log.LongitudinalPersonality.standard: + return 1.0 + elif personality==log.LongitudinalPersonality.aggressive: + return 0.5 + else: + raise NotImplementedError("Longitudinal personality not supported") + + +def get_T_FOLLOW(personality=log.LongitudinalPersonality.standard): + if personality==log.LongitudinalPersonality.relaxed: + return 1.75 + elif personality==log.LongitudinalPersonality.standard: + return 1.45 + elif personality==log.LongitudinalPersonality.aggressive: + return 1.25 + else: + raise NotImplementedError("Longitudinal personality not supported") + +def get_stopped_equivalence_factor(v_lead): + return (v_lead**2) / (2 * COMFORT_BRAKE) + +def get_safe_obstacle_distance(v_ego, t_follow): + return (v_ego**2) / (2 * COMFORT_BRAKE) + t_follow * v_ego + STOP_DISTANCE + +def desired_follow_distance(v_ego, v_lead, t_follow=None): + if t_follow is None: + t_follow = get_T_FOLLOW() + return get_safe_obstacle_distance(v_ego, t_follow) - get_stopped_equivalence_factor(v_lead) + + +def gen_long_model(): + model = AcadosModel() + model.name = MODEL_NAME + + # set up states & controls + x_ego = SX.sym('x_ego') + v_ego = SX.sym('v_ego') + a_ego = SX.sym('a_ego') + model.x = vertcat(x_ego, v_ego, a_ego) + + # controls + j_ego = SX.sym('j_ego') + model.u = vertcat(j_ego) + + # xdot + x_ego_dot = SX.sym('x_ego_dot') + v_ego_dot = SX.sym('v_ego_dot') + a_ego_dot = SX.sym('a_ego_dot') + model.xdot = vertcat(x_ego_dot, v_ego_dot, a_ego_dot) + + # live parameters + a_min = SX.sym('a_min') + a_max = SX.sym('a_max') + x_obstacle = SX.sym('x_obstacle') + prev_a = SX.sym('prev_a') + lead_t_follow = SX.sym('lead_t_follow') + lead_danger_factor = SX.sym('lead_danger_factor') + model.p = vertcat(a_min, a_max, x_obstacle, prev_a, lead_t_follow, lead_danger_factor) + + # dynamics model + f_expl = vertcat(v_ego, a_ego, j_ego) + model.f_impl_expr = model.xdot - f_expl + model.f_expl_expr = f_expl + return model + + +def gen_long_ocp(): + ocp = AcadosOcp() + ocp.model = gen_long_model() + + Tf = T_IDXS[-1] + + # set dimensions + ocp.dims.N = N + + # set cost module + ocp.cost.cost_type = 'NONLINEAR_LS' + ocp.cost.cost_type_e = 'NONLINEAR_LS' + + QR = np.zeros((COST_DIM, COST_DIM)) + Q = np.zeros((COST_E_DIM, COST_E_DIM)) + + ocp.cost.W = QR + ocp.cost.W_e = Q + + x_ego, v_ego, a_ego = ocp.model.x[0], ocp.model.x[1], ocp.model.x[2] + j_ego = ocp.model.u[0] + + a_min, a_max = ocp.model.p[0], ocp.model.p[1] + x_obstacle = ocp.model.p[2] + prev_a = ocp.model.p[3] + lead_t_follow = ocp.model.p[4] + lead_danger_factor = ocp.model.p[5] + + ocp.cost.yref = np.zeros((COST_DIM, )) + ocp.cost.yref_e = np.zeros((COST_E_DIM, )) + + desired_dist_comfort = get_safe_obstacle_distance(v_ego, lead_t_follow) + + # The main cost in normal operation is how close you are to the "desired" distance + # from an obstacle at every timestep. This obstacle can be a lead car + # or other object. In e2e mode we can use x_position targets as a cost + # instead. + costs = [((x_obstacle - x_ego) - (desired_dist_comfort)) / (v_ego + 10.), + x_ego, + v_ego, + a_ego, + a_ego - prev_a, + j_ego] + ocp.model.cost_y_expr = vertcat(*costs) + ocp.model.cost_y_expr_e = vertcat(*costs[:-1]) + + # Constraints on speed, acceleration and desired distance to + # the obstacle, which is treated as a slack constraint so it + # behaves like an asymmetrical cost. + constraints = vertcat(v_ego, + (a_ego - a_min), + (a_max - a_ego), + ((x_obstacle - x_ego) - lead_danger_factor * (desired_dist_comfort)) / (v_ego + 10.)) + ocp.model.con_h_expr = constraints + + x0 = np.zeros(X_DIM) + ocp.constraints.x0 = x0 + ocp.parameter_values = np.array([-1.2, 1.2, 0.0, 0.0, get_T_FOLLOW(), LEAD_DANGER_FACTOR]) + + + # We put all constraint cost weights to 0 and only set them at runtime + cost_weights = np.zeros(CONSTR_DIM) + ocp.cost.zl = cost_weights + ocp.cost.Zl = cost_weights + ocp.cost.Zu = cost_weights + ocp.cost.zu = cost_weights + + ocp.constraints.lh = np.zeros(CONSTR_DIM) + ocp.constraints.uh = 1e4*np.ones(CONSTR_DIM) + ocp.constraints.idxsh = np.arange(CONSTR_DIM) + + # The HPIPM solver can give decent solutions even when it is stopped early + # Which is critical for our purpose where compute time is strictly bounded + # We use HPIPM in the SPEED_ABS mode, which ensures fastest runtime. This + # does not cause issues since the problem is well bounded. + ocp.solver_options.qp_solver = 'PARTIAL_CONDENSING_HPIPM' + ocp.solver_options.hessian_approx = 'GAUSS_NEWTON' + ocp.solver_options.integrator_type = 'ERK' + ocp.solver_options.nlp_solver_type = ACADOS_SOLVER_TYPE + ocp.solver_options.qp_solver_cond_N = 1 + + # More iterations take too much time and less lead to inaccurate convergence in + # some situations. Ideally we would run just 1 iteration to ensure fixed runtime. + ocp.solver_options.qp_solver_iter_max = 10 + ocp.solver_options.qp_tol = 1e-3 + + # set prediction horizon + ocp.solver_options.tf = Tf + ocp.solver_options.shooting_nodes = T_IDXS + + ocp.code_export_directory = EXPORT_DIR + return ocp + + +class LongitudinalMpc: + def __init__(self, mode='acc', dt=DT_MDL): + self.mode = mode + self.dt = dt + self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N) + self.reset() + self.source = SOURCES[2] + + def reset(self): + # self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N) + self.solver.reset() + # self.solver.options_set('print_level', 2) + self.v_solution = np.zeros(N+1) + self.a_solution = np.zeros(N+1) + self.prev_a = np.array(self.a_solution) + self.j_solution = np.zeros(N) + self.yref = np.zeros((N+1, COST_DIM)) + for i in range(N): + self.solver.cost_set(i, "yref", self.yref[i]) + self.solver.cost_set(N, "yref", self.yref[N][:COST_E_DIM]) + self.x_sol = np.zeros((N+1, X_DIM)) + self.u_sol = np.zeros((N,1)) + self.params = np.zeros((N+1, PARAM_DIM)) + for i in range(N+1): + self.solver.set(i, 'x', np.zeros(X_DIM)) + self.last_cloudlog_t = 0 + self.status = False + self.crash_cnt = 0.0 + self.solution_status = 0 + # timers + self.solve_time = 0.0 + self.time_qp_solution = 0.0 + self.time_linearization = 0.0 + self.time_integrator = 0.0 + self.x0 = np.zeros(X_DIM) + self.set_weights() + + def set_cost_weights(self, cost_weights, constraint_cost_weights): + W = np.asfortranarray(np.diag(cost_weights)) + for i in range(N): + # TODO don't hardcode A_CHANGE_COST idx + # reduce the cost on (a-a_prev) later in the horizon. + W[4,4] = cost_weights[4] * np.interp(T_IDXS[i], [0.0, 1.0, 2.0], [1.0, 1.0, 0.0]) + self.solver.cost_set(i, 'W', W) + # Setting the slice without the copy make the array not contiguous, + # causing issues with the C interface. + self.solver.cost_set(N, 'W', np.copy(W[:COST_E_DIM, :COST_E_DIM])) + + # Set L2 slack cost on lower bound constraints + Zl = np.array(constraint_cost_weights) + for i in range(N): + self.solver.cost_set(i, 'Zl', Zl) + + def set_weights(self, prev_accel_constraint=True, personality=log.LongitudinalPersonality.standard): + jerk_factor = get_jerk_factor(personality) + if self.mode == 'acc': + a_change_cost = A_CHANGE_COST if prev_accel_constraint else 0 + cost_weights = [X_EGO_OBSTACLE_COST, X_EGO_COST, V_EGO_COST, A_EGO_COST, jerk_factor * a_change_cost, jerk_factor * J_EGO_COST] + constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST] + elif self.mode == 'blended': + a_change_cost = 40.0 if prev_accel_constraint else 0 + cost_weights = [0., 0.1, 0.2, 5.0, a_change_cost, 1.0] + constraint_cost_weights = [LIMIT_COST, LIMIT_COST, LIMIT_COST, DANGER_ZONE_COST] + else: + raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner cost set') + self.set_cost_weights(cost_weights, constraint_cost_weights) + + def set_cur_state(self, v, a): + v_prev = self.x0[1] + self.x0[1] = v + self.x0[2] = a + if abs(v_prev - v) > 2.: # probably only helps if v < v_prev + for i in range(N+1): + self.solver.set(i, 'x', self.x0) + + @staticmethod + def extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau): + a_lead_traj = a_lead * np.exp(-a_lead_tau * (T_IDXS**2)/2.) + v_lead_traj = np.clip(v_lead + np.cumsum(T_DIFFS * a_lead_traj), 0.0, 1e8) + x_lead_traj = x_lead + np.cumsum(T_DIFFS * v_lead_traj) + lead_xv = np.column_stack((x_lead_traj, v_lead_traj)) + return lead_xv + + def process_lead(self, lead): + v_ego = self.x0[1] + if lead is not None and lead.status: + x_lead = lead.dRel + v_lead = lead.vLead + a_lead = lead.aLeadK + a_lead_tau = lead.aLeadTau + else: + # Fake a fast lead car, so mpc can keep running in the same mode + x_lead = 50.0 + v_lead = v_ego + 10.0 + a_lead = 0.0 + a_lead_tau = _LEAD_ACCEL_TAU + + # MPC will not converge if immediate crash is expected + # Clip lead distance to what is still possible to brake for + min_x_lead = ((v_ego + v_lead)/2) * (v_ego - v_lead) / (-ACCEL_MIN * 2) + x_lead = np.clip(x_lead, min_x_lead, 1e8) + v_lead = np.clip(v_lead, 0.0, 1e8) + a_lead = np.clip(a_lead, -10., 5.) + lead_xv = self.extrapolate_lead(x_lead, v_lead, a_lead, a_lead_tau) + return lead_xv + + def update(self, radarstate, v_cruise, x, v, a, j, personality=log.LongitudinalPersonality.standard): + t_follow = get_T_FOLLOW(personality) + v_ego = self.x0[1] + self.status = radarstate.leadOne.status or radarstate.leadTwo.status + + lead_xv_0 = self.process_lead(radarstate.leadOne) + lead_xv_1 = self.process_lead(radarstate.leadTwo) + + # To estimate a safe distance from a moving lead, we calculate how much stopping + # distance that lead needs as a minimum. We can add that to the current distance + # and then treat that as a stopped car/obstacle at this new distance. + lead_0_obstacle = lead_xv_0[:,0] + get_stopped_equivalence_factor(lead_xv_0[:,1]) + lead_1_obstacle = lead_xv_1[:,0] + get_stopped_equivalence_factor(lead_xv_1[:,1]) + + self.params[:,0] = ACCEL_MIN + self.params[:,1] = ACCEL_MAX + + # Update in ACC mode or ACC/e2e blend + if self.mode == 'acc': + self.params[:,5] = LEAD_DANGER_FACTOR + + # Fake an obstacle for cruise, this ensures smooth acceleration to set speed + # when the leads are no factor. + v_lower = v_ego + (T_IDXS * CRUISE_MIN_ACCEL * 1.05) + # TODO does this make sense when max_a is negative? + v_upper = v_ego + (T_IDXS * CRUISE_MAX_ACCEL * 1.05) + v_cruise_clipped = np.clip(v_cruise * np.ones(N+1), + v_lower, + v_upper) + cruise_obstacle = np.cumsum(T_DIFFS * v_cruise_clipped) + get_safe_obstacle_distance(v_cruise_clipped, t_follow) + x_obstacles = np.column_stack([lead_0_obstacle, lead_1_obstacle, cruise_obstacle]) + self.source = SOURCES[np.argmin(x_obstacles[0])] + + # These are not used in ACC mode + x[:], v[:], a[:], j[:] = 0.0, 0.0, 0.0, 0.0 + + elif self.mode == 'blended': + self.params[:,5] = 1.0 + + x_obstacles = np.column_stack([lead_0_obstacle, + lead_1_obstacle]) + cruise_target = T_IDXS * np.clip(v_cruise, v_ego - 2.0, 1e3) + x[0] + xforward = ((v[1:] + v[:-1]) / 2) * (T_IDXS[1:] - T_IDXS[:-1]) + x = np.cumsum(np.insert(xforward, 0, x[0])) + + x_and_cruise = np.column_stack([x, cruise_target]) + x = np.min(x_and_cruise, axis=1) + + self.source = 'e2e' if x_and_cruise[1,0] < x_and_cruise[1,1] else 'cruise' + + else: + raise NotImplementedError(f'Planner mode {self.mode} not recognized in planner update') + + self.yref[:,1] = x + self.yref[:,2] = v + self.yref[:,3] = a + self.yref[:,5] = j + for i in range(N): + self.solver.set(i, "yref", self.yref[i]) + self.solver.set(N, "yref", self.yref[N][:COST_E_DIM]) + + self.params[:,2] = np.min(x_obstacles, axis=1) + self.params[:,3] = np.copy(self.prev_a) + self.params[:,4] = t_follow + + self.run() + if (np.any(lead_xv_0[FCW_IDXS,0] - self.x_sol[FCW_IDXS,0] < CRASH_DISTANCE) and + radarstate.leadOne.modelProb > 0.9): + self.crash_cnt += 1 + else: + self.crash_cnt = 0 + + # Check if it got within lead comfort range + # TODO This should be done cleaner + if self.mode == 'blended': + if any((lead_0_obstacle - get_safe_obstacle_distance(self.x_sol[:,1], t_follow))- self.x_sol[:,0] < 0.0): + self.source = 'lead0' + if any((lead_1_obstacle - get_safe_obstacle_distance(self.x_sol[:,1], t_follow))- self.x_sol[:,0] < 0.0) and \ + (lead_1_obstacle[0] - lead_0_obstacle[0]): + self.source = 'lead1' + + def run(self): + # t0 = time.monotonic() + # reset = 0 + for i in range(N+1): + self.solver.set(i, 'p', self.params[i]) + self.solver.constraints_set(0, "lbx", self.x0) + self.solver.constraints_set(0, "ubx", self.x0) + + self.solution_status = self.solver.solve() + self.solve_time = float(self.solver.get_stats('time_tot')[0]) + self.time_qp_solution = float(self.solver.get_stats('time_qp')[0]) + self.time_linearization = float(self.solver.get_stats('time_lin')[0]) + self.time_integrator = float(self.solver.get_stats('time_sim')[0]) + + # qp_iter = self.solver.get_stats('statistics')[-1][-1] # SQP_RTI specific + # print(f"long_mpc timings: tot {self.solve_time:.2e}, qp {self.time_qp_solution:.2e}, lin {self.time_linearization:.2e}, \ + # integrator {self.time_integrator:.2e}, qp_iter {qp_iter}") + # res = self.solver.get_residuals() + # print(f"long_mpc residuals: {res[0]:.2e}, {res[1]:.2e}, {res[2]:.2e}, {res[3]:.2e}") + # self.solver.print_statistics() + + for i in range(N+1): + self.x_sol[i] = self.solver.get(i, 'x') + for i in range(N): + self.u_sol[i] = self.solver.get(i, 'u') + + self.v_solution = self.x_sol[:,1] + self.a_solution = self.x_sol[:,2] + self.j_solution = self.u_sol[:,0] + + self.prev_a = np.interp(T_IDXS + self.dt, T_IDXS, self.a_solution) + + t = time.monotonic() + if self.solution_status != 0: + if t > self.last_cloudlog_t + 5.0: + self.last_cloudlog_t = t + cloudlog.warning(f"Long mpc reset, solution_status: {self.solution_status}") + self.reset() + # reset = 1 + # print(f"long_mpc timings: total internal {self.solve_time:.2e}, external: {(time.monotonic() - t0):.2e} qp {self.time_qp_solution:.2e}, \ + # lin {self.time_linearization:.2e} qp_iter {qp_iter}, reset {reset}") + + +if __name__ == "__main__": + ocp = gen_long_ocp() + AcadosOcpSolver.generate(ocp, json_file=JSON_FILE) + # AcadosOcpSolver.build(ocp.code_export_directory, with_cython=True) diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py new file mode 100755 index 0000000000..34fc85f8a5 --- /dev/null +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 +import math +import numpy as np + +import cereal.messaging as messaging +from opendbc.car.interfaces import ACCEL_MIN, ACCEL_MAX +from openpilot.common.constants import CV +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.modeld.constants import ModelConstants +from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState +from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import LongitudinalMpc +from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import T_IDXS as T_IDXS_MPC +from openpilot.selfdrive.controls.lib.drive_helpers import CONTROL_N, get_accel_from_plan +from openpilot.selfdrive.car.cruise import V_CRUISE_MAX, V_CRUISE_UNSET +from openpilot.common.swaglog import cloudlog + +LON_MPC_STEP = 0.2 # first step is 0.2s +A_CRUISE_MAX_VALS = [1.6, 1.2, 0.8, 0.6] +A_CRUISE_MAX_BP = [0., 10.0, 25., 40.] +CONTROL_N_T_IDX = ModelConstants.T_IDXS[:CONTROL_N] +ALLOW_THROTTLE_THRESHOLD = 0.4 +MIN_ALLOW_THROTTLE_SPEED = 2.5 + +# Lookup table for turns +_A_TOTAL_MAX_V = [1.7, 3.2] +_A_TOTAL_MAX_BP = [20., 40.] + + +def get_max_accel(v_ego): + return np.interp(v_ego, A_CRUISE_MAX_BP, A_CRUISE_MAX_VALS) + +def get_coast_accel(pitch): + return np.sin(pitch) * -5.65 - 0.3 # fitted from data using xx/projects/allow_throttle/compute_coast_accel.py + + +def limit_accel_in_turns(v_ego, angle_steers, a_target, CP): + """ + This function returns a limited long acceleration allowed, depending on the existing lateral acceleration + this should avoid accelerating when losing the target in turns + """ + # FIXME: This function to calculate lateral accel is incorrect and should use the VehicleModel + # The lookup table for turns should also be updated if we do this + a_total_max = np.interp(v_ego, _A_TOTAL_MAX_BP, _A_TOTAL_MAX_V) + a_y = v_ego ** 2 * angle_steers * CV.DEG_TO_RAD / (CP.steerRatio * CP.wheelbase) + a_x_allowed = math.sqrt(max(a_total_max ** 2 - a_y ** 2, 0.)) + + return [a_target[0], min(a_target[1], a_x_allowed)] + + +class LongitudinalPlanner: + def __init__(self, CP, init_v=0.0, init_a=0.0, dt=DT_MDL): + self.CP = CP + self.mpc = LongitudinalMpc(dt=dt) + # TODO remove mpc modes when TR released + self.mpc.mode = 'acc' + self.fcw = False + self.dt = dt + self.allow_throttle = True + + self.a_desired = init_a + self.v_desired_filter = FirstOrderFilter(init_v, 2.0, self.dt) + self.prev_accel_clip = [ACCEL_MIN, ACCEL_MAX] + self.output_a_target = 0.0 + self.output_should_stop = False + + self.v_desired_trajectory = np.zeros(CONTROL_N) + self.a_desired_trajectory = np.zeros(CONTROL_N) + self.j_desired_trajectory = np.zeros(CONTROL_N) + self.solverExecutionTime = 0.0 + + @staticmethod + def parse_model(model_msg): + if (len(model_msg.position.x) == ModelConstants.IDX_N and + len(model_msg.velocity.x) == ModelConstants.IDX_N and + len(model_msg.acceleration.x) == ModelConstants.IDX_N): + x = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.position.x) + v = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.velocity.x) + a = np.interp(T_IDXS_MPC, ModelConstants.T_IDXS, model_msg.acceleration.x) + j = np.zeros(len(T_IDXS_MPC)) + else: + x = np.zeros(len(T_IDXS_MPC)) + v = np.zeros(len(T_IDXS_MPC)) + a = np.zeros(len(T_IDXS_MPC)) + j = np.zeros(len(T_IDXS_MPC)) + if len(model_msg.meta.disengagePredictions.gasPressProbs) > 1: + throttle_prob = model_msg.meta.disengagePredictions.gasPressProbs[1] + else: + throttle_prob = 1.0 + return x, v, a, j, throttle_prob + + def update(self, sm): + mode = 'blended' if sm['selfdriveState'].experimentalMode else 'acc' + + if len(sm['carControl'].orientationNED) == 3: + accel_coast = get_coast_accel(sm['carControl'].orientationNED[1]) + else: + accel_coast = ACCEL_MAX + + v_ego = sm['carState'].vEgo + v_cruise_kph = min(sm['carState'].vCruise, V_CRUISE_MAX) + v_cruise = v_cruise_kph * CV.KPH_TO_MS + v_cruise_initialized = sm['carState'].vCruise != V_CRUISE_UNSET + + long_control_off = sm['controlsState'].longControlState == LongCtrlState.off + force_slow_decel = sm['controlsState'].forceDecel + + # Reset current state when not engaged, or user is controlling the speed + reset_state = long_control_off if self.CP.openpilotLongitudinalControl else not sm['selfdriveState'].enabled + # PCM cruise speed may be updated a few cycles later, check if initialized + reset_state = reset_state or not v_cruise_initialized + + # No change cost when user is controlling the speed, or when standstill + prev_accel_constraint = not (reset_state or sm['carState'].standstill) + + if mode == 'acc': + accel_clip = [ACCEL_MIN, get_max_accel(v_ego)] + steer_angle_without_offset = sm['carState'].steeringAngleDeg - sm['liveParameters'].angleOffsetDeg + accel_clip = limit_accel_in_turns(v_ego, steer_angle_without_offset, accel_clip, self.CP) + else: + accel_clip = [ACCEL_MIN, ACCEL_MAX] + + if reset_state: + self.v_desired_filter.x = v_ego + # Clip aEgo to cruise limits to prevent large accelerations when becoming active + self.a_desired = np.clip(sm['carState'].aEgo, accel_clip[0], accel_clip[1]) + + # Prevent divergence, smooth in current v_ego + self.v_desired_filter.x = max(0.0, self.v_desired_filter.update(v_ego)) + x, v, a, j, throttle_prob = self.parse_model(sm['modelV2']) + # Don't clip at low speeds since throttle_prob doesn't account for creep + self.allow_throttle = throttle_prob > ALLOW_THROTTLE_THRESHOLD or v_ego <= MIN_ALLOW_THROTTLE_SPEED + + if not self.allow_throttle: + clipped_accel_coast = max(accel_coast, accel_clip[0]) + clipped_accel_coast_interp = np.interp(v_ego, [MIN_ALLOW_THROTTLE_SPEED, MIN_ALLOW_THROTTLE_SPEED*2], [accel_clip[1], clipped_accel_coast]) + accel_clip[1] = min(accel_clip[1], clipped_accel_coast_interp) + + if force_slow_decel: + v_cruise = 0.0 + + self.mpc.set_weights(prev_accel_constraint, personality=sm['selfdriveState'].personality) + self.mpc.set_cur_state(self.v_desired_filter.x, self.a_desired) + self.mpc.update(sm['radarState'], v_cruise, x, v, a, j, personality=sm['selfdriveState'].personality) + + self.v_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.v_solution) + self.a_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC, self.mpc.a_solution) + self.j_desired_trajectory = np.interp(CONTROL_N_T_IDX, T_IDXS_MPC[:-1], self.mpc.j_solution) + + # TODO counter is only needed because radar is glitchy, remove once radar is gone + self.fcw = self.mpc.crash_cnt > 2 and not sm['carState'].standstill + if self.fcw: + cloudlog.info("FCW triggered") + + # Interpolate 0.05 seconds and save as starting point for next iteration + a_prev = self.a_desired + self.a_desired = float(np.interp(self.dt, CONTROL_N_T_IDX, self.a_desired_trajectory)) + self.v_desired_filter.x = self.v_desired_filter.x + self.dt * (self.a_desired + a_prev) / 2.0 + + action_t = self.CP.longitudinalActuatorDelay + DT_MDL + output_a_target_mpc, output_should_stop_mpc = get_accel_from_plan(self.v_desired_trajectory, self.a_desired_trajectory, CONTROL_N_T_IDX, + action_t=action_t, vEgoStopping=self.CP.vEgoStopping) + output_a_target_e2e = sm['modelV2'].action.desiredAcceleration + output_should_stop_e2e = sm['modelV2'].action.shouldStop + + if mode == 'acc': + output_a_target = output_a_target_mpc + self.output_should_stop = output_should_stop_mpc + else: + output_a_target = min(output_a_target_mpc, output_a_target_e2e) + self.output_should_stop = output_should_stop_e2e or output_should_stop_mpc + + for idx in range(2): + accel_clip[idx] = np.clip(accel_clip[idx], self.prev_accel_clip[idx] - 0.05, self.prev_accel_clip[idx] + 0.05) + self.output_a_target = np.clip(output_a_target, accel_clip[0], accel_clip[1]) + self.prev_accel_clip = accel_clip + + def publish(self, sm, pm): + plan_send = messaging.new_message('longitudinalPlan') + + plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'selfdriveState', 'radarState']) + + longitudinalPlan = plan_send.longitudinalPlan + longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2'] + longitudinalPlan.processingDelay = (plan_send.logMonoTime / 1e9) - sm.logMonoTime['modelV2'] + longitudinalPlan.solverExecutionTime = self.mpc.solve_time + + longitudinalPlan.speeds = self.v_desired_trajectory.tolist() + longitudinalPlan.accels = self.a_desired_trajectory.tolist() + longitudinalPlan.jerks = self.j_desired_trajectory.tolist() + + longitudinalPlan.hasLead = sm['radarState'].leadOne.status + longitudinalPlan.longitudinalPlanSource = self.mpc.source + longitudinalPlan.fcw = self.fcw + + longitudinalPlan.aTarget = float(self.output_a_target) + longitudinalPlan.shouldStop = bool(self.output_should_stop) + longitudinalPlan.allowBrake = True + longitudinalPlan.allowThrottle = bool(self.allow_throttle) + + pm.send('longitudinalPlan', plan_send) diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py new file mode 100755 index 0000000000..bec7eede0b --- /dev/null +++ b/selfdrive/controls/plannerd.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +from cereal import car +from openpilot.common.params import Params +from openpilot.common.realtime import Priority, config_realtime_process +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.controls.lib.ldw import LaneDepartureWarning +from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner +import cereal.messaging as messaging + + +def main(): + config_realtime_process(5, Priority.CTRL_LOW) + + cloudlog.info("plannerd is waiting for CarParams") + params = Params() + CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams) + cloudlog.info("plannerd got CarParams: %s", CP.brand) + + ldw = LaneDepartureWarning() + longitudinal_planner = LongitudinalPlanner(CP) + pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance']) + sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState'], + poll='modelV2') + + while True: + sm.update() + if sm.updated['modelV2']: + longitudinal_planner.update(sm) + longitudinal_planner.publish(sm, pm) + + ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl']) + msg = messaging.new_message('driverAssistance') + msg.valid = sm.all_checks(['carState', 'carControl', 'modelV2', 'liveParameters']) + msg.driverAssistance.leftLaneDeparture = ldw.left + msg.driverAssistance.rightLaneDeparture = ldw.right + pm.send('driverAssistance', msg) + + +if __name__ == "__main__": + main() diff --git a/selfdrive/controls/radard.py b/selfdrive/controls/radard.py new file mode 100755 index 0000000000..98fce1cb26 --- /dev/null +++ b/selfdrive/controls/radard.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +import math +import numpy as np +from collections import deque +from typing import Any + +import capnp +from cereal import messaging, log, car +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL, Priority, config_realtime_process +from openpilot.common.swaglog import cloudlog +from openpilot.common.simple_kalman import KF1D + + +# Default lead acceleration decay set to 50% at 1s +_LEAD_ACCEL_TAU = 1.5 + +# radar tracks +SPEED, ACCEL = 0, 1 # Kalman filter states enum + +# stationary qualification parameters +V_EGO_STATIONARY = 4. # no stationary object flag below this speed + +RADAR_TO_CENTER = 2.7 # (deprecated) RADAR is ~ 2.7m ahead from center of car +RADAR_TO_CAMERA = 1.52 # RADAR is ~ 1.5m ahead from center of mesh frame + + +class KalmanParams: + def __init__(self, dt: float): + # Lead Kalman Filter params, calculating K from A, C, Q, R requires the control library. + # hardcoding a lookup table to compute K for values of radar_ts between 0.01s and 0.2s + assert dt > .01 and dt < .2, "Radar time step must be between .01s and 0.2s" + self.A = [[1.0, dt], [0.0, 1.0]] + self.C = [1.0, 0.0] + #Q = np.matrix([[10., 0.0], [0.0, 100.]]) + #R = 1e3 + #K = np.matrix([[ 0.05705578], [ 0.03073241]]) + dts = [i * 0.01 for i in range(1, 21)] + K0 = [0.12287673, 0.14556536, 0.16522756, 0.18281627, 0.1988689, 0.21372394, + 0.22761098, 0.24069424, 0.253096, 0.26491023, 0.27621103, 0.28705801, + 0.29750003, 0.30757767, 0.31732515, 0.32677158, 0.33594201, 0.34485814, + 0.35353899, 0.36200124] + K1 = [0.29666309, 0.29330885, 0.29042818, 0.28787125, 0.28555364, 0.28342219, + 0.28144091, 0.27958406, 0.27783249, 0.27617149, 0.27458948, 0.27307714, + 0.27162685, 0.27023228, 0.26888809, 0.26758976, 0.26633338, 0.26511557, + 0.26393339, 0.26278425] + self.K = [[np.interp(dt, dts, K0)], [np.interp(dt, dts, K1)]] + + +class Track: + def __init__(self, identifier: int, v_lead: float, kalman_params: KalmanParams): + self.identifier = identifier + self.cnt = 0 + self.aLeadTau = FirstOrderFilter(_LEAD_ACCEL_TAU, 0.45, DT_MDL) + self.K_A = kalman_params.A + self.K_C = kalman_params.C + self.K_K = kalman_params.K + self.kf = KF1D([[v_lead], [0.0]], self.K_A, self.K_C, self.K_K) + + def update(self, d_rel: float, y_rel: float, v_rel: float, v_lead: float, measured: float): + # relative values, copy + self.dRel = d_rel # LONG_DIST + self.yRel = y_rel # -LAT_DIST + self.vRel = v_rel # REL_SPEED + self.vLead = v_lead + self.measured = measured # measured or estimate + + # computed velocity and accelerations + if self.cnt > 0: + self.kf.update(self.vLead) + + self.vLeadK = float(self.kf.x[SPEED][0]) + self.aLeadK = float(self.kf.x[ACCEL][0]) + + # Learn if constant acceleration + if abs(self.aLeadK) < 0.5: + self.aLeadTau.x = _LEAD_ACCEL_TAU + else: + self.aLeadTau.update(0.0) + + self.cnt += 1 + + def get_RadarState(self, model_prob: float = 0.0): + return { + "dRel": float(self.dRel), + "yRel": float(self.yRel), + "vRel": float(self.vRel), + "vLead": float(self.vLead), + "vLeadK": float(self.vLeadK), + "aLeadK": float(self.aLeadK), + "aLeadTau": float(self.aLeadTau.x), + "status": True, + "fcw": self.is_potential_fcw(model_prob), + "modelProb": model_prob, + "radar": True, + "radarTrackId": self.identifier, + } + + def potential_low_speed_lead(self, v_ego: float): + # stop for stuff in front of you and low speed, even without model confirmation + # Radar points closer than 0.75, are almost always glitches on toyota radars + return abs(self.yRel) < 1.0 and (v_ego < V_EGO_STATIONARY) and (0.75 < self.dRel < 25) + + def is_potential_fcw(self, model_prob: float): + return model_prob > .9 + + def __str__(self): + ret = f"x: {self.dRel:4.1f} y: {self.yRel:4.1f} v: {self.vRel:4.1f} a: {self.aLeadK:4.1f}" + return ret + + +def laplacian_pdf(x: float, mu: float, b: float): + b = max(b, 1e-4) + return math.exp(-abs(x-mu)/b) + + +def match_vision_to_track(v_ego: float, lead: capnp._DynamicStructReader, tracks: dict[int, Track]): + offset_vision_dist = lead.x[0] - RADAR_TO_CAMERA + + def prob(c): + prob_d = laplacian_pdf(c.dRel, offset_vision_dist, lead.xStd[0]) + prob_y = laplacian_pdf(c.yRel, -lead.y[0], lead.yStd[0]) + prob_v = laplacian_pdf(c.vRel + v_ego, lead.v[0], lead.vStd[0]) + + # This isn't exactly right, but it's a good heuristic + return prob_d * prob_y * prob_v + + track = max(tracks.values(), key=prob) + + # if no 'sane' match is found return -1 + # stationary radar points can be false positives + dist_sane = abs(track.dRel - offset_vision_dist) < max([(offset_vision_dist)*.25, 5.0]) + vel_sane = (abs(track.vRel + v_ego - lead.v[0]) < 10) or (v_ego + track.vRel > 3) + if dist_sane and vel_sane: + return track + else: + return None + + +def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: float, model_v_ego: float): + lead_v_rel_pred = lead_msg.v[0] - model_v_ego + return { + "dRel": float(lead_msg.x[0] - RADAR_TO_CAMERA), + "yRel": float(-lead_msg.y[0]), + "vRel": float(lead_v_rel_pred), + "vLead": float(v_ego + lead_v_rel_pred), + "vLeadK": float(v_ego + lead_v_rel_pred), + "aLeadK": float(lead_msg.a[0]), + "aLeadTau": 0.3, + "fcw": False, + "modelProb": float(lead_msg.prob), + "status": True, + "radar": False, + "radarTrackId": -1, + } + + +def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capnp._DynamicStructReader, + model_v_ego: float, low_speed_override: bool = True) -> dict[str, Any]: + # Determine leads, this is where the essential logic happens + if len(tracks) > 0 and ready and lead_msg.prob > .5: + track = match_vision_to_track(v_ego, lead_msg, tracks) + else: + track = None + + lead_dict = {'status': False} + if track is not None: + lead_dict = track.get_RadarState(lead_msg.prob) + elif (track is None) and ready and (lead_msg.prob > .5): + lead_dict = get_RadarState_from_vision(lead_msg, v_ego, model_v_ego) + + if low_speed_override: + low_speed_tracks = [c for c in tracks.values() if c.potential_low_speed_lead(v_ego)] + if len(low_speed_tracks) > 0: + closest_track = min(low_speed_tracks, key=lambda c: c.dRel) + + # Only choose new track if it is actually closer than the previous one + if (not lead_dict['status']) or (closest_track.dRel < lead_dict['dRel']): + lead_dict = closest_track.get_RadarState() + + return lead_dict + + +class RadarD: + def __init__(self, delay: float = 0.0): + self.current_time = 0.0 + + self.tracks: dict[int, Track] = {} + self.kalman_params = KalmanParams(DT_MDL) + + self.v_ego = 0.0 + self.v_ego_hist = deque([0.0], maxlen=int(round(delay / DT_MDL))+1) + self.last_v_ego_frame = -1 + + self.radar_state: capnp._DynamicStructBuilder | None = None + self.radar_state_valid = False + + self.ready = False + + def update(self, sm: messaging.SubMaster, rr: car.RadarData): + self.ready = sm.seen['modelV2'] + self.current_time = 1e-9*max(sm.logMonoTime.values()) + + if sm.recv_frame['carState'] != self.last_v_ego_frame: + self.v_ego = sm['carState'].vEgo + self.v_ego_hist.append(self.v_ego) + self.last_v_ego_frame = sm.recv_frame['carState'] + + ar_pts = {pt.trackId: [pt.dRel, pt.yRel, pt.vRel, pt.measured] for pt in rr.points} + + # *** remove missing points from meta data *** + for ids in list(self.tracks.keys()): + if ids not in ar_pts: + self.tracks.pop(ids, None) + + # *** compute the tracks *** + for ids in ar_pts: + rpt = ar_pts[ids] + + # align v_ego by a fixed time to align it with the radar measurement + v_lead = rpt[2] + self.v_ego_hist[0] + + # create the track if it doesn't exist or it's a new track + if ids not in self.tracks: + self.tracks[ids] = Track(ids, v_lead, self.kalman_params) + self.tracks[ids].update(rpt[0], rpt[1], rpt[2], v_lead, rpt[3]) + + # *** publish radarState *** + self.radar_state_valid = sm.all_checks() + self.radar_state = log.RadarState.new_message() + self.radar_state.mdMonoTime = sm.logMonoTime['modelV2'] + self.radar_state.radarErrors = rr.errors + self.radar_state.carStateMonoTime = sm.logMonoTime['carState'] + + if len(sm['modelV2'].velocity.x): + model_v_ego = sm['modelV2'].velocity.x[0] + else: + model_v_ego = self.v_ego + leads_v3 = sm['modelV2'].leadsV3 + if len(leads_v3) > 1: + self.radar_state.leadOne = get_lead(self.v_ego, self.ready, self.tracks, leads_v3[0], model_v_ego, low_speed_override=True) + self.radar_state.leadTwo = get_lead(self.v_ego, self.ready, self.tracks, leads_v3[1], model_v_ego, low_speed_override=False) + + def publish(self, pm: messaging.PubMaster): + assert self.radar_state is not None + + radar_msg = messaging.new_message("radarState") + radar_msg.valid = self.radar_state_valid + radar_msg.radarState = self.radar_state + pm.send("radarState", radar_msg) + + +# fuses camera and radar data for best lead detection +def main() -> None: + config_realtime_process(5, Priority.CTRL_LOW) + + # wait for stats about the car to come in from controls + cloudlog.info("radard is waiting for CarParams") + CP = messaging.log_from_bytes(Params().get("CarParams", block=True), car.CarParams) + cloudlog.info("radard got CarParams") + + # *** setup messaging + sm = messaging.SubMaster(['modelV2', 'carState', 'liveTracks'], poll='modelV2') + pm = messaging.PubMaster(['radarState']) + + RD = RadarD(CP.radarDelay) + + while 1: + sm.update() + + RD.update(sm, sm['liveTracks']) + RD.publish(pm) + + +if __name__ == "__main__": + main() diff --git a/selfdrive/controls/tests/__init__.py b/selfdrive/controls/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/controls/tests/test_following_distance.py b/selfdrive/controls/tests/test_following_distance.py new file mode 100644 index 0000000000..0fd543dd60 --- /dev/null +++ b/selfdrive/controls/tests/test_following_distance.py @@ -0,0 +1,40 @@ +import pytest +import itertools +from parameterized import parameterized_class + +from cereal import log + +from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import desired_follow_distance, get_T_FOLLOW +from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver + + +def run_following_distance_simulation(v_lead, t_end=100.0, e2e=False, personality=0): + man = Maneuver( + '', + duration=t_end, + initial_speed=float(v_lead), + lead_relevancy=True, + initial_distance_lead=100, + speed_lead_values=[v_lead], + breakpoints=[0.], + e2e=e2e, + personality=personality, + ) + valid, output = man.evaluate() + assert valid + return output[-1,2] - output[-1,1] + + +@parameterized_class(("e2e", "personality", "speed"), itertools.product( + [True, False], # e2e + [log.LongitudinalPersonality.relaxed, # personality + log.LongitudinalPersonality.standard, + log.LongitudinalPersonality.aggressive], + [0,10,35])) # speed +class TestFollowingDistance: + def test_following_distance(self): + v_lead = float(self.speed) + simulation_steady_state = run_following_distance_simulation(v_lead, e2e=self.e2e, personality=self.personality) + correct_steady_state = desired_follow_distance(v_lead, v_lead, get_T_FOLLOW(self.personality)) + err_ratio = 0.2 if self.e2e else 0.1 + assert simulation_steady_state == pytest.approx(correct_steady_state, abs=err_ratio * correct_steady_state + .5) diff --git a/selfdrive/controls/tests/test_latcontrol.py b/selfdrive/controls/tests/test_latcontrol.py new file mode 100644 index 0000000000..0ce06dc996 --- /dev/null +++ b/selfdrive/controls/tests/test_latcontrol.py @@ -0,0 +1,44 @@ +from parameterized import parameterized + +from cereal import car, log +from opendbc.car.car_helpers import interfaces +from opendbc.car.honda.values import CAR as HONDA +from opendbc.car.toyota.values import CAR as TOYOTA +from opendbc.car.nissan.values import CAR as NISSAN +from opendbc.car.gm.values import CAR as GM +from opendbc.car.vehicle_model import VehicleModel +from openpilot.selfdrive.controls.lib.latcontrol_pid import LatControlPID +from openpilot.selfdrive.controls.lib.latcontrol_torque import LatControlTorque +from openpilot.selfdrive.controls.lib.latcontrol_angle import LatControlAngle + + +class TestLatControl: + + @parameterized.expand([(HONDA.HONDA_CIVIC, LatControlPID), (TOYOTA.TOYOTA_RAV4, LatControlTorque), + (NISSAN.NISSAN_LEAF, LatControlAngle), (GM.CHEVROLET_BOLT_EUV, LatControlTorque)]) + def test_saturation(self, car_name, controller): + CarInterface = interfaces[car_name] + CP = CarInterface.get_non_essential_params(car_name) + CI = CarInterface(CP) + VM = VehicleModel(CP) + + controller = controller(CP.as_reader(), CI) + + CS = car.CarState.new_message() + CS.vEgo = 30 + CS.steeringPressed = False + + params = log.LiveParametersData.new_message() + + # Saturate for curvature limited and controller limited + for _ in range(1000): + _, _, lac_log = controller.update(True, CS, VM, params, False, 0, True) + assert lac_log.saturated + + for _ in range(1000): + _, _, lac_log = controller.update(True, CS, VM, params, False, 0, False) + assert not lac_log.saturated + + for _ in range(1000): + _, _, lac_log = controller.update(True, CS, VM, params, False, 1, False) + assert lac_log.saturated diff --git a/selfdrive/controls/tests/test_lateral_mpc.py b/selfdrive/controls/tests/test_lateral_mpc.py new file mode 100644 index 0000000000..3aa0fd1bce --- /dev/null +++ b/selfdrive/controls/tests/test_lateral_mpc.py @@ -0,0 +1,85 @@ +import pytest +import numpy as np +from openpilot.selfdrive.controls.lib.lateral_mpc_lib.lat_mpc import LateralMpc +from openpilot.selfdrive.controls.lib.drive_helpers import CAR_ROTATION_RADIUS +from openpilot.selfdrive.controls.lib.lateral_mpc_lib.lat_mpc import N as LAT_MPC_N + + +def run_mpc(lat_mpc=None, v_ref=30., x_init=0., y_init=0., psi_init=0., curvature_init=0., + lane_width=3.6, poly_shift=0.): + + if lat_mpc is None: + lat_mpc = LateralMpc() + lat_mpc.set_weights(1., .1, 0.0, .05, 800) + + y_pts = poly_shift * np.ones(LAT_MPC_N + 1) + heading_pts = np.zeros(LAT_MPC_N + 1) + curv_rate_pts = np.zeros(LAT_MPC_N + 1) + + x0 = np.array([x_init, y_init, psi_init, curvature_init]) + p = np.column_stack([v_ref * np.ones(LAT_MPC_N + 1), + CAR_ROTATION_RADIUS * np.ones(LAT_MPC_N + 1)]) + + # converge in no more than 10 iterations + for _ in range(10): + lat_mpc.run(x0, p, + y_pts, heading_pts, curv_rate_pts) + return lat_mpc.x_sol + + +class TestLateralMpc: + + def _assert_null(self, sol, curvature=1e-6): + for i in range(len(sol)): + assert sol[0,i,1] == pytest.approx(0, abs=curvature) + assert sol[0,i,2] == pytest.approx(0, abs=curvature) + assert sol[0,i,3] == pytest.approx(0, abs=curvature) + + def _assert_simmetry(self, sol, curvature=1e-6): + for i in range(len(sol)): + assert sol[0,i,1] == pytest.approx(-sol[1,i,1], abs=curvature) + assert sol[0,i,2] == pytest.approx(-sol[1,i,2], abs=curvature) + assert sol[0,i,3] == pytest.approx(-sol[1,i,3], abs=curvature) + assert sol[0,i,0] == pytest.approx(sol[1,i,0], abs=curvature) + + def test_straight(self): + sol = run_mpc() + self._assert_null(np.array([sol])) + + def test_y_symmetry(self): + sol = [] + for y_init in [-0.5, 0.5]: + sol.append(run_mpc(y_init=y_init)) + self._assert_simmetry(np.array(sol)) + + def test_poly_symmetry(self): + sol = [] + for poly_shift in [-1., 1.]: + sol.append(run_mpc(poly_shift=poly_shift)) + self._assert_simmetry(np.array(sol)) + + def test_curvature_symmetry(self): + sol = [] + for curvature_init in [-0.1, 0.1]: + sol.append(run_mpc(curvature_init=curvature_init)) + self._assert_simmetry(np.array(sol)) + + def test_psi_symmetry(self): + sol = [] + for psi_init in [-0.1, 0.1]: + sol.append(run_mpc(psi_init=psi_init)) + self._assert_simmetry(np.array(sol)) + + def test_no_overshoot(self): + y_init = 1. + sol = run_mpc(y_init=y_init) + for y in list(sol[:,1]): + assert y_init >= abs(y) + + def test_switch_convergence(self): + lat_mpc = LateralMpc() + sol = run_mpc(lat_mpc=lat_mpc, poly_shift=3.0, v_ref=7.0) + right_psi_deg = np.degrees(sol[:,2]) + sol = run_mpc(lat_mpc=lat_mpc, poly_shift=-3.0, v_ref=7.0) + left_psi_deg = np.degrees(sol[:,2]) + np.testing.assert_almost_equal(right_psi_deg, -left_psi_deg, decimal=3) diff --git a/selfdrive/controls/tests/test_leads.py b/selfdrive/controls/tests/test_leads.py new file mode 100644 index 0000000000..77384fea20 --- /dev/null +++ b/selfdrive/controls/tests/test_leads.py @@ -0,0 +1,31 @@ +import cereal.messaging as messaging + +from opendbc.car.toyota.values import CAR as TOYOTA +from openpilot.selfdrive.test.process_replay import replay_process_with_name + + +class TestLeads: + def test_radar_fault(self): + # if there's no radar-related can traffic, radard should either not respond or respond with an error + # this is tightly coupled with underlying car radar_interface implementation, but it's a good sanity check + def single_iter_pkg(): + # single iter package, with meaningless cans and empty carState/modelV2 + msgs = [] + for _ in range(500): + can = messaging.new_message("can", 1) + cs = messaging.new_message("carState") + cp = messaging.new_message("carParams") + msgs.append(can.as_reader()) + msgs.append(cs.as_reader()) + msgs.append(cp.as_reader()) + model = messaging.new_message("modelV2") + msgs.append(model.as_reader()) + + return msgs + + msgs = [m for _ in range(3) for m in single_iter_pkg()] + out = replay_process_with_name("card", msgs, fingerprint=TOYOTA.TOYOTA_COROLLA_TSS2) + states = [m for m in out if m.which() == "liveTracks"] + failures = [not state.valid for state in states] + + assert len(states) == 0 or all(failures) diff --git a/selfdrive/controls/tests/test_longcontrol.py b/selfdrive/controls/tests/test_longcontrol.py new file mode 100644 index 0000000000..ab50810d89 --- /dev/null +++ b/selfdrive/controls/tests/test_longcontrol.py @@ -0,0 +1,56 @@ +from cereal import car +from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState, long_control_state_trans + + + + +class TestLongControlStateTransition: + + def test_stay_stopped(self): + CP = car.CarParams.new_message() + active = True + current_state = LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=True, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=False, brake_pressed=True, cruise_standstill=False) + assert next_state == LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=False, brake_pressed=False, cruise_standstill=True) + assert next_state == LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + should_stop=False, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.pid + active = False + next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + should_stop=False, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.off + +def test_engage(): + CP = car.CarParams.new_message() + active = True + current_state = LongCtrlState.off + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=True, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=False, brake_pressed=True, cruise_standstill=False) + assert next_state == LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=False, brake_pressed=False, cruise_standstill=True) + assert next_state == LongCtrlState.stopping + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=False, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.pid + +def test_starting(): + CP = car.CarParams.new_message(startingState=True, vEgoStarting=0.5) + active = True + current_state = LongCtrlState.starting + next_state = long_control_state_trans(CP, active, current_state, v_ego=0.1, + should_stop=False, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.starting + next_state = long_control_state_trans(CP, active, current_state, v_ego=1.0, + should_stop=False, brake_pressed=False, cruise_standstill=False) + assert next_state == LongCtrlState.pid diff --git a/selfdrive/controls/tests/test_torqued_lat_accel_offset.py b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py new file mode 100644 index 0000000000..84389856b6 --- /dev/null +++ b/selfdrive/controls/tests/test_torqued_lat_accel_offset.py @@ -0,0 +1,70 @@ +import numpy as np +from cereal import car, messaging +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY +from opendbc.car import structs +from opendbc.car.lateral import get_friction, FRICTION_THRESHOLD +from openpilot.common.realtime import DT_MDL +from openpilot.selfdrive.locationd.torqued import TorqueEstimator, MIN_BUCKET_POINTS, POINTS_PER_BUCKET, STEER_BUCKET_BOUNDS + +np.random.seed(0) + +LA_ERR_STD = 1.0 +INPUT_NOISE_STD = 0.08 +V_EGO = 30.0 + +WARMUP_BUCKET_POINTS = (1.5*MIN_BUCKET_POINTS).astype(int) +STRAIGHT_ROAD_LA_BOUNDS = (0.02, 0.03) + +ROLL_BIAS_DEG = 2.0 +ROLL_COMPENSATION_BIAS = ACCELERATION_DUE_TO_GRAVITY*float(np.sin(np.deg2rad(ROLL_BIAS_DEG))) +TORQUE_TUNE = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=0.0, friction=0.2) +TORQUE_TUNE_BIASED = structs.CarParams.LateralTorqueTuning(latAccelFactor=2.0, latAccelOffset=-ROLL_COMPENSATION_BIAS, friction=0.2) + +def generate_inputs(torque_tune, la_err_std, input_noise_std=None): + rng = np.random.default_rng(0) + steer_torques = np.concat([rng.uniform(bnd[0], bnd[1], pts) for bnd, pts in zip(STEER_BUCKET_BOUNDS, WARMUP_BUCKET_POINTS, strict=True)]) + la_errs = rng.normal(scale=la_err_std, size=steer_torques.size) + frictions = np.array([get_friction(la_err, 0.0, FRICTION_THRESHOLD, torque_tune) for la_err in la_errs]) + lat_accels = torque_tune.latAccelFactor*steer_torques + torque_tune.latAccelOffset + frictions + if input_noise_std is not None: + steer_torques += rng.normal(scale=input_noise_std, size=steer_torques.size) + lat_accels += rng.normal(scale=input_noise_std, size=steer_torques.size) + return steer_torques, lat_accels + +def get_warmed_up_estimator(steer_torques, lat_accels): + est = TorqueEstimator(car.CarParams()) + for steer_torque, lat_accel in zip(steer_torques, lat_accels, strict=True): + est.filtered_points.add_point(steer_torque, lat_accel) + return est + +def simulate_straight_road_msgs(est): + carControl = messaging.new_message('carControl').carControl + carOutput = messaging.new_message('carOutput').carOutput + carState = messaging.new_message('carState').carState + livePose = messaging.new_message('livePose').livePose + carControl.latActive = True + carState.vEgo = V_EGO + carState.steeringPressed = False + ts = DT_MDL*np.arange(2*POINTS_PER_BUCKET) + steer_torques = np.concat((np.linspace(-0.03, -0.02, POINTS_PER_BUCKET), np.linspace(0.02, 0.03, POINTS_PER_BUCKET))) + lat_accels = TORQUE_TUNE.latAccelFactor * steer_torques + for t, steer_torque, lat_accel in zip(ts, steer_torques, lat_accels, strict=True): + carOutput.actuatorsOutput.torque = float(-steer_torque) + livePose.orientationNED.x = float(np.deg2rad(ROLL_BIAS_DEG)) + livePose.angularVelocityDevice.z = float(lat_accel / V_EGO) + for which, msg in (('carControl', carControl), ('carOutput', carOutput), ('carState', carState), ('livePose', livePose)): + est.handle_log(t, which, msg) + +def test_estimated_offset(): + steer_torques, lat_accels = generate_inputs(TORQUE_TUNE_BIASED, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) + est = get_warmed_up_estimator(steer_torques, lat_accels) + msg = est.get_msg() + # TODO add lataccelfactor and friction check when we have more accurate estimates + assert abs(msg.liveTorqueParameters.latAccelOffsetRaw - TORQUE_TUNE_BIASED.latAccelOffset) < 0.1 + +def test_straight_road_roll_bias(): + steer_torques, lat_accels = generate_inputs(TORQUE_TUNE, la_err_std=LA_ERR_STD, input_noise_std=INPUT_NOISE_STD) + est = get_warmed_up_estimator(steer_torques, lat_accels) + simulate_straight_road_msgs(est) + msg = est.get_msg() + assert (msg.liveTorqueParameters.latAccelOffsetRaw < -0.05) and np.isfinite(msg.liveTorqueParameters.latAccelOffsetRaw) diff --git a/selfdrive/debug/README.md b/selfdrive/debug/README.md new file mode 100644 index 0000000000..83b8a994db --- /dev/null +++ b/selfdrive/debug/README.md @@ -0,0 +1,59 @@ +# debug scripts + +## [can_printer.py](can_printer.py) + +``` +usage: can_printer.py [-h] [--bus BUS] [--max_msg MAX_MSG] [--addr ADDR] + +simple CAN data viewer + +optional arguments: + -h, --help show this help message and exit + --bus BUS CAN bus to print out (default: 0) + --max_msg MAX_MSG max addr (default: None) + --addr ADDR +``` + +## [dump.py](dump.py) + +``` +usage: dump.py [-h] [--pipe] [--raw] [--json] [--dump-json] [--no-print] [--addr ADDR] [--values VALUES] [socket [socket ...]] + +Dump communication sockets. See cereal/services.py for a complete list of available sockets. + +positional arguments: + socket socket names to dump. defaults to all services defined in cereal + +optional arguments: + -h, --help show this help message and exit + --pipe + --raw + --json + --dump-json + --no-print + --addr ADDR + --values VALUES values to monitor (instead of entire event) +``` + +## [vw_mqb_config.py](vw_mqb_config.py) + +``` +usage: vw_mqb_config.py [-h] [--debug] {enable,show,disable} + +Shows Volkswagen EPS software and coding info, and enables or disables Heading Control +Assist (Lane Assist). Useful for enabling HCA on cars without factory Lane Assist that want +to use openpilot integrated at the CAN gateway (J533). + +positional arguments: + {enable,show,disable} + show or modify current EPS HCA config + +optional arguments: + -h, --help show this help message and exit + --debug enable ISO-TP/UDS stack debugging output + +This tool is meant to run directly on a vehicle-installed comma three, with +the openpilot/tmux processes stopped. It should also work on a separate PC with a USB- +attached comma panda. Vehicle ignition must be on. Recommend engine not be running when +making changes. Must turn ignition off and on again for any changes to take effect. +``` diff --git a/selfdrive/debug/__init__.py b/selfdrive/debug/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/debug/can_print_changes.py b/selfdrive/debug/can_print_changes.py new file mode 100755 index 0000000000..97d60b2b05 --- /dev/null +++ b/selfdrive/debug/can_print_changes.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +import argparse +import binascii +import time +from collections import defaultdict + +import cereal.messaging as messaging +from openpilot.selfdrive.debug.can_table import can_table +from openpilot.tools.lib.logreader import LogIterable, LogReader + +RED = '\033[91m' +CLEAR = '\033[0m' + +def update(msgs, bus, dat, low_to_high, high_to_low, quiet=False): + for x in msgs: + if x.which() != 'can': + continue + + for y in x.can: + if y.src == bus: + dat[y.address] = y.dat + + i = int.from_bytes(y.dat, byteorder='big') + l_h = low_to_high[y.address] + h_l = high_to_low[y.address] + + change = None + if (i | l_h) != l_h: + low_to_high[y.address] = i | l_h + change = "+" + + if (~i | h_l) != h_l: + high_to_low[y.address] = ~i | h_l + change = "-" + + if change and not quiet: + print(f"{time.monotonic():.2f}\t{hex(y.address)} ({y.address})\t{change}{binascii.hexlify(y.dat)}") + + +def can_printer(bus=0, init_msgs=None, new_msgs=None, table=False): + logcan = messaging.sub_sock('can', timeout=10) + + dat = defaultdict(int) + low_to_high = defaultdict(int) + high_to_low = defaultdict(int) + + if init_msgs is not None: + update(init_msgs, bus, dat, low_to_high, high_to_low, quiet=True) + + low_to_high_init = low_to_high.copy() + high_to_low_init = high_to_low.copy() + + if new_msgs is not None: + update(new_msgs, bus, dat, low_to_high, high_to_low) + else: + # Live mode + print(f"Waiting for messages on bus {bus}") + try: + while 1: + can_recv = messaging.drain_sock(logcan) + update(can_recv, bus, dat, low_to_high, high_to_low) + time.sleep(0.02) + except KeyboardInterrupt: + pass + + print("\n\n") + tables = "" + for addr in sorted(dat.keys()): + init = low_to_high_init[addr] & high_to_low_init[addr] + now = low_to_high[addr] & high_to_low[addr] + d = now & ~init + if d == 0: + continue + b = d.to_bytes(len(dat[addr]), byteorder='big') + + byts = ''.join([(c if c == '0' else f'{RED}{c}{CLEAR}') for c in str(binascii.hexlify(b))[2:-1]]) + header = f"{hex(addr).ljust(6)}({str(addr).ljust(4)})" + print(header, byts) + tables += f"{header}\n" + tables += can_table(b) + "\n\n" + + if table: + print(tables) + +if __name__ == "__main__": + desc = """Collects messages and prints when a new bit transition is observed. + This is very useful to find signals based on user triggered actions, such as blinkers and seatbelt. + Leave the script running until no new transitions are seen, then perform the action.""" + parser = argparse.ArgumentParser(description=desc, + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--bus", type=int, help="CAN bus to print out", default=0) + parser.add_argument("--table", action="store_true", help="Print a cabana-like table") + parser.add_argument("init", type=str, nargs='?', help="Route or segment to initialize with. Use empty quotes to compare against all zeros.") + parser.add_argument("comp", type=str, nargs='?', help="Route or segment to compare against init") + + args = parser.parse_args() + + init_lr: LogIterable | None = None + new_lr: LogIterable | None = None + + if args.init: + if args.init == '': + init_lr = [] + else: + init_lr = LogReader(args.init) + if args.comp: + new_lr = LogReader(args.comp) + + can_printer(args.bus, init_msgs=init_lr, new_msgs=new_lr, table=args.table) diff --git a/selfdrive/debug/can_printer.py b/selfdrive/debug/can_printer.py new file mode 100755 index 0000000000..f2ed6730d3 --- /dev/null +++ b/selfdrive/debug/can_printer.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import argparse +import binascii +import time +from collections import defaultdict + +import cereal.messaging as messaging + + +def can_printer(bus, max_msg, addr, ascii_decode): + logcan = messaging.sub_sock('can', addr=addr) + + start = time.monotonic() + lp = time.monotonic() + msgs = defaultdict(list) + while 1: + can_recv = messaging.drain_sock(logcan, wait_for_one=True) + for x in can_recv: + for y in x.can: + if y.src == bus: + msgs[y.address].append(y.dat) + + if time.monotonic() - lp > 0.1: + dd = chr(27) + "[2J" + dd += f"{time.monotonic() - start:5.2f}\n" + for _addr in sorted(msgs.keys()): + a = f"\"{msgs[_addr][-1].decode('ascii', 'backslashreplace')}\"" if ascii_decode else "" + x = binascii.hexlify(msgs[_addr][-1]).decode('ascii') + freq = len(msgs[_addr]) / (time.monotonic() - start) + if max_msg is None or _addr < max_msg: + dd += f"{_addr:04X}({_addr:4d})({len(msgs[_addr]):6d})({freq:3}dHz) {x.ljust(20)} {a}\n" + print(dd) + lp = time.monotonic() + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="simple CAN data viewer", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("--bus", type=int, help="CAN bus to print out", default=0) + parser.add_argument("--max_msg", type=int, help="max addr") + parser.add_argument("--ascii", action='store_true', help="decode as ascii") + parser.add_argument("--addr", default="127.0.0.1") + + args = parser.parse_args() + can_printer(args.bus, args.max_msg, args.addr, args.ascii) diff --git a/selfdrive/debug/can_table.py b/selfdrive/debug/can_table.py new file mode 100755 index 0000000000..11d070e708 --- /dev/null +++ b/selfdrive/debug/can_table.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import argparse +import pandas as pd + +import cereal.messaging as messaging + + +def can_table(dat): + rows = [] + for b in dat: + r = list(bin(b).lstrip('0b').zfill(8)) + r += [hex(b)] + rows.append(r) + + df = pd.DataFrame(data=rows) + df.columns = [str(n) for n in range(7, -1, -1)] + [' '] + table = df.to_markdown(tablefmt='grid') + return table + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Cabana-like table of bits for your terminal", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("addr", type=str, nargs=1) + parser.add_argument("bus", type=int, default=0, nargs='?') + + args = parser.parse_args() + + addr = int(args.addr[0], 0) + can = messaging.sub_sock('can', conflate=False, timeout=None) + + print(f"waiting for {hex(addr)} ({addr}) on bus {args.bus}...") + + latest = None + while True: + for msg in messaging.drain_sock(can, wait_for_one=True): + for m in msg.can: + if m.address == addr and m.src == args.bus: + latest = m + + if latest is None: + continue + + table = can_table(latest.dat) + print(f"\n\n{hex(addr)} ({addr}) on bus {args.bus}\n{table}") diff --git a/selfdrive/debug/car/clear_dtc.py b/selfdrive/debug/car/clear_dtc.py new file mode 100755 index 0000000000..b2c5fe3db5 --- /dev/null +++ b/selfdrive/debug/car/clear_dtc.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import sys +import argparse +from subprocess import check_output, CalledProcessError +from opendbc.car.carlog import carlog +from opendbc.car.uds import UdsClient, MessageTimeoutError, SESSION_TYPE, DTC_GROUP_TYPE +from opendbc.car.structs import CarParams +from panda import Panda + +parser = argparse.ArgumentParser(description="clear DTC status") +parser.add_argument("addr", type=lambda x: int(x,0), nargs="?", default=0x7DF) # default is functional (broadcast) address +parser.add_argument("--bus", type=int, default=0) +parser.add_argument('--debug', action='store_true') +args = parser.parse_args() + +if args.debug: + carlog.setLevel('DEBUG') + +try: + check_output(["pidof", "pandad"]) + print("pandad is running, please kill openpilot before running this script! (aborted)") + sys.exit(1) +except CalledProcessError as e: + if e.returncode != 1: # 1 == no process found (pandad not running) + raise e + +panda = Panda() +panda.set_safety_mode(CarParams.SafetyModel.elm327) +uds_client = UdsClient(panda, args.addr, bus=args.bus) +print("extended diagnostic session ...") +try: + uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) +except MessageTimeoutError: + # functional address isn't properly handled so a timeout occurs + if args.addr != 0x7DF: + raise +print("clear diagnostic info ...") +try: + uds_client.clear_diagnostic_information(DTC_GROUP_TYPE.ALL) +except MessageTimeoutError: + # functional address isn't properly handled so a timeout occurs + if args.addr != 0x7DF: + pass +print("") +print("you may need to power cycle your vehicle now") diff --git a/selfdrive/debug/car/disable_ecu.py b/selfdrive/debug/car/disable_ecu.py new file mode 100755 index 0000000000..14d0cbb9cf --- /dev/null +++ b/selfdrive/debug/car/disable_ecu.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +import time +import cereal.messaging as messaging +from opendbc.car.disable_ecu import disable_ecu +from openpilot.selfdrive.car.card import can_comm_callbacks + +if __name__ == "__main__": + sendcan = messaging.pub_sock('sendcan') + logcan = messaging.sub_sock('can') + can_callbacks = can_comm_callbacks(logcan, sendcan) + time.sleep(1) + + # honda bosch radar disable + disabled = disable_ecu(*can_callbacks, bus=1, addr=0x18DAB0F1, com_cont_req=b'\x28\x83\x03', timeout=0.5) + print(f"disabled: {disabled}") diff --git a/selfdrive/debug/car/ecu_addrs.py b/selfdrive/debug/car/ecu_addrs.py new file mode 100755 index 0000000000..584c930ebf --- /dev/null +++ b/selfdrive/debug/car/ecu_addrs.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import argparse +import time +import cereal.messaging as messaging +from opendbc.car.carlog import carlog +from opendbc.car.ecu_addrs import get_all_ecu_addrs +from openpilot.common.params import Params +from openpilot.selfdrive.car.card import can_comm_callbacks, obd_callback + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Get addresses of all ECUs') + parser.add_argument('--debug', action='store_true') + parser.add_argument('--bus', type=int, default=1) + parser.add_argument('--no-obd', action='store_true') + parser.add_argument('--timeout', type=float, default=1.0) + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + logcan = messaging.sub_sock('can') + sendcan = messaging.pub_sock('sendcan') + can_callbacks = can_comm_callbacks(logcan, sendcan) + + # Set up params for pandad + params = Params() + params.remove("FirmwareQueryDone") + params.put_bool("IsOnroad", False) + time.sleep(0.2) # thread is 10 Hz + params.put_bool("IsOnroad", True) + + obd_callback(params)(not args.no_obd) + + print("Getting ECU addresses ...") + ecu_addrs = get_all_ecu_addrs(*can_callbacks, args.bus, args.timeout) + + print() + print("Found ECUs on rx addresses:") + for addr, subaddr, _ in ecu_addrs: + msg = f" {hex(addr)}" + if subaddr is not None: + msg += f" (sub-address: {hex(subaddr)})" + print(msg) diff --git a/selfdrive/debug/car/fw_versions.py b/selfdrive/debug/car/fw_versions.py new file mode 100755 index 0000000000..6ae10d2fb2 --- /dev/null +++ b/selfdrive/debug/car/fw_versions.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +import time +import argparse +import cereal.messaging as messaging +from cereal import car +from opendbc.car.carlog import carlog +from opendbc.car.fw_versions import get_fw_versions, match_fw_to_car +from opendbc.car.vin import get_vin +from openpilot.common.params import Params +from openpilot.selfdrive.car.card import can_comm_callbacks, obd_callback +from typing import Any + +Ecu = car.CarParams.Ecu + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Get firmware version of ECUs') + parser.add_argument('--scan', action='store_true') + parser.add_argument('--debug', action='store_true') + parser.add_argument('--brand', help='Only query addresses/with requests for this brand') + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + logcan = messaging.sub_sock('can') + pandaStates_sock = messaging.sub_sock('pandaStates') + sendcan = messaging.pub_sock('sendcan') + can_callbacks = can_comm_callbacks(logcan, sendcan) + + # Set up params for pandad + params = Params() + params.remove("FirmwareQueryDone") + params.put_bool("IsOnroad", False) + time.sleep(0.2) # thread is 10 Hz + params.put_bool("IsOnroad", True) + set_obd_multiplexing = obd_callback(params) + + extra: Any = None + if args.scan: + extra = {} + # Honda + for i in range(256): + extra[(Ecu.unknown, 0x18da00f1 + (i << 8), None)] = [] + extra[(Ecu.unknown, 0x700 + i, None)] = [] + extra[(Ecu.unknown, 0x750, i)] = [] + extra = {"any": {"debug": extra}} + + num_pandas = len(messaging.recv_one_retry(pandaStates_sock).pandaStates) + + t = time.monotonic() + print("Getting vin...") + set_obd_multiplexing(True) + vin_rx_addr, vin_rx_bus, vin = get_vin(*can_callbacks, (0, 1)) + print(f'RX: {hex(vin_rx_addr)}, BUS: {vin_rx_bus}, VIN: {vin}') + print(f"Getting VIN took {time.monotonic() - t:.3f} s") + print() + + t = time.monotonic() + fw_vers = get_fw_versions(*can_callbacks, set_obd_multiplexing, query_brand=args.brand, extra=extra, num_pandas=num_pandas, progress=True) + _, candidates = match_fw_to_car(fw_vers, vin) + + print() + print("Found FW versions") + print("{") + padding = max([len(fw.brand) for fw in fw_vers] or [0]) + for version in fw_vers: + subaddr = None if version.subAddress == 0 else hex(version.subAddress) + print(f" Brand: {version.brand:{padding}}, bus: {version.bus}, OBD: {version.obdMultiplexing} - " + + f"(Ecu.{version.ecu}, {hex(version.address)}, {subaddr}): [{version.fwVersion!r}]") + print("}") + + print() + print("Possible matches:", candidates) + print(f"Getting fw took {time.monotonic() - t:.3f} s") diff --git a/selfdrive/debug/car/hyundai_enable_radar_points.py b/selfdrive/debug/car/hyundai_enable_radar_points.py new file mode 100755 index 0000000000..93f5949eac --- /dev/null +++ b/selfdrive/debug/car/hyundai_enable_radar_points.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +"""Some Hyundai radars can be reconfigured to output (debug) radar points on bus 1. +Reconfiguration is done over UDS by reading/writing to 0x0142 using the Read/Write Data By Identifier +endpoints (0x22 & 0x2E). This script checks your radar firmware version against a list of known +firmware versions. If you want to try on a new radar make sure to note the default config value +in case it's different from the other radars and you need to revert the changes. + +After changing the config the car should not show any faults when openpilot is not running. +These config changes are persistent across car reboots. You need to run this script again +to go back to the default values. + +USE AT YOUR OWN RISK! Safety features, like AEB and FCW, might be affected by these changes.""" + +import sys +import argparse +from typing import NamedTuple +from subprocess import check_output, CalledProcessError + +from opendbc.car.carlog import carlog +from opendbc.car.uds import UdsClient, SESSION_TYPE, DATA_IDENTIFIER_TYPE +from opendbc.car.structs import CarParams +from panda.python import Panda + +class ConfigValues(NamedTuple): + default_config: bytes + tracks_enabled: bytes + +# If your radar supports changing data identifier 0x0142 as well make a PR to +# this file to add your firmware version. Make sure to post a drive as proof! +# NOTE: these firmware versions do not match what openpilot uses +# because this script uses a different diagnostic session type +SUPPORTED_FW_VERSIONS = { + # 2020 SONATA + b"DN8_ SCC FHCUP 1.00 1.00 99110-L0000\x19\x08)\x15T ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + b"DN8_ SCC F-CUP 1.00 1.00 99110-L0000\x19\x08)\x15T ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2021 SONATA HYBRID + b"DNhe SCC FHCUP 1.00 1.00 99110-L5000\x19\x04&\x13' ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + b"DNhe SCC FHCUP 1.00 1.02 99110-L5000 \x01#\x15# ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2020 PALISADE + b"LX2_ SCC FHCUP 1.00 1.04 99110-S8100\x19\x05\x02\x16V ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2022 PALISADE + b"LX2_ SCC FHCUP 1.00 1.00 99110-S8110!\x04\x05\x17\x01 ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2020 SANTA FE + b"TM__ SCC F-CUP 1.00 1.03 99110-S2000\x19\x050\x13' ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2020 GENESIS G70 + b'IK__ SCC F-CUP 1.00 1.02 96400-G9100\x18\x07\x06\x17\x12 ': ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2019 SANTA FE + b"TM__ SCC F-CUP 1.00 1.00 99110-S1210\x19\x01%\x168 ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + b"TM__ SCC F-CUP 1.00 1.02 99110-S2000\x18\x07\x08\x18W ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), + # 2021 K5 HEV + b"DLhe SCC FHCUP 1.00 1.02 99110-L7000 \x01 \x102 ": ConfigValues( + default_config=b"\x00\x00\x00\x01\x00\x00", + tracks_enabled=b"\x00\x00\x00\x01\x00\x01"), +} + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='configure radar to output points (or reset to default)') + parser.add_argument('--default', action="store_true", default=False, help='reset to default configuration (default: false)') + parser.add_argument('--debug', action="store_true", default=False, help='enable debug output (default: false)') + parser.add_argument('--bus', type=int, default=0, help='can bus to use (default: 0)') + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + try: + check_output(["pidof", "pandad"]) + print("pandad is running, please kill openpilot before running this script! (aborted)") + sys.exit(1) + except CalledProcessError as e: + if e.returncode != 1: # 1 == no process found (pandad not running) + raise e + + confirm = input("power on the vehicle keeping the engine off (press start button twice) then type OK to continue: ").upper().strip() + if confirm != "OK": + print("\nyou didn't type 'OK! (aborted)") + sys.exit(0) + + panda = Panda() + panda.set_safety_mode(CarParams.SafetyModel.elm327) + uds_client = UdsClient(panda, 0x7D0, bus=args.bus) + + print("\n[START DIAGNOSTIC SESSION]") + session_type : SESSION_TYPE = 0x07 # type: ignore + uds_client.diagnostic_session_control(session_type) + + print("[HARDWARE/SOFTWARE VERSION]") + fw_version_data_id : DATA_IDENTIFIER_TYPE = 0xf100 # type: ignore + fw_version = uds_client.read_data_by_identifier(fw_version_data_id) + print(fw_version) + if fw_version not in SUPPORTED_FW_VERSIONS.keys(): + print("radar not supported! (aborted)") + sys.exit(1) + + print("[GET CONFIGURATION]") + config_data_id : DATA_IDENTIFIER_TYPE = 0x0142 # type: ignore + current_config = uds_client.read_data_by_identifier(config_data_id) + config_values = SUPPORTED_FW_VERSIONS[fw_version] + new_config = config_values.default_config if args.default else config_values.tracks_enabled + print(f"current config: 0x{current_config.hex()}") + if current_config != new_config: + print("[CHANGE CONFIGURATION]") + print(f"new config: 0x{new_config.hex()}") + uds_client.write_data_by_identifier(config_data_id, new_config) + if not args.default and current_config != SUPPORTED_FW_VERSIONS[fw_version].default_config: + print("\ncurrent config does not match expected default! (aborted)") + sys.exit(1) + + print("[DONE]") + print("\nrestart your vehicle and ensure there are no faults") + if not args.default: + print("you can run this script again with --default to go back to the original (factory) settings") + else: + print("[DONE]") + print("\ncurrent config is already the desired configuration") + sys.exit(0) diff --git a/selfdrive/debug/car/toyota_eps_factor.py b/selfdrive/debug/car/toyota_eps_factor.py new file mode 100755 index 0000000000..f35a86e1ad --- /dev/null +++ b/selfdrive/debug/car/toyota_eps_factor.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +import sys +import numpy as np +import matplotlib.pyplot as plt +from sklearn import linear_model +from opendbc.car.toyota.values import STEER_THRESHOLD + +from openpilot.tools.lib.logreader import LogReader + +MIN_SAMPLES = 30 * 100 + + +def to_signed(n, bits): + if n >= (1 << max((bits - 1), 0)): + n = n - (1 << max(bits, 0)) + return n + + +def get_eps_factor(lr, plot=False): + engaged = False + steering_pressed = False + torque_cmd, eps_torque = None, None + cmds, eps = [], [] + + for msg in lr: + if msg.which() != 'can': + continue + + for m in msg.can: + if m.address == 0x2e4 and m.src == 128: + engaged = bool(m.dat[0] & 1) + torque_cmd = to_signed((m.dat[1] << 8) | m.dat[2], 16) + elif m.address == 0x260 and m.src == 0: + eps_torque = to_signed((m.dat[5] << 8) | m.dat[6], 16) + steering_pressed = abs(to_signed((m.dat[1] << 8) | m.dat[2], 16)) > STEER_THRESHOLD + + if engaged and torque_cmd is not None and eps_torque is not None and not steering_pressed: + cmds.append(torque_cmd) + eps.append(eps_torque) + else: + if len(cmds) > MIN_SAMPLES: + break + cmds, eps = [], [] + + if len(cmds) < MIN_SAMPLES: + raise Exception("too few samples found in route") + + lm = linear_model.LinearRegression(fit_intercept=False) + lm.fit(np.array(cmds).reshape(-1, 1), eps) + scale_factor = 1. / lm.coef_[0] + + if plot: + plt.plot(np.array(eps) * scale_factor) + plt.plot(cmds) + plt.show() + return scale_factor + + +if __name__ == "__main__": + lr = LogReader(sys.argv[1]) + n = get_eps_factor(lr, plot="--plot" in sys.argv) + print("EPS torque factor: ", n) diff --git a/selfdrive/debug/car/vin.py b/selfdrive/debug/car/vin.py new file mode 100755 index 0000000000..9b1d6528cc --- /dev/null +++ b/selfdrive/debug/car/vin.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import argparse +import time +import cereal.messaging as messaging +from opendbc.car.carlog import carlog +from opendbc.car.vin import get_vin +from openpilot.selfdrive.car.card import can_comm_callbacks + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Get VIN of the car') + parser.add_argument('--debug', action='store_true') + parser.add_argument('--bus', type=int, default=1) + parser.add_argument('--timeout', type=float, default=0.1) + parser.add_argument('--retry', type=int, default=5) + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + sendcan = messaging.pub_sock('sendcan') + logcan = messaging.sub_sock('can') + can_callbacks = can_comm_callbacks(logcan, sendcan) + time.sleep(1) + + vin_rx_addr, vin_rx_bus, vin = get_vin(*can_callbacks, (args.bus,), args.timeout, args.retry) + print(f'RX: {hex(vin_rx_addr)}, BUS: {vin_rx_bus}, VIN: {vin}') diff --git a/selfdrive/debug/car/vw_mqb_config.py b/selfdrive/debug/car/vw_mqb_config.py new file mode 100755 index 0000000000..3c55642e40 --- /dev/null +++ b/selfdrive/debug/car/vw_mqb_config.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 + +import argparse +import struct +from enum import IntEnum +from opendbc.car.carlog import carlog +from opendbc.car.uds import UdsClient, MessageTimeoutError, NegativeResponseError, SESSION_TYPE,\ + DATA_IDENTIFIER_TYPE, ACCESS_TYPE +from opendbc.car.structs import CarParams +from panda import Panda +from datetime import date + +# TODO: extend UDS library to allow custom/vendor-defined data identifiers without ignoring type checks +class VOLKSWAGEN_DATA_IDENTIFIER_TYPE(IntEnum): + CODING = 0x0600 + +# TODO: extend UDS library security_access() to take an access level offset per ISO 14229-1:2020 10.4 and remove this +class ACCESS_TYPE_LEVEL_1(IntEnum): + REQUEST_SEED = ACCESS_TYPE.REQUEST_SEED + 2 + SEND_KEY = ACCESS_TYPE.SEND_KEY + 2 + +MQB_EPS_CAN_ADDR = 0x712 +RX_OFFSET = 0x6a + +if __name__ == "__main__": + desc_text = "Shows Volkswagen EPS software and coding info, and enables or disables Heading Control Assist " + \ + "(Lane Assist). Useful for enabling HCA on cars without factory Lane Assist that want to use " + \ + "openpilot integrated at the CAN gateway (J533)." + epilog_text = "This tool is meant to run directly on a vehicle-installed comma three, with the " + \ + "openpilot/tmux processes stopped. It should also work on a separate PC with a USB-attached comma " + \ + "panda. Vehicle ignition must be on. Recommend engine not be running when making changes. Must " + \ + "turn ignition off and on again for any changes to take effect." + parser = argparse.ArgumentParser(description=desc_text, epilog=epilog_text) + parser.add_argument("--debug", action="store_true", help="enable ISO-TP/UDS stack debugging output") + parser.add_argument("action", choices={"show", "enable", "disable"}, help="show or modify current EPS HCA config") + args = parser.parse_args() + + if args.debug: + carlog.setLevel('DEBUG') + + panda = Panda() + panda.set_safety_mode(CarParams.SafetyModel.elm327) + uds_client = UdsClient(panda, MQB_EPS_CAN_ADDR, MQB_EPS_CAN_ADDR + RX_OFFSET, 1, timeout=0.2) + + try: + uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) + except MessageTimeoutError: + print("Timeout opening session with EPS") + quit() + + odx_file, current_coding = None, None + try: + hw_pn = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_HARDWARE_NUMBER).decode("utf-8") + sw_pn = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_SPARE_PART_NUMBER).decode("utf-8") + sw_ver = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.VEHICLE_MANUFACTURER_ECU_SOFTWARE_VERSION_NUMBER).decode("utf-8") + component = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.SYSTEM_NAME_OR_ENGINE_TYPE).decode("utf-8") + odx_file = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.ODX_FILE).decode("utf-8").rstrip('\x00') + current_coding = uds_client.read_data_by_identifier(VOLKSWAGEN_DATA_IDENTIFIER_TYPE.CODING) # type: ignore + coding_text = current_coding.hex() + + print("\nEPS diagnostic data\n") + print(f" Part No HW: {hw_pn}") + print(f" Part No SW: {sw_pn}") + print(f" SW Version: {sw_ver}") + print(f" Component: {component}") + print(f" Coding: {coding_text}") + print(f" ASAM Dataset: {odx_file}") + except NegativeResponseError: + print("Error fetching data from EPS") + quit() + except MessageTimeoutError: + print("Timeout fetching data from EPS") + quit() + + coding_variant, current_coding_array, coding_byte, coding_bit = None, None, 0, 0 + coding_length = len(current_coding) + + # EPS_MQB_ZFLS + if odx_file in ("EV_SteerAssisMQB", "EV_SteerAssisMNB"): + coding_variant = "ZFLS" + coding_byte = 0 + coding_bit = 4 + + # MQB_PP_APA, MQB_VWBS_GEN2 + elif odx_file in ("EV_SteerAssisVWBSMQBA", "EV_SteerAssisVWBSMQBGen2"): + coding_variant = "APA" + coding_byte = 3 + coding_bit = 0 + + else: + print("Configuration changes not yet supported on this EPS!") + quit() + + current_coding_array = struct.unpack(f"!{coding_length}B", current_coding) + hca_enabled = (current_coding_array[coding_byte] & (1 << coding_bit) != 0) + hca_text = ("DISABLED", "ENABLED")[hca_enabled] + print(f" Lane Assist: {hca_text}") + + try: + params = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION).decode("utf-8") + param_version_system_params = params[1:3] + param_vehicle_type = params[3:5] + param_index_char_curve = params[5:7] + param_version_char_values = params[7:9] + param_version_memory_map = params[9:11] + print("\nEPS parameterization (per-vehicle calibration) data\n") + print(f" Version of system parameters: {param_version_system_params}") + print(f" Vehicle type: {param_vehicle_type}") + print(f" Index of characteristic curve: {param_index_char_curve}") + print(f" Version of characteristic values: {param_version_char_values}") + print(f" Version of memory map: {param_version_memory_map}") + except (NegativeResponseError, MessageTimeoutError): + print("Error fetching parameterization data from EPS!") + quit() + + if args.action in ["enable", "disable"]: + print("\nAttempting configuration update") + + assert(coding_variant in ("ZFLS", "APA")) + # ZFLS EPS config coding length can be anywhere from 1 to 4 bytes, but the + # bit we care about is always in the same place in the first byte + if args.action == "enable": + new_byte = current_coding_array[coding_byte] | (1 << coding_bit) + else: + new_byte = current_coding_array[coding_byte] & ~(1 << coding_bit) + new_coding = current_coding[0:coding_byte] + new_byte.to_bytes(1, "little") + current_coding[coding_byte+1:] + + try: + seed = uds_client.security_access(ACCESS_TYPE_LEVEL_1.REQUEST_SEED) # type: ignore + key = struct.unpack("!I", seed)[0] + 28183 # yeah, it's like that + uds_client.security_access(ACCESS_TYPE_LEVEL_1.SEND_KEY, struct.pack("!I", key)) # type: ignore + except (NegativeResponseError, MessageTimeoutError): + print("Security access failed!") + print("Open the hood and retry (disables the \"diagnostic firewall\" on newer vehicles)") + quit() + + try: + # Programming date and tester number must be written before making + # a change, or write to CODING will fail with request sequence error + # Encoding on tester is unclear, it contains the workshop code in the + # last two bytes, but not the VZ/importer or tester serial number + # Can't seem to read it back, but we can read the calibration tester, + # so fib a little and say that same tester did the programming + current_date = date.today() + formatted_date = current_date.strftime('%y-%m-%d') + year, month, day = (int(part) for part in formatted_date.split('-')) + prog_date = bytes([year, month, day]) + uds_client.write_data_by_identifier(DATA_IDENTIFIER_TYPE.PROGRAMMING_DATE, prog_date) + tester_num = uds_client.read_data_by_identifier(DATA_IDENTIFIER_TYPE.CALIBRATION_REPAIR_SHOP_CODE_OR_CALIBRATION_EQUIPMENT_SERIAL_NUMBER) + uds_client.write_data_by_identifier(DATA_IDENTIFIER_TYPE.REPAIR_SHOP_CODE_OR_TESTER_SERIAL_NUMBER, tester_num) + uds_client.write_data_by_identifier(VOLKSWAGEN_DATA_IDENTIFIER_TYPE.CODING, new_coding) # type: ignore + except (NegativeResponseError, MessageTimeoutError): + print("Writing new configuration failed!") + print("Make sure the comma processes are stopped: tmux kill-session -t comma") + quit() + + try: + # Read back result just to make 100% sure everything worked + current_coding_text = uds_client.read_data_by_identifier(VOLKSWAGEN_DATA_IDENTIFIER_TYPE.CODING).hex() # type: ignore + print(f" New coding: {current_coding_text}") + except (NegativeResponseError, MessageTimeoutError): + print("Reading back updated coding failed!") + quit() + print("EPS configuration successfully updated") diff --git a/selfdrive/debug/check_can_parser_performance.py b/selfdrive/debug/check_can_parser_performance.py new file mode 100755 index 0000000000..20987b3cf4 --- /dev/null +++ b/selfdrive/debug/check_can_parser_performance.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import numpy as np +import time +from tqdm import tqdm + +from cereal import car +from opendbc.car.tests.routes import CarTestRoute +from openpilot.selfdrive.car.tests.test_models import TestCarModelBase +from openpilot.tools.plotjuggler.juggle import DEMO_ROUTE + +N_RUNS = 10 + + +class CarModelTestCase(TestCarModelBase): + test_route = CarTestRoute(DEMO_ROUTE, None) + + +if __name__ == '__main__': + # Get CAN messages and parsers + tm = CarModelTestCase() + tm.setUpClass() + tm.setUp() + + CC = car.CarControl.new_message() + ets = [] + for _ in tqdm(range(N_RUNS)): + start_t = time.process_time_ns() + for msg in tm.can_msgs: + for cp in tm.CI.can_parsers.values(): + if cp is not None: + cp.update_strings(msg) + ets.append((time.process_time_ns() - start_t) * 1e-6) + + print(f'{len(tm.can_msgs)} CAN packets, {N_RUNS} runs') + print(f'{np.mean(ets):.2f} mean ms, {max(ets):.2f} max ms, {min(ets):.2f} min ms, {np.std(ets):.2f} std ms') + print(f'{np.mean(ets) / len(tm.can_msgs):.4f} mean ms / CAN packet') diff --git a/selfdrive/debug/check_freq.py b/selfdrive/debug/check_freq.py new file mode 100755 index 0000000000..1765aeb86b --- /dev/null +++ b/selfdrive/debug/check_freq.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import argparse +import numpy as np +import time +from collections import defaultdict, deque +from collections.abc import MutableSequence + +import cereal.messaging as messaging + + +if __name__ == "__main__": + context = messaging.Context() + poller = messaging.Poller() + + parser = argparse.ArgumentParser() + parser.add_argument("socket", type=str, nargs='*', help="socket name") + args = parser.parse_args() + + socket_names = args.socket + sockets = {} + + rcv_times: defaultdict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) + valids: defaultdict[str, deque[bool]] = defaultdict(lambda: deque(maxlen=100)) + + t = time.monotonic() + for name in socket_names: + sock = messaging.sub_sock(name, poller=poller) + sockets[sock] = name + + prev_print = t + while True: + for socket in poller.poll(100): + msg = messaging.recv_one(socket) + if msg is None: + continue + + name = msg.which() + + t = time.monotonic() + rcv_times[name].append(msg.logMonoTime / 1e9) + valids[name].append(msg.valid) + + if t - prev_print > 1: + print() + for name in socket_names: + dts = np.diff(rcv_times[name]) + mean = np.mean(dts) + print(f"{name}: Freq {1.0 / mean:.2f} Hz, Min {np.min(dts) / mean * 100:.2f}%, Max {np.max(dts) / mean * 100:.2f}%, valid ", all(valids[name])) + + prev_print = t diff --git a/selfdrive/debug/check_lag.py b/selfdrive/debug/check_lag.py new file mode 100755 index 0000000000..341ae79c8b --- /dev/null +++ b/selfdrive/debug/check_lag.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST + +TO_CHECK = ['carState'] + + +if __name__ == "__main__": + sm = messaging.SubMaster(TO_CHECK) + + prev_t: dict[str, float] = {} + + while True: + sm.update() + + for s in TO_CHECK: + if sm.updated[s]: + t = sm.logMonoTime[s] / 1e9 + + if s in prev_t: + expected = 1.0 / (SERVICE_LIST[s].frequency) + dt = t - prev_t[s] + if dt > 10 * expected: + print(t, s, dt) + + prev_t[s] = t diff --git a/selfdrive/debug/check_timings.py b/selfdrive/debug/check_timings.py new file mode 100755 index 0000000000..fc527cd81b --- /dev/null +++ b/selfdrive/debug/check_timings.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import sys +import time +import numpy as np +import datetime +from collections.abc import MutableSequence +from collections import defaultdict + +import cereal.messaging as messaging + + +if __name__ == "__main__": + ts: defaultdict[str, MutableSequence[float]] = defaultdict(list) + socks = {s: messaging.sub_sock(s, conflate=False) for s in sys.argv[1:]} + try: + st = time.monotonic() + while True: + print() + for s, sock in socks.items(): + msgs = messaging.drain_sock(sock) + for m in msgs: + ts[s].append(m.logMonoTime / 1e6) + + if len(ts[s]) > 2: + d = np.diff(ts[s])[-100:] + print(f"{s:25} {np.mean(d):7.2f} {np.std(d):7.2f} {np.max(d):7.2f} {np.min(d):7.2f}") + time.sleep(1) + except KeyboardInterrupt: + print("\n") + print("="*5, "timing summary", "="*5) + for s, sock in socks.items(): + msgs = messaging.drain_sock(sock) + if len(ts[s]) > 2: + d = np.diff(ts[s]) + print(f"{s:25} {np.mean(d):7.2f} {np.std(d):7.2f} {np.max(d):7.2f} {np.min(d):7.2f}") + print("="*5, datetime.timedelta(seconds=time.monotonic()-st), "="*5) diff --git a/selfdrive/debug/count_events.py b/selfdrive/debug/count_events.py new file mode 100755 index 0000000000..76e02d414e --- /dev/null +++ b/selfdrive/debug/count_events.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +import sys +import math +import datetime +from collections import Counter +from pprint import pprint +from typing import cast + +from cereal.services import SERVICE_LIST +from openpilot.tools.lib.logreader import LogReader, ReadMode +from openpilot.selfdrive.test.process_replay.migration import migrate_all + +if __name__ == "__main__": + cnt_events: Counter = Counter() + + cams = [s for s in SERVICE_LIST if s.endswith('CameraState')] + cnt_cameras = dict.fromkeys(cams, 0) + + events: list[tuple[float, set[str]]] = [] + alerts: list[tuple[float, str]] = [] + start_time = math.inf + end_time = -math.inf + ignition_off = None + for msg in migrate_all(LogReader(sys.argv[1], ReadMode.QLOG)): + t = (msg.logMonoTime - start_time) / 1e9 + end_time = max(end_time, msg.logMonoTime) + start_time = min(start_time, msg.logMonoTime) + + if msg.which() == 'onroadEvents': + for e in msg.onroadEvents: + cnt_events[e.name] += 1 + + ae = {str(e.name) for e in msg.onroadEvents if e.name not in ('pedalPressed', 'steerOverride', 'gasPressedOverride')} + if len(events) == 0 or ae != events[-1][1]: + events.append((t, ae)) + + elif msg.which() == 'selfdriveState': + at = msg.selfdriveState.alertType + if "/override" not in at or "lanechange" in at.lower(): + if len(alerts) == 0 or alerts[-1][1] != at: + alerts.append((t, at)) + elif msg.which() == 'pandaStates': + if ignition_off is None: + ign = any(ps.ignitionLine or ps.ignitionCan for ps in msg.pandaStates) + if not ign: + ignition_off = msg.logMonoTime + break + elif msg.which() in cams: + cnt_cameras[msg.which()] += 1 + + duration = (end_time - start_time) / 1e9 + + print("Events") + pprint(cnt_events) + + print("\n") + print("Events") + for t, evt in events: + print(f"{t:8.2f} {evt}") + + print("\n") + print("Cameras") + for k, v in cnt_cameras.items(): + s = SERVICE_LIST[k] + expected_frames = int(s.frequency * duration / cast(float, s.decimation)) + print(" ", k.ljust(20), f"{v}, {v/expected_frames:.1%} of expected") + + print("\n") + print("Alerts") + for t, a in alerts: + print(f"{t:8.2f} {a}") + + print("\n") + if ignition_off is not None: + ignition_off = round((ignition_off - start_time) / 1e9, 2) + print("Ignition off at", ignition_off) + print("Route duration", datetime.timedelta(seconds=duration)) diff --git a/selfdrive/debug/cpu_usage_stat.py b/selfdrive/debug/cpu_usage_stat.py new file mode 100755 index 0000000000..397e9f35f5 --- /dev/null +++ b/selfdrive/debug/cpu_usage_stat.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# type: ignore +''' +System tools like top/htop can only show current cpu usage values, so I write this script to do statistics jobs. + Features: + Use psutil library to sample cpu usage(avergage for all cores) of openpilot processes, at a rate of 5 samples/sec. + Do cpu usage statistics periodically, 5 seconds as a cycle. + Calculate the average cpu usage within this cycle. + Calculate minumium/maximum/accumulated_average cpu usage as long term inspections. + Monitor multiple processes simuteneously. + Sample usage: + root@localhost:/data/openpilot$ python selfdrive/debug/cpu_usage_stat.py pandad,ubloxd + ('Add monitored proc:', './pandad') + ('Add monitored proc:', 'python locationd/ubloxd.py') + pandad: 1.96%, min: 1.96%, max: 1.96%, acc: 1.96% + ubloxd.py: 0.39%, min: 0.39%, max: 0.39%, acc: 0.39% +''' +import psutil +import time +import os +import sys +import numpy as np +import argparse +import re +from collections import defaultdict + +from openpilot.system.manager.process_config import managed_processes + +# Do statistics every 5 seconds +PRINT_INTERVAL = 5 +SLEEP_INTERVAL = 0.2 + +monitored_proc_names = [ + # android procs + 'SurfaceFlinger', 'sensors.qcom' +] + list(managed_processes.keys()) + +cpu_time_names = ['user', 'system', 'children_user', 'children_system'] + + +def get_arg_parser(): + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("proc_names", nargs="?", default='', + help="Process names to be monitored, comma separated") + parser.add_argument("--list_all", action='store_true', + help="Show all running processes' cmdline") + parser.add_argument("--detailed_times", action='store_true', + help="show cpu time details (split by user, system, child user, child system)") + return parser + + +if __name__ == "__main__": + args = get_arg_parser().parse_args(sys.argv[1:]) + if args.list_all: + for p in psutil.process_iter(): + print('cmdline', p.cmdline(), 'name', p.name()) + sys.exit(0) + + if len(args.proc_names) > 0: + monitored_proc_names = args.proc_names.split(',') + monitored_procs = [] + stats = {} + for p in psutil.process_iter(): + if p == psutil.Process(): + continue + matched = any(l for l in p.cmdline() if any(pn for pn in monitored_proc_names if re.match(fr'.*{pn}.*', l, re.M | re.I))) + if matched: + k = ' '.join(p.cmdline()) + print('Add monitored proc:', k) + stats[k] = {'cpu_samples': defaultdict(list), 'min': defaultdict(lambda: None), 'max': defaultdict(lambda: None), + 'avg': defaultdict(float), 'last_cpu_times': None, 'last_sys_time': None} + stats[k]['last_sys_time'] = time.monotonic() + stats[k]['last_cpu_times'] = p.cpu_times() + monitored_procs.append(p) + i = 0 + interval_int = int(PRINT_INTERVAL / SLEEP_INTERVAL) + while True: + for p in monitored_procs: + k = ' '.join(p.cmdline()) + cur_sys_time = time.monotonic() + cur_cpu_times = p.cpu_times() + cpu_times = np.subtract(cur_cpu_times, stats[k]['last_cpu_times']) / (cur_sys_time - stats[k]['last_sys_time']) + stats[k]['last_sys_time'] = cur_sys_time + stats[k]['last_cpu_times'] = cur_cpu_times + cpu_percent = 0 + for num, name in enumerate(cpu_time_names): + stats[k]['cpu_samples'][name].append(cpu_times[num]) + cpu_percent += cpu_times[num] + stats[k]['cpu_samples']['total'].append(cpu_percent) + time.sleep(SLEEP_INTERVAL) + i += 1 + if i % interval_int == 0: + l = [] + for k, stat in stats.items(): + if len(stat['cpu_samples']) <= 0: + continue + for name, samples in stat['cpu_samples'].items(): + samples = np.array(samples) + avg = samples.mean() + c = samples.size + min_cpu = np.amin(samples) + max_cpu = np.amax(samples) + if stat['min'][name] is None or min_cpu < stat['min'][name]: + stat['min'][name] = min_cpu + if stat['max'][name] is None or max_cpu > stat['max'][name]: + stat['max'][name] = max_cpu + stat['avg'][name] = (stat['avg'][name] * (i - c) + avg * c) / (i) + stat['cpu_samples'][name] = [] + + msg = f"avg: {stat['avg']['total']:.2%}, min: {stat['min']['total']:.2%}, max: {stat['max']['total']:.2%} {os.path.basename(k)}" + if args.detailed_times: + for stat_type in ['avg', 'min', 'max']: + msg += f"\n {stat_type}: {[(name + ':' + str(round(stat[stat_type][name] * 100, 2))) for name in cpu_time_names]}" + l.append((os.path.basename(k), stat['avg']['total'], msg)) + l.sort(key=lambda x: -x[1]) + for x in l: + print(x[2]) + print('avg sum: {:.2%} over {} samples {} seconds\n'.format( + sum(stat['avg']['total'] for k, stat in stats.items()), i, i * SLEEP_INTERVAL + )) diff --git a/selfdrive/debug/cycle_alerts.py b/selfdrive/debug/cycle_alerts.py new file mode 100755 index 0000000000..11e75a7a8e --- /dev/null +++ b/selfdrive/debug/cycle_alerts.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +import time +import random + +from cereal import car, log +import cereal.messaging as messaging +from opendbc.car.honda.interface import CarInterface +from openpilot.common.realtime import DT_CTRL +from openpilot.selfdrive.selfdrived.events import ET, Events +from openpilot.selfdrive.selfdrived.alertmanager import AlertManager +from openpilot.system.manager.process_config import managed_processes + +EventName = log.OnroadEvent.EventName + +def randperc() -> float: + return 100. * random.random() + +def cycle_alerts(duration=200, is_metric=False): + # all alerts + #alerts = list(EVENTS.keys()) + + # this plays each type of audible alert + alerts = [ + (EventName.buttonEnable, ET.ENABLE), + (EventName.buttonCancel, ET.USER_DISABLE), + (EventName.wrongGear, ET.NO_ENTRY), + + (EventName.locationdTemporaryError, ET.SOFT_DISABLE), + (EventName.paramsdTemporaryError, ET.SOFT_DISABLE), + (EventName.accFaulted, ET.IMMEDIATE_DISABLE), + + # DM sequence + (EventName.preDriverDistracted, ET.WARNING), + (EventName.promptDriverDistracted, ET.WARNING), + (EventName.driverDistracted, ET.WARNING), + ] + + # debug alerts + alerts = [ + #(EventName.highCpuUsage, ET.NO_ENTRY), + #(EventName.lowMemory, ET.PERMANENT), + #(EventName.overheat, ET.PERMANENT), + #(EventName.outOfSpace, ET.PERMANENT), + #(EventName.modeldLagging, ET.PERMANENT), + #(EventName.processNotRunning, ET.NO_ENTRY), + #(EventName.commIssue, ET.NO_ENTRY), + #(EventName.calibrationInvalid, ET.PERMANENT), + (EventName.cameraMalfunction, ET.PERMANENT), + (EventName.cameraFrameRate, ET.PERMANENT), + ] + + cameras = ['roadCameraState', 'wideRoadCameraState', 'driverCameraState'] + + CS = car.CarState.new_message() + CP = CarInterface.get_non_essential_params("HONDA_CIVIC") + sm = messaging.SubMaster(['deviceState', 'pandaStates', 'roadCameraState', 'modelV2', 'liveCalibration', + 'driverMonitoringState', 'longitudinalPlan', 'livePose', + 'managerState'] + cameras) + + pm = messaging.PubMaster(['selfdriveState', 'pandaStates', 'deviceState']) + + events = Events() + AM = AlertManager() + + frame = 0 + while True: + for alert, et in alerts: + events.clear() + events.add(alert) + + sm['deviceState'].freeSpacePercent = randperc() + sm['deviceState'].memoryUsagePercent = int(randperc()) + sm['deviceState'].cpuTempC = [randperc() for _ in range(3)] + sm['deviceState'].gpuTempC = [randperc() for _ in range(3)] + sm['deviceState'].cpuUsagePercent = [int(randperc()) for _ in range(8)] + sm['modelV2'].frameDropPerc = randperc() + + if random.random() > 0.25: + sm['modelV2'].velocity.x = [random.random(), ] + if random.random() > 0.25: + CS.vEgo = random.random() + + procs = [p.get_process_state_msg() for p in managed_processes.values()] + random.shuffle(procs) + for i in range(random.randint(0, 10)): + procs[i].shouldBeRunning = True + sm['managerState'].processes = procs + + sm['liveCalibration'].rpyCalib = [-1 * random.random() for _ in range(random.randint(0, 3))] + + for s in sm.data.keys(): + prob = 0.3 if s in cameras else 0.08 + sm.alive[s] = random.random() > prob + sm.valid[s] = random.random() > prob + sm.freq_ok[s] = random.random() > prob + + a = events.create_alerts([et, ], [CP, CS, sm, is_metric, 0]) + AM.add_many(frame, a) + alert = AM.process_alerts(frame, []) + print(alert) + for _ in range(duration): + dat = messaging.new_message() + dat.init('selfdriveState') + dat.selfdriveState.enabled = False + + if alert: + dat.selfdriveState.alertText1 = alert.alert_text_1 + dat.selfdriveState.alertText2 = alert.alert_text_2 + dat.selfdriveState.alertSize = alert.alert_size + dat.selfdriveState.alertStatus = alert.alert_status + dat.selfdriveState.alertType = alert.alert_type + dat.selfdriveState.alertSound = alert.audible_alert + pm.send('selfdriveState', dat) + + dat = messaging.new_message() + dat.init('deviceState') + dat.deviceState.started = True + pm.send('deviceState', dat) + + dat = messaging.new_message('pandaStates', 1) + dat.pandaStates[0].ignitionLine = True + dat.pandaStates[0].pandaType = log.PandaState.PandaType.uno + pm.send('pandaStates', dat) + + frame += 1 + time.sleep(DT_CTRL) + +if __name__ == '__main__': + cycle_alerts() diff --git a/selfdrive/debug/debug_fw_fingerprinting_offline.py b/selfdrive/debug/debug_fw_fingerprinting_offline.py new file mode 100755 index 0000000000..d841e91053 --- /dev/null +++ b/selfdrive/debug/debug_fw_fingerprinting_offline.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +import argparse + +from opendbc.car import uds +from openpilot.tools.lib.live_logreader import live_logreader +from openpilot.tools.lib.logreader import LogReader, ReadMode + + +def main(route: str | None, addrs: list[int], rxoffset: int | None): + """ + TODO: + - highlight TX vs RX clearly + - disambiguate sendcan and can (useful to know if something sent on sendcan made it to the bus on can->128) + - print as fixed width table, easier to read + """ + + if route is None: + lr = live_logreader() + else: + lr = LogReader(route, default_mode=ReadMode.RLOG, sort_by_time=True) + + start_mono_time = None + prev_mono_time = 0 + + # include rx addresses + addrs = addrs + [uds.get_rx_addr_for_tx_addr(addr, rxoffset) for addr in addrs] + + for msg in lr: + if msg.which() == 'can': + if start_mono_time is None: + start_mono_time = msg.logMonoTime + + if msg.which() in ("can", 'sendcan'): + for can in getattr(msg, msg.which()): + if can.address in addrs or not len(addrs): + if msg.logMonoTime != prev_mono_time: + print() + prev_mono_time = msg.logMonoTime + print(f"{msg.which():>7}: rxaddr={can.address}, bus={str(can.src) + ',':<4} {round((msg.logMonoTime - start_mono_time) * 1e-6)} ms, " + + f"0x{can.dat.hex()}, {can.dat}, {len(can.dat)=}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='View back and forth ISO-TP communication between various ECUs given an address') + parser.add_argument('route', nargs='?', help='Route name, live if not specified') + parser.add_argument('--addrs', nargs='*', default=[], help='List of tx address to view (0x7e0 for engine)') + parser.add_argument('--rxoffset', default='') + args = parser.parse_args() + + addrs = [int(addr, base=16) if addr.startswith('0x') else int(addr) for addr in args.addrs] + rxoffset = int(args.rxoffset, base=16) if args.rxoffset else None + main(args.route, addrs, rxoffset) diff --git a/selfdrive/debug/dump.py b/selfdrive/debug/dump.py new file mode 100755 index 0000000000..78cf51e3db --- /dev/null +++ b/selfdrive/debug/dump.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +import sys +import argparse +import json +import codecs + +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.tools.lib.live_logreader import raw_live_logreader + + +codecs.register_error("strict", codecs.backslashreplace_errors) + +def hexdump(msg): + m = str.upper(msg.hex()) + m = [m[i:i+2] for i in range(0,len(m),2)] + m = [m[i:i+16] for i in range(0,len(m),16)] + for row,dump in enumerate(m): + addr = '%08X:' % (row*16) + raw = ' '.join(dump[:8]) + ' ' + ' '.join(dump[8:]) + space = ' ' * (48 - len(raw)) + asci = ''.join(chr(int(x,16)) if 0x20 <= int(x,16) <= 0x7E else '.' for x in dump) + print(f'{addr} {raw} {space} {asci}') + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='Dump communication sockets. See cereal/services.py for a complete list of available sockets.') + parser.add_argument('--pipe', action='store_true') + parser.add_argument('--raw', action='store_true') + parser.add_argument('--json', action='store_true') + parser.add_argument('--dump-json', action='store_true') + parser.add_argument('--no-print', action='store_true') + parser.add_argument('--addr', default='127.0.0.1') + parser.add_argument('--values', help='values to monitor (instead of entire event)') + parser.add_argument("socket", type=str, nargs='*', default=list(SERVICE_LIST.keys()), help="socket names to dump. defaults to all services defined in cereal") + args = parser.parse_args() + + lr = raw_live_logreader(args.socket, args.addr) + + values = None + if args.values: + values = [s.strip().split(".") for s in args.values.split(",")] + + for msg in lr: + with log.Event.from_bytes(msg) as evt: + if not args.no_print: + if args.pipe: + sys.stdout.write(str(msg)) + sys.stdout.flush() + elif args.raw: + hexdump(msg) + elif args.json: + print(json.loads(msg)) + elif args.dump_json: + print(json.dumps(evt.to_dict())) + elif values: + print(f"logMonotime = {evt.logMonoTime}") + for value in values: + if hasattr(evt, value[0]): + item = evt + for key in value: + item = getattr(item, key) + print(f"{'.'.join(value)} = {item}") + print("") + else: + try: + print(evt) + except UnicodeDecodeError: + w = evt.which() + s = f"( logMonoTime {evt.logMonoTime} \n {w} = " + s += str(evt.__getattr__(w)) + s += f"\n valid = {evt.valid} )" + print(s) diff --git a/selfdrive/debug/dump_car_docs.py b/selfdrive/debug/dump_car_docs.py new file mode 100755 index 0000000000..f0e99cda24 --- /dev/null +++ b/selfdrive/debug/dump_car_docs.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import argparse +import pickle + +from opendbc.car.docs import get_all_car_docs + + +def dump_car_docs(path): + with open(path, 'wb') as f: + pickle.dump(get_all_car_docs(), f) + print(f'Dumping car info to {path}') + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--path", required=True) + args = parser.parse_args() + dump_car_docs(args.path) diff --git a/selfdrive/debug/filter_log_message.py b/selfdrive/debug/filter_log_message.py new file mode 100755 index 0000000000..9cbab0b41f --- /dev/null +++ b/selfdrive/debug/filter_log_message.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +import argparse +import json + +import cereal.messaging as messaging +from openpilot.tools.lib.logreader import LogReader + +LEVELS = { + "DEBUG": 10, + "INFO": 20, + "WARNING": 30, + "ERROR": 40, + "CRITICAL": 50, +} + +ANDROID_LOG_SOURCE = { + 0: "MAIN", + 1: "RADIO", + 2: "EVENTS", + 3: "SYSTEM", + 4: "CRASH", + 5: "KERNEL", +} + + +def print_logmessage(t, msg, min_level): + try: + log = json.loads(msg) + if log['levelnum'] >= min_level: + print(f"[{t / 1e9:.6f}] {log['filename']}:{log.get('lineno', '')} - {log.get('funcname', '')}: {log['msg']}") + if 'exc_info' in log: + print(log['exc_info']) + except json.decoder.JSONDecodeError: + print(f"[{t / 1e9:.6f}] decode error: {msg}") + + +def print_androidlog(t, msg): + source = ANDROID_LOG_SOURCE[msg.id] + try: + m = json.loads(msg.message)['MESSAGE'] + except Exception: + m = msg.message + + print(f"[{t / 1e9:.6f}] {source} {msg.pid} {msg.tag} - {m}") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--absolute', action='store_true') + parser.add_argument('--level', default='DEBUG') + parser.add_argument('--addr', default='127.0.0.1') + parser.add_argument("route", type=str, nargs='*', help="route name + segment number for offline usage") + args = parser.parse_args() + + min_level = LEVELS[args.level] + + if args.route: + st = None if not args.absolute else 0 + for route in args.route: + lr = LogReader(route, sort_by_time=True) + for m in lr: + if st is None: + st = m.logMonoTime + if m.which() == 'logMessage': + print_logmessage(m.logMonoTime-st, m.logMessage, min_level) + elif m.which() == 'errorLogMessage': + print_logmessage(m.logMonoTime-st, m.errorLogMessage, min_level) + elif m.which() == 'androidLog': + print_androidlog(m.logMonoTime-st, m.androidLog) + else: + sm = messaging.SubMaster(['logMessage', 'androidLog'], addr=args.addr) + while True: + sm.update() + + if sm.updated['logMessage']: + print_logmessage(sm.logMonoTime['logMessage'], sm['logMessage'], min_level) + + if sm.updated['androidLog']: + print_androidlog(sm.logMonoTime['androidLog'], sm['androidLog']) diff --git a/selfdrive/debug/fingerprint_from_route.py b/selfdrive/debug/fingerprint_from_route.py new file mode 100755 index 0000000000..179ff4c838 --- /dev/null +++ b/selfdrive/debug/fingerprint_from_route.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +import sys +from openpilot.tools.lib.logreader import LogReader, ReadMode + + +def get_fingerprint(lr): + # TODO: make this a nice tool for car ports. should also work with qlogs for FW + + fw = None + vin = None + msgs = {} + for msg in lr: + if msg.which() == 'carParams': + fw = msg.carParams.carFw + vin = msg.carParams.carVin + elif msg.which() == 'can': + for c in msg.can: + # read also msgs sent by EON on CAN bus 0x80 and filter out the + # addr with more than 11 bits + if c.src % 0x80 == 0 and c.address < 0x800 and c.address not in (0x7df, 0x7e0, 0x7e8): + msgs[c.address] = len(c.dat) + + # show CAN fingerprint + fingerprint = ', '.join(f"{v[0]}: {v[1]}" for v in sorted(msgs.items())) + print(f"\nfound {len(msgs)} messages. CAN fingerprint:\n") + print(fingerprint) + + # TODO: also print the fw fingerprint merged with the existing ones + # show FW fingerprint + print("\nFW fingerprint:\n") + for f in fw: + print(f" (Ecu.{f.ecu}, {hex(f.address)}, {None if f.subAddress == 0 else f.subAddress}): [") + print(f" {f.fwVersion},") + print(" ],") + print() + print(f"VIN: {vin}") + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: ./fingerprint_from_route.py ") + sys.exit(1) + + lr = LogReader(sys.argv[1], ReadMode.QLOG) + get_fingerprint(lr) diff --git a/selfdrive/debug/fuzz_fw_fingerprint.py b/selfdrive/debug/fuzz_fw_fingerprint.py new file mode 100755 index 0000000000..fa99e6bfbe --- /dev/null +++ b/selfdrive/debug/fuzz_fw_fingerprint.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# type: ignore +import random +from collections import defaultdict + +from tqdm import tqdm + +from opendbc.car.fw_versions import match_fw_to_car_fuzzy +from opendbc.car.toyota.values import FW_VERSIONS as TOYOTA_FW_VERSIONS +from opendbc.car.honda.values import FW_VERSIONS as HONDA_FW_VERSIONS +from opendbc.car.hyundai.values import FW_VERSIONS as HYUNDAI_FW_VERSIONS +from opendbc.car.volkswagen.values import FW_VERSIONS as VW_FW_VERSIONS + + +FWS = {} +FWS.update(TOYOTA_FW_VERSIONS) +FWS.update(HONDA_FW_VERSIONS) +FWS.update(HYUNDAI_FW_VERSIONS) +FWS.update(VW_FW_VERSIONS) + +if __name__ == "__main__": + total = 0 + match = 0 + wrong_match = 0 + confusions = defaultdict(set) + + for _ in tqdm(range(1000)): + for candidate, fws in FWS.items(): + fw_dict = {} + for (_, addr, subaddr), fw_list in fws.items(): + fw_dict[(addr, subaddr)] = [random.choice(fw_list)] + + matches = match_fw_to_car_fuzzy(fw_dict, log=False, exclude=candidate) + + total += 1 + if len(matches) == 1: + if list(matches)[0] == candidate: + match += 1 + else: + confusions[candidate] |= matches + wrong_match += 1 + + print() + for candidate, wrong_matches in sorted(confusions.items()): + print(candidate, wrong_matches) + + print() + print(f"Total fuzz cases: {total}") + print(f"Correct matches: {match}") + print(f"Wrong matches: {wrong_match}") + + diff --git a/selfdrive/debug/get_fingerprint.py b/selfdrive/debug/get_fingerprint.py new file mode 100755 index 0000000000..75c3d5579f --- /dev/null +++ b/selfdrive/debug/get_fingerprint.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +# simple script to get a vehicle fingerprint. + +# Instructions: +# - connect to a Panda +# - run selfdrive/pandad/pandad +# - launching this script +# Note: it's very important that the car is in stock mode, in order to collect a complete fingerprint +# - since some messages are published at low frequency, keep this script running for at least 30s, +# until all messages are received at least once + +import cereal.messaging as messaging + +logcan = messaging.sub_sock('can') +msgs = {} +while True: + lc = messaging.recv_sock(logcan, True) + if lc is None: + continue + + for c in lc.can: + # read also msgs sent by EON on CAN bus 0x80 and filter out the + # addr with more than 11 bits + if c.src % 0x80 == 0 and c.address < 0x800 and c.address not in (0x7df, 0x7e0, 0x7e8): + msgs[c.address] = len(c.dat) + + fingerprint = ', '.join(f"{v[0]}: {v[1]}" for v in sorted(msgs.items())) + + print(f"number of messages {len(msgs)}:") + print(f"fingerprint {fingerprint}") diff --git a/selfdrive/debug/live_cpu_and_temp.py b/selfdrive/debug/live_cpu_and_temp.py new file mode 100755 index 0000000000..ee0524ec9d --- /dev/null +++ b/selfdrive/debug/live_cpu_and_temp.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +import argparse +import numpy as np +import capnp +from collections import defaultdict + +from cereal.messaging import SubMaster + +def cputime_total(ct): + return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq + + +def cputime_busy(ct): + return ct.user + ct.nice + ct.system + ct.irq + ct.softirq + + +def proc_cputime_total(ct): + return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem + + +def proc_name(proc): + name = proc.name + if len(proc.cmdline): + name = proc.cmdline[0] + if len(proc.exe): + name = proc.exe + " - " + name + + return name + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--mem', action='store_true') + parser.add_argument('--cpu', action='store_true') + args = parser.parse_args() + + sm = SubMaster(['deviceState', 'procLog']) + + last_temp = 0.0 + last_mem = 0.0 + total_times = [0.]*8 + busy_times = [0.]*8 + + prev_proclog: capnp._DynamicStructReader | None = None + prev_proclog_t: int | None = None + + while True: + sm.update() + + if sm.updated['deviceState']: + t = sm['deviceState'] + last_temp = np.mean(t.cpuTempC) + last_mem = t.memoryUsagePercent + + if sm.updated['procLog']: + m = sm['procLog'] + + cores = [0.]*8 + total_times_new = [0.]*8 + busy_times_new = [0.]*8 + + for c in m.cpuTimes: + n = c.cpuNum + total_times_new[n] = cputime_total(c) + busy_times_new[n] = cputime_busy(c) + + for n in range(8): + t_busy = busy_times_new[n] - busy_times[n] + t_total = total_times_new[n] - total_times[n] + cores[n] = t_busy / t_total + + total_times = total_times_new[:] + busy_times = busy_times_new[:] + + print(f"CPU {100.0 * np.mean(cores):.2f}% - RAM: {last_mem:.2f}% - Temp {last_temp:.2f}C") + + if args.cpu and prev_proclog is not None and prev_proclog_t is not None: + procs: dict[str, float] = defaultdict(float) + dt = (sm.logMonoTime['procLog'] - prev_proclog_t) / 1e9 + for proc in m.procs: + try: + name = proc_name(proc) + prev_proc = [p for p in prev_proclog.procs if proc.pid == p.pid][0] + cpu_time = proc_cputime_total(proc) - proc_cputime_total(prev_proc) + cpu_usage = cpu_time / dt * 100. + procs[name] += cpu_usage + except IndexError: + pass + + print("Top CPU usage:") + for k, v in sorted(procs.items(), key=lambda item: item[1], reverse=True)[:10]: + print(f"{k.rjust(70)} {v:.2f} %") + print() + + if args.mem: + mems = {} + for proc in m.procs: + name = proc_name(proc) + mems[name] = float(proc.memRss) / 1e6 + print("Top memory usage:") + for k, v in sorted(mems.items(), key=lambda item: item[1], reverse=True)[:10]: + print(f"{k.rjust(70)} {v:.2f} MB") + print() + + prev_proclog = m + prev_proclog_t = sm.logMonoTime['procLog'] diff --git a/selfdrive/debug/max_lat_accel.py b/selfdrive/debug/max_lat_accel.py new file mode 100755 index 0000000000..dc44e8ac40 --- /dev/null +++ b/selfdrive/debug/max_lat_accel.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +import argparse +import numpy as np +import matplotlib.pyplot as plt +from functools import partial +from tqdm import tqdm +from typing import NamedTuple +from openpilot.tools.lib.logreader import LogReader +from openpilot.selfdrive.locationd.models.pose_kf import EARTH_G + +RLOG_MIN_LAT_ACTIVE = 50 +RLOG_MIN_STEERING_UNPRESSED = 50 +RLOG_MIN_REQUESTING_MAX = 25 # sample many times after reaching max torque + +QLOG_DECIMATION = 10 + + +class Event(NamedTuple): + lateral_accel: float + speed: float + roll: float + timestamp: float # relative to start of route (s) + + +def find_events(lr: LogReader, extrapolate: bool = False, qlog: bool = False) -> list[Event]: + min_lat_active = RLOG_MIN_LAT_ACTIVE // QLOG_DECIMATION if qlog else RLOG_MIN_LAT_ACTIVE + min_steering_unpressed = RLOG_MIN_STEERING_UNPRESSED // QLOG_DECIMATION if qlog else RLOG_MIN_STEERING_UNPRESSED + min_requesting_max = RLOG_MIN_REQUESTING_MAX // QLOG_DECIMATION if qlog else RLOG_MIN_REQUESTING_MAX + + # if we test with driver torque safety, max torque can be slightly noisy + steer_threshold = 0.7 if extrapolate else 0.95 + + events = [] + + # state tracking + steering_unpressed = 0 # frames + requesting_max = 0 # frames + lat_active = 0 # frames + + # current state + curvature = 0 + v_ego = 0 + roll = 0 + out_torque = 0 + + start_ts = 0 + for msg in lr: + if msg.which() == 'carControl': + if start_ts == 0: + start_ts = msg.logMonoTime + + lat_active = lat_active + 1 if msg.carControl.latActive else 0 + + elif msg.which() == 'carOutput': + out_torque = msg.carOutput.actuatorsOutput.torque + requesting_max = requesting_max + 1 if abs(out_torque) > steer_threshold else 0 + + elif msg.which() == 'carState': + steering_unpressed = steering_unpressed + 1 if not msg.carState.steeringPressed else 0 + v_ego = msg.carState.vEgo + + elif msg.which() == 'controlsState': + curvature = msg.controlsState.curvature + + elif msg.which() == 'liveParameters': + roll = msg.liveParameters.roll + + if lat_active > min_lat_active and steering_unpressed > min_steering_unpressed and requesting_max > min_requesting_max: + # TODO: record max lat accel at the end of the event, need to use the past lat accel as overriding can happen before we detect it + requesting_max = 0 + + factor = 1 / abs(out_torque) + current_lateral_accel = (curvature * v_ego ** 2 * factor) - roll * EARTH_G + events.append(Event(current_lateral_accel, v_ego, roll, round((msg.logMonoTime - start_ts) * 1e-9, 2))) + print(events[-1]) + + return events + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Find max lateral acceleration events", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("route", nargs='+') + parser.add_argument("-e", "--extrapolate", action="store_true", help="Extrapolates max lateral acceleration events linearly. " + + "This option can be far less accurate.") + args = parser.parse_args() + + events = [] + for route in tqdm(args.route): + try: + lr = LogReader(route, sort_by_time=True) + except Exception: + print(f'Skipping {route}') + continue + + qlog = route.endswith('/q') + if qlog: + print('WARNING: Treating route as qlog!') + + print('Finding events...') + events += lr.run_across_segments(8, partial(find_events, extrapolate=args.extrapolate, qlog=qlog), disable_tqdm=True) + + print() + print(f'Found {len(events)} events') + + perc_left_accel = -np.percentile([-ev.lateral_accel for ev in events if ev.lateral_accel < 0] or [0], 90) + perc_right_accel = np.percentile([ev.lateral_accel for ev in events if ev.lateral_accel > 0] or [0], 90) + + CP = lr.first('carParams') + + plt.ion() + plt.clf() + plt.suptitle(f'{CP.carFingerprint} - Max lateral acceleration events') + plt.title(', '.join(args.route)) + plt.scatter([ev.speed for ev in events], [ev.lateral_accel for ev in events], label='max lateral accel events') + + plt.plot([0, 35], [3, 3], c='r', label='ISO 11270 - 3 m/s^2') + plt.plot([0, 35], [-3, -3], c='r') + + plt.plot([0, 35], [perc_left_accel, perc_left_accel], c='g', linestyle='--', label='90th percentile left lateral accel') + plt.plot([0, 35], [perc_right_accel, perc_right_accel], c='#ff7f0e', linestyle='--', label='90th percentile right lateral accel') + plt.text(0.4, float(perc_left_accel + 0.4), f'{perc_left_accel:.2f} m/s^2', verticalalignment='center', fontsize=12) + plt.text(0.4, float(perc_right_accel - 0.4), f'{perc_right_accel:.2f} m/s^2', verticalalignment='center', fontsize=12) + + plt.xlim(0, 35) + plt.ylim(-5, 5) + plt.xlabel('speed (m/s)') + plt.ylabel('lateral acceleration (m/s^2)') + plt.legend() + plt.show(block=True) diff --git a/selfdrive/debug/measure_torque_time_to_max.py b/selfdrive/debug/measure_torque_time_to_max.py new file mode 100755 index 0000000000..7052dccf7d --- /dev/null +++ b/selfdrive/debug/measure_torque_time_to_max.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# type: ignore + +import os +import argparse +import struct +from collections import deque +from statistics import mean + +from cereal import log +import cereal.messaging as messaging + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='Sniff a communication socket') + parser.add_argument('--addr', default='127.0.0.1') + args = parser.parse_args() + + if args.addr != "127.0.0.1": + os.environ["ZMQ"] = "1" + messaging.reset_context() + + poller = messaging.Poller() + messaging.sub_sock('can', poller, addr=args.addr) + + active = 0 + start_t = 0 + start_v = 0 + max_v = 0 + max_t = 0 + window = deque(maxlen=10) + avg = 0 + while 1: + polld = poller.poll(1000) + for sock in polld: + msg = sock.receive() + with log.Event.from_bytes(msg) as log_evt: + evt = log_evt + + for item in evt.can: + if item.address == 0xe4 and item.src == 128: + torque_req = struct.unpack('!h', item.dat[0:2])[0] + # print(torque_req) + active = abs(torque_req) > 0 + if abs(torque_req) < 100: + if max_v > 5: + print(f'{start_v} -> {max_v} = {round(max_v - start_v, 2)} over {round(max_t - start_t, 2)}s') + start_t = evt.logMonoTime / 1e9 + start_v = avg + max_t = 0 + max_v = 0 + if item.address == 0x1ab and item.src == 0: + motor_torque = ((item.dat[0] & 0x3) << 8) + item.dat[1] + window.append(motor_torque) + avg = mean(window) + #print(f'{evt.logMonoTime}: {avg}') + if active and avg > max_v + 0.5: + max_v = avg + max_t = evt.logMonoTime / 1e9 diff --git a/selfdrive/debug/print_docs_diff.py b/selfdrive/debug/print_docs_diff.py new file mode 100755 index 0000000000..388acf3af5 --- /dev/null +++ b/selfdrive/debug/print_docs_diff.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import argparse +from collections import defaultdict +import difflib +import pickle + +from opendbc.car.docs import get_all_car_docs +from opendbc.car.docs_definitions import Column + +FOOTNOTE_TAG = "{}" +STAR_ICON = '' +VIDEO_ICON = '' + \ + '' +COLUMNS = "|" + "|".join([column.value for column in Column]) + "|" +COLUMN_HEADER = "|---|---|---|{}|".format("|".join([":---:"] * (len(Column) - 3))) +ARROW_SYMBOL = "➡️" + + +def load_base_car_docs(path): + with open(path, "rb") as f: + return pickle.load(f) + + +def match_cars(base_cars, new_cars): + changes = [] + additions = [] + for new in new_cars: + # Addition if no close matches or close match already used + # Change if close match and not already used + matches = difflib.get_close_matches(new.name, [b.name for b in base_cars], cutoff=0.) + if not len(matches) or matches[0] in [c[1].name for c in changes]: + additions.append(new) + else: + changes.append((new, next(car for car in base_cars if car.name == matches[0]))) + + # Removal if base car not in changes + removals = [b for b in base_cars if b.name not in [c[1].name for c in changes]] + return changes, additions, removals + + +def build_column_diff(base_car, new_car): + row_builder = [] + for column in Column: + base_column = base_car.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) + new_column = new_car.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) + + if base_column != new_column: + row_builder.append(f"{base_column} {ARROW_SYMBOL} {new_column}") + else: + row_builder.append(new_column) + + return format_row(row_builder) + + +def format_row(builder): + return "|" + "|".join(builder) + "|" + + +def print_car_docs_diff(path): + base_car_docs = defaultdict(list) + new_car_docs = defaultdict(list) + + for car in load_base_car_docs(path): + base_car_docs[car.car_fingerprint].append(car) + for car in get_all_car_docs(): + new_car_docs[car.car_fingerprint].append(car) + + # Add new platforms to base cars so we can detect additions and removals in one pass + base_car_docs.update({car: [] for car in new_car_docs if car not in base_car_docs}) + + changes = defaultdict(list) + for base_car_model, base_cars in base_car_docs.items(): + # Match car info changes, and get additions and removals + new_cars = new_car_docs[base_car_model] + car_changes, car_additions, car_removals = match_cars(base_cars, new_cars) + + # Removals + for car_docs in car_removals: + changes["removals"].append(format_row([car_docs.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) for column in Column])) + + # Additions + for car_docs in car_additions: + changes["additions"].append(format_row([car_docs.get_column(column, STAR_ICON, VIDEO_ICON, FOOTNOTE_TAG) for column in Column])) + + for new_car, base_car in car_changes: + # Column changes + row_diff = build_column_diff(base_car, new_car) + if ARROW_SYMBOL in row_diff: + changes["column"].append(row_diff) + + # Detail sentence changes + if base_car.detail_sentence != new_car.detail_sentence: + changes["detail"].append(f"- Sentence for {base_car.name} changed!\n" + + " ```diff\n" + + f" - {base_car.detail_sentence}\n" + + f" + {new_car.detail_sentence}\n" + + " ```") + + # Print diff + if any(len(c) for c in changes.values()): + markdown_builder = ["### ⚠️ This PR makes changes to [CARS.md](../blob/master/docs/CARS.md) ⚠️"] + + for title, category in (("## 🔀 Column Changes", "column"), ("## ❌ Removed", "removals"), + ("## ➕ Added", "additions"), ("## 📖 Detail Sentence Changes", "detail")): + if len(changes[category]): + markdown_builder.append(title) + if category not in ("detail",): + markdown_builder.append(COLUMNS) + markdown_builder.append(COLUMN_HEADER) + markdown_builder.extend(changes[category]) + + print("\n".join(markdown_builder)) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--path", required=True) + args = parser.parse_args() + print_car_docs_diff(args.path) diff --git a/selfdrive/debug/print_flags.py b/selfdrive/debug/print_flags.py new file mode 100755 index 0000000000..a50d929f54 --- /dev/null +++ b/selfdrive/debug/print_flags.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +from opendbc.car.values import BRANDS + +for brand in BRANDS: + all_flags = set() + for platform in brand: + if platform.config.flags != 0: + all_flags |= set(platform.config.flags) + + if len(all_flags): + print(brand.__module__.split('.')[-2].upper() + ':') + for flag in sorted(all_flags): + print(f' {flag.name:<24}:', {platform.name for platform in brand.with_flags(flag)}) + print() diff --git a/selfdrive/debug/qlog_size.py b/selfdrive/debug/qlog_size.py new file mode 100755 index 0000000000..6d494b6f75 --- /dev/null +++ b/selfdrive/debug/qlog_size.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +import argparse +import zstandard as zstd +from collections import defaultdict + +import matplotlib.pyplot as plt + +from cereal.services import SERVICE_LIST +from openpilot.common.file_helpers import LOG_COMPRESSION_LEVEL +from openpilot.tools.lib.logreader import LogReader +from tqdm import tqdm + +MIN_SIZE = 0.5 # Percent size of total to show as separate entry + + +def make_pie(msgs, typ): + msgs_by_type = defaultdict(list) + for m in msgs: + msgs_by_type[m.which()].append(m.as_builder().to_bytes()) + + total = len(zstd.compress(b"".join([m.as_builder().to_bytes() for m in msgs]), LOG_COMPRESSION_LEVEL)) + uncompressed_total = len(b"".join([m.as_builder().to_bytes() for m in msgs])) + + length_by_type = {k: len(b"".join(v)) for k, v in msgs_by_type.items()} + # calculate compressed size by calculating diff when removed from the segment + compressed_length_by_type = {} + for k in tqdm(msgs_by_type.keys(), desc="Compressing"): + compressed_length_by_type[k] = total - len(zstd.compress(b"".join([m.as_builder().to_bytes() for m in msgs if m.which() != k]), LOG_COMPRESSION_LEVEL)) + + sizes = sorted(compressed_length_by_type.items(), key=lambda kv: kv[1]) + + print("name - comp. size (uncomp. size)") + for (name, sz) in sizes: + print(f"{name:<22} - {sz / 1024:.2f} kB ({length_by_type[name] / 1024:.2f} kB)") + print() + print(f"{typ} - Real total {total / 1024:.2f} kB") + print(f"{typ} - Breakdown total {sum(compressed_length_by_type.values()) / 1024:.2f} kB") + print(f"{typ} - Uncompressed total {uncompressed_total / 1024 / 1024:.2f} MB") + + sizes_large = [(k, sz) for (k, sz) in sizes if sz >= total * MIN_SIZE / 100] + sizes_large += [('other', sum(sz for (_, sz) in sizes if sz < total * MIN_SIZE / 100))] + + labels, sizes = zip(*sizes_large, strict=True) + + plt.figure() + plt.title(f"{typ}") + plt.pie(sizes, labels=labels, autopct='%1.1f%%') + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='View log size breakdown by message type') + parser.add_argument('route', help='route to use') + parser.add_argument('--as-qlog', action='store_true', help='decimate rlog using latest decimation factors') + args = parser.parse_args() + + msgs = list(LogReader(args.route)) + + if args.as_qlog: + new_msgs = [] + msg_cnts: dict[str, int] = defaultdict(int) + for msg in msgs: + msg_which = msg.which() + if msg.which() in ("initData", "sentinel"): + new_msgs.append(msg) + continue + + if msg_which not in SERVICE_LIST: + continue + + decimation = SERVICE_LIST[msg_which].decimation + if decimation is not None and msg_cnts[msg_which] % decimation == 0: + new_msgs.append(msg) + msg_cnts[msg_which] += 1 + + msgs = new_msgs + + make_pie(msgs, 'qlog') + plt.show() diff --git a/selfdrive/debug/read_dtc_status.py b/selfdrive/debug/read_dtc_status.py new file mode 100755 index 0000000000..f9dad53577 --- /dev/null +++ b/selfdrive/debug/read_dtc_status.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import sys +import argparse +from subprocess import check_output, CalledProcessError +from opendbc.car.carlog import carlog +from opendbc.car.uds import UdsClient, SESSION_TYPE, DTC_REPORT_TYPE, DTC_STATUS_MASK_TYPE, get_dtc_num_as_str, get_dtc_status_names +from opendbc.car.structs import CarParams +from panda import Panda + +parser = argparse.ArgumentParser(description="read DTC status") +parser.add_argument("addr", type=lambda x: int(x,0)) +parser.add_argument("--bus", type=int, default=0) +parser.add_argument('--debug', action='store_true') +args = parser.parse_args() + +if args.debug: + carlog.setLevel('DEBUG') + +try: + check_output(["pidof", "pandad"]) + print("pandad is running, please kill openpilot before running this script! (aborted)") + sys.exit(1) +except CalledProcessError as e: + if e.returncode != 1: # 1 == no process found (pandad not running) + raise e + +panda = Panda() +panda.set_safety_mode(CarParams.SafetyModel.elm327) +uds_client = UdsClient(panda, args.addr, bus=args.bus) +print("extended diagnostic session ...") +uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC) +print("read diagnostic codes ...") +data = uds_client.read_dtc_information(DTC_REPORT_TYPE.DTC_BY_STATUS_MASK, DTC_STATUS_MASK_TYPE.ALL) +print("status availability:", " ".join(get_dtc_status_names(data[0]))) +print("DTC status:") +for i in range(1, len(data), 4): + dtc_num = get_dtc_num_as_str(data[i:i+3]) + dtc_status = " ".join(get_dtc_status_names(data[i+3])) + print(dtc_num, dtc_status) diff --git a/selfdrive/debug/run_process_on_route.py b/selfdrive/debug/run_process_on_route.py new file mode 100755 index 0000000000..d6743fedcb --- /dev/null +++ b/selfdrive/debug/run_process_on_route.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import argparse + +from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, replay_process +from openpilot.selfdrive.test.process_replay.test_processes import EXCLUDED_PROCS +from openpilot.tools.lib.logreader import LogReader, save_log + +ALLOW_PROCS = {c.proc_name for c in CONFIGS} + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Run process on route and create new logs", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("route", help="The route name to use") + parser.add_argument("--fingerprint", help="The fingerprint to use") + parser.add_argument("--whitelist-procs", nargs='*', default=ALLOW_PROCS, help="Whitelist given processes (e.g. controlsd)") + parser.add_argument("--blacklist-procs", nargs='*', default=EXCLUDED_PROCS, help="Blacklist given processes (e.g. controlsd)") + args = parser.parse_args() + + allowed_procs = set(args.whitelist_procs) - set(args.blacklist_procs) + cfgs = [c for c in CONFIGS if c.proc_name in allowed_procs] + + inputs = list(LogReader(args.route)) + outputs = replay_process(cfgs, inputs, fingerprint=args.fingerprint) + + # Remove message generated by the process under test and merge in the new messages + produces = {o.which() for o in outputs} + inputs = [i for i in inputs if i.which() not in produces] + outputs = sorted(inputs + outputs, key=lambda x: x.logMonoTime) + + fn = f"{args.route.replace('/', '_')}_{'_'.join(allowed_procs)}.zst" + print(f"Saving log to {fn}") + save_log(fn, outputs) diff --git a/selfdrive/debug/set_car_params.py b/selfdrive/debug/set_car_params.py new file mode 100755 index 0000000000..aec30b4d74 --- /dev/null +++ b/selfdrive/debug/set_car_params.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import sys + +from cereal import car +from openpilot.common.params import Params +from openpilot.tools.lib.route import Route +from openpilot.tools.lib.logreader import LogReader + +if __name__ == "__main__": + CP = None + if len(sys.argv) > 1: + r = Route(sys.argv[1]) + cps = [m for m in LogReader(r.qlog_paths()[0]) if m.which() == 'carParams'] + CP = cps[0].carParams.as_builder() + else: + CP = car.CarParams.new_message() + CP.openpilotLongitudinalControl = True + CP.alphaLongitudinalAvailable = False + + cp_bytes = CP.to_bytes() + for p in ("CarParams", "CarParamsCache", "CarParamsPersistent"): + Params().put(p, cp_bytes) diff --git a/selfdrive/debug/test_fw_query_on_routes.py b/selfdrive/debug/test_fw_query_on_routes.py new file mode 100755 index 0000000000..1216b7299f --- /dev/null +++ b/selfdrive/debug/test_fw_query_on_routes.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python3 +# type: ignore + +from collections import defaultdict +import argparse +import os +import traceback +from tqdm import tqdm +from opendbc.car.car_helpers import interface_names +from opendbc.car.fingerprints import MIGRATION +from opendbc.car.fw_versions import VERSIONS, match_fw_to_car +from openpilot.tools.lib.logreader import LogReader, ReadMode +from openpilot.tools.lib.route import SegmentRange + + +NO_API = "NO_API" in os.environ +SUPPORTED_BRANDS = VERSIONS.keys() +SUPPORTED_CARS = [brand for brand in SUPPORTED_BRANDS for brand in interface_names[brand]] +UNKNOWN_BRAND = "unknown" + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Run FW fingerprint on Qlog of route or list of routes') + parser.add_argument('route', help='Route or file with list of routes') + parser.add_argument('--car', help='Force comparison fingerprint to known car') + args = parser.parse_args() + + if os.path.exists(args.route): + routes = list(open(args.route)) + else: + routes = [args.route] + + mismatches = defaultdict(list) + + not_fingerprinted = 0 + solved_by_fuzzy = 0 + + good_exact = 0 + wrong_fuzzy = 0 + good_fuzzy = 0 + + dongles = [] + for route in tqdm(routes): + sr = SegmentRange(route) + dongle_id = sr.dongle_id + + if dongle_id in dongles: + continue + + if sr.slice == '' and sr.selector is None: + route += '/0' + + lr = LogReader(route, default_mode=ReadMode.QLOG) + + try: + dongles.append(dongle_id) + + CP = None + for msg in lr: + if msg.which() == "pandaStates": + if msg.pandaStates[0].pandaType in ('unknown', 'whitePanda', 'greyPanda', 'pedal'): + print("wrong panda type") + break + + elif msg.which() == "carParams": + CP = msg.carParams + car_fw = [fw for fw in CP.carFw if not fw.logging] + if len(car_fw) == 0: + print("WARNING: no fw") + + live_fingerprint = CP.carFingerprint + live_fingerprint = MIGRATION.get(live_fingerprint, live_fingerprint) + + if args.car is not None: + live_fingerprint = args.car + + if live_fingerprint not in SUPPORTED_CARS: + print("not in supported cars") + break + + _, exact_matches = match_fw_to_car(car_fw, CP.carVin, allow_exact=True, allow_fuzzy=False) + _, fuzzy_matches = match_fw_to_car(car_fw, CP.carVin, allow_exact=False, allow_fuzzy=True) + + if (len(exact_matches) == 1) and (list(exact_matches)[0] == live_fingerprint): + good_exact += 1 + print(f"Correct! Live: {live_fingerprint} - Fuzzy: {fuzzy_matches}") + + # Check if fuzzy match was correct + if len(fuzzy_matches) == 1: + if list(fuzzy_matches)[0] != live_fingerprint: + wrong_fuzzy += 1 + print("Fuzzy match wrong! Fuzzy:", fuzzy_matches, "Live:", live_fingerprint) + else: + good_fuzzy += 1 + break + + print("Old style:", live_fingerprint, "Vin", CP.carVin) + print("New style (exact):", exact_matches) + print("New style (fuzzy):", fuzzy_matches) + + padding = max([len(fw.brand or UNKNOWN_BRAND) for fw in car_fw] + [0]) + for version in sorted(car_fw, key=lambda fw: fw.brand): + subaddr = None if version.subAddress == 0 else hex(version.subAddress) + print(f" Brand: {version.brand or UNKNOWN_BRAND:{padding}}, bus: {version.bus} - " + + f"(Ecu.{version.ecu}, {hex(version.address)}, {subaddr}): [{version.fwVersion}],") + + print("Mismatches") + found = False + for brand in SUPPORTED_BRANDS: + car_fws = VERSIONS[brand] + if live_fingerprint in car_fws: + found = True + expected = car_fws[live_fingerprint] + for (_, expected_addr, expected_sub_addr), v in expected.items(): + for version in car_fw: + if version.brand != brand and len(version.brand): + continue + sub_addr = None if version.subAddress == 0 else version.subAddress + addr = version.address + + if (addr, sub_addr) == (expected_addr, expected_sub_addr): + if version.fwVersion not in v: + print(f"({hex(addr)}, {'None' if sub_addr is None else hex(sub_addr)}) - {version.fwVersion}") + + # Add to global list of mismatches + mismatch = (addr, sub_addr, version.fwVersion) + if mismatch not in mismatches[live_fingerprint]: + mismatches[live_fingerprint].append(mismatch) + + # No FW versions for this car yet, add them all to mismatch list + if not found: + for version in car_fw: + sub_addr = None if version.subAddress == 0 else version.subAddress + addr = version.address + mismatch = (addr, sub_addr, version.fwVersion) + if mismatch not in mismatches[live_fingerprint]: + mismatches[live_fingerprint].append(mismatch) + + print() + not_fingerprinted += 1 + + if len(fuzzy_matches) == 1: + if list(fuzzy_matches)[0] == live_fingerprint: + solved_by_fuzzy += 1 + else: + wrong_fuzzy += 1 + print("Fuzzy match wrong! Fuzzy:", fuzzy_matches, "Live:", live_fingerprint) + + break + + if CP is None: + print("no CarParams in logs") + except Exception: + traceback.print_exc() + except KeyboardInterrupt: + break + + print() + # Print FW versions that need to be added separated out by car and address + for car, m in sorted(mismatches.items()): + print(car) + addrs = defaultdict(list) + for (addr, sub_addr, version) in m: + addrs[(addr, sub_addr)].append(version) + + for (addr, sub_addr), versions in addrs.items(): + print(f" ({hex(addr)}, {'None' if sub_addr is None else hex(sub_addr)}): [") + for v in versions: + print(f" {v},") + print(" ]") + print() + + print() + print(f"Number of dongle ids checked: {len(dongles)}") + print(f"Fingerprinted: {good_exact}") + print(f"Not fingerprinted: {not_fingerprinted}") + print(f" of which had a fuzzy match: {solved_by_fuzzy}") + + print() + print(f"Correct fuzzy matches: {good_fuzzy}") + print(f"Wrong fuzzy matches: {wrong_fuzzy}") + print() + diff --git a/selfdrive/debug/touch_replay.py b/selfdrive/debug/touch_replay.py new file mode 100755 index 0000000000..6e5ecbbe5b --- /dev/null +++ b/selfdrive/debug/touch_replay.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import argparse + +import numpy as np +import matplotlib.pyplot as plt + +from openpilot.tools.lib.logreader import LogReader + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--width', default=2160, type=int) + parser.add_argument('--height', default=1080, type=int) + parser.add_argument('--route', default='rlog', type=str) + args = parser.parse_args() + + w = args.width + h = args.height + route = args.route + + fingers = [[-1, -1]] * 5 + touch_points = [] + current_slot = 0 + + lr = list(LogReader(route)) + for msg in lr: + if msg.which() == 'touch': + for event in msg.touch: + if event.type == 3 and event.code == 47: + current_slot = event.value + elif event.type == 3 and event.code == 57 and event.value == -1: + fingers[current_slot] = [-1, -1] + elif event.type == 3 and event.code == 53: + fingers[current_slot][1] = event.value + if fingers[current_slot][0] != -1: + touch_points.append(fingers[current_slot].copy()) + elif event.type == 3 and event.code == 54: + fingers[current_slot][0] = w - event.value + if fingers[current_slot][1] != -1: + touch_points.append(fingers[current_slot].copy()) + + if not touch_points: + print(f'No touch events found for {route}') + quit() + + unique_points, counts = np.unique(touch_points, axis=0, return_counts=True) + + plt.figure(figsize=(10, 3)) + plt.scatter(unique_points[:, 0], unique_points[:, 1], c=counts, s=counts * 20, edgecolors='red') + plt.colorbar() + plt.title(f'Touches for {route}') + plt.xlim(0, w) + plt.ylim(0, h) + plt.grid(True) + plt.show() diff --git a/selfdrive/debug/uiview.py b/selfdrive/debug/uiview.py new file mode 100755 index 0000000000..8e75769a85 --- /dev/null +++ b/selfdrive/debug/uiview.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +import time + +from cereal import car, log, messaging +from openpilot.common.params import Params +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.hardware import HARDWARE + +if __name__ == "__main__": + CP = car.CarParams(notCar=True, wheelbase=1, steerRatio=10) + Params().put("CarParams", CP.to_bytes()) + + procs = ['camerad', 'ui', 'modeld', 'calibrationd', 'plannerd', 'dmonitoringmodeld', 'dmonitoringd'] + for p in procs: + managed_processes[p].start() + + pm = messaging.PubMaster(['controlsState', 'deviceState', 'pandaStates', 'carParams']) + + msgs = {s: messaging.new_message(s) for s in ['controlsState', 'deviceState', 'carParams']} + msgs['deviceState'].deviceState.started = True + msgs['deviceState'].deviceState.deviceType = HARDWARE.get_device_type() + msgs['carParams'].carParams.openpilotLongitudinalControl = True + + msgs['pandaStates'] = messaging.new_message('pandaStates', 1) + msgs['pandaStates'].pandaStates[0].ignitionLine = True + msgs['pandaStates'].pandaStates[0].pandaType = log.PandaState.PandaType.uno + + try: + while True: + time.sleep(1 / 100) # continually send, rate doesn't matter + for s in msgs: + pm.send(s, msgs[s]) + except KeyboardInterrupt: + for p in procs: + managed_processes[p].stop() diff --git a/selfdrive/locationd/.gitignore b/selfdrive/locationd/.gitignore new file mode 100644 index 0000000000..1a8c72388a --- /dev/null +++ b/selfdrive/locationd/.gitignore @@ -0,0 +1,2 @@ +params_learner +paramsd diff --git a/selfdrive/locationd/SConscript b/selfdrive/locationd/SConscript new file mode 100644 index 0000000000..e8eeff7e0c --- /dev/null +++ b/selfdrive/locationd/SConscript @@ -0,0 +1,21 @@ +Import('env', 'rednose') + +# build ekf models +rednose_gen_dir = 'models/generated' +rednose_gen_deps = [ + "models/constants.py", +] +pose_ekf = env.RednoseCompileFilter( + target='pose', + filter_gen_script='models/pose_kf.py', + output_dir=rednose_gen_dir, + extra_gen_artifacts=[], + gen_script_deps=rednose_gen_deps, +) +car_ekf = env.RednoseCompileFilter( + target='car', + filter_gen_script='models/car_kf.py', + output_dir=rednose_gen_dir, + extra_gen_artifacts=[], + gen_script_deps=rednose_gen_deps, +) diff --git a/selfdrive/locationd/__init__.py b/selfdrive/locationd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/locationd/calibrationd.py b/selfdrive/locationd/calibrationd.py new file mode 100755 index 0000000000..03c044982e --- /dev/null +++ b/selfdrive/locationd/calibrationd.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python3 +''' +This process finds calibration values. More info on what these calibration values +are can be found here https://github.com/commaai/openpilot/tree/master/common/transformations +While the roll calibration is a real value that can be estimated, here we assume it's zero, +and the image input into the neural network is not corrected for roll. +''' + +import os +import capnp +import numpy as np +from typing import NoReturn + +from cereal import log, car +import cereal.messaging as messaging +from openpilot.system.hardware import HARDWARE +from openpilot.common.constants import CV +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process +from openpilot.common.transformations.orientation import rot_from_euler, euler_from_rot +from openpilot.common.swaglog import cloudlog + +MIN_SPEED_FILTER = 15 * CV.MPH_TO_MS +MAX_VEL_ANGLE_STD = np.radians(0.25) +MAX_YAW_RATE_FILTER = np.radians(2) # per second + +MAX_HEIGHT_STD = np.exp(-3.5) + +# This is at model frequency, blocks needed for efficiency +SMOOTH_CYCLES = 10 +BLOCK_SIZE = 100 +INPUTS_NEEDED = 5 # Minimum blocks needed for valid calibration +INPUTS_WANTED = 50 # We want a little bit more than we need for stability +MAX_ALLOWED_YAW_SPREAD = np.radians(2) +MAX_ALLOWED_PITCH_SPREAD = np.radians(4) +RPY_INIT = np.array([0.0,0.0,0.0]) +WIDE_FROM_DEVICE_EULER_INIT = np.array([0.0, 0.0, 0.0]) +HEIGHT_INIT = np.array([1.22]) + +# These values are needed to accommodate the model frame in the narrow cam +if HARDWARE.get_device_type() == 'mici': + PITCH_LIMITS = np.array([-0.143101, 0.22235988]) +else: + PITCH_LIMITS = np.array([-0.09074112085129739, 0.17]) +YAW_LIMITS = np.array([-0.06912048084718224, 0.06912048084718235]) +DEBUG = os.getenv("DEBUG") is not None + + +def is_calibration_valid(rpy: np.ndarray) -> bool: + return (PITCH_LIMITS[0] < rpy[1] < PITCH_LIMITS[1]) and (YAW_LIMITS[0] < rpy[2] < YAW_LIMITS[1]) # type: ignore + + +def sanity_clip(rpy: np.ndarray) -> np.ndarray: + if np.isnan(rpy).any(): + rpy = RPY_INIT + return np.array([rpy[0], + np.clip(rpy[1], PITCH_LIMITS[0] - .005, PITCH_LIMITS[1] + .005), + np.clip(rpy[2], YAW_LIMITS[0] - .005, YAW_LIMITS[1] + .005)]) + +def moving_avg_with_linear_decay(prev_mean: np.ndarray, new_val: np.ndarray, idx: int, block_size: float) -> np.ndarray: + return (idx*prev_mean + (block_size - idx) * new_val) / block_size + +class Calibrator: + def __init__(self, param_put: bool = False): + self.param_put = param_put + + self.not_car = False + + # Read saved calibration + self.params = Params() + calibration_params = self.params.get("CalibrationParams") + rpy_init = RPY_INIT + wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT + height = HEIGHT_INIT + valid_blocks = 0 + self.cal_status = log.LiveCalibrationData.Status.uncalibrated + + if param_put and calibration_params: + try: + with log.Event.from_bytes(calibration_params) as msg: + rpy_init = np.array(msg.liveCalibration.rpyCalib) + valid_blocks = msg.liveCalibration.validBlocks + wide_from_device_euler = np.array(msg.liveCalibration.wideFromDeviceEuler) + height = np.array(msg.liveCalibration.height) + except Exception: + cloudlog.exception("Error reading cached CalibrationParams") + + self.reset(rpy_init, valid_blocks, wide_from_device_euler, height) + self.update_status() + + def reset(self, rpy_init: np.ndarray = RPY_INIT, + valid_blocks: int = 0, + wide_from_device_euler_init: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT, + height_init: np.ndarray = HEIGHT_INIT, + smooth_from: np.ndarray = None) -> None: + if not np.isfinite(rpy_init).all(): + self.rpy = RPY_INIT.copy() + else: + self.rpy = rpy_init.copy() + + if not np.isfinite(height_init).all() or len(height_init) != 1: + self.height = HEIGHT_INIT.copy() + else: + self.height = height_init.copy() + + if not np.isfinite(wide_from_device_euler_init).all() or len(wide_from_device_euler_init) != 3: + self.wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT.copy() + else: + self.wide_from_device_euler = wide_from_device_euler_init.copy() + + if not np.isfinite(valid_blocks) or valid_blocks < 0: + self.valid_blocks = 0 + else: + self.valid_blocks = valid_blocks + + self.rpys = np.tile(self.rpy, (INPUTS_WANTED, 1)) + self.wide_from_device_eulers = np.tile(self.wide_from_device_euler, (INPUTS_WANTED, 1)) + self.heights = np.tile(self.height, (INPUTS_WANTED, 1)) + + self.idx = 0 + self.block_idx = 0 + self.v_ego = 0.0 + + if smooth_from is None: + self.old_rpy = RPY_INIT + self.old_rpy_weight = 0.0 + else: + self.old_rpy = smooth_from + self.old_rpy_weight = 1.0 + + def get_valid_idxs(self) -> list[int]: + # exclude current block_idx from validity window + before_current = list(range(self.block_idx)) + after_current = list(range(min(self.valid_blocks, self.block_idx + 1), self.valid_blocks)) + return before_current + after_current + + def update_status(self) -> None: + valid_idxs = self.get_valid_idxs() + if valid_idxs: + self.wide_from_device_euler = np.mean(self.wide_from_device_eulers[valid_idxs], axis=0) + self.height = np.mean(self.heights[valid_idxs], axis=0) + rpys = self.rpys[valid_idxs] + self.rpy = np.mean(rpys, axis=0) + max_rpy_calib = np.array(np.max(rpys, axis=0)) + min_rpy_calib = np.array(np.min(rpys, axis=0)) + self.calib_spread = np.abs(max_rpy_calib - min_rpy_calib) + else: + self.calib_spread = np.zeros(3) + + if self.valid_blocks < INPUTS_NEEDED: + if self.cal_status == log.LiveCalibrationData.Status.recalibrating: + self.cal_status = log.LiveCalibrationData.Status.recalibrating + else: + self.cal_status = log.LiveCalibrationData.Status.uncalibrated + elif is_calibration_valid(self.rpy): + self.cal_status = log.LiveCalibrationData.Status.calibrated + else: + self.cal_status = log.LiveCalibrationData.Status.invalid + + # If spread is too high, assume mounting was changed and reset to last block. + # Make the transition smooth. Abrupt transitions are not good for feedback loop through supercombo model. + # TODO: add height spread check with smooth transition too + spread_too_high = self.calib_spread[1] > MAX_ALLOWED_PITCH_SPREAD or self.calib_spread[2] > MAX_ALLOWED_YAW_SPREAD + if spread_too_high and self.cal_status == log.LiveCalibrationData.Status.calibrated: + self.reset(self.rpys[self.block_idx - 1], valid_blocks=1, smooth_from=self.rpy) + self.cal_status = log.LiveCalibrationData.Status.recalibrating + + write_this_cycle = (self.idx == 0) and (self.block_idx % (INPUTS_WANTED//5) == 5) + if self.param_put and write_this_cycle: + self.params.put_nonblocking("CalibrationParams", self.get_msg(True).to_bytes()) + + def handle_v_ego(self, v_ego: float) -> None: + self.v_ego = v_ego + + def get_smooth_rpy(self) -> np.ndarray: + if self.old_rpy_weight > 0: + return self.old_rpy_weight * self.old_rpy + (1.0 - self.old_rpy_weight) * self.rpy + else: + return self.rpy + + def handle_cam_odom(self, trans: list[float], + rot: list[float], + wide_from_device_euler: list[float], + trans_std: list[float], + road_transform_trans: list[float], + road_transform_trans_std: list[float]) -> np.ndarray | None: + self.old_rpy_weight = max(0.0, self.old_rpy_weight - 1/SMOOTH_CYCLES) + + straight_and_fast = ((self.v_ego > MIN_SPEED_FILTER) and (trans[0] > MIN_SPEED_FILTER) and (abs(rot[2]) < MAX_YAW_RATE_FILTER)) + angle_std_threshold = MAX_VEL_ANGLE_STD + height_std_threshold = MAX_HEIGHT_STD + rpy_certain = np.arctan2(trans_std[1], trans[0]) < angle_std_threshold + if len(road_transform_trans_std) == 3: + height_certain = road_transform_trans_std[2] < height_std_threshold + else: + height_certain = True + + certain_if_calib = (rpy_certain and height_certain) or (self.valid_blocks < INPUTS_NEEDED) + if not (straight_and_fast and certain_if_calib): + return None + + observed_rpy = np.array([0, + -np.arctan2(trans[2], trans[0]), + np.arctan2(trans[1], trans[0])]) + new_rpy = euler_from_rot(rot_from_euler(self.get_smooth_rpy()).dot(rot_from_euler(observed_rpy))) + new_rpy = sanity_clip(new_rpy) + + if len(wide_from_device_euler) == 3: + new_wide_from_device_euler = np.array(wide_from_device_euler) + else: + new_wide_from_device_euler = WIDE_FROM_DEVICE_EULER_INIT + + if (len(road_transform_trans) == 3): + new_height = np.array([road_transform_trans[2]]) + else: + new_height = HEIGHT_INIT + + self.rpys[self.block_idx] = moving_avg_with_linear_decay(self.rpys[self.block_idx], new_rpy, self.idx, float(BLOCK_SIZE)) + self.wide_from_device_eulers[self.block_idx] = moving_avg_with_linear_decay(self.wide_from_device_eulers[self.block_idx], + new_wide_from_device_euler, self.idx, float(BLOCK_SIZE)) + self.heights[self.block_idx] = moving_avg_with_linear_decay(self.heights[self.block_idx], new_height, self.idx, float(BLOCK_SIZE)) + + self.idx = (self.idx + 1) % BLOCK_SIZE + if self.idx == 0: + self.block_idx += 1 + self.valid_blocks = max(self.block_idx, self.valid_blocks) + self.block_idx = self.block_idx % INPUTS_WANTED + + self.update_status() + + return new_rpy + + def get_msg(self, valid: bool) -> capnp.lib.capnp._DynamicStructBuilder: + smooth_rpy = self.get_smooth_rpy() + + msg = messaging.new_message('liveCalibration') + msg.valid = valid + + liveCalibration = msg.liveCalibration + liveCalibration.validBlocks = self.valid_blocks + liveCalibration.calStatus = self.cal_status + liveCalibration.calPerc = min(100 * (self.valid_blocks * BLOCK_SIZE + self.idx) // (INPUTS_NEEDED * BLOCK_SIZE), 100) + liveCalibration.rpyCalib = smooth_rpy.tolist() + liveCalibration.rpyCalibSpread = self.calib_spread.tolist() + liveCalibration.wideFromDeviceEuler = self.wide_from_device_euler.tolist() + liveCalibration.height = self.height.tolist() + + if self.not_car: + liveCalibration.validBlocks = INPUTS_NEEDED + liveCalibration.calStatus = log.LiveCalibrationData.Status.calibrated + liveCalibration.calPerc = 100. + liveCalibration.rpyCalib = [0, 0, 0] + liveCalibration.rpyCalibSpread = self.calib_spread.tolist() + + return msg + + def send_data(self, pm: messaging.PubMaster, valid: bool) -> None: + pm.send('liveCalibration', self.get_msg(valid)) + + +def main() -> NoReturn: + config_realtime_process([0, 1, 2, 3], 5) + + pm = messaging.PubMaster(['liveCalibration']) + sm = messaging.SubMaster(['cameraOdometry', 'carState'], poll='cameraOdometry') + + params_reader = Params() + CP = messaging.log_from_bytes(params_reader.get("CarParams", block=True), car.CarParams) + + calibrator = Calibrator(param_put=True) + calibrator.not_car = CP.notCar + + while 1: + timeout = 0 if sm.frame == -1 else 100 + sm.update(timeout) + + if sm.updated['cameraOdometry']: + calibrator.handle_v_ego(sm['carState'].vEgo) + new_rpy = calibrator.handle_cam_odom(sm['cameraOdometry'].trans, + sm['cameraOdometry'].rot, + sm['cameraOdometry'].wideFromDeviceEuler, + sm['cameraOdometry'].transStd, + sm['cameraOdometry'].roadTransformTrans, + sm['cameraOdometry'].roadTransformTransStd) + + if DEBUG and new_rpy is not None: + print('got new rpy', new_rpy) + + # 4Hz driven by cameraOdometry + if sm.frame % 5 == 0: + calibrator.send_data(pm, sm.all_checks()) + + +if __name__ == "__main__": + main() diff --git a/selfdrive/locationd/helpers.py b/selfdrive/locationd/helpers.py new file mode 100644 index 0000000000..bf4588a40c --- /dev/null +++ b/selfdrive/locationd/helpers.py @@ -0,0 +1,183 @@ +import numpy as np +from typing import Any +from functools import cache + +from cereal import log +from openpilot.common.transformations.orientation import rot_from_euler, euler_from_rot + + +@cache +def fft_next_good_size(n: int) -> int: + """ + smallest composite of 2, 3, 5, 7, 11 that is >= n + inspired by pocketfft + """ + if n <= 6: + return n + best, f2 = 2 * n, 1 + while f2 < best: + f23 = f2 + while f23 < best: + f235 = f23 + while f235 < best: + f2357 = f235 + while f2357 < best: + f235711 = f2357 + while f235711 < best: + best = f235711 if f235711 >= n else best + f235711 *= 11 + f2357 *= 7 + f235 *= 5 + f23 *= 3 + f2 *= 2 + return best + + +def parabolic_peak_interp(R, max_index): + if max_index == 0 or max_index == len(R) - 1: + return max_index + + y_m1, y_0, y_p1 = R[max_index - 1], R[max_index], R[max_index + 1] + offset = 0.5 * (y_p1 - y_m1) / (2 * y_0 - y_p1 - y_m1) + + return max_index + offset + + +def rotate_cov(rot_matrix, cov_in): + return rot_matrix @ cov_in @ rot_matrix.T + + +def rotate_std(rot_matrix, std_in): + return np.sqrt(np.diag(rotate_cov(rot_matrix, np.diag(std_in**2)))) + + +class NPQueue: + def __init__(self, maxlen: int, rowsize: int) -> None: + self.maxlen = maxlen + self.arr = np.empty((0, rowsize)) + + def __len__(self) -> int: + return len(self.arr) + + def append(self, pt: list[float]) -> None: + if len(self.arr) < self.maxlen: + self.arr = np.append(self.arr, [pt], axis=0) + else: + self.arr[:-1] = self.arr[1:] + self.arr[-1] = pt + + +class PointBuckets: + def __init__(self, x_bounds: list[tuple[float, float]], min_points: list[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None: + self.x_bounds = x_bounds + self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds} + self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True)) + self.min_points_total = min_points_total + + def __len__(self) -> int: + return sum([len(v) for v in self.buckets.values()]) + + def is_valid(self) -> bool: + individual_buckets_valid = all(len(v) >= min_pts for v, min_pts in zip(self.buckets.values(), self.buckets_min_points.values(), strict=True)) + total_points_valid = self.__len__() >= self.min_points_total + return individual_buckets_valid and total_points_valid + + def get_valid_percent(self) -> int: + total_points_perc = min(self.__len__() / self.min_points_total * 100, 100) + individual_buckets_perc = min(min(len(v) / min_pts * 100 for v, min_pts in + zip(self.buckets.values(), self.buckets_min_points.values(), strict=True)), 100) + return int((total_points_perc + individual_buckets_perc) / 2) + + def is_calculable(self) -> bool: + return all(len(v) > 0 for v in self.buckets.values()) + + def add_point(self, x: float, y: float) -> None: + raise NotImplementedError + + def get_points(self, num_points: int = None) -> Any: + points = np.vstack([x.arr for x in self.buckets.values()]) + if num_points is None: + return points + return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)] + + def load_points(self, points: list[list[float]]) -> None: + for point in points: + self.add_point(*point) + + +class ParameterEstimator: + """ Base class for parameter estimators """ + def reset(self) -> None: + raise NotImplementedError + + def handle_log(self, t: int, which: str, msg: log.Event) -> None: + raise NotImplementedError + + def get_msg(self, valid: bool, with_points: bool) -> log.Event: + raise NotImplementedError + + +class Measurement: + x, y, z = (property(lambda self: self.xyz[0]), property(lambda self: self.xyz[1]), property(lambda self: self.xyz[2])) + x_std, y_std, z_std = (property(lambda self: self.xyz_std[0]), property(lambda self: self.xyz_std[1]), property(lambda self: self.xyz_std[2])) + roll, pitch, yaw = x, y, z + roll_std, pitch_std, yaw_std = x_std, y_std, z_std + + def __init__(self, xyz: np.ndarray, xyz_std: np.ndarray): + self.xyz: np.ndarray = xyz + self.xyz_std: np.ndarray = xyz_std + + @classmethod + def from_measurement_xyz(cls, measurement: log.LivePose.XYZMeasurement) -> 'Measurement': + return cls( + xyz=np.array([measurement.x, measurement.y, measurement.z]), + xyz_std=np.array([measurement.xStd, measurement.yStd, measurement.zStd]) + ) + + +class Pose: + def __init__(self, orientation: Measurement, velocity: Measurement, acceleration: Measurement, angular_velocity: Measurement): + self.orientation = orientation + self.velocity = velocity + self.acceleration = acceleration + self.angular_velocity = angular_velocity + + @classmethod + def from_live_pose(cls, live_pose: log.LivePose) -> 'Pose': + return Pose( + orientation=Measurement.from_measurement_xyz(live_pose.orientationNED), + velocity=Measurement.from_measurement_xyz(live_pose.velocityDevice), + acceleration=Measurement.from_measurement_xyz(live_pose.accelerationDevice), + angular_velocity=Measurement.from_measurement_xyz(live_pose.angularVelocityDevice) + ) + + +class PoseCalibrator: + def __init__(self): + self.calib_valid = False + self.calib_from_device = np.eye(3) + + def _transform_calib_from_device(self, meas: Measurement): + new_xyz = self.calib_from_device @ meas.xyz + new_xyz_std = rotate_std(self.calib_from_device, meas.xyz_std) + return Measurement(new_xyz, new_xyz_std) + + def _ned_from_calib(self, orientation: Measurement): + ned_from_device = rot_from_euler(orientation.xyz) + ned_from_calib = ned_from_device @ self.calib_from_device.T + ned_from_calib_euler_meas = Measurement(euler_from_rot(ned_from_calib), np.full(3, np.nan)) + return ned_from_calib_euler_meas + + def build_calibrated_pose(self, pose: Pose) -> Pose: + ned_from_calib_euler = self._ned_from_calib(pose.orientation) + angular_velocity_calib = self._transform_calib_from_device(pose.angular_velocity) + acceleration_calib = self._transform_calib_from_device(pose.acceleration) + velocity_calib = self._transform_calib_from_device(pose.angular_velocity) + + return Pose(ned_from_calib_euler, velocity_calib, acceleration_calib, angular_velocity_calib) + + def feed_live_calib(self, live_calib: log.LiveCalibrationData): + calib_rpy = np.array(live_calib.rpyCalib) + device_from_calib = rot_from_euler(calib_rpy) + self.calib_from_device = device_from_calib.T + self.calib_valid = live_calib.calStatus == log.LiveCalibrationData.Status.calibrated diff --git a/selfdrive/locationd/lagd.py b/selfdrive/locationd/lagd.py new file mode 100755 index 0000000000..d7834f7f1f --- /dev/null +++ b/selfdrive/locationd/lagd.py @@ -0,0 +1,394 @@ +#!/usr/bin/env python3 +import os +import numpy as np +import capnp +from collections import deque +from functools import partial + +import cereal.messaging as messaging +from cereal import car, log +from cereal.services import SERVICE_LIST +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose, fft_next_good_size, parabolic_peak_interp + +BLOCK_SIZE = 100 +BLOCK_NUM = 50 +BLOCK_NUM_NEEDED = 5 +MOVING_WINDOW_SEC = 60.0 +MIN_OKAY_WINDOW_SEC = 25.0 +MIN_RECOVERY_BUFFER_SEC = 2.0 +MIN_VEGO = 15.0 +MIN_ABS_YAW_RATE = 0.0 +MAX_YAW_RATE_SANITY_CHECK = 1.0 +MIN_NCC = 0.95 +MAX_LAG = 1.0 +MAX_LAG_STD = 0.1 +MAX_LAT_ACCEL = 2.0 +MAX_LAT_ACCEL_DIFF = 0.6 +MIN_CONFIDENCE = 0.7 +CORR_BORDER_OFFSET = 5 +LAG_CANDIDATE_CORR_THRESHOLD = 0.9 + + +def masked_normalized_cross_correlation(expected_sig: np.ndarray, actual_sig: np.ndarray, mask: np.ndarray, n: int): + """ + References: + D. Padfield. "Masked FFT registration". In Proc. Computer Vision and + Pattern Recognition, pp. 2918-2925 (2010). + :DOI:`10.1109/CVPR.2010.5540032` + """ + + eps = np.finfo(np.float64).eps + expected_sig = np.asarray(expected_sig, dtype=np.float64) + actual_sig = np.asarray(actual_sig, dtype=np.float64) + + expected_sig[~mask] = 0.0 + actual_sig[~mask] = 0.0 + + rotated_expected_sig = expected_sig[::-1] + rotated_mask = mask[::-1] + + fft = partial(np.fft.fft, n=n) + + actual_sig_fft = fft(actual_sig) + rotated_expected_sig_fft = fft(rotated_expected_sig) + actual_mask_fft = fft(mask.astype(np.float64)) + rotated_mask_fft = fft(rotated_mask.astype(np.float64)) + + number_overlap_masked_samples = np.fft.ifft(rotated_mask_fft * actual_mask_fft).real + number_overlap_masked_samples[:] = np.round(number_overlap_masked_samples) + number_overlap_masked_samples[:] = np.fmax(number_overlap_masked_samples, eps) + masked_correlated_actual_fft = np.fft.ifft(rotated_mask_fft * actual_sig_fft).real + masked_correlated_expected_fft = np.fft.ifft(actual_mask_fft * rotated_expected_sig_fft).real + + numerator = np.fft.ifft(rotated_expected_sig_fft * actual_sig_fft).real + numerator -= masked_correlated_actual_fft * masked_correlated_expected_fft / number_overlap_masked_samples + + actual_squared_fft = fft(actual_sig ** 2) + actual_sig_denom = np.fft.ifft(rotated_mask_fft * actual_squared_fft).real + actual_sig_denom -= masked_correlated_actual_fft ** 2 / number_overlap_masked_samples + actual_sig_denom[:] = np.fmax(actual_sig_denom, 0.0) + + rotated_expected_squared_fft = fft(rotated_expected_sig ** 2) + expected_sig_denom = np.fft.ifft(actual_mask_fft * rotated_expected_squared_fft).real + expected_sig_denom -= masked_correlated_expected_fft ** 2 / number_overlap_masked_samples + expected_sig_denom[:] = np.fmax(expected_sig_denom, 0.0) + + denom = np.sqrt(actual_sig_denom * expected_sig_denom) + + # zero-out samples with very small denominators + tol = 1e3 * eps * np.max(np.abs(denom), keepdims=True) + nonzero_indices = denom > tol + + ncc = np.zeros_like(denom, dtype=np.float64) + ncc[nonzero_indices] = numerator[nonzero_indices] / denom[nonzero_indices] + np.clip(ncc, -1, 1, out=ncc) + + return ncc + + +class Points: + def __init__(self, num_points: int): + self.times = deque[float]([0.0] * num_points, maxlen=num_points) + self.okay = deque[bool]([False] * num_points, maxlen=num_points) + self.desired = deque[float]([0.0] * num_points, maxlen=num_points) + self.actual = deque[float]([0.0] * num_points, maxlen=num_points) + + @property + def num_points(self): + return len(self.desired) + + @property + def num_okay(self): + return np.count_nonzero(self.okay) + + def update(self, t: float, desired: float, actual: float, okay: bool): + self.times.append(t) + self.okay.append(okay) + self.desired.append(desired) + self.actual.append(actual) + + def get(self) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + return np.array(self.times), np.array(self.desired), np.array(self.actual), np.array(self.okay) + + +class BlockAverage: + def __init__(self, num_blocks: int, block_size: int, valid_blocks: int, initial_value: float): + self.num_blocks = num_blocks + self.block_size = block_size + self.block_idx = valid_blocks % num_blocks + self.idx = 0 + + self.values = np.tile(initial_value, (num_blocks, 1)) + self.valid_blocks = valid_blocks + + def update(self, value: float): + self.values[self.block_idx] = (self.idx * self.values[self.block_idx] + value) / (self.idx + 1) + self.idx = (self.idx + 1) % self.block_size + if self.idx == 0: + self.block_idx = (self.block_idx + 1) % self.num_blocks + self.valid_blocks = min(self.valid_blocks + 1, self.num_blocks) + + def get(self) -> tuple[float, float, float, float]: + valid_block_idx = [i for i in range(self.valid_blocks) if i != self.block_idx] + valid_and_current_idx = valid_block_idx + ([self.block_idx] if self.idx > 0 else []) + + if len(valid_block_idx) > 0: + valid_mean = float(np.mean(self.values[valid_block_idx], axis=0).item()) + valid_std = float(np.std(self.values[valid_block_idx], axis=0).item()) + else: + valid_mean, valid_std = float('nan'), float('nan') + + if len(valid_and_current_idx) > 0: + current_mean = float(np.mean(self.values[valid_and_current_idx], axis=0).item()) + current_std = float(np.std(self.values[valid_and_current_idx], axis=0).item()) + else: + current_mean, current_std = float('nan'), float('nan') + + return valid_mean, valid_std, current_mean, current_std + + +class LateralLagEstimator: + inputs = {"carControl", "carState", "controlsState", "liveCalibration", "livePose"} + + def __init__(self, CP: car.CarParams, dt: float, + block_count: int = BLOCK_NUM, min_valid_block_count: int = BLOCK_NUM_NEEDED, block_size: int = BLOCK_SIZE, + window_sec: float = MOVING_WINDOW_SEC, okay_window_sec: float = MIN_OKAY_WINDOW_SEC, min_recovery_buffer_sec: float = MIN_RECOVERY_BUFFER_SEC, + min_vego: float = MIN_VEGO, min_yr: float = MIN_ABS_YAW_RATE, min_ncc: float = MIN_NCC, + max_lat_accel: float = MAX_LAT_ACCEL, max_lat_accel_diff: float = MAX_LAT_ACCEL_DIFF, min_confidence: float = MIN_CONFIDENCE): + self.dt = dt + self.window_sec = window_sec + self.okay_window_sec = okay_window_sec + self.min_recovery_buffer_sec = min_recovery_buffer_sec + self.initial_lag = CP.steerActuatorDelay + 0.2 + self.block_size = block_size + self.block_count = block_count + self.min_valid_block_count = min_valid_block_count + self.min_vego = min_vego + self.min_yr = min_yr + self.min_ncc = min_ncc + self.min_confidence = min_confidence + self.max_lat_accel = max_lat_accel + self.max_lat_accel_diff = max_lat_accel_diff + + self.t = 0.0 + self.lat_active = False + self.steering_pressed = False + self.steering_saturated = False + self.desired_curvature = 0.0 + self.v_ego = 0.0 + self.yaw_rate = 0.0 + self.yaw_rate_std = 0.0 + self.pose_valid = False + + self.last_lat_inactive_t = 0.0 + self.last_steering_pressed_t = 0.0 + self.last_steering_saturated_t = 0.0 + self.last_pose_invalid_t = 0.0 + self.last_estimate_t = 0.0 + + self.calibrator = PoseCalibrator() + + self.reset(self.initial_lag, 0) + + def reset(self, initial_lag: float, valid_blocks: int): + window_len = int(self.window_sec / self.dt) + self.points = Points(window_len) + self.block_avg = BlockAverage(self.block_count, self.block_size, valid_blocks, initial_lag) + + def get_msg(self, valid: bool, debug: bool = False) -> capnp._DynamicStructBuilder: + msg = messaging.new_message('liveDelay') + + msg.valid = valid + + liveDelay = msg.liveDelay + + valid_mean_lag, valid_std, current_mean_lag, current_std = self.block_avg.get() + if self.block_avg.valid_blocks >= self.min_valid_block_count and not np.isnan(valid_mean_lag) and not np.isnan(valid_std): + if valid_std > MAX_LAG_STD: + liveDelay.status = log.LiveDelayData.Status.invalid + else: + liveDelay.status = log.LiveDelayData.Status.estimated + else: + liveDelay.status = log.LiveDelayData.Status.unestimated + + if liveDelay.status == log.LiveDelayData.Status.estimated: + liveDelay.lateralDelay = valid_mean_lag + else: + liveDelay.lateralDelay = self.initial_lag + + if not np.isnan(current_mean_lag) and not np.isnan(current_std): + liveDelay.lateralDelayEstimate = current_mean_lag + liveDelay.lateralDelayEstimateStd = current_std + else: + liveDelay.lateralDelayEstimate = self.initial_lag + liveDelay.lateralDelayEstimateStd = 0.0 + + liveDelay.validBlocks = self.block_avg.valid_blocks + liveDelay.calPerc = min(100 * (self.block_avg.valid_blocks * self.block_size + self.block_avg.idx) // + (self.min_valid_block_count * self.block_size), 100) + if debug: + liveDelay.points = self.block_avg.values.flatten().tolist() + + return msg + + def handle_log(self, t: float, which: str, msg: capnp._DynamicStructReader): + if which == "carControl": + self.lat_active = msg.latActive + elif which == "carState": + self.steering_pressed = msg.steeringPressed + self.v_ego = msg.vEgo + elif which == "controlsState": + self.steering_saturated = getattr(msg.lateralControlState, msg.lateralControlState.which()).saturated + self.desired_curvature = msg.desiredCurvature + elif which == "liveCalibration": + self.calibrator.feed_live_calib(msg) + elif which == "livePose": + device_pose = Pose.from_live_pose(msg) + calibrated_pose = self.calibrator.build_calibrated_pose(device_pose) + self.yaw_rate = calibrated_pose.angular_velocity.yaw + self.yaw_rate_std = calibrated_pose.angular_velocity.yaw_std + self.pose_valid = msg.angularVelocityDevice.valid and msg.posenetOK and msg.inputsOK + self.t = t + + def points_enough(self): + return self.points.num_points >= int(self.okay_window_sec / self.dt) + + def points_valid(self): + return self.points.num_okay >= int(self.okay_window_sec / self.dt) + + def update_points(self): + la_desired = self.desired_curvature * self.v_ego * self.v_ego + la_actual_pose = self.yaw_rate * self.v_ego + + fast = self.v_ego > self.min_vego + turning = np.abs(self.yaw_rate) >= self.min_yr + sensors_valid = self.pose_valid and np.abs(self.yaw_rate) < MAX_YAW_RATE_SANITY_CHECK and self.yaw_rate_std < MAX_YAW_RATE_SANITY_CHECK + la_valid = np.abs(la_actual_pose) <= self.max_lat_accel and np.abs(la_desired - la_actual_pose) <= self.max_lat_accel_diff + calib_valid = self.calibrator.calib_valid + + if not self.lat_active: + self.last_lat_inactive_t = self.t + if self.steering_pressed: + self.last_steering_pressed_t = self.t + if self.steering_saturated: + self.last_steering_saturated_t = self.t + if not sensors_valid or not la_valid: + self.last_pose_invalid_t = self.t + + has_recovered = all( # wait for recovery after !lat_active, steering_pressed, steering_saturated, !sensors/la_valid + self.t - last_t >= self.min_recovery_buffer_sec + for last_t in [self.last_lat_inactive_t, self.last_steering_pressed_t, self.last_steering_saturated_t, self.last_pose_invalid_t] + ) + okay = self.lat_active and not self.steering_pressed and not self.steering_saturated and \ + fast and turning and has_recovered and calib_valid and sensors_valid and la_valid + + self.points.update(self.t, la_desired, la_actual_pose, okay) + + def update_estimate(self): + if not self.points_enough(): + return + + times, desired, actual, okay = self.points.get() + # check if there are any new valid data points since the last update + is_valid = self.points_valid() + if self.last_estimate_t != 0 and times[0] <= self.last_estimate_t: + new_values_start_idx = next(-i for i, t in enumerate(reversed(times)) if t <= self.last_estimate_t) + is_valid = is_valid and not (new_values_start_idx == 0 or not np.any(okay[new_values_start_idx:])) + + delay, corr, confidence = self.actuator_delay(desired, actual, okay, self.dt, MAX_LAG) + if corr < self.min_ncc or confidence < self.min_confidence or not is_valid: + return + + self.block_avg.update(delay) + self.last_estimate_t = self.t + + @staticmethod + def actuator_delay(expected_sig: np.ndarray, actual_sig: np.ndarray, mask: np.ndarray, dt: float, max_lag: float) -> tuple[float, float, float]: + assert len(expected_sig) == len(actual_sig) + max_lag_samples = int(max_lag / dt) + padded_size = fft_next_good_size(len(expected_sig) + max_lag_samples) + + ncc = masked_normalized_cross_correlation(expected_sig, actual_sig, mask, padded_size) + + # only consider lags from 0 to max_lag + roi = np.s_[len(expected_sig) - 1: len(expected_sig) - 1 + max_lag_samples] + extended_roi = np.s_[roi.start - CORR_BORDER_OFFSET: roi.stop + CORR_BORDER_OFFSET] + roi_ncc = ncc[roi] + extended_roi_ncc = ncc[extended_roi] + + max_corr_index = np.argmax(roi_ncc) + corr = roi_ncc[max_corr_index] + lag = parabolic_peak_interp(roi_ncc, max_corr_index) * dt + + # to estimate lag confidence, gather all high-correlation candidates and see how spread they are + # if e.g. 0.8 and 0.4 are both viable, this is an ambiguous case + ncc_thresh = (roi_ncc.max() - roi_ncc.min()) * LAG_CANDIDATE_CORR_THRESHOLD + roi_ncc.min() + good_lag_candidate_mask = extended_roi_ncc >= ncc_thresh + good_lag_candidate_edges = np.diff(good_lag_candidate_mask.astype(int), prepend=0, append=0) + starts, ends = np.where(good_lag_candidate_edges == 1)[0], np.where(good_lag_candidate_edges == -1)[0] - 1 + run_idx = np.searchsorted(starts, max_corr_index + CORR_BORDER_OFFSET, side='right') - 1 + width = ends[run_idx] - starts[run_idx] + 1 + confidence = np.clip(1 - width * dt, 0, 1) + + return lag, corr, confidence + + +def retrieve_initial_lag(params: Params, CP: car.CarParams): + last_lag_data = params.get("LiveDelay") + last_carparams_data = params.get("CarParamsPrevRoute") + + if last_lag_data is not None: + try: + with log.Event.from_bytes(last_lag_data) as last_lag_msg, car.CarParams.from_bytes(last_carparams_data) as last_CP: + ld = last_lag_msg.liveDelay + if last_CP.carFingerprint != CP.carFingerprint: + raise Exception("Car model mismatch") + + lag, valid_blocks, status = ld.lateralDelayEstimate, ld.validBlocks, ld.status + assert valid_blocks <= BLOCK_NUM, "Invalid number of valid blocks" + assert status != log.LiveDelayData.Status.invalid, "Lag estimate is invalid" + return lag, valid_blocks + except Exception as e: + cloudlog.error(f"Failed to retrieve initial lag: {e}") + params.remove("LiveDelay") + + return None + + +def main(): + config_realtime_process([0, 1, 2, 3], 5) + + DEBUG = bool(int(os.getenv("DEBUG", "0"))) + + pm = messaging.PubMaster(['liveDelay']) + sm = messaging.SubMaster(['livePose', 'liveCalibration', 'carState', 'controlsState', 'carControl'], poll='livePose') + + params = Params() + CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams) + + lag_learner = LateralLagEstimator(CP, 1. / SERVICE_LIST['livePose'].frequency) + if (initial_lag_params := retrieve_initial_lag(params, CP)) is not None: + lag, valid_blocks = initial_lag_params + lag_learner.reset(lag, valid_blocks) + + while True: + sm.update() + if sm.all_checks(): + for which in sorted(sm.updated.keys(), key=lambda x: sm.logMonoTime[x]): + if sm.updated[which]: + t = sm.logMonoTime[which] * 1e-9 + lag_learner.handle_log(t, which, sm[which]) + lag_learner.update_points() + + # 4Hz driven by livePose + if sm.frame % 5 == 0: + lag_learner.update_estimate() + lag_msg = lag_learner.get_msg(sm.all_checks(), DEBUG) + lag_msg_dat = lag_msg.to_bytes() + pm.send('liveDelay', lag_msg_dat) + + if sm.frame % 1200 == 0: # cache every 60 seconds + params.put_nonblocking("LiveDelay", lag_msg_dat) diff --git a/selfdrive/locationd/locationd.py b/selfdrive/locationd/locationd.py new file mode 100755 index 0000000000..f6a0935ed9 --- /dev/null +++ b/selfdrive/locationd/locationd.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python3 +import os +import time +import capnp +import numpy as np +from enum import Enum +from collections import defaultdict + +from cereal import log, messaging +from cereal.services import SERVICE_LIST +from openpilot.common.transformations.orientation import rot_from_euler +from openpilot.common.realtime import config_realtime_process +from openpilot.common.params import Params +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.locationd.helpers import rotate_std +from openpilot.selfdrive.locationd.models.pose_kf import PoseKalman, States +from openpilot.selfdrive.locationd.models.constants import ObservationKind, GENERATED_DIR + +ACCEL_SANITY_CHECK = 100.0 # m/s^2 +ROTATION_SANITY_CHECK = 10.0 # rad/s +TRANS_SANITY_CHECK = 200.0 # m/s +CALIB_RPY_SANITY_CHECK = 0.5 # rad (+- 30 deg) +MIN_STD_SANITY_CHECK = 1e-5 # m or rad +MAX_FILTER_REWIND_TIME = 0.8 # s +MAX_SENSOR_TIME_DIFF = 0.1 # s +YAWRATE_CROSS_ERR_CHECK_FACTOR = 30 +INPUT_INVALID_LIMIT = 2.0 # 1 (camodo) / 9 (sensor) bad input[s] ignored +INPUT_INVALID_RECOVERY = 10.0 # ~10 secs to resume after exceeding allowed bad inputs by one +POSENET_STD_INITIAL_VALUE = 10.0 +POSENET_STD_HIST_HALF = 20 + + +def calculate_invalid_input_decay(invalid_limit, recovery_time, frequency): + return (1 - 1 / (2 * invalid_limit)) ** (1 / (recovery_time * frequency)) + + +def init_xyz_measurement(measurement: capnp._DynamicStructBuilder, values: np.ndarray, stds: np.ndarray, valid: bool): + assert len(values) == len(stds) == 3 + measurement.x, measurement.y, measurement.z = map(float, values) + measurement.xStd, measurement.yStd, measurement.zStd = map(float, stds) + measurement.valid = valid + + +class HandleLogResult(Enum): + SUCCESS = 0 + TIMING_INVALID = 1 + INPUT_INVALID = 2 + SENSOR_SOURCE_INVALID = 3 + + +class LocationEstimator: + def __init__(self, debug: bool): + self.kf = PoseKalman(GENERATED_DIR, MAX_FILTER_REWIND_TIME) + + self.debug = debug + + self.posenet_stds = np.array([POSENET_STD_INITIAL_VALUE] * (POSENET_STD_HIST_HALF * 2)) + self.car_speed = 0.0 + self.camodo_yawrate_distribution = np.array([0.0, 10.0]) # mean, std + self.device_from_calib = np.eye(3) + + obs_kinds = [ObservationKind.PHONE_ACCEL, ObservationKind.PHONE_GYRO, ObservationKind.CAMERA_ODO_ROTATION, ObservationKind.CAMERA_ODO_TRANSLATION] + self.observations = {kind: np.zeros(3, dtype=np.float32) for kind in obs_kinds} + self.observation_errors = {kind: np.zeros(3, dtype=np.float32) for kind in obs_kinds} + + def reset(self, t: float, x_initial: np.ndarray = PoseKalman.initial_x, P_initial: np.ndarray = PoseKalman.initial_P): + self.kf.init_state(x_initial, covs=P_initial, filter_time=t) + + def _validate_sensor_source(self, source: log.SensorEventData.SensorSource): + # some segments have two IMUs, ignore the second one + return source != log.SensorEventData.SensorSource.bmx055 + + def _validate_sensor_time(self, sensor_time: float, t: float): + # ignore empty readings + if sensor_time == 0: + return False + + # sensor time and log time should be close + sensor_time_invalid = abs(sensor_time - t) > MAX_SENSOR_TIME_DIFF + if sensor_time_invalid: + cloudlog.warning("Sensor reading ignored, sensor timestamp more than 100ms off from log time") + return not sensor_time_invalid + + def _validate_timestamp(self, t: float): + kf_t = self.kf.t + invalid = not np.isnan(kf_t) and (kf_t - t) > MAX_FILTER_REWIND_TIME + if invalid: + cloudlog.warning("Observation timestamp is older than the max rewind threshold of the filter") + return not invalid + + def _finite_check(self, t: float, new_x: np.ndarray, new_P: np.ndarray): + all_finite = np.isfinite(new_x).all() and np.isfinite(new_P).all() + if not all_finite: + cloudlog.error("Non-finite values detected, kalman reset") + self.reset(t) + + def handle_log(self, t: float, which: str, msg: capnp._DynamicStructReader) -> HandleLogResult: + new_x, new_P = None, None + if which == "accelerometer" and msg.which() == "acceleration": + sensor_time = msg.timestamp * 1e-9 + + if not self._validate_sensor_time(sensor_time, t) or not self._validate_timestamp(sensor_time): + return HandleLogResult.TIMING_INVALID + + if not self._validate_sensor_source(msg.source): + return HandleLogResult.SENSOR_SOURCE_INVALID + + v = msg.acceleration.v + meas = np.array([-v[2], -v[1], -v[0]]) + if np.linalg.norm(meas) >= ACCEL_SANITY_CHECK: + return HandleLogResult.INPUT_INVALID + + acc_res = self.kf.predict_and_observe(sensor_time, ObservationKind.PHONE_ACCEL, meas) + if acc_res is not None: + _, new_x, _, new_P, _, _, (acc_err,), _, _ = acc_res + self.observation_errors[ObservationKind.PHONE_ACCEL] = np.array(acc_err) + self.observations[ObservationKind.PHONE_ACCEL] = meas + + elif which == "gyroscope" and msg.which() == "gyroUncalibrated": + sensor_time = msg.timestamp * 1e-9 + + if not self._validate_sensor_time(sensor_time, t) or not self._validate_timestamp(sensor_time): + return HandleLogResult.TIMING_INVALID + + if not self._validate_sensor_source(msg.source): + return HandleLogResult.SENSOR_SOURCE_INVALID + + v = msg.gyroUncalibrated.v + meas = np.array([-v[2], -v[1], -v[0]]) + + gyro_bias = self.kf.x[States.GYRO_BIAS] + gyro_camodo_yawrate_err = np.abs((meas[2] - gyro_bias[2]) - self.camodo_yawrate_distribution[0]) + gyro_camodo_yawrate_err_threshold = YAWRATE_CROSS_ERR_CHECK_FACTOR * self.camodo_yawrate_distribution[1] + gyro_valid = gyro_camodo_yawrate_err < gyro_camodo_yawrate_err_threshold + + if np.linalg.norm(meas) >= ROTATION_SANITY_CHECK or not gyro_valid: + return HandleLogResult.INPUT_INVALID + + gyro_res = self.kf.predict_and_observe(sensor_time, ObservationKind.PHONE_GYRO, meas) + if gyro_res is not None: + _, new_x, _, new_P, _, _, (gyro_err,), _, _ = gyro_res + self.observation_errors[ObservationKind.PHONE_GYRO] = np.array(gyro_err) + self.observations[ObservationKind.PHONE_GYRO] = meas + + elif which == "carState": + self.car_speed = abs(msg.vEgo) + + elif which == "liveCalibration": + # Note that we use this message during calibration + if len(msg.rpyCalib) > 0: + calib = np.array(msg.rpyCalib) + if calib.min() < -CALIB_RPY_SANITY_CHECK or calib.max() > CALIB_RPY_SANITY_CHECK: + return HandleLogResult.INPUT_INVALID + + self.device_from_calib = rot_from_euler(calib) + + elif which == "cameraOdometry": + if not self._validate_timestamp(t): + return HandleLogResult.TIMING_INVALID + + rot_device = np.matmul(self.device_from_calib, np.array(msg.rot)) + trans_device = np.matmul(self.device_from_calib, np.array(msg.trans)) + + if np.linalg.norm(rot_device) > ROTATION_SANITY_CHECK or np.linalg.norm(trans_device) > TRANS_SANITY_CHECK: + return HandleLogResult.INPUT_INVALID + + rot_calib_std = np.array(msg.rotStd) + trans_calib_std = np.array(msg.transStd) + + if rot_calib_std.min() <= MIN_STD_SANITY_CHECK or trans_calib_std.min() <= MIN_STD_SANITY_CHECK: + return HandleLogResult.INPUT_INVALID + + if np.linalg.norm(rot_calib_std) > 10 * ROTATION_SANITY_CHECK or np.linalg.norm(trans_calib_std) > 10 * TRANS_SANITY_CHECK: + return HandleLogResult.INPUT_INVALID + + self.posenet_stds = np.roll(self.posenet_stds, -1) + self.posenet_stds[-1] = trans_calib_std[0] + + # Multiply by N to avoid to high certainty in kalman filter because of temporally correlated noise + rot_calib_std *= 10 + trans_calib_std *= 2 + + rot_device_std = rotate_std(self.device_from_calib, rot_calib_std) + trans_device_std = rotate_std(self.device_from_calib, trans_calib_std) + rot_device_noise = rot_device_std ** 2 + trans_device_noise = trans_device_std ** 2 + + cam_odo_rot_res = self.kf.predict_and_observe(t, ObservationKind.CAMERA_ODO_ROTATION, rot_device, np.array([np.diag(rot_device_noise)])) + cam_odo_trans_res = self.kf.predict_and_observe(t, ObservationKind.CAMERA_ODO_TRANSLATION, trans_device, np.array([np.diag(trans_device_noise)])) + self.camodo_yawrate_distribution = np.array([rot_device[2], rot_device_std[2]]) + if cam_odo_rot_res is not None: + _, new_x, _, new_P, _, _, (cam_odo_rot_err,), _, _ = cam_odo_rot_res + self.observation_errors[ObservationKind.CAMERA_ODO_ROTATION] = np.array(cam_odo_rot_err) + self.observations[ObservationKind.CAMERA_ODO_ROTATION] = rot_device + if cam_odo_trans_res is not None: + _, new_x, _, new_P, _, _, (cam_odo_trans_err,), _, _ = cam_odo_trans_res + self.observation_errors[ObservationKind.CAMERA_ODO_TRANSLATION] = np.array(cam_odo_trans_err) + self.observations[ObservationKind.CAMERA_ODO_TRANSLATION] = trans_device + + if new_x is not None and new_P is not None: + self._finite_check(t, new_x, new_P) + return HandleLogResult.SUCCESS + + def get_msg(self, sensors_valid: bool, inputs_valid: bool, filter_valid: bool): + state, cov = self.kf.x, self.kf.P + std = np.sqrt(np.diag(cov)) + + orientation_ned, orientation_ned_std = state[States.NED_ORIENTATION], std[States.NED_ORIENTATION] + velocity_device, velocity_device_std = state[States.DEVICE_VELOCITY], std[States.DEVICE_VELOCITY] + angular_velocity_device, angular_velocity_device_std = state[States.ANGULAR_VELOCITY], std[States.ANGULAR_VELOCITY] + acceleration_device, acceleration_device_std = state[States.ACCELERATION], std[States.ACCELERATION] + + msg = messaging.new_message("livePose") + msg.valid = filter_valid + + livePose = msg.livePose + init_xyz_measurement(livePose.orientationNED, orientation_ned, orientation_ned_std, filter_valid) + init_xyz_measurement(livePose.velocityDevice, velocity_device, velocity_device_std, filter_valid) + init_xyz_measurement(livePose.angularVelocityDevice, angular_velocity_device, angular_velocity_device_std, filter_valid) + init_xyz_measurement(livePose.accelerationDevice, acceleration_device, acceleration_device_std, filter_valid) + if self.debug: + livePose.debugFilterState.value = state.tolist() + livePose.debugFilterState.std = std.tolist() + livePose.debugFilterState.valid = filter_valid + livePose.debugFilterState.observations = [ + {'kind': k, 'value': self.observations[k].tolist(), 'error': self.observation_errors[k].tolist()} + for k in self.observations.keys() + ] + + old_mean = np.mean(self.posenet_stds[:POSENET_STD_HIST_HALF]) + new_mean = np.mean(self.posenet_stds[POSENET_STD_HIST_HALF:]) + std_spike = (new_mean / old_mean) > 4.0 and new_mean > 7.0 + + livePose.inputsOK = inputs_valid + livePose.posenetOK = not std_spike or self.car_speed <= 5.0 + livePose.sensorsOK = sensors_valid + + return msg + + +def sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, simulation): + cur_time = time.monotonic() + for which, msgs in [("accelerometer", acc_msgs), ("gyroscope", gyro_msgs)]: + if len(msgs) > 0: + sensor_valid[which] = msgs[-1].valid + sensor_recv_time[which] = cur_time + + if not simulation: + sensor_alive[which] = (cur_time - sensor_recv_time[which]) < 0.1 + else: + sensor_alive[which] = len(msgs) > 0 + + return all(sensor_alive.values()) and all(sensor_valid.values()) + + +def main(): + config_realtime_process([0, 1, 2, 3], 5) + + DEBUG = bool(int(os.getenv("DEBUG", "0"))) + SIMULATION = bool(int(os.getenv("SIMULATION", "0"))) + + pm = messaging.PubMaster(['livePose']) + sm = messaging.SubMaster(['carState', 'liveCalibration', 'cameraOdometry'], poll='cameraOdometry') + # separate sensor sockets for efficiency + sensor_sockets = [messaging.sub_sock(which, timeout=20) for which in ['accelerometer', 'gyroscope']] + sensor_alive, sensor_valid, sensor_recv_time = defaultdict(bool), defaultdict(bool), defaultdict(float) + + params = Params() + + estimator = LocationEstimator(DEBUG) + + filter_initialized = False + critcal_services = ["accelerometer", "gyroscope", "cameraOdometry"] + observation_input_invalid = defaultdict(int) + + input_invalid_limit = {s: round(INPUT_INVALID_LIMIT * (SERVICE_LIST[s].frequency / 20.)) for s in critcal_services} + input_invalid_threshold = {s: input_invalid_limit[s] - 0.5 for s in critcal_services} + input_invalid_decay = {s: calculate_invalid_input_decay(input_invalid_limit[s], INPUT_INVALID_RECOVERY, SERVICE_LIST[s].frequency) for s in critcal_services} + + initial_pose_data = params.get("LocationFilterInitialState") + if initial_pose_data is not None: + with log.Event.from_bytes(initial_pose_data) as lp_msg: + filter_state = lp_msg.livePose.debugFilterState + x_initial = np.array(filter_state.value, dtype=np.float64) if len(filter_state.value) != 0 else PoseKalman.initial_x + P_initial = np.diag(np.array(filter_state.std, dtype=np.float64)) if len(filter_state.std) != 0 else PoseKalman.initial_P + estimator.reset(None, x_initial, P_initial) + + while True: + sm.update() + + acc_msgs, gyro_msgs = (messaging.drain_sock(sock) for sock in sensor_sockets) + + if filter_initialized: + msgs = [] + for msg in acc_msgs + gyro_msgs: + t, valid, which, data = msg.logMonoTime, msg.valid, msg.which(), getattr(msg, msg.which()) + msgs.append((t, valid, which, data)) + for which, updated in sm.updated.items(): + if not updated: + continue + t, valid, data = sm.logMonoTime[which], sm.valid[which], sm[which] + msgs.append((t, valid, which, data)) + + for log_mono_time, valid, which, msg in sorted(msgs, key=lambda x: x[0]): + if valid: + t = log_mono_time * 1e-9 + res = estimator.handle_log(t, which, msg) + if which not in critcal_services: + continue + + if res == HandleLogResult.TIMING_INVALID: + cloudlog.warning(f"Observation {which} ignored due to failed timing check") + observation_input_invalid[which] += 1 + elif res == HandleLogResult.INPUT_INVALID: + cloudlog.warning(f"Observation {which} ignored due to failed sanity check") + observation_input_invalid[which] += 1 + elif res == HandleLogResult.SUCCESS: + observation_input_invalid[which] *= input_invalid_decay[which] + else: + filter_initialized = sm.all_checks() and sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, SIMULATION) + + if sm.updated["cameraOdometry"]: + critical_service_inputs_valid = all(observation_input_invalid[s] < input_invalid_threshold[s] for s in critcal_services) + inputs_valid = sm.all_valid() and critical_service_inputs_valid + sensors_valid = sensor_all_checks(acc_msgs, gyro_msgs, sensor_valid, sensor_recv_time, sensor_alive, SIMULATION) + + msg = estimator.get_msg(sensors_valid, inputs_valid, filter_initialized) + pm.send("livePose", msg) + + +if __name__ == "__main__": + main() diff --git a/selfdrive/locationd/models/.gitignore b/selfdrive/locationd/models/.gitignore new file mode 100644 index 0000000000..9ab870da89 --- /dev/null +++ b/selfdrive/locationd/models/.gitignore @@ -0,0 +1 @@ +generated/ diff --git a/selfdrive/locationd/models/__init__.py b/selfdrive/locationd/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/locationd/models/car_kf.py b/selfdrive/locationd/models/car_kf.py new file mode 100755 index 0000000000..27cc4ef9c9 --- /dev/null +++ b/selfdrive/locationd/models/car_kf.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python3 +import math +import sys +from typing import Any + +import numpy as np + +from openpilot.common.constants import ACCELERATION_DUE_TO_GRAVITY +from openpilot.selfdrive.locationd.models.constants import ObservationKind +from openpilot.common.swaglog import cloudlog + +from rednose.helpers.kalmanfilter import KalmanFilter + +if __name__ == '__main__': # Generating sympy + import sympy as sp + from rednose.helpers.ekf_sym import gen_code +else: + from rednose.helpers.ekf_sym_pyx import EKF_sym_pyx + + +i = 0 + +def _slice(n): + global i + s = slice(i, i + n) + i += n + + return s + + +class States: + # Vehicle model params + STIFFNESS = _slice(1) # [-] + STEER_RATIO = _slice(1) # [-] + ANGLE_OFFSET = _slice(1) # [rad] + ANGLE_OFFSET_FAST = _slice(1) # [rad] + + VELOCITY = _slice(2) # (x, y) [m/s] + YAW_RATE = _slice(1) # [rad/s] + STEER_ANGLE = _slice(1) # [rad] + ROAD_ROLL = _slice(1) # [rad] + + +class CarKalman(KalmanFilter): + name = 'car' + + initial_x = np.array([ + 1.0, + 15.0, + 0.0, + 0.0, + + 10.0, 0.0, + 0.0, + 0.0, + 0.0 + ]) + + # process noise + Q = np.diag([ + (.05 / 100)**2, + .01**2, + math.radians(0.02)**2, + math.radians(0.25)**2, + + .1**2, .01**2, + math.radians(0.1)**2, + math.radians(0.1)**2, + math.radians(1)**2, + ]) + P_initial = Q.copy() + + obs_noise: dict[int, Any] = { + ObservationKind.STEER_ANGLE: np.atleast_2d(math.radians(0.05)**2), + ObservationKind.ANGLE_OFFSET_FAST: np.atleast_2d(math.radians(10.0)**2), + ObservationKind.ROAD_ROLL: np.atleast_2d(math.radians(1.0)**2), + ObservationKind.STEER_RATIO: np.atleast_2d(5.0**2), + ObservationKind.STIFFNESS: np.atleast_2d(0.5**2), + ObservationKind.ROAD_FRAME_X_SPEED: np.atleast_2d(0.1**2), + } + + global_vars = [ + 'mass', + 'rotational_inertia', + 'center_to_front', + 'center_to_rear', + 'stiffness_front', + 'stiffness_rear', + ] + + @staticmethod + def generate_code(generated_dir): + dim_state = CarKalman.initial_x.shape[0] + name = CarKalman.name + + # Linearized single-track lateral dynamics, equations 7.211-7.213 + # Massimo Guiggiani, The Science of Vehicle Dynamics: Handling, Braking, and Ride of Road and Race Cars + # Springer Cham, 2023. doi: https://doi.org/10.1007/978-3-031-06461-6 + + # globals + global_vars = [sp.Symbol(name) for name in CarKalman.global_vars] + m, j, aF, aR, cF_orig, cR_orig = global_vars + + # make functions and jacobians with sympy + # state variables + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + + # Vehicle model constants + sf = state[States.STIFFNESS, :][0, 0] + + cF, cR = sf * cF_orig, sf * cR_orig + angle_offset = state[States.ANGLE_OFFSET, :][0, 0] + angle_offset_fast = state[States.ANGLE_OFFSET_FAST, :][0, 0] + theta = state[States.ROAD_ROLL, :][0, 0] + sa = state[States.STEER_ANGLE, :][0, 0] + + sR = state[States.STEER_RATIO, :][0, 0] + u, v = state[States.VELOCITY, :] + r = state[States.YAW_RATE, :][0, 0] + + A = sp.Matrix(np.zeros((2, 2))) + A[0, 0] = -(cF + cR) / (m * u) + A[0, 1] = -(cF * aF - cR * aR) / (m * u) - u + A[1, 0] = -(cF * aF - cR * aR) / (j * u) + A[1, 1] = -(cF * aF**2 + cR * aR**2) / (j * u) + + B = sp.Matrix(np.zeros((2, 1))) + B[0, 0] = cF / m / sR + B[1, 0] = (cF * aF) / j / sR + + C = sp.Matrix(np.zeros((2, 1))) + C[0, 0] = ACCELERATION_DUE_TO_GRAVITY + C[1, 0] = 0 + + x = sp.Matrix([v, r]) # lateral velocity, yaw rate + x_dot = A * x + B * (sa - angle_offset - angle_offset_fast) - C * theta + + dt = sp.Symbol('dt') + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.VELOCITY.start + 1, 0] = x_dot[0] + state_dot[States.YAW_RATE.start, 0] = x_dot[1] + + # Basic descretization, 1st order integrator + # Can be pretty bad if dt is big + f_sym = state + dt * state_dot + + # + # Observation functions + # + obs_eqs = [ + [sp.Matrix([r]), ObservationKind.ROAD_FRAME_YAW_RATE, None], + [sp.Matrix([u, v]), ObservationKind.ROAD_FRAME_XY_SPEED, None], + [sp.Matrix([u]), ObservationKind.ROAD_FRAME_X_SPEED, None], + [sp.Matrix([sa]), ObservationKind.STEER_ANGLE, None], + [sp.Matrix([angle_offset_fast]), ObservationKind.ANGLE_OFFSET_FAST, None], + [sp.Matrix([sR]), ObservationKind.STEER_RATIO, None], + [sp.Matrix([sf]), ObservationKind.STIFFNESS, None], + [sp.Matrix([theta]), ObservationKind.ROAD_ROLL, None], + ] + + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state, global_vars=global_vars) + + def __init__(self, generated_dir): + dim_state, dim_state_err = CarKalman.initial_x.shape[0], CarKalman.P_initial.shape[0] + self.filter = EKF_sym_pyx(generated_dir, CarKalman.name, CarKalman.Q, CarKalman.initial_x, CarKalman.P_initial, + dim_state, dim_state_err, global_vars=CarKalman.global_vars, logger=cloudlog) + + def set_globals(self, mass, rotational_inertia, center_to_front, center_to_rear, stiffness_front, stiffness_rear): + self.filter.set_global("mass", mass) + self.filter.set_global("rotational_inertia", rotational_inertia) + self.filter.set_global("center_to_front", center_to_front) + self.filter.set_global("center_to_rear", center_to_rear) + self.filter.set_global("stiffness_front", stiffness_front) + self.filter.set_global("stiffness_rear", stiffness_rear) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + CarKalman.generate_code(generated_dir) diff --git a/selfdrive/locationd/models/constants.py b/selfdrive/locationd/models/constants.py new file mode 100644 index 0000000000..6d328ce6f5 --- /dev/null +++ b/selfdrive/locationd/models/constants.py @@ -0,0 +1,92 @@ +import os + +GENERATED_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), 'generated')) + +class ObservationKind: + UNKNOWN = 0 + NO_OBSERVATION = 1 + GPS_NED = 2 + ODOMETRIC_SPEED = 3 + PHONE_GYRO = 4 + GPS_VEL = 5 + PSEUDORANGE_GPS = 6 + PSEUDORANGE_RATE_GPS = 7 + SPEED = 8 + NO_ROT = 9 + PHONE_ACCEL = 10 + ORB_POINT = 11 + ECEF_POS = 12 + CAMERA_ODO_TRANSLATION = 13 + CAMERA_ODO_ROTATION = 14 + ORB_FEATURES = 15 + MSCKF_TEST = 16 + FEATURE_TRACK_TEST = 17 + LANE_PT = 18 + IMU_FRAME = 19 + PSEUDORANGE_GLONASS = 20 + PSEUDORANGE_RATE_GLONASS = 21 + PSEUDORANGE = 22 + PSEUDORANGE_RATE = 23 + ECEF_VEL = 35 + ECEF_ORIENTATION_FROM_GPS = 32 + NO_ACCEL = 33 + ORB_FEATURES_WIDE = 34 + + ROAD_FRAME_XY_SPEED = 24 # (x, y) [m/s] + ROAD_FRAME_YAW_RATE = 25 # [rad/s] + STEER_ANGLE = 26 # [rad] + ANGLE_OFFSET_FAST = 27 # [rad] + STIFFNESS = 28 # [-] + STEER_RATIO = 29 # [-] + ROAD_FRAME_X_SPEED = 30 # (x) [m/s] + ROAD_ROLL = 31 # [rad] + + names = [ + 'Unknown', + 'No observation', + 'GPS NED', + 'Odometric speed', + 'Phone gyro', + 'GPS velocity', + 'GPS pseudorange', + 'GPS pseudorange rate', + 'Speed', + 'No rotation', + 'Phone acceleration', + 'ORB point', + 'ECEF pos', + 'camera odometric translation', + 'camera odometric rotation', + 'ORB features', + 'MSCKF test', + 'Feature track test', + 'Lane ecef point', + 'imu frame eulers', + 'GLONASS pseudorange', + 'GLONASS pseudorange rate', + 'pseudorange', + 'pseudorange rate', + + 'Road Frame x,y speed', + 'Road Frame yaw rate', + 'Steer Angle', + 'Fast Angle Offset', + 'Stiffness', + 'Steer Ratio', + 'Road Frame x speed', + 'Road Roll', + 'ECEF orientation from GPS', + 'NO accel', + 'ORB features wide camera', + 'ECEF_VEL', + ] + + @classmethod + def to_string(cls, kind): + return cls.names[kind] + + +SAT_OBS = [ObservationKind.PSEUDORANGE_GPS, + ObservationKind.PSEUDORANGE_RATE_GPS, + ObservationKind.PSEUDORANGE_GLONASS, + ObservationKind.PSEUDORANGE_RATE_GLONASS] diff --git a/selfdrive/locationd/models/pose_kf.py b/selfdrive/locationd/models/pose_kf.py new file mode 100755 index 0000000000..020e51ad6e --- /dev/null +++ b/selfdrive/locationd/models/pose_kf.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +import sys +import numpy as np + +from openpilot.selfdrive.locationd.models.constants import ObservationKind + +from rednose.helpers.kalmanfilter import KalmanFilter + +if __name__=="__main__": + import sympy as sp + from rednose.helpers.ekf_sym import gen_code + from rednose.helpers.sympy_helpers import euler_rotate, rot_to_euler +else: + from rednose.helpers.ekf_sym_pyx import EKF_sym_pyx + +EARTH_G = 9.81 + + +class States: + NED_ORIENTATION = slice(0, 3) # roll, pitch, yaw in rad + DEVICE_VELOCITY = slice(3, 6) # ned velocity in m/s + ANGULAR_VELOCITY = slice(6, 9) # roll, pitch and yaw rates in rad/s + GYRO_BIAS = slice(9, 12) # roll, pitch and yaw gyroscope biases in rad/s + ACCELERATION = slice(12, 15) # acceleration in device frame in m/s**2 + ACCEL_BIAS = slice(15, 18) # Acceletometer bias in m/s**2 + + +class PoseKalman(KalmanFilter): + name = "pose" + + # state + initial_x = np.array([0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0]) + # state covariance + initial_P = np.diag([0.01**2, 0.01**2, 0.01**2, + 10**2, 10**2, 10**2, + 1**2, 1**2, 1**2, + 1**2, 1**2, 1**2, + 100**2, 100**2, 100**2, + 0.01**2, 0.01**2, 0.01**2]) + + # process noise + Q = np.diag([0.001**2, 0.001**2, 0.001**2, + 0.01**2, 0.01**2, 0.01**2, + 0.1**2, 0.1**2, 0.1**2, + (0.005 / 100)**2, (0.005 / 100)**2, (0.005 / 100)**2, + 3**2, 3**2, 3**2, + 0.005**2, 0.005**2, 0.005**2]) + + obs_noise = {ObservationKind.PHONE_GYRO: np.diag([0.025**2, 0.025**2, 0.025**2]), + ObservationKind.PHONE_ACCEL: np.diag([.5**2, .5**2, .5**2]), + ObservationKind.CAMERA_ODO_TRANSLATION: np.diag([0.5**2, 0.5**2, 0.5**2]), + ObservationKind.CAMERA_ODO_ROTATION: np.diag([0.05**2, 0.05**2, 0.05**2])} + + @staticmethod + def generate_code(generated_dir): + name = PoseKalman.name + dim_state = PoseKalman.initial_x.shape[0] + dim_state_err = PoseKalman.initial_P.shape[0] + + state_sym = sp.MatrixSymbol('state', dim_state, 1) + state = sp.Matrix(state_sym) + roll, pitch, yaw = state[States.NED_ORIENTATION, :] + velocity = state[States.DEVICE_VELOCITY, :] + angular_velocity = state[States.ANGULAR_VELOCITY, :] + vroll, vpitch, vyaw = angular_velocity + gyro_bias = state[States.GYRO_BIAS, :] + acceleration = state[States.ACCELERATION, :] + acc_bias = state[States.ACCEL_BIAS, :] + + dt = sp.Symbol('dt') + + ned_from_device = euler_rotate(roll, pitch, yaw) + device_from_ned = ned_from_device.T + + state_dot = sp.Matrix(np.zeros((dim_state, 1))) + state_dot[States.DEVICE_VELOCITY, :] = acceleration + + f_sym = state + dt * state_dot + device_from_device_t1 = euler_rotate(dt*vroll, dt*vpitch, dt*vyaw) + ned_from_device_t1 = ned_from_device * device_from_device_t1 + f_sym[States.NED_ORIENTATION, :] = rot_to_euler(ned_from_device_t1) + + centripetal_acceleration = angular_velocity.cross(velocity) + gravity = sp.Matrix([0, 0, -EARTH_G]) + h_gyro_sym = angular_velocity + gyro_bias + h_acc_sym = device_from_ned * gravity + acceleration + centripetal_acceleration + acc_bias + h_phone_rot_sym = angular_velocity + h_relative_motion_sym = velocity + obs_eqs = [ + [h_gyro_sym, ObservationKind.PHONE_GYRO, None], + [h_acc_sym, ObservationKind.PHONE_ACCEL, None], + [h_relative_motion_sym, ObservationKind.CAMERA_ODO_TRANSLATION, None], + [h_phone_rot_sym, ObservationKind.CAMERA_ODO_ROTATION, None], + ] + gen_code(generated_dir, name, f_sym, dt, state_sym, obs_eqs, dim_state, dim_state_err) + + def __init__(self, generated_dir, max_rewind_age): + dim_state, dim_state_err = PoseKalman.initial_x.shape[0], PoseKalman.initial_P.shape[0] + self.filter = EKF_sym_pyx(generated_dir, self.name, PoseKalman.Q, PoseKalman.initial_x, PoseKalman.initial_P, + dim_state, dim_state_err, max_rewind_age=max_rewind_age) + + +if __name__ == "__main__": + generated_dir = sys.argv[2] + PoseKalman.generate_code(generated_dir) diff --git a/selfdrive/locationd/paramsd.py b/selfdrive/locationd/paramsd.py new file mode 100755 index 0000000000..b4084fe5bc --- /dev/null +++ b/selfdrive/locationd/paramsd.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python3 +import os +import numpy as np +import capnp + +import cereal.messaging as messaging +from cereal import car, log +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process, DT_MDL +from openpilot.selfdrive.locationd.models.car_kf import CarKalman, ObservationKind, States +from openpilot.selfdrive.locationd.models.constants import GENERATED_DIR +from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose +from openpilot.common.swaglog import cloudlog + +MAX_ANGLE_OFFSET_DELTA = 20 * DT_MDL # Max 20 deg/s +ROLL_MAX_DELTA = np.radians(20.0) * DT_MDL # 20deg in 1 second is well within curvature limits +ROLL_MIN, ROLL_MAX = np.radians(-10), np.radians(10) +ROLL_LOWERED_MAX = np.radians(8) +ROLL_STD_MAX = np.radians(1.5) +LATERAL_ACC_SENSOR_THRESHOLD = 4.0 +OFFSET_MAX = 10.0 +OFFSET_LOWERED_MAX = 8.0 +MIN_ACTIVE_SPEED = 1.0 +LOW_ACTIVE_SPEED = 10.0 + + +class VehicleParamsLearner: + def __init__(self, CP: car.CarParams, steer_ratio: float, stiffness_factor: float, angle_offset: float, P_initial: np.ndarray | None = None): + self.kf = CarKalman(GENERATED_DIR) + + self.x_initial = CarKalman.initial_x.copy() + self.x_initial[States.STEER_RATIO] = steer_ratio + self.x_initial[States.STIFFNESS] = stiffness_factor + self.x_initial[States.ANGLE_OFFSET] = angle_offset + self.P_initial = P_initial if P_initial is not None else CarKalman.P_initial + + self.kf.set_globals( + mass=CP.mass, + rotational_inertia=CP.rotationalInertia, + center_to_front=CP.centerToFront, + center_to_rear=CP.wheelbase - CP.centerToFront, + stiffness_front=CP.tireStiffnessFront, + stiffness_rear=CP.tireStiffnessRear + ) + + self.min_sr, self.max_sr = 0.5 * CP.steerRatio, 2.0 * CP.steerRatio + + self.calibrator = PoseCalibrator() + + self.observed_speed = 0.0 + self.observed_yaw_rate = 0.0 + self.observed_roll = 0.0 + + self.avg_offset_valid = True + self.total_offset_valid = True + self.roll_valid = True + + self.reset(None) + + def reset(self, t: float | None): + self.kf.init_state(self.x_initial, covs=self.P_initial, filter_time=t) + + self.angle_offset, self.roll, self.active = np.degrees(self.x_initial[States.ANGLE_OFFSET].item()), 0.0, False + self.avg_angle_offset = self.angle_offset + + def handle_log(self, t: float, which: str, msg: capnp._DynamicStructReader): + if which == 'livePose': + device_pose = Pose.from_live_pose(msg) + calibrated_pose = self.calibrator.build_calibrated_pose(device_pose) + + yaw_rate, yaw_rate_std = calibrated_pose.angular_velocity.z, calibrated_pose.angular_velocity.z_std + yaw_rate_valid = msg.angularVelocityDevice.valid + yaw_rate_valid = yaw_rate_valid and 0 < yaw_rate_std < 10 # rad/s + yaw_rate_valid = yaw_rate_valid and abs(yaw_rate) < 1 # rad/s + if not yaw_rate_valid: + # This is done to bound the yaw rate estimate when localizer values are invalid or calibrating + yaw_rate, yaw_rate_std = 0.0, np.radians(10.0) + self.observed_yaw_rate = yaw_rate + + localizer_roll, localizer_roll_std = device_pose.orientation.x, device_pose.orientation.x_std + localizer_roll_std = np.radians(1) if np.isnan(localizer_roll_std) else localizer_roll_std + roll_valid = (localizer_roll_std < ROLL_STD_MAX) and (ROLL_MIN < localizer_roll < ROLL_MAX) and msg.sensorsOK + if roll_valid: + roll = localizer_roll + # Experimentally found multiplier of 2 to be best trade-off between stability and accuracy or similar? + roll_std = 2 * localizer_roll_std + else: + # This is done to bound the road roll estimate when localizer values are invalid + roll = 0.0 + roll_std = np.radians(10.0) + self.observed_roll = np.clip(roll, self.observed_roll - ROLL_MAX_DELTA, self.observed_roll + ROLL_MAX_DELTA) + + if self.active: + if msg.posenetOK: + self.kf.predict_and_observe(t, + ObservationKind.ROAD_FRAME_YAW_RATE, + np.array([[-self.observed_yaw_rate]]), + np.array([np.atleast_2d(yaw_rate_std**2)])) + + self.kf.predict_and_observe(t, + ObservationKind.ROAD_ROLL, + np.array([[self.observed_roll]]), + np.array([np.atleast_2d(roll_std**2)])) + self.kf.predict_and_observe(t, ObservationKind.ANGLE_OFFSET_FAST, np.array([[0]])) + + # We observe the current stiffness and steer ratio (with a high observation noise) to bound + # the respective estimate STD. Otherwise the STDs keep increasing, causing rapid changes in the + # states in longer routes (especially straight stretches). + stiffness = float(self.kf.x[States.STIFFNESS].item()) + steer_ratio = float(self.kf.x[States.STEER_RATIO].item()) + self.kf.predict_and_observe(t, ObservationKind.STIFFNESS, np.array([[stiffness]])) + self.kf.predict_and_observe(t, ObservationKind.STEER_RATIO, np.array([[steer_ratio]])) + + elif which == 'liveCalibration': + self.calibrator.feed_live_calib(msg) + + elif which == 'carState': + steering_angle = msg.steeringAngleDeg + + in_linear_region = abs(steering_angle) < 45 + self.observed_speed = msg.vEgo + self.active = self.observed_speed > MIN_ACTIVE_SPEED and in_linear_region + + if self.active: + self.kf.predict_and_observe(t, ObservationKind.STEER_ANGLE, np.array([[np.radians(steering_angle)]])) + self.kf.predict_and_observe(t, ObservationKind.ROAD_FRAME_X_SPEED, np.array([[self.observed_speed]])) + + if not self.active: + # Reset time when stopped so uncertainty doesn't grow + self.kf.filter.set_filter_time(t) # type: ignore + self.kf.filter.reset_rewind() # type: ignore + + def get_msg(self, valid: bool, debug: bool = False) -> capnp._DynamicStructBuilder: + x = self.kf.x + P = np.sqrt(self.kf.P.diagonal()) + if not np.all(np.isfinite(x)): + cloudlog.error("NaN in liveParameters estimate. Resetting to default values") + self.reset(self.kf.t) + x = self.kf.x + + self.avg_angle_offset = np.clip(np.degrees(x[States.ANGLE_OFFSET].item()), + self.avg_angle_offset - MAX_ANGLE_OFFSET_DELTA, self.avg_angle_offset + MAX_ANGLE_OFFSET_DELTA) + self.angle_offset = np.clip(np.degrees(x[States.ANGLE_OFFSET].item() + x[States.ANGLE_OFFSET_FAST].item()), + self.angle_offset - MAX_ANGLE_OFFSET_DELTA, self.angle_offset + MAX_ANGLE_OFFSET_DELTA) + self.roll = np.clip(float(x[States.ROAD_ROLL].item()), self.roll - ROLL_MAX_DELTA, self.roll + ROLL_MAX_DELTA) + roll_std = float(P[States.ROAD_ROLL].item()) + if self.active and self.observed_speed > LOW_ACTIVE_SPEED: + # Account for the opposite signs of the yaw rates + # At low speeds, bumping into a curb can cause the yaw rate to be very high + sensors_valid = bool(abs(self.observed_speed * (x[States.YAW_RATE].item() + self.observed_yaw_rate)) < LATERAL_ACC_SENSOR_THRESHOLD) + else: + sensors_valid = True + self.avg_offset_valid = check_valid_with_hysteresis(self.avg_offset_valid, self.avg_angle_offset, OFFSET_MAX, OFFSET_LOWERED_MAX) + self.total_offset_valid = check_valid_with_hysteresis(self.total_offset_valid, self.angle_offset, OFFSET_MAX, OFFSET_LOWERED_MAX) + self.roll_valid = check_valid_with_hysteresis(self.roll_valid, self.roll, ROLL_MAX, ROLL_LOWERED_MAX) + + msg = messaging.new_message('liveParameters') + + msg.valid = valid + + liveParameters = msg.liveParameters + liveParameters.posenetValid = True + liveParameters.sensorValid = sensors_valid + liveParameters.steerRatio = float(x[States.STEER_RATIO].item()) + liveParameters.stiffnessFactor = float(x[States.STIFFNESS].item()) + liveParameters.roll = float(self.roll) + liveParameters.angleOffsetAverageDeg = float(self.avg_angle_offset) + liveParameters.angleOffsetDeg = float(self.angle_offset) + liveParameters.steerRatioValid = self.min_sr <= liveParameters.steerRatio <= self.max_sr + liveParameters.stiffnessFactorValid = 0.2 <= liveParameters.stiffnessFactor <= 5.0 + liveParameters.angleOffsetAverageValid = bool(self.avg_offset_valid) + liveParameters.angleOffsetValid = bool(self.total_offset_valid) + liveParameters.valid = all(( + liveParameters.angleOffsetAverageValid, + liveParameters.angleOffsetValid , + self.roll_valid, + roll_std < ROLL_STD_MAX, + liveParameters.stiffnessFactorValid, + liveParameters.steerRatioValid, + )) + liveParameters.steerRatioStd = float(P[States.STEER_RATIO].item()) + liveParameters.stiffnessFactorStd = float(P[States.STIFFNESS].item()) + liveParameters.angleOffsetAverageStd = float(P[States.ANGLE_OFFSET].item()) + liveParameters.angleOffsetFastStd = float(P[States.ANGLE_OFFSET_FAST].item()) + if debug: + liveParameters.debugFilterState = log.LiveParametersData.FilterState.new_message() + liveParameters.debugFilterState.value = x.tolist() + liveParameters.debugFilterState.std = P.tolist() + + return msg + + +def check_valid_with_hysteresis(current_valid: bool, val: float, threshold: float, lowered_threshold: float): + if current_valid: + current_valid = abs(val) < threshold + else: + current_valid = abs(val) < lowered_threshold + return current_valid + + +# TODO: Remove this function after few releases (added in 0.9.9) +def migrate_cached_vehicle_params_if_needed(params: Params): + last_parameters_data_old = params.get("LiveParameters") + last_parameters_data = params.get("LiveParametersV2") + if last_parameters_data_old is None or last_parameters_data is not None: + return + + try: + last_parameters_msg = messaging.new_message('liveParameters') + last_parameters_msg.liveParameters.valid = True + last_parameters_msg.liveParameters.steerRatio = last_parameters_data_old['steerRatio'] + last_parameters_msg.liveParameters.stiffnessFactor = last_parameters_data_old['stiffnessFactor'] + last_parameters_msg.liveParameters.angleOffsetAverageDeg = last_parameters_data_old['angleOffsetAverageDeg'] + params.put("LiveParametersV2", last_parameters_msg.to_bytes()) + except Exception as e: + cloudlog.error(f"Failed to perform parameter migration: {e}") + params.remove("LiveParameters") + + +def retrieve_initial_vehicle_params(params: Params, CP: car.CarParams, replay: bool, debug: bool): + last_parameters_data = params.get("LiveParametersV2") + last_carparams_data = params.get("CarParamsPrevRoute") + + steer_ratio, stiffness_factor, angle_offset_deg, p_initial = CP.steerRatio, 1.0, 0.0, None + + retrieve_success = False + if last_parameters_data is not None and last_carparams_data is not None: + try: + with log.Event.from_bytes(last_parameters_data) as last_lp_msg, car.CarParams.from_bytes(last_carparams_data) as last_CP: + lp = last_lp_msg.liveParameters + # Check if car model matches + if last_CP.carFingerprint != CP.carFingerprint: + raise Exception("Car model mismatch") + + # Check if starting values are sane + min_sr, max_sr = 0.5 * CP.steerRatio, 2.0 * CP.steerRatio + steer_ratio_sane = min_sr <= lp.steerRatio <= max_sr + if not steer_ratio_sane: + raise Exception(f"Invalid starting values found {lp}") + + initial_filter_std = np.array(lp.debugFilterState.std) + if debug and len(initial_filter_std) != 0: + p_initial = np.diag(initial_filter_std) + + steer_ratio, stiffness_factor, angle_offset_deg = lp.steerRatio, lp.stiffnessFactor, lp.angleOffsetAverageDeg + retrieve_success = True + except Exception as e: + cloudlog.error(f"Failed to retrieve initial values: {e}") + params.remove("LiveParametersV2") + + if not replay: + # When driving in wet conditions the stiffness can go down, and then be too low on the next drive + # Without a way to detect this we have to reset the stiffness every drive + stiffness_factor = 1.0 + + if not retrieve_success: + cloudlog.info("Parameter learner resetting to default values") + + return steer_ratio, stiffness_factor, angle_offset_deg, p_initial + + +def main(): + config_realtime_process([0, 1, 2, 3], 5) + + DEBUG = bool(int(os.getenv("DEBUG", "0"))) + REPLAY = bool(int(os.getenv("REPLAY", "0"))) + + pm = messaging.PubMaster(['liveParameters']) + sm = messaging.SubMaster(['livePose', 'liveCalibration', 'carState'], poll='livePose') + + params = Params() + CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams) + + migrate_cached_vehicle_params_if_needed(params) + + steer_ratio, stiffness_factor, angle_offset_deg, pInitial = retrieve_initial_vehicle_params(params, CP, REPLAY, DEBUG) + learner = VehicleParamsLearner(CP, steer_ratio, stiffness_factor, np.radians(angle_offset_deg), pInitial) + + while True: + sm.update() + if sm.all_checks(): + for which in sorted(sm.updated.keys(), key=lambda x: sm.logMonoTime[x]): + if sm.updated[which]: + t = sm.logMonoTime[which] * 1e-9 + learner.handle_log(t, which, sm[which]) + + if sm.updated['livePose']: + msg = learner.get_msg(sm.all_checks(), debug=DEBUG) + + msg_dat = msg.to_bytes() + if sm.frame % 1200 == 0: # once a minute + params.put_nonblocking("LiveParametersV2", msg_dat) + + pm.send('liveParameters', msg_dat) + + +if __name__ == "__main__": + main() diff --git a/selfdrive/locationd/test/.gitignore b/selfdrive/locationd/test/.gitignore new file mode 100644 index 0000000000..89f9ac04aa --- /dev/null +++ b/selfdrive/locationd/test/.gitignore @@ -0,0 +1 @@ +out/ diff --git a/selfdrive/locationd/test/__init__.py b/selfdrive/locationd/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/locationd/test/test_calibrationd.py b/selfdrive/locationd/test/test_calibrationd.py new file mode 100644 index 0000000000..df61b6a7c7 --- /dev/null +++ b/selfdrive/locationd/test/test_calibrationd.py @@ -0,0 +1,112 @@ +import random + +import numpy as np + +import cereal.messaging as messaging +from cereal import log +from openpilot.common.params import Params +from openpilot.selfdrive.locationd.calibrationd import Calibrator, INPUTS_NEEDED, INPUTS_WANTED, BLOCK_SIZE, MIN_SPEED_FILTER, \ + MAX_YAW_RATE_FILTER, SMOOTH_CYCLES, HEIGHT_INIT, MAX_ALLOWED_PITCH_SPREAD, MAX_ALLOWED_YAW_SPREAD + + +def process_messages(c, cam_odo_calib, cycles, + cam_odo_speed=MIN_SPEED_FILTER + 1, + carstate_speed=MIN_SPEED_FILTER + 1, + cam_odo_yr=0.0, + cam_odo_speed_std=1e-3, + cam_odo_height_std=1e-3): + old_rpy_weight_prev = 0.0 + for _ in range(cycles): + assert (old_rpy_weight_prev - c.old_rpy_weight < 1/SMOOTH_CYCLES + 1e-3) + old_rpy_weight_prev = c.old_rpy_weight + c.handle_v_ego(carstate_speed) + c.handle_cam_odom([cam_odo_speed, + np.sin(cam_odo_calib[2]) * cam_odo_speed, + -np.sin(cam_odo_calib[1]) * cam_odo_speed], + [0.0, 0.0, cam_odo_yr], + [0.0, 0.0, 0.0], + [cam_odo_speed_std, cam_odo_speed_std, cam_odo_speed_std], + [0.0, 0.0, HEIGHT_INIT.item()], + [cam_odo_height_std, cam_odo_height_std, cam_odo_height_std]) + +class TestCalibrationd: + + def test_read_saved_params(self): + msg = messaging.new_message('liveCalibration') + msg.liveCalibration.validBlocks = random.randint(1, 10) + msg.liveCalibration.rpyCalib = [random.random() for _ in range(3)] + msg.liveCalibration.height = [random.random() for _ in range(1)] + Params().put("CalibrationParams", msg.to_bytes()) + c = Calibrator(param_put=True) + + np.testing.assert_allclose(msg.liveCalibration.rpyCalib, c.rpy) + np.testing.assert_allclose(msg.liveCalibration.height, c.height) + assert msg.liveCalibration.validBlocks == c.valid_blocks + + + def test_calibration_basics(self): + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_WANTED) + assert c.valid_blocks == INPUTS_WANTED + np.testing.assert_allclose(c.rpy, np.zeros(3)) + np.testing.assert_allclose(c.height, HEIGHT_INIT) + c.reset() + + + def test_calibration_low_speed_reject(self): + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_WANTED, cam_odo_speed=MIN_SPEED_FILTER - 1) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_WANTED, carstate_speed=MIN_SPEED_FILTER - 1) + assert c.valid_blocks == 0 + np.testing.assert_allclose(c.rpy, np.zeros(3)) + np.testing.assert_allclose(c.height, HEIGHT_INIT) + + + def test_calibration_yaw_rate_reject(self): + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_WANTED, cam_odo_yr=MAX_YAW_RATE_FILTER) + assert c.valid_blocks == 0 + np.testing.assert_allclose(c.rpy, np.zeros(3)) + np.testing.assert_allclose(c.height, HEIGHT_INIT) + + + def test_calibration_speed_std_reject(self): + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_WANTED, cam_odo_speed_std=1e3) + assert c.valid_blocks == INPUTS_NEEDED + np.testing.assert_allclose(c.rpy, np.zeros(3)) + + + def test_calibration_speed_std_height_reject(self): + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_WANTED, cam_odo_height_std=1e3) + assert c.valid_blocks == INPUTS_NEEDED + np.testing.assert_allclose(c.rpy, np.zeros(3)) + + + def test_calibration_auto_reset(self): + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_NEEDED) + assert c.valid_blocks == INPUTS_NEEDED + np.testing.assert_allclose(c.rpy, [0.0, 0.0, 0.0], atol=1e-3) + process_messages(c, [0.0, MAX_ALLOWED_PITCH_SPREAD*0.9, MAX_ALLOWED_YAW_SPREAD*0.9], BLOCK_SIZE + 10) + assert c.valid_blocks == INPUTS_NEEDED + 1 + assert c.cal_status == log.LiveCalibrationData.Status.calibrated + + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_NEEDED) + assert c.valid_blocks == INPUTS_NEEDED + np.testing.assert_allclose(c.rpy, [0.0, 0.0, 0.0]) + process_messages(c, [0.0, MAX_ALLOWED_PITCH_SPREAD*1.1, 0.0], BLOCK_SIZE + 10) + assert c.valid_blocks == 1 + assert c.cal_status == log.LiveCalibrationData.Status.recalibrating + np.testing.assert_allclose(c.rpy, [0.0, MAX_ALLOWED_PITCH_SPREAD*1.1, 0.0], atol=1e-2) + + c = Calibrator(param_put=False) + process_messages(c, [0.0, 0.0, 0.0], BLOCK_SIZE * INPUTS_NEEDED) + assert c.valid_blocks == INPUTS_NEEDED + np.testing.assert_allclose(c.rpy, [0.0, 0.0, 0.0]) + process_messages(c, [0.0, 0.0, MAX_ALLOWED_YAW_SPREAD*1.1], BLOCK_SIZE + 10) + assert c.valid_blocks == 1 + assert c.cal_status == log.LiveCalibrationData.Status.recalibrating + np.testing.assert_allclose(c.rpy, [0.0, 0.0, MAX_ALLOWED_YAW_SPREAD*1.1], atol=1e-2) diff --git a/selfdrive/locationd/test/test_lagd.py b/selfdrive/locationd/test/test_lagd.py new file mode 100644 index 0000000000..a3dfce9c29 --- /dev/null +++ b/selfdrive/locationd/test/test_lagd.py @@ -0,0 +1,136 @@ +import random +import numpy as np +import time +import pytest + +from cereal import messaging, log, car +from openpilot.selfdrive.locationd.lagd import LateralLagEstimator, retrieve_initial_lag, masked_normalized_cross_correlation, \ + BLOCK_NUM_NEEDED, BLOCK_SIZE, MIN_OKAY_WINDOW_SEC +from openpilot.selfdrive.test.process_replay.migration import migrate, migrate_carParams +from openpilot.selfdrive.locationd.test.test_locationd_scenarios import TEST_ROUTE +from openpilot.common.params import Params +from openpilot.tools.lib.logreader import LogReader +from openpilot.system.hardware import PC + +MAX_ERR_FRAMES = 1 +DT = 0.05 + + +def process_messages(estimator, lag_frames, n_frames, vego=20.0, rejection_threshold=0.0): + for i in range(n_frames): + t = i * estimator.dt + desired_la = np.cos(10 * t) * 0.1 + actual_la = np.cos(10 * (t - lag_frames * estimator.dt)) * 0.1 + + # if sample is masked out, set it to desired value (no lag) + rejected = random.uniform(0, 1) < rejection_threshold + if rejected: + actual_la = desired_la + + desired_cuvature = float(desired_la / (vego ** 2)) + actual_yr = float(actual_la / vego) + msgs = [ + (t, "carControl", car.CarControl(latActive=not rejected)), + (t, "carState", car.CarState(vEgo=vego, steeringPressed=False)), + (t, "controlsState", log.ControlsState(desiredCurvature=desired_cuvature)), + (t, "livePose", log.LivePose(angularVelocityDevice=log.LivePose.XYZMeasurement(z=actual_yr, valid=True), + posenetOK=True, inputsOK=True)), + (t, "liveCalibration", log.LiveCalibrationData(rpyCalib=[0, 0, 0], calStatus=log.LiveCalibrationData.Status.calibrated)), + ] + for t, w, m in msgs: + estimator.handle_log(t, w, m) + estimator.update_points() + estimator.update_estimate() + + +class TestLagd: + def test_read_saved_params(self): + params = Params() + + lr = migrate(LogReader(TEST_ROUTE), [migrate_carParams]) + CP = next(m for m in lr if m.which() == "carParams").carParams + + msg = messaging.new_message('liveDelay') + msg.liveDelay.lateralDelayEstimate = random.random() + msg.liveDelay.validBlocks = random.randint(1, 10) + params.put("LiveDelay", msg.to_bytes()) + params.put("CarParamsPrevRoute", CP.as_builder().to_bytes()) + + saved_lag_params = retrieve_initial_lag(params, CP) + assert saved_lag_params is not None + + lag, valid_blocks = saved_lag_params + assert lag == msg.liveDelay.lateralDelayEstimate + assert valid_blocks == msg.liveDelay.validBlocks + + def test_ncc(self): + lag_frames = random.randint(1, 19) + + desired_sig = np.sin(np.arange(0.0, 10.0, 0.1)) + actual_sig = np.sin(np.arange(0.0, 10.0, 0.1) - lag_frames * 0.1) + mask = np.ones(len(desired_sig), dtype=bool) + + corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20] + assert np.argmax(corr) == lag_frames + + # add some noise + desired_sig += np.random.normal(0, 0.05, len(desired_sig)) + actual_sig += np.random.normal(0, 0.05, len(actual_sig)) + corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20] + assert np.argmax(corr) in range(lag_frames - MAX_ERR_FRAMES, lag_frames + MAX_ERR_FRAMES + 1) + + # mask out 40% of the values, and make them noise + mask = np.random.choice([True, False], size=len(desired_sig), p=[0.6, 0.4]) + desired_sig[~mask] = np.random.normal(0, 1, size=np.sum(~mask)) + actual_sig[~mask] = np.random.normal(0, 1, size=np.sum(~mask)) + corr = masked_normalized_cross_correlation(desired_sig, actual_sig, mask, 200)[len(desired_sig) - 1:len(desired_sig) + 20] + assert np.argmax(corr) in range(lag_frames - MAX_ERR_FRAMES, lag_frames + MAX_ERR_FRAMES + 1) + + def test_empty_estimator(self): + mocked_CP = car.CarParams(steerActuatorDelay=0.8) + estimator = LateralLagEstimator(mocked_CP, DT) + msg = estimator.get_msg(True) + assert msg.liveDelay.status == 'unestimated' + assert np.allclose(msg.liveDelay.lateralDelay, estimator.initial_lag) + assert np.allclose(msg.liveDelay.lateralDelayEstimate, estimator.initial_lag) + assert msg.liveDelay.validBlocks == 0 + assert msg.liveDelay.calPerc == 0 + + def test_estimator_basics(self, subtests): + for lag_frames in range(5): + with subtests.test(msg=f"lag_frames={lag_frames}"): + mocked_CP = car.CarParams(steerActuatorDelay=0.8) + estimator = LateralLagEstimator(mocked_CP, DT, min_recovery_buffer_sec=0.0, min_yr=0.0) + process_messages(estimator, lag_frames, int(MIN_OKAY_WINDOW_SEC / DT) + BLOCK_NUM_NEEDED * BLOCK_SIZE) + msg = estimator.get_msg(True) + assert msg.liveDelay.status == 'estimated' + assert np.allclose(msg.liveDelay.lateralDelay, lag_frames * DT, atol=0.01) + assert np.allclose(msg.liveDelay.lateralDelayEstimate, lag_frames * DT, atol=0.01) + assert np.allclose(msg.liveDelay.lateralDelayEstimateStd, 0.0, atol=0.01) + assert msg.liveDelay.validBlocks == BLOCK_NUM_NEEDED + assert msg.liveDelay.calPerc == 100 + + def test_estimator_masking(self): + mocked_CP, lag_frames = car.CarParams(steerActuatorDelay=0.8), random.randint(1, 19) + estimator = LateralLagEstimator(mocked_CP, DT, min_recovery_buffer_sec=0.0, min_yr=0.0, min_valid_block_count=1) + process_messages(estimator, lag_frames, (int(MIN_OKAY_WINDOW_SEC / DT) + BLOCK_SIZE) * 2, rejection_threshold=0.4) + msg = estimator.get_msg(True) + assert np.allclose(msg.liveDelay.lateralDelayEstimate, lag_frames * DT, atol=0.01) + assert np.allclose(msg.liveDelay.lateralDelayEstimateStd, 0.0, atol=0.01) + assert msg.liveDelay.calPerc == 100 + + @pytest.mark.skipif(PC, reason="only on device") + @pytest.mark.timeout(60) + def test_estimator_performance(self): + mocked_CP = car.CarParams(steerActuatorDelay=0.8) + estimator = LateralLagEstimator(mocked_CP, DT) + + ds = [] + for _ in range(1000): + st = time.perf_counter() + estimator.update_points() + estimator.update_estimate() + d = time.perf_counter() - st + ds.append(d) + + assert np.mean(ds) < DT diff --git a/selfdrive/locationd/test/test_locationd_scenarios.py b/selfdrive/locationd/test/test_locationd_scenarios.py new file mode 100644 index 0000000000..0ea7ac183f --- /dev/null +++ b/selfdrive/locationd/test/test_locationd_scenarios.py @@ -0,0 +1,190 @@ +import numpy as np +from collections import defaultdict +from enum import Enum + +from openpilot.tools.lib.logreader import LogReader +from openpilot.selfdrive.test.process_replay.migration import migrate_all +from openpilot.selfdrive.test.process_replay.process_replay import replay_process_with_name + +# TODO find a new segment to test +TEST_ROUTE = "4019fff6e54cf1c7|00000123--4bc0d95ef6/5" +GPS_MESSAGES = ['gpsLocationExternal', 'gpsLocation'] +SELECT_COMPARE_FIELDS = { + 'yaw_rate': ['angularVelocityDevice', 'z'], + 'roll': ['orientationNED', 'x'], + 'inputs_flag': ['inputsOK'], + 'sensors_flag': ['sensorsOK'], +} +JUNK_IDX = 100 +CONSISTENT_SPIKES_COUNT = 10 + + +class Scenario(Enum): + BASE = 'base' + GYRO_OFF = 'gyro_off' + GYRO_SPIKE_MIDWAY = 'gyro_spike_midway' + GYRO_CONSISTENT_SPIKES = 'gyro_consistent_spikes' + ACCEL_OFF = 'accel_off' + ACCEL_SPIKE_MIDWAY = 'accel_spike_midway' + ACCEL_CONSISTENT_SPIKES = 'accel_consistent_spikes' + SENSOR_TIMING_SPIKE_MIDWAY = 'timing_spikes' + SENSOR_TIMING_CONSISTENT_SPIKES = 'timing_consistent_spikes' + + +def get_select_fields_data(logs): + def get_nested_keys(msg, keys): + val = None + for key in keys: + val = getattr(msg if val is None else val, key) if isinstance(key, str) else val[key] + return val + lp = [x.livePose for x in logs if x.which() == 'livePose'] + data = defaultdict(list) + for msg in lp: + for key, fields in SELECT_COMPARE_FIELDS.items(): + data[key].append(get_nested_keys(msg, fields)) + for key in data: + data[key] = np.array(data[key][JUNK_IDX:], dtype=float) + return data + + +def modify_logs_midway(logs, which, count, fn): + non_which = [x for x in logs if x.which() != which] + which = [x for x in logs if x.which() == which] + temps = which[len(which) // 2:len(which) // 2 + count] + for i, temp in enumerate(temps): + temp = temp.as_builder() + fn(temp) + which[len(which) // 2 + i] = temp.as_reader() + return sorted(non_which + which, key=lambda x: x.logMonoTime) + + +def run_scenarios(scenario, logs): + if scenario == Scenario.BASE: + pass + + elif scenario == Scenario.GYRO_OFF: + logs = sorted([x for x in logs if x.which() != 'gyroscope'], key=lambda x: x.logMonoTime) + + elif scenario == Scenario.GYRO_SPIKE_MIDWAY or scenario == Scenario.GYRO_CONSISTENT_SPIKES: + def gyro_spike(msg): + msg.gyroscope.gyroUncalibrated.v[0] += 3.0 + count = 1 if scenario == Scenario.GYRO_SPIKE_MIDWAY else CONSISTENT_SPIKES_COUNT + logs = modify_logs_midway(logs, 'gyroscope', count, gyro_spike) + + elif scenario == Scenario.ACCEL_OFF: + logs = sorted([x for x in logs if x.which() != 'accelerometer'], key=lambda x: x.logMonoTime) + + elif scenario == Scenario.ACCEL_SPIKE_MIDWAY or scenario == Scenario.ACCEL_CONSISTENT_SPIKES: + def acc_spike(msg): + msg.accelerometer.acceleration.v[0] += 100.0 + count = 1 if scenario == Scenario.ACCEL_SPIKE_MIDWAY else CONSISTENT_SPIKES_COUNT + logs = modify_logs_midway(logs, 'accelerometer', count, acc_spike) + + elif scenario == Scenario.SENSOR_TIMING_SPIKE_MIDWAY or scenario == Scenario.SENSOR_TIMING_CONSISTENT_SPIKES: + def timing_spike(msg): + msg.accelerometer.timestamp -= int(0.150 * 1e9) + count = 1 if scenario == Scenario.SENSOR_TIMING_SPIKE_MIDWAY else CONSISTENT_SPIKES_COUNT + logs = modify_logs_midway(logs, 'accelerometer', count, timing_spike) + + replayed_logs = replay_process_with_name(name='locationd', lr=logs) + return get_select_fields_data(logs), get_select_fields_data(replayed_logs) + + +class TestLocationdScenarios: + """ + Test locationd with different scenarios. In all these scenarios, we expect the following: + - locationd kalman filter should never go unstable (we care mostly about yaw_rate, roll, gpsOK, inputsOK, sensorsOK) + - faulty values should be ignored, with appropriate flags set + """ + + @classmethod + def setup_class(cls): + cls.logs = migrate_all(LogReader(TEST_ROUTE)) + + def test_base(self): + """ + Test: unchanged log + Expected Result: + - yaw_rate: unchanged + - roll: unchanged + """ + orig_data, replayed_data = run_scenarios(Scenario.BASE, self.logs) + assert np.allclose(orig_data['yaw_rate'], replayed_data['yaw_rate'], atol=np.radians(0.35)) + assert np.allclose(orig_data['roll'], replayed_data['roll'], atol=np.radians(0.55)) + + def test_gyro_off(self): + """ + Test: no gyroscope message for the entire segment + Expected Result: + - yaw_rate: 0 + - roll: 0 + - sensorsOK: False + """ + _, replayed_data = run_scenarios(Scenario.GYRO_OFF, self.logs) + assert np.allclose(replayed_data['yaw_rate'], 0.0) + assert np.allclose(replayed_data['roll'], 0.0) + assert np.all(replayed_data['sensors_flag'] == 0.0) + + def test_gyro_spike(self): + """ + Test: a gyroscope spike in the middle of the segment + Expected Result: + - yaw_rate: unchanged + - roll: unchanged + - inputsOK: False for some time after the spike, True for the rest + """ + orig_data, replayed_data = run_scenarios(Scenario.GYRO_SPIKE_MIDWAY, self.logs) + assert np.allclose(orig_data['yaw_rate'], replayed_data['yaw_rate'], atol=np.radians(0.35)) + assert np.allclose(orig_data['roll'], replayed_data['roll'], atol=np.radians(0.55)) + assert np.all(replayed_data['inputs_flag'] == orig_data['inputs_flag']) + assert np.all(replayed_data['sensors_flag'] == orig_data['sensors_flag']) + + def test_consistent_gyro_spikes(self): + """ + Test: consistent timing spikes for N gyroscope messages in the middle of the segment + Expected Result: inputsOK becomes False after N of bad measurements + """ + orig_data, replayed_data = run_scenarios(Scenario.GYRO_CONSISTENT_SPIKES, self.logs) + assert np.diff(replayed_data['inputs_flag'])[501] == -1.0 + assert np.diff(replayed_data['inputs_flag'])[708] == 1.0 + + def test_accel_off(self): + """ + Test: no accelerometer message for the entire segment + Expected Result: + - yaw_rate: 0 + - roll: 0 + - sensorsOK: False + """ + _, replayed_data = run_scenarios(Scenario.ACCEL_OFF, self.logs) + assert np.allclose(replayed_data['yaw_rate'], 0.0) + assert np.allclose(replayed_data['roll'], 0.0) + assert np.all(replayed_data['sensors_flag'] == 0.0) + + def test_accel_spike(self): + """ + ToDo: + Test: an accelerometer spike in the middle of the segment + Expected Result: Right now, the kalman filter is not robust to small spikes like it is to gyroscope spikes. + """ + orig_data, replayed_data = run_scenarios(Scenario.ACCEL_SPIKE_MIDWAY, self.logs) + assert np.allclose(orig_data['yaw_rate'], replayed_data['yaw_rate'], atol=np.radians(0.35)) + assert np.allclose(orig_data['roll'], replayed_data['roll'], atol=np.radians(0.55)) + + def test_single_timing_spike(self): + """ + Test: timing of 150ms off for the single accelerometer message in the middle of the segment + Expected Result: the message is ignored, and inputsOK is False for that time + """ + orig_data, replayed_data = run_scenarios(Scenario.SENSOR_TIMING_SPIKE_MIDWAY, self.logs) + assert np.all(replayed_data['inputs_flag'] == orig_data['inputs_flag']) + assert np.all(replayed_data['sensors_flag'] == orig_data['sensors_flag']) + + def test_consistent_timing_spikes(self): + """ + Test: consistent timing spikes for N accelerometer messages in the middle of the segment + Expected Result: inputsOK becomes False after N of bad measurements + """ + orig_data, replayed_data = run_scenarios(Scenario.SENSOR_TIMING_CONSISTENT_SPIKES, self.logs) + assert np.diff(replayed_data['inputs_flag'])[501] == -1.0 + assert np.diff(replayed_data['inputs_flag'])[707] == 1.0 diff --git a/selfdrive/locationd/test/test_paramsd.py b/selfdrive/locationd/test/test_paramsd.py new file mode 100644 index 0000000000..dd496b7675 --- /dev/null +++ b/selfdrive/locationd/test/test_paramsd.py @@ -0,0 +1,67 @@ +import random +import numpy as np + +from cereal import messaging +from openpilot.selfdrive.locationd.paramsd import retrieve_initial_vehicle_params, migrate_cached_vehicle_params_if_needed +from openpilot.selfdrive.locationd.models.car_kf import CarKalman +from openpilot.selfdrive.locationd.test.test_locationd_scenarios import TEST_ROUTE +from openpilot.selfdrive.test.process_replay.migration import migrate, migrate_carParams +from openpilot.common.params import Params +from openpilot.tools.lib.logreader import LogReader + + +def get_random_live_parameters(CP): + msg = messaging.new_message("liveParameters") + msg.liveParameters.steerRatio = (random.random() + 0.5) * CP.steerRatio + msg.liveParameters.stiffnessFactor = random.random() + msg.liveParameters.angleOffsetAverageDeg = random.random() + msg.liveParameters.debugFilterState.std = [random.random() for _ in range(CarKalman.P_initial.shape[0])] + return msg + + +class TestParamsd: + def test_read_saved_params(self): + params = Params() + + lr = migrate(LogReader(TEST_ROUTE), [migrate_carParams]) + CP = next(m for m in lr if m.which() == "carParams").carParams + + msg = get_random_live_parameters(CP) + params.put("LiveParametersV2", msg.to_bytes()) + params.put("CarParamsPrevRoute", CP.as_builder().to_bytes()) + + migrate_cached_vehicle_params_if_needed(params) # this is not tested here but should not mess anything up or throw an error + sr, sf, offset, p_init = retrieve_initial_vehicle_params(params, CP, replay=True, debug=True) + np.testing.assert_allclose(sr, msg.liveParameters.steerRatio) + np.testing.assert_allclose(sf, msg.liveParameters.stiffnessFactor) + np.testing.assert_allclose(offset, msg.liveParameters.angleOffsetAverageDeg) + np.testing.assert_equal(p_init.shape, CarKalman.P_initial.shape) + np.testing.assert_allclose(np.diagonal(p_init), msg.liveParameters.debugFilterState.std) + + # TODO Remove this test after the support for old format is removed + def test_read_saved_params_old_format(self): + params = Params() + + lr = migrate(LogReader(TEST_ROUTE), [migrate_carParams]) + CP = next(m for m in lr if m.which() == "carParams").carParams + + msg = get_random_live_parameters(CP) + params.put("LiveParameters", msg.liveParameters.to_dict()) + params.put("CarParamsPrevRoute", CP.as_builder().to_bytes()) + params.remove("LiveParametersV2") + + migrate_cached_vehicle_params_if_needed(params) + sr, sf, offset, _ = retrieve_initial_vehicle_params(params, CP, replay=True, debug=True) + np.testing.assert_allclose(sr, msg.liveParameters.steerRatio) + np.testing.assert_allclose(sf, msg.liveParameters.stiffnessFactor) + np.testing.assert_allclose(offset, msg.liveParameters.angleOffsetAverageDeg) + assert params.get("LiveParametersV2") is not None + + def test_read_saved_params_corrupted_old_format(self): + params = Params() + params.put("LiveParameters", {}) + params.remove("LiveParametersV2") + + migrate_cached_vehicle_params_if_needed(params) + assert params.get("LiveParameters") is None + assert params.get("LiveParametersV2") is None diff --git a/selfdrive/locationd/test/test_torqued.py b/selfdrive/locationd/test/test_torqued.py new file mode 100644 index 0000000000..53f3120c36 --- /dev/null +++ b/selfdrive/locationd/test/test_torqued.py @@ -0,0 +1,25 @@ +from cereal import car +from openpilot.selfdrive.locationd.torqued import TorqueEstimator + + +def test_cal_percent(): + est = TorqueEstimator(car.CarParams()) + msg = est.get_msg() + assert msg.liveTorqueParameters.calPerc == 0 + + for (low, high), min_pts in zip(est.filtered_points.buckets.keys(), + est.filtered_points.buckets_min_points.values(), strict=True): + for _ in range(int(min_pts)): + est.filtered_points.add_point((low + high) / 2.0, 0.0) + + # enough bucket points, but not enough total points + msg = est.get_msg() + assert msg.liveTorqueParameters.calPerc == (len(est.filtered_points) / est.min_points_total * 100 + 100) / 2 + + # add enough points to bucket with most capacity + key = list(est.filtered_points.buckets)[0] + for _ in range(est.min_points_total - len(est.filtered_points)): + est.filtered_points.add_point((key[0] + key[1]) / 2.0, 0.0) + + msg = est.get_msg() + assert msg.liveTorqueParameters.calPerc == 100 diff --git a/selfdrive/locationd/torqued.py b/selfdrive/locationd/torqued.py new file mode 100755 index 0000000000..3f9b846e82 --- /dev/null +++ b/selfdrive/locationd/torqued.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +import os +import numpy as np +from collections import deque, defaultdict + +import cereal.messaging as messaging +from cereal import car, log +from openpilot.common.constants import ACCELERATION_DUE_TO_GRAVITY +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process, DT_MDL +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.locationd.helpers import PointBuckets, ParameterEstimator, PoseCalibrator, Pose + +HISTORY = 5 # secs +POINTS_PER_BUCKET = 1500 +MIN_POINTS_TOTAL = 4000 +MIN_POINTS_TOTAL_QLOG = 600 +FIT_POINTS_TOTAL = 2000 +FIT_POINTS_TOTAL_QLOG = 600 +MIN_VEL = 15 # m/s +FRICTION_FACTOR = 1.5 # ~85% of data coverage +FACTOR_SANITY = 0.3 +FACTOR_SANITY_QLOG = 0.5 +FRICTION_SANITY = 0.5 +FRICTION_SANITY_QLOG = 0.8 +STEER_MIN_THRESHOLD = 0.02 +MIN_FILTER_DECAY = 50 +MAX_FILTER_DECAY = 250 +LAT_ACC_THRESHOLD = 1 +STEER_BUCKET_BOUNDS = [(-0.5, -0.3), (-0.3, -0.2), (-0.2, -0.1), (-0.1, 0), (0, 0.1), (0.1, 0.2), (0.2, 0.3), (0.3, 0.5)] +MIN_BUCKET_POINTS = np.array([100, 300, 500, 500, 500, 500, 300, 100]) +MIN_ENGAGE_BUFFER = 2 # secs + +VERSION = 1 # bump this to invalidate old parameter caches +ALLOWED_CARS = ['toyota', 'hyundai', 'rivian', 'honda'] + + +def slope2rot(slope): + sin = np.sqrt(slope ** 2 / (slope ** 2 + 1)) + cos = np.sqrt(1 / (slope ** 2 + 1)) + return np.array([[cos, -sin], [sin, cos]]) + + +class TorqueBuckets(PointBuckets): + def add_point(self, x, y): + for bound_min, bound_max in self.x_bounds: + if (x >= bound_min) and (x < bound_max): + self.buckets[(bound_min, bound_max)].append([x, 1.0, y]) + break + + +class TorqueEstimator(ParameterEstimator): + def __init__(self, CP, decimated=False, track_all_points=False): + self.hist_len = int(HISTORY / DT_MDL) + self.lag = 0.0 + self.track_all_points = track_all_points # for offline analysis, without max lateral accel or max steer torque filters + if decimated: + self.min_bucket_points = MIN_BUCKET_POINTS / 10 + self.min_points_total = MIN_POINTS_TOTAL_QLOG + self.fit_points = FIT_POINTS_TOTAL_QLOG + self.factor_sanity = FACTOR_SANITY_QLOG + self.friction_sanity = FRICTION_SANITY_QLOG + + else: + self.min_bucket_points = MIN_BUCKET_POINTS + self.min_points_total = MIN_POINTS_TOTAL + self.fit_points = FIT_POINTS_TOTAL + self.factor_sanity = FACTOR_SANITY + self.friction_sanity = FRICTION_SANITY + + self.offline_friction = 0.0 + self.offline_latAccelFactor = 0.0 + self.resets = 0.0 + self.use_params = CP.brand in ALLOWED_CARS and CP.lateralTuning.which() == 'torque' + + if CP.lateralTuning.which() == 'torque': + self.offline_friction = CP.lateralTuning.torque.friction + self.offline_latAccelFactor = CP.lateralTuning.torque.latAccelFactor + + self.calibrator = PoseCalibrator() + + self.reset() + + initial_params = { + 'latAccelFactor': self.offline_latAccelFactor, + 'latAccelOffset': 0.0, + 'frictionCoefficient': self.offline_friction, + 'points': [] + } + self.decay = MIN_FILTER_DECAY + self.min_lataccel_factor = (1.0 - self.factor_sanity) * self.offline_latAccelFactor + self.max_lataccel_factor = (1.0 + self.factor_sanity) * self.offline_latAccelFactor + self.min_friction = (1.0 - self.friction_sanity) * self.offline_friction + self.max_friction = (1.0 + self.friction_sanity) * self.offline_friction + + # try to restore cached params + params = Params() + params_cache = params.get("CarParamsPrevRoute") + torque_cache = params.get("LiveTorqueParameters") + if params_cache is not None and torque_cache is not None: + try: + with log.Event.from_bytes(torque_cache) as log_evt: + cache_ltp = log_evt.liveTorqueParameters + with car.CarParams.from_bytes(params_cache) as msg: + cache_CP = msg + if self.get_restore_key(cache_CP, cache_ltp.version) == self.get_restore_key(CP, VERSION): + if cache_ltp.liveValid: + initial_params = { + 'latAccelFactor': cache_ltp.latAccelFactorFiltered, + 'latAccelOffset': cache_ltp.latAccelOffsetFiltered, + 'frictionCoefficient': cache_ltp.frictionCoefficientFiltered + } + initial_params['points'] = cache_ltp.points + self.decay = cache_ltp.decay + self.filtered_points.load_points(initial_params['points']) + cloudlog.info("restored torque params from cache") + except Exception: + cloudlog.exception("failed to restore cached torque params") + params.remove("LiveTorqueParameters") + + self.filtered_params = {} + for param in initial_params: + self.filtered_params[param] = FirstOrderFilter(initial_params[param], self.decay, DT_MDL) + + @staticmethod + def get_restore_key(CP, version): + a, b = None, None + if CP.lateralTuning.which() == 'torque': + a = CP.lateralTuning.torque.friction + b = CP.lateralTuning.torque.latAccelFactor + return (CP.carFingerprint, CP.lateralTuning.which(), a, b, version) + + def reset(self): + self.resets += 1.0 + self.decay = MIN_FILTER_DECAY + self.raw_points = defaultdict(lambda: deque(maxlen=self.hist_len)) + self.filtered_points = TorqueBuckets(x_bounds=STEER_BUCKET_BOUNDS, + min_points=self.min_bucket_points, + min_points_total=self.min_points_total, + points_per_bucket=POINTS_PER_BUCKET, + rowsize=3) + self.all_torque_points = [] + + def estimate_params(self): + points = self.filtered_points.get_points(self.fit_points) + # total least square solution as both x and y are noisy observations + # this is empirically the slope of the hysteresis parallelogram as opposed to the line through the diagonals + try: + _, _, v = np.linalg.svd(points, full_matrices=False) + slope, offset = -v.T[0:2, 2] / v.T[2, 2] + _, spread = np.matmul(points[:, [0, 2]], slope2rot(slope)).T + friction_coeff = np.std(spread) * FRICTION_FACTOR + except np.linalg.LinAlgError as e: + cloudlog.exception(f"Error computing live torque params: {e}") + slope = offset = friction_coeff = np.nan + return slope, offset, friction_coeff + + def update_params(self, params): + self.decay = min(self.decay + DT_MDL, MAX_FILTER_DECAY) + for param, value in params.items(): + self.filtered_params[param].update(value) + self.filtered_params[param].update_alpha(self.decay) + + def handle_log(self, t, which, msg): + if which == "carControl": + self.raw_points["carControl_t"].append(t + self.lag) + self.raw_points["lat_active"].append(msg.latActive) + elif which == "carOutput": + self.raw_points["carOutput_t"].append(t + self.lag) + self.raw_points["steer_torque"].append(-msg.actuatorsOutput.torque) + elif which == "carState": + self.raw_points["carState_t"].append(t + self.lag) + # TODO: check if high aEgo affects resulting lateral accel + self.raw_points["vego"].append(msg.vEgo) + self.raw_points["steer_override"].append(msg.steeringPressed) + elif which == "liveCalibration": + self.calibrator.feed_live_calib(msg) + elif which == "liveDelay": + self.lag = msg.lateralDelay + # calculate lateral accel from past steering torque + elif which == "livePose": + if len(self.raw_points['steer_torque']) == self.hist_len: + device_pose = Pose.from_live_pose(msg) + calibrated_pose = self.calibrator.build_calibrated_pose(device_pose) + angular_velocity_calibrated = calibrated_pose.angular_velocity + + yaw_rate = angular_velocity_calibrated.yaw + roll = device_pose.orientation.roll + # check lat active up to now (without lag compensation) + lat_active = np.interp(np.arange(t - MIN_ENGAGE_BUFFER, t + self.lag, DT_MDL), + self.raw_points['carControl_t'], self.raw_points['lat_active']).astype(bool) + steer_override = np.interp(np.arange(t - MIN_ENGAGE_BUFFER, t + self.lag, DT_MDL), + self.raw_points['carState_t'], self.raw_points['steer_override']).astype(bool) + vego = np.interp(t, self.raw_points['carState_t'], self.raw_points['vego']) + steer = np.interp(t, self.raw_points['carOutput_t'], self.raw_points['steer_torque']).item() + lateral_acc = (vego * yaw_rate) - (np.sin(roll) * ACCELERATION_DUE_TO_GRAVITY).item() + if all(lat_active) and not any(steer_override) and (vego > MIN_VEL) and (abs(steer) > STEER_MIN_THRESHOLD): + if abs(lateral_acc) <= LAT_ACC_THRESHOLD: + self.filtered_points.add_point(steer, lateral_acc) + + if self.track_all_points: + self.all_torque_points.append([steer, lateral_acc]) + + def get_msg(self, valid=True, with_points=False): + msg = messaging.new_message('liveTorqueParameters') + msg.valid = valid + liveTorqueParameters = msg.liveTorqueParameters + liveTorqueParameters.version = VERSION + liveTorqueParameters.useParams = self.use_params + + # Calculate raw estimates when possible, only update filters when enough points are gathered + if self.filtered_points.is_calculable(): + latAccelFactor, latAccelOffset, frictionCoeff = self.estimate_params() + liveTorqueParameters.latAccelFactorRaw = float(latAccelFactor) + liveTorqueParameters.latAccelOffsetRaw = float(latAccelOffset) + liveTorqueParameters.frictionCoefficientRaw = float(frictionCoeff) + + if self.filtered_points.is_valid(): + if any(val is None or np.isnan(val) for val in [latAccelFactor, latAccelOffset, frictionCoeff]): + cloudlog.exception("Live torque parameters are invalid.") + liveTorqueParameters.liveValid = False + self.reset() + else: + liveTorqueParameters.liveValid = True + latAccelFactor = np.clip(latAccelFactor, self.min_lataccel_factor, self.max_lataccel_factor) + frictionCoeff = np.clip(frictionCoeff, self.min_friction, self.max_friction) + self.update_params({'latAccelFactor': latAccelFactor, 'latAccelOffset': latAccelOffset, 'frictionCoefficient': frictionCoeff}) + + if with_points: + liveTorqueParameters.points = self.filtered_points.get_points()[:, [0, 2]].tolist() + + liveTorqueParameters.latAccelFactorFiltered = float(self.filtered_params['latAccelFactor'].x) + liveTorqueParameters.latAccelOffsetFiltered = float(self.filtered_params['latAccelOffset'].x) + liveTorqueParameters.frictionCoefficientFiltered = float(self.filtered_params['frictionCoefficient'].x) + liveTorqueParameters.totalBucketPoints = len(self.filtered_points) + liveTorqueParameters.calPerc = self.filtered_points.get_valid_percent() + liveTorqueParameters.decay = self.decay + liveTorqueParameters.maxResets = self.resets + return msg + + +def main(demo=False): + config_realtime_process([0, 1, 2, 3], 5) + + DEBUG = bool(int(os.getenv("DEBUG", "0"))) + + pm = messaging.PubMaster(['liveTorqueParameters']) + sm = messaging.SubMaster(['carControl', 'carOutput', 'carState', 'liveCalibration', 'livePose', 'liveDelay'], poll='livePose') + + params = Params() + estimator = TorqueEstimator(messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams)) + + while True: + sm.update() + if sm.all_checks(): + for which in sm.updated.keys(): + if sm.updated[which]: + t = sm.logMonoTime[which] * 1e-9 + estimator.handle_log(t, which, sm[which]) + + # 4Hz driven by livePose + if sm.frame % 5 == 0: + pm.send('liveTorqueParameters', estimator.get_msg(valid=sm.all_checks(), with_points=DEBUG)) + + # Cache points every 60 seconds while onroad + if sm.frame % 240 == 0: + msg = estimator.get_msg(valid=sm.all_checks(), with_points=True) + params.put_nonblocking("LiveTorqueParameters", msg.to_bytes()) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description='Process the --demo argument.') + parser.add_argument('--demo', action='store_true', help='A boolean for demo mode.') + args = parser.parse_args() + main(demo=args.demo) diff --git a/selfdrive/modeld/SConscript b/selfdrive/modeld/SConscript new file mode 100644 index 0000000000..f20855c2cb --- /dev/null +++ b/selfdrive/modeld/SConscript @@ -0,0 +1,70 @@ +import os +import glob + +Import('env', 'envCython', 'arch', 'cereal', 'messaging', 'common', 'visionipc', 'transformations') +lenv = env.Clone() +lenvCython = envCython.Clone() + +libs = [cereal, messaging, visionipc, common, 'capnp', 'kj', 'pthread'] +frameworks = [] + +common_src = [ + "models/commonmodel.cc", + "transforms/loadyuv.cc", + "transforms/transform.cc", +] + +# OpenCL is a framework on Mac +if arch == "Darwin": + frameworks += ['OpenCL'] +else: + libs += ['OpenCL'] + +# Set path definitions +for pathdef, fn in {'TRANSFORM': 'transforms/transform.cl', 'LOADYUV': 'transforms/loadyuv.cl'}.items(): + for xenv in (lenv, lenvCython): + xenv['CXXFLAGS'].append(f'-D{pathdef}_PATH=\\"{File(fn).abspath}\\"') + +# Compile cython +cython_libs = envCython["LIBS"] + libs +commonmodel_lib = lenv.Library('commonmodel', common_src) +lenvCython.Program('models/commonmodel_pyx.so', 'models/commonmodel_pyx.pyx', LIBS=[commonmodel_lib, *cython_libs], FRAMEWORKS=frameworks) +tinygrad_files = ["#"+x for x in glob.glob(env.Dir("#tinygrad_repo").relpath + "/**", recursive=True, root_dir=env.Dir("#").abspath) if 'pycache' not in x] + +# Get model metadata +for model_name in ['driving_vision', 'driving_policy']: + fn = File(f"models/{model_name}").abspath + script_files = [File(Dir("#selfdrive/modeld").File("get_model_metadata.py").abspath)] + cmd = f'python3 {Dir("#selfdrive/modeld").abspath}/get_model_metadata.py {fn}.onnx' + lenv.Command(fn + "_metadata.pkl", [fn + ".onnx"] + tinygrad_files + script_files, cmd) + +def tg_compile(flags, model_name): + pythonpath_string = 'PYTHONPATH="${PYTHONPATH}:' + env.Dir("#tinygrad_repo").abspath + '"' + fn = File(f"models/{model_name}").abspath + return lenv.Command( + fn + "_tinygrad.pkl", + [fn + ".onnx"] + tinygrad_files, + f'{pythonpath_string} {flags} python3 {Dir("#tinygrad_repo").abspath}/examples/openpilot/compile3.py {fn}.onnx {fn}_tinygrad.pkl' + ) + +# Compile small models +for model_name in ['driving_vision', 'driving_policy', 'dmonitoring_model']: + flags = { + 'larch64': 'DEV=QCOM', + 'Darwin': f'DEV=CPU HOME={os.path.expanduser("~")} IMAGE=0', # tinygrad calls brew which needs a $HOME in the env + }.get(arch, 'DEV=CPU CPU_LLVM=1 IMAGE=0') + tg_compile(flags, model_name) + +# Compile BIG model if USB GPU is available +if "USBGPU" in os.environ: + import subprocess + # because tg doesn't support multi-process + devs = subprocess.check_output('python3 -c "from tinygrad import Device; print(list(Device.get_available_devices()))"', shell=True, cwd=env.Dir('#').abspath) + if b"AMD" in devs: + print("USB GPU detected... building") + flags = "DEV=AMD AMD_IFACE=USB AMD_LLVM=1 NOLOCALS=0 IMAGE=0" + bp = tg_compile(flags, "big_driving_policy") + bv = tg_compile(flags, "big_driving_vision") + lenv.SideEffect('lock', [bp, bv]) # tg doesn't support multi-process so build serially + else: + print("USB GPU not detected... skipping") diff --git a/selfdrive/modeld/__init__.py b/selfdrive/modeld/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/modeld/constants.py b/selfdrive/modeld/constants.py new file mode 100644 index 0000000000..ff7e1d8600 --- /dev/null +++ b/selfdrive/modeld/constants.py @@ -0,0 +1,87 @@ +import numpy as np + +def index_function(idx, max_val=192, max_idx=32): + return (max_val) * ((idx/max_idx)**2) + +class ModelConstants: + # time and distance indices + IDX_N = 33 + T_IDXS = [index_function(idx, max_val=10.0) for idx in range(IDX_N)] + X_IDXS = [index_function(idx, max_val=192.0) for idx in range(IDX_N)] + LEAD_T_IDXS = [0., 2., 4., 6., 8., 10.] + LEAD_T_OFFSETS = [0., 2., 4.] + META_T_IDXS = [2., 4., 6., 8., 10.] + + # model inputs constants + N_FRAMES = 2 + MODEL_RUN_FREQ = 20 + MODEL_CONTEXT_FREQ = 5 # "model_trained_fps" + + FEATURE_LEN = 512 + + DESIRE_LEN = 8 + TRAFFIC_CONVENTION_LEN = 2 + LAT_PLANNER_STATE_LEN = 4 + LATERAL_CONTROL_PARAMS_LEN = 2 + PREV_DESIRED_CURV_LEN = 1 + + # model outputs constants + FCW_THRESHOLDS_5MS2 = np.array([.05, .05, .15, .15, .15], dtype=np.float32) + FCW_THRESHOLDS_3MS2 = np.array([.7, .7], dtype=np.float32) + FCW_5MS2_PROBS_WIDTH = 5 + FCW_3MS2_PROBS_WIDTH = 2 + + DISENGAGE_WIDTH = 5 + POSE_WIDTH = 6 + WIDE_FROM_DEVICE_WIDTH = 3 + LEAD_WIDTH = 4 + LANE_LINES_WIDTH = 2 + ROAD_EDGES_WIDTH = 2 + PLAN_WIDTH = 15 + DESIRE_PRED_WIDTH = 8 + LAT_PLANNER_SOLUTION_WIDTH = 4 + DESIRED_CURV_WIDTH = 1 + + NUM_LANE_LINES = 4 + NUM_ROAD_EDGES = 2 + + LEAD_TRAJ_LEN = 6 + DESIRE_PRED_LEN = 4 + + PLAN_MHP_N = 5 + LEAD_MHP_N = 2 + PLAN_MHP_SELECTION = 1 + LEAD_MHP_SELECTION = 3 + + FCW_THRESHOLD_5MS2_HIGH = 0.15 + FCW_THRESHOLD_5MS2_LOW = 0.05 + FCW_THRESHOLD_3MS2 = 0.7 + + CONFIDENCE_BUFFER_LEN = 5 + RYG_GREEN = 0.01165 + RYG_YELLOW = 0.06157 + + POLY_PATH_DEGREE = 4 + +# model outputs slices +class Plan: + POSITION = slice(0, 3) + VELOCITY = slice(3, 6) + ACCELERATION = slice(6, 9) + T_FROM_CURRENT_EULER = slice(9, 12) + ORIENTATION_RATE = slice(12, 15) + +class Meta: + ENGAGED = slice(0, 1) + # next 2, 4, 6, 8, 10 seconds + GAS_DISENGAGE = slice(1, 31, 6) + BRAKE_DISENGAGE = slice(2, 31, 6) + STEER_OVERRIDE = slice(3, 31, 6) + HARD_BRAKE_3 = slice(4, 31, 6) + HARD_BRAKE_4 = slice(5, 31, 6) + HARD_BRAKE_5 = slice(6, 31, 6) + # next 0, 2, 4, 6, 8, 10 seconds + GAS_PRESS = slice(31, 55, 4) + BRAKE_PRESS = slice(32, 55, 4) + LEFT_BLINKER = slice(33, 55, 4) + RIGHT_BLINKER = slice(34, 55, 4) diff --git a/selfdrive/modeld/dmonitoringmodeld.py b/selfdrive/modeld/dmonitoringmodeld.py new file mode 100755 index 0000000000..2851a3e7da --- /dev/null +++ b/selfdrive/modeld/dmonitoringmodeld.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +import os +from openpilot.system.hardware import TICI +os.environ['DEV'] = 'QCOM' if TICI else 'CPU' +from tinygrad.tensor import Tensor +from tinygrad.dtype import dtypes +import math +import time +import pickle +import ctypes +import numpy as np +from pathlib import Path + +from cereal import messaging +from cereal.messaging import PubMaster, SubMaster +from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf +from openpilot.common.swaglog import cloudlog +from openpilot.common.realtime import config_realtime_process +from openpilot.common.transformations.model import dmonitoringmodel_intrinsics, DM_INPUT_SIZE +from openpilot.common.transformations.camera import _ar_ox_fisheye, _os_fisheye +from openpilot.selfdrive.modeld.models.commonmodel_pyx import CLContext, MonitoringModelFrame +from openpilot.selfdrive.modeld.parse_model_outputs import sigmoid +from openpilot.selfdrive.modeld.runners.tinygrad_helpers import qcom_tensor_from_opencl_address + +MODEL_WIDTH, MODEL_HEIGHT = DM_INPUT_SIZE +CALIB_LEN = 3 +FEATURE_LEN = 512 +OUTPUT_SIZE = 83 + FEATURE_LEN + +PROCESS_NAME = "selfdrive.modeld.dmonitoringmodeld" +SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') +MODEL_PKL_PATH = Path(__file__).parent / 'models/dmonitoring_model_tinygrad.pkl' + +# TODO: slice from meta +class DriverStateResult(ctypes.Structure): + _fields_ = [ + ("face_orientation", ctypes.c_float*3), + ("face_position", ctypes.c_float*3), + ("face_orientation_std", ctypes.c_float*3), + ("face_position_std", ctypes.c_float*3), + ("face_prob", ctypes.c_float), + ("_unused_a", ctypes.c_float*8), + ("left_eye_prob", ctypes.c_float), + ("_unused_b", ctypes.c_float*8), + ("right_eye_prob", ctypes.c_float), + ("left_blink_prob", ctypes.c_float), + ("right_blink_prob", ctypes.c_float), + ("sunglasses_prob", ctypes.c_float), + ("_unused_c", ctypes.c_float), + ("_unused_d", ctypes.c_float*4), + ("not_ready_prob", ctypes.c_float*2)] + + +class DMonitoringModelResult(ctypes.Structure): + _fields_ = [ + ("driver_state_lhd", DriverStateResult), + ("driver_state_rhd", DriverStateResult), + ("wheel_on_right_prob", ctypes.c_float), + ("features", ctypes.c_float*FEATURE_LEN)] + + +class ModelState: + inputs: dict[str, np.ndarray] + output: np.ndarray + + def __init__(self, cl_ctx): + assert ctypes.sizeof(DMonitoringModelResult) == OUTPUT_SIZE * ctypes.sizeof(ctypes.c_float) + + self.frame = MonitoringModelFrame(cl_ctx) + self.numpy_inputs = { + 'calib': np.zeros((1, CALIB_LEN), dtype=np.float32), + } + + self.tensor_inputs = {k: Tensor(v, device='NPY').realize() for k,v in self.numpy_inputs.items()} + with open(MODEL_PKL_PATH, "rb") as f: + self.model_run = pickle.load(f) + + def run(self, buf: VisionBuf, calib: np.ndarray, transform: np.ndarray) -> tuple[np.ndarray, float]: + self.numpy_inputs['calib'][0,:] = calib + + t1 = time.perf_counter() + + input_img_cl = self.frame.prepare(buf, transform.flatten()) + if TICI: + # The imgs tensors are backed by opencl memory, only need init once + if 'input_img' not in self.tensor_inputs: + self.tensor_inputs['input_img'] = qcom_tensor_from_opencl_address(input_img_cl.mem_address, (1, MODEL_WIDTH*MODEL_HEIGHT), dtype=dtypes.uint8) + else: + self.tensor_inputs['input_img'] = Tensor(self.frame.buffer_from_cl(input_img_cl).reshape((1, MODEL_WIDTH*MODEL_HEIGHT)), dtype=dtypes.uint8).realize() + + + output = self.model_run(**self.tensor_inputs).contiguous().realize().uop.base.buffer.numpy() + + t2 = time.perf_counter() + return output, t2 - t1 + + +def fill_driver_state(msg, ds_result: DriverStateResult): + msg.faceOrientation = list(ds_result.face_orientation) + msg.faceOrientationStd = [math.exp(x) for x in ds_result.face_orientation_std] + msg.facePosition = list(ds_result.face_position[:2]) + msg.facePositionStd = [math.exp(x) for x in ds_result.face_position_std[:2]] + msg.faceProb = float(sigmoid(ds_result.face_prob)) + msg.leftEyeProb = float(sigmoid(ds_result.left_eye_prob)) + msg.rightEyeProb = float(sigmoid(ds_result.right_eye_prob)) + msg.leftBlinkProb = float(sigmoid(ds_result.left_blink_prob)) + msg.rightBlinkProb = float(sigmoid(ds_result.right_blink_prob)) + msg.sunglassesProb = float(sigmoid(ds_result.sunglasses_prob)) + msg.notReadyProb = [float(sigmoid(x)) for x in ds_result.not_ready_prob] + + +def get_driverstate_packet(model_output: np.ndarray, frame_id: int, location_ts: int, execution_time: float, gpu_execution_time: float): + model_result = ctypes.cast(model_output.ctypes.data, ctypes.POINTER(DMonitoringModelResult)).contents + msg = messaging.new_message('driverStateV2', valid=True) + ds = msg.driverStateV2 + ds.frameId = frame_id + ds.modelExecutionTime = execution_time + ds.gpuExecutionTime = gpu_execution_time + ds.wheelOnRightProb = float(sigmoid(model_result.wheel_on_right_prob)) + ds.rawPredictions = model_output.tobytes() if SEND_RAW_PRED else b'' + fill_driver_state(ds.leftDriverData, model_result.driver_state_lhd) + fill_driver_state(ds.rightDriverData, model_result.driver_state_rhd) + return msg + + +def main(): + config_realtime_process(7, 5) + + cl_context = CLContext() + model = ModelState(cl_context) + cloudlog.warning("models loaded, dmonitoringmodeld starting") + + cloudlog.warning("connecting to driver stream") + vipc_client = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_DRIVER, True, cl_context) + while not vipc_client.connect(False): + time.sleep(0.1) + assert vipc_client.is_connected() + cloudlog.warning(f"connected with buffer size: {vipc_client.buffer_len}") + + sm = SubMaster(["liveCalibration"]) + pm = PubMaster(["driverStateV2"]) + + calib = np.zeros(CALIB_LEN, dtype=np.float32) + model_transform = None + + while True: + buf = vipc_client.recv() + if buf is None: + continue + + if model_transform is None: + cam = _os_fisheye if buf.width == _os_fisheye.width else _ar_ox_fisheye + model_transform = np.linalg.inv(np.dot(dmonitoringmodel_intrinsics, np.linalg.inv(cam.intrinsics))).astype(np.float32) + + sm.update(0) + if sm.updated["liveCalibration"]: + calib[:] = np.array(sm["liveCalibration"].rpyCalib) + + t1 = time.perf_counter() + model_output, gpu_execution_time = model.run(buf, calib, model_transform) + t2 = time.perf_counter() + + pm.send("driverStateV2", get_driverstate_packet(model_output, vipc_client.frame_id, vipc_client.timestamp_sof, t2 - t1, gpu_execution_time)) + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + cloudlog.warning("got SIGINT") diff --git a/selfdrive/modeld/fill_model_msg.py b/selfdrive/modeld/fill_model_msg.py new file mode 100644 index 0000000000..82c4c92b1d --- /dev/null +++ b/selfdrive/modeld/fill_model_msg.py @@ -0,0 +1,193 @@ +import os +import capnp +import numpy as np +from cereal import log +from openpilot.selfdrive.modeld.constants import ModelConstants, Plan, Meta + +SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') + +ConfidenceClass = log.ModelDataV2.ConfidenceClass + + +class PublishState: + def __init__(self): + self.disengage_buffer = np.zeros(ModelConstants.CONFIDENCE_BUFFER_LEN*ModelConstants.DISENGAGE_WIDTH, dtype=np.float32) + self.prev_brake_5ms2_probs = np.zeros(ModelConstants.FCW_5MS2_PROBS_WIDTH, dtype=np.float32) + self.prev_brake_3ms2_probs = np.zeros(ModelConstants.FCW_3MS2_PROBS_WIDTH, dtype=np.float32) + +def fill_xyzt(builder, t, x, y, z, x_std=None, y_std=None, z_std=None): + builder.t = t + builder.x = x.tolist() + builder.y = y.tolist() + builder.z = z.tolist() + if x_std is not None: + builder.xStd = x_std.tolist() + if y_std is not None: + builder.yStd = y_std.tolist() + if z_std is not None: + builder.zStd = z_std.tolist() + +def fill_xyvat(builder, t, x, y, v, a, x_std=None, y_std=None, v_std=None, a_std=None): + builder.t = t + builder.x = x.tolist() + builder.y = y.tolist() + builder.v = v.tolist() + builder.a = a.tolist() + if x_std is not None: + builder.xStd = x_std.tolist() + if y_std is not None: + builder.yStd = y_std.tolist() + if v_std is not None: + builder.vStd = v_std.tolist() + if a_std is not None: + builder.aStd = a_std.tolist() + +def fill_xyz_poly(builder, degree, x, y, z): + xyz = np.stack([x, y, z], axis=1) + coeffs = np.polynomial.polynomial.polyfit(ModelConstants.T_IDXS, xyz, deg=degree) + builder.xCoefficients = coeffs[:, 0].tolist() + builder.yCoefficients = coeffs[:, 1].tolist() + builder.zCoefficients = coeffs[:, 2].tolist() + +def fill_lane_line_meta(builder, lane_lines, lane_line_probs): + builder.leftY = lane_lines[1].y[0] + builder.leftProb = lane_line_probs[1] + builder.rightY = lane_lines[2].y[0] + builder.rightProb = lane_line_probs[2] + +def fill_model_msg(base_msg: capnp._DynamicStructBuilder, extended_msg: capnp._DynamicStructBuilder, + net_output_data: dict[str, np.ndarray], action: log.ModelDataV2.Action, + publish_state: PublishState, vipc_frame_id: int, vipc_frame_id_extra: int, + frame_id: int, frame_drop: float, timestamp_eof: int, model_execution_time: float, + valid: bool) -> None: + frame_age = frame_id - vipc_frame_id if frame_id > vipc_frame_id else 0 + frame_drop_perc = frame_drop * 100 + extended_msg.valid = valid + base_msg.valid = valid + + driving_model_data = base_msg.drivingModelData + + driving_model_data.frameId = vipc_frame_id + driving_model_data.frameIdExtra = vipc_frame_id_extra + driving_model_data.frameDropPerc = frame_drop_perc + driving_model_data.modelExecutionTime = model_execution_time + + driving_model_data.action = action + + modelV2 = extended_msg.modelV2 + modelV2.frameId = vipc_frame_id + modelV2.frameIdExtra = vipc_frame_id_extra + modelV2.frameAge = frame_age + modelV2.frameDropPerc = frame_drop_perc + modelV2.timestampEof = timestamp_eof + modelV2.modelExecutionTime = model_execution_time + + # plan + fill_xyzt(modelV2.position, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.POSITION].T, *net_output_data['plan_stds'][0,:,Plan.POSITION].T) + fill_xyzt(modelV2.velocity, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.VELOCITY].T) + fill_xyzt(modelV2.acceleration, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.ACCELERATION].T) + fill_xyzt(modelV2.orientation, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.T_FROM_CURRENT_EULER].T) + fill_xyzt(modelV2.orientationRate, ModelConstants.T_IDXS, *net_output_data['plan'][0,:,Plan.ORIENTATION_RATE].T) + + # poly path + fill_xyz_poly(driving_model_data.path, ModelConstants.POLY_PATH_DEGREE, *net_output_data['plan'][0,:,Plan.POSITION].T) + + # action + modelV2.action = action + + # times at X_IDXS of edges and lines aren't used + LINE_T_IDXS: list[float] = [] + + # lane lines + modelV2.init('laneLines', 4) + for i in range(4): + lane_line = modelV2.laneLines[i] + fill_xyzt(lane_line, LINE_T_IDXS, np.array(ModelConstants.X_IDXS), net_output_data['lane_lines'][0,i,:,0], net_output_data['lane_lines'][0,i,:,1]) + modelV2.laneLineStds = net_output_data['lane_lines_stds'][0,:,0,0].tolist() + modelV2.laneLineProbs = net_output_data['lane_lines_prob'][0,1::2].tolist() + + fill_lane_line_meta(driving_model_data.laneLineMeta, modelV2.laneLines, modelV2.laneLineProbs) + + # road edges + modelV2.init('roadEdges', 2) + for i in range(2): + road_edge = modelV2.roadEdges[i] + fill_xyzt(road_edge, LINE_T_IDXS, np.array(ModelConstants.X_IDXS), net_output_data['road_edges'][0,i,:,0], net_output_data['road_edges'][0,i,:,1]) + modelV2.roadEdgeStds = net_output_data['road_edges_stds'][0,:,0,0].tolist() + + # leads + modelV2.init('leadsV3', 3) + for i in range(3): + lead = modelV2.leadsV3[i] + fill_xyvat(lead, ModelConstants.LEAD_T_IDXS, *net_output_data['lead'][0,i].T, *net_output_data['lead_stds'][0,i].T) + lead.prob = net_output_data['lead_prob'][0,i].tolist() + lead.probTime = ModelConstants.LEAD_T_OFFSETS[i] + + # meta + meta = modelV2.meta + meta.desireState = net_output_data['desire_state'][0].reshape(-1).tolist() + meta.desirePrediction = net_output_data['desire_pred'][0].reshape(-1).tolist() + meta.engagedProb = net_output_data['meta'][0,Meta.ENGAGED].item() + meta.init('disengagePredictions') + disengage_predictions = meta.disengagePredictions + disengage_predictions.t = ModelConstants.META_T_IDXS + disengage_predictions.brakeDisengageProbs = net_output_data['meta'][0,Meta.BRAKE_DISENGAGE].tolist() + disengage_predictions.gasDisengageProbs = net_output_data['meta'][0,Meta.GAS_DISENGAGE].tolist() + disengage_predictions.steerOverrideProbs = net_output_data['meta'][0,Meta.STEER_OVERRIDE].tolist() + disengage_predictions.brake3MetersPerSecondSquaredProbs = net_output_data['meta'][0,Meta.HARD_BRAKE_3].tolist() + disengage_predictions.brake4MetersPerSecondSquaredProbs = net_output_data['meta'][0,Meta.HARD_BRAKE_4].tolist() + disengage_predictions.brake5MetersPerSecondSquaredProbs = net_output_data['meta'][0,Meta.HARD_BRAKE_5].tolist() + disengage_predictions.gasPressProbs = net_output_data['meta'][0,Meta.GAS_PRESS].tolist() + disengage_predictions.brakePressProbs = net_output_data['meta'][0,Meta.BRAKE_PRESS].tolist() + + publish_state.prev_brake_5ms2_probs[:-1] = publish_state.prev_brake_5ms2_probs[1:] + publish_state.prev_brake_5ms2_probs[-1] = net_output_data['meta'][0,Meta.HARD_BRAKE_5][0] + publish_state.prev_brake_3ms2_probs[:-1] = publish_state.prev_brake_3ms2_probs[1:] + publish_state.prev_brake_3ms2_probs[-1] = net_output_data['meta'][0,Meta.HARD_BRAKE_3][0] + hard_brake_predicted = (publish_state.prev_brake_5ms2_probs > ModelConstants.FCW_THRESHOLDS_5MS2).all() and \ + (publish_state.prev_brake_3ms2_probs > ModelConstants.FCW_THRESHOLDS_3MS2).all() + meta.hardBrakePredicted = hard_brake_predicted.item() + + # confidence + if vipc_frame_id % (2*ModelConstants.MODEL_RUN_FREQ) == 0: + # any disengage prob + brake_disengage_probs = net_output_data['meta'][0,Meta.BRAKE_DISENGAGE] + gas_disengage_probs = net_output_data['meta'][0,Meta.GAS_DISENGAGE] + steer_override_probs = net_output_data['meta'][0,Meta.STEER_OVERRIDE] + any_disengage_probs = 1-((1-brake_disengage_probs)*(1-gas_disengage_probs)*(1-steer_override_probs)) + # independent disengage prob for each 2s slice + ind_disengage_probs = np.r_[any_disengage_probs[0], np.diff(any_disengage_probs) / (1 - any_disengage_probs[:-1])] + # rolling buf for 2, 4, 6, 8, 10s + publish_state.disengage_buffer[:-ModelConstants.DISENGAGE_WIDTH] = publish_state.disengage_buffer[ModelConstants.DISENGAGE_WIDTH:] + publish_state.disengage_buffer[-ModelConstants.DISENGAGE_WIDTH:] = ind_disengage_probs + + score = 0. + for i in range(ModelConstants.DISENGAGE_WIDTH): + score += publish_state.disengage_buffer[i*ModelConstants.DISENGAGE_WIDTH+ModelConstants.DISENGAGE_WIDTH-1-i].item() / ModelConstants.DISENGAGE_WIDTH + if score < ModelConstants.RYG_GREEN: + modelV2.confidence = ConfidenceClass.green + elif score < ModelConstants.RYG_YELLOW: + modelV2.confidence = ConfidenceClass.yellow + else: + modelV2.confidence = ConfidenceClass.red + + # raw prediction if enabled + if SEND_RAW_PRED: + modelV2.rawPredictions = net_output_data['raw_pred'].tobytes() + +def fill_pose_msg(msg: capnp._DynamicStructBuilder, net_output_data: dict[str, np.ndarray], + vipc_frame_id: int, vipc_dropped_frames: int, timestamp_eof: int, live_calib_seen: bool) -> None: + msg.valid = live_calib_seen & (vipc_dropped_frames < 1) + cameraOdometry = msg.cameraOdometry + + cameraOdometry.frameId = vipc_frame_id + cameraOdometry.timestampEof = timestamp_eof + + cameraOdometry.trans = net_output_data['pose'][0,:3].tolist() + cameraOdometry.rot = net_output_data['pose'][0,3:].tolist() + cameraOdometry.wideFromDeviceEuler = net_output_data['wide_from_device_euler'][0,:].tolist() + cameraOdometry.roadTransformTrans = net_output_data['road_transform'][0,:3].tolist() + cameraOdometry.transStd = net_output_data['pose_stds'][0,:3].tolist() + cameraOdometry.rotStd = net_output_data['pose_stds'][0,3:].tolist() + cameraOdometry.wideFromDeviceEulerStd = net_output_data['wide_from_device_euler_stds'][0,:].tolist() + cameraOdometry.roadTransformTransStd = net_output_data['road_transform_stds'][0,:3].tolist() diff --git a/selfdrive/modeld/get_model_metadata.py b/selfdrive/modeld/get_model_metadata.py new file mode 100755 index 0000000000..2001d23d75 --- /dev/null +++ b/selfdrive/modeld/get_model_metadata.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +import sys +import pathlib +import onnx +import codecs +import pickle +from typing import Any + +def get_name_and_shape(value_info:onnx.ValueInfoProto) -> tuple[str, tuple[int,...]]: + shape = tuple([int(dim.dim_value) for dim in value_info.type.tensor_type.shape.dim]) + name = value_info.name + return name, shape + +def get_metadata_value_by_name(model:onnx.ModelProto, name:str) -> str | Any: + for prop in model.metadata_props: + if prop.key == name: + return prop.value + return None + +if __name__ == "__main__": + model_path = pathlib.Path(sys.argv[1]) + model = onnx.load(str(model_path)) + output_slices = get_metadata_value_by_name(model, 'output_slices') + assert output_slices is not None, 'output_slices not found in metadata' + + metadata = { + 'model_checkpoint': get_metadata_value_by_name(model, 'model_checkpoint'), + 'output_slices': pickle.loads(codecs.decode(output_slices.encode(), "base64")), + 'input_shapes': dict([get_name_and_shape(x) for x in model.graph.input]), + 'output_shapes': dict([get_name_and_shape(x) for x in model.graph.output]) + } + + metadata_path = model_path.parent / (model_path.stem + '_metadata.pkl') + with open(metadata_path, 'wb') as f: + pickle.dump(metadata, f) + + print(f'saved metadata to {metadata_path}') diff --git a/selfdrive/modeld/modeld.py b/selfdrive/modeld/modeld.py new file mode 100755 index 0000000000..006eeef6f5 --- /dev/null +++ b/selfdrive/modeld/modeld.py @@ -0,0 +1,411 @@ +#!/usr/bin/env python3 +import os +from openpilot.system.hardware import TICI +os.environ['DEV'] = 'QCOM' if TICI else 'CPU' +USBGPU = "USBGPU" in os.environ +if USBGPU: + os.environ['DEV'] = 'AMD' + os.environ['AMD_IFACE'] = 'USB' +from tinygrad.tensor import Tensor +from tinygrad.dtype import dtypes +import time +import pickle +import numpy as np +import cereal.messaging as messaging +from cereal import car, log +from pathlib import Path +from cereal.messaging import PubMaster, SubMaster +from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf +from opendbc.car.car_helpers import get_demo_car_params +from openpilot.common.swaglog import cloudlog +from openpilot.common.params import Params +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.realtime import config_realtime_process, DT_MDL +from openpilot.common.transformations.camera import DEVICE_CAMERAS +from openpilot.common.transformations.model import get_warp_matrix +from openpilot.selfdrive.controls.lib.desire_helper import DesireHelper +from openpilot.selfdrive.controls.lib.drive_helpers import get_accel_from_plan, smooth_value, get_curvature_from_plan +from openpilot.selfdrive.modeld.parse_model_outputs import Parser +from openpilot.selfdrive.modeld.fill_model_msg import fill_model_msg, fill_pose_msg, PublishState +from openpilot.selfdrive.modeld.constants import ModelConstants, Plan +from openpilot.selfdrive.modeld.models.commonmodel_pyx import DrivingModelFrame, CLContext +from openpilot.selfdrive.modeld.runners.tinygrad_helpers import qcom_tensor_from_opencl_address + + +PROCESS_NAME = "selfdrive.modeld.modeld" +SEND_RAW_PRED = os.getenv('SEND_RAW_PRED') + +VISION_PKL_PATH = Path(__file__).parent / 'models/driving_vision_tinygrad.pkl' +POLICY_PKL_PATH = Path(__file__).parent / 'models/driving_policy_tinygrad.pkl' +VISION_METADATA_PATH = Path(__file__).parent / 'models/driving_vision_metadata.pkl' +POLICY_METADATA_PATH = Path(__file__).parent / 'models/driving_policy_metadata.pkl' + +LAT_SMOOTH_SECONDS = 0.1 +LONG_SMOOTH_SECONDS = 0.3 +MIN_LAT_CONTROL_SPEED = 0.3 + + +def get_action_from_model(model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action, + lat_action_t: float, long_action_t: float, v_ego: float) -> log.ModelDataV2.Action: + plan = model_output['plan'][0] + desired_accel, should_stop = get_accel_from_plan(plan[:,Plan.VELOCITY][:,0], + plan[:,Plan.ACCELERATION][:,0], + ModelConstants.T_IDXS, + action_t=long_action_t) + desired_accel = smooth_value(desired_accel, prev_action.desiredAcceleration, LONG_SMOOTH_SECONDS) + + desired_curvature = get_curvature_from_plan(plan[:,Plan.T_FROM_CURRENT_EULER][:,2], + plan[:,Plan.ORIENTATION_RATE][:,2], + ModelConstants.T_IDXS, + v_ego, + lat_action_t) + if v_ego > MIN_LAT_CONTROL_SPEED: + desired_curvature = smooth_value(desired_curvature, prev_action.desiredCurvature, LAT_SMOOTH_SECONDS) + else: + desired_curvature = prev_action.desiredCurvature + + return log.ModelDataV2.Action(desiredCurvature=float(desired_curvature), + desiredAcceleration=float(desired_accel), + shouldStop=bool(should_stop)) + +class FrameMeta: + frame_id: int = 0 + timestamp_sof: int = 0 + timestamp_eof: int = 0 + + def __init__(self, vipc=None): + if vipc is not None: + self.frame_id, self.timestamp_sof, self.timestamp_eof = vipc.frame_id, vipc.timestamp_sof, vipc.timestamp_eof + +class InputQueues: + def __init__ (self, model_fps, env_fps, n_frames_input): + assert env_fps % model_fps == 0 + assert env_fps >= model_fps + self.model_fps = model_fps + self.env_fps = env_fps + self.n_frames_input = n_frames_input + + self.dtypes = {} + self.shapes = {} + self.q = {} + + def update_dtypes_and_shapes(self, input_dtypes, input_shapes) -> None: + self.dtypes.update(input_dtypes) + if self.env_fps == self.model_fps: + self.shapes.update(input_shapes) + else: + for k in input_shapes: + shape = list(input_shapes[k]) + if 'img' in k: + n_channels = shape[1] // self.n_frames_input + shape[1] = (self.env_fps // self.model_fps + (self.n_frames_input - 1)) * n_channels + else: + shape[1] = (self.env_fps // self.model_fps) * shape[1] + self.shapes[k] = tuple(shape) + + def reset(self) -> None: + self.q = {k: np.zeros(self.shapes[k], dtype=self.dtypes[k]) for k in self.dtypes.keys()} + + def enqueue(self, inputs:dict[str, np.ndarray]) -> None: + for k in inputs.keys(): + if inputs[k].dtype != self.dtypes[k]: + raise ValueError(f'supplied input <{k}({inputs[k].dtype})> has wrong dtype, expected {self.dtypes[k]}') + input_shape = list(self.shapes[k]) + input_shape[1] = -1 + single_input = inputs[k].reshape(tuple(input_shape)) + sz = single_input.shape[1] + self.q[k][:,:-sz] = self.q[k][:,sz:] + self.q[k][:,-sz:] = single_input + + def get(self, *names) -> dict[str, np.ndarray]: + if self.env_fps == self.model_fps: + return {k: self.q[k] for k in names} + else: + out = {} + for k in names: + shape = self.shapes[k] + if 'img' in k: + n_channels = shape[1] // (self.env_fps // self.model_fps + (self.n_frames_input - 1)) + out[k] = np.concatenate([self.q[k][:, s:s+n_channels] for s in np.linspace(0, shape[1] - n_channels, self.n_frames_input, dtype=int)], axis=1) + elif 'pulse' in k: + # any pulse within interval counts + out[k] = self.q[k].reshape((shape[0], shape[1] * self.model_fps // self.env_fps, self.env_fps // self.model_fps, -1)).max(axis=2) + else: + idxs = np.arange(-1, -shape[1], -self.env_fps // self.model_fps)[::-1] + out[k] = self.q[k][:, idxs] + return out + +class ModelState: + frames: dict[str, DrivingModelFrame] + inputs: dict[str, np.ndarray] + output: np.ndarray + prev_desire: np.ndarray # for tracking the rising edge of the pulse + + def __init__(self, context: CLContext): + with open(VISION_METADATA_PATH, 'rb') as f: + vision_metadata = pickle.load(f) + self.vision_input_shapes = vision_metadata['input_shapes'] + self.vision_input_names = list(self.vision_input_shapes.keys()) + self.vision_output_slices = vision_metadata['output_slices'] + vision_output_size = vision_metadata['output_shapes']['outputs'][1] + + with open(POLICY_METADATA_PATH, 'rb') as f: + policy_metadata = pickle.load(f) + self.policy_input_shapes = policy_metadata['input_shapes'] + self.policy_output_slices = policy_metadata['output_slices'] + policy_output_size = policy_metadata['output_shapes']['outputs'][1] + + self.frames = {name: DrivingModelFrame(context, ModelConstants.MODEL_RUN_FREQ//ModelConstants.MODEL_CONTEXT_FREQ) for name in self.vision_input_names} + self.prev_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) + + # policy inputs + self.numpy_inputs = {k: np.zeros(self.policy_input_shapes[k], dtype=np.float32) for k in self.policy_input_shapes} + self.full_input_queues = InputQueues(ModelConstants.MODEL_CONTEXT_FREQ, ModelConstants.MODEL_RUN_FREQ, ModelConstants.N_FRAMES) + for k in ['desire_pulse', 'features_buffer']: + self.full_input_queues.update_dtypes_and_shapes({k: self.numpy_inputs[k].dtype}, {k: self.numpy_inputs[k].shape}) + self.full_input_queues.reset() + + # img buffers are managed in openCL transform code + self.vision_inputs: dict[str, Tensor] = {} + self.vision_output = np.zeros(vision_output_size, dtype=np.float32) + self.policy_inputs = {k: Tensor(v, device='NPY').realize() for k,v in self.numpy_inputs.items()} + self.policy_output = np.zeros(policy_output_size, dtype=np.float32) + self.parser = Parser() + + with open(VISION_PKL_PATH, "rb") as f: + self.vision_run = pickle.load(f) + + with open(POLICY_PKL_PATH, "rb") as f: + self.policy_run = pickle.load(f) + + def slice_outputs(self, model_outputs: np.ndarray, output_slices: dict[str, slice]) -> dict[str, np.ndarray]: + parsed_model_outputs = {k: model_outputs[np.newaxis, v] for k,v in output_slices.items()} + return parsed_model_outputs + + def run(self, bufs: dict[str, VisionBuf], transforms: dict[str, np.ndarray], + inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None: + # Model decides when action is completed, so desire input is just a pulse triggered on rising edge + inputs['desire_pulse'][0] = 0 + new_desire = np.where(inputs['desire_pulse'] - self.prev_desire > .99, inputs['desire_pulse'], 0) + self.prev_desire[:] = inputs['desire_pulse'] + + imgs_cl = {name: self.frames[name].prepare(bufs[name], transforms[name].flatten()) for name in self.vision_input_names} + + if TICI and not USBGPU: + # The imgs tensors are backed by opencl memory, only need init once + for key in imgs_cl: + if key not in self.vision_inputs: + self.vision_inputs[key] = qcom_tensor_from_opencl_address(imgs_cl[key].mem_address, self.vision_input_shapes[key], dtype=dtypes.uint8) + else: + for key in imgs_cl: + frame_input = self.frames[key].buffer_from_cl(imgs_cl[key]).reshape(self.vision_input_shapes[key]) + self.vision_inputs[key] = Tensor(frame_input, dtype=dtypes.uint8).realize() + + if prepare_only: + return None + + self.vision_output = self.vision_run(**self.vision_inputs).contiguous().realize().uop.base.buffer.numpy() + vision_outputs_dict = self.parser.parse_vision_outputs(self.slice_outputs(self.vision_output, self.vision_output_slices)) + + self.full_input_queues.enqueue({'features_buffer': vision_outputs_dict['hidden_state'], 'desire_pulse': new_desire}) + for k in ['desire_pulse', 'features_buffer']: + self.numpy_inputs[k][:] = self.full_input_queues.get(k)[k] + self.numpy_inputs['traffic_convention'][:] = inputs['traffic_convention'] + + self.policy_output = self.policy_run(**self.policy_inputs).contiguous().realize().uop.base.buffer.numpy() + policy_outputs_dict = self.parser.parse_policy_outputs(self.slice_outputs(self.policy_output, self.policy_output_slices)) + + combined_outputs_dict = {**vision_outputs_dict, **policy_outputs_dict} + if SEND_RAW_PRED: + combined_outputs_dict['raw_pred'] = np.concatenate([self.vision_output.copy(), self.policy_output.copy()]) + + return combined_outputs_dict + + +def main(demo=False): + cloudlog.warning("modeld init") + + if not USBGPU: + # USB GPU currently saturates a core so can't do this yet, + # also need to move the aux USB interrupts for good timings + config_realtime_process(7, 54) + + st = time.monotonic() + cloudlog.warning("setting up CL context") + cl_context = CLContext() + cloudlog.warning("CL context ready; loading model") + model = ModelState(cl_context) + cloudlog.warning(f"models loaded in {time.monotonic() - st:.1f}s, modeld starting") + + # visionipc clients + while True: + available_streams = VisionIpcClient.available_streams("camerad", block=False) + if available_streams: + use_extra_client = VisionStreamType.VISION_STREAM_WIDE_ROAD in available_streams and VisionStreamType.VISION_STREAM_ROAD in available_streams + main_wide_camera = VisionStreamType.VISION_STREAM_ROAD not in available_streams + break + time.sleep(.1) + + vipc_client_main_stream = VisionStreamType.VISION_STREAM_WIDE_ROAD if main_wide_camera else VisionStreamType.VISION_STREAM_ROAD + vipc_client_main = VisionIpcClient("camerad", vipc_client_main_stream, True, cl_context) + vipc_client_extra = VisionIpcClient("camerad", VisionStreamType.VISION_STREAM_WIDE_ROAD, False, cl_context) + cloudlog.warning(f"vision stream set up, main_wide_camera: {main_wide_camera}, use_extra_client: {use_extra_client}") + + while not vipc_client_main.connect(False): + time.sleep(0.1) + while use_extra_client and not vipc_client_extra.connect(False): + time.sleep(0.1) + + cloudlog.warning(f"connected main cam with buffer size: {vipc_client_main.buffer_len} ({vipc_client_main.width} x {vipc_client_main.height})") + if use_extra_client: + cloudlog.warning(f"connected extra cam with buffer size: {vipc_client_extra.buffer_len} ({vipc_client_extra.width} x {vipc_client_extra.height})") + + # messaging + pm = PubMaster(["modelV2", "drivingModelData", "cameraOdometry"]) + sm = SubMaster(["deviceState", "carState", "roadCameraState", "liveCalibration", "driverMonitoringState", "carControl", "liveDelay"]) + + publish_state = PublishState() + params = Params() + + # setup filter to track dropped frames + frame_dropped_filter = FirstOrderFilter(0., 10., 1. / ModelConstants.MODEL_RUN_FREQ) + frame_id = 0 + last_vipc_frame_id = 0 + run_count = 0 + + model_transform_main = np.zeros((3, 3), dtype=np.float32) + model_transform_extra = np.zeros((3, 3), dtype=np.float32) + live_calib_seen = False + buf_main, buf_extra = None, None + meta_main = FrameMeta() + meta_extra = FrameMeta() + + + if demo: + CP = get_demo_car_params() + else: + CP = messaging.log_from_bytes(params.get("CarParams", block=True), car.CarParams) + cloudlog.info("modeld got CarParams: %s", CP.brand) + + # TODO this needs more thought, use .2s extra for now to estimate other delays + # TODO Move smooth seconds to action function + long_delay = CP.longitudinalActuatorDelay + LONG_SMOOTH_SECONDS + prev_action = log.ModelDataV2.Action() + + DH = DesireHelper() + + while True: + # Keep receiving frames until we are at least 1 frame ahead of previous extra frame + while meta_main.timestamp_sof < meta_extra.timestamp_sof + 25000000: + buf_main = vipc_client_main.recv() + meta_main = FrameMeta(vipc_client_main) + if buf_main is None: + break + + if buf_main is None: + cloudlog.debug("vipc_client_main no frame") + continue + + if use_extra_client: + # Keep receiving extra frames until frame id matches main camera + while True: + buf_extra = vipc_client_extra.recv() + meta_extra = FrameMeta(vipc_client_extra) + if buf_extra is None or meta_main.timestamp_sof < meta_extra.timestamp_sof + 25000000: + break + + if buf_extra is None: + cloudlog.debug("vipc_client_extra no frame") + continue + + if abs(meta_main.timestamp_sof - meta_extra.timestamp_sof) > 10000000: + cloudlog.error(f"frames out of sync! main: {meta_main.frame_id} ({meta_main.timestamp_sof / 1e9:.5f}),\ + extra: {meta_extra.frame_id} ({meta_extra.timestamp_sof / 1e9:.5f})") + + else: + # Use single camera + buf_extra = buf_main + meta_extra = meta_main + + sm.update(0) + desire = DH.desire + is_rhd = sm["driverMonitoringState"].isRHD + frame_id = sm["roadCameraState"].frameId + v_ego = max(sm["carState"].vEgo, 0.) + lat_delay = sm["liveDelay"].lateralDelay + LAT_SMOOTH_SECONDS + if sm.updated["liveCalibration"] and sm.seen['roadCameraState'] and sm.seen['deviceState']: + device_from_calib_euler = np.array(sm["liveCalibration"].rpyCalib, dtype=np.float32) + dc = DEVICE_CAMERAS[(str(sm['deviceState'].deviceType), str(sm['roadCameraState'].sensor))] + model_transform_main = get_warp_matrix(device_from_calib_euler, dc.ecam.intrinsics if main_wide_camera else dc.fcam.intrinsics, False).astype(np.float32) + model_transform_extra = get_warp_matrix(device_from_calib_euler, dc.ecam.intrinsics, True).astype(np.float32) + live_calib_seen = True + + traffic_convention = np.zeros(2) + traffic_convention[int(is_rhd)] = 1 + + vec_desire = np.zeros(ModelConstants.DESIRE_LEN, dtype=np.float32) + if desire >= 0 and desire < ModelConstants.DESIRE_LEN: + vec_desire[desire] = 1 + + # tracked dropped frames + vipc_dropped_frames = max(0, meta_main.frame_id - last_vipc_frame_id - 1) + frames_dropped = frame_dropped_filter.update(min(vipc_dropped_frames, 10)) + if run_count < 10: # let frame drops warm up + frame_dropped_filter.x = 0. + frames_dropped = 0. + run_count = run_count + 1 + + frame_drop_ratio = frames_dropped / (1 + frames_dropped) + prepare_only = vipc_dropped_frames > 0 + if prepare_only: + cloudlog.error(f"skipping model eval. Dropped {vipc_dropped_frames} frames") + + bufs = {name: buf_extra if 'big' in name else buf_main for name in model.vision_input_names} + transforms = {name: model_transform_extra if 'big' in name else model_transform_main for name in model.vision_input_names} + inputs:dict[str, np.ndarray] = { + 'desire_pulse': vec_desire, + 'traffic_convention': traffic_convention, + } + + mt1 = time.perf_counter() + model_output = model.run(bufs, transforms, inputs, prepare_only) + mt2 = time.perf_counter() + model_execution_time = mt2 - mt1 + + if model_output is not None: + modelv2_send = messaging.new_message('modelV2') + drivingdata_send = messaging.new_message('drivingModelData') + posenet_send = messaging.new_message('cameraOdometry') + + action = get_action_from_model(model_output, prev_action, lat_delay + DT_MDL, long_delay + DT_MDL, v_ego) + prev_action = action + fill_model_msg(drivingdata_send, modelv2_send, model_output, action, + publish_state, meta_main.frame_id, meta_extra.frame_id, frame_id, + frame_drop_ratio, meta_main.timestamp_eof, model_execution_time, live_calib_seen) + + desire_state = modelv2_send.modelV2.meta.desireState + l_lane_change_prob = desire_state[log.Desire.laneChangeLeft] + r_lane_change_prob = desire_state[log.Desire.laneChangeRight] + lane_change_prob = l_lane_change_prob + r_lane_change_prob + DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob) + modelv2_send.modelV2.meta.laneChangeState = DH.lane_change_state + modelv2_send.modelV2.meta.laneChangeDirection = DH.lane_change_direction + drivingdata_send.drivingModelData.meta.laneChangeState = DH.lane_change_state + drivingdata_send.drivingModelData.meta.laneChangeDirection = DH.lane_change_direction + + fill_pose_msg(posenet_send, model_output, meta_main.frame_id, vipc_dropped_frames, meta_main.timestamp_eof, live_calib_seen) + pm.send('modelV2', modelv2_send) + pm.send('drivingModelData', drivingdata_send) + pm.send('cameraOdometry', posenet_send) + last_vipc_frame_id = meta_main.frame_id + + +if __name__ == "__main__": + try: + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--demo', action='store_true', help='A boolean for demo mode.') + args = parser.parse_args() + main(demo=args.demo) + except KeyboardInterrupt: + cloudlog.warning("got SIGINT") diff --git a/selfdrive/modeld/models/README.md b/selfdrive/modeld/models/README.md new file mode 100644 index 0000000000..04b69c61c3 --- /dev/null +++ b/selfdrive/modeld/models/README.md @@ -0,0 +1,66 @@ +## Neural networks in openpilot +To view the architecture of the ONNX networks, you can use [netron](https://netron.app/) + +## Driving Model (vision model + temporal policy model) +### Vision inputs (Full size: 799906 x float32) +* **image stream** + * Two consecutive images (256 * 512 * 3 in RGB) recorded at 20 Hz : 393216 = 2 * 6 * 128 * 256 + * Each 256 * 512 image is represented in YUV420 with 6 channels : 6 * 128 * 256 + * Channels 0,1,2,3 represent the full-res Y channel and are represented in numpy as Y[::2, ::2], Y[::2, 1::2], Y[1::2, ::2], and Y[1::2, 1::2] + * Channel 4 represents the half-res U channel + * Channel 5 represents the half-res V channel +* **wide image stream** + * Two consecutive images (256 * 512 * 3 in RGB) recorded at 20 Hz : 393216 = 2 * 6 * 128 * 256 + * Each 256 * 512 image is represented in YUV420 with 6 channels : 6 * 128 * 256 + * Channels 0,1,2,3 represent the full-res Y channel and are represented in numpy as Y[::2, ::2], Y[::2, 1::2], Y[1::2, ::2], and Y[1::2, 1::2] + * Channel 4 represents the half-res U channel + * Channel 5 represents the half-res V channel +### Policy inputs +* **desire** + * one-hot encoded buffer to command model to execute certain actions, bit needs to be sent for the past 5 seconds (at 20FPS) : 100 * 8 +* **traffic convention** + * one-hot encoded vector to tell model whether traffic is right-hand or left-hand traffic : 2 +* **lateral control params** + * speed and steering delay for predicting the desired curvature: 2 +* **previous desired curvatures** + * vector of previously predicted desired curvatures: 100 * 1 +* **feature buffer** + * a buffer of intermediate features including the current feature to form a 5 seconds temporal context (at 20FPS) : 100 * 512 + + +### Driving Model output format (Full size: XXX x float32) +Refer to **slice_outputs** and **parse_vision_outputs/parse_policy_outputs** in modeld. + + +## Driver Monitoring Model +* .onnx model can be run with onnx runtimes +* .dlc file is a pre-quantized model and only runs on qualcomm DSPs + +### input format +* single image W = 1440 H = 960 luminance channel (Y) from the planar YUV420 format: + * full input size is 1440 * 960 = 1382400 + * normalized ranging from 0.0 to 1.0 in float32 (onnx runner) or ranging from 0 to 255 in uint8 (snpe runner) +* camera calibration angles (roll, pitch, yaw) from liveCalibration: 3 x float32 inputs + +### output format +* 84 x float32 outputs = 2 + 41 * 2 ([parsing example](https://github.com/commaai/openpilot/blob/22ce4e17ba0d3bfcf37f8255a4dd1dc683fe0c38/selfdrive/modeld/models/dmonitoring.cc#L33)) + * for each person in the front seats (2 * 41) + * face pose: 12 = 6 + 6 + * face orientation [pitch, yaw, roll] in camera frame: 3 + * face position [dx, dy] relative to image center: 2 + * normalized face size: 1 + * standard deviations for above outputs: 6 + * face visible probability: 1 + * eyes: 20 = (8 + 1) + (8 + 1) + 1 + 1 + * eye position and size, and their standard deviations: 8 + * eye visible probability: 1 + * eye closed probability: 1 + * wearing sunglasses probability: 1 + * face occluded probability: 1 + * touching wheel probability: 1 + * paying attention probability: 1 + * (deprecated) distracted probabilities: 2 + * using phone probability: 1 + * distracted probability: 1 + * common outputs 1 + * left hand drive probability: 1 diff --git a/selfdrive/modeld/models/__init__.py b/selfdrive/modeld/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/modeld/models/big_driving_policy.onnx b/selfdrive/modeld/models/big_driving_policy.onnx new file mode 120000 index 0000000000..e1b653a14a --- /dev/null +++ b/selfdrive/modeld/models/big_driving_policy.onnx @@ -0,0 +1 @@ +driving_policy.onnx \ No newline at end of file diff --git a/selfdrive/modeld/models/big_driving_vision.onnx b/selfdrive/modeld/models/big_driving_vision.onnx new file mode 120000 index 0000000000..28ee71dd74 --- /dev/null +++ b/selfdrive/modeld/models/big_driving_vision.onnx @@ -0,0 +1 @@ +driving_vision.onnx \ No newline at end of file diff --git a/selfdrive/modeld/models/commonmodel.cc b/selfdrive/modeld/models/commonmodel.cc new file mode 100644 index 0000000000..d3341e76ec --- /dev/null +++ b/selfdrive/modeld/models/commonmodel.cc @@ -0,0 +1,64 @@ +#include "selfdrive/modeld/models/commonmodel.h" + +#include +#include + +#include "common/clutil.h" + +DrivingModelFrame::DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip) : ModelFrame(device_id, context) { + input_frames = std::make_unique(buf_size); + temporal_skip = _temporal_skip; + input_frames_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); + img_buffer_20hz_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (temporal_skip+1)*frame_size_bytes, NULL, &err)); + region.origin = temporal_skip * frame_size_bytes; + region.size = frame_size_bytes; + last_img_cl = CL_CHECK_ERR(clCreateSubBuffer(img_buffer_20hz_cl, CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®ion, &err)); + + loadyuv_init(&loadyuv, context, device_id, MODEL_WIDTH, MODEL_HEIGHT); + init_transform(device_id, context, MODEL_WIDTH, MODEL_HEIGHT); +} + +cl_mem* DrivingModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { + run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); + + for (int i = 0; i < temporal_skip; i++) { + CL_CHECK(clEnqueueCopyBuffer(q, img_buffer_20hz_cl, img_buffer_20hz_cl, (i+1)*frame_size_bytes, i*frame_size_bytes, frame_size_bytes, 0, nullptr, nullptr)); + } + loadyuv_queue(&loadyuv, q, y_cl, u_cl, v_cl, last_img_cl); + + copy_queue(&loadyuv, q, img_buffer_20hz_cl, input_frames_cl, 0, 0, frame_size_bytes); + copy_queue(&loadyuv, q, last_img_cl, input_frames_cl, 0, frame_size_bytes, frame_size_bytes); + + // NOTE: Since thneed is using a different command queue, this clFinish is needed to ensure the image is ready. + clFinish(q); + return &input_frames_cl; +} + +DrivingModelFrame::~DrivingModelFrame() { + deinit_transform(); + loadyuv_destroy(&loadyuv); + CL_CHECK(clReleaseMemObject(input_frames_cl)); + CL_CHECK(clReleaseMemObject(img_buffer_20hz_cl)); + CL_CHECK(clReleaseMemObject(last_img_cl)); + CL_CHECK(clReleaseCommandQueue(q)); +} + + +MonitoringModelFrame::MonitoringModelFrame(cl_device_id device_id, cl_context context) : ModelFrame(device_id, context) { + input_frames = std::make_unique(buf_size); + input_frame_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, buf_size, NULL, &err)); + + init_transform(device_id, context, MODEL_WIDTH, MODEL_HEIGHT); +} + +cl_mem* MonitoringModelFrame::prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { + run_transform(yuv_cl, MODEL_WIDTH, MODEL_HEIGHT, frame_width, frame_height, frame_stride, frame_uv_offset, projection); + clFinish(q); + return &y_cl; +} + +MonitoringModelFrame::~MonitoringModelFrame() { + deinit_transform(); + CL_CHECK(clReleaseMemObject(input_frame_cl)); + CL_CHECK(clReleaseCommandQueue(q)); +} diff --git a/selfdrive/modeld/models/commonmodel.h b/selfdrive/modeld/models/commonmodel.h new file mode 100644 index 0000000000..176d7eb6dc --- /dev/null +++ b/selfdrive/modeld/models/commonmodel.h @@ -0,0 +1,97 @@ +#pragma once + +#include +#include +#include + +#include + +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include "common/mat.h" +#include "selfdrive/modeld/transforms/loadyuv.h" +#include "selfdrive/modeld/transforms/transform.h" + +class ModelFrame { +public: + ModelFrame(cl_device_id device_id, cl_context context) { + q = CL_CHECK_ERR(clCreateCommandQueue(context, device_id, 0, &err)); + } + virtual ~ModelFrame() {} + virtual cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { return NULL; } + uint8_t* buffer_from_cl(cl_mem *in_frames, int buffer_size) { + CL_CHECK(clEnqueueReadBuffer(q, *in_frames, CL_TRUE, 0, buffer_size, input_frames.get(), 0, nullptr, nullptr)); + clFinish(q); + return &input_frames[0]; + } + + int MODEL_WIDTH; + int MODEL_HEIGHT; + int MODEL_FRAME_SIZE; + int buf_size; + +protected: + cl_mem y_cl, u_cl, v_cl; + Transform transform; + cl_command_queue q; + std::unique_ptr input_frames; + + void init_transform(cl_device_id device_id, cl_context context, int model_width, int model_height) { + y_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, model_width * model_height, NULL, &err)); + u_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (model_width / 2) * (model_height / 2), NULL, &err)); + v_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (model_width / 2) * (model_height / 2), NULL, &err)); + transform_init(&transform, context, device_id); + } + + void deinit_transform() { + transform_destroy(&transform); + CL_CHECK(clReleaseMemObject(v_cl)); + CL_CHECK(clReleaseMemObject(u_cl)); + CL_CHECK(clReleaseMemObject(y_cl)); + } + + void run_transform(cl_mem yuv_cl, int model_width, int model_height, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection) { + transform_queue(&transform, q, + yuv_cl, frame_width, frame_height, frame_stride, frame_uv_offset, + y_cl, u_cl, v_cl, model_width, model_height, projection); + } +}; + +class DrivingModelFrame : public ModelFrame { +public: + DrivingModelFrame(cl_device_id device_id, cl_context context, int _temporal_skip); + ~DrivingModelFrame(); + cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection); + + const int MODEL_WIDTH = 512; + const int MODEL_HEIGHT = 256; + const int MODEL_FRAME_SIZE = MODEL_WIDTH * MODEL_HEIGHT * 3 / 2; + const int buf_size = MODEL_FRAME_SIZE * 2; // 2 frames are temporal_skip frames apart + const size_t frame_size_bytes = MODEL_FRAME_SIZE * sizeof(uint8_t); + +private: + LoadYUVState loadyuv; + cl_mem img_buffer_20hz_cl, last_img_cl, input_frames_cl; + cl_buffer_region region; + int temporal_skip; +}; + +class MonitoringModelFrame : public ModelFrame { +public: + MonitoringModelFrame(cl_device_id device_id, cl_context context); + ~MonitoringModelFrame(); + cl_mem* prepare(cl_mem yuv_cl, int frame_width, int frame_height, int frame_stride, int frame_uv_offset, const mat3& projection); + + const int MODEL_WIDTH = 1440; + const int MODEL_HEIGHT = 960; + const int MODEL_FRAME_SIZE = MODEL_WIDTH * MODEL_HEIGHT; + const int buf_size = MODEL_FRAME_SIZE; + +private: + cl_mem input_frame_cl; +}; diff --git a/selfdrive/modeld/models/commonmodel.pxd b/selfdrive/modeld/models/commonmodel.pxd new file mode 100644 index 0000000000..4ac64d9172 --- /dev/null +++ b/selfdrive/modeld/models/commonmodel.pxd @@ -0,0 +1,27 @@ +# distutils: language = c++ + +from msgq.visionipc.visionipc cimport cl_device_id, cl_context, cl_mem + +cdef extern from "common/mat.h": + cdef struct mat3: + float v[9] + +cdef extern from "common/clutil.h": + cdef unsigned long CL_DEVICE_TYPE_DEFAULT + cl_device_id cl_get_device_id(unsigned long) + cl_context cl_create_context(cl_device_id) + void cl_release_context(cl_context) + +cdef extern from "selfdrive/modeld/models/commonmodel.h": + cppclass ModelFrame: + int buf_size + unsigned char * buffer_from_cl(cl_mem*, int); + cl_mem * prepare(cl_mem, int, int, int, int, mat3) + + cppclass DrivingModelFrame: + int buf_size + DrivingModelFrame(cl_device_id, cl_context, int) + + cppclass MonitoringModelFrame: + int buf_size + MonitoringModelFrame(cl_device_id, cl_context) diff --git a/selfdrive/modeld/models/commonmodel_pyx.pxd b/selfdrive/modeld/models/commonmodel_pyx.pxd new file mode 100644 index 0000000000..0bb798625b --- /dev/null +++ b/selfdrive/modeld/models/commonmodel_pyx.pxd @@ -0,0 +1,13 @@ +# distutils: language = c++ + +from msgq.visionipc.visionipc cimport cl_mem +from msgq.visionipc.visionipc_pyx cimport CLContext as BaseCLContext + +cdef class CLContext(BaseCLContext): + pass + +cdef class CLMem: + cdef cl_mem * mem + + @staticmethod + cdef create(void*) diff --git a/selfdrive/modeld/models/commonmodel_pyx.pyx b/selfdrive/modeld/models/commonmodel_pyx.pyx new file mode 100644 index 0000000000..5b7d11bc71 --- /dev/null +++ b/selfdrive/modeld/models/commonmodel_pyx.pyx @@ -0,0 +1,74 @@ +# distutils: language = c++ +# cython: c_string_encoding=ascii, language_level=3 + +import numpy as np +cimport numpy as cnp +from libc.string cimport memcpy +from libc.stdint cimport uintptr_t + +from msgq.visionipc.visionipc cimport cl_mem +from msgq.visionipc.visionipc_pyx cimport VisionBuf, CLContext as BaseCLContext +from .commonmodel cimport CL_DEVICE_TYPE_DEFAULT, cl_get_device_id, cl_create_context, cl_release_context +from .commonmodel cimport mat3, ModelFrame as cppModelFrame, DrivingModelFrame as cppDrivingModelFrame, MonitoringModelFrame as cppMonitoringModelFrame + + +cdef class CLContext(BaseCLContext): + def __cinit__(self): + self.device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT) + self.context = cl_create_context(self.device_id) + + def __dealloc__(self): + if self.context: + cl_release_context(self.context) + +cdef class CLMem: + @staticmethod + cdef create(void * cmem): + mem = CLMem() + mem.mem = cmem + return mem + + @property + def mem_address(self): + return (self.mem) + +def cl_from_visionbuf(VisionBuf buf): + return CLMem.create(&buf.buf.buf_cl) + + +cdef class ModelFrame: + cdef cppModelFrame * frame + cdef int buf_size + + def __dealloc__(self): + del self.frame + + def prepare(self, VisionBuf buf, float[:] projection): + cdef mat3 cprojection + memcpy(cprojection.v, &projection[0], 9*sizeof(float)) + cdef cl_mem * data + data = self.frame.prepare(buf.buf.buf_cl, buf.width, buf.height, buf.stride, buf.uv_offset, cprojection) + return CLMem.create(data) + + def buffer_from_cl(self, CLMem in_frames): + cdef unsigned char * data2 + data2 = self.frame.buffer_from_cl(in_frames.mem, self.buf_size) + return np.asarray( data2) + + +cdef class DrivingModelFrame(ModelFrame): + cdef cppDrivingModelFrame * _frame + + def __cinit__(self, CLContext context, int temporal_skip): + self._frame = new cppDrivingModelFrame(context.device_id, context.context, temporal_skip) + self.frame = (self._frame) + self.buf_size = self._frame.buf_size + +cdef class MonitoringModelFrame(ModelFrame): + cdef cppMonitoringModelFrame * _frame + + def __cinit__(self, CLContext context): + self._frame = new cppMonitoringModelFrame(context.device_id, context.context) + self.frame = (self._frame) + self.buf_size = self._frame.buf_size + diff --git a/selfdrive/modeld/models/dmonitoring_model.onnx b/selfdrive/modeld/models/dmonitoring_model.onnx new file mode 100644 index 0000000000..da60e9a907 Binary files /dev/null and b/selfdrive/modeld/models/dmonitoring_model.onnx differ diff --git a/selfdrive/modeld/models/driving_policy.onnx b/selfdrive/modeld/models/driving_policy.onnx new file mode 100644 index 0000000000..50b198a58c Binary files /dev/null and b/selfdrive/modeld/models/driving_policy.onnx differ diff --git a/selfdrive/modeld/models/driving_vision.onnx b/selfdrive/modeld/models/driving_vision.onnx new file mode 100644 index 0000000000..ac18efb0b8 Binary files /dev/null and b/selfdrive/modeld/models/driving_vision.onnx differ diff --git a/selfdrive/modeld/parse_model_outputs.py b/selfdrive/modeld/parse_model_outputs.py new file mode 100644 index 0000000000..038f51ca9c --- /dev/null +++ b/selfdrive/modeld/parse_model_outputs.py @@ -0,0 +1,122 @@ +import numpy as np +from openpilot.selfdrive.modeld.constants import ModelConstants + +def safe_exp(x, out=None): + # -11 is around 10**14, more causes float16 overflow + return np.exp(np.clip(x, -np.inf, 11), out=out) + +def sigmoid(x): + return 1. / (1. + safe_exp(-x)) + +def softmax(x, axis=-1): + x -= np.max(x, axis=axis, keepdims=True) + if x.dtype == np.float32 or x.dtype == np.float64: + safe_exp(x, out=x) + else: + x = safe_exp(x) + x /= np.sum(x, axis=axis, keepdims=True) + return x + +class Parser: + def __init__(self, ignore_missing=False): + self.ignore_missing = ignore_missing + + def check_missing(self, outs, name): + missing = name not in outs + if missing and not self.ignore_missing: + raise ValueError(f"Missing output {name}") + return missing + + def parse_categorical_crossentropy(self, name, outs, out_shape=None): + if self.check_missing(outs, name): + return + raw = outs[name] + if out_shape is not None: + raw = raw.reshape((raw.shape[0],) + out_shape) + outs[name] = softmax(raw, axis=-1) + + def parse_binary_crossentropy(self, name, outs): + if self.check_missing(outs, name): + return + raw = outs[name] + outs[name] = sigmoid(raw) + + def parse_mdn(self, name, outs, in_N=0, out_N=1, out_shape=None): + if self.check_missing(outs, name): + return + raw = outs[name] + raw = raw.reshape((raw.shape[0], max(in_N, 1), -1)) + + n_values = (raw.shape[2] - out_N)//2 + pred_mu = raw[:,:,:n_values] + pred_std = safe_exp(raw[:,:,n_values: 2*n_values]) + + if in_N > 1: + weights = np.zeros((raw.shape[0], in_N, out_N), dtype=raw.dtype) + for i in range(out_N): + weights[:,:,i - out_N] = softmax(raw[:,:,i - out_N], axis=-1) + + if out_N == 1: + for fidx in range(weights.shape[0]): + idxs = np.argsort(weights[fidx][:,0])[::-1] + weights[fidx] = weights[fidx][idxs] + pred_mu[fidx] = pred_mu[fidx][idxs] + pred_std[fidx] = pred_std[fidx][idxs] + full_shape = tuple([raw.shape[0], in_N] + list(out_shape)) + outs[name + '_weights'] = weights + outs[name + '_hypotheses'] = pred_mu.reshape(full_shape) + outs[name + '_stds_hypotheses'] = pred_std.reshape(full_shape) + + pred_mu_final = np.zeros((raw.shape[0], out_N, n_values), dtype=raw.dtype) + pred_std_final = np.zeros((raw.shape[0], out_N, n_values), dtype=raw.dtype) + for fidx in range(weights.shape[0]): + for hidx in range(out_N): + idxs = np.argsort(weights[fidx,:,hidx])[::-1] + pred_mu_final[fidx, hidx] = pred_mu[fidx, idxs[0]] + pred_std_final[fidx, hidx] = pred_std[fidx, idxs[0]] + else: + pred_mu_final = pred_mu + pred_std_final = pred_std + + if out_N > 1: + final_shape = tuple([raw.shape[0], out_N] + list(out_shape)) + else: + final_shape = tuple([raw.shape[0],] + list(out_shape)) + outs[name] = pred_mu_final.reshape(final_shape) + outs[name + '_stds'] = pred_std_final.reshape(final_shape) + + def is_mhp(self, outs, name, shape): + if self.check_missing(outs, name): + return False + if outs[name].shape[1] == 2 * shape: + return False + return True + + def parse_vision_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]: + self.parse_mdn('pose', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,)) + self.parse_mdn('wide_from_device_euler', outs, in_N=0, out_N=0, out_shape=(ModelConstants.WIDE_FROM_DEVICE_WIDTH,)) + self.parse_mdn('road_transform', outs, in_N=0, out_N=0, out_shape=(ModelConstants.POSE_WIDTH,)) + self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH)) + self.parse_mdn('road_edges', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_ROAD_EDGES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH)) + self.parse_binary_crossentropy('lane_lines_prob', outs) + self.parse_categorical_crossentropy('desire_pred', outs, out_shape=(ModelConstants.DESIRE_PRED_LEN,ModelConstants.DESIRE_PRED_WIDTH)) + self.parse_binary_crossentropy('meta', outs) + self.parse_binary_crossentropy('lead_prob', outs) + lead_mhp = self.is_mhp(outs, 'lead', ModelConstants.LEAD_MHP_SELECTION * ModelConstants.LEAD_TRAJ_LEN * ModelConstants.LEAD_WIDTH) + lead_in_N, lead_out_N = (ModelConstants.LEAD_MHP_N, ModelConstants.LEAD_MHP_SELECTION) if lead_mhp else (0, 0) + lead_out_shape = (ModelConstants.LEAD_TRAJ_LEN, ModelConstants.LEAD_WIDTH) if lead_mhp else \ + (ModelConstants.LEAD_MHP_SELECTION, ModelConstants.LEAD_TRAJ_LEN, ModelConstants.LEAD_WIDTH) + self.parse_mdn('lead', outs, in_N=lead_in_N, out_N=lead_out_N, out_shape=lead_out_shape) + return outs + + def parse_policy_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]: + plan_mhp = self.is_mhp(outs, 'plan', ModelConstants.IDX_N * ModelConstants.PLAN_WIDTH) + plan_in_N, plan_out_N = (ModelConstants.PLAN_MHP_N, ModelConstants.PLAN_MHP_SELECTION) if plan_mhp else (0, 0) + self.parse_mdn('plan', outs, in_N=plan_in_N, out_N=plan_out_N, out_shape=(ModelConstants.IDX_N, ModelConstants.PLAN_WIDTH)) + self.parse_categorical_crossentropy('desire_state', outs, out_shape=(ModelConstants.DESIRE_PRED_WIDTH,)) + return outs + + def parse_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]: + outs = self.parse_vision_outputs(outs) + outs = self.parse_policy_outputs(outs) + return outs diff --git a/selfdrive/modeld/runners/tinygrad_helpers.py b/selfdrive/modeld/runners/tinygrad_helpers.py new file mode 100644 index 0000000000..776381341c --- /dev/null +++ b/selfdrive/modeld/runners/tinygrad_helpers.py @@ -0,0 +1,8 @@ + +from tinygrad.tensor import Tensor +from tinygrad.helpers import to_mv + +def qcom_tensor_from_opencl_address(opencl_address, shape, dtype): + cl_buf_desc_ptr = to_mv(opencl_address, 8).cast('Q')[0] + rawbuf_ptr = to_mv(cl_buf_desc_ptr, 0x100).cast('Q')[20] # offset 0xA0 is a raw gpu pointer. + return Tensor.from_blob(rawbuf_ptr, shape, dtype=dtype, device='QCOM') diff --git a/selfdrive/modeld/tests/__init__.py b/selfdrive/modeld/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/modeld/tests/test_modeld.py b/selfdrive/modeld/tests/test_modeld.py new file mode 100644 index 0000000000..6927c9e473 --- /dev/null +++ b/selfdrive/modeld/tests/test_modeld.py @@ -0,0 +1,102 @@ +import numpy as np +import random + +import cereal.messaging as messaging +from msgq.visionipc import VisionIpcServer, VisionStreamType +from opendbc.car.car_helpers import get_demo_car_params +from openpilot.common.params import Params +from openpilot.common.transformations.camera import DEVICE_CAMERAS +from openpilot.common.realtime import DT_MDL +from openpilot.system.manager.process_config import managed_processes +from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_camera_state + +CAM = DEVICE_CAMERAS[("tici", "ar0231")].fcam +IMG = np.zeros(int(CAM.width*CAM.height*(3/2)), dtype=np.uint8) +IMG_BYTES = IMG.flatten().tobytes() + + +class TestModeld: + + def setup_method(self): + self.vipc_server = VisionIpcServer("camerad") + self.vipc_server.create_buffers(VisionStreamType.VISION_STREAM_ROAD, 40, CAM.width, CAM.height) + self.vipc_server.create_buffers(VisionStreamType.VISION_STREAM_DRIVER, 40, CAM.width, CAM.height) + self.vipc_server.create_buffers(VisionStreamType.VISION_STREAM_WIDE_ROAD, 40, CAM.width, CAM.height) + self.vipc_server.start_listener() + Params().put("CarParams", get_demo_car_params().to_bytes()) + + self.sm = messaging.SubMaster(['modelV2', 'cameraOdometry']) + self.pm = messaging.PubMaster(['roadCameraState', 'wideRoadCameraState', 'liveCalibration']) + + managed_processes['modeld'].start() + self.pm.wait_for_readers_to_update("roadCameraState", 10) + + def teardown_method(self): + managed_processes['modeld'].stop() + del self.vipc_server + + def _send_frames(self, frame_id, cams=None): + if cams is None: + cams = ('roadCameraState', 'wideRoadCameraState') + + cs = None + for cam in cams: + msg = messaging.new_message(cam) + cs = getattr(msg, cam) + cs.frameId = frame_id + cs.timestampSof = int((frame_id * DT_MDL) * 1e9) + cs.timestampEof = int(cs.timestampSof + (DT_MDL * 1e9)) + cam_meta = meta_from_camera_state(cam) + + self.pm.send(msg.which(), msg) + self.vipc_server.send(cam_meta.stream, IMG_BYTES, cs.frameId, + cs.timestampSof, cs.timestampEof) + return cs + + def _wait(self): + self.sm.update(5000) + if self.sm['modelV2'].frameId != self.sm['cameraOdometry'].frameId: + self.sm.update(1000) + + def test_modeld(self): + for n in range(1, 500): + cs = self._send_frames(n) + self._wait() + + mdl = self.sm['modelV2'] + assert mdl.frameId == n + assert mdl.frameIdExtra == n + assert mdl.timestampEof == cs.timestampEof + assert mdl.frameAge == 0 + assert mdl.frameDropPerc == 0 + + odo = self.sm['cameraOdometry'] + assert odo.frameId == n + assert odo.timestampEof == cs.timestampEof + + def test_dropped_frames(self): + """ + modeld should only run on consecutive road frames + """ + frame_id = -1 + road_frames = list() + for n in range(1, 50): + if (random.random() < 0.1) and n > 3: + cams = random.choice([(), ('wideRoadCameraState', )]) + self._send_frames(n, cams) + else: + self._send_frames(n) + road_frames.append(n) + self._wait() + + if len(road_frames) < 3 or road_frames[-1] - road_frames[-2] == 1: + frame_id = road_frames[-1] + + mdl = self.sm['modelV2'] + odo = self.sm['cameraOdometry'] + assert mdl.frameId == frame_id + assert mdl.frameIdExtra == frame_id + assert odo.frameId == frame_id + if n != frame_id: + assert not self.sm.updated['modelV2'] + assert not self.sm.updated['cameraOdometry'] diff --git a/selfdrive/modeld/transforms/loadyuv.cc b/selfdrive/modeld/transforms/loadyuv.cc new file mode 100644 index 0000000000..c93f5cd038 --- /dev/null +++ b/selfdrive/modeld/transforms/loadyuv.cc @@ -0,0 +1,76 @@ +#include "selfdrive/modeld/transforms/loadyuv.h" + +#include +#include +#include + +void loadyuv_init(LoadYUVState* s, cl_context ctx, cl_device_id device_id, int width, int height) { + memset(s, 0, sizeof(*s)); + + s->width = width; + s->height = height; + + char args[1024]; + snprintf(args, sizeof(args), + "-cl-fast-relaxed-math -cl-denorms-are-zero " + "-DTRANSFORMED_WIDTH=%d -DTRANSFORMED_HEIGHT=%d", + width, height); + cl_program prg = cl_program_from_file(ctx, device_id, LOADYUV_PATH, args); + + s->loadys_krnl = CL_CHECK_ERR(clCreateKernel(prg, "loadys", &err)); + s->loaduv_krnl = CL_CHECK_ERR(clCreateKernel(prg, "loaduv", &err)); + s->copy_krnl = CL_CHECK_ERR(clCreateKernel(prg, "copy", &err)); + + // done with this + CL_CHECK(clReleaseProgram(prg)); +} + +void loadyuv_destroy(LoadYUVState* s) { + CL_CHECK(clReleaseKernel(s->loadys_krnl)); + CL_CHECK(clReleaseKernel(s->loaduv_krnl)); + CL_CHECK(clReleaseKernel(s->copy_krnl)); +} + +void loadyuv_queue(LoadYUVState* s, cl_command_queue q, + cl_mem y_cl, cl_mem u_cl, cl_mem v_cl, + cl_mem out_cl) { + cl_int global_out_off = 0; + + CL_CHECK(clSetKernelArg(s->loadys_krnl, 0, sizeof(cl_mem), &y_cl)); + CL_CHECK(clSetKernelArg(s->loadys_krnl, 1, sizeof(cl_mem), &out_cl)); + CL_CHECK(clSetKernelArg(s->loadys_krnl, 2, sizeof(cl_int), &global_out_off)); + + const size_t loadys_work_size = (s->width*s->height)/8; + CL_CHECK(clEnqueueNDRangeKernel(q, s->loadys_krnl, 1, NULL, + &loadys_work_size, NULL, 0, 0, NULL)); + + const size_t loaduv_work_size = ((s->width/2)*(s->height/2))/8; + global_out_off += (s->width*s->height); + + CL_CHECK(clSetKernelArg(s->loaduv_krnl, 0, sizeof(cl_mem), &u_cl)); + CL_CHECK(clSetKernelArg(s->loaduv_krnl, 1, sizeof(cl_mem), &out_cl)); + CL_CHECK(clSetKernelArg(s->loaduv_krnl, 2, sizeof(cl_int), &global_out_off)); + + CL_CHECK(clEnqueueNDRangeKernel(q, s->loaduv_krnl, 1, NULL, + &loaduv_work_size, NULL, 0, 0, NULL)); + + global_out_off += (s->width/2)*(s->height/2); + + CL_CHECK(clSetKernelArg(s->loaduv_krnl, 0, sizeof(cl_mem), &v_cl)); + CL_CHECK(clSetKernelArg(s->loaduv_krnl, 1, sizeof(cl_mem), &out_cl)); + CL_CHECK(clSetKernelArg(s->loaduv_krnl, 2, sizeof(cl_int), &global_out_off)); + + CL_CHECK(clEnqueueNDRangeKernel(q, s->loaduv_krnl, 1, NULL, + &loaduv_work_size, NULL, 0, 0, NULL)); +} + +void copy_queue(LoadYUVState* s, cl_command_queue q, cl_mem src, cl_mem dst, + size_t src_offset, size_t dst_offset, size_t size) { + CL_CHECK(clSetKernelArg(s->copy_krnl, 0, sizeof(cl_mem), &src)); + CL_CHECK(clSetKernelArg(s->copy_krnl, 1, sizeof(cl_mem), &dst)); + CL_CHECK(clSetKernelArg(s->copy_krnl, 2, sizeof(cl_int), &src_offset)); + CL_CHECK(clSetKernelArg(s->copy_krnl, 3, sizeof(cl_int), &dst_offset)); + const size_t copy_work_size = size/8; + CL_CHECK(clEnqueueNDRangeKernel(q, s->copy_krnl, 1, NULL, + ©_work_size, NULL, 0, 0, NULL)); +} \ No newline at end of file diff --git a/selfdrive/modeld/transforms/loadyuv.cl b/selfdrive/modeld/transforms/loadyuv.cl new file mode 100644 index 0000000000..970187a6d7 --- /dev/null +++ b/selfdrive/modeld/transforms/loadyuv.cl @@ -0,0 +1,47 @@ +#define UV_SIZE ((TRANSFORMED_WIDTH/2)*(TRANSFORMED_HEIGHT/2)) + +__kernel void loadys(__global uchar8 const * const Y, + __global uchar * out, + int out_offset) +{ + const int gid = get_global_id(0); + const int ois = gid * 8; + const int oy = ois / TRANSFORMED_WIDTH; + const int ox = ois % TRANSFORMED_WIDTH; + + const uchar8 ys = Y[gid]; + + // 02 + // 13 + + __global uchar* outy0; + __global uchar* outy1; + if ((oy & 1) == 0) { + outy0 = out + out_offset; //y0 + outy1 = out + out_offset + UV_SIZE*2; //y2 + } else { + outy0 = out + out_offset + UV_SIZE; //y1 + outy1 = out + out_offset + UV_SIZE*3; //y3 + } + + vstore4(ys.s0246, 0, outy0 + (oy/2) * (TRANSFORMED_WIDTH/2) + ox/2); + vstore4(ys.s1357, 0, outy1 + (oy/2) * (TRANSFORMED_WIDTH/2) + ox/2); +} + +__kernel void loaduv(__global uchar8 const * const in, + __global uchar8 * out, + int out_offset) +{ + const int gid = get_global_id(0); + const uchar8 inv = in[gid]; + out[gid + out_offset / 8] = inv; +} + +__kernel void copy(__global uchar8 * in, + __global uchar8 * out, + int in_offset, + int out_offset) +{ + const int gid = get_global_id(0); + out[gid + out_offset / 8] = in[gid + in_offset / 8]; +} diff --git a/selfdrive/modeld/transforms/loadyuv.h b/selfdrive/modeld/transforms/loadyuv.h new file mode 100644 index 0000000000..659059cd25 --- /dev/null +++ b/selfdrive/modeld/transforms/loadyuv.h @@ -0,0 +1,20 @@ +#pragma once + +#include "common/clutil.h" + +typedef struct { + int width, height; + cl_kernel loadys_krnl, loaduv_krnl, copy_krnl; +} LoadYUVState; + +void loadyuv_init(LoadYUVState* s, cl_context ctx, cl_device_id device_id, int width, int height); + +void loadyuv_destroy(LoadYUVState* s); + +void loadyuv_queue(LoadYUVState* s, cl_command_queue q, + cl_mem y_cl, cl_mem u_cl, cl_mem v_cl, + cl_mem out_cl); + + +void copy_queue(LoadYUVState* s, cl_command_queue q, cl_mem src, cl_mem dst, + size_t src_offset, size_t dst_offset, size_t size); \ No newline at end of file diff --git a/selfdrive/modeld/transforms/transform.cc b/selfdrive/modeld/transforms/transform.cc new file mode 100644 index 0000000000..305643cf42 --- /dev/null +++ b/selfdrive/modeld/transforms/transform.cc @@ -0,0 +1,97 @@ +#include "selfdrive/modeld/transforms/transform.h" + +#include +#include + +#include "common/clutil.h" + +void transform_init(Transform* s, cl_context ctx, cl_device_id device_id) { + memset(s, 0, sizeof(*s)); + + cl_program prg = cl_program_from_file(ctx, device_id, TRANSFORM_PATH, ""); + s->krnl = CL_CHECK_ERR(clCreateKernel(prg, "warpPerspective", &err)); + // done with this + CL_CHECK(clReleaseProgram(prg)); + + s->m_y_cl = CL_CHECK_ERR(clCreateBuffer(ctx, CL_MEM_READ_WRITE, 3*3*sizeof(float), NULL, &err)); + s->m_uv_cl = CL_CHECK_ERR(clCreateBuffer(ctx, CL_MEM_READ_WRITE, 3*3*sizeof(float), NULL, &err)); +} + +void transform_destroy(Transform* s) { + CL_CHECK(clReleaseMemObject(s->m_y_cl)); + CL_CHECK(clReleaseMemObject(s->m_uv_cl)); + CL_CHECK(clReleaseKernel(s->krnl)); +} + +void transform_queue(Transform* s, + cl_command_queue q, + cl_mem in_yuv, int in_width, int in_height, int in_stride, int in_uv_offset, + cl_mem out_y, cl_mem out_u, cl_mem out_v, + int out_width, int out_height, + const mat3& projection) { + const int zero = 0; + + // sampled using pixel center origin + // (because that's how fastcv and opencv does it) + + mat3 projection_y = projection; + + // in and out uv is half the size of y. + mat3 projection_uv = transform_scale_buffer(projection, 0.5); + + CL_CHECK(clEnqueueWriteBuffer(q, s->m_y_cl, CL_TRUE, 0, 3*3*sizeof(float), (void*)projection_y.v, 0, NULL, NULL)); + CL_CHECK(clEnqueueWriteBuffer(q, s->m_uv_cl, CL_TRUE, 0, 3*3*sizeof(float), (void*)projection_uv.v, 0, NULL, NULL)); + + const int in_y_width = in_width; + const int in_y_height = in_height; + const int in_y_px_stride = 1; + const int in_uv_width = in_width/2; + const int in_uv_height = in_height/2; + const int in_uv_px_stride = 2; + const int in_u_offset = in_uv_offset; + const int in_v_offset = in_uv_offset + 1; + + const int out_y_width = out_width; + const int out_y_height = out_height; + const int out_uv_width = out_width/2; + const int out_uv_height = out_height/2; + + CL_CHECK(clSetKernelArg(s->krnl, 0, sizeof(cl_mem), &in_yuv)); // src + CL_CHECK(clSetKernelArg(s->krnl, 1, sizeof(cl_int), &in_stride)); // src_row_stride + CL_CHECK(clSetKernelArg(s->krnl, 2, sizeof(cl_int), &in_y_px_stride)); // src_px_stride + CL_CHECK(clSetKernelArg(s->krnl, 3, sizeof(cl_int), &zero)); // src_offset + CL_CHECK(clSetKernelArg(s->krnl, 4, sizeof(cl_int), &in_y_height)); // src_rows + CL_CHECK(clSetKernelArg(s->krnl, 5, sizeof(cl_int), &in_y_width)); // src_cols + CL_CHECK(clSetKernelArg(s->krnl, 6, sizeof(cl_mem), &out_y)); // dst + CL_CHECK(clSetKernelArg(s->krnl, 7, sizeof(cl_int), &out_y_width)); // dst_row_stride + CL_CHECK(clSetKernelArg(s->krnl, 8, sizeof(cl_int), &zero)); // dst_offset + CL_CHECK(clSetKernelArg(s->krnl, 9, sizeof(cl_int), &out_y_height)); // dst_rows + CL_CHECK(clSetKernelArg(s->krnl, 10, sizeof(cl_int), &out_y_width)); // dst_cols + CL_CHECK(clSetKernelArg(s->krnl, 11, sizeof(cl_mem), &s->m_y_cl)); // M + + const size_t work_size_y[2] = {(size_t)out_y_width, (size_t)out_y_height}; + + CL_CHECK(clEnqueueNDRangeKernel(q, s->krnl, 2, NULL, + (const size_t*)&work_size_y, NULL, 0, 0, NULL)); + + const size_t work_size_uv[2] = {(size_t)out_uv_width, (size_t)out_uv_height}; + + CL_CHECK(clSetKernelArg(s->krnl, 2, sizeof(cl_int), &in_uv_px_stride)); // src_px_stride + CL_CHECK(clSetKernelArg(s->krnl, 3, sizeof(cl_int), &in_u_offset)); // src_offset + CL_CHECK(clSetKernelArg(s->krnl, 4, sizeof(cl_int), &in_uv_height)); // src_rows + CL_CHECK(clSetKernelArg(s->krnl, 5, sizeof(cl_int), &in_uv_width)); // src_cols + CL_CHECK(clSetKernelArg(s->krnl, 6, sizeof(cl_mem), &out_u)); // dst + CL_CHECK(clSetKernelArg(s->krnl, 7, sizeof(cl_int), &out_uv_width)); // dst_row_stride + CL_CHECK(clSetKernelArg(s->krnl, 8, sizeof(cl_int), &zero)); // dst_offset + CL_CHECK(clSetKernelArg(s->krnl, 9, sizeof(cl_int), &out_uv_height)); // dst_rows + CL_CHECK(clSetKernelArg(s->krnl, 10, sizeof(cl_int), &out_uv_width)); // dst_cols + CL_CHECK(clSetKernelArg(s->krnl, 11, sizeof(cl_mem), &s->m_uv_cl)); // M + + CL_CHECK(clEnqueueNDRangeKernel(q, s->krnl, 2, NULL, + (const size_t*)&work_size_uv, NULL, 0, 0, NULL)); + CL_CHECK(clSetKernelArg(s->krnl, 3, sizeof(cl_int), &in_v_offset)); // src_ofset + CL_CHECK(clSetKernelArg(s->krnl, 6, sizeof(cl_mem), &out_v)); // dst + + CL_CHECK(clEnqueueNDRangeKernel(q, s->krnl, 2, NULL, + (const size_t*)&work_size_uv, NULL, 0, 0, NULL)); +} diff --git a/selfdrive/modeld/transforms/transform.cl b/selfdrive/modeld/transforms/transform.cl new file mode 100644 index 0000000000..2ca25920cd --- /dev/null +++ b/selfdrive/modeld/transforms/transform.cl @@ -0,0 +1,54 @@ +#define INTER_BITS 5 +#define INTER_TAB_SIZE (1 << INTER_BITS) +#define INTER_SCALE 1.f / INTER_TAB_SIZE + +#define INTER_REMAP_COEF_BITS 15 +#define INTER_REMAP_COEF_SCALE (1 << INTER_REMAP_COEF_BITS) + +__kernel void warpPerspective(__global const uchar * src, + int src_row_stride, int src_px_stride, int src_offset, int src_rows, int src_cols, + __global uchar * dst, + int dst_row_stride, int dst_offset, int dst_rows, int dst_cols, + __constant float * M) +{ + int dx = get_global_id(0); + int dy = get_global_id(1); + + if (dx < dst_cols && dy < dst_rows) + { + float X0 = M[0] * dx + M[1] * dy + M[2]; + float Y0 = M[3] * dx + M[4] * dy + M[5]; + float W = M[6] * dx + M[7] * dy + M[8]; + W = W != 0.0f ? INTER_TAB_SIZE / W : 0.0f; + int X = rint(X0 * W), Y = rint(Y0 * W); + + int sx = convert_short_sat(X >> INTER_BITS); + int sy = convert_short_sat(Y >> INTER_BITS); + + short sx_clamp = clamp(sx, 0, src_cols - 1); + short sx_p1_clamp = clamp(sx + 1, 0, src_cols - 1); + short sy_clamp = clamp(sy, 0, src_rows - 1); + short sy_p1_clamp = clamp(sy + 1, 0, src_rows - 1); + int v0 = convert_int(src[mad24(sy_clamp, src_row_stride, src_offset + sx_clamp*src_px_stride)]); + int v1 = convert_int(src[mad24(sy_clamp, src_row_stride, src_offset + sx_p1_clamp*src_px_stride)]); + int v2 = convert_int(src[mad24(sy_p1_clamp, src_row_stride, src_offset + sx_clamp*src_px_stride)]); + int v3 = convert_int(src[mad24(sy_p1_clamp, src_row_stride, src_offset + sx_p1_clamp*src_px_stride)]); + + short ay = (short)(Y & (INTER_TAB_SIZE - 1)); + short ax = (short)(X & (INTER_TAB_SIZE - 1)); + float taby = 1.f/INTER_TAB_SIZE*ay; + float tabx = 1.f/INTER_TAB_SIZE*ax; + + int dst_index = mad24(dy, dst_row_stride, dst_offset + dx); + + int itab0 = convert_short_sat_rte( (1.0f-taby)*(1.0f-tabx) * INTER_REMAP_COEF_SCALE ); + int itab1 = convert_short_sat_rte( (1.0f-taby)*tabx * INTER_REMAP_COEF_SCALE ); + int itab2 = convert_short_sat_rte( taby*(1.0f-tabx) * INTER_REMAP_COEF_SCALE ); + int itab3 = convert_short_sat_rte( taby*tabx * INTER_REMAP_COEF_SCALE ); + + int val = v0 * itab0 + v1 * itab1 + v2 * itab2 + v3 * itab3; + + uchar pix = convert_uchar_sat((val + (1 << (INTER_REMAP_COEF_BITS-1))) >> INTER_REMAP_COEF_BITS); + dst[dst_index] = pix; + } +} diff --git a/selfdrive/modeld/transforms/transform.h b/selfdrive/modeld/transforms/transform.h new file mode 100644 index 0000000000..771a7054b3 --- /dev/null +++ b/selfdrive/modeld/transforms/transform.h @@ -0,0 +1,25 @@ +#pragma once + +#define CL_USE_DEPRECATED_OPENCL_1_2_APIS +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include "common/mat.h" + +typedef struct { + cl_kernel krnl; + cl_mem m_y_cl, m_uv_cl; +} Transform; + +void transform_init(Transform* s, cl_context ctx, cl_device_id device_id); + +void transform_destroy(Transform* transform); + +void transform_queue(Transform* s, cl_command_queue q, + cl_mem yuv, int in_width, int in_height, int in_stride, int in_uv_offset, + cl_mem out_y, cl_mem out_u, cl_mem out_v, + int out_width, int out_height, + const mat3& projection); diff --git a/selfdrive/monitoring/README.md b/selfdrive/monitoring/README.md new file mode 100644 index 0000000000..2a29ea06b5 --- /dev/null +++ b/selfdrive/monitoring/README.md @@ -0,0 +1,15 @@ +# driver monitoring (DM) + +Uploading driver-facing camera footage is opt-in, but it is encouraged to opt-in to improve the DM model. You can always change your preference using the "Record and Upload Driver Camera" toggle. + +## Troubleshooting + +Before creating a bug report, go through these troubleshooting steps. + +* Ensure the driver-facing camera has a good view of the driver in normal driving positions. + * This can be checked in Settings -> Device -> Preview Driver Camera (when car is off). +* If the camera can't see the driver, the device should be re-mounted. + +## Bug report + +In order for us to look into DM bug reports, we'll need the driver-facing camera footage. If you don't normally have this enabled, simply enable the toggle for a single drive. Also ensure the "Upload Raw Logs" toggle is enabled before going for a drive. diff --git a/selfdrive/monitoring/dmonitoringd.py b/selfdrive/monitoring/dmonitoringd.py new file mode 100755 index 0000000000..f137b406b4 --- /dev/null +++ b/selfdrive/monitoring/dmonitoringd.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +import cereal.messaging as messaging +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process +from openpilot.selfdrive.monitoring.helpers import DriverMonitoring + + +def dmonitoringd_thread(): + config_realtime_process([0, 1, 2, 3], 5) + + params = Params() + pm = messaging.PubMaster(['driverMonitoringState']) + sm = messaging.SubMaster(['driverStateV2', 'liveCalibration', 'carState', 'selfdriveState', 'modelV2'], poll='driverStateV2') + + DM = DriverMonitoring(rhd_saved=params.get_bool("IsRhdDetected"), always_on=params.get_bool("AlwaysOnDM")) + + # 20Hz <- dmonitoringmodeld + while True: + sm.update() + if not sm.updated['driverStateV2']: + # iterate when model has new output + continue + + valid = sm.all_checks() + if valid: + DM.run_step(sm) + + # publish + dat = DM.get_state_packet(valid=valid) + pm.send('driverMonitoringState', dat) + + # load live always-on toggle + if sm['driverStateV2'].frameId % 40 == 1: + DM.always_on = params.get_bool("AlwaysOnDM") + + # save rhd virtual toggle every 5 mins + if (sm['driverStateV2'].frameId % 6000 == 0 and + DM.wheelpos_learner.filtered_stat.n > DM.settings._WHEELPOS_FILTER_MIN_COUNT and + DM.wheel_on_right == (DM.wheelpos_learner.filtered_stat.M > DM.settings._WHEELPOS_THRESHOLD)): + params.put_bool_nonblocking("IsRhdDetected", DM.wheel_on_right) + +def main(): + dmonitoringd_thread() + + +if __name__ == '__main__': + main() diff --git a/selfdrive/monitoring/helpers.py b/selfdrive/monitoring/helpers.py new file mode 100644 index 0000000000..c2e5bc3fe4 --- /dev/null +++ b/selfdrive/monitoring/helpers.py @@ -0,0 +1,417 @@ +from math import atan2 +import numpy as np + +from cereal import car, log +import cereal.messaging as messaging +from openpilot.selfdrive.selfdrived.events import Events +from openpilot.common.realtime import DT_DMON +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.params import Params +from openpilot.common.stat_live import RunningStatFilter +from openpilot.common.transformations.camera import DEVICE_CAMERAS + +EventName = log.OnroadEvent.EventName + +# ****************************************************************************************** +# NOTE: To fork maintainers. +# Disabling or nerfing safety features will get you and your users banned from our servers. +# We recommend that you do not change these numbers from the defaults. +# ****************************************************************************************** + +class DRIVER_MONITOR_SETTINGS: + def __init__(self): + self._DT_DMON = DT_DMON + # ref (page15-16): https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:42018X1947&rid=2 + self._AWARENESS_TIME = 30. # passive wheeltouch total timeout + self._AWARENESS_PRE_TIME_TILL_TERMINAL = 15. + self._AWARENESS_PROMPT_TIME_TILL_TERMINAL = 6. + self._DISTRACTED_TIME = 11. # active monitoring total timeout + self._DISTRACTED_PRE_TIME_TILL_TERMINAL = 8. + self._DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 6. + + self._FACE_THRESHOLD = 0.7 + self._EYE_THRESHOLD = 0.65 + self._SG_THRESHOLD = 0.9 + self._BLINK_THRESHOLD = 0.865 + + self._EE_THRESH11 = 0.4 + self._EE_THRESH12 = 15.0 + self._EE_MAX_OFFSET1 = 0.06 + self._EE_MIN_OFFSET1 = 0.025 + + self._POSE_PITCH_THRESHOLD = 0.3133 + self._POSE_PITCH_THRESHOLD_SLACK = 0.3237 + self._POSE_PITCH_THRESHOLD_STRICT = self._POSE_PITCH_THRESHOLD + self._POSE_YAW_THRESHOLD = 0.4020 + self._POSE_YAW_THRESHOLD_SLACK = 0.5042 + self._POSE_YAW_THRESHOLD_STRICT = self._POSE_YAW_THRESHOLD + self._PITCH_NATURAL_OFFSET = 0.029 # initial value before offset is learned + self._PITCH_NATURAL_THRESHOLD = 0.449 + self._YAW_NATURAL_OFFSET = 0.097 # initial value before offset is learned + self._PITCH_MAX_OFFSET = 0.124 + self._PITCH_MIN_OFFSET = -0.0881 + self._YAW_MAX_OFFSET = 0.289 + self._YAW_MIN_OFFSET = -0.0246 + + self._POSESTD_THRESHOLD = 0.3 + self._HI_STD_FALLBACK_TIME = int(10 / self._DT_DMON) # fall back to wheel touch if model is uncertain for 10s + self._DISTRACTED_FILTER_TS = 0.25 # 0.6Hz + self._ALWAYS_ON_ALERT_MIN_SPEED = 11 + + self._POSE_CALIB_MIN_SPEED = 13 # 30 mph + self._POSE_OFFSET_MIN_COUNT = int(60 / self._DT_DMON) # valid data counts before calibration completes, 1min cumulative + self._POSE_OFFSET_MAX_COUNT = int(360 / self._DT_DMON) # stop deweighting new data after 6 min, aka "short term memory" + + self._WHEELPOS_CALIB_MIN_SPEED = 11 + self._WHEELPOS_THRESHOLD = 0.5 + self._WHEELPOS_FILTER_MIN_COUNT = int(15 / self._DT_DMON) # allow 15 seconds to converge wheel side + + self._RECOVERY_FACTOR_MAX = 5. # relative to minus step change + self._RECOVERY_FACTOR_MIN = 1.25 # relative to minus step change + + self._MAX_TERMINAL_ALERTS = 3 # not allowed to engage after 3 terminal alerts + self._MAX_TERMINAL_DURATION = int(30 / self._DT_DMON) # not allowed to engage after 30s of terminal alerts + +class DistractedType: + NOT_DISTRACTED = 0 + DISTRACTED_POSE = 1 << 0 + DISTRACTED_BLINK = 1 << 1 + DISTRACTED_E2E = 1 << 2 + +class DriverPose: + def __init__(self, max_trackable): + self.yaw = 0. + self.pitch = 0. + self.roll = 0. + self.yaw_std = 0. + self.pitch_std = 0. + self.roll_std = 0. + self.pitch_offseter = RunningStatFilter(max_trackable=max_trackable) + self.yaw_offseter = RunningStatFilter(max_trackable=max_trackable) + self.calibrated = False + self.low_std = True + self.cfactor_pitch = 1. + self.cfactor_yaw = 1. + +class DriverBlink: + def __init__(self): + self.left = 0. + self.right = 0. + + +# model output refers to center of undistorted+leveled image +EFL = 598.0 # focal length in K +cam = DEVICE_CAMERAS[("tici", "ar0231")] # corrected image has same size as raw +W, H = (cam.dcam.width, cam.dcam.height) # corrected image has same size as raw + +def face_orientation_from_net(angles_desc, pos_desc, rpy_calib): + # the output of these angles are in device frame + # so from driver's perspective, pitch is up and yaw is right + + pitch_net, yaw_net, roll_net = angles_desc + + face_pixel_position = ((pos_desc[0]+0.5)*W, (pos_desc[1]+0.5)*H) + yaw_focal_angle = atan2(face_pixel_position[0] - W//2, EFL) + pitch_focal_angle = atan2(face_pixel_position[1] - H//2, EFL) + + pitch = pitch_net + pitch_focal_angle + yaw = -yaw_net + yaw_focal_angle + + # no calib for roll + pitch -= rpy_calib[1] + yaw -= rpy_calib[2] + return roll_net, pitch, yaw + + +class DriverMonitoring: + def __init__(self, rhd_saved=False, settings=None, always_on=False): + if settings is None: + settings = DRIVER_MONITOR_SETTINGS() + # init policy settings + self.settings = settings + + # init driver status + self.wheelpos_learner = RunningStatFilter() + self.pose = DriverPose(self.settings._POSE_OFFSET_MAX_COUNT) + self.blink = DriverBlink() + self.eev1 = 0. + self.ee1_offseter = RunningStatFilter(max_trackable=self.settings._POSE_OFFSET_MAX_COUNT) + self.ee1_calibrated = False + + self.always_on = always_on + self.distracted_types = [] + self.driver_distracted = False + self.driver_distraction_filter = FirstOrderFilter(0., self.settings._DISTRACTED_FILTER_TS, self.settings._DT_DMON) + self.wheel_on_right = False + self.wheel_on_right_last = None + self.wheel_on_right_default = rhd_saved + self.face_detected = False + self.terminal_alert_cnt = 0 + self.terminal_time = 0 + self.step_change = 0. + self.active_monitoring_mode = True + self.is_model_uncertain = False + self.hi_stds = 0 + self.threshold_pre = self.settings._DISTRACTED_PRE_TIME_TILL_TERMINAL / self.settings._DISTRACTED_TIME + self.threshold_prompt = self.settings._DISTRACTED_PROMPT_TIME_TILL_TERMINAL / self.settings._DISTRACTED_TIME + + self.params = Params() + self.too_distracted = self.params.get_bool("DriverTooDistracted") + + self._reset_awareness() + self._set_timers(active_monitoring=True) + self._reset_events() + + def _reset_awareness(self): + self.awareness = 1. + self.awareness_active = 1. + self.awareness_passive = 1. + + def _reset_events(self): + self.current_events = Events() + + def _set_timers(self, active_monitoring): + if self.active_monitoring_mode and self.awareness <= self.threshold_prompt: + if active_monitoring: + self.step_change = self.settings._DT_DMON / self.settings._DISTRACTED_TIME + else: + self.step_change = 0. + return # no exploit after orange alert + elif self.awareness <= 0.: + return + + if active_monitoring: + # when falling back from passive mode to active mode, reset awareness to avoid false alert + if not self.active_monitoring_mode: + self.awareness_passive = self.awareness + self.awareness = self.awareness_active + + self.threshold_pre = self.settings._DISTRACTED_PRE_TIME_TILL_TERMINAL / self.settings._DISTRACTED_TIME + self.threshold_prompt = self.settings._DISTRACTED_PROMPT_TIME_TILL_TERMINAL / self.settings._DISTRACTED_TIME + self.step_change = self.settings._DT_DMON / self.settings._DISTRACTED_TIME + self.active_monitoring_mode = True + else: + if self.active_monitoring_mode: + self.awareness_active = self.awareness + self.awareness = self.awareness_passive + + self.threshold_pre = self.settings._AWARENESS_PRE_TIME_TILL_TERMINAL / self.settings._AWARENESS_TIME + self.threshold_prompt = self.settings._AWARENESS_PROMPT_TIME_TILL_TERMINAL / self.settings._AWARENESS_TIME + self.step_change = self.settings._DT_DMON / self.settings._AWARENESS_TIME + self.active_monitoring_mode = False + + def _set_policy(self, model_data, car_speed): + bp = model_data.meta.disengagePredictions.brakeDisengageProbs[0] # brake disengage prob in next 2s + k1 = max(-0.00156*((car_speed-16)**2)+0.6, 0.2) + bp_normal = max(min(bp / k1, 0.5),0) + self.pose.cfactor_pitch = np.interp(bp_normal, [0, 0.5], + [self.settings._POSE_PITCH_THRESHOLD_SLACK, + self.settings._POSE_PITCH_THRESHOLD_STRICT]) / self.settings._POSE_PITCH_THRESHOLD + self.pose.cfactor_yaw = np.interp(bp_normal, [0, 0.5], + [self.settings._POSE_YAW_THRESHOLD_SLACK, + self.settings._POSE_YAW_THRESHOLD_STRICT]) / self.settings._POSE_YAW_THRESHOLD + + def _get_distracted_types(self): + distracted_types = [] + + if not self.pose.calibrated: + pitch_error = self.pose.pitch - self.settings._PITCH_NATURAL_OFFSET + yaw_error = self.pose.yaw - self.settings._YAW_NATURAL_OFFSET + else: + pitch_error = self.pose.pitch - min(max(self.pose.pitch_offseter.filtered_stat.mean(), + self.settings._PITCH_MIN_OFFSET), self.settings._PITCH_MAX_OFFSET) + yaw_error = self.pose.yaw - min(max(self.pose.yaw_offseter.filtered_stat.mean(), + self.settings._YAW_MIN_OFFSET), self.settings._YAW_MAX_OFFSET) + pitch_error = 0 if pitch_error > 0 else abs(pitch_error) # no positive pitch limit + yaw_error = abs(yaw_error) + if pitch_error > (self.settings._POSE_PITCH_THRESHOLD*self.pose.cfactor_pitch if self.pose.calibrated else self.settings._PITCH_NATURAL_THRESHOLD) or \ + yaw_error > self.settings._POSE_YAW_THRESHOLD*self.pose.cfactor_yaw: + distracted_types.append(DistractedType.DISTRACTED_POSE) + + if (self.blink.left + self.blink.right)*0.5 > self.settings._BLINK_THRESHOLD: + distracted_types.append(DistractedType.DISTRACTED_BLINK) + + if self.ee1_calibrated: + ee1_dist = self.eev1 > max(min(self.ee1_offseter.filtered_stat.M, self.settings._EE_MAX_OFFSET1), self.settings._EE_MIN_OFFSET1) \ + * self.settings._EE_THRESH12 + else: + ee1_dist = self.eev1 > self.settings._EE_THRESH11 + if ee1_dist: + distracted_types.append(DistractedType.DISTRACTED_E2E) + + return distracted_types + + def _update_states(self, driver_state, cal_rpy, car_speed, op_engaged): + rhd_pred = driver_state.wheelOnRightProb + # calibrates only when there's movement and either face detected + if car_speed > self.settings._WHEELPOS_CALIB_MIN_SPEED and (driver_state.leftDriverData.faceProb > self.settings._FACE_THRESHOLD or + driver_state.rightDriverData.faceProb > self.settings._FACE_THRESHOLD): + self.wheelpos_learner.push_and_update(rhd_pred) + if self.wheelpos_learner.filtered_stat.n > self.settings._WHEELPOS_FILTER_MIN_COUNT: + self.wheel_on_right = self.wheelpos_learner.filtered_stat.M > self.settings._WHEELPOS_THRESHOLD + else: + self.wheel_on_right = self.wheel_on_right_default # use default/saved if calibration is unfinished + # make sure no switching when engaged + if op_engaged and self.wheel_on_right_last is not None and self.wheel_on_right_last != self.wheel_on_right: + self.wheel_on_right = self.wheel_on_right_last + driver_data = driver_state.rightDriverData if self.wheel_on_right else driver_state.leftDriverData + if not all(len(x) > 0 for x in (driver_data.faceOrientation, driver_data.facePosition, + driver_data.faceOrientationStd, driver_data.facePositionStd, + driver_data.notReadyProb)): + return + + self.face_detected = driver_data.faceProb > self.settings._FACE_THRESHOLD + self.pose.roll, self.pose.pitch, self.pose.yaw = face_orientation_from_net(driver_data.faceOrientation, driver_data.facePosition, cal_rpy) + if self.wheel_on_right: + self.pose.yaw *= -1 + self.wheel_on_right_last = self.wheel_on_right + self.pose.pitch_std = driver_data.faceOrientationStd[0] + self.pose.yaw_std = driver_data.faceOrientationStd[1] + model_std_max = max(self.pose.pitch_std, self.pose.yaw_std) + self.pose.low_std = model_std_max < self.settings._POSESTD_THRESHOLD + self.blink.left = driver_data.leftBlinkProb * (driver_data.leftEyeProb > self.settings._EYE_THRESHOLD) \ + * (driver_data.sunglassesProb < self.settings._SG_THRESHOLD) + self.blink.right = driver_data.rightBlinkProb * (driver_data.rightEyeProb > self.settings._EYE_THRESHOLD) \ + * (driver_data.sunglassesProb < self.settings._SG_THRESHOLD) + self.eev1 = driver_data.notReadyProb[0] + + self.distracted_types = self._get_distracted_types() + self.driver_distracted = (DistractedType.DISTRACTED_E2E in self.distracted_types or DistractedType.DISTRACTED_POSE in self.distracted_types + or DistractedType.DISTRACTED_BLINK in self.distracted_types) \ + and driver_data.faceProb > self.settings._FACE_THRESHOLD and self.pose.low_std + self.driver_distraction_filter.update(self.driver_distracted) + + # update offseter + # only update when driver is actively driving the car above a certain speed + if self.face_detected and car_speed > self.settings._POSE_CALIB_MIN_SPEED and self.pose.low_std and (not op_engaged or not self.driver_distracted): + self.pose.pitch_offseter.push_and_update(self.pose.pitch) + self.pose.yaw_offseter.push_and_update(self.pose.yaw) + self.ee1_offseter.push_and_update(self.eev1) + + self.pose.calibrated = self.pose.pitch_offseter.filtered_stat.n > self.settings._POSE_OFFSET_MIN_COUNT and \ + self.pose.yaw_offseter.filtered_stat.n > self.settings._POSE_OFFSET_MIN_COUNT + self.ee1_calibrated = self.ee1_offseter.filtered_stat.n > self.settings._POSE_OFFSET_MIN_COUNT + + self.is_model_uncertain = self.hi_stds > self.settings._HI_STD_FALLBACK_TIME + self._set_timers(self.face_detected and not self.is_model_uncertain) + if self.face_detected and not self.pose.low_std and not self.driver_distracted: + self.hi_stds += 1 + elif self.face_detected and self.pose.low_std: + self.hi_stds = 0 + + def _update_events(self, driver_engaged, op_engaged, standstill, wrong_gear, car_speed): + self._reset_events() + # Block engaging until ignition cycle after max number or time of distractions + if self.terminal_alert_cnt >= self.settings._MAX_TERMINAL_ALERTS or \ + self.terminal_time >= self.settings._MAX_TERMINAL_DURATION: + if not self.too_distracted: + self.params.put_bool_nonblocking("DriverTooDistracted", True) + self.too_distracted = True + + # Always-on distraction lockout is temporary + if self.too_distracted or (self.always_on and self.awareness <= self.threshold_prompt): + self.current_events.add(EventName.tooDistracted) + + always_on_valid = self.always_on and not wrong_gear + if (driver_engaged and self.awareness > 0 and not self.active_monitoring_mode) or \ + (not always_on_valid and not op_engaged) or \ + (always_on_valid and not op_engaged and self.awareness <= 0): + # always reset on disengage with normal mode; disengage resets only on red if always on + self._reset_awareness() + return + + driver_attentive = self.driver_distraction_filter.x < 0.37 + awareness_prev = self.awareness + + if (driver_attentive and self.face_detected and self.pose.low_std and self.awareness > 0): + if driver_engaged: + self._reset_awareness() + return + # only restore awareness when paying attention and alert is not red + self.awareness = min(self.awareness + ((self.settings._RECOVERY_FACTOR_MAX-self.settings._RECOVERY_FACTOR_MIN)* + (1.-self.awareness)+self.settings._RECOVERY_FACTOR_MIN)*self.step_change, 1.) + if self.awareness == 1.: + self.awareness_passive = min(self.awareness_passive + self.step_change, 1.) + # don't display alert banner when awareness is recovering and has cleared orange + if self.awareness > self.threshold_prompt: + return + + _reaching_audible = self.awareness - self.step_change <= self.threshold_prompt + _reaching_terminal = self.awareness - self.step_change <= 0 + standstill_orange_exemption = standstill and _reaching_audible + always_on_red_exemption = always_on_valid and not op_engaged and _reaching_terminal + always_on_lowspeed_exemption = always_on_valid and not op_engaged and car_speed < self.settings._ALWAYS_ON_ALERT_MIN_SPEED + + certainly_distracted = self.driver_distraction_filter.x > 0.63 and self.driver_distracted and self.face_detected + maybe_distracted = self.hi_stds > self.settings._HI_STD_FALLBACK_TIME or not self.face_detected + + if certainly_distracted or maybe_distracted: + # should always be counting if distracted unless at standstill (lowspeed for always-on) and reaching orange + # also will not be reaching 0 if DM is active when not engaged + if not (standstill_orange_exemption or always_on_red_exemption or (always_on_lowspeed_exemption and _reaching_audible)): + self.awareness = max(self.awareness - self.step_change, -0.1) + + alert = None + if self.awareness <= 0.: + # terminal red alert: disengagement required + alert = EventName.driverDistracted if self.active_monitoring_mode else EventName.driverUnresponsive + self.terminal_time += 1 + if awareness_prev > 0.: + self.terminal_alert_cnt += 1 + elif self.awareness <= self.threshold_prompt: + # prompt orange alert + alert = EventName.promptDriverDistracted if self.active_monitoring_mode else EventName.promptDriverUnresponsive + elif self.awareness <= self.threshold_pre and not always_on_lowspeed_exemption: + # pre green alert + alert = EventName.preDriverDistracted if self.active_monitoring_mode else EventName.preDriverUnresponsive + + if alert is not None: + self.current_events.add(alert) + + + def get_state_packet(self, valid=True): + # build driverMonitoringState packet + dat = messaging.new_message('driverMonitoringState', valid=valid) + dat.driverMonitoringState = { + "events": self.current_events.to_msg(), + "faceDetected": self.face_detected, + "isDistracted": self.driver_distracted, + "distractedType": sum(self.distracted_types), + "awarenessStatus": self.awareness, + "posePitchOffset": self.pose.pitch_offseter.filtered_stat.mean(), + "posePitchValidCount": self.pose.pitch_offseter.filtered_stat.n, + "poseYawOffset": self.pose.yaw_offseter.filtered_stat.mean(), + "poseYawValidCount": self.pose.yaw_offseter.filtered_stat.n, + "stepChange": self.step_change, + "awarenessActive": self.awareness_active, + "awarenessPassive": self.awareness_passive, + "isLowStd": self.pose.low_std, + "hiStdCount": self.hi_stds, + "isActiveMode": self.active_monitoring_mode, + "isRHD": self.wheel_on_right, + } + return dat + + def run_step(self, sm): + # Set strictness + self._set_policy( + model_data=sm['modelV2'], + car_speed=sm['carState'].vEgo + ) + + # Parse data from dmonitoringmodeld + self._update_states( + driver_state=sm['driverStateV2'], + cal_rpy=sm['liveCalibration'].rpyCalib, + car_speed=sm['carState'].vEgo, + op_engaged=sm['selfdriveState'].enabled + ) + + # Update distraction events + self._update_events( + driver_engaged=sm['carState'].steeringPressed or sm['carState'].gasPressed, + op_engaged=sm['selfdriveState'].enabled, + standstill=sm['carState'].standstill, + wrong_gear=sm['carState'].gearShifter in [car.CarState.GearShifter.reverse, car.CarState.GearShifter.park], + car_speed=sm['carState'].vEgo + ) diff --git a/selfdrive/monitoring/test_monitoring.py b/selfdrive/monitoring/test_monitoring.py new file mode 100644 index 0000000000..1cc7101880 --- /dev/null +++ b/selfdrive/monitoring/test_monitoring.py @@ -0,0 +1,205 @@ +import numpy as np + +from cereal import log +from openpilot.common.realtime import DT_DMON +from openpilot.selfdrive.monitoring.helpers import DriverMonitoring, DRIVER_MONITOR_SETTINGS + +EventName = log.OnroadEvent.EventName +dm_settings = DRIVER_MONITOR_SETTINGS() + +TEST_TIMESPAN = 120 # seconds +DISTRACTED_SECONDS_TO_ORANGE = dm_settings._DISTRACTED_TIME - dm_settings._DISTRACTED_PROMPT_TIME_TILL_TERMINAL + 1 +DISTRACTED_SECONDS_TO_RED = dm_settings._DISTRACTED_TIME + 1 +INVISIBLE_SECONDS_TO_ORANGE = dm_settings._AWARENESS_TIME - dm_settings._AWARENESS_PROMPT_TIME_TILL_TERMINAL + 1 +INVISIBLE_SECONDS_TO_RED = dm_settings._AWARENESS_TIME + 1 + +def make_msg(face_detected, distracted=False, model_uncertain=False): + ds = log.DriverStateV2.new_message() + ds.leftDriverData.faceOrientation = [0., 0., 0.] + ds.leftDriverData.facePosition = [0., 0.] + ds.leftDriverData.faceProb = 1. * face_detected + ds.leftDriverData.leftEyeProb = 1. + ds.leftDriverData.rightEyeProb = 1. + ds.leftDriverData.leftBlinkProb = 1. * distracted + ds.leftDriverData.rightBlinkProb = 1. * distracted + ds.leftDriverData.faceOrientationStd = [1.*model_uncertain, 1.*model_uncertain, 1.*model_uncertain] + ds.leftDriverData.facePositionStd = [1.*model_uncertain, 1.*model_uncertain] + # TODO: test both separately when e2e is used + ds.leftDriverData.notReadyProb = [0., 0.] + return ds + + +# driver state from neural net, 10Hz +msg_NO_FACE_DETECTED = make_msg(False) +msg_ATTENTIVE = make_msg(True) +msg_DISTRACTED = make_msg(True, distracted=True) +msg_ATTENTIVE_UNCERTAIN = make_msg(True, model_uncertain=True) +msg_DISTRACTED_UNCERTAIN = make_msg(True, distracted=True, model_uncertain=True) +msg_DISTRACTED_BUT_SOMEHOW_UNCERTAIN = make_msg(True, distracted=True, model_uncertain=dm_settings._POSESTD_THRESHOLD*1.5) + +# driver interaction with car +car_interaction_DETECTED = True +car_interaction_NOT_DETECTED = False + +# some common state vectors +always_no_face = [msg_NO_FACE_DETECTED] * int(TEST_TIMESPAN / DT_DMON) +always_attentive = [msg_ATTENTIVE] * int(TEST_TIMESPAN / DT_DMON) +always_distracted = [msg_DISTRACTED] * int(TEST_TIMESPAN / DT_DMON) +always_true = [True] * int(TEST_TIMESPAN / DT_DMON) +always_false = [False] * int(TEST_TIMESPAN / DT_DMON) + +class TestMonitoring: + def _run_seq(self, msgs, interaction, engaged, standstill): + DM = DriverMonitoring() + events = [] + for idx in range(len(msgs)): + DM._update_states(msgs[idx], [0, 0, 0], 0, engaged[idx]) + # cal_rpy and car_speed don't matter here + + # evaluate events at 10Hz for tests + DM._update_events(interaction[idx], engaged[idx], standstill[idx], 0, 0) + events.append(DM.current_events) + assert len(events) == len(msgs), f"got {len(events)} for {len(msgs)} driverState input msgs" + return events, DM + + def _assert_no_events(self, events): + assert all(not len(e) for e in events) + + # engaged, driver is attentive all the time + def test_fully_aware_driver(self): + events, _ = self._run_seq(always_attentive, always_false, always_true, always_false) + self._assert_no_events(events) + + # engaged, driver is distracted and does nothing + def test_fully_distracted_driver(self): + events, d_status = self._run_seq(always_distracted, always_false, always_true, always_false) + assert len(events[int((d_status.settings._DISTRACTED_TIME-d_status.settings._DISTRACTED_PRE_TIME_TILL_TERMINAL)/2/DT_DMON)]) == 0 + assert events[int((d_status.settings._DISTRACTED_TIME-d_status.settings._DISTRACTED_PRE_TIME_TILL_TERMINAL + \ + ((d_status.settings._DISTRACTED_PRE_TIME_TILL_TERMINAL-d_status.settings._DISTRACTED_PROMPT_TIME_TILL_TERMINAL)/2))/DT_DMON)].names[0] == \ + EventName.preDriverDistracted + assert events[int((d_status.settings._DISTRACTED_TIME-d_status.settings._DISTRACTED_PROMPT_TIME_TILL_TERMINAL + \ + ((d_status.settings._DISTRACTED_PROMPT_TIME_TILL_TERMINAL)/2))/DT_DMON)].names[0] == EventName.promptDriverDistracted + assert events[int((d_status.settings._DISTRACTED_TIME + \ + ((TEST_TIMESPAN-10-d_status.settings._DISTRACTED_TIME)/2))/DT_DMON)].names[0] == EventName.driverDistracted + assert isinstance(d_status.awareness, float) + + # engaged, no face detected the whole time, no action + def test_fully_invisible_driver(self): + events, d_status = self._run_seq(always_no_face, always_false, always_true, always_false) + assert len(events[int((d_status.settings._AWARENESS_TIME-d_status.settings._AWARENESS_PRE_TIME_TILL_TERMINAL)/2/DT_DMON)]) == 0 + assert events[int((d_status.settings._AWARENESS_TIME-d_status.settings._AWARENESS_PRE_TIME_TILL_TERMINAL + \ + ((d_status.settings._AWARENESS_PRE_TIME_TILL_TERMINAL-d_status.settings._AWARENESS_PROMPT_TIME_TILL_TERMINAL)/2))/DT_DMON)].names[0] == \ + EventName.preDriverUnresponsive + assert events[int((d_status.settings._AWARENESS_TIME-d_status.settings._AWARENESS_PROMPT_TIME_TILL_TERMINAL + \ + ((d_status.settings._AWARENESS_PROMPT_TIME_TILL_TERMINAL)/2))/DT_DMON)].names[0] == EventName.promptDriverUnresponsive + assert events[int((d_status.settings._AWARENESS_TIME + \ + ((TEST_TIMESPAN-10-d_status.settings._AWARENESS_TIME)/2))/DT_DMON)].names[0] == EventName.driverUnresponsive + + # engaged, down to orange, driver pays attention, back to normal; then down to orange, driver touches wheel + # - should have short orange recovery time and no green afterwards; wheel touch only recovers when paying attention + def test_normal_driver(self): + ds_vector = [msg_DISTRACTED] * int(DISTRACTED_SECONDS_TO_ORANGE/DT_DMON) + \ + [msg_ATTENTIVE] * int(DISTRACTED_SECONDS_TO_ORANGE/DT_DMON) + \ + [msg_DISTRACTED] * int((DISTRACTED_SECONDS_TO_ORANGE+2)/DT_DMON) + \ + [msg_ATTENTIVE] * (int(TEST_TIMESPAN/DT_DMON)-int((DISTRACTED_SECONDS_TO_ORANGE*3+2)/DT_DMON)) + interaction_vector = [car_interaction_NOT_DETECTED] * int(DISTRACTED_SECONDS_TO_ORANGE*3/DT_DMON) + \ + [car_interaction_DETECTED] * (int(TEST_TIMESPAN/DT_DMON)-int(DISTRACTED_SECONDS_TO_ORANGE*3/DT_DMON)) + events, _ = self._run_seq(ds_vector, interaction_vector, always_true, always_false) + assert len(events[int(DISTRACTED_SECONDS_TO_ORANGE*0.5/DT_DMON)]) == 0 + assert events[int((DISTRACTED_SECONDS_TO_ORANGE-0.1)/DT_DMON)].names[0] == EventName.promptDriverDistracted + assert len(events[int(DISTRACTED_SECONDS_TO_ORANGE*1.5/DT_DMON)]) == 0 + assert events[int((DISTRACTED_SECONDS_TO_ORANGE*3-0.1)/DT_DMON)].names[0] == EventName.promptDriverDistracted + assert events[int((DISTRACTED_SECONDS_TO_ORANGE*3+0.1)/DT_DMON)].names[0] == EventName.promptDriverDistracted + assert len(events[int((DISTRACTED_SECONDS_TO_ORANGE*3+2.5)/DT_DMON)]) == 0 + + # engaged, down to orange, driver dodges camera, then comes back still distracted, down to red, \ + # driver dodges, and then touches wheel to no avail, disengages and reengages + # - orange/red alert should remain after disappearance, and only disengaging clears red + def test_biggest_comma_fan(self): + _invisible_time = 2 # seconds + ds_vector = always_distracted[:] + interaction_vector = always_false[:] + op_vector = always_true[:] + ds_vector[int(DISTRACTED_SECONDS_TO_ORANGE/DT_DMON):int((DISTRACTED_SECONDS_TO_ORANGE+_invisible_time)/DT_DMON)] \ + = [msg_NO_FACE_DETECTED] * int(_invisible_time/DT_DMON) + ds_vector[int((DISTRACTED_SECONDS_TO_RED+_invisible_time)/DT_DMON):int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time)/DT_DMON)] \ + = [msg_NO_FACE_DETECTED] * int(_invisible_time/DT_DMON) + interaction_vector[int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time+0.5)/DT_DMON):int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time+1.5)/DT_DMON)] \ + = [True] * int(1/DT_DMON) + op_vector[int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time+2.5)/DT_DMON):int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time+3)/DT_DMON)] \ + = [False] * int(0.5/DT_DMON) + events, _ = self._run_seq(ds_vector, interaction_vector, op_vector, always_false) + assert events[int((DISTRACTED_SECONDS_TO_ORANGE+0.5*_invisible_time)/DT_DMON)].names[0] == EventName.promptDriverDistracted + assert events[int((DISTRACTED_SECONDS_TO_RED+1.5*_invisible_time)/DT_DMON)].names[0] == EventName.driverDistracted + assert events[int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time+1.5)/DT_DMON)].names[0] == EventName.driverDistracted + assert len(events[int((DISTRACTED_SECONDS_TO_RED+2*_invisible_time+3.5)/DT_DMON)]) == 0 + + # engaged, invisible driver, down to orange, driver touches wheel; then down to orange again, driver appears + # - both actions should clear the alert, but momentary appearance should not + def test_sometimes_transparent_commuter(self): + _visible_time = np.random.choice([0.5, 10]) + ds_vector = always_no_face[:]*2 + interaction_vector = always_false[:]*2 + ds_vector[int((2*INVISIBLE_SECONDS_TO_ORANGE+1)/DT_DMON):int((2*INVISIBLE_SECONDS_TO_ORANGE+1+_visible_time)/DT_DMON)] = \ + [msg_ATTENTIVE] * int(_visible_time/DT_DMON) + interaction_vector[int((INVISIBLE_SECONDS_TO_ORANGE)/DT_DMON):int((INVISIBLE_SECONDS_TO_ORANGE+1)/DT_DMON)] = [True] * int(1/DT_DMON) + events, _ = self._run_seq(ds_vector, interaction_vector, 2*always_true, 2*always_false) + assert len(events[int(INVISIBLE_SECONDS_TO_ORANGE*0.5/DT_DMON)]) == 0 + assert events[int((INVISIBLE_SECONDS_TO_ORANGE-0.1)/DT_DMON)].names[0] == EventName.promptDriverUnresponsive + assert len(events[int((INVISIBLE_SECONDS_TO_ORANGE+0.1)/DT_DMON)]) == 0 + if _visible_time == 0.5: + assert events[int((INVISIBLE_SECONDS_TO_ORANGE*2+1-0.1)/DT_DMON)].names[0] == EventName.promptDriverUnresponsive + assert events[int((INVISIBLE_SECONDS_TO_ORANGE*2+1+0.1+_visible_time)/DT_DMON)].names[0] == EventName.preDriverUnresponsive + elif _visible_time == 10: + assert events[int((INVISIBLE_SECONDS_TO_ORANGE*2+1-0.1)/DT_DMON)].names[0] == EventName.promptDriverUnresponsive + assert len(events[int((INVISIBLE_SECONDS_TO_ORANGE*2+1+0.1+_visible_time)/DT_DMON)]) == 0 + + # engaged, invisible driver, down to red, driver appears and then touches wheel, then disengages/reengages + # - only disengage will clear the alert + def test_last_second_responder(self): + _visible_time = 2 # seconds + ds_vector = always_no_face[:] + interaction_vector = always_false[:] + op_vector = always_true[:] + ds_vector[int(INVISIBLE_SECONDS_TO_RED/DT_DMON):int((INVISIBLE_SECONDS_TO_RED+_visible_time)/DT_DMON)] = [msg_ATTENTIVE] * int(_visible_time/DT_DMON) + interaction_vector[int((INVISIBLE_SECONDS_TO_RED+_visible_time)/DT_DMON):int((INVISIBLE_SECONDS_TO_RED+_visible_time+1)/DT_DMON)] = [True] * int(1/DT_DMON) + op_vector[int((INVISIBLE_SECONDS_TO_RED+_visible_time+1)/DT_DMON):int((INVISIBLE_SECONDS_TO_RED+_visible_time+0.5)/DT_DMON)] = [False] * int(0.5/DT_DMON) + events, _ = self._run_seq(ds_vector, interaction_vector, op_vector, always_false) + assert len(events[int(INVISIBLE_SECONDS_TO_ORANGE*0.5/DT_DMON)]) == 0 + assert events[int((INVISIBLE_SECONDS_TO_ORANGE-0.1)/DT_DMON)].names[0] == EventName.promptDriverUnresponsive + assert events[int((INVISIBLE_SECONDS_TO_RED-0.1)/DT_DMON)].names[0] == EventName.driverUnresponsive + assert events[int((INVISIBLE_SECONDS_TO_RED+0.5*_visible_time)/DT_DMON)].names[0] == EventName.driverUnresponsive + assert events[int((INVISIBLE_SECONDS_TO_RED+_visible_time+0.5)/DT_DMON)].names[0] == EventName.driverUnresponsive + assert len(events[int((INVISIBLE_SECONDS_TO_RED+_visible_time+1+0.1)/DT_DMON)]) == 0 + + # disengaged, always distracted driver + # - dm should stay quiet when not engaged + def test_pure_dashcam_user(self): + events, _ = self._run_seq(always_distracted, always_false, always_false, always_false) + assert sum(len(event) for event in events) == 0 + + # engaged, car stops at traffic light, down to orange, no action, then car starts moving + # - should only reach green when stopped, but continues counting down on launch + def test_long_traffic_light_victim(self): + _redlight_time = 60 # seconds + standstill_vector = always_true[:] + standstill_vector[int(_redlight_time/DT_DMON):] = [False] * int((TEST_TIMESPAN-_redlight_time)/DT_DMON) + events, d_status = self._run_seq(always_distracted, always_false, always_true, standstill_vector) + assert events[int((d_status.settings._DISTRACTED_TIME-d_status.settings._DISTRACTED_PRE_TIME_TILL_TERMINAL+1)/DT_DMON)].names[0] == \ + EventName.preDriverDistracted + assert events[int((_redlight_time-0.1)/DT_DMON)].names[0] == EventName.preDriverDistracted + assert events[int((_redlight_time+0.5)/DT_DMON)].names[0] == EventName.promptDriverDistracted + + # engaged, model is somehow uncertain and driver is distracted + # - should fall back to wheel touch after uncertain alert + def test_somehow_indecisive_model(self): + ds_vector = [msg_DISTRACTED_BUT_SOMEHOW_UNCERTAIN] * int(TEST_TIMESPAN/DT_DMON) + interaction_vector = always_false[:] + events, d_status = self._run_seq(ds_vector, interaction_vector, always_true, always_false) + assert EventName.preDriverUnresponsive in \ + events[int((INVISIBLE_SECONDS_TO_ORANGE-1+DT_DMON*d_status.settings._HI_STD_FALLBACK_TIME-0.1)/DT_DMON)].names + assert EventName.promptDriverUnresponsive in \ + events[int((INVISIBLE_SECONDS_TO_ORANGE-1+DT_DMON*d_status.settings._HI_STD_FALLBACK_TIME+0.1)/DT_DMON)].names + assert EventName.driverUnresponsive in \ + events[int((INVISIBLE_SECONDS_TO_RED-1+DT_DMON*d_status.settings._HI_STD_FALLBACK_TIME+0.1)/DT_DMON)].names + diff --git a/selfdrive/pandad/.gitignore b/selfdrive/pandad/.gitignore new file mode 100644 index 0000000000..f7226cdb87 --- /dev/null +++ b/selfdrive/pandad/.gitignore @@ -0,0 +1,3 @@ +pandad +pandad_api_impl.cpp +tests/test_pandad_usbprotocol diff --git a/selfdrive/pandad/SConscript b/selfdrive/pandad/SConscript new file mode 100644 index 0000000000..58777cafe9 --- /dev/null +++ b/selfdrive/pandad/SConscript @@ -0,0 +1,13 @@ +Import('env', 'envCython', 'common', 'messaging') + +libs = ['usb-1.0', common, messaging, 'pthread'] +panda = env.Library('panda', ['panda.cc', 'panda_comms.cc', 'spi.cc']) + +env.Program('pandad', ['main.cc', 'pandad.cc', 'panda_safety.cc'], LIBS=[panda] + libs) +env.Library('libcan_list_to_can_capnp', ['can_list_to_can_capnp.cc']) + +pandad_python = envCython.Program('pandad_api_impl.so', 'pandad_api_impl.pyx', LIBS=["can_list_to_can_capnp", 'capnp', 'kj'] + envCython["LIBS"]) +Export('pandad_python') + +if GetOption('extras'): + env.Program('tests/test_pandad_usbprotocol', ['tests/test_pandad_usbprotocol.cc'], LIBS=[panda] + libs) diff --git a/selfdrive/pandad/__init__.py b/selfdrive/pandad/__init__.py new file mode 100644 index 0000000000..cc680e1676 --- /dev/null +++ b/selfdrive/pandad/__init__.py @@ -0,0 +1,4 @@ +# Cython, now uses scons to build +from openpilot.selfdrive.pandad.pandad_api_impl import can_list_to_can_capnp, can_capnp_to_list +assert can_list_to_can_capnp +assert can_capnp_to_list diff --git a/selfdrive/pandad/can_list_to_can_capnp.cc b/selfdrive/pandad/can_list_to_can_capnp.cc new file mode 100644 index 0000000000..f2cf153453 --- /dev/null +++ b/selfdrive/pandad/can_list_to_can_capnp.cc @@ -0,0 +1,50 @@ +#include "cereal/messaging/messaging.h" +#include "selfdrive/pandad/can_types.h" + +void can_list_to_can_capnp_cpp(const std::vector &can_list, std::string &out, bool sendcan, bool valid) { + MessageBuilder msg; + auto event = msg.initEvent(valid); + + auto canData = sendcan ? event.initSendcan(can_list.size()) : event.initCan(can_list.size()); + int j = 0; + for (auto it = can_list.begin(); it != can_list.end(); it++, j++) { + auto c = canData[j]; + c.setAddress(it->address); + c.setDat(kj::arrayPtr((uint8_t*)it->dat.data(), it->dat.size())); + c.setSrc(it->src); + } + const uint64_t msg_size = capnp::computeSerializedSizeInWords(msg) * sizeof(capnp::word); + out.resize(msg_size); + kj::ArrayOutputStream output_stream(kj::ArrayPtr((unsigned char *)out.data(), msg_size)); + capnp::writeMessage(output_stream, msg); +} + +// Converts a vector of Cap'n Proto serialized can strings into a vector of CanData structures. +void can_capnp_to_can_list_cpp(const std::vector &strings, std::vector &can_list, bool sendcan) { + AlignedBuffer aligned_buf; + can_list.reserve(strings.size()); + + for (const auto &str : strings) { + // extract the messages + capnp::FlatArrayMessageReader reader(aligned_buf.align(str.data(), str.size())); + cereal::Event::Reader event = reader.getRoot(); + + auto frames = sendcan ? event.getSendcan() : event.getCan(); + + // Add new CanData entry + CanData &can_data = can_list.emplace_back(); + can_data.nanos = event.getLogMonoTime(); + can_data.frames.reserve(frames.size()); + + // Populate CAN frames + for (const auto &frame : frames) { + CanFrame &can_frame = can_data.frames.emplace_back(); + can_frame.src = frame.getSrc(); + can_frame.address = frame.getAddress(); + + // Copy CAN data + auto dat = frame.getDat(); + can_frame.dat.assign(dat.begin(), dat.end()); + } + } +} diff --git a/selfdrive/pandad/can_types.h b/selfdrive/pandad/can_types.h new file mode 100644 index 0000000000..5fae581cfa --- /dev/null +++ b/selfdrive/pandad/can_types.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +struct CanFrame { + long src; + uint32_t address; + std::vector dat; +}; + +struct CanData { + uint64_t nanos; + std::vector frames; +}; \ No newline at end of file diff --git a/selfdrive/pandad/main.cc b/selfdrive/pandad/main.cc new file mode 100644 index 0000000000..b63d884a45 --- /dev/null +++ b/selfdrive/pandad/main.cc @@ -0,0 +1,22 @@ +#include + +#include "selfdrive/pandad/pandad.h" +#include "common/swaglog.h" +#include "common/util.h" +#include "system/hardware/hw.h" + +int main(int argc, char *argv[]) { + LOGW("starting pandad"); + + if (!Hardware::PC()) { + int err; + err = util::set_realtime_priority(54); + assert(err == 0); + err = util::set_core_affinity({3}); + assert(err == 0); + } + + std::vector serials(argv + 1, argv + argc); + pandad_main_thread(serials); + return 0; +} diff --git a/selfdrive/pandad/panda.cc b/selfdrive/pandad/panda.cc new file mode 100644 index 0000000000..93e139f0ec --- /dev/null +++ b/selfdrive/pandad/panda.cc @@ -0,0 +1,312 @@ +#include "selfdrive/pandad/panda.h" + +#include + +#include +#include +#include + +#include "cereal/messaging/messaging.h" +#include "common/swaglog.h" +#include "common/util.h" + +const bool PANDAD_MAXOUT = getenv("PANDAD_MAXOUT") != nullptr; + +Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) { + // try USB first, then SPI + try { + handle = std::make_unique(serial); + LOGW("connected to %s over USB", serial.c_str()); + } catch (std::exception &e) { +#ifndef __APPLE__ + handle = std::make_unique(serial); + LOGW("connected to %s over SPI", serial.c_str()); +#else + throw e; +#endif + } + + hw_type = get_hw_type(); + can_reset_communications(); +} + +bool Panda::connected() { + return handle->connected; +} + +bool Panda::comms_healthy() { + return handle->comms_healthy; +} + +std::string Panda::hw_serial() { + return handle->hw_serial; +} + +std::vector Panda::list(bool usb_only) { + std::vector serials = PandaUsbHandle::list(); + +#ifndef __APPLE__ + if (!usb_only) { + for (const auto &s : PandaSpiHandle::list()) { + if (std::find(serials.begin(), serials.end(), s) == serials.end()) { + serials.push_back(s); + } + } + } +#endif + + return serials; +} + +void Panda::set_safety_model(cereal::CarParams::SafetyModel safety_model, uint16_t safety_param) { + handle->control_write(0xdc, (uint16_t)safety_model, safety_param); +} + +void Panda::set_alternative_experience(uint16_t alternative_experience) { + handle->control_write(0xdf, alternative_experience, 0); +} + +std::string Panda::serial_read(int port_number) { + std::string ret; + char buffer[USBPACKET_MAX_SIZE] = {}; + + while (true) { + int bytes_read = handle->control_read(0xe0, port_number, 0, (unsigned char *)buffer, USBPACKET_MAX_SIZE); + if (bytes_read <= 0) { + break; + } + ret.append(buffer, bytes_read); + } + + return ret; +} + +void Panda::set_uart_baud(int uart, int rate) { + handle->control_write(0xe4, uart, int(rate / 300)); +} + +cereal::PandaState::PandaType Panda::get_hw_type() { + unsigned char hw_query[1] = {0}; + + handle->control_read(0xc1, 0, 0, hw_query, 1); + return (cereal::PandaState::PandaType)(hw_query[0]); +} + +void Panda::set_fan_speed(uint16_t fan_speed) { + handle->control_write(0xb1, fan_speed, 0); +} + +uint16_t Panda::get_fan_speed() { + uint16_t fan_speed_rpm = 0; + handle->control_read(0xb2, 0, 0, (unsigned char*)&fan_speed_rpm, sizeof(fan_speed_rpm)); + return fan_speed_rpm; +} + +void Panda::set_ir_pwr(uint16_t ir_pwr) { + handle->control_write(0xb0, ir_pwr, 0); +} + +std::optional Panda::get_state() { + health_t health {0}; + int err = handle->control_read(0xd2, 0, 0, (unsigned char*)&health, sizeof(health)); + return err >= 0 ? std::make_optional(health) : std::nullopt; +} + +std::optional Panda::get_can_state(uint16_t can_number) { + can_health_t can_health {0}; + int err = handle->control_read(0xc2, can_number, 0, (unsigned char*)&can_health, sizeof(can_health)); + return err >= 0 ? std::make_optional(can_health) : std::nullopt; +} + +void Panda::set_loopback(bool loopback) { + handle->control_write(0xe5, loopback, 0); +} + +std::optional> Panda::get_firmware_version() { + std::vector fw_sig_buf(128); + int read_1 = handle->control_read(0xd3, 0, 0, &fw_sig_buf[0], 64); + int read_2 = handle->control_read(0xd4, 0, 0, &fw_sig_buf[64], 64); + return ((read_1 == 64) && (read_2 == 64)) ? std::make_optional(fw_sig_buf) : std::nullopt; +} + +std::optional Panda::get_serial() { + char serial_buf[17] = {'\0'}; + int err = handle->control_read(0xd0, 0, 0, (uint8_t*)serial_buf, 16); + return err >= 0 ? std::make_optional(serial_buf) : std::nullopt; +} + +bool Panda::up_to_date() { + if (auto fw_sig = get_firmware_version()) { + for (auto fn : { "panda.bin.signed", "panda_h7.bin.signed" }) { + auto content = util::read_file(std::string("../../panda/board/obj/") + fn); + if (content.size() >= fw_sig->size() && + memcmp(content.data() + content.size() - fw_sig->size(), fw_sig->data(), fw_sig->size()) == 0) { + return true; + } + } + } + return false; +} + +void Panda::set_power_saving(bool power_saving) { + handle->control_write(0xe7, power_saving, 0); +} + +void Panda::enable_deepsleep() { + handle->control_write(0xfb, 0, 0); +} + +void Panda::send_heartbeat(bool engaged) { + handle->control_write(0xf3, engaged, 0); +} + +void Panda::set_can_speed_kbps(uint16_t bus, uint16_t speed) { + handle->control_write(0xde, bus, (speed * 10)); +} + +void Panda::set_can_fd_auto(uint16_t bus, bool enabled) { + handle->control_write(0xe8, bus, enabled); +} + +void Panda::set_data_speed_kbps(uint16_t bus, uint16_t speed) { + handle->control_write(0xf9, bus, (speed * 10)); +} + +void Panda::set_canfd_non_iso(uint16_t bus, bool non_iso) { + handle->control_write(0xfc, bus, non_iso); +} + +static uint8_t len_to_dlc(uint8_t len) { + if (len <= 8) { + return len; + } + if (len <= 24) { + return 8 + ((len - 8) / 4) + ((len % 4) ? 1 : 0); + } else { + return 11 + (len / 16) + ((len % 16) ? 1 : 0); + } +} + +void Panda::pack_can_buffer(const capnp::List::Reader &can_data_list, + std::function write_func) { + int32_t pos = 0; + uint8_t send_buf[2 * USB_TX_SOFT_LIMIT]; + + for (const auto &cmsg : can_data_list) { + // check if the message is intended for this panda + uint8_t bus = cmsg.getSrc(); + if (bus < bus_offset || bus >= (bus_offset + PANDA_BUS_OFFSET)) { + continue; + } + auto can_data = cmsg.getDat(); + uint8_t data_len_code = len_to_dlc(can_data.size()); + assert(can_data.size() <= 64); + assert(can_data.size() == dlc_to_len[data_len_code]); + + can_header header = {}; + header.addr = cmsg.getAddress(); + header.extended = (cmsg.getAddress() >= 0x800) ? 1 : 0; + header.data_len_code = data_len_code; + header.bus = bus - bus_offset; + header.checksum = 0; + + memcpy(&send_buf[pos], (uint8_t *)&header, sizeof(can_header)); + memcpy(&send_buf[pos + sizeof(can_header)], (uint8_t *)can_data.begin(), can_data.size()); + uint32_t msg_size = sizeof(can_header) + can_data.size(); + + // set checksum + ((can_header *) &send_buf[pos])->checksum = calculate_checksum(&send_buf[pos], msg_size); + + pos += msg_size; + + if (pos >= USB_TX_SOFT_LIMIT) { + write_func(send_buf, pos); + pos = 0; + } + } + + // send remaining packets + if (pos > 0) write_func(send_buf, pos); +} + +void Panda::can_send(const capnp::List::Reader &can_data_list) { + pack_can_buffer(can_data_list, [=](uint8_t* data, size_t size) { + handle->bulk_write(3, data, size, 5); + }); +} + +bool Panda::can_receive(std::vector& out_vec) { + // Check if enough space left in buffer to store RECV_SIZE data + assert(receive_buffer_size + RECV_SIZE <= sizeof(receive_buffer)); + + int recv = handle->bulk_read(0x81, &receive_buffer[receive_buffer_size], RECV_SIZE); + if (!comms_healthy()) { + return false; + } + + if (PANDAD_MAXOUT) { + static uint8_t junk[RECV_SIZE]; + handle->bulk_read(0xab, junk, RECV_SIZE - recv); + } + + bool ret = true; + if (recv > 0) { + receive_buffer_size += recv; + ret = unpack_can_buffer(receive_buffer, receive_buffer_size, out_vec); + } + return ret; +} + +void Panda::can_reset_communications() { + handle->control_write(0xc0, 0, 0); +} + +bool Panda::unpack_can_buffer(uint8_t *data, uint32_t &size, std::vector &out_vec) { + int pos = 0; + + while (pos <= size - sizeof(can_header)) { + can_header header; + memcpy(&header, &data[pos], sizeof(can_header)); + + const uint8_t data_len = dlc_to_len[header.data_len_code]; + if (pos + sizeof(can_header) + data_len > size) { + // we don't have all the data for this message yet + break; + } + + if (calculate_checksum(&data[pos], sizeof(can_header) + data_len) != 0) { + LOGE("Panda CAN checksum failed"); + size = 0; + can_reset_communications(); + return false; + } + + can_frame &canData = out_vec.emplace_back(); + canData.address = header.addr; + canData.src = header.bus + bus_offset; + if (header.rejected) { + canData.src += CAN_REJECTED_BUS_OFFSET; + } + if (header.returned) { + canData.src += CAN_RETURNED_BUS_OFFSET; + } + + canData.dat.assign((char *)&data[pos + sizeof(can_header)], data_len); + + pos += sizeof(can_header) + data_len; + } + + // move the overflowing data to the beginning of the buffer for the next round + memmove(data, &data[pos], size - pos); + size -= pos; + + return true; +} + +uint8_t Panda::calculate_checksum(uint8_t *data, uint32_t len) { + uint8_t checksum = 0U; + for (uint32_t i = 0U; i < len; i++) { + checksum ^= data[i]; + } + return checksum; +} diff --git a/selfdrive/pandad/panda.h b/selfdrive/pandad/panda.h new file mode 100644 index 0000000000..5cbce44f28 --- /dev/null +++ b/selfdrive/pandad/panda.h @@ -0,0 +1,99 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cereal/gen/cpp/car.capnp.h" +#include "cereal/gen/cpp/log.capnp.h" +#include "panda/board/health.h" +#include "panda/board/can.h" +#include "selfdrive/pandad/panda_comms.h" + +#define USB_TX_SOFT_LIMIT (0x100U) +#define USBPACKET_MAX_SIZE (0x40) + +#define RECV_SIZE (0x4000U) + +#define CAN_REJECTED_BUS_OFFSET 0xC0U +#define CAN_RETURNED_BUS_OFFSET 0x80U + +#define PANDA_BUS_OFFSET 4 + +struct __attribute__((packed)) can_header { + uint8_t reserved : 1; + uint8_t bus : 3; + uint8_t data_len_code : 4; + uint8_t rejected : 1; + uint8_t returned : 1; + uint8_t extended : 1; + uint32_t addr : 29; + uint8_t checksum : 8; +}; + +struct can_frame { + long address; + std::string dat; + long src; +}; + + +class Panda { +private: + std::unique_ptr handle; + +public: + Panda(std::string serial="", uint32_t bus_offset=0); + + cereal::PandaState::PandaType hw_type = cereal::PandaState::PandaType::UNKNOWN; + const uint32_t bus_offset; + + bool connected(); + bool comms_healthy(); + std::string hw_serial(); + + // Static functions + static std::vector list(bool usb_only=false); + + // Panda functionality + cereal::PandaState::PandaType get_hw_type(); + void set_safety_model(cereal::CarParams::SafetyModel safety_model, uint16_t safety_param=0U); + void set_alternative_experience(uint16_t alternative_experience); + std::string serial_read(int port_number = 0); + void set_uart_baud(int uart, int rate); + void set_fan_speed(uint16_t fan_speed); + uint16_t get_fan_speed(); + void set_ir_pwr(uint16_t ir_pwr); + std::optional get_state(); + std::optional get_can_state(uint16_t can_number); + void set_loopback(bool loopback); + std::optional> get_firmware_version(); + bool up_to_date(); + std::optional get_serial(); + void set_power_saving(bool power_saving); + void enable_deepsleep(); + void send_heartbeat(bool engaged); + void set_can_speed_kbps(uint16_t bus, uint16_t speed); + void set_can_fd_auto(uint16_t bus, bool enabled); + void set_data_speed_kbps(uint16_t bus, uint16_t speed); + void set_canfd_non_iso(uint16_t bus, bool non_iso); + void can_send(const capnp::List::Reader &can_data_list); + bool can_receive(std::vector& out_vec); + void can_reset_communications(); + +protected: + // for unit tests + uint8_t receive_buffer[RECV_SIZE + sizeof(can_header) + 64]; + uint32_t receive_buffer_size = 0; + + Panda(uint32_t bus_offset) : bus_offset(bus_offset) {} + void pack_can_buffer(const capnp::List::Reader &can_data_list, + std::function write_func); + bool unpack_can_buffer(uint8_t *data, uint32_t &size, std::vector &out_vec); + uint8_t calculate_checksum(uint8_t *data, uint32_t len); +}; diff --git a/selfdrive/pandad/panda_comms.cc b/selfdrive/pandad/panda_comms.cc new file mode 100644 index 0000000000..8a20f397d3 --- /dev/null +++ b/selfdrive/pandad/panda_comms.cc @@ -0,0 +1,227 @@ +#include "selfdrive/pandad/panda.h" + +#include +#include +#include + +#include "common/swaglog.h" + +static libusb_context *init_usb_ctx() { + libusb_context *context = nullptr; + int err = libusb_init(&context); + if (err != 0) { + LOGE("libusb initialization error"); + return nullptr; + } + +#if LIBUSB_API_VERSION >= 0x01000106 + libusb_set_option(context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); +#else + libusb_set_debug(context, 3); +#endif + return context; +} + +PandaUsbHandle::PandaUsbHandle(std::string serial) : PandaCommsHandle(serial) { + // init libusb + ssize_t num_devices; + libusb_device **dev_list = NULL; + int err = 0; + ctx = init_usb_ctx(); + if (!ctx) { goto fail; } + + // connect by serial + num_devices = libusb_get_device_list(ctx, &dev_list); + if (num_devices < 0) { goto fail; } + for (size_t i = 0; i < num_devices; ++i) { + libusb_device_descriptor desc; + libusb_get_device_descriptor(dev_list[i], &desc); + if (desc.idVendor == 0x3801 && desc.idProduct == 0xddcc) { + int ret = libusb_open(dev_list[i], &dev_handle); + if (dev_handle == NULL || ret < 0) { goto fail; } + + unsigned char desc_serial[26] = { 0 }; + ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, desc_serial, std::size(desc_serial)); + if (ret < 0) { goto fail; } + + hw_serial = std::string((char *)desc_serial, ret); + if (serial.empty() || serial == hw_serial) { + break; + } + libusb_close(dev_handle); + dev_handle = NULL; + } + } + if (dev_handle == NULL) goto fail; + libusb_free_device_list(dev_list, 1); + dev_list = nullptr; + + if (libusb_kernel_driver_active(dev_handle, 0) == 1) { + libusb_detach_kernel_driver(dev_handle, 0); + } + + err = libusb_set_configuration(dev_handle, 1); + if (err != 0) { goto fail; } + + err = libusb_claim_interface(dev_handle, 0); + if (err != 0) { goto fail; } + + return; + +fail: + if (dev_list != NULL) { + libusb_free_device_list(dev_list, 1); + } + cleanup(); + throw std::runtime_error("Error connecting to panda"); +} + +PandaUsbHandle::~PandaUsbHandle() { + std::lock_guard lk(hw_lock); + cleanup(); + connected = false; +} + +void PandaUsbHandle::cleanup() { + if (dev_handle) { + libusb_release_interface(dev_handle, 0); + libusb_close(dev_handle); + } + + if (ctx) { + libusb_exit(ctx); + } +} + +std::vector PandaUsbHandle::list() { + static std::unique_ptr context(init_usb_ctx(), libusb_exit); + // init libusb + ssize_t num_devices; + libusb_device **dev_list = NULL; + std::vector serials; + if (!context) { return serials; } + + num_devices = libusb_get_device_list(context.get(), &dev_list); + if (num_devices < 0) { + LOGE("libusb can't get device list"); + goto finish; + } + for (size_t i = 0; i < num_devices; ++i) { + libusb_device *device = dev_list[i]; + libusb_device_descriptor desc; + libusb_get_device_descriptor(device, &desc); + if (desc.idVendor == 0x3801 && desc.idProduct == 0xddcc) { + libusb_device_handle *handle = NULL; + int ret = libusb_open(device, &handle); + if (ret < 0) { goto finish; } + + unsigned char desc_serial[26] = { 0 }; + ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, desc_serial, std::size(desc_serial)); + libusb_close(handle); + if (ret < 0) { goto finish; } + + serials.push_back(std::string((char *)desc_serial, ret)); + } + } + +finish: + if (dev_list != NULL) { + libusb_free_device_list(dev_list, 1); + } + return serials; +} + +void PandaUsbHandle::handle_usb_issue(int err, const char func[]) { + LOGE_100("usb error %d \"%s\" in %s", err, libusb_strerror((enum libusb_error)err), func); + if (err == LIBUSB_ERROR_NO_DEVICE) { + LOGE("lost connection"); + connected = false; + } + // TODO: check other errors, is simply retrying okay? +} + +int PandaUsbHandle::control_write(uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned int timeout) { + int err; + const uint8_t bmRequestType = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE; + + if (!connected) { + return LIBUSB_ERROR_NO_DEVICE; + } + + std::lock_guard lk(hw_lock); + do { + err = libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, NULL, 0, timeout); + if (err < 0) handle_usb_issue(err, __func__); + } while (err < 0 && connected); + + return err; +} + +int PandaUsbHandle::control_read(uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) { + int err; + const uint8_t bmRequestType = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE; + + if (!connected) { + return LIBUSB_ERROR_NO_DEVICE; + } + + std::lock_guard lk(hw_lock); + do { + err = libusb_control_transfer(dev_handle, bmRequestType, bRequest, wValue, wIndex, data, wLength, timeout); + if (err < 0) handle_usb_issue(err, __func__); + } while (err < 0 && connected); + + return err; +} + +int PandaUsbHandle::bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { + int err; + int transferred = 0; + + if (!connected) { + return 0; + } + + std::lock_guard lk(hw_lock); + do { + // Try sending can messages. If the receive buffer on the panda is full it will NAK + // and libusb will try again. After 5ms, it will time out. We will drop the messages. + err = libusb_bulk_transfer(dev_handle, endpoint, data, length, &transferred, timeout); + + if (err == LIBUSB_ERROR_TIMEOUT) { + LOGW("Transmit buffer full"); + break; + } else if (err != 0 || length != transferred) { + handle_usb_issue(err, __func__); + } + } while (err != 0 && connected); + + return transferred; +} + +int PandaUsbHandle::bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { + int err; + int transferred = 0; + + if (!connected) { + return 0; + } + + std::lock_guard lk(hw_lock); + + do { + err = libusb_bulk_transfer(dev_handle, endpoint, data, length, &transferred, timeout); + + if (err == LIBUSB_ERROR_TIMEOUT) { + break; // timeout is okay to exit, recv still happened + } else if (err == LIBUSB_ERROR_OVERFLOW) { + comms_healthy = false; + LOGE_100("overflow got 0x%x", transferred); + } else if (err != 0) { + handle_usb_issue(err, __func__); + } + + } while (err != 0 && connected); + + return transferred; +} diff --git a/selfdrive/pandad/panda_comms.h b/selfdrive/pandad/panda_comms.h new file mode 100644 index 0000000000..9c452faf6d --- /dev/null +++ b/selfdrive/pandad/panda_comms.h @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include +#include +#include + +#ifndef __APPLE__ +#include +#endif + +#include + + +#define TIMEOUT 0 +#define SPI_BUF_SIZE 2048 + + +// comms base class +class PandaCommsHandle { +public: + PandaCommsHandle(std::string serial) {} + virtual ~PandaCommsHandle() {} + virtual void cleanup() = 0; + + std::string hw_serial; + std::atomic connected = true; + std::atomic comms_healthy = true; + static std::vector list(); + + // HW communication + virtual int control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout=TIMEOUT) = 0; + virtual int control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout=TIMEOUT) = 0; + virtual int bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT) = 0; + virtual int bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT) = 0; +}; + +class PandaUsbHandle : public PandaCommsHandle { +public: + PandaUsbHandle(std::string serial); + ~PandaUsbHandle(); + int control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout=TIMEOUT); + int control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout=TIMEOUT); + int bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT); + int bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT); + void cleanup(); + + static std::vector list(); + +private: + libusb_context *ctx = NULL; + libusb_device_handle *dev_handle = NULL; + std::recursive_mutex hw_lock; + void handle_usb_issue(int err, const char func[]); +}; + +#ifndef __APPLE__ +struct __attribute__((packed)) spi_header { + uint8_t sync; + uint8_t endpoint; + uint16_t tx_len; + uint16_t max_rx_len; +}; + +class PandaSpiHandle : public PandaCommsHandle { +public: + PandaSpiHandle(std::string serial); + ~PandaSpiHandle(); + int control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout=TIMEOUT); + int control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout=TIMEOUT); + int bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT); + int bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout=TIMEOUT); + void cleanup(); + + static std::vector list(); + +private: + int spi_fd = -1; + uint8_t tx_buf[SPI_BUF_SIZE]; + uint8_t rx_buf[SPI_BUF_SIZE]; + inline static std::recursive_mutex hw_lock; + + int wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout, unsigned int length); + int bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t rx_len, unsigned int timeout); + int spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len, unsigned int timeout); + int spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len, unsigned int timeout); + int lltransfer(spi_ioc_transfer &t); + + spi_header header; + uint32_t xfer_count = 0; +}; +#endif diff --git a/selfdrive/pandad/panda_safety.cc b/selfdrive/pandad/panda_safety.cc new file mode 100644 index 0000000000..b089503417 --- /dev/null +++ b/selfdrive/pandad/panda_safety.cc @@ -0,0 +1,81 @@ +#include "selfdrive/pandad/pandad.h" +#include "cereal/messaging/messaging.h" +#include "common/swaglog.h" + +void PandaSafety::configureSafetyMode(bool is_onroad) { + if (is_onroad && !safety_configured_) { + updateMultiplexingMode(); + + auto car_params = fetchCarParams(); + if (!car_params.empty()) { + LOGW("got %lu bytes CarParams", car_params.size()); + setSafetyMode(car_params); + safety_configured_ = true; + } + } else if (!is_onroad) { + initialized_ = false; + safety_configured_ = false; + log_once_ = false; + } +} + +void PandaSafety::updateMultiplexingMode() { + // Initialize to ELM327 without OBD multiplexing for initial fingerprinting + if (!initialized_) { + prev_obd_multiplexing_ = false; + for (int i = 0; i < pandas_.size(); ++i) { + pandas_[i]->set_safety_model(cereal::CarParams::SafetyModel::ELM327, 1U); + } + initialized_ = true; + } + + // Switch between multiplexing modes based on the OBD multiplexing request + bool obd_multiplexing_requested = params_.getBool("ObdMultiplexingEnabled"); + if (obd_multiplexing_requested != prev_obd_multiplexing_) { + for (int i = 0; i < pandas_.size(); ++i) { + const uint16_t safety_param = (i > 0 || !obd_multiplexing_requested) ? 1U : 0U; + pandas_[i]->set_safety_model(cereal::CarParams::SafetyModel::ELM327, safety_param); + } + prev_obd_multiplexing_ = obd_multiplexing_requested; + params_.putBool("ObdMultiplexingChanged", true); + } +} + +std::string PandaSafety::fetchCarParams() { + if (!params_.getBool("FirmwareQueryDone")) { + return {}; + } + + if (!log_once_) { + LOGW("Finished FW query, Waiting for params to set safety model"); + log_once_ = true; + } + + if (!params_.getBool("ControlsReady")) { + return {}; + } + return params_.get("CarParams"); +} + +void PandaSafety::setSafetyMode(const std::string ¶ms_string) { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(params_string.data(), params_string.size())); + cereal::CarParams::Reader car_params = cmsg.getRoot(); + + auto safety_configs = car_params.getSafetyConfigs(); + uint16_t alternative_experience = car_params.getAlternativeExperience(); + + for (int i = 0; i < pandas_.size(); ++i) { + // Default to SILENT safety model if not specified + cereal::CarParams::SafetyModel safety_model = cereal::CarParams::SafetyModel::SILENT; + uint16_t safety_param = 0U; + if (i < safety_configs.size()) { + safety_model = safety_configs[i].getSafetyModel(); + safety_param = safety_configs[i].getSafetyParam(); + } + + LOGW("Panda %d: setting safety model: %d, param: %d, alternative experience: %d", i, (int)safety_model, safety_param, alternative_experience); + pandas_[i]->set_alternative_experience(alternative_experience); + pandas_[i]->set_safety_model(safety_model, safety_param); + } +} diff --git a/selfdrive/pandad/pandad.cc b/selfdrive/pandad/pandad.cc new file mode 100644 index 0000000000..2931eb4acd --- /dev/null +++ b/selfdrive/pandad/pandad.cc @@ -0,0 +1,524 @@ +#include "selfdrive/pandad/pandad.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cereal/gen/cpp/car.capnp.h" +#include "cereal/messaging/messaging.h" +#include "common/ratekeeper.h" +#include "common/swaglog.h" +#include "common/timing.h" +#include "common/util.h" +#include "system/hardware/hw.h" + +// -- Multi-panda conventions -- +// Ordering: +// - The internal panda will always be the first panda +// - Consecutive pandas will be sorted based on panda type, and then serial number +// Connecting: +// - If a panda connection is dropped, pandad will reconnect to all pandas +// - If a panda is added, we will only reconnect when we are offroad +// CAN buses: +// - Each panda will have its block of 4 buses. E.g.: the second panda will use +// bus numbers 4, 5, 6 and 7 +// - The internal panda will always be used for accessing the OBD2 port, +// and thus firmware queries +// Safety: +// - SafetyConfig is a list, which is mapped to the connected pandas +// - If there are more pandas connected than there are SafetyConfigs, +// the excess pandas will remain in "silent" or "noOutput" mode +// Ignition: +// - If any of the ignition sources in any panda is high, ignition is high + +#define MAX_IR_PANDA_VAL 50 +#define CUTOFF_IL 400 +#define SATURATE_IL 1000 + +ExitHandler do_exit; + +bool check_all_connected(const std::vector &pandas) { + for (const auto& panda : pandas) { + if (!panda->connected()) { + do_exit = true; + return false; + } + } + return true; +} + +Panda *connect(std::string serial="", uint32_t index=0) { + std::unique_ptr panda; + try { + panda = std::make_unique(serial, (index * PANDA_BUS_OFFSET)); + } catch (std::exception &e) { + return nullptr; + } + + // common panda config + if (getenv("BOARDD_LOOPBACK")) { + panda->set_loopback(true); + } + //panda->enable_deepsleep(); + + for (int i = 0; i < PANDA_CAN_CNT; i++) { + panda->set_can_fd_auto(i, true); + } + + if (!panda->up_to_date() && !getenv("BOARDD_SKIP_FW_CHECK")) { + throw std::runtime_error("Panda firmware out of date. Run pandad.py to update."); + } + + return panda.release(); +} + +void can_send_thread(std::vector pandas, bool fake_send) { + util::set_thread_name("pandad_can_send"); + + AlignedBuffer aligned_buf; + std::unique_ptr context(Context::create()); + std::unique_ptr subscriber(SubSocket::create(context.get(), "sendcan")); + assert(subscriber != NULL); + subscriber->setTimeout(100); + + // run as fast as messages come in + while (!do_exit && check_all_connected(pandas)) { + std::unique_ptr msg(subscriber->receive()); + if (!msg) { + continue; + } + + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(msg.get())); + cereal::Event::Reader event = cmsg.getRoot(); + + // Don't send if older than 1 second + if ((nanos_since_boot() - event.getLogMonoTime() < 1e9) && !fake_send) { + for (const auto& panda : pandas) { + LOGT("sending sendcan to panda: %s", (panda->hw_serial()).c_str()); + panda->can_send(event.getSendcan()); + LOGT("sendcan sent to panda: %s", (panda->hw_serial()).c_str()); + } + } else { + LOGE("sendcan too old to send: %" PRIu64 ", %" PRIu64, nanos_since_boot(), event.getLogMonoTime()); + } + } +} + +void can_recv(std::vector &pandas, PubMaster *pm) { + static std::vector raw_can_data; + { + bool comms_healthy = true; + raw_can_data.clear(); + for (const auto& panda : pandas) { + comms_healthy &= panda->can_receive(raw_can_data); + } + + MessageBuilder msg; + auto evt = msg.initEvent(); + evt.setValid(comms_healthy); + auto canData = evt.initCan(raw_can_data.size()); + for (size_t i = 0; i < raw_can_data.size(); ++i) { + canData[i].setAddress(raw_can_data[i].address); + canData[i].setDat(kj::arrayPtr((uint8_t*)raw_can_data[i].dat.data(), raw_can_data[i].dat.size())); + canData[i].setSrc(raw_can_data[i].src); + } + pm->send("can", msg); + } +} + +void fill_panda_state(cereal::PandaState::Builder &ps, cereal::PandaState::PandaType hw_type, const health_t &health) { + ps.setVoltage(health.voltage_pkt); + ps.setCurrent(health.current_pkt); + ps.setUptime(health.uptime_pkt); + ps.setSafetyTxBlocked(health.safety_tx_blocked_pkt); + ps.setSafetyRxInvalid(health.safety_rx_invalid_pkt); + ps.setIgnitionLine(health.ignition_line_pkt); + ps.setIgnitionCan(health.ignition_can_pkt); + ps.setControlsAllowed(health.controls_allowed_pkt); + ps.setTxBufferOverflow(health.tx_buffer_overflow_pkt); + ps.setRxBufferOverflow(health.rx_buffer_overflow_pkt); + ps.setPandaType(hw_type); + ps.setSafetyModel(cereal::CarParams::SafetyModel(health.safety_mode_pkt)); + ps.setSafetyParam(health.safety_param_pkt); + ps.setFaultStatus(cereal::PandaState::FaultStatus(health.fault_status_pkt)); + ps.setPowerSaveEnabled((bool)(health.power_save_enabled_pkt)); + ps.setHeartbeatLost((bool)(health.heartbeat_lost_pkt)); + ps.setAlternativeExperience(health.alternative_experience_pkt); + ps.setHarnessStatus(cereal::PandaState::HarnessStatus(health.car_harness_status_pkt)); + ps.setInterruptLoad(health.interrupt_load_pkt); + ps.setFanPower(health.fan_power); + ps.setSafetyRxChecksInvalid((bool)(health.safety_rx_checks_invalid_pkt)); + ps.setSpiErrorCount(health.spi_error_count_pkt); + ps.setSbu1Voltage(health.sbu1_voltage_mV / 1000.0f); + ps.setSbu2Voltage(health.sbu2_voltage_mV / 1000.0f); +} + +void fill_panda_can_state(cereal::PandaState::PandaCanState::Builder &cs, const can_health_t &can_health) { + cs.setBusOff((bool)can_health.bus_off); + cs.setBusOffCnt(can_health.bus_off_cnt); + cs.setErrorWarning((bool)can_health.error_warning); + cs.setErrorPassive((bool)can_health.error_passive); + cs.setLastError(cereal::PandaState::PandaCanState::LecErrorCode(can_health.last_error)); + cs.setLastStoredError(cereal::PandaState::PandaCanState::LecErrorCode(can_health.last_stored_error)); + cs.setLastDataError(cereal::PandaState::PandaCanState::LecErrorCode(can_health.last_data_error)); + cs.setLastDataStoredError(cereal::PandaState::PandaCanState::LecErrorCode(can_health.last_data_stored_error)); + cs.setReceiveErrorCnt(can_health.receive_error_cnt); + cs.setTransmitErrorCnt(can_health.transmit_error_cnt); + cs.setTotalErrorCnt(can_health.total_error_cnt); + cs.setTotalTxLostCnt(can_health.total_tx_lost_cnt); + cs.setTotalRxLostCnt(can_health.total_rx_lost_cnt); + cs.setTotalTxCnt(can_health.total_tx_cnt); + cs.setTotalRxCnt(can_health.total_rx_cnt); + cs.setTotalFwdCnt(can_health.total_fwd_cnt); + cs.setCanSpeed(can_health.can_speed); + cs.setCanDataSpeed(can_health.can_data_speed); + cs.setCanfdEnabled(can_health.canfd_enabled); + cs.setBrsEnabled(can_health.brs_enabled); + cs.setCanfdNonIso(can_health.canfd_non_iso); + cs.setIrq0CallRate(can_health.irq0_call_rate); + cs.setIrq1CallRate(can_health.irq1_call_rate); + cs.setIrq2CallRate(can_health.irq2_call_rate); + cs.setCanCoreResetCnt(can_health.can_core_reset_cnt); +} + +std::optional send_panda_states(PubMaster *pm, const std::vector &pandas, bool is_onroad, bool spoofing_started) { + bool ignition_local = false; + const uint32_t pandas_cnt = pandas.size(); + + // build msg + MessageBuilder msg; + auto evt = msg.initEvent(); + auto pss = evt.initPandaStates(pandas_cnt); + + std::vector pandaStates; + pandaStates.reserve(pandas_cnt); + + std::vector> pandaCanStates; + pandaCanStates.reserve(pandas_cnt); + + const bool red_panda_comma_three = (pandas.size() == 2) && + (pandas[0]->hw_type == cereal::PandaState::PandaType::DOS) && + (pandas[1]->hw_type == cereal::PandaState::PandaType::RED_PANDA); + + for (const auto& panda : pandas){ + auto health_opt = panda->get_state(); + if (!health_opt) { + return std::nullopt; + } + + health_t health = *health_opt; + + std::array can_health{}; + for (uint32_t i = 0; i < PANDA_CAN_CNT; i++) { + auto can_health_opt = panda->get_can_state(i); + if (!can_health_opt) { + return std::nullopt; + } + can_health[i] = *can_health_opt; + } + pandaCanStates.push_back(can_health); + + if (spoofing_started) { + health.ignition_line_pkt = 1; + } + + // on comma three setups with a red panda, the dos can + // get false positive ignitions due to the harness box + // without a harness connector, so ignore it + if (red_panda_comma_three && (panda->hw_type == cereal::PandaState::PandaType::DOS)) { + health.ignition_line_pkt = 0; + } + + ignition_local |= ((health.ignition_line_pkt != 0) || (health.ignition_can_pkt != 0)); + + pandaStates.push_back(health); + } + + for (uint32_t i = 0; i < pandas_cnt; i++) { + auto panda = pandas[i]; + const auto &health = pandaStates[i]; + + // Make sure CAN buses are live: safety_setter_thread does not work if Panda CAN are silent and there is only one other CAN node + if (health.safety_mode_pkt == (uint8_t)(cereal::CarParams::SafetyModel::SILENT)) { + panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT); + } + + bool power_save_desired = !ignition_local; + if (health.power_save_enabled_pkt != power_save_desired) { + panda->set_power_saving(power_save_desired); + } + + // set safety mode to NO_OUTPUT when car is off or we're not onroad. ELM327 is an alternative if we want to leverage athenad/connect + bool should_close_relay = !ignition_local || !is_onroad; + if (should_close_relay && (health.safety_mode_pkt != (uint8_t)(cereal::CarParams::SafetyModel::NO_OUTPUT))) { + panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT); + } + + if (!panda->comms_healthy()) { + evt.setValid(false); + } + + auto ps = pss[i]; + fill_panda_state(ps, panda->hw_type, health); + + auto cs = std::array{ps.initCanState0(), ps.initCanState1(), ps.initCanState2()}; + for (uint32_t j = 0; j < PANDA_CAN_CNT; j++) { + fill_panda_can_state(cs[j], pandaCanStates[i][j]); + } + + // Convert faults bitset to capnp list + std::bitset fault_bits(health.faults_pkt); + auto faults = ps.initFaults(fault_bits.count()); + + size_t j = 0; + for (size_t f = size_t(cereal::PandaState::FaultType::RELAY_MALFUNCTION); + f <= size_t(cereal::PandaState::FaultType::HEARTBEAT_LOOP_WATCHDOG); f++) { + if (fault_bits.test(f)) { + faults.set(j, cereal::PandaState::FaultType(f)); + j++; + } + } + } + + pm->send("pandaStates", msg); + return ignition_local; +} + +void send_peripheral_state(Panda *panda, PubMaster *pm) { + // build msg + MessageBuilder msg; + auto evt = msg.initEvent(); + evt.setValid(panda->comms_healthy()); + + auto ps = evt.initPeripheralState(); + ps.setPandaType(panda->hw_type); + + double read_time = millis_since_boot(); + ps.setVoltage(Hardware::get_voltage()); + ps.setCurrent(Hardware::get_current()); + read_time = millis_since_boot() - read_time; + if (read_time > 50) { + LOGW("reading hwmon took %lfms", read_time); + } + + // fall back to panda's voltage and current measurement + if (ps.getVoltage() == 0 && ps.getCurrent() == 0) { + auto health_opt = panda->get_state(); + if (health_opt) { + health_t health = *health_opt; + ps.setVoltage(health.voltage_pkt); + ps.setCurrent(health.current_pkt); + } + } + + uint16_t fan_speed_rpm = panda->get_fan_speed(); + ps.setFanSpeedRpm(fan_speed_rpm); + + pm->send("peripheralState", msg); +} + +void process_panda_state(std::vector &pandas, PubMaster *pm, bool engaged, bool is_onroad, bool spoofing_started) { + std::vector connected_serials; + for (Panda *p : pandas) { + connected_serials.push_back(p->hw_serial()); + } + + { + auto ignition_opt = send_panda_states(pm, pandas, is_onroad, spoofing_started); + if (!ignition_opt) { + LOGE("Failed to get ignition_opt"); + return; + } + + // check if we should have pandad reconnect + if (!ignition_opt.value()) { + bool comms_healthy = true; + for (const auto &panda : pandas) { + comms_healthy &= panda->comms_healthy(); + } + + if (!comms_healthy) { + LOGE("Reconnecting, communication to pandas not healthy"); + do_exit = true; + + } else { + // check for new pandas + for (std::string &s : Panda::list(true)) { + if (!std::count(connected_serials.begin(), connected_serials.end(), s)) { + LOGW("Reconnecting to new panda: %s", s.c_str()); + do_exit = true; + break; + } + } + } + } + + for (const auto &panda : pandas) { + panda->send_heartbeat(engaged); + } + } +} + +void process_peripheral_state(Panda *panda, PubMaster *pm, bool no_fan_control) { + static SubMaster sm({"deviceState", "driverCameraState"}); + + static uint64_t last_driver_camera_t = 0; + static uint16_t prev_fan_speed = 999; + static int ir_pwr = 0; + static int prev_ir_pwr = 999; + + static FirstOrderFilter integ_lines_filter(0, 30.0, 0.05); + + { + sm.update(0); + if (sm.updated("deviceState") && !no_fan_control) { + // Fan speed + uint16_t fan_speed = sm["deviceState"].getDeviceState().getFanSpeedPercentDesired(); + if (fan_speed != prev_fan_speed || sm.frame % 100 == 0) { + panda->set_fan_speed(fan_speed); + prev_fan_speed = fan_speed; + } + } + + if (sm.updated("driverCameraState")) { + auto event = sm["driverCameraState"]; + int cur_integ_lines = event.getDriverCameraState().getIntegLines(); + + cur_integ_lines = integ_lines_filter.update(cur_integ_lines); + last_driver_camera_t = event.getLogMonoTime(); + + if (cur_integ_lines <= CUTOFF_IL) { + ir_pwr = 0; + } else if (cur_integ_lines > SATURATE_IL) { + ir_pwr = 100; + } else { + ir_pwr = 100 * (cur_integ_lines - CUTOFF_IL) / (SATURATE_IL - CUTOFF_IL); + } + } + + // Disable IR on input timeout + if (nanos_since_boot() - last_driver_camera_t > 1e9) { + ir_pwr = 0; + } + + if (ir_pwr != prev_ir_pwr || sm.frame % 100 == 0) { + int16_t ir_panda = util::map_val(ir_pwr, 0, 100, 0, MAX_IR_PANDA_VAL); + panda->set_ir_pwr(ir_panda); + Hardware::set_ir_power(ir_pwr); + prev_ir_pwr = ir_pwr; + } + } +} + +void pandad_run(std::vector &pandas) { + const bool no_fan_control = getenv("NO_FAN_CONTROL") != nullptr; + const bool spoofing_started = getenv("STARTED") != nullptr; + const bool fake_send = getenv("FAKESEND") != nullptr; + + // Start the CAN send thread + std::thread send_thread(can_send_thread, pandas, fake_send); + + Params params; + RateKeeper rk("pandad", 100); + SubMaster sm({"selfdriveState"}); + PubMaster pm({"can", "pandaStates", "peripheralState"}); + PandaSafety panda_safety(pandas); + Panda *peripheral_panda = pandas[0]; + bool engaged = false; + bool is_onroad = false; + + // Main loop: receive CAN data and process states + while (!do_exit && check_all_connected(pandas)) { + can_recv(pandas, &pm); + + // Process peripheral state at 20 Hz + if (rk.frame() % 5 == 0) { + process_peripheral_state(peripheral_panda, &pm, no_fan_control); + } + + // Process panda state at 10 Hz + if (rk.frame() % 10 == 0) { + sm.update(0); + engaged = sm.allAliveAndValid({"selfdriveState"}) && sm["selfdriveState"].getSelfdriveState().getEnabled(); + is_onroad = params.getBool("IsOnroad"); + process_panda_state(pandas, &pm, engaged, is_onroad, spoofing_started); + panda_safety.configureSafetyMode(is_onroad); + } + + // Send out peripheralState at 2Hz + if (rk.frame() % 50 == 0) { + send_peripheral_state(peripheral_panda, &pm); + } + + // Forward logs from pandas to cloudlog if available + for (auto *panda : pandas) { + std::string log = panda->serial_read(); + if (!log.empty()) { + if (log.find("Register 0x") != std::string::npos) { + // Log register divergent faults as errors + LOGE("%s", log.c_str()); + } else { + LOGD("%s", log.c_str()); + } + } + } + + rk.keepTime(); + } + + // Close relay on exit to prevent a fault + if (is_onroad && !engaged) { + for (auto &p : pandas) { + if (p->connected()) { + p->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT); + } + } + } + + send_thread.join(); +} + +void pandad_main_thread(std::vector serials) { + if (serials.size() == 0) { + serials = Panda::list(); + + if (serials.size() == 0) { + LOGW("no pandas found, exiting"); + return; + } + } + + std::string serials_str; + for (int i = 0; i < serials.size(); i++) { + serials_str += serials[i]; + if (i < serials.size() - 1) serials_str += ", "; + } + LOGW("connecting to pandas: %s", serials_str.c_str()); + + // connect to all provided serials + std::vector pandas; + for (int i = 0; i < serials.size() && !do_exit; /**/) { + Panda *p = connect(serials[i], i); + if (!p) { + util::sleep_for(100); + continue; + } + + pandas.push_back(p); + ++i; + } + + if (!do_exit) { + LOGW("connected to all pandas"); + pandad_run(pandas); + } + + for (Panda *panda : pandas) { + delete panda; + } +} diff --git a/selfdrive/pandad/pandad.h b/selfdrive/pandad/pandad.h new file mode 100644 index 0000000000..637807e074 --- /dev/null +++ b/selfdrive/pandad/pandad.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include "common/params.h" +#include "selfdrive/pandad/panda.h" + +void pandad_main_thread(std::vector serials); + +class PandaSafety { +public: + PandaSafety(const std::vector &pandas) : pandas_(pandas) {} + void configureSafetyMode(bool is_onroad); + +private: + void updateMultiplexingMode(); + std::string fetchCarParams(); + void setSafetyMode(const std::string ¶ms_string); + + bool initialized_ = false; + bool log_once_ = false; + bool safety_configured_ = false; + bool prev_obd_multiplexing_ = false; + std::vector pandas_; + Params params_; +}; diff --git a/selfdrive/pandad/pandad.py b/selfdrive/pandad/pandad.py new file mode 100755 index 0000000000..d75af283f2 --- /dev/null +++ b/selfdrive/pandad/pandad.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# simple pandad wrapper that updates the panda first +import os +import usb1 +import time +import signal +import subprocess + +from panda import Panda, PandaDFU, PandaProtocolMismatch, FW_PATH +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.system.hardware import HARDWARE +from openpilot.common.swaglog import cloudlog + + +def get_expected_signature(panda: Panda) -> bytes: + try: + fn = os.path.join(FW_PATH, panda.get_mcu_type().config.app_fn) + return Panda.get_signature_from_firmware(fn) + except Exception: + cloudlog.exception("Error computing expected signature") + return b"" + +def flash_panda(panda_serial: str) -> Panda: + try: + panda = Panda(panda_serial) + except PandaProtocolMismatch: + cloudlog.warning("detected protocol mismatch, reflashing panda") + HARDWARE.recover_internal_panda() + raise + + fw_signature = get_expected_signature(panda) + internal_panda = panda.is_internal() + + panda_version = "bootstub" if panda.bootstub else panda.get_version() + panda_signature = b"" if panda.bootstub else panda.get_signature() + cloudlog.warning(f"Panda {panda_serial} connected, version: {panda_version}, signature {panda_signature.hex()[:16]}, expected {fw_signature.hex()[:16]}") + + if panda.bootstub or panda_signature != fw_signature: + cloudlog.info("Panda firmware out of date, update required") + panda.flash() + cloudlog.info("Done flashing") + + if panda.bootstub: + bootstub_version = panda.get_version() + cloudlog.info(f"Flashed firmware not booting, flashing development bootloader. {bootstub_version=}, {internal_panda=}") + if internal_panda: + HARDWARE.recover_internal_panda() + panda.recover(reset=(not internal_panda)) + cloudlog.info("Done flashing bootstub") + + if panda.bootstub: + cloudlog.info("Panda still not booting, exiting") + raise AssertionError + + panda_signature = panda.get_signature() + if panda_signature != fw_signature: + cloudlog.info("Version mismatch after flashing, exiting") + raise AssertionError + + return panda + + +def main() -> None: + # signal pandad to close the relay and exit + def signal_handler(signum, frame): + cloudlog.info(f"Caught signal {signum}, exiting") + nonlocal do_exit + do_exit = True + if process is not None: + process.send_signal(signal.SIGINT) + + process = None + do_exit = False + signal.signal(signal.SIGINT, signal_handler) + + count = 0 + first_run = True + params = Params() + no_internal_panda_count = 0 + + while not do_exit: + try: + count += 1 + cloudlog.event("pandad.flash_and_connect", count=count) + params.remove("PandaSignatures") + + # Handle missing internal panda + if no_internal_panda_count > 0: + if no_internal_panda_count == 3: + cloudlog.info("No pandas found, putting internal panda into DFU") + HARDWARE.recover_internal_panda() + else: + cloudlog.info("No pandas found, resetting internal panda") + HARDWARE.reset_internal_panda() + time.sleep(3) # wait to come back up + + # Flash all Pandas in DFU mode + dfu_serials = PandaDFU.list() + if len(dfu_serials) > 0: + for serial in dfu_serials: + cloudlog.info(f"Panda in DFU mode found, flashing recovery {serial}") + PandaDFU(serial).recover() + time.sleep(1) + + panda_serials = Panda.list() + if len(panda_serials) == 0: + no_internal_panda_count += 1 + continue + + cloudlog.info(f"{len(panda_serials)} panda(s) found, connecting - {panda_serials}") + + # Flash pandas + pandas: list[Panda] = [] + for serial in panda_serials: + pandas.append(flash_panda(serial)) + + # Ensure internal panda is present if expected + internal_pandas = [panda for panda in pandas if panda.is_internal()] + if HARDWARE.has_internal_panda() and len(internal_pandas) == 0: + cloudlog.error("Internal panda is missing, trying again") + no_internal_panda_count += 1 + continue + no_internal_panda_count = 0 + + # sort pandas to have deterministic order + # * the internal one is always first + # * then sort by hardware type + # * as a last resort, sort by serial number + pandas.sort(key=lambda x: (not x.is_internal(), x.get_type(), x.get_usb_serial())) + panda_serials = [p.get_usb_serial() for p in pandas] + + # log panda fw versions + params.put("PandaSignatures", b','.join(p.get_signature() for p in pandas)) + + for panda in pandas: + # check health for lost heartbeat + health = panda.health() + if health["heartbeat_lost"]: + params.put_bool("PandaHeartbeatLost", True) + cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial()) + if health["som_reset_triggered"]: + params.put_bool("PandaSomResetTriggered", True) + cloudlog.event("panda.som_reset_triggered", health=health, serial=panda.get_usb_serial()) + + if first_run: + # reset panda to ensure we're in a good state + cloudlog.info(f"Resetting panda {panda.get_usb_serial()}") + panda.reset(reconnect=True) + + for p in pandas: + p.close() + # TODO: wrap all panda exceptions in a base panda exception + except (usb1.USBErrorNoDevice, usb1.USBErrorPipe): + # a panda was disconnected while setting everything up. let's try again + cloudlog.exception("Panda USB exception while setting up") + continue + except PandaProtocolMismatch: + cloudlog.exception("pandad.protocol_mismatch") + continue + except Exception: + cloudlog.exception("pandad.uncaught_exception") + continue + + first_run = False + + # run pandad with all connected serials as arguments + os.environ['MANAGER_DAEMON'] = 'pandad' + process = subprocess.Popen(["./pandad", *panda_serials], cwd=os.path.join(BASEDIR, "selfdrive/pandad")) + process.wait() + + +if __name__ == "__main__": + main() diff --git a/selfdrive/pandad/pandad_api_impl.pyx b/selfdrive/pandad/pandad_api_impl.pyx new file mode 100644 index 0000000000..aaecb8a594 --- /dev/null +++ b/selfdrive/pandad/pandad_api_impl.pyx @@ -0,0 +1,56 @@ +# distutils: language = c++ +# cython: language_level=3 +from cython.operator cimport dereference as deref, preincrement as preinc +from libcpp.vector cimport vector +from libcpp.string cimport string +from libcpp cimport bool +from libc.stdint cimport uint8_t, uint32_t, uint64_t + +cdef extern from "selfdrive/pandad/can_types.h": + cdef struct CanFrame: + long src + uint32_t address + vector[uint8_t] dat + + cdef struct CanData: + uint64_t nanos + vector[CanFrame] frames + +cdef extern from "can_list_to_can_capnp.cc": + void can_list_to_can_capnp_cpp(const vector[CanFrame] &can_list, string &out, bool sendcan, bool valid) nogil + void can_capnp_to_can_list_cpp(const vector[string] &strings, vector[CanData] &can_data, bool sendcan) + +def can_list_to_can_capnp(can_msgs, msgtype='can', valid=True): + cdef CanFrame *f + cdef vector[CanFrame] can_list + cdef uint32_t cpp_can_msgs_len = len(can_msgs) + + with nogil: + can_list.reserve(cpp_can_msgs_len) + + for can_msg in can_msgs: + f = &(can_list.emplace_back()) + f.address = can_msg[0] + f.dat = can_msg[1] + f.src = can_msg[2] + + cdef string out + cdef bool is_sendcan = (msgtype == 'sendcan') + cdef bool is_valid = valid + with nogil: + can_list_to_can_capnp_cpp(can_list, out, is_sendcan, is_valid) + return out + +def can_capnp_to_list(strings, msgtype='can'): + cdef vector[CanData] data + can_capnp_to_can_list_cpp(strings, data, msgtype == 'sendcan') + + result = [] + cdef CanData *d + cdef vector[CanData].iterator it = data.begin() + while it != data.end(): + d = &deref(it) + frames = [(f.address, (&f.dat[0])[:f.dat.size()], f.src) for f in d.frames] + result.append((d.nanos, frames)) + preinc(it) + return result diff --git a/selfdrive/pandad/spi.cc b/selfdrive/pandad/spi.cc new file mode 100644 index 0000000000..b6ee57801a --- /dev/null +++ b/selfdrive/pandad/spi.cc @@ -0,0 +1,410 @@ +#ifndef __APPLE__ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "common/util.h" +#include "common/timing.h" +#include "common/swaglog.h" +#include "panda/board/comms_definitions.h" +#include "selfdrive/pandad/panda_comms.h" + + +#define SPI_SYNC 0x5AU +#define SPI_HACK 0x79U +#define SPI_DACK 0x85U +#define SPI_NACK 0x1FU +#define SPI_CHECKSUM_START 0xABU + + +enum SpiError { + NACK = -2, + ACK_TIMEOUT = -3, +}; + +const unsigned int SPI_ACK_TIMEOUT = 500; // milliseconds +const std::string SPI_DEVICE = "/dev/spidev0.0"; + +class LockEx { +public: + LockEx(int fd, std::recursive_mutex &m) : fd(fd), m(m) { + m.lock(); + flock(fd, LOCK_EX); + } + + ~LockEx() { + flock(fd, LOCK_UN); + m.unlock(); + } + +private: + int fd; + std::recursive_mutex &m; +}; + +#define SPILOG(fn, fmt, ...) do { \ + fn(fmt, ## __VA_ARGS__); \ + fn(" %d / 0x%x / %d / %d / tx: %s", \ + xfer_count, header.endpoint, header.tx_len, header.max_rx_len, \ + util::hexdump(tx_buf, std::min((int)header.tx_len, 8)).c_str()); \ + } while (0) + +PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { + int ret; + const int uid_len = 12; + uint8_t uid[uid_len] = {0}; + + uint32_t spi_mode = SPI_MODE_0; + uint8_t spi_bits_per_word = 8; + + // 50MHz is the max of the 845. note that some older + // revs of the comma three may not support this speed + uint32_t spi_speed = 50000000; + try { + if (!util::file_exists(SPI_DEVICE)) { + throw std::runtime_error("Error connecting to panda: SPI device not found"); + } + + spi_fd = open(SPI_DEVICE.c_str(), O_RDWR); + if (spi_fd < 0) { + LOGE("failed opening SPI device %d", spi_fd); + throw std::runtime_error("Error connecting to panda: failed to open SPI device"); + } + + // SPI settings + util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode, "failed setting SPI mode"); + util::safe_ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed, "failed setting SPI speed"); + util::safe_ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word, "failed setting SPI bits per word"); + + // get hw UID/serial + ret = control_read(0xc3, 0, 0, uid, uid_len, 100); + if (ret == uid_len) { + std::stringstream stream; + for (int i = 0; i < uid_len; i++) { + stream << std::hex << std::setw(2) << std::setfill('0') << int(uid[i]); + } + hw_serial = stream.str(); + } else { + LOGD("failed to get serial %d", ret); + throw std::runtime_error("Error connecting to panda: failed to get serial"); + } + + if (!serial.empty() && (serial != hw_serial)) { + throw std::runtime_error("Error connecting to panda: serial mismatch"); + } + + } catch (...) { + cleanup(); + throw; + } + return; +} + +PandaSpiHandle::~PandaSpiHandle() { + std::lock_guard lk(hw_lock); + cleanup(); +} + +void PandaSpiHandle::cleanup() { + if (spi_fd != -1) { + close(spi_fd); + spi_fd = -1; + } +} + + + +int PandaSpiHandle::control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout) { + ControlPacket_t packet = { + .request = request, + .param1 = param1, + .param2 = param2, + .length = 0 + }; + return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), NULL, 0, timeout); +} + +int PandaSpiHandle::control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout) { + ControlPacket_t packet = { + .request = request, + .param1 = param1, + .param2 = param2, + .length = length + }; + return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), data, length, timeout); +} + +int PandaSpiHandle::bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { + return bulk_transfer(endpoint, data, length, NULL, 0, timeout); +} +int PandaSpiHandle::bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { + return bulk_transfer(endpoint, NULL, 0, data, length, timeout); +} + +int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t rx_len, unsigned int timeout) { + const int xfer_size = SPI_BUF_SIZE - 0x40; + + int ret = 0; + uint16_t length = (tx_data != NULL) ? tx_len : rx_len; + for (int i = 0; i < (int)std::ceil((float)length / xfer_size); i++) { + int d; + if (tx_data != NULL) { + int len = std::min(xfer_size, tx_len - (xfer_size * i)); + d = spi_transfer_retry(endpoint, tx_data + (xfer_size * i), len, NULL, 0, timeout); + } else { + uint16_t to_read = std::min(xfer_size, rx_len - ret); + d = spi_transfer_retry(endpoint, NULL, 0, rx_data + (xfer_size * i), to_read, timeout); + } + + if (d < 0) { + SPILOG(LOGE, "SPI: bulk transfer failed with %d", d); + comms_healthy = false; + return d; + } + + ret += d; + if ((rx_data != NULL) && d < xfer_size) { + break; + } + } + + return ret; +} + +std::vector PandaSpiHandle::list() { + try { + PandaSpiHandle sh(""); + return {sh.hw_serial}; + } catch (std::exception &e) { + // no panda on SPI + } + return {}; +} + +void add_checksum(uint8_t *data, int data_len) { + data[data_len] = SPI_CHECKSUM_START; + for (int i=0; i < data_len; i++) { + data[data_len] ^= data[i]; + } +} + +bool check_checksum(uint8_t *data, int data_len) { + uint8_t checksum = SPI_CHECKSUM_START; + for (uint16_t i = 0U; i < data_len; i++) { + checksum ^= data[i]; + } + return checksum == 0U; +} + + +int PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len, unsigned int timeout) { + int ret; + int nack_count = 0; + int timeout_count = 0; + bool timed_out = false; + double start_time = millis_since_boot(); + + do { + ret = spi_transfer(endpoint, tx_data, tx_len, rx_data, max_rx_len, timeout); + + if (ret < 0) { + timed_out = (timeout != 0) && (timeout_count > 5); + timeout_count += ret == SpiError::ACK_TIMEOUT; + + // give other threads a chance to run + std::this_thread::yield(); + + if (ret == SpiError::NACK) { + // prevent busy waiting while the panda is NACK'ing + // due to full TX buffers + nack_count += 1; + if (nack_count > 3) { + SPILOG(LOGD, "NACK sleep %d", nack_count); + usleep(std::clamp(nack_count*10, 200, 2000)); + } + } + } + } while (ret < 0 && connected && !timed_out); + + if (ret < 0) { + SPILOG(LOGE, "transfer failed, after %d tries, %.2fms", timeout_count, millis_since_boot() - start_time); + } + + return ret; +} + +int PandaSpiHandle::wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout, unsigned int length) { + double start_millis = millis_since_boot(); + if (timeout == 0) { + timeout = SPI_ACK_TIMEOUT; + } + timeout = std::clamp(timeout, 20U, SPI_ACK_TIMEOUT); + + spi_ioc_transfer transfer = { + .tx_buf = (uint64_t)tx_buf, + .rx_buf = (uint64_t)rx_buf, + .len = length, + }; + memset(tx_buf, tx, length); + + while (true) { + int ret = lltransfer(transfer); + if (ret < 0) { + SPILOG(LOGE, "SPI: failed to send ACK request"); + return ret; + } + + if (rx_buf[0] == ack) { + break; + } else if (rx_buf[0] == SPI_NACK) { + SPILOG(LOGD, "SPI: got NACK, waiting for 0x%x", ack); + return SpiError::NACK; + } + + // handle timeout + if (millis_since_boot() - start_millis > timeout) { + SPILOG(LOGW, "SPI: timed out waiting for ACK, waiting for 0x%x", ack); + return SpiError::ACK_TIMEOUT; + } + } + + return 0; +} + +int PandaSpiHandle::lltransfer(spi_ioc_transfer &t) { + static const double err_prob = std::stod(util::getenv("SPI_ERR_PROB", "-1")); + + if (err_prob > 0) { + if ((static_cast(rand()) / RAND_MAX) < err_prob) { + printf("transfer len error\n"); + t.len = rand() % SPI_BUF_SIZE; + } + if ((static_cast(rand()) / RAND_MAX) < err_prob && t.tx_buf != (uint64_t)NULL) { + printf("corrupting TX\n"); + for (int i = 0; i < t.len; i++) { + if ((static_cast(rand()) / RAND_MAX) > 0.9) { + ((uint8_t*)t.tx_buf)[i] = (uint8_t)(rand() % 256); + } + } + } + } + + int ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &t); + + if (err_prob > 0) { + if ((static_cast(rand()) / RAND_MAX) < err_prob && t.rx_buf != (uint64_t)NULL) { + printf("corrupting RX\n"); + for (int i = 0; i < t.len; i++) { + if ((static_cast(rand()) / RAND_MAX) > 0.9) { + ((uint8_t*)t.rx_buf)[i] = (uint8_t)(rand() % 256); + } + } + } + } + + return ret; +} + +int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len, unsigned int timeout) { + int ret; + uint16_t rx_data_len; + LockEx lock(spi_fd, hw_lock); + + // needs to be less, since we need to have space for the checksum + assert(tx_len < SPI_BUF_SIZE); + assert(max_rx_len < SPI_BUF_SIZE); + + xfer_count++; + header = { + .sync = SPI_SYNC, + .endpoint = endpoint, + .tx_len = tx_len, + .max_rx_len = max_rx_len + }; + + spi_ioc_transfer transfer = { + .tx_buf = (uint64_t)tx_buf, + .rx_buf = (uint64_t)rx_buf + }; + + // Send header + memcpy(tx_buf, &header, sizeof(header)); + add_checksum(tx_buf, sizeof(header)); + transfer.len = sizeof(header) + 1; + ret = lltransfer(transfer); + if (ret < 0) { + SPILOG(LOGE, "SPI: failed to send header"); + goto fail; + } + + // Wait for (N)ACK + ret = wait_for_ack(SPI_HACK, 0x11, timeout, 1); + if (ret < 0) { + goto fail; + } + + // Send data + if (tx_data != NULL) { + memcpy(tx_buf, tx_data, tx_len); + } + add_checksum(tx_buf, tx_len); + transfer.len = tx_len + 1; + ret = lltransfer(transfer); + if (ret < 0) { + SPILOG(LOGE, "SPI: failed to send data"); + goto fail; + } + + // Wait for (N)ACK + ret = wait_for_ack(SPI_DACK, 0x13, timeout, 3); + if (ret < 0) { + goto fail; + } + + // Read data + rx_data_len = *(uint16_t *)(rx_buf+1); + if (rx_data_len >= SPI_BUF_SIZE) { + SPILOG(LOGE, "SPI: RX data len larger than buf size %d", rx_data_len); + goto fail; + } + + transfer.len = rx_data_len + 1; + transfer.rx_buf = (uint64_t)(rx_buf + 2 + 1); + ret = lltransfer(transfer); + if (ret < 0) { + SPILOG(LOGE, "SPI: failed to read rx data"); + goto fail; + } + if (!check_checksum(rx_buf, rx_data_len + 4)) { + SPILOG(LOGE, "SPI: bad checksum"); + goto fail; + } + + if (rx_data != NULL) { + memcpy(rx_data, rx_buf + 3, rx_data_len); + } + + return rx_data_len; + +fail: + // ensure slave is in a consistent state + // and ready for the next transfer + int nack_cnt = 0; + while (nack_cnt < 3) { + if (wait_for_ack(SPI_NACK, 0x14, 1, SPI_BUF_SIZE/2) == 0) { + nack_cnt += 1; + } else { + nack_cnt = 0; + } + } + + if (ret >= 0) ret = -1; + return ret; +} +#endif diff --git a/selfdrive/pandad/tests/__init__.py b/selfdrive/pandad/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/pandad/tests/bootstub.panda_h7.bin b/selfdrive/pandad/tests/bootstub.panda_h7.bin new file mode 100755 index 0000000000..1d9445004e Binary files /dev/null and b/selfdrive/pandad/tests/bootstub.panda_h7.bin differ diff --git a/selfdrive/pandad/tests/bootstub.panda_h7_spiv0.bin b/selfdrive/pandad/tests/bootstub.panda_h7_spiv0.bin new file mode 100755 index 0000000000..5cf2fa4519 Binary files /dev/null and b/selfdrive/pandad/tests/bootstub.panda_h7_spiv0.bin differ diff --git a/selfdrive/pandad/tests/test_pandad.py b/selfdrive/pandad/tests/test_pandad.py new file mode 100644 index 0000000000..88d3939a6a --- /dev/null +++ b/selfdrive/pandad/tests/test_pandad.py @@ -0,0 +1,114 @@ +import os +import pytest +import time + +import cereal.messaging as messaging +from cereal import log +from openpilot.common.gpio import gpio_set, gpio_init +from panda import Panda, PandaDFU +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.hardware import HARDWARE +from openpilot.system.hardware.tici.pins import GPIO + +HERE = os.path.dirname(os.path.realpath(__file__)) + + +@pytest.mark.tici +class TestPandad: + + def setup_method(self): + # ensure panda is up + if len(Panda.list()) == 0: + self._run_test(60) + + def teardown_method(self): + managed_processes['pandad'].stop() + + def _run_test(self, timeout=30) -> float: + st = time.monotonic() + sm = messaging.SubMaster(['pandaStates']) + + managed_processes['pandad'].start() + while (time.monotonic() - st) < timeout: + sm.update(100) + if len(sm['pandaStates']) and sm['pandaStates'][0].pandaType != log.PandaState.PandaType.unknown: + break + dt = time.monotonic() - st + managed_processes['pandad'].stop() + + if len(sm['pandaStates']) == 0 or sm['pandaStates'][0].pandaType == log.PandaState.PandaType.unknown: + raise Exception("pandad failed to start") + + return dt + + def _go_to_dfu(self): + HARDWARE.recover_internal_panda() + assert Panda.wait_for_dfu(None, 10) + + def _assert_no_panda(self): + assert not Panda.wait_for_dfu(None, 3) + assert not Panda.wait_for_panda(None, 3) + + def _flash_bootstub(self, fn): + self._go_to_dfu() + pd = PandaDFU(None) + if fn is None: + fn = os.path.join(HERE, pd.get_mcu_type().config.bootstub_fn) + with open(fn, "rb") as f: + pd.program_bootstub(f.read()) + pd.reset() + HARDWARE.reset_internal_panda() + + def test_in_dfu(self): + HARDWARE.recover_internal_panda() + self._run_test(60) + + def test_in_bootstub(self): + with Panda() as p: + p.reset(enter_bootstub=True) + assert p.bootstub + self._run_test() + + def test_internal_panda_reset(self): + gpio_init(GPIO.STM_RST_N, True) + gpio_set(GPIO.STM_RST_N, 1) + time.sleep(0.5) + assert all(not Panda(s).is_internal() for s in Panda.list()) + self._run_test() + + assert any(Panda(s).is_internal() for s in Panda.list()) + + def test_best_case_startup_time(self): + # run once so we're up to date + self._run_test(60) + + ts = [] + for _ in range(10): + # should be nearly instant this time + dt = self._run_test(5) + ts.append(dt) + + # 5s for USB (due to enumeration) + # - 0.2s pandad -> pandad + # - plus some buffer + print("startup times", ts, sum(ts) / len(ts)) + assert 0.1 < (sum(ts)/len(ts)) < 0.7 + + def test_old_spi_protocol(self): + # flash firmware with old SPI protocol + self._flash_bootstub(os.path.join(HERE, "bootstub.panda_h7_spiv0.bin")) + self._run_test(45) + + def test_release_to_devel_bootstub(self): + self._flash_bootstub(None) + self._run_test(45) + + def test_recover_from_bad_bootstub(self): + self._go_to_dfu() + with PandaDFU(None) as pd: + pd.program_bootstub(b"\x00"*1024) + pd.reset() + HARDWARE.reset_internal_panda() + self._assert_no_panda() + + self._run_test(60) diff --git a/selfdrive/pandad/tests/test_pandad_loopback.py b/selfdrive/pandad/tests/test_pandad_loopback.py new file mode 100644 index 0000000000..bf1c557128 --- /dev/null +++ b/selfdrive/pandad/tests/test_pandad_loopback.py @@ -0,0 +1,113 @@ +import os +import copy +import random +import time +import pytest +from collections import defaultdict +from pprint import pprint + +import cereal.messaging as messaging +from cereal import car, log +from opendbc.car.can_definitions import CanData +from openpilot.common.retry import retry +from openpilot.common.params import Params +from openpilot.common.timeout import Timeout +from openpilot.selfdrive.pandad import can_list_to_can_capnp +from openpilot.system.hardware import TICI +from openpilot.selfdrive.test.helpers import with_processes + + +@retry(attempts=3) +def setup_pandad(num_pandas): + params = Params() + params.clear_all() + params.put_bool("IsOnroad", False) + + sm = messaging.SubMaster(['pandaStates']) + with Timeout(90, "pandad didn't start"): + while sm.recv_frame['pandaStates'] < 1 or len(sm['pandaStates']) == 0 or \ + any(ps.pandaType == log.PandaState.PandaType.unknown for ps in sm['pandaStates']): + sm.update(1000) + + found_pandas = len(sm['pandaStates']) + assert num_pandas == found_pandas, "connected pandas ({found_pandas}) doesn't match expected panda count ({num_pandas}). \ + connect another panda for multipanda tests." + + # pandad safety setting relies on these params + cp = car.CarParams.new_message() + + safety_config = car.CarParams.SafetyConfig.new_message() + safety_config.safetyModel = car.CarParams.SafetyModel.allOutput + cp.safetyConfigs = [safety_config]*num_pandas + + params.put_bool("IsOnroad", True) + params.put_bool("FirmwareQueryDone", True) + params.put_bool("ControlsReady", True) + params.put("CarParams", cp.to_bytes()) + + with Timeout(90, "pandad didn't set safety mode"): + while any(ps.safetyModel != car.CarParams.SafetyModel.allOutput for ps in sm['pandaStates']): + sm.update(1000) + +def send_random_can_messages(sendcan, count, num_pandas=1): + sent_msgs = defaultdict(set) + for _ in range(count): + to_send = [] + for __ in range(random.randrange(20)): + bus = random.choice([b for b in range(3*num_pandas) if b % 4 != 3]) + addr = random.randrange(1, 1<<29) + dat = bytes(random.getrandbits(8) for _ in range(random.randrange(1, 9))) + if (addr, dat) in sent_msgs[bus]: + continue + sent_msgs[bus].add((addr, dat)) + to_send.append(CanData(addr, dat, bus)) + sendcan.send(can_list_to_can_capnp(to_send, msgtype='sendcan')) + return sent_msgs + + +@pytest.mark.tici +class TestBoarddLoopback: + @classmethod + def setup_class(cls): + os.environ['STARTED'] = '1' + os.environ['BOARDD_LOOPBACK'] = '1' + + @with_processes(['pandad']) + def test_loopback(self): + num_pandas = 2 if TICI and "SINGLE_PANDA" not in os.environ else 1 + setup_pandad(num_pandas) + + sendcan = messaging.pub_sock('sendcan') + can = messaging.sub_sock('can', conflate=False, timeout=100) + sm = messaging.SubMaster(['pandaStates']) + time.sleep(1) + + n = 200 + for i in range(n): + print(f"pandad loopback {i}/{n}") + + sent_msgs = send_random_can_messages(sendcan, random.randrange(20, 100), num_pandas) + + sent_loopback = copy.deepcopy(sent_msgs) + sent_loopback.update({k+128: copy.deepcopy(v) for k, v in sent_msgs.items()}) + sent_total = {k: len(v) for k, v in sent_loopback.items()} + for _ in range(100 * 5): + sm.update(0) + recvd = messaging.drain_sock(can, wait_for_one=True) + for msg in recvd: + for m in msg.can: + key = (m.address, m.dat) + assert key in sent_loopback[m.src], f"got unexpected msg: {m.src=} {m.address=} {m.dat=}" + sent_loopback[m.src].discard(key) + + if all(len(v) == 0 for v in sent_loopback.values()): + break + + # if a set isn't empty, messages got dropped + pprint(sent_msgs) + pprint(sent_loopback) + print({k: len(x) for k, x in sent_loopback.items()}) + print(sum([len(x) for x in sent_loopback.values()])) + pprint(sm['pandaStates']) # may drop messages due to RX buffer overflow + for bus in sent_loopback.keys(): + assert not len(sent_loopback[bus]), f"loop {i}: bus {bus} missing {len(sent_loopback[bus])} out of {sent_total[bus]} messages" diff --git a/selfdrive/pandad/tests/test_pandad_spi.py b/selfdrive/pandad/tests/test_pandad_spi.py new file mode 100644 index 0000000000..da4b181993 --- /dev/null +++ b/selfdrive/pandad/tests/test_pandad_spi.py @@ -0,0 +1,102 @@ +import os +import time +import numpy as np +import pytest +import random + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from openpilot.selfdrive.test.helpers import with_processes +from openpilot.selfdrive.pandad.tests.test_pandad_loopback import setup_pandad, send_random_can_messages + +JUNGLE_SPAM = "JUNGLE_SPAM" in os.environ + +@pytest.mark.tici +class TestBoarddSpi: + @classmethod + def setup_class(cls): + os.environ['STARTED'] = '1' + os.environ['SPI_ERR_PROB'] = '0.001' + if not JUNGLE_SPAM: + os.environ['BOARDD_LOOPBACK'] = '1' + + @with_processes(['pandad']) + def test_spi_corruption(self, subtests): + setup_pandad(1) + + sendcan = messaging.pub_sock('sendcan') + socks = {s: messaging.sub_sock(s, conflate=False, timeout=100) for s in ('can', 'pandaStates', 'peripheralState')} + time.sleep(2) + for s in socks.values(): + messaging.drain_sock_raw(s) + + total_recv_count = 0 + total_sent_count = 0 + sent_msgs = {bus: list() for bus in range(3)} + + st = time.monotonic() + ts = {s: list() for s in socks.keys()} + for _ in range(int(os.getenv("TEST_TIME", "20"))): + # send some CAN messages + if not JUNGLE_SPAM: + sent = send_random_can_messages(sendcan, random.randrange(2, 20)) + for k, v in sent.items(): + sent_msgs[k].extend(list(v)) + total_sent_count += len(v) + + for service, sock in socks.items(): + for m in messaging.drain_sock(sock): + ts[service].append(m.logMonoTime) + + # sanity check for corruption + assert m.valid or (service == "can") + if service == "can": + for msg in m.can: + if JUNGLE_SPAM: + # PandaJungle.set_generated_can(True) + i = msg.address - 0x200 + assert msg.address >= 0x200 + assert msg.src == (i%3) + assert msg.dat == b"\xff"*(i%8) + total_recv_count += 1 + continue + + if msg.src > 4: + continue + key = (msg.address, msg.dat) + assert key in sent_msgs[msg.src], f"got unexpected msg: {msg.src=} {msg.address=} {msg.dat=}" + # TODO: enable this + #sent_msgs[msg.src].remove(key) + total_recv_count += 1 + elif service == "pandaStates": + assert len(m.pandaStates) == 1 + ps = m.pandaStates[0] + assert ps.uptime < 1000 + assert ps.pandaType == "tres" + assert ps.ignitionLine + assert not ps.ignitionCan + assert 4000 < ps.voltage < 14000 + elif service == "peripheralState": + ps = m.peripheralState + assert ps.pandaType == "tres" + assert 4000 < ps.voltage < 14000 + assert 50 < ps.current < 1000 + assert ps.fanSpeedRpm < 10000 + + time.sleep(0.5) + et = time.monotonic() - st + + print("\n======== timing report ========") + for service, times in ts.items(): + dts = np.diff(times)/1e6 + print(service.ljust(17), f"{np.mean(dts):7.2f} {np.min(dts):7.2f} {np.max(dts):7.2f}") + with subtests.test(msg="timing check", service=service): + edt = 1e3 / SERVICE_LIST[service].frequency + assert edt*0.9 < np.mean(dts) < edt*1.1 + assert np.max(dts) < edt*8 + assert np.min(dts) < edt + assert len(dts) >= ((et-0.5)*SERVICE_LIST[service].frequency*0.8) + + with subtests.test(msg="CAN traffic"): + print(f"Sent {total_sent_count} CAN messages, got {total_recv_count} back. {total_recv_count/(total_sent_count+1e-4):.2%} received") + assert total_recv_count > 20 diff --git a/selfdrive/pandad/tests/test_pandad_usbprotocol.cc b/selfdrive/pandad/tests/test_pandad_usbprotocol.cc new file mode 100644 index 0000000000..11f7184efd --- /dev/null +++ b/selfdrive/pandad/tests/test_pandad_usbprotocol.cc @@ -0,0 +1,135 @@ +#define CATCH_CONFIG_MAIN +#define CATCH_CONFIG_ENABLE_BENCHMARKING + +#include "catch2/catch.hpp" +#include "cereal/messaging/messaging.h" +#include "common/util.h" +#include "selfdrive/pandad/panda.h" + +struct PandaTest : public Panda { + PandaTest(uint32_t bus_offset, int can_list_size, cereal::PandaState::PandaType hw_type); + void test_can_send(); + void test_can_recv(uint32_t chunk_size = 0); + void test_chunked_can_recv(); + + std::map test_data; + int can_list_size = 0; + int total_pakets_size = 0; + MessageBuilder msg; + capnp::List::Reader can_data_list; +}; + +PandaTest::PandaTest(uint32_t bus_offset_, int can_list_size, cereal::PandaState::PandaType hw_type) : can_list_size(can_list_size), Panda(bus_offset_) { + this->hw_type = hw_type; + int data_limit = ((hw_type == cereal::PandaState::PandaType::RED_PANDA) ? std::size(dlc_to_len) : 8); + // prepare test data + for (int i = 0; i < data_limit; ++i) { + std::random_device rd; + std::independent_bits_engine rbe(rd()); + + int data_len = dlc_to_len[i]; + std::string bytes(data_len, '\0'); + std::generate(bytes.begin(), bytes.end(), std::ref(rbe)); + test_data[data_len] = bytes; + } + + // generate can messages for this panda + auto can_list = msg.initEvent().initSendcan(can_list_size); + for (uint8_t i = 0; i < can_list_size; ++i) { + auto can = can_list[i]; + uint32_t id = util::random_int(0, std::size(dlc_to_len) - 1); + const std::string &dat = test_data[dlc_to_len[id]]; + can.setAddress(i); + can.setSrc(util::random_int(0, 2) + bus_offset); + can.setDat(kj::ArrayPtr((uint8_t *)dat.data(), dat.size())); + total_pakets_size += sizeof(can_header) + dat.size(); + } + + can_data_list = can_list.asReader(); + INFO("test " << can_list_size << " packets, total size " << total_pakets_size); +} + +void PandaTest::test_can_send() { + std::vector unpacked_data; + this->pack_can_buffer(can_data_list, [&](uint8_t *chunk, size_t size) { + unpacked_data.insert(unpacked_data.end(), chunk, &chunk[size]); + }); + REQUIRE(unpacked_data.size() == total_pakets_size); + + int cnt = 0; + INFO("test can message integrity"); + for (int pos = 0, pckt_len = 0; pos < unpacked_data.size(); pos += pckt_len) { + can_header header; + memcpy(&header, &unpacked_data[pos], sizeof(can_header)); + const uint8_t data_len = dlc_to_len[header.data_len_code]; + pckt_len = sizeof(can_header) + data_len; + + REQUIRE(header.addr == cnt); + REQUIRE(test_data.find(data_len) != test_data.end()); + const std::string &dat = test_data[data_len]; + REQUIRE(memcmp(dat.data(), &unpacked_data[pos + sizeof(can_header)], dat.size()) == 0); + ++cnt; + } + REQUIRE(cnt == can_list_size); +} + +void PandaTest::test_can_recv(uint32_t rx_chunk_size) { + std::vector frames; + this->pack_can_buffer(can_data_list, [&](uint8_t *data, uint32_t size) { + if (rx_chunk_size == 0) { + REQUIRE(this->unpack_can_buffer(data, size, frames)); + } else { + this->receive_buffer_size = 0; + uint32_t pos = 0; + + while (pos < size) { + uint32_t chunk_size = std::min(rx_chunk_size, size - pos); + memcpy(&this->receive_buffer[this->receive_buffer_size], &data[pos], chunk_size); + this->receive_buffer_size += chunk_size; + pos += chunk_size; + + REQUIRE(this->unpack_can_buffer(this->receive_buffer, this->receive_buffer_size, frames)); + } + } + }); + + REQUIRE(frames.size() == can_list_size); + for (int i = 0; i < frames.size(); ++i) { + REQUIRE(frames[i].address == i); + REQUIRE(test_data.find(frames[i].dat.size()) != test_data.end()); + const std::string &dat = test_data[frames[i].dat.size()]; + REQUIRE(memcmp(dat.data(), frames[i].dat.data(), dat.size()) == 0); + } +} + +TEST_CASE("send/recv CAN 2.0 packets") { + auto bus_offset = GENERATE(0, 4); + auto can_list_size = GENERATE(1, 3, 5, 10, 30, 60, 100, 200); + PandaTest test(bus_offset, can_list_size, cereal::PandaState::PandaType::DOS); + + SECTION("can_send") { + test.test_can_send(); + } + SECTION("can_receive") { + test.test_can_recv(); + } + SECTION("chunked_can_receive") { + test.test_can_recv(0x40); + } +} + +TEST_CASE("send/recv CAN FD packets") { + auto bus_offset = GENERATE(0, 4); + auto can_list_size = GENERATE(1, 3, 5, 10, 30, 60, 100, 200); + PandaTest test(bus_offset, can_list_size, cereal::PandaState::PandaType::RED_PANDA); + + SECTION("can_send") { + test.test_can_send(); + } + SECTION("can_receive") { + test.test_can_recv(); + } + SECTION("chunked_can_receive") { + test.test_can_recv(0x40); + } +} diff --git a/selfdrive/selfdrived/alertmanager.py b/selfdrive/selfdrived/alertmanager.py new file mode 100644 index 0000000000..251d32ba9a --- /dev/null +++ b/selfdrive/selfdrived/alertmanager.py @@ -0,0 +1,67 @@ +import copy +import os +import json +from collections import defaultdict +from dataclasses import dataclass + +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.selfdrive.selfdrived.events import Alert, EmptyAlert + + +with open(os.path.join(BASEDIR, "selfdrive/selfdrived/alerts_offroad.json")) as f: + OFFROAD_ALERTS = json.load(f) + + +def set_offroad_alert(alert: str, show_alert: bool, extra_text: str = None) -> None: + if show_alert: + a = copy.copy(OFFROAD_ALERTS[alert]) + a['extra'] = extra_text or '' + Params().put(alert, a) + else: + Params().remove(alert) + + +@dataclass +class AlertEntry: + alert: Alert | None = None + start_frame: int = -1 + end_frame: int = -1 + added_frame: int = -1 + + def active(self, frame: int) -> bool: + return frame <= self.end_frame + + def just_added(self, frame: int) -> bool: + return self.active(frame) and frame == (self.added_frame + 1) + +class AlertManager: + def __init__(self): + self.alerts: dict[str, AlertEntry] = defaultdict(AlertEntry) + self.current_alert = EmptyAlert + + def add_many(self, frame: int, alerts: list[Alert]) -> None: + for alert in alerts: + entry = self.alerts[alert.alert_type] + entry.alert = alert + if not entry.just_added(frame): + entry.start_frame = frame + min_end_frame = entry.start_frame + alert.duration + entry.end_frame = max(frame + 1, min_end_frame) + entry.added_frame = frame + + def process_alerts(self, frame: int, clear_event_types: set): + ae = AlertEntry() + for v in self.alerts.values(): + if not v.alert: + continue + + if v.alert.event_type in clear_event_types: + v.end_frame = -1 + + # sort by priority first and then by start_frame + greater = ae.alert is None or (v.alert.priority, v.start_frame) > (ae.alert.priority, ae.start_frame) + if v.active(frame) and greater: + ae = v + + self.current_alert = ae.alert if ae.alert is not None else EmptyAlert diff --git a/selfdrive/selfdrived/alerts_offroad.json b/selfdrive/selfdrived/alerts_offroad.json new file mode 100644 index 0000000000..3d97135f60 --- /dev/null +++ b/selfdrive/selfdrived/alerts_offroad.json @@ -0,0 +1,45 @@ +{ + "Offroad_TemperatureTooHigh": { + "text": "Device temperature too high. System cooling down before starting. Current internal component temperature: %1", + "severity": 0 + }, + "Offroad_ConnectivityNeededPrompt": { + "text": "Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1", + "severity": 0, + "_comment": "Set extra field to number of days" + }, + "Offroad_ConnectivityNeeded": { + "text": "Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates.", + "severity": 1 + }, + "Offroad_UpdateFailed": { + "text": "Unable to download updates\n%1", + "severity": 1, + "_comment": "Set extra field to the failed reason." + }, + "Offroad_IsTakingSnapshot": { + "text": "Taking camera snapshots. System won't start until finished.", + "severity": 0 + }, + "Offroad_NeosUpdate": { + "text": "An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install.", + "severity": 0 + }, + "Offroad_UnregisteredHardware": { + "text": "Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support.", + "severity": 1 + }, + "Offroad_CarUnrecognized": { + "text": "openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai.", + "severity": 0 + }, + "Offroad_Recalibration": { + "text": "openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield.", + "severity": 0 + }, + "Offroad_ExcessiveActuation": { + "text": "openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting.", + "severity": 1, + "_comment": "Set extra field to lateral or longitudinal." + } +} diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py new file mode 100755 index 0000000000..c865cc94a6 --- /dev/null +++ b/selfdrive/selfdrived/events.py @@ -0,0 +1,1042 @@ +#!/usr/bin/env python3 +import bisect +import math +import os +from enum import IntEnum +from collections.abc import Callable + +from cereal import log, car +import cereal.messaging as messaging +from openpilot.common.constants import CV +from openpilot.common.git import get_short_branch +from openpilot.common.realtime import DT_CTRL +from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER +from openpilot.system.micd import SAMPLE_RATE, SAMPLE_BUFFER +from openpilot.selfdrive.ui.feedback.feedbackd import FEEDBACK_MAX_DURATION + +AlertSize = log.SelfdriveState.AlertSize +AlertStatus = log.SelfdriveState.AlertStatus +VisualAlert = car.CarControl.HUDControl.VisualAlert +AudibleAlert = car.CarControl.HUDControl.AudibleAlert +EventName = log.OnroadEvent.EventName + + +# Alert priorities +class Priority(IntEnum): + LOWEST = 0 + LOWER = 1 + LOW = 2 + MID = 3 + HIGH = 4 + HIGHEST = 5 + + +# Event types +class ET: + ENABLE = 'enable' + PRE_ENABLE = 'preEnable' + OVERRIDE_LATERAL = 'overrideLateral' + OVERRIDE_LONGITUDINAL = 'overrideLongitudinal' + NO_ENTRY = 'noEntry' + WARNING = 'warning' + USER_DISABLE = 'userDisable' + SOFT_DISABLE = 'softDisable' + IMMEDIATE_DISABLE = 'immediateDisable' + PERMANENT = 'permanent' + + +# get event name from enum +EVENT_NAME = {v: k for k, v in EventName.schema.enumerants.items()} + + +class Events: + def __init__(self): + self.events: list[int] = [] + self.static_events: list[int] = [] + self.event_counters = dict.fromkeys(EVENTS.keys(), 0) + + @property + def names(self) -> list[int]: + return self.events + + def __len__(self) -> int: + return len(self.events) + + def add(self, event_name: int, static: bool=False) -> None: + if static: + bisect.insort(self.static_events, event_name) + bisect.insort(self.events, event_name) + + def clear(self) -> None: + self.event_counters = {k: (v + 1 if k in self.events else 0) for k, v in self.event_counters.items()} + self.events = self.static_events.copy() + + def contains(self, event_type: str) -> bool: + return any(event_type in EVENTS.get(e, {}) for e in self.events) + + def create_alerts(self, event_types: list[str], callback_args=None): + if callback_args is None: + callback_args = [] + + ret = [] + for e in self.events: + types = EVENTS[e].keys() + for et in event_types: + if et in types: + alert = EVENTS[e][et] + if not isinstance(alert, Alert): + alert = alert(*callback_args) + + if DT_CTRL * (self.event_counters[e] + 1) >= alert.creation_delay: + alert.alert_type = f"{EVENT_NAME[e]}/{et}" + alert.event_type = et + ret.append(alert) + return ret + + def add_from_msg(self, events): + for e in events: + bisect.insort(self.events, e.name.raw) + + def to_msg(self): + ret = [] + for event_name in self.events: + event = log.OnroadEvent.new_message() + event.name = event_name + for event_type in EVENTS.get(event_name, {}): + setattr(event, event_type, True) + ret.append(event) + return ret + + +class Alert: + def __init__(self, + alert_text_1: str, + alert_text_2: str, + alert_status: log.SelfdriveState.AlertStatus, + alert_size: log.SelfdriveState.AlertSize, + priority: Priority, + visual_alert: car.CarControl.HUDControl.VisualAlert, + audible_alert: car.CarControl.HUDControl.AudibleAlert, + duration: float, + creation_delay: float = 0.): + + self.alert_text_1 = alert_text_1 + self.alert_text_2 = alert_text_2 + self.alert_status = alert_status + self.alert_size = alert_size + self.priority = priority + self.visual_alert = visual_alert + self.audible_alert = audible_alert + + self.duration = int(duration / DT_CTRL) + + self.creation_delay = creation_delay + + self.alert_type = "" + self.event_type: str | None = None + + def __str__(self) -> str: + return f"{self.alert_text_1}/{self.alert_text_2} {self.priority} {self.visual_alert} {self.audible_alert}" + + def __gt__(self, alert2) -> bool: + if not isinstance(alert2, Alert): + return False + return self.priority > alert2.priority + +EmptyAlert = Alert("" , "", AlertStatus.normal, AlertSize.none, Priority.LOWEST, + VisualAlert.none, AudibleAlert.none, 0) + +class NoEntryAlert(Alert): + def __init__(self, alert_text_2: str, + alert_text_1: str = "openpilot Unavailable", + visual_alert: car.CarControl.HUDControl.VisualAlert=VisualAlert.none): + super().__init__(alert_text_1, alert_text_2, AlertStatus.normal, + AlertSize.mid, Priority.LOW, visual_alert, + AudibleAlert.refuse, 3.) + + +class SoftDisableAlert(Alert): + def __init__(self, alert_text_2: str): + super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2, + AlertStatus.userPrompt, AlertSize.full, + Priority.MID, VisualAlert.steerRequired, + AudibleAlert.warningSoft, 2.), + + +# less harsh version of SoftDisable, where the condition is user-triggered +class UserSoftDisableAlert(SoftDisableAlert): + def __init__(self, alert_text_2: str): + super().__init__(alert_text_2), + self.alert_text_1 = "openpilot will disengage" + + +class ImmediateDisableAlert(Alert): + def __init__(self, alert_text_2: str): + super().__init__("TAKE CONTROL IMMEDIATELY", alert_text_2, + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.steerRequired, + AudibleAlert.warningImmediate, 4.), + + +class EngagementAlert(Alert): + def __init__(self, audible_alert: car.CarControl.HUDControl.AudibleAlert): + super().__init__("", "", + AlertStatus.normal, AlertSize.none, + Priority.MID, VisualAlert.none, + audible_alert, .2), + + +class NormalPermanentAlert(Alert): + def __init__(self, alert_text_1: str, alert_text_2: str = "", duration: float = 0.2, priority: Priority = Priority.LOWER, creation_delay: float = 0.): + super().__init__(alert_text_1, alert_text_2, + AlertStatus.normal, AlertSize.mid if len(alert_text_2) else AlertSize.small, + priority, VisualAlert.none, AudibleAlert.none, duration, creation_delay=creation_delay), + + +class StartupAlert(Alert): + def __init__(self, alert_text_1: str, alert_text_2: str = "Always keep hands on wheel and eyes on road", alert_status=AlertStatus.normal): + super().__init__(alert_text_1, alert_text_2, + alert_status, AlertSize.mid, + Priority.LOWER, VisualAlert.none, AudibleAlert.none, 5.), + + + +# ********** helper functions ********** +def get_display_speed(speed_ms: float, metric: bool) -> str: + speed = int(round(speed_ms * (CV.MS_TO_KPH if metric else CV.MS_TO_MPH))) + unit = 'km/h' if metric else 'mph' + return f"{speed} {unit}" + + +# ********** alert callback functions ********** + +AlertCallbackType = Callable[[car.CarParams, car.CarState, messaging.SubMaster, bool, int, log.ControlsState], Alert] + + +def soft_disable_alert(alert_text_2: str) -> AlertCallbackType: + def func(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + if soft_disable_time < int(0.5 / DT_CTRL): + return ImmediateDisableAlert(alert_text_2) + return SoftDisableAlert(alert_text_2) + return func + +def user_soft_disable_alert(alert_text_2: str) -> AlertCallbackType: + def func(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + if soft_disable_time < int(0.5 / DT_CTRL): + return ImmediateDisableAlert(alert_text_2) + return UserSoftDisableAlert(alert_text_2) + return func + +def startup_master_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + branch = get_short_branch() # Ensure get_short_branch is cached to avoid lags on startup + if "REPLAY" in os.environ: + branch = "replay" + + return StartupAlert("WARNING: This branch is not tested", branch, alert_status=AlertStatus.userPrompt) + +def below_engage_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + return NoEntryAlert(f"Drive above {get_display_speed(CP.minEnableSpeed, metric)} to engage") + + +def below_steer_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + return Alert( + f"Steer Assist Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, 0.4) + + +def calibration_incomplete_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + first_word = 'Recalibration' if sm['liveCalibration'].calStatus == log.LiveCalibrationData.Status.recalibrating else 'Calibration' + return Alert( + f"{first_word} in Progress: {sm['liveCalibration'].calPerc:.0f}%", + f"Drive Above {get_display_speed(MIN_SPEED_FILTER, metric)}", + AlertStatus.normal, AlertSize.mid, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2) + + +def audio_feedback_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + duration = FEEDBACK_MAX_DURATION - ((sm['audioFeedback'].blockNum + 1) * SAMPLE_BUFFER / SAMPLE_RATE) + return NormalPermanentAlert( + "Recording Audio Feedback", + f"{round(duration)} second{'s' if round(duration) != 1 else ''} remaining. Press again to save early.", + priority=Priority.LOW) + + +# *** debug alerts *** + +def out_of_space_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + full_perc = round(100. - sm['deviceState'].freeSpacePercent) + return NormalPermanentAlert("Out of Storage", f"{full_perc}% full") + + +def posenet_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + mdl = sm['modelV2'].velocity.x[0] if len(sm['modelV2'].velocity.x) else math.nan + err = CS.vEgo - mdl + msg = f"Speed Error: {err:.1f} m/s" + return NoEntryAlert(msg, alert_text_1="Posenet Speed Invalid") + + +def process_not_running_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + not_running = [p.name for p in sm['managerState'].processes if not p.running and p.shouldBeRunning] + msg = ', '.join(not_running) + return NoEntryAlert(msg, alert_text_1="Process Not Running") + + +def comm_issue_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + bs = [s for s in sm.data.keys() if not sm.all_checks([s, ])] + msg = ', '.join(bs[:4]) # can't fit too many on one line + return NoEntryAlert(msg, alert_text_1="Communication Issue Between Processes") + + +def camera_malfunction_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + all_cams = ('roadCameraState', 'driverCameraState', 'wideRoadCameraState') + bad_cams = [s.replace('State', '') for s in all_cams if s in sm.data.keys() and not sm.all_checks([s, ])] + return NormalPermanentAlert("Camera Malfunction", ', '.join(bad_cams)) + + +def calibration_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + rpy = sm['liveCalibration'].rpyCalib + yaw = math.degrees(rpy[2] if len(rpy) == 3 else math.nan) + pitch = math.degrees(rpy[1] if len(rpy) == 3 else math.nan) + angles = f"Remount Device (Pitch: {pitch:.1f}°, Yaw: {yaw:.1f}°)" + return NormalPermanentAlert("Calibration Invalid", angles) + + +def paramsd_invalid_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + if not sm['liveParameters'].angleOffsetValid: + angle_offset_deg = sm['liveParameters'].angleOffsetDeg + title = "Steering misalignment detected" + text = f"Angle offset too high (Offset: {angle_offset_deg:.1f}°)" + elif not sm['liveParameters'].steerRatioValid: + steer_ratio = sm['liveParameters'].steerRatio + title = "Steer ratio mismatch" + text = f"Steering rack geometry may be off (Ratio: {steer_ratio:.1f})" + elif not sm['liveParameters'].stiffnessFactorValid: + stiffness_factor = sm['liveParameters'].stiffnessFactor + title = "Abnormal tire stiffness" + text = f"Check tires, pressure, or alignment (Factor: {stiffness_factor:.1f})" + else: + return NoEntryAlert("paramsd Temporary Error") + + return NoEntryAlert(alert_text_1=title, alert_text_2=text) + +def overheat_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + cpu = max(sm['deviceState'].cpuTempC, default=0.) + gpu = max(sm['deviceState'].gpuTempC, default=0.) + temp = max((cpu, gpu, sm['deviceState'].memoryTempC)) + return NormalPermanentAlert("System Overheated", f"{temp:.0f} °C") + + +def low_memory_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + return NormalPermanentAlert("Low Memory", f"{sm['deviceState'].memoryUsagePercent}% used") + + +def high_cpu_usage_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + x = max(sm['deviceState'].cpuUsagePercent, default=0.) + return NormalPermanentAlert("High CPU Usage", f"{x}% used") + + +def modeld_lagging_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + return NormalPermanentAlert("Driving Model Lagging", f"{sm['modelV2'].frameDropPerc:.1f}% frames dropped") + + +def wrong_car_mode_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + text = "Enable Adaptive Cruise to Engage" + if CP.brand == "honda": + text = "Enable Main Switch to Engage" + return NoEntryAlert(text) + + +def joystick_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + gb = sm['carControl'].actuators.accel / 4. + steer = sm['carControl'].actuators.torque + vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%" + return NormalPermanentAlert("Joystick Mode", vals) + + +def longitudinal_maneuver_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + ad = sm['alertDebug'] + audible_alert = AudibleAlert.prompt if 'Active' in ad.alertText1 else AudibleAlert.none + alert_status = AlertStatus.userPrompt if 'Active' in ad.alertText1 else AlertStatus.normal + alert_size = AlertSize.mid if ad.alertText2 else AlertSize.small + return Alert(ad.alertText1, ad.alertText2, + alert_status, alert_size, + Priority.LOW, VisualAlert.none, audible_alert, 0.2) + + +def personality_changed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + personality = str(personality).title() + return NormalPermanentAlert(f"Driving Personality: {personality}", duration=1.5) + + +def invalid_lkas_setting_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: + text = "Toggle stock LKAS on or off to engage" + if CP.brand == "tesla": + text = "Switch to Traffic-Aware Cruise Control to engage" + elif CP.brand == "mazda": + text = "Enable your car's LKAS to engage" + elif CP.brand == "nissan": + text = "Disable your car's stock LKAS to engage" + return NormalPermanentAlert("Invalid LKAS setting", text) + + + +EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { + # ********** events with no alerts ********** + + EventName.stockFcw: {}, + EventName.actuatorsApiUnavailable: {}, + + # ********** events only containing alerts displayed in all states ********** + + EventName.joystickDebug: { + ET.WARNING: joystick_alert, + ET.PERMANENT: NormalPermanentAlert("Joystick Mode"), + }, + + EventName.longitudinalManeuver: { + ET.WARNING: longitudinal_maneuver_alert, + ET.PERMANENT: NormalPermanentAlert("Longitudinal Maneuver Mode", + "Ensure road ahead is clear"), + }, + + EventName.selfdriveInitializing: { + ET.NO_ENTRY: NoEntryAlert("System Initializing"), + }, + + EventName.startup: { + ET.PERMANENT: StartupAlert("Be ready to take over at any time") + }, + + EventName.startupMaster: { + ET.PERMANENT: startup_master_alert, + }, + + EventName.startupNoControl: { + ET.PERMANENT: StartupAlert("Dashcam mode"), + ET.NO_ENTRY: NoEntryAlert("Dashcam mode"), + }, + + EventName.startupNoCar: { + ET.PERMANENT: StartupAlert("Dashcam mode for unsupported car"), + }, + + EventName.startupNoSecOcKey: { + ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", + "Security Key Not Available", + priority=Priority.HIGH), + }, + + EventName.dashcamMode: { + ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", + priority=Priority.LOWEST), + }, + + EventName.invalidLkasSetting: { + ET.PERMANENT: invalid_lkas_setting_alert, + ET.NO_ENTRY: NoEntryAlert("Invalid LKAS setting"), + }, + + EventName.cruiseMismatch: { + #ET.PERMANENT: ImmediateDisableAlert("openpilot failed to cancel cruise"), + }, + + # openpilot doesn't recognize the car. This switches openpilot into a + # read-only mode. This can be solved by adding your fingerprint. + # See https://github.com/commaai/openpilot/wiki/Fingerprinting for more information + EventName.carUnrecognized: { + ET.PERMANENT: NormalPermanentAlert("Dashcam Mode", + "Car Unrecognized", + priority=Priority.LOWEST), + }, + + EventName.aeb: { + ET.PERMANENT: Alert( + "BRAKE!", + "Emergency Braking: Risk of Collision", + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.), + ET.NO_ENTRY: NoEntryAlert("AEB: Risk of Collision"), + }, + + EventName.stockAeb: { + ET.PERMANENT: Alert( + "BRAKE!", + "Stock AEB: Risk of Collision", + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 2.), + ET.NO_ENTRY: NoEntryAlert("Stock AEB: Risk of Collision"), + }, + + EventName.fcw: { + ET.PERMANENT: Alert( + "BRAKE!", + "Risk of Collision", + AlertStatus.critical, AlertSize.full, + Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.warningSoft, 2.), + }, + + EventName.ldw: { + ET.PERMANENT: Alert( + "Lane Departure Detected", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.ldw, AudibleAlert.prompt, 3.), + }, + + # ********** events only containing alerts that display while engaged ********** + + EventName.steerTempUnavailableSilent: { + ET.WARNING: Alert( + "Steering Assist Temporarily Unavailable", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.prompt, 1.8), + }, + + EventName.preDriverDistracted: { + ET.PERMANENT: Alert( + "Pay Attention", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.promptDriverDistracted: { + ET.PERMANENT: Alert( + "Pay Attention", + "Driver Distracted", + AlertStatus.userPrompt, AlertSize.mid, + Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1), + }, + + EventName.driverDistracted: { + ET.PERMANENT: Alert( + "DISENGAGE IMMEDIATELY", + "Driver Distracted", + AlertStatus.critical, AlertSize.full, + Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1), + }, + + EventName.preDriverUnresponsive: { + ET.PERMANENT: Alert( + "Touch Steering Wheel: No Face Detected", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .1), + }, + + EventName.promptDriverUnresponsive: { + ET.PERMANENT: Alert( + "Touch Steering Wheel", + "Driver Unresponsive", + AlertStatus.userPrompt, AlertSize.mid, + Priority.MID, VisualAlert.steerRequired, AudibleAlert.promptDistracted, .1), + }, + + EventName.driverUnresponsive: { + ET.PERMANENT: Alert( + "DISENGAGE IMMEDIATELY", + "Driver Unresponsive", + AlertStatus.critical, AlertSize.full, + Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.warningImmediate, .1), + }, + + EventName.manualRestart: { + ET.WARNING: Alert( + "TAKE CONTROL", + "Resume Driving Manually", + AlertStatus.userPrompt, AlertSize.mid, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + + EventName.resumeRequired: { + ET.WARNING: Alert( + "Press Resume to Exit Standstill", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + + EventName.belowSteerSpeed: { + ET.WARNING: below_steer_speed_alert, + }, + + EventName.preLaneChangeLeft: { + ET.WARNING: Alert( + "Steer Left to Start Lane Change Once Safe", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.preLaneChangeRight: { + ET.WARNING: Alert( + "Steer Right to Start Lane Change Once Safe", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.laneChangeBlocked: { + ET.WARNING: Alert( + "Car Detected in Blindspot", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.prompt, .1), + }, + + EventName.laneChange: { + ET.WARNING: Alert( + "Changing Lanes", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.steerSaturated: { + ET.WARNING: Alert( + "Take Control", + "Turn Exceeds Steering Limit", + AlertStatus.userPrompt, AlertSize.mid, + Priority.LOW, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 2.), + }, + + # Thrown when the fan is driven at >50% but is not rotating + EventName.fanMalfunction: { + ET.PERMANENT: NormalPermanentAlert("Fan Malfunction", "Likely Hardware Issue"), + }, + + # Camera is not outputting frames + EventName.cameraMalfunction: { + ET.PERMANENT: camera_malfunction_alert, + ET.SOFT_DISABLE: soft_disable_alert("Camera Malfunction"), + ET.NO_ENTRY: NoEntryAlert("Camera Malfunction: Reboot Your Device"), + }, + # Camera framerate too low + EventName.cameraFrameRate: { + ET.PERMANENT: NormalPermanentAlert("Camera Frame Rate Low", "Reboot your Device"), + ET.SOFT_DISABLE: soft_disable_alert("Camera Frame Rate Low"), + ET.NO_ENTRY: NoEntryAlert("Camera Frame Rate Low: Reboot Your Device"), + }, + + # Unused + + EventName.locationdTemporaryError: { + ET.NO_ENTRY: NoEntryAlert("locationd Temporary Error"), + ET.SOFT_DISABLE: soft_disable_alert("locationd Temporary Error"), + }, + + EventName.locationdPermanentError: { + ET.NO_ENTRY: NoEntryAlert("locationd Permanent Error"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("locationd Permanent Error"), + ET.PERMANENT: NormalPermanentAlert("locationd Permanent Error"), + }, + + # openpilot tries to learn certain parameters about your car by observing + # how the car behaves to steering inputs from both human and openpilot driving. + # This includes: + # - steer ratio: gear ratio of the steering rack. Steering angle divided by tire angle + # - tire stiffness: how much grip your tires have + # - angle offset: most steering angle sensors are offset and measure a non zero angle when driving straight + # This alert is thrown when any of these values exceed a sanity check. This can be caused by + # bad alignment or bad sensor data. If this happens consistently consider creating an issue on GitHub + EventName.paramsdTemporaryError: { + ET.NO_ENTRY: paramsd_invalid_alert, + ET.SOFT_DISABLE: soft_disable_alert("paramsd Temporary Error"), + }, + + EventName.paramsdPermanentError: { + ET.NO_ENTRY: NoEntryAlert("paramsd Permanent Error"), + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("paramsd Permanent Error"), + ET.PERMANENT: NormalPermanentAlert("paramsd Permanent Error"), + }, + + # ********** events that affect controls state transitions ********** + + EventName.pcmEnable: { + ET.ENABLE: EngagementAlert(AudibleAlert.engage), + }, + + EventName.buttonEnable: { + ET.ENABLE: EngagementAlert(AudibleAlert.engage), + }, + + EventName.pcmDisable: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + }, + + EventName.buttonCancel: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Cancel Pressed"), + }, + + EventName.brakeHold: { + ET.WARNING: Alert( + "Press Resume to Exit Brake Hold", + "", + AlertStatus.userPrompt, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, .2), + }, + + EventName.parkBrake: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Parking Brake Engaged"), + }, + + EventName.pedalPressed: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Pedal Pressed", + visual_alert=VisualAlert.brakePressed), + }, + + EventName.steerDisengage: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Steering Pressed"), + }, + + EventName.preEnableStandstill: { + ET.PRE_ENABLE: Alert( + "Release Brake to Engage", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1, creation_delay=1.), + }, + + EventName.gasPressedOverride: { + ET.OVERRIDE_LONGITUDINAL: Alert( + "", + "", + AlertStatus.normal, AlertSize.none, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.steerOverride: { + ET.OVERRIDE_LATERAL: Alert( + "", + "", + AlertStatus.normal, AlertSize.none, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1), + }, + + EventName.wrongCarMode: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: wrong_car_mode_alert, + }, + + EventName.resumeBlocked: { + ET.NO_ENTRY: NoEntryAlert("Press Set to Engage"), + }, + + EventName.wrongCruiseMode: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + ET.NO_ENTRY: NoEntryAlert("Adaptive Cruise Disabled"), + }, + + EventName.steerTempUnavailable: { + ET.SOFT_DISABLE: soft_disable_alert("Steering Assist Temporarily Unavailable"), + ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable"), + }, + + EventName.steerTimeLimit: { + ET.SOFT_DISABLE: soft_disable_alert("Vehicle Steering Time Limit"), + ET.NO_ENTRY: NoEntryAlert("Vehicle Steering Time Limit"), + }, + + EventName.outOfSpace: { + ET.PERMANENT: out_of_space_alert, + ET.NO_ENTRY: NoEntryAlert("Out of Storage"), + }, + + EventName.belowEngageSpeed: { + ET.NO_ENTRY: below_engage_speed_alert, + }, + + EventName.sensorDataInvalid: { + ET.PERMANENT: Alert( + "Sensor Data Invalid", + "Possible Hardware Issue", + AlertStatus.normal, AlertSize.mid, + Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=1.), + ET.NO_ENTRY: NoEntryAlert("Sensor Data Invalid"), + ET.SOFT_DISABLE: soft_disable_alert("Sensor Data Invalid"), + }, + + EventName.noGps: { + }, + + EventName.tooDistracted: { + ET.NO_ENTRY: NoEntryAlert("Distraction Level Too High"), + }, + + EventName.excessiveActuation: { + ET.SOFT_DISABLE: soft_disable_alert("Excessive Actuation"), + ET.NO_ENTRY: NoEntryAlert("Excessive Actuation"), + }, + + EventName.overheat: { + ET.PERMANENT: overheat_alert, + ET.SOFT_DISABLE: soft_disable_alert("System Overheated"), + ET.NO_ENTRY: NoEntryAlert("System Overheated"), + }, + + EventName.wrongGear: { + ET.SOFT_DISABLE: user_soft_disable_alert("Gear not D"), + ET.NO_ENTRY: NoEntryAlert("Gear not D"), + }, + + # This alert is thrown when the calibration angles are outside of the acceptable range. + # For example if the device is pointed too much to the left or the right. + # Usually this can only be solved by removing the mount from the windshield completely, + # and attaching while making sure the device is pointed straight forward and is level. + # See https://comma.ai/setup for more information + EventName.calibrationInvalid: { + ET.PERMANENT: calibration_invalid_alert, + ET.SOFT_DISABLE: soft_disable_alert("Calibration Invalid: Remount Device & Recalibrate"), + ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Remount Device & Recalibrate"), + }, + + EventName.calibrationIncomplete: { + ET.PERMANENT: calibration_incomplete_alert, + ET.SOFT_DISABLE: soft_disable_alert("Calibration Incomplete"), + ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"), + }, + + EventName.calibrationRecalibrating: { + ET.PERMANENT: calibration_incomplete_alert, + ET.SOFT_DISABLE: soft_disable_alert("Device Remount Detected: Recalibrating"), + ET.NO_ENTRY: NoEntryAlert("Remount Detected: Recalibrating"), + }, + + EventName.doorOpen: { + ET.SOFT_DISABLE: user_soft_disable_alert("Door Open"), + ET.NO_ENTRY: NoEntryAlert("Door Open"), + }, + + EventName.seatbeltNotLatched: { + ET.SOFT_DISABLE: user_soft_disable_alert("Seatbelt Unlatched"), + ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"), + }, + + EventName.espDisabled: { + ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Disabled"), + ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Disabled"), + }, + + EventName.lowBattery: { + ET.SOFT_DISABLE: soft_disable_alert("Low Battery"), + ET.NO_ENTRY: NoEntryAlert("Low Battery"), + }, + + # Different openpilot services communicate between each other at a certain + # interval. If communication does not follow the regular schedule this alert + # is thrown. This can mean a service crashed, did not broadcast a message for + # ten times the regular interval, or the average interval is more than 10% too high. + EventName.commIssue: { + ET.SOFT_DISABLE: soft_disable_alert("Communication Issue Between Processes"), + ET.NO_ENTRY: comm_issue_alert, + }, + EventName.commIssueAvgFreq: { + ET.SOFT_DISABLE: soft_disable_alert("Low Communication Rate Between Processes"), + ET.NO_ENTRY: NoEntryAlert("Low Communication Rate Between Processes"), + }, + + EventName.selfdrivedLagging: { + ET.SOFT_DISABLE: soft_disable_alert("System Lagging"), + ET.NO_ENTRY: NoEntryAlert("Selfdrive Process Lagging: Reboot Your Device"), + }, + + # Thrown when manager detects a service exited unexpectedly while driving + EventName.processNotRunning: { + ET.NO_ENTRY: process_not_running_alert, + ET.SOFT_DISABLE: soft_disable_alert("Process Not Running"), + }, + + EventName.radarFault: { + ET.SOFT_DISABLE: soft_disable_alert("Radar Error: Restart the Car"), + ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"), + }, + + EventName.radarTempUnavailable: { + ET.SOFT_DISABLE: soft_disable_alert("Radar Temporarily Unavailable"), + ET.NO_ENTRY: NoEntryAlert("Radar Temporarily Unavailable"), + }, + + # Every frame from the camera should be processed by the model. If modeld + # is not processing frames fast enough they have to be dropped. This alert is + # thrown when over 20% of frames are dropped. + EventName.modeldLagging: { + ET.SOFT_DISABLE: soft_disable_alert("Driving Model Lagging"), + ET.NO_ENTRY: NoEntryAlert("Driving Model Lagging"), + ET.PERMANENT: modeld_lagging_alert, + }, + + # Besides predicting the path, lane lines and lead car data the model also + # predicts the current velocity and rotation speed of the car. If the model is + # very uncertain about the current velocity while the car is moving, this + # usually means the model has trouble understanding the scene. This is used + # as a heuristic to warn the driver. + EventName.posenetInvalid: { + ET.SOFT_DISABLE: soft_disable_alert("Posenet Speed Invalid"), + ET.NO_ENTRY: posenet_invalid_alert, + }, + + # When the localizer detects an acceleration of more than 40 m/s^2 (~4G) we + # alert the driver the device might have fallen from the windshield. + EventName.deviceFalling: { + ET.SOFT_DISABLE: soft_disable_alert("Device Fell Off Mount"), + ET.NO_ENTRY: NoEntryAlert("Device Fell Off Mount"), + }, + + EventName.lowMemory: { + ET.SOFT_DISABLE: soft_disable_alert("Low Memory: Reboot Your Device"), + ET.PERMANENT: low_memory_alert, + ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"), + }, + + EventName.accFaulted: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Cruise Fault: Restart the Car"), + ET.PERMANENT: NormalPermanentAlert("Cruise Fault: Restart the car to engage"), + ET.NO_ENTRY: NoEntryAlert("Cruise Fault: Restart the Car"), + }, + + EventName.espActive: { + ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Active"), + ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Active"), + }, + + EventName.controlsMismatch: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Controls Mismatch"), + ET.NO_ENTRY: NoEntryAlert("Controls Mismatch"), + }, + + # Sometimes the USB stack on the device can get into a bad state + # causing the connection to the panda to be lost + EventName.usbError: { + ET.SOFT_DISABLE: soft_disable_alert("USB Error: Reboot Your Device"), + ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device"), + ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"), + }, + + # This alert can be thrown for the following reasons: + # - No CAN data received at all + # - CAN data is received, but some message are not received at the right frequency + # If you're not writing a new car port, this is usually cause by faulty wiring + EventName.canError: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Error"), + ET.PERMANENT: Alert( + "CAN Error: Check Connections", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.), + ET.NO_ENTRY: NoEntryAlert("CAN Error: Check Connections"), + }, + + EventName.canBusMissing: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Bus Disconnected"), + ET.PERMANENT: Alert( + "CAN Bus Disconnected: Likely Faulty Cable", + "", + AlertStatus.normal, AlertSize.small, + Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.), + ET.NO_ENTRY: NoEntryAlert("CAN Bus Disconnected: Check Connections"), + }, + + EventName.steerUnavailable: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS Fault: Restart the Car"), + ET.PERMANENT: NormalPermanentAlert("LKAS Fault: Restart the car to engage"), + ET.NO_ENTRY: NoEntryAlert("LKAS Fault: Restart the Car"), + }, + + EventName.reverseGear: { + ET.PERMANENT: Alert( + "Reverse\nGear", + "", + AlertStatus.normal, AlertSize.full, + Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2, creation_delay=0.5), + ET.USER_DISABLE: ImmediateDisableAlert("Reverse Gear"), + ET.NO_ENTRY: NoEntryAlert("Reverse Gear"), + }, + + # On cars that use stock ACC the car can decide to cancel ACC for various reasons. + # When this happens we can no long control the car so the user needs to be warned immediately. + EventName.cruiseDisabled: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Cruise Is Off"), + }, + + # When the relay in the harness box opens the CAN bus between the LKAS camera + # and the rest of the car is separated. When messages from the LKAS camera + # are received on the car side this usually means the relay hasn't opened correctly + # and this alert is thrown. + EventName.relayMalfunction: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Harness Relay Malfunction"), + ET.PERMANENT: NormalPermanentAlert("Harness Relay Malfunction", "Check Hardware"), + ET.NO_ENTRY: NoEntryAlert("Harness Relay Malfunction"), + }, + + EventName.speedTooLow: { + ET.IMMEDIATE_DISABLE: Alert( + "openpilot Canceled", + "Speed too low", + AlertStatus.normal, AlertSize.mid, + Priority.HIGH, VisualAlert.none, AudibleAlert.disengage, 3.), + }, + + # When the car is driving faster than most cars in the training data, the model outputs can be unpredictable. + EventName.speedTooHigh: { + ET.WARNING: Alert( + "Speed Too High", + "Model uncertain at this speed", + AlertStatus.userPrompt, AlertSize.mid, + Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.promptRepeat, 4.), + ET.NO_ENTRY: NoEntryAlert("Slow down to engage"), + }, + + EventName.vehicleSensorsInvalid: { + ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("Vehicle Sensors Invalid"), + ET.PERMANENT: NormalPermanentAlert("Vehicle Sensors Calibrating", "Drive to Calibrate"), + ET.NO_ENTRY: NoEntryAlert("Vehicle Sensors Calibrating"), + }, + + EventName.personalityChanged: { + ET.WARNING: personality_changed_alert, + }, + + EventName.userBookmark: { + ET.PERMANENT: NormalPermanentAlert("Bookmark Saved", duration=1.5), + }, + + EventName.audioFeedback: { + ET.PERMANENT: audio_feedback_alert, + }, +} + + +if __name__ == '__main__': + # print all alerts by type and priority + from cereal.services import SERVICE_LIST + from collections import defaultdict + + event_names = {v: k for k, v in EventName.schema.enumerants.items()} + alerts_by_type: dict[str, dict[Priority, list[str]]] = defaultdict(lambda: defaultdict(list)) + + CP = car.CarParams.new_message() + CS = car.CarState.new_message() + sm = messaging.SubMaster(list(SERVICE_LIST.keys())) + + for i, alerts in EVENTS.items(): + for et, alert in alerts.items(): + if callable(alert): + alert = alert(CP, CS, sm, False, 1, log.LongitudinalPersonality.standard) + alerts_by_type[et][alert.priority].append(event_names[i]) + + all_alerts: dict[str, list[tuple[Priority, list[str]]]] = {} + for et, priority_alerts in alerts_by_type.items(): + all_alerts[et] = sorted(priority_alerts.items(), key=lambda x: x[0], reverse=True) + + for status, evs in sorted(all_alerts.items(), key=lambda x: x[0]): + print(f"**** {status} ****") + for p, alert_list in evs: + print(f" {repr(p)}:") + print(" ", ', '.join(alert_list), "\n") diff --git a/selfdrive/selfdrived/helpers.py b/selfdrive/selfdrived/helpers.py new file mode 100644 index 0000000000..f7468cbe43 --- /dev/null +++ b/selfdrive/selfdrived/helpers.py @@ -0,0 +1,54 @@ +import math +from enum import StrEnum, auto + +from cereal import car, messaging +from openpilot.common.realtime import DT_CTRL +from openpilot.selfdrive.locationd.helpers import Pose +from opendbc.car import ACCELERATION_DUE_TO_GRAVITY +from opendbc.car.lateral import ISO_LATERAL_ACCEL +from opendbc.car.interfaces import ACCEL_MIN, ACCEL_MAX + +MIN_EXCESSIVE_ACTUATION_COUNT = int(0.25 / DT_CTRL) +MIN_LATERAL_ENGAGE_BUFFER = int(1 / DT_CTRL) + + +class ExcessiveActuationType(StrEnum): + LONGITUDINAL = auto() + LATERAL = auto() + + +class ExcessiveActuationCheck: + def __init__(self): + self._excessive_counter = 0 + self._engaged_counter = 0 + + def update(self, sm: messaging.SubMaster, CS: car.CarState, calibrated_pose: Pose) -> ExcessiveActuationType | None: + # CS.aEgo can be noisy to bumps in the road, transitioning from standstill, losing traction, etc. + # longitudinal + accel_calibrated = calibrated_pose.acceleration.x + excessive_long_actuation = sm['carControl'].longActive and (accel_calibrated > ACCEL_MAX * 2 or accel_calibrated < ACCEL_MIN * 2) + + # lateral + yaw_rate = calibrated_pose.angular_velocity.yaw + roll = sm['liveParameters'].roll + roll_compensated_lateral_accel = (CS.vEgo * yaw_rate) - (math.sin(roll) * ACCELERATION_DUE_TO_GRAVITY) + + # Prevent false positives after overriding + excessive_lat_actuation = False + self._engaged_counter = self._engaged_counter + 1 if sm['carControl'].latActive and not CS.steeringPressed else 0 + if self._engaged_counter > MIN_LATERAL_ENGAGE_BUFFER: + if abs(roll_compensated_lateral_accel) > ISO_LATERAL_ACCEL * 2: + excessive_lat_actuation = True + + # livePose acceleration can be noisy due to bad mounting or aliased livePose measurements + livepose_valid = abs(CS.aEgo - accel_calibrated) < 2 + self._excessive_counter = self._excessive_counter + 1 if livepose_valid and (excessive_long_actuation or excessive_lat_actuation) else 0 + + excessive_type = None + if self._excessive_counter > MIN_EXCESSIVE_ACTUATION_COUNT: + if excessive_long_actuation: + excessive_type = ExcessiveActuationType.LONGITUDINAL + else: + excessive_type = ExcessiveActuationType.LATERAL + + return excessive_type diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py new file mode 100755 index 0000000000..e9c62fe327 --- /dev/null +++ b/selfdrive/selfdrived/selfdrived.py @@ -0,0 +1,530 @@ +#!/usr/bin/env python3 +import os +import time +import threading + +import cereal.messaging as messaging + +from cereal import car, log +from msgq.visionipc import VisionIpcClient, VisionStreamType + + +from openpilot.common.params import Params +from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL +from openpilot.common.swaglog import cloudlog +from openpilot.common.gps import get_gps_location_service + +from openpilot.selfdrive.car.car_specific import CarSpecificEvents +from openpilot.selfdrive.locationd.helpers import PoseCalibrator, Pose +from openpilot.selfdrive.selfdrived.events import Events, ET +from openpilot.selfdrive.selfdrived.helpers import ExcessiveActuationCheck +from openpilot.selfdrive.selfdrived.state import StateMachine +from openpilot.selfdrive.selfdrived.alertmanager import AlertManager, set_offroad_alert + +from openpilot.system.version import get_build_metadata + +REPLAY = "REPLAY" in os.environ +SIMULATION = "SIMULATION" in os.environ +TESTING_CLOSET = "TESTING_CLOSET" in os.environ + +LONGITUDINAL_PERSONALITY_MAP = {v: k for k, v in log.LongitudinalPersonality.schema.enumerants.items()} + +ThermalStatus = log.DeviceState.ThermalStatus +State = log.SelfdriveState.OpenpilotState +PandaType = log.PandaState.PandaType +LaneChangeState = log.LaneChangeState +LaneChangeDirection = log.LaneChangeDirection +EventName = log.OnroadEvent.EventName +ButtonType = car.CarState.ButtonEvent.Type +SafetyModel = car.CarParams.SafetyModel + +IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput) + + +class SelfdriveD: + def __init__(self, CP=None): + self.params = Params() + + # Ensure the current branch is cached, otherwise the first cycle lags + build_metadata = get_build_metadata() + + if CP is None: + cloudlog.info("selfdrived is waiting for CarParams") + self.CP = messaging.log_from_bytes(self.params.get("CarParams", block=True), car.CarParams) + cloudlog.info("selfdrived got CarParams") + else: + self.CP = CP + + self.car_events = CarSpecificEvents(self.CP) + + self.pose_calibrator = PoseCalibrator() + self.calibrated_pose: Pose | None = None + self.excessive_actuation_check = ExcessiveActuationCheck() + self.excessive_actuation = self.params.get("Offroad_ExcessiveActuation") is not None + + # Setup sockets + self.pm = messaging.PubMaster(['selfdriveState', 'onroadEvents']) + + self.gps_location_service = get_gps_location_service(self.params) + self.gps_packets = [self.gps_location_service] + self.sensor_packets = ["accelerometer", "gyroscope"] + self.camera_packets = ["roadCameraState", "driverCameraState", "wideRoadCameraState"] + + # TODO: de-couple selfdrived with card/conflate on carState without introducing controls mismatches + self.car_state_sock = messaging.sub_sock('carState', timeout=20) + + ignore = self.sensor_packets + self.gps_packets + ['alertDebug'] + if SIMULATION: + ignore += ['driverCameraState', 'managerState'] + if REPLAY: + # no vipc in replay will make them ignored anyways + ignore += ['roadCameraState', 'wideRoadCameraState'] + self.sm = messaging.SubMaster(['deviceState', 'pandaStates', 'peripheralState', 'modelV2', 'liveCalibration', + 'carOutput', 'driverMonitoringState', 'longitudinalPlan', 'livePose', 'liveDelay', + 'managerState', 'liveParameters', 'radarState', 'liveTorqueParameters', + 'controlsState', 'carControl', 'driverAssistance', 'alertDebug', 'userBookmark', 'audioFeedback'] + \ + self.camera_packets + self.sensor_packets + self.gps_packets, + ignore_alive=ignore, ignore_avg_freq=ignore, + ignore_valid=ignore, frequency=int(1/DT_CTRL)) + + # read params + self.is_metric = self.params.get_bool("IsMetric") + self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled") + self.disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator") + + car_recognized = self.CP.brand != 'mock' + + # cleanup old params + if not self.CP.alphaLongitudinalAvailable: + self.params.remove("AlphaLongitudinalEnabled") + if not self.CP.openpilotLongitudinalControl: + self.params.remove("ExperimentalMode") + + self.CS_prev = car.CarState.new_message() + self.AM = AlertManager() + self.events = Events() + + self.initialized = False + self.enabled = False + self.active = False + self.mismatch_counter = 0 + self.cruise_mismatch_counter = 0 + self.last_steering_pressed_frame = 0 + self.distance_traveled = 0 + self.last_functional_fan_frame = 0 + self.events_prev = [] + self.logged_comm_issue = None + self.not_running_prev = None + self.experimental_mode = False + self.personality = self.params.get("LongitudinalPersonality", return_default=True) + self.recalibrating_seen = False + self.state_machine = StateMachine() + self.rk = Ratekeeper(100, print_delay_threshold=None) + + # Determine startup event + self.startup_event = EventName.startup if build_metadata.openpilot.comma_remote and build_metadata.tested_channel else EventName.startupMaster + if not car_recognized: + self.startup_event = EventName.startupNoCar + elif car_recognized and self.CP.passive: + self.startup_event = EventName.startupNoControl + elif self.CP.secOcRequired and not self.CP.secOcKeyAvailable: + self.startup_event = EventName.startupNoSecOcKey + + if not car_recognized: + self.events.add(EventName.carUnrecognized, static=True) + set_offroad_alert("Offroad_CarUnrecognized", True) + elif self.CP.passive: + self.events.add(EventName.dashcamMode, static=True) + + def update_events(self, CS): + """Compute onroadEvents from carState""" + + self.events.clear() + + if self.sm['controlsState'].lateralControlState.which() == 'debugState': + self.events.add(EventName.joystickDebug) + self.startup_event = None + + if self.sm.recv_frame['alertDebug'] > 0: + self.events.add(EventName.longitudinalManeuver) + self.startup_event = None + + # Add startup event + if self.startup_event is not None: + self.events.add(self.startup_event) + self.startup_event = None + + # Don't add any more events if not initialized + if not self.initialized: + self.events.add(EventName.selfdriveInitializing) + return + + # Check for user bookmark press (bookmark button or end of LKAS button feedback) + if self.sm.updated['userBookmark']: + self.events.add(EventName.userBookmark) + + if self.sm.updated['audioFeedback']: + self.events.add(EventName.audioFeedback) + + # Don't add any more events while in dashcam mode + if self.CP.passive: + return + + # Block resume if cruise never previously enabled + resume_pressed = any(be.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for be in CS.buttonEvents) + if not self.CP.pcmCruise and CS.vCruise > 250 and resume_pressed: + self.events.add(EventName.resumeBlocked) + + if not self.CP.notCar: + self.events.add_from_msg(self.sm['driverMonitoringState'].events) + + # Add car events, ignore if CAN isn't valid + if CS.canValid: + car_events = self.car_events.update(CS, self.CS_prev, self.sm['carControl']).to_msg() + self.events.add_from_msg(car_events) + + if self.CP.notCar: + # wait for everything to init first + if self.sm.frame > int(5. / DT_CTRL) and self.initialized: + # body always wants to enable + self.events.add(EventName.pcmEnable) + + # Disable on rising edge of accelerator or brake. Also disable on brake when speed > 0 + if (CS.gasPressed and not self.CS_prev.gasPressed and self.disengage_on_accelerator) or \ + (CS.brakePressed and (not self.CS_prev.brakePressed or not CS.standstill)) or \ + (CS.regenBraking and (not self.CS_prev.regenBraking or not CS.standstill)): + self.events.add(EventName.pedalPressed) + + # Create events for temperature, disk space, and memory + if self.sm['deviceState'].thermalStatus >= ThermalStatus.red: + self.events.add(EventName.overheat) + if self.sm['deviceState'].freeSpacePercent < 7 and not SIMULATION: + self.events.add(EventName.outOfSpace) + if self.sm['deviceState'].memoryUsagePercent > 90 and not SIMULATION: + self.events.add(EventName.lowMemory) + + # Alert if fan isn't spinning for 5 seconds + if self.sm['peripheralState'].pandaType != log.PandaState.PandaType.unknown: + if self.sm['peripheralState'].fanSpeedRpm < 500 and self.sm['deviceState'].fanSpeedPercentDesired > 50: + # allow enough time for the fan controller in the panda to recover from stalls + if (self.sm.frame - self.last_functional_fan_frame) * DT_CTRL > 15.0: + self.events.add(EventName.fanMalfunction) + else: + self.last_functional_fan_frame = self.sm.frame + + # Handle calibration status + cal_status = self.sm['liveCalibration'].calStatus + if cal_status != log.LiveCalibrationData.Status.calibrated: + if cal_status == log.LiveCalibrationData.Status.uncalibrated: + self.events.add(EventName.calibrationIncomplete) + elif cal_status == log.LiveCalibrationData.Status.recalibrating: + if not self.recalibrating_seen: + set_offroad_alert("Offroad_Recalibration", True) + self.recalibrating_seen = True + self.events.add(EventName.calibrationRecalibrating) + else: + self.events.add(EventName.calibrationInvalid) + + # Lane departure warning + if self.is_ldw_enabled and self.sm.valid['driverAssistance']: + if self.sm['driverAssistance'].leftLaneDeparture or self.sm['driverAssistance'].rightLaneDeparture: + self.events.add(EventName.ldw) + + # ****************************************************************************************** + # NOTE: To fork maintainers. + # Disabling or nerfing safety features will get you and your users banned from our servers. + # We recommend that you do not change these numbers from the defaults. + if self.sm.updated['liveCalibration']: + self.pose_calibrator.feed_live_calib(self.sm['liveCalibration']) + if self.sm.updated['livePose']: + device_pose = Pose.from_live_pose(self.sm['livePose']) + self.calibrated_pose = self.pose_calibrator.build_calibrated_pose(device_pose) + + if self.calibrated_pose is not None: + excessive_actuation = self.excessive_actuation_check.update(self.sm, CS, self.calibrated_pose) + if not self.excessive_actuation and excessive_actuation is not None: + set_offroad_alert("Offroad_ExcessiveActuation", True, extra_text=str(excessive_actuation)) + self.excessive_actuation = True + + if self.excessive_actuation: + self.events.add(EventName.excessiveActuation) + # ****************************************************************************************** + + # Handle lane change + if self.sm['modelV2'].meta.laneChangeState == LaneChangeState.preLaneChange: + direction = self.sm['modelV2'].meta.laneChangeDirection + if (CS.leftBlindspot and direction == LaneChangeDirection.left) or \ + (CS.rightBlindspot and direction == LaneChangeDirection.right): + self.events.add(EventName.laneChangeBlocked) + else: + if direction == LaneChangeDirection.left: + self.events.add(EventName.preLaneChangeLeft) + else: + self.events.add(EventName.preLaneChangeRight) + elif self.sm['modelV2'].meta.laneChangeState in (LaneChangeState.laneChangeStarting, + LaneChangeState.laneChangeFinishing): + self.events.add(EventName.laneChange) + + for i, pandaState in enumerate(self.sm['pandaStates']): + # All pandas must match the list of safetyConfigs, and if outside this list, must be silent or noOutput + if i < len(self.CP.safetyConfigs): + safety_mismatch = pandaState.safetyModel != self.CP.safetyConfigs[i].safetyModel or \ + pandaState.safetyParam != self.CP.safetyConfigs[i].safetyParam or \ + pandaState.alternativeExperience != self.CP.alternativeExperience + else: + safety_mismatch = pandaState.safetyModel not in IGNORED_SAFETY_MODES + + # safety mismatch allows some time for pandad to set the safety mode and publish it back from panda + if (safety_mismatch and self.sm.frame*DT_CTRL > 10.) or pandaState.safetyRxChecksInvalid or self.mismatch_counter >= 200: + self.events.add(EventName.controlsMismatch) + + if log.PandaState.FaultType.relayMalfunction in pandaState.faults: + self.events.add(EventName.relayMalfunction) + + # Handle HW and system malfunctions + # Order is very intentional here. Be careful when modifying this. + # All events here should at least have NO_ENTRY and SOFT_DISABLE. + num_events = len(self.events) + + not_running = {p.name for p in self.sm['managerState'].processes if not p.running and p.shouldBeRunning} + if self.sm.recv_frame['managerState'] and len(not_running): + if not_running != self.not_running_prev: + cloudlog.event("process_not_running", not_running=not_running, error=True) + self.not_running_prev = not_running + if self.sm.recv_frame['managerState'] and not_running: + self.events.add(EventName.processNotRunning) + else: + if not SIMULATION and not self.rk.lagging: + if not self.sm.all_alive(self.camera_packets): + self.events.add(EventName.cameraMalfunction) + elif not self.sm.all_freq_ok(self.camera_packets): + self.events.add(EventName.cameraFrameRate) + if not REPLAY and self.rk.lagging: + self.events.add(EventName.selfdrivedLagging) + if self.sm['radarState'].radarErrors.canError: + self.events.add(EventName.canError) + elif self.sm['radarState'].radarErrors.radarUnavailableTemporary: + self.events.add(EventName.radarTempUnavailable) + elif any(self.sm['radarState'].radarErrors.to_dict().values()): + self.events.add(EventName.radarFault) + if not self.sm.valid['pandaStates']: + self.events.add(EventName.usbError) + if CS.canTimeout: + self.events.add(EventName.canBusMissing) + elif not CS.canValid: + self.events.add(EventName.canError) + + # generic catch-all. ideally, a more specific event should be added above instead + has_disable_events = self.events.contains(ET.NO_ENTRY) and (self.events.contains(ET.SOFT_DISABLE) or self.events.contains(ET.IMMEDIATE_DISABLE)) + no_system_errors = (not has_disable_events) or (len(self.events) == num_events) + if not self.sm.all_checks() and no_system_errors: + if not self.sm.all_alive(): + self.events.add(EventName.commIssue) + elif not self.sm.all_freq_ok(): + self.events.add(EventName.commIssueAvgFreq) + else: + self.events.add(EventName.commIssue) + + logs = { + 'invalid': [s for s, valid in self.sm.valid.items() if not valid], + 'not_alive': [s for s, alive in self.sm.alive.items() if not alive], + 'not_freq_ok': [s for s, freq_ok in self.sm.freq_ok.items() if not freq_ok], + } + if logs != self.logged_comm_issue: + cloudlog.event("commIssue", error=True, **logs) + self.logged_comm_issue = logs + else: + self.logged_comm_issue = None + + if not self.CP.notCar: + if not self.sm['livePose'].posenetOK: + self.events.add(EventName.posenetInvalid) + if not self.sm['livePose'].inputsOK: + self.events.add(EventName.locationdTemporaryError) + if not self.sm['liveParameters'].valid and cal_status == log.LiveCalibrationData.Status.calibrated and not TESTING_CLOSET and (not SIMULATION or REPLAY): + self.events.add(EventName.paramsdTemporaryError) + + # conservative HW alert. if the data or frequency are off, locationd will throw an error + if any((self.sm.frame - self.sm.recv_frame[s])*DT_CTRL > 10. for s in self.sensor_packets): + self.events.add(EventName.sensorDataInvalid) + + if not REPLAY: + # Check for mismatch between openpilot and car's PCM + cruise_mismatch = CS.cruiseState.enabled and (not self.enabled or not self.CP.pcmCruise) + self.cruise_mismatch_counter = self.cruise_mismatch_counter + 1 if cruise_mismatch else 0 + if self.cruise_mismatch_counter > int(6. / DT_CTRL): + self.events.add(EventName.cruiseMismatch) + + # Send a "steering required alert" if saturation count has reached the limit + if CS.steeringPressed: + self.last_steering_pressed_frame = self.sm.frame + recent_steer_pressed = (self.sm.frame - self.last_steering_pressed_frame)*DT_CTRL < 2.0 + controlstate = self.sm['controlsState'] + lac = getattr(controlstate.lateralControlState, controlstate.lateralControlState.which()) + if lac.active and not recent_steer_pressed and not self.CP.notCar: + clipped_speed = max(CS.vEgo, 0.3) + actual_lateral_accel = controlstate.curvature * (clipped_speed**2) + desired_lateral_accel = self.sm['modelV2'].action.desiredCurvature * (clipped_speed**2) + undershooting = abs(desired_lateral_accel) / abs(1e-3 + actual_lateral_accel) > 1.2 + turning = abs(desired_lateral_accel) > 1.0 + # TODO: lac.saturated includes speed and other checks, should be pulled out + if undershooting and turning and lac.saturated: + self.events.add(EventName.steerSaturated) + + # Check for FCW + stock_long_is_braking = self.enabled and not self.CP.openpilotLongitudinalControl and CS.aEgo < -1.25 + model_fcw = self.sm['modelV2'].meta.hardBrakePredicted and not CS.brakePressed and not stock_long_is_braking + planner_fcw = self.sm['longitudinalPlan'].fcw and self.enabled + if (planner_fcw or model_fcw) and not self.CP.notCar: + self.events.add(EventName.fcw) + + # GPS checks + gps_ok = self.sm.recv_frame[self.gps_location_service] > 0 and (self.sm.frame - self.sm.recv_frame[self.gps_location_service]) * DT_CTRL < 2.0 + if not gps_ok and self.sm['livePose'].inputsOK and (self.distance_traveled > 1500): + self.events.add(EventName.noGps) + if gps_ok: + self.distance_traveled = 0 + self.distance_traveled += abs(CS.vEgo) * DT_CTRL + + # TODO: fix simulator + if not SIMULATION or REPLAY: + if self.sm['modelV2'].frameDropPerc > 20: + self.events.add(EventName.modeldLagging) + + # Decrement personality on distance button press + if self.CP.openpilotLongitudinalControl: + if any(not be.pressed and be.type == ButtonType.gapAdjustCruise for be in CS.buttonEvents): + self.personality = (self.personality - 1) % 3 + self.params.put_nonblocking('LongitudinalPersonality', self.personality) + self.events.add(EventName.personalityChanged) + + def data_sample(self): + _car_state = messaging.recv_one(self.car_state_sock) + CS = _car_state.carState if _car_state else self.CS_prev + + self.sm.update(0) + + if not self.initialized: + all_valid = CS.canValid and self.sm.all_checks() + timed_out = self.sm.frame * DT_CTRL > 6. + if all_valid or timed_out or (SIMULATION and not REPLAY): + available_streams = VisionIpcClient.available_streams("camerad", block=False) + if VisionStreamType.VISION_STREAM_ROAD not in available_streams: + self.sm.ignore_alive.append('roadCameraState') + self.sm.ignore_valid.append('roadCameraState') + if VisionStreamType.VISION_STREAM_WIDE_ROAD not in available_streams: + self.sm.ignore_alive.append('wideRoadCameraState') + self.sm.ignore_valid.append('wideRoadCameraState') + + if REPLAY and any(ps.controlsAllowed for ps in self.sm['pandaStates']): + self.state_machine.state = State.enabled + + self.initialized = True + cloudlog.event( + "selfdrived.initialized", + dt=self.sm.frame*DT_CTRL, + timeout=timed_out, + canValid=CS.canValid, + invalid=[s for s, valid in self.sm.valid.items() if not valid], + not_alive=[s for s, alive in self.sm.alive.items() if not alive], + not_freq_ok=[s for s, freq_ok in self.sm.freq_ok.items() if not freq_ok], + error=True, + ) + + # When the panda and selfdrived do not agree on controls_allowed + # we want to disengage openpilot. However the status from the panda goes through + # another socket other than the CAN messages and one can arrive earlier than the other. + # Therefore we allow a mismatch for two samples, then we trigger the disengagement. + if not self.enabled: + self.mismatch_counter = 0 + + # All pandas not in silent mode must have controlsAllowed when openpilot is enabled + if self.enabled and any(not ps.controlsAllowed for ps in self.sm['pandaStates'] + if ps.safetyModel not in IGNORED_SAFETY_MODES): + self.mismatch_counter += 1 + + return CS + + def update_alerts(self, CS): + clear_event_types = set() + if ET.WARNING not in self.state_machine.current_alert_types: + clear_event_types.add(ET.WARNING) + if self.enabled: + clear_event_types.add(ET.NO_ENTRY) + + pers = LONGITUDINAL_PERSONALITY_MAP[self.personality] + alerts = self.events.create_alerts(self.state_machine.current_alert_types, [self.CP, CS, self.sm, self.is_metric, + self.state_machine.soft_disable_timer, pers]) + self.AM.add_many(self.sm.frame, alerts) + self.AM.process_alerts(self.sm.frame, clear_event_types) + + def publish_selfdriveState(self, CS): + # selfdriveState + ss_msg = messaging.new_message('selfdriveState') + ss_msg.valid = True + ss = ss_msg.selfdriveState + ss.enabled = self.enabled + ss.active = self.active + ss.state = self.state_machine.state + ss.engageable = not self.events.contains(ET.NO_ENTRY) + ss.experimentalMode = self.experimental_mode + ss.personality = self.personality + + ss.alertText1 = self.AM.current_alert.alert_text_1 + ss.alertText2 = self.AM.current_alert.alert_text_2 + ss.alertSize = self.AM.current_alert.alert_size + ss.alertStatus = self.AM.current_alert.alert_status + ss.alertType = self.AM.current_alert.alert_type + ss.alertSound = self.AM.current_alert.audible_alert + ss.alertHudVisual = self.AM.current_alert.visual_alert + + self.pm.send('selfdriveState', ss_msg) + + # onroadEvents - logged every second or on change + if (self.sm.frame % int(1. / DT_CTRL) == 0) or (self.events.names != self.events_prev): + ce_send = messaging.new_message('onroadEvents', len(self.events)) + ce_send.valid = True + ce_send.onroadEvents = self.events.to_msg() + self.pm.send('onroadEvents', ce_send) + self.events_prev = self.events.names.copy() + + def step(self): + CS = self.data_sample() + self.update_events(CS) + if not self.CP.passive and self.initialized: + self.enabled, self.active = self.state_machine.update(self.events) + self.update_alerts(CS) + + self.publish_selfdriveState(CS) + + self.CS_prev = CS + + def params_thread(self, evt): + while not evt.is_set(): + self.is_metric = self.params.get_bool("IsMetric") + self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled") + self.disengage_on_accelerator = self.params.get_bool("DisengageOnAccelerator") + self.experimental_mode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl + self.personality = self.params.get("LongitudinalPersonality", return_default=True) + time.sleep(0.1) + + def run(self): + e = threading.Event() + t = threading.Thread(target=self.params_thread, args=(e, )) + try: + t.start() + while True: + self.step() + self.rk.monitor_time() + finally: + e.set() + t.join() + + +def main(): + config_realtime_process(4, Priority.CTRL_HIGH) + s = SelfdriveD() + s.run() + +if __name__ == "__main__": + main() diff --git a/selfdrive/selfdrived/state.py b/selfdrive/selfdrived/state.py new file mode 100644 index 0000000000..073ddb56eb --- /dev/null +++ b/selfdrive/selfdrived/state.py @@ -0,0 +1,98 @@ +from cereal import log +from openpilot.selfdrive.selfdrived.events import Events, ET +from openpilot.common.realtime import DT_CTRL + +State = log.SelfdriveState.OpenpilotState + +SOFT_DISABLE_TIME = 3 # seconds +ACTIVE_STATES = (State.enabled, State.softDisabling, State.overriding) +ENABLED_STATES = (State.preEnabled, *ACTIVE_STATES) + +class StateMachine: + def __init__(self): + self.current_alert_types = [ET.PERMANENT] + self.state = State.disabled + self.soft_disable_timer = 0 + + def update(self, events: Events): + # decrement the soft disable timer at every step, as it's reset on + # entrance in SOFT_DISABLING state + self.soft_disable_timer = max(0, self.soft_disable_timer - 1) + + self.current_alert_types = [ET.PERMANENT] + + # ENABLED, SOFT DISABLING, PRE ENABLING, OVERRIDING + if self.state != State.disabled: + # user and immediate disable always have priority in a non-disabled state + if events.contains(ET.USER_DISABLE): + self.state = State.disabled + self.current_alert_types.append(ET.USER_DISABLE) + + elif events.contains(ET.IMMEDIATE_DISABLE): + self.state = State.disabled + self.current_alert_types.append(ET.IMMEDIATE_DISABLE) + + else: + # ENABLED + if self.state == State.enabled: + if events.contains(ET.SOFT_DISABLE): + self.state = State.softDisabling + self.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL) + self.current_alert_types.append(ET.SOFT_DISABLE) + + elif events.contains(ET.OVERRIDE_LATERAL) or events.contains(ET.OVERRIDE_LONGITUDINAL): + self.state = State.overriding + self.current_alert_types += [ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL] + + # SOFT DISABLING + elif self.state == State.softDisabling: + if not events.contains(ET.SOFT_DISABLE): + # no more soft disabling condition, so go back to ENABLED + self.state = State.enabled + + elif self.soft_disable_timer > 0: + self.current_alert_types.append(ET.SOFT_DISABLE) + + elif self.soft_disable_timer <= 0: + self.state = State.disabled + + # PRE ENABLING + elif self.state == State.preEnabled: + if not events.contains(ET.PRE_ENABLE): + self.state = State.enabled + else: + self.current_alert_types.append(ET.PRE_ENABLE) + + # OVERRIDING + elif self.state == State.overriding: + if events.contains(ET.SOFT_DISABLE): + self.state = State.softDisabling + self.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL) + self.current_alert_types.append(ET.SOFT_DISABLE) + elif not (events.contains(ET.OVERRIDE_LATERAL) or events.contains(ET.OVERRIDE_LONGITUDINAL)): + self.state = State.enabled + else: + self.current_alert_types += [ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL] + + # DISABLED + elif self.state == State.disabled: + if events.contains(ET.ENABLE): + if events.contains(ET.NO_ENTRY): + self.current_alert_types.append(ET.NO_ENTRY) + + else: + if events.contains(ET.PRE_ENABLE): + self.state = State.preEnabled + elif events.contains(ET.OVERRIDE_LATERAL) or events.contains(ET.OVERRIDE_LONGITUDINAL): + self.state = State.overriding + else: + self.state = State.enabled + self.current_alert_types.append(ET.ENABLE) + + # Check if openpilot is engaged and actuators are enabled + enabled = self.state in ENABLED_STATES + active = self.state in ACTIVE_STATES + if active: + self.current_alert_types.append(ET.WARNING) + return enabled, active + diff --git a/selfdrive/selfdrived/tests/test_alertmanager.py b/selfdrive/selfdrived/tests/test_alertmanager.py new file mode 100644 index 0000000000..030b7d4515 --- /dev/null +++ b/selfdrive/selfdrived/tests/test_alertmanager.py @@ -0,0 +1,58 @@ +import random + +from openpilot.selfdrive.selfdrived.events import Alert, EmptyAlert, EVENTS +from openpilot.selfdrive.selfdrived.alertmanager import AlertManager + + +class TestAlertManager: + + def test_duration(self): + """ + Enforce that an alert lasts for max(alert duration, duration the alert is added) + """ + for duration in range(1, 100): + alert = None + while not isinstance(alert, Alert): + event = random.choice([e for e in EVENTS.values() if len(e)]) + alert = random.choice(list(event.values())) + + alert.duration = duration + + # check two cases: + # - alert is added to AM for <= the alert's duration + # - alert is added to AM for > alert's duration + for greater in (True, False): + if greater: + add_duration = duration + random.randint(1, 10) + else: + add_duration = random.randint(1, duration) + show_duration = max(duration, add_duration) + + AM = AlertManager() + for frame in range(duration+10): + if frame < add_duration: + AM.add_many(frame, [alert, ]) + AM.process_alerts(frame, set()) + + shown = AM.current_alert != EmptyAlert + should_show = frame <= show_duration + assert shown == should_show, f"{frame=} {add_duration=} {duration=}" + + # check one case: + # - if alert is re-added to AM before it ends the duration is extended + if duration > 1: + AM = AlertManager() + show_duration = duration * 2 + for frame in range(duration * 2 + 10): + if frame == 0: + AM.add_many(frame, [alert, ]) + + if frame == duration: + # add alert one frame before it ends + assert AM.current_alert == alert + AM.add_many(frame, [alert, ]) + AM.process_alerts(frame, set()) + + shown = AM.current_alert != EmptyAlert + should_show = frame <= show_duration + assert shown == should_show, f"{frame=} {duration=}" diff --git a/selfdrive/selfdrived/tests/test_alerts.py b/selfdrive/selfdrived/tests/test_alerts.py new file mode 100644 index 0000000000..c971806999 --- /dev/null +++ b/selfdrive/selfdrived/tests/test_alerts.py @@ -0,0 +1,130 @@ +import copy +import json +import os +import random +from PIL import Image, ImageDraw, ImageFont + +from cereal import log, car +from cereal.messaging import SubMaster +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.selfdrive.selfdrived.events import Alert, EVENTS, ET +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS + +AlertSize = log.SelfdriveState.AlertSize + +OFFROAD_ALERTS_PATH = os.path.join(BASEDIR, "selfdrive/selfdrived/alerts_offroad.json") + +# TODO: add callback alerts +ALERTS = [] +for event_types in EVENTS.values(): + for alert in event_types.values(): + ALERTS.append(alert) + + +class TestAlerts: + + @classmethod + def setup_class(cls): + with open(OFFROAD_ALERTS_PATH) as f: + cls.offroad_alerts = json.loads(f.read()) + + # Create fake objects for callback + cls.CS = car.CarState.new_message() + cls.CP = car.CarParams.new_message() + cfg = [c for c in CONFIGS if c.proc_name == 'selfdrived'][0] + cls.sm = SubMaster(cfg.pubs) + + def test_events_defined(self): + # Ensure all events in capnp schema are defined in events.py + events = log.OnroadEvent.EventName.schema.enumerants + + for name, e in events.items(): + if not name.endswith("DEPRECATED"): + fail_msg = f"{name} @{e} not in EVENTS" + assert e in EVENTS.keys(), fail_msg + + # ensure alert text doesn't exceed allowed width + def test_alert_text_length(self): + font_path = os.path.join(BASEDIR, "selfdrive/assets/fonts") + regular_font_path = os.path.join(font_path, "Inter-SemiBold.ttf") + bold_font_path = os.path.join(font_path, "Inter-Bold.ttf") + semibold_font_path = os.path.join(font_path, "Inter-SemiBold.ttf") + + max_text_width = 2160 - 300 # full screen width is usable, minus sidebar + draw = ImageDraw.Draw(Image.new('RGB', (0, 0))) + + fonts = { + AlertSize.small: [ImageFont.truetype(semibold_font_path, 74)], + AlertSize.mid: [ImageFont.truetype(bold_font_path, 88), + ImageFont.truetype(regular_font_path, 66)], + } + + for alert in ALERTS: + if not isinstance(alert, Alert): + alert = alert(self.CP, self.CS, self.sm, metric=False, soft_disable_time=100, personality=log.LongitudinalPersonality.standard) + + # for full size alerts, both text fields wrap the text, + # so it's unlikely that they would go past the max width + if alert.alert_size in (AlertSize.none, AlertSize.full): + continue + + for i, txt in enumerate([alert.alert_text_1, alert.alert_text_2]): + if i >= len(fonts[alert.alert_size]): + break + + font = fonts[alert.alert_size][i] + left, _, right, _ = draw.textbbox((0, 0), txt, font) + width = right - left + msg = f"type: {alert.alert_type} msg: {txt}" + assert width <= max_text_width, msg + + def test_alert_sanity_check(self): + for event_types in EVENTS.values(): + for event_type, a in event_types.items(): + # TODO: add callback alerts + if not isinstance(a, Alert): + continue + + if a.alert_size == AlertSize.none: + assert len(a.alert_text_1) == 0 + assert len(a.alert_text_2) == 0 + elif a.alert_size == AlertSize.small: + assert len(a.alert_text_1) > 0 + assert len(a.alert_text_2) == 0 + elif a.alert_size == AlertSize.mid: + assert len(a.alert_text_1) > 0 + assert len(a.alert_text_2) > 0 + else: + assert len(a.alert_text_1) > 0 + + assert a.duration >= 0. + + if event_type not in (ET.WARNING, ET.PERMANENT, ET.PRE_ENABLE): + assert a.creation_delay == 0. + + def test_offroad_alerts(self): + params = Params() + for a in self.offroad_alerts: + # set the alert + alert = copy.copy(self.offroad_alerts[a]) + set_offroad_alert(a, True) + alert['extra'] = '' + assert alert == params.get(a) + + # then delete it + set_offroad_alert(a, False) + assert params.get(a) is None + + def test_offroad_alerts_extra_text(self): + params = Params() + for i in range(50): + # set the alert + a = random.choice(list(self.offroad_alerts)) + alert = self.offroad_alerts[a] + set_offroad_alert(a, True, extra_text="a"*i) + + written_alert = params.get(a) + assert "a"*i == written_alert['extra'] + assert alert["text"] == written_alert['text'] diff --git a/selfdrive/selfdrived/tests/test_state_machine.py b/selfdrive/selfdrived/tests/test_state_machine.py new file mode 100644 index 0000000000..b720f48f1e --- /dev/null +++ b/selfdrive/selfdrived/tests/test_state_machine.py @@ -0,0 +1,92 @@ +from cereal import log +from openpilot.common.realtime import DT_CTRL +from openpilot.selfdrive.selfdrived.state import StateMachine, SOFT_DISABLE_TIME +from openpilot.selfdrive.selfdrived.events import Events, ET, EVENTS, NormalPermanentAlert + +State = log.SelfdriveState.OpenpilotState + +# The event types that maintain the current state +MAINTAIN_STATES = {State.enabled: (None,), State.disabled: (None,), State.softDisabling: (ET.SOFT_DISABLE,), + State.preEnabled: (ET.PRE_ENABLE,), State.overriding: (ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL)} +ALL_STATES = tuple(State.schema.enumerants.values()) +# The event types checked in DISABLED section of state machine +ENABLE_EVENT_TYPES = (ET.ENABLE, ET.PRE_ENABLE, ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL) + + +def make_event(event_types): + event = {} + for ev in event_types: + event[ev] = NormalPermanentAlert("alert") + EVENTS[0] = event + return 0 + + +class TestStateMachine: + def setup_method(self): + self.events = Events() + self.state_machine = StateMachine() + self.state_machine.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL) + + def test_immediate_disable(self): + for state in ALL_STATES: + for et in MAINTAIN_STATES[state]: + self.events.add(make_event([et, ET.IMMEDIATE_DISABLE])) + self.state_machine.state = state + self.state_machine.update(self.events) + assert State.disabled == self.state_machine.state + self.events.clear() + + def test_user_disable(self): + for state in ALL_STATES: + for et in MAINTAIN_STATES[state]: + self.events.add(make_event([et, ET.USER_DISABLE])) + self.state_machine.state = state + self.state_machine.update(self.events) + assert State.disabled == self.state_machine.state + self.events.clear() + + def test_soft_disable(self): + for state in ALL_STATES: + if state == State.preEnabled: # preEnabled considers NO_ENTRY instead + continue + for et in MAINTAIN_STATES[state]: + self.events.add(make_event([et, ET.SOFT_DISABLE])) + self.state_machine.state = state + self.state_machine.update(self.events) + assert self.state_machine.state == State.disabled if state == State.disabled else State.softDisabling + self.events.clear() + + def test_soft_disable_timer(self): + self.state_machine.state = State.enabled + self.events.add(make_event([ET.SOFT_DISABLE])) + self.state_machine.update(self.events) + for _ in range(int(SOFT_DISABLE_TIME / DT_CTRL)): + assert self.state_machine.state == State.softDisabling + self.state_machine.update(self.events) + + assert self.state_machine.state == State.disabled + + def test_no_entry(self): + # Make sure noEntry keeps us disabled + for et in ENABLE_EVENT_TYPES: + self.events.add(make_event([ET.NO_ENTRY, et])) + self.state_machine.update(self.events) + assert self.state_machine.state == State.disabled + self.events.clear() + + def test_no_entry_pre_enable(self): + # preEnabled with noEntry event + self.state_machine.state = State.preEnabled + self.events.add(make_event([ET.NO_ENTRY, ET.PRE_ENABLE])) + self.state_machine.update(self.events) + assert self.state_machine.state == State.preEnabled + + def test_maintain_states(self): + # Given current state's event type, we should maintain state + for state in ALL_STATES: + for et in MAINTAIN_STATES[state]: + self.state_machine.state = state + self.events.add(make_event([et])) + self.state_machine.update(self.events) + assert self.state_machine.state == state + self.events.clear() diff --git a/selfdrive/test/.gitignore b/selfdrive/test/.gitignore new file mode 100644 index 0000000000..5801faadf4 --- /dev/null +++ b/selfdrive/test/.gitignore @@ -0,0 +1,9 @@ +out/ +docker_out/ + +process_replay/diff.txt +process_replay/model_diff.txt +valgrind_logs.txt + +*.bz2 +*.hevc diff --git a/selfdrive/test/__init__.py b/selfdrive/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/test/cpp_harness.py b/selfdrive/test/cpp_harness.py new file mode 100755 index 0000000000..f9f425102b --- /dev/null +++ b/selfdrive/test/cpp_harness.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 +import subprocess +import sys + +from openpilot.common.prefix import OpenpilotPrefix + +with OpenpilotPrefix(): + ret = subprocess.call(sys.argv[1:]) + +sys.exit(ret) diff --git a/selfdrive/test/docker_build.sh b/selfdrive/test/docker_build.sh new file mode 100755 index 0000000000..4d58a1507c --- /dev/null +++ b/selfdrive/test/docker_build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +set -e + +# To build sim and docs, you can run the following to mount the scons cache to the same place as in CI: +# mkdir -p .ci_cache/scons_cache +# sudo mount --bind /tmp/scons_cache/ .ci_cache/scons_cache + +SCRIPT_DIR=$(dirname "$0") +OPENPILOT_DIR=$SCRIPT_DIR/../../ +if [ -n "$TARGET_ARCHITECTURE" ]; then + PLATFORM="linux/$TARGET_ARCHITECTURE" + TAG_SUFFIX="-$TARGET_ARCHITECTURE" +else + PLATFORM="linux/$(uname -m)" + TAG_SUFFIX="" +fi + +source $SCRIPT_DIR/docker_common.sh $1 "$TAG_SUFFIX" + +DOCKER_BUILDKIT=1 docker buildx build --provenance false --pull --platform $PLATFORM --load --cache-to type=inline --cache-from type=registry,ref=$REMOTE_TAG -t $DOCKER_IMAGE:latest -t $REMOTE_TAG -t $LOCAL_TAG -f $OPENPILOT_DIR/$DOCKER_FILE $OPENPILOT_DIR + +if [ -n "$PUSH_IMAGE" ]; then + docker push $REMOTE_TAG + docker tag $REMOTE_TAG $REMOTE_SHA_TAG + docker push $REMOTE_SHA_TAG +fi diff --git a/selfdrive/test/docker_common.sh b/selfdrive/test/docker_common.sh new file mode 100644 index 0000000000..2887fff74b --- /dev/null +++ b/selfdrive/test/docker_common.sh @@ -0,0 +1,18 @@ +if [ "$1" = "base" ]; then + export DOCKER_IMAGE=openpilot-base + export DOCKER_FILE=Dockerfile.openpilot_base +elif [ "$1" = "prebuilt" ]; then + export DOCKER_IMAGE=openpilot-prebuilt + export DOCKER_FILE=Dockerfile.openpilot +else + echo "Invalid docker build image: '$1'" + exit 1 +fi + +export DOCKER_REGISTRY=ghcr.io/commaai +export COMMIT_SHA=$(git rev-parse HEAD) + +TAG_SUFFIX=$2 +LOCAL_TAG=$DOCKER_IMAGE$TAG_SUFFIX +REMOTE_TAG=$DOCKER_REGISTRY/$LOCAL_TAG +REMOTE_SHA_TAG=$DOCKER_REGISTRY/$LOCAL_TAG:$COMMIT_SHA diff --git a/selfdrive/test/fuzzy_generation.py b/selfdrive/test/fuzzy_generation.py new file mode 100644 index 0000000000..94eb0dfaa6 --- /dev/null +++ b/selfdrive/test/fuzzy_generation.py @@ -0,0 +1,81 @@ +import capnp +import hypothesis.strategies as st +from typing import Any +from collections.abc import Callable +from functools import cache + +from cereal import log + +DrawType = Callable[[st.SearchStrategy], Any] + + +class FuzzyGenerator: + def __init__(self, draw: DrawType, real_floats: bool): + self.draw = draw + self.native_type_map = FuzzyGenerator._get_native_type_map(real_floats) + + def generate_native_type(self, field: str) -> st.SearchStrategy[bool | int | float | str | bytes]: + value_func = self.native_type_map.get(field) + if value_func is not None: + return value_func + else: + raise NotImplementedError(f'Invalid type: {field}') + + def generate_field(self, field: capnp.lib.capnp._StructSchemaField) -> st.SearchStrategy: + def rec(field_type: capnp.lib.capnp._DynamicStructReader) -> st.SearchStrategy: + type_which = field_type.which() + if type_which == 'struct': + return self.generate_struct(field.schema.elementType if base_type == 'list' else field.schema) + elif type_which == 'list': + return st.lists(rec(field_type.list.elementType)) + elif type_which == 'enum': + schema = field.schema.elementType if base_type == 'list' else field.schema + return st.sampled_from(list(schema.enumerants.keys())) + else: + return self.generate_native_type(type_which) + + try: + if hasattr(field.proto, 'slot'): + slot_type = field.proto.slot.type + base_type = slot_type.which() + return rec(slot_type) + else: + return self.generate_struct(field.schema) + except capnp.lib.capnp.KjException: + return self.generate_struct(field.schema) + + def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: str = None) -> st.SearchStrategy[dict[str, Any]]: + single_fill: tuple[str, ...] = (event,) if event else (self.draw(st.sampled_from(schema.union_fields)),) if schema.union_fields else () + fields_to_generate = schema.non_union_fields + single_fill + return st.fixed_dictionaries({field: self.generate_field(schema.fields[field]) for field in fields_to_generate if not field.endswith('DEPRECATED')}) + + @staticmethod + @cache + def _get_native_type_map(real_floats: bool) -> dict[str, st.SearchStrategy]: + return { + 'bool': st.booleans(), + 'int8': st.integers(min_value=-2**7, max_value=2**7-1), + 'int16': st.integers(min_value=-2**15, max_value=2**15-1), + 'int32': st.integers(min_value=-2**31, max_value=2**31-1), + 'int64': st.integers(min_value=-2**63, max_value=2**63-1), + 'uint8': st.integers(min_value=0, max_value=2**8-1), + 'uint16': st.integers(min_value=0, max_value=2**16-1), + 'uint32': st.integers(min_value=0, max_value=2**32-1), + 'uint64': st.integers(min_value=0, max_value=2**64-1), + 'float32': st.floats(width=32, allow_nan=not real_floats, allow_infinity=not real_floats), + 'float64': st.floats(width=64, allow_nan=not real_floats, allow_infinity=not real_floats), + 'text': st.text(max_size=1000), + 'data': st.binary(max_size=1000), + 'anyPointer': st.text(), # Note: No need to define a separate function for anyPointer + } + + @classmethod + def get_random_msg(cls, draw: DrawType, struct: capnp.lib.capnp._StructModule, real_floats: bool = False) -> dict[str, Any]: + fg = cls(draw, real_floats=real_floats) + data: dict[str, Any] = draw(fg.generate_struct(struct.schema)) + return data + + @classmethod + def get_random_event_msg(cls, draw: DrawType, events: list[str], real_floats: bool = False) -> list[dict[str, Any]]: + fg = cls(draw, real_floats=real_floats) + return [draw(fg.generate_struct(log.Event.schema, e)) for e in sorted(events)] diff --git a/selfdrive/test/helpers.py b/selfdrive/test/helpers.py new file mode 100644 index 0000000000..81635aa31f --- /dev/null +++ b/selfdrive/test/helpers.py @@ -0,0 +1,128 @@ +import contextlib +import http.server +import os +import threading +import time +import pytest + +from functools import wraps + +import cereal.messaging as messaging +from openpilot.common.params import Params +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.version import training_version, terms_version + + +def set_params_enabled(): + os.environ['FINGERPRINT'] = "TOYOTA_COROLLA_TSS2" + os.environ['LOGPRINT'] = "debug" + + params = Params() + params.put("HasAcceptedTerms", terms_version) + params.put("CompletedTrainingVersion", training_version) + params.put_bool("OpenpilotEnabledToggle", True) + + # valid calib + msg = messaging.new_message('liveCalibration') + msg.liveCalibration.validBlocks = 20 + msg.liveCalibration.rpyCalib = [0.0, 0.0, 0.0] + params.put("CalibrationParams", msg.to_bytes()) + +def release_only(f): + @wraps(f) + def wrap(self, *args, **kwargs): + if "RELEASE" not in os.environ: + pytest.skip("This test is only for release branches") + f(self, *args, **kwargs) + return wrap + + +@contextlib.contextmanager +def processes_context(processes, init_time=0, ignore_stopped=None): + ignore_stopped = [] if ignore_stopped is None else ignore_stopped + + # start and assert started + for n, p in enumerate(processes): + managed_processes[p].start() + if n < len(processes) - 1: + time.sleep(init_time) + + assert all(managed_processes[name].proc.exitcode is None for name in processes) + + try: + yield [managed_processes[name] for name in processes] + # assert processes are still started + assert all(managed_processes[name].proc.exitcode is None for name in processes if name not in ignore_stopped) + finally: + for p in processes: + managed_processes[p].stop() + + +def with_processes(processes, init_time=0, ignore_stopped=None): + def wrapper(func): + @wraps(func) + def wrap(*args, **kwargs): + with processes_context(processes, init_time, ignore_stopped): + return func(*args, **kwargs) + + return wrap + return wrapper + + +def noop(*args, **kwargs): + pass + + +def read_segment_list(segment_list_path): + with open(segment_list_path) as f: + seg_list = f.read().splitlines() + + return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)] + + +@contextlib.contextmanager +def http_server_context(handler, setup=None): + host = '127.0.0.1' + server = http.server.HTTPServer((host, 0), handler) + port = server.server_port + t = threading.Thread(target=server.serve_forever) + t.start() + + if setup is not None: + setup(host, port) + + try: + yield (host, port) + finally: + server.shutdown() + server.server_close() + t.join() + + +def with_http_server(func, handler=http.server.BaseHTTPRequestHandler, setup=None): + @wraps(func) + def inner(*args, **kwargs): + with http_server_context(handler, setup) as (host, port): + return func(*args, f"http://{host}:{port}", **kwargs) + return inner + + +def DirectoryHttpServer(directory) -> type[http.server.SimpleHTTPRequestHandler]: + # creates an http server that serves files from directory + class Handler(http.server.SimpleHTTPRequestHandler): + API_NO_RESPONSE = False + API_BAD_RESPONSE = False + + def do_GET(self): + if self.API_NO_RESPONSE: + return + + if self.API_BAD_RESPONSE: + self.send_response(500, "") + return + super().do_GET() + + def __init__(self, *args, **kwargs): + super().__init__(*args, directory=str(directory), **kwargs) + + return Handler diff --git a/selfdrive/test/longitudinal_maneuvers/.gitignore b/selfdrive/test/longitudinal_maneuvers/.gitignore new file mode 100644 index 0000000000..d42ab353ab --- /dev/null +++ b/selfdrive/test/longitudinal_maneuvers/.gitignore @@ -0,0 +1 @@ +out/* diff --git a/selfdrive/test/longitudinal_maneuvers/__init__.py b/selfdrive/test/longitudinal_maneuvers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/test/longitudinal_maneuvers/maneuver.py b/selfdrive/test/longitudinal_maneuvers/maneuver.py new file mode 100644 index 0000000000..dfd5b3e109 --- /dev/null +++ b/selfdrive/test/longitudinal_maneuvers/maneuver.py @@ -0,0 +1,83 @@ +import numpy as np +from openpilot.selfdrive.test.longitudinal_maneuvers.plant import Plant + + +class Maneuver: + def __init__(self, title, duration, **kwargs): + # Was tempted to make a builder class + self.distance_lead = kwargs.get("initial_distance_lead", 200.0) + self.speed = kwargs.get("initial_speed", 0.0) + self.lead_relevancy = kwargs.get("lead_relevancy", 0) + + self.breakpoints = kwargs.get("breakpoints", [0.0, duration]) + self.speed_lead_values = kwargs.get("speed_lead_values", [0.0 for i in range(len(self.breakpoints))]) + self.prob_lead_values = kwargs.get("prob_lead_values", [1.0 for i in range(len(self.breakpoints))]) + self.prob_throttle_values = kwargs.get("prob_throttle_values", [1.0 for i in range(len(self.breakpoints))]) + self.cruise_values = kwargs.get("cruise_values", [50.0 for i in range(len(self.breakpoints))]) + self.pitch_values = kwargs.get("pitch_values", [0.0 for i in range(len(self.breakpoints))]) + + self.only_lead2 = kwargs.get("only_lead2", False) + self.only_radar = kwargs.get("only_radar", False) + self.ensure_start = kwargs.get("ensure_start", False) + self.ensure_slowdown = kwargs.get("ensure_slowdown", False) + self.enabled = kwargs.get("enabled", True) + self.e2e = kwargs.get("e2e", False) + self.personality = kwargs.get("personality", 0) + self.force_decel = kwargs.get("force_decel", False) + + self.duration = duration + self.title = title + + def evaluate(self): + plant = Plant( + lead_relevancy=self.lead_relevancy, + speed=self.speed, + distance_lead=self.distance_lead, + enabled=self.enabled, + only_lead2=self.only_lead2, + only_radar=self.only_radar, + e2e=self.e2e, + personality=self.personality, + force_decel=self.force_decel, + ) + + valid = True + logs = [] + while plant.current_time < self.duration: + speed_lead = np.interp(plant.current_time, self.breakpoints, self.speed_lead_values) + prob_lead = np.interp(plant.current_time, self.breakpoints, self.prob_lead_values) + cruise = np.interp(plant.current_time, self.breakpoints, self.cruise_values) + pitch = np.interp(plant.current_time, self.breakpoints, self.pitch_values) + prob_throttle = np.interp(plant.current_time, self.breakpoints, self.prob_throttle_values) + log = plant.step(speed_lead, prob_lead, cruise, pitch, prob_throttle) + + d_rel = log['distance_lead'] - log['distance'] if self.lead_relevancy else 200. + v_rel = speed_lead - log['speed'] if self.lead_relevancy else 0. + log['d_rel'] = d_rel + log['v_rel'] = v_rel + logs.append(np.array([plant.current_time, + log['distance'], + log['distance_lead'], + log['speed'], + speed_lead, + log['acceleration']])) + + if d_rel < .4 and (self.only_radar or prob_lead > 0.5): + print("Crashed!!!!") + valid = False + + if self.ensure_start and log['v_rel'] > 0 and log['acceleration'] < 1e-3: + print('LongitudinalPlanner not starting!') + valid = False + + if self.ensure_slowdown and log['speed'] > 5.5: + print('LongitudinalPlanner not slowing down!') + valid = False + + if self.force_decel and log['speed'] > 1e-1 and log['acceleration'] > -0.04: + print('Not stopping with force decel') + valid = False + + + print("maneuver end", valid) + return valid, np.array(logs) diff --git a/selfdrive/test/longitudinal_maneuvers/plant.py b/selfdrive/test/longitudinal_maneuvers/plant.py new file mode 100755 index 0000000000..b8c6adb436 --- /dev/null +++ b/selfdrive/test/longitudinal_maneuvers/plant.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +import time +import numpy as np + +from cereal import log +import cereal.messaging as messaging +from openpilot.common.realtime import Ratekeeper, DT_MDL +from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState +from openpilot.selfdrive.modeld.constants import ModelConstants +from openpilot.selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner +from openpilot.selfdrive.controls.radard import _LEAD_ACCEL_TAU + + +class Plant: + messaging_initialized = False + + def __init__(self, lead_relevancy=False, speed=0.0, distance_lead=2.0, + enabled=True, only_lead2=False, only_radar=False, e2e=False, personality=0, force_decel=False): + self.rate = 1. / DT_MDL + + if not Plant.messaging_initialized: + Plant.radar = messaging.pub_sock('radarState') + Plant.controls_state = messaging.pub_sock('controlsState') + Plant.selfdrive_state = messaging.pub_sock('selfdriveState') + Plant.car_state = messaging.pub_sock('carState') + Plant.plan = messaging.sub_sock('longitudinalPlan') + Plant.messaging_initialized = True + + self.v_lead_prev = 0.0 + + self.distance = 0. + self.speed = speed + self.should_stop = False + self.acceleration = 0.0 + + # lead car + self.lead_relevancy = lead_relevancy + self.distance_lead = distance_lead + self.enabled = enabled + self.only_lead2 = only_lead2 + self.only_radar = only_radar + self.e2e = e2e + self.personality = personality + self.force_decel = force_decel + + self.rk = Ratekeeper(self.rate, print_delay_threshold=100.0) + self.ts = 1. / self.rate + time.sleep(0.1) + self.sm = messaging.SubMaster(['longitudinalPlan']) + + from opendbc.car.honda.values import CAR + from opendbc.car.honda.interface import CarInterface + + self.planner = LongitudinalPlanner(CarInterface.get_non_essential_params(CAR.HONDA_CIVIC), init_v=self.speed) + + @property + def current_time(self): + return float(self.rk.frame) / self.rate + + def step(self, v_lead=0.0, prob_lead=1.0, v_cruise=50., pitch=0.0, prob_throttle=1.0): + # ******** publish a fake model going straight and fake calibration ******** + # note that this is worst case for MPC, since model will delay long mpc by one time step + radar = messaging.new_message('radarState') + control = messaging.new_message('controlsState') + ss = messaging.new_message('selfdriveState') + car_state = messaging.new_message('carState') + lp = messaging.new_message('liveParameters') + car_control = messaging.new_message('carControl') + model = messaging.new_message('modelV2') + a_lead = (v_lead - self.v_lead_prev)/self.ts + self.v_lead_prev = v_lead + + if self.lead_relevancy: + d_rel = np.maximum(0., self.distance_lead - self.distance) + v_rel = v_lead - self.speed + if self.only_radar: + status = True + elif prob_lead > .5: + status = True + else: + status = False + else: + d_rel = 200. + v_rel = 0. + prob_lead = 0.0 + status = False + + lead = log.RadarState.LeadData.new_message() + lead.dRel = float(d_rel) + lead.yRel = 0.0 + lead.vRel = float(v_rel) + lead.aRel = float(a_lead - self.acceleration) + lead.vLead = float(v_lead) + lead.vLeadK = float(v_lead) + lead.aLeadK = float(a_lead) + # TODO use real radard logic for this + lead.aLeadTau = float(_LEAD_ACCEL_TAU) + lead.status = status + lead.modelProb = float(prob_lead) + if not self.only_lead2: + radar.radarState.leadOne = lead + radar.radarState.leadTwo = lead + + # Simulate model predicting slightly faster speed + # this is to ensure lead policy is effective when model + # does not predict slowdown in e2e mode + position = log.XYZTData.new_message() + position.x = [float(x) for x in (self.speed + 0.5) * np.array(ModelConstants.T_IDXS)] + model.modelV2.position = position + model.modelV2.action.desiredAcceleration = float(self.acceleration + 0.1) + velocity = log.XYZTData.new_message() + velocity.x = [float(x) for x in (self.speed + 0.5) * np.ones_like(ModelConstants.T_IDXS)] + velocity.x[0] = float(self.speed) # always start at current speed + model.modelV2.velocity = velocity + acceleration = log.XYZTData.new_message() + acceleration.x = [float(x) for x in np.zeros_like(ModelConstants.T_IDXS)] + model.modelV2.acceleration = acceleration + model.modelV2.meta.disengagePredictions.gasPressProbs = [float(prob_throttle) for _ in range(6)] + + control.controlsState.longControlState = LongCtrlState.pid if self.enabled else LongCtrlState.off + ss.selfdriveState.experimentalMode = self.e2e + ss.selfdriveState.personality = self.personality + control.controlsState.forceDecel = self.force_decel + car_state.carState.vEgo = float(self.speed) + car_state.carState.standstill = bool(self.speed < 0.01) + car_state.carState.vCruise = float(v_cruise * 3.6) + car_control.carControl.orientationNED = [0., float(pitch), 0.] + + # ******** get controlsState messages for plotting *** + sm = {'radarState': radar.radarState, + 'carState': car_state.carState, + 'carControl': car_control.carControl, + 'controlsState': control.controlsState, + 'selfdriveState': ss.selfdriveState, + 'liveParameters': lp.liveParameters, + 'modelV2': model.modelV2} + self.planner.update(sm) + self.acceleration = self.planner.output_a_target + self.speed = self.speed + self.acceleration * self.ts + self.should_stop = self.planner.output_should_stop + fcw = self.planner.fcw + self.distance_lead = self.distance_lead + v_lead * self.ts + + # ******** run the car ******** + #print(self.distance, speed) + if self.speed <= 0: + self.speed = 0 + self.acceleration = 0 + self.distance = self.distance + self.speed * self.ts + + # *** radar model *** + if self.lead_relevancy: + d_rel = np.maximum(0., self.distance_lead - self.distance) + v_rel = v_lead - self.speed + else: + d_rel = 200. + v_rel = 0. + + # print at 5hz + # if (self.rk.frame % (self.rate // 5)) == 0: + # print("%2.2f sec %6.2f m %6.2f m/s %6.2f m/s2 lead_rel: %6.2f m %6.2f m/s" + # % (self.current_time, self.distance, self.speed, self.acceleration, d_rel, v_rel)) + + + # ******** update prevs ******** + self.rk.monitor_time() + + return { + "distance": self.distance, + "speed": self.speed, + "acceleration": self.acceleration, + "should_stop": self.should_stop, + "distance_lead": self.distance_lead, + "fcw": fcw, + } + +# simple engage in standalone mode +def plant_thread(): + plant = Plant() + while 1: + plant.step() + + +if __name__ == "__main__": + plant_thread() diff --git a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py new file mode 100644 index 0000000000..ab1800b4fb --- /dev/null +++ b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py @@ -0,0 +1,191 @@ +import itertools +from parameterized import parameterized_class + +from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import STOP_DISTANCE +from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver + + +# TODO: make new FCW tests +def create_maneuvers(kwargs): + maneuvers = [ + Maneuver( + 'approach stopped car at 25m/s, initial distance: 120m', + duration=20., + initial_speed=25., + lead_relevancy=True, + initial_distance_lead=120., + speed_lead_values=[30., 0.], + breakpoints=[0., 1.], + **kwargs, + ), + Maneuver( + 'approach stopped car at 20m/s, initial distance 90m', + duration=20., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=90., + speed_lead_values=[20., 0.], + breakpoints=[0., 1.], + **kwargs, + ), + Maneuver( + 'steady state following a car at 20m/s, then lead decel to 0mph at 1m/s^2', + duration=50., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=35., + speed_lead_values=[20., 20., 0.], + breakpoints=[0., 15., 35.0], + **kwargs, + ), + Maneuver( + 'steady state following a car at 20m/s, then lead decel to 0mph at 2m/s^2', + duration=50., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=35., + speed_lead_values=[20., 20., 0.], + breakpoints=[0., 15., 25.0], + **kwargs, + ), + Maneuver( + 'steady state following a car at 20m/s, then lead decel to 0mph at 3m/s^2', + duration=50., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=35., + speed_lead_values=[20., 20., 0.], + breakpoints=[0., 15., 21.66], + **kwargs, + ), + Maneuver( + 'steady state following a car at 20m/s, then lead decel to 0mph at 3+m/s^2', + duration=40., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=35., + speed_lead_values=[20., 20., 0.], + prob_lead_values=[0., 1., 1.], + cruise_values=[20., 20., 20.], + breakpoints=[2., 2.01, 8.8], + **kwargs, + ), + Maneuver( + "approach stopped car at 20m/s, with prob_lead_values", + duration=30., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=120., + speed_lead_values=[0.0, 0., 0.], + prob_lead_values=[0.0, 0., 1.], + cruise_values=[20., 20., 20.], + breakpoints=[0.0, 2., 2.01], + **kwargs, + ), + Maneuver( + "approach stopped car at 20m/s, with prob_throttle_values and pitch = -0.1", + duration=30., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=120., + speed_lead_values=[0.0, 0., 0.], + prob_throttle_values=[1., 0., 0.], + cruise_values=[20., 20., 20.], + pitch_values=[0., -0.1, -0.1], + breakpoints=[0.0, 2., 2.01], + **kwargs, + ), + Maneuver( + "approach stopped car at 20m/s, with prob_throttle_values and pitch = +0.1", + duration=30., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=120., + speed_lead_values=[0.0, 0., 0.], + prob_throttle_values=[1., 0., 0.], + cruise_values=[20., 20., 20.], + pitch_values=[0., 0.1, 0.1], + breakpoints=[0.0, 2., 2.01], + **kwargs, + ), + Maneuver( + "approach slower cut-in car at 20m/s", + duration=20., + initial_speed=20., + lead_relevancy=True, + initial_distance_lead=50., + speed_lead_values=[15., 15.], + breakpoints=[1., 11.], + only_lead2=True, + **kwargs, + ), + Maneuver( + "stay stopped behind radar override lead", + duration=20., + initial_speed=0., + lead_relevancy=True, + initial_distance_lead=10., + speed_lead_values=[0., 0.], + prob_lead_values=[0., 0.], + breakpoints=[1., 11.], + only_radar=True, + **kwargs, + ), + Maneuver( + "NaN recovery", + duration=30., + initial_speed=15., + lead_relevancy=True, + initial_distance_lead=60., + speed_lead_values=[0., 0., 0.0], + breakpoints=[1., 1.01, 11.], + cruise_values=[float("nan"), 15., 15.], + **kwargs, + ), + Maneuver( + 'cruising at 25 m/s while disabled', + duration=20., + initial_speed=25., + lead_relevancy=False, + enabled=False, + **kwargs, + ), + Maneuver( + "slow to 5m/s with allow_throttle = False and pitch = +0.1", + duration=30., + initial_speed=20., + lead_relevancy=False, + prob_throttle_values=[1., 0., 0.], + cruise_values=[20., 20., 20.], + pitch_values=[0., 0.1, 0.1], + breakpoints=[0.0, 2., 2.01], + ensure_slowdown=True, + **kwargs, + )] + if not kwargs['force_decel']: + # controls relies on planner commanding to move for stock-ACC resume spamming + maneuvers.append(Maneuver( + "resume from a stop", + duration=20., + initial_speed=0., + lead_relevancy=True, + initial_distance_lead=STOP_DISTANCE, + speed_lead_values=[0., 0., 2.], + breakpoints=[1., 10., 15.], + ensure_start=True, + **kwargs, + )) + return maneuvers + + +@parameterized_class(("e2e", "force_decel"), itertools.product([True, False], repeat=2)) +class TestLongitudinalControl: + e2e: bool + force_decel: bool + + def test_maneuver(self, subtests): + for maneuver in create_maneuvers({"e2e": self.e2e, "force_decel": self.force_decel}): + with subtests.test(title=maneuver.title, e2e=maneuver.e2e, force_decel=maneuver.force_decel): + print(maneuver.title, f'in {"e2e" if maneuver.e2e else "acc"} mode') + valid, _ = maneuver.evaluate() + assert valid diff --git a/selfdrive/test/process_replay/.gitignore b/selfdrive/test/process_replay/.gitignore new file mode 100644 index 0000000000..a35cd58d41 --- /dev/null +++ b/selfdrive/test/process_replay/.gitignore @@ -0,0 +1 @@ +fakedata/ diff --git a/selfdrive/test/process_replay/README.md b/selfdrive/test/process_replay/README.md new file mode 100644 index 0000000000..dc801e4285 --- /dev/null +++ b/selfdrive/test/process_replay/README.md @@ -0,0 +1,126 @@ +# Process replay + +Process replay is a regression test designed to identify any changes in the output of a process. This test replays a segment through individual processes and compares the output to a known good replay. Each make is represented in the test with a segment. + +If the test fails, make sure that you didn't unintentionally change anything. If there are intentional changes, the reference logs will be updated. + +Use `test_processes.py` to run the test locally. +Use `FILEREADER_CACHE='1' test_processes.py` to cache log files. + +Currently the following processes are tested: + +* controlsd +* radard +* plannerd +* calibrationd +* dmonitoringd +* locationd +* paramsd +* ubloxd +* torqued + +### Usage +``` +Usage: test_processes.py [-h] [--whitelist-procs PROCS] [--whitelist-cars CARS] [--blacklist-procs PROCS] + [--blacklist-cars CARS] [--ignore-fields FIELDS] [--ignore-msgs MSGS] [--update-refs] [--upload-only] +Regression test to identify changes in a process's output +optional arguments: + -h, --help show this help message and exit + --whitelist-procs PROCS Whitelist given processes from the test (e.g. controlsd) + --whitelist-cars WHITELIST_CARS Whitelist given cars from the test (e.g. HONDA) + --blacklist-procs BLACKLIST_PROCS Blacklist given processes from the test (e.g. controlsd) + --blacklist-cars BLACKLIST_CARS Blacklist given cars from the test (e.g. HONDA) + --ignore-fields IGNORE_FIELDS Extra fields or msgs to ignore (e.g. driverMonitoringState.events) + --ignore-msgs IGNORE_MSGS Msgs to ignore (e.g. onroadEvents) + --update-refs Updates reference logs using current commit + --upload-only Skips testing processes and uploads logs from previous test run +``` + +## Forks + +openpilot forks can use this test with their own reference logs, by default `test_proccesses.py` saves logs locally. + +To generate new logs: + +`./test_processes.py` + +Then, check in the new logs using git-lfs. Make sure to also update the `ref_commit` file to the current commit. + +## API + +Process replay test suite exposes programmatic APIs for simultaneously running processes or groups of processes on provided logs. + +```py +def replay_process_with_name(name: Union[str, Iterable[str]], lr: LogIterable, *args, **kwargs) -> List[capnp._DynamicStructReader]: + +def replay_process( + cfg: Union[ProcessConfig, Iterable[ProcessConfig]], lr: LogIterable, frs: Optional[Dict[str, Any]] = None, + fingerprint: Optional[str] = None, return_all_logs: bool = False, custom_params: Optional[Dict[str, Any]] = None, disable_progress: bool = False +) -> List[capnp._DynamicStructReader]: +``` + +Example usage: +```py +from openpilot.selfdrive.test.process_replay import replay_process_with_name +from openpilot.tools.lib.logreader import LogReader + +lr = LogReader(...) + +# provide a name of the process to replay +output_logs = replay_process_with_name('locationd', lr) + +# or list of names +output_logs = replay_process_with_name(['ubloxd', 'locationd'], lr) +``` + +Supported processes: +* controlsd +* radard +* plannerd +* calibrationd +* dmonitoringd +* locationd +* paramsd +* ubloxd +* torqued +* modeld +* dmonitoringmodeld + +Certain processes may require an initial state, which is usually supplied within `Params` and persisting from segment to segment (e.g CalibrationParams, LiveParameters). The `custom_params` is dictionary used to prepopulate `Params` with arbitrary values. The `get_custom_params_from_lr` helper is provided to fetch meaningful values from log files. + +```py +from openpilot.selfdrive.test.process_replay import get_custom_params_from_lr + +previous_segment_lr = LogReader(...) +current_segment_lr = LogReader(...) + +custom_params = get_custom_params_from_lr(previous_segment_lr, 'last') + +output_logs = replay_process_with_name('calibrationd', lr, custom_params=custom_params) +``` + +Replaying processes that use VisionIPC (e.g. modeld, dmonitoringmodeld) require additional `frs` dictionary with camera states as keys and `FrameReader` objects as values. + +```py +from openpilot.tools.lib.framereader import FrameReader + +frs = { + 'roadCameraState': FrameReader(...), + 'wideRoadCameraState': FrameReader(...), + 'driverCameraState': FrameReader(...), +} + +output_logs = replay_process_with_name(['modeld', 'dmonitoringmodeld'], lr, frs=frs) +``` + +To capture stdout/stderr of the replayed process, `captured_output_store` can be provided. + +```py +output_store = dict() +# pass dictionary by reference, it will be filled with standard outputs - even if process replay fails +output_logs = replay_process_with_name(['radard', 'plannerd'], lr, captured_output_store=output_store) + +# entries with captured output in format { 'out': '...', 'err': '...' } will be added to provided dictionary for each replayed process +print(output_store['radard']['out']) # radard stdout +print(output_store['radard']['err']) # radard stderr +``` diff --git a/selfdrive/test/process_replay/__init__.py b/selfdrive/test/process_replay/__init__.py new file mode 100644 index 0000000000..b994277186 --- /dev/null +++ b/selfdrive/test/process_replay/__init__.py @@ -0,0 +1,2 @@ +from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, get_process_config, get_custom_params_from_lr, \ + replay_process, replay_process_with_name # noqa: F401 diff --git a/selfdrive/test/process_replay/capture.py b/selfdrive/test/process_replay/capture.py new file mode 100644 index 0000000000..90c279ef35 --- /dev/null +++ b/selfdrive/test/process_replay/capture.py @@ -0,0 +1,59 @@ +import os +import sys + +from typing import no_type_check + +class FdRedirect: + def __init__(self, file_prefix: str, fd: int): + fname = os.path.join("/tmp", f"{file_prefix}.{fd}") + if os.path.exists(fname): + os.unlink(fname) + self.dest_fd = os.open(fname, os.O_WRONLY | os.O_CREAT) + self.dest_fname = fname + self.source_fd = fd + os.set_inheritable(self.dest_fd, True) + + def __del__(self): + os.close(self.dest_fd) + + def purge(self) -> None: + os.unlink(self.dest_fname) + + def read(self) -> bytes: + with open(self.dest_fname, "rb") as f: + return f.read() or b"" + + def link(self) -> None: + os.dup2(self.dest_fd, self.source_fd) + + +class ProcessOutputCapture: + def __init__(self, proc_name: str, prefix: str): + prefix = f"{proc_name}_{prefix}" + self.stdout_redirect = FdRedirect(prefix, 1) + self.stderr_redirect = FdRedirect(prefix, 2) + + def __del__(self): + self.stdout_redirect.purge() + self.stderr_redirect.purge() + + @no_type_check # ipython classes have incompatible signatures + def link_with_current_proc(self) -> None: + try: + # prevent ipykernel from redirecting stdout/stderr of python subprocesses + from ipykernel.iostream import OutStream + if isinstance(sys.stdout, OutStream): + sys.stdout = sys.__stdout__ + if isinstance(sys.stderr, OutStream): + sys.stderr = sys.__stderr__ + except ImportError: + pass + + # link stdout/stderr to the fifo + self.stdout_redirect.link() + self.stderr_redirect.link() + + def read_outerr(self) -> tuple[str, str]: + out_str = self.stdout_redirect.read().decode() + err_str = self.stderr_redirect.read().decode() + return out_str, err_str diff --git a/selfdrive/test/process_replay/compare_logs.py b/selfdrive/test/process_replay/compare_logs.py new file mode 100755 index 0000000000..13d51a636f --- /dev/null +++ b/selfdrive/test/process_replay/compare_logs.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +import sys +import math +import capnp +import numbers +import dictdiffer +from collections import Counter + +from openpilot.tools.lib.logreader import LogReader + +EPSILON = sys.float_info.epsilon + + +def remove_ignored_fields(msg, ignore): + msg = msg.as_builder() + for key in ignore: + attr = msg + keys = key.split(".") + if msg.which() != keys[0] and len(keys) > 1: + continue + + for k in keys[:-1]: + # indexing into list + if k.isdigit(): + attr = attr[int(k)] + else: + attr = getattr(attr, k) + + v = getattr(attr, keys[-1]) + if isinstance(v, bool): + val = False + elif isinstance(v, numbers.Number): + val = 0 + elif isinstance(v, (list, capnp.lib.capnp._DynamicListBuilder)): + val = [] + else: + raise NotImplementedError(f"Unknown type: {type(v)}") + setattr(attr, keys[-1], val) + return msg + + +def compare_logs(log1, log2, ignore_fields=None, ignore_msgs=None, tolerance=None,): + if ignore_fields is None: + ignore_fields = [] + if ignore_msgs is None: + ignore_msgs = [] + tolerance = EPSILON if tolerance is None else tolerance + + log1, log2 = ( + [m for m in log if m.which() not in ignore_msgs] + for log in (log1, log2) + ) + + if len(log1) != len(log2): + cnt1 = Counter(m.which() for m in log1) + cnt2 = Counter(m.which() for m in log2) + raise Exception(f"logs are not same length: {len(log1)} VS {len(log2)}\n\t\t{cnt1}\n\t\t{cnt2}") + + diff = [] + for msg1, msg2 in zip(log1, log2, strict=True): + if msg1.which() != msg2.which(): + raise Exception("msgs not aligned between logs") + + msg1 = remove_ignored_fields(msg1, ignore_fields) + msg2 = remove_ignored_fields(msg2, ignore_fields) + + if msg1.to_bytes() != msg2.to_bytes(): + msg1_dict = msg1.as_reader().to_dict(verbose=True) + msg2_dict = msg2.as_reader().to_dict(verbose=True) + + dd = dictdiffer.diff(msg1_dict, msg2_dict, ignore=ignore_fields) + + # Dictdiffer only supports relative tolerance, we also want to check for absolute + # TODO: add this to dictdiffer + def outside_tolerance(diff): + try: + if diff[0] == "change": + a, b = diff[2] + finite = math.isfinite(a) and math.isfinite(b) + if finite and isinstance(a, numbers.Number) and isinstance(b, numbers.Number): + return abs(a - b) > max(tolerance, tolerance * max(abs(a), abs(b))) + except TypeError: + pass + return True + + dd = list(filter(outside_tolerance, dd)) + + diff.extend(dd) + return diff + + +def format_process_diff(diff): + diff_short, diff_long = "", "" + + if isinstance(diff, str): + diff_short += f" {diff}\n" + diff_long += f"\t{diff}\n" + else: + cnt: dict[str, int] = {} + for d in diff: + diff_long += f"\t{str(d)}\n" + + k = str(d[1]) + cnt[k] = 1 if k not in cnt else cnt[k] + 1 + + for k, v in sorted(cnt.items()): + diff_short += f" {k}: {v}\n" + + return diff_short, diff_long + + +def format_diff(results, log_paths, ref_commit): + diff_short, diff_long = "", "" + diff_long += f"***** tested against commit {ref_commit} *****\n" + + failed = False + for segment, result in list(results.items()): + diff_short += f"***** results for segment {segment} *****\n" + diff_long += f"***** differences for segment {segment} *****\n" + + for proc, diff in list(result.items()): + diff_long += f"*** process: {proc} ***\n" + diff_long += f"\tref: {log_paths[segment][proc]['ref']}\n" + diff_long += f"\tnew: {log_paths[segment][proc]['new']}\n\n" + + diff_short += f" {proc}\n" + + if isinstance(diff, str) or len(diff): + diff_short += f" ref: {log_paths[segment][proc]['ref']}\n" + diff_short += f" new: {log_paths[segment][proc]['new']}\n\n" + failed = True + + proc_diff_short, proc_diff_long = format_process_diff(diff) + + diff_long += proc_diff_long + diff_short += proc_diff_short + + return diff_short, diff_long, failed + + +if __name__ == "__main__": + log1 = list(LogReader(sys.argv[1])) + log2 = list(LogReader(sys.argv[2])) + ignore_fields = sys.argv[3:] or ["logMonoTime"] + results = {"segment": {"proc": compare_logs(log1, log2, ignore_fields)}} + log_paths = {"segment": {"proc": {"ref": sys.argv[1], "new": sys.argv[2]}}} + diff_short, diff_long, failed = format_diff(results, log_paths, None) + + print(diff_long) + print(diff_short) diff --git a/selfdrive/test/process_replay/migration.py b/selfdrive/test/process_replay/migration.py new file mode 100644 index 0000000000..33b363cfd9 --- /dev/null +++ b/selfdrive/test/process_replay/migration.py @@ -0,0 +1,472 @@ +from collections import defaultdict +from collections.abc import Callable +import capnp +import functools +import traceback + +from cereal import messaging, car, log +from opendbc.car.fingerprints import MIGRATION +from opendbc.car.toyota.values import EPS_SCALE, ToyotaSafetyFlags +from opendbc.car.ford.values import CAR as FORD, FordFlags, FordSafetyFlags +from opendbc.car.hyundai.values import HyundaiSafetyFlags +from opendbc.car.gm.values import GMSafetyFlags +from openpilot.selfdrive.modeld.constants import ModelConstants +from openpilot.selfdrive.modeld.fill_model_msg import fill_xyz_poly, fill_lane_line_meta +from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_encode_index +from openpilot.selfdrive.controls.lib.longitudinal_planner import get_accel_from_plan, CONTROL_N_T_IDX +from openpilot.system.manager.process_config import managed_processes +from openpilot.tools.lib.logreader import LogIterable + +MessageWithIndex = tuple[int, capnp.lib.capnp._DynamicStructReader] +MigrationOps = tuple[list[tuple[int, capnp.lib.capnp._DynamicStructReader]], list[capnp.lib.capnp._DynamicStructReader], list[int]] +MigrationFunc = Callable[[list[MessageWithIndex]], MigrationOps] + + +# rules for migration functions +# 1. must use the decorator @migration(inputs=[...], product="...") and MigrationFunc signature +# 2. it only gets the messages that are in the inputs list +# 3. product is the message type created by the migration function, and the function will be skipped if product type already exists in lr +# 4. it must return a list of operations to be applied to the logreader (replace, add, delete) +# 5. all migration functions must be independent of each other +def migrate_all(lr: LogIterable, manager_states: bool = False, panda_states: bool = False, camera_states: bool = False): + migrations = [ + migrate_sensorEvents, + migrate_carParams, + migrate_gpsLocation, + migrate_deviceState, + migrate_carOutput, + migrate_controlsState, + migrate_carState, + migrate_liveLocationKalman, + migrate_liveTracks, + migrate_driverAssistance, + migrate_drivingModelData, + migrate_onroadEvents, + migrate_driverMonitoringState, + migrate_longitudinalPlan, + ] + if manager_states: + migrations.append(migrate_managerState) + if panda_states: + migrations.extend([migrate_pandaStates, migrate_peripheralState]) + if camera_states: + migrations.append(migrate_cameraStates) + + return migrate(lr, migrations) + + +def migrate(lr: LogIterable, migration_funcs: list[MigrationFunc]): + lr = list(lr) + grouped = defaultdict(list) + for i, msg in enumerate(lr): + grouped[msg.which()].append(i) + + replace_ops, add_ops, del_ops = [], [], [] + for migration in migration_funcs: + assert hasattr(migration, "inputs") and hasattr(migration, "product"), "Migration functions must use @migration decorator" + if migration.product in grouped: # skip if product already exists + continue + + sorted_indices = sorted(ii for i in migration.inputs for ii in grouped[i]) + msg_gen = [(i, lr[i]) for i in sorted_indices] + r_ops, a_ops, d_ops = migration(msg_gen) + replace_ops.extend(r_ops) + add_ops.extend(a_ops) + del_ops.extend(d_ops) + + for index, msg in replace_ops: + lr[index] = msg + for index in sorted(del_ops, reverse=True): + del lr[index] + for msg in add_ops: + lr.append(msg) + lr = sorted(lr, key=lambda x: x.logMonoTime) + + return lr + + +def migration(inputs: list[str], product: str|None=None): + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + wrapper.inputs = inputs + wrapper.product = product + return wrapper + return decorator + + +@migration(inputs=["longitudinalPlan", "carParams"]) +def migrate_longitudinalPlan(msgs): + ops = [] + + needs_migration = all(msg.longitudinalPlan.aTarget == 0.0 for _, msg in msgs if msg.which() == 'longitudinalPlan') + CP = next((m.carParams for _, m in msgs if m.which() == 'carParams'), None) + if not needs_migration or CP is None: + return [], [], [] + + for index, msg in msgs: + if msg.which() != 'longitudinalPlan': + continue + new_msg = msg.as_builder() + a_target, should_stop = get_accel_from_plan(msg.longitudinalPlan.speeds, msg.longitudinalPlan.accels, CONTROL_N_T_IDX) + new_msg.longitudinalPlan.aTarget, new_msg.longitudinalPlan.shouldStop = float(a_target), bool(should_stop) + ops.append((index, new_msg.as_reader())) + return ops, [], [] + + +@migration(inputs=["longitudinalPlan"], product="driverAssistance") +def migrate_driverAssistance(msgs): + add_ops = [] + for _, msg in msgs: + new_msg = messaging.new_message('driverAssistance', valid=True, logMonoTime=msg.logMonoTime) + add_ops.append(new_msg.as_reader()) + return [], add_ops, [] + + +@migration(inputs=["modelV2"], product="drivingModelData") +def migrate_drivingModelData(msgs): + add_ops = [] + for _, msg in msgs: + dmd = messaging.new_message('drivingModelData', valid=msg.valid, logMonoTime=msg.logMonoTime) + for field in ["frameId", "frameIdExtra", "frameDropPerc", "modelExecutionTime", "action"]: + setattr(dmd.drivingModelData, field, getattr(msg.modelV2, field)) + for meta_field in ["laneChangeState", "laneChangeState"]: + setattr(dmd.drivingModelData.meta, meta_field, getattr(msg.modelV2.meta, meta_field)) + if len(msg.modelV2.laneLines) and len(msg.modelV2.laneLineProbs): + fill_lane_line_meta(dmd.drivingModelData.laneLineMeta, msg.modelV2.laneLines, msg.modelV2.laneLineProbs) + if all(len(a) for a in [msg.modelV2.position.x, msg.modelV2.position.y, msg.modelV2.position.z]): + fill_xyz_poly(dmd.drivingModelData.path, ModelConstants.POLY_PATH_DEGREE, msg.modelV2.position.x, msg.modelV2.position.y, msg.modelV2.position.z) + add_ops.append( dmd.as_reader()) + return [], add_ops, [] + + +@migration(inputs=["liveTracksDEPRECATED"], product="liveTracks") +def migrate_liveTracks(msgs): + ops = [] + for index, msg in msgs: + new_msg = messaging.new_message('liveTracks') + new_msg.valid = msg.valid + new_msg.logMonoTime = msg.logMonoTime + + pts = [] + for track in msg.liveTracksDEPRECATED: + pt = car.RadarData.RadarPoint() + pt.trackId = track.trackId + + pt.dRel = track.dRel + pt.yRel = track.yRel + pt.vRel = track.vRel + pt.aRel = track.aRel + pt.measured = True + pts.append(pt) + + new_msg.liveTracks.points = pts + ops.append((index, new_msg.as_reader())) + return ops, [], [] + + +@migration(inputs=["liveLocationKalmanDEPRECATED"], product="livePose") +def migrate_liveLocationKalman(msgs): + nans = [float('nan')] * 3 + ops = [] + for index, msg in msgs: + m = messaging.new_message('livePose') + m.valid = msg.valid + m.logMonoTime = msg.logMonoTime + for field in ["orientationNED", "velocityDevice", "accelerationDevice", "angularVelocityDevice"]: + lp_field, llk_field = getattr(m.livePose, field), getattr(msg.liveLocationKalmanDEPRECATED, field) + lp_field.x, lp_field.y, lp_field.z = llk_field.value or nans + lp_field.xStd, lp_field.yStd, lp_field.zStd = llk_field.std or nans + lp_field.valid = llk_field.valid + for flag in ["inputsOK", "posenetOK", "sensorsOK"]: + setattr(m.livePose, flag, getattr(msg.liveLocationKalmanDEPRECATED, flag)) + ops.append((index, m.as_reader())) + return ops, [], [] + + +@migration(inputs=["controlsState"], product="selfdriveState") +def migrate_controlsState(msgs): + add_ops = [] + for _, msg in msgs: + m = messaging.new_message('selfdriveState') + m.valid = msg.valid + m.logMonoTime = msg.logMonoTime + ss = m.selfdriveState + for field in ("enabled", "active", "state", "engageable", "alertText1", "alertText2", + "alertStatus", "alertSize", "alertType", "experimentalMode", + "personality"): + setattr(ss, field, getattr(msg.controlsState, field+"DEPRECATED")) + add_ops.append(m.as_reader()) + return [], add_ops, [] + + +@migration(inputs=["carState", "controlsState"]) +def migrate_carState(msgs): + ops = [] + last_cs = None + for index, msg in msgs: + if msg.which() == 'controlsState': + last_cs = msg + elif msg.which() == 'carState' and last_cs is not None: + if last_cs.controlsState.vCruiseDEPRECATED - msg.carState.vCruise > 0.1: + msg = msg.as_builder() + msg.carState.vCruise = last_cs.controlsState.vCruiseDEPRECATED + msg.carState.vCruiseCluster = last_cs.controlsState.vCruiseClusterDEPRECATED + ops.append((index, msg.as_reader())) + return ops, [], [] + + +@migration(inputs=["managerState"]) +def migrate_managerState(msgs): + ops = [] + for index, msg in msgs: + new_msg = msg.as_builder() + new_msg.managerState.processes = [{'name': name, 'running': True} for name in managed_processes] + ops.append((index, new_msg.as_reader())) + return ops, [], [] + + +@migration(inputs=["gpsLocation", "gpsLocationExternal"]) +def migrate_gpsLocation(msgs): + ops = [] + for index, msg in msgs: + new_msg = msg.as_builder() + g = getattr(new_msg, new_msg.which()) + # hasFix is a newer field + if not g.hasFix and g.flags == 1: + g.hasFix = True + ops.append((index, new_msg.as_reader())) + return ops, [], [] + + +@migration(inputs=["deviceState", "initData"]) +def migrate_deviceState(msgs): + init_data = next((m.initData for _, m in msgs if m.which() == 'initData'), None) + device_state = next((m.deviceState for _, m in msgs if m.which() == 'deviceState'), None) + if init_data is None or device_state is None: + return [], [], [] + + ops = [] + for i, msg in msgs: + if msg.which() == 'deviceState': + n = msg.as_builder() + n.deviceState.deviceType = init_data.deviceType + ops.append((i, n.as_reader())) + return ops, [], [] + + +@migration(inputs=["carControl"], product="carOutput") +def migrate_carOutput(msgs): + add_ops = [] + for _, msg in msgs: + co = messaging.new_message('carOutput') + co.valid = msg.valid + co.logMonoTime = msg.logMonoTime + co.carOutput.actuatorsOutput = msg.carControl.actuatorsOutputDEPRECATED + add_ops.append(co.as_reader()) + return [], add_ops, [] + + +@migration(inputs=["pandaStates", "pandaStateDEPRECATED", "carParams"]) +def migrate_pandaStates(msgs): + # TODO: safety param migration should be handled automatically + safety_param_migration = { + "TOYOTA_PRIUS": EPS_SCALE["TOYOTA_PRIUS"] | ToyotaSafetyFlags.STOCK_LONGITUDINAL, + "TOYOTA_RAV4": EPS_SCALE["TOYOTA_RAV4"] | ToyotaSafetyFlags.ALT_BRAKE, + "KIA_EV6": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CANFD_LKA_STEERING, + "CHEVROLET_VOLT": GMSafetyFlags.EV, + "CHEVROLET_BOLT_EUV": GMSafetyFlags.EV | GMSafetyFlags.HW_CAM, + } + # TODO: get new Ford route + safety_param_migration |= dict.fromkeys((set(FORD) - FORD.with_flags(FordFlags.CANFD)), FordSafetyFlags.LONG_CONTROL) + + # Migrate safety param base on carParams + CP = next((m.carParams for _, m in msgs if m.which() == 'carParams'), None) + assert CP is not None, "carParams message not found" + fingerprint = MIGRATION.get(CP.carFingerprint, CP.carFingerprint) + if fingerprint in safety_param_migration: + safety_param = safety_param_migration[fingerprint].value + elif len(CP.safetyConfigs): + safety_param = CP.safetyConfigs[0].safetyParam + if CP.safetyConfigs[0].safetyParamDEPRECATED != 0: + safety_param = CP.safetyConfigs[0].safetyParamDEPRECATED + else: + safety_param = CP.safetyParamDEPRECATED + + ops = [] + for index, msg in msgs: + if msg.which() == 'pandaStateDEPRECATED': + new_msg = messaging.new_message('pandaStates', 1) + new_msg.valid = msg.valid + new_msg.logMonoTime = msg.logMonoTime + new_msg.pandaStates[0] = msg.pandaStateDEPRECATED + new_msg.pandaStates[0].safetyParam = safety_param + ops.append((index, new_msg.as_reader())) + elif msg.which() == 'pandaStates': + new_msg = msg.as_builder() + new_msg.pandaStates[-1].safetyParam = safety_param + # Clear DISABLE_DISENGAGE_ON_GAS bit to fix controls mismatch + new_msg.pandaStates[-1].alternativeExperience &= ~1 + ops.append((index, new_msg.as_reader())) + return ops, [], [] + + +@migration(inputs=["pandaStates", "pandaStateDEPRECATED"], product="peripheralState") +def migrate_peripheralState(msgs): + add_ops = [] + + which = "pandaStates" if any(msg.which() == "pandaStates" for _, msg in msgs) else "pandaStateDEPRECATED" + for _, msg in msgs: + if msg.which() != which: + continue + new_msg = messaging.new_message("peripheralState") + new_msg.valid = msg.valid + new_msg.logMonoTime = msg.logMonoTime + add_ops.append(new_msg.as_reader()) + return [], add_ops, [] + + +@migration(inputs=["roadEncodeIdx", "wideRoadEncodeIdx", "driverEncodeIdx", "roadCameraState", "wideRoadCameraState", "driverCameraState"]) +def migrate_cameraStates(msgs): + add_ops, del_ops = [], [] + frame_to_encode_id = defaultdict(dict) + # just for encodeId fallback mechanism + min_frame_id = defaultdict(lambda: float('inf')) + + for _, msg in msgs: + if msg.which() not in ["roadEncodeIdx", "wideRoadEncodeIdx", "driverEncodeIdx"]: + continue + + encode_index = getattr(msg, msg.which()) + meta = meta_from_encode_index(msg.which()) + + assert encode_index.segmentId < 1200, f"Encoder index segmentId greater that 1200: {msg.which()} {encode_index.segmentId}" + frame_to_encode_id[meta.camera_state][encode_index.frameId] = encode_index.segmentId + + for index, msg in msgs: + if msg.which() not in ["roadCameraState", "wideRoadCameraState", "driverCameraState"]: + continue + + camera_state = getattr(msg, msg.which()) + min_frame_id[msg.which()] = min(min_frame_id[msg.which()], camera_state.frameId) + + encode_id = frame_to_encode_id[msg.which()].get(camera_state.frameId) + if encode_id is None: + print(f"Missing encoded frame for camera feed {msg.which()} with frameId: {camera_state.frameId}") + if len(frame_to_encode_id[msg.which()]) != 0: + del_ops.append(index) + continue + + # fallback mechanism for logs without encodeIdx (e.g. logs from before 2022 with dcamera recording disabled) + # try to fake encode_id by subtracting lowest frameId + encode_id = camera_state.frameId - min_frame_id[msg.which()] + print(f"Faking encodeId to {encode_id} for camera feed {msg.which()} with frameId: {camera_state.frameId}") + + new_msg = messaging.new_message(msg.which()) + new_camera_state = getattr(new_msg, new_msg.which()) + new_camera_state.sensor = camera_state.sensor + new_camera_state.frameId = encode_id + new_camera_state.encodeId = encode_id + # timestampSof was added later so it might be missing on some old segments + if camera_state.timestampSof == 0 and camera_state.timestampEof > 25000000: + new_camera_state.timestampSof = camera_state.timestampEof - 18000000 + else: + new_camera_state.timestampSof = camera_state.timestampSof + new_camera_state.timestampEof = camera_state.timestampEof + new_msg.logMonoTime = msg.logMonoTime + new_msg.valid = msg.valid + + del_ops.append(index) + add_ops.append(new_msg.as_reader()) + return [], add_ops, del_ops + + +@migration(inputs=["carParams"]) +def migrate_carParams(msgs): + ops = [] + for index, msg in msgs: + CP = msg.as_builder() + CP.carParams.carFingerprint = MIGRATION.get(CP.carParams.carFingerprint, CP.carParams.carFingerprint) + for car_fw in CP.carParams.carFw: + car_fw.brand = CP.carParams.brand + ops.append((index, CP.as_reader())) + return ops, [], [] + + +@migration(inputs=["sensorEventsDEPRECATED"], product="sensorEvents") +def migrate_sensorEvents(msgs): + add_ops, del_ops = [], [] + for index, msg in msgs: + # migrate to split sensor events + for evt in msg.sensorEventsDEPRECATED: + # build new message for each sensor type + sensor_service = '' + if evt.which() == 'acceleration': + sensor_service = 'accelerometer' + elif evt.which() == 'gyro' or evt.which() == 'gyroUncalibrated': + sensor_service = 'gyroscope' + elif evt.which() == 'light' or evt.which() == 'proximity': + sensor_service = 'lightSensor' + elif evt.which() == 'magnetic' or evt.which() == 'magneticUncalibrated': + sensor_service = 'magnetometer' + elif evt.which() == 'temperature': + sensor_service = 'temperatureSensor' + + m = messaging.new_message(sensor_service) + m.valid = True + m.logMonoTime = msg.logMonoTime + + m_dat = getattr(m, sensor_service) + m_dat.version = evt.version + m_dat.sensor = evt.sensor + m_dat.type = evt.type + m_dat.source = evt.source + m_dat.timestamp = evt.timestamp + setattr(m_dat, evt.which(), getattr(evt, evt.which())) + + add_ops.append(m.as_reader()) + del_ops.append(index) + return [], add_ops, del_ops + + +@migration(inputs=["onroadEventsDEPRECATED"], product="onroadEvents") +def migrate_onroadEvents(msgs): + ops = [] + for index, msg in msgs: + onroadEvents = [] + for event in msg.onroadEventsDEPRECATED: + try: + if not str(event.name).endswith('DEPRECATED'): + # dict converts name enum into string representation + onroadEvents.append(log.OnroadEvent(**event.to_dict())) + except RuntimeError: # Member was null + traceback.print_exc() + + new_msg = messaging.new_message('onroadEvents', len(msg.onroadEventsDEPRECATED)) + new_msg.valid = msg.valid + new_msg.logMonoTime = msg.logMonoTime + new_msg.onroadEvents = onroadEvents + ops.append((index, new_msg.as_reader())) + + return ops, [], [] + + +@migration(inputs=["driverMonitoringState"]) +def migrate_driverMonitoringState(msgs): + ops = [] + for index, msg in msgs: + msg = msg.as_builder() + events = [] + for event in msg.driverMonitoringState.eventsDEPRECATED: + try: + if not str(event.name).endswith('DEPRECATED'): + # dict converts name enum into string representation + events.append(log.OnroadEvent(**event.to_dict())) + except RuntimeError: # Member was null + traceback.print_exc() + + msg.driverMonitoringState.events = events + ops.append((index, msg.as_reader())) + + return ops, [], [] diff --git a/selfdrive/test/process_replay/model_replay.py b/selfdrive/test/process_replay/model_replay.py new file mode 100755 index 0000000000..59b8cf8250 --- /dev/null +++ b/selfdrive/test/process_replay/model_replay.py @@ -0,0 +1,306 @@ +#!/usr/bin/env python3 +import os +import pickle +import sys +from collections import defaultdict +from typing import Any +import tempfile +from itertools import zip_longest + +import matplotlib.pyplot as plt +import numpy as np +from tabulate import tabulate + +from openpilot.common.git import get_commit +from openpilot.system.hardware import PC +from openpilot.tools.lib.openpilotci import get_url +from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff +from openpilot.selfdrive.test.process_replay.process_replay import get_process_config, replay_process +from openpilot.tools.lib.framereader import FrameReader +from openpilot.tools.lib.logreader import LogReader, save_log +from openpilot.tools.lib.github_utils import GithubUtils + +TEST_ROUTE = "8494c69d3c710e81|000001d4--2648a9a404" +SEGMENT = 4 +START_FRAME = 0 +END_FRAME = 60 + +SEND_EXTRA_INPUTS = bool(int(os.getenv("SEND_EXTRA_INPUTS", "0"))) + +DATA_TOKEN = os.getenv("CI_ARTIFACTS_TOKEN","") +API_TOKEN = os.getenv("GITHUB_COMMENTS_TOKEN","") +MODEL_REPLAY_BUCKET="model_replay_master" +GITHUB = GithubUtils(API_TOKEN, DATA_TOKEN) + +EXEC_TIMINGS = [ + # model, instant max, average max + ("modelV2", 0.035, 0.025), + ("driverStateV2", 0.02, 0.015), +] + +def get_log_fn(test_route, ref="master"): + return f"{test_route}_model_tici_{ref}.zst" + +def plot(proposed, master, title, tmp): + proposed = list(proposed) + master = list(master) + fig, ax = plt.subplots() + ax.plot(master, label='MASTER') + ax.plot(proposed, label='PROPOSED') + plt.legend(loc='best') + plt.title(title) + plt.savefig(f'{tmp}/{title}.png') + return (title + '.png', proposed == master) + +def get_event(logs, event): + return (getattr(m, m.which()) for m in filter(lambda m: m.which() == event, logs)) + +def zl(array, fill): + return zip_longest(array, [], fillvalue=fill) + +def get_idx_if_non_empty(l, idx=None): + return l if idx is None else (l[idx] if len(l) > 0 else None) + +def generate_report(proposed, master, tmp, commit): + ModelV2_Plots = zl([ + (lambda x: get_idx_if_non_empty(x.velocity.x, 0), "velocity.x"), + (lambda x: get_idx_if_non_empty(x.action.desiredCurvature), "desiredCurvature"), + (lambda x: get_idx_if_non_empty(x.action.desiredAcceleration), "desiredAcceleration"), + (lambda x: get_idx_if_non_empty(x.leadsV3[0].x, 0), "leadsV3.x"), + (lambda x: get_idx_if_non_empty(x.laneLines[1].y, 0), "laneLines.y"), + (lambda x: get_idx_if_non_empty(x.meta.desireState, 3), "desireState.laneChangeLeft"), + (lambda x: get_idx_if_non_empty(x.meta.desireState, 4), "desireState.laneChangeRight"), + (lambda x: get_idx_if_non_empty(x.meta.disengagePredictions.gasPressProbs, 1), "gasPressProbs") + ], "modelV2") + DriverStateV2_Plots = zl([ + (lambda x: get_idx_if_non_empty(x.wheelOnRightProb), "wheelOnRightProb"), + (lambda x: get_idx_if_non_empty(x.leftDriverData.faceProb), "leftDriverData.faceProb"), + (lambda x: get_idx_if_non_empty(x.leftDriverData.faceOrientation, 0), "leftDriverData.faceOrientation0"), + (lambda x: get_idx_if_non_empty(x.leftDriverData.leftBlinkProb), "leftDriverData.leftBlinkProb"), + (lambda x: get_idx_if_non_empty(x.leftDriverData.notReadyProb, 0), "leftDriverData.notReadyProb0"), + (lambda x: get_idx_if_non_empty(x.rightDriverData.faceProb), "rightDriverData.faceProb"), + ], "driverStateV2") + + return [plot(map(v[0], get_event(proposed, event)), \ + map(v[0], get_event(master, event)), f"{v[1]}_{commit[:7]}", tmp) \ + for v,event in ([*ModelV2_Plots] + [*DriverStateV2_Plots])] + +def create_table(title, files, link, open_table=False): + if not files: + return "" + table = [f'
    {title}'] + for i,f in enumerate(files): + if not (i % 2): + table.append("") + table.append(f'') + if (i % 2): + table.append("") + table.append("
    ") + table = "".join(table) + return table + +def comment_replay_report(proposed, master, full_logs): + with tempfile.TemporaryDirectory() as tmp: + PR_BRANCH = os.getenv("GIT_BRANCH","") + DATA_BUCKET = f"model_replay_{PR_BRANCH}" + + try: + GITHUB.get_pr_number(PR_BRANCH) + except Exception: + print("No PR associated with this branch. Skipping report.") + return + + commit = get_commit() + files = generate_report(proposed, master, tmp, commit) + + GITHUB.upload_files(DATA_BUCKET, [(x[0], tmp + '/' + x[0]) for x in files]) + + log_name = get_log_fn(TEST_ROUTE, commit) + save_log(log_name, full_logs) + GITHUB.upload_file(DATA_BUCKET, os.path.basename(log_name), log_name) + + diff_files = [x for x in files if not x[1]] + link = GITHUB.get_bucket_link(DATA_BUCKET) + diff_plots = create_table("Model Replay Differences", diff_files, link, open_table=True) + all_plots = create_table("All Model Replay Plots", files, link) + comment = f"ref for commit {commit}: {link}/{log_name}" + diff_plots + all_plots + GITHUB.comment_on_pr(comment, PR_BRANCH, "commaci-public", True) + +def trim_logs(logs, start_frame, end_frame, frs_types, include_all_types): + all_msgs = [] + cam_state_counts = defaultdict(int) + for msg in sorted(logs, key=lambda m: m.logMonoTime): + if msg.which() in frs_types: + cam_state_counts[msg.which()] += 1 + if any(cam_state_counts[state] >= start_frame for state in frs_types): + all_msgs.append(msg) + if all(cam_state_counts[state] == end_frame for state in frs_types): + break + + if len(include_all_types) != 0: + other_msgs = [m for m in logs if m.which() in include_all_types] + all_msgs.extend(other_msgs) + + return all_msgs + + +def model_replay(lr, frs): + # modeld is using frame pairs + modeld_logs = trim_logs(lr, START_FRAME, END_FRAME, {"roadCameraState", "wideRoadCameraState"}, + {"roadEncodeIdx", "wideRoadEncodeIdx", "carParams", "carState", "carControl", "can"}) + dmodeld_logs = trim_logs(lr, START_FRAME, END_FRAME, {"driverCameraState"}, {"driverEncodeIdx", "carParams", "can"}) + + if not SEND_EXTRA_INPUTS: + modeld_logs = [msg for msg in modeld_logs if msg.which() != 'liveCalibration'] + dmodeld_logs = [msg for msg in dmodeld_logs if msg.which() != 'liveCalibration'] + + # initial setup + for s in ('liveCalibration', 'deviceState'): + msg = next(msg for msg in lr if msg.which() == s).as_builder() + msg.logMonoTime = lr[0].logMonoTime + modeld_logs.insert(1, msg.as_reader()) + dmodeld_logs.insert(1, msg.as_reader()) + + modeld = get_process_config("modeld") + dmonitoringmodeld = get_process_config("dmonitoringmodeld") + + modeld_msgs = replay_process(modeld, modeld_logs, frs) + dmonitoringmodeld_msgs = replay_process(dmonitoringmodeld, dmodeld_logs, frs) + + msgs = modeld_msgs + dmonitoringmodeld_msgs + + header = ['model', 'max instant', 'max instant allowed', 'average', 'max average allowed', 'test result'] + rows = [] + timings_ok = True + for (s, instant_max, avg_max) in EXEC_TIMINGS: + ts = [getattr(m, s).modelExecutionTime for m in msgs if m.which() == s] + # TODO some init can happen in first iteration + ts = ts[1:] + + errors = [] + if np.max(ts) > instant_max: + errors.append("❌ FAILED MAX TIMING CHECK ❌") + if np.mean(ts) > avg_max: + errors.append("❌ FAILED AVG TIMING CHECK ❌") + + timings_ok = not errors and timings_ok + rows.append([s, np.max(ts), instant_max, np.mean(ts), avg_max, "\n".join(errors) or "✅"]) + + print("------------------------------------------------") + print("----------------- Model Timing -----------------") + print("------------------------------------------------") + print(tabulate(rows, header, tablefmt="simple_grid", stralign="center", numalign="center", floatfmt=".4f")) + assert timings_ok or PC + + return msgs + + +def get_frames(): + regen_cache = "--regen-cache" in sys.argv + frames_cache = '/tmp/model_replay_cache' if PC else '/data/model_replay_cache' + os.makedirs(frames_cache, exist_ok=True) + + cache_name = f'{frames_cache}/{TEST_ROUTE}_{SEGMENT}_{START_FRAME}_{END_FRAME}.pkl' + if os.path.isfile(cache_name) and not regen_cache: + try: + print(f"Loading frames from cache {cache_name}") + return pickle.load(open(cache_name, "rb")) + except Exception as e: + print(f"Failed to load frames from cache {cache_name}: {e}") + + frs = { + 'roadCameraState': FrameReader(get_url(TEST_ROUTE, SEGMENT, "fcamera.hevc"), pix_fmt='nv12', cache_size=END_FRAME - START_FRAME), + 'driverCameraState': FrameReader(get_url(TEST_ROUTE, SEGMENT, "dcamera.hevc"), pix_fmt='nv12', cache_size=END_FRAME - START_FRAME), + 'wideRoadCameraState': FrameReader(get_url(TEST_ROUTE, SEGMENT, "ecamera.hevc"), pix_fmt='nv12', cache_size=END_FRAME - START_FRAME), + } + for fr in frs.values(): + for fidx in range(START_FRAME, END_FRAME): + fr.get(fidx) + fr.it = None + print(f"Dumping frame cache {cache_name}") + pickle.dump(frs, open(cache_name, "wb")) + return frs + +if __name__ == "__main__": + update = "--update" in sys.argv or (os.getenv("GIT_BRANCH", "") == 'master') + replay_dir = os.path.dirname(os.path.abspath(__file__)) + + # load logs + lr = list(LogReader(get_url(TEST_ROUTE, SEGMENT, "rlog.zst"))) + frs = get_frames() + + log_msgs = [] + # run replays + log_msgs += model_replay(lr, frs) + + # get diff + failed = False + if not update: + log_fn = get_log_fn(TEST_ROUTE) + try: + all_logs = list(LogReader(GITHUB.get_file_url(MODEL_REPLAY_BUCKET, log_fn))) + cmp_log = [] + model_start_index = next(i for i, m in enumerate(all_logs) if m.which() in ("modelV2", "drivingModelData", "cameraOdometry")) + cmp_log += all_logs[model_start_index+START_FRAME*3:model_start_index + END_FRAME*3] + dmon_start_index = next(i for i, m in enumerate(all_logs) if m.which() == "driverStateV2") + cmp_log += all_logs[dmon_start_index+START_FRAME:dmon_start_index + END_FRAME] + + ignore = [ + 'logMonoTime', + 'drivingModelData.frameDropPerc', + 'drivingModelData.modelExecutionTime', + 'modelV2.frameDropPerc', + 'modelV2.modelExecutionTime', + 'driverStateV2.modelExecutionTime', + 'driverStateV2.gpuExecutionTime' + ] + if PC: + # TODO We ignore whole bunch so we can compare important stuff + # like posenet with reasonable tolerance + ignore += ['modelV2.acceleration.x', + 'modelV2.position.x', + 'modelV2.position.xStd', + 'modelV2.position.y', + 'modelV2.position.yStd', + 'modelV2.position.z', + 'modelV2.position.zStd', + 'drivingModelData.path.xCoefficients',] + for i in range(3): + for field in ('x', 'y', 'v', 'a'): + ignore.append(f'modelV2.leadsV3.{i}.{field}') + ignore.append(f'modelV2.leadsV3.{i}.{field}Std') + for i in range(4): + for field in ('x', 'y', 'z', 't'): + ignore.append(f'modelV2.laneLines.{i}.{field}') + for i in range(2): + for field in ('x', 'y', 'z', 't'): + ignore.append(f'modelV2.roadEdges.{i}.{field}') + tolerance = .3 if PC else None + results: Any = {TEST_ROUTE: {}} + log_paths: Any = {TEST_ROUTE: {"models": {'ref': log_fn, 'new': log_fn}}} + results[TEST_ROUTE]["models"] = compare_logs(cmp_log, log_msgs, tolerance=tolerance, ignore_fields=ignore) + diff_short, diff_long, failed = format_diff(results, log_paths, 'master') + + if "CI" in os.environ: + comment_replay_report(log_msgs, cmp_log, log_msgs) + failed = False + print(diff_long) + print('-------------\n'*5) + print(diff_short) + with open("model_diff.txt", "w") as f: + f.write(diff_long) + except Exception as e: + print(str(e)) + failed = True + + # upload new refs + if update and not PC: + print("Uploading new refs") + log_fn = get_log_fn(TEST_ROUTE) + save_log(log_fn, log_msgs) + try: + GITHUB.upload_file(MODEL_REPLAY_BUCKET, os.path.basename(log_fn), log_fn) + except Exception as e: + print("failed to upload", e) + + sys.exit(int(failed)) diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py new file mode 100755 index 0000000000..1144b7955e --- /dev/null +++ b/selfdrive/test/process_replay/process_replay.py @@ -0,0 +1,803 @@ +#!/usr/bin/env python3 +import os +import time +import copy +import heapq +import signal +from collections import Counter +from dataclasses import dataclass, field +from itertools import islice +from typing import Any +from collections.abc import Callable, Iterable +from tqdm import tqdm +import capnp +from openpilot.system.hardware.hw import Paths + +import cereal.messaging as messaging +from cereal import car +from cereal.services import SERVICE_LIST +from msgq.visionipc import VisionIpcServer, get_endpoint_name as vipc_get_endpoint_name +from opendbc.car.can_definitions import CanData +from opendbc.car.car_helpers import get_car, interfaces +from openpilot.common.params import Params +from openpilot.common.prefix import OpenpilotPrefix +from openpilot.common.timeout import Timeout +from openpilot.common.realtime import DT_CTRL +from openpilot.system.manager.process_config import managed_processes +from openpilot.selfdrive.test.process_replay.vision_meta import meta_from_camera_state, available_streams +from openpilot.selfdrive.test.process_replay.migration import migrate_all +from openpilot.selfdrive.test.process_replay.capture import ProcessOutputCapture +from openpilot.tools.lib.logreader import LogIterable +from openpilot.tools.lib.framereader import FrameReader + +# Numpy gives different results based on CPU features after version 19 +NUMPY_TOLERANCE = 1e-2 +PROC_REPLAY_DIR = os.path.dirname(os.path.abspath(__file__)) +FAKEDATA = os.path.join(PROC_REPLAY_DIR, "fakedata/") + + +class LauncherWithCapture: + def __init__(self, capture: ProcessOutputCapture, launcher: Callable): + self.capture = capture + self.launcher = launcher + + def __call__(self, *args, **kwargs): + self.capture.link_with_current_proc() + self.launcher(*args, **kwargs) + + +class ReplayContext: + def __init__(self, cfg): + self.proc_name = cfg.proc_name + self.pubs = cfg.pubs + self.main_pub = cfg.main_pub + self.main_pub_drained = cfg.main_pub_drained + assert len(self.pubs) != 0 or self.main_pub is not None + + def __enter__(self): + self.open_context() + + return self + + def __exit__(self, exc_type, exc_obj, exc_tb): + self.close_context() + + def open_context(self): + messaging.toggle_fake_events(True) + messaging.set_fake_prefix(self.proc_name) + + if self.main_pub is None: + self.events = {} + for pub in self.pubs: + self.events[pub] = messaging.fake_event_handle(pub, enable=True) + else: + self.events = {self.main_pub: messaging.fake_event_handle(self.main_pub, enable=True)} + + def close_context(self): + del self.events + + messaging.toggle_fake_events(False) + messaging.delete_fake_prefix() + + @property + def all_recv_called_events(self): + return [man.recv_called_event for man in self.events.values()] + + @property + def all_recv_ready_events(self): + return [man.recv_ready_event for man in self.events.values()] + + def send_sync(self, pm, endpoint, dat): + self.events[endpoint].recv_called_event.wait() + self.events[endpoint].recv_called_event.clear() + pm.send(endpoint, dat) + self.events[endpoint].recv_ready_event.set() + + def unlock_sockets(self): + expected_sets = len(self.events) + while expected_sets > 0: + index = messaging.wait_for_one_event(self.all_recv_called_events) + self.all_recv_called_events[index].clear() + self.all_recv_ready_events[index].set() + expected_sets -= 1 + + def wait_for_recv_called(self): + messaging.wait_for_one_event(self.all_recv_called_events) + + def wait_for_next_recv(self, trigger_empty_recv): + index = messaging.wait_for_one_event(self.all_recv_called_events) + if self.main_pub is not None and self.main_pub_drained and trigger_empty_recv: + self.all_recv_called_events[index].clear() + self.all_recv_ready_events[index].set() + self.all_recv_called_events[index].wait() + + +@dataclass +class ProcessConfig: + proc_name: str + pubs: list[str] + subs: list[str] + ignore: list[str] + config_callback: Callable | None = None + init_callback: Callable | None = None + should_recv_callback: Callable | None = None + tolerance: float | None = None + processing_time: float = 0.001 + timeout: int = 30 + simulation: bool = True + # Set to service process receives on first + main_pub: str | None = None + main_pub_drained: bool = False + vision_pubs: list[str] = field(default_factory=list) + ignore_alive_pubs: list[str] = field(default_factory=list) + + def __post_init__(self): + # If the process is polling a service, we can just lock that one to speed up replay + if self.main_pub is None and isinstance(self.should_recv_callback, MessageBasedRcvCallback): + self.main_pub = self.should_recv_callback.trigger_msg_type + + +class ProcessContainer: + def __init__(self, cfg: ProcessConfig): + self.prefix = OpenpilotPrefix(create_dirs_on_enter=False, clean_dirs_on_exit=False) + self.cfg = copy.deepcopy(cfg) + self.process = copy.deepcopy(managed_processes[cfg.proc_name]) + self.msg_queue: list[capnp._DynamicStructReader] = [] + self.cnt = 0 + self.pm: messaging.PubMaster | None = None + self.sockets: list[messaging.SubSocket] | None = None + self.rc: ReplayContext | None = None + self.vipc_server: VisionIpcServer | None = None + self.environ_config: dict[str, Any] | None = None + self.capture: ProcessOutputCapture | None = None + + @property + def has_empty_queue(self) -> bool: + return len(self.msg_queue) == 0 + + @property + def pubs(self) -> list[str]: + return self.cfg.pubs + + @property + def subs(self) -> list[str]: + return self.cfg.subs + + def _clean_env(self): + for k in self.environ_config.keys(): + if k in os.environ: + del os.environ[k] + + for k in ["PROC_NAME", "SIMULATION"]: + if k in os.environ: + del os.environ[k] + + def _setup_env(self, params_config: dict[str, Any], environ_config: dict[str, Any]): + for k, v in environ_config.items(): + if len(v) != 0: + os.environ[k] = v + elif k in os.environ: + del os.environ[k] + + os.environ["PROC_NAME"] = self.cfg.proc_name + if self.cfg.simulation: + os.environ["SIMULATION"] = "1" + elif "SIMULATION" in os.environ: + del os.environ["SIMULATION"] + + params = Params() + for k, v in params_config.items(): + if isinstance(v, bool): + params.put_bool(k, v) + else: + params.put(k, v) + + self.environ_config = environ_config + + def _setup_vision_ipc(self, all_msgs: LogIterable, frs: dict[str, Any]): + assert len(self.cfg.vision_pubs) != 0 + + vipc_server = VisionIpcServer("camerad") + streams_metas = available_streams(all_msgs) + for meta in streams_metas: + if meta.camera_state in self.cfg.vision_pubs: + assert frs[meta.camera_state].pix_fmt == 'nv12' + frame_size = (frs[meta.camera_state].w, frs[meta.camera_state].h) + vipc_server.create_buffers(meta.stream, 2, *frame_size) + vipc_server.start_listener() + + self.vipc_server = vipc_server + self.cfg.vision_pubs = [meta.camera_state for meta in streams_metas if meta.camera_state in self.cfg.vision_pubs] + + def _start_process(self): + if self.capture is not None: + self.process.launcher = LauncherWithCapture(self.capture, self.process.launcher) + self.process.prepare() + self.process.start() + + def start( + self, params_config: dict[str, Any], environ_config: dict[str, Any], + all_msgs: LogIterable, frs: dict[str, FrameReader] | None, + fingerprint: str | None, capture_output: bool + ): + with self.prefix as p: + self.prefix.create_dirs() + self._setup_env(params_config, environ_config) + + if self.cfg.config_callback is not None: + params = Params() + self.cfg.config_callback(params, self.cfg, all_msgs) + + self.rc = ReplayContext(self.cfg) + self.rc.open_context() + + self.pm = messaging.PubMaster(self.cfg.pubs) + self.sockets = [messaging.sub_sock(s, timeout=100) for s in self.cfg.subs] + + if len(self.cfg.vision_pubs) != 0: + assert frs is not None + self._setup_vision_ipc(all_msgs, frs) + assert self.vipc_server is not None + + if capture_output: + self.capture = ProcessOutputCapture(self.cfg.proc_name, p.prefix) + + self._start_process() + + if self.cfg.init_callback is not None: + self.cfg.init_callback(self.rc, self.pm, all_msgs, fingerprint) + + def stop(self): + with self.prefix: + self.process.signal(signal.SIGKILL) + self.process.stop() + self.rc.close_context() + self.prefix.clean_dirs() + self._clean_env() + + def get_output_msgs(self, start_time: int): + assert self.rc and self.sockets + + output_msgs = [] + self.rc.wait_for_recv_called() + for socket in self.sockets: + ms = messaging.drain_sock(socket) + for m in ms: + m = m.as_builder() + m.logMonoTime = start_time + int(self.cfg.processing_time * 1e9) + output_msgs.append(m.as_reader()) + return output_msgs + + def run_step(self, msg: capnp._DynamicStructReader, frs: dict[str, FrameReader] | None) -> list[capnp._DynamicStructReader]: + assert self.rc and self.pm and self.sockets and self.process.proc + + output_msgs = [] + end_of_cycle = True + if self.cfg.should_recv_callback is not None: + end_of_cycle = self.cfg.should_recv_callback(msg, self.cfg, self.cnt) + + self.msg_queue.append(msg) + if end_of_cycle: + with self.prefix, Timeout(self.cfg.timeout, error_msg=f"timed out testing process {repr(self.cfg.proc_name)}"): + # call recv to let sub-sockets reconnect, after we know the process is ready + if self.cnt == 0: + for s in self.sockets: + messaging.recv_one_or_none(s) + + # certain processes use drain_sock. need to cause empty recv to break from this loop + trigger_empty_recv = False + if self.cfg.main_pub and self.cfg.main_pub_drained: + trigger_empty_recv = any(m.which() == self.cfg.main_pub for m in self.msg_queue) + + # get output msgs from previous inputs + output_msgs = self.get_output_msgs(msg.logMonoTime) + + for m in self.msg_queue: + self.pm.send(m.which(), m.as_builder()) + # send frames if needed + if self.vipc_server is not None and m.which() in self.cfg.vision_pubs: + camera_state = getattr(m, m.which()) + camera_meta = meta_from_camera_state(m.which()) + assert frs is not None + img = frs[m.which()].get(camera_state.frameId) + self.vipc_server.send(camera_meta.stream, img.flatten().tobytes(), + camera_state.frameId, camera_state.timestampSof, camera_state.timestampEof) + self.msg_queue = [] + + self.rc.unlock_sockets() + if trigger_empty_recv: + self.rc.unlock_sockets() + self.cnt += 1 + assert self.process.proc.is_alive() + + return output_msgs + + +def card_fingerprint_callback(rc, pm, msgs, fingerprint): + print("start fingerprinting") + params = Params() + canmsgs = list(islice((m for m in msgs if m.which() == "can"), 300)) + + # card expects one arbitrary can and pandaState + rc.send_sync(pm, "can", messaging.new_message("can", 1)) + pm.send("pandaStates", messaging.new_message("pandaStates", 1)) + rc.send_sync(pm, "can", messaging.new_message("can", 1)) + rc.wait_for_next_recv(True) + + # fingerprinting is done, when CarParams is set + while params.get("CarParams") is None: + if len(canmsgs) == 0: + raise ValueError("Fingerprinting failed. Run out of can msgs") + + m = canmsgs.pop(0) + rc.send_sync(pm, "can", m.as_builder().to_bytes()) + rc.wait_for_next_recv(True) + + +def get_car_params_callback(rc, pm, msgs, fingerprint): + params = Params() + if fingerprint: + CarInterface = interfaces[fingerprint] + CP = CarInterface.get_non_essential_params(fingerprint) + else: + can_msgs = ([CanData(can.address, can.dat, can.src) for can in m.can] for m in msgs if m.which() == "can") + cached_params_raw = params.get("CarParamsCache") + assert next(can_msgs, None), "CAN messages are required for fingerprinting" + assert os.environ.get("SKIP_FW_QUERY", False) or cached_params_raw is not None, \ + "CarParamsCache is required for fingerprinting. Make sure to keep carParams msgs in the logs." + + def can_recv(wait_for_one: bool = False) -> list[list[CanData]]: + return [next(can_msgs, [])] + + cached_params = None + if cached_params_raw is not None: + with car.CarParams.from_bytes(cached_params_raw) as _cached_params: + cached_params = _cached_params + + CP = get_car(can_recv, lambda _msgs: None, lambda obd: None, params.get_bool("AlphaLongitudinalEnabled"), False, cached_params=cached_params).CP + + params.put("CarParams", CP.to_bytes()) + + +def card_rcv_callback(msg, cfg, frame): + # no sendcan until card is initialized + if msg.which() != "can": + return False + + socks = [ + s for s in cfg.subs if + frame % int(SERVICE_LIST[msg.which()].frequency / SERVICE_LIST[s].frequency) == 0 + ] + if "sendcan" in socks and (frame - 1) < 2000: + socks.remove("sendcan") + return len(socks) > 0 + + +class ModeldCameraSyncRcvCallback: + def __init__(self): + self.road_present = False + self.wide_road_present = False + self.is_dual_camera = True + + def __call__(self, msg, cfg, frame): + self.is_dual_camera = len(cfg.vision_pubs) == 2 + if msg.which() == "roadCameraState": + self.road_present = True + elif msg.which() == "wideRoadCameraState": + self.wide_road_present = True + + if self.road_present and self.wide_road_present: + self.road_present, self.wide_road_present = False, False + return True + elif self.road_present and not self.is_dual_camera: + self.road_present = False + return True + else: + return False + + +class MessageBasedRcvCallback: + def __init__(self, trigger_msg_type: str, first_frame: bool = False): + self.trigger_msg_type = trigger_msg_type + self.first_frame = first_frame + + def __call__(self, msg, cfg, frame): + # publish on first frame or trigger msg + return ((frame - 1) == 0 and self.first_frame) or msg.which() == self.trigger_msg_type + + +def selfdrived_config_callback(params, cfg, lr): + ublox = params.get_bool("UbloxAvailable") + sub_keys = ({"gpsLocation", } if ublox else {"gpsLocationExternal", }) + + cfg.pubs = set(cfg.pubs) - sub_keys + + +CONFIGS = [ + ProcessConfig( + proc_name="selfdrived", + pubs=[ + "carState", "deviceState", "pandaStates", "peripheralState", "liveCalibration", "driverMonitoringState", + "longitudinalPlan", "livePose", "liveDelay", "liveParameters", "radarState", "modelV2", + "driverCameraState", "roadCameraState", "wideRoadCameraState", "managerState", "liveTorqueParameters", + "accelerometer", "gyroscope", "carOutput", "gpsLocationExternal", "gpsLocation", "controlsState", + "carControl", "driverAssistance", "alertDebug", "audioFeedback", + ], + subs=["selfdriveState", "onroadEvents"], + ignore=["logMonoTime"], + config_callback=selfdrived_config_callback, + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("carState", True), + tolerance=NUMPY_TOLERANCE, + processing_time=0.004, + ), + ProcessConfig( + proc_name="controlsd", + pubs=["liveParameters", "liveTorqueParameters", "modelV2", "selfdriveState", + "liveCalibration", "livePose", "longitudinalPlan", "carState", "carOutput", + "driverMonitoringState", "onroadEvents", "driverAssistance"], + subs=["carControl", "controlsState"], + ignore=["logMonoTime", ], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("selfdriveState"), + tolerance=NUMPY_TOLERANCE, + ), + ProcessConfig( + proc_name="card", + pubs=["pandaStates", "carControl", "onroadEvents", "can"], + subs=["sendcan", "carState", "carParams", "carOutput", "liveTracks"], + ignore=["logMonoTime", "carState.cumLagMs"], + init_callback=card_fingerprint_callback, + should_recv_callback=card_rcv_callback, + tolerance=NUMPY_TOLERANCE, + processing_time=0.004, + main_pub="can", + main_pub_drained=True, + ), + ProcessConfig( + proc_name="radard", + pubs=["liveTracks", "carState", "modelV2"], + subs=["radarState"], + ignore=["logMonoTime"], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("modelV2"), + ), + ProcessConfig( + proc_name="plannerd", + pubs=["modelV2", "carControl", "carState", "controlsState", "liveParameters", "radarState", "selfdriveState"], + subs=["longitudinalPlan", "driverAssistance"], + ignore=["logMonoTime", "longitudinalPlan.processingDelay", "longitudinalPlan.solverExecutionTime"], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("modelV2"), + tolerance=NUMPY_TOLERANCE, + ), + ProcessConfig( + proc_name="calibrationd", + pubs=["carState", "cameraOdometry"], + subs=["liveCalibration"], + ignore=["logMonoTime"], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("cameraOdometry", True), + ), + ProcessConfig( + proc_name="dmonitoringd", + pubs=["driverStateV2", "liveCalibration", "carState", "modelV2", "selfdriveState"], + subs=["driverMonitoringState"], + ignore=["logMonoTime"], + should_recv_callback=MessageBasedRcvCallback("driverStateV2"), + tolerance=NUMPY_TOLERANCE, + ), + ProcessConfig( + proc_name="locationd", + pubs=[ + "cameraOdometry", "accelerometer", "gyroscope", "liveCalibration", "carState" + ], + subs=["livePose"], + ignore=["logMonoTime"], + should_recv_callback=MessageBasedRcvCallback("cameraOdometry"), + tolerance=NUMPY_TOLERANCE, + ), + ProcessConfig( + proc_name="paramsd", + pubs=["livePose", "liveCalibration", "carState"], + subs=["liveParameters"], + ignore=["logMonoTime"], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("livePose"), + tolerance=NUMPY_TOLERANCE, + processing_time=0.004, + ), + ProcessConfig( + proc_name="lagd", + pubs=["livePose", "liveCalibration", "carState", "carControl", "controlsState"], + subs=["liveDelay"], + ignore=["logMonoTime"], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("livePose"), + tolerance=NUMPY_TOLERANCE, + ), + ProcessConfig( + proc_name="ubloxd", + pubs=["ubloxRaw"], + subs=["ubloxGnss", "gpsLocationExternal"], + ignore=["logMonoTime"], + ), + ProcessConfig( + proc_name="torqued", + pubs=["livePose", "liveCalibration", "liveDelay", "carState", "carControl", "carOutput"], + subs=["liveTorqueParameters"], + ignore=["logMonoTime"], + init_callback=get_car_params_callback, + should_recv_callback=MessageBasedRcvCallback("livePose", True), + tolerance=NUMPY_TOLERANCE, + ), + ProcessConfig( + proc_name="modeld", + pubs=["deviceState", "roadCameraState", "wideRoadCameraState", "liveCalibration", "liveDelay", "driverMonitoringState", "carState", "carControl"], + subs=["modelV2", "drivingModelData", "cameraOdometry"], + ignore=["logMonoTime", "modelV2.frameDropPerc", "modelV2.modelExecutionTime", "drivingModelData.frameDropPerc", "drivingModelData.modelExecutionTime"], + should_recv_callback=ModeldCameraSyncRcvCallback(), + tolerance=NUMPY_TOLERANCE, + processing_time=0.020, + main_pub=vipc_get_endpoint_name("camerad", meta_from_camera_state("roadCameraState").stream), + vision_pubs=["roadCameraState", "wideRoadCameraState"], + ignore_alive_pubs=["wideRoadCameraState"], + init_callback=get_car_params_callback, + ), + ProcessConfig( + proc_name="dmonitoringmodeld", + pubs=["liveCalibration", "driverCameraState"], + subs=["driverStateV2"], + ignore=["logMonoTime", "driverStateV2.modelExecutionTime", "driverStateV2.gpuExecutionTime"], + should_recv_callback=MessageBasedRcvCallback("driverCameraState"), + tolerance=NUMPY_TOLERANCE, + processing_time=0.020, + main_pub=vipc_get_endpoint_name("camerad", meta_from_camera_state("driverCameraState").stream), + vision_pubs=["driverCameraState"], + ignore_alive_pubs=["driverCameraState"], + ), +] + + +def get_process_config(name: str) -> ProcessConfig: + try: + return copy.deepcopy(next(c for c in CONFIGS if c.proc_name == name)) + except StopIteration as ex: + raise Exception(f"Cannot find process config with name: {name}") from ex + + +def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> dict[str, Any]: + """ + Use this to get custom params dict based on provided logs. + Useful when replaying following processes: calibrationd, paramsd, torqued + The params may be based on first or last message of given type (carParams, liveCalibration, liveParameters, liveTorqueParameters) in the logs. + """ + + car_params = [m for m in lr if m.which() == "carParams"] + live_calibration = [m for m in lr if m.which() == "liveCalibration"] + live_parameters = [m for m in lr if m.which() == "liveParameters"] + live_torque_parameters = [m for m in lr if m.which() == "liveTorqueParameters"] + + assert initial_state in ["first", "last"] + msg_index = 0 if initial_state == "first" else -1 + + assert len(car_params) > 0, "carParams required for initial state of liveParameters and CarParamsPrevRoute" + CP = car_params[msg_index].carParams + + custom_params = { + "CarParamsPrevRoute": CP.as_builder().to_bytes() + } + + if len(live_calibration) > 0: + custom_params["CalibrationParams"] = live_calibration[msg_index].as_builder().to_bytes() + if len(live_parameters) > 0: + custom_params["LiveParametersV2"] = live_parameters[msg_index].as_builder().to_bytes() + if len(live_torque_parameters) > 0: + custom_params["LiveTorqueParameters"] = live_torque_parameters[msg_index].as_builder().to_bytes() + + return custom_params + + +def replay_process_with_name(name: str | Iterable[str], lr: LogIterable, *args, **kwargs) -> list[capnp._DynamicStructReader]: + if isinstance(name, str): + cfgs = [get_process_config(name)] + elif isinstance(name, Iterable): + cfgs = [get_process_config(n) for n in name] + else: + raise ValueError("name must be str or collections of strings") + + return replay_process(cfgs, lr, *args, **kwargs) + + +def replay_process( + cfg: ProcessConfig | Iterable[ProcessConfig], lr: LogIterable, frs: dict[str, FrameReader] = None, + fingerprint: str = None, return_all_logs: bool = False, custom_params: dict[str, Any] = None, + captured_output_store: dict[str, dict[str, str]] = None, disable_progress: bool = False +) -> list[capnp._DynamicStructReader]: + if isinstance(cfg, Iterable): + cfgs = list(cfg) + else: + cfgs = [cfg] + + all_msgs = migrate_all(lr, + manager_states=True, + panda_states=any("pandaStates" in cfg.pubs for cfg in cfgs), + camera_states=any(len(cfg.vision_pubs) != 0 for cfg in cfgs)) + process_logs = _replay_multi_process(cfgs, all_msgs, frs, fingerprint, custom_params, captured_output_store, disable_progress) + + if return_all_logs: + keys = {m.which() for m in process_logs} + modified_logs = [m for m in all_msgs if m.which() not in keys] + modified_logs.extend(process_logs) + modified_logs.sort(key=lambda m: int(m.logMonoTime)) + log_msgs = modified_logs + else: + log_msgs = process_logs + + return log_msgs + + +def _replay_multi_process( + cfgs: list[ProcessConfig], lr: LogIterable, frs: dict[str, FrameReader] | None, fingerprint: str | None, + custom_params: dict[str, Any] | None, captured_output_store: dict[str, dict[str, str]] | None, disable_progress: bool +) -> list[capnp._DynamicStructReader]: + if fingerprint is not None: + params_config = generate_params_config(lr=lr, fingerprint=fingerprint, custom_params=custom_params) + env_config = generate_environ_config(fingerprint=fingerprint) + else: + CP = next((m.carParams for m in lr if m.which() == "carParams"), None) + params_config = generate_params_config(lr=lr, CP=CP, custom_params=custom_params) + env_config = generate_environ_config(CP=CP) + + # validate frs and vision pubs + all_vision_pubs = [pub for cfg in cfgs for pub in cfg.vision_pubs] + if len(all_vision_pubs) != 0: + assert frs is not None, "frs must be provided when replaying process using vision streams" + assert all(meta_from_camera_state(st) is not None for st in all_vision_pubs), \ + f"undefined vision stream spotted, probably misconfigured process: (vision pubs: {all_vision_pubs})" + required_vision_pubs = {m.camera_state for m in available_streams(lr)} & set(all_vision_pubs) + assert all(st in frs for st in required_vision_pubs), f"frs for this process must contain following vision streams: {required_vision_pubs}" + + all_msgs = sorted(lr, key=lambda msg: msg.logMonoTime) + log_msgs = [] + containers = [] + try: + for cfg in cfgs: + container = ProcessContainer(cfg) + containers.append(container) + container.start(params_config, env_config, all_msgs, frs, fingerprint, captured_output_store is not None) + + all_pubs = {pub for container in containers for pub in container.pubs} + all_subs = {sub for container in containers for sub in container.subs} + lr_pubs = all_pubs - all_subs + pubs_to_containers = {pub: [container for container in containers if pub in container.pubs] for pub in all_pubs} + + pub_msgs = [msg for msg in all_msgs if msg.which() in lr_pubs] + # external queue for messages taken from logs; internal queue for messages generated by processes, which will be republished + external_pub_queue: list[capnp._DynamicStructReader] = pub_msgs.copy() + internal_pub_queue: list[capnp._DynamicStructReader] = [] + # heap for maintaining the order of messages generated by processes, where each element: (logMonoTime, index in internal_pub_queue) + internal_pub_index_heap: list[tuple[int, int]] = [] + + pbar = tqdm(total=len(external_pub_queue), disable=disable_progress) + while len(external_pub_queue) != 0 or (len(internal_pub_index_heap) != 0 and not all(c.has_empty_queue for c in containers)): + if len(internal_pub_index_heap) == 0 or (len(external_pub_queue) != 0 and external_pub_queue[0].logMonoTime < internal_pub_index_heap[0][0]): + msg = external_pub_queue.pop(0) + pbar.update(1) + else: + _, index = heapq.heappop(internal_pub_index_heap) + msg = internal_pub_queue[index] + + target_containers = pubs_to_containers[msg.which()] + for container in target_containers: + output_msgs = container.run_step(msg, frs) + for m in output_msgs: + if m.which() in all_pubs: + internal_pub_queue.append(m) + heapq.heappush(internal_pub_index_heap, (m.logMonoTime, len(internal_pub_queue) - 1)) + log_msgs.extend(output_msgs) + + # flush last set of messages from each process + for container in containers: + last_time = log_msgs[-1].logMonoTime if len(log_msgs) > 0 else int(time.monotonic() * 1e9) + log_msgs.extend(container.get_output_msgs(last_time)) + finally: + for container in containers: + container.stop() + if captured_output_store is not None: + assert container.capture is not None + out, err = container.capture.read_outerr() + captured_output_store[container.cfg.proc_name] = {"out": out, "err": err} + + return log_msgs + + +def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=None) -> dict[str, Any]: + params_dict = { + "OpenpilotEnabledToggle": True, + "DisengageOnAccelerator": True, + "DisableLogging": False, + } + + if custom_params is not None: + params_dict.update(custom_params) + if lr is not None: + has_ublox = any(msg.which() == "ubloxGnss" for msg in lr) + params_dict["UbloxAvailable"] = has_ublox + is_rhd = next((msg.driverMonitoringState.isRHD for msg in lr if msg.which() == "driverMonitoringState"), False) + params_dict["IsRhdDetected"] = is_rhd + + if CP is not None: + if fingerprint is None: + if CP.fingerprintSource == "fw": + params_dict["CarParamsCache"] = CP.as_builder().to_bytes() + + if CP.openpilotLongitudinalControl: + params_dict["AlphaLongitudinalEnabled"] = True + + if CP.notCar: + params_dict["JoystickDebugMode"] = True + + return params_dict + + +def generate_environ_config(CP=None, fingerprint=None, log_dir=None) -> dict[str, Any]: + environ_dict = {} + environ_dict["PARAMS_ROOT"] = f"{Paths.shm_path()}/params" + if log_dir is not None: + environ_dict["LOG_ROOT"] = log_dir + + environ_dict["REPLAY"] = "1" + + # Regen or python process + if CP is not None and fingerprint is None: + if CP.fingerprintSource == "fw": + environ_dict['SKIP_FW_QUERY'] = "" + environ_dict['FINGERPRINT'] = "" + else: + environ_dict['SKIP_FW_QUERY'] = "1" + environ_dict['FINGERPRINT'] = CP.carFingerprint + elif fingerprint is not None: + environ_dict['SKIP_FW_QUERY'] = "1" + environ_dict['FINGERPRINT'] = fingerprint + else: + environ_dict["SKIP_FW_QUERY"] = "" + environ_dict["FINGERPRINT"] = "" + + return environ_dict + + +def check_openpilot_enabled(msgs: LogIterable) -> bool: + cur_enabled_count = 0 + max_enabled_count = 0 + for msg in msgs: + if msg.which() == "carParams": + if msg.carParams.notCar: + return True + elif msg.which() == "selfdriveState": + if msg.selfdriveState.active: + cur_enabled_count += 1 + else: + cur_enabled_count = 0 + max_enabled_count = max(max_enabled_count, cur_enabled_count) + + return max_enabled_count > int(10. / DT_CTRL) + + +def check_most_messages_valid(msgs: LogIterable, threshold: float = 0.9) -> bool: + relevant_services = {sock for cfg in CONFIGS for sock in cfg.subs} + msgs_counts = Counter(msg.which() for msg in msgs) + msgs_valid_counts = Counter(msg.which() for msg in msgs if msg.valid) + + most_valid_for_service = {} + for msg_type in msgs_counts.keys(): + if msg_type not in relevant_services: + continue + + valid_share = msgs_valid_counts.get(msg_type, 0) / msgs_counts[msg_type] + ok = valid_share >= threshold + if not ok: + print(f"WARNING: Service {msg_type} has {valid_share * 100:.2f}% valid messages, which is below threshold of {threshold * 100:.2f}%") + most_valid_for_service[msg_type] = ok + + return all(most_valid_for_service.values()) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit new file mode 100644 index 0000000000..a833fadb94 --- /dev/null +++ b/selfdrive/test/process_replay/ref_commit @@ -0,0 +1 @@ +afcab1abb62b9d5678342956cced4712f44e909e \ No newline at end of file diff --git a/selfdrive/test/process_replay/regen.py b/selfdrive/test/process_replay/regen.py new file mode 100755 index 0000000000..ec35a5c3ac --- /dev/null +++ b/selfdrive/test/process_replay/regen.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +import os +import argparse +import time +import capnp + +from typing import Any +from collections.abc import Iterable + +from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, ProcessConfig, replay_process, get_process_config, \ + check_openpilot_enabled, check_most_messages_valid, get_custom_params_from_lr +from openpilot.selfdrive.test.update_ci_routes import upload_route +from openpilot.tools.lib.framereader import FrameReader +from openpilot.tools.lib.logreader import LogReader, LogIterable, save_log +from openpilot.tools.lib.openpilotci import get_url + + +def regen_segment( + lr: LogIterable, frs: dict[str, Any] = None, + processes: Iterable[ProcessConfig] = CONFIGS, disable_tqdm: bool = False +) -> list[capnp._DynamicStructReader]: + all_msgs = sorted(lr, key=lambda m: m.logMonoTime) + custom_params = get_custom_params_from_lr(all_msgs) + + print("Replayed processes:", [p.proc_name for p in processes]) + print("\n\n", "*"*30, "\n\n", sep="") + + output_logs = replay_process(processes, all_msgs, frs, return_all_logs=True, custom_params=custom_params, disable_progress=disable_tqdm) + + return output_logs + + +def setup_data_readers( + route: str, sidx: int, needs_driver_cam: bool = True, needs_road_cam: bool = True, dummy_driver_cam: bool = False +) -> tuple[LogReader, dict[str, Any]]: + lr = LogReader(f"{route}/{sidx}/r") + frs = {} + if needs_road_cam: + frs['roadCameraState'] = FrameReader(get_url(route, str(sidx), "fcamera.hevc")) + if next((True for m in lr if m.which() == "wideRoadCameraState"), False): + frs['wideRoadCameraState'] = FrameReader(get_url(route, str(sidx), "ecamera.hevc")) + if needs_driver_cam: + if dummy_driver_cam: + frs['driverCameraState'] = FrameReader(get_url(route, str(sidx), "fcamera.hevc")) # Use fcam as dummy + else: + device_type = next(str(msg.initData.deviceType) for msg in lr if msg.which() == "initData") + assert device_type != "neo", "Driver camera not supported on neo segments. Use dummy dcamera." + frs['driverCameraState'] = FrameReader(get_url(route, str(sidx), "dcamera.hevc")) + + return lr, frs + + +def regen_and_save( + route: str, sidx: int, processes: str | Iterable[str] = "all", outdir: str = FAKEDATA, + upload: bool = False, disable_tqdm: bool = False, dummy_driver_cam: bool = False +) -> str: + if not isinstance(processes, str) and not hasattr(processes, "__iter__"): + raise ValueError("whitelist_proc must be a string or iterable") + + if processes != "all": + if isinstance(processes, str): + raise ValueError(f"Invalid value for processes: {processes}") + + replayed_processes = [] + for d in processes: + cfg = get_process_config(d) + replayed_processes.append(cfg) + else: + replayed_processes = CONFIGS + + all_vision_pubs = {pub for cfg in replayed_processes for pub in cfg.vision_pubs} + lr, frs = setup_data_readers(route, sidx, + needs_driver_cam="driverCameraState" in all_vision_pubs, + needs_road_cam="roadCameraState" in all_vision_pubs or "wideRoadCameraState" in all_vision_pubs, + dummy_driver_cam=dummy_driver_cam) + output_logs = regen_segment(lr, frs, replayed_processes, disable_tqdm=disable_tqdm) + + log_dir = os.path.join(outdir, time.strftime("%Y-%m-%d--%H-%M-%S--0", time.gmtime())) + rel_log_dir = os.path.relpath(log_dir) + rpath = os.path.join(log_dir, "rlog.zst") + + os.makedirs(log_dir) + save_log(rpath, output_logs, compress=True) + + print("\n\n", "*"*30, "\n\n", sep="") + print("New route:", rel_log_dir, "\n") + + if not check_openpilot_enabled(output_logs): + raise Exception("Route did not engage for long enough") + if not check_most_messages_valid(output_logs): + raise Exception("Route has too many invalid messages") + + if upload: + upload_route(rel_log_dir) + + return rel_log_dir + + +if __name__ == "__main__": + def comma_separated_list(string): + return string.split(",") + + all_procs = [p.proc_name for p in CONFIGS] + parser = argparse.ArgumentParser(description="Generate new segments from old ones") + parser.add_argument("--upload", action="store_true", help="Upload the new segment to the CI bucket") + parser.add_argument("--outdir", help="log output dir", default=FAKEDATA) + parser.add_argument("--dummy-dcamera", action='store_true', help="Use dummy blank driver camera") + parser.add_argument("--whitelist-procs", type=comma_separated_list, default=all_procs, + help="Comma-separated whitelist of processes to regen (e.g. controlsd,radard)") + parser.add_argument("--blacklist-procs", type=comma_separated_list, default=[], + help="Comma-separated blacklist of processes to regen (e.g. controlsd,radard)") + parser.add_argument("route", type=str, help="The source route") + parser.add_argument("seg", type=int, help="Segment in source route") + args = parser.parse_args() + + blacklist_set = set(args.blacklist_procs) + processes = [p for p in args.whitelist_procs if p not in blacklist_set] + regen_and_save(args.route, args.seg, processes=processes, upload=args.upload, outdir=args.outdir, dummy_driver_cam=args.dummy_dcamera) diff --git a/selfdrive/test/process_replay/regen_all.py b/selfdrive/test/process_replay/regen_all.py new file mode 100755 index 0000000000..78a90b420c --- /dev/null +++ b/selfdrive/test/process_replay/regen_all.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import argparse +import concurrent.futures +import os +import random +import traceback +from tqdm import tqdm + +from openpilot.common.prefix import OpenpilotPrefix +from openpilot.selfdrive.test.process_replay.regen import regen_and_save +from openpilot.selfdrive.test.process_replay.test_processes import FAKEDATA, source_segments as segments +from openpilot.tools.lib.route import SegmentName + + +def regen_job(segment, upload, disable_tqdm): + with OpenpilotPrefix(): + sn = SegmentName(segment[1]) + fake_dongle_id = 'regen' + ''.join(random.choice('0123456789ABCDEF') for _ in range(11)) + try: + relr = regen_and_save(sn.route_name.canonical_name, sn.segment_num, upload=upload, + outdir=os.path.join(FAKEDATA, fake_dongle_id), disable_tqdm=disable_tqdm, dummy_driver_cam=True) + relr = '|'.join(relr.split('/')[-2:]) + return f' ("{segment[0]}", "{relr}"), ' + except Exception as e: + err = f" {segment} failed: {str(e)}" + err += traceback.format_exc() + err += "\n\n" + return err + + +if __name__ == "__main__": + all_cars = {car for car, _ in segments} + + parser = argparse.ArgumentParser(description="Generate new segments from old ones") + parser.add_argument("-j", "--jobs", type=int, default=1) + parser.add_argument("--no-upload", action="store_true") + parser.add_argument("--whitelist-cars", type=str, nargs="*", default=all_cars, + help="Whitelist given cars from the test (e.g. HONDA)") + parser.add_argument("--blacklist-cars", type=str, nargs="*", default=[], + help="Blacklist given cars from the test (e.g. HONDA)") + args = parser.parse_args() + + tested_cars = set(args.whitelist_cars) - set(args.blacklist_cars) + tested_cars = {c.upper() for c in tested_cars} + tested_segments = [(car, segment) for car, segment in segments if car in tested_cars] + + with concurrent.futures.ProcessPoolExecutor(max_workers=args.jobs) as pool: + p = pool.map(regen_job, tested_segments, [not args.no_upload] * len(tested_segments), [args.jobs > 1] * len(tested_segments)) + msg = "Copy these new segments into test_processes.py:" + for seg in tqdm(p, desc="Generating segments", total=len(tested_segments)): + msg += "\n" + str(seg) + print() + print() + print(msg) diff --git a/selfdrive/test/process_replay/test_fuzzy.py b/selfdrive/test/process_replay/test_fuzzy.py new file mode 100644 index 0000000000..723112163e --- /dev/null +++ b/selfdrive/test/process_replay/test_fuzzy.py @@ -0,0 +1,31 @@ +import copy +import os +from hypothesis import given, HealthCheck, Phase, settings +import hypothesis.strategies as st +from parameterized import parameterized + +from cereal import log +from opendbc.car.toyota.values import CAR as TOYOTA +from openpilot.selfdrive.test.fuzzy_generation import FuzzyGenerator +import openpilot.selfdrive.test.process_replay.process_replay as pr + +# These processes currently fail because of unrealistic data breaking assumptions +# that openpilot makes causing error with NaN, inf, int size, array indexing ... +# TODO: Make each one testable +NOT_TESTED = ['selfdrived', 'controlsd', 'card', 'plannerd', 'calibrationd', 'dmonitoringd', 'paramsd', 'dmonitoringmodeld', 'modeld'] + +TEST_CASES = [(cfg.proc_name, copy.deepcopy(cfg)) for cfg in pr.CONFIGS if cfg.proc_name not in NOT_TESTED] +MAX_EXAMPLES = int(os.environ.get("MAX_EXAMPLES", "10")) + +class TestFuzzProcesses: + + # TODO: make this faster and increase examples + @parameterized.expand(TEST_CASES) + @given(st.data()) + @settings(phases=[Phase.generate, Phase.target], max_examples=MAX_EXAMPLES, deadline=1000, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large]) + def test_fuzz_process(self, proc_name, cfg, data): + msgs = FuzzyGenerator.get_random_event_msg(data.draw, events=cfg.pubs, real_floats=True) + lr = [log.Event.new_message(**m).as_reader() for m in msgs] + cfg.timeout = 5 + pr.replay_process(cfg, lr, fingerprint=TOYOTA.TOYOTA_COROLLA_TSS2, disable_progress=True) diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py new file mode 100755 index 0000000000..5868ca4c1c --- /dev/null +++ b/selfdrive/test/process_replay/test_processes.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +import argparse +import concurrent.futures +import os +import sys +from collections import defaultdict +from tqdm import tqdm +from typing import Any + +from opendbc.car.car_helpers import interface_names +from openpilot.common.git import get_commit +from openpilot.tools.lib.openpilotci import get_url, upload_file +from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff +from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, PROC_REPLAY_DIR, FAKEDATA, replay_process, \ + check_most_messages_valid +from openpilot.tools.lib.filereader import FileReader +from openpilot.tools.lib.logreader import LogReader, save_log + +source_segments = [ + ("HYUNDAI", "02c45f73a2e5c6e9|2021-01-01--19-08-22--1"), # HYUNDAI.HYUNDAI_SONATA + ("HYUNDAI2", "d545129f3ca90f28|2022-11-07--20-43-08--3"), # HYUNDAI.HYUNDAI_KIA_EV6 (+ QCOM GPS) + ("TOYOTA", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.TOYOTA_PRIUS + ("TOYOTA2", "0982d79ebb0de295|2021-01-03--20-03-36--6"), # TOYOTA.TOYOTA_RAV4 + ("TOYOTA3", "8011d605be1cbb77|000000cc--8e8d8ec716--6"), # TOYOTA.TOYOTA_COROLLA_TSS2 + ("HONDA", "eb140f119469d9ab|2021-06-12--10-46-24--27"), # HONDA.HONDA_CIVIC (NIDEC) + ("HONDA2", "7d2244f34d1bbcda|2021-06-25--12-25-37--26"), # HONDA.HONDA_ACCORD (BOSCH) + ("CHRYSLER", "4deb27de11bee626|2021-02-20--11-28-55--8"), # CHRYSLER.CHRYSLER_PACIFICA_2018_HYBRID + ("RAM", "17fc16d840fe9d21|2023-04-26--13-28-44--5"), # CHRYSLER.RAM_1500_5TH_GEN + ("SUBARU", "341dccd5359e3c97|2022-09-12--10-35-33--3"), # SUBARU.SUBARU_OUTBACK + ("GM", "376bf99325883932|2022-10-27--13-41-22--1"), # GM.CHEVROLET_BOLT_EUV + ("NISSAN", "35336926920f3571|2021-02-12--18-38-48--46"), # NISSAN.NISSAN_XTRAIL + ("VOLKSWAGEN", "de9592456ad7d144|2021-06-29--11-00-15--6"), # VOLKSWAGEN.VOLKSWAGEN_GOLF + # FIXME the sensor timings are bad in mazda segment, we're not fully testing it, but it should be replaced + ("MAZDA", "bd6a637565e91581|2021-10-30--15-14-53--4"), # MAZDA.MAZDA_CX9_2021 + ("FORD", "54827bf84c38b14f|2023-01-26--21-59-07--4"), # FORD.FORD_BRONCO_SPORT_MK1 + ("RIVIAN", "bc095dc92e101734|000000db--ee9fe46e57--1"), # RIVIAN.RIVIAN_R1_GEN1 + ("TESLA", "2c912ca5de3b1ee9|0000025d--6eb6bcbca4--4"), # TESLA.TESLA_MODEL_Y + + # Enable when port is tested and dashcamOnly is no longer set + #("VOLKSWAGEN2", "3cfdec54aa035f3f|2022-07-19--23-45-10--2"), # VOLKSWAGEN.VOLKSWAGEN_PASSAT_NMS +] + +segments = [ + ("HYUNDAI", "regenAA0FC4ED71E|2025-04-08--22-57-50--0"), + ("HYUNDAI2", "regenAFB9780D823|2025-04-08--23-00-34--0"), + ("TOYOTA", "regen218A4DCFAA1|2025-04-08--22-57-51--0"), + ("TOYOTA2", "regen107352E20EB|2025-04-08--22-57-46--0"), + ("TOYOTA3", "regen1455E3B4BDF|2025-04-09--03-26-06--0"), + ("HONDA", "regenB328FF8BA0A|2025-04-08--22-57-45--0"), + ("HONDA2", "regen6170C8C9A35|2025-04-08--22-57-46--0"), + ("CHRYSLER", "regen5B28FC2A437|2025-04-08--23-04-24--0"), + ("RAM", "regenBF81EA96E08|2025-04-08--23-06-54--0"), + ("SUBARU", "regen7366F13F6A1|2025-04-08--23-07-07--0"), + ("GM", "regen1271097D038|2025-04-09--03-26-00--0"), + ("NISSAN", "regen15D60604EAB|2025-04-08--23-06-59--0"), + ("VOLKSWAGEN", "regen0F2F06C9539|2025-04-08--23-06-56--0"), + ("MAZDA", "regenACF84CCF482|2024-08-30--03-21-55--0"), + ("FORD", "regen755D8CB1E1F|2025-04-08--23-13-43--0"), + ("RIVIAN", "regen5FCAC896BBE|2025-04-08--23-13-35--0"), + ("TESLA", "2c912ca5de3b1ee9|0000025d--6eb6bcbca4--4"), +] + +# dashcamOnly makes don't need to be tested until a full port is done +excluded_interfaces = ["mock", "body", "psa"] + +BASE_URL = "https://commadataci.blob.core.windows.net/openpilotci/" +REF_COMMIT_FN = os.path.join(PROC_REPLAY_DIR, "ref_commit") +EXCLUDED_PROCS = {"modeld", "dmonitoringmodeld"} + + +def run_test_process(data): + segment, cfg, args, cur_log_fn, ref_log_path, lr_dat = data + res = None + if not args.upload_only: + lr = LogReader.from_bytes(lr_dat) + res, log_msgs = test_process(cfg, lr, segment, ref_log_path, cur_log_fn, args.ignore_fields, args.ignore_msgs) + # save logs so we can upload when updating refs + save_log(cur_log_fn, log_msgs) + + if args.update_refs or args.upload_only: + print(f'Uploading: {os.path.basename(cur_log_fn)}') + assert os.path.exists(cur_log_fn), f"Cannot find log to upload: {cur_log_fn}" + upload_file(cur_log_fn, os.path.basename(cur_log_fn)) + os.remove(cur_log_fn) + return (segment, cfg.proc_name, res) + + +def get_log_data(segment): + r, n = segment.rsplit("--", 1) + with FileReader(get_url(r, n, "rlog.zst")) as f: + return (segment, f.read()) + + +def test_process(cfg, lr, segment, ref_log_path, new_log_path, ignore_fields=None, ignore_msgs=None): + if ignore_fields is None: + ignore_fields = [] + if ignore_msgs is None: + ignore_msgs = [] + + ref_log_msgs = list(LogReader(ref_log_path)) + + try: + log_msgs = replay_process(cfg, lr, disable_progress=True) + except Exception as e: + raise Exception("failed on segment: " + segment) from e + + if not check_most_messages_valid(log_msgs): + return f"Route did not have enough valid messages: {new_log_path}", log_msgs + + # skip this check if the segment is using qcom gps + if cfg.proc_name != 'ubloxd' or any(m.which() in cfg.pubs for m in lr): + seen_msgs = {m.which() for m in log_msgs} + expected_msgs = set(cfg.subs) + if seen_msgs != expected_msgs: + return f"Expected messages: {expected_msgs}, but got: {seen_msgs}", log_msgs + + try: + return compare_logs(ref_log_msgs, log_msgs, ignore_fields + cfg.ignore, ignore_msgs, cfg.tolerance), log_msgs + except Exception as e: + return str(e), log_msgs + + +if __name__ == "__main__": + all_cars = {car for car, _ in segments} + all_procs = {cfg.proc_name for cfg in CONFIGS if cfg.proc_name not in EXCLUDED_PROCS} + + cpu_count = os.cpu_count() or 1 + + parser = argparse.ArgumentParser(description="Regression test to identify changes in a process's output") + parser.add_argument("--whitelist-procs", type=str, nargs="*", default=all_procs, + help="Whitelist given processes from the test (e.g. controlsd)") + parser.add_argument("--whitelist-cars", type=str, nargs="*", default=all_cars, + help="Whitelist given cars from the test (e.g. HONDA)") + parser.add_argument("--blacklist-procs", type=str, nargs="*", default=[], + help="Blacklist given processes from the test (e.g. controlsd)") + parser.add_argument("--blacklist-cars", type=str, nargs="*", default=[], + help="Blacklist given cars from the test (e.g. HONDA)") + parser.add_argument("--ignore-fields", type=str, nargs="*", default=[], + help="Extra fields or msgs to ignore (e.g. driverMonitoringState.events)") + parser.add_argument("--ignore-msgs", type=str, nargs="*", default=[], + help="Msgs to ignore (e.g. carEvents)") + parser.add_argument("--update-refs", action="store_true", + help="Updates reference logs using current commit") + parser.add_argument("--upload-only", action="store_true", + help="Skips testing processes and uploads logs from previous test run") + parser.add_argument("-j", "--jobs", type=int, default=max(cpu_count - 2, 1), + help="Max amount of parallel jobs") + args = parser.parse_args() + + tested_procs = set(args.whitelist_procs) - set(args.blacklist_procs) + tested_cars = set(args.whitelist_cars) - set(args.blacklist_cars) + tested_cars = {c.upper() for c in tested_cars} + + full_test = (tested_procs == all_procs) and (tested_cars == all_cars) and all(len(x) == 0 for x in (args.ignore_fields, args.ignore_msgs)) + upload = args.update_refs or args.upload_only + os.makedirs(os.path.dirname(FAKEDATA), exist_ok=True) + + if upload: + assert full_test, "Need to run full test when updating refs" + + try: + with open(REF_COMMIT_FN) as f: + ref_commit = f.read().strip() + except FileNotFoundError: + print("Couldn't find reference commit") + sys.exit(1) + + cur_commit = get_commit() + if not cur_commit: + raise Exception("Couldn't get current commit") + + print(f"***** testing against commit {ref_commit} *****") + + # check to make sure all car brands are tested + if full_test: + untested = (set(interface_names) - set(excluded_interfaces)) - {c.lower() for c in tested_cars} + assert len(untested) == 0, f"Cars missing routes: {str(untested)}" + + log_paths: defaultdict[str, dict[str, dict[str, str]]] = defaultdict(lambda: defaultdict(dict)) + with concurrent.futures.ProcessPoolExecutor(max_workers=args.jobs) as pool: + if not args.upload_only: + download_segments = [seg for car, seg in segments if car in tested_cars] + log_data: dict[str, LogReader] = {} + p1 = pool.map(get_log_data, download_segments) + for segment, lr in tqdm(p1, desc="Getting Logs", total=len(download_segments)): + log_data[segment] = lr + + pool_args: Any = [] + for car_brand, segment in segments: + if car_brand not in tested_cars: + continue + + for cfg in CONFIGS: + if cfg.proc_name not in tested_procs: + continue + + # to speed things up, we only test all segments on card + if cfg.proc_name not in ('card', 'controlsd', 'lagd') and car_brand not in ('HYUNDAI', 'TOYOTA'): + continue + + cur_log_fn = os.path.join(FAKEDATA, f"{segment}_{cfg.proc_name}_{cur_commit}.zst") + if args.update_refs: # reference logs will not exist if routes were just regenerated + ref_log_path = get_url(*segment.rsplit("--", 1,), "rlog.zst") + else: + ref_log_fn = os.path.join(FAKEDATA, f"{segment}_{cfg.proc_name}_{ref_commit}.zst") + ref_log_path = ref_log_fn if os.path.exists(ref_log_fn) else BASE_URL + os.path.basename(ref_log_fn) + + dat = None if args.upload_only else log_data[segment] + pool_args.append((segment, cfg, args, cur_log_fn, ref_log_path, dat)) + + log_paths[segment][cfg.proc_name]['ref'] = ref_log_path + log_paths[segment][cfg.proc_name]['new'] = cur_log_fn + + results: Any = defaultdict(dict) + p2 = pool.map(run_test_process, pool_args) + for (segment, proc, result) in tqdm(p2, desc="Running Tests", total=len(pool_args)): + if not args.upload_only: + results[segment][proc] = result + + diff_short, diff_long, failed = format_diff(results, log_paths, ref_commit) + if not upload: + with open(os.path.join(PROC_REPLAY_DIR, "diff.txt"), "w") as f: + f.write(diff_long) + print(diff_short) + + if failed: + print("TEST FAILED") + print("\n\nTo push the new reference logs for this commit run:") + print("./test_processes.py --upload-only") + else: + print("TEST SUCCEEDED") + + else: + with open(REF_COMMIT_FN, "w") as f: + f.write(cur_commit) + print(f"\n\nUpdated reference logs for commit: {cur_commit}") + + sys.exit(int(failed)) diff --git a/selfdrive/test/process_replay/test_regen.py b/selfdrive/test/process_replay/test_regen.py new file mode 100644 index 0000000000..5f26daf786 --- /dev/null +++ b/selfdrive/test/process_replay/test_regen.py @@ -0,0 +1,37 @@ +from parameterized import parameterized + +from openpilot.selfdrive.test.process_replay.regen import regen_segment +from openpilot.selfdrive.test.process_replay.process_replay import check_openpilot_enabled +from openpilot.tools.lib.openpilotci import get_url +from openpilot.tools.lib.logreader import LogReader +from openpilot.tools.lib.framereader import FrameReader + +TESTED_SEGMENTS = [ + ("PRIUS_C2", "0982d79ebb0de295|2021-01-04--17-13-21--13"), # TOYOTA.TOYOTA_PRIUS: NEO, pandaStateDEPRECATED, no peripheralState, sensorEventsDEPRECATED + # Enable these once regen on CI becomes faster or use them for different tests running controlsd in isolation + # ("MAZDA_C3", "bd6a637565e91581|2021-10-30--15-14-53--4"), # MAZDA.CX9_2021: TICI, incomplete managerState + # ("FORD_C3", "54827bf84c38b14f|2023-01-26--21-59-07--4"), # FORD.BRONCO_SPORT_MK1: TICI +] + + +def ci_setup_data_readers(route, sidx): + lr = LogReader(get_url(route, sidx, "rlog.bz2")) + frs = { + 'roadCameraState': FrameReader(get_url(route, sidx, "fcamera.hevc")), + 'driverCameraState': FrameReader(get_url(route, sidx, "fcamera.hevc")), + } + if next((True for m in lr if m.which() == "wideRoadCameraState"), False): + frs["wideRoadCameraState"] = FrameReader(get_url(route, sidx, "ecamera.hevc")) + + return lr, frs + + +class TestRegen: + @parameterized.expand(TESTED_SEGMENTS) + def test_engaged(self, case_name, segment): + route, sidx = segment.rsplit("--", 1) + lr, frs = ci_setup_data_readers(route, sidx) + output_logs = regen_segment(lr, frs, disable_tqdm=True) + + engaged = check_openpilot_enabled(output_logs) + assert engaged, f"openpilot not engaged in {case_name}" diff --git a/selfdrive/test/process_replay/vision_meta.py b/selfdrive/test/process_replay/vision_meta.py new file mode 100644 index 0000000000..12deb58724 --- /dev/null +++ b/selfdrive/test/process_replay/vision_meta.py @@ -0,0 +1,43 @@ +from collections import namedtuple +from msgq.visionipc import VisionStreamType +from openpilot.common.realtime import DT_MDL, DT_DMON +from openpilot.common.transformations.camera import DEVICE_CAMERAS + +VideoStreamMeta = namedtuple("VideoStreamMeta", ["camera_state", "encode_index", "stream", "dt", "frame_sizes"]) +ROAD_CAMERA_FRAME_SIZES = {k: (v.dcam.width, v.dcam.height) for k, v in DEVICE_CAMERAS.items()} +WIDE_ROAD_CAMERA_FRAME_SIZES = {k: (v.ecam.width, v.ecam.height) for k, v in DEVICE_CAMERAS.items() if v.ecam is not None} +DRIVER_CAMERA_FRAME_SIZES = {k: (v.dcam.width, v.dcam.height) for k, v in DEVICE_CAMERAS.items()} +VIPC_STREAM_METADATA = [ + # metadata: (state_msg_type, encode_msg_type, stream_type, dt, frame_sizes) + ("roadCameraState", "roadEncodeIdx", VisionStreamType.VISION_STREAM_ROAD, DT_MDL, ROAD_CAMERA_FRAME_SIZES), + ("wideRoadCameraState", "wideRoadEncodeIdx", VisionStreamType.VISION_STREAM_WIDE_ROAD, DT_MDL, WIDE_ROAD_CAMERA_FRAME_SIZES), + ("driverCameraState", "driverEncodeIdx", VisionStreamType.VISION_STREAM_DRIVER, DT_DMON, DRIVER_CAMERA_FRAME_SIZES), +] + + +def meta_from_camera_state(state): + meta = next((VideoStreamMeta(*meta) for meta in VIPC_STREAM_METADATA if meta[0] == state), None) + return meta + + +def meta_from_encode_index(encode_index): + meta = next((VideoStreamMeta(*meta) for meta in VIPC_STREAM_METADATA if meta[1] == encode_index), None) + return meta + + +def meta_from_stream_type(stream_type): + meta = next((VideoStreamMeta(*meta) for meta in VIPC_STREAM_METADATA if meta[2] == stream_type), None) + return meta + + +def available_streams(lr=None): + if lr is None: + return [VideoStreamMeta(*meta) for meta in VIPC_STREAM_METADATA] + + result = [] + for meta in VIPC_STREAM_METADATA: + has_cam_state = next((True for m in lr if m.which() == meta[0]), False) + if has_cam_state: + result.append(VideoStreamMeta(*meta)) + + return result diff --git a/selfdrive/test/scons_build_test.sh b/selfdrive/test/scons_build_test.sh new file mode 100755 index 0000000000..5ffdb4379e --- /dev/null +++ b/selfdrive/test/scons_build_test.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e + +SCRIPT_DIR=$(dirname "$0") +BASEDIR=$(realpath "$SCRIPT_DIR/../../") +cd $BASEDIR + +# tests that our build system's dependencies are configured properly, +# needs a machine with lots of cores + +# helpful commands: +# scons -Q --tree=derived + +cd $BASEDIR/opendbc_repo/ +scons --clean +scons --no-cache --random -j$(nproc) +if ! scons -q; then + echo "FAILED: all build products not up to date after first pass." + exit 1 +fi diff --git a/selfdrive/test/setup_device_ci.sh b/selfdrive/test/setup_device_ci.sh new file mode 100755 index 0000000000..98909bfb52 --- /dev/null +++ b/selfdrive/test/setup_device_ci.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash + +set -e +set -x + +if [ -z "$SOURCE_DIR" ]; then + echo "SOURCE_DIR must be set" + exit 1 +fi + +if [ -z "$GIT_COMMIT" ]; then + echo "GIT_COMMIT must be set" + exit 1 +fi + +if [ -z "$TEST_DIR" ]; then + echo "TEST_DIR must be set" + exit 1 +fi + +# prevent storage from filling up +rm -rf /data/media/0/realdata/* + +rm -rf /data/safe_staging/ || true +if [ -d /data/safe_staging/ ]; then + sudo umount /data/safe_staging/merged/ || true + rm -rf /data/safe_staging/ || true +fi + +CONTINUE_PATH="/data/continue.sh" +tee $CONTINUE_PATH << EOF +#!/usr/bin/env bash + +sudo abctl --set_success + +# patch sshd config +sudo mount -o rw,remount / +sudo sed -i "s,/data/params/d/GithubSshKeys,/usr/comma/setup_keys," /etc/ssh/sshd_config +sudo systemctl daemon-reload +sudo systemctl restart ssh +sudo systemctl restart NetworkManager +sudo systemctl disable ssh-param-watcher.path +sudo systemctl disable ssh-param-watcher.service +sudo mount -o ro,remount / + +while true; do + if ! sudo systemctl is-active -q ssh; then + sudo systemctl start ssh + fi + + #if ! pgrep -f 'ciui.py' > /dev/null 2>&1; then + # echo 'starting UI' + # cp $SOURCE_DIR/selfdrive/test/ciui.py /data/ + # /data/ciui.py & + #fi + + awk '{print \$1}' /proc/uptime > /var/tmp/power_watchdog + sleep 5s +done + +sleep infinity +EOF +chmod +x $CONTINUE_PATH + +safe_checkout() { + # completely clean TEST_DIR + + cd $SOURCE_DIR + + # cleanup orphaned locks + find .git -type f -name "*.lock" -exec rm {} + + + git reset --hard + git fetch --no-tags --no-recurse-submodules -j4 --verbose --depth 1 origin $GIT_COMMIT + find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \; + git reset --hard $GIT_COMMIT + git checkout $GIT_COMMIT + git clean -xdff + git submodule sync + git submodule foreach --recursive "git reset --hard && git clean -xdff" + git submodule update --init --recursive + git submodule foreach --recursive "git reset --hard && git clean -xdff" + + git lfs pull + (ulimit -n 65535 && git lfs prune) + + echo "git checkout done, t=$SECONDS" + du -hs $SOURCE_DIR $SOURCE_DIR/.git + + rsync -a --delete $SOURCE_DIR $TEST_DIR +} + +unsafe_checkout() {( set -e + # checkout directly in test dir, leave old build products + + cd $TEST_DIR + + # cleanup orphaned locks + find .git -type f -name "*.lock" -exec rm {} + + + git fetch --no-tags --no-recurse-submodules -j8 --verbose --depth 1 origin $GIT_COMMIT + git checkout --force --no-recurse-submodules $GIT_COMMIT + git reset --hard $GIT_COMMIT + git clean -dff + git submodule sync + git submodule foreach --recursive "git reset --hard && git clean -df" + git submodule update --init --recursive + git submodule foreach --recursive "git reset --hard && git clean -df" + + git lfs pull + (ulimit -n 65535 && git lfs prune) +)} + +export GIT_PACK_THREADS=8 + +# set up environment +if [ ! -d "$SOURCE_DIR" ]; then + git clone https://github.com/commaai/openpilot.git $SOURCE_DIR +fi + +if [ ! -z "$UNSAFE" ]; then + echo "trying unsafe checkout" + set +e + unsafe_checkout + if [[ "$?" -ne 0 ]]; then + safe_checkout + fi + set -e +else + echo "doing safe checkout" + safe_checkout +fi + +echo "$TEST_DIR synced with $GIT_COMMIT, t=$SECONDS" diff --git a/selfdrive/test/setup_vsound.sh b/selfdrive/test/setup_vsound.sh new file mode 100755 index 0000000000..aab1499744 --- /dev/null +++ b/selfdrive/test/setup_vsound.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +{ + #start pulseaudio daemon + sudo pulseaudio -D + + # create a virtual null audio and set it to default device + sudo pactl load-module module-null-sink sink_name=virtual_audio + sudo pactl set-default-sink virtual_audio +} > /dev/null 2>&1 diff --git a/selfdrive/test/setup_xvfb.sh b/selfdrive/test/setup_xvfb.sh new file mode 100755 index 0000000000..692b84d65f --- /dev/null +++ b/selfdrive/test/setup_xvfb.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Sets up a virtual display for running map renderer and simulator without an X11 display + +DISP_ID=99 +export DISPLAY=:$DISP_ID + +sudo Xvfb $DISPLAY -screen 0 2160x1080x24 2>/dev/null & + +# check for x11 socket for the specified display ID +while [ ! -S /tmp/.X11-unix/X$DISP_ID ] +do + echo "Waiting for Xvfb..." + sleep 1 +done + +touch ~/.Xauthority +export XDG_SESSION_TYPE="x11" +xset -q \ No newline at end of file diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py new file mode 100644 index 0000000000..b4b9b9dbbe --- /dev/null +++ b/selfdrive/test/test_onroad.py @@ -0,0 +1,450 @@ +import math +import json +import os +import pytest +import shutil +import subprocess +import time +import numpy as np +from collections import Counter, defaultdict +from pathlib import Path +from tabulate import tabulate + +from cereal import log +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from openpilot.common.basedir import BASEDIR +from openpilot.common.timeout import Timeout +from openpilot.common.params import Params +from openpilot.selfdrive.selfdrived.events import EVENTS, ET +from openpilot.selfdrive.test.helpers import set_params_enabled, release_only +from openpilot.system.hardware.hw import Paths +from openpilot.tools.lib.logreader import LogReader +from openpilot.tools.lib.log_time_series import msgs_to_time_series + +""" +CPU usage budget +* each process is entitled to at least 8% +* total CPU usage of openpilot (sum(PROCS.values()) + should not exceed MAX_TOTAL_CPU +""" + +TEST_DURATION = 25 +LOG_OFFSET = 8 + +MAX_TOTAL_CPU = 300. # total for all 8 cores +PROCS = { + # Baseline CPU usage by process + "selfdrive.controls.controlsd": 16.0, + "selfdrive.selfdrived.selfdrived": 16.0, + "selfdrive.car.card": 26.0, + "./loggerd": 14.0, + "./encoderd": 13.0, + "./camerad": 10.0, + "selfdrive.controls.plannerd": 8.0, + "./ui": 18.0, + "system.sensord.sensord": 13.0, + "selfdrive.controls.radard": 2.0, + "selfdrive.modeld.modeld": 22.0, + "selfdrive.modeld.dmonitoringmodeld": 18.0, + "system.hardware.hardwared": 4.0, + "selfdrive.locationd.calibrationd": 2.0, + "selfdrive.locationd.torqued": 5.0, + "selfdrive.locationd.locationd": 25.0, + "selfdrive.locationd.paramsd": 9.0, + "selfdrive.locationd.lagd": 11.0, + "selfdrive.ui.soundd": 3.0, + "selfdrive.ui.feedback.feedbackd": 1.0, + "selfdrive.monitoring.dmonitoringd": 4.0, + "system.proclogd": 3.0, + "system.logmessaged": 1.0, + "system.tombstoned": 0, + "system.journald": 1.0, + "system.micd": 5.0, + "system.timed": 0, + "selfdrive.pandad.pandad": 0, + "system.statsd": 1.0, + "system.loggerd.uploader": 15.0, + "system.loggerd.deleter": 1.0, + "./pandad": 19.0, + "system.qcomgpsd.qcomgpsd": 1.0, +} + +TIMINGS = { + # rtols: max/min, rsd + "can": [2.5, 0.35], + "pandaStates": [2.5, 0.35], + "peripheralState": [2.5, 0.35], + "sendcan": [2.5, 0.35], + "carState": [2.5, 0.35], + "carControl": [2.5, 0.35], + "controlsState": [2.5, 0.35], + "longitudinalPlan": [2.5, 0.5], + "driverAssistance": [2.5, 0.5], + "roadCameraState": [2.5, 0.35], + "driverCameraState": [2.5, 0.35], + "modelV2": [2.5, 0.35], + "driverStateV2": [2.5, 0.40], + "livePose": [2.5, 0.35], + "liveParameters": [2.5, 0.35], + "wideRoadCameraState": [1.5, 0.35], +} + +LOGS_SIZE = { # MB per segment + "qlog.zst": 0.5, + "rlog.zst": 8.1, + "qcamera.ts": 2.3, +} +LOGS_SIZE.update(dict.fromkeys(['ecamera.hevc', 'fcamera.hevc', 'dcamera.hevc'], 76.5)) + + +def cputime_total(ct): + return ct.cpuUser + ct.cpuSystem + ct.cpuChildrenUser + ct.cpuChildrenSystem + + +@pytest.mark.tici +@pytest.mark.skip_tici_setup +class TestOnroad: + + @classmethod + def setup_class(cls): + if "DEBUG" in os.environ: + segs = filter(lambda x: os.path.exists(os.path.join(x, "rlog.zst")), Path(Paths.log_root()).iterdir()) + segs = sorted(segs, key=lambda x: x.stat().st_mtime) + cls.lr = list(LogReader(os.path.join(segs[-1], "rlog.zst"))) + cls.ts = msgs_to_time_series(cls.lr) + return + + # setup env + params = Params() + params.remove("CurrentRoute") + params.put_bool("RecordFront", True) + set_params_enabled() + os.environ['REPLAY'] = '1' + os.environ['TESTING_CLOSET'] = '1' + if os.path.exists(Paths.log_root()): + shutil.rmtree(Paths.log_root()) + + # start manager and run openpilot for TEST_DURATION + proc = None + try: + manager_path = os.path.join(BASEDIR, "system/manager/manager.py") + cls.manager_st = time.monotonic() + proc = subprocess.Popen(["python", manager_path]) + + sm = messaging.SubMaster(['carState']) + with Timeout(30, "controls didn't start"): + while not sm.seen['carState']: + sm.update(1000) + + route = params.get("CurrentRoute") + assert route is not None + + segs = list(Path(Paths.log_root()).glob(f"{route}--*")) + assert len(segs) == 1 + + time.sleep(TEST_DURATION) + finally: + if proc is not None: + proc.terminate() + if proc.wait(60) is None: + proc.kill() + + cls.lr = list(LogReader(os.path.join(str(segs[0]), "rlog.zst"))) + st = time.monotonic() + cls.ts = msgs_to_time_series(cls.lr) + print("msgs to time series", time.monotonic() - st) + log_path = segs[0] + + cls.log_sizes = {} + for f in log_path.iterdir(): + assert f.is_file() + cls.log_sizes[f] = f.stat().st_size / 1e6 + + cls.msgs = defaultdict(list) + for m in cls.lr: + cls.msgs[m.which()].append(m) + + def test_service_frequencies(self, subtests): + for s, msgs in self.msgs.items(): + if s in ('initData', 'sentinel'): + continue + + # skip gps services for now + if s in ('ubloxGnss', 'ubloxRaw', 'gnssMeasurements', 'gpsLocation', 'gpsLocationExternal', 'qcomGnss'): + continue + + with subtests.test(service=s): + assert len(msgs) >= math.floor(SERVICE_LIST[s].frequency*int(TEST_DURATION*0.8)) + + def test_manager_starting_time(self): + st = self.ts['managerState']['t'][0] + assert (st - self.manager_st) < 12.5, f"manager.py took {st - self.manager_st}s to publish the first 'managerState' msg" + + def test_cloudlog_size(self): + msgs = self.msgs['logMessage'] + + total_size = sum(len(m.as_builder().to_bytes()) for m in msgs) + assert total_size < 3.5e5 + + cnt = Counter(json.loads(m.logMessage)['filename'] for m in msgs) + big_logs = [f for f, n in cnt.most_common(3) if n / sum(cnt.values()) > 30.] + assert len(big_logs) == 0, f"Log spam: {big_logs}" + + def test_log_sizes(self, subtests): + # TODO: this isn't super stable between different devices + for f, sz in self.log_sizes.items(): + rate = LOGS_SIZE[f.name]/60. + minn = rate * TEST_DURATION * 0.5 + maxx = rate * TEST_DURATION * 1.5 + with subtests.test(file=f.name): + assert minn < sz < maxx + + def test_ui_timings(self): + result = "\n" + result += "------------------------------------------------\n" + result += "-------------- UI Draw Timing ------------------\n" + result += "------------------------------------------------\n" + + ts = self.ts['uiDebug']['drawTimeMillis'] + result += f"min {min(ts):.2f}ms\n" + result += f"max {max(ts):.2f}ms\n" + result += f"std {np.std(ts):.2f}ms\n" + result += f"mean {np.mean(ts):.2f}ms\n" + result += "------------------------------------------------\n" + print(result) + + assert max(ts) < 250. + assert np.mean(ts) < 10. + #self.assertLess(np.std(ts), 5.) + + # some slow frames are expected since camerad/modeld can preempt ui + veryslow = [x for x in ts if x > 40.] + assert len(veryslow) < 5, f"Too many slow frame draw times: {veryslow}" + + def test_cpu_usage(self, subtests): + print("\n------------------------------------------------") + print("------------------ CPU Usage -------------------") + print("------------------------------------------------") + + plogs_by_proc = defaultdict(list) + for pl in self.msgs['procLog']: + for x in pl.procLog.procs: + if len(x.cmdline) > 0: + n = list(x.cmdline)[0] + plogs_by_proc[n].append(x) + + cpu_ok = True + dt = (self.msgs['procLog'][-1].logMonoTime - self.msgs['procLog'][0].logMonoTime) / 1e9 + header = ['process', 'usage', 'expected', 'max allowed', 'test result'] + rows = [] + for proc_name, expected in PROCS.items(): + + error = "" + usage = 0. + x = plogs_by_proc[proc_name] + if len(x) > 2: + cpu_time = cputime_total(x[-1]) - cputime_total(x[0]) + usage = cpu_time / dt * 100. + + max_allowed = max(expected * 1.8, expected + 5.0) + if usage > max_allowed: + error = "❌ USING MORE CPU THAN EXPECTED ❌" + cpu_ok = False + + else: + error = "❌ NO METRICS FOUND ❌" + cpu_ok = False + + rows.append([proc_name, usage, expected, max_allowed, error or "✅"]) + print(tabulate(rows, header, tablefmt="simple_grid", stralign="center", numalign="center", floatfmt=".2f")) + + # Ensure there's no missing procs + all_procs = {p.name for p in self.msgs['managerState'][0].managerState.processes if p.shouldBeRunning} + for p in all_procs: + with subtests.test(proc=p): + assert any(p in pp for pp in PROCS.keys()), f"Expected CPU usage missing for {p}" + + # total CPU check + procs_tot = sum([(max(x) if isinstance(x, tuple) else x) for x in PROCS.values()]) + with subtests.test(name="total CPU"): + assert procs_tot < MAX_TOTAL_CPU, "Total CPU budget exceeded" + print("------------------------------------------------") + print(f"Total allocated CPU usage is {procs_tot}%, budget is {MAX_TOTAL_CPU}%, {MAX_TOTAL_CPU-procs_tot:.1f}% left") + print("------------------------------------------------") + + assert cpu_ok + + def test_memory_usage(self): + print("\n------------------------------------------------") + print("--------------- Memory Usage -------------------") + print("------------------------------------------------") + offset = int(SERVICE_LIST['deviceState'].frequency * LOG_OFFSET) + mems = [m.deviceState.memoryUsagePercent for m in self.msgs['deviceState'][offset:]] + print("Memory usage: ", mems) + + # check for big leaks. note that memory usage is + # expected to go up while the MSGQ buffers fill up + assert np.average(mems) <= 65, "Average memory usage above 65%" + assert np.max(np.diff(mems)) <= 4, "Max memory increase too high" + assert np.average(np.diff(mems)) <= 1, "Average memory increase too high" + + def test_camera_frame_timings(self, subtests): + # test timing within a single camera + result = "\n" + result += "------------------------------------------------\n" + result += "----------------- SOF Timing ------------------\n" + result += "------------------------------------------------\n" + for name in ['roadCameraState', 'wideRoadCameraState', 'driverCameraState']: + ts = self.ts[name]['timestampSof'] + d_ms = np.diff(ts) / 1e6 + d50 = np.abs(d_ms-50) + result += f"{name} sof delta vs 50ms: min {min(d50):.2f}ms\n" + result += f"{name} sof delta vs 50ms: max {max(d50):.2f}ms\n" + result += f"{name} sof delta vs 50ms: mean {d50.mean():.2f}ms\n" + with subtests.test(camera=name): + assert max(d50) < 5.0, f"high SOF delta vs 50ms: {max(d50)}" + result += "------------------------------------------------\n" + print(result) + + def test_camera_sync(self, subtests): + cam_states = ['roadCameraState', 'wideRoadCameraState', 'driverCameraState'] + encode_cams = ['roadEncodeIdx', 'wideRoadEncodeIdx', 'driverEncodeIdx'] + for cams in (cam_states, encode_cams): + with subtests.test(cams=cams): + # sanity checks within a single cam + for cam in cams: + with subtests.test(test="frame_skips", camera=cam): + assert set(np.diff(self.ts[cam]['frameId'])) == {1, }, "Frame ID skips" + + # EOF > SOF + eof_sof_diff = self.ts[cam]['timestampEof'] - self.ts[cam]['timestampSof'] + assert np.all(eof_sof_diff > 0) + assert np.all(eof_sof_diff < 50*1e6) + + first_fid = {min(self.ts[c]['frameId']) for c in cams} + assert len(first_fid) == 1, "Cameras don't start on same frame ID" + if cam.endswith('CameraState'): + # camerad guarantees that all cams start on frame ID 0 + # (note loggerd also needs to start up fast enough to catch it) + assert next(iter(first_fid)) < 100, "Cameras start on frame ID too high" + + # we don't do a full segment rotation, so these might not match exactly + last_fid = {max(self.ts[c]['frameId']) for c in cams} + assert max(last_fid) - min(last_fid) < 10 + + start, end = min(first_fid), min(last_fid) + for i in range(end-start): + ts = {c: round(self.ts[c]['timestampSof'][i]/1e6, 1) for c in cams} + diff = (max(ts.values()) - min(ts.values())) + assert diff < 2, f"Cameras not synced properly: frame_id={start+i}, {diff=:.1f}ms, {ts=}" + + def test_camera_encoder_matches(self, subtests): + # sanity check that the frame metadata is consistent with the encoded frames + pairs = [('roadCameraState', 'roadEncodeIdx'), + ('wideRoadCameraState', 'wideRoadEncodeIdx'), + ('driverCameraState', 'driverEncodeIdx')] + for cam, enc in pairs: + with subtests.test(camera=cam, encoder=enc): + cam_frames = {fid: (sof, eof) for fid, sof, eof in zip( + self.ts[cam]['frameId'], + self.ts[cam]['timestampSof'], + self.ts[cam]['timestampEof'], + strict=True, + )} + for i, fid in enumerate(self.ts[enc]['frameId']): + cam_sof, cam_eof = cam_frames[fid] + enc_sof, enc_eof = self.ts[enc]['timestampSof'][i], self.ts[enc]['timestampEof'][i] + assert enc_sof == cam_sof, f"SOF mismatch: frameId={fid}, enc_sof={enc_sof}, cam_sof={cam_sof}" + assert enc_eof == cam_eof, f"EOF mismatch: frameId={fid}, enc_eof={enc_eof}, cam_eof={cam_eof}" + + def test_mpc_execution_timings(self): + result = "\n" + result += "------------------------------------------------\n" + result += "----------------- MPC Timing ------------------\n" + result += "------------------------------------------------\n" + + cfgs = [("longitudinalPlan", 0.05, 0.05),] + for (s, instant_max, avg_max) in cfgs: + ts = [getattr(m, s).solverExecutionTime for m in self.msgs[s]] + assert max(ts) < instant_max, f"high '{s}' execution time: {max(ts)}" + assert np.mean(ts) < avg_max, f"high avg '{s}' execution time: {np.mean(ts)}" + result += f"'{s}' execution time: min {min(ts):.5f}s\n" + result += f"'{s}' execution time: max {max(ts):.5f}s\n" + result += f"'{s}' execution time: mean {np.mean(ts):.5f}s\n" + result += "------------------------------------------------\n" + print(result) + + def test_model_execution_timings(self, subtests): + result = "\n" + result += "------------------------------------------------\n" + result += "----------------- Model Timing -----------------\n" + result += "------------------------------------------------\n" + cfgs = [ + # since multiple processes use the GPU and can preempt each other, + # these numbers are not fully self-contained. + ("modelV2", 0.06, 0.040), + + # can miss cycles here and there, just important the avg frequency is 20Hz + ("driverStateV2", 0.3, 0.05), + ] + for (s, instant_max, avg_max) in cfgs: + ts = [getattr(m, s).modelExecutionTime for m in self.msgs[s]] + # TODO some init can happen in first iteration + ts = ts[1:] + result += f"'{s}' execution time: min {min(ts):.5f}s\n" + result += f"'{s}' execution time: max {max(ts):.5f}s\n" + result += f"'{s}' execution time: mean {np.mean(ts):.5f}s\n" + with subtests.test(s): + assert max(ts) < instant_max, f"high '{s}' execution time: {max(ts)}" + assert np.mean(ts) < avg_max, f"high avg '{s}' execution time: {np.mean(ts)}" + result += "------------------------------------------------\n" + print(result) + + def test_timings(self): + passed = True + print("\n------------------------------------------------") + print("----------------- Service Timings --------------") + print("------------------------------------------------") + + header = ['service', 'max', 'min', 'mean', 'expected mean', 'rsd', 'max allowed rsd', 'test result'] + rows = [] + for s, (maxmin, rsd) in TIMINGS.items(): + offset = int(SERVICE_LIST[s].frequency * LOG_OFFSET) + msgs = [m.logMonoTime for m in self.msgs[s][offset:]] + if not len(msgs): + raise Exception(f"missing {s}") + + ts = np.diff(msgs) / 1e9 + dt = 1 / SERVICE_LIST[s].frequency + + errors = [] + if not np.allclose(np.mean(ts), dt, rtol=0.03, atol=0): + errors.append("❌ FAILED MEAN TIMING CHECK ❌") + if not np.allclose([np.max(ts), np.min(ts)], dt, rtol=maxmin, atol=0): + errors.append("❌ FAILED MAX/MIN TIMING CHECK ❌") + if (np.std(ts)/dt) > rsd: + errors.append("❌ FAILED RSD TIMING CHECK ❌") + passed = not errors and passed + rows.append([s, *(np.array([np.max(ts), np.min(ts), np.mean(ts), dt])*1e3), np.std(ts)/dt, rsd, "\n".join(errors) or "✅"]) + + print(tabulate(rows, header, tablefmt="simple_grid", stralign="center", numalign="center", floatfmt=".2f")) + assert passed + + @release_only + def test_startup(self): + startup_alert = self.ts['selfdriveState']['alertText1'][0] + expected = EVENTS[log.OnroadEvent.EventName.startup][ET.PERMANENT].alert_text_1 + assert startup_alert == expected, "wrong startup alert" + + def test_engagable(self): + no_entries = Counter() + for m in self.msgs['onroadEvents']: + for evt in m.onroadEvents: + if evt.noEntry: + no_entries[evt.name] += 1 + + offset = int(SERVICE_LIST['selfdriveState'].frequency * LOG_OFFSET) + eng = [m.selfdriveState.engageable for m in self.msgs['selfdriveState'][offset:]] + assert all(eng), \ + f"Not engageable for whole segment:\n- selfdriveState.engageable: {Counter(eng)}\n- No entry events: {no_entries}" diff --git a/selfdrive/test/test_updated.py b/selfdrive/test/test_updated.py new file mode 100644 index 0000000000..95365640f5 --- /dev/null +++ b/selfdrive/test/test_updated.py @@ -0,0 +1,295 @@ +import datetime +import os +import pytest +import time +import tempfile +import shutil +import signal +import subprocess +import random + +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params + + +@pytest.mark.tici +class TestUpdated: + + def setup_method(self): + self.updated_proc = None + + self.tmp_dir = tempfile.TemporaryDirectory() + org_dir = os.path.join(self.tmp_dir.name, "commaai") + + self.basedir = os.path.join(org_dir, "openpilot") + self.git_remote_dir = os.path.join(org_dir, "openpilot_remote") + self.staging_dir = os.path.join(org_dir, "safe_staging") + for d in [org_dir, self.basedir, self.git_remote_dir, self.staging_dir]: + os.mkdir(d) + + self.neos_version = os.path.join(org_dir, "neos_version") + self.neosupdate_dir = os.path.join(org_dir, "neosupdate") + with open(self.neos_version, "w") as f: + v = subprocess.check_output(r"bash -c 'source launch_env.sh && echo $REQUIRED_NEOS_VERSION'", + cwd=BASEDIR, shell=True, encoding='utf8').strip() + f.write(v) + + self.upper_dir = os.path.join(self.staging_dir, "upper") + self.merged_dir = os.path.join(self.staging_dir, "merged") + self.finalized_dir = os.path.join(self.staging_dir, "finalized") + + # setup local submodule remotes + submodules = subprocess.check_output("git submodule --quiet foreach 'echo $name'", + shell=True, cwd=BASEDIR, encoding='utf8').split() + for s in submodules: + sub_path = os.path.join(org_dir, s.split("_repo")[0]) + self._run(f"git clone {s} {sub_path}.git", cwd=BASEDIR) + + # setup two git repos, a remote and one we'll run updated in + self._run([ + f"git clone {BASEDIR} {self.git_remote_dir}", + f"git clone {self.git_remote_dir} {self.basedir}", + f"cd {self.basedir} && git submodule init && git submodule update", + f"cd {self.basedir} && scons -j{os.cpu_count()} cereal/ common/" + ]) + + self.params = Params(os.path.join(self.basedir, "persist/params")) + self.params.clear_all() + os.sync() + + def teardown_method(self): + try: + if self.updated_proc is not None: + self.updated_proc.terminate() + self.updated_proc.wait(30) + except Exception as e: + print(e) + self.tmp_dir.cleanup() + + + # *** test helpers *** + + + def _run(self, cmd, cwd=None): + if not isinstance(cmd, list): + cmd = (cmd,) + + for c in cmd: + subprocess.check_output(c, cwd=cwd, shell=True) + + def _get_updated_proc(self): + os.environ["PYTHONPATH"] = self.basedir + os.environ["GIT_AUTHOR_NAME"] = "testy tester" + os.environ["GIT_COMMITTER_NAME"] = "testy tester" + os.environ["GIT_AUTHOR_EMAIL"] = "testy@tester.test" + os.environ["GIT_COMMITTER_EMAIL"] = "testy@tester.test" + os.environ["UPDATER_TEST_IP"] = "localhost" + os.environ["UPDATER_LOCK_FILE"] = os.path.join(self.tmp_dir.name, "updater.lock") + os.environ["UPDATER_STAGING_ROOT"] = self.staging_dir + os.environ["UPDATER_NEOS_VERSION"] = self.neos_version + os.environ["UPDATER_NEOSUPDATE_DIR"] = self.neosupdate_dir + updated_path = os.path.join(self.basedir, "system/updated.py") + return subprocess.Popen(updated_path, env=os.environ) + + def _start_updater(self, offroad=True, nosleep=False): + self.params.put_bool("IsOffroad", offroad) + self.updated_proc = self._get_updated_proc() + if not nosleep: + time.sleep(1) + + def _update_now(self): + self.updated_proc.send_signal(signal.SIGHUP) + + # TODO: this should be implemented in params + def _read_param(self, key, timeout=1): + ret = None + start_time = time.monotonic() + while ret is None: + ret = self.params.get(key) + if time.monotonic() - start_time > timeout: + break + time.sleep(0.01) + return ret + + def _wait_for_update(self, timeout=30, clear_param=False): + if clear_param: + self.params.remove("LastUpdateTime") + + self._update_now() + t = self._read_param("LastUpdateTime", timeout=timeout) + if t is None: + raise Exception("timed out waiting for update to complete") + + def _make_commit(self): + all_dirs, all_files = [], [] + for root, dirs, files in os.walk(self.git_remote_dir): + if ".git" in root: + continue + for d in dirs: + all_dirs.append(os.path.join(root, d)) + for f in files: + all_files.append(os.path.join(root, f)) + + # make a new dir and some new files + new_dir = os.path.join(self.git_remote_dir, "this_is_a_new_dir") + os.mkdir(new_dir) + for _ in range(random.randrange(5, 30)): + for d in (new_dir, random.choice(all_dirs)): + with tempfile.NamedTemporaryFile(dir=d, delete=False) as f: + f.write(os.urandom(random.randrange(1, 1000000))) + + # modify some files + for f in random.sample(all_files, random.randrange(5, 50)): + with open(f, "w+") as ff: + txt = ff.readlines() + ff.seek(0) + for line in txt: + ff.write(line[::-1]) + + # remove some files + for f in random.sample(all_files, random.randrange(5, 50)): + os.remove(f) + + # remove some dirs + for d in random.sample(all_dirs, random.randrange(1, 10)): + shutil.rmtree(d) + + # commit the changes + self._run([ + "git add -A", + "git commit -m 'an update'", + ], cwd=self.git_remote_dir) + + def _check_update_state(self, update_available): + # make sure LastUpdateTime is recent + last_update_time = self._read_param("LastUpdateTime") + td = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_update_time + assert td.total_seconds() < 10 + self.params.remove("LastUpdateTime") + + # wait a bit for the rest of the params to be written + time.sleep(0.1) + + # check params + update = self._read_param("UpdateAvailable") + assert update == "1" == update_available, f"UpdateAvailable: {repr(update)}" + assert self._read_param("UpdateFailedCount") == 0 + + # TODO: check that the finalized update actually matches remote + # check the .overlay_init and .overlay_consistent flags + assert os.path.isfile(os.path.join(self.basedir, ".overlay_init")) + assert os.path.isfile(os.path.join(self.finalized_dir, ".overlay_consistent")) == update_available + + + # *** test cases *** + + + # Run updated for 100 cycles with no update + def test_no_update(self): + self._start_updater() + for _ in range(100): + self._wait_for_update(clear_param=True) + self._check_update_state(False) + + # Let the updater run with no update for a cycle, then write an update + def test_update(self): + self._start_updater() + + # run for a cycle with no update + self._wait_for_update(clear_param=True) + self._check_update_state(False) + + # write an update to our remote + self._make_commit() + + # run for a cycle to get the update + self._wait_for_update(timeout=60, clear_param=True) + self._check_update_state(True) + + # run another cycle with no update + self._wait_for_update(clear_param=True) + self._check_update_state(True) + + # Let the updater run for 10 cycles, and write an update every cycle + @pytest.mark.skip("need to make this faster") + def test_update_loop(self): + self._start_updater() + + # run for a cycle with no update + self._wait_for_update(clear_param=True) + for _ in range(10): + time.sleep(0.5) + self._make_commit() + self._wait_for_update(timeout=90, clear_param=True) + self._check_update_state(True) + + # Test overlay re-creation after tracking a new file in basedir's git + def test_overlay_reinit(self): + self._start_updater() + + overlay_init_fn = os.path.join(self.basedir, ".overlay_init") + + # run for a cycle with no update + self._wait_for_update(clear_param=True) + self.params.remove("LastUpdateTime") + first_mtime = os.path.getmtime(overlay_init_fn) + + # touch a file in the basedir + self._run("touch new_file && git add new_file", cwd=self.basedir) + + # run another cycle, should have a new mtime + self._wait_for_update(clear_param=True) + second_mtime = os.path.getmtime(overlay_init_fn) + assert first_mtime != second_mtime + + # run another cycle, mtime should be same as last cycle + self._wait_for_update(clear_param=True) + new_mtime = os.path.getmtime(overlay_init_fn) + assert second_mtime == new_mtime + + # Make sure updated exits if another instance is running + def test_multiple_instances(self): + # start updated and let it run for a cycle + self._start_updater() + time.sleep(1) + self._wait_for_update(clear_param=True) + + # start another instance + second_updated = self._get_updated_proc() + ret_code = second_updated.wait(timeout=5) + assert ret_code is not None + + + # *** test cases with NEOS updates *** + + + # Run updated with no update, make sure it clears the old NEOS update + def test_clear_neos_cache(self): + # make the dir and some junk files + os.mkdir(self.neosupdate_dir) + for _ in range(15): + with tempfile.NamedTemporaryFile(dir=self.neosupdate_dir, delete=False) as f: + f.write(os.urandom(random.randrange(1, 1000000))) + + self._start_updater() + self._wait_for_update(clear_param=True) + self._check_update_state(False) + assert not os.path.isdir(self.neosupdate_dir) + + # Let the updater run with no update for a cycle, then write an update + @pytest.mark.skip("TODO: only runs on device") + def test_update_with_neos_update(self): + # bump the NEOS version and commit it + self._run([ + "echo 'export REQUIRED_NEOS_VERSION=3' >> launch_env.sh", + "git -c user.name='testy' -c user.email='testy@tester.test' \ + commit -am 'a neos update'", + ], cwd=self.git_remote_dir) + + # run for a cycle to get the update + self._start_updater() + self._wait_for_update(timeout=60, clear_param=True) + self._check_update_state(True) + + # TODO: more comprehensive check + assert os.path.isdir(self.neosupdate_dir) diff --git a/selfdrive/test/update_ci_routes.py b/selfdrive/test/update_ci_routes.py new file mode 100755 index 0000000000..2bf06b4860 --- /dev/null +++ b/selfdrive/test/update_ci_routes.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +import os +import re +import subprocess +import sys +from collections.abc import Iterable + +from tqdm import tqdm + +from opendbc.car.tests.routes import routes as test_car_models_routes +from openpilot.selfdrive.test.process_replay.test_processes import source_segments as replay_segments +from openpilot.tools.lib.azure_container import AzureContainer +from openpilot.tools.lib.openpilotcontainers import DataCIContainer, DataProdContainer, OpenpilotCIContainer + +SOURCES: list[AzureContainer] = [ + DataProdContainer, + DataCIContainer +] + +DEST = OpenpilotCIContainer + +def upload_route(path: str, exclude_patterns: Iterable[str] = None) -> None: + if exclude_patterns is None: + exclude_patterns = [r'dcamera\.hevc'] + + r, n = path.rsplit("--", 1) + r = '/'.join(r.split('/')[-2:]) # strip out anything extra in the path + destpath = f"{r}/{n}" + for file in os.listdir(path): + if any(re.search(pattern, file) for pattern in exclude_patterns): + continue + DEST.upload_file(os.path.join(path, file), f"{destpath}/{file}") + + +def sync_to_ci_public(route: str) -> bool: + dest_container, dest_key = DEST.get_client_and_key() + key_prefix = route.replace('|', '/') + dongle_id = key_prefix.split('/')[0] + + if next(dest_container.list_blob_names(name_starts_with=key_prefix), None) is not None: + return True + + print(f"Uploading {route}") + for source_container in SOURCES: + # assumes az login has been run + print(f"Trying {source_container.ACCOUNT}/{source_container.CONTAINER}") + _, source_key = source_container.get_client_and_key() + cmd = [ + "azcopy", + "copy", + f"{source_container.BASE_URL}{key_prefix}?{source_key}", + f"{DEST.BASE_URL}{dongle_id}?{dest_key}", + "--recursive=true", + "--overwrite=false", + "--exclude-pattern=*/dcamera.hevc", + ] + + try: + result = subprocess.call(cmd, stdout=subprocess.DEVNULL) + if result == 0: + print("Success") + return True + except subprocess.CalledProcessError: + print("Failed") + + return False + + +if __name__ == "__main__": + failed_routes = [] + + to_sync = sys.argv[1:] + + if not len(to_sync): + # sync routes from the car tests routes and process replay + to_sync.extend([rt.route for rt in test_car_models_routes]) + to_sync.extend([s[1].rsplit('--', 1)[0] for s in replay_segments]) + + for r in tqdm(to_sync): + if not sync_to_ci_public(r): + failed_routes.append(r) + + if len(failed_routes): + print("failed routes:", failed_routes) diff --git a/selfdrive/ui/.gitignore b/selfdrive/ui/.gitignore new file mode 100644 index 0000000000..7e9eaf932f --- /dev/null +++ b/selfdrive/ui/.gitignore @@ -0,0 +1,14 @@ +moc_* +*.moc + +translations/main_test_en.* + +ui +mui +watch3 +installer/installers/* +qt/setup/setup +qt/setup/reset +qt/setup/wifi +qt/setup/updater +translations/alerts_generated.h diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript new file mode 100644 index 0000000000..2b57be7227 --- /dev/null +++ b/selfdrive/ui/SConscript @@ -0,0 +1,98 @@ +import json +Import('env', 'qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations') + +base_libs = [common, messaging, visionipc, transformations, + 'm', 'OpenCL', 'ssl', 'crypto', 'pthread'] + qt_env["LIBS"] + +if arch == 'larch64': + base_libs.append('EGL') + +if arch == "Darwin": + del base_libs[base_libs.index('OpenCL')] + qt_env['FRAMEWORKS'] += ['OpenCL'] + +# FIXME: remove this once we're on 5.15 (24.04) +qt_env['CXXFLAGS'] += ["-Wno-deprecated-declarations"] + +qt_util = qt_env.Library("qt_util", ["#selfdrive/ui/qt/api.cc", "#selfdrive/ui/qt/util.cc"], LIBS=base_libs) +widgets_src = ["qt/widgets/input.cc", "qt/widgets/wifi.cc", "qt/prime_state.cc", + "qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", + "qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc", + "qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc", + "qt/request_repeater.cc", "qt/qt_window.cc", "qt/network/networking.cc", "qt/network/wifi_manager.cc"] + +widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=base_libs) +Export('widgets') +qt_libs = [widgets, qt_util] + base_libs + +qt_src = ["main.cc", "ui.cc", "qt/sidebar.cc", "qt/body.cc", + "qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc", + "qt/offroad/software_settings.cc", "qt/offroad/developer_panel.cc", "qt/offroad/onboarding.cc", + "qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc", "qt/offroad/firehose.cc", + "qt/onroad/onroad_home.cc", "qt/onroad/annotated_camera.cc", "qt/onroad/model.cc", + "qt/onroad/buttons.cc", "qt/onroad/alerts.cc", "qt/onroad/driver_monitoring.cc", "qt/onroad/hud.cc"] + +# build translation files +with open(File("translations/languages.json").abspath) as f: + languages = json.loads(f.read()) +translation_sources = [f"#selfdrive/ui/translations/{l}.ts" for l in languages.values()] +translation_targets = [src.replace(".ts", ".qm") for src in translation_sources] +lrelease_bin = 'third_party/qt5/larch64/bin/lrelease' if arch == 'larch64' else 'lrelease' + +lrelease = qt_env.Command(translation_targets, translation_sources, f"{lrelease_bin} $SOURCES") +qt_env.NoClean(translation_sources) +qt_env.Precious(translation_sources) + +# create qrc file for compiled translations to include with assets +translations_assets_src = "#selfdrive/assets/translations_assets.qrc" +with open(File(translations_assets_src).abspath, 'w') as f: + f.write('\n\n') + f.write('\n'.join([f'../ui/translations/{l}.qm' for l in languages.values()])) + f.write('\n\n') + +# build assets +assets = "#selfdrive/assets/assets.cc" +assets_src = "#selfdrive/assets/assets.qrc" +qt_env.Command(assets, [assets_src, translations_assets_src], f"rcc $SOURCES -o $TARGET") +qt_env.Depends(assets, Glob('#selfdrive/assets/*', exclude=[assets, assets_src, translations_assets_src, "#selfdrive/assets/assets.o"]) + [lrelease]) +asset_obj = qt_env.Object("assets", assets) + +# build main UI +qt_env.Program("ui", qt_src + [asset_obj], LIBS=qt_libs) +if GetOption('extras'): + qt_src.remove("main.cc") # replaced by test_runner + qt_env.Program('tests/test_translations', [asset_obj, 'tests/test_runner.cc', 'tests/test_translations.cc'] + qt_src, LIBS=qt_libs) + + # build installers + if arch != "Darwin": + raylib_env = env.Clone() + raylib_env['LIBPATH'] += [f'#third_party/raylib/{arch}/'] + raylib_env['LINKFLAGS'].append('-Wl,-strip-debug') + + raylib_libs = common + ["raylib"] + if arch == "larch64": + raylib_libs += ["GLESv2", "EGL", "gdb", "drm"] + else: + raylib_libs += ["GL"] + + release = "release3" + installers = [ + ("openpilot", release), + ("openpilot_test", f"{release}-staging"), + ("openpilot_nightly", "nightly"), + ("openpilot_internal", "nightly-dev"), + ] + + cont = raylib_env.Command("installer/continue_openpilot.o", "installer/continue_openpilot.sh", + "ld -r -b binary -o $TARGET $SOURCE") + inter = raylib_env.Command("installer/inter_ttf.o", "installer/inter-ascii.ttf", + "ld -r -b binary -o $TARGET $SOURCE") + for name, branch in installers: + d = {'BRANCH': f"'\"{branch}\"'"} + if "internal" in name: + d['INTERNAL'] = "1" + + obj = raylib_env.Object(f"installer/installers/installer_{name}.o", ["installer/installer.cc"], CPPDEFINES=d) + f = raylib_env.Program(f"installer/installers/installer_{name}", [obj, cont, inter], LIBS=raylib_libs) + # keep installers small + assert f[0].get_size() < 1900*1e3, f[0].get_size() diff --git a/selfdrive/ui/__init__.py b/selfdrive/ui/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/ui/feedback/feedbackd.py b/selfdrive/ui/feedback/feedbackd.py new file mode 100755 index 0000000000..2d131a0d5e --- /dev/null +++ b/selfdrive/ui/feedback/feedbackd.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +import cereal.messaging as messaging +from openpilot.common.params import Params +from openpilot.common.swaglog import cloudlog +from cereal import car +from openpilot.system.micd import SAMPLE_RATE, SAMPLE_BUFFER + +FEEDBACK_MAX_DURATION = 10.0 +ButtonType = car.CarState.ButtonEvent.Type + + +def main(): + params = Params() + pm = messaging.PubMaster(['userBookmark', 'audioFeedback']) + sm = messaging.SubMaster(['rawAudioData', 'bookmarkButton', 'carState']) + should_record_audio = False + block_num = 0 + waiting_for_release = False + early_stop_triggered = False + + while True: + sm.update() + should_send_bookmark = False + + # TODO: https://github.com/commaai/openpilot/issues/36015 + if False and sm.updated['carState'] and sm['carState'].canValid: + for be in sm['carState'].buttonEvents: + if be.type == ButtonType.lkas: + if be.pressed: + if not should_record_audio: + if params.get_bool("RecordAudioFeedback"): # Start recording on first press if toggle set + should_record_audio = True + block_num = 0 + waiting_for_release = False + early_stop_triggered = False + cloudlog.info("LKAS button pressed - starting 10-second audio feedback") + else: + should_send_bookmark = True # immediately send bookmark if toggle false + cloudlog.info("LKAS button pressed - bookmarking") + elif should_record_audio and not waiting_for_release: # Wait for release of second press to stop recording early + waiting_for_release = True + elif waiting_for_release: # Second press released + waiting_for_release = False + early_stop_triggered = True + cloudlog.info("LKAS button released - ending recording early") + + if should_record_audio and sm.updated['rawAudioData']: + raw_audio = sm['rawAudioData'] + msg = messaging.new_message('audioFeedback', valid=True) + msg.audioFeedback.audio.data = raw_audio.data + msg.audioFeedback.audio.sampleRate = raw_audio.sampleRate + msg.audioFeedback.blockNum = block_num + block_num += 1 + if (block_num * SAMPLE_BUFFER / SAMPLE_RATE) >= FEEDBACK_MAX_DURATION or early_stop_triggered: # Check for timeout or early stop + should_send_bookmark = True # send bookmark at end of audio segment + should_record_audio = False + early_stop_triggered = False + cloudlog.info("10-second recording completed or second button press - stopping audio feedback") + pm.send('audioFeedback', msg) + + if sm.updated['bookmarkButton']: + cloudlog.info("Bookmark button pressed!") + should_send_bookmark = True + + if should_send_bookmark: + msg = messaging.new_message('userBookmark', valid=True) + pm.send('userBookmark', msg) + + +if __name__ == '__main__': + main() diff --git a/selfdrive/ui/installer/continue_openpilot.sh b/selfdrive/ui/installer/continue_openpilot.sh new file mode 100755 index 0000000000..ed41ab6f3f --- /dev/null +++ b/selfdrive/ui/installer/continue_openpilot.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd /data/openpilot +exec ./launch_openpilot.sh diff --git a/selfdrive/ui/installer/installer.cc b/selfdrive/ui/installer/installer.cc new file mode 100644 index 0000000000..a9b84b5c06 --- /dev/null +++ b/selfdrive/ui/installer/installer.cc @@ -0,0 +1,207 @@ +#include +#include +#include +#include + +#include "common/swaglog.h" +#include "common/util.h" +#include "third_party/raylib/include/raylib.h" + +int freshClone(); +int cachedFetch(const std::string &cache); +int executeGitCommand(const std::string &cmd); + +std::string get_str(std::string const s) { + std::string::size_type pos = s.find('?'); + assert(pos != std::string::npos); + return s.substr(0, pos); +} + +// Leave some extra space for the fork installer +const std::string GIT_URL = get_str("https://github.com/commaai/openpilot.git" "? "); +const std::string BRANCH_STR = get_str(BRANCH "? "); + +#define GIT_SSH_URL "git@github.com:commaai/openpilot.git" +#define CONTINUE_PATH "/data/continue.sh" + +const std::string INSTALL_PATH = "/data/openpilot"; +const std::string VALID_CACHE_PATH = "/data/.openpilot_cache"; + +#define TMP_INSTALL_PATH "/data/tmppilot" + +const int FONT_SIZE = 120; + +extern const uint8_t str_continue[] asm("_binary_selfdrive_ui_installer_continue_openpilot_sh_start"); +extern const uint8_t str_continue_end[] asm("_binary_selfdrive_ui_installer_continue_openpilot_sh_end"); +extern const uint8_t inter_ttf[] asm("_binary_selfdrive_ui_installer_inter_ascii_ttf_start"); +extern const uint8_t inter_ttf_end[] asm("_binary_selfdrive_ui_installer_inter_ascii_ttf_end"); + +Font font; + +void run(const char* cmd) { + int err = std::system(cmd); + assert(err == 0); +} + +void finishInstall() { + BeginDrawing(); + ClearBackground(BLACK); + const char *m = "Finishing install..."; + int text_width = MeasureText(m, FONT_SIZE); + DrawTextEx(font, m, (Vector2){(float)(GetScreenWidth() - text_width)/2 + FONT_SIZE, (float)(GetScreenHeight() - FONT_SIZE)/2}, FONT_SIZE, 0, WHITE); + EndDrawing(); + util::sleep_for(60 * 1000); +} + +void renderProgress(int progress) { + BeginDrawing(); + ClearBackground(BLACK); + DrawTextEx(font, "Installing...", (Vector2){150, 290}, 110, 0, WHITE); + Rectangle bar = {150, 570, (float)GetScreenWidth() - 300, 72}; + DrawRectangleRec(bar, (Color){41, 41, 41, 255}); + progress = std::clamp(progress, 0, 100); + bar.width *= progress / 100.0f; + DrawRectangleRec(bar, (Color){70, 91, 234, 255}); + DrawTextEx(font, (std::to_string(progress) + "%").c_str(), (Vector2){150, 670}, 85, 0, WHITE); + EndDrawing(); +} + +int doInstall() { + // wait for valid time + while (!util::system_time_valid()) { + util::sleep_for(500); + LOGD("Waiting for valid time"); + } + + // cleanup previous install attempts + run("rm -rf " TMP_INSTALL_PATH); + + // do the install + if (util::file_exists(INSTALL_PATH) && util::file_exists(VALID_CACHE_PATH)) { + return cachedFetch(INSTALL_PATH); + } else { + return freshClone(); + } +} + +int freshClone() { + LOGD("Doing fresh clone"); + std::string cmd = util::string_format("git clone --progress %s -b %s --depth=1 --recurse-submodules %s 2>&1", + GIT_URL.c_str(), BRANCH_STR.c_str(), TMP_INSTALL_PATH); + return executeGitCommand(cmd); +} + +int cachedFetch(const std::string &cache) { + LOGD("Fetching with cache: %s", cache.c_str()); + + run(util::string_format("cp -rp %s %s", cache.c_str(), TMP_INSTALL_PATH).c_str()); + run(util::string_format("cd %s && git remote set-branches --add origin %s", TMP_INSTALL_PATH, BRANCH_STR.c_str()).c_str()); + + renderProgress(10); + + return executeGitCommand(util::string_format("cd %s && git fetch --progress origin %s 2>&1", TMP_INSTALL_PATH, BRANCH_STR.c_str())); +} + +int executeGitCommand(const std::string &cmd) { + static const std::array stages = { + // prefix, weight in percentage + std::pair{"Receiving objects: ", 91}, + std::pair{"Resolving deltas: ", 2}, + std::pair{"Updating files: ", 7}, + }; + + FILE *pipe = popen(cmd.c_str(), "r"); + if (!pipe) return -1; + + char buffer[512]; + while (fgets(buffer, sizeof(buffer), pipe) != nullptr) { + std::string line(buffer); + int base = 0; + for (const auto &[text, weight] : stages) { + if (line.find(text) != std::string::npos) { + size_t percentPos = line.find("%"); + if (percentPos != std::string::npos && percentPos >= 3) { + int percent = std::stoi(line.substr(percentPos - 3, 3)); + int progress = base + int(percent / 100. * weight); + renderProgress(progress); + } + break; + } + base += weight; + } + } + return pclose(pipe); +} + +void cloneFinished(int exitCode) { + LOGD("git finished with %d", exitCode); + assert(exitCode == 0); + + renderProgress(100); + + // ensure correct branch is checked out + int err = chdir(TMP_INSTALL_PATH); + assert(err == 0); + run(("git checkout " + BRANCH_STR).c_str()); + run(("git reset --hard origin/" + BRANCH_STR).c_str()); + run("git submodule update --init"); + + // move into place + run(("rm -f " + VALID_CACHE_PATH).c_str()); + run(("rm -rf " + INSTALL_PATH).c_str()); + run(util::string_format("mv %s %s", TMP_INSTALL_PATH, INSTALL_PATH.c_str()).c_str()); + +#ifdef INTERNAL + run("mkdir -p /data/params/d/"); + + // https://github.com/commaci2.keys + const std::string ssh_keys = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMX2kU8eBZyEWmbq0tjMPxksWWVuIV/5l64GabcYbdpI"; + std::map params = { + {"SshEnabled", "1"}, + {"RecordFrontLock", "1"}, + {"GithubSshKeys", ssh_keys}, + }; + for (const auto& [key, value] : params) { + std::ofstream param; + param.open("/data/params/d/" + key); + param << value; + param.close(); + } + run(("cd " + INSTALL_PATH + " && " + "git remote set-url origin --push " GIT_SSH_URL " && " + "git config --replace-all remote.origin.fetch \"+refs/heads/*:refs/remotes/origin/*\"").c_str()); +#endif + + // write continue.sh + FILE *of = fopen("/data/continue.sh.new", "wb"); + assert(of != NULL); + + size_t num = str_continue_end - str_continue; + size_t num_written = fwrite(str_continue, 1, num, of); + assert(num == num_written); + fclose(of); + + run("chmod +x /data/continue.sh.new"); + run("mv /data/continue.sh.new " CONTINUE_PATH); + + // wait for the installed software's UI to take over + finishInstall(); +} + +int main(int argc, char *argv[]) { + InitWindow(2160, 1080, "Installer"); + font = LoadFontFromMemory(".ttf", inter_ttf, inter_ttf_end - inter_ttf, FONT_SIZE, NULL, 0); + SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR); + + if (util::file_exists(CONTINUE_PATH)) { + finishInstall(); + } else { + renderProgress(0); + int result = doInstall(); + cloneFinished(result); + } + + CloseWindow(); + UnloadFont(font); + return 0; +} diff --git a/selfdrive/ui/installer/inter-ascii.ttf b/selfdrive/ui/installer/inter-ascii.ttf new file mode 100644 index 0000000000..6ca06dd0c7 Binary files /dev/null and b/selfdrive/ui/installer/inter-ascii.ttf differ diff --git a/selfdrive/ui/layouts/__init__.py b/selfdrive/ui/layouts/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/ui/layouts/home.py b/selfdrive/ui/layouts/home.py new file mode 100644 index 0000000000..f7f57c680d --- /dev/null +++ b/selfdrive/ui/layouts/home.py @@ -0,0 +1,218 @@ +import time +import pyray as rl +from collections.abc import Callable +from enum import IntEnum +from openpilot.common.params import Params +from openpilot.selfdrive.ui.widgets.offroad_alerts import UpdateAlert, OffroadAlert +from openpilot.selfdrive.ui.widgets.exp_mode_button import ExperimentalModeButton +from openpilot.selfdrive.ui.widgets.prime import PrimeWidget +from openpilot.selfdrive.ui.widgets.setup import SetupWidget +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos +from openpilot.system.ui.widgets.label import gui_label +from openpilot.system.ui.widgets import Widget + +HEADER_HEIGHT = 80 +HEAD_BUTTON_FONT_SIZE = 40 +CONTENT_MARGIN = 40 +SPACING = 25 +RIGHT_COLUMN_WIDTH = 750 +REFRESH_INTERVAL = 10.0 + +PRIME_BG_COLOR = rl.Color(51, 51, 51, 255) + + +class HomeLayoutState(IntEnum): + HOME = 0 + UPDATE = 1 + ALERTS = 2 + + +class HomeLayout(Widget): + def __init__(self): + super().__init__() + self.params = Params() + + self.update_alert = UpdateAlert() + self.offroad_alert = OffroadAlert() + + self.current_state = HomeLayoutState.HOME + self.last_refresh = 0 + self.settings_callback: callable | None = None + + self.update_available = False + self.alert_count = 0 + self._prev_update_available = False + self._prev_alerts_present = False + + self.header_rect = rl.Rectangle(0, 0, 0, 0) + self.content_rect = rl.Rectangle(0, 0, 0, 0) + self.left_column_rect = rl.Rectangle(0, 0, 0, 0) + self.right_column_rect = rl.Rectangle(0, 0, 0, 0) + + self.update_notif_rect = rl.Rectangle(0, 0, 200, HEADER_HEIGHT - 10) + self.alert_notif_rect = rl.Rectangle(0, 0, 220, HEADER_HEIGHT - 10) + + self._prime_widget = PrimeWidget() + self._setup_widget = SetupWidget() + + self._exp_mode_button = ExperimentalModeButton() + self._setup_callbacks() + + def show_event(self): + self.last_refresh = time.monotonic() + self._refresh() + + def _setup_callbacks(self): + self.update_alert.set_dismiss_callback(lambda: self._set_state(HomeLayoutState.HOME)) + self.offroad_alert.set_dismiss_callback(lambda: self._set_state(HomeLayoutState.HOME)) + + def set_settings_callback(self, callback: Callable): + self.settings_callback = callback + + def _set_state(self, state: HomeLayoutState): + self.current_state = state + + def _render(self, rect: rl.Rectangle): + current_time = time.monotonic() + if current_time - self.last_refresh >= REFRESH_INTERVAL: + self._refresh() + self.last_refresh = current_time + + self._render_header() + + # Render content based on current state + if self.current_state == HomeLayoutState.HOME: + self._render_home_content() + elif self.current_state == HomeLayoutState.UPDATE: + self._render_update_view() + elif self.current_state == HomeLayoutState.ALERTS: + self._render_alerts_view() + + def _update_state(self): + self.header_rect = rl.Rectangle( + self._rect.x + CONTENT_MARGIN, self._rect.y + CONTENT_MARGIN, self._rect.width - 2 * CONTENT_MARGIN, HEADER_HEIGHT + ) + + content_y = self._rect.y + CONTENT_MARGIN + HEADER_HEIGHT + SPACING + content_height = self._rect.height - CONTENT_MARGIN - HEADER_HEIGHT - SPACING - CONTENT_MARGIN + + self.content_rect = rl.Rectangle( + self._rect.x + CONTENT_MARGIN, content_y, self._rect.width - 2 * CONTENT_MARGIN, content_height + ) + + left_width = self.content_rect.width - RIGHT_COLUMN_WIDTH - SPACING + + self.left_column_rect = rl.Rectangle(self.content_rect.x, self.content_rect.y, left_width, self.content_rect.height) + + self.right_column_rect = rl.Rectangle( + self.content_rect.x + left_width + SPACING, self.content_rect.y, RIGHT_COLUMN_WIDTH, self.content_rect.height + ) + + self.update_notif_rect.x = self.header_rect.x + self.update_notif_rect.y = self.header_rect.y + (self.header_rect.height - 60) // 2 + + notif_x = self.header_rect.x + (220 if self.update_available else 0) + self.alert_notif_rect.x = notif_x + self.alert_notif_rect.y = self.header_rect.y + (self.header_rect.height - 60) // 2 + + def _handle_mouse_release(self, mouse_pos: MousePos): + super()._handle_mouse_release(mouse_pos) + + if self.update_available and rl.check_collision_point_rec(mouse_pos, self.update_notif_rect): + self._set_state(HomeLayoutState.UPDATE) + elif self.alert_count > 0 and rl.check_collision_point_rec(mouse_pos, self.alert_notif_rect): + self._set_state(HomeLayoutState.ALERTS) + + def _render_header(self): + font = gui_app.font(FontWeight.MEDIUM) + + version_text_width = self.header_rect.width + + # Update notification button + if self.update_available: + version_text_width -= self.update_notif_rect.width + + # Highlight if currently viewing updates + highlight_color = rl.Color(75, 95, 255, 255) if self.current_state == HomeLayoutState.UPDATE else rl.Color(54, 77, 239, 255) + rl.draw_rectangle_rounded(self.update_notif_rect, 0.3, 10, highlight_color) + + text = "UPDATE" + text_width = measure_text_cached(font, text, HEAD_BUTTON_FONT_SIZE).x + text_x = self.update_notif_rect.x + (self.update_notif_rect.width - text_width) // 2 + text_y = self.update_notif_rect.y + (self.update_notif_rect.height - HEAD_BUTTON_FONT_SIZE) // 2 + rl.draw_text_ex(font, text, rl.Vector2(int(text_x), int(text_y)), HEAD_BUTTON_FONT_SIZE, 0, rl.WHITE) + + # Alert notification button + if self.alert_count > 0: + version_text_width -= self.alert_notif_rect.width + + # Highlight if currently viewing alerts + highlight_color = rl.Color(255, 70, 70, 255) if self.current_state == HomeLayoutState.ALERTS else rl.Color(226, 44, 44, 255) + rl.draw_rectangle_rounded(self.alert_notif_rect, 0.3, 10, highlight_color) + + alert_text = f"{self.alert_count} ALERT{'S' if self.alert_count > 1 else ''}" + text_width = measure_text_cached(font, alert_text, HEAD_BUTTON_FONT_SIZE).x + text_x = self.alert_notif_rect.x + (self.alert_notif_rect.width - text_width) // 2 + text_y = self.alert_notif_rect.y + (self.alert_notif_rect.height - HEAD_BUTTON_FONT_SIZE) // 2 + rl.draw_text_ex(font, alert_text, rl.Vector2(int(text_x), int(text_y)), HEAD_BUTTON_FONT_SIZE, 0, rl.WHITE) + + # Version text (right aligned) + if self.update_available or self.alert_count > 0: + version_text_width -= SPACING * 1.5 + + version_rect = rl.Rectangle(self.header_rect.x + self.header_rect.width - version_text_width, self.header_rect.y, + version_text_width, self.header_rect.height) + gui_label(version_rect, self._get_version_text(), 48, rl.WHITE, alignment=rl.GuiTextAlignment.TEXT_ALIGN_RIGHT) + + def _render_home_content(self): + self._render_left_column() + self._render_right_column() + + def _render_update_view(self): + self.update_alert.render(self.content_rect) + + def _render_alerts_view(self): + self.offroad_alert.render(self.content_rect) + + def _render_left_column(self): + self._prime_widget.render(self.left_column_rect) + + def _render_right_column(self): + exp_height = 125 + exp_rect = rl.Rectangle( + self.right_column_rect.x, self.right_column_rect.y, self.right_column_rect.width, exp_height + ) + self._exp_mode_button.render(exp_rect) + + setup_rect = rl.Rectangle( + self.right_column_rect.x, + self.right_column_rect.y + exp_height + SPACING, + self.right_column_rect.width, + self.right_column_rect.height - exp_height - SPACING, + ) + self._setup_widget.render(setup_rect) + + def _refresh(self): + # TODO: implement _update_state with a timer + update_available = self.update_alert.refresh() + alert_count = self.offroad_alert.refresh() + alerts_present = alert_count > 0 + + # Show panels on transition from no alert/update to any alerts/update + if not update_available and not alerts_present: + self.current_state = HomeLayoutState.HOME + elif update_available and ((not self._prev_update_available) or (not alerts_present and self.current_state == HomeLayoutState.ALERTS)): + self.current_state = HomeLayoutState.UPDATE + elif alerts_present and ((not self._prev_alerts_present) or (not update_available and self.current_state == HomeLayoutState.UPDATE)): + self.current_state = HomeLayoutState.ALERTS + + self.update_available = update_available + self.alert_count = alert_count + self._prev_update_available = update_available + self._prev_alerts_present = alerts_present + + def _get_version_text(self) -> str: + brand = "openpilot" + description = self.params.get("UpdaterCurrentDescription") + return f"{brand} {description}" if description else brand diff --git a/selfdrive/ui/layouts/main.py b/selfdrive/ui/layouts/main.py new file mode 100644 index 0000000000..a2401ef8be --- /dev/null +++ b/selfdrive/ui/layouts/main.py @@ -0,0 +1,107 @@ +import pyray as rl +from enum import IntEnum +import cereal.messaging as messaging +from openpilot.system.ui.lib.application import gui_app +from openpilot.selfdrive.ui.layouts.sidebar import Sidebar, SIDEBAR_WIDTH +from openpilot.selfdrive.ui.layouts.home import HomeLayout +from openpilot.selfdrive.ui.layouts.settings.settings import SettingsLayout, PanelType +from openpilot.selfdrive.ui.onroad.augmented_road_view import AugmentedRoadView +from openpilot.selfdrive.ui.ui_state import device, ui_state +from openpilot.system.ui.widgets import Widget +from openpilot.selfdrive.ui.layouts.onboarding import OnboardingWindow + + +class MainState(IntEnum): + HOME = 0 + SETTINGS = 1 + ONROAD = 2 + + +class MainLayout(Widget): + def __init__(self): + super().__init__() + + self._pm = messaging.PubMaster(['bookmarkButton']) + + self._sidebar = Sidebar() + self._current_mode = MainState.HOME + self._prev_onroad = False + + # Initialize layouts + self._layouts = {MainState.HOME: HomeLayout(), MainState.SETTINGS: SettingsLayout(), MainState.ONROAD: AugmentedRoadView()} + + self._sidebar_rect = rl.Rectangle(0, 0, 0, 0) + self._content_rect = rl.Rectangle(0, 0, 0, 0) + + # Set callbacks + self._setup_callbacks() + + # Start onboarding if terms or training not completed + self._onboarding_window = OnboardingWindow() + if not self._onboarding_window.completed: + gui_app.set_modal_overlay(self._onboarding_window) + + def _render(self, _): + self._handle_onroad_transition() + self._render_main_content() + + def _setup_callbacks(self): + self._sidebar.set_callbacks(on_settings=self._on_settings_clicked, + on_flag=self._on_bookmark_clicked, + open_settings=lambda: self.open_settings(PanelType.TOGGLES)) + self._layouts[MainState.HOME]._setup_widget.set_open_settings_callback(lambda: self.open_settings(PanelType.FIREHOSE)) + self._layouts[MainState.SETTINGS].set_callbacks(on_close=self._set_mode_for_state) + self._layouts[MainState.ONROAD].set_click_callback(self._on_onroad_clicked) + device.add_interactive_timeout_callback(self._set_mode_for_state) + + def _update_layout_rects(self): + self._sidebar_rect = rl.Rectangle(self._rect.x, self._rect.y, SIDEBAR_WIDTH, self._rect.height) + + x_offset = SIDEBAR_WIDTH if self._sidebar.is_visible else 0 + self._content_rect = rl.Rectangle(self._rect.y + x_offset, self._rect.y, self._rect.width - x_offset, self._rect.height) + + def _handle_onroad_transition(self): + if ui_state.started != self._prev_onroad: + self._prev_onroad = ui_state.started + + self._set_mode_for_state() + + def _set_mode_for_state(self): + if ui_state.started: + # Don't hide sidebar from interactive timeout + if self._current_mode != MainState.ONROAD: + self._sidebar.set_visible(False) + self._set_current_layout(MainState.ONROAD) + else: + self._set_current_layout(MainState.HOME) + self._sidebar.set_visible(True) + + def _set_current_layout(self, layout: MainState): + if layout != self._current_mode: + self._layouts[self._current_mode].hide_event() + self._current_mode = layout + self._layouts[self._current_mode].show_event() + + def open_settings(self, panel_type: PanelType): + self._layouts[MainState.SETTINGS].set_current_panel(panel_type) + self._set_current_layout(MainState.SETTINGS) + self._sidebar.set_visible(False) + + def _on_settings_clicked(self): + self.open_settings(PanelType.DEVICE) + + def _on_bookmark_clicked(self): + user_bookmark = messaging.new_message('bookmarkButton') + user_bookmark.valid = True + self._pm.send('bookmarkButton', user_bookmark) + + def _on_onroad_clicked(self): + self._sidebar.set_visible(not self._sidebar.is_visible) + + def _render_main_content(self): + # Render sidebar + if self._sidebar.is_visible: + self._sidebar.render(self._sidebar_rect) + + content_rect = self._content_rect if self._sidebar.is_visible else self._rect + self._layouts[self._current_mode].render(content_rect) diff --git a/selfdrive/ui/layouts/onboarding.py b/selfdrive/ui/layouts/onboarding.py new file mode 100644 index 0000000000..ea6fedebf7 --- /dev/null +++ b/selfdrive/ui/layouts/onboarding.py @@ -0,0 +1,197 @@ +import os +import re +from enum import IntEnum + +import pyray as rl +from openpilot.common.basedir import BASEDIR +from openpilot.system.ui.lib.application import FontWeight, gui_app +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle +from openpilot.system.ui.widgets.label import Label, TextAlignment +from openpilot.selfdrive.ui.ui_state import ui_state + +DEBUG = False + +STEP_RECTS = [rl.Rectangle(104, 800, 633, 175), rl.Rectangle(1835, 0, 2159, 1080), rl.Rectangle(1835, 0, 2156, 1080), + rl.Rectangle(1526, 473, 427, 472), rl.Rectangle(1643, 441, 217, 223), rl.Rectangle(1835, 0, 2155, 1080), + rl.Rectangle(1786, 591, 267, 236), rl.Rectangle(1353, 0, 804, 1080), rl.Rectangle(1458, 485, 633, 211), + rl.Rectangle(95, 794, 1158, 187), rl.Rectangle(1560, 170, 392, 397), rl.Rectangle(1835, 0, 2159, 1080), + rl.Rectangle(1351, 0, 807, 1080), rl.Rectangle(1835, 0, 2158, 1080), rl.Rectangle(1531, 82, 441, 920), + rl.Rectangle(1336, 438, 490, 393), rl.Rectangle(1835, 0, 2159, 1080), rl.Rectangle(1835, 0, 2159, 1080), + rl.Rectangle(87, 795, 1187, 186)] + +DM_RECORD_STEP = 9 +DM_RECORD_YES_RECT = rl.Rectangle(695, 794, 558, 187) + +RESTART_TRAINING_RECT = rl.Rectangle(87, 795, 472, 186) + + +class OnboardingState(IntEnum): + TERMS = 0 + ONBOARDING = 1 + DECLINE = 2 + + +class TrainingGuide(Widget): + def __init__(self, completed_callback=None): + super().__init__() + self._completed_callback = completed_callback + + self._step = 0 + self._load_images() + + def _load_images(self): + self._images = [] + paths = [fn for fn in os.listdir(os.path.join(BASEDIR, "selfdrive/assets/training")) if re.match(r'^step\d*\.png$', fn)] + paths = sorted(paths, key=lambda x: int(re.search(r'\d+', x).group())) + for fn in paths: + path = os.path.join(BASEDIR, "selfdrive/assets/training", fn) + self._images.append(gui_app.texture(path, gui_app.width, gui_app.height)) + + def _handle_mouse_release(self, mouse_pos): + if rl.check_collision_point_rec(mouse_pos, STEP_RECTS[self._step]): + # Record DM camera? + if self._step == DM_RECORD_STEP: + yes = rl.check_collision_point_rec(mouse_pos, DM_RECORD_YES_RECT) + print(f"putting RecordFront to {yes}") + ui_state.params.put_bool("RecordFront", yes) + + # Restart training? + elif self._step == len(self._images) - 1: + if rl.check_collision_point_rec(mouse_pos, RESTART_TRAINING_RECT): + self._step = -1 + + self._step += 1 + + # Finished? + if self._step >= len(self._images): + self._step = 0 + if self._completed_callback: + self._completed_callback() + + def _render(self, _): + rl.draw_texture(self._images[self._step], 0, 0, rl.WHITE) + + # progress bar + if 0 < self._step < len(STEP_RECTS) - 1: + h = 20 + w = int((self._step / (len(STEP_RECTS) - 1)) * self._rect.width) + rl.draw_rectangle(int(self._rect.x), int(self._rect.y + self._rect.height - h), + w, h, rl.Color(70, 91, 234, 255)) + + if DEBUG: + rl.draw_rectangle_lines_ex(STEP_RECTS[self._step], 3, rl.RED) + + return -1 + + +class TermsPage(Widget): + def __init__(self, on_accept=None, on_decline=None): + super().__init__() + self._on_accept = on_accept + self._on_decline = on_decline + + self._title = Label("Welcome to openpilot", font_size=90, font_weight=FontWeight.BOLD, text_alignment=TextAlignment.LEFT) + self._desc = Label("You must accept the Terms and Conditions to use openpilot. Read the latest terms at https://comma.ai/terms before continuing.", + font_size=90, font_weight=FontWeight.MEDIUM, text_alignment=TextAlignment.LEFT) + + self._decline_btn = Button("Decline", click_callback=on_decline) + self._accept_btn = Button("Agree", button_style=ButtonStyle.PRIMARY, click_callback=on_accept) + + def _render(self, _): + welcome_x = self._rect.x + 165 + welcome_y = self._rect.y + 165 + welcome_rect = rl.Rectangle(welcome_x, welcome_y, self._rect.width - welcome_x, 90) + self._title.render(welcome_rect) + + desc_x = welcome_x + # TODO: Label doesn't top align when wrapping + desc_y = welcome_y - 100 + desc_rect = rl.Rectangle(desc_x, desc_y, self._rect.width - desc_x, self._rect.height - desc_y - 250) + self._desc.render(desc_rect) + + btn_y = self._rect.y + self._rect.height - 160 - 45 + btn_width = (self._rect.width - 45 * 3) / 2 + self._decline_btn.render(rl.Rectangle(self._rect.x + 45, btn_y, btn_width, 160)) + self._accept_btn.render(rl.Rectangle(self._rect.x + 45 * 2 + btn_width, btn_y, btn_width, 160)) + + if DEBUG: + rl.draw_rectangle_lines_ex(welcome_rect, 3, rl.RED) + rl.draw_rectangle_lines_ex(desc_rect, 3, rl.RED) + + return -1 + + +class DeclinePage(Widget): + def __init__(self, back_callback=None): + super().__init__() + self._text = Label("You must accept the Terms and Conditions in order to use openpilot.", + font_size=90, font_weight=FontWeight.MEDIUM, text_alignment=TextAlignment.LEFT) + self._back_btn = Button("Back", click_callback=back_callback) + self._uninstall_btn = Button("Decline, uninstall openpilot", button_style=ButtonStyle.DANGER, + click_callback=self._on_uninstall_clicked) + + def _on_uninstall_clicked(self): + ui_state.params.put_bool("DoUninstall", True) + gui_app.request_close() + + def _render(self, _): + btn_y = self._rect.y + self._rect.height - 160 - 45 + btn_width = (self._rect.width - 45 * 3) / 2 + self._back_btn.render(rl.Rectangle(self._rect.x + 45, btn_y, btn_width, 160)) + self._uninstall_btn.render(rl.Rectangle(self._rect.x + 45 * 2 + btn_width, btn_y, btn_width, 160)) + + # text rect in middle of top and button + text_height = btn_y - (200 + 45) + text_rect = rl.Rectangle(self._rect.x + 165, self._rect.y + (btn_y - text_height) / 2 + 10, self._rect.width - (165 * 2), text_height) + if DEBUG: + rl.draw_rectangle_lines_ex(text_rect, 3, rl.RED) + self._text.render(text_rect) + + +class OnboardingWindow(Widget): + def __init__(self): + super().__init__() + self._current_terms_version = ui_state.params.get("TermsVersion") + self._current_training_version = ui_state.params.get("TrainingVersion") + self._accepted_terms: bool = ui_state.params.get("HasAcceptedTerms") == self._current_terms_version + self._training_done: bool = ui_state.params.get("CompletedTrainingVersion") == self._current_training_version + + self._state = OnboardingState.TERMS if not self._accepted_terms else OnboardingState.ONBOARDING + + # Windows + self._terms = TermsPage(on_accept=self._on_terms_accepted, on_decline=self._on_terms_declined) + self._training_guide: TrainingGuide | None = None + self._decline_page = DeclinePage(back_callback=self._on_decline_back) + + @property + def completed(self) -> bool: + return self._accepted_terms and self._training_done + + def _on_terms_declined(self): + self._state = OnboardingState.DECLINE + + def _on_decline_back(self): + self._state = OnboardingState.TERMS + + def _on_terms_accepted(self): + ui_state.params.put("HasAcceptedTerms", self._current_terms_version) + self._state = OnboardingState.ONBOARDING + if self._training_done: + gui_app.set_modal_overlay(None) + + def _on_completed_training(self): + ui_state.params.put("CompletedTrainingVersion", self._current_training_version) + gui_app.set_modal_overlay(None) + + def _render(self, _): + if self._training_guide is None: + self._training_guide = TrainingGuide(completed_callback=self._on_completed_training) + + if self._state == OnboardingState.TERMS: + self._terms.render(self._rect) + if self._state == OnboardingState.ONBOARDING: + self._training_guide.render(self._rect) + elif self._state == OnboardingState.DECLINE: + self._decline_page.render(self._rect) + return -1 diff --git a/selfdrive/ui/layouts/settings/developer.py b/selfdrive/ui/layouts/settings/developer.py new file mode 100644 index 0000000000..cfef0f84d1 --- /dev/null +++ b/selfdrive/ui/layouts/settings/developer.py @@ -0,0 +1,61 @@ +from openpilot.common.params import Params +from openpilot.selfdrive.ui.widgets.ssh_key import ssh_key_item +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.list_view import toggle_item +from openpilot.system.ui.widgets.scroller import Scroller + +# Description constants +DESCRIPTIONS = { + 'enable_adb': ( + "ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. " + + "See https://docs.comma.ai/how-to/connect-to-comma for more info." + ), + 'joystick_debug_mode': "Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)", + 'ssh_key': ( + "Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username " + + "other than your own. A comma employee will NEVER ask you to add their GitHub username." + ), +} + + +class DeveloperLayout(Widget): + def __init__(self): + super().__init__() + self._params = Params() + items = [ + toggle_item( + "Enable ADB", + description=DESCRIPTIONS["enable_adb"], + initial_state=self._params.get_bool("AdbEnabled"), + callback=self._on_enable_adb, + ), + ssh_key_item("SSH Key", description=DESCRIPTIONS["ssh_key"]), + toggle_item( + "Joystick Debug Mode", + description=DESCRIPTIONS["joystick_debug_mode"], + initial_state=self._params.get_bool("JoystickDebugMode"), + callback=self._on_joystick_debug_mode, + ), + toggle_item( + "Longitudinal Maneuver Mode", + description="", + initial_state=self._params.get_bool("LongitudinalManeuverMode"), + callback=self._on_long_maneuver_mode, + ), + toggle_item( + "openpilot Longitudinal Control (Alpha)", + description="", + initial_state=self._params.get_bool("AlphaLongitudinalEnabled"), + callback=self._on_alpha_long_enabled, + ), + ] + + self._scroller = Scroller(items, line_separator=True, spacing=0) + + def _render(self, rect): + self._scroller.render(rect) + + def _on_enable_adb(self): pass + def _on_joystick_debug_mode(self): pass + def _on_long_maneuver_mode(self): pass + def _on_alpha_long_enabled(self): pass diff --git a/selfdrive/ui/layouts/settings/device.py b/selfdrive/ui/layouts/settings/device.py new file mode 100644 index 0000000000..c41c8b0a26 --- /dev/null +++ b/selfdrive/ui/layouts/settings/device.py @@ -0,0 +1,151 @@ +import os +import json + +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.selfdrive.ui.onroad.driver_camera_dialog import DriverCameraDialog +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.selfdrive.ui.layouts.onboarding import TrainingGuide +from openpilot.selfdrive.ui.widgets.pairing_dialog import PairingDialog +from openpilot.system.hardware import TICI +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.widgets import Widget, DialogResult +from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dialog +from openpilot.system.ui.widgets.html_render import HtmlModal +from openpilot.system.ui.widgets.list_view import text_item, button_item, dual_button_item +from openpilot.system.ui.widgets.option_dialog import MultiOptionDialog +from openpilot.system.ui.widgets.scroller import Scroller + +# Description constants +DESCRIPTIONS = { + 'pair_device': "Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.", + 'driver_camera': "Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)", + 'reset_calibration': ( + "openpilot requires the device to be mounted within 4° left or right and within 5° " + + "up or 9° down. openpilot is continuously calibrating, resetting is rarely required." + ), + 'review_guide': "Review the rules, features, and limitations of openpilot", +} + + +class DeviceLayout(Widget): + def __init__(self): + super().__init__() + + self._params = Params() + self._select_language_dialog: MultiOptionDialog | None = None + self._driver_camera: DriverCameraDialog | None = None + self._pair_device_dialog: PairingDialog | None = None + self._fcc_dialog: HtmlModal | None = None + self._training_guide: TrainingGuide | None = None + + items = self._initialize_items() + self._scroller = Scroller(items, line_separator=True, spacing=0) + + def _initialize_items(self): + dongle_id = self._params.get("DongleId") or "N/A" + serial = self._params.get("HardwareSerial") or "N/A" + + self._pair_device_btn = button_item("Pair Device", "PAIR", DESCRIPTIONS['pair_device'], callback=self._pair_device) + self._pair_device_btn.set_visible(lambda: not ui_state.prime_state.is_paired()) + + items = [ + text_item("Dongle ID", dongle_id), + text_item("Serial", serial), + self._pair_device_btn, + button_item("Driver Camera", "PREVIEW", DESCRIPTIONS['driver_camera'], callback=self._show_driver_camera, enabled=ui_state.is_offroad), + button_item("Reset Calibration", "RESET", DESCRIPTIONS['reset_calibration'], callback=self._reset_calibration_prompt), + regulatory_btn := button_item("Regulatory", "VIEW", callback=self._on_regulatory), + button_item("Review Training Guide", "REVIEW", DESCRIPTIONS['review_guide'], self._on_review_training_guide), + button_item("Change Language", "CHANGE", callback=self._show_language_selection, enabled=ui_state.is_offroad), + dual_button_item("Reboot", "Power Off", left_callback=self._reboot_prompt, right_callback=self._power_off_prompt), + ] + regulatory_btn.set_visible(TICI) + return items + + def _render(self, rect): + self._scroller.render(rect) + + def _show_language_selection(self): + try: + languages_file = os.path.join(BASEDIR, "selfdrive/ui/translations/languages.json") + with open(languages_file, encoding='utf-8') as f: + languages = json.load(f) + + self._select_language_dialog = MultiOptionDialog("Select a language", languages) + gui_app.set_modal_overlay(self._select_language_dialog, callback=self._handle_language_selection) + except FileNotFoundError: + pass + + def _handle_language_selection(self, result: int): + if result == 1 and self._select_language_dialog: + selected_language = self._select_language_dialog.selection + self._params.put("LanguageSetting", selected_language) + + self._select_language_dialog = None + + def _show_driver_camera(self): + if not self._driver_camera: + self._driver_camera = DriverCameraDialog() + + gui_app.set_modal_overlay(self._driver_camera, callback=lambda result: setattr(self, '_driver_camera', None)) + + def _reset_calibration_prompt(self): + if ui_state.engaged: + gui_app.set_modal_overlay(alert_dialog("Disengage to Reset Calibration")) + return + + dialog = ConfirmDialog("Are you sure you want to reset calibration?", "Reset") + gui_app.set_modal_overlay(dialog, callback=self._reset_calibration) + + def _reset_calibration(self, result: int): + if ui_state.engaged or result != DialogResult.CONFIRM: + return + + self._params.remove("CalibrationParams") + self._params.remove("LiveTorqueParameters") + self._params.remove("LiveParameters") + self._params.remove("LiveParametersV2") + self._params.remove("LiveDelay") + self._params.put_bool("OnroadCycleRequested", True) + + def _reboot_prompt(self): + if ui_state.engaged: + gui_app.set_modal_overlay(alert_dialog("Disengage to Reboot")) + return + + dialog = ConfirmDialog("Are you sure you want to reboot?", "Reboot") + gui_app.set_modal_overlay(dialog, callback=self._perform_reboot) + + def _perform_reboot(self, result: int): + if not ui_state.engaged and result == DialogResult.CONFIRM: + self._params.put_bool_nonblocking("DoReboot", True) + + def _power_off_prompt(self): + if ui_state.engaged: + gui_app.set_modal_overlay(alert_dialog("Disengage to Power Off")) + return + + dialog = ConfirmDialog("Are you sure you want to power off?", "Power Off") + gui_app.set_modal_overlay(dialog, callback=self._perform_power_off) + + def _perform_power_off(self, result: int): + if not ui_state.engaged and result == DialogResult.CONFIRM: + self._params.put_bool_nonblocking("DoShutdown", True) + + def _pair_device(self): + if not self._pair_device_dialog: + self._pair_device_dialog = PairingDialog() + gui_app.set_modal_overlay(self._pair_device_dialog, callback=lambda result: setattr(self, '_pair_device_dialog', None)) + + def _on_regulatory(self): + if not self._fcc_dialog: + self._fcc_dialog = HtmlModal(os.path.join(BASEDIR, "selfdrive/assets/offroad/fcc.html")) + gui_app.set_modal_overlay(self._fcc_dialog) + + def _on_review_training_guide(self): + if not self._training_guide: + def completed_callback(): + gui_app.set_modal_overlay(None) + self._training_guide = TrainingGuide(completed_callback=completed_callback) + gui_app.set_modal_overlay(self._training_guide) diff --git a/selfdrive/ui/layouts/settings/firehose.py b/selfdrive/ui/layouts/settings/firehose.py new file mode 100644 index 0000000000..7e1d3b61ba --- /dev/null +++ b/selfdrive/ui/layouts/settings/firehose.py @@ -0,0 +1,179 @@ +import pyray as rl +import time +import threading + +from openpilot.common.api import api_get +from openpilot.common.params import Params +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.widgets import Widget +from openpilot.selfdrive.ui.lib.api_helpers import get_token + +TITLE = "Firehose Mode" +DESCRIPTION = ( + "openpilot learns to drive by watching humans, like you, drive.\n\n" + + "Firehose Mode allows you to maximize your training data uploads to improve " + + "openpilot's driving models. More data means bigger models, which means better Experimental Mode." +) +INSTRUCTIONS = ( + "For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.\n\n" + + "Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.\n\n" + + "Frequently Asked Questions\n\n" + + "Does it matter how or where I drive? Nope, just drive as you normally would.\n\n" + + "Do all of my segments get pulled in Firehose Mode? No, we selectively pull a subset of your segments.\n\n" + + "What's a good USB-C adapter? Any fast phone or laptop charger should be fine.\n\n" + + "Does it matter which software I run? Yes, only upstream openpilot (and particular forks) are able to be used for training." +) + + +class FirehoseLayout(Widget): + PARAM_KEY = "ApiCache_FirehoseStats" + GREEN = rl.Color(46, 204, 113, 255) + RED = rl.Color(231, 76, 60, 255) + GRAY = rl.Color(68, 68, 68, 255) + LIGHT_GRAY = rl.Color(228, 228, 228, 255) + UPDATE_INTERVAL = 30 # seconds + + def __init__(self): + super().__init__() + self.params = Params() + self.segment_count = self._get_segment_count() + self.scroll_panel = GuiScrollPanel() + + self.running = True + self.update_thread = threading.Thread(target=self._update_loop, daemon=True) + self.update_thread.start() + self.last_update_time = 0 + + def _get_segment_count(self) -> int: + stats = self.params.get(self.PARAM_KEY) + if not stats: + return 0 + try: + return int(stats.get("firehose", 0)) + except Exception: + cloudlog.exception(f"Failed to decode firehose stats: {stats}") + return 0 + + def __del__(self): + self.running = False + if self.update_thread and self.update_thread.is_alive(): + self.update_thread.join(timeout=1.0) + + def _render(self, rect: rl.Rectangle): + # Calculate content dimensions + content_width = rect.width - 80 + content_height = self._calculate_content_height(int(content_width)) + content_rect = rl.Rectangle(rect.x, rect.y, rect.width, content_height) + + # Handle scrolling and render with clipping + scroll_offset = self.scroll_panel.update(rect, content_rect) + rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height)) + self._render_content(rect, scroll_offset) + rl.end_scissor_mode() + + def _calculate_content_height(self, content_width: int) -> int: + height = 80 # Top margin + + # Title + height += 100 + 40 + + # Description + desc_font = gui_app.font(FontWeight.NORMAL) + desc_lines = wrap_text(desc_font, DESCRIPTION, 45, content_width) + height += len(desc_lines) * 45 + 40 + + # Status section + height += 32 # Separator + status_text, _ = self._get_status() + status_lines = wrap_text(gui_app.font(FontWeight.BOLD), status_text, 60, content_width) + height += len(status_lines) * 60 + 20 + + # Contribution count (if available) + if self.segment_count > 0: + contrib_text = f"{self.segment_count} segment(s) of your driving is in the training dataset so far." + contrib_lines = wrap_text(gui_app.font(FontWeight.BOLD), contrib_text, 52, content_width) + height += len(contrib_lines) * 52 + 20 + + # Instructions section + height += 32 # Separator + inst_lines = wrap_text(gui_app.font(FontWeight.NORMAL), INSTRUCTIONS, 40, content_width) + height += len(inst_lines) * 40 + 40 # Bottom margin + + return height + + def _render_content(self, rect: rl.Rectangle, scroll_offset: float): + x = int(rect.x + 40) + y = int(rect.y + 40 + scroll_offset) + w = int(rect.width - 80) + + # Title + title_font = gui_app.font(FontWeight.MEDIUM) + rl.draw_text_ex(title_font, TITLE, rl.Vector2(x, y), 100, 0, rl.WHITE) + y += 140 + + # Description + y = self._draw_wrapped_text(x, y, w, DESCRIPTION, gui_app.font(FontWeight.NORMAL), 45, rl.WHITE) + y += 40 + + # Separator + rl.draw_rectangle(x, y, w, 2, self.GRAY) + y += 30 + + # Status + status_text, status_color = self._get_status() + y = self._draw_wrapped_text(x, y, w, status_text, gui_app.font(FontWeight.BOLD), 60, status_color) + y += 20 + + # Contribution count (if available) + if self.segment_count > 0: + contrib_text = f"{self.segment_count} segment(s) of your driving is in the training dataset so far." + y = self._draw_wrapped_text(x, y, w, contrib_text, gui_app.font(FontWeight.BOLD), 52, rl.WHITE) + y += 20 + + # Separator + rl.draw_rectangle(x, y, w, 2, self.GRAY) + y += 30 + + # Instructions + self._draw_wrapped_text(x, y, w, INSTRUCTIONS, gui_app.font(FontWeight.NORMAL), 40, self.LIGHT_GRAY) + + def _draw_wrapped_text(self, x, y, width, text, font, size, color): + wrapped = wrap_text(font, text, size, width) + for line in wrapped: + rl.draw_text_ex(font, line, rl.Vector2(x, y), size, 0, color) + y += size + return y + + def _get_status(self) -> tuple[str, rl.Color]: + network_type = ui_state.sm["deviceState"].networkType + network_metered = ui_state.sm["deviceState"].networkMetered + + if not network_metered and network_type != 0: # Not metered and connected + return "ACTIVE", self.GREEN + else: + return "INACTIVE: connect to an unmetered network", self.RED + + def _fetch_firehose_stats(self): + try: + dongle_id = self.params.get("DongleId") + if not dongle_id or dongle_id == UNREGISTERED_DONGLE_ID: + return + identity_token = get_token(dongle_id) + response = api_get(f"v1/devices/{dongle_id}/firehose_stats", access_token=identity_token) + if response.status_code == 200: + data = response.json() + self.segment_count = data.get("firehose", 0) + self.params.put(self.PARAM_KEY, data) + except Exception as e: + cloudlog.error(f"Failed to fetch firehose stats: {e}") + + def _update_loop(self): + while self.running: + if not ui_state.started: + self._fetch_firehose_stats() + time.sleep(self.UPDATE_INTERVAL) diff --git a/selfdrive/ui/layouts/settings/settings.py b/selfdrive/ui/layouts/settings/settings.py new file mode 100644 index 0000000000..d43382f199 --- /dev/null +++ b/selfdrive/ui/layouts/settings/settings.py @@ -0,0 +1,166 @@ +import pyray as rl +from dataclasses import dataclass +from enum import IntEnum +from collections.abc import Callable +from openpilot.selfdrive.ui.layouts.settings.developer import DeveloperLayout +from openpilot.selfdrive.ui.layouts.settings.device import DeviceLayout +from openpilot.selfdrive.ui.layouts.settings.firehose import FirehoseLayout +from openpilot.selfdrive.ui.layouts.settings.software import SoftwareLayout +from openpilot.selfdrive.ui.layouts.settings.toggles import TogglesLayout +from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.lib.wifi_manager import WifiManager +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.network import NetworkUI + +# Settings close button +SETTINGS_CLOSE_TEXT = "×" +SETTINGS_CLOSE_TEXT_Y_OFFSET = 8 # The '×' character isn't quite vertically centered in the font so we need to offset it a bit to fully center it + +# Constants +SIDEBAR_WIDTH = 500 +CLOSE_BTN_SIZE = 200 +NAV_BTN_HEIGHT = 110 +PANEL_MARGIN = 50 + +# Colors +SIDEBAR_COLOR = rl.BLACK +PANEL_COLOR = rl.Color(41, 41, 41, 255) +CLOSE_BTN_COLOR = rl.Color(41, 41, 41, 255) +CLOSE_BTN_PRESSED = rl.Color(59, 59, 59, 255) +TEXT_NORMAL = rl.Color(128, 128, 128, 255) +TEXT_SELECTED = rl.WHITE + + +class PanelType(IntEnum): + DEVICE = 0 + NETWORK = 1 + TOGGLES = 2 + SOFTWARE = 3 + FIREHOSE = 4 + DEVELOPER = 5 + + +@dataclass +class PanelInfo: + name: str + instance: Widget + button_rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0) + + +class SettingsLayout(Widget): + def __init__(self): + super().__init__() + self._current_panel = PanelType.DEVICE + + # Panel configuration + wifi_manager = WifiManager() + wifi_manager.set_active(False) + + self._panels = { + PanelType.DEVICE: PanelInfo("Device", DeviceLayout()), + PanelType.NETWORK: PanelInfo("Network", NetworkUI(wifi_manager)), + PanelType.TOGGLES: PanelInfo("Toggles", TogglesLayout()), + PanelType.SOFTWARE: PanelInfo("Software", SoftwareLayout()), + PanelType.FIREHOSE: PanelInfo("Firehose", FirehoseLayout()), + PanelType.DEVELOPER: PanelInfo("Developer", DeveloperLayout()), + } + + self._font_medium = gui_app.font(FontWeight.MEDIUM) + + # Callbacks + self._close_callback: Callable | None = None + + def set_callbacks(self, on_close: Callable): + self._close_callback = on_close + + def _render(self, rect: rl.Rectangle): + # Calculate layout + sidebar_rect = rl.Rectangle(rect.x, rect.y, SIDEBAR_WIDTH, rect.height) + panel_rect = rl.Rectangle(rect.x + SIDEBAR_WIDTH, rect.y, rect.width - SIDEBAR_WIDTH, rect.height) + + # Draw components + self._draw_sidebar(sidebar_rect) + self._draw_current_panel(panel_rect) + + def _draw_sidebar(self, rect: rl.Rectangle): + rl.draw_rectangle_rec(rect, SIDEBAR_COLOR) + + # Close button + close_btn_rect = rl.Rectangle( + rect.x + (rect.width - CLOSE_BTN_SIZE) / 2, rect.y + 60, CLOSE_BTN_SIZE, CLOSE_BTN_SIZE + ) + + pressed = (rl.is_mouse_button_down(rl.MouseButton.MOUSE_BUTTON_LEFT) and + rl.check_collision_point_rec(rl.get_mouse_position(), close_btn_rect)) + close_color = CLOSE_BTN_PRESSED if pressed else CLOSE_BTN_COLOR + rl.draw_rectangle_rounded(close_btn_rect, 1.0, 20, close_color) + + close_text_size = measure_text_cached(self._font_medium, SETTINGS_CLOSE_TEXT, 140) + close_text_pos = rl.Vector2( + close_btn_rect.x + (close_btn_rect.width - close_text_size.x) / 2, + close_btn_rect.y + (close_btn_rect.height - close_text_size.y) / 2 - SETTINGS_CLOSE_TEXT_Y_OFFSET, + ) + rl.draw_text_ex(self._font_medium, SETTINGS_CLOSE_TEXT, close_text_pos, 140, 0, TEXT_SELECTED) + + # Store close button rect for click detection + self._close_btn_rect = close_btn_rect + + # Navigation buttons + y = rect.y + 300 + for panel_type, panel_info in self._panels.items(): + button_rect = rl.Rectangle(rect.x + 50, y, rect.width - 150, NAV_BTN_HEIGHT) + + # Button styling + is_selected = panel_type == self._current_panel + text_color = TEXT_SELECTED if is_selected else TEXT_NORMAL + # Draw button text (right-aligned) + text_size = measure_text_cached(self._font_medium, panel_info.name, 65) + text_pos = rl.Vector2( + button_rect.x + button_rect.width - text_size.x, button_rect.y + (button_rect.height - text_size.y) / 2 + ) + rl.draw_text_ex(self._font_medium, panel_info.name, text_pos, 65, 0, text_color) + + # Store button rect for click detection + panel_info.button_rect = button_rect + + y += NAV_BTN_HEIGHT + + def _draw_current_panel(self, rect: rl.Rectangle): + rl.draw_rectangle_rounded( + rl.Rectangle(rect.x + 10, rect.y + 10, rect.width - 20, rect.height - 20), 0.04, 30, PANEL_COLOR + ) + content_rect = rl.Rectangle(rect.x + PANEL_MARGIN, rect.y + 25, rect.width - (PANEL_MARGIN * 2), rect.height - 50) + # rl.draw_rectangle_rounded(content_rect, 0.03, 30, PANEL_COLOR) + panel = self._panels[self._current_panel] + if panel.instance: + panel.instance.render(content_rect) + + def _handle_mouse_release(self, mouse_pos: MousePos) -> bool: + # Check close button + if rl.check_collision_point_rec(mouse_pos, self._close_btn_rect): + if self._close_callback: + self._close_callback() + return True + + # Check navigation buttons + for panel_type, panel_info in self._panels.items(): + if rl.check_collision_point_rec(mouse_pos, panel_info.button_rect): + self.set_current_panel(panel_type) + return True + + return False + + def set_current_panel(self, panel_type: PanelType): + if panel_type != self._current_panel: + self._panels[self._current_panel].instance.hide_event() + self._current_panel = panel_type + self._panels[self._current_panel].instance.show_event() + + def show_event(self): + super().show_event() + self._panels[self._current_panel].instance.show_event() + + def hide_event(self): + super().hide_event() + self._panels[self._current_panel].instance.hide_event() diff --git a/selfdrive/ui/layouts/settings/software.py b/selfdrive/ui/layouts/settings/software.py new file mode 100644 index 0000000000..7aebc609f8 --- /dev/null +++ b/selfdrive/ui/layouts/settings/software.py @@ -0,0 +1,161 @@ +import os +import time +import datetime +from openpilot.common.time_helpers import system_time_valid +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.widgets import Widget, DialogResult +from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog +from openpilot.system.ui.widgets.list_view import button_item, text_item, ListItem +from openpilot.system.ui.widgets.scroller import Scroller + +# TODO: remove this. updater fails to respond on startup if time is not correct +UPDATED_TIMEOUT = 10 # seconds to wait for updated to respond + + +def time_ago(date: datetime.datetime | None) -> str: + if not date: + return "never" + + if not system_time_valid(): + return date.strftime("%a %b %d %Y") + + now = datetime.datetime.now(datetime.UTC) + if date.tzinfo is None: + date = date.replace(tzinfo=datetime.UTC) + + diff_seconds = int((now - date).total_seconds()) + if diff_seconds < 60: + return "now" + if diff_seconds < 3600: + m = diff_seconds // 60 + return f"{m} minute{'s' if m != 1 else ''} ago" + if diff_seconds < 86400: + h = diff_seconds // 3600 + return f"{h} hour{'s' if h != 1 else ''} ago" + if diff_seconds < 604800: + d = diff_seconds // 86400 + return f"{d} day{'s' if d != 1 else ''} ago" + return date.strftime("%a %b %d %Y") + + +class SoftwareLayout(Widget): + def __init__(self): + super().__init__() + + self._onroad_label = ListItem(title="Updates are only downloaded while the car is off.") + self._version_item = text_item("Current Version", ui_state.params.get("UpdaterCurrentDescription") or "") + self._download_btn = button_item("Download", "CHECK", callback=self._on_download_update) + + # Install button is initially hidden + self._install_btn = button_item("Install Update", "INSTALL", callback=self._on_install_update) + self._install_btn.set_visible(False) + + # Track waiting-for-updater transition to avoid brief re-enable while still idle + self._waiting_for_updater = False + self._waiting_start_ts: float = 0.0 + + items = self._init_items() + self._scroller = Scroller(items, line_separator=True, spacing=0) + + def _init_items(self): + items = [ + self._onroad_label, + self._version_item, + self._download_btn, + self._install_btn, + button_item("Target Branch", "SELECT", callback=self._on_select_branch), + button_item("Uninstall", "UNINSTALL", callback=self._on_uninstall), + ] + return items + + def _render(self, rect): + self._scroller.render(rect) + + def _update_state(self): + # Show/hide onroad warning + self._onroad_label.set_visible(ui_state.is_onroad()) + + # Update current version and release notes + current_desc = ui_state.params.get("UpdaterCurrentDescription") or "" + current_release_notes = (ui_state.params.get("UpdaterCurrentReleaseNotes") or b"").decode("utf-8", "replace") + self._version_item.action_item.set_text(current_desc) + self._version_item.set_description(current_release_notes) + + # Update download button visibility and state + self._download_btn.set_visible(ui_state.is_offroad()) + + updater_state = ui_state.params.get("UpdaterState") or "idle" + failed_count = ui_state.params.get("UpdateFailedCount") or 0 + fetch_available = ui_state.params.get_bool("UpdaterFetchAvailable") + update_available = ui_state.params.get_bool("UpdateAvailable") + + if updater_state != "idle": + # Updater responded + self._waiting_for_updater = False + self._download_btn.action_item.set_enabled(False) + self._download_btn.action_item.set_value(updater_state) + else: + if failed_count > 0: + self._download_btn.action_item.set_value("failed to check for update") + self._download_btn.action_item.set_text("CHECK") + elif fetch_available: + self._download_btn.action_item.set_value("update available") + self._download_btn.action_item.set_text("DOWNLOAD") + else: + last_update = ui_state.params.get("LastUpdateTime") + if last_update: + formatted = time_ago(last_update) + self._download_btn.action_item.set_value(f"up to date, last checked {formatted}") + else: + self._download_btn.action_item.set_value("up to date, last checked never") + self._download_btn.action_item.set_text("CHECK") + + # If we've been waiting too long without a state change, reset state + if self._waiting_for_updater and (time.monotonic() - self._waiting_start_ts > UPDATED_TIMEOUT): + self._waiting_for_updater = False + + # Only enable if we're not waiting for updater to flip out of idle + self._download_btn.action_item.set_enabled(not self._waiting_for_updater) + + # Update install button + self._install_btn.set_visible(ui_state.is_offroad() and update_available) + if update_available: + new_desc = ui_state.params.get("UpdaterNewDescription") or "" + new_release_notes = (ui_state.params.get("UpdaterNewReleaseNotes") or b"").decode("utf-8", "replace") + self._install_btn.action_item.set_text("INSTALL") + self._install_btn.action_item.set_value(new_desc) + self._install_btn.set_description(new_release_notes) + # Enable install button for testing (like Qt showEvent) + self._install_btn.action_item.set_enabled(True) + else: + self._install_btn.set_visible(False) + + def _on_download_update(self): + # Check if we should start checking or start downloading + self._download_btn.action_item.set_enabled(False) + if self._download_btn.action_item.text == "CHECK": + # Start checking for updates + self._waiting_for_updater = True + self._waiting_start_ts = time.monotonic() + os.system("pkill -SIGUSR1 -f system.updated.updated") + else: + # Start downloading + self._waiting_for_updater = True + self._waiting_start_ts = time.monotonic() + os.system("pkill -SIGHUP -f system.updated.updated") + + def _on_uninstall(self): + def handle_uninstall_confirmation(result): + if result == DialogResult.CONFIRM: + ui_state.params.put_bool("DoUninstall", True) + + dialog = ConfirmDialog("Are you sure you want to uninstall?", "Uninstall") + gui_app.set_modal_overlay(dialog, callback=handle_uninstall_confirmation) + + def _on_install_update(self): + # Trigger reboot to install update + self._install_btn.action_item.set_enabled(False) + ui_state.params.put_bool("DoReboot", True) + + def _on_select_branch(self): pass diff --git a/selfdrive/ui/layouts/settings/toggles.py b/selfdrive/ui/layouts/settings/toggles.py new file mode 100644 index 0000000000..1e0e7bfd53 --- /dev/null +++ b/selfdrive/ui/layouts/settings/toggles.py @@ -0,0 +1,95 @@ +from openpilot.common.params import Params +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.list_view import multiple_button_item, toggle_item +from openpilot.system.ui.widgets.scroller import Scroller + +# Description constants +DESCRIPTIONS = { + "OpenpilotEnabledToggle": ( + "Use the openpilot system for adaptive cruise control and lane keep driver assistance. " + + "Your attention is required at all times to use this feature." + ), + "DisengageOnAccelerator": "When enabled, pressing the accelerator pedal will disengage openpilot.", + "LongitudinalPersonality": ( + "Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. " + + "In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with " + + "your steering wheel distance button." + ), + "IsLdwEnabled": ( + "Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line " + + "without a turn signal activated while driving over 31 mph (50 km/h)." + ), + "AlwaysOnDM": "Enable driver monitoring even when openpilot is not engaged.", + 'RecordFront': "Upload data from the driver facing camera and help improve the driver monitoring algorithm.", + "IsMetric": "Display speed in km/h instead of mph.", + "RecordAudio": "Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect.", +} + + +class TogglesLayout(Widget): + def __init__(self): + super().__init__() + self._params = Params() + items = [ + toggle_item( + "Enable openpilot", + DESCRIPTIONS["OpenpilotEnabledToggle"], + self._params.get_bool("OpenpilotEnabledToggle"), + icon="chffr_wheel.png", + ), + toggle_item( + "Experimental Mode", + initial_state=self._params.get_bool("ExperimentalMode"), + icon="experimental_white.png", + ), + toggle_item( + "Disengage on Accelerator Pedal", + DESCRIPTIONS["DisengageOnAccelerator"], + self._params.get_bool("DisengageOnAccelerator"), + icon="disengage_on_accelerator.png", + ), + multiple_button_item( + "Driving Personality", + DESCRIPTIONS["LongitudinalPersonality"], + buttons=["Aggressive", "Standard", "Relaxed"], + button_width=255, + callback=self._set_longitudinal_personality, + selected_index=self._params.get("LongitudinalPersonality", return_default=True), + icon="speed_limit.png" + ), + toggle_item( + "Enable Lane Departure Warnings", + DESCRIPTIONS["IsLdwEnabled"], + self._params.get_bool("IsLdwEnabled"), + icon="warning.png", + ), + toggle_item( + "Always-On Driver Monitoring", + DESCRIPTIONS["AlwaysOnDM"], + self._params.get_bool("AlwaysOnDM"), + icon="monitoring.png", + ), + toggle_item( + "Record and Upload Driver Camera", + DESCRIPTIONS["RecordFront"], + self._params.get_bool("RecordFront"), + icon="monitoring.png", + ), + toggle_item( + "Record and Upload Microphone Audio", + DESCRIPTIONS["RecordAudio"], + self._params.get_bool("RecordAudio"), + icon="microphone.png", + ), + toggle_item( + "Use Metric System", DESCRIPTIONS["IsMetric"], self._params.get_bool("IsMetric"), icon="metric.png" + ), + ] + + self._scroller = Scroller(items, line_separator=True, spacing=0) + + def _render(self, rect): + self._scroller.render(rect) + + def _set_longitudinal_personality(self, button_index: int): + self._params.put("LongitudinalPersonality", button_index) diff --git a/selfdrive/ui/layouts/sidebar.py b/selfdrive/ui/layouts/sidebar.py new file mode 100644 index 0000000000..34354ecbab --- /dev/null +++ b/selfdrive/ui/layouts/sidebar.py @@ -0,0 +1,236 @@ +import pyray as rl +import time +from dataclasses import dataclass +from collections.abc import Callable +from cereal import log +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import Widget + +SIDEBAR_WIDTH = 300 +METRIC_HEIGHT = 126 +METRIC_WIDTH = 240 +METRIC_MARGIN = 30 +FONT_SIZE = 35 + +SETTINGS_BTN = rl.Rectangle(50, 35, 200, 117) +HOME_BTN = rl.Rectangle(60, 860, 180, 180) + +ThermalStatus = log.DeviceState.ThermalStatus +NetworkType = log.DeviceState.NetworkType + + +# Color scheme +class Colors: + SIDEBAR_BG = rl.Color(57, 57, 57, 255) + WHITE = rl.WHITE + WHITE_DIM = rl.Color(255, 255, 255, 85) + GRAY = rl.Color(84, 84, 84, 255) + + # Status colors + GOOD = rl.WHITE + WARNING = rl.Color(218, 202, 37, 255) + DANGER = rl.Color(201, 34, 49, 255) + + # UI elements + METRIC_BORDER = rl.Color(255, 255, 255, 85) + BUTTON_NORMAL = rl.WHITE + BUTTON_PRESSED = rl.Color(255, 255, 255, 166) + + +NETWORK_TYPES = { + NetworkType.none: "Offline", + NetworkType.wifi: "WiFi", + NetworkType.cell2G: "2G", + NetworkType.cell3G: "3G", + NetworkType.cell4G: "LTE", + NetworkType.cell5G: "5G", + NetworkType.ethernet: "Ethernet", +} + + +@dataclass(slots=True) +class MetricData: + label: str + value: str + color: rl.Color + + def update(self, label: str, value: str, color: rl.Color): + self.label = label + self.value = value + self.color = color + + +class Sidebar(Widget): + def __init__(self): + super().__init__() + self._net_type = NETWORK_TYPES.get(NetworkType.none) + self._net_strength = 0 + + self._temp_status = MetricData("TEMP", "GOOD", Colors.GOOD) + self._panda_status = MetricData("VEHICLE", "ONLINE", Colors.GOOD) + self._connect_status = MetricData("CONNECT", "OFFLINE", Colors.WARNING) + self._recording_audio = False + + self._home_img = gui_app.texture("images/button_home.png", HOME_BTN.width, HOME_BTN.height) + self._flag_img = gui_app.texture("images/button_flag.png", HOME_BTN.width, HOME_BTN.height) + self._settings_img = gui_app.texture("images/button_settings.png", SETTINGS_BTN.width, SETTINGS_BTN.height) + self._mic_img = gui_app.texture("icons/microphone.png", 30, 30) + self._mic_indicator_rect = rl.Rectangle(0, 0, 0, 0) + self._font_regular = gui_app.font(FontWeight.NORMAL) + self._font_bold = gui_app.font(FontWeight.SEMI_BOLD) + + # Callbacks + self._on_settings_click: Callable | None = None + self._on_flag_click: Callable | None = None + self._open_settings_callback: Callable | None = None + + def set_callbacks(self, on_settings: Callable | None = None, on_flag: Callable | None = None, + open_settings: Callable | None = None): + self._on_settings_click = on_settings + self._on_flag_click = on_flag + self._open_settings_callback = open_settings + + def _render(self, rect: rl.Rectangle): + # Background + rl.draw_rectangle_rec(rect, Colors.SIDEBAR_BG) + + self._draw_buttons(rect) + self._draw_network_indicator(rect) + self._draw_metrics(rect) + + def _update_state(self): + sm = ui_state.sm + if not sm.updated['deviceState']: + return + + device_state = sm['deviceState'] + + self._recording_audio = sm.alive['rawAudioData'] + self._update_network_status(device_state) + self._update_temperature_status(device_state) + self._update_connection_status(device_state) + self._update_panda_status() + + def _update_network_status(self, device_state): + self._net_type = NETWORK_TYPES.get(device_state.networkType.raw, "Unknown") + strength = device_state.networkStrength + self._net_strength = max(0, min(5, strength.raw + 1)) if strength > 0 else 0 + + def _update_temperature_status(self, device_state): + thermal_status = device_state.thermalStatus + + if thermal_status == ThermalStatus.green: + self._temp_status.update("TEMP", "GOOD", Colors.GOOD) + elif thermal_status == ThermalStatus.yellow: + self._temp_status.update("TEMP", "OK", Colors.WARNING) + else: + self._temp_status.update("TEMP", "HIGH", Colors.DANGER) + + def _update_connection_status(self, device_state): + last_ping = device_state.lastAthenaPingTime + if last_ping == 0: + self._connect_status.update("CONNECT", "OFFLINE", Colors.WARNING) + elif time.monotonic_ns() - last_ping < 80_000_000_000: # 80 seconds in nanoseconds + self._connect_status.update("CONNECT", "ONLINE", Colors.GOOD) + else: + self._connect_status.update("CONNECT", "ERROR", Colors.DANGER) + + def _update_panda_status(self): + if ui_state.panda_type == log.PandaState.PandaType.unknown: + self._panda_status.update("NO", "PANDA", Colors.DANGER) + else: + self._panda_status.update("VEHICLE", "ONLINE", Colors.GOOD) + + def _handle_mouse_release(self, mouse_pos: MousePos): + if rl.check_collision_point_rec(mouse_pos, SETTINGS_BTN): + if self._on_settings_click: + self._on_settings_click() + elif rl.check_collision_point_rec(mouse_pos, HOME_BTN) and ui_state.started: + if self._on_flag_click: + self._on_flag_click() + elif self._recording_audio and rl.check_collision_point_rec(mouse_pos, self._mic_indicator_rect): + if self._open_settings_callback: + self._open_settings_callback() + + def _draw_buttons(self, rect: rl.Rectangle): + mouse_pos = rl.get_mouse_position() + mouse_down = self.is_pressed and rl.is_mouse_button_down(rl.MouseButton.MOUSE_BUTTON_LEFT) + + # Settings button + settings_down = mouse_down and rl.check_collision_point_rec(mouse_pos, SETTINGS_BTN) + tint = Colors.BUTTON_PRESSED if settings_down else Colors.BUTTON_NORMAL + rl.draw_texture(self._settings_img, int(SETTINGS_BTN.x), int(SETTINGS_BTN.y), tint) + + # Home/Flag button + flag_pressed = mouse_down and rl.check_collision_point_rec(mouse_pos, HOME_BTN) + button_img = self._flag_img if ui_state.started else self._home_img + + tint = Colors.BUTTON_PRESSED if (ui_state.started and flag_pressed) else Colors.BUTTON_NORMAL + rl.draw_texture(button_img, int(HOME_BTN.x), int(HOME_BTN.y), tint) + + # Microphone button + if self._recording_audio: + self._mic_indicator_rect = rl.Rectangle(rect.x + rect.width - 138, rect.y + 245, 75, 40) + + mic_pressed = mouse_down and rl.check_collision_point_rec(mouse_pos, self._mic_indicator_rect) + bg_color = rl.Color(Colors.DANGER.r, Colors.DANGER.g, Colors.DANGER.b, int(255 * 0.65)) if mic_pressed else Colors.DANGER + + rl.draw_rectangle_rounded(self._mic_indicator_rect, 1, 10, bg_color) + rl.draw_texture(self._mic_img, int(self._mic_indicator_rect.x + (self._mic_indicator_rect.width - self._mic_img.width) / 2), + int(self._mic_indicator_rect.y + (self._mic_indicator_rect.height - self._mic_img.height) / 2), Colors.WHITE) + + def _draw_network_indicator(self, rect: rl.Rectangle): + # Signal strength dots + x_start = rect.x + 58 + y_pos = rect.y + 196 + dot_size = 27 + dot_spacing = 37 + + for i in range(5): + color = Colors.WHITE if i < self._net_strength else Colors.GRAY + x = int(x_start + i * dot_spacing + dot_size // 2) + y = int(y_pos + dot_size // 2) + rl.draw_circle(x, y, dot_size // 2, color) + + # Network type text + text_y = rect.y + 247 + text_pos = rl.Vector2(rect.x + 58, text_y) + rl.draw_text_ex(self._font_regular, self._net_type, text_pos, FONT_SIZE, 0, Colors.WHITE) + + def _draw_metrics(self, rect: rl.Rectangle): + metrics = [(self._temp_status, 338), (self._panda_status, 496), (self._connect_status, 654)] + + for metric, y_offset in metrics: + self._draw_metric(rect, metric, rect.y + y_offset) + + def _draw_metric(self, rect: rl.Rectangle, metric: MetricData, y: float): + metric_rect = rl.Rectangle(rect.x + METRIC_MARGIN, y, METRIC_WIDTH, METRIC_HEIGHT) + # Draw colored left edge (clipped rounded rectangle) + edge_rect = rl.Rectangle(metric_rect.x + 4, metric_rect.y + 4, 100, 118) + rl.begin_scissor_mode(int(metric_rect.x + 4), int(metric_rect.y), 18, int(metric_rect.height)) + rl.draw_rectangle_rounded(edge_rect, 0.3, 10, metric.color) + rl.end_scissor_mode() + + # Draw border + rl.draw_rectangle_rounded_lines_ex(metric_rect, 0.3, 10, 2, Colors.METRIC_BORDER) + + label_size = measure_text_cached(self._font_bold, metric.label, FONT_SIZE) + value_size = measure_text_cached(self._font_bold, metric.value, FONT_SIZE) + text_height = label_size.y + value_size.y + + label_y = metric_rect.y + (metric_rect.height - text_height) / 2 + value_y = label_y + label_size.y + + # label + rl.draw_text_ex(self._font_bold, metric.label, rl.Vector2( + metric_rect.x + 22 + (metric_rect.width - 22 - label_size.x) / 2, + label_y + ), FONT_SIZE, 0, Colors.WHITE) + + # value + rl.draw_text_ex(self._font_bold, metric.value, rl.Vector2( + metric_rect.x + 22 + (metric_rect.width - 22 - value_size.x) / 2, + value_y + ), FONT_SIZE, 0, Colors.WHITE) diff --git a/selfdrive/ui/lib/api_helpers.py b/selfdrive/ui/lib/api_helpers.py new file mode 100644 index 0000000000..b83efedb60 --- /dev/null +++ b/selfdrive/ui/lib/api_helpers.py @@ -0,0 +1,14 @@ +import time +from functools import lru_cache +from openpilot.common.api import Api + +TOKEN_EXPIRY_HOURS = 2 + + +@lru_cache(maxsize=1) +def _get_token(dongle_id: str, t: int): + return Api(dongle_id).get_token(expiry_hours=TOKEN_EXPIRY_HOURS) + + +def get_token(dongle_id: str): + return _get_token(dongle_id, int(time.monotonic() / (TOKEN_EXPIRY_HOURS / 2 * 60 * 60))) diff --git a/selfdrive/ui/lib/prime_state.py b/selfdrive/ui/lib/prime_state.py new file mode 100644 index 0000000000..30ad0f763a --- /dev/null +++ b/selfdrive/ui/lib/prime_state.py @@ -0,0 +1,104 @@ +from enum import IntEnum +import os +import threading +import time + +from openpilot.common.api import api_get +from openpilot.common.params import Params +from openpilot.common.swaglog import cloudlog +from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID +from openpilot.selfdrive.ui.lib.api_helpers import get_token + + +class PrimeType(IntEnum): + UNKNOWN = -2 + UNPAIRED = -1 + NONE = 0 + MAGENTA = 1 + LITE = 2 + BLUE = 3 + MAGENTA_NEW = 4 + PURPLE = 5 + + +class PrimeState: + FETCH_INTERVAL = 5.0 # seconds between API calls + API_TIMEOUT = 10.0 # seconds for API requests + SLEEP_INTERVAL = 0.5 # seconds to sleep between checks in the worker thread + + def __init__(self): + self._params = Params() + self._lock = threading.Lock() + self.prime_type: PrimeType = self._load_initial_state() + + self._running = False + self._thread = None + self.start() + + def _load_initial_state(self) -> PrimeType: + prime_type_str = os.getenv("PRIME_TYPE") or self._params.get("PrimeType") + try: + if prime_type_str is not None: + return PrimeType(int(prime_type_str)) + except (ValueError, TypeError): + pass + return PrimeType.UNKNOWN + + def _fetch_prime_status(self) -> None: + dongle_id = self._params.get("DongleId") + if not dongle_id or dongle_id == UNREGISTERED_DONGLE_ID: + return + + try: + identity_token = get_token(dongle_id) + response = api_get(f"v1.1/devices/{dongle_id}", timeout=self.API_TIMEOUT, access_token=identity_token) + if response.status_code == 200: + data = response.json() + is_paired = data.get("is_paired", False) + prime_type = data.get("prime_type", 0) + self.set_type(PrimeType(prime_type) if is_paired else PrimeType.UNPAIRED) + except Exception as e: + cloudlog.error(f"Failed to fetch prime status: {e}") + + def set_type(self, prime_type: PrimeType) -> None: + with self._lock: + if prime_type != self.prime_type: + self.prime_type = prime_type + self._params.put("PrimeType", int(prime_type)) + cloudlog.info(f"Prime type updated to {prime_type}") + + def _worker_thread(self) -> None: + while self._running: + self._fetch_prime_status() + + for _ in range(int(self.FETCH_INTERVAL / self.SLEEP_INTERVAL)): + if not self._running: + break + time.sleep(self.SLEEP_INTERVAL) + + def start(self) -> None: + if self._thread and self._thread.is_alive(): + return + self._running = True + self._thread = threading.Thread(target=self._worker_thread, daemon=True) + self._thread.start() + + def stop(self) -> None: + self._running = False + if self._thread and self._thread.is_alive(): + self._thread.join(timeout=1.0) + + def get_type(self) -> PrimeType: + with self._lock: + return self.prime_type + + def is_prime(self) -> bool: + with self._lock: + return bool(self.prime_type > PrimeType.NONE) + + def is_paired(self) -> bool: + with self._lock: + return self.prime_type > PrimeType.UNPAIRED + + def __del__(self): + self.stop() diff --git a/selfdrive/ui/main.cc b/selfdrive/ui/main.cc new file mode 100644 index 0000000000..4903a3db3d --- /dev/null +++ b/selfdrive/ui/main.cc @@ -0,0 +1,30 @@ +#include + +#include +#include + +#include "system/hardware/hw.h" +#include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/window.h" + +int main(int argc, char *argv[]) { + setpriority(PRIO_PROCESS, 0, -20); + + qInstallMessageHandler(swagLogMessageHandler); + initApp(argc, argv); + + QTranslator translator; + QString translation_file = QString::fromStdString(Params().get("LanguageSetting")); + if (!translator.load(QString(":/%1").arg(translation_file)) && translation_file.length()) { + qCritical() << "Failed to load translation file:" << translation_file; + } + + QApplication a(argc, argv); + a.installTranslator(&translator); + + MainWindow w; + setMainWindow(&w); + a.installEventFilter(&w); + return a.exec(); +} diff --git a/selfdrive/ui/onroad/__init__.py b/selfdrive/ui/onroad/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/ui/onroad/alert_renderer.py b/selfdrive/ui/onroad/alert_renderer.py new file mode 100644 index 0000000000..e81129b137 --- /dev/null +++ b/selfdrive/ui/onroad/alert_renderer.py @@ -0,0 +1,165 @@ +import time +import pyray as rl +from dataclasses import dataclass +from cereal import messaging, log +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.hardware import TICI +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.label import gui_text_box + +AlertSize = log.SelfdriveState.AlertSize +AlertStatus = log.SelfdriveState.AlertStatus + +ALERT_MARGIN = 40 +ALERT_PADDING = 60 +ALERT_LINE_SPACING = 45 +ALERT_BORDER_RADIUS = 30 + +ALERT_FONT_SMALL = 66 +ALERT_FONT_MEDIUM = 74 +ALERT_FONT_BIG = 88 + +SELFDRIVE_STATE_TIMEOUT = 5 # Seconds +SELFDRIVE_UNRESPONSIVE_TIMEOUT = 10 # Seconds + +# Constants +ALERT_COLORS = { + AlertStatus.normal: rl.Color(0x15, 0x15, 0x15, 0xF1), # #151515 with alpha 0xF1 + AlertStatus.userPrompt: rl.Color(0xDA, 0x6F, 0x25, 0xF1), # #DA6F25 with alpha 0xF1 + AlertStatus.critical: rl.Color(0xC9, 0x22, 0x31, 0xF1), # #C92231 with alpha 0xF1 +} + + +@dataclass +class Alert: + text1: str = "" + text2: str = "" + size: int = 0 + status: int = 0 + + +# Pre-defined alert instances +ALERT_STARTUP_PENDING = Alert( + text1="openpilot Unavailable", + text2="Waiting to start", + size=AlertSize.mid, + status=AlertStatus.normal, +) + +ALERT_CRITICAL_TIMEOUT = Alert( + text1="TAKE CONTROL IMMEDIATELY", + text2="System Unresponsive", + size=AlertSize.full, + status=AlertStatus.critical, +) + +ALERT_CRITICAL_REBOOT = Alert( + text1="System Unresponsive", + text2="Reboot Device", + size=AlertSize.full, + status=AlertStatus.critical, +) + + +class AlertRenderer(Widget): + def __init__(self): + super().__init__() + self.font_regular: rl.Font = gui_app.font(FontWeight.NORMAL) + self.font_bold: rl.Font = gui_app.font(FontWeight.BOLD) + + def get_alert(self, sm: messaging.SubMaster) -> Alert | None: + """Generate the current alert based on selfdrive state.""" + ss = sm['selfdriveState'] + + # Check if selfdriveState messages have stopped arriving + if not sm.updated['selfdriveState']: + recv_frame = sm.recv_frame['selfdriveState'] + time_since_onroad = time.monotonic() - ui_state.started_time + + # 1. Never received selfdriveState since going onroad + waiting_for_startup = recv_frame < ui_state.started_frame + if waiting_for_startup and time_since_onroad > 5: + return ALERT_STARTUP_PENDING + + # 2. Lost communication with selfdriveState after receiving it + if TICI and not waiting_for_startup: + ss_missing = time.monotonic() - sm.recv_time['selfdriveState'] + if ss_missing > SELFDRIVE_STATE_TIMEOUT: + if ss.enabled and (ss_missing - SELFDRIVE_STATE_TIMEOUT) < SELFDRIVE_UNRESPONSIVE_TIMEOUT: + return ALERT_CRITICAL_TIMEOUT + return ALERT_CRITICAL_REBOOT + + # No alert if size is none + if ss.alertSize == 0: + return None + + # Return current alert + return Alert(text1=ss.alertText1, text2=ss.alertText2, size=ss.alertSize.raw, status=ss.alertStatus.raw) + + def _render(self, rect: rl.Rectangle) -> bool: + alert = self.get_alert(ui_state.sm) + if not alert: + return False + + alert_rect = self._get_alert_rect(rect, alert.size) + self._draw_background(alert_rect, alert) + + text_rect = rl.Rectangle( + alert_rect.x + ALERT_PADDING, + alert_rect.y + ALERT_PADDING, + alert_rect.width - 2 * ALERT_PADDING, + alert_rect.height - 2 * ALERT_PADDING + ) + self._draw_text(text_rect, alert) + return True + + def _get_alert_rect(self, rect: rl.Rectangle, size: int) -> rl.Rectangle: + if size == AlertSize.full: + return rect + + height = (ALERT_FONT_MEDIUM + 2 * ALERT_PADDING if size == AlertSize.small else + ALERT_FONT_BIG + ALERT_LINE_SPACING + ALERT_FONT_SMALL + 2 * ALERT_PADDING) + + return rl.Rectangle( + rect.x + ALERT_MARGIN, + rect.y + rect.height - ALERT_MARGIN - height, + rect.width - 2 * ALERT_MARGIN, + height + ) + + def _draw_background(self, rect: rl.Rectangle, alert: Alert) -> None: + color = ALERT_COLORS.get(alert.status, ALERT_COLORS[AlertStatus.normal]) + + if alert.size != AlertSize.full: + roundness = ALERT_BORDER_RADIUS / (min(rect.width, rect.height) / 2) + rl.draw_rectangle_rounded(rect, roundness, 10, color) + else: + rl.draw_rectangle_rec(rect, color) + + def _draw_text(self, rect: rl.Rectangle, alert: Alert) -> None: + if alert.size == AlertSize.small: + self._draw_centered(alert.text1, rect, self.font_bold, ALERT_FONT_MEDIUM) + + elif alert.size == AlertSize.mid: + self._draw_centered(alert.text1, rect, self.font_bold, ALERT_FONT_BIG, center_y=False) + rect.y += ALERT_FONT_BIG + ALERT_LINE_SPACING + self._draw_centered(alert.text2, rect, self.font_regular, ALERT_FONT_SMALL, center_y=False) + + else: + is_long = len(alert.text1) > 15 + font_size1 = 132 if is_long else 177 + align_ment = rl.GuiTextAlignment.TEXT_ALIGN_CENTER + vertical_align = rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE + text_rect = rl.Rectangle(rect.x, rect.y, rect.width, rect.height // 2) + + gui_text_box(text_rect, alert.text1, font_size1, alignment=align_ment, alignment_vertical=vertical_align, font_weight=FontWeight.BOLD) + text_rect.y = rect.y + rect.height // 2 + gui_text_box(text_rect, alert.text2, ALERT_FONT_BIG, alignment=align_ment) + + def _draw_centered(self, text, rect, font, font_size, center_y=True, color=rl.WHITE) -> None: + text_size = measure_text_cached(font, text, font_size) + x = rect.x + (rect.width - text_size.x) / 2 + y = rect.y + ((rect.height - text_size.y) / 2 if center_y else 0) + rl.draw_text_ex(font, text, rl.Vector2(x, y), font_size, 0, color) diff --git a/selfdrive/ui/onroad/augmented_road_view.py b/selfdrive/ui/onroad/augmented_road_view.py new file mode 100644 index 0000000000..0a4c45163b --- /dev/null +++ b/selfdrive/ui/onroad/augmented_road_view.py @@ -0,0 +1,222 @@ +import numpy as np +import pyray as rl +from cereal import log +from msgq.visionipc import VisionStreamType +from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus, UI_BORDER_SIZE +from openpilot.selfdrive.ui.onroad.alert_renderer import AlertRenderer +from openpilot.selfdrive.ui.onroad.driver_state import DriverStateRenderer +from openpilot.selfdrive.ui.onroad.hud_renderer import HudRenderer +from openpilot.selfdrive.ui.onroad.model_renderer import ModelRenderer +from openpilot.selfdrive.ui.onroad.cameraview import CameraView +from openpilot.system.ui.lib.application import gui_app +from openpilot.common.transformations.camera import DEVICE_CAMERAS, DeviceCameraConfig, view_frame_from_device_frame +from openpilot.common.transformations.orientation import rot_from_euler + +OpState = log.SelfdriveState.OpenpilotState +CALIBRATED = log.LiveCalibrationData.Status.calibrated +ROAD_CAM = VisionStreamType.VISION_STREAM_ROAD +WIDE_CAM = VisionStreamType.VISION_STREAM_WIDE_ROAD +DEFAULT_DEVICE_CAMERA = DEVICE_CAMERAS["tici", "ar0231"] + +BORDER_COLORS = { + UIStatus.DISENGAGED: rl.Color(0x17, 0x33, 0x49, 0xC8), # Blue for disengaged state + UIStatus.OVERRIDE: rl.Color(0x91, 0x9B, 0x95, 0xF1), # Gray for override state + UIStatus.ENGAGED: rl.Color(0x17, 0x86, 0x44, 0xF1), # Green for engaged state +} + +WIDE_CAM_MAX_SPEED = 10.0 # m/s (22 mph) +ROAD_CAM_MIN_SPEED = 15.0 # m/s (34 mph) + + +class AugmentedRoadView(CameraView): + def __init__(self, stream_type: VisionStreamType = VisionStreamType.VISION_STREAM_ROAD): + super().__init__("camerad", stream_type) + self._set_placeholder_color(BORDER_COLORS[UIStatus.DISENGAGED]) + + self.device_camera: DeviceCameraConfig | None = None + self.view_from_calib = view_frame_from_device_frame.copy() + self.view_from_wide_calib = view_frame_from_device_frame.copy() + + self._last_calib_time: float = 0 + self._last_rect_dims = (0.0, 0.0) + self._last_stream_type = stream_type + self._cached_matrix: np.ndarray | None = None + self._content_rect = rl.Rectangle() + + self.model_renderer = ModelRenderer() + self._hud_renderer = HudRenderer() + self.alert_renderer = AlertRenderer() + self.driver_state_renderer = DriverStateRenderer() + + def _render(self, rect): + # Only render when system is started to avoid invalid data access + if not ui_state.started: + return + + self._switch_stream_if_needed(ui_state.sm) + + # Update calibration before rendering + self._update_calibration() + + # Create inner content area with border padding + self._content_rect = rl.Rectangle( + rect.x + UI_BORDER_SIZE, + rect.y + UI_BORDER_SIZE, + rect.width - 2 * UI_BORDER_SIZE, + rect.height - 2 * UI_BORDER_SIZE, + ) + + # Draw colored border based on driving state + self._draw_border(rect) + + # Enable scissor mode to clip all rendering within content rectangle boundaries + # This creates a rendering viewport that prevents graphics from drawing outside the border + rl.begin_scissor_mode( + int(self._content_rect.x), + int(self._content_rect.y), + int(self._content_rect.width), + int(self._content_rect.height) + ) + + # Render the base camera view + super()._render(rect) + + # Draw all UI overlays + self.model_renderer.render(self._content_rect) + self._hud_renderer.render(self._content_rect) + if not self.alert_renderer.render(self._content_rect): + self.driver_state_renderer.render(self._content_rect) + + # Custom UI extension point - add custom overlays here + # Use self._content_rect for positioning within camera bounds + + # End clipping region + rl.end_scissor_mode() + + def _handle_mouse_press(self, _): + if not self._hud_renderer.user_interacting() and self._click_callback is not None: + self._click_callback() + + def _handle_mouse_release(self, _): + # We only call click callback on press if not interacting with HUD + pass + + def _draw_border(self, rect: rl.Rectangle): + border_color = BORDER_COLORS.get(ui_state.status, BORDER_COLORS[UIStatus.DISENGAGED]) + rl.draw_rectangle_lines_ex(rect, UI_BORDER_SIZE, border_color) + + def _switch_stream_if_needed(self, sm): + if sm['selfdriveState'].experimentalMode and WIDE_CAM in self.available_streams: + v_ego = sm['carState'].vEgo + if v_ego < WIDE_CAM_MAX_SPEED: + target = WIDE_CAM + elif v_ego > ROAD_CAM_MIN_SPEED: + target = ROAD_CAM + else: + # Hysteresis zone - keep current stream + target = self.stream_type + else: + target = ROAD_CAM + + if self.stream_type != target: + self.switch_stream(target) + + def _update_calibration(self): + # Update device camera if not already set + sm = ui_state.sm + if not self.device_camera and sm.seen['roadCameraState'] and sm.seen['deviceState']: + self.device_camera = DEVICE_CAMERAS[(str(sm['deviceState'].deviceType), str(sm['roadCameraState'].sensor))] + + # Check if live calibration data is available and valid + if not (sm.updated["liveCalibration"] and sm.valid['liveCalibration']): + return + + calib = sm['liveCalibration'] + if len(calib.rpyCalib) != 3 or calib.calStatus != CALIBRATED: + return + + # Update view_from_calib matrix + device_from_calib = rot_from_euler(calib.rpyCalib) + self.view_from_calib = view_frame_from_device_frame @ device_from_calib + + # Update wide calibration if available + if hasattr(calib, 'wideFromDeviceEuler') and len(calib.wideFromDeviceEuler) == 3: + wide_from_device = rot_from_euler(calib.wideFromDeviceEuler) + self.view_from_wide_calib = view_frame_from_device_frame @ wide_from_device @ device_from_calib + + def _calc_frame_matrix(self, rect: rl.Rectangle) -> np.ndarray: + # Check if we can use cached matrix + calib_time = ui_state.sm.recv_frame['liveCalibration'] + current_dims = (self._content_rect.width, self._content_rect.height) + if (self._last_calib_time == calib_time and + self._last_rect_dims == current_dims and + self._last_stream_type == self.stream_type and + self._cached_matrix is not None): + return self._cached_matrix + + # Get camera configuration + device_camera = self.device_camera or DEFAULT_DEVICE_CAMERA + is_wide_camera = self.stream_type == WIDE_CAM + intrinsic = device_camera.ecam.intrinsics if is_wide_camera else device_camera.fcam.intrinsics + calibration = self.view_from_wide_calib if is_wide_camera else self.view_from_calib + zoom = 2.0 if is_wide_camera else 1.1 + + # Calculate transforms for vanishing point + inf_point = np.array([1000.0, 0.0, 0.0]) + calib_transform = intrinsic @ calibration + kep = calib_transform @ inf_point + + # Calculate center points and dimensions + x, y = self._content_rect.x, self._content_rect.y + w, h = self._content_rect.width, self._content_rect.height + cx, cy = intrinsic[0, 2], intrinsic[1, 2] + + # Calculate max allowed offsets with margins + margin = 5 + max_x_offset = cx * zoom - w / 2 - margin + max_y_offset = cy * zoom - h / 2 - margin + + # Calculate and clamp offsets to prevent out-of-bounds issues + try: + if abs(kep[2]) > 1e-6: + x_offset = np.clip((kep[0] / kep[2] - cx) * zoom, -max_x_offset, max_x_offset) + y_offset = np.clip((kep[1] / kep[2] - cy) * zoom, -max_y_offset, max_y_offset) + else: + x_offset, y_offset = 0, 0 + except (ZeroDivisionError, OverflowError): + x_offset, y_offset = 0, 0 + + # Cache the computed transformation matrix to avoid recalculations + self._last_calib_time = calib_time + self._last_rect_dims = current_dims + self._last_stream_type = self.stream_type + self._cached_matrix = np.array([ + [zoom * 2 * cx / w, 0, -x_offset / w * 2], + [0, zoom * 2 * cy / h, -y_offset / h * 2], + [0, 0, 1.0] + ]) + + video_transform = np.array([ + [zoom, 0.0, (w / 2 + x - x_offset) - (cx * zoom)], + [0.0, zoom, (h / 2 + y - y_offset) - (cy * zoom)], + [0.0, 0.0, 1.0] + ]) + self.model_renderer.set_transform(video_transform @ calib_transform) + + return self._cached_matrix + + +if __name__ == "__main__": + gui_app.init_window("OnRoad Camera View") + road_camera_view = AugmentedRoadView(ROAD_CAM) + print("***press space to switch camera view***") + try: + for _ in gui_app.render(): + ui_state.update() + if rl.is_key_released(rl.KeyboardKey.KEY_SPACE): + if WIDE_CAM in road_camera_view.available_streams: + stream = ROAD_CAM if road_camera_view.stream_type == WIDE_CAM else WIDE_CAM + road_camera_view.switch_stream(stream) + road_camera_view.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + finally: + road_camera_view.close() diff --git a/selfdrive/ui/onroad/cameraview.py b/selfdrive/ui/onroad/cameraview.py new file mode 100644 index 0000000000..ca031e2f17 --- /dev/null +++ b/selfdrive/ui/onroad/cameraview.py @@ -0,0 +1,346 @@ +import platform +import numpy as np +import pyray as rl + +from msgq.visionipc import VisionIpcClient, VisionStreamType, VisionBuf +from openpilot.common.swaglog import cloudlog +from openpilot.system.hardware import TICI +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.egl import init_egl, create_egl_image, destroy_egl_image, bind_egl_image_to_texture, EGLImage +from openpilot.system.ui.widgets import Widget + +CONNECTION_RETRY_INTERVAL = 0.2 # seconds between connection attempts + +VERSION = """ +#version 300 es +precision mediump float; +""" +if platform.system() == "Darwin": + VERSION = """ + #version 330 core + """ + + +VERTEX_SHADER = VERSION + """ +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; +uniform mat4 mvp; +out vec2 fragTexCoord; +out vec4 fragColor; +void main() { + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + gl_Position = mvp * vec4(vertexPosition, 1.0); +} +""" + +# Choose fragment shader based on platform capabilities +if TICI: + FRAME_FRAGMENT_SHADER = """ + #version 300 es + #extension GL_OES_EGL_image_external_essl3 : enable + precision mediump float; + in vec2 fragTexCoord; + uniform samplerExternalOES texture0; + out vec4 fragColor; + void main() { + vec4 color = texture(texture0, fragTexCoord); + fragColor = vec4(pow(color.rgb, vec3(1.0/1.28)), color.a); + } + """ +else: + FRAME_FRAGMENT_SHADER = VERSION + """ + in vec2 fragTexCoord; + uniform sampler2D texture0; + uniform sampler2D texture1; + out vec4 fragColor; + void main() { + float y = texture(texture0, fragTexCoord).r; + vec2 uv = texture(texture1, fragTexCoord).ra - 0.5; + fragColor = vec4(y + 1.402*uv.y, y - 0.344*uv.x - 0.714*uv.y, y + 1.772*uv.x, 1.0); + } + """ + + +class CameraView(Widget): + def __init__(self, name: str, stream_type: VisionStreamType): + super().__init__() + self._name = name + # Primary stream + self.client = VisionIpcClient(name, stream_type, conflate=True) + self._stream_type = stream_type + self.available_streams: list[VisionStreamType] = [] + + # Target stream for switching + self._target_client: VisionIpcClient | None = None + self._target_stream_type: VisionStreamType | None = None + self._switching: bool = False + + self._texture_needs_update = True + self.last_connection_attempt: float = 0.0 + self.shader = rl.load_shader_from_memory(VERTEX_SHADER, FRAME_FRAGMENT_SHADER) + self._texture1_loc: int = rl.get_shader_location(self.shader, "texture1") if not TICI else -1 + + self.frame: VisionBuf | None = None + self.texture_y: rl.Texture | None = None + self.texture_uv: rl.Texture | None = None + + # EGL resources + self.egl_images: dict[int, EGLImage] = {} + self.egl_texture: rl.Texture | None = None + + self._placeholder_color: rl.Color | None = None + + # Initialize EGL for zero-copy rendering on TICI + if TICI: + if not init_egl(): + raise RuntimeError("Failed to initialize EGL") + + # Create a 1x1 pixel placeholder texture for EGL image binding + temp_image = rl.gen_image_color(1, 1, rl.BLACK) + self.egl_texture = rl.load_texture_from_image(temp_image) + rl.unload_image(temp_image) + + def _set_placeholder_color(self, color: rl.Color): + """Set a placeholder color to be drawn when no frame is available.""" + self._placeholder_color = color + + def switch_stream(self, stream_type: VisionStreamType) -> None: + if self._stream_type == stream_type: + return + + if self._switching and self._target_stream_type == stream_type: + return + + cloudlog.debug(f'Preparing switch from {self._stream_type} to {stream_type}') + + if self._target_client: + del self._target_client + + self._target_stream_type = stream_type + self._target_client = VisionIpcClient(self._name, stream_type, conflate=True) + self._switching = True + + @property + def stream_type(self) -> VisionStreamType: + return self._stream_type + + def close(self) -> None: + self._clear_textures() + + # Clean up EGL texture + if TICI and self.egl_texture: + rl.unload_texture(self.egl_texture) + self.egl_texture = None + + # Clean up shader + if self.shader and self.shader.id: + rl.unload_shader(self.shader) + + self.client = None + + def __del__(self): + self.close() + + def _calc_frame_matrix(self, rect: rl.Rectangle) -> np.ndarray: + if not self.frame: + return np.eye(3) + + # Calculate aspect ratios + widget_aspect_ratio = rect.width / rect.height + frame_aspect_ratio = self.frame.width / self.frame.height + + # Calculate scaling factors to maintain aspect ratio + zx = min(frame_aspect_ratio / widget_aspect_ratio, 1.0) + zy = min(widget_aspect_ratio / frame_aspect_ratio, 1.0) + + return np.array([ + [zx, 0.0, 0.0], + [0.0, zy, 0.0], + [0.0, 0.0, 1.0] + ]) + + def _render(self, rect: rl.Rectangle): + if self._switching: + self._handle_switch() + + if not self._ensure_connection(): + self._draw_placeholder(rect) + return + + # Try to get a new buffer without blocking + buffer = self.client.recv(timeout_ms=0) + if buffer: + self._texture_needs_update = True + self.frame = buffer + + if not self.frame: + self._draw_placeholder(rect) + return + + transform = self._calc_frame_matrix(rect) + src_rect = rl.Rectangle(0, 0, float(self.frame.width), float(self.frame.height)) + # Flip driver camera horizontally + if self._stream_type == VisionStreamType.VISION_STREAM_DRIVER: + src_rect.width = -src_rect.width + + # Calculate scale + scale_x = rect.width * transform[0, 0] # zx + scale_y = rect.height * transform[1, 1] # zy + + # Calculate base position (centered) + x_offset = rect.x + (rect.width - scale_x) / 2 + y_offset = rect.y + (rect.height - scale_y) / 2 + + x_offset += transform[0, 2] * rect.width / 2 + y_offset += transform[1, 2] * rect.height / 2 + + dst_rect = rl.Rectangle(x_offset, y_offset, scale_x, scale_y) + + # Render with appropriate method + if TICI: + self._render_egl(src_rect, dst_rect) + else: + self._render_textures(src_rect, dst_rect) + + def _draw_placeholder(self, rect: rl.Rectangle): + if self._placeholder_color: + rl.draw_rectangle_rec(rect, self._placeholder_color) + + def _render_egl(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle) -> None: + """Render using EGL for direct buffer access""" + if self.frame is None or self.egl_texture is None: + return + + idx = self.frame.idx + egl_image = self.egl_images.get(idx) + + # Create EGL image if needed + if egl_image is None: + egl_image = create_egl_image(self.frame.width, self.frame.height, self.frame.stride, self.frame.fd, self.frame.uv_offset) + if egl_image: + self.egl_images[idx] = egl_image + else: + return + + # Update texture dimensions to match current frame + self.egl_texture.width = self.frame.width + self.egl_texture.height = self.frame.height + + # Bind the EGL image to our texture + bind_egl_image_to_texture(self.egl_texture.id, egl_image) + + # Render with shader + rl.begin_shader_mode(self.shader) + rl.draw_texture_pro(self.egl_texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) + rl.end_shader_mode() + + def _render_textures(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle) -> None: + """Render using texture copies""" + if not self.texture_y or not self.texture_uv or self.frame is None: + return + + # Update textures with new frame data + if self._texture_needs_update: + y_data = self.frame.data[: self.frame.uv_offset] + uv_data = self.frame.data[self.frame.uv_offset:] + + rl.update_texture(self.texture_y, rl.ffi.cast("void *", y_data.ctypes.data)) + rl.update_texture(self.texture_uv, rl.ffi.cast("void *", uv_data.ctypes.data)) + self._texture_needs_update = False + + # Render with shader + rl.begin_shader_mode(self.shader) + rl.set_shader_value_texture(self.shader, self._texture1_loc, self.texture_uv) + rl.draw_texture_pro(self.texture_y, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) + rl.end_shader_mode() + + def _ensure_connection(self) -> bool: + if not self.client.is_connected(): + self.frame = None + self.available_streams.clear() + + # Throttle connection attempts + current_time = rl.get_time() + if current_time - self.last_connection_attempt < CONNECTION_RETRY_INTERVAL: + return False + self.last_connection_attempt = current_time + + if not self.client.connect(False) or not self.client.num_buffers: + return False + + cloudlog.debug(f"Connected to {self._name} stream: {self._stream_type}, buffers: {self.client.num_buffers}") + self._initialize_textures() + self.available_streams = self.client.available_streams(self._name, block=False) + + return True + + def _handle_switch(self) -> None: + """Check if target stream is ready and switch immediately.""" + if not self._target_client or not self._switching: + return + + # Try to connect target if needed + if not self._target_client.is_connected(): + if not self._target_client.connect(False) or not self._target_client.num_buffers: + return + + cloudlog.debug(f"Target stream connected: {self._target_stream_type}") + + # Check if target has frames ready + target_frame = self._target_client.recv(timeout_ms=0) + if target_frame: + self.frame = target_frame # Update current frame to target frame + self._complete_switch() + + def _complete_switch(self) -> None: + """Instantly switch to target stream.""" + cloudlog.debug(f"Switching to {self._target_stream_type}") + # Clean up current resources + if self.client: + del self.client + + # Switch to target + self.client = self._target_client + self._stream_type = self._target_stream_type + self._texture_needs_update = True + + # Reset state + self._target_client = None + self._target_stream_type = None + self._switching = False + + # Initialize textures for new stream + self._initialize_textures() + + def _initialize_textures(self): + self._clear_textures() + if not TICI: + self.texture_y = rl.load_texture_from_image(rl.Image(None, int(self.client.stride), + int(self.client.height), 1, rl.PixelFormat.PIXELFORMAT_UNCOMPRESSED_GRAYSCALE)) + self.texture_uv = rl.load_texture_from_image(rl.Image(None, int(self.client.stride // 2), + int(self.client.height // 2), 1, rl.PixelFormat.PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA)) + + def _clear_textures(self): + if self.texture_y and self.texture_y.id: + rl.unload_texture(self.texture_y) + self.texture_y = None + + if self.texture_uv and self.texture_uv.id: + rl.unload_texture(self.texture_uv) + self.texture_uv = None + + # Clean up EGL resources + if TICI: + for data in self.egl_images.values(): + destroy_egl_image(data) + self.egl_images = {} + + +if __name__ == "__main__": + gui_app.init_window("camera view") + road = CameraView("camerad", VisionStreamType.VISION_STREAM_ROAD) + for _ in gui_app.render(): + road.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) diff --git a/selfdrive/ui/onroad/driver_camera_dialog.py b/selfdrive/ui/onroad/driver_camera_dialog.py new file mode 100644 index 0000000000..a3bd2e23e0 --- /dev/null +++ b/selfdrive/ui/onroad/driver_camera_dialog.py @@ -0,0 +1,106 @@ +import numpy as np +import pyray as rl +from msgq.visionipc import VisionStreamType +from openpilot.selfdrive.ui.onroad.cameraview import CameraView +from openpilot.selfdrive.ui.onroad.driver_state import DriverStateRenderer +from openpilot.selfdrive.ui.ui_state import ui_state, device +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.widgets.label import gui_label + + +class DriverCameraDialog(CameraView): + def __init__(self): + super().__init__("camerad", VisionStreamType.VISION_STREAM_DRIVER) + self.driver_state_renderer = DriverStateRenderer() + # TODO: this can grow unbounded, should be given some thought + device.add_interactive_timeout_callback(self.stop_dmonitoringmodeld) + ui_state.params.put_bool("IsDriverViewEnabled", True) + + def stop_dmonitoringmodeld(self): + ui_state.params.put_bool("IsDriverViewEnabled", False) + gui_app.set_modal_overlay(None) + + def _handle_mouse_release(self, _): + super()._handle_mouse_release(_) + self.stop_dmonitoringmodeld() + + def _render(self, rect): + super()._render(rect) + + if not self.frame: + gui_label( + rect, + "camera starting", + font_size=100, + font_weight=FontWeight.BOLD, + alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER, + ) + return -1 + + self._draw_face_detection(rect) + self.driver_state_renderer.render(rect) + + return -1 + + def _draw_face_detection(self, rect: rl.Rectangle) -> None: + driver_state = ui_state.sm["driverStateV2"] + is_rhd = driver_state.wheelOnRightProb > 0.5 + driver_data = driver_state.rightDriverData if is_rhd else driver_state.leftDriverData + face_detect = driver_data.faceProb > 0.7 + if not face_detect: + return + + # Get face position and orientation + face_x, face_y = driver_data.facePosition + face_std = max(driver_data.faceOrientationStd[0], driver_data.faceOrientationStd[1]) + alpha = 0.7 + if face_std > 0.15: + alpha = max(0.7 - (face_std - 0.15) * 3.5, 0.0) + + # use approx instead of distort_points + # TODO: replace with distort_points + fbox_x = int(1080.0 - 1714.0 * face_x) + fbox_y = int(-135.0 + (504.0 + abs(face_x) * 112.0) + (1205.0 - abs(face_x) * 724.0) * face_y) + box_size = 220 + + line_color = rl.Color(255, 255, 255, int(alpha * 255)) + rl.draw_rectangle_rounded_lines_ex( + rl.Rectangle(fbox_x - box_size / 2, fbox_y - box_size / 2, box_size, box_size), + 35.0 / box_size / 2, + 10, + 10, + line_color, + ) + + def _calc_frame_matrix(self, rect: rl.Rectangle) -> np.ndarray: + driver_view_ratio = 2.0 + + # Get stream dimensions + if self.frame: + stream_width = self.frame.width + stream_height = self.frame.height + else: + # Default values if frame not available + stream_width = 1928 + stream_height = 1208 + + yscale = stream_height * driver_view_ratio / stream_width + xscale = yscale * rect.height / rect.width * stream_width / stream_height + + return np.array([ + [xscale, 0.0, 0.0], + [0.0, yscale, 0.0], + [0.0, 0.0, 1.0] + ]) + + +if __name__ == "__main__": + gui_app.init_window("Driver Camera View") + + driver_camera_view = DriverCameraDialog() + try: + for _ in gui_app.render(): + ui_state.update() + driver_camera_view.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + finally: + driver_camera_view.close() diff --git a/selfdrive/ui/onroad/driver_state.py b/selfdrive/ui/onroad/driver_state.py new file mode 100644 index 0000000000..a25d9bd316 --- /dev/null +++ b/selfdrive/ui/onroad/driver_state.py @@ -0,0 +1,232 @@ +import numpy as np +import pyray as rl +from dataclasses import dataclass +from openpilot.selfdrive.ui.ui_state import ui_state, UI_BORDER_SIZE +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.widgets import Widget + +# Default 3D coordinates for face keypoints as a NumPy array +DEFAULT_FACE_KPTS_3D = np.array([ + [-5.98, -51.20, 8.00], [-17.64, -49.14, 8.00], [-23.81, -46.40, 8.00], [-29.98, -40.91, 8.00], + [-32.04, -37.49, 8.00], [-34.10, -32.00, 8.00], [-36.16, -21.03, 8.00], [-36.16, 6.40, 8.00], + [-35.47, 10.51, 8.00], [-32.73, 19.43, 8.00], [-29.30, 26.29, 8.00], [-24.50, 33.83, 8.00], + [-19.01, 41.37, 8.00], [-14.21, 46.17, 8.00], [-12.16, 47.54, 8.00], [-4.61, 49.60, 8.00], + [4.99, 49.60, 8.00], [12.53, 47.54, 8.00], [14.59, 46.17, 8.00], [19.39, 41.37, 8.00], + [24.87, 33.83, 8.00], [29.67, 26.29, 8.00], [33.10, 19.43, 8.00], [35.84, 10.51, 8.00], + [36.53, 6.40, 8.00], [36.53, -21.03, 8.00], [34.47, -32.00, 8.00], [32.42, -37.49, 8.00], + [30.36, -40.91, 8.00], [24.19, -46.40, 8.00], [18.02, -49.14, 8.00], [6.36, -51.20, 8.00], + [-5.98, -51.20, 8.00], +], dtype=np.float32) + +# UI constants +BTN_SIZE = 192 +IMG_SIZE = 144 +ARC_LENGTH = 133 +ARC_THICKNESS_DEFAULT = 6.7 +ARC_THICKNESS_EXTEND = 12.0 + +SCALES_POS = np.array([0.9, 0.4, 0.4], dtype=np.float32) +SCALES_NEG = np.array([0.7, 0.4, 0.4], dtype=np.float32) + +ARC_POINT_COUNT = 37 # Number of points in the arc +ARC_ANGLES = np.linspace(0.0, np.pi, ARC_POINT_COUNT, dtype=np.float32) + + +@dataclass +class ArcData: + """Data structure for arc rendering parameters.""" + x: float + y: float + width: float + height: float + thickness: float + + +class DriverStateRenderer(Widget): + def __init__(self): + super().__init__() + # Initial state with NumPy arrays + self.face_kpts_draw = DEFAULT_FACE_KPTS_3D.copy() + self.is_active = False + self.is_rhd = False + self.dm_fade_state = 0.0 + self.last_rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0) + self.driver_pose_vals = np.zeros(3, dtype=np.float32) + self.driver_pose_diff = np.zeros(3, dtype=np.float32) + self.driver_pose_sins = np.zeros(3, dtype=np.float32) + self.driver_pose_coss = np.zeros(3, dtype=np.float32) + self.face_keypoints_transformed = np.zeros((DEFAULT_FACE_KPTS_3D.shape[0], 2), dtype=np.float32) + self.position_x: float = 0.0 + self.position_y: float = 0.0 + self.h_arc_data = None + self.v_arc_data = None + + # Pre-allocate drawing arrays + self.face_lines = [rl.Vector2(0, 0) for _ in range(len(DEFAULT_FACE_KPTS_3D))] + self.h_arc_lines = [rl.Vector2(0, 0) for _ in range(ARC_POINT_COUNT)] + self.v_arc_lines = [rl.Vector2(0, 0) for _ in range(ARC_POINT_COUNT)] + + # Load the driver face icon + self.dm_img = gui_app.texture("icons/driver_face.png", IMG_SIZE, IMG_SIZE) + + # Colors + self.white_color = rl.Color(255, 255, 255, 255) + self.arc_color = rl.Color(26, 242, 66, 255) + self.engaged_color = rl.Color(26, 242, 66, 255) + self.disengaged_color = rl.Color(139, 139, 139, 255) + + self.set_visible(lambda: (ui_state.sm.recv_frame['driverStateV2'] > ui_state.started_frame and + ui_state.sm.seen['driverMonitoringState'])) + + def _render(self, rect): + # Set opacity based on active state + opacity = 0.65 if self.is_active else 0.2 + + # Draw background circle + rl.draw_circle(int(self.position_x), int(self.position_y), BTN_SIZE // 2, rl.Color(0, 0, 0, 70)) + + # Draw face icon + icon_pos = rl.Vector2(self.position_x - self.dm_img.width // 2, self.position_y - self.dm_img.height // 2) + rl.draw_texture_v(self.dm_img, icon_pos, rl.Color(255, 255, 255, int(255 * opacity))) + + # Draw face outline + self.white_color.a = int(255 * opacity) + rl.draw_spline_linear(self.face_lines, len(self.face_lines), 5.2, self.white_color) + + # Set arc color based on engaged state + self.arc_color = self.engaged_color if ui_state.engaged else self.disengaged_color + self.arc_color.a = int(0.4 * 255 * (1.0 - self.dm_fade_state)) # Fade out when inactive + + # Draw arcs + if self.h_arc_data: + rl.draw_spline_linear(self.h_arc_lines, len(self.h_arc_lines), self.h_arc_data.thickness, self.arc_color) + if self.v_arc_data: + rl.draw_spline_linear(self.v_arc_lines, len(self.v_arc_lines), self.v_arc_data.thickness, self.arc_color) + + def _update_state(self): + """Update the driver monitoring state based on model data""" + sm = ui_state.sm + if not sm.updated["driverMonitoringState"]: + if (self._rect.x != self.last_rect.x or self._rect.y != self.last_rect.y or + self._rect.width != self.last_rect.width or self._rect.height != self.last_rect.height): + self._pre_calculate_drawing_elements() + self.last_rect = self._rect + return + + # Get monitoring state + dm_state = sm["driverMonitoringState"] + self.is_active = dm_state.isActiveMode + self.is_rhd = dm_state.isRHD + + # Update fade state (smoother transition between active/inactive) + fade_target = 0.0 if self.is_active else 0.5 + self.dm_fade_state = np.clip(self.dm_fade_state + 0.2 * (fade_target - self.dm_fade_state), 0.0, 1.0) + + # Get driver orientation data from appropriate camera + driverstate = sm["driverStateV2"] + driver_data = driverstate.rightDriverData if self.is_rhd else driverstate.leftDriverData + driver_orient = driver_data.faceOrientation + + # Update pose values with scaling and smoothing + driver_orient = np.array(driver_orient) + scales = np.where(driver_orient < 0, SCALES_NEG, SCALES_POS) + v_this = driver_orient * scales + self.driver_pose_diff = np.abs(self.driver_pose_vals - v_this) + self.driver_pose_vals = 0.8 * v_this + 0.2 * self.driver_pose_vals # Smooth changes + + # Apply fade to rotation and compute sin/cos + rotation_amount = self.driver_pose_vals * (1.0 - self.dm_fade_state) + self.driver_pose_sins = np.sin(rotation_amount) + self.driver_pose_coss = np.cos(rotation_amount) + + # Create rotation matrix for 3D face model + sin_y, sin_x, sin_z = self.driver_pose_sins + cos_y, cos_x, cos_z = self.driver_pose_coss + r_xyz = np.array( + [ + [cos_x * cos_z, cos_x * sin_z, -sin_x], + [-sin_y * sin_x * cos_z - cos_y * sin_z, -sin_y * sin_x * sin_z + cos_y * cos_z, -sin_y * cos_x], + [cos_y * sin_x * cos_z - sin_y * sin_z, cos_y * sin_x * sin_z + sin_y * cos_z, cos_y * cos_x], + ] + ) + + # Transform face keypoints using vectorized matrix multiplication + self.face_kpts_draw = DEFAULT_FACE_KPTS_3D @ r_xyz.T + self.face_kpts_draw[:, 2] = self.face_kpts_draw[:, 2] * (1.0 - self.dm_fade_state) + 8 * self.dm_fade_state + + # Pre-calculate the transformed keypoints + kp_depth = (self.face_kpts_draw[:, 2] - 8) / 120.0 + 1.0 + self.face_keypoints_transformed = self.face_kpts_draw[:, :2] * kp_depth[:, None] + + # Pre-calculate all drawing elements + self._pre_calculate_drawing_elements() + + def _pre_calculate_drawing_elements(self): + """Pre-calculate all drawing elements based on the current rectangle""" + # Calculate icon position (bottom-left or bottom-right) + width, height = self._rect.width, self._rect.height + offset = UI_BORDER_SIZE + BTN_SIZE // 2 + self.position_x = self._rect.x + (width - offset if self.is_rhd else offset) + self.position_y = self._rect.y + height - offset + + # Pre-calculate the face lines positions + positioned_keypoints = self.face_keypoints_transformed + np.array([self.position_x, self.position_y]) + for i in range(len(positioned_keypoints)): + self.face_lines[i].x = positioned_keypoints[i][0] + self.face_lines[i].y = positioned_keypoints[i][1] + + # Calculate arc dimensions based on head rotation + delta_x = -self.driver_pose_sins[1] * ARC_LENGTH / 2.0 # Horizontal movement + delta_y = -self.driver_pose_sins[0] * ARC_LENGTH / 2.0 # Vertical movement + + # Horizontal arc + h_width = abs(delta_x) + self.h_arc_data = self._calculate_arc_data( + delta_x, h_width, self.position_x, self.position_y - ARC_LENGTH / 2, + self.driver_pose_sins[1], self.driver_pose_diff[1], is_horizontal=True + ) + + # Vertical arc + v_height = abs(delta_y) + self.v_arc_data = self._calculate_arc_data( + delta_y, v_height, self.position_x - ARC_LENGTH / 2, self.position_y, + self.driver_pose_sins[0], self.driver_pose_diff[0], is_horizontal=False + ) + + def _calculate_arc_data( + self, delta: float, size: float, x: float, y: float, sin_val: float, diff_val: float, is_horizontal: bool + ): + """Calculate arc data and pre-compute arc points.""" + if size <= 0: + return None + + thickness = ARC_THICKNESS_DEFAULT + ARC_THICKNESS_EXTEND * min(1.0, diff_val * 5.0) + start_angle = (90 if sin_val > 0 else -90) if is_horizontal else (0 if sin_val > 0 else 180) + x = min(x + delta, x) if is_horizontal else x + y = y if is_horizontal else min(y + delta, y) + + arc_data = ArcData( + x=x, + y=y, + width=size if is_horizontal else ARC_LENGTH, + height=ARC_LENGTH if is_horizontal else size, + thickness=thickness, + ) + + # Pre-calculate arc points + angles = ARC_ANGLES + np.deg2rad(start_angle) + + center_x = x + arc_data.width / 2 + center_y = y + arc_data.height / 2 + radius_x = arc_data.width / 2 + radius_y = arc_data.height / 2 + + x_coords = center_x + np.cos(angles) * radius_x + y_coords = center_y + np.sin(angles) * radius_y + + arc_lines = self.h_arc_lines if is_horizontal else self.v_arc_lines + for i, (x_coord, y_coord) in enumerate(zip(x_coords, y_coords, strict=True)): + arc_lines[i].x = x_coord + arc_lines[i].y = y_coord + + return arc_data diff --git a/selfdrive/ui/onroad/exp_button.py b/selfdrive/ui/onroad/exp_button.py new file mode 100644 index 0000000000..175233c5ba --- /dev/null +++ b/selfdrive/ui/onroad/exp_button.py @@ -0,0 +1,73 @@ +import time +import pyray as rl +from openpilot.common.params import Params +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.widgets import Widget + + +class ExpButton(Widget): + def __init__(self, button_size: int, icon_size: int): + super().__init__() + self._params = Params() + self._experimental_mode: bool = False + self._engageable: bool = False + + # State hold mechanism + self._hold_duration = 2.0 # seconds + self._held_mode: bool | None = None + self._hold_end_time: float | None = None + + self._white_color: rl.Color = rl.Color(255, 255, 255, 255) + self._black_bg: rl.Color = rl.Color(0, 0, 0, 166) + self._txt_wheel: rl.Texture = gui_app.texture('icons/chffr_wheel.png', icon_size, icon_size) + self._txt_exp: rl.Texture = gui_app.texture('icons/experimental.png', icon_size, icon_size) + self._rect = rl.Rectangle(0, 0, button_size, button_size) + + def set_rect(self, rect: rl.Rectangle) -> None: + self._rect.x, self._rect.y = rect.x, rect.y + + def _update_state(self) -> None: + selfdrive_state = ui_state.sm["selfdriveState"] + self._experimental_mode = selfdrive_state.experimentalMode + self._engageable = selfdrive_state.engageable or selfdrive_state.enabled + + def _handle_mouse_release(self, _): + super()._handle_mouse_release(_) + if self._is_toggle_allowed(): + new_mode = not self._experimental_mode + self._params.put_bool("ExperimentalMode", new_mode) + + # Hold new state temporarily + self._held_mode = new_mode + self._hold_end_time = time.monotonic() + self._hold_duration + + def _render(self, rect: rl.Rectangle) -> None: + center_x = int(self._rect.x + self._rect.width // 2) + center_y = int(self._rect.y + self._rect.height // 2) + + self._white_color.a = 180 if self.is_pressed or not self._engageable else 255 + + texture = self._txt_exp if self._held_or_actual_mode() else self._txt_wheel + rl.draw_circle(center_x, center_y, self._rect.width / 2, self._black_bg) + rl.draw_texture(texture, center_x - texture.width // 2, center_y - texture.height // 2, self._white_color) + + def _held_or_actual_mode(self): + now = time.monotonic() + if self._hold_end_time and now < self._hold_end_time: + return self._held_mode + + if self._hold_end_time and now >= self._hold_end_time: + self._hold_end_time = self._held_mode = None + + return self._experimental_mode + + def _is_toggle_allowed(self): + if not self._params.get_bool("ExperimentalModeConfirmed"): + return False + + car_params = ui_state.sm["carParams"] + if car_params.alphaLongitudinalAvailable: + return self._params.get_bool("AlphaLongitudinalEnabled") + else: + return car_params.openpilotLongitudinalControl diff --git a/selfdrive/ui/onroad/hud_renderer.py b/selfdrive/ui/onroad/hud_renderer.py new file mode 100644 index 0000000000..c813d852bc --- /dev/null +++ b/selfdrive/ui/onroad/hud_renderer.py @@ -0,0 +1,179 @@ +import pyray as rl +from dataclasses import dataclass +from openpilot.common.constants import CV +from openpilot.selfdrive.ui.onroad.exp_button import ExpButton +from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import Widget + +# Constants +SET_SPEED_NA = 255 +KM_TO_MILE = 0.621371 +CRUISE_DISABLED_CHAR = '–' + + +@dataclass(frozen=True) +class UIConfig: + header_height: int = 300 + border_size: int = 30 + button_size: int = 192 + set_speed_width_metric: int = 200 + set_speed_width_imperial: int = 172 + set_speed_height: int = 204 + wheel_icon_size: int = 144 + + +@dataclass(frozen=True) +class FontSizes: + current_speed: int = 176 + speed_unit: int = 66 + max_speed: int = 40 + set_speed: int = 90 + + +@dataclass(frozen=True) +class Colors: + white: rl.Color = rl.WHITE + disengaged: rl.Color = rl.Color(145, 155, 149, 255) + override: rl.Color = rl.Color(145, 155, 149, 255) # Added + engaged: rl.Color = rl.Color(128, 216, 166, 255) + disengaged_bg: rl.Color = rl.Color(0, 0, 0, 153) + override_bg: rl.Color = rl.Color(145, 155, 149, 204) + engaged_bg: rl.Color = rl.Color(128, 216, 166, 204) + grey: rl.Color = rl.Color(166, 166, 166, 255) + dark_grey: rl.Color = rl.Color(114, 114, 114, 255) + black_translucent: rl.Color = rl.Color(0, 0, 0, 166) + white_translucent: rl.Color = rl.Color(255, 255, 255, 200) + border_translucent: rl.Color = rl.Color(255, 255, 255, 75) + header_gradient_start: rl.Color = rl.Color(0, 0, 0, 114) + header_gradient_end: rl.Color = rl.BLANK + + +UI_CONFIG = UIConfig() +FONT_SIZES = FontSizes() +COLORS = Colors() + + +class HudRenderer(Widget): + def __init__(self): + super().__init__() + """Initialize the HUD renderer.""" + self.is_cruise_set: bool = False + self.is_cruise_available: bool = False + self.set_speed: float = SET_SPEED_NA + self.speed: float = 0.0 + self.v_ego_cluster_seen: bool = False + + self._font_semi_bold: rl.Font = gui_app.font(FontWeight.SEMI_BOLD) + self._font_bold: rl.Font = gui_app.font(FontWeight.BOLD) + self._font_medium: rl.Font = gui_app.font(FontWeight.MEDIUM) + + self._exp_button: ExpButton = ExpButton(UI_CONFIG.button_size, UI_CONFIG.wheel_icon_size) + + def _update_state(self) -> None: + """Update HUD state based on car state and controls state.""" + sm = ui_state.sm + if sm.recv_frame["carState"] < ui_state.started_frame: + self.is_cruise_set = False + self.set_speed = SET_SPEED_NA + self.speed = 0.0 + return + + controls_state = sm['controlsState'] + car_state = sm['carState'] + + v_cruise_cluster = car_state.vCruiseCluster + self.set_speed = ( + controls_state.vCruiseDEPRECATED if v_cruise_cluster == 0.0 else v_cruise_cluster + ) + self.is_cruise_set = 0 < self.set_speed < SET_SPEED_NA + self.is_cruise_available = self.set_speed != -1 + + if self.is_cruise_set and not ui_state.is_metric: + self.set_speed *= KM_TO_MILE + + v_ego_cluster = car_state.vEgoCluster + self.v_ego_cluster_seen = self.v_ego_cluster_seen or v_ego_cluster != 0.0 + v_ego = v_ego_cluster if self.v_ego_cluster_seen else car_state.vEgo + speed_conversion = CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH + self.speed = max(0.0, v_ego * speed_conversion) + + def _render(self, rect: rl.Rectangle) -> None: + """Render HUD elements to the screen.""" + # Draw the header background + rl.draw_rectangle_gradient_v( + int(rect.x), + int(rect.y), + int(rect.width), + UI_CONFIG.header_height, + COLORS.header_gradient_start, + COLORS.header_gradient_end, + ) + + if self.is_cruise_available: + self._draw_set_speed(rect) + + self._draw_current_speed(rect) + + button_x = rect.x + rect.width - UI_CONFIG.border_size - UI_CONFIG.button_size + button_y = rect.y + UI_CONFIG.border_size + self._exp_button.render(rl.Rectangle(button_x, button_y, UI_CONFIG.button_size, UI_CONFIG.button_size)) + + def user_interacting(self) -> bool: + return self._exp_button.is_pressed + + def _draw_set_speed(self, rect: rl.Rectangle) -> None: + """Draw the MAX speed indicator box.""" + set_speed_width = UI_CONFIG.set_speed_width_metric if ui_state.is_metric else UI_CONFIG.set_speed_width_imperial + x = rect.x + 60 + (UI_CONFIG.set_speed_width_imperial - set_speed_width) // 2 + y = rect.y + 45 + + set_speed_rect = rl.Rectangle(x, y, set_speed_width, UI_CONFIG.set_speed_height) + rl.draw_rectangle_rounded(set_speed_rect, 0.2, 30, COLORS.black_translucent) + rl.draw_rectangle_rounded_lines_ex(set_speed_rect, 0.2, 30, 6, COLORS.border_translucent) + + max_color = COLORS.grey + set_speed_color = COLORS.dark_grey + if self.is_cruise_set: + set_speed_color = COLORS.white + if ui_state.status == UIStatus.ENGAGED: + max_color = COLORS.engaged + elif ui_state.status == UIStatus.DISENGAGED: + max_color = COLORS.disengaged + elif ui_state.status == UIStatus.OVERRIDE: + max_color = COLORS.override + + max_text = "MAX" + max_text_width = measure_text_cached(self._font_semi_bold, max_text, FONT_SIZES.max_speed).x + rl.draw_text_ex( + self._font_semi_bold, + max_text, + rl.Vector2(x + (set_speed_width - max_text_width) / 2, y + 27), + FONT_SIZES.max_speed, + 0, + max_color, + ) + + set_speed_text = CRUISE_DISABLED_CHAR if not self.is_cruise_set else str(round(self.set_speed)) + speed_text_width = measure_text_cached(self._font_bold, set_speed_text, FONT_SIZES.set_speed).x + rl.draw_text_ex( + self._font_bold, + set_speed_text, + rl.Vector2(x + (set_speed_width - speed_text_width) / 2, y + 77), + FONT_SIZES.set_speed, + 0, + set_speed_color, + ) + + def _draw_current_speed(self, rect: rl.Rectangle) -> None: + """Draw the current vehicle speed and unit.""" + speed_text = str(round(self.speed)) + speed_text_size = measure_text_cached(self._font_bold, speed_text, FONT_SIZES.current_speed) + speed_pos = rl.Vector2(rect.x + rect.width / 2 - speed_text_size.x / 2, 180 - speed_text_size.y / 2) + rl.draw_text_ex(self._font_bold, speed_text, speed_pos, FONT_SIZES.current_speed, 0, COLORS.white) + + unit_text = "km/h" if ui_state.is_metric else "mph" + unit_text_size = measure_text_cached(self._font_medium, unit_text, FONT_SIZES.speed_unit) + unit_pos = rl.Vector2(rect.x + rect.width / 2 - unit_text_size.x / 2, 290 - unit_text_size.y / 2) + rl.draw_text_ex(self._font_medium, unit_text, unit_pos, FONT_SIZES.speed_unit, 0, COLORS.white_translucent) diff --git a/selfdrive/ui/onroad/model_renderer.py b/selfdrive/ui/onroad/model_renderer.py new file mode 100644 index 0000000000..a770c0f92f --- /dev/null +++ b/selfdrive/ui/onroad/model_renderer.py @@ -0,0 +1,422 @@ +import colorsys +import numpy as np +import pyray as rl +from cereal import messaging, car +from dataclasses import dataclass, field +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.params import Params +from openpilot.selfdrive.locationd.calibrationd import HEIGHT_INIT +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.shader_polygon import draw_polygon +from openpilot.system.ui.widgets import Widget + +CLIP_MARGIN = 500 +MIN_DRAW_DISTANCE = 10.0 +MAX_DRAW_DISTANCE = 100.0 + +MAX_POINTS = 200 + +THROTTLE_COLORS = [ + rl.Color(13, 248, 122, 102), # HSLF(148/360, 0.94, 0.51, 0.4) + rl.Color(114, 255, 92, 89), # HSLF(112/360, 1.0, 0.68, 0.35) + rl.Color(114, 255, 92, 0), # HSLF(112/360, 1.0, 0.68, 0.0) +] + +NO_THROTTLE_COLORS = [ + rl.Color(242, 242, 242, 102), # HSLF(148/360, 0.0, 0.95, 0.4) + rl.Color(242, 242, 242, 89), # HSLF(112/360, 0.0, 0.95, 0.35) + rl.Color(242, 242, 242, 0), # HSLF(112/360, 0.0, 0.95, 0.0) +] + + +@dataclass +class ModelPoints: + raw_points: np.ndarray = field(default_factory=lambda: np.empty((0, 3), dtype=np.float32)) + projected_points: np.ndarray = field(default_factory=lambda: np.empty((0, 2), dtype=np.float32)) + + +@dataclass +class LeadVehicle: + glow: list[float] = field(default_factory=list) + chevron: list[float] = field(default_factory=list) + fill_alpha: int = 0 + + +class ModelRenderer(Widget): + def __init__(self): + super().__init__() + self._longitudinal_control = False + self._experimental_mode = False + self._blend_filter = FirstOrderFilter(1.0, 0.25, 1 / gui_app.target_fps) + self._prev_allow_throttle = True + self._lane_line_probs = np.zeros(4, dtype=np.float32) + self._road_edge_stds = np.zeros(2, dtype=np.float32) + self._lead_vehicles = [LeadVehicle(), LeadVehicle()] + self._path_offset_z = HEIGHT_INIT[0] + + # Initialize ModelPoints objects + self._path = ModelPoints() + self._lane_lines = [ModelPoints() for _ in range(4)] + self._road_edges = [ModelPoints() for _ in range(2)] + self._acceleration_x = np.empty((0,), dtype=np.float32) + + # Transform matrix (3x3 for car space to screen space) + self._car_space_transform = np.zeros((3, 3), dtype=np.float32) + self._transform_dirty = True + self._clip_region = None + + self._exp_gradient = { + 'start': (0.0, 1.0), # Bottom of path + 'end': (0.0, 0.0), # Top of path + 'colors': [], + 'stops': [], + } + + # Get longitudinal control setting from car parameters + if car_params := Params().get("CarParams"): + cp = messaging.log_from_bytes(car_params, car.CarParams) + self._longitudinal_control = cp.openpilotLongitudinalControl + + def set_transform(self, transform: np.ndarray): + self._car_space_transform = transform.astype(np.float32) + self._transform_dirty = True + + def _render(self, rect: rl.Rectangle): + sm = ui_state.sm + + # Check if data is up-to-date + if (sm.recv_frame["liveCalibration"] < ui_state.started_frame or + sm.recv_frame["modelV2"] < ui_state.started_frame): + return + + # Set up clipping region + self._clip_region = rl.Rectangle( + rect.x - CLIP_MARGIN, rect.y - CLIP_MARGIN, rect.width + 2 * CLIP_MARGIN, rect.height + 2 * CLIP_MARGIN + ) + + # Update state + self._experimental_mode = sm['selfdriveState'].experimentalMode + + live_calib = sm['liveCalibration'] + self._path_offset_z = live_calib.height[0] if live_calib.height else HEIGHT_INIT[0] + + if sm.updated['carParams']: + self._longitudinal_control = sm['carParams'].openpilotLongitudinalControl + + model = sm['modelV2'] + radar_state = sm['radarState'] if sm.valid['radarState'] else None + lead_one = radar_state.leadOne if radar_state else None + render_lead_indicator = self._longitudinal_control and radar_state is not None + + # Update model data when needed + model_updated = sm.updated['modelV2'] + if model_updated or sm.updated['radarState'] or self._transform_dirty: + if model_updated: + self._update_raw_points(model) + + path_x_array = self._path.raw_points[:, 0] + if path_x_array.size == 0: + return + + self._update_model(lead_one, path_x_array) + if render_lead_indicator: + self._update_leads(radar_state, path_x_array) + self._transform_dirty = False + + # Draw elements + self._draw_lane_lines() + self._draw_path(sm) + + if render_lead_indicator and radar_state: + self._draw_lead_indicator() + + def _update_raw_points(self, model): + """Update raw 3D points from model data""" + self._path.raw_points = np.array([model.position.x, model.position.y, model.position.z], dtype=np.float32).T + + for i, lane_line in enumerate(model.laneLines): + self._lane_lines[i].raw_points = np.array([lane_line.x, lane_line.y, lane_line.z], dtype=np.float32).T + + for i, road_edge in enumerate(model.roadEdges): + self._road_edges[i].raw_points = np.array([road_edge.x, road_edge.y, road_edge.z], dtype=np.float32).T + + self._lane_line_probs = np.array(model.laneLineProbs, dtype=np.float32) + self._road_edge_stds = np.array(model.roadEdgeStds, dtype=np.float32) + self._acceleration_x = np.array(model.acceleration.x, dtype=np.float32) + + def _update_leads(self, radar_state, path_x_array): + """Update positions of lead vehicles""" + self._lead_vehicles = [LeadVehicle(), LeadVehicle()] + leads = [radar_state.leadOne, radar_state.leadTwo] + + for i, lead_data in enumerate(leads): + if lead_data and lead_data.status: + d_rel, y_rel, v_rel = lead_data.dRel, lead_data.yRel, lead_data.vRel + idx = self._get_path_length_idx(path_x_array, d_rel) + + # Get z-coordinate from path at the lead vehicle position + z = self._path.raw_points[idx, 2] if idx < len(self._path.raw_points) else 0.0 + point = self._map_to_screen(d_rel, -y_rel, z + self._path_offset_z) + if point: + self._lead_vehicles[i] = self._update_lead_vehicle(d_rel, v_rel, point, self._rect) + + def _update_model(self, lead, path_x_array): + """Update model visualization data based on model message""" + max_distance = np.clip(path_x_array[-1], MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE) + max_idx = self._get_path_length_idx(self._lane_lines[0].raw_points[:, 0], max_distance) + + # Update lane lines using raw points + for i, lane_line in enumerate(self._lane_lines): + lane_line.projected_points = self._map_line_to_polygon( + lane_line.raw_points, 0.025 * self._lane_line_probs[i], 0.0, max_idx + ) + + # Update road edges using raw points + for road_edge in self._road_edges: + road_edge.projected_points = self._map_line_to_polygon(road_edge.raw_points, 0.025, 0.0, max_idx) + + # Update path using raw points + if lead and lead.status: + lead_d = lead.dRel * 2.0 + max_distance = np.clip(lead_d - min(lead_d * 0.35, 10.0), 0.0, max_distance) + + max_idx = self._get_path_length_idx(path_x_array, max_distance) + self._path.projected_points = self._map_line_to_polygon( + self._path.raw_points, 0.9, self._path_offset_z, max_idx, allow_invert=False + ) + + self._update_experimental_gradient() + + def _update_experimental_gradient(self): + """Pre-calculate experimental mode gradient colors""" + if not self._experimental_mode: + return + + max_len = min(len(self._path.projected_points) // 2, len(self._acceleration_x)) + + segment_colors = [] + gradient_stops = [] + + i = 0 + while i < max_len: + # Some points (screen space) are out of frame (rect space) + track_y = self._path.projected_points[i][1] + if track_y < self._rect.y or track_y > (self._rect.y + self._rect.height): + i += 1 + continue + + # Calculate color based on acceleration (0 is bottom, 1 is top) + lin_grad_point = 1 - (track_y - self._rect.y) / self._rect.height + + # speed up: 120, slow down: 0 + path_hue = np.clip(60 + self._acceleration_x[i] * 35, 0, 120) + + saturation = min(abs(self._acceleration_x[i] * 1.5), 1) + lightness = np.interp(saturation, [0.0, 1.0], [0.95, 0.62]) + alpha = np.interp(lin_grad_point, [0.75 / 2.0, 0.75], [0.4, 0.0]) + + # Use HSL to RGB conversion + color = self._hsla_to_color(path_hue / 360.0, saturation, lightness, alpha) + + gradient_stops.append(lin_grad_point) + segment_colors.append(color) + + # Skip a point, unless next is last + i += 1 + (1 if (i + 2) < max_len else 0) + + # Store the gradient in the path object + self._exp_gradient['colors'] = segment_colors + self._exp_gradient['stops'] = gradient_stops + + def _update_lead_vehicle(self, d_rel, v_rel, point, rect): + speed_buff, lead_buff = 10.0, 40.0 + + # Calculate fill alpha + fill_alpha = 0 + if d_rel < lead_buff: + fill_alpha = 255 * (1.0 - (d_rel / lead_buff)) + if v_rel < 0: + fill_alpha += 255 * (-1 * (v_rel / speed_buff)) + fill_alpha = min(fill_alpha, 255) + + # Calculate size and position + sz = np.clip((25 * 30) / (d_rel / 3 + 30), 15.0, 30.0) * 2.35 + x = np.clip(point[0], 0.0, rect.width - sz / 2) + y = min(point[1], rect.height - sz * 0.6) + + g_xo = sz / 5 + g_yo = sz / 10 + + glow = [(x + (sz * 1.35) + g_xo, y + sz + g_yo), (x, y - g_yo), (x - (sz * 1.35) - g_xo, y + sz + g_yo)] + chevron = [(x + (sz * 1.25), y + sz), (x, y), (x - (sz * 1.25), y + sz)] + + return LeadVehicle(glow=glow, chevron=chevron, fill_alpha=int(fill_alpha)) + + def _draw_lane_lines(self): + """Draw lane lines and road edges""" + for i, lane_line in enumerate(self._lane_lines): + if lane_line.projected_points.size == 0: + continue + + alpha = np.clip(self._lane_line_probs[i], 0.0, 0.7) + color = rl.Color(255, 255, 255, int(alpha * 255)) + draw_polygon(self._rect, lane_line.projected_points, color) + + for i, road_edge in enumerate(self._road_edges): + if road_edge.projected_points.size == 0: + continue + + alpha = np.clip(1.0 - self._road_edge_stds[i], 0.0, 1.0) + color = rl.Color(255, 0, 0, int(alpha * 255)) + draw_polygon(self._rect, road_edge.projected_points, color) + + def _draw_path(self, sm): + """Draw path with dynamic coloring based on mode and throttle state.""" + if not self._path.projected_points.size: + return + + allow_throttle = sm['longitudinalPlan'].allowThrottle or not self._longitudinal_control + self._blend_filter.update(int(allow_throttle)) + + if self._experimental_mode: + # Draw with acceleration coloring + if len(self._exp_gradient['colors']) > 1: + draw_polygon(self._rect, self._path.projected_points, gradient=self._exp_gradient) + else: + draw_polygon(self._rect, self._path.projected_points, rl.Color(255, 255, 255, 30)) + else: + # Blend throttle/no throttle colors based on transition + blend_factor = round(self._blend_filter.x * 100) / 100 + blended_colors = self._blend_colors(NO_THROTTLE_COLORS, THROTTLE_COLORS, blend_factor) + gradient = { + 'start': (0.0, 1.0), # Bottom of path + 'end': (0.0, 0.0), # Top of path + 'colors': blended_colors, + 'stops': [0.0, 0.5, 1.0], + } + draw_polygon(self._rect, self._path.projected_points, gradient=gradient) + + def _draw_lead_indicator(self): + # Draw lead vehicles if available + for lead in self._lead_vehicles: + if not lead.glow or not lead.chevron: + continue + + rl.draw_triangle_fan(lead.glow, len(lead.glow), rl.Color(218, 202, 37, 255)) + rl.draw_triangle_fan(lead.chevron, len(lead.chevron), rl.Color(201, 34, 49, lead.fill_alpha)) + + @staticmethod + def _get_path_length_idx(pos_x_array: np.ndarray, path_height: float) -> int: + """Get the index corresponding to the given path height""" + if len(pos_x_array) == 0: + return 0 + indices = np.where(pos_x_array <= path_height)[0] + return indices[-1] if indices.size > 0 else 0 + + def _map_to_screen(self, in_x, in_y, in_z): + """Project a point in car space to screen space""" + input_pt = np.array([in_x, in_y, in_z]) + pt = self._car_space_transform @ input_pt + + if abs(pt[2]) < 1e-6: + return None + + x, y = pt[0] / pt[2], pt[1] / pt[2] + + clip = self._clip_region + if not (clip.x <= x <= clip.x + clip.width and clip.y <= y <= clip.y + clip.height): + return None + + return (x, y) + + def _map_line_to_polygon(self, line: np.ndarray, y_off: float, z_off: float, max_idx: int, allow_invert: bool = True) -> np.ndarray: + """Convert 3D line to 2D polygon for rendering.""" + if line.shape[0] == 0: + return np.empty((0, 2), dtype=np.float32) + + # Slice points and filter non-negative x-coordinates + points = line[:max_idx + 1] + points = points[points[:, 0] >= 0] + if points.shape[0] == 0: + return np.empty((0, 2), dtype=np.float32) + + N = points.shape[0] + # Generate left and right 3D points in one array using broadcasting + offsets = np.array([[0, -y_off, z_off], [0, y_off, z_off]], dtype=np.float32) + points_3d = points[None, :, :] + offsets[:, None, :] # Shape: 2xNx3 + points_3d = points_3d.reshape(2 * N, 3) # Shape: (2*N)x3 + + # Transform all points to projected space in one operation + proj = self._car_space_transform @ points_3d.T # Shape: 3x(2*N) + proj = proj.reshape(3, 2, N) + left_proj = proj[:, 0, :] + right_proj = proj[:, 1, :] + + # Filter points where z is sufficiently large + valid_proj = (np.abs(left_proj[2]) >= 1e-6) & (np.abs(right_proj[2]) >= 1e-6) + if not np.any(valid_proj): + return np.empty((0, 2), dtype=np.float32) + + # Compute screen coordinates + left_screen = left_proj[:2, valid_proj] / left_proj[2, valid_proj][None, :] + right_screen = right_proj[:2, valid_proj] / right_proj[2, valid_proj][None, :] + + # Define clip region bounds + clip = self._clip_region + x_min, x_max = clip.x, clip.x + clip.width + y_min, y_max = clip.y, clip.y + clip.height + + # Filter points within clip region + left_in_clip = ( + (left_screen[0] >= x_min) & (left_screen[0] <= x_max) & + (left_screen[1] >= y_min) & (left_screen[1] <= y_max) + ) + right_in_clip = ( + (right_screen[0] >= x_min) & (right_screen[0] <= x_max) & + (right_screen[1] >= y_min) & (right_screen[1] <= y_max) + ) + both_in_clip = left_in_clip & right_in_clip + + if not np.any(both_in_clip): + return np.empty((0, 2), dtype=np.float32) + + # Select valid and clipped points + left_screen = left_screen[:, both_in_clip] + right_screen = right_screen[:, both_in_clip] + + # Handle Y-coordinate inversion on hills + if not allow_invert and left_screen.shape[1] > 1: + y = left_screen[1, :] # y-coordinates + keep = y == np.minimum.accumulate(y) + if not np.any(keep): + return np.empty((0, 2), dtype=np.float32) + left_screen = left_screen[:, keep] + right_screen = right_screen[:, keep] + + return np.vstack((left_screen.T, right_screen[:, ::-1].T)).astype(np.float32) + + @staticmethod + def _hsla_to_color(h, s, l, a): + rgb = colorsys.hls_to_rgb(h, l, s) + return rl.Color( + int(rgb[0] * 255), + int(rgb[1] * 255), + int(rgb[2] * 255), + int(a * 255) + ) + + @staticmethod + def _blend_colors(begin_colors, end_colors, t): + if t >= 1.0: + return end_colors + if t <= 0.0: + return begin_colors + + inv_t = 1.0 - t + return [rl.Color( + int(inv_t * start.r + t * end.r), + int(inv_t * start.g + t * end.g), + int(inv_t * start.b + t * end.b), + int(inv_t * start.a + t * end.a) + ) for start, end in zip(begin_colors, end_colors, strict=True)] diff --git a/selfdrive/ui/qt/api.cc b/selfdrive/ui/qt/api.cc new file mode 100644 index 0000000000..6889b40e51 --- /dev/null +++ b/selfdrive/ui/qt/api.cc @@ -0,0 +1,142 @@ +#include "selfdrive/ui/qt/api.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/util.h" +#include "system/hardware/hw.h" +#include "selfdrive/ui/qt/util.h" + +namespace CommaApi { + +RSA *get_rsa_private_key() { + static std::unique_ptr rsa_private(nullptr, RSA_free); + if (!rsa_private) { + FILE *fp = fopen(Path::rsa_file().c_str(), "rb"); + if (!fp) { + qDebug() << "No RSA private key found, please run manager.py or registration.py"; + return nullptr; + } + rsa_private.reset(PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)); + fclose(fp); + } + return rsa_private.get(); +} + +QByteArray rsa_sign(const QByteArray &data) { + RSA *rsa_private = get_rsa_private_key(); + if (!rsa_private) return {}; + + QByteArray sig(RSA_size(rsa_private), Qt::Uninitialized); + unsigned int sig_len; + int ret = RSA_sign(NID_sha256, (unsigned char*)data.data(), data.size(), (unsigned char*)sig.data(), &sig_len, rsa_private); + assert(ret == 1); + assert(sig.size() == sig_len); + return sig; +} + +QString create_jwt(const QJsonObject &payloads, int expiry) { + QJsonObject header = {{"alg", "RS256"}}; + + auto t = QDateTime::currentSecsSinceEpoch(); + QJsonObject payload = {{"identity", getDongleId().value_or("")}, {"nbf", t}, {"iat", t}, {"exp", t + expiry}}; + for (auto it = payloads.begin(); it != payloads.end(); ++it) { + payload.insert(it.key(), it.value()); + } + + auto b64_opts = QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals; + QString jwt = QJsonDocument(header).toJson(QJsonDocument::Compact).toBase64(b64_opts) + '.' + + QJsonDocument(payload).toJson(QJsonDocument::Compact).toBase64(b64_opts); + + auto hash = QCryptographicHash::hash(jwt.toUtf8(), QCryptographicHash::Sha256); + return jwt + "." + rsa_sign(hash).toBase64(b64_opts); +} + +} // namespace CommaApi + +HttpRequest::HttpRequest(QObject *parent, bool create_jwt, int timeout) : create_jwt(create_jwt), QObject(parent) { + networkTimer = new QTimer(this); + networkTimer->setSingleShot(true); + networkTimer->setInterval(timeout); + connect(networkTimer, &QTimer::timeout, this, &HttpRequest::requestTimeout); +} + +bool HttpRequest::active() const { + return reply != nullptr; +} + +bool HttpRequest::timeout() const { + return reply && reply->error() == QNetworkReply::OperationCanceledError; +} + +void HttpRequest::sendRequest(const QString &requestURL, const HttpRequest::Method method) { + if (active()) { + qDebug() << "HttpRequest is active"; + return; + } + QString token; + if (create_jwt) { + token = CommaApi::create_jwt(); + } else { + QString token_json = QString::fromStdString(util::read_file(util::getenv("HOME") + "/.comma/auth.json")); + QJsonDocument json_d = QJsonDocument::fromJson(token_json.toUtf8()); + token = json_d["access_token"].toString(); + } + + QNetworkRequest request; + request.setUrl(QUrl(requestURL)); + request.setRawHeader("User-Agent", getUserAgent().toUtf8()); + + if (!token.isEmpty()) { + request.setRawHeader(QByteArray("Authorization"), ("JWT " + token).toUtf8()); + } + + if (method == HttpRequest::Method::GET) { + reply = nam()->get(request); + } else if (method == HttpRequest::Method::DELETE) { + reply = nam()->deleteResource(request); + } + + networkTimer->start(); + connect(reply, &QNetworkReply::finished, this, &HttpRequest::requestFinished); +} + +void HttpRequest::requestTimeout() { + reply->abort(); +} + +void HttpRequest::requestFinished() { + networkTimer->stop(); + + if (reply->error() == QNetworkReply::NoError) { + emit requestDone(reply->readAll(), true, reply->error()); + } else { + QString error; + if (reply->error() == QNetworkReply::OperationCanceledError) { + nam()->clearAccessCache(); + nam()->clearConnectionCache(); + error = "Request timed out"; + } else { + error = reply->errorString(); + } + emit requestDone(error, false, reply->error()); + } + + reply->deleteLater(); + reply = nullptr; +} + +QNetworkAccessManager *HttpRequest::nam() { + static QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager(qApp); + return networkAccessManager; +} diff --git a/selfdrive/ui/qt/api.h b/selfdrive/ui/qt/api.h new file mode 100644 index 0000000000..ad64d7e722 --- /dev/null +++ b/selfdrive/ui/qt/api.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +#include "common/util.h" + +namespace CommaApi { + +const QString BASE_URL = util::getenv("API_HOST", "https://api.commadotai.com").c_str(); +QByteArray rsa_sign(const QByteArray &data); +QString create_jwt(const QJsonObject &payloads = {}, int expiry = 3600); + +} // namespace CommaApi + +/** + * Makes a request to the request endpoint. + */ + +class HttpRequest : public QObject { + Q_OBJECT + +public: + enum class Method {GET, DELETE}; + + explicit HttpRequest(QObject* parent, bool create_jwt = true, int timeout = 20000); + void sendRequest(const QString &requestURL, const Method method = Method::GET); + bool active() const; + bool timeout() const; + +signals: + void requestDone(const QString &response, bool success, QNetworkReply::NetworkError error); + +protected: + QNetworkReply *reply = nullptr; + +private: + static QNetworkAccessManager *nam(); + QTimer *networkTimer = nullptr; + bool create_jwt; + +private slots: + void requestTimeout(); + void requestFinished(); +}; diff --git a/selfdrive/ui/qt/body.cc b/selfdrive/ui/qt/body.cc new file mode 100644 index 0000000000..e01adbe063 --- /dev/null +++ b/selfdrive/ui/qt/body.cc @@ -0,0 +1,161 @@ +#include "selfdrive/ui/qt/body.h" + +#include +#include + +#include +#include + +#include "common/params.h" +#include "common/timing.h" + +RecordButton::RecordButton(QWidget *parent) : QPushButton(parent) { + setCheckable(true); + setChecked(false); + setFixedSize(148, 148); + + QObject::connect(this, &QPushButton::toggled, [=]() { + setEnabled(false); + }); +} + +void RecordButton::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + QPoint center(width() / 2, height() / 2); + + QColor bg(isChecked() ? "#FFFFFF" : "#737373"); + QColor accent(isChecked() ? "#FF0000" : "#FFFFFF"); + if (!isEnabled()) { + bg = QColor("#404040"); + accent = QColor("#FFFFFF"); + } + + if (isDown()) { + accent.setAlphaF(0.7); + } + + p.setPen(Qt::NoPen); + p.setBrush(bg); + p.drawEllipse(center, 74, 74); + + p.setPen(QPen(accent, 6)); + p.setBrush(Qt::NoBrush); + p.drawEllipse(center, 42, 42); + + p.setPen(Qt::NoPen); + p.setBrush(accent); + p.drawEllipse(center, 22, 22); +} + + +BodyWindow::BodyWindow(QWidget *parent) : fuel_filter(1.0, 5., 1. / UI_FREQ), QWidget(parent) { + QStackedLayout *layout = new QStackedLayout(this); + layout->setStackingMode(QStackedLayout::StackAll); + + QWidget *w = new QWidget; + QVBoxLayout *vlayout = new QVBoxLayout(w); + vlayout->setMargin(45); + layout->addWidget(w); + + // face + face = new QLabel(); + face->setAlignment(Qt::AlignCenter); + layout->addWidget(face); + awake = new QMovie("../assets/body/awake.gif", {}, this); + awake->setCacheMode(QMovie::CacheAll); + sleep = new QMovie("../assets/body/sleep.gif", {}, this); + sleep->setCacheMode(QMovie::CacheAll); + + // record button + btn = new RecordButton(this); + vlayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight); + QObject::connect(btn, &QPushButton::clicked, [=](bool checked) { + btn->setEnabled(false); + Params().putBool("DisableLogging", !checked); + last_button = nanos_since_boot(); + }); + w->raise(); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &BodyWindow::updateState); +} + +void BodyWindow::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + p.fillRect(rect(), QColor(0, 0, 0)); + + // battery outline + detail + p.translate(width() - 136, 16); + const QColor gray = QColor("#737373"); + p.setBrush(Qt::NoBrush); + p.setPen(QPen(gray, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + p.drawRoundedRect(2, 2, 78, 36, 8, 8); + + p.setPen(Qt::NoPen); + p.setBrush(gray); + p.drawRoundedRect(84, 12, 6, 16, 4, 4); + p.drawRect(84, 12, 3, 16); + + // battery level + double fuel = std::clamp(fuel_filter.x(), 0.2f, 1.0f); + const int m = 5; // manual margin since we can't do an inner border + p.setPen(Qt::NoPen); + p.setBrush(fuel > 0.25 ? QColor("#32D74B") : QColor("#FF453A")); + p.drawRoundedRect(2 + m, 2 + m, (78 - 2*m)*fuel, 36 - 2*m, 4, 4); + + // charging status + if (charging) { + p.setPen(Qt::NoPen); + p.setBrush(Qt::white); + const QPolygonF charger({ + QPointF(12.31, 0), + QPointF(12.31, 16.92), + QPointF(18.46, 16.92), + QPointF(6.15, 40), + QPointF(6.15, 23.08), + QPointF(0, 23.08), + }); + p.drawPolygon(charger.translated(98, 0)); + } +} + +void BodyWindow::offroadTransition(bool offroad) { + btn->setChecked(true); + btn->setEnabled(true); + fuel_filter.reset(1.0); +} + +void BodyWindow::updateState(const UIState &s) { + if (!isVisible()) { + return; + } + + const SubMaster &sm = *(s.sm); + auto cs = sm["carState"].getCarState(); + + charging = cs.getCharging(); + fuel_filter.update(cs.getFuelGauge()); + + // TODO: use carState.standstill when that's fixed + const bool standstill = std::abs(cs.getVEgo()) < 0.01; + QMovie *m = standstill ? sleep : awake; + if (m != face->movie()) { + face->setMovie(m); + face->movie()->start(); + } + + // update record button state + if (sm.updated("managerState") && (sm.rcv_time("managerState") - last_button)*1e-9 > 0.5) { + for (auto proc : sm["managerState"].getManagerState().getProcesses()) { + if (proc.getName() == "loggerd") { + btn->setEnabled(true); + btn->setChecked(proc.getRunning()); + } + } + } + + update(); +} diff --git a/selfdrive/ui/qt/body.h b/selfdrive/ui/qt/body.h new file mode 100644 index 0000000000..567a54d49b --- /dev/null +++ b/selfdrive/ui/qt/body.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include "common/util.h" +#include "selfdrive/ui/ui.h" + +class RecordButton : public QPushButton { + Q_OBJECT + +public: + RecordButton(QWidget* parent = 0); + +private: + void paintEvent(QPaintEvent*) override; +}; + +class BodyWindow : public QWidget { + Q_OBJECT + +public: + BodyWindow(QWidget* parent = 0); + +private: + bool charging = false; + uint64_t last_button = 0; + FirstOrderFilter fuel_filter; + QLabel *face; + QMovie *awake, *sleep; + RecordButton *btn; + void paintEvent(QPaintEvent*) override; + +private slots: + void updateState(const UIState &s); + void offroadTransition(bool onroad); +}; diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc new file mode 100644 index 0000000000..8b1fdf474c --- /dev/null +++ b/selfdrive/ui/qt/home.cc @@ -0,0 +1,243 @@ +#include "selfdrive/ui/qt/home.h" + +#include +#include +#include +#include + +#include "selfdrive/ui/qt/offroad/experimental_mode.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/widgets/prime.h" + +// HomeWindow: the container for the offroad and onroad UIs + +HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) { + QHBoxLayout *main_layout = new QHBoxLayout(this); + main_layout->setMargin(0); + main_layout->setSpacing(0); + + sidebar = new Sidebar(this); + main_layout->addWidget(sidebar); + QObject::connect(sidebar, &Sidebar::openSettings, this, &HomeWindow::openSettings); + + slayout = new QStackedLayout(); + main_layout->addLayout(slayout); + + home = new OffroadHome(this); + QObject::connect(home, &OffroadHome::openSettings, this, &HomeWindow::openSettings); + slayout->addWidget(home); + + onroad = new OnroadWindow(this); + slayout->addWidget(onroad); + + body = new BodyWindow(this); + slayout->addWidget(body); + + driver_view = new DriverViewWindow(this); + connect(driver_view, &DriverViewWindow::done, [=] { + showDriverView(false); + }); + slayout->addWidget(driver_view); + setAttribute(Qt::WA_NoSystemBackground); + QObject::connect(uiState(), &UIState::uiUpdate, this, &HomeWindow::updateState); + QObject::connect(uiState(), &UIState::offroadTransition, this, &HomeWindow::offroadTransition); + QObject::connect(uiState(), &UIState::offroadTransition, sidebar, &Sidebar::offroadTransition); +} + +void HomeWindow::showSidebar(bool show) { + sidebar->setVisible(show); +} + +void HomeWindow::updateState(const UIState &s) { + const SubMaster &sm = *(s.sm); + + // switch to the generic robot UI + if (onroad->isVisible() && !body->isEnabled() && sm["carParams"].getCarParams().getNotCar()) { + body->setEnabled(true); + slayout->setCurrentWidget(body); + } +} + +void HomeWindow::offroadTransition(bool offroad) { + body->setEnabled(false); + sidebar->setVisible(offroad); + if (offroad) { + slayout->setCurrentWidget(home); + } else { + slayout->setCurrentWidget(onroad); + } +} + +void HomeWindow::showDriverView(bool show) { + if (show) { + emit closeSettings(); + slayout->setCurrentWidget(driver_view); + } else { + slayout->setCurrentWidget(home); + } + sidebar->setVisible(show == false); +} + +void HomeWindow::mousePressEvent(QMouseEvent* e) { + // Handle sidebar collapsing + if ((onroad->isVisible() || body->isVisible()) && (!sidebar->isVisible() || e->x() > sidebar->width())) { + sidebar->setVisible(!sidebar->isVisible()); + } +} + +void HomeWindow::mouseDoubleClickEvent(QMouseEvent* e) { + HomeWindow::mousePressEvent(e); + const SubMaster &sm = *(uiState()->sm); + if (sm["carParams"].getCarParams().getNotCar()) { + if (onroad->isVisible()) { + slayout->setCurrentWidget(body); + } else if (body->isVisible()) { + slayout->setCurrentWidget(onroad); + } + showSidebar(false); + } +} + +// OffroadHome: the offroad home page + +OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) { + QVBoxLayout* main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(40, 40, 40, 40); + + // top header + QHBoxLayout* header_layout = new QHBoxLayout(); + header_layout->setContentsMargins(0, 0, 0, 0); + header_layout->setSpacing(16); + + update_notif = new QPushButton(tr("UPDATE")); + update_notif->setVisible(false); + update_notif->setStyleSheet("background-color: #364DEF;"); + QObject::connect(update_notif, &QPushButton::clicked, [=]() { center_layout->setCurrentIndex(1); }); + header_layout->addWidget(update_notif, 0, Qt::AlignHCenter | Qt::AlignLeft); + + alert_notif = new QPushButton(); + alert_notif->setVisible(false); + alert_notif->setStyleSheet("background-color: #E22C2C;"); + QObject::connect(alert_notif, &QPushButton::clicked, [=] { center_layout->setCurrentIndex(2); }); + header_layout->addWidget(alert_notif, 0, Qt::AlignHCenter | Qt::AlignLeft); + + version = new ElidedLabel(); + header_layout->addWidget(version, 0, Qt::AlignHCenter | Qt::AlignRight); + + main_layout->addLayout(header_layout); + + // main content + main_layout->addSpacing(25); + center_layout = new QStackedLayout(); + + QWidget *home_widget = new QWidget(this); + { + QHBoxLayout *home_layout = new QHBoxLayout(home_widget); + home_layout->setContentsMargins(0, 0, 0, 0); + home_layout->setSpacing(30); + + // left: PrimeAdWidget + QStackedWidget *left_widget = new QStackedWidget(this); + QVBoxLayout *left_prime_layout = new QVBoxLayout(); + left_prime_layout->setContentsMargins(0, 0, 0, 0); + QWidget *prime_user = new PrimeUserWidget(); + prime_user->setStyleSheet(R"( + border-radius: 10px; + background-color: #333333; + )"); + left_prime_layout->addWidget(prime_user); + left_prime_layout->addStretch(); + left_widget->addWidget(new LayoutWidget(left_prime_layout)); + left_widget->addWidget(new PrimeAdWidget); + left_widget->setStyleSheet("border-radius: 10px;"); + + connect(uiState()->prime_state, &PrimeState::changed, [left_widget]() { + left_widget->setCurrentIndex(uiState()->prime_state->isSubscribed() ? 0 : 1); + }); + + home_layout->addWidget(left_widget, 1); + + // right: ExperimentalModeButton, SetupWidget + QWidget* right_widget = new QWidget(this); + QVBoxLayout* right_column = new QVBoxLayout(right_widget); + right_column->setContentsMargins(0, 0, 0, 0); + right_widget->setFixedWidth(750); + right_column->setSpacing(30); + + ExperimentalModeButton *experimental_mode = new ExperimentalModeButton(this); + QObject::connect(experimental_mode, &ExperimentalModeButton::openSettings, this, &OffroadHome::openSettings); + right_column->addWidget(experimental_mode, 1); + + SetupWidget *setup_widget = new SetupWidget; + QObject::connect(setup_widget, &SetupWidget::openSettings, this, &OffroadHome::openSettings); + right_column->addWidget(setup_widget, 1); + + home_layout->addWidget(right_widget, 1); + } + center_layout->addWidget(home_widget); + + // add update & alerts widgets + update_widget = new UpdateAlert(); + QObject::connect(update_widget, &UpdateAlert::dismiss, [=]() { center_layout->setCurrentIndex(0); }); + center_layout->addWidget(update_widget); + alerts_widget = new OffroadAlert(); + QObject::connect(alerts_widget, &OffroadAlert::dismiss, [=]() { center_layout->setCurrentIndex(0); }); + center_layout->addWidget(alerts_widget); + + main_layout->addLayout(center_layout, 1); + + // set up refresh timer + timer = new QTimer(this); + timer->callOnTimeout(this, &OffroadHome::refresh); + + setStyleSheet(R"( + * { + color: white; + } + OffroadHome { + background-color: black; + } + OffroadHome > QPushButton { + padding: 15px 30px; + border-radius: 5px; + font-size: 40px; + font-weight: 500; + } + OffroadHome > QLabel { + font-size: 55px; + } + )"); +} + +void OffroadHome::showEvent(QShowEvent *event) { + refresh(); + timer->start(10 * 1000); +} + +void OffroadHome::hideEvent(QHideEvent *event) { + timer->stop(); +} + +void OffroadHome::refresh() { + version->setText(getBrand() + " " + QString::fromStdString(params.get("UpdaterCurrentDescription"))); + + bool updateAvailable = update_widget->refresh(); + int alerts = alerts_widget->refresh(); + + // pop-up new notification + int idx = center_layout->currentIndex(); + if (!updateAvailable && !alerts) { + idx = 0; + } else if (updateAvailable && (!update_notif->isVisible() || (!alerts && idx == 2))) { + idx = 1; + } else if (alerts && (!alert_notif->isVisible() || (!updateAvailable && idx == 1))) { + idx = 2; + } + center_layout->setCurrentIndex(idx); + + update_notif->setVisible(updateAvailable); + alert_notif->setVisible(alerts); + if (alerts) { + alert_notif->setText(QString::number(alerts) + (alerts > 1 ? tr(" ALERTS") : tr(" ALERT"))); + } +} diff --git a/selfdrive/ui/qt/home.h b/selfdrive/ui/qt/home.h new file mode 100644 index 0000000000..a19b70ac3f --- /dev/null +++ b/selfdrive/ui/qt/home.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "common/params.h" +#include "selfdrive/ui/qt/offroad/driverview.h" +#include "selfdrive/ui/qt/body.h" +#include "selfdrive/ui/qt/onroad/onroad_home.h" +#include "selfdrive/ui/qt/sidebar.h" +#include "selfdrive/ui/qt/widgets/controls.h" +#include "selfdrive/ui/qt/widgets/offroad_alerts.h" +#include "selfdrive/ui/ui.h" + +class OffroadHome : public QFrame { + Q_OBJECT + +public: + explicit OffroadHome(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); + +private: + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + void refresh(); + + Params params; + + QTimer* timer; + ElidedLabel* version; + QStackedLayout* center_layout; + UpdateAlert *update_widget; + OffroadAlert* alerts_widget; + QPushButton* alert_notif; + QPushButton* update_notif; +}; + +class HomeWindow : public QWidget { + Q_OBJECT + +public: + explicit HomeWindow(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); + void closeSettings(); + +public slots: + void offroadTransition(bool offroad); + void showDriverView(bool show); + void showSidebar(bool show); + +protected: + void mousePressEvent(QMouseEvent* e) override; + void mouseDoubleClickEvent(QMouseEvent* e) override; + +private: + Sidebar *sidebar; + OffroadHome *home; + OnroadWindow *onroad; + BodyWindow *body; + DriverViewWindow *driver_view; + QStackedLayout *slayout; + +private slots: + void updateState(const UIState &s); +}; diff --git a/selfdrive/ui/qt/network/networking.cc b/selfdrive/ui/qt/network/networking.cc new file mode 100644 index 0000000000..f19786a46f --- /dev/null +++ b/selfdrive/ui/qt/network/networking.cc @@ -0,0 +1,413 @@ +#include "selfdrive/ui/qt/network/networking.h" + +#include + +#include +#include +#include + +#include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/widgets/controls.h" +#include "selfdrive/ui/qt/widgets/scrollview.h" + +static const int ICON_WIDTH = 49; + +// Networking functions + +Networking::Networking(QWidget* parent, bool show_advanced) : QFrame(parent) { + main_layout = new QStackedLayout(this); + + wifi = new WifiManager(this); + connect(wifi, &WifiManager::refreshSignal, this, &Networking::refresh); + connect(wifi, &WifiManager::wrongPassword, this, &Networking::wrongPassword); + + wifiScreen = new QWidget(this); + QVBoxLayout* vlayout = new QVBoxLayout(wifiScreen); + vlayout->setContentsMargins(20, 20, 20, 20); + if (show_advanced) { + QPushButton* advancedSettings = new QPushButton(tr("Advanced")); + advancedSettings->setObjectName("advanced_btn"); + advancedSettings->setStyleSheet("margin-right: 30px;"); + advancedSettings->setFixedSize(400, 100); + connect(advancedSettings, &QPushButton::clicked, [=]() { main_layout->setCurrentWidget(an); }); + vlayout->addSpacing(10); + vlayout->addWidget(advancedSettings, 0, Qt::AlignRight); + vlayout->addSpacing(10); + } + + wifiWidget = new WifiUI(this, wifi); + wifiWidget->setObjectName("wifiWidget"); + connect(wifiWidget, &WifiUI::connectToNetwork, this, &Networking::connectToNetwork); + + ScrollView *wifiScroller = new ScrollView(wifiWidget, this); + wifiScroller->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + vlayout->addWidget(wifiScroller, 1); + main_layout->addWidget(wifiScreen); + + an = new AdvancedNetworking(this, wifi); + connect(an, &AdvancedNetworking::backPress, [=]() { main_layout->setCurrentWidget(wifiScreen); }); + connect(an, &AdvancedNetworking::requestWifiScreen, [=]() { main_layout->setCurrentWidget(wifiScreen); }); + main_layout->addWidget(an); + + QPalette pal = palette(); + pal.setColor(QPalette::Window, QColor(0x29, 0x29, 0x29)); + setAutoFillBackground(true); + setPalette(pal); + + setStyleSheet(R"( + #wifiWidget > QPushButton, #back_btn, #advanced_btn { + font-size: 50px; + margin: 0px; + padding: 15px; + border-width: 0; + border-radius: 30px; + color: #dddddd; + background-color: #393939; + } + #back_btn:pressed, #advanced_btn:pressed { + background-color: #4a4a4a; + } + )"); + main_layout->setCurrentWidget(wifiScreen); +} + +void Networking::setPrimeType(PrimeState::Type type) { + an->setGsmVisible(type == PrimeState::PRIME_TYPE_NONE || type == PrimeState::PRIME_TYPE_LITE); + wifi->ipv4_forward = (type == PrimeState::PRIME_TYPE_NONE || type == PrimeState::PRIME_TYPE_LITE); +} + +void Networking::refresh() { + wifiWidget->refresh(); + an->refresh(); +} + +void Networking::connectToNetwork(const Network n) { + if (wifi->isKnownConnection(n.ssid)) { + wifi->activateWifiConnection(n.ssid); + } else if (n.security_type == SecurityType::OPEN) { + wifi->connect(n, false); + } else if (n.security_type == SecurityType::WPA) { + QString pass = InputDialog::getText(tr("Enter password"), this, tr("for \"%1\"").arg(QString::fromUtf8(n.ssid)), true, 8); + if (!pass.isEmpty()) { + wifi->connect(n, false, pass); + } + } +} + +void Networking::wrongPassword(const QString &ssid) { + if (wifi->seenNetworks.contains(ssid)) { + const Network &n = wifi->seenNetworks.value(ssid); + QString pass = InputDialog::getText(tr("Wrong password"), this, tr("for \"%1\"").arg(QString::fromUtf8(n.ssid)), true, 8); + if (!pass.isEmpty()) { + wifi->connect(n, false, pass); + } + } +} + +void Networking::showEvent(QShowEvent *event) { + wifi->start(); +} + +void Networking::hideEvent(QHideEvent *event) { + main_layout->setCurrentWidget(wifiScreen); + wifi->stop(); +} + +// AdvancedNetworking functions + +AdvancedNetworking::AdvancedNetworking(QWidget* parent, WifiManager* wifi): QWidget(parent), wifi(wifi) { + + QVBoxLayout* main_layout = new QVBoxLayout(this); + main_layout->setMargin(40); + main_layout->setSpacing(20); + + // Back button + QPushButton* back = new QPushButton(tr("Back")); + back->setObjectName("back_btn"); + back->setFixedSize(400, 100); + connect(back, &QPushButton::clicked, [=]() { emit backPress(); }); + main_layout->addWidget(back, 0, Qt::AlignLeft); + + ListWidget *list = new ListWidget(this); + // Enable tethering layout + tetheringToggle = new ToggleControl(tr("Enable Tethering"), "", "", wifi->isTetheringEnabled()); + list->addItem(tetheringToggle); + QObject::connect(tetheringToggle, &ToggleControl::toggleFlipped, this, &AdvancedNetworking::toggleTethering); + + // Change tethering password + ButtonControl *editPasswordButton = new ButtonControl(tr("Tethering Password"), tr("EDIT")); + connect(editPasswordButton, &ButtonControl::clicked, [=]() { + QString pass = InputDialog::getText(tr("Enter new tethering password"), this, "", true, 8, wifi->getTetheringPassword()); + if (!pass.isEmpty()) { + wifi->changeTetheringPassword(pass); + } + }); + list->addItem(editPasswordButton); + + // IP address + ipLabel = new LabelControl(tr("IP Address"), wifi->ipv4_address); + list->addItem(ipLabel); + + // Roaming toggle + const bool roamingEnabled = params.getBool("GsmRoaming"); + roamingToggle = new ToggleControl(tr("Enable Roaming"), "", "", roamingEnabled); + QObject::connect(roamingToggle, &ToggleControl::toggleFlipped, [=](bool state) { + params.putBool("GsmRoaming", state); + wifi->updateGsmSettings(state, QString::fromStdString(params.get("GsmApn")), params.getBool("GsmMetered")); + }); + list->addItem(roamingToggle); + + // APN settings + editApnButton = new ButtonControl(tr("APN Setting"), tr("EDIT")); + connect(editApnButton, &ButtonControl::clicked, [=]() { + const QString cur_apn = QString::fromStdString(params.get("GsmApn")); + QString apn = InputDialog::getText(tr("Enter APN"), this, tr("leave blank for automatic configuration"), false, -1, cur_apn).trimmed(); + + if (apn.isEmpty()) { + params.remove("GsmApn"); + } else { + params.put("GsmApn", apn.toStdString()); + } + wifi->updateGsmSettings(params.getBool("GsmRoaming"), apn, params.getBool("GsmMetered")); + }); + list->addItem(editApnButton); + + // Cellular metered toggle (prime lite or none) + const bool metered = params.getBool("GsmMetered"); + cellularMeteredToggle = new ToggleControl(tr("Cellular Metered"), tr("Prevent large data uploads when on a metered cellular connection"), "", metered); + QObject::connect(cellularMeteredToggle, &SshToggle::toggleFlipped, [=](bool state) { + params.putBool("GsmMetered", state); + wifi->updateGsmSettings(params.getBool("GsmRoaming"), QString::fromStdString(params.get("GsmApn")), state); + }); + list->addItem(cellularMeteredToggle); + + // Wi-Fi metered toggle + std::vector metered_button_texts{tr("default"), tr("metered"), tr("unmetered")}; + wifiMeteredToggle = new MultiButtonControl(tr("Wi-Fi Network Metered"), tr("Prevent large data uploads when on a metered Wi-Fi connection"), "", metered_button_texts); + QObject::connect(wifiMeteredToggle, &MultiButtonControl::buttonClicked, [=](int id) { + wifiMeteredToggle->setEnabled(false); + MeteredType metered = MeteredType::UNKNOWN; + if (id == NM_METERED_YES) { + metered = MeteredType::YES; + } else if (id == NM_METERED_NO) { + metered = MeteredType::NO; + } + auto pending_call = wifi->setCurrentNetworkMetered(metered); + if (pending_call) { + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(*pending_call); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=]() { + refresh(); + watcher->deleteLater(); + }); + } + }); + list->addItem(wifiMeteredToggle); + + // Hidden Network + hiddenNetworkButton = new ButtonControl(tr("Hidden Network"), tr("CONNECT")); + connect(hiddenNetworkButton, &ButtonControl::clicked, [=]() { + QString ssid = InputDialog::getText(tr("Enter SSID"), this, "", false, 1); + if (!ssid.isEmpty()) { + QString pass = InputDialog::getText(tr("Enter password"), this, tr("for \"%1\"").arg(ssid), true, -1); + Network hidden_network; + hidden_network.ssid = ssid.toUtf8(); + if (!pass.isEmpty()) { + hidden_network.security_type = SecurityType::WPA; + wifi->connect(hidden_network, true, pass); + } else { + wifi->connect(hidden_network, true); + } + emit requestWifiScreen(); + } + }); + list->addItem(hiddenNetworkButton); + + // Set initial config + wifi->updateGsmSettings(roamingEnabled, QString::fromStdString(params.get("GsmApn")), metered); + + main_layout->addWidget(new ScrollView(list, this)); + main_layout->addStretch(1); +} + +void AdvancedNetworking::setGsmVisible(bool visible) { + roamingToggle->setVisible(visible); + editApnButton->setVisible(visible); + cellularMeteredToggle->setVisible(visible); +} + +void AdvancedNetworking::refresh() { + ipLabel->setText(wifi->ipv4_address); + tetheringToggle->setEnabled(true); + + if (wifi->isTetheringEnabled() || wifi->ipv4_address == "") { + wifiMeteredToggle->setEnabled(false); + wifiMeteredToggle->setCheckedButton(0); + } else if (wifi->ipv4_address != "") { + MeteredType metered = wifi->currentNetworkMetered(); + wifiMeteredToggle->setEnabled(true); + wifiMeteredToggle->setCheckedButton(static_cast(metered)); + } + + update(); +} + +void AdvancedNetworking::toggleTethering(bool enabled) { + wifi->setTetheringEnabled(enabled); + tetheringToggle->setEnabled(false); + if (enabled) { + wifiMeteredToggle->setEnabled(false); + wifiMeteredToggle->setCheckedButton(0); + } +} + +// WifiUI functions + +WifiUI::WifiUI(QWidget *parent, WifiManager* wifi) : QWidget(parent), wifi(wifi) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(0, 0, 0, 0); + main_layout->setSpacing(0); + + // load imgs + for (const auto &s : {"low", "medium", "high", "full"}) { + QPixmap pix(ASSET_PATH + "/icons/wifi_strength_" + s + ".svg"); + strengths.push_back(pix.scaledToHeight(68, Qt::SmoothTransformation)); + } + lock = QPixmap(ASSET_PATH + "icons/lock_closed.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation); + checkmark = QPixmap(ASSET_PATH + "icons/checkmark.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation); + circled_slash = QPixmap(ASSET_PATH + "icons/circled_slash.svg").scaledToWidth(ICON_WIDTH, Qt::SmoothTransformation); + + scanningLabel = new QLabel(tr("Scanning for networks...")); + scanningLabel->setStyleSheet("font-size: 65px;"); + main_layout->addWidget(scanningLabel, 0, Qt::AlignCenter); + + wifi_list_widget = new ListWidget(this); + wifi_list_widget->setVisible(false); + main_layout->addWidget(wifi_list_widget); + + setStyleSheet(R"( + QScrollBar::handle:vertical { + min-height: 0px; + border-radius: 4px; + background-color: #8A8A8A; + } + #forgetBtn { + font-size: 32px; + font-weight: 600; + color: #292929; + background-color: #BDBDBD; + border-width: 1px solid #828282; + border-radius: 5px; + padding: 40px; + padding-bottom: 16px; + padding-top: 16px; + } + #forgetBtn:pressed { + background-color: #828282; + } + #connecting { + font-size: 32px; + font-weight: 600; + color: white; + border-radius: 0; + padding: 27px; + padding-left: 43px; + padding-right: 43px; + background-color: black; + } + #ssidLabel { + text-align: left; + border: none; + padding-top: 50px; + padding-bottom: 50px; + } + #ssidLabel:disabled { + color: #696969; + } + )"); +} + +void WifiUI::refresh() { + bool is_empty = wifi->seenNetworks.isEmpty(); + scanningLabel->setVisible(is_empty); + wifi_list_widget->setVisible(!is_empty); + if (is_empty) return; + + setUpdatesEnabled(false); + + const bool is_tethering_enabled = wifi->isTetheringEnabled(); + QList sortedNetworks = wifi->seenNetworks.values(); + std::sort(sortedNetworks.begin(), sortedNetworks.end(), compare_by_strength); + + int n = 0; + for (Network &network : sortedNetworks) { + QPixmap status_icon; + if (network.connected == ConnectedType::CONNECTED) { + status_icon = checkmark; + } else if (network.security_type == SecurityType::UNSUPPORTED) { + status_icon = circled_slash; + } else if (network.security_type == SecurityType::WPA) { + status_icon = lock; + } + bool show_forget_btn = wifi->isKnownConnection(network.ssid) && !is_tethering_enabled; + QPixmap strength = strengths[strengthLevel(network.strength)]; + + auto item = getItem(n++); + item->setItem(network, status_icon, show_forget_btn, strength); + item->setVisible(true); + } + for (; n < wifi_items.size(); ++n) wifi_items[n]->setVisible(false); + + setUpdatesEnabled(true); +} + +WifiItem *WifiUI::getItem(int n) { + auto item = n < wifi_items.size() ? wifi_items[n] : wifi_items.emplace_back(new WifiItem(tr("CONNECTING..."), tr("FORGET"))); + if (!item->parentWidget()) { + QObject::connect(item, &WifiItem::connectToNetwork, this, &WifiUI::connectToNetwork); + QObject::connect(item, &WifiItem::forgotNetwork, [this](const Network n) { + if (ConfirmationDialog::confirm(tr("Forget Wi-Fi Network \"%1\"?").arg(QString::fromUtf8(n.ssid)), tr("Forget"), this)) + wifi->forgetConnection(n.ssid); + }); + wifi_list_widget->addItem(item); + } + return item; +} + +// WifiItem + +WifiItem::WifiItem(const QString &connecting_text, const QString &forget_text, QWidget *parent) : QWidget(parent) { + QHBoxLayout *hlayout = new QHBoxLayout(this); + hlayout->setContentsMargins(44, 0, 73, 0); + hlayout->setSpacing(50); + + hlayout->addWidget(ssidLabel = new ElidedLabel()); + ssidLabel->setObjectName("ssidLabel"); + ssidLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + hlayout->addWidget(connecting = new QPushButton(connecting_text), 0, Qt::AlignRight); + connecting->setObjectName("connecting"); + hlayout->addWidget(forgetBtn = new QPushButton(forget_text), 0, Qt::AlignRight); + forgetBtn->setObjectName("forgetBtn"); + hlayout->addWidget(iconLabel = new QLabel(), 0, Qt::AlignRight); + hlayout->addWidget(strengthLabel = new QLabel(), 0, Qt::AlignRight); + + iconLabel->setFixedWidth(ICON_WIDTH); + QObject::connect(forgetBtn, &QPushButton::clicked, [this]() { emit forgotNetwork(network); }); + QObject::connect(ssidLabel, &ElidedLabel::clicked, [this]() { + if (network.connected == ConnectedType::DISCONNECTED) emit connectToNetwork(network); + }); +} + +void WifiItem::setItem(const Network &n, const QPixmap &status_icon, bool show_forget_btn, const QPixmap &strength_icon) { + network = n; + + ssidLabel->setText(n.ssid); + ssidLabel->setEnabled(n.security_type != SecurityType::UNSUPPORTED); + ssidLabel->setFont(InterFont(55, network.connected == ConnectedType::DISCONNECTED ? QFont::Normal : QFont::Bold)); + + connecting->setVisible(n.connected == ConnectedType::CONNECTING); + forgetBtn->setVisible(show_forget_btn); + + iconLabel->setPixmap(status_icon); + strengthLabel->setPixmap(strength_icon); +} diff --git a/selfdrive/ui/qt/network/networking.h b/selfdrive/ui/qt/network/networking.h new file mode 100644 index 0000000000..0bdf64e459 --- /dev/null +++ b/selfdrive/ui/qt/network/networking.h @@ -0,0 +1,105 @@ +#pragma once + +#include + +#include "selfdrive/ui/qt/network/wifi_manager.h" +#include "selfdrive/ui/qt/prime_state.h" +#include "selfdrive/ui/qt/widgets/input.h" +#include "selfdrive/ui/qt/widgets/ssh_keys.h" +#include "selfdrive/ui/qt/widgets/toggle.h" + +class WifiItem : public QWidget { + Q_OBJECT +public: + explicit WifiItem(const QString &connecting_text, const QString &forget_text, QWidget* parent = nullptr); + void setItem(const Network& n, const QPixmap &icon, bool show_forget_btn, const QPixmap &strength); + +signals: + // Cannot pass Network by reference. it may change after the signal is sent. + void connectToNetwork(const Network n); + void forgotNetwork(const Network n); + +protected: + ElidedLabel* ssidLabel; + QPushButton* connecting; + QPushButton* forgetBtn; + QLabel* iconLabel; + QLabel* strengthLabel; + Network network; +}; + +class WifiUI : public QWidget { + Q_OBJECT + +public: + explicit WifiUI(QWidget *parent = 0, WifiManager* wifi = 0); + +private: + WifiItem *getItem(int n); + + WifiManager *wifi = nullptr; + QLabel *scanningLabel = nullptr; + QPixmap lock; + QPixmap checkmark; + QPixmap circled_slash; + QVector strengths; + ListWidget *wifi_list_widget = nullptr; + std::vector wifi_items; + +signals: + void connectToNetwork(const Network n); + +public slots: + void refresh(); +}; + +class AdvancedNetworking : public QWidget { + Q_OBJECT +public: + explicit AdvancedNetworking(QWidget* parent = 0, WifiManager* wifi = 0); + void setGsmVisible(bool visible); + +private: + LabelControl* ipLabel; + ToggleControl* tetheringToggle; + ToggleControl* roamingToggle; + ButtonControl* editApnButton; + ButtonControl* hiddenNetworkButton; + ToggleControl* cellularMeteredToggle; + MultiButtonControl* wifiMeteredToggle; + WifiManager* wifi = nullptr; + Params params; + +signals: + void backPress(); + void requestWifiScreen(); + +public slots: + void toggleTethering(bool enabled); + void refresh(); +}; + +class Networking : public QFrame { + Q_OBJECT + +public: + explicit Networking(QWidget* parent = 0, bool show_advanced = true); + void setPrimeType(PrimeState::Type type); + WifiManager* wifi = nullptr; + +private: + QStackedLayout* main_layout = nullptr; + QWidget* wifiScreen = nullptr; + AdvancedNetworking* an = nullptr; + WifiUI* wifiWidget; + + void showEvent(QShowEvent* event) override; + void hideEvent(QHideEvent* event) override; + +public slots: + void refresh(); + +private slots: + void connectToNetwork(const Network n); + void wrongPassword(const QString &ssid); +}; diff --git a/selfdrive/ui/qt/network/networkmanager.h b/selfdrive/ui/qt/network/networkmanager.h new file mode 100644 index 0000000000..8bdeaf3bbd --- /dev/null +++ b/selfdrive/ui/qt/network/networkmanager.h @@ -0,0 +1,48 @@ +#pragma once + +/** + * We are using a NetworkManager DBUS API : https://developer.gnome.org/NetworkManager/1.26/spec.html + * */ + +// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApFlags +const int NM_802_11_AP_FLAGS_NONE = 0x00000000; +const int NM_802_11_AP_FLAGS_PRIVACY = 0x00000001; +const int NM_802_11_AP_FLAGS_WPS = 0x00000002; + +// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApSecurityFlags +const int NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001; +const int NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002; +const int NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010; +const int NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020; +const int NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100; +const int NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200; + +const QString NM_DBUS_PATH = "/org/freedesktop/NetworkManager"; +const QString NM_DBUS_PATH_SETTINGS = "/org/freedesktop/NetworkManager/Settings"; + +const QString NM_DBUS_INTERFACE = "org.freedesktop.NetworkManager"; +const QString NM_DBUS_INTERFACE_PROPERTIES = "org.freedesktop.DBus.Properties"; +const QString NM_DBUS_INTERFACE_SETTINGS = "org.freedesktop.NetworkManager.Settings"; +const QString NM_DBUS_INTERFACE_SETTINGS_CONNECTION = "org.freedesktop.NetworkManager.Settings.Connection"; +const QString NM_DBUS_INTERFACE_DEVICE = "org.freedesktop.NetworkManager.Device"; +const QString NM_DBUS_INTERFACE_DEVICE_WIRELESS = "org.freedesktop.NetworkManager.Device.Wireless"; +const QString NM_DBUS_INTERFACE_ACCESS_POINT = "org.freedesktop.NetworkManager.AccessPoint"; +const QString NM_DBUS_INTERFACE_ACTIVE_CONNECTION = "org.freedesktop.NetworkManager.Connection.Active"; +const QString NM_DBUS_INTERFACE_IP4_CONFIG = "org.freedesktop.NetworkManager.IP4Config"; + +const QString NM_DBUS_SERVICE = "org.freedesktop.NetworkManager"; + +const int NM_DEVICE_STATE_UNKNOWN = 0; +const int NM_DEVICE_STATE_ACTIVATED = 100; +const int NM_DEVICE_STATE_NEED_AUTH = 60; +const int NM_DEVICE_TYPE_WIFI = 2; +const int NM_DEVICE_TYPE_MODEM = 8; +const int NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8; +const int DBUS_TIMEOUT = 100; + +// https://developer-old.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NMMetered +const int NM_METERED_UNKNOWN = 0; +const int NM_METERED_YES = 1; +const int NM_METERED_NO = 2; +const int NM_METERED_GUESS_YES = 3; +const int NM_METERED_GUESS_NO = 4; diff --git a/selfdrive/ui/qt/network/wifi_manager.cc b/selfdrive/ui/qt/network/wifi_manager.cc new file mode 100644 index 0000000000..d4ad8974b0 --- /dev/null +++ b/selfdrive/ui/qt/network/wifi_manager.cc @@ -0,0 +1,539 @@ +#include "selfdrive/ui/qt/network/wifi_manager.h" + +#include + +#include "common/swaglog.h" +#include "selfdrive/ui/qt/util.h" + +bool compare_by_strength(const Network &a, const Network &b) { + return std::tuple(a.connected, strengthLevel(a.strength), b.ssid) > + std::tuple(b.connected, strengthLevel(b.strength), a.ssid); +} + +template +T call(const QString &path, const QString &interface, const QString &method, Args &&...args) { + QDBusInterface nm(NM_DBUS_SERVICE, path, interface, QDBusConnection::systemBus()); + nm.setTimeout(DBUS_TIMEOUT); + + QDBusMessage response = nm.call(method, std::forward(args)...); + if (response.type() == QDBusMessage::ErrorMessage) { + qCritical() << "DBus call error:" << response.errorMessage(); + return T(); + } + + if constexpr (std::is_same_v) { + return response; + } else if (response.arguments().count() >= 1) { + QVariant vFirst = response.arguments().at(0).value().variant(); + if (vFirst.canConvert()) { + return vFirst.value(); + } + QDebug critical = qCritical(); + critical << "Variant unpacking failure :" << method << ','; + (critical << ... << args); + } + return T(); +} + +template +QDBusPendingCall asyncCall(const QString &path, const QString &interface, const QString &method, Args &&...args) { + QDBusInterface nm = QDBusInterface(NM_DBUS_SERVICE, path, interface, QDBusConnection::systemBus()); + return nm.asyncCall(method, args...); +} + +bool emptyPath(const QString &path) { + return path == "" || path == "/"; +} + +WifiManager::WifiManager(QObject *parent) : QObject(parent) { + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + + // Set tethering ssid as "weedle" + first 4 characters of a dongle id + tethering_ssid = "weedle"; + if (auto dongle_id = getDongleId()) { + tethering_ssid += "-" + dongle_id->left(4); + } + + adapter = getAdapter(); + if (!adapter.isEmpty()) { + setup(); + } else { + QDBusConnection::systemBus().connect(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeviceAdded", this, SLOT(deviceAdded(QDBusObjectPath))); + } + + timer.callOnTimeout(this, &WifiManager::requestScan); + + initConnections(); +} + +void WifiManager::setup() { + auto bus = QDBusConnection::systemBus(); + bus.connect(NM_DBUS_SERVICE, adapter, NM_DBUS_INTERFACE_DEVICE, "StateChanged", this, SLOT(stateChange(unsigned int, unsigned int, unsigned int))); + bus.connect(NM_DBUS_SERVICE, adapter, NM_DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", this, SLOT(propertyChange(QString, QVariantMap, QStringList))); + + bus.connect(NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "ConnectionRemoved", this, SLOT(connectionRemoved(QDBusObjectPath))); + bus.connect(NM_DBUS_SERVICE, NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "NewConnection", this, SLOT(newConnection(QDBusObjectPath))); + + raw_adapter_state = call(adapter, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_DEVICE, "State"); + activeAp = call(adapter, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_DEVICE_WIRELESS, "ActiveAccessPoint").path(); + + requestScan(); +} + +void WifiManager::start() { + timer.start(5000); + refreshNetworks(); +} + +void WifiManager::stop() { + timer.stop(); +} + +void WifiManager::refreshNetworks() { + if (adapter.isEmpty() || !timer.isActive()) return; + + QDBusPendingCall pending_call = asyncCall(adapter, NM_DBUS_INTERFACE_DEVICE_WIRELESS, "GetAllAccessPoints"); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending_call); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &WifiManager::refreshFinished); +} + +void WifiManager::refreshFinished(QDBusPendingCallWatcher *watcher) { + ipv4_address = getIp4Address(); + seenNetworks.clear(); + + const QDBusReply> watcher_reply = *watcher; + if (!watcher_reply.isValid()) { + qCritical() << "Failed to refresh"; + watcher->deleteLater(); + return; + } + + for (const QDBusObjectPath &path : watcher_reply.value()) { + QDBusReply reply = call(path.path(), NM_DBUS_INTERFACE_PROPERTIES, "GetAll", NM_DBUS_INTERFACE_ACCESS_POINT); + if (!reply.isValid()) { + qCritical() << "Failed to retrieve properties for path:" << path.path(); + continue; + } + + auto properties = reply.value(); + const QByteArray ssid = properties["Ssid"].toByteArray(); + if (ssid.isEmpty()) continue; + + // May be multiple access points for each SSID. + // Use first for ssid and security type, then update connected status and strength using all + if (!seenNetworks.contains(ssid)) { + seenNetworks[ssid] = {ssid, 0U, ConnectedType::DISCONNECTED, getSecurityType(properties)}; + } + + if (path.path() == activeAp) { + seenNetworks[ssid].connected = (ssid == connecting_to_network) ? ConnectedType::CONNECTING : ConnectedType::CONNECTED; + } + + uint32_t strength = properties["Strength"].toUInt(); + if (seenNetworks[ssid].strength < strength) { + seenNetworks[ssid].strength = strength; + } + } + + emit refreshSignal(); + watcher->deleteLater(); +} + +QString WifiManager::getIp4Address() { + if (raw_adapter_state != NM_DEVICE_STATE_ACTIVATED) return ""; + + for (const auto &p : getActiveConnections()) { + QString type = call(p.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type"); + if (type == "802-11-wireless") { + auto ip4config = call(p.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Ip4Config"); + const auto &arr = call(ip4config.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_IP4_CONFIG, "AddressData"); + QVariantMap path; + arr.beginArray(); + while (!arr.atEnd()) { + arr >> path; + arr.endArray(); + return path.value("address").value(); + } + arr.endArray(); + } + } + return ""; +} + +SecurityType WifiManager::getSecurityType(const QVariantMap &properties) { + int sflag = properties["Flags"].toUInt(); + int wpaflag = properties["WpaFlags"].toUInt(); + int rsnflag = properties["RsnFlags"].toUInt(); + int wpa_props = wpaflag | rsnflag; + + // obtained by looking at flags of networks in the office as reported by an Android phone + const int supports_wpa = NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_KEY_MGMT_PSK; + + if ((sflag == NM_802_11_AP_FLAGS_NONE) || ((sflag & NM_802_11_AP_FLAGS_WPS) && !(wpa_props & supports_wpa))) { + return SecurityType::OPEN; + } else if ((sflag & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_props & supports_wpa) && !(wpa_props & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + return SecurityType::WPA; + } else { + LOGW("Unsupported network! sflag: %d, wpaflag: %d, rsnflag: %d", sflag, wpaflag, rsnflag); + return SecurityType::UNSUPPORTED; + } +} + +void WifiManager::connect(const Network &n, const bool is_hidden, const QString &password, const QString &username) { + setCurrentConnecting(n.ssid); + forgetConnection(n.ssid); // Clear all connections that may already exist to the network we are connecting + Connection connection; + connection["connection"]["type"] = "802-11-wireless"; + connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}'); + connection["connection"]["id"] = "openpilot connection " + QString::fromStdString(n.ssid.toStdString()); + connection["connection"]["autoconnect-retries"] = 0; + + connection["802-11-wireless"]["ssid"] = n.ssid; + connection["802-11-wireless"]["hidden"] = is_hidden; + connection["802-11-wireless"]["mode"] = "infrastructure"; + + if (n.security_type == SecurityType::WPA) { + connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk"; + connection["802-11-wireless-security"]["auth-alg"] = "open"; + connection["802-11-wireless-security"]["psk"] = password; + } + + connection["ipv4"]["method"] = "auto"; + connection["ipv4"]["dns-priority"] = 600; + connection["ipv6"]["method"] = "ignore"; + + asyncCall(NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "AddConnection", QVariant::fromValue(connection)); +} + +void WifiManager::deactivateConnectionBySsid(const QString &ssid) { + for (QDBusObjectPath active_connection : getActiveConnections()) { + auto pth = call(active_connection.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "SpecificObject"); + if (!emptyPath(pth.path())) { + QString Ssid = get_property(pth.path(), "Ssid"); + if (Ssid == ssid) { + deactivateConnection(active_connection); + return; + } + } + } +} + +void WifiManager::deactivateConnection(const QDBusObjectPath &path) { + asyncCall(NM_DBUS_PATH, NM_DBUS_INTERFACE, "DeactivateConnection", QVariant::fromValue(path)); +} + +QVector WifiManager::getActiveConnections() { + auto result = call(NM_DBUS_PATH, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE, "ActiveConnections"); + return qdbus_cast>(result); +} + +bool WifiManager::isKnownConnection(const QString &ssid) { + return !getConnectionPath(ssid).path().isEmpty(); +} + +void WifiManager::forgetConnection(const QString &ssid) { + const QDBusObjectPath &path = getConnectionPath(ssid); + if (!path.path().isEmpty()) { + call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Delete"); + } +} + +void WifiManager::setCurrentConnecting(const QString &ssid) { + connecting_to_network = ssid; + for (auto &network : seenNetworks) { + network.connected = (network.ssid == ssid) ? ConnectedType::CONNECTING : ConnectedType::DISCONNECTED; + } + emit refreshSignal(); +} + +uint WifiManager::getAdapterType(const QDBusObjectPath &path) { + return call(path.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_DEVICE, "DeviceType"); +} + +void WifiManager::requestScan() { + if (!adapter.isEmpty()) { + asyncCall(adapter, NM_DBUS_INTERFACE_DEVICE_WIRELESS, "RequestScan", QVariantMap()); + } +} + +QByteArray WifiManager::get_property(const QString &network_path , const QString &property) { + return call(network_path, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACCESS_POINT, property); +} + +QString WifiManager::getAdapter(const uint adapter_type) { + QDBusReply> response = call(NM_DBUS_PATH, NM_DBUS_INTERFACE, "GetDevices"); + for (const QDBusObjectPath &path : response.value()) { + if (getAdapterType(path) == adapter_type) { + return path.path(); + } + } + return ""; +} + +void WifiManager::stateChange(unsigned int new_state, unsigned int previous_state, unsigned int change_reason) { + raw_adapter_state = new_state; + if (new_state == NM_DEVICE_STATE_NEED_AUTH && change_reason == NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT && !connecting_to_network.isEmpty()) { + forgetConnection(connecting_to_network); + emit wrongPassword(connecting_to_network); + } else if (new_state == NM_DEVICE_STATE_ACTIVATED) { + connecting_to_network = ""; + refreshNetworks(); + } +} + +// https://developer.gnome.org/NetworkManager/stable/gdbus-org.freedesktop.NetworkManager.Device.Wireless.html +void WifiManager::propertyChange(const QString &interface, const QVariantMap &props, const QStringList &invalidated_props) { + if (interface == NM_DBUS_INTERFACE_DEVICE_WIRELESS && props.contains("LastScan")) { + refreshNetworks(); + } else if (interface == NM_DBUS_INTERFACE_DEVICE_WIRELESS && props.contains("ActiveAccessPoint")) { + activeAp = props.value("ActiveAccessPoint").value().path(); + } +} + +void WifiManager::deviceAdded(const QDBusObjectPath &path) { + if (getAdapterType(path) == NM_DEVICE_TYPE_WIFI && emptyPath(adapter)) { + adapter = path.path(); + setup(); + } +} + +void WifiManager::connectionRemoved(const QDBusObjectPath &path) { + knownConnections.remove(path); +} + +void WifiManager::newConnection(const QDBusObjectPath &path) { + Connection settings = getConnectionSettings(path); + if (settings.value("connection").value("type") == "802-11-wireless") { + knownConnections[path] = settings.value("802-11-wireless").value("ssid").toString(); + if (knownConnections[path] != tethering_ssid) { + activateWifiConnection(knownConnections[path]); + } + } +} + +QDBusObjectPath WifiManager::getConnectionPath(const QString &ssid) { + return knownConnections.key(ssid); +} + +Connection WifiManager::getConnectionSettings(const QDBusObjectPath &path) { + return QDBusReply(call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "GetSettings")).value(); +} + +void WifiManager::initConnections() { + const QDBusReply> response = call(NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "ListConnections"); + for (const QDBusObjectPath &path : response.value()) { + const Connection settings = getConnectionSettings(path); + if (settings.value("connection").value("type") == "802-11-wireless") { + knownConnections[path] = settings.value("802-11-wireless").value("ssid").toString(); + } else if (settings.value("connection").value("id") == "lte") { + lteConnectionPath = path; + } + } + + if (!isKnownConnection(tethering_ssid)) { + addTetheringConnection(); + } +} + +std::optional WifiManager::activateWifiConnection(const QString &ssid) { + const QDBusObjectPath &path = getConnectionPath(ssid); + if (!path.path().isEmpty()) { + setCurrentConnecting(ssid); + return asyncCall(NM_DBUS_PATH, NM_DBUS_INTERFACE, "ActivateConnection", QVariant::fromValue(path), QVariant::fromValue(QDBusObjectPath(adapter)), QVariant::fromValue(QDBusObjectPath("/"))); + } + return std::nullopt; +} + +void WifiManager::activateModemConnection(const QDBusObjectPath &path) { + QString modem = getAdapter(NM_DEVICE_TYPE_MODEM); + if (!path.path().isEmpty() && !modem.isEmpty()) { + asyncCall(NM_DBUS_PATH, NM_DBUS_INTERFACE, "ActivateConnection", QVariant::fromValue(path), QVariant::fromValue(QDBusObjectPath(modem)), QVariant::fromValue(QDBusObjectPath("/"))); + } +} + +// function matches tici/hardware.py +// FIXME: it can mistakenly show CELL when connected to WIFI +NetworkType WifiManager::currentNetworkType() { + auto primary_conn = call(NM_DBUS_PATH, NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE, "PrimaryConnection"); + auto primary_type = call(primary_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type"); + + if (primary_type == "802-3-ethernet") { + return NetworkType::ETHERNET; + } else if (primary_type == "802-11-wireless" && !isTetheringEnabled()) { + return NetworkType::WIFI; + } else { + for (const QDBusObjectPath &conn : getActiveConnections()) { + auto type = call(conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type"); + if (type == "gsm") { + return NetworkType::CELL; + } + } + } + return NetworkType::NONE; +} + +MeteredType WifiManager::currentNetworkMetered() { + MeteredType metered = MeteredType::UNKNOWN; + for (const auto &active_conn : getActiveConnections()) { + QString type = call(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type"); + if (type == "802-11-wireless") { + QDBusObjectPath conn = call(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Connection"); + if (!conn.path().isEmpty()) { + Connection settings = getConnectionSettings(conn); + int metered_prop = settings.value("connection").value("metered").toInt(); + if (metered_prop == NM_METERED_YES) { + metered = MeteredType::YES; + } else if (metered_prop == NM_METERED_NO) { + metered = MeteredType::NO; + } + } + break; + } + } + return metered; +} + +std::optional WifiManager::setCurrentNetworkMetered(MeteredType metered) { + for (const auto &active_conn : getActiveConnections()) { + QString type = call(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Type"); + if (type == "802-11-wireless") { + if (!isTetheringEnabled()) { + QDBusObjectPath conn = call(active_conn.path(), NM_DBUS_INTERFACE_PROPERTIES, "Get", NM_DBUS_INTERFACE_ACTIVE_CONNECTION, "Connection"); + if (!conn.path().isEmpty()) { + Connection settings = getConnectionSettings(conn); + settings["connection"]["metered"] = static_cast(metered); + return asyncCall(conn.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Update", QVariant::fromValue(settings)); + } + } + } + } + return std::nullopt; +} + +void WifiManager::updateGsmSettings(bool roaming, QString apn, bool metered) { + if (!lteConnectionPath.path().isEmpty()) { + bool changes = false; + bool auto_config = apn.isEmpty(); + Connection settings = getConnectionSettings(lteConnectionPath); + if (settings.value("gsm").value("auto-config").toBool() != auto_config) { + qWarning() << "Changing gsm.auto-config to" << auto_config; + settings["gsm"]["auto-config"] = auto_config; + changes = true; + } + + if (settings.value("gsm").value("apn").toString() != apn) { + qWarning() << "Changing gsm.apn to" << apn; + settings["gsm"]["apn"] = apn; + changes = true; + } + + if (settings.value("gsm").value("home-only").toBool() == roaming) { + qWarning() << "Changing gsm.home-only to" << !roaming; + settings["gsm"]["home-only"] = !roaming; + changes = true; + } + + int meteredInt = metered ? NM_METERED_UNKNOWN : NM_METERED_NO; + if (settings.value("connection").value("metered").toInt() != meteredInt) { + qWarning() << "Changing connection.metered to" << meteredInt; + settings["connection"]["metered"] = meteredInt; + changes = true; + } + + if (changes) { + QDBusPendingCall pending_call = asyncCall(lteConnectionPath.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "UpdateUnsaved", QVariant::fromValue(settings)); // update is temporary + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending_call); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher]() { + deactivateConnection(lteConnectionPath); + activateModemConnection(lteConnectionPath); + watcher->deleteLater(); + }); + } + } +} + +// Functions for tethering +void WifiManager::addTetheringConnection() { + Connection connection; + connection["connection"]["id"] = "Hotspot"; + connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}'); + connection["connection"]["type"] = "802-11-wireless"; + connection["connection"]["interface-name"] = "wlan0"; + connection["connection"]["autoconnect"] = false; + + connection["802-11-wireless"]["band"] = "bg"; + connection["802-11-wireless"]["mode"] = "ap"; + connection["802-11-wireless"]["ssid"] = tethering_ssid.toUtf8(); + + connection["802-11-wireless-security"]["group"] = QStringList("ccmp"); + connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk"; + connection["802-11-wireless-security"]["pairwise"] = QStringList("ccmp"); + connection["802-11-wireless-security"]["proto"] = QStringList("rsn"); + connection["802-11-wireless-security"]["psk"] = defaultTetheringPassword; + + connection["ipv4"]["method"] = "shared"; + QVariantMap address; + address["address"] = "192.168.43.1"; + address["prefix"] = 24u; + connection["ipv4"]["address-data"] = QVariant::fromValue(IpConfig() << address); + connection["ipv4"]["gateway"] = "192.168.43.1"; + connection["ipv4"]["never-default"] = true; + connection["ipv6"]["method"] = "ignore"; + + asyncCall(NM_DBUS_PATH_SETTINGS, NM_DBUS_INTERFACE_SETTINGS, "AddConnection", QVariant::fromValue(connection)); +} + +void WifiManager::tetheringActivated(QDBusPendingCallWatcher *call) { + if (!ipv4_forward) { + QTimer::singleShot(5000, this, [=] { + qWarning() << "net.ipv4.ip_forward = 0"; + std::system("sudo sysctl net.ipv4.ip_forward=0"); + }); + } + call->deleteLater(); + tethering_on = true; +} + +void WifiManager::setTetheringEnabled(bool enabled) { + if (enabled) { + auto pending_call = activateWifiConnection(tethering_ssid); + + if (pending_call) { + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(*pending_call); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &WifiManager::tetheringActivated); + } + + } else { + deactivateConnectionBySsid(tethering_ssid); + tethering_on = false; + } +} + +bool WifiManager::isTetheringEnabled() { + if (!emptyPath(activeAp)) { + return get_property(activeAp, "Ssid") == tethering_ssid; + } + return false; +} + +QString WifiManager::getTetheringPassword() { + const QDBusObjectPath &path = getConnectionPath(tethering_ssid); + if (!path.path().isEmpty()) { + QDBusReply> response = call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "GetSecrets", "802-11-wireless-security"); + return response.value().value("802-11-wireless-security").value("psk").toString(); + } + return ""; +} + +void WifiManager::changeTetheringPassword(const QString &newPassword) { + const QDBusObjectPath &path = getConnectionPath(tethering_ssid); + if (!path.path().isEmpty()) { + Connection settings = getConnectionSettings(path); + settings["802-11-wireless-security"]["psk"] = newPassword; + call(path.path(), NM_DBUS_INTERFACE_SETTINGS_CONNECTION, "Update", QVariant::fromValue(settings)); + if (isTetheringEnabled()) { + activateWifiConnection(tethering_ssid); + } + } +} diff --git a/selfdrive/ui/qt/network/wifi_manager.h b/selfdrive/ui/qt/network/wifi_manager.h new file mode 100644 index 0000000000..cab932a388 --- /dev/null +++ b/selfdrive/ui/qt/network/wifi_manager.h @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include + +#include "selfdrive/ui/qt/network/networkmanager.h" + +enum class SecurityType { + OPEN, + WPA, + UNSUPPORTED +}; +enum class ConnectedType { + DISCONNECTED, + CONNECTING, + CONNECTED +}; +enum class NetworkType { + NONE, + WIFI, + CELL, + ETHERNET +}; +enum class MeteredType { + UNKNOWN, + YES, + NO +}; + +typedef QMap Connection; +typedef QVector IpConfig; + +struct Network { + QByteArray ssid; + unsigned int strength; + ConnectedType connected; + SecurityType security_type; +}; +bool compare_by_strength(const Network &a, const Network &b); +inline int strengthLevel(unsigned int strength) { return std::clamp((int)round(strength / 33.), 0, 3); } + +class WifiManager : public QObject { + Q_OBJECT + +public: + QMap seenNetworks; + QMap knownConnections; + QString ipv4_address; + bool tethering_on = false; + bool ipv4_forward = false; + + explicit WifiManager(QObject* parent); + void start(); + void stop(); + void requestScan(); + void forgetConnection(const QString &ssid); + bool isKnownConnection(const QString &ssid); + std::optional activateWifiConnection(const QString &ssid); + NetworkType currentNetworkType(); + MeteredType currentNetworkMetered(); + std::optional setCurrentNetworkMetered(MeteredType metered); + void updateGsmSettings(bool roaming, QString apn, bool metered); + void connect(const Network &ssid, const bool is_hidden = false, const QString &password = {}, const QString &username = {}); + + // Tethering functions + void setTetheringEnabled(bool enabled); + bool isTetheringEnabled(); + void changeTetheringPassword(const QString &newPassword); + QString getTetheringPassword(); + +private: + QString adapter; // Path to network manager wifi-device + QTimer timer; + unsigned int raw_adapter_state = NM_DEVICE_STATE_UNKNOWN; // Connection status https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NMDeviceState + QString connecting_to_network; + QString tethering_ssid; + const QString defaultTetheringPassword = "swagswagcomma"; + QString activeAp; + QDBusObjectPath lteConnectionPath; + + QString getAdapter(const uint = NM_DEVICE_TYPE_WIFI); + uint getAdapterType(const QDBusObjectPath &path); + QString getIp4Address(); + void deactivateConnectionBySsid(const QString &ssid); + void deactivateConnection(const QDBusObjectPath &path); + QVector getActiveConnections(); + QByteArray get_property(const QString &network_path, const QString &property); + SecurityType getSecurityType(const QVariantMap &properties); + QDBusObjectPath getConnectionPath(const QString &ssid); + Connection getConnectionSettings(const QDBusObjectPath &path); + void initConnections(); + void setup(); + void refreshNetworks(); + void activateModemConnection(const QDBusObjectPath &path); + void addTetheringConnection(); + void setCurrentConnecting(const QString &ssid); + +signals: + void wrongPassword(const QString &ssid); + void refreshSignal(); + +private slots: + void stateChange(unsigned int new_state, unsigned int previous_state, unsigned int change_reason); + void propertyChange(const QString &interface, const QVariantMap &props, const QStringList &invalidated_props); + void deviceAdded(const QDBusObjectPath &path); + void connectionRemoved(const QDBusObjectPath &path); + void newConnection(const QDBusObjectPath &path); + void refreshFinished(QDBusPendingCallWatcher *call); + void tetheringActivated(QDBusPendingCallWatcher *call); +}; diff --git a/selfdrive/ui/qt/offroad/developer_panel.cc b/selfdrive/ui/qt/offroad/developer_panel.cc new file mode 100644 index 0000000000..a095228da2 --- /dev/null +++ b/selfdrive/ui/qt/offroad/developer_panel.cc @@ -0,0 +1,95 @@ +#include "selfdrive/ui/qt/offroad/developer_panel.h" +#include "selfdrive/ui/qt/widgets/ssh_keys.h" +#include "selfdrive/ui/qt/widgets/controls.h" + +DeveloperPanel::DeveloperPanel(SettingsWindow *parent) : ListWidget(parent) { + adbToggle = new ParamControl("AdbEnabled", tr("Enable ADB"), + tr("ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info."), ""); + addItem(adbToggle); + + // SSH keys + addItem(new SshToggle()); + addItem(new SshControl()); + + joystickToggle = new ParamControl("JoystickDebugMode", tr("Joystick Debug Mode"), "", ""); + QObject::connect(joystickToggle, &ParamControl::toggleFlipped, [=](bool state) { + params.putBool("LongitudinalManeuverMode", false); + longManeuverToggle->refresh(); + }); + addItem(joystickToggle); + + longManeuverToggle = new ParamControl("LongitudinalManeuverMode", tr("Longitudinal Maneuver Mode"), "", ""); + QObject::connect(longManeuverToggle, &ParamControl::toggleFlipped, [=](bool state) { + params.putBool("JoystickDebugMode", false); + joystickToggle->refresh(); + }); + addItem(longManeuverToggle); + + experimentalLongitudinalToggle = new ParamControl( + "AlphaLongitudinalEnabled", + tr("openpilot Longitudinal Control (Alpha)"), + QString("%1

    %2") + .arg(tr("WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB).")) + .arg(tr("On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. " + "Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha.")), + "" + ); + experimentalLongitudinalToggle->setConfirmation(true, false); + QObject::connect(experimentalLongitudinalToggle, &ParamControl::toggleFlipped, [=]() { + updateToggles(offroad); + }); + addItem(experimentalLongitudinalToggle); + + // Joystick and longitudinal maneuvers should be hidden on release branches + is_release = params.getBool("IsReleaseBranch"); + + // Toggles should be not available to change in onroad state + QObject::connect(uiState(), &UIState::offroadTransition, this, &DeveloperPanel::updateToggles); +} + +void DeveloperPanel::updateToggles(bool _offroad) { + for (auto btn : findChildren()) { + btn->setVisible(!is_release); + + /* + * experimentalLongitudinalToggle should be toggelable when: + * - visible, and + * - during onroad & offroad states + */ + if (btn != experimentalLongitudinalToggle) { + btn->setEnabled(_offroad); + } + } + + // longManeuverToggle and experimentalLongitudinalToggle should not be toggleable if the car does not have longitudinal control + auto cp_bytes = params.get("CarParamsPersistent"); + if (!cp_bytes.empty()) { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + cereal::CarParams::Reader CP = cmsg.getRoot(); + + if (!CP.getAlphaLongitudinalAvailable() || is_release) { + params.remove("AlphaLongitudinalEnabled"); + experimentalLongitudinalToggle->setEnabled(false); + } + + /* + * experimentalLongitudinalToggle should be visible when: + * - is not a release branch, and + * - the car supports experimental longitudinal control (alpha) + */ + experimentalLongitudinalToggle->setVisible(CP.getAlphaLongitudinalAvailable() && !is_release); + + longManeuverToggle->setEnabled(hasLongitudinalControl(CP) && _offroad); + } else { + longManeuverToggle->setEnabled(false); + experimentalLongitudinalToggle->setVisible(false); + } + experimentalLongitudinalToggle->refresh(); + + offroad = _offroad; +} + +void DeveloperPanel::showEvent(QShowEvent *event) { + updateToggles(offroad); +} diff --git a/selfdrive/ui/qt/offroad/developer_panel.h b/selfdrive/ui/qt/offroad/developer_panel.h new file mode 100644 index 0000000000..c73421b185 --- /dev/null +++ b/selfdrive/ui/qt/offroad/developer_panel.h @@ -0,0 +1,22 @@ +#pragma once + +#include "selfdrive/ui/qt/offroad/settings.h" + +class DeveloperPanel : public ListWidget { + Q_OBJECT +public: + explicit DeveloperPanel(SettingsWindow *parent); + void showEvent(QShowEvent *event) override; + +private: + Params params; + ParamControl* adbToggle; + ParamControl* joystickToggle; + ParamControl* longManeuverToggle; + ParamControl* experimentalLongitudinalToggle; + bool is_release; + bool offroad = false; + +private slots: + void updateToggles(bool _offroad); +}; diff --git a/selfdrive/ui/qt/offroad/driverview.cc b/selfdrive/ui/qt/offroad/driverview.cc new file mode 100644 index 0000000000..9010227f18 --- /dev/null +++ b/selfdrive/ui/qt/offroad/driverview.cc @@ -0,0 +1,82 @@ +#include "selfdrive/ui/qt/offroad/driverview.h" + +#include +#include + +#include "selfdrive/ui/qt/util.h" + +DriverViewWindow::DriverViewWindow(QWidget* parent) : CameraWidget("camerad", VISION_STREAM_DRIVER, parent) { + QObject::connect(this, &CameraWidget::clicked, this, &DriverViewWindow::done); + QObject::connect(device(), &Device::interactiveTimeout, this, [this]() { + if (isVisible()) { + emit done(); + } + }); +} + +void DriverViewWindow::showEvent(QShowEvent* event) { + params.putBool("IsDriverViewEnabled", true); + device()->resetInteractiveTimeout(60); + CameraWidget::showEvent(event); +} + +void DriverViewWindow::hideEvent(QHideEvent* event) { + params.putBool("IsDriverViewEnabled", false); + stopVipcThread(); + CameraWidget::hideEvent(event); +} + +void DriverViewWindow::paintGL() { + CameraWidget::paintGL(); + + std::lock_guard lk(frame_lock); + QPainter p(this); + // startup msg + if (frames.empty()) { + p.setPen(Qt::white); + p.setRenderHint(QPainter::TextAntialiasing); + p.setFont(InterFont(100, QFont::Bold)); + p.drawText(geometry(), Qt::AlignCenter, tr("camera starting")); + return; + } + + const auto &sm = *(uiState()->sm); + cereal::DriverStateV2::Reader driver_state = sm["driverStateV2"].getDriverStateV2(); + bool is_rhd = driver_state.getWheelOnRightProb() > 0.5; + auto driver_data = is_rhd ? driver_state.getRightDriverData() : driver_state.getLeftDriverData(); + + bool face_detected = driver_data.getFaceProb() > 0.7; + if (face_detected) { + auto fxy_list = driver_data.getFacePosition(); + auto std_list = driver_data.getFaceOrientationStd(); + float face_x = fxy_list[0]; + float face_y = fxy_list[1]; + float face_std = std::max(std_list[0], std_list[1]); + + float alpha = 0.7; + if (face_std > 0.15) { + alpha = std::max(0.7 - (face_std-0.15)*3.5, 0.0); + } + const int box_size = 220; + // use approx instead of distort_points + int fbox_x = 1080.0 - 1714.0 * face_x; + int fbox_y = -135.0 + (504.0 + std::abs(face_x)*112.0) + (1205.0 - std::abs(face_x)*724.0) * face_y; + p.setPen(QPen(QColor(255, 255, 255, alpha * 255), 10)); + p.drawRoundedRect(fbox_x - box_size / 2, fbox_y - box_size / 2, box_size, box_size, 35.0, 35.0); + } + + driver_monitor.updateState(*uiState()); + driver_monitor.draw(p, rect()); +} + +mat4 DriverViewWindow::calcFrameMatrix() { + const float driver_view_ratio = 2.0; + const float yscale = stream_height * driver_view_ratio / stream_width; + const float xscale = yscale * glHeight() / glWidth() * stream_width / stream_height; + return mat4{{ + xscale, 0.0, 0.0, 0.0, + 0.0, yscale, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }}; +} diff --git a/selfdrive/ui/qt/offroad/driverview.h b/selfdrive/ui/qt/offroad/driverview.h new file mode 100644 index 0000000000..f6eb752fe6 --- /dev/null +++ b/selfdrive/ui/qt/offroad/driverview.h @@ -0,0 +1,23 @@ +#pragma once + +#include "selfdrive/ui/qt/widgets/cameraview.h" +#include "selfdrive/ui/qt/onroad/driver_monitoring.h" + +class DriverViewWindow : public CameraWidget { + Q_OBJECT + +public: + explicit DriverViewWindow(QWidget *parent); + +signals: + void done(); + +protected: + mat4 calcFrameMatrix() override; + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + void paintGL() override; + + Params params; + DriverMonitorRenderer driver_monitor; +}; diff --git a/selfdrive/ui/qt/offroad/experimental_mode.cc b/selfdrive/ui/qt/offroad/experimental_mode.cc new file mode 100644 index 0000000000..e255073f39 --- /dev/null +++ b/selfdrive/ui/qt/offroad/experimental_mode.cc @@ -0,0 +1,76 @@ +#include "selfdrive/ui/qt/offroad/experimental_mode.h" + +#include +#include +#include +#include +#include + +#include "selfdrive/ui/ui.h" + +ExperimentalModeButton::ExperimentalModeButton(QWidget *parent) : QPushButton(parent) { + chill_pixmap = QPixmap("../assets/icons/couch.svg").scaledToWidth(img_width, Qt::SmoothTransformation); + experimental_pixmap = QPixmap("../assets/icons/experimental_grey.svg").scaledToWidth(img_width, Qt::SmoothTransformation); + + // go to toggles and expand experimental mode description + connect(this, &QPushButton::clicked, [=]() { emit openSettings(2, "ExperimentalMode"); }); + + setFixedHeight(125); + QHBoxLayout *main_layout = new QHBoxLayout; + main_layout->setContentsMargins(horizontal_padding, 0, horizontal_padding, 0); + + mode_label = new QLabel; + mode_icon = new QLabel; + mode_icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + + main_layout->addWidget(mode_label, 1, Qt::AlignLeft); + main_layout->addWidget(mode_icon, 0, Qt::AlignRight); + + setLayout(main_layout); + + setStyleSheet(R"( + QPushButton { + border: none; + } + + QLabel { + font-size: 45px; + font-weight: 300; + text-align: left; + font-family: JetBrainsMono; + color: #000000; + } + )"); +} + +void ExperimentalModeButton::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + + QPainterPath path; + path.addRoundedRect(rect(), 10, 10); + + // gradient + bool pressed = isDown(); + QLinearGradient gradient(rect().left(), 0, rect().right(), 0); + if (experimental_mode) { + gradient.setColorAt(0, QColor(255, 155, 63, pressed ? 0xcc : 0xff)); + gradient.setColorAt(1, QColor(219, 56, 34, pressed ? 0xcc : 0xff)); + } else { + gradient.setColorAt(0, QColor(20, 255, 171, pressed ? 0xcc : 0xff)); + gradient.setColorAt(1, QColor(35, 149, 255, pressed ? 0xcc : 0xff)); + } + p.fillPath(path, gradient); + + // vertical line + p.setPen(QPen(QColor(0, 0, 0, 0x4d), 3, Qt::SolidLine)); + int line_x = rect().right() - img_width - (2 * horizontal_padding); + p.drawLine(line_x, rect().bottom(), line_x, rect().top()); +} + +void ExperimentalModeButton::showEvent(QShowEvent *event) { + experimental_mode = params.getBool("ExperimentalMode"); + mode_icon->setPixmap(experimental_mode ? experimental_pixmap : chill_pixmap); + mode_label->setText(experimental_mode ? tr("EXPERIMENTAL MODE ON") : tr("CHILL MODE ON")); +} diff --git a/selfdrive/ui/qt/offroad/experimental_mode.h b/selfdrive/ui/qt/offroad/experimental_mode.h new file mode 100644 index 0000000000..bfb7638bbe --- /dev/null +++ b/selfdrive/ui/qt/offroad/experimental_mode.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "common/params.h" + +class ExperimentalModeButton : public QPushButton { + Q_OBJECT + +public: + explicit ExperimentalModeButton(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString &toggle = ""); + +private: + void showEvent(QShowEvent *event) override; + + Params params; + bool experimental_mode; + int img_width = 100; + int horizontal_padding = 30; + QPixmap experimental_pixmap; + QPixmap chill_pixmap; + QLabel *mode_label; + QLabel *mode_icon; + +protected: + void paintEvent(QPaintEvent *event) override; +}; diff --git a/selfdrive/ui/qt/offroad/firehose.cc b/selfdrive/ui/qt/offroad/firehose.cc new file mode 100644 index 0000000000..aa158b4c7b --- /dev/null +++ b/selfdrive/ui/qt/offroad/firehose.cc @@ -0,0 +1,112 @@ +#include "selfdrive/ui/qt/offroad/firehose.h" +#include "selfdrive/ui/ui.h" +#include "selfdrive/ui/qt/offroad/settings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +FirehosePanel::FirehosePanel(SettingsWindow *parent) : QWidget((QWidget*)parent) { + layout = new QVBoxLayout(this); + layout->setContentsMargins(40, 40, 40, 40); + layout->setSpacing(20); + + // header + QLabel *title = new QLabel(tr("Firehose Mode")); + title->setStyleSheet("font-size: 100px; font-weight: 500; font-family: 'Noto Color Emoji';"); + layout->addWidget(title, 0, Qt::AlignCenter); + + // Create a container for the content + QFrame *content = new QFrame(); + content->setStyleSheet("background-color: #292929; border-radius: 15px; padding: 20px;"); + QVBoxLayout *content_layout = new QVBoxLayout(content); + content_layout->setSpacing(20); + + // Top description + QLabel *description = new QLabel(tr("openpilot learns to drive by watching humans, like you, drive.\n\nFirehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode.")); + description->setStyleSheet("font-size: 45px; padding-bottom: 20px;"); + description->setWordWrap(true); + content_layout->addWidget(description); + + // Add a separator + QFrame *line = new QFrame(); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + line->setStyleSheet("background-color: #444444; margin-top: 5px; margin-bottom: 5px;"); + content_layout->addWidget(line); + + toggle_label = new QLabel(tr("Firehose Mode: ACTIVE")); + toggle_label->setStyleSheet("font-size: 60px; font-weight: bold; color: white;"); + content_layout->addWidget(toggle_label); + + // Add contribution label + contribution_label = new QLabel(); + contribution_label->setStyleSheet("font-size: 52px; margin-top: 10px; margin-bottom: 10px;"); + contribution_label->setWordWrap(true); + contribution_label->hide(); + content_layout->addWidget(contribution_label); + + // Add a separator before detailed instructions + QFrame *line2 = new QFrame(); + line2->setFrameShape(QFrame::HLine); + line2->setFrameShadow(QFrame::Sunken); + line2->setStyleSheet("background-color: #444444; margin-top: 10px; margin-bottom: 10px;"); + content_layout->addWidget(line2); + + // Detailed instructions at the bottom + detailed_instructions = new QLabel(tr( + "For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.
    " + "
    " + "Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.
    " + "

    " + "Frequently Asked Questions

    " + "Does it matter how or where I drive? Nope, just drive as you normally would.

    " + "Do all of my segments get pulled in Firehose Mode? No, we selectively pull a subset of your segments.

    " + "What's a good USB-C adapter? Any fast phone or laptop charger should be fine.

    " + "Does it matter which software I run? Yes, only upstream openpilot (and particular forks) are able to be used for training." + )); + detailed_instructions->setStyleSheet("font-size: 40px; color: #E4E4E4;"); + detailed_instructions->setWordWrap(true); + content_layout->addWidget(detailed_instructions); + + layout->addWidget(content, 1); + + // Set up the API request for firehose stats + const QString dongle_id = QString::fromStdString(Params().get("DongleId")); + firehose_stats = new RequestRepeater(this, CommaApi::BASE_URL + "/v1/devices/" + dongle_id + "/firehose_stats", + "ApiCache_FirehoseStats", 30, true); + QObject::connect(firehose_stats, &RequestRepeater::requestDone, [=](const QString &response, bool success) { + if (success) { + QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); + QJsonObject json = doc.object(); + int count = json["firehose"].toInt(); + contribution_label->setText(tr("%n segment(s) of your driving is in the training dataset so far.", "", count)); + contribution_label->show(); + } + }); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &FirehosePanel::refresh); +} + +void FirehosePanel::refresh() { + auto deviceState = (*uiState()->sm)["deviceState"].getDeviceState(); + auto networkType = deviceState.getNetworkType(); + bool networkMetered = deviceState.getNetworkMetered(); + + bool is_active = !networkMetered && (networkType != cereal::DeviceState::NetworkType::NONE); + if (is_active) { + toggle_label->setText(tr("ACTIVE")); + toggle_label->setStyleSheet("font-size: 60px; font-weight: bold; color: #2ecc71;"); + } else { + toggle_label->setText(tr("INACTIVE: connect to an unmetered network")); + toggle_label->setStyleSheet("font-size: 60px;"); + } +} diff --git a/selfdrive/ui/qt/offroad/firehose.h b/selfdrive/ui/qt/offroad/firehose.h new file mode 100644 index 0000000000..9082cb0f99 --- /dev/null +++ b/selfdrive/ui/qt/offroad/firehose.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include "selfdrive/ui/qt/request_repeater.h" + +// Forward declarations +class SettingsWindow; + +class FirehosePanel : public QWidget { + Q_OBJECT +public: + explicit FirehosePanel(SettingsWindow *parent); + +private: + QVBoxLayout *layout; + + QLabel *detailed_instructions; + QLabel *contribution_label; + QLabel *toggle_label; + + RequestRepeater *firehose_stats; + +private slots: + void refresh(); +}; diff --git a/selfdrive/ui/qt/offroad/onboarding.cc b/selfdrive/ui/qt/offroad/onboarding.cc new file mode 100644 index 0000000000..1390566671 --- /dev/null +++ b/selfdrive/ui/qt/offroad/onboarding.cc @@ -0,0 +1,211 @@ +#include "selfdrive/ui/qt/offroad/onboarding.h" + +#include + +#include +#include +#include +#include + +#include "common/util.h" +#include "common/params.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/widgets/input.h" + +TrainingGuide::TrainingGuide(QWidget *parent) : QFrame(parent) { + setAttribute(Qt::WA_OpaquePaintEvent); +} + +void TrainingGuide::mouseReleaseEvent(QMouseEvent *e) { + if (click_timer.elapsed() < 250) { + return; + } + click_timer.restart(); + + auto contains = [this](QRect r, const QPoint &pt) { + if (image.size() != image_raw_size) { + QTransform transform; + transform.translate((width()- image.width()) / 2.0, (height()- image.height()) / 2.0); + transform.scale(image.width() / (float)image_raw_size.width(), image.height() / (float)image_raw_size.height()); + r= transform.mapRect(r); + } + return r.contains(pt); + }; + + if (contains(boundingRect[currentIndex], e->pos())) { + if (currentIndex == 9) { + const QRect yes = QRect(707, 804, 531, 164); + Params().putBool("RecordFront", contains(yes, e->pos())); + } + currentIndex += 1; + } else if (currentIndex == (boundingRect.size() - 2) && contains(boundingRect.last(), e->pos())) { + currentIndex = 0; + } + + if (currentIndex >= (boundingRect.size() - 1)) { + emit completedTraining(); + } else { + update(); + } +} + +void TrainingGuide::showEvent(QShowEvent *event) { + currentIndex = 0; + click_timer.start(); +} + +QImage TrainingGuide::loadImage(int id) { + QImage img(img_path + QString("step%1.png").arg(id)); + image_raw_size = img.size(); + if (image_raw_size != rect().size()) { + img = img.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + return img; +} + +void TrainingGuide::paintEvent(QPaintEvent *event) { + QPainter painter(this); + + QRect bg(0, 0, painter.device()->width(), painter.device()->height()); + painter.fillRect(bg, QColor("#000000")); + + image = loadImage(currentIndex); + QRect rect(image.rect()); + rect.moveCenter(bg.center()); + painter.drawImage(rect.topLeft(), image); + + // progress bar + if (currentIndex > 0 && currentIndex < (boundingRect.size() - 2)) { + const int h = 20; + const int w = (currentIndex / (float)(boundingRect.size() - 2)) * width(); + painter.fillRect(QRect(0, height() - h, w, h), QColor("#465BEA")); + } +} + +void TermsPage::showEvent(QShowEvent *event) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(45, 35, 45, 45); + main_layout->setSpacing(0); + + QVBoxLayout *vlayout = new QVBoxLayout(); + vlayout->setContentsMargins(165, 165, 165, 0); + main_layout->addLayout(vlayout); + + QLabel *title = new QLabel(tr("Welcome to openpilot")); + title->setStyleSheet("font-size: 90px; font-weight: 500;"); + vlayout->addWidget(title, 0, Qt::AlignTop | Qt::AlignLeft); + + vlayout->addSpacing(90); + QLabel *desc = new QLabel(tr("You must accept the Terms and Conditions to use openpilot. Read the latest terms at https://comma.ai/terms before continuing.")); + desc->setWordWrap(true); + desc->setStyleSheet("font-size: 80px; font-weight: 300;"); + vlayout->addWidget(desc, 0); + + vlayout->addStretch(); + + QHBoxLayout* buttons = new QHBoxLayout; + buttons->setMargin(0); + buttons->setSpacing(45); + main_layout->addLayout(buttons); + + QPushButton *decline_btn = new QPushButton(tr("Decline")); + buttons->addWidget(decline_btn); + QObject::connect(decline_btn, &QPushButton::clicked, this, &TermsPage::declinedTerms); + + accept_btn = new QPushButton(tr("Agree")); + accept_btn->setStyleSheet(R"( + QPushButton { + background-color: #465BEA; + } + QPushButton:pressed { + background-color: #3049F4; + } + )"); + buttons->addWidget(accept_btn); + QObject::connect(accept_btn, &QPushButton::clicked, this, &TermsPage::acceptedTerms); +} + +void DeclinePage::showEvent(QShowEvent *event) { + if (layout()) { + return; + } + + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setMargin(45); + main_layout->setSpacing(40); + + QLabel *text = new QLabel(this); + text->setText(tr("You must accept the Terms and Conditions in order to use openpilot.")); + text->setStyleSheet(R"(font-size: 80px; font-weight: 300; margin: 200px;)"); + text->setWordWrap(true); + main_layout->addWidget(text, 0, Qt::AlignCenter); + + QHBoxLayout* buttons = new QHBoxLayout; + buttons->setSpacing(45); + main_layout->addLayout(buttons); + + QPushButton *back_btn = new QPushButton(tr("Back")); + buttons->addWidget(back_btn); + + QObject::connect(back_btn, &QPushButton::clicked, this, &DeclinePage::getBack); + + QPushButton *uninstall_btn = new QPushButton(tr("Decline, uninstall %1").arg(getBrand())); + uninstall_btn->setStyleSheet("background-color: #B73D3D"); + buttons->addWidget(uninstall_btn); + QObject::connect(uninstall_btn, &QPushButton::clicked, [=]() { + Params().putBool("DoUninstall", true); + }); +} + +void OnboardingWindow::updateActiveScreen() { + if (!accepted_terms) { + setCurrentIndex(0); + } else if (!training_done) { + setCurrentIndex(1); + } else { + emit onboardingDone(); + } +} + +OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) { + std::string current_terms_version = params.get("TermsVersion"); + std::string current_training_version = params.get("TrainingVersion"); + accepted_terms = params.get("HasAcceptedTerms") == current_terms_version; + training_done = params.get("CompletedTrainingVersion") == current_training_version; + + TermsPage* terms = new TermsPage(this); + addWidget(terms); + connect(terms, &TermsPage::acceptedTerms, [=]() { + params.put("HasAcceptedTerms", current_terms_version); + accepted_terms = true; + updateActiveScreen(); + }); + connect(terms, &TermsPage::declinedTerms, [=]() { setCurrentIndex(2); }); + + TrainingGuide* tr = new TrainingGuide(this); + addWidget(tr); + connect(tr, &TrainingGuide::completedTraining, [=]() { + training_done = true; + params.put("CompletedTrainingVersion", current_training_version); + updateActiveScreen(); + }); + + DeclinePage* declinePage = new DeclinePage(this); + addWidget(declinePage); + connect(declinePage, &DeclinePage::getBack, [=]() { updateActiveScreen(); }); + + setStyleSheet(R"( + * { + color: white; + background-color: black; + } + QPushButton { + height: 160px; + font-size: 55px; + font-weight: 400; + border-radius: 10px; + background-color: #4F4F4F; + } + )"); + updateActiveScreen(); +} diff --git a/selfdrive/ui/qt/offroad/onboarding.h b/selfdrive/ui/qt/offroad/onboarding.h new file mode 100644 index 0000000000..db229c5fa6 --- /dev/null +++ b/selfdrive/ui/qt/offroad/onboarding.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "common/params.h" +#include "selfdrive/ui/qt/qt_window.h" + +class TrainingGuide : public QFrame { + Q_OBJECT + +public: + explicit TrainingGuide(QWidget *parent = 0); + +private: + void showEvent(QShowEvent *event) override; + void paintEvent(QPaintEvent *event) override; + void mouseReleaseEvent(QMouseEvent* e) override; + QImage loadImage(int id); + + QImage image; + QSize image_raw_size; + int currentIndex = 0; + + // Bounding boxes for each training guide step + const QRect continueBtn = {1840, 0, 320, 1080}; + QVector boundingRect { + QRect(112, 804, 618, 164), + continueBtn, + continueBtn, + QRect(1641, 558, 210, 313), + QRect(1662, 528, 184, 108), + continueBtn, + QRect(1814, 621, 211, 170), + QRect(1350, 0, 497, 755), + QRect(1540, 386, 468, 238), + QRect(112, 804, 1126, 164), + QRect(1598, 199, 316, 333), + continueBtn, + QRect(1364, 90, 796, 990), + continueBtn, + QRect(1593, 114, 318, 853), + QRect(1379, 511, 391, 243), + continueBtn, + continueBtn, + QRect(630, 804, 626, 164), + QRect(108, 804, 426, 164), + }; + + const QString img_path = "../assets/training/"; + QElapsedTimer click_timer; + +signals: + void completedTraining(); +}; + + +class TermsPage : public QFrame { + Q_OBJECT + +public: + explicit TermsPage(QWidget *parent = 0) : QFrame(parent) {} + +private: + void showEvent(QShowEvent *event) override; + + QPushButton *accept_btn; + +signals: + void acceptedTerms(); + void declinedTerms(); +}; + +class DeclinePage : public QFrame { + Q_OBJECT + +public: + explicit DeclinePage(QWidget *parent = 0) : QFrame(parent) {} + +private: + void showEvent(QShowEvent *event) override; + +signals: + void getBack(); +}; + +class OnboardingWindow : public QStackedWidget { + Q_OBJECT + +public: + explicit OnboardingWindow(QWidget *parent = 0); + inline void showTrainingGuide() { setCurrentIndex(1); } + inline bool completed() const { return accepted_terms && training_done; } + +private: + void updateActiveScreen(); + + Params params; + bool accepted_terms = false, training_done = false; + +signals: + void onboardingDone(); +}; diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc new file mode 100644 index 0000000000..96734d69d9 --- /dev/null +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -0,0 +1,537 @@ +#include +#include +#include +#include +#include + +#include + +#include "common/watchdog.h" +#include "common/util.h" +#include "selfdrive/ui/qt/network/networking.h" +#include "selfdrive/ui/qt/offroad/settings.h" +#include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/widgets/prime.h" +#include "selfdrive/ui/qt/widgets/scrollview.h" +#include "selfdrive/ui/qt/offroad/developer_panel.h" +#include "selfdrive/ui/qt/offroad/firehose.h" + +TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) { + // param, title, desc, icon, restart needed + std::vector> toggle_defs{ + { + "OpenpilotEnabledToggle", + tr("Enable openpilot"), + tr("Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature."), + "../assets/icons/chffr_wheel.png", + true, + }, + { + "ExperimentalMode", + tr("Experimental Mode"), + "", + "../assets/icons/experimental_white.svg", + false, + }, + { + "DisengageOnAccelerator", + tr("Disengage on Accelerator Pedal"), + tr("When enabled, pressing the accelerator pedal will disengage openpilot."), + "../assets/icons/disengage_on_accelerator.svg", + false, + }, + { + "IsLdwEnabled", + tr("Enable Lane Departure Warnings"), + tr("Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h)."), + "../assets/icons/warning.png", + false, + }, + { + "AlwaysOnDM", + tr("Always-On Driver Monitoring"), + tr("Enable driver monitoring even when openpilot is not engaged."), + "../assets/icons/monitoring.png", + false, + }, + { + "RecordFront", + tr("Record and Upload Driver Camera"), + tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."), + "../assets/icons/monitoring.png", + true, + }, + { + "RecordAudio", + tr("Record and Upload Microphone Audio"), + tr("Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect."), + "../assets/icons/microphone.png", + true, + }, + { + "IsMetric", + tr("Use Metric System"), + tr("Display speed in km/h instead of mph."), + "../assets/icons/metric.png", + false, + }, + }; + + + std::vector longi_button_texts{tr("Aggressive"), tr("Standard"), tr("Relaxed")}; + long_personality_setting = new ButtonParamControl("LongitudinalPersonality", tr("Driving Personality"), + tr("Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. " + "In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with " + "your steering wheel distance button."), + "../assets/icons/speed_limit.png", + longi_button_texts); + + // set up uiState update for personality setting + QObject::connect(uiState(), &UIState::uiUpdate, this, &TogglesPanel::updateState); + + for (auto &[param, title, desc, icon, needs_restart] : toggle_defs) { + auto toggle = new ParamControl(param, title, desc, icon, this); + + bool locked = params.getBool((param + "Lock").toStdString()); + toggle->setEnabled(!locked); + + if (needs_restart && !locked) { + toggle->setDescription(toggle->getDescription() + tr(" Changing this setting will restart openpilot if the car is powered on.")); + + QObject::connect(uiState(), &UIState::engagedChanged, [toggle](bool engaged) { + toggle->setEnabled(!engaged); + }); + + QObject::connect(toggle, &ParamControl::toggleFlipped, [=](bool state) { + params.putBool("OnroadCycleRequested", true); + }); + } + + addItem(toggle); + toggles[param.toStdString()] = toggle; + + // insert longitudinal personality after NDOG toggle + if (param == "DisengageOnAccelerator") { + addItem(long_personality_setting); + } + } + + // Toggles with confirmation dialogs + toggles["ExperimentalMode"]->setActiveIcon("../assets/icons/experimental.svg"); + toggles["ExperimentalMode"]->setConfirmation(true, true); +} + +void TogglesPanel::updateState(const UIState &s) { + const SubMaster &sm = *(s.sm); + + if (sm.updated("selfdriveState")) { + auto personality = sm["selfdriveState"].getSelfdriveState().getPersonality(); + if (personality != s.scene.personality && s.scene.started && isVisible()) { + long_personality_setting->setCheckedButton(static_cast(personality)); + } + uiState()->scene.personality = personality; + } +} + +void TogglesPanel::expandToggleDescription(const QString ¶m) { + toggles[param.toStdString()]->showDescription(); +} + +void TogglesPanel::scrollToToggle(const QString ¶m) { + if (auto it = toggles.find(param.toStdString()); it != toggles.end()) { + auto scroll_area = qobject_cast(parent()->parent()); + if (scroll_area) { + scroll_area->ensureWidgetVisible(it->second); + } + } +} + +void TogglesPanel::showEvent(QShowEvent *event) { + updateToggles(); +} + +void TogglesPanel::updateToggles() { + auto experimental_mode_toggle = toggles["ExperimentalMode"]; + const QString e2e_description = QString("%1
    " + "

    %2


    " + "%3
    " + "

    %4


    " + "%5
    ") + .arg(tr("openpilot defaults to driving in chill mode. Experimental mode enables alpha-level features that aren't ready for chill mode. Experimental features are listed below:")) + .arg(tr("End-to-End Longitudinal Control")) + .arg(tr("Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. " + "Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; " + "mistakes should be expected.")) + .arg(tr("New Driving Visualization")) + .arg(tr("The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.")); + + const bool is_release = params.getBool("IsReleaseBranch"); + auto cp_bytes = params.get("CarParamsPersistent"); + if (!cp_bytes.empty()) { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(cp_bytes.data(), cp_bytes.size())); + cereal::CarParams::Reader CP = cmsg.getRoot(); + + if (hasLongitudinalControl(CP)) { + // normal description and toggle + experimental_mode_toggle->setEnabled(true); + experimental_mode_toggle->setDescription(e2e_description); + long_personality_setting->setEnabled(true); + } else { + // no long for now + experimental_mode_toggle->setEnabled(false); + long_personality_setting->setEnabled(false); + params.remove("ExperimentalMode"); + + const QString unavailable = tr("Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control."); + + QString long_desc = unavailable + " " + \ + tr("openpilot longitudinal control may come in a future update."); + if (CP.getAlphaLongitudinalAvailable()) { + if (is_release) { + long_desc = unavailable + " " + tr("An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches."); + } else { + long_desc = tr("Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode."); + } + } + experimental_mode_toggle->setDescription("" + long_desc + "

    " + e2e_description); + } + + experimental_mode_toggle->refresh(); + } else { + experimental_mode_toggle->setDescription(e2e_description); + } +} + +DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { + setSpacing(50); + addItem(new LabelControl(tr("Dongle ID"), getDongleId().value_or(tr("N/A")))); + addItem(new LabelControl(tr("Serial"), params.get("HardwareSerial").c_str())); + + pair_device = new ButtonControl(tr("Pair Device"), tr("PAIR"), + tr("Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.")); + connect(pair_device, &ButtonControl::clicked, [=]() { + PairingPopup popup(this); + popup.exec(); + }); + addItem(pair_device); + + // offroad-only buttons + + auto dcamBtn = new ButtonControl(tr("Driver Camera"), tr("PREVIEW"), + tr("Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)")); + connect(dcamBtn, &ButtonControl::clicked, [=]() { emit showDriverView(); }); + addItem(dcamBtn); + + resetCalibBtn = new ButtonControl(tr("Reset Calibration"), tr("RESET"), ""); + connect(resetCalibBtn, &ButtonControl::showDescriptionEvent, this, &DevicePanel::updateCalibDescription); + connect(resetCalibBtn, &ButtonControl::clicked, [&]() { + if (!uiState()->engaged()) { + if (ConfirmationDialog::confirm(tr("Are you sure you want to reset calibration?"), tr("Reset"), this)) { + // Check engaged again in case it changed while the dialog was open + if (!uiState()->engaged()) { + params.remove("CalibrationParams"); + params.remove("LiveTorqueParameters"); + params.remove("LiveParameters"); + params.remove("LiveParametersV2"); + params.remove("LiveDelay"); + params.putBool("OnroadCycleRequested", true); + updateCalibDescription(); + } + } + } else { + ConfirmationDialog::alert(tr("Disengage to Reset Calibration"), this); + } + }); + addItem(resetCalibBtn); + + auto retrainingBtn = new ButtonControl(tr("Review Training Guide"), tr("REVIEW"), tr("Review the rules, features, and limitations of openpilot")); + connect(retrainingBtn, &ButtonControl::clicked, [=]() { + if (ConfirmationDialog::confirm(tr("Are you sure you want to review the training guide?"), tr("Review"), this)) { + emit reviewTrainingGuide(); + } + }); + addItem(retrainingBtn); + + if (Hardware::TICI()) { + auto regulatoryBtn = new ButtonControl(tr("Regulatory"), tr("VIEW"), ""); + connect(regulatoryBtn, &ButtonControl::clicked, [=]() { + const std::string txt = util::read_file("../assets/offroad/fcc.html"); + ConfirmationDialog::rich(QString::fromStdString(txt), this); + }); + addItem(regulatoryBtn); + } + + auto translateBtn = new ButtonControl(tr("Change Language"), tr("CHANGE"), ""); + connect(translateBtn, &ButtonControl::clicked, [=]() { + QMap langs = getSupportedLanguages(); + QString selection = MultiOptionDialog::getSelection(tr("Select a language"), langs.keys(), langs.key(uiState()->language), this); + if (!selection.isEmpty()) { + // put language setting, exit Qt UI, and trigger fast restart + params.put("LanguageSetting", langs[selection].toStdString()); + qApp->exit(18); + watchdog_kick(0); + } + }); + addItem(translateBtn); + + QObject::connect(uiState()->prime_state, &PrimeState::changed, [this] (PrimeState::Type type) { + pair_device->setVisible(type == PrimeState::PRIME_TYPE_UNPAIRED); + }); + QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + for (auto btn : findChildren()) { + if (btn != pair_device && btn != resetCalibBtn) { + btn->setEnabled(offroad); + } + } + }); + + // power buttons + QHBoxLayout *power_layout = new QHBoxLayout(); + power_layout->setSpacing(30); + + QPushButton *reboot_btn = new QPushButton(tr("Reboot")); + reboot_btn->setObjectName("reboot_btn"); + power_layout->addWidget(reboot_btn); + QObject::connect(reboot_btn, &QPushButton::clicked, this, &DevicePanel::reboot); + + QPushButton *poweroff_btn = new QPushButton(tr("Power Off")); + poweroff_btn->setObjectName("poweroff_btn"); + power_layout->addWidget(poweroff_btn); + QObject::connect(poweroff_btn, &QPushButton::clicked, this, &DevicePanel::poweroff); + + if (!Hardware::PC()) { + connect(uiState(), &UIState::offroadTransition, poweroff_btn, &QPushButton::setVisible); + } + + setStyleSheet(R"( + #reboot_btn { height: 120px; border-radius: 15px; background-color: #393939; } + #reboot_btn:pressed { background-color: #4a4a4a; } + #poweroff_btn { height: 120px; border-radius: 15px; background-color: #E22C2C; } + #poweroff_btn:pressed { background-color: #FF2424; } + )"); + addItem(power_layout); +} + +void DevicePanel::updateCalibDescription() { + QString desc = tr("openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down."); + std::string calib_bytes = params.get("CalibrationParams"); + if (!calib_bytes.empty()) { + try { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(calib_bytes.data(), calib_bytes.size())); + auto calib = cmsg.getRoot().getLiveCalibration(); + if (calib.getCalStatus() != cereal::LiveCalibrationData::Status::UNCALIBRATED) { + double pitch = calib.getRpyCalib()[1] * (180 / M_PI); + double yaw = calib.getRpyCalib()[2] * (180 / M_PI); + desc += tr(" Your device is pointed %1° %2 and %3° %4.") + .arg(QString::number(std::abs(pitch), 'g', 1), pitch > 0 ? tr("down") : tr("up"), + QString::number(std::abs(yaw), 'g', 1), yaw > 0 ? tr("left") : tr("right")); + } + } catch (kj::Exception) { + qInfo() << "invalid CalibrationParams"; + } + } + + int lag_perc = 0; + std::string lag_bytes = params.get("LiveDelay"); + if (!lag_bytes.empty()) { + try { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(lag_bytes.data(), lag_bytes.size())); + lag_perc = cmsg.getRoot().getLiveDelay().getCalPerc(); + } catch (kj::Exception) { + qInfo() << "invalid LiveDelay"; + } + } + if (lag_perc < 100) { + desc += tr("\n\nSteering lag calibration is %1% complete.").arg(lag_perc); + } else { + desc += tr("\n\nSteering lag calibration is complete."); + } + + std::string torque_bytes = params.get("LiveTorqueParameters"); + if (!torque_bytes.empty()) { + try { + AlignedBuffer aligned_buf; + capnp::FlatArrayMessageReader cmsg(aligned_buf.align(torque_bytes.data(), torque_bytes.size())); + auto torque = cmsg.getRoot().getLiveTorqueParameters(); + // don't add for non-torque cars + if (torque.getUseParams()) { + int torque_perc = torque.getCalPerc(); + if (torque_perc < 100) { + desc += tr(" Steering torque response calibration is %1% complete.").arg(torque_perc); + } else { + desc += tr(" Steering torque response calibration is complete."); + } + } + } catch (kj::Exception) { + qInfo() << "invalid LiveTorqueParameters"; + } + } + + desc += "\n\n"; + desc += tr("openpilot is continuously calibrating, resetting is rarely required. " + "Resetting calibration will restart openpilot if the car is powered on."); + resetCalibBtn->setDescription(desc); +} + +void DevicePanel::reboot() { + if (!uiState()->engaged()) { + if (ConfirmationDialog::confirm(tr("Are you sure you want to reboot?"), tr("Reboot"), this)) { + // Check engaged again in case it changed while the dialog was open + if (!uiState()->engaged()) { + params.putBool("DoReboot", true); + } + } + } else { + ConfirmationDialog::alert(tr("Disengage to Reboot"), this); + } +} + +void DevicePanel::poweroff() { + if (!uiState()->engaged()) { + if (ConfirmationDialog::confirm(tr("Are you sure you want to power off?"), tr("Power Off"), this)) { + // Check engaged again in case it changed while the dialog was open + if (!uiState()->engaged()) { + params.putBool("DoShutdown", true); + } + } + } else { + ConfirmationDialog::alert(tr("Disengage to Power Off"), this); + } +} + +void SettingsWindow::showEvent(QShowEvent *event) { + setCurrentPanel(0); +} + +void SettingsWindow::setCurrentPanel(int index, const QString ¶m) { + if (!param.isEmpty()) { + // Check if param ends with "Panel" to determine if it's a panel name + if (param.endsWith("Panel")) { + QString panelName = param; + panelName.chop(5); // Remove "Panel" suffix + + // Find the panel by name + for (int i = 0; i < nav_btns->buttons().size(); i++) { + if (nav_btns->buttons()[i]->text() == tr(panelName.toStdString().c_str())) { + index = i; + break; + } + } + } else { + emit expandToggleDescription(param); + emit scrollToToggle(param); + } + } + + panel_widget->setCurrentIndex(index); + nav_btns->buttons()[index]->setChecked(true); +} + +SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) { + + // setup two main layouts + sidebar_widget = new QWidget; + QVBoxLayout *sidebar_layout = new QVBoxLayout(sidebar_widget); + panel_widget = new QStackedWidget(); + + // close button + QPushButton *close_btn = new QPushButton(tr("×")); + close_btn->setStyleSheet(R"( + QPushButton { + font-size: 140px; + padding-bottom: 20px; + border-radius: 100px; + background-color: #292929; + font-weight: 400; + } + QPushButton:pressed { + background-color: #3B3B3B; + } + )"); + close_btn->setFixedSize(200, 200); + sidebar_layout->addSpacing(45); + sidebar_layout->addWidget(close_btn, 0, Qt::AlignCenter); + QObject::connect(close_btn, &QPushButton::clicked, this, &SettingsWindow::closeSettings); + + // setup panels + DevicePanel *device = new DevicePanel(this); + QObject::connect(device, &DevicePanel::reviewTrainingGuide, this, &SettingsWindow::reviewTrainingGuide); + QObject::connect(device, &DevicePanel::showDriverView, this, &SettingsWindow::showDriverView); + + TogglesPanel *toggles = new TogglesPanel(this); + QObject::connect(this, &SettingsWindow::expandToggleDescription, toggles, &TogglesPanel::expandToggleDescription); + QObject::connect(this, &SettingsWindow::scrollToToggle, toggles, &TogglesPanel::scrollToToggle); + + auto networking = new Networking(this); + QObject::connect(uiState()->prime_state, &PrimeState::changed, networking, &Networking::setPrimeType); + + QList> panels = { + {tr("Device"), device}, + {tr("Network"), networking}, + {tr("Toggles"), toggles}, + {tr("Software"), new SoftwarePanel(this)}, + {tr("Firehose"), new FirehosePanel(this)}, + {tr("Developer"), new DeveloperPanel(this)}, + }; + + nav_btns = new QButtonGroup(this); + for (auto &[name, panel] : panels) { + QPushButton *btn = new QPushButton(name); + btn->setCheckable(true); + btn->setChecked(nav_btns->buttons().size() == 0); + btn->setStyleSheet(R"( + QPushButton { + color: grey; + border: none; + background: none; + font-size: 65px; + font-weight: 500; + } + QPushButton:checked { + color: white; + } + QPushButton:pressed { + color: #ADADAD; + } + )"); + btn->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + nav_btns->addButton(btn); + sidebar_layout->addWidget(btn, 0, Qt::AlignRight); + + const int lr_margin = name != tr("Network") ? 50 : 0; // Network panel handles its own margins + panel->setContentsMargins(lr_margin, 25, lr_margin, 25); + + ScrollView *panel_frame = new ScrollView(panel, this); + panel_widget->addWidget(panel_frame); + + QObject::connect(btn, &QPushButton::clicked, [=, w = panel_frame]() { + btn->setChecked(true); + panel_widget->setCurrentWidget(w); + }); + } + sidebar_layout->setContentsMargins(50, 50, 100, 50); + + // main settings layout, sidebar + main panel + QHBoxLayout *main_layout = new QHBoxLayout(this); + + sidebar_widget->setFixedWidth(500); + main_layout->addWidget(sidebar_widget); + main_layout->addWidget(panel_widget); + + setStyleSheet(R"( + * { + color: white; + font-size: 50px; + } + SettingsWindow { + background-color: black; + } + QStackedWidget, ScrollView { + background-color: #292929; + border-radius: 30px; + } + )"); +} diff --git a/selfdrive/ui/qt/offroad/settings.h b/selfdrive/ui/qt/offroad/settings.h new file mode 100644 index 0000000000..d52cf16bb7 --- /dev/null +++ b/selfdrive/ui/qt/offroad/settings.h @@ -0,0 +1,106 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "selfdrive/ui/ui.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/widgets/controls.h" + +// ********** settings window + top-level panels ********** +class SettingsWindow : public QFrame { + Q_OBJECT + +public: + explicit SettingsWindow(QWidget *parent = 0); + void setCurrentPanel(int index, const QString ¶m = ""); + +protected: + void showEvent(QShowEvent *event) override; + +signals: + void closeSettings(); + void reviewTrainingGuide(); + void showDriverView(); + void expandToggleDescription(const QString ¶m); + void scrollToToggle(const QString ¶m); + +private: + QPushButton *sidebar_alert_widget; + QWidget *sidebar_widget; + QButtonGroup *nav_btns; + QStackedWidget *panel_widget; +}; + +class DevicePanel : public ListWidget { + Q_OBJECT +public: + explicit DevicePanel(SettingsWindow *parent); + +signals: + void reviewTrainingGuide(); + void showDriverView(); + +private slots: + void poweroff(); + void reboot(); + void updateCalibDescription(); + +private: + Params params; + ButtonControl *pair_device; + ButtonControl *resetCalibBtn; +}; + +class TogglesPanel : public ListWidget { + Q_OBJECT +public: + explicit TogglesPanel(SettingsWindow *parent); + void showEvent(QShowEvent *event) override; + +public slots: + void expandToggleDescription(const QString ¶m); + void scrollToToggle(const QString ¶m); + +private slots: + void updateState(const UIState &s); + +private: + Params params; + std::map toggles; + ButtonParamControl *long_personality_setting; + + void updateToggles(); +}; + +class SoftwarePanel : public ListWidget { + Q_OBJECT +public: + explicit SoftwarePanel(QWidget* parent = nullptr); + +private: + void showEvent(QShowEvent *event) override; + void updateLabels(); + void checkForUpdates(); + + bool is_onroad = false; + + QLabel *onroadLbl; + LabelControl *versionLbl; + ButtonControl *installBtn; + ButtonControl *downloadBtn; + ButtonControl *targetBranchBtn; + + Params params; + ParamWatcher *fs_watch; +}; + +// Forward declaration +class FirehosePanel; diff --git a/selfdrive/ui/qt/offroad/software_settings.cc b/selfdrive/ui/qt/offroad/software_settings.cc new file mode 100644 index 0000000000..9bc3fad3c9 --- /dev/null +++ b/selfdrive/ui/qt/offroad/software_settings.cc @@ -0,0 +1,156 @@ +#include "selfdrive/ui/qt/offroad/settings.h" + +#include +#include +#include + +#include +#include + +#include "common/params.h" +#include "common/util.h" +#include "selfdrive/ui/ui.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/widgets/controls.h" +#include "selfdrive/ui/qt/widgets/input.h" +#include "system/hardware/hw.h" + + +void SoftwarePanel::checkForUpdates() { + std::system("pkill -SIGUSR1 -f system.updated.updated"); +} + +SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent) { + onroadLbl = new QLabel(tr("Updates are only downloaded while the car is off.")); + onroadLbl->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left; padding-top: 30px; padding-bottom: 30px;"); + addItem(onroadLbl); + + // current version + versionLbl = new LabelControl(tr("Current Version"), ""); + addItem(versionLbl); + + // download update btn + downloadBtn = new ButtonControl(tr("Download"), tr("CHECK")); + connect(downloadBtn, &ButtonControl::clicked, [=]() { + downloadBtn->setEnabled(false); + if (downloadBtn->text() == tr("CHECK")) { + checkForUpdates(); + } else { + std::system("pkill -SIGHUP -f system.updated.updated"); + } + }); + addItem(downloadBtn); + + // install update btn + installBtn = new ButtonControl(tr("Install Update"), tr("INSTALL")); + connect(installBtn, &ButtonControl::clicked, [=]() { + installBtn->setEnabled(false); + params.putBool("DoReboot", true); + }); + addItem(installBtn); + + // branch selecting + targetBranchBtn = new ButtonControl(tr("Target Branch"), tr("SELECT")); + connect(targetBranchBtn, &ButtonControl::clicked, [=]() { + auto current = params.get("GitBranch"); + QStringList branches = QString::fromStdString(params.get("UpdaterAvailableBranches")).split(","); + for (QString b : {current.c_str(), "devel-staging", "devel", "nightly", "nightly-dev", "master"}) { + auto i = branches.indexOf(b); + if (i >= 0) { + branches.removeAt(i); + branches.insert(0, b); + } + } + + QString cur = QString::fromStdString(params.get("UpdaterTargetBranch")); + QString selection = MultiOptionDialog::getSelection(tr("Select a branch"), branches, cur, this); + if (!selection.isEmpty()) { + params.put("UpdaterTargetBranch", selection.toStdString()); + targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch"))); + checkForUpdates(); + } + }); + if (!params.getBool("IsTestedBranch")) { + addItem(targetBranchBtn); + } + + // uninstall button + auto uninstallBtn = new ButtonControl(tr("Uninstall %1").arg(getBrand()), tr("UNINSTALL")); + connect(uninstallBtn, &ButtonControl::clicked, [&]() { + if (ConfirmationDialog::confirm(tr("Are you sure you want to uninstall?"), tr("Uninstall"), this)) { + params.putBool("DoUninstall", true); + } + }); + addItem(uninstallBtn); + + fs_watch = new ParamWatcher(this); + QObject::connect(fs_watch, &ParamWatcher::paramChanged, [=](const QString ¶m_name, const QString ¶m_value) { + updateLabels(); + }); + + connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + is_onroad = !offroad; + updateLabels(); + }); + + updateLabels(); +} + +void SoftwarePanel::showEvent(QShowEvent *event) { + // nice for testing on PC + installBtn->setEnabled(true); + + updateLabels(); +} + +void SoftwarePanel::updateLabels() { + // add these back in case the files got removed + fs_watch->addParam("LastUpdateTime"); + fs_watch->addParam("UpdateFailedCount"); + fs_watch->addParam("UpdaterState"); + fs_watch->addParam("UpdateAvailable"); + + if (!isVisible()) { + return; + } + + // updater only runs offroad + onroadLbl->setVisible(is_onroad); + downloadBtn->setVisible(!is_onroad); + + // download update + QString updater_state = QString::fromStdString(params.get("UpdaterState")); + bool failed = std::atoi(params.get("UpdateFailedCount").c_str()) > 0; + if (updater_state != "idle") { + downloadBtn->setEnabled(false); + downloadBtn->setValue(updater_state); + } else { + if (failed) { + downloadBtn->setText(tr("CHECK")); + downloadBtn->setValue(tr("failed to check for update")); + } else if (params.getBool("UpdaterFetchAvailable")) { + downloadBtn->setText(tr("DOWNLOAD")); + downloadBtn->setValue(tr("update available")); + } else { + QString lastUpdate = tr("never"); + auto tm = params.get("LastUpdateTime"); + if (!tm.empty()) { + lastUpdate = timeAgo(QDateTime::fromString(QString::fromStdString(tm + "Z"), Qt::ISODate)); + } + downloadBtn->setText(tr("CHECK")); + downloadBtn->setValue(tr("up to date, last checked %1").arg(lastUpdate)); + } + downloadBtn->setEnabled(true); + } + targetBranchBtn->setValue(QString::fromStdString(params.get("UpdaterTargetBranch"))); + + // current + new versions + versionLbl->setText(QString::fromStdString(params.get("UpdaterCurrentDescription"))); + versionLbl->setDescription(QString::fromStdString(params.get("UpdaterCurrentReleaseNotes"))); + + installBtn->setVisible(!is_onroad && params.getBool("UpdateAvailable")); + installBtn->setValue(QString::fromStdString(params.get("UpdaterNewDescription"))); + installBtn->setDescription(QString::fromStdString(params.get("UpdaterNewReleaseNotes"))); + + update(); +} diff --git a/selfdrive/ui/qt/onroad/alerts.cc b/selfdrive/ui/qt/onroad/alerts.cc new file mode 100644 index 0000000000..0236e20f16 --- /dev/null +++ b/selfdrive/ui/qt/onroad/alerts.cc @@ -0,0 +1,112 @@ +#include "selfdrive/ui/qt/onroad/alerts.h" + +#include +#include + +#include "selfdrive/ui/qt/util.h" + +void OnroadAlerts::updateState(const UIState &s) { + Alert a = getAlert(*(s.sm), s.scene.started_frame); + if (!alert.equal(a)) { + alert = a; + update(); + } +} + +void OnroadAlerts::clear() { + alert = {}; + update(); +} + +OnroadAlerts::Alert OnroadAlerts::getAlert(const SubMaster &sm, uint64_t started_frame) { + const cereal::SelfdriveState::Reader &ss = sm["selfdriveState"].getSelfdriveState(); + const uint64_t selfdrive_frame = sm.rcv_frame("selfdriveState"); + + Alert a = {}; + if (selfdrive_frame >= started_frame) { // Don't get old alert. + a = {ss.getAlertText1().cStr(), ss.getAlertText2().cStr(), + ss.getAlertType().cStr(), ss.getAlertSize(), ss.getAlertStatus()}; + } + + if (!sm.updated("selfdriveState") && (sm.frame - started_frame) > 5 * UI_FREQ) { + const int SELFDRIVE_STATE_TIMEOUT = 5; + const int ss_missing = (nanos_since_boot() - sm.rcv_time("selfdriveState")) / 1e9; + + // Handle selfdrive timeout + if (selfdrive_frame < started_frame) { + // car is started, but selfdriveState hasn't been seen at all + a = {tr("openpilot Unavailable"), tr("Waiting to start"), + "selfdriveWaiting", cereal::SelfdriveState::AlertSize::MID, + cereal::SelfdriveState::AlertStatus::NORMAL}; + } else if (ss_missing > SELFDRIVE_STATE_TIMEOUT && !Hardware::PC()) { + // car is started, but selfdrive is lagging or died + if (ss.getEnabled() && (ss_missing - SELFDRIVE_STATE_TIMEOUT) < 10) { + a = {tr("TAKE CONTROL IMMEDIATELY"), tr("System Unresponsive"), + "selfdriveUnresponsive", cereal::SelfdriveState::AlertSize::FULL, + cereal::SelfdriveState::AlertStatus::CRITICAL}; + } else { + a = {tr("System Unresponsive"), tr("Reboot Device"), + "selfdriveUnresponsivePermanent", cereal::SelfdriveState::AlertSize::MID, + cereal::SelfdriveState::AlertStatus::NORMAL}; + } + } + } + return a; +} + +void OnroadAlerts::paintEvent(QPaintEvent *event) { + if (alert.size == cereal::SelfdriveState::AlertSize::NONE) { + return; + } + static std::map alert_heights = { + {cereal::SelfdriveState::AlertSize::SMALL, 271}, + {cereal::SelfdriveState::AlertSize::MID, 420}, + {cereal::SelfdriveState::AlertSize::FULL, height()}, + }; + int h = alert_heights[alert.size]; + + int margin = 40; + int radius = 30; + if (alert.size == cereal::SelfdriveState::AlertSize::FULL) { + margin = 0; + radius = 0; + } + QRect r = QRect(0 + margin, height() - h + margin, width() - margin*2, h - margin*2); + + QPainter p(this); + + // draw background + gradient + p.setPen(Qt::NoPen); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + p.setBrush(QBrush(alert_colors[alert.status])); + p.drawRoundedRect(r, radius, radius); + + QLinearGradient g(0, r.y(), 0, r.bottom()); + g.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.05)); + g.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0.35)); + + p.setCompositionMode(QPainter::CompositionMode_DestinationOver); + p.setBrush(QBrush(g)); + p.drawRoundedRect(r, radius, radius); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + + // text + const QPoint c = r.center(); + p.setPen(QColor(0xff, 0xff, 0xff)); + p.setRenderHint(QPainter::TextAntialiasing); + if (alert.size == cereal::SelfdriveState::AlertSize::SMALL) { + p.setFont(InterFont(74, QFont::DemiBold)); + p.drawText(r, Qt::AlignCenter, alert.text1); + } else if (alert.size == cereal::SelfdriveState::AlertSize::MID) { + p.setFont(InterFont(88, QFont::Bold)); + p.drawText(QRect(0, c.y() - 125, width(), 150), Qt::AlignHCenter | Qt::AlignTop, alert.text1); + p.setFont(InterFont(66)); + p.drawText(QRect(0, c.y() + 21, width(), 90), Qt::AlignHCenter, alert.text2); + } else if (alert.size == cereal::SelfdriveState::AlertSize::FULL) { + bool l = alert.text1.length() > 15; + p.setFont(InterFont(l ? 132 : 177, QFont::Bold)); + p.drawText(QRect(0, r.y() + (l ? 240 : 270), width(), 600), Qt::AlignHCenter | Qt::TextWordWrap, alert.text1); + p.setFont(InterFont(88)); + p.drawText(QRect(0, r.height() - (l ? 361 : 420), width(), 300), Qt::AlignHCenter | Qt::TextWordWrap, alert.text2); + } +} diff --git a/selfdrive/ui/qt/onroad/alerts.h b/selfdrive/ui/qt/onroad/alerts.h new file mode 100644 index 0000000000..de38d8ffc3 --- /dev/null +++ b/selfdrive/ui/qt/onroad/alerts.h @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include "selfdrive/ui/ui.h" + +class OnroadAlerts : public QWidget { + Q_OBJECT + +public: + OnroadAlerts(QWidget *parent = 0) : QWidget(parent) {} + void updateState(const UIState &s); + void clear(); + +protected: + struct Alert { + QString text1; + QString text2; + QString type; + cereal::SelfdriveState::AlertSize size; + cereal::SelfdriveState::AlertStatus status; + + bool equal(const Alert &other) const { + return text1 == other.text1 && text2 == other.text2 && type == other.type; + } + }; + + const QMap alert_colors = { + {cereal::SelfdriveState::AlertStatus::NORMAL, QColor(0x15, 0x15, 0x15, 0xf1)}, + {cereal::SelfdriveState::AlertStatus::USER_PROMPT, QColor(0xDA, 0x6F, 0x25, 0xf1)}, + {cereal::SelfdriveState::AlertStatus::CRITICAL, QColor(0xC9, 0x22, 0x31, 0xf1)}, + }; + + void paintEvent(QPaintEvent*) override; + OnroadAlerts::Alert getAlert(const SubMaster &sm, uint64_t started_frame); + + QColor bg; + Alert alert = {}; +}; diff --git a/selfdrive/ui/qt/onroad/annotated_camera.cc b/selfdrive/ui/qt/onroad/annotated_camera.cc new file mode 100644 index 0000000000..f504ad69f1 --- /dev/null +++ b/selfdrive/ui/qt/onroad/annotated_camera.cc @@ -0,0 +1,157 @@ + +#include "selfdrive/ui/qt/onroad/annotated_camera.h" + +#include +#include +#include + +#include "common/swaglog.h" +#include "selfdrive/ui/qt/util.h" + +// Window that shows camera view and variety of info drawn on top +AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget *parent) + : fps_filter(UI_FREQ, 3, 1. / UI_FREQ), CameraWidget("camerad", type, parent) { + pm = std::make_unique(std::vector{"uiDebug"}); + + main_layout = new QVBoxLayout(this); + main_layout->setMargin(UI_BORDER_SIZE); + main_layout->setSpacing(0); + + experimental_btn = new ExperimentalButton(this); + main_layout->addWidget(experimental_btn, 0, Qt::AlignTop | Qt::AlignRight); +} + +void AnnotatedCameraWidget::updateState(const UIState &s) { + // update engageability/experimental mode button + experimental_btn->updateState(s); + dmon.updateState(s); +} + +void AnnotatedCameraWidget::initializeGL() { + CameraWidget::initializeGL(); + qInfo() << "OpenGL version:" << QString((const char*)glGetString(GL_VERSION)); + qInfo() << "OpenGL vendor:" << QString((const char*)glGetString(GL_VENDOR)); + qInfo() << "OpenGL renderer:" << QString((const char*)glGetString(GL_RENDERER)); + qInfo() << "OpenGL language version:" << QString((const char*)glGetString(GL_SHADING_LANGUAGE_VERSION)); + + prev_draw_t = millis_since_boot(); + setBackgroundColor(bg_colors[STATUS_DISENGAGED]); +} + +mat4 AnnotatedCameraWidget::calcFrameMatrix() { + // Project point at "infinity" to compute x and y offsets + // to ensure this ends up in the middle of the screen + // for narrow come and a little lower for wide cam. + // TODO: use proper perspective transform? + + // Select intrinsic matrix and calibration based on camera type + auto *s = uiState(); + bool wide_cam = active_stream_type == VISION_STREAM_WIDE_ROAD; + const auto &intrinsic_matrix = wide_cam ? ECAM_INTRINSIC_MATRIX : FCAM_INTRINSIC_MATRIX; + const auto &calibration = wide_cam ? s->scene.view_from_wide_calib : s->scene.view_from_calib; + + // Compute the calibration transformation matrix + const auto calib_transform = intrinsic_matrix * calibration; + + float zoom = wide_cam ? 2.0 : 1.1; + Eigen::Vector3f inf(1000., 0., 0.); + auto Kep = calib_transform * inf; + + int w = width(), h = height(); + float center_x = intrinsic_matrix(0, 2); + float center_y = intrinsic_matrix(1, 2); + + float max_x_offset = center_x * zoom - w / 2 - 5; + float max_y_offset = center_y * zoom - h / 2 - 5; + float x_offset = std::clamp((Kep.x() / Kep.z() - center_x) * zoom, -max_x_offset, max_x_offset); + float y_offset = std::clamp((Kep.y() / Kep.z() - center_y) * zoom, -max_y_offset, max_y_offset); + + // Apply transformation such that video pixel coordinates match video + // 1) Put (0, 0) in the middle of the video + // 2) Apply same scaling as video + // 3) Put (0, 0) in top left corner of video + Eigen::Matrix3f video_transform =(Eigen::Matrix3f() << + zoom, 0.0f, (w / 2 - x_offset) - (center_x * zoom), + 0.0f, zoom, (h / 2 - y_offset) - (center_y * zoom), + 0.0f, 0.0f, 1.0f).finished(); + + model.setTransform(video_transform * calib_transform); + + float zx = zoom * 2 * center_x / w; + float zy = zoom * 2 * center_y / h; + return mat4{{ + zx, 0.0, 0.0, -x_offset / w * 2, + 0.0, zy, 0.0, y_offset / h * 2, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }}; +} + +void AnnotatedCameraWidget::paintGL() { + UIState *s = uiState(); + SubMaster &sm = *(s->sm); + const double start_draw_t = millis_since_boot(); + + // draw camera frame + { + std::lock_guard lk(frame_lock); + + if (frames.empty()) { + if (skip_frame_count > 0) { + skip_frame_count--; + qDebug() << "skipping frame, not ready"; + return; + } + } else { + // skip drawing up to this many frames if we're + // missing camera frames. this smooths out the + // transitions from the narrow and wide cameras + skip_frame_count = 5; + } + + // Wide or narrow cam dependent on speed + bool has_wide_cam = available_streams.count(VISION_STREAM_WIDE_ROAD); + if (has_wide_cam) { + float v_ego = sm["carState"].getCarState().getVEgo(); + if ((v_ego < 10) || available_streams.size() == 1) { + wide_cam_requested = true; + } else if (v_ego > 15) { + wide_cam_requested = false; + } + wide_cam_requested = wide_cam_requested && sm["selfdriveState"].getSelfdriveState().getExperimentalMode(); + } + CameraWidget::setStreamType(wide_cam_requested ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD); + CameraWidget::setFrameId(sm["modelV2"].getModelV2().getFrameId()); + CameraWidget::paintGL(); + } + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(Qt::NoPen); + + model.draw(painter, rect()); + dmon.draw(painter, rect()); + hud.updateState(*s); + hud.draw(painter, rect()); + + double cur_draw_t = millis_since_boot(); + double dt = cur_draw_t - prev_draw_t; + double fps = fps_filter.update(1. / dt * 1000); + if (fps < 15) { + LOGW("slow frame rate: %.2f fps", fps); + } + prev_draw_t = cur_draw_t; + + // publish debug msg + MessageBuilder msg; + auto m = msg.initEvent().initUiDebug(); + m.setDrawTimeMillis(cur_draw_t - start_draw_t); + pm->send("uiDebug", msg); +} + +void AnnotatedCameraWidget::showEvent(QShowEvent *event) { + CameraWidget::showEvent(event); + + ui_update_params(uiState()); + prev_draw_t = millis_since_boot(); +} diff --git a/selfdrive/ui/qt/onroad/annotated_camera.h b/selfdrive/ui/qt/onroad/annotated_camera.h new file mode 100644 index 0000000000..d205579f6c --- /dev/null +++ b/selfdrive/ui/qt/onroad/annotated_camera.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include "selfdrive/ui/qt/onroad/hud.h" +#include "selfdrive/ui/qt/onroad/buttons.h" +#include "selfdrive/ui/qt/onroad/driver_monitoring.h" +#include "selfdrive/ui/qt/onroad/model.h" +#include "selfdrive/ui/qt/widgets/cameraview.h" + +class AnnotatedCameraWidget : public CameraWidget { + Q_OBJECT + +public: + explicit AnnotatedCameraWidget(VisionStreamType type, QWidget* parent = 0); + void updateState(const UIState &s); + +private: + QVBoxLayout *main_layout; + ExperimentalButton *experimental_btn; + DriverMonitorRenderer dmon; + HudRenderer hud; + ModelRenderer model; + std::unique_ptr pm; + + int skip_frame_count = 0; + bool wide_cam_requested = false; + +protected: + void paintGL() override; + void initializeGL() override; + void showEvent(QShowEvent *event) override; + mat4 calcFrameMatrix() override; + + double prev_draw_t = 0; + FirstOrderFilter fps_filter; +}; diff --git a/selfdrive/ui/qt/onroad/buttons.cc b/selfdrive/ui/qt/onroad/buttons.cc new file mode 100644 index 0000000000..32e58c9dba --- /dev/null +++ b/selfdrive/ui/qt/onroad/buttons.cc @@ -0,0 +1,49 @@ +#include "selfdrive/ui/qt/onroad/buttons.h" + +#include + +#include "selfdrive/ui/qt/util.h" + +void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity) { + p.setRenderHint(QPainter::Antialiasing); + p.setOpacity(1.0); // bg dictates opacity of ellipse + p.setPen(Qt::NoPen); + p.setBrush(bg); + p.drawEllipse(center, btn_size / 2, btn_size / 2); + p.setOpacity(opacity); + p.drawPixmap(center - QPoint(img.width() / 2, img.height() / 2), img); + p.setOpacity(1.0); +} + +// ExperimentalButton +ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(false), engageable(false), QPushButton(parent) { + setFixedSize(btn_size, btn_size); + + engage_img = loadPixmap("../assets/icons/chffr_wheel.png", {img_size, img_size}); + experimental_img = loadPixmap("../assets/icons/experimental.svg", {img_size, img_size}); + QObject::connect(this, &QPushButton::clicked, this, &ExperimentalButton::changeMode); +} + +void ExperimentalButton::changeMode() { + const auto cp = (*uiState()->sm)["carParams"].getCarParams(); + bool can_change = hasLongitudinalControl(cp) && params.getBool("ExperimentalModeConfirmed"); + if (can_change) { + params.putBool("ExperimentalMode", !experimental_mode); + } +} + +void ExperimentalButton::updateState(const UIState &s) { + const auto cs = (*s.sm)["selfdriveState"].getSelfdriveState(); + bool eng = cs.getEngageable() || cs.getEnabled(); + if ((cs.getExperimentalMode() != experimental_mode) || (eng != engageable)) { + engageable = eng; + experimental_mode = cs.getExperimentalMode(); + update(); + } +} + +void ExperimentalButton::paintEvent(QPaintEvent *event) { + QPainter p(this); + QPixmap img = experimental_mode ? experimental_img : engage_img; + drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0); +} diff --git a/selfdrive/ui/qt/onroad/buttons.h b/selfdrive/ui/qt/onroad/buttons.h new file mode 100644 index 0000000000..9c91bc3c7b --- /dev/null +++ b/selfdrive/ui/qt/onroad/buttons.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "selfdrive/ui/ui.h" + +const int btn_size = 192; +const int img_size = (btn_size / 4) * 3; + +class ExperimentalButton : public QPushButton { + Q_OBJECT + +public: + explicit ExperimentalButton(QWidget *parent = 0); + void updateState(const UIState &s); + +private: + void paintEvent(QPaintEvent *event) override; + void changeMode(); + + Params params; + QPixmap engage_img; + QPixmap experimental_img; + bool experimental_mode; + bool engageable; +}; + +void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, const QBrush &bg, float opacity); diff --git a/selfdrive/ui/qt/onroad/driver_monitoring.cc b/selfdrive/ui/qt/onroad/driver_monitoring.cc new file mode 100644 index 0000000000..49f2c950b4 --- /dev/null +++ b/selfdrive/ui/qt/onroad/driver_monitoring.cc @@ -0,0 +1,107 @@ +#include "selfdrive/ui/qt/onroad/driver_monitoring.h" +#include +#include + +#include "selfdrive/ui/qt/onroad/buttons.h" +#include "selfdrive/ui/qt/util.h" + +// Default 3D coordinates for face keypoints +static constexpr vec3 DEFAULT_FACE_KPTS_3D[] = { + {-5.98, -51.20, 8.00}, {-17.64, -49.14, 8.00}, {-23.81, -46.40, 8.00}, {-29.98, -40.91, 8.00}, {-32.04, -37.49, 8.00}, + {-34.10, -32.00, 8.00}, {-36.16, -21.03, 8.00}, {-36.16, 6.40, 8.00}, {-35.47, 10.51, 8.00}, {-32.73, 19.43, 8.00}, + {-29.30, 26.29, 8.00}, {-24.50, 33.83, 8.00}, {-19.01, 41.37, 8.00}, {-14.21, 46.17, 8.00}, {-12.16, 47.54, 8.00}, + {-4.61, 49.60, 8.00}, {4.99, 49.60, 8.00}, {12.53, 47.54, 8.00}, {14.59, 46.17, 8.00}, {19.39, 41.37, 8.00}, + {24.87, 33.83, 8.00}, {29.67, 26.29, 8.00}, {33.10, 19.43, 8.00}, {35.84, 10.51, 8.00}, {36.53, 6.40, 8.00}, + {36.53, -21.03, 8.00}, {34.47, -32.00, 8.00}, {32.42, -37.49, 8.00}, {30.36, -40.91, 8.00}, {24.19, -46.40, 8.00}, + {18.02, -49.14, 8.00}, {6.36, -51.20, 8.00}, {-5.98, -51.20, 8.00}, +}; + +// Colors used for drawing based on monitoring state +static const QColor DMON_ENGAGED_COLOR = QColor::fromRgbF(0.1, 0.945, 0.26); +static const QColor DMON_DISENGAGED_COLOR = QColor::fromRgbF(0.545, 0.545, 0.545); + +DriverMonitorRenderer::DriverMonitorRenderer() : face_kpts_draw(std::size(DEFAULT_FACE_KPTS_3D)) { + dm_img = loadPixmap("../assets/icons/driver_face.png", {img_size + 5, img_size + 5}); +} + +void DriverMonitorRenderer::updateState(const UIState &s) { + auto &sm = *(s.sm); + is_visible = sm["selfdriveState"].getSelfdriveState().getAlertSize() == cereal::SelfdriveState::AlertSize::NONE && + sm.rcv_frame("driverStateV2") > s.scene.started_frame; + if (!is_visible) return; + + auto dm_state = sm["driverMonitoringState"].getDriverMonitoringState(); + is_active = dm_state.getIsActiveMode(); + is_rhd = dm_state.getIsRHD(); + dm_fade_state = std::clamp(dm_fade_state + 0.2f * (0.5f - is_active), 0.0f, 1.0f); + + const auto &driverstate = sm["driverStateV2"].getDriverStateV2(); + const auto driver_orient = is_rhd ? driverstate.getRightDriverData().getFaceOrientation() : driverstate.getLeftDriverData().getFaceOrientation(); + + for (int i = 0; i < 3; ++i) { + float v_this = (i == 0 ? (driver_orient[i] < 0 ? 0.7 : 0.9) : 0.4) * driver_orient[i]; + driver_pose_diff[i] = std::abs(driver_pose_vals[i] - v_this); + driver_pose_vals[i] = 0.8f * v_this + (1 - 0.8) * driver_pose_vals[i]; + driver_pose_sins[i] = std::sin(driver_pose_vals[i] * (1.0f - dm_fade_state)); + driver_pose_coss[i] = std::cos(driver_pose_vals[i] * (1.0f - dm_fade_state)); + } + + auto [sin_y, sin_x, sin_z] = driver_pose_sins; + auto [cos_y, cos_x, cos_z] = driver_pose_coss; + + // Rotation matrix for transforming face keypoints based on driver's head orientation + const mat3 r_xyz = {{ + cos_x * cos_z, cos_x * sin_z, -sin_x, + -sin_y * sin_x * cos_z - cos_y * sin_z, -sin_y * sin_x * sin_z + cos_y * cos_z, -sin_y * cos_x, + cos_y * sin_x * cos_z - sin_y * sin_z, cos_y * sin_x * sin_z + sin_y * cos_z, cos_y * cos_x, + }}; + + // Transform vertices + for (int i = 0; i < face_kpts_draw.size(); ++i) { + vec3 kpt = matvecmul3(r_xyz, DEFAULT_FACE_KPTS_3D[i]); + face_kpts_draw[i] = {{kpt.v[0], kpt.v[1], kpt.v[2] * (1.0f - dm_fade_state) + 8 * dm_fade_state}}; + } +} + +void DriverMonitorRenderer::draw(QPainter &painter, const QRect &surface_rect) { + if (!is_visible) return; + + painter.save(); + + int offset = UI_BORDER_SIZE + btn_size / 2; + float x = is_rhd ? surface_rect.width() - offset : offset; + float y = surface_rect.height() - offset; + float opacity = is_active ? 0.65f : 0.2f; + + drawIcon(painter, QPoint(x, y), dm_img, QColor(0, 0, 0, 70), opacity); + + QPointF keypoints[std::size(DEFAULT_FACE_KPTS_3D)]; + for (int i = 0; i < std::size(keypoints); ++i) { + const auto &v = face_kpts_draw[i].v; + float kp = (v[2] - 8) / 120.0f + 1.0f; + keypoints[i] = QPointF(v[0] * kp + x, v[1] * kp + y); + } + + painter.setPen(QPen(QColor::fromRgbF(1.0, 1.0, 1.0, opacity), 5.2, Qt::SolidLine, Qt::RoundCap)); + painter.drawPolyline(keypoints, std::size(keypoints)); + + // tracking arcs + const int arc_l = 133; + const float arc_t_default = 6.7f; + const float arc_t_extend = 12.0f; + QColor arc_color = uiState()->engaged() ? DMON_ENGAGED_COLOR : DMON_DISENGAGED_COLOR; + arc_color.setAlphaF(0.4 * (1.0f - dm_fade_state)); + + float delta_x = -driver_pose_sins[1] * arc_l / 2.0f; + float delta_y = -driver_pose_sins[0] * arc_l / 2.0f; + + // Draw horizontal tracking arc + painter.setPen(QPen(arc_color, arc_t_default + arc_t_extend * std::min(1.0, driver_pose_diff[1] * 5.0), Qt::SolidLine, Qt::RoundCap)); + painter.drawArc(QRectF(std::min(x + delta_x, x), y - arc_l / 2, std::abs(delta_x), arc_l), (driver_pose_sins[1] > 0 ? 90 : -90) * 16, 180 * 16); + + // Draw vertical tracking arc + painter.setPen(QPen(arc_color, arc_t_default + arc_t_extend * std::min(1.0, driver_pose_diff[0] * 5.0), Qt::SolidLine, Qt::RoundCap)); + painter.drawArc(QRectF(x - arc_l / 2, std::min(y + delta_y, y), arc_l, std::abs(delta_y)), (driver_pose_sins[0] > 0 ? 0 : 180) * 16, 180 * 16); + + painter.restore(); +} diff --git a/selfdrive/ui/qt/onroad/driver_monitoring.h b/selfdrive/ui/qt/onroad/driver_monitoring.h new file mode 100644 index 0000000000..47db151c81 --- /dev/null +++ b/selfdrive/ui/qt/onroad/driver_monitoring.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include "selfdrive/ui/ui.h" + +class DriverMonitorRenderer { +public: + DriverMonitorRenderer(); + void updateState(const UIState &s); + void draw(QPainter &painter, const QRect &surface_rect); + +private: + float driver_pose_vals[3] = {}; + float driver_pose_diff[3] = {}; + float driver_pose_sins[3] = {}; + float driver_pose_coss[3] = {}; + bool is_visible = false; + bool is_active = false; + bool is_rhd = false; + float dm_fade_state = 1.0; + QPixmap dm_img; + std::vector face_kpts_draw; +}; diff --git a/selfdrive/ui/qt/onroad/hud.cc b/selfdrive/ui/qt/onroad/hud.cc new file mode 100644 index 0000000000..4cfa3d0e3c --- /dev/null +++ b/selfdrive/ui/qt/onroad/hud.cc @@ -0,0 +1,112 @@ +#include "selfdrive/ui/qt/onroad/hud.h" + +#include + +#include "selfdrive/ui/qt/util.h" + +constexpr int SET_SPEED_NA = 255; + +HudRenderer::HudRenderer() {} + +void HudRenderer::updateState(const UIState &s) { + is_metric = s.scene.is_metric; + status = s.status; + + const SubMaster &sm = *(s.sm); + if (sm.rcv_frame("carState") < s.scene.started_frame) { + is_cruise_set = false; + set_speed = SET_SPEED_NA; + speed = 0.0; + return; + } + + const auto &controls_state = sm["controlsState"].getControlsState(); + const auto &car_state = sm["carState"].getCarState(); + + // Handle older routes where vCruiseCluster is not set + set_speed = car_state.getVCruiseCluster() == 0.0 ? controls_state.getVCruiseDEPRECATED() : car_state.getVCruiseCluster(); + is_cruise_set = set_speed > 0 && set_speed != SET_SPEED_NA; + is_cruise_available = set_speed != -1; + + if (is_cruise_set && !is_metric) { + set_speed *= KM_TO_MILE; + } + + // Handle older routes where vEgoCluster is not set + v_ego_cluster_seen = v_ego_cluster_seen || car_state.getVEgoCluster() != 0.0; + float v_ego = v_ego_cluster_seen ? car_state.getVEgoCluster() : car_state.getVEgo(); + speed = std::max(0.0f, v_ego * (is_metric ? MS_TO_KPH : MS_TO_MPH)); +} + +void HudRenderer::draw(QPainter &p, const QRect &surface_rect) { + p.save(); + + // Draw header gradient + QLinearGradient bg(0, UI_HEADER_HEIGHT - (UI_HEADER_HEIGHT / 2.5), 0, UI_HEADER_HEIGHT); + bg.setColorAt(0, QColor::fromRgbF(0, 0, 0, 0.45)); + bg.setColorAt(1, QColor::fromRgbF(0, 0, 0, 0)); + p.fillRect(0, 0, surface_rect.width(), UI_HEADER_HEIGHT, bg); + + + if (is_cruise_available) { + drawSetSpeed(p, surface_rect); + } + drawCurrentSpeed(p, surface_rect); + + p.restore(); +} + +void HudRenderer::drawSetSpeed(QPainter &p, const QRect &surface_rect) { + // Draw outer box + border to contain set speed + const QSize default_size = {172, 204}; + QSize set_speed_size = is_metric ? QSize(200, 204) : default_size; + QRect set_speed_rect(QPoint(60 + (default_size.width() - set_speed_size.width()) / 2, 45), set_speed_size); + + // Draw set speed box + p.setPen(QPen(QColor(255, 255, 255, 75), 6)); + p.setBrush(QColor(0, 0, 0, 166)); + p.drawRoundedRect(set_speed_rect, 32, 32); + + // Colors based on status + QColor max_color = QColor(0xa6, 0xa6, 0xa6, 0xff); + QColor set_speed_color = QColor(0x72, 0x72, 0x72, 0xff); + if (is_cruise_set) { + set_speed_color = QColor(255, 255, 255); + if (status == STATUS_DISENGAGED) { + max_color = QColor(255, 255, 255); + } else if (status == STATUS_OVERRIDE) { + max_color = QColor(0x91, 0x9b, 0x95, 0xff); + } else { + max_color = QColor(0x80, 0xd8, 0xa6, 0xff); + } + } + + // Draw "MAX" text + p.setFont(InterFont(40, QFont::DemiBold)); + p.setPen(max_color); + p.drawText(set_speed_rect.adjusted(0, 27, 0, 0), Qt::AlignTop | Qt::AlignHCenter, tr("MAX")); + + // Draw set speed + QString setSpeedStr = is_cruise_set ? QString::number(std::nearbyint(set_speed)) : "–"; + p.setFont(InterFont(90, QFont::Bold)); + p.setPen(set_speed_color); + p.drawText(set_speed_rect.adjusted(0, 77, 0, 0), Qt::AlignTop | Qt::AlignHCenter, setSpeedStr); +} + +void HudRenderer::drawCurrentSpeed(QPainter &p, const QRect &surface_rect) { + QString speedStr = QString::number(std::nearbyint(speed)); + + p.setFont(InterFont(176, QFont::Bold)); + drawText(p, surface_rect.center().x(), 210, speedStr); + + p.setFont(InterFont(66)); + drawText(p, surface_rect.center().x(), 290, is_metric ? tr("km/h") : tr("mph"), 200); +} + +void HudRenderer::drawText(QPainter &p, int x, int y, const QString &text, int alpha) { + QRect real_rect = p.fontMetrics().boundingRect(text); + real_rect.moveCenter({x, y - real_rect.height() / 2}); + + p.setPen(QColor(0xff, 0xff, 0xff, alpha)); + p.drawText(real_rect.x(), real_rect.bottom(), text); +} diff --git a/selfdrive/ui/qt/onroad/hud.h b/selfdrive/ui/qt/onroad/hud.h new file mode 100644 index 0000000000..b2ac379dbe --- /dev/null +++ b/selfdrive/ui/qt/onroad/hud.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "selfdrive/ui/ui.h" + +class HudRenderer : public QObject { + Q_OBJECT + +public: + HudRenderer(); + void updateState(const UIState &s); + void draw(QPainter &p, const QRect &surface_rect); + +private: + void drawSetSpeed(QPainter &p, const QRect &surface_rect); + void drawCurrentSpeed(QPainter &p, const QRect &surface_rect); + void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255); + + float speed = 0; + float set_speed = 0; + bool is_cruise_set = false; + bool is_cruise_available = true; + bool is_metric = false; + bool v_ego_cluster_seen = false; + int status = STATUS_DISENGAGED; +}; diff --git a/selfdrive/ui/qt/onroad/model.cc b/selfdrive/ui/qt/onroad/model.cc new file mode 100644 index 0000000000..52902abdc8 --- /dev/null +++ b/selfdrive/ui/qt/onroad/model.cc @@ -0,0 +1,250 @@ +#include "selfdrive/ui/qt/onroad/model.h" + +constexpr int CLIP_MARGIN = 500; +constexpr float MIN_DRAW_DISTANCE = 10.0; +constexpr float MAX_DRAW_DISTANCE = 100.0; + +static int get_path_length_idx(const cereal::XYZTData::Reader &line, const float path_height) { + const auto &line_x = line.getX(); + int max_idx = 0; + for (int i = 1; i < line_x.size() && line_x[i] <= path_height; ++i) { + max_idx = i; + } + return max_idx; +} + +void ModelRenderer::draw(QPainter &painter, const QRect &surface_rect) { + auto *s = uiState(); + auto &sm = *(s->sm); + // Check if data is up-to-date + if (sm.rcv_frame("liveCalibration") < s->scene.started_frame || + sm.rcv_frame("modelV2") < s->scene.started_frame) { + return; + } + + clip_region = surface_rect.adjusted(-CLIP_MARGIN, -CLIP_MARGIN, CLIP_MARGIN, CLIP_MARGIN); + experimental_mode = sm["selfdriveState"].getSelfdriveState().getExperimentalMode(); + longitudinal_control = sm["carParams"].getCarParams().getOpenpilotLongitudinalControl(); + path_offset_z = sm["liveCalibration"].getLiveCalibration().getHeight()[0]; + + painter.save(); + + const auto &model = sm["modelV2"].getModelV2(); + const auto &radar_state = sm["radarState"].getRadarState(); + const auto &lead_one = radar_state.getLeadOne(); + + update_model(model, lead_one); + drawLaneLines(painter); + drawPath(painter, model, surface_rect.height()); + + if (longitudinal_control && sm.alive("radarState")) { + update_leads(radar_state, model.getPosition()); + const auto &lead_two = radar_state.getLeadTwo(); + if (lead_one.getStatus()) { + drawLead(painter, lead_one, lead_vertices[0], surface_rect); + } + if (lead_two.getStatus() && (std::abs(lead_one.getDRel() - lead_two.getDRel()) > 3.0)) { + drawLead(painter, lead_two, lead_vertices[1], surface_rect); + } + } + + painter.restore(); +} + +void ModelRenderer::update_leads(const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line) { + for (int i = 0; i < 2; ++i) { + const auto &lead_data = (i == 0) ? radar_state.getLeadOne() : radar_state.getLeadTwo(); + if (lead_data.getStatus()) { + float z = line.getZ()[get_path_length_idx(line, lead_data.getDRel())]; + mapToScreen(lead_data.getDRel(), -lead_data.getYRel(), z + path_offset_z, &lead_vertices[i]); + } + } +} + +void ModelRenderer::update_model(const cereal::ModelDataV2::Reader &model, const cereal::RadarState::LeadData::Reader &lead) { + const auto &model_position = model.getPosition(); + float max_distance = std::clamp(*(model_position.getX().end() - 1), MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE); + + // update lane lines + const auto &lane_lines = model.getLaneLines(); + const auto &line_probs = model.getLaneLineProbs(); + int max_idx = get_path_length_idx(lane_lines[0], max_distance); + for (int i = 0; i < std::size(lane_line_vertices); i++) { + lane_line_probs[i] = line_probs[i]; + mapLineToPolygon(lane_lines[i], 0.025 * lane_line_probs[i], 0, &lane_line_vertices[i], max_idx); + } + + // update road edges + const auto &road_edges = model.getRoadEdges(); + const auto &edge_stds = model.getRoadEdgeStds(); + for (int i = 0; i < std::size(road_edge_vertices); i++) { + road_edge_stds[i] = edge_stds[i]; + mapLineToPolygon(road_edges[i], 0.025, 0, &road_edge_vertices[i], max_idx); + } + + // update path + if (lead.getStatus()) { + const float lead_d = lead.getDRel() * 2.; + max_distance = std::clamp((float)(lead_d - fmin(lead_d * 0.35, 10.)), 0.0f, max_distance); + } + max_idx = get_path_length_idx(model_position, max_distance); + mapLineToPolygon(model_position, 0.9, path_offset_z, &track_vertices, max_idx, false); +} + +void ModelRenderer::drawLaneLines(QPainter &painter) { + // lanelines + for (int i = 0; i < std::size(lane_line_vertices); ++i) { + painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp(lane_line_probs[i], 0.0, 0.7))); + painter.drawPolygon(lane_line_vertices[i]); + } + + // road edges + for (int i = 0; i < std::size(road_edge_vertices); ++i) { + painter.setBrush(QColor::fromRgbF(1.0, 0, 0, std::clamp(1.0 - road_edge_stds[i], 0.0, 1.0))); + painter.drawPolygon(road_edge_vertices[i]); + } +} + +void ModelRenderer::drawPath(QPainter &painter, const cereal::ModelDataV2::Reader &model, int height) { + QLinearGradient bg(0, height, 0, 0); + if (experimental_mode) { + // The first half of track_vertices are the points for the right side of the path + const auto &acceleration = model.getAcceleration().getX(); + const int max_len = std::min(track_vertices.length() / 2, acceleration.size()); + + for (int i = 0; i < max_len; ++i) { + // Some points are out of frame + int track_idx = max_len - i - 1; // flip idx to start from bottom right + if (track_vertices[track_idx].y() < 0 || track_vertices[track_idx].y() > height) continue; + + // Flip so 0 is bottom of frame + float lin_grad_point = (height - track_vertices[track_idx].y()) / height; + + // speed up: 120, slow down: 0 + float path_hue = fmax(fmin(60 + acceleration[i] * 35, 120), 0); + // FIXME: painter.drawPolygon can be slow if hue is not rounded + path_hue = int(path_hue * 100 + 0.5) / 100; + + float saturation = fmin(fabs(acceleration[i] * 1.5), 1); + float lightness = util::map_val(saturation, 0.0f, 1.0f, 0.95f, 0.62f); // lighter when grey + float alpha = util::map_val(lin_grad_point, 0.75f / 2.f, 0.75f, 0.4f, 0.0f); // matches previous alpha fade + bg.setColorAt(lin_grad_point, QColor::fromHslF(path_hue / 360., saturation, lightness, alpha)); + + // Skip a point, unless next is last + i += (i + 2) < max_len ? 1 : 0; + } + + } else { + updatePathGradient(bg); + } + + painter.setBrush(bg); + painter.drawPolygon(track_vertices); +} + +void ModelRenderer::updatePathGradient(QLinearGradient &bg) { + static const QColor throttle_colors[] = { + QColor::fromHslF(148. / 360., 0.94, 0.51, 0.4), + QColor::fromHslF(112. / 360., 1.0, 0.68, 0.35), + QColor::fromHslF(112. / 360., 1.0, 0.68, 0.0)}; + + static const QColor no_throttle_colors[] = { + QColor::fromHslF(148. / 360., 0.0, 0.95, 0.4), + QColor::fromHslF(112. / 360., 0.0, 0.95, 0.35), + QColor::fromHslF(112. / 360., 0.0, 0.95, 0.0), + }; + + // Transition speed; 0.1 corresponds to 0.5 seconds at UI_FREQ + constexpr float transition_speed = 0.1f; + + // Start transition if throttle state changes + bool allow_throttle = (*uiState()->sm)["longitudinalPlan"].getLongitudinalPlan().getAllowThrottle() || !longitudinal_control; + if (allow_throttle != prev_allow_throttle) { + prev_allow_throttle = allow_throttle; + // Invert blend factor for a smooth transition when the state changes mid-animation + blend_factor = std::max(1.0f - blend_factor, 0.0f); + } + + const QColor *begin_colors = allow_throttle ? no_throttle_colors : throttle_colors; + const QColor *end_colors = allow_throttle ? throttle_colors : no_throttle_colors; + if (blend_factor < 1.0f) { + blend_factor = std::min(blend_factor + transition_speed, 1.0f); + } + + // Set gradient colors by blending the start and end colors + bg.setColorAt(0.0f, blendColors(begin_colors[0], end_colors[0], blend_factor)); + bg.setColorAt(0.5f, blendColors(begin_colors[1], end_colors[1], blend_factor)); + bg.setColorAt(1.0f, blendColors(begin_colors[2], end_colors[2], blend_factor)); +} + +QColor ModelRenderer::blendColors(const QColor &start, const QColor &end, float t) { + if (t == 1.0f) return end; + return QColor::fromRgbF( + (1 - t) * start.redF() + t * end.redF(), + (1 - t) * start.greenF() + t * end.greenF(), + (1 - t) * start.blueF() + t * end.blueF(), + (1 - t) * start.alphaF() + t * end.alphaF()); +} + +void ModelRenderer::drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, + const QPointF &vd, const QRect &surface_rect) { + const float speedBuff = 10.; + const float leadBuff = 40.; + const float d_rel = lead_data.getDRel(); + const float v_rel = lead_data.getVRel(); + + float fillAlpha = 0; + if (d_rel < leadBuff) { + fillAlpha = 255 * (1.0 - (d_rel / leadBuff)); + if (v_rel < 0) { + fillAlpha += 255 * (-1 * (v_rel / speedBuff)); + } + fillAlpha = (int)(fmin(fillAlpha, 255)); + } + + float sz = std::clamp((25 * 30) / (d_rel / 3 + 30), 15.0f, 30.0f) * 2.35; + float x = std::clamp(vd.x(), 0.f, surface_rect.width() - sz / 2); + float y = std::min(vd.y(), surface_rect.height() - sz * 0.6); + + float g_xo = sz / 5; + float g_yo = sz / 10; + + QPointF glow[] = {{x + (sz * 1.35) + g_xo, y + sz + g_yo}, {x, y - g_yo}, {x - (sz * 1.35) - g_xo, y + sz + g_yo}}; + painter.setBrush(QColor(218, 202, 37, 255)); + painter.drawPolygon(glow, std::size(glow)); + + // chevron + QPointF chevron[] = {{x + (sz * 1.25), y + sz}, {x, y}, {x - (sz * 1.25), y + sz}}; + painter.setBrush(QColor(201, 34, 49, fillAlpha)); + painter.drawPolygon(chevron, std::size(chevron)); +} + +// Projects a point in car to space to the corresponding point in full frame image space. +bool ModelRenderer::mapToScreen(float in_x, float in_y, float in_z, QPointF *out) { + Eigen::Vector3f input(in_x, in_y, in_z); + auto pt = car_space_transform * input; + *out = QPointF(pt.x() / pt.z(), pt.y() / pt.z()); + return clip_region.contains(*out); +} + +void ModelRenderer::mapLineToPolygon(const cereal::XYZTData::Reader &line, float y_off, float z_off, + QPolygonF *pvd, int max_idx, bool allow_invert) { + const auto line_x = line.getX(), line_y = line.getY(), line_z = line.getZ(); + QPointF left, right; + pvd->clear(); + for (int i = 0; i <= max_idx; i++) { + // highly negative x positions are drawn above the frame and cause flickering, clip to zy plane of camera + if (line_x[i] < 0) continue; + + bool l = mapToScreen(line_x[i], line_y[i] - y_off, line_z[i] + z_off, &left); + bool r = mapToScreen(line_x[i], line_y[i] + y_off, line_z[i] + z_off, &right); + if (l && r) { + // For wider lines the drawn polygon will "invert" when going over a hill and cause artifacts + if (!allow_invert && pvd->size() && left.y() > pvd->back().y()) { + continue; + } + pvd->push_back(left); + pvd->push_front(right); + } + } +} diff --git a/selfdrive/ui/qt/onroad/model.h b/selfdrive/ui/qt/onroad/model.h new file mode 100644 index 0000000000..79547e4b83 --- /dev/null +++ b/selfdrive/ui/qt/onroad/model.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +#include "selfdrive/ui/ui.h" + +class ModelRenderer { +public: + ModelRenderer() {} + void setTransform(const Eigen::Matrix3f &transform) { car_space_transform = transform; } + void draw(QPainter &painter, const QRect &surface_rect); + +private: + bool mapToScreen(float in_x, float in_y, float in_z, QPointF *out); + void mapLineToPolygon(const cereal::XYZTData::Reader &line, float y_off, float z_off, + QPolygonF *pvd, int max_idx, bool allow_invert = true); + void drawLead(QPainter &painter, const cereal::RadarState::LeadData::Reader &lead_data, const QPointF &vd, const QRect &surface_rect); + void update_leads(const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line); + void update_model(const cereal::ModelDataV2::Reader &model, const cereal::RadarState::LeadData::Reader &lead); + void drawLaneLines(QPainter &painter); + void drawPath(QPainter &painter, const cereal::ModelDataV2::Reader &model, int height); + void updatePathGradient(QLinearGradient &bg); + QColor blendColors(const QColor &start, const QColor &end, float t); + + bool longitudinal_control = false; + bool experimental_mode = false; + float blend_factor = 1.0f; + bool prev_allow_throttle = true; + float lane_line_probs[4] = {}; + float road_edge_stds[2] = {}; + float path_offset_z = 1.22f; + QPolygonF track_vertices; + QPolygonF lane_line_vertices[4] = {}; + QPolygonF road_edge_vertices[2] = {}; + QPointF lead_vertices[2] = {}; + Eigen::Matrix3f car_space_transform = Eigen::Matrix3f::Zero(); + QRectF clip_region; +}; diff --git a/selfdrive/ui/qt/onroad/onroad_home.cc b/selfdrive/ui/qt/onroad/onroad_home.cc new file mode 100644 index 0000000000..080f9bd50f --- /dev/null +++ b/selfdrive/ui/qt/onroad/onroad_home.cc @@ -0,0 +1,65 @@ +#include "selfdrive/ui/qt/onroad/onroad_home.h" + +#include +#include + +#include "selfdrive/ui/qt/util.h" + +OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setMargin(UI_BORDER_SIZE); + QStackedLayout *stacked_layout = new QStackedLayout; + stacked_layout->setStackingMode(QStackedLayout::StackAll); + main_layout->addLayout(stacked_layout); + + nvg = new AnnotatedCameraWidget(VISION_STREAM_ROAD, this); + + QWidget * split_wrapper = new QWidget; + split = new QHBoxLayout(split_wrapper); + split->setContentsMargins(0, 0, 0, 0); + split->setSpacing(0); + split->addWidget(nvg); + + if (getenv("DUAL_CAMERA_VIEW")) { + CameraWidget *arCam = new CameraWidget("camerad", VISION_STREAM_ROAD, this); + split->insertWidget(0, arCam); + } + + stacked_layout->addWidget(split_wrapper); + + alerts = new OnroadAlerts(this); + alerts->setAttribute(Qt::WA_TransparentForMouseEvents, true); + stacked_layout->addWidget(alerts); + + // setup stacking order + alerts->raise(); + + setAttribute(Qt::WA_OpaquePaintEvent); + QObject::connect(uiState(), &UIState::uiUpdate, this, &OnroadWindow::updateState); + QObject::connect(uiState(), &UIState::offroadTransition, this, &OnroadWindow::offroadTransition); +} + +void OnroadWindow::updateState(const UIState &s) { + if (!s.scene.started) { + return; + } + + alerts->updateState(s); + nvg->updateState(s); + + QColor bgColor = bg_colors[s.status]; + if (bg != bgColor) { + // repaint border + bg = bgColor; + update(); + } +} + +void OnroadWindow::offroadTransition(bool offroad) { + alerts->clear(); +} + +void OnroadWindow::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.fillRect(rect(), QColor(bg.red(), bg.green(), bg.blue(), 255)); +} diff --git a/selfdrive/ui/qt/onroad/onroad_home.h b/selfdrive/ui/qt/onroad/onroad_home.h new file mode 100644 index 0000000000..c321d2d44f --- /dev/null +++ b/selfdrive/ui/qt/onroad/onroad_home.h @@ -0,0 +1,22 @@ +#pragma once + +#include "selfdrive/ui/qt/onroad/alerts.h" +#include "selfdrive/ui/qt/onroad/annotated_camera.h" + +class OnroadWindow : public QWidget { + Q_OBJECT + +public: + OnroadWindow(QWidget* parent = 0); + +private: + void paintEvent(QPaintEvent *event); + OnroadAlerts *alerts; + AnnotatedCameraWidget *nvg; + QColor bg = bg_colors[STATUS_DISENGAGED]; + QHBoxLayout* split; + +private slots: + void offroadTransition(bool offroad); + void updateState(const UIState &s); +}; diff --git a/selfdrive/ui/qt/prime_state.cc b/selfdrive/ui/qt/prime_state.cc new file mode 100644 index 0000000000..f12daf1e3c --- /dev/null +++ b/selfdrive/ui/qt/prime_state.cc @@ -0,0 +1,48 @@ +#include "selfdrive/ui/qt/prime_state.h" + +#include + +#include "selfdrive/ui/qt/api.h" +#include "selfdrive/ui/qt/request_repeater.h" +#include "selfdrive/ui/qt/util.h" + +PrimeState::PrimeState(QObject* parent) : QObject(parent) { + const char *env_prime_type = std::getenv("PRIME_TYPE"); + auto type = env_prime_type ? env_prime_type : Params().get("PrimeType"); + + if (!type.empty()) { + prime_type = static_cast(std::atoi(type.c_str())); + } + + if (auto dongleId = getDongleId()) { + QString url = CommaApi::BASE_URL + "/v1.1/devices/" + *dongleId + "/"; + RequestRepeater* repeater = new RequestRepeater(this, url, "ApiCache_Device", 5); + QObject::connect(repeater, &RequestRepeater::requestDone, this, &PrimeState::handleReply); + } + + // Emit the initial state change + QTimer::singleShot(1, [this]() { emit changed(prime_type); }); +} + +void PrimeState::handleReply(const QString& response, bool success) { + if (!success) return; + + QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); + if (doc.isNull()) { + qDebug() << "JSON Parse failed on getting pairing and PrimeState status"; + return; + } + + QJsonObject json = doc.object(); + bool is_paired = json["is_paired"].toBool(); + auto type = static_cast(json["prime_type"].toInt()); + setType(is_paired ? type : PrimeState::PRIME_TYPE_UNPAIRED); +} + +void PrimeState::setType(PrimeState::Type type) { + if (type != prime_type) { + prime_type = type; + Params().put("PrimeType", std::to_string(prime_type)); + emit changed(prime_type); + } +} diff --git a/selfdrive/ui/qt/prime_state.h b/selfdrive/ui/qt/prime_state.h new file mode 100644 index 0000000000..0e2e3bb043 --- /dev/null +++ b/selfdrive/ui/qt/prime_state.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +class PrimeState : public QObject { + Q_OBJECT + +public: + + enum Type { + PRIME_TYPE_UNKNOWN = -2, + PRIME_TYPE_UNPAIRED = -1, + PRIME_TYPE_NONE = 0, + PRIME_TYPE_MAGENTA = 1, + PRIME_TYPE_LITE = 2, + PRIME_TYPE_BLUE = 3, + PRIME_TYPE_MAGENTA_NEW = 4, + PRIME_TYPE_PURPLE = 5, + }; + + PrimeState(QObject *parent); + void setType(PrimeState::Type type); + inline PrimeState::Type currentType() const { return prime_type; } + inline bool isSubscribed() const { return prime_type > PrimeState::PRIME_TYPE_NONE; } + +signals: + void changed(PrimeState::Type prime_type); + +private: + void handleReply(const QString &response, bool success); + + PrimeState::Type prime_type = PrimeState::PRIME_TYPE_UNKNOWN; +}; diff --git a/selfdrive/ui/qt/qt_window.cc b/selfdrive/ui/qt/qt_window.cc new file mode 100644 index 0000000000..cdd817ae2f --- /dev/null +++ b/selfdrive/ui/qt/qt_window.cc @@ -0,0 +1,36 @@ +#include "selfdrive/ui/qt/qt_window.h" + +void setMainWindow(QWidget *w) { + const float scale = util::getenv("SCALE", 1.0f); + const QSize sz = QGuiApplication::primaryScreen()->size(); + + if (Hardware::PC() && scale == 1.0 && !(sz - DEVICE_SCREEN_SIZE).isValid()) { + w->setMinimumSize(QSize(640, 480)); // allow resize smaller than fullscreen + w->setMaximumSize(DEVICE_SCREEN_SIZE); + w->resize(sz); + } else { + w->setFixedSize(DEVICE_SCREEN_SIZE * scale); + } + w->show(); + +#ifdef __TICI__ + QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); + wl_surface *s = reinterpret_cast(native->nativeResourceForWindow("surface", w->windowHandle())); + wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270); + wl_surface_commit(s); + + w->setWindowState(Qt::WindowFullScreen); + w->setVisible(true); + + // ensure we have a valid eglDisplay, otherwise the ui will silently fail + void *egl = native->nativeResourceForWindow("egldisplay", w->windowHandle()); + assert(egl != nullptr); +#endif +} + + +extern "C" { + void set_main_window(void *w) { + setMainWindow((QWidget*)w); + } +} diff --git a/selfdrive/ui/qt/qt_window.h b/selfdrive/ui/qt/qt_window.h new file mode 100644 index 0000000000..b9783477eb --- /dev/null +++ b/selfdrive/ui/qt/qt_window.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include +#include +#include + +#ifdef __TICI__ +#include +#include +#include +#endif + +#include "system/hardware/hw.h" + +const QString ASSET_PATH = ":/"; +const QSize DEVICE_SCREEN_SIZE = {2160, 1080}; + +void setMainWindow(QWidget *w); diff --git a/selfdrive/ui/qt/request_repeater.cc b/selfdrive/ui/qt/request_repeater.cc new file mode 100644 index 0000000000..7aa731898c --- /dev/null +++ b/selfdrive/ui/qt/request_repeater.cc @@ -0,0 +1,27 @@ +#include "selfdrive/ui/qt/request_repeater.h" + +RequestRepeater::RequestRepeater(QObject *parent, const QString &requestURL, const QString &cacheKey, + int period, bool while_onroad) : HttpRequest(parent) { + timer = new QTimer(this); + timer->setTimerType(Qt::VeryCoarseTimer); + QObject::connect(timer, &QTimer::timeout, [=]() { + if ((!uiState()->scene.started || while_onroad) && device()->isAwake() && !active()) { + sendRequest(requestURL); + } + }); + + timer->start(period * 1000); + + if (!cacheKey.isEmpty()) { + prevResp = QString::fromStdString(params.get(cacheKey.toStdString())); + if (!prevResp.isEmpty()) { + QTimer::singleShot(500, [=]() { emit requestDone(prevResp, true, QNetworkReply::NoError); }); + } + QObject::connect(this, &HttpRequest::requestDone, [=](const QString &resp, bool success) { + if (success && resp != prevResp) { + params.put(cacheKey.toStdString(), resp.toStdString()); + prevResp = resp; + } + }); + } +} diff --git a/selfdrive/ui/qt/request_repeater.h b/selfdrive/ui/qt/request_repeater.h new file mode 100644 index 0000000000..c0e2758273 --- /dev/null +++ b/selfdrive/ui/qt/request_repeater.h @@ -0,0 +1,15 @@ +#pragma once + +#include "common/util.h" +#include "selfdrive/ui/qt/api.h" +#include "selfdrive/ui/ui.h" + +class RequestRepeater : public HttpRequest { +public: + RequestRepeater(QObject *parent, const QString &requestURL, const QString &cacheKey = "", int period = 0, bool while_onroad=false); + +private: + Params params; + QTimer *timer; + QString prevResp; +}; diff --git a/selfdrive/ui/qt/sidebar.cc b/selfdrive/ui/qt/sidebar.cc new file mode 100644 index 0000000000..e9c6a2f7c0 --- /dev/null +++ b/selfdrive/ui/qt/sidebar.cc @@ -0,0 +1,165 @@ +#include "selfdrive/ui/qt/sidebar.h" + +#include + +#include "selfdrive/ui/qt/util.h" + +void Sidebar::drawMetric(QPainter &p, const QPair &label, QColor c, int y) { + const QRect rect = {30, y, 240, 126}; + + p.setPen(Qt::NoPen); + p.setBrush(QBrush(c)); + p.setClipRect(rect.x() + 4, rect.y(), 18, rect.height(), Qt::ClipOperation::ReplaceClip); + p.drawRoundedRect(QRect(rect.x() + 4, rect.y() + 4, 100, 118), 18, 18); + p.setClipping(false); + + QPen pen = QPen(QColor(0xff, 0xff, 0xff, 0x55)); + pen.setWidth(2); + p.setPen(pen); + p.setBrush(Qt::NoBrush); + p.drawRoundedRect(rect, 20, 20); + + p.setPen(QColor(0xff, 0xff, 0xff)); + p.setFont(InterFont(35, QFont::DemiBold)); + p.drawText(rect.adjusted(22, 0, 0, 0), Qt::AlignCenter, label.first + "\n" + label.second); +} + +Sidebar::Sidebar(QWidget *parent) : QFrame(parent), onroad(false), flag_pressed(false), settings_pressed(false), mic_indicator_pressed(false) { + home_img = loadPixmap("../assets/images/button_home.png", home_btn.size()); + flag_img = loadPixmap("../assets/images/button_flag.png", home_btn.size()); + settings_img = loadPixmap("../assets/images/button_settings.png", settings_btn.size(), Qt::IgnoreAspectRatio); + mic_img = loadPixmap("../assets/icons/microphone.png", QSize(30, 30)); + link_img = loadPixmap("../assets/icons/link.png", QSize(60, 60)); + + connect(this, &Sidebar::valueChanged, [=] { update(); }); + + setAttribute(Qt::WA_OpaquePaintEvent); + setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + setFixedWidth(300); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &Sidebar::updateState); + + pm = std::make_unique(std::vector{"bookmarkButton"}); +} + +void Sidebar::mousePressEvent(QMouseEvent *event) { + if (onroad && home_btn.contains(event->pos())) { + flag_pressed = true; + update(); + } else if (settings_btn.contains(event->pos())) { + settings_pressed = true; + update(); + } else if (recording_audio && mic_indicator_btn.contains(event->pos())) { + mic_indicator_pressed = true; + update(); + } +} + +void Sidebar::mouseReleaseEvent(QMouseEvent *event) { + if (flag_pressed || settings_pressed || mic_indicator_pressed) { + flag_pressed = settings_pressed = mic_indicator_pressed = false; + update(); + } + if (onroad && home_btn.contains(event->pos())) { + MessageBuilder msg; + msg.initEvent().initBookmarkButton(); + pm->send("bookmarkButton", msg); + } else if (settings_btn.contains(event->pos())) { + emit openSettings(); + } else if (recording_audio && mic_indicator_btn.contains(event->pos())) { + emit openSettings(2, "RecordAudio"); + } +} + +void Sidebar::offroadTransition(bool offroad) { + onroad = !offroad; + update(); +} + +void Sidebar::updateState(const UIState &s) { + if (!isVisible()) return; + + auto &sm = *(s.sm); + + networking = networking ? networking : window()->findChild(""); + bool tethering_on = networking && networking->wifi->tethering_on; + auto deviceState = sm["deviceState"].getDeviceState(); + setProperty("netType", tethering_on ? "Hotspot": network_type[deviceState.getNetworkType()]); + int strength = tethering_on ? 4 : (int)deviceState.getNetworkStrength(); + setProperty("netStrength", strength > 0 ? strength + 1 : 0); + + ItemStatus connectStatus; + auto last_ping = deviceState.getLastAthenaPingTime(); + if (last_ping == 0) { + connectStatus = ItemStatus{{tr("CONNECT"), tr("OFFLINE")}, warning_color}; + } else { + connectStatus = nanos_since_boot() - last_ping < 80e9 + ? ItemStatus{{tr("CONNECT"), tr("ONLINE")}, good_color} + : ItemStatus{{tr("CONNECT"), tr("ERROR")}, danger_color}; + } + setProperty("connectStatus", QVariant::fromValue(connectStatus)); + + ItemStatus tempStatus = {{tr("TEMP"), tr("HIGH")}, danger_color}; + auto ts = deviceState.getThermalStatus(); + if (ts == cereal::DeviceState::ThermalStatus::GREEN) { + tempStatus = {{tr("TEMP"), tr("GOOD")}, good_color}; + } else if (ts == cereal::DeviceState::ThermalStatus::YELLOW) { + tempStatus = {{tr("TEMP"), tr("OK")}, warning_color}; + } + setProperty("tempStatus", QVariant::fromValue(tempStatus)); + + ItemStatus pandaStatus = {{tr("VEHICLE"), tr("ONLINE")}, good_color}; + if (s.scene.pandaType == cereal::PandaState::PandaType::UNKNOWN) { + pandaStatus = {{tr("NO"), tr("PANDA")}, danger_color}; + } + setProperty("pandaStatus", QVariant::fromValue(pandaStatus)); + + setProperty("recordingAudio", s.scene.recording_audio); +} + +void Sidebar::paintEvent(QPaintEvent *event) { + QPainter p(this); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing); + + p.fillRect(rect(), QColor(57, 57, 57)); + + // buttons + p.setOpacity(settings_pressed ? 0.65 : 1.0); + p.drawPixmap(settings_btn.x(), settings_btn.y(), settings_img); + p.setOpacity(onroad && flag_pressed ? 0.65 : 1.0); + p.drawPixmap(home_btn.x(), home_btn.y(), onroad ? flag_img : home_img); + if (recording_audio) { + p.setBrush(danger_color); + p.setOpacity(mic_indicator_pressed ? 0.65 : 1.0); + p.drawRoundedRect(mic_indicator_btn, mic_indicator_btn.height() / 2, mic_indicator_btn.height() / 2); + int icon_x = mic_indicator_btn.x() + (mic_indicator_btn.width() - mic_img.width()) / 2; + int icon_y = mic_indicator_btn.y() + (mic_indicator_btn.height() - mic_img.height()) / 2; + p.drawPixmap(icon_x, icon_y, mic_img); + } + p.setOpacity(1.0); + + // network + int x = 58; + const QColor gray(0x54, 0x54, 0x54); + for (int i = 0; i < 5; ++i) { + p.setBrush(i < net_strength ? Qt::white : gray); + p.drawEllipse(x, 196, 27, 27); + x += 37; + } + + p.setFont(InterFont(35)); + p.setPen(QColor(0xff, 0xff, 0xff)); + const QRect r = QRect(58, 247, width() - 100, 50); + + if (net_type == "Hotspot") { + p.drawPixmap(r.x(), r.y() + (r.height() - link_img.height()) / 2, link_img); + } else { + p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, net_type); + } + + // metrics + drawMetric(p, temp_status.first, temp_status.second, 338); + drawMetric(p, panda_status.first, panda_status.second, 496); + drawMetric(p, connect_status.first, connect_status.second, 654); +} diff --git a/selfdrive/ui/qt/sidebar.h b/selfdrive/ui/qt/sidebar.h new file mode 100644 index 0000000000..6a2b7b6951 --- /dev/null +++ b/selfdrive/ui/qt/sidebar.h @@ -0,0 +1,66 @@ +#pragma once + +#include + +#include +#include + +#include "selfdrive/ui/ui.h" +#include "selfdrive/ui/qt/network/networking.h" + +typedef QPair, QColor> ItemStatus; +Q_DECLARE_METATYPE(ItemStatus); + +class Sidebar : public QFrame { + Q_OBJECT + Q_PROPERTY(ItemStatus connectStatus MEMBER connect_status NOTIFY valueChanged); + Q_PROPERTY(ItemStatus pandaStatus MEMBER panda_status NOTIFY valueChanged); + Q_PROPERTY(ItemStatus tempStatus MEMBER temp_status NOTIFY valueChanged); + Q_PROPERTY(QString netType MEMBER net_type NOTIFY valueChanged); + Q_PROPERTY(int netStrength MEMBER net_strength NOTIFY valueChanged); + Q_PROPERTY(bool recordingAudio MEMBER recording_audio NOTIFY valueChanged); + +public: + explicit Sidebar(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); + void valueChanged(); + +public slots: + void offroadTransition(bool offroad); + void updateState(const UIState &s); + +protected: + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void drawMetric(QPainter &p, const QPair &label, QColor c, int y); + + QPixmap home_img, flag_img, settings_img, mic_img, link_img; + bool onroad, recording_audio, flag_pressed, settings_pressed, mic_indicator_pressed; + const QMap network_type = { + {cereal::DeviceState::NetworkType::NONE, tr("--")}, + {cereal::DeviceState::NetworkType::WIFI, tr("Wi-Fi")}, + {cereal::DeviceState::NetworkType::ETHERNET, tr("ETH")}, + {cereal::DeviceState::NetworkType::CELL2_G, tr("2G")}, + {cereal::DeviceState::NetworkType::CELL3_G, tr("3G")}, + {cereal::DeviceState::NetworkType::CELL4_G, tr("LTE")}, + {cereal::DeviceState::NetworkType::CELL5_G, tr("5G")} + }; + + const QRect home_btn = QRect(60, 860, 180, 180); + const QRect settings_btn = QRect(50, 35, 200, 117); + const QRect mic_indicator_btn = QRect(158, 252, 75, 40); + const QColor good_color = QColor(255, 255, 255); + const QColor warning_color = QColor(218, 202, 37); + const QColor danger_color = QColor(201, 34, 49); + + ItemStatus connect_status, panda_status, temp_status; + QString net_type; + int net_strength = 0; + +private: + std::unique_ptr pm; + Networking *networking = nullptr; +}; diff --git a/selfdrive/ui/qt/util.cc b/selfdrive/ui/qt/util.cc new file mode 100644 index 0000000000..493c203977 --- /dev/null +++ b/selfdrive/ui/qt/util.cc @@ -0,0 +1,228 @@ +#include "selfdrive/ui/qt/util.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/swaglog.h" +#include "common/util.h" +#include "system/hardware/hw.h" + +QString getVersion() { + static QString version = QString::fromStdString(Params().get("Version")); + return version; +} + +QString getBrand() { + return QObject::tr("openpilot"); +} + +QString getUserAgent() { + return "openpilot-" + getVersion(); +} + +std::optional getDongleId() { + std::string id = Params().get("DongleId"); + + if (!id.empty() && (id != "UnregisteredDevice")) { + return QString::fromStdString(id); + } else { + return {}; + } +} + +QMap getSupportedLanguages() { + QFile f(":/languages.json"); + f.open(QIODevice::ReadOnly | QIODevice::Text); + QString val = f.readAll(); + + QJsonObject obj = QJsonDocument::fromJson(val.toUtf8()).object(); + QMap map; + for (auto key : obj.keys()) { + map[key] = obj[key].toString(); + } + return map; +} + +QString timeAgo(const QDateTime &date) { + if (!util::system_time_valid()) { + return date.date().toString(); + } + + int diff = date.secsTo(QDateTime::currentDateTimeUtc()); + + QString s; + if (diff < 60) { + s = QObject::tr("now"); + } else if (diff < 60 * 60) { + int minutes = diff / 60; + s = QObject::tr("%n minute(s) ago", "", minutes); + } else if (diff < 60 * 60 * 24) { + int hours = diff / (60 * 60); + s = QObject::tr("%n hour(s) ago", "", hours); + } else if (diff < 3600 * 24 * 7) { + int days = diff / (60 * 60 * 24); + s = QObject::tr("%n day(s) ago", "", days); + } else { + s = date.date().toString(); + } + + return s; +} + +void setQtSurfaceFormat() { + QSurfaceFormat fmt; +#ifdef __APPLE__ + fmt.setVersion(3, 2); + fmt.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + fmt.setRenderableType(QSurfaceFormat::OpenGL); +#else + fmt.setRenderableType(QSurfaceFormat::OpenGLES); +#endif + fmt.setSamples(16); + fmt.setStencilBufferSize(1); + QSurfaceFormat::setDefaultFormat(fmt); +} + +void sigTermHandler(int s) { + std::signal(s, SIG_DFL); + qApp->quit(); +} + +void initApp(int argc, char *argv[], bool disable_hidpi) { + Hardware::set_display_power(true); + Hardware::set_brightness(65); + + // setup signal handlers to exit gracefully + std::signal(SIGINT, sigTermHandler); + std::signal(SIGTERM, sigTermHandler); + + QString app_dir; +#ifdef __APPLE__ + // Get the devicePixelRatio, and scale accordingly to maintain 1:1 rendering + QApplication tmp(argc, argv); + app_dir = QCoreApplication::applicationDirPath(); + if (disable_hidpi) { + qputenv("QT_SCALE_FACTOR", QString::number(1.0 / tmp.devicePixelRatio()).toLocal8Bit()); + } +#else + app_dir = QFileInfo(util::readlink("/proc/self/exe").c_str()).path(); +#endif + + qputenv("QT_DBL_CLICK_DIST", QByteArray::number(150)); + // ensure the current dir matches the exectuable's directory + QDir::setCurrent(app_dir); + + setQtSurfaceFormat(); +} + +void swagLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + static std::map levels = { + {QtMsgType::QtDebugMsg, CLOUDLOG_DEBUG}, + {QtMsgType::QtInfoMsg, CLOUDLOG_INFO}, + {QtMsgType::QtWarningMsg, CLOUDLOG_WARNING}, + {QtMsgType::QtCriticalMsg, CLOUDLOG_ERROR}, + {QtMsgType::QtSystemMsg, CLOUDLOG_ERROR}, + {QtMsgType::QtFatalMsg, CLOUDLOG_CRITICAL}, + }; + + std::string file, function; + if (context.file != nullptr) file = context.file; + if (context.function != nullptr) function = context.function; + + auto bts = msg.toUtf8(); + cloudlog_e(levels[type], file.c_str(), context.line, function.c_str(), "%s", bts.constData()); +} + + +QWidget* topWidget(QWidget* widget) { + while (widget->parentWidget() != nullptr) widget=widget->parentWidget(); + return widget; +} + +QPixmap loadPixmap(const QString &fileName, const QSize &size, Qt::AspectRatioMode aspectRatioMode) { + if (size.isEmpty()) { + return QPixmap(fileName); + } else { + return QPixmap(fileName).scaled(size, aspectRatioMode, Qt::SmoothTransformation); + } +} + +static QHash load_bootstrap_icons() { + QHash icons; + + QFile f(":/bootstrap-icons.svg"); + if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { + QDomDocument xml; + xml.setContent(&f); + QDomNode n = xml.documentElement().firstChild(); + while (!n.isNull()) { + QDomElement e = n.toElement(); + if (!e.isNull() && e.hasAttribute("id")) { + QString svg_str; + QTextStream stream(&svg_str); + n.save(stream, 0); + svg_str.replace("", ""); + icons[e.attribute("id")] = svg_str.toUtf8(); + } + n = n.nextSibling(); + } + } + return icons; +} + +QPixmap bootstrapPixmap(const QString &id) { + static QHash icons = load_bootstrap_icons(); + + QPixmap pixmap; + if (auto it = icons.find(id); it != icons.end()) { + pixmap.loadFromData(it.value(), "svg"); + } + return pixmap; +} + +bool hasLongitudinalControl(const cereal::CarParams::Reader &car_params) { + // Using the experimental longitudinal toggle, returns whether longitudinal control + // will be active without needing a restart of openpilot + return car_params.getAlphaLongitudinalAvailable() + ? Params().getBool("AlphaLongitudinalEnabled") + : car_params.getOpenpilotLongitudinalControl(); +} + +// ParamWatcher + +ParamWatcher::ParamWatcher(QObject *parent) : QObject(parent) { + watcher = new QFileSystemWatcher(this); + QObject::connect(watcher, &QFileSystemWatcher::fileChanged, this, &ParamWatcher::fileChanged); +} + +void ParamWatcher::fileChanged(const QString &path) { + auto param_name = QFileInfo(path).fileName(); + auto param_value = QString::fromStdString(params.get(param_name.toStdString())); + + auto it = params_hash.find(param_name); + bool content_changed = (it == params_hash.end()) || (it.value() != param_value); + params_hash[param_name] = param_value; + // emit signal when the content changes. + if (content_changed) { + emit paramChanged(param_name, param_value); + } +} + +void ParamWatcher::addParam(const QString ¶m_name) { + watcher->addPath(QString::fromStdString(params.getParamPath(param_name.toStdString()))); +} diff --git a/selfdrive/ui/qt/util.h b/selfdrive/ui/qt/util.h new file mode 100644 index 0000000000..2bf1a70a62 --- /dev/null +++ b/selfdrive/ui/qt/util.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cereal/gen/cpp/car.capnp.h" +#include "common/params.h" + +QString getVersion(); +QString getBrand(); +QString getUserAgent(); +std::optional getDongleId(); +QMap getSupportedLanguages(); +void setQtSurfaceFormat(); +void sigTermHandler(int s); +QString timeAgo(const QDateTime &date); +void swagLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); +void initApp(int argc, char *argv[], bool disable_hidpi = true); +QWidget* topWidget(QWidget* widget); +QPixmap loadPixmap(const QString &fileName, const QSize &size = {}, Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio); +QPixmap bootstrapPixmap(const QString &id); +bool hasLongitudinalControl(const cereal::CarParams::Reader &car_params); + +struct InterFont : public QFont { + InterFont(int pixel_size, QFont::Weight weight = QFont::Normal) : QFont("Inter") { + setPixelSize(pixel_size); + setWeight(weight); + } +}; + +class ParamWatcher : public QObject { + Q_OBJECT + +public: + ParamWatcher(QObject *parent); + void addParam(const QString ¶m_name); + +signals: + void paramChanged(const QString ¶m_name, const QString ¶m_value); + +private: + void fileChanged(const QString &path); + + QFileSystemWatcher *watcher; + QHash params_hash; + Params params; +}; diff --git a/selfdrive/ui/qt/widgets/cameraview.cc b/selfdrive/ui/qt/widgets/cameraview.cc new file mode 100644 index 0000000000..5f533cd090 --- /dev/null +++ b/selfdrive/ui/qt/widgets/cameraview.cc @@ -0,0 +1,365 @@ +#include "selfdrive/ui/qt/widgets/cameraview.h" + +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include + +namespace { + +const char frame_vertex_shader[] = +#ifdef __APPLE__ + "#version 330 core\n" +#else + "#version 300 es\n" +#endif + "layout(location = 0) in vec4 aPosition;\n" + "layout(location = 1) in vec2 aTexCoord;\n" + "uniform mat4 uTransform;\n" + "out vec2 vTexCoord;\n" + "void main() {\n" + " gl_Position = uTransform * aPosition;\n" + " vTexCoord = aTexCoord;\n" + "}\n"; + +const char frame_fragment_shader[] = +#ifdef __TICI__ + "#version 300 es\n" + "#extension GL_OES_EGL_image_external_essl3 : enable\n" + "precision mediump float;\n" + "uniform samplerExternalOES uTexture;\n" + "in vec2 vTexCoord;\n" + "out vec4 colorOut;\n" + "void main() {\n" + " colorOut = texture(uTexture, vTexCoord);\n" + // gamma to improve worst case visibility when dark + " colorOut.rgb = pow(colorOut.rgb, vec3(1.0/1.28));\n" + "}\n"; +#else +#ifdef __APPLE__ + "#version 330 core\n" +#else + "#version 300 es\n" + "precision mediump float;\n" +#endif + "uniform sampler2D uTextureY;\n" + "uniform sampler2D uTextureUV;\n" + "in vec2 vTexCoord;\n" + "out vec4 colorOut;\n" + "void main() {\n" + " float y = texture(uTextureY, vTexCoord).r;\n" + " vec2 uv = texture(uTextureUV, vTexCoord).rg - 0.5;\n" + " float r = y + 1.402 * uv.y;\n" + " float g = y - 0.344 * uv.x - 0.714 * uv.y;\n" + " float b = y + 1.772 * uv.x;\n" + " colorOut = vec4(r, g, b, 1.0);\n" + "}\n"; +#endif + +} // namespace + +CameraWidget::CameraWidget(std::string stream_name, VisionStreamType type, QWidget* parent) : + stream_name(stream_name), active_stream_type(type), requested_stream_type(type), QOpenGLWidget(parent) { + setAttribute(Qt::WA_OpaquePaintEvent); + qRegisterMetaType>("availableStreams"); + QObject::connect(this, &CameraWidget::vipcThreadConnected, this, &CameraWidget::vipcConnected, Qt::BlockingQueuedConnection); + QObject::connect(this, &CameraWidget::vipcThreadFrameReceived, this, &CameraWidget::vipcFrameReceived, Qt::QueuedConnection); + QObject::connect(this, &CameraWidget::vipcAvailableStreamsUpdated, this, &CameraWidget::availableStreamsUpdated, Qt::QueuedConnection); + QObject::connect(QApplication::instance(), &QCoreApplication::aboutToQuit, this, &CameraWidget::stopVipcThread); +} + +CameraWidget::~CameraWidget() { + makeCurrent(); + stopVipcThread(); + if (isValid()) { + glDeleteVertexArrays(1, &frame_vao); + glDeleteBuffers(1, &frame_vbo); + glDeleteBuffers(1, &frame_ibo); +#ifndef __TICI__ + glDeleteTextures(2, textures); +#endif + } + doneCurrent(); +} + +// Qt uses device-independent pixels, depending on platform this may be +// different to what OpenGL uses +int CameraWidget::glWidth() { + return width() * devicePixelRatio(); +} + +int CameraWidget::glHeight() { + return height() * devicePixelRatio(); +} + +void CameraWidget::initializeGL() { + initializeOpenGLFunctions(); + + program = std::make_unique(context()); + bool ret = program->addShaderFromSourceCode(QOpenGLShader::Vertex, frame_vertex_shader); + assert(ret); + ret = program->addShaderFromSourceCode(QOpenGLShader::Fragment, frame_fragment_shader); + assert(ret); + + program->link(); + GLint frame_pos_loc = program->attributeLocation("aPosition"); + GLint frame_texcoord_loc = program->attributeLocation("aTexCoord"); + + auto [x1, x2, y1, y2] = requested_stream_type == VISION_STREAM_DRIVER ? std::tuple(0.f, 1.f, 1.f, 0.f) : std::tuple(1.f, 0.f, 1.f, 0.f); + const uint8_t frame_indicies[] = {0, 1, 2, 0, 2, 3}; + const float frame_coords[4][4] = { + {-1.0, -1.0, x2, y1}, // bl + {-1.0, 1.0, x2, y2}, // tl + { 1.0, 1.0, x1, y2}, // tr + { 1.0, -1.0, x1, y1}, // br + }; + + glGenVertexArrays(1, &frame_vao); + glBindVertexArray(frame_vao); + glGenBuffers(1, &frame_vbo); + glBindBuffer(GL_ARRAY_BUFFER, frame_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(frame_coords), frame_coords, GL_STATIC_DRAW); + glEnableVertexAttribArray(frame_pos_loc); + glVertexAttribPointer(frame_pos_loc, 2, GL_FLOAT, GL_FALSE, + sizeof(frame_coords[0]), (const void *)0); + glEnableVertexAttribArray(frame_texcoord_loc); + glVertexAttribPointer(frame_texcoord_loc, 2, GL_FLOAT, GL_FALSE, + sizeof(frame_coords[0]), (const void *)(sizeof(float) * 2)); + glGenBuffers(1, &frame_ibo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, frame_ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(frame_indicies), frame_indicies, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + glUseProgram(program->programId()); + +#ifdef __TICI__ + glUniform1i(program->uniformLocation("uTexture"), 0); +#else + glGenTextures(2, textures); + glUniform1i(program->uniformLocation("uTextureY"), 0); + glUniform1i(program->uniformLocation("uTextureUV"), 1); +#endif +} + +void CameraWidget::showEvent(QShowEvent *event) { + if (!vipc_thread) { + clearFrames(); + vipc_thread = new QThread(); + connect(vipc_thread, &QThread::started, [=]() { vipcThread(); }); + connect(vipc_thread, &QThread::finished, vipc_thread, &QObject::deleteLater); + vipc_thread->start(); + } +} + +void CameraWidget::stopVipcThread() { + makeCurrent(); + if (vipc_thread) { + vipc_thread->requestInterruption(); + vipc_thread->quit(); + vipc_thread->wait(); + vipc_thread = nullptr; + } + +#ifdef __TICI__ + EGLDisplay egl_display = eglGetCurrentDisplay(); + assert(egl_display != EGL_NO_DISPLAY); + for (auto &pair : egl_images) { + eglDestroyImageKHR(egl_display, pair.second); + assert(eglGetError() == EGL_SUCCESS); + } + egl_images.clear(); +#endif +} + +void CameraWidget::availableStreamsUpdated(std::set streams) { + available_streams = streams; +} + +mat4 CameraWidget::calcFrameMatrix() { + // Scale the frame to fit the widget while maintaining the aspect ratio. + float widget_aspect_ratio = (float)width() / height(); + float frame_aspect_ratio = (float)stream_width / stream_height; + float zx = std::min(frame_aspect_ratio / widget_aspect_ratio, 1.0f); + float zy = std::min(widget_aspect_ratio / frame_aspect_ratio, 1.0f); + + return mat4{{ + zx, 0.0, 0.0, 0.0, + 0.0, zy, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }}; +} + +void CameraWidget::paintGL() { + glClearColor(bg.redF(), bg.greenF(), bg.blueF(), bg.alphaF()); + glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + std::lock_guard lk(frame_lock); + if (frames.empty()) return; + + int frame_idx = frames.size() - 1; + + // Always draw latest frame until sync logic is more stable + // for (frame_idx = 0; frame_idx < frames.size() - 1; frame_idx++) { + // if (frames[frame_idx].first == draw_frame_id) break; + // } + + // Log duplicate/dropped frames + if (frames[frame_idx].first == prev_frame_id) { + qDebug() << "Drawing same frame twice" << frames[frame_idx].first; + } else if (frames[frame_idx].first != prev_frame_id + 1) { + qDebug() << "Skipped frame" << frames[frame_idx].first; + } + prev_frame_id = frames[frame_idx].first; + VisionBuf *frame = frames[frame_idx].second; + assert(frame != nullptr); + + auto frame_mat = calcFrameMatrix(); + + glViewport(0, 0, glWidth(), glHeight()); + glBindVertexArray(frame_vao); + glUseProgram(program->programId()); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +#ifdef __TICI__ + // no frame copy + glActiveTexture(GL_TEXTURE0); + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_images[frame->idx]); + assert(glGetError() == GL_NO_ERROR); +#else + // fallback to copy + glPixelStorei(GL_UNPACK_ROW_LENGTH, stream_stride); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width, stream_height, GL_RED, GL_UNSIGNED_BYTE, frame->y); + assert(glGetError() == GL_NO_ERROR); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, stream_stride/2); + glActiveTexture(GL_TEXTURE0 + 1); + glBindTexture(GL_TEXTURE_2D, textures[1]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, stream_width/2, stream_height/2, GL_RG, GL_UNSIGNED_BYTE, frame->uv); + assert(glGetError() == GL_NO_ERROR); +#endif + + glUniformMatrix4fv(program->uniformLocation("uTransform"), 1, GL_TRUE, frame_mat.v); + glEnableVertexAttribArray(0); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (const void *)0); + glDisableVertexAttribArray(0); + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +} + +void CameraWidget::vipcConnected(VisionIpcClient *vipc_client) { + makeCurrent(); + stream_width = vipc_client->buffers[0].width; + stream_height = vipc_client->buffers[0].height; + stream_stride = vipc_client->buffers[0].stride; + +#ifdef __TICI__ + EGLDisplay egl_display = eglGetCurrentDisplay(); + assert(egl_display != EGL_NO_DISPLAY); + for (auto &pair : egl_images) { + eglDestroyImageKHR(egl_display, pair.second); + } + egl_images.clear(); + + for (int i = 0; i < vipc_client->num_buffers; i++) { // import buffers into OpenGL + int fd = dup(vipc_client->buffers[i].fd); // eglDestroyImageKHR will close, so duplicate + EGLint img_attrs[] = { + EGL_WIDTH, (int)vipc_client->buffers[i].width, + EGL_HEIGHT, (int)vipc_client->buffers[i].height, + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_NV12, + EGL_DMA_BUF_PLANE0_FD_EXT, fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, (int)vipc_client->buffers[i].stride, + EGL_DMA_BUF_PLANE1_FD_EXT, fd, + EGL_DMA_BUF_PLANE1_OFFSET_EXT, (int)vipc_client->buffers[i].uv_offset, + EGL_DMA_BUF_PLANE1_PITCH_EXT, (int)vipc_client->buffers[i].stride, + EGL_NONE + }; + egl_images[i] = eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, 0, img_attrs); + assert(eglGetError() == EGL_SUCCESS); + } +#else + glBindTexture(GL_TEXTURE_2D, textures[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, stream_width, stream_height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr); + assert(glGetError() == GL_NO_ERROR); + + glBindTexture(GL_TEXTURE_2D, textures[1]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, stream_width/2, stream_height/2, 0, GL_RG, GL_UNSIGNED_BYTE, nullptr); + assert(glGetError() == GL_NO_ERROR); +#endif +} + +void CameraWidget::vipcFrameReceived() { + update(); +} + +void CameraWidget::vipcThread() { + VisionStreamType cur_stream = requested_stream_type; + std::unique_ptr vipc_client; + VisionIpcBufExtra meta_main = {0}; + + while (!QThread::currentThread()->isInterruptionRequested()) { + if (!vipc_client || cur_stream != requested_stream_type) { + clearFrames(); + qDebug().nospace() << "connecting to stream " << requested_stream_type << ", was connected to " << cur_stream; + cur_stream = requested_stream_type; + vipc_client.reset(new VisionIpcClient(stream_name, cur_stream, false)); + } + active_stream_type = cur_stream; + + if (!vipc_client->connected) { + clearFrames(); + auto streams = VisionIpcClient::getAvailableStreams(stream_name, false); + if (streams.empty()) { + QThread::msleep(100); + continue; + } + emit vipcAvailableStreamsUpdated(streams); + + if (!vipc_client->connect(false)) { + QThread::msleep(100); + continue; + } + emit vipcThreadConnected(vipc_client.get()); + } + + if (VisionBuf *buf = vipc_client->recv(&meta_main, 1000)) { + { + std::lock_guard lk(frame_lock); + frames.push_back(std::make_pair(meta_main.frame_id, buf)); + while (frames.size() > FRAME_BUFFER_SIZE) { + frames.pop_front(); + } + } + emit vipcThreadFrameReceived(); + } else { + if (!isVisible()) { + vipc_client->connected = false; + } + } + } +} + +void CameraWidget::clearFrames() { + std::lock_guard lk(frame_lock); + frames.clear(); + available_streams.clear(); +} diff --git a/selfdrive/ui/qt/widgets/cameraview.h b/selfdrive/ui/qt/widgets/cameraview.h new file mode 100644 index 0000000000..598603a08a --- /dev/null +++ b/selfdrive/ui/qt/widgets/cameraview.h @@ -0,0 +1,89 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __TICI__ +#define EGL_EGLEXT_PROTOTYPES +#define EGL_NO_X11 +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#include +#include +#include +#endif + +#include "msgq/visionipc/visionipc_client.h" +#include "selfdrive/ui/ui.h" + +const int FRAME_BUFFER_SIZE = 5; + +class CameraWidget : public QOpenGLWidget, protected QOpenGLFunctions { + Q_OBJECT + +public: + using QOpenGLWidget::QOpenGLWidget; + explicit CameraWidget(std::string stream_name, VisionStreamType stream_type, QWidget* parent = nullptr); + ~CameraWidget(); + void setBackgroundColor(const QColor &color) { bg = color; } + void setFrameId(int frame_id) { draw_frame_id = frame_id; } + void setStreamType(VisionStreamType type) { requested_stream_type = type; } + VisionStreamType getStreamType() { return active_stream_type; } + void stopVipcThread(); + +signals: + void clicked(); + void vipcThreadConnected(VisionIpcClient *); + void vipcThreadFrameReceived(); + void vipcAvailableStreamsUpdated(std::set); + +protected: + void paintGL() override; + void initializeGL() override; + void showEvent(QShowEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override { emit clicked(); } + virtual mat4 calcFrameMatrix(); + void vipcThread(); + void clearFrames(); + + int glWidth(); + int glHeight(); + + GLuint frame_vao, frame_vbo, frame_ibo; + GLuint textures[2]; + std::unique_ptr program; + QColor bg = QColor("#000000"); + +#ifdef __TICI__ + std::map egl_images; +#endif + + std::string stream_name; + int stream_width = 0; + int stream_height = 0; + int stream_stride = 0; + std::atomic active_stream_type; + std::atomic requested_stream_type; + std::set available_streams; + QThread *vipc_thread = nullptr; + std::recursive_mutex frame_lock; + std::deque> frames; + uint32_t draw_frame_id = 0; + uint32_t prev_frame_id = 0; + +protected slots: + void vipcConnected(VisionIpcClient *vipc_client); + void vipcFrameReceived(); + void availableStreamsUpdated(std::set streams); +}; + +Q_DECLARE_METATYPE(std::set); diff --git a/selfdrive/ui/qt/widgets/controls.cc b/selfdrive/ui/qt/widgets/controls.cc new file mode 100644 index 0000000000..40dda971f5 --- /dev/null +++ b/selfdrive/ui/qt/widgets/controls.cc @@ -0,0 +1,141 @@ +#include "selfdrive/ui/qt/widgets/controls.h" + +#include +#include + +AbstractControl::AbstractControl(const QString &title, const QString &desc, const QString &icon, QWidget *parent) : QFrame(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setMargin(0); + + hlayout = new QHBoxLayout; + hlayout->setMargin(0); + hlayout->setSpacing(20); + + // left icon + icon_label = new QLabel(this); + hlayout->addWidget(icon_label); + if (!icon.isEmpty()) { + icon_pixmap = QPixmap(icon).scaledToWidth(80, Qt::SmoothTransformation); + icon_label->setPixmap(icon_pixmap); + icon_label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + } + icon_label->setVisible(!icon.isEmpty()); + + // title + title_label = new QPushButton(title); + title_label->setFixedHeight(120); + title_label->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left; border: none;"); + hlayout->addWidget(title_label, 1); + + // value next to control button + value = new ElidedLabel(); + value->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + value->setStyleSheet("color: #aaaaaa"); + hlayout->addWidget(value); + + main_layout->addLayout(hlayout); + + // description + description = new QLabel(desc); + description->setContentsMargins(40, 20, 40, 20); + description->setStyleSheet("font-size: 40px; color: grey"); + description->setWordWrap(true); + description->setVisible(false); + main_layout->addWidget(description); + + connect(title_label, &QPushButton::clicked, [=]() { + if (!description->isVisible()) { + emit showDescriptionEvent(); + } + + if (!description->text().isEmpty()) { + description->setVisible(!description->isVisible()); + } + }); + + main_layout->addStretch(); +} + +void AbstractControl::hideEvent(QHideEvent *e) { + if (description != nullptr) { + description->hide(); + } +} + +// controls + +ButtonControl::ButtonControl(const QString &title, const QString &text, const QString &desc, QWidget *parent) : AbstractControl(title, desc, "", parent) { + btn.setText(text); + btn.setStyleSheet(R"( + QPushButton { + padding: 0; + border-radius: 50px; + font-size: 35px; + font-weight: 500; + color: #E4E4E4; + background-color: #393939; + } + QPushButton:pressed { + background-color: #4a4a4a; + } + QPushButton:disabled { + color: #33E4E4E4; + } + )"); + btn.setFixedSize(250, 100); + QObject::connect(&btn, &QPushButton::clicked, this, &ButtonControl::clicked); + hlayout->addWidget(&btn); +} + +// ElidedLabel + +ElidedLabel::ElidedLabel(QWidget *parent) : ElidedLabel({}, parent) {} + +ElidedLabel::ElidedLabel(const QString &text, QWidget *parent) : QLabel(text.trimmed(), parent) { + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + setMinimumWidth(1); +} + +void ElidedLabel::resizeEvent(QResizeEvent* event) { + QLabel::resizeEvent(event); + lastText_ = elidedText_ = ""; +} + +void ElidedLabel::paintEvent(QPaintEvent *event) { + const QString curText = text(); + if (curText != lastText_) { + elidedText_ = fontMetrics().elidedText(curText, Qt::ElideRight, contentsRect().width()); + lastText_ = curText; + } + + QPainter painter(this); + drawFrame(&painter); + QStyleOption opt; + opt.initFrom(this); + style()->drawItemText(&painter, contentsRect(), alignment(), opt.palette, isEnabled(), elidedText_, foregroundRole()); +} + +// ParamControl + +ParamControl::ParamControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, QWidget *parent) + : ToggleControl(title, desc, icon, false, parent) { + key = param.toStdString(); + QObject::connect(this, &ParamControl::toggleFlipped, this, &ParamControl::toggleClicked); +} + +void ParamControl::toggleClicked(bool state) { + auto do_confirm = [this]() { + QString content("

    " + title_label->text() + "


    " + "

    " + getDescription() + "

    "); + return ConfirmationDialog(content, tr("Enable"), tr("Cancel"), true, this).exec(); + }; + + bool confirmed = store_confirm && params.getBool(key + "Confirmed"); + if (!confirm || confirmed || !state || do_confirm()) { + if (store_confirm && state) params.putBool(key + "Confirmed", true); + params.putBool(key, state); + setIcon(state); + } else { + toggle.togglePosition(); + } +} diff --git a/selfdrive/ui/qt/widgets/controls.h b/selfdrive/ui/qt/widgets/controls.h new file mode 100644 index 0000000000..3342de5324 --- /dev/null +++ b/selfdrive/ui/qt/widgets/controls.h @@ -0,0 +1,319 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common/params.h" +#include "selfdrive/ui/qt/widgets/input.h" +#include "selfdrive/ui/qt/widgets/toggle.h" + +class ElidedLabel : public QLabel { + Q_OBJECT + +public: + explicit ElidedLabel(QWidget *parent = 0); + explicit ElidedLabel(const QString &text, QWidget *parent = 0); + +signals: + void clicked(); + +protected: + void paintEvent(QPaintEvent *event) override; + void resizeEvent(QResizeEvent* event) override; + void mouseReleaseEvent(QMouseEvent *event) override { + if (rect().contains(event->pos())) { + emit clicked(); + } + } + QString lastText_, elidedText_; +}; + + +class AbstractControl : public QFrame { + Q_OBJECT + +public: + void setDescription(const QString &desc) { + if (description) description->setText(desc); + } + + void setTitle(const QString &title) { + title_label->setText(title); + } + + void setValue(const QString &val) { + value->setText(val); + } + + const QString getDescription() { + return description->text(); + } + + QLabel *icon_label; + QPixmap icon_pixmap; + +public slots: + void showDescription() { + description->setVisible(true); + } + +signals: + void showDescriptionEvent(); + +protected: + AbstractControl(const QString &title, const QString &desc = "", const QString &icon = "", QWidget *parent = nullptr); + void hideEvent(QHideEvent *e) override; + + QHBoxLayout *hlayout; + QPushButton *title_label; + +private: + ElidedLabel *value; + QLabel *description = nullptr; +}; + +// widget to display a value +class LabelControl : public AbstractControl { + Q_OBJECT + +public: + LabelControl(const QString &title, const QString &text = "", const QString &desc = "", QWidget *parent = nullptr) : AbstractControl(title, desc, "", parent) { + label.setText(text); + label.setAlignment(Qt::AlignRight | Qt::AlignVCenter); + hlayout->addWidget(&label); + } + void setText(const QString &text) { label.setText(text); } + +private: + ElidedLabel label; +}; + +// widget for a button with a label +class ButtonControl : public AbstractControl { + Q_OBJECT + +public: + ButtonControl(const QString &title, const QString &text, const QString &desc = "", QWidget *parent = nullptr); + inline void setText(const QString &text) { btn.setText(text); } + inline QString text() const { return btn.text(); } + +signals: + void clicked(); + +public slots: + void setEnabled(bool enabled) { btn.setEnabled(enabled); } + +private: + QPushButton btn; +}; + +class ToggleControl : public AbstractControl { + Q_OBJECT + +public: + ToggleControl(const QString &title, const QString &desc = "", const QString &icon = "", const bool state = false, QWidget *parent = nullptr) : AbstractControl(title, desc, icon, parent) { + toggle.setFixedSize(150, 100); + if (state) { + toggle.togglePosition(); + } + hlayout->addWidget(&toggle); + QObject::connect(&toggle, &Toggle::stateChanged, this, &ToggleControl::toggleFlipped); + } + + void setEnabled(bool enabled) { + toggle.setEnabled(enabled); + toggle.update(); + } + +signals: + void toggleFlipped(bool state); + +protected: + Toggle toggle; +}; + +// widget to toggle params +class ParamControl : public ToggleControl { + Q_OBJECT + +public: + ParamControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, QWidget *parent = nullptr); + void setConfirmation(bool _confirm, bool _store_confirm) { + confirm = _confirm; + store_confirm = _store_confirm; + } + + void setActiveIcon(const QString &icon) { + active_icon_pixmap = QPixmap(icon).scaledToWidth(80, Qt::SmoothTransformation); + } + + void refresh() { + bool state = params.getBool(key); + if (state != toggle.on) { + toggle.togglePosition(); + setIcon(state); + } + } + + void showEvent(QShowEvent *event) override { + refresh(); + } + +private: + void toggleClicked(bool state); + void setIcon(bool state) { + if (state && !active_icon_pixmap.isNull()) { + icon_label->setPixmap(active_icon_pixmap); + } else if (!icon_pixmap.isNull()) { + icon_label->setPixmap(icon_pixmap); + } + } + + std::string key; + Params params; + QPixmap active_icon_pixmap; + bool confirm = false; + bool store_confirm = false; +}; + +class MultiButtonControl : public AbstractControl { + Q_OBJECT +public: + MultiButtonControl(const QString &title, const QString &desc, const QString &icon, + const std::vector &button_texts, const int minimum_button_width = 225) : AbstractControl(title, desc, icon) { + const QString style = R"( + QPushButton { + border-radius: 50px; + font-size: 40px; + font-weight: 500; + height:100px; + padding: 0 25 0 25; + color: #E4E4E4; + background-color: #393939; + } + QPushButton:pressed { + background-color: #4a4a4a; + } + QPushButton:checked:enabled { + background-color: #33Ab4C; + } + QPushButton:checked:disabled { + background-color: #9933Ab4C; + } + QPushButton:disabled { + color: #33E4E4E4; + } + )"; + + button_group = new QButtonGroup(this); + button_group->setExclusive(true); + for (int i = 0; i < button_texts.size(); i++) { + QPushButton *button = new QPushButton(button_texts[i], this); + button->setCheckable(true); + button->setChecked(i == 0); + button->setStyleSheet(style); + button->setMinimumWidth(minimum_button_width); + hlayout->addWidget(button); + button_group->addButton(button, i); + } + + QObject::connect(button_group, QOverload::of(&QButtonGroup::buttonClicked), this, &MultiButtonControl::buttonClicked); + } + + void setEnabled(bool enable) { + for (auto btn : button_group->buttons()) { + btn->setEnabled(enable); + } + } + + void setCheckedButton(int id) { + button_group->button(id)->setChecked(true); + } + +signals: + void buttonClicked(int id); + +protected: + QButtonGroup *button_group; +}; + +class ButtonParamControl : public MultiButtonControl { + Q_OBJECT +public: + ButtonParamControl(const QString ¶m, const QString &title, const QString &desc, const QString &icon, + const std::vector &button_texts, const int minimum_button_width = 225) : MultiButtonControl(title, desc, icon, + button_texts, minimum_button_width) { + key = param.toStdString(); + int value = atoi(params.get(key).c_str()); + + if (value > 0 && value < button_group->buttons().size()) { + button_group->button(value)->setChecked(true); + } + + QObject::connect(this, QOverload::of(&MultiButtonControl::buttonClicked), [=](int id) { + params.put(key, std::to_string(id)); + }); + } + + void refresh() { + int value = atoi(params.get(key).c_str()); + button_group->button(value)->setChecked(true); + } + + void showEvent(QShowEvent *event) override { + refresh(); + } + +private: + std::string key; + Params params; +}; + +class ListWidget : public QWidget { + Q_OBJECT + public: + explicit ListWidget(QWidget *parent = 0) : QWidget(parent), outer_layout(this) { + outer_layout.setMargin(0); + outer_layout.setSpacing(0); + outer_layout.addLayout(&inner_layout); + inner_layout.setMargin(0); + inner_layout.setSpacing(25); // default spacing is 25 + outer_layout.addStretch(1); + } + inline void addItem(QWidget *w) { inner_layout.addWidget(w); } + inline void addItem(QLayout *layout) { inner_layout.addLayout(layout); } + inline void setSpacing(int spacing) { inner_layout.setSpacing(spacing); } + +private: + void paintEvent(QPaintEvent *) override { + QPainter p(this); + p.setPen(Qt::gray); + for (int i = 0; i < inner_layout.count() - 1; ++i) { + QWidget *widget = inner_layout.itemAt(i)->widget(); + if (widget == nullptr || widget->isVisible()) { + QRect r = inner_layout.itemAt(i)->geometry(); + int bottom = r.bottom() + inner_layout.spacing() / 2; + p.drawLine(r.left() + 40, bottom, r.right() - 40, bottom); + } + } + } + QVBoxLayout outer_layout; + QVBoxLayout inner_layout; +}; + +// convenience class for wrapping layouts +class LayoutWidget : public QWidget { + Q_OBJECT + +public: + LayoutWidget(QLayout *l, QWidget *parent = nullptr) : QWidget(parent) { + setLayout(l); + } +}; diff --git a/selfdrive/ui/qt/widgets/input.cc b/selfdrive/ui/qt/widgets/input.cc new file mode 100644 index 0000000000..0cbf14931b --- /dev/null +++ b/selfdrive/ui/qt/widgets/input.cc @@ -0,0 +1,336 @@ +#include "selfdrive/ui/qt/widgets/input.h" + +#include +#include + +#include "system/hardware/hw.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/widgets/scrollview.h" + + +DialogBase::DialogBase(QWidget *parent) : QDialog(parent) { + Q_ASSERT(parent != nullptr); + parent->installEventFilter(this); + + setStyleSheet(R"( + * { + outline: none; + color: white; + font-family: Inter; + } + DialogBase { + background-color: black; + } + QPushButton { + height: 160; + font-size: 55px; + font-weight: 400; + border-radius: 10px; + color: white; + background-color: #333333; + } + QPushButton:pressed { + background-color: #444444; + } + )"); +} + +bool DialogBase::eventFilter(QObject *o, QEvent *e) { + if (o == parent() && e->type() == QEvent::Hide) { + reject(); + } + return QDialog::eventFilter(o, e); +} + +int DialogBase::exec() { + setMainWindow(this); + return QDialog::exec(); +} + +InputDialog::InputDialog(const QString &title, QWidget *parent, const QString &subtitle, bool secret) : DialogBase(parent) { + main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(50, 55, 50, 50); + main_layout->setSpacing(0); + + // build header + QHBoxLayout *header_layout = new QHBoxLayout(); + + QVBoxLayout *vlayout = new QVBoxLayout; + header_layout->addLayout(vlayout); + label = new QLabel(title, this); + label->setStyleSheet("font-size: 90px; font-weight: bold;"); + vlayout->addWidget(label, 1, Qt::AlignTop | Qt::AlignLeft); + + if (!subtitle.isEmpty()) { + sublabel = new QLabel(subtitle, this); + sublabel->setStyleSheet("font-size: 55px; font-weight: light; color: #BDBDBD;"); + vlayout->addWidget(sublabel, 1, Qt::AlignTop | Qt::AlignLeft); + } + + QPushButton* cancel_btn = new QPushButton(tr("Cancel")); + cancel_btn->setFixedSize(386, 125); + cancel_btn->setStyleSheet(R"( + QPushButton { + font-size: 48px; + border-radius: 10px; + color: #E4E4E4; + background-color: #333333; + } + QPushButton:pressed { + background-color: #444444; + } + )"); + header_layout->addWidget(cancel_btn, 0, Qt::AlignRight); + QObject::connect(cancel_btn, &QPushButton::clicked, this, &InputDialog::reject); + QObject::connect(cancel_btn, &QPushButton::clicked, this, &InputDialog::cancel); + + main_layout->addLayout(header_layout); + + // text box + main_layout->addStretch(2); + + QWidget *textbox_widget = new QWidget; + textbox_widget->setObjectName("textbox"); + QHBoxLayout *textbox_layout = new QHBoxLayout(textbox_widget); + textbox_layout->setContentsMargins(50, 0, 50, 0); + + textbox_widget->setStyleSheet(R"( + #textbox { + margin-left: 50px; + margin-right: 50px; + border-radius: 0; + border-bottom: 3px solid #BDBDBD; + } + * { + border: none; + font-size: 80px; + font-weight: light; + background-color: transparent; + } + )"); + + line = new QLineEdit(); + line->setStyleSheet("lineedit-password-character: 8226; lineedit-password-mask-delay: 1500;"); + textbox_layout->addWidget(line, 1); + + if (secret) { + eye_btn = new QPushButton(); + eye_btn->setCheckable(true); + eye_btn->setFixedSize(150, 120); + QObject::connect(eye_btn, &QPushButton::toggled, [=](bool checked) { + if (checked) { + eye_btn->setIcon(QIcon(ASSET_PATH + "icons/eye_closed.svg")); + eye_btn->setIconSize(QSize(81, 54)); + line->setEchoMode(QLineEdit::Password); + } else { + eye_btn->setIcon(QIcon(ASSET_PATH + "icons/eye_open.svg")); + eye_btn->setIconSize(QSize(81, 44)); + line->setEchoMode(QLineEdit::Normal); + } + }); + eye_btn->toggle(); + eye_btn->setChecked(false); + textbox_layout->addWidget(eye_btn); + } + + main_layout->addWidget(textbox_widget, 0, Qt::AlignBottom); + main_layout->addSpacing(25); + + k = new Keyboard(this); + QObject::connect(k, &Keyboard::emitEnter, this, &InputDialog::handleEnter); + QObject::connect(k, &Keyboard::emitBackspace, this, [=]() { + line->backspace(); + }); + QObject::connect(k, &Keyboard::emitKey, this, [=](const QString &key) { + line->insert(key.left(1)); + }); + + main_layout->addWidget(k, 2, Qt::AlignBottom); +} + +QString InputDialog::getText(const QString &prompt, QWidget *parent, const QString &subtitle, + bool secret, int minLength, const QString &defaultText) { + InputDialog d(prompt, parent, subtitle, secret); + d.line->setText(defaultText); + d.setMinLength(minLength); + const int ret = d.exec(); + return ret ? d.text() : QString(); +} + +QString InputDialog::text() { + return line->text(); +} + +void InputDialog::show() { + setMainWindow(this); +} + +void InputDialog::handleEnter() { + if (line->text().length() >= minLength) { + done(QDialog::Accepted); + emitText(line->text()); + } else { + setMessage(tr("Need at least %n character(s)!", "", minLength), false); + } +} + +void InputDialog::setMessage(const QString &message, bool clearInputField) { + label->setText(message); + if (clearInputField) { + line->setText(""); + } +} + +void InputDialog::setMinLength(int length) { + minLength = length; +} + +// ConfirmationDialog + +ConfirmationDialog::ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, const QString &cancel_text, + const bool rich, QWidget *parent) : DialogBase(parent) { + QFrame *container = new QFrame(this); + container->setStyleSheet(R"( + QFrame { background-color: #1B1B1B; color: #C9C9C9; } + #confirm_btn { background-color: #465BEA; } + #confirm_btn:pressed { background-color: #3049F4; } + )"); + QVBoxLayout *main_layout = new QVBoxLayout(container); + main_layout->setContentsMargins(32, rich ? 32 : 120, 32, 32); + + QLabel *prompt = new QLabel(prompt_text, this); + prompt->setWordWrap(true); + prompt->setAlignment(rich ? Qt::AlignLeft : Qt::AlignHCenter); + prompt->setStyleSheet((rich ? "font-size: 42px; font-weight: light;" : "font-size: 70px; font-weight: bold;") + QString(" margin: 45px;")); + main_layout->addWidget(rich ? (QWidget*)new ScrollView(prompt, this) : (QWidget*)prompt, 1, Qt::AlignTop); + + // cancel + confirm buttons + QHBoxLayout *btn_layout = new QHBoxLayout(); + btn_layout->setSpacing(30); + main_layout->addLayout(btn_layout); + + if (cancel_text.length()) { + QPushButton* cancel_btn = new QPushButton(cancel_text); + btn_layout->addWidget(cancel_btn); + QObject::connect(cancel_btn, &QPushButton::clicked, this, &ConfirmationDialog::reject); + } + + if (confirm_text.length()) { + QPushButton* confirm_btn = new QPushButton(confirm_text); + confirm_btn->setObjectName("confirm_btn"); + btn_layout->addWidget(confirm_btn); + QObject::connect(confirm_btn, &QPushButton::clicked, this, &ConfirmationDialog::accept); + } + + QVBoxLayout *outer_layout = new QVBoxLayout(this); + int margin = rich ? 100 : 200; + outer_layout->setContentsMargins(margin, margin, margin, margin); + outer_layout->addWidget(container); +} + +bool ConfirmationDialog::alert(const QString &prompt_text, QWidget *parent) { + ConfirmationDialog d(prompt_text, tr("Ok"), "", false, parent); + return d.exec(); +} + +bool ConfirmationDialog::confirm(const QString &prompt_text, const QString &confirm_text, QWidget *parent) { + ConfirmationDialog d(prompt_text, confirm_text, tr("Cancel"), false, parent); + return d.exec(); +} + +bool ConfirmationDialog::rich(const QString &prompt_text, QWidget *parent) { + ConfirmationDialog d(prompt_text, tr("Ok"), "", true, parent); + return d.exec(); +} + +// MultiOptionDialog + +MultiOptionDialog::MultiOptionDialog(const QString &prompt_text, const QStringList &l, const QString ¤t, QWidget *parent) : DialogBase(parent) { + QFrame *container = new QFrame(this); + container->setStyleSheet(R"( + QFrame { background-color: #1B1B1B; } + #confirm_btn[enabled="false"] { background-color: #2B2B2B; } + #confirm_btn:enabled { background-color: #465BEA; } + #confirm_btn:enabled:pressed { background-color: #3049F4; } + )"); + + QVBoxLayout *main_layout = new QVBoxLayout(container); + main_layout->setContentsMargins(55, 50, 55, 50); + + QLabel *title = new QLabel(prompt_text, this); + title->setStyleSheet("font-size: 70px; font-weight: 500;"); + main_layout->addWidget(title, 0, Qt::AlignLeft | Qt::AlignTop); + main_layout->addSpacing(25); + + QWidget *listWidget = new QWidget(this); + QVBoxLayout *listLayout = new QVBoxLayout(listWidget); + listLayout->setSpacing(20); + listWidget->setStyleSheet(R"( + QPushButton { + height: 135; + padding: 0px 50px; + text-align: left; + font-size: 55px; + font-weight: 300; + border-radius: 10px; + background-color: #4F4F4F; + } + QPushButton:checked { background-color: #465BEA; } + )"); + + QButtonGroup *group = new QButtonGroup(listWidget); + group->setExclusive(true); + + QPushButton *confirm_btn = new QPushButton(tr("Select")); + confirm_btn->setObjectName("confirm_btn"); + confirm_btn->setEnabled(false); + + for (const QString &s : l) { + QPushButton *selectionLabel = new QPushButton(s); + selectionLabel->setCheckable(true); + selectionLabel->setChecked(s == current); + QObject::connect(selectionLabel, &QPushButton::toggled, [=](bool checked) { + if (checked) selection = s; + if (selection != current) { + confirm_btn->setEnabled(true); + } else { + confirm_btn->setEnabled(false); + } + }); + + group->addButton(selectionLabel); + listLayout->addWidget(selectionLabel); + } + // add stretch to keep buttons spaced correctly + listLayout->addStretch(1); + + ScrollView *scroll_view = new ScrollView(listWidget, this); + scroll_view->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + main_layout->addWidget(scroll_view); + main_layout->addSpacing(35); + + // cancel + confirm buttons + QHBoxLayout *blayout = new QHBoxLayout; + main_layout->addLayout(blayout); + blayout->setSpacing(50); + + QPushButton *cancel_btn = new QPushButton(tr("Cancel")); + QObject::connect(cancel_btn, &QPushButton::clicked, this, &ConfirmationDialog::reject); + QObject::connect(confirm_btn, &QPushButton::clicked, this, &ConfirmationDialog::accept); + blayout->addWidget(cancel_btn); + blayout->addWidget(confirm_btn); + + QVBoxLayout *outer_layout = new QVBoxLayout(this); + outer_layout->setContentsMargins(50, 50, 50, 50); + outer_layout->addWidget(container); +} + +QString MultiOptionDialog::getSelection(const QString &prompt_text, const QStringList &l, const QString ¤t, QWidget *parent) { + MultiOptionDialog d(prompt_text, l, current, parent); + if (d.exec()) { + return d.selection; + } + return ""; +} diff --git a/selfdrive/ui/qt/widgets/input.h b/selfdrive/ui/qt/widgets/input.h new file mode 100644 index 0000000000..089e54e4a0 --- /dev/null +++ b/selfdrive/ui/qt/widgets/input.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "selfdrive/ui/qt/widgets/keyboard.h" + + +class DialogBase : public QDialog { + Q_OBJECT + +protected: + DialogBase(QWidget *parent); + bool eventFilter(QObject *o, QEvent *e) override; + +public slots: + int exec() override; +}; + +class InputDialog : public DialogBase { + Q_OBJECT + +public: + explicit InputDialog(const QString &title, QWidget *parent, const QString &subtitle = "", bool secret = false); + static QString getText(const QString &title, QWidget *parent, const QString &subtitle = "", + bool secret = false, int minLength = -1, const QString &defaultText = ""); + QString text(); + void setMessage(const QString &message, bool clearInputField = true); + void setMinLength(int length); + void show(); + +private: + int minLength; + QLineEdit *line; + Keyboard *k; + QLabel *label; + QLabel *sublabel; + QVBoxLayout *main_layout; + QPushButton *eye_btn; + +private slots: + void handleEnter(); + +signals: + void cancel(); + void emitText(const QString &text); +}; + +class ConfirmationDialog : public DialogBase { + Q_OBJECT + +public: + explicit ConfirmationDialog(const QString &prompt_text, const QString &confirm_text, + const QString &cancel_text, const bool rich, QWidget* parent); + static bool alert(const QString &prompt_text, QWidget *parent); + static bool confirm(const QString &prompt_text, const QString &confirm_text, QWidget *parent); + static bool rich(const QString &prompt_text, QWidget *parent); +}; + +class MultiOptionDialog : public DialogBase { + Q_OBJECT + +public: + explicit MultiOptionDialog(const QString &prompt_text, const QStringList &l, const QString ¤t, QWidget *parent); + static QString getSelection(const QString &prompt_text, const QStringList &l, const QString ¤t, QWidget *parent); + QString selection; +}; diff --git a/selfdrive/ui/qt/widgets/keyboard.cc b/selfdrive/ui/qt/widgets/keyboard.cc new file mode 100644 index 0000000000..9ead27b8d5 --- /dev/null +++ b/selfdrive/ui/qt/widgets/keyboard.cc @@ -0,0 +1,182 @@ +#include "selfdrive/ui/qt/widgets/keyboard.h" + +#include + +#include +#include +#include +#include +#include + +const QString BACKSPACE_KEY = "⌫"; +const QString ENTER_KEY = "→"; +const QString SHIFT_KEY = "⇧"; +const QString CAPS_LOCK_KEY = "⇪"; + +const QMap KEY_STRETCH = {{" ", 3}, {ENTER_KEY, 2}}; + +const QStringList CONTROL_BUTTONS = {SHIFT_KEY, CAPS_LOCK_KEY, "ABC", "#+=", "123", BACKSPACE_KEY, ENTER_KEY}; + +const float key_spacing_vertical = 20; +const float key_spacing_horizontal = 15; + +KeyButton::KeyButton(const QString &text, QWidget *parent) : QPushButton(text, parent) { + setAttribute(Qt::WA_AcceptTouchEvents); + setFocusPolicy(Qt::NoFocus); +} + +bool KeyButton::event(QEvent *event) { + if (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchEnd) { + QTouchEvent *touchEvent = static_cast(event); + if (!touchEvent->touchPoints().empty()) { + const QEvent::Type mouseType = event->type() == QEvent::TouchBegin ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + QMouseEvent mouseEvent(mouseType, touchEvent->touchPoints().front().pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QPushButton::event(&mouseEvent); + event->accept(); + parentWidget()->update(); + return true; + } + } + return QPushButton::event(event); +} + +KeyboardLayout::KeyboardLayout(QWidget* parent, const std::vector>& layout) : QWidget(parent) { + QVBoxLayout* main_layout = new QVBoxLayout(this); + main_layout->setMargin(0); + main_layout->setSpacing(0); + + QButtonGroup* btn_group = new QButtonGroup(this); + QObject::connect(btn_group, SIGNAL(buttonClicked(QAbstractButton*)), parent, SLOT(handleButton(QAbstractButton*))); + + for (const auto &s : layout) { + QHBoxLayout *hlayout = new QHBoxLayout; + hlayout->setSpacing(0); + + if (main_layout->count() == 1) { + hlayout->addSpacing(90); + } + + for (const QString &p : s) { + KeyButton* btn = new KeyButton(p); + if (p == BACKSPACE_KEY) { + btn->setAutoRepeat(true); + } else if (p == ENTER_KEY) { + btn->setStyleSheet(R"( + QPushButton { + background-color: #465BEA; + } + QPushButton:pressed { + background-color: #444444; + } + )"); + } + btn->setFixedHeight(135 + key_spacing_vertical); + btn_group->addButton(btn); + hlayout->addWidget(btn, KEY_STRETCH.value(p, 1)); + } + + if (main_layout->count() == 1) { + hlayout->addSpacing(90); + } + + main_layout->addLayout(hlayout); + } + + setStyleSheet(QString(R"( + QPushButton { + font-size: 75px; + margin-left: %1px; + margin-right: %1px; + margin-top: %2px; + margin-bottom: %2px; + padding: 0px; + border-radius: 10px; + color: #dddddd; + background-color: #444444; + } + QPushButton:pressed { + background-color: #333333; + } + )").arg(key_spacing_vertical / 2).arg(key_spacing_horizontal / 2)); +} + +Keyboard::Keyboard(QWidget *parent) : QFrame(parent) { + main_layout = new QStackedLayout(this); + main_layout->setMargin(0); + + // lowercase + std::vector> lowercase = { + {"q", "w", "e", "r", "t", "y", "u", "i", "o", "p"}, + {"a", "s", "d", "f", "g", "h", "j", "k", "l"}, + {SHIFT_KEY, "z", "x", "c", "v", "b", "n", "m", BACKSPACE_KEY}, + {"123", "/", "-", " ", ".", ENTER_KEY}, + }; + main_layout->addWidget(new KeyboardLayout(this, lowercase)); + + // uppercase + std::vector> uppercase = { + {"Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"}, + {"A", "S", "D", "F", "G", "H", "J", "K", "L"}, + {SHIFT_KEY, "Z", "X", "C", "V", "B", "N", "M", BACKSPACE_KEY}, + {"123", "/", "-", " ", ".", ENTER_KEY}, + }; + main_layout->addWidget(new KeyboardLayout(this, uppercase)); + + // numbers + specials + std::vector> numbers = { + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}, + {"-", "/", ":", ";", "(", ")", "$", "&&", "@", "\""}, + {"#+=", ".", ",", "?", "!", "`", BACKSPACE_KEY}, + {"ABC", " ", ".", ENTER_KEY}, + }; + main_layout->addWidget(new KeyboardLayout(this, numbers)); + + // extra specials + std::vector> specials = { + {"[", "]", "{", "}", "#", "%", "^", "*", "+", "="}, + {"_", "\\", "|", "~", "<", ">", "€", "£", "¥", "•"}, + {"123", ".", ",", "?", "!", "'", BACKSPACE_KEY}, + {"ABC", " ", ".", ENTER_KEY}, + }; + main_layout->addWidget(new KeyboardLayout(this, specials)); + + main_layout->setCurrentIndex(0); +} + +void Keyboard::handleCapsPress() { + shift_state = (shift_state + 1) % 3; + bool is_uppercase = shift_state > 0; + main_layout->setCurrentIndex(is_uppercase); + + for (KeyButton* btn : main_layout->currentWidget()->findChildren()) { + if (btn->text() == SHIFT_KEY || btn->text() == CAPS_LOCK_KEY) { + btn->setText(shift_state == 2 ? CAPS_LOCK_KEY : SHIFT_KEY); + btn->setStyleSheet(is_uppercase ? "background-color: #465BEA;" : ""); + } + } +} + +void Keyboard::handleButton(QAbstractButton* btn) { + const QString &key = btn->text(); + if (CONTROL_BUTTONS.contains(key)) { + if (key == "ABC" || key == "123" || key == "#+=") { + int index = (key == "ABC") ? 0 : (key == "123" ? 2 : 3); + main_layout->setCurrentIndex(index); + shift_state = 0; + } else if (key == SHIFT_KEY || key == CAPS_LOCK_KEY) { + handleCapsPress(); + } else if (key == ENTER_KEY) { + main_layout->setCurrentIndex(0); + shift_state = 0; + emit emitEnter(); + } else if (key == BACKSPACE_KEY) { + emit emitBackspace(); + } + } else { + if (shift_state == 1 && "A" <= key && key <= "Z") { + main_layout->setCurrentIndex(0); + shift_state = 0; + } + emit emitKey(key); + } +} diff --git a/selfdrive/ui/qt/widgets/keyboard.h b/selfdrive/ui/qt/widgets/keyboard.h new file mode 100644 index 0000000000..e61617283a --- /dev/null +++ b/selfdrive/ui/qt/widgets/keyboard.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include +#include +#include + +class KeyButton : public QPushButton { + Q_OBJECT + +public: + KeyButton(const QString &text, QWidget *parent = 0); + bool event(QEvent *event) override; +}; + +class KeyboardLayout : public QWidget { + Q_OBJECT + +public: + explicit KeyboardLayout(QWidget* parent, const std::vector>& layout); +}; + +class Keyboard : public QFrame { + Q_OBJECT + +public: + explicit Keyboard(QWidget *parent = 0); + +private: + QStackedLayout* main_layout; + int shift_state = 0; + +private slots: + void handleButton(QAbstractButton* m_button); + void handleCapsPress(); + +signals: + void emitKey(const QString &s); + void emitBackspace(); + void emitEnter(); +}; diff --git a/selfdrive/ui/qt/widgets/offroad_alerts.cc b/selfdrive/ui/qt/widgets/offroad_alerts.cc new file mode 100644 index 0000000000..3a4828a2a8 --- /dev/null +++ b/selfdrive/ui/qt/widgets/offroad_alerts.cc @@ -0,0 +1,138 @@ +#include "selfdrive/ui/qt/widgets/offroad_alerts.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "common/util.h" +#include "system/hardware/hw.h" +#include "selfdrive/ui/qt/widgets/scrollview.h" + +AbstractAlert::AbstractAlert(bool hasRebootBtn, QWidget *parent) : QFrame(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setMargin(50); + main_layout->setSpacing(30); + + QWidget *widget = new QWidget; + scrollable_layout = new QVBoxLayout(widget); + widget->setStyleSheet("background-color: transparent;"); + main_layout->addWidget(new ScrollView(widget)); + + // bottom footer, dismiss + reboot buttons + QHBoxLayout *footer_layout = new QHBoxLayout(); + main_layout->addLayout(footer_layout); + + QPushButton *dismiss_btn = new QPushButton(tr("Close")); + dismiss_btn->setFixedSize(400, 125); + footer_layout->addWidget(dismiss_btn, 0, Qt::AlignBottom | Qt::AlignLeft); + QObject::connect(dismiss_btn, &QPushButton::clicked, this, &AbstractAlert::dismiss); + + action_btn = new QPushButton(); + action_btn->setVisible(false); + action_btn->setFixedHeight(125); + footer_layout->addWidget(action_btn, 0, Qt::AlignBottom | Qt::AlignRight); + QObject::connect(action_btn, &QPushButton::clicked, [=]() { + if (!alerts["Offroad_ExcessiveActuation"]->text().isEmpty()) { + params.remove("Offroad_ExcessiveActuation"); + } else { + params.putBool("SnoozeUpdate", true); + } + }); + QObject::connect(action_btn, &QPushButton::clicked, this, &AbstractAlert::dismiss); + action_btn->setStyleSheet("color: white; background-color: #4F4F4F; padding-left: 60px; padding-right: 60px;"); + + if (hasRebootBtn) { + QPushButton *rebootBtn = new QPushButton(tr("Reboot and Update")); + rebootBtn->setFixedSize(600, 125); + footer_layout->addWidget(rebootBtn, 0, Qt::AlignBottom | Qt::AlignRight); + QObject::connect(rebootBtn, &QPushButton::clicked, [=]() { Hardware::reboot(); }); + } + + setStyleSheet(R"( + * { + font-size: 48px; + color: white; + } + QFrame { + border-radius: 30px; + background-color: #393939; + } + QPushButton { + color: black; + font-weight: 500; + border-radius: 30px; + background-color: white; + } + )"); +} + +int OffroadAlert::refresh() { + // build widgets for each offroad alert on first refresh + if (alerts.empty()) { + QString json = util::read_file("../selfdrived/alerts_offroad.json").c_str(); + QJsonObject obj = QJsonDocument::fromJson(json.toUtf8()).object(); + + // descending sort labels by severity + std::vector> sorted; + for (auto it = obj.constBegin(); it != obj.constEnd(); ++it) { + sorted.push_back({it.key().toStdString(), it.value()["severity"].toInt()}); + } + std::sort(sorted.begin(), sorted.end(), [=](auto &l, auto &r) { return l.second > r.second; }); + + for (auto &[key, severity] : sorted) { + QLabel *l = new QLabel(this); + alerts[key] = l; + l->setMargin(60); + l->setWordWrap(true); + l->setStyleSheet(QString("background-color: %1").arg(severity ? "#E22C2C" : "#292929")); + scrollable_layout->addWidget(l); + } + scrollable_layout->addStretch(1); + } + + int alertCount = 0; + for (const auto &[key, label] : alerts) { + QString text; + std::string bytes = params.get(key); + if (bytes.size()) { + auto doc_par = QJsonDocument::fromJson(bytes.c_str()); + text = tr(doc_par["text"].toString().toUtf8().data()); + auto extra = doc_par["extra"].toString(); + if (!extra.isEmpty()) { + text = text.arg(extra); + } + } + label->setText(text); + label->setVisible(!text.isEmpty()); + alertCount += !text.isEmpty(); + } + + action_btn->setVisible(!alerts["Offroad_ExcessiveActuation"]->text().isEmpty() || !alerts["Offroad_ConnectivityNeeded"]->text().isEmpty()); + if (!alerts["Offroad_ExcessiveActuation"]->text().isEmpty()) { + action_btn->setText(tr("Acknowledge Excessive Actuation")); + } else { + action_btn->setText(tr("Snooze Update")); + } + + return alertCount; +} + +UpdateAlert::UpdateAlert(QWidget *parent) : AbstractAlert(true, parent) { + releaseNotes = new QLabel(this); + releaseNotes->setWordWrap(true); + releaseNotes->setAlignment(Qt::AlignTop); + scrollable_layout->addWidget(releaseNotes); +} + +bool UpdateAlert::refresh() { + bool updateAvailable = params.getBool("UpdateAvailable"); + if (updateAvailable) { + releaseNotes->setText(params.get("UpdaterNewReleaseNotes").c_str()); + } + return updateAvailable; +} diff --git a/selfdrive/ui/qt/widgets/offroad_alerts.h b/selfdrive/ui/qt/widgets/offroad_alerts.h new file mode 100644 index 0000000000..2dcf4f9d8c --- /dev/null +++ b/selfdrive/ui/qt/widgets/offroad_alerts.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include "common/params.h" + +class AbstractAlert : public QFrame { + Q_OBJECT + +protected: + AbstractAlert(bool hasRebootBtn, QWidget *parent = nullptr); + + QPushButton *action_btn; + QVBoxLayout *scrollable_layout; + Params params; + std::map alerts; + +signals: + void dismiss(); +}; + +class UpdateAlert : public AbstractAlert { + Q_OBJECT + +public: + UpdateAlert(QWidget *parent = 0); + bool refresh(); + +private: + QLabel *releaseNotes = nullptr; +}; + +class OffroadAlert : public AbstractAlert { + Q_OBJECT + +public: + explicit OffroadAlert(QWidget *parent = 0) : AbstractAlert(false, parent) {} + int refresh(); +}; diff --git a/selfdrive/ui/qt/widgets/prime.cc b/selfdrive/ui/qt/widgets/prime.cc new file mode 100644 index 0000000000..ee820c46a3 --- /dev/null +++ b/selfdrive/ui/qt/widgets/prime.cc @@ -0,0 +1,265 @@ +#include "selfdrive/ui/qt/widgets/prime.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "selfdrive/ui/qt/request_repeater.h" +#include "selfdrive/ui/qt/util.h" +#include "selfdrive/ui/qt/qt_window.h" +#include "selfdrive/ui/qt/widgets/wifi.h" + +using qrcodegen::QrCode; + +PairingQRWidget::PairingQRWidget(QWidget* parent) : QWidget(parent) { + timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, &PairingQRWidget::refresh); +} + +void PairingQRWidget::showEvent(QShowEvent *event) { + refresh(); + timer->start(5 * 60 * 1000); + device()->setOffroadBrightness(100); +} + +void PairingQRWidget::hideEvent(QHideEvent *event) { + timer->stop(); + device()->setOffroadBrightness(BACKLIGHT_OFFROAD); +} + +void PairingQRWidget::refresh() { + QString pairToken = CommaApi::create_jwt({{"pair", true}}); + QString qrString = "https://connect.comma.ai/?pair=" + pairToken; + this->updateQrCode(qrString); + update(); +} + +void PairingQRWidget::updateQrCode(const QString &text) { + QrCode qr = QrCode::encodeText(text.toUtf8().data(), QrCode::Ecc::LOW); + qint32 sz = qr.getSize(); + QImage im(sz, sz, QImage::Format_RGB32); + + QRgb black = qRgb(0, 0, 0); + QRgb white = qRgb(255, 255, 255); + for (int y = 0; y < sz; y++) { + for (int x = 0; x < sz; x++) { + im.setPixel(x, y, qr.getModule(x, y) ? black : white); + } + } + + // Integer division to prevent anti-aliasing + int final_sz = ((width() / sz) - 1) * sz; + img = QPixmap::fromImage(im.scaled(final_sz, final_sz, Qt::KeepAspectRatio), Qt::MonoOnly); +} + +void PairingQRWidget::paintEvent(QPaintEvent *e) { + QPainter p(this); + p.fillRect(rect(), Qt::white); + + QSize s = (size() - img.size()) / 2; + p.drawPixmap(s.width(), s.height(), img); +} + + +PairingPopup::PairingPopup(QWidget *parent) : DialogBase(parent) { + QHBoxLayout *hlayout = new QHBoxLayout(this); + hlayout->setContentsMargins(0, 0, 0, 0); + hlayout->setSpacing(0); + + setStyleSheet("PairingPopup { background-color: #E0E0E0; }"); + + // text + QVBoxLayout *vlayout = new QVBoxLayout(); + vlayout->setContentsMargins(85, 70, 50, 70); + vlayout->setSpacing(50); + hlayout->addLayout(vlayout, 1); + { + QPushButton *close = new QPushButton(QIcon(":/icons/close.svg"), "", this); + close->setIconSize(QSize(80, 80)); + close->setStyleSheet("border: none;"); + vlayout->addWidget(close, 0, Qt::AlignLeft); + QObject::connect(close, &QPushButton::clicked, this, &QDialog::reject); + + vlayout->addSpacing(30); + + QLabel *title = new QLabel(tr("Pair your device to your comma account"), this); + title->setStyleSheet("font-size: 75px; color: black;"); + title->setWordWrap(true); + vlayout->addWidget(title); + + QLabel *instructions = new QLabel(QString(R"( +
      +
    1. %1
    2. +
    3. %2
    4. +
    5. %3
    6. +
    + )").arg(tr("Go to https://connect.comma.ai on your phone")) + .arg(tr("Click \"add new device\" and scan the QR code on the right")) + .arg(tr("Bookmark connect.comma.ai to your home screen to use it like an app")), this); + + instructions->setStyleSheet("font-size: 47px; font-weight: bold; color: black;"); + instructions->setWordWrap(true); + vlayout->addWidget(instructions); + + vlayout->addStretch(); + } + + // QR code + PairingQRWidget *qr = new PairingQRWidget(this); + hlayout->addWidget(qr, 1); +} + +int PairingPopup::exec() { + if (!util::system_time_valid()) { + ConfirmationDialog::alert(tr("Please connect to Wi-Fi to complete initial pairing"), parentWidget()); + return QDialog::Rejected; + } + return DialogBase::exec(); +} + + +PrimeUserWidget::PrimeUserWidget(QWidget *parent) : QFrame(parent) { + setObjectName("primeWidget"); + QVBoxLayout *mainLayout = new QVBoxLayout(this); + mainLayout->setContentsMargins(56, 40, 56, 40); + mainLayout->setSpacing(20); + + QLabel *subscribed = new QLabel(tr("✓ SUBSCRIBED")); + subscribed->setStyleSheet("font-size: 41px; font-weight: bold; color: #86FF4E;"); + mainLayout->addWidget(subscribed); + + QLabel *commaPrime = new QLabel(tr("comma prime")); + commaPrime->setStyleSheet("font-size: 75px; font-weight: bold;"); + mainLayout->addWidget(commaPrime); +} + + +PrimeAdWidget::PrimeAdWidget(QWidget* parent) : QFrame(parent) { + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(80, 90, 80, 60); + main_layout->setSpacing(0); + + QLabel *upgrade = new QLabel(tr("Upgrade Now")); + upgrade->setStyleSheet("font-size: 75px; font-weight: bold;"); + main_layout->addWidget(upgrade, 0, Qt::AlignTop); + main_layout->addSpacing(50); + + QLabel *description = new QLabel(tr("Become a comma prime member at connect.comma.ai")); + description->setStyleSheet("font-size: 56px; font-weight: light; color: white;"); + description->setWordWrap(true); + main_layout->addWidget(description, 0, Qt::AlignTop); + + main_layout->addStretch(); + + QLabel *features = new QLabel(tr("PRIME FEATURES:")); + features->setStyleSheet("font-size: 41px; font-weight: bold; color: #E5E5E5;"); + main_layout->addWidget(features, 0, Qt::AlignBottom); + main_layout->addSpacing(30); + + QVector bullets = {tr("Remote access"), tr("24/7 LTE connectivity"), tr("1 year of drive storage"), tr("Remote snapshots")}; + for (auto &b : bullets) { + const QString check = " "; + QLabel *l = new QLabel(check + b); + l->setAlignment(Qt::AlignLeft); + l->setStyleSheet("font-size: 50px; margin-bottom: 15px;"); + main_layout->addWidget(l, 0, Qt::AlignBottom); + } + + setStyleSheet(R"( + PrimeAdWidget { + border-radius: 10px; + background-color: #333333; + } + )"); +} + + +SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { + mainLayout = new QStackedWidget; + + // Unpaired, registration prompt layout + + QFrame* finishRegistration = new QFrame; + finishRegistration->setObjectName("primeWidget"); + QVBoxLayout* finishRegistrationLayout = new QVBoxLayout(finishRegistration); + finishRegistrationLayout->setSpacing(38); + finishRegistrationLayout->setContentsMargins(64, 48, 64, 48); + + QLabel* registrationTitle = new QLabel(tr("Finish Setup")); + registrationTitle->setStyleSheet("font-size: 75px; font-weight: bold;"); + finishRegistrationLayout->addWidget(registrationTitle); + + QLabel* registrationDescription = new QLabel(tr("Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer.")); + registrationDescription->setWordWrap(true); + registrationDescription->setStyleSheet("font-size: 50px; font-weight: light;"); + finishRegistrationLayout->addWidget(registrationDescription); + + finishRegistrationLayout->addStretch(); + + QPushButton* pair = new QPushButton(tr("Pair device")); + pair->setStyleSheet(R"( + QPushButton { + font-size: 55px; + font-weight: 500; + border-radius: 10px; + background-color: #465BEA; + padding: 64px; + } + QPushButton:pressed { + background-color: #3049F4; + } + )"); + finishRegistrationLayout->addWidget(pair); + + popup = new PairingPopup(this); + QObject::connect(pair, &QPushButton::clicked, popup, &PairingPopup::exec); + + mainLayout->addWidget(finishRegistration); + + // build stacked layout + QVBoxLayout *outer_layout = new QVBoxLayout(this); + outer_layout->setContentsMargins(0, 0, 0, 0); + outer_layout->addWidget(mainLayout); + + QWidget *content = new QWidget; + QVBoxLayout *content_layout = new QVBoxLayout(content); + content_layout->setContentsMargins(0, 0, 0, 0); + content_layout->setSpacing(30); + + WiFiPromptWidget *wifi_prompt = new WiFiPromptWidget; + QObject::connect(wifi_prompt, &WiFiPromptWidget::openSettings, this, &SetupWidget::openSettings); + content_layout->addWidget(wifi_prompt); + content_layout->addStretch(); + + mainLayout->addWidget(content); + + mainLayout->setCurrentIndex(1); + + setStyleSheet(R"( + #primeWidget { + border-radius: 10px; + background-color: #333333; + } + )"); + + // Retain size while hidden + QSizePolicy sp_retain = sizePolicy(); + sp_retain.setRetainSizeWhenHidden(true); + setSizePolicy(sp_retain); + + QObject::connect(uiState()->prime_state, &PrimeState::changed, [this](PrimeState::Type type) { + if (type == PrimeState::PRIME_TYPE_UNPAIRED) { + mainLayout->setCurrentIndex(0); // Display "Pair your device" widget + } else { + popup->reject(); + mainLayout->setCurrentIndex(1); // Display Wi-Fi prompt widget + } + }); +} diff --git a/selfdrive/ui/qt/widgets/prime.h b/selfdrive/ui/qt/widgets/prime.h new file mode 100644 index 0000000000..266a90a92c --- /dev/null +++ b/selfdrive/ui/qt/widgets/prime.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include +#include + +#include "selfdrive/ui/qt/widgets/input.h" + +// pairing QR code +class PairingQRWidget : public QWidget { + Q_OBJECT + +public: + explicit PairingQRWidget(QWidget* parent = 0); + void paintEvent(QPaintEvent*) override; + +private: + QPixmap img; + QTimer *timer; + void updateQrCode(const QString &text); + void showEvent(QShowEvent *event) override; + void hideEvent(QHideEvent *event) override; + +private slots: + void refresh(); +}; + + +// pairing popup widget +class PairingPopup : public DialogBase { + Q_OBJECT + +public: + explicit PairingPopup(QWidget* parent); + int exec() override; +}; + + +// widget for paired users with prime +class PrimeUserWidget : public QFrame { + Q_OBJECT + +public: + explicit PrimeUserWidget(QWidget* parent = 0); +}; + + +// widget for paired users without prime +class PrimeAdWidget : public QFrame { + Q_OBJECT +public: + explicit PrimeAdWidget(QWidget* parent = 0); +}; + + +// container widget +class SetupWidget : public QFrame { + Q_OBJECT + +public: + explicit SetupWidget(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); + +private: + PairingPopup *popup; + QStackedWidget *mainLayout; +}; diff --git a/selfdrive/ui/qt/widgets/scrollview.cc b/selfdrive/ui/qt/widgets/scrollview.cc new file mode 100644 index 0000000000..978bf83a63 --- /dev/null +++ b/selfdrive/ui/qt/widgets/scrollview.cc @@ -0,0 +1,49 @@ +#include "selfdrive/ui/qt/widgets/scrollview.h" + +#include +#include + +// TODO: disable horizontal scrolling and resize + +ScrollView::ScrollView(QWidget *w, QWidget *parent) : QScrollArea(parent) { + setWidget(w); + setWidgetResizable(true); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setStyleSheet("background-color: transparent; border:none"); + + QString style = R"( + QScrollBar:vertical { + border: none; + background: transparent; + width: 10px; + margin: 0; + } + QScrollBar::handle:vertical { + min-height: 0px; + border-radius: 5px; + background-color: white; + } + QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { + height: 0px; + } + QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: none; + } + )"; + verticalScrollBar()->setStyleSheet(style); + horizontalScrollBar()->setStyleSheet(style); + + QScroller *scroller = QScroller::scroller(this->viewport()); + QScrollerProperties sp = scroller->scrollerProperties(); + + sp.setScrollMetric(QScrollerProperties::VerticalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff)); + sp.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff)); + sp.setScrollMetric(QScrollerProperties::MousePressEventDelay, 0.01); + scroller->grabGesture(this->viewport(), QScroller::LeftMouseButtonGesture); + scroller->setScrollerProperties(sp); +} + +void ScrollView::hideEvent(QHideEvent *e) { + verticalScrollBar()->setValue(0); +} diff --git a/selfdrive/ui/qt/widgets/scrollview.h b/selfdrive/ui/qt/widgets/scrollview.h new file mode 100644 index 0000000000..024331aa39 --- /dev/null +++ b/selfdrive/ui/qt/widgets/scrollview.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +class ScrollView : public QScrollArea { + Q_OBJECT + +public: + explicit ScrollView(QWidget *w = nullptr, QWidget *parent = nullptr); +protected: + void hideEvent(QHideEvent *e) override; +}; diff --git a/selfdrive/ui/qt/widgets/ssh_keys.cc b/selfdrive/ui/qt/widgets/ssh_keys.cc new file mode 100644 index 0000000000..26743952de --- /dev/null +++ b/selfdrive/ui/qt/widgets/ssh_keys.cc @@ -0,0 +1,64 @@ +#include "selfdrive/ui/qt/widgets/ssh_keys.h" + +#include "common/params.h" +#include "selfdrive/ui/qt/api.h" +#include "selfdrive/ui/qt/widgets/input.h" + +SshControl::SshControl() : + ButtonControl(tr("SSH Keys"), "", tr("Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username " + "other than your own. A comma employee will NEVER ask you to add their GitHub username.")) { + + QObject::connect(this, &ButtonControl::clicked, [=]() { + if (text() == tr("ADD")) { + QString username = InputDialog::getText(tr("Enter your GitHub username"), this); + if (username.length() > 0) { + setText(tr("LOADING")); + setEnabled(false); + getUserKeys(username); + } + } else { + params.remove("GithubUsername"); + params.remove("GithubSshKeys"); + refresh(); + } + }); + + refresh(); +} + +void SshControl::refresh() { + QString param = QString::fromStdString(params.get("GithubSshKeys")); + if (param.length()) { + setValue(QString::fromStdString(params.get("GithubUsername"))); + setText(tr("REMOVE")); + } else { + setValue(""); + setText(tr("ADD")); + } + setEnabled(true); +} + +void SshControl::getUserKeys(const QString &username) { + HttpRequest *request = new HttpRequest(this, false); + QObject::connect(request, &HttpRequest::requestDone, [=](const QString &resp, bool success) { + if (success) { + if (!resp.isEmpty()) { + params.put("GithubUsername", username.toStdString()); + params.put("GithubSshKeys", resp.toStdString()); + } else { + ConfirmationDialog::alert(tr("Username '%1' has no keys on GitHub").arg(username), this); + } + } else { + if (request->timeout()) { + ConfirmationDialog::alert(tr("Request timed out"), this); + } else { + ConfirmationDialog::alert(tr("Username '%1' doesn't exist on GitHub").arg(username), this); + } + } + + refresh(); + request->deleteLater(); + }); + + request->sendRequest("https://github.com/" + username + ".keys"); +} diff --git a/selfdrive/ui/qt/widgets/ssh_keys.h b/selfdrive/ui/qt/widgets/ssh_keys.h new file mode 100644 index 0000000000..920bd651e2 --- /dev/null +++ b/selfdrive/ui/qt/widgets/ssh_keys.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "system/hardware/hw.h" +#include "selfdrive/ui/qt/widgets/controls.h" + +// SSH enable toggle +class SshToggle : public ToggleControl { + Q_OBJECT + +public: + SshToggle() : ToggleControl(tr("Enable SSH"), "", "", Hardware::get_ssh_enabled()) { + QObject::connect(this, &SshToggle::toggleFlipped, [=](bool state) { + Hardware::set_ssh_enabled(state); + }); + } +}; + +// SSH key management widget +class SshControl : public ButtonControl { + Q_OBJECT + +public: + SshControl(); + +private: + Params params; + + void refresh(); + void getUserKeys(const QString &username); +}; diff --git a/selfdrive/ui/qt/widgets/toggle.cc b/selfdrive/ui/qt/widgets/toggle.cc new file mode 100644 index 0000000000..82302ad5bc --- /dev/null +++ b/selfdrive/ui/qt/widgets/toggle.cc @@ -0,0 +1,83 @@ +#include "selfdrive/ui/qt/widgets/toggle.h" + +#include + +Toggle::Toggle(QWidget *parent) : QAbstractButton(parent), +_height(80), +_height_rect(60), +on(false), +_anim(new QPropertyAnimation(this, "offset_circle", this)) +{ + _radius = _height / 2; + _x_circle = _radius; + _y_circle = _radius; + _y_rect = (_height - _height_rect)/2; + circleColor = QColor(0xffffff); // placeholder + green = QColor(0xffffff); // placeholder + setEnabled(true); +} + +void Toggle::paintEvent(QPaintEvent *e) { + this->setFixedHeight(_height); + QPainter p(this); + p.setPen(Qt::NoPen); + p.setRenderHint(QPainter::Antialiasing, true); + + // Draw toggle background left + p.setBrush(green); + p.drawRoundedRect(QRect(0, _y_rect, _x_circle + _radius, _height_rect), _height_rect/2, _height_rect/2); + + // Draw toggle background right + p.setBrush(QColor(0x393939)); + p.drawRoundedRect(QRect(_x_circle - _radius, _y_rect, width() - (_x_circle - _radius), _height_rect), _height_rect/2, _height_rect/2); + + // Draw toggle circle + p.setBrush(circleColor); + p.drawEllipse(QRectF(_x_circle - _radius, _y_circle - _radius, 2 * _radius, 2 * _radius)); +} + +void Toggle::mouseReleaseEvent(QMouseEvent *e) { + if (!enabled) { + return; + } + const int left = _radius; + const int right = width() - _radius; + if ((_x_circle != left && _x_circle != right) || !this->rect().contains(e->localPos().toPoint())) { + // If mouse release isn't in rect or animation is running, don't parse touch events + return; + } + if (e->button() & Qt::LeftButton) { + togglePosition(); + emit stateChanged(on); + } +} + +void Toggle::togglePosition() { + on = !on; + const int left = _radius; + const int right = width() - _radius; + _anim->setStartValue(on ? left + immediateOffset : right - immediateOffset); + _anim->setEndValue(on ? right : left); + _anim->setDuration(animation_duration); + _anim->start(); + repaint(); +} + +void Toggle::enterEvent(QEvent *e) { + QAbstractButton::enterEvent(e); +} + +bool Toggle::getEnabled() { + return enabled; +} + +void Toggle::setEnabled(bool value) { + enabled = value; + if (value) { + circleColor.setRgb(0xfafafa); + green.setRgb(0x33ab4c); + } else { + circleColor.setRgb(0x888888); + green.setRgb(0x227722); + } +} diff --git a/selfdrive/ui/qt/widgets/toggle.h b/selfdrive/ui/qt/widgets/toggle.h new file mode 100644 index 0000000000..e7263a008f --- /dev/null +++ b/selfdrive/ui/qt/widgets/toggle.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +class Toggle : public QAbstractButton { + Q_OBJECT + Q_PROPERTY(int offset_circle READ offset_circle WRITE set_offset_circle CONSTANT) + +public: + Toggle(QWidget* parent = nullptr); + void togglePosition(); + bool on; + int animation_duration = 150; + int immediateOffset = 0; + int offset_circle() const { + return _x_circle; + } + + void set_offset_circle(int o) { + _x_circle = o; + update(); + } + bool getEnabled(); + void setEnabled(bool value); + +protected: + void paintEvent(QPaintEvent*) override; + void mouseReleaseEvent(QMouseEvent*) override; + void enterEvent(QEvent*) override; + +private: + QColor circleColor; + QColor green; + bool enabled = true; + int _x_circle, _y_circle; + int _height, _radius; + int _height_rect, _y_rect; + QPropertyAnimation *_anim = nullptr; + +signals: + void stateChanged(bool new_state); +}; diff --git a/selfdrive/ui/qt/widgets/wifi.cc b/selfdrive/ui/qt/widgets/wifi.cc new file mode 100644 index 0000000000..d7eb8beeb3 --- /dev/null +++ b/selfdrive/ui/qt/widgets/wifi.cc @@ -0,0 +1,45 @@ +#include "selfdrive/ui/qt/widgets/wifi.h" + +#include +#include +#include +#include + +WiFiPromptWidget::WiFiPromptWidget(QWidget *parent) : QFrame(parent) { + // Setup Firehose Mode + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->setContentsMargins(56, 40, 56, 40); + main_layout->setSpacing(42); + + QLabel *title = new QLabel(tr("🔥 Firehose Mode 🔥")); + title->setStyleSheet("font-size: 64px; font-weight: 500;"); + main_layout->addWidget(title); + + QLabel *desc = new QLabel(tr("Maximize your training data uploads to improve openpilot's driving models.")); + desc->setStyleSheet("font-size: 40px; font-weight: 400;"); + desc->setWordWrap(true); + main_layout->addWidget(desc); + + QPushButton *settings_btn = new QPushButton(tr("Open")); + connect(settings_btn, &QPushButton::clicked, [=]() { emit openSettings(1, "FirehosePanel"); }); + settings_btn->setStyleSheet(R"( + QPushButton { + font-size: 48px; + font-weight: 500; + border-radius: 10px; + background-color: #465BEA; + padding: 32px; + } + QPushButton:pressed { + background-color: #3049F4; + } + )"); + main_layout->addWidget(settings_btn); + + setStyleSheet(R"( + WiFiPromptWidget { + background-color: #333333; + border-radius: 10px; + } + )"); +} \ No newline at end of file diff --git a/selfdrive/ui/qt/widgets/wifi.h b/selfdrive/ui/qt/widgets/wifi.h new file mode 100644 index 0000000000..3e68a15b7b --- /dev/null +++ b/selfdrive/ui/qt/widgets/wifi.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +class WiFiPromptWidget : public QFrame { + Q_OBJECT + +public: + explicit WiFiPromptWidget(QWidget* parent = 0); + +signals: + void openSettings(int index = 0, const QString ¶m = ""); +}; diff --git a/selfdrive/ui/qt/window.cc b/selfdrive/ui/qt/window.cc new file mode 100644 index 0000000000..6b579fcc5d --- /dev/null +++ b/selfdrive/ui/qt/window.cc @@ -0,0 +1,98 @@ +#include "selfdrive/ui/qt/window.h" + +#include + +#include "system/hardware/hw.h" + +MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { + main_layout = new QStackedLayout(this); + main_layout->setMargin(0); + + homeWindow = new HomeWindow(this); + main_layout->addWidget(homeWindow); + QObject::connect(homeWindow, &HomeWindow::openSettings, this, &MainWindow::openSettings); + QObject::connect(homeWindow, &HomeWindow::closeSettings, this, &MainWindow::closeSettings); + + settingsWindow = new SettingsWindow(this); + main_layout->addWidget(settingsWindow); + QObject::connect(settingsWindow, &SettingsWindow::closeSettings, this, &MainWindow::closeSettings); + QObject::connect(settingsWindow, &SettingsWindow::reviewTrainingGuide, [=]() { + onboardingWindow->showTrainingGuide(); + main_layout->setCurrentWidget(onboardingWindow); + }); + QObject::connect(settingsWindow, &SettingsWindow::showDriverView, [=] { + homeWindow->showDriverView(true); + }); + + onboardingWindow = new OnboardingWindow(this); + main_layout->addWidget(onboardingWindow); + QObject::connect(onboardingWindow, &OnboardingWindow::onboardingDone, [=]() { + main_layout->setCurrentWidget(homeWindow); + }); + if (!onboardingWindow->completed()) { + main_layout->setCurrentWidget(onboardingWindow); + } + + QObject::connect(uiState(), &UIState::offroadTransition, [=](bool offroad) { + if (!offroad) { + closeSettings(); + } + }); + QObject::connect(device(), &Device::interactiveTimeout, [=]() { + if (main_layout->currentWidget() == settingsWindow) { + closeSettings(); + } + }); + + // load fonts + QFontDatabase::addApplicationFont("../assets/fonts/Inter-Black.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-Bold.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-ExtraBold.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-ExtraLight.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-Medium.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-Regular.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-SemiBold.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/Inter-Thin.ttf"); + QFontDatabase::addApplicationFont("../assets/fonts/JetBrainsMono-Medium.ttf"); + + // no outline to prevent the focus rectangle + setStyleSheet(R"( + * { + font-family: Inter; + outline: none; + } + )"); + setAttribute(Qt::WA_NoSystemBackground); +} + +void MainWindow::openSettings(int index, const QString ¶m) { + main_layout->setCurrentWidget(settingsWindow); + settingsWindow->setCurrentPanel(index, param); +} + +void MainWindow::closeSettings() { + main_layout->setCurrentWidget(homeWindow); + + if (uiState()->scene.started) { + homeWindow->showSidebar(false); + } +} + +bool MainWindow::eventFilter(QObject *obj, QEvent *event) { + bool ignore = false; + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::MouseButtonPress: + case QEvent::MouseMove: { + // ignore events when device is awakened by resetInteractiveTimeout + ignore = !device()->isAwake(); + device()->resetInteractiveTimeout(); + break; + } + default: + break; + } + return ignore; +} diff --git a/selfdrive/ui/qt/window.h b/selfdrive/ui/qt/window.h new file mode 100644 index 0000000000..05b61e1f76 --- /dev/null +++ b/selfdrive/ui/qt/window.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "selfdrive/ui/qt/home.h" +#include "selfdrive/ui/qt/offroad/onboarding.h" +#include "selfdrive/ui/qt/offroad/settings.h" + +class MainWindow : public QWidget { + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + +private: + bool eventFilter(QObject *obj, QEvent *event) override; + void openSettings(int index = 0, const QString ¶m = ""); + void closeSettings(); + + QStackedLayout *main_layout; + HomeWindow *homeWindow; + SettingsWindow *settingsWindow; + OnboardingWindow *onboardingWindow; +}; diff --git a/selfdrive/ui/soundd.py b/selfdrive/ui/soundd.py new file mode 100644 index 0000000000..13f3b22091 --- /dev/null +++ b/selfdrive/ui/soundd.py @@ -0,0 +1,164 @@ +import math +import numpy as np +import time +import wave + + +from cereal import car, messaging +from openpilot.common.basedir import BASEDIR +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.realtime import Ratekeeper +from openpilot.common.retry import retry +from openpilot.common.swaglog import cloudlog + +from openpilot.system import micd + +SAMPLE_RATE = 48000 +SAMPLE_BUFFER = 4096 # (approx 100ms) +MAX_VOLUME = 1.0 +MIN_VOLUME = 0.1 +SELFDRIVE_STATE_TIMEOUT = 5 # 5 seconds +FILTER_DT = 1. / (micd.SAMPLE_RATE / micd.FFT_SAMPLES) + +AMBIENT_DB = 30 # DB where MIN_VOLUME is applied +DB_SCALE = 30 # AMBIENT_DB + DB_SCALE is where MAX_VOLUME is applied + +AudibleAlert = car.CarControl.HUDControl.AudibleAlert + + +sound_list: dict[int, tuple[str, int | None, float]] = { + # AudibleAlert, file name, play count (none for infinite) + AudibleAlert.engage: ("engage.wav", 1, MAX_VOLUME), + AudibleAlert.disengage: ("disengage.wav", 1, MAX_VOLUME), + AudibleAlert.refuse: ("refuse.wav", 1, MAX_VOLUME), + + AudibleAlert.prompt: ("prompt.wav", 1, MAX_VOLUME), + AudibleAlert.promptRepeat: ("prompt.wav", None, MAX_VOLUME), + AudibleAlert.promptDistracted: ("prompt_distracted.wav", None, MAX_VOLUME), + + AudibleAlert.warningSoft: ("warning_soft.wav", None, MAX_VOLUME), + AudibleAlert.warningImmediate: ("warning_immediate.wav", None, MAX_VOLUME), +} + +def check_selfdrive_timeout_alert(sm): + ss_missing = time.monotonic() - sm.recv_time['selfdriveState'] + + if ss_missing > SELFDRIVE_STATE_TIMEOUT: + if sm['selfdriveState'].enabled and (ss_missing - SELFDRIVE_STATE_TIMEOUT) < 10: + return True + + return False + + +class Soundd: + def __init__(self): + self.load_sounds() + + self.current_alert = AudibleAlert.none + self.current_volume = MIN_VOLUME + self.current_sound_frame = 0 + + self.selfdrive_timeout_alert = False + + self.spl_filter_weighted = FirstOrderFilter(0, 2.5, FILTER_DT, initialized=False) + + def load_sounds(self): + self.loaded_sounds: dict[int, np.ndarray] = {} + + # Load all sounds + for sound in sound_list: + filename, play_count, volume = sound_list[sound] + + with wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r') as wavefile: + assert wavefile.getnchannels() == 1 + assert wavefile.getsampwidth() == 2 + assert wavefile.getframerate() == SAMPLE_RATE + + length = wavefile.getnframes() + self.loaded_sounds[sound] = np.frombuffer(wavefile.readframes(length), dtype=np.int16).astype(np.float32) / (2**16/2) + + def get_sound_data(self, frames): # get "frames" worth of data from the current alert sound, looping when required + + ret = np.zeros(frames, dtype=np.float32) + + if self.current_alert != AudibleAlert.none: + num_loops = sound_list[self.current_alert][1] + sound_data = self.loaded_sounds[self.current_alert] + written_frames = 0 + + current_sound_frame = self.current_sound_frame % len(sound_data) + loops = self.current_sound_frame // len(sound_data) + + while written_frames < frames and (num_loops is None or loops < num_loops): + available_frames = sound_data.shape[0] - current_sound_frame + frames_to_write = min(available_frames, frames - written_frames) + ret[written_frames:written_frames+frames_to_write] = sound_data[current_sound_frame:current_sound_frame+frames_to_write] + written_frames += frames_to_write + self.current_sound_frame += frames_to_write + + return ret * self.current_volume + + def callback(self, data_out: np.ndarray, frames: int, time, status) -> None: + if status: + cloudlog.warning(f"soundd stream over/underflow: {status}") + data_out[:frames, 0] = self.get_sound_data(frames) + + def update_alert(self, new_alert): + current_alert_played_once = self.current_alert == AudibleAlert.none or self.current_sound_frame > len(self.loaded_sounds[self.current_alert]) + if self.current_alert != new_alert and (new_alert != AudibleAlert.none or current_alert_played_once): + self.current_alert = new_alert + self.current_sound_frame = 0 + + def get_audible_alert(self, sm): + if sm.updated['selfdriveState']: + new_alert = sm['selfdriveState'].alertSound.raw + self.update_alert(new_alert) + elif check_selfdrive_timeout_alert(sm): + self.update_alert(AudibleAlert.warningImmediate) + self.selfdrive_timeout_alert = True + elif self.selfdrive_timeout_alert: + self.update_alert(AudibleAlert.none) + self.selfdrive_timeout_alert = False + + def calculate_volume(self, weighted_db): + volume = ((weighted_db - AMBIENT_DB) / DB_SCALE) * (MAX_VOLUME - MIN_VOLUME) + MIN_VOLUME + return math.pow(10, (np.clip(volume, MIN_VOLUME, MAX_VOLUME) - 1)) + + @retry(attempts=7, delay=3) + def get_stream(self, sd): + # reload sounddevice to reinitialize portaudio + sd._terminate() + sd._initialize() + return sd.OutputStream(channels=1, samplerate=SAMPLE_RATE, callback=self.callback, blocksize=SAMPLE_BUFFER) + + def soundd_thread(self): + # sounddevice must be imported after forking processes + import sounddevice as sd + + sm = messaging.SubMaster(['selfdriveState', 'soundPressure']) + + with self.get_stream(sd) as stream: + rk = Ratekeeper(20) + + cloudlog.info(f"soundd stream started: {stream.samplerate=} {stream.channels=} {stream.dtype=} {stream.device=}, {stream.blocksize=}") + while True: + sm.update(0) + + if sm.updated['soundPressure'] and self.current_alert == AudibleAlert.none: # only update volume filter when not playing alert + self.spl_filter_weighted.update(sm["soundPressure"].soundPressureWeightedDb) + self.current_volume = self.calculate_volume(float(self.spl_filter_weighted.x)) + + self.get_audible_alert(sm) + + rk.keep_time() + + assert stream.active + + +def main(): + s = Soundd() + s.soundd_thread() + + +if __name__ == "__main__": + main() diff --git a/selfdrive/ui/tests/.gitignore b/selfdrive/ui/tests/.gitignore new file mode 100644 index 0000000000..91898ac59a --- /dev/null +++ b/selfdrive/ui/tests/.gitignore @@ -0,0 +1,3 @@ +test +test_translations +test_ui/report_1 \ No newline at end of file diff --git a/selfdrive/ui/tests/__init__.py b/selfdrive/ui/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/ui/tests/body.py b/selfdrive/ui/tests/body.py new file mode 100755 index 0000000000..07a2ef5128 --- /dev/null +++ b/selfdrive/ui/tests/body.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +import time +import cereal.messaging as messaging + +if __name__ == "__main__": + while True: + pm = messaging.PubMaster(['carParams', 'carState']) + batt = 1. + while True: + msg = messaging.new_message('carParams') + msg.carParams.brand = "body" + msg.carParams.notCar = True + pm.send('carParams', msg) + + for b in range(100, 0, -1): + msg = messaging.new_message('carState') + msg.carState.charging = True + msg.carState.fuelGauge = b / 100. + pm.send('carState', msg) + time.sleep(0.1) + + time.sleep(1) diff --git a/selfdrive/ui/tests/create_test_translations.sh b/selfdrive/ui/tests/create_test_translations.sh new file mode 100755 index 0000000000..ed0890d946 --- /dev/null +++ b/selfdrive/ui/tests/create_test_translations.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -e + +UI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"/.. +TEST_TEXT="(WRAPPED_SOURCE_TEXT)" +TEST_TS_FILE=$UI_DIR/translations/main_test_en.ts +TEST_QM_FILE=$UI_DIR/translations/main_test_en.qm + +# translation strings +UNFINISHED="<\/translation>" +TRANSLATED="$TEST_TEXT<\/translation>" + +mkdir -p $UI_DIR/translations +rm -f $TEST_TS_FILE $TEST_QM_FILE +lupdate -recursive "$UI_DIR" -ts $TEST_TS_FILE +sed -i "s/$UNFINISHED/$TRANSLATED/" $TEST_TS_FILE +lrelease $TEST_TS_FILE diff --git a/selfdrive/ui/tests/cycle_offroad_alerts.py b/selfdrive/ui/tests/cycle_offroad_alerts.py new file mode 100755 index 0000000000..e468d88e0e --- /dev/null +++ b/selfdrive/ui/tests/cycle_offroad_alerts.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +import os +import sys +import time +import json + +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert + +if __name__ == "__main__": + params = Params() + + with open(os.path.join(BASEDIR, "selfdrive/selfdrived/alerts_offroad.json")) as f: + offroad_alerts = json.load(f) + + t = 10 if len(sys.argv) < 2 else int(sys.argv[1]) + while True: + print("setting alert update") + params.put_bool("UpdateAvailable", True) + r = open(os.path.join(BASEDIR, "RELEASES.md")).read() + r = r[:r.find('\n\n')] # Slice latest release notes + params.put("UpdaterNewReleaseNotes", r + "\n") + + time.sleep(t) + params.put_bool("UpdateAvailable", False) + + # cycle through normal alerts + for a in offroad_alerts: + print("setting alert:", a) + set_offroad_alert(a, True) + time.sleep(t) + set_offroad_alert(a, False) + + print("no alert") + time.sleep(t) diff --git a/selfdrive/ui/tests/test_feedbackd.py b/selfdrive/ui/tests/test_feedbackd.py new file mode 100644 index 0000000000..6b7ec44863 --- /dev/null +++ b/selfdrive/ui/tests/test_feedbackd.py @@ -0,0 +1,53 @@ +import pytest +import cereal.messaging as messaging +from cereal import car +from openpilot.common.params import Params +from openpilot.system.manager.process_config import managed_processes + + +@pytest.mark.skip("tmp disabled") +class TestFeedbackd: + def setup_method(self): + self.pm = messaging.PubMaster(['carState', 'rawAudioData']) + self.sm = messaging.SubMaster(['audioFeedback']) + + def _send_lkas_button(self, pressed: bool): + msg = messaging.new_message('carState') + msg.carState.canValid = True + msg.carState.buttonEvents = [{'type': car.CarState.ButtonEvent.Type.lkas, 'pressed': pressed}] + self.pm.send('carState', msg) + + def _send_audio_data(self, count: int = 5): + for _ in range(count): + audio_msg = messaging.new_message('rawAudioData') + audio_msg.rawAudioData.data = bytes(1600) # 800 samples of int16 + audio_msg.rawAudioData.sampleRate = 16000 + self.pm.send('rawAudioData', audio_msg) + self.sm.update(timeout=100) + + @pytest.mark.parametrize("record_feedback", [False, True]) + def test_audio_feedback(self, record_feedback): + Params().put_bool("RecordAudioFeedback", record_feedback) + + managed_processes["feedbackd"].start() + assert self.pm.wait_for_readers_to_update('carState', timeout=5) + assert self.pm.wait_for_readers_to_update('rawAudioData', timeout=5) + + self._send_lkas_button(pressed=True) + self._send_audio_data() + self._send_lkas_button(pressed=False) + self._send_audio_data() + + if record_feedback: + assert self.sm.updated['audioFeedback'], "audioFeedback should be published when enabled" + else: + assert not self.sm.updated['audioFeedback'], "audioFeedback should not be published when disabled" + + self._send_lkas_button(pressed=True) + self._send_audio_data() + self._send_lkas_button(pressed=False) + self._send_audio_data() + + assert not self.sm.updated['audioFeedback'], "audioFeedback should not be published after second press" + + managed_processes["feedbackd"].stop() diff --git a/selfdrive/ui/tests/test_raylib_ui.py b/selfdrive/ui/tests/test_raylib_ui.py new file mode 100644 index 0000000000..3f23301972 --- /dev/null +++ b/selfdrive/ui/tests/test_raylib_ui.py @@ -0,0 +1,8 @@ +import time +from openpilot.selfdrive.test.helpers import with_processes + + +@with_processes(["raylib_ui"]) +def test_raylib_ui(): + """Test initialization of the UI widgets is successful.""" + time.sleep(1) diff --git a/selfdrive/ui/tests/test_runner.cc b/selfdrive/ui/tests/test_runner.cc new file mode 100644 index 0000000000..c8cc0d3e05 --- /dev/null +++ b/selfdrive/ui/tests/test_runner.cc @@ -0,0 +1,26 @@ +#define CATCH_CONFIG_RUNNER +#include "catch2/catch.hpp" + +#include +#include +#include +#include + +int main(int argc, char **argv) { + // unit tests for Qt + QApplication app(argc, argv); + + QString language_file = "main_test_en"; + // FIXME: pytest-cpp considers this print as a test case + qDebug() << "Loading language:" << language_file; + + QTranslator translator; + QString translationsPath = QDir::cleanPath(qApp->applicationDirPath() + "/../translations"); + if (!translator.load(language_file, translationsPath)) { + qDebug() << "Failed to load translation file!"; + } + app.installTranslator(&translator); + + const int res = Catch::Session().run(argc, argv); + return (res < 0xff ? res : 0xff); +} diff --git a/selfdrive/ui/tests/test_soundd.py b/selfdrive/ui/tests/test_soundd.py new file mode 100644 index 0000000000..a9da8455eb --- /dev/null +++ b/selfdrive/ui/tests/test_soundd.py @@ -0,0 +1,35 @@ +from cereal import car +from cereal import messaging +from cereal.messaging import SubMaster, PubMaster +from openpilot.selfdrive.ui.soundd import SELFDRIVE_STATE_TIMEOUT, check_selfdrive_timeout_alert + +import time + +AudibleAlert = car.CarControl.HUDControl.AudibleAlert + + +class TestSoundd: + def test_check_selfdrive_timeout_alert(self): + sm = SubMaster(['selfdriveState']) + pm = PubMaster(['selfdriveState']) + + for _ in range(100): + cs = messaging.new_message('selfdriveState') + cs.selfdriveState.enabled = True + + pm.send("selfdriveState", cs) + + time.sleep(0.01) + + sm.update(0) + + assert not check_selfdrive_timeout_alert(sm) + + for _ in range(SELFDRIVE_STATE_TIMEOUT * 110): + sm.update(0) + time.sleep(0.01) + + assert check_selfdrive_timeout_alert(sm) + + # TODO: add test with micd for checking that soundd actually outputs sounds + diff --git a/selfdrive/ui/tests/test_translations.cc b/selfdrive/ui/tests/test_translations.cc new file mode 100644 index 0000000000..fcefc5784f --- /dev/null +++ b/selfdrive/ui/tests/test_translations.cc @@ -0,0 +1,48 @@ +#include "catch2/catch.hpp" + +#include "common/params.h" +#include "selfdrive/ui/qt/window.h" + +const QString TEST_TEXT = "(WRAPPED_SOURCE_TEXT)"; // what each string should be translated to +QRegExp RE_NUM("\\d*"); + +QStringList getParentWidgets(QWidget* widget){ + QStringList parentWidgets; + while (widget->parentWidget() != Q_NULLPTR) { + widget = widget->parentWidget(); + parentWidgets.append(widget->metaObject()->className()); + } + return parentWidgets; +} + +template +void checkWidgetTrWrap(MainWindow &w) { + for (auto widget : w.findChildren()) { + const QString text = widget->text(); + bool isNumber = RE_NUM.exactMatch(text); + bool wrapped = text.contains(TEST_TEXT); + QString parentWidgets = getParentWidgets(widget).join("->"); + + if (!text.isEmpty() && !isNumber && !wrapped) { + FAIL(("\"" + text + "\" must be wrapped. Parent widgets: " + parentWidgets).toStdString()); + } + + // warn if source string wrapped, but UI adds text + // TODO: add way to ignore this + if (wrapped && text != TEST_TEXT) { + WARN(("\"" + text + "\" is dynamic and needs a custom retranslate function. Parent widgets: " + parentWidgets).toStdString()); + } + } +} + +// Tests all strings in the UI are wrapped with tr() +TEST_CASE("UI: test all strings wrapped") { + Params().remove("LanguageSetting"); + Params().remove("HardwareSerial"); + Params().remove("DongleId"); + qputenv("TICI", "1"); + + MainWindow w; + checkWidgetTrWrap(w); + checkWidgetTrWrap(w); +} diff --git a/selfdrive/ui/tests/test_translations.py b/selfdrive/ui/tests/test_translations.py new file mode 100644 index 0000000000..2ae3356bb8 --- /dev/null +++ b/selfdrive/ui/tests/test_translations.py @@ -0,0 +1,124 @@ +import pytest +import json +import os +import re +import xml.etree.ElementTree as ET +import string +import requests +from parameterized import parameterized_class + +from openpilot.selfdrive.ui.update_translations import TRANSLATIONS_DIR, LANGUAGES_FILE + +with open(LANGUAGES_FILE) as f: + translation_files = json.load(f) + +UNFINISHED_TRANSLATION_TAG = "" not in cur_translations, \ + f"{self.file} ({self.name}) translation file has obsolete translations. Run selfdrive/ui/update_translations.py --vanish to remove them" + + def test_finished_translations(self): + """ + Tests ran on each translation marked "finished" + Plural: + - that any numerus (plural) translations have all plural forms non-empty + - that the correct format specifier is used (%n) + Non-plural: + - that translation is not empty + - that translation format arguments are consistent + """ + tr_xml = ET.parse(os.path.join(TRANSLATIONS_DIR, f"{self.file}.ts")) + + for context in tr_xml.getroot(): + for message in context.iterfind("message"): + translation = message.find("translation") + source_text = message.find("source").text + + # Do not test unfinished translations + if translation.get("type") == "unfinished": + continue + + if message.get("numerus") == "yes": + numerusform = [t.text for t in translation.findall("numerusform")] + + for nf in numerusform: + assert nf is not None, f"Ensure all plural translation forms are completed: {source_text}" + assert "%n" in nf, "Ensure numerus argument (%n) exists in translation." + assert FORMAT_ARG.search(nf) is None, f"Plural translations must use %n, not %1, %2, etc.: {numerusform}" + + else: + assert translation.text is not None, f"Ensure translation is completed: {source_text}" + + source_args = FORMAT_ARG.findall(source_text) + translation_args = FORMAT_ARG.findall(translation.text) + assert sorted(source_args) == sorted(translation_args), \ + f"Ensure format arguments are consistent: `{source_text}` vs. `{translation.text}`" + + def test_no_locations(self): + for line in self._read_translation_file(TRANSLATIONS_DIR, self.file).splitlines(): + assert not line.strip().startswith(LOCATION_TAG), \ + f"Line contains location tag: {line.strip()}, remove all line numbers." + + def test_entities_error(self): + cur_translations = self._read_translation_file(TRANSLATIONS_DIR, self.file) + matches = re.findall(r'@(\w+);', cur_translations) + assert len(matches) == 0, f"The string(s) {matches} were found with '@' instead of '&'" + + def test_bad_language(self): + IGNORED_WORDS = {'pédale'} + + match = re.search(r'_([a-zA-Z]{2,3})', self.file) + assert match, f"{self.name} - could not parse language" + + try: + response = requests.get( + f"https://raw.githubusercontent.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/{match.group(1)}" + ) + response.raise_for_status() + except requests.exceptions.HTTPError as e: + if e.response is not None and e.response.status_code == 429: + pytest.skip("word list rate limited") + raise + + banned_words = {line.strip() for line in response.text.splitlines()} + + for context in ET.parse(os.path.join(TRANSLATIONS_DIR, f"{self.file}.ts")).getroot(): + for message in context.iterfind("message"): + translation = message.find("translation") + if translation.get("type") == "unfinished": + continue + + translation_text = " ".join([t.text for t in translation.findall("numerusform")]) if message.get("numerus") == "yes" else translation.text + + if not translation_text: + continue + + words = set(translation_text.translate(str.maketrans('', '', string.punctuation + '%n')).lower().split()) + bad_words_found = words & (banned_words - IGNORED_WORDS) + assert not bad_words_found, f"Bad language found in {self.name}: '{translation_text}'. Bad word(s): {', '.join(bad_words_found)}" diff --git a/selfdrive/ui/tests/test_ui/print_mouse_coords.py b/selfdrive/ui/tests/test_ui/print_mouse_coords.py new file mode 100755 index 0000000000..1e88ce57d3 --- /dev/null +++ b/selfdrive/ui/tests/test_ui/print_mouse_coords.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +""" +Simple script to print mouse coordinates on Ubuntu. +Run with: python print_mouse_coords.py +Press Ctrl+C to exit. +""" + +from pynput import mouse + +print("Mouse coordinate printer - Press Ctrl+C to exit") +print("Click to set the top left origin") + +origin: tuple[int, int] | None = None +clicks: list[tuple[int, int]] = [] + + +def on_click(x, y, button, pressed): + global origin, clicks + if pressed: # Only on mouse down, not up + if origin is None: + origin = (x, y) + print(f"Origin set to: {x},{y}") + else: + rel_x = x - origin[0] + rel_y = y - origin[1] + clicks.append((rel_x, rel_y)) + print(f"Clicks: {clicks}") + + +if __name__ == "__main__": + try: + # Start mouse listener + with mouse.Listener(on_click=on_click) as listener: + listener.join() + except KeyboardInterrupt: + print("\nExiting...") diff --git a/selfdrive/ui/tests/test_ui/raylib_screenshots.py b/selfdrive/ui/tests/test_ui/raylib_screenshots.py new file mode 100755 index 0000000000..e77a2d4d7e --- /dev/null +++ b/selfdrive/ui/tests/test_ui/raylib_screenshots.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +import os +import sys +import shutil +import time +import pathlib +from collections import namedtuple + +import pyautogui +import pywinctl + +from cereal import log +from cereal import messaging +from cereal.messaging import PubMaster +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.common.prefix import OpenpilotPrefix +from openpilot.selfdrive.test.helpers import with_processes +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.system.updated.updated import parse_release_notes + +TEST_DIR = pathlib.Path(__file__).parent +TEST_OUTPUT_DIR = TEST_DIR / "raylib_report" +SCREENSHOTS_DIR = TEST_OUTPUT_DIR / "screenshots" +UI_DELAY = 0.2 + +# Offroad alerts to test +OFFROAD_ALERTS = ['Offroad_IsTakingSnapshot'] + + +def put_update_params(params: Params): + params.put("UpdaterCurrentReleaseNotes", parse_release_notes(BASEDIR)) + params.put("UpdaterNewReleaseNotes", parse_release_notes(BASEDIR)) + description = "0.10.1 / this-is-a-really-super-mega-long-branch-name / 7864838 / Oct 03" + params.put("UpdaterCurrentDescription", description) + params.put("UpdaterNewDescription", description) + + +def setup_homescreen(click, pm: PubMaster): + pass + + +def setup_settings(click, pm: PubMaster): + click(100, 100) + + +def close_settings(click, pm: PubMaster): + click(240, 216) + + +def setup_settings_network(click, pm: PubMaster): + setup_settings(click, pm) + click(278, 450) + + +def setup_settings_toggles(click, pm: PubMaster): + setup_settings(click, pm) + click(278, 600) + + +def setup_settings_software(click, pm: PubMaster): + put_update_params(Params()) + setup_settings(click, pm) + click(278, 720) + + +def setup_settings_firehose(click, pm: PubMaster): + setup_settings(click, pm) + click(278, 845) + + +def setup_settings_developer(click, pm: PubMaster): + setup_settings(click, pm) + click(278, 950) + + +def setup_keyboard(click, pm: PubMaster): + setup_settings_developer(click, pm) + click(1930, 270) + + +def setup_pair_device(click, pm: PubMaster): + click(1950, 800) + + +def setup_offroad_alert(click, pm: PubMaster): + set_offroad_alert("Offroad_TemperatureTooHigh", True, extra_text='99C') + set_offroad_alert("Offroad_ExcessiveActuation", True, extra_text='longitudinal') + for alert in OFFROAD_ALERTS: + set_offroad_alert(alert, True) + + setup_settings(click, pm) + close_settings(click, pm) + + +def setup_confirmation_dialog(click, pm: PubMaster): + setup_settings(click, pm) + click(1985, 791) # reset calibration + + +def setup_homescreen_update_available(click, pm: PubMaster): + params = Params() + params.put_bool("UpdateAvailable", True) + put_update_params(params) + setup_settings(click, pm) + close_settings(click, pm) + + +def setup_software_release_notes(click, pm: PubMaster): + setup_settings(click, pm) + setup_settings_software(click, pm) + click(588, 110) # expand description for current version + + +CASES = { + "homescreen": setup_homescreen, + "settings_device": setup_settings, + "settings_network": setup_settings_network, + "settings_toggles": setup_settings_toggles, + "settings_software": setup_settings_software, + "settings_firehose": setup_settings_firehose, + "settings_developer": setup_settings_developer, + "keyboard": setup_keyboard, + "pair_device": setup_pair_device, + "offroad_alert": setup_offroad_alert, + "homescreen_update_available": setup_homescreen_update_available, + "confirmation_dialog": setup_confirmation_dialog, + "software_release_notes": setup_software_release_notes, +} + + +class TestUI: + def __init__(self): + os.environ["SCALE"] = os.getenv("SCALE", "1") + sys.modules["mouseinfo"] = False + + def setup(self): + # Seed minimal offroad state + self.pm = PubMaster(["deviceState"]) + ds = messaging.new_message('deviceState') + ds.deviceState.networkType = log.DeviceState.NetworkType.wifi + for _ in range(5): + self.pm.send('deviceState', ds) + ds.clear_write_flag() + time.sleep(0.05) + time.sleep(0.5) + try: + self.ui = pywinctl.getWindowsWithTitle("UI")[0] + except Exception as e: + print(f"failed to find ui window, assuming that it's in the top left (for Xvfb) {e}") + self.ui = namedtuple("bb", ["left", "top", "width", "height"])(0, 0, 2160, 1080) + + def screenshot(self, name: str): + full_screenshot = pyautogui.screenshot() + cropped = full_screenshot.crop((self.ui.left, self.ui.top, self.ui.left + self.ui.width, self.ui.top + self.ui.height)) + cropped.save(SCREENSHOTS_DIR / f"{name}.png") + + def click(self, x: int, y: int, *args, **kwargs): + pyautogui.mouseDown(self.ui.left + x, self.ui.top + y, *args, **kwargs) + time.sleep(0.01) + pyautogui.mouseUp(self.ui.left + x, self.ui.top + y, *args, **kwargs) + + @with_processes(["raylib_ui"]) + def test_ui(self, name, setup_case): + self.setup() + time.sleep(UI_DELAY) # wait for UI to start + setup_case(self.click, self.pm) + self.screenshot(name) + + +def create_screenshots(): + if TEST_OUTPUT_DIR.exists(): + shutil.rmtree(TEST_OUTPUT_DIR) + SCREENSHOTS_DIR.mkdir(parents=True) + + t = TestUI() + with OpenpilotPrefix(): + params = Params() + params.put("DongleId", "123456789012345") + for name, setup in CASES.items(): + t.test_ui(name, setup) + + +if __name__ == "__main__": + create_screenshots() diff --git a/selfdrive/ui/tests/test_ui/run.py b/selfdrive/ui/tests/test_ui/run.py new file mode 100755 index 0000000000..32aead0b4f --- /dev/null +++ b/selfdrive/ui/tests/test_ui/run.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python3 +import capnp +import pathlib +import shutil +import sys +import os +import pywinctl +import pyautogui +import pickle +import time +from collections import namedtuple + +from cereal import car, log +from msgq.visionipc import VisionIpcServer, VisionStreamType +from cereal.messaging import PubMaster, log_from_bytes, sub_sock +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.common.prefix import OpenpilotPrefix +from openpilot.common.transformations.camera import CameraConfig, DEVICE_CAMERAS +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.selfdrive.test.helpers import with_processes +from openpilot.selfdrive.test.process_replay.migration import migrate, migrate_controlsState, migrate_carState +from openpilot.tools.lib.logreader import LogReader +from openpilot.tools.lib.framereader import FrameReader +from openpilot.tools.lib.route import Route +from openpilot.tools.lib.cache import DEFAULT_CACHE_DIR + +UI_DELAY = 0.1 # may be slower on CI? +TEST_ROUTE = "a2a0ccea32023010|2023-07-27--13-01-19" + +STREAMS: list[tuple[VisionStreamType, CameraConfig, bytes]] = [] +OFFROAD_ALERTS = ['Offroad_IsTakingSnapshot', ] +DATA: dict[str, capnp.lib.capnp._DynamicStructBuilder] = dict.fromkeys( + ["carParams", "deviceState", "pandaStates", "controlsState", "selfdriveState", + "liveCalibration", "modelV2", "radarState", "driverMonitoringState", "carState", + "driverStateV2", "roadCameraState", "wideRoadCameraState", "driverCameraState"], None) + +def setup_homescreen(click, pm: PubMaster): + pass + +def setup_settings_device(click, pm: PubMaster): + click(100, 100) + +def setup_settings_toggles(click, pm: PubMaster): + setup_settings_device(click, pm) + click(278, 600) + time.sleep(UI_DELAY) + +def setup_settings_software(click, pm: PubMaster): + setup_settings_device(click, pm) + click(278, 720) + time.sleep(UI_DELAY) + +def setup_settings_firehose(click, pm: PubMaster): + click(1780, 730) + +def setup_settings_developer(click, pm: PubMaster): + CP = car.CarParams() + CP.alphaLongitudinalAvailable = True + Params().put("CarParamsPersistent", CP.to_bytes()) + + setup_settings_device(click, pm) + click(278, 970) + time.sleep(UI_DELAY) + +def setup_onroad(click, pm: PubMaster): + vipc_server = VisionIpcServer("camerad") + for stream_type, cam, _ in STREAMS: + vipc_server.create_buffers(stream_type, 5, cam.width, cam.height) + vipc_server.start_listener() + + uidebug_received_cnt = 0 + packet_id = 0 + uidebug_sock = sub_sock('uiDebug') + + # Condition check for uiDebug processing + check_uidebug = DATA['deviceState'].deviceState.started and not DATA['carParams'].carParams.notCar + + # Loop until 20 'uiDebug' messages are received + while uidebug_received_cnt <= 20: + for service, data in DATA.items(): + if data: + data.clear_write_flag() + pm.send(service, data) + + for stream_type, _, image in STREAMS: + vipc_server.send(stream_type, image, packet_id, packet_id, packet_id) + + if check_uidebug: + while uidebug_sock.receive(non_blocking=True): + uidebug_received_cnt += 1 + else: + uidebug_received_cnt += 1 + + packet_id += 1 + time.sleep(0.05) + +def setup_onroad_disengaged(click, pm: PubMaster): + DATA['selfdriveState'].selfdriveState.enabled = False + setup_onroad(click, pm) + DATA['selfdriveState'].selfdriveState.enabled = True + +def setup_onroad_override(click, pm: PubMaster): + DATA['selfdriveState'].selfdriveState.state = log.SelfdriveState.OpenpilotState.overriding + setup_onroad(click, pm) + DATA['selfdriveState'].selfdriveState.state = log.SelfdriveState.OpenpilotState.enabled + + +def setup_onroad_wide(click, pm: PubMaster): + DATA['selfdriveState'].selfdriveState.experimentalMode = True + DATA["carState"].carState.vEgo = 1 + setup_onroad(click, pm) + +def setup_onroad_sidebar(click, pm: PubMaster): + setup_onroad(click, pm) + click(500, 500) + setup_onroad(click, pm) + +def setup_onroad_wide_sidebar(click, pm: PubMaster): + setup_onroad_wide(click, pm) + click(500, 500) + setup_onroad_wide(click, pm) + +def setup_body(click, pm: PubMaster): + DATA['carParams'].carParams.brand = "body" + DATA['carParams'].carParams.notCar = True + DATA['carState'].carState.charging = True + DATA['carState'].carState.fuelGauge = 50.0 + setup_onroad(click, pm) + +def setup_keyboard(click, pm: PubMaster): + setup_settings_device(click, pm) + click(250, 965) + click(1930, 420) + +def setup_keyboard_uppercase(click, pm: PubMaster): + setup_keyboard(click, pm) + click(200, 800) + +def setup_driver_camera(click, pm: PubMaster): + setup_settings_device(click, pm) + click(1950, 435) + DATA['deviceState'].deviceState.started = False + setup_onroad(click, pm) + DATA['deviceState'].deviceState.started = True + +def setup_onroad_alert(click, pm: PubMaster, text1, text2, size, status=log.SelfdriveState.AlertStatus.normal): + print(f'setup onroad alert, size: {size}') + state = DATA['selfdriveState'] + origin_state_bytes = state.to_bytes() + cs = state.selfdriveState + cs.alertText1 = text1 + cs.alertText2 = text2 + cs.alertSize = size + cs.alertStatus = status + cs.alertType = "test_onroad_alert" + setup_onroad(click, pm) + DATA['selfdriveState'] = log_from_bytes(origin_state_bytes).as_builder() + +def setup_onroad_alert_small(click, pm: PubMaster): + setup_onroad_alert(click, pm, 'This is a small alert message', '', log.SelfdriveState.AlertSize.small) + +def setup_onroad_alert_mid(click, pm: PubMaster): + setup_onroad_alert(click, pm, 'Medium Alert', 'This is a medium alert message', log.SelfdriveState.AlertSize.mid) + +def setup_onroad_alert_full(click, pm: PubMaster): + setup_onroad_alert(click, pm, 'Full Alert', 'This is a full alert message', log.SelfdriveState.AlertSize.full) + +def setup_offroad_alert(click, pm: PubMaster): + for alert in OFFROAD_ALERTS: + set_offroad_alert(alert, True) + + # Toggle between settings and home to refresh the offroad alert widget + setup_settings_device(click, pm) + click(240, 216) + +def setup_update_available(click, pm: PubMaster): + Params().put_bool("UpdateAvailable", True) + release_notes_path = os.path.join(BASEDIR, "RELEASES.md") + with open(release_notes_path) as file: + release_notes = file.read().split('\n\n', 1)[0] + Params().put("UpdaterNewReleaseNotes", release_notes + "\n") + + setup_settings_device(click, pm) + click(240, 216) + +def setup_pair_device(click, pm: PubMaster): + click(1950, 435) + click(1800, 900) + +CASES = { + "homescreen": setup_homescreen, + "prime": setup_homescreen, + "pair_device": setup_pair_device, + "settings_device": setup_settings_device, + "settings_toggles": setup_settings_toggles, + "settings_software": setup_settings_software, + "settings_firehose": setup_settings_firehose, + "settings_developer": setup_settings_developer, + "onroad": setup_onroad, + "onroad_disengaged": setup_onroad_disengaged, + "onroad_override": setup_onroad_override, + "onroad_sidebar": setup_onroad_sidebar, + "onroad_alert_small": setup_onroad_alert_small, + "onroad_alert_mid": setup_onroad_alert_mid, + "onroad_alert_full": setup_onroad_alert_full, + "onroad_wide": setup_onroad_wide, + "onroad_wide_sidebar": setup_onroad_wide_sidebar, + "driver_camera": setup_driver_camera, + "body": setup_body, + "offroad_alert": setup_offroad_alert, + "update_available": setup_update_available, + "keyboard": setup_keyboard, + "keyboard_uppercase": setup_keyboard_uppercase +} + +TEST_DIR = pathlib.Path(__file__).parent + +TEST_OUTPUT_DIR = TEST_DIR / "report_1" +SCREENSHOTS_DIR = TEST_OUTPUT_DIR / "screenshots" + + +class TestUI: + def __init__(self): + os.environ["SCALE"] = "1" + sys.modules["mouseinfo"] = False + + def setup(self): + self.pm = PubMaster(list(DATA.keys())) + DATA['deviceState'].deviceState.networkType = log.DeviceState.NetworkType.wifi + DATA['deviceState'].deviceState.lastAthenaPingTime = 0 + for _ in range(10): + self.pm.send('deviceState', DATA['deviceState']) + DATA['deviceState'].clear_write_flag() + time.sleep(0.05) + try: + self.ui = pywinctl.getWindowsWithTitle("ui")[0] + except Exception as e: + print(f"failed to find ui window, assuming that it's in the top left (for Xvfb) {e}") + self.ui = namedtuple("bb", ["left", "top", "width", "height"])(0,0,2160,1080) + + def screenshot(self, name): + im = pyautogui.screenshot(SCREENSHOTS_DIR / f"{name}.png", region=(self.ui.left, self.ui.top, self.ui.width, self.ui.height)) + assert im.width == 2160 + assert im.height == 1080 + + def click(self, x, y, *args, **kwargs): + pyautogui.click(self.ui.left + x, self.ui.top + y, *args, **kwargs) + time.sleep(UI_DELAY) # give enough time for the UI to react + + @with_processes(["ui"]) + def test_ui(self, name, setup_case): + self.setup() + setup_case(self.click, self.pm) + self.screenshot(name) + +def create_screenshots(): + if TEST_OUTPUT_DIR.exists(): + shutil.rmtree(TEST_OUTPUT_DIR) + + SCREENSHOTS_DIR.mkdir(parents=True) + + route = Route(TEST_ROUTE) + + segnum = 2 + lr = LogReader(route.qlog_paths()[segnum]) + DATA['carParams'] = next((event.as_builder() for event in lr if event.which() == 'carParams'), None) + for event in migrate(lr, [migrate_controlsState, migrate_carState]): + if event.which() in DATA: + DATA[event.which()] = event.as_builder() + + if all(DATA.values()): + break + + cam = DEVICE_CAMERAS[("tici", "ar0231")] + + frames_cache = f'{DEFAULT_CACHE_DIR}/ui_frames' + if os.path.isfile(frames_cache): + with open(frames_cache, 'rb') as f: + frames = pickle.load(f) + road_img = frames[0] + wide_road_img = frames[1] + driver_img = frames[2] + else: + with open(frames_cache, 'wb') as f: + road_img = FrameReader(route.camera_paths()[segnum], pix_fmt="nv12").get(0) + wide_road_img = FrameReader(route.ecamera_paths()[segnum], pix_fmt="nv12").get(0) + driver_img = FrameReader(route.dcamera_paths()[segnum], pix_fmt="nv12").get(0) + pickle.dump([road_img, wide_road_img, driver_img], f) + + STREAMS.append((VisionStreamType.VISION_STREAM_ROAD, cam.fcam, road_img.flatten().tobytes())) + STREAMS.append((VisionStreamType.VISION_STREAM_WIDE_ROAD, cam.ecam, wide_road_img.flatten().tobytes())) + STREAMS.append((VisionStreamType.VISION_STREAM_DRIVER, cam.dcam, driver_img.flatten().tobytes())) + + t = TestUI() + + for name, setup in CASES.items(): + with OpenpilotPrefix(): + params = Params() + params.put("DongleId", "123456789012345") + if name == 'prime': + params.put('PrimeType', 1) + elif name == 'pair_device': + params.put('ApiCache_Device', {"is_paired":0, "prime_type":-1}) + + t.test_ui(name, setup) + +if __name__ == "__main__": + print("creating test screenshots") + create_screenshots() diff --git a/selfdrive/ui/tests/test_ui/template.html b/selfdrive/ui/tests/test_ui/template.html new file mode 100644 index 0000000000..68df5879e6 --- /dev/null +++ b/selfdrive/ui/tests/test_ui/template.html @@ -0,0 +1,34 @@ + + + + +{% for name, (image, ref_image) in cases.items() %} + +

    {{name}}

    +
    +
    + +
    +
    + +
    + +{% endfor %} + \ No newline at end of file diff --git a/selfdrive/ui/translations/README.md b/selfdrive/ui/translations/README.md new file mode 100644 index 0000000000..4f11fe3388 --- /dev/null +++ b/selfdrive/ui/translations/README.md @@ -0,0 +1,71 @@ +# Multilanguage + +[![languages](https://raw.githubusercontent.com/commaai/openpilot/badges/translation_badge.svg)](#) + +## Contributing + +Before getting started, make sure you have set up the openpilot Ubuntu development environment by reading the [tools README.md](/tools/README.md). + +### Policy + +Most of the languages supported by openpilot come from and are maintained by the community via pull requests. A pull request likely to be merged is one that [fixes a translation or adds missing translations.](https://github.com/commaai/openpilot/blob/master/selfdrive/ui/translations/README.md#improving-an-existing-language) + +We also generally merge pull requests adding support for a new language if there are community members willing to maintain it. Maintaining a language is ensuring quality and completion of translations before each openpilot release. + +comma may remove or hide language support from releases depending on translation quality and completeness. + +### Adding a New Language + +openpilot provides a few tools to help contributors manage their translations and to ensure quality. To get started: + +1. Add your new language to [languages.json](/selfdrive/ui/translations/languages.json) with the appropriate [language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) and the localized language name (Traditional Chinese is `中文(繁體)`). +2. Generate the XML translation file (`*.ts`): + ```shell + selfdrive/ui/update_translations.py + ``` +3. Edit the translation file, marking each translation as completed: + ```shell + linguist selfdrive/ui/translations/your_language_file.ts + ``` +4. View your finished translations by compiling and starting the UI, then find it in the language selector: + ```shell + scons -j$(nproc) selfdrive/ui && selfdrive/ui/ui + ``` +5. Read [Checking the UI](#checking-the-ui) to double-check your translations fit in the UI. + +### Improving an Existing Language + +Follow step 3. above, you can review existing translations and add missing ones. Once you're done, just open a pull request to openpilot. + +### Checking the UI +Different languages use varying space to convey the same message, so it's a good idea to double-check that your translations do not overlap and fit into each widget. Start the UI (step 4. above) and view each page, making adjustments to translations as needed. + +#### To view offroad alerts: + +With the UI started, you can view the offroad alerts with: +```shell +selfdrive/ui/tests/cycle_offroad_alerts.py +``` + +### Updating the UI + +Any time you edit source code in the UI, you need to update the translations to ensure the line numbers and contexts are up to date (first step above). + +### Testing + +openpilot has a few unit tests to make sure all translations are up-to-date and that all strings are wrapped in a translation marker. They are run in CI, but you can also run them locally. + +Tests translation files up to date: + +```shell +selfdrive/ui/tests/test_translations.py +``` + +Tests all static source strings are wrapped: + +```shell +selfdrive/ui/tests/create_test_translations.sh && selfdrive/ui/tests/test_translations +``` + +--- +![multilanguage_onroad](https://user-images.githubusercontent.com/25857203/178912800-2c798af8-78e3-498e-9e19-35906e0bafff.png) diff --git a/selfdrive/ui/translations/auto_translate.py b/selfdrive/ui/translations/auto_translate.py new file mode 100755 index 0000000000..c2e4bbc552 --- /dev/null +++ b/selfdrive/ui/translations/auto_translate.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 + +import argparse +import json +import os +import pathlib +import xml.etree.ElementTree as ET +from typing import cast + +import requests + +TRANSLATIONS_DIR = pathlib.Path(__file__).resolve().parent +TRANSLATIONS_LANGUAGES = TRANSLATIONS_DIR / "languages.json" + +OPENAI_MODEL = "gpt-4" +OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") +OPENAI_PROMPT = "You are a professional translator from English to {language} (ISO 639 language code). " + \ + "The following sentence or word is in the GUI of a software called openpilot, translate it accordingly." + + +def get_language_files(languages: list[str] = None) -> dict[str, pathlib.Path]: + files = {} + + with open(TRANSLATIONS_LANGUAGES) as fp: + language_dict = json.load(fp) + + for filename in language_dict.values(): + path = TRANSLATIONS_DIR / f"{filename}.ts" + language = path.stem.split("main_")[1] + + if languages is None or language in languages: + files[language] = path + + return files + + +def translate_phrase(text: str, language: str) -> str: + response = requests.post( + "https://api.openai.com/v1/chat/completions", + json={ + "model": OPENAI_MODEL, + "messages": [ + { + "role": "system", + "content": OPENAI_PROMPT.format(language=language), + }, + { + "role": "user", + "content": text, + }, + ], + "temperature": 0.8, + "max_tokens": 1024, + "top_p": 1, + }, + headers={ + "Authorization": f"Bearer {OPENAI_API_KEY}", + "Content-Type": "application/json", + }, + ) + + if 400 <= response.status_code < 600: + raise requests.HTTPError(f'Error {response.status_code}: {response.json()}', response=response) + + data = response.json() + + return cast(str, data["choices"][0]["message"]["content"]) + + +def translate_file(path: pathlib.Path, language: str, all_: bool) -> None: + tree = ET.parse(path) + + root = tree.getroot() + + for context in root.findall("./context"): + name = context.find("name") + if name is None: + raise ValueError("name not found") + + print(f"Context: {name.text}") + + for message in context.findall("./message"): + source = message.find("source") + translation = message.find("translation") + + if source is None or translation is None: + raise ValueError("source or translation not found") + + if not all_ and translation.attrib.get("type") != "unfinished": + continue + + llm_translation = translate_phrase(cast(str, source.text), language) + + print(f"Source: {source.text}\n" + + f"Current translation: {translation.text}\n" + + f"LLM translation: {llm_translation}") + + translation.text = llm_translation + + with path.open("w", encoding="utf-8") as fp: + fp.write('\n' + + '\n' + + ET.tostring(root, encoding="utf-8").decode()) + + +def main(): + arg_parser = argparse.ArgumentParser("Auto translate") + + group = arg_parser.add_mutually_exclusive_group(required=True) + group.add_argument("-a", "--all-files", action="store_true", help="Translate all files") + group.add_argument("-f", "--file", nargs="+", help="Translate the selected files. (Example: -f fr de)") + + arg_parser.add_argument("-t", "--all-translations", action="store_true", default=False, help="Translate all sections. (Default: only unfinished)") + + args = arg_parser.parse_args() + + if OPENAI_API_KEY is None: + print("OpenAI API key is missing. (Hint: use `export OPENAI_API_KEY=YOUR-KEY` before you run the script).\n" + + "If you don't have one go to: https://beta.openai.com/account/api-keys.") + exit(1) + + files = get_language_files(None if args.all_files else args.file) + + if args.file: + missing_files = set(args.file) - set(files) + if len(missing_files): + print(f"No language files found: {missing_files}") + exit(1) + + print(f"Translation mode: {'all' if args.all_translations else 'only unfinished'}. Files: {list(files)}") + + for lang, path in files.items(): + print(f"Translate {lang} ({path})") + translate_file(path, lang, args.all_translations) + + +if __name__ == "__main__": + main() diff --git a/selfdrive/ui/translations/create_badges.py b/selfdrive/ui/translations/create_badges.py new file mode 100755 index 0000000000..3e14c33255 --- /dev/null +++ b/selfdrive/ui/translations/create_badges.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +import json +import os +import requests +import xml.etree.ElementTree as ET + +from openpilot.common.basedir import BASEDIR +from openpilot.selfdrive.ui.tests.test_translations import UNFINISHED_TRANSLATION_TAG +from openpilot.selfdrive.ui.update_translations import LANGUAGES_FILE, TRANSLATIONS_DIR + +TRANSLATION_TAG = " 90 else (204, 55, 27)}" + + # Download badge + badge_label = f"LANGUAGE {name}" + badge_message = f"{percent_finished}% complete" + if unfinished_translations != 0: + badge_message += f" ({unfinished_translations} unfinished)" + + r = requests.get(f"{SHIELDS_URL}/{badge_label}-{badge_message}-{color}", timeout=10) + assert r.status_code == 200, "Error downloading badge" + content_svg = r.content.decode("utf-8") + + xml = ET.fromstring(content_svg) + assert "width" in xml.attrib + max_badge_width = max(max_badge_width, int(xml.attrib["width"])) + + # Make tag ids in each badge unique to combine them into one svg + for tag in ("r", "s"): + content_svg = content_svg.replace(f'id="{tag}"', f'id="{tag}{idx}"') + content_svg = content_svg.replace(f'"url(#{tag})"', f'"url(#{tag}{idx})"') + + badge_svg.extend([f'', content_svg, ""]) + + badge_svg.insert(0, '') + badge_svg.append("") + + with open(os.path.join(BASEDIR, "translation_badge.svg"), "w") as badge_f: + badge_f.write("\n".join(badge_svg)) diff --git a/selfdrive/ui/translations/languages.json b/selfdrive/ui/translations/languages.json new file mode 100644 index 0000000000..132b5088d7 --- /dev/null +++ b/selfdrive/ui/translations/languages.json @@ -0,0 +1,14 @@ +{ + "English": "main_en", + "Deutsch": "main_de", + "Français": "main_fr", + "Português": "main_pt-BR", + "Español": "main_es", + "Türkçe": "main_tr", + "العربية": "main_ar", + "ไทย": "main_th", + "中文(繁體)": "main_zh-CHT", + "中文(简体)": "main_zh-CHS", + "한국어": "main_ko", + "日本語": "main_ja" +} diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts new file mode 100644 index 0000000000..381712770e --- /dev/null +++ b/selfdrive/ui/translations/main_ar.ts @@ -0,0 +1,1090 @@ + + + + + AbstractAlert + + Close + إغلاق + + + Reboot and Update + إعادة التشغيل والتحديث + + + + AdvancedNetworking + + Back + السابق + + + Enable Tethering + تمكين الربط + + + Tethering Password + كلمة مرور الربط + + + EDIT + تعديل + + + Enter new tethering password + أدخل كلمة مرور الربط الجديدة + + + IP Address + عنوان IP + + + Enable Roaming + تمكين التجوال + + + APN Setting + إعدادات APN + + + Enter APN + إدخال APN + + + leave blank for automatic configuration + اتركه فارغاً من أجل التكوين التلقائي + + + Cellular Metered + محدود بالاتصال الخلوي + + + Hidden Network + شبكة مخفية + + + CONNECT + الاتصال + + + Enter SSID + أدخل SSID + + + Enter password + أدخل كلمة المرور + + + for "%1" + من أجل "%1" + + + Prevent large data uploads when on a metered cellular connection + + + + default + + + + metered + + + + unmetered + + + + Wi-Fi Network Metered + + + + Prevent large data uploads when on a metered Wi-Fi connection + + + + + ConfirmationDialog + + Ok + موافق + + + Cancel + إلغاء + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + يجب عليك قبول الشروط والأحكام من أجل استخدام openpilot. + + + Back + السابق + + + Decline, uninstall %1 + رفض، إلغاء التثبيت %1 + + + + DeveloperPanel + + Joystick Debug Mode + وضع تصحيح أخطاء عصا التحكم + + + Longitudinal Maneuver Mode + وضع المناورة الطولية + + + openpilot Longitudinal Control (Alpha) + التحكم الطولي openpilot (ألفا) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + تحذير: التحكم الطولي في openpilot في المرحلة ألفا لهذه السيارة، وسيقوم بتعطيل مكابح الطوارئ الآلية (AEB). + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + في هذه السيارة يعمل openpilot افتراضياً بالشكل المدمج في التحكم التكيفي في السرعة بدلاً من التحكم الطولي. قم بتمكين هذا الخيار من أجل الانتقال إلى التحكم الطولي. يوصى بتمكين الوضع التجريبي عند استخدام وضع التحكم الطولي ألفا من openpilot. + + + Enable ADB + تمكين ADB + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + أداة ADB (Android Debug Bridge) تسمح بالاتصال بجهازك عبر USB أو عبر الشبكة. راجع هذا الرابط: https://docs.comma.ai/how-to/connect-to-comma لمزيد من المعلومات. + + + + DevicePanel + + Dongle ID + معرف دونجل + + + N/A + غير متاح + + + Serial + الرقم التسلسلي + + + Driver Camera + كاميرة السائق + + + PREVIEW + معاينة + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + قم بمعاينة الكاميرا المواجهة للسائق للتأكد من أن نظام مراقبة السائق يتمتع برؤية جيدة. (يجب أن تكون السيارة متوقفة) + + + Reset Calibration + إعادة ضبط المعايرة + + + RESET + إعادة الضبط + + + Are you sure you want to reset calibration? + هل أنت متأكد أنك تريد إعادة ضبط المعايرة؟ + + + Review Training Guide + مراجعة دليل التدريب + + + REVIEW + مراجعة + + + Review the rules, features, and limitations of openpilot + مراجعة الأدوار والميزات والقيود في openpilot + + + Are you sure you want to review the training guide? + هل أنت متأكد أنك تريد مراجعة دليل التدريب؟ + + + Regulatory + التنظيمية + + + VIEW + عرض + + + Change Language + تغيير اللغة + + + CHANGE + تغيير + + + Select a language + اختر لغة + + + Reboot + إعادة التشغيل + + + Power Off + إيقاف التشغيل + + + Your device is pointed %1° %2 and %3° %4. + يشير جهازك إلى %1 درجة %2، و%3 درجة %4. + + + down + نحو الأسفل + + + up + نحو الأعلى + + + left + نحو اليسار + + + right + نحو اليمين + + + Are you sure you want to reboot? + هل أنت متأكد أنك تريد إعادة التشغيل؟ + + + Disengage to Reboot + فك الارتباط من أجل إعادة التشغيل + + + Are you sure you want to power off? + هل أنت متأكد أنك تريد إيقاف التشغيل؟ + + + Disengage to Power Off + فك الارتباط من أجل إيقاف التشغيل + + + Reset + إعادة الضبط + + + Review + مراجعة + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + اقرن جهازك بجهاز (connect.comma.ai) واحصل على عرضك من comma prime. + + + Pair Device + إقران الجهاز + + + PAIR + إقران + + + Disengage to Reset Calibration + + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + + + + + +Steering lag calibration is %1% complete. + + + + + +Steering lag calibration is complete. + + + + Steering torque response calibration is %1% complete. + + + + Steering torque response calibration is complete. + + + + + DriverViewWindow + + camera starting + بدء تشغيل الكاميرا + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + تشغيل الوضع التجريبي + + + CHILL MODE ON + تشغيل وضع الراحة + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + يتعلم تطبيق openpilot كيفية القيادة من خلال مشاهدة البشر، مثلك، أثناء القيادة. + +يتيح لك وضع خرطوم الحريق زيادة تحميلات بيانات التدريب لتحسين نماذج القيادة في OpenPilot. كلما زادت البيانات، زادت النماذج، مما يعني وضعًا تجريبيًا أفضل. + + + Firehose Mode: ACTIVE + وضع خرطوم الحريق: نشط + + + ACTIVE + نشط + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + للحصول على أقصى فعالية، أحضر جهازك إلى الداخل واتصل بمحول USB-C جيد وشبكة Wi-Fi أسبوعياً.<br><br>يمكن أن يعمل وضع خرطوم الحريق أيضاً أثناء القيادة إذا كنت متصلاً بنقطة اتصال أو ببطاقة SIM غير محدودة.<br><br><br><b>الأسئلة المتكررة</b><br><br><i>هل يهم كيف أو أين أقود؟</i> لا، فقط قد كما تفعل عادة.<br><br><i>هل يتم سحب كل مقاطع رحلاتي في وضع خرطوم الحريق؟</i> لا، نقوم بسحب مجموعة مختارة من مقاطع رحلاتك.<br><br><i>ما هو محول USB-C الجيد؟</i> أي شاحن سريع للهاتف أو اللابتوب يجب أن يكون مناسباً.<br><br><i>هل يهم أي برنامج أستخدم؟</i> نعم، فقط النسخة الأصلية من openpilot (وأفرع معينة) يمكن استخدامها للتدريب. + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + حتى الآن، يوجد </b>%n مقطع<b>%n من قيادتك في مجموعة بيانات التدريب. + حتى الآن، يوجد </b>%n مقطع<b>%n من قيادتك في مجموعة بيانات التدريب. + حتى الآن، يوجد </b>%n مقطع<b>%n من قيادتك في مجموعة بيانات التدريب. + حتى الآن، يوجد </b>%n مقطع<b>%n من قيادتك في مجموعة بيانات التدريب. + حتى الآن، يوجد </b>%n مقطع<b>%n من قيادتك في مجموعة بيانات التدريب. + حتى الآن، يوجد </b>%n مقطع<b>%n من قيادتك في مجموعة بيانات التدريب. + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + + + + Firehose Mode + + + + + HudRenderer + + km/h + كم/س + + + mph + ميل/س + + + MAX + MAX + + + + InputDialog + + Cancel + إلغاء + + + Need at least %n character(s)! + + تحتاج إلى حرف %n على الأقل! + تحتاج إلى حرف %n على الأقل! + تحتاج إلى حرفين %n على الأقل! + تحتاج إلى %n أحرف على الأقل! + تحتاج إلى %n أحرف على الأقل! + تحتاج إلى %n حرف على الأقل! + + + + + MultiOptionDialog + + Select + اختيار + + + Cancel + إلغاء + + + + Networking + + Advanced + متقدم + + + Enter password + أدخل كلمة المرور + + + for "%1" + من أجل "%1" + + + Wrong password + كلمة مرور خاطئة + + + + OffroadAlert + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + درجة حرارة الجهاز مرتفعة جداً. يقوم النظام بالتبريد قبل البدء. درجة الحرارة الحالية للمكونات الداخلية: %1 + + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + اتصل فوراً بالإنترنت للتحقق من وجود تحديثات. إذا لم تكم متصلاً بالإنترنت فإن openpilot لن يساهم في %1 + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + اتصل بالإنترنت للتحقق من وجود تحديثات. لا يعمل openpilot تلقائياً إلا إذا اتصل بالإنترنت من أجل التحقق من التحديثات. + + + Unable to download updates +%1 + غير قادر على تحميل التحديثات +%1 + + + Taking camera snapshots. System won't start until finished. + التقاط لقطات كاميرا. لن يبدأ النظام حتى تنتهي هذه العملية. + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + يتم تنزيل تحديث لنظام تشغيل جهازك في الخلفية. سيطلَب منك التحديث عندما يصبح جاهزاً للتثبيت. + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + لم يكن openpilot قادراً على تحديد سيارتك. إما أن تكون سيارتك غير مدعومة أو أنه لم يتم التعرف على وحدة التحكم الإلكتروني (ECUs) فيها. يرجى تقديم طلب سحب من أجل إضافة نسخ برمجيات ثابتة إلى السيارة المناسبة. هل تحتاج إلى أي مساعدة؟ لا تتردد في التواصل مع doscord.comma.ai. + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + لقد اكتشف openpilot تغييراً في موقع تركيب الجهاز. تأكد من تثبيت الجهاز بشكل كامل في موقعه وتثبيته بإحكام على الزجاج الأمامي. + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + + + + Acknowledge Excessive Actuation + + + + Snooze Update + تأخير التحديث + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + تحديث + + + ALERTS + التنبهات + + + ALERT + تنبيه + + + + OnroadAlerts + + openpilot Unavailable + openpilot غير متوفر + + + TAKE CONTROL IMMEDIATELY + تحكم على الفور + + + Reboot Device + إعادة التشغيل + + + Waiting to start + في انتظار البدء + + + System Unresponsive + النظام لا يستجيب + + + + PairingPopup + + Pair your device to your comma account + اقرن جهازك مع حسابك على comma + + + Go to https://connect.comma.ai on your phone + انتقل إلى https://connect.comma.ai على جوالك + + + Click "add new device" and scan the QR code on the right + انقر "،إضافة جهاز جديد"، وامسح رمز الاستجابة السريعة (QR) على اليمين + + + Bookmark connect.comma.ai to your home screen to use it like an app + اجعل لـconnect.comma.ai إشارة مرجعية على شاشتك الرئيسية من أجل استخدامه مثل أي تطبيق + + + Please connect to Wi-Fi to complete initial pairing + يرجى الاتصال بشبكة الواي فاي لإكمال الاقتران الأولي + + + + ParamControl + + Enable + تمكين + + + Cancel + إلغاء + + + + PrimeAdWidget + + Upgrade Now + الترقية الآن + + + Become a comma prime member at connect.comma.ai + كن عضوًا في comma prime على connect.comma.ai + + + PRIME FEATURES: + الميزات الأساسية: + + + Remote access + التحكم عن بعد + + + 24/7 LTE connectivity + اتصال LTE على مدار الساعة 24/7 + + + 1 year of drive storage + سنة واحدة من تخزين القرص + + + Remote snapshots + لقطات عن بُعد + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ مشترك + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + منذ %n دقيقة + منذ %n دقيقة + منذ دقيقتين %n + منذ %n دقائق + منذ %n دقائق + منذ %n دقيقة + + + + %n hour(s) ago + + منذ %n ساعة + منذ %n ساعة + منذ ساعتين %n + منذ %n ساعات + منذ %n ساعات + منذ %n ساعة + + + + %n day(s) ago + + منذ %n يوم + منذ %n يوم + منذ يومين %n + منذ %n أيام + منذ %n أيام + منذ %n يوم + + + + now + الآن + + + + SettingsWindow + + × + × + + + Device + الجهاز + + + Network + الشبكة + + + Toggles + المثبتتات + + + Software + البرنامج + + + Developer + المطور + + + Firehose + خرطوم الحريق + + + + SetupWidget + + Finish Setup + إنهاء الإعداد + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + اقرن جهازك بجهاز (connect.comma.ai) واحصل على عرضك من comma prime. + + + Pair device + اقتران الجهاز + + + + Sidebar + + CONNECT + الاتصال + + + OFFLINE + غير متصل + + + ONLINE + متصل + + + ERROR + خطأ + + + TEMP + درجة الحرارة + + + HIGH + مرتفع + + + GOOD + جيد + + + OK + موافق + + + VEHICLE + المركبة + + + NO + لا + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + UNINSTALL + إلغاء التثبيت + + + Uninstall %1 + إلغاء التثبيت %1 + + + Are you sure you want to uninstall? + هل أنت متأكد أنك تريد إلغاء التثبيت؟ + + + CHECK + التحقق + + + Updates are only downloaded while the car is off. + يتم تحميل التحديثات فقط عندما تكون السيارة متوقفة. + + + Current Version + النسخة الحالية + + + Download + تنزيل + + + Install Update + تثبيت التحديث + + + INSTALL + تثبيت + + + Target Branch + فرع الهدف + + + SELECT + اختيار + + + Select a branch + اختر فرعاً + + + Uninstall + إلغاء التثبيت + + + failed to check for update + فشل التحقق من التحديث + + + DOWNLOAD + تنزيل + + + update available + يتوفر تحديث + + + never + إطلاقاً + + + up to date, last checked %1 + أحدث نسخة، آخر تحقق %1 + + + + SshControl + + SSH Keys + مفاتيح SSH + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + تنبيه: هذا يمنح SSH إمكانية الوصول إلى جميع المفاتيح العامة في إعدادات GitHub. لا تقم بإدخال اسم مستخدم GitHub بدلاً من اسمك. لن تطلب منك comma employee إطلاقاً أن تضيف اسم مستخدم GitHub الخاص بهم. + + + ADD + إضافة + + + Enter your GitHub username + ادخل اسم المستخدم GitHub الخاص بك + + + LOADING + يتم التحميل + + + REMOVE + إزالة + + + Username '%1' has no keys on GitHub + لا يحتوي اسم المستخدم '%1' أي مفاتيح على GitHub + + + Request timed out + انتهى وقت الطلب + + + Username '%1' doesn't exist on GitHub + اسم المستخدم '%1' غير موجود على GitHub + + + + SshToggle + + Enable SSH + تمكين SSH + + + + TermsPage + + Decline + رفض + + + Agree + أوافق + + + Welcome to openpilot + مرحباً بكم في openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + يجب عليك قبول الشروط والأحكام لاستخدام openpilot. اقرأ أحدث الشروط على <span style='color: #465BEA;'>https://comma.ai/terms</span> قبل الاستمرار. + + + + TogglesPanel + + Enable openpilot + تمكين openpilot + + + Enable Lane Departure Warnings + قم بتمكين تحذيرات مغادرة المسار + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + تلقي التنبيهات من أجل الالتفاف للعودة إلى المسار عندما تنحرف سيارتك فوق الخط المحدد للمسار دون تشغيل إشارة الانعطاف عند القيادة لمسافة تزيد عن 31 ميل/سا (50 كم/سا). + + + Use Metric System + استخدام النظام المتري + + + Display speed in km/h instead of mph. + عرض السرعة بواحدات كم/سا بدلاً من ميل/سا. + + + Record and Upload Driver Camera + تسجيل وتحميل كاميرا السائق + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + تحميل البيانات من الكاميرا المواجهة للسائق، والمساعدة في تحسين خوارزمية مراقبة السائق. + + + Disengage on Accelerator Pedal + فك الارتباط عن دواسة الوقود + + + When enabled, pressing the accelerator pedal will disengage openpilot. + عند تمكين هذه الميزة، فإن الضغط على دواسة الوقود سيؤدي إلى فك ارتباط openpilot. + + + Experimental Mode + الوضع التجريبي + + + Aggressive + الهجومي + + + Standard + القياسي + + + Relaxed + الراحة + + + Driving Personality + شخصية القيادة + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + يتم وضع openpilot بشكل قياسي في <b>وضعية الراحة</b>. يمكن الوضع التجريبي <b>ميزات المستوى ألفا</b> التي لا تكون جاهزة في وضع الراحة: + + + End-to-End Longitudinal Control + التحكم الطولي من طرف إلى طرف + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + دع نظام القيادة يتحكم بالوقود والمكابح. سيقوم openpilot بالقيادة كما لو أنه كائن بشري، بما في ذلك التوقف عند الإشارة الحمراء، وإشارات التوقف. وبما أن نمط القيادة يحدد سرعة القيادة، فإن السرعة المضبوطة تشكل الحد الأقصى فقط. هذه خاصية الجودة ألفا، فيجب توقع حدوث الأخطاء. + + + New Driving Visualization + تصور القيادة الديد + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + الوضع التجريبي غير متوفر حالياً في هذه السيارة نظراً لاستخدام رصيد التحكم التكيفي بالسرعة من أجل التحكم الطولي. + + + openpilot longitudinal control may come in a future update. + قد يتم الحصول على التحكم الطولي في openpilot في عمليات التحديث المستقبلية. + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + يمكن اختبار نسخة ألفا من التحكم الطولي من openpilot، مع الوضع التجريبي، لكن على الفروع غير المطلقة. + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + تمكين التحكم الطولي من openpilot (ألفا) للسماح بالوضع التجريبي. + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + يوصى بالمعيار. في الوضع العدواني، سيتبع الطيار المفتوح السيارات الرائدة بشكل أقرب ويكون أكثر عدوانية مع البنزين والفرامل. في الوضع المريح، سيبقى openpilot بعيدًا عن السيارات الرائدة. في السيارات المدعومة، يمكنك التنقل بين هذه الشخصيات باستخدام زر مسافة عجلة القيادة. + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + ستتحول واجهة القيادة إلى الكاميرا الواسعة المواجهة للطريق عند السرعات المنخفضة لعرض بعض المنعطفات بشكل أفضل. كما سيتم عرض شعار وضع التجريبي في الزاوية العلوية اليمنى. + + + Always-On Driver Monitoring + مراقبة السائق المستمرة + + + Enable driver monitoring even when openpilot is not engaged. + تمكين مراقبة السائق حتى عندما لا يكون نظام OpenPilot مُفعّلاً. + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + + + + Changing this setting will restart openpilot if the car is powered on. + + + + Record and Upload Microphone Audio + + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + + + + + WiFiPromptWidget + + Open + انفتح + + + Maximize your training data uploads to improve openpilot's driving models. + قم بزيادة تحميلات بيانات التدريب الخاصة بك لتحسين نماذج القيادة الخاصة بـ openpilot. + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> وضع خرطوم الحريق <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + يتم البحث عن شبكات... + + + CONNECTING... + يتم الاتصال... + + + FORGET + نسيان هذه الشبكة + + + Forget Wi-Fi Network "%1"? + هل تريد نسيان شبكة الواي فاي "%1"؟ + + + Forget + نسيان + + + diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts new file mode 100644 index 0000000000..28b07029eb --- /dev/null +++ b/selfdrive/ui/translations/main_de.ts @@ -0,0 +1,1072 @@ + + + + + AbstractAlert + + Close + Schließen + + + Reboot and Update + Aktualisieren und neu starten + + + + AdvancedNetworking + + Back + Zurück + + + Enable Tethering + Tethering aktivieren + + + Tethering Password + Tethering Passwort + + + EDIT + ÄNDERN + + + Enter new tethering password + Neues tethering Passwort eingeben + + + IP Address + IP Adresse + + + Enable Roaming + Roaming aktivieren + + + APN Setting + APN Einstellungen + + + Enter APN + APN eingeben + + + leave blank for automatic configuration + für automatische Konfiguration leer lassen + + + Cellular Metered + Getaktete Verbindung + + + Hidden Network + Verborgenes Netzwerk + + + CONNECT + VERBINDEN + + + Enter SSID + SSID eingeben + + + Enter password + Passwort eingeben + + + for "%1" + für "%1" + + + Prevent large data uploads when on a metered cellular connection + + + + default + + + + metered + + + + unmetered + + + + Wi-Fi Network Metered + + + + Prevent large data uploads when on a metered Wi-Fi connection + + + + + ConfirmationDialog + + Ok + Ok + + + Cancel + Abbrechen + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + Du musst die Nutzungsbedingungen akzeptieren, um Openpilot zu benutzen. + + + Back + Zurück + + + Decline, uninstall %1 + Ablehnen, deinstallieren %1 + + + + DeveloperPanel + + Joystick Debug Mode + Joystick Debug-Modus + + + Longitudinal Maneuver Mode + Längsmanöver-Modus + + + openpilot Longitudinal Control (Alpha) + openpilot Längsregelung (Alpha) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + WARNUNG: Die openpilot Längsregelung befindet sich für dieses Fahrzeug im Alpha-Stadium und deaktiviert das automatische Notbremsen (AEB). + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + Bei diesem Fahrzeug verwendet openpilot standardmäßig den eingebauten Tempomaten anstelle der openpilot Längsregelung. Aktiviere diese Option, um auf die openpilot Längsregelung umzuschalten. Es wird empfohlen, den experimentellen Modus zu aktivieren, wenn die openpilot Längsregelung (Alpha) aktiviert wird. + + + Enable ADB + ADB aktivieren + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB (Android Debug Bridge) ermöglicht die Verbindung zu deinem Gerät über USB oder Netzwerk. Siehe https://docs.comma.ai/how-to/connect-to-comma für weitere Informationen. + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + Nicht verfügbar + + + Serial + Seriennummer + + + Driver Camera + Fahrerkamera + + + PREVIEW + VORSCHAU + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Vorschau der auf den Fahrer gerichteten Kamera, um sicherzustellen, dass die Fahrerüberwachung eine gute Sicht hat. (Fahrzeug muss aus sein) + + + Reset Calibration + Neu kalibrieren + + + RESET + RESET + + + Are you sure you want to reset calibration? + Bist du sicher, dass du die Kalibrierung zurücksetzen möchtest? + + + Review Training Guide + Trainingsanleitung wiederholen + + + REVIEW + TRAINING + + + Review the rules, features, and limitations of openpilot + Wiederhole die Regeln, Fähigkeiten und Limitierungen von Openpilot + + + Are you sure you want to review the training guide? + Bist du sicher, dass du die Trainingsanleitung wiederholen möchtest? + + + Regulatory + Rechtliche Hinweise + + + VIEW + ANSEHEN + + + Change Language + Sprache ändern + + + CHANGE + ÄNDERN + + + Select a language + Sprache wählen + + + Reboot + Neustart + + + Power Off + Ausschalten + + + Your device is pointed %1° %2 and %3° %4. + Deine Geräteausrichtung ist %1° %2 und %3° %4. + + + down + unten + + + up + oben + + + left + links + + + right + rechts + + + Are you sure you want to reboot? + Bist du sicher, dass du das Gerät neu starten möchtest? + + + Disengage to Reboot + Für Neustart deaktivieren + + + Are you sure you want to power off? + Bist du sicher, dass du das Gerät ausschalten möchtest? + + + Disengage to Power Off + Zum Ausschalten deaktivieren + + + Reset + Zurücksetzen + + + Review + Überprüfen + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Koppele dein Gerät mit Comma Connect (connect.comma.ai) und sichere dir dein Comma Prime Angebot. + + + Pair Device + Gerät koppeln + + + PAIR + KOPPELN + + + Disengage to Reset Calibration + + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + + + + + +Steering lag calibration is %1% complete. + + + + + +Steering lag calibration is complete. + + + + Steering torque response calibration is %1% complete. + + + + Steering torque response calibration is complete. + + + + + DriverViewWindow + + camera starting + Kamera startet + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + EXPERIMENTELLER MODUS AN + + + CHILL MODE ON + ENTSPANNTER MODUS AN + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + openpilot lernt das Fahren, indem es Menschen wie dir beim Fahren zuschaut. + +Der Firehose-Modus ermöglicht es dir, deine Trainingsdaten-Uploads zu maximieren, um die Fahrmodelle von openpilot zu verbessern. Mehr Daten bedeuten größere Modelle, was zu einem besseren Experimentellen Modus führt. + + + Firehose Mode: ACTIVE + Firehose-Modus: AKTIV + + + ACTIVE + AKTIV + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + Für maximale Effektivität bring dein Gerät jede Woche nach drinnen und verbinde es mit einem guten USB-C-Adapter und WLAN.<br><br>Der Firehose-Modus funktioniert auch während der Fahrt, wenn das Gerät mit einem Hotspot oder einer ungedrosselten SIM-Karte verbunden ist.<br><br><br><b>Häufig gestellte Fragen</b><br><br><i>Spielt es eine Rolle, wie oder wo ich fahre?</i> Nein, fahre einfach wie gewohnt.<br><br><i>Werden im Firehose-Modus alle meine Segmente hochgeladen?</i> Nein, wir wählen selektiv nur einen Teil deiner Segmente aus.<br><br><i>Welcher USB-C-Adapter ist gut?</i> Jedes Schnellladegerät für Handy oder Laptop sollte ausreichen.<br><br><i>Spielt es eine Rolle, welche Software ich nutze?</i> Ja, nur das offizielle Upstream‑openpilot (und bestimmte Forks) kann für das Training verwendet werden. + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>%n Segment</b> deiner Fahrten ist bisher im Trainingsdatensatz. + <b>%n Segmente</b> deiner Fahrten sind bisher im Trainingsdatensatz. + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INAKTIV</span>: Verbinde dich mit einem ungedrosselten Netzwerk + + + Firehose Mode + + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + MAX + + + + InputDialog + + Cancel + Abbrechen + + + Need at least %n character(s)! + + Mindestens %n Buchstabe benötigt! + Mindestens %n Buchstaben benötigt! + + + + + MultiOptionDialog + + Select + Auswählen + + + Cancel + Abbrechen + + + + Networking + + Advanced + Erweitert + + + Enter password + Passwort eingeben + + + for "%1" + für "%1" + + + Wrong password + Falsches Passwort + + + + OffroadAlert + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + Stelle sofort eine Internetverbindung her, um nach Updates zu suchen. Wenn du keine Verbindung herstellst, kann openpilot in %1 nicht mehr aktiviert werden. + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + Verbinde dich mit dem Internet, um nach Updates zu suchen. openpilot startet nicht automatisch, bis eine Internetverbindung besteht und nach Updates gesucht wurde. + + + Unable to download updates +%1 + Updates konnten nicht heruntergeladen werden +%1 + + + Taking camera snapshots. System won't start until finished. + Kamera-Snapshots werden aufgenommen. Das System startet erst, wenn dies abgeschlossen ist. + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + Ein Update für das Betriebssystem deines Geräts wird im Hintergrund heruntergeladen. Du wirst aufgefordert, das Update zu installieren, sobald es bereit ist. + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilot konnte dein Auto nicht identifizieren. Dein Auto wird entweder nicht unterstützt oder die Steuergeräte (ECUs) werden nicht erkannt. Bitte reiche einen Pull Request ein, um die Firmware-Versionen für das richtige Fahrzeug hinzuzufügen. Hilfe findest du auf discord.comma.ai. + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilot hat eine Änderung der Montageposition des Geräts erkannt. Stelle sicher, dass das Gerät vollständig in der Halterung sitzt und die Halterung fest an der Windschutzscheibe befestigt ist. + + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + Gerätetemperatur zu hoch. Das System kühlt ab, bevor es startet. Aktuelle interne Komponententemperatur: %1 + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + + + + Acknowledge Excessive Actuation + + + + Snooze Update + Update pausieren + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + Aktualisieren + + + ALERTS + HINWEISE + + + ALERT + HINWEIS + + + + OnroadAlerts + + openpilot Unavailable + openpilot nicht verfügbar + + + TAKE CONTROL IMMEDIATELY + ÜBERNIMM SOFORT DIE KONTROLLE + + + Reboot Device + Gerät neu starten + + + Waiting to start + Warten auf Start + + + System Unresponsive + System reagiert nicht + + + + PairingPopup + + Pair your device to your comma account + Verbinde dein Gerät mit deinem comma Konto + + + Go to https://connect.comma.ai on your phone + Gehe zu https://connect.comma.ai auf deinem Handy + + + Click "add new device" and scan the QR code on the right + Klicke auf "neues Gerät hinzufügen" und scanne den QR code rechts + + + Bookmark connect.comma.ai to your home screen to use it like an app + Füge connect.comma.ai als Lesezeichen auf deinem Homescreen hinzu um es wie eine App zu verwenden + + + Please connect to Wi-Fi to complete initial pairing + Bitte verbinde dich mit WLAN, um die Koppelung abzuschließen. + + + + ParamControl + + Cancel + Abbrechen + + + Enable + Aktivieren + + + + PrimeAdWidget + + Upgrade Now + Jetzt abonieren + + + Become a comma prime member at connect.comma.ai + Werde Comma Prime Mitglied auf connect.comma.ai + + + PRIME FEATURES: + PRIME FUNKTIONEN: + + + Remote access + Fernzugriff + + + 24/7 LTE connectivity + 24/7 LTE-Verbindung + + + 1 year of drive storage + Fahrdaten-Speicherung für 1 Jahr + + + Remote snapshots + Remote-Snapshots + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ ABBONIERT + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + vor %n Minute + vor %n Minuten + + + + %n hour(s) ago + + vor %n Stunde + vor %n Stunden + + + + %n day(s) ago + + vor %n Tag + vor %n Tagen + + + + now + jetzt + + + + SettingsWindow + + × + x + + + Device + Gerät + + + Network + Netzwerk + + + Toggles + Schalter + + + Software + Software + + + Developer + Entwickler + + + Firehose + Firehose + + + + SetupWidget + + Finish Setup + Einrichtung beenden + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Koppele dein Gerät mit Comma Connect (connect.comma.ai) und sichere dir dein Comma Prime Angebot. + + + Pair device + Gerät koppeln + + + + Sidebar + + CONNECT + This is a brand/service name for comma connect, don't translate + CONNECT + + + OFFLINE + OFFLINE + + + ONLINE + ONLINE + + + ERROR + FEHLER + + + TEMP + TEMP + + + HIGH + HOCH + + + GOOD + GUT + + + OK + OK + + + VEHICLE + FAHRZEUG + + + NO + KEIN + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + WLAN + + + ETH + LAN + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + UNINSTALL + Too long for UI + DEINSTALL + + + Uninstall %1 + Deinstalliere %1 + + + Are you sure you want to uninstall? + Bist du sicher, dass du Openpilot entfernen möchtest? + + + CHECK + ÜBERPRÜFEN + + + Updates are only downloaded while the car is off. + Updates werden nur heruntergeladen, wenn das Auto aus ist. + + + Current Version + Aktuelle Version + + + Download + Download + + + Install Update + Update installieren + + + INSTALL + INSTALLIEREN + + + Target Branch + Ziel Branch + + + SELECT + AUSWÄHLEN + + + Select a branch + Wähle einen Branch + + + Uninstall + Deinstallieren + + + failed to check for update + Update-Prüfung fehlgeschlagen + + + up to date, last checked %1 + Auf dem neuesten Stand, zuletzt geprüft am %1 + + + DOWNLOAD + HERUNTERLADEN + + + update available + Update verfügbar + + + never + nie + + + + SshControl + + SSH Keys + SSH Schlüssel + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + Warnung: Dies ermöglicht SSH zugriff für alle öffentlichen Schlüssel in deinen Github Einstellungen. Gib niemals einen anderen Benutzernamen, als deinen Eigenen an. Comma Angestellte fragen dich niemals danach ihren Github Benutzernamen hinzuzufügen. + + + ADD + HINZUFÜGEN + + + Enter your GitHub username + Gib deinen GitHub Benutzernamen ein + + + LOADING + LADEN + + + REMOVE + LÖSCHEN + + + Username '%1' has no keys on GitHub + Benutzername '%1' hat keine Schlüssel auf GitHub + + + Request timed out + Zeitüberschreitung der Anforderung + + + Username '%1' doesn't exist on GitHub + Benutzername '%1' existiert nicht auf GitHub + + + + SshToggle + + Enable SSH + SSH aktivieren + + + + TermsPage + + Decline + Ablehnen + + + Agree + Zustimmen + + + Welcome to openpilot + Willkommen bei openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + Du musst die Nutzungsbedingungen akzeptieren, um openpilot zu verwenden. Lies die aktuellen Bedingungen unter <span style='color: #465BEA;'>https://comma.ai/terms</span>, bevor du fortfährst. + + + + TogglesPanel + + Enable openpilot + Openpilot aktivieren + + + Enable Lane Departure Warnings + Spurverlassenswarnungen aktivieren + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + Erhalte Warnungen, zurück in die Spur zu lenken, wenn dein Auto über eine erkannte Fahrstreifenmarkierung ohne aktivierten Blinker mit mehr als 50 km/h fährt. + + + Use Metric System + Benutze das metrische System + + + Display speed in km/h instead of mph. + Zeige die Geschwindigkeit in km/h anstatt von mph. + + + Record and Upload Driver Camera + Fahrerkamera aufnehmen und hochladen + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Lade Daten der Fahreraufmerksamkeitsüberwachungskamera hoch, um die Fahreraufmerksamkeitsüberwachungsalgorithmen zu verbessern. + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Wenn aktiviert, deaktiviert sich Openpilot sobald das Gaspedal betätigt wird. + + + Experimental Mode + Experimenteller Modus + + + Disengage on Accelerator Pedal + Bei Gasbetätigung ausschalten + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + Openpilot fährt standardmäßig im <b>entspannten Modus</b>. Der Experimentelle Modus aktiviert<b>Alpha-level Funktionen</b>, die noch nicht für den entspannten Modus bereit sind. Die experimentellen Funktionen sind die Folgenden: + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + Lass das Fahrmodell Gas und Bremse kontrollieren. Openpilot wird so fahren, wie es dies von einem Menschen erwarten würde; inklusive des Anhaltens für Ampeln und Stoppschildern. Da das Fahrmodell entscheidet wie schnell es fährt stellt die gesetzte Geschwindigkeit lediglich das obere Limit dar. Dies ist ein Alpha-level Funktion. Fehler sind zu erwarten. + + + New Driving Visualization + Neue Fahrvisualisierung + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + Der experimentelle Modus ist momentan für dieses Auto nicht verfügbar da es den eingebauten adaptiven Tempomaten des Autos benutzt. + + + Aggressive + Aggressiv + + + Standard + Standard + + + Relaxed + Entspannt + + + Driving Personality + Fahrstil + + + End-to-End Longitudinal Control + Ende-zu-Ende Längsregelung + + + openpilot longitudinal control may come in a future update. + Die openpilot Längsregelung könnte in einem zukünftigen Update verfügbar sein. + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + Eine Alpha-Version der openpilot Längsregelung kann zusammen mit dem Experimentellen Modus auf non-stable Branches getestet werden. + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + Aktiviere den Schalter für openpilot Längsregelung (Alpha), um den Experimentellen Modus zu erlauben. + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + Standard wird empfohlen. Im aggressiven Modus folgt openpilot vorausfahrenden Fahrzeugen enger und ist beim Gasgeben und Bremsen aggressiver. Im entspannten Modus hält openpilot mehr Abstand zu vorausfahrenden Fahrzeugen. Bei unterstützten Fahrzeugen kannst du mit der Abstandstaste am Lenkrad zwischen diesen Fahrstilen wechseln. + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + Die Fahrvisualisierung wechselt bei niedrigen Geschwindigkeiten auf die nach vorne gerichtete Weitwinkelkamera, um Kurven besser darzustellen. Das Logo des Experimentellen Modus wird außerdem oben rechts angezeigt. + + + Always-On Driver Monitoring + Dauerhaft aktive Fahrerüberwachung + + + Enable driver monitoring even when openpilot is not engaged. + Fahrerüberwachung auch aktivieren, wenn openpilot nicht aktiv ist. + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + + + + Changing this setting will restart openpilot if the car is powered on. + + + + Record and Upload Microphone Audio + + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + + + + + WiFiPromptWidget + + Open + Öffnen + + + Maximize your training data uploads to improve openpilot's driving models. + Maximiere deine Trainingsdaten-Uploads, um die Fahrmodelle von openpilot zu verbessern. + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose-Modus <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + Suche nach Netzwerken... + + + CONNECTING... + VERBINDEN... + + + FORGET + VERGESSEN + + + Forget Wi-Fi Network "%1"? + WLAN Netzwerk "%1" vergessen? + + + Forget + Vergessen + + + diff --git a/selfdrive/ui/translations/main_en.ts b/selfdrive/ui/translations/main_en.ts new file mode 100644 index 0000000000..fbccbedb20 --- /dev/null +++ b/selfdrive/ui/translations/main_en.ts @@ -0,0 +1,48 @@ + + + + + FirehosePanel + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>%n segment</b> of your driving is in the training dataset so far. + <b>%n segments</b> of your driving are in the training dataset so far. + + + + + InputDialog + + Need at least %n character(s)! + + Need at least %n character! + Need at least %n characters! + + + + + QObject + + %n minute(s) ago + + %n minute ago + %n minutes ago + + + + %n hour(s) ago + + %n hour ago + %n hours ago + + + + %n day(s) ago + + %n day ago + %n days ago + + + + diff --git a/selfdrive/ui/translations/main_es.ts b/selfdrive/ui/translations/main_es.ts new file mode 100644 index 0000000000..e8d57dddbe --- /dev/null +++ b/selfdrive/ui/translations/main_es.ts @@ -0,0 +1,1074 @@ + + + + + AbstractAlert + + Close + Cerrar + + + Reboot and Update + Reiniciar y Actualizar + + + + AdvancedNetworking + + Back + Volver + + + Enable Tethering + Activar Tether + + + Tethering Password + Contraseña de Tethering + + + EDIT + EDITAR + + + Enter new tethering password + Nueva contraseña de tethering + + + IP Address + Dirección IP + + + Enable Roaming + Activar Roaming + + + APN Setting + Configuración de APN + + + Enter APN + Insertar APN + + + leave blank for automatic configuration + dejar en blanco para configuración automática + + + Cellular Metered + Plano de datos limitado + + + Hidden Network + Red Oculta + + + CONNECT + CONECTAR + + + Enter SSID + Ingrese SSID + + + Enter password + Ingrese contraseña + + + for "%1" + para "%1" + + + Prevent large data uploads when on a metered cellular connection + Evite cargas de grandes cantidades de datos cuando utilice una conexión celular medida + + + default + por defecto + + + metered + medido + + + unmetered + sin medidor + + + Wi-Fi Network Metered + Red Wi-Fi medida + + + Prevent large data uploads when on a metered Wi-Fi connection + Evite cargas de grandes cantidades de datos cuando esté en una conexión Wi-Fi medida + + + + ConfirmationDialog + + Ok + OK + + + Cancel + Cancelar + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + Debe aceptar los términos y condiciones para poder utilizar openpilot. + + + Back + Atrás + + + Decline, uninstall %1 + Rechazar, desinstalar %1 + + + + DeveloperPanel + + Joystick Debug Mode + Modo de depuración de joystick + + + Longitudinal Maneuver Mode + Modo de maniobra longitudinal + + + openpilot Longitudinal Control (Alpha) + Control longitudinal de openpilot (fase experimental) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + AVISO: el control longitudinal de openpilot está en fase experimental para este automóvil y desactivará el Frenado Automático de Emergencia (AEB). + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + En este automóvil, openpilot se configura de manera predeterminada con el Autocrucero Adaptativo (ACC) incorporado en el automóvil en lugar del control longitudinal de openpilot. Habilita esta opción para cambiar al control longitudinal de openpilot. Se recomienda activar el modo experimental al habilitar el control longitudinal de openpilot (aún en fase experimental). + + + Enable ADB + Activar ADB + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB (Android Debug Bridge) permite conectar a su dispositivo por USB o por red. Visite https://docs.comma.ai/how-to/connect-to-comma para más información. + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + N/A + + + Serial + Serial + + + Pair Device + Emparejar Dispositivo + + + PAIR + EMPAREJAR + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Empareja tu dispositivo con comma connect (connect.comma.ai) y reclama tu oferta de comma prime. + + + Driver Camera + Cámara del conductor + + + PREVIEW + VISUALIZAR + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Previsualizar la cámara del conductor para garantizar que la monitorización del sistema tenga buena visibilidad (el vehículo tiene que estar apagado) + + + Reset Calibration + Formatear Calibración + + + RESET + REINICIAR + + + Are you sure you want to reset calibration? + ¿Seguro que quiere formatear la calibración? + + + Reset + Formatear + + + Review Training Guide + Revisar la Guía de Entrenamiento + + + REVIEW + REVISAR + + + Review the rules, features, and limitations of openpilot + Revisar las reglas, características y limitaciones de openpilot + + + Are you sure you want to review the training guide? + ¿Seguro que quiere revisar la guía de entrenamiento? + + + Review + Revisar + + + Regulatory + Regulador + + + VIEW + VER + + + Change Language + Cambiar Idioma + + + CHANGE + CAMBIAR + + + Select a language + Seleccione el idioma + + + Reboot + Reiniciar + + + Power Off + Apagar + + + Your device is pointed %1° %2 and %3° %4. + Su dispositivo está apuntando %1° %2 y %3° %4. + + + down + abajo + + + up + arriba + + + left + izquierda + + + right + derecha + + + Are you sure you want to reboot? + ¿Seguro qué quiere reiniciar? + + + Disengage to Reboot + Desactivar para Reiniciar + + + Are you sure you want to power off? + ¿Seguro qué quiere apagar? + + + Disengage to Power Off + Desactivar para apagar + + + Disengage to Reset Calibration + Desactivar para restablecer la calibración + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + openpilot requiere que el dispositivo esté montado dentro de los 4° hacia la izquierda o la derecha y dentro de los 5° hacia arriba o 9° hacia abajo. + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + Openpilot se calibra continuamente, por lo que rara vez es necesario reiniciarlo. Restablecer la calibración reiniciará Openpilot si el automóvil está encendido. + + + + +Steering lag calibration is %1% complete. + + +La calibración del retraso de dirección está %1% completada. + + + + +Steering lag calibration is complete. + + +La calibración del retraso de la dirección está completa. + + + Steering torque response calibration is %1% complete. + La calibración de la respuesta del par de dirección está %1% completada. + + + Steering torque response calibration is complete. + La calibración de la respuesta del par de dirección está completa. + + + + DriverViewWindow + + camera starting + iniciando cámara + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + MODO EXPERIMENTAL + + + CHILL MODE ON + MODO CHILL + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + openpilot aprende a conducir observando a humanos, como tú, conducir. + +El Modo Firehose te permite maximizar las subidas de datos de entrenamiento para mejorar los modelos de conducción de openpilot. Más datos significan modelos más grandes, lo que significa un mejor Modo Experimental. + + + Firehose Mode: ACTIVE + Modo Firehose: ACTIVO + + + ACTIVE + ACTIVO + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + Para máxima efectividad, traiga su dispositivo adentro y conéctelo a un buen adaptador USB-C y Wi-Fi semanalmente.<br><br>El Modo Firehose también puede funcionar mientras conduce si está conectado a un punto de acceso o tarjeta SIM ilimitada.<br><br><br><b>Preguntas Frecuentes</b><br><br><i>¿Importa cómo o dónde conduzco?</i> No, solo conduzca como lo haría normalmente.<br><br><i>¿Se extraen todos mis segmentos en el Modo Firehose?</i> No, seleccionamos selectivamente un subconjunto de sus segmentos.<br><br><i>¿Qué es un buen adaptador USB-C?</i> Cualquier cargador rápido de teléfono o portátil debería funcionar.<br><br><i>¿Importa qué software ejecuto?</i> Sí, solo el openpilot original (y forks específicos) pueden usarse para el entrenamiento. + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>%n segmento</b> de tu conducción está en el conjunto de datos de entrenamiento hasta ahora. + <b>%n segmentos</b> de tu conducción están en el conjunto de datos de entrenamiento hasta ahora. + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVO</span>: conéctate a una red sin límite de datos + + + Firehose Mode + Modo manguera contra incendios + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + MAX + + + + InputDialog + + Cancel + Cancelar + + + Need at least %n character(s)! + + ¡Necesita mínimo %n caracter! + ¡Necesita mínimo %n caracteres! + + + + + MultiOptionDialog + + Select + Seleccionar + + + Cancel + Cancelar + + + + Networking + + Advanced + Avanzado + + + Enter password + Ingresar contraseña + + + for "%1" + para "%1" + + + Wrong password + Contraseña incorrecta + + + + OffroadAlert + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + La temperatura del dispositivo es muy alta. El sistema se está enfriando antes de iniciar. Temperatura actual del componente interno: %1 + + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + Conéctese inmediatamente al internet para buscar actualizaciones. Si no se conecta al internet, openpilot no iniciará en %1 + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + Conectese al internet para buscar actualizaciones. openpilot no iniciará automáticamente hasta conectarse al internet para buscar actualizaciones. + + + Unable to download updates +%1 + Incapaz de descargar actualizaciones. +%1 + + + Taking camera snapshots. System won't start until finished. + Tomando capturas de las cámaras. El sistema no se iniciará hasta que finalice. + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + Se está descargando una actualización del sistema operativo de su dispositivo en segundo plano. Se le pedirá que actualice cuando esté listo para instalarse. + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilot no pudo identificar su automóvil. Su automóvil no es compatible o no se reconocen sus ECU. Por favor haga un pull request para agregar las versiones de firmware del vehículo adecuado. ¿Necesita ayuda? Únase a discord.comma.ai. + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilot detectó un cambio en la posición de montaje del dispositivo. Asegúrese de que el dispositivo esté completamente asentado en el soporte y que el soporte esté firmemente asegurado al parabrisas. + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + + + + Acknowledge Excessive Actuation + + + + Snooze Update + Posponer Actualización + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + ACTUALIZAR + + + ALERTS + ALERTAS + + + ALERT + ALERTA + + + + OnroadAlerts + + openpilot Unavailable + openpilot no disponible + + + TAKE CONTROL IMMEDIATELY + TOME CONTROL INMEDIATAMENTE + + + Reboot Device + Reiniciar Dispositivo + + + Waiting to start + Esperando para iniciar + + + System Unresponsive + Systema no responde + + + + PairingPopup + + Pair your device to your comma account + Empareje su dispositivo con su cuenta de comma + + + Go to https://connect.comma.ai on your phone + Vaya a https://connect.comma.ai en su teléfono + + + Click "add new device" and scan the QR code on the right + Seleccione "agregar nuevo dispositivo" y escanee el código QR a la derecha + + + Bookmark connect.comma.ai to your home screen to use it like an app + Añada connect.comma.ai a su pantalla de inicio para usarlo como una aplicación + + + Please connect to Wi-Fi to complete initial pairing + Conéctese a Wi-Fi para completar el emparejamiento inicial + + + + ParamControl + + Enable + Activar + + + Cancel + Cancelar + + + + PrimeAdWidget + + Upgrade Now + Actualizar Ahora + + + Become a comma prime member at connect.comma.ai + Hazte miembro de comma prime en connect.comma.ai + + + PRIME FEATURES: + BENEFICIOS PRIME: + + + Remote access + Acceso remoto + + + 24/7 LTE connectivity + Conectividad LTE 24/7 + + + 1 year of drive storage + 1 año de almacenamiento + + + Remote snapshots + Capturas remotas + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ SUSCRITO + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + now + ahora + + + %n minute(s) ago + + hace %n min + hace %n mins + + + + %n hour(s) ago + + hace %n hora + hace %n horas + + + + %n day(s) ago + + hace %n día + hace %n días + + + + + SettingsWindow + + × + × + + + Device + Dispositivo + + + Network + Red + + + Toggles + Ajustes + + + Software + Software + + + Developer + Desarrollador + + + Firehose + Firehose + + + + SetupWidget + + Finish Setup + Terminar configuración + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Empareje su dispositivo con comma connect (connect.comma.ai) y reclame su oferta de comma prime. + + + Pair device + Emparejar dispositivo + + + + Sidebar + + CONNECT + CONNECT + + + OFFLINE + OFFLINE + + + ONLINE + EN LÍNEA + + + ERROR + ERROR + + + TEMP + TEMP + + + HIGH + ALTA + + + GOOD + BUENA + + + OK + OK + + + VEHICLE + VEHÍCULO + + + NO + SIN + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + Actualizaciones solo se descargan con el auto apagado. + + + Current Version + Versión Actual + + + Download + Descargar + + + CHECK + VERIFICAR + + + Install Update + Actualizar + + + INSTALL + INSTALAR + + + Target Branch + Rama objetivo + + + SELECT + SELECCIONAR + + + Select a branch + Selecione una rama + + + Uninstall %1 + Desinstalar %1 + + + UNINSTALL + DESINSTALAR + + + Are you sure you want to uninstall? + ¿Seguro qué desea desinstalar? + + + Uninstall + Desinstalar + + + failed to check for update + no se pudo buscar actualizaciones + + + DOWNLOAD + DESCARGAR + + + update available + actualización disponible + + + never + nunca + + + up to date, last checked %1 + actualizado, último chequeo %1 + + + + SshControl + + SSH Keys + Clave SSH + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + Aviso: Esto otorga acceso SSH a todas las claves públicas en su Github. Nunca ingrese un nombre de usuario de Github que no sea suyo. Un empleado de comma NUNCA le pedirá que añada un usuario de Github que no sea el suyo. + + + ADD + AÑADIR + + + Enter your GitHub username + Ingrese su usuario de GitHub + + + LOADING + CARGANDO + + + REMOVE + ELIMINAR + + + Username '%1' has no keys on GitHub + El usuario "%1” no tiene claves en GitHub + + + Request timed out + Solicitud expirada + + + Username '%1' doesn't exist on GitHub + El usuario '%1' no existe en Github + + + + SshToggle + + Enable SSH + Habilitar SSH + + + + TermsPage + + Decline + Rechazar + + + Agree + Aceptar + + + Welcome to openpilot + Bienvenido a openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + Debe aceptar los Términos y Condiciones para usar openpilot. Lea los términos más recientes en <span style='color: #465BEA;'>https://comma.ai/terms</span> antes de continuar. + + + + TogglesPanel + + Enable openpilot + Activar openpilot + + + Experimental Mode + Modo Experimental + + + Disengage on Accelerator Pedal + Desactivar con el Acelerador + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Cuando esté activado, presionar el acelerador deshabilitará openpilot. + + + Enable Lane Departure Warnings + Activar Avisos de Salida de Carril + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + Recibir alertas para volver al carril cuando su vehículo se salga fuera del carril sin que esté activada la señal de giro y esté conduciendo por encima de 50 km/h (31 mph). + + + Always-On Driver Monitoring + Monitoreo Permanente del Conductor + + + Enable driver monitoring even when openpilot is not engaged. + Habilitar el monitoreo del conductor incluso cuando Openpilot no esté activado. + + + Record and Upload Driver Camera + Grabar y Subir Cámara del Conductor + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Subir datos de la cámara del conductor para ayudar a mejorar el algoritmo de monitoreo del conductor. + + + Use Metric System + Usar Sistema Métrico + + + Display speed in km/h instead of mph. + Mostrar velocidad en km/h en vez de mph. + + + Aggressive + Agresivo + + + Standard + Estándar + + + Relaxed + Relajado + + + Driving Personality + Personalidad de conducción + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + Se recomienda el modo estándar. En el modo agresivo, openpilot seguirá más cerca a los autos delante suyo y será más agresivo con el acelerador y el freno. En modo relajado, openpilot se mantendrá más alejado de los autos delante suyo. En automóviles compatibles, puede recorrer estas personalidades con el botón de distancia del volante. + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + openpilot por defecto conduce en <b>modo chill</b>. El modo Experimental activa <b>funcionalidades en fase experimental</b>, que no están listas para el modo chill. Las funcionalidades del modo expeimental están listados abajo: + + + End-to-End Longitudinal Control + Control Longitudinal de Punta a Punta + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + Dajar que el modelo de conducción controle la aceleración y el frenado. openpilot conducirá como piensa que lo haría una persona, incluiyendo parar en los semáforos en rojo y las señales de alto. Dado que el modelo decide la velocidad de conducción, la velocidad de crucero establecida solo actuará como el límite superior. Este recurso aún está en fase experimental; deberían esperarse errores. + + + New Driving Visualization + Nueva Visualización de la conducción + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + La visualización de la conducción cambiará a la cámara que enfoca la carretera a velocidades bajas para mostrar mejor los giros. El logo del modo experimental también se mostrará en la esquina superior derecha. + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + El modo Experimental no está disponible actualmente para este auto, ya que el ACC default del auto está siendo usado para el control longitudinal. + + + openpilot longitudinal control may come in a future update. + El control longitudinal de openpilot podrá llegar en futuras actualizaciones. + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + Se puede probar una versión experimental del control longitudinal openpilot, junto con el modo Experimental, en ramas no liberadas. + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + Activar el control longitudinal (fase experimental) para permitir el modo Experimental. + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + Utilice el sistema openpilot para el control de crucero adaptativo y la asistencia al conductor para mantenerse en el carril. Se requiere su atención en todo momento para utilizar esta función. + + + Changing this setting will restart openpilot if the car is powered on. + Cambiar esta configuración reiniciará Openpilot si el automóvil está encendido. + + + Record and Upload Microphone Audio + Grabar y cargar audio de micrófono + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + Graba y almacena el audio del micrófono mientras conduces. El audio se incluirá en el video de la cámara del tablero en comma connect. + + + + WiFiPromptWidget + + Open + Abrir + + + Maximize your training data uploads to improve openpilot's driving models. + Maximice sus cargas de datos de entrenamiento para mejorar los modelos de conducción de openpilot. + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> Modo Firehose <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + Buscando redes... + + + CONNECTING... + CONECTANDO... + + + FORGET + OLVIDAR + + + Forget Wi-Fi Network "%1"? + ¿Olvidar la Red de Wi-Fi "%1"? + + + Forget + Olvidar + + + diff --git a/selfdrive/ui/translations/main_fr.ts b/selfdrive/ui/translations/main_fr.ts new file mode 100644 index 0000000000..4efb92d0c8 --- /dev/null +++ b/selfdrive/ui/translations/main_fr.ts @@ -0,0 +1,1068 @@ + + + + + AbstractAlert + + Close + Fermer + + + Reboot and Update + Redémarrer et mettre à jour + + + + AdvancedNetworking + + Back + Retour + + + Enable Tethering + Activer le partage de connexion + + + Tethering Password + Mot de passe du partage de connexion + + + EDIT + MODIFIER + + + Enter new tethering password + Entrez le nouveau mot de passe du partage de connexion + + + IP Address + Adresse IP + + + Enable Roaming + Activer l'itinérance + + + APN Setting + Paramètre APN + + + Enter APN + Entrer le nom du point d'accès + + + leave blank for automatic configuration + laisser vide pour une configuration automatique + + + Cellular Metered + Connexion cellulaire limitée + + + Hidden Network + Réseau Caché + + + CONNECT + CONNECTER + + + Enter SSID + Entrer le SSID + + + Enter password + Entrer le mot de passe + + + for "%1" + pour "%1" + + + Prevent large data uploads when on a metered cellular connection + + + + default + + + + metered + + + + unmetered + + + + Wi-Fi Network Metered + + + + Prevent large data uploads when on a metered Wi-Fi connection + + + + + ConfirmationDialog + + Ok + Ok + + + Cancel + Annuler + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + Vous devez accepter les conditions générales pour utiliser openpilot. + + + Back + Retour + + + Decline, uninstall %1 + Refuser, désinstaller %1 + + + + DeveloperPanel + + Joystick Debug Mode + Mode débogage au joystick + + + Longitudinal Maneuver Mode + Mode manœuvre longitudinale + + + openpilot Longitudinal Control (Alpha) + Contrôle longitudinal openpilot (Alpha) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + ATTENTION : le contrôle longitudinal openpilot est en alpha pour cette voiture et désactivera le freinage d'urgence automatique (AEB). + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + Sur cette voiture, openpilot utilise par défaut le régulateur de vitesse adaptatif intégré à la voiture plutôt que le contrôle longitudinal d'openpilot. Activez ceci pour passer au contrôle longitudinal openpilot. Il est recommandé d'activer le mode expérimental lors de l'activation du contrôle longitudinal openpilot alpha. + + + Enable ADB + + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + N/A + + + Serial + N° de série + + + Driver Camera + Caméra conducteur + + + PREVIEW + APERÇU + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Aperçu de la caméra orientée vers le conducteur pour assurer une bonne visibilité de la surveillance du conducteur. (véhicule doit être éteint) + + + Reset Calibration + Réinitialiser la calibration + + + RESET + RÉINITIALISER + + + Are you sure you want to reset calibration? + Êtes-vous sûr de vouloir réinitialiser la calibration ? + + + Reset + Réinitialiser + + + Review Training Guide + Revoir le guide de formation + + + REVIEW + REVOIR + + + Review the rules, features, and limitations of openpilot + Revoir les règles, fonctionnalités et limitations d'openpilot + + + Are you sure you want to review the training guide? + Êtes-vous sûr de vouloir revoir le guide de formation ? + + + Review + Revoir + + + Regulatory + Réglementaire + + + VIEW + VOIR + + + Change Language + Changer de langue + + + CHANGE + CHANGER + + + Select a language + Choisir une langue + + + Reboot + Redémarrer + + + Power Off + Éteindre + + + Your device is pointed %1° %2 and %3° %4. + Votre appareil est orienté %1° %2 et %3° %4. + + + down + bas + + + up + haut + + + left + gauche + + + right + droite + + + Are you sure you want to reboot? + Êtes-vous sûr de vouloir redémarrer ? + + + Disengage to Reboot + Désengager pour redémarrer + + + Are you sure you want to power off? + Êtes-vous sûr de vouloir éteindre ? + + + Disengage to Power Off + Désengager pour éteindre + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Associez votre appareil avec comma connect (connect.comma.ai) et profitez de l'offre comma prime. + + + Pair Device + Associer l'appareil + + + PAIR + ASSOCIER + + + Disengage to Reset Calibration + + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + + + + + +Steering lag calibration is %1% complete. + + + + + +Steering lag calibration is complete. + + + + Steering torque response calibration is %1% complete. + + + + Steering torque response calibration is complete. + + + + + DriverViewWindow + + camera starting + démarrage de la caméra + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + MODE EXPÉRIMENTAL ACTIVÉ + + + CHILL MODE ON + MODE DÉTENTE ACTIVÉ + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + + + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + + + + Firehose Mode + + + + + HudRenderer + + km/h + km/h + + + mph + mi/h + + + MAX + MAX + + + + InputDialog + + Cancel + Annuler + + + Need at least %n character(s)! + + Besoin d'au moins %n caractère ! + Besoin d'au moins %n caractères ! + + + + + MultiOptionDialog + + Select + Sélectionner + + + Cancel + Annuler + + + + Networking + + Advanced + Avancé + + + Enter password + Entrer le mot de passe + + + for "%1" + pour "%1" + + + Wrong password + Mot de passe incorrect + + + + OffroadAlert + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + Température de l'appareil trop élevée. Le système doit refroidir avant de démarrer. Température actuelle de l'appareil : %1 + + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + Connectez-vous immédiatement à internet pour vérifier les mises à jour. Si vous ne vous connectez pas à internet, openpilot ne s'engagera pas dans %1 + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + Connectez l'appareil à internet pour vérifier les mises à jour. openpilot ne démarrera pas automatiquement tant qu'il ne se connecte pas à internet pour vérifier les mises à jour. + + + Unable to download updates +%1 + Impossible de télécharger les mises à jour +%1 + + + Taking camera snapshots. System won't start until finished. + Capture de clichés photo. Le système ne démarrera pas tant qu'il n'est pas terminé. + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + Une mise à jour du système d'exploitation de votre appareil est en cours de téléchargement en arrière-plan. Vous serez invité à effectuer la mise à jour lorsqu'elle sera prête à être installée. + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilot n'a pas pu identifier votre voiture. Votre voiture n'est pas supportée ou ses ECUs ne sont pas reconnues. Veuillez soumettre un pull request pour ajouter les versions de firmware au véhicule approprié. Besoin d'aide ? Rejoignez discord.comma.ai. + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilot a détecté un changement dans la position de montage de l'appareil. Assurez-vous que l'appareil est totalement inséré dans le support et que le support est fermement fixé au pare-brise. + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + + + + Acknowledge Excessive Actuation + + + + Snooze Update + Reporter la mise à jour + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + MISE À JOUR + + + ALERTS + ALERTES + + + ALERT + ALERTE + + + + OnroadAlerts + + openpilot Unavailable + openpilot indisponible + + + TAKE CONTROL IMMEDIATELY + REPRENEZ LE CONTRÔLE IMMÉDIATEMENT + + + Reboot Device + Redémarrer l'appareil + + + Waiting to start + En attente de démarrage + + + System Unresponsive + Système inopérant + + + + PairingPopup + + Pair your device to your comma account + Associez votre appareil à votre compte comma + + + Go to https://connect.comma.ai on your phone + Allez sur https://connect.comma.ai sur votre téléphone + + + Click "add new device" and scan the QR code on the right + Cliquez sur "ajouter un nouvel appareil" et scannez le code QR à droite + + + Bookmark connect.comma.ai to your home screen to use it like an app + Ajoutez connect.comma.ai à votre écran d'accueil pour l'utiliser comme une application + + + Please connect to Wi-Fi to complete initial pairing + Connectez-vous au Wi-Fi pour terminer l'appairage initial + + + + ParamControl + + Enable + Activer + + + Cancel + Annuler + + + + PrimeAdWidget + + Upgrade Now + Mettre à niveau + + + Become a comma prime member at connect.comma.ai + Devenez membre comma prime sur connect.comma.ai + + + PRIME FEATURES: + FONCTIONNALITÉS PRIME : + + + Remote access + Accès à distance + + + 24/7 LTE connectivity + Connexion LTE 24/7 + + + 1 year of drive storage + 1 an de stockage de trajets + + + Remote snapshots + Captures à distance + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ ABONNÉ + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + il y a %n minute + il y a %n minutes + + + + %n hour(s) ago + + il y a %n heure + il y a %n heures + + + + %n day(s) ago + + il y a %n jour + il y a %n jours + + + + now + maintenant + + + + SettingsWindow + + × + × + + + Device + Appareil + + + Network + Réseau + + + Toggles + Options + + + Software + Logiciel + + + Developer + Dév. + + + Firehose + + + + + SetupWidget + + Finish Setup + Terminer l'installation + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Associez votre appareil avec comma connect (connect.comma.ai) et profitez de l'offre comma prime. + + + Pair device + Associer l'appareil + + + + Sidebar + + CONNECT + CONNECTER + + + OFFLINE + HORS LIGNE + + + ONLINE + EN LIGNE + + + ERROR + ERREUR + + + TEMP + TEMP + + + HIGH + HAUT + + + GOOD + BON + + + OK + OK + + + VEHICLE + VÉHICULE + + + NO + NON + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + Les MàJ sont téléchargées uniquement si la voiture est éteinte. + + + Current Version + Version actuelle + + + Download + Télécharger + + + CHECK + VÉRIFIER + + + Install Update + Installer la mise à jour + + + INSTALL + INSTALLER + + + Target Branch + Branche cible + + + SELECT + SÉLECTIONNER + + + Select a branch + Sélectionner une branche + + + Uninstall %1 + Désinstaller %1 + + + UNINSTALL + DÉSINSTALLER + + + Are you sure you want to uninstall? + Êtes-vous sûr de vouloir désinstaller ? + + + Uninstall + Désinstaller + + + failed to check for update + échec de la vérification de la mise à jour + + + DOWNLOAD + TÉLÉCHARGER + + + update available + mise à jour disponible + + + never + jamais + + + up to date, last checked %1 + à jour, dernière vérification %1 + + + + SshControl + + SSH Keys + Clés SSH + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + Attention : Ceci accorde l'accès SSH à toutes les clés publiques de vos paramètres GitHub. N'entrez jamais un nom d'utilisateur GitHub autre que le vôtre. Un employé de comma ne vous demandera JAMAIS d'ajouter son nom d'utilisateur GitHub. + + + ADD + AJOUTER + + + Enter your GitHub username + Entrez votre nom d'utilisateur GitHub + + + LOADING + CHARGEMENT + + + REMOVE + SUPPRIMER + + + Username '%1' has no keys on GitHub + L'utilisateur '%1' n'a pas de clés sur GitHub + + + Request timed out + Délai de la demande dépassé + + + Username '%1' doesn't exist on GitHub + L'utilisateur '%1' n'existe pas sur GitHub + + + + SshToggle + + Enable SSH + Activer SSH + + + + TermsPage + + Decline + Refuser + + + Agree + Accepter + + + Welcome to openpilot + + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + + + + + TogglesPanel + + Enable openpilot + Activer openpilot + + + Experimental Mode + Mode expérimental + + + Disengage on Accelerator Pedal + Désengager avec la pédale d'accélérateur + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Lorsqu'il est activé, appuyer sur la pédale d'accélérateur désengagera openpilot. + + + Enable Lane Departure Warnings + Activer les avertissements de sortie de voie + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + Recevez des alertes pour revenir dans la voie lorsque votre véhicule dérive au-delà d'une ligne de voie détectée sans clignotant activé en roulant à plus de 31 mph (50 km/h). + + + Record and Upload Driver Camera + Enregistrer et télécharger la caméra conducteur + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Publiez les données de la caméra orientée vers le conducteur et aidez à améliorer l'algorithme de surveillance du conducteur. + + + Use Metric System + Utiliser le système métrique + + + Display speed in km/h instead of mph. + Afficher la vitesse en km/h au lieu de mph. + + + Aggressive + Aggressif + + + Standard + Standard + + + Relaxed + Détendu + + + Driving Personality + Personnalité de conduite + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + Par défaut, openpilot conduit en <b>mode détente</b>. Le mode expérimental permet d'activer des <b>fonctionnalités alpha</b> qui ne sont pas prêtes pour le mode détente. Les fonctionnalités expérimentales sont listées ci-dessous : + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + Laissez le modèle de conduite contrôler l'accélérateur et les freins. openpilot conduira comme il pense qu'un humain le ferait, y compris s'arrêter aux feux rouges et aux panneaux stop. Comme le modèle de conduite décide de la vitesse à adopter, la vitesse définie ne servira que de limite supérieure. Cette fonctionnalité est de qualité alpha ; des erreurs sont à prévoir. + + + New Driving Visualization + Nouvelle visualisation de la conduite + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + Le mode expérimental est actuellement indisponible pour cette voiture car le régulateur de vitesse adaptatif d'origine est utilisé pour le contrôle longitudinal. + + + openpilot longitudinal control may come in a future update. + Le contrôle longitudinal openpilot pourrait être disponible dans une future mise à jour. + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + Une version alpha du contrôle longitudinal openpilot peut être testée, avec le mode expérimental, sur des branches non publiées. + + + End-to-End Longitudinal Control + Contrôle longitudinal de bout en bout + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + Activer le contrôle longitudinal d'openpilot (en alpha) pour autoriser le mode expérimental. + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + Le mode Standard est recommandé. En mode Agressif, openpilot suivra les véhicules de plus près et sera plus dynamique avec l'accélérateur et le frein. En mode Détendu, openpilot maintiendra une distance plus importante avec les véhicules qui précèdent. Sur les véhicules compatibles, vous pouvez alterner entre ces personnalités à l'aide du bouton de distance au volant. + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + La visualisation de la conduite passera sur la caméra grand angle dirigée vers la route à faible vitesse afin de mieux montrer certains virages. Le logo du mode expérimental s'affichera également dans le coin supérieur droit. + + + Always-On Driver Monitoring + Surveillance continue du conducteur + + + Enable driver monitoring even when openpilot is not engaged. + Activer la surveillance conducteur lorsque openpilot n'est pas actif. + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + + + + Changing this setting will restart openpilot if the car is powered on. + + + + Record and Upload Microphone Audio + + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + + + + + WiFiPromptWidget + + Open + + + + Maximize your training data uploads to improve openpilot's driving models. + + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + + WifiUI + + Scanning for networks... + Recherche de réseaux... + + + CONNECTING... + CONNEXION... + + + FORGET + OUBLIER + + + Forget Wi-Fi Network "%1"? + Oublier le réseau Wi-Fi "%1" ? + + + Forget + Oublier + + + diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts new file mode 100644 index 0000000000..4307cee91f --- /dev/null +++ b/selfdrive/ui/translations/main_ja.ts @@ -0,0 +1,1069 @@ + + + + + AbstractAlert + + Close + 閉じる + + + Reboot and Update + 再起動してアップデート + + + + AdvancedNetworking + + Back + 戻る + + + Enable Tethering + テザリング有効 + + + Tethering Password + テザリングパスワード + + + EDIT + 編集 + + + Enter new tethering password + 新しいテザリングパスワードを入力 + + + IP Address + IPアドレス + + + Enable Roaming + ローミング有効 + + + APN Setting + APN設定 + + + Enter APN + APNを入力 + + + leave blank for automatic configuration + 自動で設定するには空白のままにしてください + + + Cellular Metered + 従量制通信設定 + + + Hidden Network + ネットワーク非表示 + + + CONNECT + 接続 + + + Enter SSID + SSIDを入力 + + + Enter password + パスワードを入力 + + + for "%1" + [%1] + + + Prevent large data uploads when on a metered cellular connection + モバイルデータ回線を使用しているときは大容量データをアップロードしません + + + default + 標準設定 + + + metered + 従量制 + + + unmetered + 定額制 + + + Wi-Fi Network Metered + 従量制のWi-Fiネットワーク + + + Prevent large data uploads when on a metered Wi-Fi connection + 通信制限のあるWi-Fi接続では大容量データをアップロードしません + + + + ConfirmationDialog + + Ok + OK + + + Cancel + キャンセル + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + openpilotを使用するためには利用規約に同意する必要があります + + + Back + 戻る + + + Decline, uninstall %1 + 同意しない(%1をアンインストール) + + + + DeveloperPanel + + Joystick Debug Mode + ジョイスティックデバッグモード + + + Longitudinal Maneuver Mode + アクセル制御マニューバー + + + openpilot Longitudinal Control (Alpha) + openpilotアクセル制御(Alpha) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + この車ではopenpilotのアクセル制御はアルファ版であり、自動緊急ブレーキ(AEB)が無効化されます。 + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + この車では、openpilotは車両内蔵のACC(アダプティブクルーズコントロール)をデフォルトとして使用し、openpilotのアクセル制御は無効化されています。アクセル制御をopenpilotに切り替えるにはこの設定を有効にしてください。また同時にExperimentalモードを推奨します。 + + + Enable ADB + ADBを有効にする + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB(Android Debug Bridge)により、USBまたはネットワーク経由でデバイスに接続できます。詳細は、https://docs.comma.ai/how-to/connect-to-comma を参照してください。 + + + + DevicePanel + + Dongle ID + ドングルID + + + N/A + 該当なし + + + Serial + シリアル番号 + + + Driver Camera + 車内カメラ + + + PREVIEW + プレビュー + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + 車内カメラでドライバー監視システムのカメラ画像を確認できます。(車両のパワーOFF時の機能です) + + + Reset Calibration + キャリブレーションリセット + + + RESET + リセット + + + Are you sure you want to reset calibration? + キャリブレーションをリセットしますか? + + + Review Training Guide + トレーニングガイドを見る + + + REVIEW + 確認 + + + Review the rules, features, and limitations of openpilot + openpilotのルール、機能、および制限を確認してください + + + Are you sure you want to review the training guide? + トレーニングガイドを始めてもよろしいですか? + + + Regulatory + 規約 + + + VIEW + 確認 + + + Change Language + 多言語対応 + + + CHANGE + 変更 + + + Select a language + 言語を選択 + + + Reboot + 再起動 + + + Power Off + パワーオフ + + + Your device is pointed %1° %2 and %3° %4. + このデバイスは%2 %1°、%4 %3°の向きに設置されています。 + + + down + + + + up + + + + left + + + + right + + + + Are you sure you want to reboot? + 再起動してもよろしいですか? + + + Disengage to Reboot + 再起動するには車を一旦停止してください + + + Are you sure you want to power off? + パワーオフしてもよろしいですか? + + + Disengage to Power Off + パワーオフするには車を一旦停止してください + + + Reset + リセット + + + Review + 見る + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + デバイスをcommaコネクト(connect.comma.ai)でペアリングしてcommaプライムの特典を受け取ってください。 + + + Pair Device + デバイスのペアリング + + + PAIR + OK + + + Disengage to Reset Calibration + キャリブレーションをリセットするには運転支援を解除して下さい。 + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + openpilotの本体は左右4°以内、上5°下9°以内の角度で取付ける必要があります。 + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + openpilot は継続的にキャリブレーションを行っており、リセットが必要になることはほとんどありません。キャリブレーションをリセットすると、車の電源が入っている場合はopenpilotが再起動します。 + + + + +Steering lag calibration is %1% complete. + + +ステアリング遅延のキャリブレーションが%1%完了。 + + + + +Steering lag calibration is complete. + + +ステアリング遅延のキャリブレーション完了。 + + + Steering torque response calibration is %1% complete. + ステアリングトルク応答のキャリブレーションが%1%完了。 + + + Steering torque response calibration is complete. + ステアリングトルク応答のキャリブレーション完了。 + + + + DriverViewWindow + + camera starting + カメラ起動中 + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + EXPERIMENTALモード + + + CHILL MODE ON + CHILLモード + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + openpilotは人間であるあなたの運転から学び、AI学習します。 + +Firehoseモードを有効にすると学習データを最大限アップロードし、openpilotの運転モデルを改善することができます。より多くのデータはより大きなモデルとなり、Experimentalモードの精度を向上させます。 + + + Firehose Mode: ACTIVE + Firehoseモード: 作動中 + + + ACTIVE + 動作中 + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + 最大の効果を得るためにはデバイスを屋内に持ち込み、大容量のUSB-C充電器とWi-Fiに毎週接続してください。<br><br>Firehoseモードは公衆無線LANや大容量契約のSIMカードに接続していれば、運転中でも動作します。<br><br><br><b>よくある質問(FAQ)</b><br><br><i>運転のやり方や走る場所は重要ですか?</i> いいえ、普段どおりに運転するだけで大丈夫です。<br><br><i>Firehoseモードでは全てのデータがアップロードされますか?</i> いいえ、アップロードするデータを選ぶことができます。<br><br><i>大容量のUSB-C充電器とは何ですか?</i> スマートフォンやノートパソコンを高速に充電できるものを使って下さい。<br><br><i>どのフォークを使うかは重要ですか?</i>はい、トレーニングには公式のopenpilot(および特定のフォーク)のみが使用できます。 + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + あなたの運転の<b>%nセグメント</b>がこれまでのトレーニングデータに含まれています。 + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>動作停止</span>: 大容量のネットワークに接続してください + + + Firehose Mode + Firehoseモード + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + 最大速度 + + + + InputDialog + + Cancel + キャンセル + + + Need at least %n character(s)! + + %n文字以上にして下さい! + + + + + MultiOptionDialog + + Select + 選択 + + + Cancel + キャンセル + + + + Networking + + Advanced + 詳細 + + + Enter password + パスワードを入力 + + + for "%1" + [%1] + + + Wrong password + パスワードが違います + + + + OffroadAlert + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + インターネットへ接続してアップデートを確認してください。未接続のままではopenpilotを使用できなくなります。あと[%1] + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + インターネットに接続してアップデートを確認してください。接続するまでopenpilotは使用できません。 + + + Unable to download updates +%1 + 更新をダウンロードできませんでした +%1 + + + Taking camera snapshots. System won't start until finished. + スナップショットを撮影中です。完了するまでシステムは起動しません。 + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + オペレーティングシステムがバックグラウンドでダウンロードされています。インストールの準備が整うと更新を促されます。 + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilotが車両を識別できませんでした。車が未対応またはECUが認識されていない可能性があります。該当車両のファームウェアバージョンを追加するためにプルリクエストしてください。サポートが必要な場合は discord.comma.ai に参加することができます。 + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilotがデバイスの取り付け位置にずれを検出しました。デバイスの固定とマウントがフロントガラスにしっかりと取り付けられていることを確認してください。 + + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + デバイスの温度が高すぎるためシステム起動前の冷却中です。現在のデバイス内部温度: %1 + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + 製品のcomma.aiへの登録に失敗しました。このデバイスはcomma.aiのサーバーに接続したりアップロードを行ったりすることはできず、comma.aiからのサポートも受けられません。もしcomma.ai/shopで購入した場合は、https://comma.ai/support にてサポートチケットをご提出ください。 + + + Acknowledge Excessive Actuation + 過剰な作動の検知 + + + Snooze Update + また後で更新する + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + 更新 + + + ALERTS + 警告 + + + ALERT + 警告 + + + + OnroadAlerts + + openpilot Unavailable + openpilotは使用できません + + + TAKE CONTROL IMMEDIATELY + 直ちに車の運転に戻って下さい + + + Reboot Device + デバイスを再起動してください + + + Waiting to start + 始動を待機しています + + + System Unresponsive + システムが応答しません + + + + PairingPopup + + Pair your device to your comma account + デバイスとcommaアカウントを連携して下さい + + + Go to https://connect.comma.ai on your phone + スマートフォンで https://connect.comma.ai にアクセスしてください + + + Click "add new device" and scan the QR code on the right + 「add new device」を押して右側のQRコードをスキャンしてください + + + Bookmark connect.comma.ai to your home screen to use it like an app + connect.comma.aiのサイトをホーム画面に追加して、アプリのように使うことができます。 + + + Please connect to Wi-Fi to complete initial pairing + 最初にペアリングするため、Wi-Fiに接続してください + + + + ParamControl + + Cancel + キャンセル + + + Enable + 有効にする + + + + PrimeAdWidget + + Upgrade Now + 今すぐアップグレード + + + Become a comma prime member at connect.comma.ai + connect.comma.ai からプライム会員に登録できます + + + PRIME FEATURES: + 特典: + + + Remote access + リモートアクセス + + + 24/7 LTE connectivity + 24時間365日のLTE接続 + + + 1 year of drive storage + 1年間分のドライブストレージ + + + Remote snapshots + リモートスナップショット + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ 有効です + + + comma prime + commaプライム + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + %n分前 + + + + %n hour(s) ago + + %n時間前 + + + + %n day(s) ago + + %n日前 + + + + now + たった今 + + + + SettingsWindow + + × + × + + + Device + デバイス + + + Network + ネット + + + Toggles + 機能 + + + Software + ソフト + + + Developer + 開発 + + + Firehose + データ学習 + + + + SetupWidget + + Finish Setup + セットアップの完了 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + デバイスをcommaコネクト(connect.comma.ai)でペアリングしてcommaプライムの特典を受け取ってください。 + + + Pair device + デバイスのペアリング + + + + Sidebar + + CONNECT + 接続 + + + OFFLINE + オフライン + + + ONLINE + オンライン + + + ERROR + エラー + + + TEMP + 温度 + + + HIGH + 高温 + + + GOOD + 最適 + + + OK + OK + + + VEHICLE + 車両 + + + NO + NO + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + 車の電源がオフの間のみアップデートがダウンロードできます。 + + + Current Version + 現在のバージョン + + + Download + ダウンロード + + + Install Update + アップデート + + + INSTALL + インストール + + + Target Branch + 対象のブランチ + + + SELECT + 選択 + + + Select a branch + ブランチを選択 + + + UNINSTALL + 実行 + + + Uninstall %1 + %1をアンインストール + + + Are you sure you want to uninstall? + アンインストールしてもよろしいですか? + + + CHECK + 確認 + + + Uninstall + アンインストール + + + failed to check for update + アップデートの確認に失敗しました。 + + + up to date, last checked %1 + 最新の状態です。最終確認日時:%1 + + + DOWNLOAD + ダウンロード + + + update available + アップデートが利用可能です + + + never + 無効 + + + + SshControl + + SSH Keys + SSH 鍵 + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + 警告: これはGitHubの設定にあるすべての公開鍵への SSH アクセスを許可するものです。自分以外のGitHubユーザー名を入力しないでください。commaのスタッフがGitHubのユーザー名を追加するようお願いすることはありません。 + + + ADD + 追加 + + + Enter your GitHub username + GitHubのユーザー名を入力してください + + + LOADING + 読み込み中 + + + REMOVE + 削除 + + + Username '%1' has no keys on GitHub + ユーザー名“%1”は GitHub に公開鍵がありません + + + Request timed out + リクエストタイムアウト + + + Username '%1' doesn't exist on GitHub + ユーザー名”%1”は GitHub に存在しません + + + + SshToggle + + Enable SSH + SSHの有効化 + + + + TermsPage + + Decline + 拒否 + + + Agree + 同意 + + + Welcome to openpilot + openpilotへようこそ + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + openpilotを使用するには利用規約に同意する必要があります。続行する前に最新の規約を以下でご確認ください: <span style='color: #465BEA;'>https://comma.ai/terms</span> + + + + TogglesPanel + + Enable openpilot + openpilotを有効化 + + + Enable Lane Departure Warnings + 車線逸脱警報の有効化 + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + 時速31マイル(50km)以上のスピードで走行中、ウインカーを作動させずに検出したレーン上に車両が触れた場合、手動で車線内に戻るように警告を行います。 + + + Use Metric System + メートル法の使用 + + + Display speed in km/h instead of mph. + 速度は mph ではなく km/h で表示されます。 + + + Record and Upload Driver Camera + 車内カメラの録画とアップロード + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + 車内カメラの映像をアップロードし、ドライバー監視システムのアルゴリズムの向上に役立てます。 + + + Disengage on Accelerator Pedal + アクセルを踏むと運転サポートを中断 + + + When enabled, pressing the accelerator pedal will disengage openpilot. + この機能を有効化すると、openpilotを利用中にアクセルを踏むとopenpilotによる運転サポートを中断します。 + + + Experimental Mode + Experimentalモード + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + openpilotは標準ではゆっくりとくつろげる運転を提供します。このExperimental(実験)モードを有効にすると、以下のアグレッシブな開発中の機能を利用する事ができます。 + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + openpilotにアクセルとブレーキを任せます。openpilotは赤信号や一時停止サインでの停止を含み、人間と同じように考えて運転を行います。openpilotが運転速度を決定するため、あなたが設定する速度は上限速度になります。この機能は実験段階のため、openpilotの運転ミスに常に備えて注意してください。 + + + New Driving Visualization + 新しい運転画面 + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + 車両の標準ACC(アダプティブ・クルーズ・コントロール)がアクセル制御に使用されているため、現在Experimentalモードは利用できません。 + + + Aggressive + アグレッシブ + + + Standard + 標準 + + + Relaxed + リラックス + + + Driving Personality + 運転傾向 + + + End-to-End Longitudinal Control + End-to-Endアクセル制御 + + + openpilot longitudinal control may come in a future update. + openpilotのアクセル制御は将来のアップデートで利用できる可能性があります。 + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + openpilotのアルファ版アクセル制御は、Experimentalモードと共に非リリースのブランチでテストすることができます。 + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + openpilotのアクセル制御機能(アルファ)を有効にして、Experimentalモードを許可してください。 + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + 標準モードが推奨されます。アグレッシブモードではopenpilotは先行車に近づいて追従し、アクセルとブレーキがより強気になります。リラックスモードではopenpilotは先行車から距離を取って走行します。サポートされている車両ではステアリングホイールの距離ボタンでこれらのモードを切り替えることができます。 + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + 運転時の画面効果として、低速時にカーブをより良く表示するために道路用の広角カメラに切り替わります。またExperimentalモードのロゴが右上隅に表示されます。 + + + Always-On Driver Monitoring + 運転者の常時モニタリング + + + Enable driver monitoring even when openpilot is not engaged. + openpilotが作動していない場合でも運転者モニタリングを有効にする。 + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + openpilotシステムを使用してアダプティブクルーズコントロールおよび車線維持支援を行います。システム使用中は常にドライバーが事故を起こさないように注意を払ってください。 + + + Changing this setting will restart openpilot if the car is powered on. + この設定を変更すると車の電源が入っている場合はopenpilotが再起動します。 + + + Record and Upload Microphone Audio + マイク音声の録音とアップロード + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + 運転中にマイク音声を録音・保存します。音声は comma connect のドライブレコーダー映像に含まれます。 + + + + WiFiPromptWidget + + Open + 開く + + + Maximize your training data uploads to improve openpilot's driving models. + openpilotの運転モデルを改善するために、大容量の学習データをアップロードして下さい。 + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehoseモード <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + ネットワークをスキャン中... + + + CONNECTING... + 接続中... + + + FORGET + 削除 + + + Forget Wi-Fi Network "%1"? + Wi-Fiネットワーク%1を削除してもよろしいですか? + + + Forget + 削除 + + + diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts new file mode 100644 index 0000000000..9ab43dd9b8 --- /dev/null +++ b/selfdrive/ui/translations/main_ko.ts @@ -0,0 +1,1069 @@ + + + + + AbstractAlert + + Close + 닫기 + + + Reboot and Update + 업데이트 및 재부팅 + + + + AdvancedNetworking + + Back + 뒤로 + + + Enable Tethering + 테더링 사용 + + + Tethering Password + 테더링 비밀번호 + + + EDIT + 편집 + + + Enter new tethering password + 새 테더링 비밀번호를 입력하세요 + + + IP Address + IP 주소 + + + Enable Roaming + 로밍 사용 + + + APN Setting + APN 설정 + + + Enter APN + APN 입력 + + + leave blank for automatic configuration + 자동 설정하려면 빈 칸으로 두세요 + + + Cellular Metered + 모바일 데이터 종량제 + + + Hidden Network + 숨겨진 네트워크 + + + CONNECT + 연결됨 + + + Enter SSID + SSID 입력 + + + Enter password + 비밀번호를 입력하세요 + + + for "%1" + "%1"에 접속하려면 비밀번호가 필요합니다 + + + Prevent large data uploads when on a metered cellular connection + 모바일 데이터 종량제 사용 시 대용량 데이터 업로드 방지 + + + default + 기본 + + + metered + 종량제 + + + unmetered + 무제한 + + + Wi-Fi Network Metered + 제한된 Wi-Fi 네트워크 + + + Prevent large data uploads when on a metered Wi-Fi connection + 제한된 Wi-Fi 사용 시 대용량 데이터 업로드 방지 + + + + ConfirmationDialog + + Ok + 확인 + + + Cancel + 취소 + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + 오픈파일럿을 사용하려면 이용약관에 동의해야 합니다. + + + Back + 뒤로 + + + Decline, uninstall %1 + 거절, %1 제거 + + + + DeveloperPanel + + Joystick Debug Mode + 조이스틱 디버그 모드 + + + Longitudinal Maneuver Mode + 가감속 제어 조작 모드 + + + openpilot Longitudinal Control (Alpha) + 오픈파일럿 가감속 제어 (알파) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + 경고: 오픈파일럿 가감속 제어는 알파 기능으로 차량의 자동긴급제동(AEB)기능이 작동하지 않습니다. + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + 이 차량에서 오픈파일럿은 오픈파일럿 가감속 제어 대신 기본적으로 차량의 ACC로 가감속을 제어합니다. 오픈파일럿 가감속 제어로 전환하려면 이 기능을 활성화하세요. 오픈파일럿 가감속 제어 알파 기능을 활성화하는 경우 실험 모드 활성화를 권장합니다. + + + Enable ADB + ADB 사용 + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB (안드로이드 디버그 브릿지) USB 또는 네트워크를 통해 장치에 연결할 수 있습니다. 자세한 내용은 https://docs.comma.ai/how-to/connect-to-comma를 참조하세요. + + + + DevicePanel + + Dongle ID + 동글 ID + + + N/A + N/A + + + Serial + 시리얼 + + + Driver Camera + 운전자 카메라 + + + PREVIEW + 미리보기 + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + 운전자 모니터링이 잘 되는지 확인하기 위해 후면 카메라를 미리 봅니다. (차량 시동이 꺼져 있어야 합니다) + + + Reset Calibration + 캘리브레이션 + + + RESET + 초기화 + + + Are you sure you want to reset calibration? + 캘리브레이션을 초기화하시겠습니까? + + + Review Training Guide + 트레이닝 가이드 + + + REVIEW + 다시보기 + + + Review the rules, features, and limitations of openpilot + 오픈파일럿의 규칙, 기능 및 제한 다시 확인 + + + Are you sure you want to review the training guide? + 트레이닝 가이드를 다시 확인하시겠습니까? + + + Regulatory + 규제 + + + VIEW + 보기 + + + Change Language + 언어 변경 + + + CHANGE + 변경 + + + Select a language + 언어를 선택하세요 + + + Reboot + 재부팅 + + + Power Off + 전원 끄기 + + + Your device is pointed %1° %2 and %3° %4. + 사용자의 장치는 %2 %1° 및 %4 %3° 의 방향으로 장착되어 있습니다. + + + down + 아래로 + + + up + 위로 + + + left + 좌측으로 + + + right + 우측으로 + + + Are you sure you want to reboot? + 재부팅하시겠습니까? + + + Disengage to Reboot + 재부팅하려면 연결을 해제하세요 + + + Are you sure you want to power off? + 전원을 끄시겠습니까? + + + Disengage to Power Off + 전원을 끄려면 연결을 해제하세요 + + + Reset + 초기화 + + + Review + 다시보기 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + 장치를 comma connect (connect.comma.ai)에서 동기화하고 comma prime 무료 이용권을 사용하세요. + + + Pair Device + 장치 동기화 + + + PAIR + 동기화 + + + Disengage to Reset Calibration + 캘리브레이션을 재설정하려면 해제하세요 + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + 오픈파일럿 장치는 좌우측으로는 4° 또는 위로는 5° 아래로는 9° 이내에 장착해야합니다. + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + 오픈파일럿은 지속적으로 갤리브레이션되어 재설정이 거의 필요하지 않습니다. 차량과 연결된 경우 캘리브레이션 재설정이 오픈파일럿을 재시작합니다. + + + + +Steering lag calibration is %1% complete. + + +조향 지연 캘리브레이션이 %1% 진행되었습니다. + + + + +Steering lag calibration is complete. + + +조향 지연 캘리브레이션이 완료되었습니다. + + + Steering torque response calibration is %1% complete. + 조향 토크 응답 캘리브레이션이 %1% 진행되었습니다. + + + Steering torque response calibration is complete. + 조향 토크 응답 캘리브레이션이 완료되었습니다. + + + + DriverViewWindow + + camera starting + 카메라 시작 중 + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + 실험 모드 사용 + + + CHILL MODE ON + 안정 모드 사용 + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + 오픈파일럿은 여러분과 같은 사람이 운전하는 모습을 보면서 운전하는 법을 배웁니다. + +파이어호스 모드를 사용하면 학습 데이터 업로드를 최대화하여 오픈파일럿의 주행 모델을 개선할 수 있습니다. 더 많은 데이터는 더 큰 모델을 의미하며, 이는 더 나은 실험 모드를 의미합니다. + + + Firehose Mode: ACTIVE + 파이어호스 모드: 활성화 + + + ACTIVE + 활성 상태 + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + 최대한의 효과를 얻으려면 매주 장치를 실내로 가져와 좋은 USB-C 충전기와 Wi-Fi에 연결하세요.<br><br>파이어호스 모드는 핫스팟 또는 무제한 네트워크에 연결된 경우 주행 중에도 작동할 수 있습니다.<br><br><br><b>자주 묻는 질문</b><br><br><i>운전 방법이나 장소가 중요한가요?</i> 아니요, 평소처럼 운전하시면 됩니다.<br><br><i>파이어호스 모드에서 제 모든 구간을 가져오나요?<br><br><i> 아니요, 저희는 여러분의 구간 중 일부를 선별적으로 가져옵니다.<br><br><i>좋은 USB-C 충전기는 무엇인가요?</i> 휴대폰이나 노트북충전이 가능한 고속 충전기이면 괜찮습니다.<br><br><i>어떤 소프트웨어를 실행하는지가 중요한가요?</i> 예, 오직 공식 오픈파일럿의 특정 포크만 트레이닝에 사용할 수 있습니다. + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>%n 구간</b> 의 운전이 지금까지의 학습 데이터셋에 포함되어 있습니다. + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>비활성 상태</span>: 무제한 네트워크에 연결 하세요 + + + Firehose Mode + 파이어호스 모드 + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + MAX + + + + InputDialog + + Cancel + 취소 + + + Need at least %n character(s)! + + 최소 %n자 이상이어야 합니다! + + + + + MultiOptionDialog + + Select + 선택 + + + Cancel + 취소 + + + + Networking + + Advanced + 고급 설정 + + + Enter password + 비밀번호를 입력하세요 + + + for "%1" + "%1"에 접속하려면 비밀번호가 필요합니다 + + + Wrong password + 비밀번호가 틀렸습니다 + + + + OffroadAlert + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + 즉시 인터넷에 연결하여 업데이트를 확인하세요. 인터넷에 연결되어 있지 않으면 %1 이후에는 오픈파일럿이 활성화되지 않습니다. + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + 업데이트 확인을 위해 인터넷 연결이 필요합니다. 오픈파일럿은 업데이트 확인을 위해 인터넷에 연결될 때까지 자동으로 시작되지 않습니다. + + + Unable to download updates +%1 + 업데이트를 다운로드할 수 없습니다 +%1 + + + Taking camera snapshots. System won't start until finished. + 카메라 스냅샷 찍기가 완료될 때까지 시스템이 시작되지 않습니다. + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + 백그라운드에서 운영 체제에 대한 업데이트가 다운로드되고 있습니다. 설치가 준비되면 업데이트 메시지가 표시됩니다. + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + 오픈파일럿이 차량을 식별할 수 없습니다. 지원되지 않는 차량이거나 ECU가 인식되지 않습니다. 해당 차량에 맞는 펌웨어 버전을 추가하려면 PR을 제출하세요. 도움이 필요하시면 discord.comma.ai에 참여하세요. + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + 오픈파일럿 장치의 장착 위치가 변경되었습니다. 장치가 마운트에 완전히 장착되고 마운트가 앞유리에 단단히 고정되었는지 확인하세요. + + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + 장치 온도가 너무 높습니다. 시작하기 전에 시스템을 냉각하고 있습니다. 현재 내부 구성 요소 온도: %1 + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + 장치를 comma.ai 백엔드에 등록하지 못했습니다. comma.ai 서버에 연결하거나 업로드하지 않으며 comma.ai로부터 지원을받지 않습니다. comma.ai shop에서 구매 한 장치 인 경우 https://comma.ai/support에서 티켓을 여십시오. + + + Acknowledge Excessive Actuation + 과도한 작동을 인정하십시오 + + + Snooze Update + 업데이트 일시 중지 + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + 업데이트 + + + ALERTS + 알림 + + + ALERT + 알림 + + + + OnroadAlerts + + openpilot Unavailable + 오픈파일럿을 사용할수없습니다 + + + TAKE CONTROL IMMEDIATELY + 핸들을 잡아주세요 + + + Reboot Device + 장치를 재부팅하세요 + + + Waiting to start + 시작을 기다리는중 + + + System Unresponsive + 시스템이 응답하지않습니다 + + + + PairingPopup + + Pair your device to your comma account + 장치를 comma 계정에 동기화합니다 + + + Go to https://connect.comma.ai on your phone + https://connect.comma.ai에 접속하세요 + + + Click "add new device" and scan the QR code on the right + "새 장치 추가"를 클릭하고 오른쪽 QR 코드를 스캔하세요 + + + Bookmark connect.comma.ai to your home screen to use it like an app + connect.comma.ai를 앱처럼 사용하려면 홈 화면에 바로가기를 만드세요 + + + Please connect to Wi-Fi to complete initial pairing + 초기 동기화를 완료하려면 Wi-Fi에 연결하세요. + + + + ParamControl + + Cancel + 취소 + + + Enable + 활성화 + + + + PrimeAdWidget + + Upgrade Now + 지금 업그레이드하세요 + + + Become a comma prime member at connect.comma.ai + connect.comma.ai에서 comma prime 사용자로 등록하세요 + + + PRIME FEATURES: + PRIME 기능: + + + Remote access + 원격 접속 + + + 24/7 LTE connectivity + 항상 LTE 연결 + + + 1 year of drive storage + 1년간 주행 로그 저장 + + + Remote snapshots + 원격 스냅샷 + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ 구독함 + + + comma prime + comma prime + + + + QObject + + openpilot + 오픈파일럿 + + + %n minute(s) ago + + %n 분 전 + + + + %n hour(s) ago + + %n 시간 전 + + + + %n day(s) ago + + %n 일 전 + + + + now + now + + + + SettingsWindow + + × + × + + + Device + 장치 + + + Network + 네트워크 + + + Toggles + 토글 + + + Software + 소프트웨어 + + + Developer + 개발자 + + + Firehose + 파이어호스 + + + + SetupWidget + + Finish Setup + 설정 완료 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + 장치를 comma connect (connect.comma.ai)에서 동기화하고 comma prime 무료 이용권을 사용하세요. + + + Pair device + 장치 동기화 + + + + Sidebar + + CONNECT + 커넥트 + + + OFFLINE + 연결 안됨 + + + ONLINE + 온라인 + + + ERROR + 오류 + + + TEMP + 온도 + + + HIGH + 높음 + + + GOOD + 좋음 + + + OK + OK + + + VEHICLE + 차량 + + + NO + NO + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + LAN + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + 업데이트는 차량 시동이 꺼졌을 때 다운로드됩니다. + + + Current Version + 현재 버전 + + + Download + 다운로드 + + + Install Update + 업데이트 설치 + + + INSTALL + 설치 + + + Target Branch + 대상 브랜치 + + + SELECT + 선택 + + + Select a branch + 브랜치 선택 + + + UNINSTALL + 제거 + + + Uninstall %1 + %1 제거 + + + Are you sure you want to uninstall? + 제거하시겠습니까? + + + CHECK + 확인 + + + Uninstall + 제거 + + + failed to check for update + 업데이트를 확인하지 못했습니다 + + + up to date, last checked %1 + 최신 버전입니다. 마지막 확인: %1 + + + DOWNLOAD + 다운로드 + + + update available + 업데이트 가능 + + + never + 업데이트 안함 + + + + SshControl + + SSH Keys + SSH 키 + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + 경고: 이 설정은 GitHub에 등록된 모든 공용 키에 대해 SSH 액세스 권한을 부여합니다. 본인의 GitHub 사용자 아이디 이외에는 입력하지 마십시오. comma에서는 GitHub 아이디를 추가하라는 요청을 하지 않습니다. + + + ADD + 추가 + + + Enter your GitHub username + GitHub 사용자 ID + + + LOADING + 로딩 중 + + + REMOVE + 삭제 + + + Username '%1' has no keys on GitHub + 사용자 '%1'의 GitHub에 키가 등록되어 있지 않습니다 + + + Request timed out + 요청 시간 초과 + + + Username '%1' doesn't exist on GitHub + GitHub 사용자 '%1'를 찾지 못했습니다 + + + + SshToggle + + Enable SSH + SSH 사용 + + + + TermsPage + + Decline + 거절 + + + Agree + 동의 + + + Welcome to openpilot + 오픈파일럿에 오신 것을 환영합니다. + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + 오픈파일럿을 사용하려면 이용약관에 동의해야 합니다. 최신 약관은 <span style='color: #465BEA;'>https://comma.ai/terms</span> 에서 최신 약관을 읽은 후 계속하세요. + + + + TogglesPanel + + Enable openpilot + 오픈파일럿 사용 + + + Enable Lane Departure Warnings + 차선 이탈 경고 활성화 + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + 차량이 50km/h(31mph) 이상의 속도로 주행할 때 방향지시등이 켜지지 않은 상태에서 차선을 벗어나면 경고합니다. + + + Use Metric System + 미터법 사용 + + + Display speed in km/h instead of mph. + mph 대신 km/h로 속도를 표시합니다. + + + Record and Upload Driver Camera + 운전자 카메라 녹화 및 업로드 + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + 운전자 카메라의 영상 데이터를 업로드하여 운전자 모니터링 알고리즘을 개선합니다. + + + Disengage on Accelerator Pedal + 가속페달 조작 시 해제 + + + When enabled, pressing the accelerator pedal will disengage openpilot. + 활성화된 경우 가속 페달을 밟으면 오픈파일럿이 해제됩니다. + + + Experimental Mode + 실험 모드 + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + 오픈파일럿은 기본적으로 <b>안정 모드</b>로 주행합니다. 실험 모드는 안정화되지 않은 <b>알파 수준의 기능</b>을 활성화합니다. 실험 모드의 기능은 아래와 같습니다: + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + 주행모델이 가감속을 제어하도록 합니다. 오픈파일럿은 빨간불과 정지신호를 보고 정지하는것을 포함하여 사람이 운전하는 방식대로 작동하며 주행 모델이 속도를 결정하므로 설정 속도는 최대 제한 속도로만 작동합니다. 이는 알파 수준의 기능이며 오류가 발생할수있으니 사용에 주의해야 합니다. + + + New Driving Visualization + 새로운 주행 시각화 + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + 차량의 ACC가 가감속 제어에 사용되기 때문에, 이 차량에서는 실험 모드를 사용할 수 없습니다. + + + openpilot longitudinal control may come in a future update. + 오픈파일럿 가감속 제어는 향후 업데이트에서 지원될 수 있습니다. + + + Aggressive + 공격적 + + + Standard + 표준 + + + Relaxed + 편안한 + + + Driving Personality + 주행 모드 + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + 오픈파일럿 가감속 제어 알파 버전은 비 릴리즈 브랜치에서 실험 모드와 함께 테스트할 수 있습니다. + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + 실험 모드를 사용하려면 오픈파일럿 E2E 가감속 제어 (알파) 토글을 활성화하세요. + + + End-to-End Longitudinal Control + E2E 가감속 제어 + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + 표준 모드를 권장합니다. 공격적 모드의 오픈파일럿은 선두 차량을 더 가까이 따라가고 가감속제어를 사용하여 더욱 공격적으로 움직입니다. 편안한 모드의 오픈파일럿은 선두 차량으로부터 더 멀리 떨어져 있습니다. 지원되는 차량에서는 차간거리 버튼을 사용하여 이러한 특성을 순환할 수 있습니다. + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + 운전 시각화는 일부 회전을 더 잘 보여주기 위해 저속에서 도로를 향한 광각 카메라로 전환됩니다. 우측 상단에 실험 모드 로고가 표시됩니다. + + + Always-On Driver Monitoring + 상시 운전자 모니터링 + + + Enable driver monitoring even when openpilot is not engaged. + 오픈파일럿이 활성화되지 않은 경우에도 드라이버 모니터링을 활성화합니다. + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + ACC 및 차선 유지 지원을 위해 오픈파일럿 시스템을 사용하십시오. 이 기능을 사용하려면 항상주의를 기울여야합니다. + + + Changing this setting will restart openpilot if the car is powered on. + 이 설정을 변경하면 차량이 재가동된후 오픈파일럿이 시작됩니다. + + + Record and Upload Microphone Audio + 마이크 오디오 녹음 및 업로드 + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + 운전 중에 마이크 오디오를 녹음하고 저장하십시오. 오디오는 comma connect의 대시캠 비디오에 포함됩니다. + + + + WiFiPromptWidget + + Open + 열기 + + + Maximize your training data uploads to improve openpilot's driving models. + 오픈파일럿의 주행 모델 개선을 위해 학습 데이터 업로드를 최대화하세요. + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> 파이어호스 모드 <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + 네트워크 검색 중... + + + CONNECTING... + 연결 중... + + + FORGET + 삭제 + + + Forget Wi-Fi Network "%1"? + Wi-Fi "%1"에 자동으로 연결하지 않겠습니까? + + + Forget + 삭제 + + + diff --git a/selfdrive/ui/translations/main_nl.ts b/selfdrive/ui/translations/main_nl.ts new file mode 100644 index 0000000000..10651a4160 --- /dev/null +++ b/selfdrive/ui/translations/main_nl.ts @@ -0,0 +1,1120 @@ + + + + + AbstractAlert + + Close + Sluit + + + Snooze Update + Update uitstellen + + + Reboot and Update + Opnieuw Opstarten en Updaten + + + + AdvancedNetworking + + Back + Terug + + + Enable Tethering + Tethering Inschakelen + + + Tethering Password + Tethering Wachtwoord + + + EDIT + AANPASSEN + + + Enter new tethering password + Voer nieuw tethering wachtwoord in + + + IP Address + IP Adres + + + Enable Roaming + Roaming Inschakelen + + + APN Setting + APN Instelling + + + Enter APN + Voer APN in + + + leave blank for automatic configuration + laat leeg voor automatische configuratie + + + Cellular Metered + + + + Prevent large data uploads when on a metered connection + + + + + AnnotatedCameraWidget + + km/h + km/u + + + mph + mph + + + MAX + MAX + + + SPEED + SPEED + + + LIMIT + LIMIT + + + + ConfirmationDialog + + Ok + Ok + + + Cancel + Annuleren + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + U moet de Algemene Voorwaarden accepteren om openpilot te gebruiken. + + + Back + Terug + + + Decline, uninstall %1 + Afwijzen, verwijder %1 + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + Nvt + + + Serial + Serienummer + + + Driver Camera + Bestuurders Camera + + + PREVIEW + BEKIJKEN + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Bekijk de naar de bestuurder gerichte camera om ervoor te zorgen dat het monitoren van de bestuurder goed zicht heeft. (Voertuig moet uitgschakeld zijn) + + + Reset Calibration + Kalibratie Resetten + + + RESET + RESET + + + Are you sure you want to reset calibration? + Weet u zeker dat u de kalibratie wilt resetten? + + + Review Training Guide + Doorloop de Training Opnieuw + + + REVIEW + BEKIJKEN + + + Review the rules, features, and limitations of openpilot + Bekijk de regels, functies en beperkingen van openpilot + + + Are you sure you want to review the training guide? + Weet u zeker dat u de training opnieuw wilt doorlopen? + + + Regulatory + Regelgeving + + + VIEW + BEKIJKEN + + + Change Language + Taal Wijzigen + + + CHANGE + WIJZIGEN + + + Select a language + Selecteer een taal + + + Reboot + Opnieuw Opstarten + + + Power Off + Uitschakelen + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. + openpilot vereist dat het apparaat binnen 4° links of rechts en binnen 5° omhoog of 8° omlaag wordt gemonteerd. openpilot kalibreert continu, resetten is zelden nodig. + + + Your device is pointed %1° %2 and %3° %4. + Uw apparaat is gericht op %1° %2 en %3° %4. + + + down + omlaag + + + up + omhoog + + + left + links + + + right + rechts + + + Are you sure you want to reboot? + Weet u zeker dat u opnieuw wilt opstarten? + + + Disengage to Reboot + Deactiveer openpilot om opnieuw op te starten + + + Are you sure you want to power off? + Weet u zeker dat u wilt uitschakelen? + + + Disengage to Power Off + Deactiveer openpilot om uit te schakelen + + + + DriveStats + + Drives + Ritten + + + Hours + Uren + + + ALL TIME + TOTAAL + + + PAST WEEK + AFGELOPEN WEEK + + + KM + Km + + + Miles + Mijl + + + + DriverViewScene + + camera starting + Camera wordt gestart + + + + InputDialog + + Cancel + Annuleren + + + Need at least %n character(s)! + + Heeft minstens %n karakter nodig! + Heeft minstens %n karakters nodig! + + + + + Installer + + Installing... + Installeren... + + + Receiving objects: + Objecten ontvangen: + + + Resolving deltas: + Deltas verwerken: + + + Updating files: + Bestanden bijwerken: + + + + MapETA + + eta + eta + + + min + min + + + hr + uur + + + km + km + + + mi + mi + + + + MapInstructions + + km + km + + + m + m + + + mi + mi + + + ft + ft + + + + MapPanel + + Current Destination + Huidige Bestemming + + + CLEAR + LEEGMAKEN + + + Recent Destinations + Recente Bestemmingen + + + Try the Navigation Beta + Probeer de Navigatie Bèta + + + Get turn-by-turn directions displayed and more with a comma +prime subscription. Sign up now: https://connect.comma.ai + Krijg stapsgewijze routebeschrijving en meer met een comma +prime abonnement. Meld u nu aan: https://connect.comma.ai + + + No home +location set + Geen thuislocatie +ingesteld + + + No work +location set + Geen werklocatie +ingesteld + + + no recent destinations + geen recente bestemmingen + + + + MapWindow + + Map Loading + Kaart wordt geladen + + + Waiting for GPS + Wachten op GPS + + + + MultiOptionDialog + + Select + Selecteer + + + Cancel + Annuleren + + + + Networking + + Advanced + Geavanceerd + + + Enter password + Voer wachtwoord in + + + for "%1" + voor "%1" + + + Wrong password + Verkeerd wachtwoord + + + + OffroadHome + + UPDATE + UPDATE + + + ALERTS + WAARSCHUWINGEN + + + ALERT + WAARSCHUWING + + + + PairingPopup + + Pair your device to your comma account + Koppel uw apparaat aan uw comma-account + + + Go to https://connect.comma.ai on your phone + Ga naar https://connect.comma.ai op uw telefoon + + + Click "add new device" and scan the QR code on the right + Klik op "add new device" en scan de QR-code aan de rechterkant + + + Bookmark connect.comma.ai to your home screen to use it like an app + Voeg connect.comma.ai toe op uw startscherm om het als een app te gebruiken + + + + PrimeAdWidget + + Upgrade Now + Upgrade nu + + + Become a comma prime member at connect.comma.ai + Word een comma prime lid op connect.comma.ai + + + PRIME FEATURES: + PRIME BEVAT: + + + Remote access + Toegang op afstand + + + 1 year of storage + 1 jaar lang opslag + + + Developer perks + Voordelen voor ontwikkelaars + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ GEABONNEERD + + + comma prime + comma prime + + + CONNECT.COMMA.AI + CONNECT.COMMA.AI + + + COMMA POINTS + COMMA PUNTEN + + + + QObject + + Reboot + Opnieuw Opstarten + + + Exit + Afsluiten + + + dashcam + dashcam + + + openpilot + openpilot + + + %n minute(s) ago + + %n minuut geleden + %n minuten geleden + + + + %n hour(s) ago + + %n uur geleden + %n uur geleden + + + + %n day(s) ago + + %n dag geleden + %n dagen geleden + + + + + Reset + + Reset failed. Reboot to try again. + Opnieuw instellen mislukt. Start opnieuw op om opnieuw te proberen. + + + Are you sure you want to reset your device? + Weet u zeker dat u uw apparaat opnieuw wilt instellen? + + + Resetting device... + Apparaat opnieuw instellen... + + + System Reset + Systeemreset + + + System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot. + Systeemreset geactiveerd. Druk op bevestigen om alle inhoud en instellingen te wissen. Druk op Annuleren om het opstarten te hervatten. + + + Cancel + Annuleren + + + Reboot + Opnieuw Opstarten + + + Confirm + Bevestigen + + + Unable to mount data partition. Press confirm to reset your device. + Kan gegevenspartitie niet koppelen. Druk op bevestigen om uw apparaat te resetten. + + + + RichTextDialog + + Ok + Ok + + + + SettingsWindow + + × + × + + + Device + Apparaat + + + Network + Netwerk + + + Toggles + Opties + + + Software + Software + + + Navigation + Navigatie + + + + Setup + + WARNING: Low Voltage + WAARCHUWING: Lage Spanning + + + Power your device in a car with a harness or proceed at your own risk. + Voorzie uw apparaat van stroom in een auto met een harnas (car harness) of ga op eigen risico verder. + + + Power off + Uitschakelen + + + Continue + Doorgaan + + + Getting Started + Aan de slag + + + Before we get on the road, let’s finish installation and cover some details. + Laten we, voordat we op pad gaan, de installatie afronden en enkele details bespreken. + + + Connect to Wi-Fi + Maak verbinding met Wi-Fi + + + Back + Terug + + + Continue without Wi-Fi + Doorgaan zonder Wi-Fi + + + Waiting for internet + Wachten op internet + + + Choose Software to Install + Kies Software om te Installeren + + + Dashcam + Dashcam + + + Custom Software + Andere Software + + + Enter URL + Voer URL in + + + for Custom Software + voor Andere Software + + + Downloading... + Downloaden... + + + Download Failed + Downloaden Mislukt + + + Ensure the entered URL is valid, and the device’s internet connection is good. + Zorg ervoor dat de ingevoerde URL geldig is en dat de internetverbinding van het apparaat goed is. + + + Reboot device + Apparaat opnieuw opstarten + + + Start over + Begin opnieuw + + + + SetupWidget + + Finish Setup + Installatie voltooien + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Koppel uw apparaat met comma connect (connect.comma.ai) en claim uw comma prime-aanbieding. + + + Pair device + Apparaat koppelen + + + + Sidebar + + CONNECT + VERBINDING + + + OFFLINE + OFFLINE + + + ONLINE + ONLINE + + + ERROR + FOUT + + + TEMP + TEMP + + + HIGH + HOOG + + + GOOD + GOED + + + OK + OK + + + VEHICLE + VOERTUIG + + + NO + GEEN + + + PANDA + PANDA + + + GPS + GPS + + + SEARCH + ZOEKEN + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + 4G + + + 5G + 5G + + + + SoftwarePanel + + Git Branch + Git Branch + + + Git Commit + Git Commit + + + OS Version + OS Versie + + + Version + Versie + + + Last Update Check + Laatste Updatecontrole + + + The last time openpilot successfully checked for an update. The updater only runs while the car is off. + De laatste keer dat openpilot met succes heeft gecontroleerd op een update. De updater werkt alleen als de auto is uitgeschakeld. + + + Check for Update + Controleer op Updates + + + CHECKING + CONTROLEER + + + Switch Branch + Branch Verwisselen + + + ENTER + INVOEREN + + + The new branch will be pulled the next time the updater runs. + Tijdens de volgende update wordt de nieuwe branch opgehaald. + + + Enter branch name + Voer branch naam in + + + Uninstall %1 + Verwijder %1 + + + UNINSTALL + VERWIJDER + + + Are you sure you want to uninstall? + Weet u zeker dat u de installatie ongedaan wilt maken? + + + failed to fetch update + ophalen van update mislukt + + + CHECK + CONTROLEER + + + Updates are only downloaded while the car is off. + + + + Current Version + + + + Download + + + + Install Update + + + + INSTALL + + + + Target Branch + + + + SELECT + + + + Select a branch + + + + + SshControl + + SSH Keys + SSH Sleutels + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + Waarschuwing: dit geeft SSH toegang tot alle openbare sleutels in uw GitHub-instellingen. Voer nooit een andere GitHub-gebruikersnaam in dan die van uzelf. Een medewerker van comma zal u NOOIT vragen om zijn GitHub-gebruikersnaam toe te voegen. + + + ADD + TOEVOEGEN + + + Enter your GitHub username + Voer uw GitHub gebruikersnaam in + + + LOADING + LADEN + + + REMOVE + VERWIJDEREN + + + Username '%1' has no keys on GitHub + Gebruikersnaam '%1' heeft geen SSH sleutels op GitHub + + + Request timed out + Time-out van aanvraag + + + Username '%1' doesn't exist on GitHub + Gebruikersnaam '%1' bestaat niet op GitHub + + + + SshToggle + + Enable SSH + SSH Inschakelen + + + + TermsPage + + Terms & Conditions + Algemene Voorwaarden + + + Decline + Afwijzen + + + Scroll to accept + Scroll om te accepteren + + + Agree + Akkoord + + + + TogglesPanel + + Enable openpilot + openpilot Inschakelen + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + Gebruik het openpilot-systeem voor adaptieve cruisecontrol en rijstrookassistentie. Uw aandacht is te allen tijde vereist om deze functie te gebruiken. Het wijzigen van deze instelling wordt van kracht wanneer de auto wordt uitgeschakeld. + + + Enable Lane Departure Warnings + Waarschuwingen bij Verlaten Rijstrook Inschakelen + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + Ontvang waarschuwingen om terug naar de rijstrook te sturen wanneer uw voertuig over een gedetecteerde rijstrookstreep drijft zonder dat de richtingaanwijzer wordt geactiveerd terwijl u harder rijdt dan 50 km/u (31 mph). + + + Use Metric System + Gebruik Metrisch Systeem + + + Display speed in km/h instead of mph. + Geef snelheid weer in km/u in plaats van mph. + + + Record and Upload Driver Camera + Opnemen en Uploaden van de Bestuurders Camera + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Upload gegevens van de bestuurders camera en help het algoritme voor het monitoren van de bestuurder te verbeteren. + + + Disengage on Accelerator Pedal + Deactiveren Met Gaspedaal + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Indien ingeschakeld, zal het indrukken van het gaspedaal openpilot deactiveren. + + + Show ETA in 24h Format + Toon verwachte aankomsttijd in 24-uurs formaat + + + Use 24h format instead of am/pm + Gebruik 24-uurs formaat in plaats van AM en PM + + + Show Map on Left Side of UI + Toon kaart aan linkerkant van het scherm + + + Show map on left side when in split screen view. + Toon kaart links in gesplitste schermweergave. + + + openpilot Longitudinal Control + openpilot Longitudinale Controle + + + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! + openpilot zal de radar van de auto uitschakelen en de controle over gas en remmen overnemen. Waarschuwing: hierdoor wordt AEB (automatische noodrem) uitgeschakeld! + + + 🌮 End-to-end longitudinal (extremely alpha) 🌮 + + + + Experimental openpilot Longitudinal Control + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> + + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. + + + + openpilot longitudinal control is not currently available for this car. + + + + Enable experimental longitudinal control to enable this. + + + + + Updater + + Update Required + Update Vereist + + + An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. The download size is approximately 1GB. + Een update van het besturingssysteem is vereist. Verbind je apparaat met Wi-Fi voor de snelste update-ervaring. De downloadgrootte is ongeveer 1 GB. + + + Connect to Wi-Fi + Maak verbinding met Wi-Fi + + + Install + Installeer + + + Back + Terug + + + Loading... + Aan het laden... + + + Reboot + Opnieuw Opstarten + + + Update failed + Update mislukt + + + + WifiUI + + Scanning for networks... + Scannen naar netwerken... + + + CONNECTING... + VERBINDEN... + + + FORGET + VERGETEN + + + Forget Wi-Fi Network "%1"? + Vergeet Wi-Fi Netwerk "%1"? + + + diff --git a/selfdrive/ui/translations/main_pl.ts b/selfdrive/ui/translations/main_pl.ts new file mode 100644 index 0000000000..4f8b03ef50 --- /dev/null +++ b/selfdrive/ui/translations/main_pl.ts @@ -0,0 +1,1124 @@ + + + + + AbstractAlert + + Close + Zamknij + + + Snooze Update + Zaktualizuj później + + + Reboot and Update + Uruchom ponownie i zaktualizuj + + + + AdvancedNetworking + + Back + Wróć + + + Enable Tethering + Włącz hotspot osobisty + + + Tethering Password + Hasło do hotspotu + + + EDIT + EDYTUJ + + + Enter new tethering password + Wprowadź nowe hasło do hotspotu + + + IP Address + Adres IP + + + Enable Roaming + Włącz roaming danych + + + APN Setting + Ustawienia APN + + + Enter APN + Wprowadź APN + + + leave blank for automatic configuration + Pozostaw puste, aby użyć domyślnej konfiguracji + + + Cellular Metered + + + + Prevent large data uploads when on a metered connection + + + + + AnnotatedCameraWidget + + km/h + km/h + + + mph + mph + + + MAX + MAX + + + SPEED + PRĘDKOŚĆ + + + LIMIT + OGRANICZENIE + + + + ConfirmationDialog + + Ok + Ok + + + Cancel + Anuluj + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + Aby korzystać z openpilota musisz zaakceptować regulamin. + + + Back + Wróć + + + Decline, uninstall %1 + Odrzuć, odinstaluj %1 + + + + DevicePanel + + Dongle ID + ID adaptera + + + N/A + N/A + + + Serial + Numer seryjny + + + Driver Camera + Kamera kierowcy + + + PREVIEW + PODGLĄD + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Wyświetl podgląd z kamery skierowanej na kierowcę, aby upewnić się, że monitoring kierowcy ma dobry zakres widzenia. (pojazd musi być wyłączony) + + + Reset Calibration + Zresetuj kalibrację + + + RESET + ZRESETUJ + + + Are you sure you want to reset calibration? + Czy na pewno chcesz zresetować kalibrację? + + + Review Training Guide + Zapoznaj się z samouczkiem + + + REVIEW + ZAPOZNAJ SIĘ + + + Review the rules, features, and limitations of openpilot + Zapoznaj się z zasadami, funkcjami i ograniczeniami openpilota + + + Are you sure you want to review the training guide? + Czy na pewno chcesz się zapoznać z samouczkiem? + + + Regulatory + Regulacja + + + VIEW + WIDOK + + + Change Language + Zmień język + + + CHANGE + ZMIEŃ + + + Select a language + Wybierz język + + + Reboot + Uruchom ponownie + + + Power Off + Wyłącz + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. + openpilot wymaga, aby urządzenie było zamontowane z maksymalnym odchyłem 4° poziomo, 5° w górę oraz 8° w dół. openpilot jest ciągle kalibrowany, rzadko konieczne jest resetowania urządzenia. + + + Your device is pointed %1° %2 and %3° %4. + Twoje urządzenie jest skierowane %1° %2 oraz %3° %4. + + + down + w dół + + + up + w górę + + + left + w lewo + + + right + w prawo + + + Are you sure you want to reboot? + Czy na pewno chcesz uruchomić ponownie urządzenie? + + + Disengage to Reboot + Aby uruchomić ponownie, odłącz sterowanie + + + Are you sure you want to power off? + Czy na pewno chcesz wyłączyć urządzenie? + + + Disengage to Power Off + Aby wyłączyć urządzenie, odłącz sterowanie + + + + DriveStats + + Drives + Przejazdy + + + Hours + Godziny + + + ALL TIME + CAŁKOWICIE + + + PAST WEEK + OSTATNI TYDZIEŃ + + + KM + KM + + + Miles + Mile + + + + DriverViewScene + + camera starting + uruchamianie kamery + + + + InputDialog + + Cancel + Anuluj + + + Need at least %n character(s)! + + Wpisana wartość powinna składać się przynajmniej z %n znaku! + Wpisana wartość powinna skłądać się przynajmniej z %n znaków! + Wpisana wartość powinna skłądać się przynajmniej z %n znaków! + + + + + Installer + + Installing... + Instalowanie... + + + Receiving objects: + Odbieranie obiektów: + + + Resolving deltas: + Rozwiązywanie różnic: + + + Updating files: + Aktualizacja plików: + + + + MapETA + + eta + przewidywany czas + + + min + min + + + hr + godz + + + km + km + + + mi + mi + + + + MapInstructions + + km + km + + + m + m + + + mi + mi + + + ft + ft + + + + MapPanel + + Current Destination + Miejsce docelowe + + + CLEAR + WYCZYŚĆ + + + Recent Destinations + Ostatnie miejsca docelowe + + + Try the Navigation Beta + Wypróbuj nawigację w wersji beta + + + Get turn-by-turn directions displayed and more with a comma +prime subscription. Sign up now: https://connect.comma.ai + Odblokuj nawigację zakręt po zakęcie i wiele więcej subskrybując +comma prime. Zarejestruj się teraz: https://connect.comma.ai + + + No home +location set + Lokalizacja domu +nie została ustawiona + + + No work +location set + Miejsce pracy +nie zostało ustawione + + + no recent destinations + brak ostatnich miejsc docelowych + + + + MapWindow + + Map Loading + Ładowanie Mapy + + + Waiting for GPS + Oczekiwanie na sygnał GPS + + + + MultiOptionDialog + + Select + Wybierz + + + Cancel + Anuluj + + + + Networking + + Advanced + Zaawansowane + + + Enter password + Wprowadź hasło + + + for "%1" + do "%1" + + + Wrong password + Niepoprawne hasło + + + + OffroadHome + + UPDATE + UAKTUALNIJ + + + ALERTS + ALERTY + + + ALERT + ALERT + + + + PairingPopup + + Pair your device to your comma account + Sparuj swoje urzadzenie ze swoim kontem comma + + + Go to https://connect.comma.ai on your phone + Wejdź na stronę https://connect.comma.ai na swoim telefonie + + + Click "add new device" and scan the QR code on the right + Kliknij "add new device" i zeskanuj kod QR znajdujący się po prawej stronie + + + Bookmark connect.comma.ai to your home screen to use it like an app + Dodaj connect.comma.ai do zakładek na swoim ekranie początkowym, aby korzystać z niej jak z aplikacji + + + + PrimeAdWidget + + Upgrade Now + Uaktualnij teraz + + + Become a comma prime member at connect.comma.ai + Zostań członkiem comma prime na connect.comma.ai + + + PRIME FEATURES: + FUNKCJE PRIME: + + + Remote access + Zdalny dostęp + + + 1 year of storage + 1 rok przechowywania danych + + + Developer perks + Udogodnienia dla programistów + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ ZASUBSKRYBOWANO + + + comma prime + comma prime + + + CONNECT.COMMA.AI + CONNECT.COMMA.AI + + + COMMA POINTS + COMMA POINTS + + + + QObject + + Reboot + Uruchom Ponownie + + + Exit + Wyjdź + + + dashcam + wideorejestrator + + + openpilot + openpilot + + + %n minute(s) ago + + %n minutę temu + %n minuty temu + %n minut temu + + + + %n hour(s) ago + + % godzinę temu + %n godziny temu + %n godzin temu + + + + %n day(s) ago + + %n dzień temu + %n dni temu + %n dni temu + + + + + Reset + + Reset failed. Reboot to try again. + Wymazywanie zakończone niepowodzeniem. Aby spróbować ponownie, uruchom ponownie urządzenie. + + + Are you sure you want to reset your device? + Czy na pewno chcesz wymazać urządzenie? + + + Resetting device... + Wymazywanie urządzenia... + + + System Reset + Przywróć do ustawień fabrycznych + + + System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot. + Przywracanie do ustawień fabrycznych. Wciśnij potwierdź, aby usunąć wszystkie dane oraz ustawienia. Wciśnij anuluj, aby wznowić uruchamianie. + + + Cancel + Anuluj + + + Reboot + Uruchom ponownie + + + Confirm + Potwiedź + + + Unable to mount data partition. Press confirm to reset your device. + Partycja nie została zamontowana poprawnie. Wciśnij potwierdź, aby uruchomić ponownie urządzenie. + + + + RichTextDialog + + Ok + Ok + + + + SettingsWindow + + × + x + + + Device + Urządzenie + + + Network + Sieć + + + Toggles + Przełączniki + + + Software + Oprogramowanie + + + Navigation + Nawigacja + + + + Setup + + WARNING: Low Voltage + OSTRZEŻENIE: Niskie Napięcie + + + Power your device in a car with a harness or proceed at your own risk. + Podłącz swoje urządzenie do zasilania poprzez podłączenienie go do pojazdu lub kontynuuj na własną odpowiedzialność. + + + Power off + Wyłącz + + + Continue + Kontynuuj + + + Getting Started + Zacznij + + + Before we get on the road, let’s finish installation and cover some details. + Zanim ruszysz w drogę, dokończ instalację i podaj kilka szczegółów. + + + Connect to Wi-Fi + Połącz z Wi-Fi + + + Back + Wróć + + + Continue without Wi-Fi + Kontynuuj bez połączenia z Wif-Fi + + + Waiting for internet + Oczekiwanie na połączenie sieciowe + + + Choose Software to Install + Wybierz oprogramowanie do instalacji + + + Dashcam + Wideorejestrator + + + Custom Software + Własne oprogramowanie + + + Enter URL + Wprowadź adres URL + + + for Custom Software + do własnego oprogramowania + + + Downloading... + Pobieranie... + + + Download Failed + Pobieranie nie powiodło się + + + Ensure the entered URL is valid, and the device’s internet connection is good. + Upewnij się, że wpisany adres URL jest poprawny, a połączenie internetowe działa poprawnie. + + + Reboot device + Uruchom ponownie + + + Start over + Zacznij od początku + + + + SetupWidget + + Finish Setup + Zakończ konfigurację + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Sparuj swoje urządzenie z comma connect (connect.comma.ai) i wybierz swoją ofertę comma prime. + + + Pair device + Sparuj urządzenie + + + + Sidebar + + CONNECT + POŁĄCZENIE + + + OFFLINE + OFFLINE + + + ONLINE + ONLINE + + + ERROR + BŁĄD + + + TEMP + TEMP + + + HIGH + WYSOKA + + + GOOD + DOBRA + + + OK + OK + + + VEHICLE + POJAZD + + + NO + BRAK + + + PANDA + PANDA + + + GPS + GPS + + + SEARCH + SZUKAJ + + + -- + -- + + + Wi-Fi + Wi-FI + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Git Branch + Gałąź Git + + + Git Commit + Git commit + + + OS Version + Wersja systemu + + + Version + Wersja + + + Last Update Check + Ostatnie sprawdzenie aktualizacji + + + The last time openpilot successfully checked for an update. The updater only runs while the car is off. + Ostatni raz kiedy openpilot znalazł aktualizację. Aktualizator może być uruchomiony wyłącznie wtedy, kiedy pojazd jest wyłączony. + + + Check for Update + Sprawdź uaktualnienia + + + CHECKING + SPRAWDZANIE + + + Switch Branch + Zmień gąłąź + + + ENTER + WPROWADŹ + + + The new branch will be pulled the next time the updater runs. + Nowa gałąź będzie pobrana przy następnym uruchomieniu aktualizatora. + + + Enter branch name + Wprowadź nazwę gałęzi + + + Uninstall %1 + Odinstaluj %1 + + + UNINSTALL + ODINSTALUJ + + + Are you sure you want to uninstall? + Czy na pewno chcesz odinstalować? + + + failed to fetch update + pobieranie aktualizacji zakończone niepowodzeniem + + + CHECK + SPRAWDŹ + + + Updates are only downloaded while the car is off. + + + + Current Version + + + + Download + + + + Install Update + + + + INSTALL + + + + Target Branch + + + + SELECT + + + + Select a branch + + + + + SshControl + + SSH Keys + Klucze SSH + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + Ostrzeżenie: To spowoduje przekazanie dostępu do wszystkich Twoich publicznych kuczy z ustawień GitHuba. Nigdy nie wprowadzaj nazwy użytkownika innej niż swoja. Pracownik comma NIGDY nie poprosi o dodanie swojej nazwy uzytkownika. + + + ADD + DODAJ + + + Enter your GitHub username + Wpisz swoją nazwę użytkownika GitHub + + + LOADING + ŁADOWANIE + + + REMOVE + USUŃ + + + Username '%1' has no keys on GitHub + Użytkownik '%1' nie posiada żadnych kluczy na GitHubie + + + Request timed out + Limit czasu rządania + + + Username '%1' doesn't exist on GitHub + Użytkownik '%1' nie istnieje na GitHubie + + + + SshToggle + + Enable SSH + Włącz SSH + + + + TermsPage + + Terms & Conditions + Regulamin + + + Decline + Odrzuć + + + Scroll to accept + Przewiń w dół, aby zaakceptować + + + Agree + Zaakceptuj + + + + TogglesPanel + + Enable openpilot + Włącz openpilota + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off. + Użyj openpilota do zachowania bezpiecznego odstępu między pojazdami i do asystowania w utrzymywaniu pasa ruchu. Twoja pełna uwaga jest wymagana przez cały czas korzystania z tej funkcji. Ustawienie to może być wdrożone wyłącznie wtedy, gdy pojazd jest wyłączony. + + + Enable Lane Departure Warnings + Włącz ostrzeganie przed zmianą pasa ruchu + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + Otrzymuj alerty o powrocie na właściwy pas, kiedy Twój pojazd przekroczy linię bez włączonego kierunkowskazu jadąc powyżej 50 km/h (31 mph). + + + Use Metric System + Korzystaj z systemu metrycznego + + + Display speed in km/h instead of mph. + Wyświetl prędkość w km/h zamiast mph. + + + Record and Upload Driver Camera + Nagraj i prześlij nagranie z kamery kierowcy + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Prześlij dane z kamery skierowanej na kierowcę i pomóż poprawiać algorytm monitorowania kierowcy. + + + Disengage on Accelerator Pedal + Odłącz poprzez naciśnięcie gazu + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Po włączeniu, naciśnięcie na pedał gazu odłączy openpilota. + + + Show ETA in 24h Format + Pokaż oczekiwany czas dojazdu w formacie 24-godzinnym + + + Use 24h format instead of am/pm + Korzystaj z formatu 24-godzinnego zamiast 12-godzinnego + + + Show Map on Left Side of UI + Pokaż mapę po lewej stronie ekranu + + + Show map on left side when in split screen view. + Pokaż mapę po lewej stronie kiedy ekran jest podzielony. + + + openpilot Longitudinal Control + Kontrola wzdłużna openpilota + + + openpilot will disable the car's radar and will take over control of gas and brakes. Warning: this disables AEB! + openpilot wyłączy radar samochodu i przejmie kontrolę nad gazem i hamulcem. Ostrzeżenie: wyłączony zostanie system AEB! + + + 🌮 End-to-end longitudinal (extremely alpha) 🌮 + + + + Experimental openpilot Longitudinal Control + + + + <b>WARNING: openpilot longitudinal control is experimental for this car and will disable AEB.</b> + + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would. Super experimental. + + + + openpilot longitudinal control is not currently available for this car. + + + + Enable experimental longitudinal control to enable this. + + + + + Updater + + Update Required + Wymagana Aktualizacja + + + An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. The download size is approximately 1GB. + Wymagana aktualizacja systemu operacyjnego. Aby przyspieszyć proces aktualizacji połącz swoje urzeądzenie do Wi-Fi. Rozmiar pobieranej paczki wynosi około 1GB. + + + Connect to Wi-Fi + Połącz się z Wi-Fi + + + Install + Zainstaluj + + + Back + Wróć + + + Loading... + Ładowanie... + + + Reboot + Uruchom ponownie + + + Update failed + Aktualizacja nie powiodła się + + + + WifiUI + + Scanning for networks... + Wyszukiwanie sieci... + + + CONNECTING... + ŁĄCZENIE... + + + FORGET + ZAPOMNIJ + + + Forget Wi-Fi Network "%1"? + Czy chcesz zapomnieć sieć "%1"? + + + diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts new file mode 100644 index 0000000000..77aa5e07c1 --- /dev/null +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -0,0 +1,1074 @@ + + + + + AbstractAlert + + Close + Fechar + + + Reboot and Update + Reiniciar e Atualizar + + + + AdvancedNetworking + + Back + Voltar + + + Enable Tethering + Ativar Tether + + + Tethering Password + Senha Tethering + + + EDIT + EDITAR + + + Enter new tethering password + Insira nova senha tethering + + + IP Address + Endereço IP + + + Enable Roaming + Ativar Roaming + + + APN Setting + APN Config + + + Enter APN + Insira APN + + + leave blank for automatic configuration + deixe em branco para configuração automática + + + Cellular Metered + Plano de Dados Limitado + + + Hidden Network + Rede Oculta + + + CONNECT + CONECTE + + + Enter SSID + Digite o SSID + + + Enter password + Insira a senha + + + for "%1" + para "%1" + + + Prevent large data uploads when on a metered cellular connection + Previna o envio de grandes volumes de dados em conexões de celular com franquia de limite de dados + + + default + padrão + + + metered + limitada + + + unmetered + ilimitada + + + Wi-Fi Network Metered + Rede Wi-Fi com Franquia + + + Prevent large data uploads when on a metered Wi-Fi connection + Previna o envio de grandes volumes de dados em conexões Wi-Fi com franquia de limite de dados + + + + ConfirmationDialog + + Ok + OK + + + Cancel + Cancelar + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + Você precisa aceitar os Termos e Condições para utilizar openpilot. + + + Back + Voltar + + + Decline, uninstall %1 + Rejeitar, desintalar %1 + + + + DeveloperPanel + + Joystick Debug Mode + Modo Joystick Debug + + + Longitudinal Maneuver Mode + Modo Longitudinal Maneuver + + + openpilot Longitudinal Control (Alpha) + Controle Longitudinal openpilot (Embrionário) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + AVISO: o controle longitudinal openpilot está em estado embrionário para este carro e desativará a Frenagem Automática de Emergência (AEB). + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + Neste carro, o openpilot tem como padrão o ACC embutido do carro em vez do controle longitudinal do openpilot. Habilite isso para alternar para o controle longitudinal openpilot. Recomenda-se ativar o modo Experimental ao ativar o embrionário controle longitudinal openpilot. + + + Enable ADB + Habilitar ADB + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB (Android Debug Bridge) permite conectar ao seu dispositivo por meio do USB ou através da rede. Veja https://docs.comma.ai/how-to/connect-to-comma para maiores informações. + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + N/A + + + Serial + Serial + + + Driver Camera + Câmera do Motorista + + + PREVIEW + VER + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Pré-visualizar a câmera voltada para o motorista para garantir que o monitoramento do sistema tenha uma boa visibilidade (veículo precisa estar desligado) + + + Reset Calibration + Reinicializar Calibragem + + + RESET + RESET + + + Are you sure you want to reset calibration? + Tem certeza que quer resetar a calibragem? + + + Review Training Guide + Revisar Guia de Treinamento + + + REVIEW + REVISAR + + + Review the rules, features, and limitations of openpilot + Revisar regras, aprimoramentos e limitações do openpilot + + + Are you sure you want to review the training guide? + Tem certeza que quer rever o treinamento? + + + Regulatory + Regulatório + + + VIEW + VER + + + Change Language + Alterar Idioma + + + CHANGE + ALTERAR + + + Select a language + Selecione o Idioma + + + Reboot + Reiniciar + + + Power Off + Desligar + + + Your device is pointed %1° %2 and %3° %4. + Seu dispositivo está montado %1° %2 e %3° %4. + + + down + baixo + + + up + cima + + + left + esquerda + + + right + direita + + + Are you sure you want to reboot? + Tem certeza que quer reiniciar? + + + Disengage to Reboot + Desacione para Reiniciar + + + Are you sure you want to power off? + Tem certeza que quer desligar? + + + Disengage to Power Off + Desacione para Desligar + + + Reset + Resetar + + + Review + Revisar + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Pareie seu dispositivo com comma connect (connect.comma.ai) e reivindique sua oferta de comma prime. + + + Pair Device + Parear Dispositivo + + + PAIR + PAREAR + + + Disengage to Reset Calibration + Desacione para Resetar a Calibração + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + O openpilot exige que o dispositivo seja montado dentro de 4° para a esquerda ou direita e dentro de 5° para cima ou 9° para baixo. + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + O openpilot está em constante calibração, raramente sendo necessário redefini-lo. Redefinir a calibração reiniciará o openpilot se o carro estiver ligado. + + + + +Steering lag calibration is %1% complete. + + +A calibração do atraso da direção está %1% concluída. + + + + +Steering lag calibration is complete. + + +A calibração do atraso da direção foi concluída. + + + Steering torque response calibration is %1% complete. + A calibração da resposta de torque da direção está %1% concluída. + + + Steering torque response calibration is complete. + A calibração da resposta do torque da direção foi concluída. + + + + DriverViewWindow + + camera starting + câmera iniciando + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + MODO EXPERIMENTAL ON + + + CHILL MODE ON + MODO CHILL ON + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + O openpilot aprende a dirigir observando humanos, como você, dirigirem. + +O Modo Firehose permite maximizar o envio de dados de treinamento para melhorar os modelos de direção do openpilot. Mais dados significam modelos maiores, o que resulta em um Modo Experimental melhor. + + + Firehose Mode: ACTIVE + Modo Firehose: ATIVO + + + ACTIVE + ATIVO + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + Para maior eficácia, leve seu dispositivo para dentro de casa e conecte-o a um bom adaptador USB-C e Wi-Fi semanalmente.<br><br>O Modo Firehose também pode funcionar enquanto você dirige, se estiver conectado a um hotspot ou a um chip SIM com dados ilimitados.<br><br><br><b>Perguntas Frequentes</b><br><br><i>Importa como ou onde eu dirijo?</i> Não, basta dirigir normalmente.<br><br><i>Todos os meus segmentos são enviados no Modo Firehose?</i> Não, selecionamos apenas um subconjunto dos seus segmentos.<br><br><i>Qual é um bom adaptador USB-C?</i> Qualquer carregador rápido de telefone ou laptop deve ser suficiente.<br><br><i>Importa qual software eu uso?</i> Sim, apenas o openpilot oficial (e alguns forks específicos) podem ser usados para treinamento. + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>%n segmento</b> da sua direção está no conjunto de dados de treinamento até agora. + <b>%n segmentos</b> da sua direção estão no conjunto de dados de treinamento até agora. + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INATIVO</span>: conecte-se a uma rede sem limite <br> de dados + + + Firehose Mode + Modo Firehose + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + LIMITE + + + + InputDialog + + Cancel + Cancelar + + + Need at least %n character(s)! + + Necessita no mínimo %n caractere! + Necessita no mínimo %n caracteres! + + + + + MultiOptionDialog + + Select + Selecione + + + Cancel + Cancelar + + + + Networking + + Advanced + Avançado + + + Enter password + Insira a senha + + + for "%1" + para "%1" + + + Wrong password + Senha incorreta + + + + OffroadAlert + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + Conecte-se imediatamente à internet para verificar se há atualizações. Se você não se conectar à internet em %1 não será possível acionar o openpilot. + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + Conecte-se à internet para verificar se há atualizações. O openpilot não será iniciado automaticamente até que ele se conecte à internet para verificar se há atualizações. + + + Unable to download updates +%1 + Não é possível baixar atualizações +%1 + + + Taking camera snapshots. System won't start until finished. + Tirando fotos da câmera. O sistema não será iniciado até terminar. + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + Uma atualização para o sistema operacional do seu dispositivo está sendo baixada em segundo plano. Você será solicitado a atualizar quando estiver pronto para instalar. + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + O openpilot não conseguiu identificar o seu carro. Seu carro não é suportado ou seus ECUs não são reconhecidos. Envie um pull request para adicionar as versões de firmware ao veículo adequado. Precisa de ajuda? Junte-se discord.comma.ai. + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + O openpilot detectou uma mudança na posição de montagem do dispositivo. Verifique se o dispositivo está totalmente encaixado no suporte e se o suporte está firmemente preso ao para-brisa. + + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + Temperatura do dispositivo muito alta. O sistema está sendo resfriado antes de iniciar. A temperatura atual do componente interno é: %1 + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + O dispositivo não conseguiu se registrar no backend da comma.ai. Ele não se conecta nem faz upload para os servidores da comma.ai e não recebe suporte da comma.ai. Se este for um dispositivo adquirido em comma.ai/shop, abra um ticket em https://comma.ai/support. + + + Acknowledge Excessive Actuation + Reconhecer Atuação Excessiva + + + Snooze Update + Adiar Atualização + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + openpilot detectou atuação excessiva de %1 na sua última condução. Entre em contato com o suporte em https://comma.ai/support e compartilhe o Dongle ID do seu dispositivo para solução de problemas. + + + + OffroadHome + + UPDATE + ATUALIZAÇÃO + + + ALERTS + ALERTAS + + + ALERT + ALERTA + + + + OnroadAlerts + + openpilot Unavailable + openpilot Indisponível + + + TAKE CONTROL IMMEDIATELY + ASSUMA IMEDIATAMENTE + + + Reboot Device + Reinicie o Dispositivo + + + Waiting to start + Aguardando para iniciar + + + System Unresponsive + Sistema sem Resposta + + + + PairingPopup + + Pair your device to your comma account + Pareie seu dispositivo à sua conta comma + + + Go to https://connect.comma.ai on your phone + navegue até https://connect.comma.ai no seu telefone + + + Click "add new device" and scan the QR code on the right + Clique "add new device" e escaneie o QR code a seguir + + + Bookmark connect.comma.ai to your home screen to use it like an app + Salve connect.comma.ai como sua página inicial para utilizar como um app + + + Please connect to Wi-Fi to complete initial pairing + Por favor conecte ao Wi-Fi para completar o pareamento inicial + + + + ParamControl + + Cancel + Cancelar + + + Enable + Ativar + + + + PrimeAdWidget + + Upgrade Now + Atualizar Agora + + + Become a comma prime member at connect.comma.ai + Seja um membro comma prime em connect.comma.ai + + + PRIME FEATURES: + BENEFÍCIOS PRIME: + + + Remote access + Acesso remoto (proxy comma) + + + 24/7 LTE connectivity + Conectividade LTE (só nos EUA) + + + 1 year of drive storage + 1 ano de dados em nuvem + + + Remote snapshots + Captura remota + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ INSCRITO + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + há %n minuto + há %n minutos + + + + %n hour(s) ago + + há %n hora + há %n horas + + + + %n day(s) ago + + há %n dia + há %n dias + + + + now + agora + + + + SettingsWindow + + × + × + + + Device + Dispositivo + + + Network + Rede + + + Toggles + Ajustes + + + Software + Software + + + Developer + Desenvdor + + + Firehose + Firehose + + + + SetupWidget + + Finish Setup + Concluir + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Pareie seu dispositivo com comma connect (connect.comma.ai) e reivindique sua oferta de comma prime. + + + Pair device + Parear dispositivo + + + + Sidebar + + CONNECT + CONEXÃO + + + OFFLINE + OFFLINE + + + ONLINE + ONLINE + + + ERROR + ERRO + + + TEMP + TEMP + + + HIGH + ALTA + + + GOOD + BOA + + + OK + OK + + + VEHICLE + VEÍCULO + + + NO + SEM + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + Atualizações baixadas durante o motor desligado. + + + Current Version + Versão Atual + + + Download + Download + + + Install Update + Instalar Atualização + + + INSTALL + INSTALAR + + + Target Branch + Alterar Branch + + + SELECT + SELECIONE + + + Select a branch + Selecione uma branch + + + UNINSTALL + REMOVER + + + Uninstall %1 + Desinstalar o %1 + + + Are you sure you want to uninstall? + Tem certeza que quer desinstalar? + + + CHECK + VERIFICAR + + + Uninstall + Desinstalar + + + failed to check for update + falha ao verificar por atualizações + + + up to date, last checked %1 + atualizado, última verificação %1 + + + DOWNLOAD + BAIXAR + + + update available + atualização disponível + + + never + nunca + + + + SshControl + + SSH Keys + Chave SSH + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + Aviso: isso concede acesso SSH a todas as chaves públicas nas configurações do GitHub. Nunca insira um nome de usuário do GitHub que não seja o seu. Um funcionário da comma NUNCA pedirá que você adicione seu nome de usuário do GitHub. + + + ADD + ADICIONAR + + + Enter your GitHub username + Insira seu nome de usuário do GitHub + + + LOADING + CARREGANDO + + + REMOVE + REMOVER + + + Username '%1' has no keys on GitHub + Usuário "%1” não possui chaves no GitHub + + + Request timed out + A solicitação expirou + + + Username '%1' doesn't exist on GitHub + Usuário '%1' não existe no GitHub + + + + SshToggle + + Enable SSH + Habilitar SSH + + + + TermsPage + + Decline + Declinar + + + Agree + Concordo + + + Welcome to openpilot + Bem vindo ao openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + Você deve aceitar os Termos e Condições para usar o openpilot. Leia os termos mais recentes em <span style='color: #465BEA;'>https://comma.ai/terms</span> antes de continuar. + + + + TogglesPanel + + Enable openpilot + Ativar openpilot + + + Enable Lane Departure Warnings + Ativar Avisos de Saída de Faixa + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + Receba alertas para voltar para a pista se o seu veículo sair da faixa e a seta não tiver sido acionada previamente quando em velocidades superiores a 50 km/h. + + + Use Metric System + Usar Sistema Métrico + + + Display speed in km/h instead of mph. + Exibir velocidade em km/h invés de mph. + + + Record and Upload Driver Camera + Gravar e Upload Câmera Motorista + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Upload dados da câmera voltada para o motorista e ajude a melhorar o algoritmo de monitoramentor. + + + Disengage on Accelerator Pedal + Desacionar com Pedal do Acelerador + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Quando ativado, pressionar o pedal do acelerador desacionará o openpilot. + + + Experimental Mode + Modo Experimental + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + openpilot por padrão funciona em <b>modo chill</b>. modo Experimental ativa <b>recursos de nível-embrionário</b> que não estão prontos para o modo chill. Recursos experimentais estão listados abaixo: + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + Deixe o modelo de IA controlar o acelerador e os freios. O openpilot irá dirigir como pensa que um humano faria, incluindo parar em sinais vermelhos e sinais de parada. Uma vez que o modelo de condução decide a velocidade a conduzir, a velocidade definida apenas funcionará como um limite superior. Este é um recurso de qualidade embrionária; erros devem ser esperados. + + + New Driving Visualization + Nova Visualização de Condução + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + O modo Experimental está atualmente indisponível para este carro já que o ACC original do carro é usado para controle longitudinal. + + + openpilot longitudinal control may come in a future update. + O controle longitudinal openpilot poderá vir em uma atualização futura. + + + Aggressive + Disputa + + + Standard + Neutro + + + Relaxed + Calmo + + + Driving Personality + Temperamento de Direção + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + Uma versão embrionária do controle longitudinal openpilot pode ser testada em conjunto com o modo Experimental, em branches que não sejam de produção. + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + Habilite o controle longitudinal (embrionário) openpilot para permitir o modo Experimental. + + + End-to-End Longitudinal Control + Controle Longitudinal de Ponta a Ponta + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + Neutro é o recomendado. No modo disputa o openpilot seguirá o carro da frente mais de perto e será mais agressivo com a aceleração e frenagem. No modo calmo o openpilot se manterá mais longe do carro da frente. Em carros compatíveis, você pode alternar esses temperamentos com o botão de distância do volante. + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + A visualização de condução fará a transição para a câmera grande angular voltada para a estrada em baixas velocidades para mostrar melhor algumas curvas. O logotipo do modo Experimental também será mostrado no canto superior direito. + + + Always-On Driver Monitoring + Monitoramento do Motorista Sempre Ativo + + + Enable driver monitoring even when openpilot is not engaged. + Habilite o monitoramento do motorista mesmo quando o openpilot não estiver acionado. + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + Use o sistema openpilot para controle de cruzeiro adaptativo e assistência ao motorista de manutenção de faixa. Sua atenção é necessária o tempo todo para usar esse recurso. + + + Changing this setting will restart openpilot if the car is powered on. + Alterar esta configuração fará com que o openpilot reinicie se o carro estiver ligado. + + + Record and Upload Microphone Audio + Gravar e Fazer Upload do Áudio do Microfone + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + Grave e armazene o áudio do microfone enquanto estiver dirigindo. O áudio será incluído ao vídeo dashcam no comma connect. + + + + WiFiPromptWidget + + Open + Abrir + + + Maximize your training data uploads to improve openpilot's driving models. + Maximize seus envios de dados de treinamento para melhorar os modelos de direção do openpilot. + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> Modo Firehose <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + Procurando redes... + + + CONNECTING... + CONECTANDO... + + + FORGET + ESQUECER + + + Forget Wi-Fi Network "%1"? + Esquecer Rede Wi-Fi "%1"? + + + Forget + Esquecer + + + diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts new file mode 100644 index 0000000000..9bd6822086 --- /dev/null +++ b/selfdrive/ui/translations/main_th.ts @@ -0,0 +1,1065 @@ + + + + + AbstractAlert + + Close + ปิด + + + Reboot and Update + รีบูตและอัปเดต + + + + AdvancedNetworking + + Back + ย้อนกลับ + + + Enable Tethering + ปล่อยฮอตสปอต + + + Tethering Password + รหัสผ่านฮอตสปอต + + + EDIT + แก้ไข + + + Enter new tethering password + ป้อนรหัสผ่านฮอตสปอตใหม่ + + + IP Address + หมายเลขไอพี + + + Enable Roaming + เปิดใช้งานโรมมิ่ง + + + APN Setting + ตั้งค่า APN + + + Enter APN + ป้อนค่า APN + + + leave blank for automatic configuration + เว้นว่างเพื่อตั้งค่าอัตโนมัติ + + + Cellular Metered + ลดการส่งข้อมูลผ่านเซลลูล่าร์ + + + Hidden Network + เครือข่ายที่ซ่อนอยู่ + + + CONNECT + เชื่อมต่อ + + + Enter SSID + ป้อนค่า SSID + + + Enter password + ใส่รหัสผ่าน + + + for "%1" + สำหรับ "%1" + + + Prevent large data uploads when on a metered cellular connection + + + + default + + + + metered + + + + unmetered + + + + Wi-Fi Network Metered + + + + Prevent large data uploads when on a metered Wi-Fi connection + + + + + ConfirmationDialog + + Ok + ตกลง + + + Cancel + ยกเลิก + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + คุณต้องยอมรับเงื่อนไขและข้อตกลง เพื่อใช้งาน openpilot + + + Back + ย้อนกลับ + + + Decline, uninstall %1 + ปฏิเสธ และถอนการติดตั้ง %1 + + + + DeveloperPanel + + Joystick Debug Mode + โหมดดีบักจอยสติ๊ก + + + Longitudinal Maneuver Mode + โหมดการควบคุมการเร่ง/เบรค + + + openpilot Longitudinal Control (Alpha) + ระบบควบคุมการเร่ง/เบรคโดย openpilot (Alpha) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + คำเตือน: การควบคุมการเร่ง/เบรคโดย openpilot สำหรับรถคันนี้ยังอยู่ในสถานะ alpha และระบบเบรคฉุกเฉินอัตโนมัติ (AEB) จะถูกปิด + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + โดยปกติสำหรับรถคันนี้ openpilot จะควบคุมการเร่ง/เบรคด้วยระบบ ACC จากโรงงาน แทนการควยคุมโดย openpilot เปิดสวิตซ์นี้เพื่อให้ openpilot ควบคุมการเร่ง/เบรค แนะนำให้เปิดโหมดทดลองเมื่อต้องการให้ openpilot ควบคุมการเร่ง/เบรค ซึ่งอยู่ในสถานะ alpha + + + Enable ADB + เปิด ADB + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB (Android Debug Bridge) อนุญาตให้เชื่อมต่ออุปกรณ์ของคุณผ่าน USB หรือผ่านเครือข่าย ดูข้อมูลเพิ่มเติมที่ https://docs.comma.ai/how-to/connect-to-comma + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + ไม่มี + + + Serial + ซีเรียล + + + Driver Camera + กล้องฝั่งคนขับ + + + PREVIEW + แสดงภาพ + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + ดูภาพตัวอย่างกล้องที่หันเข้าหาคนขับเพื่อให้แน่ใจว่าการตรวจสอบคนขับมีทัศนวิสัยที่ดี (รถต้องดับเครื่องยนต์) + + + Reset Calibration + รีเซ็ตการคาลิเบรท + + + RESET + รีเซ็ต + + + Are you sure you want to reset calibration? + คุณแน่ใจหรือไม่ว่าต้องการรีเซ็ตการคาลิเบรท? + + + Review Training Guide + ทบทวนคู่มือการใช้งาน + + + REVIEW + ทบทวน + + + Review the rules, features, and limitations of openpilot + ตรวจสอบกฎ คุณสมบัติ และข้อจำกัดของ openpilot + + + Are you sure you want to review the training guide? + คุณแน่ใจหรือไม่ว่าต้องการทบทวนคู่มือการใช้งาน? + + + Regulatory + ระเบียบข้อบังคับ + + + VIEW + ดู + + + Change Language + เปลี่ยนภาษา + + + CHANGE + เปลี่ยน + + + Select a language + เลือกภาษา + + + Reboot + รีบูต + + + Power Off + ปิดเครื่อง + + + Your device is pointed %1° %2 and %3° %4. + อุปกรณ์ของคุณเอียงไปทาง %2 %1° และ %4 %3° + + + down + ด้านล่าง + + + up + ด้านบน + + + left + ด้านซ้าย + + + right + ด้านขวา + + + Are you sure you want to reboot? + คุณแน่ใจหรือไม่ว่าต้องการรีบูต? + + + Disengage to Reboot + ยกเลิกระบบช่วยขับเพื่อรีบูต + + + Are you sure you want to power off? + คุณแน่ใจหรือไม่ว่าต้องการปิดเครื่อง? + + + Disengage to Power Off + ยกเลิกระบบช่วยขับเพื่อปิดเครื่อง + + + Reset + รีเซ็ต + + + Review + ทบทวน + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + จับคู่อุปกรณ์ของคุณกับ comma connect (connect.comma.ai) และรับข้อเสนอ comma prime ของคุณ + + + Pair Device + จับคู่อุปกรณ์ + + + PAIR + จับคู่ + + + Disengage to Reset Calibration + + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + + + + + +Steering lag calibration is %1% complete. + + + + + +Steering lag calibration is complete. + + + + Steering torque response calibration is %1% complete. + + + + Steering torque response calibration is complete. + + + + + DriverViewWindow + + camera starting + กำลังเปิดกล้อง + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + คุณกำลังใช้โหมดทดลอง + + + CHILL MODE ON + คุณกำลังใช้โหมดชิล + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + openpilot เรียนรู้วิธีขับรถจากการเฝ้าดูการขับขี่ของมนุษย์เช่นคุณ + +โหมดสายยางดับเพลิงช่วยให้คุณอัปโหลดข้อมูลการฝึกฝนได้มากที่สุด เพื่อนำไปพัฒนาโมเดลการขับขี่ของ openpilot ข้อมูลที่มากขึ้นหมายถึงโมเดลที่ใหญ่ขึ้น และนั่นหมายถึงโหมดทดลองที่ดีขึ้น + + + Firehose Mode: ACTIVE + โหมดสายยางดับเพลิง: เปิดใช้งาน + + + ACTIVE + เปิดใช้งาน + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + เพื่อประสิทธิภาพสูงสุด ควรนำอุปกรณ์เข้ามาข้างใน เชื่อมต่อกับอะแดปเตอร์ USB-C คุณภาพดี และ Wi-Fi สัปดาห์ละครั้ง<br><br>โหมดสายยางดับเพลิงยังสามารถทำงานระหว่างขับรถได้ หากเชื่อมต่อกับฮอตสปอตหรือซิมการ์ดที่มีเน็ตไม่จำกัด<br><br><br><b>คำถามที่พบบ่อย</b><br><br><i>วิธีการขับหรือสถานที่ขับขี่มีผลหรือไม่?</i>ไม่มีผล แค่ขับขี่ตามปกติของคุณ<br><br><i>เซกเมนต์ทั้งหมดของฉันจะถูกดึงข้อมูลในโหมดสายยางดับเพลิงหรือไม่?</i>ไม่ใช่ เราจะเลือกดึงข้อมูลเพียงบางส่วนจากเซกเมนต์ของคุณ<br><br><i>อะแดปเตอร์ USB-C แบบไหนดี?</i>ที่ชาร์จเร็วของโทรศัพท์หรือแล็ปท็อปแบบใดก็ได้ สามารถใช้ได้<br><br><i>ซอฟต์แวร์ที่ใช้มีผลหรือไม่?</i>มีผล เฉพาะ openpilot ตัวหลัก (และ fork เฉพาะบางตัว) เท่านั้น ที่สามารถนำข้อมูลไปใช้ฝึกฝนโมเดลได้ + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + มีการขับขี่ของคุณ <b>%n เซกเมนต์</b> อยู่ในชุดข้อมูลการฝึกฝนแล้วในขณะนี้ + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>ไม่เปิดใช้งาน</span>: เชื่อมต่อกับเครือข่ายที่ไม่จำกัดข้อมูล + + + Firehose Mode + + + + + HudRenderer + + km/h + กม./ชม. + + + mph + ไมล์/ชม. + + + MAX + สูงสุด + + + + InputDialog + + Cancel + ยกเลิก + + + Need at least %n character(s)! + + ต้องการอย่างน้อย %n ตัวอักษร! + + + + + MultiOptionDialog + + Select + เลือก + + + Cancel + ยกเลิก + + + + Networking + + Advanced + ขั้นสูง + + + Enter password + ใส่รหัสผ่าน + + + for "%1" + สำหรับ "%1" + + + Wrong password + รหัสผ่านผิด + + + + OffroadAlert + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + อุณหภูมิของอุปกรณ์สูงเกินไป ระบบกำลังทำความเย็นก่อนเริ่ม อุณหภูมิของชิ้นส่วนภายในปัจจุบัน: %1 + + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + กรุณาเชื่อมต่ออินเตอร์เน็ตเพื่อตรวจสอบอัปเดทเดี๋ยวนี้ ถ้าคุณไม่เชื่อมต่ออินเตอร์เน็ต openpilot จะไม่ทำงานในอีก %1 + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + กรุณาเชื่อมต่ออินเตอร์เน็ตเพื่อตรวจสอบอัปเดท openpilot จะไม่เริ่มทำงานอัตโนมัติจนกว่าจะได้เชื่อมต่อกับอินเตอร์เน็ตเพื่อตรวจสอบอัปเดท + + + Unable to download updates +%1 + ไม่สามารถดาวน์โหลดอัพเดทได้ +%1 + + + Taking camera snapshots. System won't start until finished. + กล้องกำลังถ่ายภาพ ระบบจะไม่เริ่มทำงานจนกว่าจะเสร็จ + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + กำลังดาวน์โหลดอัปเดทสำหรับระบบปฏิบัติการอยู่เบื้องหลัง คุณจะได้รับการแจ้งเตือนเมื่อระบบพร้อมสำหรับการติดตั้ง + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilot ไม่สามารถระบุรถยนต์ของคุณได้ ระบบอาจไม่รองรับรถยนต์ของคุณหรือไม่รู้จัก ECU กรุณาส่ง pull request เพื่อเพิ่มรุ่นของเฟิร์มแวร์ให้กับรถยนต์ที่เหมาะสม หากต้องการความช่วยเหลือให้เข้าร่วม discord.comma.ai + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilot ตรวจพบการเปลี่ยนแปลงของตำแหน่งที่ติดตั้ง กรุณาตรวจสอบว่าได้เลื่อนอุปกรณ์เข้ากับจุดติดตั้งจนสุดแล้ว และจุดติดตั้งได้ยึดติดกับกระจกหน้าอย่างแน่นหนา + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + + + + Acknowledge Excessive Actuation + + + + Snooze Update + เลื่อนการอัปเดต + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + อัปเดต + + + ALERTS + การแจ้งเตือน + + + ALERT + การแจ้งเตือน + + + + OnroadAlerts + + openpilot Unavailable + openpilot ไม่สามารถใช้งานได้ + + + TAKE CONTROL IMMEDIATELY + เข้าควบคุมรถเดี๋ยวนี้ + + + Reboot Device + รีบูตอุปกรณ์ + + + Waiting to start + รอเริ่มทำงาน + + + System Unresponsive + ระบบไม่ตอบสนอง + + + + PairingPopup + + Pair your device to your comma account + จับคู่อุปกรณ์ของคุณกับบัญชี comma ของคุณ + + + Go to https://connect.comma.ai on your phone + ไปที่ https://connect.comma.ai ด้วยโทรศัพท์ของคุณ + + + Click "add new device" and scan the QR code on the right + กดที่ "add new device" และสแกนคิวอาร์โค้ดทางด้านขวา + + + Bookmark connect.comma.ai to your home screen to use it like an app + จดจำ connect.comma.ai โดยการเพิ่มไปยังหน้าจอโฮม เพื่อใช้งานเหมือนเป็นแอปพลิเคชัน + + + Please connect to Wi-Fi to complete initial pairing + กรุณาเชื่อมต่อ Wi-Fi เพื่อทำการจับคู่ครั้งแรกให้เสร็จสิ้น + + + + ParamControl + + Enable + เปิดใช้งาน + + + Cancel + ยกเลิก + + + + PrimeAdWidget + + Upgrade Now + อัพเกรดเดี๋ยวนี้ + + + Become a comma prime member at connect.comma.ai + สมัครสมาชิก comma prime ได้ที่ connect.comma.ai + + + PRIME FEATURES: + คุณสมบัติของ PRIME: + + + Remote access + การเข้าถึงระยะไกล + + + 24/7 LTE connectivity + การเชื่อมต่อ LTE แบบ 24/7 + + + 1 year of drive storage + จัดเก็บข้อมูลการขับขี่นาน 1 ปี + + + Remote snapshots + ภาพถ่ายระยะไกล + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ สมัครสำเร็จ + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + %n นาทีที่แล้ว + + + + %n hour(s) ago + + %n ชั่วโมงที่แล้ว + + + + %n day(s) ago + + %n วันที่แล้ว + + + + now + ตอนนี้ + + + + SettingsWindow + + × + × + + + Device + อุปกรณ์ + + + Network + เครือข่าย + + + Toggles + ตัวเลือก + + + Software + ซอฟต์แวร์ + + + Developer + นักพัฒนา + + + Firehose + สายยางดับเพลิง + + + + SetupWidget + + Finish Setup + ตั้งค่าเสร็จสิ้น + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + จับคู่อุปกรณ์ของคุณกับ comma connect (connect.comma.ai) และรับข้อเสนอ comma prime ของคุณ + + + Pair device + จับคู่อุปกรณ์ + + + + Sidebar + + CONNECT + เชื่อมต่อ + + + OFFLINE + ออฟไลน์ + + + ONLINE + ออนไลน์ + + + ERROR + เกิดข้อผิดพลาด + + + TEMP + อุณหภูมิ + + + HIGH + สูง + + + GOOD + ดี + + + OK + พอใช้ + + + VEHICLE + รถยนต์ + + + NO + ไม่พบ + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Uninstall %1 + ถอนการติดตั้ง %1 + + + UNINSTALL + ถอนการติดตั้ง + + + Are you sure you want to uninstall? + คุณแน่ใจหรือไม่ว่าต้องการถอนการติดตั้ง? + + + CHECK + ตรวจสอบ + + + Updates are only downloaded while the car is off. + ตัวอัปเดตจะดำเนินการดาวน์โหลดเมื่อรถดับเครื่องยนต์อยู่เท่านั้น + + + Current Version + เวอร์ชั่นปัจจุบัน + + + Download + ดาวน์โหลด + + + Install Update + ติดตั้งตัวอัปเดต + + + INSTALL + ติดตั้ง + + + Target Branch + Branch ที่เลือก + + + SELECT + เลือก + + + Select a branch + เลือก Branch + + + Uninstall + ถอนการติดตั้ง + + + failed to check for update + ไม่สามารถตรวจสอบอัปเดตได้ + + + DOWNLOAD + ดาวน์โหลด + + + update available + มีอัปเดตใหม่ + + + never + ไม่เคย + + + up to date, last checked %1 + ล่าสุดแล้ว ตรวจสอบครั้งสุดท้ายเมื่อ %1 + + + + SshControl + + SSH Keys + คีย์ SSH + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + คำเตือน: สิ่งนี้ให้สิทธิ์ SSH เข้าถึงคีย์สาธารณะทั้งหมดใน GitHub ของคุณ อย่าป้อนชื่อผู้ใช้ GitHub อื่นนอกเหนือจากของคุณเอง พนักงาน comma จะไม่ขอให้คุณเพิ่มชื่อผู้ใช้ GitHub ของพวกเขา + + + ADD + เพิ่ม + + + Enter your GitHub username + ป้อนชื่อผู้ใช้ GitHub ของคุณ + + + LOADING + กำลังโหลด + + + REMOVE + ลบ + + + Username '%1' has no keys on GitHub + ชื่อผู้ใช้ '%1' ไม่มีคีย์บน GitHub + + + Request timed out + ตรวจสอบไม่สำเร็จ เนื่องจากใช้เวลามากเกินไป + + + Username '%1' doesn't exist on GitHub + ไม่พบชื่อผู้ใช้ '%1' บน GitHub + + + + SshToggle + + Enable SSH + เปิดใช้งาน SSH + + + + TermsPage + + Decline + ปฏิเสธ + + + Agree + ยอมรับ + + + Welcome to openpilot + ยินดีต้อนรับสู่ openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + คุณต้องยอมรับข้อกำหนดและเงื่อนไขเพื่อใช้งาน openpilot อ่านข้อกำหนดล่าสุดได้ที่ <span style='color: #465BEA;'>https://comma.ai/terms</span> ก่อนดำเนินการต่อ + + + + TogglesPanel + + Enable openpilot + เปิดใช้งาน openpilot + + + Enable Lane Departure Warnings + เปิดใช้งานการเตือนการออกนอกเลน + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + รับการแจ้งเตือนให้เลี้ยวกลับเข้าเลนเมื่อรถของคุณตรวจพบการข้ามช่องจราจรโดยไม่เปิดสัญญาณไฟเลี้ยวในขณะขับขี่ที่ความเร็วเกิน 31 ไมล์ต่อชั่วโมง (50 กม./ชม) + + + Use Metric System + ใช้ระบบเมตริก + + + Display speed in km/h instead of mph. + แสดงความเร็วเป็น กม./ชม. แทน ไมล์/ชั่วโมง + + + Record and Upload Driver Camera + บันทึกและอัปโหลดภาพจากกล้องคนขับ + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + อัปโหลดข้อมูลจากกล้องที่หันหน้าไปทางคนขับ และช่วยปรับปรุงอัลกอริธึมการตรวจสอบผู้ขับขี่ + + + Disengage on Accelerator Pedal + ยกเลิกระบบช่วยขับเมื่อเหยียบคันเร่ง + + + When enabled, pressing the accelerator pedal will disengage openpilot. + เมื่อเปิดใช้งาน การกดแป้นคันเร่งจะเป็นการยกเลิกระบบช่วยขับโดย openpilot + + + Experimental Mode + โหมดทดลอง + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + โดยปกติ openpilot จะขับใน<b>โหมดชิล</b> เปิดโหมดทดลองเพื่อใช้<b>ความสามารถในขั้นพัฒนา</b> ซึ่งยังไม่พร้อมสำหรับโหมดชิล ความสามารถในขั้นพัฒนามีดังนี้: + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + ให้ openpilot ควบคุมการเร่ง/เบรค โดย openpilot จะขับอย่างที่มนุษย์คิด รวมถึงการหยุดที่ไฟแดง และป้ายหยุดรถ เนื่องจาก openpilot จะกำหนดความเร็วในการขับด้วยตัวเอง การตั้งความเร็วจะเป็นเพียงการกำหนดความเร็วสูงสูดเท่านั้น ความสามารถนี้ยังอยู่ในขั้นพัฒนา อาจเกิดข้อผิดพลาดขึ้นได้ + + + New Driving Visualization + การแสดงภาพการขับขี่แบบใหม่ + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + ขณะนี้โหมดทดลองไม่สามารถใช้งานได้ในรถคันนี้ เนื่องจากเปิดใช้ระบบควบคุมการเร่ง/เบรคของรถที่ติดตั้งจากโรงงานอยู่ + + + openpilot longitudinal control may come in a future update. + ระบบควบคุมการเร่ง/เบรคโดย openpilot อาจมาในการอัปเดตในอนาคต + + + Aggressive + ดุดัน + + + Standard + มาตรฐาน + + + Relaxed + ผ่อนคลาย + + + Driving Personality + บุคลิกการขับขี่ + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + ระบบควบคุมการเร่ง/เบรคโดย openpilot เวอร์ชัน alpha สามารถทดสอบได้พร้อมกับโหมดการทดลอง บน branch ที่กำลังพัฒนา + + + End-to-End Longitudinal Control + ควบคุมเร่ง/เบรคแบบ End-to-End + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + เปิดระบบควบคุมการเร่ง/เบรคโดย openpilot (alpha) เพื่อเปิดใช้งานโหมดทดลอง + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + แนะนำให้ใช้แบบมาตรฐาน ในโหมดดุดัน openpilot จะตามรถคันหน้าใกล้ขึ้นและเร่งและเบรคแบบดุดันมากขึ้น ในโหมดผ่อนคลาย openpilot จะอยู่ห่างจากรถคันหน้ามากขึ้น ในรถรุ่นที่รองรับคุณสามารถเปลี่ยนบุคลิกไปแบบต่าง ๆ โดยใช้ปุ่มปรับระยะห่างบนพวงมาลัย + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + การแสดงภาพการขับขี่จะเปลี่ยนไปใช้กล้องมุมกว้างที่หันหน้าไปทางถนนเมื่ออยู่ในความเร็วต่ำ เพื่อแสดงภาพการเลี้ยวที่ดีขึ้น โลโก้โหมดการทดลองจะแสดงที่มุมบนขวาด้วย + + + Always-On Driver Monitoring + การเฝ้าระวังผู้ขับขี่ตลอดเวลา + + + Enable driver monitoring even when openpilot is not engaged. + เปิดใช้งานการเฝ้าระวังผู้ขับขี่แม้เมื่อ openpilot ไม่ได้เข้าควบคุมอยู่ + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + + + + Changing this setting will restart openpilot if the car is powered on. + + + + Record and Upload Microphone Audio + + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + + + + + WiFiPromptWidget + + Open + เปิด + + + Maximize your training data uploads to improve openpilot's driving models. + อัปโหลดข้อมูลการฝึกฝนให้ได้มากที่สุด เพื่อพัฒนาโมเดลการขับขี่ของ openpilot + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> โหมดสายยางดับเพลิง <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + กำลังสแกนหาเครือข่าย... + + + CONNECTING... + กำลังเชื่อมต่อ... + + + FORGET + เลิกใช้ + + + Forget Wi-Fi Network "%1"? + เลิกใช้เครือข่าย Wi-Fi "%1"? + + + Forget + เลิกใช้ + + + diff --git a/selfdrive/ui/translations/main_tr.ts b/selfdrive/ui/translations/main_tr.ts new file mode 100644 index 0000000000..7c6c692d54 --- /dev/null +++ b/selfdrive/ui/translations/main_tr.ts @@ -0,0 +1,1062 @@ + + + + + AbstractAlert + + Close + Kapat + + + Reboot and Update + Güncelle ve Yeniden başlat + + + + AdvancedNetworking + + Back + Geri dön + + + Enable Tethering + Kişisel erişim noktasını aç + + + Tethering Password + Kişisel erişim noktasının parolası + + + EDIT + DÜZENLE + + + Enter new tethering password + Erişim noktasına yeni bir sonraki başlatılışında çekilir. parola belirleyin. + + + IP Address + IP Adresi + + + Enable Roaming + Hücresel veri aç + + + APN Setting + APN Ayarları + + + Enter APN + APN Gir + + + leave blank for automatic configuration + otomatik yapılandırma için boş bırakın + + + Cellular Metered + + + + Hidden Network + + + + CONNECT + BAĞLANTI + + + Enter SSID + APN Gir + + + Enter password + Parolayı girin + + + for "%1" + için "%1" + + + Prevent large data uploads when on a metered cellular connection + + + + default + + + + metered + + + + unmetered + + + + Wi-Fi Network Metered + + + + Prevent large data uploads when on a metered Wi-Fi connection + + + + + ConfirmationDialog + + Ok + Tamam + + + Cancel + Vazgeç + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + Openpilotu kullanmak için Kullanıcı Koşullarını kabul etmelisiniz. + + + Back + Geri + + + Decline, uninstall %1 + Reddet, Kurulumu kaldır. %1 + + + + DeveloperPanel + + Joystick Debug Mode + + + + Longitudinal Maneuver Mode + + + + openpilot Longitudinal Control (Alpha) + + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + + + + Enable ADB + + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + + + + + DevicePanel + + Dongle ID + Adaptör ID + + + N/A + N/A + + + Serial + Seri Numara + + + Driver Camera + Sürücü Kamerası + + + PREVIEW + ÖN İZLEME + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + Sürücü kamerasının görüş açısını test etmek için kamerayı önizleyin (Araç kapalı olmalıdır.) + + + Reset Calibration + Kalibrasyonu sıfırla + + + RESET + SIFIRLA + + + Are you sure you want to reset calibration? + Kalibrasyon ayarını sıfırlamak istediğinizden emin misiniz? + + + Review Training Guide + Eğitim kılavuzunu inceleyin + + + REVIEW + GÖZDEN GEÇİR + + + Review the rules, features, and limitations of openpilot + openpilot sisteminin kurallarını ve sınırlamalarını gözden geçirin. + + + Are you sure you want to review the training guide? + Eğitim kılavuzunu incelemek istediğinizden emin misiniz? + + + Regulatory + Mevzuat + + + VIEW + BAK + + + Change Language + Dili değiştir + + + CHANGE + DEĞİŞTİR + + + Select a language + Dil seçin + + + Reboot + Yeniden başlat + + + Power Off + Sistemi kapat + + + Your device is pointed %1° %2 and %3° %4. + Cihazınız %1° %2 ve %3° %4 yönünde ayarlı + + + down + aşağı + + + up + yukarı + + + left + sol + + + right + sağ + + + Are you sure you want to reboot? + Cihazı Tekrar başlatmak istediğinizden eminmisiniz? + + + Disengage to Reboot + Bağlantıyı kes ve Cihazı Yeniden başlat + + + Are you sure you want to power off? + Cihazı kapatmak istediğizden eminmisiniz? + + + Disengage to Power Off + Bağlantıyı kes ve Cihazı kapat + + + Reset + + + + Review + + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Cihazınızı comma connect (connect.comma.ai) ile eşleştirin ve comma prime aboneliğine göz atın. + + + Pair Device + + + + PAIR + + + + Disengage to Reset Calibration + + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + + + + + +Steering lag calibration is %1% complete. + + + + + +Steering lag calibration is complete. + + + + Steering torque response calibration is %1% complete. + + + + Steering torque response calibration is complete. + + + + + DriverViewWindow + + camera starting + kamera başlatılıyor + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + + + + CHILL MODE ON + + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + + + + Firehose Mode: ACTIVE + + + + ACTIVE + + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + + + + Firehose Mode + + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + MAX + + + + InputDialog + + Cancel + Kapat + + + Need at least %n character(s)! + + En az %n karakter gerekli! + + + + + MultiOptionDialog + + Select + Seç + + + Cancel + İptal et + + + + Networking + + Advanced + Gelişmiş Seçenekler + + + Enter password + Parolayı girin + + + for "%1" + için "%1" + + + Wrong password + Yalnış parola + + + + OffroadAlert + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + + + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + + + + Unable to download updates +%1 + + + + Taking camera snapshots. System won't start until finished. + + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + + + + Acknowledge Excessive Actuation + + + + Snooze Update + Güncellemeyi sessize al + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + + + + + OffroadHome + + UPDATE + GÜNCELLE + + + ALERTS + UYARILAR + + + ALERT + UYARI + + + + OnroadAlerts + + openpilot Unavailable + + + + TAKE CONTROL IMMEDIATELY + + + + Reboot Device + + + + Waiting to start + + + + System Unresponsive + + + + + PairingPopup + + Pair your device to your comma account + comma.ai hesabınız ile cihazı eşleştirin + + + Go to https://connect.comma.ai on your phone + Telefonuzdan https://connect.comma.ai sitesine gidin + + + Click "add new device" and scan the QR code on the right + Yeni cihaz eklemek için sağdaki QR kodunu okutun + + + Bookmark connect.comma.ai to your home screen to use it like an app + Uygulama gibi kullanmak için connect.comma.ai sitesini yer işaretlerine ekleyin. + + + Please connect to Wi-Fi to complete initial pairing + + + + + ParamControl + + Enable + + + + Cancel + + + + + PrimeAdWidget + + Upgrade Now + Hemen yükselt + + + Become a comma prime member at connect.comma.ai + connect.comma.ai üzerinden comma prime üyesi olun + + + PRIME FEATURES: + PRIME ABONELİĞİNİN ÖZELLİKLERİ: + + + Remote access + Uzaktan erişim + + + 24/7 LTE connectivity + + + + 1 year of drive storage + + + + Remote snapshots + + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ ABONE + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + %n dakika önce + + + + %n hour(s) ago + + %n saat önce + + + + %n day(s) ago + + %n gün önce + + + + now + + + + + SettingsWindow + + × + x + + + Device + Cihaz + + + Network + + + + Toggles + Değiştirme + + + Software + Yazılım + + + Developer + + + + Firehose + + + + + SetupWidget + + Finish Setup + Kurulumu bitir + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + Cihazınızı comma connect (connect.comma.ai) ile eşleştirin ve comma prime aboneliğine göz atın. + + + Pair device + Cihazı eşleştirme + + + + Sidebar + + CONNECT + BAĞLANTI + + + OFFLINE + ÇEVRİMDIŞI + + + ONLINE + ÇEVRİMİÇİ + + + ERROR + HATA + + + TEMP + SICAKLIK + + + HIGH + YÜKSEK + + + GOOD + İYİ + + + OK + TAMAM + + + VEHICLE + ARAÇ + + + NO + HAYIR + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-FI + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Uninstall %1 + Kaldır %1 + + + UNINSTALL + KALDIR + + + Are you sure you want to uninstall? + Kaldırmak istediğinden eminmisin? + + + CHECK + KONTROL ET + + + Updates are only downloaded while the car is off. + + + + Current Version + + + + Download + + + + Install Update + + + + INSTALL + + + + Target Branch + + + + SELECT + + + + Select a branch + + + + Uninstall + + + + failed to check for update + + + + DOWNLOAD + + + + update available + + + + never + + + + up to date, last checked %1 + + + + + SshControl + + SSH Keys + SSH Anahtarları + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + UYARI: Bu, GitHub ayarlarınızdaki tüm ortak anahtarlara SSH erişimi sağlar. Asla kendi kullanıcı adınız dışında bir sonraki başlatılışında çekilir. GitHub kullanıcı adı girmeyin. + + + ADD + EKLE + + + Enter your GitHub username + Github kullanıcı adınızı giriniz + + + LOADING + YÜKLENİYOR + + + REMOVE + KALDIR + + + Username '%1' has no keys on GitHub + Kullanısının '%1' Github erişim anahtarı yok + + + Request timed out + İstek zaman aşımına uğradı + + + Username '%1' doesn't exist on GitHub + Github kullanıcısı %1 bulunamadı + + + + SshToggle + + Enable SSH + SSH aç + + + + TermsPage + + Decline + Reddet + + + Agree + Kabul et + + + Welcome to openpilot + + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + + + + + TogglesPanel + + Enable openpilot + openpilot'u aktifleştir + + + Enable Lane Departure Warnings + Şerit ihlali uyarı alın + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + 50 km/s (31 mph) hızın üzerinde sürüş sırasında aracınız dönüş sinyali vermeden algılanan bir sonraki başlatılışında çekilir. şerit çizgisi ihlalinde şeride geri dönmek için uyarılar alın. + + + Use Metric System + Metrik sistemi kullan + + + Display speed in km/h instead of mph. + Hızı mph yerine km/h şeklinde görüntüleyin. + + + Record and Upload Driver Camera + Sürücü kamerasını kayıt et. + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + Sürücüye bakan kamera verisini yükleyin ve Cihazın algoritmasını geliştirmemize yardımcı olun. + + + When enabled, pressing the accelerator pedal will disengage openpilot. + Aktifleştirilirse eğer gaz pedalına basınca openpilot devre dışı kalır. + + + Experimental Mode + + + + Disengage on Accelerator Pedal + + + + Aggressive + + + + Standard + + + + Relaxed + + + + Driving Personality + + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + + + + End-to-End Longitudinal Control + + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + + + + New Driving Visualization + + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + + + + openpilot longitudinal control may come in a future update. + + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + + + + Always-On Driver Monitoring + + + + Enable driver monitoring even when openpilot is not engaged. + + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + + + + Changing this setting will restart openpilot if the car is powered on. + + + + Record and Upload Microphone Audio + + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + + + + + WiFiPromptWidget + + Open + + + + Maximize your training data uploads to improve openpilot's driving models. + + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + + WifiUI + + Scanning for networks... + Ağ aranıyor... + + + CONNECTING... + BAĞLANILIYOR... + + + FORGET + UNUT + + + Forget Wi-Fi Network "%1"? + Wi-Fi ağını unut "%1"? + + + Forget + + + + diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts new file mode 100644 index 0000000000..9481e62f10 --- /dev/null +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -0,0 +1,1069 @@ + + + + + AbstractAlert + + Close + 关闭 + + + Reboot and Update + 重启并更新 + + + + AdvancedNetworking + + Back + 返回 + + + Enable Tethering + 启用WiFi热点 + + + Tethering Password + WiFi热点密码 + + + EDIT + 编辑 + + + Enter new tethering password + 输入新的WiFi热点密码 + + + IP Address + IP 地址 + + + Enable Roaming + 启用数据漫游 + + + APN Setting + APN 设置 + + + Enter APN + 输入 APN + + + leave blank for automatic configuration + 留空以自动配置 + + + Cellular Metered + 按流量计费的手机移动网络 + + + Hidden Network + 隐藏的网络 + + + CONNECT + 连线 + + + Enter SSID + 输入 SSID + + + Enter password + 输入密码 + + + for "%1" + 网络名称:"%1" + + + Prevent large data uploads when on a metered cellular connection + 在按流量计费的移动网络上,防止上传大数据 + + + default + 默认 + + + metered + 按流量计费 + + + unmetered + 不按流量计费 + + + Wi-Fi Network Metered + 按流量计费的 WLAN 网络 + + + Prevent large data uploads when on a metered Wi-Fi connection + 在按流量计费的 WLAN 网络上,防止上传大数据 + + + + ConfirmationDialog + + Ok + 好的 + + + Cancel + 取消 + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + 您必须接受条款和条件以使用openpilot。 + + + Back + 返回 + + + Decline, uninstall %1 + 拒绝并卸载%1 + + + + DeveloperPanel + + Joystick Debug Mode + 摇杆调试模式 + + + Longitudinal Maneuver Mode + 纵向操控测试模式 + + + openpilot Longitudinal Control (Alpha) + openpilot纵向控制(Alpha 版) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + 警告:此车辆的 openpilot 纵向控制功能目前处于Alpha版本,使用此功能将会停用自动紧急制动(AEB)功能。 + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + 在这辆车上,openpilot 默认使用车辆内建的主动巡航控制(ACC),而非 openpilot 的纵向控制。启用此项功能可切换至 openpilot 的纵向控制。当启用 openpilot 纵向控制 Alpha 版本时,建议同时启用实验性模式(Experimental mode)。 + + + Enable ADB + 启用 ADB + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB(Android调试桥接)允许通过USB或网络连接到您的设备。更多信息请参见 [https://docs.comma.ai/how-to/connect-to-comma](https://docs.comma.ai/how-to/connect-to-comma)。 + + + + DevicePanel + + Dongle ID + 设备ID(Dongle ID) + + + N/A + N/A + + + Serial + 序列号 + + + Driver Camera + 驾驶员摄像头 + + + PREVIEW + 预览 + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + 打开并预览驾驶员摄像头,以确保驾驶员监控具有良好视野。(仅熄火时可用) + + + Reset Calibration + 重置设备校准 + + + RESET + 重置 + + + Are you sure you want to reset calibration? + 您确定要重置设备校准吗? + + + Review Training Guide + 新手指南 + + + REVIEW + 查看 + + + Review the rules, features, and limitations of openpilot + 查看 openpilot 的使用规则,以及其功能和限制 + + + Are you sure you want to review the training guide? + 您确定要查看新手指南吗? + + + Regulatory + 监管信息 + + + VIEW + 查看 + + + Change Language + 切换语言 + + + CHANGE + 切换 + + + Select a language + 选择语言 + + + Reboot + 重启 + + + Power Off + 关机 + + + Your device is pointed %1° %2 and %3° %4. + 您的设备校准为%1° %2、%3° %4。 + + + down + 朝下 + + + up + 朝上 + + + left + 朝左 + + + right + 朝右 + + + Are you sure you want to reboot? + 您确定要重新启动吗? + + + Disengage to Reboot + 取消openpilot以重新启动 + + + Are you sure you want to power off? + 您确定要关机吗? + + + Disengage to Power Off + 取消openpilot以关机 + + + Reset + 重置 + + + Review + 预览 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + 将您的设备与comma connect (connect.comma.ai)配对并领取您的comma prime优惠。 + + + Pair Device + 配对设备 + + + PAIR + 配对 + + + Disengage to Reset Calibration + 解除以重置校准 + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + openpilot 要求设备的安装角度:左右偏移需在 4° 以内,上下俯仰角度需在向上 5° 至向下 9° 的范围内。 + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + openpilot 会持续进行校准,因此很少需要重置。如果车辆电源已开启,重置校准会重新启动 openpilot。 + + + + +Steering lag calibration is %1% complete. + + +转向延迟校准已完成 %1%。 + + + + +Steering lag calibration is complete. + + +转向延迟校准已完成。 + + + Steering torque response calibration is %1% complete. + 转向扭矩响应校准已完成 %1%。 + + + Steering torque response calibration is complete. + 转向扭矩响应校准已完成。 + + + + DriverViewWindow + + camera starting + 正在启动相机 + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + 试验模式运行 + + + CHILL MODE ON + 轻松模式运行 + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + openpilot 通过观察人类驾驶(包括您)来学习如何驾驶。 + +“Firehose 模式”允许您最大化上传训练数据,以改进 openpilot 的驾驶模型。更多数据意味着更强大的模型,也就意味着更优秀的“实验模式”。 + + + Firehose Mode: ACTIVE + Firehose 模式:激活中 + + + ACTIVE + 激活中 + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + 为了达到最佳效果,请每周将您的设备带回室内,并连接到优质的 USB-C 充电器和 Wi-Fi。<br><br>Firehose 模式在行驶时也能运行,但需连接到移动热点或使用不限流量的 SIM 卡。<br><br><br><b>常见问题</b><br><br><i>我开车的方式或地点有影响吗?</i>不会,请像平常一样驾驶即可。<br><br><i>Firehose 模式会上传所有的驾驶片段吗?</i>不会,我们会选择性地上传部分片段。<br><br><i>什么是好的 USB-C 充电器?</i>任何快速手机或笔记本电脑充电器都应该适用。<br><br><i>我使用的软件版本有影响吗?</i>有的,只有官方 openpilot(以及特定的分支)可以用于训练。 + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>目前已有 %n 段</b> 您的驾驶数据被纳入训练数据集。 + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>闲置</span>:请连接到不限流量的网络 + + + Firehose Mode + Firehose 模式 + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + 最高定速 + + + + InputDialog + + Cancel + 取消 + + + Need at least %n character(s)! + + 至少需要 %n 个字符! + + + + + MultiOptionDialog + + Select + 选择 + + + Cancel + 取消 + + + + Networking + + Advanced + 高级 + + + Enter password + 输入密码 + + + for "%1" + 网络名称:"%1" + + + Wrong password + 密码错误 + + + + OffroadAlert + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + 请立即连接网络检查更新。如果不连接网络,openpilot 将在 %1 后便无法使用 + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + 请连接至互联网以检查更新。在连接至互联网并完成更新检查之前,openpilot 将不会自动启动。 + + + Unable to download updates +%1 + 无法下载更新 +%1 + + + Taking camera snapshots. System won't start until finished. + 正在使用相机拍摄中。在完成之前,系统将无法启动。 + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + 一个针对您设备的操作系统更新正在后台下载中。当更新准备好安装时,您将收到提示进行更新。 + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilot 无法识别您的车辆。您的车辆可能未被支持,或是其电控单元 (ECU) 未被识别。请提交一个 Pull Request 为您的车辆添加正确的固件版本。需要帮助吗?请加入 discord.comma.ai。 + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilot 检测到设备的安装位置发生变化。请确保设备完全安装在支架上,并确保支架牢固地固定在挡风玻璃上。 + + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + 设备温度过高。系统正在冷却中,等冷却完毕后才会启动。目前内部组件温度:%1 + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + 设备未能注册到 comma.ai 后端。该设备将无法连接或上传数据到 comma.ai 服务器,也无法获得 comma.ai 的支持。如果该设备是在 comma.ai/shop 购买的,请访问 https://comma.ai/support 提交工单。 + + + Acknowledge Excessive Actuation + 确认过度作动 + + + Snooze Update + 推迟更新 + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + openpilot 在您上一次驾驶中,检测到过度的 %1 作动。请访问 https://comma.ai/support 联系客服,并提供您设备的 Dongle ID 以便进行故障排查。 + + + + OffroadHome + + UPDATE + 更新 + + + ALERTS + 警报 + + + ALERT + 警报 + + + + OnroadAlerts + + openpilot Unavailable + 无法使用 openpilot + + + TAKE CONTROL IMMEDIATELY + 立即接管 + + + Reboot Device + 重启设备 + + + Waiting to start + 等待开始 + + + System Unresponsive + 系统无响应 + + + + PairingPopup + + Pair your device to your comma account + 将您的设备与comma账号配对 + + + Go to https://connect.comma.ai on your phone + 在手机上访问 https://connect.comma.ai + + + Click "add new device" and scan the QR code on the right + 点击“添加新设备”,扫描右侧二维码 + + + Bookmark connect.comma.ai to your home screen to use it like an app + 将 connect.comma.ai 收藏到您的主屏幕,以便像应用程序一样使用它 + + + Please connect to Wi-Fi to complete initial pairing + 请连接 Wi-Fi 以完成初始配对 + + + + ParamControl + + Cancel + 取消 + + + Enable + 启用 + + + + PrimeAdWidget + + Upgrade Now + 现在升级 + + + Become a comma prime member at connect.comma.ai + 打开connect.comma.ai以注册comma prime会员 + + + PRIME FEATURES: + comma prime特权: + + + Remote access + 远程访问 + + + 24/7 LTE connectivity + 全天候 LTE 连接 + + + 1 year of drive storage + 一年的行驶记录储存空间 + + + Remote snapshots + 远程快照 + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ 已订阅 + + + comma prime + comma prime + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + %n 分钟前 + + + + %n hour(s) ago + + %n 小时前 + + + + %n day(s) ago + + %n 天前 + + + + now + 现在 + + + + SettingsWindow + + × + × + + + Device + 设备 + + + Network + 网络 + + + Toggles + 设定 + + + Software + 软件 + + + Developer + 开发人员 + + + Firehose + Firehose + + + + SetupWidget + + Finish Setup + 完成设置 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + 将您的设备与comma connect (connect.comma.ai)配对并领取您的comma prime优惠。 + + + Pair device + 配对设备 + + + + Sidebar + + CONNECT + CONNECT + + + OFFLINE + 离线 + + + ONLINE + 在线 + + + ERROR + 连接出错 + + + TEMP + 设备温度 + + + HIGH + 过热 + + + GOOD + 良好 + + + OK + 一般 + + + VEHICLE + 车辆连接 + + + NO + + + + PANDA + PANDA + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + 以太网 + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + 车辆熄火时才能下载升级文件。 + + + Current Version + 当前版本 + + + Download + 下载 + + + Install Update + 安装更新 + + + INSTALL + 安装 + + + Target Branch + 目标分支 + + + SELECT + 选择 + + + Select a branch + 选择分支 + + + UNINSTALL + 卸载 + + + Uninstall %1 + 卸载 %1 + + + Are you sure you want to uninstall? + 您确定要卸载吗? + + + CHECK + 查看 + + + Uninstall + 卸载 + + + failed to check for update + 检查更新失败 + + + up to date, last checked %1 + 已经是最新版本,上次检查时间为 %1 + + + DOWNLOAD + 下载 + + + update available + 有可用的更新 + + + never + 从未更新 + + + + SshControl + + SSH Keys + SSH密钥 + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + 警告:这将授予SSH访问权限给您GitHub设置中的所有公钥。切勿输入您自己以外的GitHub用户名。comma员工永远不会要求您添加他们的GitHub用户名。 + + + ADD + 添加 + + + Enter your GitHub username + 输入您的GitHub用户名 + + + LOADING + 正在加载 + + + REMOVE + 删除 + + + Username '%1' has no keys on GitHub + 用户名“%1”在GitHub上没有密钥 + + + Request timed out + 请求超时 + + + Username '%1' doesn't exist on GitHub + GitHub上不存在用户名“%1” + + + + SshToggle + + Enable SSH + 启用SSH + + + + TermsPage + + Decline + 拒绝 + + + Agree + 同意 + + + Welcome to openpilot + 欢迎使用 openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + 您必须接受《条款与条件》才能使用 openpilot。在继续之前,请先阅读最新条款:<span style='color: #465BEA;'>https://comma.ai/terms</span>。 + + + + TogglesPanel + + Enable openpilot + 启用openpilot + + + Enable Lane Departure Warnings + 启用车道偏离警告 + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + 车速超过31mph(50km/h)时,若检测到车辆越过车道线且未打转向灯,系统将发出警告以提醒您返回车道。 + + + Use Metric System + 使用公制单位 + + + Display speed in km/h instead of mph. + 显示车速时,以km/h代替mph。 + + + Record and Upload Driver Camera + 录制并上传驾驶员摄像头 + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + 上传驾驶员摄像头的数据,帮助改进驾驶员监控算法。 + + + Disengage on Accelerator Pedal + 踩油门时取消控制 + + + When enabled, pressing the accelerator pedal will disengage openpilot. + 启用后,踩下油门踏板将取消openpilot。 + + + Experimental Mode + 测试模式 + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + openpilot 默认 <b>轻松模式</b>驾驶车辆。试验模式启用一些轻松模式之外的 <b>试验性功能</b>。试验性功能包括: + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + 允许驾驶模型控制加速和制动,openpilot将模仿人类驾驶车辆,包括在红灯和停车让行标识前停车。鉴于驾驶模型确定行驶车速,所设定的车速仅作为上限。此功能尚处于早期测试状态,有可能会出现操作错误。 + + + New Driving Visualization + 新驾驶视角 + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + 由于此车辆使用自带的ACC纵向控制,当前无法使用试验模式。 + + + openpilot longitudinal control may come in a future update. + openpilot纵向控制可能会在未来的更新中提供。 + + + Aggressive + 积极 + + + Standard + 标准 + + + Relaxed + 舒适 + + + Driving Personality + 驾驶风格 + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + 在正式(release)版本以外的分支上,可以测试 openpilot 纵向控制的 Alpha 版本以及实验模式。 + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + 启用 openpilot 纵向控制(alpha)开关以允许实验模式。 + + + End-to-End Longitudinal Control + 端到端纵向控制 + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + 推荐使用标准模式。在积极模式下,openpilot 会更靠近前方车辆,并在油门和刹车方面更加激进。在放松模式下,openpilot 会与前方车辆保持更远距离。在支持的车型上,你可以使用方向盘上的距离按钮来循环切换这些驾驶风格。 + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + 在低速时,驾驶可视化将转换为道路朝向的广角摄像头,以更好地展示某些转弯。测试模式标志也将显示在右上角。 + + + Always-On Driver Monitoring + 驾驶员监控常开 + + + Enable driver monitoring even when openpilot is not engaged. + 即使在openpilot未激活时也启用驾驶员监控。 + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + openpilot 系统提供“自适应巡航”和“车道保持”驾驶辅助功能。使用此功能时,您需要时刻保持专注。 + + + Changing this setting will restart openpilot if the car is powered on. + 如果车辆已通电,更改此设置将会重新启动 openpilot。 + + + Record and Upload Microphone Audio + 录制并上传麦克风音频 + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + 在驾驶时录制并存储麦克风音频。该音频将会包含在 comma connect 的行车记录仪视频中。 + + + + WiFiPromptWidget + + Open + 开启 + + + Maximize your training data uploads to improve openpilot's driving models. + 最大化您的训练数据上传,以改善 openpilot 的驾驶模型。 + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose 模式 <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + 正在扫描网络…… + + + CONNECTING... + 正在连接…… + + + FORGET + 忽略 + + + Forget Wi-Fi Network "%1"? + 忽略WiFi网络 "%1"? + + + Forget + 忽略 + + + diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts new file mode 100644 index 0000000000..c3ef55d3d9 --- /dev/null +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -0,0 +1,1069 @@ + + + + + AbstractAlert + + Close + 關閉 + + + Reboot and Update + 重啟並更新 + + + + AdvancedNetworking + + Back + 回上頁 + + + Enable Tethering + 啟用網路分享 + + + Tethering Password + 網路分享密碼 + + + EDIT + 編輯 + + + Enter new tethering password + 輸入新的網路分享密碼 + + + IP Address + IP 地址 + + + Enable Roaming + 啟用漫遊 + + + APN Setting + APN 設置 + + + Enter APN + 輸入 APN + + + leave blank for automatic configuration + 留空白將自動配置 + + + Cellular Metered + 計費的行動網路 + + + Hidden Network + 隱藏的網路 + + + CONNECT + 連線 + + + Enter SSID + 輸入 SSID + + + Enter password + 輸入密碼 + + + for "%1" + 給 "%1" + + + Prevent large data uploads when on a metered cellular connection + 在使用計費行動網路時,防止上傳大量數據 + + + default + 預設 + + + metered + 計費 + + + unmetered + 非計費 + + + Wi-Fi Network Metered + 計費 Wi-Fi 網路 + + + Prevent large data uploads when on a metered Wi-Fi connection + 在使用計費 Wi-Fi 網路時,防止上傳大量數據 + + + + ConfirmationDialog + + Ok + 確定 + + + Cancel + 取消 + + + + DeclinePage + + You must accept the Terms and Conditions in order to use openpilot. + 您必須先接受條款和條件才能使用 openpilot。 + + + Back + 回上頁 + + + Decline, uninstall %1 + 拒絕並解除安裝 %1 + + + + DeveloperPanel + + Joystick Debug Mode + 搖桿調試模式 + + + Longitudinal Maneuver Mode + 縱向操控測試模式 + + + openpilot Longitudinal Control (Alpha) + openpilot 縱向控制 (Alpha 版) + + + WARNING: openpilot longitudinal control is in alpha for this car and will disable Automatic Emergency Braking (AEB). + 警告:此車輛的 openpilot 縱向控制功能目前處於 Alpha 版本,使用此功能將會停用自動緊急煞車(AEB)功能。 + + + On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when enabling openpilot longitudinal control alpha. + 在這輛車上,openpilot 預設使用車輛內建的主動巡航控制(ACC),而非 openpilot 的縱向控制。啟用此項功能可切換至 openpilot 的縱向控制。當啟用 openpilot 縱向控制 Alpha 版本時,建議同時啟用實驗性模式(Experimental mode)。 + + + Enable ADB + 啟用 ADB + + + ADB (Android Debug Bridge) allows connecting to your device over USB or over the network. See https://docs.comma.ai/how-to/connect-to-comma for more info. + ADB(Android 調試橋接)允許通過 USB 或網絡連接到您的設備。更多信息請參見 [https://docs.comma.ai/how-to/connect-to-comma](https://docs.comma.ai/how-to/connect-to-comma)。 + + + + DevicePanel + + Dongle ID + Dongle ID + + + N/A + 無法使用 + + + Serial + 序號 + + + Driver Camera + 駕駛員監控鏡頭 + + + PREVIEW + 預覽 + + + Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off) + 預覽駕駛員監控鏡頭畫面,以確保其具有良好視野。(僅在熄火時可用) + + + Reset Calibration + 重設校準 + + + RESET + 重設 + + + Are you sure you want to reset calibration? + 您確定要重設校準嗎? + + + Review Training Guide + 觀看使用教學 + + + REVIEW + 觀看 + + + Review the rules, features, and limitations of openpilot + 觀看 openpilot 的使用規則、功能和限制 + + + Are you sure you want to review the training guide? + 您確定要觀看使用教學嗎? + + + Regulatory + 法規/監管 + + + VIEW + 觀看 + + + Change Language + 更改語言 + + + CHANGE + 更改 + + + Select a language + 選擇語言 + + + Reboot + 重新啟動 + + + Power Off + 關機 + + + Your device is pointed %1° %2 and %3° %4. + 你的裝置目前朝%2 %1° 以及朝%4 %3° 。 + + + down + + + + up + + + + left + + + + right + + + + Are you sure you want to reboot? + 您確定要重新啟動嗎? + + + Disengage to Reboot + 請先取消控車才能重新啟動 + + + Are you sure you want to power off? + 您確定您要關機嗎? + + + Disengage to Power Off + 請先取消控車才能關機 + + + Reset + 重設 + + + Review + 回顧 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + 將您的裝置與 comma connect (connect.comma.ai) 配對並領取您的 comma 高級會員優惠。 + + + Pair Device + 配對裝置 + + + PAIR + 配對 + + + Disengage to Reset Calibration + 解除以重設校準 + + + openpilot requires the device to be mounted within 4° left or right and within 5° up or 9° down. + openpilot 要求裝置的安裝角度,左右偏移須在 4° 以內,上下角度則須介於仰角 5° 至俯角 9° 之間。 + + + openpilot is continuously calibrating, resetting is rarely required. Resetting calibration will restart openpilot if the car is powered on. + openpilot 會持續進行校準,因此很少需要重設。若車輛電源開啟,重設校準將會重新啟動 openpilot。 + + + + +Steering lag calibration is %1% complete. + + +轉向延遲校準已完成 %1%。 + + + + +Steering lag calibration is complete. + + +轉向延遲校準已完成。 + + + Steering torque response calibration is %1% complete. + 轉向扭矩反應校準已完成 %1%。 + + + Steering torque response calibration is complete. + 轉向扭矩反應校準已完成。 + + + + DriverViewWindow + + camera starting + 開啟相機中 + + + + ExperimentalModeButton + + EXPERIMENTAL MODE ON + 實驗模式 ON + + + CHILL MODE ON + 輕鬆模式 ON + + + + FirehosePanel + + openpilot learns to drive by watching humans, like you, drive. + +Firehose Mode allows you to maximize your training data uploads to improve openpilot's driving models. More data means bigger models, which means better Experimental Mode. + openpilot 透過觀察人類駕駛(包括您)來學習如何駕駛。 + +「Firehose 模式」可讓您最大化上傳訓練數據,以改進 openpilot 的駕駛模型。更多數據代表更強大的模型,也就意味著更優秀的「實驗模式」。 + + + Firehose Mode: ACTIVE + Firehose 模式:啟用中 + + + ACTIVE + 啟用中 + + + For maximum effectiveness, bring your device inside and connect to a good USB-C adapter and Wi-Fi weekly.<br><br>Firehose Mode can also work while you're driving if connected to a hotspot or unlimited SIM card.<br><br><br><b>Frequently Asked Questions</b><br><br><i>Does it matter how or where I drive?</i> Nope, just drive as you normally would.<br><br><i>Do all of my segments get pulled in Firehose Mode?</i> No, we selectively pull a subset of your segments.<br><br><i>What's a good USB-C adapter?</i> Any fast phone or laptop charger should be fine.<br><br><i>Does it matter which software I run?</i> Yes, only upstream openpilot (and particular forks) are able to be used for training. + 為了達到最佳效果,請每週將您的裝置帶回室內,並連接至優質的 USB-C 充電器與 Wi-Fi。<br><br>訓練資料上傳模式在行駛時也能運作,但需連接至行動熱點或使用不限流量的 SIM 卡。<br><br><br><b>常見問題</b><br><br><i>我開車的方式或地點有影響嗎?</i> 不會,請像平常一樣駕駛即可。<br><br><i>Firehose 模式會上傳所有的駕駛片段嗎?</i>不會,我們會選擇性地上傳部分片段。<br><br><i>什麼是好的 USB-C 充電器?</i>任何快速手機或筆電充電器都應該適用。<br><br><i>我使用的軟體版本有影響嗎?</i>有的,只有官方 openpilot(以及特定的分支)可以用於訓練。 + + + <b>%n segment(s)</b> of your driving is in the training dataset so far. + + <b>目前已有 %n 段</b> 您的駕駛數據被納入訓練資料集。 + + + + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>INACTIVE</span>: connect to an unmetered network + <span stylesheet='font-size: 60px; font-weight: bold; color: #e74c3c;'>閒置中</span>:請連接到不按流量計費的網絡 + + + Firehose Mode + Firehose 模式 + + + + HudRenderer + + km/h + km/h + + + mph + mph + + + MAX + 最高 + + + + InputDialog + + Cancel + 取消 + + + Need at least %n character(s)! + + 需要至少 %n 個字元! + + + + + MultiOptionDialog + + Select + 選擇 + + + Cancel + 取消 + + + + Networking + + Advanced + 進階 + + + Enter password + 輸入密碼 + + + for "%1" + 給 "%1" + + + Wrong password + 密碼錯誤 + + + + OffroadAlert + + Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in %1 + 請立即連接網路檢查更新。如果不連接網路,openpilot 將在 %1 後便無法使用 + + + Connect to internet to check for updates. openpilot won't automatically start until it connects to internet to check for updates. + 請連接至網際網路以檢查更新。在連接至網際網路並完成更新檢查之前,openpilot 將不會自動啟動。 + + + Unable to download updates +%1 + 無法下載更新 +%1 + + + Taking camera snapshots. System won't start until finished. + 正在使用相機拍攝中。在完成之前,系統將無法啟動。 + + + An update to your device's operating system is downloading in the background. You will be prompted to update when it's ready to install. + 一個有關操作系統的更新正在後台下載中。當更新準備好安裝時,您將收到提示進行更新。 + + + openpilot was unable to identify your car. Your car is either unsupported or its ECUs are not recognized. Please submit a pull request to add the firmware versions to the proper vehicle. Need help? Join discord.comma.ai. + openpilot 無法識別您的車輛。您的車輛可能未被支援,或是其電控單元 (ECU) 未被識別。請提交一個 Pull Request 為您的車輛添加正確的韌體版本。需要幫助嗎?請加入 discord.comma.ai 。 + + + openpilot detected a change in the device's mounting position. Ensure the device is fully seated in the mount and the mount is firmly secured to the windshield. + openpilot 偵測到裝置的安裝位置發生變化。請確保裝置完全安裝在支架上,並確保支架牢固地固定在擋風玻璃上。 + + + Device temperature too high. System cooling down before starting. Current internal component temperature: %1 + 裝置溫度過高。系統正在冷卻中,等冷卻完畢後才會啟動。目前內部組件溫度:%1 + + + Device failed to register with the comma.ai backend. It will not connect or upload to comma.ai servers, and receives no support from comma.ai. If this is a device purchased at comma.ai/shop, open a ticket at https://comma.ai/support. + 裝置註冊 comma.ai 後端失敗。此裝置將無法連線或上傳資料至 comma.ai 伺服器,也無法獲得 comma.ai 的支援。若此裝置購自 comma.ai/shop,請至 https://comma.ai/support 建立支援請求。 + + + Acknowledge Excessive Actuation + 確認過度作動 + + + Snooze Update + 延後更新 + + + openpilot detected excessive %1 actuation on your last drive. Please contact support at https://comma.ai/support and share your device's Dongle ID for troubleshooting. + openpilot 在您上次的駕駛中,偵測到過度的 %1 作動。請至 https://comma.ai/support 聯絡客服,並提供您裝置的 Dongle ID 以進行故障排除。 + + + + OffroadHome + + UPDATE + 更新 + + + ALERTS + 提醒 + + + ALERT + 提醒 + + + + OnroadAlerts + + openpilot Unavailable + 無法使用 openpilot + + + TAKE CONTROL IMMEDIATELY + 立即接管 + + + Reboot Device + 請重新啟裝置 + + + Waiting to start + 等待開始 + + + System Unresponsive + 系統無回應 + + + + PairingPopup + + Pair your device to your comma account + 將裝置與您的 comma 帳號配對 + + + Go to https://connect.comma.ai on your phone + 用手機連至 https://connect.comma.ai + + + Click "add new device" and scan the QR code on the right + 點選 "add new device" 後掃描右邊的二維碼 + + + Bookmark connect.comma.ai to your home screen to use it like an app + 將 connect.comma.ai 加入您的主螢幕,以便像手機 App 一樣使用它 + + + Please connect to Wi-Fi to complete initial pairing + 請連接 Wi-Fi 以完成初始配對 + + + + ParamControl + + Cancel + 取消 + + + Enable + 啟用 + + + + PrimeAdWidget + + Upgrade Now + 馬上升級 + + + Become a comma prime member at connect.comma.ai + 成為 connect.comma.ai 的高級會員 + + + PRIME FEATURES: + 高級會員特點: + + + Remote access + 遠端存取 + + + 24/7 LTE connectivity + 24/7 LTE 連線 + + + 1 year of drive storage + 一年的行駛記錄儲存空間 + + + Remote snapshots + 遠端快照 + + + + PrimeUserWidget + + ✓ SUBSCRIBED + ✓ 已訂閱 + + + comma prime + comma 高級會員 + + + + QObject + + openpilot + openpilot + + + %n minute(s) ago + + %n 分鐘前 + + + + %n hour(s) ago + + %n 小時前 + + + + %n day(s) ago + + %n 天前 + + + + now + 現在 + + + + SettingsWindow + + × + × + + + Device + 裝置 + + + Network + 網路 + + + Toggles + 設定 + + + Software + 軟體 + + + Developer + 開發人員 + + + Firehose + Firehose + + + + SetupWidget + + Finish Setup + 完成設置 + + + Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer. + 將您的裝置與 comma connect (connect.comma.ai) 配對並領取您的 comma 高級會員優惠。 + + + Pair device + 配對裝置 + + + + Sidebar + + CONNECT + 雲端服務 + + + OFFLINE + 已離線 + + + ONLINE + 已連線 + + + ERROR + 錯誤 + + + TEMP + 溫度 + + + HIGH + 偏高 + + + GOOD + 正常 + + + OK + 一般 + + + VEHICLE + 車輛通訊 + + + NO + 未連線 + + + PANDA + 車輛通訊 + + + -- + -- + + + Wi-Fi + Wi-Fi + + + ETH + ETH + + + 2G + 2G + + + 3G + 3G + + + LTE + LTE + + + 5G + 5G + + + + SoftwarePanel + + Updates are only downloaded while the car is off. + 系統更新只會在熄火時下載。 + + + Current Version + 當前版本 + + + Download + 下載 + + + Install Update + 安裝更新 + + + INSTALL + 安裝 + + + Target Branch + 目標分支 + + + SELECT + 選取 + + + Select a branch + 選取一個分支 + + + UNINSTALL + 解除安裝 + + + Uninstall %1 + 解除安裝 %1 + + + Are you sure you want to uninstall? + 您確定您要解除安裝嗎? + + + CHECK + 檢查 + + + Uninstall + 解除安裝 + + + failed to check for update + 檢查更新失敗 + + + up to date, last checked %1 + 已經是最新版本,上次檢查時間為 %1 + + + DOWNLOAD + 下載 + + + update available + 有可用的更新 + + + never + 從未更新 + + + + SshControl + + SSH Keys + SSH 金鑰 + + + Warning: This grants SSH access to all public keys in your GitHub settings. Never enter a GitHub username other than your own. A comma employee will NEVER ask you to add their GitHub username. + 警告:這將授權給 GitHub 帳號中所有公鑰 SSH 訪問權限。切勿輸入非您自己的 GitHub 使用者名稱。comma 員工「永遠不會」要求您添加他們的 GitHub 使用者名稱。 + + + ADD + 新增 + + + Enter your GitHub username + 請輸入您 GitHub 的使用者名稱 + + + LOADING + 載入中 + + + REMOVE + 移除 + + + Username '%1' has no keys on GitHub + GitHub 用戶 '%1' 沒有設定任何金鑰 + + + Request timed out + 請求超時 + + + Username '%1' doesn't exist on GitHub + GitHub 用戶 '%1' 不存在 + + + + SshToggle + + Enable SSH + 啟用 SSH 服務 + + + + TermsPage + + Decline + 拒絕 + + + Agree + 接受 + + + Welcome to openpilot + 歡迎使用 openpilot + + + You must accept the Terms and Conditions to use openpilot. Read the latest terms at <span style='color: #465BEA;'>https://comma.ai/terms</span> before continuing. + 您必須接受《條款與條件》才能使用 openpilot。在繼續之前,請先閱讀最新條款:<span style='color: #465BEA;'>https://comma.ai/terms</span>。 + + + + TogglesPanel + + Enable openpilot + 啟用 openpilot + + + Enable Lane Departure Warnings + 啟用車道偏離警告 + + + Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h). + 車速在時速 50 公里 (31 英里) 以上且未打方向燈的情況下,如果偵測到車輛駛出目前車道線時,發出車道偏離警告。 + + + Use Metric System + 使用公制單位 + + + Display speed in km/h instead of mph. + 啟用後,速度單位顯示將從 mp/h 改為 km/h。 + + + Record and Upload Driver Camera + 記錄並上傳駕駛監控影像 + + + Upload data from the driver facing camera and help improve the driver monitoring algorithm. + 上傳駕駛監控的錄影來協助我們提升駕駛監控的準確率。 + + + Disengage on Accelerator Pedal + 油門取消控車 + + + When enabled, pressing the accelerator pedal will disengage openpilot. + 啟用後,踩踏油門將會取消 openpilot 控制。 + + + Experimental Mode + 實驗模式 + + + openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below: + openpilot 預設以 <b>輕鬆模式</b> 駕駛。 實驗模式啟用了尚未準備好進入輕鬆模式的 <b>alpha 級功能</b>。實驗功能如下: + + + Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected. + 讓駕駛模型來控制油門及煞車。openpilot將會模擬人類的駕駛行為,包含在看見紅燈及停止標示時停車。由於車速將由駕駛模型決定,因此您設定的時速將成為速度上限。本功能仍在早期實驗階段,請預期模型有犯錯的可能性。 + + + New Driving Visualization + 新的駕駛視覺介面 + + + Experimental mode is currently unavailable on this car since the car's stock ACC is used for longitudinal control. + 因車輛使用內建ACC系統,無法在本車輛上啟動實驗模式。 + + + openpilot longitudinal control may come in a future update. + openpilot 縱向控制可能會在未來的更新中提供。 + + + Aggressive + 積極 + + + Standard + 標準 + + + Relaxed + 舒適 + + + Driving Personality + 駕駛風格 + + + An alpha version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. + 在正式 (release) 版以外的分支上可以測試 openpilot 縱向控制的 Alpha 版本以及實驗模式。 + + + Enable the openpilot longitudinal control (alpha) toggle to allow Experimental mode. + 啟用 openpilot 縱向控制(alpha)切換以允許實驗模式。 + + + End-to-End Longitudinal Control + 端到端縱向控制 + + + Standard is recommended. In aggressive mode, openpilot will follow lead cars closer and be more aggressive with the gas and brake. In relaxed mode openpilot will stay further away from lead cars. On supported cars, you can cycle through these personalities with your steering wheel distance button. + 建議使用標準模式。在積極模式下,openpilot 會更接近前車並更積極地使用油門和剎車。在輕鬆模式下,openpilot 會與前車保持較遠距離。對於支援的汽車,您可以使用方向盤上的距離按鈕來切換這些駕駛風格。 + + + The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner. + 在低速時,駕駛可視化將切換至道路朝向的廣角攝影機,以更好地顯示某些彎道。在右上角還會顯示「實驗模式」的標誌。 + + + Always-On Driver Monitoring + 駕駛監控常開 + + + Enable driver monitoring even when openpilot is not engaged. + 即使在openpilot未激活時也啟用駕駛監控。 + + + Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. + openpilot 系統提供「主動式巡航」與「車道維持」等駕駛輔助功能。使用這些功能時,您必須隨時保持專注。 + + + Changing this setting will restart openpilot if the car is powered on. + 若車輛電源為開啟狀態,變更此設定將會重新啟動 openpilot。 + + + Record and Upload Microphone Audio + 錄製並上傳麥克風音訊 + + + Record and store microphone audio while driving. The audio will be included in the dashcam video in comma connect. + 在駕駛時錄製並儲存麥克風音訊。此音訊將會收錄在 comma connect 的行車記錄器影片中。 + + + + WiFiPromptWidget + + Open + 開啟 + + + Maximize your training data uploads to improve openpilot's driving models. + 最大化您的訓練數據上傳,以改善 openpilot 的駕駛模型。 + + + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose Mode <span style='font-family: Noto Color Emoji;'>🔥</span> + <span style='font-family: "Noto Color Emoji";'>🔥</span> Firehose 模式 <span style='font-family: Noto Color Emoji;'>🔥</span> + + + + WifiUI + + Scanning for networks... + 掃描無線網路中... + + + CONNECTING... + 連線中... + + + FORGET + 清除 + + + Forget Wi-Fi Network "%1"? + 清除 Wi-Fi 網路 "%1"? + + + Forget + 清除 + + + diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc new file mode 100644 index 0000000000..9ec61b9b81 --- /dev/null +++ b/selfdrive/ui/ui.cc @@ -0,0 +1,203 @@ +#include "selfdrive/ui/ui.h" + +#include +#include + +#include + +#include "common/transformations/orientation.hpp" +#include "common/swaglog.h" +#include "common/util.h" +#include "common/watchdog.h" +#include "system/hardware/hw.h" + +#define BACKLIGHT_DT 0.05 +#define BACKLIGHT_TS 10.00 + +static void update_sockets(UIState *s) { + s->sm->update(0); +} + +static void update_state(UIState *s) { + SubMaster &sm = *(s->sm); + UIScene &scene = s->scene; + + if (sm.updated("liveCalibration")) { + auto list2rot = [](const capnp::List::Reader &rpy_list) ->Eigen::Matrix3f { + return euler2rot({rpy_list[0], rpy_list[1], rpy_list[2]}).cast(); + }; + + auto live_calib = sm["liveCalibration"].getLiveCalibration(); + if (live_calib.getCalStatus() == cereal::LiveCalibrationData::Status::CALIBRATED) { + auto device_from_calib = list2rot(live_calib.getRpyCalib()); + auto wide_from_device = list2rot(live_calib.getWideFromDeviceEuler()); + s->scene.view_from_calib = VIEW_FROM_DEVICE * device_from_calib; + s->scene.view_from_wide_calib = VIEW_FROM_DEVICE * wide_from_device * device_from_calib; + } else { + s->scene.view_from_calib = s->scene.view_from_wide_calib = VIEW_FROM_DEVICE; + } + } + if (sm.updated("pandaStates")) { + auto pandaStates = sm["pandaStates"].getPandaStates(); + if (pandaStates.size() > 0) { + scene.pandaType = pandaStates[0].getPandaType(); + + if (scene.pandaType != cereal::PandaState::PandaType::UNKNOWN) { + scene.ignition = false; + for (const auto& pandaState : pandaStates) { + scene.ignition |= pandaState.getIgnitionLine() || pandaState.getIgnitionCan(); + } + } + } + } else if ((s->sm->frame - s->sm->rcv_frame("pandaStates")) > 5*UI_FREQ) { + scene.pandaType = cereal::PandaState::PandaType::UNKNOWN; + } + if (sm.updated("wideRoadCameraState")) { + auto cam_state = sm["wideRoadCameraState"].getWideRoadCameraState(); + scene.light_sensor = std::max(100.0f - cam_state.getExposureValPercent(), 0.0f); + } else if (!sm.allAliveAndValid({"wideRoadCameraState"})) { + scene.light_sensor = -1; + } + scene.started = sm["deviceState"].getDeviceState().getStarted() && scene.ignition; + + auto params = Params(); + scene.recording_audio = params.getBool("RecordAudio") && scene.started; +} + +void ui_update_params(UIState *s) { + auto params = Params(); + s->scene.is_metric = params.getBool("IsMetric"); +} + +void UIState::updateStatus() { + if (scene.started && sm->updated("selfdriveState")) { + auto ss = (*sm)["selfdriveState"].getSelfdriveState(); + auto state = ss.getState(); + if (state == cereal::SelfdriveState::OpenpilotState::PRE_ENABLED || state == cereal::SelfdriveState::OpenpilotState::OVERRIDING) { + status = STATUS_OVERRIDE; + } else { + status = ss.getEnabled() ? STATUS_ENGAGED : STATUS_DISENGAGED; + } + } + + if (engaged() != engaged_prev) { + engaged_prev = engaged(); + emit engagedChanged(engaged()); + } + + // Handle onroad/offroad transition + if (scene.started != started_prev || sm->frame == 1) { + if (scene.started) { + status = STATUS_DISENGAGED; + scene.started_frame = sm->frame; + } + started_prev = scene.started; + emit offroadTransition(!scene.started); + } +} + +UIState::UIState(QObject *parent) : QObject(parent) { + sm = std::make_unique(std::vector{ + "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", + "pandaStates", "carParams", "driverMonitoringState", "carState", "driverStateV2", + "wideRoadCameraState", "managerState", "selfdriveState", "longitudinalPlan", + }); + prime_state = new PrimeState(this); + language = QString::fromStdString(Params().get("LanguageSetting")); + + // update timer + timer = new QTimer(this); + QObject::connect(timer, &QTimer::timeout, this, &UIState::update); + timer->start(1000 / UI_FREQ); +} + +void UIState::update() { + update_sockets(this); + update_state(this); + updateStatus(); + + if (sm->frame % UI_FREQ == 0) { + watchdog_kick(nanos_since_boot()); + } + emit uiUpdate(*this); +} + +Device::Device(QObject *parent) : brightness_filter(BACKLIGHT_OFFROAD, BACKLIGHT_TS, BACKLIGHT_DT), QObject(parent) { + setAwake(true); + resetInteractiveTimeout(); + + QObject::connect(uiState(), &UIState::uiUpdate, this, &Device::update); +} + +void Device::update(const UIState &s) { + updateBrightness(s); + updateWakefulness(s); +} + +void Device::setAwake(bool on) { + if (on != awake) { + awake = on; + Hardware::set_display_power(awake); + LOGD("setting display power %d", awake); + emit displayPowerChanged(awake); + } +} + +void Device::resetInteractiveTimeout(int timeout) { + if (timeout == -1) { + timeout = (ignition_on ? 10 : 30); + } + interactive_timeout = timeout * UI_FREQ; +} + +void Device::updateBrightness(const UIState &s) { + float clipped_brightness = offroad_brightness; + if (s.scene.started && s.scene.light_sensor >= 0) { + clipped_brightness = s.scene.light_sensor; + + // CIE 1931 - https://www.photonstophotos.net/GeneralTopics/Exposure/Psychometric_Lightness_and_Gamma.htm + if (clipped_brightness <= 8) { + clipped_brightness = (clipped_brightness / 903.3); + } else { + clipped_brightness = std::pow((clipped_brightness + 16.0) / 116.0, 3.0); + } + + // Scale back to 10% to 100% + clipped_brightness = std::clamp(100.0f * clipped_brightness, 10.0f, 100.0f); + } + + int brightness = brightness_filter.update(clipped_brightness); + if (!awake) { + brightness = 0; + } + + if (brightness != last_brightness) { + if (!brightness_future.isRunning()) { + brightness_future = QtConcurrent::run(Hardware::set_brightness, brightness); + last_brightness = brightness; + } + } +} + +void Device::updateWakefulness(const UIState &s) { + bool ignition_just_turned_off = !s.scene.ignition && ignition_on; + ignition_on = s.scene.ignition; + + if (ignition_just_turned_off) { + resetInteractiveTimeout(); + } else if (interactive_timeout > 0 && --interactive_timeout == 0) { + emit interactiveTimeout(); + } + + setAwake(s.scene.ignition || interactive_timeout > 0); +} + +UIState *uiState() { + static UIState ui_state; + return &ui_state; +} + +Device *device() { + static Device _device; + return &_device; +} diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h new file mode 100644 index 0000000000..b3c482aafe --- /dev/null +++ b/selfdrive/ui/ui.h @@ -0,0 +1,132 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + +#include "cereal/messaging/messaging.h" +#include "common/mat.h" +#include "common/params.h" +#include "common/util.h" +#include "system/hardware/hw.h" +#include "selfdrive/ui/qt/prime_state.h" + +const int UI_BORDER_SIZE = 30; +const int UI_HEADER_HEIGHT = 420; + +const int UI_FREQ = 20; // Hz +const int BACKLIGHT_OFFROAD = 50; + +const Eigen::Matrix3f VIEW_FROM_DEVICE = (Eigen::Matrix3f() << + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0).finished(); + +const Eigen::Matrix3f FCAM_INTRINSIC_MATRIX = (Eigen::Matrix3f() << + 2648.0, 0.0, 1928.0 / 2, + 0.0, 2648.0, 1208.0 / 2, + 0.0, 0.0, 1.0).finished(); + +// tici ecam focal probably wrong? magnification is not consistent across frame +// Need to retrain model before this can be changed +const Eigen::Matrix3f ECAM_INTRINSIC_MATRIX = (Eigen::Matrix3f() << + 567.0, 0.0, 1928.0 / 2, + 0.0, 567.0, 1208.0 / 2, + 0.0, 0.0, 1.0).finished(); + +typedef enum UIStatus { + STATUS_DISENGAGED, + STATUS_OVERRIDE, + STATUS_ENGAGED, +} UIStatus; + +const QColor bg_colors [] = { + [STATUS_DISENGAGED] = QColor(0x17, 0x33, 0x49, 0xc8), + [STATUS_OVERRIDE] = QColor(0x91, 0x9b, 0x95, 0xf1), + [STATUS_ENGAGED] = QColor(0x17, 0x86, 0x44, 0xf1), +}; + +typedef struct UIScene { + Eigen::Matrix3f view_from_calib = VIEW_FROM_DEVICE; + Eigen::Matrix3f view_from_wide_calib = VIEW_FROM_DEVICE; + cereal::PandaState::PandaType pandaType; + + cereal::LongitudinalPersonality personality; + + float light_sensor = -1; + bool started, ignition, is_metric, recording_audio; + uint64_t started_frame; +} UIScene; + +class UIState : public QObject { + Q_OBJECT + +public: + UIState(QObject* parent = 0); + void updateStatus(); + inline bool engaged() const { + return scene.started && (*sm)["selfdriveState"].getSelfdriveState().getEnabled(); + } + + std::unique_ptr sm; + UIStatus status; + UIScene scene = {}; + QString language; + PrimeState *prime_state; + +signals: + void uiUpdate(const UIState &s); + void offroadTransition(bool offroad); + void engagedChanged(bool engaged); + +private slots: + void update(); + +private: + QTimer *timer; + bool started_prev = false; + bool engaged_prev = false; +}; + +UIState *uiState(); + +// device management class +class Device : public QObject { + Q_OBJECT + +public: + Device(QObject *parent = 0); + bool isAwake() { return awake; } + void setOffroadBrightness(int brightness) { + offroad_brightness = std::clamp(brightness, 0, 100); + } + +private: + bool awake = false; + int interactive_timeout = 0; + bool ignition_on = false; + + int offroad_brightness = BACKLIGHT_OFFROAD; + int last_brightness = 0; + FirstOrderFilter brightness_filter; + QFuture brightness_future; + + void updateBrightness(const UIState &s); + void updateWakefulness(const UIState &s); + void setAwake(bool on); + +signals: + void displayPowerChanged(bool on); + void interactiveTimeout(); + +public slots: + void resetInteractiveTimeout(int timeout = -1); + void update(const UIState &s); +}; + +Device *device(); +void ui_update_params(UIState *s); diff --git a/selfdrive/ui/ui.py b/selfdrive/ui/ui.py new file mode 100755 index 0000000000..5fb6fd5737 --- /dev/null +++ b/selfdrive/ui/ui.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +import pyray as rl +from openpilot.common.watchdog import kick_watchdog +from openpilot.system.ui.lib.application import gui_app +from openpilot.selfdrive.ui.layouts.main import MainLayout +from openpilot.selfdrive.ui.ui_state import ui_state + + +def main(): + # TODO: https://github.com/commaai/agnos-builder/pull/490 + # os.nice(-20) + + gui_app.init_window("UI") + main_layout = MainLayout() + main_layout.set_rect(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + for showing_dialog in gui_app.render(): + ui_state.update() + + kick_watchdog() + + if not showing_dialog: + main_layout.render() + + +if __name__ == "__main__": + main() diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py new file mode 100644 index 0000000000..9c45519b4b --- /dev/null +++ b/selfdrive/ui/ui_state.py @@ -0,0 +1,229 @@ +import pyray as rl +import numpy as np +import time +import threading +from collections.abc import Callable +from enum import Enum +from cereal import messaging, log +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.params import Params, UnknownKeyName +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.ui.lib.prime_state import PrimeState +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.hardware import HARDWARE + +UI_BORDER_SIZE = 30 +BACKLIGHT_OFFROAD = 50 + + +class UIStatus(Enum): + DISENGAGED = "disengaged" + ENGAGED = "engaged" + OVERRIDE = "override" + + +class UIState: + _instance: 'UIState | None' = None + + def __new__(cls): + if cls._instance is None: + cls._instance = super().__new__(cls) + cls._instance._initialize() + return cls._instance + + def _initialize(self): + self.params = Params() + self.sm = messaging.SubMaster( + [ + "modelV2", + "controlsState", + "liveCalibration", + "radarState", + "deviceState", + "pandaStates", + "carParams", + "driverMonitoringState", + "carState", + "driverStateV2", + "roadCameraState", + "wideRoadCameraState", + "managerState", + "selfdriveState", + "longitudinalPlan", + "rawAudioData", + ] + ) + + self.prime_state = PrimeState() + + # UI Status tracking + self.status: UIStatus = UIStatus.DISENGAGED + self.started_frame: int = 0 + self.started_time: float = 0.0 + self._engaged_prev: bool = False + self._started_prev: bool = False + + # Core state variables + self.is_metric: bool = self.params.get_bool("IsMetric") + self.started: bool = False + self.ignition: bool = False + self.panda_type: log.PandaState.PandaType = log.PandaState.PandaType.unknown + self.personality: log.LongitudinalPersonality = log.LongitudinalPersonality.standard + self.light_sensor: float = -1.0 + + self._update_params() + + @property + def engaged(self) -> bool: + return self.started and self.sm["selfdriveState"].enabled + + def is_onroad(self) -> bool: + return self.started + + def is_offroad(self) -> bool: + return not self.started + + def update(self) -> None: + self.sm.update(0) + self._update_state() + self._update_status() + device.update() + + def _update_state(self) -> None: + # Handle panda states updates + if self.sm.updated["pandaStates"]: + panda_states = self.sm["pandaStates"] + + if len(panda_states) > 0: + # Get panda type from first panda + self.panda_type = panda_states[0].pandaType + # Check ignition status across all pandas + if self.panda_type != log.PandaState.PandaType.unknown: + self.ignition = any(state.ignitionLine or state.ignitionCan for state in panda_states) + elif self.sm.frame - self.sm.recv_frame["pandaStates"] > 5 * rl.get_fps(): + self.panda_type = log.PandaState.PandaType.unknown + + # Handle wide road camera state updates + if self.sm.updated["wideRoadCameraState"]: + cam_state = self.sm["wideRoadCameraState"] + self.light_sensor = max(100.0 - cam_state.exposureValPercent, 0.0) + elif not self.sm.alive["wideRoadCameraState"] or not self.sm.valid["wideRoadCameraState"]: + self.light_sensor = -1 + + # Update started state + self.started = self.sm["deviceState"].started and self.ignition + + def _update_status(self) -> None: + if self.started and self.sm.updated["selfdriveState"]: + ss = self.sm["selfdriveState"] + state = ss.state + + if state in (log.SelfdriveState.OpenpilotState.preEnabled, log.SelfdriveState.OpenpilotState.overriding): + self.status = UIStatus.OVERRIDE + else: + self.status = UIStatus.ENGAGED if ss.enabled else UIStatus.DISENGAGED + + # Check for engagement state changes + if self.engaged != self._engaged_prev: + self._engaged_prev = self.engaged + + # Handle onroad/offroad transition + if self.started != self._started_prev or self.sm.frame == 1: + if self.started: + self.status = UIStatus.DISENGAGED + self.started_frame = self.sm.frame + self.started_time = time.monotonic() + + self._started_prev = self.started + + def _update_params(self) -> None: + try: + self.is_metric = self.params.get_bool("IsMetric") + except UnknownKeyName: + self.is_metric = False + + +class Device: + def __init__(self): + self._ignition = False + self._interaction_time: float = -1 + self._interactive_timeout_callbacks: list[Callable] = [] + self._prev_timed_out = False + self._awake = False + + self._offroad_brightness: int = BACKLIGHT_OFFROAD + self._last_brightness: int = 0 + self._brightness_filter = FirstOrderFilter(BACKLIGHT_OFFROAD, 10.00, 1 / gui_app.target_fps) + self._brightness_thread: threading.Thread | None = None + + def reset_interactive_timeout(self, timeout: int = -1) -> None: + if timeout == -1: + timeout = 10 if ui_state.ignition else 30 + self._interaction_time = time.monotonic() + timeout + + def add_interactive_timeout_callback(self, callback: Callable): + self._interactive_timeout_callbacks.append(callback) + + def update(self): + # do initial reset + if self._interaction_time <= 0: + self.reset_interactive_timeout() + + self._update_brightness() + self._update_wakefulness() + + def set_offroad_brightness(self, brightness: int): + # TODO: not yet used, should be used in prime widget for QR code, etc. + self._offroad_brightness = min(max(brightness, 0), 100) + + def _update_brightness(self): + clipped_brightness = self._offroad_brightness + + if ui_state.started and ui_state.light_sensor >= 0: + clipped_brightness = ui_state.light_sensor + + # CIE 1931 - https://www.photonstophotos.net/GeneralTopics/Exposure/Psychometric_Lightness_and_Gamma.htm + if clipped_brightness <= 8: + clipped_brightness = clipped_brightness / 903.3 + else: + clipped_brightness = ((clipped_brightness + 16.0) / 116.0) ** 3.0 + + clipped_brightness = float(np.clip(100 * clipped_brightness, 10, 100)) + + brightness = round(self._brightness_filter.update(clipped_brightness)) + if not self._awake: + brightness = 0 + + if brightness != self._last_brightness: + if self._brightness_thread is None or not self._brightness_thread.is_alive(): + cloudlog.debug(f"setting display brightness {brightness}") + self._brightness_thread = threading.Thread(target=HARDWARE.set_screen_brightness, args=(brightness,)) + self._brightness_thread.start() + self._last_brightness = brightness + + def _update_wakefulness(self): + # Handle interactive timeout + ignition_just_turned_off = not ui_state.ignition and self._ignition + self._ignition = ui_state.ignition + + if ignition_just_turned_off or any(ev.left_down for ev in gui_app.mouse_events): + self.reset_interactive_timeout() + + interaction_timeout = time.monotonic() > self._interaction_time + if interaction_timeout and not self._prev_timed_out: + for callback in self._interactive_timeout_callbacks: + callback() + self._prev_timed_out = interaction_timeout + + self._set_awake(ui_state.ignition or not interaction_timeout) + + def _set_awake(self, on: bool): + if on != self._awake: + self._awake = on + cloudlog.debug(f"setting display power {int(on)}") + HARDWARE.set_display_power(on) + + +# Global instance +ui_state = UIState() +device = Device() diff --git a/selfdrive/ui/update_translations.py b/selfdrive/ui/update_translations.py new file mode 100755 index 0000000000..65880bdad9 --- /dev/null +++ b/selfdrive/ui/update_translations.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import argparse +import json +import os + +from openpilot.common.basedir import BASEDIR + +UI_DIR = os.path.join(BASEDIR, "selfdrive", "ui") +TRANSLATIONS_DIR = os.path.join(UI_DIR, "translations") +LANGUAGES_FILE = os.path.join(TRANSLATIONS_DIR, "languages.json") +TRANSLATIONS_INCLUDE_FILE = os.path.join(TRANSLATIONS_DIR, "alerts_generated.h") +PLURAL_ONLY = ["main_en"] # base language, only create entries for strings with plural forms + + +def generate_translations_include(): + # offroad alerts + # TODO translate events from openpilot.selfdrive/controls/lib/events.py + content = "// THIS IS AN AUTOGENERATED FILE, PLEASE EDIT alerts_offroad.json\n" + with open(os.path.join(BASEDIR, "selfdrive/selfdrived/alerts_offroad.json")) as f: + for alert in json.load(f).values(): + content += f'QT_TRANSLATE_NOOP("OffroadAlert", R"({alert["text"]})");\n' + + with open(TRANSLATIONS_INCLUDE_FILE, "w") as f: + f.write(content) + + +def update_translations(vanish: bool = False, translation_files: None | list[str] = None, translations_dir: str = TRANSLATIONS_DIR): + if translation_files is None: + with open(LANGUAGES_FILE) as f: + translation_files = json.load(f).values() + + for file in translation_files: + tr_file = os.path.join(translations_dir, f"{file}.ts") + args = f"lupdate -locations none -recursive {UI_DIR} -ts {tr_file} -I {BASEDIR}" + if vanish: + args += " -no-obsolete" + if file in PLURAL_ONLY: + args += " -pluralonly" + ret = os.system(args) + assert ret == 0 + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Update translation files for UI", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--vanish", action="store_true", help="Remove translations with source text no longer found") + args = parser.parse_args() + + generate_translations_include() + update_translations(args.vanish) diff --git a/selfdrive/ui/watch3.py b/selfdrive/ui/watch3.py new file mode 100755 index 0000000000..bb64cdc4d5 --- /dev/null +++ b/selfdrive/ui/watch3.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +import pyray as rl + +from msgq.visionipc import VisionStreamType +from openpilot.system.ui.lib.application import gui_app +from openpilot.selfdrive.ui.onroad.cameraview import CameraView + + +if __name__ == "__main__": + gui_app.init_window("watch3") + road = CameraView("camerad", VisionStreamType.VISION_STREAM_ROAD) + driver = CameraView("camerad", VisionStreamType.VISION_STREAM_DRIVER) + wide = CameraView("camerad", VisionStreamType.VISION_STREAM_WIDE_ROAD) + for _ in gui_app.render(): + road.render(rl.Rectangle(gui_app.width // 4, 0, gui_app.width // 2, gui_app.height // 2)) + driver.render(rl.Rectangle(0, gui_app.height // 2, gui_app.width // 2, gui_app.height // 2)) + wide.render(rl.Rectangle(gui_app.width // 2, gui_app.height // 2, gui_app.width // 2, gui_app.height // 2)) diff --git a/selfdrive/ui/widgets/__init__.py b/selfdrive/ui/widgets/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selfdrive/ui/widgets/exp_mode_button.py b/selfdrive/ui/widgets/exp_mode_button.py new file mode 100644 index 0000000000..6fe7b6843c --- /dev/null +++ b/selfdrive/ui/widgets/exp_mode_button.py @@ -0,0 +1,66 @@ +import pyray as rl +from openpilot.common.params import Params +from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE +from openpilot.system.ui.widgets import Widget + + +class ExperimentalModeButton(Widget): + def __init__(self): + super().__init__() + + self.img_width = 80 + self.horizontal_padding = 30 + self.button_height = 125 + + self.params = Params() + self.experimental_mode = self.params.get_bool("ExperimentalMode") + + self.chill_pixmap = gui_app.texture("icons/couch.png", self.img_width, self.img_width) + self.experimental_pixmap = gui_app.texture("icons/experimental_grey.png", self.img_width, self.img_width) + + def _get_gradient_colors(self): + alpha = 0xCC if self.is_pressed else 0xFF + + if self.experimental_mode: + return rl.Color(255, 155, 63, alpha), rl.Color(219, 56, 34, alpha) + else: + return rl.Color(20, 255, 171, alpha), rl.Color(35, 149, 255, alpha) + + def _draw_gradient_background(self, rect): + start_color, end_color = self._get_gradient_colors() + rl.draw_rectangle_gradient_h(int(rect.x), int(rect.y), int(rect.width), int(rect.height), + start_color, end_color) + + def _handle_mouse_release(self, mouse_pos): + self.experimental_mode = not self.experimental_mode + # TODO: Opening settings for ExperimentalMode + self.params.put_bool("ExperimentalMode", self.experimental_mode) + + def _render(self, rect): + rl.draw_rectangle_rounded(rect, 0.08, 20, rl.WHITE) + + rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height)) + self._draw_gradient_background(rect) + rl.end_scissor_mode() + + # Draw vertical separator line + line_x = rect.x + rect.width - self.img_width - (2 * self.horizontal_padding) + separator_color = rl.Color(0, 0, 0, 77) # 0x4d = 77 + rl.draw_line_ex(rl.Vector2(line_x, rect.y), rl.Vector2(line_x, rect.y + rect.height), 3, separator_color) + + # Draw text label (left aligned) + text = "EXPERIMENTAL MODE ON" if self.experimental_mode else "CHILL MODE ON" + text_x = rect.x + self.horizontal_padding + text_y = rect.y + rect.height / 2 - 45 * FONT_SCALE // 2 # Center vertically + + rl.draw_text_ex(gui_app.font(FontWeight.NORMAL), text, rl.Vector2(int(text_x), int(text_y)), 45, 0, rl.BLACK) + + # Draw icon (right aligned) + icon_x = rect.x + rect.width - self.horizontal_padding - self.img_width + icon_y = rect.y + (rect.height - self.img_width) / 2 + icon_rect = rl.Rectangle(icon_x, icon_y, self.img_width, self.img_width) + + # Draw current mode icon + current_icon = self.experimental_pixmap if self.experimental_mode else self.chill_pixmap + source_rect = rl.Rectangle(0, 0, current_icon.width, current_icon.height) + rl.draw_texture_pro(current_icon, source_rect, icon_rect, rl.Vector2(0, 0), 0, rl.WHITE) diff --git a/selfdrive/ui/widgets/offroad_alerts.py b/selfdrive/ui/widgets/offroad_alerts.py new file mode 100644 index 0000000000..1045971636 --- /dev/null +++ b/selfdrive/ui/widgets/offroad_alerts.py @@ -0,0 +1,339 @@ +import pyray as rl +from enum import IntEnum +from abc import ABC, abstractmethod +from collections.abc import Callable +from dataclasses import dataclass +from openpilot.common.params import Params +from openpilot.system.hardware import HARDWARE +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.html_render import HtmlRenderer +from openpilot.selfdrive.selfdrived.alertmanager import OFFROAD_ALERTS + + +NO_RELEASE_NOTES = "

    No release notes available.

    " + + +class AlertColors: + HIGH_SEVERITY = rl.Color(226, 44, 44, 255) + LOW_SEVERITY = rl.Color(41, 41, 41, 255) + BACKGROUND = rl.Color(57, 57, 57, 255) + BUTTON = rl.WHITE + BUTTON_PRESSED = rl.Color(200, 200, 200, 255) + BUTTON_TEXT = rl.BLACK + SNOOZE_BG = rl.Color(79, 79, 79, 255) + SNOOZE_BG_PRESSED = rl.Color(100, 100, 100, 255) + TEXT = rl.WHITE + + +class AlertConstants: + MIN_BUTTON_WIDTH = 400 + BUTTON_HEIGHT = 125 + MARGIN = 50 + SPACING = 30 + FONT_SIZE = 48 + BORDER_RADIUS = 30 * 2 # matches Qt's 30px + ALERT_HEIGHT = 120 + ALERT_SPACING = 10 + ALERT_INSET = 60 + + +@dataclass +class AlertData: + key: str + text: str + severity: int + visible: bool = False + + +class ButtonStyle(IntEnum): + LIGHT = 0 + DARK = 1 + + +class ActionButton(Widget): + def __init__(self, text: str, style: ButtonStyle = ButtonStyle.LIGHT, + min_width: int = AlertConstants.MIN_BUTTON_WIDTH): + super().__init__() + self._style = style + self._min_width = min_width + self._font = gui_app.font(FontWeight.MEDIUM) + self.set_text(text) + + def set_text(self, text: str): + self._text = text + self._text_width = measure_text_cached(gui_app.font(FontWeight.MEDIUM), self._text, AlertConstants.FONT_SIZE).x + self._rect.width = max(self._text_width + 60 * 2, self._min_width) + self._rect.height = AlertConstants.BUTTON_HEIGHT + + def _render(self, _): + roundness = AlertConstants.BORDER_RADIUS / self._rect.height + bg_color = AlertColors.BUTTON if self._style == ButtonStyle.LIGHT else AlertColors.SNOOZE_BG + if self.is_pressed: + bg_color = AlertColors.BUTTON_PRESSED if self._style == ButtonStyle.LIGHT else AlertColors.SNOOZE_BG_PRESSED + + rl.draw_rectangle_rounded(self._rect, roundness, 10, bg_color) + + # center text + color = rl.WHITE if self._style == ButtonStyle.DARK else rl.BLACK + text_x = int(self._rect.x + (self._rect.width - self._text_width) // 2) + text_y = int(self._rect.y + (self._rect.height - AlertConstants.FONT_SIZE) // 2) + rl.draw_text_ex(self._font, self._text, rl.Vector2(text_x, text_y), AlertConstants.FONT_SIZE, 0, color) + + +class AbstractAlert(Widget, ABC): + def __init__(self, has_reboot_btn: bool = False): + super().__init__() + self.params = Params() + self.has_reboot_btn = has_reboot_btn + self.dismiss_callback: Callable | None = None + + def snooze_callback(): + self.params.put_bool("SnoozeUpdate", True) + if self.dismiss_callback: + self.dismiss_callback() + + def excessive_actuation_callback(): + self.params.remove("Offroad_ExcessiveActuation") + if self.dismiss_callback: + self.dismiss_callback() + + self.dismiss_btn = ActionButton("Close") + + self.snooze_btn = ActionButton("Snooze Update", style=ButtonStyle.DARK) + self.snooze_btn.set_click_callback(snooze_callback) + + self.excessive_actuation_btn = ActionButton("Acknowledge Excessive Actuation", style=ButtonStyle.DARK, min_width=800) + self.excessive_actuation_btn.set_click_callback(excessive_actuation_callback) + + self.reboot_btn = ActionButton("Reboot and Update", min_width=600) + self.reboot_btn.set_click_callback(lambda: HARDWARE.reboot()) + + # TODO: just use a Scroller? + self.content_rect = rl.Rectangle(0, 0, 0, 0) + self.scroll_panel_rect = rl.Rectangle(0, 0, 0, 0) + self.scroll_panel = GuiScrollPanel() + + def set_dismiss_callback(self, callback: Callable): + self.dismiss_callback = callback + self.dismiss_btn.set_click_callback(self.dismiss_callback) + + @abstractmethod + def refresh(self) -> bool: + pass + + @abstractmethod + def get_content_height(self) -> float: + pass + + def _render(self, rect: rl.Rectangle): + rl.draw_rectangle_rounded(rect, AlertConstants.BORDER_RADIUS / rect.height, 10, AlertColors.BACKGROUND) + + footer_height = AlertConstants.BUTTON_HEIGHT + AlertConstants.SPACING + content_height = rect.height - 2 * AlertConstants.MARGIN - footer_height + + self.content_rect = rl.Rectangle( + rect.x + AlertConstants.MARGIN, + rect.y + AlertConstants.MARGIN, + rect.width - 2 * AlertConstants.MARGIN, + content_height, + ) + self.scroll_panel_rect = rl.Rectangle( + self.content_rect.x, self.content_rect.y, self.content_rect.width, self.content_rect.height + ) + + self._render_scrollable_content() + self._render_footer(rect) + + def _render_scrollable_content(self): + content_total_height = self.get_content_height() + content_bounds = rl.Rectangle(0, 0, self.scroll_panel_rect.width, content_total_height) + scroll_offset = self.scroll_panel.update(self.scroll_panel_rect, content_bounds) + + rl.begin_scissor_mode( + int(self.scroll_panel_rect.x), + int(self.scroll_panel_rect.y), + int(self.scroll_panel_rect.width), + int(self.scroll_panel_rect.height), + ) + + content_rect_with_scroll = rl.Rectangle( + self.scroll_panel_rect.x, + self.scroll_panel_rect.y + scroll_offset, + self.scroll_panel_rect.width, + content_total_height, + ) + + self._render_content(content_rect_with_scroll) + rl.end_scissor_mode() + + @abstractmethod + def _render_content(self, content_rect: rl.Rectangle): + pass + + def _render_footer(self, rect: rl.Rectangle): + footer_y = rect.y + rect.height - AlertConstants.MARGIN - AlertConstants.BUTTON_HEIGHT + + dismiss_x = rect.x + AlertConstants.MARGIN + self.dismiss_btn.set_position(dismiss_x, footer_y) + self.dismiss_btn.render() + + if self.has_reboot_btn: + reboot_x = rect.x + rect.width - AlertConstants.MARGIN - self.reboot_btn.rect.width + self.reboot_btn.set_position(reboot_x, footer_y) + self.reboot_btn.render() + + elif self.excessive_actuation_btn.is_visible: + actuation_x = rect.x + rect.width - AlertConstants.MARGIN - self.excessive_actuation_btn.rect.width + self.excessive_actuation_btn.set_position(actuation_x, footer_y) + self.excessive_actuation_btn.render() + + elif self.snooze_btn.is_visible: + snooze_x = rect.x + rect.width - AlertConstants.MARGIN - self.snooze_btn.rect.width + self.snooze_btn.set_position(snooze_x, footer_y) + self.snooze_btn.render() + + +class OffroadAlert(AbstractAlert): + def __init__(self): + super().__init__(has_reboot_btn=False) + self.sorted_alerts: list[AlertData] = [] + + def refresh(self): + if not self.sorted_alerts: + self._build_alerts() + + active_count = 0 + connectivity_needed = False + excessive_actuation = False + + for alert_data in self.sorted_alerts: + text = "" + alert_json = self.params.get(alert_data.key) + + if alert_json: + text = alert_json.get("text", "").replace("%1", alert_json.get("extra", "")) + + alert_data.text = text + alert_data.visible = bool(text) + + if alert_data.visible: + active_count += 1 + + if alert_data.key == "Offroad_ConnectivityNeeded" and alert_data.visible: + connectivity_needed = True + + if alert_data.key == "Offroad_ExcessiveActuation" and alert_data.visible: + excessive_actuation = True + + self.excessive_actuation_btn.set_visible(excessive_actuation) + self.snooze_btn.set_visible(connectivity_needed and not excessive_actuation) + return active_count + + def get_content_height(self) -> float: + if not self.sorted_alerts: + return 0 + + total_height = 20 + font = gui_app.font(FontWeight.NORMAL) + + for alert_data in self.sorted_alerts: + if not alert_data.visible: + continue + + text_width = int(self.content_rect.width - (AlertConstants.ALERT_INSET * 2)) + wrapped_lines = wrap_text(font, alert_data.text, AlertConstants.FONT_SIZE, text_width) + line_count = len(wrapped_lines) + text_height = line_count * (AlertConstants.FONT_SIZE + 5) + alert_item_height = max(text_height + (AlertConstants.ALERT_INSET * 2), AlertConstants.ALERT_HEIGHT) + total_height += alert_item_height + AlertConstants.ALERT_SPACING + + if total_height > 20: + total_height = total_height - AlertConstants.ALERT_SPACING + 20 + + return total_height + + def _build_alerts(self): + self.sorted_alerts = [] + for key, config in sorted(OFFROAD_ALERTS.items(), key=lambda x: x[1].get("severity", 0), reverse=True): + severity = config.get("severity", 0) + alert_data = AlertData(key=key, text="", severity=severity) + self.sorted_alerts.append(alert_data) + + def _render_content(self, content_rect: rl.Rectangle): + y_offset = AlertConstants.ALERT_SPACING + font = gui_app.font(FontWeight.NORMAL) + + for alert_data in self.sorted_alerts: + if not alert_data.visible: + continue + + bg_color = AlertColors.HIGH_SEVERITY if alert_data.severity > 0 else AlertColors.LOW_SEVERITY + text_width = int(content_rect.width - (AlertConstants.ALERT_INSET * 2)) + wrapped_lines = wrap_text(font, alert_data.text, AlertConstants.FONT_SIZE, text_width) + line_count = len(wrapped_lines) + text_height = line_count * (AlertConstants.FONT_SIZE + 5) + alert_item_height = max(text_height + (AlertConstants.ALERT_INSET * 2), AlertConstants.ALERT_HEIGHT) + + alert_rect = rl.Rectangle( + content_rect.x + 10, + content_rect.y + y_offset, + content_rect.width - 30, + alert_item_height, + ) + + roundness = AlertConstants.BORDER_RADIUS / min(alert_rect.height, alert_rect.width) + rl.draw_rectangle_rounded(alert_rect, roundness, 10, bg_color) + + text_x = alert_rect.x + AlertConstants.ALERT_INSET + text_y = alert_rect.y + AlertConstants.ALERT_INSET + + for i, line in enumerate(wrapped_lines): + rl.draw_text_ex( + font, + line, + rl.Vector2(text_x, text_y + i * (AlertConstants.FONT_SIZE + 5)), + AlertConstants.FONT_SIZE, + 0, + AlertColors.TEXT, + ) + + y_offset += alert_item_height + AlertConstants.ALERT_SPACING + + +class UpdateAlert(AbstractAlert): + def __init__(self): + super().__init__(has_reboot_btn=True) + self.release_notes = "" + self._wrapped_release_notes = "" + self._cached_content_height: float = 0.0 + self._html_renderer = HtmlRenderer(text="") + + def refresh(self) -> bool: + update_available: bool = self.params.get_bool("UpdateAvailable") + if update_available: + self.release_notes = (self.params.get("UpdaterNewReleaseNotes") or b"").decode("utf8").strip() + self._html_renderer.parse_html_content(self.release_notes or NO_RELEASE_NOTES) + self._cached_content_height = 0 + else: + self._html_renderer.parse_html_content(NO_RELEASE_NOTES) + + return update_available + + def get_content_height(self) -> float: + if not self.release_notes: + return 100 + + if self._cached_content_height == 0: + self._wrapped_release_notes = self.release_notes + size = measure_text_cached(gui_app.font(FontWeight.NORMAL), self._wrapped_release_notes, AlertConstants.FONT_SIZE) + self._cached_content_height = max(size.y + 60, 100) + + return self._cached_content_height + + def _render_content(self, content_rect: rl.Rectangle): + notes_rect = rl.Rectangle(content_rect.x + 30, content_rect.y + 30, content_rect.width - 60, content_rect.height - 60) + self._html_renderer.render(notes_rect) diff --git a/selfdrive/ui/widgets/pairing_dialog.py b/selfdrive/ui/widgets/pairing_dialog.py new file mode 100644 index 0000000000..64e1b701f1 --- /dev/null +++ b/selfdrive/ui/widgets/pairing_dialog.py @@ -0,0 +1,181 @@ +import pyray as rl +import qrcode +import numpy as np +import time + +from openpilot.common.api import Api +from openpilot.common.swaglog import cloudlog +from openpilot.common.params import Params +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.lib.application import FontWeight, gui_app +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.selfdrive.ui.ui_state import ui_state + + +class IconButton(Widget): + def __init__(self, texture: rl.Texture): + super().__init__() + self._texture = texture + + def _render(self, rect: rl.Rectangle): + color = rl.Color(180, 180, 180, 150) if self.is_pressed else rl.WHITE + draw_x = rect.x + (rect.width - self._texture.width) / 2 + draw_y = rect.y + (rect.height - self._texture.height) / 2 + rl.draw_texture(self._texture, int(draw_x), int(draw_y), color) + + +class PairingDialog(Widget): + """Dialog for device pairing with QR code.""" + + QR_REFRESH_INTERVAL = 300 # 5 minutes in seconds + + def __init__(self): + super().__init__() + self.params = Params() + self.qr_texture: rl.Texture | None = None + self.last_qr_generation = 0 + self._close_btn = IconButton(gui_app.texture("icons/close.png", 80, 80)) + self._close_btn.set_click_callback(lambda: gui_app.set_modal_overlay(None)) + + def _get_pairing_url(self) -> str: + try: + dongle_id = self.params.get("DongleId") or "" + token = Api(dongle_id).get_token({'pair': True}) + except Exception as e: + cloudlog.warning(f"Failed to get pairing token: {e}") + token = "" + return f"https://connect.comma.ai/?pair={token}" + + def _generate_qr_code(self) -> None: + try: + qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4) + qr.add_data(self._get_pairing_url()) + qr.make(fit=True) + + pil_img = qr.make_image(fill_color="black", back_color="white").convert('RGBA') + img_array = np.array(pil_img, dtype=np.uint8) + + if self.qr_texture and self.qr_texture.id != 0: + rl.unload_texture(self.qr_texture) + + rl_image = rl.Image() + rl_image.data = rl.ffi.cast("void *", img_array.ctypes.data) + rl_image.width = pil_img.width + rl_image.height = pil_img.height + rl_image.mipmaps = 1 + rl_image.format = rl.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 + + self.qr_texture = rl.load_texture_from_image(rl_image) + except Exception as e: + cloudlog.warning(f"QR code generation failed: {e}") + self.qr_texture = None + + def _check_qr_refresh(self) -> None: + current_time = time.monotonic() + if current_time - self.last_qr_generation >= self.QR_REFRESH_INTERVAL: + self._generate_qr_code() + self.last_qr_generation = current_time + + def _update_state(self): + if ui_state.prime_state.is_paired(): + gui_app.set_modal_overlay(None) + + def _render(self, rect: rl.Rectangle) -> int: + rl.clear_background(rl.Color(224, 224, 224, 255)) + + self._check_qr_refresh() + + margin = 70 + content_rect = rl.Rectangle(rect.x + margin, rect.y + margin, rect.width - 2 * margin, rect.height - 2 * margin) + y = content_rect.y + + # Close button + close_size = 80 + pad = 20 + close_rect = rl.Rectangle(content_rect.x - pad, y - pad, close_size + pad * 2, close_size + pad * 2) + self._close_btn.render(close_rect) + + y += close_size + 40 + + # Title + title = "Pair your device to your comma account" + title_font = gui_app.font(FontWeight.NORMAL) + left_width = int(content_rect.width * 0.5 - 15) + + title_wrapped = wrap_text(title_font, title, 75, left_width) + rl.draw_text_ex(title_font, "\n".join(title_wrapped), rl.Vector2(content_rect.x, y), 75, 0.0, rl.BLACK) + y += len(title_wrapped) * 75 + 60 + + # Two columns: instructions and QR code + remaining_height = content_rect.height - (y - content_rect.y) + right_width = content_rect.width // 2 - 20 + + # Instructions + self._render_instructions(rl.Rectangle(content_rect.x, y, left_width, remaining_height)) + + # QR code + qr_size = min(right_width, content_rect.height) - 40 + qr_x = content_rect.x + left_width + 40 + (right_width - qr_size) // 2 + qr_y = content_rect.y + self._render_qr_code(rl.Rectangle(qr_x, qr_y, qr_size, qr_size)) + + return -1 + + def _render_instructions(self, rect: rl.Rectangle) -> None: + instructions = [ + "Go to https://connect.comma.ai on your phone", + "Click \"add new device\" and scan the QR code on the right", + "Bookmark connect.comma.ai to your home screen to use it like an app", + ] + + font = gui_app.font(FontWeight.BOLD) + y = rect.y + + for i, text in enumerate(instructions): + circle_radius = 25 + circle_x = rect.x + circle_radius + 15 + text_x = rect.x + circle_radius * 2 + 40 + text_width = rect.width - (circle_radius * 2 + 40) + + wrapped = wrap_text(font, text, 47, int(text_width)) + text_height = len(wrapped) * 47 + circle_y = y + text_height // 2 + + # Circle and number + rl.draw_circle(int(circle_x), int(circle_y), circle_radius, rl.Color(70, 70, 70, 255)) + number = str(i + 1) + number_width = measure_text_cached(font, number, 30).x + rl.draw_text_ex(font, number, (int(circle_x - number_width // 2), int(circle_y - 15)), 30, 0, rl.WHITE) + + # Text + rl.draw_text_ex(font, "\n".join(wrapped), rl.Vector2(text_x, y), 47, 0.0, rl.BLACK) + y += text_height + 50 + + def _render_qr_code(self, rect: rl.Rectangle) -> None: + if not self.qr_texture: + rl.draw_rectangle_rounded(rect, 0.1, 20, rl.Color(240, 240, 240, 255)) + error_font = gui_app.font(FontWeight.BOLD) + rl.draw_text_ex( + error_font, "QR Code Error", rl.Vector2(rect.x + 20, rect.y + rect.height // 2 - 15), 30, 0.0, rl.RED + ) + return + + source = rl.Rectangle(0, 0, self.qr_texture.width, self.qr_texture.height) + rl.draw_texture_pro(self.qr_texture, source, rect, rl.Vector2(0, 0), 0, rl.WHITE) + + def __del__(self): + if self.qr_texture and self.qr_texture.id != 0: + rl.unload_texture(self.qr_texture) + + +if __name__ == "__main__": + gui_app.init_window("pairing device") + pairing = PairingDialog() + try: + for _ in gui_app.render(): + result = pairing.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + if result != -1: + break + finally: + del pairing diff --git a/selfdrive/ui/widgets/prime.py b/selfdrive/ui/widgets/prime.py new file mode 100644 index 0000000000..6b601f6dff --- /dev/null +++ b/selfdrive/ui/widgets/prime.py @@ -0,0 +1,62 @@ +import pyray as rl + +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.label import gui_label + + +class PrimeWidget(Widget): + """Widget for displaying comma prime subscription status""" + + PRIME_BG_COLOR = rl.Color(51, 51, 51, 255) + + def _render(self, rect): + if ui_state.prime_state.is_prime(): + self._render_for_prime_user(rect) + else: + self._render_for_non_prime_users(rect) + + def _render_for_non_prime_users(self, rect: rl.Rectangle): + """Renders the advertisement for non-Prime users.""" + + rl.draw_rectangle_rounded(rect, 0.02, 10, self.PRIME_BG_COLOR) + + # Layout + x, y = rect.x + 80, rect.y + 90 + w = rect.width - 160 + + # Title + gui_label(rl.Rectangle(x, y, w, 90), "Upgrade Now", 75, font_weight=FontWeight.BOLD) + + # Description with wrapping + desc_y = y + 140 + font = gui_app.font(FontWeight.LIGHT) + wrapped_text = "\n".join(wrap_text(font, "Become a comma prime member at connect.comma.ai", 56, int(w))) + text_size = measure_text_cached(font, wrapped_text, 56) + rl.draw_text_ex(font, wrapped_text, rl.Vector2(x, desc_y), 56, 0, rl.WHITE) + + # Features section + features_y = desc_y + text_size.y + 50 + gui_label(rl.Rectangle(x, features_y, w, 50), "PRIME FEATURES:", 41, font_weight=FontWeight.BOLD) + + # Feature list + features = ["Remote access", "24/7 LTE connectivity", "1 year of drive storage", "Remote snapshots"] + for i, feature in enumerate(features): + item_y = features_y + 80 + i * 65 + gui_label(rl.Rectangle(x, item_y, 50, 60), "✓", 50, color=rl.Color(70, 91, 234, 255)) + gui_label(rl.Rectangle(x + 60, item_y, w - 60, 60), feature, 50) + + def _render_for_prime_user(self, rect: rl.Rectangle): + """Renders the prime user widget with subscription status.""" + + rl.draw_rectangle_rounded(rl.Rectangle(rect.x, rect.y, rect.width, 230), 0.02, 10, self.PRIME_BG_COLOR) + + x = rect.x + 56 + y = rect.y + 40 + + font = gui_app.font(FontWeight.BOLD) + rl.draw_text_ex(font, "✓ SUBSCRIBED", rl.Vector2(x, y), 41, 0, rl.Color(134, 255, 78, 255)) + rl.draw_text_ex(font, "comma prime", rl.Vector2(x, y + 61), 75, 0, rl.WHITE) diff --git a/selfdrive/ui/widgets/setup.py b/selfdrive/ui/widgets/setup.py new file mode 100644 index 0000000000..e4e44b7d04 --- /dev/null +++ b/selfdrive/ui/widgets/setup.py @@ -0,0 +1,93 @@ +import pyray as rl +from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.selfdrive.ui.widgets.pairing_dialog import PairingDialog +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle + + +class SetupWidget(Widget): + def __init__(self): + super().__init__() + self._open_settings_callback = None + self._pairing_dialog: PairingDialog | None = None + self._pair_device_btn = Button("Pair device", self._show_pairing, button_style=ButtonStyle.PRIMARY) + self._open_settings_btn = Button("Open", lambda: self._open_settings_callback() if self._open_settings_callback else None, + button_style=ButtonStyle.PRIMARY) + + def set_open_settings_callback(self, callback): + self._open_settings_callback = callback + + def _render(self, rect: rl.Rectangle): + if not ui_state.prime_state.is_paired(): + self._render_registration(rect) + else: + self._render_firehose_prompt(rect) + + def _render_registration(self, rect: rl.Rectangle): + """Render registration prompt.""" + + rl.draw_rectangle_rounded(rl.Rectangle(rect.x, rect.y, rect.width, 630), 0.02, 20, rl.Color(51, 51, 51, 255)) + + x = rect.x + 64 + y = rect.y + 48 + w = rect.width - 128 + + # Title + font = gui_app.font(FontWeight.BOLD) + rl.draw_text_ex(font, "Finish Setup", rl.Vector2(x, y), 75, 0, rl.WHITE) + y += 113 # 75 + 38 spacing + + # Description + desc = "Pair your device with comma connect (connect.comma.ai) and claim your comma prime offer." + light_font = gui_app.font(FontWeight.LIGHT) + wrapped = wrap_text(light_font, desc, 50, int(w)) + for line in wrapped: + rl.draw_text_ex(light_font, line, rl.Vector2(x, y), 50, 0, rl.WHITE) + y += 50 + + button_rect = rl.Rectangle(x, y + 50, w, 128) + self._pair_device_btn.render(button_rect) + + def _render_firehose_prompt(self, rect: rl.Rectangle): + """Render firehose prompt widget.""" + + rl.draw_rectangle_rounded(rl.Rectangle(rect.x, rect.y, rect.width, 450), 0.02, 20, rl.Color(51, 51, 51, 255)) + + # Content margins (56, 40, 56, 40) + x = rect.x + 56 + y = rect.y + 40 + w = rect.width - 112 + spacing = 42 + + # Title with fire emojis + title_font = gui_app.font(FontWeight.MEDIUM) + title_text = "Firehose Mode" + rl.draw_text_ex(title_font, title_text, rl.Vector2(x, y), 64, 0, rl.WHITE) + y += 64 + spacing + + # Description + desc_font = gui_app.font(FontWeight.NORMAL) + desc_text = "Maximize your training data uploads to improve openpilot's driving models." + wrapped_desc = wrap_text(desc_font, desc_text, 40, int(w)) + + for line in wrapped_desc: + rl.draw_text_ex(desc_font, line, rl.Vector2(x, y), 40, 0, rl.WHITE) + y += 40 + + y += spacing + + # Open button + button_height = 48 + 64 # font size + padding + button_rect = rl.Rectangle(x, y, w, button_height) + self._open_settings_btn.render(button_rect) + + def _show_pairing(self): + if not self._pairing_dialog: + self._pairing_dialog = PairingDialog() + gui_app.set_modal_overlay(self._pairing_dialog, lambda result: setattr(self, '_pairing_dialog', None)) + + def __del__(self): + if self._pairing_dialog: + del self._pairing_dialog diff --git a/selfdrive/ui/widgets/ssh_key.py b/selfdrive/ui/widgets/ssh_key.py new file mode 100644 index 0000000000..370141bd64 --- /dev/null +++ b/selfdrive/ui/widgets/ssh_key.py @@ -0,0 +1,128 @@ +import pyray as rl +import requests +import threading +import copy +from collections.abc import Callable +from enum import Enum + +from openpilot.common.params import Params +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import DialogResult +from openpilot.system.ui.widgets.button import Button, ButtonStyle +from openpilot.system.ui.widgets.confirm_dialog import alert_dialog +from openpilot.system.ui.widgets.keyboard import Keyboard +from openpilot.system.ui.widgets.list_view import ( + ItemAction, + ListItem, + BUTTON_HEIGHT, + BUTTON_BORDER_RADIUS, + BUTTON_FONT_SIZE, + BUTTON_WIDTH, +) + + +class SshKeyActionState(Enum): + LOADING = "LOADING" + ADD = "ADD" + REMOVE = "REMOVE" + + +class SshKeyAction(ItemAction): + HTTP_TIMEOUT = 15 # seconds + MAX_WIDTH = 500 + + def __init__(self): + super().__init__(self.MAX_WIDTH, True) + + self._keyboard = Keyboard(min_text_size=1) + self._params = Params() + self._error_message: str = "" + self._text_font = gui_app.font(FontWeight.MEDIUM) + self._button = Button("", click_callback=self._handle_button_click, button_style=ButtonStyle.LIST_ACTION, + border_radius=BUTTON_BORDER_RADIUS, font_size=BUTTON_FONT_SIZE) + + self._refresh_state() + + def set_touch_valid_callback(self, touch_callback: Callable[[], bool]) -> None: + super().set_touch_valid_callback(touch_callback) + self._button.set_touch_valid_callback(touch_callback) + + def _refresh_state(self): + self._username = self._params.get("GithubUsername") + self._state = SshKeyActionState.REMOVE if self._params.get("GithubSshKeys") else SshKeyActionState.ADD + + def _render(self, rect: rl.Rectangle) -> bool: + # Show error dialog if there's an error + if self._error_message: + message = copy.copy(self._error_message) + gui_app.set_modal_overlay(alert_dialog(message)) + self._username = "" + self._error_message = "" + + # Draw username if exists + if self._username: + text_size = measure_text_cached(self._text_font, self._username, BUTTON_FONT_SIZE) + rl.draw_text_ex( + self._text_font, + self._username, + (rect.x + rect.width - BUTTON_WIDTH - text_size.x - 30, rect.y + (rect.height - text_size.y) / 2), + BUTTON_FONT_SIZE, + 1.0, + rl.WHITE, + ) + + # Draw button + button_rect = rl.Rectangle(rect.x + rect.width - BUTTON_WIDTH, rect.y + (rect.height - BUTTON_HEIGHT) / 2, BUTTON_WIDTH, BUTTON_HEIGHT) + self._button.set_rect(button_rect) + self._button.set_text(self._state.value) + self._button.set_enabled(self._state != SshKeyActionState.LOADING) + self._button.render(button_rect) + return False + + def _handle_button_click(self): + if self._state == SshKeyActionState.ADD: + self._keyboard.reset() + self._keyboard.set_title("Enter your GitHub username") + gui_app.set_modal_overlay(self._keyboard, callback=self._on_username_submit) + elif self._state == SshKeyActionState.REMOVE: + self._params.remove("GithubUsername") + self._params.remove("GithubSshKeys") + self._refresh_state() + + def _on_username_submit(self, result: DialogResult): + if result != DialogResult.CONFIRM: + return + + username = self._keyboard.text.strip() + if not username: + return + + self._state = SshKeyActionState.LOADING + threading.Thread(target=lambda: self._fetch_ssh_key(username), daemon=True).start() + + def _fetch_ssh_key(self, username: str): + try: + url = f"https://github.com/{username}.keys" + response = requests.get(url, timeout=self.HTTP_TIMEOUT) + response.raise_for_status() + keys = response.text.strip() + if not keys: + raise requests.exceptions.HTTPError("No SSH keys found") + + # Success - save keys + self._params.put("GithubUsername", username) + self._params.put("GithubSshKeys", keys) + self._state = SshKeyActionState.REMOVE + self._username = username + + except requests.exceptions.Timeout: + self._error_message = "Request timed out" + self._state = SshKeyActionState.ADD + except Exception: + self._error_message = f"No SSH keys found for user '{username}'" + self._state = SshKeyActionState.ADD + + +def ssh_key_item(title: str, description: str): + return ListItem(title=title, description=description, action_item=SshKeyAction()) diff --git a/site_scons/site_tools/cython.py b/site_scons/site_tools/cython.py new file mode 100644 index 0000000000..f11db1d71b --- /dev/null +++ b/site_scons/site_tools/cython.py @@ -0,0 +1,75 @@ +import re +import SCons +from SCons.Action import Action +from SCons.Scanner import Scanner +import numpy as np + +pyx_from_import_re = re.compile(r'^from\s+(\S+)\s+cimport', re.M) +pyx_import_re = re.compile(r'^cimport\s+(\S+)', re.M) +cdef_import_re = re.compile(r'^cdef extern from\s+.(\S+).:', re.M) + +np_version = SCons.Script.Value(np.__version__) + +def pyx_scan(node, env, path, arg=None): + contents = node.get_text_contents() + env.Depends(str(node).split('.')[0] + env['CYTHONCFILESUFFIX'], np_version) + + # from cimport ... + matches = pyx_from_import_re.findall(contents) + # cimport + matches += pyx_import_re.findall(contents) + + # Modules can be either .pxd or .pyx files + files = [m.replace('.', '/') + '.pxd' for m in matches] + files += [m.replace('.', '/') + '.pyx' for m in matches] + + # cdef extern from + files += cdef_import_re.findall(contents) + + # Handle relative imports + cur_dir = str(node.get_dir()) + files = [cur_dir + f if f.startswith('/') else f for f in files] + + # Filter out non-existing files (probably system imports) + files = [f for f in files if env.File(f).exists()] + return env.File(files) + + +pyxscanner = Scanner(function=pyx_scan, skeys=['.pyx', '.pxd'], recursive=True) +cythonAction = Action("$CYTHONCOM") + + +def create_builder(env): + try: + cython = env['BUILDERS']['Cython'] + except KeyError: + cython = SCons.Builder.Builder( + action=cythonAction, + emitter={}, + suffix=cython_suffix_emitter, + single_source=1 + ) + env.Append(SCANNERS=pyxscanner) + env['BUILDERS']['Cython'] = cython + return cython + +def cython_suffix_emitter(env, source): + return "$CYTHONCFILESUFFIX" + +def generate(env): + env["CYTHON"] = "cythonize" + env["CYTHONCOM"] = "$CYTHON $CYTHONFLAGS $SOURCE" + env["CYTHONCFILESUFFIX"] = ".cpp" + + c_file, _ = SCons.Tool.createCFileBuilders(env) + + c_file.suffix['.pyx'] = cython_suffix_emitter + c_file.add_action('.pyx', cythonAction) + + c_file.suffix['.py'] = cython_suffix_emitter + c_file.add_action('.py', cythonAction) + + create_builder(env) + +def exists(env): + return True diff --git a/system/__init__.py b/system/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/athena/__init__.py b/system/athena/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/athena/athenad.py b/system/athena/athenad.py new file mode 100755 index 0000000000..6ed53b759c --- /dev/null +++ b/system/athena/athenad.py @@ -0,0 +1,861 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import base64 +import hashlib +import io +import json +import os +import queue +import random +import select +import socket +import sys +import tempfile +import threading +import time +from dataclasses import asdict, dataclass, replace +from datetime import datetime +from functools import partial, total_ordering +from queue import Queue +from typing import cast +from collections.abc import Callable + +import requests +from requests.adapters import HTTPAdapter, DEFAULT_POOLBLOCK +from jsonrpc import JSONRPCResponseManager, dispatcher +from websocket import (ABNF, WebSocket, WebSocketException, WebSocketTimeoutException, + create_connection) + +import cereal.messaging as messaging +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.common.api import Api +from openpilot.common.file_helpers import CallbackReader, get_upload_stream +from openpilot.common.params import Params +from openpilot.common.realtime import set_core_affinity +from openpilot.system.hardware import HARDWARE, PC +from openpilot.system.loggerd.xattr_cache import getxattr, setxattr +from openpilot.common.swaglog import cloudlog +from openpilot.system.version import get_build_metadata +from openpilot.system.hardware.hw import Paths + + +ATHENA_HOST = os.getenv('ATHENA_HOST', 'wss://athena.comma.ai') +HANDLER_THREADS = int(os.getenv('HANDLER_THREADS', "4")) +LOCAL_PORT_WHITELIST = {22, } # SSH + +LOG_ATTR_NAME = 'user.upload' +LOG_ATTR_VALUE_MAX_UNIX_TIME = int.to_bytes(2147483647, 4, sys.byteorder) +RECONNECT_TIMEOUT_S = 70 + +RETRY_DELAY = 10 # seconds +MAX_RETRY_COUNT = 30 # Try for at most 5 minutes if upload fails immediately +MAX_AGE = 31 * 24 * 3600 # seconds +WS_FRAME_SIZE = 4096 +DEVICE_STATE_UPDATE_INTERVAL = 1.0 # in seconds +DEFAULT_UPLOAD_PRIORITY = 99 # higher number = lower priority + +# https://bytesolutions.com/dscp-tos-cos-precedence-conversion-chart, +# https://en.wikipedia.org/wiki/Differentiated_services +UPLOAD_TOS = 0x20 # CS1, low priority background traffic +SSH_TOS = 0x90 # AF42, DSCP of 36/HDD_LINUX_AC_VI with the minimum delay flag + +NetworkType = log.DeviceState.NetworkType + +UploadFileDict = dict[str, str | int | float | bool] +UploadItemDict = dict[str, str | bool | int | float | dict[str, str]] + +UploadFilesToUrlResponse = dict[str, int | list[UploadItemDict] | list[str]] + + +class UploadTOSAdapter(HTTPAdapter): + def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs): + pool_kwargs["socket_options"] = [(socket.IPPROTO_IP, socket.IP_TOS, UPLOAD_TOS)] + super().init_poolmanager(connections, maxsize, block, **pool_kwargs) + + +UPLOAD_SESS = requests.Session() +UPLOAD_SESS.mount("http://", UploadTOSAdapter()) +UPLOAD_SESS.mount("https://", UploadTOSAdapter()) + + +@dataclass +class UploadFile: + fn: str + url: str + headers: dict[str, str] + allow_cellular: bool + priority: int = DEFAULT_UPLOAD_PRIORITY + + @classmethod + def from_dict(cls, d: dict) -> UploadFile: + return cls(d.get("fn", ""), d.get("url", ""), d.get("headers", {}), d.get("allow_cellular", False), d.get("priority", DEFAULT_UPLOAD_PRIORITY)) + + +@dataclass +@total_ordering +class UploadItem: + path: str + url: str + headers: dict[str, str] + created_at: int + id: str | None + retry_count: int = 0 + current: bool = False + progress: float = 0 + allow_cellular: bool = False + priority: int = DEFAULT_UPLOAD_PRIORITY + + @classmethod + def from_dict(cls, d: dict) -> UploadItem: + return cls(d["path"], d["url"], d["headers"], d["created_at"], d["id"], d["retry_count"], d["current"], + d["progress"], d["allow_cellular"], d["priority"]) + + def __lt__(self, other): + if not isinstance(other, UploadItem): + return NotImplemented + return self.priority < other.priority + + def __eq__(self, other): + if not isinstance(other, UploadItem): + return NotImplemented + return self.priority == other.priority + + +dispatcher["echo"] = lambda s: s +recv_queue: Queue[str] = queue.Queue() +send_queue: Queue[str] = queue.Queue() +upload_queue: Queue[UploadItem] = queue.PriorityQueue() +low_priority_send_queue: Queue[str] = queue.Queue() +log_recv_queue: Queue[str] = queue.Queue() +cancelled_uploads: set[str] = set() + +cur_upload_items: dict[int, UploadItem | None] = {} + + +def strip_zst_extension(fn: str) -> str: + if fn.endswith('.zst'): + return fn[:-4] + return fn + + +class AbortTransferException(Exception): + pass + + +class UploadQueueCache: + + @staticmethod + def initialize(upload_queue: Queue[UploadItem]) -> None: + try: + upload_queue_json = Params().get("AthenadUploadQueue") + if upload_queue_json is not None: + for item in upload_queue_json: + upload_queue.put(UploadItem.from_dict(item)) + except Exception: + cloudlog.exception("athena.UploadQueueCache.initialize.exception") + + @staticmethod + def cache(upload_queue: Queue[UploadItem]) -> None: + try: + queue: list[UploadItem | None] = list(upload_queue.queue) + items = [asdict(i) for i in queue if i is not None and (i.id not in cancelled_uploads)] + Params().put("AthenadUploadQueue", items) + except Exception: + cloudlog.exception("athena.UploadQueueCache.cache.exception") + + +def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None: + end_event = threading.Event() + + threads = [ + threading.Thread(target=ws_manage, args=(ws, end_event), name='ws_manage'), + threading.Thread(target=ws_recv, args=(ws, end_event), name='ws_recv'), + threading.Thread(target=ws_send, args=(ws, end_event), name='ws_send'), + threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler'), + threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler2'), + threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler3'), + threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler4'), + threading.Thread(target=log_handler, args=(end_event,), name='log_handler'), + threading.Thread(target=stat_handler, args=(end_event,), name='stat_handler'), + ] + [ + threading.Thread(target=jsonrpc_handler, args=(end_event,), name=f'worker_{x}') + for x in range(HANDLER_THREADS) + ] + + for thread in threads: + thread.start() + try: + while not end_event.wait(0.1): + if exit_event is not None and exit_event.is_set(): + end_event.set() + except (KeyboardInterrupt, SystemExit): + end_event.set() + raise + finally: + for thread in threads: + cloudlog.debug(f"athena.joining {thread.name}") + thread.join() + + +def jsonrpc_handler(end_event: threading.Event) -> None: + dispatcher["startLocalProxy"] = partial(startLocalProxy, end_event) + while not end_event.is_set(): + try: + data = recv_queue.get(timeout=1) + if "method" in data: + cloudlog.event("athena.jsonrpc_handler.call_method", data=data) + response = JSONRPCResponseManager.handle(data, dispatcher) + send_queue.put_nowait(response.json) + elif "id" in data and ("result" in data or "error" in data): + log_recv_queue.put_nowait(data) + else: + raise Exception("not a valid request or response") + except queue.Empty: + pass + except Exception as e: + cloudlog.exception("athena jsonrpc handler failed") + send_queue.put_nowait(json.dumps({"error": str(e)})) + + +def retry_upload(tid: int, end_event: threading.Event, increase_count: bool = True) -> None: + item = cur_upload_items[tid] + if item is not None and item.retry_count < MAX_RETRY_COUNT: + new_retry_count = item.retry_count + 1 if increase_count else item.retry_count + + item = replace( + item, + retry_count=new_retry_count, + progress=0, + current=False + ) + upload_queue.put_nowait(item) + UploadQueueCache.cache(upload_queue) + + cur_upload_items[tid] = None + + for _ in range(RETRY_DELAY): + time.sleep(1) + if end_event.is_set(): + break + + +def cb(sm, item, tid, end_event: threading.Event, sz: int, cur: int) -> None: + # Abort transfer if connection changed to metered after starting upload + # or if athenad is shutting down to re-connect the websocket + if not item.allow_cellular: + if (time.monotonic() - sm.recv_time['deviceState']) > DEVICE_STATE_UPDATE_INTERVAL: + sm.update(0) + if sm['deviceState'].networkMetered: + raise AbortTransferException + + if end_event.is_set(): + raise AbortTransferException + + cur_upload_items[tid] = replace(item, progress=cur / sz if sz else 1) + + +def upload_handler(end_event: threading.Event) -> None: + sm = messaging.SubMaster(['deviceState']) + tid = threading.get_ident() + + while not end_event.is_set(): + cur_upload_items[tid] = None + + try: + cur_upload_items[tid] = item = replace(upload_queue.get(timeout=1), current=True) + + if item.id in cancelled_uploads: + cancelled_uploads.remove(item.id) + continue + + # Remove item if too old + age = datetime.now() - datetime.fromtimestamp(item.created_at / 1000) + if age.total_seconds() > MAX_AGE: + cloudlog.event("athena.upload_handler.expired", item=item, error=True) + continue + + # Check if uploading over metered connection is allowed + sm.update(0) + metered = sm['deviceState'].networkMetered + network_type = sm['deviceState'].networkType.raw + if metered and (not item.allow_cellular): + retry_upload(tid, end_event, False) + continue + + try: + fn = item.path + try: + sz = os.path.getsize(fn) + except OSError: + sz = -1 + + cloudlog.event("athena.upload_handler.upload_start", fn=fn, sz=sz, network_type=network_type, metered=metered, retry_count=item.retry_count) + + with _do_upload(item, partial(cb, sm, item, tid, end_event)) as response: + if response.status_code not in (200, 201, 401, 403, 412): + cloudlog.event("athena.upload_handler.retry", status_code=response.status_code, fn=fn, sz=sz, network_type=network_type, metered=metered) + retry_upload(tid, end_event) + else: + cloudlog.event("athena.upload_handler.success", fn=fn, sz=sz, network_type=network_type, metered=metered) + + UploadQueueCache.cache(upload_queue) + except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.SSLError): + cloudlog.event("athena.upload_handler.timeout", fn=fn, sz=sz, network_type=network_type, metered=metered) + retry_upload(tid, end_event) + except AbortTransferException: + cloudlog.event("athena.upload_handler.abort", fn=fn, sz=sz, network_type=network_type, metered=metered) + retry_upload(tid, end_event, False) + + except queue.Empty: + pass + except Exception: + cloudlog.exception("athena.upload_handler.exception") + + +def _do_upload(upload_item: UploadItem, callback: Callable = None) -> requests.Response: + path = upload_item.path + compress = False + + # If file does not exist, but does exist without the .zst extension we will compress on the fly + if not os.path.exists(path) and os.path.exists(strip_zst_extension(path)): + path = strip_zst_extension(path) + compress = True + + stream = None + try: + stream, content_length = get_upload_stream(path, compress) + response = UPLOAD_SESS.put(upload_item.url, + data=CallbackReader(stream, callback, content_length) if callback else stream, + headers={**upload_item.headers, 'Content-Length': str(content_length)}, + timeout=30) + return response + finally: + if stream: + stream.close() + + +# security: user should be able to request any message from their car +@dispatcher.add_method +def getMessage(service: str, timeout: int = 1000) -> dict: + if service is None or service not in SERVICE_LIST: + raise Exception("invalid service") + + socket = messaging.sub_sock(service, timeout=timeout) + try: + ret = messaging.recv_one(socket) + + if ret is None: + raise TimeoutError + + # this is because capnp._DynamicStructReader doesn't have typing information + return cast(dict, ret.to_dict()) + finally: + del socket + + +@dispatcher.add_method +def getVersion() -> dict[str, str]: + build_metadata = get_build_metadata() + return { + "version": build_metadata.openpilot.version, + "remote": build_metadata.openpilot.git_normalized_origin, + "branch": build_metadata.channel, + "commit": build_metadata.openpilot.git_commit, + } + + +def scan_dir(path: str, prefix: str) -> list[str]: + files = [] + # only walk directories that match the prefix + # (glob and friends traverse entire dir tree) + with os.scandir(path) as i: + for e in i: + rel_path = os.path.relpath(e.path, Paths.log_root()) + if e.is_dir(follow_symlinks=False): + # add trailing slash + rel_path = os.path.join(rel_path, '') + # if prefix is a partial dir name, current dir will start with prefix + # if prefix is a partial file name, prefix with start with dir name + if rel_path.startswith(prefix) or prefix.startswith(rel_path): + files.extend(scan_dir(e.path, prefix)) + else: + if rel_path.startswith(prefix): + files.append(rel_path) + return files + +@dispatcher.add_method +def listDataDirectory(prefix='') -> list[str]: + return scan_dir(Paths.log_root(), prefix) + + +@dispatcher.add_method +def uploadFileToUrl(fn: str, url: str, headers: dict[str, str]) -> UploadFilesToUrlResponse: + # this is because mypy doesn't understand that the decorator doesn't change the return type + response: UploadFilesToUrlResponse = uploadFilesToUrls([{ + "fn": fn, + "url": url, + "headers": headers, + }]) + return response + + +@dispatcher.add_method +def uploadFilesToUrls(files_data: list[UploadFileDict]) -> UploadFilesToUrlResponse: + files = map(UploadFile.from_dict, files_data) + + items: list[UploadItemDict] = [] + failed: list[str] = [] + for file in files: + if len(file.fn) == 0 or file.fn[0] == '/' or '..' in file.fn or len(file.url) == 0: + failed.append(file.fn) + continue + + path = os.path.join(Paths.log_root(), file.fn) + if not os.path.exists(path) and not os.path.exists(strip_zst_extension(path)): + failed.append(file.fn) + continue + + # Skip item if already in queue + url = file.url.split('?')[0] + if any(url == item['url'].split('?')[0] for item in listUploadQueue()): + continue + + item = UploadItem( + path=path, + url=file.url, + headers=file.headers, + created_at=int(time.time() * 1000), # noqa: TID251 + id=None, + allow_cellular=file.allow_cellular, + priority=file.priority, + ) + upload_id = hashlib.sha1(str(item).encode()).hexdigest() + item = replace(item, id=upload_id) + upload_queue.put_nowait(item) + items.append(asdict(item)) + + UploadQueueCache.cache(upload_queue) + + resp: UploadFilesToUrlResponse = {"enqueued": len(items), "items": items} + if failed: + cloudlog.event("athena.uploadFilesToUrls.failed", failed=failed, error=True) + resp["failed"] = failed + + return resp + + +@dispatcher.add_method +def listUploadQueue() -> list[UploadItemDict]: + items = list(upload_queue.queue) + list(cur_upload_items.values()) + return [asdict(i) for i in items if (i is not None) and (i.id not in cancelled_uploads)] + + +@dispatcher.add_method +def cancelUpload(upload_id: str | list[str]) -> dict[str, int | str]: + if not isinstance(upload_id, list): + upload_id = [upload_id] + + uploading_ids = {item.id for item in list(upload_queue.queue)} + cancelled_ids = uploading_ids.intersection(upload_id) + if len(cancelled_ids) == 0: + return {"success": 0, "error": "not found"} + + cancelled_uploads.update(cancelled_ids) + return {"success": 1} + +@dispatcher.add_method +def setRouteViewed(route: str) -> dict[str, int | str]: + # maintain a list of the last 10 routes viewed in connect + params = Params() + + r = params.get("AthenadRecentlyViewedRoutes") + routes = [] if r is None else r.split(",") + routes.append(route) + + # remove duplicates + routes = list(dict.fromkeys(routes)) + + params.put("AthenadRecentlyViewedRoutes", ",".join(routes[-10:])) + return {"success": 1} + + +def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local_port: int) -> dict[str, int]: + try: + # migration, can be removed once 0.9.8 is out for a while + if local_port == 8022: + local_port = 22 + + if local_port not in LOCAL_PORT_WHITELIST: + raise Exception("Requested local port not whitelisted") + + cloudlog.debug("athena.startLocalProxy.starting") + + dongle_id = Params().get("DongleId") + identity_token = Api(dongle_id).get_token() + ws = create_connection(remote_ws_uri, + cookie="jwt=" + identity_token, + enable_multithread=True) + + # Set TOS to keep connection responsive while under load. + ws.sock.setsockopt(socket.IPPROTO_IP, socket.IP_TOS, SSH_TOS) + + ssock, csock = socket.socketpair() + local_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + local_sock.connect(('127.0.0.1', local_port)) + local_sock.setblocking(False) + + proxy_end_event = threading.Event() + threads = [ + threading.Thread(target=ws_proxy_recv, args=(ws, local_sock, ssock, proxy_end_event, global_end_event)), + threading.Thread(target=ws_proxy_send, args=(ws, local_sock, csock, proxy_end_event)) + ] + for thread in threads: + thread.start() + + cloudlog.debug("athena.startLocalProxy.started") + return {"success": 1} + except Exception as e: + cloudlog.exception("athenad.startLocalProxy.exception") + raise e + + +@dispatcher.add_method +def getPublicKey() -> str | None: + if not os.path.isfile(Paths.persist_root() + '/comma/id_rsa.pub'): + return None + + with open(Paths.persist_root() + '/comma/id_rsa.pub') as f: + return f.read() + + +@dispatcher.add_method +def getSshAuthorizedKeys() -> str: + return cast(str, Params().get("GithubSshKeys") or "") + + +@dispatcher.add_method +def getGithubUsername() -> str: + return cast(str, Params().get("GithubUsername") or "") + +@dispatcher.add_method +def getSimInfo(): + return HARDWARE.get_sim_info() + + +@dispatcher.add_method +def getNetworkType(): + return HARDWARE.get_network_type() + + +@dispatcher.add_method +def getNetworkMetered() -> bool: + network_type = HARDWARE.get_network_type() + return HARDWARE.get_network_metered(network_type) + + +@dispatcher.add_method +def getNetworks(): + return HARDWARE.get_networks() + + +@dispatcher.add_method +def takeSnapshot() -> str | dict[str, str] | None: + from openpilot.system.camerad.snapshot import jpeg_write, snapshot + ret = snapshot() + if ret is not None: + def b64jpeg(x): + if x is not None: + f = io.BytesIO() + jpeg_write(f, x) + return base64.b64encode(f.getvalue()).decode("utf-8") + else: + return None + return {'jpegBack': b64jpeg(ret[0]), + 'jpegFront': b64jpeg(ret[1])} + else: + raise Exception("not available while camerad is started") + + +def get_logs_to_send_sorted() -> list[str]: + # TODO: scan once then use inotify to detect file creation/deletion + curr_time = int(time.time()) # noqa: TID251 + logs = [] + for log_entry in os.listdir(Paths.swaglog_root()): + log_path = os.path.join(Paths.swaglog_root(), log_entry) + time_sent = 0 + try: + value = getxattr(log_path, LOG_ATTR_NAME) + if value is not None: + time_sent = int.from_bytes(value, sys.byteorder) + except (ValueError, TypeError): + pass + # assume send failed and we lost the response if sent more than one hour ago + if not time_sent or curr_time - time_sent > 3600: + logs.append(log_entry) + # excluding most recent (active) log file + return sorted(logs)[:-1] + + +def log_handler(end_event: threading.Event) -> None: + if PC: + return + + log_files = [] + last_scan = 0. + while not end_event.is_set(): + try: + curr_scan = time.monotonic() + if curr_scan - last_scan > 10: + log_files = get_logs_to_send_sorted() + last_scan = curr_scan + + # send one log + curr_log = None + if len(log_files) > 0: + log_entry = log_files.pop() # newest log file + cloudlog.debug(f"athena.log_handler.forward_request {log_entry}") + try: + curr_time = int(time.time()) # noqa: TID251 + log_path = os.path.join(Paths.swaglog_root(), log_entry) + setxattr(log_path, LOG_ATTR_NAME, int.to_bytes(curr_time, 4, sys.byteorder)) + with open(log_path) as f: + jsonrpc = { + "method": "forwardLogs", + "params": { + "logs": f.read() + }, + "jsonrpc": "2.0", + "id": log_entry + } + low_priority_send_queue.put_nowait(json.dumps(jsonrpc)) + curr_log = log_entry + except OSError: + pass # file could be deleted by log rotation + + # wait for response up to ~100 seconds + # always read queue at least once to process any old responses that arrive + for _ in range(100): + if end_event.is_set(): + break + try: + log_resp = json.loads(log_recv_queue.get(timeout=1)) + log_entry = log_resp.get("id") + log_success = "result" in log_resp and log_resp["result"].get("success") + cloudlog.debug(f"athena.log_handler.forward_response {log_entry} {log_success}") + if log_entry and log_success: + log_path = os.path.join(Paths.swaglog_root(), log_entry) + try: + setxattr(log_path, LOG_ATTR_NAME, LOG_ATTR_VALUE_MAX_UNIX_TIME) + except OSError: + pass # file could be deleted by log rotation + if curr_log == log_entry: + break + except queue.Empty: + if curr_log is None: + break + + except Exception: + cloudlog.exception("athena.log_handler.exception") + + +def stat_handler(end_event: threading.Event) -> None: + STATS_DIR = Paths.stats_root() + last_scan = 0.0 + + while not end_event.is_set(): + curr_scan = time.monotonic() + try: + if curr_scan - last_scan > 10: + stat_filenames = list(filter(lambda name: not name.startswith(tempfile.gettempprefix()), os.listdir(STATS_DIR))) + if len(stat_filenames) > 0: + stat_path = os.path.join(STATS_DIR, stat_filenames[0]) + with open(stat_path) as f: + jsonrpc = { + "method": "storeStats", + "params": { + "stats": f.read() + }, + "jsonrpc": "2.0", + "id": stat_filenames[0] + } + low_priority_send_queue.put_nowait(json.dumps(jsonrpc)) + os.remove(stat_path) + last_scan = curr_scan + except Exception: + cloudlog.exception("athena.stat_handler.exception") + time.sleep(0.1) + + +def ws_proxy_recv(ws: WebSocket, local_sock: socket.socket, ssock: socket.socket, end_event: threading.Event, global_end_event: threading.Event) -> None: + while not (end_event.is_set() or global_end_event.is_set()): + try: + r = select.select((ws.sock,), (), (), 30) + if r[0]: + data = ws.recv() + if isinstance(data, str): + data = data.encode("utf-8") + local_sock.sendall(data) + except WebSocketTimeoutException: + pass + except Exception: + cloudlog.exception("athenad.ws_proxy_recv.exception") + break + + cloudlog.debug("athena.ws_proxy_recv closing sockets") + ssock.close() + local_sock.close() + ws.close() + cloudlog.debug("athena.ws_proxy_recv done closing sockets") + + end_event.set() + + +def ws_proxy_send(ws: WebSocket, local_sock: socket.socket, signal_sock: socket.socket, end_event: threading.Event) -> None: + while not end_event.is_set(): + try: + r, _, _ = select.select((local_sock, signal_sock), (), ()) + if r: + if r[0].fileno() == signal_sock.fileno(): + # got end signal from ws_proxy_recv + end_event.set() + break + data = local_sock.recv(4096) + if not data: + # local_sock is dead + end_event.set() + break + + ws.send(data, ABNF.OPCODE_BINARY) + except Exception: + cloudlog.exception("athenad.ws_proxy_send.exception") + end_event.set() + + cloudlog.debug("athena.ws_proxy_send closing sockets") + signal_sock.close() + cloudlog.debug("athena.ws_proxy_send done closing sockets") + + +def ws_recv(ws: WebSocket, end_event: threading.Event) -> None: + last_ping = int(time.monotonic() * 1e9) + while not end_event.is_set(): + try: + opcode, data = ws.recv_data(control_frame=True) + if opcode in (ABNF.OPCODE_TEXT, ABNF.OPCODE_BINARY): + if opcode == ABNF.OPCODE_TEXT: + data = data.decode("utf-8") + recv_queue.put_nowait(data) + elif opcode == ABNF.OPCODE_PING: + last_ping = int(time.monotonic() * 1e9) + Params().put("LastAthenaPingTime", last_ping) + except WebSocketTimeoutException: + ns_since_last_ping = int(time.monotonic() * 1e9) - last_ping + if ns_since_last_ping > RECONNECT_TIMEOUT_S * 1e9: + cloudlog.exception("athenad.ws_recv.timeout") + end_event.set() + except Exception: + cloudlog.exception("athenad.ws_recv.exception") + end_event.set() + + +def ws_send(ws: WebSocket, end_event: threading.Event) -> None: + while not end_event.is_set(): + try: + try: + data = send_queue.get_nowait() + except queue.Empty: + data = low_priority_send_queue.get(timeout=1) + for i in range(0, len(data), WS_FRAME_SIZE): + frame = data[i:i+WS_FRAME_SIZE] + last = i + WS_FRAME_SIZE >= len(data) + opcode = ABNF.OPCODE_TEXT if i == 0 else ABNF.OPCODE_CONT + ws.send_frame(ABNF.create_frame(frame, opcode, last)) + except queue.Empty: + pass + except Exception: + cloudlog.exception("athenad.ws_send.exception") + end_event.set() + + +def ws_manage(ws: WebSocket, end_event: threading.Event) -> None: + params = Params() + onroad_prev = None + sock = ws.sock + + while True: + onroad = params.get_bool("IsOnroad") + if onroad != onroad_prev: + onroad_prev = onroad + + if sock is not None: + # While not sending data, onroad, we can expect to time out in 7 + (7 * 2) = 21s + # offroad, we can expect to time out in 30 + (10 * 3) = 60s + # FIXME: TCP_USER_TIMEOUT is effectively 2x for some reason (32s), so it's mostly unused + if sys.platform == 'linux': + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_USER_TIMEOUT, 16000 if onroad else 0) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 7 if onroad else 30) + elif sys.platform == 'darwin': + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPALIVE, 7 if onroad else 30) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 7 if onroad else 10) + sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 2 if onroad else 3) + + if end_event.wait(5): + break + + +def backoff(retries: int) -> int: + return random.randrange(0, min(128, int(2 ** retries))) + + +def main(exit_event: threading.Event = None): + try: + set_core_affinity([0, 1, 2, 3]) + except Exception: + cloudlog.exception("failed to set core affinity") + + params = Params() + dongle_id = params.get("DongleId") + UploadQueueCache.initialize(upload_queue) + + ws_uri = ATHENA_HOST + "/ws/v2/" + dongle_id + api = Api(dongle_id) + + conn_start = None + conn_retries = 0 + while exit_event is None or not exit_event.is_set(): + try: + if conn_start is None: + conn_start = time.monotonic() + + cloudlog.event("athenad.main.connecting_ws", ws_uri=ws_uri, retries=conn_retries) + ws = create_connection(ws_uri, + cookie="jwt=" + api.get_token(), + enable_multithread=True, + timeout=30.0) + cloudlog.event("athenad.main.connected_ws", ws_uri=ws_uri, retries=conn_retries, + duration=time.monotonic() - conn_start) + conn_start = None + + conn_retries = 0 + cur_upload_items.clear() + + handle_long_poll(ws, exit_event) + + ws.close() + except (KeyboardInterrupt, SystemExit): + break + except (ConnectionError, TimeoutError, WebSocketException): + conn_retries += 1 + params.remove("LastAthenaPingTime") + except Exception: + cloudlog.exception("athenad.main.exception") + + conn_retries += 1 + params.remove("LastAthenaPingTime") + + time.sleep(backoff(conn_retries)) + + +if __name__ == "__main__": + main() diff --git a/system/athena/manage_athenad.py b/system/athena/manage_athenad.py new file mode 100755 index 0000000000..ee63606b66 --- /dev/null +++ b/system/athena/manage_athenad.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import time +from multiprocessing import Process + +from openpilot.common.params import Params +from openpilot.system.manager.process import launcher +from openpilot.common.swaglog import cloudlog +from openpilot.system.hardware import HARDWARE +from openpilot.system.version import get_build_metadata + +ATHENA_MGR_PID_PARAM = "AthenadPid" + + +def main(): + params = Params() + dongle_id = params.get("DongleId") + build_metadata = get_build_metadata() + + cloudlog.bind_global(dongle_id=dongle_id, + version=build_metadata.openpilot.version, + origin=build_metadata.openpilot.git_normalized_origin, + branch=build_metadata.channel, + commit=build_metadata.openpilot.git_commit, + dirty=build_metadata.openpilot.is_dirty, + device=HARDWARE.get_device_type()) + + try: + while 1: + cloudlog.info("starting athena daemon") + proc = Process(name='athenad', target=launcher, args=('system.athena.athenad', 'athenad')) + proc.start() + proc.join() + cloudlog.event("athenad exited", exitcode=proc.exitcode) + time.sleep(5) + except Exception: + cloudlog.exception("manage_athenad.exception") + finally: + params.remove(ATHENA_MGR_PID_PARAM) + + +if __name__ == '__main__': + main() diff --git a/system/athena/registration.py b/system/athena/registration.py new file mode 100755 index 0000000000..80c087188d --- /dev/null +++ b/system/athena/registration.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +import time +import json +import jwt +from pathlib import Path + +from datetime import datetime, timedelta, UTC +from openpilot.common.api import api_get +from openpilot.common.params import Params +from openpilot.common.spinner import Spinner +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.system.hardware import HARDWARE, PC +from openpilot.system.hardware.hw import Paths +from openpilot.common.swaglog import cloudlog + + +UNREGISTERED_DONGLE_ID = "UnregisteredDevice" + +def is_registered_device() -> bool: + dongle = Params().get("DongleId") + return dongle not in (None, UNREGISTERED_DONGLE_ID) + + +def register(show_spinner=False) -> str | None: + """ + All devices built since March 2024 come with all + info stored in /persist/. This is kept around + only for devices built before then. + + With a backend update to take serial number instead + of dongle ID to some endpoints, this can be removed + entirely. + """ + params = Params() + + dongle_id: str | None = params.get("DongleId") + if dongle_id is None and Path(Paths.persist_root()+"/comma/dongle_id").is_file(): + # not all devices will have this; added early in comma 3X production (2/28/24) + with open(Paths.persist_root()+"/comma/dongle_id") as f: + dongle_id = f.read().strip() + + pubkey = Path(Paths.persist_root()+"/comma/id_rsa.pub") + if not pubkey.is_file(): + dongle_id = UNREGISTERED_DONGLE_ID + cloudlog.warning(f"missing public key: {pubkey}") + elif dongle_id is None: + if show_spinner: + spinner = Spinner() + spinner.update("registering device") + + # Create registration token, in the future, this key will make JWTs directly + with open(Paths.persist_root()+"/comma/id_rsa.pub") as f1, open(Paths.persist_root()+"/comma/id_rsa") as f2: + public_key = f1.read() + private_key = f2.read() + + # Block until we get the imei + serial = HARDWARE.get_serial() + start_time = time.monotonic() + imei1: str | None = None + imei2: str | None = None + while imei1 is None and imei2 is None: + try: + imei1, imei2 = HARDWARE.get_imei(0), HARDWARE.get_imei(1) + except Exception: + cloudlog.exception("Error getting imei, trying again...") + time.sleep(1) + + if time.monotonic() - start_time > 60 and show_spinner: + spinner.update(f"registering device - serial: {serial}, IMEI: ({imei1}, {imei2})") + + backoff = 0 + start_time = time.monotonic() + while True: + try: + register_token = jwt.encode({'register': True, 'exp': datetime.now(UTC).replace(tzinfo=None) + timedelta(hours=1)}, private_key, algorithm='RS256') + cloudlog.info("getting pilotauth") + resp = api_get("v2/pilotauth/", method='POST', timeout=15, + imei=imei1, imei2=imei2, serial=serial, public_key=public_key, register_token=register_token) + + if resp.status_code in (402, 403): + cloudlog.info(f"Unable to register device, got {resp.status_code}") + dongle_id = UNREGISTERED_DONGLE_ID + else: + dongleauth = json.loads(resp.text) + dongle_id = dongleauth["dongle_id"] + break + except Exception: + cloudlog.exception("failed to authenticate") + backoff = min(backoff + 1, 15) + time.sleep(backoff) + + if time.monotonic() - start_time > 60 and show_spinner: + spinner.update(f"registering device - serial: {serial}, IMEI: ({imei1}, {imei2})") + + if show_spinner: + spinner.close() + + if dongle_id: + params.put("DongleId", dongle_id) + set_offroad_alert("Offroad_UnregisteredHardware", (dongle_id == UNREGISTERED_DONGLE_ID) and not PC) + return dongle_id + + +if __name__ == "__main__": + print(register()) diff --git a/system/athena/tests/__init__.py b/system/athena/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/athena/tests/helpers.py b/system/athena/tests/helpers.py new file mode 100644 index 0000000000..a0a9cccdc1 --- /dev/null +++ b/system/athena/tests/helpers.py @@ -0,0 +1,70 @@ +import http.server +import socket + + +class MockResponse: + def __init__(self, json, status_code): + self.json = json + self.text = json + self.status_code = status_code + + +class EchoSocket: + def __init__(self, port): + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.bind(('127.0.0.1', port)) + self.socket.listen(1) + + def run(self): + conn, _ = self.socket.accept() + conn.settimeout(5.0) + + try: + while True: + data = conn.recv(4096) + if data: + print(f'EchoSocket got {data}') + conn.sendall(data) + else: + break + finally: + conn.shutdown(0) + conn.close() + self.socket.shutdown(0) + self.socket.close() + + +class MockApi: + def __init__(self, dongle_id): + pass + + def get_token(self): + return "fake-token" + + +class MockWebsocket: + sock = socket.socket() + + def __init__(self, recv_queue, send_queue): + self.recv_queue = recv_queue + self.send_queue = send_queue + + def recv(self): + data = self.recv_queue.get() + if isinstance(data, Exception): + raise data + return data + + def send(self, data, opcode): + self.send_queue.put_nowait((data, opcode)) + + def close(self): + pass + + +class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler): + def do_PUT(self): + length = int(self.headers['Content-Length']) + self.rfile.read(length) + self.send_response(201, "Created") + self.end_headers() diff --git a/system/athena/tests/test_athenad.py b/system/athena/tests/test_athenad.py new file mode 100644 index 0000000000..99ac3b1c6b --- /dev/null +++ b/system/athena/tests/test_athenad.py @@ -0,0 +1,448 @@ +import pytest +from functools import wraps +import json +import multiprocessing +import os +import requests +import shutil +import time +import threading +import queue +from dataclasses import asdict, replace +from datetime import datetime, timedelta + +from websocket import ABNF +from websocket._exceptions import WebSocketConnectionClosedException + +from cereal import messaging + +from openpilot.common.params import Params +from openpilot.common.timeout import Timeout +from openpilot.system.athena import athenad +from openpilot.system.athena.athenad import MAX_RETRY_COUNT, UPLOAD_SESS, dispatcher +from openpilot.system.athena.tests.helpers import HTTPRequestHandler, MockWebsocket, MockApi, EchoSocket +from openpilot.selfdrive.test.helpers import http_server_context +from openpilot.system.hardware.hw import Paths + + +def seed_athena_server(host, port): + with Timeout(2, 'HTTP Server seeding failed'): + while True: + try: + UPLOAD_SESS.put(f'http://{host}:{port}/qlog.zst', data='', timeout=10) + break + except requests.exceptions.ConnectionError: + time.sleep(0.1) + +def with_upload_handler(func): + @wraps(func) + def wrapper(*args, **kwargs): + end_event = threading.Event() + thread = threading.Thread(target=athenad.upload_handler, args=(end_event,)) + thread.start() + try: + return func(*args, **kwargs) + finally: + end_event.set() + thread.join() + return wrapper + +@pytest.fixture +def mock_create_connection(mocker): + return mocker.patch('openpilot.system.athena.athenad.create_connection') + +@pytest.fixture +def host(): + with http_server_context(handler=HTTPRequestHandler, setup=seed_athena_server) as (host, port): + yield f"http://{host}:{port}" + +class TestAthenadMethods: + @classmethod + def setup_class(cls): + cls.SOCKET_PORT = 45454 + athenad.Api = MockApi + athenad.LOCAL_PORT_WHITELIST = {cls.SOCKET_PORT} + + def setup_method(self): + self.default_params = { + "DongleId": "0000000000000000", + "GithubSshKeys": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC307aE+nuHzTAgaJhzSf5v7ZZQW9gaperjhCmyPyl4PzY7T1mDGenTlVTN7yoVFZ9UfO9oMQqo0n1OwDIiqbIFxqnhrHU0cYfj88rI85m5BEKlNu5RdaVTj1tcbaPpQc5kZEolaI1nDDjzV0lwS7jo5VYDHseiJHlik3HH1SgtdtsuamGR2T80q1SyW+5rHoMOJG73IH2553NnWuikKiuikGHUYBd00K1ilVAK2xSiMWJp55tQfZ0ecr9QjEsJ+J/efL4HqGNXhffxvypCXvbUYAFSddOwXUPo5BTKevpxMtH+2YrkpSjocWA04VnTYFiPG6U4ItKmbLOTFZtPzoez private", # noqa: E501 + "GithubUsername": "commaci", + "AthenadUploadQueue": [], + } + + self.params = Params() + for k, v in self.default_params.items(): + self.params.put(k, v) + self.params.put_bool("GsmMetered", True) + + athenad.upload_queue = queue.PriorityQueue() + athenad.cur_upload_items.clear() + athenad.cancelled_uploads.clear() + + for i in os.listdir(Paths.log_root()): + p = os.path.join(Paths.log_root(), i) + if os.path.isdir(p): + shutil.rmtree(p) + else: + os.unlink(p) + + # *** test helpers *** + + @staticmethod + def _wait_for_upload(): + now = time.monotonic() + while time.monotonic() - now < 5: + if athenad.upload_queue.qsize() == 0: + break + + @staticmethod + def _create_file(file: str, parent: str = None, data: bytes = b'') -> str: + fn = os.path.join(Paths.log_root() if parent is None else parent, file) + os.makedirs(os.path.dirname(fn), exist_ok=True) + with open(fn, 'wb') as f: + f.write(data) + return fn + + + # *** test cases *** + + def test_echo(self): + assert dispatcher["echo"]("bob") == "bob" + + def test_get_message(self): + with pytest.raises(TimeoutError) as _: + dispatcher["getMessage"]("controlsState") + + end_event = multiprocessing.Event() + + pub_sock = messaging.pub_sock("deviceState") + + def send_deviceState(): + while not end_event.is_set(): + msg = messaging.new_message('deviceState') + pub_sock.send(msg.to_bytes()) + time.sleep(0.01) + + p = multiprocessing.Process(target=send_deviceState) + p.start() + time.sleep(0.1) + try: + deviceState = dispatcher["getMessage"]("deviceState") + assert deviceState['deviceState'] + finally: + end_event.set() + p.join() + + def test_list_data_directory(self): + route = '2021-03-29--13-32-47' + segments = [0, 1, 2, 3, 11] + + filenames = ['qlog.zst', 'qcamera.ts', 'rlog.zst', 'fcamera.hevc', 'ecamera.hevc', 'dcamera.hevc'] + files = [f'{route}--{s}/{f}' for s in segments for f in filenames] + for file in files: + self._create_file(file) + + resp = dispatcher["listDataDirectory"]() + assert resp, 'list empty!' + assert len(resp) == len(files) + + resp = dispatcher["listDataDirectory"](f'{route}--123') + assert len(resp) == 0 + + prefix = f'{route}' + expected = list(filter(lambda f: f.startswith(prefix), files)) + resp = dispatcher["listDataDirectory"](prefix) + assert resp, 'list empty!' + assert len(resp) == len(expected) + + prefix = f'{route}--1' + expected = list(filter(lambda f: f.startswith(prefix), files)) + resp = dispatcher["listDataDirectory"](prefix) + assert resp, 'list empty!' + assert len(resp) == len(expected) + + prefix = f'{route}--1/' + expected = list(filter(lambda f: f.startswith(prefix), files)) + resp = dispatcher["listDataDirectory"](prefix) + assert resp, 'list empty!' + assert len(resp) == len(expected) + + prefix = f'{route}--1/q' + expected = list(filter(lambda f: f.startswith(prefix), files)) + resp = dispatcher["listDataDirectory"](prefix) + assert resp, 'list empty!' + assert len(resp) == len(expected) + + def test_strip_extension(self): + # any requested log file with an invalid extension won't return as existing + fn = self._create_file('qlog.bz2') + if fn.endswith('.bz2'): + assert athenad.strip_zst_extension(fn) == fn + + fn = self._create_file('qlog.zst') + if fn.endswith('.zst'): + assert athenad.strip_zst_extension(fn) == fn[:-4] + + @pytest.mark.parametrize("compress", [True, False]) + def test_do_upload(self, host, compress): + # random bytes to ensure rather large object post-compression + fn = self._create_file('qlog', data=os.urandom(10000 * 1024)) + + upload_fn = fn + ('.zst' if compress else '') + item = athenad.UploadItem(path=upload_fn, url="http://localhost:1238", headers={}, created_at=int(time.time()*1000), id='') # noqa: TID251 + with pytest.raises(requests.exceptions.ConnectionError): + athenad._do_upload(item) + + item = athenad.UploadItem(path=upload_fn, url=f"{host}/qlog.zst", headers={}, created_at=int(time.time()*1000), id='') # noqa: TID251 + resp = athenad._do_upload(item) + assert resp.status_code == 201 + + def test_upload_file_to_url(self, host): + fn = self._create_file('qlog.zst') + + resp = dispatcher["uploadFileToUrl"]("qlog.zst", f"{host}/qlog.zst", {}) + assert resp['enqueued'] == 1 + assert 'failed' not in resp + assert {"path": fn, "url": f"{host}/qlog.zst", "headers": {}}.items() <= resp['items'][0].items() + assert resp['items'][0].get('id') is not None + assert athenad.upload_queue.qsize() == 1 + + def test_upload_file_to_url_duplicate(self, host): + self._create_file('qlog.zst') + + url1 = f"{host}/qlog.zst?sig=sig1" + dispatcher["uploadFileToUrl"]("qlog.zst", url1, {}) + + # Upload same file again, but with different signature + url2 = f"{host}/qlog.zst?sig=sig2" + resp = dispatcher["uploadFileToUrl"]("qlog.zst", url2, {}) + assert resp == {'enqueued': 0, 'items': []} + + def test_upload_file_to_url_does_not_exist(self, host): + not_exists_resp = dispatcher["uploadFileToUrl"]("does_not_exist.zst", "http://localhost:1238", {}) + assert not_exists_resp == {'enqueued': 0, 'items': [], 'failed': ['does_not_exist.zst']} + + @with_upload_handler + def test_upload_handler(self, host): + fn = self._create_file('qlog.zst') + item = athenad.UploadItem(path=fn, url=f"{host}/qlog.zst", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) # noqa: TID251 + + athenad.upload_queue.put_nowait(item) + self._wait_for_upload() + time.sleep(0.1) + + # TODO: verify that upload actually succeeded + # TODO: also check that end_event and metered network raises AbortTransferException + assert athenad.upload_queue.qsize() == 0 + + @pytest.mark.parametrize("status,retry", [(500,True), (412,False)]) + @with_upload_handler + def test_upload_handler_retry(self, mocker, host, status, retry): + mock_put = mocker.patch('openpilot.system.athena.athenad.UPLOAD_SESS.put') + mock_put.return_value.__enter__.return_value.status_code = status + fn = self._create_file('qlog.zst') + item = athenad.UploadItem(path=fn, url=f"{host}/qlog.zst", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) # noqa: TID251 + + athenad.upload_queue.put_nowait(item) + self._wait_for_upload() + time.sleep(0.1) + + assert athenad.upload_queue.qsize() == (1 if retry else 0) + + if retry: + assert athenad.upload_queue.get().retry_count == 1 + + @with_upload_handler + def test_upload_handler_timeout(self): + """When an upload times out or fails to connect it should be placed back in the queue""" + fn = self._create_file('qlog.zst') + item = athenad.UploadItem(path=fn, url="http://localhost:44444/qlog.zst", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) # noqa: TID251 + item_no_retry = replace(item, retry_count=MAX_RETRY_COUNT) + + athenad.upload_queue.put_nowait(item_no_retry) + self._wait_for_upload() + time.sleep(0.1) + + # Check that upload with retry count exceeded is not put back + assert athenad.upload_queue.qsize() == 0 + + athenad.upload_queue.put_nowait(item) + self._wait_for_upload() + time.sleep(0.1) + + # Check that upload item was put back in the queue with incremented retry count + assert athenad.upload_queue.qsize() == 1 + assert athenad.upload_queue.get().retry_count == 1 + + @with_upload_handler + def test_cancel_upload(self): + item = athenad.UploadItem(path="qlog.zst", url="http://localhost:44444/qlog.zst", headers={}, + created_at=int(time.time()*1000), id='id', allow_cellular=True) # noqa: TID251 + athenad.upload_queue.put_nowait(item) + dispatcher["cancelUpload"](item.id) + + assert item.id in athenad.cancelled_uploads + + self._wait_for_upload() + time.sleep(0.1) + + assert athenad.upload_queue.qsize() == 0 + assert len(athenad.cancelled_uploads) == 0 + + @with_upload_handler + def test_cancel_expiry(self): + t_future = datetime.now() - timedelta(days=40) + ts = int(t_future.strftime("%s")) * 1000 + + # Item that would time out if actually uploaded + fn = self._create_file('qlog.zst') + item = athenad.UploadItem(path=fn, url="http://localhost:44444/qlog.zst", headers={}, created_at=ts, id='', allow_cellular=True) + + athenad.upload_queue.put_nowait(item) + self._wait_for_upload() + time.sleep(0.1) + + assert athenad.upload_queue.qsize() == 0 + + def test_list_upload_queue_empty(self): + items = dispatcher["listUploadQueue"]() + assert len(items) == 0 + + @with_upload_handler + def test_list_upload_queue_current(self, host: str): + fn = self._create_file('qlog.zst') + item = athenad.UploadItem(path=fn, url=f"{host}/qlog.zst", headers={}, created_at=int(time.time()*1000), id='', allow_cellular=True) # noqa: TID251 + + athenad.upload_queue.put_nowait(item) + self._wait_for_upload() + + items = dispatcher["listUploadQueue"]() + assert len(items) == 1 + assert items[0]['current'] + + def test_list_upload_queue_priority(self): + priorities = (25, 50, 99, 75, 0) + + for i in priorities: + fn = f'qlog_{i}.zst' + fp = self._create_file(fn) + item = athenad.UploadItem( + path=fp, + url=f"http://localhost:44444/{fn}", + headers={}, + created_at=int(time.time()*1000), # noqa: TID251 + id='', + allow_cellular=True, + priority=i + ) + athenad.upload_queue.put_nowait(item) + + for i in sorted(priorities): + assert athenad.upload_queue.get_nowait().priority == i + + def test_list_upload_queue(self): + item = athenad.UploadItem(path="qlog.zst", url="http://localhost:44444/qlog.zst", headers={}, + created_at=int(time.time()*1000), id='id', allow_cellular=True) # noqa: TID251 + athenad.upload_queue.put_nowait(item) + + items = dispatcher["listUploadQueue"]() + assert len(items) == 1 + assert items[0] == asdict(item) + assert not items[0]['current'] + + athenad.cancelled_uploads.add(item.id) + items = dispatcher["listUploadQueue"]() + assert len(items) == 0 + + def test_upload_queue_persistence(self): + item1 = athenad.UploadItem(path="_", url="_", headers={}, created_at=int(time.time()), id='id1') # noqa: TID251 + item2 = athenad.UploadItem(path="_", url="_", headers={}, created_at=int(time.time()), id='id2') # noqa: TID251 + + athenad.upload_queue.put_nowait(item1) + athenad.upload_queue.put_nowait(item2) + + # Ensure canceled items are not persisted + athenad.cancelled_uploads.add(item2.id) + + # serialize item + athenad.UploadQueueCache.cache(athenad.upload_queue) + + # deserialize item + athenad.upload_queue.queue.clear() + athenad.UploadQueueCache.initialize(athenad.upload_queue) + + assert athenad.upload_queue.qsize() == 1 + assert asdict(athenad.upload_queue.queue[-1]) == asdict(item1) + + def test_start_local_proxy(self, mock_create_connection): + end_event = threading.Event() + + ws_recv = queue.Queue() + ws_send = queue.Queue() + mock_ws = MockWebsocket(ws_recv, ws_send) + mock_create_connection.return_value = mock_ws + + echo_socket = EchoSocket(self.SOCKET_PORT) + socket_thread = threading.Thread(target=echo_socket.run) + socket_thread.start() + + athenad.startLocalProxy(end_event, 'ws://localhost:1234', self.SOCKET_PORT) + + ws_recv.put_nowait(b'ping') + try: + recv = ws_send.get(timeout=5) + assert recv == (b'ping', ABNF.OPCODE_BINARY), recv + finally: + # signal websocket close to athenad.ws_proxy_recv + ws_recv.put_nowait(WebSocketConnectionClosedException()) + socket_thread.join() + + def test_get_ssh_authorized_keys(self): + keys = dispatcher["getSshAuthorizedKeys"]() + assert keys == self.default_params["GithubSshKeys"] + + def test_get_github_username(self): + keys = dispatcher["getGithubUsername"]() + assert keys == self.default_params["GithubUsername"] + + def test_get_version(self): + resp = dispatcher["getVersion"]() + keys = ["version", "remote", "branch", "commit"] + assert list(resp.keys()) == keys + for k in keys: + assert isinstance(resp[k], str), f"{k} is not a string" + assert len(resp[k]) > 0, f"{k} has no value" + + def test_jsonrpc_handler(self): + end_event = threading.Event() + thread = threading.Thread(target=athenad.jsonrpc_handler, args=(end_event,)) + thread.daemon = True + thread.start() + try: + # with params + athenad.recv_queue.put_nowait(json.dumps({"method": "echo", "params": ["hello"], "jsonrpc": "2.0", "id": 0})) + resp = athenad.send_queue.get(timeout=3) + assert json.loads(resp) == {'result': 'hello', 'id': 0, 'jsonrpc': '2.0'} + # without params + athenad.recv_queue.put_nowait(json.dumps({"method": "getNetworkType", "jsonrpc": "2.0", "id": 0})) + resp = athenad.send_queue.get(timeout=3) + assert json.loads(resp) == {'result': 1, 'id': 0, 'jsonrpc': '2.0'} + # log forwarding + athenad.recv_queue.put_nowait(json.dumps({'result': {'success': 1}, 'id': 0, 'jsonrpc': '2.0'})) + resp = athenad.log_recv_queue.get(timeout=3) + assert json.loads(resp) == {'result': {'success': 1}, 'id': 0, 'jsonrpc': '2.0'} + finally: + end_event.set() + thread.join() + + def test_get_logs_to_send_sorted(self): + fl = list() + for i in range(10): + file = f'swaglog.{i:010}' + self._create_file(file, Paths.swaglog_root()) + fl.append(file) + + # ensure the list is all logs except most recent + sl = athenad.get_logs_to_send_sorted() + assert sl == fl[:-1] diff --git a/system/athena/tests/test_athenad_ping.py b/system/athena/tests/test_athenad_ping.py new file mode 100644 index 0000000000..8ff1e37a5d --- /dev/null +++ b/system/athena/tests/test_athenad_ping.py @@ -0,0 +1,102 @@ +import pytest +import subprocess +import threading +import time +from typing import cast + +from openpilot.common.params import Params +from openpilot.common.timeout import Timeout +from openpilot.system.athena import athenad +from openpilot.system.manager.helpers import write_onroad_params +from openpilot.system.hardware import TICI + +TIMEOUT_TOLERANCE = 20 # seconds + + +def wifi_radio(on: bool) -> None: + if not TICI: + return + print(f"wifi {'on' if on else 'off'}") + subprocess.run(["nmcli", "radio", "wifi", "on" if on else "off"], check=True) + + +class TestAthenadPing: + params: Params + dongle_id: str + + athenad: threading.Thread + exit_event: threading.Event + + def _get_ping_time(self) -> str | None: + return cast(str | None, self.params.get("LastAthenaPingTime")) + + def _clear_ping_time(self) -> None: + self.params.remove("LastAthenaPingTime") + + def _received_ping(self) -> bool: + return self._get_ping_time() is not None + + @classmethod + def teardown_class(cls) -> None: + wifi_radio(True) + + def setup_method(self) -> None: + self.params = Params() + self.dongle_id = self.params.get("DongleId") + + wifi_radio(True) + self._clear_ping_time() + + self.exit_event = threading.Event() + self.athenad = threading.Thread(target=athenad.main, args=(self.exit_event,)) + + def teardown_method(self) -> None: + if self.athenad.is_alive(): + self.exit_event.set() + self.athenad.join() + + def assertTimeout(self, reconnect_time: float, subtests, mocker) -> None: + self.athenad.start() + + mock_create_connection = mocker.patch('openpilot.system.athena.athenad.create_connection', + new_callable=lambda: mocker.MagicMock(wraps=athenad.create_connection)) + + time.sleep(1) + mock_create_connection.assert_called_once() + mock_create_connection.reset_mock() + + # check normal behavior, server pings on connection + with subtests.test("Wi-Fi: receives ping"), Timeout(70, "no ping received"): + while not self._received_ping(): + time.sleep(0.1) + print("ping received") + + mock_create_connection.assert_not_called() + + # websocket should attempt reconnect after short time + with subtests.test("LTE: attempt reconnect"): + wifi_radio(False) + print("waiting for reconnect attempt") + start_time = time.monotonic() + with Timeout(reconnect_time, "no reconnect attempt"): + while not mock_create_connection.called: + time.sleep(0.1) + print(f"reconnect attempt after {time.monotonic() - start_time:.2f}s") + + self._clear_ping_time() + + # check ping received after reconnect + with subtests.test("LTE: receives ping"), Timeout(70, "no ping received"): + while not self._received_ping(): + time.sleep(0.1) + print("ping received") + + @pytest.mark.skipif(not TICI, reason="only run on desk") + def test_offroad(self, subtests, mocker) -> None: + write_onroad_params(False, self.params) + self.assertTimeout(60 + TIMEOUT_TOLERANCE, subtests, mocker) # based using TCP keepalive settings + + @pytest.mark.skipif(not TICI, reason="only run on desk") + def test_onroad(self, subtests, mocker) -> None: + write_onroad_params(True, self.params) + self.assertTimeout(21 + TIMEOUT_TOLERANCE, subtests, mocker) diff --git a/system/athena/tests/test_registration.py b/system/athena/tests/test_registration.py new file mode 100644 index 0000000000..c20722659a --- /dev/null +++ b/system/athena/tests/test_registration.py @@ -0,0 +1,76 @@ +import json +from Crypto.PublicKey import RSA +from pathlib import Path + +from openpilot.common.params import Params +from openpilot.system.athena.registration import register, UNREGISTERED_DONGLE_ID +from openpilot.system.athena.tests.helpers import MockResponse +from openpilot.system.hardware.hw import Paths + + +class TestRegistration: + + def setup_method(self): + # clear params and setup key paths + self.params = Params() + + persist_dir = Path(Paths.persist_root()) / "comma" + persist_dir.mkdir(parents=True, exist_ok=True) + + self.priv_key = persist_dir / "id_rsa" + self.pub_key = persist_dir / "id_rsa.pub" + self.dongle_id = persist_dir / "dongle_id" + + def _generate_keys(self): + self.pub_key.touch() + k = RSA.generate(2048) + with open(self.priv_key, "wb") as f: + f.write(k.export_key()) + with open(self.pub_key, "wb") as f: + f.write(k.publickey().export_key()) + + def test_valid_cache(self, mocker): + # if all params are written, return the cached dongle id. + # should work with a dongle ID on either /persist/ or normal params + self._generate_keys() + + dongle = "DONGLE_ID_123" + m = mocker.patch("openpilot.system.athena.registration.api_get", autospec=True) + for persist, params in [(True, True), (True, False), (False, True)]: + self.params.put("DongleId", dongle if params else "") + with open(self.dongle_id, "w") as f: + f.write(dongle if persist else "") + assert register() == dongle + assert not m.called + + def test_no_keys(self, mocker): + # missing pubkey + m = mocker.patch("openpilot.system.athena.registration.api_get", autospec=True) + dongle = register() + assert m.call_count == 0 + assert dongle == UNREGISTERED_DONGLE_ID + assert self.params.get("DongleId") == dongle + + def test_missing_cache(self, mocker): + # keys exist but no dongle id + self._generate_keys() + m = mocker.patch("openpilot.system.athena.registration.api_get", autospec=True) + dongle = "DONGLE_ID_123" + m.return_value = MockResponse(json.dumps({'dongle_id': dongle}), 200) + assert register() == dongle + assert m.call_count == 1 + + # call again, shouldn't hit the API this time + assert register() == dongle + assert m.call_count == 1 + assert self.params.get("DongleId") == dongle + + def test_unregistered(self, mocker): + # keys exist, but unregistered + self._generate_keys() + m = mocker.patch("openpilot.system.athena.registration.api_get", autospec=True) + m.return_value = MockResponse(None, 402) + dongle = register() + assert m.call_count == 1 + assert dongle == UNREGISTERED_DONGLE_ID + assert self.params.get("DongleId") == dongle diff --git a/system/camerad/SConscript b/system/camerad/SConscript new file mode 100644 index 0000000000..e288c6d8b0 --- /dev/null +++ b/system/camerad/SConscript @@ -0,0 +1,11 @@ +Import('env', 'arch', 'messaging', 'common', 'visionipc') + +libs = [common, 'OpenCL', messaging, visionipc] + +if arch != "Darwin": + camera_obj = env.Object(['cameras/camera_qcom2.cc', 'cameras/camera_common.cc', 'cameras/spectra.cc', + 'cameras/cdm.cc', 'sensors/ox03c10.cc', 'sensors/os04c10.cc']) + env.Program('camerad', ['main.cc', camera_obj], LIBS=libs) + +if GetOption("extras") and arch == "x86_64": + env.Program('test/test_ae_gray', ['test/test_ae_gray.cc', camera_obj], LIBS=libs) diff --git a/system/camerad/__init__.py b/system/camerad/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/camerad/cameras/bps_blobs.h b/system/camerad/cameras/bps_blobs.h new file mode 100644 index 0000000000..54941b8d76 --- /dev/null +++ b/system/camerad/cameras/bps_blobs.h @@ -0,0 +1,30 @@ +#include +#include + + +/* ********************************************************** + THIS FILE IS AUTO-GENERATED, DO NOT EDIT DIRECTLY! + ********************************************************** */ + + +unsigned char bps_cfg[4][768] = { +{ /* placeholder */ }, + {0x3, 0x0, 0x0, 0x0, 0x88, 0x7, 0x0, 0x0, 0xB8, 0x4, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0xB, 0x0, 0x0, 0xB8, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x88, 0x7, 0x0, 0x0, 0xB8, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0xC0, 0x4, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x60, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x3, 0x0, 0x0, 0x0, 0x88, 0x7, 0x0, 0x0, 0xB8, 0x4, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0xB, 0x0, 0x0, 0xB8, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x88, 0x7, 0x0, 0x0, 0xB8, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0xC0, 0x4, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x60, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x3, 0x0, 0x0, 0x0, 0x40, 0x5, 0x0, 0x0, 0xF8, 0x2, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE0, 0x7, 0x0, 0x0, 0xF8, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x40, 0x5, 0x0, 0x0, 0xF8, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x80, 0x5, 0x0, 0x0, 0x80, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, +}; + +unsigned char bps_striping_output[4][0x9a0] = { +{ /* placeholder */ }, + {0x5, 0x0, 0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x5B, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x5B, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x4, 0x5C, 0x2, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x70, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0x89, 0x23, 0x0, 0x1, 0x0, 0x0, 0x0, 0xCC, 0x5, 0x87, 0x7, 0x0, 0x0, 0x0, 0x0, 0xD0, 0x5, 0x87, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x2, 0xA4, 0xFD, 0x50, 0xB1, 0x9, 0x0, 0x8, 0x0, 0x33, 0x0, 0x8, 0x2, 0xA4, 0xFD, 0x50, 0xB1, 0x9, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x2, 0xA6, 0xFD, 0x68, 0xC0, 0x9, 0x0, 0x8, 0x0, 0x34, 0x0, 0xD0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1C, 0x8, 0x0, 0x14, 0x4, 0xD3, 0x5, 0x0, 0x0, 0x0, 0x0, 0x18, 0x4, 0xCF, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x0, 0xA4, 0xFD, 0x10, 0xAA, 0x5, 0x0, 0x8, 0x0, 0x33, 0x0, 0x50, 0x0, 0xA4, 0xFD, 0x10, 0xAA, 0x5, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x0, 0xA6, 0xFD, 0x88, 0xA4, 0x5, 0x0, 0x8, 0x0, 0x34, 0x0, 0x18, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1C, 0x8, 0x0, 0x5C, 0x2, 0x1B, 0x4, 0x0, 0x0, 0x0, 0x0, 0x60, 0x2, 0x17, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x98, 0xFE, 0xA4, 0xFD, 0x50, 0x8B, 0x7, 0x0, 0x8, 0x0, 0x33, 0x0, 0x98, 0xFE, 0xA4, 0xFD, 0x50, 0x8B, 0x7, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9E, 0xFE, 0xA6, 0xFD, 0x28, 0x71, 0x7, 0x0, 0x8, 0x0, 0x34, 0x0, 0x60, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1C, 0x8, 0x0, 0xC0, 0x0, 0x63, 0x2, 0x0, 0x0, 0x0, 0x0, 0xC4, 0x0, 0x5F, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0x9C, 0x1, 0xCE, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFC, 0xFC, 0xA4, 0xFD, 0x20, 0xA9, 0xE, 0x0, 0x8, 0x0, 0x33, 0x0, 0xFC, 0xFC, 0xA4, 0xFD, 0x20, 0xA9, 0xE, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xFD, 0xA6, 0xFD, 0xA8, 0x7B, 0xE, 0x0, 0x8, 0x0, 0x34, 0x0, 0xC4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x98, 0x7, 0x0, 0x0, 0x0, 0xC7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xC4, 0x0, 0x62, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0xFC, 0xA4, 0xFD, 0x20, 0xBF, 0x13, 0x0, 0x8, 0x0, 0x33, 0x0, 0x3C, 0xFC, 0xA4, 0xFD, 0x20, 0xBF, 0x13, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0xFC, 0xA6, 0xFD, 0xA8, 0xA6, 0x13, 0x0, 0x8, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE0, 0x9C, 0x3, 0x0, 0x20, 0x4, 0x1, 0x0, 0x5D, 0x59, 0xAB, 0x0, 0xC8, 0x8C, 0xFD, 0xF4, 0x3, 0x0, 0x0, 0x0, 0xB8, 0x13, 0xFD, 0xFF, 0xAC, 0x5F, 0x8C, 0xF5, 0x0, 0x20, 0x4E, 0x0, 0xAB, 0xAA, 0xAA, 0xAA, 0x40, 0x69, 0xFD, 0xF4, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38, 0x6B, 0x8B, 0xF5, 0x11, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x9F, 0x9, 0x0, 0x0, 0xB8, 0x2B, 0x6B, 0x15, 0xC0, 0x6A, 0x8C, 0xF5, 0x0, 0x0, 0x0, 0x0, 0xB8, 0x13, 0xFD, 0xFF, 0x2A, 0x5, 0x1, 0x0, 0xC0, 0x13, 0xFD, 0xFF, 0x2C, 0x14, 0xFD, 0xFF, 0x14, 0x14, 0xFD, 0xFF, 0xCC, 0xE8, 0x89, 0xF5, 0xC0, 0x13, 0xFD, 0xFF, 0x64, 0x6A, 0x8C, 0xF5, 0x3, 0x0, 0x0, 0x0, 0xA0, 0x6B, 0x8B, 0xF5, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x8, 0x69, 0x8C, 0xF5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0x6A, 0x8C, 0xF5, 0x8, 0x69, 0x8C, 0xF5, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0x9, 0x0, 0x0, 0xF8, 0xB2, 0xFD, 0xF4, 0x50, 0x35, 0x8C, 0xF5, 0xD0, 0x14, 0xC1, 0xF4, 0x1, 0xD0, 0x3B, 0xF5, 0x64, 0x1F, 0xFD, 0xFF, 0xD0, 0xAD, 0x4, 0xF5, 0x2C, 0x30, 0x1, 0x0, 0x0, 0x10, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC, 0x30, 0x1, 0x0, 0xD0, 0x14, 0xC1, 0xF4, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1F, 0xFD, 0xFF, 0x3C, 0x23, 0xFD, 0x34, 0x31, 0x32, 0x31, 0x36, 0xA0, 0x6B, 0x8B, 0xF5, 0x60, 0x14, 0xFD, 0xFF, 0x0, 0x30, 0x1, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1F, 0xFD, 0xFF, 0x3C, 0x23, 0xFD, 0xFF, 0xC0, 0xDC, 0x1, 0xF5, 0x4C, 0x0, 0x0, 0x0, 0x54, 0x14, 0xFD, 0xFF, 0x50, 0x1D, 0x1, 0x0, 0x30, 0x14, 0x1, 0x0, 0x98, 0x1D, 0x1, 0x0, 0x0, 0xA1, 0x0, 0x0, 0x0, 0xA1, 0x0, 0x0, 0x98, 0x1D, 0x1, 0x0, 0x6C, 0x1F, 0xFD, 0xFF, 0x64, 0x1F, 0xFD, 0xFF, 0x68, 0x1F, 0xFD, 0xFF, 0x0, 0x0, 0x0, 0x0}, + {0x5, 0x0, 0x6, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x5B, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x5B, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x4, 0x5C, 0x2, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x70, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0x89, 0x23, 0x0, 0x1, 0x0, 0x0, 0x0, 0xCC, 0x5, 0x87, 0x7, 0x0, 0x0, 0x0, 0x0, 0xD0, 0x5, 0x87, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x2, 0xA4, 0xFD, 0x50, 0xB1, 0x9, 0x0, 0x8, 0x0, 0x33, 0x0, 0x8, 0x2, 0xA4, 0xFD, 0x50, 0xB1, 0x9, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x2, 0xA6, 0xFD, 0x68, 0xC0, 0x9, 0x0, 0x8, 0x0, 0x34, 0x0, 0xD0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1C, 0x8, 0x0, 0x14, 0x4, 0xD3, 0x5, 0x0, 0x0, 0x0, 0x0, 0x18, 0x4, 0xCF, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x0, 0xA4, 0xFD, 0x10, 0xAA, 0x5, 0x0, 0x8, 0x0, 0x33, 0x0, 0x50, 0x0, 0xA4, 0xFD, 0x10, 0xAA, 0x5, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x0, 0xA6, 0xFD, 0x88, 0xA4, 0x5, 0x0, 0x8, 0x0, 0x34, 0x0, 0x18, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1C, 0x8, 0x0, 0x5C, 0x2, 0x1B, 0x4, 0x0, 0x0, 0x0, 0x0, 0x60, 0x2, 0x17, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x98, 0xFE, 0xA4, 0xFD, 0x50, 0x8B, 0x7, 0x0, 0x8, 0x0, 0x33, 0x0, 0x98, 0xFE, 0xA4, 0xFD, 0x50, 0x8B, 0x7, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9E, 0xFE, 0xA6, 0xFD, 0x28, 0x71, 0x7, 0x0, 0x8, 0x0, 0x34, 0x0, 0x60, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1C, 0x8, 0x0, 0xC0, 0x0, 0x63, 0x2, 0x0, 0x0, 0x0, 0x0, 0xC4, 0x0, 0x5F, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x9B, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0x9C, 0x1, 0xCE, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFC, 0xFC, 0xA4, 0xFD, 0x20, 0xA9, 0xE, 0x0, 0x8, 0x0, 0x33, 0x0, 0xFC, 0xFC, 0xA4, 0xFD, 0x20, 0xA9, 0xE, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xFD, 0xA6, 0xFD, 0xA8, 0x7B, 0xE, 0x0, 0x8, 0x0, 0x34, 0x0, 0xC4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x98, 0x7, 0x0, 0x0, 0x0, 0xC7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xC4, 0x0, 0x62, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3C, 0xFC, 0xA4, 0xFD, 0x20, 0xBF, 0x13, 0x0, 0x8, 0x0, 0x33, 0x0, 0x3C, 0xFC, 0xA4, 0xFD, 0x20, 0xBF, 0x13, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3E, 0xFC, 0xA6, 0xFD, 0xA8, 0xA6, 0x13, 0x0, 0x8, 0x0, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE0, 0x9C, 0x3, 0x0, 0x20, 0x4, 0x1, 0x0, 0xA0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x60, 0x5D, 0x1, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0xFC, 0x57, 0x12, 0xF5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x12, 0xF5, 0x0, 0x0, 0x0, 0x0, 0x9F, 0x9, 0x0, 0x0, 0x5E, 0x0, 0x0, 0x0, 0x5F, 0x0, 0x0, 0x0, 0x6E, 0x0, 0x0, 0x0, 0x77, 0x0, 0x0, 0x0, 0x7C, 0x0, 0x0, 0x0, 0x35, 0x1, 0x0, 0x0, 0x26, 0x0, 0x0, 0x0, 0xA4, 0x61, 0x5D, 0x1, 0x58, 0x3, 0x0, 0x0, 0xC0, 0x13, 0xFD, 0xFF, 0x64, 0x6A, 0x8C, 0xF5, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x12, 0xF5, 0x9F, 0x9, 0x0, 0x0, 0xA0, 0x9, 0x0, 0x0, 0xFC, 0x57, 0x12, 0xF5, 0x33, 0x1, 0x0, 0x0, 0xD0, 0x14, 0xC1, 0xF4, 0x1, 0xD0, 0x3B, 0xF5, 0x64, 0x1F, 0xFD, 0xFF, 0xD0, 0xAD, 0x4, 0xF5, 0x2C, 0x30, 0x1, 0x0, 0x0, 0x10, 0x0, 0x0, 0x2C, 0x0, 0x0, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x27, 0x5E, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x31, 0x32, 0x31, 0x36, 0x10, 0x20, 0xFD, 0xFF, 0x60, 0x14, 0xFD, 0xFF, 0x0, 0x30, 0x1, 0x0, 0xA0, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4C, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1F, 0xFD, 0xFF, 0x3C, 0x23, 0xFD, 0xFF, 0xC0, 0xDC, 0x1, 0xF5, 0x0, 0x30, 0x1, 0x0, 0x54, 0x14, 0xFD, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x30, 0x14, 0x1, 0x0, 0x98, 0x1D, 0x1, 0x0, 0x0, 0xA1, 0x0, 0x0, 0x0, 0xA1, 0x0, 0x0, 0x98, 0x1D, 0x1, 0x0, 0x6C, 0x1F, 0xFD, 0xFF, 0x64, 0x1F, 0xFD, 0xFF, 0x68, 0x1F, 0xFD, 0xFF, 0x0, 0x0, 0x0, 0x0}, + {0x4, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0xFF, 0xFF, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0x7B, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0x7B, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF7, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xF8, 0x2, 0x7C, 0x1, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x2, 0x0, 0x70, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x0, 0xA4, 0xFD, 0x10, 0xAA, 0x5, 0x0, 0x8, 0x0, 0x33, 0x0, 0x50, 0x0, 0xA4, 0xFD, 0x10, 0xAA, 0x5, 0x0, 0x8, 0x0, 0x33, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x56, 0x0, 0xA6, 0xFD, 0x88, 0xA4, 0x5, 0x0, 0x8, 0x0, 0x34, 0x0, 0x18, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x0, 0x0, 0x0, 0x78, 0x14, 0x5E, 0x1, 0xB8, 0x5D, 0x12, 0xF5, 0xDC, 0x3B, 0x12, 0xF5, 0x24, 0x0, 0x0, 0x0, 0xFC, 0xF9, 0x3, 0xF5, 0x0, 0x96, 0xF, 0x0, 0x1, 0x5, 0x0, 0x0, 0x84, 0x3, 0x3F, 0x5, 0x0, 0x0, 0x0, 0x0, 0x88, 0x3, 0x3F, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE4, 0x0, 0x84, 0xFE, 0x20, 0xFF, 0x2, 0x0, 0x7, 0x0, 0x38, 0x0, 0xE4, 0x0, 0x84, 0xFE, 0x20, 0xFF, 0x2, 0x0, 0x7, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xEA, 0x0, 0x86, 0xFE, 0x8, 0x4, 0x3, 0x0, 0x7, 0x0, 0x38, 0x0, 0x88, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1A, 0x5, 0x0, 0xCC, 0x1, 0x8B, 0x3, 0x0, 0x0, 0x0, 0x0, 0xD0, 0x1, 0x87, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0xB7, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xB8, 0x1, 0xDC, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2C, 0xFF, 0x84, 0xFE, 0xA0, 0xE3, 0x2, 0x0, 0x7, 0x0, 0x38, 0x0, 0x2C, 0xFF, 0x84, 0xFE, 0xA0, 0xE3, 0x2, 0x0, 0x7, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x32, 0xFF, 0x86, 0xFE, 0xE8, 0xD3, 0x2, 0x0, 0x7, 0x0, 0x38, 0x0, 0xD0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x1A, 0x5, 0x0, 0xC0, 0x0, 0xD3, 0x1, 0x0, 0x0, 0x0, 0x0, 0xC4, 0x0, 0xCF, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x1, 0x0, 0x0, 0xB, 0x1, 0x0, 0x0, 0xB, 0x1, 0x0, 0x0, 0xB, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0x1, 0x0, 0x0, 0xB, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xC, 0x1, 0x86, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0xFE, 0x84, 0xFE, 0x10, 0xB8, 0x5, 0x0, 0x7, 0x0, 0x38, 0x0, 0x20, 0xFE, 0x84, 0xFE, 0x10, 0xB8, 0x5, 0x0, 0x7, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x26, 0xFE, 0x86, 0xFE, 0xC8, 0x9B, 0x5, 0x0, 0x7, 0x0, 0x38, 0x0, 0xC4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xA0, 0x1B, 0x3, 0x0, 0x0, 0x0, 0xC7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xB, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0xC3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x1, 0x0, 0xC4, 0x0, 0x62, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0xFD, 0x84, 0xFE, 0x10, 0x18, 0x9, 0x0, 0x7, 0x0, 0x38, 0x0, 0x60, 0xFD, 0x84, 0xFE, 0x10, 0x18, 0x9, 0x0, 0x7, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0xFD, 0x86, 0xFE, 0xA8, 0x7, 0x9, 0x0, 0x7, 0x0, 0x38, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xE0, 0x45, 0x2, 0x0}, +}; + +unsigned char bps_settings[4][684] = { +{ /* placeholder */ }, + {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, + {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, +}; + diff --git a/system/camerad/cameras/camera_common.cc b/system/camerad/cameras/camera_common.cc new file mode 100644 index 0000000000..1f6ad9b4be --- /dev/null +++ b/system/camerad/cameras/camera_common.cc @@ -0,0 +1,114 @@ +#include "system/camerad/cameras/camera_common.h" + +#include +#include + +#include "common/swaglog.h" +#include "system/camerad/cameras/spectra.h" + + +void CameraBuf::init(cl_device_id device_id, cl_context context, SpectraCamera *cam, VisionIpcServer * v, int frame_cnt, VisionStreamType type) { + vipc_server = v; + stream_type = type; + frame_buf_count = frame_cnt; + + const SensorInfo *sensor = cam->sensor.get(); + + // RAW frames from ISP + if (cam->cc.output_type != ISP_IFE_PROCESSED) { + camera_bufs_raw = std::make_unique(frame_buf_count); + + const int raw_frame_size = (sensor->frame_height + sensor->extra_height) * sensor->frame_stride; + for (int i = 0; i < frame_buf_count; i++) { + camera_bufs_raw[i].allocate(raw_frame_size); + camera_bufs_raw[i].init_cl(device_id, context); + } + LOGD("allocated %d CL buffers", frame_buf_count); + } + + // the encoder HW tells us the size it wants after setting it up. + // TODO: VENUS_BUFFER_SIZE should give the size, but it's too small. dependent on encoder settings? + size_t nv12_size = (out_img_width <= 1344 ? 2900 : 2346)*cam->stride; + + vipc_server->create_buffers_with_sizes(stream_type, VIPC_BUFFER_COUNT, out_img_width, out_img_height, nv12_size, cam->stride, cam->uv_offset); + LOGD("created %d YUV vipc buffers with size %dx%d", VIPC_BUFFER_COUNT, cam->stride, cam->y_height); +} + +CameraBuf::~CameraBuf() { + if (camera_bufs_raw != nullptr) { + for (int i = 0; i < frame_buf_count; i++) { + camera_bufs_raw[i].free(); + } + } +} + +void CameraBuf::sendFrameToVipc() { + assert(cur_buf_idx >=0 && cur_buf_idx < frame_buf_count); + + if (camera_bufs_raw) { + cur_camera_buf = &camera_bufs_raw[cur_buf_idx]; + } + + cur_yuv_buf = vipc_server->get_buffer(stream_type, cur_buf_idx); + + VisionIpcBufExtra extra = { + cur_frame_data.frame_id, + cur_frame_data.timestamp_sof, + cur_frame_data.timestamp_eof, + }; + cur_yuv_buf->set_frame_id(cur_frame_data.frame_id); + vipc_server->send(cur_yuv_buf, &extra); +} + +// common functions + +kj::Array get_raw_frame_image(const CameraBuf *b) { + const uint8_t *dat = (const uint8_t *)b->cur_camera_buf->addr; + + kj::Array frame_image = kj::heapArray(b->cur_camera_buf->len); + uint8_t *resized_dat = frame_image.begin(); + + memcpy(resized_dat, dat, b->cur_camera_buf->len); + + return kj::mv(frame_image); +} + +float calculate_exposure_value(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip) { + int lum_med; + uint32_t lum_binning[256] = {0}; + const uint8_t *pix_ptr = b->cur_yuv_buf->y; + + unsigned int lum_total = 0; + for (int y = ae_xywh.y; y < ae_xywh.y + ae_xywh.h; y += y_skip) { + for (int x = ae_xywh.x; x < ae_xywh.x + ae_xywh.w; x += x_skip) { + uint8_t lum = pix_ptr[(y * b->out_img_width) + x]; + lum_binning[lum]++; + lum_total += 1; + } + } + + // Find mean lumimance value + unsigned int lum_cur = 0; + for (lum_med = 255; lum_med >= 0; lum_med--) { + lum_cur += lum_binning[lum_med]; + + if (lum_cur >= lum_total / 2) { + break; + } + } + + return lum_med / 256.0; +} + +int open_v4l_by_name_and_index(const char name[], int index, int flags) { + for (int v4l_index = 0; /**/; ++v4l_index) { + std::string v4l_name = util::read_file(util::string_format("/sys/class/video4linux/v4l-subdev%d/name", v4l_index)); + if (v4l_name.empty()) return -1; + if (v4l_name.find(name) == 0) { + if (index == 0) { + return HANDLE_EINTR(open(util::string_format("/dev/v4l-subdev%d", v4l_index).c_str(), flags)); + } + index--; + } + } +} diff --git a/system/camerad/cameras/camera_common.h b/system/camerad/cameras/camera_common.h new file mode 100644 index 0000000000..c26859cbc4 --- /dev/null +++ b/system/camerad/cameras/camera_common.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +#include "cereal/messaging/messaging.h" +#include "msgq/visionipc/visionipc_server.h" +#include "common/util.h" + + +const int VIPC_BUFFER_COUNT = 18; + +typedef struct FrameMetadata { + uint32_t frame_id; + uint32_t request_id; + uint64_t timestamp_sof; + uint64_t timestamp_eof; + float processing_time; +} FrameMetadata; + +class SpectraCamera; + +class CameraBuf { +private: + int frame_buf_count; + +public: + VisionIpcServer *vipc_server; + VisionStreamType stream_type; + + int cur_buf_idx; + FrameMetadata cur_frame_data; + VisionBuf *cur_yuv_buf; + VisionBuf *cur_camera_buf; + std::unique_ptr camera_bufs_raw; + uint32_t out_img_width, out_img_height; + + CameraBuf() = default; + ~CameraBuf(); + void init(cl_device_id device_id, cl_context context, SpectraCamera *cam, VisionIpcServer * v, int frame_cnt, VisionStreamType type); + void sendFrameToVipc(); +}; + +void camerad_thread(); +kj::Array get_raw_frame_image(const CameraBuf *b); +float calculate_exposure_value(const CameraBuf *b, Rect ae_xywh, int x_skip, int y_skip); +int open_v4l_by_name_and_index(const char name[], int index = 0, int flags = O_RDWR | O_NONBLOCK); diff --git a/system/camerad/cameras/camera_qcom2.cc b/system/camerad/cameras/camera_qcom2.cc new file mode 100644 index 0000000000..85f358977c --- /dev/null +++ b/system/camerad/cameras/camera_qcom2.cc @@ -0,0 +1,323 @@ +#include "system/camerad/cameras/camera_common.h" +#include "system/camerad/cameras/spectra.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __TICI__ +#include "CL/cl_ext_qcom.h" +#else +#define CL_PRIORITY_HINT_HIGH_QCOM NULL +#define CL_CONTEXT_PRIORITY_HINT_QCOM NULL +#endif + +#include "media/cam_sensor_cmn_header.h" + +#include "common/clutil.h" +#include "common/params.h" +#include "common/swaglog.h" + + +ExitHandler do_exit; + +// for debugging +const bool env_debug_frames = getenv("DEBUG_FRAMES") != nullptr; +const bool env_log_raw_frames = getenv("LOG_RAW_FRAMES") != nullptr; +const bool env_ctrl_exp_from_params = getenv("CTRL_EXP_FROM_PARAMS") != nullptr; + + +class CameraState { +public: + SpectraCamera camera; + int exposure_time = 5; + bool dc_gain_enabled = false; + int dc_gain_weight = 0; + int gain_idx = 0; + float analog_gain_frac = 0; + + float cur_ev[3] = {}; + float best_ev_score = 0; + int new_exp_g = 0; + int new_exp_t = 0; + + Rect ae_xywh = {}; + float measured_grey_fraction = 0; + float target_grey_fraction = 0.3; + + float fl_pix = 0; + std::unique_ptr pm; + + CameraState(SpectraMaster *master, const CameraConfig &config) : camera(master, config) {}; + ~CameraState(); + void init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx); + void update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain); + void set_camera_exposure(float grey_frac); + void set_exposure_rect(); + void sendState(); + + float get_gain_factor() const { + return (1 + dc_gain_weight * (camera.sensor->dc_gain_factor-1) / camera.sensor->dc_gain_max_weight); + } +}; + +void CameraState::init(VisionIpcServer *v, cl_device_id device_id, cl_context ctx) { + camera.camera_open(v, device_id, ctx); + + if (!camera.enabled) return; + + fl_pix = camera.cc.focal_len / camera.sensor->pixel_size_mm / camera.sensor->out_scale; + set_exposure_rect(); + + dc_gain_weight = camera.sensor->dc_gain_min_weight; + gain_idx = camera.sensor->analog_gain_rec_idx; + cur_ev[0] = cur_ev[1] = cur_ev[2] = get_gain_factor() * camera.sensor->sensor_analog_gains[gain_idx] * exposure_time; + + pm = std::make_unique(std::vector{camera.cc.publish_name}); +} + +CameraState::~CameraState() {} + +void CameraState::set_exposure_rect() { + // set areas for each camera, shouldn't be changed + std::vector> ae_targets = { + // (Rect, F) + std::make_pair((Rect){96, 250, 1734, 524}, 567.0), // wide + std::make_pair((Rect){96, 160, 1734, 986}, 2648.0), // road + std::make_pair((Rect){96, 242, 1736, 906}, 567.0) // driver + }; + int h_ref = 1208; + /* + exposure target intrinsics is + [ + [F, 0, 0.5*ae_xywh[2]] + [0, F, 0.5*H-ae_xywh[1]] + [0, 0, 1] + ] + */ + auto ae_target = ae_targets[camera.cc.camera_num]; + Rect xywh_ref = ae_target.first; + float fl_ref = ae_target.second; + + ae_xywh = (Rect){ + std::max(0, (int)camera.buf.out_img_width / 2 - (int)(fl_pix / fl_ref * xywh_ref.w / 2)), + std::max(0, (int)camera.buf.out_img_height / 2 - (int)(fl_pix / fl_ref * (h_ref / 2 - xywh_ref.y))), + std::min((int)(fl_pix / fl_ref * xywh_ref.w), (int)camera.buf.out_img_width / 2 + (int)(fl_pix / fl_ref * xywh_ref.w / 2)), + std::min((int)(fl_pix / fl_ref * xywh_ref.h), (int)camera.buf.out_img_height / 2 + (int)(fl_pix / fl_ref * (h_ref / 2 - xywh_ref.y))) + }; +} + +void CameraState::update_exposure_score(float desired_ev, int exp_t, int exp_g_idx, float exp_gain) { + float score = camera.sensor->getExposureScore(desired_ev, exp_t, exp_g_idx, exp_gain, gain_idx); + if (score < best_ev_score) { + new_exp_t = exp_t; + new_exp_g = exp_g_idx; + best_ev_score = score; + } +} + +void CameraState::set_camera_exposure(float grey_frac) { + if (!camera.enabled) return; + std::vector target_grey_minimums = {0.1, 0.1, 0.125}; // wide, road, driver + + const float dt = 0.05; + + const float ts_grey = 10.0; + const float ts_ev = 0.05; + + const float k_grey = (dt / ts_grey) / (1.0 + dt / ts_grey); + const float k_ev = (dt / ts_ev) / (1.0 + dt / ts_ev); + + // It takes 3 frames for the commanded exposure settings to take effect. The first frame is already started by the time + // we reach this function, the other 2 are due to the register buffering in the sensor. + // Therefore we use the target EV from 3 frames ago, the grey fraction that was just measured was the result of that control action. + // TODO: Lower latency to 2 frames, by using the histogram outputted by the sensor we can do AE before the debayering is complete + + const auto &sensor = camera.sensor; + // Offset idx by one to not get stuck in self loop + const float cur_ev_ = cur_ev[(camera.buf.cur_frame_data.frame_id - 1) % 3] * sensor->ev_scale; + + // Scale target grey between min and 0.4 depending on lighting conditions + float new_target_grey = std::clamp(0.4 - 0.3 * log2(1.0 + sensor->target_grey_factor*cur_ev_) / log2(6000.0), target_grey_minimums[camera.cc.camera_num], 0.4); + float target_grey = (1.0 - k_grey) * target_grey_fraction + k_grey * new_target_grey; + + float desired_ev = std::clamp(cur_ev_ / sensor->ev_scale * target_grey / grey_frac, sensor->min_ev, sensor->max_ev); + float k = (1.0 - k_ev) / 3.0; + desired_ev = (k * cur_ev[0]) + (k * cur_ev[1]) + (k * cur_ev[2]) + (k_ev * desired_ev); + + best_ev_score = 1e6; + new_exp_g = 0; + new_exp_t = 0; + + // Hysteresis around high conversion gain + // We usually want this on since it results in lower noise, but turn off in very bright day scenes + bool enable_dc_gain = dc_gain_enabled; + if (!enable_dc_gain && target_grey < sensor->dc_gain_on_grey) { + enable_dc_gain = true; + dc_gain_weight = sensor->dc_gain_min_weight; + } else if (enable_dc_gain && target_grey > sensor->dc_gain_off_grey) { + enable_dc_gain = false; + dc_gain_weight = sensor->dc_gain_max_weight; + } + + if (enable_dc_gain && dc_gain_weight < sensor->dc_gain_max_weight) {dc_gain_weight += 1;} + if (!enable_dc_gain && dc_gain_weight > sensor->dc_gain_min_weight) {dc_gain_weight -= 1;} + + std::string gain_bytes, time_bytes; + if (env_ctrl_exp_from_params) { + static Params params; + gain_bytes = params.get("CameraDebugExpGain"); + time_bytes = params.get("CameraDebugExpTime"); + } + + if (gain_bytes.size() > 0 && time_bytes.size() > 0) { + // Override gain and exposure time + gain_idx = std::stoi(gain_bytes); + exposure_time = std::stoi(time_bytes); + + new_exp_g = gain_idx; + new_exp_t = exposure_time; + enable_dc_gain = false; + } else { + // Simple brute force optimizer to choose sensor parameters to reach desired EV + int min_g = std::max(gain_idx - 1, sensor->analog_gain_min_idx); + int max_g = std::min(gain_idx + 1, sensor->analog_gain_max_idx); + for (int g = min_g; g <= max_g; g++) { + float gain = sensor->sensor_analog_gains[g] * get_gain_factor(); + + // Compute optimal time for given gain + int t = std::clamp(int(std::round(desired_ev / gain)), sensor->exposure_time_min, sensor->exposure_time_max); + + // Only go below recommended gain when absolutely necessary to not overexpose + if (g < sensor->analog_gain_rec_idx && t > 20 && g < gain_idx) { + continue; + } + + update_exposure_score(desired_ev, t, g, gain); + } + } + + measured_grey_fraction = grey_frac; + target_grey_fraction = target_grey; + + analog_gain_frac = sensor->sensor_analog_gains[new_exp_g]; + gain_idx = new_exp_g; + exposure_time = new_exp_t; + dc_gain_enabled = enable_dc_gain; + + float gain = analog_gain_frac * get_gain_factor(); + cur_ev[camera.buf.cur_frame_data.frame_id % 3] = exposure_time * gain; + + // LOGE("ae - camera %d, cur_t %.5f, sof %.5f, dt %.5f", camera.cc.camera_num, 1e-9 * nanos_since_boot(), 1e-9 * camera.buf.cur_frame_data.timestamp_sof, 1e-9 * (nanos_since_boot() - camera.buf.cur_frame_data.timestamp_sof)); + + auto exp_reg_array = sensor->getExposureRegisters(exposure_time, new_exp_g, dc_gain_enabled); + camera.sensors_i2c(exp_reg_array.data(), exp_reg_array.size(), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, camera.sensor->data_word); +} + +void CameraState::sendState() { + camera.buf.sendFrameToVipc(); + + MessageBuilder msg; + auto framed = (msg.initEvent().*camera.cc.init_camera_state)(); + const FrameMetadata &meta = camera.buf.cur_frame_data; + framed.setFrameId(meta.frame_id); + framed.setRequestId(meta.request_id); + framed.setTimestampEof(meta.timestamp_eof); + framed.setTimestampSof(meta.timestamp_sof); + framed.setIntegLines(exposure_time); + framed.setGain(analog_gain_frac * get_gain_factor()); + framed.setHighConversionGain(dc_gain_enabled); + framed.setMeasuredGreyFraction(measured_grey_fraction); + framed.setTargetGreyFraction(target_grey_fraction); + framed.setProcessingTime(meta.processing_time); + + const float ev = cur_ev[meta.frame_id % 3]; + const float perc = util::map_val(ev, camera.sensor->min_ev, camera.sensor->max_ev, 0.0f, 100.0f); + framed.setExposureValPercent(perc); + framed.setSensor(camera.sensor->image_sensor); + + // Log raw frames for road camera + if (env_log_raw_frames && camera.cc.stream_type == VISION_STREAM_ROAD && meta.frame_id % 100 == 5) { // no overlap with qlog decimation + framed.setImage(get_raw_frame_image(&camera.buf)); + } + + set_camera_exposure(calculate_exposure_value(&camera.buf, ae_xywh, 2, camera.cc.stream_type != VISION_STREAM_DRIVER ? 2 : 4)); + + // Send the message + pm->send(camera.cc.publish_name, msg); +} + +void camerad_thread() { + // TODO: centralize enabled handling + + cl_device_id device_id = cl_get_device_id(CL_DEVICE_TYPE_DEFAULT); + const cl_context_properties props[] = {CL_CONTEXT_PRIORITY_HINT_QCOM, CL_PRIORITY_HINT_HIGH_QCOM, 0}; + cl_context ctx = CL_CHECK_ERR(clCreateContext(props, 1, &device_id, NULL, NULL, &err)); + + VisionIpcServer v("camerad", device_id, ctx); + + // *** initial ISP init *** + SpectraMaster m; + m.init(); + + // *** per-cam init *** + std::vector> cams; + for (const auto &config : ALL_CAMERA_CONFIGS) { + auto cam = std::make_unique(&m, config); + cam->init(&v, device_id, ctx); + cams.emplace_back(std::move(cam)); + } + + v.start_listener(); + + // start devices + LOG("-- Starting devices"); + for (auto &cam : cams) cam->camera.sensors_start(); + + // poll events + LOG("-- Dequeueing Video events"); + while (!do_exit) { + struct pollfd fds[1] = {{.fd = m.video0_fd, .events = POLLPRI}}; + int ret = poll(fds, std::size(fds), 1000); + if (ret < 0) { + if (errno == EINTR || errno == EAGAIN) continue; + LOGE("poll failed (%d - %d)", ret, errno); + break; + } + + if (!(fds[0].revents & POLLPRI)) continue; + + struct v4l2_event ev = {0}; + ret = HANDLE_EINTR(ioctl(fds[0].fd, VIDIOC_DQEVENT, &ev)); + if (ret == 0) { + if (ev.type == V4L_EVENT_CAM_REQ_MGR_EVENT) { + struct cam_req_mgr_message *event_data = (struct cam_req_mgr_message *)ev.u.data; + if (env_debug_frames) { + printf("sess_hdl 0x%6X, link_hdl 0x%6X, frame_id %lu, req_id %lu, timestamp %.2f ms, sof_status %d\n", event_data->session_hdl, event_data->u.frame_msg.link_hdl, + event_data->u.frame_msg.frame_id, event_data->u.frame_msg.request_id, event_data->u.frame_msg.timestamp/1e6, event_data->u.frame_msg.sof_status); + do_exit = do_exit || event_data->u.frame_msg.frame_id > (1*20); + } + + for (auto &cam : cams) { + if (event_data->session_hdl == cam->camera.session_handle) { + if (cam->camera.handle_camera_event(event_data)) { + cam->sendState(); + } + break; + } + } + } else { + LOGE("unhandled event %d\n", ev.type); + } + } else { + LOGE("VIDIOC_DQEVENT failed, errno=%d", errno); + } + } +} diff --git a/system/camerad/cameras/cdm.cc b/system/camerad/cameras/cdm.cc new file mode 100644 index 0000000000..d4ef20c48c --- /dev/null +++ b/system/camerad/cameras/cdm.cc @@ -0,0 +1,47 @@ +#include "cdm.h" +#include "stddef.h" + +int write_dmi(uint8_t *dst, uint64_t *addr, uint32_t length, uint32_t dmi_addr, uint8_t sel) { + struct cdm_dmi_cmd *cmd = (struct cdm_dmi_cmd*)dst; + cmd->cmd = CAM_CDM_CMD_DMI_32; + cmd->length = length - 1; + cmd->reserved = 0; + cmd->addr = 0; // gets patched in + cmd->DMIAddr = dmi_addr; + cmd->DMISel = sel; + + *addr = (uint64_t)(dst + offsetof(struct cdm_dmi_cmd, addr)); + return sizeof(struct cdm_dmi_cmd); +} + +int write_cont(uint8_t *dst, uint32_t reg, const std::vector &vals) { + struct cdm_regcontinuous_cmd *cmd = (struct cdm_regcontinuous_cmd*)dst; + cmd->cmd = CAM_CDM_CMD_REG_CONT; + cmd->count = vals.size(); + cmd->offset = reg; + cmd->reserved0 = 0; + cmd->reserved1 = 0; + + uint32_t *vd = (uint32_t*)(dst + sizeof(struct cdm_regcontinuous_cmd)); + for (int i = 0; i < vals.size(); i++) { + *vd = vals[i]; + vd++; + } + + return sizeof(struct cdm_regcontinuous_cmd) + vals.size()*sizeof(uint32_t); +} + +int write_random(uint8_t *dst, const std::vector &vals) { + struct cdm_regrandom_cmd *cmd = (struct cdm_regrandom_cmd*)dst; + cmd->cmd = CAM_CDM_CMD_REG_RANDOM; + cmd->count = vals.size() / 2; + cmd->reserved = 0; + + uint32_t *vd = (uint32_t*)(dst + sizeof(struct cdm_regrandom_cmd)); + for (int i = 0; i < vals.size(); i++) { + *vd = vals[i]; + vd++; + } + + return sizeof(struct cdm_regrandom_cmd) + vals.size()*sizeof(uint32_t); +} diff --git a/system/camerad/cameras/cdm.h b/system/camerad/cameras/cdm.h new file mode 100644 index 0000000000..adda600400 --- /dev/null +++ b/system/camerad/cameras/cdm.h @@ -0,0 +1,79 @@ +#pragma once + +#include +#include +#include +#include +#include + +// our helpers +int write_random(uint8_t *dst, const std::vector &vals); +int write_cont(uint8_t *dst, uint32_t reg, const std::vector &vals); +int write_dmi(uint8_t *dst, uint64_t *addr, uint32_t length, uint32_t dmi_addr, uint8_t sel); + +// from drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.{c,h} + +enum cam_cdm_command { + CAM_CDM_CMD_UNUSED = 0x0, + CAM_CDM_CMD_DMI = 0x1, + CAM_CDM_CMD_NOT_DEFINED = 0x2, + CAM_CDM_CMD_REG_CONT = 0x3, + CAM_CDM_CMD_REG_RANDOM = 0x4, + CAM_CDM_CMD_BUFF_INDIRECT = 0x5, + CAM_CDM_CMD_GEN_IRQ = 0x6, + CAM_CDM_CMD_WAIT_EVENT = 0x7, + CAM_CDM_CMD_CHANGE_BASE = 0x8, + CAM_CDM_CMD_PERF_CTRL = 0x9, + CAM_CDM_CMD_DMI_32 = 0xa, + CAM_CDM_CMD_DMI_64 = 0xb, + CAM_CDM_CMD_PRIVATE_BASE = 0xc, + CAM_CDM_CMD_SWD_DMI_32 = (CAM_CDM_CMD_PRIVATE_BASE + 0x64), + CAM_CDM_CMD_SWD_DMI_64 = (CAM_CDM_CMD_PRIVATE_BASE + 0x65), + CAM_CDM_CMD_PRIVATE_BASE_MAX = 0x7F +}; + +/** + * struct cdm_regrandom_cmd - Definition for CDM random register command. + * @count: Number of register writes + * @reserved: reserved bits + * @cmd: Command ID (CDMCmd) + */ +struct cdm_regrandom_cmd { + unsigned int count : 16; + unsigned int reserved : 8; + unsigned int cmd : 8; +} __attribute__((__packed__)); + +/** + * struct cdm_regcontinuous_cmd - Definition for a CDM register range command. + * @count: Number of register writes + * @reserved0: reserved bits + * @cmd: Command ID (CDMCmd) + * @offset: Start address of the range of registers + * @reserved1: reserved bits + */ +struct cdm_regcontinuous_cmd { + unsigned int count : 16; + unsigned int reserved0 : 8; + unsigned int cmd : 8; + unsigned int offset : 24; + unsigned int reserved1 : 8; +} __attribute__((__packed__)); + +/** + * struct cdm_dmi_cmd - Definition for a CDM DMI command. + * @length: Number of bytes in LUT - 1 + * @reserved: reserved bits + * @cmd: Command ID (CDMCmd) + * @addr: Address of the LUT in memory + * @DMIAddr: Address of the target DMI config register + * @DMISel: DMI identifier + */ +struct cdm_dmi_cmd { + unsigned int length : 16; + unsigned int reserved : 8; + unsigned int cmd : 8; + unsigned int addr; + unsigned int DMIAddr : 24; + unsigned int DMISel : 8; +} __attribute__((__packed__)); diff --git a/system/camerad/cameras/hw.h b/system/camerad/cameras/hw.h new file mode 100644 index 0000000000..f20a1b3ade --- /dev/null +++ b/system/camerad/cameras/hw.h @@ -0,0 +1,68 @@ +#pragma once + +#include "common/util.h" +#include "cereal/gen/cpp/log.capnp.h" +#include "msgq/visionipc/visionipc_server.h" + +#include "media/cam_isp_ife.h" + + +typedef enum { + ISP_RAW_OUTPUT, // raw frame from sensor + ISP_IFE_PROCESSED, // fully processed image through the IFE + ISP_BPS_PROCESSED, // fully processed image through the BPS +} SpectraOutputType; + +// For the comma 3X three camera platform + +struct CameraConfig { + int camera_num; + VisionStreamType stream_type; + float focal_len; // millimeters + const char *publish_name; + cereal::FrameData::Builder (cereal::Event::Builder::*init_camera_state)(); + bool enabled; + uint32_t phy; + bool vignetting_correction; + SpectraOutputType output_type; +}; + +// NOTE: to be able to disable road and wide road, we still have to configure the sensor over i2c +// If you don't do this, the strobe GPIO is an output (even in reset it seems!) +const CameraConfig WIDE_ROAD_CAMERA_CONFIG = { + .camera_num = 0, + .stream_type = VISION_STREAM_WIDE_ROAD, + .focal_len = 1.71, + .publish_name = "wideRoadCameraState", + .init_camera_state = &cereal::Event::Builder::initWideRoadCameraState, + .enabled = !getenv("DISABLE_WIDE_ROAD"), + .phy = CAM_ISP_IFE_IN_RES_PHY_0, + .vignetting_correction = false, + .output_type = ISP_IFE_PROCESSED, +}; + +const CameraConfig ROAD_CAMERA_CONFIG = { + .camera_num = 1, + .stream_type = VISION_STREAM_ROAD, + .focal_len = 8.0, + .publish_name = "roadCameraState", + .init_camera_state = &cereal::Event::Builder::initRoadCameraState, + .enabled = !getenv("DISABLE_ROAD"), + .phy = CAM_ISP_IFE_IN_RES_PHY_1, + .vignetting_correction = true, + .output_type = ISP_IFE_PROCESSED, +}; + +const CameraConfig DRIVER_CAMERA_CONFIG = { + .camera_num = 2, + .stream_type = VISION_STREAM_DRIVER, + .focal_len = 1.71, + .publish_name = "driverCameraState", + .init_camera_state = &cereal::Event::Builder::initDriverCameraState, + .enabled = !getenv("DISABLE_DRIVER"), + .phy = CAM_ISP_IFE_IN_RES_PHY_2, + .vignetting_correction = false, + .output_type = ISP_BPS_PROCESSED, +}; + +const CameraConfig ALL_CAMERA_CONFIGS[] = {WIDE_ROAD_CAMERA_CONFIG, ROAD_CAMERA_CONFIG, DRIVER_CAMERA_CONFIG}; diff --git a/system/camerad/cameras/ife.h b/system/camerad/cameras/ife.h new file mode 100644 index 0000000000..fd87d2baa4 --- /dev/null +++ b/system/camerad/cameras/ife.h @@ -0,0 +1,236 @@ +#pragma once + +#include "cdm.h" + +#include "system/camerad/cameras/hw.h" +#include "system/camerad/sensors/sensor.h" + +int build_common_ife_bps(uint8_t *dst, const CameraConfig cam, const SensorInfo *s, std::vector &patches, bool ife) { + uint8_t *start = dst; + + /* + Common between IFE and BPS. + */ + + // IFE -> BPS addresses + /* + std::map addrs = { + {0xf30, 0x3468}, + }; + */ + + // YUV + dst += write_cont(dst, ife ? 0xf30 : 0x3468, { + 0x00680208, + 0x00000108, + 0x00400000, + 0x03ff0000, + 0x01c01ed8, + 0x00001f68, + 0x02000000, + 0x03ff0000, + 0x1fb81e88, + 0x000001c0, + 0x02000000, + 0x03ff0000, + }); + + return dst - start; +} + +int build_update(uint8_t *dst, const CameraConfig cam, const SensorInfo *s, std::vector &patches) { + uint8_t *start = dst; + + // init sequence + dst += write_random(dst, { + 0x2c, 0xffffffff, + 0x30, 0xffffffff, + 0x34, 0xffffffff, + 0x38, 0xffffffff, + 0x3c, 0xffffffff, + }); + + // demux cfg + dst += write_cont(dst, 0x560, { + 0x00000001, + 0x04440444, + 0x04450445, + 0x04440444, + 0x04450445, + 0x000000ca, + 0x0000009c, + }); + + // white balance + dst += write_cont(dst, 0x6fc, { + 0x00800080, + 0x00000080, + 0x00000000, + 0x00000000, + }); + + // module config/enables (e.g. enable debayer, white balance, etc.) + dst += write_cont(dst, 0x40, { + 0x00000c06 | ((uint32_t)(cam.vignetting_correction) << 8), + }); + dst += write_cont(dst, 0x44, { + 0x00000000, + }); + dst += write_cont(dst, 0x48, { + (1 << 3) | (1 << 1), + }); + dst += write_cont(dst, 0x4c, { + 0x00000019, + }); + dst += write_cont(dst, 0xf00, { + 0x00000000, + }); + + // cropping + dst += write_cont(dst, 0xe0c, { + 0x00000e00, + }); + dst += write_cont(dst, 0xe2c, { + 0x00000e00, + }); + + // black level scale + offset + dst += write_cont(dst, 0x6b0, { + ((uint32_t)(1 << 11) << 0xf) | (s->black_level << (14 - s->bits_per_pixel)), + 0x0, + 0x0, + }); + + return dst - start; +} + + +int build_initial_config(uint8_t *dst, const CameraConfig cam, const SensorInfo *s, std::vector &patches, uint32_t out_width, uint32_t out_height) { + uint8_t *start = dst; + + // start with the every frame config + dst += build_update(dst, cam, s, patches); + + uint64_t addr; + + // setup + dst += write_cont(dst, 0x478, { + 0x00000004, + 0x004000c0, + }); + dst += write_cont(dst, 0x488, { + 0x00000000, + 0x00000000, + 0x00000f0f, + }); + dst += write_cont(dst, 0x49c, { + 0x00000001, + }); + dst += write_cont(dst, 0xce4, { + 0x00000000, + 0x00000000, + }); + + // linearization + dst += write_cont(dst, 0x4dc, { + 0x00000000, + }); + dst += write_cont(dst, 0x4e0, s->linearization_pts); + dst += write_cont(dst, 0x4f0, s->linearization_pts); + dst += write_cont(dst, 0x500, s->linearization_pts); + dst += write_cont(dst, 0x510, s->linearization_pts); + // TODO: this is DMI64 in the dump, does that matter? + dst += write_dmi(dst, &addr, s->linearization_lut.size()*sizeof(uint32_t), 0xc24, 9); + patches.push_back(addr - (uint64_t)start); + + // vignetting correction + dst += write_cont(dst, 0x6bc, { + 0x0b3c0000, + 0x00670067, + 0xd3b1300c, + 0x13b1300c, + }); + dst += write_cont(dst, 0x6d8, { + 0xec4e4000, + 0x0100c003, + }); + dst += write_dmi(dst, &addr, s->vignetting_lut.size()*sizeof(uint32_t), 0xc24, 14); // GRR + patches.push_back(addr - (uint64_t)start); + dst += write_dmi(dst, &addr, s->vignetting_lut.size()*sizeof(uint32_t), 0xc24, 15); // GBB + patches.push_back(addr - (uint64_t)start); + + // debayer + dst += write_cont(dst, 0x6f8, { + 0x00000100, + }); + dst += write_cont(dst, 0x71c, { + 0x00008000, + 0x08000066, + }); + + // color correction + dst += write_cont(dst, 0x760, s->color_correct_matrix); + + // gamma + dst += write_cont(dst, 0x798, { + 0x00000000, + }); + dst += write_dmi(dst, &addr, s->gamma_lut_rgb.size()*sizeof(uint32_t), 0xc24, 26); // G + patches.push_back(addr - (uint64_t)start); + dst += write_dmi(dst, &addr, s->gamma_lut_rgb.size()*sizeof(uint32_t), 0xc24, 28); // B + patches.push_back(addr - (uint64_t)start); + dst += write_dmi(dst, &addr, s->gamma_lut_rgb.size()*sizeof(uint32_t), 0xc24, 30); // R + patches.push_back(addr - (uint64_t)start); + + // output size/scaling + dst += write_cont(dst, 0xa3c, { + 0x00000003, + ((out_width - 1) << 16) | (s->frame_width - 1), + 0x30036666, + 0x00000000, + 0x00000000, + s->frame_width - 1, + ((out_height - 1) << 16) | (s->frame_height - 1), + 0x30036666, + 0x00000000, + 0x00000000, + s->frame_height - 1, + }); + dst += write_cont(dst, 0xa68, { + 0x00000003, + ((out_width / 2 - 1) << 16) | (s->frame_width - 1), + 0x3006cccc, + 0x00000000, + 0x00000000, + s->frame_width - 1, + ((out_height / 2 - 1) << 16) | (s->frame_height - 1), + 0x3006cccc, + 0x00000000, + 0x00000000, + s->frame_height - 1, + }); + + // cropping + dst += write_cont(dst, 0xe10, { + out_height - 1, + out_width - 1, + }); + dst += write_cont(dst, 0xe30, { + out_height / 2 - 1, + out_width - 1, + }); + dst += write_cont(dst, 0xe18, { + 0x0ff00000, + 0x00000016, + }); + dst += write_cont(dst, 0xe38, { + 0x0ff00000, + 0x00000017, + }); + + dst += build_common_ife_bps(dst, cam, s, patches, true); + + return dst - start; +} + + diff --git a/system/camerad/cameras/spectra.cc b/system/camerad/cameras/spectra.cc new file mode 100644 index 0000000000..caf7871573 --- /dev/null +++ b/system/camerad/cameras/spectra.cc @@ -0,0 +1,1502 @@ +#include "cdm.h" + +#include +#include +#include +#include +#include + +#include "media/cam_defs.h" +#include "media/cam_isp.h" +#include "media/cam_icp.h" +#include "media/cam_isp_ife.h" +#include "media/cam_sensor_cmn_header.h" +#include "media/cam_sync.h" +#include "third_party/linux/include/msm_media_info.h" + +#include "common/util.h" +#include "common/swaglog.h" +#include "system/camerad/cameras/ife.h" +#include "system/camerad/cameras/spectra.h" +#include "system/camerad/cameras/bps_blobs.h" + + +// ************** low level camera helpers **************** + +int do_cam_control(int fd, int op_code, void *handle, int size) { + struct cam_control camcontrol = {0}; + camcontrol.op_code = op_code; + camcontrol.handle = (uint64_t)handle; + if (size == 0) { + camcontrol.size = 8; + camcontrol.handle_type = CAM_HANDLE_MEM_HANDLE; + } else { + camcontrol.size = size; + camcontrol.handle_type = CAM_HANDLE_USER_POINTER; + } + + int ret = HANDLE_EINTR(ioctl(fd, VIDIOC_CAM_CONTROL, &camcontrol)); + if (ret == -1) { + LOGE("VIDIOC_CAM_CONTROL error: op_code %d - errno %d", op_code, errno); + } + return ret; +} + +int do_sync_control(int fd, uint32_t id, void *handle, uint32_t size) { + struct cam_private_ioctl_arg arg = { + .id = id, + .size = size, + .ioctl_ptr = (uint64_t)handle, + }; + int ret = HANDLE_EINTR(ioctl(fd, CAM_PRIVATE_IOCTL_CMD, &arg)); + + int32_t ioctl_result = static_cast(arg.result); + if (ret < 0) { + LOGE("CAM_SYNC error: id %u - errno %d - ret %d - ioctl_result %d", id, errno, ret, ioctl_result); + return ret; + } + if (ioctl_result != 0) { + LOGE("CAM_SYNC error: id %u - errno %d - ret %d - ioctl_result %d", id, errno, ret, ioctl_result); + return ioctl_result; + } + return ret; +} + +std::optional device_acquire(int fd, int32_t session_handle, void *data, uint32_t num_resources) { + struct cam_acquire_dev_cmd cmd = { + .session_handle = session_handle, + .handle_type = CAM_HANDLE_USER_POINTER, + .num_resources = (uint32_t)(data ? num_resources : 0), + .resource_hdl = (uint64_t)data, + }; + int err = do_cam_control(fd, CAM_ACQUIRE_DEV, &cmd, sizeof(cmd)); + return err == 0 ? std::make_optional(cmd.dev_handle) : std::nullopt; +} + +int device_config(int fd, int32_t session_handle, int32_t dev_handle, uint64_t packet_handle) { + struct cam_config_dev_cmd cmd = { + .session_handle = session_handle, + .dev_handle = dev_handle, + .packet_handle = packet_handle, + }; + return do_cam_control(fd, CAM_CONFIG_DEV, &cmd, sizeof(cmd)); +} + +int device_control(int fd, int op_code, int session_handle, int dev_handle) { + // start stop and release are all the same + struct cam_start_stop_dev_cmd cmd { .session_handle = session_handle, .dev_handle = dev_handle }; + return do_cam_control(fd, op_code, &cmd, sizeof(cmd)); +} + +void *alloc_w_mmu_hdl(int video0_fd, int len, uint32_t *handle, int align, int flags, int mmu_hdl, int mmu_hdl2) { + struct cam_mem_mgr_alloc_cmd mem_mgr_alloc_cmd = {0}; + mem_mgr_alloc_cmd.len = len; + mem_mgr_alloc_cmd.align = align; + mem_mgr_alloc_cmd.flags = flags; + mem_mgr_alloc_cmd.num_hdl = 0; + if (mmu_hdl != 0) { + mem_mgr_alloc_cmd.mmu_hdls[0] = mmu_hdl; + mem_mgr_alloc_cmd.num_hdl++; + } + if (mmu_hdl2 != 0) { + mem_mgr_alloc_cmd.mmu_hdls[1] = mmu_hdl2; + mem_mgr_alloc_cmd.num_hdl++; + } + + do_cam_control(video0_fd, CAM_REQ_MGR_ALLOC_BUF, &mem_mgr_alloc_cmd, sizeof(mem_mgr_alloc_cmd)); + *handle = mem_mgr_alloc_cmd.out.buf_handle; + + void *ptr = NULL; + if (mem_mgr_alloc_cmd.out.fd > 0) { + ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, mem_mgr_alloc_cmd.out.fd, 0); + assert(ptr != MAP_FAILED); + } + + // LOGD("allocated: %x %d %llx mapped %p", mem_mgr_alloc_cmd.out.buf_handle, mem_mgr_alloc_cmd.out.fd, mem_mgr_alloc_cmd.out.vaddr, ptr); + + return ptr; +} + +void release(int video0_fd, uint32_t handle) { + struct cam_mem_mgr_release_cmd mem_mgr_release_cmd = {0}; + mem_mgr_release_cmd.buf_handle = handle; + + int ret = do_cam_control(video0_fd, CAM_REQ_MGR_RELEASE_BUF, &mem_mgr_release_cmd, sizeof(mem_mgr_release_cmd)); + assert(ret == 0); +} + +static cam_cmd_power *power_set_wait(cam_cmd_power *power, int16_t delay_ms) { + cam_cmd_unconditional_wait *unconditional_wait = (cam_cmd_unconditional_wait *)((char *)power + (sizeof(struct cam_cmd_power) + (power->count - 1) * sizeof(struct cam_power_settings))); + unconditional_wait->cmd_type = CAMERA_SENSOR_CMD_TYPE_WAIT; + unconditional_wait->delay = delay_ms; + unconditional_wait->op_code = CAMERA_SENSOR_WAIT_OP_SW_UCND; + return (struct cam_cmd_power *)(unconditional_wait + 1); +} + +// *** MemoryManager *** + +void *MemoryManager::alloc_buf(int size, uint32_t *handle) { + void *ptr; + auto &cache = cached_allocations[size]; + if (!cache.empty()) { + ptr = cache.front(); + cache.pop(); + *handle = handle_lookup[ptr]; + } else { + ptr = alloc_w_mmu_hdl(video0_fd, size, handle); + handle_lookup[ptr] = *handle; + size_lookup[ptr] = size; + } + memset(ptr, 0, size); + return ptr; +} + +void MemoryManager::free(void *ptr) { + cached_allocations[size_lookup[ptr]].push(ptr); +} + +MemoryManager::~MemoryManager() { + for (auto& x : cached_allocations) { + while (!x.second.empty()) { + void *ptr = x.second.front(); + x.second.pop(); + LOGD("freeing cached allocation %p with size %d", ptr, size_lookup[ptr]); + munmap(ptr, size_lookup[ptr]); + + // release fd + close(handle_lookup[ptr] >> 16); + release(video0_fd, handle_lookup[ptr]); + + handle_lookup.erase(ptr); + size_lookup.erase(ptr); + } + } +} + +// *** SpectraMaster *** + +void SpectraMaster::init() { + LOG("-- Opening devices"); + // video0 is req_mgr, the target of many ioctls + video0_fd = HANDLE_EINTR(open("/dev/v4l/by-path/platform-soc:qcom_cam-req-mgr-video-index0", O_RDWR | O_NONBLOCK)); + assert(video0_fd >= 0); + LOGD("opened video0"); + + // video1 is cam_sync, the target of some ioctls + cam_sync_fd = HANDLE_EINTR(open("/dev/v4l/by-path/platform-cam_sync-video-index0", O_RDWR | O_NONBLOCK)); + assert(cam_sync_fd >= 0); + LOGD("opened video1 (cam_sync)"); + + // looks like there's only one of these + isp_fd = open_v4l_by_name_and_index("cam-isp"); + assert(isp_fd >= 0); + LOGD("opened isp %d", (int)isp_fd); + + icp_fd = open_v4l_by_name_and_index("cam-icp"); + assert(icp_fd >= 0); + LOGD("opened icp %d", (int)icp_fd); + + // query ISP for MMU handles + LOG("-- Query for MMU handles"); + struct cam_isp_query_cap_cmd isp_query_cap_cmd = {0}; + struct cam_query_cap_cmd query_cap_cmd = {0}; + query_cap_cmd.handle_type = 1; + query_cap_cmd.caps_handle = (uint64_t)&isp_query_cap_cmd; + query_cap_cmd.size = sizeof(isp_query_cap_cmd); + int ret = do_cam_control(isp_fd, CAM_QUERY_CAP, &query_cap_cmd, sizeof(query_cap_cmd)); + assert(ret == 0); + LOGD("using MMU handle: %x", isp_query_cap_cmd.device_iommu.non_secure); + LOGD("using MMU handle: %x", isp_query_cap_cmd.cdm_iommu.non_secure); + device_iommu = isp_query_cap_cmd.device_iommu.non_secure; + cdm_iommu = isp_query_cap_cmd.cdm_iommu.non_secure; + + // query ICP for MMU handles + struct cam_icp_query_cap_cmd icp_query_cap_cmd = {0}; + query_cap_cmd.caps_handle = (uint64_t)&icp_query_cap_cmd; + query_cap_cmd.size = sizeof(icp_query_cap_cmd); + ret = do_cam_control(icp_fd, CAM_QUERY_CAP, &query_cap_cmd, sizeof(query_cap_cmd)); + assert(ret == 0); + LOGD("using ICP MMU handle: %x", icp_query_cap_cmd.dev_iommu_handle.non_secure); + icp_device_iommu = icp_query_cap_cmd.dev_iommu_handle.non_secure; + + // subscribe + LOG("-- Subscribing"); + struct v4l2_event_subscription sub = {0}; + sub.type = V4L_EVENT_CAM_REQ_MGR_EVENT; + sub.id = V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS; + ret = HANDLE_EINTR(ioctl(video0_fd, VIDIOC_SUBSCRIBE_EVENT, &sub)); + LOGD("req mgr subscribe: %d", ret); + + mem_mgr.init(video0_fd); +} + +// *** SpectraCamera *** + +SpectraCamera::SpectraCamera(SpectraMaster *master, const CameraConfig &config) + : m(master), + enabled(config.enabled), + cc(config) { + ife_buf_depth = VIPC_BUFFER_COUNT; + assert(ife_buf_depth < MAX_IFE_BUFS); +} + +SpectraCamera::~SpectraCamera() { + if (open) { + camera_close(); + } +} + +int SpectraCamera::clear_req_queue() { + // for "non-realtime" BPS + if (icp_dev_handle > 0) { + struct cam_flush_dev_cmd cmd = { + .session_handle = session_handle, + .dev_handle = icp_dev_handle, + .flush_type = CAM_FLUSH_TYPE_ALL, + }; + int err = do_cam_control(m->icp_fd, CAM_FLUSH_REQ, &cmd, sizeof(cmd)); + assert(err == 0); + LOGD("flushed bps: %d", err); + } + + // for "realtime" devices + struct cam_req_mgr_flush_info req_mgr_flush_request = {0}; + req_mgr_flush_request.session_hdl = session_handle; + req_mgr_flush_request.link_hdl = link_handle; + req_mgr_flush_request.flush_type = CAM_REQ_MGR_FLUSH_TYPE_ALL; + int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_FLUSH_REQ, &req_mgr_flush_request, sizeof(req_mgr_flush_request)); + LOGD("flushed all req: %d", ret); // returns a "time until timeout" on clearing the workq + + for (int i = 0; i < MAX_IFE_BUFS; ++i) { + destroySyncObjectAt(i); + } + + return ret; +} + +void SpectraCamera::camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx) { + if (!openSensor()) { + return; + } + + if (!enabled) return; + + buf.out_img_width = sensor->frame_width / sensor->out_scale; + buf.out_img_height = (sensor->hdr_offset > 0 ? (sensor->frame_height - sensor->hdr_offset) / 2 : sensor->frame_height) / sensor->out_scale; + + // size is driven by all the HW that handles frames, + // the video encoder has certain alignment requirements in this case + stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, buf.out_img_width); + y_height = VENUS_Y_SCANLINES(COLOR_FMT_NV12, buf.out_img_height); + uv_height = VENUS_UV_SCANLINES(COLOR_FMT_NV12, buf.out_img_height); + uv_offset = stride*y_height; + yuv_size = uv_offset + stride*uv_height; + if (cc.output_type != ISP_RAW_OUTPUT) { + uv_offset = ALIGNED_SIZE(uv_offset, 0x1000); + yuv_size = uv_offset + ALIGNED_SIZE(stride*uv_height, 0x1000); + } + assert(stride == VENUS_UV_STRIDE(COLOR_FMT_NV12, buf.out_img_width)); + assert(y_height/2 == uv_height); + + open = true; + configISP(); + if (cc.output_type == ISP_BPS_PROCESSED) configICP(); + configCSIPHY(); + linkDevices(); + + LOGD("camera init %d", cc.camera_num); + buf.init(device_id, ctx, this, v, ife_buf_depth, cc.stream_type); + camera_map_bufs(); + clearAndRequeue(1); +} + +void SpectraCamera::sensors_start() { + if (!enabled) return; + LOGD("starting sensor %d", cc.camera_num); + sensors_i2c(sensor->start_reg_array.data(), sensor->start_reg_array.size(), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, sensor->data_word); +} + +void SpectraCamera::sensors_poke(int request_id) { + uint32_t cam_packet_handle = 0; + int size = sizeof(struct cam_packet); + auto pkt = m->mem_mgr.alloc(size, &cam_packet_handle); + pkt->num_cmd_buf = 0; + pkt->kmd_cmd_buf_index = -1; + pkt->header.size = size; + pkt->header.op_code = CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP; + pkt->header.request_id = request_id; + + int ret = device_config(sensor_fd, session_handle, sensor_dev_handle, cam_packet_handle); + if (ret != 0) { + LOGE("** sensor %d FAILED poke, disabling", cc.camera_num); + enabled = false; + return; + } +} + +void SpectraCamera::sensors_i2c(const struct i2c_random_wr_payload* dat, int len, int op_code, bool data_word) { + // LOGD("sensors_i2c: %d", len); + uint32_t cam_packet_handle = 0; + int size = sizeof(struct cam_packet)+sizeof(struct cam_cmd_buf_desc)*1; + auto pkt = m->mem_mgr.alloc(size, &cam_packet_handle); + pkt->num_cmd_buf = 1; + pkt->kmd_cmd_buf_index = -1; + pkt->header.size = size; + pkt->header.op_code = op_code; + struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload; + + buf_desc[0].size = buf_desc[0].length = sizeof(struct i2c_rdwr_header) + len*sizeof(struct i2c_random_wr_payload); + buf_desc[0].type = CAM_CMD_BUF_I2C; + + auto i2c_random_wr = m->mem_mgr.alloc(buf_desc[0].size, (uint32_t*)&buf_desc[0].mem_handle); + i2c_random_wr->header.count = len; + i2c_random_wr->header.op_code = 1; + i2c_random_wr->header.cmd_type = CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR; + i2c_random_wr->header.data_type = data_word ? CAMERA_SENSOR_I2C_TYPE_WORD : CAMERA_SENSOR_I2C_TYPE_BYTE; + i2c_random_wr->header.addr_type = CAMERA_SENSOR_I2C_TYPE_WORD; + memcpy(i2c_random_wr->random_wr_payload, dat, len*sizeof(struct i2c_random_wr_payload)); + + int ret = device_config(sensor_fd, session_handle, sensor_dev_handle, cam_packet_handle); + if (ret != 0) { + LOGE("** sensor %d FAILED i2c, disabling", cc.camera_num); + enabled = false; + return; + } +} + +int SpectraCamera::sensors_init() { + uint32_t cam_packet_handle = 0; + int size = sizeof(struct cam_packet)+sizeof(struct cam_cmd_buf_desc)*2; + auto pkt = m->mem_mgr.alloc(size, &cam_packet_handle); + pkt->num_cmd_buf = 2; + pkt->kmd_cmd_buf_index = -1; + pkt->header.op_code = CSLDeviceTypeImageSensor | CAM_SENSOR_PACKET_OPCODE_SENSOR_PROBE; + pkt->header.size = size; + struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload; + + buf_desc[0].size = buf_desc[0].length = sizeof(struct cam_cmd_i2c_info) + sizeof(struct cam_cmd_probe); + buf_desc[0].type = CAM_CMD_BUF_LEGACY; + auto i2c_info = m->mem_mgr.alloc(buf_desc[0].size, (uint32_t*)&buf_desc[0].mem_handle); + auto probe = (struct cam_cmd_probe *)(i2c_info.get() + 1); + + probe->camera_id = cc.camera_num; + i2c_info->slave_addr = sensor->getSlaveAddress(cc.camera_num); + // 0(I2C_STANDARD_MODE) = 100khz, 1(I2C_FAST_MODE) = 400khz + //i2c_info->i2c_freq_mode = I2C_STANDARD_MODE; + i2c_info->i2c_freq_mode = I2C_FAST_MODE; + i2c_info->cmd_type = CAMERA_SENSOR_CMD_TYPE_I2C_INFO; + + probe->data_type = CAMERA_SENSOR_I2C_TYPE_WORD; + probe->addr_type = CAMERA_SENSOR_I2C_TYPE_WORD; + probe->op_code = 3; // don't care? + probe->cmd_type = CAMERA_SENSOR_CMD_TYPE_PROBE; + probe->reg_addr = sensor->probe_reg_addr; + probe->expected_data = sensor->probe_expected_data; + probe->data_mask = 0; + + //buf_desc[1].size = buf_desc[1].length = 148; + buf_desc[1].size = buf_desc[1].length = 196; + buf_desc[1].type = CAM_CMD_BUF_I2C; + auto power_settings = m->mem_mgr.alloc(buf_desc[1].size, (uint32_t*)&buf_desc[1].mem_handle); + + // power on + struct cam_cmd_power *power = power_settings.get(); + power->count = 4; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP; + power->power_settings[0].power_seq_type = 3; // clock?? + power->power_settings[1].power_seq_type = 1; // analog + power->power_settings[2].power_seq_type = 2; // digital + power->power_settings[3].power_seq_type = 8; // reset low + power = power_set_wait(power, 1); + + // set clock + power->count = 1; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP; + power->power_settings[0].power_seq_type = 0; + power->power_settings[0].config_val_low = sensor->mclk_frequency; + power = power_set_wait(power, 1); + + // reset high + power->count = 1; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP; + power->power_settings[0].power_seq_type = 8; + power->power_settings[0].config_val_low = 1; + // wait 650000 cycles @ 19.2 mhz = 33.8 ms + power = power_set_wait(power, 34); + + // probe happens here + + // disable clock + power->count = 1; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN; + power->power_settings[0].power_seq_type = 0; + power->power_settings[0].config_val_low = 0; + power = power_set_wait(power, 1); + + // reset high + power->count = 1; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN; + power->power_settings[0].power_seq_type = 8; + power->power_settings[0].config_val_low = 1; + power = power_set_wait(power, 1); + + // reset low + power->count = 1; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN; + power->power_settings[0].power_seq_type = 8; + power->power_settings[0].config_val_low = 0; + power = power_set_wait(power, 1); + + // power off + power->count = 3; + power->cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN; + power->power_settings[0].power_seq_type = 2; + power->power_settings[1].power_seq_type = 1; + power->power_settings[2].power_seq_type = 3; + + int ret = do_cam_control(sensor_fd, CAM_SENSOR_PROBE_CMD, (void *)(uintptr_t)cam_packet_handle, 0); + LOGD("probing the sensor: %d", ret); + return ret; +} + +void add_patch(struct cam_packet *pkt, int32_t dst_hdl, uint32_t dst_offset, int32_t src_hdl, uint32_t src_offset) { + void *ptr = (char*)&pkt->payload + pkt->patch_offset; + struct cam_patch_desc *p = (struct cam_patch_desc *)((unsigned char*)ptr + sizeof(struct cam_patch_desc)*pkt->num_patches); + p->dst_buf_hdl = dst_hdl; + p->src_buf_hdl = src_hdl; + p->dst_offset = dst_offset; + p->src_offset = src_offset; + pkt->num_patches++; +}; + +void SpectraCamera::config_bps(int idx, int request_id) { + /* + Handles per-frame BPS config. + * BPS = Bayer Processing Segment + */ + + int size = sizeof(struct cam_packet) + sizeof(struct cam_cmd_buf_desc)*2 + sizeof(struct cam_buf_io_cfg)*2; + size += sizeof(struct cam_patch_desc)*9; + + uint32_t cam_packet_handle = 0; + auto pkt = m->mem_mgr.alloc(size, &cam_packet_handle); + + pkt->header.op_code = CSLDeviceTypeBPS | CAM_ICP_OPCODE_BPS_UPDATE; + pkt->header.request_id = request_id; + pkt->header.size = size; + + typedef struct { + struct { + uint32_t ptr[2]; + uint32_t unknown[2]; + } frames[9]; + + uint32_t unknown1; + uint32_t unknown2; + uint32_t unknown3; + uint32_t unknown4; + + uint32_t cdm_addr; + uint32_t cdm_size; + uint32_t settings_addr; + uint32_t striping_addr; + uint32_t cdm_addr2; + + uint32_t req_id; + uint64_t handle; + } bps_tmp; + + typedef struct { + uint32_t a; + uint32_t n; + unsigned base : 32; + unsigned unused : 12; + unsigned length : 20; + uint32_t p; + uint32_t u; + uint32_t h; + uint32_t b; + } cdm_tmp; + + // *** cmd buf *** + std::vector patches; + struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload; + { + pkt->num_cmd_buf = 2; + pkt->kmd_cmd_buf_index = -1; + pkt->kmd_cmd_buf_offset = 0; + + buf_desc[0].meta_data = 0; + buf_desc[0].mem_handle = bps_cmd.handle; + buf_desc[0].type = CAM_CMD_BUF_FW; + buf_desc[0].offset = bps_cmd.aligned_size()*idx; + + buf_desc[0].length = sizeof(bps_tmp) + sizeof(cdm_tmp); + buf_desc[0].size = buf_desc[0].length; + + // rest gets patched in + bps_tmp *fp = (bps_tmp *)((unsigned char *)bps_cmd.ptr + buf_desc[0].offset); + memset(fp, 0, buf_desc[0].length); + fp->handle = (uint64_t)icp_dev_handle; + fp->cdm_size = bps_cdm_striping_bl.size; // this comes from the striping lib create call + fp->req_id = 0; // why always 0? + + cdm_tmp *pa = (cdm_tmp *)((unsigned char *)fp + sizeof(bps_tmp)); + pa->a = 0; + pa->n = 1; + pa->p = 20; // GENERIC + pa->u = 0; + pa->h = 0; + pa->b = 0; + pa->unused = 0; + pa->base = 0; // this gets patched + + int cdm_len = 0; + + if (bps_lin_reg.size() == 0) { + for (int i = 0; i < 4; i++) { + bps_lin_reg.push_back(((sensor->linearization_pts[i] & 0xffff) << 0x10) | (sensor->linearization_pts[i] >> 0x10)); + } + } + + if (bps_ccm_reg.size() == 0) { + for (int i = 0; i < 3; i++) { + bps_ccm_reg.push_back(sensor->color_correct_matrix[i] | (sensor->color_correct_matrix[i+3] << 0x10)); + bps_ccm_reg.push_back(sensor->color_correct_matrix[i+6]); + } + } + + // white balance + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x2868, { + 0x04000400, + 0x00000400, + 0x00000000, + 0x00000000, + }); + // debayer + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x2878, { + 0x00000080, + 0x00800066, + }); + // linearization, EN=0 + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1868, bps_lin_reg); + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1878, bps_lin_reg); + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1888, bps_lin_reg); + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x1898, bps_lin_reg); + /* + uint8_t *start = (unsigned char *)bps_cdm_program_array.ptr + cdm_len; + uint64_t addr; + cdm_len += write_dmi((unsigned char *)bps_cdm_program_array.ptr + cdm_len, &addr, sensor->linearization_lut.size()*sizeof(uint32_t), 0x1808, 1); + patches.push_back(addr - (uint64_t)start); + */ + // color correction + cdm_len += write_cont((unsigned char *)bps_cdm_program_array.ptr + cdm_len, 0x2e68, bps_ccm_reg); + + cdm_len += build_common_ife_bps((unsigned char *)bps_cdm_program_array.ptr + cdm_len, cc, sensor.get(), patches, false); + + pa->length = cdm_len - 1; + + // *** second command *** + // parsed by cam_icp_packet_generic_blob_handler + struct isp_packet { + uint32_t header; + struct cam_icp_clk_bw_request clk; + } __attribute__((packed)) tmp; + tmp.header = CAM_ICP_CMD_GENERIC_BLOB_CLK; + tmp.header |= (sizeof(cam_icp_clk_bw_request)) << 8; + tmp.clk.budget_ns = 0x1fca058; + tmp.clk.frame_cycles = 2329024; // comes from the striping lib + tmp.clk.rt_flag = 0x0; + tmp.clk.uncompressed_bw = 0x38512180; + tmp.clk.compressed_bw = 0x38512180; + + buf_desc[1].size = sizeof(tmp); + buf_desc[1].offset = 0; + buf_desc[1].length = buf_desc[1].size - buf_desc[1].offset; + buf_desc[1].type = CAM_CMD_BUF_GENERIC; + buf_desc[1].meta_data = CAM_ICP_CMD_META_GENERIC_BLOB; + auto buf2 = m->mem_mgr.alloc(buf_desc[1].size, (uint32_t*)&buf_desc[1].mem_handle); + memcpy(buf2.get(), &tmp, sizeof(tmp)); + } + + // *** io config *** + pkt->num_io_configs = 2; + pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf; + struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset); + { + // input frame + io_cfg[0].offsets[0] = 0; + io_cfg[0].mem_handle[0] = buf_handle_raw[idx]; + + io_cfg[0].planes[0] = (struct cam_plane_cfg){ + .width = sensor->frame_width, + .height = sensor->frame_height + sensor->extra_height, + .plane_stride = sensor->frame_stride, + .slice_height = sensor->frame_height + sensor->extra_height, + }; + io_cfg[0].format = sensor->mipi_format; + io_cfg[0].color_space = CAM_COLOR_SPACE_BASE; + io_cfg[0].color_pattern = 0x5; + io_cfg[0].bpp = (sensor->mipi_format == CAM_FORMAT_MIPI_RAW_10 ? 0xa : 0xc); + io_cfg[0].resource_type = CAM_ICP_BPS_INPUT_IMAGE; + io_cfg[0].fence = sync_objs_ife[idx]; + io_cfg[0].direction = CAM_BUF_INPUT; + io_cfg[0].subsample_pattern = 0x1; + io_cfg[0].framedrop_pattern = 0x1; + + // output frame + io_cfg[1].mem_handle[0] = buf_handle_yuv[idx]; + io_cfg[1].mem_handle[1] = buf_handle_yuv[idx]; + io_cfg[1].planes[0] = (struct cam_plane_cfg){ + .width = buf.out_img_width, + .height = buf.out_img_height, + .plane_stride = stride, + .slice_height = y_height, + }; + io_cfg[1].planes[1] = (struct cam_plane_cfg){ + .width = buf.out_img_width, + .height = buf.out_img_height / 2, + .plane_stride = stride, + .slice_height = uv_height, + }; + io_cfg[1].offsets[1] = ALIGNED_SIZE(io_cfg[1].planes[0].plane_stride*io_cfg[1].planes[0].slice_height, 0x1000); + assert(io_cfg[1].offsets[1] == uv_offset); + + io_cfg[1].format = CAM_FORMAT_NV12; // TODO: why is this 21 in the dump? should be 12 + io_cfg[1].color_space = CAM_COLOR_SPACE_BT601_FULL; + io_cfg[1].resource_type = CAM_ICP_BPS_OUTPUT_IMAGE_FULL; + io_cfg[1].fence = sync_objs_bps[idx]; + io_cfg[1].direction = CAM_BUF_OUTPUT; + io_cfg[1].subsample_pattern = 0x1; + io_cfg[1].framedrop_pattern = 0x1; + } + + // *** patches *** + { + assert(patches.size() == 0 | patches.size() == 1); + pkt->patch_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf + sizeof(struct cam_buf_io_cfg)*pkt->num_io_configs; + + if (patches.size() > 0) { + add_patch(pkt.get(), bps_cmd.handle, patches[0], bps_linearization_lut.handle, 0); + } + + // input frame + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, frames[0].ptr[0]), buf_handle_raw[idx], 0); + + // output frame + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, frames[1].ptr[0]), buf_handle_yuv[idx], 0); + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, frames[1].ptr[1]), buf_handle_yuv[idx], io_cfg[1].offsets[1]); + + // rest of buffers + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, settings_addr), bps_iq.handle, 0); + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, cdm_addr2), bps_cmd.handle, sizeof(bps_tmp)); + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + 0xc8, bps_cdm_program_array.handle, 0); + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, striping_addr), bps_striping.handle, 0); + add_patch(pkt.get(), bps_cmd.handle, buf_desc[0].offset + offsetof(bps_tmp, cdm_addr), bps_cdm_striping_bl.handle, 0); + } + + int ret = device_config(m->icp_fd, session_handle, icp_dev_handle, cam_packet_handle); + assert(ret == 0); +} + +void SpectraCamera::config_ife(int idx, int request_id, bool init) { + /* + Handles initial + per-frame IFE config. + * IFE = Image Front End + */ + int size = sizeof(struct cam_packet) + sizeof(struct cam_cmd_buf_desc)*2; + size += sizeof(struct cam_patch_desc)*10; + if (!init) { + size += sizeof(struct cam_buf_io_cfg); + } + + uint32_t cam_packet_handle = 0; + auto pkt = m->mem_mgr.alloc(size, &cam_packet_handle); + + if (!init) { + pkt->header.op_code = CSLDeviceTypeIFE | OpcodesIFEUpdate; // 0xf000001 + pkt->header.request_id = request_id; + } else { + pkt->header.op_code = CSLDeviceTypeIFE | OpcodesIFEInitialConfig; // 0xf000000 + pkt->header.request_id = 1; + } + pkt->header.size = size; + + // *** cmd buf *** + std::vector patches; + { + struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload; + pkt->num_cmd_buf = 2; + + // *** first command *** + buf_desc[0].size = ife_cmd.size; + buf_desc[0].length = 0; + buf_desc[0].type = CAM_CMD_BUF_DIRECT; + buf_desc[0].meta_data = CAM_ISP_PACKET_META_COMMON; + buf_desc[0].mem_handle = ife_cmd.handle; + buf_desc[0].offset = ife_cmd.aligned_size()*idx; + + // stream of IFE register writes + bool is_raw = cc.output_type != ISP_IFE_PROCESSED; + if (!is_raw) { + if (init) { + buf_desc[0].length = build_initial_config((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, cc, sensor.get(), patches, buf.out_img_width, buf.out_img_height); + } else { + buf_desc[0].length = build_update((unsigned char*)ife_cmd.ptr + buf_desc[0].offset, cc, sensor.get(), patches); + } + } + + pkt->kmd_cmd_buf_offset = buf_desc[0].length; + pkt->kmd_cmd_buf_index = 0; + + // *** second command *** + // parsed by cam_isp_packet_generic_blob_handler + struct isp_packet { + uint32_t type_0; + cam_isp_resource_hfr_config resource_hfr; + + uint32_t type_1; + cam_isp_clock_config clock; + uint64_t extra_rdi_hz[3]; + + uint32_t type_2; + cam_isp_bw_config bw; + struct cam_isp_bw_vote extra_rdi_vote[6]; + } __attribute__((packed)) tmp; + memset(&tmp, 0, sizeof(tmp)); + + tmp.type_0 = CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG; + tmp.type_0 |= sizeof(cam_isp_resource_hfr_config) << 8; + static_assert(sizeof(cam_isp_resource_hfr_config) == 0x20); + tmp.resource_hfr = { + .num_ports = 1, + .port_hfr_config[0] = { + .resource_type = static_cast(is_raw ? CAM_ISP_IFE_OUT_RES_RDI_0 : CAM_ISP_IFE_OUT_RES_FULL), + .subsample_pattern = 1, + .subsample_period = 0, + .framedrop_pattern = 1, + .framedrop_period = 0, + } + }; + + tmp.type_1 = CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG; + tmp.type_1 |= (sizeof(cam_isp_clock_config) + sizeof(tmp.extra_rdi_hz)) << 8; + static_assert((sizeof(cam_isp_clock_config) + sizeof(tmp.extra_rdi_hz)) == 0x38); + tmp.clock = { + .usage_type = 1, // dual mode + .num_rdi = 4, + .left_pix_hz = 404000000, + .right_pix_hz = 404000000, + .rdi_hz[0] = 404000000, + }; + + tmp.type_2 = CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG; + tmp.type_2 |= (sizeof(cam_isp_bw_config) + sizeof(tmp.extra_rdi_vote)) << 8; + static_assert((sizeof(cam_isp_bw_config) + sizeof(tmp.extra_rdi_vote)) == 0xe0); + tmp.bw = { + .usage_type = 1, // dual mode + .num_rdi = 4, + .left_pix_vote = { + .resource_id = 0, + .cam_bw_bps = 450000000, + .ext_bw_bps = 450000000, + }, + .rdi_vote[0] = { + .resource_id = 0, + .cam_bw_bps = 8706200000, + .ext_bw_bps = 8706200000, + }, + }; + + static_assert(offsetof(struct isp_packet, type_2) == 0x60); + + buf_desc[1].size = sizeof(tmp); + buf_desc[1].offset = !init ? 0x60 : 0; + buf_desc[1].length = buf_desc[1].size - buf_desc[1].offset; + buf_desc[1].type = CAM_CMD_BUF_GENERIC; + buf_desc[1].meta_data = CAM_ISP_PACKET_META_GENERIC_BLOB_COMMON; + auto buf2 = m->mem_mgr.alloc(buf_desc[1].size, (uint32_t*)&buf_desc[1].mem_handle); + memcpy(buf2.get(), &tmp, sizeof(tmp)); + } + + // *** io config *** + if (!init) { + // configure output frame + pkt->num_io_configs = 1; + pkt->io_configs_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf; + + struct cam_buf_io_cfg *io_cfg = (struct cam_buf_io_cfg *)((char*)&pkt->payload + pkt->io_configs_offset); + if (cc.output_type != ISP_IFE_PROCESSED) { + io_cfg[0].mem_handle[0] = buf_handle_raw[idx]; + io_cfg[0].planes[0] = (struct cam_plane_cfg){ + .width = sensor->frame_width, + .height = sensor->frame_height, + .plane_stride = sensor->frame_stride, + .slice_height = sensor->frame_height + sensor->extra_height, + }; + io_cfg[0].format = sensor->mipi_format; + io_cfg[0].color_space = CAM_COLOR_SPACE_BASE; + io_cfg[0].color_pattern = 0x5; + io_cfg[0].bpp = (sensor->mipi_format == CAM_FORMAT_MIPI_RAW_10 ? 0xa : 0xc); + io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_RDI_0; + io_cfg[0].fence = sync_objs_ife[idx]; + io_cfg[0].direction = CAM_BUF_OUTPUT; + io_cfg[0].subsample_pattern = 0x1; + io_cfg[0].framedrop_pattern = 0x1; + } else { + io_cfg[0].mem_handle[0] = buf_handle_yuv[idx]; + io_cfg[0].mem_handle[1] = buf_handle_yuv[idx]; + io_cfg[0].planes[0] = (struct cam_plane_cfg){ + .width = buf.out_img_width, + .height = buf.out_img_height, + .plane_stride = stride, + .slice_height = y_height, + }; + io_cfg[0].planes[1] = (struct cam_plane_cfg){ + .width = buf.out_img_width, + .height = buf.out_img_height / 2, + .plane_stride = stride, + .slice_height = uv_height, + }; + io_cfg[0].offsets[1] = uv_offset; + io_cfg[0].format = CAM_FORMAT_NV12; + io_cfg[0].color_space = 0; + io_cfg[0].color_pattern = 0x0; + io_cfg[0].bpp = 0; + io_cfg[0].resource_type = CAM_ISP_IFE_OUT_RES_FULL; + io_cfg[0].fence = sync_objs_ife[idx]; + io_cfg[0].direction = CAM_BUF_OUTPUT; + io_cfg[0].subsample_pattern = 0x1; + io_cfg[0].framedrop_pattern = 0x1; + } + } + + // *** patches *** + // sets up the kernel driver to do address translation for the IFE + { + // order here corresponds to the one in build_initial_config + assert(patches.size() == 6 || patches.size() == 0); + + pkt->patch_offset = sizeof(struct cam_cmd_buf_desc)*pkt->num_cmd_buf + sizeof(struct cam_buf_io_cfg)*pkt->num_io_configs; + if (patches.size() > 0) { + // linearization LUT + add_patch(pkt.get(), ife_cmd.handle, patches[0], ife_linearization_lut.handle, 0); + + // vignetting correction LUTs + add_patch(pkt.get(), ife_cmd.handle, patches[1], ife_vignetting_lut.handle, 0); + add_patch(pkt.get(), ife_cmd.handle, patches[2], ife_vignetting_lut.handle, ife_vignetting_lut.size); + + // gamma LUTs + for (int i = 0; i < 3; i++) { + add_patch(pkt.get(), ife_cmd.handle, patches[i+3], ife_gamma_lut.handle, ife_gamma_lut.size*i); + } + } + } + + int ret = device_config(m->isp_fd, session_handle, isp_dev_handle, cam_packet_handle); + assert(ret == 0); +} + +void SpectraCamera::enqueue_frame(uint64_t request_id) { + int i = request_id % ife_buf_depth; + assert(sync_objs_ife[i] == 0); + + // create output fences + struct cam_sync_info sync_create = {0}; + strcpy(sync_create.name, "NodeOutputPortFence"); + int ret = do_sync_control(m->cam_sync_fd, CAM_SYNC_CREATE, &sync_create, sizeof(sync_create)); + if (ret != 0) { + LOGE("failed to create fence: %d %d", ret, sync_create.sync_obj); + } else { + sync_objs_ife[i] = sync_create.sync_obj; + } + + if (icp_dev_handle > 0) { + ret = do_cam_control(m->cam_sync_fd, CAM_SYNC_CREATE, &sync_create, sizeof(sync_create)); + if (ret != 0) { + LOGE("failed to create fence: %d %d", ret, sync_create.sync_obj); + } else { + sync_objs_bps[i] = sync_create.sync_obj; + } + } + + // schedule request with camera request manager + struct cam_req_mgr_sched_request req_mgr_sched_request = {0}; + req_mgr_sched_request.session_hdl = session_handle; + req_mgr_sched_request.link_hdl = link_handle; + req_mgr_sched_request.req_id = request_id; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_SCHED_REQ, &req_mgr_sched_request, sizeof(req_mgr_sched_request)); + if (ret != 0) { + LOGE("failed to schedule cam mgr request: %d %lu", ret, request_id); + } + + // poke sensor, must happen after schedule + sensors_poke(request_id); + + // submit request to IFE and BPS + config_ife(i, request_id); + if (cc.output_type == ISP_BPS_PROCESSED) config_bps(i, request_id); +} + +void SpectraCamera::destroySyncObjectAt(int index) { + auto destroy_sync_obj = [](int cam_sync_fd, int32_t &sync_obj) { + if (sync_obj == 0) return; + + struct cam_sync_info sync_destroy = {.sync_obj = sync_obj}; + int ret = do_sync_control(cam_sync_fd, CAM_SYNC_DESTROY, &sync_destroy, sizeof(sync_destroy)); + if (ret != 0) { + LOGE("Failed to destroy sync object: %d, sync_obj: %d", ret, sync_destroy.sync_obj); + } + + sync_obj = 0; // Reset the sync object to 0 + }; + + destroy_sync_obj(m->cam_sync_fd, sync_objs_ife[index]); + destroy_sync_obj(m->cam_sync_fd, sync_objs_bps[index]); +} + +void SpectraCamera::camera_map_bufs() { + int ret; + for (int i = 0; i < ife_buf_depth; i++) { + // map our VisionIPC bufs into ISP memory + struct cam_mem_mgr_map_cmd mem_mgr_map_cmd = {0}; + mem_mgr_map_cmd.flags = CAM_MEM_FLAG_HW_READ_WRITE; + mem_mgr_map_cmd.mmu_hdls[0] = m->device_iommu; + mem_mgr_map_cmd.num_hdl = 1; + if (icp_dev_handle > 0) { + mem_mgr_map_cmd.num_hdl = 2; + mem_mgr_map_cmd.mmu_hdls[1] = m->icp_device_iommu; + } + + if (cc.output_type != ISP_IFE_PROCESSED) { + // RAW bayer images + mem_mgr_map_cmd.fd = buf.camera_bufs_raw[i].fd; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd)); + assert(ret == 0); + LOGD("map buf req: (fd: %d) 0x%x %d", buf.camera_bufs_raw[i].fd, mem_mgr_map_cmd.out.buf_handle, ret); + buf_handle_raw[i] = mem_mgr_map_cmd.out.buf_handle; + } + + if (cc.output_type != ISP_RAW_OUTPUT) { + // final processed images + VisionBuf *vb = buf.vipc_server->get_buffer(buf.stream_type, i); + mem_mgr_map_cmd.fd = vb->fd; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_MAP_BUF, &mem_mgr_map_cmd, sizeof(mem_mgr_map_cmd)); + LOGD("map buf req: (fd: %d) 0x%x %d", vb->fd, mem_mgr_map_cmd.out.buf_handle, ret); + buf_handle_yuv[i] = mem_mgr_map_cmd.out.buf_handle; + } + } +} + +bool SpectraCamera::openSensor() { + sensor_fd = open_v4l_by_name_and_index("cam-sensor-driver", cc.camera_num); + assert(sensor_fd >= 0); + LOGD("opened sensor for %d", cc.camera_num); + + LOGD("-- Probing sensor %d", cc.camera_num); + + auto init_sensor_lambda = [this](SensorInfo *s) { + if (s->image_sensor == cereal::FrameData::ImageSensor::OS04C10 && cc.output_type == ISP_IFE_PROCESSED) { + ((OS04C10*)s)->ife_downscale_configure(); + } + sensor.reset(s); + return (sensors_init() == 0); + }; + + // Figure out which sensor we have + if (!init_sensor_lambda(new OX03C10) && + !init_sensor_lambda(new OS04C10)) { + LOGE("** sensor %d FAILED bringup, disabling", cc.camera_num); + enabled = false; + return false; + } + LOGD("-- Probing sensor %d success", cc.camera_num); + + // create session + struct cam_req_mgr_session_info session_info = {}; + int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_CREATE_SESSION, &session_info, sizeof(session_info)); + LOGD("get session: %d 0x%X", ret, session_info.session_hdl); + session_handle = session_info.session_hdl; + + // access the sensor + LOGD("-- Accessing sensor"); + auto sensor_dev_handle_ = device_acquire(sensor_fd, session_handle, nullptr); + assert(sensor_dev_handle_); + sensor_dev_handle = *sensor_dev_handle_; + LOGD("acquire sensor dev"); + + LOG("-- Configuring sensor"); + sensors_i2c(sensor->init_reg_array.data(), sensor->init_reg_array.size(), CAM_SENSOR_PACKET_OPCODE_SENSOR_CONFIG, sensor->data_word); + return true; +} + +void SpectraCamera::configISP() { + if (!enabled) return; + + struct cam_isp_in_port_info in_port_info = { + // ISP input to the CSID + .res_type = cc.phy, + .lane_type = CAM_ISP_LANE_TYPE_DPHY, + .lane_num = 4, + .lane_cfg = 0x3210, + + .vc = 0x0, + .dt = sensor->frame_data_type, + .format = sensor->mipi_format, + + .test_pattern = sensor->bayer_pattern, + .usage_type = 0x0, + + .left_start = 0, + .left_stop = sensor->frame_width - 1, + .left_width = sensor->frame_width, + + .right_start = 0, + .right_stop = sensor->frame_width - 1, + .right_width = sensor->frame_width, + + .line_start = sensor->frame_offset, + .line_stop = sensor->frame_height + sensor->frame_offset - 1, + .height = sensor->frame_height + sensor->frame_offset, + + .pixel_clk = 0x0, + .batch_size = 0x0, + .dsp_mode = CAM_ISP_DSP_MODE_NONE, + .hbi_cnt = 0x0, + .custom_csid = 0x0, + + // ISP outputs + .num_out_res = 0x1, + .data[0] = (struct cam_isp_out_port_info){ + .res_type = CAM_ISP_IFE_OUT_RES_FULL, + .format = CAM_FORMAT_NV12, + .width = buf.out_img_width, + .height = buf.out_img_height + sensor->extra_height, + .comp_grp_id = 0x0, .split_point = 0x0, .secure_mode = 0x0, + }, + }; + + if (cc.output_type != ISP_IFE_PROCESSED) { + in_port_info.line_start = 0; + in_port_info.line_stop = sensor->frame_height + sensor->extra_height - 1; + in_port_info.height = sensor->frame_height + sensor->extra_height; + + in_port_info.data[0].res_type = CAM_ISP_IFE_OUT_RES_RDI_0; + in_port_info.data[0].format = sensor->mipi_format; + } + + struct cam_isp_resource isp_resource = { + .resource_id = CAM_ISP_RES_ID_PORT, + .handle_type = CAM_HANDLE_USER_POINTER, + .res_hdl = (uint64_t)&in_port_info, + .length = sizeof(in_port_info), + }; + + auto isp_dev_handle_ = device_acquire(m->isp_fd, session_handle, &isp_resource); + assert(isp_dev_handle_); + isp_dev_handle = *isp_dev_handle_; + LOGD("acquire isp dev"); + + // allocate IFE memory, then configure it + ife_cmd.init(m, 67984, 0x20, false, m->device_iommu, m->cdm_iommu, ife_buf_depth); + if (cc.output_type == ISP_IFE_PROCESSED) { + assert(sensor->gamma_lut_rgb.size() == 64); + ife_gamma_lut.init(m, sensor->gamma_lut_rgb.size()*sizeof(uint32_t), 0x20, false, m->device_iommu, m->cdm_iommu, 3); // 3 for RGB + for (int i = 0; i < 3; i++) { + memcpy(ife_gamma_lut.ptr + ife_gamma_lut.size*i, sensor->gamma_lut_rgb.data(), ife_gamma_lut.size); + } + assert(sensor->linearization_lut.size() == 36); + ife_linearization_lut.init(m, sensor->linearization_lut.size()*sizeof(uint32_t), 0x20, false, m->device_iommu, m->cdm_iommu); + memcpy(ife_linearization_lut.ptr, sensor->linearization_lut.data(), ife_linearization_lut.size); + assert(sensor->vignetting_lut.size() == 221); + ife_vignetting_lut.init(m, sensor->vignetting_lut.size()*sizeof(uint32_t), 0x20, false, m->device_iommu, m->cdm_iommu, 2); + for (int i = 0; i < 2; i++) { + memcpy(ife_vignetting_lut.ptr + ife_vignetting_lut.size*i, sensor->vignetting_lut.data(), ife_vignetting_lut.size); + } + } + + config_ife(0, 1, true); +} + +void SpectraCamera::configICP() { + /* + Configures both the ICP and BPS. + */ + + int cfg_handle; + + uint32_t cfg_size = sizeof(bps_cfg[0]) / sizeof(bps_cfg[0][0]); + void *cfg = alloc_w_mmu_hdl(m->video0_fd, cfg_size, (uint32_t*)&cfg_handle, 0x1, + CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_HW_SHARED_ACCESS, + m->icp_device_iommu); + memcpy(cfg, bps_cfg[sensor->num()], cfg_size); + + struct cam_icp_acquire_dev_info icp_info = { + .scratch_mem_size = 0x0, + .dev_type = CAM_ICP_RES_TYPE_BPS, + .io_config_cmd_size = cfg_size, + .io_config_cmd_handle = cfg_handle, + .secure_mode = 0, + .num_out_res = 1, + .in_res = (struct cam_icp_res_info){ + .format = 0x9, // RAW MIPI + .width = sensor->frame_width, + .height = sensor->frame_height, + .fps = 20, + }, + .out_res[0] = (struct cam_icp_res_info){ + .format = 0x3, // YUV420NV12 + .width = buf.out_img_width, + .height = buf.out_img_height, + .fps = 20, + }, + }; + auto h = device_acquire(m->icp_fd, session_handle, &icp_info); + assert(h); + icp_dev_handle = *h; + LOGD("acquire icp dev"); + + release(m->video0_fd, cfg_handle); + + // BPS has a lot of buffers to init + bps_cmd.init(m, 464, 0x20, true, m->icp_device_iommu, 0, ife_buf_depth); + + // BPSIQSettings struct + uint32_t settings_size = sizeof(bps_settings[0]) / sizeof(bps_settings[0][0]); + bps_iq.init(m, settings_size, 0x20, true, m->icp_device_iommu); + memcpy(bps_iq.ptr, bps_settings[sensor->num()], settings_size); + + // for cdm register writes, just make it bigger than you need + bps_cdm_program_array.init(m, 0x1000, 0x20, true, m->icp_device_iommu); + + // striping lib output + uint32_t striping_size = sizeof(bps_striping_output[0]) / sizeof(bps_striping_output[0][0]); + bps_striping.init(m, striping_size, 0x20, true, m->icp_device_iommu); + memcpy(bps_striping.ptr, bps_striping_output[sensor->num()], striping_size); + + // used internally by the BPS, we just allocate it. + // size comes from the BPSStripingLib + bps_cdm_striping_bl.init(m, 0xa100, 0x20, true, m->icp_device_iommu); + + // LUTs + /* + bps_linearization_lut.init(m, sensor->linearization_lut.size()*sizeof(uint32_t), 0x20, true, m->icp_device_iommu); + memcpy(bps_linearization_lut.ptr, sensor->linearization_lut.data(), bps_linearization_lut.size); + */ +} + +void SpectraCamera::configCSIPHY() { + csiphy_fd = open_v4l_by_name_and_index("cam-csiphy-driver", cc.camera_num); + assert(csiphy_fd >= 0); + LOGD("opened csiphy for %d", cc.camera_num); + + struct cam_csiphy_acquire_dev_info csiphy_acquire_dev_info = {.combo_mode = 0}; + auto csiphy_dev_handle_ = device_acquire(csiphy_fd, session_handle, &csiphy_acquire_dev_info); + assert(csiphy_dev_handle_); + csiphy_dev_handle = *csiphy_dev_handle_; + LOGD("acquire csiphy dev"); + + // config csiphy + LOG("-- Config CSI PHY"); + { + uint32_t cam_packet_handle = 0; + int size = sizeof(struct cam_packet)+sizeof(struct cam_cmd_buf_desc)*1; + auto pkt = m->mem_mgr.alloc(size, &cam_packet_handle); + pkt->num_cmd_buf = 1; + pkt->kmd_cmd_buf_index = -1; + pkt->header.size = size; + struct cam_cmd_buf_desc *buf_desc = (struct cam_cmd_buf_desc *)&pkt->payload; + + buf_desc[0].size = buf_desc[0].length = sizeof(struct cam_csiphy_info); + buf_desc[0].type = CAM_CMD_BUF_GENERIC; + + auto csiphy_info = m->mem_mgr.alloc(buf_desc[0].size, (uint32_t*)&buf_desc[0].mem_handle); + csiphy_info->lane_mask = 0x1f; + csiphy_info->lane_assign = 0x3210;// skip clk. How is this 16 bit for 5 channels?? + csiphy_info->csiphy_3phase = 0x0; // no 3 phase, only 2 conductors per lane + csiphy_info->combo_mode = 0x0; + csiphy_info->lane_cnt = 0x4; + csiphy_info->secure_mode = 0x0; + csiphy_info->settle_time = MIPI_SETTLE_CNT * 200000000ULL; + csiphy_info->data_rate = 48000000; // Calculated by camera_freqs.py + + int ret_ = device_config(csiphy_fd, session_handle, csiphy_dev_handle, cam_packet_handle); + assert(ret_ == 0); + } +} + +void SpectraCamera::linkDevices() { + LOG("-- Link devices"); + struct cam_req_mgr_link_info req_mgr_link_info = {0}; + req_mgr_link_info.session_hdl = session_handle; + req_mgr_link_info.num_devices = 2; + req_mgr_link_info.dev_hdls[0] = isp_dev_handle; + req_mgr_link_info.dev_hdls[1] = sensor_dev_handle; + int ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_LINK, &req_mgr_link_info, sizeof(req_mgr_link_info)); + assert(ret == 0); + link_handle = req_mgr_link_info.link_hdl; + LOGD("link: %d session: 0x%X isp: 0x%X sensors: 0x%X link: 0x%X", ret, session_handle, isp_dev_handle, sensor_dev_handle, link_handle); + + struct cam_req_mgr_link_control req_mgr_link_control = {0}; + req_mgr_link_control.ops = CAM_REQ_MGR_LINK_ACTIVATE; + req_mgr_link_control.session_hdl = session_handle; + req_mgr_link_control.num_links = 1; + req_mgr_link_control.link_hdls[0] = link_handle; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_LINK_CONTROL, &req_mgr_link_control, sizeof(req_mgr_link_control)); + LOGD("link control: %d", ret); + + ret = device_control(csiphy_fd, CAM_START_DEV, session_handle, csiphy_dev_handle); + LOGD("start csiphy: %d", ret); + assert(ret == 0); + ret = device_control(m->isp_fd, CAM_START_DEV, session_handle, isp_dev_handle); + LOGD("start isp: %d", ret); + assert(ret == 0); + if (cc.output_type == ISP_BPS_PROCESSED) { + ret = device_control(m->icp_fd, CAM_START_DEV, session_handle, icp_dev_handle); + LOGD("start icp: %d", ret); + assert(ret == 0); + } +} + +void SpectraCamera::camera_close() { + LOG("-- Stop devices %d", cc.camera_num); + + if (enabled) { + clear_req_queue(); + + // ret = device_control(sensor_fd, CAM_STOP_DEV, session_handle, sensor_dev_handle); + // LOGD("stop sensor: %d", ret); + int ret = device_control(m->isp_fd, CAM_STOP_DEV, session_handle, isp_dev_handle); + LOGD("stop isp: %d", ret); + if (cc.output_type == ISP_BPS_PROCESSED) { + ret = device_control(m->icp_fd, CAM_STOP_DEV, session_handle, icp_dev_handle); + LOGD("stop icp: %d", ret); + } + ret = device_control(csiphy_fd, CAM_STOP_DEV, session_handle, csiphy_dev_handle); + LOGD("stop csiphy: %d", ret); + + // link control stop + LOG("-- Stop link control"); + struct cam_req_mgr_link_control req_mgr_link_control = {0}; + req_mgr_link_control.ops = CAM_REQ_MGR_LINK_DEACTIVATE; + req_mgr_link_control.session_hdl = session_handle; + req_mgr_link_control.num_links = 1; + req_mgr_link_control.link_hdls[0] = link_handle; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_LINK_CONTROL, &req_mgr_link_control, sizeof(req_mgr_link_control)); + LOGD("link control stop: %d", ret); + + // unlink + LOG("-- Unlink"); + struct cam_req_mgr_unlink_info req_mgr_unlink_info = {0}; + req_mgr_unlink_info.session_hdl = session_handle; + req_mgr_unlink_info.link_hdl = link_handle; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_UNLINK, &req_mgr_unlink_info, sizeof(req_mgr_unlink_info)); + LOGD("unlink: %d", ret); + + // release devices + LOGD("-- Release devices"); + ret = device_control(m->isp_fd, CAM_RELEASE_DEV, session_handle, isp_dev_handle); + LOGD("release isp: %d", ret); + if (cc.output_type == ISP_BPS_PROCESSED) { + ret = device_control(m->icp_fd, CAM_RELEASE_DEV, session_handle, icp_dev_handle); + LOGD("release icp: %d", ret); + } + ret = device_control(csiphy_fd, CAM_RELEASE_DEV, session_handle, csiphy_dev_handle); + LOGD("release csiphy: %d", ret); + + for (int i = 0; i < ife_buf_depth; i++) { + if (buf_handle_raw[i]) { + release(m->video0_fd, buf_handle_raw[i]); + } + if (buf_handle_yuv[i]) { + release(m->video0_fd, buf_handle_yuv[i]); + } + } + LOGD("released buffers"); + } + + int ret = device_control(sensor_fd, CAM_RELEASE_DEV, session_handle, sensor_dev_handle); + LOGD("release sensor: %d", ret); + + // destroyed session + struct cam_req_mgr_session_info session_info = {.session_hdl = session_handle}; + ret = do_cam_control(m->video0_fd, CAM_REQ_MGR_DESTROY_SESSION, &session_info, sizeof(session_info)); + LOGD("destroyed session %d: %d", cc.camera_num, ret); +} + +bool SpectraCamera::handle_camera_event(const cam_req_mgr_message *event_data) { + /* + Handles camera SOF event. Returns true if the frame is valid for publishing. + */ + + uint64_t request_id = event_data->u.frame_msg.request_id; // ID from the camera request manager + uint64_t frame_id_raw = event_data->u.frame_msg.frame_id; // raw as opposed to our re-indexed frame ID + uint64_t timestamp = event_data->u.frame_msg.timestamp; // timestamped in the kernel's SOF IRQ callback + //LOGD("handle cam %d ts %lu req id %lu frame id %lu", cc.camera_num, timestamp, request_id, frame_id_raw); + + // if there's a lag, some more frames could have already come in before + // we cleared the queue, so we'll still get them with valid (> 0) request IDs. + if (timestamp < last_requeue_ts) { + LOGD("skipping frame: ts before requeue / cam %d ts %lu req id %lu frame id %lu", cc.camera_num, timestamp, request_id, frame_id_raw); + return false; + } + + if (stress_test("skipping SOF event")) { + return false; + } + + if (!validateEvent(request_id, frame_id_raw)) { + return false; + } + + // Update tracking variables + if (request_id == request_id_last + 1) { + skip_expected = false; + } + frame_id_raw_last = frame_id_raw; + request_id_last = request_id; + + // Wait until frame's fully read out and processed + if (!waitForFrameReady(request_id)) { + // Reset queue on sync failure to prevent frame tearing + LOGE("camera %d sync failure %ld %ld ", cc.camera_num, request_id, frame_id_raw); + clearAndRequeue(request_id + 1); + return false; + } + + int buf_idx = request_id % ife_buf_depth; + bool ret = processFrame(buf_idx, request_id, frame_id_raw, timestamp); + destroySyncObjectAt(buf_idx); + enqueue_frame(request_id + ife_buf_depth); // request next frame for this slot + return ret; +} + +bool SpectraCamera::validateEvent(uint64_t request_id, uint64_t frame_id_raw) { + // check if the request ID is even valid. this happens after queued + // requests are cleared. unclear if it happens any other time. + if (request_id == 0) { + if (invalid_request_count++ > ife_buf_depth+2) { + LOGE("camera %d reset after half second of invalid requests", cc.camera_num); + clearAndRequeue(request_id_last + 1); + invalid_request_count = 0; + } + return false; + } + invalid_request_count = 0; + + // check for skips in frame_id or request_id + if (!skip_expected) { + if (frame_id_raw != frame_id_raw_last + 1) { + LOGE("camera %d frame ID skipped, %lu -> %lu", cc.camera_num, frame_id_raw_last, frame_id_raw); + clearAndRequeue(request_id + 1); + return false; + } + + if (request_id != request_id_last + 1) { + LOGE("camera %d requests skipped %ld -> %ld", cc.camera_num, request_id_last, request_id); + clearAndRequeue(request_id + 1); + return false; + } + } + return true; +} + +void SpectraCamera::clearAndRequeue(uint64_t from_request_id) { + // clear everything, then queue up a fresh set of frames + LOGW("clearing and requeuing camera %d from %lu", cc.camera_num, from_request_id); + clear_req_queue(); + last_requeue_ts = nanos_since_boot(); + for (uint64_t id = from_request_id; id < from_request_id + ife_buf_depth; ++id) { + enqueue_frame(id); + } + skip_expected = true; +} + +bool SpectraCamera::waitForFrameReady(uint64_t request_id) { + int buf_idx = request_id % ife_buf_depth; + assert(sync_objs_ife[buf_idx]); + + if (stress_test("sync sleep time")) { + util::sleep_for(350); + return false; + } + + auto waitForSync = [&](uint32_t sync_obj, int timeout_ms, const char *sync_type) { + double st = millis_since_boot(); + struct cam_sync_wait sync_wait = {}; + sync_wait.sync_obj = sync_obj; + sync_wait.timeout_ms = stress_test(sync_type) ? 1 : timeout_ms; + bool ret = do_sync_control(m->cam_sync_fd, CAM_SYNC_WAIT, &sync_wait, sizeof(sync_wait)) == 0; + double et = millis_since_boot(); + if (!ret) LOGE("camera %d %s failed after %.2fms", cc.camera_num, sync_type, et-st); + return ret; + }; + + // wait for frame from IFE + // - in RAW_OUTPUT mode, this time is just the frame readout from the sensor + // - in IFE_PROCESSED mode, this time also includes image processing (~1ms) + bool success = waitForSync(sync_objs_ife[buf_idx], 100, "IFE sync"); + if (success && sync_objs_bps[buf_idx]) { + // BPS is typically 7ms + success = waitForSync(sync_objs_bps[buf_idx], 50, "BPS sync"); + } + + return success; +} + +bool SpectraCamera::processFrame(int buf_idx, uint64_t request_id, uint64_t frame_id_raw, uint64_t timestamp) { + if (!syncFirstFrame(cc.camera_num, request_id, frame_id_raw, timestamp)) { + return false; + } + + // in IFE_PROCESSED mode, we can't know the true EOF, so recover it with sensor readout time + uint64_t timestamp_eof = timestamp + sensor->readout_time_ns; + + // Update buffer and frame data + buf.cur_buf_idx = buf_idx; + buf.cur_frame_data = { + .frame_id = (uint32_t)(frame_id_raw - camera_sync_data[cc.camera_num].frame_id_offset), + .request_id = (uint32_t)request_id, + .timestamp_sof = timestamp, + .timestamp_eof = timestamp_eof, + .processing_time = float((nanos_since_boot() - timestamp_eof) * 1e-9) + }; + return true; +} + +bool SpectraCamera::syncFirstFrame(int camera_id, uint64_t request_id, uint64_t raw_id, uint64_t timestamp) { + if (first_frame_synced) return true; + + // Store the frame data for this camera + camera_sync_data[camera_id] = SyncData{timestamp, raw_id + 1}; + + // Ensure all cameras are up + int enabled_camera_count = std::count_if(std::begin(ALL_CAMERA_CONFIGS), std::end(ALL_CAMERA_CONFIGS), + [](const auto &config) { return config.enabled; }); + bool all_cams_up = camera_sync_data.size() == enabled_camera_count; + + // Wait until the timestamps line up + bool all_cams_synced = true; + for (const auto &[_, sync_data] : camera_sync_data) { + uint64_t diff = std::max(timestamp, sync_data.timestamp) - + std::min(timestamp, sync_data.timestamp); + if (diff > 0.2*1e6) { // milliseconds + all_cams_synced = false; + } + } + + if (all_cams_up && all_cams_synced) { + first_frame_synced = true; + for (const auto&[cam, sync_data] : camera_sync_data) { + LOGW("camera %d synced on frame_id_offset %ld timestamp %lu", cam, sync_data.frame_id_offset, sync_data.timestamp); + } + } + + // Timeout in case the timestamps never line up + if (raw_id > 40) { + LOGE("camera first frame sync timed out"); + first_frame_synced = true; + } + + return false; +} diff --git a/system/camerad/cameras/spectra.h b/system/camerad/cameras/spectra.h new file mode 100644 index 0000000000..13cb13f98f --- /dev/null +++ b/system/camerad/cameras/spectra.h @@ -0,0 +1,219 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "media/cam_req_mgr.h" + +#include "common/util.h" +#include "common/swaglog.h" +#include "system/camerad/cameras/hw.h" +#include "system/camerad/cameras/camera_common.h" +#include "system/camerad/sensors/sensor.h" + +#define MAX_IFE_BUFS 20 + +const int MIPI_SETTLE_CNT = 33; // Calculated by camera_freqs.py + +// For use with the Titan 170 ISP in the SDM845 +// https://github.com/commaai/agnos-kernel-sdm845 + +// CSLDeviceType/CSLPacketOpcodesIFE from camx +// cam_packet_header.op_code = (device << 24) | (opcode); +#define CSLDeviceTypeImageSensor (0x01 << 24) +#define CSLDeviceTypeIFE (0x0F << 24) +#define CSLDeviceTypeBPS (0x10 << 24) +#define OpcodesIFEInitialConfig 0x0 +#define OpcodesIFEUpdate 0x1 + +std::optional device_acquire(int fd, int32_t session_handle, void *data, uint32_t num_resources=1); +int device_config(int fd, int32_t session_handle, int32_t dev_handle, uint64_t packet_handle); +int device_control(int fd, int op_code, int session_handle, int dev_handle); +int do_cam_control(int fd, int op_code, void *handle, int size); +void *alloc_w_mmu_hdl(int video0_fd, int len, uint32_t *handle, int align = 8, int flags = CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE, + int mmu_hdl = 0, int mmu_hdl2 = 0); +void release(int video0_fd, uint32_t handle); + +class MemoryManager { +public: + void init(int _video0_fd) { video0_fd = _video0_fd; } + ~MemoryManager(); + + template + auto alloc(int len, uint32_t *handle) { + return std::unique_ptr>((T*)alloc_buf(len, handle), [this](void *ptr) { this->free(ptr); }); + } + +private: + void *alloc_buf(int len, uint32_t *handle); + void free(void *ptr); + + std::map handle_lookup; + std::map size_lookup; + std::map > cached_allocations; + int video0_fd; +}; + +class SpectraMaster { +public: + void init(); + + unique_fd video0_fd; + unique_fd cam_sync_fd; + unique_fd isp_fd; + unique_fd icp_fd; + int device_iommu = -1; + int cdm_iommu = -1; + int icp_device_iommu = -1; + MemoryManager mem_mgr; +}; + +class SpectraBuf { +public: + SpectraBuf() = default; + + ~SpectraBuf() { + if (video_fd >= 0 && ptr) { + munmap(ptr, mmap_size); + release(video_fd, handle); + } + } + + void init(SpectraMaster *m, int s, int a, bool shared_access, int mmu_hdl = 0, int mmu_hdl2 = 0, int count = 1) { + video_fd = m->video0_fd; + size = s; + alignment = a; + mmap_size = aligned_size() * count; + + uint32_t flags = CAM_MEM_FLAG_HW_READ_WRITE | CAM_MEM_FLAG_KMD_ACCESS | CAM_MEM_FLAG_UMD_ACCESS | CAM_MEM_FLAG_CMD_BUF_TYPE; + if (shared_access) { + flags |= CAM_MEM_FLAG_HW_SHARED_ACCESS; + } + + void *p = alloc_w_mmu_hdl(video_fd, mmap_size, (uint32_t*)&handle, alignment, flags, mmu_hdl, mmu_hdl2); + ptr = (unsigned char*)p; + assert(ptr != NULL); + }; + + uint32_t aligned_size() { + return ALIGNED_SIZE(size, alignment); + }; + + int video_fd = -1; + unsigned char *ptr = nullptr; + int size = 0, alignment = 0, handle = 0, mmap_size = 0; +}; + +class SpectraCamera { +public: + SpectraCamera(SpectraMaster *master, const CameraConfig &config); + ~SpectraCamera(); + + void camera_open(VisionIpcServer *v, cl_device_id device_id, cl_context ctx); + bool handle_camera_event(const cam_req_mgr_message *event_data); + void camera_close(); + void camera_map_bufs(); + void config_bps(int idx, int request_id); + void config_ife(int idx, int request_id, bool init=false); + + int clear_req_queue(); + void enqueue_frame(uint64_t request_id); + + int sensors_init(); + void sensors_start(); + void sensors_poke(int request_id); + void sensors_i2c(const struct i2c_random_wr_payload* dat, int len, int op_code, bool data_word); + + bool openSensor(); + void configISP(); + void configICP(); + void configCSIPHY(); + void linkDevices(); + void destroySyncObjectAt(int index); + + // *** state *** + + int ife_buf_depth = -1; + bool open = false; + bool enabled = true; + CameraConfig cc; + std::unique_ptr sensor; + + // YUV image size + uint32_t stride; + uint32_t y_height; + uint32_t uv_height; + uint32_t uv_offset; + uint32_t yuv_size; + + unique_fd sensor_fd; + unique_fd csiphy_fd; + + int32_t session_handle = -1; + int32_t sensor_dev_handle = -1; + int32_t isp_dev_handle = -1; + int32_t icp_dev_handle = -1; + int32_t csiphy_dev_handle = -1; + + int32_t link_handle = -1; + + SpectraBuf ife_cmd; + SpectraBuf ife_gamma_lut; + SpectraBuf ife_linearization_lut; + SpectraBuf ife_vignetting_lut; + + SpectraBuf bps_cmd; + SpectraBuf bps_cdm_buffer; + SpectraBuf bps_cdm_program_array; + SpectraBuf bps_cdm_striping_bl; + SpectraBuf bps_iq; + SpectraBuf bps_striping; + SpectraBuf bps_linearization_lut; + std::vector bps_lin_reg; + std::vector bps_ccm_reg; + + int buf_handle_yuv[MAX_IFE_BUFS] = {}; + int buf_handle_raw[MAX_IFE_BUFS] = {}; + int sync_objs_ife[MAX_IFE_BUFS] = {}; + int sync_objs_bps[MAX_IFE_BUFS] = {}; + uint64_t request_id_last = 0; + uint64_t last_requeue_ts = 0; + uint64_t frame_id_raw_last = 0; + int invalid_request_count = 0; + bool skip_expected = true; + + CameraBuf buf; + SpectraMaster *m; + +private: + void clearAndRequeue(uint64_t from_request_id); + bool validateEvent(uint64_t request_id, uint64_t frame_id_raw); + bool waitForFrameReady(uint64_t request_id); + bool processFrame(int buf_idx, uint64_t request_id, uint64_t frame_id_raw, uint64_t timestamp); + static bool syncFirstFrame(int camera_id, uint64_t request_id, uint64_t raw_id, uint64_t timestamp); + struct SyncData { + uint64_t timestamp; + uint64_t frame_id_offset = 0; + }; + inline static std::map camera_sync_data; + inline static bool first_frame_synced = false; + + // a mode for stressing edge cases: realignment, sync failures, etc. + inline bool stress_test(std::string log) { + static double last_trigger = 0; + static double prob = std::stod(util::getenv("SPECTRA_ERROR_PROB", "-1")); + static double dt = std::stod(util::getenv("SPECTRA_ERROR_DT", "1")); + bool triggered = (prob > 0) && \ + ((static_cast(rand()) / RAND_MAX) < prob) && \ + (millis_since_boot() - last_trigger) > dt; + if (triggered) { + last_trigger = millis_since_boot(); + LOGE("stress test (cam %d): %s", cc.camera_num, log.c_str()); + } + return triggered; + } +}; diff --git a/system/camerad/main.cc b/system/camerad/main.cc new file mode 100644 index 0000000000..05fdef1a65 --- /dev/null +++ b/system/camerad/main.cc @@ -0,0 +1,15 @@ +#include "system/camerad/cameras/camera_common.h" + +#include + +#include "common/params.h" +#include "common/util.h" + +int main(int argc, char *argv[]) { + // doesn't need RT priority since we're using isolcpus + int ret = util::set_core_affinity({6}); + assert(ret == 0 || Params().getBool("IsOffroad")); // failure ok while offroad due to offlining cores + + camerad_thread(); + return 0; +} diff --git a/system/camerad/sensors/os04c10.cc b/system/camerad/sensors/os04c10.cc new file mode 100644 index 0000000000..38be4ecca4 --- /dev/null +++ b/system/camerad/sensors/os04c10.cc @@ -0,0 +1,145 @@ +#include + +#include "system/camerad/sensors/sensor.h" + +namespace { + +const float sensor_analog_gains_OS04C10[] = { + 1.0, 1.0625, 1.125, 1.1875, 1.25, 1.3125, 1.375, 1.4375, 1.5, 1.5625, 1.6875, + 1.8125, 1.9375, 2.0, 2.125, 2.25, 2.375, 2.5, 2.625, 2.75, 2.875, 3.0, + 3.125, 3.375, 3.625, 3.875, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, + 5.75, 6.0, 6.25, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, + 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5}; + +const uint32_t os04c10_analog_gains_reg[] = { + 0x080, 0x088, 0x090, 0x098, 0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0C0, 0x0C8, 0x0D8, + 0x0E8, 0x0F8, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, + 0x190, 0x1B0, 0x1D0, 0x1F0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, + 0x2E0, 0x300, 0x320, 0x340, 0x380, 0x3C0, 0x400, 0x440, 0x480, 0x4C0, 0x500, + 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780, 0x7C0}; + +} // namespace + +void OS04C10::ife_downscale_configure() { + out_scale = 2; + + pixel_size_mm = 0.002; + frame_width = 2688; + frame_height = 1520; + exposure_time_max = 2352; + + init_reg_array.insert(init_reg_array.end(), std::begin(ife_downscale_override_array_os04c10), std::end(ife_downscale_override_array_os04c10)); +} + +OS04C10::OS04C10() { + image_sensor = cereal::FrameData::ImageSensor::OS04C10; + bayer_pattern = CAM_ISP_PATTERN_BAYER_BGBGBG; + pixel_size_mm = 0.004; + data_word = false; + + // hdr_offset = 64 * 2 + 8; // stagger + frame_width = 1344; + frame_height = 760; //760 * 2 + hdr_offset; + frame_stride = (frame_width * 12 / 8); // no alignment + + extra_height = 0; + frame_offset = 0; + + start_reg_array.assign(std::begin(start_reg_array_os04c10), std::end(start_reg_array_os04c10)); + init_reg_array.assign(std::begin(init_array_os04c10), std::end(init_array_os04c10)); + probe_reg_addr = 0x300a; + probe_expected_data = 0x5304; + bits_per_pixel = 12; + mipi_format = CAM_FORMAT_MIPI_RAW_12; + frame_data_type = 0x2c; + mclk_frequency = 24000000; // Hz + + // TODO: this was set from logs. actually calculate it out + readout_time_ns = 11000000; + + ev_scale = 150.0; + dc_gain_factor = 1; + dc_gain_min_weight = 1; // always on is fine + dc_gain_max_weight = 1; + dc_gain_on_grey = 0.9; + dc_gain_off_grey = 1.0; + exposure_time_min = 2; + exposure_time_max = 1684; + analog_gain_min_idx = 0x0; + analog_gain_rec_idx = 0x0; // 1x + analog_gain_max_idx = 0x28; + analog_gain_cost_delta = -1; + analog_gain_cost_low = 0.4; + analog_gain_cost_high = 6.4; + for (int i = 0; i <= analog_gain_max_idx; i++) { + sensor_analog_gains[i] = sensor_analog_gains_OS04C10[i]; + } + min_ev = exposure_time_min * sensor_analog_gains[analog_gain_min_idx]; + max_ev = exposure_time_max * dc_gain_factor * sensor_analog_gains[analog_gain_max_idx]; + target_grey_factor = 0.01; + + black_level = 48; + color_correct_matrix = { + 0x000000c2, 0x00000fe0, 0x00000fde, + 0x00000fa7, 0x000000d9, 0x00001000, + 0x00000fca, 0x00000fef, 0x000000c7, + }; + for (int i = 0; i < 65; i++) { + float fx = i / 64.0; + gamma_lut_rgb.push_back((uint32_t)((10*fx)/(1+9*fx)*1023.0 + 0.5)); + } + prepare_gamma_lut(); + linearization_lut = { + 0x02000000, 0x02000000, 0x02000000, 0x02000000, + 0x020007ff, 0x020007ff, 0x020007ff, 0x020007ff, + 0x02000bff, 0x02000bff, 0x02000bff, 0x02000bff, + 0x020017ff, 0x020017ff, 0x020017ff, 0x020017ff, + 0x02001bff, 0x02001bff, 0x02001bff, 0x02001bff, + 0x020023ff, 0x020023ff, 0x020023ff, 0x020023ff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + }; + linearization_pts = {0x07ff0bff, 0x17ff1bff, 0x23ff3fff, 0x3fff3fff}; + vignetting_lut = { + 0x01064832, 0x00da26d1, 0x00bb25d9, 0x00aac556, 0x00a06503, 0x009a64d3, 0x009744ba, 0x009744ba, 0x009a24d1, 0x00a00500, 0x00aa2551, 0x00ba45d2, 0x00d826c1, 0x01040820, 0x013729b9, 0x0171ab8d, 0x01b36d9b, + 0x00eee777, 0x00c2c616, 0x00ae2571, 0x009fe4ff, 0x0096e4b7, 0x0090e487, 0x008d446a, 0x008d2469, 0x0090a485, 0x009684b4, 0x009f64fb, 0x00ad456a, 0x00c1a60d, 0x00eca765, 0x011fc8fe, 0x015a4ad2, 0x019c0ce0, + 0x00dee6f7, 0x00b9c5ce, 0x00a5652b, 0x009964cb, 0x00904482, 0x00892449, 0x0085842c, 0x0085642b, 0x0088e447, 0x008fe47f, 0x0098e4c7, 0x00a4c526, 0x00b8a5c5, 0x00dc86e4, 0x010fc87e, 0x014a2a51, 0x018c0c60, + 0x00d626b1, 0x00b4e5a7, 0x00a1e50f, 0x0095e4af, 0x008c2461, 0x00850428, 0x0081640b, 0x0081440a, 0x0084a425, 0x008ba45d, 0x009564ab, 0x00a1450a, 0x00b3c59e, 0x00d3e69f, 0x01070838, 0x01418a0c, 0x01834c1a, + 0x00d4c6a6, 0x00b425a1, 0x00a1450a, 0x009544aa, 0x008b645b, 0x00844422, 0x0080a405, 0x0080a405, 0x00840420, 0x008b0458, 0x0094c4a6, 0x00a0a505, 0x00b30598, 0x00d26693, 0x0105a82d, 0x01402a01, 0x0181ec0f, + 0x00daa6d5, 0x00b765bb, 0x00a3c51e, 0x0097a4bd, 0x008e4472, 0x00872439, 0x0083841c, 0x0083641b, 0x0086e437, 0x008de46f, 0x009724b9, 0x00a30518, 0x00b665b3, 0x00d866c3, 0x010b885c, 0x01460a30, 0x0187ec3f, + 0x00e80740, 0x00bec5f6, 0x00aa6553, 0x009d24e9, 0x009404a0, 0x008d846c, 0x0089e44f, 0x0089e44f, 0x008d446a, 0x0093c49e, 0x009ca4e5, 0x00a9854c, 0x00bdc5ee, 0x00e5a72d, 0x0118c8c6, 0x01534a9a, 0x01952ca9, + 0x00fca7e5, 0x00d06683, 0x00b5c5ae, 0x00a5852c, 0x009c84e4, 0x009664b3, 0x0093649b, 0x0093449a, 0x009624b1, 0x009c24e1, 0x00a50528, 0x00b4e5a7, 0x00ce8674, 0x00fa47d2, 0x012d696b, 0x0167eb3f, 0x01a9cd4e, + 0x011888c4, 0x00ec6763, 0x00c7863c, 0x00b4e5a7, 0x00a8a545, 0x00a1c50e, 0x009ec4f6, 0x009ea4f5, 0x00a1a50d, 0x00a82541, 0x00b445a2, 0x00c5e62f, 0x00ea6753, 0x011648b2, 0x01496a4b, 0x0183ec1f, 0x01c5ae2d, + 0x013bc9de, 0x010fa87d, 0x00eac756, 0x00cd466a, 0x00bc25e1, 0x00b405a0, 0x00afc57e, 0x00afa57d, 0x00b3a59d, 0x00bbc5de, 0x00cc0660, 0x00e92749, 0x010da86d, 0x013989cc, 0x016cab65, 0x01a72d39, 0x01e8ef47, + 0x01666b33, 0x013a49d2, 0x011568ab, 0x00f7e7bf, 0x00e1c70e, 0x00d2e697, 0x00cb665b, 0x00cb2659, 0x00d26693, 0x00e0c706, 0x00f6a7b5, 0x0113c89e, 0x013849c2, 0x01642b21, 0x01974cba, 0x01d1ce8e, 0x0213909c, + 0x01986cc3, 0x016c2b61, 0x01476a3b, 0x0129e94f, 0x0113a89d, 0x0104c826, 0x00fd47ea, 0x00fd27e9, 0x01044822, 0x0112c896, 0x0128a945, 0x0145ca2e, 0x016a4b52, 0x01960cb0, 0x01c92e49, 0x0203b01d, 0x0245922c, + 0x01d1ae8d, 0x01a58d2c, 0x0180ac05, 0x01632b19, 0x014cea67, 0x013e29f1, 0x013689b4, 0x013669b3, 0x013d89ec, 0x014c0a60, 0x0161eb0f, 0x017f0bf8, 0x01a38d1c, 0x01cf4e7a, 0x02029014, 0x023d11e8, 0x027ed3f6, + }; +} + +std::vector OS04C10::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { + uint32_t long_time = exposure_time; + uint32_t real_gain = os04c10_analog_gains_reg[new_exp_g]; + + return { + {0x3501, long_time>>8}, {0x3502, long_time&0xFF}, + {0x3508, real_gain>>8}, {0x3509, real_gain&0xFF}, + {0x350c, real_gain>>8}, {0x350d, real_gain&0xFF}, + }; +} + +int OS04C10::getSlaveAddress(int port) const { + assert(port >= 0 && port <= 2); + return (int[]){0x6C, 0x20, 0x6C}[port]; +} + +float OS04C10::getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const { + float score = std::abs(desired_ev - (exp_t * exp_gain)); + float m = exp_g_idx > analog_gain_rec_idx ? analog_gain_cost_high : analog_gain_cost_low; + score += std::abs(exp_g_idx - (int)analog_gain_rec_idx) * m; + score += ((1 - analog_gain_cost_delta) + + analog_gain_cost_delta * (exp_g_idx - analog_gain_min_idx) / (analog_gain_max_idx - analog_gain_min_idx)) * + std::abs(exp_g_idx - gain_idx) * 3.0; + return score; +} diff --git a/system/camerad/sensors/os04c10_registers.h b/system/camerad/sensors/os04c10_registers.h new file mode 100644 index 0000000000..7cd9e97be5 --- /dev/null +++ b/system/camerad/sensors/os04c10_registers.h @@ -0,0 +1,352 @@ +#pragma once + +const struct i2c_random_wr_payload start_reg_array_os04c10[] = {{0x100, 1}}; +const struct i2c_random_wr_payload stop_reg_array_os04c10[] = {{0x100, 0}}; + +const struct i2c_random_wr_payload init_array_os04c10[] = { + // DP_2688X1520_NEWSTG_MIPI0776Mbps_30FPS_10BIT_FOURLANE + {0x0103, 0x01}, + + // PLL + {0x0301, 0xe4}, + {0x0303, 0x01}, + {0x0305, 0xb6}, + {0x0306, 0x01}, + {0x0307, 0x17}, + {0x0323, 0x04}, + {0x0324, 0x01}, + {0x0325, 0x62}, + + {0x3012, 0x06}, + {0x3013, 0x02}, + {0x3016, 0x72}, + {0x3021, 0x03}, + {0x3106, 0x21}, + {0x3107, 0xa1}, + + // ? + {0x3624, 0x00}, + {0x3625, 0x4c}, + {0x3660, 0x04}, + {0x3666, 0xa5}, + {0x3667, 0xa5}, + {0x366a, 0x50}, + {0x3673, 0x0d}, + {0x3672, 0x0d}, + {0x3671, 0x0d}, + {0x3670, 0x0d}, + {0x3685, 0x00}, + {0x3694, 0x0d}, + {0x3693, 0x0d}, + {0x3692, 0x0d}, + {0x3691, 0x0d}, + {0x3696, 0x4c}, + {0x3697, 0x4c}, + {0x3698, 0x00}, + {0x3699, 0x80}, + {0x369a, 0x80}, + {0x369b, 0x1f}, + {0x369c, 0x1f}, + {0x369d, 0x80}, + {0x369e, 0x40}, + {0x369f, 0x21}, + {0x36a0, 0x12}, + {0x36a1, 0xdd}, + {0x36a2, 0x66}, + {0x370a, 0x02}, + {0x370e, 0x00}, + {0x3710, 0x00}, + {0x3713, 0x04}, + {0x3725, 0x02}, + {0x372a, 0x03}, + {0x3738, 0xce}, + {0x3748, 0x02}, + {0x374a, 0x02}, + {0x374c, 0x02}, + {0x374e, 0x02}, + {0x3756, 0x00}, + {0x3757, 0x00}, + {0x3767, 0x00}, + {0x3771, 0x00}, + {0x377b, 0x28}, + {0x377c, 0x00}, + {0x377d, 0x0c}, + {0x3781, 0x03}, + {0x3782, 0x00}, + {0x3789, 0x14}, + {0x3795, 0x02}, + {0x379c, 0x00}, + {0x379d, 0x00}, + {0x37b8, 0x04}, + {0x37ba, 0x03}, + {0x37bb, 0x00}, + {0x37bc, 0x04}, + {0x37be, 0x26}, + {0x37c4, 0x11}, + {0x37c5, 0x80}, + {0x37c6, 0x14}, + {0x37c7, 0xa8}, + {0x37da, 0x11}, + {0x381f, 0x08}, + {0x3881, 0x00}, + {0x3888, 0x04}, + {0x388b, 0x00}, + {0x3c80, 0x10}, + {0x3c86, 0x00}, + {0x3c8c, 0x20}, + {0x3c9f, 0x01}, + {0x3d85, 0x1b}, + {0x3d8c, 0x71}, + {0x3d8d, 0xe2}, + {0x3f00, 0x0b}, + {0x3f06, 0x04}, + + // BLC + {0x400a, 0x01}, + {0x400b, 0x50}, + {0x400e, 0x08}, + {0x4043, 0x7e}, + {0x4045, 0x7e}, + {0x4047, 0x7e}, + {0x4049, 0x7e}, + {0x4090, 0x04}, + {0x40b0, 0x00}, + {0x40b1, 0x00}, + {0x40b2, 0x00}, + {0x40b3, 0x00}, + {0x40b4, 0x00}, + {0x40b5, 0x00}, + {0x40b7, 0x00}, + {0x40b8, 0x00}, + {0x40b9, 0x00}, + {0x40ba, 0x01}, + + {0x4301, 0x00}, + {0x4303, 0x00}, + {0x4502, 0x04}, + {0x4503, 0x00}, + {0x4504, 0x06}, + {0x4506, 0x00}, + {0x4507, 0x47}, + {0x4803, 0x00}, + {0x480c, 0x32}, + {0x480e, 0x04}, + {0x4813, 0xe4}, + {0x4819, 0x70}, + {0x481f, 0x30}, + {0x4823, 0x3f}, + {0x4825, 0x30}, + {0x4833, 0x10}, + {0x484b, 0x27}, + {0x488b, 0x00}, + {0x4d00, 0x04}, + {0x4d01, 0xad}, + {0x4d02, 0xbc}, + {0x4d03, 0xa1}, + {0x4d04, 0x1f}, + {0x4d05, 0x4c}, + {0x4d0b, 0x01}, + {0x4e00, 0x2a}, + {0x4e0d, 0x00}, + + // ISP + {0x5001, 0x09}, + {0x5004, 0x00}, + {0x5080, 0x04}, + {0x5036, 0x80}, + {0x5180, 0x70}, + {0x5181, 0x10}, + + // DPC + {0x520a, 0x03}, + {0x520b, 0x06}, + {0x520c, 0x0c}, + + {0x580b, 0x0f}, + {0x580d, 0x00}, + {0x580f, 0x00}, + {0x5820, 0x00}, + {0x5821, 0x00}, + + {0x301c, 0xf8}, + {0x301e, 0xb4}, + {0x301f, 0xf0}, + {0x3022, 0x61}, + {0x3109, 0xe7}, + {0x3600, 0x00}, + {0x3610, 0x65}, + {0x3611, 0x85}, + {0x3613, 0x3a}, + {0x3615, 0x60}, + {0x3621, 0xb0}, + {0x3620, 0x0c}, + {0x3629, 0x00}, + {0x3661, 0x04}, + {0x3664, 0x70}, + {0x3665, 0x00}, + {0x3681, 0x80}, + {0x3682, 0x40}, + {0x3683, 0x21}, + {0x3684, 0x12}, + {0x3700, 0x2a}, + {0x3701, 0x12}, + {0x3703, 0x28}, + {0x3704, 0x0e}, + {0x3706, 0x9d}, + {0x3709, 0x4a}, + {0x370b, 0x48}, + {0x370c, 0x01}, + {0x370f, 0x00}, + {0x3714, 0x28}, + {0x3716, 0x04}, + {0x3719, 0x11}, + {0x371a, 0x1e}, + {0x3720, 0x00}, + {0x3724, 0x13}, + {0x373f, 0xb0}, + {0x3741, 0x9d}, + {0x3743, 0x9d}, + {0x3745, 0x9d}, + {0x3747, 0x9d}, + {0x3749, 0x48}, + {0x374b, 0x48}, + {0x374d, 0x48}, + {0x374f, 0x48}, + {0x3755, 0x10}, + {0x376c, 0x00}, + {0x378d, 0x3c}, + {0x3790, 0x01}, + {0x3791, 0x01}, + {0x3798, 0x40}, + {0x379e, 0x00}, + {0x379f, 0x04}, + {0x37a1, 0x10}, + {0x37a2, 0x1e}, + {0x37a8, 0x10}, + {0x37a9, 0x1e}, + {0x37ac, 0xa0}, + {0x37b9, 0x01}, + {0x37bd, 0x01}, + {0x37bf, 0x26}, + {0x37c0, 0x11}, + {0x37c2, 0x14}, + {0x37cd, 0x19}, + {0x37e0, 0x08}, + {0x37e6, 0x04}, + {0x37e5, 0x02}, + {0x37e1, 0x0c}, + {0x3737, 0x04}, + {0x37d8, 0x02}, + {0x37e2, 0x10}, + {0x3739, 0x10}, + {0x3662, 0x08}, + {0x37e4, 0x20}, + {0x37e3, 0x08}, + {0x37d9, 0x04}, + {0x4040, 0x00}, + {0x4041, 0x03}, + {0x4008, 0x01}, + {0x4009, 0x06}, + + // FSIN + {0x3002, 0x22}, + {0x3663, 0x22}, + {0x368a, 0x04}, + {0x3822, 0x44}, + {0x3823, 0x00}, + {0x3829, 0x03}, + {0x3832, 0xf8}, + {0x382c, 0x00}, + {0x3844, 0x06}, + {0x3843, 0x00}, + {0x382a, 0x00}, + {0x382b, 0x0c}, + + // 2704x1536 -> 2688x1520 out + {0x3800, 0x00}, {0x3801, 0x00}, + {0x3802, 0x00}, {0x3803, 0x00}, + {0x3804, 0x0a}, {0x3805, 0x8f}, + {0x3806, 0x05}, {0x3807, 0xff}, + {0x3808, 0x05}, {0x3809, 0x40}, + {0x380a, 0x02}, {0x380b, 0xf8}, + {0x3811, 0x08}, + {0x3813, 0x08}, + {0x3814, 0x03}, + {0x3815, 0x01}, + {0x3816, 0x03}, + {0x3817, 0x01}, + + {0x380c, 0x0b}, {0x380d, 0xac}, // HTS + {0x380e, 0x06}, {0x380f, 0x9c}, // VTS + + {0x3820, 0xb3}, + {0x3821, 0x01}, + {0x3880, 0x00}, + {0x3882, 0x20}, + {0x3c91, 0x0b}, + {0x3c94, 0x45}, + {0x3cad, 0x00}, + {0x3cae, 0x00}, + {0x4000, 0xf3}, + {0x4001, 0x60}, + {0x4003, 0x40}, + {0x4300, 0xff}, + {0x4302, 0x0f}, + {0x4305, 0x83}, + {0x4505, 0x84}, + {0x4809, 0x0e}, + {0x480a, 0x04}, + {0x4837, 0x15}, + {0x4c00, 0x08}, + {0x4c01, 0x08}, + {0x4c04, 0x00}, + {0x4c05, 0x00}, + {0x5000, 0xf9}, + // {0x0100, 0x01}, + // {0x320d, 0x00}, + // {0x3208, 0xa0}, + + // initialize exposure + {0x3503, 0x88}, + + // long + {0x3500, 0x00}, {0x3501, 0x00}, {0x3502, 0x10}, + {0x3508, 0x00}, {0x3509, 0x80}, + {0x350a, 0x04}, {0x350b, 0x00}, + + // short + {0x3510, 0x00}, {0x3511, 0x00}, {0x3512, 0x40}, + {0x350c, 0x00}, {0x350d, 0x80}, + {0x350e, 0x04}, {0x350f, 0x00}, + + // wb + // b + {0x5100, 0x06}, {0x5101, 0x7e}, + {0x5140, 0x06}, {0x5141, 0x7e}, + // g + {0x5102, 0x04}, {0x5103, 0x00}, + {0x5142, 0x04}, {0x5143, 0x00}, + // r + {0x5104, 0x08}, {0x5105, 0xd6}, + {0x5144, 0x08}, {0x5145, 0xd6}, +}; + +const struct i2c_random_wr_payload ife_downscale_override_array_os04c10[] = { + // OS04C10_AA_00_02_17_wAO_2688x1524_MIPI728Mbps_Linear12bit_20FPS_4Lane_MCLK24MHz + {0x3c8c, 0x40}, + {0x3714, 0x24}, + {0x37c2, 0x04}, + {0x3662, 0x10}, + {0x37d9, 0x08}, + {0x4041, 0x07}, + {0x4008, 0x02}, + {0x4009, 0x0d}, + {0x3808, 0x0a}, {0x3809, 0x80}, + {0x380a, 0x05}, {0x380b, 0xf0}, + {0x3814, 0x01}, + {0x3816, 0x01}, + {0x380c, 0x08}, {0x380d, 0x5c}, // HTS + {0x380e, 0x09}, {0x380f, 0x38}, // VTS + {0x3820, 0xb0}, + {0x3821, 0x00}, +}; diff --git a/system/camerad/sensors/ox03c10.cc b/system/camerad/sensors/ox03c10.cc new file mode 100644 index 0000000000..6f7e658f48 --- /dev/null +++ b/system/camerad/sensors/ox03c10.cc @@ -0,0 +1,141 @@ +#include + +#include "system/camerad/sensors/sensor.h" + +namespace { + +const float sensor_analog_gains_OX03C10[] = { + 1.0, 1.0625, 1.125, 1.1875, 1.25, 1.3125, 1.375, 1.4375, 1.5, 1.5625, 1.6875, + 1.8125, 1.9375, 2.0, 2.125, 2.25, 2.375, 2.5, 2.625, 2.75, 2.875, 3.0, + 3.125, 3.375, 3.625, 3.875, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, + 5.75, 6.0, 6.25, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, + 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, 15.0, 15.5}; + +const uint32_t ox03c10_analog_gains_reg[] = { + 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1B0, + 0x1D0, 0x1F0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300, + 0x320, 0x360, 0x3A0, 0x3E0, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580, + 0x5C0, 0x600, 0x640, 0x680, 0x700, 0x780, 0x800, 0x880, 0x900, 0x980, 0xA00, + 0xA80, 0xB00, 0xB80, 0xC00, 0xC80, 0xD00, 0xD80, 0xE00, 0xE80, 0xF00, 0xF80}; + +const uint32_t VS_TIME_MIN_OX03C10 = 1; +const uint32_t VS_TIME_MAX_OX03C10 = 34; // vs < 35 + +} // namespace + +OX03C10::OX03C10() { + image_sensor = cereal::FrameData::ImageSensor::OX03C10; + bayer_pattern = CAM_ISP_PATTERN_BAYER_GRGRGR; + pixel_size_mm = 0.003; + data_word = false; + frame_width = 1928; + frame_height = 1208; + frame_stride = (frame_width * 12 / 8) + 4; + extra_height = 16; // top 2 + bot 14 + frame_offset = 2; + + start_reg_array.assign(std::begin(start_reg_array_ox03c10), std::end(start_reg_array_ox03c10)); + init_reg_array.assign(std::begin(init_array_ox03c10), std::end(init_array_ox03c10)); + probe_reg_addr = 0x300a; + probe_expected_data = 0x5803; + bits_per_pixel = 12; + mipi_format = CAM_FORMAT_MIPI_RAW_12; + frame_data_type = 0x2c; // one is 0x2a, two are 0x2b + mclk_frequency = 24000000; //Hz + + readout_time_ns = 14697000; + + dc_gain_factor = 7.32; + dc_gain_min_weight = 1; // always on is fine + dc_gain_max_weight = 1; + dc_gain_on_grey = 0.9; + dc_gain_off_grey = 1.0; + exposure_time_min = 2; // 1x + exposure_time_max = 2016; + analog_gain_min_idx = 0x0; + analog_gain_rec_idx = 0x0; // 1x + analog_gain_max_idx = 0x36; + analog_gain_cost_delta = -1; + analog_gain_cost_low = 0.4; + analog_gain_cost_high = 6.4; + for (int i = 0; i <= analog_gain_max_idx; i++) { + sensor_analog_gains[i] = sensor_analog_gains_OX03C10[i]; + } + min_ev = (exposure_time_min + VS_TIME_MIN_OX03C10) * sensor_analog_gains[analog_gain_min_idx]; + max_ev = exposure_time_max * dc_gain_factor * sensor_analog_gains[analog_gain_max_idx]; + target_grey_factor = 0.01; + + black_level = 0; + color_correct_matrix = { + 0x000000b6, 0x00000ff1, 0x00000fda, + 0x00000fcc, 0x000000b9, 0x00000ffb, + 0x00000fc2, 0x00000ff6, 0x000000c9, + }; + for (int i = 0; i < 65; i++) { + float fx = i / 64.0; + fx = -0.507089*exp(-12.54124638*fx) + 0.9655*pow(fx, 0.5) - 0.472597*fx + 0.507089; + gamma_lut_rgb.push_back((uint32_t)(fx*1023.0 + 0.5)); + } + prepare_gamma_lut(); + linearization_lut = { + 0x00200000, 0x00200000, 0x00200000, 0x00200000, + 0x00404080, 0x00404080, 0x00404080, 0x00404080, + 0x00804100, 0x00804100, 0x00804100, 0x00804100, + 0x02014402, 0x02014402, 0x02014402, 0x02014402, + 0x0402c804, 0x0402c804, 0x0402c804, 0x0402c804, + 0x0805d00a, 0x0805d00a, 0x0805d00a, 0x0805d00a, + 0x100ba015, 0x100ba015, 0x100ba015, 0x100ba015, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, + }; + linearization_pts = {0x07ff0bff, 0x17ff1bff, 0x1fff23ff, 0x27ff3fff}; + vignetting_lut = { + 0x00eaa755, 0x00cf2679, 0x00bc05e0, 0x00acc566, 0x00a1450a, 0x009984cc, 0x0095a4ad, 0x009584ac, 0x009944ca, 0x00a0c506, 0x00ac0560, 0x00bb25d9, 0x00ce2671, 0x00e90748, 0x01112889, 0x014a2a51, 0x01984cc2, + 0x00db06d8, 0x00c30618, 0x00afe57f, 0x00a0a505, 0x009524a9, 0x008d646b, 0x0089844c, 0x0089644b, 0x008d2469, 0x0094a4a5, 0x009fe4ff, 0x00af0578, 0x00c20610, 0x00d986cc, 0x00fda7ed, 0x01320990, 0x017aebd7, + 0x00d1868c, 0x00baa5d5, 0x00a7853c, 0x009844c2, 0x008cc466, 0x0085a42d, 0x0083641b, 0x0083641b, 0x0085842c, 0x008c4462, 0x0097a4bd, 0x00a6c536, 0x00b9a5cd, 0x00d06683, 0x00f1678b, 0x01226913, 0x0167ab3d, + 0x00cd0668, 0x00b625b1, 0x00a30518, 0x0093c49e, 0x00884442, 0x00830418, 0x0080e407, 0x0080c406, 0x0082e417, 0x0087c43e, 0x00932499, 0x00a22511, 0x00b525a9, 0x00cbe65f, 0x00eb0758, 0x011a68d3, 0x015daaed, + 0x00cc4662, 0x00b565ab, 0x00a24512, 0x00930498, 0x0087843c, 0x0082a415, 0x00806403, 0x00806403, 0x00828414, 0x00870438, 0x00926493, 0x00a1850c, 0x00b465a3, 0x00cb2659, 0x00ea2751, 0x011928c9, 0x015c2ae1, + 0x00cf667b, 0x00b885c4, 0x00a5652b, 0x009624b1, 0x008aa455, 0x00846423, 0x00822411, 0x00822411, 0x00844422, 0x008a2451, 0x009564ab, 0x00a48524, 0x00b785bc, 0x00ce4672, 0x00ee6773, 0x011e88f4, 0x0162eb17, + 0x00d6c6b6, 0x00bf65fb, 0x00ac4562, 0x009d04e8, 0x0091848c, 0x0089c44e, 0x00862431, 0x00860430, 0x0089844c, 0x00910488, 0x009c64e3, 0x00ab655b, 0x00be65f3, 0x00d566ab, 0x00f847c2, 0x012b2959, 0x01726b93, + 0x00e3e71f, 0x00ca0650, 0x00b705b8, 0x00a7a53d, 0x009c24e1, 0x009484a4, 0x00908484, 0x00908484, 0x009424a1, 0x009bc4de, 0x00a70538, 0x00b625b1, 0x00c90648, 0x00e26713, 0x0108e847, 0x013fe9ff, 0x018bcc5e, + 0x00f807c0, 0x00d966cb, 0x00c5862c, 0x00b625b1, 0x00aaa555, 0x00a30518, 0x009f04f8, 0x009f04f8, 0x00a2a515, 0x00aa2551, 0x00b585ac, 0x00c4a625, 0x00d846c2, 0x00f647b2, 0x0121a90d, 0x015e4af2, 0x01b8cdc6, + 0x011548aa, 0x00f1678b, 0x00d886c4, 0x00c86643, 0x00bce5e7, 0x00b545aa, 0x00b1658b, 0x00b1458a, 0x00b505a8, 0x00bc85e4, 0x00c7c63e, 0x00d786bc, 0x00efe77f, 0x0113489a, 0x0144ea27, 0x01888c44, 0x01fdcfee, + 0x013e49f2, 0x0113e89f, 0x00f5a7ad, 0x00e0c706, 0x00d30698, 0x00cb665b, 0x00c7663b, 0x00c7663b, 0x00cb0658, 0x00d2a695, 0x00dfe6ff, 0x00f467a3, 0x01122891, 0x013be9df, 0x01750ba8, 0x01cfae7d, 0x025912c8, + 0x01766bb3, 0x01446a23, 0x011fc8fe, 0x0105e82f, 0x00f467a3, 0x00e9874c, 0x00e46723, 0x00e44722, 0x00e92749, 0x00f3a79d, 0x0104c826, 0x011e48f2, 0x01424a12, 0x01738b9c, 0x01bf6dfb, 0x023611b0, 0x02ced676, + 0x01cf8e7c, 0x01866c33, 0x015aaad5, 0x013ae9d7, 0x01250928, 0x011768bb, 0x0110a885, 0x01108884, 0x0116e8b7, 0x01242921, 0x0139a9cd, 0x0158eac7, 0x01840c20, 0x01cb0e58, 0x0233719b, 0x02b9d5ce, 0x03645b22, + }; +} + +std::vector OX03C10::getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { + // t_HCG&t_LCG + t_VS on LPD, t_SPD on SPD + uint32_t hcg_time = exposure_time; + uint32_t lcg_time = hcg_time; + uint32_t spd_time = std::min(std::max((uint32_t)exposure_time, (exposure_time_max + VS_TIME_MAX_OX03C10) / 3), exposure_time_max + VS_TIME_MAX_OX03C10); + uint32_t vs_time = std::min(std::max((uint32_t)exposure_time / 40, VS_TIME_MIN_OX03C10), VS_TIME_MAX_OX03C10); + + uint32_t real_gain = ox03c10_analog_gains_reg[new_exp_g]; + + return { + {0x3501, hcg_time>>8}, {0x3502, hcg_time&0xFF}, + {0x3581, lcg_time>>8}, {0x3582, lcg_time&0xFF}, + {0x3541, spd_time>>8}, {0x3542, spd_time&0xFF}, + {0x35c2, vs_time&0xFF}, + + {0x3508, real_gain>>8}, {0x3509, real_gain&0xFF}, + }; +} + +int OX03C10::getSlaveAddress(int port) const { + assert(port >= 0 && port <= 2); + return (int[]){0x6C, 0x20, 0x6C}[port]; +} + +float OX03C10::getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const { + float score = std::abs(desired_ev - (exp_t * exp_gain)); + float m = exp_g_idx > analog_gain_rec_idx ? analog_gain_cost_high : analog_gain_cost_low; + score += std::abs(exp_g_idx - (int)analog_gain_rec_idx) * m; + score += ((1 - analog_gain_cost_delta) + + analog_gain_cost_delta * (exp_g_idx - analog_gain_min_idx) / (analog_gain_max_idx - analog_gain_min_idx)) * + std::abs(exp_g_idx - gain_idx) * 5.0; + return score; +} diff --git a/system/camerad/sensors/ox03c10_registers.h b/system/camerad/sensors/ox03c10_registers.h new file mode 100644 index 0000000000..bb7a1c5dd6 --- /dev/null +++ b/system/camerad/sensors/ox03c10_registers.h @@ -0,0 +1,751 @@ +#pragma once + +const struct i2c_random_wr_payload start_reg_array_ox03c10[] = {{0x100, 1}}; +const struct i2c_random_wr_payload stop_reg_array_ox03c10[] = {{0x100, 0}}; + +const struct i2c_random_wr_payload init_array_ox03c10[] = { + {0x103, 1}, + {0x107, 1}, + + // X3C_1920x1280_60fps_HDR4_LFR_PWL12_mipi1200 + + // TPM + {0x4d5a, 0x1a}, {0x4d09, 0xff}, {0x4d09, 0xdf}, + + /*) + // group 4 + {0x3208, 0x04}, + {0x4620, 0x04}, + {0x3208, 0x14}, + + // group 5 + {0x3208, 0x05}, + {0x4620, 0x04}, + {0x3208, 0x15}, + + // group 2 + {0x3208, 0x02}, + {0x3507, 0x00}, + {0x3208, 0x12}, + + // delay launch group 2 + {0x3208, 0xa2},*/ + + // **NOTE**: if this is changed, readout_time_ns must be updated in the Sensor config + // PLL setup + {0x0301, 0xc8}, // pll1_divs, pll1_predivp, pll1_divpix + {0x0303, 0x01}, // pll1_prediv + {0x0304, 0x01}, {0x0305, 0x2c}, // pll1_loopdiv = 300 + {0x0306, 0x04}, // pll1_divmipi = 4 + {0x0307, 0x01}, // pll1_divm = 1 + {0x0316, 0x00}, + {0x0317, 0x00}, + {0x0318, 0x00}, + {0x0323, 0x05}, // pll2_prediv + {0x0324, 0x01}, {0x0325, 0x2c}, // pll2_divp = 300 + + // SCLK/PCLK + {0x0400, 0xe0}, {0x0401, 0x80}, + {0x0403, 0xde}, {0x0404, 0x34}, + {0x0405, 0x3b}, {0x0406, 0xde}, + {0x0407, 0x08}, + {0x0408, 0xe0}, {0x0409, 0x7f}, + {0x040a, 0xde}, {0x040b, 0x34}, + {0x040c, 0x47}, {0x040d, 0xd8}, + {0x040e, 0x08}, + + // xchk + {0x2803, 0xfe}, {0x280b, 0x00}, {0x280c, 0x79}, + + // SC ctrl + {0x3001, 0x03}, // io_pad_oen + {0x3002, 0xfc}, // io_pad_oen + {0x3005, 0x80}, // io_pad_out + {0x3007, 0x01}, // io_pad_sel + {0x3008, 0x80}, // io_pad_sel + + // FSIN (frame sync) with external pulses + {0x3009, 0x2}, + {0x3015, 0x2}, + {0x383E, 0x80}, + {0x3881, 0x4}, + {0x3882, 0x8}, {0x3883, 0x0D}, + {0x3836, 0x1F}, {0x3837, 0x40}, + + // causes issues on some devices + //{0x3822, 0x33}, // wait for pulse before first frame + + {0x3892, 0x44}, + {0x3823, 0x41}, + + {0x3012, 0x41}, // SC_PHY_CTRL = 4 lane MIPI + {0x3020, 0x05}, // SC_CTRL_20 + + // this is not in the datasheet, listed as RSVD + // but the camera doesn't work without it + {0x3700, 0x28}, {0x3701, 0x15}, {0x3702, 0x19}, {0x3703, 0x23}, + {0x3704, 0x0a}, {0x3705, 0x00}, {0x3706, 0x3e}, {0x3707, 0x0d}, + {0x3708, 0x50}, {0x3709, 0x5a}, {0x370a, 0x00}, {0x370b, 0x96}, + {0x3711, 0x11}, {0x3712, 0x13}, {0x3717, 0x02}, {0x3718, 0x73}, + {0x372c, 0x40}, {0x3733, 0x01}, {0x3738, 0x36}, {0x3739, 0x36}, + {0x373a, 0x25}, {0x373b, 0x25}, {0x373f, 0x21}, {0x3740, 0x21}, + {0x3741, 0x21}, {0x3742, 0x21}, {0x3747, 0x28}, {0x3748, 0x28}, + {0x3749, 0x19}, {0x3755, 0x1a}, {0x3756, 0x0a}, {0x3757, 0x1c}, + {0x3765, 0x19}, {0x3766, 0x05}, {0x3767, 0x05}, {0x3768, 0x13}, + {0x376c, 0x07}, {0x3778, 0x20}, {0x377c, 0xc8}, {0x3781, 0x02}, + {0x3783, 0x02}, {0x379c, 0x58}, {0x379e, 0x00}, {0x379f, 0x00}, + {0x37a0, 0x00}, {0x37bc, 0x22}, {0x37c0, 0x01}, {0x37c4, 0x3e}, + {0x37c5, 0x3e}, {0x37c6, 0x2a}, {0x37c7, 0x28}, {0x37c8, 0x02}, + {0x37c9, 0x12}, {0x37cb, 0x29}, {0x37cd, 0x29}, {0x37d2, 0x00}, + {0x37d3, 0x73}, {0x37d6, 0x00}, {0x37d7, 0x6b}, {0x37dc, 0x00}, + {0x37df, 0x54}, {0x37e2, 0x00}, {0x37e3, 0x00}, {0x37f8, 0x00}, + {0x37f9, 0x01}, {0x37fa, 0x00}, {0x37fb, 0x19}, + + // also RSVD + {0x3c03, 0x01}, {0x3c04, 0x01}, {0x3c06, 0x21}, {0x3c08, 0x01}, + {0x3c09, 0x01}, {0x3c0a, 0x01}, {0x3c0b, 0x21}, {0x3c13, 0x21}, + {0x3c14, 0x82}, {0x3c16, 0x13}, {0x3c21, 0x00}, {0x3c22, 0xf3}, + {0x3c37, 0x12}, {0x3c38, 0x31}, {0x3c3c, 0x00}, {0x3c3d, 0x03}, + {0x3c44, 0x16}, {0x3c5c, 0x8a}, {0x3c5f, 0x03}, {0x3c61, 0x80}, + {0x3c6f, 0x2b}, {0x3c70, 0x5f}, {0x3c71, 0x2c}, {0x3c72, 0x2c}, + {0x3c73, 0x2c}, {0x3c76, 0x12}, + + // PEC checks + {0x3182, 0x12}, + + {0x320e, 0x00}, {0x320f, 0x00}, // RSVD + {0x3211, 0x61}, + {0x3215, 0xcd}, + {0x3219, 0x08}, + + {0x3506, 0x20}, {0x3507, 0x00}, // hcg fine exposure + {0x350a, 0x01}, {0x350b, 0x00}, {0x350c, 0x00}, // hcg digital gain + + {0x3586, 0x40}, {0x3587, 0x00}, // lcg fine exposure + {0x358a, 0x01}, {0x358b, 0x00}, {0x358c, 0x00}, // lcg digital gain + + {0x3546, 0x20}, {0x3547, 0x00}, // spd fine exposure + {0x354a, 0x01}, {0x354b, 0x00}, {0x354c, 0x00}, // spd digital gain + + {0x35c6, 0xb0}, {0x35c7, 0x00}, // vs fine exposure + {0x35ca, 0x01}, {0x35cb, 0x00}, {0x35cc, 0x00}, // vs digital gain + + // also RSVD + {0x3600, 0x8f}, {0x3605, 0x16}, {0x3609, 0xf0}, {0x360a, 0x01}, + {0x360e, 0x1d}, {0x360f, 0x10}, {0x3610, 0x70}, {0x3611, 0x3a}, + {0x3612, 0x28}, {0x361a, 0x29}, {0x361b, 0x6c}, {0x361c, 0x0b}, + {0x361d, 0x00}, {0x361e, 0xfc}, {0x362a, 0x00}, {0x364d, 0x0f}, + {0x364e, 0x18}, {0x364f, 0x12}, {0x3653, 0x1c}, {0x3654, 0x00}, + {0x3655, 0x1f}, {0x3656, 0x1f}, {0x3657, 0x0c}, {0x3658, 0x0a}, + {0x3659, 0x14}, {0x365a, 0x18}, {0x365b, 0x14}, {0x365c, 0x10}, + {0x365e, 0x12}, {0x3674, 0x08}, {0x3677, 0x3a}, {0x3678, 0x3a}, + {0x3679, 0x19}, + + // Y_ADDR_START = 4 + {0x3802, 0x00}, {0x3803, 0x04}, + // Y_ADDR_END = 0x50b + {0x3806, 0x05}, {0x3807, 0x0b}, + + // X_OUTPUT_SIZE = 0x780 = 1920 (changed to 1928) + {0x3808, 0x07}, {0x3809, 0x88}, + + // Y_OUTPUT_SIZE = 0x500 = 1280 (changed to 1208) + {0x380a, 0x04}, {0x380b, 0xb8}, + + // horizontal timing 0x447 + {0x380c, 0x04}, {0x380d, 0x47}, + + // rows per frame (was 0x2ae) + // 0x8ae = 53.65 ms + {0x380e, 0x08}, {0x380f, 0x15}, + // this should be triggered by FSIN, not free running + + {0x3810, 0x00}, {0x3811, 0x08}, // x cutoff + {0x3812, 0x00}, {0x3813, 0x04}, // y cutoff + {0x3816, 0x01}, + {0x3817, 0x01}, + {0x381c, 0x18}, + {0x381e, 0x01}, + {0x381f, 0x01}, + + // don't mirror, just flip + {0x3820, 0x04}, + + {0x3821, 0x19}, + {0x3832, 0xF0}, + {0x3834, 0xF0}, + {0x384c, 0x02}, + {0x384d, 0x0d}, + {0x3850, 0x00}, + {0x3851, 0x42}, + {0x3852, 0x00}, + {0x3853, 0x40}, + {0x3858, 0x04}, + {0x388c, 0x02}, + {0x388d, 0x2b}, + + // APC + {0x3b40, 0x05}, {0x3b41, 0x40}, {0x3b42, 0x00}, {0x3b43, 0x90}, + {0x3b44, 0x00}, {0x3b45, 0x20}, {0x3b46, 0x00}, {0x3b47, 0x20}, + {0x3b48, 0x19}, {0x3b49, 0x12}, {0x3b4a, 0x16}, {0x3b4b, 0x2e}, + {0x3b4c, 0x00}, {0x3b4d, 0x00}, + {0x3b86, 0x00}, {0x3b87, 0x34}, {0x3b88, 0x00}, {0x3b89, 0x08}, + {0x3b8a, 0x05}, {0x3b8b, 0x00}, {0x3b8c, 0x07}, {0x3b8d, 0x80}, + {0x3b8e, 0x00}, {0x3b8f, 0x00}, {0x3b92, 0x05}, {0x3b93, 0x00}, + {0x3b94, 0x07}, {0x3b95, 0x80}, {0x3b9e, 0x09}, + + // OTP + {0x3d82, 0x73}, + {0x3d85, 0x05}, + {0x3d8a, 0x03}, + {0x3d8b, 0xff}, + {0x3d99, 0x00}, + {0x3d9a, 0x9f}, + {0x3d9b, 0x00}, + {0x3d9c, 0xa0}, + {0x3da4, 0x00}, + {0x3da7, 0x50}, + + // DTR + {0x420e, 0x6b}, + {0x420f, 0x6e}, + {0x4210, 0x06}, + {0x4211, 0xc1}, + {0x421e, 0x02}, + {0x421f, 0x45}, + {0x4220, 0xe1}, + {0x4221, 0x01}, + {0x4301, 0xff}, + {0x4307, 0x03}, + {0x4308, 0x13}, + {0x430a, 0x13}, + {0x430d, 0x93}, + {0x430f, 0x57}, + {0x4310, 0x95}, + {0x4311, 0x16}, + {0x4316, 0x00}, + + {0x4317, 0x38}, // both embedded rows are enabled + + {0x4319, 0x03}, // spd dcg + {0x431a, 0x00}, // 8 bit mipi + {0x431b, 0x00}, + {0x431d, 0x2a}, + {0x431e, 0x11}, + + {0x431f, 0x20}, // enable PWL (pwl0_en), 12 bits + //{0x431f, 0x00}, // disable PWL + + {0x4320, 0x19}, + {0x4323, 0x80}, + {0x4324, 0x00}, + {0x4503, 0x4e}, + {0x4505, 0x00}, + {0x4509, 0x00}, + {0x450a, 0x00}, + {0x4580, 0xf8}, + {0x4583, 0x07}, + {0x4584, 0x6a}, + {0x4585, 0x08}, + {0x4586, 0x05}, + {0x4587, 0x04}, + {0x4588, 0x73}, + {0x4589, 0x05}, + {0x458a, 0x1f}, + {0x458b, 0x02}, + {0x458c, 0xdc}, + {0x458d, 0x03}, + {0x458e, 0x02}, + {0x4597, 0x07}, + {0x4598, 0x40}, + {0x4599, 0x0e}, + {0x459a, 0x0e}, + {0x459b, 0xfb}, + {0x459c, 0xf3}, + {0x4602, 0x00}, + {0x4603, 0x13}, + {0x4604, 0x00}, + {0x4609, 0x0a}, + {0x460a, 0x30}, + {0x4610, 0x00}, + {0x4611, 0x70}, + {0x4612, 0x01}, + {0x4613, 0x00}, + {0x4614, 0x00}, + {0x4615, 0x70}, + {0x4616, 0x01}, + {0x4617, 0x00}, + + {0x4800, 0x04}, // invert output PCLK + {0x480a, 0x22}, + {0x4813, 0xe4}, + + // mipi + {0x4814, 0x2a}, + {0x4837, 0x0d}, + {0x484b, 0x47}, + {0x484f, 0x00}, + {0x4887, 0x51}, + {0x4d00, 0x4a}, + {0x4d01, 0x18}, + {0x4d05, 0xff}, + {0x4d06, 0x88}, + {0x4d08, 0x63}, + {0x4d09, 0xdf}, + {0x4d15, 0x7d}, + {0x4d1a, 0x20}, + {0x4d30, 0x0a}, + {0x4d31, 0x00}, + {0x4d34, 0x7d}, + {0x4d3c, 0x7d}, + {0x4f00, 0x00}, + {0x4f01, 0x00}, + {0x4f02, 0x00}, + {0x4f03, 0x20}, + {0x4f04, 0xe0}, + {0x6a00, 0x00}, + {0x6a01, 0x20}, + {0x6a02, 0x00}, + {0x6a03, 0x20}, + {0x6a04, 0x02}, + {0x6a05, 0x80}, + {0x6a06, 0x01}, + {0x6a07, 0xe0}, + {0x6a08, 0xcf}, + {0x6a09, 0x01}, + {0x6a0a, 0x40}, + {0x6a20, 0x00}, + {0x6a21, 0x02}, + {0x6a22, 0x00}, + {0x6a23, 0x00}, + {0x6a24, 0x00}, + {0x6a25, 0x00}, + {0x6a26, 0x00}, + {0x6a27, 0x00}, + {0x6a28, 0x00}, + + // isp + {0x5000, 0x8f}, + {0x5001, 0x75}, + {0x5002, 0x7f}, // PWL0 + //{0x5002, 0x3f}, // PWL disable + {0x5003, 0x7a}, + + {0x5004, 0x3e}, + {0x5005, 0x1e}, + {0x5006, 0x1e}, + {0x5007, 0x1e}, + + {0x5008, 0x00}, + {0x500c, 0x00}, + {0x502c, 0x00}, + {0x502e, 0x00}, + {0x502f, 0x00}, + {0x504b, 0x00}, + {0x5053, 0x00}, + {0x505b, 0x00}, + {0x5063, 0x00}, + {0x5070, 0x00}, + {0x5074, 0x04}, + {0x507a, 0x04}, + {0x507b, 0x09}, + {0x5500, 0x02}, + {0x5700, 0x02}, + {0x5900, 0x02}, + {0x6007, 0x04}, + {0x6008, 0x05}, + {0x6009, 0x02}, + {0x600b, 0x08}, + {0x600c, 0x07}, + {0x600d, 0x88}, + {0x6016, 0x00}, + {0x6027, 0x04}, + {0x6028, 0x05}, + {0x6029, 0x02}, + {0x602b, 0x08}, + {0x602c, 0x07}, + {0x602d, 0x88}, + {0x6047, 0x04}, + {0x6048, 0x05}, + {0x6049, 0x02}, + {0x604b, 0x08}, + {0x604c, 0x07}, + {0x604d, 0x88}, + {0x6067, 0x04}, + {0x6068, 0x05}, + {0x6069, 0x02}, + {0x606b, 0x08}, + {0x606c, 0x07}, + {0x606d, 0x88}, + {0x6087, 0x04}, + {0x6088, 0x05}, + {0x6089, 0x02}, + {0x608b, 0x08}, + {0x608c, 0x07}, + {0x608d, 0x88}, + + // 12-bit PWL0 + {0x5e00, 0x00}, + + // m_ndX_exp[0:32] + // 9*2+0xa*3+0xb*2+0xc*2+0xd*2+0xe*2+0xf*2+0x10*2+0x11*2+0x12*4+0x13*3+0x14*3+0x15*3+0x16 = 518 + {0x5e01, 0x09}, + {0x5e02, 0x09}, + {0x5e03, 0x0a}, + {0x5e04, 0x0a}, + {0x5e05, 0x0a}, + {0x5e06, 0x0b}, + {0x5e07, 0x0b}, + {0x5e08, 0x0c}, + {0x5e09, 0x0c}, + {0x5e0a, 0x0d}, + {0x5e0b, 0x0d}, + {0x5e0c, 0x0e}, + {0x5e0d, 0x0e}, + {0x5e0e, 0x0f}, + {0x5e0f, 0x0f}, + {0x5e10, 0x10}, + {0x5e11, 0x10}, + {0x5e12, 0x11}, + {0x5e13, 0x11}, + {0x5e14, 0x12}, + {0x5e15, 0x12}, + {0x5e16, 0x12}, + {0x5e17, 0x12}, + {0x5e18, 0x13}, + {0x5e19, 0x13}, + {0x5e1a, 0x13}, + {0x5e1b, 0x14}, + {0x5e1c, 0x14}, + {0x5e1d, 0x14}, + {0x5e1e, 0x15}, + {0x5e1f, 0x15}, + {0x5e20, 0x15}, + {0x5e21, 0x16}, + + // m_ndY_val[0:32] + // 0x200+0xff+0x100*3+0x80*12+0x40*16 = 4095 + {0x5e22, 0x00}, {0x5e23, 0x02}, {0x5e24, 0x00}, + {0x5e25, 0x00}, {0x5e26, 0x00}, {0x5e27, 0xff}, + {0x5e28, 0x00}, {0x5e29, 0x01}, {0x5e2a, 0x00}, + {0x5e2b, 0x00}, {0x5e2c, 0x01}, {0x5e2d, 0x00}, + {0x5e2e, 0x00}, {0x5e2f, 0x01}, {0x5e30, 0x00}, + {0x5e31, 0x00}, {0x5e32, 0x00}, {0x5e33, 0x80}, + {0x5e34, 0x00}, {0x5e35, 0x00}, {0x5e36, 0x80}, + {0x5e37, 0x00}, {0x5e38, 0x00}, {0x5e39, 0x80}, + {0x5e3a, 0x00}, {0x5e3b, 0x00}, {0x5e3c, 0x80}, + {0x5e3d, 0x00}, {0x5e3e, 0x00}, {0x5e3f, 0x80}, + {0x5e40, 0x00}, {0x5e41, 0x00}, {0x5e42, 0x80}, + {0x5e43, 0x00}, {0x5e44, 0x00}, {0x5e45, 0x80}, + {0x5e46, 0x00}, {0x5e47, 0x00}, {0x5e48, 0x80}, + {0x5e49, 0x00}, {0x5e4a, 0x00}, {0x5e4b, 0x80}, + {0x5e4c, 0x00}, {0x5e4d, 0x00}, {0x5e4e, 0x80}, + {0x5e4f, 0x00}, {0x5e50, 0x00}, {0x5e51, 0x80}, + {0x5e52, 0x00}, {0x5e53, 0x00}, {0x5e54, 0x80}, + {0x5e55, 0x00}, {0x5e56, 0x00}, {0x5e57, 0x40}, + {0x5e58, 0x00}, {0x5e59, 0x00}, {0x5e5a, 0x40}, + {0x5e5b, 0x00}, {0x5e5c, 0x00}, {0x5e5d, 0x40}, + {0x5e5e, 0x00}, {0x5e5f, 0x00}, {0x5e60, 0x40}, + {0x5e61, 0x00}, {0x5e62, 0x00}, {0x5e63, 0x40}, + {0x5e64, 0x00}, {0x5e65, 0x00}, {0x5e66, 0x40}, + {0x5e67, 0x00}, {0x5e68, 0x00}, {0x5e69, 0x40}, + {0x5e6a, 0x00}, {0x5e6b, 0x00}, {0x5e6c, 0x40}, + {0x5e6d, 0x00}, {0x5e6e, 0x00}, {0x5e6f, 0x40}, + {0x5e70, 0x00}, {0x5e71, 0x00}, {0x5e72, 0x40}, + {0x5e73, 0x00}, {0x5e74, 0x00}, {0x5e75, 0x40}, + {0x5e76, 0x00}, {0x5e77, 0x00}, {0x5e78, 0x40}, + {0x5e79, 0x00}, {0x5e7a, 0x00}, {0x5e7b, 0x40}, + {0x5e7c, 0x00}, {0x5e7d, 0x00}, {0x5e7e, 0x40}, + {0x5e7f, 0x00}, {0x5e80, 0x00}, {0x5e81, 0x40}, + {0x5e82, 0x00}, {0x5e83, 0x00}, {0x5e84, 0x40}, + + // disable PWL + /*{0x5e01, 0x18}, {0x5e02, 0x00}, {0x5e03, 0x00}, {0x5e04, 0x00}, + {0x5e05, 0x00}, {0x5e06, 0x00}, {0x5e07, 0x00}, {0x5e08, 0x00}, + {0x5e09, 0x00}, {0x5e0a, 0x00}, {0x5e0b, 0x00}, {0x5e0c, 0x00}, + {0x5e0d, 0x00}, {0x5e0e, 0x00}, {0x5e0f, 0x00}, {0x5e10, 0x00}, + {0x5e11, 0x00}, {0x5e12, 0x00}, {0x5e13, 0x00}, {0x5e14, 0x00}, + {0x5e15, 0x00}, {0x5e16, 0x00}, {0x5e17, 0x00}, {0x5e18, 0x00}, + {0x5e19, 0x00}, {0x5e1a, 0x00}, {0x5e1b, 0x00}, {0x5e1c, 0x00}, + {0x5e1d, 0x00}, {0x5e1e, 0x00}, {0x5e1f, 0x00}, {0x5e20, 0x00}, + {0x5e21, 0x00}, + + {0x5e22, 0x00}, {0x5e23, 0x0f}, {0x5e24, 0xFF},*/ + + {0x4001, 0x2b}, // BLC_CTRL_1 + {0x4008, 0x02}, {0x4009, 0x03}, + {0x4018, 0x12}, + {0x4022, 0x40}, + {0x4023, 0x20}, + + // all black level targets are 0x40 + {0x4026, 0x00}, {0x4027, 0x40}, + {0x4028, 0x00}, {0x4029, 0x40}, + {0x402a, 0x00}, {0x402b, 0x40}, + {0x402c, 0x00}, {0x402d, 0x40}, + + {0x407e, 0xcc}, + {0x407f, 0x18}, + {0x4080, 0xff}, + {0x4081, 0xff}, + {0x4082, 0x01}, + {0x4083, 0x53}, + {0x4084, 0x01}, + {0x4085, 0x2b}, + {0x4086, 0x00}, + {0x4087, 0xb3}, + + {0x4640, 0x40}, + {0x4641, 0x11}, + {0x4642, 0x0e}, + {0x4643, 0xee}, + {0x4646, 0x0f}, + {0x4648, 0x00}, + {0x4649, 0x03}, + + {0x4f00, 0x00}, + {0x4f01, 0x00}, + {0x4f02, 0x80}, + {0x4f03, 0x2c}, + {0x4f04, 0xf8}, + + {0x4d09, 0xff}, + {0x4d09, 0xdf}, + + {0x5003, 0x7a}, + {0x5b80, 0x08}, + {0x5c00, 0x08}, + {0x5c80, 0x00}, + {0x5bbe, 0x12}, + {0x5c3e, 0x12}, + {0x5cbe, 0x12}, + {0x5b8a, 0x80}, + {0x5b8b, 0x80}, + {0x5b8c, 0x80}, + {0x5b8d, 0x80}, + {0x5b8e, 0x60}, + {0x5b8f, 0x80}, + {0x5b90, 0x80}, + {0x5b91, 0x80}, + {0x5b92, 0x80}, + {0x5b93, 0x20}, + {0x5b94, 0x80}, + {0x5b95, 0x80}, + {0x5b96, 0x80}, + {0x5b97, 0x20}, + {0x5b98, 0x00}, + {0x5b99, 0x80}, + {0x5b9a, 0x40}, + {0x5b9b, 0x20}, + {0x5b9c, 0x00}, + {0x5b9d, 0x00}, + {0x5b9e, 0x80}, + {0x5b9f, 0x00}, + {0x5ba0, 0x00}, + {0x5ba1, 0x00}, + {0x5ba2, 0x00}, + {0x5ba3, 0x00}, + {0x5ba4, 0x00}, + {0x5ba5, 0x00}, + {0x5ba6, 0x00}, + {0x5ba7, 0x00}, + {0x5ba8, 0x02}, + {0x5ba9, 0x00}, + {0x5baa, 0x02}, + {0x5bab, 0x76}, + {0x5bac, 0x03}, + {0x5bad, 0x08}, + {0x5bae, 0x00}, + {0x5baf, 0x80}, + {0x5bb0, 0x00}, + {0x5bb1, 0xc0}, + {0x5bb2, 0x01}, + {0x5bb3, 0x00}, + + // m_nNormCombineWeight + {0x5c0a, 0x80}, {0x5c0b, 0x80}, {0x5c0c, 0x80}, {0x5c0d, 0x80}, {0x5c0e, 0x60}, + {0x5c0f, 0x80}, {0x5c10, 0x80}, {0x5c11, 0x80}, {0x5c12, 0x60}, {0x5c13, 0x20}, + {0x5c14, 0x80}, {0x5c15, 0x80}, {0x5c16, 0x80}, {0x5c17, 0x20}, {0x5c18, 0x00}, + {0x5c19, 0x80}, {0x5c1a, 0x40}, {0x5c1b, 0x20}, {0x5c1c, 0x00}, {0x5c1d, 0x00}, + {0x5c1e, 0x80}, {0x5c1f, 0x00}, {0x5c20, 0x00}, {0x5c21, 0x00}, {0x5c22, 0x00}, + {0x5c23, 0x00}, {0x5c24, 0x00}, {0x5c25, 0x00}, {0x5c26, 0x00}, {0x5c27, 0x00}, + + // m_nCombinThreL + {0x5c28, 0x02}, {0x5c29, 0x00}, + {0x5c2a, 0x02}, {0x5c2b, 0x76}, + {0x5c2c, 0x03}, {0x5c2d, 0x08}, + + // m_nCombinThreS + {0x5c2e, 0x00}, {0x5c2f, 0x80}, + {0x5c30, 0x00}, {0x5c31, 0xc0}, + {0x5c32, 0x01}, {0x5c33, 0x00}, + + // m_nNormCombineWeight + {0x5c8a, 0x80}, {0x5c8b, 0x80}, {0x5c8c, 0x80}, {0x5c8d, 0x80}, {0x5c8e, 0x80}, + {0x5c8f, 0x80}, {0x5c90, 0x80}, {0x5c91, 0x80}, {0x5c92, 0x80}, {0x5c93, 0x60}, + {0x5c94, 0x80}, {0x5c95, 0x80}, {0x5c96, 0x80}, {0x5c97, 0x60}, {0x5c98, 0x40}, + {0x5c99, 0x80}, {0x5c9a, 0x80}, {0x5c9b, 0x80}, {0x5c9c, 0x40}, {0x5c9d, 0x00}, + {0x5c9e, 0x80}, {0x5c9f, 0x80}, {0x5ca0, 0x80}, {0x5ca1, 0x20}, {0x5ca2, 0x00}, + {0x5ca3, 0x80}, {0x5ca4, 0x80}, {0x5ca5, 0x00}, {0x5ca6, 0x00}, {0x5ca7, 0x00}, + + {0x5ca8, 0x01}, {0x5ca9, 0x00}, + {0x5caa, 0x02}, {0x5cab, 0x00}, + {0x5cac, 0x03}, {0x5cad, 0x08}, + + {0x5cae, 0x01}, {0x5caf, 0x00}, + {0x5cb0, 0x02}, {0x5cb1, 0x00}, + {0x5cb2, 0x03}, {0x5cb3, 0x08}, + + // combine ISP + {0x5be7, 0x80}, + {0x5bc9, 0x80}, + {0x5bca, 0x80}, + {0x5bcb, 0x80}, + {0x5bcc, 0x80}, + {0x5bcd, 0x80}, + {0x5bce, 0x80}, + {0x5bcf, 0x80}, + {0x5bd0, 0x80}, + {0x5bd1, 0x80}, + {0x5bd2, 0x20}, + {0x5bd3, 0x80}, + {0x5bd4, 0x40}, + {0x5bd5, 0x20}, + {0x5bd6, 0x00}, + {0x5bd7, 0x00}, + {0x5bd8, 0x00}, + {0x5bd9, 0x00}, + {0x5bda, 0x00}, + {0x5bdb, 0x00}, + {0x5bdc, 0x00}, + {0x5bdd, 0x00}, + {0x5bde, 0x00}, + {0x5bdf, 0x00}, + {0x5be0, 0x00}, + {0x5be1, 0x00}, + {0x5be2, 0x00}, + {0x5be3, 0x00}, + {0x5be4, 0x00}, + {0x5be5, 0x00}, + {0x5be6, 0x00}, + + // m_nSPDCombineWeight + {0x5c49, 0x80}, {0x5c4a, 0x80}, {0x5c4b, 0x80}, {0x5c4c, 0x80}, {0x5c4d, 0x40}, + {0x5c4e, 0x80}, {0x5c4f, 0x80}, {0x5c50, 0x80}, {0x5c51, 0x60}, {0x5c52, 0x20}, + {0x5c53, 0x80}, {0x5c54, 0x80}, {0x5c55, 0x80}, {0x5c56, 0x20}, {0x5c57, 0x00}, + {0x5c58, 0x80}, {0x5c59, 0x40}, {0x5c5a, 0x20}, {0x5c5b, 0x00}, {0x5c5c, 0x00}, + {0x5c5d, 0x80}, {0x5c5e, 0x00}, {0x5c5f, 0x00}, {0x5c60, 0x00}, {0x5c61, 0x00}, + {0x5c62, 0x00}, {0x5c63, 0x00}, {0x5c64, 0x00}, {0x5c65, 0x00}, {0x5c66, 0x00}, + + // m_nSPDCombineWeight + {0x5cc9, 0x80}, {0x5cca, 0x80}, {0x5ccb, 0x80}, {0x5ccc, 0x80}, {0x5ccd, 0x80}, + {0x5cce, 0x80}, {0x5ccf, 0x80}, {0x5cd0, 0x80}, {0x5cd1, 0x80}, {0x5cd2, 0x60}, + {0x5cd3, 0x80}, {0x5cd4, 0x80}, {0x5cd5, 0x80}, {0x5cd6, 0x60}, {0x5cd7, 0x40}, + {0x5cd8, 0x80}, {0x5cd9, 0x80}, {0x5cda, 0x80}, {0x5cdb, 0x40}, {0x5cdc, 0x20}, + {0x5cdd, 0x80}, {0x5cde, 0x80}, {0x5cdf, 0x80}, {0x5ce0, 0x20}, {0x5ce1, 0x00}, + {0x5ce2, 0x80}, {0x5ce3, 0x80}, {0x5ce4, 0x80}, {0x5ce5, 0x00}, {0x5ce6, 0x00}, + + {0x5d74, 0x01}, + {0x5d75, 0x00}, + + {0x5d1f, 0x81}, + {0x5d11, 0x00}, + {0x5d12, 0x10}, + {0x5d13, 0x10}, + {0x5d15, 0x05}, + {0x5d16, 0x05}, + {0x5d17, 0x05}, + {0x5d08, 0x03}, + {0x5d09, 0xb6}, + {0x5d0a, 0x03}, + {0x5d0b, 0xb6}, + {0x5d18, 0x03}, + {0x5d19, 0xb6}, + {0x5d62, 0x01}, + {0x5d40, 0x02}, + {0x5d41, 0x01}, + {0x5d63, 0x1f}, + {0x5d64, 0x00}, + {0x5d65, 0x80}, + {0x5d56, 0x00}, + {0x5d57, 0x20}, + {0x5d58, 0x00}, + {0x5d59, 0x20}, + {0x5d5a, 0x00}, + {0x5d5b, 0x0c}, + {0x5d5c, 0x02}, + {0x5d5d, 0x40}, + {0x5d5e, 0x02}, + {0x5d5f, 0x40}, + {0x5d60, 0x03}, + {0x5d61, 0x40}, + {0x5d4a, 0x02}, + {0x5d4b, 0x40}, + {0x5d4c, 0x02}, + {0x5d4d, 0x40}, + {0x5d4e, 0x02}, + {0x5d4f, 0x40}, + {0x5d50, 0x18}, + {0x5d51, 0x80}, + {0x5d52, 0x18}, + {0x5d53, 0x80}, + {0x5d54, 0x18}, + {0x5d55, 0x80}, + {0x5d46, 0x20}, + {0x5d47, 0x00}, + {0x5d48, 0x22}, + {0x5d49, 0x00}, + {0x5d42, 0x20}, + {0x5d43, 0x00}, + {0x5d44, 0x22}, + {0x5d45, 0x00}, + + {0x5004, 0x1e}, + {0x4221, 0x03}, // this is changed from 1 -> 3 + + // DCG exposure coarse + // {0x3501, 0x01}, {0x3502, 0xc8}, + // SPD exposure coarse + // {0x3541, 0x01}, {0x3542, 0xc8}, + // VS exposure coarse + // {0x35c1, 0x00}, {0x35c2, 0x01}, + + // crc reference + {0x420e, 0x66}, {0x420f, 0x5d}, {0x4210, 0xa8}, {0x4211, 0x55}, + // crc stat check + {0x507a, 0x5f}, {0x507b, 0x46}, + + // watchdog control + {0x4f00, 0x00}, {0x4f01, 0x01}, {0x4f02, 0x80}, {0x4f04, 0x2c}, + + // color balance gains + // blue + {0x5280, 0x06}, {0x5281, 0xCB}, // hcg + {0x5480, 0x06}, {0x5481, 0xCB}, // lcg + {0x5680, 0x06}, {0x5681, 0xCB}, // spd + {0x5880, 0x06}, {0x5881, 0xCB}, // vs + + // green(blue) + {0x5282, 0x04}, {0x5283, 0x00}, + {0x5482, 0x04}, {0x5483, 0x00}, + {0x5682, 0x04}, {0x5683, 0x00}, + {0x5882, 0x04}, {0x5883, 0x00}, + + // green(red) + {0x5284, 0x04}, {0x5285, 0x00}, + {0x5484, 0x04}, {0x5485, 0x00}, + {0x5684, 0x04}, {0x5685, 0x00}, + {0x5884, 0x04}, {0x5885, 0x00}, + + // red + {0x5286, 0x08}, {0x5287, 0xDE}, + {0x5486, 0x08}, {0x5487, 0xDE}, + {0x5686, 0x08}, {0x5687, 0xDE}, + {0x5886, 0x08}, {0x5887, 0xDE}, + + // fixed gains + {0x3588, 0x01}, {0x3589, 0x00}, + {0x35c8, 0x01}, {0x35c9, 0x00}, + {0x3548, 0x0F}, {0x3549, 0x00}, + {0x35c1, 0x00}, +}; diff --git a/system/camerad/sensors/sensor.h b/system/camerad/sensors/sensor.h new file mode 100644 index 0000000000..96aa8b604f --- /dev/null +++ b/system/camerad/sensors/sensor.h @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "media/cam_isp.h" +#include "media/cam_sensor.h" + +#include "cereal/gen/cpp/log.capnp.h" +#include "system/camerad/sensors/ox03c10_registers.h" +#include "system/camerad/sensors/os04c10_registers.h" + +#define ANALOG_GAIN_MAX_CNT 55 + +class SensorInfo { +public: + SensorInfo() = default; + virtual std::vector getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const { return {}; } + virtual float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const {return 0; } + virtual int getSlaveAddress(int port) const { assert(0); } + + cereal::FrameData::ImageSensor image_sensor = cereal::FrameData::ImageSensor::UNKNOWN; + float pixel_size_mm; + uint32_t frame_width, frame_height; + uint32_t frame_stride; + uint32_t frame_offset = 0; + uint32_t extra_height = 0; + int out_scale = 1; + int registers_offset = -1; + int stats_offset = -1; + int hdr_offset = -1; + + int exposure_time_min; + int exposure_time_max; + + float dc_gain_factor; + int dc_gain_min_weight; + int dc_gain_max_weight; + float dc_gain_on_grey; + float dc_gain_off_grey; + + float ev_scale = 1.0; + float sensor_analog_gains[ANALOG_GAIN_MAX_CNT]; + int analog_gain_min_idx; + int analog_gain_max_idx; + int analog_gain_rec_idx; + int analog_gain_cost_delta; + float analog_gain_cost_low; + float analog_gain_cost_high; + float target_grey_factor; + float min_ev; + float max_ev; + + bool data_word; + uint32_t probe_reg_addr; + uint32_t probe_expected_data; + std::vector start_reg_array; + std::vector init_reg_array; + + uint32_t bits_per_pixel; + uint32_t bayer_pattern; + uint32_t mipi_format; + uint32_t mclk_frequency; + uint32_t frame_data_type; + + uint32_t readout_time_ns; // used to recover EOF from SOF + + // ISP image processing params + uint32_t black_level; + std::vector color_correct_matrix; // 3x3 + std::vector gamma_lut_rgb; // gamma LUTs are length 64 * sizeof(uint32_t); same for r/g/b here + void prepare_gamma_lut() { + for (int i = 0; i < 64; i++) { + gamma_lut_rgb[i] |= ((uint32_t)(gamma_lut_rgb[i+1] - gamma_lut_rgb[i]) << 10); + } + gamma_lut_rgb.pop_back(); + } + std::vector linearization_lut; // length 36 + std::vector linearization_pts; // length 4 + std::vector vignetting_lut; // length 221 + + const int num() const { + return static_cast(image_sensor); + }; +}; + +class OX03C10 : public SensorInfo { +public: + OX03C10(); + std::vector getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const override; + float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override; + int getSlaveAddress(int port) const override; +}; + +class OS04C10 : public SensorInfo { +public: + OS04C10(); + void ife_downscale_configure(); + std::vector getExposureRegisters(int exposure_time, int new_exp_g, bool dc_gain_enabled) const override; + float getExposureScore(float desired_ev, int exp_t, int exp_g_idx, float exp_gain, int gain_idx) const override; + int getSlaveAddress(int port) const override; +}; diff --git a/system/camerad/snapshot.py b/system/camerad/snapshot.py new file mode 100755 index 0000000000..b3369891d7 --- /dev/null +++ b/system/camerad/snapshot.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +import subprocess +import time + +import numpy as np +from PIL import Image + +import cereal.messaging as messaging +from msgq.visionipc import VisionIpcClient, VisionStreamType +from openpilot.common.params import Params +from openpilot.common.realtime import DT_MDL +from openpilot.system.hardware import PC +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.system.manager.process_config import managed_processes + + +VISION_STREAMS = { + "roadCameraState": VisionStreamType.VISION_STREAM_ROAD, + "driverCameraState": VisionStreamType.VISION_STREAM_DRIVER, + "wideRoadCameraState": VisionStreamType.VISION_STREAM_WIDE_ROAD, +} + + +def jpeg_write(fn, dat): + img = Image.fromarray(dat) + img.save(fn, "JPEG") + + +def yuv_to_rgb(y, u, v): + ul = np.repeat(np.repeat(u, 2).reshape(u.shape[0], y.shape[1]), 2, axis=0).reshape(y.shape) + vl = np.repeat(np.repeat(v, 2).reshape(v.shape[0], y.shape[1]), 2, axis=0).reshape(y.shape) + + yuv = np.dstack((y, ul, vl)).astype(np.int16) + yuv[:, :, 1:] -= 128 + + m = np.array([ + [1.00000, 1.00000, 1.00000], + [0.00000, -0.39465, 2.03211], + [1.13983, -0.58060, 0.00000], + ]) + rgb = np.dot(yuv, m).clip(0, 255) + return rgb.astype(np.uint8) + + +def extract_image(buf): + y = np.array(buf.data[:buf.uv_offset], dtype=np.uint8).reshape((-1, buf.stride))[:buf.height, :buf.width] + u = np.array(buf.data[buf.uv_offset::2], dtype=np.uint8).reshape((-1, buf.stride//2))[:buf.height//2, :buf.width//2] + v = np.array(buf.data[buf.uv_offset+1::2], dtype=np.uint8).reshape((-1, buf.stride//2))[:buf.height//2, :buf.width//2] + + return yuv_to_rgb(y, u, v) + + +def get_snapshots(frame="roadCameraState", front_frame="driverCameraState"): + sockets = [s for s in (frame, front_frame) if s is not None] + sm = messaging.SubMaster(sockets) + vipc_clients = {s: VisionIpcClient("camerad", VISION_STREAMS[s], True) for s in sockets} + + # wait 4 sec from camerad startup for focus and exposure + while sm[sockets[0]].frameId < int(4. / DT_MDL): + sm.update() + + for client in vipc_clients.values(): + client.connect(True) + + # grab images + rear, front = None, None + if frame is not None: + c = vipc_clients[frame] + rear = extract_image(c.recv()) + if front_frame is not None: + c = vipc_clients[front_frame] + front = extract_image(c.recv()) + return rear, front + + +def snapshot(): + params = Params() + + if (not params.get_bool("IsOffroad")) or params.get_bool("IsTakingSnapshot"): + print("Already taking snapshot") + return None, None + + front_camera_allowed = params.get_bool("RecordFront") + params.put_bool("IsTakingSnapshot", True) + set_offroad_alert("Offroad_IsTakingSnapshot", True) + time.sleep(2.0) # Give hardwared time to read the param, or if just started give camerad time to start + + # Check if camerad is already started + try: + subprocess.check_call(["pgrep", "camerad"]) + print("Camerad already running") + params.put_bool("IsTakingSnapshot", False) + params.remove("Offroad_IsTakingSnapshot") + return None, None + except subprocess.CalledProcessError: + pass + + try: + # Allow testing on replay on PC + if not PC: + managed_processes['camerad'].start() + + frame = "wideRoadCameraState" + front_frame = "driverCameraState" if front_camera_allowed else None + rear, front = get_snapshots(frame, front_frame) + finally: + managed_processes['camerad'].stop() + params.put_bool("IsTakingSnapshot", False) + set_offroad_alert("Offroad_IsTakingSnapshot", False) + + if not front_camera_allowed: + front = None + + return rear, front + + +if __name__ == "__main__": + pic, fpic = snapshot() + if pic is not None: + print(pic.shape) + jpeg_write("/tmp/back.jpg", pic) + if fpic is not None: + jpeg_write("/tmp/front.jpg", fpic) + else: + print("Error taking snapshot") diff --git a/system/camerad/test/.gitignore b/system/camerad/test/.gitignore new file mode 100644 index 0000000000..d67473ebcd --- /dev/null +++ b/system/camerad/test/.gitignore @@ -0,0 +1,2 @@ +jpegs/ +test_ae_gray diff --git a/system/camerad/test/debug.sh b/system/camerad/test/debug.sh new file mode 100755 index 0000000000..a031be6923 --- /dev/null +++ b/system/camerad/test/debug.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e + +#echo 4294967295 | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl + +# no CCI and UTIL, very spammy +echo 0xfffdbfff | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl +#echo 0 | sudo tee /sys/module/cam_debug_util/parameters/debug_mdl + +sudo dmesg -C +scons -u -j8 --minimal . +export DEBUG_FRAMES=1 +export DISABLE_ROAD=1 DISABLE_WIDE_ROAD=1 +#export DISABLE_DRIVER=1 +export LOGPRINT=debug +./camerad diff --git a/system/camerad/test/icp_debug.sh b/system/camerad/test/icp_debug.sh new file mode 100755 index 0000000000..ebeef9bf8f --- /dev/null +++ b/system/camerad/test/icp_debug.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +cd /sys/kernel/debug/tracing +echo "" > trace +echo 1 > tracing_on +#echo Y > /sys/kernel/debug/camera_icp/a5_debug_q +echo 0x1 > /sys/kernel/debug/camera_icp/a5_debug_type +echo 1 > /sys/kernel/debug/tracing/events/camera/enable +echo 0xffffffff > /sys/kernel/debug/camera_icp/a5_debug_lvl +echo 1 > /sys/kernel/debug/tracing/events/camera/cam_icp_fw_dbg/enable + +cat /sys/kernel/debug/tracing/trace_pipe diff --git a/system/camerad/test/intercept.sh b/system/camerad/test/intercept.sh new file mode 100755 index 0000000000..e269929afc --- /dev/null +++ b/system/camerad/test/intercept.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +DISABLE_ROAD=1 DISABLE_WIDE_ROAD=1 DEBUG_FRAMES=1 LOGPRINT=debug LD_PRELOAD=/data/tici_test_scripts/isp/interceptor/tmpioctl.so ./camerad diff --git a/system/camerad/test/stress_restart.sh b/system/camerad/test/stress_restart.sh new file mode 100755 index 0000000000..0445dcba79 --- /dev/null +++ b/system/camerad/test/stress_restart.sh @@ -0,0 +1,9 @@ +#!/bin/sh +cd .. +while :; do + ./camerad & + pid="$!" + sleep 2 + kill -2 $pid + wait $pid +done diff --git a/system/camerad/test/test_ae_gray.cc b/system/camerad/test/test_ae_gray.cc new file mode 100644 index 0000000000..39c3d9c4e5 --- /dev/null +++ b/system/camerad/test/test_ae_gray.cc @@ -0,0 +1,84 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" + +#include + +#include +#include + +#include "common/util.h" +#include "system/camerad/cameras/camera_common.h" + +#define W 240 +#define H 160 + + +#define TONE_SPLITS 3 + +float gts[TONE_SPLITS * TONE_SPLITS * TONE_SPLITS * TONE_SPLITS] = { + 0.917969, 0.917969, 0.375000, 0.917969, 0.375000, 0.375000, 0.187500, 0.187500, 0.187500, 0.917969, + 0.375000, 0.375000, 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.093750, 0.093750, + 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.917969, 0.375000, 0.375000, + 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.187500, 0.093750, 0.093750, 0.093750, 0.093750, + 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, 0.093750, + 0.093750, 0.093750, 0.093750, 0.093750, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, + 0.000000}; + + +TEST_CASE("camera.test_calculate_exposure_value") { + // set up fake camerabuf + CameraBuf cb = {}; + VisionBuf vb = {}; + uint8_t * fb_y = new uint8_t[W*H]; + vb.y = fb_y; + cb.cur_yuv_buf = &vb; + cb.out_img_width = W; + cb.out_img_height = H; + Rect rect = {0, 0, W-1, H-1}; + + printf("AE test patterns %dx%d\n", cb.out_img_width, cb.out_img_height); + + // mix of 5 tones + uint8_t l[5] = {0, 24, 48, 96, 235}; // 235 is yuv max + + bool passed = true; + float rtol = 0.05; + // generate pattern and calculate EV + int cnt = 0; + for (int i_0=0; i_0 rtol*evgt) { + passed = false; + } + + // report + printf("%d/%d/%d/%d/%d: ev %f, gt %f, err %f\n", h_0, h_1, h_2, h_3, h_4, ev, evgt, fabs(ev - evgt) / (evgt != 0 ? evgt : 0.00001f)); + cnt++; + } + } + } + } + assert(passed); + + delete[] fb_y; +} diff --git a/system/camerad/test/test_camerad.py b/system/camerad/test/test_camerad.py new file mode 100644 index 0000000000..1f3f97b082 --- /dev/null +++ b/system/camerad/test/test_camerad.py @@ -0,0 +1,101 @@ +import os +import time +import pytest +import numpy as np + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from openpilot.system.manager.process_config import managed_processes +from openpilot.tools.lib.log_time_series import msgs_to_time_series + +TEST_TIMESPAN = 10 +CAMERAS = ('roadCameraState', 'driverCameraState', 'wideRoadCameraState') + + +def run_and_log(procs, services, duration): + logs = [] + + try: + for p in procs: + managed_processes[p].start() + socks = [messaging.sub_sock(s, conflate=False, timeout=100) for s in services] + + start_time = time.monotonic() + while time.monotonic() - start_time < duration: + for s in socks: + logs.extend(messaging.drain_sock(s)) + for p in procs: + assert managed_processes[p].proc.is_alive() + finally: + for p in procs: + managed_processes[p].stop() + + return logs + +@pytest.fixture(scope="module") +def logs(): + logs = run_and_log(["camerad", ], CAMERAS, TEST_TIMESPAN) + ts = msgs_to_time_series(logs) + + for cam in CAMERAS: + expected_frames = SERVICE_LIST[cam].frequency * TEST_TIMESPAN + cnt = len(ts[cam]['t']) + assert expected_frames*0.8 < cnt < expected_frames*1.2, f"unexpected frame count {cam}: {expected_frames=}, got {cnt}" + + dts = np.abs(np.diff([ts[cam]['timestampSof']/1e6]) - 1000/SERVICE_LIST[cam].frequency) + assert (dts < 1.0).all(), f"{cam} dts(ms) out of spec: max diff {dts.max()}, 99 percentile {np.percentile(dts, 99)}" + return ts + +@pytest.mark.tici +class TestCamerad: + def test_frame_skips(self, logs): + for c in CAMERAS: + assert set(np.diff(logs[c]['frameId'])) == {1, }, f"{c} has frame skips" + + def test_frame_sync(self, logs): + n = range(len(logs['roadCameraState']['t'][:-10])) + + frame_ids = {i: [logs[cam]['frameId'][i] for cam in CAMERAS] for i in n} + assert all(len(set(v)) == 1 for v in frame_ids.values()), "frame IDs not aligned" + + frame_times = {i: [logs[cam]['timestampSof'][i] for cam in CAMERAS] for i in n} + diffs = {i: (max(ts) - min(ts))/1e6 for i, ts in frame_times.items()} + + laggy_frames = {k: v for k, v in diffs.items() if v > 1.1} + assert len(laggy_frames) == 0, f"Frames not synced properly: {laggy_frames=}" + + def test_sanity_checks(self, logs): + self._sanity_checks(logs) + + def _sanity_checks(self, ts): + for c in CAMERAS: + assert c in ts + assert len(ts[c]['t']) > 20 + + # not a valid request id + assert 0 not in ts[c]['requestId'] + + # should monotonically increase + assert np.all(np.diff(ts[c]['frameId']) >= 1) + assert np.all(np.diff(ts[c]['requestId']) >= 1) + + # EOF > SOF + assert np.all((ts[c]['timestampEof'] - ts[c]['timestampSof']) > 0) + + # logMonoTime > SOF + assert np.all((ts[c]['t'] - ts[c]['timestampSof']/1e9) > 1e-7) + + # logMonoTime > EOF, needs some tolerance since EOF is (SOF + readout time) but there is noise in the SOF timestamping (done via IRQ) + assert np.mean((ts[c]['t'] - ts[c]['timestampEof']/1e9) > 1e-7) > 0.7 # should be mostly logMonoTime > EOF + assert np.all((ts[c]['t'] - ts[c]['timestampEof']/1e9) > -0.10) # when EOF > logMonoTime, it should never be more than two frames + + def test_stress_test(self): + os.environ['SPECTRA_ERROR_PROB'] = '0.008' + logs = run_and_log(["camerad", ], CAMERAS, 10) + ts = msgs_to_time_series(logs) + + # we should see some jumps from introduced errors + assert np.max([ np.max(np.diff(ts[c]['frameId'])) for c in CAMERAS ]) > 1 + assert np.max([ np.max(np.diff(ts[c]['requestId'])) for c in CAMERAS ]) > 1 + + self._sanity_checks(ts) diff --git a/system/camerad/test/test_exposure.py b/system/camerad/test/test_exposure.py new file mode 100644 index 0000000000..b853b0f2f2 --- /dev/null +++ b/system/camerad/test/test_exposure.py @@ -0,0 +1,51 @@ +import time +import numpy as np +import pytest + +from openpilot.selfdrive.test.helpers import with_processes +from openpilot.system.camerad.snapshot import get_snapshots + +TEST_TIME = 45 +REPEAT = 5 + +@pytest.mark.tici +class TestCamerad: + @classmethod + def setup_class(cls): + pass + + def _numpy_rgb2gray(self, im): + ret = np.clip(im[:,:,2] * 0.114 + im[:,:,1] * 0.587 + im[:,:,0] * 0.299, 0, 255).astype(np.uint8) + return ret + + def _is_exposure_okay(self, i, med_mean=None): + if med_mean is None: + med_mean = np.array([[0.2,0.4],[0.2,0.6]]) + h, w = i.shape[:2] + i = i[h//10:9*h//10,w//10:9*w//10] + med_ex, mean_ex = med_mean + i = self._numpy_rgb2gray(i) + i_median = np.median(i) / 255. + i_mean = np.mean(i) / 255. + print([i_median, i_mean]) + return med_ex[0] < i_median < med_ex[1] and mean_ex[0] < i_mean < mean_ex[1] + + @with_processes(['camerad']) + def test_camera_operation(self): + passed = 0 + start = time.monotonic() + while time.monotonic() - start < TEST_TIME and passed < REPEAT: + rpic, dpic = get_snapshots(frame="roadCameraState", front_frame="driverCameraState") + wpic, _ = get_snapshots(frame="wideRoadCameraState") + + res = self._is_exposure_okay(rpic) + res = res and self._is_exposure_okay(dpic) + res = res and self._is_exposure_okay(wpic) + + if passed > 0 and not res: + passed = -passed # fails test if any failure after first sus + break + + passed += int(res) + time.sleep(2) + assert passed >= REPEAT diff --git a/system/hardware/.gitignore b/system/hardware/.gitignore new file mode 100644 index 0000000000..980f09abfa --- /dev/null +++ b/system/hardware/.gitignore @@ -0,0 +1 @@ +eon/rat diff --git a/system/hardware/__init__.py b/system/hardware/__init__.py new file mode 100644 index 0000000000..99079b5ef3 --- /dev/null +++ b/system/hardware/__init__.py @@ -0,0 +1,16 @@ +import os +from typing import cast + +from openpilot.system.hardware.base import HardwareBase +from openpilot.system.hardware.tici.hardware import Tici +from openpilot.system.hardware.pc.hardware import Pc + +TICI = os.path.isfile('/TICI') +AGNOS = os.path.isfile('/AGNOS') +PC = not TICI + + +if TICI: + HARDWARE = cast(HardwareBase, Tici()) +else: + HARDWARE = cast(HardwareBase, Pc()) diff --git a/system/hardware/base.h b/system/hardware/base.h new file mode 100644 index 0000000000..df9700a017 --- /dev/null +++ b/system/hardware/base.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include + +#include "cereal/gen/cpp/log.capnp.h" + +// no-op base hw class +class HardwareNone { +public: + static std::string get_os_version() { return ""; } + static std::string get_name() { return ""; } + static cereal::InitData::DeviceType get_device_type() { return cereal::InitData::DeviceType::UNKNOWN; } + static int get_voltage() { return 0; } + static int get_current() { return 0; } + + static std::string get_serial() { return "cccccc"; } + + static std::map get_init_logs() { + return {}; + } + + static void reboot() {} + static void poweroff() {} + static void set_brightness(int percent) {} + static void set_ir_power(int percentage) {} + static void set_display_power(bool on) {} + + static bool get_ssh_enabled() { return false; } + static void set_ssh_enabled(bool enabled) {} + + static bool PC() { return false; } + static bool TICI() { return false; } + static bool AGNOS() { return false; } +}; diff --git a/system/hardware/base.py b/system/hardware/base.py new file mode 100644 index 0000000000..17d0ec1614 --- /dev/null +++ b/system/hardware/base.py @@ -0,0 +1,243 @@ +import os +from abc import abstractmethod, ABC +from dataclasses import dataclass, fields + +from cereal import log + +NetworkType = log.DeviceState.NetworkType + +class LPAError(RuntimeError): + pass + +class LPAProfileNotFoundError(LPAError): + pass + +@dataclass +class Profile: + iccid: str + nickname: str + enabled: bool + provider: str + +@dataclass +class ThermalZone: + # a zone from /sys/class/thermal/thermal_zone* + name: str # a.k.a type + scale: float = 1000. # scale to get degrees in C + zone_number = -1 + + def read(self) -> float: + if self.zone_number < 0: + for n in os.listdir("/sys/devices/virtual/thermal"): + if not n.startswith("thermal_zone"): + continue + with open(os.path.join("/sys/devices/virtual/thermal", n, "type")) as f: + if f.read().strip() == self.name: + self.zone_number = int(n.removeprefix("thermal_zone")) + break + + try: + with open(f"/sys/devices/virtual/thermal/thermal_zone{self.zone_number}/temp") as f: + return int(f.read()) / self.scale + except FileNotFoundError: + return 0 + +@dataclass +class ThermalConfig: + cpu: list[ThermalZone] | None = None + gpu: list[ThermalZone] | None = None + dsp: ThermalZone | None = None + pmic: list[ThermalZone] | None = None + memory: ThermalZone | None = None + intake: ThermalZone | None = None + exhaust: ThermalZone | None = None + case: ThermalZone | None = None + + def get_msg(self): + ret = {} + for f in fields(ThermalConfig): + v = getattr(self, f.name) + if v is not None: + if isinstance(v, list): + ret[f.name + "TempC"] = [x.read() for x in v] + else: + ret[f.name + "TempC"] = v.read() + return ret + +class LPABase(ABC): + @abstractmethod + def bootstrap(self) -> None: + pass + + @abstractmethod + def list_profiles(self) -> list[Profile]: + pass + + @abstractmethod + def get_active_profile(self) -> Profile | None: + pass + + @abstractmethod + def delete_profile(self, iccid: str) -> None: + pass + + @abstractmethod + def download_profile(self, qr: str, nickname: str | None = None) -> None: + pass + + @abstractmethod + def nickname_profile(self, iccid: str, nickname: str) -> None: + pass + + @abstractmethod + def switch_profile(self, iccid: str) -> None: + pass + + def is_comma_profile(self, iccid: str) -> bool: + return any(iccid.startswith(prefix) for prefix in ('8985235',)) + +class HardwareBase(ABC): + @staticmethod + def get_cmdline() -> dict[str, str]: + with open('/proc/cmdline') as f: + cmdline = f.read() + return {kv[0]: kv[1] for kv in [s.split('=') for s in cmdline.split(' ')] if len(kv) == 2} + + @staticmethod + def read_param_file(path, parser, default=0): + try: + with open(path) as f: + return parser(f.read()) + except Exception: + return default + + def booted(self) -> bool: + return True + + @abstractmethod + def reboot(self, reason=None): + pass + + @abstractmethod + def uninstall(self): + pass + + @abstractmethod + def get_os_version(self): + pass + + @abstractmethod + def get_device_type(self): + pass + + @abstractmethod + def get_imei(self, slot) -> str: + pass + + @abstractmethod + def get_serial(self): + pass + + @abstractmethod + def get_network_info(self): + pass + + @abstractmethod + def get_network_type(self): + pass + + @abstractmethod + def get_sim_info(self): + pass + + @abstractmethod + def get_sim_lpa(self) -> LPABase: + pass + + @abstractmethod + def get_network_strength(self, network_type): + pass + + def get_network_metered(self, network_type) -> bool: + return network_type not in (NetworkType.none, NetworkType.wifi, NetworkType.ethernet) + + @staticmethod + def set_bandwidth_limit(upload_speed_kbps: int, download_speed_kbps: int) -> None: + pass + + @abstractmethod + def get_current_power_draw(self): + pass + + @abstractmethod + def get_som_power_draw(self): + pass + + @abstractmethod + def shutdown(self): + pass + + def get_thermal_config(self): + return ThermalConfig() + + def set_display_power(self, on: bool): + pass + + @abstractmethod + def set_screen_brightness(self, percentage): + pass + + @abstractmethod + def get_screen_brightness(self): + pass + + @abstractmethod + def set_power_save(self, powersave_enabled): + pass + + @abstractmethod + def get_gpu_usage_percent(self): + pass + + def get_modem_version(self): + return None + + @abstractmethod + def get_modem_temperatures(self): + pass + + + @abstractmethod + def initialize_hardware(self): + pass + + def configure_modem(self): + pass + + def reboot_modem(self): + pass + + @abstractmethod + def get_networks(self): + pass + + def has_internal_panda(self) -> bool: + return False + + def reset_internal_panda(self): + pass + + def recover_internal_panda(self): + pass + + def get_modem_data_usage(self): + return -1, -1 + + def get_voltage(self) -> float: + return 0. + + def get_current(self) -> float: + return 0. + + def set_ir_power(self, percent: int): + pass diff --git a/system/hardware/esim.py b/system/hardware/esim.py new file mode 100755 index 0000000000..909ad41e03 --- /dev/null +++ b/system/hardware/esim.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +import argparse +import time +from openpilot.system.hardware import HARDWARE +from openpilot.system.hardware.base import LPABase + + +def bootstrap(lpa: LPABase) -> None: + print('┌──────────────────────────────────────────────────────────────────────────────┐') + print('│ WARNING, PLEASE READ BEFORE PROCEEDING │') + print('│ │') + print('│ this is an irreversible operation that will remove the comma-provisioned │') + print('│ profile. │') + print('│ │') + print('│ after this operation, you must purchase a new eSIM from comma in order to │') + print('│ use the comma prime subscription again. │') + print('└──────────────────────────────────────────────────────────────────────────────┘') + print() + for severity in ('sure', '100% sure'): + print(f'are you {severity} you want to proceed? (y/N) ', end='') + confirm = input() + if confirm != 'y': + print('aborting') + exit(0) + lpa.bootstrap() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(prog='esim.py', description='manage eSIM profiles on your comma device', epilog='comma.ai') + parser.add_argument('--bootstrap', action='store_true', help='bootstrap the eUICC (required before downloading profiles)') + parser.add_argument('--backend', choices=['qmi', 'at'], default='qmi', help='use the specified backend, defaults to qmi') + parser.add_argument('--switch', metavar='iccid', help='switch to profile') + parser.add_argument('--delete', metavar='iccid', help='delete profile (warning: this cannot be undone)') + parser.add_argument('--download', nargs=2, metavar=('qr', 'name'), help='download a profile using QR code (format: LPA:1$rsp.truphone.com$QRF-SPEEDTEST)') + parser.add_argument('--nickname', nargs=2, metavar=('iccid', 'name'), help='update the nickname for a profile') + args = parser.parse_args() + + mutated = False + lpa = HARDWARE.get_sim_lpa() + if args.bootstrap: + bootstrap(lpa) + mutated = True + elif args.switch: + lpa.switch_profile(args.switch) + mutated = True + elif args.delete: + confirm = input('are you sure you want to delete this profile? (y/N) ') + if confirm == 'y': + lpa.delete_profile(args.delete) + mutated = True + else: + print('cancelled') + exit(0) + elif args.download: + lpa.download_profile(args.download[0], args.download[1]) + elif args.nickname: + lpa.nickname_profile(args.nickname[0], args.nickname[1]) + else: + parser.print_help() + + if mutated: + HARDWARE.reboot_modem() + # eUICC needs a small delay post-reboot before querying profiles + time.sleep(.5) + + profiles = lpa.list_profiles() + print(f'\n{len(profiles)} profile{"s" if len(profiles) > 1 else ""}:') + for p in profiles: + print(f'- {p.iccid} (nickname: {p.nickname or ""}) (provider: {p.provider}) - {"enabled" if p.enabled else "disabled"}') diff --git a/system/hardware/fan_controller.py b/system/hardware/fan_controller.py new file mode 100755 index 0000000000..4c7adc0a3e --- /dev/null +++ b/system/hardware/fan_controller.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import numpy as np +from abc import ABC, abstractmethod + +from openpilot.common.realtime import DT_HW +from openpilot.common.swaglog import cloudlog +from openpilot.common.pid import PIDController + +class BaseFanController(ABC): + @abstractmethod + def update(self, cur_temp: float, ignition: bool) -> int: + pass + + +class TiciFanController(BaseFanController): + def __init__(self) -> None: + super().__init__() + cloudlog.info("Setting up TICI fan handler") + + self.last_ignition = False + self.controller = PIDController(k_p=0, k_i=4e-3, k_f=1, rate=(1 / DT_HW)) + + def update(self, cur_temp: float, ignition: bool) -> int: + self.controller.pos_limit = 100 if ignition else 30 + self.controller.neg_limit = 30 if ignition else 0 + + if ignition != self.last_ignition: + self.controller.reset() + + error = cur_temp - 75 + fan_pwr_out = int(self.controller.update( + error=error, + feedforward=np.interp(cur_temp, [60.0, 100.0], [0, 100]) + )) + + self.last_ignition = ignition + return fan_pwr_out + diff --git a/system/hardware/hardwared.py b/system/hardware/hardwared.py new file mode 100755 index 0000000000..1048acfe0a --- /dev/null +++ b/system/hardware/hardwared.py @@ -0,0 +1,488 @@ +#!/usr/bin/env python3 +import fcntl +import os +import queue +import struct +import threading +import time +from collections import OrderedDict, namedtuple + +import psutil + +import cereal.messaging as messaging +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.common.dict_helpers import strip_deprecated_keys +from openpilot.common.filter_simple import FirstOrderFilter +from openpilot.common.params import Params +from openpilot.common.realtime import DT_HW +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.system.hardware import HARDWARE, TICI, AGNOS, PC +from openpilot.system.loggerd.config import get_available_percent +from openpilot.system.statsd import statlog +from openpilot.common.swaglog import cloudlog +from openpilot.system.hardware.power_monitoring import PowerMonitoring +from openpilot.system.hardware.fan_controller import TiciFanController +from openpilot.system.version import terms_version, training_version +from openpilot.system.athena.registration import UNREGISTERED_DONGLE_ID + +ThermalStatus = log.DeviceState.ThermalStatus +NetworkType = log.DeviceState.NetworkType +NetworkStrength = log.DeviceState.NetworkStrength +CURRENT_TAU = 15. # 15s time constant +TEMP_TAU = 5. # 5s time constant +DISCONNECT_TIMEOUT = 5. # wait 5 seconds before going offroad after disconnect so you get an alert +PANDA_STATES_TIMEOUT = round(1000 / SERVICE_LIST['pandaStates'].frequency * 1.5) # 1.5x the expected pandaState frequency +ONROAD_CYCLE_TIME = 1 # seconds to wait offroad after requesting an onroad cycle + +ThermalBand = namedtuple("ThermalBand", ['min_temp', 'max_temp']) +HardwareState = namedtuple("HardwareState", ['network_type', 'network_info', 'network_strength', 'network_stats', + 'network_metered', 'modem_temps']) + +# List of thermal bands. We will stay within this region as long as we are within the bounds. +# When exiting the bounds, we'll jump to the lower or higher band. Bands are ordered in the dict. +THERMAL_BANDS = OrderedDict({ + ThermalStatus.green: ThermalBand(None, 80.0), + ThermalStatus.yellow: ThermalBand(75.0, 96.0), + ThermalStatus.red: ThermalBand(88.0, 107.), + ThermalStatus.danger: ThermalBand(94.0, None), +}) + +# Override to highest thermal band when offroad and above this temp +OFFROAD_DANGER_TEMP = 75 + +prev_offroad_states: dict[str, tuple[bool, str | None]] = {} + + + +def set_offroad_alert_if_changed(offroad_alert: str, show_alert: bool, extra_text: str | None=None): + if prev_offroad_states.get(offroad_alert, None) == (show_alert, extra_text): + return + prev_offroad_states[offroad_alert] = (show_alert, extra_text) + set_offroad_alert(offroad_alert, show_alert, extra_text) + +def touch_thread(end_event): + count = 0 + + pm = messaging.PubMaster(["touch"]) + + event_format = "llHHi" + event_size = struct.calcsize(event_format) + event_frame = [] + + with open("/dev/input/by-path/platform-894000.i2c-event", "rb") as event_file: + fcntl.fcntl(event_file, fcntl.F_SETFL, os.O_NONBLOCK) + while not end_event.is_set(): + if (count % int(1. / DT_HW)) == 0: + event = event_file.read(event_size) + if event: + (sec, usec, etype, code, value) = struct.unpack(event_format, event) + if etype != 0 or code != 0 or value != 0: + touch = log.Touch.new_message() + touch.sec = sec + touch.usec = usec + touch.type = etype + touch.code = code + touch.value = value + event_frame.append(touch) + else: # end of frame, push new log + msg = messaging.new_message('touch', len(event_frame), valid=True) + msg.touch = event_frame + pm.send('touch', msg) + event_frame = [] + continue + + count += 1 + time.sleep(DT_HW) + + +def hw_state_thread(end_event, hw_queue): + """Handles non critical hardware state, and sends over queue""" + count = 0 + prev_hw_state = None + + modem_version = None + modem_configured = False + modem_restarted = False + modem_missing_count = 0 + + while not end_event.is_set(): + # these are expensive calls. update every 10s + if (count % int(10. / DT_HW)) == 0: + try: + network_type = HARDWARE.get_network_type() + modem_temps = HARDWARE.get_modem_temperatures() + if len(modem_temps) == 0 and prev_hw_state is not None: + modem_temps = prev_hw_state.modem_temps + + # Log modem version once + if AGNOS and (modem_version is None): + modem_version = HARDWARE.get_modem_version() + + if modem_version is not None: + cloudlog.event("modem version", version=modem_version) + else: + if not modem_restarted: + # TODO: we may be able to remove this with a MM update + # ModemManager's probing on startup can fail + # rarely, restart the service to probe again. + modem_missing_count += 1 + if modem_missing_count > 3: + modem_restarted = True + cloudlog.event("restarting ModemManager") + os.system("sudo systemctl restart --no-block ModemManager") + + tx, rx = HARDWARE.get_modem_data_usage() + + hw_state = HardwareState( + network_type=network_type, + network_info=HARDWARE.get_network_info(), + network_strength=HARDWARE.get_network_strength(network_type), + network_stats={'wwanTx': tx, 'wwanRx': rx}, + network_metered=HARDWARE.get_network_metered(network_type), + modem_temps=modem_temps, + ) + + try: + hw_queue.put_nowait(hw_state) + except queue.Full: + pass + + if not modem_configured and HARDWARE.get_modem_version() is not None: + cloudlog.warning("configuring modem") + HARDWARE.configure_modem() + modem_configured = True + + prev_hw_state = hw_state + except Exception: + cloudlog.exception("Error getting hardware state") + + count += 1 + time.sleep(DT_HW) + + +def hardware_thread(end_event, hw_queue) -> None: + pm = messaging.PubMaster(['deviceState']) + sm = messaging.SubMaster(["peripheralState", "gpsLocationExternal", "selfdriveState", "pandaStates"], poll="pandaStates") + + count = 0 + + onroad_conditions: dict[str, bool] = { + "ignition": False, + "not_onroad_cycle": True, + "device_temp_good": True, + } + startup_conditions: dict[str, bool] = {} + startup_conditions_prev: dict[str, bool] = {} + + off_ts: float | None = None + started_ts: float | None = None + started_seen = False + startup_blocked_ts: float | None = None + thermal_status = ThermalStatus.yellow + + last_hw_state = HardwareState( + network_type=NetworkType.none, + network_info=None, + network_metered=False, + network_strength=NetworkStrength.unknown, + network_stats={'wwanTx': -1, 'wwanRx': -1}, + modem_temps=[], + ) + + all_temp_filter = FirstOrderFilter(0., TEMP_TAU, DT_HW, initialized=False) + offroad_temp_filter = FirstOrderFilter(0., TEMP_TAU, DT_HW, initialized=False) + should_start_prev = False + in_car = False + engaged_prev = False + offroad_cycle_count = 0 + + params = Params() + power_monitor = PowerMonitoring() + + uptime_offroad: float = params.get("UptimeOffroad", return_default=True) + uptime_onroad: float = params.get("UptimeOnroad", return_default=True) + last_uptime_ts: float = time.monotonic() + + HARDWARE.initialize_hardware() + thermal_config = HARDWARE.get_thermal_config() + + fan_controller = None + + while not end_event.is_set(): + sm.update(PANDA_STATES_TIMEOUT) + + pandaStates = sm['pandaStates'] + peripheralState = sm['peripheralState'] + peripheral_panda_present = peripheralState.pandaType != log.PandaState.PandaType.unknown + + # handle requests to cycle system started state + if params.get_bool("OnroadCycleRequested"): + params.put_bool("OnroadCycleRequested", False) + offroad_cycle_count = sm.frame + onroad_conditions["not_onroad_cycle"] = (sm.frame - offroad_cycle_count) >= ONROAD_CYCLE_TIME * SERVICE_LIST['pandaStates'].frequency + + if sm.updated['pandaStates'] and len(pandaStates) > 0: + + # Set ignition based on any panda connected + onroad_conditions["ignition"] = any(ps.ignitionLine or ps.ignitionCan for ps in pandaStates if ps.pandaType != log.PandaState.PandaType.unknown) + + pandaState = pandaStates[0] + + in_car = pandaState.harnessStatus != log.PandaState.HarnessStatus.notConnected + + # Setup fan handler on first connect to panda + if fan_controller is None and peripheral_panda_present: + if TICI: + fan_controller = TiciFanController() + + elif (time.monotonic() - sm.recv_time['pandaStates']) > DISCONNECT_TIMEOUT: + if onroad_conditions["ignition"]: + onroad_conditions["ignition"] = False + cloudlog.error("panda timed out onroad") + + # Run at 2Hz, plus either edge of ignition + ign_edge = (started_ts is not None) != all(onroad_conditions.values()) + if (sm.frame % round(SERVICE_LIST['pandaStates'].frequency * DT_HW) != 0) and not ign_edge: + continue + + msg = messaging.new_message('deviceState', valid=True) + msg.deviceState = thermal_config.get_msg() + msg.deviceState.deviceType = HARDWARE.get_device_type() + + try: + last_hw_state = hw_queue.get_nowait() + except queue.Empty: + pass + + msg.deviceState.freeSpacePercent = get_available_percent(default=100.0) + msg.deviceState.memoryUsagePercent = int(round(psutil.virtual_memory().percent)) + msg.deviceState.gpuUsagePercent = int(round(HARDWARE.get_gpu_usage_percent())) + online_cpu_usage = [int(round(n)) for n in psutil.cpu_percent(percpu=True)] + offline_cpu_usage = [0., ] * (len(msg.deviceState.cpuTempC) - len(online_cpu_usage)) + msg.deviceState.cpuUsagePercent = online_cpu_usage + offline_cpu_usage + + msg.deviceState.networkType = last_hw_state.network_type + msg.deviceState.networkMetered = last_hw_state.network_metered + msg.deviceState.networkStrength = last_hw_state.network_strength + msg.deviceState.networkStats = last_hw_state.network_stats + if last_hw_state.network_info is not None: + msg.deviceState.networkInfo = last_hw_state.network_info + + msg.deviceState.modemTempC = last_hw_state.modem_temps + + msg.deviceState.screenBrightnessPercent = HARDWARE.get_screen_brightness() + + # this subset is only used for offroad + temp_sources = [ + msg.deviceState.memoryTempC, + max(msg.deviceState.cpuTempC, default=0.), + max(msg.deviceState.gpuTempC, default=0.), + ] + offroad_comp_temp = offroad_temp_filter.update(max(temp_sources)) + + # this drives the thermal status while onroad + temp_sources.append(max(msg.deviceState.pmicTempC, default=0.)) + all_comp_temp = all_temp_filter.update(max(temp_sources)) + msg.deviceState.maxTempC = all_comp_temp + + if fan_controller is not None: + msg.deviceState.fanSpeedPercentDesired = fan_controller.update(all_comp_temp, onroad_conditions["ignition"]) + + is_offroad_for_5_min = (started_ts is None) and ((not started_seen) or (off_ts is None) or (time.monotonic() - off_ts > 60 * 5)) + if is_offroad_for_5_min and offroad_comp_temp > OFFROAD_DANGER_TEMP: + # if device is offroad and already hot without the extra onroad load, + # we want to cool down first before increasing load + thermal_status = ThermalStatus.danger + else: + current_band = THERMAL_BANDS[thermal_status] + band_idx = list(THERMAL_BANDS.keys()).index(thermal_status) + if current_band.min_temp is not None and all_comp_temp < current_band.min_temp: + thermal_status = list(THERMAL_BANDS.keys())[band_idx - 1] + elif current_band.max_temp is not None and all_comp_temp > current_band.max_temp: + thermal_status = list(THERMAL_BANDS.keys())[band_idx + 1] + + # **** starting logic **** + + startup_conditions["up_to_date"] = params.get("Offroad_ConnectivityNeeded") is None or params.get_bool("DisableUpdates") or params.get_bool("SnoozeUpdate") + startup_conditions["no_excessive_actuation"] = params.get("Offroad_ExcessiveActuation") is None + startup_conditions["not_uninstalling"] = not params.get_bool("DoUninstall") + startup_conditions["accepted_terms"] = params.get("HasAcceptedTerms") == terms_version + + # with 2% left, we killall, otherwise the phone will take a long time to boot + startup_conditions["free_space"] = msg.deviceState.freeSpacePercent > 2 + startup_conditions["completed_training"] = params.get("CompletedTrainingVersion") == training_version + startup_conditions["not_driver_view"] = not params.get_bool("IsDriverViewEnabled") + startup_conditions["not_taking_snapshot"] = not params.get_bool("IsTakingSnapshot") + + # must be at an engageable thermal band to go onroad + startup_conditions["device_temp_engageable"] = thermal_status < ThermalStatus.red + + # ensure device is fully booted + startup_conditions["device_booted"] = startup_conditions.get("device_booted", False) or HARDWARE.booted() + + # if the temperature enters the danger zone, go offroad to cool down + onroad_conditions["device_temp_good"] = thermal_status < ThermalStatus.danger + extra_text = f"{offroad_comp_temp:.1f}C" + show_alert = (not onroad_conditions["device_temp_good"] or not startup_conditions["device_temp_engageable"]) and onroad_conditions["ignition"] + set_offroad_alert_if_changed("Offroad_TemperatureTooHigh", show_alert, extra_text=extra_text) + + # *** registration check *** + if not PC: + # we enforce this for our software, but you are welcome + # to make a different decision in your software + startup_conditions["registered_device"] = PC or (params.get("DongleId") != UNREGISTERED_DONGLE_ID) + + # Handle offroad/onroad transition + should_start = all(onroad_conditions.values()) + if started_ts is None: + should_start = should_start and all(startup_conditions.values()) + + if should_start != should_start_prev or (count == 0): + params.put_bool("IsEngaged", False) + engaged_prev = False + HARDWARE.set_power_save(not should_start) + + if sm.updated['selfdriveState']: + engaged = sm['selfdriveState'].enabled + if engaged != engaged_prev: + params.put_bool("IsEngaged", engaged) + engaged_prev = engaged + + try: + with open('/dev/kmsg', 'w') as kmsg: + kmsg.write(f"<3>[hardware] engaged: {engaged}\n") + except Exception: + pass + + if should_start: + off_ts = None + if started_ts is None: + started_ts = time.monotonic() + started_seen = True + if startup_blocked_ts is not None: + cloudlog.event("Startup after block", block_duration=(time.monotonic() - startup_blocked_ts), + startup_conditions=startup_conditions, onroad_conditions=onroad_conditions, + startup_conditions_prev=startup_conditions_prev, error=True) + startup_blocked_ts = None + else: + if onroad_conditions["ignition"] and (startup_conditions != startup_conditions_prev): + cloudlog.event("Startup blocked", startup_conditions=startup_conditions, onroad_conditions=onroad_conditions, error=True) + startup_conditions_prev = startup_conditions.copy() + startup_blocked_ts = time.monotonic() + + started_ts = None + if off_ts is None: + off_ts = time.monotonic() + + # Offroad power monitoring + voltage = None if peripheralState.pandaType == log.PandaState.PandaType.unknown else peripheralState.voltage + power_monitor.calculate(voltage, onroad_conditions["ignition"]) + msg.deviceState.offroadPowerUsageUwh = power_monitor.get_power_used() + msg.deviceState.carBatteryCapacityUwh = max(0, power_monitor.get_car_battery_capacity()) + current_power_draw = HARDWARE.get_current_power_draw() + statlog.sample("power_draw", current_power_draw) + msg.deviceState.powerDrawW = current_power_draw + + som_power_draw = HARDWARE.get_som_power_draw() + statlog.sample("som_power_draw", som_power_draw) + msg.deviceState.somPowerDrawW = som_power_draw + + # Check if we need to shut down + if power_monitor.should_shutdown(onroad_conditions["ignition"], in_car, off_ts, started_seen): + cloudlog.warning(f"shutting device down, offroad since {off_ts}") + params.put_bool("DoShutdown", True) + + msg.deviceState.started = started_ts is not None + msg.deviceState.startedMonoTime = int(1e9*(started_ts or 0)) + + last_ping = params.get("LastAthenaPingTime") + if last_ping is not None: + msg.deviceState.lastAthenaPingTime = last_ping + + msg.deviceState.thermalStatus = thermal_status + pm.send("deviceState", msg) + + # Log to statsd + statlog.gauge("free_space_percent", msg.deviceState.freeSpacePercent) + statlog.gauge("gpu_usage_percent", msg.deviceState.gpuUsagePercent) + statlog.gauge("memory_usage_percent", msg.deviceState.memoryUsagePercent) + for i, usage in enumerate(msg.deviceState.cpuUsagePercent): + statlog.gauge(f"cpu{i}_usage_percent", usage) + for i, temp in enumerate(msg.deviceState.cpuTempC): + statlog.gauge(f"cpu{i}_temperature", temp) + for i, temp in enumerate(msg.deviceState.gpuTempC): + statlog.gauge(f"gpu{i}_temperature", temp) + statlog.gauge("memory_temperature", msg.deviceState.memoryTempC) + for i, temp in enumerate(msg.deviceState.pmicTempC): + statlog.gauge(f"pmic{i}_temperature", temp) + for i, temp in enumerate(last_hw_state.modem_temps): + statlog.gauge(f"modem_temperature{i}", temp) + statlog.gauge("fan_speed_percent_desired", msg.deviceState.fanSpeedPercentDesired) + statlog.gauge("screen_brightness_percent", msg.deviceState.screenBrightnessPercent) + + # report to server once every 10 minutes + rising_edge_started = should_start and not should_start_prev + if rising_edge_started or (count % int(600. / DT_HW)) == 0: + dat = { + 'count': count, + 'pandaStates': [strip_deprecated_keys(p.to_dict()) for p in pandaStates], + 'peripheralState': strip_deprecated_keys(peripheralState.to_dict()), + 'location': (strip_deprecated_keys(sm["gpsLocationExternal"].to_dict()) if sm.alive["gpsLocationExternal"] else None), + 'deviceState': strip_deprecated_keys(msg.to_dict()) + } + cloudlog.event("STATUS_PACKET", **dat) + + # save last one before going onroad + if rising_edge_started: + try: + params.put("LastOffroadStatusPacket", dat) + except Exception: + cloudlog.exception("failed to save offroad status") + + params.put_bool_nonblocking("NetworkMetered", msg.deviceState.networkMetered) + + now_ts = time.monotonic() + if off_ts: + uptime_offroad += now_ts - max(last_uptime_ts, off_ts) + elif started_ts: + uptime_onroad += now_ts - max(last_uptime_ts, started_ts) + last_uptime_ts = now_ts + + if (count % int(60. / DT_HW)) == 0: + params.put("UptimeOffroad", uptime_offroad) + params.put("UptimeOnroad", uptime_onroad) + + count += 1 + should_start_prev = should_start + + +def main(): + hw_queue = queue.Queue(maxsize=1) + end_event = threading.Event() + + threads = [ + threading.Thread(target=hw_state_thread, args=(end_event, hw_queue)), + threading.Thread(target=hardware_thread, args=(end_event, hw_queue)), + ] + + if TICI: + threads.append(threading.Thread(target=touch_thread, args=(end_event,))) + + for t in threads: + t.start() + + try: + while True: + time.sleep(1) + if not all(t.is_alive() for t in threads): + break + finally: + end_event.set() + + for t in threads: + t.join() + + +if __name__ == "__main__": + main() diff --git a/system/hardware/hw.h b/system/hardware/hw.h new file mode 100644 index 0000000000..a9058401ce --- /dev/null +++ b/system/hardware/hw.h @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include "system/hardware/base.h" +#include "common/util.h" + +#if __TICI__ +#include "system/hardware/tici/hardware.h" +#define Hardware HardwareTici +#else +#include "system/hardware/pc/hardware.h" +#define Hardware HardwarePC +#endif + +namespace Path { + inline std::string openpilot_prefix() { + return util::getenv("OPENPILOT_PREFIX", ""); + } + + inline std::string comma_home() { + return util::getenv("HOME") + "/.comma" + Path::openpilot_prefix(); + } + + inline std::string log_root() { + if (const char *env = getenv("LOG_ROOT")) { + return env; + } + return Hardware::PC() ? Path::comma_home() + "/media/0/realdata" : "/data/media/0/realdata"; + } + + inline std::string params() { + return util::getenv("PARAMS_ROOT", Hardware::PC() ? (Path::comma_home() + "/params") : "/data/params"); + } + + inline std::string rsa_file() { + return Hardware::PC() ? Path::comma_home() + "/persist/comma/id_rsa" : "/persist/comma/id_rsa"; + } + + inline std::string swaglog_ipc() { + return "ipc:///tmp/logmessage" + Path::openpilot_prefix(); + } + + inline std::string download_cache_root() { + if (const char *env = getenv("COMMA_CACHE")) { + return env; + } + return "/tmp/comma_download_cache" + Path::openpilot_prefix() + "/"; + } + + inline std::string shm_path() { + #ifdef __APPLE__ + return"/tmp"; + #else + return "/dev/shm"; + #endif + } +} // namespace Path diff --git a/system/hardware/hw.py b/system/hardware/hw.py new file mode 100644 index 0000000000..dc36dc0474 --- /dev/null +++ b/system/hardware/hw.py @@ -0,0 +1,65 @@ +import os +import platform +from pathlib import Path + +from openpilot.system.hardware import PC + +DEFAULT_DOWNLOAD_CACHE_ROOT = "/tmp/comma_download_cache" + +class Paths: + @staticmethod + def comma_home() -> str: + return os.path.join(str(Path.home()), ".comma" + os.environ.get("OPENPILOT_PREFIX", "")) + + @staticmethod + def log_root() -> str: + if os.environ.get('LOG_ROOT', False): + return os.environ['LOG_ROOT'] + elif PC: + return str(Path(Paths.comma_home()) / "media" / "0" / "realdata") + else: + return '/data/media/0/realdata/' + + @staticmethod + def swaglog_root() -> str: + if PC: + return os.path.join(Paths.comma_home(), "log") + else: + return "/data/log/" + + @staticmethod + def swaglog_ipc() -> str: + return "ipc:///tmp/logmessage" + os.environ.get("OPENPILOT_PREFIX", "") + + @staticmethod + def download_cache_root() -> str: + if os.environ.get('COMMA_CACHE', False): + return os.environ['COMMA_CACHE'] + "/" + return DEFAULT_DOWNLOAD_CACHE_ROOT + os.environ.get("OPENPILOT_PREFIX", "") + "/" + + @staticmethod + def persist_root() -> str: + if PC: + return os.path.join(Paths.comma_home(), "persist") + else: + return "/persist/" + + @staticmethod + def stats_root() -> str: + if PC: + return str(Path(Paths.comma_home()) / "stats") + else: + return "/data/stats/" + + @staticmethod + def config_root() -> str: + if PC: + return Paths.comma_home() + else: + return "/tmp/.comma" + + @staticmethod + def shm_path() -> str: + if PC and platform.system() == "Darwin": + return "/tmp" # This is not really shared memory on macOS, but it's the closest we can get + return "/dev/shm" diff --git a/system/hardware/pc/__init__.py b/system/hardware/pc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/hardware/pc/hardware.h b/system/hardware/pc/hardware.h new file mode 100644 index 0000000000..978dd771c8 --- /dev/null +++ b/system/hardware/pc/hardware.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#include "system/hardware/base.h" + +class HardwarePC : public HardwareNone { +public: + static std::string get_os_version() { return "openpilot for PC"; } + static std::string get_name() { return "pc"; } + static cereal::InitData::DeviceType get_device_type() { return cereal::InitData::DeviceType::PC; } + static bool PC() { return true; } + static bool TICI() { return util::getenv("TICI", 0) == 1; } + static bool AGNOS() { return util::getenv("TICI", 0) == 1; } +}; diff --git a/system/hardware/pc/hardware.py b/system/hardware/pc/hardware.py new file mode 100644 index 0000000000..6c11896390 --- /dev/null +++ b/system/hardware/pc/hardware.py @@ -0,0 +1,78 @@ +import random + +from cereal import log +from openpilot.system.hardware.base import HardwareBase, LPABase + +NetworkType = log.DeviceState.NetworkType +NetworkStrength = log.DeviceState.NetworkStrength + +class Pc(HardwareBase): + def get_os_version(self): + return None + + def get_device_type(self): + return "pc" + + def reboot(self, reason=None): + print("REBOOT!") + + def uninstall(self): + print("uninstall") + + def get_imei(self, slot): + return f"{random.randint(0, 1 << 32):015d}" + + def get_serial(self): + return "cccccccc" + + def get_network_info(self): + return None + + def get_network_type(self): + return NetworkType.wifi + + def get_sim_info(self): + return { + 'sim_id': '', + 'mcc_mnc': None, + 'network_type': ["Unknown"], + 'sim_state': ["ABSENT"], + 'data_connected': False + } + + def get_sim_lpa(self) -> LPABase: + raise NotImplementedError("SIM LPA not implemented for PC") + + def get_network_strength(self, network_type): + return NetworkStrength.unknown + + def get_current_power_draw(self): + return 0 + + def get_som_power_draw(self): + return 0 + + def shutdown(self): + print("SHUTDOWN!") + + def set_screen_brightness(self, percentage): + pass + + def get_screen_brightness(self): + return 0 + + def set_power_save(self, powersave_enabled): + pass + + def get_gpu_usage_percent(self): + return 0 + + def get_modem_temperatures(self): + return [] + + + def initialize_hardware(self): + pass + + def get_networks(self): + return None diff --git a/system/hardware/power_monitoring.py b/system/hardware/power_monitoring.py new file mode 100644 index 0000000000..f8b0e8b629 --- /dev/null +++ b/system/hardware/power_monitoring.py @@ -0,0 +1,126 @@ +import time +import threading + +from openpilot.common.params import Params +from openpilot.system.hardware import HARDWARE +from openpilot.common.swaglog import cloudlog +from openpilot.system.statsd import statlog + +CAR_VOLTAGE_LOW_PASS_K = 0.011 # LPF gain for 45s tau (dt/tau / (dt/tau + 1)) + +# While driving, a battery charges completely in about 30-60 minutes +CAR_BATTERY_CAPACITY_uWh = 30e6 +CAR_CHARGING_RATE_W = 45 + +VBATT_PAUSE_CHARGING = 11.8 # Lower limit on the LPF car battery voltage +MAX_TIME_OFFROAD_S = 30*3600 +MIN_ON_TIME_S = 3600 +DELAY_SHUTDOWN_TIME_S = 300 # Wait at least DELAY_SHUTDOWN_TIME_S seconds after offroad_time to shutdown. +VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S = 60 + +class PowerMonitoring: + def __init__(self): + self.params = Params() + self.last_measurement_time = None # Used for integration delta + self.last_save_time = 0 # Used for saving current value in a param + self.power_used_uWh = 0 # Integrated power usage in uWh since going into offroad + self.next_pulsed_measurement_time = None + self.car_voltage_mV = 12e3 # Low-passed version of peripheralState voltage + self.car_voltage_instant_mV = 12e3 # Last value of peripheralState voltage + self.integration_lock = threading.Lock() + + car_battery_capacity_uWh = self.params.get("CarBatteryCapacity") or 0 + + # Reset capacity if it's low + self.car_battery_capacity_uWh = max((CAR_BATTERY_CAPACITY_uWh / 10), car_battery_capacity_uWh) + + # Calculation tick + def calculate(self, voltage: int | None, ignition: bool): + try: + now = time.monotonic() + + # If peripheralState is None, we're probably not in a car, so we don't care + if voltage is None: + with self.integration_lock: + self.last_measurement_time = None + self.next_pulsed_measurement_time = None + self.power_used_uWh = 0 + return + + # Low-pass battery voltage + self.car_voltage_instant_mV = voltage + self.car_voltage_mV = ((voltage * CAR_VOLTAGE_LOW_PASS_K) + (self.car_voltage_mV * (1 - CAR_VOLTAGE_LOW_PASS_K))) + statlog.gauge("car_voltage", self.car_voltage_mV / 1e3) + + # Cap the car battery power and save it in a param every 10-ish seconds + self.car_battery_capacity_uWh = max(self.car_battery_capacity_uWh, 0) + self.car_battery_capacity_uWh = min(self.car_battery_capacity_uWh, CAR_BATTERY_CAPACITY_uWh) + if now - self.last_save_time >= 10: + self.params.put_nonblocking("CarBatteryCapacity", int(self.car_battery_capacity_uWh)) + self.last_save_time = now + + # First measurement, set integration time + with self.integration_lock: + if self.last_measurement_time is None: + self.last_measurement_time = now + return + + if ignition: + # If there is ignition, we integrate the charging rate of the car + with self.integration_lock: + self.power_used_uWh = 0 + integration_time_h = (now - self.last_measurement_time) / 3600 + if integration_time_h < 0: + raise ValueError(f"Negative integration time: {integration_time_h}h") + self.car_battery_capacity_uWh += (CAR_CHARGING_RATE_W * 1e6 * integration_time_h) + self.last_measurement_time = now + else: + # Get current power draw somehow + current_power = HARDWARE.get_current_power_draw() + + # Do the integration + self._perform_integration(now, current_power) + except Exception: + cloudlog.exception("Power monitoring calculation failed") + + def _perform_integration(self, t: float, current_power: float) -> None: + with self.integration_lock: + try: + if self.last_measurement_time: + integration_time_h = (t - self.last_measurement_time) / 3600 + power_used = (current_power * 1000000) * integration_time_h + if power_used < 0: + raise ValueError(f"Negative power used! Integration time: {integration_time_h} h Current Power: {power_used} uWh") + self.power_used_uWh += power_used + self.car_battery_capacity_uWh -= power_used + self.last_measurement_time = t + except Exception: + cloudlog.exception("Integration failed") + + # Get the power usage + def get_power_used(self) -> int: + return int(self.power_used_uWh) + + def get_car_battery_capacity(self) -> int: + return int(self.car_battery_capacity_uWh) + + # See if we need to shutdown + def should_shutdown(self, ignition: bool, in_car: bool, offroad_timestamp: float | None, started_seen: bool): + if offroad_timestamp is None: + return False + + now = time.monotonic() + should_shutdown = False + offroad_time = (now - offroad_timestamp) + low_voltage_shutdown = (self.car_voltage_mV < (VBATT_PAUSE_CHARGING * 1e3) and + offroad_time > VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S) + should_shutdown |= offroad_time > MAX_TIME_OFFROAD_S + should_shutdown |= low_voltage_shutdown + should_shutdown |= (self.car_battery_capacity_uWh <= 0) + should_shutdown &= not ignition + should_shutdown &= (not self.params.get_bool("DisablePowerDown")) + should_shutdown &= in_car + should_shutdown &= offroad_time > DELAY_SHUTDOWN_TIME_S + should_shutdown |= self.params.get_bool("ForcePowerDown") + should_shutdown &= started_seen or (now > MIN_ON_TIME_S) + return should_shutdown diff --git a/system/hardware/tests/__init__.py b/system/hardware/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/hardware/tests/test_fan_controller.py b/system/hardware/tests/test_fan_controller.py new file mode 100644 index 0000000000..002c1edfda --- /dev/null +++ b/system/hardware/tests/test_fan_controller.py @@ -0,0 +1,50 @@ +import pytest + +from openpilot.system.hardware.fan_controller import TiciFanController + +ALL_CONTROLLERS = [TiciFanController] + +def patched_controller(mocker, controller_class): + mocker.patch("os.system", new=mocker.Mock()) + return controller_class() + +class TestFanController: + def wind_up(self, controller, ignition=True): + for _ in range(1000): + controller.update(100, ignition) + + def wind_down(self, controller, ignition=False): + for _ in range(1000): + controller.update(10, ignition) + + @pytest.mark.parametrize("controller_class", ALL_CONTROLLERS) + def test_hot_onroad(self, mocker, controller_class): + controller = patched_controller(mocker, controller_class) + self.wind_up(controller) + assert controller.update(100, True) >= 70 + + @pytest.mark.parametrize("controller_class", ALL_CONTROLLERS) + def test_offroad_limits(self, mocker, controller_class): + controller = patched_controller(mocker, controller_class) + self.wind_up(controller) + assert controller.update(100, False) <= 30 + + @pytest.mark.parametrize("controller_class", ALL_CONTROLLERS) + def test_no_fan_wear(self, mocker, controller_class): + controller = patched_controller(mocker, controller_class) + self.wind_down(controller) + assert controller.update(10, False) == 0 + + @pytest.mark.parametrize("controller_class", ALL_CONTROLLERS) + def test_limited(self, mocker, controller_class): + controller = patched_controller(mocker, controller_class) + self.wind_up(controller, True) + assert controller.update(100, True) == 100 + + @pytest.mark.parametrize("controller_class", ALL_CONTROLLERS) + def test_windup_speed(self, mocker, controller_class): + controller = patched_controller(mocker, controller_class) + self.wind_down(controller, True) + for _ in range(10): + controller.update(90, True) + assert controller.update(90, True) >= 60 diff --git a/system/hardware/tests/test_power_monitoring.py b/system/hardware/tests/test_power_monitoring.py new file mode 100644 index 0000000000..1dff6c6c5f --- /dev/null +++ b/system/hardware/tests/test_power_monitoring.py @@ -0,0 +1,199 @@ +import pytest + +from openpilot.common.params import Params +from openpilot.system.hardware.power_monitoring import PowerMonitoring, CAR_BATTERY_CAPACITY_uWh, \ + CAR_CHARGING_RATE_W, VBATT_PAUSE_CHARGING, DELAY_SHUTDOWN_TIME_S + +# Create fake time +ssb = 0. +def mock_time_monotonic(): + global ssb + ssb += 1. + return ssb + +TEST_DURATION_S = 50 +GOOD_VOLTAGE = 12 * 1e3 +VOLTAGE_BELOW_PAUSE_CHARGING = (VBATT_PAUSE_CHARGING - 1) * 1e3 + +def pm_patch(mocker, name, value, constant=False): + if constant: + mocker.patch(f"openpilot.system.hardware.power_monitoring.{name}", value) + else: + mocker.patch(f"openpilot.system.hardware.power_monitoring.{name}", return_value=value) + + +@pytest.fixture(autouse=True) +def mock_time(mocker): + mocker.patch("time.monotonic", mock_time_monotonic) + + +class TestPowerMonitoring: + def setup_method(self): + self.params = Params() + + # Test to see that it doesn't do anything when pandaState is None + def test_panda_state_present(self): + pm = PowerMonitoring() + for _ in range(10): + pm.calculate(None, None) + assert pm.get_power_used() == 0 + assert pm.get_car_battery_capacity() == (CAR_BATTERY_CAPACITY_uWh / 10) + + # Test to see that it doesn't integrate offroad when ignition is True + def test_offroad_ignition(self): + pm = PowerMonitoring() + for _ in range(10): + pm.calculate(GOOD_VOLTAGE, True) + assert pm.get_power_used() == 0 + + # Test to see that it integrates with discharging battery + def test_offroad_integration_discharging(self, mocker): + POWER_DRAW = 4 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + for _ in range(TEST_DURATION_S + 1): + pm.calculate(GOOD_VOLTAGE, False) + expected_power_usage = ((TEST_DURATION_S/3600) * POWER_DRAW * 1e6) + assert abs(pm.get_power_used() - expected_power_usage) < 10 + + # Test to check positive integration of car_battery_capacity + def test_car_battery_integration_onroad(self, mocker): + POWER_DRAW = 4 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = 0 + for _ in range(TEST_DURATION_S + 1): + pm.calculate(GOOD_VOLTAGE, True) + expected_capacity = ((TEST_DURATION_S/3600) * CAR_CHARGING_RATE_W * 1e6) + assert abs(pm.get_car_battery_capacity() - expected_capacity) < 10 + + # Test to check positive integration upper limit + def test_car_battery_integration_upper_limit(self, mocker): + POWER_DRAW = 4 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh - 1000 + for _ in range(TEST_DURATION_S + 1): + pm.calculate(GOOD_VOLTAGE, True) + estimated_capacity = CAR_BATTERY_CAPACITY_uWh + (CAR_CHARGING_RATE_W / 3600 * 1e6) + assert abs(pm.get_car_battery_capacity() - estimated_capacity) < 10 + + # Test to check negative integration of car_battery_capacity + def test_car_battery_integration_offroad(self, mocker): + POWER_DRAW = 4 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh + for _ in range(TEST_DURATION_S + 1): + pm.calculate(GOOD_VOLTAGE, False) + expected_capacity = CAR_BATTERY_CAPACITY_uWh - ((TEST_DURATION_S/3600) * POWER_DRAW * 1e6) + assert abs(pm.get_car_battery_capacity() - expected_capacity) < 10 + + # Test to check negative integration lower limit + def test_car_battery_integration_lower_limit(self, mocker): + POWER_DRAW = 4 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = 1000 + for _ in range(TEST_DURATION_S + 1): + pm.calculate(GOOD_VOLTAGE, False) + estimated_capacity = 0 - ((1/3600) * POWER_DRAW * 1e6) + assert abs(pm.get_car_battery_capacity() - estimated_capacity) < 10 + + # Test to check policy of stopping charging after MAX_TIME_OFFROAD_S + def test_max_time_offroad(self, mocker): + MOCKED_MAX_OFFROAD_TIME = 3600 + POWER_DRAW = 0 # To stop shutting down for other reasons + pm_patch(mocker, "MAX_TIME_OFFROAD_S", MOCKED_MAX_OFFROAD_TIME, constant=True) + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh + start_time = ssb + ignition = False + while ssb <= start_time + MOCKED_MAX_OFFROAD_TIME: + pm.calculate(GOOD_VOLTAGE, ignition) + if (ssb - start_time) % 1000 == 0 and ssb < start_time + MOCKED_MAX_OFFROAD_TIME: + assert not pm.should_shutdown(ignition, True, start_time, False) + assert pm.should_shutdown(ignition, True, start_time, False) + + def test_car_voltage(self, mocker): + POWER_DRAW = 0 # To stop shutting down for other reasons + TEST_TIME = 350 + VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S = 50 + pm_patch(mocker, "VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S", VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S, constant=True) + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh + ignition = False + start_time = ssb + for i in range(TEST_TIME): + pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition) + if i % 10 == 0: + assert pm.should_shutdown(ignition, True, start_time, True) == \ + (pm.car_voltage_mV < VBATT_PAUSE_CHARGING * 1e3 and \ + (ssb - start_time) > VOLTAGE_SHUTDOWN_MIN_OFFROAD_TIME_S and \ + (ssb - start_time) > DELAY_SHUTDOWN_TIME_S) + assert pm.should_shutdown(ignition, True, start_time, True) + + # Test to check policy of not stopping charging when DisablePowerDown is set + def test_disable_power_down(self, mocker): + POWER_DRAW = 0 # To stop shutting down for other reasons + TEST_TIME = 100 + self.params.put_bool("DisablePowerDown", True) + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh + ignition = False + for i in range(TEST_TIME): + pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition) + if i % 10 == 0: + assert not pm.should_shutdown(ignition, True, ssb, False) + assert not pm.should_shutdown(ignition, True, ssb, False) + + # Test to check policy of not stopping charging when ignition + def test_ignition(self, mocker): + POWER_DRAW = 0 # To stop shutting down for other reasons + TEST_TIME = 100 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh + ignition = True + for i in range(TEST_TIME): + pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition) + if i % 10 == 0: + assert not pm.should_shutdown(ignition, True, ssb, False) + assert not pm.should_shutdown(ignition, True, ssb, False) + + # Test to check policy of not stopping charging when harness is not connected + def test_harness_connection(self, mocker): + POWER_DRAW = 0 # To stop shutting down for other reasons + TEST_TIME = 100 + pm_patch(mocker, "HARDWARE.get_current_power_draw", POWER_DRAW) + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = CAR_BATTERY_CAPACITY_uWh + + ignition = False + for i in range(TEST_TIME): + pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition) + if i % 10 == 0: + assert not pm.should_shutdown(ignition, False, ssb, False) + assert not pm.should_shutdown(ignition, False, ssb, False) + + def test_delay_shutdown_time(self): + pm = PowerMonitoring() + pm.car_battery_capacity_uWh = 0 + ignition = False + in_car = True + offroad_timestamp = ssb + started_seen = True + pm.calculate(VOLTAGE_BELOW_PAUSE_CHARGING, ignition) + + while ssb < offroad_timestamp + DELAY_SHUTDOWN_TIME_S: + assert not pm.should_shutdown(ignition, in_car, + offroad_timestamp, + started_seen), \ + f"Should not shutdown before {DELAY_SHUTDOWN_TIME_S} seconds offroad time" + assert pm.should_shutdown(ignition, in_car, + offroad_timestamp, + started_seen), \ + f"Should shutdown after {DELAY_SHUTDOWN_TIME_S} seconds offroad time" diff --git a/system/hardware/tici/__init__.py b/system/hardware/tici/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/hardware/tici/agnos.json b/system/hardware/tici/agnos.json new file mode 100644 index 0000000000..d93963cf2c --- /dev/null +++ b/system/hardware/tici/agnos.json @@ -0,0 +1,84 @@ +[ + { + "name": "xbl", + "url": "https://commadist.azureedge.net/agnosupdate/xbl-effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b.img.xz", + "hash": "effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b", + "hash_raw": "effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b", + "size": 3282256, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "ed61a650bea0c56652dd0fc68465d8fc722a4e6489dc8f257630c42c6adcdc89" + }, + { + "name": "xbl_config", + "url": "https://commadist.azureedge.net/agnosupdate/xbl_config-63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c.img.xz", + "hash": "63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c", + "hash_raw": "63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c", + "size": 98124, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "b12801ffaa81e58e3cef914488d3b447e35483ba549b28c6cd9deb4814c3265f" + }, + { + "name": "abl", + "url": "https://commadist.azureedge.net/agnosupdate/abl-556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee.img.xz", + "hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", + "hash_raw": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", + "size": 274432, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee" + }, + { + "name": "aop", + "url": "https://commadist.azureedge.net/agnosupdate/aop-21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9.img.xz", + "hash": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9", + "hash_raw": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9", + "size": 184364, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "c1be2f4aac5b3af49b904b027faec418d05efd7bd5144eb4fdfcba602bcf2180" + }, + { + "name": "devcfg", + "url": "https://commadist.azureedge.net/agnosupdate/devcfg-d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620.img.xz", + "hash": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620", + "hash_raw": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620", + "size": 40336, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "17b229668b20305ff8fa3cd5f94716a3aaa1e5bf9d1c24117eff7f2f81ae719f" + }, + { + "name": "boot", + "url": "https://commadist.azureedge.net/agnosupdate/boot-b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb.img.xz", + "hash": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "hash_raw": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "size": 17442816, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "8ed6c2796be5c5b29d64e6413b8e878d5bd1a3981d15216d2b5e84140cc4ea2a" + }, + { + "name": "system", + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img.xz", + "hash": "325414e5c9f7516b2bf0fedb6abe6682f717897a6d84ab70d5afe91a59f244e9", + "hash_raw": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "size": 4718592000, + "sparse": true, + "full_check": false, + "has_ab": true, + "ondevice_hash": "79f4f6d0b5b4a416f0f31261b430943a78e37c26d0e226e0ef412fe0eae3c727", + "alt": { + "hash": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img", + "size": 4718592000 + } + } +] \ No newline at end of file diff --git a/system/hardware/tici/agnos.py b/system/hardware/tici/agnos.py new file mode 100755 index 0000000000..f5261953d5 --- /dev/null +++ b/system/hardware/tici/agnos.py @@ -0,0 +1,337 @@ +#!/usr/bin/env python3 +import hashlib +import json +import lzma +import os +import struct +import subprocess +import time +from collections.abc import Generator + +import requests + +import openpilot.system.updated.casync.casync as casync + +SPARSE_CHUNK_FMT = struct.Struct('H2xI4x') +CAIBX_URL = "https://commadist.azureedge.net/agnosupdate/" + +AGNOS_MANIFEST_FILE = "system/hardware/tici/agnos.json" + + +class StreamingDecompressor: + def __init__(self, url: str) -> None: + self.buf = b"" + + self.req = requests.get(url, stream=True, headers={'Accept-Encoding': None}, timeout=60) + self.it = self.req.iter_content(chunk_size=1024 * 1024) + self.decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_AUTO) + self.eof = False + self.sha256 = hashlib.sha256() + + def read(self, length: int) -> bytes: + while len(self.buf) < length and not self.eof: + if self.decompressor.needs_input: + self.req.raise_for_status() + + try: + compressed = next(self.it) + except StopIteration: + self.eof = True + break + else: + compressed = b'' + + self.buf += self.decompressor.decompress(compressed, max_length=length) + + if self.decompressor.eof: + self.eof = True + break + + result = self.buf[:length] + self.buf = self.buf[length:] + + self.sha256.update(result) + return result + + +def unsparsify(f: StreamingDecompressor) -> Generator[bytes, None, None]: + # https://source.android.com/devices/bootloader/images#sparse-format + magic = struct.unpack("I", f.read(4))[0] + assert(magic == 0xed26ff3a) + + # Version + major = struct.unpack("H", f.read(2))[0] + minor = struct.unpack("H", f.read(2))[0] + assert(major == 1 and minor == 0) + + f.read(2) # file header size + f.read(2) # chunk header size + + block_sz = struct.unpack("I", f.read(4))[0] + f.read(4) # total blocks + num_chunks = struct.unpack("I", f.read(4))[0] + f.read(4) # crc checksum + + for _ in range(num_chunks): + chunk_type, out_blocks = SPARSE_CHUNK_FMT.unpack(f.read(12)) + + if chunk_type == 0xcac1: # Raw + # TODO: yield in smaller chunks. Yielding only block_sz is too slow. Largest observed data chunk is 252 MB. + yield f.read(out_blocks * block_sz) + elif chunk_type == 0xcac2: # Fill + filler = f.read(4) * (block_sz // 4) + for _ in range(out_blocks): + yield filler + elif chunk_type == 0xcac3: # Don't care + yield b"" + else: + raise Exception("Unhandled sparse chunk type") + + +# noop wrapper with same API as unsparsify() for non sparse images +def noop(f: StreamingDecompressor) -> Generator[bytes, None, None]: + while len(chunk := f.read(1024 * 1024)) > 0: + yield chunk + + +def get_target_slot_number() -> int: + current_slot = subprocess.check_output(["abctl", "--boot_slot"], encoding='utf-8').strip() + return 1 if current_slot == "_a" else 0 + + +def slot_number_to_suffix(slot_number: int) -> str: + assert slot_number in (0, 1) + return '_a' if slot_number == 0 else '_b' + + +def get_partition_path(target_slot_number: int, partition: dict) -> str: + path = f"/dev/disk/by-partlabel/{partition['name']}" + + if partition.get('has_ab', True): + path += slot_number_to_suffix(target_slot_number) + + return path + + +def get_raw_hash(path: str, partition_size: int) -> str: + raw_hash = hashlib.sha256() + pos, chunk_size = 0, 1024 * 1024 + + with open(path, 'rb+') as out: + while pos < partition_size: + n = min(chunk_size, partition_size - pos) + raw_hash.update(out.read(n)) + pos += n + + return raw_hash.hexdigest().lower() + + +def verify_partition(target_slot_number: int, partition: dict[str, str | int], force_full_check: bool = False) -> bool: + full_check = partition['full_check'] or force_full_check + path = get_partition_path(target_slot_number, partition) + + if not isinstance(partition['size'], int): + return False + + partition_size: int = partition['size'] + + if not isinstance(partition['hash_raw'], str): + return False + + partition_hash: str = partition['hash_raw'] + + if full_check: + return get_raw_hash(path, partition_size) == partition_hash.lower() + else: + with open(path, 'rb+') as out: + out.seek(partition_size) + return out.read(64) == partition_hash.lower().encode() + + +def clear_partition_hash(target_slot_number: int, partition: dict) -> None: + path = get_partition_path(target_slot_number, partition) + with open(path, 'wb+') as out: + partition_size = partition['size'] + + out.seek(partition_size) + out.write(b"\x00" * 64) + os.sync() + + +def extract_compressed_image(target_slot_number: int, partition: dict, cloudlog): + path = get_partition_path(target_slot_number, partition) + downloader = StreamingDecompressor(partition['url']) + + with open(path, 'wb+') as out: + # Flash partition + last_p = 0 + raw_hash = hashlib.sha256() + f = unsparsify if partition['sparse'] else noop + for chunk in f(downloader): + raw_hash.update(chunk) + out.write(chunk) + p = int(out.tell() / partition['size'] * 100) + if p != last_p: + last_p = p + print(f"Installing {partition['name']}: {p}", flush=True) + + if raw_hash.hexdigest().lower() != partition['hash_raw'].lower(): + raise Exception(f"Raw hash mismatch '{raw_hash.hexdigest().lower()}'") + + if downloader.sha256.hexdigest().lower() != partition['hash'].lower(): + raise Exception("Uncompressed hash mismatch") + + if out.tell() != partition['size']: + raise Exception("Uncompressed size mismatch") + + os.sync() + + +def extract_casync_image(target_slot_number: int, partition: dict, cloudlog): + path = get_partition_path(target_slot_number, partition) + seed_path = path[:-1] + ('b' if path[-1] == 'a' else 'a') + + target = casync.parse_caibx(partition['casync_caibx']) + + sources: list[tuple[str, casync.ChunkReader, casync.ChunkDict]] = [] + + # First source is the current partition. + try: + raw_hash = get_raw_hash(seed_path, partition['size']) + caibx_url = f"{CAIBX_URL}{partition['name']}-{raw_hash}.caibx" + + try: + cloudlog.info(f"casync fetching {caibx_url}") + sources += [('seed', casync.FileChunkReader(seed_path), casync.build_chunk_dict(casync.parse_caibx(caibx_url)))] + except requests.RequestException: + cloudlog.error(f"casync failed to load {caibx_url}") + except Exception: + cloudlog.exception("casync failed to hash seed partition") + + # Second source is the target partition, this allows for resuming + sources += [('target', casync.FileChunkReader(path), casync.build_chunk_dict(target))] + + # Finally we add the remote source to download any missing chunks + sources += [('remote', casync.RemoteChunkReader(partition['casync_store']), casync.build_chunk_dict(target))] + + last_p = 0 + + def progress(cur): + nonlocal last_p + p = int(cur / partition['size'] * 100) + if p != last_p: + last_p = p + print(f"Installing {partition['name']}: {p}", flush=True) + + stats = casync.extract(target, sources, path, progress) + cloudlog.error(f'casync done {json.dumps(stats)}') + + os.sync() + if not verify_partition(target_slot_number, partition, force_full_check=True): + raise Exception(f"Raw hash mismatch '{partition['hash_raw'].lower()}'") + + +def flash_partition(target_slot_number: int, partition: dict, cloudlog, standalone=False): + cloudlog.info(f"Downloading and writing {partition['name']}") + + if verify_partition(target_slot_number, partition): + cloudlog.info(f"Already flashed {partition['name']}") + return + + # Clear hash before flashing in case we get interrupted + full_check = partition['full_check'] + if not full_check: + clear_partition_hash(target_slot_number, partition) + + path = get_partition_path(target_slot_number, partition) + + if ('casync_caibx' in partition) and not standalone: + extract_casync_image(target_slot_number, partition, cloudlog) + else: + extract_compressed_image(target_slot_number, partition, cloudlog) + + # Write hash after successful flash + if not full_check: + with open(path, 'wb+') as out: + out.seek(partition['size']) + out.write(partition['hash_raw'].lower().encode()) + + +def swap(manifest_path: str, target_slot_number: int, cloudlog) -> None: + update = json.load(open(manifest_path)) + for partition in update: + if not partition.get('full_check', False): + clear_partition_hash(target_slot_number, partition) + + while True: + out = subprocess.check_output(f"abctl --set_active {target_slot_number}", shell=True, stderr=subprocess.STDOUT, encoding='utf8') + if ("No such file or directory" not in out) and ("lun as boot lun" in out): + cloudlog.info(f"Swap successful {out}") + break + else: + cloudlog.error(f"Swap failed {out}") + + +def flash_agnos_update(manifest_path: str, target_slot_number: int, cloudlog, standalone=False) -> None: + update = json.load(open(manifest_path)) + + cloudlog.info(f"Target slot {target_slot_number}") + + # set target slot as unbootable + os.system(f"abctl --set_unbootable {target_slot_number}") + + for partition in update: + success = False + + for retries in range(10): + try: + flash_partition(target_slot_number, partition, cloudlog, standalone) + success = True + break + + except requests.exceptions.RequestException: + cloudlog.exception("Failed") + cloudlog.info(f"Failed to download {partition['name']}, retrying ({retries})") + time.sleep(10) + + if not success: + cloudlog.info(f"Failed to flash {partition['name']}, aborting") + raise Exception("Maximum retries exceeded") + + cloudlog.info(f"AGNOS ready on slot {target_slot_number}") + + +def verify_agnos_update(manifest_path: str, target_slot_number: int) -> bool: + update = json.load(open(manifest_path)) + return all(verify_partition(target_slot_number, partition) for partition in update) + + +if __name__ == "__main__": + import argparse + import logging + + parser = argparse.ArgumentParser(description="Flash and verify AGNOS update", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + + parser.add_argument("--verify", action="store_true", help="Verify and perform swap if update ready") + parser.add_argument("--swap", action="store_true", help="Verify and perform swap, downloads if necessary") + parser.add_argument("manifest", help="Manifest json") + args = parser.parse_args() + + logging.basicConfig(level=logging.INFO) + + target_slot_number = get_target_slot_number() + if args.verify: + if verify_agnos_update(args.manifest, target_slot_number): + swap(args.manifest, target_slot_number, logging) + exit(0) + exit(1) + elif args.swap: + while not verify_agnos_update(args.manifest, target_slot_number): + logging.error("Verification failed. Flashing AGNOS") + flash_agnos_update(args.manifest, target_slot_number, logging, standalone=True) + + logging.warning(f"Verification succeeded. Swapping to slot {target_slot_number}") + swap(args.manifest, target_slot_number, logging) + else: + flash_agnos_update(args.manifest, target_slot_number, logging, standalone=True) diff --git a/system/hardware/tici/all-partitions.json b/system/hardware/tici/all-partitions.json new file mode 100644 index 0000000000..ebffc01dfd --- /dev/null +++ b/system/hardware/tici/all-partitions.json @@ -0,0 +1,400 @@ +[ + { + "name": "gpt_main_0", + "url": "https://commadist.azureedge.net/agnosupdate/gpt_main_0-8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd.img.xz", + "hash": "8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd", + "hash_raw": "8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd", + "size": 24576, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "8928a31fd9ee20f8703649f89833eba9b55e84b6415e67799c777b163c95a0bd", + "gpt": { + "lun": 0, + "start_sector": 0, + "num_sectors": 6 + } + }, + { + "name": "gpt_main_1", + "url": "https://commadist.azureedge.net/agnosupdate/gpt_main_1-fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6.img.xz", + "hash": "fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6", + "hash_raw": "fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6", + "size": 24576, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "fe8ef7653db588d7420a625920ca06927dfcb0ed8aff3e3a1c74a52a24398ba6", + "gpt": { + "lun": 1, + "start_sector": 0, + "num_sectors": 6 + } + }, + { + "name": "gpt_main_2", + "url": "https://commadist.azureedge.net/agnosupdate/gpt_main_2-5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21.img.xz", + "hash": "5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21", + "hash_raw": "5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21", + "size": 24576, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "5ccfc7240c8cbfa2f1a018a2e376cf274a6baf858c9bfe71951d8e28cab53c21", + "gpt": { + "lun": 2, + "start_sector": 0, + "num_sectors": 6 + } + }, + { + "name": "gpt_main_3", + "url": "https://commadist.azureedge.net/agnosupdate/gpt_main_3-c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159.img.xz", + "hash": "c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159", + "hash_raw": "c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159", + "size": 24576, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "c707979fa21e89519328f4f30c2b21c9c453401ca8303f914c1873d410a95159", + "gpt": { + "lun": 3, + "start_sector": 0, + "num_sectors": 6 + } + }, + { + "name": "gpt_main_4", + "url": "https://commadist.azureedge.net/agnosupdate/gpt_main_4-e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e.img.xz", + "hash": "e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e", + "hash_raw": "e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e", + "size": 24576, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "e9405dcd785dbe79412184e1894a9c51ab7deb33bb612166c4c42a3d2bf42a0e", + "gpt": { + "lun": 4, + "start_sector": 0, + "num_sectors": 6 + } + }, + { + "name": "gpt_main_5", + "url": "https://commadist.azureedge.net/agnosupdate/gpt_main_5-21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3.img.xz", + "hash": "21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3", + "hash_raw": "21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3", + "size": 24576, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "21ae965f05b2fa8d02e04f1eb74718f9779864f6eacdeb859757d6435e8ccce3", + "gpt": { + "lun": 5, + "start_sector": 0, + "num_sectors": 6 + } + }, + { + "name": "persist", + "url": "https://commadist.azureedge.net/agnosupdate/persist-d6af4ec18df180c7417353b52a9e05e43a6480b29425f087874136436cefe786.img.xz", + "hash": "d6af4ec18df180c7417353b52a9e05e43a6480b29425f087874136436cefe786", + "hash_raw": "d6af4ec18df180c7417353b52a9e05e43a6480b29425f087874136436cefe786", + "size": 4096, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "d6af4ec18df180c7417353b52a9e05e43a6480b29425f087874136436cefe786" + }, + { + "name": "systemrw", + "url": "https://commadist.azureedge.net/agnosupdate/systemrw-8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e.img.xz", + "hash": "8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e", + "hash_raw": "8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e", + "size": 16777216, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "8ce150ca38ef64a0885fc2fe816e5b63bae8adb4df5d809c5b318e6996366c7e" + }, + { + "name": "cache", + "url": "https://commadist.azureedge.net/agnosupdate/cache-ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4.img.xz", + "hash": "ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4", + "hash_raw": "ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4", + "size": 134217728, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "ebfbaaa2f96dc4e5fea4f126364e5bf5b3b44c12cbc753b62fdd8baab82f70b4" + }, + { + "name": "xbl", + "url": "https://commadist.azureedge.net/agnosupdate/xbl-effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b.img.xz", + "hash": "effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b", + "hash_raw": "effa23294138e2297b85a5b482a885184c437b5ab25d74f2a62d4fce4e68f63b", + "size": 3282256, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "ed61a650bea0c56652dd0fc68465d8fc722a4e6489dc8f257630c42c6adcdc89" + }, + { + "name": "xbl_config", + "url": "https://commadist.azureedge.net/agnosupdate/xbl_config-63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c.img.xz", + "hash": "63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c", + "hash_raw": "63d019efed684601f145ef37628e62c8da73f5053a8e51d7de09e72b8b11f97c", + "size": 98124, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "b12801ffaa81e58e3cef914488d3b447e35483ba549b28c6cd9deb4814c3265f" + }, + { + "name": "abl", + "url": "https://commadist.azureedge.net/agnosupdate/abl-556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee.img.xz", + "hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", + "hash_raw": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee", + "size": 274432, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "556bbb4ed1c671402b217bd2f3c07edce4f88b0bbd64e92241b82e396aa9ebee" + }, + { + "name": "aop", + "url": "https://commadist.azureedge.net/agnosupdate/aop-21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9.img.xz", + "hash": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9", + "hash_raw": "21370172e590bd4ea907a558bcd6df20dc7a6c7d38b8e62fdde18f4a512ba9e9", + "size": 184364, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "c1be2f4aac5b3af49b904b027faec418d05efd7bd5144eb4fdfcba602bcf2180" + }, + { + "name": "bluetooth", + "url": "https://commadist.azureedge.net/agnosupdate/bluetooth-9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533.img.xz", + "hash": "9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533", + "hash_raw": "9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533", + "size": 1048576, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "9bb766d2d2ce0cc4491664b3010fe1ef62f8ffc1e362d55f78e48c4141f75533" + }, + { + "name": "cmnlib64", + "url": "https://commadist.azureedge.net/agnosupdate/cmnlib64-1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3.img.xz", + "hash": "1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3", + "hash_raw": "1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3", + "size": 524288, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "1a876bd151bb9635f18719c4a17f953079de6e11d3eaec800968fc75669e0dc3" + }, + { + "name": "cmnlib", + "url": "https://commadist.azureedge.net/agnosupdate/cmnlib-63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82.img.xz", + "hash": "63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82", + "hash_raw": "63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82", + "size": 524288, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "63df823e8a5fae01d66cb2b8c20f0d2ddb5c5f2425e5d0992a64676273ba1c82" + }, + { + "name": "devcfg", + "url": "https://commadist.azureedge.net/agnosupdate/devcfg-d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620.img.xz", + "hash": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620", + "hash_raw": "d7d7e52963bbedbbf8a7e66847579ca106a0a729ce2cf60f4b8d8ea4b535d620", + "size": 40336, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "17b229668b20305ff8fa3cd5f94716a3aaa1e5bf9d1c24117eff7f2f81ae719f" + }, + { + "name": "devinfo", + "url": "https://commadist.azureedge.net/agnosupdate/devinfo-143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3.img.xz", + "hash": "143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3", + "hash_raw": "143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3", + "size": 4096, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "143869c499a7e878fbeab756e9c53074195770cc41d6d0d10e45c043141389a3" + }, + { + "name": "dsp", + "url": "https://commadist.azureedge.net/agnosupdate/dsp-4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248.img.xz", + "hash": "4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248", + "hash_raw": "4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248", + "size": 33554432, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "4b15fbd2f45581f1553f33f01649e450b24aa19d5deff2ac7dcb16a534d9c248" + }, + { + "name": "hyp", + "url": "https://commadist.azureedge.net/agnosupdate/hyp-ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927.img.xz", + "hash": "ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927", + "hash_raw": "ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927", + "size": 524288, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "ff5ece6a4e3d2b4d898c77ffe193fc8bbc8acebe78263996ecf52373d8088927" + }, + { + "name": "keymaster", + "url": "https://commadist.azureedge.net/agnosupdate/keymaster-5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04.img.xz", + "hash": "5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04", + "hash_raw": "5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04", + "size": 524288, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "5c968c76f29b9a4d66fbe57e639bac6b7a2c83b1758e25abbaf5d276b8a6af04" + }, + { + "name": "limits", + "url": "https://commadist.azureedge.net/agnosupdate/limits-94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1.img.xz", + "hash": "94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1", + "hash_raw": "94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1", + "size": 4096, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "94951a0f7aa55fb6cb975535ce4ebbfe6d695f04cb5424677b01c10dfa2e94e1" + }, + { + "name": "logfs", + "url": "https://commadist.azureedge.net/agnosupdate/logfs-b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220.img.xz", + "hash": "b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220", + "hash_raw": "b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220", + "size": 8388608, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "b8b5ac87f3d954404fc7ecbdd9ee3b5b0cf5691e5006e6ec55db4c899ff61220" + }, + { + "name": "modem", + "url": "https://commadist.azureedge.net/agnosupdate/modem-a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994.img.xz", + "hash": "a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994", + "hash_raw": "a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994", + "size": 125829120, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "a3d014f0896d77a2df7e5a80a70f43a51a047b9d03cfc675b6f0e31a6ecc4994" + }, + { + "name": "qupfw", + "url": "https://commadist.azureedge.net/agnosupdate/qupfw-64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a.img.xz", + "hash": "64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a", + "hash_raw": "64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a", + "size": 65536, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "64cc7c29d5d69b04267452b8b4ddba9f4809e68f476fc162ca283f58537afe4a" + }, + { + "name": "splash", + "url": "https://commadist.azureedge.net/agnosupdate/splash-5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08.img.xz", + "hash": "5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08", + "hash_raw": "5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08", + "size": 34226176, + "sparse": false, + "full_check": true, + "has_ab": false, + "ondevice_hash": "5c61260048f22ede6e6343fabb27f6ff73f9271f4751a01aaf7abf097afc1f08" + }, + { + "name": "storsec", + "url": "https://commadist.azureedge.net/agnosupdate/storsec-4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce.img.xz", + "hash": "4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce", + "hash_raw": "4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce", + "size": 131072, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "4494d86f68b125fbf2c004c824b1c6dbe71e61a65d2a1cc7db13c553edcb3fce" + }, + { + "name": "tz", + "url": "https://commadist.azureedge.net/agnosupdate/tz-e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16.img.xz", + "hash": "e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16", + "hash_raw": "e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16", + "size": 2097152, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "e9443bf187641661bfa6c96702b9ab0156e72fb7482500f8799ba9ee2503cb16" + }, + { + "name": "boot", + "url": "https://commadist.azureedge.net/agnosupdate/boot-b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb.img.xz", + "hash": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "hash_raw": "b96882012ab6cddda04f440009c798a6cff65977f984b12072e89afa592d86cb", + "size": 17442816, + "sparse": false, + "full_check": true, + "has_ab": true, + "ondevice_hash": "8ed6c2796be5c5b29d64e6413b8e878d5bd1a3981d15216d2b5e84140cc4ea2a" + }, + { + "name": "system", + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img.xz", + "hash": "325414e5c9f7516b2bf0fedb6abe6682f717897a6d84ab70d5afe91a59f244e9", + "hash_raw": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "size": 4718592000, + "sparse": true, + "full_check": false, + "has_ab": true, + "ondevice_hash": "79f4f6d0b5b4a416f0f31261b430943a78e37c26d0e226e0ef412fe0eae3c727", + "alt": { + "hash": "2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc", + "url": "https://commadist.azureedge.net/agnosupdate/system-2b1bb223bf2100376ad5d543bfa4a483f33327b3478ec20ab36048388472c4bc.img", + "size": 4718592000 + } + }, + { + "name": "userdata_90", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_90-b3112984d2a8534a83d2ce43d35efdd10c7d163d9699f611f0f72ad9e9cb5af9.img.xz", + "hash": "bea163e6fb6ac6224c7f32619affb5afb834cd859971b0cab6d8297dd0098f0a", + "hash_raw": "b3112984d2a8534a83d2ce43d35efdd10c7d163d9699f611f0f72ad9e9cb5af9", + "size": 96636764160, + "sparse": true, + "full_check": true, + "has_ab": false, + "ondevice_hash": "f4841c6ae3207197886e5efbd50f44cc24822680d7b785fa2d2743c657f23287" + }, + { + "name": "userdata_89", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_89-3e63f670e4270474cec96f4da9250ee4e87e3106b0b043b7e82371e1c761e167.img.xz", + "hash": "b5458a29dd7d4a4c9b7ad77b8baa5f804142ac78d97c6668839bf2a650e32518", + "hash_raw": "3e63f670e4270474cec96f4da9250ee4e87e3106b0b043b7e82371e1c761e167", + "size": 95563022336, + "sparse": true, + "full_check": true, + "has_ab": false, + "ondevice_hash": "1dc10c542d3b019258fc08dc7dfdb49d9abad065e46d030b89bc1a2e0197f526" + }, + { + "name": "userdata_30", + "url": "https://commadist.azureedge.net/agnosupdate/userdata_30-1d3885d4370974e55f0c6f567fd0344fc5ee10db067aa5810fbaf402eadb032c.img.xz", + "hash": "687d178cfc91be5d7e8aa1333405b610fdce01775b8333bd0985b81642b94eea", + "hash_raw": "1d3885d4370974e55f0c6f567fd0344fc5ee10db067aa5810fbaf402eadb032c", + "size": 32212254720, + "sparse": true, + "full_check": true, + "has_ab": false, + "ondevice_hash": "9ddbd1dae6ee7dc919f018364cf2f29dad138c9203c5a49aea0cbb9bf2e137e5" + } +] \ No newline at end of file diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py new file mode 100755 index 0000000000..bfdcc6ddaf --- /dev/null +++ b/system/hardware/tici/amplifier.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +import time +from smbus2 import SMBus +from collections import namedtuple + +# https://datasheets.maximintegrated.com/en/ds/MAX98089.pdf + +AmpConfig = namedtuple('AmpConfig', ['name', 'value', 'register', 'offset', 'mask']) +EQParams = namedtuple('EQParams', ['K', 'k1', 'k2', 'c1', 'c2']) + +def configs_from_eq_params(base, eq_params): + return [ + AmpConfig("K (high)", (eq_params.K >> 8), base, 0, 0xFF), + AmpConfig("K (low)", (eq_params.K & 0xFF), base + 1, 0, 0xFF), + AmpConfig("k1 (high)", (eq_params.k1 >> 8), base + 2, 0, 0xFF), + AmpConfig("k1 (low)", (eq_params.k1 & 0xFF), base + 3, 0, 0xFF), + AmpConfig("k2 (high)", (eq_params.k2 >> 8), base + 4, 0, 0xFF), + AmpConfig("k2 (low)", (eq_params.k2 & 0xFF), base + 5, 0, 0xFF), + AmpConfig("c1 (high)", (eq_params.c1 >> 8), base + 6, 0, 0xFF), + AmpConfig("c1 (low)", (eq_params.c1 & 0xFF), base + 7, 0, 0xFF), + AmpConfig("c2 (high)", (eq_params.c2 >> 8), base + 8, 0, 0xFF), + AmpConfig("c2 (low)", (eq_params.c2 & 0xFF), base + 9, 0, 0xFF), + ] + +BASE_CONFIG = [ + AmpConfig("MCLK prescaler", 0b01, 0x10, 4, 0b00110000), + AmpConfig("PM: enable speakers", 0b11, 0x4D, 4, 0b00110000), + AmpConfig("PM: enable DACs", 0b11, 0x4D, 0, 0b00000011), + AmpConfig("Enable PLL1", 0b1, 0x12, 7, 0b10000000), + AmpConfig("Enable PLL2", 0b1, 0x1A, 7, 0b10000000), + AmpConfig("DAI1: I2S mode", 0b00100, 0x14, 2, 0b01111100), + AmpConfig("DAI2: I2S mode", 0b00100, 0x1C, 2, 0b01111100), + AmpConfig("DAI1 Passband filtering: music mode", 0b1, 0x18, 7, 0b10000000), + AmpConfig("DAI1 voice mode gain (DV1G)", 0b00, 0x2F, 4, 0b00110000), + AmpConfig("DAI1 attenuation (DV1)", 0x0, 0x2F, 0, 0b00001111), + AmpConfig("DAI2 attenuation (DV2)", 0x0, 0x31, 0, 0b00001111), + AmpConfig("DAI2: DC blocking", 0b1, 0x20, 0, 0b00000001), + AmpConfig("DAI2: High sample rate", 0b0, 0x20, 3, 0b00001000), + AmpConfig("ALC enable", 0b1, 0x43, 7, 0b10000000), + AmpConfig("ALC/excursion limiter release time", 0b101, 0x43, 4, 0b01110000), + AmpConfig("ALC multiband enable", 0b1, 0x43, 3, 0b00001000), + AmpConfig("DAI1 EQ enable", 0b0, 0x49, 0, 0b00000001), + AmpConfig("DAI2 EQ clip detection disabled", 0b1, 0x32, 4, 0b00010000), + AmpConfig("DAI2 EQ attenuation", 0x5, 0x32, 0, 0b00001111), + AmpConfig("Excursion limiter upper corner freq", 0b100, 0x41, 4, 0b01110000), + AmpConfig("Excursion limiter lower corner freq", 0b00, 0x41, 0, 0b00000011), + AmpConfig("Excursion limiter threshold", 0b000, 0x42, 0, 0b00001111), + AmpConfig("Distortion limit (THDCLP)", 0x6, 0x46, 4, 0b11110000), + AmpConfig("Distortion limiter release time constant", 0b0, 0x46, 0, 0b00000001), + AmpConfig("Right DAC input mixer: DAI1 left", 0b0, 0x22, 3, 0b00001000), + AmpConfig("Right DAC input mixer: DAI1 right", 0b0, 0x22, 2, 0b00000100), + AmpConfig("Right DAC input mixer: DAI2 left", 0b1, 0x22, 1, 0b00000010), + AmpConfig("Right DAC input mixer: DAI2 right", 0b0, 0x22, 0, 0b00000001), + AmpConfig("DAI1 audio port selector", 0b10, 0x16, 6, 0b11000000), + AmpConfig("DAI2 audio port selector", 0b01, 0x1E, 6, 0b11000000), + AmpConfig("Enable left digital microphone", 0b1, 0x48, 5, 0b00100000), + AmpConfig("Enable right digital microphone", 0b1, 0x48, 4, 0b00010000), + AmpConfig("Enhanced volume smoothing disabled", 0b0, 0x49, 7, 0b10000000), + AmpConfig("Volume adjustment smoothing disabled", 0b0, 0x49, 6, 0b01000000), + AmpConfig("Zero-crossing detection disabled", 0b0, 0x49, 5, 0b00100000), +] + +CONFIGS = { + "tizi": [ + AmpConfig("Left speaker output from left DAC", 0b1, 0x2B, 0, 0b11111111), + AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), + AmpConfig("Left Speaker Mixer Gain", 0b00, 0x2D, 0, 0b00000011), + AmpConfig("Right Speaker Mixer Gain", 0b00, 0x2D, 2, 0b00001100), + AmpConfig("Left speaker output volume", 0x17, 0x3D, 0, 0b00011111), + AmpConfig("Right speaker output volume", 0x17, 0x3E, 0, 0b00011111), + + AmpConfig("DAI2 EQ enable", 0b0, 0x49, 1, 0b00000010), + AmpConfig("DAI2: DC blocking", 0b0, 0x20, 0, 0b00000001), + AmpConfig("ALC enable", 0b0, 0x43, 7, 0b10000000), + AmpConfig("DAI2 EQ attenuation", 0x2, 0x32, 0, 0b00001111), + AmpConfig("Excursion limiter upper corner freq", 0b001, 0x41, 4, 0b01110000), + AmpConfig("Excursion limiter threshold", 0b100, 0x42, 0, 0b00001111), + AmpConfig("Distortion limit (THDCLP)", 0x0, 0x46, 4, 0b11110000), + AmpConfig("Distortion limiter release time constant", 0b1, 0x46, 0, 0b00000001), + AmpConfig("Left DAC input mixer: DAI1 left", 0b0, 0x22, 7, 0b10000000), + AmpConfig("Left DAC input mixer: DAI1 right", 0b0, 0x22, 6, 0b01000000), + AmpConfig("Left DAC input mixer: DAI2 left", 0b1, 0x22, 5, 0b00100000), + AmpConfig("Left DAC input mixer: DAI2 right", 0b0, 0x22, 4, 0b00010000), + AmpConfig("Right DAC input mixer: DAI2 left", 0b0, 0x22, 1, 0b00000010), + AmpConfig("Right DAC input mixer: DAI2 right", 0b1, 0x22, 0, 0b00000001), + AmpConfig("Volume adjustment smoothing disabled", 0b1, 0x49, 6, 0b01000000), + ], +} + +class Amplifier: + AMP_I2C_BUS = 0 + AMP_ADDRESS = 0x10 + + def __init__(self, debug=False): + self.debug = debug + + def _get_shutdown_config(self, amp_disabled: bool) -> AmpConfig: + return AmpConfig("Global shutdown", 0b0 if amp_disabled else 0b1, 0x51, 7, 0b10000000) + + def _set_configs(self, configs: list[AmpConfig]) -> None: + with SMBus(self.AMP_I2C_BUS) as bus: + for config in configs: + if self.debug: + print(f"Setting \"{config.name}\" to {config.value}:") + + old_value = bus.read_byte_data(self.AMP_ADDRESS, config.register, force=True) + new_value = (old_value & (~config.mask)) | ((config.value << config.offset) & config.mask) + bus.write_byte_data(self.AMP_ADDRESS, config.register, new_value, force=True) + + if self.debug: + print(f" Changed {hex(config.register)}: {hex(old_value)} -> {hex(new_value)}") + + def set_configs(self, configs: list[AmpConfig]) -> bool: + # retry in case panda is using the amp + tries = 15 + backoff = 0. + for i in range(tries): + try: + self._set_configs(configs) + return True + except OSError: + backoff += 0.1 + time.sleep(backoff) + print(f"Failed to set amp config, {tries - i - 1} retries left") + return False + + def set_global_shutdown(self, amp_disabled: bool) -> bool: + return self.set_configs([self._get_shutdown_config(amp_disabled), ]) + + def initialize_configuration(self, model: str) -> bool: + cfgs = [ + self._get_shutdown_config(True), + *BASE_CONFIG, + *CONFIGS[model], + self._get_shutdown_config(False), + ] + return self.set_configs(cfgs) + + +if __name__ == "__main__": + with open("/sys/firmware/devicetree/base/model") as f: + model = f.read().strip('\x00') + model = model.split('comma ')[-1] + + amp = Amplifier() + amp.initialize_configuration(model) diff --git a/system/hardware/tici/esim.nmconnection b/system/hardware/tici/esim.nmconnection new file mode 100644 index 0000000000..74f6f8e82c --- /dev/null +++ b/system/hardware/tici/esim.nmconnection @@ -0,0 +1,30 @@ +[connection] +id=esim +uuid=fff6553c-3284-4707-a6b1-acc021caaafb +type=gsm +permissions= +autoconnect=true +autoconnect-retries=100 +autoconnect-priority=2 +metered=1 + +[gsm] +apn= +home-only=false +auto-config=true +sim-id= + +[ipv4] +route-metric=1000 +dns-priority=1000 +dns-search= +method=auto + +[ipv6] +ddr-gen-mode=stable-privacy +dns-search= +route-metric=1000 +dns-priority=1000 +method=auto + +[proxy] diff --git a/system/hardware/tici/esim.py b/system/hardware/tici/esim.py new file mode 100644 index 0000000000..391ba45531 --- /dev/null +++ b/system/hardware/tici/esim.py @@ -0,0 +1,135 @@ +import json +import os +import shutil +import subprocess +from typing import Literal + +from openpilot.system.hardware.base import LPABase, LPAError, LPAProfileNotFoundError, Profile + +class TiciLPA(LPABase): + def __init__(self, interface: Literal['qmi', 'at'] = 'qmi'): + self.env = os.environ.copy() + self.env['LPAC_APDU'] = interface + self.env['QMI_DEVICE'] = '/dev/cdc-wdm0' + self.env['AT_DEVICE'] = '/dev/ttyUSB2' + + self.timeout_sec = 45 + + if shutil.which('lpac') is None: + raise LPAError('lpac not found, must be installed!') + + def list_profiles(self) -> list[Profile]: + msgs = self._invoke('profile', 'list') + self._validate_successful(msgs) + return [Profile( + iccid=p['iccid'], + nickname=p['profileNickname'], + enabled=p['profileState'] == 'enabled', + provider=p['serviceProviderName'] + ) for p in msgs[-1]['payload']['data']] + + def get_active_profile(self) -> Profile | None: + return next((p for p in self.list_profiles() if p.enabled), None) + + def delete_profile(self, iccid: str) -> None: + self._validate_profile_exists(iccid) + latest = self.get_active_profile() + if latest is not None and latest.iccid == iccid: + raise LPAError('cannot delete active profile, switch to another profile first') + self._validate_successful(self._invoke('profile', 'delete', iccid)) + self._process_notifications() + + def download_profile(self, qr: str, nickname: str | None = None) -> None: + self._check_bootstrapped() + msgs = self._invoke('profile', 'download', '-a', qr) + self._validate_successful(msgs) + new_profile = next((m for m in msgs if m['payload']['message'] == 'es8p_meatadata_parse'), None) + if new_profile is None: + raise LPAError('no new profile found') + if nickname: + self.nickname_profile(new_profile['payload']['data']['iccid'], nickname) + self._process_notifications() + + def nickname_profile(self, iccid: str, nickname: str) -> None: + self._validate_profile_exists(iccid) + self._validate_successful(self._invoke('profile', 'nickname', iccid, nickname)) + + def switch_profile(self, iccid: str) -> None: + self._check_bootstrapped() + self._validate_profile_exists(iccid) + latest = self.get_active_profile() + if latest and latest.iccid == iccid: + return + self._validate_successful(self._invoke('profile', 'enable', iccid)) + self._process_notifications() + + def bootstrap(self) -> None: + """ + find all comma-provisioned profiles and delete them. they conflict with user-provisioned profiles + and must be deleted. + + **note**: this is a **very** destructive operation. you **must** purchase a new comma SIM in order + to use comma prime again. + """ + if self._is_bootstrapped(): + return + + for p in self.list_profiles(): + if self.is_comma_profile(p.iccid): + self._disable_profile(p.iccid) + self.delete_profile(p.iccid) + + def _disable_profile(self, iccid: str) -> None: + self._validate_successful(self._invoke('profile', 'disable', iccid)) + self._process_notifications() + + def _check_bootstrapped(self) -> None: + assert self._is_bootstrapped(), 'eUICC is not bootstrapped, please bootstrap before performing this operation' + + def _is_bootstrapped(self) -> bool: + """ check if any comma provisioned profiles are on the eUICC """ + return not any(self.is_comma_profile(iccid) for iccid in (p.iccid for p in self.list_profiles())) + + def _invoke(self, *cmd: str): + proc = subprocess.Popen(['sudo', '-E', 'lpac'] + list(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=self.env) + try: + out, err = proc.communicate(timeout=self.timeout_sec) + except subprocess.TimeoutExpired as e: + proc.kill() + raise LPAError(f"lpac {cmd} timed out after {self.timeout_sec} seconds") from e + + messages = [] + for line in out.decode().strip().splitlines(): + if line.startswith('{'): + message = json.loads(line) + + # lpac response format validations + assert 'type' in message, 'expected type in message' + assert message['type'] == 'lpa' or message['type'] == 'progress', 'expected lpa or progress message type' + assert 'payload' in message, 'expected payload in message' + assert 'code' in message['payload'], 'expected code in message payload' + assert 'data' in message['payload'], 'expected data in message payload' + + msg_ret_code = message['payload']['code'] + if msg_ret_code != 0: + raise LPAError(f"lpac {' '.join(cmd)} failed with code {msg_ret_code}: <{message['payload']['message']}> {message['payload']['data']}") + + messages.append(message) + + if len(messages) == 0: + raise LPAError(f"lpac {cmd} returned no messages") + + return messages + + def _process_notifications(self) -> None: + """ + Process notifications stored on the eUICC, typically to activate/deactivate the profile with the carrier. + """ + self._validate_successful(self._invoke('notification', 'process', '-a', '-r')) + + def _validate_profile_exists(self, iccid: str) -> None: + if not any(p.iccid == iccid for p in self.list_profiles()): + raise LPAProfileNotFoundError(f'profile {iccid} does not exist') + + def _validate_successful(self, msgs: list[dict]) -> None: + assert msgs[-1]['payload']['message'] == 'success', 'expected success notification' diff --git a/system/hardware/tici/hardware.h b/system/hardware/tici/hardware.h new file mode 100644 index 0000000000..ed8a7e7d17 --- /dev/null +++ b/system/hardware/tici/hardware.h @@ -0,0 +1,110 @@ +#pragma once + +#include +#include +#include +#include +#include +#include // for std::clamp + +#include "common/params.h" +#include "common/util.h" +#include "system/hardware/base.h" + +class HardwareTici : public HardwareNone { +public: + static bool TICI() { return true; } + static bool AGNOS() { return true; } + static std::string get_os_version() { + return "AGNOS " + util::read_file("/VERSION"); + } + + static std::string get_name() { + std::string model = util::read_file("/sys/firmware/devicetree/base/model"); + return util::strip(model.substr(std::string("comma ").size())); + } + + static cereal::InitData::DeviceType get_device_type() { + static const std::map device_map = { + {"tici", cereal::InitData::DeviceType::TICI}, + {"tizi", cereal::InitData::DeviceType::TIZI}, + {"mici", cereal::InitData::DeviceType::MICI} + }; + auto it = device_map.find(get_name()); + assert(it != device_map.end()); + return it->second; + } + + static int get_voltage() { return std::atoi(util::read_file("/sys/class/hwmon/hwmon1/in1_input").c_str()); } + static int get_current() { return std::atoi(util::read_file("/sys/class/hwmon/hwmon1/curr1_input").c_str()); } + + static std::string get_serial() { + static std::string serial(""); + if (serial.empty()) { + std::ifstream stream("/proc/cmdline"); + std::string cmdline; + std::getline(stream, cmdline); + + auto start = cmdline.find("serialno="); + if (start == std::string::npos) { + serial = "cccccc"; + } else { + auto end = cmdline.find(" ", start + 9); + serial = cmdline.substr(start + 9, end - start - 9); + } + } + return serial; + } + + static void reboot() { std::system("sudo reboot"); } + static void poweroff() { std::system("sudo poweroff"); } + static void set_brightness(int percent) { + float max = std::stof(util::read_file("/sys/class/backlight/panel0-backlight/max_brightness")); + std::ofstream("/sys/class/backlight/panel0-backlight/brightness") << int(percent * (max / 100.0f)) << "\n"; + } + static void set_display_power(bool on) { + std::ofstream("/sys/class/backlight/panel0-backlight/bl_power") << (on ? "0" : "4") << "\n"; + } + + static void set_ir_power(int percent) { + auto device = get_device_type(); + if (device == cereal::InitData::DeviceType::TICI || + device == cereal::InitData::DeviceType::TIZI) { + return; + } + + int value = util::map_val(std::clamp(percent, 0, 100), 0, 100, 0, 300); + std::ofstream("/sys/class/leds/led:switch_2/brightness") << 0 << "\n"; + std::ofstream("/sys/class/leds/led:torch_2/brightness") << value << "\n"; + std::ofstream("/sys/class/leds/led:switch_2/brightness") << value << "\n"; + } + + static std::map get_init_logs() { + std::map ret = { + {"/BUILD", util::read_file("/BUILD")}, + {"lsblk", util::check_output("lsblk -o NAME,SIZE,STATE,VENDOR,MODEL,REV,SERIAL")}, + {"SOM ID", util::read_file("/sys/devices/platform/vendor/vendor:gpio-som-id/som_id")}, + }; + + std::string bs = util::check_output("abctl --boot_slot"); + ret["boot slot"] = bs.substr(0, bs.find_first_of("\n")); + + std::string temp = util::read_file("/dev/disk/by-partlabel/ssd"); + temp.erase(temp.find_last_not_of(std::string("\0\r\n", 3))+1); + ret["boot temp"] = temp; + + // TODO: log something from system and boot + for (std::string part : {"xbl", "abl", "aop", "devcfg", "xbl_config"}) { + for (std::string slot : {"a", "b"}) { + std::string partition = part + "_" + slot; + std::string hash = util::check_output("sha256sum /dev/disk/by-partlabel/" + partition); + ret[partition] = hash.substr(0, hash.find_first_of(" ")); + } + } + + return ret; + } + + static bool get_ssh_enabled() { return Params().getBool("SshEnabled"); } + static void set_ssh_enabled(bool enabled) { Params().putBool("SshEnabled", enabled); } +}; diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py new file mode 100644 index 0000000000..36e65ad91c --- /dev/null +++ b/system/hardware/tici/hardware.py @@ -0,0 +1,607 @@ +import math +import os +import subprocess +import time +import tempfile +from enum import IntEnum +from functools import cached_property, lru_cache +from pathlib import Path + +from cereal import log +from openpilot.common.util import sudo_read, sudo_write +from openpilot.common.gpio import gpio_set, gpio_init, get_irqs_for_action +from openpilot.system.hardware.base import HardwareBase, LPABase, ThermalConfig, ThermalZone +from openpilot.system.hardware.tici import iwlist +from openpilot.system.hardware.tici.esim import TiciLPA +from openpilot.system.hardware.tici.pins import GPIO +from openpilot.system.hardware.tici.amplifier import Amplifier + +NM = 'org.freedesktop.NetworkManager' +NM_CON_ACT = NM + '.Connection.Active' +NM_DEV = NM + '.Device' +NM_DEV_WL = NM + '.Device.Wireless' +NM_DEV_STATS = NM + '.Device.Statistics' +NM_AP = NM + '.AccessPoint' +DBUS_PROPS = 'org.freedesktop.DBus.Properties' + +MM = 'org.freedesktop.ModemManager1' +MM_MODEM = MM + ".Modem" +MM_MODEM_SIMPLE = MM + ".Modem.Simple" +MM_SIM = MM + ".Sim" + +class MM_MODEM_STATE(IntEnum): + FAILED = -1 + UNKNOWN = 0 + INITIALIZING = 1 + LOCKED = 2 + DISABLED = 3 + DISABLING = 4 + ENABLING = 5 + ENABLED = 6 + SEARCHING = 7 + REGISTERED = 8 + DISCONNECTING = 9 + CONNECTING = 10 + CONNECTED = 11 + +class NMMetered(IntEnum): + NM_METERED_UNKNOWN = 0 + NM_METERED_YES = 1 + NM_METERED_NO = 2 + NM_METERED_GUESS_YES = 3 + NM_METERED_GUESS_NO = 4 + +TIMEOUT = 0.1 +REFRESH_RATE_MS = 1000 + +NetworkType = log.DeviceState.NetworkType +NetworkStrength = log.DeviceState.NetworkStrength + +# https://developer.gnome.org/ModemManager/unstable/ModemManager-Flags-and-Enumerations.html#MMModemAccessTechnology +MM_MODEM_ACCESS_TECHNOLOGY_UMTS = 1 << 5 +MM_MODEM_ACCESS_TECHNOLOGY_LTE = 1 << 14 + + +def affine_irq(val, action): + irqs = get_irqs_for_action(action) + if len(irqs) == 0: + print(f"No IRQs found for '{action}'") + return + + for i in irqs: + sudo_write(str(val), f"/proc/irq/{i}/smp_affinity_list") + +@lru_cache +def get_device_type(): + # lru_cache and cache can cause memory leaks when used in classes + with open("/sys/firmware/devicetree/base/model") as f: + model = f.read().strip('\x00') + return model.split('comma ')[-1] + +class Tici(HardwareBase): + @cached_property + def bus(self): + import dbus + return dbus.SystemBus() + + @cached_property + def nm(self): + return self.bus.get_object(NM, '/org/freedesktop/NetworkManager') + + @property # this should not be cached, in case the modemmanager restarts + def mm(self): + return self.bus.get_object(MM, '/org/freedesktop/ModemManager1') + + @cached_property + def amplifier(self): + if self.get_device_type() == "mici": + return None + return Amplifier() + + def get_os_version(self): + with open("/VERSION") as f: + return f.read().strip() + + def get_device_type(self): + return get_device_type() + + def reboot(self, reason=None): + subprocess.check_output(["sudo", "reboot"]) + + def uninstall(self): + Path("/data/__system_reset__").touch() + os.sync() + self.reboot() + + def get_serial(self): + return self.get_cmdline()['androidboot.serialno'] + + def get_voltage(self): + with open("/sys/class/hwmon/hwmon1/in1_input") as f: + return int(f.read()) + + def get_current(self): + with open("/sys/class/hwmon/hwmon1/curr1_input") as f: + return int(f.read()) + + def set_ir_power(self, percent: int): + if self.get_device_type() in ("tici", "tizi"): + return + + value = int((percent / 100) * 300) + with open("/sys/class/leds/led:switch_2/brightness", "w") as f: + f.write("0\n") + with open("/sys/class/leds/led:torch_2/brightness", "w") as f: + f.write(f"{value}\n") + with open("/sys/class/leds/led:switch_2/brightness", "w") as f: + f.write(f"{value}\n") + + def get_network_type(self): + try: + primary_connection = self.nm.Get(NM, 'PrimaryConnection', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + primary_connection = self.bus.get_object(NM, primary_connection) + primary_type = primary_connection.Get(NM_CON_ACT, 'Type', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + + if primary_type == '802-3-ethernet': + return NetworkType.ethernet + elif primary_type == '802-11-wireless': + return NetworkType.wifi + else: + active_connections = self.nm.Get(NM, 'ActiveConnections', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + for conn in active_connections: + c = self.bus.get_object(NM, conn) + tp = c.Get(NM_CON_ACT, 'Type', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + if tp == 'gsm': + modem = self.get_modem() + access_t = modem.Get(MM_MODEM, 'AccessTechnologies', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + if access_t >= MM_MODEM_ACCESS_TECHNOLOGY_LTE: + return NetworkType.cell4G + elif access_t >= MM_MODEM_ACCESS_TECHNOLOGY_UMTS: + return NetworkType.cell3G + else: + return NetworkType.cell2G + except Exception: + pass + + return NetworkType.none + + def get_modem(self): + objects = self.mm.GetManagedObjects(dbus_interface="org.freedesktop.DBus.ObjectManager", timeout=TIMEOUT) + modem_path = list(objects.keys())[0] + return self.bus.get_object(MM, modem_path) + + def get_wlan(self): + wlan_path = self.nm.GetDeviceByIpIface('wlan0', dbus_interface=NM, timeout=TIMEOUT) + return self.bus.get_object(NM, wlan_path) + + def get_wwan(self): + wwan_path = self.nm.GetDeviceByIpIface('wwan0', dbus_interface=NM, timeout=TIMEOUT) + return self.bus.get_object(NM, wwan_path) + + def get_sim_info(self): + modem = self.get_modem() + sim_path = modem.Get(MM_MODEM, 'Sim', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + + if sim_path == "/": + return { + 'sim_id': '', + 'mcc_mnc': None, + 'network_type': ["Unknown"], + 'sim_state': ["ABSENT"], + 'data_connected': False + } + else: + sim = self.bus.get_object(MM, sim_path) + return { + 'sim_id': str(sim.Get(MM_SIM, 'SimIdentifier', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)), + 'mcc_mnc': str(sim.Get(MM_SIM, 'OperatorIdentifier', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)), + 'network_type': ["Unknown"], + 'sim_state': ["READY"], + 'data_connected': modem.Get(MM_MODEM, 'State', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) == MM_MODEM_STATE.CONNECTED, + } + + def get_sim_lpa(self) -> LPABase: + return TiciLPA() + + def get_imei(self, slot): + if slot != 0: + return "" + + return str(self.get_modem().Get(MM_MODEM, 'EquipmentIdentifier', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)) + + def get_network_info(self): + if self.get_device_type() == "mici": + return None + try: + modem = self.get_modem() + info = modem.Command("AT+QNWINFO", math.ceil(TIMEOUT), dbus_interface=MM_MODEM, timeout=TIMEOUT) + extra = modem.Command('AT+QENG="servingcell"', math.ceil(TIMEOUT), dbus_interface=MM_MODEM, timeout=TIMEOUT) + state = modem.Get(MM_MODEM, 'State', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + except Exception: + return None + + if info and info.startswith('+QNWINFO: '): + info = info.replace('+QNWINFO: ', '').replace('"', '').split(',') + extra = "" if extra is None else extra.replace('+QENG: "servingcell",', '').replace('"', '') + state = "" if state is None else MM_MODEM_STATE(state).name + + if len(info) != 4: + return None + + technology, operator, band, channel = info + + return({ + 'technology': technology, + 'operator': operator, + 'band': band, + 'channel': int(channel), + 'extra': extra, + 'state': state, + }) + else: + return None + + def parse_strength(self, percentage): + if percentage < 25: + return NetworkStrength.poor + elif percentage < 50: + return NetworkStrength.moderate + elif percentage < 75: + return NetworkStrength.good + else: + return NetworkStrength.great + + def get_network_strength(self, network_type): + network_strength = NetworkStrength.unknown + + try: + if network_type == NetworkType.none: + pass + elif network_type == NetworkType.wifi: + wlan = self.get_wlan() + active_ap_path = wlan.Get(NM_DEV_WL, 'ActiveAccessPoint', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + if active_ap_path != "/": + active_ap = self.bus.get_object(NM, active_ap_path) + strength = int(active_ap.Get(NM_AP, 'Strength', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)) + network_strength = self.parse_strength(strength) + else: # Cellular + modem = self.get_modem() + strength = int(modem.Get(MM_MODEM, 'SignalQuality', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)[0]) + network_strength = self.parse_strength(strength) + except Exception: + pass + + return network_strength + + def get_network_metered(self, network_type) -> bool: + try: + primary_connection = self.nm.Get(NM, 'PrimaryConnection', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + primary_connection = self.bus.get_object(NM, primary_connection) + primary_devices = primary_connection.Get(NM_CON_ACT, 'Devices', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + + for dev in primary_devices: + dev_obj = self.bus.get_object(NM, str(dev)) + metered_prop = dev_obj.Get(NM_DEV, 'Metered', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + + if network_type == NetworkType.wifi: + if metered_prop in [NMMetered.NM_METERED_YES, NMMetered.NM_METERED_GUESS_YES]: + return True + elif network_type in [NetworkType.cell2G, NetworkType.cell3G, NetworkType.cell4G, NetworkType.cell5G]: + if metered_prop == NMMetered.NM_METERED_NO: + return False + except Exception: + pass + + return super().get_network_metered(network_type) + + def get_modem_version(self): + try: + modem = self.get_modem() + return modem.Get(MM_MODEM, 'Revision', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + except Exception: + return None + + def get_modem_temperatures(self): + timeout = 0.2 # Default timeout is too short + try: + modem = self.get_modem() + temps = modem.Command("AT+QTEMP", math.ceil(timeout), dbus_interface=MM_MODEM, timeout=timeout) + return list(filter(lambda t: t != 255, map(int, temps.split(' ')[1].split(',')))) + except Exception: + return [] + + + def get_current_power_draw(self): + return (self.read_param_file("/sys/class/hwmon/hwmon1/power1_input", int) / 1e6) + + def get_som_power_draw(self): + return (self.read_param_file("/sys/class/power_supply/bms/voltage_now", int) * self.read_param_file("/sys/class/power_supply/bms/current_now", int) / 1e12) + + def shutdown(self): + os.system("sudo poweroff") + + def get_thermal_config(self): + intake, exhaust, case = None, None, None + if self.get_device_type() == "mici": + case = ThermalZone("case") + intake = ThermalZone("intake") + exhaust = ThermalZone("exhaust") + return ThermalConfig(cpu=[ThermalZone(f"cpu{i}-silver-usr") for i in range(4)] + + [ThermalZone(f"cpu{i}-gold-usr") for i in range(4)], + gpu=[ThermalZone("gpu0-usr"), ThermalZone("gpu1-usr")], + dsp=ThermalZone("compute-hvx-usr"), + memory=ThermalZone("ddr-usr"), + pmic=[ThermalZone("pm8998_tz"), ThermalZone("pm8005_tz")], + intake=intake, + exhaust=exhaust, + case=case) + + def set_display_power(self, on): + try: + with open("/sys/class/backlight/panel0-backlight/bl_power", "w") as f: + f.write("0" if on else "4") + except Exception: + pass + + def set_screen_brightness(self, percentage): + try: + with open("/sys/class/backlight/panel0-backlight/max_brightness") as f: + max_brightness = float(f.read().strip()) + + val = int(percentage * (max_brightness / 100.)) + with open("/sys/class/backlight/panel0-backlight/brightness", "w") as f: + f.write(str(val)) + except Exception: + pass + + def get_screen_brightness(self): + try: + with open("/sys/class/backlight/panel0-backlight/max_brightness") as f: + max_brightness = float(f.read().strip()) + + with open("/sys/class/backlight/panel0-backlight/brightness") as f: + return int(float(f.read()) / (max_brightness / 100.)) + except Exception: + return 0 + + def set_power_save(self, powersave_enabled): + # amplifier, 100mW at idle + if self.amplifier is not None: + self.amplifier.set_global_shutdown(amp_disabled=powersave_enabled) + if not powersave_enabled: + self.amplifier.initialize_configuration(self.get_device_type()) + + # *** CPU config *** + + # offline big cluster + for i in range(4, 8): + val = '0' if powersave_enabled else '1' + sudo_write(val, f'/sys/devices/system/cpu/cpu{i}/online') + + for n in ('0', '4'): + if powersave_enabled and n == '4': + continue + gov = 'ondemand' if powersave_enabled else 'performance' + sudo_write(gov, f'/sys/devices/system/cpu/cpufreq/policy{n}/scaling_governor') + + # *** IRQ config *** + + # GPU, modeld core + affine_irq(7, "kgsl-3d0") + + # camerad core + camera_irqs = ("a5", "cci", "cpas_camnoc", "cpas-cdm", "csid", "ife", "csid-lite", "ife-lite") + for n in camera_irqs: + affine_irq(6, n) + + def get_gpu_usage_percent(self): + try: + with open('/sys/class/kgsl/kgsl-3d0/gpubusy') as f: + used, total = f.read().strip().split() + return 100.0 * int(used) / int(total) + except Exception: + return 0 + + def initialize_hardware(self): + if self.amplifier is not None: + self.amplifier.initialize_configuration(self.get_device_type()) + + # Allow hardwared to write engagement status to kmsg + os.system("sudo chmod a+w /dev/kmsg") + + # Ensure fan gpio is enabled so fan runs until shutdown, also turned on at boot by the ABL + gpio_init(GPIO.SOM_ST_IO, True) + gpio_set(GPIO.SOM_ST_IO, 1) + + # *** IRQ config *** + + # mask off big cluster from default affinity + sudo_write("f", "/proc/irq/default_smp_affinity") + + # move these off the default core + affine_irq(1, "msm_drm") # display + affine_irq(1, "msm_vidc") # encoders + affine_irq(1, "i2c_geni") # sensors + + # *** GPU config *** + # https://github.com/commaai/agnos-kernel-sdm845/blob/master/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi#L216 + sudo_write("1", "/sys/class/kgsl/kgsl-3d0/min_pwrlevel") + sudo_write("1", "/sys/class/kgsl/kgsl-3d0/max_pwrlevel") + sudo_write("1", "/sys/class/kgsl/kgsl-3d0/force_bus_on") + sudo_write("1", "/sys/class/kgsl/kgsl-3d0/force_clk_on") + sudo_write("1", "/sys/class/kgsl/kgsl-3d0/force_rail_on") + sudo_write("1000", "/sys/class/kgsl/kgsl-3d0/idle_timer") + sudo_write("performance", "/sys/class/kgsl/kgsl-3d0/devfreq/governor") + sudo_write("710", "/sys/class/kgsl/kgsl-3d0/max_clock_mhz") + + # setup governors + sudo_write("performance", "/sys/class/devfreq/soc:qcom,cpubw/governor") + sudo_write("performance", "/sys/class/devfreq/soc:qcom,memlat-cpu0/governor") + sudo_write("performance", "/sys/class/devfreq/soc:qcom,memlat-cpu4/governor") + + # *** VIDC (encoder) config *** + sudo_write("N", "/sys/kernel/debug/msm_vidc/clock_scaling") + sudo_write("Y", "/sys/kernel/debug/msm_vidc/disable_thermal_mitigation") + + # pandad core + affine_irq(3, "spi_geni") # SPI + try: + pid = subprocess.check_output(["pgrep", "-f", "spi0"], encoding='utf8').strip() + subprocess.call(["sudo", "chrt", "-f", "-p", "1", pid]) + subprocess.call(["sudo", "taskset", "-pc", "3", pid]) + except subprocess.CalledProcessException as e: + print(str(e)) + + def configure_modem(self): + sim_id = self.get_sim_info().get('sim_id', '') + + modem = self.get_modem() + try: + manufacturer = str(modem.Get(MM_MODEM, 'Manufacturer', dbus_interface=DBUS_PROPS, timeout=TIMEOUT)) + except Exception: + manufacturer = None + + cmds = [] + + if self.get_device_type() in ("tizi", ): + # clear out old blue prime initial APN + os.system('mmcli -m any --3gpp-set-initial-eps-bearer-settings="apn="') + + cmds += [ + # SIM hot swap + 'AT+QSIMDET=1,0', + 'AT+QSIMSTAT=1', + + # configure modem as data-centric + 'AT+QNVW=5280,0,"0102000000000000"', + 'AT+QNVFW="/nv/item_files/ims/IMS_enable",00', + 'AT+QNVFW="/nv/item_files/modem/mmode/ue_usage_setting",01', + ] + elif manufacturer == 'Cavli Inc.': + cmds += [ + 'AT^SIMSWAP=1', # use SIM slot, instead of internal eSIM + 'AT$QCSIMSLEEP=0', # disable SIM sleep + 'AT$QCSIMCFG=SimPowerSave,0', # more sleep disable + + # ethernet config + 'AT$QCPCFG=usbNet,0', + 'AT$QCNETDEVCTL=3,1', + ] + else: + # this modem gets upset with too many AT commands + if sim_id is None or len(sim_id) == 0: + cmds += [ + # SIM sleep disable + 'AT$QCSIMSLEEP=0', + 'AT$QCSIMCFG=SimPowerSave,0', + + # ethernet config + 'AT$QCPCFG=usbNet,1', + ] + + for cmd in cmds: + try: + modem.Command(cmd, math.ceil(TIMEOUT), dbus_interface=MM_MODEM, timeout=TIMEOUT) + except Exception: + pass + + # eSIM prime + dest = "/etc/NetworkManager/system-connections/esim.nmconnection" + if self.get_sim_lpa().is_comma_profile(sim_id) and not os.path.exists(dest): + with open(Path(__file__).parent/'esim.nmconnection') as f, tempfile.NamedTemporaryFile(mode='w') as tf: + dat = f.read() + dat = dat.replace("sim-id=", f"sim-id={sim_id}") + tf.write(dat) + tf.flush() + + # needs to be root + os.system(f"sudo cp {tf.name} {dest}") + os.system(f"sudo nmcli con load {dest}") + + def reboot_modem(self): + modem = self.get_modem() + for state in (0, 1): + try: + modem.Command(f'AT+CFUN={state}', math.ceil(TIMEOUT), dbus_interface=MM_MODEM, timeout=TIMEOUT) + except Exception: + pass + + def get_networks(self): + r = {} + + wlan = iwlist.scan() + if wlan is not None: + r['wlan'] = wlan + + lte_info = self.get_network_info() + if lte_info is not None: + extra = lte_info['extra'] + + # ,"LTE",,,,,,,, + # ,,,,,,, + if 'LTE' in extra: + extra = extra.split(',') + try: + r['lte'] = [{ + "mcc": int(extra[3]), + "mnc": int(extra[4]), + "cid": int(extra[5], 16), + "nmr": [{"pci": int(extra[6]), "earfcn": int(extra[7])}], + }] + except (ValueError, IndexError): + pass + + return r + + def get_modem_data_usage(self): + try: + wwan = self.get_wwan() + + # Ensure refresh rate is set so values don't go stale + refresh_rate = wwan.Get(NM_DEV_STATS, 'RefreshRateMs', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + if refresh_rate != REFRESH_RATE_MS: + u = type(refresh_rate) + wwan.Set(NM_DEV_STATS, 'RefreshRateMs', u(REFRESH_RATE_MS), dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + + tx = wwan.Get(NM_DEV_STATS, 'TxBytes', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + rx = wwan.Get(NM_DEV_STATS, 'RxBytes', dbus_interface=DBUS_PROPS, timeout=TIMEOUT) + return int(tx), int(rx) + except Exception: + return -1, -1 + + def has_internal_panda(self): + return True + + def reset_internal_panda(self): + gpio_init(GPIO.STM_RST_N, True) + gpio_init(GPIO.STM_BOOT0, True) + + gpio_set(GPIO.STM_RST_N, 1) + gpio_set(GPIO.STM_BOOT0, 0) + time.sleep(1) + gpio_set(GPIO.STM_RST_N, 0) + + def recover_internal_panda(self): + gpio_init(GPIO.STM_RST_N, True) + gpio_init(GPIO.STM_BOOT0, True) + + gpio_set(GPIO.STM_RST_N, 1) + gpio_set(GPIO.STM_BOOT0, 1) + time.sleep(0.5) + gpio_set(GPIO.STM_RST_N, 0) + time.sleep(0.5) + gpio_set(GPIO.STM_BOOT0, 0) + + def booted(self): + # this normally boots within 8s, but on rare occasions takes 30+s + encoder_state = sudo_read("/sys/kernel/debug/msm_vidc/core0/info") + if "Core state: 0" in encoder_state and (time.monotonic() < 60*2): + return False + return True + +if __name__ == "__main__": + t = Tici() + t.configure_modem() + t.initialize_hardware() + t.set_power_save(False) + print(t.get_sim_info()) diff --git a/system/hardware/tici/id_rsa b/system/hardware/tici/id_rsa new file mode 100644 index 0000000000..3f269afe22 --- /dev/null +++ b/system/hardware/tici/id_rsa @@ -0,0 +1,28 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC+iXXq30Tq+J5N +Kat3KWHCzcmwZ55nGh6WggAqECa5CasBlM9VeROpVu3beA+5h0MibRgbD4DMtVXB +t6gEvZ8nd04E7eLA9LTZyFDZ7SkSOVj4oXOQsT0GnJmKrASW5KslTWqVzTfo2XCt +Z+004ikLxmyFeBO8NOcErW1pa8gFdQDToH9FrA7kgysic/XVESTOoe7XlzRoe/eZ +acEQ+jtnmFd21A4aEADkk00Ahjr0uKaJiLUAPatxs2icIXWpgYtfqqtaKF23wSt6 +1OTu6cAwXbOWr3m+IUSRUO0IRzEIQS3z1jfd1svgzSgSSwZ1Lhj4AoKxIEAIc8qJ +rO4uymCJAgMBAAECggEBAISFevxHGdoL3Z5xkw6oO5SQKO2GxEeVhRzNgmu/HA+q +x8OryqD6O1CWY4037kft6iWxlwiLOdwna2P25ueVM3LxqdQH2KS4DmlCx+kq6FwC +gv063fQPMhC9LpWimvaQSPEC7VUPjQlo4tPY6sTTYBUOh0A1ihRm/x7juKuQCWix +Cq8C/DVnB1X4mGj+W3nJc5TwVJtgJbbiBrq6PWrhvB/3qmkxHRL7dU2SBb2iNRF1 +LLY30dJx/cD73UDKNHrlrsjk3UJc29Mp4/MladKvUkRqNwlYxSuAtJV0nZ3+iFkL +s3adSTHdJpClQer45R51rFDlVsDz2ZBpb/hRNRoGDuECgYEA6A1EixLq7QYOh3cb +Xhyh3W4kpVvA/FPfKH1OMy3ONOD/Y9Oa+M/wthW1wSoRL2n+uuIW5OAhTIvIEivj +6bAZsTT3twrvOrvYu9rx9aln4p8BhyvdjeW4kS7T8FP5ol6LoOt2sTP3T1LOuJPO +uQvOjlKPKIMh3c3RFNWTnGzMPa0CgYEA0jNiPLxP3A2nrX0keKDI+VHuvOY88gdh +0W5BuLMLovOIDk9aQFIbBbMuW1OTjHKv9NK+Lrw+YbCFqOGf1dU/UN5gSyE8lX/Q +FsUGUqUZx574nJZnOIcy3ONOnQLcvHAQToLFAGUd7PWgP3CtHkt9hEv2koUwL4vo +ikTP1u9Gkc0CgYEA2apoWxPZrY963XLKBxNQecYxNbLFaWq67t3rFnKm9E8BAICi +4zUaE5J1tMVi7Vi9iks9Ml9SnNyZRQJKfQ+kaebHXbkyAaPmfv+26rqHKboA0uxA +nDOZVwXX45zBkp6g1sdHxJx8JLoGEnkC9eyvSi0C//tRLx86OhLErXwYcNkCf1it +VMRKrWYoXJTUNo6tRhvodM88UnnIo3u3CALjhgU4uC1RTMHV4ZCGBwiAOb8GozSl +s5YD1E1iKwEULloHnK6BIh6P5v8q7J6uf/xdqoKMjlWBHgq6/roxKvkSPA1DOZ3l +jTadcgKFnRUmc+JT9p/ZbCxkA/ALFg8++G+0ghECgYA8vG3M/utweLvq4RI7l7U7 +b+i2BajfK2OmzNi/xugfeLjY6k2tfQGRuv6ppTjehtji2uvgDWkgjJUgPfZpir3I +RsVMUiFgloWGHETOy0Qvc5AwtqTJFLTD1Wza2uBilSVIEsg6Y83Gickh+ejOmEsY +6co17RFaAZHwGfCFFjO76Q== +-----END RSA PRIVATE KEY----- diff --git a/system/hardware/tici/iwlist.py b/system/hardware/tici/iwlist.py new file mode 100644 index 0000000000..1e7c428b40 --- /dev/null +++ b/system/hardware/tici/iwlist.py @@ -0,0 +1,35 @@ +import subprocess + + +def scan(interface="wlan0"): + result = [] + try: + r = subprocess.check_output(["iwlist", interface, "scan"], encoding='utf8') + + mac = None + for line in r.split('\n'): + if "Address" in line: + # Based on the adapter eithere a percentage or dBm is returned + # Add previous network in case no dBm signal level was seen + if mac is not None: + result.append({"mac": mac}) + mac = None + + mac = line.split(' ')[-1] + elif "dBm" in line: + try: + level = line.split('Signal level=')[1] + rss = int(level.split(' ')[0]) + result.append({"mac": mac, "rss": rss}) + mac = None + except ValueError: + continue + + # Add last network if no dBm was found + if mac is not None: + result.append({"mac": mac}) + + return result + + except Exception: + return None diff --git a/system/hardware/tici/pins.py b/system/hardware/tici/pins.py new file mode 100644 index 0000000000..bdbea591fb --- /dev/null +++ b/system/hardware/tici/pins.py @@ -0,0 +1,27 @@ +# GPIO pin definitions +class GPIO: + # both GPIO_STM_RST_N and GPIO_LTE_RST_N are misnamed, they are high to reset + HUB_RST_N = 30 + UBLOX_RST_N = 32 + UBLOX_SAFEBOOT_N = 33 + GNSS_PWR_EN = 34 # SCHEMATIC LABEL: GPIO_UBLOX_PWR_EN + + STM_RST_N = 124 + STM_BOOT0 = 134 + STM_PWR_EN_N = 41 # because STM32H7 RST doesn't generate a full power-on-reset + + SIREN = 42 + SOM_ST_IO = 49 + + LTE_RST_N = 50 + LTE_PWRKEY = 116 + LTE_BOOT = 52 + + # GPIO_CAM0_DVDD_EN = /sys/kernel/debug/regulator/camera_rear_ldo + CAM0_AVDD_EN = 8 + CAM0_RSTN = 9 + CAM1_RSTN = 7 + CAM2_RSTN = 12 + + # Sensor interrupts + LSM_INT = 84 diff --git a/system/hardware/tici/power_monitor.py b/system/hardware/tici/power_monitor.py new file mode 100755 index 0000000000..296290dae8 --- /dev/null +++ b/system/hardware/tici/power_monitor.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +import sys +import time +import datetime +import numpy as np +from collections import deque + +from openpilot.common.realtime import Ratekeeper +from openpilot.common.filter_simple import FirstOrderFilter + + +def read_power(): + with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/power1_input") as f: + return int(f.read()) / 1e6 + +def sample_power(seconds=5) -> list[float]: + rate = 123 + rk = Ratekeeper(rate, print_delay_threshold=None) + + pwrs = [] + for _ in range(rate*seconds): + pwrs.append(read_power()) + rk.keep_time() + return pwrs + +def get_power(seconds=5): + pwrs = sample_power(seconds) + return np.mean(pwrs) + +def wait_for_power(min_pwr, max_pwr, min_secs_in_range, timeout): + start_time = time.monotonic() + pwrs = deque([min_pwr - 1.]*min_secs_in_range, maxlen=min_secs_in_range) + while (time.monotonic() - start_time < timeout): + pwrs.append(get_power(1)) + if all(min_pwr <= p <= max_pwr for p in pwrs): + break + return np.mean(pwrs) + + +if __name__ == "__main__": + duration = None + if len(sys.argv) > 1: + duration = int(sys.argv[1]) + + rate = 23 + rk = Ratekeeper(rate, print_delay_threshold=None) + fltr = FirstOrderFilter(0, 5, 1. / rate, initialized=False) + + measurements = [] + start_time = time.monotonic() + + try: + while duration is None or time.monotonic() - start_time < duration: + fltr.update(read_power()) + if rk.frame % rate == 0: + measurements.append(fltr.x) + t = datetime.timedelta(seconds=time.monotonic() - start_time) + avg = sum(measurements) / len(measurements) + print(f"Now: {fltr.x:.2f} W, Avg: {avg:.2f} W over {t}") + rk.keep_time() + except KeyboardInterrupt: + pass + + t = datetime.timedelta(seconds=time.monotonic() - start_time) + avg = sum(measurements) / len(measurements) + print(f"\nAverage power: {avg:.2f}W over {t}") diff --git a/system/hardware/tici/precise_power_measure.py b/system/hardware/tici/precise_power_measure.py new file mode 100755 index 0000000000..52fe0850ab --- /dev/null +++ b/system/hardware/tici/precise_power_measure.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 +import numpy as np +from openpilot.system.hardware.tici.power_monitor import sample_power + +if __name__ == '__main__': + print("measuring for 5 seconds") + for _ in range(3): + pwrs = sample_power() + print(f"mean {np.mean(pwrs):.2f} std {np.std(pwrs):.2f}") diff --git a/system/hardware/tici/restart_modem.sh b/system/hardware/tici/restart_modem.sh new file mode 100755 index 0000000000..741dc72050 --- /dev/null +++ b/system/hardware/tici/restart_modem.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +#nmcli connection modify --temporary lte gsm.home-only yes +#nmcli connection modify --temporary lte gsm.auto-config yes +#nmcli connection modify --temporary lte connection.autoconnect-retries 20 +sudo nmcli connection reload + +sudo systemctl stop ModemManager +nmcli con down lte +nmcli con down blue-prime + +# power cycle modem +/usr/comma/lte/lte.sh stop_blocking +/usr/comma/lte/lte.sh start + +sudo systemctl restart NetworkManager +#sudo systemctl restart ModemManager +sudo ModemManager --debug diff --git a/system/hardware/tici/tests/__init__.py b/system/hardware/tici/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/hardware/tici/tests/compare_casync_manifest.py b/system/hardware/tici/tests/compare_casync_manifest.py new file mode 100755 index 0000000000..7de66d91d0 --- /dev/null +++ b/system/hardware/tici/tests/compare_casync_manifest.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +import argparse +import collections +import multiprocessing +import os + +import requests +from tqdm import tqdm + +import openpilot.system.hardware.tici.casync as casync + + +def get_chunk_download_size(chunk): + sha = chunk.sha.hex() + path = os.path.join(remote_url, sha[:4], sha + ".cacnk") + if os.path.isfile(path): + return os.path.getsize(path) + else: + r = requests.head(path, timeout=10) + r.raise_for_status() + return int(r.headers['content-length']) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='Compute overlap between two casync manifests') + parser.add_argument('frm') + parser.add_argument('to') + args = parser.parse_args() + + frm = casync.parse_caibx(args.frm) + to = casync.parse_caibx(args.to) + remote_url = args.to.replace('.caibx', '') + + most_common = collections.Counter(t.sha for t in to).most_common(1)[0][0] + + frm_dict = casync.build_chunk_dict(frm) + + # Get content-length for each chunk + with multiprocessing.Pool() as pool: + szs = list(tqdm(pool.imap(get_chunk_download_size, to), total=len(to))) + chunk_sizes = {t.sha: sz for (t, sz) in zip(to, szs, strict=True)} + + sources: dict[str, list[int]] = { + 'seed': [], + 'remote_uncompressed': [], + 'remote_compressed': [], + } + + for chunk in to: + # Assume most common chunk is the zero chunk + if chunk.sha == most_common: + continue + + if chunk.sha in frm_dict: + sources['seed'].append(chunk.length) + else: + sources['remote_uncompressed'].append(chunk.length) + sources['remote_compressed'].append(chunk_sizes[chunk.sha]) + + print() + print("Update statistics (excluding zeros)") + print() + print("Download only with no seed:") + print(f" Remote (uncompressed)\t\t{sum(sources['seed'] + sources['remote_uncompressed']) / 1000 / 1000:.2f} MB\tn = {len(to)}") + print(f" Remote (compressed download)\t{sum(chunk_sizes.values()) / 1000 / 1000:.2f} MB\tn = {len(to)}") + print() + print("Upgrade with seed partition:") + print(f" Seed (uncompressed)\t\t{sum(sources['seed']) / 1000 / 1000:.2f} MB\t\t\t\tn = {len(sources['seed'])}") + sz, n = sum(sources['remote_uncompressed']), len(sources['remote_uncompressed']) + print(f" Remote (uncompressed)\t\t{sz / 1000 / 1000:.2f} MB\t(avg {sz / 1000 / 1000 / n:4f} MB)\tn = {n}") + sz, n = sum(sources['remote_compressed']), len(sources['remote_compressed']) + print(f" Remote (compressed download)\t{sz / 1000 / 1000:.2f} MB\t(avg {sz / 1000 / 1000 / n:4f} MB)\tn = {n}") diff --git a/system/hardware/tici/tests/test_agnos_updater.py b/system/hardware/tici/tests/test_agnos_updater.py new file mode 100644 index 0000000000..a1bbd363fd --- /dev/null +++ b/system/hardware/tici/tests/test_agnos_updater.py @@ -0,0 +1,20 @@ +import json +import os +import requests + +TEST_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__))) +MANIFEST = os.path.join(TEST_DIR, "../agnos.json") + + +class TestAgnosUpdater: + + def test_manifest(self): + with open(MANIFEST) as f: + m = json.load(f) + + for img in m: + r = requests.head(img['url'], timeout=10) + r.raise_for_status() + assert r.headers['Content-Type'] == "application/x-xz" + if not img['sparse']: + assert img['hash'] == img['hash_raw'] diff --git a/system/hardware/tici/tests/test_amplifier.py b/system/hardware/tici/tests/test_amplifier.py new file mode 100644 index 0000000000..3f75436db1 --- /dev/null +++ b/system/hardware/tici/tests/test_amplifier.py @@ -0,0 +1,70 @@ +import pytest +import time +import random +import subprocess + +from panda import Panda +from openpilot.system.hardware import TICI, HARDWARE +from openpilot.system.hardware.tici.hardware import Tici +from openpilot.system.hardware.tici.amplifier import Amplifier + + +class TestAmplifier: + + @classmethod + def setup_class(cls): + if not TICI: + pytest.skip() + + def setup_method(self): + # clear dmesg + subprocess.check_call("sudo dmesg -C", shell=True) + + HARDWARE.reset_internal_panda() + Panda.wait_for_panda(None, 30) + self.panda = Panda() + + def teardown_method(self): + HARDWARE.reset_internal_panda() + + def _check_for_i2c_errors(self, expected): + dmesg = subprocess.check_output("dmesg", shell=True, encoding='utf8') + i2c_lines = [l for l in dmesg.strip().splitlines() if 'i2c_geni a88000.i2c' in l] + i2c_str = '\n'.join(i2c_lines) + + if not expected: + return len(i2c_lines) == 0 + else: + return "i2c error :-107" in i2c_str or "Bus arbitration lost" in i2c_str + + def test_init(self): + amp = Amplifier(debug=True) + r = amp.initialize_configuration(Tici().get_device_type()) + assert r + assert self._check_for_i2c_errors(False) + + def test_shutdown(self): + amp = Amplifier(debug=True) + for _ in range(10): + r = amp.set_global_shutdown(True) + r = amp.set_global_shutdown(False) + # amp config should be successful, with no i2c errors + assert r + assert self._check_for_i2c_errors(False) + + def test_init_while_siren_play(self): + for _ in range(10): + self.panda.set_siren(False) + time.sleep(0.1) + + self.panda.set_siren(True) + time.sleep(random.randint(0, 5)) + + amp = Amplifier(debug=True) + r = amp.initialize_configuration(Tici().get_device_type()) + assert r + + if self._check_for_i2c_errors(True): + break + else: + pytest.fail("didn't hit any i2c errors") diff --git a/system/hardware/tici/tests/test_esim.py b/system/hardware/tici/tests/test_esim.py new file mode 100644 index 0000000000..6fab931cce --- /dev/null +++ b/system/hardware/tici/tests/test_esim.py @@ -0,0 +1,51 @@ +import pytest + +from openpilot.system.hardware import HARDWARE, TICI +from openpilot.system.hardware.base import LPAProfileNotFoundError + +# https://euicc-manual.osmocom.org/docs/rsp/known-test-profile +# iccid is always the same for the given activation code +TEST_ACTIVATION_CODE = 'LPA:1$rsp.truphone.com$QRF-BETTERROAMING-PMRDGIR2EARDEIT5' +TEST_ICCID = '8944476500001944011' + +TEST_NICKNAME = 'test_profile' + +def cleanup(): + lpa = HARDWARE.get_sim_lpa() + try: + lpa.delete_profile(TEST_ICCID) + except LPAProfileNotFoundError: + pass + lpa.process_notifications() + +class TestEsim: + + @classmethod + def setup_class(cls): + if not TICI: + pytest.skip() + cleanup() + + @classmethod + def teardown_class(cls): + cleanup() + + def test_provision_enable_disable(self): + lpa = HARDWARE.get_sim_lpa() + current_active = lpa.get_active_profile() + + lpa.download_profile(TEST_ACTIVATION_CODE, TEST_NICKNAME) + assert any(p.iccid == TEST_ICCID and p.nickname == TEST_NICKNAME for p in lpa.list_profiles()) + + lpa.enable_profile(TEST_ICCID) + new_active = lpa.get_active_profile() + assert new_active is not None + assert new_active.iccid == TEST_ICCID + assert new_active.nickname == TEST_NICKNAME + + lpa.disable_profile(TEST_ICCID) + new_active = lpa.get_active_profile() + assert new_active is None + + if current_active: + lpa.enable_profile(current_active.iccid) diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py new file mode 100644 index 0000000000..4fbde81673 --- /dev/null +++ b/system/hardware/tici/tests/test_power_draw.py @@ -0,0 +1,128 @@ +from collections import defaultdict, deque +import pytest +import time +import numpy as np +from dataclasses import dataclass +from tabulate import tabulate + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from opendbc.car.car_helpers import get_demo_car_params +from openpilot.common.mock import mock_messages +from openpilot.common.params import Params +from openpilot.system.hardware.tici.power_monitor import get_power +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.manager.manager import manager_cleanup + +SAMPLE_TIME = 8 # seconds to sample power +MAX_WARMUP_TIME = 30 # seconds to wait for SAMPLE_TIME consecutive valid samples + +@dataclass +class Proc: + procs: list[str] + power: float + msgs: list[str] + rtol: float = 0.05 + atol: float = 0.12 + + @property + def name(self): + return '+'.join(self.procs) + + +PROCS = [ + Proc(['camerad'], 1.65, atol=0.4, msgs=['roadCameraState', 'wideRoadCameraState', 'driverCameraState']), + Proc(['modeld'], 1.24, atol=0.2, msgs=['modelV2']), + Proc(['dmonitoringmodeld'], 0.65, atol=0.35, msgs=['driverStateV2']), + Proc(['encoderd'], 0.23, msgs=[]), +] + + +@pytest.mark.tici +class TestPowerDraw: + + def setup_method(self): + Params().put("CarParams", get_demo_car_params().to_bytes()) + + # wait a bit for power save to disable + time.sleep(5) + + def teardown_method(self): + manager_cleanup() + + def get_expected_messages(self, proc): + return int(sum(SAMPLE_TIME * SERVICE_LIST[msg].frequency for msg in proc.msgs)) + + def valid_msg_count(self, proc, msg_counts): + msgs_received = sum(msg_counts[msg] for msg in proc.msgs) + msgs_expected = self.get_expected_messages(proc) + return np.isclose(msgs_expected, msgs_received, rtol=.02, atol=2) + + def valid_power_draw(self, proc, used): + return np.isclose(used, proc.power, rtol=proc.rtol, atol=proc.atol) + + def tabulate_msg_counts(self, msgs_and_power): + msg_counts = defaultdict(int) + for _, counts in msgs_and_power: + for msg, count in counts.items(): + msg_counts[msg] += count + return msg_counts + + def get_power_with_warmup_for_target(self, proc, prev): + socks = {msg: messaging.sub_sock(msg) for msg in proc.msgs} + for sock in socks.values(): + messaging.drain_sock_raw(sock) + + msgs_and_power = deque([], maxlen=SAMPLE_TIME) + + start_time = time.monotonic() + + while (time.monotonic() - start_time) < MAX_WARMUP_TIME: + power = get_power(1) + iteration_msg_counts = {} + for msg,sock in socks.items(): + iteration_msg_counts[msg] = len(messaging.drain_sock_raw(sock)) + msgs_and_power.append((power, iteration_msg_counts)) + + if len(msgs_and_power) < SAMPLE_TIME: + continue + + msg_counts = self.tabulate_msg_counts(msgs_and_power) + now = np.mean([m[0] for m in msgs_and_power]) + + if self.valid_msg_count(proc, msg_counts) and self.valid_power_draw(proc, now - prev): + break + + return now, msg_counts, time.monotonic() - start_time - SAMPLE_TIME + + @mock_messages(['livePose']) + def test_camera_procs(self, subtests): + baseline = get_power() + + prev = baseline + used = {} + warmup_time = {} + msg_counts = {} + + for proc in PROCS: + for p in proc.procs: + managed_processes[p].start() + now, local_msg_counts, warmup_time[proc.name] = self.get_power_with_warmup_for_target(proc, prev) + msg_counts.update(local_msg_counts) + + used[proc.name] = now - prev + prev = now + + manager_cleanup() + + tab = [['process', 'expected (W)', 'measured (W)', '# msgs expected', '# msgs received', "warmup time (s)"]] + for proc in PROCS: + cur = used[proc.name] + expected = proc.power + msgs_received = sum(msg_counts[msg] for msg in proc.msgs) + tab.append([proc.name, round(expected, 2), round(cur, 2), self.get_expected_messages(proc), msgs_received, round(warmup_time[proc.name], 2)]) + with subtests.test(proc=proc.name): + assert self.valid_msg_count(proc, msg_counts), f"expected {self.get_expected_messages(proc)} msgs, got {msgs_received} msgs" + assert self.valid_power_draw(proc, cur), f"expected {expected:.2f}W, got {cur:.2f}W" + print(tabulate(tab)) + print(f"Baseline {baseline:.2f}W\n") diff --git a/system/hardware/tici/updater b/system/hardware/tici/updater new file mode 100755 index 0000000000..5773489eca Binary files /dev/null and b/system/hardware/tici/updater differ diff --git a/system/journald.py b/system/journald.py new file mode 100755 index 0000000000..37158b9251 --- /dev/null +++ b/system/journald.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +import json +import subprocess + +import cereal.messaging as messaging +from openpilot.common.swaglog import cloudlog + + +def main(): + pm = messaging.PubMaster(['androidLog']) + cmd = ['journalctl', '-f', '-o', 'json'] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, text=True) + assert proc.stdout is not None + try: + for line in proc.stdout: + line = line.strip() + if not line: + continue + try: + kv = json.loads(line) + except json.JSONDecodeError: + cloudlog.exception("failed to parse journalctl output") + continue + + msg = messaging.new_message('androidLog') + entry = msg.androidLog + entry.ts = int(kv.get('__REALTIME_TIMESTAMP', 0)) + entry.message = json.dumps(kv) + if '_PID' in kv: + entry.pid = int(kv['_PID']) + if 'PRIORITY' in kv: + entry.priority = int(kv['PRIORITY']) + if 'SYSLOG_IDENTIFIER' in kv: + entry.tag = kv['SYSLOG_IDENTIFIER'] + + pm.send('androidLog', msg) + finally: + proc.terminate() + proc.wait() + + +if __name__ == '__main__': + main() diff --git a/system/loggerd/.gitignore b/system/loggerd/.gitignore new file mode 100644 index 0000000000..53dc24e6f2 --- /dev/null +++ b/system/loggerd/.gitignore @@ -0,0 +1,4 @@ +loggerd +encoderd +bootlog +tests/test_logger diff --git a/system/loggerd/SConscript b/system/loggerd/SConscript new file mode 100644 index 0000000000..cf169f4dc6 --- /dev/null +++ b/system/loggerd/SConscript @@ -0,0 +1,26 @@ +Import('env', 'arch', 'messaging', 'common', 'visionipc') + +libs = [common, messaging, visionipc, + 'avformat', 'avcodec', 'avutil', + 'yuv', 'OpenCL', 'pthread', 'zstd'] + +src = ['logger.cc', 'zstd_writer.cc', 'video_writer.cc', 'encoder/encoder.cc', 'encoder/v4l_encoder.cc', 'encoder/jpeg_encoder.cc'] +if arch != "larch64": + src += ['encoder/ffmpeg_encoder.cc'] + +if arch == "Darwin": + # fix OpenCL + del libs[libs.index('OpenCL')] + env['FRAMEWORKS'] = ['OpenCL'] + # exclude v4l + del src[src.index('encoder/v4l_encoder.cc')] + +logger_lib = env.Library('logger', src) +libs.insert(0, logger_lib) + +env.Program('loggerd', ['loggerd.cc'], LIBS=libs) +env.Program('encoderd', ['encoderd.cc'], LIBS=libs + ["jpeg"]) +env.Program('bootlog.cc', LIBS=libs) + +if GetOption('extras'): + env.Program('tests/test_logger', ['tests/test_runner.cc', 'tests/test_logger.cc', 'tests/test_zstd_writer.cc'], LIBS=libs + ['curl', 'crypto']) diff --git a/system/loggerd/__init__.py b/system/loggerd/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/loggerd/bootlog.cc b/system/loggerd/bootlog.cc new file mode 100644 index 0000000000..1b87ce394f --- /dev/null +++ b/system/loggerd/bootlog.cc @@ -0,0 +1,68 @@ +#include +#include + +#include "cereal/messaging/messaging.h" +#include "common/params.h" +#include "common/swaglog.h" +#include "system/loggerd/logger.h" +#include "system/loggerd/zstd_writer.h" + + +static kj::Array build_boot_log() { + MessageBuilder msg; + auto boot = msg.initEvent().initBoot(); + + boot.setWallTimeNanos(nanos_since_epoch()); + + std::string pstore = "/sys/fs/pstore"; + std::map pstore_map = util::read_files_in_dir(pstore); + + int i = 0; + auto lpstore = boot.initPstore().initEntries(pstore_map.size()); + for (auto& kv : pstore_map) { + auto lentry = lpstore[i]; + lentry.setKey(kv.first); + lentry.setValue(capnp::Data::Reader((const kj::byte*)kv.second.data(), kv.second.size())); + i++; + } + + // Gather output of commands + std::vector bootlog_commands = { + "[ -x \"$(command -v journalctl)\" ] && journalctl -o short-monotonic", + }; + + + auto commands = boot.initCommands().initEntries(bootlog_commands.size()); + for (int j = 0; j < bootlog_commands.size(); j++) { + auto lentry = commands[j]; + + lentry.setKey(bootlog_commands[j]); + + const std::string result = util::check_output(bootlog_commands[j]); + lentry.setValue(capnp::Data::Reader((const kj::byte*)result.data(), result.size())); + } + + boot.setLaunchLog(util::read_file("/tmp/launch_log")); + return capnp::messageToFlatArray(msg); +} + +int main(int argc, char** argv) { + const std::string id = logger_get_identifier("BootCount"); + const std::string path = Path::log_root() + "/boot/" + id + ".zst"; + LOGW("bootlog to %s", path.c_str()); + + // Open bootlog + bool r = util::create_directories(Path::log_root() + "/boot/", 0775); + assert(r); + + ZstdFileWriter file(path, LOG_COMPRESSION_LEVEL); + // Write initdata + file.write(logger_build_init_data().asBytes()); + // Write bootlog + file.write(build_boot_log().asBytes()); + + // Write out bootlog param to match routes with bootlog + Params().put("CurrentBootlog", id.c_str()); + + return 0; +} diff --git a/system/loggerd/config.py b/system/loggerd/config.py new file mode 100644 index 0000000000..e1c47c768d --- /dev/null +++ b/system/loggerd/config.py @@ -0,0 +1,29 @@ +import os +from openpilot.system.hardware.hw import Paths + + +CAMERA_FPS = 20 +SEGMENT_LENGTH = 60 + +STATS_DIR_FILE_LIMIT = 10000 +STATS_SOCKET = "ipc:///tmp/stats" +STATS_FLUSH_TIME_S = 60 + +def get_available_percent(default: float) -> float: + try: + statvfs = os.statvfs(Paths.log_root()) + available_percent = 100.0 * statvfs.f_bavail / statvfs.f_blocks + except OSError: + available_percent = default + + return available_percent + + +def get_available_bytes(default: int) -> int: + try: + statvfs = os.statvfs(Paths.log_root()) + available_bytes = statvfs.f_bavail * statvfs.f_frsize + except OSError: + available_bytes = default + + return available_bytes diff --git a/system/loggerd/deleter.py b/system/loggerd/deleter.py new file mode 100755 index 0000000000..eb8fd35f21 --- /dev/null +++ b/system/loggerd/deleter.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +import os +import shutil +import threading +from openpilot.system.hardware.hw import Paths +from openpilot.common.swaglog import cloudlog +from openpilot.system.loggerd.config import get_available_bytes, get_available_percent +from openpilot.system.loggerd.uploader import listdir_by_creation +from openpilot.system.loggerd.xattr_cache import getxattr + +MIN_BYTES = 5 * 1024 * 1024 * 1024 +MIN_PERCENT = 10 + +DELETE_LAST = ['boot', 'crash'] + +PRESERVE_ATTR_NAME = 'user.preserve' +PRESERVE_ATTR_VALUE = b'1' +PRESERVE_COUNT = 5 + + +def has_preserve_xattr(d: str) -> bool: + return getxattr(os.path.join(Paths.log_root(), d), PRESERVE_ATTR_NAME) == PRESERVE_ATTR_VALUE + + +def get_preserved_segments(dirs_by_creation: list[str]) -> set[str]: + # skip deleting most recent N preserved segments (and their prior segment) + preserved = set() + for n, d in enumerate(filter(has_preserve_xattr, reversed(dirs_by_creation))): + if n == PRESERVE_COUNT: + break + date_str, _, seg_str = d.rpartition("--") + + # ignore non-segment directories + if not date_str: + continue + try: + seg_num = int(seg_str) + except ValueError: + continue + + # preserve segment and two prior + for _seg_num in range(max(0, seg_num - 2), seg_num + 1): + preserved.add(f"{date_str}--{_seg_num}") + + return preserved + + +def deleter_thread(exit_event: threading.Event): + while not exit_event.is_set(): + out_of_bytes = get_available_bytes(default=MIN_BYTES + 1) < MIN_BYTES + out_of_percent = get_available_percent(default=MIN_PERCENT + 1) < MIN_PERCENT + + if out_of_percent or out_of_bytes: + dirs = listdir_by_creation(Paths.log_root()) + preserved_dirs = get_preserved_segments(dirs) + + # remove the earliest directory we can + for delete_dir in sorted(dirs, key=lambda d: (d in DELETE_LAST, d in preserved_dirs)): + delete_path = os.path.join(Paths.log_root(), delete_dir) + + if any(name.endswith(".lock") for name in os.listdir(delete_path)): + continue + + try: + cloudlog.info(f"deleting {delete_path}") + shutil.rmtree(delete_path) + break + except OSError: + cloudlog.exception(f"issue deleting {delete_path}") + exit_event.wait(.1) + else: + exit_event.wait(30) + + +def main(): + deleter_thread(threading.Event()) + + +if __name__ == "__main__": + main() diff --git a/system/loggerd/encoder/encoder.cc b/system/loggerd/encoder/encoder.cc new file mode 100644 index 0000000000..06922b0cd0 --- /dev/null +++ b/system/loggerd/encoder/encoder.cc @@ -0,0 +1,42 @@ +#include "system/loggerd/encoder/encoder.h" + +VideoEncoder::VideoEncoder(const EncoderInfo &encoder_info, int in_width, int in_height) + : encoder_info(encoder_info), in_width(in_width), in_height(in_height) { + + out_width = encoder_info.frame_width > 0 ? encoder_info.frame_width : in_width; + out_height = encoder_info.frame_height > 0 ? encoder_info.frame_height : in_height; + + pm.reset(new PubMaster(std::vector{encoder_info.publish_name})); +} + +void VideoEncoder::publisher_publish(int segment_num, uint32_t idx, VisionIpcBufExtra &extra, + unsigned int flags, kj::ArrayPtr header, kj::ArrayPtr dat) { + MessageBuilder msg; + auto event = msg.initEvent(true); + auto edat = (event.*(encoder_info.init_encode_data_func))(); + auto edata = edat.initIdx(); + struct timespec ts; + timespec_get(&ts, TIME_UTC); + edat.setUnixTimestampNanos((uint64_t)ts.tv_sec*1000000000 + ts.tv_nsec); + edata.setFrameId(extra.frame_id); + edata.setTimestampSof(extra.timestamp_sof); + edata.setTimestampEof(extra.timestamp_eof); + edata.setType(encoder_info.get_settings(in_width).encode_type); + edata.setEncodeId(cnt++); + edata.setSegmentNum(segment_num); + edata.setSegmentId(idx); + edata.setFlags(flags); + edata.setLen(dat.size()); + edat.adoptData(msg.getOrphanage().referenceExternalData(dat)); + edat.setWidth(out_width); + edat.setHeight(out_height); + if (flags & V4L2_BUF_FLAG_KEYFRAME) edat.setHeader(header); + + uint32_t bytes_size = capnp::computeSerializedSizeInWords(msg) * sizeof(capnp::word); + if (msg_cache.size() < bytes_size) { + msg_cache.resize(bytes_size); + } + kj::ArrayOutputStream output_stream(kj::ArrayPtr(msg_cache.data(), bytes_size)); + capnp::writeMessage(output_stream, msg); + pm->send(encoder_info.publish_name, msg_cache.data(), bytes_size); +} diff --git a/system/loggerd/encoder/encoder.h b/system/loggerd/encoder/encoder.h new file mode 100644 index 0000000000..57146fafc3 --- /dev/null +++ b/system/loggerd/encoder/encoder.h @@ -0,0 +1,42 @@ +#pragma once + +// has to be in this order +#ifdef __linux__ +#include "third_party/linux/include/v4l2-controls.h" +#include +#else +#define V4L2_BUF_FLAG_KEYFRAME 8 +#endif + +#include +#include +#include +#include +#include + +#include "cereal/messaging/messaging.h" +#include "msgq/visionipc/visionipc.h" +#include "common/queue.h" +#include "system/loggerd/loggerd.h" + +class VideoEncoder { +public: + VideoEncoder(const EncoderInfo &encoder_info, int in_width, int in_height); + virtual ~VideoEncoder() {} + virtual int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra) = 0; + virtual void encoder_open() = 0; + virtual void encoder_close() = 0; + + void publisher_publish(int segment_num, uint32_t idx, VisionIpcBufExtra &extra, unsigned int flags, kj::ArrayPtr header, kj::ArrayPtr dat); + +protected: + int in_width, in_height; + int out_width, out_height; + const EncoderInfo encoder_info; + +private: + // total frames encoded + int cnt = 0; + std::unique_ptr pm; + std::vector msg_cache; +}; diff --git a/system/loggerd/encoder/ffmpeg_encoder.cc b/system/loggerd/encoder/ffmpeg_encoder.cc new file mode 100644 index 0000000000..4d6be47182 --- /dev/null +++ b/system/loggerd/encoder/ffmpeg_encoder.cc @@ -0,0 +1,150 @@ +#include "system/loggerd/encoder/ffmpeg_encoder.h" + +#include +#include + +#include +#include +#include + +#define __STDC_CONSTANT_MACROS + +#include "third_party/libyuv/include/libyuv.h" + +extern "C" { +#include +#include +#include +} + +#include "common/swaglog.h" +#include "common/util.h" + +const int env_debug_encoder = (getenv("DEBUG_ENCODER") != NULL) ? atoi(getenv("DEBUG_ENCODER")) : 0; + +FfmpegEncoder::FfmpegEncoder(const EncoderInfo &encoder_info, int in_width, int in_height) + : VideoEncoder(encoder_info, in_width, in_height) { + frame = av_frame_alloc(); + assert(frame); + frame->format = AV_PIX_FMT_YUV420P; + frame->width = out_width; + frame->height = out_height; + frame->linesize[0] = out_width; + frame->linesize[1] = out_width/2; + frame->linesize[2] = out_width/2; + + convert_buf.resize(in_width * in_height * 3 / 2); + + if (in_width != out_width || in_height != out_height) { + downscale_buf.resize(out_width * out_height * 3 / 2); + } +} + +FfmpegEncoder::~FfmpegEncoder() { + encoder_close(); + av_frame_free(&frame); +} + +void FfmpegEncoder::encoder_open() { + auto codec_id = encoder_info.get_settings(in_width).encode_type == cereal::EncodeIndex::Type::QCAMERA_H264 + ? AV_CODEC_ID_H264 + : AV_CODEC_ID_FFVHUFF; + const AVCodec *codec = avcodec_find_encoder(codec_id); + + this->codec_ctx = avcodec_alloc_context3(codec); + assert(this->codec_ctx); + this->codec_ctx->width = frame->width; + this->codec_ctx->height = frame->height; + this->codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; + this->codec_ctx->time_base = (AVRational){ 1, encoder_info.fps }; + int err = avcodec_open2(this->codec_ctx, codec, NULL); + assert(err >= 0); + + is_open = true; + segment_num++; + counter = 0; +} + +void FfmpegEncoder::encoder_close() { + if (!is_open) return; + + avcodec_free_context(&codec_ctx); + is_open = false; +} + +int FfmpegEncoder::encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra) { + assert(buf->width == this->in_width); + assert(buf->height == this->in_height); + + uint8_t *cy = convert_buf.data(); + uint8_t *cu = cy + in_width * in_height; + uint8_t *cv = cu + (in_width / 2) * (in_height / 2); + libyuv::NV12ToI420(buf->y, buf->stride, + buf->uv, buf->stride, + cy, in_width, + cu, in_width/2, + cv, in_width/2, + in_width, in_height); + + if (downscale_buf.size() > 0) { + uint8_t *out_y = downscale_buf.data(); + uint8_t *out_u = out_y + frame->width * frame->height; + uint8_t *out_v = out_u + (frame->width / 2) * (frame->height / 2); + libyuv::I420Scale(cy, in_width, + cu, in_width/2, + cv, in_width/2, + in_width, in_height, + out_y, frame->width, + out_u, frame->width/2, + out_v, frame->width/2, + frame->width, frame->height, + libyuv::kFilterNone); + frame->data[0] = out_y; + frame->data[1] = out_u; + frame->data[2] = out_v; + } else { + frame->data[0] = cy; + frame->data[1] = cu; + frame->data[2] = cv; + } + frame->pts = counter*50*1000; // 50ms per frame + + int ret = counter; + + int err = avcodec_send_frame(this->codec_ctx, frame); + if (err < 0) { + LOGE("avcodec_send_frame error %d", err); + ret = -1; + } + + AVPacket pkt = {}; + pkt.data = NULL; + pkt.size = 0; + while (ret >= 0) { + err = avcodec_receive_packet(this->codec_ctx, &pkt); + if (err == AVERROR_EOF) { + break; + } else if (err == AVERROR(EAGAIN)) { + // Encoder might need a few frames on startup to get started. Keep going + ret = 0; + break; + } else if (err < 0) { + LOGE("avcodec_receive_packet error %d", err); + ret = -1; + break; + } + + if (env_debug_encoder) { + printf("%20s got %8d bytes flags %8x idx %4d id %8d\n", encoder_info.publish_name, pkt.size, pkt.flags, counter, extra->frame_id); + } + + publisher_publish(segment_num, counter, *extra, + (pkt.flags & AV_PKT_FLAG_KEY) ? V4L2_BUF_FLAG_KEYFRAME : 0, + kj::arrayPtr(pkt.data, (size_t)0), // TODO: get the header + kj::arrayPtr(pkt.data, pkt.size)); + + counter++; + } + av_packet_unref(&pkt); + return ret; +} diff --git a/system/loggerd/encoder/ffmpeg_encoder.h b/system/loggerd/encoder/ffmpeg_encoder.h new file mode 100644 index 0000000000..cd5ac1e13a --- /dev/null +++ b/system/loggerd/encoder/ffmpeg_encoder.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +#include "system/loggerd/encoder/encoder.h" +#include "system/loggerd/loggerd.h" + +class FfmpegEncoder : public VideoEncoder { +public: + FfmpegEncoder(const EncoderInfo &encoder_info, int in_width, int in_height); + ~FfmpegEncoder(); + int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra); + void encoder_open(); + void encoder_close(); + +private: + int segment_num = -1; + int counter = 0; + bool is_open = false; + + AVCodecContext *codec_ctx; + AVFrame *frame = NULL; + std::vector convert_buf; + std::vector downscale_buf; +}; diff --git a/system/loggerd/encoder/jpeg_encoder.cc b/system/loggerd/encoder/jpeg_encoder.cc new file mode 100644 index 0000000000..6bb946157c --- /dev/null +++ b/system/loggerd/encoder/jpeg_encoder.cc @@ -0,0 +1,105 @@ +#include "system/loggerd/encoder/jpeg_encoder.h" + +#include +#include + +JpegEncoder::JpegEncoder(const std::string &pusblish_name, int width, int height) + : publish_name(pusblish_name), thumbnail_width(width), thumbnail_height(height) { + yuv_buffer.resize((thumbnail_width * ((thumbnail_height + 15) & ~15) * 3) / 2); + pm = std::make_unique(std::vector{pusblish_name.c_str()}); +} + +JpegEncoder::~JpegEncoder() { + if (out_buffer) { + free(out_buffer); + } +} + +void JpegEncoder::pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra) { + generateThumbnail(buf->y, buf->uv, buf->width, buf->height, buf->stride); + + MessageBuilder msg; + auto thumbnaild = msg.initEvent().initThumbnail(); + thumbnaild.setFrameId(extra.frame_id); + thumbnaild.setTimestampEof(extra.timestamp_eof); + thumbnaild.setThumbnail({out_buffer, out_size}); + + pm->send(publish_name.c_str(), msg); +} + +void JpegEncoder::generateThumbnail(const uint8_t *y_addr, const uint8_t *uv_addr, int width, int height, int stride) { + int downscale = width / thumbnail_width; + assert(downscale * thumbnail_height == height); + + // make the buffer big enough. jpeg_write_raw_data requires 16-pixels aligned height to be used. + uint8_t *y_plane = yuv_buffer.data(); + uint8_t *u_plane = y_plane + thumbnail_width * thumbnail_height; + uint8_t *v_plane = u_plane + (thumbnail_width * thumbnail_height) / 4; + { + // subsampled conversion from nv12 to yuv + for (int hy = 0; hy < thumbnail_height / 2; hy++) { + for (int hx = 0; hx < thumbnail_width / 2; hx++) { + int ix = hx * downscale + (downscale - 1) / 2; + int iy = hy * downscale + (downscale - 1) / 2; + y_plane[(hy * 2 + 0) * thumbnail_width + (hx * 2 + 0)] = y_addr[(iy * 2 + 0) * stride + ix * 2 + 0]; + y_plane[(hy * 2 + 0) * thumbnail_width + (hx * 2 + 1)] = y_addr[(iy * 2 + 0) * stride + ix * 2 + 1]; + y_plane[(hy * 2 + 1) * thumbnail_width + (hx * 2 + 0)] = y_addr[(iy * 2 + 1) * stride + ix * 2 + 0]; + y_plane[(hy * 2 + 1) * thumbnail_width + (hx * 2 + 1)] = y_addr[(iy * 2 + 1) * stride + ix * 2 + 1]; + u_plane[hy * thumbnail_width / 2 + hx] = uv_addr[iy * stride + ix * 2 + 0]; + v_plane[hy * thumbnail_width / 2 + hx] = uv_addr[iy * stride + ix * 2 + 1]; + } + } + } + + compressToJpeg(y_plane, u_plane, v_plane); +} + +void JpegEncoder::compressToJpeg(uint8_t *y_plane, uint8_t *u_plane, uint8_t *v_plane) { + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + if (out_buffer) { + free(out_buffer); + out_buffer = nullptr; + out_size = 0; + } + jpeg_mem_dest(&cinfo, &out_buffer, &out_size); + + cinfo.image_width = thumbnail_width; + cinfo.image_height = thumbnail_height; + cinfo.input_components = 3; + + jpeg_set_defaults(&cinfo); + jpeg_set_colorspace(&cinfo, JCS_YCbCr); + // configure sampling factors for yuv420. + cinfo.comp_info[0].h_samp_factor = 2; // Y + cinfo.comp_info[0].v_samp_factor = 2; + cinfo.comp_info[1].h_samp_factor = 1; // U + cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = 1; // V + cinfo.comp_info[2].v_samp_factor = 1; + cinfo.raw_data_in = TRUE; + + jpeg_set_quality(&cinfo, 50, TRUE); + jpeg_start_compress(&cinfo, TRUE); + + JSAMPROW y[16], u[8], v[8]; + JSAMPARRAY planes[3]{y, u, v}; + + for (int line = 0; line < cinfo.image_height; line += 16) { + for (int i = 0; i < 16; ++i) { + y[i] = y_plane + (line + i) * cinfo.image_width; + if (i % 2 == 0) { + int offset = (cinfo.image_width / 2) * ((i + line) / 2); + u[i / 2] = u_plane + offset; + v[i / 2] = v_plane + offset; + } + } + jpeg_write_raw_data(&cinfo, planes, 16); + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); +} diff --git a/system/loggerd/encoder/jpeg_encoder.h b/system/loggerd/encoder/jpeg_encoder.h new file mode 100644 index 0000000000..af1427c19a --- /dev/null +++ b/system/loggerd/encoder/jpeg_encoder.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "cereal/messaging/messaging.h" +#include "msgq/visionipc/visionbuf.h" + +class JpegEncoder { +public: + JpegEncoder(const std::string &pusblish_name, int width, int height); + ~JpegEncoder(); + void pushThumbnail(VisionBuf *buf, const VisionIpcBufExtra &extra); + +private: + void generateThumbnail(const uint8_t *y, const uint8_t *uv, int width, int height, int stride); + void compressToJpeg(uint8_t *y_plane, uint8_t *u_plane, uint8_t *v_plane); + + int thumbnail_width; + int thumbnail_height; + std::string publish_name; + std::vector yuv_buffer; + std::unique_ptr pm; + + // JPEG output buffer + unsigned char* out_buffer = nullptr; + unsigned long out_size = 0; +}; diff --git a/system/loggerd/encoder/v4l_encoder.cc b/system/loggerd/encoder/v4l_encoder.cc new file mode 100644 index 0000000000..6ee3af13b0 --- /dev/null +++ b/system/loggerd/encoder/v4l_encoder.cc @@ -0,0 +1,323 @@ +#include +#include +#include +#include + +#include "system/loggerd/encoder/v4l_encoder.h" +#include "common/util.h" +#include "common/timing.h" + +#include "third_party/libyuv/include/libyuv.h" +#include "third_party/linux/include/msm_media_info.h" + +// has to be in this order +#include "third_party/linux/include/v4l2-controls.h" +#include +#define V4L2_QCOM_BUF_FLAG_CODECCONFIG 0x00020000 +#define V4L2_QCOM_BUF_FLAG_EOS 0x02000000 + +/* + kernel debugging: + echo 0xff > /sys/module/videobuf2_core/parameters/debug + echo 0x7fffffff > /sys/kernel/debug/msm_vidc/debug_level + echo 0xff > /sys/devices/platform/soc/aa00000.qcom,vidc/video4linux/video33/dev_debug +*/ +const int env_debug_encoder = (getenv("DEBUG_ENCODER") != NULL) ? atoi(getenv("DEBUG_ENCODER")) : 0; + +static void dequeue_buffer(int fd, v4l2_buf_type buf_type, unsigned int *index=NULL, unsigned int *bytesused=NULL, unsigned int *flags=NULL, struct timeval *timestamp=NULL) { + v4l2_plane plane = {0}; + v4l2_buffer v4l_buf = { + .type = buf_type, + .memory = V4L2_MEMORY_USERPTR, + .m = { .planes = &plane, }, + .length = 1, + }; + util::safe_ioctl(fd, VIDIOC_DQBUF, &v4l_buf, "VIDIOC_DQBUF failed"); + + if (index) *index = v4l_buf.index; + if (bytesused) *bytesused = v4l_buf.m.planes[0].bytesused; + if (flags) *flags = v4l_buf.flags; + if (timestamp) *timestamp = v4l_buf.timestamp; + assert(v4l_buf.m.planes[0].data_offset == 0); +} + +static void queue_buffer(int fd, v4l2_buf_type buf_type, unsigned int index, VisionBuf *buf, struct timeval timestamp={}) { + v4l2_plane plane = { + .length = (unsigned int)buf->len, + .m = { .userptr = (unsigned long)buf->addr, }, + .bytesused = (uint32_t)buf->len, + .reserved = {(unsigned int)buf->fd} + }; + + v4l2_buffer v4l_buf = { + .type = buf_type, + .index = index, + .memory = V4L2_MEMORY_USERPTR, + .m = { .planes = &plane, }, + .length = 1, + .flags = V4L2_BUF_FLAG_TIMESTAMP_COPY, + .timestamp = timestamp + }; + util::safe_ioctl(fd, VIDIOC_QBUF, &v4l_buf, "VIDIOC_QBUF failed"); +} + +static void request_buffers(int fd, v4l2_buf_type buf_type, unsigned int count) { + struct v4l2_requestbuffers reqbuf = { + .type = buf_type, + .memory = V4L2_MEMORY_USERPTR, + .count = count + }; + util::safe_ioctl(fd, VIDIOC_REQBUFS, &reqbuf, "VIDIOC_REQBUFS failed"); +} + +void V4LEncoder::dequeue_handler(V4LEncoder *e) { + std::string dequeue_thread_name = "dq-"+std::string(e->encoder_info.publish_name); + util::set_thread_name(dequeue_thread_name.c_str()); + + e->segment_num++; + uint32_t idx = -1; + bool exit = false; + + // POLLIN is capture, POLLOUT is frame + struct pollfd pfd; + pfd.events = POLLIN | POLLOUT; + pfd.fd = e->fd; + + // save the header + kj::Array header; + + while (!exit) { + int rc = poll(&pfd, 1, 1000); + if (rc < 0) { + if (errno != EINTR) { + // TODO: exit encoder? + // ignore the error and keep going + LOGE("poll failed (%d - %d)", rc, errno); + } + continue; + } else if (rc == 0) { + LOGE("encoder dequeue poll timeout"); + continue; + } + + if (env_debug_encoder >= 2) { + printf("%20s poll %x at %.2f ms\n", e->encoder_info.publish_name, pfd.revents, millis_since_boot()); + } + + int frame_id = -1; + if (pfd.revents & POLLIN) { + unsigned int bytesused, flags, index; + struct timeval timestamp; + dequeue_buffer(e->fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &index, &bytesused, &flags, ×tamp); + e->buf_out[index].sync(VISIONBUF_SYNC_FROM_DEVICE); + uint8_t *buf = (uint8_t*)e->buf_out[index].addr; + int64_t ts = timestamp.tv_sec * 1000000 + timestamp.tv_usec; + + // eof packet, we exit + if (flags & V4L2_QCOM_BUF_FLAG_EOS) { + exit = true; + } else if (flags & V4L2_QCOM_BUF_FLAG_CODECCONFIG) { + // save header + header = kj::heapArray(buf, bytesused); + } else { + VisionIpcBufExtra extra = e->extras.pop(); + assert(extra.timestamp_eof/1000 == ts); // stay in sync + frame_id = extra.frame_id; + ++idx; + e->publisher_publish(e->segment_num, idx, extra, flags, header, kj::arrayPtr(buf, bytesused)); + } + + if (env_debug_encoder) { + printf("%20s got(%d) %6d bytes flags %8x idx %3d/%4d id %8d ts %ld lat %.2f ms (%lu frames free)\n", + e->encoder_info.publish_name, index, bytesused, flags, e->segment_num, idx, frame_id, ts, millis_since_boot()-(ts/1000.), e->free_buf_in.size()); + } + + // requeue the buffer + queue_buffer(e->fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, index, &e->buf_out[index]); + } + + if (pfd.revents & POLLOUT) { + unsigned int index; + dequeue_buffer(e->fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, &index); + e->free_buf_in.push(index); + } + } +} + +V4LEncoder::V4LEncoder(const EncoderInfo &encoder_info, int in_width, int in_height) + : VideoEncoder(encoder_info, in_width, in_height) { + fd = HANDLE_EINTR(open("/dev/v4l/by-path/platform-aa00000.qcom_vidc-video-index1", O_RDWR|O_NONBLOCK)); + assert(fd >= 0); + + struct v4l2_capability cap; + util::safe_ioctl(fd, VIDIOC_QUERYCAP, &cap, "VIDIOC_QUERYCAP failed"); + LOGD("opened encoder device %s %s = %d", cap.driver, cap.card, fd); + assert(strcmp((const char *)cap.driver, "msm_vidc_driver") == 0); + assert(strcmp((const char *)cap.card, "msm_vidc_venc") == 0); + + EncoderSettings encoder_settings = encoder_info.get_settings(in_width); + bool is_h265 = encoder_settings.encode_type == cereal::EncodeIndex::Type::FULL_H_E_V_C; + + struct v4l2_format fmt_out = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + .fmt = { + .pix_mp = { + // downscales are free with v4l + .width = (unsigned int)(out_width), + .height = (unsigned int)(out_height), + .pixelformat = is_h265 ? V4L2_PIX_FMT_HEVC : V4L2_PIX_FMT_H264, + .field = V4L2_FIELD_ANY, + .colorspace = V4L2_COLORSPACE_DEFAULT, + } + } + }; + util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt_out, "VIDIOC_S_FMT failed"); + + v4l2_streamparm streamparm = { + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .parm = { + .output = { + // TODO: more stuff here? we don't know + .timeperframe = { + .numerator = 1, + .denominator = (unsigned int)encoder_info.fps + } + } + } + }; + util::safe_ioctl(fd, VIDIOC_S_PARM, &streamparm, "VIDIOC_S_PARM failed"); + + struct v4l2_format fmt_in = { + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + .fmt = { + .pix_mp = { + .width = (unsigned int)in_width, + .height = (unsigned int)in_height, + .pixelformat = V4L2_PIX_FMT_NV12, + .field = V4L2_FIELD_ANY, + .colorspace = V4L2_COLORSPACE_470_SYSTEM_BG, + } + } + }; + util::safe_ioctl(fd, VIDIOC_S_FMT, &fmt_in, "VIDIOC_S_FMT failed"); + + LOGD("in buffer size %d, out buffer size %d", + fmt_in.fmt.pix_mp.plane_fmt[0].sizeimage, + fmt_out.fmt.pix_mp.plane_fmt[0].sizeimage); + + // shared ctrls + { + struct v4l2_control ctrls[] = { + { .id = V4L2_CID_MPEG_VIDEO_BITRATE, .value = encoder_settings.bitrate}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES, .value = encoder_settings.gop_size - encoder_settings.b_frames - 1}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES, .value = encoder_settings.b_frames}, + { .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE, .value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL, .value = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_PRIORITY, .value = V4L2_MPEG_VIDC_VIDEO_PRIORITY_REALTIME_DISABLE}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD, .value = 1}, + }; + for (auto ctrl : ctrls) { + util::safe_ioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL failed"); + } + } + + if (is_h265) { + struct v4l2_control ctrls[] = { + { .id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_PROFILE, .value = V4L2_MPEG_VIDC_VIDEO_HEVC_PROFILE_MAIN}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_HEVC_TIER_LEVEL, .value = V4L2_MPEG_VIDC_VIDEO_HEVC_LEVEL_HIGH_TIER_LEVEL_5}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_VUI_TIMING_INFO, .value = V4L2_MPEG_VIDC_VIDEO_VUI_TIMING_INFO_ENABLED}, + }; + for (auto ctrl : ctrls) { + util::safe_ioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL failed"); + } + } else { + struct v4l2_control ctrls[] = { + { .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, .value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH}, + { .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, .value = V4L2_MPEG_VIDEO_H264_LEVEL_UNKNOWN}, + { .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, .value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC}, + { .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL, .value = V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0}, + { .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE, .value = 0}, + { .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, .value = 0}, + { .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, .value = 0}, + { .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE, .value = 0}, + }; + for (auto ctrl : ctrls) { + util::safe_ioctl(fd, VIDIOC_S_CTRL, &ctrl, "VIDIOC_S_CTRL failed"); + } + } + + // allocate buffers + request_buffers(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, BUF_OUT_COUNT); + request_buffers(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, BUF_IN_COUNT); + + // start encoder + v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + util::safe_ioctl(fd, VIDIOC_STREAMON, &buf_type, "VIDIOC_STREAMON failed"); + buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + util::safe_ioctl(fd, VIDIOC_STREAMON, &buf_type, "VIDIOC_STREAMON failed"); + + // queue up output buffers + for (unsigned int i = 0; i < BUF_OUT_COUNT; i++) { + buf_out[i].allocate(fmt_out.fmt.pix_mp.plane_fmt[0].sizeimage); + queue_buffer(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, i, &buf_out[i]); + } + // queue up input buffers + for (unsigned int i = 0; i < BUF_IN_COUNT; i++) { + free_buf_in.push(i); + } +} + +void V4LEncoder::encoder_open() { + dequeue_handler_thread = std::thread(V4LEncoder::dequeue_handler, this); + this->is_open = true; + this->counter = 0; +} + +int V4LEncoder::encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra) { + struct timeval timestamp { + .tv_sec = (long)(extra->timestamp_eof/1000000000), + .tv_usec = (long)((extra->timestamp_eof/1000) % 1000000), + }; + + // reserve buffer + int buffer_in = free_buf_in.pop(); + + // push buffer + extras.push(*extra); + //buf->sync(VISIONBUF_SYNC_TO_DEVICE); + queue_buffer(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, buffer_in, buf, timestamp); + + return this->counter++; +} + +void V4LEncoder::encoder_close() { + if (this->is_open) { + // pop all the frames before closing, then put the buffers back + for (int i = 0; i < BUF_IN_COUNT; i++) free_buf_in.pop(); + for (int i = 0; i < BUF_IN_COUNT; i++) free_buf_in.push(i); + // no frames, stop the encoder + struct v4l2_encoder_cmd encoder_cmd = { .cmd = V4L2_ENC_CMD_STOP }; + util::safe_ioctl(fd, VIDIOC_ENCODER_CMD, &encoder_cmd, "VIDIOC_ENCODER_CMD failed"); + // join waits for V4L2_QCOM_BUF_FLAG_EOS + dequeue_handler_thread.join(); + assert(extras.empty()); + } + this->is_open = false; +} + +V4LEncoder::~V4LEncoder() { + encoder_close(); + v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + util::safe_ioctl(fd, VIDIOC_STREAMOFF, &buf_type, "VIDIOC_STREAMOFF failed"); + request_buffers(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 0); + buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + util::safe_ioctl(fd, VIDIOC_STREAMOFF, &buf_type, "VIDIOC_STREAMOFF failed"); + request_buffers(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 0); + close(fd); + + for (int i = 0; i < BUF_OUT_COUNT; i++) { + if (buf_out[i].free() != 0) { + LOGE("Failed to free buffer"); + } + } +} diff --git a/system/loggerd/encoder/v4l_encoder.h b/system/loggerd/encoder/v4l_encoder.h new file mode 100644 index 0000000000..58011d60e1 --- /dev/null +++ b/system/loggerd/encoder/v4l_encoder.h @@ -0,0 +1,31 @@ +#pragma once + +#include "common/queue.h" +#include "system/loggerd/encoder/encoder.h" + +#define BUF_IN_COUNT 7 +#define BUF_OUT_COUNT 6 + +class V4LEncoder : public VideoEncoder { +public: + V4LEncoder(const EncoderInfo &encoder_info, int in_width, int in_height); + ~V4LEncoder(); + int encode_frame(VisionBuf* buf, VisionIpcBufExtra *extra); + void encoder_open(); + void encoder_close(); + +private: + int fd; + + bool is_open = false; + int segment_num = -1; + int counter = 0; + + SafeQueue extras; + + static void dequeue_handler(V4LEncoder *e); + std::thread dequeue_handler_thread; + + VisionBuf buf_out[BUF_OUT_COUNT]; + SafeQueue free_buf_in; +}; diff --git a/system/loggerd/encoderd.cc b/system/loggerd/encoderd.cc new file mode 100644 index 0000000000..9d4b81a3f9 --- /dev/null +++ b/system/loggerd/encoderd.cc @@ -0,0 +1,173 @@ +#include + +#include "system/loggerd/loggerd.h" +#include "system/loggerd/encoder/jpeg_encoder.h" + +#ifdef __TICI__ +#include "system/loggerd/encoder/v4l_encoder.h" +#define Encoder V4LEncoder +#else +#include "system/loggerd/encoder/ffmpeg_encoder.h" +#define Encoder FfmpegEncoder +#endif + +ExitHandler do_exit; + +struct EncoderdState { + int max_waiting = 0; + + // Sync logic for startup + std::atomic encoders_ready = 0; + std::atomic start_frame_id = 0; + bool camera_ready[VISION_STREAM_WIDE_ROAD + 1] = {}; + bool camera_synced[VISION_STREAM_WIDE_ROAD + 1] = {}; +}; + +// Handle initial encoder syncing by waiting for all encoders to reach the same frame id +bool sync_encoders(EncoderdState *s, VisionStreamType cam_type, uint32_t frame_id) { + if (s->camera_synced[cam_type]) return true; + + if (s->max_waiting > 1 && s->encoders_ready != s->max_waiting) { + // add a small margin to the start frame id in case one of the encoders already dropped the next frame + update_max_atomic(s->start_frame_id, frame_id + 2); + if (std::exchange(s->camera_ready[cam_type], true) == false) { + ++s->encoders_ready; + LOGD("camera %d encoder ready", cam_type); + } + return false; + } else { + if (s->max_waiting == 1) update_max_atomic(s->start_frame_id, frame_id); + bool synced = frame_id >= s->start_frame_id; + s->camera_synced[cam_type] = synced; + if (!synced) LOGD("camera %d waiting for frame %d, cur %d", cam_type, (int)s->start_frame_id, frame_id); + return synced; + } +} + + +void encoder_thread(EncoderdState *s, const LogCameraInfo &cam_info) { + util::set_thread_name(cam_info.thread_name); + + std::vector> encoders; + VisionIpcClient vipc_client = VisionIpcClient("camerad", cam_info.stream_type, false); + + std::unique_ptr jpeg_encoder; + + int cur_seg = 0; + while (!do_exit) { + if (!vipc_client.connect(false)) { + util::sleep_for(5); + continue; + } + + // init encoders + if (encoders.empty()) { + const VisionBuf &buf_info = vipc_client.buffers[0]; + LOGW("encoder %s init %zux%zu", cam_info.thread_name, buf_info.width, buf_info.height); + assert(buf_info.width > 0 && buf_info.height > 0); + + for (const auto &encoder_info : cam_info.encoder_infos) { + auto &e = encoders.emplace_back(new Encoder(encoder_info, buf_info.width, buf_info.height)); + e->encoder_open(); + } + + // Only one thumbnail can be generated per camera stream + if (auto thumbnail_name = cam_info.encoder_infos[0].thumbnail_name) { + jpeg_encoder = std::make_unique(thumbnail_name, buf_info.width / 4, buf_info.height / 4); + } + } + + bool lagging = false; + while (!do_exit) { + VisionIpcBufExtra extra; + VisionBuf* buf = vipc_client.recv(&extra); + if (buf == nullptr) continue; + + // detect loop around and drop the frames + if (buf->get_frame_id() != extra.frame_id) { + if (!lagging) { + LOGE("encoder %s lag buffer id: %" PRIu64 " extra id: %d", cam_info.thread_name, buf->get_frame_id(), extra.frame_id); + lagging = true; + } + continue; + } + lagging = false; + + if (!sync_encoders(s, cam_info.stream_type, extra.frame_id)) { + continue; + } + if (do_exit) break; + + // do rotation if required + const int frames_per_seg = SEGMENT_LENGTH * MAIN_FPS; + if (cur_seg >= 0 && extra.frame_id >= ((cur_seg + 1) * frames_per_seg) + s->start_frame_id) { + for (auto &e : encoders) { + e->encoder_close(); + e->encoder_open(); + } + ++cur_seg; + } + + // encode a frame + for (int i = 0; i < encoders.size(); ++i) { + int out_id = encoders[i]->encode_frame(buf, &extra); + + if (out_id == -1) { + LOGE("Failed to encode frame. frame_id: %d", extra.frame_id); + } + } + + if (jpeg_encoder && (extra.frame_id % 1200 == 100)) { + jpeg_encoder->pushThumbnail(buf, extra); + } + } + } +} + +template +void encoderd_thread(const LogCameraInfo (&cameras)[N]) { + EncoderdState s; + + std::set streams; + while (!do_exit) { + streams = VisionIpcClient::getAvailableStreams("camerad", false); + if (!streams.empty()) { + break; + } + util::sleep_for(100); + } + + if (!streams.empty()) { + std::vector encoder_threads; + for (auto stream : streams) { + auto it = std::find_if(std::begin(cameras), std::end(cameras), + [stream](auto &cam) { return cam.stream_type == stream; }); + assert(it != std::end(cameras)); + ++s.max_waiting; + encoder_threads.push_back(std::thread(encoder_thread, &s, *it)); + } + + for (auto &t : encoder_threads) t.join(); + } +} + +int main(int argc, char* argv[]) { + if (!Hardware::PC()) { + int ret; + ret = util::set_realtime_priority(52); + assert(ret == 0); + ret = util::set_core_affinity({3}); + assert(ret == 0); + } + if (argc > 1) { + std::string arg1(argv[1]); + if (arg1 == "--stream") { + encoderd_thread(stream_cameras_logged); + } else { + LOGE("Argument '%s' is not supported", arg1.c_str()); + } + } else { + encoderd_thread(cameras_logged); + } + return 0; +} diff --git a/system/loggerd/logger.cc b/system/loggerd/logger.cc new file mode 100644 index 0000000000..0ebe323939 --- /dev/null +++ b/system/loggerd/logger.cc @@ -0,0 +1,202 @@ +#include "system/loggerd/logger.h" + +#include +#include +#include +#include +#include +#include + +#include "common/params.h" +#include "common/swaglog.h" +#include "common/version.h" + +// ***** log metadata ***** +kj::Array logger_build_init_data() { + uint64_t wall_time = nanos_since_epoch(); + + MessageBuilder msg; + auto init = msg.initEvent().initInitData(); + + init.setWallTimeNanos(wall_time); + init.setVersion(COMMA_VERSION); + init.setDirty(!getenv("CLEAN")); + init.setDeviceType(Hardware::get_device_type()); + + // log kernel args + std::ifstream cmdline_stream("/proc/cmdline"); + std::vector kernel_args; + std::string buf; + while (cmdline_stream >> buf) { + kernel_args.push_back(buf); + } + + auto lkernel_args = init.initKernelArgs(kernel_args.size()); + for (int i=0; i params_map = params.readAll(); + + init.setGitCommit(params_map["GitCommit"]); + init.setGitCommitDate(params_map["GitCommitDate"]); + init.setGitBranch(params_map["GitBranch"]); + init.setGitRemote(params_map["GitRemote"]); + init.setPassive(false); + init.setDongleId(params_map["DongleId"]); + + // for prebuilt branches + init.setGitSrcCommit(util::read_file("../../git_src_commit")); + init.setGitSrcCommitDate(util::read_file("../../git_src_commit_date")); + + auto lparams = init.initParams().initEntries(params_map.size()); + int j = 0; + for (auto& [key, value] : params_map) { + auto lentry = lparams[j]; + lentry.setKey(key); + if ( !(params.getKeyFlag(key) & DONT_LOG) ) { + lentry.setValue(capnp::Data::Reader((const kj::byte*)value.data(), value.size())); + } + j++; + } + + // log commands + std::vector log_commands = { + "df -h", // usage for all filesystems + }; + + auto hw_logs = Hardware::get_init_logs(); + + auto commands = init.initCommands().initEntries(log_commands.size() + hw_logs.size()); + for (int i = 0; i < log_commands.size(); i++) { + auto lentry = commands[i]; + + lentry.setKey(log_commands[i]); + + const std::string result = util::check_output(log_commands[i]); + lentry.setValue(capnp::Data::Reader((const kj::byte*)result.data(), result.size())); + } + + int i = log_commands.size(); + for (auto &[key, value] : hw_logs) { + auto lentry = commands[i]; + lentry.setKey(key); + lentry.setValue(capnp::Data::Reader((const kj::byte*)value.data(), value.size())); + i++; + } + + return capnp::messageToFlatArray(msg); +} + +std::string logger_get_identifier(std::string key) { + // a log identifier is a 32 bit counter, plus a 10 character unique ID. + // e.g. 000001a3--c20ba54385 + + Params params; + uint32_t cnt; + try { + cnt = std::stoul(params.get(key)); + } catch (std::exception &e) { + cnt = 0; + } + params.put(key, std::to_string(cnt + 1)); + + std::stringstream ss; + std::random_device rd; + std::mt19937 mt(rd()); + std::uniform_int_distribution dist(0, 15); + for (int i = 0; i < 10; ++i) { + ss << std::hex << dist(mt); + } + + return util::string_format("%08x--%s", cnt, ss.str().c_str()); +} + +std::string zstd_decompress(const std::string &in) { + ZSTD_DCtx *dctx = ZSTD_createDCtx(); + assert(dctx != nullptr); + + // Initialize input and output buffers + ZSTD_inBuffer input = {in.data(), in.size(), 0}; + + // Estimate and reserve memory for decompressed data + size_t estimatedDecompressedSize = ZSTD_getFrameContentSize(in.data(), in.size()); + if (estimatedDecompressedSize == ZSTD_CONTENTSIZE_ERROR || estimatedDecompressedSize == ZSTD_CONTENTSIZE_UNKNOWN) { + estimatedDecompressedSize = in.size() * 2; // Use a fallback size + } + + std::string decompressedData; + decompressedData.reserve(estimatedDecompressedSize); + + const size_t bufferSize = ZSTD_DStreamOutSize(); // Recommended output buffer size + std::string outputBuffer(bufferSize, '\0'); + + while (input.pos < input.size) { + ZSTD_outBuffer output = {outputBuffer.data(), bufferSize, 0}; + + size_t result = ZSTD_decompressStream(dctx, &output, &input); + if (ZSTD_isError(result)) { + break; + } + + decompressedData.append(outputBuffer.data(), output.pos); + } + + ZSTD_freeDCtx(dctx); + decompressedData.shrink_to_fit(); + return decompressedData; +} + + +static void log_sentinel(LoggerState *log, SentinelType type, int exit_signal = 0) { + MessageBuilder msg; + auto sen = msg.initEvent().initSentinel(); + sen.setType(type); + sen.setSignal(exit_signal); + log->write(msg.toBytes(), true); +} + +LoggerState::LoggerState(const std::string &log_root) { + route_name = logger_get_identifier("RouteCount"); + route_path = log_root + "/" + route_name; + init_data = logger_build_init_data(); +} + +LoggerState::~LoggerState() { + if (rlog) { + log_sentinel(this, SentinelType::END_OF_ROUTE, exit_signal); + std::remove(lock_file.c_str()); + } +} + +bool LoggerState::next() { + if (rlog) { + log_sentinel(this, SentinelType::END_OF_SEGMENT); + std::remove(lock_file.c_str()); + } + + segment_path = route_path + "--" + std::to_string(++part); + bool ret = util::create_directories(segment_path, 0775); + assert(ret == true); + + lock_file = segment_path + "/rlog.lock"; + std::ofstream{lock_file}; + + rlog.reset(new ZstdFileWriter(segment_path + "/rlog.zst", LOG_COMPRESSION_LEVEL)); + qlog.reset(new ZstdFileWriter(segment_path + "/qlog.zst", LOG_COMPRESSION_LEVEL)); + + // log init data & sentinel type. + write(init_data.asBytes(), true); + log_sentinel(this, part > 0 ? SentinelType::START_OF_SEGMENT : SentinelType::START_OF_ROUTE); + return true; +} + +void LoggerState::write(uint8_t* data, size_t size, bool in_qlog) { + rlog->write(data, size); + if (in_qlog) qlog->write(data, size); +} diff --git a/system/loggerd/logger.h b/system/loggerd/logger.h new file mode 100644 index 0000000000..18d07b5f38 --- /dev/null +++ b/system/loggerd/logger.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +#include "cereal/messaging/messaging.h" +#include "common/util.h" +#include "system/hardware/hw.h" +#include "system/loggerd/zstd_writer.h" + +constexpr int LOG_COMPRESSION_LEVEL = 10; + +typedef cereal::Sentinel::SentinelType SentinelType; + +class LoggerState { +public: + LoggerState(const std::string& log_root = Path::log_root()); + ~LoggerState(); + bool next(); + void write(uint8_t* data, size_t size, bool in_qlog); + inline int segment() const { return part; } + inline const std::string& segmentPath() const { return segment_path; } + inline const std::string& routeName() const { return route_name; } + inline void write(kj::ArrayPtr bytes, bool in_qlog) { write(bytes.begin(), bytes.size(), in_qlog); } + inline void setExitSignal(int signal) { exit_signal = signal; } + +protected: + int part = -1, exit_signal = 0; + std::string route_path, route_name, segment_path, lock_file; + kj::Array init_data; + std::unique_ptr rlog, qlog; +}; + +kj::Array logger_build_init_data(); +std::string logger_get_identifier(std::string key); +std::string zstd_decompress(const std::string &in); diff --git a/system/loggerd/loggerd.cc b/system/loggerd/loggerd.cc new file mode 100644 index 0000000000..21de1ff33f --- /dev/null +++ b/system/loggerd/loggerd.cc @@ -0,0 +1,358 @@ +#include + +#include +#include +#include +#include +#include + +#include "common/params.h" +#include "system/loggerd/encoder/encoder.h" +#include "system/loggerd/loggerd.h" +#include "system/loggerd/video_writer.h" + +ExitHandler do_exit; + +struct LoggerdState { + LoggerState logger; + std::atomic last_camera_seen_tms{0.0}; + std::atomic ready_to_rotate{0}; // count of encoders ready to rotate + int max_waiting = 0; + double last_rotate_tms = 0.; // last rotate time in ms +}; + +void logger_rotate(LoggerdState *s) { + bool ret =s->logger.next(); + assert(ret); + s->ready_to_rotate = 0; + s->last_rotate_tms = millis_since_boot(); + LOGW((s->logger.segment() == 0) ? "logging to %s" : "rotated to %s", s->logger.segmentPath().c_str()); +} + +void rotate_if_needed(LoggerdState *s) { + // all encoders ready, trigger rotation + bool all_ready = s->ready_to_rotate == s->max_waiting; + + // fallback logic to prevent extremely long segments in the case of camera, encoder, etc. malfunctions + bool timed_out = false; + double tms = millis_since_boot(); + double seg_length_secs = (tms - s->last_rotate_tms) / 1000.; + if ((seg_length_secs > SEGMENT_LENGTH) && !LOGGERD_TEST) { + // TODO: might be nice to put these reasons in the sentinel + if ((tms - s->last_camera_seen_tms) > NO_CAMERA_PATIENCE) { + timed_out = true; + LOGE("no camera packets seen. auto rotating"); + } else if (seg_length_secs > SEGMENT_LENGTH*1.2) { + timed_out = true; + LOGE("segment too long. auto rotating"); + } + } + + if (all_ready || timed_out) { + logger_rotate(s); + } +} + +struct RemoteEncoder { + std::unique_ptr writer; + int encoderd_segment_offset; + int current_segment = -1; + std::vector q; + int dropped_frames = 0; + bool recording = false; + bool marked_ready_to_rotate = false; + bool seen_first_packet = false; + bool audio_initialized = false; +}; + +size_t write_encode_data(LoggerdState *s, cereal::Event::Reader event, RemoteEncoder &re, const EncoderInfo &encoder_info) { + auto edata = (event.*(encoder_info.get_encode_data_func))(); + auto idx = edata.getIdx(); + auto flags = idx.getFlags(); + + // if we aren't recording yet, try to start, since we are in the correct segment + if (!re.recording) { + if (flags & V4L2_BUF_FLAG_KEYFRAME) { + // only create on iframe + if (re.dropped_frames) { + // this should only happen for the first segment, maybe + LOGW("%s: dropped %d non iframe packets before init", encoder_info.publish_name, re.dropped_frames); + re.dropped_frames = 0; + } + if (encoder_info.record) { + // write the header + auto header = edata.getHeader(); + re.writer->write((uint8_t *)header.begin(), header.size(), idx.getTimestampEof() / 1000, true, false); + } + re.recording = true; + } else { + // this is a sad case when we aren't recording, but don't have an iframe + // nothing we can do but drop the frame + ++re.dropped_frames; + return 0; + } + } + + // we have to be recording if we are here + assert(re.recording); + + // if we are actually writing the video file, do so + if (re.writer) { + auto data = edata.getData(); + re.writer->write((uint8_t *)data.begin(), data.size(), idx.getTimestampEof() / 1000, false, flags & V4L2_BUF_FLAG_KEYFRAME); + } + + // put it in log stream as the idx packet + MessageBuilder bmsg; + auto evt = bmsg.initEvent(event.getValid()); + evt.setLogMonoTime(event.getLogMonoTime()); + (evt.*(encoder_info.set_encode_idx_func))(idx); + auto new_msg = bmsg.toBytes(); + s->logger.write((uint8_t *)new_msg.begin(), new_msg.size(), true); // always in qlog? + return new_msg.size(); +} + +int handle_encoder_msg(LoggerdState *s, Message *msg, std::string &name, struct RemoteEncoder &re, const EncoderInfo &encoder_info) { + int bytes_count = 0; + + // extract the message + capnp::FlatArrayMessageReader cmsg(kj::ArrayPtr((capnp::word *)msg->getData(), msg->getSize() / sizeof(capnp::word))); + auto event = cmsg.getRoot(); + auto edata = (event.*(encoder_info.get_encode_data_func))(); + auto idx = edata.getIdx(); + + // encoderd can have started long before loggerd + if (!re.seen_first_packet) { + re.seen_first_packet = true; + re.encoderd_segment_offset = idx.getSegmentNum(); + LOGD("%s: has encoderd offset %d", name.c_str(), re.encoderd_segment_offset); + } + int offset_segment_num = idx.getSegmentNum() - re.encoderd_segment_offset; + + if (offset_segment_num == s->logger.segment()) { + // loggerd is now on the segment that matches this packet + + // if this is a new segment, we close any possible old segments, move to the new, and process any queued packets + if (re.current_segment != s->logger.segment()) { + // if we aren't actually recording, don't create the writer + if (encoder_info.record) { + assert(encoder_info.filename != NULL); + re.writer.reset(new VideoWriter(s->logger.segmentPath().c_str(), + encoder_info.filename, idx.getType() != cereal::EncodeIndex::Type::FULL_H_E_V_C, + edata.getWidth(), edata.getHeight(), encoder_info.fps, idx.getType())); + re.recording = false; + re.audio_initialized = false; + } + re.current_segment = s->logger.segment(); + re.marked_ready_to_rotate = false; + } + if (re.audio_initialized || !encoder_info.include_audio) { + // we are in this segment now, process any queued messages before this one + if (!re.q.empty()) { + for (auto qmsg : re.q) { + capnp::FlatArrayMessageReader reader({(capnp::word *)qmsg->getData(), qmsg->getSize() / sizeof(capnp::word)}); + bytes_count += write_encode_data(s, reader.getRoot(), re, encoder_info); + delete qmsg; + } + re.q.clear(); + } + bytes_count += write_encode_data(s, event, re, encoder_info); + delete msg; + } else if (re.q.size() > MAIN_FPS*10) { + LOGE_100("%s: dropping frame waiting for audio initialization, queue is too large", name.c_str()); + delete msg; + } else { + re.q.push_back(msg); // queue up all the new segment messages, they go in after audio is initialized + } + } else if (offset_segment_num > s->logger.segment()) { + // encoderd packet has a newer segment, this means encoderd has rolled over + if (!re.marked_ready_to_rotate) { + re.marked_ready_to_rotate = true; + ++s->ready_to_rotate; + LOGD("rotate %d -> %d ready %d/%d for %s", + s->logger.segment(), offset_segment_num, + s->ready_to_rotate.load(), s->max_waiting, name.c_str()); + } + + // TODO: define this behavior, but for now don't leak + if (re.q.size() > MAIN_FPS*10) { + LOGE_100("%s: dropping frame, queue is too large", name.c_str()); + delete msg; + } else { + // queue up all the new segment messages, they go in after the rotate + re.q.push_back(msg); + } + } else { + LOGE("%s: encoderd packet has a older segment!!! idx.getSegmentNum():%d s->logger.segment():%d re.encoderd_segment_offset:%d", + name.c_str(), idx.getSegmentNum(), s->logger.segment(), re.encoderd_segment_offset); + // free the message, it's useless. this should never happen + // actually, this can happen if you restart encoderd + re.encoderd_segment_offset = -s->logger.segment(); + delete msg; + } + + return bytes_count; +} + +void handle_preserve_segment(LoggerdState *s) { + static int prev_segment = -1; + if (s->logger.segment() == prev_segment) return; + + LOGW("preserving %s", s->logger.segmentPath().c_str()); + +#ifdef __APPLE__ + int ret = setxattr(s->logger.segmentPath().c_str(), PRESERVE_ATTR_NAME, &PRESERVE_ATTR_VALUE, 1, 0, 0); +#else + int ret = setxattr(s->logger.segmentPath().c_str(), PRESERVE_ATTR_NAME, &PRESERVE_ATTR_VALUE, 1, 0); +#endif + if (ret) { + LOGE("setxattr %s failed for %s: %s", PRESERVE_ATTR_NAME, s->logger.segmentPath().c_str(), strerror(errno)); + } + + // mark route for uploading + Params params; + std::string routes = params.get("AthenadRecentlyViewedRoutes"); + params.put("AthenadRecentlyViewedRoutes", routes + "," + s->logger.routeName()); + + prev_segment = s->logger.segment(); +} + +void loggerd_thread() { + // setup messaging + typedef struct ServiceState { + std::string name; + int counter, freq; + bool encoder, preserve_segment, record_audio; + } ServiceState; + std::unordered_map service_state; + std::unordered_map remote_encoders; + + std::unique_ptr ctx(Context::create()); + std::unique_ptr poller(Poller::create()); + + // subscribe to all socks + for (const auto& [_, it] : services) { + const bool encoder = util::ends_with(it.name, "EncodeData"); + const bool livestream_encoder = util::starts_with(it.name, "livestream"); + const bool record_audio = (it.name == "rawAudioData") && Params().getBool("RecordAudio"); + if (it.should_log || (encoder && !livestream_encoder) || record_audio) { + LOGD("logging %s", it.name.c_str()); + + SubSocket * sock = SubSocket::create(ctx.get(), it.name); + assert(sock != NULL); + poller->registerSocket(sock); + service_state[sock] = { + .name = it.name, + .counter = 0, + .freq = it.decimation, + .encoder = encoder, + .preserve_segment = (it.name == "userBookmark") || (it.name == "audioFeedback"), + .record_audio = record_audio, + }; + } + } + + LoggerdState s; + // init logger + logger_rotate(&s); + Params().put("CurrentRoute", s.logger.routeName()); + + std::map encoder_infos_dict; + std::vector encoders_with_audio; + for (const auto &cam : cameras_logged) { + for (const auto &encoder_info : cam.encoder_infos) { + encoder_infos_dict[encoder_info.publish_name] = encoder_info; + s.max_waiting++; + } + } + + for (auto &[sock, service] : service_state) { + auto it = encoder_infos_dict.find(service.name); + if (it != encoder_infos_dict.end() && it->second.include_audio) { + encoders_with_audio.push_back(&remote_encoders[sock]); + } + } + + uint64_t msg_count = 0, bytes_count = 0; + double start_ts = millis_since_boot(); + while (!do_exit) { + // poll for new messages on all sockets + for (auto sock : poller->poll(1000)) { + if (do_exit) break; + + ServiceState &service = service_state[sock]; + if (service.preserve_segment) { + handle_preserve_segment(&s); + } + + // drain socket + int count = 0; + Message *msg = nullptr; + while (!do_exit && (msg = sock->receive(true))) { + const bool in_qlog = service.freq != -1 && (service.counter++ % service.freq == 0); + + if (service.record_audio) { + capnp::FlatArrayMessageReader cmsg(kj::ArrayPtr((capnp::word *)msg->getData(), msg->getSize() / sizeof(capnp::word))); + auto event = cmsg.getRoot(); + auto audio_data = event.getRawAudioData().getData(); + auto sample_rate = event.getRawAudioData().getSampleRate(); + for (auto* encoder : encoders_with_audio) { + if (encoder && encoder->writer) { + encoder->writer->write_audio((uint8_t*)audio_data.begin(), audio_data.size(), event.getLogMonoTime() / 1000, sample_rate); + encoder->audio_initialized = true; + } + } + } + + if (service.encoder) { + s.last_camera_seen_tms = millis_since_boot(); + bytes_count += handle_encoder_msg(&s, msg, service.name, remote_encoders[sock], encoder_infos_dict[service.name]); + } else { + s.logger.write((uint8_t *)msg->getData(), msg->getSize(), in_qlog); + bytes_count += msg->getSize(); + delete msg; + } + + rotate_if_needed(&s); + + if ((++msg_count % 10000) == 0) { + double seconds = (millis_since_boot() - start_ts) / 1000.0; + LOGD("%" PRIu64 " messages, %.2f msg/sec, %.2f KB/sec", msg_count, msg_count / seconds, bytes_count * 0.001 / seconds); + } + + count++; + if (count >= 200) { + LOGD("large volume of '%s' messages", service.name.c_str()); + break; + } + } + } + } + + LOGW("closing logger"); + s.logger.setExitSignal(do_exit.signal); + + if (do_exit.power_failure) { + LOGE("power failure"); + sync(); + LOGE("sync done"); + } + + // messaging cleanup + for (auto &[sock, service] : service_state) delete sock; +} + +int main(int argc, char** argv) { + if (!Hardware::PC()) { + int ret; + ret = util::set_core_affinity({0, 1, 2, 3}); + assert(ret == 0); + // TODO: why does this impact camerad timings? + //ret = util::set_realtime_priority(1); + //assert(ret == 0); + } + + loggerd_thread(); + + return 0; +} diff --git a/system/loggerd/loggerd.h b/system/loggerd/loggerd.h new file mode 100644 index 0000000000..967caec867 --- /dev/null +++ b/system/loggerd/loggerd.h @@ -0,0 +1,170 @@ +#pragma once + +#include + +#include "cereal/messaging/messaging.h" +#include "cereal/services.h" +#include "msgq/visionipc/visionipc_client.h" +#include "system/hardware/hw.h" +#include "common/params.h" +#include "common/swaglog.h" +#include "common/util.h" + +#include "system/loggerd/logger.h" + +constexpr int MAIN_FPS = 20; +const auto MAIN_ENCODE_TYPE = Hardware::PC() ? cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS : cereal::EncodeIndex::Type::FULL_H_E_V_C; +#define NO_CAMERA_PATIENCE 500 // fall back to time-based rotation if all cameras are dead + +#define INIT_ENCODE_FUNCTIONS(encode_type) \ + .get_encode_data_func = &cereal::Event::Reader::get##encode_type##Data, \ + .set_encode_idx_func = &cereal::Event::Builder::set##encode_type##Idx, \ + .init_encode_data_func = &cereal::Event::Builder::init##encode_type##Data + +const bool LOGGERD_TEST = getenv("LOGGERD_TEST"); +const int SEGMENT_LENGTH = LOGGERD_TEST ? atoi(getenv("LOGGERD_SEGMENT_LENGTH")) : 60; + +constexpr char PRESERVE_ATTR_NAME[] = "user.preserve"; +constexpr char PRESERVE_ATTR_VALUE = '1'; + +struct EncoderSettings { + cereal::EncodeIndex::Type encode_type; + int bitrate; + int gop_size; + int b_frames = 0; // we don't use b frames + + static EncoderSettings MainEncoderSettings(int in_width) { + if (in_width <= 1344) { + return EncoderSettings{.encode_type = MAIN_ENCODE_TYPE, .bitrate = 5'000'000, .gop_size = 20}; + } else { + return EncoderSettings{.encode_type = MAIN_ENCODE_TYPE, .bitrate = 10'000'000, .gop_size = 30}; + } + } + + static EncoderSettings QcamEncoderSettings() { + return EncoderSettings{.encode_type = cereal::EncodeIndex::Type::QCAMERA_H264, .bitrate = 256'000, .gop_size = 15}; + } + + static EncoderSettings StreamEncoderSettings() { + return EncoderSettings{.encode_type = cereal::EncodeIndex::Type::QCAMERA_H264, .bitrate = 1'000'000, .gop_size = 15}; + } +}; + +class EncoderInfo { +public: + const char *publish_name; + const char *thumbnail_name = NULL; + const char *filename = NULL; + bool record = true; + bool include_audio = false; + int frame_width = -1; + int frame_height = -1; + int fps = MAIN_FPS; + std::function get_settings; + + ::cereal::EncodeData::Reader (cereal::Event::Reader::*get_encode_data_func)() const; + void (cereal::Event::Builder::*set_encode_idx_func)(::cereal::EncodeIndex::Reader); + cereal::EncodeData::Builder (cereal::Event::Builder::*init_encode_data_func)(); +}; + +class LogCameraInfo { +public: + const char *thread_name; + int fps = MAIN_FPS; + VisionStreamType stream_type; + std::vector encoder_infos; +}; + +const EncoderInfo main_road_encoder_info = { + .publish_name = "roadEncodeData", + .thumbnail_name = "thumbnail", + .filename = "fcamera.hevc", + .get_settings = [](int in_width){return EncoderSettings::MainEncoderSettings(in_width);}, + INIT_ENCODE_FUNCTIONS(RoadEncode), +}; + +const EncoderInfo main_wide_road_encoder_info = { + .publish_name = "wideRoadEncodeData", + .filename = "ecamera.hevc", + .get_settings = [](int in_width){return EncoderSettings::MainEncoderSettings(in_width);}, + INIT_ENCODE_FUNCTIONS(WideRoadEncode), +}; + +const EncoderInfo main_driver_encoder_info = { + .publish_name = "driverEncodeData", + .filename = "dcamera.hevc", + .record = Params().getBool("RecordFront"), + .get_settings = [](int in_width){return EncoderSettings::MainEncoderSettings(in_width);}, + INIT_ENCODE_FUNCTIONS(DriverEncode), +}; + +const EncoderInfo stream_road_encoder_info = { + .publish_name = "livestreamRoadEncodeData", + //.thumbnail_name = "thumbnail", + .record = false, + .get_settings = [](int){return EncoderSettings::StreamEncoderSettings();}, + INIT_ENCODE_FUNCTIONS(LivestreamRoadEncode), +}; + +const EncoderInfo stream_wide_road_encoder_info = { + .publish_name = "livestreamWideRoadEncodeData", + .record = false, + .get_settings = [](int){return EncoderSettings::StreamEncoderSettings();}, + INIT_ENCODE_FUNCTIONS(LivestreamWideRoadEncode), +}; + +const EncoderInfo stream_driver_encoder_info = { + .publish_name = "livestreamDriverEncodeData", + .record = false, + .get_settings = [](int){return EncoderSettings::StreamEncoderSettings();}, + INIT_ENCODE_FUNCTIONS(LivestreamDriverEncode), +}; + +const EncoderInfo qcam_encoder_info = { + .publish_name = "qRoadEncodeData", + .filename = "qcamera.ts", + .get_settings = [](int){return EncoderSettings::QcamEncoderSettings();}, + .frame_width = 526, + .frame_height = 330, + .include_audio = Params().getBool("RecordAudio"), + INIT_ENCODE_FUNCTIONS(QRoadEncode), +}; + +const LogCameraInfo road_camera_info{ + .thread_name = "road_cam_encoder", + .stream_type = VISION_STREAM_ROAD, + .encoder_infos = {main_road_encoder_info, qcam_encoder_info} +}; + +const LogCameraInfo wide_road_camera_info{ + .thread_name = "wide_road_cam_encoder", + .stream_type = VISION_STREAM_WIDE_ROAD, + .encoder_infos = {main_wide_road_encoder_info} +}; + +const LogCameraInfo driver_camera_info{ + .thread_name = "driver_cam_encoder", + .stream_type = VISION_STREAM_DRIVER, + .encoder_infos = {main_driver_encoder_info} +}; + +const LogCameraInfo stream_road_camera_info{ + .thread_name = "road_cam_encoder", + .stream_type = VISION_STREAM_ROAD, + .encoder_infos = {stream_road_encoder_info} +}; + +const LogCameraInfo stream_wide_road_camera_info{ + .thread_name = "wide_road_cam_encoder", + .stream_type = VISION_STREAM_WIDE_ROAD, + .encoder_infos = {stream_wide_road_encoder_info} +}; + +const LogCameraInfo stream_driver_camera_info{ + .thread_name = "driver_cam_encoder", + .stream_type = VISION_STREAM_DRIVER, + .encoder_infos = {stream_driver_encoder_info} +}; + +const LogCameraInfo cameras_logged[] = {road_camera_info, wide_road_camera_info, driver_camera_info}; +const LogCameraInfo stream_cameras_logged[] = {stream_road_camera_info, stream_wide_road_camera_info, stream_driver_camera_info}; diff --git a/system/loggerd/tests/__init__.py b/system/loggerd/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/loggerd/tests/loggerd_tests_common.py b/system/loggerd/tests/loggerd_tests_common.py new file mode 100644 index 0000000000..87c3da65c2 --- /dev/null +++ b/system/loggerd/tests/loggerd_tests_common.py @@ -0,0 +1,90 @@ +import os +import random +from pathlib import Path + + +import openpilot.system.loggerd.deleter as deleter +import openpilot.system.loggerd.uploader as uploader +from openpilot.common.params import Params +from openpilot.system.hardware.hw import Paths +from openpilot.system.loggerd.xattr_cache import setxattr + + +def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: bytes = None) -> None: + file_path.parent.mkdir(parents=True, exist_ok=True) + + if lock: + lock_path = str(file_path) + ".lock" + os.close(os.open(lock_path, os.O_CREAT | os.O_EXCL)) + + chunks = 128 + chunk_bytes = int(size_mb * 1024 * 1024 / chunks) + data = os.urandom(chunk_bytes) + + with open(file_path, "wb") as f: + for _ in range(chunks): + f.write(data) + + if upload_xattr is not None: + setxattr(str(file_path), uploader.UPLOAD_ATTR_NAME, upload_xattr) + +class MockResponse: + def __init__(self, text, status_code): + self.text = text + self.status_code = status_code + +class MockApi: + def __init__(self, dongle_id): + pass + + def get(self, *args, **kwargs): + return MockResponse('{"url": "http://localhost/does/not/exist", "headers": {}}', 200) + + def get_token(self): + return "fake-token" + +class MockApiIgnore: + def __init__(self, dongle_id): + pass + + def get(self, *args, **kwargs): + return MockResponse('', 412) + + def get_token(self): + return "fake-token" + +class UploaderTestCase: + f_type = "UNKNOWN" + + root: Path + seg_num: int + seg_format: str + seg_format2: str + seg_dir: str + + def set_ignore(self): + uploader.Api = MockApiIgnore + + def setup_method(self): + uploader.Api = MockApi + uploader.fake_upload = True + uploader.force_wifi = True + uploader.allow_sleep = False + self.seg_num = random.randint(1, 300) + self.seg_format = "00000004--0ac3964c96--{}" + self.seg_format2 = "00000005--4c4e99b08b--{}" + self.seg_dir = self.seg_format.format(self.seg_num) + + self.params = Params() + self.params.put("IsOffroad", True) + self.params.put("DongleId", "0000000000000000") + + def make_file_with_data(self, f_dir: str, fn: str, size_mb: float = .1, lock: bool = False, + upload_xattr: bytes = None, preserve_xattr: bytes = None) -> Path: + file_path = Path(Paths.log_root()) / f_dir / fn + create_random_file(file_path, size_mb, lock, upload_xattr) + + if preserve_xattr is not None: + setxattr(str(file_path.parent), deleter.PRESERVE_ATTR_NAME, preserve_xattr) + + return file_path diff --git a/system/loggerd/tests/test_deleter.py b/system/loggerd/tests/test_deleter.py new file mode 100644 index 0000000000..6222ea253b --- /dev/null +++ b/system/loggerd/tests/test_deleter.py @@ -0,0 +1,117 @@ +import time +import threading +from collections import namedtuple +from pathlib import Path +from collections.abc import Sequence + +import openpilot.system.loggerd.deleter as deleter +from openpilot.common.timeout import Timeout, TimeoutException +from openpilot.system.loggerd.tests.loggerd_tests_common import UploaderTestCase + +Stats = namedtuple("Stats", ['f_bavail', 'f_blocks', 'f_frsize']) + + +class TestDeleter(UploaderTestCase): + def fake_statvfs(self, d): + return self.fake_stats + + def setup_method(self): + self.f_type = "fcamera.hevc" + super().setup_method() + self.fake_stats = Stats(f_bavail=0, f_blocks=10, f_frsize=4096) + deleter.os.statvfs = self.fake_statvfs + + def start_thread(self): + self.end_event = threading.Event() + self.del_thread = threading.Thread(target=deleter.deleter_thread, args=[self.end_event]) + self.del_thread.daemon = True + self.del_thread.start() + + def join_thread(self): + self.end_event.set() + self.del_thread.join() + + def test_delete(self): + f_path = self.make_file_with_data(self.seg_dir, self.f_type, 1) + + self.start_thread() + + try: + with Timeout(2, "Timeout waiting for file to be deleted"): + while f_path.exists(): + time.sleep(0.01) + finally: + self.join_thread() + + def assertDeleteOrder(self, f_paths: Sequence[Path], timeout: int = 5) -> None: + deleted_order = [] + + self.start_thread() + try: + with Timeout(timeout, "Timeout waiting for files to be deleted"): + while True: + for f in f_paths: + if not f.exists() and f not in deleted_order: + deleted_order.append(f) + if len(deleted_order) == len(f_paths): + break + time.sleep(0.01) + except TimeoutException: + print("Not deleted:", [f for f in f_paths if f not in deleted_order]) + raise + finally: + self.join_thread() + + assert deleted_order == f_paths, "Files not deleted in expected order" + + def test_delete_order(self): + self.assertDeleteOrder([ + self.make_file_with_data(self.seg_format.format(0), self.f_type), + self.make_file_with_data(self.seg_format.format(1), self.f_type), + self.make_file_with_data(self.seg_format2.format(0), self.f_type), + ]) + + def test_delete_many_preserved(self): + self.assertDeleteOrder([ + self.make_file_with_data(self.seg_format.format(0), self.f_type), + self.make_file_with_data(self.seg_format.format(1), self.f_type, preserve_xattr=deleter.PRESERVE_ATTR_VALUE), + self.make_file_with_data(self.seg_format.format(2), self.f_type), + ] + [ + self.make_file_with_data(self.seg_format2.format(i), self.f_type, preserve_xattr=deleter.PRESERVE_ATTR_VALUE) + for i in range(5) + ]) + + def test_delete_last(self): + self.assertDeleteOrder([ + self.make_file_with_data(self.seg_format.format(1), self.f_type), + self.make_file_with_data(self.seg_format2.format(0), self.f_type), + self.make_file_with_data(self.seg_format.format(0), self.f_type, preserve_xattr=deleter.PRESERVE_ATTR_VALUE), + self.make_file_with_data("boot", self.seg_format[:-4]), + self.make_file_with_data("crash", self.seg_format2[:-4]), + ]) + + def test_no_delete_when_available_space(self): + f_path = self.make_file_with_data(self.seg_dir, self.f_type) + + block_size = 4096 + available = (10 * 1024 * 1024 * 1024) / block_size # 10GB free + self.fake_stats = Stats(f_bavail=available, f_blocks=10, f_frsize=block_size) + + self.start_thread() + start_time = time.monotonic() + while f_path.exists() and time.monotonic() - start_time < 2: + time.sleep(0.01) + self.join_thread() + + assert f_path.exists(), "File deleted with available space" + + def test_no_delete_with_lock_file(self): + f_path = self.make_file_with_data(self.seg_dir, self.f_type, lock=True) + + self.start_thread() + start_time = time.monotonic() + while f_path.exists() and time.monotonic() - start_time < 2: + time.sleep(0.01) + self.join_thread() + + assert f_path.exists(), "File deleted when locked" diff --git a/system/loggerd/tests/test_encoder.py b/system/loggerd/tests/test_encoder.py new file mode 100644 index 0000000000..e4dabd3df9 --- /dev/null +++ b/system/loggerd/tests/test_encoder.py @@ -0,0 +1,152 @@ +import math +import os +import pytest +import random +import shutil +import subprocess +import time +from pathlib import Path + +from parameterized import parameterized +from tqdm import trange + +from openpilot.common.params import Params +from openpilot.common.timeout import Timeout +from openpilot.system.hardware import TICI +from openpilot.system.manager.process_config import managed_processes +from openpilot.tools.lib.logreader import LogReader +from openpilot.system.hardware.hw import Paths + +SEGMENT_LENGTH = 2 +FULL_SIZE = 2507572 +def hevc_size(w): return FULL_SIZE // 2 if w <= 1344 else FULL_SIZE +CAMERAS = [ + ("fcamera.hevc", 20, hevc_size, "roadEncodeIdx"), + ("dcamera.hevc", 20, hevc_size, "driverEncodeIdx"), + ("ecamera.hevc", 20, hevc_size, "wideRoadEncodeIdx"), + ("qcamera.ts", 20, lambda x: 130000, None), +] + +# we check frame count, so we don't have to be too strict on size +FILE_SIZE_TOLERANCE = 0.7 + + +@pytest.mark.tici # TODO: all of loggerd should work on PC +class TestEncoder: + + def setup_method(self): + self._clear_logs() + os.environ["LOGGERD_TEST"] = "1" + os.environ["LOGGERD_SEGMENT_LENGTH"] = str(SEGMENT_LENGTH) + + def teardown_method(self): + self._clear_logs() + + def _clear_logs(self): + if os.path.exists(Paths.log_root()): + shutil.rmtree(Paths.log_root()) + + def _get_latest_segment_path(self): + last_route = sorted(Path(Paths.log_root()).iterdir())[-1] + return os.path.join(Paths.log_root(), last_route) + + # TODO: this should run faster than real time + @parameterized.expand([(True, ), (False, )]) + def test_log_rotation(self, record_front): + Params().put_bool("RecordFront", record_front) + + managed_processes['sensord'].start() + managed_processes['loggerd'].start() + managed_processes['encoderd'].start() + + time.sleep(1.0) + managed_processes['camerad'].start() + + num_segments = int(os.getenv("SEGMENTS", random.randint(2, 8))) + + # wait for loggerd to make the dir for first segment + route_prefix_path = None + with Timeout(int(SEGMENT_LENGTH*3)): + while route_prefix_path is None: + try: + route_prefix_path = self._get_latest_segment_path().rsplit("--", 1)[0] + except Exception: + time.sleep(0.1) + + def check_seg(i): + # check each camera file size + counts = [] + first_frames = [] + for camera, fps, size_lambda, encode_idx_name in CAMERAS: + if not record_front and "dcamera" in camera: + continue + + file_path = f"{route_prefix_path}--{i}/{camera}" + + # check file exists + assert os.path.exists(file_path), f"segment #{i}: '{file_path}' missing" + + # TODO: this ffprobe call is really slow + # get width and check frame count + cmd = f"ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets,width -of csv=p=0 {file_path}" + if TICI: + cmd = "LD_LIBRARY_PATH=/usr/local/lib " + cmd + + expected_frames = fps * SEGMENT_LENGTH + probe = subprocess.check_output(cmd, shell=True, encoding='utf8').split('\n')[0].strip().split(',') + frame_width, frame_count = int(probe[0]), int(probe[1]) + counts.append(frame_count) + + assert frame_count == expected_frames, \ + f"segment #{i}: {camera} failed frame count check: expected {expected_frames}, got {frame_count}" + + # sanity check file size + file_size = os.path.getsize(file_path) + target_size = size_lambda(frame_width) + assert math.isclose(file_size, target_size, rel_tol=FILE_SIZE_TOLERANCE), \ + f"{file_path} size {file_size} isn't close to target size {target_size}" + + # Check encodeIdx + if encode_idx_name is not None: + rlog_path = f"{route_prefix_path}--{i}/rlog.zst" + msgs = [m for m in LogReader(rlog_path) if m.which() == encode_idx_name] + encode_msgs = [getattr(m, encode_idx_name) for m in msgs] + + valid = [m.valid for m in msgs] + segment_idxs = [m.segmentId for m in encode_msgs] + encode_idxs = [m.encodeId for m in encode_msgs] + frame_idxs = [m.frameId for m in encode_msgs] + + # Check frame count + assert frame_count == len(segment_idxs) + assert frame_count == len(encode_idxs) + + # Check for duplicates or skips + assert 0 == segment_idxs[0] + assert len(set(segment_idxs)) == len(segment_idxs) + + assert all(valid) + + assert expected_frames * i == encode_idxs[0] + first_frames.append(frame_idxs[0]) + assert len(set(encode_idxs)) == len(encode_idxs) + + assert 1 == len(set(first_frames)) + + if TICI: + expected_frames = fps * SEGMENT_LENGTH + assert min(counts) == expected_frames + shutil.rmtree(f"{route_prefix_path}--{i}") + + try: + for i in trange(num_segments): + # poll for next segment + with Timeout(int(SEGMENT_LENGTH*10), error_msg=f"timed out waiting for segment {i}"): + while Path(f"{route_prefix_path}--{i+1}") not in Path(Paths.log_root()).iterdir(): + time.sleep(0.1) + check_seg(i) + finally: + managed_processes['loggerd'].stop() + managed_processes['encoderd'].stop() + managed_processes['camerad'].stop() + managed_processes['sensord'].stop() diff --git a/system/loggerd/tests/test_logger.cc b/system/loggerd/tests/test_logger.cc new file mode 100644 index 0000000000..40a45a68d5 --- /dev/null +++ b/system/loggerd/tests/test_logger.cc @@ -0,0 +1,75 @@ +#include "catch2/catch.hpp" +#include "system/loggerd/logger.h" + +typedef cereal::Sentinel::SentinelType SentinelType; + +void verify_segment(const std::string &route_path, int segment, int max_segment, int required_event_cnt) { + const std::string segment_path = route_path + "--" + std::to_string(segment); + SentinelType begin_sentinel = segment == 0 ? SentinelType::START_OF_ROUTE : SentinelType::START_OF_SEGMENT; + SentinelType end_sentinel = segment == max_segment - 1 ? SentinelType::END_OF_ROUTE : SentinelType::END_OF_SEGMENT; + + REQUIRE(!util::file_exists(segment_path + "/rlog.lock")); + for (const char *fn : {"/rlog.zst", "/qlog.zst"}) { + const std::string log_file = segment_path + fn; + std::string log = util::read_file(log_file); + REQUIRE(!log.empty()); + std::string decompressed_log = zstd_decompress(log); + int event_cnt = 0, i = 0; + kj::ArrayPtr words((capnp::word *)decompressed_log.data(), decompressed_log.size() / sizeof(capnp::word)); + while (words.size() > 0) { + try { + capnp::FlatArrayMessageReader reader(words); + auto event = reader.getRoot(); + words = kj::arrayPtr(reader.getEnd(), words.end()); + if (i == 0) { + REQUIRE(event.which() == cereal::Event::INIT_DATA); + } else if (i == 1) { + REQUIRE(event.which() == cereal::Event::SENTINEL); + REQUIRE(event.getSentinel().getType() == begin_sentinel); + REQUIRE(event.getSentinel().getSignal() == 0); + } else if (words.size() > 0) { + REQUIRE(event.which() == cereal::Event::CLOCKS); + ++event_cnt; + } else { + // the last event must be SENTINEL + REQUIRE(event.which() == cereal::Event::SENTINEL); + REQUIRE(event.getSentinel().getType() == end_sentinel); + REQUIRE(event.getSentinel().getSignal() == (end_sentinel == SentinelType::END_OF_ROUTE ? 1 : 0)); + } + ++i; + } catch (const kj::Exception &ex) { + INFO("failed parse " << i << " exception :" << ex.getDescription()); + REQUIRE(0); + break; + } + } + REQUIRE(event_cnt == required_event_cnt); + } +} + +void write_msg(LoggerState *logger) { + MessageBuilder msg; + msg.initEvent().initClocks(); + logger->write(msg.toBytes(), true); +} + +TEST_CASE("logger") { + const int segment_cnt = 100; + const std::string log_root = "/tmp/test_logger"; + system(("rm " + log_root + " -rf").c_str()); + std::string route_name; + { + LoggerState logger(log_root); + route_name = logger.routeName(); + for (int i = 0; i < segment_cnt; ++i) { + REQUIRE(logger.next()); + REQUIRE(util::file_exists(logger.segmentPath() + "/rlog.lock")); + REQUIRE(logger.segment() == i); + write_msg(&logger); + } + logger.setExitSignal(1); + } + for (int i = 0; i < segment_cnt; ++i) { + verify_segment(log_root + "/" + route_name, i, segment_cnt, 1); + } +} diff --git a/system/loggerd/tests/test_loggerd.py b/system/loggerd/tests/test_loggerd.py new file mode 100644 index 0000000000..c6a4b12e63 --- /dev/null +++ b/system/loggerd/tests/test_loggerd.py @@ -0,0 +1,324 @@ +import numpy as np +import os +import re +import random +import string +import subprocess +import time +from collections import defaultdict +from pathlib import Path +import pytest + +import cereal.messaging as messaging +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.common.timeout import Timeout +from openpilot.system.hardware.hw import Paths +from openpilot.system.loggerd.xattr_cache import getxattr +from openpilot.system.loggerd.deleter import PRESERVE_ATTR_NAME, PRESERVE_ATTR_VALUE +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.version import get_version +from openpilot.tools.lib.helpers import RE +from openpilot.tools.lib.logreader import LogReader +from msgq.visionipc import VisionIpcServer, VisionStreamType +from openpilot.common.transformations.camera import DEVICE_CAMERAS + +SentinelType = log.Sentinel.SentinelType + +CEREAL_SERVICES = [f for f in log.Event.schema.union_fields if f in SERVICE_LIST + and SERVICE_LIST[f].should_log and "encode" not in f.lower()] + + +class TestLoggerd: + def _get_latest_log_dir(self): + log_dirs = sorted(Path(Paths.log_root()).iterdir(), key=lambda f: f.stat().st_mtime) + return log_dirs[-1] + + def _get_log_dir(self, x): + for l in x.splitlines(): + for p in l.split(' '): + path = Path(p.strip()) + if path.is_dir(): + return path + return None + + def _get_log_fn(self, x): + for l in x.splitlines(): + for p in l.split(' '): + path = Path(p.strip()) + if path.is_file(): + return path + return None + + def _gen_bootlog(self): + with Timeout(5): + out = subprocess.check_output("./bootlog", cwd=os.path.join(BASEDIR, "system/loggerd"), encoding='utf-8') + + log_fn = self._get_log_fn(out) + + # check existence + assert log_fn is not None + + return log_fn + + def _check_init_data(self, msgs): + msg = msgs[0] + assert msg.which() == 'initData' + + def _check_sentinel(self, msgs, route): + start_type = SentinelType.startOfRoute if route else SentinelType.startOfSegment + assert msgs[1].sentinel.type == start_type + + end_type = SentinelType.endOfRoute if route else SentinelType.endOfSegment + assert msgs[-1].sentinel.type == end_type + + def _publish_random_messages(self, services: list[str]) -> dict[str, list]: + pm = messaging.PubMaster(services) + + managed_processes["loggerd"].start() + for s in services: + assert pm.wait_for_readers_to_update(s, timeout=5) + + sent_msgs = defaultdict(list) + for _ in range(random.randint(2, 10) * 100): + for s in services: + try: + m = messaging.new_message(s) + except Exception: + m = messaging.new_message(s, random.randint(2, 10)) + pm.send(s, m) + sent_msgs[s].append(m) + + for s in services: + assert pm.wait_for_readers_to_update(s, timeout=5) + managed_processes["loggerd"].stop() + + return sent_msgs + + def _publish_camera_and_audio_messages(self, num_segs=1, segment_length=5): + d = DEVICE_CAMERAS[("tici", "ar0231")] + streams = [ + (VisionStreamType.VISION_STREAM_ROAD, (d.fcam.width, d.fcam.height, 2048 * 2346, 2048, 2048 * 1216), "roadCameraState"), + (VisionStreamType.VISION_STREAM_DRIVER, (d.dcam.width, d.dcam.height, 2048 * 2346, 2048, 2048 * 1216), "driverCameraState"), + (VisionStreamType.VISION_STREAM_WIDE_ROAD, (d.ecam.width, d.ecam.height, 2048 * 2346, 2048, 2048 * 1216), "wideRoadCameraState"), + ] + + pm = messaging.PubMaster([s for _, _, s in streams] + ["rawAudioData"]) + vipc_server = VisionIpcServer("camerad") + for stream_type, frame_spec, _ in streams: + vipc_server.create_buffers_with_sizes(stream_type, 40, *(frame_spec)) + vipc_server.start_listener() + + os.environ["LOGGERD_TEST"] = "1" + os.environ["LOGGERD_SEGMENT_LENGTH"] = str(segment_length) + managed_processes["loggerd"].start() + managed_processes["encoderd"].start() + assert pm.wait_for_readers_to_update("roadCameraState", timeout=5) + + fps = 20 + for n in range(1, int(num_segs * segment_length * fps) + 1): + # send video + for stream_type, frame_spec, state in streams: + dat = np.empty(frame_spec[2], dtype=np.uint8) + vipc_server.send(stream_type, dat[:].flatten().tobytes(), n, n / fps, n / fps) + + camera_state = messaging.new_message(state) + frame = getattr(camera_state, state) + frame.frameId = n + pm.send(state, camera_state) + + # send audio + msg = messaging.new_message('rawAudioData') + msg.rawAudioData.data = bytes(800 * 2) # 800 samples of int16 + msg.rawAudioData.sampleRate = 16000 + pm.send('rawAudioData', msg) + + for _, _, state in streams: + assert pm.wait_for_readers_to_update(state, timeout=5, dt=0.001) + + managed_processes["loggerd"].stop() + managed_processes["encoderd"].stop() + + def test_init_data_values(self): + os.environ["CLEAN"] = random.choice(["0", "1"]) + + dongle = ''.join(random.choice(string.printable) for n in range(random.randint(1, 100))) + fake_params = [ + # param, initData field, value + ("DongleId", "dongleId", dongle), + ("GitCommit", "gitCommit", "commit"), + ("GitCommitDate", "gitCommitDate", "date"), + ("GitBranch", "gitBranch", "branch"), + ("GitRemote", "gitRemote", "remote"), + ] + params = Params() + for k, _, v in fake_params: + params.put(k, v) + params.put("AccessToken", "abc") + + lr = list(LogReader(str(self._gen_bootlog()))) + initData = lr[0].initData + + assert initData.dirty != bool(os.environ["CLEAN"]) + assert initData.version == get_version() + + if os.path.isfile("/proc/cmdline"): + with open("/proc/cmdline") as f: + assert list(initData.kernelArgs) == f.read().strip().split(" ") + + with open("/proc/version") as f: + assert initData.kernelVersion == f.read() + + # check params + logged_params = {entry.key: entry.value for entry in initData.params.entries} + expected_params = {k for k, _, __ in fake_params} | {'AccessToken', 'BootCount'} + assert set(logged_params.keys()) == expected_params, set(logged_params.keys()) ^ expected_params + assert logged_params['AccessToken'] == b'', f"DONT_LOG param value was logged: {repr(logged_params['AccessToken'])}" + for param_key, initData_key, v in fake_params: + assert getattr(initData, initData_key) == v + assert logged_params[param_key].decode() == v + + @pytest.mark.xdist_group("camera_encoder_tests") # setting xdist group ensures tests are run in same worker, prevents encoderd from crashing + def test_rotation(self): + Params().put("RecordFront", True) + + expected_files = {"rlog.zst", "qlog.zst", "qcamera.ts", "fcamera.hevc", "dcamera.hevc", "ecamera.hevc"} + + num_segs = random.randint(2, 3) + length = random.randint(4, 5) # H264 encoder uses 40 lookahead frames and does B-frame reordering, so minimum 3 seconds before qcam output + + self._publish_camera_and_audio_messages(num_segs=num_segs, segment_length=length) + + route_path = str(self._get_latest_log_dir()).rsplit("--", 1)[0] + for n in range(num_segs): + p = Path(f"{route_path}--{n}") + logged = {f.name for f in p.iterdir() if f.is_file()} + diff = logged ^ expected_files + assert len(diff) == 0, f"didn't get all expected files. seg={n} {route_path=}, {diff=}\n{logged=} {expected_files=}" + + def test_bootlog(self): + # generate bootlog with fake launch log + launch_log = ''.join(str(random.choice(string.printable)) for _ in range(100)) + with open("/tmp/launch_log", "w") as f: + f.write(launch_log) + + bootlog_path = self._gen_bootlog() + lr = list(LogReader(str(bootlog_path))) + + # check length + assert len(lr) == 2 # boot + initData + + self._check_init_data(lr) + + # check msgs + bootlog_msgs = [m for m in lr if m.which() == 'boot'] + assert len(bootlog_msgs) == 1 + + # sanity check values + boot = bootlog_msgs.pop().boot + assert abs(boot.wallTimeNanos - time.time_ns()) < 5*1e9 # within 5s + assert boot.launchLog == launch_log + + for fn in ["console-ramoops", "pmsg-ramoops-0"]: + path = Path(os.path.join("/sys/fs/pstore/", fn)) + if path.is_file(): + with open(path, "rb") as f: + expected_val = f.read() + bootlog_val = [e.value for e in boot.pstore.entries if e.key == fn][0] + assert expected_val == bootlog_val + + # next one should increment by one + bl1 = re.match(RE.LOG_ID_V2, bootlog_path.name) + bl2 = re.match(RE.LOG_ID_V2, self._gen_bootlog().name) + assert bl1.group('uid') != bl2.group('uid') + assert int(bl1.group('count')) == 0 and int(bl2.group('count')) == 1 + + def test_qlog(self): + qlog_services = [s for s in CEREAL_SERVICES if SERVICE_LIST[s].decimation is not None] + no_qlog_services = [s for s in CEREAL_SERVICES if SERVICE_LIST[s].decimation is None] + + services = random.sample(qlog_services, random.randint(2, min(10, len(qlog_services)))) + \ + random.sample(no_qlog_services, random.randint(2, min(10, len(no_qlog_services)))) + sent_msgs = self._publish_random_messages(services) + + qlog_path = os.path.join(self._get_latest_log_dir(), "qlog.zst") + lr = list(LogReader(qlog_path)) + + # check initData and sentinel + self._check_init_data(lr) + self._check_sentinel(lr, True) + + recv_msgs = defaultdict(list) + for m in lr: + recv_msgs[m.which()].append(m) + + for s, msgs in sent_msgs.items(): + recv_cnt = len(recv_msgs[s]) + + if s in no_qlog_services: + # check services with no specific decimation aren't in qlog + assert recv_cnt == 0, f"got {recv_cnt} {s} msgs in qlog" + else: + # check logged message count matches decimation + expected_cnt = (len(msgs) - 1) // SERVICE_LIST[s].decimation + 1 + assert recv_cnt == expected_cnt, f"expected {expected_cnt} msgs for {s}, got {recv_cnt}" + + def test_rlog(self): + services = random.sample(CEREAL_SERVICES, random.randint(5, 10)) + sent_msgs = self._publish_random_messages(services) + + lr = list(LogReader(os.path.join(self._get_latest_log_dir(), "rlog.zst"))) + + # check initData and sentinel + self._check_init_data(lr) + self._check_sentinel(lr, True) + + # check all messages were logged and in order + lr = lr[2:-1] # slice off initData and both sentinels + for m in lr: + sent = sent_msgs[m.which()].pop(0) + sent.clear_write_flag() + assert sent.to_bytes() == m.as_builder().to_bytes() + + def test_preserving_bookmarked_segments(self): + services = set(random.sample(CEREAL_SERVICES, random.randint(5, 10))) | {"userBookmark"} + self._publish_random_messages(services) + + segment_dir = self._get_latest_log_dir() + assert getxattr(segment_dir, PRESERVE_ATTR_NAME) == PRESERVE_ATTR_VALUE + + def test_not_preserving_nonbookmarked_segments(self): + services = set(random.sample(CEREAL_SERVICES, random.randint(5, 10))) - {"userBookmark", "audioFeedback"} + self._publish_random_messages(services) + + segment_dir = self._get_latest_log_dir() + assert getxattr(segment_dir, PRESERVE_ATTR_NAME) is None + + @pytest.mark.xdist_group("camera_encoder_tests") # setting xdist group ensures tests are run in same worker, prevents encoderd from crashing + @pytest.mark.parametrize("record_front", [True, False]) + def test_record_front(self, record_front): + params = Params() + params.put_bool("RecordFront", record_front) + + self._publish_camera_and_audio_messages() + + dcamera_hevc_exists = os.path.exists(os.path.join(self._get_latest_log_dir(), 'dcamera.hevc')) + assert dcamera_hevc_exists == record_front + + @pytest.mark.xdist_group("camera_encoder_tests") # setting xdist group ensures tests are run in same worker, prevents encoderd from crashing + @pytest.mark.parametrize("record_audio", [True, False]) + def test_record_audio(self, record_audio): + params = Params() + params.put_bool("RecordAudio", record_audio) + + self._publish_camera_and_audio_messages() + + qcamera_ts_path = os.path.join(self._get_latest_log_dir(), 'qcamera.ts') + ffprobe_cmd = f"ffprobe -i {qcamera_ts_path} -show_streams -select_streams a -loglevel error" + has_audio_stream = subprocess.run(ffprobe_cmd, shell=True, capture_output=True).stdout.strip() != b'' + assert has_audio_stream == record_audio + + raw_audio_in_rlog = any(m.which() == 'rawAudioData' for m in LogReader(os.path.join(self._get_latest_log_dir(), 'rlog.zst'))) + assert raw_audio_in_rlog == record_audio diff --git a/system/loggerd/tests/test_runner.cc b/system/loggerd/tests/test_runner.cc new file mode 100644 index 0000000000..62bf7476a1 --- /dev/null +++ b/system/loggerd/tests/test_runner.cc @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/system/loggerd/tests/test_uploader.py b/system/loggerd/tests/test_uploader.py new file mode 100644 index 0000000000..961a8aa36f --- /dev/null +++ b/system/loggerd/tests/test_uploader.py @@ -0,0 +1,184 @@ +import os +import time +import threading +import logging +import json +from pathlib import Path +from openpilot.system.hardware.hw import Paths + +from openpilot.common.swaglog import cloudlog +from openpilot.system.loggerd.uploader import main, UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE + +from openpilot.system.loggerd.tests.loggerd_tests_common import UploaderTestCase + + +class FakeLogHandler(logging.Handler): + def __init__(self): + logging.Handler.__init__(self) + self.reset() + + def reset(self): + self.upload_order = list() + self.upload_ignored = list() + + def emit(self, record): + try: + j = json.loads(record.getMessage()) + if j["event"] == "upload_success": + self.upload_order.append(j["key"]) + if j["event"] == "upload_ignored": + self.upload_ignored.append(j["key"]) + except Exception: + pass + +log_handler = FakeLogHandler() +cloudlog.addHandler(log_handler) + + +class TestUploader(UploaderTestCase): + def setup_method(self): + super().setup_method() + log_handler.reset() + + def start_thread(self): + self.end_event = threading.Event() + self.up_thread = threading.Thread(target=main, args=[self.end_event]) + self.up_thread.daemon = True + self.up_thread.start() + + def join_thread(self): + self.end_event.set() + self.up_thread.join() + + def gen_files(self, lock=False, xattr: bytes = None, boot=True) -> list[Path]: + f_paths = [] + for t in ["qlog", "rlog", "dcamera.hevc", "fcamera.hevc"]: + f_paths.append(self.make_file_with_data(self.seg_dir, t, 1, lock=lock, upload_xattr=xattr)) + + if boot: + f_paths.append(self.make_file_with_data("boot", f"{self.seg_dir}", 1, lock=lock, upload_xattr=xattr)) + return f_paths + + def gen_order(self, seg1: list[int], seg2: list[int], boot=True) -> list[str]: + keys = [] + if boot: + keys += [f"boot/{self.seg_format.format(i)}.zst" for i in seg1] + keys += [f"boot/{self.seg_format2.format(i)}.zst" for i in seg2] + keys += [f"{self.seg_format.format(i)}/qlog.zst" for i in seg1] + keys += [f"{self.seg_format2.format(i)}/qlog.zst" for i in seg2] + return keys + + def test_upload(self): + self.gen_files(lock=False) + + self.start_thread() + # allow enough time that files could upload twice if there is a bug in the logic + time.sleep(1) + self.join_thread() + + exp_order = self.gen_order([self.seg_num], []) + + assert len(log_handler.upload_ignored) == 0, "Some files were ignored" + assert not len(log_handler.upload_order) < len(exp_order), "Some files failed to upload" + assert not len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice" + for f_path in exp_order: + assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded" + + assert log_handler.upload_order == exp_order, "Files uploaded in wrong order" + + def test_upload_with_wrong_xattr(self): + self.gen_files(lock=False, xattr=b'0') + + self.start_thread() + # allow enough time that files could upload twice if there is a bug in the logic + time.sleep(1) + self.join_thread() + + exp_order = self.gen_order([self.seg_num], []) + + assert len(log_handler.upload_ignored) == 0, "Some files were ignored" + assert not len(log_handler.upload_order) < len(exp_order), "Some files failed to upload" + assert not len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice" + for f_path in exp_order: + assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded" + + assert log_handler.upload_order == exp_order, "Files uploaded in wrong order" + + def test_upload_ignored(self): + self.set_ignore() + self.gen_files(lock=False) + + self.start_thread() + # allow enough time that files could upload twice if there is a bug in the logic + time.sleep(1) + self.join_thread() + + exp_order = self.gen_order([self.seg_num], []) + + assert len(log_handler.upload_order) == 0, "Some files were not ignored" + assert not len(log_handler.upload_ignored) < len(exp_order), "Some files failed to ignore" + assert not len(log_handler.upload_ignored) > len(exp_order), "Some files were ignored twice" + for f_path in exp_order: + assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not ignored" + + assert log_handler.upload_ignored == exp_order, "Files ignored in wrong order" + + def test_upload_files_in_create_order(self): + seg1_nums = [0, 1, 2, 10, 20] + for i in seg1_nums: + self.seg_dir = self.seg_format.format(i) + self.gen_files(boot=False) + seg2_nums = [5, 50, 51] + for i in seg2_nums: + self.seg_dir = self.seg_format2.format(i) + self.gen_files(boot=False) + + exp_order = self.gen_order(seg1_nums, seg2_nums, boot=False) + + self.start_thread() + # allow enough time that files could upload twice if there is a bug in the logic + time.sleep(1) + self.join_thread() + + assert len(log_handler.upload_ignored) == 0, "Some files were ignored" + assert not len(log_handler.upload_order) < len(exp_order), "Some files failed to upload" + assert not len(log_handler.upload_order) > len(exp_order), "Some files were uploaded twice" + for f_path in exp_order: + assert os.getxattr((Path(Paths.log_root()) / f_path).with_suffix(""), UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE, "All files not uploaded" + + assert log_handler.upload_order == exp_order, "Files uploaded in wrong order" + + def test_no_upload_with_lock_file(self): + self.start_thread() + + time.sleep(0.25) + f_paths = self.gen_files(lock=True, boot=False) + + # allow enough time that files should have been uploaded if they would be uploaded + time.sleep(1) + self.join_thread() + + for f_path in f_paths: + fn = f_path.with_suffix(f_path.suffix.replace(".zst", "")) + uploaded = UPLOAD_ATTR_NAME in os.listxattr(fn) and os.getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE + assert not uploaded, "File upload when locked" + + def test_no_upload_with_xattr(self): + self.gen_files(lock=False, xattr=UPLOAD_ATTR_VALUE) + + self.start_thread() + # allow enough time that files could upload twice if there is a bug in the logic + time.sleep(1) + self.join_thread() + + assert len(log_handler.upload_order) == 0, "File uploaded again" + + def test_clear_locks_on_startup(self): + f_paths = self.gen_files(lock=True, boot=False) + self.start_thread() + time.sleep(0.25) + self.join_thread() + + for f_path in f_paths: + lock_path = f_path.with_suffix(f_path.suffix + ".lock") + assert not lock_path.is_file(), "File lock not cleared on startup" diff --git a/system/loggerd/tests/test_zstd_writer.cc b/system/loggerd/tests/test_zstd_writer.cc new file mode 100644 index 0000000000..479e866a14 --- /dev/null +++ b/system/loggerd/tests/test_zstd_writer.cc @@ -0,0 +1,44 @@ +#include + +#include +#include +#include + +#include "common/util.h" +#include "system/loggerd/logger.h" +#include "system/loggerd/zstd_writer.h" + +TEST_CASE("ZstdFileWriter writes and compresses data correctly in loops", "[ZstdFileWriter]") { + const std::string filename = "test_zstd_file.zst"; + const int iterations = 100; + const size_t dataSize = 1024; + + std::string totalTestData; + + // Step 1: Write compressed data to file in a loop + { + ZstdFileWriter writer(filename, LOG_COMPRESSION_LEVEL); + // Write various data sizes including edge cases + std::vector testSizes = {dataSize, 1, 0, dataSize * 2}; // Normal, minimal, empty, large + for (int i = 0; i < iterations; ++i) { + size_t currentSize = testSizes[i % testSizes.size()]; + std::string testData = util::random_string(currentSize); + totalTestData.append(testData); + + writer.write((void *)testData.c_str(), testData.size()); + } + } + + // Step 2: Decompress the file and verify the data + auto compressedContent = util::read_file(filename); + REQUIRE(compressedContent.size() > 0); + REQUIRE(compressedContent.size() < totalTestData.size()); + std::string decompressedData = zstd_decompress(compressedContent); + + // Step 3: Verify that the decompressed data matches the original accumulated data + REQUIRE(decompressedData.size() == totalTestData.size()); + REQUIRE(std::memcmp(decompressedData.data(), totalTestData.c_str(), totalTestData.size()) == 0); + + // Clean up the test file + std::remove(filename.c_str()); +} diff --git a/system/loggerd/tests/vidc_debug.sh b/system/loggerd/tests/vidc_debug.sh new file mode 100755 index 0000000000..7471f2ab08 --- /dev/null +++ b/system/loggerd/tests/vidc_debug.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -e + +cd /sys/kernel/debug/tracing +echo "" > trace +echo 1 > tracing_on +echo 1 > /sys/kernel/debug/tracing/events/msm_vidc/enable + +echo 0xff > /sys/module/videobuf2_core/parameters/debug +echo 0x7fffffff > /sys/kernel/debug/msm_vidc/debug_level +echo 0xff > /sys/devices/platform/soc/aa00000.qcom,vidc/video4linux/video33/dev_debug + +cat /sys/kernel/debug/tracing/trace_pipe diff --git a/system/loggerd/uploader.py b/system/loggerd/uploader.py new file mode 100755 index 0000000000..38fc0e9209 --- /dev/null +++ b/system/loggerd/uploader.py @@ -0,0 +1,273 @@ +#!/usr/bin/env python3 +import json +import os +import random +import requests +import threading +import time +import traceback +import datetime +from collections.abc import Iterator + +from cereal import log +import cereal.messaging as messaging +from openpilot.common.api import Api +from openpilot.common.file_helpers import get_upload_stream +from openpilot.common.params import Params +from openpilot.common.realtime import set_core_affinity +from openpilot.system.hardware.hw import Paths +from openpilot.system.loggerd.xattr_cache import getxattr, setxattr +from openpilot.common.swaglog import cloudlog + +NetworkType = log.DeviceState.NetworkType +UPLOAD_ATTR_NAME = 'user.upload' +UPLOAD_ATTR_VALUE = b'1' + +MAX_UPLOAD_SIZES = { + "qlog": 25*1e6, # can't be too restrictive here since we use qlogs to find + # bugs, including ones that can cause massive log sizes + "qcam": 5*1e6, +} + +allow_sleep = bool(os.getenv("UPLOADER_SLEEP", "1")) +force_wifi = os.getenv("FORCEWIFI") is not None +fake_upload = os.getenv("FAKEUPLOAD") is not None + + +class FakeRequest: + def __init__(self): + self.headers = {"Content-Length": "0"} + + +class FakeResponse: + def __init__(self): + self.status_code = 200 + self.request = FakeRequest() + + +def get_directory_sort(d: str) -> list[str]: + # ensure old format is sorted sooner + o = ["0", ] if d.startswith("2024-") else ["1", ] + return o + [s.rjust(10, '0') for s in d.rsplit('--', 1)] + +def listdir_by_creation(d: str) -> list[str]: + if not os.path.isdir(d): + return [] + + try: + paths = [f for f in os.listdir(d) if os.path.isdir(os.path.join(d, f))] + paths = sorted(paths, key=get_directory_sort) + return paths + except OSError: + cloudlog.exception("listdir_by_creation failed") + return [] + +def clear_locks(root: str) -> None: + for logdir in os.listdir(root): + path = os.path.join(root, logdir) + try: + for fname in os.listdir(path): + if fname.endswith(".lock"): + os.unlink(os.path.join(path, fname)) + except OSError: + cloudlog.exception("clear_locks failed") + + +class Uploader: + def __init__(self, dongle_id: str, root: str): + self.dongle_id = dongle_id + self.api = Api(dongle_id) + self.root = root + + self.params = Params() + + # stats for last successfully uploaded file + self.last_filename = "" + + self.immediate_folders = ["crash/", "boot/"] + self.immediate_priority = {"qlog": 0, "qlog.zst": 0, "qcamera.ts": 1} + + def list_upload_files(self, metered: bool) -> Iterator[tuple[str, str, str]]: + r = self.params.get("AthenadRecentlyViewedRoutes") + requested_routes = [] if r is None else [route for route in r.split(",") if route] + + for logdir in listdir_by_creation(self.root): + path = os.path.join(self.root, logdir) + try: + names = os.listdir(path) + except OSError: + continue + + if any(name.endswith(".lock") for name in names): + continue + + for name in sorted(names, key=lambda n: self.immediate_priority.get(n, 1000)): + key = os.path.join(logdir, name) + fn = os.path.join(path, name) + # skip files already uploaded + try: + ctime = os.path.getctime(fn) + is_uploaded = getxattr(fn, UPLOAD_ATTR_NAME) == UPLOAD_ATTR_VALUE + except OSError: + cloudlog.event("uploader_getxattr_failed", key=key, fn=fn) + # deleter could have deleted, so skip + continue + if is_uploaded: + continue + + # limit uploading on metered connections + if metered: + dt = datetime.timedelta(hours=12) + if logdir in self.immediate_folders and (datetime.datetime.now() - datetime.datetime.fromtimestamp(ctime)) < dt: + continue + + if name == "qcamera.ts" and not any(logdir.startswith(r.split('|')[-1]) for r in requested_routes): + continue + + yield name, key, fn + + def next_file_to_upload(self, metered: bool) -> tuple[str, str, str] | None: + upload_files = list(self.list_upload_files(metered)) + + for name, key, fn in upload_files: + if any(f in fn for f in self.immediate_folders): + return name, key, fn + + for name, key, fn in upload_files: + if name in self.immediate_priority: + return name, key, fn + + return None + + def do_upload(self, key: str, fn: str): + url_resp = self.api.get("v1.4/" + self.dongle_id + "/upload_url/", timeout=10, path=key, access_token=self.api.get_token()) + if url_resp.status_code == 412: + return url_resp + + url_resp_json = json.loads(url_resp.text) + url = url_resp_json['url'] + headers = url_resp_json['headers'] + cloudlog.debug("upload_url v1.4 %s %s", url, str(headers)) + + if fake_upload: + return FakeResponse() + + stream = None + try: + compress = key.endswith('.zst') and not fn.endswith('.zst') + stream, _ = get_upload_stream(fn, compress) + response = requests.put(url, data=stream, headers=headers, timeout=10) + return response + finally: + if stream: + stream.close() + + def upload(self, name: str, key: str, fn: str, network_type: int, metered: bool) -> bool: + try: + sz = os.path.getsize(fn) + except OSError: + cloudlog.exception("upload: getsize failed") + return False + + cloudlog.event("upload_start", key=key, fn=fn, sz=sz, network_type=network_type, metered=metered) + + if sz == 0: + # tag files of 0 size as uploaded + success = True + elif name in MAX_UPLOAD_SIZES and sz > MAX_UPLOAD_SIZES[name]: + cloudlog.event("uploader_too_large", key=key, fn=fn, sz=sz) + success = True + else: + start_time = time.monotonic() + + stat = None + last_exc = None + try: + stat = self.do_upload(key, fn) + except Exception as e: + last_exc = (e, traceback.format_exc()) + + if stat is not None and stat.status_code in (200, 201, 401, 403, 412): + self.last_filename = fn + dt = time.monotonic() - start_time + if stat.status_code == 412: + cloudlog.event("upload_ignored", key=key, fn=fn, sz=sz, network_type=network_type, metered=metered) + else: + content_length = int(stat.request.headers.get("Content-Length", 0)) + speed = (content_length / 1e6) / dt + cloudlog.event("upload_success", key=key, fn=fn, sz=sz, content_length=content_length, + network_type=network_type, metered=metered, speed=speed) + success = True + else: + success = False + cloudlog.event("upload_failed", stat=stat, exc=last_exc, key=key, fn=fn, sz=sz, network_type=network_type, metered=metered) + + if success: + # tag file as uploaded + try: + setxattr(fn, UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE) + except OSError: + cloudlog.event("uploader_setxattr_failed", exc=last_exc, key=key, fn=fn, sz=sz) + + return success + + + def step(self, network_type: int, metered: bool) -> bool | None: + d = self.next_file_to_upload(metered) + if d is None: + return None + + name, key, fn = d + + # qlogs and bootlogs need to be compressed before uploading + if key.endswith(('qlog', 'rlog')) or (key.startswith('boot/') and not key.endswith('.zst')): + key += ".zst" + + return self.upload(name, key, fn, network_type, metered) + + +def main(exit_event: threading.Event = None) -> None: + if exit_event is None: + exit_event = threading.Event() + + try: + set_core_affinity([0, 1, 2, 3]) + except Exception: + cloudlog.exception("failed to set core affinity") + + clear_locks(Paths.log_root()) + + params = Params() + dongle_id = params.get("DongleId") + + if dongle_id is None: + cloudlog.info("uploader missing dongle_id") + raise Exception("uploader can't start without dongle id") + + sm = messaging.SubMaster(['deviceState']) + uploader = Uploader(dongle_id, Paths.log_root()) + + backoff = 0.1 + while not exit_event.is_set(): + sm.update(0) + offroad = params.get_bool("IsOffroad") + network_type = sm['deviceState'].networkType if not force_wifi else NetworkType.wifi + if network_type == NetworkType.none: + if allow_sleep: + time.sleep(60 if offroad else 5) + continue + + success = uploader.step(sm['deviceState'].networkType.raw, sm['deviceState'].networkMetered) + if success is None: + backoff = 60 if offroad else 5 + elif success: + backoff = 0.1 + else: + cloudlog.info("upload backoff %r", backoff) + backoff = min(backoff*2, 120) + if allow_sleep: + time.sleep(backoff + random.uniform(0, backoff)) + + +if __name__ == "__main__": + main() diff --git a/system/loggerd/video_writer.cc b/system/loggerd/video_writer.cc new file mode 100644 index 0000000000..1b47a8fceb --- /dev/null +++ b/system/loggerd/video_writer.cc @@ -0,0 +1,234 @@ +#include + +#include "system/loggerd/video_writer.h" +#include "common/swaglog.h" +#include "common/util.h" + +VideoWriter::VideoWriter(const char *path, const char *filename, bool remuxing, int width, int height, int fps, cereal::EncodeIndex::Type codec) + : remuxing(remuxing) { + vid_path = util::string_format("%s/%s", path, filename); + lock_path = util::string_format("%s/%s.lock", path, filename); + + int lock_fd = HANDLE_EINTR(open(lock_path.c_str(), O_RDWR | O_CREAT, 0664)); + assert(lock_fd >= 0); + close(lock_fd); + + LOGD("encoder_open %s remuxing:%d", this->vid_path.c_str(), this->remuxing); + if (this->remuxing) { + bool raw = (codec == cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS); + avformat_alloc_output_context2(&this->ofmt_ctx, NULL, raw ? "matroska" : NULL, this->vid_path.c_str()); + assert(this->ofmt_ctx); + + // set codec correctly. needed? + assert(codec != cereal::EncodeIndex::Type::FULL_H_E_V_C); + const AVCodec *avcodec = avcodec_find_encoder(raw ? AV_CODEC_ID_FFVHUFF : AV_CODEC_ID_H264); + assert(avcodec); + + this->codec_ctx = avcodec_alloc_context3(avcodec); + assert(this->codec_ctx); + this->codec_ctx->width = width; + this->codec_ctx->height = height; + this->codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; + this->codec_ctx->time_base = (AVRational){ 1, fps }; + + if (codec == cereal::EncodeIndex::Type::BIG_BOX_LOSSLESS) { + // without this, there's just noise + int err = avcodec_open2(this->codec_ctx, avcodec, NULL); + assert(err >= 0); + } + + this->out_stream = avformat_new_stream(this->ofmt_ctx, raw ? avcodec : NULL); + assert(this->out_stream); + + int err = avio_open(&this->ofmt_ctx->pb, this->vid_path.c_str(), AVIO_FLAG_WRITE); + assert(err >= 0); + + } else { + this->of = util::safe_fopen(this->vid_path.c_str(), "wb"); + assert(this->of); + } +} + +void VideoWriter::initialize_audio(int sample_rate) { + assert(this->ofmt_ctx->oformat->audio_codec != AV_CODEC_ID_NONE); // check output format supports audio streams + const AVCodec *audio_avcodec = avcodec_find_encoder(AV_CODEC_ID_AAC); + assert(audio_avcodec); + this->audio_codec_ctx = avcodec_alloc_context3(audio_avcodec); + assert(this->audio_codec_ctx); + this->audio_codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + this->audio_codec_ctx->sample_rate = sample_rate; + #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) // FFmpeg 5.1+ + av_channel_layout_default(&this->audio_codec_ctx->ch_layout, 1); + #else + this->audio_codec_ctx->channel_layout = AV_CH_LAYOUT_MONO; + #endif + this->audio_codec_ctx->bit_rate = 32000; + this->audio_codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + this->audio_codec_ctx->time_base = (AVRational){1, audio_codec_ctx->sample_rate}; + int err = avcodec_open2(this->audio_codec_ctx, audio_avcodec, NULL); + assert(err >= 0); + av_log_set_level(AV_LOG_WARNING); // hide "QAvg" info msgs at the end of every segment + + this->audio_stream = avformat_new_stream(this->ofmt_ctx, NULL); + assert(this->audio_stream); + err = avcodec_parameters_from_context(this->audio_stream->codecpar, this->audio_codec_ctx); + assert(err >= 0); + + this->audio_frame = av_frame_alloc(); + assert(this->audio_frame); + this->audio_frame->format = this->audio_codec_ctx->sample_fmt; + #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) // FFmpeg 5.1+ + av_channel_layout_copy(&this->audio_frame->ch_layout, &this->audio_codec_ctx->ch_layout); + #else + this->audio_frame->channel_layout = this->audio_codec_ctx->channel_layout; + #endif + this->audio_frame->sample_rate = this->audio_codec_ctx->sample_rate; + this->audio_frame->nb_samples = this->audio_codec_ctx->frame_size; + err = av_frame_get_buffer(this->audio_frame, 0); + assert(err >= 0); +} + +void VideoWriter::write(uint8_t *data, int len, long long timestamp, bool codecconfig, bool keyframe) { + if (of && data) { + size_t written = util::safe_fwrite(data, 1, len, of); + if (written != len) { + LOGE("failed to write file.errno=%d", errno); + } + } + + if (remuxing) { + if (codecconfig) { + if (len > 0) { + codec_ctx->extradata = (uint8_t*)av_mallocz(len + AV_INPUT_BUFFER_PADDING_SIZE); + codec_ctx->extradata_size = len; + memcpy(codec_ctx->extradata, data, len); + } + int err = avcodec_parameters_from_context(out_stream->codecpar, codec_ctx); + assert(err >= 0); + // if there is an audio stream, it must be initialized before this point + err = avformat_write_header(ofmt_ctx, NULL); + assert(err >= 0); + header_written = true; + } else { + // input timestamps are in microseconds + AVRational in_timebase = {1, 1000000}; + + AVPacket pkt = {}; + pkt.data = data; + pkt.size = len; + pkt.stream_index = this->out_stream->index; + + enum AVRounding rnd = static_cast(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); + pkt.pts = pkt.dts = av_rescale_q_rnd(timestamp, in_timebase, ofmt_ctx->streams[0]->time_base, rnd); + pkt.duration = av_rescale_q(50*1000, in_timebase, ofmt_ctx->streams[0]->time_base); + + if (keyframe) { + pkt.flags |= AV_PKT_FLAG_KEY; + } + + // TODO: can use av_write_frame for non raw? + int err = av_interleaved_write_frame(ofmt_ctx, &pkt); + if (err < 0) { LOGW("ts encoder write issue len: %d ts: %lld", len, timestamp); } + + av_packet_unref(&pkt); + } + } +} + +void VideoWriter::write_audio(uint8_t *data, int len, long long timestamp, int sample_rate) { + if (!remuxing) return; + if (!audio_initialized) { + initialize_audio(sample_rate); + audio_initialized = true; + } + if (!audio_codec_ctx) return; + // sync logMonoTime of first audio packet with the timestampEof of first video packet + if (audio_pts == 0) { + audio_pts = (timestamp * audio_codec_ctx->sample_rate) / 1000000ULL; + } + + // convert s16le samples to fltp and add to buffer + const int16_t *raw_samples = reinterpret_cast(data); + int sample_count = len / sizeof(int16_t); + constexpr float normalizer = 1.0f / 32768.0f; + + const size_t max_buffer_size = sample_rate * 10; // 10 seconds + if (audio_buffer.size() + sample_count > max_buffer_size) { + size_t samples_to_drop = (audio_buffer.size() + sample_count) - max_buffer_size; + LOGE("Audio buffer overflow, dropping %zu oldest samples", samples_to_drop); + audio_buffer.erase(audio_buffer.begin(), audio_buffer.begin() + samples_to_drop); + audio_pts += samples_to_drop; + } + + // Add new samples to the buffer + const size_t original_size = audio_buffer.size(); + audio_buffer.resize(original_size + sample_count); + std::transform(raw_samples, raw_samples + sample_count, audio_buffer.begin() + original_size, + [](int16_t sample) { return sample * normalizer; }); + + if (!header_written) return; // header not written yet, process audio frame after header is written + while (audio_buffer.size() >= audio_codec_ctx->frame_size) { + audio_frame->pts = audio_pts; + float *f_samples = reinterpret_cast(audio_frame->data[0]); + std::copy(audio_buffer.begin(), audio_buffer.begin() + audio_codec_ctx->frame_size, f_samples); + audio_buffer.erase(audio_buffer.begin(), audio_buffer.begin() + audio_codec_ctx->frame_size); + encode_and_write_audio_frame(audio_frame); + } +} + +void VideoWriter::encode_and_write_audio_frame(AVFrame* frame) { + if (!remuxing || !audio_codec_ctx) return; + int send_result = avcodec_send_frame(audio_codec_ctx, frame); // encode frame + if (send_result >= 0) { + AVPacket *pkt = av_packet_alloc(); + while (avcodec_receive_packet(audio_codec_ctx, pkt) == 0) { + av_packet_rescale_ts(pkt, audio_codec_ctx->time_base, audio_stream->time_base); + pkt->stream_index = audio_stream->index; + + int err = av_interleaved_write_frame(ofmt_ctx, pkt); // write encoded frame + if (err < 0) { + LOGW("AUDIO: Write frame failed - error: %d", err); + } + av_packet_unref(pkt); + } + av_packet_free(&pkt); + } else { + LOGW("AUDIO: Failed to send audio frame to encoder: %d", send_result); + } + audio_pts += audio_codec_ctx->frame_size; +} + +void VideoWriter::process_remaining_audio() { + // Process remaining audio samples by padding with silence + if (audio_buffer.size() > 0 && audio_buffer.size() < audio_codec_ctx->frame_size) { + audio_buffer.resize(audio_codec_ctx->frame_size, 0.0f); + + // Encode final frame + audio_frame->pts = audio_pts; + float *f_samples = reinterpret_cast(audio_frame->data[0]); + std::copy(audio_buffer.begin(), audio_buffer.end(), f_samples); + encode_and_write_audio_frame(audio_frame); + } +} + +VideoWriter::~VideoWriter() { + if (this->remuxing) { + if (this->audio_codec_ctx) { + process_remaining_audio(); + encode_and_write_audio_frame(NULL); // flush encoder + avcodec_free_context(&this->audio_codec_ctx); + } + int err = av_write_trailer(this->ofmt_ctx); + if (err != 0) LOGE("av_write_trailer failed %d", err); + avcodec_free_context(&this->codec_ctx); + if (this->audio_frame) av_frame_free(&this->audio_frame); + err = avio_closep(&this->ofmt_ctx->pb); + if (err != 0) LOGE("avio_closep failed %d", err); + avformat_free_context(this->ofmt_ctx); + } else { + util::safe_fflush(this->of); + fclose(this->of); + this->of = nullptr; + } + unlink(this->lock_path.c_str()); +} diff --git a/system/loggerd/video_writer.h b/system/loggerd/video_writer.h new file mode 100644 index 0000000000..e973c5d811 --- /dev/null +++ b/system/loggerd/video_writer.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +extern "C" { +#include +#include +} + +#include "cereal/messaging/messaging.h" + +class VideoWriter { +public: + VideoWriter(const char *path, const char *filename, bool remuxing, int width, int height, int fps, cereal::EncodeIndex::Type codec); + void write(uint8_t *data, int len, long long timestamp, bool codecconfig, bool keyframe); + void write_audio(uint8_t *data, int len, long long timestamp, int sample_rate); + + ~VideoWriter(); + +private: + void initialize_audio(int sample_rate); + void encode_and_write_audio_frame(AVFrame* frame); + void process_remaining_audio(); + + std::string vid_path, lock_path; + FILE *of = nullptr; + + AVCodecContext *codec_ctx; + AVFormatContext *ofmt_ctx; + AVStream *out_stream; + + bool audio_initialized = false; + bool header_written = false; + AVStream *audio_stream = nullptr; + AVCodecContext *audio_codec_ctx = nullptr; + AVFrame *audio_frame = nullptr; + uint64_t audio_pts = 0; + std::deque audio_buffer; + + bool remuxing; +}; diff --git a/system/loggerd/xattr_cache.py b/system/loggerd/xattr_cache.py new file mode 100644 index 0000000000..39bb172059 --- /dev/null +++ b/system/loggerd/xattr_cache.py @@ -0,0 +1,23 @@ +import errno + +import xattr + +_cached_attributes: dict[tuple, bytes | None] = {} + +def getxattr(path: str, attr_name: str) -> bytes | None: + key = (path, attr_name) + if key not in _cached_attributes: + try: + response = xattr.getxattr(path, attr_name) + except OSError as e: + # ENODATA (Linux) or ENOATTR (macOS) means attribute hasn't been set + if e.errno == errno.ENODATA or (hasattr(errno, 'ENOATTR') and e.errno == errno.ENOATTR): + response = None + else: + raise + _cached_attributes[key] = response + return _cached_attributes[key] + +def setxattr(path: str, attr_name: str, attr_value: bytes) -> None: + _cached_attributes.pop((path, attr_name), None) + xattr.setxattr(path, attr_name, attr_value) diff --git a/system/loggerd/zstd_writer.cc b/system/loggerd/zstd_writer.cc new file mode 100644 index 0000000000..69ca64479e --- /dev/null +++ b/system/loggerd/zstd_writer.cc @@ -0,0 +1,65 @@ + +#include "system/loggerd/zstd_writer.h" + +#include + +#include "common/util.h" + +// Constructor: Initializes compression stream and opens file +ZstdFileWriter::ZstdFileWriter(const std::string& filename, int compression_level) { + // Create the compression stream + cstream_ = ZSTD_createCStream(); + assert(cstream_); + + size_t initResult = ZSTD_initCStream(cstream_, compression_level); + assert(!ZSTD_isError(initResult)); + + input_cache_capacity_ = ZSTD_CStreamInSize(); + input_cache_.reserve(input_cache_capacity_); + output_buffer_.resize(ZSTD_CStreamOutSize()); + + file_ = util::safe_fopen(filename.c_str(), "wb"); + assert(file_ != nullptr); +} + +// Destructor: Finalizes compression and closes file +ZstdFileWriter::~ZstdFileWriter() { + flushCache(true); + util::safe_fflush(file_); + + int err = fclose(file_); + assert(err == 0); + + ZSTD_freeCStream(cstream_); +} + +// Compresses and writes data to file +void ZstdFileWriter::write(void* data, size_t size) { + // Add data to the input cache + input_cache_.insert(input_cache_.end(), (uint8_t*)data, (uint8_t*)data + size); + + // If the cache is full, compress and write to the file + if (input_cache_.size() >= input_cache_capacity_) { + flushCache(false); + } +} + +// Compress and flush the input cache to the file +void ZstdFileWriter::flushCache(bool last_chunk) { + ZSTD_inBuffer input = {input_cache_.data(), input_cache_.size(), 0}; + ZSTD_EndDirective mode = !last_chunk ? ZSTD_e_continue : ZSTD_e_end; + int finished = 0; + + do { + ZSTD_outBuffer output = {output_buffer_.data(), output_buffer_.size(), 0}; + size_t remaining = ZSTD_compressStream2(cstream_, &output, &input, mode); + assert(!ZSTD_isError(remaining)); + + size_t written = util::safe_fwrite(output_buffer_.data(), 1, output.pos, file_); + assert(written == output.pos); + + finished = last_chunk ? (remaining == 0) : (input.pos == input.size); + } while (!finished); + + input_cache_.clear(); // Clear cache after compression +} diff --git a/system/loggerd/zstd_writer.h b/system/loggerd/zstd_writer.h new file mode 100644 index 0000000000..b11deaab20 --- /dev/null +++ b/system/loggerd/zstd_writer.h @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include +#include +#include + +class ZstdFileWriter { +public: + ZstdFileWriter(const std::string &filename, int compression_level); + ~ZstdFileWriter(); + void write(void* data, size_t size); + inline void write(kj::ArrayPtr array) { write(array.begin(), array.size()); } + +private: + void flushCache(bool last_chunk); + + size_t input_cache_capacity_ = 0; + std::vector input_cache_; + std::vector output_buffer_; + ZSTD_CStream *cstream_; + FILE* file_ = nullptr; +}; diff --git a/system/logmessaged.py b/system/logmessaged.py new file mode 100755 index 0000000000..c095c26192 --- /dev/null +++ b/system/logmessaged.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +import zmq +from typing import NoReturn + +import cereal.messaging as messaging +from openpilot.common.logging_extra import SwagLogFileFormatter +from openpilot.system.hardware.hw import Paths +from openpilot.common.swaglog import get_file_handler + + +def main() -> NoReturn: + log_handler = get_file_handler() + log_handler.setFormatter(SwagLogFileFormatter(None)) + log_level = 20 # logging.INFO + + ctx = zmq.Context.instance() + sock = ctx.socket(zmq.PULL) + sock.bind(Paths.swaglog_ipc()) + + # and we publish them + log_message_sock = messaging.pub_sock('logMessage') + error_log_message_sock = messaging.pub_sock('errorLogMessage') + + try: + while True: + dat = b''.join(sock.recv_multipart()) + level = dat[0] + record = dat[1:].decode("utf-8") + if level >= log_level: + log_handler.emit(record) + + if len(record) > 2*1024*1024: + print("WARNING: log too big to publish", len(record)) + print(record[:100]) + continue + + # then we publish them + msg = messaging.new_message(None, valid=True, logMessage=record) + log_message_sock.send(msg.to_bytes()) + + if level >= 40: # logging.ERROR + msg = messaging.new_message(None, valid=True, errorLogMessage=record) + error_log_message_sock.send(msg.to_bytes()) + finally: + sock.close() + ctx.term() + + # can hit this if interrupted during a rollover + try: + log_handler.close() + except ValueError: + pass + +if __name__ == "__main__": + main() diff --git a/system/manager/__init__.py b/system/manager/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/manager/build.py b/system/manager/build.py new file mode 100755 index 0000000000..b6153ee8a4 --- /dev/null +++ b/system/manager/build.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +import os +import subprocess +from pathlib import Path + +# NOTE: Do NOT import anything here that needs be built (e.g. params) +from openpilot.common.basedir import BASEDIR +from openpilot.common.spinner import Spinner +from openpilot.common.text_window import TextWindow +from openpilot.common.swaglog import cloudlog, add_file_handler +from openpilot.system.hardware import HARDWARE, AGNOS +from openpilot.system.version import get_build_metadata + +MAX_CACHE_SIZE = 4e9 if "CI" in os.environ else 2e9 +CACHE_DIR = Path("/data/scons_cache" if AGNOS else "/tmp/scons_cache") + +TOTAL_SCONS_NODES = 3275 +MAX_BUILD_PROGRESS = 100 + +def build(spinner: Spinner, dirty: bool = False, minimal: bool = False) -> None: + env = os.environ.copy() + env['SCONS_PROGRESS'] = "1" + nproc = os.cpu_count() + if nproc is None: + nproc = 2 + + extra_args = ["--minimal"] if minimal else [] + + if AGNOS: + HARDWARE.set_power_save(False) + os.sched_setaffinity(0, range(8)) # ensure we can use the isolcpus cores + + # building with all cores can result in using too + # much memory, so retry with less parallelism + compile_output: list[bytes] = [] + for n in (nproc, nproc/2, 1): + compile_output.clear() + scons: subprocess.Popen = subprocess.Popen(["scons", f"-j{int(n)}", "--cache-populate", *extra_args], cwd=BASEDIR, env=env, stderr=subprocess.PIPE) + assert scons.stderr is not None + + # Read progress from stderr and update spinner + while scons.poll() is None: + try: + line = scons.stderr.readline() + if line is None: + continue + line = line.rstrip() + + prefix = b'progress: ' + if line.startswith(prefix): + i = int(line[len(prefix):]) + spinner.update_progress(MAX_BUILD_PROGRESS * min(1., i / TOTAL_SCONS_NODES), 100.) + elif len(line): + compile_output.append(line) + print(line.decode('utf8', 'replace')) + except Exception: + pass + + if scons.returncode == 0: + break + + if scons.returncode != 0: + # Read remaining output + if scons.stderr is not None: + compile_output += scons.stderr.read().split(b'\n') + + # Build failed log errors + error_s = b"\n".join(compile_output).decode('utf8', 'replace') + add_file_handler(cloudlog) + cloudlog.error("scons build failed\n" + error_s) + + # Show TextWindow + spinner.close() + if not os.getenv("CI"): + with TextWindow("openpilot failed to build\n \n" + error_s) as t: + t.wait_for_exit() + exit(1) + + # enforce max cache size + cache_files = [f for f in CACHE_DIR.rglob('*') if f.is_file()] + cache_files.sort(key=lambda f: f.stat().st_mtime) + cache_size = sum(f.stat().st_size for f in cache_files) + for f in cache_files: + if cache_size < MAX_CACHE_SIZE: + break + cache_size -= f.stat().st_size + f.unlink() + + +if __name__ == "__main__": + spinner = Spinner() + spinner.update_progress(0, 100) + build_metadata = get_build_metadata() + build(spinner, build_metadata.openpilot.is_dirty, minimal = AGNOS) diff --git a/system/manager/helpers.py b/system/manager/helpers.py new file mode 100644 index 0000000000..047d0ac2d6 --- /dev/null +++ b/system/manager/helpers.py @@ -0,0 +1,67 @@ +import errno +import fcntl +import os +import sys +import pathlib +import shutil +import signal +import subprocess +import tempfile +import threading + +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params + +def unblock_stdout() -> None: + # get a non-blocking stdout + child_pid, child_pty = os.forkpty() + if child_pid != 0: # parent + + # child is in its own process group, manually pass kill signals + signal.signal(signal.SIGINT, lambda signum, frame: os.kill(child_pid, signal.SIGINT)) + signal.signal(signal.SIGTERM, lambda signum, frame: os.kill(child_pid, signal.SIGTERM)) + + fcntl.fcntl(sys.stdout, fcntl.F_SETFL, fcntl.fcntl(sys.stdout, fcntl.F_GETFL) | os.O_NONBLOCK) + + while True: + try: + dat = os.read(child_pty, 4096) + except OSError as e: + if e.errno == errno.EIO: + break + continue + + if not dat: + break + + try: + sys.stdout.write(dat.decode('utf8')) + except (OSError, UnicodeDecodeError): + pass + + # os.wait() returns a tuple with the pid and a 16 bit value + # whose low byte is the signal number and whose high byte is the exit status + exit_status = os.wait()[1] >> 8 + os._exit(exit_status) + + +def write_onroad_params(started, params): + params.put_bool("IsOnroad", started) + params.put_bool("IsOffroad", not started) + + +def save_bootlog(): + # copy current params + tmp = tempfile.mkdtemp() + params_dirname = pathlib.Path(Params().get_param_path()).name + params_dir = os.path.join(tmp, params_dirname) + shutil.copytree(Params().get_param_path(), params_dir, dirs_exist_ok=True) + + def fn(tmpdir): + env = os.environ.copy() + env['PARAMS_COPY_PATH'] = tmpdir + subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "system/loggerd"), env=env) + shutil.rmtree(tmpdir) + t = threading.Thread(target=fn, args=(tmp, )) + t.daemon = True + t.start() diff --git a/system/manager/manager.py b/system/manager/manager.py new file mode 100755 index 0000000000..36055d8635 --- /dev/null +++ b/system/manager/manager.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python3 +import datetime +import os +import signal +import sys +import time +import traceback + +from cereal import log +import cereal.messaging as messaging +import openpilot.system.sentry as sentry +from openpilot.common.params import Params, ParamKeyFlag +from openpilot.common.text_window import TextWindow +from openpilot.system.hardware import HARDWARE +from openpilot.system.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog +from openpilot.system.manager.process import ensure_running +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.athena.registration import register, UNREGISTERED_DONGLE_ID +from openpilot.common.swaglog import cloudlog, add_file_handler +from openpilot.system.version import get_build_metadata, terms_version, training_version +from openpilot.system.hardware.hw import Paths + + +def manager_init() -> None: + save_bootlog() + + build_metadata = get_build_metadata() + + params = Params() + params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START) + params.clear_all(ParamKeyFlag.CLEAR_ON_ONROAD_TRANSITION) + params.clear_all(ParamKeyFlag.CLEAR_ON_OFFROAD_TRANSITION) + params.clear_all(ParamKeyFlag.CLEAR_ON_IGNITION_ON) + if build_metadata.release_channel: + params.clear_all(ParamKeyFlag.DEVELOPMENT_ONLY) + + if params.get_bool("RecordFrontLock"): + params.put_bool("RecordFront", True) + + # set unset params to their default value + for k in params.all_keys(): + default_value = params.get_default_value(k) + if default_value is not None and params.get(k) is None: + params.put(k, default_value) + + # Create folders needed for msgq + try: + os.mkdir(Paths.shm_path()) + except FileExistsError: + pass + except PermissionError: + print(f"WARNING: failed to make {Paths.shm_path()}") + + # set params + serial = HARDWARE.get_serial() + params.put("Version", build_metadata.openpilot.version) + params.put("TermsVersion", terms_version) + params.put("TrainingVersion", training_version) + params.put("GitCommit", build_metadata.openpilot.git_commit) + params.put("GitCommitDate", build_metadata.openpilot.git_commit_date) + params.put("GitBranch", build_metadata.channel) + params.put("GitRemote", build_metadata.openpilot.git_origin) + params.put_bool("IsTestedBranch", build_metadata.tested_channel) + params.put_bool("IsReleaseBranch", build_metadata.release_channel) + params.put("HardwareSerial", serial) + + # set dongle id + reg_res = register(show_spinner=True) + if reg_res: + dongle_id = reg_res + else: + raise Exception(f"Registration failed for device {serial}") + os.environ['DONGLE_ID'] = dongle_id # Needed for swaglog + os.environ['GIT_ORIGIN'] = build_metadata.openpilot.git_normalized_origin # Needed for swaglog + os.environ['GIT_BRANCH'] = build_metadata.channel # Needed for swaglog + os.environ['GIT_COMMIT'] = build_metadata.openpilot.git_commit # Needed for swaglog + + if not build_metadata.openpilot.is_dirty: + os.environ['CLEAN'] = '1' + + # init logging + sentry.init(sentry.SentryProject.SELFDRIVE) + cloudlog.bind_global(dongle_id=dongle_id, + version=build_metadata.openpilot.version, + origin=build_metadata.openpilot.git_normalized_origin, + branch=build_metadata.channel, + commit=build_metadata.openpilot.git_commit, + dirty=build_metadata.openpilot.is_dirty, + device=HARDWARE.get_device_type()) + + # preimport all processes + for p in managed_processes.values(): + p.prepare() + + +def manager_cleanup() -> None: + # send signals to kill all procs + for p in managed_processes.values(): + p.stop(block=False) + + # ensure all are killed + for p in managed_processes.values(): + p.stop(block=True) + + cloudlog.info("everything is dead") + + +def manager_thread() -> None: + cloudlog.bind(daemon="manager") + cloudlog.info("manager start") + cloudlog.info({"environ": os.environ}) + + params = Params() + + ignore: list[str] = [] + if params.get("DongleId") in (None, UNREGISTERED_DONGLE_ID): + ignore += ["manage_athenad", "uploader"] + if os.getenv("NOBOARD") is not None: + ignore.append("pandad") + ignore += [x for x in os.getenv("BLOCK", "").split(",") if len(x) > 0] + + sm = messaging.SubMaster(['deviceState', 'carParams', 'pandaStates'], poll='deviceState') + pm = messaging.PubMaster(['managerState']) + + write_onroad_params(False, params) + ensure_running(managed_processes.values(), False, params=params, CP=sm['carParams'], not_run=ignore) + + started_prev = False + ignition_prev = False + + while True: + sm.update(1000) + + started = sm['deviceState'].started + + if started and not started_prev: + params.clear_all(ParamKeyFlag.CLEAR_ON_ONROAD_TRANSITION) + elif not started and started_prev: + params.clear_all(ParamKeyFlag.CLEAR_ON_OFFROAD_TRANSITION) + + ignition = any(ps.ignitionLine or ps.ignitionCan for ps in sm['pandaStates'] if ps.pandaType != log.PandaState.PandaType.unknown) + if ignition and not ignition_prev: + params.clear_all(ParamKeyFlag.CLEAR_ON_IGNITION_ON) + + # update onroad params, which drives pandad's safety setter thread + if started != started_prev: + write_onroad_params(started, params) + + started_prev = started + ignition_prev = ignition + + ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore) + + running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) + for p in managed_processes.values() if p.proc) + print(running) + cloudlog.debug(running) + + # send managerState + msg = messaging.new_message('managerState', valid=True) + msg.managerState.processes = [p.get_process_state_msg() for p in managed_processes.values()] + pm.send('managerState', msg) + + # kick AGNOS power monitoring watchdog + try: + if sm.all_checks(['deviceState']): + with open("/var/tmp/power_watchdog", "w") as f: + f.write(str(time.monotonic())) + except Exception: + pass + + # Exit main loop when uninstall/shutdown/reboot is needed + shutdown = False + for param in ("DoUninstall", "DoShutdown", "DoReboot"): + if params.get_bool(param): + shutdown = True + params.put("LastManagerExitReason", f"{param} {datetime.datetime.now()}") + cloudlog.warning(f"Shutting down manager - {param} set") + + if shutdown: + break + + +def main() -> None: + manager_init() + if os.getenv("PREPAREONLY") is not None: + return + + # SystemExit on sigterm + signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1)) + + try: + manager_thread() + except Exception: + traceback.print_exc() + sentry.capture_exception() + finally: + manager_cleanup() + + params = Params() + if params.get_bool("DoUninstall"): + cloudlog.warning("uninstalling") + HARDWARE.uninstall() + elif params.get_bool("DoReboot"): + cloudlog.warning("reboot") + HARDWARE.reboot() + elif params.get_bool("DoShutdown"): + cloudlog.warning("shutdown") + HARDWARE.shutdown() + + +if __name__ == "__main__": + unblock_stdout() + + try: + main() + except KeyboardInterrupt: + print("got CTRL-C, exiting") + except Exception: + add_file_handler(cloudlog) + cloudlog.exception("Manager failed to start") + + try: + managed_processes['ui'].stop() + except Exception: + pass + + # Show last 3 lines of traceback + error = traceback.format_exc(-3) + error = "Manager failed to start\n\n" + error + with TextWindow(error) as t: + t.wait_for_exit() + + raise + + # manual exit because we are forked + sys.exit(0) diff --git a/system/manager/process.py b/system/manager/process.py new file mode 100644 index 0000000000..5e86e87c76 --- /dev/null +++ b/system/manager/process.py @@ -0,0 +1,296 @@ +import importlib +import os +import signal +import struct +import time +import subprocess +from collections.abc import Callable, ValuesView +from abc import ABC, abstractmethod +from multiprocessing import Process + +from setproctitle import setproctitle + +from cereal import car, log +import cereal.messaging as messaging +import openpilot.system.sentry as sentry +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.common.swaglog import cloudlog +from openpilot.common.watchdog import WATCHDOG_FN + +ENABLE_WATCHDOG = os.getenv("NO_WATCHDOG") is None + + +def launcher(proc: str, name: str) -> None: + try: + # import the process + mod = importlib.import_module(proc) + + # rename the process + setproctitle(proc) + + # create new context since we forked + messaging.reset_context() + + # add daemon name tag to logs + cloudlog.bind(daemon=name) + sentry.set_tag("daemon", name) + + # exec the process + mod.main() + except KeyboardInterrupt: + cloudlog.warning(f"child {proc} got SIGINT") + except Exception: + # can't install the crash handler because sys.excepthook doesn't play nice + # with threads, so catch it here. + sentry.capture_exception() + raise + + +def nativelauncher(pargs: list[str], cwd: str, name: str) -> None: + os.environ['MANAGER_DAEMON'] = name + + # exec the process + os.chdir(cwd) + os.execvp(pargs[0], pargs) + + +def join_process(process: Process, timeout: float) -> None: + # Process().join(timeout) will hang due to a python 3 bug: https://bugs.python.org/issue28382 + # We have to poll the exitcode instead + t = time.monotonic() + while time.monotonic() - t < timeout and process.exitcode is None: + time.sleep(0.001) + + +class ManagerProcess(ABC): + daemon = False + sigkill = False + should_run: Callable[[bool, Params, car.CarParams], bool] + proc: Process | None = None + enabled = True + name = "" + + last_watchdog_time = 0 + watchdog_max_dt: int | None = None + watchdog_seen = False + shutting_down = False + + @abstractmethod + def prepare(self) -> None: + pass + + @abstractmethod + def start(self) -> None: + pass + + def restart(self) -> None: + self.stop(sig=signal.SIGKILL) + self.start() + + def check_watchdog(self, started: bool) -> None: + if self.watchdog_max_dt is None or self.proc is None: + return + + try: + fn = WATCHDOG_FN + str(self.proc.pid) + with open(fn, "rb") as f: + self.last_watchdog_time = struct.unpack('Q', f.read())[0] + except Exception: + pass + + dt = time.monotonic() - self.last_watchdog_time / 1e9 + + if dt > self.watchdog_max_dt: + if self.watchdog_seen and ENABLE_WATCHDOG: + cloudlog.error(f"Watchdog timeout for {self.name} (exitcode {self.proc.exitcode}) restarting ({started=})") + self.restart() + else: + self.watchdog_seen = True + + def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals = None) -> int | None: + if self.proc is None: + return None + + if self.proc.exitcode is None: + if not self.shutting_down: + cloudlog.info(f"killing {self.name}") + if sig is None: + sig = signal.SIGKILL if self.sigkill else signal.SIGINT + self.signal(sig) + self.shutting_down = True + + if not block: + return None + + join_process(self.proc, 5) + + # If process failed to die send SIGKILL + if self.proc.exitcode is None and retry: + cloudlog.info(f"killing {self.name} with SIGKILL") + self.signal(signal.SIGKILL) + self.proc.join() + + ret = self.proc.exitcode + cloudlog.info(f"{self.name} is dead with {ret}") + + if self.proc.exitcode is not None: + self.shutting_down = False + self.proc = None + + return ret + + def signal(self, sig: int) -> None: + if self.proc is None: + return + + # Don't signal if already exited + if self.proc.exitcode is not None and self.proc.pid is not None: + return + + # Can't signal if we don't have a pid + if self.proc.pid is None: + return + + cloudlog.info(f"sending signal {sig} to {self.name}") + os.kill(self.proc.pid, sig) + + def get_process_state_msg(self): + state = log.ManagerState.ProcessState.new_message() + state.name = self.name + if self.proc: + state.running = self.proc.is_alive() + state.shouldBeRunning = self.proc is not None and not self.shutting_down + state.pid = self.proc.pid or 0 + state.exitCode = self.proc.exitcode or 0 + return state + + +class NativeProcess(ManagerProcess): + def __init__(self, name, cwd, cmdline, should_run, enabled=True, sigkill=False, watchdog_max_dt=None): + self.name = name + self.cwd = cwd + self.cmdline = cmdline + self.should_run = should_run + self.enabled = enabled + self.sigkill = sigkill + self.watchdog_max_dt = watchdog_max_dt + self.launcher = nativelauncher + + def prepare(self) -> None: + pass + + def start(self) -> None: + # In case we only tried a non blocking stop we need to stop it before restarting + if self.shutting_down: + self.stop() + + if self.proc is not None: + return + + cwd = os.path.join(BASEDIR, self.cwd) + cloudlog.info(f"starting process {self.name}") + self.proc = Process(name=self.name, target=self.launcher, args=(self.cmdline, cwd, self.name)) + self.proc.start() + self.watchdog_seen = False + self.shutting_down = False + + +class PythonProcess(ManagerProcess): + def __init__(self, name, module, should_run, enabled=True, sigkill=False, watchdog_max_dt=None): + self.name = name + self.module = module + self.should_run = should_run + self.enabled = enabled + self.sigkill = sigkill + self.watchdog_max_dt = watchdog_max_dt + self.launcher = launcher + + def prepare(self) -> None: + if self.enabled: + cloudlog.info(f"preimporting {self.module}") + importlib.import_module(self.module) + + def start(self) -> None: + # In case we only tried a non blocking stop we need to stop it before restarting + if self.shutting_down: + self.stop() + + if self.proc is not None: + return + + # TODO: this is just a workaround for this tinygrad check: + # https://github.com/tinygrad/tinygrad/blob/ac9c96dae1656dc220ee4acc39cef4dd449aa850/tinygrad/device.py#L26 + name = self.name if "modeld" not in self.name else "MainProcess" + + cloudlog.info(f"starting python {self.module}") + self.proc = Process(name=name, target=self.launcher, args=(self.module, self.name)) + self.proc.start() + self.watchdog_seen = False + self.shutting_down = False + + +class DaemonProcess(ManagerProcess): + """Python process that has to stay running across manager restart. + This is used for athena so you don't lose SSH access when restarting manager.""" + def __init__(self, name, module, param_name, enabled=True): + self.name = name + self.module = module + self.param_name = param_name + self.enabled = enabled + self.params = None + + @staticmethod + def should_run(started, params, CP): + return True + + def prepare(self) -> None: + pass + + def start(self) -> None: + if self.params is None: + self.params = Params() + + pid = self.params.get(self.param_name) + if pid is not None: + try: + os.kill(int(pid), 0) + with open(f'/proc/{pid}/cmdline') as f: + if self.module in f.read(): + # daemon is running + return + except (OSError, FileNotFoundError): + # process is dead + pass + + cloudlog.info(f"starting daemon {self.name}") + proc = subprocess.Popen(['python', '-m', self.module], + stdin=open('/dev/null'), + stdout=open('/dev/null', 'w'), + stderr=open('/dev/null', 'w'), + preexec_fn=os.setpgrp) + + self.params.put(self.param_name, proc.pid) + + def stop(self, retry=True, block=True, sig=None) -> None: + pass + + +def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None, + not_run: list[str] | None=None) -> list[ManagerProcess]: + if not_run is None: + not_run = [] + + running = [] + for p in procs: + if p.enabled and p.name not in not_run and p.should_run(started, params, CP): + running.append(p) + else: + p.stop(block=False) + + p.check_watchdog(started) + + for p in running: + p.start() + + return running diff --git a/system/manager/process_config.py b/system/manager/process_config.py new file mode 100644 index 0000000000..22f159e891 --- /dev/null +++ b/system/manager/process_config.py @@ -0,0 +1,119 @@ +import os +import operator +import platform + +from cereal import car +from openpilot.common.params import Params +from openpilot.system.hardware import PC, TICI +from openpilot.system.manager.process import PythonProcess, NativeProcess, DaemonProcess + +WEBCAM = os.getenv("USE_WEBCAM") is not None + +def driverview(started: bool, params: Params, CP: car.CarParams) -> bool: + return started or params.get_bool("IsDriverViewEnabled") + +def notcar(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and CP.notCar + +def iscar(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and not CP.notCar + +def logging(started: bool, params: Params, CP: car.CarParams) -> bool: + run = (not CP.notCar) or not params.get_bool("DisableLogging") + return started and run + +def ublox_available() -> bool: + return os.path.exists('/dev/ttyHS0') and not os.path.exists('/persist/comma/use-quectel-gps') + +def ublox(started: bool, params: Params, CP: car.CarParams) -> bool: + use_ublox = ublox_available() + if use_ublox != params.get_bool("UbloxAvailable"): + params.put_bool("UbloxAvailable", use_ublox) + return started and use_ublox + +def joystick(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and params.get_bool("JoystickDebugMode") + +def not_joystick(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and not params.get_bool("JoystickDebugMode") + +def long_maneuver(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and params.get_bool("LongitudinalManeuverMode") + +def not_long_maneuver(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and not params.get_bool("LongitudinalManeuverMode") + +def qcomgps(started: bool, params: Params, CP: car.CarParams) -> bool: + return started and not ublox_available() + +def always_run(started: bool, params: Params, CP: car.CarParams) -> bool: + return True + +def only_onroad(started: bool, params: Params, CP: car.CarParams) -> bool: + return started + +def only_offroad(started: bool, params: Params, CP: car.CarParams) -> bool: + return not started + +def or_(*fns): + return lambda *args: operator.or_(*(fn(*args) for fn in fns)) + +def and_(*fns): + return lambda *args: operator.and_(*(fn(*args) for fn in fns)) + +procs = [ + DaemonProcess("manage_athenad", "system.athena.manage_athenad", "AthenadPid"), + + NativeProcess("loggerd", "system/loggerd", ["./loggerd"], logging), + NativeProcess("encoderd", "system/loggerd", ["./encoderd"], only_onroad), + NativeProcess("stream_encoderd", "system/loggerd", ["./encoderd", "--stream"], notcar), + PythonProcess("logmessaged", "system.logmessaged", always_run), + + NativeProcess("camerad", "system/camerad", ["./camerad"], driverview, enabled=not WEBCAM), + PythonProcess("webcamerad", "tools.webcam.camerad", driverview, enabled=WEBCAM), + PythonProcess("proclogd", "system.proclogd", only_onroad, enabled=platform.system() != "Darwin"), + PythonProcess("journald", "system.journald", only_onroad, platform.system() != "Darwin"), + PythonProcess("micd", "system.micd", iscar), + PythonProcess("timed", "system.timed", always_run, enabled=not PC), + + PythonProcess("modeld", "selfdrive.modeld.modeld", only_onroad), + PythonProcess("dmonitoringmodeld", "selfdrive.modeld.dmonitoringmodeld", driverview, enabled=(WEBCAM or not PC)), + + PythonProcess("sensord", "system.sensord.sensord", only_onroad, enabled=not PC), + NativeProcess("ui", "selfdrive/ui", ["./ui"], always_run, watchdog_max_dt=(5 if not PC else None)), + PythonProcess("raylib_ui", "selfdrive.ui.ui", always_run, enabled=False, watchdog_max_dt=(5 if not PC else None)), + PythonProcess("soundd", "selfdrive.ui.soundd", only_onroad), + PythonProcess("locationd", "selfdrive.locationd.locationd", only_onroad), + NativeProcess("_pandad", "selfdrive/pandad", ["./pandad"], always_run, enabled=False), + PythonProcess("calibrationd", "selfdrive.locationd.calibrationd", only_onroad), + PythonProcess("torqued", "selfdrive.locationd.torqued", only_onroad), + PythonProcess("controlsd", "selfdrive.controls.controlsd", and_(not_joystick, iscar)), + PythonProcess("joystickd", "tools.joystick.joystickd", or_(joystick, notcar)), + PythonProcess("selfdrived", "selfdrive.selfdrived.selfdrived", only_onroad), + PythonProcess("card", "selfdrive.car.card", only_onroad), + PythonProcess("deleter", "system.loggerd.deleter", always_run), + PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", driverview, enabled=(WEBCAM or not PC)), + PythonProcess("qcomgpsd", "system.qcomgpsd.qcomgpsd", qcomgps, enabled=TICI), + PythonProcess("pandad", "selfdrive.pandad.pandad", always_run), + PythonProcess("paramsd", "selfdrive.locationd.paramsd", only_onroad), + PythonProcess("lagd", "selfdrive.locationd.lagd", only_onroad), + PythonProcess("ubloxd", "system.ubloxd.ubloxd", ublox, enabled=TICI), + PythonProcess("pigeond", "system.ubloxd.pigeond", ublox, enabled=TICI), + PythonProcess("plannerd", "selfdrive.controls.plannerd", not_long_maneuver), + PythonProcess("maneuversd", "tools.longitudinal_maneuvers.maneuversd", long_maneuver), + PythonProcess("radard", "selfdrive.controls.radard", only_onroad), + PythonProcess("hardwared", "system.hardware.hardwared", always_run), + PythonProcess("tombstoned", "system.tombstoned", always_run, enabled=not PC), + PythonProcess("updated", "system.updated.updated", only_offroad, enabled=not PC), + PythonProcess("uploader", "system.loggerd.uploader", always_run), + PythonProcess("statsd", "system.statsd", always_run), + PythonProcess("feedbackd", "selfdrive.ui.feedback.feedbackd", only_onroad), + + # debug procs + NativeProcess("bridge", "cereal/messaging", ["./bridge"], notcar), + PythonProcess("webrtcd", "system.webrtc.webrtcd", notcar), + PythonProcess("webjoystick", "tools.bodyteleop.web", notcar), + PythonProcess("joystick", "tools.joystick.joystick_control", and_(joystick, iscar)), +] + +managed_processes = {p.name: p for p in procs} diff --git a/system/manager/test/__init__.py b/system/manager/test/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/manager/test/test_manager.py b/system/manager/test/test_manager.py new file mode 100644 index 0000000000..34d07c6724 --- /dev/null +++ b/system/manager/test/test_manager.py @@ -0,0 +1,81 @@ +import os +import pytest +import signal +import time + +from cereal import car +from openpilot.common.params import Params +import openpilot.system.manager.manager as manager +from openpilot.system.manager.process import ensure_running +from openpilot.system.manager.process_config import managed_processes, procs +from openpilot.system.hardware import HARDWARE + +os.environ['FAKEUPLOAD'] = "1" + +MAX_STARTUP_TIME = 3 +BLACKLIST_PROCS = ['manage_athenad', 'pandad', 'pigeond'] + + +class TestManager: + def setup_method(self): + HARDWARE.set_power_save(False) + + # ensure clean CarParams + params = Params() + params.clear_all() + + def teardown_method(self): + manager.manager_cleanup() + + def test_manager_prepare(self): + os.environ['PREPAREONLY'] = '1' + manager.main() + + def test_duplicate_procs(self): + assert len(procs) == len(managed_processes), "Duplicate process names" + + def test_blacklisted_procs(self): + # TODO: ensure there are blacklisted procs until we have a dedicated test + assert len(BLACKLIST_PROCS), "No blacklisted procs to test not_run" + + def test_set_params_with_default_value(self): + params = Params() + params.clear_all() + + os.environ['PREPAREONLY'] = '1' + manager.main() + for k in params.all_keys(): + default_value = params.get_default_value(k) + if default_value is not None: + assert params.get(k) == default_value + assert params.get("OpenpilotEnabledToggle") + assert params.get("RouteCount") == 0 + + @pytest.mark.skip("this test is flaky the way it's currently written, should be moved to test_onroad") + def test_clean_exit(self, subtests): + """ + Ensure all processes exit cleanly when stopped. + """ + HARDWARE.set_power_save(False) + manager.manager_init() + + CP = car.CarParams.new_message() + procs = ensure_running(managed_processes.values(), True, Params(), CP, not_run=BLACKLIST_PROCS) + + time.sleep(10) + + for p in procs: + with subtests.test(proc=p.name): + state = p.get_process_state_msg() + assert state.running, f"{p.name} not running" + exit_code = p.stop(retry=False) + + assert p.name not in BLACKLIST_PROCS, f"{p.name} was started" + + assert exit_code is not None, f"{p.name} failed to exit" + + # TODO: interrupted blocking read exits with 1 in cereal. use a more unique return code + exit_codes = [0, 1] + if p.sigkill: + exit_codes = [-signal.SIGKILL] + assert exit_code in exit_codes, f"{p.name} died with {exit_code}" diff --git a/system/micd.py b/system/micd.py new file mode 100755 index 0000000000..02ef82390b --- /dev/null +++ b/system/micd.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +import numpy as np +from functools import cache +import threading + +from cereal import messaging +from openpilot.common.realtime import Ratekeeper +from openpilot.common.retry import retry +from openpilot.common.swaglog import cloudlog + +RATE = 10 +FFT_SAMPLES = 1600 # 100ms +REFERENCE_SPL = 2e-5 # newtons/m^2 +SAMPLE_RATE = 16000 +SAMPLE_BUFFER = 800 # 50ms + + +@cache +def get_a_weighting_filter(): + # Calculate the A-weighting filter + # https://en.wikipedia.org/wiki/A-weighting + freqs = np.fft.fftfreq(FFT_SAMPLES, d=1 / SAMPLE_RATE) + A = 12194 ** 2 * freqs ** 4 / ((freqs ** 2 + 20.6 ** 2) * (freqs ** 2 + 12194 ** 2) * np.sqrt((freqs ** 2 + 107.7 ** 2) * (freqs ** 2 + 737.9 ** 2))) + return A / np.max(A) + + +def calculate_spl(measurements): + # https://www.engineeringtoolbox.com/sound-pressure-d_711.html + sound_pressure = np.sqrt(np.mean(measurements ** 2)) # RMS of amplitudes + if sound_pressure > 0: + sound_pressure_level = 20 * np.log10(sound_pressure / REFERENCE_SPL) # dB + else: + sound_pressure_level = 0 + return sound_pressure, sound_pressure_level + + +def apply_a_weighting(measurements: np.ndarray) -> np.ndarray: + # Generate a Hanning window of the same length as the audio measurements + measurements_windowed = measurements * np.hanning(len(measurements)) + + # Apply the A-weighting filter to the signal + return np.abs(np.fft.ifft(np.fft.fft(measurements_windowed) * get_a_weighting_filter())) + + +class Mic: + def __init__(self): + self.rk = Ratekeeper(RATE) + self.pm = messaging.PubMaster(['soundPressure', 'rawAudioData']) + + self.measurements = np.empty(0) + + self.sound_pressure = 0 + self.sound_pressure_weighted = 0 + self.sound_pressure_level_weighted = 0 + + self.lock = threading.Lock() + + def update(self): + with self.lock: + sound_pressure = self.sound_pressure + sound_pressure_weighted = self.sound_pressure_weighted + sound_pressure_level_weighted = self.sound_pressure_level_weighted + + msg = messaging.new_message('soundPressure', valid=True) + msg.soundPressure.soundPressure = float(sound_pressure) + msg.soundPressure.soundPressureWeighted = float(sound_pressure_weighted) + msg.soundPressure.soundPressureWeightedDb = float(sound_pressure_level_weighted) + + self.pm.send('soundPressure', msg) + self.rk.keep_time() + + def callback(self, indata, frames, time, status): + """ + Using amplitude measurements, calculate an uncalibrated sound pressure and sound pressure level. + Then apply A-weighting to the raw amplitudes and run the same calculations again. + + Logged A-weighted equivalents are rough approximations of the human-perceived loudness. + """ + msg = messaging.new_message('rawAudioData', valid=True) + audio_data_int_16 = (indata[:, 0] * 32767).astype(np.int16) + msg.rawAudioData.data = audio_data_int_16.tobytes() + msg.rawAudioData.sampleRate = SAMPLE_RATE + self.pm.send('rawAudioData', msg) + + with self.lock: + self.measurements = np.concatenate((self.measurements, indata[:, 0])) + + while self.measurements.size >= FFT_SAMPLES: + measurements = self.measurements[:FFT_SAMPLES] + + self.sound_pressure, _ = calculate_spl(measurements) + measurements_weighted = apply_a_weighting(measurements) + self.sound_pressure_weighted, self.sound_pressure_level_weighted = calculate_spl(measurements_weighted) + + self.measurements = self.measurements[FFT_SAMPLES:] + + @retry(attempts=7, delay=3) + def get_stream(self, sd): + # reload sounddevice to reinitialize portaudio + sd._terminate() + sd._initialize() + return sd.InputStream(channels=1, samplerate=SAMPLE_RATE, callback=self.callback, blocksize=SAMPLE_BUFFER) + + def micd_thread(self): + # sounddevice must be imported after forking processes + import sounddevice as sd + + with self.get_stream(sd) as stream: + cloudlog.info(f"micd stream started: {stream.samplerate=} {stream.channels=} {stream.dtype=} {stream.device=}, {stream.blocksize=}") + while True: + self.update() + + +def main(): + mic = Mic() + mic.micd_thread() + + +if __name__ == "__main__": + main() diff --git a/system/proclogd.py b/system/proclogd.py new file mode 100755 index 0000000000..3279425b7b --- /dev/null +++ b/system/proclogd.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +import os +from typing import NoReturn, TypedDict + +from cereal import messaging +from openpilot.common.realtime import Ratekeeper +from openpilot.common.swaglog import cloudlog + +JIFFY = os.sysconf(os.sysconf_names['SC_CLK_TCK']) +PAGE_SIZE = os.sysconf(os.sysconf_names['SC_PAGE_SIZE']) + + +def _cpu_times() -> list[dict[str, float]]: + cpu_times: list[dict[str, float]] = [] + try: + with open('/proc/stat') as f: + lines = f.readlines()[1:] + for line in lines: + if not line.startswith('cpu') or len(line) < 4 or not line[3].isdigit(): + break + parts = line.split() + cpu_times.append({ + 'cpuNum': int(parts[0][3:]), + 'user': float(parts[1]) / JIFFY, + 'nice': float(parts[2]) / JIFFY, + 'system': float(parts[3]) / JIFFY, + 'idle': float(parts[4]) / JIFFY, + 'iowait': float(parts[5]) / JIFFY, + 'irq': float(parts[6]) / JIFFY, + 'softirq': float(parts[7]) / JIFFY, + }) + except Exception: + cloudlog.exception("failed to read /proc/stat") + return cpu_times + + +def _mem_info() -> dict[str, int]: + keys = ["MemTotal:", "MemFree:", "MemAvailable:", "Buffers:", "Cached:", "Active:", "Inactive:", "Shmem:"] + info: dict[str, int] = dict.fromkeys(keys, 0) + try: + with open('/proc/meminfo') as f: + for line in f: + parts = line.split() + if parts and parts[0] in info: + info[parts[0]] = int(parts[1]) * 1024 + except Exception: + cloudlog.exception("failed to read /proc/meminfo") + return info + + +_STAT_POS = { + 'pid': 1, + 'state': 3, + 'ppid': 4, + 'utime': 14, + 'stime': 15, + 'cutime': 16, + 'cstime': 17, + 'priority': 18, + 'nice': 19, + 'num_threads': 20, + 'starttime': 22, + 'vsize': 23, + 'rss': 24, + 'processor': 39, +} + +class ProcStat(TypedDict): + name: str + pid: int + state: str + ppid: int + utime: int + stime: int + cutime: int + cstime: int + priority: int + nice: int + num_threads: int + starttime: int + vms: int + rss: int + processor: int + + +def _parse_proc_stat(stat: str) -> ProcStat | None: + open_paren = stat.find('(') + close_paren = stat.rfind(')') + if open_paren == -1 or close_paren == -1 or open_paren > close_paren: + return None + name = stat[open_paren + 1:close_paren] + stat = stat[:open_paren] + stat[open_paren:close_paren].replace(' ', '_') + stat[close_paren:] + parts = stat.split() + if len(parts) < 52: + return None + try: + return { + 'name': name, + 'pid': int(parts[_STAT_POS['pid'] - 1]), + 'state': parts[_STAT_POS['state'] - 1][0], + 'ppid': int(parts[_STAT_POS['ppid'] - 1]), + 'utime': int(parts[_STAT_POS['utime'] - 1]), + 'stime': int(parts[_STAT_POS['stime'] - 1]), + 'cutime': int(parts[_STAT_POS['cutime'] - 1]), + 'cstime': int(parts[_STAT_POS['cstime'] - 1]), + 'priority': int(parts[_STAT_POS['priority'] - 1]), + 'nice': int(parts[_STAT_POS['nice'] - 1]), + 'num_threads': int(parts[_STAT_POS['num_threads'] - 1]), + 'starttime': int(parts[_STAT_POS['starttime'] - 1]), + 'vms': int(parts[_STAT_POS['vsize'] - 1]), + 'rss': int(parts[_STAT_POS['rss'] - 1]), + 'processor': int(parts[_STAT_POS['processor'] - 1]), + } + except Exception: + cloudlog.exception("failed to parse /proc//stat") + return None + +class ProcExtra(TypedDict): + pid: int + name: str + exe: str + cmdline: list[str] + + +_proc_cache: dict[int, ProcExtra] = {} + + +def _get_proc_extra(pid: int, name: str) -> ProcExtra: + cache: ProcExtra | None = _proc_cache.get(pid) + if cache is None or cache.get('name') != name: + exe = '' + cmdline: list[str] = [] + try: + exe = os.readlink(f'/proc/{pid}/exe') + except OSError: + pass + try: + with open(f'/proc/{pid}/cmdline', 'rb') as f: + cmdline = [c.decode('utf-8', errors='replace') for c in f.read().split(b'\0') if c] + except OSError: + pass + cache = {'pid': pid, 'name': name, 'exe': exe, 'cmdline': cmdline} + _proc_cache[pid] = cache + return cache + + +def _procs() -> list[ProcStat]: + stats: list[ProcStat] = [] + for pid_str in os.listdir('/proc'): + if not pid_str.isdigit(): + continue + try: + with open(f'/proc/{pid_str}/stat') as f: + stat = f.read() + parsed = _parse_proc_stat(stat) + if parsed is not None: + stats.append(parsed) + except OSError: + continue + return stats + + +def build_proc_log_message(msg) -> None: + pl = msg.procLog + + procs = _procs() + l = pl.init('procs', len(procs)) + for i, r in enumerate(procs): + proc = l[i] + proc.pid = r['pid'] + proc.state = ord(r['state'][0]) + proc.ppid = r['ppid'] + proc.cpuUser = r['utime'] / JIFFY + proc.cpuSystem = r['stime'] / JIFFY + proc.cpuChildrenUser = r['cutime'] / JIFFY + proc.cpuChildrenSystem = r['cstime'] / JIFFY + proc.priority = r['priority'] + proc.nice = r['nice'] + proc.numThreads = r['num_threads'] + proc.startTime = r['starttime'] / JIFFY + proc.memVms = r['vms'] + proc.memRss = r['rss'] * PAGE_SIZE + proc.processor = r['processor'] + proc.name = r['name'] + + extra = _get_proc_extra(r['pid'], r['name']) + proc.exe = extra['exe'] + cmdline = proc.init('cmdline', len(extra['cmdline'])) + for j, arg in enumerate(extra['cmdline']): + cmdline[j] = arg + + cpu_times = _cpu_times() + cpu_list = pl.init('cpuTimes', len(cpu_times)) + for i, ct in enumerate(cpu_times): + cpu = cpu_list[i] + cpu.cpuNum = ct['cpuNum'] + cpu.user = ct['user'] + cpu.nice = ct['nice'] + cpu.system = ct['system'] + cpu.idle = ct['idle'] + cpu.iowait = ct['iowait'] + cpu.irq = ct['irq'] + cpu.softirq = ct['softirq'] + + mem_info = _mem_info() + pl.mem.total = mem_info["MemTotal:"] + pl.mem.free = mem_info["MemFree:"] + pl.mem.available = mem_info["MemAvailable:"] + pl.mem.buffers = mem_info["Buffers:"] + pl.mem.cached = mem_info["Cached:"] + pl.mem.active = mem_info["Active:"] + pl.mem.inactive = mem_info["Inactive:"] + pl.mem.shared = mem_info["Shmem:"] + + +def main() -> NoReturn: + pm = messaging.PubMaster(['procLog']) + rk = Ratekeeper(0.5) + while True: + msg = messaging.new_message('procLog', valid=True) + build_proc_log_message(msg) + pm.send('procLog', msg) + rk.keep_time() + + +if __name__ == '__main__': + main() diff --git a/system/qcomgpsd/modemdiag.py b/system/qcomgpsd/modemdiag.py new file mode 100644 index 0000000000..5d72aeba9e --- /dev/null +++ b/system/qcomgpsd/modemdiag.py @@ -0,0 +1,94 @@ +import select +from serial import Serial +from crcmod import mkCrcFun +from struct import pack, unpack_from, calcsize + +class ModemDiag: + def __init__(self): + self.serial = self.open_serial() + self.pend = b'' + + def open_serial(self): + serial = Serial("/dev/ttyUSB0", baudrate=115200, rtscts=True, dsrdtr=True, timeout=0, exclusive=True) + serial.flush() + serial.reset_input_buffer() + serial.reset_output_buffer() + return serial + + ccitt_crc16 = mkCrcFun(0x11021, initCrc=0, xorOut=0xffff) + ESCAPE_CHAR = b'\x7d' + TRAILER_CHAR = b'\x7e' + + def hdlc_encapsulate(self, payload): + payload += pack('= 3 + assert payload[-1:] == self.TRAILER_CHAR + payload = payload[:-1] + payload = payload.replace(bytes([self.ESCAPE_CHAR[0], self.TRAILER_CHAR[0] ^ 0x20]), self.TRAILER_CHAR) + payload = payload.replace(bytes([self.ESCAPE_CHAR[0], self.ESCAPE_CHAR[0] ^ 0x20]), self.ESCAPE_CHAR) + assert payload[-2:] == pack(' NoReturn: + while True: + try: + with open(device) as nmeaport: + for line in nmeaport: + line = line.strip() + if DEBUG: + print(line) + if not line.startswith("$"): # all NMEA messages start with $ + continue + if not nmea_checksum_ok(line): + continue + + fields = line.split(",") + match fields[0]: + case "$GNCLK": + # fields at end are reserved (not used) + gnss_clock = GnssClockNmeaPort(*fields[1:10]) # type: ignore[arg-type] + print(gnss_clock) + case "$GNMEAS": + # fields at end are reserved (not used) + gnss_meas = GnssMeasNmeaPort(*fields[1:14]) # type: ignore[arg-type] + print(gnss_meas) + except Exception as e: + print(e) + sleep(1) + +def main() -> NoReturn: + from openpilot.common.gpio import gpio_init, gpio_set + from openpilot.system.hardware.tici.pins import GPIO + from openpilot.system.qcomgpsd.qcomgpsd import at_cmd + + try: + check_output(["pidof", "qcomgpsd"]) + print("qcomgpsd is running, please kill openpilot before running this script! (aborted)") + sys.exit(1) + except CalledProcessError as e: + if e.returncode != 1: # 1 == no process found (pandad not running) + raise e + + print("power up antenna ...") + gpio_init(GPIO.GNSS_PWR_EN, True) + gpio_set(GPIO.GNSS_PWR_EN, True) + + if b"+QGPS: 0" not in (at_cmd("AT+QGPS?") or b""): + print("stop location tracking ...") + at_cmd("AT+QGPSEND") + + if b'+QGPSCFG: "outport",usbnmea' not in (at_cmd('AT+QGPSCFG="outport"') or b""): + print("configure outport ...") + at_cmd('AT+QGPSCFG="outport","usbnmea"') # usbnmea = /dev/ttyUSB1 + + if b'+QGPSCFG: "gnssrawdata",3,0' not in (at_cmd('AT+QGPSCFG="gnssrawdata"') or b""): + print("configure gnssrawdata ...") + # AT+QGPSCFG="gnssrawdata",,' + # values: + # 0x01 = GPS + # 0x02 = GLONASS + # 0x04 = BEIDOU + # 0x08 = GALILEO + # 0x10 = QZSS + # values: + # 0 = NMEA port + # 1 = AT port + at_cmd('AT+QGPSCFG="gnssrawdata",3,0') # enable all constellations, output data to NMEA port + print("rebooting ...") + at_cmd('AT+CFUN=1,1') + print("re-run this script when it is back up") + sys.exit(2) + + print("starting location tracking ...") + at_cmd("AT+QGPS=1") + + process_nmea_port_messages() + +if __name__ == "__main__": + main() diff --git a/system/qcomgpsd/qcomgpsd.py b/system/qcomgpsd/qcomgpsd.py new file mode 100755 index 0000000000..819b17f113 --- /dev/null +++ b/system/qcomgpsd/qcomgpsd.py @@ -0,0 +1,463 @@ +#!/usr/bin/env python3 +import os +import sys +import signal +import itertools +import math +import time +import requests +import shutil +import subprocess +import datetime +from multiprocessing import Process, Event +from typing import NoReturn +from struct import unpack_from, calcsize, pack + +from cereal import log +import cereal.messaging as messaging +from openpilot.common.gpio import gpio_init, gpio_set +from openpilot.common.retry import retry +from openpilot.common.time_helpers import system_time_valid +from openpilot.system.hardware.tici.pins import GPIO +from openpilot.common.swaglog import cloudlog +from openpilot.system.qcomgpsd.modemdiag import ModemDiag, DIAG_LOG_F, setup_logs, send_recv +from openpilot.system.qcomgpsd.structs import (dict_unpacker, position_report, relist, + gps_measurement_report, gps_measurement_report_sv, + glonass_measurement_report, glonass_measurement_report_sv, + oemdre_measurement_report, oemdre_measurement_report_sv, oemdre_svpoly_report, + LOG_GNSS_GPS_MEASUREMENT_REPORT, LOG_GNSS_GLONASS_MEASUREMENT_REPORT, + LOG_GNSS_POSITION_REPORT, LOG_GNSS_OEMDRE_MEASUREMENT_REPORT, + LOG_GNSS_OEMDRE_SVPOLY_REPORT) + +DEBUG = int(os.getenv("DEBUG", "0"))==1 +ASSIST_DATA_FILE = '/tmp/xtra3grc.bin' +ASSIST_DATA_FILE_DOWNLOAD = ASSIST_DATA_FILE + '.download' +ASSISTANCE_URL = 'http://xtrapath3.izatcloud.net/xtra3grc.bin' + +LOG_TYPES = [ + LOG_GNSS_GPS_MEASUREMENT_REPORT, + LOG_GNSS_GLONASS_MEASUREMENT_REPORT, + LOG_GNSS_OEMDRE_MEASUREMENT_REPORT, + LOG_GNSS_POSITION_REPORT, + LOG_GNSS_OEMDRE_SVPOLY_REPORT, +] + + +miscStatusFields = { + "multipathEstimateIsValid": 0, + "directionIsValid": 1, +} + +measurementStatusFields = { + "subMillisecondIsValid": 0, + "subBitTimeIsKnown": 1, + "satelliteTimeIsKnown": 2, + "bitEdgeConfirmedFromSignal": 3, + "measuredVelocity": 4, + "fineOrCoarseVelocity": 5, + "lockPointValid": 6, + "lockPointPositive": 7, + + "lastUpdateFromDifference": 9, + "lastUpdateFromVelocityDifference": 10, + "strongIndicationOfCrossCorelation": 11, + "tentativeMeasurement": 12, + "measurementNotUsable": 13, + "sirCheckIsNeeded": 14, + "probationMode": 15, + + "multipathIndicator": 24, + "imdJammingIndicator": 25, + "lteB13TxJammingIndicator": 26, + "freshMeasurementIndicator": 27, +} + +measurementStatusGPSFields = { + "gpsRoundRobinRxDiversity": 18, + "gpsRxDiversity": 19, + "gpsLowBandwidthRxDiversityCombined": 20, + "gpsHighBandwidthNu4": 21, + "gpsHighBandwidthNu8": 22, + "gpsHighBandwidthUniform": 23, +} + +measurementStatusGlonassFields = { + "glonassMeanderBitEdgeValid": 16, + "glonassTimeMarkValid": 17 +} + +@retry(attempts=10, delay=1.0) +def try_setup_logs(diag, logs): + return setup_logs(diag, logs) + +@retry(attempts=3, delay=1.0) +def at_cmd(cmd: str) -> str | None: + return subprocess.check_output(f"mmcli -m any --timeout 30 --command='{cmd}'", shell=True, encoding='utf8') + +def gps_enabled() -> bool: + return "QGPS: 1" in at_cmd("AT+QGPS?") + +def download_assistance(): + try: + response = requests.get(ASSISTANCE_URL, timeout=5, stream=True) + + with open(ASSIST_DATA_FILE_DOWNLOAD, 'wb') as fp: + for chunk in response.iter_content(chunk_size=8192): + fp.write(chunk) + if fp.tell() > 1e5: + cloudlog.error("Qcom assistance data larger than expected") + return + + os.rename(ASSIST_DATA_FILE_DOWNLOAD, ASSIST_DATA_FILE) + + except requests.exceptions.RequestException: + cloudlog.exception("Failed to download assistance file") + return + +def downloader_loop(event): + if os.path.exists(ASSIST_DATA_FILE): + os.remove(ASSIST_DATA_FILE) + + alt_path = os.getenv("QCOM_ALT_ASSISTANCE_PATH", None) + if alt_path is not None and os.path.exists(alt_path): + shutil.copyfile(alt_path, ASSIST_DATA_FILE) + + try: + while not os.path.exists(ASSIST_DATA_FILE) and not event.is_set(): + download_assistance() + event.wait(timeout=10) + except KeyboardInterrupt: + pass + +@retry(attempts=5, delay=0.2, ignore_failure=True) +def inject_assistance(): + cmd = f"mmcli -m any --timeout 30 --location-inject-assistance-data={ASSIST_DATA_FILE}" + subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=True) + cloudlog.info("successfully loaded assistance data") + +@retry(attempts=5, delay=1.0) +def setup_quectel(diag: ModemDiag) -> bool: + ret = False + + # enable OEMDRE in the NV + # TODO: it has to reboot for this to take effect + DIAG_NV_READ_F = 38 + DIAG_NV_WRITE_F = 39 + NV_GNSS_OEM_FEATURE_MASK = 7165 + send_recv(diag, DIAG_NV_WRITE_F, pack(' NoReturn: + unpack_gps_meas, size_gps_meas = dict_unpacker(gps_measurement_report, True) + unpack_gps_meas_sv, size_gps_meas_sv = dict_unpacker(gps_measurement_report_sv, True) + + unpack_glonass_meas, size_glonass_meas = dict_unpacker(glonass_measurement_report, True) + unpack_glonass_meas_sv, size_glonass_meas_sv = dict_unpacker(glonass_measurement_report_sv, True) + + unpack_oemdre_meas, size_oemdre_meas = dict_unpacker(oemdre_measurement_report, True) + unpack_oemdre_meas_sv, size_oemdre_meas_sv = dict_unpacker(oemdre_measurement_report_sv, True) + + unpack_svpoly, _ = dict_unpacker(oemdre_svpoly_report, True) + unpack_position, _ = dict_unpacker(position_report) + + unpack_position, _ = dict_unpacker(position_report) + + wait_for_modem() + + stop_download_event = Event() + assist_fetch_proc = Process(target=downloader_loop, args=(stop_download_event,)) + assist_fetch_proc.start() + def cleanup(sig, frame): + cloudlog.warning("caught sig disabling quectel gps") + + gpio_set(GPIO.GNSS_PWR_EN, False) + try: + teardown_quectel(diag) + cloudlog.warning("quectel cleanup done") + except NameError: + cloudlog.warning('quectel not yet setup') + + stop_download_event.set() + assist_fetch_proc.kill() + assist_fetch_proc.join() + + sys.exit(0) + signal.signal(signal.SIGINT, cleanup) + signal.signal(signal.SIGTERM, cleanup) + + # connect to modem + diag = ModemDiag() + r = setup_quectel(diag) + want_assistance = not r + cloudlog.warning("quectel setup done") + gpio_init(GPIO.GNSS_PWR_EN, True) + gpio_set(GPIO.GNSS_PWR_EN, True) + + pm = messaging.PubMaster(['qcomGnss', 'gpsLocation']) + + while 1: + if os.path.exists(ASSIST_DATA_FILE) and want_assistance: + setup_quectel(diag) + want_assistance = False + + opcode, payload = diag.recv() + if opcode != DIAG_LOG_F: + cloudlog.error(f"Unhandled opcode: {opcode}") + continue + + (pending_msgs, log_outer_length), inner_log_packet = unpack_from(' 0: + cloudlog.debug(f"have {pending_msgs} pending messages") + assert log_outer_length == len(inner_log_packet) + + (log_inner_length, log_type, log_time), log_payload = unpack_from(' 6*SECS_IN_DAY: + epoch.week += 1 + elif epoch.tow > 6*SECS_IN_DAY and current_gps_time.tow < SECS_IN_DAY: + epoch.week -= 1 + + poly.gpsWeek = epoch.week + poly.gpsTow = epoch.tow + ''' + pm.send('qcomGnss', msg) + + elif log_type in [LOG_GNSS_GPS_MEASUREMENT_REPORT, LOG_GNSS_GLONASS_MEASUREMENT_REPORT]: + msg = messaging.new_message('qcomGnss', valid=True) + + gnss = msg.qcomGnss + gnss.logTs = log_time + gnss.init('measurementReport') + report = gnss.measurementReport + + if log_type == LOG_GNSS_GPS_MEASUREMENT_REPORT: + dat = unpack_gps_meas(log_payload) + sats = log_payload[size_gps_meas:] + unpack_meas_sv, size_meas_sv = unpack_gps_meas_sv, size_gps_meas_sv + report.source = 0 # gps + measurement_status_fields = (measurementStatusFields.items(), measurementStatusGPSFields.items()) + elif log_type == LOG_GNSS_GLONASS_MEASUREMENT_REPORT: + dat = unpack_glonass_meas(log_payload) + sats = log_payload[size_glonass_meas:] + unpack_meas_sv, size_meas_sv = unpack_glonass_meas_sv, size_glonass_meas_sv + report.source = 1 # glonass + measurement_status_fields = (measurementStatusFields.items(), measurementStatusGlonassFields.items()) + else: + raise RuntimeError(f"invalid log_type: {log_type}") + + for k,v in dat.items(): + if k == "version": + assert v == 0 + elif k == "week": + report.gpsWeek = v + elif k == "svCount": + pass + else: + setattr(report, k, v) + report.init('sv', dat['svCount']) + if dat['svCount'] > 0: + assert len(sats)//dat['svCount'] == size_meas_sv + for i in range(dat['svCount']): + sv = report.sv[i] + sv.init('measurementStatus') + sat = unpack_meas_sv(sats[size_meas_sv*i:size_meas_sv*(i+1)]) + for k,v in sat.items(): + if k == "parityErrorCount": + sv.gpsParityErrorCount = v + elif k == "frequencyIndex": + sv.glonassFrequencyIndex = v + elif k == "hemmingErrorCount": + sv.glonassHemmingErrorCount = v + elif k == "measurementStatus": + for kk,vv in itertools.chain(*measurement_status_fields): + setattr(sv.measurementStatus, kk, bool(v & (1< Accelerometer BIT[1] 0x00000002 <96> Gyro 0x0000FFFC - Reserved A bit set to 1 indicates that certain fields as defined by the SENSOR_AIDING_MASK were aided with sensor data*/ + uint32 q_SensorAidMask; /* Denotes which component of the position report was assisted with additional sensors defined in SENSOR_DATA_USAGE_MASK BIT[0] 0x00000001 <96> Heading aided with sensor data BIT[1] 0x00000002 <96> Speed aided with sensor data BIT[2] 0x00000004 <96> Position aided with sensor data BIT[3] 0x00000008 <96> Velocity aided with sensor data 0xFFFFFFF0 <96> Reserved */ + uint8 u_NumGpsSvsUsed; /* The number of GPS SVs used in the fix */ + uint8 u_TotalGpsSvs; /* Total number of GPS SVs detected by searcher, including ones not used in position calculation */ + uint8 u_NumGloSvsUsed; /* The number of Glonass SVs used in the fix */ + uint8 u_TotalGloSvs; /* Total number of Glonass SVs detected by searcher, including ones not used in position calculation */ + uint8 u_NumBdsSvsUsed; /* The number of BeiDou SVs used in the fix */ + uint8 u_TotalBdsSvs; /* Total number of BeiDou SVs detected by searcher, including ones not used in position calculation */ +""" # noqa: E501 + +def name_to_camelcase(nam): + ret = [] + i = 0 + while i < len(nam): + if nam[i] == "_": + ret.append(nam[i+1].upper()) + i += 2 + else: + ret.append(nam[i]) + i += 1 + return ''.join(ret) + +def parse_struct(ss): + st = "<" + nams = [] + for l in ss.strip().split("\n"): + if len(l.strip()) == 0: + continue + typ, nam = l.split(";")[0].split() + #print(typ, nam) + if typ == "float" or '_Flt' in nam: + st += "f" + elif typ == "double" or '_Dbl' in nam: + st += "d" + elif typ in ["uint8", "uint8_t"]: + st += "B" + elif typ in ["int8", "int8_t"]: + st += "b" + elif typ in ["uint32", "uint32_t"]: + st += "I" + elif typ in ["int32", "int32_t"]: + st += "i" + elif typ in ["uint16", "uint16_t"]: + st += "H" + elif typ in ["int16", "int16_t"]: + st += "h" + elif typ in ["uint64", "uint64_t"]: + st += "Q" + else: + raise RuntimeError(f"unknown type {typ}") + if '[' in nam: + cnt = int(nam.split("[")[1].split("]")[0]) + st += st[-1]*(cnt-1) + for i in range(cnt): + nams.append(f'{nam.split("[")[0]}[{i}]') + else: + nams.append(nam) + return st, nams + +def dict_unpacker(ss, camelcase = False): + st, nams = parse_struct(ss) + if camelcase: + nams = [name_to_camelcase(x) for x in nams] + sz = calcsize(st) + return lambda x: dict(zip(nams, unpack_from(st, x), strict=True)), sz + +def relist(dat): + list_keys = set() + for key in dat.keys(): + if '[' in key: + list_keys.add(key.split('[')[0]) + list_dict = {} + for list_key in list_keys: + list_dict[list_key] = [] + i = 0 + while True: + key = list_key + f'[{i}]' + if key not in dat: + break + list_dict[list_key].append(dat[key]) + del dat[key] + i += 1 + return {**dat, **list_dict} diff --git a/system/qcomgpsd/tests/test_qcomgpsd.py b/system/qcomgpsd/tests/test_qcomgpsd.py new file mode 100644 index 0000000000..2fc6205ea4 --- /dev/null +++ b/system/qcomgpsd/tests/test_qcomgpsd.py @@ -0,0 +1,119 @@ +import os +import pytest +import json +import time +import datetime +import subprocess + +import cereal.messaging as messaging +from openpilot.system.qcomgpsd.qcomgpsd import at_cmd, wait_for_modem +from openpilot.system.manager.process_config import managed_processes + +GOOD_SIGNAL = bool(int(os.getenv("GOOD_SIGNAL", '0'))) + + +@pytest.mark.tici +class TestRawgpsd: + @classmethod + def setup_class(cls): + os.environ['GPS_COLD_START'] = '1' + os.system("sudo systemctl start systemd-resolved") + os.system("sudo systemctl restart ModemManager lte") + wait_for_modem() + + @classmethod + def teardown_class(cls): + managed_processes['qcomgpsd'].stop() + os.system("sudo systemctl restart systemd-resolved") + os.system("sudo systemctl restart ModemManager lte") + + def setup_method(self): + self.sm = messaging.SubMaster(['qcomGnss', 'gpsLocation', 'gnssMeasurements']) + + def teardown_method(self): + managed_processes['qcomgpsd'].stop() + os.system("sudo systemctl restart systemd-resolved") + + def _wait_for_output(self, t): + dt = 0.1 + for _ in range(t*int(1/dt)): + self.sm.update(0) + if self.sm.updated['qcomGnss']: + break + time.sleep(dt) + return self.sm.updated['qcomGnss'] + + def test_no_crash_double_command(self): + at_cmd("AT+QGPSDEL=0") + at_cmd("AT+QGPSDEL=0") + + def test_wait_for_modem(self): + os.system("sudo systemctl stop ModemManager") + managed_processes['qcomgpsd'].start() + assert not self._wait_for_output(5) + + os.system("sudo systemctl restart ModemManager") + assert self._wait_for_output(30) + + def test_startup_time(self, subtests): + for internet in (True, False): + if not internet: + os.system("sudo systemctl stop systemd-resolved") + with subtests.test(internet=internet): + managed_processes['qcomgpsd'].start() + assert self._wait_for_output(7) + managed_processes['qcomgpsd'].stop() + + def test_turns_off_gnss(self, subtests): + for s in (0.1, 1, 5): + with subtests.test(runtime=s): + managed_processes['qcomgpsd'].start() + time.sleep(s) + managed_processes['qcomgpsd'].stop() + + ls = subprocess.check_output("mmcli -m any --location-status --output-json", shell=True, encoding='utf-8') + loc_status = json.loads(ls) + assert set(loc_status['modem']['location']['enabled']) <= {'3gpp-lac-ci'} + + + def check_assistance(self, should_be_loaded): + # after QGPSDEL: '+QGPSXTRADATA: 0,"1980/01/05,19:00:00"' + # after loading: '+QGPSXTRADATA: 10080,"2023/06/24,19:00:00"' + out = at_cmd("AT+QGPSXTRADATA?") + out = out.split("+QGPSXTRADATA:")[1].split("'")[0].strip() + valid_duration, injected_time_str = out.split(",", 1) + if should_be_loaded: + assert valid_duration == "10080" # should be max time + injected_time = datetime.datetime.strptime(injected_time_str.replace("\"", ""), "%Y/%m/%d,%H:%M:%S") + assert abs((datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - injected_time).total_seconds()) < 60*60*12 + else: + valid_duration, injected_time_str = out.split(",", 1) + injected_time_str = injected_time_str.replace('\"', '').replace('\'', '') + assert injected_time_str[:] == '1980/01/05,19:00:00'[:] + assert valid_duration == '0' + + def test_assistance_loading(self): + managed_processes['qcomgpsd'].start() + assert self._wait_for_output(10) + managed_processes['qcomgpsd'].stop() + self.check_assistance(True) + + def test_no_assistance_loading(self): + os.system("sudo systemctl stop systemd-resolved") + + managed_processes['qcomgpsd'].start() + assert self._wait_for_output(10) + managed_processes['qcomgpsd'].stop() + self.check_assistance(False) + + def test_late_assistance_loading(self): + os.system("sudo systemctl stop systemd-resolved") + + managed_processes['qcomgpsd'].start() + self._wait_for_output(17) + assert self.sm.updated['qcomGnss'] + + os.system("sudo systemctl restart systemd-resolved") + time.sleep(15) + managed_processes['qcomgpsd'].stop() + self.check_assistance(True) diff --git a/system/sensord/__init__.py b/system/sensord/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/sensord/sensord.py b/system/sensord/sensord.py new file mode 100755 index 0000000000..2b6467fa78 --- /dev/null +++ b/system/sensord/sensord.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +import os +import time +import ctypes +import select +import threading + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from openpilot.common.util import sudo_write +from openpilot.common.realtime import config_realtime_process, Ratekeeper +from openpilot.common.swaglog import cloudlog +from openpilot.common.gpio import gpiochip_get_ro_value_fd, gpioevent_data + +from openpilot.system.sensord.sensors.i2c_sensor import Sensor +from openpilot.system.sensord.sensors.lsm6ds3_accel import LSM6DS3_Accel +from openpilot.system.sensord.sensors.lsm6ds3_gyro import LSM6DS3_Gyro +from openpilot.system.sensord.sensors.lsm6ds3_temp import LSM6DS3_Temp +from openpilot.system.sensord.sensors.mmc5603nj_magn import MMC5603NJ_Magn + +I2C_BUS_IMU = 1 + +def interrupt_loop(sensors: list[tuple[Sensor, str, bool]], event) -> None: + pm = messaging.PubMaster([service for sensor, service, interrupt in sensors if interrupt]) + + # Requesting both edges as the data ready pulse from the lsm6ds sensor is + # very short (75us) and is mostly detected as falling edge instead of rising. + # So if it is detected as rising the following falling edge is skipped. + fd = gpiochip_get_ro_value_fd("sensord", 0, 84) + + # Configure IRQ affinity + irq_path = "/proc/irq/336/smp_affinity_list" + if not os.path.exists(irq_path): + irq_path = "/proc/irq/335/smp_affinity_list" + if os.path.exists(irq_path): + sudo_write('1\n', irq_path) + + offset = time.time_ns() - time.monotonic_ns() + + poller = select.poll() + poller.register(fd, select.POLLIN | select.POLLPRI) + while not event.is_set(): + events = poller.poll(100) + if not events: + cloudlog.error("poll timed out") + continue + if not (events[0][1] & (select.POLLIN | select.POLLPRI)): + cloudlog.error("no poll events set") + continue + + dat = os.read(fd, ctypes.sizeof(gpioevent_data)*16) + evd = gpioevent_data.from_buffer_copy(dat) + + cur_offset = time.time_ns() - time.monotonic_ns() + if abs(cur_offset - offset) > 10 * 1e6: # ms + cloudlog.warning(f"time jumped: {cur_offset} {offset}") + offset = cur_offset + continue + + ts = evd.timestamp - cur_offset + for sensor, service, interrupt in sensors: + if interrupt: + try: + evt = sensor.get_event(ts) + if not sensor.is_data_valid(): + continue + msg = messaging.new_message(service, valid=True) + setattr(msg, service, evt) + pm.send(service, msg) + except Sensor.DataNotReady: + pass + except Exception: + cloudlog.exception(f"Error processing {service}") + + +def polling_loop(sensor: Sensor, service: str, event: threading.Event) -> None: + pm = messaging.PubMaster([service]) + rk = Ratekeeper(SERVICE_LIST[service].frequency, print_delay_threshold=None) + while not event.is_set(): + try: + evt = sensor.get_event() + if not sensor.is_data_valid(): + continue + msg = messaging.new_message(service, valid=True) + setattr(msg, service, evt) + pm.send(service, msg) + except Exception: + cloudlog.exception(f"Error in {service} polling loop") + rk.keep_time() + +def main() -> None: + config_realtime_process([1, ], 1) + + sensors_cfg = [ + (LSM6DS3_Accel(I2C_BUS_IMU), "accelerometer", True), + (LSM6DS3_Gyro(I2C_BUS_IMU), "gyroscope", True), + (LSM6DS3_Temp(I2C_BUS_IMU), "temperatureSensor", False), + (MMC5603NJ_Magn(I2C_BUS_IMU), "magnetometer", False), + ] + + # Reset sensors + for sensor, _, _ in sensors_cfg: + try: + sensor.reset() + except Exception: + cloudlog.exception(f"Error initializing {sensor} sensor") + + # Initialize sensors + exit_event = threading.Event() + threads = [ + threading.Thread(target=interrupt_loop, args=(sensors_cfg, exit_event), daemon=True) + ] + for sensor, service, interrupt in sensors_cfg: + try: + sensor.init() + if not interrupt: + # Start polling thread for sensors without interrupts + threads.append(threading.Thread( + target=polling_loop, + args=(sensor, service, exit_event), + daemon=True + )) + except Exception: + cloudlog.exception(f"Error initializing {service} sensor") + + try: + for t in threads: + t.start() + while any(t.is_alive() for t in threads): + time.sleep(1) + except KeyboardInterrupt: + pass + finally: + exit_event.set() + for t in threads: + if t.is_alive(): + t.join() + + for sensor, _, _ in sensors_cfg: + try: + sensor.shutdown() + except Exception: + cloudlog.exception("Error shutting down sensor") + +if __name__ == "__main__": + main() diff --git a/system/sensord/sensors/__init__.py b/system/sensord/sensors/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/sensord/sensors/i2c_sensor.py b/system/sensord/sensors/i2c_sensor.py new file mode 100644 index 0000000000..336ebb1fd3 --- /dev/null +++ b/system/sensord/sensors/i2c_sensor.py @@ -0,0 +1,77 @@ +import time +import smbus2 +import ctypes +from collections.abc import Iterable + +from cereal import log + +class Sensor: + class SensorException(Exception): + pass + + class DataNotReady(SensorException): + pass + + def __init__(self, bus: int) -> None: + self.bus = smbus2.SMBus(bus) + self.source = log.SensorEventData.SensorSource.velodyne # unknown + self.start_ts = 0. + + def __del__(self): + self.bus.close() + + def read(self, addr: int, length: int) -> bytes: + return bytes(self.bus.read_i2c_block_data(self.device_address, addr, length)) + + def write(self, addr: int, data: int) -> None: + self.bus.write_byte_data(self.device_address, addr, data) + + def writes(self, writes: Iterable[tuple[int, int]]) -> None: + for addr, data in writes: + self.write(addr, data) + + def verify_chip_id(self, address: int, expected_ids: list[int]) -> int: + chip_id = self.read(address, 1)[0] + assert chip_id in expected_ids + return chip_id + + # Abstract methods that must be implemented by subclasses + @property + def device_address(self) -> int: + raise NotImplementedError + + def reset(self) -> None: + # optional. + # not part of init due to shared registers + pass + + def init(self) -> None: + raise NotImplementedError + + def get_event(self, ts: int | None = None) -> log.SensorEventData: + raise NotImplementedError + + def shutdown(self) -> None: + raise NotImplementedError + + def is_data_valid(self) -> bool: + if self.start_ts == 0: + self.start_ts = time.monotonic() + + # unclear whether we need this... + return (time.monotonic() - self.start_ts) > 0.5 + + # *** helpers *** + @staticmethod + def wait(): + # a standard small sleep + time.sleep(0.005) + + @staticmethod + def parse_16bit(lsb: int, msb: int) -> int: + return ctypes.c_int16((msb << 8) | lsb).value + + @staticmethod + def parse_20bit(b2: int, b1: int, b0: int) -> int: + combined = ctypes.c_uint32((b0 << 16) | (b1 << 8) | b2).value + return ctypes.c_int32(combined).value // (1 << 4) diff --git a/system/sensord/sensors/lsm6ds3_accel.py b/system/sensord/sensors/lsm6ds3_accel.py new file mode 100644 index 0000000000..43863daa93 --- /dev/null +++ b/system/sensord/sensors/lsm6ds3_accel.py @@ -0,0 +1,161 @@ +import os +import time + +from cereal import log +from openpilot.system.sensord.sensors.i2c_sensor import Sensor + +class LSM6DS3_Accel(Sensor): + LSM6DS3_ACCEL_I2C_REG_DRDY_CFG = 0x0B + LSM6DS3_ACCEL_I2C_REG_INT1_CTRL = 0x0D + LSM6DS3_ACCEL_I2C_REG_CTRL1_XL = 0x10 + LSM6DS3_ACCEL_I2C_REG_CTRL3_C = 0x12 + LSM6DS3_ACCEL_I2C_REG_CTRL5_C = 0x14 + LSM6DS3_ACCEL_I2C_REG_STAT_REG = 0x1E + LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL = 0x28 + + LSM6DS3_ACCEL_ODR_104HZ = (0b0100 << 4) + LSM6DS3_ACCEL_INT1_DRDY_XL = 0b1 + LSM6DS3_ACCEL_DRDY_XLDA = 0b1 + LSM6DS3_ACCEL_DRDY_PULSE_MODE = (1 << 7) + LSM6DS3_ACCEL_IF_INC = 0b00000100 + + LSM6DS3_ACCEL_ODR_52HZ = (0b0011 << 4) + LSM6DS3_ACCEL_FS_4G = (0b10 << 2) + LSM6DS3_ACCEL_IF_INC_BDU = 0b01000100 + LSM6DS3_ACCEL_POSITIVE_TEST = 0b01 + LSM6DS3_ACCEL_NEGATIVE_TEST = 0b10 + LSM6DS3_ACCEL_MIN_ST_LIMIT_mg = 90.0 + LSM6DS3_ACCEL_MAX_ST_LIMIT_mg = 1700.0 + + @property + def device_address(self) -> int: + return 0x6A + + def reset(self): + self.write(0x12, 0x1) + time.sleep(0.1) + + def init(self): + chip_id = self.verify_chip_id(0x0F, [0x69, 0x6A]) + if chip_id == 0x6A: + self.source = log.SensorEventData.SensorSource.lsm6ds3trc + else: + self.source = log.SensorEventData.SensorSource.lsm6ds3 + + # self-test + if os.getenv("LSM_SELF_TEST") == "1": + self.self_test(self.LSM6DS3_ACCEL_POSITIVE_TEST) + self.self_test(self.LSM6DS3_ACCEL_NEGATIVE_TEST) + + # actual init + int1 = self.read(self.LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, 1)[0] + int1 |= self.LSM6DS3_ACCEL_INT1_DRDY_XL + self.writes(( + # Enable continuous update and automatic address increment + (self.LSM6DS3_ACCEL_I2C_REG_CTRL3_C, self.LSM6DS3_ACCEL_IF_INC), + # Set ODR to 104 Hz, FS to ±2g (default) + (self.LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, self.LSM6DS3_ACCEL_ODR_104HZ), + # Configure data ready signal to pulse mode + (self.LSM6DS3_ACCEL_I2C_REG_DRDY_CFG, self.LSM6DS3_ACCEL_DRDY_PULSE_MODE), + # Enable data ready interrupt on INT1 without resetting existing interrupts + (self.LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, int1), + )) + + def get_event(self, ts: int | None = None) -> log.SensorEventData: + assert ts is not None # must come from the IRQ event + + # Check if data is ready since IRQ is shared with gyro + status_reg = self.read(self.LSM6DS3_ACCEL_I2C_REG_STAT_REG, 1)[0] + if (status_reg & self.LSM6DS3_ACCEL_DRDY_XLDA) == 0: + raise self.DataNotReady + + scale = 9.81 * 2.0 / (1 << 15) + b = self.read(self.LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, 6) + x = self.parse_16bit(b[0], b[1]) * scale + y = self.parse_16bit(b[2], b[3]) * scale + z = self.parse_16bit(b[4], b[5]) * scale + + event = log.SensorEventData.new_message() + event.timestamp = ts + event.version = 1 + event.sensor = 1 # SENSOR_ACCELEROMETER + event.type = 1 # SENSOR_TYPE_ACCELEROMETER + event.source = self.source + a = event.init('acceleration') + a.v = [y, -x, z] + a.status = 1 + return event + + def shutdown(self) -> None: + # Disable data ready interrupt on INT1 + value = self.read(self.LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, 1)[0] + value &= ~self.LSM6DS3_ACCEL_INT1_DRDY_XL + self.write(self.LSM6DS3_ACCEL_I2C_REG_INT1_CTRL, value) + + # Power down by clearing ODR bits + value = self.read(self.LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, 1)[0] + value &= 0x0F + self.write(self.LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, value) + + # *** self-test stuff *** + def _wait_for_data_ready(self): + while True: + drdy = self.read(self.LSM6DS3_ACCEL_I2C_REG_STAT_REG, 1)[0] + if drdy & self.LSM6DS3_ACCEL_DRDY_XLDA: + break + + def _read_and_avg_data(self, scaling: float) -> list[float]: + out_buf = [0.0, 0.0, 0.0] + for _ in range(5): + self._wait_for_data_ready() + b = self.read(self.LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, 6) + for j in range(3): + val = self.parse_16bit(b[j*2], b[j*2+1]) * scaling + out_buf[j] += val + return [x / 5.0 for x in out_buf] + + def self_test(self, test_type: int) -> None: + # Prepare sensor for self-test + self.write(self.LSM6DS3_ACCEL_I2C_REG_CTRL3_C, self.LSM6DS3_ACCEL_IF_INC_BDU) + + # Configure ODR and full scale based on sensor type + if self.source == log.SensorEventData.SensorSource.lsm6ds3trc: + odr_fs = self.LSM6DS3_ACCEL_FS_4G | self.LSM6DS3_ACCEL_ODR_52HZ + scaling = 0.122 # mg/LSB for ±4g + else: + odr_fs = self.LSM6DS3_ACCEL_ODR_52HZ + scaling = 0.061 # mg/LSB for ±2g + self.write(self.LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, odr_fs) + + # Wait for stable output + time.sleep(0.1) + self._wait_for_data_ready() + val_st_off = self._read_and_avg_data(scaling) + + # Enable self-test + self.write(self.LSM6DS3_ACCEL_I2C_REG_CTRL5_C, test_type) + + # Wait for stable output + time.sleep(0.1) + self._wait_for_data_ready() + val_st_on = self._read_and_avg_data(scaling) + + # Disable sensor and self-test + self.write(self.LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, 0) + self.write(self.LSM6DS3_ACCEL_I2C_REG_CTRL5_C, 0) + + # Calculate differences and check limits + test_val = [abs(on - off) for on, off in zip(val_st_on, val_st_off, strict=False)] + for val in test_val: + if val < self.LSM6DS3_ACCEL_MIN_ST_LIMIT_mg or val > self.LSM6DS3_ACCEL_MAX_ST_LIMIT_mg: + raise self.SensorException(f"Accelerometer self-test failed for test type {test_type}") + +if __name__ == "__main__": + import numpy as np + s = LSM6DS3_Accel(1) + s.init() + time.sleep(0.2) + e = s.get_event(0) + print(e) + print(np.linalg.norm(e.acceleration.v)) + s.shutdown() diff --git a/system/sensord/sensors/lsm6ds3_gyro.py b/system/sensord/sensors/lsm6ds3_gyro.py new file mode 100644 index 0000000000..60de2bbe02 --- /dev/null +++ b/system/sensord/sensors/lsm6ds3_gyro.py @@ -0,0 +1,145 @@ +import os +import math +import time + +from cereal import log +from openpilot.system.sensord.sensors.i2c_sensor import Sensor + +class LSM6DS3_Gyro(Sensor): + LSM6DS3_GYRO_I2C_REG_DRDY_CFG = 0x0B + LSM6DS3_GYRO_I2C_REG_INT1_CTRL = 0x0D + LSM6DS3_GYRO_I2C_REG_CTRL2_G = 0x11 + LSM6DS3_GYRO_I2C_REG_CTRL5_C = 0x14 + LSM6DS3_GYRO_I2C_REG_STAT_REG = 0x1E + LSM6DS3_GYRO_I2C_REG_OUTX_L_G = 0x22 + + LSM6DS3_GYRO_ODR_104HZ = (0b0100 << 4) + LSM6DS3_GYRO_INT1_DRDY_G = 0b10 + LSM6DS3_GYRO_DRDY_GDA = 0b10 + LSM6DS3_GYRO_DRDY_PULSE_MODE = (1 << 7) + + LSM6DS3_GYRO_ODR_208HZ = (0b0101 << 4) + LSM6DS3_GYRO_FS_2000dps = (0b11 << 2) + LSM6DS3_GYRO_POSITIVE_TEST = (0b01 << 2) + LSM6DS3_GYRO_NEGATIVE_TEST = (0b11 << 2) + LSM6DS3_GYRO_MIN_ST_LIMIT_mdps = 150000.0 + LSM6DS3_GYRO_MAX_ST_LIMIT_mdps = 700000.0 + + @property + def device_address(self) -> int: + return 0x6A + + def reset(self): + self.write(0x12, 0x1) + time.sleep(0.1) + + def init(self): + chip_id = self.verify_chip_id(0x0F, [0x69, 0x6A]) + if chip_id == 0x6A: + self.source = log.SensorEventData.SensorSource.lsm6ds3trc + else: + self.source = log.SensorEventData.SensorSource.lsm6ds3 + + # self-test + if "LSM_SELF_TEST" in os.environ: + self.self_test(self.LSM6DS3_GYRO_POSITIVE_TEST) + self.self_test(self.LSM6DS3_GYRO_NEGATIVE_TEST) + + # actual init + self.writes(( + # TODO: set scale. Default is +- 250 deg/s + (self.LSM6DS3_GYRO_I2C_REG_CTRL2_G, self.LSM6DS3_GYRO_ODR_104HZ), + # Configure data ready signal to pulse mode + (self.LSM6DS3_GYRO_I2C_REG_DRDY_CFG, self.LSM6DS3_GYRO_DRDY_PULSE_MODE), + )) + value = self.read(self.LSM6DS3_GYRO_I2C_REG_INT1_CTRL, 1)[0] + value |= self.LSM6DS3_GYRO_INT1_DRDY_G + self.write(self.LSM6DS3_GYRO_I2C_REG_INT1_CTRL, value) + + def get_event(self, ts: int | None = None) -> log.SensorEventData: + assert ts is not None # must come from the IRQ event + + # Check if gyroscope data is ready, since it's shared with accelerometer + status_reg = self.read(self.LSM6DS3_GYRO_I2C_REG_STAT_REG, 1)[0] + if not (status_reg & self.LSM6DS3_GYRO_DRDY_GDA): + raise self.DataNotReady + + b = self.read(self.LSM6DS3_GYRO_I2C_REG_OUTX_L_G, 6) + x = self.parse_16bit(b[0], b[1]) + y = self.parse_16bit(b[2], b[3]) + z = self.parse_16bit(b[4], b[5]) + scale = (8.75 / 1000.0) * (math.pi / 180.0) + xyz = [y * scale, -x * scale, z * scale] + + event = log.SensorEventData.new_message() + event.timestamp = ts + event.version = 2 + event.sensor = 5 # SENSOR_GYRO_UNCALIBRATED + event.type = 16 # SENSOR_TYPE_GYROSCOPE_UNCALIBRATED + event.source = self.source + g = event.init('gyroUncalibrated') + g.v = xyz + g.status = 1 + return event + + def shutdown(self) -> None: + # Disable data ready interrupt on INT1 + value = self.read(self.LSM6DS3_GYRO_I2C_REG_INT1_CTRL, 1)[0] + value &= ~self.LSM6DS3_GYRO_INT1_DRDY_G + self.write(self.LSM6DS3_GYRO_I2C_REG_INT1_CTRL, value) + + # Power down by clearing ODR bits + value = self.read(self.LSM6DS3_GYRO_I2C_REG_CTRL2_G, 1)[0] + value &= 0x0F + self.write(self.LSM6DS3_GYRO_I2C_REG_CTRL2_G, value) + + # *** self-test stuff *** + def _wait_for_data_ready(self): + while True: + drdy = self.read(self.LSM6DS3_GYRO_I2C_REG_STAT_REG, 1)[0] + if drdy & self.LSM6DS3_GYRO_DRDY_GDA: + break + + def _read_and_avg_data(self) -> list[float]: + out_buf = [0.0, 0.0, 0.0] + for _ in range(5): + self._wait_for_data_ready() + b = self.read(self.LSM6DS3_GYRO_I2C_REG_OUTX_L_G, 6) + for j in range(3): + val = self.parse_16bit(b[j*2], b[j*2+1]) * 70.0 # mdps/LSB for 2000 dps + out_buf[j] += val + return [x / 5.0 for x in out_buf] + + def self_test(self, test_type: int): + # Set ODR to 208Hz, FS to 2000dps + self.write(self.LSM6DS3_GYRO_I2C_REG_CTRL2_G, self.LSM6DS3_GYRO_ODR_208HZ | self.LSM6DS3_GYRO_FS_2000dps) + + # Wait for stable output + time.sleep(0.15) + self._wait_for_data_ready() + val_st_off = self._read_and_avg_data() + + # Enable self-test + self.write(self.LSM6DS3_GYRO_I2C_REG_CTRL5_C, test_type) + + # Wait for stable output + time.sleep(0.05) + self._wait_for_data_ready() + val_st_on = self._read_and_avg_data() + + # Disable sensor and self-test + self.write(self.LSM6DS3_GYRO_I2C_REG_CTRL2_G, 0) + self.write(self.LSM6DS3_GYRO_I2C_REG_CTRL5_C, 0) + + # Calculate differences and check limits + test_val = [abs(on - off) for on, off in zip(val_st_on, val_st_off, strict=False)] + for val in test_val: + if val < self.LSM6DS3_GYRO_MIN_ST_LIMIT_mdps or val > self.LSM6DS3_GYRO_MAX_ST_LIMIT_mdps: + raise Exception(f"Gyroscope self-test failed for test type {test_type}") + +if __name__ == "__main__": + s = LSM6DS3_Gyro(1) + s.init() + time.sleep(0.1) + print(s.get_event(0)) + s.shutdown() diff --git a/system/sensord/sensors/lsm6ds3_temp.py b/system/sensord/sensors/lsm6ds3_temp.py new file mode 100644 index 0000000000..b9bb9fe3da --- /dev/null +++ b/system/sensord/sensors/lsm6ds3_temp.py @@ -0,0 +1,33 @@ +import time + +from cereal import log +from openpilot.system.sensord.sensors.i2c_sensor import Sensor + +# https://content.arduino.cc/assets/st_imu_lsm6ds3_datasheet.pdf +class LSM6DS3_Temp(Sensor): + @property + def device_address(self) -> int: + return 0x6A + + def _read_temperature(self) -> float: + scale = 16.0 if self.source == log.SensorEventData.SensorSource.lsm6ds3 else 256.0 + data = self.read(0x20, 2) + return 25 + (self.parse_16bit(data[0], data[1]) / scale) + + def init(self): + chip_id = self.verify_chip_id(0x0F, [0x69, 0x6A]) + if chip_id == 0x6A: + self.source = log.SensorEventData.SensorSource.lsm6ds3trc + else: + self.source = log.SensorEventData.SensorSource.lsm6ds3 + + def get_event(self, ts: int | None = None) -> log.SensorEventData: + event = log.SensorEventData.new_message() + event.version = 1 + event.timestamp = int(time.monotonic() * 1e9) + event.source = self.source + event.temperature = self._read_temperature() + return event + + def shutdown(self) -> None: + pass diff --git a/system/sensord/sensors/mmc5603nj_magn.py b/system/sensord/sensors/mmc5603nj_magn.py new file mode 100644 index 0000000000..255e99eb3e --- /dev/null +++ b/system/sensord/sensors/mmc5603nj_magn.py @@ -0,0 +1,76 @@ +import time + +from cereal import log +from openpilot.system.sensord.sensors.i2c_sensor import Sensor + +# https://www.mouser.com/datasheet/2/821/Memsic_09102019_Datasheet_Rev.B-1635324.pdf + +# Register addresses +REG_ODR = 0x1A +REG_INTERNAL_0 = 0x1B +REG_INTERNAL_1 = 0x1C + +# Control register settings +CMM_FREQ_EN = (1 << 7) +AUTO_SR_EN = (1 << 5) +SET = (1 << 3) +RESET = (1 << 4) + +class MMC5603NJ_Magn(Sensor): + @property + def device_address(self) -> int: + return 0x30 + + def init(self): + self.verify_chip_id(0x39, [0x10, ]) + self.writes(( + (REG_ODR, 0), + + # Set BW to 0b01 for 1-150 Hz operation + (REG_INTERNAL_1, 0b01), + )) + + def _read_data(self, cycle) -> list[float]: + # start measurement + self.write(REG_INTERNAL_0, cycle) + self.wait() + + # read out XYZ + scale = 1.0 / 16384.0 + b = self.read(0x00, 9) + return [ + (self.parse_20bit(b[6], b[1], b[0]) * scale) - 32.0, + (self.parse_20bit(b[7], b[3], b[2]) * scale) - 32.0, + (self.parse_20bit(b[8], b[5], b[4]) * scale) - 32.0, + ] + + def get_event(self, ts: int | None = None) -> log.SensorEventData: + ts = time.monotonic_ns() + + # SET - RESET cycle + xyz = self._read_data(SET) + reset_xyz = self._read_data(RESET) + vals = [*xyz, *reset_xyz] + + event = log.SensorEventData.new_message() + event.timestamp = ts + event.version = 1 + event.sensor = 3 # SENSOR_MAGNETOMETER_UNCALIBRATED + event.type = 14 # SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED + event.source = log.SensorEventData.SensorSource.mmc5603nj + + m = event.init('magneticUncalibrated') + m.v = vals + m.status = int(all(int(v) != -32 for v in vals)) + + return event + + def shutdown(self) -> None: + v = self.read(REG_INTERNAL_0, 1)[0] + self.writes(( + # disable auto-reset of measurements + (REG_INTERNAL_0, (v & (~(CMM_FREQ_EN | AUTO_SR_EN)))), + + # disable continuous mode + (REG_ODR, 0), + )) diff --git a/system/sensord/tests/__init__.py b/system/sensord/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/sensord/tests/test_sensord.py b/system/sensord/tests/test_sensord.py new file mode 100644 index 0000000000..1dab652386 --- /dev/null +++ b/system/sensord/tests/test_sensord.py @@ -0,0 +1,232 @@ +import os +import pytest +import time +import numpy as np +from collections import namedtuple, defaultdict + +import cereal.messaging as messaging +from cereal import log +from cereal.services import SERVICE_LIST +from openpilot.common.gpio import get_irqs_for_action +from openpilot.common.timeout import Timeout +from openpilot.system.hardware import HARDWARE +from openpilot.system.manager.process_config import managed_processes + +LSM = { + ('lsm6ds3', 'acceleration'), + ('lsm6ds3', 'gyroUncalibrated'), + ('lsm6ds3', 'temperature'), +} +LSM_C = {(x[0]+'trc', x[1]) for x in LSM} + +MMC = { + ('mmc5603nj', 'magneticUncalibrated'), +} + +SENSOR_CONFIGURATIONS: list[set] = { + "mici": [LSM, LSM_C], + "tizi": [MMC | LSM, MMC | LSM_C], + "tici": [LSM, LSM_C, MMC | LSM, MMC | LSM_C], +}.get(HARDWARE.get_device_type(), []) + +Sensor = log.SensorEventData.SensorSource +SensorConfig = namedtuple('SensorConfig', ['type', 'sanity_min', 'sanity_max']) +ALL_SENSORS = { + Sensor.lsm6ds3: { + SensorConfig("acceleration", 5, 15), + SensorConfig("gyroUncalibrated", 0, .2), + SensorConfig("temperature", 0, 60), + }, + + Sensor.lsm6ds3trc: { + SensorConfig("acceleration", 5, 15), + SensorConfig("gyroUncalibrated", 0, .2), + SensorConfig("temperature", 0, 60), + }, + + Sensor.mmc5603nj: { + SensorConfig("magneticUncalibrated", 0, 300), + } +} + + +def get_irq_count(irq: int): + with open(f"/sys/kernel/irq/{irq}/per_cpu_count") as f: + per_cpu = map(int, f.read().split(",")) + return sum(per_cpu) + +def read_sensor_events(duration_sec): + sensor_types = ['accelerometer', 'gyroscope', 'magnetometer', 'accelerometer2', + 'gyroscope2', 'temperatureSensor', 'temperatureSensor2'] + socks = {} + poller = messaging.Poller() + events = defaultdict(list) + for stype in sensor_types: + socks[stype] = messaging.sub_sock(stype, poller=poller, timeout=100) + + # wait for sensors to come up + with Timeout(int(os.environ.get("SENSOR_WAIT", "5")), "sensors didn't come up"): + while len(poller.poll(250)) == 0: + pass + time.sleep(1) + for s in socks.values(): + messaging.drain_sock_raw(s) + + st = time.monotonic() + while time.monotonic() - st < duration_sec: + for s in socks: + events[s] += messaging.drain_sock(socks[s]) + time.sleep(0.1) + + assert sum(map(len, events.values())) != 0, "No sensor events collected!" + + return {k: v for k, v in events.items() if len(v) > 0} + +@pytest.mark.tici +class TestSensord: + @classmethod + def setup_class(cls): + # enable LSM self test + os.environ["LSM_SELF_TEST"] = "1" + + # read initial sensor values every test case can use + os.system("pkill -f \\\\./sensord") + try: + managed_processes["sensord"].start() + cls.sample_secs = int(os.getenv("SAMPLE_SECS", "10")) + cls.events = read_sensor_events(cls.sample_secs) + + # determine sensord's irq + cls.sensord_irq = get_irqs_for_action("sensord")[0] + finally: + # teardown won't run if this doesn't succeed + managed_processes["sensord"].stop() + + @classmethod + def teardown_class(cls): + managed_processes["sensord"].stop() + + def teardown_method(self): + managed_processes["sensord"].stop() + + def test_sensors_present(self): + # verify correct sensors configuration + seen = set() + for etype in self.events: + for measurement in self.events[etype]: + m = getattr(measurement, measurement.which()) + seen.add((str(m.source), m.which())) + + assert seen in SENSOR_CONFIGURATIONS + + def test_lsm6ds3_timing(self, subtests): + # verify measurements are sampled and published at 104Hz + + sensor_t = { + 1: [], # accel + 5: [], # gyro + } + + for measurement in self.events['accelerometer']: + m = getattr(measurement, measurement.which()) + sensor_t[m.sensor].append(m.timestamp) + + for measurement in self.events['gyroscope']: + m = getattr(measurement, measurement.which()) + sensor_t[m.sensor].append(m.timestamp) + + for s, vals in sensor_t.items(): + with subtests.test(sensor=s): + assert len(vals) > 0 + tdiffs = np.diff(vals) / 1e6 # millis + + high_delay_diffs = list(filter(lambda d: d >= 20., tdiffs)) + assert len(high_delay_diffs) < 15, f"Too many large diffs: {high_delay_diffs}" + + avg_diff = sum(tdiffs)/len(tdiffs) + avg_freq = 1. / (avg_diff * 1e-3) + assert 92. < avg_freq < 114., f"avg freq {avg_freq}Hz wrong, expected 104Hz" + + stddev = np.std(tdiffs) + assert stddev < 2.0, f"Standard-dev to big {stddev}" + + def test_sensor_frequency(self, subtests): + for s, msgs in self.events.items(): + with subtests.test(sensor=s): + freq = len(msgs) / self.sample_secs + ef = SERVICE_LIST[s].frequency + assert ef*0.85 <= freq <= ef*1.15 + + def test_logmonottime_timestamp_diff(self): + # ensure diff between the message logMonotime and sample timestamp is small + + tdiffs = list() + for etype in self.events: + for measurement in self.events[etype]: + m = getattr(measurement, measurement.which()) + + # check if gyro and accel timestamps are before logMonoTime + if str(m.source).startswith("lsm6ds3") and m.which() != 'temperature': + err_msg = f"Timestamp after logMonoTime: {m.timestamp} > {measurement.logMonoTime}" + assert m.timestamp < measurement.logMonoTime, err_msg + + # negative values might occur, as non interrupt packages created + # before the sensor is read + tdiffs.append(abs(measurement.logMonoTime - m.timestamp) / 1e6) + + # some sensors have a read procedure that will introduce an expected diff on the order of 20ms + high_delay_diffs = set(filter(lambda d: d >= 25., tdiffs)) + assert len(high_delay_diffs) < 20, f"Too many measurements published: {high_delay_diffs}" + + avg_diff = round(sum(tdiffs)/len(tdiffs), 4) + assert avg_diff < 4, f"Avg packet diff: {avg_diff:.1f}ms" + + def test_sensor_values(self): + sensor_values = dict() + for etype in self.events: + for measurement in self.events[etype]: + m = getattr(measurement, measurement.which()) + key = (m.source.raw, m.which()) + values = getattr(m, m.which()) + + if hasattr(values, 'v'): + values = values.v + values = np.atleast_1d(values) + + if key in sensor_values: + sensor_values[key].append(values) + else: + sensor_values[key] = [values] + + # Sanity check sensor values + for sensor, stype in sensor_values: + for s in ALL_SENSORS[sensor]: + if s.type != stype: + continue + + key = (sensor, s.type) + mean_norm = np.mean(np.linalg.norm(sensor_values[key], axis=1)) + err_msg = f"Sensor '{sensor} {s.type}' failed sanity checks {mean_norm} is not between {s.sanity_min} and {s.sanity_max}" + assert s.sanity_min <= mean_norm <= s.sanity_max, err_msg + + def test_sensor_verify_no_interrupts_after_stop(self): + managed_processes["sensord"].start() + time.sleep(3) + + # read /proc/interrupts to verify interrupts are received + state_one = get_irq_count(self.sensord_irq) + time.sleep(1) + state_two = get_irq_count(self.sensord_irq) + + error_msg = f"no interrupts received after sensord start!\n{state_one} {state_two}" + assert state_one != state_two, error_msg + + managed_processes["sensord"].stop() + time.sleep(1) + + # read /proc/interrupts to verify no more interrupts are received + state_one = get_irq_count(self.sensord_irq) + time.sleep(1) + state_two = get_irq_count(self.sensord_irq) + assert state_one == state_two, "Interrupts received after sensord stop!" + diff --git a/system/sentry.py b/system/sentry.py new file mode 100644 index 0000000000..47d64ba0fd --- /dev/null +++ b/system/sentry.py @@ -0,0 +1,73 @@ +"""Install exception handler for process crash.""" +import sentry_sdk +from enum import Enum +from sentry_sdk.integrations.threading import ThreadingIntegration + +from openpilot.common.params import Params +from openpilot.system.athena.registration import is_registered_device +from openpilot.system.hardware import HARDWARE, PC +from openpilot.common.swaglog import cloudlog +from openpilot.system.version import get_build_metadata, get_version + + +class SentryProject(Enum): + # python project + SELFDRIVE = "https://6f3c7076c1e14b2aa10f5dde6dda0cc4@o33823.ingest.sentry.io/77924" + # native project + SELFDRIVE_NATIVE = "https://3e4b586ed21a4479ad5d85083b639bc6@o33823.ingest.sentry.io/157615" + + +def report_tombstone(fn: str, message: str, contents: str) -> None: + cloudlog.error({'tombstone': message}) + + with sentry_sdk.configure_scope() as scope: + scope.set_extra("tombstone_fn", fn) + scope.set_extra("tombstone", contents) + sentry_sdk.capture_message(message=message) + sentry_sdk.flush() + + +def capture_exception(*args, **kwargs) -> None: + cloudlog.error("crash", exc_info=kwargs.get('exc_info', 1)) + + try: + sentry_sdk.capture_exception(*args, **kwargs) + sentry_sdk.flush() # https://github.com/getsentry/sentry-python/issues/291 + except Exception: + cloudlog.exception("sentry exception") + + +def set_tag(key: str, value: str) -> None: + sentry_sdk.set_tag(key, value) + + +def init(project: SentryProject) -> bool: + build_metadata = get_build_metadata() + # forks like to mess with this, so double check + comma_remote = build_metadata.openpilot.comma_remote and "commaai" in build_metadata.openpilot.git_origin + if not comma_remote or not is_registered_device() or PC: + return False + + env = "release" if build_metadata.tested_channel else "master" + dongle_id = Params().get("DongleId") + + integrations = [] + if project == SentryProject.SELFDRIVE: + integrations.append(ThreadingIntegration(propagate_hub=True)) + + sentry_sdk.init(project.value, + default_integrations=False, + release=get_version(), + integrations=integrations, + traces_sample_rate=1.0, + max_value_length=8192, + environment=env) + + sentry_sdk.set_user({"id": dongle_id}) + sentry_sdk.set_tag("dirty", build_metadata.openpilot.is_dirty) + sentry_sdk.set_tag("origin", build_metadata.openpilot.git_origin) + sentry_sdk.set_tag("branch", build_metadata.channel) + sentry_sdk.set_tag("commit", build_metadata.openpilot.git_commit) + sentry_sdk.set_tag("device", HARDWARE.get_device_type()) + + return True diff --git a/system/statsd.py b/system/statsd.py new file mode 100755 index 0000000000..d60064fc91 --- /dev/null +++ b/system/statsd.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +import os +import zmq +import time +import uuid +from pathlib import Path +from collections import defaultdict +from datetime import datetime, UTC +from typing import NoReturn + +from openpilot.common.params import Params +from cereal.messaging import SubMaster +from openpilot.system.hardware.hw import Paths +from openpilot.common.swaglog import cloudlog +from openpilot.system.hardware import HARDWARE +from openpilot.common.file_helpers import atomic_write_in_dir +from openpilot.system.version import get_build_metadata +from openpilot.system.loggerd.config import STATS_DIR_FILE_LIMIT, STATS_SOCKET, STATS_FLUSH_TIME_S + + +class METRIC_TYPE: + GAUGE = 'g' + SAMPLE = 'sa' + +class StatLog: + def __init__(self): + self.pid = None + self.zctx = None + self.sock = None + + def connect(self) -> None: + self.zctx = zmq.Context() + self.sock = self.zctx.socket(zmq.PUSH) + self.sock.setsockopt(zmq.LINGER, 10) + self.sock.connect(STATS_SOCKET) + self.pid = os.getpid() + + def __del__(self): + if self.sock is not None: + self.sock.close() + if self.zctx is not None: + self.zctx.term() + + def _send(self, metric: str) -> None: + if os.getpid() != self.pid: + self.connect() + + try: + self.sock.send_string(metric, zmq.NOBLOCK) + except zmq.error.Again: + # drop :/ + pass + + def gauge(self, name: str, value: float) -> None: + self._send(f"{name}:{value}|{METRIC_TYPE.GAUGE}") + + # Samples will be recorded in a buffer and at aggregation time, + # statistical properties will be logged (mean, count, percentiles, ...) + def sample(self, name: str, value: float): + self._send(f"{name}:{value}|{METRIC_TYPE.SAMPLE}") + + +def main() -> NoReturn: + dongle_id = Params().get("DongleId") + def get_influxdb_line(measurement: str, value: float | dict[str, float], timestamp: datetime, tags: dict) -> str: + res = f"{measurement}" + for k, v in tags.items(): + res += f",{k}={str(v)}" + res += " " + + if isinstance(value, float): + value = {'value': value} + + for k, v in value.items(): + res += f"{k}={v}," + + res += f"dongle_id=\"{dongle_id}\" {int(timestamp.timestamp() * 1e9)}\n" + return res + + # open statistics socket + ctx = zmq.Context.instance() + sock = ctx.socket(zmq.PULL) + sock.bind(STATS_SOCKET) + + STATS_DIR = Paths.stats_root() + + # initialize stats directory + Path(STATS_DIR).mkdir(parents=True, exist_ok=True) + + build_metadata = get_build_metadata() + + # initialize tags + tags = { + 'started': False, + 'version': build_metadata.openpilot.version, + 'branch': build_metadata.channel, + 'dirty': build_metadata.openpilot.is_dirty, + 'origin': build_metadata.openpilot.git_normalized_origin, + 'deviceType': HARDWARE.get_device_type(), + } + + # subscribe to deviceState for started state + sm = SubMaster(['deviceState']) + + idx = 0 + boot_uid = str(uuid.uuid4())[:8] + last_flush_time = time.monotonic() + gauges = {} + samples: dict[str, list[float]] = defaultdict(list) + try: + while True: + started_prev = sm['deviceState'].started + sm.update() + + # Update metrics + while True: + try: + metric = sock.recv_string(zmq.NOBLOCK) + try: + metric_type = metric.split('|')[1] + metric_name = metric.split(':')[0] + metric_value = float(metric.split('|')[0].split(':')[1]) + + if metric_type == METRIC_TYPE.GAUGE: + gauges[metric_name] = metric_value + elif metric_type == METRIC_TYPE.SAMPLE: + samples[metric_name].append(metric_value) + else: + cloudlog.event("unknown metric type", metric_type=metric_type) + except Exception: + cloudlog.event("malformed metric", metric=metric) + except zmq.error.Again: + break + + # flush when started state changes or after FLUSH_TIME_S + if (time.monotonic() > last_flush_time + STATS_FLUSH_TIME_S) or (sm['deviceState'].started != started_prev): + result = "" + current_time = datetime.now(UTC) + tags['started'] = sm['deviceState'].started + + for key, value in gauges.items(): + result += get_influxdb_line(f"gauge.{key}", value, current_time, tags) + + for key, values in samples.items(): + values.sort() + sample_count = len(values) + sample_sum = sum(values) + + stats = { + 'count': sample_count, + 'min': values[0], + 'max': values[-1], + 'mean': sample_sum / sample_count, + } + for percentile in [0.05, 0.5, 0.95]: + value = values[int(round(percentile * (sample_count - 1)))] + stats[f"p{int(percentile * 100)}"] = value + + result += get_influxdb_line(f"sample.{key}", stats, current_time, tags) + + # clear intermediate data + gauges.clear() + samples.clear() + last_flush_time = time.monotonic() + + # check that we aren't filling up the drive + if len(os.listdir(STATS_DIR)) < STATS_DIR_FILE_LIMIT: + if len(result) > 0: + stats_path = os.path.join(STATS_DIR, f"{boot_uid}_{idx}") + with atomic_write_in_dir(stats_path) as f: + f.write(result) + idx += 1 + else: + cloudlog.error("stats dir full") + finally: + sock.close() + ctx.term() + + +if __name__ == "__main__": + main() +else: + statlog = StatLog() diff --git a/system/tests/__init__.py b/system/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/tests/test_logmessaged.py b/system/tests/test_logmessaged.py new file mode 100644 index 0000000000..9ccc8ef53b --- /dev/null +++ b/system/tests/test_logmessaged.py @@ -0,0 +1,55 @@ +import glob +import os +import time + +import cereal.messaging as messaging +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.hardware.hw import Paths +from openpilot.common.swaglog import cloudlog, ipchandler + + +class TestLogmessaged: + def setup_method(self): + # clear the IPC buffer in case some other tests used cloudlog and filled it + ipchandler.close() + ipchandler.connect() + + managed_processes['logmessaged'].start() + self.sock = messaging.sub_sock("logMessage", timeout=1000, conflate=False) + self.error_sock = messaging.sub_sock("logMessage", timeout=1000, conflate=False) + + # ensure sockets are connected + time.sleep(0.5) + messaging.drain_sock(self.sock) + messaging.drain_sock(self.error_sock) + + def teardown_method(self): + del self.sock + del self.error_sock + managed_processes['logmessaged'].stop(block=True) + + def _get_log_files(self): + return list(glob.glob(os.path.join(Paths.swaglog_root(), "swaglog.*"))) + + def test_simple_log(self): + msgs = [f"abc {i}" for i in range(10)] + for m in msgs: + cloudlog.error(m) + time.sleep(0.5) + m = messaging.drain_sock(self.sock) + assert len(m) == len(msgs) + assert len(self._get_log_files()) >= 1 + + def test_big_log(self): + n = 10 + msg = "a"*3*1024*1024 + for _ in range(n): + cloudlog.info(msg) + time.sleep(0.5) + + msgs = messaging.drain_sock(self.sock) + assert len(msgs) == 0 + + logsize = sum([os.path.getsize(f) for f in self._get_log_files()]) + assert (n*len(msg)) < logsize < (n*(len(msg)+1024)) + diff --git a/system/timed.py b/system/timed.py new file mode 100755 index 0000000000..b7131b04c0 --- /dev/null +++ b/system/timed.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +import datetime +import subprocess +import time +from typing import NoReturn + +import cereal.messaging as messaging +from openpilot.common.time_helpers import min_date, system_time_valid +from openpilot.common.swaglog import cloudlog +from openpilot.common.params import Params +from openpilot.common.gps import get_gps_location_service + + +def set_time(new_time): + diff = datetime.datetime.now() - new_time + if abs(diff) < datetime.timedelta(seconds=10): + cloudlog.debug(f"Time diff too small: {diff}") + return + + cloudlog.debug(f"Setting time to {new_time}") + try: + subprocess.run(f"TZ=UTC date -s '{new_time}'", shell=True, check=True) + except subprocess.CalledProcessError: + cloudlog.exception("timed.failed_setting_time") + + +def main() -> NoReturn: + """ + timed has two responsibilities: + - getting the current time from GPS + - publishing the time in the logs + + AGNOS will also use NTP to update the time. + """ + + params = Params() + gps_location_service = get_gps_location_service(params) + + pm = messaging.PubMaster(['clocks']) + sm = messaging.SubMaster([gps_location_service]) + while True: + sm.update(1000) + + msg = messaging.new_message('clocks') + msg.valid = system_time_valid() + msg.clocks.wallTimeNanos = time.time_ns() + pm.send('clocks', msg) + + gps = sm[gps_location_service] + gps_time = datetime.datetime.fromtimestamp(gps.unixTimestampMillis / 1000.) + if not sm.updated[gps_location_service] or (time.monotonic() - sm.logMonoTime[gps_location_service] / 1e9) > 2.0: + continue + if not gps.hasFix: + continue + if gps_time < min_date(): + continue + + set_time(gps_time) + time.sleep(10) + +if __name__ == "__main__": + main() diff --git a/system/tombstoned.py b/system/tombstoned.py new file mode 100755 index 0000000000..5bcced2666 --- /dev/null +++ b/system/tombstoned.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +import datetime +import os +import re +import shutil +import signal +import subprocess +import time +import glob +from typing import NoReturn + +import openpilot.system.sentry as sentry +from openpilot.system.hardware.hw import Paths +from openpilot.common.swaglog import cloudlog +from openpilot.system.version import get_build_metadata + +MAX_SIZE = 1_000_000 * 100 # allow up to 100M +MAX_TOMBSTONE_FN_LEN = 62 # 85 - 23 ("/crash/") + +TOMBSTONE_DIR = "/data/tombstones/" +APPORT_DIR = "/var/crash/" + + +def safe_fn(s): + extra = ['_'] + return "".join(c for c in s if c.isalnum() or c in extra).rstrip() + + +def clear_apport_folder(): + for f in glob.glob(APPORT_DIR + '*'): + try: + os.remove(f) + except Exception: + pass + + +def get_apport_stacktrace(fn): + try: + cmd = f'apport-retrace -s <(cat <(echo "Package: openpilot") "{fn}")' + return subprocess.check_output(cmd, shell=True, encoding='utf8', timeout=30, executable='/bin/bash') + except subprocess.CalledProcessError: + return "Error getting stacktrace" + except subprocess.TimeoutExpired: + return "Timeout getting stacktrace" + + +def get_tombstones(): + """Returns list of (filename, ctime) for all crashlogs""" + files = [] + if os.path.exists(APPORT_DIR): + with os.scandir(APPORT_DIR) as d: + # Loop over first 1000 directory entries + for _, f in zip(range(1000), d, strict=False): + if f.name.startswith("tombstone"): + files.append((f.path, int(f.stat().st_ctime))) + elif f.name.endswith(".crash") and f.stat().st_mode == 0o100640: + files.append((f.path, int(f.stat().st_ctime))) + return files + + +def report_tombstone_apport(fn): + f_size = os.path.getsize(fn) + if f_size > MAX_SIZE: + cloudlog.error(f"Tombstone {fn} too big, {f_size}. Skipping...") + return + + message = "" # One line description of the crash + contents = "" # Full file contents without coredump + path = "" # File path relative to openpilot directory + + proc_maps = False + + with open(fn) as f: + for line in f: + if "CoreDump" in line: + break + elif "ProcMaps" in line: + proc_maps = True + elif "ProcStatus" in line: + proc_maps = False + + if not proc_maps: + contents += line + + if "ExecutablePath" in line: + path = line.strip().split(': ')[-1] + path = path.replace('/data/openpilot/', '') + message += path + elif "Signal" in line: + message += " - " + line.strip() + + try: + sig_num = int(line.strip().split(': ')[-1]) + message += " (" + signal.Signals(sig_num).name + ")" + except ValueError: + pass + + stacktrace = get_apport_stacktrace(fn) + stacktrace_s = stacktrace.split('\n') + crash_function = "No stacktrace" + + if len(stacktrace_s) > 2: + found = False + + # Try to find first entry in openpilot, fall back to first line + for line in stacktrace_s: + if "at selfdrive/" in line: + crash_function = line + found = True + break + + if not found: + crash_function = stacktrace_s[1] + + # Remove arguments that can contain pointers to make sentry one-liner unique + crash_function = " ".join(x for x in crash_function.split(' ')[1:] if not x.startswith('0x')) + crash_function = re.sub(r'\(.*?\)', '', crash_function) + + contents = stacktrace + "\n\n" + contents + message = message + " - " + crash_function + sentry.report_tombstone(fn, message, contents) + + # Copy crashlog to upload folder + clean_path = path.replace('/', '_') + date = datetime.datetime.now().strftime("%Y-%m-%d--%H-%M-%S") + + build_metadata = get_build_metadata() + + new_fn = f"{date}_{(build_metadata.openpilot.git_commit or 'nocommit')[:8]}_{safe_fn(clean_path)}"[:MAX_TOMBSTONE_FN_LEN] + + crashlog_dir = os.path.join(Paths.log_root(), "crash") + os.makedirs(crashlog_dir, exist_ok=True) + + # Files could be on different filesystems, copy, then delete + shutil.copy(fn, os.path.join(crashlog_dir, new_fn)) + + try: + os.remove(fn) + except PermissionError: + pass + + +def main() -> NoReturn: + should_report = sentry.init(sentry.SentryProject.SELFDRIVE_NATIVE) + + # Clear apport folder on start, otherwise duplicate crashes won't register + clear_apport_folder() + initial_tombstones = set(get_tombstones()) + + while True: + now_tombstones = set(get_tombstones()) + + for fn, _ in (now_tombstones - initial_tombstones): + # clear logs if we're not interested in them + if not should_report: + try: + os.remove(fn) + except Exception: + pass + continue + + try: + cloudlog.info(f"reporting new tombstone {fn}") + if fn.endswith(".crash"): + report_tombstone_apport(fn) + else: + cloudlog.error(f"unknown crash type: {fn}") + except Exception: + cloudlog.exception(f"Error reporting tombstone {fn}") + + initial_tombstones = now_tombstones + time.sleep(5) + + +if __name__ == "__main__": + main() diff --git a/system/ubloxd/SConscript b/system/ubloxd/SConscript new file mode 100644 index 0000000000..9eb50760ba --- /dev/null +++ b/system/ubloxd/SConscript @@ -0,0 +1,11 @@ +Import('env') + +if GetOption('kaitai'): + current_dir = Dir('./generated/').srcnode().abspath + python_cmd = f"kaitai-struct-compiler --target python --outdir {current_dir} $SOURCES" + env.Command(File('./generated/ubx.py'), 'ubx.ksy', python_cmd) + env.Command(File('./generated/gps.py'), 'gps.ksy', python_cmd) + env.Command(File('./generated/glonass.py'), 'glonass.ksy', python_cmd) + # kaitai issue: https://github.com/kaitai-io/kaitai_struct/issues/910 + py_glonass_fix = env.Command(None, File('./generated/glonass.py'), "sed -i 's/self._io.align_to_byte()/# self._io.align_to_byte()/' $SOURCES") + env.Depends(py_glonass_fix, File('./generated/glonass.py')) diff --git a/system/ubloxd/generated/glonass.py b/system/ubloxd/generated/glonass.py new file mode 100644 index 0000000000..40aa16bb6f --- /dev/null +++ b/system/ubloxd/generated/glonass.py @@ -0,0 +1,247 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import kaitaistruct +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9): + raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__)) + +class Glonass(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.idle_chip = self._io.read_bits_int_be(1) != 0 + self.string_number = self._io.read_bits_int_be(4) + # workaround for kaitai bit alignment issue (see glonass_fix.patch for C++) + # self._io.align_to_byte() + _on = self.string_number + if _on == 4: + self.data = Glonass.String4(self._io, self, self._root) + elif _on == 1: + self.data = Glonass.String1(self._io, self, self._root) + elif _on == 3: + self.data = Glonass.String3(self._io, self, self._root) + elif _on == 5: + self.data = Glonass.String5(self._io, self, self._root) + elif _on == 2: + self.data = Glonass.String2(self._io, self, self._root) + else: + self.data = Glonass.StringNonImmediate(self._io, self, self._root) + self.hamming_code = self._io.read_bits_int_be(8) + self.pad_1 = self._io.read_bits_int_be(11) + self.superframe_number = self._io.read_bits_int_be(16) + self.pad_2 = self._io.read_bits_int_be(8) + self.frame_number = self._io.read_bits_int_be(8) + + class String4(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.tau_n_sign = self._io.read_bits_int_be(1) != 0 + self.tau_n_value = self._io.read_bits_int_be(21) + self.delta_tau_n_sign = self._io.read_bits_int_be(1) != 0 + self.delta_tau_n_value = self._io.read_bits_int_be(4) + self.e_n = self._io.read_bits_int_be(5) + self.not_used_1 = self._io.read_bits_int_be(14) + self.p4 = self._io.read_bits_int_be(1) != 0 + self.f_t = self._io.read_bits_int_be(4) + self.not_used_2 = self._io.read_bits_int_be(3) + self.n_t = self._io.read_bits_int_be(11) + self.n = self._io.read_bits_int_be(5) + self.m = self._io.read_bits_int_be(2) + + @property + def tau_n(self): + if hasattr(self, '_m_tau_n'): + return self._m_tau_n + + self._m_tau_n = ((self.tau_n_value * -1) if self.tau_n_sign else self.tau_n_value) + return getattr(self, '_m_tau_n', None) + + @property + def delta_tau_n(self): + if hasattr(self, '_m_delta_tau_n'): + return self._m_delta_tau_n + + self._m_delta_tau_n = ((self.delta_tau_n_value * -1) if self.delta_tau_n_sign else self.delta_tau_n_value) + return getattr(self, '_m_delta_tau_n', None) + + + class StringNonImmediate(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.data_1 = self._io.read_bits_int_be(64) + self.data_2 = self._io.read_bits_int_be(8) + + + class String5(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.n_a = self._io.read_bits_int_be(11) + self.tau_c = self._io.read_bits_int_be(32) + self.not_used = self._io.read_bits_int_be(1) != 0 + self.n_4 = self._io.read_bits_int_be(5) + self.tau_gps = self._io.read_bits_int_be(22) + self.l_n = self._io.read_bits_int_be(1) != 0 + + + class String1(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.not_used = self._io.read_bits_int_be(2) + self.p1 = self._io.read_bits_int_be(2) + self.t_k = self._io.read_bits_int_be(12) + self.x_vel_sign = self._io.read_bits_int_be(1) != 0 + self.x_vel_value = self._io.read_bits_int_be(23) + self.x_accel_sign = self._io.read_bits_int_be(1) != 0 + self.x_accel_value = self._io.read_bits_int_be(4) + self.x_sign = self._io.read_bits_int_be(1) != 0 + self.x_value = self._io.read_bits_int_be(26) + + @property + def x_vel(self): + if hasattr(self, '_m_x_vel'): + return self._m_x_vel + + self._m_x_vel = ((self.x_vel_value * -1) if self.x_vel_sign else self.x_vel_value) + return getattr(self, '_m_x_vel', None) + + @property + def x_accel(self): + if hasattr(self, '_m_x_accel'): + return self._m_x_accel + + self._m_x_accel = ((self.x_accel_value * -1) if self.x_accel_sign else self.x_accel_value) + return getattr(self, '_m_x_accel', None) + + @property + def x(self): + if hasattr(self, '_m_x'): + return self._m_x + + self._m_x = ((self.x_value * -1) if self.x_sign else self.x_value) + return getattr(self, '_m_x', None) + + + class String2(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.b_n = self._io.read_bits_int_be(3) + self.p2 = self._io.read_bits_int_be(1) != 0 + self.t_b = self._io.read_bits_int_be(7) + self.not_used = self._io.read_bits_int_be(5) + self.y_vel_sign = self._io.read_bits_int_be(1) != 0 + self.y_vel_value = self._io.read_bits_int_be(23) + self.y_accel_sign = self._io.read_bits_int_be(1) != 0 + self.y_accel_value = self._io.read_bits_int_be(4) + self.y_sign = self._io.read_bits_int_be(1) != 0 + self.y_value = self._io.read_bits_int_be(26) + + @property + def y_vel(self): + if hasattr(self, '_m_y_vel'): + return self._m_y_vel + + self._m_y_vel = ((self.y_vel_value * -1) if self.y_vel_sign else self.y_vel_value) + return getattr(self, '_m_y_vel', None) + + @property + def y_accel(self): + if hasattr(self, '_m_y_accel'): + return self._m_y_accel + + self._m_y_accel = ((self.y_accel_value * -1) if self.y_accel_sign else self.y_accel_value) + return getattr(self, '_m_y_accel', None) + + @property + def y(self): + if hasattr(self, '_m_y'): + return self._m_y + + self._m_y = ((self.y_value * -1) if self.y_sign else self.y_value) + return getattr(self, '_m_y', None) + + + class String3(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.p3 = self._io.read_bits_int_be(1) != 0 + self.gamma_n_sign = self._io.read_bits_int_be(1) != 0 + self.gamma_n_value = self._io.read_bits_int_be(10) + self.not_used = self._io.read_bits_int_be(1) != 0 + self.p = self._io.read_bits_int_be(2) + self.l_n = self._io.read_bits_int_be(1) != 0 + self.z_vel_sign = self._io.read_bits_int_be(1) != 0 + self.z_vel_value = self._io.read_bits_int_be(23) + self.z_accel_sign = self._io.read_bits_int_be(1) != 0 + self.z_accel_value = self._io.read_bits_int_be(4) + self.z_sign = self._io.read_bits_int_be(1) != 0 + self.z_value = self._io.read_bits_int_be(26) + + @property + def gamma_n(self): + if hasattr(self, '_m_gamma_n'): + return self._m_gamma_n + + self._m_gamma_n = ((self.gamma_n_value * -1) if self.gamma_n_sign else self.gamma_n_value) + return getattr(self, '_m_gamma_n', None) + + @property + def z_vel(self): + if hasattr(self, '_m_z_vel'): + return self._m_z_vel + + self._m_z_vel = ((self.z_vel_value * -1) if self.z_vel_sign else self.z_vel_value) + return getattr(self, '_m_z_vel', None) + + @property + def z_accel(self): + if hasattr(self, '_m_z_accel'): + return self._m_z_accel + + self._m_z_accel = ((self.z_accel_value * -1) if self.z_accel_sign else self.z_accel_value) + return getattr(self, '_m_z_accel', None) + + @property + def z(self): + if hasattr(self, '_m_z'): + return self._m_z + + self._m_z = ((self.z_value * -1) if self.z_sign else self.z_value) + return getattr(self, '_m_z', None) + + diff --git a/system/ubloxd/generated/gps.py b/system/ubloxd/generated/gps.py new file mode 100644 index 0000000000..a999016f3e --- /dev/null +++ b/system/ubloxd/generated/gps.py @@ -0,0 +1,193 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import kaitaistruct +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO + + +if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9): + raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__)) + +class Gps(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.tlm = Gps.Tlm(self._io, self, self._root) + self.how = Gps.How(self._io, self, self._root) + _on = self.how.subframe_id + if _on == 1: + self.body = Gps.Subframe1(self._io, self, self._root) + elif _on == 2: + self.body = Gps.Subframe2(self._io, self, self._root) + elif _on == 3: + self.body = Gps.Subframe3(self._io, self, self._root) + elif _on == 4: + self.body = Gps.Subframe4(self._io, self, self._root) + + class Subframe1(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.week_no = self._io.read_bits_int_be(10) + self.code = self._io.read_bits_int_be(2) + self.sv_accuracy = self._io.read_bits_int_be(4) + self.sv_health = self._io.read_bits_int_be(6) + self.iodc_msb = self._io.read_bits_int_be(2) + self.l2_p_data_flag = self._io.read_bits_int_be(1) != 0 + self.reserved1 = self._io.read_bits_int_be(23) + self.reserved2 = self._io.read_bits_int_be(24) + self.reserved3 = self._io.read_bits_int_be(24) + self.reserved4 = self._io.read_bits_int_be(16) + self._io.align_to_byte() + self.t_gd = self._io.read_s1() + self.iodc_lsb = self._io.read_u1() + self.t_oc = self._io.read_u2be() + self.af_2 = self._io.read_s1() + self.af_1 = self._io.read_s2be() + self.af_0_sign = self._io.read_bits_int_be(1) != 0 + self.af_0_value = self._io.read_bits_int_be(21) + self.reserved5 = self._io.read_bits_int_be(2) + + @property + def af_0(self): + if hasattr(self, '_m_af_0'): + return self._m_af_0 + + self._m_af_0 = ((self.af_0_value - (1 << 21)) if self.af_0_sign else self.af_0_value) + return getattr(self, '_m_af_0', None) + + + class Subframe3(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.c_ic = self._io.read_s2be() + self.omega_0 = self._io.read_s4be() + self.c_is = self._io.read_s2be() + self.i_0 = self._io.read_s4be() + self.c_rc = self._io.read_s2be() + self.omega = self._io.read_s4be() + self.omega_dot_sign = self._io.read_bits_int_be(1) != 0 + self.omega_dot_value = self._io.read_bits_int_be(23) + self._io.align_to_byte() + self.iode = self._io.read_u1() + self.idot_sign = self._io.read_bits_int_be(1) != 0 + self.idot_value = self._io.read_bits_int_be(13) + self.reserved = self._io.read_bits_int_be(2) + + @property + def omega_dot(self): + if hasattr(self, '_m_omega_dot'): + return self._m_omega_dot + + self._m_omega_dot = ((self.omega_dot_value - (1 << 23)) if self.omega_dot_sign else self.omega_dot_value) + return getattr(self, '_m_omega_dot', None) + + @property + def idot(self): + if hasattr(self, '_m_idot'): + return self._m_idot + + self._m_idot = ((self.idot_value - (1 << 13)) if self.idot_sign else self.idot_value) + return getattr(self, '_m_idot', None) + + + class Subframe4(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.data_id = self._io.read_bits_int_be(2) + self.page_id = self._io.read_bits_int_be(6) + self._io.align_to_byte() + _on = self.page_id + if _on == 56: + self.body = Gps.Subframe4.IonosphereData(self._io, self, self._root) + + class IonosphereData(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.a0 = self._io.read_s1() + self.a1 = self._io.read_s1() + self.a2 = self._io.read_s1() + self.a3 = self._io.read_s1() + self.b0 = self._io.read_s1() + self.b1 = self._io.read_s1() + self.b2 = self._io.read_s1() + self.b3 = self._io.read_s1() + + + + class How(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.tow_count = self._io.read_bits_int_be(17) + self.alert = self._io.read_bits_int_be(1) != 0 + self.anti_spoof = self._io.read_bits_int_be(1) != 0 + self.subframe_id = self._io.read_bits_int_be(3) + self.reserved = self._io.read_bits_int_be(2) + + + class Tlm(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.preamble = self._io.read_bytes(1) + if not self.preamble == b"\x8B": + raise kaitaistruct.ValidationNotEqualError(b"\x8B", self.preamble, self._io, u"/types/tlm/seq/0") + self.tlm = self._io.read_bits_int_be(14) + self.integrity_status = self._io.read_bits_int_be(1) != 0 + self.reserved = self._io.read_bits_int_be(1) != 0 + + + class Subframe2(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.iode = self._io.read_u1() + self.c_rs = self._io.read_s2be() + self.delta_n = self._io.read_s2be() + self.m_0 = self._io.read_s4be() + self.c_uc = self._io.read_s2be() + self.e = self._io.read_s4be() + self.c_us = self._io.read_s2be() + self.sqrt_a = self._io.read_u4be() + self.t_oe = self._io.read_u2be() + self.fit_interval_flag = self._io.read_bits_int_be(1) != 0 + self.aoda = self._io.read_bits_int_be(5) + self.reserved = self._io.read_bits_int_be(2) + + + diff --git a/system/ubloxd/generated/ubx.py b/system/ubloxd/generated/ubx.py new file mode 100644 index 0000000000..9946584388 --- /dev/null +++ b/system/ubloxd/generated/ubx.py @@ -0,0 +1,273 @@ +# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +import kaitaistruct +from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO +from enum import Enum + + +if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9): + raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__)) + +class Ubx(KaitaiStruct): + + class GnssType(Enum): + gps = 0 + sbas = 1 + galileo = 2 + beidou = 3 + imes = 4 + qzss = 5 + glonass = 6 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.magic = self._io.read_bytes(2) + if not self.magic == b"\xB5\x62": + raise kaitaistruct.ValidationNotEqualError(b"\xB5\x62", self.magic, self._io, u"/seq/0") + self.msg_type = self._io.read_u2be() + self.length = self._io.read_u2le() + _on = self.msg_type + if _on == 2569: + self.body = Ubx.MonHw(self._io, self, self._root) + elif _on == 533: + self.body = Ubx.RxmRawx(self._io, self, self._root) + elif _on == 531: + self.body = Ubx.RxmSfrbx(self._io, self, self._root) + elif _on == 309: + self.body = Ubx.NavSat(self._io, self, self._root) + elif _on == 2571: + self.body = Ubx.MonHw2(self._io, self, self._root) + elif _on == 263: + self.body = Ubx.NavPvt(self._io, self, self._root) + + class RxmRawx(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.rcv_tow = self._io.read_f8le() + self.week = self._io.read_u2le() + self.leap_s = self._io.read_s1() + self.num_meas = self._io.read_u1() + self.rec_stat = self._io.read_u1() + self.reserved1 = self._io.read_bytes(3) + self._raw_meas = [] + self.meas = [] + for i in range(self.num_meas): + self._raw_meas.append(self._io.read_bytes(32)) + _io__raw_meas = KaitaiStream(BytesIO(self._raw_meas[i])) + self.meas.append(Ubx.RxmRawx.Measurement(_io__raw_meas, self, self._root)) + + + class Measurement(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.pr_mes = self._io.read_f8le() + self.cp_mes = self._io.read_f8le() + self.do_mes = self._io.read_f4le() + self.gnss_id = KaitaiStream.resolve_enum(Ubx.GnssType, self._io.read_u1()) + self.sv_id = self._io.read_u1() + self.reserved2 = self._io.read_bytes(1) + self.freq_id = self._io.read_u1() + self.lock_time = self._io.read_u2le() + self.cno = self._io.read_u1() + self.pr_stdev = self._io.read_u1() + self.cp_stdev = self._io.read_u1() + self.do_stdev = self._io.read_u1() + self.trk_stat = self._io.read_u1() + self.reserved3 = self._io.read_bytes(1) + + + + class RxmSfrbx(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.gnss_id = KaitaiStream.resolve_enum(Ubx.GnssType, self._io.read_u1()) + self.sv_id = self._io.read_u1() + self.reserved1 = self._io.read_bytes(1) + self.freq_id = self._io.read_u1() + self.num_words = self._io.read_u1() + self.reserved2 = self._io.read_bytes(1) + self.version = self._io.read_u1() + self.reserved3 = self._io.read_bytes(1) + self.body = [] + for i in range(self.num_words): + self.body.append(self._io.read_u4le()) + + + + class NavSat(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.itow = self._io.read_u4le() + self.version = self._io.read_u1() + self.num_svs = self._io.read_u1() + self.reserved = self._io.read_bytes(2) + self._raw_svs = [] + self.svs = [] + for i in range(self.num_svs): + self._raw_svs.append(self._io.read_bytes(12)) + _io__raw_svs = KaitaiStream(BytesIO(self._raw_svs[i])) + self.svs.append(Ubx.NavSat.Nav(_io__raw_svs, self, self._root)) + + + class Nav(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.gnss_id = KaitaiStream.resolve_enum(Ubx.GnssType, self._io.read_u1()) + self.sv_id = self._io.read_u1() + self.cno = self._io.read_u1() + self.elev = self._io.read_s1() + self.azim = self._io.read_s2le() + self.pr_res = self._io.read_s2le() + self.flags = self._io.read_u4le() + + + + class NavPvt(KaitaiStruct): + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.i_tow = self._io.read_u4le() + self.year = self._io.read_u2le() + self.month = self._io.read_u1() + self.day = self._io.read_u1() + self.hour = self._io.read_u1() + self.min = self._io.read_u1() + self.sec = self._io.read_u1() + self.valid = self._io.read_u1() + self.t_acc = self._io.read_u4le() + self.nano = self._io.read_s4le() + self.fix_type = self._io.read_u1() + self.flags = self._io.read_u1() + self.flags2 = self._io.read_u1() + self.num_sv = self._io.read_u1() + self.lon = self._io.read_s4le() + self.lat = self._io.read_s4le() + self.height = self._io.read_s4le() + self.h_msl = self._io.read_s4le() + self.h_acc = self._io.read_u4le() + self.v_acc = self._io.read_u4le() + self.vel_n = self._io.read_s4le() + self.vel_e = self._io.read_s4le() + self.vel_d = self._io.read_s4le() + self.g_speed = self._io.read_s4le() + self.head_mot = self._io.read_s4le() + self.s_acc = self._io.read_s4le() + self.head_acc = self._io.read_u4le() + self.p_dop = self._io.read_u2le() + self.flags3 = self._io.read_u1() + self.reserved1 = self._io.read_bytes(5) + self.head_veh = self._io.read_s4le() + self.mag_dec = self._io.read_s2le() + self.mag_acc = self._io.read_u2le() + + + class MonHw2(KaitaiStruct): + + class ConfigSource(Enum): + flash = 102 + otp = 111 + config_pins = 112 + rom = 113 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.ofs_i = self._io.read_s1() + self.mag_i = self._io.read_u1() + self.ofs_q = self._io.read_s1() + self.mag_q = self._io.read_u1() + self.cfg_source = KaitaiStream.resolve_enum(Ubx.MonHw2.ConfigSource, self._io.read_u1()) + self.reserved1 = self._io.read_bytes(3) + self.low_lev_cfg = self._io.read_u4le() + self.reserved2 = self._io.read_bytes(8) + self.post_status = self._io.read_u4le() + self.reserved3 = self._io.read_bytes(4) + + + class MonHw(KaitaiStruct): + + class AntennaStatus(Enum): + init = 0 + dontknow = 1 + ok = 2 + short = 3 + open = 4 + + class AntennaPower(Enum): + false = 0 + true = 1 + dontknow = 2 + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.pin_sel = self._io.read_u4le() + self.pin_bank = self._io.read_u4le() + self.pin_dir = self._io.read_u4le() + self.pin_val = self._io.read_u4le() + self.noise_per_ms = self._io.read_u2le() + self.agc_cnt = self._io.read_u2le() + self.a_status = KaitaiStream.resolve_enum(Ubx.MonHw.AntennaStatus, self._io.read_u1()) + self.a_power = KaitaiStream.resolve_enum(Ubx.MonHw.AntennaPower, self._io.read_u1()) + self.flags = self._io.read_u1() + self.reserved1 = self._io.read_bytes(1) + self.used_mask = self._io.read_u4le() + self.vp = self._io.read_bytes(17) + self.jam_ind = self._io.read_u1() + self.reserved2 = self._io.read_bytes(2) + self.pin_irq = self._io.read_u4le() + self.pull_h = self._io.read_u4le() + self.pull_l = self._io.read_u4le() + + + @property + def checksum(self): + if hasattr(self, '_m_checksum'): + return self._m_checksum + + _pos = self._io.pos() + self._io.seek((self.length + 6)) + self._m_checksum = self._io.read_u2le() + self._io.seek(_pos) + return getattr(self, '_m_checksum', None) + + diff --git a/system/ubloxd/glonass.ksy b/system/ubloxd/glonass.ksy new file mode 100644 index 0000000000..be99f6e497 --- /dev/null +++ b/system/ubloxd/glonass.ksy @@ -0,0 +1,176 @@ +# http://gauss.gge.unb.ca/GLONASS.ICD.pdf +# some variables are misprinted but good in the old doc +# https://www.unavco.org/help/glossary/docs/ICD_GLONASS_4.0_(1998)_en.pdf +meta: + id: glonass + endian: be + bit-endian: be +seq: + - id: idle_chip + type: b1 + - id: string_number + type: b4 + - id: data + type: + switch-on: string_number + cases: + 1: string_1 + 2: string_2 + 3: string_3 + 4: string_4 + 5: string_5 + _: string_non_immediate + - id: hamming_code + type: b8 + - id: pad_1 + type: b11 + - id: superframe_number + type: b16 + - id: pad_2 + type: b8 + - id: frame_number + type: b8 + +types: + string_1: + seq: + - id: not_used + type: b2 + - id: p1 + type: b2 + - id: t_k + type: b12 + - id: x_vel_sign + type: b1 + - id: x_vel_value + type: b23 + - id: x_accel_sign + type: b1 + - id: x_accel_value + type: b4 + - id: x_sign + type: b1 + - id: x_value + type: b26 + instances: + x_vel: + value: 'x_vel_sign ? (x_vel_value * (-1)) : x_vel_value' + x_accel: + value: 'x_accel_sign ? (x_accel_value * (-1)) : x_accel_value' + x: + value: 'x_sign ? (x_value * (-1)) : x_value' + string_2: + seq: + - id: b_n + type: b3 + - id: p2 + type: b1 + - id: t_b + type: b7 + - id: not_used + type: b5 + - id: y_vel_sign + type: b1 + - id: y_vel_value + type: b23 + - id: y_accel_sign + type: b1 + - id: y_accel_value + type: b4 + - id: y_sign + type: b1 + - id: y_value + type: b26 + instances: + y_vel: + value: 'y_vel_sign ? (y_vel_value * (-1)) : y_vel_value' + y_accel: + value: 'y_accel_sign ? (y_accel_value * (-1)) : y_accel_value' + y: + value: 'y_sign ? (y_value * (-1)) : y_value' + string_3: + seq: + - id: p3 + type: b1 + - id: gamma_n_sign + type: b1 + - id: gamma_n_value + type: b10 + - id: not_used + type: b1 + - id: p + type: b2 + - id: l_n + type: b1 + - id: z_vel_sign + type: b1 + - id: z_vel_value + type: b23 + - id: z_accel_sign + type: b1 + - id: z_accel_value + type: b4 + - id: z_sign + type: b1 + - id: z_value + type: b26 + instances: + gamma_n: + value: 'gamma_n_sign ? (gamma_n_value * (-1)) : gamma_n_value' + z_vel: + value: 'z_vel_sign ? (z_vel_value * (-1)) : z_vel_value' + z_accel: + value: 'z_accel_sign ? (z_accel_value * (-1)) : z_accel_value' + z: + value: 'z_sign ? (z_value * (-1)) : z_value' + string_4: + seq: + - id: tau_n_sign + type: b1 + - id: tau_n_value + type: b21 + - id: delta_tau_n_sign + type: b1 + - id: delta_tau_n_value + type: b4 + - id: e_n + type: b5 + - id: not_used_1 + type: b14 + - id: p4 + type: b1 + - id: f_t + type: b4 + - id: not_used_2 + type: b3 + - id: n_t + type: b11 + - id: n + type: b5 + - id: m + type: b2 + instances: + tau_n: + value: 'tau_n_sign ? (tau_n_value * (-1)) : tau_n_value' + delta_tau_n: + value: 'delta_tau_n_sign ? (delta_tau_n_value * (-1)) : delta_tau_n_value' + string_5: + seq: + - id: n_a + type: b11 + - id: tau_c + type: b32 + - id: not_used + type: b1 + - id: n_4 + type: b5 + - id: tau_gps + type: b22 + - id: l_n + type: b1 + string_non_immediate: + seq: + - id: data_1 + type: b64 + - id: data_2 + type: b8 diff --git a/system/ubloxd/gps.ksy b/system/ubloxd/gps.ksy new file mode 100644 index 0000000000..893ad1b25b --- /dev/null +++ b/system/ubloxd/gps.ksy @@ -0,0 +1,189 @@ +# https://www.gps.gov/technical/icwg/IS-GPS-200E.pdf +meta: + id: gps + endian: be + bit-endian: be +seq: + - id: tlm + type: tlm + - id: how + type: how + - id: body + type: + switch-on: how.subframe_id + cases: + 1: subframe_1 + 2: subframe_2 + 3: subframe_3 + 4: subframe_4 +types: + tlm: + seq: + - id: preamble + contents: [0x8b] + - id: tlm + type: b14 + - id: integrity_status + type: b1 + - id: reserved + type: b1 + how: + seq: + - id: tow_count + type: b17 + - id: alert + type: b1 + - id: anti_spoof + type: b1 + - id: subframe_id + type: b3 + - id: reserved + type: b2 + subframe_1: + seq: + # Word 3 + - id: week_no + type: b10 + - id: code + type: b2 + - id: sv_accuracy + type: b4 + - id: sv_health + type: b6 + - id: iodc_msb + type: b2 + # Word 4 + - id: l2_p_data_flag + type: b1 + - id: reserved1 + type: b23 + # Word 5 + - id: reserved2 + type: b24 + # Word 6 + - id: reserved3 + type: b24 + # Word 7 + - id: reserved4 + type: b16 + - id: t_gd + type: s1 + # Word 8 + - id: iodc_lsb + type: u1 + - id: t_oc + type: u2 + # Word 9 + - id: af_2 + type: s1 + - id: af_1 + type: s2 + # Word 10 + - id: af_0_sign + type: b1 + - id: af_0_value + type: b21 + - id: reserved5 + type: b2 + instances: + af_0: + value: 'af_0_sign ? (af_0_value - (1 << 21)) : af_0_value' + subframe_2: + seq: + # Word 3 + - id: iode + type: u1 + - id: c_rs + type: s2 + # Word 4 & 5 + - id: delta_n + type: s2 + - id: m_0 + type: s4 + # Word 6 & 7 + - id: c_uc + type: s2 + - id: e + type: s4 + # Word 8 & 9 + - id: c_us + type: s2 + - id: sqrt_a + type: u4 + # Word 10 + - id: t_oe + type: u2 + - id: fit_interval_flag + type: b1 + - id: aoda + type: b5 + - id: reserved + type: b2 + subframe_3: + seq: + # Word 3 & 4 + - id: c_ic + type: s2 + - id: omega_0 + type: s4 + # Word 5 & 6 + - id: c_is + type: s2 + - id: i_0 + type: s4 + # Word 7 & 8 + - id: c_rc + type: s2 + - id: omega + type: s4 + # Word 9 + - id: omega_dot_sign + type: b1 + - id: omega_dot_value + type: b23 + # Word 10 + - id: iode + type: u1 + - id: idot_sign + type: b1 + - id: idot_value + type: b13 + - id: reserved + type: b2 + instances: + omega_dot: + value: 'omega_dot_sign ? (omega_dot_value - (1 << 23)) : omega_dot_value' + idot: + value: 'idot_sign ? (idot_value - (1 << 13)) : idot_value' + subframe_4: + seq: + # Word 3 + - id: data_id + type: b2 + - id: page_id + type: b6 + - id: body + type: + switch-on: page_id + cases: + 56: ionosphere_data + types: + ionosphere_data: + seq: + - id: a0 + type: s1 + - id: a1 + type: s1 + - id: a2 + type: s1 + - id: a3 + type: s1 + - id: b0 + type: s1 + - id: b1 + type: s1 + - id: b2 + type: s1 + - id: b3 + type: s1 + diff --git a/system/ubloxd/pigeond.py b/system/ubloxd/pigeond.py new file mode 100755 index 0000000000..e458a9d65f --- /dev/null +++ b/system/ubloxd/pigeond.py @@ -0,0 +1,309 @@ +#!/usr/bin/env python3 +import sys +import time +import signal +import serial +import struct +import requests +import urllib.parse +from datetime import datetime, UTC + +from cereal import messaging +from openpilot.common.time_helpers import system_time_valid +from openpilot.common.params import Params +from openpilot.common.swaglog import cloudlog +from openpilot.system.hardware import TICI +from openpilot.common.gpio import gpio_init, gpio_set +from openpilot.system.hardware.tici.pins import GPIO + +UBLOX_TTY = "/dev/ttyHS0" + +UBLOX_ACK = b"\xb5\x62\x05\x01\x02\x00" +UBLOX_NACK = b"\xb5\x62\x05\x00\x02\x00" +UBLOX_SOS_ACK = b"\xb5\x62\x09\x14\x08\x00\x02\x00\x00\x00\x01\x00\x00\x00" +UBLOX_SOS_NACK = b"\xb5\x62\x09\x14\x08\x00\x02\x00\x00\x00\x00\x00\x00\x00" +UBLOX_BACKUP_RESTORE_MSG = b"\xb5\x62\x09\x14\x08\x00\x03" +UBLOX_ASSIST_ACK = b"\xb5\x62\x13\x60\x08\x00" + +def set_power(enabled: bool) -> None: + gpio_init(GPIO.UBLOX_SAFEBOOT_N, True) + gpio_init(GPIO.GNSS_PWR_EN, True) + gpio_init(GPIO.UBLOX_RST_N, True) + + gpio_set(GPIO.UBLOX_SAFEBOOT_N, True) + gpio_set(GPIO.GNSS_PWR_EN, enabled) + gpio_set(GPIO.UBLOX_RST_N, enabled) + +def add_ubx_checksum(msg: bytes) -> bytes: + A = B = 0 + for b in msg[2:]: + A = (A + b) % 256 + B = (B + A) % 256 + return msg + bytes([A, B]) + +def get_assistnow_messages(token: str) -> list[bytes]: + # make request + # TODO: implement adding the last known location + r = requests.get("https://online-live2.services.u-blox.com/GetOnlineData.ashx", params=urllib.parse.urlencode({ + 'token': token, + 'gnss': 'gps,glo', + 'datatype': 'eph,alm,aux', + }, safe=':,'), timeout=5) + assert r.status_code == 200, "Got invalid status code" + dat = r.content + + # split up messages + msgs = [] + while len(dat) > 0: + assert dat[:2] == b"\xB5\x62" + msg_len = 6 + (dat[5] << 8 | dat[4]) + 2 + msgs.append(dat[:msg_len]) + dat = dat[msg_len:] + return msgs + + +class TTYPigeon: + def __init__(self): + self.tty = serial.VTIMESerial(UBLOX_TTY, baudrate=9600, timeout=0) + + def send(self, dat: bytes) -> None: + self.tty.write(dat) + + def receive(self) -> bytes: + dat = b'' + while len(dat) < 0x1000: + d = self.tty.read(0x40) + dat += d + if len(d) == 0: + break + return dat + + def set_baud(self, baud: int) -> None: + self.tty.baudrate = baud + + def wait_for_ack(self, ack: bytes = UBLOX_ACK, nack: bytes = UBLOX_NACK, timeout: float = 0.5) -> bool: + dat = b'' + st = time.monotonic() + while True: + dat += self.receive() + if ack in dat: + cloudlog.debug("Received ACK from ublox") + return True + elif nack in dat: + cloudlog.error("Received NACK from ublox") + return False + elif time.monotonic() - st > timeout: + cloudlog.error("No response from ublox") + raise TimeoutError('No response from ublox') + time.sleep(0.001) + + def send_with_ack(self, dat: bytes, ack: bytes = UBLOX_ACK, nack: bytes = UBLOX_NACK) -> None: + self.send(dat) + self.wait_for_ack(ack, nack) + + def wait_for_backup_restore_status(self, timeout: float = 1.) -> int: + dat = b'' + st = time.monotonic() + while True: + dat += self.receive() + position = dat.find(UBLOX_BACKUP_RESTORE_MSG) + if position >= 0 and len(dat) >= position + 11: + return dat[position + 10] + elif time.monotonic() - st > timeout: + cloudlog.error("No backup restore response from ublox") + raise TimeoutError('No response from ublox') + time.sleep(0.001) + + def reset_device(self) -> bool: + # deleting the backup does not always work on first try (mostly on second try) + for _ in range(5): + # device cold start + self.send(b"\xb5\x62\x06\x04\x04\x00\xff\xff\x00\x00\x0c\x5d") + time.sleep(1) # wait for cold start + init_baudrate(self) + + # clear configuration + self.send_with_ack(b"\xb5\x62\x06\x09\x0d\x00\x1f\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x71\xd7") + + # clear flash memory (almanac backup) + self.send_with_ack(b"\xB5\x62\x09\x14\x04\x00\x01\x00\x00\x00\x22\xf0") + + # try restoring backup to verify it got deleted + self.send(b"\xB5\x62\x09\x14\x00\x00\x1D\x60") + # 1: failed to restore, 2: could restore, 3: no backup + status = self.wait_for_backup_restore_status() + if status == 1 or status == 3: + return True + return False + +def save_almanac(pigeon: TTYPigeon) -> None: + # store almanac in flash + pigeon.send(b"\xB5\x62\x09\x14\x04\x00\x00\x00\x00\x00\x21\xEC") + try: + if pigeon.wait_for_ack(ack=UBLOX_SOS_ACK, nack=UBLOX_SOS_NACK): + cloudlog.info("Done storing almanac") + else: + cloudlog.error("Error storing almanac") + except TimeoutError: + pass + +def init_baudrate(pigeon: TTYPigeon): + # ublox default setting on startup is 9600 baudrate + pigeon.set_baud(9600) + + # $PUBX,41,1,0007,0003,460800,0*15\r\n + pigeon.send(b"\x24\x50\x55\x42\x58\x2C\x34\x31\x2C\x31\x2C\x30\x30\x30\x37\x2C\x30\x30\x30\x33\x2C\x34\x36\x30\x38\x30\x30\x2C\x30\x2A\x31\x35\x0D\x0A") + time.sleep(0.1) + pigeon.set_baud(460800) + + +def init_pigeon(pigeon: TTYPigeon) -> bool: + # try initializing a few times + for _ in range(10): + try: + + # setup port config + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x14\x00\x03\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x1E\x7F") + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x14\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x35") + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x14\x00\x01\x00\x00\x00\xC0\x08\x00\x00\x00\x08\x07\x00\x01\x00\x01\x00\x00\x00\x00\x00\xF4\x80") + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x14\x00\x04\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1D\x85") + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x00\x00\x06\x18") + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x01\x00\x01\x08\x22") + pigeon.send_with_ack(b"\xb5\x62\x06\x00\x01\x00\x03\x0A\x24") + + # UBX-CFG-RATE (0x06 0x08) + pigeon.send_with_ack(b"\xB5\x62\x06\x08\x06\x00\x64\x00\x01\x00\x00\x00\x79\x10") + + # UBX-CFG-NAV5 (0x06 0x24) + pigeon.send_with_ack(b"\xB5\x62\x06\x24\x24\x00\x05\x00\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5A\x63") + + # UBX-CFG-ODO (0x06 0x1E) + pigeon.send_with_ack(b"\xB5\x62\x06\x1E\x14\x00\x00\x00\x00\x00\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3C\x37") + pigeon.send_with_ack(b"\xB5\x62\x06\x39\x08\x00\xFF\xAD\x62\xAD\x1E\x63\x00\x00\x83\x0C") + pigeon.send_with_ack(b"\xB5\x62\x06\x23\x28\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x56\x24") + + # UBX-CFG-NAV5 (0x06 0x24) + pigeon.send_with_ack(b"\xB5\x62\x06\x24\x00\x00\x2A\x84") + pigeon.send_with_ack(b"\xB5\x62\x06\x23\x00\x00\x29\x81") + pigeon.send_with_ack(b"\xB5\x62\x06\x1E\x00\x00\x24\x72") + pigeon.send_with_ack(b"\xB5\x62\x06\x39\x00\x00\x3F\xC3") + + # UBX-CFG-MSG (set message rate) + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x01\x07\x01\x13\x51") + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x02\x15\x01\x22\x70") + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x02\x13\x01\x20\x6C") + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x0A\x09\x01\x1E\x70") + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x0A\x0B\x01\x20\x74") + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x01\x35\x01\x41\xAD") + cloudlog.debug("pigeon configured") + + # try restoring almanac backup + pigeon.send(b"\xB5\x62\x09\x14\x00\x00\x1D\x60") + restore_status = pigeon.wait_for_backup_restore_status() + if restore_status == 2: + cloudlog.warning("almanac backup restored") + elif restore_status == 3: + cloudlog.warning("no almanac backup found") + else: + cloudlog.error(f"failed to restore almanac backup, status: {restore_status}") + + # sending time to ublox + if system_time_valid(): + t_now = datetime.now(UTC).replace(tzinfo=None) + cloudlog.warning("Sending current time to ublox") + + # UBX-MGA-INI-TIME_UTC + msg = add_ubx_checksum(b"\xB5\x62\x13\x40\x18\x00" + struct.pack(" None: + # register exit handler + signal.signal(signal.SIGINT, lambda sig, frame: deinitialize_and_exit(pigeon)) + + # power cycle ublox + set_power(False) + time.sleep(0.1) + set_power(True) + time.sleep(0.5) + + init_baudrate(pigeon) + init_pigeon(pigeon) + +def run_receiving(duration: int = 0): + pm = messaging.PubMaster(['ubloxRaw']) + + pigeon = TTYPigeon() + init(pigeon) + + start_time = time.monotonic() + last_almanac_save = time.monotonic() + while (duration == 0) or (time.monotonic() - start_time < duration): + dat = pigeon.receive() + if len(dat) > 0: + if dat[0] == 0x00: + cloudlog.warning("received invalid data from ublox, re-initing!") + init(pigeon) + continue + + # send out to socket + msg = messaging.new_message('ubloxRaw', len(dat), valid=True) + msg.ubloxRaw = dat[:] + pm.send('ubloxRaw', msg) + + # save almanac every 5 minutes + if (time.monotonic() - last_almanac_save) > 60*5: + save_almanac(pigeon) + last_almanac_save = time.monotonic() + else: + # prevent locking up a CPU core if ublox disconnects + time.sleep(0.001) + + +def main(): + assert TICI, "unsupported hardware for pigeond" + run_receiving() + +if __name__ == "__main__": + main() diff --git a/system/ubloxd/tests/test_pigeond.py b/system/ubloxd/tests/test_pigeond.py new file mode 100644 index 0000000000..202820e412 --- /dev/null +++ b/system/ubloxd/tests/test_pigeond.py @@ -0,0 +1,54 @@ +import pytest +import time + +import cereal.messaging as messaging +from cereal.services import SERVICE_LIST +from openpilot.common.gpio import gpio_read +from openpilot.selfdrive.test.helpers import with_processes +from openpilot.system.manager.process_config import managed_processes +from openpilot.system.hardware.tici.pins import GPIO + + +# TODO: test TTFF when we have good A-GNSS +@pytest.mark.tici +class TestPigeond: + + def teardown_method(self): + managed_processes['pigeond'].stop() + + @with_processes(['pigeond']) + def test_frequency(self): + sm = messaging.SubMaster(['ubloxRaw']) + + # setup time + for _ in range(int(5 * SERVICE_LIST['ubloxRaw'].frequency)): + sm.update() + + for _ in range(int(10 * SERVICE_LIST['ubloxRaw'].frequency)): + sm.update() + assert sm.all_checks() + + def test_startup_time(self): + for _ in range(5): + sm = messaging.SubMaster(['ubloxRaw']) + managed_processes['pigeond'].start() + + start_time = time.monotonic() + for __ in range(10): + sm.update(1 * 1000) + if sm.updated['ubloxRaw']: + break + assert sm.recv_frame['ubloxRaw'] > 0, "pigeond didn't start outputting messages in time" + + et = time.monotonic() - start_time + assert et < 5, f"pigeond took {et:.1f}s to start" + managed_processes['pigeond'].stop() + + def test_turns_off_ublox(self): + for s in (0.1, 0.5, 1, 5): + managed_processes['pigeond'].start() + time.sleep(s) + managed_processes['pigeond'].stop() + + assert gpio_read(GPIO.UBLOX_RST_N) == 0 + assert gpio_read(GPIO.GNSS_PWR_EN) == 0 diff --git a/system/ubloxd/ubloxd.py b/system/ubloxd/ubloxd.py new file mode 100755 index 0000000000..84a926dd78 --- /dev/null +++ b/system/ubloxd/ubloxd.py @@ -0,0 +1,519 @@ +#!/usr/bin/env python3 +import math +import capnp +import calendar +import numpy as np +from collections import defaultdict +from dataclasses import dataclass + +from cereal import log +from cereal import messaging +from openpilot.system.ubloxd.generated.ubx import Ubx +from openpilot.system.ubloxd.generated.gps import Gps +from openpilot.system.ubloxd.generated.glonass import Glonass + + +SECS_IN_MIN = 60 +SECS_IN_HR = 60 * SECS_IN_MIN +SECS_IN_DAY = 24 * SECS_IN_HR +SECS_IN_WEEK = 7 * SECS_IN_DAY + + +class UbxFramer: + PREAMBLE1 = 0xB5 + PREAMBLE2 = 0x62 + HEADER_SIZE = 6 + CHECKSUM_SIZE = 2 + + def __init__(self) -> None: + self.buf = bytearray() + self.last_log_time = 0.0 + + def reset(self) -> None: + self.buf.clear() + + @staticmethod + def _checksum_ok(frame: bytes) -> bool: + ck_a = 0 + ck_b = 0 + for b in frame[2:-2]: + ck_a = (ck_a + b) & 0xFF + ck_b = (ck_b + ck_a) & 0xFF + return ck_a == frame[-2] and ck_b == frame[-1] + + def add_data(self, log_time: float, incoming: bytes) -> list[bytes]: + self.last_log_time = log_time + out: list[bytes] = [] + if not incoming: + return out + self.buf += incoming + + while True: + # find preamble + if len(self.buf) < 2: + break + start = self.buf.find(b"\xB5\x62") + if start < 0: + # no preamble in buffer + self.buf.clear() + break + if start > 0: + # drop garbage before preamble + self.buf = self.buf[start:] + + if len(self.buf) < self.HEADER_SIZE: + break + + length_le = int.from_bytes(self.buf[4:6], 'little', signed=False) + total_len = self.HEADER_SIZE + length_le + self.CHECKSUM_SIZE + if len(self.buf) < total_len: + break + + candidate = bytes(self.buf[:total_len]) + if self._checksum_ok(candidate): + out.append(candidate) + # consume this frame + self.buf = self.buf[total_len:] + else: + # drop first byte and retry + self.buf = self.buf[1:] + + return out + + +def _bit(b: int, shift: int) -> bool: + return (b & (1 << shift)) != 0 + + +@dataclass +class EphemerisCaches: + gps_subframes: defaultdict[int, dict[int, bytes]] + glonass_strings: defaultdict[int, dict[int, bytes]] + glonass_string_times: defaultdict[int, dict[int, float]] + glonass_string_superframes: defaultdict[int, dict[int, int]] + + +class UbloxMsgParser: + gpsPi = 3.1415926535898 + + # user range accuracy in meters + glonass_URA_lookup: dict[int, float] = { + 0: 1, 1: 2, 2: 2.5, 3: 4, 4: 5, 5: 7, + 6: 10, 7: 12, 8: 14, 9: 16, 10: 32, + 11: 64, 12: 128, 13: 256, 14: 512, 15: 1024, + } + + def __init__(self) -> None: + self.framer = UbxFramer() + self.caches = EphemerisCaches( + gps_subframes=defaultdict(dict), + glonass_strings=defaultdict(dict), + glonass_string_times=defaultdict(dict), + glonass_string_superframes=defaultdict(dict), + ) + + # Message generation entry point + def parse_frame(self, frame: bytes) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + # Quick header parse + msg_type = int.from_bytes(frame[2:4], 'big') + payload = frame[6:-2] + if msg_type == 0x0107: + body = Ubx.NavPvt.from_bytes(payload) + return self._gen_nav_pvt(body) + if msg_type == 0x0213: + # Manually parse RXM-SFRBX to avoid Kaitai EOF on some frames + if len(payload) < 8: + return None + gnss_id = payload[0] + sv_id = payload[1] + freq_id = payload[3] + num_words = payload[4] + exp = 8 + 4 * num_words + if exp != len(payload): + return None + words: list[int] = [] + off = 8 + for _ in range(num_words): + words.append(int.from_bytes(payload[off:off+4], 'little')) + off += 4 + + class _SfrbxView: + def __init__(self, gid: int, sid: int, fid: int, body: list[int]): + self.gnss_id = Ubx.GnssType(gid) + self.sv_id = sid + self.freq_id = fid + self.body = body + view = _SfrbxView(gnss_id, sv_id, freq_id, words) + return self._gen_rxm_sfrbx(view) + if msg_type == 0x0215: + body = Ubx.RxmRawx.from_bytes(payload) + return self._gen_rxm_rawx(body) + if msg_type == 0x0A09: + body = Ubx.MonHw.from_bytes(payload) + return self._gen_mon_hw(body) + if msg_type == 0x0A0B: + body = Ubx.MonHw2.from_bytes(payload) + return self._gen_mon_hw2(body) + if msg_type == 0x0135: + body = Ubx.NavSat.from_bytes(payload) + return self._gen_nav_sat(body) + return None + + # NAV-PVT -> gpsLocationExternal + def _gen_nav_pvt(self, msg: Ubx.NavPvt) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('gpsLocationExternal', valid=True) + gps = dat.gpsLocationExternal + gps.source = log.GpsLocationData.SensorSource.ublox + gps.flags = msg.flags + gps.hasFix = (msg.flags % 2) == 1 + gps.latitude = msg.lat * 1e-07 + gps.longitude = msg.lon * 1e-07 + gps.altitude = msg.height * 1e-03 + gps.speed = msg.g_speed * 1e-03 + gps.bearingDeg = msg.head_mot * 1e-5 + gps.horizontalAccuracy = msg.h_acc * 1e-03 + gps.satelliteCount = msg.num_sv + + # build UTC timestamp millis (NAV-PVT is in UTC) + # tolerate invalid or unset date values like C++ timegm + try: + utc_tt = calendar.timegm((msg.year, msg.month, msg.day, msg.hour, msg.min, msg.sec, 0, 0, 0)) + except Exception: + utc_tt = 0 + gps.unixTimestampMillis = int(utc_tt * 1e3 + (msg.nano * 1e-6)) + + # match C++ float32 rounding semantics exactly + gps.vNED = [ + float(np.float32(msg.vel_n) * np.float32(1e-03)), + float(np.float32(msg.vel_e) * np.float32(1e-03)), + float(np.float32(msg.vel_d) * np.float32(1e-03)), + ] + gps.verticalAccuracy = msg.v_acc * 1e-03 + gps.speedAccuracy = msg.s_acc * 1e-03 + gps.bearingAccuracyDeg = msg.head_acc * 1e-05 + return ('gpsLocationExternal', dat) + + # RXM-SFRBX dispatch to GPS or GLONASS ephemeris + def _gen_rxm_sfrbx(self, msg) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + if msg.gnss_id == Ubx.GnssType.gps: + return self._parse_gps_ephemeris(msg) + if msg.gnss_id == Ubx.GnssType.glonass: + return self._parse_glonass_ephemeris(msg) + return None + + def _parse_gps_ephemeris(self, msg: Ubx.RxmSfrbx) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + # body is list of 10 words; convert to 30-byte subframe (strip parity/padding) + body = msg.body + if len(body) != 10: + return None + subframe_data = bytearray() + for word in body: + word >>= 6 + subframe_data.append((word >> 16) & 0xFF) + subframe_data.append((word >> 8) & 0xFF) + subframe_data.append(word & 0xFF) + + sf = Gps.from_bytes(bytes(subframe_data)) + subframe_id = sf.how.subframe_id + if subframe_id < 1 or subframe_id > 3: + return None + self.caches.gps_subframes[msg.sv_id][subframe_id] = bytes(subframe_data) + + if len(self.caches.gps_subframes[msg.sv_id]) != 3: + return None + + dat = messaging.new_message('ubloxGnss', valid=True) + eph = dat.ubloxGnss.init('ephemeris') + eph.svId = msg.sv_id + + iode_s2 = 0 + iode_s3 = 0 + iodc_lsb = 0 + week = 0 + + # Subframe 1 + sf1 = Gps.from_bytes(self.caches.gps_subframes[msg.sv_id][1]) + s1 = sf1.body + assert isinstance(s1, Gps.Subframe1) + week = s1.week_no + week += 1024 + if week < 1877: + week += 1024 + eph.tgd = s1.t_gd * math.pow(2, -31) + eph.toc = s1.t_oc * math.pow(2, 4) + eph.af2 = s1.af_2 * math.pow(2, -55) + eph.af1 = s1.af_1 * math.pow(2, -43) + eph.af0 = s1.af_0 * math.pow(2, -31) + eph.svHealth = s1.sv_health + eph.towCount = sf1.how.tow_count + iodc_lsb = s1.iodc_lsb + + # Subframe 2 + sf2 = Gps.from_bytes(self.caches.gps_subframes[msg.sv_id][2]) + s2 = sf2.body + assert isinstance(s2, Gps.Subframe2) + if s2.t_oe == 0 and sf2.how.tow_count * 6 >= (SECS_IN_WEEK - 2 * SECS_IN_HR): + week += 1 + eph.crs = s2.c_rs * math.pow(2, -5) + eph.deltaN = s2.delta_n * math.pow(2, -43) * self.gpsPi + eph.m0 = s2.m_0 * math.pow(2, -31) * self.gpsPi + eph.cuc = s2.c_uc * math.pow(2, -29) + eph.ecc = s2.e * math.pow(2, -33) + eph.cus = s2.c_us * math.pow(2, -29) + eph.a = math.pow(s2.sqrt_a * math.pow(2, -19), 2.0) + eph.toe = s2.t_oe * math.pow(2, 4) + iode_s2 = s2.iode + + # Subframe 3 + sf3 = Gps.from_bytes(self.caches.gps_subframes[msg.sv_id][3]) + s3 = sf3.body + assert isinstance(s3, Gps.Subframe3) + eph.cic = s3.c_ic * math.pow(2, -29) + eph.omega0 = s3.omega_0 * math.pow(2, -31) * self.gpsPi + eph.cis = s3.c_is * math.pow(2, -29) + eph.i0 = s3.i_0 * math.pow(2, -31) * self.gpsPi + eph.crc = s3.c_rc * math.pow(2, -5) + eph.omega = s3.omega * math.pow(2, -31) * self.gpsPi + eph.omegaDot = s3.omega_dot * math.pow(2, -43) * self.gpsPi + eph.iode = s3.iode + eph.iDot = s3.idot * math.pow(2, -43) * self.gpsPi + iode_s3 = s3.iode + + eph.toeWeek = week + eph.tocWeek = week + + # clear cache for this SV + self.caches.gps_subframes[msg.sv_id].clear() + if not (iodc_lsb == iode_s2 == iode_s3): + return None + return ('ubloxGnss', dat) + + def _parse_glonass_ephemeris(self, msg: Ubx.RxmSfrbx) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder] | None: + # words are 4 bytes each; Glonass parser expects 16 bytes (string) + body = msg.body + if len(body) != 4: + return None + string_bytes = bytearray() + for word in body: + for i in (3, 2, 1, 0): + string_bytes.append((word >> (8 * i)) & 0xFF) + + gl = Glonass.from_bytes(bytes(string_bytes)) + string_number = gl.string_number + if string_number < 1 or string_number > 5 or gl.idle_chip: + return None + + # correlate by superframe and timing, similar to C++ logic + freq_id = msg.freq_id + superframe_unknown = False + needs_clear = False + for i in range(1, 6): + if i not in self.caches.glonass_strings[freq_id]: + continue + sf_prev = self.caches.glonass_string_superframes[freq_id].get(i, 0) + if sf_prev == 0 or gl.superframe_number == 0: + superframe_unknown = True + elif sf_prev != gl.superframe_number: + needs_clear = True + if superframe_unknown: + prev_time = self.caches.glonass_string_times[freq_id].get(i, 0.0) + if abs((prev_time - 2.0 * i) - (self.framer.last_log_time - 2.0 * string_number)) > 10: + needs_clear = True + + if needs_clear: + self.caches.glonass_strings[freq_id].clear() + self.caches.glonass_string_superframes[freq_id].clear() + self.caches.glonass_string_times[freq_id].clear() + + self.caches.glonass_strings[freq_id][string_number] = bytes(string_bytes) + self.caches.glonass_string_superframes[freq_id][string_number] = gl.superframe_number + self.caches.glonass_string_times[freq_id][string_number] = self.framer.last_log_time + + if msg.sv_id == 255: + # unknown SV id + return None + if len(self.caches.glonass_strings[freq_id]) != 5: + return None + + dat = messaging.new_message('ubloxGnss', valid=True) + eph = dat.ubloxGnss.init('glonassEphemeris') + eph.svId = msg.sv_id + eph.freqNum = msg.freq_id - 7 + + current_day = 0 + tk = 0 + + # string 1 + try: + s1 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][1]).data + except Exception: + return None + assert isinstance(s1, Glonass.String1) + eph.p1 = int(s1.p1) + tk = int(s1.t_k) + eph.tkDEPRECATED = tk + eph.xVel = float(s1.x_vel) * math.pow(2, -20) + eph.xAccel = float(s1.x_accel) * math.pow(2, -30) + eph.x = float(s1.x) * math.pow(2, -11) + + # string 2 + try: + s2 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][2]).data + except Exception: + return None + assert isinstance(s2, Glonass.String2) + eph.svHealth = int(s2.b_n >> 2) + eph.p2 = int(s2.p2) + eph.tb = int(s2.t_b) + eph.yVel = float(s2.y_vel) * math.pow(2, -20) + eph.yAccel = float(s2.y_accel) * math.pow(2, -30) + eph.y = float(s2.y) * math.pow(2, -11) + + # string 3 + try: + s3 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][3]).data + except Exception: + return None + assert isinstance(s3, Glonass.String3) + eph.p3 = int(s3.p3) + eph.gammaN = float(s3.gamma_n) * math.pow(2, -40) + eph.svHealth = int(eph.svHealth | (1 if s3.l_n else 0)) + eph.zVel = float(s3.z_vel) * math.pow(2, -20) + eph.zAccel = float(s3.z_accel) * math.pow(2, -30) + eph.z = float(s3.z) * math.pow(2, -11) + + # string 4 + try: + s4 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][4]).data + except Exception: + return None + assert isinstance(s4, Glonass.String4) + current_day = int(s4.n_t) + eph.nt = current_day + eph.tauN = float(s4.tau_n) * math.pow(2, -30) + eph.deltaTauN = float(s4.delta_tau_n) * math.pow(2, -30) + eph.age = int(s4.e_n) + eph.p4 = int(s4.p4) + eph.svURA = float(self.glonass_URA_lookup.get(int(s4.f_t), 0.0)) + # consistency check: SV slot number + # if it doesn't match, keep going but note mismatch (no logging here) + eph.svType = int(s4.m) + + # string 5 + try: + s5 = Glonass.from_bytes(self.caches.glonass_strings[freq_id][5]).data + except Exception: + return None + assert isinstance(s5, Glonass.String5) + eph.n4 = int(s5.n_4) + tk_seconds = int(SECS_IN_HR * ((tk >> 7) & 0x1F) + SECS_IN_MIN * ((tk >> 1) & 0x3F) + (tk & 0x1) * 30) + eph.tkSeconds = tk_seconds + + self.caches.glonass_strings[freq_id].clear() + return ('ubloxGnss', dat) + + def _gen_rxm_rawx(self, msg: Ubx.RxmRawx) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + mr = dat.ubloxGnss.init('measurementReport') + mr.rcvTow = msg.rcv_tow + mr.gpsWeek = msg.week + mr.leapSeconds = msg.leap_s + + mb = mr.init('measurements', msg.num_meas) + for i, m in enumerate(msg.meas): + mb[i].svId = m.sv_id + mb[i].pseudorange = m.pr_mes + mb[i].carrierCycles = m.cp_mes + mb[i].doppler = m.do_mes + mb[i].gnssId = int(m.gnss_id.value) + mb[i].glonassFrequencyIndex = m.freq_id + mb[i].locktime = m.lock_time + mb[i].cno = m.cno + mb[i].pseudorangeStdev = 0.01 * (math.pow(2, (m.pr_stdev & 15))) + mb[i].carrierPhaseStdev = 0.004 * (m.cp_stdev & 15) + mb[i].dopplerStdev = 0.002 * (math.pow(2, (m.do_stdev & 15))) + + ts = mb[i].init('trackingStatus') + trk = m.trk_stat + ts.pseudorangeValid = _bit(trk, 0) + ts.carrierPhaseValid = _bit(trk, 1) + ts.halfCycleValid = _bit(trk, 2) + ts.halfCycleSubtracted = _bit(trk, 3) + + mr.numMeas = msg.num_meas + rs = mr.init('receiverStatus') + rs.leapSecValid = _bit(msg.rec_stat, 0) + rs.clkReset = _bit(msg.rec_stat, 2) + return ('ubloxGnss', dat) + + def _gen_nav_sat(self, msg: Ubx.NavSat) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + sr = dat.ubloxGnss.init('satReport') + sr.iTow = msg.itow + svs = sr.init('svs', msg.num_svs) + for i, s in enumerate(msg.svs): + svs[i].svId = s.sv_id + svs[i].gnssId = int(s.gnss_id.value) + svs[i].flagsBitfield = s.flags + svs[i].cno = s.cno + svs[i].elevationDeg = s.elev + svs[i].azimuthDeg = s.azim + svs[i].pseudorangeResidual = s.pr_res * 0.1 + return ('ubloxGnss', dat) + + def _gen_mon_hw(self, msg: Ubx.MonHw) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + hw = dat.ubloxGnss.init('hwStatus') + hw.noisePerMS = msg.noise_per_ms + hw.flags = msg.flags + hw.agcCnt = msg.agc_cnt + hw.aStatus = int(msg.a_status.value) + hw.aPower = int(msg.a_power.value) + hw.jamInd = msg.jam_ind + return ('ubloxGnss', dat) + + def _gen_mon_hw2(self, msg: Ubx.MonHw2) -> tuple[str, capnp.lib.capnp._DynamicStructBuilder]: + dat = messaging.new_message('ubloxGnss', valid=True) + hw = dat.ubloxGnss.init('hwStatus2') + hw.ofsI = msg.ofs_i + hw.magI = msg.mag_i + hw.ofsQ = msg.ofs_q + hw.magQ = msg.mag_q + # Map Ubx enum to cereal enum {undefined=0, rom=1, otp=2, configpins=3, flash=4} + cfg_map = { + Ubx.MonHw2.ConfigSource.rom: 1, + Ubx.MonHw2.ConfigSource.otp: 2, + Ubx.MonHw2.ConfigSource.config_pins: 3, + Ubx.MonHw2.ConfigSource.flash: 4, + } + hw.cfgSource = cfg_map.get(msg.cfg_source, 0) + hw.lowLevCfg = msg.low_lev_cfg + hw.postStatus = msg.post_status + return ('ubloxGnss', dat) + + +def main(): + parser = UbloxMsgParser() + pm = messaging.PubMaster(['ubloxGnss', 'gpsLocationExternal']) + sock = messaging.sub_sock('ubloxRaw', timeout=100, conflate=False) + + while True: + msg = messaging.recv_one_or_none(sock) + if msg is None: + continue + + data = bytes(msg.ubloxRaw) + log_time = msg.logMonoTime * 1e-9 + frames = parser.framer.add_data(log_time, data) + for frame in frames: + try: + res = parser.parse_frame(frame) + except Exception: + continue + if not res: + continue + service, dat = res + pm.send(service, dat) + +if __name__ == '__main__': + main() diff --git a/system/ubloxd/ubx.ksy b/system/ubloxd/ubx.ksy new file mode 100644 index 0000000000..02c757fe71 --- /dev/null +++ b/system/ubloxd/ubx.ksy @@ -0,0 +1,293 @@ +meta: + id: ubx + endian: le +seq: + - id: magic + contents: [0xb5, 0x62] + - id: msg_type + type: u2be + - id: length + type: u2 + - id: body + type: + switch-on: msg_type + cases: + 0x0107: nav_pvt + 0x0213: rxm_sfrbx + 0x0215: rxm_rawx + 0x0a09: mon_hw + 0x0a0b: mon_hw2 + 0x0135: nav_sat +instances: + checksum: + pos: length + 6 + type: u2 + +types: + mon_hw: + seq: + - id: pin_sel + type: u4 + - id: pin_bank + type: u4 + - id: pin_dir + type: u4 + - id: pin_val + type: u4 + - id: noise_per_ms + type: u2 + - id: agc_cnt + type: u2 + - id: a_status + type: u1 + enum: antenna_status + - id: a_power + type: u1 + enum: antenna_power + - id: flags + type: u1 + - id: reserved1 + size: 1 + - id: used_mask + type: u4 + - id: vp + size: 17 + - id: jam_ind + type: u1 + - id: reserved2 + size: 2 + - id: pin_irq + type: u4 + - id: pull_h + type: u4 + - id: pull_l + type: u4 + enums: + antenna_status: + 0: init + 1: dontknow + 2: ok + 3: short + 4: open + antenna_power: + 0: off + 1: on + 2: dontknow + + mon_hw2: + seq: + - id: ofs_i + type: s1 + - id: mag_i + type: u1 + - id: ofs_q + type: s1 + - id: mag_q + type: u1 + - id: cfg_source + type: u1 + enum: config_source + - id: reserved1 + size: 3 + - id: low_lev_cfg + type: u4 + - id: reserved2 + size: 8 + - id: post_status + type: u4 + - id: reserved3 + size: 4 + + enums: + config_source: + 113: rom + 111: otp + 112: config_pins + 102: flash + + rxm_sfrbx: + seq: + - id: gnss_id + type: u1 + enum: gnss_type + - id: sv_id + type: u1 + - id: reserved1 + size: 1 + - id: freq_id + type: u1 + - id: num_words + type: u1 + - id: reserved2 + size: 1 + - id: version + type: u1 + - id: reserved3 + size: 1 + - id: body + type: u4 + repeat: expr + repeat-expr: num_words + + rxm_rawx: + seq: + - id: rcv_tow + type: f8 + - id: week + type: u2 + - id: leap_s + type: s1 + - id: num_meas + type: u1 + - id: rec_stat + type: u1 + - id: reserved1 + size: 3 + - id: meas + type: measurement + size: 32 + repeat: expr + repeat-expr: num_meas + types: + measurement: + seq: + - id: pr_mes + type: f8 + - id: cp_mes + type: f8 + - id: do_mes + type: f4 + - id: gnss_id + type: u1 + enum: gnss_type + - id: sv_id + type: u1 + - id: reserved2 + size: 1 + - id: freq_id + type: u1 + - id: lock_time + type: u2 + - id: cno + type: u1 + - id: pr_stdev + type: u1 + - id: cp_stdev + type: u1 + - id: do_stdev + type: u1 + - id: trk_stat + type: u1 + - id: reserved3 + size: 1 + nav_sat: + seq: + - id: itow + type: u4 + - id: version + type: u1 + - id: num_svs + type: u1 + - id: reserved + size: 2 + - id: svs + type: nav + size: 12 + repeat: expr + repeat-expr: num_svs + types: + nav: + seq: + - id: gnss_id + type: u1 + enum: gnss_type + - id: sv_id + type: u1 + - id: cno + type: u1 + - id: elev + type: s1 + - id: azim + type: s2 + - id: pr_res + type: s2 + - id: flags + type: u4 + + nav_pvt: + seq: + - id: i_tow + type: u4 + - id: year + type: u2 + - id: month + type: u1 + - id: day + type: u1 + - id: hour + type: u1 + - id: min + type: u1 + - id: sec + type: u1 + - id: valid + type: u1 + - id: t_acc + type: u4 + - id: nano + type: s4 + - id: fix_type + type: u1 + - id: flags + type: u1 + - id: flags2 + type: u1 + - id: num_sv + type: u1 + - id: lon + type: s4 + - id: lat + type: s4 + - id: height + type: s4 + - id: h_msl + type: s4 + - id: h_acc + type: u4 + - id: v_acc + type: u4 + - id: vel_n + type: s4 + - id: vel_e + type: s4 + - id: vel_d + type: s4 + - id: g_speed + type: s4 + - id: head_mot + type: s4 + - id: s_acc + type: s4 + - id: head_acc + type: u4 + - id: p_dop + type: u2 + - id: flags3 + type: u1 + - id: reserved1 + size: 5 + - id: head_veh + type: s4 + - id: mag_dec + type: s2 + - id: mag_acc + type: u2 +enums: + gnss_type: + 0: gps + 1: sbas + 2: galileo + 3: beidou + 4: imes + 5: qzss + 6: glonass diff --git a/system/ui/README.md b/system/ui/README.md new file mode 100644 index 0000000000..b124ae4d85 --- /dev/null +++ b/system/ui/README.md @@ -0,0 +1,15 @@ +# ui + +The user interfaces here are built with [raylib](https://www.raylib.com/). + +Quick start: +* set `SHOW_FPS=1` to show the FPS +* set `STRICT_MODE=1` to kill the app if it drops too much below 60fps +* set `SCALE=1.5` to scale the entire UI by 1.5x +* https://www.raylib.com/cheatsheet/cheatsheet.html +* https://electronstudio.github.io/raylib-python-cffi/README.html#quickstart + +Style guide: +* All graphical elements should subclass [`Widget`](/system/ui/widgets/__init__.py). + * Prefer a stateful widget over a function for easy migration from QT +* All internal class variables and functions should be prefixed with `_` diff --git a/system/ui/lib/__init__.py b/system/ui/lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/ui/lib/application.py b/system/ui/lib/application.py new file mode 100644 index 0000000000..755a335e4d --- /dev/null +++ b/system/ui/lib/application.py @@ -0,0 +1,430 @@ +import atexit +import cffi +import os +import time +import pyray as rl +import threading +from collections.abc import Callable +from collections import deque +from dataclasses import dataclass +from enum import StrEnum +from typing import NamedTuple +from importlib.resources import as_file, files +from openpilot.common.swaglog import cloudlog +from openpilot.system.hardware import HARDWARE, PC, TICI +from openpilot.common.realtime import Ratekeeper + +_DEFAULT_FPS = int(os.getenv("FPS", 20 if TICI else 60)) +FPS_LOG_INTERVAL = 5 # Seconds between logging FPS drops +FPS_DROP_THRESHOLD = 0.9 # FPS drop threshold for triggering a warning +FPS_CRITICAL_THRESHOLD = 0.5 # Critical threshold for triggering strict actions +MOUSE_THREAD_RATE = 140 # touch controller runs at 140Hz +MAX_TOUCH_SLOTS = 2 + +ENABLE_VSYNC = os.getenv("ENABLE_VSYNC", "0") == "1" +SHOW_FPS = os.getenv("SHOW_FPS") == "1" +SHOW_TOUCHES = os.getenv("SHOW_TOUCHES") == "1" +STRICT_MODE = os.getenv("STRICT_MODE") == "1" +SCALE = float(os.getenv("SCALE", "1.0")) + +DEFAULT_TEXT_SIZE = 60 +DEFAULT_TEXT_COLOR = rl.WHITE + +# Qt draws fonts accounting for ascent/descent differently, so compensate to match old styles +# The real scales for the fonts below range from 1.212 to 1.266 +FONT_SCALE = 1.242 + +ASSETS_DIR = files("openpilot.selfdrive").joinpath("assets") +FONT_DIR = ASSETS_DIR.joinpath("fonts") + + +class FontWeight(StrEnum): + THIN = "Inter-Thin.ttf" + EXTRA_LIGHT = "Inter-ExtraLight.ttf" + LIGHT = "Inter-Light.ttf" + NORMAL = "Inter-Regular.ttf" + MEDIUM = "Inter-Medium.ttf" + SEMI_BOLD = "Inter-SemiBold.ttf" + BOLD = "Inter-Bold.ttf" + EXTRA_BOLD = "Inter-ExtraBold.ttf" + BLACK = "Inter-Black.ttf" + + +@dataclass +class ModalOverlay: + overlay: object = None + callback: Callable | None = None + + +class MousePos(NamedTuple): + x: float + y: float + + +class MouseEvent(NamedTuple): + pos: MousePos + slot: int + left_pressed: bool + left_released: bool + left_down: bool + t: float + + +class MouseState: + def __init__(self, scale: float = 1.0): + self._scale = scale + self._events: deque[MouseEvent] = deque(maxlen=MOUSE_THREAD_RATE) # bound event list + self._prev_mouse_event: list[MouseEvent | None] = [None] * MAX_TOUCH_SLOTS + + self._rk = Ratekeeper(MOUSE_THREAD_RATE) + self._lock = threading.Lock() + self._exit_event = threading.Event() + self._thread = None + + def get_events(self) -> list[MouseEvent]: + with self._lock: + events = list(self._events) + self._events.clear() + return events + + def start(self): + self._exit_event.clear() + if self._thread is None or not self._thread.is_alive(): + self._thread = threading.Thread(target=self._run_thread, daemon=True) + self._thread.start() + + def stop(self): + self._exit_event.set() + if self._thread is not None and self._thread.is_alive(): + self._thread.join() + + def _run_thread(self): + while not self._exit_event.is_set(): + rl.poll_input_events() + self._handle_mouse_event() + self._rk.keep_time() + + def _handle_mouse_event(self): + for slot in range(MAX_TOUCH_SLOTS): + mouse_pos = rl.get_touch_position(slot) + x = mouse_pos.x / self._scale if self._scale != 1.0 else mouse_pos.x + y = mouse_pos.y / self._scale if self._scale != 1.0 else mouse_pos.y + ev = MouseEvent( + MousePos(x, y), + slot, + rl.is_mouse_button_pressed(slot), # noqa: TID251 + rl.is_mouse_button_released(slot), # noqa: TID251 + rl.is_mouse_button_down(slot), + time.monotonic(), + ) + # Only add changes + if self._prev_mouse_event[slot] is None or ev[:-1] != self._prev_mouse_event[slot][:-1]: + with self._lock: + self._events.append(ev) + self._prev_mouse_event[slot] = ev + + +class GuiApplication: + def __init__(self, width: int, height: int): + self._fonts: dict[FontWeight, rl.Font] = {} + self._width = width + self._height = height + self._scale = SCALE + self._scaled_width = int(self._width * self._scale) + self._scaled_height = int(self._height * self._scale) + self._render_texture: rl.RenderTexture | None = None + self._textures: dict[str, rl.Texture] = {} + self._target_fps: int = _DEFAULT_FPS + self._last_fps_log_time: float = time.monotonic() + self._window_close_requested = False + self._trace_log_callback = None + self._modal_overlay = ModalOverlay() + + self._mouse = MouseState(self._scale) + self._mouse_events: list[MouseEvent] = [] + + # Debug variables + self._mouse_history: deque[MousePos] = deque(maxlen=MOUSE_THREAD_RATE) + + @property + def target_fps(self): + return self._target_fps + + def request_close(self): + self._window_close_requested = True + + def init_window(self, title: str, fps: int = _DEFAULT_FPS): + atexit.register(self.close) # Automatically call close() on exit + + HARDWARE.set_display_power(True) + HARDWARE.set_screen_brightness(65) + + self._set_log_callback() + rl.set_trace_log_level(rl.TraceLogLevel.LOG_ALL) + + flags = rl.ConfigFlags.FLAG_MSAA_4X_HINT + if ENABLE_VSYNC: + flags |= rl.ConfigFlags.FLAG_VSYNC_HINT + rl.set_config_flags(flags) + + rl.init_window(self._scaled_width, self._scaled_height, title) + if self._scale != 1.0: + rl.set_mouse_scale(1 / self._scale, 1 / self._scale) + self._render_texture = rl.load_render_texture(self._width, self._height) + rl.set_texture_filter(self._render_texture.texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR) + rl.set_target_fps(fps) + + self._target_fps = fps + self._set_styles() + self._load_fonts() + self._patch_text_functions() + + if not PC: + self._mouse.start() + + def set_modal_overlay(self, overlay, callback: Callable | None = None): + if self._modal_overlay.overlay is not None: + if self._modal_overlay.callback is not None: + self._modal_overlay.callback(-1) + + self._modal_overlay = ModalOverlay(overlay=overlay, callback=callback) + + def texture(self, asset_path: str, width: int, height: int, alpha_premultiply=False, keep_aspect_ratio=True): + cache_key = f"{asset_path}_{width}_{height}_{alpha_premultiply}{keep_aspect_ratio}" + if cache_key in self._textures: + return self._textures[cache_key] + + with as_file(ASSETS_DIR.joinpath(asset_path)) as fspath: + texture_obj = self._load_texture_from_image(fspath.as_posix(), width, height, alpha_premultiply, keep_aspect_ratio) + self._textures[cache_key] = texture_obj + return texture_obj + + def _load_texture_from_image(self, image_path: str, width: int, height: int, alpha_premultiply=False, keep_aspect_ratio=True): + """Load and resize a texture, storing it for later automatic unloading.""" + image = rl.load_image(image_path) + + if alpha_premultiply: + rl.image_alpha_premultiply(image) + + # Resize with aspect ratio preservation if requested + if keep_aspect_ratio: + orig_width = image.width + orig_height = image.height + + scale_width = width / orig_width + scale_height = height / orig_height + + # Calculate new dimensions + scale = min(scale_width, scale_height) + new_width = int(orig_width * scale) + new_height = int(orig_height * scale) + + rl.image_resize(image, new_width, new_height) + else: + rl.image_resize(image, width, height) + + texture = rl.load_texture_from_image(image) + # Set texture filtering to smooth the result + rl.set_texture_filter(texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR) + + rl.unload_image(image) + return texture + + def close(self): + if not rl.is_window_ready(): + return + + for texture in self._textures.values(): + rl.unload_texture(texture) + self._textures = {} + + for font in self._fonts.values(): + rl.unload_font(font) + self._fonts = {} + + if self._render_texture is not None: + rl.unload_render_texture(self._render_texture) + self._render_texture = None + + if not PC: + self._mouse.stop() + + rl.close_window() + + @property + def mouse_events(self) -> list[MouseEvent]: + return self._mouse_events + + def render(self): + try: + while not (self._window_close_requested or rl.window_should_close()): + if PC: + # Thread is not used on PC, need to manually add mouse events + self._mouse._handle_mouse_event() + + # Store all mouse events for the current frame + self._mouse_events = self._mouse.get_events() + + if self._render_texture: + rl.begin_texture_mode(self._render_texture) + rl.clear_background(rl.BLACK) + else: + rl.begin_drawing() + rl.clear_background(rl.BLACK) + + # Handle modal overlay rendering and input processing + if self._modal_overlay.overlay: + if hasattr(self._modal_overlay.overlay, 'render'): + result = self._modal_overlay.overlay.render(rl.Rectangle(0, 0, self.width, self.height)) + elif callable(self._modal_overlay.overlay): + result = self._modal_overlay.overlay() + else: + raise Exception + + if result >= 0: + # Clear the overlay and execute the callback + original_modal = self._modal_overlay + self._modal_overlay = ModalOverlay() + if original_modal.callback is not None: + original_modal.callback(result) + yield True + else: + yield False + + if self._render_texture: + rl.end_texture_mode() + rl.begin_drawing() + rl.clear_background(rl.BLACK) + src_rect = rl.Rectangle(0, 0, float(self._width), -float(self._height)) + dst_rect = rl.Rectangle(0, 0, float(self._scaled_width), float(self._scaled_height)) + rl.draw_texture_pro(self._render_texture.texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) + + if SHOW_FPS: + rl.draw_fps(10, 10) + + if SHOW_TOUCHES: + for mouse_event in self._mouse_events: + if mouse_event.left_pressed: + self._mouse_history.clear() + self._mouse_history.append(mouse_event.pos) + + if self._mouse_history: + mouse_pos = self._mouse_history[-1] + rl.draw_circle(int(mouse_pos.x), int(mouse_pos.y), 15, rl.RED) + for idx, mouse_pos in enumerate(self._mouse_history): + perc = idx / len(self._mouse_history) + color = rl.Color(min(int(255 * (1.5 - perc)), 255), int(min(255 * (perc + 0.5), 255)), 50, 255) + rl.draw_circle(int(mouse_pos.x), int(mouse_pos.y), 5, color) + + rl.end_drawing() + self._monitor_fps() + except KeyboardInterrupt: + pass + + def font(self, font_weight: FontWeight = FontWeight.NORMAL): + return self._fonts[font_weight] + + @property + def width(self): + return self._width + + @property + def height(self): + return self._height + + def _load_fonts(self): + # Create a character set from our keyboard layouts + from openpilot.system.ui.widgets.keyboard import KEYBOARD_LAYOUTS + + all_chars = set() + for layout in KEYBOARD_LAYOUTS.values(): + all_chars.update(key for row in layout for key in row) + all_chars = "".join(all_chars) + all_chars += "–✓×°§•" + + codepoint_count = rl.ffi.new("int *", 1) + codepoints = rl.load_codepoints(all_chars, codepoint_count) + + for font_weight_file in FontWeight: + with as_file(FONT_DIR.joinpath(font_weight_file)) as fspath: + font = rl.load_font_ex(fspath.as_posix(), 200, codepoints, codepoint_count[0]) + rl.set_texture_filter(font.texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR) + self._fonts[font_weight_file] = font + + rl.unload_codepoints(codepoints) + rl.gui_set_font(self._fonts[FontWeight.NORMAL]) + + def _set_styles(self): + rl.gui_set_style(rl.GuiControl.DEFAULT, rl.GuiControlProperty.BORDER_WIDTH, 0) + rl.gui_set_style(rl.GuiControl.DEFAULT, rl.GuiDefaultProperty.TEXT_SIZE, DEFAULT_TEXT_SIZE) + rl.gui_set_style(rl.GuiControl.DEFAULT, rl.GuiDefaultProperty.BACKGROUND_COLOR, rl.color_to_int(rl.BLACK)) + rl.gui_set_style(rl.GuiControl.DEFAULT, rl.GuiControlProperty.TEXT_COLOR_NORMAL, rl.color_to_int(DEFAULT_TEXT_COLOR)) + rl.gui_set_style(rl.GuiControl.DEFAULT, rl.GuiControlProperty.BASE_COLOR_NORMAL, rl.color_to_int(rl.Color(50, 50, 50, 255))) + + def _patch_text_functions(self): + # Wrap pyray text APIs to apply a global text size scale so our px sizes match Qt + if not hasattr(rl, "_orig_draw_text_ex"): + rl._orig_draw_text_ex = rl.draw_text_ex + + def _draw_text_ex_scaled(font, text, position, font_size, spacing, tint): + return rl._orig_draw_text_ex(font, text, position, font_size * FONT_SCALE, spacing, tint) + + rl.draw_text_ex = _draw_text_ex_scaled + + def _set_log_callback(self): + ffi_libc = cffi.FFI() + ffi_libc.cdef(""" + int vasprintf(char **strp, const char *fmt, void *ap); + void free(void *ptr); + """) + libc = ffi_libc.dlopen(None) + + @rl.ffi.callback("void(int, char *, void *)") + def trace_log_callback(log_level, text, args): + try: + text_addr = int(rl.ffi.cast("uintptr_t", text)) + args_addr = int(rl.ffi.cast("uintptr_t", args)) + text_libc = ffi_libc.cast("char *", text_addr) + args_libc = ffi_libc.cast("void *", args_addr) + + out = ffi_libc.new("char **") + if libc.vasprintf(out, text_libc, args_libc) >= 0 and out[0] != ffi_libc.NULL: + text_str = ffi_libc.string(out[0]).decode("utf-8", "replace") + libc.free(out[0]) + else: + text_str = rl.ffi.string(text).decode("utf-8", "replace") + except Exception as e: + text_str = f"[Log decode error: {e}]" + + if log_level == rl.TraceLogLevel.LOG_ERROR: + cloudlog.error(f"raylib: {text_str}") + elif log_level == rl.TraceLogLevel.LOG_WARNING: + cloudlog.warning(f"raylib: {text_str}") + elif log_level == rl.TraceLogLevel.LOG_INFO: + cloudlog.info(f"raylib: {text_str}") + elif log_level == rl.TraceLogLevel.LOG_DEBUG: + cloudlog.debug(f"raylib: {text_str}") + else: + cloudlog.error(f"raylib: Unknown level {log_level}: {text_str}") + + # Store callback reference + self._trace_log_callback = trace_log_callback + rl.set_trace_log_callback(self._trace_log_callback) + + def _monitor_fps(self): + fps = rl.get_fps() + + # Log FPS drop below threshold at regular intervals + if fps < self._target_fps * FPS_DROP_THRESHOLD: + current_time = time.monotonic() + if current_time - self._last_fps_log_time >= FPS_LOG_INTERVAL: + cloudlog.warning(f"FPS dropped below {self._target_fps}: {fps}") + self._last_fps_log_time = current_time + + # Strict mode: terminate UI if FPS drops too much + if STRICT_MODE and fps < self._target_fps * FPS_CRITICAL_THRESHOLD: + cloudlog.error(f"FPS dropped critically below {fps}. Shutting down UI.") + os._exit(1) + + +gui_app = GuiApplication(2160, 1080) diff --git a/system/ui/lib/egl.py b/system/ui/lib/egl.py new file mode 100644 index 0000000000..d119a8a832 --- /dev/null +++ b/system/ui/lib/egl.py @@ -0,0 +1,177 @@ +import os +import cffi +from dataclasses import dataclass +from typing import Any +from openpilot.common.swaglog import cloudlog + +# EGL constants +EGL_LINUX_DMA_BUF_EXT = 0x3270 +EGL_WIDTH = 0x3057 +EGL_HEIGHT = 0x3056 +EGL_LINUX_DRM_FOURCC_EXT = 0x3271 +EGL_DMA_BUF_PLANE0_FD_EXT = 0x3272 +EGL_DMA_BUF_PLANE0_OFFSET_EXT = 0x3273 +EGL_DMA_BUF_PLANE0_PITCH_EXT = 0x3274 +EGL_DMA_BUF_PLANE1_FD_EXT = 0x3275 +EGL_DMA_BUF_PLANE1_OFFSET_EXT = 0x3276 +EGL_DMA_BUF_PLANE1_PITCH_EXT = 0x3277 +EGL_NONE = 0x3038 +GL_TEXTURE0 = 0x84C0 +GL_TEXTURE_EXTERNAL_OES = 0x8D65 + +# DRM Format for NV12 +DRM_FORMAT_NV12 = 842094158 + + +@dataclass +class EGLImage: + """Container for EGL image and associated resources""" + + egl_image: Any + fd: int + + +@dataclass +class EGLState: + """Container for all EGL-related state""" + + initialized: bool = False + ffi: Any = None + egl_lib: Any = None + gles_lib: Any = None + + # EGL display connection - shared across all users + display: Any = None + + # Constants + NO_CONTEXT: Any = None + NO_DISPLAY: Any = None + NO_IMAGE_KHR: Any = None + + # Function pointers + get_current_display: Any = None + create_image_khr: Any = None + destroy_image_khr: Any = None + image_target_texture: Any = None + get_error: Any = None + bind_texture: Any = None + active_texture: Any = None + + +# Create a single instance of the state +_egl = EGLState() + + +def init_egl() -> bool: + """Initialize EGL and load necessary functions""" + global _egl + + # Don't re-initialize if already done + if _egl.initialized: + return True + + try: + _egl.ffi = cffi.FFI() + _egl.ffi.cdef(""" + typedef int EGLint; + typedef unsigned int EGLBoolean; + typedef unsigned int EGLenum; + typedef unsigned int GLenum; + typedef void *EGLContext; + typedef void *EGLDisplay; + typedef void *EGLClientBuffer; + typedef void *EGLImageKHR; + typedef void *GLeglImageOES; + + EGLDisplay eglGetCurrentDisplay(void); + EGLint eglGetError(void); + EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attrib_list); + EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image); + void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image); + void glBindTexture(GLenum target, unsigned int texture); + void glActiveTexture(GLenum texture); + """) + + # Load libraries + _egl.egl_lib = _egl.ffi.dlopen("libEGL.so") + _egl.gles_lib = _egl.ffi.dlopen("libGLESv2.so") + + # Cast NULL pointers + _egl.NO_CONTEXT = _egl.ffi.cast("void *", 0) + _egl.NO_DISPLAY = _egl.ffi.cast("void *", 0) + _egl.NO_IMAGE_KHR = _egl.ffi.cast("void *", 0) + + # Bind functions + _egl.get_current_display = _egl.egl_lib.eglGetCurrentDisplay + _egl.create_image_khr = _egl.egl_lib.eglCreateImageKHR + _egl.destroy_image_khr = _egl.egl_lib.eglDestroyImageKHR + _egl.image_target_texture = _egl.gles_lib.glEGLImageTargetTexture2DOES + _egl.get_error = _egl.egl_lib.eglGetError + _egl.bind_texture = _egl.gles_lib.glBindTexture + _egl.active_texture = _egl.gles_lib.glActiveTexture + + # Initialize EGL display once here + _egl.display = _egl.get_current_display() + if _egl.display == _egl.NO_DISPLAY: + raise RuntimeError("Failed to get EGL display") + + _egl.initialized = True + return True + except Exception as e: + cloudlog.exception(f"EGL initialization failed: {e}") + _egl.initialized = False + return False + + +def create_egl_image(width: int, height: int, stride: int, fd: int, uv_offset: int) -> EGLImage | None: + assert _egl.initialized, "EGL not initialized" + + # Duplicate fd since EGL needs it + dup_fd = os.dup(fd) + + # Create image attributes for EGL + img_attrs = [ + EGL_WIDTH, width, + EGL_HEIGHT, height, + EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_NV12, + EGL_DMA_BUF_PLANE0_FD_EXT, dup_fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, stride, + EGL_DMA_BUF_PLANE1_FD_EXT, dup_fd, + EGL_DMA_BUF_PLANE1_OFFSET_EXT, uv_offset, + EGL_DMA_BUF_PLANE1_PITCH_EXT, stride, + EGL_NONE + ] + + attr_array = _egl.ffi.new("int[]", img_attrs) + egl_image = _egl.create_image_khr(_egl.display, _egl.NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, _egl.ffi.NULL, attr_array) + + if egl_image == _egl.NO_IMAGE_KHR: + cloudlog.error(f"Failed to create EGL image: {_egl.get_error()}") + os.close(dup_fd) + return None + + return EGLImage(egl_image=egl_image, fd=dup_fd) + + +def destroy_egl_image(egl_image: EGLImage) -> None: + assert _egl.initialized, "EGL not initialized" + + _egl.destroy_image_khr(_egl.display, egl_image.egl_image) + + # Close the duplicated fd we created in create_egl_image() + # We need to handle OSError since the fd might already be closed + try: + os.close(egl_image.fd) + except OSError: + pass + + +def bind_egl_image_to_texture(texture_id: int, egl_image: EGLImage) -> None: + assert _egl.initialized, "EGL not initialized" + + _egl.active_texture(GL_TEXTURE0) + _egl.bind_texture(GL_TEXTURE_EXTERNAL_OES, texture_id) + _egl.image_target_texture(GL_TEXTURE_EXTERNAL_OES, egl_image.egl_image) diff --git a/system/ui/lib/emoji.py b/system/ui/lib/emoji.py new file mode 100644 index 0000000000..28139158a1 --- /dev/null +++ b/system/ui/lib/emoji.py @@ -0,0 +1,47 @@ +import io +import re + +from PIL import Image, ImageDraw, ImageFont +import pyray as rl + +_cache: dict[str, rl.Texture] = {} + +EMOJI_REGEX = re.compile( +"""[\U0001F600-\U0001F64F +\U0001F300-\U0001F5FF +\U0001F680-\U0001F6FF +\U0001F1E0-\U0001F1FF +\U00002700-\U000027BF +\U0001F900-\U0001F9FF +\U00002600-\U000026FF +\U00002300-\U000023FF +\U00002B00-\U00002BFF +\U0001FA70-\U0001FAFF +\U0001F700-\U0001F77F +\u2640-\u2642 +\u2600-\u2B55 +\u200d +\u23cf +\u23e9 +\u231a +\ufe0f +\u3030 +]+""", + flags=re.UNICODE +) + +def find_emoji(text): + return [(m.start(), m.end(), m.group()) for m in EMOJI_REGEX.finditer(text)] + +def emoji_tex(emoji): + if emoji not in _cache: + img = Image.new("RGBA", (128, 128), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + font = ImageFont.truetype("NotoColorEmoji", 109) + draw.text((0, 0), emoji, font=font, embedded_color=True) + buffer = io.BytesIO() + img.save(buffer, format="PNG") + l = buffer.tell() + buffer.seek(0) + _cache[emoji] = rl.load_texture_from_image(rl.load_image_from_memory(".png", buffer.getvalue(), l)) + return _cache[emoji] diff --git a/system/ui/lib/networkmanager.py b/system/ui/lib/networkmanager.py new file mode 100644 index 0000000000..ffa2ff4db9 --- /dev/null +++ b/system/ui/lib/networkmanager.py @@ -0,0 +1,46 @@ +from enum import IntEnum + + +# NetworkManager device states +class NMDeviceState(IntEnum): + UNKNOWN = 0 + DISCONNECTED = 30 + PREPARE = 40 + STATE_CONFIG = 50 + NEED_AUTH = 60 + IP_CONFIG = 70 + ACTIVATED = 100 + DEACTIVATING = 110 + + +# NetworkManager constants +NM = "org.freedesktop.NetworkManager" +NM_PATH = '/org/freedesktop/NetworkManager' +NM_IFACE = 'org.freedesktop.NetworkManager' +NM_ACCESS_POINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' +NM_SETTINGS_PATH = '/org/freedesktop/NetworkManager/Settings' +NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManager.Settings' +NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManager.Settings.Connection' +NM_ACTIVE_CONNECTION_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' +NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' +NM_PROPERTIES_IFACE = 'org.freedesktop.DBus.Properties' +NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' +NM_IP4_CONFIG_IFACE = 'org.freedesktop.NetworkManager.IP4Config' + +NM_DEVICE_TYPE_WIFI = 2 +NM_DEVICE_TYPE_MODEM = 8 +NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8 +NM_DEVICE_STATE_REASON_NEW_ACTIVATION = 60 + +# https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApFlags +NM_802_11_AP_FLAGS_NONE = 0x0 +NM_802_11_AP_FLAGS_PRIVACY = 0x1 +NM_802_11_AP_FLAGS_WPS = 0x2 + +# https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApSecurityFlags +NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001 +NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002 +NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010 +NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020 +NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100 +NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200 diff --git a/system/ui/lib/scroll_panel.py b/system/ui/lib/scroll_panel.py new file mode 100644 index 0000000000..d0d59df1ff --- /dev/null +++ b/system/ui/lib/scroll_panel.py @@ -0,0 +1,125 @@ +import math +import pyray as rl +from enum import IntEnum +from openpilot.system.ui.lib.application import gui_app, MouseEvent +from openpilot.common.filter_simple import FirstOrderFilter + +# Scroll constants for smooth scrolling behavior +MOUSE_WHEEL_SCROLL_SPEED = 50 +BOUNCE_RETURN_RATE = 5 # ~0.92 at 60fps +MIN_VELOCITY = 2 # px/s, changes from auto scroll to steady state +MIN_VELOCITY_FOR_CLICKING = 2 * 60 # px/s, accepts clicks while auto scrolling below this velocity +DRAG_THRESHOLD = 12 # pixels of movement to consider it a drag, not a click + +DEBUG = False + + +class ScrollState(IntEnum): + IDLE = 0 # Not dragging, content may be bouncing or scrolling with inertia + DRAGGING_CONTENT = 1 # User is actively dragging the content + + +class GuiScrollPanel: + def __init__(self): + self._scroll_state: ScrollState = ScrollState.IDLE + self._last_mouse_y: float = 0.0 + self._start_mouse_y: float = 0.0 # Track the initial mouse position for drag detection + self._offset_filter_y = FirstOrderFilter(0.0, 0.1, 1 / gui_app.target_fps) + self._velocity_filter_y = FirstOrderFilter(0.0, 0.05, 1 / gui_app.target_fps) + self._last_drag_time: float = 0.0 + + def update(self, bounds: rl.Rectangle, content: rl.Rectangle) -> float: + for mouse_event in gui_app.mouse_events: + if mouse_event.slot == 0: + self._handle_mouse_event(mouse_event, bounds, content) + + self._update_state(bounds, content) + + return float(self._offset_filter_y.x) + + def _update_state(self, bounds: rl.Rectangle, content: rl.Rectangle): + if DEBUG: + rl.draw_rectangle_lines(0, 0, abs(int(self._velocity_filter_y.x)), 10, rl.RED) + + # Handle mouse wheel + self._offset_filter_y.x += rl.get_mouse_wheel_move() * MOUSE_WHEEL_SCROLL_SPEED + + max_scroll_distance = max(0, content.height - bounds.height) + if self._scroll_state == ScrollState.IDLE: + above_bounds, below_bounds = self._check_bounds(bounds, content) + + # Decay velocity when idle + if abs(self._velocity_filter_y.x) > MIN_VELOCITY: + # Faster decay if bouncing back from out of bounds + friction = math.exp(-BOUNCE_RETURN_RATE * 1 / gui_app.target_fps) + self._velocity_filter_y.x *= friction ** 2 if (above_bounds or below_bounds) else friction + else: + self._velocity_filter_y.x = 0.0 + + if above_bounds or below_bounds: + if above_bounds: + self._offset_filter_y.update(0) + else: + self._offset_filter_y.update(-max_scroll_distance) + + self._offset_filter_y.x += self._velocity_filter_y.x / gui_app.target_fps + + elif self._scroll_state == ScrollState.DRAGGING_CONTENT: + # Mouse not moving, decay velocity + if not len(gui_app.mouse_events): + self._velocity_filter_y.update(0.0) + + # Settle to exact bounds + if abs(self._offset_filter_y.x) < 1e-2: + self._offset_filter_y.x = 0.0 + elif abs(self._offset_filter_y.x + max_scroll_distance) < 1e-2: + self._offset_filter_y.x = -max_scroll_distance + + def _handle_mouse_event(self, mouse_event: MouseEvent, bounds: rl.Rectangle, content: rl.Rectangle): + if self._scroll_state == ScrollState.IDLE: + if rl.check_collision_point_rec(mouse_event.pos, bounds): + if mouse_event.left_pressed: + self._start_mouse_y = mouse_event.pos.y + # Interrupt scrolling with new drag + # TODO: stop scrolling with any tap, need to fix is_touch_valid + if abs(self._velocity_filter_y.x) > MIN_VELOCITY_FOR_CLICKING: + self._scroll_state = ScrollState.DRAGGING_CONTENT + # Start velocity at initial measurement for more immediate response + self._velocity_filter_y.initialized = False + + if mouse_event.left_down: + if abs(mouse_event.pos.y - self._start_mouse_y) > DRAG_THRESHOLD: + self._scroll_state = ScrollState.DRAGGING_CONTENT + # Start velocity at initial measurement for more immediate response + self._velocity_filter_y.initialized = False + + elif self._scroll_state == ScrollState.DRAGGING_CONTENT: + if mouse_event.left_released: + self._scroll_state = ScrollState.IDLE + else: + delta_y = mouse_event.pos.y - self._last_mouse_y + above_bounds, below_bounds = self._check_bounds(bounds, content) + # Rubber banding effect when out of bands + if above_bounds or below_bounds: + delta_y /= 3 + + self._offset_filter_y.x += delta_y + + # Track velocity for inertia + dt = mouse_event.t - self._last_drag_time + if dt > 0: + drag_velocity = delta_y / dt + self._velocity_filter_y.update(drag_velocity) + + # TODO: just store last mouse event! + self._last_drag_time = mouse_event.t + self._last_mouse_y = mouse_event.pos.y + + def _check_bounds(self, bounds: rl.Rectangle, content: rl.Rectangle) -> tuple[bool, bool]: + max_scroll_distance = max(0, content.height - bounds.height) + above_bounds = self._offset_filter_y.x > 0 + below_bounds = self._offset_filter_y.x < -max_scroll_distance + return above_bounds, below_bounds + + def is_touch_valid(self): + return self._scroll_state == ScrollState.IDLE and abs(self._velocity_filter_y.x) < MIN_VELOCITY_FOR_CLICKING diff --git a/system/ui/lib/shader_polygon.py b/system/ui/lib/shader_polygon.py new file mode 100644 index 0000000000..d03ad5d8c6 --- /dev/null +++ b/system/ui/lib/shader_polygon.py @@ -0,0 +1,319 @@ +import platform +import pyray as rl +import numpy as np +from typing import Any + +MAX_GRADIENT_COLORS = 15 + +VERSION = """ +#version 300 es +precision highp float; +""" +if platform.system() == "Darwin": + VERSION = """ + #version 330 core + """ + +FRAGMENT_SHADER = VERSION + """ +in vec2 fragTexCoord; +out vec4 finalColor; + +uniform vec2 points[100]; +uniform int pointCount; +uniform vec4 fillColor; +uniform vec2 resolution; + +uniform int useGradient; +uniform vec2 gradientStart; +uniform vec2 gradientEnd; +uniform vec4 gradientColors[15]; +uniform float gradientStops[15]; +uniform int gradientColorCount; + +vec4 getGradientColor(vec2 pos) { + vec2 gradientDir = gradientEnd - gradientStart; + float gradientLength = length(gradientDir); + if (gradientLength < 0.001) return gradientColors[0]; + + vec2 normalizedDir = gradientDir / gradientLength; + float t = clamp(dot(pos - gradientStart, normalizedDir) / gradientLength, 0.0, 1.0); + + if (gradientColorCount <= 1) return gradientColors[0]; + + // handle t before first / after last stop + if (t <= gradientStops[0]) return gradientColors[0]; + if (t >= gradientStops[gradientColorCount-1]) return gradientColors[gradientColorCount-1]; + for (int i = 0; i < gradientColorCount - 1; i++) { + if (t >= gradientStops[i] && t <= gradientStops[i+1]) { + float segmentT = (t - gradientStops[i]) / (gradientStops[i+1] - gradientStops[i]); + return mix(gradientColors[i], gradientColors[i+1], segmentT); + } + } + + return gradientColors[gradientColorCount-1]; +} + +bool isPointInsidePolygon(vec2 p) { + if (pointCount < 3) return false; + int crossings = 0; + for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { + vec2 pi = points[i]; + vec2 pj = points[j]; + if (distance(pi, pj) < 0.001) continue; + if (((pi.y > p.y) != (pj.y > p.y)) && + (p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y + 0.001) + pi.x)) { + crossings++; + } + } + return (crossings & 1) == 1; +} + +float distanceToEdge(vec2 p) { + float minDist = 1000.0; + + for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { + vec2 edge0 = points[j]; + vec2 edge1 = points[i]; + + if (distance(edge0, edge1) < 0.0001) continue; + + vec2 v1 = p - edge0; + vec2 v2 = edge1 - edge0; + float l2 = dot(v2, v2); + + if (l2 < 0.0001) { + float dist = length(v1); + minDist = min(minDist, dist); + continue; + } + + float t = clamp(dot(v1, v2) / l2, 0.0, 1.0); + vec2 projection = edge0 + t * v2; + float dist = length(p - projection); + minDist = min(minDist, dist); + } + + return minDist; +} + +void main() { + vec2 pixel = fragTexCoord * resolution; + + bool inside = isPointInsidePolygon(pixel); + float sd = (inside ? 1.0 : -1.0) * distanceToEdge(pixel); + + // ~1 pixel wide anti-aliasing + float w = max(0.75, fwidth(sd)); + + float alpha = smoothstep(-w, w, sd); + if (alpha > 0.0){ + vec4 color = useGradient == 1 ? getGradientColor(pixel) : fillColor; + finalColor = vec4(color.rgb, color.a * alpha); + } else { + discard; + } +} +""" + +# Default vertex shader +VERTEX_SHADER = VERSION + """ +in vec3 vertexPosition; +in vec2 vertexTexCoord; +out vec2 fragTexCoord; +uniform mat4 mvp; + +void main() { + fragTexCoord = vertexTexCoord; + gl_Position = mvp * vec4(vertexPosition, 1.0); +} +""" + +UNIFORM_INT = rl.ShaderUniformDataType.SHADER_UNIFORM_INT +UNIFORM_FLOAT = rl.ShaderUniformDataType.SHADER_UNIFORM_FLOAT +UNIFORM_VEC2 = rl.ShaderUniformDataType.SHADER_UNIFORM_VEC2 +UNIFORM_VEC4 = rl.ShaderUniformDataType.SHADER_UNIFORM_VEC4 + + +class ShaderState: + _instance: Any = None + + @classmethod + def get_instance(cls): + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + if ShaderState._instance is not None: + raise Exception("This class is a singleton. Use get_instance() instead.") + + self.initialized = False + self.shader = None + self.white_texture = None + + # Shader uniform locations + self.locations = { + 'pointCount': None, + 'fillColor': None, + 'resolution': None, + 'points': None, + 'useGradient': None, + 'gradientStart': None, + 'gradientEnd': None, + 'gradientColors': None, + 'gradientStops': None, + 'gradientColorCount': None, + 'mvp': None, + } + + # Pre-allocated FFI objects + self.point_count_ptr = rl.ffi.new("int[]", [0]) + self.resolution_ptr = rl.ffi.new("float[]", [0.0, 0.0]) + self.fill_color_ptr = rl.ffi.new("float[]", [0.0, 0.0, 0.0, 0.0]) + self.use_gradient_ptr = rl.ffi.new("int[]", [0]) + self.gradient_start_ptr = rl.ffi.new("float[]", [0.0, 0.0]) + self.gradient_end_ptr = rl.ffi.new("float[]", [0.0, 0.0]) + self.color_count_ptr = rl.ffi.new("int[]", [0]) + self.gradient_colors_ptr = rl.ffi.new("float[]", MAX_GRADIENT_COLORS * 4) + self.gradient_stops_ptr = rl.ffi.new("float[]", MAX_GRADIENT_COLORS) + + def initialize(self): + if self.initialized: + return + + self.shader = rl.load_shader_from_memory(VERTEX_SHADER, FRAGMENT_SHADER) + + # Create and cache white texture + white_img = rl.gen_image_color(2, 2, rl.WHITE) + self.white_texture = rl.load_texture_from_image(white_img) + rl.set_texture_filter(self.white_texture, rl.TEXTURE_FILTER_BILINEAR) + rl.unload_image(white_img) + + # Cache all uniform locations + for uniform in self.locations.keys(): + self.locations[uniform] = rl.get_shader_location(self.shader, uniform) + + # Setup default MVP matrix + mvp_ptr = rl.ffi.new("float[16]", [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]) + rl.set_shader_value_matrix(self.shader, self.locations['mvp'], rl.Matrix(*mvp_ptr)) + + self.initialized = True + + def cleanup(self): + if not self.initialized: + return + + if self.white_texture: + rl.unload_texture(self.white_texture) + self.white_texture = None + + if self.shader: + rl.unload_shader(self.shader) + self.shader = None + + self.initialized = False + + +def _configure_shader_color(state, color, gradient, clipped_rect, original_rect): + use_gradient = 1 if gradient else 0 + state.use_gradient_ptr[0] = use_gradient + rl.set_shader_value(state.shader, state.locations['useGradient'], state.use_gradient_ptr, UNIFORM_INT) + + if use_gradient: + start = np.array(gradient['start']) * np.array([original_rect.width, original_rect.height]) + np.array([original_rect.x, original_rect.y]) + end = np.array(gradient['end']) * np.array([original_rect.width, original_rect.height]) + np.array([original_rect.x, original_rect.y]) + start = start - np.array([clipped_rect.x, clipped_rect.y]) + end = end - np.array([clipped_rect.x, clipped_rect.y]) + state.gradient_start_ptr[0:2] = start.astype(np.float32) + state.gradient_end_ptr[0:2] = end.astype(np.float32) + rl.set_shader_value(state.shader, state.locations['gradientStart'], state.gradient_start_ptr, UNIFORM_VEC2) + rl.set_shader_value(state.shader, state.locations['gradientEnd'], state.gradient_end_ptr, UNIFORM_VEC2) + + colors = gradient['colors'] + color_count = min(len(colors), MAX_GRADIENT_COLORS) + state.color_count_ptr[0] = color_count + for i, c in enumerate(colors[:color_count]): + base_idx = i * 4 + state.gradient_colors_ptr[base_idx:base_idx+4] = [c.r / 255.0, c.g / 255.0, c.b / 255.0, c.a / 255.0] + rl.set_shader_value_v(state.shader, state.locations['gradientColors'], state.gradient_colors_ptr, UNIFORM_VEC4, color_count) + + stops = gradient.get('stops', [i / max(1, color_count - 1) for i in range(color_count)]) + stops = np.clip(stops[:color_count], 0.0, 1.0) + state.gradient_stops_ptr[0:color_count] = stops + rl.set_shader_value_v(state.shader, state.locations['gradientStops'], state.gradient_stops_ptr, UNIFORM_FLOAT, color_count) + rl.set_shader_value(state.shader, state.locations['gradientColorCount'], state.color_count_ptr, UNIFORM_INT) + else: + color = color or rl.WHITE + state.fill_color_ptr[0:4] = [color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0] + rl.set_shader_value(state.shader, state.locations['fillColor'], state.fill_color_ptr, UNIFORM_VEC4) + + +def draw_polygon(origin_rect: rl.Rectangle, points: np.ndarray, color=None, gradient=None): + """ + Draw a complex polygon using shader-based even-odd fill rule + + Args: + rect: Rectangle defining the drawing area + points: numpy array of (x,y) points defining the polygon + color: Solid fill color (rl.Color) + gradient: Dict with gradient parameters: + { + 'start': (x1, y1), # Start point (normalized 0-1) + 'end': (x2, y2), # End point (normalized 0-1) + 'colors': [rl.Color], # List of colors at stops + 'stops': [float] # List of positions (0-1) + } + """ + if len(points) < 3: + return + + state = ShaderState.get_instance() + if not state.initialized: + state.initialize() + + # Find bounding box + min_xy = np.min(points, axis=0) + max_xy = np.max(points, axis=0) + clip_x = max(origin_rect.x, min_xy[0]) + clip_y = max(origin_rect.y, min_xy[1]) + clip_right = min(origin_rect.x + origin_rect.width, max_xy[0]) + clip_bottom = min(origin_rect.y + origin_rect.height, max_xy[1]) + + # Check if polygon is completely off-screen + if clip_x >= clip_right or clip_y >= clip_bottom: + return + + clipped_rect = rl.Rectangle(clip_x, clip_y, clip_right - clip_x, clip_bottom - clip_y) + + # Transform points relative to the CLIPPED area + transformed_points = points - np.array([clip_x, clip_y]) + + # Set shader values + state.point_count_ptr[0] = len(transformed_points) + rl.set_shader_value(state.shader, state.locations['pointCount'], state.point_count_ptr, UNIFORM_INT) + + state.resolution_ptr[0:2] = [clipped_rect.width, clipped_rect.height] + rl.set_shader_value(state.shader, state.locations['resolution'], state.resolution_ptr, UNIFORM_VEC2) + + flat_points = np.ascontiguousarray(transformed_points.flatten().astype(np.float32)) + points_ptr = rl.ffi.cast("float *", flat_points.ctypes.data) + rl.set_shader_value_v(state.shader, state.locations['points'], points_ptr, UNIFORM_VEC2, len(transformed_points)) + + _configure_shader_color(state, color, gradient, clipped_rect, origin_rect) + + # Render + rl.begin_shader_mode(state.shader) + rl.draw_texture_pro( + state.white_texture, + rl.Rectangle(0, 0, 2, 2), + clipped_rect, + rl.Vector2(0, 0), + 0.0, + rl.WHITE, + ) + rl.end_shader_mode() + + +def cleanup_shader_resources(): + state = ShaderState.get_instance() + state.cleanup() diff --git a/system/ui/lib/text_measure.py b/system/ui/lib/text_measure.py new file mode 100644 index 0000000000..fcb7b25ccd --- /dev/null +++ b/system/ui/lib/text_measure.py @@ -0,0 +1,15 @@ +import pyray as rl +from openpilot.system.ui.lib.application import FONT_SCALE + +_cache: dict[int, rl.Vector2] = {} + + +def measure_text_cached(font: rl.Font, text: str, font_size: int, spacing: int = 0) -> rl.Vector2: + """Caches text measurements to avoid redundant calculations.""" + key = hash((font.texture.id, text, font_size, spacing)) + if key in _cache: + return _cache[key] + + result = rl.measure_text_ex(font, text, font_size * FONT_SCALE, spacing) # noqa: TID251 + _cache[key] = result + return result diff --git a/system/ui/lib/utils.py b/system/ui/lib/utils.py new file mode 100644 index 0000000000..77035d0da0 --- /dev/null +++ b/system/ui/lib/utils.py @@ -0,0 +1,18 @@ +import pyray as rl + + +class GuiStyleContext: + def __init__(self, styles: list[tuple[int, int, int]]): + """styles is a list of tuples (control, prop, new_value)""" + self.styles = styles + self.prev_styles: list[tuple[int, int, int]] = [] + + def __enter__(self): + for control, prop, new_value in self.styles: + prev_value = rl.gui_get_style(control, prop) + self.prev_styles.append((control, prop, prev_value)) + rl.gui_set_style(control, prop, new_value) + + def __exit__(self, exc_type, exc_value, traceback): + for control, prop, prev_value in self.prev_styles: + rl.gui_set_style(control, prop, prev_value) diff --git a/system/ui/lib/wifi_manager.py b/system/ui/lib/wifi_manager.py new file mode 100644 index 0000000000..5594742cb3 --- /dev/null +++ b/system/ui/lib/wifi_manager.py @@ -0,0 +1,754 @@ +import atexit +import threading +import time +import uuid +import subprocess +from collections.abc import Callable +from dataclasses import dataclass +from enum import IntEnum +from typing import Any + +from jeepney import DBusAddress, new_method_call +from jeepney.bus_messages import MatchRule, message_bus +from jeepney.io.blocking import open_dbus_connection as open_dbus_connection_blocking +from jeepney.io.threading import DBusRouter, open_dbus_connection as open_dbus_connection_threading +from jeepney.low_level import MessageType +from jeepney.wrappers import Properties + +from openpilot.common.swaglog import cloudlog +from openpilot.system.ui.lib.networkmanager import (NM, NM_WIRELESS_IFACE, NM_802_11_AP_SEC_PAIR_WEP40, + NM_802_11_AP_SEC_PAIR_WEP104, NM_802_11_AP_SEC_GROUP_WEP40, + NM_802_11_AP_SEC_GROUP_WEP104, NM_802_11_AP_SEC_KEY_MGMT_PSK, + NM_802_11_AP_SEC_KEY_MGMT_802_1X, NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, NM_802_11_AP_FLAGS_WPS, + NM_PATH, NM_IFACE, NM_ACCESS_POINT_IFACE, NM_SETTINGS_PATH, + NM_SETTINGS_IFACE, NM_CONNECTION_IFACE, NM_DEVICE_IFACE, + NM_DEVICE_TYPE_WIFI, NM_DEVICE_TYPE_MODEM, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, + NM_DEVICE_STATE_REASON_NEW_ACTIVATION, NM_ACTIVE_CONNECTION_IFACE, + NM_IP4_CONFIG_IFACE, NMDeviceState) + +try: + from openpilot.common.params import Params +except Exception: + Params = None + +TETHERING_IP_ADDRESS = "192.168.43.1" +DEFAULT_TETHERING_PASSWORD = "swagswagcomma" +SIGNAL_QUEUE_SIZE = 10 +SCAN_PERIOD_SECONDS = 10 + + +class SecurityType(IntEnum): + OPEN = 0 + WPA = 1 + WPA2 = 2 + WPA3 = 3 + UNSUPPORTED = 4 + + +class MeteredType(IntEnum): + UNKNOWN = 0 + YES = 1 + NO = 2 + + +def get_security_type(flags: int, wpa_flags: int, rsn_flags: int) -> SecurityType: + wpa_props = wpa_flags | rsn_flags + + # obtained by looking at flags of networks in the office as reported by an Android phone + supports_wpa = (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_GROUP_WEP40 | + NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_KEY_MGMT_PSK) + + if (flags == NM_802_11_AP_FLAGS_NONE) or ((flags & NM_802_11_AP_FLAGS_WPS) and not (wpa_props & supports_wpa)): + return SecurityType.OPEN + elif (flags & NM_802_11_AP_FLAGS_PRIVACY) and (wpa_props & supports_wpa) and not (wpa_props & NM_802_11_AP_SEC_KEY_MGMT_802_1X): + return SecurityType.WPA + else: + cloudlog.warning(f"Unsupported network! flags: {flags}, wpa_flags: {wpa_flags}, rsn_flags: {rsn_flags}") + return SecurityType.UNSUPPORTED + + +@dataclass(frozen=True) +class Network: + ssid: str + strength: int + is_connected: bool + security_type: SecurityType + is_saved: bool + + @classmethod + def from_dbus(cls, ssid: str, aps: list["AccessPoint"], is_saved: bool) -> "Network": + # we only want to show the strongest AP for each Network/SSID + strongest_ap = max(aps, key=lambda ap: ap.strength) + is_connected = any(ap.is_connected for ap in aps) + security_type = get_security_type(strongest_ap.flags, strongest_ap.wpa_flags, strongest_ap.rsn_flags) + + return cls( + ssid=ssid, + strength=strongest_ap.strength, + is_connected=is_connected and is_saved, + security_type=security_type, + is_saved=is_saved, + ) + + +@dataclass(frozen=True) +class AccessPoint: + ssid: str + bssid: str + strength: int + is_connected: bool + flags: int + wpa_flags: int + rsn_flags: int + ap_path: str + + @classmethod + def from_dbus(cls, ap_props: dict[str, tuple[str, Any]], ap_path: str, active_ap_path: str) -> "AccessPoint": + ssid = bytes(ap_props['Ssid'][1]).decode("utf-8", "replace") + bssid = str(ap_props['HwAddress'][1]) + strength = int(ap_props['Strength'][1]) + flags = int(ap_props['Flags'][1]) + wpa_flags = int(ap_props['WpaFlags'][1]) + rsn_flags = int(ap_props['RsnFlags'][1]) + + return cls( + ssid=ssid, + bssid=bssid, + strength=strength, + is_connected=ap_path == active_ap_path, + flags=flags, + wpa_flags=wpa_flags, + rsn_flags=rsn_flags, + ap_path=ap_path, + ) + + +class WifiManager: + def __init__(self): + self._networks: list[Network] = [] # a network can be comprised of multiple APs + self._active = True # used to not run when not in settings + self._exit = False + + # DBus connections + try: + self._router_main = DBusRouter(open_dbus_connection_threading(bus="SYSTEM")) # used by scanner / general method calls + self._conn_monitor = open_dbus_connection_blocking(bus="SYSTEM") # used by state monitor thread + self._nm = DBusAddress(NM_PATH, bus_name=NM, interface=NM_IFACE) + except FileNotFoundError: + cloudlog.exception("Failed to connect to system D-Bus") + self._exit = True + + # Store wifi device path + self._wifi_device: str | None = None + + # State + self._connecting_to_ssid: str = "" + self._ipv4_address: str = "" + self._current_network_metered: MeteredType = MeteredType.UNKNOWN + self._tethering_password: str = "" + self._ipv4_forward = False + + self._last_network_update: float = 0.0 + self._callback_queue: list[Callable] = [] + + self._tethering_ssid = "weedle" + if Params is not None: + dongle_id = Params().get("DongleId") + if dongle_id: + self._tethering_ssid += "-" + dongle_id[:4] + + # Callbacks + self._need_auth: list[Callable[[str], None]] = [] + self._activated: list[Callable[[], None]] = [] + self._forgotten: list[Callable[[], None]] = [] + self._networks_updated: list[Callable[[list[Network]], None]] = [] + self._disconnected: list[Callable[[], None]] = [] + + self._lock = threading.Lock() + self._scan_thread = threading.Thread(target=self._network_scanner, daemon=True) + self._state_thread = threading.Thread(target=self._monitor_state, daemon=True) + self._initialize() + atexit.register(self.stop) + + def _initialize(self): + def worker(): + self._wait_for_wifi_device() + + self._scan_thread.start() + self._state_thread.start() + + if Params is not None and self._tethering_ssid not in self._get_connections(): + self._add_tethering_connection() + + self._tethering_password = self._get_tethering_password() + cloudlog.debug("WifiManager initialized") + + threading.Thread(target=worker, daemon=True).start() + + def set_callbacks(self, need_auth: Callable[[str], None] | None = None, + activated: Callable[[], None] | None = None, + forgotten: Callable[[], None] | None = None, + networks_updated: Callable[[list[Network]], None] | None = None, + disconnected: Callable[[], None] | None = None): + if need_auth is not None: + self._need_auth.append(need_auth) + if activated is not None: + self._activated.append(activated) + if forgotten is not None: + self._forgotten.append(forgotten) + if networks_updated is not None: + self._networks_updated.append(networks_updated) + if disconnected is not None: + self._disconnected.append(disconnected) + + @property + def ipv4_address(self) -> str: + return self._ipv4_address + + @property + def current_network_metered(self) -> MeteredType: + return self._current_network_metered + + @property + def tethering_password(self) -> str: + return self._tethering_password + + def _enqueue_callbacks(self, cbs: list[Callable], *args): + for cb in cbs: + self._callback_queue.append(lambda _cb=cb: _cb(*args)) + + def process_callbacks(self): + # Call from UI thread to run any pending callbacks + to_run, self._callback_queue = self._callback_queue, [] + for cb in to_run: + cb() + + def set_active(self, active: bool): + self._active = active + + # Scan immediately if we haven't scanned in a while + if active and time.monotonic() - self._last_network_update > SCAN_PERIOD_SECONDS / 2: + self._last_network_update = 0.0 + + def _monitor_state(self): + rule = MatchRule( + type="signal", + interface=NM_DEVICE_IFACE, + member="StateChanged", + path=self._wifi_device, + ) + + # Filter for StateChanged signal + self._conn_monitor.send_and_get_reply(message_bus.AddMatch(rule)) + + with self._conn_monitor.filter(rule, bufsize=SIGNAL_QUEUE_SIZE) as q: + while not self._exit: + if not self._active: + time.sleep(1) + continue + + # Block until a matching signal arrives + try: + msg = self._conn_monitor.recv_until_filtered(q, timeout=1) + except TimeoutError: + continue + + new_state, previous_state, change_reason = msg.body + + # BAD PASSWORD + if new_state == NMDeviceState.NEED_AUTH and change_reason == NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT and len(self._connecting_to_ssid): + self.forget_connection(self._connecting_to_ssid, block=True) + self._enqueue_callbacks(self._need_auth, self._connecting_to_ssid) + self._connecting_to_ssid = "" + + elif new_state == NMDeviceState.ACTIVATED: + if len(self._activated): + self._update_networks() + self._enqueue_callbacks(self._activated) + self._connecting_to_ssid = "" + + elif new_state == NMDeviceState.DISCONNECTED and change_reason != NM_DEVICE_STATE_REASON_NEW_ACTIVATION: + self._connecting_to_ssid = "" + self._enqueue_callbacks(self._forgotten) + + def _network_scanner(self): + while not self._exit: + if self._active: + if time.monotonic() - self._last_network_update > SCAN_PERIOD_SECONDS: + # Scan for networks every 10 seconds + # TODO: should update when scan is complete (PropertiesChanged), but this is more than good enough for now + self._update_networks() + self._request_scan() + self._last_network_update = time.monotonic() + time.sleep(1 / 2.) + + def _wait_for_wifi_device(self): + while not self._exit: + device_path = self._get_adapter(NM_DEVICE_TYPE_WIFI) + if device_path is not None: + self._wifi_device = device_path + break + time.sleep(1) + + def _get_adapter(self, adapter_type: int) -> str | None: + # Return the first NetworkManager device path matching adapter_type + try: + device_paths = self._router_main.send_and_get_reply(new_method_call(self._nm, 'GetDevices')).body[0] + for device_path in device_paths: + dev_addr = DBusAddress(device_path, bus_name=NM, interface=NM_DEVICE_IFACE) + dev_type = self._router_main.send_and_get_reply(Properties(dev_addr).get('DeviceType')).body[0][1] + if dev_type == adapter_type: + return str(device_path) + except Exception as e: + cloudlog.exception(f"Error getting adapter type {adapter_type}: {e}") + return None + + def _get_connections(self) -> dict[str, str]: + settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) + known_connections = self._router_main.send_and_get_reply(new_method_call(settings_addr, 'ListConnections')).body[0] + + conns: dict[str, str] = {} + for conn_path in known_connections: + settings = self._get_connection_settings(conn_path) + + if len(settings) == 0: + cloudlog.warning(f'Failed to get connection settings for {conn_path}') + continue + + if "802-11-wireless" in settings: + ssid = settings['802-11-wireless']['ssid'][1].decode("utf-8", "replace") + if ssid != "": + conns[ssid] = conn_path + return conns + + def _get_active_connections(self): + return self._router_main.send_and_get_reply(Properties(self._nm).get('ActiveConnections')).body[0][1] + + def _get_connection_settings(self, conn_path: str) -> dict: + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, 'GetSettings')) + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to get connection settings: {reply}') + return {} + return dict(reply.body[0]) + + def _add_tethering_connection(self): + connection = { + 'connection': { + 'type': ('s', '802-11-wireless'), + 'uuid': ('s', str(uuid.uuid4())), + 'id': ('s', 'Hotspot'), + 'autoconnect-retries': ('i', 0), + 'interface-name': ('s', 'wlan0'), + 'autoconnect': ('b', False), + }, + '802-11-wireless': { + 'band': ('s', 'bg'), + 'mode': ('s', 'ap'), + 'ssid': ('ay', self._tethering_ssid.encode("utf-8")), + }, + '802-11-wireless-security': { + 'group': ('as', ['ccmp']), + 'key-mgmt': ('s', 'wpa-psk'), + 'pairwise': ('as', ['ccmp']), + 'proto': ('as', ['rsn']), + 'psk': ('s', DEFAULT_TETHERING_PASSWORD), + }, + 'ipv4': { + 'method': ('s', 'shared'), + 'address-data': ('aa{sv}', [[ + ('address', ('s', TETHERING_IP_ADDRESS)), + ('prefix', ('u', 24)), + ]]), + 'gateway': ('s', TETHERING_IP_ADDRESS), + 'never-default': ('b', True), + }, + 'ipv6': {'method': ('s', 'ignore')}, + } + + settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) + self._router_main.send_and_get_reply(new_method_call(settings_addr, 'AddConnection', 'a{sa{sv}}', (connection,))) + + def connect_to_network(self, ssid: str, password: str, hidden: bool = False): + def worker(): + # Clear all connections that may already exist to the network we are connecting to + self._connecting_to_ssid = ssid + self.forget_connection(ssid, block=True) + + connection = { + 'connection': { + 'type': ('s', '802-11-wireless'), + 'uuid': ('s', str(uuid.uuid4())), + 'id': ('s', f'openpilot connection {ssid}'), + 'autoconnect-retries': ('i', 0), + }, + '802-11-wireless': { + 'ssid': ('ay', ssid.encode("utf-8")), + 'hidden': ('b', hidden), + 'mode': ('s', 'infrastructure'), + }, + 'ipv4': { + 'method': ('s', 'auto'), + 'dns-priority': ('i', 600), + }, + 'ipv6': {'method': ('s', 'ignore')}, + } + + if password: + connection['802-11-wireless-security'] = { + 'key-mgmt': ('s', 'wpa-psk'), + 'auth-alg': ('s', 'open'), + 'psk': ('s', password), + } + + settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) + self._router_main.send_and_get_reply(new_method_call(settings_addr, 'AddConnection', 'a{sa{sv}}', (connection,))) + self.activate_connection(ssid, block=True) + + threading.Thread(target=worker, daemon=True).start() + + def forget_connection(self, ssid: str, block: bool = False): + def worker(): + conn_path = self._get_connections().get(ssid, None) + if conn_path is not None: + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + self._router_main.send_and_get_reply(new_method_call(conn_addr, 'Delete')) + + if len(self._forgotten): + self._update_networks() + self._enqueue_callbacks(self._forgotten) + + if block: + worker() + else: + threading.Thread(target=worker, daemon=True).start() + + def activate_connection(self, ssid: str, block: bool = False): + def worker(): + conn_path = self._get_connections().get(ssid, None) + if conn_path is not None: + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + self._connecting_to_ssid = ssid + self._router_main.send(new_method_call(self._nm, 'ActivateConnection', 'ooo', + (conn_path, self._wifi_device, "/"))) + + if block: + worker() + else: + threading.Thread(target=worker, daemon=True).start() + + def _deactivate_connection(self, ssid: str): + for conn_path in self._get_active_connections(): + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_ACTIVE_CONNECTION_IFACE) + specific_obj_path = self._router_main.send_and_get_reply(Properties(conn_addr).get('SpecificObject')).body[0][1] + + if specific_obj_path != "/": + ap_addr = DBusAddress(specific_obj_path, bus_name=NM, interface=NM_ACCESS_POINT_IFACE) + ap_ssid = bytes(self._router_main.send_and_get_reply(Properties(ap_addr).get('Ssid')).body[0][1]).decode("utf-8", "replace") + + if ap_ssid == ssid: + self._router_main.send_and_get_reply(new_method_call(self._nm, 'DeactivateConnection', 'o', (conn_path,))) + return + + def is_tethering_active(self) -> bool: + for network in self._networks: + if network.is_connected: + return bool(network.ssid == self._tethering_ssid) + return False + + def set_tethering_password(self, password: str): + def worker(): + conn_path = self._get_connections().get(self._tethering_ssid, None) + if conn_path is None: + cloudlog.warning('No tethering connection found') + return + + settings = self._get_connection_settings(conn_path) + if len(settings) == 0: + cloudlog.warning(f'Failed to get tethering settings for {conn_path}') + return + + settings['802-11-wireless-security']['psk'] = ('s', password) + + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, 'Update', 'a{sa{sv}}', (settings,))) + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to update tethering settings: {reply}') + return + + self._tethering_password = password + if self.is_tethering_active(): + self.activate_connection(self._tethering_ssid, block=True) + + threading.Thread(target=worker, daemon=True).start() + + def _get_tethering_password(self) -> str: + conn_path = self._get_connections().get(self._tethering_ssid, None) + if conn_path is None: + cloudlog.warning('No tethering connection found') + return '' + + reply = self._router_main.send_and_get_reply(new_method_call( + DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE), + 'GetSecrets', 's', ('802-11-wireless-security',) + )) + + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to get tethering password: {reply}') + return '' + + secrets = reply.body[0] + if '802-11-wireless-security' not in secrets: + return '' + + return str(secrets['802-11-wireless-security'].get('psk', ('s', ''))[1]) + + def set_ipv4_forward(self, enabled: bool): + self._ipv4_forward = enabled + + def set_tethering_active(self, active: bool): + def worker(): + if active: + self.activate_connection(self._tethering_ssid, block=True) + + if not self._ipv4_forward: + time.sleep(5) + cloudlog.warning("net.ipv4.ip_forward = 0") + subprocess.run(["sudo", "sysctl", "net.ipv4.ip_forward=0"], check=False) + else: + self._deactivate_connection(self._tethering_ssid) + + threading.Thread(target=worker, daemon=True).start() + + def _update_current_network_metered(self) -> None: + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + self._current_network_metered = MeteredType.UNKNOWN + for active_conn in self._get_active_connections(): + conn_addr = DBusAddress(active_conn, bus_name=NM, interface=NM_ACTIVE_CONNECTION_IFACE) + conn_type = self._router_main.send_and_get_reply(Properties(conn_addr).get('Type')).body[0][1] + + if conn_type == '802-11-wireless': + conn_path = self._router_main.send_and_get_reply(Properties(conn_addr).get('Connection')).body[0][1] + if conn_path == "/": + continue + + settings = self._get_connection_settings(conn_path) + + if len(settings) == 0: + cloudlog.warning(f'Failed to get connection settings for {conn_path}') + continue + + metered_prop = settings['connection'].get('metered', ('i', 0))[1] + if metered_prop == MeteredType.YES: + self._current_network_metered = MeteredType.YES + elif metered_prop == MeteredType.NO: + self._current_network_metered = MeteredType.NO + return + + def set_current_network_metered(self, metered: MeteredType): + def worker(): + for active_conn in self._get_active_connections(): + conn_addr = DBusAddress(active_conn, bus_name=NM, interface=NM_ACTIVE_CONNECTION_IFACE) + conn_type = self._router_main.send_and_get_reply(Properties(conn_addr).get('Type')).body[0][1] + + if conn_type == '802-11-wireless' and not self.is_tethering_active(): + conn_path = self._router_main.send_and_get_reply(Properties(conn_addr).get('Connection')).body[0][1] + if conn_path == "/": + continue + + settings = self._get_connection_settings(conn_path) + + if len(settings) == 0: + cloudlog.warning(f'Failed to get connection settings for {conn_path}') + return + + settings['connection']['metered'] = ('i', int(metered)) + + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, 'Update', 'a{sa{sv}}', (settings,))) + if reply.header.message_type == MessageType.error: + cloudlog.warning(f'Failed to update tethering settings: {reply}') + return + + threading.Thread(target=worker, daemon=True).start() + + def _request_scan(self): + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + wifi_addr = DBusAddress(self._wifi_device, bus_name=NM, interface=NM_WIRELESS_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(wifi_addr, 'RequestScan', 'a{sv}', ({},))) + + if reply.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to request scan: {reply}") + + def _update_networks(self): + with self._lock: + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + # returns '/' if no active AP + wifi_addr = DBusAddress(self._wifi_device, NM, interface=NM_WIRELESS_IFACE) + active_ap_path = self._router_main.send_and_get_reply(Properties(wifi_addr).get('ActiveAccessPoint')).body[0][1] + ap_paths = self._router_main.send_and_get_reply(new_method_call(wifi_addr, 'GetAllAccessPoints')).body[0] + + aps: dict[str, list[AccessPoint]] = {} + + for ap_path in ap_paths: + ap_addr = DBusAddress(ap_path, NM, interface=NM_ACCESS_POINT_IFACE) + ap_props = self._router_main.send_and_get_reply(Properties(ap_addr).get_all()) + + # some APs have been seen dropping off during iteration + if ap_props.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to get AP properties for {ap_path}") + continue + + try: + ap = AccessPoint.from_dbus(ap_props.body[0], ap_path, active_ap_path) + if ap.ssid == "": + continue + + if ap.ssid not in aps: + aps[ap.ssid] = [] + + aps[ap.ssid].append(ap) + except Exception: + # catch all for parsing errors + cloudlog.exception(f"Failed to parse AP properties for {ap_path}") + + known_connections = self._get_connections() + networks = [Network.from_dbus(ssid, ap_list, ssid in known_connections) for ssid, ap_list in aps.items()] + networks.sort(key=lambda n: (-n.is_connected, -n.strength, n.ssid.lower())) + self._networks = networks + + self._update_ipv4_address() + self._update_current_network_metered() + + self._enqueue_callbacks(self._networks_updated, self._networks) + + def _update_ipv4_address(self): + if self._wifi_device is None: + cloudlog.warning("No WiFi device found") + return + + self._ipv4_address = "" + + for conn_path in self._get_active_connections(): + conn_addr = DBusAddress(conn_path, bus_name=NM, interface=NM_ACTIVE_CONNECTION_IFACE) + conn_type = self._router_main.send_and_get_reply(Properties(conn_addr).get('Type')).body[0][1] + if conn_type == '802-11-wireless': + ip4config_path = self._router_main.send_and_get_reply(Properties(conn_addr).get('Ip4Config')).body[0][1] + + if ip4config_path != "/": + ip4config_addr = DBusAddress(ip4config_path, bus_name=NM, interface=NM_IP4_CONFIG_IFACE) + address_data = self._router_main.send_and_get_reply(Properties(ip4config_addr).get('AddressData')).body[0][1] + + for entry in address_data: + if 'address' in entry: + self._ipv4_address = entry['address'][1] + return + + def __del__(self): + self.stop() + + def update_gsm_settings(self, roaming: bool, apn: str, metered: bool): + """Update GSM settings for cellular connection""" + + def worker(): + try: + lte_connection_path = self._get_lte_connection_path() + if not lte_connection_path: + cloudlog.warning("No LTE connection found") + return + + settings = self._get_connection_settings(lte_connection_path) + + if len(settings) == 0: + cloudlog.warning(f"Failed to get connection settings for {lte_connection_path}") + return + + # Ensure dicts exist + if 'gsm' not in settings: + settings['gsm'] = {} + if 'connection' not in settings: + settings['connection'] = {} + + changes = False + auto_config = apn == "" + + if settings['gsm'].get('auto-config', ('b', False))[1] != auto_config: + cloudlog.warning(f'Changing gsm.auto-config to {auto_config}') + settings['gsm']['auto-config'] = ('b', auto_config) + changes = True + + if settings['gsm'].get('apn', ('s', ''))[1] != apn: + cloudlog.warning(f'Changing gsm.apn to {apn}') + settings['gsm']['apn'] = ('s', apn) + changes = True + + if settings['gsm'].get('home-only', ('b', False))[1] == roaming: + cloudlog.warning(f'Changing gsm.home-only to {not roaming}') + settings['gsm']['home-only'] = ('b', not roaming) + changes = True + + # Unknown means NetworkManager decides + metered_int = int(MeteredType.UNKNOWN if metered else MeteredType.NO) + if settings['connection'].get('metered', ('i', 0))[1] != metered_int: + cloudlog.warning(f'Changing connection.metered to {metered_int}') + settings['connection']['metered'] = ('i', metered_int) + changes = True + + if changes: + # Update the connection settings (temporary update) + conn_addr = DBusAddress(lte_connection_path, bus_name=NM, interface=NM_CONNECTION_IFACE) + reply = self._router_main.send_and_get_reply(new_method_call(conn_addr, 'UpdateUnsaved', 'a{sa{sv}}', (settings,))) + + if reply.header.message_type == MessageType.error: + cloudlog.warning(f"Failed to update GSM settings: {reply}") + return + + self._activate_modem_connection(lte_connection_path) + except Exception as e: + cloudlog.exception(f"Error updating GSM settings: {e}") + + threading.Thread(target=worker, daemon=True).start() + + def _get_lte_connection_path(self) -> str | None: + try: + settings_addr = DBusAddress(NM_SETTINGS_PATH, bus_name=NM, interface=NM_SETTINGS_IFACE) + known_connections = self._router_main.send_and_get_reply(new_method_call(settings_addr, 'ListConnections')).body[0] + + for conn_path in known_connections: + settings = self._get_connection_settings(conn_path) + if settings and settings.get('connection', {}).get('id', ('s', ''))[1] == 'lte': + return str(conn_path) + except Exception as e: + cloudlog.exception(f"Error finding LTE connection: {e}") + return None + + def _activate_modem_connection(self, connection_path: str): + try: + modem_device = self._get_adapter(NM_DEVICE_TYPE_MODEM) + if modem_device and connection_path: + self._router_main.send_and_get_reply(new_method_call(self._nm, 'ActivateConnection', 'ooo', (connection_path, modem_device, "/"))) + except Exception as e: + cloudlog.exception(f"Error activating modem connection: {e}") + + def stop(self): + if not self._exit: + self._exit = True + self._scan_thread.join() + self._state_thread.join() + + self._router_main.close() + self._router_main.conn.close() + self._conn_monitor.close() diff --git a/system/ui/lib/wrap_text.py b/system/ui/lib/wrap_text.py new file mode 100644 index 0000000000..f6caa3c5f0 --- /dev/null +++ b/system/ui/lib/wrap_text.py @@ -0,0 +1,111 @@ +import pyray as rl +from openpilot.system.ui.lib.text_measure import measure_text_cached + + +def _break_long_word(font: rl.Font, word: str, font_size: int, max_width: int) -> list[str]: + if not word: + return [] + + parts = [] + remaining = word + + while remaining: + if measure_text_cached(font, remaining, font_size).x <= max_width: + parts.append(remaining) + break + + # Binary search for the longest substring that fits + left, right = 1, len(remaining) + best_fit = 1 + + while left <= right: + mid = (left + right) // 2 + substring = remaining[:mid] + width = measure_text_cached(font, substring, font_size).x + + if width <= max_width: + best_fit = mid + left = mid + 1 + else: + right = mid - 1 + + # Add the part that fits + parts.append(remaining[:best_fit]) + remaining = remaining[best_fit:] + + return parts + + +_cache: dict[int, list[str]] = {} + + +def wrap_text(font: rl.Font, text: str, font_size: int, max_width: int) -> list[str]: + key = hash((font.texture.id, text, font_size, max_width)) + if key in _cache: + return _cache[key] + + if not text or max_width <= 0: + return [] + + # Split text by newlines first to preserve explicit line breaks + paragraphs = text.split('\n') + all_lines: list[str] = [] + + for paragraph in paragraphs: + # Handle empty paragraphs (preserve empty lines) + if not paragraph.strip(): + all_lines.append("") + continue + + # Process each paragraph separately + words = paragraph.split() + if not words: + all_lines.append("") + continue + + lines: list[str] = [] + current_line: list[str] = [] + current_width = 0 + space_width = int(measure_text_cached(font, " ", font_size).x) + + for word in words: + word_width = int(measure_text_cached(font, word, font_size).x) + + # Check if word alone exceeds max width (need to break the word) + if word_width > max_width: + # Finish current line if it has content + if current_line: + lines.append(" ".join(current_line)) + current_line = [] + current_width = 0 + + # Break the long word into parts + lines.extend(_break_long_word(font, word, font_size, max_width)) + continue + + # Calculate width if we add this word + needed_width = current_width + if current_line: # Need space before word + needed_width += space_width + needed_width += word_width + + # Check if word fits on current line + if needed_width <= max_width: + current_line.append(word) + current_width = needed_width + else: + # Start new line with this word + if current_line: + lines.append(" ".join(current_line)) + current_line = [word] + current_width = word_width + + # Add remaining words + if current_line: + lines.append(" ".join(current_line)) + + # Add all lines from this paragraph + all_lines.extend(lines) + + _cache[key] = all_lines + return all_lines diff --git a/system/ui/reset.py b/system/ui/reset.py new file mode 100755 index 0000000000..a5cf1731dc --- /dev/null +++ b/system/ui/reset.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 +import os +import sys +import threading +import time +from enum import IntEnum + +import pyray as rl + +from openpilot.system.hardware import PC +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle +from openpilot.system.ui.widgets.label import gui_label, gui_text_box + +USERDATA = "/dev/disk/by-partlabel/userdata" +TIMEOUT = 3*60 + + +class ResetMode(IntEnum): + USER_RESET = 0 # user initiated a factory reset from openpilot + RECOVER = 1 # userdata is corrupt for some reason, give a chance to recover + FORMAT = 2 # finish up a factory reset from a tool that doesn't flash an empty partition to userdata + + +class ResetState(IntEnum): + NONE = 0 + CONFIRM = 1 + RESETTING = 2 + FAILED = 3 + + +class Reset(Widget): + def __init__(self, mode): + super().__init__() + self._mode = mode + self._previous_reset_state = None + self._reset_state = ResetState.NONE + self._cancel_button = Button("Cancel", self._cancel_callback) + self._confirm_button = Button("Confirm", self._confirm, button_style=ButtonStyle.PRIMARY) + self._reboot_button = Button("Reboot", lambda: os.system("sudo reboot")) + self._render_status = True + + def _cancel_callback(self): + self._render_status = False + + def _do_erase(self): + if PC: + return + + # Removing data and formatting + rm = os.system("sudo rm -rf /data/*") + os.system(f"sudo umount {USERDATA}") + fmt = os.system(f"yes | sudo mkfs.ext4 {USERDATA}") + + if rm == 0 or fmt == 0: + os.system("sudo reboot") + else: + self._reset_state = ResetState.FAILED + + def start_reset(self): + self._reset_state = ResetState.RESETTING + threading.Timer(0.1, self._do_erase).start() + + def _update_state(self): + if self._reset_state != self._previous_reset_state: + self._previous_reset_state = self._reset_state + self._timeout_st = time.monotonic() + elif self._reset_state != ResetState.RESETTING and (time.monotonic() - self._timeout_st) > TIMEOUT: + exit(0) + + def _render(self, rect: rl.Rectangle): + label_rect = rl.Rectangle(rect.x + 140, rect.y, rect.width - 280, 100) + gui_label(label_rect, "System Reset", 100, font_weight=FontWeight.BOLD) + + text_rect = rl.Rectangle(rect.x + 140, rect.y + 140, rect.width - 280, rect.height - 90 - 100) + gui_text_box(text_rect, self._get_body_text(), 90) + + button_height = 160 + button_spacing = 50 + button_top = rect.y + rect.height - button_height + button_width = (rect.width - button_spacing) / 2.0 + + if self._reset_state != ResetState.RESETTING: + if self._mode == ResetMode.RECOVER: + self._reboot_button.render(rl.Rectangle(rect.x, button_top, button_width, button_height)) + elif self._mode == ResetMode.USER_RESET: + self._cancel_button.render(rl.Rectangle(rect.x, button_top, button_width, button_height)) + + if self._reset_state != ResetState.FAILED: + self._confirm_button.render(rl.Rectangle(rect.x + button_width + 50, button_top, button_width, button_height)) + else: + self._reboot_button.render(rl.Rectangle(rect.x, button_top, rect.width, button_height)) + + return self._render_status + + def _confirm(self): + if self._reset_state == ResetState.CONFIRM: + self.start_reset() + else: + self._reset_state = ResetState.CONFIRM + + def _get_body_text(self): + if self._reset_state == ResetState.CONFIRM: + return "Are you sure you want to reset your device?" + if self._reset_state == ResetState.RESETTING: + return "Resetting device...\nThis may take up to a minute." + if self._reset_state == ResetState.FAILED: + return "Reset failed. Reboot to try again." + if self._mode == ResetMode.RECOVER: + return "Unable to mount data partition. Partition may be corrupted. Press confirm to erase and reset your device." + return "System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot." + + +def main(): + mode = ResetMode.USER_RESET + if len(sys.argv) > 1: + if sys.argv[1] == '--recover': + mode = ResetMode.RECOVER + elif sys.argv[1] == "--format": + mode = ResetMode.FORMAT + + gui_app.init_window("System Reset", 20) + reset = Reset(mode) + + if mode == ResetMode.FORMAT: + reset.start_reset() + + for _ in gui_app.render(): + if not reset.render(rl.Rectangle(45, 200, gui_app.width - 90, gui_app.height - 245)): + break + + +if __name__ == "__main__": + main() diff --git a/system/ui/setup.py b/system/ui/setup.py new file mode 100755 index 0000000000..e0d737cb1c --- /dev/null +++ b/system/ui/setup.py @@ -0,0 +1,436 @@ +#!/usr/bin/env python3 +import os +import re +import threading +import time +import urllib.request +from urllib.parse import urlparse +from enum import IntEnum +import shutil + +import pyray as rl + +from cereal import log +from openpilot.common.run import run_cmd +from openpilot.system.hardware import HARDWARE +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle, ButtonRadio +from openpilot.system.ui.widgets.keyboard import Keyboard +from openpilot.system.ui.widgets.label import Label, TextAlignment +from openpilot.system.ui.widgets.network import WifiManagerUI, WifiManager + +NetworkType = log.DeviceState.NetworkType + +MARGIN = 50 +TITLE_FONT_SIZE = 116 +TITLE_FONT_WEIGHT = FontWeight.MEDIUM +NEXT_BUTTON_WIDTH = 310 +BODY_FONT_SIZE = 96 +BUTTON_HEIGHT = 160 +BUTTON_SPACING = 50 + +OPENPILOT_URL = "https://openpilot.comma.ai" +USER_AGENT = f"AGNOSSetup-{HARDWARE.get_os_version()}" + +CONTINUE_PATH = "/data/continue.sh" +TMP_CONTINUE_PATH = "/data/continue.sh.new" +INSTALL_PATH = "/data/openpilot" +VALID_CACHE_PATH = "/data/.openpilot_cache" +INSTALLER_SOURCE_PATH = "/usr/comma/installer" +INSTALLER_DESTINATION_PATH = "/tmp/installer" +INSTALLER_URL_PATH = "/tmp/installer_url" + +CONTINUE = """#!/usr/bin/env bash + +cd /data/openpilot +exec ./launch_openpilot.sh +""" + +class SetupState(IntEnum): + LOW_VOLTAGE = 0 + GETTING_STARTED = 1 + NETWORK_SETUP = 2 + SOFTWARE_SELECTION = 3 + CUSTOM_SOFTWARE = 4 + DOWNLOADING = 5 + DOWNLOAD_FAILED = 6 + CUSTOM_SOFTWARE_WARNING = 7 + + +class Setup(Widget): + def __init__(self): + super().__init__() + self.state = SetupState.GETTING_STARTED + self.network_check_thread = None + self.network_connected = threading.Event() + self.wifi_connected = threading.Event() + self.stop_network_check_thread = threading.Event() + self.failed_url = "" + self.failed_reason = "" + self.download_url = "" + self.download_progress = 0 + self.download_thread = None + self.wifi_ui = WifiManagerUI(WifiManager()) + self.keyboard = Keyboard() + self.selected_radio = None + self.warning = gui_app.texture("icons/warning.png", 150, 150) + self.checkmark = gui_app.texture("icons/circled_check.png", 100, 100) + + self._low_voltage_title_label = Label("WARNING: Low Voltage", TITLE_FONT_SIZE, FontWeight.MEDIUM, TextAlignment.LEFT, text_color=rl.Color(255, 89, 79, 255)) + self._low_voltage_body_label = Label("Power your device in a car with a harness or proceed at your own risk.", BODY_FONT_SIZE, + text_alignment=TextAlignment.LEFT) + self._low_voltage_continue_button = Button("Continue", self._low_voltage_continue_button_callback) + self._low_voltage_poweroff_button = Button("Power Off", HARDWARE.shutdown) + + self._getting_started_button = Button("", self._getting_started_button_callback, button_style=ButtonStyle.PRIMARY, border_radius=0) + self._getting_started_title_label = Label("Getting Started", TITLE_FONT_SIZE, FontWeight.BOLD, TextAlignment.LEFT) + self._getting_started_body_label = Label("Before we get on the road, let's finish installation and cover some details.", + BODY_FONT_SIZE, text_alignment=TextAlignment.LEFT) + + self._software_selection_openpilot_button = ButtonRadio("openpilot", self.checkmark, font_size=BODY_FONT_SIZE, text_padding=80) + self._software_selection_custom_software_button = ButtonRadio("Custom Software", self.checkmark, font_size=BODY_FONT_SIZE, text_padding=80) + self._software_selection_continue_button = Button("Continue", self._software_selection_continue_button_callback, + button_style=ButtonStyle.PRIMARY) + self._software_selection_continue_button.set_enabled(False) + self._software_selection_back_button = Button("Back", self._software_selection_back_button_callback) + self._software_selection_title_label = Label("Choose Software to Use", TITLE_FONT_SIZE, FontWeight.BOLD, TextAlignment.LEFT) + + self._download_failed_reboot_button = Button("Reboot device", HARDWARE.reboot) + self._download_failed_startover_button = Button("Start over", self._download_failed_startover_button_callback, button_style=ButtonStyle.PRIMARY) + self._download_failed_title_label = Label("Download Failed", TITLE_FONT_SIZE, FontWeight.BOLD, TextAlignment.LEFT) + self._download_failed_url_label = Label("", 64, FontWeight.NORMAL, TextAlignment.LEFT) + self._download_failed_body_label = Label("", BODY_FONT_SIZE, text_alignment=TextAlignment.LEFT) + + self._network_setup_back_button = Button("Back", self._network_setup_back_button_callback) + self._network_setup_continue_button = Button("Waiting for internet", self._network_setup_continue_button_callback, + button_style=ButtonStyle.PRIMARY) + self._network_setup_continue_button.set_enabled(False) + self._network_setup_title_label = Label("Connect to Wi-Fi", TITLE_FONT_SIZE, FontWeight.BOLD, TextAlignment.LEFT) + + self._custom_software_warning_continue_button = Button("Scroll to continue", self._custom_software_warning_continue_button_callback, + button_style=ButtonStyle.PRIMARY) + self._custom_software_warning_continue_button.set_enabled(False) + self._custom_software_warning_back_button = Button("Back", self._custom_software_warning_back_button_callback) + self._custom_software_warning_title_label = Label("WARNING: Custom Software", 100, FontWeight.BOLD, TextAlignment.LEFT, text_color=rl.Color(255,89,79,255), + text_padding=60) + self._custom_software_warning_body_label = Label("Use caution when installing third-party software.\n\n" + + "⚠️ It has not been tested by comma.\n\n" + + "⚠️ It may not comply with relevant safety standards.\n\n" + + "⚠️ It may cause damage to your device and/or vehicle.\n\n" + + "If you'd like to proceed, use https://flash.comma.ai " + + "to restore your device to a factory state later.", + 85, text_alignment=TextAlignment.LEFT, text_padding=60) + self._custom_software_warning_body_scroll_panel = GuiScrollPanel() + + self._downloading_body_label = Label("Downloading...", TITLE_FONT_SIZE, FontWeight.MEDIUM) + + try: + with open("/sys/class/hwmon/hwmon1/in1_input") as f: + voltage = float(f.read().strip()) / 1000.0 + if voltage < 7: + self.state = SetupState.LOW_VOLTAGE + except (FileNotFoundError, ValueError): + self.state = SetupState.LOW_VOLTAGE + + def _render(self, rect: rl.Rectangle): + if self.state == SetupState.LOW_VOLTAGE: + self.render_low_voltage(rect) + elif self.state == SetupState.GETTING_STARTED: + self.render_getting_started(rect) + elif self.state == SetupState.NETWORK_SETUP: + self.render_network_setup(rect) + elif self.state == SetupState.SOFTWARE_SELECTION: + self.render_software_selection(rect) + elif self.state == SetupState.CUSTOM_SOFTWARE_WARNING: + self.render_custom_software_warning(rect) + elif self.state == SetupState.CUSTOM_SOFTWARE: + self.render_custom_software() + elif self.state == SetupState.DOWNLOADING: + self.render_downloading(rect) + elif self.state == SetupState.DOWNLOAD_FAILED: + self.render_download_failed(rect) + + def _low_voltage_continue_button_callback(self): + self.state = SetupState.GETTING_STARTED + + def _custom_software_warning_back_button_callback(self): + self.state = SetupState.SOFTWARE_SELECTION + + def _custom_software_warning_continue_button_callback(self): + self.state = SetupState.NETWORK_SETUP + self.stop_network_check_thread.clear() + self.start_network_check() + + def _getting_started_button_callback(self): + self.state = SetupState.SOFTWARE_SELECTION + + def _software_selection_back_button_callback(self): + self.state = SetupState.GETTING_STARTED + + def _software_selection_continue_button_callback(self): + if self._software_selection_openpilot_button.selected: + self.use_openpilot() + else: + self.state = SetupState.CUSTOM_SOFTWARE_WARNING + + def _download_failed_startover_button_callback(self): + self.state = SetupState.GETTING_STARTED + + def _network_setup_back_button_callback(self): + self.state = SetupState.SOFTWARE_SELECTION + + def _network_setup_continue_button_callback(self): + self.stop_network_check_thread.set() + if self._software_selection_openpilot_button.selected: + self.download(OPENPILOT_URL) + else: + self.state = SetupState.CUSTOM_SOFTWARE + + def render_low_voltage(self, rect: rl.Rectangle): + rl.draw_texture(self.warning, int(rect.x + 150), int(rect.y + 110), rl.WHITE) + + self._low_voltage_title_label.render(rl.Rectangle(rect.x + 150, rect.y + 110 + 150 + 100, rect.width - 500 - 150, TITLE_FONT_SIZE)) + self._low_voltage_body_label.render(rl.Rectangle(rect.x + 150, rect.y + 110 + 150 + 150, rect.width - 500, BODY_FONT_SIZE * 3)) + + button_width = (rect.width - MARGIN * 3) / 2 + button_y = rect.height - MARGIN - BUTTON_HEIGHT + self._low_voltage_poweroff_button.render(rl.Rectangle(rect.x + MARGIN, button_y, button_width, BUTTON_HEIGHT)) + self._low_voltage_continue_button.render(rl.Rectangle(rect.x + MARGIN * 2 + button_width, button_y, button_width, BUTTON_HEIGHT)) + + def render_getting_started(self, rect: rl.Rectangle): + self._getting_started_title_label.render(rl.Rectangle(rect.x + 165, rect.y + 280, rect.width - 265, TITLE_FONT_SIZE)) + self._getting_started_body_label.render(rl.Rectangle(rect.x + 165, rect.y + 280 + TITLE_FONT_SIZE, rect.width - 500, BODY_FONT_SIZE * 3)) + + btn_rect = rl.Rectangle(rect.width - NEXT_BUTTON_WIDTH, 0, NEXT_BUTTON_WIDTH, rect.height) + self._getting_started_button.render(btn_rect) + triangle = gui_app.texture("images/button_continue_triangle.png", 54, int(btn_rect.height)) + rl.draw_texture_v(triangle, rl.Vector2(btn_rect.x + btn_rect.width / 2 - triangle.width / 2, btn_rect.height / 2 - triangle.height / 2), rl.WHITE) + + def check_network_connectivity(self): + while not self.stop_network_check_thread.is_set(): + if self.state == SetupState.NETWORK_SETUP: + try: + urllib.request.urlopen(OPENPILOT_URL, timeout=2) + self.network_connected.set() + if HARDWARE.get_network_type() == NetworkType.wifi: + self.wifi_connected.set() + else: + self.wifi_connected.clear() + except Exception: + self.network_connected.clear() + time.sleep(1) + + def start_network_check(self): + if self.network_check_thread is None or not self.network_check_thread.is_alive(): + self.network_check_thread = threading.Thread(target=self.check_network_connectivity, daemon=True) + self.network_check_thread.start() + + def close(self): + if self.network_check_thread is not None: + self.stop_network_check_thread.set() + self.network_check_thread.join() + + def render_network_setup(self, rect: rl.Rectangle): + self._network_setup_title_label.render(rl.Rectangle(rect.x + MARGIN, rect.y + MARGIN, rect.width - MARGIN * 2, TITLE_FONT_SIZE)) + + wifi_rect = rl.Rectangle(rect.x + MARGIN, rect.y + TITLE_FONT_SIZE + MARGIN + 25, rect.width - MARGIN * 2, + rect.height - TITLE_FONT_SIZE - 25 - BUTTON_HEIGHT - MARGIN * 3) + rl.draw_rectangle_rounded(wifi_rect, 0.05, 10, rl.Color(51, 51, 51, 255)) + wifi_content_rect = rl.Rectangle(wifi_rect.x + MARGIN, wifi_rect.y, wifi_rect.width - MARGIN * 2, wifi_rect.height) + self.wifi_ui.render(wifi_content_rect) + + button_width = (rect.width - BUTTON_SPACING - MARGIN * 2) / 2 + button_y = rect.height - BUTTON_HEIGHT - MARGIN + + self._network_setup_back_button.render(rl.Rectangle(rect.x + MARGIN, button_y, button_width, BUTTON_HEIGHT)) + + # Check network connectivity status + continue_enabled = self.network_connected.is_set() + self._network_setup_continue_button.set_enabled(continue_enabled) + continue_text = ("Continue" if self.wifi_connected.is_set() else "Continue without Wi-Fi") if continue_enabled else "Waiting for internet" + self._network_setup_continue_button.set_text(continue_text) + self._network_setup_continue_button.render(rl.Rectangle(rect.x + MARGIN + button_width + BUTTON_SPACING, button_y, button_width, BUTTON_HEIGHT)) + + def render_software_selection(self, rect: rl.Rectangle): + self._software_selection_title_label.render(rl.Rectangle(rect.x + MARGIN, rect.y + MARGIN, rect.width - MARGIN * 2, TITLE_FONT_SIZE)) + + radio_height = 230 + radio_spacing = 30 + + self._software_selection_continue_button.set_enabled(False) + + openpilot_rect = rl.Rectangle(rect.x + MARGIN, rect.y + TITLE_FONT_SIZE + MARGIN * 2, rect.width - MARGIN * 2, radio_height) + self._software_selection_openpilot_button.render(openpilot_rect) + + if self._software_selection_openpilot_button.selected: + self._software_selection_continue_button.set_enabled(True) + self._software_selection_custom_software_button.selected = False + + custom_rect = rl.Rectangle(rect.x + MARGIN, rect.y + TITLE_FONT_SIZE + MARGIN * 2 + radio_height + radio_spacing, rect.width - MARGIN * 2, radio_height) + self._software_selection_custom_software_button.render(custom_rect) + + if self._software_selection_custom_software_button.selected: + self._software_selection_continue_button.set_enabled(True) + self._software_selection_openpilot_button.selected = False + + button_width = (rect.width - BUTTON_SPACING - MARGIN * 2) / 2 + button_y = rect.height - BUTTON_HEIGHT - MARGIN + + self._software_selection_back_button.render(rl.Rectangle(rect.x + MARGIN, button_y, button_width, BUTTON_HEIGHT)) + self._software_selection_continue_button.render(rl.Rectangle(rect.x + MARGIN + button_width + BUTTON_SPACING, button_y, button_width, BUTTON_HEIGHT)) + + def render_downloading(self, rect: rl.Rectangle): + self._downloading_body_label.render(rl.Rectangle(rect.x, rect.y + rect.height / 2 - TITLE_FONT_SIZE / 2, rect.width, TITLE_FONT_SIZE)) + + def render_download_failed(self, rect: rl.Rectangle): + self._download_failed_title_label.render(rl.Rectangle(rect.x + 117, rect.y + 185, rect.width - 117, TITLE_FONT_SIZE)) + self._download_failed_url_label.set_text(self.failed_url) + self._download_failed_url_label.render(rl.Rectangle(rect.x + 117, rect.y + 185 + TITLE_FONT_SIZE + 67, rect.width - 117 - 100, 64)) + + self._download_failed_body_label.set_text(self.failed_reason) + self._download_failed_body_label.render(rl.Rectangle(rect.x + 117, rect.y, rect.width - 117 - 100, rect.height)) + + button_width = (rect.width - BUTTON_SPACING - MARGIN * 2) / 2 + button_y = rect.height - BUTTON_HEIGHT - MARGIN + self._download_failed_reboot_button.render(rl.Rectangle(rect.x + MARGIN, button_y, button_width, BUTTON_HEIGHT)) + self._download_failed_startover_button.render(rl.Rectangle(rect.x + MARGIN + button_width + BUTTON_SPACING, button_y, button_width, BUTTON_HEIGHT)) + + def render_custom_software_warning(self, rect: rl.Rectangle): + warn_rect = rl.Rectangle(rect.x, rect.y, rect.width, 1500) + offset = self._custom_software_warning_body_scroll_panel.update(rect, warn_rect) + + button_width = (rect.width - MARGIN * 3) / 2 + button_y = rect.height - MARGIN - BUTTON_HEIGHT + + rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(button_y - BODY_FONT_SIZE)) + y_offset = rect.y + offset + self._custom_software_warning_title_label.render(rl.Rectangle(rect.x + 50, y_offset + 150, rect.width - 265, TITLE_FONT_SIZE)) + self._custom_software_warning_body_label.render(rl.Rectangle(rect.x + 50, y_offset + 200 , rect.width - 50, BODY_FONT_SIZE * 3)) + rl.end_scissor_mode() + + self._custom_software_warning_back_button.render(rl.Rectangle(rect.x + MARGIN, button_y, button_width, BUTTON_HEIGHT)) + self._custom_software_warning_continue_button.render(rl.Rectangle(rect.x + MARGIN * 2 + button_width, button_y, button_width, BUTTON_HEIGHT)) + if offset < (rect.height - warn_rect.height): + self._custom_software_warning_continue_button.set_enabled(True) + self._custom_software_warning_continue_button.set_text("Continue") + + def render_custom_software(self): + def handle_keyboard_result(result): + # Enter pressed + if result == 1: + url = self.keyboard.text + self.keyboard.clear() + if url: + self.download(url) + + # Cancel pressed + elif result == 0: + self.state = SetupState.SOFTWARE_SELECTION + + self.keyboard.reset() + self.keyboard.set_title("Enter URL", "for Custom Software") + gui_app.set_modal_overlay(self.keyboard, callback=handle_keyboard_result) + + def use_openpilot(self): + if os.path.isdir(INSTALL_PATH) and os.path.isfile(VALID_CACHE_PATH): + os.remove(VALID_CACHE_PATH) + with open(TMP_CONTINUE_PATH, "w") as f: + f.write(CONTINUE) + run_cmd(["chmod", "+x", TMP_CONTINUE_PATH]) + shutil.move(TMP_CONTINUE_PATH, CONTINUE_PATH) + shutil.copyfile(INSTALLER_SOURCE_PATH, INSTALLER_DESTINATION_PATH) + + # give time for installer UI to take over + time.sleep(1) + gui_app.request_close() + else: + self.state = SetupState.NETWORK_SETUP + self.stop_network_check_thread.clear() + self.start_network_check() + + def download(self, url: str): + # autocomplete incomplete URLs + if re.match("^([^/.]+)/([^/]+)$", url): + url = f"https://installer.comma.ai/{url}" + + parsed = urlparse(url, scheme='https') + self.download_url = (urlparse(f"https://{url}") if not parsed.netloc else parsed).geturl() + + self.state = SetupState.DOWNLOADING + + self.download_thread = threading.Thread(target=self._download_thread, daemon=True) + self.download_thread.start() + + def _download_thread(self): + try: + import tempfile + + fd, tmpfile = tempfile.mkstemp(prefix="installer_") + + headers = {"User-Agent": USER_AGENT, "X-openpilot-serial": HARDWARE.get_serial()} + req = urllib.request.Request(self.download_url, headers=headers) + + with open(tmpfile, 'wb') as f, urllib.request.urlopen(req, timeout=30) as response: + total_size = int(response.headers.get('content-length', 0)) + downloaded = 0 + block_size = 8192 + + while True: + buffer = response.read(block_size) + if not buffer: + break + + downloaded += len(buffer) + f.write(buffer) + + if total_size: + self.download_progress = int(downloaded * 100 / total_size) + + is_elf = False + with open(tmpfile, 'rb') as f: + header = f.read(4) + is_elf = header == b'\x7fELF' + + if not is_elf: + self.download_failed(self.download_url, "No custom software found at this URL.") + return + + # AGNOS might try to execute the installer before this process exits. + # Therefore, important to close the fd before renaming the installer. + os.close(fd) + os.rename(tmpfile, INSTALLER_DESTINATION_PATH) + + with open(INSTALLER_URL_PATH, "w") as f: + f.write(self.download_url) + + # give time for installer UI to take over + time.sleep(5) + gui_app.request_close() + + except Exception: + error_msg = "Ensure the entered URL is valid, and the device's internet connection is good." + self.download_failed(self.download_url, error_msg) + + def download_failed(self, url: str, reason: str): + self.failed_url = url + self.failed_reason = reason + self.state = SetupState.DOWNLOAD_FAILED + + +def main(): + try: + gui_app.init_window("Setup", 20) + setup = Setup() + for _ in gui_app.render(): + setup.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + setup.close() + except Exception as e: + print(f"Setup error: {e}") + finally: + gui_app.close() + + +if __name__ == "__main__": + main() diff --git a/system/ui/spinner.py b/system/ui/spinner.py new file mode 100755 index 0000000000..eb33f08349 --- /dev/null +++ b/system/ui/spinner.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +import pyray as rl +import select +import sys + +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.text import wrap_text +from openpilot.system.ui.widgets import Widget + +# Constants +PROGRESS_BAR_WIDTH = 1000 +PROGRESS_BAR_HEIGHT = 20 +DEGREES_PER_SECOND = 360.0 # one full rotation per second +MARGIN_H = 100 +TEXTURE_SIZE = 360 +FONT_SIZE = 96 +LINE_HEIGHT = 104 +DARKGRAY = (55, 55, 55, 255) + + +def clamp(value, min_value, max_value): + return max(min(value, max_value), min_value) + + +class Spinner(Widget): + def __init__(self): + super().__init__() + self._comma_texture = gui_app.texture("images/spinner_comma.png", TEXTURE_SIZE, TEXTURE_SIZE) + self._spinner_texture = gui_app.texture("images/spinner_track.png", TEXTURE_SIZE, TEXTURE_SIZE, alpha_premultiply=True) + self._rotation = 0.0 + self._progress: int | None = None + self._wrapped_lines: list[str] = [] + + def set_text(self, text: str) -> None: + if text.isdigit(): + self._progress = clamp(int(text), 0, 100) + self._wrapped_lines = [] + else: + self._progress = None + self._wrapped_lines = wrap_text(text, FONT_SIZE, gui_app.width - MARGIN_H) + + def _render(self, rect: rl.Rectangle): + if self._wrapped_lines: + # Calculate total height required for spinner and text + spacing = 50 + total_height = TEXTURE_SIZE + spacing + len(self._wrapped_lines) * LINE_HEIGHT + center_y = (rect.height - total_height) / 2.0 + TEXTURE_SIZE / 2.0 + else: + # Center spinner vertically + spacing = 150 + center_y = rect.height / 2.0 + y_pos = center_y + TEXTURE_SIZE / 2.0 + spacing + + center = rl.Vector2(rect.width / 2.0, center_y) + spinner_origin = rl.Vector2(TEXTURE_SIZE / 2.0, TEXTURE_SIZE / 2.0) + comma_position = rl.Vector2(center.x - TEXTURE_SIZE / 2.0, center.y - TEXTURE_SIZE / 2.0) + + delta_time = rl.get_frame_time() + self._rotation = (self._rotation + DEGREES_PER_SECOND * delta_time) % 360.0 + + # Draw rotating spinner and static comma logo + rl.draw_texture_pro(self._spinner_texture, rl.Rectangle(0, 0, TEXTURE_SIZE, TEXTURE_SIZE), + rl.Rectangle(center.x, center.y, TEXTURE_SIZE, TEXTURE_SIZE), + spinner_origin, self._rotation, rl.WHITE) + rl.draw_texture_v(self._comma_texture, comma_position, rl.WHITE) + + # Display the progress bar or text based on user input + if self._progress is not None: + bar = rl.Rectangle(center.x - PROGRESS_BAR_WIDTH / 2.0, y_pos, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT) + rl.draw_rectangle_rounded(bar, 1, 10, DARKGRAY) + + bar.width *= self._progress / 100.0 + rl.draw_rectangle_rounded(bar, 1, 10, rl.WHITE) + elif self._wrapped_lines: + for i, line in enumerate(self._wrapped_lines): + text_size = measure_text_cached(gui_app.font(), line, FONT_SIZE) + rl.draw_text_ex(gui_app.font(), line, rl.Vector2(center.x - text_size.x / 2, y_pos + i * LINE_HEIGHT), + FONT_SIZE, 0.0, rl.WHITE) + + +def _read_stdin(): + """Non-blocking read of available lines from stdin.""" + lines = [] + while True: + rlist, _, _ = select.select([sys.stdin], [], [], 0.0) + if not rlist: + break + line = sys.stdin.readline().strip() + if line == "": + break + lines.append(line) + return lines + + +def main(): + gui_app.init_window("Spinner") + spinner = Spinner() + for _ in gui_app.render(): + text_list = _read_stdin() + if text_list: + spinner.set_text(text_list[-1]) + + spinner.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + + +if __name__ == "__main__": + main() diff --git a/system/ui/text.py b/system/ui/text.py new file mode 100755 index 0000000000..707b30983b --- /dev/null +++ b/system/ui/text.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +import re +import sys +import pyray as rl +from openpilot.system.hardware import HARDWARE, PC +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle + +MARGIN = 50 +SPACING = 40 +FONT_SIZE = 72 +LINE_HEIGHT = 80 +BUTTON_SIZE = rl.Vector2(310, 160) + +DEMO_TEXT = """This is a sample text that will be wrapped and scrolled if necessary. + The text is long enough to demonstrate scrolling and word wrapping.""" * 30 + + +def wrap_text(text, font_size, max_width): + lines = [] + font = gui_app.font() + + for paragraph in text.split("\n"): + if not paragraph.strip(): + # Don't add empty lines first, ensuring wrap_text("") returns [] + if lines: + lines.append("") + continue + indent = re.match(r"^\s*", paragraph).group() + current_line = indent + words = re.split(r"(\s+)", paragraph[len(indent):]) + while len(words): + word = words.pop(0) + test_line = current_line + word + (words.pop(0) if words else "") + if measure_text_cached(font, test_line, font_size).x <= max_width: + current_line = test_line + else: + lines.append(current_line) + current_line = word + " " + current_line = current_line.rstrip() + if current_line: + lines.append(current_line) + + return lines + + +class TextWindow(Widget): + def __init__(self, text: str): + super().__init__() + self._textarea_rect = rl.Rectangle(MARGIN, MARGIN, gui_app.width - MARGIN * 2, gui_app.height - MARGIN * 2) + self._wrapped_lines = wrap_text(text, FONT_SIZE, self._textarea_rect.width - 20) + self._content_rect = rl.Rectangle(0, 0, self._textarea_rect.width - 20, len(self._wrapped_lines) * LINE_HEIGHT) + self._scroll_panel = GuiScrollPanel() + self._scroll_panel._offset_filter_y.x = -max(self._content_rect.height - self._textarea_rect.height, 0) + + button_text = "Exit" if PC else "Reboot" + self._button = Button(button_text, click_callback=self._on_button_clicked, button_style=ButtonStyle.TRANSPARENT_WHITE_BORDER) + + @staticmethod + def _on_button_clicked(): + gui_app.request_close() + if not PC: + HARDWARE.reboot() + + def _render(self, rect: rl.Rectangle): + scroll = self._scroll_panel.update(self._textarea_rect, self._content_rect) + rl.begin_scissor_mode(int(self._textarea_rect.x), int(self._textarea_rect.y), int(self._textarea_rect.width), int(self._textarea_rect.height)) + for i, line in enumerate(self._wrapped_lines): + position = rl.Vector2(self._textarea_rect.x, self._textarea_rect.y + scroll + i * LINE_HEIGHT) + if position.y + LINE_HEIGHT < self._textarea_rect.y or position.y > self._textarea_rect.y + self._textarea_rect.height: + continue + rl.draw_text_ex(gui_app.font(), line, position, FONT_SIZE, 0, rl.WHITE) + rl.end_scissor_mode() + + button_bounds = rl.Rectangle(rect.width - MARGIN - BUTTON_SIZE.x - SPACING, rect.height - MARGIN - BUTTON_SIZE.y, BUTTON_SIZE.x, BUTTON_SIZE.y) + self._button.render(button_bounds) + + +if __name__ == "__main__": + text = sys.argv[1] if len(sys.argv) > 1 else DEMO_TEXT + gui_app.init_window("Text Viewer") + text_window = TextWindow(text) + for _ in gui_app.render(): + text_window.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) diff --git a/system/ui/updater.py b/system/ui/updater.py new file mode 100755 index 0000000000..48903fa5bd --- /dev/null +++ b/system/ui/updater.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 +import sys +import subprocess +import threading +import pyray as rl +from enum import IntEnum + +from openpilot.system.hardware import HARDWARE +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.lib.wifi_manager import WifiManager +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle +from openpilot.system.ui.widgets.label import gui_text_box, gui_label +from openpilot.system.ui.widgets.network import WifiManagerUI + +# Constants +MARGIN = 50 +BUTTON_HEIGHT = 160 +BUTTON_WIDTH = 400 +PROGRESS_BAR_HEIGHT = 72 +TITLE_FONT_SIZE = 80 +BODY_FONT_SIZE = 65 +BACKGROUND_COLOR = rl.BLACK +PROGRESS_BG_COLOR = rl.Color(41, 41, 41, 255) +PROGRESS_COLOR = rl.Color(54, 77, 239, 255) + + +class Screen(IntEnum): + PROMPT = 0 + WIFI = 1 + PROGRESS = 2 + + +class Updater(Widget): + def __init__(self, updater_path, manifest_path): + super().__init__() + self.updater = updater_path + self.manifest = manifest_path + self.current_screen = Screen.PROMPT + + self.progress_value = 0 + self.progress_text = "Loading..." + self.show_reboot_button = False + self.process = None + self.update_thread = None + self.wifi_manager_ui = WifiManagerUI(WifiManager()) + + # Buttons + self._wifi_button = Button("Connect to Wi-Fi", click_callback=lambda: self.set_current_screen(Screen.WIFI)) + self._install_button = Button("Install", click_callback=self.install_update, button_style=ButtonStyle.PRIMARY) + self._back_button = Button("Back", click_callback=lambda: self.set_current_screen(Screen.PROMPT)) + self._reboot_button = Button("Reboot", click_callback=lambda: HARDWARE.reboot()) + + def set_current_screen(self, screen: Screen): + self.current_screen = screen + + def install_update(self): + self.set_current_screen(Screen.PROGRESS) + self.progress_value = 0 + self.progress_text = "Downloading..." + self.show_reboot_button = False + + # Start the update process in a separate thread + self.update_thread = threading.Thread(target=self._run_update_process) + self.update_thread.daemon = True + self.update_thread.start() + + def _run_update_process(self): + # TODO: just import it and run in a thread without a subprocess + cmd = [self.updater, "--swap", self.manifest] + self.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + text=True, bufsize=1, universal_newlines=True) + + for line in self.process.stdout: + parts = line.strip().split(":") + if len(parts) == 2: + self.progress_text = parts[0] + try: + self.progress_value = int(float(parts[1])) + except ValueError: + pass + + exit_code = self.process.wait() + if exit_code == 0: + HARDWARE.reboot() + else: + self.progress_text = "Update failed" + self.show_reboot_button = True + + def render_prompt_screen(self, rect: rl.Rectangle): + # Title + title_rect = rl.Rectangle(MARGIN + 50, 250, rect.width - MARGIN * 2 - 100, TITLE_FONT_SIZE) + gui_label(title_rect, "Update Required", TITLE_FONT_SIZE, font_weight=FontWeight.BOLD) + + # Description + desc_text = ("An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. " + + "The download size is approximately 1GB.") + + desc_rect = rl.Rectangle(MARGIN + 50, 250 + TITLE_FONT_SIZE + 75, rect.width - MARGIN * 2 - 100, BODY_FONT_SIZE * 3) + gui_text_box(desc_rect, desc_text, BODY_FONT_SIZE) + + # Buttons at the bottom + button_y = rect.height - MARGIN - BUTTON_HEIGHT + button_width = (rect.width - MARGIN * 3) // 2 + + # WiFi button + wifi_button_rect = rl.Rectangle(MARGIN, button_y, button_width, BUTTON_HEIGHT) + self._wifi_button.render(wifi_button_rect) + + # Install button + install_button_rect = rl.Rectangle(MARGIN * 2 + button_width, button_y, button_width, BUTTON_HEIGHT) + self._install_button.render(install_button_rect) + + def render_wifi_screen(self, rect: rl.Rectangle): + # Draw the Wi-Fi manager UI + wifi_rect = rl.Rectangle(MARGIN + 50, MARGIN, rect.width - MARGIN * 2 - 100, rect.height - MARGIN * 2 - BUTTON_HEIGHT - 20) + self.wifi_manager_ui.render(wifi_rect) + + back_button_rect = rl.Rectangle(MARGIN, rect.height - MARGIN - BUTTON_HEIGHT, BUTTON_WIDTH, BUTTON_HEIGHT) + self._back_button.render(back_button_rect) + + def render_progress_screen(self, rect: rl.Rectangle): + title_rect = rl.Rectangle(MARGIN + 100, 330, rect.width - MARGIN * 2 - 200, 100) + gui_label(title_rect, self.progress_text, 90, font_weight=FontWeight.SEMI_BOLD) + + # Progress bar + bar_rect = rl.Rectangle(MARGIN + 100, 330 + 100 + 100, rect.width - MARGIN * 2 - 200, PROGRESS_BAR_HEIGHT) + rl.draw_rectangle_rounded(bar_rect, 0.5, 10, PROGRESS_BG_COLOR) + + # Calculate the width of the progress chunk + progress_width = (bar_rect.width * self.progress_value) / 100 + if progress_width > 0: + progress_rect = rl.Rectangle(bar_rect.x, bar_rect.y, progress_width, bar_rect.height) + rl.draw_rectangle_rounded(progress_rect, 0.5, 10, PROGRESS_COLOR) + + # Show reboot button if needed + if self.show_reboot_button: + reboot_rect = rl.Rectangle(MARGIN + 100, rect.height - MARGIN - BUTTON_HEIGHT, BUTTON_WIDTH, BUTTON_HEIGHT) + self._reboot_button.render(reboot_rect) + + def _render(self, rect: rl.Rectangle): + if self.current_screen == Screen.PROMPT: + self.render_prompt_screen(rect) + elif self.current_screen == Screen.WIFI: + self.render_wifi_screen(rect) + elif self.current_screen == Screen.PROGRESS: + self.render_progress_screen(rect) + + +def main(): + if len(sys.argv) < 3: + print("Usage: updater.py ") + sys.exit(1) + + updater_path = sys.argv[1] + manifest_path = sys.argv[2] + + try: + gui_app.init_window("System Update") + updater = Updater(updater_path, manifest_path) + for _ in gui_app.render(): + updater.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + finally: + # Make sure we clean up even if there's an error + gui_app.close() + + +if __name__ == "__main__": + main() diff --git a/system/ui/widgets/__init__.py b/system/ui/widgets/__init__.py new file mode 100644 index 0000000000..0157dd3ef4 --- /dev/null +++ b/system/ui/widgets/__init__.py @@ -0,0 +1,150 @@ +import abc +import pyray as rl +from enum import IntEnum +from collections.abc import Callable +from openpilot.system.ui.lib.application import gui_app, MousePos, MAX_TOUCH_SLOTS + + +class DialogResult(IntEnum): + CANCEL = 0 + CONFIRM = 1 + NO_ACTION = -1 + + +class Widget(abc.ABC): + def __init__(self): + self._rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0) + self._parent_rect: rl.Rectangle = rl.Rectangle(0, 0, 0, 0) + self.__is_pressed = [False] * MAX_TOUCH_SLOTS + # if current mouse/touch down started within the widget's rectangle + self.__tracking_is_pressed = [False] * MAX_TOUCH_SLOTS + self._enabled: bool | Callable[[], bool] = True + self._is_visible: bool | Callable[[], bool] = True + self._touch_valid_callback: Callable[[], bool] | None = None + self._click_callback: Callable[[], None] | None = None + self._multi_touch = False + + @property + def rect(self) -> rl.Rectangle: + return self._rect + + def set_rect(self, rect: rl.Rectangle) -> None: + changed = (self._rect.x != rect.x or self._rect.y != rect.y or + self._rect.width != rect.width or self._rect.height != rect.height) + self._rect = rect + if changed: + self._update_layout_rects() + + def set_parent_rect(self, parent_rect: rl.Rectangle) -> None: + """Can be used like size hint in QT""" + self._parent_rect = parent_rect + + @property + def is_pressed(self) -> bool: + return any(self.__is_pressed) + + @property + def enabled(self) -> bool: + return self._enabled() if callable(self._enabled) else self._enabled + + def set_enabled(self, enabled: bool | Callable[[], bool]) -> None: + self._enabled = enabled + + @property + def is_visible(self) -> bool: + return self._is_visible() if callable(self._is_visible) else self._is_visible + + def set_visible(self, visible: bool | Callable[[], bool]) -> None: + self._is_visible = visible + + def set_click_callback(self, click_callback: Callable[[], None] | None) -> None: + """Set a callback to be called when the widget is clicked.""" + self._click_callback = click_callback + + def set_touch_valid_callback(self, touch_callback: Callable[[], bool]) -> None: + """Set a callback to determine if the widget can be clicked.""" + self._touch_valid_callback = touch_callback + + def _touch_valid(self) -> bool: + """Check if the widget can be touched.""" + return self._touch_valid_callback() if self._touch_valid_callback else True + + def set_position(self, x: float, y: float) -> None: + changed = (self._rect.x != x or self._rect.y != y) + self._rect.x, self._rect.y = x, y + if changed: + self._update_layout_rects() + + def render(self, rect: rl.Rectangle = None) -> bool | int | None: + if rect is not None: + self.set_rect(rect) + + self._update_state() + + if not self.is_visible: + return None + + ret = self._render(self._rect) + + # Keep track of whether mouse down started within the widget's rectangle + if self.enabled: + for mouse_event in gui_app.mouse_events: + if not self._multi_touch and mouse_event.slot != 0: + continue + + # Ignores touches/presses that start outside our rect + # Allows touch to leave the rect and come back in focus if mouse did not release + if mouse_event.left_pressed and self._touch_valid(): + if rl.check_collision_point_rec(mouse_event.pos, self._rect): + self._handle_mouse_press(mouse_event.pos) + self.__is_pressed[mouse_event.slot] = True + self.__tracking_is_pressed[mouse_event.slot] = True + + # Callback such as scroll panel signifies user is scrolling + elif not self._touch_valid(): + self.__is_pressed[mouse_event.slot] = False + self.__tracking_is_pressed[mouse_event.slot] = False + + elif mouse_event.left_released: + if self.__is_pressed[mouse_event.slot] and rl.check_collision_point_rec(mouse_event.pos, self._rect): + self._handle_mouse_release(mouse_event.pos) + self.__is_pressed[mouse_event.slot] = False + self.__tracking_is_pressed[mouse_event.slot] = False + + # Mouse/touch is still within our rect + elif rl.check_collision_point_rec(mouse_event.pos, self._rect): + if self.__tracking_is_pressed[mouse_event.slot]: + self.__is_pressed[mouse_event.slot] = True + + # Mouse/touch left our rect but may come back into focus later + elif not rl.check_collision_point_rec(mouse_event.pos, self._rect): + self.__is_pressed[mouse_event.slot] = False + + return ret + + @abc.abstractmethod + def _render(self, rect: rl.Rectangle) -> bool | int | None: + """Render the widget within the given rectangle.""" + + def _update_state(self): + """Optionally update the widget's non-layout state. This is called before rendering.""" + + def _update_layout_rects(self) -> None: + """Optionally update any layout rects on Widget rect change.""" + + def _handle_mouse_press(self, mouse_pos: MousePos) -> bool: + """Optionally handle mouse press events.""" + return False + + def _handle_mouse_release(self, mouse_pos: MousePos) -> bool: + """Optionally handle mouse release events.""" + if self._click_callback: + self._click_callback() + return False + + def show_event(self): + """Optionally handle show event. Parent must manually call this""" + + def hide_event(self): + """Optionally handle hide event. Parent must manually call this""" + diff --git a/system/ui/widgets/button.py b/system/ui/widgets/button.py new file mode 100644 index 0000000000..141f682db0 --- /dev/null +++ b/system/ui/widgets/button.py @@ -0,0 +1,170 @@ +from collections.abc import Callable +from enum import IntEnum + +import pyray as rl + +from openpilot.system.ui.lib.application import FontWeight, MousePos +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.label import TextAlignment, Label + + +class ButtonStyle(IntEnum): + NORMAL = 0 # Most common, neutral buttons + PRIMARY = 1 # For main actions + DANGER = 2 # For critical actions, like reboot or delete + TRANSPARENT = 3 # For buttons with transparent background and border + TRANSPARENT_WHITE_TEXT = 9 # For buttons with transparent background and border and white text + TRANSPARENT_WHITE_BORDER = 10 # For buttons with transparent background and white border and text + ACTION = 4 + LIST_ACTION = 5 # For list items with action buttons + NO_EFFECT = 6 + KEYBOARD = 7 + FORGET_WIFI = 8 + + +ICON_PADDING = 15 +DEFAULT_BUTTON_FONT_SIZE = 60 +ACTION_BUTTON_FONT_SIZE = 48 + +BUTTON_TEXT_COLOR = { + ButtonStyle.NORMAL: rl.Color(228, 228, 228, 255), + ButtonStyle.PRIMARY: rl.Color(228, 228, 228, 255), + ButtonStyle.DANGER: rl.Color(228, 228, 228, 255), + ButtonStyle.TRANSPARENT: rl.BLACK, + ButtonStyle.TRANSPARENT_WHITE_TEXT: rl.WHITE, + ButtonStyle.TRANSPARENT_WHITE_BORDER: rl.Color(228, 228, 228, 255), + ButtonStyle.ACTION: rl.BLACK, + ButtonStyle.LIST_ACTION: rl.Color(228, 228, 228, 255), + ButtonStyle.NO_EFFECT: rl.Color(228, 228, 228, 255), + ButtonStyle.KEYBOARD: rl.Color(221, 221, 221, 255), + ButtonStyle.FORGET_WIFI: rl.Color(51, 51, 51, 255), +} + +BUTTON_DISABLED_TEXT_COLORS = { + ButtonStyle.TRANSPARENT_WHITE_TEXT: rl.WHITE, +} + +BUTTON_BACKGROUND_COLORS = { + ButtonStyle.NORMAL: rl.Color(51, 51, 51, 255), + ButtonStyle.PRIMARY: rl.Color(70, 91, 234, 255), + ButtonStyle.DANGER: rl.Color(255, 36, 36, 255), + ButtonStyle.TRANSPARENT: rl.BLACK, + ButtonStyle.TRANSPARENT_WHITE_TEXT: rl.BLANK, + ButtonStyle.TRANSPARENT_WHITE_BORDER: rl.BLACK, + ButtonStyle.ACTION: rl.Color(189, 189, 189, 255), + ButtonStyle.LIST_ACTION: rl.Color(57, 57, 57, 255), + ButtonStyle.NO_EFFECT: rl.Color(51, 51, 51, 255), + ButtonStyle.KEYBOARD: rl.Color(68, 68, 68, 255), + ButtonStyle.FORGET_WIFI: rl.Color(189, 189, 189, 255), +} + +BUTTON_PRESSED_BACKGROUND_COLORS = { + ButtonStyle.NORMAL: rl.Color(74, 74, 74, 255), + ButtonStyle.PRIMARY: rl.Color(48, 73, 244, 255), + ButtonStyle.DANGER: rl.Color(255, 36, 36, 255), + ButtonStyle.TRANSPARENT: rl.BLACK, + ButtonStyle.TRANSPARENT_WHITE_TEXT: rl.BLANK, + ButtonStyle.TRANSPARENT_WHITE_BORDER: rl.BLANK, + ButtonStyle.ACTION: rl.Color(130, 130, 130, 255), + ButtonStyle.LIST_ACTION: rl.Color(74, 74, 74, 74), + ButtonStyle.NO_EFFECT: rl.Color(51, 51, 51, 255), + ButtonStyle.KEYBOARD: rl.Color(51, 51, 51, 255), + ButtonStyle.FORGET_WIFI: rl.Color(130, 130, 130, 255), +} + +BUTTON_DISABLED_BACKGROUND_COLORS = { + ButtonStyle.TRANSPARENT_WHITE_TEXT: rl.BLANK, +} + + +class Button(Widget): + def __init__(self, + text: str, + click_callback: Callable[[], None] | None = None, + font_size: int = DEFAULT_BUTTON_FONT_SIZE, + font_weight: FontWeight = FontWeight.MEDIUM, + button_style: ButtonStyle = ButtonStyle.NORMAL, + border_radius: int = 10, + text_alignment: TextAlignment = TextAlignment.CENTER, + text_padding: int = 20, + icon=None, + multi_touch: bool = False, + ): + + super().__init__() + self._button_style = button_style + self._border_radius = border_radius + self._background_color = BUTTON_BACKGROUND_COLORS[self._button_style] + + self._label = Label(text, font_size, font_weight, text_alignment, text_padding, + BUTTON_TEXT_COLOR[self._button_style], icon=icon) + + self._click_callback = click_callback + self._multi_touch = multi_touch + + def set_text(self, text): + self._label.set_text(text) + + def set_button_style(self, button_style: ButtonStyle): + self._button_style = button_style + self._background_color = BUTTON_BACKGROUND_COLORS[self._button_style] + self._label.set_text_color(BUTTON_TEXT_COLOR[self._button_style]) + + def _update_state(self): + if self.enabled: + self._label.set_text_color(BUTTON_TEXT_COLOR[self._button_style]) + if self.is_pressed: + self._background_color = BUTTON_PRESSED_BACKGROUND_COLORS[self._button_style] + else: + self._background_color = BUTTON_BACKGROUND_COLORS[self._button_style] + elif self._button_style != ButtonStyle.NO_EFFECT: + self._background_color = BUTTON_DISABLED_BACKGROUND_COLORS.get(self._button_style, rl.Color(51, 51, 51, 255)) + self._label.set_text_color(BUTTON_DISABLED_TEXT_COLORS.get(self._button_style, rl.Color(228, 228, 228, 51))) + + def _render(self, _): + roundness = self._border_radius / (min(self._rect.width, self._rect.height) / 2) + if self._button_style == ButtonStyle.TRANSPARENT_WHITE_BORDER: + rl.draw_rectangle_rounded(self._rect, roundness, 10, rl.BLACK) + rl.draw_rectangle_rounded_lines_ex(self._rect, roundness, 10, 2, rl.WHITE) + else: + rl.draw_rectangle_rounded(self._rect, roundness, 10, self._background_color) + self._label.render(self._rect) + + +class ButtonRadio(Button): + def __init__(self, + text: str, + icon, + click_callback: Callable[[], None] | None = None, + font_size: int = DEFAULT_BUTTON_FONT_SIZE, + text_alignment: TextAlignment = TextAlignment.LEFT, + border_radius: int = 10, + text_padding: int = 20, + ): + + super().__init__(text, click_callback=click_callback, font_size=font_size, + border_radius=border_radius, text_padding=text_padding, + text_alignment=text_alignment) + self._text_padding = text_padding + self._icon = icon + self.selected = False + + def _handle_mouse_release(self, mouse_pos: MousePos): + super()._handle_mouse_release(mouse_pos) + self.selected = not self.selected + + def _update_state(self): + if self.selected: + self._background_color = BUTTON_BACKGROUND_COLORS[ButtonStyle.PRIMARY] + else: + self._background_color = BUTTON_BACKGROUND_COLORS[ButtonStyle.NORMAL] + + def _render(self, _): + roundness = self._border_radius / (min(self._rect.width, self._rect.height) / 2) + rl.draw_rectangle_rounded(self._rect, roundness, 10, self._background_color) + self._label.render(self._rect) + + if self._icon and self.selected: + icon_y = self._rect.y + (self._rect.height - self._icon.height) / 2 + icon_x = self._rect.x + self._rect.width - self._icon.width - self._text_padding - ICON_PADDING + rl.draw_texture_v(self._icon, rl.Vector2(icon_x, icon_y), rl.WHITE if self.enabled else rl.Color(255, 255, 255, 100)) diff --git a/system/ui/widgets/confirm_dialog.py b/system/ui/widgets/confirm_dialog.py new file mode 100644 index 0000000000..606b04b6e9 --- /dev/null +++ b/system/ui/widgets/confirm_dialog.py @@ -0,0 +1,72 @@ +import pyray as rl +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.widgets import DialogResult +from openpilot.system.ui.widgets.button import ButtonStyle, Button +from openpilot.system.ui.widgets.label import Label +from openpilot.system.ui.widgets import Widget + +DIALOG_WIDTH = 1748 +DIALOG_HEIGHT = 690 +BUTTON_HEIGHT = 160 +MARGIN = 50 +TEXT_AREA_HEIGHT_REDUCTION = 200 +BACKGROUND_COLOR = rl.Color(27, 27, 27, 255) + + +class ConfirmDialog(Widget): + def __init__(self, text: str, confirm_text: str, cancel_text: str = "Cancel"): + super().__init__() + self._label = Label(text, 70, FontWeight.BOLD, text_color=rl.Color(201, 201, 201, 255)) + self._cancel_button = Button(cancel_text, self._cancel_button_callback) + self._confirm_button = Button(confirm_text, self._confirm_button_callback, button_style=ButtonStyle.PRIMARY) + self._dialog_result = DialogResult.NO_ACTION + self._cancel_text = cancel_text + + def set_text(self, text): + self._label.set_text(text) + + def reset(self): + self._dialog_result = DialogResult.NO_ACTION + + def _cancel_button_callback(self): + self._dialog_result = DialogResult.CANCEL + + def _confirm_button_callback(self): + self._dialog_result = DialogResult.CONFIRM + + def _render(self, rect: rl.Rectangle): + dialog_x = (gui_app.width - DIALOG_WIDTH) / 2 + dialog_y = (gui_app.height - DIALOG_HEIGHT) / 2 + dialog_rect = rl.Rectangle(dialog_x, dialog_y, DIALOG_WIDTH, DIALOG_HEIGHT) + + bottom = dialog_rect.y + dialog_rect.height + button_width = (dialog_rect.width - 3 * MARGIN) // 2 + cancel_button_x = dialog_rect.x + MARGIN + confirm_button_x = dialog_rect.x + dialog_rect.width - button_width - MARGIN + button_y = bottom - BUTTON_HEIGHT - MARGIN + cancel_button = rl.Rectangle(cancel_button_x, button_y, button_width, BUTTON_HEIGHT) + confirm_button = rl.Rectangle(confirm_button_x, button_y, button_width, BUTTON_HEIGHT) + + rl.draw_rectangle_rec(dialog_rect, BACKGROUND_COLOR) + + text_rect = rl.Rectangle(dialog_rect.x + MARGIN, dialog_rect.y, dialog_rect.width - 2 * MARGIN, dialog_rect.height - TEXT_AREA_HEIGHT_REDUCTION) + self._label.render(text_rect) + + if rl.is_key_pressed(rl.KeyboardKey.KEY_ENTER): + self._dialog_result = DialogResult.CONFIRM + elif rl.is_key_pressed(rl.KeyboardKey.KEY_ESCAPE): + self._dialog_result = DialogResult.CANCEL + + if self._cancel_text: + self._confirm_button.render(confirm_button) + self._cancel_button.render(cancel_button) + else: + centered_button_x = dialog_rect.x + (dialog_rect.width - button_width) / 2 + centered_confirm_button = rl.Rectangle(centered_button_x, button_y, button_width, BUTTON_HEIGHT) + self._confirm_button.render(centered_confirm_button) + + return self._dialog_result + + +def alert_dialog(message: str, button_text: str = "OK"): + return ConfirmDialog(message, button_text, cancel_text="") diff --git a/system/ui/widgets/html_render.py b/system/ui/widgets/html_render.py new file mode 100644 index 0000000000..91a1ccbbc4 --- /dev/null +++ b/system/ui/widgets/html_render.py @@ -0,0 +1,257 @@ +import re +import pyray as rl +from dataclasses import dataclass +from enum import Enum +from typing import Any +from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle + +LIST_INDENT_PX = 40 + + +class ElementType(Enum): + H1 = "h1" + H2 = "h2" + H3 = "h3" + H4 = "h4" + H5 = "h5" + H6 = "h6" + P = "p" + UL = "ul" + LI = "li" + BR = "br" + + +TAG_NAMES = '|'.join([t.value for t in ElementType]) +START_TAG_RE = re.compile(f'<({TAG_NAMES})>') +END_TAG_RE = re.compile(f'') + + +def is_tag(token: str) -> tuple[bool, bool, ElementType | None]: + supported_tag = bool(START_TAG_RE.fullmatch(token)) + supported_end_tag = bool(END_TAG_RE.fullmatch(token)) + tag = ElementType(token[1:-1].strip('/')) if supported_tag or supported_end_tag else None + return supported_tag, supported_end_tag, tag + + +@dataclass +class HtmlElement: + type: ElementType + content: str + font_size: int + font_weight: FontWeight + margin_top: int + margin_bottom: int + line_height: float = 1.2 + indent_level: int = 0 + + +class HtmlRenderer(Widget): + def __init__(self, file_path: str | None = None, text: str | None = None, + text_size: dict | None = None, text_color: rl.Color = rl.WHITE): + super().__init__() + self._text_color = text_color + self._normal_font = gui_app.font(FontWeight.NORMAL) + self._bold_font = gui_app.font(FontWeight.BOLD) + self._indent_level = 0 + + if text_size is None: + text_size = {} + + # Untagged text defaults to

    + self.styles: dict[ElementType, dict[str, Any]] = { + ElementType.H1: {"size": 68, "weight": FontWeight.BOLD, "margin_top": 20, "margin_bottom": 16}, + ElementType.H2: {"size": 60, "weight": FontWeight.BOLD, "margin_top": 24, "margin_bottom": 12}, + ElementType.H3: {"size": 52, "weight": FontWeight.BOLD, "margin_top": 20, "margin_bottom": 10}, + ElementType.H4: {"size": 48, "weight": FontWeight.BOLD, "margin_top": 16, "margin_bottom": 8}, + ElementType.H5: {"size": 44, "weight": FontWeight.BOLD, "margin_top": 12, "margin_bottom": 6}, + ElementType.H6: {"size": 40, "weight": FontWeight.BOLD, "margin_top": 10, "margin_bottom": 4}, + ElementType.P: {"size": text_size.get(ElementType.P, 38), "weight": FontWeight.NORMAL, "margin_top": 8, "margin_bottom": 12}, + ElementType.LI: {"size": 38, "weight": FontWeight.NORMAL, "color": rl.Color(40, 40, 40, 255), "margin_top": 6, "margin_bottom": 6}, + ElementType.BR: {"size": 0, "weight": FontWeight.NORMAL, "margin_top": 0, "margin_bottom": 12}, + } + + self.elements: list[HtmlElement] = [] + if file_path is not None: + self.parse_html_file(file_path) + elif text is not None: + self.parse_html_content(text) + else: + raise ValueError("Either file_path or text must be provided") + + def parse_html_file(self, file_path: str) -> None: + with open(file_path, encoding='utf-8') as file: + content = file.read() + self.parse_html_content(content) + + def parse_html_content(self, html_content: str) -> None: + self.elements.clear() + + # Remove HTML comments + html_content = re.sub(r'', '', html_content, flags=re.DOTALL) + + # Remove DOCTYPE, html, head, body tags but keep their content + html_content = re.sub(r']*>', '', html_content) + html_content = re.sub(r']*>', '', html_content) + + # Parse HTML + tokens = re.findall(r']+>|<[^>]+>|[^<\s]+', html_content) + + def close_tag(): + nonlocal current_content + nonlocal current_tag + + # If no tag is set, default to paragraph so we don't lose text + if current_tag is None: + current_tag = ElementType.P + + text = ' '.join(current_content).strip() + current_content = [] + if text: + if current_tag == ElementType.LI: + text = '• ' + text + self._add_element(current_tag, text) + + current_content: list[str] = [] + current_tag: ElementType | None = None + for token in tokens: + is_start_tag, is_end_tag, tag = is_tag(token) + if tag is not None: + if tag == ElementType.BR: + self._add_element(ElementType.BR, "") + + elif is_start_tag or is_end_tag: + # Always add content regardless of opening or closing tag + close_tag() + + # TODO: reset to None if end tag? + if is_start_tag: + current_tag = tag + + # increment after we add the content for the current tag + if tag == ElementType.UL: + self._indent_level = self._indent_level + 1 if is_start_tag else max(0, self._indent_level - 1) + + else: + current_content.append(token) + + if current_content: + close_tag() + + def _add_element(self, element_type: ElementType, content: str) -> None: + style = self.styles[element_type] + + element = HtmlElement( + type=element_type, + content=content, + font_size=style["size"], + font_weight=style["weight"], + margin_top=style["margin_top"], + margin_bottom=style["margin_bottom"], + indent_level=self._indent_level, + ) + + self.elements.append(element) + + def _render(self, rect: rl.Rectangle): + # TODO: speed up by removing duplicate calculations across renders + current_y = rect.y + padding = 20 + content_width = rect.width - (padding * 2) + + for element in self.elements: + if element.type == ElementType.BR: + current_y += element.margin_bottom + continue + + current_y += element.margin_top + if current_y > rect.y + rect.height: + break + + if element.content: + font = self._get_font(element.font_weight) + wrapped_lines = wrap_text(font, element.content, element.font_size, int(content_width)) + + for line in wrapped_lines: + if current_y < rect.y - element.font_size * FONT_SCALE: + current_y += element.font_size * FONT_SCALE * element.line_height + continue + + if current_y > rect.y + rect.height: + break + + text_x = rect.x + (max(element.indent_level - 1, 0) * LIST_INDENT_PX) + rl.draw_text_ex(font, line, rl.Vector2(text_x + padding, current_y), element.font_size, 0, self._text_color) + + current_y += element.font_size * FONT_SCALE * element.line_height + + # Apply bottom margin + current_y += element.margin_bottom + + return current_y - rect.y + + def get_total_height(self, content_width: int) -> float: + total_height = 0.0 + padding = 20 + usable_width = content_width - (padding * 2) + + for element in self.elements: + if element.type == ElementType.BR: + total_height += element.margin_bottom + continue + + total_height += element.margin_top + + if element.content: + font = self._get_font(element.font_weight) + wrapped_lines = wrap_text(font, element.content, element.font_size, int(usable_width)) + + for _ in wrapped_lines: + total_height += element.font_size * FONT_SCALE * element.line_height + + total_height += element.margin_bottom + + return total_height + + def _get_font(self, weight: FontWeight): + if weight == FontWeight.BOLD: + return self._bold_font + return self._normal_font + + +class HtmlModal(Widget): + def __init__(self, file_path: str | None = None, text: str | None = None): + super().__init__() + self._content = HtmlRenderer(file_path=file_path, text=text) + self._scroll_panel = GuiScrollPanel() + self._ok_button = Button("OK", click_callback=lambda: gui_app.set_modal_overlay(None), button_style=ButtonStyle.PRIMARY) + + def _render(self, rect: rl.Rectangle): + margin = 50 + content_rect = rl.Rectangle(rect.x + margin, rect.y + margin, rect.width - (margin * 2), rect.height - (margin * 2)) + + button_height = 160 + button_spacing = 20 + scrollable_height = content_rect.height - button_height - button_spacing + + scrollable_rect = rl.Rectangle(content_rect.x, content_rect.y, content_rect.width, scrollable_height) + + total_height = self._content.get_total_height(int(scrollable_rect.width)) + scroll_content_rect = rl.Rectangle(scrollable_rect.x, scrollable_rect.y, scrollable_rect.width, total_height) + scroll_offset = self._scroll_panel.update(scrollable_rect, scroll_content_rect) + scroll_content_rect.y += scroll_offset + + rl.begin_scissor_mode(int(scrollable_rect.x), int(scrollable_rect.y), int(scrollable_rect.width), int(scrollable_rect.height)) + self._content.render(scroll_content_rect) + rl.end_scissor_mode() + + button_width = (rect.width - 3 * 50) // 3 + button_x = content_rect.x + content_rect.width - button_width + button_y = content_rect.y + content_rect.height - button_height + button_rect = rl.Rectangle(button_x, button_y, button_width, button_height) + self._ok_button.render(button_rect) + + return -1 diff --git a/system/ui/widgets/inputbox.py b/system/ui/widgets/inputbox.py new file mode 100644 index 0000000000..239d63037e --- /dev/null +++ b/system/ui/widgets/inputbox.py @@ -0,0 +1,228 @@ +import pyray as rl +import time +from openpilot.system.ui.lib.application import gui_app, MousePos +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import Widget + +PASSWORD_MASK_CHAR = "•" +PASSWORD_MASK_DELAY = 1.5 # Seconds to show character before masking + + +class InputBox(Widget): + def __init__(self, max_text_size=255, password_mode=False): + super().__init__() + self._max_text_size = max_text_size + self._input_text = "" + self._cursor_position = 0 + self._password_mode = password_mode + self._blink_counter = 0 + self._show_cursor = False + self._last_key_pressed = 0 + self._key_press_time = 0 + self._repeat_delay = 30 + self._repeat_rate = 4 + self._text_offset = 0 + self._visible_width = 0 + self._last_char_time = 0 # Track when last character was added + self._masked_length = 0 # How many characters are currently masked + + @property + def text(self): + return self._input_text + + @text.setter + def text(self, value): + self._input_text = value[: self._max_text_size] + self._cursor_position = len(self._input_text) + self._update_text_offset() + + def set_password_mode(self, password_mode): + self._password_mode = password_mode + + def clear(self): + self._input_text = '' + self._cursor_position = 0 + self._text_offset = 0 + + def set_cursor_position(self, position): + """Set the cursor position and reset the blink counter.""" + if 0 <= position <= len(self._input_text): + self._cursor_position = position + self._blink_counter = 0 + self._show_cursor = True + self._update_text_offset() + + def _update_text_offset(self): + """Ensure the cursor is visible by adjusting text offset.""" + if self._visible_width == 0: + return + + font = gui_app.font() + display_text = self._get_display_text() + padding = 10 + + if self._cursor_position > 0: + cursor_x = measure_text_cached(font, display_text[: self._cursor_position], self._font_size).x + else: + cursor_x = 0 + + visible_width = self._visible_width - (padding * 2) + + # Adjust offset if cursor would be outside visible area + if cursor_x < self._text_offset: + self._text_offset = max(0, cursor_x - padding) + elif cursor_x > self._text_offset + visible_width: + self._text_offset = cursor_x - visible_width + padding + + def add_char_at_cursor(self, char): + """Add a character at the current cursor position.""" + if len(self._input_text) < self._max_text_size: + self._input_text = self._input_text[: self._cursor_position] + char + self._input_text[self._cursor_position:] + self.set_cursor_position(self._cursor_position + 1) + + if self._password_mode: + self._last_char_time = time.monotonic() + + return True + return False + + def delete_char_before_cursor(self): + """Delete the character before the cursor position (backspace).""" + if self._cursor_position > 0: + self._input_text = self._input_text[: self._cursor_position - 1] + self._input_text[self._cursor_position:] + self.set_cursor_position(self._cursor_position - 1) + return True + return False + + def delete_char_at_cursor(self): + """Delete the character at the cursor position (delete).""" + if self._cursor_position < len(self._input_text): + self._input_text = self._input_text[: self._cursor_position] + self._input_text[self._cursor_position + 1:] + self.set_cursor_position(self._cursor_position) + return True + return False + + def _render(self, rect, color=rl.BLACK, border_color=rl.DARKGRAY, text_color=rl.WHITE, font_size=80): + # Store dimensions for text offset calculations + self._visible_width = rect.width + self._font_size = font_size + + # Draw input box + rl.draw_rectangle_rec(rect, color) + + # Process keyboard input + self._handle_keyboard_input() + + # Update cursor blink + self._blink_counter += 1 + if self._blink_counter >= 30: + self._show_cursor = not self._show_cursor + self._blink_counter = 0 + + # Display text + font = gui_app.font() + display_text = self._get_display_text() + padding = 10 + + # Clip text within input box bounds + buffer = 2 + rl.begin_scissor_mode(int(rect.x + padding - buffer), int(rect.y), int(rect.width - padding * 2 + buffer * 2), int(rect.height)) + rl.draw_text_ex( + font, + display_text, + rl.Vector2(int(rect.x + padding - self._text_offset), int(rect.y + rect.height / 2 - font_size / 2)), + font_size, + 0, + text_color, + ) + + # Draw cursor + if self._show_cursor: + cursor_x = rect.x + padding + if len(display_text) > 0 and self._cursor_position > 0: + cursor_x += measure_text_cached(font, display_text[: self._cursor_position], font_size).x + + # Apply text offset to cursor position + cursor_x -= self._text_offset + + cursor_height = font_size + 4 + cursor_y = rect.y + rect.height / 2 - cursor_height / 2 + rl.draw_line(int(cursor_x), int(cursor_y), int(cursor_x), int(cursor_y + cursor_height), rl.WHITE) + + rl.end_scissor_mode() + + def _get_display_text(self): + """Get text to display, applying password masking with delay if needed.""" + if not self._password_mode: + return self._input_text + + # Show character at last edited position if within delay window + masked_text = PASSWORD_MASK_CHAR * len(self._input_text) + recent_edit = time.monotonic() - self._last_char_time < PASSWORD_MASK_DELAY + if recent_edit and self._input_text: + last_pos = max(0, self._cursor_position - 1) + if last_pos < len(self._input_text): + return masked_text[:last_pos] + self._input_text[last_pos] + masked_text[last_pos + 1:] + + return masked_text + + def _handle_mouse_release(self, mouse_pos: MousePos): + # Calculate cursor position from click + if len(self._input_text) > 0: + font = gui_app.font() + display_text = self._get_display_text() + + # Find the closest character position to the click + relative_x = mouse_pos.x - (self._rect.x + 10) + self._text_offset + best_pos = 0 + min_distance = float('inf') + + for i in range(len(self._input_text) + 1): + char_width = measure_text_cached(font, display_text[:i], self._font_size).x + distance = abs(relative_x - char_width) + if distance < min_distance: + min_distance = distance + best_pos = i + + self.set_cursor_position(best_pos) + else: + self.set_cursor_position(0) + + def _handle_keyboard_input(self): + # Handle navigation keys + key = rl.get_key_pressed() + if key != 0: + self._process_key(key) + if key in (rl.KEY_LEFT, rl.KEY_RIGHT, rl.KEY_BACKSPACE, rl.KEY_DELETE): + self._last_key_pressed = key + self._key_press_time = 0 + + # Handle repeats for held keys + elif self._last_key_pressed != 0: + if rl.is_key_down(self._last_key_pressed): + self._key_press_time += 1 + if self._key_press_time > self._repeat_delay and self._key_press_time % self._repeat_rate == 0: + self._process_key(self._last_key_pressed) + else: + self._last_key_pressed = 0 + + # Handle text input + char = rl.get_char_pressed() + if char != 0 and char >= 32: # Filter out control characters + self.add_char_at_cursor(chr(char)) + + def _process_key(self, key): + if key == rl.KEY_LEFT: + if self._cursor_position > 0: + self.set_cursor_position(self._cursor_position - 1) + elif key == rl.KEY_RIGHT: + if self._cursor_position < len(self._input_text): + self.set_cursor_position(self._cursor_position + 1) + elif key == rl.KEY_BACKSPACE: + self.delete_char_before_cursor() + elif key == rl.KEY_DELETE: + self.delete_char_at_cursor() + elif key == rl.KEY_HOME: + self.set_cursor_position(0) + elif key == rl.KEY_END: + self.set_cursor_position(len(self._input_text)) diff --git a/system/ui/widgets/keyboard.py b/system/ui/widgets/keyboard.py new file mode 100644 index 0000000000..70f06f6b9d --- /dev/null +++ b/system/ui/widgets/keyboard.py @@ -0,0 +1,268 @@ +from functools import partial +import time +from typing import Literal + +import pyray as rl + +from openpilot.system.ui.lib.application import gui_app, FontWeight +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import ButtonStyle, Button +from openpilot.system.ui.widgets.inputbox import InputBox +from openpilot.system.ui.widgets.label import Label, TextAlignment + +KEY_FONT_SIZE = 96 +DOUBLE_CLICK_THRESHOLD = 0.5 # seconds +DELETE_REPEAT_DELAY = 0.5 +DELETE_REPEAT_INTERVAL = 0.07 + +# Constants for special keys +CONTENT_MARGIN = 50 +BACKSPACE_KEY = "<-" +ENTER_KEY = "->" +SPACE_KEY = " " +SHIFT_INACTIVE_KEY = "SHIFT_OFF" +SHIFT_ACTIVE_KEY = "SHIFT_ON" +CAPS_LOCK_KEY = "CAPS" +NUMERIC_KEY = "123" +SYMBOL_KEY = "#+=" +ABC_KEY = "ABC" + +# Define keyboard layouts as a dictionary for easier access +KEYBOARD_LAYOUTS = { + "lowercase": [ + ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"], + ["a", "s", "d", "f", "g", "h", "j", "k", "l"], + [SHIFT_INACTIVE_KEY, "z", "x", "c", "v", "b", "n", "m", BACKSPACE_KEY], + [NUMERIC_KEY, "/", "-", SPACE_KEY, ".", ENTER_KEY], + ], + "uppercase": [ + ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"], + ["A", "S", "D", "F", "G", "H", "J", "K", "L"], + [SHIFT_ACTIVE_KEY, "Z", "X", "C", "V", "B", "N", "M", BACKSPACE_KEY], + [NUMERIC_KEY, "/", "-", SPACE_KEY, ".", ENTER_KEY], + ], + "numbers": [ + ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], + ["-", "/", ":", ";", "(", ")", "$", "&", "@", "\""], + [SYMBOL_KEY, ".", ",", "?", "!", "`", BACKSPACE_KEY], + [ABC_KEY, SPACE_KEY, ".", ENTER_KEY], + ], + "specials": [ + ["[", "]", "{", "}", "#", "%", "^", "*", "+", "="], + ["_", "\\", "|", "~", "<", ">", "€", "£", "¥", "•"], + [NUMERIC_KEY, ".", ",", "?", "!", "'", BACKSPACE_KEY], + [ABC_KEY, SPACE_KEY, ".", ENTER_KEY], + ], +} + + +class Keyboard(Widget): + def __init__(self, max_text_size: int = 255, min_text_size: int = 0, password_mode: bool = False, show_password_toggle: bool = False): + super().__init__() + self._layout_name: Literal["lowercase", "uppercase", "numbers", "specials"] = "lowercase" + self._caps_lock = False + self._last_shift_press_time = 0 + self._title = Label("", 90, FontWeight.BOLD, TextAlignment.LEFT) + self._sub_title = Label("", 55, FontWeight.NORMAL, TextAlignment.LEFT) + + self._max_text_size = max_text_size + self._min_text_size = min_text_size + self._input_box = InputBox(max_text_size) + self._password_mode = password_mode + self._show_password_toggle = show_password_toggle + + # Backspace key repeat tracking + self._backspace_pressed: bool = False + self._backspace_press_time: float = 0.0 + self._backspace_last_repeat: float = 0.0 + + self._render_return_status = -1 + self._cancel_button = Button("Cancel", self._cancel_button_callback) + + self._eye_button = Button("", self._eye_button_callback, button_style=ButtonStyle.TRANSPARENT) + + self._eye_open_texture = gui_app.texture("icons/eye_open.png", 81, 54) + self._eye_closed_texture = gui_app.texture("icons/eye_closed.png", 81, 54) + self._key_icons = { + BACKSPACE_KEY: gui_app.texture("icons/backspace.png", 80, 80), + SHIFT_INACTIVE_KEY: gui_app.texture("icons/shift.png", 80, 80), + SHIFT_ACTIVE_KEY: gui_app.texture("icons/shift-fill.png", 80, 80), + CAPS_LOCK_KEY: gui_app.texture("icons/capslock-fill.png", 80, 80), + ENTER_KEY: gui_app.texture("icons/arrow-right.png", 80, 80), + } + + self._all_keys = {} + for l in KEYBOARD_LAYOUTS: + for _, keys in enumerate(KEYBOARD_LAYOUTS[l]): + for _, key in enumerate(keys): + if key in self._key_icons: + texture = self._key_icons[key] + self._all_keys[key] = Button("", partial(self._key_callback, key), icon=texture, + button_style=ButtonStyle.PRIMARY if key == ENTER_KEY else ButtonStyle.KEYBOARD, multi_touch=True) + else: + self._all_keys[key] = Button(key, partial(self._key_callback, key), button_style=ButtonStyle.KEYBOARD, font_size=85, multi_touch=True) + self._all_keys[CAPS_LOCK_KEY] = Button("", partial(self._key_callback, CAPS_LOCK_KEY), icon=self._key_icons[CAPS_LOCK_KEY], + button_style=ButtonStyle.KEYBOARD, multi_touch=True) + + def set_text(self, text: str): + self._input_box.text = text + + @property + def text(self): + return self._input_box.text + + def clear(self): + self._layout_name = "lowercase" + self._caps_lock = False + self._input_box.clear() + self._backspace_pressed = False + + def set_title(self, title: str, sub_title: str = ""): + self._title.set_text(title) + self._sub_title.set_text(sub_title) + + def _eye_button_callback(self): + self._password_mode = not self._password_mode + + def _cancel_button_callback(self): + self.clear() + self._render_return_status = 0 + + def _key_callback(self, k): + if k == ENTER_KEY: + self._render_return_status = 1 + else: + self.handle_key_press(k) + + def _render(self, rect: rl.Rectangle): + rect = rl.Rectangle(rect.x + CONTENT_MARGIN, rect.y + CONTENT_MARGIN, rect.width - 2 * CONTENT_MARGIN, rect.height - 2 * CONTENT_MARGIN) + self._title.render(rl.Rectangle(rect.x, rect.y, rect.width, 95)) + self._sub_title.render(rl.Rectangle(rect.x, rect.y + 95, rect.width, 60)) + self._cancel_button.render(rl.Rectangle(rect.x + rect.width - 386, rect.y, 386, 125)) + + # Draw input box and password toggle + input_margin = 25 + input_box_rect = rl.Rectangle(rect.x + input_margin, rect.y + 160, rect.width - input_margin, 100) + self._render_input_area(input_box_rect) + + # Process backspace key repeat if it's held down + if not self._all_keys[BACKSPACE_KEY].is_pressed: + self._backspace_pressed = False + + if self._backspace_pressed: + current_time = time.monotonic() + time_since_press = current_time - self._backspace_press_time + + # After initial delay, start repeating with shorter intervals + if time_since_press > DELETE_REPEAT_DELAY: + time_since_last_repeat = current_time - self._backspace_last_repeat + if time_since_last_repeat > DELETE_REPEAT_INTERVAL: + self._input_box.delete_char_before_cursor() + self._backspace_last_repeat = current_time + + layout = KEYBOARD_LAYOUTS[self._layout_name] + + h_space, v_space = 15, 15 + row_y_start = rect.y + 300 # Starting Y position for the first row + key_height = (rect.height - 300 - 3 * v_space) / 4 + key_max_width = (rect.width - (len(layout[2]) - 1) * h_space) / len(layout[2]) + + # Iterate over the rows of keys in the current layout + for row, keys in enumerate(layout): + key_width = min((rect.width - (180 if row == 1 else 0) - h_space * (len(keys) - 1)) / len(keys), key_max_width) + start_x = rect.x + (90 if row == 1 else 0) + + for i, key in enumerate(keys): + if i > 0: + start_x += h_space + + new_width = (key_width * 3 + h_space * 2) if key == SPACE_KEY else (key_width * 2 + h_space if key == ENTER_KEY else key_width) + key_rect = rl.Rectangle(start_x, row_y_start + row * (key_height + v_space), new_width, key_height) + start_x += new_width + + is_enabled = key != ENTER_KEY or len(self._input_box.text) >= self._min_text_size + + if key == BACKSPACE_KEY and self._all_keys[BACKSPACE_KEY].is_pressed and not self._backspace_pressed: + self._backspace_pressed = True + self._backspace_press_time = time.monotonic() + self._backspace_last_repeat = time.monotonic() + + if key in self._key_icons: + if key == SHIFT_ACTIVE_KEY and self._caps_lock: + key = CAPS_LOCK_KEY + self._all_keys[key].set_enabled(is_enabled) + self._all_keys[key].render(key_rect) + else: + self._all_keys[key].set_enabled(is_enabled) + self._all_keys[key].render(key_rect) + + return self._render_return_status + + def _render_input_area(self, input_rect: rl.Rectangle): + if self._show_password_toggle: + self._input_box.set_password_mode(self._password_mode) + self._input_box.render(rl.Rectangle(input_rect.x, input_rect.y, input_rect.width - 100, input_rect.height)) + + # render eye icon + eye_texture = self._eye_closed_texture if self._password_mode else self._eye_open_texture + + eye_rect = rl.Rectangle(input_rect.x + input_rect.width - 90, input_rect.y, 80, input_rect.height) + self._eye_button.render(eye_rect) + + eye_x = eye_rect.x + (eye_rect.width - eye_texture.width) / 2 + eye_y = eye_rect.y + (eye_rect.height - eye_texture.height) / 2 + + rl.draw_texture_v(eye_texture, rl.Vector2(eye_x, eye_y), rl.WHITE) + else: + self._input_box.render(input_rect) + + rl.draw_line_ex( + rl.Vector2(input_rect.x, input_rect.y + input_rect.height - 2), + rl.Vector2(input_rect.x + input_rect.width, input_rect.y + input_rect.height - 2), + 3.0, # 3 pixel thickness + rl.Color(189, 189, 189, 255), + ) + + def handle_key_press(self, key): + if key in (CAPS_LOCK_KEY, ABC_KEY): + self._caps_lock = False + self._layout_name = "lowercase" + elif key == SHIFT_INACTIVE_KEY: + self._last_shift_press_time = time.monotonic() + self._layout_name = "uppercase" + elif key == SHIFT_ACTIVE_KEY: + if time.monotonic() - self._last_shift_press_time < DOUBLE_CLICK_THRESHOLD: + self._caps_lock = True + else: + self._layout_name = "lowercase" + elif key == NUMERIC_KEY: + self._layout_name = "numbers" + elif key == SYMBOL_KEY: + self._layout_name = "specials" + elif key == BACKSPACE_KEY: + self._input_box.delete_char_before_cursor() + else: + self._input_box.add_char_at_cursor(key) + if not self._caps_lock and self._layout_name == "uppercase": + self._layout_name = "lowercase" + + def reset(self, min_text_size: int | None = None): + if min_text_size is not None: + self._min_text_size = min_text_size + self._render_return_status = -1 + self.clear() + + +if __name__ == "__main__": + gui_app.init_window("Keyboard") + keyboard = Keyboard(min_text_size=8, show_password_toggle=True) + for _ in gui_app.render(): + keyboard.set_title("Keyboard Input", "Type your text below") + result = keyboard.render(rl.Rectangle(0, 0, gui_app.width, gui_app.height)) + if result == 1: + print(f"You typed: {keyboard.text}") + gui_app.request_close() + elif result == 0: + print("Canceled") + gui_app.request_close() + gui_app.close() diff --git a/system/ui/widgets/label.py b/system/ui/widgets/label.py new file mode 100644 index 0000000000..2da9a9f8df --- /dev/null +++ b/system/ui/widgets/label.py @@ -0,0 +1,177 @@ +from enum import IntEnum +from itertools import zip_longest + +import pyray as rl + +from openpilot.system.ui.lib.application import gui_app, FontWeight, DEFAULT_TEXT_SIZE, DEFAULT_TEXT_COLOR +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.lib.utils import GuiStyleContext +from openpilot.system.ui.lib.emoji import find_emoji, emoji_tex +from openpilot.system.ui.lib.wrap_text import wrap_text +from openpilot.system.ui.widgets import Widget + +ICON_PADDING = 15 + +class TextAlignment(IntEnum): + LEFT = 0 + CENTER = 1 + RIGHT = 2 + +# TODO: This should be a Widget class +def gui_label( + rect: rl.Rectangle, + text: str, + font_size: int = DEFAULT_TEXT_SIZE, + color: rl.Color = DEFAULT_TEXT_COLOR, + font_weight: FontWeight = FontWeight.NORMAL, + alignment: int = rl.GuiTextAlignment.TEXT_ALIGN_LEFT, + alignment_vertical: int = rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE, + elide_right: bool = True +): + font = gui_app.font(font_weight) + text_size = measure_text_cached(font, text, font_size) + display_text = text + + # Elide text to fit within the rectangle + if elide_right and text_size.x > rect.width: + ellipsis = "..." + left, right = 0, len(text) + while left < right: + mid = (left + right) // 2 + candidate = text[:mid] + ellipsis + candidate_size = measure_text_cached(font, candidate, font_size) + if candidate_size.x <= rect.width: + left = mid + 1 + else: + right = mid + display_text = text[: left - 1] + ellipsis if left > 0 else ellipsis + text_size = measure_text_cached(font, display_text, font_size) + + # Calculate horizontal position based on alignment + text_x = rect.x + { + rl.GuiTextAlignment.TEXT_ALIGN_LEFT: 0, + rl.GuiTextAlignment.TEXT_ALIGN_CENTER: (rect.width - text_size.x) / 2, + rl.GuiTextAlignment.TEXT_ALIGN_RIGHT: rect.width - text_size.x, + }.get(alignment, 0) + + # Calculate vertical position based on alignment + text_y = rect.y + { + rl.GuiTextAlignmentVertical.TEXT_ALIGN_TOP: 0, + rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE: (rect.height - text_size.y) / 2, + rl.GuiTextAlignmentVertical.TEXT_ALIGN_BOTTOM: rect.height - text_size.y, + }.get(alignment_vertical, 0) + + # Draw the text in the specified rectangle + rl.draw_text_ex(font, display_text, rl.Vector2(text_x, text_y), font_size, 0, color) + + +def gui_text_box( + rect: rl.Rectangle, + text: str, + font_size: int = DEFAULT_TEXT_SIZE, + color: rl.Color = DEFAULT_TEXT_COLOR, + alignment: int = rl.GuiTextAlignment.TEXT_ALIGN_LEFT, + alignment_vertical: int = rl.GuiTextAlignmentVertical.TEXT_ALIGN_TOP, + font_weight: FontWeight = FontWeight.NORMAL, +): + styles = [ + (rl.GuiControl.DEFAULT, rl.GuiControlProperty.TEXT_COLOR_NORMAL, rl.color_to_int(color)), + (rl.GuiControl.DEFAULT, rl.GuiDefaultProperty.TEXT_SIZE, font_size), + (rl.GuiControl.DEFAULT, rl.GuiDefaultProperty.TEXT_LINE_SPACING, font_size), + (rl.GuiControl.DEFAULT, rl.GuiControlProperty.TEXT_ALIGNMENT, alignment), + (rl.GuiControl.DEFAULT, rl.GuiDefaultProperty.TEXT_ALIGNMENT_VERTICAL, alignment_vertical), + (rl.GuiControl.DEFAULT, rl.GuiDefaultProperty.TEXT_WRAP_MODE, rl.GuiTextWrapMode.TEXT_WRAP_WORD) + ] + if font_weight != FontWeight.NORMAL: + rl.gui_set_font(gui_app.font(font_weight)) + + with GuiStyleContext(styles): + rl.gui_label(rect, text) + + if font_weight != FontWeight.NORMAL: + rl.gui_set_font(gui_app.font(FontWeight.NORMAL)) + + +# Non-interactive text area. Can render emojis and an optional specified icon. +class Label(Widget): + def __init__(self, + text: str, + font_size: int = DEFAULT_TEXT_SIZE, + font_weight: FontWeight = FontWeight.NORMAL, + text_alignment: TextAlignment = TextAlignment.CENTER, + text_padding: int = 20, + text_color: rl.Color = DEFAULT_TEXT_COLOR, + icon = None, + ): + + super().__init__() + self._font_weight = font_weight + self._font = gui_app.font(self._font_weight) + self._font_size = font_size + self._text_alignment = text_alignment + self._text_padding = text_padding + self._text_color = text_color + self._icon = icon + self.set_text(text) + + def set_text(self, text): + self._text_raw = text + self._update_text(self._text_raw) + + def set_text_color(self, color): + self._text_color = color + + def _update_layout_rects(self): + self._update_text(self._text_raw) + + def _update_text(self, text): + self._emojis = [] + self._text_size = [] + self._text = wrap_text(self._font, text, self._font_size, self._rect.width - (self._text_padding*2)) + for t in self._text: + self._emojis.append(find_emoji(t)) + self._text_size.append(measure_text_cached(self._font, t, self._font_size)) + + def _render(self, _): + text = self._text[0] if self._text else None + text_size = self._text_size[0] if self._text_size else rl.Vector2(0.0, 0.0) + text_pos = rl.Vector2(0, (self._rect.y + (self._rect.height - (text_size.y)) // 2)) + + if self._icon: + icon_y = self._rect.y + (self._rect.height - self._icon.height) / 2 + if text: + if self._text_alignment == TextAlignment.LEFT: + icon_x = self._rect.x + self._text_padding + text_pos.x = self._icon.width + ICON_PADDING + elif self._text_alignment == TextAlignment.CENTER: + total_width = self._icon.width + ICON_PADDING + text_size.x + icon_x = self._rect.x + (self._rect.width - total_width) / 2 + text_pos.x = self._icon.width + ICON_PADDING + else: + icon_x = (self._rect.x + self._rect.width - text_size.x - self._text_padding) - ICON_PADDING - self._icon.width + else: + icon_x = self._rect.x + (self._rect.width - self._icon.width) / 2 + rl.draw_texture_v(self._icon, rl.Vector2(icon_x, icon_y), rl.WHITE) + + for text, text_size, emojis in zip_longest(self._text, self._text_size, self._emojis, fillvalue=[]): + line_pos = rl.Vector2(text_pos.x, text_pos.y) + if self._text_alignment == TextAlignment.LEFT: + line_pos.x += self._rect.x + self._text_padding + elif self._text_alignment == TextAlignment.CENTER: + line_pos.x += self._rect.x + (self._rect.width - text_size.x) // 2 + elif self._text_alignment == TextAlignment.RIGHT: + line_pos.x += self._rect.x + self._rect.width - text_size.x - self._text_padding + + prev_index = 0 + for start, end, emoji in emojis: + text_before = text[prev_index:start] + width_before = measure_text_cached(self._font, text_before, self._font_size) + rl.draw_text_ex(self._font, text_before, line_pos, self._font_size, 0, self._text_color) + line_pos.x += width_before.x + + tex = emoji_tex(emoji) + rl.draw_texture_ex(tex, line_pos, 0.0, self._font_size / tex.height, self._text_color) + line_pos.x += self._font_size + prev_index = end + rl.draw_text_ex(self._font, text[prev_index:], line_pos, self._font_size, 0, self._text_color) + text_pos.y += text_size.y or self._font_size diff --git a/system/ui/widgets/list_view.py b/system/ui/widgets/list_view.py new file mode 100644 index 0000000000..509c49be35 --- /dev/null +++ b/system/ui/widgets/list_view.py @@ -0,0 +1,426 @@ +import os +import pyray as rl +from collections.abc import Callable +from abc import ABC +from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos +from openpilot.system.ui.lib.text_measure import measure_text_cached +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle +from openpilot.system.ui.widgets.toggle import Toggle, WIDTH as TOGGLE_WIDTH, HEIGHT as TOGGLE_HEIGHT +from openpilot.system.ui.widgets.label import gui_label +from openpilot.system.ui.widgets.html_render import HtmlRenderer, ElementType + +ITEM_BASE_WIDTH = 600 +ITEM_BASE_HEIGHT = 170 +ITEM_PADDING = 20 +ITEM_TEXT_FONT_SIZE = 50 +ITEM_TEXT_COLOR = rl.WHITE +ITEM_TEXT_VALUE_COLOR = rl.Color(170, 170, 170, 255) +ITEM_DESC_TEXT_COLOR = rl.Color(128, 128, 128, 255) +ITEM_DESC_FONT_SIZE = 40 +ITEM_DESC_V_OFFSET = 140 +RIGHT_ITEM_PADDING = 20 +ICON_SIZE = 80 +BUTTON_WIDTH = 250 +BUTTON_HEIGHT = 100 +BUTTON_BORDER_RADIUS = 50 +BUTTON_FONT_SIZE = 35 +BUTTON_FONT_WEIGHT = FontWeight.MEDIUM + +TEXT_PADDING = 20 + + +def _resolve_value(value, default=""): + if callable(value): + return value() + return value if value is not None else default + + +# Abstract base class for right-side items +class ItemAction(Widget, ABC): + def __init__(self, width: int = BUTTON_HEIGHT, enabled: bool | Callable[[], bool] = True): + super().__init__() + self.set_rect(rl.Rectangle(0, 0, width, 0)) + self._enabled_source = enabled + + def get_width_hint(self) -> float: + # Return's action ideal width, 0 means use full width + return self._rect.width + + def set_enabled(self, enabled: bool | Callable[[], bool]): + self._enabled_source = enabled + + @property + def enabled(self): + return _resolve_value(self._enabled_source, False) + + +class ToggleAction(ItemAction): + def __init__(self, initial_state: bool = False, width: int = TOGGLE_WIDTH, enabled: bool | Callable[[], bool] = True): + super().__init__(width, enabled) + self.toggle = Toggle(initial_state=initial_state) + self.state = initial_state + + def set_touch_valid_callback(self, touch_callback: Callable[[], bool]) -> None: + super().set_touch_valid_callback(touch_callback) + self.toggle.set_touch_valid_callback(touch_callback) + + def _render(self, rect: rl.Rectangle) -> bool: + self.toggle.set_enabled(self.enabled) + clicked = self.toggle.render(rl.Rectangle(rect.x, rect.y + (rect.height - TOGGLE_HEIGHT) / 2, self._rect.width, TOGGLE_HEIGHT)) + self.state = self.toggle.get_state() + return bool(clicked) + + def set_state(self, state: bool): + self.state = state + self.toggle.set_state(state) + + def get_state(self) -> bool: + return self.state + + +class ButtonAction(ItemAction): + def __init__(self, text: str | Callable[[], str], width: int = BUTTON_WIDTH, enabled: bool | Callable[[], bool] = True): + super().__init__(width, enabled) + self._text_source = text + self._value_source: str | Callable[[], str] | None = None + self._pressed = False + self._font = gui_app.font(FontWeight.NORMAL) + + def pressed(): + self._pressed = True + + self._button = Button( + self.text, + font_size=BUTTON_FONT_SIZE, + font_weight=BUTTON_FONT_WEIGHT, + button_style=ButtonStyle.LIST_ACTION, + border_radius=BUTTON_BORDER_RADIUS, + click_callback=pressed, + ) + self.set_enabled(enabled) + + def set_touch_valid_callback(self, touch_callback: Callable[[], bool]) -> None: + super().set_touch_valid_callback(touch_callback) + self._button.set_touch_valid_callback(touch_callback) + + def set_text(self, text: str | Callable[[], str]): + self._text_source = text + + def set_value(self, value: str | Callable[[], str]): + self._value_source = value + + @property + def text(self): + return _resolve_value(self._text_source, "Error") + + @property + def value(self): + return _resolve_value(self._value_source, "") + + def _render(self, rect: rl.Rectangle) -> bool: + self._button.set_text(self.text) + self._button.set_enabled(_resolve_value(self.enabled)) + button_rect = rl.Rectangle(rect.x, rect.y + (rect.height - BUTTON_HEIGHT) / 2, BUTTON_WIDTH, BUTTON_HEIGHT) + self._button.render(button_rect) + + value_text = self.value + if value_text: + spacing = 20 + text_size = measure_text_cached(self._font, value_text, ITEM_TEXT_FONT_SIZE) + text_x = button_rect.x - spacing - text_size.x + text_y = rect.y + (rect.height - text_size.y) / 2 + rl.draw_text_ex(self._font, value_text, rl.Vector2(text_x, text_y), ITEM_TEXT_FONT_SIZE, 0, ITEM_TEXT_VALUE_COLOR) + + # TODO: just use the generic Widget click callbacks everywhere, no returning from render + pressed = self._pressed + self._pressed = False + return pressed + + +class TextAction(ItemAction): + def __init__(self, text: str | Callable[[], str], color: rl.Color = ITEM_TEXT_COLOR, enabled: bool | Callable[[], bool] = True): + self._text_source = text + self.color = color + + self._font = gui_app.font(FontWeight.NORMAL) + initial_text = _resolve_value(text, "") + text_width = measure_text_cached(self._font, initial_text, ITEM_TEXT_FONT_SIZE).x + super().__init__(int(text_width + TEXT_PADDING), enabled) + + @property + def text(self): + return _resolve_value(self._text_source, "Error") + + def get_width_hint(self) -> float: + text_width = measure_text_cached(self._font, self.text, ITEM_TEXT_FONT_SIZE).x + return text_width + TEXT_PADDING + + def _render(self, rect: rl.Rectangle) -> bool: + gui_label(self._rect, self.text, font_size=ITEM_TEXT_FONT_SIZE, color=self.color, + font_weight=FontWeight.NORMAL, alignment=rl.GuiTextAlignment.TEXT_ALIGN_RIGHT, + alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE) + return False + + def set_text(self, text: str | Callable[[], str]): + self._text_source = text + + def get_width(self) -> int: + text_width = measure_text_cached(self._font, self.text, ITEM_TEXT_FONT_SIZE).x + return int(text_width + TEXT_PADDING) + + +class DualButtonAction(ItemAction): + def __init__(self, left_text: str, right_text: str, left_callback: Callable = None, + right_callback: Callable = None, enabled: bool | Callable[[], bool] = True): + super().__init__(width=0, enabled=enabled) # Width 0 means use full width + self.left_text, self.right_text = left_text, right_text + + self.left_button = Button(left_text, click_callback=left_callback, button_style=ButtonStyle.LIST_ACTION) + self.right_button = Button(right_text, click_callback=right_callback, button_style=ButtonStyle.DANGER) + + def set_touch_valid_callback(self, touch_callback: Callable[[], bool]) -> None: + super().set_touch_valid_callback(touch_callback) + self.left_button.set_touch_valid_callback(touch_callback) + self.right_button.set_touch_valid_callback(touch_callback) + + def _render(self, rect: rl.Rectangle): + button_spacing = 30 + button_height = 120 + button_width = (rect.width - button_spacing) / 2 + button_y = rect.y + (rect.height - button_height) / 2 + + left_rect = rl.Rectangle(rect.x, button_y, button_width, button_height) + right_rect = rl.Rectangle(rect.x + button_width + button_spacing, button_y, button_width, button_height) + + # Render buttons + self.left_button.render(left_rect) + self.right_button.render(right_rect) + + +class MultipleButtonAction(ItemAction): + def __init__(self, buttons: list[str], button_width: int, selected_index: int = 0, callback: Callable = None): + super().__init__(width=len(buttons) * button_width + (len(buttons) - 1) * RIGHT_ITEM_PADDING, enabled=True) + self.buttons = buttons + self.button_width = button_width + self.selected_button = selected_index + self.callback = callback + self._font = gui_app.font(FontWeight.MEDIUM) + + def _render(self, rect: rl.Rectangle): + spacing = RIGHT_ITEM_PADDING + button_y = rect.y + (rect.height - BUTTON_HEIGHT) / 2 + + for i, text in enumerate(self.buttons): + button_x = rect.x + i * (self.button_width + spacing) + button_rect = rl.Rectangle(button_x, button_y, self.button_width, BUTTON_HEIGHT) + + # Check button state + mouse_pos = rl.get_mouse_position() + is_pressed = rl.check_collision_point_rec(mouse_pos, button_rect) and self.enabled and self.is_pressed + is_selected = i == self.selected_button + + # Button colors + if is_selected: + bg_color = rl.Color(51, 171, 76, 255) # Green + elif is_pressed: + bg_color = rl.Color(74, 74, 74, 255) # Dark gray + else: + bg_color = rl.Color(57, 57, 57, 255) # Gray + + if not self.enabled: + bg_color = rl.Color(bg_color.r, bg_color.g, bg_color.b, 150) # Dim + + # Draw button + rl.draw_rectangle_rounded(button_rect, 1.0, 20, bg_color) + + # Draw text + text_size = measure_text_cached(self._font, text, 40) + text_x = button_x + (self.button_width - text_size.x) / 2 + text_y = button_y + (BUTTON_HEIGHT - text_size.y) / 2 + text_color = rl.Color(228, 228, 228, 255) if self.enabled else rl.Color(150, 150, 150, 255) + rl.draw_text_ex(self._font, text, rl.Vector2(text_x, text_y), 40, 0, text_color) + + def _handle_mouse_release(self, mouse_pos: MousePos): + spacing = RIGHT_ITEM_PADDING + button_y = self._rect.y + (self._rect.height - BUTTON_HEIGHT) / 2 + for i, _text in enumerate(self.buttons): + button_x = self._rect.x + i * (self.button_width + spacing) + button_rect = rl.Rectangle(button_x, button_y, self.button_width, BUTTON_HEIGHT) + if rl.check_collision_point_rec(mouse_pos, button_rect): + self.selected_button = i + if self.callback: + self.callback(i) + + +class ListItem(Widget): + def __init__(self, title: str = "", icon: str | None = None, description: str | Callable[[], str] | None = None, + description_visible: bool = False, callback: Callable | None = None, + action_item: ItemAction | None = None): + super().__init__() + self.title = title + self.icon = icon + self._description = description + self.description_visible = description_visible + self.callback = callback + self.action_item = action_item + + self.set_rect(rl.Rectangle(0, 0, ITEM_BASE_WIDTH, ITEM_BASE_HEIGHT)) + self._font = gui_app.font(FontWeight.NORMAL) + self._icon_texture = gui_app.texture(os.path.join("icons", self.icon), ICON_SIZE, ICON_SIZE) if self.icon else None + + self._html_renderer = HtmlRenderer(text="", text_size={ElementType.P: ITEM_DESC_FONT_SIZE}, + text_color=ITEM_DESC_TEXT_COLOR) + self.set_description(self.description) + + # Cached properties for performance + self._prev_description: str | None = self.description + + def set_touch_valid_callback(self, touch_callback: Callable[[], bool]) -> None: + super().set_touch_valid_callback(touch_callback) + if self.action_item: + self.action_item.set_touch_valid_callback(touch_callback) + + def set_parent_rect(self, parent_rect: rl.Rectangle): + super().set_parent_rect(parent_rect) + self._rect.width = parent_rect.width + + def _handle_mouse_release(self, mouse_pos: MousePos): + if not self.is_visible: + return + + # Check not in action rect + if self.action_item: + action_rect = self.get_right_item_rect(self._rect) + if rl.check_collision_point_rec(mouse_pos, action_rect): + # Click was on right item, don't toggle description + return + + if self.description: + self.description_visible = not self.description_visible + content_width = int(self._rect.width - ITEM_PADDING * 2) + self._rect.height = self.get_item_height(self._font, content_width) + + def _update_state(self): + # Detect changes if description is callback + new_description = self.description + if new_description != self._prev_description: + self.set_description(new_description) + + def _render(self, _): + if not self.is_visible: + return + + # Don't draw items that are not in parent's viewport + if ((self._rect.y + self.rect.height) <= self._parent_rect.y or + self._rect.y >= (self._parent_rect.y + self._parent_rect.height)): + return + + content_x = self._rect.x + ITEM_PADDING + text_x = content_x + + # Only draw title and icon for items that have them + if self.title: + # Draw icon if present + if self.icon: + rl.draw_texture(self._icon_texture, int(content_x), int(self._rect.y + (ITEM_BASE_HEIGHT - self._icon_texture.width) // 2), rl.WHITE) + text_x += ICON_SIZE + ITEM_PADDING + + # Draw main text + text_size = measure_text_cached(self._font, self.title, ITEM_TEXT_FONT_SIZE) + item_y = self._rect.y + (ITEM_BASE_HEIGHT - text_size.y) // 2 + rl.draw_text_ex(self._font, self.title, rl.Vector2(text_x, item_y), ITEM_TEXT_FONT_SIZE, 0, ITEM_TEXT_COLOR) + + # Draw description if visible + if self.description_visible: + content_width = int(self._rect.width - ITEM_PADDING * 2) + description_height = self._html_renderer.get_total_height(content_width) + description_rect = rl.Rectangle( + self._rect.x + ITEM_PADDING, + self._rect.y + ITEM_DESC_V_OFFSET, + content_width, + description_height + ) + self._html_renderer.render(description_rect) + + # Draw right item if present + if self.action_item: + right_rect = self.get_right_item_rect(self._rect) + right_rect.y = self._rect.y + if self.action_item.render(right_rect) and self.action_item.enabled: + # Right item was clicked/activated + if self.callback: + self.callback() + + def set_description(self, description: str | Callable[[], str] | None): + self._description = description + new_desc = self.description + self._html_renderer.parse_html_content(new_desc) + self._prev_description = new_desc + + @property + def description(self): + return _resolve_value(self._description, "") + + def get_item_height(self, font: rl.Font, max_width: int) -> float: + if not self.is_visible: + return 0 + + height = float(ITEM_BASE_HEIGHT) + if self.description_visible: + description_height = self._html_renderer.get_total_height(max_width) + height += description_height - (ITEM_BASE_HEIGHT - ITEM_DESC_V_OFFSET) + ITEM_PADDING + return height + + def get_right_item_rect(self, item_rect: rl.Rectangle) -> rl.Rectangle: + if not self.action_item: + return rl.Rectangle(0, 0, 0, 0) + + right_width = self.action_item.get_width_hint() + if right_width == 0: # Full width action (like DualButtonAction) + return rl.Rectangle(item_rect.x + ITEM_PADDING, item_rect.y, + item_rect.width - (ITEM_PADDING * 2), ITEM_BASE_HEIGHT) + + # Clip width to available space, never overlapping this Item's title + content_width = item_rect.width - (ITEM_PADDING * 2) + title_width = measure_text_cached(self._font, self.title, ITEM_TEXT_FONT_SIZE).x + right_width = min(content_width - title_width, right_width) + + right_x = item_rect.x + item_rect.width - right_width + right_y = item_rect.y + return rl.Rectangle(right_x, right_y, right_width, ITEM_BASE_HEIGHT) + + +# Factory functions +def simple_item(title: str, callback: Callable | None = None) -> ListItem: + return ListItem(title=title, callback=callback) + + +def toggle_item(title: str, description: str | Callable[[], str] | None = None, initial_state: bool = False, + callback: Callable | None = None, icon: str = "", enabled: bool | Callable[[], bool] = True) -> ListItem: + action = ToggleAction(initial_state=initial_state, enabled=enabled) + return ListItem(title=title, description=description, action_item=action, icon=icon, callback=callback) + + +def button_item(title: str, button_text: str | Callable[[], str], description: str | Callable[[], str] | None = None, + callback: Callable | None = None, enabled: bool | Callable[[], bool] = True) -> ListItem: + action = ButtonAction(text=button_text, enabled=enabled) + return ListItem(title=title, description=description, action_item=action, callback=callback) + + +def text_item(title: str, value: str | Callable[[], str], description: str | Callable[[], str] | None = None, + callback: Callable | None = None, enabled: bool | Callable[[], bool] = True) -> ListItem: + action = TextAction(text=value, color=ITEM_TEXT_VALUE_COLOR, enabled=enabled) + return ListItem(title=title, description=description, action_item=action, callback=callback) + + +def dual_button_item(left_text: str, right_text: str, left_callback: Callable = None, right_callback: Callable = None, + description: str | Callable[[], str] | None = None, enabled: bool | Callable[[], bool] = True) -> ListItem: + action = DualButtonAction(left_text, right_text, left_callback, right_callback, enabled) + return ListItem(title="", description=description, action_item=action) + + +def multiple_button_item(title: str, description: str, buttons: list[str], selected_index: int, + button_width: int = BUTTON_WIDTH, callback: Callable = None, icon: str = ""): + action = MultipleButtonAction(buttons, button_width, selected_index, callback=callback) + return ListItem(title=title, description=description, icon=icon, action_item=action) diff --git a/system/ui/widgets/network.py b/system/ui/widgets/network.py new file mode 100644 index 0000000000..85b98f10ac --- /dev/null +++ b/system/ui/widgets/network.py @@ -0,0 +1,483 @@ +from enum import IntEnum +from functools import partial +from typing import cast + +import pyray as rl +from openpilot.system.ui.lib.application import gui_app +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.lib.wifi_manager import WifiManager, SecurityType, Network, MeteredType +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import ButtonStyle, Button +from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog +from openpilot.system.ui.widgets.keyboard import Keyboard +from openpilot.system.ui.widgets.label import TextAlignment, gui_label +from openpilot.system.ui.widgets.scroller import Scroller +from openpilot.system.ui.widgets.list_view import ButtonAction, ListItem, MultipleButtonAction, ToggleAction, button_item, text_item + +# These are only used for AdvancedNetworkSettings, standalone apps just need WifiManagerUI +try: + from openpilot.common.params import Params + from openpilot.selfdrive.ui.ui_state import ui_state + from openpilot.selfdrive.ui.lib.prime_state import PrimeType +except Exception: + Params = None + ui_state = None # type: ignore + PrimeType = None # type: ignore + +NM_DEVICE_STATE_NEED_AUTH = 60 +MIN_PASSWORD_LENGTH = 8 +MAX_PASSWORD_LENGTH = 64 +ITEM_HEIGHT = 160 +ICON_SIZE = 50 + +STRENGTH_ICONS = [ + "icons/wifi_strength_low.png", + "icons/wifi_strength_medium.png", + "icons/wifi_strength_high.png", + "icons/wifi_strength_full.png", +] + + +class PanelType(IntEnum): + WIFI = 0 + ADVANCED = 1 + + +class UIState(IntEnum): + IDLE = 0 + CONNECTING = 1 + NEEDS_AUTH = 2 + SHOW_FORGET_CONFIRM = 3 + FORGETTING = 4 + + +class NavButton(Widget): + def __init__(self, text: str): + super().__init__() + self.text = text + self.set_rect(rl.Rectangle(0, 0, 400, 100)) + + def _render(self, _): + color = rl.Color(74, 74, 74, 255) if self.is_pressed else rl.Color(57, 57, 57, 255) + rl.draw_rectangle_rounded(self._rect, 0.6, 10, color) + gui_label(self.rect, self.text, font_size=60, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) + + +class NetworkUI(Widget): + def __init__(self, wifi_manager: WifiManager): + super().__init__() + self._wifi_manager = wifi_manager + self._current_panel: PanelType = PanelType.WIFI + self._wifi_panel = WifiManagerUI(wifi_manager) + self._advanced_panel = AdvancedNetworkSettings(wifi_manager) + self._nav_button = NavButton("Advanced") + self._nav_button.set_click_callback(self._cycle_panel) + + def show_event(self): + self._set_current_panel(PanelType.WIFI) + self._wifi_panel.show_event() + + def hide_event(self): + self._wifi_panel.hide_event() + + def _cycle_panel(self): + if self._current_panel == PanelType.WIFI: + self._set_current_panel(PanelType.ADVANCED) + else: + self._set_current_panel(PanelType.WIFI) + + def _render(self, _): + # subtract button + content_rect = rl.Rectangle(self._rect.x, self._rect.y + self._nav_button.rect.height + 20, + self._rect.width, self._rect.height - self._nav_button.rect.height - 20) + if self._current_panel == PanelType.WIFI: + self._nav_button.text = "Advanced" + self._nav_button.set_position(self._rect.x + self._rect.width - self._nav_button.rect.width, self._rect.y + 10) + self._wifi_panel.render(content_rect) + else: + self._nav_button.text = "Back" + self._nav_button.set_position(self._rect.x, self._rect.y + 10) + self._advanced_panel.render(content_rect) + + self._nav_button.render() + + def _set_current_panel(self, panel: PanelType): + self._current_panel = panel + + +class AdvancedNetworkSettings(Widget): + def __init__(self, wifi_manager: WifiManager): + super().__init__() + self._wifi_manager = wifi_manager + self._wifi_manager.set_callbacks(networks_updated=self._on_network_updated) + self._params = Params() + + self._keyboard = Keyboard(max_text_size=MAX_PASSWORD_LENGTH, min_text_size=MIN_PASSWORD_LENGTH, show_password_toggle=True) + + # Tethering + self._tethering_action = ToggleAction(initial_state=False) + tethering_btn = ListItem(title="Enable Tethering", action_item=self._tethering_action, callback=self._toggle_tethering) + + # Edit tethering password + self._tethering_password_action = ButtonAction(text="EDIT") + tethering_password_btn = ListItem(title="Tethering Password", action_item=self._tethering_password_action, callback=self._edit_tethering_password) + + # Roaming toggle + roaming_enabled = self._params.get_bool("GsmRoaming") + self._roaming_action = ToggleAction(initial_state=roaming_enabled) + self._roaming_btn = ListItem(title="Enable Roaming", action_item=self._roaming_action, callback=self._toggle_roaming) + + # Cellular metered toggle + cellular_metered = self._params.get_bool("GsmMetered") + self._cellular_metered_action = ToggleAction(initial_state=cellular_metered) + self._cellular_metered_btn = ListItem(title="Cellular Metered", description="Prevent large data uploads when on a metered cellular connection", + action_item=self._cellular_metered_action, callback=self._toggle_cellular_metered) + + # APN setting + self._apn_btn = button_item("APN Setting", "EDIT", callback=self._edit_apn) + + # Wi-Fi metered toggle + self._wifi_metered_action = MultipleButtonAction(["default", "metered", "unmetered"], 255, 0, callback=self._toggle_wifi_metered) + wifi_metered_btn = ListItem(title="Wi-Fi Network Metered", description="Prevent large data uploads when on a metered Wi-Fi connection", + action_item=self._wifi_metered_action) + + items: list[Widget] = [ + tethering_btn, + tethering_password_btn, + text_item("IP Address", lambda: self._wifi_manager.ipv4_address), + self._roaming_btn, + self._apn_btn, + self._cellular_metered_btn, + wifi_metered_btn, + button_item("Hidden Network", "CONNECT", callback=self._connect_to_hidden_network), + ] + + self._scroller = Scroller(items, line_separator=True, spacing=0) + + # Set initial config + metered = self._params.get_bool("GsmMetered") + self._wifi_manager.update_gsm_settings(roaming_enabled, self._params.get("GsmApn") or "", metered) + + def _on_network_updated(self, networks: list[Network]): + self._tethering_action.set_enabled(True) + self._tethering_action.set_state(self._wifi_manager.is_tethering_active()) + self._tethering_password_action.set_enabled(True) + + if self._wifi_manager.is_tethering_active() or self._wifi_manager.ipv4_address == "": + self._wifi_metered_action.set_enabled(False) + self._wifi_metered_action.selected_button = 0 + elif self._wifi_manager.ipv4_address != "": + metered = self._wifi_manager.current_network_metered + self._wifi_metered_action.set_enabled(True) + self._wifi_metered_action.selected_button = int(metered) if metered in (MeteredType.UNKNOWN, MeteredType.YES, MeteredType.NO) else 0 + + def _toggle_tethering(self): + checked = self._tethering_action.state + self._tethering_action.set_enabled(False) + if checked: + self._wifi_metered_action.set_enabled(False) + self._wifi_manager.set_tethering_active(checked) + + def _toggle_roaming(self): + roaming_state = self._roaming_action.state + self._params.put_bool("GsmRoaming", roaming_state) + self._wifi_manager.update_gsm_settings(roaming_state, self._params.get("GsmApn") or "", self._params.get_bool("GsmMetered")) + + def _edit_apn(self): + def update_apn(result): + if result != 1: + return + + apn = self._keyboard.text.strip() + if apn == "": + self._params.remove("GsmApn") + else: + self._params.put("GsmApn", apn) + + self._wifi_manager.update_gsm_settings(self._params.get_bool("GsmRoaming"), apn, self._params.get_bool("GsmMetered")) + + current_apn = self._params.get("GsmApn") or "" + self._keyboard.reset(min_text_size=0) + self._keyboard.set_title("Enter APN", "leave blank for automatic configuration") + self._keyboard.set_text(current_apn) + gui_app.set_modal_overlay(self._keyboard, update_apn) + + def _toggle_cellular_metered(self): + metered = self._cellular_metered_action.state + self._params.put_bool("GsmMetered", metered) + self._wifi_manager.update_gsm_settings(self._params.get_bool("GsmRoaming"), self._params.get("GsmApn") or "", metered) + + def _toggle_wifi_metered(self, metered): + metered_type = {0: MeteredType.UNKNOWN, 1: MeteredType.YES, 2: MeteredType.NO}.get(metered, MeteredType.UNKNOWN) + self._wifi_metered_action.set_enabled(False) + self._wifi_manager.set_current_network_metered(metered_type) + + def _connect_to_hidden_network(self): + def connect_hidden(result): + if result != 1: + return + + ssid = self._keyboard.text + if not ssid: + return + + def enter_password(result): + password = self._keyboard.text + if password == "": + # connect without password + self._wifi_manager.connect_to_network(ssid, "", hidden=True) + return + + self._wifi_manager.connect_to_network(ssid, password, hidden=True) + + self._keyboard.reset(min_text_size=0) + self._keyboard.set_title("Enter password", f"for \"{ssid}\"") + gui_app.set_modal_overlay(self._keyboard, enter_password) + + self._keyboard.reset(min_text_size=1) + self._keyboard.set_title("Enter SSID", "") + gui_app.set_modal_overlay(self._keyboard, connect_hidden) + + def _edit_tethering_password(self): + def update_password(result): + if result != 1: + return + + password = self._keyboard.text + self._wifi_manager.set_tethering_password(password) + self._tethering_password_action.set_enabled(False) + + self._keyboard.reset(min_text_size=MIN_PASSWORD_LENGTH) + self._keyboard.set_title("Enter new tethering password", "") + self._keyboard.set_text(self._wifi_manager.tethering_password) + gui_app.set_modal_overlay(self._keyboard, update_password) + + def _update_state(self): + self._wifi_manager.process_callbacks() + + # If not using prime SIM, show GSM settings and enable IPv4 forwarding + show_cell_settings = ui_state.prime_state.get_type() in (PrimeType.NONE, PrimeType.LITE) + self._wifi_manager.set_ipv4_forward(show_cell_settings) + self._roaming_btn.set_visible(show_cell_settings) + self._apn_btn.set_visible(show_cell_settings) + self._cellular_metered_btn.set_visible(show_cell_settings) + + def _render(self, _): + self._scroller.render(self._rect) + + +class WifiManagerUI(Widget): + def __init__(self, wifi_manager: WifiManager): + super().__init__() + self._wifi_manager = wifi_manager + self.state: UIState = UIState.IDLE + self._state_network: Network | None = None # for CONNECTING / NEEDS_AUTH / SHOW_FORGET_CONFIRM / FORGETTING + self._password_retry: bool = False # for NEEDS_AUTH + self.btn_width: int = 200 + self.scroll_panel = GuiScrollPanel() + self.keyboard = Keyboard(max_text_size=MAX_PASSWORD_LENGTH, min_text_size=MIN_PASSWORD_LENGTH, show_password_toggle=True) + self._load_icons() + + self._networks: list[Network] = [] + self._networks_buttons: dict[str, Button] = {} + self._forget_networks_buttons: dict[str, Button] = {} + self._confirm_dialog = ConfirmDialog("", "Forget", "Cancel") + + self._wifi_manager.set_callbacks(need_auth=self._on_need_auth, + activated=self._on_activated, + forgotten=self._on_forgotten, + networks_updated=self._on_network_updated, + disconnected=self._on_disconnected) + + def show_event(self): + # start/stop scanning when widget is visible + self._wifi_manager.set_active(True) + + def hide_event(self): + self._wifi_manager.set_active(False) + + def _load_icons(self): + for icon in STRENGTH_ICONS + ["icons/checkmark.png", "icons/circled_slash.png", "icons/lock_closed.png"]: + gui_app.texture(icon, ICON_SIZE, ICON_SIZE) + + def _update_state(self): + self._wifi_manager.process_callbacks() + + def _render(self, rect: rl.Rectangle): + if not self._networks: + gui_label(rect, "Scanning Wi-Fi networks...", 72, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) + return + + if self.state == UIState.NEEDS_AUTH and self._state_network: + self.keyboard.set_title("Wrong password" if self._password_retry else "Enter password", f"for {self._state_network.ssid}") + self.keyboard.reset(min_text_size=MIN_PASSWORD_LENGTH) + gui_app.set_modal_overlay(self.keyboard, lambda result: self._on_password_entered(cast(Network, self._state_network), result)) + elif self.state == UIState.SHOW_FORGET_CONFIRM and self._state_network: + self._confirm_dialog.set_text(f'Forget Wi-Fi Network "{self._state_network.ssid}"?') + self._confirm_dialog.reset() + gui_app.set_modal_overlay(self._confirm_dialog, callback=lambda result: self.on_forgot_confirm_finished(self._state_network, result)) + else: + self._draw_network_list(rect) + + def _on_password_entered(self, network: Network, result: int): + if result == 1: + password = self.keyboard.text + self.keyboard.clear() + + if len(password) >= MIN_PASSWORD_LENGTH: + self.connect_to_network(network, password) + elif result == 0: + self.state = UIState.IDLE + + def on_forgot_confirm_finished(self, network, result: int): + if result == 1: + self.forget_network(network) + elif result == 0: + self.state = UIState.IDLE + + def _draw_network_list(self, rect: rl.Rectangle): + content_rect = rl.Rectangle(rect.x, rect.y, rect.width, len(self._networks) * ITEM_HEIGHT) + offset = self.scroll_panel.update(rect, content_rect) + + rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height)) + for i, network in enumerate(self._networks): + y_offset = rect.y + i * ITEM_HEIGHT + offset + item_rect = rl.Rectangle(rect.x, y_offset, rect.width, ITEM_HEIGHT) + if not rl.check_collision_recs(item_rect, rect): + continue + + self._draw_network_item(item_rect, network) + if i < len(self._networks) - 1: + line_y = int(item_rect.y + item_rect.height - 1) + rl.draw_line(int(item_rect.x), int(line_y), int(item_rect.x + item_rect.width), line_y, rl.LIGHTGRAY) + + rl.end_scissor_mode() + + def _draw_network_item(self, rect, network: Network): + spacing = 50 + ssid_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, ITEM_HEIGHT) + signal_icon_rect = rl.Rectangle(rect.x + rect.width - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE) + security_icon_rect = rl.Rectangle(signal_icon_rect.x - spacing - ICON_SIZE, rect.y + (ITEM_HEIGHT - ICON_SIZE) / 2, ICON_SIZE, ICON_SIZE) + + status_text = "" + if self.state == UIState.CONNECTING and self._state_network: + if self._state_network.ssid == network.ssid: + self._networks_buttons[network.ssid].set_enabled(False) + status_text = "CONNECTING..." + elif self.state == UIState.FORGETTING and self._state_network: + if self._state_network.ssid == network.ssid: + self._networks_buttons[network.ssid].set_enabled(False) + status_text = "FORGETTING..." + elif network.security_type == SecurityType.UNSUPPORTED: + self._networks_buttons[network.ssid].set_enabled(False) + else: + self._networks_buttons[network.ssid].set_enabled(True) + + self._networks_buttons[network.ssid].render(ssid_rect) + + if status_text: + status_text_rect = rl.Rectangle(security_icon_rect.x - 410, rect.y, 410, ITEM_HEIGHT) + gui_label(status_text_rect, status_text, font_size=48, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER) + else: + # If the network is saved, show the "Forget" button + if network.is_saved: + forget_btn_rect = rl.Rectangle( + security_icon_rect.x - self.btn_width - spacing, + rect.y + (ITEM_HEIGHT - 80) / 2, + self.btn_width, + 80, + ) + self._forget_networks_buttons[network.ssid].render(forget_btn_rect) + + self._draw_status_icon(security_icon_rect, network) + self._draw_signal_strength_icon(signal_icon_rect, network) + + def _networks_buttons_callback(self, network): + if not network.is_saved and network.security_type != SecurityType.OPEN: + self.state = UIState.NEEDS_AUTH + self._state_network = network + self._password_retry = False + elif not network.is_connected: + self.connect_to_network(network) + + def _forget_networks_buttons_callback(self, network): + self.state = UIState.SHOW_FORGET_CONFIRM + self._state_network = network + + def _draw_status_icon(self, rect, network: Network): + """Draw the status icon based on network's connection state""" + icon_file = None + if network.is_connected and self.state != UIState.CONNECTING: + icon_file = "icons/checkmark.png" + elif network.security_type == SecurityType.UNSUPPORTED: + icon_file = "icons/circled_slash.png" + elif network.security_type != SecurityType.OPEN: + icon_file = "icons/lock_closed.png" + + if not icon_file: + return + + texture = gui_app.texture(icon_file, ICON_SIZE, ICON_SIZE) + icon_rect = rl.Vector2(rect.x, rect.y + (ICON_SIZE - texture.height) / 2) + rl.draw_texture_v(texture, icon_rect, rl.WHITE) + + def _draw_signal_strength_icon(self, rect: rl.Rectangle, network: Network): + """Draw the Wi-Fi signal strength icon based on network's signal strength""" + strength_level = max(0, min(3, round(network.strength / 33.0))) + rl.draw_texture_v(gui_app.texture(STRENGTH_ICONS[strength_level], ICON_SIZE, ICON_SIZE), rl.Vector2(rect.x, rect.y), rl.WHITE) + + def connect_to_network(self, network: Network, password=''): + self.state = UIState.CONNECTING + self._state_network = network + if network.is_saved and not password: + self._wifi_manager.activate_connection(network.ssid) + else: + self._wifi_manager.connect_to_network(network.ssid, password) + + def forget_network(self, network: Network): + self.state = UIState.FORGETTING + self._state_network = network + self._wifi_manager.forget_connection(network.ssid) + + def _on_network_updated(self, networks: list[Network]): + self._networks = networks + for n in self._networks: + self._networks_buttons[n.ssid] = Button(n.ssid, partial(self._networks_buttons_callback, n), font_size=55, text_alignment=TextAlignment.LEFT, + button_style=ButtonStyle.TRANSPARENT_WHITE_TEXT) + self._networks_buttons[n.ssid].set_touch_valid_callback(lambda: self.scroll_panel.is_touch_valid()) + self._forget_networks_buttons[n.ssid] = Button("Forget", partial(self._forget_networks_buttons_callback, n), button_style=ButtonStyle.FORGET_WIFI, + font_size=45) + self._forget_networks_buttons[n.ssid].set_touch_valid_callback(lambda: self.scroll_panel.is_touch_valid()) + + def _on_need_auth(self, ssid): + network = next((n for n in self._networks if n.ssid == ssid), None) + if network: + self.state = UIState.NEEDS_AUTH + self._state_network = network + self._password_retry = True + + def _on_activated(self): + if self.state == UIState.CONNECTING: + self.state = UIState.IDLE + + def _on_forgotten(self): + if self.state == UIState.FORGETTING: + self.state = UIState.IDLE + + def _on_disconnected(self): + if self.state == UIState.CONNECTING: + self.state = UIState.IDLE + + +def main(): + gui_app.init_window("Wi-Fi Manager") + wifi_ui = WifiManagerUI(WifiManager()) + + for _ in gui_app.render(): + wifi_ui.render(rl.Rectangle(50, 50, gui_app.width - 100, gui_app.height - 100)) + + gui_app.close() + + +if __name__ == "__main__": + main() diff --git a/system/ui/widgets/option_dialog.py b/system/ui/widgets/option_dialog.py new file mode 100644 index 0000000000..604cd59fd0 --- /dev/null +++ b/system/ui/widgets/option_dialog.py @@ -0,0 +1,71 @@ +import pyray as rl +from openpilot.system.ui.lib.application import FontWeight, gui_app +from openpilot.system.ui.widgets import Widget +from openpilot.system.ui.widgets.button import Button, ButtonStyle, TextAlignment +from openpilot.system.ui.widgets.label import gui_label +from openpilot.system.ui.widgets.scroller import Scroller + +# Constants +MARGIN = 50 +TITLE_FONT_SIZE = 70 +ITEM_HEIGHT = 135 +BUTTON_SPACING = 50 +BUTTON_HEIGHT = 160 +ITEM_SPACING = 50 +LIST_ITEM_SPACING = 25 + + +class MultiOptionDialog(Widget): + def __init__(self, title, options, current=""): + super().__init__() + self.title = title + self.options = options + self.current = current + self.selection = current + + # Create scroller with option buttons + self.option_buttons = [Button(option, click_callback=lambda opt=option: self._on_option_clicked(opt), + text_alignment=TextAlignment.LEFT, button_style=ButtonStyle.NORMAL) for option in options] + self.scroller = Scroller(self.option_buttons, spacing=LIST_ITEM_SPACING) + + self.cancel_button = Button("Cancel", click_callback=lambda: gui_app.set_modal_overlay(None)) + self.select_button = Button("Select", click_callback=lambda: gui_app.set_modal_overlay(None), button_style=ButtonStyle.PRIMARY) + + def _on_option_clicked(self, option): + self.selection = option + + def _render(self, rect): + dialog_rect = rl.Rectangle(rect.x + MARGIN, rect.y + MARGIN, rect.width - 2 * MARGIN, rect.height - 2 * MARGIN) + rl.draw_rectangle_rounded(dialog_rect, 0.02, 20, rl.Color(30, 30, 30, 255)) + + content_rect = rl.Rectangle(dialog_rect.x + MARGIN, dialog_rect.y + MARGIN, + dialog_rect.width - 2 * MARGIN, dialog_rect.height - 2 * MARGIN) + + gui_label(rl.Rectangle(content_rect.x, content_rect.y, content_rect.width, TITLE_FONT_SIZE), self.title, 70, font_weight=FontWeight.BOLD) + + # Options area + options_y = content_rect.y + TITLE_FONT_SIZE + ITEM_SPACING + options_h = content_rect.height - TITLE_FONT_SIZE - BUTTON_HEIGHT - 2 * ITEM_SPACING + options_rect = rl.Rectangle(content_rect.x, options_y, content_rect.width, options_h) + + # Update button styles and set width based on selection + for i, option in enumerate(self.options): + selected = option == self.selection + button = self.option_buttons[i] + button.set_button_style(ButtonStyle.PRIMARY if selected else ButtonStyle.NORMAL) + button.set_rect(rl.Rectangle(0, 0, options_rect.width, ITEM_HEIGHT)) + + self.scroller.render(options_rect) + + # Buttons + button_y = content_rect.y + content_rect.height - BUTTON_HEIGHT + button_w = (content_rect.width - BUTTON_SPACING) / 2 + + cancel_rect = rl.Rectangle(content_rect.x, button_y, button_w, BUTTON_HEIGHT) + self.cancel_button.render(cancel_rect) + + select_rect = rl.Rectangle(content_rect.x + button_w + BUTTON_SPACING, button_y, button_w, BUTTON_HEIGHT) + self.select_button.set_enabled(self.selection != self.current) + self.select_button.render(select_rect) + + return -1 diff --git a/system/ui/widgets/scroller.py b/system/ui/widgets/scroller.py new file mode 100644 index 0000000000..c76f30d196 --- /dev/null +++ b/system/ui/widgets/scroller.py @@ -0,0 +1,78 @@ +import pyray as rl +from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel +from openpilot.system.ui.widgets import Widget + +ITEM_SPACING = 40 +LINE_COLOR = rl.GRAY +LINE_PADDING = 40 + + +class LineSeparator(Widget): + def __init__(self, height: int = 1): + super().__init__() + self._rect = rl.Rectangle(0, 0, 0, height) + + def set_parent_rect(self, parent_rect: rl.Rectangle) -> None: + super().set_parent_rect(parent_rect) + self._rect.width = parent_rect.width + + def _render(self, _): + rl.draw_line(int(self._rect.x) + LINE_PADDING, int(self._rect.y), + int(self._rect.x + self._rect.width) - LINE_PADDING * 2, int(self._rect.y), + LINE_COLOR) + + +class Scroller(Widget): + def __init__(self, items: list[Widget], spacing: int = ITEM_SPACING, line_separator: bool = False, pad_end: bool = True): + super().__init__() + self._items: list[Widget] = [] + self._spacing = spacing + self._line_separator = LineSeparator() if line_separator else None + self._pad_end = pad_end + + self.scroll_panel = GuiScrollPanel() + + for item in items: + self.add_widget(item) + + def add_widget(self, item: Widget) -> None: + self._items.append(item) + item.set_touch_valid_callback(self.scroll_panel.is_touch_valid) + + def _render(self, _): + # TODO: don't draw items that are not in the viewport + visible_items = [item for item in self._items if item.is_visible] + + # Add line separator between items + if self._line_separator is not None: + l = len(visible_items) + for i in range(1, len(visible_items)): + visible_items.insert(l - i, self._line_separator) + + content_height = sum(item.rect.height for item in visible_items) + self._spacing * (len(visible_items)) + if not self._pad_end: + content_height -= self._spacing + scroll = self.scroll_panel.update(self._rect, rl.Rectangle(0, 0, self._rect.width, content_height)) + + rl.begin_scissor_mode(int(self._rect.x), int(self._rect.y), + int(self._rect.width), int(self._rect.height)) + + cur_height = 0 + for idx, item in enumerate(visible_items): + if not item.is_visible: + continue + + # Nicely lay out items vertically + x = self._rect.x + y = self._rect.y + cur_height + self._spacing * (idx != 0) + cur_height += item.rect.height + self._spacing * (idx != 0) + + # Consider scroll + y += scroll + + # Update item state + item.set_position(x, y) + item.set_parent_rect(self._rect) + item.render() + + rl.end_scissor_mode() diff --git a/system/ui/widgets/toggle.py b/system/ui/widgets/toggle.py new file mode 100644 index 0000000000..968afda9c8 --- /dev/null +++ b/system/ui/widgets/toggle.py @@ -0,0 +1,77 @@ +import pyray as rl +from openpilot.system.ui.lib.application import MousePos +from openpilot.system.ui.widgets import Widget + +ON_COLOR = rl.Color(51, 171, 76, 255) +OFF_COLOR = rl.Color(0x39, 0x39, 0x39, 255) +KNOB_COLOR = rl.WHITE +DISABLED_ON_COLOR = rl.Color(0x22, 0x77, 0x22, 255) # Dark green when disabled + on +DISABLED_OFF_COLOR = rl.Color(0x39, 0x39, 0x39, 255) +DISABLED_KNOB_COLOR = rl.Color(0x88, 0x88, 0x88, 255) +WIDTH, HEIGHT = 160, 80 +BG_HEIGHT = 60 +ANIMATION_SPEED = 8.0 + + +class Toggle(Widget): + def __init__(self, initial_state=False): + super().__init__() + self._state = initial_state + self._enabled = True + self._progress = 1.0 if initial_state else 0.0 + self._target = self._progress + self._clicked = False + + def set_rect(self, rect: rl.Rectangle): + self._rect = rl.Rectangle(rect.x, rect.y, WIDTH, HEIGHT) + + def _handle_mouse_release(self, mouse_pos: MousePos): + if not self._enabled: + return + + self._clicked = True + self._state = not self._state + self._target = 1.0 if self._state else 0.0 + + def get_state(self): + return self._state + + def set_state(self, state: bool): + self._state = state + self._target = 1.0 if state else 0.0 + + def is_enabled(self): + return self._enabled + + def update(self): + if abs(self._progress - self._target) > 0.01: + delta = rl.get_frame_time() * ANIMATION_SPEED + self._progress += delta if self._progress < self._target else -delta + self._progress = max(0.0, min(1.0, self._progress)) + + def _render(self, rect: rl.Rectangle): + self.update() + + if self._enabled: + bg_color = self._blend_color(OFF_COLOR, ON_COLOR, self._progress) + knob_color = KNOB_COLOR + else: + bg_color = self._blend_color(DISABLED_OFF_COLOR, DISABLED_ON_COLOR, self._progress) + knob_color = DISABLED_KNOB_COLOR + + # Draw background + bg_rect = rl.Rectangle(self._rect.x + 5, self._rect.y + 10, WIDTH - 10, BG_HEIGHT) + rl.draw_rectangle_rounded(bg_rect, 1.0, 10, bg_color) + + # Draw knob + knob_x = self._rect.x + HEIGHT / 2 + (WIDTH - HEIGHT) * self._progress + knob_y = self._rect.y + HEIGHT / 2 + rl.draw_circle(int(knob_x), int(knob_y), HEIGHT / 2, knob_color) + + # TODO: use click callback + clicked = self._clicked + self._clicked = False + return clicked + + def _blend_color(self, c1, c2, t): + return rl.Color(int(c1.r + (c2.r - c1.r) * t), int(c1.g + (c2.g - c1.g) * t), int(c1.b + (c2.b - c1.b) * t), 255) diff --git a/system/updated/casync/casync.py b/system/updated/casync/casync.py new file mode 100755 index 0000000000..7a3303a9e9 --- /dev/null +++ b/system/updated/casync/casync.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +import io +import lzma +import os +import pathlib +import struct +import sys +import time +from abc import ABC, abstractmethod +from collections import defaultdict, namedtuple +from collections.abc import Callable +from typing import IO + +import requests +from Crypto.Hash import SHA512 +from openpilot.system.updated.casync import tar +from openpilot.system.updated.casync.common import create_casync_tar_package + +CA_FORMAT_INDEX = 0x96824d9c7b129ff9 +CA_FORMAT_TABLE = 0xe75b9e112f17417d +CA_FORMAT_TABLE_TAIL_MARKER = 0xe75b9e112f17417 +FLAGS = 0xb000000000000000 + +CA_HEADER_LEN = 48 +CA_TABLE_HEADER_LEN = 16 +CA_TABLE_ENTRY_LEN = 40 +CA_TABLE_MIN_LEN = CA_TABLE_HEADER_LEN + CA_TABLE_ENTRY_LEN + +CHUNK_DOWNLOAD_TIMEOUT = 60 +CHUNK_DOWNLOAD_RETRIES = 3 + +CAIBX_DOWNLOAD_TIMEOUT = 120 + +Chunk = namedtuple('Chunk', ['sha', 'offset', 'length']) +ChunkDict = dict[bytes, Chunk] + + +class ChunkReader(ABC): + @abstractmethod + def read(self, chunk: Chunk) -> bytes: + ... + + +class BinaryChunkReader(ChunkReader): + """Reads chunks from a local file""" + def __init__(self, file_like: IO[bytes]) -> None: + super().__init__() + self.f = file_like + + def read(self, chunk: Chunk) -> bytes: + self.f.seek(chunk.offset) + return self.f.read(chunk.length) + + +class FileChunkReader(BinaryChunkReader): + def __init__(self, path: str) -> None: + super().__init__(open(path, 'rb')) + + def __del__(self): + self.f.close() + + +class RemoteChunkReader(ChunkReader): + """Reads lzma compressed chunks from a remote store""" + + def __init__(self, url: str) -> None: + super().__init__() + self.url = url + self.session = requests.Session() + + def read(self, chunk: Chunk) -> bytes: + sha_hex = chunk.sha.hex() + url = os.path.join(self.url, sha_hex[:4], sha_hex + ".cacnk") + + if os.path.isfile(url): + with open(url, 'rb') as f: + contents = f.read() + else: + for i in range(CHUNK_DOWNLOAD_RETRIES): + try: + resp = self.session.get(url, timeout=CHUNK_DOWNLOAD_TIMEOUT) + break + except Exception: + if i == CHUNK_DOWNLOAD_RETRIES - 1: + raise + time.sleep(CHUNK_DOWNLOAD_TIMEOUT) + + resp.raise_for_status() + contents = resp.content + + decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_AUTO) + return decompressor.decompress(contents) + + +class DirectoryTarChunkReader(BinaryChunkReader): + """creates a tar archive of a directory and reads chunks from it""" + + def __init__(self, path: str, cache_file: str) -> None: + create_casync_tar_package(pathlib.Path(path), pathlib.Path(cache_file)) + + self.f = open(cache_file, "rb") + return super().__init__(self.f) + + def __del__(self): + self.f.close() + os.unlink(self.f.name) + + +def parse_caibx(caibx_path: str) -> list[Chunk]: + """Parses the chunks from a caibx file. Can handle both local and remote files. + Returns a list of chunks with hash, offset and length""" + caibx: io.BufferedIOBase + if os.path.isfile(caibx_path): + caibx = open(caibx_path, 'rb') + else: + resp = requests.get(caibx_path, timeout=CAIBX_DOWNLOAD_TIMEOUT) + resp.raise_for_status() + caibx = io.BytesIO(resp.content) + + caibx.seek(0, os.SEEK_END) + caibx_len = caibx.tell() + caibx.seek(0, os.SEEK_SET) + + # Parse header + length, magic, flags, min_size, _, max_size = struct.unpack("= min_size + + chunks.append(Chunk(sha, offset, length)) + offset = new_offset + + caibx.close() + return chunks + + +def build_chunk_dict(chunks: list[Chunk]) -> ChunkDict: + """Turn a list of chunks into a dict for faster lookups based on hash. + Keep first chunk since it's more likely to be already downloaded.""" + r = {} + for c in chunks: + if c.sha not in r: + r[c.sha] = c + return r + + +def extract(target: list[Chunk], + sources: list[tuple[str, ChunkReader, ChunkDict]], + out_path: str, + progress: Callable[[int], None] = None): + stats: dict[str, int] = defaultdict(int) + + mode = 'rb+' if os.path.exists(out_path) else 'wb' + with open(out_path, mode) as out: + for cur_chunk in target: + + # Find source for desired chunk + for name, chunk_reader, store_chunks in sources: + if cur_chunk.sha in store_chunks: + bts = chunk_reader.read(store_chunks[cur_chunk.sha]) + + # Check length + if len(bts) != cur_chunk.length: + continue + + # Check hash + if SHA512.new(bts, truncate="256").digest() != cur_chunk.sha: + continue + + # Write to output + out.seek(cur_chunk.offset) + out.write(bts) + + stats[name] += cur_chunk.length + + if progress is not None: + progress(sum(stats.values())) + + break + else: + raise RuntimeError("Desired chunk not found in provided stores") + + return stats + + +def extract_directory(target: list[Chunk], + sources: list[tuple[str, ChunkReader, ChunkDict]], + out_path: str, + tmp_file: str, + progress: Callable[[int], None] = None): + """extract a directory stored as a casync tar archive""" + + stats = extract(target, sources, tmp_file, progress) + + with open(tmp_file, "rb") as f: + tar.extract_tar_archive(f, pathlib.Path(out_path)) + + return stats + + +def print_stats(stats: dict[str, int]): + total_bytes = sum(stats.values()) + print(f"Total size: {total_bytes / 1024 / 1024:.2f} MB") + for name, total in stats.items(): + print(f" {name}: {total / 1024 / 1024:.2f} MB ({total / total_bytes * 100:.1f}%)") + + +def extract_simple(caibx_path, out_path, store_path): + # (name, callback, chunks) + target = parse_caibx(caibx_path) + sources = [ + # (store_path, RemoteChunkReader(store_path), build_chunk_dict(target)), + (store_path, FileChunkReader(store_path), build_chunk_dict(target)), + ] + + return extract(target, sources, out_path) + + +if __name__ == "__main__": + caibx = sys.argv[1] + out = sys.argv[2] + store = sys.argv[3] + + stats = extract_simple(caibx, out, store) + print_stats(stats) diff --git a/system/updated/casync/common.py b/system/updated/casync/common.py new file mode 100644 index 0000000000..6979f5cb06 --- /dev/null +++ b/system/updated/casync/common.py @@ -0,0 +1,61 @@ +import dataclasses +import json +import pathlib +import subprocess + +from openpilot.system.version import BUILD_METADATA_FILENAME, BuildMetadata +from openpilot.system.updated.casync import tar + + +CASYNC_ARGS = ["--with=symlinks", "--with=permissions", "--compression=xz", "--chunk-size=16M"] +CASYNC_FILES = [BUILD_METADATA_FILENAME] + + +def run(cmd): + return subprocess.check_output(cmd) + + +def get_exclude_set(path) -> set[str]: + exclude_set = set(CASYNC_FILES) + + for file in path.rglob("*"): + if file.is_file() or file.is_symlink(): + + while file.resolve() != path.resolve(): + exclude_set.add(str(file.relative_to(path))) + + file = file.parent + + return exclude_set + + +def create_build_metadata_file(path: pathlib.Path, build_metadata: BuildMetadata): + with open(path / BUILD_METADATA_FILENAME, "w") as f: + build_metadata_dict = dataclasses.asdict(build_metadata) + build_metadata_dict["openpilot"].pop("is_dirty") # this is determined at runtime + build_metadata_dict.pop("channel") # channel is unrelated to the build itself + f.write(json.dumps(build_metadata_dict)) + + +def is_not_git(path: pathlib.Path) -> bool: + return ".git" not in path.parts + + +def create_casync_tar_package(target_dir: pathlib.Path, output_path: pathlib.Path): + tar.create_tar_archive(output_path, target_dir, is_not_git) + + +def create_casync_from_file(file: pathlib.Path, output_dir: pathlib.Path, caibx_name: str): + caibx_file = output_dir / f"{caibx_name}.caibx" + run(["casync", "make", *CASYNC_ARGS, caibx_file, str(file)]) + + return caibx_file + + +def create_casync_release(target_dir: pathlib.Path, output_dir: pathlib.Path, caibx_name: str): + tar_file = output_dir / f"{caibx_name}.tar" + create_casync_tar_package(target_dir, tar_file) + caibx_file = create_casync_from_file(tar_file, output_dir, caibx_name) + tar_file.unlink() + digest = run(["casync", "digest", *CASYNC_ARGS, target_dir]).decode("utf-8").strip() + return digest, caibx_file diff --git a/system/updated/casync/tar.py b/system/updated/casync/tar.py new file mode 100644 index 0000000000..a5a8238bba --- /dev/null +++ b/system/updated/casync/tar.py @@ -0,0 +1,39 @@ +import pathlib +import tarfile +from typing import IO +from collections.abc import Callable + + +def include_default(_) -> bool: + return True + + +def create_tar_archive(filename: pathlib.Path, directory: pathlib.Path, include: Callable[[pathlib.Path], bool] = include_default): + """Creates a tar archive of a directory""" + + with tarfile.open(filename, 'w') as tar: + for file in sorted(directory.rglob("*"), key=lambda f: f.stat().st_size if f.is_file() else 0, reverse=True): + if not include(file): + continue + relative_path = str(file.relative_to(directory)) + if file.is_symlink(): + info = tarfile.TarInfo(relative_path) + info.type = tarfile.SYMTYPE + info.linkpath = str(file.readlink()) + tar.addfile(info) + + elif file.is_file(): + info = tarfile.TarInfo(relative_path) + info.size = file.stat().st_size + info.type = tarfile.REGTYPE + info.mode = file.stat().st_mode + with file.open('rb') as f: + tar.addfile(info, f) + + +def extract_tar_archive(fh: IO[bytes], directory: pathlib.Path): + """Extracts a tar archive to a directory""" + + tar = tarfile.open(fileobj=fh, mode='r') + tar.extractall(str(directory), filter=lambda info, path: info) + tar.close() diff --git a/system/updated/casync/tests/test_casync.py b/system/updated/casync/tests/test_casync.py new file mode 100644 index 0000000000..bc171e7432 --- /dev/null +++ b/system/updated/casync/tests/test_casync.py @@ -0,0 +1,264 @@ +import pytest +import os +import pathlib +import tempfile +import subprocess + +from openpilot.system.updated.casync import casync +from openpilot.system.updated.casync import tar + +# dd if=/dev/zero of=/tmp/img.raw bs=1M count=2 +# sudo losetup -f /tmp/img.raw +# losetup -a | grep img.raw +LOOPBACK = os.environ.get('LOOPBACK', None) + + +@pytest.mark.skip("not used yet") +class TestCasync: + @classmethod + def setup_class(cls): + cls.tmpdir = tempfile.TemporaryDirectory() + + # Build example contents + chunk_a = [i % 256 for i in range(1024)] * 512 + chunk_b = [(256 - i) % 256 for i in range(1024)] * 512 + zeroes = [0] * (1024 * 128) + contents = chunk_a + chunk_b + zeroes + chunk_a + + cls.contents = bytes(contents) + + # Write to file + cls.orig_fn = os.path.join(cls.tmpdir.name, 'orig.bin') + with open(cls.orig_fn, 'wb') as f: + f.write(cls.contents) + + # Create casync files + cls.manifest_fn = os.path.join(cls.tmpdir.name, 'orig.caibx') + cls.store_fn = os.path.join(cls.tmpdir.name, 'store') + subprocess.check_output(["casync", "make", "--compression=xz", "--store", cls.store_fn, cls.manifest_fn, cls.orig_fn]) + + target = casync.parse_caibx(cls.manifest_fn) + hashes = [c.sha.hex() for c in target] + + # Ensure we have chunk reuse + assert len(hashes) > len(set(hashes)) + + def setup_method(self): + # Clear target_lo + if LOOPBACK is not None: + self.target_lo = LOOPBACK + with open(self.target_lo, 'wb') as f: + f.write(b"0" * len(self.contents)) + + self.target_fn = os.path.join(self.tmpdir.name, next(tempfile._get_candidate_names())) + self.seed_fn = os.path.join(self.tmpdir.name, next(tempfile._get_candidate_names())) + + def teardown_method(self): + for fn in [self.target_fn, self.seed_fn]: + try: + os.unlink(fn) + except FileNotFoundError: + pass + + def test_simple_extract(self): + target = casync.parse_caibx(self.manifest_fn) + + sources = [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + stats = casync.extract(target, sources, self.target_fn) + + with open(self.target_fn, 'rb') as target_f: + assert target_f.read() == self.contents + + assert stats['remote'] == len(self.contents) + + def test_seed(self): + target = casync.parse_caibx(self.manifest_fn) + + # Populate seed with half of the target contents + with open(self.seed_fn, 'wb') as seed_f: + seed_f.write(self.contents[:len(self.contents) // 2]) + + sources = [('seed', casync.FileChunkReader(self.seed_fn), casync.build_chunk_dict(target))] + sources += [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + stats = casync.extract(target, sources, self.target_fn) + + with open(self.target_fn, 'rb') as target_f: + assert target_f.read() == self.contents + + assert stats['seed'] > 0 + assert stats['remote'] < len(self.contents) + + def test_already_done(self): + """Test that an already flashed target doesn't download any chunks""" + target = casync.parse_caibx(self.manifest_fn) + + with open(self.target_fn, 'wb') as f: + f.write(self.contents) + + sources = [('target', casync.FileChunkReader(self.target_fn), casync.build_chunk_dict(target))] + sources += [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + + stats = casync.extract(target, sources, self.target_fn) + + with open(self.target_fn, 'rb') as f: + assert f.read() == self.contents + + assert stats['target'] == len(self.contents) + + def test_chunk_reuse(self): + """Test that chunks that are reused are only downloaded once""" + target = casync.parse_caibx(self.manifest_fn) + + # Ensure target exists + with open(self.target_fn, 'wb'): + pass + + sources = [('target', casync.FileChunkReader(self.target_fn), casync.build_chunk_dict(target))] + sources += [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + + stats = casync.extract(target, sources, self.target_fn) + + with open(self.target_fn, 'rb') as f: + assert f.read() == self.contents + + assert stats['remote'] < len(self.contents) + + @pytest.mark.skipif(not LOOPBACK, reason="requires loopback device") + def test_lo_simple_extract(self): + target = casync.parse_caibx(self.manifest_fn) + sources = [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + + stats = casync.extract(target, sources, self.target_lo) + + with open(self.target_lo, 'rb') as target_f: + assert target_f.read(len(self.contents)) == self.contents + + assert stats['remote'] == len(self.contents) + + @pytest.mark.skipif(not LOOPBACK, reason="requires loopback device") + def test_lo_chunk_reuse(self): + """Test that chunks that are reused are only downloaded once""" + target = casync.parse_caibx(self.manifest_fn) + + sources = [('target', casync.FileChunkReader(self.target_lo), casync.build_chunk_dict(target))] + sources += [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + + stats = casync.extract(target, sources, self.target_lo) + + with open(self.target_lo, 'rb') as f: + assert f.read(len(self.contents)) == self.contents + + assert stats['remote'] < len(self.contents) + + +@pytest.mark.skip("not used yet") +class TestCasyncDirectory: + """Tests extracting a directory stored as a casync tar archive""" + + NUM_FILES = 16 + + @classmethod + def setup_cache(cls, directory, files=None): + if files is None: + files = range(cls.NUM_FILES) + + chunk_a = [i % 256 for i in range(1024)] * 512 + chunk_b = [(256 - i) % 256 for i in range(1024)] * 512 + zeroes = [0] * (1024 * 128) + cls.contents = chunk_a + chunk_b + zeroes + chunk_a + cls.contents = bytes(cls.contents) + + for i in files: + with open(os.path.join(directory, f"file_{i}.txt"), "wb") as f: + f.write(cls.contents) + + os.symlink(f"file_{i}.txt", os.path.join(directory, f"link_{i}.txt")) + + @classmethod + def setup_class(cls): + cls.tmpdir = tempfile.TemporaryDirectory() + + # Create casync files + cls.manifest_fn = os.path.join(cls.tmpdir.name, 'orig.caibx') + cls.store_fn = os.path.join(cls.tmpdir.name, 'store') + + cls.directory_to_extract = tempfile.TemporaryDirectory() + cls.setup_cache(cls.directory_to_extract.name) + + cls.orig_fn = os.path.join(cls.tmpdir.name, 'orig.tar') + tar.create_tar_archive(cls.orig_fn, pathlib.Path(cls.directory_to_extract.name)) + + subprocess.check_output(["casync", "make", "--compression=xz", "--store", cls.store_fn, cls.manifest_fn, cls.orig_fn]) + + @classmethod + def teardown_class(cls): + cls.tmpdir.cleanup() + cls.directory_to_extract.cleanup() + + def setup_method(self): + self.cache_dir = tempfile.TemporaryDirectory() + self.working_dir = tempfile.TemporaryDirectory() + self.out_dir = tempfile.TemporaryDirectory() + + def teardown_method(self): + self.cache_dir.cleanup() + self.working_dir.cleanup() + self.out_dir.cleanup() + + def run_test(self): + target = casync.parse_caibx(self.manifest_fn) + + cache_filename = os.path.join(self.working_dir.name, "cache.tar") + tmp_filename = os.path.join(self.working_dir.name, "tmp.tar") + + sources = [('cache', casync.DirectoryTarChunkReader(self.cache_dir.name, cache_filename), casync.build_chunk_dict(target))] + sources += [('remote', casync.RemoteChunkReader(self.store_fn), casync.build_chunk_dict(target))] + + stats = casync.extract_directory(target, sources, pathlib.Path(self.out_dir.name), tmp_filename) + + with open(os.path.join(self.out_dir.name, "file_0.txt"), "rb") as f: + assert f.read() == self.contents + + with open(os.path.join(self.out_dir.name, "link_0.txt"), "rb") as f: + assert f.read() == self.contents + assert os.readlink(os.path.join(self.out_dir.name, "link_0.txt")) == "file_0.txt" + + return stats + + def test_no_cache(self): + self.setup_cache(self.cache_dir.name, []) + stats = self.run_test() + assert stats['remote'] > 0 + assert stats['cache'] == 0 + + def test_full_cache(self): + self.setup_cache(self.cache_dir.name, range(self.NUM_FILES)) + stats = self.run_test() + assert stats['remote'] == 0 + assert stats['cache'] > 0 + + def test_one_file_cache(self): + self.setup_cache(self.cache_dir.name, range(1)) + stats = self.run_test() + assert stats['remote'] > 0 + assert stats['cache'] > 0 + assert stats['cache'] < stats['remote'] + + def test_one_file_incorrect_cache(self): + self.setup_cache(self.cache_dir.name, range(self.NUM_FILES)) + with open(os.path.join(self.cache_dir.name, "file_0.txt"), "wb") as f: + f.write(b"1234") + + stats = self.run_test() + assert stats['remote'] > 0 + assert stats['cache'] > 0 + assert stats['cache'] > stats['remote'] + + def test_one_file_missing_cache(self): + self.setup_cache(self.cache_dir.name, range(self.NUM_FILES)) + os.unlink(os.path.join(self.cache_dir.name, "file_12.txt")) + + stats = self.run_test() + assert stats['remote'] > 0 + assert stats['cache'] > 0 + assert stats['cache'] > stats['remote'] diff --git a/system/updated/common.py b/system/updated/common.py new file mode 100644 index 0000000000..6bb745f6b0 --- /dev/null +++ b/system/updated/common.py @@ -0,0 +1,16 @@ +import os +import pathlib + + +def get_consistent_flag(path: str) -> bool: + consistent_file = pathlib.Path(os.path.join(path, ".overlay_consistent")) + return consistent_file.is_file() + +def set_consistent_flag(path: str, consistent: bool) -> None: + os.sync() + consistent_file = pathlib.Path(os.path.join(path, ".overlay_consistent")) + if consistent: + consistent_file.touch() + elif not consistent: + consistent_file.unlink(missing_ok=True) + os.sync() diff --git a/system/updated/tests/test_base.py b/system/updated/tests/test_base.py new file mode 100644 index 0000000000..699a0f0bd3 --- /dev/null +++ b/system/updated/tests/test_base.py @@ -0,0 +1,259 @@ +import os +import pathlib +import shutil +import signal +import stat +import subprocess +import tempfile +import time +import pytest + +from openpilot.common.params import Params +from openpilot.system.manager.process import ManagerProcess +from openpilot.selfdrive.test.helpers import processes_context + + +def get_consistent_flag(path: str) -> bool: + consistent_file = pathlib.Path(os.path.join(path, ".overlay_consistent")) + return consistent_file.is_file() + + +def run(args, **kwargs): + return subprocess.check_output(args, **kwargs) + + +def update_release(directory, name, version, agnos_version, release_notes): + with open(directory / "RELEASES.md", "w") as f: + f.write(release_notes) + + (directory / "common").mkdir(exist_ok=True) + + with open(directory / "common" / "version.h", "w") as f: + f.write(f'#define COMMA_VERSION "{version}"') + + launch_env = directory / "launch_env.sh" + with open(launch_env, "w") as f: + f.write(f'export AGNOS_VERSION="{agnos_version}"') + + st = os.stat(launch_env) + os.chmod(launch_env, st.st_mode | stat.S_IEXEC) + + test_symlink = directory / "test_symlink" + if not os.path.exists(str(test_symlink)): + os.symlink("common/version.h", test_symlink) + + +def get_version(path: str) -> str: + with open(os.path.join(path, "common", "version.h")) as f: + return f.read().split('"')[1] + + +@pytest.mark.slow # TODO: can we test overlayfs in GHA? +class TestBaseUpdate: + @classmethod + def setup_class(cls): + if "Base" in cls.__name__: + pytest.skip() + + def setup_method(self): + self.tmpdir = tempfile.mkdtemp() + + run(["sudo", "mount", "-t", "tmpfs", "tmpfs", self.tmpdir]) # overlayfs doesn't work inside of docker unless this is a tmpfs + + self.mock_update_path = pathlib.Path(self.tmpdir) + + self.params = Params() + + self.basedir = self.mock_update_path / "openpilot" + self.basedir.mkdir() + + self.staging_root = self.mock_update_path / "safe_staging" + self.staging_root.mkdir() + + self.remote_dir = self.mock_update_path / "remote" + self.remote_dir.mkdir() + + os.environ["UPDATER_STAGING_ROOT"] = str(self.staging_root) + os.environ["UPDATER_LOCK_FILE"] = str(self.mock_update_path / "safe_staging_overlay.lock") + + self.MOCK_RELEASES = { + "release3": ("0.1.2", "1.2", "0.1.2 release notes"), + "master": ("0.1.3", "1.2", "0.1.3 release notes"), + } + + @pytest.fixture(autouse=True) + def mock_basedir(self, mocker): + mocker.patch("openpilot.common.basedir.BASEDIR", self.basedir) + + def set_target_branch(self, branch): + self.params.put("UpdaterTargetBranch", branch) + + def setup_basedir_release(self, release): + self.params = Params() + self.set_target_branch(release) + + def update_remote_release(self, release): + raise NotImplementedError("") + + def setup_remote_release(self, release): + raise NotImplementedError("") + + def additional_context(self): + raise NotImplementedError("") + + def teardown_method(self): + try: + run(["sudo", "umount", "-l", str(self.staging_root / "merged")]) + run(["sudo", "umount", "-l", self.tmpdir]) + shutil.rmtree(self.tmpdir) + except Exception: + print("cleanup failed...") + + def wait_for_condition(self, condition, timeout=12): + start = time.monotonic() + while True: + waited = time.monotonic() - start + if condition(): + print(f"waited {waited}s for condition ") + return waited + + if waited > timeout: + raise TimeoutError("timed out waiting for condition") + + time.sleep(1) + + def _test_finalized_update(self, branch, version, agnos_version, release_notes): + assert get_version(str(self.staging_root / "finalized")) == version + assert get_consistent_flag(str(self.staging_root / "finalized")) + assert os.access(str(self.staging_root / "finalized" / "launch_env.sh"), os.X_OK) + + with open(self.staging_root / "finalized" / "test_symlink") as f: + assert version in f.read() + +class ParamsBaseUpdateTest(TestBaseUpdate): + def _test_finalized_update(self, branch, version, agnos_version, release_notes): + assert self.params.get("UpdaterNewDescription").startswith(f"{version} / {branch}") + assert self.params.get("UpdaterNewReleaseNotes") == f"{release_notes}\n" + super()._test_finalized_update(branch, version, agnos_version, release_notes) + + def send_check_for_updates_signal(self, updated: ManagerProcess): + updated.signal(signal.SIGUSR1.value) + + def send_download_signal(self, updated: ManagerProcess): + updated.signal(signal.SIGHUP.value) + + def _test_params(self, branch, fetch_available, update_available): + assert self.params.get("UpdaterTargetBranch") == branch + assert self.params.get_bool("UpdaterFetchAvailable") == fetch_available + assert self.params.get_bool("UpdateAvailable") == update_available + + def wait_for_idle(self): + self.wait_for_condition(lambda: self.params.get("UpdaterState") == "idle") + + def wait_for_failed(self): + self.wait_for_condition(lambda: self.params.get("UpdateFailedCount") is not None and \ + self.params.get("UpdateFailedCount") > 0) + + def wait_for_fetch_available(self): + self.wait_for_condition(lambda: self.params.get_bool("UpdaterFetchAvailable")) + + def wait_for_update_available(self): + self.wait_for_condition(lambda: self.params.get_bool("UpdateAvailable")) + + def test_no_update(self): + # Start on release3, ensure we don't fetch any updates + self.setup_remote_release("release3") + self.setup_basedir_release("release3") + + with self.additional_context(), processes_context(["updated"]) as [updated]: + self._test_params("release3", False, False) + self.wait_for_idle() + self._test_params("release3", False, False) + + self.send_check_for_updates_signal(updated) + + self.wait_for_idle() + + self._test_params("release3", False, False) + + def test_new_release(self): + # Start on release3, simulate a release3 commit, ensure we fetch that update properly + self.setup_remote_release("release3") + self.setup_basedir_release("release3") + + with self.additional_context(), processes_context(["updated"]) as [updated]: + self._test_params("release3", False, False) + self.wait_for_idle() + self._test_params("release3", False, False) + + self.MOCK_RELEASES["release3"] = ("0.1.3", "1.2", "0.1.3 release notes") + self.update_remote_release("release3") + + self.send_check_for_updates_signal(updated) + + self.wait_for_fetch_available() + + self._test_params("release3", True, False) + + self.send_download_signal(updated) + + self.wait_for_update_available() + + self._test_params("release3", False, True) + self._test_finalized_update("release3", *self.MOCK_RELEASES["release3"]) + + def test_switch_branches(self): + # Start on release3, request to switch to master manually, ensure we switched + self.setup_remote_release("release3") + self.setup_remote_release("master") + self.setup_basedir_release("release3") + + with self.additional_context(), processes_context(["updated"]) as [updated]: + self._test_params("release3", False, False) + self.wait_for_idle() + self._test_params("release3", False, False) + + self.set_target_branch("master") + self.send_check_for_updates_signal(updated) + + self.wait_for_fetch_available() + + self._test_params("master", True, False) + + self.send_download_signal(updated) + + self.wait_for_update_available() + + self._test_params("master", False, True) + self._test_finalized_update("master", *self.MOCK_RELEASES["master"]) + + def test_agnos_update(self, mocker): + # Start on release3, push an update with an agnos change + self.setup_remote_release("release3") + self.setup_basedir_release("release3") + + with self.additional_context(), processes_context(["updated"]) as [updated]: + mocker.patch("openpilot.system.hardware.AGNOS", "True") + mocker.patch("openpilot.system.hardware.tici.hardware.Tici.get_os_version", "1.2") + mocker.patch("openpilot.system.hardware.tici.agnos.get_target_slot_number") + mocker.patch("openpilot.system.hardware.tici.agnos.flash_agnos_update") + + self._test_params("release3", False, False) + self.wait_for_idle() + self._test_params("release3", False, False) + + self.MOCK_RELEASES["release3"] = ("0.1.3", "1.3", "0.1.3 release notes") + self.update_remote_release("release3") + + self.send_check_for_updates_signal(updated) + + self.wait_for_fetch_available() + + self._test_params("release3", True, False) + + self.send_download_signal(updated) + + self.wait_for_update_available() + + self._test_params("release3", False, True) + self._test_finalized_update("release3", *self.MOCK_RELEASES["release3"]) diff --git a/system/updated/tests/test_git.py b/system/updated/tests/test_git.py new file mode 100644 index 0000000000..5a5a27000b --- /dev/null +++ b/system/updated/tests/test_git.py @@ -0,0 +1,22 @@ +import contextlib +from openpilot.system.updated.tests.test_base import ParamsBaseUpdateTest, run, update_release + + +class TestUpdateDGitStrategy(ParamsBaseUpdateTest): + def update_remote_release(self, release): + update_release(self.remote_dir, release, *self.MOCK_RELEASES[release]) + run(["git", "add", "."], cwd=self.remote_dir) + run(["git", "commit", "-m", f"openpilot release {release}"], cwd=self.remote_dir) + + def setup_remote_release(self, release): + run(["git", "init"], cwd=self.remote_dir) + run(["git", "checkout", "-b", release], cwd=self.remote_dir) + self.update_remote_release(release) + + def setup_basedir_release(self, release): + super().setup_basedir_release(release) + run(["git", "clone", "-b", release, self.remote_dir, self.basedir]) + + @contextlib.contextmanager + def additional_context(self): + yield diff --git a/system/updated/updated.py b/system/updated/updated.py new file mode 100755 index 0000000000..a4a1f8f34f --- /dev/null +++ b/system/updated/updated.py @@ -0,0 +1,514 @@ +#!/usr/bin/env python3 +import os +import re +import datetime +import subprocess +import psutil +import shutil +import signal +import fcntl +import time +import threading +from collections import defaultdict +from pathlib import Path + +from openpilot.common.basedir import BASEDIR +from openpilot.common.params import Params +from openpilot.common.time_helpers import system_time_valid +from openpilot.common.markdown import parse_markdown +from openpilot.common.swaglog import cloudlog +from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert +from openpilot.system.hardware import AGNOS, HARDWARE +from openpilot.system.version import get_build_metadata + +LOCK_FILE = os.getenv("UPDATER_LOCK_FILE", "/tmp/safe_staging_overlay.lock") +STAGING_ROOT = os.getenv("UPDATER_STAGING_ROOT", "/data/safe_staging") + +OVERLAY_UPPER = os.path.join(STAGING_ROOT, "upper") +OVERLAY_METADATA = os.path.join(STAGING_ROOT, "metadata") +OVERLAY_MERGED = os.path.join(STAGING_ROOT, "merged") +FINALIZED = os.path.join(STAGING_ROOT, "finalized") + +OVERLAY_INIT = Path(os.path.join(BASEDIR, ".overlay_init")) + +# do not allow to engage after this many hours onroad and this many routes +HOURS_NO_CONNECTIVITY_MAX = 27 +ROUTES_NO_CONNECTIVITY_MAX = 84 +# send an offroad prompt after this many hours onroad and this many routes +HOURS_NO_CONNECTIVITY_PROMPT = 23 +ROUTES_NO_CONNECTIVITY_PROMPT = 80 + + +class UserRequest: + NONE = 0 + CHECK = 1 + FETCH = 2 + +class WaitTimeHelper: + def __init__(self): + self.ready_event = threading.Event() + self.user_request = UserRequest.NONE + 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.user_request = UserRequest.FETCH + self.ready_event.set() + + def check_now(self, signum: int, frame) -> None: + cloudlog.info("caught SIGUSR1, checking for updates") + self.user_request = UserRequest.CHECK + self.ready_event.set() + + def sleep(self, t: float) -> None: + self.ready_event.wait(timeout=t) + +def write_time_to_param(params, param) -> None: + t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) + params.put(param, t) + +def run(cmd: list[str], cwd: str = None) -> str: + return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8') + + +def set_consistent_flag(consistent: bool) -> None: + os.sync() + consistent_file = Path(os.path.join(FINALIZED, ".overlay_consistent")) + if consistent: + consistent_file.touch() + elif not consistent: + consistent_file.unlink(missing_ok=True) + os.sync() + +def parse_release_notes(basedir: str) -> bytes: + try: + with open(os.path.join(basedir, "RELEASES.md"), "rb") as f: + r = f.read().split(b'\n\n', 1)[0] # Slice latest release notes + try: + return bytes(parse_markdown(r.decode("utf-8")), encoding="utf-8") + except Exception: + return r + b"\n" + except FileNotFoundError: + pass + except Exception: + cloudlog.exception("failed to parse release notes") + return b"" + +def setup_git_options(cwd: str) -> None: + # We sync FS object atimes (which NEOS doesn't use) and mtimes, but ctimes + # are outside user control. Make sure Git is set up to ignore system ctimes, + # because they change when we make hard links during finalize. Otherwise, + # there is a lot of unnecessary churn. This appears to be a common need on + # OSX as well: https://www.git-tower.com/blog/make-git-rebase-safe-on-osx/ + + # We are using copytree to copy the directory, which also changes + # inode numbers. Ignore those changes too. + + # Set protocol to the new version (default after git 2.26) to reduce data + # usage on git fetch --dry-run from about 400KB to 18KB. + git_cfg = [ + ("core.trustctime", "false"), + ("core.checkStat", "minimal"), + ("protocol.version", "2"), + ("gc.auto", "0"), + ("gc.autoDetach", "false"), + ] + for option, value in git_cfg: + run(["git", "config", option, value], cwd) + + +def dismount_overlay() -> None: + if os.path.ismount(OVERLAY_MERGED): + cloudlog.info("unmounting existing overlay") + run(["sudo", "umount", "-l", OVERLAY_MERGED]) + + +def init_overlay() -> None: + + # Re-create the overlay if BASEDIR/.git has changed since we created the overlay + if OVERLAY_INIT.is_file() and os.path.ismount(OVERLAY_MERGED): + git_dir_path = os.path.join(BASEDIR, ".git") + new_files = run(["find", git_dir_path, "-newer", str(OVERLAY_INIT)]) + if not len(new_files.splitlines()): + # A valid overlay already exists + return + else: + cloudlog.info(".git directory changed, recreating overlay") + + cloudlog.info("preparing new safe staging area") + + params = Params() + params.put_bool("UpdateAvailable", False) + set_consistent_flag(False) + dismount_overlay() + run(["sudo", "rm", "-rf", STAGING_ROOT]) + if os.path.isdir(STAGING_ROOT): + shutil.rmtree(STAGING_ROOT) + + for dirname in [STAGING_ROOT, OVERLAY_UPPER, OVERLAY_METADATA, OVERLAY_MERGED]: + os.mkdir(dirname, 0o755) + + if os.lstat(BASEDIR).st_dev != os.lstat(OVERLAY_MERGED).st_dev: + raise RuntimeError("base and overlay merge directories are on different filesystems; not valid for overlay FS!") + + # Leave a timestamped canary in BASEDIR to check at startup. The device clock + # should be correct by the time we get here. If the init file disappears, or + # critical mtimes in BASEDIR are newer than .overlay_init, continue.sh can + # assume that BASEDIR has used for local development or otherwise modified, + # and skips the update activation attempt. + consistent_file = Path(os.path.join(BASEDIR, ".overlay_consistent")) + if consistent_file.is_file(): + consistent_file.unlink() + OVERLAY_INIT.touch() + + os.sync() + overlay_opts = f"lowerdir={BASEDIR},upperdir={OVERLAY_UPPER},workdir={OVERLAY_METADATA}" + + mount_cmd = ["mount", "-t", "overlay", "-o", overlay_opts, "none", OVERLAY_MERGED] + run(["sudo"] + mount_cmd) + run(["sudo", "chmod", "755", os.path.join(OVERLAY_METADATA, "work")]) + + git_diff = run(["git", "diff", "--submodule=diff"], OVERLAY_MERGED) + params.put("GitDiff", git_diff) + cloudlog.info(f"git diff output:\n{git_diff}") + + +def finalize_update() -> None: + """Take the current OverlayFS merged view and finalize a copy outside of + OverlayFS, ready to be swapped-in at BASEDIR. Copy using shutil.copytree""" + + # Remove the update ready flag and any old updates + cloudlog.info("creating finalized version of the overlay") + set_consistent_flag(False) + + # Copy the merged overlay view and set the update ready flag + if os.path.exists(FINALIZED): + shutil.rmtree(FINALIZED) + shutil.copytree(OVERLAY_MERGED, FINALIZED, symlinks=True) + + run(["git", "reset", "--hard"], FINALIZED) + run(["git", "submodule", "foreach", "--recursive", "git", "reset", "--hard"], FINALIZED) + + cloudlog.info("Starting git cleanup in finalized update") + t = time.monotonic() + try: + run(["git", "gc"], FINALIZED) + run(["git", "lfs", "prune"], FINALIZED) + cloudlog.event("Done git cleanup", duration=time.monotonic() - t) + except subprocess.CalledProcessError: + cloudlog.exception(f"Failed git cleanup, took {time.monotonic() - t:.3f} s") + + set_consistent_flag(True) + cloudlog.info("done finalizing overlay") + + +def handle_agnos_update() -> None: + from openpilot.system.hardware.tici.agnos import flash_agnos_update, get_target_slot_number + + cur_version = HARDWARE.get_os_version() + updated_version = run(["bash", "-c", r"unset AGNOS_VERSION && source launch_env.sh && \ + echo -n $AGNOS_VERSION"], OVERLAY_MERGED).strip() + + cloudlog.info(f"AGNOS version check: {cur_version} vs {updated_version}") + if cur_version == updated_version: + return + + # prevent an openpilot getting swapped in with a mismatched or partially downloaded agnos + set_consistent_flag(False) + + cloudlog.info(f"Beginning background installation for AGNOS {updated_version}") + set_offroad_alert("Offroad_NeosUpdate", True) + + manifest_path = os.path.join(OVERLAY_MERGED, "system/hardware/tici/agnos.json") + target_slot_number = get_target_slot_number() + flash_agnos_update(manifest_path, target_slot_number, cloudlog) + set_offroad_alert("Offroad_NeosUpdate", False) + + + +class Updater: + def __init__(self): + self.params = Params() + self.branches = defaultdict(str) + self._has_internet: bool = False + + @property + def has_internet(self) -> bool: + return self._has_internet + + @property + def target_branch(self) -> str: + b: str | None = self.params.get("UpdaterTargetBranch") + if b is None: + b = self.get_branch(BASEDIR) + b = { + ("tizi", "release3"): "release-tizi", + }.get((HARDWARE.get_device_type(), b), b) + return b + + @property + def update_ready(self) -> bool: + consistent_file = Path(os.path.join(FINALIZED, ".overlay_consistent")) + if consistent_file.is_file(): + hash_mismatch = self.get_commit_hash(BASEDIR) != self.branches[self.target_branch] + branch_mismatch = self.get_branch(BASEDIR) != self.target_branch + on_target_branch = self.get_branch(FINALIZED) == self.target_branch + return ((hash_mismatch or branch_mismatch) and on_target_branch) + return False + + @property + def update_available(self) -> bool: + if os.path.isdir(OVERLAY_MERGED) and len(self.branches) > 0: + hash_mismatch = self.get_commit_hash(OVERLAY_MERGED) != self.branches[self.target_branch] + branch_mismatch = self.get_branch(OVERLAY_MERGED) != self.target_branch + return hash_mismatch or branch_mismatch + return False + + def get_branch(self, path: str) -> str: + return run(["git", "rev-parse", "--abbrev-ref", "HEAD"], path).rstrip() + + def get_commit_hash(self, path: str = OVERLAY_MERGED) -> str: + return run(["git", "rev-parse", "HEAD"], path).rstrip() + + def set_params(self, update_success: bool, failed_count: int, exception: str | None) -> None: + self.params.put("UpdateFailedCount", failed_count) + self.params.put("UpdaterTargetBranch", self.target_branch) + + self.params.put_bool("UpdaterFetchAvailable", self.update_available) + if len(self.branches): + self.params.put("UpdaterAvailableBranches", ','.join(self.branches.keys())) + + last_uptime_onroad = self.params.get("UptimeOnroad", return_default=True) + last_route_count = self.params.get("RouteCount", return_default=True) + if update_success: + self.params.put("LastUpdateTime", datetime.datetime.now(datetime.UTC).replace(tzinfo=None)) + self.params.put("LastUpdateUptimeOnroad", last_uptime_onroad) + self.params.put("LastUpdateRouteCount", last_route_count) + else: + last_uptime_onroad = self.params.get("LastUpdateUptimeOnroad", return_default=True) + last_route_count = self.params.get("LastUpdateRouteCount", return_default=True) + + if exception is None: + self.params.remove("LastUpdateException") + else: + self.params.put("LastUpdateException", exception) + + # Write out current and new version info + def get_description(basedir: str) -> str: + if not os.path.exists(basedir): + return "" + + version = "" + branch = "" + commit = "" + commit_date = "" + try: + branch = self.get_branch(basedir) + commit = self.get_commit_hash(basedir)[:7] + with open(os.path.join(basedir, "common", "version.h")) as f: + version = f.read().split('"')[1] + + commit_unix_ts = run(["git", "show", "-s", "--format=%ct", "HEAD"], basedir).rstrip() + dt = datetime.datetime.fromtimestamp(int(commit_unix_ts)) + commit_date = dt.strftime("%b %d") + except Exception: + cloudlog.exception("updater.get_description") + return f"{version} / {branch} / {commit} / {commit_date}" + self.params.put("UpdaterCurrentDescription", get_description(BASEDIR)) + self.params.put("UpdaterCurrentReleaseNotes", parse_release_notes(BASEDIR)) + self.params.put("UpdaterNewDescription", get_description(FINALIZED)) + self.params.put("UpdaterNewReleaseNotes", parse_release_notes(FINALIZED)) + self.params.put_bool("UpdateAvailable", self.update_ready) + + # Handle user prompt + for alert in ("Offroad_UpdateFailed", "Offroad_ConnectivityNeeded", "Offroad_ConnectivityNeededPrompt"): + set_offroad_alert(alert, False) + + dt_uptime_onroad = (self.params.get("UptimeOnroad", return_default=True) - last_uptime_onroad) / (60*60) + dt_route_count = self.params.get("RouteCount", return_default=True) - last_route_count + build_metadata = get_build_metadata() + if failed_count > 15 and exception is not None and self.has_internet: + if build_metadata.tested_channel: + extra_text = "Ensure the software is correctly installed. Uninstall and re-install if this error persists." + else: + extra_text = exception + set_offroad_alert("Offroad_UpdateFailed", True, extra_text=extra_text) + elif failed_count > 0: + if dt_uptime_onroad > HOURS_NO_CONNECTIVITY_MAX and dt_route_count > ROUTES_NO_CONNECTIVITY_MAX: + set_offroad_alert("Offroad_ConnectivityNeeded", True) + elif dt_uptime_onroad > HOURS_NO_CONNECTIVITY_PROMPT and dt_route_count > ROUTES_NO_CONNECTIVITY_PROMPT: + remaining = max(HOURS_NO_CONNECTIVITY_MAX - dt_uptime_onroad, 1) + set_offroad_alert("Offroad_ConnectivityNeededPrompt", True, extra_text=f"{remaining} hour{'' if remaining == 1 else 's'}.") + + def check_for_update(self) -> None: + cloudlog.info("checking for updates") + + excluded_branches = ('release2', 'release2-staging') + + try: + run(["git", "ls-remote", "origin", "HEAD"], OVERLAY_MERGED) + self._has_internet = True + except subprocess.CalledProcessError: + self._has_internet = False + + setup_git_options(OVERLAY_MERGED) + output = run(["git", "ls-remote", "--heads"], OVERLAY_MERGED) + + self.branches = defaultdict(lambda: None) + for line in output.split('\n'): + ls_remotes_re = r'(?P\b[0-9a-f]{5,40}\b)(\s+)(refs\/heads\/)(?P.*$)' + x = re.fullmatch(ls_remotes_re, line.strip()) + if x is not None and x.group('branch_name') not in excluded_branches: + self.branches[x.group('branch_name')] = x.group('commit_sha') + + cur_branch = self.get_branch(OVERLAY_MERGED) + 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]})") + 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...") + + # TODO: cleanly interrupt this and invalidate old update + set_consistent_flag(False) + self.params.put_bool("UpdateAvailable", False) + + setup_git_options(OVERLAY_MERGED) + + run(["git", "config", "--replace-all", "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"], OVERLAY_MERGED) + + branch = self.target_branch + git_fetch_output = run(["git", "fetch", "origin", branch], OVERLAY_MERGED) + cloudlog.info("git fetch success: %s", git_fetch_output) + + cloudlog.info("git reset in progress") + cmds = [ + ["git", "checkout", "--force", "--no-recurse-submodules", "-B", branch, "FETCH_HEAD"], + ["git", "branch", "--set-upstream-to", f"origin/{branch}"], + ["git", "reset", "--hard"], + ["git", "clean", "-xdff"], + ["git", "submodule", "sync"], + ["git", "submodule", "update", "--init", "--recursive"], + ["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)) + + # TODO: show agnos download progress + if AGNOS: + handle_agnos_update() + + # Create the finalized, ready-to-swap 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) + + with open(LOCK_FILE, 'w') as ov_lock_fd: + try: + fcntl.flock(ov_lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + except OSError as e: + raise RuntimeError("couldn't get overlay lock; is another instance running?") from e + + # Set low io priority + proc = psutil.Process() + if psutil.LINUX: + proc.ionice(psutil.IOPRIO_CLASS_BE, value=7) + + # Check if we just performed an update + if Path(os.path.join(STAGING_ROOT, "old_openpilot")).is_dir(): + cloudlog.event("update installed") + + if not params.get("InstallDate"): + t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) + params.put("InstallDate", t) + + updater = Updater() + update_failed_count = 0 # TODO: Load from param? + wait_helper = WaitTimeHelper() + + # invalidate old finalized update + set_consistent_flag(False) + + # set initial state + params.put("UpdaterState", "idle") + + # Run the update loop + first_run = True + while True: + wait_helper.ready_event.clear() + + # Attempt an update + exception = None + try: + # TODO: reuse overlay from previous updated instance if it looks clean + init_overlay() + + # ensure we have some params written soon after startup + updater.set_params(False, update_failed_count, exception) + + if not system_time_valid() or first_run: + first_run = False + wait_helper.sleep(60) + continue + + update_failed_count += 1 + + # check for update + params.put("UpdaterState", "checking...") + updater.check_for_update() + + # download update + last_fetch = params.get("UpdaterLastFetchTime") + timed_out = last_fetch is None or (datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_fetch > datetime.timedelta(days=3)) + user_requested_fetch = wait_helper.user_request == UserRequest.FETCH + if params.get_bool("NetworkMetered") and not timed_out and not user_requested_fetch: + cloudlog.info("skipping fetch, connection metered") + elif wait_helper.user_request == UserRequest.CHECK: + cloudlog.info("skipping fetch, only checking") + else: + updater.fetch_update() + write_time_to_param(params, "UpdaterLastFetchTime") + update_failed_count = 0 + except subprocess.CalledProcessError as e: + cloudlog.event( + "update process failed", + cmd=e.cmd, + output=e.output, + returncode=e.returncode + ) + exception = f"command failed: {e.cmd}\n{e.output}" + OVERLAY_INIT.unlink(missing_ok=True) + except Exception as e: + cloudlog.exception("uncaught updated exception, shouldn't happen") + exception = str(e) + OVERLAY_INIT.unlink(missing_ok=True) + + try: + params.put("UpdaterState", "idle") + update_successful = (update_failed_count == 0) + updater.set_params(update_successful, update_failed_count, exception) + except Exception: + cloudlog.exception("uncaught updated exception while setting params, shouldn't happen") + + # infrequent attempts if we successfully updated recently + wait_helper.user_request = UserRequest.NONE + wait_helper.sleep(5*60 if update_failed_count > 0 else 1.5*60*60) + + +if __name__ == "__main__": + main() diff --git a/system/version.py b/system/version.py new file mode 100755 index 0000000000..9c5a8348f9 --- /dev/null +++ b/system/version.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 +from dataclasses import dataclass +from functools import cache +import json +import os +import pathlib +import subprocess + +from openpilot.common.basedir import BASEDIR +from openpilot.common.swaglog import cloudlog +from openpilot.common.git import get_commit, get_origin, get_branch, get_short_branch, get_commit_date + +RELEASE_BRANCHES = ['release3-staging', 'release3', 'release-tici', 'release-tizi', 'nightly'] +TESTED_BRANCHES = RELEASE_BRANCHES + ['devel', 'devel-staging', 'nightly-dev'] + +BUILD_METADATA_FILENAME = "build.json" + +training_version: str = "0.2.0" +terms_version: str = "2" + + +def get_version(path: str = BASEDIR) -> str: + with open(os.path.join(path, "common", "version.h")) as _versionf: + version = _versionf.read().split('"')[1] + return version + + +def get_release_notes(path: str = BASEDIR) -> str: + with open(os.path.join(path, "RELEASES.md")) as f: + return f.read().split('\n\n', 1)[0] + + +@cache +def is_prebuilt(path: str = BASEDIR) -> bool: + return os.path.exists(os.path.join(path, 'prebuilt')) + + +@cache +def is_dirty(cwd: str = BASEDIR) -> bool: + if not get_origin() or not get_short_branch(): + return True + + dirty = False + try: + # Actually check dirty files + if not is_prebuilt(cwd): + # This is needed otherwise touched files might show up as modified + try: + subprocess.check_call(["git", "update-index", "--refresh"], cwd=cwd) + except subprocess.CalledProcessError: + pass + + branch = get_branch() + if not branch: + return True + dirty = (subprocess.call(["git", "diff-index", "--quiet", branch, "--"], cwd=cwd)) != 0 + except subprocess.CalledProcessError: + cloudlog.exception("git subprocess failed while checking dirty") + dirty = True + + return dirty + + +@dataclass +class OpenpilotMetadata: + version: str + release_notes: str + git_commit: str + git_origin: str + git_commit_date: str + build_style: str + is_dirty: bool # whether there are local changes + + @property + def short_version(self) -> str: + return self.version.split('-')[0] + + @property + def comma_remote(self) -> bool: + # note to fork maintainers, this is used for release metrics. please do not + # touch this to get rid of the orange startup alert. there's better ways to do that + return self.git_normalized_origin == "github.com/commaai/openpilot" + + @property + def git_normalized_origin(self) -> str: + return self.git_origin \ + .replace("git@", "", 1) \ + .replace(".git", "", 1) \ + .replace("https://", "", 1) \ + .replace(":", "/", 1) + + +@dataclass +class BuildMetadata: + channel: str + openpilot: OpenpilotMetadata + + @property + def tested_channel(self) -> bool: + return self.channel in TESTED_BRANCHES + + @property + def release_channel(self) -> bool: + return self.channel in RELEASE_BRANCHES + + @property + def canonical(self) -> str: + return f"{self.openpilot.version}-{self.openpilot.git_commit}-{self.openpilot.build_style}" + + @property + def ui_description(self) -> str: + return f"{self.openpilot.version} / {self.openpilot.git_commit[:6]} / {self.channel}" + + +def build_metadata_from_dict(build_metadata: dict) -> BuildMetadata: + channel = build_metadata.get("channel", "unknown") + openpilot_metadata = build_metadata.get("openpilot", {}) + version = openpilot_metadata.get("version", "unknown") + release_notes = openpilot_metadata.get("release_notes", "unknown") + git_commit = openpilot_metadata.get("git_commit", "unknown") + git_origin = openpilot_metadata.get("git_origin", "unknown") + git_commit_date = openpilot_metadata.get("git_commit_date", "unknown") + build_style = openpilot_metadata.get("build_style", "unknown") + return BuildMetadata(channel, + OpenpilotMetadata( + version=version, + release_notes=release_notes, + git_commit=git_commit, + git_origin=git_origin, + git_commit_date=git_commit_date, + build_style=build_style, + is_dirty=False)) + + +def get_build_metadata(path: str = BASEDIR) -> BuildMetadata: + build_metadata_path = pathlib.Path(path) / BUILD_METADATA_FILENAME + + if build_metadata_path.exists(): + build_metadata = json.loads(build_metadata_path.read_text()) + return build_metadata_from_dict(build_metadata) + + git_folder = pathlib.Path(path) / ".git" + + if git_folder.exists(): + return BuildMetadata(get_short_branch(path), + OpenpilotMetadata( + version=get_version(path), + release_notes=get_release_notes(path), + git_commit=get_commit(path), + git_origin=get_origin(path), + git_commit_date=get_commit_date(path), + build_style="unknown", + is_dirty=is_dirty(path))) + + cloudlog.exception("unable to get build metadata") + raise Exception("invalid build metadata") + + +if __name__ == "__main__": + from openpilot.common.params import Params + + params = Params() + params.put("TermsVersion", terms_version) + params.put("TrainingVersion", training_version) + + print(get_build_metadata()) diff --git a/system/webrtc/__init__.py b/system/webrtc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/system/webrtc/device/audio.py b/system/webrtc/device/audio.py new file mode 100644 index 0000000000..4b22033e03 --- /dev/null +++ b/system/webrtc/device/audio.py @@ -0,0 +1,109 @@ +import asyncio +import io + +import aiortc +import av +import numpy as np +import pyaudio + + +class AudioInputStreamTrack(aiortc.mediastreams.AudioStreamTrack): + PYAUDIO_TO_AV_FORMAT_MAP = { + pyaudio.paUInt8: 'u8', + pyaudio.paInt16: 's16', + pyaudio.paInt24: 's24', + pyaudio.paInt32: 's32', + pyaudio.paFloat32: 'flt', + } + + def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 16000, channels: int = 1, packet_time: float = 0.020, device_index: int = None): + super().__init__() + + self.p = pyaudio.PyAudio() + chunk_size = int(packet_time * rate) + self.stream = self.p.open(format=audio_format, + channels=channels, + rate=rate, + frames_per_buffer=chunk_size, + input=True, + input_device_index=device_index) + self.format = audio_format + self.rate = rate + self.channels = channels + self.packet_time = packet_time + self.chunk_size = chunk_size + self.pts = 0 + + async def recv(self): + mic_data = self.stream.read(self.chunk_size) + mic_array = np.frombuffer(mic_data, dtype=np.int16) + mic_array = np.expand_dims(mic_array, axis=0) + layout = 'stereo' if self.channels > 1 else 'mono' + frame = av.AudioFrame.from_ndarray(mic_array, format=self.PYAUDIO_TO_AV_FORMAT_MAP[self.format], layout=layout) + frame.rate = self.rate + frame.pts = self.pts + self.pts += frame.samples + + return frame + + +class AudioOutputSpeaker: + def __init__(self, audio_format: int = pyaudio.paInt16, rate: int = 48000, channels: int = 2, packet_time: float = 0.2, device_index: int = None): + + chunk_size = int(packet_time * rate) + self.p = pyaudio.PyAudio() + self.buffer = io.BytesIO() + self.channels = channels + self.stream = self.p.open(format=audio_format, + channels=channels, + rate=rate, + frames_per_buffer=chunk_size, + output=True, + output_device_index=device_index, + stream_callback=self.__pyaudio_callback) + self.tracks_and_tasks: list[tuple[aiortc.MediaStreamTrack, asyncio.Task | None]] = [] + + def __pyaudio_callback(self, in_data, frame_count, time_info, status): + if self.buffer.getbuffer().nbytes < frame_count * self.channels * 2: + buff = b'\x00\x00' * frame_count * self.channels + elif self.buffer.getbuffer().nbytes > 115200: # 3x the usual read size + self.buffer.seek(0) + buff = self.buffer.read(frame_count * self.channels * 4) + buff = buff[:frame_count * self.channels * 2] + self.buffer.seek(2) + else: + self.buffer.seek(0) + buff = self.buffer.read(frame_count * self.channels * 2) + self.buffer.seek(2) + return (buff, pyaudio.paContinue) + + async def __consume(self, track): + while True: + try: + frame = await track.recv() + except aiortc.MediaStreamError: + return + + self.buffer.write(bytes(frame.planes[0])) + + def hasTrack(self, track: aiortc.MediaStreamTrack) -> bool: + return any(t == track for t, _ in self.tracks_and_tasks) + + def addTrack(self, track: aiortc.MediaStreamTrack): + if not self.hasTrack(track): + self.tracks_and_tasks.append((track, None)) + + def start(self): + for index, (track, task) in enumerate(self.tracks_and_tasks): + if task is None: + self.tracks_and_tasks[index] = (track, asyncio.create_task(self.__consume(track))) + + def stop(self): + for _, task in self.tracks_and_tasks: + if task is not None: + task.cancel() + + self.tracks_and_tasks = [] + self.stream.stop_stream() + self.stream.close() + self.p.terminate() diff --git a/system/webrtc/device/video.py b/system/webrtc/device/video.py new file mode 100644 index 0000000000..1bca909294 --- /dev/null +++ b/system/webrtc/device/video.py @@ -0,0 +1,43 @@ +import asyncio + +import av +from teleoprtc.tracks import TiciVideoStreamTrack + +from cereal import messaging +from openpilot.common.realtime import DT_MDL, DT_DMON + + +class LiveStreamVideoStreamTrack(TiciVideoStreamTrack): + camera_to_sock_mapping = { + "driver": "livestreamDriverEncodeData", + "wideRoad": "livestreamWideRoadEncodeData", + "road": "livestreamRoadEncodeData", + } + + def __init__(self, camera_type: str): + dt = DT_DMON if camera_type == "driver" else DT_MDL + super().__init__(camera_type, dt) + + self._sock = messaging.sub_sock(self.camera_to_sock_mapping[camera_type], conflate=True) + self._pts = 0 + + async def recv(self): + while True: + msg = messaging.recv_one_or_none(self._sock) + if msg is not None: + break + await asyncio.sleep(0.005) + + evta = getattr(msg, msg.which()) + + packet = av.Packet(evta.header + evta.data) + packet.time_base = self._time_base + packet.pts = self._pts + + self.log_debug("track sending frame %s", self._pts) + self._pts += self._dt * self._clock_rate + + return packet + + def codec_preference(self) -> str | None: + return "H264" diff --git a/system/webrtc/schema.py b/system/webrtc/schema.py new file mode 100644 index 0000000000..d80986ebf2 --- /dev/null +++ b/system/webrtc/schema.py @@ -0,0 +1,43 @@ +import capnp +from typing import Any + + +def generate_type(type_walker, schema_walker) -> str | list[Any] | dict[str, Any]: + data_type = next(type_walker) + if data_type.which() == 'struct': + return generate_struct(next(schema_walker)) + elif data_type.which() == 'list': + _ = next(schema_walker) + return [generate_type(type_walker, schema_walker)] + elif data_type.which() == 'enum': + return "text" + else: + return str(data_type.which()) + + +def generate_struct(schema: capnp.lib.capnp._StructSchema) -> dict[str, Any]: + return {field: generate_field(schema.fields[field]) for field in schema.fields if not field.endswith("DEPRECATED")} + + +def generate_field(field: capnp.lib.capnp._StructSchemaField) -> str | list[Any] | dict[str, Any]: + def schema_walker(field): + yield field.schema + + s = field.schema + while hasattr(s, 'elementType'): + s = s.elementType + yield s + + def type_walker(field): + yield field.proto.slot.type + + t = field.proto.slot.type + while hasattr(getattr(t, t.which()), 'elementType'): + t = getattr(t, t.which()).elementType + yield t + + if field.proto.which() == "slot": + schema_gen, type_gen = schema_walker(field), type_walker(field) + return generate_type(type_gen, schema_gen) + else: + return generate_struct(field.schema) diff --git a/system/webrtc/tests/test_stream_session.py b/system/webrtc/tests/test_stream_session.py new file mode 100644 index 0000000000..113fa5e7e6 --- /dev/null +++ b/system/webrtc/tests/test_stream_session.py @@ -0,0 +1,101 @@ +import asyncio +import json +# for aiortc and its dependencies +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) +warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel + +from aiortc import RTCDataChannel +from aiortc.mediastreams import VIDEO_CLOCK_RATE, VIDEO_TIME_BASE +import capnp +import pyaudio +from cereal import messaging, log + +from openpilot.system.webrtc.webrtcd import CerealOutgoingMessageProxy, CerealIncomingMessageProxy +from openpilot.system.webrtc.device.video import LiveStreamVideoStreamTrack +from openpilot.system.webrtc.device.audio import AudioInputStreamTrack +from openpilot.common.realtime import DT_DMON + + +class TestStreamSession: + def setup_method(self): + self.loop = asyncio.new_event_loop() + + def teardown_method(self): + self.loop.stop() + self.loop.close() + + def test_outgoing_proxy(self, mocker): + test_msg = log.Event.new_message() + test_msg.logMonoTime = 123 + test_msg.valid = True + test_msg.customReservedRawData0 = b"test" + expected_dict = {"type": "customReservedRawData0", "logMonoTime": 123, "valid": True, "data": "test"} + expected_json = json.dumps(expected_dict).encode() + + channel = mocker.Mock(spec=RTCDataChannel) + mocked_submaster = messaging.SubMaster(["customReservedRawData0"]) + def mocked_update(t): + mocked_submaster.update_msgs(0, [test_msg]) + + mocker.patch.object(messaging.SubMaster, "update", side_effect=mocked_update) + proxy = CerealOutgoingMessageProxy(mocked_submaster) + proxy.add_channel(channel) + + proxy.update() + + channel.send.assert_called_once_with(expected_json) + + def test_incoming_proxy(self, mocker): + tested_msgs = [ + {"type": "customReservedRawData0", "data": "test"}, # primitive + {"type": "can", "data": [{"address": 0, "dat": "", "src": 0}]}, # list + {"type": "testJoystick", "data": {"axes": [0, 0], "buttons": [False]}}, # dict + ] + + mocked_pubmaster = mocker.MagicMock(spec=messaging.PubMaster) + + proxy = CerealIncomingMessageProxy(mocked_pubmaster) + + for msg in tested_msgs: + proxy.send(json.dumps(msg).encode()) + + mocked_pubmaster.send.assert_called_once() + mt, md = mocked_pubmaster.send.call_args.args + assert mt == msg["type"] + assert isinstance(md, capnp._DynamicStructBuilder) + assert hasattr(md, msg["type"]) + + mocked_pubmaster.reset_mock() + + def test_livestream_track(self, mocker): + fake_msg = messaging.new_message("livestreamDriverEncodeData") + + config = {"receive.return_value": fake_msg.to_bytes()} + mocker.patch("msgq.SubSocket", spec=True, **config) + track = LiveStreamVideoStreamTrack("driver") + + assert track.id.startswith("driver") + assert track.codec_preference() == "H264" + + for i in range(5): + packet = self.loop.run_until_complete(track.recv()) + assert packet.time_base == VIDEO_TIME_BASE + assert packet.pts == int(i * DT_DMON * VIDEO_CLOCK_RATE) + assert packet.size == 0 + + def test_input_audio_track(self, mocker): + packet_time, rate = 0.02, 16000 + sample_count = int(packet_time * rate) + mocked_stream = mocker.MagicMock(spec=pyaudio.Stream) + mocked_stream.read.return_value = b"\x00" * 2 * sample_count + + config = {"open.side_effect": lambda *args, **kwargs: mocked_stream} + mocker.patch("pyaudio.PyAudio", spec=True, **config) + track = AudioInputStreamTrack(audio_format=pyaudio.paInt16, packet_time=packet_time, rate=rate) + + for i in range(5): + frame = self.loop.run_until_complete(track.recv()) + assert frame.rate == rate + assert frame.samples == sample_count + assert frame.pts == i * sample_count diff --git a/system/webrtc/tests/test_webrtcd.py b/system/webrtc/tests/test_webrtcd.py new file mode 100644 index 0000000000..4fa6d8953f --- /dev/null +++ b/system/webrtc/tests/test_webrtcd.py @@ -0,0 +1,65 @@ +import pytest +import asyncio +import json +# for aiortc and its dependencies +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) +warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel + +from openpilot.system.webrtc.webrtcd import get_stream + +import aiortc +from teleoprtc import WebRTCOfferBuilder +from parameterized import parameterized_class + + +@parameterized_class(("in_services", "out_services"), [ + (["testJoystick"], ["carState"]), + ([], ["carState"]), + (["testJoystick"], []), + ([], []), +]) +@pytest.mark.asyncio +class TestWebrtcdProc: + async def assertCompletesWithTimeout(self, awaitable, timeout=1): + try: + async with asyncio.timeout(timeout): + await awaitable + except TimeoutError: + pytest.fail("Timeout while waiting for awaitable to complete") + + async def test_webrtcd(self, mocker): + mock_request = mocker.MagicMock() + async def connect(offer): + body = {'sdp': offer.sdp, 'cameras': offer.video, 'bridge_services_in': self.in_services, 'bridge_services_out': self.out_services} + mock_request.json.side_effect = mocker.AsyncMock(return_value=body) + response = await get_stream(mock_request) + response_json = json.loads(response.text) + return aiortc.RTCSessionDescription(**response_json) + + builder = WebRTCOfferBuilder(connect) + builder.offer_to_receive_video_stream("road") + builder.offer_to_receive_audio_stream() + if len(self.in_services) > 0 or len(self.out_services) > 0: + builder.add_messaging() + + stream = builder.stream() + + await self.assertCompletesWithTimeout(stream.start()) + await self.assertCompletesWithTimeout(stream.wait_for_connection()) + + assert stream.has_incoming_video_track("road") + assert stream.has_incoming_audio_track() + assert stream.has_messaging_channel() == (len(self.in_services) > 0 or len(self.out_services) > 0) + + video_track, audio_track = stream.get_incoming_video_track("road"), stream.get_incoming_audio_track() + await self.assertCompletesWithTimeout(video_track.recv()) + await self.assertCompletesWithTimeout(audio_track.recv()) + + await self.assertCompletesWithTimeout(stream.stop()) + + # cleanup, very implementation specific, test may break if it changes + assert mock_request.app["streams"].__setitem__.called, "Implementation changed, please update this test" + _, session = mock_request.app["streams"].__setitem__.call_args.args + await self.assertCompletesWithTimeout(session.post_run_cleanup()) + diff --git a/system/webrtc/webrtcd.py b/system/webrtc/webrtcd.py new file mode 100755 index 0000000000..fb93e565ff --- /dev/null +++ b/system/webrtc/webrtcd.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 + +import argparse +import asyncio +import json +import uuid +import logging +from dataclasses import dataclass, field +from typing import Any, TYPE_CHECKING + +# aiortc and its dependencies have lots of internal warnings :( +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) +warnings.filterwarnings("ignore", category=RuntimeWarning) # TODO: remove this when google-crc32c publish a python3.12 wheel + +import capnp +from aiohttp import web +if TYPE_CHECKING: + from aiortc.rtcdatachannel import RTCDataChannel + +from openpilot.system.webrtc.schema import generate_field +from cereal import messaging, log + + +class CerealOutgoingMessageProxy: + def __init__(self, sm: messaging.SubMaster): + self.sm = sm + self.channels: list[RTCDataChannel] = [] + + def add_channel(self, channel: 'RTCDataChannel'): + self.channels.append(channel) + + def to_json(self, msg_content: Any): + if isinstance(msg_content, capnp._DynamicStructReader): + msg_dict = msg_content.to_dict() + elif isinstance(msg_content, capnp._DynamicListReader): + msg_dict = [self.to_json(msg) for msg in msg_content] + elif isinstance(msg_content, bytes): + msg_dict = msg_content.decode() + else: + msg_dict = msg_content + + return msg_dict + + def update(self): + # this is blocking in async context... + self.sm.update(0) + for service, updated in self.sm.updated.items(): + if not updated: + continue + msg_dict = self.to_json(self.sm[service]) + mono_time, valid = self.sm.logMonoTime[service], self.sm.valid[service] + outgoing_msg = {"type": service, "logMonoTime": mono_time, "valid": valid, "data": msg_dict} + encoded_msg = json.dumps(outgoing_msg).encode() + for channel in self.channels: + channel.send(encoded_msg) + + +class CerealIncomingMessageProxy: + def __init__(self, pm: messaging.PubMaster): + self.pm = pm + + def send(self, message: bytes): + msg_json = json.loads(message) + msg_type, msg_data = msg_json["type"], msg_json["data"] + size = None + if not isinstance(msg_data, dict): + size = len(msg_data) + + msg = messaging.new_message(msg_type, size=size) + setattr(msg, msg_type, msg_data) + self.pm.send(msg_type, msg) + + +class CerealProxyRunner: + def __init__(self, proxy: CerealOutgoingMessageProxy): + self.proxy = proxy + self.is_running = False + self.task = None + self.logger = logging.getLogger("webrtcd") + + def start(self): + assert self.task is None + self.task = asyncio.create_task(self.run()) + + def stop(self): + if self.task is None or self.task.done(): + return + self.task.cancel() + self.task = None + + async def run(self): + from aiortc.exceptions import InvalidStateError + + while True: + try: + self.proxy.update() + except InvalidStateError: + self.logger.warning("Cereal outgoing proxy invalid state (connection closed)") + break + except Exception: + self.logger.exception("Cereal outgoing proxy failure") + await asyncio.sleep(0.01) + + +class DynamicPubMaster(messaging.PubMaster): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.lock = asyncio.Lock() + + async def add_services_if_needed(self, services): + async with self.lock: + for service in services: + if service not in self.sock: + self.sock[service] = messaging.pub_sock(service) + + +class StreamSession: + shared_pub_master = DynamicPubMaster([]) + + def __init__(self, sdp: str, cameras: list[str], incoming_services: list[str], outgoing_services: list[str], debug_mode: bool = False): + from aiortc.mediastreams import VideoStreamTrack, AudioStreamTrack + from aiortc.contrib.media import MediaBlackhole + from openpilot.system.webrtc.device.video import LiveStreamVideoStreamTrack + from openpilot.system.webrtc.device.audio import AudioInputStreamTrack, AudioOutputSpeaker + from teleoprtc import WebRTCAnswerBuilder + from teleoprtc.info import parse_info_from_offer + + config = parse_info_from_offer(sdp) + builder = WebRTCAnswerBuilder(sdp) + + assert len(cameras) == config.n_expected_camera_tracks, "Incoming stream has misconfigured number of video tracks" + for cam in cameras: + builder.add_video_stream(cam, LiveStreamVideoStreamTrack(cam) if not debug_mode else VideoStreamTrack()) + if config.expected_audio_track: + builder.add_audio_stream(AudioInputStreamTrack() if not debug_mode else AudioStreamTrack()) + if config.incoming_audio_track: + self.audio_output_cls = AudioOutputSpeaker if not debug_mode else MediaBlackhole + builder.offer_to_receive_audio_stream() + + self.stream = builder.stream() + self.identifier = str(uuid.uuid4()) + + self.incoming_bridge: CerealIncomingMessageProxy | None = None + self.incoming_bridge_services = incoming_services + self.outgoing_bridge: CerealOutgoingMessageProxy | None = None + self.outgoing_bridge_runner: CerealProxyRunner | None = None + if len(incoming_services) > 0: + self.incoming_bridge = CerealIncomingMessageProxy(self.shared_pub_master) + if len(outgoing_services) > 0: + self.outgoing_bridge = CerealOutgoingMessageProxy(messaging.SubMaster(outgoing_services)) + self.outgoing_bridge_runner = CerealProxyRunner(self.outgoing_bridge) + + self.audio_output: AudioOutputSpeaker | MediaBlackhole | None = None + self.run_task: asyncio.Task | None = None + self.logger = logging.getLogger("webrtcd") + self.logger.info("New stream session (%s), cameras %s, audio in %s out %s, incoming services %s, outgoing services %s", + self.identifier, cameras, config.incoming_audio_track, config.expected_audio_track, incoming_services, outgoing_services) + + def start(self): + self.run_task = asyncio.create_task(self.run()) + + def stop(self): + if self.run_task.done(): + return + self.run_task.cancel() + self.run_task = None + asyncio.run(self.post_run_cleanup()) + + async def get_answer(self): + return await self.stream.start() + + async def message_handler(self, message: bytes): + assert self.incoming_bridge is not None + try: + self.incoming_bridge.send(message) + except Exception: + self.logger.exception("Cereal incoming proxy failure") + + async def run(self): + try: + await self.stream.wait_for_connection() + if self.stream.has_messaging_channel(): + if self.incoming_bridge is not None: + await self.shared_pub_master.add_services_if_needed(self.incoming_bridge_services) + self.stream.set_message_handler(self.message_handler) + if self.outgoing_bridge_runner is not None: + channel = self.stream.get_messaging_channel() + self.outgoing_bridge_runner.proxy.add_channel(channel) + self.outgoing_bridge_runner.start() + if self.stream.has_incoming_audio_track(): + track = self.stream.get_incoming_audio_track(buffered=False) + self.audio_output = self.audio_output_cls() + self.audio_output.addTrack(track) + self.audio_output.start() + self.logger.info("Stream session (%s) connected", self.identifier) + + await self.stream.wait_for_disconnection() + await self.post_run_cleanup() + + self.logger.info("Stream session (%s) ended", self.identifier) + except Exception: + self.logger.exception("Stream session failure") + + async def post_run_cleanup(self): + await self.stream.stop() + if self.outgoing_bridge is not None: + self.outgoing_bridge_runner.stop() + if self.audio_output: + self.audio_output.stop() + + +@dataclass +class StreamRequestBody: + sdp: str + cameras: list[str] + bridge_services_in: list[str] = field(default_factory=list) + bridge_services_out: list[str] = field(default_factory=list) + + +async def get_stream(request: 'web.Request'): + stream_dict, debug_mode = request.app['streams'], request.app['debug'] + raw_body = await request.json() + body = StreamRequestBody(**raw_body) + + session = StreamSession(body.sdp, body.cameras, body.bridge_services_in, body.bridge_services_out, debug_mode) + answer = await session.get_answer() + session.start() + + stream_dict[session.identifier] = session + + return web.json_response({"sdp": answer.sdp, "type": answer.type}) + + +async def get_schema(request: 'web.Request'): + services = request.query["services"].split(",") + services = [s for s in services if s] + assert all(s in log.Event.schema.fields and not s.endswith("DEPRECATED") for s in services), "Invalid service name" + schema_dict = {s: generate_field(log.Event.schema.fields[s]) for s in services} + return web.json_response(schema_dict) + + +async def on_shutdown(app: 'web.Application'): + for session in app['streams'].values(): + session.stop() + del app['streams'] + + +def webrtcd_thread(host: str, port: int, debug: bool): + logging.basicConfig(level=logging.CRITICAL, handlers=[logging.StreamHandler()]) + logging_level = logging.DEBUG if debug else logging.INFO + logging.getLogger("WebRTCStream").setLevel(logging_level) + logging.getLogger("webrtcd").setLevel(logging_level) + + app = web.Application() + + app['streams'] = dict() + app['debug'] = debug + app.on_shutdown.append(on_shutdown) + app.router.add_post("/stream", get_stream) + app.router.add_get("/schema", get_schema) + + web.run_app(app, host=host, port=port) + + +def main(): + parser = argparse.ArgumentParser(description="WebRTC daemon") + parser.add_argument("--host", type=str, default="0.0.0.0", help="Host to listen on") + parser.add_argument("--port", type=int, default=5001, help="Port to listen on") + parser.add_argument("--debug", action="store_true", help="Enable debug mode") + args = parser.parse_args() + + webrtcd_thread(args.host, args.port, args.debug) + + +if __name__=="__main__": + main() diff --git a/teleoprtc b/teleoprtc new file mode 120000 index 0000000000..3d3dbc8dea --- /dev/null +++ b/teleoprtc @@ -0,0 +1 @@ +teleoprtc_repo/teleoprtc \ No newline at end of file diff --git a/teleoprtc_repo/.gitignore b/teleoprtc_repo/.gitignore new file mode 100644 index 0000000000..e9863cb7ee --- /dev/null +++ b/teleoprtc_repo/.gitignore @@ -0,0 +1,163 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +*.swp +*.swo \ No newline at end of file diff --git a/teleoprtc_repo/.pre-commit-config.yaml b/teleoprtc_repo/.pre-commit-config.yaml new file mode 100644 index 0000000000..89e745c076 --- /dev/null +++ b/teleoprtc_repo/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-ast + - id: check-json + - id: check-xml + - id: check-yaml + - id: check-merge-conflict + - id: check-symlinks + - id: check-executables-have-shebangs + - id: check-shebang-scripts-are-executable +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.7.1 + hooks: + - id: mypy +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.2 + hooks: + - id: ruff diff --git a/teleoprtc_repo/LICENSE b/teleoprtc_repo/LICENSE new file mode 100644 index 0000000000..cae6fd0a18 --- /dev/null +++ b/teleoprtc_repo/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023, 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/teleoprtc_repo/README.md b/teleoprtc_repo/README.md new file mode 100644 index 0000000000..f20d25db50 --- /dev/null +++ b/teleoprtc_repo/README.md @@ -0,0 +1,4 @@ +# teleoprtc + +Set of abstractions for webRTC communication with [openpilot](https://github.com/commaai/openpilot). + diff --git a/teleoprtc_repo/examples/face_detection/README.md b/teleoprtc_repo/examples/face_detection/README.md new file mode 100644 index 0000000000..74d6ea2cf0 --- /dev/null +++ b/teleoprtc_repo/examples/face_detection/README.md @@ -0,0 +1,10 @@ +## Face detection demo + +Run simple face detection model on video stream from driver camera of comma three. + +This example streams video frames, runs face-detection model and displays window with live detection results (bounding boxes). + +```sh +# pass the ip address of comma three, if running remotely (by default localhost) +python3 face_detection.py [--host comma-ip-address] +``` \ No newline at end of file diff --git a/teleoprtc_repo/examples/face_detection/face_detection.py b/teleoprtc_repo/examples/face_detection/face_detection.py new file mode 100755 index 0000000000..f6fba90640 --- /dev/null +++ b/teleoprtc_repo/examples/face_detection/face_detection.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +import argparse +import asyncio + +import aiortc +import aiohttp +import cv2 +import pygame + +from teleoprtc import WebRTCOfferBuilder, StreamingOffer + + +def pygame_should_quit(): + for event in pygame.event.get(): + if event.type == pygame.QUIT: + return True + return False + + +class WebrtcdConnectionProvider: + """ + Connection provider reaching webrtcd server on comma three + """ + def __init__(self, host, port=5001): + self.url = f"http://{host}:{port}/stream" + + async def __call__(self, offer: StreamingOffer) -> aiortc.RTCSessionDescription: + async with aiohttp.ClientSession() as session: + body = {'sdp': offer.sdp, 'cameras': offer.video, 'bridge_services_in': [], 'bridge_services_out': []} + async with session.post(self.url, json=body) as resp: + payload = await resp.json() + answer = aiortc.RTCSessionDescription(**payload) + return answer + + +class FaceDetector: + """ + Simple face detector using opencv + """ + def __init__(self): + self.classifier = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') + + def detect(self, array): + gray_array = cv2.cvtColor(array, cv2.COLOR_RGB2GRAY) + faces = self.classifier.detectMultiScale(gray_array, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) + return faces + + def draw(self, array, faces): + for (x, y, w, h) in faces: + cv2.rectangle(array, (x, y), (x + w, y + h), (0, 255, 0), 2) + return array + + +async def run_face_detection(stream): + # setup pygame window + pygame.init() + screen_width, screen_height = 1280, 720 + screen = pygame.display.set_mode((screen_width, screen_height)) + pygame.display.set_caption("Face detection demo") + surface = pygame.Surface((screen_width, screen_height)) + + # get the driver camera video track from the stream + # generally its better to reuse the track object instead of getting it every time + track = stream.get_incoming_video_track("driver", buffered=False) + # cv2 face detector + detector = FaceDetector() + while stream.is_connected_and_ready and not pygame_should_quit(): + try: + # receive frame as pyAV VideoFrame, convert to rgb24 numpy array + frame = await track.recv() + array = frame.to_ndarray(format="rgb24") + + # detect faces and draw rects around them + resized_array = cv2.resize(array, (screen_width, screen_height)) + faces = detector.detect(resized_array) + detector.draw(resized_array, faces) + + # display the image + pygame.surfarray.blit_array(surface, resized_array.swapaxes(0, 1)) + screen.blit(surface, (0, 0)) + pygame.display.flip() + + print("Received frame from", "driver", frame.time) + except aiortc.mediastreams.MediaStreamError: + break + + pygame.quit() + await stream.stop() + + +async def run(args): + # build your own the offer stream + builder = WebRTCOfferBuilder(WebrtcdConnectionProvider(args.host)) + # request video stream from drivers camera + builder.offer_to_receive_video_stream("driver") + # add cereal messaging streaming support + builder.add_messaging() + + stream = builder.stream() + + # start the stream then wait for connection + # server will receive the offer and attempt to fulfill it + await stream.start() + await stream.wait_for_connection() + # all the tracks and channel are ready to be used at this point + + assert stream.has_incoming_video_track("driver") and stream.has_messaging_channel() + + # run face detection loop on the drivers camera + await run_face_detection(stream) + + +if __name__=='__main__': + parser = argparse.ArgumentParser() + parser.add_argument("--host", default="localhost", help="Host for webrtcd server") + + args = parser.parse_args() + asyncio.run(run(args)) diff --git a/teleoprtc_repo/examples/videostream_cli/README.md b/teleoprtc_repo/examples/videostream_cli/README.md new file mode 100644 index 0000000000..02b49b1085 --- /dev/null +++ b/teleoprtc_repo/examples/videostream_cli/README.md @@ -0,0 +1 @@ +# VideoStream CLI diff --git a/teleoprtc_repo/examples/videostream_cli/cli.py b/teleoprtc_repo/examples/videostream_cli/cli.py new file mode 100755 index 0000000000..9640edc197 --- /dev/null +++ b/teleoprtc_repo/examples/videostream_cli/cli.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python + +import argparse +import asyncio +import dataclasses +import json +import logging + +import aiortc +from aiortc.mediastreams import VideoStreamTrack, AudioStreamTrack + +from teleoprtc import WebRTCOfferBuilder, WebRTCAnswerBuilder +from teleoprtc.stream import StreamingOffer +from teleoprtc.info import parse_info_from_offer + + +async def async_input(): + return await asyncio.to_thread(input) + + +async def StdioConnectionProvider(offer: StreamingOffer) -> aiortc.RTCSessionDescription: + print("-- Please send this JSON to server --") + print(json.dumps(dataclasses.asdict(offer))) + print("-- Press enter when the answer is ready --") + raw_payload = await async_input() + payload = json.loads(raw_payload) + answer = aiortc.RTCSessionDescription(**payload) + + return answer + + +async def run_answer(args): + streams = [] + while True: + print("-- Please enter a JSON from client --") + raw_payload = await async_input() + + payload = json.loads(raw_payload) + offer = StreamingOffer(**payload) + info = parse_info_from_offer(offer.sdp) + assert len(offer.video) == info.n_expected_camera_tracks + video_tracks = [VideoStreamTrack() for _ in offer.video] + audio_tracks = [AudioStreamTrack()] if info.expected_audio_track else [] + + stream_builder = WebRTCAnswerBuilder(offer.sdp) + for cam, track in zip(offer.video, video_tracks, strict=True): + stream_builder.add_video_stream(cam, track) + for track in audio_tracks: + stream_builder.add_audio_stream(track) + stream = stream_builder.stream() + answer = await stream.start() + streams.append(stream) + + print("-- Please send this JSON to client --") + print(json.dumps({"sdp": answer.sdp, "type": answer.type})) + + await stream.wait_for_connection() + + +async def run_offer(args): + stream_builder = WebRTCOfferBuilder(StdioConnectionProvider) + for cam in args.cameras: + stream_builder.offer_to_receive_video_stream(cam) + if args.audio: + stream_builder.offer_to_receive_audio_stream() + if args.messaging: + stream_builder.add_messaging() + stream = stream_builder.stream() + _ = await stream.start() + await stream.wait_for_connection() + print("Connection established and all tracks are ready") + + video_tracks = [stream.get_incoming_video_track(cam, False) for cam in args.cameras] + audio_track = None + if stream.has_incoming_audio_track(): + audio_track = stream.get_incoming_audio_track(False) + while True: + try: + frames = await asyncio.gather(*[track.recv() for track in video_tracks]) + for key, frame in zip(args.cameras, frames, strict=True): + print("Received frame from", key, frame.time) + if audio_track: + frame = await audio_track.recv() + print("Received frame from audio", frame.time) + except aiortc.mediastreams.MediaStreamError: + return + print("=====================================") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest="command", required=True) + + offer_parser = subparsers.add_parser("offer", description="Create offer stream") + offer_parser.add_argument("--audio", action="store_true", help="Offer to receive audio") + offer_parser.add_argument("--messaging", action="store_true", help="Add messaging support") + offer_parser.add_argument("cameras", metavar="CAMERA", type=str, nargs="+", default=[], help="Camera types to stream") + + answer_parser = subparsers.add_parser("answer", description="Create answer stream") + + args = parser.parse_args() + + logging.basicConfig(level=logging.CRITICAL, handlers=[logging.StreamHandler()]) + logger = logging.getLogger("WebRTCStream") + logger.setLevel(logging.DEBUG) + + loop = asyncio.get_event_loop() + if args.command == "offer": + loop.run_until_complete(run_offer(args)) + elif args.command == "answer": + loop.run_until_complete(run_answer(args)) diff --git a/teleoprtc_repo/pyproject.toml b/teleoprtc_repo/pyproject.toml new file mode 100644 index 0000000000..b93df69fce --- /dev/null +++ b/teleoprtc_repo/pyproject.toml @@ -0,0 +1,52 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "teleoprtc" +version = "1.0.1" +authors = [{ name="Vehicle Researcher", email="user@comma.ai" }] +description = "Comma webRTC abstractions" +readme = "README.md" +license = { file="LICENSE" } +requires-python = ">=3.8" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", +] +dependencies = [ + "aiortc>=1.6.0", + "aiohttp>=3.7.0", + "av>=11.0.0,<13.0.0", + "numpy>=1.19.0", +] + +[project.optional-dependencies] +dev = [ + "parameterized>=0.8", + "pre-commit", + "pytest", + "pytest-asyncio", + "pytest-xdist" +] + +[project.urls] +"Homepage" = "https://github.com/commaai/teleoprtc" +"Bug Tracker" = "https://github.com/commaai/teleoprtc/issues" + +# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml +[tool.ruff] +line-length = 160 +target-version="py38" + +[tool.ruff.lint] +select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF008", "RUF100", "A", "B", "TID251"] +ignore = ["W292", "E741", "E402", "C408", "ISC003", "B027", "B024"] +flake8-implicit-str-concat.allow-multiline=false + +[tool.ruff.lint.flake8-tidy-imports.banned-api] +"unittest".msg = "Use pytest" + +[tool.pytest.ini_options] +addopts = "--durations=10 -n auto" diff --git a/teleoprtc_repo/scripts/bump_tag.sh b/teleoprtc_repo/scripts/bump_tag.sh new file mode 100755 index 0000000000..0f15c558e0 --- /dev/null +++ b/teleoprtc_repo/scripts/bump_tag.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +BRANCH="$(git branch --show-current)" +TOML_VERSION="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])')" +LATEST_TAG_VERSION="$(git tag --list | sort -V -r | head -n 1)" +TAGGED_VERSION="" + +if [[ "$BRANCH" != "master" ]]; then + echo "Not on master branch." + exit 1 +fi + +if [[ "$TOML_VERSION" == "$LATEST_TAG_VERSION" ]]; then + TAGGED_VERSION=$(echo "$TOML_VERSION" | python3 -c "v = input().split('.'); v[-1]=str(int(v[-1])+1); print('.'.join(v))") + sed -i "s/version = \"$TOML_VERSION\"/version = \"$TAGGED_VERSION\"/" pyproject.toml +elif [[ -z "$LATEST_TAG_VERSION" ]] || printf "$LATEST_TAG_VERSION\n$TOML_VERSION" | sort -V -C; then + TAGGED_VERSION="$TOML_VERSION" +else + echo "Version in pyproject.toml is lower than the latest tag version." + exit 1 +fi + +echo "Tagging $TAGGED_VERSION..." +if [[ -n "$(git ls-files -m | grep pyproject.toml)" ]]; then + echo "Commiting pyproject.toml..." + git add pyproject.toml + git commit --no-verify -m "Bump version to $TAGGED_VERSION" +fi +git tag "$TAGGED_VERSION" diff --git a/teleoprtc_repo/scripts/publish_pypi.sh b/teleoprtc_repo/scripts/publish_pypi.sh new file mode 100755 index 0000000000..1cb0563ee0 --- /dev/null +++ b/teleoprtc_repo/scripts/publish_pypi.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -e + +if [[ -z "$1" ]]; then + echo "Usage: $0 " + exit 1 +fi +PYPI_TOKEN="$1" + +# install required packages +pip install --upgrade twine build + +# build the package +python3 -m build + +# upload to PyPI +REPOSITORY="" +if [[ -n "$TEST_UPLOAD" ]]; then + REPOSITORY="--repository testpypi" +fi + +python3 -m twine upload $REPOSITORY --username __token__ --password "$PYPI_TOKEN" dist/* diff --git a/teleoprtc_repo/teleoprtc/__init__.py b/teleoprtc_repo/teleoprtc/__init__.py new file mode 100644 index 0000000000..4104f949bc --- /dev/null +++ b/teleoprtc_repo/teleoprtc/__init__.py @@ -0,0 +1,2 @@ +from teleoprtc.builder import WebRTCOfferBuilder, WebRTCAnswerBuilder # noqa +from teleoprtc.stream import WebRTCBaseStream, StreamingOffer, ConnectionProvider, MessageHandler # noqa \ No newline at end of file diff --git a/teleoprtc_repo/teleoprtc/builder.py b/teleoprtc_repo/teleoprtc/builder.py new file mode 100644 index 0000000000..d054f9feda --- /dev/null +++ b/teleoprtc_repo/teleoprtc/builder.py @@ -0,0 +1,79 @@ +import abc +from typing import Dict, List + +import aiortc + +from teleoprtc.stream import WebRTCBaseStream, WebRTCOfferStream, WebRTCAnswerStream, ConnectionProvider +from teleoprtc.tracks import TiciVideoStreamTrack, TiciTrackWrapper + + +class WebRTCStreamBuilder(abc.ABC): + @abc.abstractmethod + def stream(self) -> WebRTCBaseStream: + raise NotImplementedError + + +class WebRTCOfferBuilder(WebRTCStreamBuilder): + def __init__(self, connection_provider: ConnectionProvider): + self.connection_provider = connection_provider + self.requested_camera_types: List[str] = [] + self.requested_audio = False + self.audio_tracks: List[aiortc.MediaStreamTrack] = [] + self.messaging_enabled = False + + def offer_to_receive_video_stream(self, camera_type: str): + assert camera_type in ["driver", "wideRoad", "road"] + self.requested_camera_types.append(camera_type) + + def offer_to_receive_audio_stream(self): + self.requested_audio = True + + def add_audio_stream(self, track: aiortc.MediaStreamTrack): + assert len(self.audio_tracks) == 0 + self.audio_tracks = [track] + + def add_messaging(self): + self.messaging_enabled = True + + def stream(self) -> WebRTCBaseStream: + return WebRTCOfferStream( + self.connection_provider, + consumed_camera_types=self.requested_camera_types, + consume_audio=self.requested_audio, + video_producer_tracks=[], + audio_producer_tracks=self.audio_tracks, + should_add_data_channel=self.messaging_enabled, + ) + + +class WebRTCAnswerBuilder(WebRTCStreamBuilder): + def __init__(self, offer_sdp: str): + self.offer_sdp = offer_sdp + self.video_tracks: Dict[str, aiortc.MediaStreamTrack] = dict() + self.requested_audio = False + self.audio_tracks: List[aiortc.MediaStreamTrack] = [] + + def offer_to_receive_audio_stream(self): + self.requested_audio = True + + def add_video_stream(self, camera_type: str, track: aiortc.MediaStreamTrack): + assert camera_type not in self.video_tracks + assert camera_type in ["driver", "wideRoad", "road"] + if not isinstance(track, TiciVideoStreamTrack): + track = TiciTrackWrapper(camera_type, track) + self.video_tracks[camera_type] = track + + def add_audio_stream(self, track: aiortc.MediaStreamTrack): + assert len(self.audio_tracks) == 0 + self.audio_tracks = [track] + + def stream(self) -> WebRTCBaseStream: + description = aiortc.RTCSessionDescription(sdp=self.offer_sdp, type="offer") + return WebRTCAnswerStream( + description, + consumed_camera_types=[], + consume_audio=self.requested_audio, + video_producer_tracks=list(self.video_tracks.values()), + audio_producer_tracks=self.audio_tracks, + should_add_data_channel=False, + ) diff --git a/teleoprtc_repo/teleoprtc/info.py b/teleoprtc_repo/teleoprtc/info.py new file mode 100644 index 0000000000..fb786feda1 --- /dev/null +++ b/teleoprtc_repo/teleoprtc/info.py @@ -0,0 +1,26 @@ +import dataclasses + +import aiortc + + +@dataclasses.dataclass +class StreamingMediaInfo: + n_expected_camera_tracks: int + expected_audio_track: bool + incoming_audio_track: bool + incoming_datachannel: bool + + +def parse_info_from_offer(sdp: str) -> StreamingMediaInfo: + """ + helper function to parse info about outgoing and incoming streams from an offer sdp + """ + desc = aiortc.sdp.SessionDescription.parse(sdp) + audio_tracks = [m for m in desc.media if m.kind == "audio"] + video_tracks = [m for m in desc.media if m.kind == "video" and m.direction in ["recvonly", "sendrecv"]] + application_tracks = [m for m in desc.media if m.kind == "application"] + has_incoming_audio_track = next((t for t in audio_tracks if t.direction in ["sendonly", "sendrecv"]), None) is not None + has_incoming_datachannel = len(application_tracks) > 0 + expects_outgoing_audio_track = next((t for t in audio_tracks if t.direction in ["recvonly", "sendrecv"]), None) is not None + + return StreamingMediaInfo(len(video_tracks), expects_outgoing_audio_track, has_incoming_audio_track, has_incoming_datachannel) diff --git a/teleoprtc_repo/teleoprtc/stream.py b/teleoprtc_repo/teleoprtc/stream.py new file mode 100644 index 0000000000..7b4172098e --- /dev/null +++ b/teleoprtc_repo/teleoprtc/stream.py @@ -0,0 +1,302 @@ +import abc +import asyncio +import dataclasses +import logging +from typing import Any, Awaitable, Callable, Dict, List, Optional + +import aiortc +from aiortc.contrib.media import MediaRelay + +from teleoprtc.tracks import parse_video_track_id + + +@dataclasses.dataclass +class StreamingOffer: + sdp: str + video: List[str] + + +ConnectionProvider = Callable[[StreamingOffer], Awaitable[aiortc.RTCSessionDescription]] +MessageHandler = Callable[[bytes], Awaitable[None]] + + +class WebRTCBaseStream(abc.ABC): + def __init__(self, + consumed_camera_types: List[str], + consume_audio: bool, + video_producer_tracks: List[aiortc.MediaStreamTrack], + audio_producer_tracks: List[aiortc.MediaStreamTrack], + should_add_data_channel: bool): + self.peer_connection = aiortc.RTCPeerConnection() + self.media_relay = MediaRelay() + self.expected_incoming_camera_types = consumed_camera_types + self.expected_incoming_audio = consume_audio + self.expected_number_of_incoming_media: Optional[int] = None + + self.incoming_camera_tracks: Dict[str, aiortc.MediaStreamTrack] = dict() + self.incoming_audio_tracks: List[aiortc.MediaStreamTrack] = [] + self.outgoing_video_tracks: List[aiortc.MediaStreamTrack] = video_producer_tracks + self.outgoing_audio_tracks: List[aiortc.MediaStreamTrack] = audio_producer_tracks + + self.should_add_data_channel = should_add_data_channel + self.messaging_channel: Optional[aiortc.RTCDataChannel] = None + self.incoming_message_handlers: List[MessageHandler] = [] + + self.incoming_media_ready_event = asyncio.Event() + self.messaging_channel_ready_event = asyncio.Event() + self.connection_attempted_event = asyncio.Event() + self.connection_stopped_event = asyncio.Event() + + self.peer_connection.on("connectionstatechange", self._on_connectionstatechange) + self.peer_connection.on("datachannel", self._on_incoming_datachannel) + self.peer_connection.on("track", self._on_incoming_track) + + self.logger = logging.getLogger("WebRTCStream") + + def _log_debug(self, msg: Any, *args): + self.logger.debug(f"{type(self)}() {msg}", *args) + + @property + def _number_of_incoming_media(self) -> int: + media = len(self.incoming_camera_tracks) + len(self.incoming_audio_tracks) + # if stream does not add data_channel, then it means its incoming + media += int(self.messaging_channel is not None) if not self.should_add_data_channel else 0 + return media + + def _add_consumer_transceivers(self): + for _ in self.expected_incoming_camera_types: + self.peer_connection.addTransceiver("video", direction="recvonly") + if self.expected_incoming_audio: + self.peer_connection.addTransceiver("audio", direction="recvonly") + + def _find_trackless_transceiver(self, kind: str) -> Optional[aiortc.RTCRtpTransceiver]: + transceivers = self.peer_connection.getTransceivers() + target_transceiver = None + for t in transceivers: + if t.kind == kind and t.sender.track is None: + target_transceiver = t + break + + return target_transceiver + + def _add_producer_tracks(self): + for track in self.outgoing_video_tracks: + target_transceiver = self._find_trackless_transceiver(track.kind) + if target_transceiver is None: + self.peer_connection.addTransceiver(track.kind, direction="sendonly") + + sender = self.peer_connection.addTrack(track) + if hasattr(track, "codec_preference") and track.codec_preference() is not None: + transceiver = next(t for t in self.peer_connection.getTransceivers() if t.sender == sender) + self._force_codec(transceiver, track.codec_preference(), "video") + for track in self.outgoing_audio_tracks: + target_transceiver = self._find_trackless_transceiver(track.kind) + if target_transceiver is None: + self.peer_connection.addTransceiver(track.kind, direction="sendonly") + + self.peer_connection.addTrack(track) + + def _add_messaging_channel(self, channel: Optional[aiortc.RTCDataChannel] = None): + if not channel: + channel = self.peer_connection.createDataChannel("data", ordered=True) + + for handler in self.incoming_message_handlers: + channel.on("message", handler) + + if channel.readyState == "open": + self.messaging_channel_ready_event.set() + else: + channel.on("open", lambda: self.messaging_channel_ready_event.set()) + self.messaging_channel = channel + + def _force_codec(self, transceiver: aiortc.RTCRtpTransceiver, codec: str, stream_type: str): + codec_mime = f"{stream_type}/{codec.upper()}" + rtp_codecs = aiortc.RTCRtpSender.getCapabilities(stream_type).codecs + rtp_codec = [c for c in rtp_codecs if c.mimeType == codec_mime] + transceiver.setCodecPreferences(rtp_codec) + + def _on_connectionstatechange(self): + self._log_debug("connection state is %s", self.peer_connection.connectionState) + if self.peer_connection.connectionState in ['connected', 'failed']: + self.connection_attempted_event.set() + if self.peer_connection.connectionState in ['disconnected', 'closed', 'failed']: + self.connection_stopped_event.set() + + def _on_incoming_track(self, track: aiortc.MediaStreamTrack): + self._log_debug("got track: %s %s", track.kind, track.id) + if track.kind == "video": + camera_type, _ = parse_video_track_id(track.id) + if camera_type in self.expected_incoming_camera_types: + self.incoming_camera_tracks[camera_type] = track + elif track.kind == "audio": + if self.expected_incoming_audio: + self.incoming_audio_tracks.append(track) + self._on_after_media() + + def _on_incoming_datachannel(self, channel: aiortc.RTCDataChannel): + self._log_debug("got data channel: %s", channel.label) + if channel.label == "data" and self.messaging_channel is None: + self._add_messaging_channel(channel) + self._on_after_media() + + def _on_after_media(self): + if self._number_of_incoming_media == self.expected_number_of_incoming_media: + self.incoming_media_ready_event.set() + + def _parse_incoming_streams(self, remote_sdp: str): + desc = aiortc.sdp.SessionDescription.parse(remote_sdp) + sending_medias = [m for m in desc.media if m.direction in ["sendonly", "sendrecv"]] + incoming_media_count = len(sending_medias) + if not self.should_add_data_channel: + channel_medias = [m for m in desc.media if m.kind == "application"] + incoming_media_count += len(channel_medias) + self.expected_number_of_incoming_media = incoming_media_count + + def has_incoming_video_track(self, camera_type: str) -> bool: + return camera_type in self.incoming_camera_tracks + + def has_incoming_audio_track(self) -> bool: + return len(self.incoming_audio_tracks) > 0 + + def has_messaging_channel(self) -> bool: + return self.messaging_channel is not None + + def get_incoming_video_track(self, camera_type: str, buffered: bool = False) -> aiortc.MediaStreamTrack: + assert camera_type in self.incoming_camera_tracks, "Video tracks are not enabled on this stream" + assert self.is_started, "Stream must be started" + + track = self.incoming_camera_tracks[camera_type] + relay_track = self.media_relay.subscribe(track, buffered=buffered) + return relay_track + + def get_incoming_audio_track(self, buffered: bool = False) -> aiortc.MediaStreamTrack: + assert len(self.incoming_audio_tracks) > 0, "Audio tracks are not enabled on this stream" + assert self.is_started, "Stream must be started" + + track = self.incoming_audio_tracks[0] + relay_track = self.media_relay.subscribe(track, buffered=buffered) + return relay_track + + def get_messaging_channel(self) -> aiortc.RTCDataChannel: + assert self.messaging_channel is not None, "Messaging channel is not enabled on this stream" + assert self.is_started, "Stream must be started" + + return self.messaging_channel + + def set_message_handler(self, message_handler: MessageHandler): + self.incoming_message_handlers.append(message_handler) + if self.messaging_channel is not None: + self.messaging_channel.on("message", message_handler) + + @property + def is_started(self) -> bool: + return self.peer_connection is not None and \ + self.peer_connection.localDescription is not None and \ + self.peer_connection.remoteDescription is not None and \ + self.peer_connection.connectionState != "closed" + + @property + def is_connected_and_ready(self) -> bool: + return self.peer_connection is not None and \ + self.peer_connection.connectionState == "connected" and \ + (self.expected_number_of_incoming_media == 0 or self.incoming_media_ready_event.is_set()) + + async def wait_for_connection(self): + assert self.is_started + await self.connection_attempted_event.wait() + if self.peer_connection.connectionState != 'connected': + raise ValueError("Connection failed.") + if self.expected_number_of_incoming_media: + await self.incoming_media_ready_event.wait() + if self.messaging_channel is not None: + await self.messaging_channel_ready_event.wait() + + async def wait_for_disconnection(self): + assert self.is_connected_and_ready, "Stream is not connected/ready yet (make sure wait_for_connection was awaited)" + await self.connection_stopped_event.wait() + + async def stop(self): + await self.peer_connection.close() + + @abc.abstractmethod + async def start(self) -> aiortc.RTCSessionDescription: + raise NotImplementedError + + +class WebRTCOfferStream(WebRTCBaseStream): + def __init__(self, session_provider: ConnectionProvider, *args, **kwargs): + super().__init__(*args, **kwargs) + self.session_provider = session_provider + + async def start(self) -> aiortc.RTCSessionDescription: + self._add_consumer_transceivers() + if self.should_add_data_channel: + self._add_messaging_channel() + self._add_producer_tracks() + + offer = await self.peer_connection.createOffer() + await self.peer_connection.setLocalDescription(offer) + actual_offer = self.peer_connection.localDescription + + streaming_offer = StreamingOffer( + sdp=actual_offer.sdp, + video=list(self.expected_incoming_camera_types), + ) + remote_answer = await self.session_provider(streaming_offer) + self._parse_incoming_streams(remote_sdp=remote_answer.sdp) + await self.peer_connection.setRemoteDescription(remote_answer) + actual_answer = self.peer_connection.remoteDescription + + return actual_answer + + +class WebRTCAnswerStream(WebRTCBaseStream): + def __init__(self, session: aiortc.RTCSessionDescription, *args, **kwargs): + super().__init__(*args, **kwargs) + self.session = session + + def _probe_video_codecs(self) -> List[str]: + codecs = [] + for track in self.outgoing_video_tracks: + if hasattr(track, "codec_preference") and track.codec_preference() is not None: + codecs.append(track.codec_preference()) + + return codecs + + def _override_incoming_video_codecs(self, remote_sdp: str, codecs: List[str]) -> str: + desc = aiortc.sdp.SessionDescription.parse(remote_sdp) + codec_mimes = [f"video/{c}" for c in codecs] + for m in desc.media: + if m.kind != "video": + continue + + preferred_codecs: List[aiortc.RTCRtpCodecParameters] = [c for c in m.rtp.codecs if c.mimeType in codec_mimes] + if len(preferred_codecs) == 0: + raise ValueError(f"None of {preferred_codecs} codecs is supported in remote SDP") + + m.rtp.codecs = preferred_codecs + m.fmt = [c.payloadType for c in preferred_codecs] + + return str(desc) + + async def start(self) -> aiortc.RTCSessionDescription: + assert self.peer_connection.remoteDescription is None, "Connection already established" + + self._add_consumer_transceivers() + + # since we sent already encoded frames in some cases (e.g. livestream video tracks are in H264), we need to force aiortc to actually use it + # we do that by overriding supported codec information on incoming sdp + preferred_codecs = self._probe_video_codecs() + if len(preferred_codecs) > 0: + self.session.sdp = self._override_incoming_video_codecs(self.session.sdp, preferred_codecs) + + self._parse_incoming_streams(remote_sdp=self.session.sdp) + await self.peer_connection.setRemoteDescription(self.session) + + self._add_producer_tracks() + + answer = await self.peer_connection.createAnswer() + await self.peer_connection.setLocalDescription(answer) + actual_answer = self.peer_connection.localDescription + + return actual_answer diff --git a/teleoprtc_repo/teleoprtc/tracks.py b/teleoprtc_repo/teleoprtc/tracks.py new file mode 100644 index 0000000000..2e583666a9 --- /dev/null +++ b/teleoprtc_repo/teleoprtc/tracks.py @@ -0,0 +1,76 @@ +import asyncio +import logging +import time +import fractions +from typing import Any, Optional, Tuple + +import aiortc +from aiortc.mediastreams import VIDEO_CLOCK_RATE, VIDEO_TIME_BASE + + +def video_track_id(camera_type: str, track_id: str) -> str: + return f"{camera_type}:{track_id}" + + +def parse_video_track_id(track_id: str) -> Tuple[str, str]: + parts = track_id.split(":") + if len(parts) != 2: + raise ValueError(f"Invalid video track id: {track_id}") + + camera_type, track_id = parts + return camera_type, track_id + + +class TiciVideoStreamTrack(aiortc.MediaStreamTrack): + """ + Abstract video track which associates video track with camera_type + """ + kind = "video" + + def __init__(self, camera_type: str, dt: float, time_base: fractions.Fraction = VIDEO_TIME_BASE, clock_rate: int = VIDEO_CLOCK_RATE): + assert camera_type in ["driver", "wideRoad", "road"] + super().__init__() + # override track id to include camera type - client needs that for identification + self._id: str = video_track_id(camera_type, self._id) + self._dt: float = dt + self._time_base: fractions.Fraction = time_base + self._clock_rate: int = clock_rate + self._start: Optional[float] = None + self._logger = logging.getLogger("WebRTCStream") + + def log_debug(self, msg: Any, *args): + self._logger.debug(f"{type(self)}() {msg}", *args) + + async def next_pts(self, current_pts) -> float: + pts: float = current_pts + self._dt * self._clock_rate + + data_time = pts * self._time_base + if self._start is None: + self._start = time.time() - data_time + else: + wait_time = self._start + data_time - time.time() + await asyncio.sleep(wait_time) + + return pts + + def codec_preference(self) -> Optional[str]: + return None + + +class TiciTrackWrapper(aiortc.MediaStreamTrack): + """ + Associates video track with camera_type + """ + def __init__(self, camera_type: str, track: aiortc.MediaStreamTrack): + assert track.kind == "video" + assert not isinstance(track, TiciVideoStreamTrack) + super().__init__() + self._id = video_track_id(camera_type, track.id) + self._track = track + + @property + def kind(self) -> str: + return self._track.kind + + async def recv(self): + return await self._track.recv() diff --git a/teleoprtc_repo/tests/test_info.py b/teleoprtc_repo/tests/test_info.py new file mode 100755 index 0000000000..5e939cdfea --- /dev/null +++ b/teleoprtc_repo/tests/test_info.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 + +from teleoprtc.info import parse_info_from_offer + + +def lf2crlf(x): + return x.replace("\n", "\r\n") + + +class TestStream: + def test_double_video_tracks(self): + sdp = """v=0 +o=- 3910210993 3910210993 IN IP4 0.0.0.0 +s=- +t=0 0 +a=group:BUNDLE 0 1 +a=msid-semantic:WMS * +m=video 9 UDP/TLS/RTP/SAVPF 97 98 99 100 101 102 +c=IN IP4 0.0.0.0 +a=recvonly +a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time +a=mid:0 +a=msid:e123f852-010c-4b7b-8761-71b72fbfd013 2b75cb0e-6b34-48d6-8bf9-21b809f2e08e +a=rtcp:9 IN IP4 0.0.0.0 +a=rtcp-mux +a=ssrc-group:FID 1048118556 4149054509 +a=ssrc:1048118556 cname:61992fce-bab5-42a0-ab8c-7112adfb1857 +a=ssrc:4149054509 cname:61992fce-bab5-42a0-ab8c-7112adfb1857 +a=rtpmap:97 VP8/90000 +a=rtcp-fb:97 nack +a=rtcp-fb:97 nack pli +a=rtcp-fb:97 goog-remb +a=rtpmap:98 rtx/90000 +a=fmtp:98 apt=97 +a=rtpmap:99 H264/90000 +a=rtcp-fb:99 nack +a=rtcp-fb:99 nack pli +a=rtcp-fb:99 goog-remb +a=fmtp:99 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f +a=rtpmap:100 rtx/90000 +a=fmtp:100 apt=99 +a=rtpmap:101 H264/90000 +a=rtcp-fb:101 nack +a=rtcp-fb:101 nack pli +a=rtcp-fb:101 goog-remb +a=fmtp:101 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f +a=rtpmap:102 rtx/90000 +a=fmtp:102 apt=101 +a=ice-ufrag:jxQW +a=ice-pwd:KpJ0tfaY2RxnIYpTHqPSSv +a=fingerprint:sha-256 70:3A:2D:37:3C:52:96:0E:10:F6:4D:7A:EB:18:38:1B:FD:CA:A5:90:D7:6C:DA:A9:39:76:C9:2F:FB:FF:56:0C +a=setup:actpass +m=video 9 UDP/TLS/RTP/SAVPF 97 98 99 100 101 102 +c=IN IP4 0.0.0.0 +a=recvonly +a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time +a=mid:1 +a=msid:e123f852-010c-4b7b-8761-71b72fbfd013 311db759-8d51-479c-a5b4-5c8d055c43ec +a=rtcp:9 IN IP4 0.0.0.0 +a=rtcp-mux +a=ssrc-group:FID 4096183284 2713379498 +a=ssrc:4096183284 cname:61992fce-bab5-42a0-ab8c-7112adfb1857 +a=ssrc:2713379498 cname:61992fce-bab5-42a0-ab8c-7112adfb1857 +a=rtpmap:97 VP8/90000 +a=rtcp-fb:97 nack +a=rtcp-fb:97 nack pli +a=rtcp-fb:97 goog-remb +a=rtpmap:98 rtx/90000 +a=fmtp:98 apt=97 +a=rtpmap:99 H264/90000 +a=rtcp-fb:99 nack +a=rtcp-fb:99 nack pli +a=rtcp-fb:99 goog-remb +a=fmtp:99 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f +a=rtpmap:100 rtx/90000 +a=fmtp:100 apt=99 +a=rtpmap:101 H264/90000 +a=rtcp-fb:101 nack +a=rtcp-fb:101 nack pli +a=rtcp-fb:101 goog-remb +a=fmtp:101 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f +a=rtpmap:102 rtx/90000 +a=fmtp:102 apt=101 +a=ice-ufrag:1234 +a=ice-pwd:1234 +a=fingerprint:sha-256 70:3A:2D:37:3C:52:96:0E:10:F6:4D:7A:EB:18:38:1B:FD:CA:A5:90:D7:6C:DA:A9:39:76:C9:2F:FB:FF:56:0C +a=setup:actpass""" + info = parse_info_from_offer(lf2crlf(sdp)) + assert info.n_expected_camera_tracks == 2 + assert not info.expected_audio_track + assert not info.incoming_audio_track + assert not info.incoming_datachannel + + def test_recvonly_audio(self): + sdp = """v=0 +o=- 3910210904 3910210904 IN IP4 0.0.0.0 +s=- +t=0 0 +a=group:BUNDLE 0 +a=msid-semantic:WMS * +m=audio 9 UDP/TLS/RTP/SAVPF 96 0 8 +c=IN IP4 0.0.0.0 +a=recvonly +a=extmap:1 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level +a=mid:0 +a=msid:eb1d3f1a-569a-465f-b419-319477bfded6 e44eecb2-1a04-4547-97d8-481389f50d5b +a=rtcp:9 IN IP4 0.0.0.0 +a=rtcp-mux +a=ssrc:1233332626 cname:ca4dede8-4994-4a6d-9ae3-923b28177ca5 +a=rtpmap:96 opus/48000/2 +a=rtpmap:0 PCMU/8000 +a=rtpmap:8 PCMA/8000 +a=ice-ufrag:1234 +a=ice-pwd:1234 +a=fingerprint:sha-256 40:4B:14:CF:70:B8:67:E1:B1:FF:7E:F9:22:6E:60:7D:73:B5:1E:38:4B:10:20:9C:CD:1C:47:02:52:ED:45:25 +a=setup:actpass""" + info = parse_info_from_offer(lf2crlf(sdp)) + assert info.n_expected_camera_tracks == 0 + assert info.expected_audio_track + assert not info.incoming_audio_track + assert not info.incoming_datachannel + + def test_incoming_datachanel(self): + sdp = """v=0 +o=- 3910211092 3910211092 IN IP4 0.0.0.0 +s=- +t=0 0 +a=group:BUNDLE 0 +a=msid-semantic:WMS * +m=application 9 DTLS/SCTP 5000 +c=IN IP4 0.0.0.0 +a=mid:0 +a=sctpmap:5000 webrtc-datachannel 65535 +a=max-message-size:65536 +a=ice-ufrag:1234 +a=ice-pwd:1234 +a=fingerprint:sha-256 9B:C0:F3:35:8E:05:A1:15:DB:F8:39:0E:B0:E0:0C:EB:82:E4:B9:26:18:A6:43:2D:B9:9A:23:96:0A:59:B6:58 +a=setup:actpass""" + info = parse_info_from_offer(lf2crlf(sdp)) + assert info.n_expected_camera_tracks == 0 + assert not info.expected_audio_track + assert not info.incoming_audio_track + assert info.incoming_datachannel diff --git a/teleoprtc_repo/tests/test_integration.py b/teleoprtc_repo/tests/test_integration.py new file mode 100755 index 0000000000..d804af7b47 --- /dev/null +++ b/teleoprtc_repo/tests/test_integration.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 + +import pytest +import asyncio +import sys + +from aiortc.mediastreams import AudioStreamTrack, VideoStreamTrack +from parameterized import parameterized + +from teleoprtc.builder import WebRTCOfferBuilder, WebRTCAnswerBuilder +from teleoprtc.stream import StreamingOffer +from teleoprtc.info import parse_info_from_offer + + +if sys.version_info >= (3, 11): + timeout = asyncio.timeout +else: + class Timeout: + def __init__(self, delay: float): + self._delay = delay + self._task = None + self._timeout_handle = None + + def _timeout(self): + if self._task: + self._task.cancel() + + async def __aenter__(self): + self._task = asyncio.current_task() + loop = asyncio.events.get_running_loop() + self._timeout_handle = loop.call_later(self._delay, self._timeout) + return self + + async def __aexit__(self, exc_type, exc, tb): + if self._timeout_handle: + self._timeout_handle.cancel() + if exc_type is asyncio.CancelledError and self._task and self._task.cancelled(): + raise asyncio.TimeoutError from exc + return False + + def timeout(delay): + return Timeout(delay) + + +class SimpleAnswerProvider: + def __init__(self): + self.stream = None + + async def __call__(self, offer: StreamingOffer): + assert self.stream is None, "This may only be called once" + + info = parse_info_from_offer(offer.sdp) + + builder = WebRTCAnswerBuilder(offer.sdp) + for cam in offer.video: + builder.add_video_stream(cam, VideoStreamTrack()) + if info.expected_audio_track: + builder.add_audio_stream(AudioStreamTrack()) + if info.incoming_audio_track: + builder.offer_to_receive_audio_stream() + + self.stream = builder.stream() + answer = await self.stream.start() + + return answer + + +@pytest.mark.asyncio +class TestStreamIntegration: + @parameterized.expand([ + # name, recv_cameras, recv_audio, messaging + ("multi_camera", ["driver", "wideRoad", "road"], False, False), + ("camera_and_audio", ["driver"], True, False), + ("camera_and__messaging", ["driver"], False, True), + ("camera_and_audio_and_messaging", ["driver", "wideRoad", "road"], True, True), + ]) + async def test_multi_camera(self, name, cameras, recv_audio, add_messaging): + simple_answerer = SimpleAnswerProvider() + offer_builder = WebRTCOfferBuilder(simple_answerer) + for cam in cameras: + offer_builder.offer_to_receive_video_stream(cam) + if recv_audio: + offer_builder.offer_to_receive_audio_stream() + if add_messaging: + offer_builder.add_messaging() + stream = offer_builder.stream() + + _ = await stream.start() + assert stream.is_started + + try: + async with timeout(2): + await stream.wait_for_connection() + except TimeoutError: + pytest.fail("Timed out waiting for connection") + assert stream.is_connected_and_ready + + assert stream.has_messaging_channel() == add_messaging + if stream.has_messaging_channel(): + channel = stream.get_messaging_channel() + assert channel is not None + assert channel.readyState == "open" + + assert stream.has_incoming_audio_track() == recv_audio + if stream.has_incoming_audio_track(): + track = stream.get_incoming_audio_track(False) + assert track is not None + assert track.readyState == "live" + assert track.kind == "audio" + # test audio recv + try: + async with timeout(1): + await track.recv() + except TimeoutError: + pytest.fail("Timed out waiting for audio frame") + + for cam in cameras: + assert stream.has_incoming_video_track(cam) + if stream.has_incoming_video_track(cam): + track = stream.get_incoming_video_track(cam, False) + assert track is not None + assert track.readyState == "live" + assert track.kind == "video" + # test video recv + try: + async with timeout(1): + await stream.get_incoming_video_track(cam, False).recv() + except TimeoutError: + pytest.fail("Timed out waiting for video frame") + + await stream.stop() + await simple_answerer.stream.stop() + assert not stream.is_started + assert not stream.is_connected_and_ready diff --git a/teleoprtc_repo/tests/test_stream.py b/teleoprtc_repo/tests/test_stream.py new file mode 100755 index 0000000000..7e697e503f --- /dev/null +++ b/teleoprtc_repo/tests/test_stream.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +import pytest + +import aiortc +from aiortc.mediastreams import AudioStreamTrack + +from teleoprtc.builder import WebRTCOfferBuilder, WebRTCAnswerBuilder +from teleoprtc.info import parse_info_from_offer +from teleoprtc.tracks import TiciVideoStreamTrack + + +class OfferCapture: + def __init__(self): + self.offer = None + + async def __call__(self, offer): + self.offer = offer + raise Exception("Offer captured") + + +class DummyH264VideoStreamTrack(TiciVideoStreamTrack): + kind = "video" + + async def recv(self): + raise NotImplementedError() + + def codec_preference(self): + return "H264" + + +@pytest.mark.asyncio +class TestOfferStream: + async def test_offer_stream_sdp_recvonly_audio(self): + capture = OfferCapture() + builder = WebRTCOfferBuilder(capture) + builder.offer_to_receive_audio_stream() + stream = builder.stream() + + try: + _ = await stream.start() + except Exception: + pass + + info = parse_info_from_offer(capture.offer.sdp) + assert info.expected_audio_track + assert not info.incoming_audio_track + + async def test_offer_stream_sdp_sendonly_audio(self): + capture = OfferCapture() + builder = WebRTCOfferBuilder(capture) + builder.add_audio_stream(AudioStreamTrack()) + stream = builder.stream() + + try: + _ = await stream.start() + except Exception: + pass + + info = parse_info_from_offer(capture.offer.sdp) + assert not info.expected_audio_track + assert info.incoming_audio_track + + async def test_offer_stream_sdp_channel(self): + capture = OfferCapture() + builder = WebRTCOfferBuilder(capture) + builder.add_messaging() + stream = builder.stream() + + try: + _ = await stream.start() + except Exception: + pass + + info = parse_info_from_offer(capture.offer.sdp) + assert info.incoming_datachannel + + +@pytest.mark.asyncio +class TestAnswerStream: + async def test_codec_preference(self): + offer_sdp = """v=0 +o=- 3910274679 3910274679 IN IP4 0.0.0.0 +s=- +t=0 0 +a=group:BUNDLE 0 +a=msid-semantic:WMS * +m=video 1337 UDP/TLS/RTP/SAVPF 97 98 99 100 101 102 +c=IN IP4 0.0.0.0 +a=recvonly +a=mid:0 +a=msid:34803878-98f8-4245-b45c-f773e5f926df 881dbc20-356a-499c-b4e8-695303bb901d +a=rtcp:9 IN IP4 0.0.0.0 +a=rtcp-mux +a=ssrc-group:FID 1303546896 3784011659 +a=ssrc:1303546896 cname:a59185ac-c115-48d3-b39b-db7d615a6966 +a=ssrc:3784011659 cname:a59185ac-c115-48d3-b39b-db7d615a6966 +a=rtpmap:97 VP8/90000 +a=rtcp-fb:97 nack +a=rtcp-fb:97 nack pli +a=rtcp-fb:97 goog-remb +a=rtpmap:99 H264/90000 +a=rtcp-fb:99 nack +a=rtcp-fb:99 nack pli +a=rtcp-fb:99 goog-remb +a=fmtp:99 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f +a=ice-ufrag:1234 +a=ice-pwd:1234 +a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A +a=setup:actpass""" + + builder = WebRTCAnswerBuilder(offer_sdp) + builder.add_video_stream("road", DummyH264VideoStreamTrack("road", 0.05)) + stream = builder.stream() + answer = await stream.start() + + sdp_desc = aiortc.sdp.SessionDescription.parse(answer.sdp) + video_desc = [m for m in sdp_desc.media if m.kind == "video"][0] + codecs = video_desc.rtp.codecs + assert codecs[0].mimeType == "video/H264" + + async def test_fail_if_preferred_codec_not_in_offer(self): + offer_sdp = """v=0 +o=- 3910274679 3910274679 IN IP4 0.0.0.0 +s=- +t=0 0 +a=group:BUNDLE 0 +a=msid-semantic:WMS * +m=video 1337 UDP/TLS/RTP/SAVPF 97 98 99 100 101 102 +c=IN IP4 0.0.0.0 +a=recvonly +a=mid:0 +a=msid:34803878-98f8-4245-b45c-f773e5f926df 881dbc20-356a-499c-b4e8-695303bb901d +a=rtcp:9 IN IP4 0.0.0.0 +a=rtcp-mux +a=ssrc-group:FID 1303546896 3784011659 +a=ssrc:1303546896 cname:a59185ac-c115-48d3-b39b-db7d615a6966 +a=ssrc:3784011659 cname:a59185ac-c115-48d3-b39b-db7d615a6966 +a=rtpmap:97 VP8/90000 +a=rtcp-fb:97 nack +a=rtcp-fb:97 nack pli +a=rtcp-fb:97 goog-remb +a=ice-ufrag:1234 +a=ice-pwd:1234 +a=fingerprint:sha-256 15:F3:F0:23:67:44:EE:2C:AA:8C:D9:50:95:26:42:7C:67:EA:1F:D2:92:C5:97:01:7B:2E:57:C9:A3:13:00:4A +a=setup:actpass""" + + builder = WebRTCAnswerBuilder(offer_sdp) + builder.add_video_stream("road", DummyH264VideoStreamTrack("road", 0.05)) + stream = builder.stream() + + with pytest.raises(ValueError): + _ = await stream.start() diff --git a/teleoprtc_repo/tests/test_track.py b/teleoprtc_repo/tests/test_track.py new file mode 100755 index 0000000000..52b4483558 --- /dev/null +++ b/teleoprtc_repo/tests/test_track.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import pytest + +import aiortc + +from teleoprtc.tracks import video_track_id, parse_video_track_id, TiciVideoStreamTrack, TiciTrackWrapper + + +class TestTracks: + def test_track_id(self): + expected_camera_type, expected_track_id = "driver", "test" + track_id = video_track_id(expected_camera_type, expected_track_id) + camera_type, track_id = parse_video_track_id(track_id) + assert expected_camera_type == camera_type + assert expected_track_id == track_id + + def test_track_id_invalid(self): + with pytest.raises(ValueError): + parse_video_track_id("test") + + def test_tici_track_id(self): + class VideoStream(TiciVideoStreamTrack): + async def recv(self): + raise NotImplementedError() + + track = VideoStream("driver", 0.1) + camera_type, _ = parse_video_track_id(track.id) + assert "driver" == camera_type + + def test_tici_wrapper_id(self): + track = TiciTrackWrapper("driver", aiortc.mediastreams.VideoStreamTrack()) + camera_type, _ = parse_video_track_id(track.id) + assert "driver" == camera_type diff --git a/third_party/.gitignore b/third_party/.gitignore new file mode 100644 index 0000000000..0d20b6487c --- /dev/null +++ b/third_party/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/third_party/SConscript b/third_party/SConscript new file mode 100644 index 0000000000..3a7497d162 --- /dev/null +++ b/third_party/SConscript @@ -0,0 +1,3 @@ +Import('env') + +env.Library('json11', ['json11/json11.cpp'], CCFLAGS=env['CCFLAGS'] + ['-Wno-unqualified-std-cast-call']) diff --git a/third_party/acados/.gitignore b/third_party/acados/.gitignore new file mode 100644 index 0000000000..68858c62e4 --- /dev/null +++ b/third_party/acados/.gitignore @@ -0,0 +1,5 @@ +acados_repo/ +lib +!x86_64/ +!larch64/ +!aarch64/ diff --git a/third_party/acados/Darwin/lib/libacados.dylib b/third_party/acados/Darwin/lib/libacados.dylib new file mode 100755 index 0000000000..3270553b02 Binary files /dev/null and b/third_party/acados/Darwin/lib/libacados.dylib differ diff --git a/third_party/acados/Darwin/lib/libblasfeo.dylib b/third_party/acados/Darwin/lib/libblasfeo.dylib new file mode 100755 index 0000000000..a7b55b860a Binary files /dev/null and b/third_party/acados/Darwin/lib/libblasfeo.dylib differ diff --git a/third_party/acados/Darwin/lib/libhpipm.dylib b/third_party/acados/Darwin/lib/libhpipm.dylib new file mode 100755 index 0000000000..d638913f98 Binary files /dev/null and b/third_party/acados/Darwin/lib/libhpipm.dylib differ diff --git a/third_party/acados/Darwin/lib/libqpOASES_e.3.1.dylib b/third_party/acados/Darwin/lib/libqpOASES_e.3.1.dylib new file mode 100755 index 0000000000..ab9888ff82 Binary files /dev/null and b/third_party/acados/Darwin/lib/libqpOASES_e.3.1.dylib differ diff --git a/third_party/acados/Darwin/lib/libqpOASES_e.dylib b/third_party/acados/Darwin/lib/libqpOASES_e.dylib new file mode 120000 index 0000000000..e3d94c4bc2 --- /dev/null +++ b/third_party/acados/Darwin/lib/libqpOASES_e.dylib @@ -0,0 +1 @@ +libqpOASES_e.3.1.dylib \ No newline at end of file diff --git a/third_party/acados/Darwin/t_renderer b/third_party/acados/Darwin/t_renderer new file mode 100755 index 0000000000..fa8e9933a8 Binary files /dev/null and b/third_party/acados/Darwin/t_renderer differ diff --git a/third_party/acados/aarch64 b/third_party/acados/aarch64 new file mode 120000 index 0000000000..062c65e8d9 --- /dev/null +++ b/third_party/acados/aarch64 @@ -0,0 +1 @@ +larch64/ \ No newline at end of file diff --git a/third_party/acados/acados_template/.gitignore b/third_party/acados/acados_template/.gitignore new file mode 100644 index 0000000000..63b741bb9d --- /dev/null +++ b/third_party/acados/acados_template/.gitignore @@ -0,0 +1,6 @@ +__pycache__/ + +# Cython intermediates +*_pyx.c +*_pyx.o +*_pyx.so diff --git a/third_party/acados/acados_template/__init__.py b/third_party/acados/acados_template/__init__.py new file mode 100644 index 0000000000..bfbe907990 --- /dev/null +++ b/third_party/acados/acados_template/__init__.py @@ -0,0 +1,40 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +from .acados_model import AcadosModel +from .acados_ocp import AcadosOcp, AcadosOcpConstraints, AcadosOcpCost, AcadosOcpDims, AcadosOcpOptions +from .acados_sim import AcadosSim, AcadosSimDims, AcadosSimOpts +from .acados_ocp_solver import AcadosOcpSolver, get_simulink_default_opts, ocp_get_default_cmake_builder +from .acados_sim_solver import AcadosSimSolver, sim_get_default_cmake_builder +from .utils import print_casadi_expression, get_acados_path, get_python_interface_path, \ + get_tera_exec_path, get_tera, check_casadi_version, acados_dae_model_json_dump, \ + casadi_length, make_object_json_dumpable, J_to_idx, get_default_simulink_opts + +from .zoro_description import ZoroDescription, process_zoro_description diff --git a/third_party/acados/acados_template/acados_layout.json b/third_party/acados/acados_template/acados_layout.json new file mode 100644 index 0000000000..a1cc5bbdf3 --- /dev/null +++ b/third_party/acados/acados_template/acados_layout.json @@ -0,0 +1,834 @@ +{ + "code_export_directory": [ + "str" + ], + "acados_include_path": [ + "str" + ], + "cython_include_dirs": [ + "list" + ], + "json_file": [ + "str" + ], + "shared_lib_ext": [ + "str" + ], + "model": { + "name" : [ + "str" + ], + "dyn_ext_fun_type" : [ + "str" + ], + "dyn_generic_source" : [ + "str" + ], + "dyn_impl_dae_fun" : [ + "str" + ], + "dyn_impl_dae_fun_jac" : [ + "str" + ], + "dyn_impl_dae_jac" : [ + "str" + ], + "dyn_disc_fun_jac_hess" : [ + "str" + ], + "dyn_disc_fun_jac" : [ + "str" + ], + "dyn_disc_fun" : [ + "str" + ], + "gnsf" : { + "nontrivial_f_LO": [ + "int" + ], + "purely_linear": [ + "int" + ] + } + }, + "parameter_values": [ + "ndarray", + [ + "np" + ] + ], + "acados_lib_path": [ + "str" + ], + "problem_class": [ + "str" + ], + "constraints": { + "constr_type": [ + "str" + ], + "constr_type_e": [ + "str" + ], + "lbx": [ + "ndarray", + [ + "nbx" + ] + ], + "lbu": [ + "ndarray", + [ + "nbu" + ] + ], + "ubx": [ + "ndarray", + [ + "nbx" + ] + ], + "ubu": [ + "ndarray", + [ + "nbu" + ] + ], + "idxbx": [ + "ndarray", + [ + "nbx" + ] + ], + "idxbu": [ + "ndarray", + [ + "nbu" + ] + ], + "lbx_e": [ + "ndarray", + [ + "nbx_e" + ] + ], + "ubx_e": [ + "ndarray", + [ + "nbx_e" + ] + ], + "idxbx_e": [ + "ndarray", + [ + "nbx_e" + ] + ], + "lbx_0": [ + "ndarray", + [ + "nbx_0" + ] + ], + "ubx_0": [ + "ndarray", + [ + "nbx_0" + ] + ], + "idxbx_0": [ + "ndarray", + [ + "nbx_0" + ] + ], + "idxbxe_0": [ + "ndarray", + [ + "nbxe_0" + ] + ], + "lg": [ + "ndarray", + [ + "ng" + ] + ], + "ug": [ + "ndarray", + [ + "ng" + ] + ], + "D": [ + "ndarray", + [ + "ng", + "nu" + ] + ], + "C": [ + "ndarray", + [ + "ng", + "nx" + ] + ], + "C_e": [ + "ndarray", + [ + "ng_e", + "nx" + ] + ], + "lg_e": [ + "ndarray", + [ + "ng_e" + ] + ], + "ug_e": [ + "ndarray", + [ + "ng_e" + ] + ], + "lh": [ + "ndarray", + [ + "nh" + ] + ], + "uh": [ + "ndarray", + [ + "nh" + ] + ], + "lh_e": [ + "ndarray", + [ + "nh_e" + ] + ], + "uh_e": [ + "ndarray", + [ + "nh_e" + ] + ], + "lphi": [ + "ndarray", + [ + "nphi" + ] + ], + "uphi": [ + "ndarray", + [ + "nphi" + ] + ], + "lphi_e": [ + "ndarray", + [ + "nphi_e" + ] + ], + "uphi_e": [ + "ndarray", + [ + "nphi_e" + ] + ], + "lsbx": [ + "ndarray", + [ + "nsbx" + ] + ], + "usbx": [ + "ndarray", + [ + "nsbx" + ] + ], + "lsbu": [ + "ndarray", + [ + "nsbu" + ] + ], + "usbu": [ + "ndarray", + [ + "nsbu" + ] + ], + "idxsbx": [ + "ndarray", + [ + "nsbx" + ] + ], + "idxsbu": [ + "ndarray", + [ + "nsbu" + ] + ], + "lsbx_e": [ + "ndarray", + [ + "nsbx_e" + ] + ], + "usbx_e": [ + "ndarray", + [ + "nsbx_e" + ] + ], + "idxsbx_e": [ + "ndarray", + [ + "nsbx_e" + ] + ], + "lsg": [ + "ndarray", + [ + "nsg" + ] + ], + "usg": [ + "ndarray", + [ + "nsg" + ] + ], + "idxsg": [ + "ndarray", + [ + "nsg" + ] + ], + "lsg_e": [ + "ndarray", + [ + "nsg_e" + ] + ], + "usg_e": [ + "ndarray", + [ + "nsg_e" + ] + ], + "idxsg_e": [ + "ndarray", + [ + "nsg_e" + ] + ], + "lsh": [ + "ndarray", + [ + "nsh" + ] + ], + "ush": [ + "ndarray", + [ + "nsh" + ] + ], + "idxsh": [ + "ndarray", + [ + "nsh" + ] + ], + "lsh_e": [ + "ndarray", + [ + "nsh_e" + ] + ], + "ush_e": [ + "ndarray", + [ + "nsh_e" + ] + ], + "idxsh_e": [ + "ndarray", + [ + "nsh_e" + ] + ], + "lsphi": [ + "ndarray", + [ + "nsphi" + ] + ], + "usphi": [ + "ndarray", + [ + "nsphi" + ] + ], + "idxsphi": [ + "ndarray", + [ + "nsphi" + ] + ], + "lsphi_e": [ + "ndarray", + [ + "nsphi_e" + ] + ], + "usphi_e": [ + "ndarray", + [ + "nsphi_e" + ] + ], + "idxsphi_e": [ + "ndarray", + [ + "nsphi_e" + ] + ] + }, + "cost": { + "cost_type_0": [ + "str" + ], + "cost_type": [ + "str" + ], + "cost_type_e": [ + "str" + ], + "cost_ext_fun_type_0": [ + "str" + ], + "cost_ext_fun_type": [ + "str" + ], + "cost_ext_fun_type_e": [ + "str" + ], + "Vu_0": [ + "ndarray", + [ + "ny_0", + "nu" + ] + ], + "Vu": [ + "ndarray", + [ + "ny", + "nu" + ] + ], + "Vx_0": [ + "ndarray", + [ + "ny_0", + "nx" + ] + ], + "Vx": [ + "ndarray", + [ + "ny", + "nx" + ] + ], + "Vx_e": [ + "ndarray", + [ + "ny_e", + "nx" + ] + ], + "Vz_0": [ + "ndarray", + [ + "ny_0", + "nz" + ] + ], + "Vz": [ + "ndarray", + [ + "ny", + "nz" + ] + ], + "W_0": [ + "ndarray", + [ + "ny_0", + "ny_0" + ] + ], + "W": [ + "ndarray", + [ + "ny", + "ny" + ] + ], + "Zl": [ + "ndarray", + [ + "ns" + ] + ], + "Zu": [ + "ndarray", + [ + "ns" + ] + ], + "zl": [ + "ndarray", + [ + "ns" + ] + ], + "zu": [ + "ndarray", + [ + "ns" + ] + ], + "W_e": [ + "ndarray", + [ + "ny_e", + "ny_e" + ] + ], + "yref_0": [ + "ndarray", + [ + "ny_0" + ] + ], + "yref": [ + "ndarray", + [ + "ny" + ] + ], + "yref_e": [ + "ndarray", + [ + "ny_e" + ] + ], + "Zl_e": [ + "ndarray", + [ + "ns_e" + ] + ], + "Zu_e": [ + "ndarray", + [ + "ns_e" + ] + ], + "zl_e": [ + "ndarray", + [ + "ns_e" + ] + ], + "zu_e": [ + "ndarray", + [ + "ns_e" + ] + ] + }, + "dims": { + "N": [ + "int" + ], + "nbu": [ + "int" + ], + "nbx": [ + "int" + ], + "nsbu": [ + "int" + ], + "nsbx": [ + "int" + ], + "nsbx_e": [ + "int" + ], + "nbx_0": [ + "int" + ], + "nbx_e": [ + "int" + ], + "nbxe_0": [ + "int" + ], + "nsg": [ + "int" + ], + "nsg_e": [ + "int" + ], + "nsh": [ + "int" + ], + "nsh_e": [ + "int" + ], + "nsphi": [ + "int" + ], + "nsphi_e": [ + "int" + ], + "ns": [ + "int" + ], + "ns_e": [ + "int" + ], + "ng": [ + "int" + ], + "ng_e": [ + "int" + ], + "np": [ + "int" + ], + "nr": [ + "int" + ], + "nr_e": [ + "int" + ], + "nh": [ + "int" + ], + "nh_e": [ + "int" + ], + "nphi": [ + "int" + ], + "nphi_e": [ + "int" + ], + "nu": [ + "int" + ], + "nx": [ + "int" + ], + "ny": [ + "int" + ], + "ny_0": [ + "int" + ], + "ny_e": [ + "int" + ], + "nz": [ + "int" + ], + "gnsf_nx1": [ + "int" + ], + "gnsf_nz1": [ + "int" + ], + "gnsf_nuhat": [ + "int" + ], + "gnsf_ny": [ + "int" + ], + "gnsf_nout": [ + "int" + ] + }, + "solver_options": { + "time_steps": [ + "ndarray", + [ + "N" + ] + ], + "hessian_approx": [ + "str" + ], + "hpipm_mode": [ + "str" + ], + "regularize_method": [ + "str" + ], + "integrator_type": [ + "str" + ], + "nlp_solver_type": [ + "str" + ], + "collocation_type": [ + "str" + ], + "globalization": [ + "str" + ], + "nlp_solver_step_length": [ + "float" + ], + "levenberg_marquardt": [ + "float" + ], + "qp_solver": [ + "str" + ], + "tf": [ + "float" + ], + "Tsim": [ + "float" + ], + "alpha_min": [ + "float" + ], + "alpha_reduction": [ + "float" + ], + "line_search_use_sufficient_descent": [ + "int" + ], + "globalization_use_SOC": [ + "int" + ], + "full_step_dual": [ + "int" + ], + "eps_sufficient_descent": [ + "float" + ], + "sim_method_num_stages": [ + "ndarray", + [ + "N" + ] + ], + "sim_method_num_steps": [ + "ndarray", + [ + "N" + ] + ], + "sim_method_newton_iter": [ + "int" + ], + "sim_method_newton_tol": [ + "float" + ], + "sim_method_jac_reuse": [ + "ndarray", + [ + "N" + ] + ], + "qp_solver_cond_N": [ + "int" + ], + "qp_solver_warm_start": [ + "int" + ], + "qp_solver_tol_stat": [ + "float" + ], + "qp_solver_tol_eq": [ + "float" + ], + "qp_solver_tol_ineq": [ + "float" + ], + "qp_solver_tol_comp": [ + "float" + ], + "qp_solver_iter_max": [ + "int" + ], + "qp_solver_cond_ric_alg": [ + "int" + ], + "qp_solver_ric_alg": [ + "int" + ], + "nlp_solver_tol_stat": [ + "float" + ], + "nlp_solver_tol_eq": [ + "float" + ], + "nlp_solver_tol_ineq": [ + "float" + ], + "nlp_solver_tol_comp": [ + "float" + ], + "nlp_solver_max_iter": [ + "int" + ], + "nlp_solver_ext_qp_res": [ + "int" + ], + "print_level": [ + "int" + ], + "initialize_t_slacks": [ + "int" + ], + "exact_hess_cost": [ + "int" + ], + "exact_hess_constr": [ + "int" + ], + "exact_hess_dyn": [ + "int" + ], + "ext_cost_num_hess": [ + "int" + ], + "ext_fun_compile_flags": [ + "str" + ], + "model_external_shared_lib_dir": [ + "str" + ], + "model_external_shared_lib_name": [ + "str" + ] + } +} diff --git a/third_party/acados/acados_template/acados_model.py b/third_party/acados/acados_template/acados_model.py new file mode 100644 index 0000000000..b7c6945442 --- /dev/null +++ b/third_party/acados/acados_template/acados_model.py @@ -0,0 +1,154 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + + +class AcadosModel(): + """ + Class containing all the information to code generate the external CasADi functions + that are needed when creating an acados ocp solver or acados integrator. + Thus, this class contains: + + a) the :py:attr:`name` of the model, + b) all CasADi variables/expressions needed in the CasADi function generation process. + """ + def __init__(self): + ## common for OCP and Integrator + self.name = None + """ + The model name is used for code generation. Type: string. Default: :code:`None` + """ + self.x = None #: CasADi variable describing the state of the system; Default: :code:`None` + self.xdot = None #: CasADi variable describing the derivative of the state wrt time; Default: :code:`None` + self.u = None #: CasADi variable describing the input of the system; Default: :code:`None` + self.z = [] #: CasADi variable describing the algebraic variables of the DAE; Default: :code:`empty` + self.p = [] #: CasADi variable describing parameters of the DAE; Default: :code:`empty` + # dynamics + self.f_impl_expr = None + """ + CasADi expression for the implicit dynamics :math:`f_\\text{impl}(\dot{x}, x, u, z, p) = 0`. + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.integrator_type` == 'IRK'. + Default: :code:`None` + """ + self.f_expl_expr = None + """ + CasADi expression for the explicit dynamics :math:`\dot{x} = f_\\text{expl}(x, u, p)`. + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.integrator_type` == 'ERK'. + Default: :code:`None` + """ + self.disc_dyn_expr = None + """ + CasADi expression for the discrete dynamics :math:`x_{+} = f_\\text{disc}(x, u, p)`. + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.integrator_type` == 'DISCRETE'. + Default: :code:`None` + """ + + self.dyn_ext_fun_type = 'casadi' #: type of external functions for dynamics module; 'casadi' or 'generic'; Default: 'casadi' + self.dyn_generic_source = None #: name of source file for discrete dyanamics; Default: :code:`None` + self.dyn_disc_fun_jac_hess = None #: name of function discrete dyanamics + jacobian and hessian; Default: :code:`None` + self.dyn_disc_fun_jac = None #: name of function discrete dyanamics + jacobian; Default: :code:`None` + self.dyn_disc_fun = None #: name of function discrete dyanamics; Default: :code:`None` + + # for GNSF models + self.gnsf = {'nontrivial_f_LO': 1, 'purely_linear': 0} + """ + dictionary containing information on GNSF structure needed when rendering templates. + Contains integers `nontrivial_f_LO`, `purely_linear`. + """ + + ## for OCP + # constraints + # BGH(default): lh <= h(x, u) <= uh + self.con_h_expr = None #: CasADi expression for the constraint :math:`h`; Default: :code:`None` + # BGP(convex over nonlinear): lphi <= phi(r(x, u)) <= uphi + self.con_phi_expr = None #: CasADi expression for the constraint phi; Default: :code:`None` + self.con_r_expr = None #: CasADi expression for the constraint phi(r); Default: :code:`None` + self.con_r_in_phi = None + # terminal + self.con_h_expr_e = None #: CasADi expression for the terminal constraint :math:`h^e`; Default: :code:`None` + self.con_r_expr_e = None #: CasADi expression for the terminal constraint; Default: :code:`None` + self.con_phi_expr_e = None #: CasADi expression for the terminal constraint; Default: :code:`None` + self.con_r_in_phi_e = None + # cost + self.cost_y_expr = None #: CasADi expression for nonlinear least squares; Default: :code:`None` + self.cost_y_expr_e = None #: CasADi expression for nonlinear least squares, terminal; Default: :code:`None` + self.cost_y_expr_0 = None #: CasADi expression for nonlinear least squares, initial; Default: :code:`None` + self.cost_expr_ext_cost = None #: CasADi expression for external cost; Default: :code:`None` + self.cost_expr_ext_cost_e = None #: CasADi expression for external cost, terminal; Default: :code:`None` + self.cost_expr_ext_cost_0 = None #: CasADi expression for external cost, initial; Default: :code:`None` + self.cost_expr_ext_cost_custom_hess = None #: CasADi expression for custom hessian (only for external cost); Default: :code:`None` + self.cost_expr_ext_cost_custom_hess_e = None #: CasADi expression for custom hessian (only for external cost), terminal; Default: :code:`None` + self.cost_expr_ext_cost_custom_hess_0 = None #: CasADi expression for custom hessian (only for external cost), initial; Default: :code:`None` + + ## CONVEX_OVER_NONLINEAR convex-over-nonlinear cost: psi(y(x, u, p) - y_ref; p) + self.cost_psi_expr_0 = None + """ + CasADi expression for the outer loss function :math:`\psi(r, p)`, initial; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type_0` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_psi_expr = None + """ + CasADi expression for the outer loss function :math:`\psi(r, p)`; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_psi_expr_e = None + """ + CasADi expression for the outer loss function :math:`\psi(r, p)`, terminal; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type_e` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_r_in_psi_expr_0 = None + """ + CasADi expression for the argument :math:`r`; to the outer loss function :math:`\psi(r, p)`, initial; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type_0` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_r_in_psi_expr = None + """ + CasADi expression for the argument :math:`r`; to the outer loss function :math:`\psi(r, p)`; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_r_in_psi_expr_e = None + """ + CasADi expression for the argument :math:`r`; to the outer loss function :math:`\psi(r, p)`, terminal; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type_e` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_conl_custom_outer_hess_0 = None + """ + CasADi expression for the custom hessian of the outer loss function (only for convex-over-nonlinear cost), initial; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type_0` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_conl_custom_outer_hess = None + """ + CasADi expression for the custom hessian of the outer loss function (only for convex-over-nonlinear cost); Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type` == 'CONVEX_OVER_NONLINEAR'. + """ + self.cost_conl_custom_outer_hess_e = None + """ + CasADi expression for the custom hessian of the outer loss function (only for convex-over-nonlinear cost), terminal; Default: :code:`None` + Used if :py:attr:`acados_template.acados_ocp.AcadosOcpOptions.cost_type_e` == 'CONVEX_OVER_NONLINEAR'. + """ diff --git a/third_party/acados/acados_template/acados_ocp.py b/third_party/acados/acados_template/acados_ocp.py new file mode 100644 index 0000000000..ec02822ceb --- /dev/null +++ b/third_party/acados/acados_template/acados_ocp.py @@ -0,0 +1,3167 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import numpy as np +import os +from .acados_model import AcadosModel +from .utils import get_acados_path, J_to_idx, J_to_idx_slack, get_lib_ext + +class AcadosOcpDims: + """ + Class containing the dimensions of the optimal control problem. + """ + def __init__(self): + self.__nx = None + self.__nu = None + self.__nz = 0 + self.__np = 0 + self.__ny = 0 + self.__ny_e = 0 + self.__ny_0 = 0 + self.__nr = 0 + self.__nr_e = 0 + self.__nh = 0 + self.__nh_e = 0 + self.__nphi = 0 + self.__nphi_e = 0 + self.__nbx = 0 + self.__nbx_0 = 0 + self.__nbx_e = 0 + self.__nbu = 0 + self.__nsbx = 0 + self.__nsbx_e = 0 + self.__nsbu = 0 + self.__nsh = 0 + self.__nsh_e = 0 + self.__nsphi = 0 + self.__nsphi_e = 0 + self.__ns = 0 + self.__ns_e = 0 + self.__ng = 0 + self.__ng_e = 0 + self.__nsg = 0 + self.__nsg_e = 0 + self.__nbxe_0 = None + self.__N = None + + + @property + def nx(self): + """:math:`n_x` - number of states. + Type: int; default: None""" + return self.__nx + + @property + def nz(self): + """:math:`n_z` - number of algebraic variables. + Type: int; default: 0""" + return self.__nz + + @property + def nu(self): + """:math:`n_u` - number of inputs. + Type: int; default: None""" + return self.__nu + + @property + def np(self): + """:math:`n_p` - number of parameters. + Type: int; default: 0""" + return self.__np + + @property + def ny(self): + """:math:`n_y` - number of residuals in Lagrange term. + Type: int; default: 0""" + return self.__ny + + @property + def ny_0(self): + """:math:`n_{y}^0` - number of residuals in Mayer term. + Type: int; default: 0""" + return self.__ny_0 + + @property + def ny_e(self): + """:math:`n_{y}^e` - number of residuals in Mayer term. + Type: int; default: 0""" + return self.__ny_e + + @property + def nr(self): + """:math:`n_{\pi}` - dimension of the image of the inner nonlinear function in positive definite constraints. + Type: int; default: 0""" + return self.__nr + + @property + def nr_e(self): + """:math:`n_{\pi}^e` - dimension of the image of the inner nonlinear function in positive definite constraints. + Type: int; default: 0""" + return self.__nr_e + + @property + def nh(self): + """:math:`n_h` - number of nonlinear constraints. + Type: int; default: 0""" + return self.__nh + + @property + def nh_e(self): + """:math:`n_{h}^e` - number of nonlinear constraints at terminal shooting node N. + Type: int; default: 0""" + return self.__nh_e + + @property + def nphi(self): + """:math:`n_{\phi}` - number of convex-over-nonlinear constraints. + Type: int; default: 0""" + return self.__nphi + + @property + def nphi_e(self): + """:math:`n_{\phi}^e` - number of convex-over-nonlinear constraints at terminal shooting node N. + Type: int; default: 0""" + return self.__nphi_e + + @property + def nbx(self): + """:math:`n_{b_x}` - number of state bounds. + Type: int; default: 0""" + return self.__nbx + + @property + def nbxe_0(self): + """:math:`n_{be_{x0}}` - number of state bounds at initial shooting node that are equalities. + Type: int; default: None""" + return self.__nbxe_0 + + @property + def nbx_0(self): + """:math:`n_{b_{x0}}` - number of state bounds for initial state. + Type: int; default: 0""" + return self.__nbx_0 + + @property + def nbx_e(self): + """:math:`n_{b_x}` - number of state bounds at terminal shooting node N. + Type: int; default: 0""" + return self.__nbx_e + + @property + def nbu(self): + """:math:`n_{b_u}` - number of input bounds. + Type: int; default: 0""" + return self.__nbu + + @property + def nsbx(self): + """:math:`n_{{sb}_x}` - number of soft state bounds. + Type: int; default: 0""" + return self.__nsbx + + @property + def nsbx_e(self): + """:math:`n_{{sb}^e_{x}}` - number of soft state bounds at terminal shooting node N. + Type: int; default: 0""" + return self.__nsbx_e + + @property + def nsbu(self): + """:math:`n_{{sb}_u}` - number of soft input bounds. + Type: int; default: 0""" + return self.__nsbu + + @property + def nsg(self): + """:math:`n_{{sg}}` - number of soft general linear constraints. + Type: int; default: 0""" + return self.__nsg + + @property + def nsg_e(self): + """:math:`n_{{sg}^e}` - number of soft general linear constraints at terminal shooting node N. + Type: int; default: 0""" + return self.__nsg_e + + @property + def nsh(self): + """:math:`n_{{sh}}` - number of soft nonlinear constraints. + Type: int; default: 0""" + return self.__nsh + + @property + def nsh_e(self): + """:math:`n_{{sh}}^e` - number of soft nonlinear constraints at terminal shooting node N. + Type: int; default: 0""" + return self.__nsh_e + + @property + def nsphi(self): + """:math:`n_{{s\phi}}` - number of soft convex-over-nonlinear constraints. + Type: int; default: 0""" + return self.__nsphi + + @property + def nsphi_e(self): + """:math:`n_{{s\phi}^e}` - number of soft convex-over-nonlinear constraints at terminal shooting node N. + Type: int; default: 0""" + return self.__nsphi_e + + @property + def ns(self): + """:math:`n_{s}` - total number of slacks. + Type: int; default: 0""" + return self.__ns + + @property + def ns_e(self): + """:math:`n_{s}^e` - total number of slacks at terminal shooting node N. + Type: int; default: 0""" + return self.__ns_e + + @property + def ng(self): + """:math:`n_{g}` - number of general polytopic constraints. + Type: int; default: 0""" + return self.__ng + + @property + def ng_e(self): + """:math:`n_{g}^e` - number of general polytopic constraints at terminal shooting node N. + Type: int; default: 0""" + return self.__ng_e + + @property + def N(self): + """:math:`N` - prediction horizon. + Type: int; default: None""" + return self.__N + + @nx.setter + def nx(self, nx): + if isinstance(nx, int) and nx > 0: + self.__nx = nx + else: + raise Exception('Invalid nx value, expected positive integer.') + + @nz.setter + def nz(self, nz): + if isinstance(nz, int) and nz > -1: + self.__nz = nz + else: + raise Exception('Invalid nz value, expected nonnegative integer.') + + @nu.setter + def nu(self, nu): + if isinstance(nu, int) and nu > -1: + self.__nu = nu + else: + raise Exception('Invalid nu value, expected nonnegative integer.') + + @np.setter + def np(self, np): + if isinstance(np, int) and np > -1: + self.__np = np + else: + raise Exception('Invalid np value, expected nonnegative integer.') + + @ny_0.setter + def ny_0(self, ny_0): + if isinstance(ny_0, int) and ny_0 > -1: + self.__ny_0 = ny_0 + else: + raise Exception('Invalid ny_0 value, expected nonnegative integer.') + + @ny.setter + def ny(self, ny): + if isinstance(ny, int) and ny > -1: + self.__ny = ny + else: + raise Exception('Invalid ny value, expected nonnegative integer.') + + @ny_e.setter + def ny_e(self, ny_e): + if isinstance(ny_e, int) and ny_e > -1: + self.__ny_e = ny_e + else: + raise Exception('Invalid ny_e value, expected nonnegative integer.') + + @nr.setter + def nr(self, nr): + if isinstance(nr, int) and nr > -1: + self.__nr = nr + else: + raise Exception('Invalid nr value, expected nonnegative integer.') + + @nr_e.setter + def nr_e(self, nr_e): + if isinstance(nr_e, int) and nr_e > -1: + self.__nr_e = nr_e + else: + raise Exception('Invalid nr_e value, expected nonnegative integer.') + + @nh.setter + def nh(self, nh): + if isinstance(nh, int) and nh > -1: + self.__nh = nh + else: + raise Exception('Invalid nh value, expected nonnegative integer.') + + @nh_e.setter + def nh_e(self, nh_e): + if isinstance(nh_e, int) and nh_e > -1: + self.__nh_e = nh_e + else: + raise Exception('Invalid nh_e value, expected nonnegative integer.') + + @nphi.setter + def nphi(self, nphi): + if isinstance(nphi, int) and nphi > -1: + self.__nphi = nphi + else: + raise Exception('Invalid nphi value, expected nonnegative integer.') + + @nphi_e.setter + def nphi_e(self, nphi_e): + if isinstance(nphi_e, int) and nphi_e > -1: + self.__nphi_e = nphi_e + else: + raise Exception('Invalid nphi_e value, expected nonnegative integer.') + + @nbx.setter + def nbx(self, nbx): + if isinstance(nbx, int) and nbx > -1: + self.__nbx = nbx + else: + raise Exception('Invalid nbx value, expected nonnegative integer.') + + @nbxe_0.setter + def nbxe_0(self, nbxe_0): + if isinstance(nbxe_0, int) and nbxe_0 > -1: + self.__nbxe_0 = nbxe_0 + else: + raise Exception('Invalid nbxe_0 value, expected nonnegative integer.') + + @nbx_0.setter + def nbx_0(self, nbx_0): + if isinstance(nbx_0, int) and nbx_0 > -1: + self.__nbx_0 = nbx_0 + else: + raise Exception('Invalid nbx_0 value, expected nonnegative integer.') + + @nbx_e.setter + def nbx_e(self, nbx_e): + if isinstance(nbx_e, int) and nbx_e > -1: + self.__nbx_e = nbx_e + else: + raise Exception('Invalid nbx_e value, expected nonnegative integer.') + + @nbu.setter + def nbu(self, nbu): + if isinstance(nbu, int) and nbu > -1: + self.__nbu = nbu + else: + raise Exception('Invalid nbu value, expected nonnegative integer.') + + @nsbx.setter + def nsbx(self, nsbx): + if isinstance(nsbx, int) and nsbx > -1: + self.__nsbx = nsbx + else: + raise Exception('Invalid nsbx value, expected nonnegative integer.') + + @nsbx_e.setter + def nsbx_e(self, nsbx_e): + if isinstance(nsbx_e, int) and nsbx_e > -1: + self.__nsbx_e = nsbx_e + else: + raise Exception('Invalid nsbx_e value, expected nonnegative integer.') + + @nsbu.setter + def nsbu(self, nsbu): + if isinstance(nsbu, int) and nsbu > -1: + self.__nsbu = nsbu + else: + raise Exception('Invalid nsbu value, expected nonnegative integer.') + + @nsg.setter + def nsg(self, nsg): + if isinstance(nsg, int) and nsg > -1: + self.__nsg = nsg + else: + raise Exception('Invalid nsg value, expected nonnegative integer.') + + @nsg_e.setter + def nsg_e(self, nsg_e): + if isinstance(nsg_e, int) and nsg_e > -1: + self.__nsg_e = nsg_e + else: + raise Exception('Invalid nsg_e value, expected nonnegative integer.') + + @nsh.setter + def nsh(self, nsh): + if isinstance(nsh, int) and nsh > -1: + self.__nsh = nsh + else: + raise Exception('Invalid nsh value, expected nonnegative integer.') + + @nsh_e.setter + def nsh_e(self, nsh_e): + if isinstance(nsh_e, int) and nsh_e > -1: + self.__nsh_e = nsh_e + else: + raise Exception('Invalid nsh_e value, expected nonnegative integer.') + + @nsphi.setter + def nsphi(self, nsphi): + if isinstance(nsphi, int) and nsphi > -1: + self.__nsphi = nsphi + else: + raise Exception('Invalid nsphi value, expected nonnegative integer.') + + @nsphi_e.setter + def nsphi_e(self, nsphi_e): + if isinstance(nsphi_e, int) and nsphi_e > -1: + self.__nsphi_e = nsphi_e + else: + raise Exception('Invalid nsphi_e value, expected nonnegative integer.') + + @ns.setter + def ns(self, ns): + if isinstance(ns, int) and ns > -1: + self.__ns = ns + else: + raise Exception('Invalid ns value, expected nonnegative integer.') + + @ns_e.setter + def ns_e(self, ns_e): + if isinstance(ns_e, int) and ns_e > -1: + self.__ns_e = ns_e + else: + raise Exception('Invalid ns_e value, expected nonnegative integer.') + + @ng.setter + def ng(self, ng): + if isinstance(ng, int) and ng > -1: + self.__ng = ng + else: + raise Exception('Invalid ng value, expected nonnegative integer.') + + @ng_e.setter + def ng_e(self, ng_e): + if isinstance(ng_e, int) and ng_e > -1: + self.__ng_e = ng_e + else: + raise Exception('Invalid ng_e value, expected nonnegative integer.') + + @N.setter + def N(self, N): + if isinstance(N, int) and N > 0: + self.__N = N + else: + raise Exception('Invalid N value, expected positive integer.') + + def set(self, attr, value): + setattr(self, attr, value) + + +class AcadosOcpCost: + """ + Class containing the numerical data of the cost: + + NOTE: all cost terms, except for the terminal one are weighted with the corresponding time step. + This means given the time steps are :math:`\Delta t_0,..., \Delta t_N`, the total cost is given by: + :math:`c_\\text{total} = \Delta t_0 \cdot c_0(x_0, u_0, p_0, z_0) + ... + \Delta t_{N-1} \cdot c_{N-1}(x_0, u_0, p_0, z_0) + c_N(x_N, p_N)`. + + This means the Lagrange cost term is given in continuous time, this makes up for a seeminglessly OCP discretization with a nonuniform time grid. + + In case of LINEAR_LS: + stage cost is + :math:`l(x,u,z) = || V_x \, x + V_u \, u + V_z \, z - y_\\text{ref}||^2_W`, + terminal cost is + :math:`m(x) = || V^e_x \, x - y_\\text{ref}^e||^2_{W^e}` + + In case of NONLINEAR_LS: + stage cost is + :math:`l(x,u,z,p) = || y(x,u,z,p) - y_\\text{ref}||^2_W`, + terminal cost is + :math:`m(x,p) = || y^e(x,p) - y_\\text{ref}^e||^2_{W^e}` + + In case of CONVEX_OVER_NONLINEAR: + stage cost is + :math:`l(x,u,p) = \psi(y(x,u,p) - y_\\text{ref}, p)`, + terminal cost is + :math:`m(x, p) = \psi^e (y^e(x,p) - y_\\text{ref}^e, p)` + """ + def __init__(self): + # initial stage + self.__cost_type_0 = None + self.__W_0 = None + self.__Vx_0 = None + self.__Vu_0 = None + self.__Vz_0 = None + self.__yref_0 = None + self.__cost_ext_fun_type_0 = 'casadi' + # Lagrange term + self.__cost_type = 'LINEAR_LS' # cost type + self.__W = np.zeros((0,0)) + self.__Vx = np.zeros((0,0)) + self.__Vu = np.zeros((0,0)) + self.__Vz = np.zeros((0,0)) + self.__yref = np.array([]) + self.__Zl = np.array([]) + self.__Zu = np.array([]) + self.__zl = np.array([]) + self.__zu = np.array([]) + self.__cost_ext_fun_type = 'casadi' + # Mayer term + self.__cost_type_e = 'LINEAR_LS' + self.__W_e = np.zeros((0,0)) + self.__Vx_e = np.zeros((0,0)) + self.__yref_e = np.array([]) + self.__Zl_e = np.array([]) + self.__Zu_e = np.array([]) + self.__zl_e = np.array([]) + self.__zu_e = np.array([]) + self.__cost_ext_fun_type_e = 'casadi' + + # initial stage + @property + def cost_type_0(self): + """Cost type at initial shooting node (0) + -- string in {EXTERNAL, LINEAR_LS, NONLINEAR_LS, CONVEX_OVER_NONLINEAR} or :code:`None`. + Default: :code:`None`. + + .. note:: Cost at initial stage is the same as for intermediate shooting nodes if not set differently explicitly. + + .. note:: If :py:attr:`cost_type_0` is set to :code:`None` values in :py:attr:`W_0`, :py:attr:`Vx_0`, :py:attr:`Vu_0`, :py:attr:`Vz_0` and :py:attr:`yref_0` are ignored (set to :code:`None`). + """ + return self.__cost_type_0 + + @property + def W_0(self): + """:math:`W_0` - weight matrix at initial shooting node (0). + Default: :code:`None`. + """ + return self.__W_0 + + @property + def Vx_0(self): + """:math:`V_x^0` - x matrix coefficient at initial shooting node (0). + Default: :code:`None`. + """ + return self.__Vx_0 + + @property + def Vu_0(self): + """:math:`V_u^0` - u matrix coefficient at initial shooting node (0). + Default: :code:`None`. + """ + return self.__Vu_0 + + @property + def Vz_0(self): + """:math:`V_z^0` - z matrix coefficient at initial shooting node (0). + Default: :code:`None`. + """ + return self.__Vz_0 + + @property + def yref_0(self): + """:math:`y_\\text{ref}^0` - reference at initial shooting node (0). + Default: :code:`None`. + """ + return self.__yref_0 + + @property + def cost_ext_fun_type_0(self): + """Type of external function for cost at initial shooting node (0) + -- string in {casadi, generic} or :code:`None` + Default: :code:'casadi'. + + .. note:: Cost at initial stage is the same as for intermediate shooting nodes if not set differently explicitly. + """ + return self.__cost_ext_fun_type_0 + + @yref_0.setter + def yref_0(self, yref_0): + if isinstance(yref_0, np.ndarray) and len(yref_0.shape) == 1: + self.__yref_0 = yref_0 + else: + raise Exception('Invalid yref_0 value, expected 1-dimensional numpy array.') + + @W_0.setter + def W_0(self, W_0): + if isinstance(W_0, np.ndarray) and len(W_0.shape) == 2: + self.__W_0 = W_0 + else: + raise Exception('Invalid cost W_0 value. ' \ + + 'Should be 2 dimensional numpy array.') + + @Vx_0.setter + def Vx_0(self, Vx_0): + if isinstance(Vx_0, np.ndarray) and len(Vx_0.shape) == 2: + self.__Vx_0 = Vx_0 + else: + raise Exception('Invalid cost Vx_0 value. ' \ + + 'Should be 2 dimensional numpy array.') + + @Vu_0.setter + def Vu_0(self, Vu_0): + if isinstance(Vu_0, np.ndarray) and len(Vu_0.shape) == 2: + self.__Vu_0 = Vu_0 + else: + raise Exception('Invalid cost Vu_0 value. ' \ + + 'Should be 2 dimensional numpy array.') + + @Vz_0.setter + def Vz_0(self, Vz_0): + if isinstance(Vz_0, np.ndarray) and len(Vz_0.shape) == 2: + self.__Vz_0 = Vz_0 + else: + raise Exception('Invalid cost Vz_0 value. ' \ + + 'Should be 2 dimensional numpy array.') + + @cost_ext_fun_type_0.setter + def cost_ext_fun_type_0(self, cost_ext_fun_type_0): + if cost_ext_fun_type_0 in ['casadi', 'generic']: + self.__cost_ext_fun_type_0 = cost_ext_fun_type_0 + else: + raise Exception('Invalid cost_ext_fun_type_0 value, expected numpy array.') + + # Lagrange term + @property + def cost_type(self): + """ + Cost type at intermediate shooting nodes (1 to N-1) + -- string in {EXTERNAL, LINEAR_LS, NONLINEAR_LS, CONVEX_OVER_NONLINEAR}. + Default: 'LINEAR_LS'. + """ + return self.__cost_type + + @property + def W(self): + """:math:`W` - weight matrix at intermediate shooting nodes (1 to N-1). + Default: :code:`np.zeros((0,0))`. + """ + return self.__W + + @property + def Vx(self): + """:math:`V_x` - x matrix coefficient at intermediate shooting nodes (1 to N-1). + Default: :code:`np.zeros((0,0))`. + """ + return self.__Vx + + @property + def Vu(self): + """:math:`V_u` - u matrix coefficient at intermediate shooting nodes (1 to N-1). + Default: :code:`np.zeros((0,0))`. + """ + return self.__Vu + + @property + def Vz(self): + """:math:`V_z` - z matrix coefficient at intermediate shooting nodes (1 to N-1). + Default: :code:`np.zeros((0,0))`. + """ + return self.__Vz + + @property + def yref(self): + """:math:`y_\\text{ref}` - reference at intermediate shooting nodes (1 to N-1). + Default: :code:`np.array([])`. + """ + return self.__yref + + @property + def Zl(self): + """:math:`Z_l` - diagonal of Hessian wrt lower slack at intermediate shooting nodes (0 to N-1). + Default: :code:`np.array([])`. + """ + return self.__Zl + + @property + def Zu(self): + """:math:`Z_u` - diagonal of Hessian wrt upper slack at intermediate shooting nodes (0 to N-1). + Default: :code:`np.array([])`. + """ + return self.__Zu + + @property + def zl(self): + """:math:`z_l` - gradient wrt lower slack at intermediate shooting nodes (0 to N-1). + Default: :code:`np.array([])`. + """ + return self.__zl + + @property + def zu(self): + """:math:`z_u` - gradient wrt upper slack at intermediate shooting nodes (0 to N-1). + Default: :code:`np.array([])`. + """ + return self.__zu + + @property + def cost_ext_fun_type(self): + """Type of external function for cost at intermediate shooting nodes (1 to N-1). + -- string in {casadi, generic} + Default: :code:'casadi'. + """ + return self.__cost_ext_fun_type + + @cost_type.setter + def cost_type(self, cost_type): + cost_types = ('LINEAR_LS', 'NONLINEAR_LS', 'EXTERNAL', 'CONVEX_OVER_NONLINEAR') + if cost_type in cost_types: + self.__cost_type = cost_type + else: + raise Exception('Invalid cost_type value.') + + @cost_type_0.setter + def cost_type_0(self, cost_type_0): + cost_types = ('LINEAR_LS', 'NONLINEAR_LS', 'EXTERNAL', 'CONVEX_OVER_NONLINEAR') + if cost_type_0 in cost_types: + self.__cost_type_0 = cost_type_0 + else: + raise Exception('Invalid cost_type_0 value.') + + @W.setter + def W(self, W): + if isinstance(W, np.ndarray) and len(W.shape) == 2: + self.__W = W + else: + raise Exception('Invalid cost W value. ' \ + + 'Should be 2 dimensional numpy array.') + + + @Vx.setter + def Vx(self, Vx): + if isinstance(Vx, np.ndarray) and len(Vx.shape) == 2: + self.__Vx = Vx + else: + raise Exception('Invalid cost Vx value. ' \ + + 'Should be 2 dimensional numpy array.') + + @Vu.setter + def Vu(self, Vu): + if isinstance(Vu, np.ndarray) and len(Vu.shape) == 2: + self.__Vu = Vu + else: + raise Exception('Invalid cost Vu value. ' \ + + 'Should be 2 dimensional numpy array.') + + @Vz.setter + def Vz(self, Vz): + if isinstance(Vz, np.ndarray) and len(Vz.shape) == 2: + self.__Vz = Vz + else: + raise Exception('Invalid cost Vz value. ' \ + + 'Should be 2 dimensional numpy array.') + + @yref.setter + def yref(self, yref): + if isinstance(yref, np.ndarray) and len(yref.shape) == 1: + self.__yref = yref + else: + raise Exception('Invalid yref value, expected 1-dimensional numpy array.') + + @Zl.setter + def Zl(self, Zl): + if isinstance(Zl, np.ndarray): + self.__Zl = Zl + else: + raise Exception('Invalid Zl value, expected numpy array.') + + @Zu.setter + def Zu(self, Zu): + if isinstance(Zu, np.ndarray): + self.__Zu = Zu + else: + raise Exception('Invalid Zu value, expected numpy array.') + + @zl.setter + def zl(self, zl): + if isinstance(zl, np.ndarray): + self.__zl = zl + else: + raise Exception('Invalid zl value, expected numpy array.') + + @zu.setter + def zu(self, zu): + if isinstance(zu, np.ndarray): + self.__zu = zu + else: + raise Exception('Invalid zu value, expected numpy array.') + + @cost_ext_fun_type.setter + def cost_ext_fun_type(self, cost_ext_fun_type): + if cost_ext_fun_type in ['casadi', 'generic']: + self.__cost_ext_fun_type = cost_ext_fun_type + else: + raise Exception("Invalid cost_ext_fun_type value, expected one in ['casadi', 'generic'].") + + # Mayer term + @property + def cost_type_e(self): + """ + Cost type at terminal shooting node (N) + -- string in {EXTERNAL, LINEAR_LS, NONLINEAR_LS, CONVEX_OVER_NONLINEAR}. + Default: 'LINEAR_LS'. + """ + return self.__cost_type_e + + @property + def W_e(self): + """:math:`W_e` - weight matrix at terminal shooting node (N). + Default: :code:`np.zeros((0,0))`. + """ + return self.__W_e + + @property + def Vx_e(self): + """:math:`V_x^e` - x matrix coefficient for cost at terminal shooting node (N). + Default: :code:`np.zeros((0,0))`. + """ + return self.__Vx_e + + @property + def yref_e(self): + """:math:`y_\\text{ref}^e` - cost reference at terminal shooting node (N). + Default: :code:`np.array([])`. + """ + return self.__yref_e + + @property + def Zl_e(self): + """:math:`Z_l^e` - diagonal of Hessian wrt lower slack at terminal shooting node (N). + Default: :code:`np.array([])`. + """ + return self.__Zl_e + + @property + def Zu_e(self): + """:math:`Z_u^e` - diagonal of Hessian wrt upper slack at terminal shooting node (N). + Default: :code:`np.array([])`. + """ + return self.__Zu_e + + @property + def zl_e(self): + """:math:`z_l^e` - gradient wrt lower slack at terminal shooting node (N). + Default: :code:`np.array([])`. + """ + return self.__zl_e + + @property + def zu_e(self): + """:math:`z_u^e` - gradient wrt upper slack at terminal shooting node (N). + Default: :code:`np.array([])`. + """ + return self.__zu_e + + @property + def cost_ext_fun_type_e(self): + """Type of external function for cost at terminal shooting node (N). + -- string in {casadi, generic} + Default: :code:'casadi'. + """ + return self.__cost_ext_fun_type_e + + @cost_type_e.setter + def cost_type_e(self, cost_type_e): + cost_types = ('LINEAR_LS', 'NONLINEAR_LS', 'EXTERNAL', 'CONVEX_OVER_NONLINEAR') + + if cost_type_e in cost_types: + self.__cost_type_e = cost_type_e + else: + raise Exception('Invalid cost_type_e value.') + + @W_e.setter + def W_e(self, W_e): + if isinstance(W_e, np.ndarray) and len(W_e.shape) == 2: + self.__W_e = W_e + else: + raise Exception('Invalid cost W_e value. ' \ + + 'Should be 2 dimensional numpy array.') + + @Vx_e.setter + def Vx_e(self, Vx_e): + if isinstance(Vx_e, np.ndarray) and len(Vx_e.shape) == 2: + self.__Vx_e = Vx_e + else: + raise Exception('Invalid cost Vx_e value. ' \ + + 'Should be 2 dimensional numpy array.') + + @yref_e.setter + def yref_e(self, yref_e): + if isinstance(yref_e, np.ndarray) and len(yref_e.shape) == 1: + self.__yref_e = yref_e + else: + raise Exception('Invalid yref_e value, expected 1-dimensional numpy array.') + + @Zl_e.setter + def Zl_e(self, Zl_e): + if isinstance(Zl_e, np.ndarray): + self.__Zl_e = Zl_e + else: + raise Exception('Invalid Zl_e value, expected numpy array.') + + @Zu_e.setter + def Zu_e(self, Zu_e): + if isinstance(Zu_e, np.ndarray): + self.__Zu_e = Zu_e + else: + raise Exception('Invalid Zu_e value, expected numpy array.') + + @zl_e.setter + def zl_e(self, zl_e): + if isinstance(zl_e, np.ndarray): + self.__zl_e = zl_e + else: + raise Exception('Invalid zl_e value, expected numpy array.') + + @zu_e.setter + def zu_e(self, zu_e): + if isinstance(zu_e, np.ndarray): + self.__zu_e = zu_e + else: + raise Exception('Invalid zu_e value, expected numpy array.') + + @cost_ext_fun_type_e.setter + def cost_ext_fun_type_e(self, cost_ext_fun_type_e): + if cost_ext_fun_type_e in ['casadi', 'generic']: + self.__cost_ext_fun_type_e = cost_ext_fun_type_e + else: + raise Exception("Invalid cost_ext_fun_type_e value, expected one in ['casadi', 'generic'].") + + def set(self, attr, value): + setattr(self, attr, value) + + +def print_J_to_idx_note(): + print("NOTE: J* matrix is converted to zero based vector idx* vector, which is returned here.") + + +class AcadosOcpConstraints: + """ + class containing the description of the constraints + """ + def __init__(self): + self.__constr_type = 'BGH' + self.__constr_type_e = 'BGH' + # initial x + self.__lbx_0 = np.array([]) + self.__ubx_0 = np.array([]) + self.__idxbx_0 = np.array([]) + self.__idxbxe_0 = np.array([]) + # state bounds + self.__lbx = np.array([]) + self.__ubx = np.array([]) + self.__idxbx = np.array([]) + # bounds on x at shooting node N + self.__lbx_e = np.array([]) + self.__ubx_e = np.array([]) + self.__idxbx_e = np.array([]) + # bounds on u + self.__lbu = np.array([]) + self.__ubu = np.array([]) + self.__idxbu = np.array([]) + # polytopic constraints + self.__lg = np.array([]) + self.__ug = np.array([]) + self.__D = np.zeros((0,0)) + self.__C = np.zeros((0,0)) + # polytopic constraints at shooting node N + self.__C_e = np.zeros((0,0)) + self.__lg_e = np.array([]) + self.__ug_e = np.array([]) + # nonlinear constraints + self.__lh = np.array([]) + self.__uh = np.array([]) + # nonlinear constraints at shooting node N + self.__uh_e = np.array([]) + self.__lh_e = np.array([]) + # convex-over-nonlinear constraints + self.__lphi = np.array([]) + self.__uphi = np.array([]) + # nonlinear constraints at shooting node N + self.__uphi_e = np.array([]) + self.__lphi_e = np.array([]) + # SLACK BOUNDS + # soft bounds on x + self.__lsbx = np.array([]) + self.__usbx = np.array([]) + self.__idxsbx = np.array([]) + # soft bounds on u + self.__lsbu = np.array([]) + self.__usbu = np.array([]) + self.__idxsbu = np.array([]) + # soft bounds on x at shooting node N + self.__lsbx_e = np.array([]) + self.__usbx_e = np.array([]) + self.__idxsbx_e= np.array([]) + # soft bounds on general linear constraints + self.__lsg = np.array([]) + self.__usg = np.array([]) + self.__idxsg = np.array([]) + # soft bounds on nonlinear constraints + self.__lsh = np.array([]) + self.__ush = np.array([]) + self.__idxsh = np.array([]) + # soft bounds on nonlinear constraints + self.__lsphi = np.array([]) + self.__usphi = np.array([]) + self.__idxsphi = np.array([]) + # soft bounds on general linear constraints at shooting node N + self.__lsg_e = np.array([]) + self.__usg_e = np.array([]) + self.__idxsg_e = np.array([]) + # soft bounds on nonlinear constraints at shooting node N + self.__lsh_e = np.array([]) + self.__ush_e = np.array([]) + self.__idxsh_e = np.array([]) + # soft bounds on nonlinear constraints at shooting node N + self.__lsphi_e = np.array([]) + self.__usphi_e = np.array([]) + self.__idxsphi_e = np.array([]) + + + # types + @property + def constr_type(self): + """Constraints type for shooting nodes (0 to N-1). string in {BGH, BGP}. + Default: BGH; BGP is for convex over nonlinear.""" + return self.__constr_type + + @property + def constr_type_e(self): + """Constraints type for terminal shooting node N. string in {BGH, BGP}. + Default: BGH; BGP is for convex over nonlinear.""" + return self.__constr_type_e + + # initial bounds on x + @property + def lbx_0(self): + """:math:`\\underline{x_0}` - lower bounds on x at initial stage 0. + Type: :code:`np.ndarray`; default: :code:`np.array([])`.""" + return self.__lbx_0 + + @property + def ubx_0(self): + """:math:`\\bar{x_0}` - upper bounds on x at initial stage 0. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__ubx_0 + + @property + def Jbx_0(self): + """:math:`J_{bx,0}` - matrix coefficient for bounds on x at initial stage 0. + Translated internally to :py:attr:`idxbx_0`""" + print_J_to_idx_note() + return self.__idxbx_0 + + @property + def idxbx_0(self): + """Indices of bounds on x at initial stage 0 + -- can be set automatically via x0. + Can be set by using :py:attr:`Jbx_0`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxbx_0 + + @property + def idxbxe_0(self): + """Indices of bounds on x0 that are equalities -- can be set automatically via :py:attr:`x0`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxbxe_0 + + # bounds on x + @property + def lbx(self): + """:math:`\\underline{x}` - lower bounds on x at intermediate shooting nodes (1 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__lbx + + @property + def ubx(self): + """:math:`\\bar{x}` - upper bounds on x at intermediate shooting nodes (1 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__ubx + + @property + def idxbx(self): + """indices of bounds on x (defines :math:`J_{bx}`) at intermediate shooting nodes (1 to N-1). + Can be set by using :py:attr:`Jbx`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxbx + + @property + def Jbx(self): + """:math:`J_{bx}` - matrix coefficient for bounds on x + at intermediate shooting nodes (1 to N-1). + Translated internally into :py:attr:`idxbx`.""" + print_J_to_idx_note() + return self.__idxbx + + # bounds on x at shooting node N + @property + def lbx_e(self): + """:math:`\\underline{x}^e` - lower bounds on x at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__lbx_e + + @property + def ubx_e(self): + """:math:`\\bar{x}^e` - upper bounds on x at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__ubx_e + + @property + def idxbx_e(self): + """Indices for bounds on x at terminal shooting node N (defines :math:`J_{bx}^e`). + Can be set by using :py:attr:`Jbx_e`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxbx_e + + @property + def Jbx_e(self): + """:math:`J_{bx}^e` matrix coefficient for bounds on x at terminal shooting node N. + Translated internally into :py:attr:`idxbx_e`.""" + print_J_to_idx_note() + return self.__idxbx_e + + # bounds on u + @property + def lbu(self): + """:math:`\\underline{u}` - lower bounds on u at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])` + """ + return self.__lbu + + @property + def ubu(self): + """:math:`\\bar{u}` - upper bounds on u at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])` + """ + return self.__ubu + + @property + def idxbu(self): + """Indices of bounds on u (defines :math:`J_{bu}`) at shooting nodes (0 to N-1). + Can be set by using :py:attr:`Jbu`. + Type: :code:`np.ndarray`; default: :code:`np.array([])` + """ + return self.__idxbu + + @property + def Jbu(self): + """:math:`J_{bu}` - matrix coefficient for bounds on u at shooting nodes (0 to N-1). + Translated internally to :py:attr:`idxbu`. + """ + print_J_to_idx_note() + return self.__idxbu + + # polytopic constraints + @property + def C(self): + """:math:`C` - C matrix in :math:`\\underline{g} \\leq D \, u + C \, x \\leq \\bar{g}` + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array((0,0))`. + """ + return self.__C + + @property + def D(self): + """:math:`D` - D matrix in :math:`\\underline{g} \\leq D \, u + C \, x \\leq \\bar{g}` + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array((0,0))` + """ + return self.__D + + @property + def lg(self): + """:math:`\\underline{g}` - lower bound for general polytopic inequalities + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])` + """ + return self.__lg + + @property + def ug(self): + """:math:`\\bar{g}` - upper bound for general polytopic inequalities + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__ug + + # polytopic constraints at shooting node N + @property + def C_e(self): + """:math:`C^e` - C matrix at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array((0,0))`. + """ + return self.__C_e + + @property + def lg_e(self): + """:math:`\\underline{g}^e` - lower bound on general polytopic inequalities + at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__lg_e + + @property + def ug_e(self): + """:math:`\\bar{g}^e` - upper bound on general polytopic inequalities + at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__ug_e + + + # nonlinear constraints + @property + def lh(self): + """:math:`\\underline{h}` - lower bound for nonlinear inequalities + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__lh + + @property + def uh(self): + """:math:`\\bar{h}` - upper bound for nonlinear inequalities + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__uh + + # nonlinear constraints at shooting node N + @property + def lh_e(self): + """:math:`\\underline{h}^e` - lower bound on nonlinear inequalities + at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__lh_e + + @property + def uh_e(self): + """:math:`\\bar{h}^e` - upper bound on nonlinear inequalities + at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__uh_e + + # convex-over-nonlinear constraints + @property + def lphi(self): + """:math:`\\underline{\phi}` - lower bound for convex-over-nonlinear inequalities + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__lphi + + @property + def uphi(self): + """:math:`\\bar{\phi}` - upper bound for convex-over-nonlinear inequalities + at shooting nodes (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__uphi + + # convex-over-nonlinear constraints at shooting node N + @property + def lphi_e(self): + """:math:`\\underline{\phi}^e` - lower bound on convex-over-nonlinear inequalities + at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__lphi_e + + @property + def uphi_e(self): + """:math:`\\bar{\phi}^e` - upper bound on convex-over-nonlinear inequalities + at terminal shooting node N. + Type: :code:`np.ndarray`; default: :code:`np.array([])`. + """ + return self.__uphi_e + + + # SLACK bounds + # soft bounds on x + @property + def lsbx(self): + """Lower bounds on slacks corresponding to soft lower bounds on x + at stages (1 to N-1); + not required - zeros by default""" + return self.__lsbx + + @property + def usbx(self): + """Lower bounds on slacks corresponding to soft upper bounds on x + at stages (1 to N-1); + not required - zeros by default""" + return self.__usbx + + @property + def idxsbx(self): + """Indices of soft bounds on x within the indices of bounds on x + at stages (1 to N-1). + Can be set by using :py:attr:`Jsbx`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsbx + + @property + def Jsbx(self): + """:math:`J_{sbx}` - matrix coefficient for soft bounds on x + at stages (1 to N-1); + Translated internally into :py:attr:`idxsbx`.""" + print_J_to_idx_note() + return self.__idxsbx + + # soft bounds on u + @property + def lsbu(self): + """Lower bounds on slacks corresponding to soft lower bounds on u + at stages (0 to N-1). + Not required - zeros by default.""" + return self.__lsbu + + @property + def usbu(self): + """Lower bounds on slacks corresponding to soft upper bounds on u + at stages (0 to N-1); + not required - zeros by default""" + return self.__usbu + + @property + def idxsbu(self): + """Indices of soft bounds on u within the indices of bounds on u + at stages (0 to N-1). + Can be set by using :py:attr:`Jsbu`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsbu + + @property + def Jsbu(self): + """:math:`J_{sbu}` - matrix coefficient for soft bounds on u + at stages (0 to N-1); + internally translated into :py:attr:`idxsbu`""" + print_J_to_idx_note() + return self.__idxsbu + + # soft bounds on x at shooting node N + @property + def lsbx_e(self): + """Lower bounds on slacks corresponding to soft lower bounds on x at shooting node N. + Not required - zeros by default""" + return self.__lsbx_e + + @property + def usbx_e(self): + """Lower bounds on slacks corresponding to soft upper bounds on x at shooting node N. + Not required - zeros by default""" + return self.__usbx_e + + @property + def idxsbx_e(self): + """Indices of soft bounds on x at shooting node N, within the indices of bounds on x at terminal shooting node N. + Can be set by using :py:attr:`Jsbx_e`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsbx_e + + @property + def Jsbx_e(self): + """:math:`J_{sbx}^e` - matrix coefficient for soft bounds on x at terminal shooting node N. + Translated internally to :py:attr:`idxsbx_e`""" + print_J_to_idx_note() + return self.__idxsbx_e + + # soft general linear constraints + @property + def lsg(self): + """Lower bounds on slacks corresponding to soft lower bounds for general linear constraints + at stages (0 to N-1). + Type: :code:`np.ndarray`; default: :code:`np.array([])` + """ + return self.__lsg + + @property + def usg(self): + """Lower bounds on slacks corresponding to soft upper bounds for general linear constraints. + Not required - zeros by default""" + return self.__usg + + @property + def idxsg(self): + """Indices of soft general linear constraints within the indices of general linear constraints. + Can be set by using :py:attr:`Jsg`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsg + + @property + def Jsg(self): + """:math:`J_{sg}` - matrix coefficient for soft bounds on general linear constraints. + Translated internally to :py:attr:`idxsg`""" + print_J_to_idx_note() + return self.__idxsg + + # soft nonlinear constraints + @property + def lsh(self): + """Lower bounds on slacks corresponding to soft lower bounds for nonlinear constraints. + Not required - zeros by default""" + return self.__lsh + + @property + def ush(self): + """Lower bounds on slacks corresponding to soft upper bounds for nonlinear constraints. + Not required - zeros by default""" + return self.__ush + + @property + def idxsh(self): + """Indices of soft nonlinear constraints within the indices of nonlinear constraints. + Can be set by using :py:attr:`Jbx`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsh + + @property + def Jsh(self): + """:math:`J_{sh}` - matrix coefficient for soft bounds on nonlinear constraints. + Translated internally to :py:attr:`idxsh`""" + print_J_to_idx_note() + return self.__idxsh + + # soft bounds on convex-over-nonlinear constraints + @property + def lsphi(self): + """Lower bounds on slacks corresponding to soft lower bounds for convex-over-nonlinear constraints. + Not required - zeros by default""" + return self.__lsphi + + @property + def usphi(self): + """Lower bounds on slacks corresponding to soft upper bounds for convex-over-nonlinear constraints. + Not required - zeros by default""" + return self.__usphi + + @property + def idxsphi(self): + """Indices of soft convex-over-nonlinear constraints within the indices of nonlinear constraints. + Can be set by using :py:attr:`Jsphi`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsphi + + @property + def Jsphi(self): + """:math:`J_{s, \phi}` - matrix coefficient for soft bounds on convex-over-nonlinear constraints. + Translated internally into :py:attr:`idxsphi`.""" + print_J_to_idx_note() + return self.__idxsphi + + + # soft bounds on general linear constraints at shooting node N + @property + def lsg_e(self): + """Lower bounds on slacks corresponding to soft lower bounds for general linear constraints at shooting node N. + Not required - zeros by default""" + return self.__lsg_e + + @property + def usg_e(self): + """Lower bounds on slacks corresponding to soft upper bounds for general linear constraints at shooting node N. + Not required - zeros by default""" + return self.__usg_e + + @property + def idxsg_e(self): + """Indices of soft general linear constraints at shooting node N within the indices of general linear constraints at shooting node N. + Can be set by using :py:attr:`Jsg_e`.""" + return self.__idxsg_e + + @property + def Jsg_e(self): + """:math:`J_{s,h}^e` - matrix coefficient for soft bounds on general linear constraints at terminal shooting node N. + Translated internally to :py:attr:`idxsg_e`""" + print_J_to_idx_note() + return self.__idxsg_e + + + # soft bounds on nonlinear constraints at shooting node N + @property + def lsh_e(self): + """Lower bounds on slacks corresponding to soft lower bounds for nonlinear constraints at terminal shooting node N. + Not required - zeros by default""" + return self.__lsh_e + + @property + def ush_e(self): + """Lower bounds on slacks corresponding to soft upper bounds for nonlinear constraints at terminal shooting node N. + Not required - zeros by default""" + return self.__ush_e + + @property + def idxsh_e(self): + """Indices of soft nonlinear constraints at shooting node N within the indices of nonlinear constraints at terminal shooting node N. + Can be set by using :py:attr:`Jsh_e`.""" + return self.__idxsh_e + + @property + def Jsh_e(self): + """:math:`J_{s,h}^e` - matrix coefficient for soft bounds on nonlinear constraints at terminal shooting node N; fills :py:attr:`idxsh_e`""" + print_J_to_idx_note() + return self.__idxsh_e + + # soft bounds on convex-over-nonlinear constraints at shooting node N + @property + def lsphi_e(self): + """Lower bounds on slacks corresponding to soft lower bounds for convex-over-nonlinear constraints at terminal shooting node N. + Not required - zeros by default""" + return self.__lsphi_e + + @property + def usphi_e(self): + """Lower bounds on slacks corresponding to soft upper bounds for convex-over-nonlinear constraints at terminal shooting node N. + Not required - zeros by default""" + return self.__usphi_e + + @property + def idxsphi_e(self): + """Indices of soft nonlinear constraints at shooting node N within the indices of nonlinear constraints at terminal shooting node N. + Can be set by using :py:attr:`Jsphi_e`. + Type: :code:`np.ndarray`; default: :code:`np.array([])`""" + return self.__idxsphi_e + + @property + def Jsphi_e(self): + """:math:`J_{sh}^e` - matrix coefficient for soft bounds on convex-over-nonlinear constraints at shooting node N. + Translated internally to :py:attr:`idxsphi_e`""" + print_J_to_idx_note() + return self.__idxsphi_e + + @property + def x0(self): + """:math:`x_0 \\in \mathbb{R}^{n_x}` - initial state -- + Translated internally to :py:attr:`idxbx_0`, :py:attr:`lbx_0`, :py:attr:`ubx_0`, :py:attr:`idxbxe_0` """ + print("x0 is converted to lbx_0, ubx_0, idxbx_0") + print("idxbx_0: ", self.__idxbx_0) + print("lbx_0: ", self.__lbx_0) + print("ubx_0: ", self.__ubx_0) + print("idxbxe_0: ", self.__idxbxe_0) + return None + + # SETTERS + @constr_type.setter + def constr_type(self, constr_type): + constr_types = ('BGH', 'BGP') + if constr_type in constr_types: + self.__constr_type = constr_type + else: + raise Exception('Invalid constr_type value. Possible values are:\n\n' \ + + ',\n'.join(constr_types) + '.\n\nYou have: ' + constr_type + '.\n\n') + + @constr_type_e.setter + def constr_type_e(self, constr_type_e): + constr_types = ('BGH', 'BGP') + if constr_type_e in constr_types: + self.__constr_type_e = constr_type_e + else: + raise Exception('Invalid constr_type_e value. Possible values are:\n\n' \ + + ',\n'.join(constr_types) + '.\n\nYou have: ' + constr_type_e + '.\n\n') + + # initial x + @lbx_0.setter + def lbx_0(self, lbx_0): + if isinstance(lbx_0, np.ndarray): + self.__lbx_0 = lbx_0 + else: + raise Exception('Invalid lbx_0 value.') + + @ubx_0.setter + def ubx_0(self, ubx_0): + if isinstance(ubx_0, np.ndarray): + self.__ubx_0 = ubx_0 + else: + raise Exception('Invalid ubx_0 value.') + + @idxbx_0.setter + def idxbx_0(self, idxbx_0): + if isinstance(idxbx_0, np.ndarray): + self.__idxbx_0 = idxbx_0 + else: + raise Exception('Invalid idxbx_0 value.') + + @Jbx_0.setter + def Jbx_0(self, Jbx_0): + if isinstance(Jbx_0, np.ndarray): + self.__idxbx_0 = J_to_idx(Jbx_0) + else: + raise Exception('Invalid Jbx_0 value.') + + @idxbxe_0.setter + def idxbxe_0(self, idxbxe_0): + if isinstance(idxbxe_0, np.ndarray): + self.__idxbxe_0 = idxbxe_0 + else: + raise Exception('Invalid idxbxe_0 value.') + + + @x0.setter + def x0(self, x0): + if isinstance(x0, np.ndarray): + self.__lbx_0 = x0 + self.__ubx_0 = x0 + self.__idxbx_0 = np.arange(x0.size) + self.__idxbxe_0 = np.arange(x0.size) + else: + raise Exception('Invalid x0 value.') + + # bounds on x + @lbx.setter + def lbx(self, lbx): + if isinstance(lbx, np.ndarray): + self.__lbx = lbx + else: + raise Exception('Invalid lbx value.') + + @ubx.setter + def ubx(self, ubx): + if isinstance(ubx, np.ndarray): + self.__ubx = ubx + else: + raise Exception('Invalid ubx value.') + + @idxbx.setter + def idxbx(self, idxbx): + if isinstance(idxbx, np.ndarray): + self.__idxbx = idxbx + else: + raise Exception('Invalid idxbx value.') + + @Jbx.setter + def Jbx(self, Jbx): + if isinstance(Jbx, np.ndarray): + self.__idxbx = J_to_idx(Jbx) + else: + raise Exception('Invalid Jbx value.') + + # bounds on u + @lbu.setter + def lbu(self, lbu): + if isinstance(lbu, np.ndarray): + self.__lbu = lbu + else: + raise Exception('Invalid lbu value.') + + @ubu.setter + def ubu(self, ubu): + if isinstance(ubu, np.ndarray): + self.__ubu = ubu + else: + raise Exception('Invalid ubu value.') + + @idxbu.setter + def idxbu(self, idxbu): + if isinstance(idxbu, np.ndarray): + self.__idxbu = idxbu + else: + raise Exception('Invalid idxbu value.') + + @Jbu.setter + def Jbu(self, Jbu): + if isinstance(Jbu, np.ndarray): + self.__idxbu = J_to_idx(Jbu) + else: + raise Exception('Invalid Jbu value.') + + # bounds on x at shooting node N + @lbx_e.setter + def lbx_e(self, lbx_e): + if isinstance(lbx_e, np.ndarray): + self.__lbx_e = lbx_e + else: + raise Exception('Invalid lbx_e value.') + + @ubx_e.setter + def ubx_e(self, ubx_e): + if isinstance(ubx_e, np.ndarray): + self.__ubx_e = ubx_e + else: + raise Exception('Invalid ubx_e value.') + + @idxbx_e.setter + def idxbx_e(self, idxbx_e): + if isinstance(idxbx_e, np.ndarray): + self.__idxbx_e = idxbx_e + else: + raise Exception('Invalid idxbx_e value.') + + @Jbx_e.setter + def Jbx_e(self, Jbx_e): + if isinstance(Jbx_e, np.ndarray): + self.__idxbx_e = J_to_idx(Jbx_e) + else: + raise Exception('Invalid Jbx_e value.') + + # polytopic constraints + @D.setter + def D(self, D): + if isinstance(D, np.ndarray) and len(D.shape) == 2: + self.__D = D + else: + raise Exception('Invalid constraint D value.' \ + + 'Should be 2 dimensional numpy array.') + + @C.setter + def C(self, C): + if isinstance(C, np.ndarray) and len(C.shape) == 2: + self.__C = C + else: + raise Exception('Invalid constraint C value.' \ + + 'Should be 2 dimensional numpy array.') + + @lg.setter + def lg(self, lg): + if isinstance(lg, np.ndarray): + self.__lg = lg + else: + raise Exception('Invalid lg value.') + + @ug.setter + def ug(self, ug): + if isinstance(ug, np.ndarray): + self.__ug = ug + else: + raise Exception('Invalid ug value.') + + # polytopic constraints at shooting node N + @C_e.setter + def C_e(self, C_e): + if isinstance(C_e, np.ndarray) and len(C_e.shape) == 2: + self.__C_e = C_e + else: + raise Exception('Invalid constraint C_e value.' \ + + 'Should be 2 dimensional numpy array.') + + @lg_e.setter + def lg_e(self, lg_e): + if isinstance(lg_e, np.ndarray): + self.__lg_e = lg_e + else: + raise Exception('Invalid lg_e value.') + + @ug_e.setter + def ug_e(self, ug_e): + if isinstance(ug_e, np.ndarray): + self.__ug_e = ug_e + else: + raise Exception('Invalid ug_e value.') + + # nonlinear constraints + @lh.setter + def lh(self, lh): + if isinstance(lh, np.ndarray): + self.__lh = lh + else: + raise Exception('Invalid lh value.') + + @uh.setter + def uh(self, uh): + if isinstance(uh, np.ndarray): + self.__uh = uh + else: + raise Exception('Invalid uh value.') + + # convex-over-nonlinear constraints + @lphi.setter + def lphi(self, lphi): + if isinstance(lphi, np.ndarray): + self.__lphi = lphi + else: + raise Exception('Invalid lphi value.') + + @uphi.setter + def uphi(self, uphi): + if isinstance(uphi, np.ndarray): + self.__uphi = uphi + else: + raise Exception('Invalid uphi value.') + + # nonlinear constraints at shooting node N + @lh_e.setter + def lh_e(self, lh_e): + if isinstance(lh_e, np.ndarray): + self.__lh_e = lh_e + else: + raise Exception('Invalid lh_e value.') + + @uh_e.setter + def uh_e(self, uh_e): + if isinstance(uh_e, np.ndarray): + self.__uh_e = uh_e + else: + raise Exception('Invalid uh_e value.') + + # convex-over-nonlinear constraints at shooting node N + @lphi_e.setter + def lphi_e(self, lphi_e): + if isinstance(lphi_e, np.ndarray): + self.__lphi_e = lphi_e + else: + raise Exception('Invalid lphi_e value.') + + @uphi_e.setter + def uphi_e(self, uphi_e): + if isinstance(uphi_e, np.ndarray): + self.__uphi_e = uphi_e + else: + raise Exception('Invalid uphi_e value.') + + # SLACK bounds + # soft bounds on x + @lsbx.setter + def lsbx(self, lsbx): + if isinstance(lsbx, np.ndarray): + self.__lsbx = lsbx + else: + raise Exception('Invalid lsbx value.') + + @usbx.setter + def usbx(self, usbx): + if isinstance(usbx, np.ndarray): + self.__usbx = usbx + else: + raise Exception('Invalid usbx value.') + + @idxsbx.setter + def idxsbx(self, idxsbx): + if isinstance(idxsbx, np.ndarray): + self.__idxsbx = idxsbx + else: + raise Exception('Invalid idxsbx value.') + + @Jsbx.setter + def Jsbx(self, Jsbx): + if isinstance(Jsbx, np.ndarray): + self.__idxsbx = J_to_idx_slack(Jsbx) + else: + raise Exception('Invalid Jsbx value, expected numpy array.') + + # soft bounds on u + @lsbu.setter + def lsbu(self, lsbu): + if isinstance(lsbu, np.ndarray): + self.__lsbu = lsbu + else: + raise Exception('Invalid lsbu value.') + + @usbu.setter + def usbu(self, usbu): + if isinstance(usbu, np.ndarray): + self.__usbu = usbu + else: + raise Exception('Invalid usbu value.') + + @idxsbu.setter + def idxsbu(self, idxsbu): + if isinstance(idxsbu, np.ndarray): + self.__idxsbu = idxsbu + else: + raise Exception('Invalid idxsbu value.') + + @Jsbu.setter + def Jsbu(self, Jsbu): + if isinstance(Jsbu, np.ndarray): + self.__idxsbu = J_to_idx_slack(Jsbu) + else: + raise Exception('Invalid Jsbu value.') + + # soft bounds on x at shooting node N + @lsbx_e.setter + def lsbx_e(self, lsbx_e): + if isinstance(lsbx_e, np.ndarray): + self.__lsbx_e = lsbx_e + else: + raise Exception('Invalid lsbx_e value.') + + @usbx_e.setter + def usbx_e(self, usbx_e): + if isinstance(usbx_e, np.ndarray): + self.__usbx_e = usbx_e + else: + raise Exception('Invalid usbx_e value.') + + @idxsbx_e.setter + def idxsbx_e(self, idxsbx_e): + if isinstance(idxsbx_e, np.ndarray): + self.__idxsbx_e = idxsbx_e + else: + raise Exception('Invalid idxsbx_e value.') + + @Jsbx_e.setter + def Jsbx_e(self, Jsbx_e): + if isinstance(Jsbx_e, np.ndarray): + self.__idxsbx_e = J_to_idx_slack(Jsbx_e) + else: + raise Exception('Invalid Jsbx_e value.') + + + # soft bounds on general linear constraints + @lsg.setter + def lsg(self, lsg): + if isinstance(lsg, np.ndarray): + self.__lsg = lsg + else: + raise Exception('Invalid lsg value.') + + @usg.setter + def usg(self, usg): + if isinstance(usg, np.ndarray): + self.__usg = usg + else: + raise Exception('Invalid usg value.') + + @idxsg.setter + def idxsg(self, idxsg): + if isinstance(idxsg, np.ndarray): + self.__idxsg = idxsg + else: + raise Exception('Invalid idxsg value.') + + @Jsg.setter + def Jsg(self, Jsg): + if isinstance(Jsg, np.ndarray): + self.__idxsg = J_to_idx_slack(Jsg) + else: + raise Exception('Invalid Jsg value, expected numpy array.') + + + # soft bounds on nonlinear constraints + @lsh.setter + def lsh(self, lsh): + if isinstance(lsh, np.ndarray): + self.__lsh = lsh + else: + raise Exception('Invalid lsh value.') + + @ush.setter + def ush(self, ush): + if isinstance(ush, np.ndarray): + self.__ush = ush + else: + raise Exception('Invalid ush value.') + + @idxsh.setter + def idxsh(self, idxsh): + if isinstance(idxsh, np.ndarray): + self.__idxsh = idxsh + else: + raise Exception('Invalid idxsh value.') + + + @Jsh.setter + def Jsh(self, Jsh): + if isinstance(Jsh, np.ndarray): + self.__idxsh = J_to_idx_slack(Jsh) + else: + raise Exception('Invalid Jsh value, expected numpy array.') + + # soft bounds on convex-over-nonlinear constraints + @lsphi.setter + def lsphi(self, lsphi): + if isinstance(lsphi, np.ndarray): + self.__lsphi = lsphi + else: + raise Exception('Invalid lsphi value.') + + @usphi.setter + def usphi(self, usphi): + if isinstance(usphi, np.ndarray): + self.__usphi = usphi + else: + raise Exception('Invalid usphi value.') + + @idxsphi.setter + def idxsphi(self, idxsphi): + if isinstance(idxsphi, np.ndarray): + self.__idxsphi = idxsphi + else: + raise Exception('Invalid idxsphi value.') + + @Jsphi.setter + def Jsphi(self, Jsphi): + if isinstance(Jsphi, np.ndarray): + self.__idxsphi = J_to_idx_slack(Jsphi) + else: + raise Exception('Invalid Jsphi value, expected numpy array.') + + # soft bounds on general linear constraints at shooting node N + @lsg_e.setter + def lsg_e(self, lsg_e): + if isinstance(lsg_e, np.ndarray): + self.__lsg_e = lsg_e + else: + raise Exception('Invalid lsg_e value.') + + @usg_e.setter + def usg_e(self, usg_e): + if isinstance(usg_e, np.ndarray): + self.__usg_e = usg_e + else: + raise Exception('Invalid usg_e value.') + + @idxsg_e.setter + def idxsg_e(self, idxsg_e): + if isinstance(idxsg_e, np.ndarray): + self.__idxsg_e = idxsg_e + else: + raise Exception('Invalid idxsg_e value.') + + @Jsg_e.setter + def Jsg_e(self, Jsg_e): + if isinstance(Jsg_e, np.ndarray): + self.__idxsg_e = J_to_idx_slack(Jsg_e) + else: + raise Exception('Invalid Jsg_e value, expected numpy array.') + + # soft bounds on nonlinear constraints at shooting node N + @lsh_e.setter + def lsh_e(self, lsh_e): + if isinstance(lsh_e, np.ndarray): + self.__lsh_e = lsh_e + else: + raise Exception('Invalid lsh_e value.') + + @ush_e.setter + def ush_e(self, ush_e): + if isinstance(ush_e, np.ndarray): + self.__ush_e = ush_e + else: + raise Exception('Invalid ush_e value.') + + @idxsh_e.setter + def idxsh_e(self, idxsh_e): + if isinstance(idxsh_e, np.ndarray): + self.__idxsh_e = idxsh_e + else: + raise Exception('Invalid idxsh_e value.') + + @Jsh_e.setter + def Jsh_e(self, Jsh_e): + if isinstance(Jsh_e, np.ndarray): + self.__idxsh_e = J_to_idx_slack(Jsh_e) + else: + raise Exception('Invalid Jsh_e value, expected numpy array.') + + + # soft bounds on convex-over-nonlinear constraints at shooting node N + @lsphi_e.setter + def lsphi_e(self, lsphi_e): + if isinstance(lsphi_e, np.ndarray): + self.__lsphi_e = lsphi_e + else: + raise Exception('Invalid lsphi_e value.') + + @usphi_e.setter + def usphi_e(self, usphi_e): + if isinstance(usphi_e, np.ndarray): + self.__usphi_e = usphi_e + else: + raise Exception('Invalid usphi_e value.') + + @idxsphi_e.setter + def idxsphi_e(self, idxsphi_e): + if isinstance(idxsphi_e, np.ndarray): + self.__idxsphi_e = idxsphi_e + else: + raise Exception('Invalid idxsphi_e value.') + + @Jsphi_e.setter + def Jsphi_e(self, Jsphi_e): + if isinstance(Jsphi_e, np.ndarray): + self.__idxsphi_e = J_to_idx_slack(Jsphi_e) + else: + raise Exception('Invalid Jsphi_e value.') + + def set(self, attr, value): + setattr(self, attr, value) + + +class AcadosOcpOptions: + """ + class containing the description of the solver options + """ + def __init__(self): + self.__qp_solver = 'PARTIAL_CONDENSING_HPIPM' # qp solver to be used in the NLP solver + self.__hessian_approx = 'GAUSS_NEWTON' # hessian approximation + self.__integrator_type = 'ERK' # integrator type + self.__tf = None # prediction horizon + self.__nlp_solver_type = 'SQP_RTI' # NLP solver + self.__globalization = 'FIXED_STEP' + self.__nlp_solver_step_length = 1.0 # fixed Newton step length + self.__levenberg_marquardt = 0.0 + self.__collocation_type = 'GAUSS_LEGENDRE' + self.__sim_method_num_stages = 4 # number of stages in the integrator + self.__sim_method_num_steps = 1 # number of steps in the integrator + self.__sim_method_newton_iter = 3 # number of Newton iterations in simulation method + self.__sim_method_newton_tol = 0.0 + self.__sim_method_jac_reuse = 0 + self.__qp_solver_tol_stat = None # QP solver stationarity tolerance + self.__qp_solver_tol_eq = None # QP solver equality tolerance + self.__qp_solver_tol_ineq = None # QP solver inequality + self.__qp_solver_tol_comp = None # QP solver complementarity + self.__qp_solver_iter_max = 50 # QP solver max iter + self.__qp_solver_cond_N = None # QP solver: new horizon after partial condensing + self.__qp_solver_warm_start = 0 + self.__qp_solver_cond_ric_alg = 1 + self.__qp_solver_ric_alg = 1 + self.__nlp_solver_tol_stat = 1e-6 # NLP solver stationarity tolerance + self.__nlp_solver_tol_eq = 1e-6 # NLP solver equality tolerance + self.__nlp_solver_tol_ineq = 1e-6 # NLP solver inequality + self.__nlp_solver_tol_comp = 1e-6 # NLP solver complementarity + self.__nlp_solver_max_iter = 100 # NLP solver maximum number of iterations + self.__nlp_solver_ext_qp_res = 0 + self.__Tsim = None # automatically calculated as tf/N + self.__print_level = 0 # print level + self.__initialize_t_slacks = 0 # possible values: 0, 1 + self.__regularize_method = None + self.__time_steps = None + self.__shooting_nodes = None + self.__exact_hess_cost = 1 + self.__exact_hess_dyn = 1 + self.__exact_hess_constr = 1 + self.__ext_cost_num_hess = 0 + self.__alpha_min = 0.05 + self.__alpha_reduction = 0.7 + self.__line_search_use_sufficient_descent = 0 + self.__globalization_use_SOC = 0 + self.__full_step_dual = 0 + self.__eps_sufficient_descent = 1e-4 + self.__hpipm_mode = 'BALANCE' + # TODO: move those out? they are more about generation than about the acados OCP solver. + self.__ext_fun_compile_flags = '-O2' + self.__model_external_shared_lib_dir = None # path to the the .so lib + self.__model_external_shared_lib_name = None # name of the the .so lib + self.__custom_update_filename = '' + self.__custom_update_header_filename = '' + self.__custom_templates = [] + self.__custom_update_copy = True + + @property + def qp_solver(self): + """QP solver to be used in the NLP solver. + String in ('PARTIAL_CONDENSING_HPIPM', 'FULL_CONDENSING_QPOASES', 'FULL_CONDENSING_HPIPM', 'PARTIAL_CONDENSING_QPDUNES', 'PARTIAL_CONDENSING_OSQP', 'FULL_CONDENSING_DAQP'). + Default: 'PARTIAL_CONDENSING_HPIPM'. + """ + return self.__qp_solver + + @property + def ext_fun_compile_flags(self): + """ + String with compiler flags for external function compilation. + Default: '-O2'. + """ + return self.__ext_fun_compile_flags + + + @property + def custom_update_filename(self): + """ + Filename of the custom C function to update solver data and parameters in between solver calls + + This file has to implement the functions + int custom_update_init_function([model.name]_solver_capsule* capsule); + int custom_update_function([model.name]_solver_capsule* capsule); + int custom_update_terminate_function([model.name]_solver_capsule* capsule); + + + Default: ''. + """ + return self.__custom_update_filename + + + @property + def custom_templates(self): + """ + List of tuples of the form: + (input_filename, output_filename) + + Custom templates are render in OCP solver generation. + + Default: []. + """ + return self.__custom_templates + + + @property + def custom_update_header_filename(self): + """ + Header filename of the custom C function to update solver data and parameters in between solver calls + + This file has to declare the custom_update functions and look as follows: + + ``` + // Called at the end of solver creation. + // This is allowed to allocate memory and store the pointer to it into capsule->custom_update_memory. + int custom_update_init_function([model.name]_solver_capsule* capsule); + + // Custom update function that can be called between solver calls + int custom_update_function([model.name]_solver_capsule* capsule, double* data, int data_len); + + // Called just before destroying the solver. + // Responsible to free allocated memory, stored at capsule->custom_update_memory. + int custom_update_terminate_function([model.name]_solver_capsule* capsule); + + Default: ''. + """ + return self.__custom_update_header_filename + + @property + def custom_update_copy(self): + """ + Boolean; + If True, the custom update function files are copied into the `code_export_directory`. + """ + return self.__custom_update_copy + + + @property + def hpipm_mode(self): + """ + Mode of HPIPM to be used, + + String in ('BALANCE', 'SPEED_ABS', 'SPEED', 'ROBUST'). + + Default: 'BALANCE'. + + see https://cdn.syscop.de/publications/Frison2020a.pdf + and the HPIPM code: + https://github.com/giaf/hpipm/blob/master/ocp_qp/x_ocp_qp_ipm.c#L69 + """ + return self.__hpipm_mode + + @property + def hessian_approx(self): + """Hessian approximation. + String in ('GAUSS_NEWTON', 'EXACT'). + Default: 'GAUSS_NEWTON'. + """ + return self.__hessian_approx + + @property + def integrator_type(self): + """ + Integrator type. + String in ('ERK', 'IRK', 'GNSF', 'DISCRETE', 'LIFTED_IRK'). + Default: 'ERK'. + """ + return self.__integrator_type + + @property + def nlp_solver_type(self): + """NLP solver. + String in ('SQP', 'SQP_RTI'). + Default: 'SQP_RTI'. + """ + return self.__nlp_solver_type + + @property + def globalization(self): + """Globalization type. + String in ('FIXED_STEP', 'MERIT_BACKTRACKING'). + Default: 'FIXED_STEP'. + + .. note:: preliminary implementation. + """ + return self.__globalization + + @property + def collocation_type(self): + """Collocation type: relevant for implicit integrators + -- string in {GAUSS_RADAU_IIA, GAUSS_LEGENDRE}. + + Default: GAUSS_LEGENDRE + """ + return self.__collocation_type + + @property + def regularize_method(self): + """Regularization method for the Hessian. + String in ('NO_REGULARIZE', 'MIRROR', 'PROJECT', 'PROJECT_REDUC_HESS', 'CONVEXIFY') or :code:`None`. + + - MIRROR: performs eigenvalue decomposition H = V^T D V and sets D_ii = max(eps, abs(D_ii)) + - PROJECT: performs eigenvalue decomposition H = V^T D V and sets D_ii = max(eps, D_ii) + - CONVEXIFY: Algorithm 6 from Verschueren2017, https://cdn.syscop.de/publications/Verschueren2017.pdf + - PROJECT_REDUC_HESS: experimental + + Note: default eps = 1e-4 + + Default: :code:`None`. + """ + return self.__regularize_method + + @property + def nlp_solver_step_length(self): + """ + Fixed Newton step length. + Type: float > 0. + Default: 1.0. + """ + return self.__nlp_solver_step_length + + @property + def levenberg_marquardt(self): + """ + Factor for LM regularization. + Type: float >= 0 + Default: 0.0. + """ + return self.__levenberg_marquardt + + @property + def sim_method_num_stages(self): + """ + Number of stages in the integrator. + Type: int > 0 or ndarray of ints > 0 of shape (N,). + Default: 4 + """ + return self.__sim_method_num_stages + + @property + def sim_method_num_steps(self): + """ + Number of steps in the integrator. + Type: int > 0 or ndarray of ints > 0 of shape (N,). + Default: 1 + """ + return self.__sim_method_num_steps + + @property + def sim_method_newton_iter(self): + """ + Number of Newton iterations in simulation method. + Type: int > 0 + Default: 3 + """ + return self.__sim_method_newton_iter + + @property + def sim_method_newton_tol(self): + """ + Tolerance of Newton system in simulation method. + Type: float: 0.0 means not used + Default: 0.0 + """ + return self.__sim_method_newton_tol + + @property + def sim_method_jac_reuse(self): + """ + Integer determining if jacobians are reused within integrator or ndarray of ints > 0 of shape (N,). + 0: False (no reuse); 1: True (reuse) + Default: 0 + """ + return self.__sim_method_jac_reuse + + @property + def qp_solver_tol_stat(self): + """ + QP solver stationarity tolerance. + Default: :code:`None` + """ + return self.__qp_solver_tol_stat + + @property + def qp_solver_tol_eq(self): + """ + QP solver equality tolerance. + Default: :code:`None` + """ + return self.__qp_solver_tol_eq + + @property + def qp_solver_tol_ineq(self): + """ + QP solver inequality. + Default: :code:`None` + """ + return self.__qp_solver_tol_ineq + + @property + def qp_solver_tol_comp(self): + """ + QP solver complementarity. + Default: :code:`None` + """ + return self.__qp_solver_tol_comp + + @property + def qp_solver_cond_N(self): + """QP solver: New horizon after partial condensing. + Set to N by default -> no condensing.""" + return self.__qp_solver_cond_N + + @property + def qp_solver_warm_start(self): + """ + QP solver: Warm starting. + 0: no warm start; 1: warm start; 2: hot start. + Default: 0 + """ + return self.__qp_solver_warm_start + + @property + def qp_solver_cond_ric_alg(self): + """ + QP solver: Determines which algorithm is used in HPIPM condensing. + 0: dont factorize hessian in the condensing; 1: factorize. + Default: 1 + """ + return self.__qp_solver_cond_ric_alg + + @property + def qp_solver_ric_alg(self): + """ + QP solver: Determines which algorithm is used in HPIPM OCP QP solver. + 0 classical Riccati, 1 square-root Riccati. + + Note: taken from [HPIPM paper]: + + (a) the classical implementation requires the reduced Hessian with respect to the dynamics + equality constraints to be positive definite, but allows the full-space Hessian to be indefinite) + (b) the square-root implementation, which in order to reduce the flop count employs the Cholesky + factorization of the Riccati recursion matrix, and therefore requires the full-space Hessian to be positive definite + + [HPIPM paper]: HPIPM: a high-performance quadratic programming framework for model predictive control, Frison and Diehl, 2020 + https://cdn.syscop.de/publications/Frison2020a.pdf + + Default: 1 + """ + return self.__qp_solver_ric_alg + + @property + def qp_solver_iter_max(self): + """ + QP solver: maximum number of iterations. + Type: int > 0 + Default: 50 + """ + return self.__qp_solver_iter_max + + @property + def tol(self): + """ + NLP solver tolerance. Sets or gets the max of :py:attr:`nlp_solver_tol_eq`, + :py:attr:`nlp_solver_tol_ineq`, :py:attr:`nlp_solver_tol_comp` + and :py:attr:`nlp_solver_tol_stat`. + """ + return max([self.__nlp_solver_tol_eq, self.__nlp_solver_tol_ineq,\ + self.__nlp_solver_tol_comp, self.__nlp_solver_tol_stat]) + + @property + def qp_tol(self): + """ + QP solver tolerance. + Sets all of the following at once or gets the max of + :py:attr:`qp_solver_tol_eq`, :py:attr:`qp_solver_tol_ineq`, + :py:attr:`qp_solver_tol_comp` and + :py:attr:`qp_solver_tol_stat`. + """ + return max([self.__qp_solver_tol_eq, self.__qp_solver_tol_ineq,\ + self.__qp_solver_tol_comp, self.__qp_solver_tol_stat]) + + @property + def nlp_solver_tol_stat(self): + """ + NLP solver stationarity tolerance. + Type: float > 0 + Default: 1e-6 + """ + return self.__nlp_solver_tol_stat + + @property + def nlp_solver_tol_eq(self): + """NLP solver equality tolerance""" + return self.__nlp_solver_tol_eq + + @property + def alpha_min(self): + """Minimal step size for globalization MERIT_BACKTRACKING, default: 0.05.""" + return self.__alpha_min + + @property + def alpha_reduction(self): + """Step size reduction factor for globalization MERIT_BACKTRACKING, default: 0.7.""" + return self.__alpha_reduction + + @property + def line_search_use_sufficient_descent(self): + """ + Determines if sufficient descent (Armijo) condition is used in line search. + Type: int; 0 or 1; + default: 0. + """ + return self.__line_search_use_sufficient_descent + + @property + def eps_sufficient_descent(self): + """ + Factor for sufficient descent (Armijo) conditon, see line_search_use_sufficient_descent. + Type: float, + default: 1e-4. + """ + return self.__eps_sufficient_descent + + @property + def globalization_use_SOC(self): + """ + Determines if second order correction (SOC) is done when using MERIT_BACKTRACKING. + SOC is done if preliminary line search does not return full step. + Type: int; 0 or 1; + default: 0. + """ + return self.__globalization_use_SOC + + @property + def full_step_dual(self): + """ + Determines if dual variables are updated with full steps (alpha=1.0) when primal variables are updated with smaller step. + Type: int; 0 or 1; + default: 0. + """ + return self.__full_step_dual + + @property + def nlp_solver_tol_ineq(self): + """NLP solver inequality tolerance""" + return self.__nlp_solver_tol_ineq + + @property + def nlp_solver_ext_qp_res(self): + """Determines if residuals of QP are computed externally within NLP solver (for debugging) + + Type: int; 0 or 1; + Default: 0. + """ + return self.__nlp_solver_ext_qp_res + + @property + def nlp_solver_tol_comp(self): + """NLP solver complementarity tolerance""" + return self.__nlp_solver_tol_comp + + @property + def nlp_solver_max_iter(self): + """ + NLP solver maximum number of iterations. + Type: int > 0 + Default: 100 + """ + return self.__nlp_solver_max_iter + + @property + def time_steps(self): + """ + Vector with time steps between the shooting nodes. Set automatically to uniform discretization if :py:attr:`N` and :py:attr:`tf` are provided. + Default: :code:`None` + """ + return self.__time_steps + + @property + def shooting_nodes(self): + """ + Vector with the shooting nodes, time_steps will be computed from it automatically. + Default: :code:`None` + """ + return self.__shooting_nodes + + @property + def tf(self): + """ + Prediction horizon + Type: float > 0 + Default: :code:`None` + """ + return self.__tf + + @property + def Tsim(self): + """ + Time horizon for one integrator step. Automatically calculated as :py:attr:`tf`/:py:attr:`N`. + Default: :code:`None` + """ + return self.__Tsim + + @property + def print_level(self): + """ + Verbosity of printing. + Type: int >= 0 + Default: 0 + """ + return self.__print_level + + @property + def model_external_shared_lib_dir(self): + """Path to the .so lib""" + return self.__model_external_shared_lib_dir + + @property + def model_external_shared_lib_name(self): + """Name of the .so lib""" + return self.__model_external_shared_lib_name + + @property + def exact_hess_constr(self): + """ + Used in case of hessian_approx == 'EXACT'.\n + Can be used to turn off exact hessian contributions from the constraints module. + """ + return self.__exact_hess_constr + + @property + def exact_hess_cost(self): + """ + Used in case of hessian_approx == 'EXACT'.\n + Can be used to turn off exact hessian contributions from the cost module. + """ + return self.__exact_hess_cost + + @property + def exact_hess_dyn(self): + """ + Used in case of hessian_approx == 'EXACT'.\n + Can be used to turn off exact hessian contributions from the dynamics module. + """ + return self.__exact_hess_dyn + + @property + def ext_cost_num_hess(self): + """ + Determines if custom hessian approximation for cost contribution is used (> 0).\n + Or if hessian contribution is evaluated exactly using CasADi external function (=0 - default). + """ + return self.__ext_cost_num_hess + + @qp_solver.setter + def qp_solver(self, qp_solver): + qp_solvers = ('PARTIAL_CONDENSING_HPIPM', \ + 'FULL_CONDENSING_QPOASES', 'FULL_CONDENSING_HPIPM', \ + 'PARTIAL_CONDENSING_QPDUNES', 'PARTIAL_CONDENSING_OSQP', \ + 'FULL_CONDENSING_DAQP') + if qp_solver in qp_solvers: + self.__qp_solver = qp_solver + else: + raise Exception('Invalid qp_solver value. Possible values are:\n\n' \ + + ',\n'.join(qp_solvers) + '.\n\nYou have: ' + qp_solver + '.\n\n') + + @regularize_method.setter + def regularize_method(self, regularize_method): + regularize_methods = ('NO_REGULARIZE', 'MIRROR', 'PROJECT', \ + 'PROJECT_REDUC_HESS', 'CONVEXIFY') + if regularize_method in regularize_methods: + self.__regularize_method = regularize_method + else: + raise Exception('Invalid regularize_method value. Possible values are:\n\n' \ + + ',\n'.join(regularize_methods) + '.\n\nYou have: ' + regularize_method + '.\n\n') + + @collocation_type.setter + def collocation_type(self, collocation_type): + collocation_types = ('GAUSS_RADAU_IIA', 'GAUSS_LEGENDRE') + if collocation_type in collocation_types: + self.__collocation_type = collocation_type + else: + raise Exception('Invalid collocation_type value. Possible values are:\n\n' \ + + ',\n'.join(collocation_types) + '.\n\nYou have: ' + collocation_type + '.\n\n') + + @hpipm_mode.setter + def hpipm_mode(self, hpipm_mode): + hpipm_modes = ('BALANCE', 'SPEED_ABS', 'SPEED', 'ROBUST') + if hpipm_mode in hpipm_modes: + self.__hpipm_mode = hpipm_mode + else: + raise Exception('Invalid hpipm_mode value. Possible values are:\n\n' \ + + ',\n'.join(hpipm_modes) + '.\n\nYou have: ' + hpipm_mode + '.\n\n') + + @ext_fun_compile_flags.setter + def ext_fun_compile_flags(self, ext_fun_compile_flags): + if isinstance(ext_fun_compile_flags, str): + self.__ext_fun_compile_flags = ext_fun_compile_flags + else: + raise Exception('Invalid ext_fun_compile_flags, expected a string.\n') + + + @custom_update_filename.setter + def custom_update_filename(self, custom_update_filename): + if isinstance(custom_update_filename, str): + self.__custom_update_filename = custom_update_filename + else: + raise Exception('Invalid custom_update_filename, expected a string.\n') + + @custom_templates.setter + def custom_templates(self, custom_templates): + if not isinstance(custom_templates, list): + raise Exception('Invalid custom_templates, expected a list.\n') + for tup in custom_templates: + if not isinstance(tup, tuple): + raise Exception('Invalid custom_templates, shoubld be list of tuples.\n') + for s in tup: + if not isinstance(s, str): + raise Exception('Invalid custom_templates, shoubld be list of tuples of strings.\n') + self.__custom_templates = custom_templates + + @custom_update_header_filename.setter + def custom_update_header_filename(self, custom_update_header_filename): + if isinstance(custom_update_header_filename, str): + self.__custom_update_header_filename = custom_update_header_filename + else: + raise Exception('Invalid custom_update_header_filename, expected a string.\n') + + @custom_update_copy.setter + def custom_update_copy(self, custom_update_copy): + if isinstance(custom_update_copy, bool): + self.__custom_update_copy = custom_update_copy + else: + raise Exception('Invalid custom_update_copy, expected a bool.\n') + + @hessian_approx.setter + def hessian_approx(self, hessian_approx): + hessian_approxs = ('GAUSS_NEWTON', 'EXACT') + if hessian_approx in hessian_approxs: + self.__hessian_approx = hessian_approx + else: + raise Exception('Invalid hessian_approx value. Possible values are:\n\n' \ + + ',\n'.join(hessian_approxs) + '.\n\nYou have: ' + hessian_approx + '.\n\n') + + @integrator_type.setter + def integrator_type(self, integrator_type): + integrator_types = ('ERK', 'IRK', 'GNSF', 'DISCRETE', 'LIFTED_IRK') + if integrator_type in integrator_types: + self.__integrator_type = integrator_type + else: + raise Exception('Invalid integrator_type value. Possible values are:\n\n' \ + + ',\n'.join(integrator_types) + '.\n\nYou have: ' + integrator_type + '.\n\n') + + @tf.setter + def tf(self, tf): + self.__tf = tf + + @time_steps.setter + def time_steps(self, time_steps): + if isinstance(time_steps, np.ndarray): + if len(time_steps.shape) == 1: + self.__time_steps = time_steps + else: + raise Exception('Invalid time_steps, expected np.ndarray of shape (N,).') + else: + raise Exception('Invalid time_steps, expected np.ndarray.') + + @shooting_nodes.setter + def shooting_nodes(self, shooting_nodes): + if isinstance(shooting_nodes, np.ndarray): + if len(shooting_nodes.shape) == 1: + self.__shooting_nodes = shooting_nodes + else: + raise Exception('Invalid shooting_nodes, expected np.ndarray of shape (N+1,).') + else: + raise Exception('Invalid shooting_nodes, expected np.ndarray.') + + @Tsim.setter + def Tsim(self, Tsim): + self.__Tsim = Tsim + + @globalization.setter + def globalization(self, globalization): + globalization_types = ('MERIT_BACKTRACKING', 'FIXED_STEP') + if globalization in globalization_types: + self.__globalization = globalization + else: + raise Exception('Invalid globalization value. Possible values are:\n\n' \ + + ',\n'.join(globalization_types) + '.\n\nYou have: ' + globalization + '.\n\n') + + @alpha_min.setter + def alpha_min(self, alpha_min): + self.__alpha_min = alpha_min + + @alpha_reduction.setter + def alpha_reduction(self, alpha_reduction): + self.__alpha_reduction = alpha_reduction + + @line_search_use_sufficient_descent.setter + def line_search_use_sufficient_descent(self, line_search_use_sufficient_descent): + if line_search_use_sufficient_descent in [0, 1]: + self.__line_search_use_sufficient_descent = line_search_use_sufficient_descent + else: + raise Exception(f'Invalid value for line_search_use_sufficient_descent. Possible values are 0, 1, got {line_search_use_sufficient_descent}') + + @globalization_use_SOC.setter + def globalization_use_SOC(self, globalization_use_SOC): + if globalization_use_SOC in [0, 1]: + self.__globalization_use_SOC = globalization_use_SOC + else: + raise Exception(f'Invalid value for globalization_use_SOC. Possible values are 0, 1, got {globalization_use_SOC}') + + @full_step_dual.setter + def full_step_dual(self, full_step_dual): + if full_step_dual in [0, 1]: + self.__full_step_dual = full_step_dual + else: + raise Exception(f'Invalid value for full_step_dual. Possible values are 0, 1, got {full_step_dual}') + + @eps_sufficient_descent.setter + def eps_sufficient_descent(self, eps_sufficient_descent): + if isinstance(eps_sufficient_descent, float) and eps_sufficient_descent > 0: + self.__eps_sufficient_descent = eps_sufficient_descent + else: + raise Exception('Invalid eps_sufficient_descent value. eps_sufficient_descent must be a positive float.') + + @sim_method_num_stages.setter + def sim_method_num_stages(self, sim_method_num_stages): + + # if isinstance(sim_method_num_stages, int): + # self.__sim_method_num_stages = sim_method_num_stages + # else: + # raise Exception('Invalid sim_method_num_stages value. sim_method_num_stages must be an integer.') + + self.__sim_method_num_stages = sim_method_num_stages + + @sim_method_num_steps.setter + def sim_method_num_steps(self, sim_method_num_steps): + + # if isinstance(sim_method_num_steps, int): + # self.__sim_method_num_steps = sim_method_num_steps + # else: + # raise Exception('Invalid sim_method_num_steps value. sim_method_num_steps must be an integer.') + self.__sim_method_num_steps = sim_method_num_steps + + + @sim_method_newton_iter.setter + def sim_method_newton_iter(self, sim_method_newton_iter): + + if isinstance(sim_method_newton_iter, int): + self.__sim_method_newton_iter = sim_method_newton_iter + else: + raise Exception('Invalid sim_method_newton_iter value. sim_method_newton_iter must be an integer.') + + @sim_method_jac_reuse.setter + def sim_method_jac_reuse(self, sim_method_jac_reuse): + # if sim_method_jac_reuse in (True, False): + self.__sim_method_jac_reuse = sim_method_jac_reuse + # else: + # raise Exception('Invalid sim_method_jac_reuse value. sim_method_jac_reuse must be a Boolean.') + + @nlp_solver_type.setter + def nlp_solver_type(self, nlp_solver_type): + nlp_solver_types = ('SQP', 'SQP_RTI') + if nlp_solver_type in nlp_solver_types: + self.__nlp_solver_type = nlp_solver_type + else: + raise Exception('Invalid nlp_solver_type value. Possible values are:\n\n' \ + + ',\n'.join(nlp_solver_types) + '.\n\nYou have: ' + nlp_solver_type + '.\n\n') + + @nlp_solver_step_length.setter + def nlp_solver_step_length(self, nlp_solver_step_length): + if isinstance(nlp_solver_step_length, float) and nlp_solver_step_length > 0: + self.__nlp_solver_step_length = nlp_solver_step_length + else: + raise Exception('Invalid nlp_solver_step_length value. nlp_solver_step_length must be a positive float.') + + @levenberg_marquardt.setter + def levenberg_marquardt(self, levenberg_marquardt): + if isinstance(levenberg_marquardt, float) and levenberg_marquardt >= 0: + self.__levenberg_marquardt = levenberg_marquardt + else: + raise Exception('Invalid levenberg_marquardt value. levenberg_marquardt must be a positive float.') + + @qp_solver_iter_max.setter + def qp_solver_iter_max(self, qp_solver_iter_max): + if isinstance(qp_solver_iter_max, int) and qp_solver_iter_max > 0: + self.__qp_solver_iter_max = qp_solver_iter_max + else: + raise Exception('Invalid qp_solver_iter_max value. qp_solver_iter_max must be a positive int.') + + @qp_solver_ric_alg.setter + def qp_solver_ric_alg(self, qp_solver_ric_alg): + if qp_solver_ric_alg in [0, 1]: + self.__qp_solver_ric_alg = qp_solver_ric_alg + else: + raise Exception(f'Invalid qp_solver_ric_alg value. qp_solver_ric_alg must be in [0, 1], got {qp_solver_ric_alg}.') + + @qp_solver_cond_ric_alg.setter + def qp_solver_cond_ric_alg(self, qp_solver_cond_ric_alg): + if qp_solver_cond_ric_alg in [0, 1]: + self.__qp_solver_cond_ric_alg = qp_solver_cond_ric_alg + else: + raise Exception(f'Invalid qp_solver_cond_ric_alg value. qp_solver_cond_ric_alg must be in [0, 1], got {qp_solver_cond_ric_alg}.') + + + @qp_solver_cond_N.setter + def qp_solver_cond_N(self, qp_solver_cond_N): + if isinstance(qp_solver_cond_N, int) and qp_solver_cond_N >= 0: + self.__qp_solver_cond_N = qp_solver_cond_N + else: + raise Exception('Invalid qp_solver_cond_N value. qp_solver_cond_N must be a positive int.') + + @qp_solver_warm_start.setter + def qp_solver_warm_start(self, qp_solver_warm_start): + if qp_solver_warm_start in [0, 1, 2]: + self.__qp_solver_warm_start = qp_solver_warm_start + else: + raise Exception('Invalid qp_solver_warm_start value. qp_solver_warm_start must be 0 or 1 or 2.') + + @qp_tol.setter + def qp_tol(self, qp_tol): + if isinstance(qp_tol, float) and qp_tol > 0: + self.__qp_solver_tol_eq = qp_tol + self.__qp_solver_tol_ineq = qp_tol + self.__qp_solver_tol_stat = qp_tol + self.__qp_solver_tol_comp = qp_tol + else: + raise Exception('Invalid qp_tol value. qp_tol must be a positive float.') + + @qp_solver_tol_stat.setter + def qp_solver_tol_stat(self, qp_solver_tol_stat): + if isinstance(qp_solver_tol_stat, float) and qp_solver_tol_stat > 0: + self.__qp_solver_tol_stat = qp_solver_tol_stat + else: + raise Exception('Invalid qp_solver_tol_stat value. qp_solver_tol_stat must be a positive float.') + + @qp_solver_tol_eq.setter + def qp_solver_tol_eq(self, qp_solver_tol_eq): + if isinstance(qp_solver_tol_eq, float) and qp_solver_tol_eq > 0: + self.__qp_solver_tol_eq = qp_solver_tol_eq + else: + raise Exception('Invalid qp_solver_tol_eq value. qp_solver_tol_eq must be a positive float.') + + @qp_solver_tol_ineq.setter + def qp_solver_tol_ineq(self, qp_solver_tol_ineq): + if isinstance(qp_solver_tol_ineq, float) and qp_solver_tol_ineq > 0: + self.__qp_solver_tol_ineq = qp_solver_tol_ineq + else: + raise Exception('Invalid qp_solver_tol_ineq value. qp_solver_tol_ineq must be a positive float.') + + @qp_solver_tol_comp.setter + def qp_solver_tol_comp(self, qp_solver_tol_comp): + if isinstance(qp_solver_tol_comp, float) and qp_solver_tol_comp > 0: + self.__qp_solver_tol_comp = qp_solver_tol_comp + else: + raise Exception('Invalid qp_solver_tol_comp value. qp_solver_tol_comp must be a positive float.') + + @tol.setter + def tol(self, tol): + if isinstance(tol, float) and tol > 0: + self.__nlp_solver_tol_eq = tol + self.__nlp_solver_tol_ineq = tol + self.__nlp_solver_tol_stat = tol + self.__nlp_solver_tol_comp = tol + else: + raise Exception('Invalid tol value. tol must be a positive float.') + + @nlp_solver_tol_stat.setter + def nlp_solver_tol_stat(self, nlp_solver_tol_stat): + if isinstance(nlp_solver_tol_stat, float) and nlp_solver_tol_stat > 0: + self.__nlp_solver_tol_stat = nlp_solver_tol_stat + else: + raise Exception('Invalid nlp_solver_tol_stat value. nlp_solver_tol_stat must be a positive float.') + + @nlp_solver_tol_eq.setter + def nlp_solver_tol_eq(self, nlp_solver_tol_eq): + if isinstance(nlp_solver_tol_eq, float) and nlp_solver_tol_eq > 0: + self.__nlp_solver_tol_eq = nlp_solver_tol_eq + else: + raise Exception('Invalid nlp_solver_tol_eq value. nlp_solver_tol_eq must be a positive float.') + + @nlp_solver_tol_ineq.setter + def nlp_solver_tol_ineq(self, nlp_solver_tol_ineq): + if isinstance(nlp_solver_tol_ineq, float) and nlp_solver_tol_ineq > 0: + self.__nlp_solver_tol_ineq = nlp_solver_tol_ineq + else: + raise Exception('Invalid nlp_solver_tol_ineq value. nlp_solver_tol_ineq must be a positive float.') + + @nlp_solver_ext_qp_res.setter + def nlp_solver_ext_qp_res(self, nlp_solver_ext_qp_res): + if nlp_solver_ext_qp_res in [0, 1]: + self.__nlp_solver_ext_qp_res = nlp_solver_ext_qp_res + else: + raise Exception('Invalid nlp_solver_ext_qp_res value. nlp_solver_ext_qp_res must be in [0, 1].') + + @nlp_solver_tol_comp.setter + def nlp_solver_tol_comp(self, nlp_solver_tol_comp): + if isinstance(nlp_solver_tol_comp, float) and nlp_solver_tol_comp > 0: + self.__nlp_solver_tol_comp = nlp_solver_tol_comp + else: + raise Exception('Invalid nlp_solver_tol_comp value. nlp_solver_tol_comp must be a positive float.') + + @nlp_solver_max_iter.setter + def nlp_solver_max_iter(self, nlp_solver_max_iter): + + if isinstance(nlp_solver_max_iter, int) and nlp_solver_max_iter > 0: + self.__nlp_solver_max_iter = nlp_solver_max_iter + else: + raise Exception('Invalid nlp_solver_max_iter value. nlp_solver_max_iter must be a positive int.') + + @print_level.setter + def print_level(self, print_level): + if isinstance(print_level, int) and print_level >= 0: + self.__print_level = print_level + else: + raise Exception('Invalid print_level value. print_level takes one of the values >=0.') + + @model_external_shared_lib_dir.setter + def model_external_shared_lib_dir(self, model_external_shared_lib_dir): + if isinstance(model_external_shared_lib_dir, str) : + self.__model_external_shared_lib_dir = model_external_shared_lib_dir + else: + raise Exception('Invalid model_external_shared_lib_dir value. Str expected.' \ + + '.\n\nYou have: ' + type(model_external_shared_lib_dir) + '.\n\n') + + @model_external_shared_lib_name.setter + def model_external_shared_lib_name(self, model_external_shared_lib_name): + if isinstance(model_external_shared_lib_name, str) : + if model_external_shared_lib_name[-3:] == '.so' : + raise Exception('Invalid model_external_shared_lib_name value. Remove the .so extension.' \ + + '.\n\nYou have: ' + type(model_external_shared_lib_name) + '.\n\n') + else : + self.__model_external_shared_lib_name = model_external_shared_lib_name + else: + raise Exception('Invalid model_external_shared_lib_name value. Str expected.' \ + + '.\n\nYou have: ' + type(model_external_shared_lib_name) + '.\n\n') + + @exact_hess_constr.setter + def exact_hess_constr(self, exact_hess_constr): + if exact_hess_constr in [0, 1]: + self.__exact_hess_constr = exact_hess_constr + else: + raise Exception('Invalid exact_hess_constr value. exact_hess_constr takes one of the values 0, 1.') + + @exact_hess_cost.setter + def exact_hess_cost(self, exact_hess_cost): + if exact_hess_cost in [0, 1]: + self.__exact_hess_cost = exact_hess_cost + else: + raise Exception('Invalid exact_hess_cost value. exact_hess_cost takes one of the values 0, 1.') + + @exact_hess_dyn.setter + def exact_hess_dyn(self, exact_hess_dyn): + if exact_hess_dyn in [0, 1]: + self.__exact_hess_dyn = exact_hess_dyn + else: + raise Exception('Invalid exact_hess_dyn value. exact_hess_dyn takes one of the values 0, 1.') + + @ext_cost_num_hess.setter + def ext_cost_num_hess(self, ext_cost_num_hess): + if ext_cost_num_hess in [0, 1]: + self.__ext_cost_num_hess = ext_cost_num_hess + else: + raise Exception('Invalid ext_cost_num_hess value. ext_cost_num_hess takes one of the values 0, 1.') + + def set(self, attr, value): + setattr(self, attr, value) + + +class AcadosOcp: + """ + Class containing the full description of the optimal control problem. + This object can be used to create an :py:class:`acados_template.acados_ocp_solver.AcadosOcpSolver`. + + The class has the following properties that can be modified to formulate a specific OCP, see below: + + - :py:attr:`dims` of type :py:class:`acados_template.acados_ocp.AcadosOcpDims` + - :py:attr:`model` of type :py:class:`acados_template.acados_model.AcadosModel` + - :py:attr:`cost` of type :py:class:`acados_template.acados_ocp.AcadosOcpCost` + - :py:attr:`constraints` of type :py:class:`acados_template.acados_ocp.AcadosOcpConstraints` + - :py:attr:`solver_options` of type :py:class:`acados_template.acados_ocp.AcadosOcpOptions` + + - :py:attr:`acados_include_path` (set automatically) + - :py:attr:`shared_lib_ext` (set automatically) + - :py:attr:`acados_lib_path` (set automatically) + - :py:attr:`parameter_values` - used to initialize the parameters (can be changed) + """ + def __init__(self, acados_path=''): + """ + Keyword arguments: + acados_path -- path of your acados installation + """ + if acados_path == '': + acados_path = get_acados_path() + + self.dims = AcadosOcpDims() + """Dimension definitions, type :py:class:`acados_template.acados_ocp.AcadosOcpDims`""" + self.model = AcadosModel() + """Model definitions, type :py:class:`acados_template.acados_model.AcadosModel`""" + self.cost = AcadosOcpCost() + """Cost definitions, type :py:class:`acados_template.acados_ocp.AcadosOcpCost`""" + self.constraints = AcadosOcpConstraints() + """Constraints definitions, type :py:class:`acados_template.acados_ocp.AcadosOcpConstraints`""" + self.solver_options = AcadosOcpOptions() + """Solver Options, type :py:class:`acados_template.acados_ocp.AcadosOcpOptions`""" + + self.acados_include_path = os.path.join(acados_path, 'include').replace(os.sep, '/') # the replace part is important on Windows for CMake + """Path to acados include directory (set automatically), type: `string`""" + self.acados_lib_path = os.path.join(acados_path, 'lib').replace(os.sep, '/') # the replace part is important on Windows for CMake + """Path to where acados library is located, type: `string`""" + self.shared_lib_ext = get_lib_ext() + + # get cython paths + from sysconfig import get_paths + self.cython_include_dirs = [np.get_include(), get_paths()['include']] + + self.__parameter_values = np.array([]) + self.__problem_class = 'OCP' + + self.code_export_directory = 'c_generated_code' + """Path to where code will be exported. Default: `c_generated_code`.""" + + @property + def parameter_values(self): + """:math:`p` - initial values for parameter - can be updated stagewise""" + return self.__parameter_values + + @parameter_values.setter + def parameter_values(self, parameter_values): + if isinstance(parameter_values, np.ndarray): + self.__parameter_values = parameter_values + else: + raise Exception('Invalid parameter_values value. ' + + f'Expected numpy array, got {type(parameter_values)}.') + + def set(self, attr, value): + # tokenize string + tokens = attr.split('_', 1) + if len(tokens) > 1: + setter_to_call = getattr(getattr(self, tokens[0]), 'set') + else: + setter_to_call = getattr(self, 'set') + + setter_to_call(tokens[1], value) + + return diff --git a/third_party/acados/acados_template/acados_ocp_solver.py b/third_party/acados/acados_template/acados_ocp_solver.py new file mode 100644 index 0000000000..ffc9cf4b0e --- /dev/null +++ b/third_party/acados/acados_template/acados_ocp_solver.py @@ -0,0 +1,1991 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import sys +import os +import json +import numpy as np +from datetime import datetime +import importlib +import shutil + +from subprocess import DEVNULL, call, STDOUT + +from ctypes import POINTER, cast, CDLL, c_void_p, c_char_p, c_double, c_int, c_int64, byref + +from copy import deepcopy +from pathlib import Path + +from .casadi_function_generation import generate_c_code_explicit_ode, \ + generate_c_code_implicit_ode, generate_c_code_gnsf, generate_c_code_discrete_dynamics, \ + generate_c_code_constraint, generate_c_code_nls_cost, generate_c_code_conl_cost, \ + generate_c_code_external_cost +from .gnsf.detect_gnsf_structure import detect_gnsf_structure +from .acados_ocp import AcadosOcp +from .acados_model import AcadosModel +from .utils import is_column, is_empty, casadi_length, render_template,\ + format_class_dict, make_object_json_dumpable, make_model_consistent,\ + set_up_imported_gnsf_model, get_ocp_nlp_layout, get_python_interface_path, get_lib_ext, check_casadi_version +from .builders import CMakeBuilder + + +def make_ocp_dims_consistent(acados_ocp: AcadosOcp): + dims = acados_ocp.dims + cost = acados_ocp.cost + constraints = acados_ocp.constraints + model = acados_ocp.model + opts = acados_ocp.solver_options + + # nx + if is_column(model.x): + dims.nx = casadi_length(model.x) + else: + raise Exception('model.x should be column vector!') + + # nu + if is_empty(model.u): + dims.nu = 0 + else: + dims.nu = casadi_length(model.u) + + # nz + if is_empty(model.z): + dims.nz = 0 + else: + dims.nz = casadi_length(model.z) + + # np + if is_empty(model.p): + dims.np = 0 + else: + dims.np = casadi_length(model.p) + if acados_ocp.parameter_values.shape[0] != dims.np: + raise Exception('inconsistent dimension np, regarding model.p and parameter_values.' + \ + f'\nGot np = {dims.np}, acados_ocp.parameter_values.shape = {acados_ocp.parameter_values.shape[0]}\n') + + ## cost + # initial stage - if not set, copy fields from path constraints + if cost.cost_type_0 is None: + cost.cost_type_0 = cost.cost_type + cost.W_0 = cost.W + cost.Vx_0 = cost.Vx + cost.Vu_0 = cost.Vu + cost.Vz_0 = cost.Vz + cost.yref_0 = cost.yref + cost.cost_ext_fun_type_0 = cost.cost_ext_fun_type + model.cost_y_expr_0 = model.cost_y_expr + model.cost_expr_ext_cost_0 = model.cost_expr_ext_cost + model.cost_expr_ext_cost_custom_hess_0 = model.cost_expr_ext_cost_custom_hess + + model.cost_psi_expr_0 = model.cost_psi_expr + model.cost_r_in_psi_expr_0 = model.cost_r_in_psi_expr + + if cost.cost_type_0 == 'LINEAR_LS': + ny_0 = cost.W_0.shape[0] + if cost.Vx_0.shape[0] != ny_0 or cost.Vu_0.shape[0] != ny_0: + raise Exception('inconsistent dimension ny_0, regarding W_0, Vx_0, Vu_0.' + \ + f'\nGot W_0[{cost.W_0.shape}], Vx_0[{cost.Vx_0.shape}], Vu_0[{cost.Vu_0.shape}]\n') + if dims.nz != 0 and cost.Vz_0.shape[0] != ny_0: + raise Exception('inconsistent dimension ny_0, regarding W_0, Vx_0, Vu_0, Vz_0.' + \ + f'\nGot W_0[{cost.W_0.shape}], Vx_0[{cost.Vx_0.shape}], Vu_0[{cost.Vu_0.shape}], Vz_0[{cost.Vz_0.shape}]\n') + if cost.Vx_0.shape[1] != dims.nx and ny_0 != 0: + raise Exception('inconsistent dimension: Vx_0 should have nx columns.') + if cost.Vu_0.shape[1] != dims.nu and ny_0 != 0: + raise Exception('inconsistent dimension: Vu_0 should have nu columns.') + if cost.yref_0.shape[0] != ny_0: + raise Exception('inconsistent dimension: regarding W_0, yref_0.' + \ + f'\nGot W_0[{cost.W_0.shape}], yref_0[{cost.yref_0.shape}]\n') + dims.ny_0 = ny_0 + + elif cost.cost_type_0 == 'NONLINEAR_LS': + ny_0 = cost.W_0.shape[0] + if is_empty(model.cost_y_expr_0) and ny_0 != 0: + raise Exception('inconsistent dimension ny_0: regarding W_0, cost_y_expr.') + elif casadi_length(model.cost_y_expr_0) != ny_0: + raise Exception('inconsistent dimension ny_0: regarding W_0, cost_y_expr.') + if cost.yref_0.shape[0] != ny_0: + raise Exception('inconsistent dimension: regarding W_0, yref_0.' + \ + f'\nGot W_0[{cost.W.shape}], yref_0[{cost.yref_0.shape}]\n') + dims.ny_0 = ny_0 + + elif cost.cost_type_0 == 'CONVEX_OVER_NONLINEAR': + if is_empty(model.cost_y_expr_0): + raise Exception('cost_y_expr_0 and/or cost_y_expr not provided.') + ny_0 = casadi_length(model.cost_y_expr_0) + if is_empty(model.cost_r_in_psi_expr_0) or casadi_length(model.cost_r_in_psi_expr_0) != ny_0: + raise Exception('inconsistent dimension ny_0: regarding cost_y_expr_0 and cost_r_in_psi_0.') + if is_empty(model.cost_psi_expr_0) or casadi_length(model.cost_psi_expr_0) != 1: + raise Exception('cost_psi_expr_0 not provided or not scalar-valued.') + if cost.yref_0.shape[0] != ny_0: + raise Exception('inconsistent dimension: regarding yref_0 and cost_y_expr_0, cost_r_in_psi_0.') + dims.ny_0 = ny_0 + + if not (opts.hessian_approx=='EXACT' and opts.exact_hess_cost==False) and opts.hessian_approx != 'GAUSS_NEWTON': + raise Exception("\nWith CONVEX_OVER_NONLINEAR cost type, possible Hessian approximations are:\n" + "GAUSS_NEWTON or EXACT with 'exact_hess_cost' == False.\n") + + elif cost.cost_type_0 == 'EXTERNAL': + if opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and model.cost_expr_ext_cost_custom_hess_0 is None: + print("\nWARNING: Gauss-Newton Hessian approximation with EXTERNAL cost type not possible!\n" + "got cost_type_0: EXTERNAL, hessian_approx: 'GAUSS_NEWTON.'\n" + "GAUSS_NEWTON hessian is only supported for cost_types [NON]LINEAR_LS.\n" + "If you continue, acados will proceed computing the exact hessian for the cost term.\n" + "Note: There is also the option to use the external cost module with a numerical hessian approximation (see `ext_cost_num_hess`).\n" + "OR the option to provide a symbolic custom hessian approximation (see `cost_expr_ext_cost_custom_hess`).\n") + + # path + if cost.cost_type == 'LINEAR_LS': + ny = cost.W.shape[0] + if cost.Vx.shape[0] != ny or cost.Vu.shape[0] != ny: + raise Exception('inconsistent dimension ny, regarding W, Vx, Vu.' + \ + f'\nGot W[{cost.W.shape}], Vx[{cost.Vx.shape}], Vu[{cost.Vu.shape}]\n') + if dims.nz != 0 and cost.Vz.shape[0] != ny: + raise Exception('inconsistent dimension ny, regarding W, Vx, Vu, Vz.' + \ + f'\nGot W[{cost.W.shape}], Vx[{cost.Vx.shape}], Vu[{cost.Vu.shape}], Vz[{cost.Vz.shape}]\n') + if cost.Vx.shape[1] != dims.nx and ny != 0: + raise Exception('inconsistent dimension: Vx should have nx columns.') + if cost.Vu.shape[1] != dims.nu and ny != 0: + raise Exception('inconsistent dimension: Vu should have nu columns.') + if cost.yref.shape[0] != ny: + raise Exception('inconsistent dimension: regarding W, yref.' + \ + f'\nGot W[{cost.W.shape}], yref[{cost.yref.shape}]\n') + dims.ny = ny + + elif cost.cost_type == 'NONLINEAR_LS': + ny = cost.W.shape[0] + if is_empty(model.cost_y_expr) and ny != 0: + raise Exception('inconsistent dimension ny: regarding W, cost_y_expr.') + elif casadi_length(model.cost_y_expr) != ny: + raise Exception('inconsistent dimension ny: regarding W, cost_y_expr.') + if cost.yref.shape[0] != ny: + raise Exception('inconsistent dimension: regarding W, yref.' + \ + f'\nGot W[{cost.W.shape}], yref[{cost.yref.shape}]\n') + dims.ny = ny + + elif cost.cost_type == 'CONVEX_OVER_NONLINEAR': + if is_empty(model.cost_y_expr): + raise Exception('cost_y_expr and/or cost_y_expr not provided.') + ny = casadi_length(model.cost_y_expr) + if is_empty(model.cost_r_in_psi_expr) or casadi_length(model.cost_r_in_psi_expr) != ny: + raise Exception('inconsistent dimension ny: regarding cost_y_expr and cost_r_in_psi.') + if is_empty(model.cost_psi_expr) or casadi_length(model.cost_psi_expr) != 1: + raise Exception('cost_psi_expr not provided or not scalar-valued.') + if cost.yref.shape[0] != ny: + raise Exception('inconsistent dimension: regarding yref and cost_y_expr, cost_r_in_psi.') + dims.ny = ny + + if not (opts.hessian_approx=='EXACT' and opts.exact_hess_cost==False) and opts.hessian_approx != 'GAUSS_NEWTON': + raise Exception("\nWith CONVEX_OVER_NONLINEAR cost type, possible Hessian approximations are:\n" + "GAUSS_NEWTON or EXACT with 'exact_hess_cost' == False.\n") + + + elif cost.cost_type == 'EXTERNAL': + if opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and model.cost_expr_ext_cost_custom_hess is None: + print("\nWARNING: Gauss-Newton Hessian approximation with EXTERNAL cost type not possible!\n" + "got cost_type: EXTERNAL, hessian_approx: 'GAUSS_NEWTON.'\n" + "GAUSS_NEWTON hessian is only supported for cost_types [NON]LINEAR_LS.\n" + "If you continue, acados will proceed computing the exact hessian for the cost term.\n" + "Note: There is also the option to use the external cost module with a numerical hessian approximation (see `ext_cost_num_hess`).\n" + "OR the option to provide a symbolic custom hessian approximation (see `cost_expr_ext_cost_custom_hess`).\n") + + # terminal + if cost.cost_type_e == 'LINEAR_LS': + ny_e = cost.W_e.shape[0] + if cost.Vx_e.shape[0] != ny_e: + raise Exception('inconsistent dimension ny_e: regarding W_e, cost_y_expr_e.' + \ + f'\nGot W_e[{cost.W_e.shape}], Vx_e[{cost.Vx_e.shape}]') + if cost.Vx_e.shape[1] != dims.nx and ny_e != 0: + raise Exception('inconsistent dimension: Vx_e should have nx columns.') + if cost.yref_e.shape[0] != ny_e: + raise Exception('inconsistent dimension: regarding W_e, yref_e.') + dims.ny_e = ny_e + + elif cost.cost_type_e == 'NONLINEAR_LS': + ny_e = cost.W_e.shape[0] + if is_empty(model.cost_y_expr_e) and ny_e != 0: + raise Exception('inconsistent dimension ny_e: regarding W_e, cost_y_expr_e.') + elif casadi_length(model.cost_y_expr_e) != ny_e: + raise Exception('inconsistent dimension ny_e: regarding W_e, cost_y_expr_e.') + if cost.yref_e.shape[0] != ny_e: + raise Exception('inconsistent dimension: regarding W_e, yref_e.') + dims.ny_e = ny_e + + elif cost.cost_type_e == 'CONVEX_OVER_NONLINEAR': + if is_empty(model.cost_y_expr_e): + raise Exception('cost_y_expr_e not provided.') + ny_e = casadi_length(model.cost_y_expr_e) + if is_empty(model.cost_r_in_psi_expr_e) or casadi_length(model.cost_r_in_psi_expr_e) != ny_e: + raise Exception('inconsistent dimension ny_e: regarding cost_y_expr_e and cost_r_in_psi_e.') + if is_empty(model.cost_psi_expr_e) or casadi_length(model.cost_psi_expr_e) != 1: + raise Exception('cost_psi_expr_e not provided or not scalar-valued.') + if cost.yref_e.shape[0] != ny_e: + raise Exception('inconsistent dimension: regarding yref_e and cost_y_expr_e, cost_r_in_psi_e.') + dims.ny_e = ny_e + + if not (opts.hessian_approx=='EXACT' and opts.exact_hess_cost==False) and opts.hessian_approx != 'GAUSS_NEWTON': + raise Exception("\nWith CONVEX_OVER_NONLINEAR cost type, possible Hessian approximations are:\n" + "GAUSS_NEWTON or EXACT with 'exact_hess_cost' == False.\n") + + + + elif cost.cost_type_e == 'EXTERNAL': + if opts.hessian_approx == 'GAUSS_NEWTON' and opts.ext_cost_num_hess == 0 and model.cost_expr_ext_cost_custom_hess_e is None: + print("\nWARNING: Gauss-Newton Hessian approximation with EXTERNAL cost type not possible!\n" + "got cost_type_e: EXTERNAL, hessian_approx: 'GAUSS_NEWTON.'\n" + "GAUSS_NEWTON hessian is only supported for cost_types [NON]LINEAR_LS.\n" + "If you continue, acados will proceed computing the exact hessian for the cost term.\n" + "Note: There is also the option to use the external cost module with a numerical hessian approximation (see `ext_cost_num_hess`).\n" + "OR the option to provide a symbolic custom hessian approximation (see `cost_expr_ext_cost_custom_hess`).\n") + + ## constraints + # initial + this_shape = constraints.lbx_0.shape + other_shape = constraints.ubx_0.shape + if not this_shape == other_shape: + raise Exception('lbx_0, ubx_0 have different shapes!') + if not is_column(constraints.lbx_0): + raise Exception('lbx_0, ubx_0 must be column vectors!') + dims.nbx_0 = constraints.lbx_0.size + + if all(constraints.lbx_0 == constraints.ubx_0) and dims.nbx_0 == dims.nx \ + and dims.nbxe_0 is None \ + and (constraints.idxbxe_0.shape == constraints.idxbx_0.shape)\ + and all(constraints.idxbxe_0 == constraints.idxbx_0): + # case: x0 was set: nbx0 are all equlities. + dims.nbxe_0 = dims.nbx_0 + elif constraints.idxbxe_0 is not None: + dims.nbxe_0 = constraints.idxbxe_0.shape[0] + elif dims.nbxe_0 is None: + # case: x0 and idxbxe_0 were not set -> dont assume nbx0 to be equality constraints. + dims.nbxe_0 = 0 + + # path + nbx = constraints.idxbx.shape[0] + if constraints.ubx.shape[0] != nbx or constraints.lbx.shape[0] != nbx: + raise Exception('inconsistent dimension nbx, regarding idxbx, ubx, lbx.') + else: + dims.nbx = nbx + + nbu = constraints.idxbu.shape[0] + if constraints.ubu.shape[0] != nbu or constraints.lbu.shape[0] != nbu: + raise Exception('inconsistent dimension nbu, regarding idxbu, ubu, lbu.') + else: + dims.nbu = nbu + + ng = constraints.lg.shape[0] + if constraints.ug.shape[0] != ng or constraints.C.shape[0] != ng \ + or constraints.D.shape[0] != ng: + raise Exception('inconsistent dimension ng, regarding lg, ug, C, D.') + else: + dims.ng = ng + + if not is_empty(model.con_h_expr): + nh = casadi_length(model.con_h_expr) + else: + nh = 0 + + if constraints.uh.shape[0] != nh or constraints.lh.shape[0] != nh: + raise Exception('inconsistent dimension nh, regarding lh, uh, con_h_expr.') + else: + dims.nh = nh + + if is_empty(model.con_phi_expr): + dims.nphi = 0 + dims.nr = 0 + else: + dims.nphi = casadi_length(model.con_phi_expr) + if is_empty(model.con_r_expr): + raise Exception('convex over nonlinear constraints: con_r_expr but con_phi_expr is nonempty') + else: + dims.nr = casadi_length(model.con_r_expr) + + # terminal + nbx_e = constraints.idxbx_e.shape[0] + if constraints.ubx_e.shape[0] != nbx_e or constraints.lbx_e.shape[0] != nbx_e: + raise Exception('inconsistent dimension nbx_e, regarding idxbx_e, ubx_e, lbx_e.') + else: + dims.nbx_e = nbx_e + + ng_e = constraints.lg_e.shape[0] + if constraints.ug_e.shape[0] != ng_e or constraints.C_e.shape[0] != ng_e: + raise Exception('inconsistent dimension ng_e, regarding_e lg_e, ug_e, C_e.') + else: + dims.ng_e = ng_e + + if not is_empty(model.con_h_expr_e): + nh_e = casadi_length(model.con_h_expr_e) + else: + nh_e = 0 + + if constraints.uh_e.shape[0] != nh_e or constraints.lh_e.shape[0] != nh_e: + raise Exception('inconsistent dimension nh_e, regarding lh_e, uh_e, con_h_expr_e.') + else: + dims.nh_e = nh_e + + if is_empty(model.con_phi_expr_e): + dims.nphi_e = 0 + dims.nr_e = 0 + else: + dims.nphi_e = casadi_length(model.con_phi_expr_e) + if is_empty(model.con_r_expr_e): + raise Exception('convex over nonlinear constraints: con_r_expr_e but con_phi_expr_e is nonempty') + else: + dims.nr_e = casadi_length(model.con_r_expr_e) + + # Slack dimensions + nsbx = constraints.idxsbx.shape[0] + if nsbx > nbx: + raise Exception(f'inconsistent dimension nsbx = {nsbx}. Is greater than nbx = {nbx}.') + if is_empty(constraints.lsbx): + constraints.lsbx = np.zeros((nsbx,)) + elif constraints.lsbx.shape[0] != nsbx: + raise Exception('inconsistent dimension nsbx, regarding idxsbx, lsbx.') + if is_empty(constraints.usbx): + constraints.usbx = np.zeros((nsbx,)) + elif constraints.usbx.shape[0] != nsbx: + raise Exception('inconsistent dimension nsbx, regarding idxsbx, usbx.') + dims.nsbx = nsbx + + nsbu = constraints.idxsbu.shape[0] + if nsbu > nbu: + raise Exception(f'inconsistent dimension nsbu = {nsbu}. Is greater than nbu = {nbu}.') + if is_empty(constraints.lsbu): + constraints.lsbu = np.zeros((nsbu,)) + elif constraints.lsbu.shape[0] != nsbu: + raise Exception('inconsistent dimension nsbu, regarding idxsbu, lsbu.') + if is_empty(constraints.usbu): + constraints.usbu = np.zeros((nsbu,)) + elif constraints.usbu.shape[0] != nsbu: + raise Exception('inconsistent dimension nsbu, regarding idxsbu, usbu.') + dims.nsbu = nsbu + + nsh = constraints.idxsh.shape[0] + if nsh > nh: + raise Exception(f'inconsistent dimension nsh = {nsh}. Is greater than nh = {nh}.') + if is_empty(constraints.lsh): + constraints.lsh = np.zeros((nsh,)) + elif constraints.lsh.shape[0] != nsh: + raise Exception('inconsistent dimension nsh, regarding idxsh, lsh.') + if is_empty(constraints.ush): + constraints.ush = np.zeros((nsh,)) + elif constraints.ush.shape[0] != nsh: + raise Exception('inconsistent dimension nsh, regarding idxsh, ush.') + dims.nsh = nsh + + nsphi = constraints.idxsphi.shape[0] + if nsphi > dims.nphi: + raise Exception(f'inconsistent dimension nsphi = {nsphi}. Is greater than nphi = {dims.nphi}.') + if is_empty(constraints.lsphi): + constraints.lsphi = np.zeros((nsphi,)) + elif constraints.lsphi.shape[0] != nsphi: + raise Exception('inconsistent dimension nsphi, regarding idxsphi, lsphi.') + if is_empty(constraints.usphi): + constraints.usphi = np.zeros((nsphi,)) + elif constraints.usphi.shape[0] != nsphi: + raise Exception('inconsistent dimension nsphi, regarding idxsphi, usphi.') + dims.nsphi = nsphi + + nsg = constraints.idxsg.shape[0] + if nsg > ng: + raise Exception(f'inconsistent dimension nsg = {nsg}. Is greater than ng = {ng}.') + if is_empty(constraints.lsg): + constraints.lsg = np.zeros((nsg,)) + elif constraints.lsg.shape[0] != nsg: + raise Exception('inconsistent dimension nsg, regarding idxsg, lsg.') + if is_empty(constraints.usg): + constraints.usg = np.zeros((nsg,)) + elif constraints.usg.shape[0] != nsg: + raise Exception('inconsistent dimension nsg, regarding idxsg, usg.') + dims.nsg = nsg + + ns = nsbx + nsbu + nsh + nsg + nsphi + wrong_field = "" + if cost.Zl.shape[0] != ns: + wrong_field = "Zl" + dim = cost.Zl.shape[0] + elif cost.Zu.shape[0] != ns: + wrong_field = "Zu" + dim = cost.Zu.shape[0] + elif cost.zl.shape[0] != ns: + wrong_field = "zl" + dim = cost.zl.shape[0] + elif cost.zu.shape[0] != ns: + wrong_field = "zu" + dim = cost.zu.shape[0] + + if wrong_field != "": + raise Exception(f'Inconsistent size for field {wrong_field}, with dimension {dim}, \n\t'\ + + f'Detected ns = {ns} = nsbx + nsbu + nsg + nsh + nsphi.\n\t'\ + + f'With nsbx = {nsbx}, nsbu = {nsbu}, nsg = {nsg}, nsh = {nsh}, nsphi = {nsphi}') + + dims.ns = ns + + nsbx_e = constraints.idxsbx_e.shape[0] + if nsbx_e > nbx_e: + raise Exception(f'inconsistent dimension nsbx_e = {nsbx_e}. Is greater than nbx_e = {nbx_e}.') + if is_empty(constraints.lsbx_e): + constraints.lsbx_e = np.zeros((nsbx_e,)) + elif constraints.lsbx_e.shape[0] != nsbx_e: + raise Exception('inconsistent dimension nsbx_e, regarding idxsbx_e, lsbx_e.') + if is_empty(constraints.usbx_e): + constraints.usbx_e = np.zeros((nsbx_e,)) + elif constraints.usbx_e.shape[0] != nsbx_e: + raise Exception('inconsistent dimension nsbx_e, regarding idxsbx_e, usbx_e.') + dims.nsbx_e = nsbx_e + + nsh_e = constraints.idxsh_e.shape[0] + if nsh_e > nh_e: + raise Exception(f'inconsistent dimension nsh_e = {nsh_e}. Is greater than nh_e = {nh_e}.') + if is_empty(constraints.lsh_e): + constraints.lsh_e = np.zeros((nsh_e,)) + elif constraints.lsh_e.shape[0] != nsh_e: + raise Exception('inconsistent dimension nsh_e, regarding idxsh_e, lsh_e.') + if is_empty(constraints.ush_e): + constraints.ush_e = np.zeros((nsh_e,)) + elif constraints.ush_e.shape[0] != nsh_e: + raise Exception('inconsistent dimension nsh_e, regarding idxsh_e, ush_e.') + dims.nsh_e = nsh_e + + nsg_e = constraints.idxsg_e.shape[0] + if nsg_e > ng_e: + raise Exception(f'inconsistent dimension nsg_e = {nsg_e}. Is greater than ng_e = {ng_e}.') + if is_empty(constraints.lsg_e): + constraints.lsg_e = np.zeros((nsg_e,)) + elif constraints.lsg_e.shape[0] != nsg_e: + raise Exception('inconsistent dimension nsg_e, regarding idxsg_e, lsg_e.') + if is_empty(constraints.usg_e): + constraints.usg_e = np.zeros((nsg_e,)) + elif constraints.usg_e.shape[0] != nsg_e: + raise Exception('inconsistent dimension nsg_e, regarding idxsg_e, usg_e.') + dims.nsg_e = nsg_e + + nsphi_e = constraints.idxsphi_e.shape[0] + if nsphi_e > dims.nphi_e: + raise Exception(f'inconsistent dimension nsphi_e = {nsphi_e}. Is greater than nphi_e = {dims.nphi_e}.') + if is_empty(constraints.lsphi_e): + constraints.lsphi_e = np.zeros((nsphi_e,)) + elif constraints.lsphi_e.shape[0] != nsphi_e: + raise Exception('inconsistent dimension nsphi_e, regarding idxsphi_e, lsphi_e.') + if is_empty(constraints.usphi_e): + constraints.usphi_e = np.zeros((nsphi_e,)) + elif constraints.usphi_e.shape[0] != nsphi_e: + raise Exception('inconsistent dimension nsphi_e, regarding idxsphi_e, usphi_e.') + dims.nsphi_e = nsphi_e + + # terminal + ns_e = nsbx_e + nsh_e + nsg_e + nsphi_e + wrong_field = "" + if cost.Zl_e.shape[0] != ns_e: + wrong_field = "Zl_e" + dim = cost.Zl_e.shape[0] + elif cost.Zu_e.shape[0] != ns_e: + wrong_field = "Zu_e" + dim = cost.Zu_e.shape[0] + elif cost.zl_e.shape[0] != ns_e: + wrong_field = "zl_e" + dim = cost.zl_e.shape[0] + elif cost.zu_e.shape[0] != ns_e: + wrong_field = "zu_e" + dim = cost.zu_e.shape[0] + + if wrong_field != "": + raise Exception(f'Inconsistent size for field {wrong_field}, with dimension {dim}, \n\t'\ + + f'Detected ns_e = {ns_e} = nsbx_e + nsg_e + nsh_e + nsphi_e.\n\t'\ + + f'With nsbx_e = {nsbx_e}, nsg_e = {nsg_e}, nsh_e = {nsh_e}, nsphi_e = {nsphi_e}') + + dims.ns_e = ns_e + + # discretization + if is_empty(opts.time_steps) and is_empty(opts.shooting_nodes): + # uniform discretization + opts.time_steps = opts.tf / dims.N * np.ones((dims.N,)) + + elif not is_empty(opts.shooting_nodes): + if np.shape(opts.shooting_nodes)[0] != dims.N+1: + raise Exception('inconsistent dimension N, regarding shooting_nodes.') + + time_steps = opts.shooting_nodes[1:] - opts.shooting_nodes[0:-1] + # identify constant time_steps: due to numerical reasons the content of time_steps might vary a bit + avg_time_steps = np.average(time_steps) + # criterion for constant time step detection: the min/max difference in values normalized by the average + check_const_time_step = (np.max(time_steps)-np.min(time_steps)) / avg_time_steps + # if the criterion is small, we have a constant time_step + if check_const_time_step < 1e-9: + time_steps[:] = avg_time_steps # if we have a constant time_step: apply the average time_step + + opts.time_steps = time_steps + + elif (not is_empty(opts.time_steps)) and (not is_empty(opts.shooting_nodes)): + Exception('Please provide either time_steps or shooting_nodes for nonuniform discretization') + + tf = np.sum(opts.time_steps) + if (tf - opts.tf) / tf > 1e-15: + raise Exception(f'Inconsistent discretization: {opts.tf}'\ + f' = tf != sum(opts.time_steps) = {tf}.') + + # num_steps + if isinstance(opts.sim_method_num_steps, np.ndarray) and opts.sim_method_num_steps.size == 1: + opts.sim_method_num_steps = opts.sim_method_num_steps.item() + + if isinstance(opts.sim_method_num_steps, (int, float)) and opts.sim_method_num_steps % 1 == 0: + opts.sim_method_num_steps = opts.sim_method_num_steps * np.ones((dims.N,), dtype=np.int64) + elif isinstance(opts.sim_method_num_steps, np.ndarray) and opts.sim_method_num_steps.size == dims.N \ + and np.all(np.equal(np.mod(opts.sim_method_num_steps, 1), 0)): + opts.sim_method_num_steps = np.reshape(opts.sim_method_num_steps, (dims.N,)).astype(np.int64) + else: + raise Exception("Wrong value for sim_method_num_steps. Should be either int or array of ints of shape (N,).") + + # num_stages + if isinstance(opts.sim_method_num_stages, np.ndarray) and opts.sim_method_num_stages.size == 1: + opts.sim_method_num_stages = opts.sim_method_num_stages.item() + + if isinstance(opts.sim_method_num_stages, (int, float)) and opts.sim_method_num_stages % 1 == 0: + opts.sim_method_num_stages = opts.sim_method_num_stages * np.ones((dims.N,), dtype=np.int64) + elif isinstance(opts.sim_method_num_stages, np.ndarray) and opts.sim_method_num_stages.size == dims.N \ + and np.all(np.equal(np.mod(opts.sim_method_num_stages, 1), 0)): + opts.sim_method_num_stages = np.reshape(opts.sim_method_num_stages, (dims.N,)).astype(np.int64) + else: + raise Exception("Wrong value for sim_method_num_stages. Should be either int or array of ints of shape (N,).") + + # jac_reuse + if isinstance(opts.sim_method_jac_reuse, np.ndarray) and opts.sim_method_jac_reuse.size == 1: + opts.sim_method_jac_reuse = opts.sim_method_jac_reuse.item() + + if isinstance(opts.sim_method_jac_reuse, (int, float)) and opts.sim_method_jac_reuse % 1 == 0: + opts.sim_method_jac_reuse = opts.sim_method_jac_reuse * np.ones((dims.N,), dtype=np.int64) + elif isinstance(opts.sim_method_jac_reuse, np.ndarray) and opts.sim_method_jac_reuse.size == dims.N \ + and np.all(np.equal(np.mod(opts.sim_method_jac_reuse, 1), 0)): + opts.sim_method_jac_reuse = np.reshape(opts.sim_method_jac_reuse, (dims.N,)).astype(np.int64) + else: + raise Exception("Wrong value for sim_method_jac_reuse. Should be either int or array of ints of shape (N,).") + + +def get_simulink_default_opts(): + python_interface_path = get_python_interface_path() + abs_path = os.path.join(python_interface_path, 'simulink_default_opts.json') + with open(abs_path , 'r') as f: + simulink_default_opts = json.load(f) + return simulink_default_opts + + +def ocp_formulation_json_dump(acados_ocp, simulink_opts=None, json_file='acados_ocp_nlp.json'): + # Load acados_ocp_nlp structure description + ocp_layout = get_ocp_nlp_layout() + + # Copy input ocp object dictionary + ocp_nlp_dict = dict(deepcopy(acados_ocp).__dict__) + # TODO: maybe make one function with formatting + + for acados_struct, v in ocp_layout.items(): + # skip non dict attributes + if not isinstance(v, dict): + continue + # setattr(ocp_nlp, acados_struct, dict(getattr(acados_ocp, acados_struct).__dict__)) + # Copy ocp object attributes dictionaries + ocp_nlp_dict[acados_struct]=dict(getattr(acados_ocp, acados_struct).__dict__) + + ocp_nlp_dict = format_class_dict(ocp_nlp_dict) + + if simulink_opts is not None: + ocp_nlp_dict['simulink_opts'] = simulink_opts + + with open(json_file, 'w') as f: + json.dump(ocp_nlp_dict, f, default=make_object_json_dumpable, indent=4, sort_keys=True) + + + +def ocp_formulation_json_load(json_file='acados_ocp_nlp.json'): + # Load acados_ocp_nlp structure description + ocp_layout = get_ocp_nlp_layout() + + with open(json_file, 'r') as f: + ocp_nlp_json = json.load(f) + + ocp_nlp_dict = json2dict(ocp_nlp_json, ocp_nlp_json['dims']) + + # Instantiate AcadosOcp object + acados_ocp = AcadosOcp() + + # load class dict + acados_ocp.__dict__ = ocp_nlp_dict + + # load class attributes dict, dims, constraints, etc + for acados_struct, v in ocp_layout.items(): + # skip non dict attributes + if not isinstance(v, dict): + continue + acados_attribute = getattr(acados_ocp, acados_struct) + acados_attribute.__dict__ = ocp_nlp_dict[acados_struct] + setattr(acados_ocp, acados_struct, acados_attribute) + + return acados_ocp + + +def ocp_generate_external_functions(acados_ocp: AcadosOcp, model: AcadosModel): + + model = make_model_consistent(model) + + if acados_ocp.solver_options.hessian_approx == 'EXACT': + opts = dict(generate_hess=1) + else: + opts = dict(generate_hess=0) + + # create code_export_dir, model_dir + code_export_dir = acados_ocp.code_export_directory + opts['code_export_directory'] = code_export_dir + model_dir = os.path.join(code_export_dir, model.name + '_model') + if not os.path.exists(model_dir): + os.makedirs(model_dir) + + check_casadi_version() + # TODO: remove dir gen from all the generate_c_* functions + if acados_ocp.model.dyn_ext_fun_type == 'casadi': + if acados_ocp.solver_options.integrator_type == 'ERK': + generate_c_code_explicit_ode(model, opts) + elif acados_ocp.solver_options.integrator_type == 'IRK': + generate_c_code_implicit_ode(model, opts) + elif acados_ocp.solver_options.integrator_type == 'LIFTED_IRK': + generate_c_code_implicit_ode(model, opts) + elif acados_ocp.solver_options.integrator_type == 'GNSF': + generate_c_code_gnsf(model, opts) + elif acados_ocp.solver_options.integrator_type == 'DISCRETE': + generate_c_code_discrete_dynamics(model, opts) + else: + raise Exception("ocp_generate_external_functions: unknown integrator type.") + else: + target_location = os.path.join(code_export_dir, model_dir, model.dyn_generic_source) + shutil.copyfile(model.dyn_generic_source, target_location) + + if acados_ocp.dims.nphi > 0 or acados_ocp.dims.nh > 0: + generate_c_code_constraint(model, model.name, False, opts) + + if acados_ocp.dims.nphi_e > 0 or acados_ocp.dims.nh_e > 0: + generate_c_code_constraint(model, model.name, True, opts) + + if acados_ocp.cost.cost_type_0 == 'NONLINEAR_LS': + generate_c_code_nls_cost(model, model.name, 'initial', opts) + elif acados_ocp.cost.cost_type_0 == 'CONVEX_OVER_NONLINEAR': + generate_c_code_conl_cost(model, model.name, 'initial', opts) + elif acados_ocp.cost.cost_type_0 == 'EXTERNAL': + generate_c_code_external_cost(model, 'initial', opts) + + if acados_ocp.cost.cost_type == 'NONLINEAR_LS': + generate_c_code_nls_cost(model, model.name, 'path', opts) + elif acados_ocp.cost.cost_type == 'CONVEX_OVER_NONLINEAR': + generate_c_code_conl_cost(model, model.name, 'path', opts) + elif acados_ocp.cost.cost_type == 'EXTERNAL': + generate_c_code_external_cost(model, 'path', opts) + + if acados_ocp.cost.cost_type_e == 'NONLINEAR_LS': + generate_c_code_nls_cost(model, model.name, 'terminal', opts) + elif acados_ocp.cost.cost_type_e == 'CONVEX_OVER_NONLINEAR': + generate_c_code_conl_cost(model, model.name, 'terminal', opts) + elif acados_ocp.cost.cost_type_e == 'EXTERNAL': + generate_c_code_external_cost(model, 'terminal', opts) + + +def ocp_get_default_cmake_builder() -> CMakeBuilder: + """ + If :py:class:`~acados_template.acados_ocp_solver.AcadosOcpSolver` is used with `CMake` this function returns a good first setting. + :return: default :py:class:`~acados_template.builders.CMakeBuilder` + """ + cmake_builder = CMakeBuilder() + cmake_builder.options_on = ['BUILD_ACADOS_OCP_SOLVER_LIB'] + return cmake_builder + + + +def ocp_render_templates(acados_ocp: AcadosOcp, json_file, cmake_builder=None, simulink_opts=None): + + # setting up loader and environment + json_path = os.path.abspath(json_file) + + if not os.path.exists(json_path): + raise Exception(f'Path "{json_path}" not found!') + + # Render templates + template_list = __ocp_get_template_list(acados_ocp, cmake_builder=cmake_builder, simulink_opts=simulink_opts) + for tup in template_list: + if len(tup) > 2: + output_dir = tup[2] + else: + output_dir = acados_ocp.code_export_directory + render_template(tup[0], tup[1], output_dir, json_path) + + # Custom templates + acados_template_path = os.path.dirname(os.path.abspath(__file__)) + custom_template_glob = os.path.join(acados_template_path, 'custom_update_templates', '*') + for tup in acados_ocp.solver_options.custom_templates: + render_template(tup[0], tup[1], acados_ocp.code_export_directory, json_path, template_glob=custom_template_glob) + + return + + + +def __ocp_get_template_list(acados_ocp: AcadosOcp, cmake_builder=None, simulink_opts=None) -> list: + """ + returns a list of tuples in the form: + (input_filename, output_filname) + or + (input_filename, output_filname, output_directory) + """ + name = acados_ocp.model.name + code_export_directory = acados_ocp.code_export_directory + template_list = [] + + template_list.append(('main.in.c', f'main_{name}.c')) + template_list.append(('acados_solver.in.c', f'acados_solver_{name}.c')) + template_list.append(('acados_solver.in.h', f'acados_solver_{name}.h')) + template_list.append(('acados_solver.in.pxd', f'acados_solver.pxd')) + if cmake_builder is not None: + template_list.append(('CMakeLists.in.txt', 'CMakeLists.txt')) + else: + template_list.append(('Makefile.in', 'Makefile')) + + + # sim + template_list.append(('acados_sim_solver.in.c', f'acados_sim_solver_{name}.c')) + template_list.append(('acados_sim_solver.in.h', f'acados_sim_solver_{name}.h')) + template_list.append(('main_sim.in.c', f'main_sim_{name}.c')) + + # model + model_dir = os.path.join(code_export_directory, f'{name}_model') + template_list.append(('model.in.h', f'{name}_model.h', model_dir)) + # constraints + constraints_dir = os.path.join(code_export_directory, f'{name}_constraints') + template_list.append(('constraints.in.h', f'{name}_constraints.h', constraints_dir)) + # cost + cost_dir = os.path.join(code_export_directory, f'{name}_cost') + template_list.append(('cost.in.h', f'{name}_cost.h', cost_dir)) + + # Simulink + if simulink_opts is not None: + template_file = os.path.join('matlab_templates', 'acados_solver_sfun.in.c') + template_list.append((template_file, f'acados_solver_sfunction_{name}.c')) + template_file = os.path.join('matlab_templates', 'acados_solver_sfun.in.c') + template_list.append((template_file, f'make_sfun_{name}.m')) + + return template_list + + +def remove_x0_elimination(acados_ocp): + acados_ocp.constraints.idxbxe_0 = np.zeros((0,)) + acados_ocp.dims.nbxe_0 = 0 + + +class AcadosOcpSolver: + """ + Class to interact with the acados ocp solver C object. + + :param acados_ocp: type :py:class:`~acados_template.acados_ocp.AcadosOcp` - description of the OCP for acados + :param json_file: name for the json file used to render the templated code - default: acados_ocp_nlp.json + :param simulink_opts: Options to configure Simulink S-function blocks, mainly to activate possible Inputs and Outputs + """ + if sys.platform=="win32": + from ctypes import wintypes + from ctypes import WinDLL + dlclose = WinDLL('kernel32', use_last_error=True).FreeLibrary + dlclose.argtypes = [wintypes.HMODULE] + else: + dlclose = CDLL(None).dlclose + dlclose.argtypes = [c_void_p] + + @classmethod + def generate(cls, acados_ocp: AcadosOcp, json_file='acados_ocp_nlp.json', simulink_opts=None, cmake_builder: CMakeBuilder = None): + """ + Generates the code for an acados OCP solver, given the description in acados_ocp. + :param acados_ocp: type AcadosOcp - description of the OCP for acados + :param json_file: name for the json file used to render the templated code - default: `acados_ocp_nlp.json` + :param simulink_opts: Options to configure Simulink S-function blocks, mainly to activate possible inputs and + outputs; default: `None` + :param cmake_builder: type :py:class:`~acados_template.builders.CMakeBuilder` generate a `CMakeLists.txt` and use + the `CMake` pipeline instead of a `Makefile` (`CMake` seems to be the better option in conjunction with + `MS Visual Studio`); default: `None` + """ + model = acados_ocp.model + acados_ocp.code_export_directory = os.path.abspath(acados_ocp.code_export_directory) + + # make dims consistent + make_ocp_dims_consistent(acados_ocp) + + # module dependent post processing + if acados_ocp.solver_options.integrator_type == 'GNSF': + if 'gnsf_model' in acados_ocp.__dict__: + set_up_imported_gnsf_model(acados_ocp) + else: + detect_gnsf_structure(acados_ocp) + + if acados_ocp.solver_options.qp_solver == 'PARTIAL_CONDENSING_QPDUNES': + remove_x0_elimination(acados_ocp) + + # set integrator time automatically + acados_ocp.solver_options.Tsim = acados_ocp.solver_options.time_steps[0] + + # generate external functions + ocp_generate_external_functions(acados_ocp, model) + + # dump to json + acados_ocp.json_file = json_file + ocp_formulation_json_dump(acados_ocp, simulink_opts=simulink_opts, json_file=json_file) + + # render templates + ocp_render_templates(acados_ocp, json_file, cmake_builder=cmake_builder, simulink_opts=simulink_opts) + + # copy custom update function + if acados_ocp.solver_options.custom_update_filename != "" and acados_ocp.solver_options.custom_update_copy: + target_location = os.path.join(acados_ocp.code_export_directory, acados_ocp.solver_options.custom_update_filename) + shutil.copyfile(acados_ocp.solver_options.custom_update_filename, target_location) + if acados_ocp.solver_options.custom_update_header_filename != "" and acados_ocp.solver_options.custom_update_copy: + target_location = os.path.join(acados_ocp.code_export_directory, acados_ocp.solver_options.custom_update_header_filename) + shutil.copyfile(acados_ocp.solver_options.custom_update_header_filename, target_location) + + + @classmethod + def build(cls, code_export_dir, with_cython=False, cmake_builder: CMakeBuilder = None, verbose: bool = True): + """ + Builds the code for an acados OCP solver, that has been generated in code_export_dir + :param code_export_dir: directory in which acados OCP solver has been generated, see generate() + :param with_cython: option indicating if the cython interface is build, default: False. + :param cmake_builder: type :py:class:`~acados_template.builders.CMakeBuilder` generate a `CMakeLists.txt` and use + the `CMake` pipeline instead of a `Makefile` (`CMake` seems to be the better option in conjunction with + `MS Visual Studio`); default: `None` + :param verbose: indicating if build command is printed + """ + code_export_dir = os.path.abspath(code_export_dir) + cwd = os.getcwd() + os.chdir(code_export_dir) + if with_cython: + call( + ['make', 'clean_all'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + call( + ['make', 'ocp_cython'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + else: + if cmake_builder is not None: + cmake_builder.exec(code_export_dir) + else: + call( + ['make', 'clean_ocp_shared_lib'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + call( + ['make', 'ocp_shared_lib'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + os.chdir(cwd) + + + @classmethod + def create_cython_solver(cls, json_file): + """ + Returns an `AcadosOcpSolverCython` object. + + This is an alternative Cython based Python wrapper to the acados OCP solver in C. + This offers faster interaction with the solver, because getter and setter calls, which include shape checking are done in compiled C code. + + The default wrapper `AcadosOcpSolver` is based on ctypes. + """ + with open(json_file, 'r') as f: + acados_ocp_json = json.load(f) + code_export_directory = acados_ocp_json['code_export_directory'] + + importlib.invalidate_caches() + rel_code_export_directory = os.path.relpath(code_export_directory) + acados_ocp_solver_pyx = importlib.import_module(f'{rel_code_export_directory}.acados_ocp_solver_pyx') + + AcadosOcpSolverCython = getattr(acados_ocp_solver_pyx, 'AcadosOcpSolverCython') + return AcadosOcpSolverCython(acados_ocp_json['model']['name'], + acados_ocp_json['solver_options']['nlp_solver_type'], + acados_ocp_json['dims']['N']) + + + def __init__(self, acados_ocp: AcadosOcp, json_file='acados_ocp_nlp.json', simulink_opts=None, build=True, generate=True, cmake_builder: CMakeBuilder = None, verbose=True): + + self.solver_created = False + if generate: + self.generate(acados_ocp, json_file=json_file, simulink_opts=simulink_opts, cmake_builder=cmake_builder) + + # load json, store options in object + with open(json_file, 'r') as f: + acados_ocp_json = json.load(f) + self.N = acados_ocp_json['dims']['N'] + self.model_name = acados_ocp_json['model']['name'] + self.solver_options = acados_ocp_json['solver_options'] + + acados_lib_path = acados_ocp_json['acados_lib_path'] + code_export_directory = acados_ocp_json['code_export_directory'] + + if build: + self.build(code_export_directory, with_cython=False, cmake_builder=cmake_builder, verbose=verbose) + + # prepare library loading + lib_prefix = 'lib' + lib_ext = get_lib_ext() + if os.name == 'nt': + lib_prefix = '' + + # Load acados library to avoid unloading the library. + # This is necessary if acados was compiled with OpenMP, since the OpenMP threads can't be destroyed. + # Unloading a library which uses OpenMP results in a segfault (on any platform?). + # see [https://stackoverflow.com/questions/34439956/vc-crash-when-freeing-a-dll-built-with-openmp] + # or [https://python.hotexamples.com/examples/_ctypes/-/dlclose/python-dlclose-function-examples.html] + libacados_name = f'{lib_prefix}acados{lib_ext}' + libacados_filepath = os.path.join(acados_lib_path, libacados_name) + self.__acados_lib = CDLL(libacados_filepath) + # find out if acados was compiled with OpenMP + try: + self.__acados_lib_uses_omp = getattr(self.__acados_lib, 'omp_get_thread_num') is not None + except AttributeError as e: + self.__acados_lib_uses_omp = False + if self.__acados_lib_uses_omp: + print('acados was compiled with OpenMP.') + else: + print('acados was compiled without OpenMP.') + libacados_ocp_solver_name = f'{lib_prefix}acados_ocp_solver_{self.model_name}{lib_ext}' + self.shared_lib_name = os.path.join(code_export_directory, libacados_ocp_solver_name) + + # get shared_lib + self.shared_lib = CDLL(self.shared_lib_name) + + # create capsule + getattr(self.shared_lib, f"{self.model_name}_acados_create_capsule").restype = c_void_p + self.capsule = getattr(self.shared_lib, f"{self.model_name}_acados_create_capsule")() + + # create solver + getattr(self.shared_lib, f"{self.model_name}_acados_create").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_create").restype = c_int + assert getattr(self.shared_lib, f"{self.model_name}_acados_create")(self.capsule)==0 + self.solver_created = True + + self.acados_ocp = acados_ocp + + # get pointers solver + self.__get_pointers_solver() + + self.status = 0 + + # gettable fields + self.__qp_dynamics_fields = ['A', 'B', 'b'] + self.__qp_cost_fields = ['Q', 'R', 'S', 'q', 'r'] + self.__qp_constraint_fields = ['C', 'D', 'lg', 'ug', 'lbx', 'ubx', 'lbu', 'ubu'] + + + def __get_pointers_solver(self): + # """ + # Private function to get the pointers for solver + # """ + # get pointers solver + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_opts").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_opts").restype = c_void_p + self.nlp_opts = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_opts")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_dims").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_dims").restype = c_void_p + self.nlp_dims = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_dims")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_config").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_config").restype = c_void_p + self.nlp_config = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_config")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_out").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_out").restype = c_void_p + self.nlp_out = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_out")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_get_sens_out").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_sens_out").restype = c_void_p + self.sens_out = getattr(self.shared_lib, f"{self.model_name}_acados_get_sens_out")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_in").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_in").restype = c_void_p + self.nlp_in = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_in")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_solver").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_solver").restype = c_void_p + self.nlp_solver = getattr(self.shared_lib, f"{self.model_name}_acados_get_nlp_solver")(self.capsule) + + + + def solve_for_x0(self, x0_bar): + """ + Wrapper around `solve()` which sets initial state constraint, solves the OCP, and returns u0. + """ + self.set(0, "lbx", x0_bar) + self.set(0, "ubx", x0_bar) + + status = self.solve() + + if status == 2: + print("Warning: acados_ocp_solver reached maximum iterations.") + elif status != 0: + raise Exception(f'acados acados_ocp_solver returned status {status}') + + u0 = self.get(0, "u") + return u0 + + + def solve(self): + """ + Solve the ocp with current input. + """ + getattr(self.shared_lib, f"{self.model_name}_acados_solve").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_solve").restype = c_int + self.status = getattr(self.shared_lib, f"{self.model_name}_acados_solve")(self.capsule) + + return self.status + + + def custom_update(self, data_: np.ndarray): + """ + A custom function that can be implemented by a user to be called between solver calls. + By default this does nothing. + The idea is to have a convenient wrapper to do complex updates of parameters and numerical data efficiently in C, + in a function that is compiled into the solver library and can be conveniently used in the Python environment. + """ + data = np.ascontiguousarray(data_, dtype=np.float64) + c_data = cast(data.ctypes.data, POINTER(c_double)) + data_len = len(data) + + getattr(self.shared_lib, f"{self.model_name}_acados_custom_update").argtypes = [c_void_p, POINTER(c_double), c_int] + getattr(self.shared_lib, f"{self.model_name}_acados_custom_update").restype = c_int + status = getattr(self.shared_lib, f"{self.model_name}_acados_custom_update")(self.capsule, c_data, data_len) + + return status + + + def reset(self, reset_qp_solver_mem=1): + """ + Sets current iterate to all zeros. + """ + getattr(self.shared_lib, f"{self.model_name}_acados_reset").argtypes = [c_void_p, c_int] + getattr(self.shared_lib, f"{self.model_name}_acados_reset").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_reset")(self.capsule, reset_qp_solver_mem) + + return + + + def set_new_time_steps(self, new_time_steps): + """ + Set new time steps. + Recreates the solver if N changes. + + :param new_time_steps: 1 dimensional np array of new time steps for the solver + + .. note:: This allows for different use-cases: either set a new size of time_steps or a new distribution of + the shooting nodes without changing the number, e.g., to reach a different final time. Both cases + do not require a new code export and compilation. + """ + + # unlikely but still possible + if not self.solver_created: + raise Exception('Solver was not yet created!') + + # check if time steps really changed in value + if np.array_equal(self.solver_options['time_steps'], new_time_steps): + return + + N = new_time_steps.size + new_time_steps_data = cast(new_time_steps.ctypes.data, POINTER(c_double)) + + # check if recreation of acados is necessary (no need to recreate acados if sizes are identical) + if len(self.solver_options['time_steps']) == N: + getattr(self.shared_lib, f"{self.model_name}_acados_update_time_steps").argtypes = [c_void_p, c_int, c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_update_time_steps").restype = c_int + assert getattr(self.shared_lib, f"{self.model_name}_acados_update_time_steps")(self.capsule, N, new_time_steps_data) == 0 + else: # recreate the solver with the new time steps + self.solver_created = False + + # delete old memory (analog to __del__) + getattr(self.shared_lib, f"{self.model_name}_acados_free").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_free").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_free")(self.capsule) + + # create solver with new time steps + getattr(self.shared_lib, f"{self.model_name}_acados_create_with_discretization").argtypes = [c_void_p, c_int, c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_create_with_discretization").restype = c_int + assert getattr(self.shared_lib, f"{self.model_name}_acados_create_with_discretization")(self.capsule, N, new_time_steps_data) == 0 + + self.solver_created = True + + # get pointers solver + self.__get_pointers_solver() + + # store time_steps, N + self.solver_options['time_steps'] = new_time_steps + self.N = N + self.solver_options['Tsim'] = self.solver_options['time_steps'][0] + + + def update_qp_solver_cond_N(self, qp_solver_cond_N: int): + """ + Recreate solver with new value `qp_solver_cond_N` with a partial condensing QP solver. + This function is relevant for code reuse, i.e., if either `set_new_time_steps(...)` is used or + the influence of a different `qp_solver_cond_N` is studied without code export and compilation. + :param qp_solver_cond_N: new number of condensing stages for the solver + + .. note:: This function can only be used in combination with a partial condensing QP solver. + + .. note:: After `set_new_time_steps(...)` is used and depending on the new number of time steps it might be + necessary to change `qp_solver_cond_N` as well (using this function), i.e., typically + `qp_solver_cond_N < N`. + """ + # unlikely but still possible + if not self.solver_created: + raise Exception('Solver was not yet created!') + if self.N < qp_solver_cond_N: + raise Exception('Setting qp_solver_cond_N to be larger than N does not work!') + if self.solver_options['qp_solver_cond_N'] != qp_solver_cond_N: + self.solver_created = False + + # recreate the solver + fun_name = f'{self.model_name}_acados_update_qp_solver_cond_N' + getattr(self.shared_lib, fun_name).argtypes = [c_void_p, c_int] + getattr(self.shared_lib, fun_name).restype = c_int + assert getattr(self.shared_lib, fun_name)(self.capsule, qp_solver_cond_N) == 0 + + # store the new value + self.solver_options['qp_solver_cond_N'] = qp_solver_cond_N + self.solver_created = True + + # get pointers solver + self.__get_pointers_solver() + + + def eval_param_sens(self, index, stage=0, field="ex"): + """ + Calculate the sensitivity of the curent solution with respect to the initial state component of index + + :param index: integer corresponding to initial state index in range(nx) + """ + + field_ = field + field = field_.encode('utf-8') + + # checks + if not isinstance(index, int): + raise Exception('AcadosOcpSolver.eval_param_sens(): index must be Integer.') + + self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = [c_void_p, c_void_p, c_void_p, c_int, c_char_p] + self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int + nx = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, self.nlp_dims, self.nlp_out, 0, "x".encode('utf-8')) + + if index < 0 or index > nx: + raise Exception(f'AcadosOcpSolver.eval_param_sens(): index must be in [0, nx-1], got: {index}.') + + # actual eval_param + self.shared_lib.ocp_nlp_eval_param_sens.argtypes = [c_void_p, c_char_p, c_int, c_int, c_void_p] + self.shared_lib.ocp_nlp_eval_param_sens.restype = None + self.shared_lib.ocp_nlp_eval_param_sens(self.nlp_solver, field, stage, index, self.sens_out) + + return + + + def get(self, stage_, field_): + """ + Get the last solution of the solver: + + :param stage: integer corresponding to shooting node + :param field: string in ['x', 'u', 'z', 'pi', 'lam', 't', 'sl', 'su',] + + .. note:: regarding lam, t: \n + the inequalities are internally organized in the following order: \n + [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n + lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi] + + .. note:: pi: multipliers for dynamics equality constraints \n + lam: multipliers for inequalities \n + t: slack variables corresponding to evaluation of all inequalities (at the solution) \n + sl: slack variables of soft lower inequality constraints \n + su: slack variables of soft upper inequality constraints \n + """ + + out_fields = ['x', 'u', 'z', 'pi', 'lam', 't', 'sl', 'su'] + # mem_fields = ['sl', 'su'] + sens_fields = ['sens_u', "sens_x"] + all_fields = out_fields + sens_fields + + field = field_ + + if (field_ not in all_fields): + raise Exception(f'AcadosOcpSolver.get(stage={stage_}, field={field_}): \'{field_}\' is an invalid argument.\ + \n Possible values are {all_fields}.') + + if not isinstance(stage_, int): + raise Exception(f'AcadosOcpSolver.get(stage={stage_}, field={field_}): stage index must be an integer, got type {type(stage_)}.') + + if stage_ < 0 or stage_ > self.N: + raise Exception(f'AcadosOcpSolver.get(stage={stage_}, field={field_}): stage index must be in [0, {self.N}], got: {stage_}.') + + if stage_ == self.N and field_ == 'pi': + raise Exception(f'AcadosOcpSolver.get(stage={stage_}, field={field_}): field \'{field_}\' does not exist at final stage {stage_}.') + + if field_ in sens_fields: + field = field_.replace('sens_', '') + + field = field.encode('utf-8') + + self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p] + self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int + + dims = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage_, field) + + out = np.ascontiguousarray(np.zeros((dims,)), dtype=np.float64) + out_data = cast(out.ctypes.data, POINTER(c_double)) + + if (field_ in out_fields): + self.shared_lib.ocp_nlp_out_get.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_out_get(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage_, field, out_data) + # elif field_ in mem_fields: + # self.shared_lib.ocp_nlp_get_at_stage.argtypes = \ + # [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + # self.shared_lib.ocp_nlp_get_at_stage(self.nlp_config, \ + # self.nlp_dims, self.nlp_solver, stage_, field, out_data) + elif field_ in sens_fields: + self.shared_lib.ocp_nlp_out_get.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_out_get(self.nlp_config, \ + self.nlp_dims, self.sens_out, stage_, field, out_data) + + return out + + + def print_statistics(self): + """ + prints statistics of previous solver run as a table: + - iter: iteration number + - res_stat: stationarity residual + - res_eq: residual wrt equality constraints (dynamics) + - res_ineq: residual wrt inequality constraints (constraints) + - res_comp: residual wrt complementarity conditions + - qp_stat: status of QP solver + - qp_iter: number of QP iterations + - alpha: SQP step size + - qp_res_stat: stationarity residual of the last QP solution + - qp_res_eq: residual wrt equality constraints (dynamics) of the last QP solution + - qp_res_ineq: residual wrt inequality constraints (constraints) of the last QP solution + - qp_res_comp: residual wrt complementarity conditions of the last QP solution + """ + stat = self.get_stats("statistics") + + if self.solver_options['nlp_solver_type'] == 'SQP': + print('\niter\tres_stat\tres_eq\t\tres_ineq\tres_comp\tqp_stat\tqp_iter\talpha') + if stat.shape[0]>8: + print('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp') + for jj in range(stat.shape[1]): + print(f'{int(stat[0][jj]):d}\t{stat[1][jj]:e}\t{stat[2][jj]:e}\t{stat[3][jj]:e}\t' + + f'{stat[4][jj]:e}\t{int(stat[5][jj]):d}\t{int(stat[6][jj]):d}\t{stat[7][jj]:e}\t') + if stat.shape[0]>8: + print('\t{:e}\t{:e}\t{:e}\t{:e}'.format( \ + stat[8][jj], stat[9][jj], stat[10][jj], stat[11][jj])) + print('\n') + elif self.solver_options['nlp_solver_type'] == 'SQP_RTI': + print('\niter\tqp_stat\tqp_iter') + if stat.shape[0]>3: + print('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp') + for jj in range(stat.shape[1]): + print('{:d}\t{:d}\t{:d}'.format( int(stat[0][jj]), int(stat[1][jj]), int(stat[2][jj]))) + if stat.shape[0]>3: + print('\t{:e}\t{:e}\t{:e}\t{:e}'.format( \ + stat[3][jj], stat[4][jj], stat[5][jj], stat[6][jj])) + print('\n') + + return + + + def store_iterate(self, filename: str = '', overwrite=False): + """ + Stores the current iterate of the ocp solver in a json file. + + :param filename: if not set, use f'{self.model_name}_iterate.json' + :param overwrite: if false and filename exists add timestamp to filename + """ + if filename == '': + filename = f'{self.model_name}_iterate.json' + + if not overwrite: + # append timestamp + if os.path.isfile(filename): + filename = filename[:-5] + filename += datetime.utcnow().strftime('%Y-%m-%d-%H:%M:%S.%f') + '.json' + + # get iterate: + solution = dict() + + lN = len(str(self.N+1)) + for i in range(self.N+1): + i_string = f'{i:0{lN}d}' + solution['x_'+i_string] = self.get(i,'x') + solution['u_'+i_string] = self.get(i,'u') + solution['z_'+i_string] = self.get(i,'z') + solution['lam_'+i_string] = self.get(i,'lam') + solution['t_'+i_string] = self.get(i, 't') + solution['sl_'+i_string] = self.get(i, 'sl') + solution['su_'+i_string] = self.get(i, 'su') + if i < self.N: + solution['pi_'+i_string] = self.get(i,'pi') + + for k in list(solution.keys()): + if len(solution[k]) == 0: + del solution[k] + + # save + with open(filename, 'w') as f: + json.dump(solution, f, default=make_object_json_dumpable, indent=4, sort_keys=True) + print("stored current iterate in ", os.path.join(os.getcwd(), filename)) + + + + def dump_last_qp_to_json(self, filename: str = '', overwrite=False): + """ + Dumps the latest QP data into a json file + + :param filename: if not set, use model_name + timestamp + '.json' + :param overwrite: if false and filename exists add timestamp to filename + """ + if filename == '': + filename = f'{self.model_name}_QP.json' + + if not overwrite: + # append timestamp + if os.path.isfile(filename): + filename = filename[:-5] + filename += datetime.utcnow().strftime('%Y-%m-%d-%H:%M:%S.%f') + '.json' + + # get QP data: + qp_data = dict() + + lN = len(str(self.N+1)) + for field in self.__qp_dynamics_fields: + for i in range(self.N): + qp_data[f'{field}_{i:0{lN}d}'] = self.get_from_qp_in(i,field) + + for field in self.__qp_constraint_fields + self.__qp_cost_fields: + for i in range(self.N+1): + qp_data[f'{field}_{i:0{lN}d}'] = self.get_from_qp_in(i,field) + + # remove empty fields + for k in list(qp_data.keys()): + if len(qp_data[k]) == 0: + del qp_data[k] + + # save + with open(filename, 'w') as f: + json.dump(qp_data, f, default=make_object_json_dumpable, indent=4, sort_keys=True) + print("stored qp from solver memory in ", os.path.join(os.getcwd(), filename)) + + + + def load_iterate(self, filename): + """ + Loads the iterate stored in json file with filename into the ocp solver. + """ + if not os.path.isfile(filename): + raise Exception('load_iterate: failed, file does not exist: ' + os.path.join(os.getcwd(), filename)) + + with open(filename, 'r') as f: + solution = json.load(f) + + print(f"loading iterate {filename}") + for key in solution.keys(): + (field, stage) = key.split('_') + self.set(int(stage), field, np.array(solution[key])) + + + def get_stats(self, field_): + """ + Get the information of the last solver call. + + :param field: string in ['statistics', 'time_tot', 'time_lin', 'time_sim', 'time_sim_ad', 'time_sim_la', 'time_qp', 'time_qp_solver_call', 'time_reg', 'sqp_iter', 'residuals', 'qp_iter', 'alpha'] + + Available fileds: + - time_tot: total CPU time previous call + - time_lin: CPU time for linearization + - time_sim: CPU time for integrator + - time_sim_ad: CPU time for integrator contribution of external function calls + - time_sim_la: CPU time for integrator contribution of linear algebra + - time_qp: CPU time qp solution + - time_qp_solver_call: CPU time inside qp solver (without converting the QP) + - time_qp_xcond: time_glob: CPU time globalization + - time_solution_sensitivities: CPU time for previous call to eval_param_sens + - time_reg: CPU time regularization + - sqp_iter: number of SQP iterations + - qp_iter: vector of QP iterations for last SQP call + - statistics: table with info about last iteration + - stat_m: number of rows in statistics matrix + - stat_n: number of columns in statistics matrix + - residuals: residuals of last iterate + - alpha: step sizes of SQP iterations + """ + + double_fields = ['time_tot', + 'time_lin', + 'time_sim', + 'time_sim_ad', + 'time_sim_la', + 'time_qp', + 'time_qp_solver_call', + 'time_qp_xcond', + 'time_glob', + 'time_solution_sensitivities', + 'time_reg' + ] + fields = double_fields + [ + 'sqp_iter', + 'qp_iter', + 'statistics', + 'stat_m', + 'stat_n', + 'residuals', + 'alpha', + ] + field = field_.encode('utf-8') + + + if field_ in ['sqp_iter', 'stat_m', 'stat_n']: + out = np.ascontiguousarray(np.zeros((1,)), dtype=np.int64) + out_data = cast(out.ctypes.data, POINTER(c_int64)) + self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + return out + + # TODO: just return double instead of np. + elif field_ in double_fields: + out = np.zeros((1,)) + out_data = cast(out.ctypes.data, POINTER(c_double)) + self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + return out + + elif field_ == 'statistics': + sqp_iter = self.get_stats("sqp_iter") + stat_m = self.get_stats("stat_m") + stat_n = self.get_stats("stat_n") + min_size = min([stat_m, sqp_iter+1]) + out = np.ascontiguousarray( + np.zeros((stat_n[0]+1, min_size[0])), dtype=np.float64) + out_data = cast(out.ctypes.data, POINTER(c_double)) + self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + return out + + elif field_ == 'qp_iter': + full_stats = self.get_stats('statistics') + if self.solver_options['nlp_solver_type'] == 'SQP': + return full_stats[6, :] + elif self.solver_options['nlp_solver_type'] == 'SQP_RTI': + return full_stats[2, :] + + elif field_ == 'alpha': + full_stats = self.get_stats('statistics') + if self.solver_options['nlp_solver_type'] == 'SQP': + return full_stats[7, :] + else: # self.solver_options['nlp_solver_type'] == 'SQP_RTI': + raise Exception("alpha values are not available for SQP_RTI") + + elif field_ == 'residuals': + return self.get_residuals() + + else: + raise Exception(f'AcadosOcpSolver.get_stats(): \'{field}\' is not a valid argument.' + + f'\n Possible values are {fields}.') + + + def get_cost(self): + """ + Returns the cost value of the current solution. + """ + # compute cost internally + self.shared_lib.ocp_nlp_eval_cost.argtypes = [c_void_p, c_void_p, c_void_p] + self.shared_lib.ocp_nlp_eval_cost(self.nlp_solver, self.nlp_in, self.nlp_out) + + # create output array + out = np.ascontiguousarray(np.zeros((1,)), dtype=np.float64) + out_data = cast(out.ctypes.data, POINTER(c_double)) + + # call getter + self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p] + + field = "cost_value".encode('utf-8') + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + + return out[0] + + + def get_residuals(self, recompute=False): + """ + Returns an array of the form [res_stat, res_eq, res_ineq, res_comp]. + This residual has to be computed for SQP_RTI solver, since it is not available by default. + + - res_stat: stationarity residual + - res_eq: residual wrt equality constraints (dynamics) + - res_ineq: residual wrt inequality constraints (constraints) + - res_comp: residual wrt complementarity conditions + """ + # compute residuals if RTI + if self.solver_options['nlp_solver_type'] == 'SQP_RTI' or recompute: + self.shared_lib.ocp_nlp_eval_residuals.argtypes = [c_void_p, c_void_p, c_void_p] + self.shared_lib.ocp_nlp_eval_residuals(self.nlp_solver, self.nlp_in, self.nlp_out) + + # create output array + out = np.ascontiguousarray(np.zeros((4, 1)), dtype=np.float64) + out_data = cast(out.ctypes.data, POINTER(c_double)) + + # call getters + self.shared_lib.ocp_nlp_get.argtypes = [c_void_p, c_void_p, c_char_p, c_void_p] + + field = "res_stat".encode('utf-8') + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + + out_data = cast(out[1].ctypes.data, POINTER(c_double)) + field = "res_eq".encode('utf-8') + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + + out_data = cast(out[2].ctypes.data, POINTER(c_double)) + field = "res_ineq".encode('utf-8') + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + + out_data = cast(out[3].ctypes.data, POINTER(c_double)) + field = "res_comp".encode('utf-8') + self.shared_lib.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_data) + return out.flatten() + + + # Note: this function should not be used anymore, better use cost_set, constraints_set + def set(self, stage_, field_, value_): + """ + Set numerical data inside the solver. + + :param stage: integer corresponding to shooting node + :param field: string in ['x', 'u', 'pi', 'lam', 't', 'p', 'xdot_guess', 'z_guess'] + + .. note:: regarding lam, t: \n + the inequalities are internally organized in the following order: \n + [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n + lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi] + + .. note:: pi: multipliers for dynamics equality constraints \n + lam: multipliers for inequalities \n + t: slack variables corresponding to evaluation of all inequalities (at the solution) \n + sl: slack variables of soft lower inequality constraints \n + su: slack variables of soft upper inequality constraints \n + """ + cost_fields = ['y_ref', 'yref'] + constraints_fields = ['lbx', 'ubx', 'lbu', 'ubu'] + out_fields = ['x', 'u', 'pi', 'lam', 't', 'z', 'sl', 'su'] + mem_fields = ['xdot_guess', 'z_guess'] + + # cast value_ to avoid conversion issues + if isinstance(value_, (float, int)): + value_ = np.array([value_]) + value_ = value_.astype(float) + + field = field_.encode('utf-8') + + stage = c_int(stage_) + + # treat parameters separately + if field_ == 'p': + getattr(self.shared_lib, f"{self.model_name}_acados_update_params").argtypes = [c_void_p, c_int, POINTER(c_double), c_int] + getattr(self.shared_lib, f"{self.model_name}_acados_update_params").restype = c_int + + value_data = cast(value_.ctypes.data, POINTER(c_double)) + + assert getattr(self.shared_lib, f"{self.model_name}_acados_update_params")(self.capsule, stage, value_data, value_.shape[0])==0 + else: + if field_ not in constraints_fields + cost_fields + out_fields + mem_fields: + raise Exception(f"AcadosOcpSolver.set(): '{field}' is not a valid argument.\n" + f" Possible values are {constraints_fields + cost_fields + out_fields + mem_fields + ['p']}.") + + self.shared_lib.ocp_nlp_dims_get_from_attr.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p] + self.shared_lib.ocp_nlp_dims_get_from_attr.restype = c_int + + dims = self.shared_lib.ocp_nlp_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage_, field) + + if value_.shape[0] != dims: + msg = f'AcadosOcpSolver.set(): mismatching dimension for field "{field_}" ' + msg += f'with dimension {dims} (you have {value_.shape[0]})' + raise Exception(msg) + + value_data = cast(value_.ctypes.data, POINTER(c_double)) + value_data_p = cast((value_data), c_void_p) + + if field_ in constraints_fields: + self.shared_lib.ocp_nlp_constraints_model_set.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_constraints_model_set(self.nlp_config, \ + self.nlp_dims, self.nlp_in, stage, field, value_data_p) + elif field_ in cost_fields: + self.shared_lib.ocp_nlp_cost_model_set.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_cost_model_set(self.nlp_config, \ + self.nlp_dims, self.nlp_in, stage, field, value_data_p) + elif field_ in out_fields: + self.shared_lib.ocp_nlp_out_set.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_out_set(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage, field, value_data_p) + elif field_ in mem_fields: + self.shared_lib.ocp_nlp_set.argtypes = \ + [c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_set(self.nlp_config, \ + self.nlp_solver, stage, field, value_data_p) + # also set z_guess, when setting z. + if field_ == 'z': + field = 'z_guess'.encode('utf-8') + self.shared_lib.ocp_nlp_set.argtypes = \ + [c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_set(self.nlp_config, \ + self.nlp_solver, stage, field, value_data_p) + return + + + def cost_set(self, stage_, field_, value_, api='warn'): + """ + Set numerical data in the cost module of the solver. + + :param stage: integer corresponding to shooting node + :param field: string, e.g. 'yref', 'W', 'ext_cost_num_hess', 'zl', 'zu', 'Zl', 'Zu' + :param value: of appropriate size + """ + # cast value_ to avoid conversion issues + if isinstance(value_, (float, int)): + value_ = np.array([value_]) + value_ = value_.astype(float) + + field = field_ + field = field.encode('utf-8') + + stage = c_int(stage_) + self.shared_lib.ocp_nlp_cost_dims_get_from_attr.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)] + self.shared_lib.ocp_nlp_cost_dims_get_from_attr.restype = c_int + + dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc) + dims_data = cast(dims.ctypes.data, POINTER(c_int)) + + self.shared_lib.ocp_nlp_cost_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage_, field, dims_data) + + value_shape = value_.shape + if len(value_shape) == 1: + value_shape = (value_shape[0], 0) + + elif len(value_shape) == 2: + if api=='old': + pass + elif api=='warn': + if not np.all(np.ravel(value_, order='F')==np.ravel(value_, order='K')): + raise Exception("Ambiguity in API detected.\n" + "Are you making an acados model from scrach? Add api='new' to cost_set and carry on.\n" + "Are you seeing this error suddenly in previously running code? Read on.\n" + f" You are relying on a now-fixed bug in cost_set for field '{field_}'.\n" + + " acados_template now correctly passes on any matrices to acados in column major format.\n" + + " Two options to fix this error: \n" + + " * Add api='old' to cost_set to restore old incorrect behaviour\n" + + " * Add api='new' to cost_set and remove any unnatural manipulation of the value argument " + + "such as non-mathematical transposes, reshaping, casting to fortran order, etc... " + + "If there is no such manipulation, then you have probably been getting an incorrect solution before.") + # Get elements in column major order + value_ = np.ravel(value_, order='F') + elif api=='new': + # Get elements in column major order + value_ = np.ravel(value_, order='F') + else: + raise Exception("Unknown api: '{}'".format(api)) + + if value_shape != tuple(dims): + raise Exception('AcadosOcpSolver.cost_set(): mismatching dimension' + + f' for field "{field_}" at stage {stage} with dimension {tuple(dims)} (you have {value_shape})') + + value_data = cast(value_.ctypes.data, POINTER(c_double)) + value_data_p = cast((value_data), c_void_p) + + self.shared_lib.ocp_nlp_cost_model_set.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_cost_model_set(self.nlp_config, \ + self.nlp_dims, self.nlp_in, stage, field, value_data_p) + + return + + + def constraints_set(self, stage_, field_, value_, api='warn'): + """ + Set numerical data in the constraint module of the solver. + + :param stage: integer corresponding to shooting node + :param field: string in ['lbx', 'ubx', 'lbu', 'ubu', 'lg', 'ug', 'lh', 'uh', 'uphi', 'C', 'D'] + :param value: of appropriate size + """ + # cast value_ to avoid conversion issues + if isinstance(value_, (float, int)): + value_ = np.array([value_]) + value_ = value_.astype(float) + + field = field_ + field = field.encode('utf-8') + + stage = c_int(stage_) + self.shared_lib.ocp_nlp_constraint_dims_get_from_attr.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)] + self.shared_lib.ocp_nlp_constraint_dims_get_from_attr.restype = c_int + + dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc) + dims_data = cast(dims.ctypes.data, POINTER(c_int)) + + self.shared_lib.ocp_nlp_constraint_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage_, field, dims_data) + + value_shape = value_.shape + if len(value_shape) == 1: + value_shape = (value_shape[0], 0) + elif len(value_shape) == 2: + if api=='old': + pass + elif api=='warn': + if not np.all(np.ravel(value_, order='F')==np.ravel(value_, order='K')): + raise Exception("Ambiguity in API detected.\n" + "Are you making an acados model from scrach? Add api='new' to constraints_set and carry on.\n" + "Are you seeing this error suddenly in previously running code? Read on.\n" + f" You are relying on a now-fixed bug in constraints_set for field '{field}'.\n" + + " acados_template now correctly passes on any matrices to acados in column major format.\n" + + " Two options to fix this error: \n" + + " * Add api='old' to constraints_set to restore old incorrect behaviour\n" + + " * Add api='new' to constraints_set and remove any unnatural manipulation of the value argument " + + "such as non-mathematical transposes, reshaping, casting to fortran order, etc... " + + "If there is no such manipulation, then you have probably been getting an incorrect solution before.") + # Get elements in column major order + value_ = np.ravel(value_, order='F') + elif api=='new': + # Get elements in column major order + value_ = np.ravel(value_, order='F') + else: + raise Exception(f"Unknown api: '{api}'") + + if value_shape != tuple(dims): + raise Exception(f'AcadosOcpSolver.constraints_set(): mismatching dimension' + + f' for field "{field_}" at stage {stage} with dimension {tuple(dims)} (you have {value_shape})') + + value_data = cast(value_.ctypes.data, POINTER(c_double)) + value_data_p = cast((value_data), c_void_p) + + self.shared_lib.ocp_nlp_constraints_model_set.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_constraints_model_set(self.nlp_config, \ + self.nlp_dims, self.nlp_in, stage, field, value_data_p) + + return + + + def get_from_qp_in(self, stage_: int, field_: str): + """ + Get numerical data from the current QP. + + :param stage: integer corresponding to shooting node + :param field: string in ['A', 'B', 'b', 'Q', 'R', 'S', 'q', 'r', 'C', 'D', 'lg', 'ug', 'lbx', 'ubx', 'lbu', 'ubu'] + """ + # idx* should be added too.. + if not isinstance(stage_, int): + raise TypeError("stage should be int") + if stage_ > self.N: + raise Exception("stage should be <= self.N") + if field_ in self.__qp_dynamics_fields and stage_ >= self.N: + raise ValueError(f"dynamics field {field_} not available at terminal stage") + if field_ not in self.__qp_dynamics_fields + self.__qp_cost_fields + self.__qp_constraint_fields: + raise Exception(f"field {field_} not supported.") + + field = field_.encode('utf-8') + stage = c_int(stage_) + + # get dims + self.shared_lib.ocp_nlp_qp_dims_get_from_attr.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, POINTER(c_int)] + self.shared_lib.ocp_nlp_qp_dims_get_from_attr.restype = c_int + + dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc) + dims_data = cast(dims.ctypes.data, POINTER(c_int)) + + self.shared_lib.ocp_nlp_qp_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage_, field, dims_data) + + # create output data + out = np.ascontiguousarray(np.zeros((np.prod(dims),)), dtype=np.float64) + out = out.reshape(dims[0], dims[1], order='F') + + out_data = cast(out.ctypes.data, POINTER(c_double)) + out_data_p = cast((out_data), c_void_p) + + # call getter + self.shared_lib.ocp_nlp_get_at_stage.argtypes = \ + [c_void_p, c_void_p, c_void_p, c_int, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_get_at_stage(self.nlp_config, \ + self.nlp_dims, self.nlp_solver, stage, field, out_data_p) + + return out + + + def options_set(self, field_, value_): + """ + Set options of the solver. + + :param field: string, e.g. 'print_level', 'rti_phase', 'initialize_t_slacks', 'step_length', 'alpha_min', 'alpha_reduction', 'qp_warm_start', 'line_search_use_sufficient_descent', 'full_step_dual', 'globalization_use_SOC', 'qp_tol_stat', 'qp_tol_eq', 'qp_tol_ineq', 'qp_tol_comp', 'qp_tau_min', 'qp_mu0' + + :param value: of type int, float, string + + - qp_tol_stat: QP solver tolerance stationarity + - qp_tol_eq: QP solver tolerance equalities + - qp_tol_ineq: QP solver tolerance inequalities + - qp_tol_comp: QP solver tolerance complementarity + - qp_tau_min: for HPIPM QP solvers: minimum value of barrier parameter in HPIPM + - qp_mu0: for HPIPM QP solvers: initial value for complementarity slackness + - warm_start_first_qp: indicates if first QP in SQP is warm_started + """ + int_fields = ['print_level', 'rti_phase', 'initialize_t_slacks', 'qp_warm_start', + 'line_search_use_sufficient_descent', 'full_step_dual', 'globalization_use_SOC', 'warm_start_first_qp'] + double_fields = ['step_length', 'tol_eq', 'tol_stat', 'tol_ineq', 'tol_comp', 'alpha_min', 'alpha_reduction', + 'eps_sufficient_descent', 'qp_tol_stat', 'qp_tol_eq', 'qp_tol_ineq', 'qp_tol_comp', 'qp_tau_min', 'qp_mu0'] + string_fields = ['globalization'] + + # check field availability and type + if field_ in int_fields: + if not isinstance(value_, int): + raise Exception(f'solver option \'{field_}\' must be of type int. You have {type(value_)}.') + else: + value_ctypes = c_int(value_) + + elif field_ in double_fields: + if not isinstance(value_, float): + raise Exception(f'solver option \'{field_}\' must be of type float. You have {type(value_)}.') + else: + value_ctypes = c_double(value_) + + elif field_ in string_fields: + if not isinstance(value_, str): + raise Exception(f'solver option \'{field_}\' must be of type str. You have {type(value_)}.') + else: + value_ctypes = value_.encode('utf-8') + else: + fields = ', '.join(int_fields + double_fields + string_fields) + raise Exception(f'AcadosOcpSolver.options_set() does not support field \'{field_}\'.\n'\ + f' Possible values are {fields}.') + + + if field_ == 'rti_phase': + if value_ < 0 or value_ > 2: + raise Exception('AcadosOcpSolver.options_set(): argument \'rti_phase\' can ' + 'take only values 0, 1, 2 for SQP-RTI-type solvers') + if self.solver_options['nlp_solver_type'] != 'SQP_RTI' and value_ > 0: + raise Exception('AcadosOcpSolver.options_set(): argument \'rti_phase\' can ' + 'take only value 0 for SQP-type solvers') + + # encode + field = field_ + field = field.encode('utf-8') + + # call C interface + if field_ in string_fields: + self.shared_lib.ocp_nlp_solver_opts_set.argtypes = \ + [c_void_p, c_void_p, c_char_p, c_char_p] + self.shared_lib.ocp_nlp_solver_opts_set(self.nlp_config, \ + self.nlp_opts, field, value_ctypes) + else: + self.shared_lib.ocp_nlp_solver_opts_set.argtypes = \ + [c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.ocp_nlp_solver_opts_set(self.nlp_config, \ + self.nlp_opts, field, byref(value_ctypes)) + return + + + def set_params_sparse(self, stage_, idx_values_, param_values_): + """ + set parameters of the solvers external function partially: + Pseudo: solver.param[idx_values_] = param_values_; + Parameters: + :param stage_: integer corresponding to shooting node + :param idx_values_: 0 based np array (or iterable) of integers: indices of parameter to be set + :param param_values_: new parameter values as numpy array + """ + + # if not isinstance(idx_values_, np.ndarray) or not issubclass(type(idx_values_[0]), np.integer): + # raise Exception('idx_values_ must be np.array of integers.') + + if not isinstance(param_values_, np.ndarray): + raise Exception('param_values_ must be np.array.') + elif np.float64 != param_values_.dtype: + raise TypeError('param_values_ must be np.array of float64.') + + if param_values_.shape[0] != len(idx_values_): + raise Exception(f'param_values_ and idx_values_ must be of the same size.' + + f' Got sizes idx {param_values_.shape[0]}, param_values {len(idx_values_)}.') + + if any(idx_values_ >= self.acados_ocp.dims.np): + raise Exception(f'idx_values_ contains value >= np = {self.acados_ocp.dims.np}') + + stage = c_int(stage_) + n_update = c_int(len(param_values_)) + + param_data = cast(param_values_.ctypes.data, POINTER(c_double)) + c_idx_values = np.ascontiguousarray(idx_values_, dtype=np.intc) + idx_data = cast(c_idx_values.ctypes.data, POINTER(c_int)) + + getattr(self.shared_lib, f"{self.model_name}_acados_update_params_sparse").argtypes = \ + [c_void_p, c_int, POINTER(c_int), POINTER(c_double), c_int] + getattr(self.shared_lib, f"{self.model_name}_acados_update_params_sparse").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_update_params_sparse") \ + (self.capsule, stage, idx_data, param_data, n_update) + + def __del__(self): + if self.solver_created: + getattr(self.shared_lib, f"{self.model_name}_acados_free").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_free").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_free")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_free_capsule").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_free_capsule").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_free_capsule")(self.capsule) + + try: + self.dlclose(self.shared_lib._handle) + except: + print(f"WARNING: acados Python interface could not close shared_lib handle of AcadosOcpSolver {self.model_name}.\n", + "Attempting to create a new one with the same name will likely result in the old one being used!") + pass diff --git a/third_party/acados/acados_template/acados_ocp_solver_pyx.pyx b/third_party/acados/acados_template/acados_ocp_solver_pyx.pyx new file mode 100644 index 0000000000..acd7f02d0a --- /dev/null +++ b/third_party/acados/acados_template/acados_ocp_solver_pyx.pyx @@ -0,0 +1,795 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# cython: language_level=3 +# cython: profile=False +# distutils: language=c + +cimport cython +from libc cimport string + +cimport acados_solver_common +# TODO: make this import more clear? it is not a general solver, but problem specific. +cimport acados_solver + +cimport numpy as cnp + +import os +from datetime import datetime +import numpy as np + + +cdef class AcadosOcpSolverCython: + """ + Class to interact with the acados ocp solver C object. + """ + + cdef acados_solver.nlp_solver_capsule *capsule + cdef void *nlp_opts + cdef acados_solver_common.ocp_nlp_dims *nlp_dims + cdef acados_solver_common.ocp_nlp_config *nlp_config + cdef acados_solver_common.ocp_nlp_out *nlp_out + cdef acados_solver_common.ocp_nlp_out *sens_out + cdef acados_solver_common.ocp_nlp_in *nlp_in + cdef acados_solver_common.ocp_nlp_solver *nlp_solver + + cdef bint solver_created + + cdef str model_name + cdef int N + + cdef str nlp_solver_type + + def __cinit__(self, model_name, nlp_solver_type, N): + + self.solver_created = False + + self.N = N + self.model_name = model_name + self.nlp_solver_type = nlp_solver_type + + # create capsule + self.capsule = acados_solver.acados_create_capsule() + + # create solver + assert acados_solver.acados_create(self.capsule) == 0 + self.solver_created = True + + # get pointers solver + self.__get_pointers_solver() + + + def __get_pointers_solver(self): + """ + Private function to get the pointers for solver + """ + # get pointers solver + self.nlp_opts = acados_solver.acados_get_nlp_opts(self.capsule) + self.nlp_dims = acados_solver.acados_get_nlp_dims(self.capsule) + self.nlp_config = acados_solver.acados_get_nlp_config(self.capsule) + self.nlp_out = acados_solver.acados_get_nlp_out(self.capsule) + self.sens_out = acados_solver.acados_get_sens_out(self.capsule) + self.nlp_in = acados_solver.acados_get_nlp_in(self.capsule) + self.nlp_solver = acados_solver.acados_get_nlp_solver(self.capsule) + + + def solve_for_x0(self, x0_bar): + """ + Wrapper around `solve()` which sets initial state constraint, solves the OCP, and returns u0. + """ + self.set(0, "lbx", x0_bar) + self.set(0, "ubx", x0_bar) + + status = self.solve() + + if status == 2: + print("Warning: acados_ocp_solver reached maximum iterations.") + elif status != 0: + raise Exception(f'acados acados_ocp_solver returned status {status}') + + u0 = self.get(0, "u") + return u0 + + + def solve(self): + """ + Solve the ocp with current input. + """ + return acados_solver.acados_solve(self.capsule) + + + def reset(self, reset_qp_solver_mem=1): + """ + Sets current iterate to all zeros. + """ + return acados_solver.acados_reset(self.capsule, reset_qp_solver_mem) + + + def custom_update(self, data_): + """ + A custom function that can be implemented by a user to be called between solver calls. + By default this does nothing. + The idea is to have a convenient wrapper to do complex updates of parameters and numerical data efficiently in C, + in a function that is compiled into the solver library and can be conveniently used in the Python environment. + """ + data_len = len(data_) + cdef cnp.ndarray[cnp.float64_t, ndim=1] data = np.ascontiguousarray(data_, dtype=np.float64) + + return acados_solver.acados_custom_update(self.capsule, data.data, data_len) + + + def set_new_time_steps(self, new_time_steps): + """ + Set new time steps. + Recreates the solver if N changes. + + :param new_time_steps: 1 dimensional np array of new time steps for the solver + + .. note:: This allows for different use-cases: either set a new size of time-steps or a new distribution of + the shooting nodes without changing the number, e.g., to reach a different final time. Both cases + do not require a new code export and compilation. + """ + + raise NotImplementedError("AcadosOcpSolverCython: does not support set_new_time_steps() since it is only a prototyping feature") + # # unlikely but still possible + # if not self.solver_created: + # raise Exception('Solver was not yet created!') + + # ## check if time steps really changed in value + # # get time steps + # cdef cnp.ndarray[cnp.float64_t, ndim=1] old_time_steps = np.ascontiguousarray(np.zeros((self.N,)), dtype=np.float64) + # assert acados_solver.acados_get_time_steps(self.capsule, self.N, old_time_steps.data) + + # if np.array_equal(old_time_steps, new_time_steps): + # return + + # N = new_time_steps.size + # cdef cnp.ndarray[cnp.float64_t, ndim=1] value = np.ascontiguousarray(new_time_steps, dtype=np.float64) + + # # check if recreation of acados is necessary (no need to recreate acados if sizes are identical) + # if len(old_time_steps) == N: + # assert acados_solver.acados_update_time_steps(self.capsule, N, value.data) == 0 + + # else: # recreate the solver with the new time steps + # self.solver_created = False + + # # delete old memory (analog to __del__) + # acados_solver.acados_free(self.capsule) + + # # create solver with new time steps + # assert acados_solver.acados_create_with_discretization(self.capsule, N, value.data) == 0 + + # self.solver_created = True + + # # get pointers solver + # self.__get_pointers_solver() + + # # store time_steps, N + # self.time_steps = new_time_steps + # self.N = N + + + def update_qp_solver_cond_N(self, qp_solver_cond_N: int): + """ + Recreate solver with new value `qp_solver_cond_N` with a partial condensing QP solver. + This function is relevant for code reuse, i.e., if either `set_new_time_steps(...)` is used or + the influence of a different `qp_solver_cond_N` is studied without code export and compilation. + :param qp_solver_cond_N: new number of condensing stages for the solver + + .. note:: This function can only be used in combination with a partial condensing QP solver. + + .. note:: After `set_new_time_steps(...)` is used and depending on the new number of time steps it might be + necessary to change `qp_solver_cond_N` as well (using this function), i.e., typically + `qp_solver_cond_N < N`. + """ + raise NotImplementedError("AcadosOcpSolverCython: does not support update_qp_solver_cond_N() since it is only a prototyping feature") + + # # unlikely but still possible + # if not self.solver_created: + # raise Exception('Solver was not yet created!') + # if self.N < qp_solver_cond_N: + # raise Exception('Setting qp_solver_cond_N to be larger than N does not work!') + # if self.qp_solver_cond_N != qp_solver_cond_N: + # self.solver_created = False + + # # recreate the solver + # acados_solver.acados_update_qp_solver_cond_N(self.capsule, qp_solver_cond_N) + + # # store the new value + # self.qp_solver_cond_N = qp_solver_cond_N + # self.solver_created = True + + # # get pointers solver + # self.__get_pointers_solver() + + + def eval_param_sens(self, index, stage=0, field="ex"): + """ + Calculate the sensitivity of the curent solution with respect to the initial state component of index + + :param index: integer corresponding to initial state index in range(nx) + """ + + field_ = field + field = field_.encode('utf-8') + + # checks + if not isinstance(index, int): + raise Exception('AcadosOcpSolverCython.eval_param_sens(): index must be Integer.') + + cdef int nx = acados_solver_common.ocp_nlp_dims_get_from_attr(self.nlp_config, self.nlp_dims, self.nlp_out, 0, "x".encode('utf-8')) + + if index < 0 or index > nx: + raise Exception(f'AcadosOcpSolverCython.eval_param_sens(): index must be in [0, nx-1], got: {index}.') + + # actual eval_param + acados_solver_common.ocp_nlp_eval_param_sens(self.nlp_solver, field, stage, index, self.sens_out) + + return + + + def get(self, int stage, str field_): + """ + Get the last solution of the solver: + + :param stage: integer corresponding to shooting node + :param field: string in ['x', 'u', 'z', 'pi', 'lam', 't', 'sl', 'su',] + + .. note:: regarding lam, t: \n + the inequalities are internally organized in the following order: \n + [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n + lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi] + + .. note:: pi: multipliers for dynamics equality constraints \n + lam: multipliers for inequalities \n + t: slack variables corresponding to evaluation of all inequalities (at the solution) \n + sl: slack variables of soft lower inequality constraints \n + su: slack variables of soft upper inequality constraints \n + """ + + out_fields = ['x', 'u', 'z', 'pi', 'lam', 't', 'sl', 'su'] + field = field_.encode('utf-8') + + if field_ not in out_fields: + raise Exception('AcadosOcpSolverCython.get(): {} is an invalid argument.\ + \n Possible values are {}.'.format(field_, out_fields)) + + if stage < 0 or stage > self.N: + raise Exception('AcadosOcpSolverCython.get(): stage index must be in [0, N], got: {}.'.format(self.N)) + + if stage == self.N and field_ == 'pi': + raise Exception('AcadosOcpSolverCython.get(): field {} does not exist at final stage {}.'\ + .format(field_, stage)) + + cdef int dims = acados_solver_common.ocp_nlp_dims_get_from_attr(self.nlp_config, + self.nlp_dims, self.nlp_out, stage, field) + + cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.zeros((dims,)) + acados_solver_common.ocp_nlp_out_get(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage, field, out.data) + + return out + + + def print_statistics(self): + """ + prints statistics of previous solver run as a table: + - iter: iteration number + - res_stat: stationarity residual + - res_eq: residual wrt equality constraints (dynamics) + - res_ineq: residual wrt inequality constraints (constraints) + - res_comp: residual wrt complementarity conditions + - qp_stat: status of QP solver + - qp_iter: number of QP iterations + - qp_res_stat: stationarity residual of the last QP solution + - qp_res_eq: residual wrt equality constraints (dynamics) of the last QP solution + - qp_res_ineq: residual wrt inequality constraints (constraints) of the last QP solution + - qp_res_comp: residual wrt complementarity conditions of the last QP solution + """ + acados_solver.acados_print_stats(self.capsule) + + + def store_iterate(self, filename='', overwrite=False): + """ + Stores the current iterate of the ocp solver in a json file. + + :param filename: if not set, use model_name + timestamp + '.json' + :param overwrite: if false and filename exists add timestamp to filename + """ + import json + if filename == '': + filename += self.model_name + '_' + 'iterate' + '.json' + + if not overwrite: + # append timestamp + if os.path.isfile(filename): + filename = filename[:-5] + filename += datetime.utcnow().strftime('%Y-%m-%d-%H:%M:%S.%f') + '.json' + + # get iterate: + solution = dict() + + lN = len(str(self.N+1)) + for i in range(self.N+1): + i_string = f'{i:0{lN}d}' + solution['x_'+i_string] = self.get(i,'x') + solution['u_'+i_string] = self.get(i,'u') + solution['z_'+i_string] = self.get(i,'z') + solution['lam_'+i_string] = self.get(i,'lam') + solution['t_'+i_string] = self.get(i, 't') + solution['sl_'+i_string] = self.get(i, 'sl') + solution['su_'+i_string] = self.get(i, 'su') + if i < self.N: + solution['pi_'+i_string] = self.get(i,'pi') + + for k in list(solution.keys()): + if len(solution[k]) == 0: + del solution[k] + + # save + with open(filename, 'w') as f: + json.dump(solution, f, default=lambda x: x.tolist(), indent=4, sort_keys=True) + print("stored current iterate in ", os.path.join(os.getcwd(), filename)) + + + def load_iterate(self, filename): + """ + Loads the iterate stored in json file with filename into the ocp solver. + """ + import json + if not os.path.isfile(filename): + raise Exception('load_iterate: failed, file does not exist: ' + os.path.join(os.getcwd(), filename)) + + with open(filename, 'r') as f: + solution = json.load(f) + + for key in solution.keys(): + (field, stage) = key.split('_') + self.set(int(stage), field, np.array(solution[key])) + + + def get_stats(self, field_): + """ + Get the information of the last solver call. + + :param field: string in ['statistics', 'time_tot', 'time_lin', 'time_sim', 'time_sim_ad', 'time_sim_la', 'time_qp', 'time_qp_solver_call', 'time_reg', 'sqp_iter'] + Available fileds: + - time_tot: total CPU time previous call + - time_lin: CPU time for linearization + - time_sim: CPU time for integrator + - time_sim_ad: CPU time for integrator contribution of external function calls + - time_sim_la: CPU time for integrator contribution of linear algebra + - time_qp: CPU time qp solution + - time_qp_solver_call: CPU time inside qp solver (without converting the QP) + - time_qp_xcond: time_glob: CPU time globalization + - time_solution_sensitivities: CPU time for previous call to eval_param_sens + - time_reg: CPU time regularization + - sqp_iter: number of SQP iterations + - qp_iter: vector of QP iterations for last SQP call + - statistics: table with info about last iteration + - stat_m: number of rows in statistics matrix + - stat_n: number of columns in statistics matrix + - residuals: residuals of last iterate + - alpha: step sizes of SQP iterations + """ + + double_fields = ['time_tot', + 'time_lin', + 'time_sim', + 'time_sim_ad', + 'time_sim_la', + 'time_qp', + 'time_qp_solver_call', + 'time_qp_xcond', + 'time_glob', + 'time_solution_sensitivities', + 'time_reg' + ] + fields = double_fields + [ + 'sqp_iter', + 'qp_iter', + 'statistics', + 'stat_m', + 'stat_n', + 'residuals', + 'alpha', + ] + field = field_.encode('utf-8') + + if field_ in ['sqp_iter', 'stat_m', 'stat_n']: + return self.__get_stat_int(field) + + elif field_ in double_fields: + return self.__get_stat_double(field) + + elif field_ == 'statistics': + sqp_iter = self.get_stats("sqp_iter") + stat_m = self.get_stats("stat_m") + stat_n = self.get_stats("stat_n") + min_size = min([stat_m, sqp_iter+1]) + return self.__get_stat_matrix(field, stat_n+1, min_size) + + elif field_ == 'qp_iter': + full_stats = self.get_stats('statistics') + if self.nlp_solver_type == 'SQP': + return full_stats[6, :] + elif self.nlp_solver_type == 'SQP_RTI': + return full_stats[2, :] + + elif field_ == 'alpha': + full_stats = self.get_stats('statistics') + if self.nlp_solver_type == 'SQP': + return full_stats[7, :] + else: # self.nlp_solver_type == 'SQP_RTI': + raise Exception("alpha values are not available for SQP_RTI") + + elif field_ == 'residuals': + return self.get_residuals() + + else: + raise NotImplementedError("TODO!") + + + def __get_stat_int(self, field): + cdef int out + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, &out) + return out + + def __get_stat_double(self, field): + cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.zeros((1,)) + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out.data) + return out + + def __get_stat_matrix(self, field, n, m): + cdef cnp.ndarray[cnp.float64_t, ndim=2] out_mat = np.ascontiguousarray(np.zeros((n, m)), dtype=np.float64) + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, out_mat.data) + return out_mat + + + def get_cost(self): + """ + Returns the cost value of the current solution. + """ + # compute cost internally + acados_solver_common.ocp_nlp_eval_cost(self.nlp_solver, self.nlp_in, self.nlp_out) + + # create output + cdef double out + + # call getter + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, "cost_value", &out) + + return out + + + def get_residuals(self, recompute=False): + """ + Returns an array of the form [res_stat, res_eq, res_ineq, res_comp]. + """ + # compute residuals if RTI + if self.nlp_solver_type == 'SQP_RTI' or recompute: + acados_solver_common.ocp_nlp_eval_residuals(self.nlp_solver, self.nlp_in, self.nlp_out) + + # create output array + cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.ascontiguousarray(np.zeros((4,), dtype=np.float64)) + cdef double double_value + + field = "res_stat".encode('utf-8') + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, &double_value) + out[0] = double_value + + field = "res_eq".encode('utf-8') + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, &double_value) + out[1] = double_value + + field = "res_ineq".encode('utf-8') + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, &double_value) + out[2] = double_value + + field = "res_comp".encode('utf-8') + acados_solver_common.ocp_nlp_get(self.nlp_config, self.nlp_solver, field, &double_value) + out[3] = double_value + + return out + + + # Note: this function should not be used anymore, better use cost_set, constraints_set + def set(self, int stage, str field_, value_): + + """ + Set numerical data inside the solver. + + :param stage: integer corresponding to shooting node + :param field: string in ['x', 'u', 'pi', 'lam', 't', 'p'] + + .. note:: regarding lam, t: \n + the inequalities are internally organized in the following order: \n + [ lbu lbx lg lh lphi ubu ubx ug uh uphi; \n + lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi] + + .. note:: pi: multipliers for dynamics equality constraints \n + lam: multipliers for inequalities \n + t: slack variables corresponding to evaluation of all inequalities (at the solution) \n + sl: slack variables of soft lower inequality constraints \n + su: slack variables of soft upper inequality constraints \n + """ + if not isinstance(value_, np.ndarray): + raise Exception(f"set: value must be numpy array, got {type(value_)}.") + cost_fields = ['y_ref', 'yref'] + constraints_fields = ['lbx', 'ubx', 'lbu', 'ubu'] + out_fields = ['x', 'u', 'pi', 'lam', 't', 'z', 'sl', 'su'] + mem_fields = ['xdot_guess', 'z_guess'] + + field = field_.encode('utf-8') + + cdef cnp.ndarray[cnp.float64_t, ndim=1] value = np.ascontiguousarray(value_, dtype=np.float64) + + # treat parameters separately + if field_ == 'p': + assert acados_solver.acados_update_params(self.capsule, stage, value.data, value.shape[0]) == 0 + else: + if field_ not in constraints_fields + cost_fields + out_fields: + raise Exception("AcadosOcpSolverCython.set(): {} is not a valid argument.\ + \nPossible values are {}.".format(field, \ + constraints_fields + cost_fields + out_fields + ['p'])) + + dims = acados_solver_common.ocp_nlp_dims_get_from_attr(self.nlp_config, + self.nlp_dims, self.nlp_out, stage, field) + + if value_.shape[0] != dims: + msg = 'AcadosOcpSolverCython.set(): mismatching dimension for field "{}" '.format(field_) + msg += 'with dimension {} (you have {})'.format(dims, value_.shape[0]) + raise Exception(msg) + + if field_ in constraints_fields: + acados_solver_common.ocp_nlp_constraints_model_set(self.nlp_config, + self.nlp_dims, self.nlp_in, stage, field, value.data) + elif field_ in cost_fields: + acados_solver_common.ocp_nlp_cost_model_set(self.nlp_config, + self.nlp_dims, self.nlp_in, stage, field, value.data) + elif field_ in out_fields: + acados_solver_common.ocp_nlp_out_set(self.nlp_config, + self.nlp_dims, self.nlp_out, stage, field, value.data) + elif field_ in mem_fields: + acados_solver_common.ocp_nlp_set(self.nlp_config, \ + self.nlp_solver, stage, field, value.data) + + if field_ == 'z': + field = 'z_guess'.encode('utf-8') + acados_solver_common.ocp_nlp_set(self.nlp_config, \ + self.nlp_solver, stage, field, value.data) + return + + def cost_set(self, int stage, str field_, value_): + """ + Set numerical data in the cost module of the solver. + + :param stage: integer corresponding to shooting node + :param field: string, e.g. 'yref', 'W', 'ext_cost_num_hess' + :param value: of appropriate size + """ + if not isinstance(value_, np.ndarray): + raise Exception(f"cost_set: value must be numpy array, got {type(value_)}.") + field = field_.encode('utf-8') + + cdef int dims[2] + acados_solver_common.ocp_nlp_cost_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage, field, &dims[0]) + + cdef double[::1,:] value + + value_shape = value_.shape + if len(value_shape) == 1: + value_shape = (value_shape[0], 0) + value = np.asfortranarray(value_[None,:]) + + elif len(value_shape) == 2: + # Get elements in column major order + value = np.asfortranarray(value_) + + if value_shape[0] != dims[0] or value_shape[1] != dims[1]: + raise Exception('AcadosOcpSolverCython.cost_set(): mismatching dimension' + + f' for field "{field_}" at stage {stage} with dimension {tuple(dims)} (you have {value_shape})') + + acados_solver_common.ocp_nlp_cost_model_set(self.nlp_config, \ + self.nlp_dims, self.nlp_in, stage, field, &value[0][0]) + + + def constraints_set(self, int stage, str field_, value_): + """ + Set numerical data in the constraint module of the solver. + + :param stage: integer corresponding to shooting node + :param field: string in ['lbx', 'ubx', 'lbu', 'ubu', 'lg', 'ug', 'lh', 'uh', 'uphi', 'C', 'D'] + :param value: of appropriate size + """ + if not isinstance(value_, np.ndarray): + raise Exception(f"constraints_set: value must be numpy array, got {type(value_)}.") + + field = field_.encode('utf-8') + + cdef int dims[2] + acados_solver_common.ocp_nlp_constraint_dims_get_from_attr(self.nlp_config, \ + self.nlp_dims, self.nlp_out, stage, field, &dims[0]) + + cdef double[::1,:] value + + value_shape = value_.shape + if len(value_shape) == 1: + value_shape = (value_shape[0], 0) + value = np.asfortranarray(value_[None,:]) + + elif len(value_shape) == 2: + # Get elements in column major order + value = np.asfortranarray(value_) + + if value_shape != tuple(dims): + raise Exception(f'AcadosOcpSolverCython.constraints_set(): mismatching dimension' + + f' for field "{field_}" at stage {stage} with dimension {tuple(dims)} (you have {value_shape})') + + acados_solver_common.ocp_nlp_constraints_model_set(self.nlp_config, \ + self.nlp_dims, self.nlp_in, stage, field, &value[0][0]) + + return + + + def get_from_qp_in(self, int stage, str field_): + """ + Get numerical data from the dynamics module of the solver: + + :param stage: integer corresponding to shooting node + :param field: string, e.g. 'A' + """ + field = field_.encode('utf-8') + + # get dims + cdef int[2] dims + acados_solver_common.ocp_nlp_qp_dims_get_from_attr(self.nlp_config, self.nlp_dims, self.nlp_out, stage, field, &dims[0]) + + # create output data + cdef cnp.ndarray[cnp.float64_t, ndim=2] out = np.zeros((dims[0], dims[1]), order='F') + + # call getter + acados_solver_common.ocp_nlp_get_at_stage(self.nlp_config, self.nlp_dims, self.nlp_solver, stage, field, out.data) + + return out + + + def options_set(self, str field_, value_): + """ + Set options of the solver. + + :param field: string, e.g. 'print_level', 'rti_phase', 'initialize_t_slacks', 'step_length', 'alpha_min', 'alpha_reduction', 'qp_warm_start', 'line_search_use_sufficient_descent', 'full_step_dual', 'globalization_use_SOC', 'qp_tol_stat', 'qp_tol_eq', 'qp_tol_ineq', 'qp_tol_comp', 'qp_tau_min', 'qp_mu0' + + :param value: of type int, float, string + + - qp_tol_stat: QP solver tolerance stationarity + - qp_tol_eq: QP solver tolerance equalities + - qp_tol_ineq: QP solver tolerance inequalities + - qp_tol_comp: QP solver tolerance complementarity + - qp_tau_min: for HPIPM QP solvers: minimum value of barrier parameter in HPIPM + - qp_mu0: for HPIPM QP solvers: initial value for complementarity slackness + - warm_start_first_qp: indicates if first QP in SQP is warm_started + """ + int_fields = ['print_level', 'rti_phase', 'initialize_t_slacks', 'qp_warm_start', 'line_search_use_sufficient_descent', 'full_step_dual', 'globalization_use_SOC', 'warm_start_first_qp'] + double_fields = ['step_length', 'tol_eq', 'tol_stat', 'tol_ineq', 'tol_comp', 'alpha_min', 'alpha_reduction', 'eps_sufficient_descent', + 'qp_tol_stat', 'qp_tol_eq', 'qp_tol_ineq', 'qp_tol_comp', 'qp_tau_min', 'qp_mu0'] + string_fields = ['globalization'] + + # encode + field = field_.encode('utf-8') + + cdef int int_value + cdef double double_value + cdef unsigned char[::1] string_value + + # check field availability and type + if field_ in int_fields: + if not isinstance(value_, int): + raise Exception('solver option {} must be of type int. You have {}.'.format(field_, type(value_))) + + if field_ == 'rti_phase': + if value_ < 0 or value_ > 2: + raise Exception('AcadosOcpSolverCython.solve(): argument \'rti_phase\' can ' + 'take only values 0, 1, 2 for SQP-RTI-type solvers') + if self.nlp_solver_type != 'SQP_RTI' and value_ > 0: + raise Exception('AcadosOcpSolverCython.solve(): argument \'rti_phase\' can ' + 'take only value 0 for SQP-type solvers') + + int_value = value_ + acados_solver_common.ocp_nlp_solver_opts_set(self.nlp_config, self.nlp_opts, field, &int_value) + + elif field_ in double_fields: + if not isinstance(value_, float): + raise Exception('solver option {} must be of type float. You have {}.'.format(field_, type(value_))) + + double_value = value_ + acados_solver_common.ocp_nlp_solver_opts_set(self.nlp_config, self.nlp_opts, field, &double_value) + + elif field_ in string_fields: + if not isinstance(value_, bytes): + raise Exception('solver option {} must be of type str. You have {}.'.format(field_, type(value_))) + + string_value = value_.encode('utf-8') + acados_solver_common.ocp_nlp_solver_opts_set(self.nlp_config, self.nlp_opts, field, &string_value[0]) + + else: + raise Exception('AcadosOcpSolverCython.options_set() does not support field {}.'\ + '\n Possible values are {}.'.format(field_, ', '.join(int_fields + double_fields + string_fields))) + + + def set_params_sparse(self, int stage, idx_values_, param_values_): + """ + set parameters of the solvers external function partially: + Pseudo: solver.param[idx_values_] = param_values_; + Parameters: + :param stage_: integer corresponding to shooting node + :param idx_values_: 0 based integer array corresponding to parameter indices to be set + :param param_values_: new parameter values as numpy array + """ + + if not isinstance(param_values_, np.ndarray): + raise Exception('param_values_ must be np.array.') + + if param_values_.shape[0] != len(idx_values_): + raise Exception(f'param_values_ and idx_values_ must be of the same size.' + + f' Got sizes idx {param_values_.shape[0]}, param_values {len(idx_values_)}.') + + # n_update = c_int(len(param_values_)) + + # param_data = cast(param_values_.ctypes.data, POINTER(c_double)) + # c_idx_values = np.ascontiguousarray(idx_values_, dtype=np.intc) + # idx_data = cast(c_idx_values.ctypes.data, POINTER(c_int)) + + # getattr(self.shared_lib, f"{self.model_name}_acados_update_params_sparse").argtypes = \ + # [c_void_p, c_int, POINTER(c_int), POINTER(c_double), c_int] + # getattr(self.shared_lib, f"{self.model_name}_acados_update_params_sparse").restype = c_int + # getattr(self.shared_lib, f"{self.model_name}_acados_update_params_sparse") \ + # (self.capsule, stage, idx_data, param_data, n_update) + + cdef cnp.ndarray[cnp.float64_t, ndim=1] value = np.ascontiguousarray(param_values_, dtype=np.float64) + # cdef cnp.ndarray[cnp.intc, ndim=1] idx = np.ascontiguousarray(idx_values_, dtype=np.intc) + + # NOTE: this does throw an error somehow: + # ValueError: Buffer dtype mismatch, expected 'int object' but got 'int' + # cdef cnp.ndarray[cnp.int, ndim=1] idx = np.ascontiguousarray(idx_values_, dtype=np.intc) + + cdef cnp.ndarray[cnp.int32_t, ndim=1] idx = np.ascontiguousarray(idx_values_, dtype=np.int32) + cdef int n_update = value.shape[0] + # print(f"in set_params_sparse Cython n_update {n_update}") + + assert acados_solver.acados_update_params_sparse(self.capsule, stage, idx.data, value.data, n_update) == 0 + return + + + def __del__(self): + if self.solver_created: + acados_solver.acados_free(self.capsule) + acados_solver.acados_free_capsule(self.capsule) diff --git a/third_party/acados/acados_template/acados_sim.py b/third_party/acados/acados_template/acados_sim.py new file mode 100644 index 0000000000..c0d6937a49 --- /dev/null +++ b/third_party/acados/acados_template/acados_sim.py @@ -0,0 +1,367 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import numpy as np +import os +from .acados_model import AcadosModel +from .utils import get_acados_path, get_lib_ext + +class AcadosSimDims: + """ + Class containing the dimensions of the model to be simulated. + """ + def __init__(self): + self.__nx = None + self.__nu = None + self.__nz = 0 + self.__np = 0 + + @property + def nx(self): + """:math:`n_x` - number of states. Type: int > 0""" + return self.__nx + + @property + def nz(self): + """:math:`n_z` - number of algebraic variables. Type: int >= 0""" + return self.__nz + + @property + def nu(self): + """:math:`n_u` - number of inputs. Type: int >= 0""" + return self.__nu + + @property + def np(self): + """:math:`n_p` - number of parameters. Type: int >= 0""" + return self.__np + + @nx.setter + def nx(self, nx): + if isinstance(nx, int) and nx > 0: + self.__nx = nx + else: + raise Exception('Invalid nx value, expected positive integer.') + + @nz.setter + def nz(self, nz): + if isinstance(nz, int) and nz > -1: + self.__nz = nz + else: + raise Exception('Invalid nz value, expected nonnegative integer.') + + @nu.setter + def nu(self, nu): + if isinstance(nu, int) and nu > -1: + self.__nu = nu + else: + raise Exception('Invalid nu value, expected nonnegative integer.') + + @np.setter + def np(self, np): + if isinstance(np, int) and np > -1: + self.__np = np + else: + raise Exception('Invalid np value, expected nonnegative integer.') + + def set(self, attr, value): + setattr(self, attr, value) + + +class AcadosSimOpts: + """ + class containing the solver options + """ + def __init__(self): + self.__integrator_type = 'ERK' + self.__collocation_type = 'GAUSS_LEGENDRE' + self.__Tsim = None + # ints + self.__sim_method_num_stages = 1 + self.__sim_method_num_steps = 1 + self.__sim_method_newton_iter = 3 + # doubles + self.__sim_method_newton_tol = 0.0 + # bools + self.__sens_forw = True + self.__sens_adj = False + self.__sens_algebraic = False + self.__sens_hess = False + self.__output_z = True + self.__sim_method_jac_reuse = 0 + self.__ext_fun_compile_flags = '-O2' + + @property + def integrator_type(self): + """Integrator type. Default: 'ERK'.""" + return self.__integrator_type + + @property + def num_stages(self): + """Number of stages in the integrator. Default: 1""" + return self.__sim_method_num_stages + + @property + def num_steps(self): + """Number of steps in the integrator. Default: 1""" + return self.__sim_method_num_steps + + @property + def newton_iter(self): + """Number of Newton iterations in simulation method. Default: 3""" + return self.__sim_method_newton_iter + + @property + def newton_tol(self): + """ + Tolerance for Newton system solved in implicit integrator (IRK, GNSF). + 0.0 means this is not used and exactly newton_iter iterations are carried out. + Default: 0.0 + """ + return self.__sim_method_newton_tol + + @property + def sens_forw(self): + """Boolean determining if forward sensitivities are computed. Default: True""" + return self.__sens_forw + + @property + def sens_adj(self): + """Boolean determining if adjoint sensitivities are computed. Default: False""" + return self.__sens_adj + + @property + def sens_algebraic(self): + """Boolean determining if sensitivities wrt algebraic variables are computed. Default: False""" + return self.__sens_algebraic + + @property + def sens_hess(self): + """Boolean determining if hessians are computed. Default: False""" + return self.__sens_hess + + @property + def output_z(self): + """Boolean determining if values for algebraic variables (corresponding to start of simulation interval) are computed. Default: True""" + return self.__output_z + + @property + def sim_method_jac_reuse(self): + """Integer determining if jacobians are reused (0 or 1). Default: 0""" + return self.__sim_method_jac_reuse + + @property + def T(self): + """Time horizon""" + return self.__Tsim + + @property + def collocation_type(self): + """Collocation type: relevant for implicit integrators + -- string in {GAUSS_RADAU_IIA, GAUSS_LEGENDRE} + + Default: GAUSS_LEGENDRE + """ + return self.__collocation_type + + @property + def ext_fun_compile_flags(self): + """ + String with compiler flags for external function compilation. + Default: '-O2'. + """ + return self.__ext_fun_compile_flags + + @ext_fun_compile_flags.setter + def ext_fun_compile_flags(self, ext_fun_compile_flags): + if isinstance(ext_fun_compile_flags, str): + self.__ext_fun_compile_flags = ext_fun_compile_flags + else: + raise Exception('Invalid ext_fun_compile_flags, expected a string.\n') + + @integrator_type.setter + def integrator_type(self, integrator_type): + integrator_types = ('ERK', 'IRK', 'GNSF') + if integrator_type in integrator_types: + self.__integrator_type = integrator_type + else: + raise Exception('Invalid integrator_type value. Possible values are:\n\n' \ + + ',\n'.join(integrator_types) + '.\n\nYou have: ' + integrator_type + '.\n\n') + + @collocation_type.setter + def collocation_type(self, collocation_type): + collocation_types = ('GAUSS_RADAU_IIA', 'GAUSS_LEGENDRE') + if collocation_type in collocation_types: + self.__collocation_type = collocation_type + else: + raise Exception('Invalid collocation_type value. Possible values are:\n\n' \ + + ',\n'.join(collocation_types) + '.\n\nYou have: ' + collocation_type + '.\n\n') + + @T.setter + def T(self, T): + self.__Tsim = T + + @num_stages.setter + def num_stages(self, num_stages): + if isinstance(num_stages, int): + self.__sim_method_num_stages = num_stages + else: + raise Exception('Invalid num_stages value. num_stages must be an integer.') + + @num_steps.setter + def num_steps(self, num_steps): + if isinstance(num_steps, int): + self.__sim_method_num_steps = num_steps + else: + raise Exception('Invalid num_steps value. num_steps must be an integer.') + + @newton_iter.setter + def newton_iter(self, newton_iter): + if isinstance(newton_iter, int): + self.__sim_method_newton_iter = newton_iter + else: + raise Exception('Invalid newton_iter value. newton_iter must be an integer.') + + @newton_tol.setter + def newton_tol(self, newton_tol): + if isinstance(newton_tol, float): + self.__sim_method_newton_tol = newton_tol + else: + raise Exception('Invalid newton_tol value. newton_tol must be an float.') + + @sens_forw.setter + def sens_forw(self, sens_forw): + if sens_forw in (True, False): + self.__sens_forw = sens_forw + else: + raise Exception('Invalid sens_forw value. sens_forw must be a Boolean.') + + @sens_adj.setter + def sens_adj(self, sens_adj): + if sens_adj in (True, False): + self.__sens_adj = sens_adj + else: + raise Exception('Invalid sens_adj value. sens_adj must be a Boolean.') + + @sens_hess.setter + def sens_hess(self, sens_hess): + if sens_hess in (True, False): + self.__sens_hess = sens_hess + else: + raise Exception('Invalid sens_hess value. sens_hess must be a Boolean.') + + @sens_algebraic.setter + def sens_algebraic(self, sens_algebraic): + if sens_algebraic in (True, False): + self.__sens_algebraic = sens_algebraic + else: + raise Exception('Invalid sens_algebraic value. sens_algebraic must be a Boolean.') + + @output_z.setter + def output_z(self, output_z): + if output_z in (True, False): + self.__output_z = output_z + else: + raise Exception('Invalid output_z value. output_z must be a Boolean.') + + @sim_method_jac_reuse.setter + def sim_method_jac_reuse(self, sim_method_jac_reuse): + if sim_method_jac_reuse in (0, 1): + self.__sim_method_jac_reuse = sim_method_jac_reuse + else: + raise Exception('Invalid sim_method_jac_reuse value. sim_method_jac_reuse must be 0 or 1.') + +class AcadosSim: + """ + The class has the following properties that can be modified to formulate a specific simulation problem, see below: + + :param acados_path: string with the path to acados. It is used to generate the include and lib paths. + + - :py:attr:`dims` of type :py:class:`acados_template.acados_ocp.AcadosSimDims` - are automatically detected from model + - :py:attr:`model` of type :py:class:`acados_template.acados_model.AcadosModel` + - :py:attr:`solver_options` of type :py:class:`acados_template.acados_sim.AcadosSimOpts` + + - :py:attr:`acados_include_path` (set automatically) + - :py:attr:`shared_lib_ext` (set automatically) + - :py:attr:`acados_lib_path` (set automatically) + - :py:attr:`parameter_values` - used to initialize the parameters (can be changed) + + """ + def __init__(self, acados_path=''): + if acados_path == '': + acados_path = get_acados_path() + self.dims = AcadosSimDims() + """Dimension definitions, automatically detected from :py:attr:`model`. Type :py:class:`acados_template.acados_sim.AcadosSimDims`""" + self.model = AcadosModel() + """Model definitions, type :py:class:`acados_template.acados_model.AcadosModel`""" + self.solver_options = AcadosSimOpts() + """Solver Options, type :py:class:`acados_template.acados_sim.AcadosSimOpts`""" + + self.acados_include_path = os.path.join(acados_path, 'include').replace(os.sep, '/') # the replace part is important on Windows for CMake + """Path to acados include directory (set automatically), type: `string`""" + self.acados_lib_path = os.path.join(acados_path, 'lib').replace(os.sep, '/') # the replace part is important on Windows for CMake + """Path to where acados library is located (set automatically), type: `string`""" + + self.code_export_directory = 'c_generated_code' + """Path to where code will be exported. Default: `c_generated_code`.""" + self.shared_lib_ext = get_lib_ext() + + # get cython paths + from sysconfig import get_paths + self.cython_include_dirs = [np.get_include(), get_paths()['include']] + + self.__parameter_values = np.array([]) + self.__problem_class = 'SIM' + + @property + def parameter_values(self): + """:math:`p` - initial values for parameter - can be updated""" + return self.__parameter_values + + @parameter_values.setter + def parameter_values(self, parameter_values): + if isinstance(parameter_values, np.ndarray): + self.__parameter_values = parameter_values + else: + raise Exception('Invalid parameter_values value. ' + + f'Expected numpy array, got {type(parameter_values)}.') + + def set(self, attr, value): + # tokenize string + tokens = attr.split('_', 1) + if len(tokens) > 1: + setter_to_call = getattr(getattr(self, tokens[0]), 'set') + else: + setter_to_call = getattr(self, 'set') + + setter_to_call(tokens[1], value) + + return diff --git a/third_party/acados/acados_template/acados_sim_layout.json b/third_party/acados/acados_template/acados_sim_layout.json new file mode 100644 index 0000000000..e3ca4b575b --- /dev/null +++ b/third_party/acados/acados_template/acados_sim_layout.json @@ -0,0 +1,53 @@ +{ + "acados_include_path": [ + "str" + ], + "model": { + "name" : [ + "str" + ] + }, + "acados_lib_path": [ + "str" + ], + "dims": { + "np": [ + "int" + ], + "nu": [ + "int" + ], + "nx": [ + "int" + ], + "nz": [ + "int" + ] + }, + "solver_options": { + "integrator_type": [ + "str" + ], + "collocation_type": [ + "str" + ], + "Tsim": [ + "float" + ], + "sim_method_num_stages": [ + "int" + ], + "sim_method_num_steps": [ + "int" + ], + "sim_method_newton_iter": [ + "int" + ], + "sim_method_newton_tol": [ + "float" + ], + "ext_fun_compile_flags": [ + "str" + ] + } +} diff --git a/third_party/acados/acados_template/acados_sim_solver.py b/third_party/acados/acados_template/acados_sim_solver.py new file mode 100644 index 0000000000..612f439eaf --- /dev/null +++ b/third_party/acados/acados_template/acados_sim_solver.py @@ -0,0 +1,559 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import sys +import os +import json +import importlib + +import numpy as np + +from subprocess import DEVNULL, call, STDOUT + +from ctypes import POINTER, cast, CDLL, c_void_p, c_char_p, c_double, c_int, c_bool, byref +from copy import deepcopy + +from .casadi_function_generation import generate_c_code_implicit_ode, generate_c_code_gnsf, generate_c_code_explicit_ode +from .acados_sim import AcadosSim +from .acados_ocp import AcadosOcp +from .utils import is_column, render_template, format_class_dict, make_object_json_dumpable,\ + make_model_consistent, set_up_imported_gnsf_model, get_python_interface_path, get_lib_ext,\ + casadi_length, is_empty, check_casadi_version +from .builders import CMakeBuilder +from .gnsf.detect_gnsf_structure import detect_gnsf_structure + + + +def make_sim_dims_consistent(acados_sim: AcadosSim): + dims = acados_sim.dims + model = acados_sim.model + # nx + if is_column(model.x): + dims.nx = casadi_length(model.x) + else: + raise Exception('model.x should be column vector!') + + # nu + if is_empty(model.u): + dims.nu = 0 + else: + dims.nu = casadi_length(model.u) + + # nz + if is_empty(model.z): + dims.nz = 0 + else: + dims.nz = casadi_length(model.z) + + # np + if is_empty(model.p): + dims.np = 0 + else: + dims.np = casadi_length(model.p) + if acados_sim.parameter_values.shape[0] != dims.np: + raise Exception('inconsistent dimension np, regarding model.p and parameter_values.' + \ + f'\nGot np = {dims.np}, acados_sim.parameter_values.shape = {acados_sim.parameter_values.shape[0]}\n') + + +def get_sim_layout(): + python_interface_path = get_python_interface_path() + abs_path = os.path.join(python_interface_path, 'acados_sim_layout.json') + with open(abs_path, 'r') as f: + sim_layout = json.load(f) + return sim_layout + + +def sim_formulation_json_dump(acados_sim: AcadosSim, json_file='acados_sim.json'): + # Load acados_sim structure description + sim_layout = get_sim_layout() + + # Copy input sim object dictionary + sim_dict = dict(deepcopy(acados_sim).__dict__) + + for key, v in sim_layout.items(): + # skip non dict attributes + if not isinstance(v, dict): continue + # Copy sim object attributes dictionaries + sim_dict[key]=dict(getattr(acados_sim, key).__dict__) + + sim_json = format_class_dict(sim_dict) + + with open(json_file, 'w') as f: + json.dump(sim_json, f, default=make_object_json_dumpable, indent=4, sort_keys=True) + + +def sim_get_default_cmake_builder() -> CMakeBuilder: + """ + If :py:class:`~acados_template.acados_sim_solver.AcadosSimSolver` is used with `CMake` this function returns a good first setting. + :return: default :py:class:`~acados_template.builders.CMakeBuilder` + """ + cmake_builder = CMakeBuilder() + cmake_builder.options_on = ['BUILD_ACADOS_SIM_SOLVER_LIB'] + return cmake_builder + + +def sim_render_templates(json_file, model_name: str, code_export_dir, cmake_options: CMakeBuilder = None): + # setting up loader and environment + json_path = os.path.join(os.getcwd(), json_file) + + if not os.path.exists(json_path): + raise Exception(f"{json_path} not found!") + + # Render templates + in_file = 'acados_sim_solver.in.c' + out_file = f'acados_sim_solver_{model_name}.c' + render_template(in_file, out_file, code_export_dir, json_path) + + in_file = 'acados_sim_solver.in.h' + out_file = f'acados_sim_solver_{model_name}.h' + render_template(in_file, out_file, code_export_dir, json_path) + + in_file = 'acados_sim_solver.in.pxd' + out_file = f'acados_sim_solver.pxd' + render_template(in_file, out_file, code_export_dir, json_path) + + # Builder + if cmake_options is not None: + in_file = 'CMakeLists.in.txt' + out_file = 'CMakeLists.txt' + render_template(in_file, out_file, code_export_dir, json_path) + else: + in_file = 'Makefile.in' + out_file = 'Makefile' + render_template(in_file, out_file, code_export_dir, json_path) + + in_file = 'main_sim.in.c' + out_file = f'main_sim_{model_name}.c' + render_template(in_file, out_file, code_export_dir, json_path) + + # folder model + model_dir = os.path.join(code_export_dir, model_name + '_model') + + in_file = 'model.in.h' + out_file = f'{model_name}_model.h' + render_template(in_file, out_file, model_dir, json_path) + + +def sim_generate_external_functions(acados_sim: AcadosSim): + model = acados_sim.model + model = make_model_consistent(model) + + integrator_type = acados_sim.solver_options.integrator_type + + opts = dict(generate_hess = acados_sim.solver_options.sens_hess, + code_export_directory = acados_sim.code_export_directory) + + # create code_export_dir, model_dir + code_export_dir = acados_sim.code_export_directory + opts['code_export_directory'] = code_export_dir + model_dir = os.path.join(code_export_dir, model.name + '_model') + if not os.path.exists(model_dir): + os.makedirs(model_dir) + + # generate external functions + check_casadi_version() + if integrator_type == 'ERK': + generate_c_code_explicit_ode(model, opts) + elif integrator_type == 'IRK': + generate_c_code_implicit_ode(model, opts) + elif integrator_type == 'GNSF': + generate_c_code_gnsf(model, opts) + + +class AcadosSimSolver: + """ + Class to interact with the acados integrator C object. + + :param acados_sim: type :py:class:`~acados_template.acados_ocp.AcadosOcp` (takes values to generate an instance :py:class:`~acados_template.acados_sim.AcadosSim`) or :py:class:`~acados_template.acados_sim.AcadosSim` + :param json_file: Default: 'acados_sim.json' + :param build: Default: True + :param cmake_builder: type :py:class:`~acados_template.utils.CMakeBuilder` generate a `CMakeLists.txt` and use + the `CMake` pipeline instead of a `Makefile` (`CMake` seems to be the better option in conjunction with + `MS Visual Studio`); default: `None` + """ + if sys.platform=="win32": + from ctypes import wintypes + from ctypes import WinDLL + dlclose = WinDLL('kernel32', use_last_error=True).FreeLibrary + dlclose.argtypes = [wintypes.HMODULE] + else: + dlclose = CDLL(None).dlclose + dlclose.argtypes = [c_void_p] + + + @classmethod + def generate(cls, acados_sim: AcadosSim, json_file='acados_sim.json', cmake_builder: CMakeBuilder = None): + """ + Generates the code for an acados sim solver, given the description in acados_sim + """ + + acados_sim.code_export_directory = os.path.abspath(acados_sim.code_export_directory) + + # make dims consistent + make_sim_dims_consistent(acados_sim) + + # module dependent post processing + if acados_sim.solver_options.integrator_type == 'GNSF': + if acados_sim.solver_options.sens_hess == True: + raise Exception("AcadosSimSolver: GNSF does not support sens_hess = True.") + if 'gnsf_model' in acados_sim.__dict__: + set_up_imported_gnsf_model(acados_sim) + else: + detect_gnsf_structure(acados_sim) + + # generate external functions + sim_generate_external_functions(acados_sim) + + # dump to json + sim_formulation_json_dump(acados_sim, json_file) + + # render templates + sim_render_templates(json_file, acados_sim.model.name, acados_sim.code_export_directory, cmake_builder) + + + @classmethod + def build(cls, code_export_dir, with_cython=False, cmake_builder: CMakeBuilder = None, verbose: bool = True): + # Compile solver + cwd = os.getcwd() + os.chdir(code_export_dir) + if with_cython: + call( + ['make', 'clean_sim_cython'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + call( + ['make', 'sim_cython'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + else: + if cmake_builder is not None: + cmake_builder.exec(code_export_dir, verbose=verbose) + else: + call( + ['make', 'sim_shared_lib'], + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + os.chdir(cwd) + + + @classmethod + def create_cython_solver(cls, json_file): + """ + """ + with open(json_file, 'r') as f: + acados_sim_json = json.load(f) + code_export_directory = acados_sim_json['code_export_directory'] + + importlib.invalidate_caches() + rel_code_export_directory = os.path.relpath(code_export_directory) + acados_sim_solver_pyx = importlib.import_module(f'{rel_code_export_directory}.acados_sim_solver_pyx') + + AcadosSimSolverCython = getattr(acados_sim_solver_pyx, 'AcadosSimSolverCython') + return AcadosSimSolverCython(acados_sim_json['model']['name']) + + def __init__(self, acados_sim, json_file='acados_sim.json', generate=True, build=True, cmake_builder: CMakeBuilder = None, verbose: bool = True): + + self.solver_created = False + self.acados_sim = acados_sim + model_name = acados_sim.model.name + self.model_name = model_name + + code_export_dir = os.path.abspath(acados_sim.code_export_directory) + + # reuse existing json and casadi functions, when creating integrator from ocp + if generate and not isinstance(acados_sim, AcadosOcp): + self.generate(acados_sim, json_file=json_file, cmake_builder=cmake_builder) + + if build: + self.build(code_export_dir, cmake_builder=cmake_builder, verbose=True) + + # prepare library loading + lib_prefix = 'lib' + lib_ext = get_lib_ext() + if os.name == 'nt': + lib_prefix = '' + + # Load acados library to avoid unloading the library. + # This is necessary if acados was compiled with OpenMP, since the OpenMP threads can't be destroyed. + # Unloading a library which uses OpenMP results in a segfault (on any platform?). + # see [https://stackoverflow.com/questions/34439956/vc-crash-when-freeing-a-dll-built-with-openmp] + # or [https://python.hotexamples.com/examples/_ctypes/-/dlclose/python-dlclose-function-examples.html] + libacados_name = f'{lib_prefix}acados{lib_ext}' + libacados_filepath = os.path.join(acados_sim.acados_lib_path, libacados_name) + self.__acados_lib = CDLL(libacados_filepath) + # find out if acados was compiled with OpenMP + try: + self.__acados_lib_uses_omp = getattr(self.__acados_lib, 'omp_get_thread_num') is not None + except AttributeError as e: + self.__acados_lib_uses_omp = False + if self.__acados_lib_uses_omp: + print('acados was compiled with OpenMP.') + else: + print('acados was compiled without OpenMP.') + libacados_sim_solver_name = f'{lib_prefix}acados_sim_solver_{self.model_name}{lib_ext}' + self.shared_lib_name = os.path.join(code_export_dir, libacados_sim_solver_name) + + # get shared_lib + self.shared_lib = CDLL(self.shared_lib_name) + + # create capsule + getattr(self.shared_lib, f"{model_name}_acados_sim_solver_create_capsule").restype = c_void_p + self.capsule = getattr(self.shared_lib, f"{model_name}_acados_sim_solver_create_capsule")() + + # create solver + getattr(self.shared_lib, f"{model_name}_acados_sim_create").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_sim_create").restype = c_int + assert getattr(self.shared_lib, f"{model_name}_acados_sim_create")(self.capsule)==0 + self.solver_created = True + + getattr(self.shared_lib, f"{model_name}_acados_get_sim_opts").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_get_sim_opts").restype = c_void_p + self.sim_opts = getattr(self.shared_lib, f"{model_name}_acados_get_sim_opts")(self.capsule) + + getattr(self.shared_lib, f"{model_name}_acados_get_sim_dims").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_get_sim_dims").restype = c_void_p + self.sim_dims = getattr(self.shared_lib, f"{model_name}_acados_get_sim_dims")(self.capsule) + + getattr(self.shared_lib, f"{model_name}_acados_get_sim_config").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_get_sim_config").restype = c_void_p + self.sim_config = getattr(self.shared_lib, f"{model_name}_acados_get_sim_config")(self.capsule) + + getattr(self.shared_lib, f"{model_name}_acados_get_sim_out").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_get_sim_out").restype = c_void_p + self.sim_out = getattr(self.shared_lib, f"{model_name}_acados_get_sim_out")(self.capsule) + + getattr(self.shared_lib, f"{model_name}_acados_get_sim_in").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_get_sim_in").restype = c_void_p + self.sim_in = getattr(self.shared_lib, f"{model_name}_acados_get_sim_in")(self.capsule) + + getattr(self.shared_lib, f"{model_name}_acados_get_sim_solver").argtypes = [c_void_p] + getattr(self.shared_lib, f"{model_name}_acados_get_sim_solver").restype = c_void_p + self.sim_solver = getattr(self.shared_lib, f"{model_name}_acados_get_sim_solver")(self.capsule) + + self.gettable_vectors = ['x', 'u', 'z', 'S_adj'] + self.gettable_matrices = ['S_forw', 'Sx', 'Su', 'S_hess', 'S_algebraic'] + self.gettable_scalars = ['CPUtime', 'time_tot', 'ADtime', 'time_ad', 'LAtime', 'time_la'] + + + def simulate(self, x=None, u=None, z=None, p=None): + """ + Simulate the system forward for the given x, u, z, p and return x_next. + Wrapper around `solve()` taking care of setting/getting inputs/outputs. + """ + if x is not None: + self.set('x', x) + if u is not None: + self.set('u', u) + if z is not None: + self.set('z', z) + if p is not None: + self.set('p', p) + + status = self.solve() + + if status == 2: + print("Warning: acados_sim_solver reached maximum iterations.") + elif status != 0: + raise Exception(f'acados_sim_solver for model {self.model_name} returned status {status}.') + + x_next = self.get('x') + return x_next + + + def solve(self): + """ + Solve the simulation problem with current input. + """ + getattr(self.shared_lib, f"{self.model_name}_acados_sim_solve").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_sim_solve").restype = c_int + + status = getattr(self.shared_lib, f"{self.model_name}_acados_sim_solve")(self.capsule) + return status + + + def get(self, field_): + """ + Get the last solution of the solver. + + :param str field: string in ['x', 'u', 'z', 'S_forw', 'Sx', 'Su', 'S_adj', 'S_hess', 'S_algebraic', 'CPUtime', 'time_tot', 'ADtime', 'time_ad', 'LAtime', 'time_la'] + """ + field = field_.encode('utf-8') + + if field_ in self.gettable_vectors: + # get dims + dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc) + dims_data = cast(dims.ctypes.data, POINTER(c_int)) + + self.shared_lib.sim_dims_get_from_attr.argtypes = [c_void_p, c_void_p, c_char_p, POINTER(c_int)] + self.shared_lib.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, dims_data) + + # allocate array + out = np.ascontiguousarray(np.zeros((dims[0],)), dtype=np.float64) + out_data = cast(out.ctypes.data, POINTER(c_double)) + + self.shared_lib.sim_out_get.argtypes = [c_void_p, c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, out_data) + + elif field_ in self.gettable_matrices: + # get dims + dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc) + dims_data = cast(dims.ctypes.data, POINTER(c_int)) + + self.shared_lib.sim_dims_get_from_attr.argtypes = [c_void_p, c_void_p, c_char_p, POINTER(c_int)] + self.shared_lib.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, dims_data) + + out = np.zeros((dims[0], dims[1]), order='F') + out_data = cast(out.ctypes.data, POINTER(c_double)) + + self.shared_lib.sim_out_get.argtypes = [c_void_p, c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, out_data) + + elif field_ in self.gettable_scalars: + scalar = c_double() + scalar_data = byref(scalar) + self.shared_lib.sim_out_get.argtypes = [c_void_p, c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, scalar_data) + + out = scalar.value + else: + raise Exception(f'AcadosSimSolver.get(): Unknown field {field_},' \ + f' available fields are {", ".join(self.gettable_vectors+self.gettable_matrices)}, {", ".join(self.gettable_scalars)}') + + return out + + + + def set(self, field_: str, value_): + """ + Set numerical data inside the solver. + + :param field: string in ['x', 'u', 'p', 'xdot', 'z', 'seed_adj', 'T'] + :param value: the value with appropriate size. + """ + settable = ['x', 'u', 'p', 'xdot', 'z', 'seed_adj', 'T'] # S_forw + + # TODO: check and throw error here. then remove checks in Cython for speed + # cast value_ to avoid conversion issues + if isinstance(value_, (float, int)): + value_ = np.array([value_]) + + value_ = value_.astype(float) + value_data = cast(value_.ctypes.data, POINTER(c_double)) + value_data_p = cast((value_data), c_void_p) + + field = field_.encode('utf-8') + + # treat parameters separately + if field_ == 'p': + model_name = self.acados_sim.model.name + getattr(self.shared_lib, f"{model_name}_acados_sim_update_params").argtypes = [c_void_p, POINTER(c_double), c_int] + value_data = cast(value_.ctypes.data, POINTER(c_double)) + getattr(self.shared_lib, f"{model_name}_acados_sim_update_params")(self.capsule, value_data, value_.shape[0]) + return + else: + # dimension check + dims = np.ascontiguousarray(np.zeros((2,)), dtype=np.intc) + dims_data = cast(dims.ctypes.data, POINTER(c_int)) + + self.shared_lib.sim_dims_get_from_attr.argtypes = [c_void_p, c_void_p, c_char_p, POINTER(c_int)] + self.shared_lib.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, dims_data) + + value_ = np.ravel(value_, order='F') + + value_shape = value_.shape + if len(value_shape) == 1: + value_shape = (value_shape[0], 0) + + if value_shape != tuple(dims): + raise Exception(f'AcadosSimSolver.set(): mismatching dimension' \ + f' for field "{field_}" with dimension {tuple(dims)} (you have {value_shape}).') + + # set + if field_ in ['xdot', 'z']: + self.shared_lib.sim_solver_set.argtypes = [c_void_p, c_char_p, c_void_p] + self.shared_lib.sim_solver_set(self.sim_solver, field, value_data_p) + elif field_ in settable: + self.shared_lib.sim_in_set.argtypes = [c_void_p, c_void_p, c_void_p, c_char_p, c_void_p] + self.shared_lib.sim_in_set(self.sim_config, self.sim_dims, self.sim_in, field, value_data_p) + else: + raise Exception(f'AcadosSimSolver.set(): Unknown field {field_},' \ + f' available fields are {", ".join(settable)}') + + return + + + def options_set(self, field_: str, value_: bool): + """ + Set solver options + + :param field: string in ['sens_forw', 'sens_adj', 'sens_hess'] + :param value: Boolean + """ + fields = ['sens_forw', 'sens_adj', 'sens_hess'] + if field_ not in fields: + raise Exception(f"field {field_} not supported. Supported values are {', '.join(fields)}.\n") + + field = field_.encode('utf-8') + value_ctypes = c_bool(value_) + + if not isinstance(value_, bool): + raise TypeError("options_set: expected boolean for value") + + # only allow setting + if getattr(self.acados_sim.solver_options, field_) or value_ == False: + self.shared_lib.sim_opts_set.argtypes = [c_void_p, c_void_p, c_char_p, POINTER(c_bool)] + self.shared_lib.sim_opts_set(self.sim_config, self.sim_opts, field, value_ctypes) + else: + raise RuntimeError(f"Cannot set option {field_} to True, because it was False in original solver options.\n") + + return + + + def __del__(self): + + if self.solver_created: + getattr(self.shared_lib, f"{self.model_name}_acados_sim_free").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_sim_free").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_sim_free")(self.capsule) + + getattr(self.shared_lib, f"{self.model_name}_acados_sim_solver_free_capsule").argtypes = [c_void_p] + getattr(self.shared_lib, f"{self.model_name}_acados_sim_solver_free_capsule").restype = c_int + getattr(self.shared_lib, f"{self.model_name}_acados_sim_solver_free_capsule")(self.capsule) + + try: + self.dlclose(self.shared_lib._handle) + except: + print(f"WARNING: acados Python interface could not close shared_lib handle of AcadosSimSolver {self.model_name}.\n", + "Attempting to create a new one with the same name will likely result in the old one being used!") + pass diff --git a/third_party/acados/acados_template/acados_sim_solver_common.pxd b/third_party/acados/acados_template/acados_sim_solver_common.pxd new file mode 100644 index 0000000000..cc6a58efd7 --- /dev/null +++ b/third_party/acados/acados_template/acados_sim_solver_common.pxd @@ -0,0 +1,64 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + + +cdef extern from "acados/sim/sim_common.h": + ctypedef struct sim_config: + pass + + ctypedef struct sim_opts: + pass + + ctypedef struct sim_in: + pass + + ctypedef struct sim_out: + pass + + +cdef extern from "acados_c/sim_interface.h": + + ctypedef struct sim_plan: + pass + + ctypedef struct sim_solver: + pass + + # out + void sim_out_get(sim_config *config, void *dims, sim_out *out, const char *field, void *value) + int sim_dims_get_from_attr(sim_config *config, void *dims, const char *field, void *dims_data) + + # opts + void sim_opts_set(sim_config *config, void *opts_, const char *field, void *value) + + # get/set + void sim_in_set(sim_config *config, void *dims, sim_in *sim_in, const char *field, void *value) + void sim_solver_set(sim_solver *solver, const char *field, void *value) \ No newline at end of file diff --git a/third_party/acados/acados_template/acados_sim_solver_pyx.pyx b/third_party/acados/acados_template/acados_sim_solver_pyx.pyx new file mode 100644 index 0000000000..be400addc7 --- /dev/null +++ b/third_party/acados/acados_template/acados_sim_solver_pyx.pyx @@ -0,0 +1,256 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# cython: language_level=3 +# cython: profile=False +# distutils: language=c + +cimport cython +from libc cimport string +# from libc cimport bool as bool_t + +cimport acados_sim_solver_common +cimport acados_sim_solver + +cimport numpy as cnp + +import os +from datetime import datetime +import numpy as np + + +cdef class AcadosSimSolverCython: + """ + Class to interact with the acados sim solver C object. + """ + + cdef acados_sim_solver.sim_solver_capsule *capsule + cdef void *sim_dims + cdef acados_sim_solver_common.sim_opts *sim_opts + cdef acados_sim_solver_common.sim_config *sim_config + cdef acados_sim_solver_common.sim_out *sim_out + cdef acados_sim_solver_common.sim_in *sim_in + cdef acados_sim_solver_common.sim_solver *sim_solver + + cdef bint solver_created + + cdef str model_name + + cdef str sim_solver_type + + cdef list gettable_vectors + cdef list gettable_matrices + cdef list gettable_scalars + + def __cinit__(self, model_name): + + self.solver_created = False + + self.model_name = model_name + + # create capsule + self.capsule = acados_sim_solver.acados_sim_solver_create_capsule() + + # create solver + assert acados_sim_solver.acados_sim_create(self.capsule) == 0 + self.solver_created = True + + # get pointers solver + self.__get_pointers_solver() + + self.gettable_vectors = ['x', 'u', 'z', 'S_adj'] + self.gettable_matrices = ['S_forw', 'Sx', 'Su', 'S_hess', 'S_algebraic'] + self.gettable_scalars = ['CPUtime', 'time_tot', 'ADtime', 'time_ad', 'LAtime', 'time_la'] + + def __get_pointers_solver(self): + """ + Private function to get the pointers for solver + """ + # get pointers solver + self.sim_opts = acados_sim_solver.acados_get_sim_opts(self.capsule) + self.sim_dims = acados_sim_solver.acados_get_sim_dims(self.capsule) + self.sim_config = acados_sim_solver.acados_get_sim_config(self.capsule) + self.sim_out = acados_sim_solver.acados_get_sim_out(self.capsule) + self.sim_in = acados_sim_solver.acados_get_sim_in(self.capsule) + self.sim_solver = acados_sim_solver.acados_get_sim_solver(self.capsule) + + + def simulate(self, x=None, u=None, z=None, p=None): + """ + Simulate the system forward for the given x, u, z, p and return x_next. + Wrapper around `solve()` taking care of setting/getting inputs/outputs. + """ + if x is not None: + self.set('x', x) + if u is not None: + self.set('u', u) + if z is not None: + self.set('z', z) + if p is not None: + self.set('p', p) + + status = self.solve() + + if status == 2: + print("Warning: acados_sim_solver reached maximum iterations.") + elif status != 0: + raise Exception(f'acados_sim_solver for model {self.model_name} returned status {status}.') + + x_next = self.get('x') + return x_next + + + def solve(self): + """ + Solve the sim with current input. + """ + return acados_sim_solver.acados_sim_solve(self.capsule) + + + def get(self, field_): + """ + Get the last solution of the solver. + + :param str field: string in ['x', 'u', 'z', 'S_forw', 'Sx', 'Su', 'S_adj', 'S_hess', 'S_algebraic', 'CPUtime', 'time_tot', 'ADtime', 'time_ad', 'LAtime', 'time_la'] + """ + field = field_.encode('utf-8') + + if field_ in self.gettable_vectors: + return self.__get_vector(field) + elif field_ in self.gettable_matrices: + return self.__get_matrix(field) + elif field_ in self.gettable_scalars: + return self.__get_scalar(field) + else: + raise Exception(f'AcadosSimSolver.get(): Unknown field {field_},' \ + f' available fields are {", ".join(self.gettable.keys())}') + + + def __get_scalar(self, field): + cdef double scalar + acados_sim_solver_common.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, &scalar) + return scalar + + + def __get_vector(self, field): + cdef int[2] dims + acados_sim_solver_common.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, &dims[0]) + # cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.ascontiguousarray(np.zeros((dims[0],), dtype=np.float64)) + cdef cnp.ndarray[cnp.float64_t, ndim=1] out = np.zeros((dims[0]),) + acados_sim_solver_common.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, out.data) + return out + + + def __get_matrix(self, field): + cdef int[2] dims + acados_sim_solver_common.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, &dims[0]) + cdef cnp.ndarray[cnp.float64_t, ndim=2] out = np.zeros((dims[0], dims[1]), order='F', dtype=np.float64) + acados_sim_solver_common.sim_out_get(self.sim_config, self.sim_dims, self.sim_out, field, out.data) + return out + + + def set(self, field_: str, value_): + """ + Set numerical data inside the solver. + + :param field: string in ['p', 'seed_adj', 'T', 'x', 'u', 'xdot', 'z'] + :param value: the value with appropriate size. + """ + settable = ['seed_adj', 'T', 'x', 'u', 'xdot', 'z', 'p'] # S_forw + + # cast value_ to avoid conversion issues + if isinstance(value_, (float, int)): + value_ = np.array([value_]) + # if len(value_.shape) > 1: + # raise RuntimeError('AcadosSimSolverCython.set(): value_ should be 1 dimensional') + + cdef cnp.ndarray[cnp.float64_t, ndim=1] value = np.ascontiguousarray(value_, dtype=np.float64).flatten() + + field = field_.encode('utf-8') + cdef int[2] dims + + # treat parameters separately + if field_ == 'p': + assert acados_sim_solver.acados_sim_update_params(self.capsule, value.data, value.shape[0]) == 0 + return + else: + acados_sim_solver_common.sim_dims_get_from_attr(self.sim_config, self.sim_dims, field, &dims[0]) + + value_ = np.ravel(value_, order='F') + + value_shape = value_.shape + if len(value_shape) == 1: + value_shape = (value_shape[0], 0) + + if value_shape != tuple(dims): + raise Exception(f'AcadosSimSolverCython.set(): mismatching dimension' \ + f' for field "{field_}" with dimension {tuple(dims)} (you have {value_shape}).') + + # set + if field_ in ['xdot', 'z']: + acados_sim_solver_common.sim_solver_set(self.sim_solver, field, value.data) + elif field_ in settable: + acados_sim_solver_common.sim_in_set(self.sim_config, self.sim_dims, self.sim_in, field, value.data) + else: + raise Exception(f'AcadosSimSolverCython.set(): Unknown field {field_},' \ + f' available fields are {", ".join(settable)}') + + + def options_set(self, field_: str, value_: bool): + """ + Set solver options + + :param field: string in ['sens_forw', 'sens_adj', 'sens_hess'] + :param value: Boolean + """ + fields = ['sens_forw', 'sens_adj', 'sens_hess'] + if field_ not in fields: + raise Exception(f"field {field_} not supported. Supported values are {', '.join(fields)}.\n") + + field = field_.encode('utf-8') + + if not isinstance(value_, bool): + raise TypeError("options_set: expected boolean for value") + + cdef bint bool_value = value_ + acados_sim_solver_common.sim_opts_set(self.sim_config, self.sim_opts, field, &bool_value) + # TODO: only allow setting + # if getattr(self.acados_sim.solver_options, field_) or value_ == False: + # acados_sim_solver_common.sim_opts_set(self.sim_config, self.sim_opts, field, &bool_value) + # else: + # raise RuntimeError(f"Cannot set option {field_} to True, because it was False in original solver options.\n") + + return + + + def __del__(self): + if self.solver_created: + acados_sim_solver.acados_sim_free(self.capsule) + acados_sim_solver.acados_sim_solver_free_capsule(self.capsule) diff --git a/third_party/acados/acados_template/acados_solver_common.pxd b/third_party/acados/acados_template/acados_solver_common.pxd new file mode 100644 index 0000000000..c6d59d40a5 --- /dev/null +++ b/third_party/acados/acados_template/acados_solver_common.pxd @@ -0,0 +1,100 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + + +cdef extern from "acados/ocp_nlp/ocp_nlp_common.h": + ctypedef struct ocp_nlp_config: + pass + + ctypedef struct ocp_nlp_dims: + pass + + ctypedef struct ocp_nlp_in: + pass + + ctypedef struct ocp_nlp_out: + pass + + +cdef extern from "acados_c/ocp_nlp_interface.h": + ctypedef enum ocp_nlp_solver_t: + pass + + ctypedef enum ocp_nlp_cost_t: + pass + + ctypedef enum ocp_nlp_dynamics_t: + pass + + ctypedef enum ocp_nlp_constraints_t: + pass + + ctypedef enum ocp_nlp_reg_t: + pass + + ctypedef struct ocp_nlp_plan: + pass + + ctypedef struct ocp_nlp_solver: + pass + + int ocp_nlp_cost_model_set(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in_, + int start_stage, const char *field, void *value) + int ocp_nlp_constraints_model_set(ocp_nlp_config *config, ocp_nlp_dims *dims, + ocp_nlp_in *in_, int stage, const char *field, void *value) + + # out + void ocp_nlp_out_set(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, void *value) + void ocp_nlp_out_get(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, void *value) + void ocp_nlp_get_at_stage(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_solver *solver, + int stage, const char *field, void *value) + int ocp_nlp_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field) + void ocp_nlp_constraint_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, int *dims_out) + void ocp_nlp_cost_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, int *dims_out) + void ocp_nlp_qp_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, int *dims_out) + + # opts + void ocp_nlp_solver_opts_set(ocp_nlp_config *config, void *opts_, const char *field, void* value) + + # solver + void ocp_nlp_eval_residuals(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out) + void ocp_nlp_eval_param_sens(ocp_nlp_solver *solver, char *field, int stage, int index, ocp_nlp_out *sens_nlp_out) + void ocp_nlp_eval_cost(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in_, ocp_nlp_out *nlp_out) + + # get/set + void ocp_nlp_get(ocp_nlp_config *config, ocp_nlp_solver *solver, const char *field, void *return_value_) + void ocp_nlp_set(ocp_nlp_config *config, ocp_nlp_solver *solver, int stage, const char *field, void *value) diff --git a/third_party/acados/acados_template/builders.py b/third_party/acados/acados_template/builders.py new file mode 100644 index 0000000000..6f21bfe8cd --- /dev/null +++ b/third_party/acados/acados_template/builders.py @@ -0,0 +1,131 @@ +# -*- coding: future_fstrings -*- +# +# Copyright 2019 Gianluca Frison, Dimitris Kouzoupis, Robin Verschueren, +# Andrea Zanelli, Niels van Duijkeren, Jonathan Frey, Tommaso Sartor, +# Branimir Novoselnik, Rien Quirynen, Rezart Qelibari, Dang Doan, +# Jonas Koenemann, Yutao Chen, Tobias Schöls, Jonas Schlagenhauf, Moritz Diehl +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import os +import sys +from subprocess import DEVNULL, call, STDOUT + + +class CMakeBuilder: + """ + Class to work with the `CMake` build system. + """ + def __init__(self): + self._source_dir = None # private source directory, this is set to code_export_dir + self.build_dir = 'build' + self._build_dir = None # private build directory, usually rendered to abspath(build_dir) + self.generator = None + """Defines the generator, options can be found via `cmake --help` under 'Generator'. Type: string. Linux default 'Unix Makefiles', Windows 'Visual Studio 15 2017 Win64'; default value: `None`.""" + # set something for Windows + if os.name == 'nt': + self.generator = 'Visual Studio 15 2017 Win64' + self.build_targets = None + """A comma-separated list of the build targets, if `None` then all targets will be build; type: List of strings; default: `None`.""" + self.options_on = None + """List of strings as CMake options which are translated to '-D Opt[0]=ON -D Opt[1]=ON ...'; default: `None`.""" + + # Generate the command string for handling the cmake command. + def get_cmd1_cmake(self): + defines_str = '' + if self.options_on is not None: + defines_arr = [f' -D{opt}=ON' for opt in self.options_on] + defines_str = ' '.join(defines_arr) + generator_str = '' + if self.generator is not None: + generator_str = f' -G"{self.generator}"' + return f'cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="{self._source_dir}"{defines_str}{generator_str} -Wdev -S"{self._source_dir}" -B"{self._build_dir}"' + + # Generate the command string for handling the build. + def get_cmd2_build(self): + import multiprocessing + cmd = f'cmake --build "{self._build_dir}" --config Release -j{multiprocessing.cpu_count()}' + if self.build_targets is not None: + cmd += f' -t {self.build_targets}' + return cmd + + # Generate the command string for handling the install command. + def get_cmd3_install(self): + return f'cmake --install "{self._build_dir}"' + + def exec(self, code_export_directory, verbose=True): + """ + Execute the compilation using `CMake` with the given settings. + :param code_export_directory: must be the absolute path to the directory where the code was exported to + """ + if(os.path.isabs(code_export_directory) is False): + print(f'(W) the code export directory "{code_export_directory}" is not an absolute path!') + self._source_dir = code_export_directory + self._build_dir = os.path.abspath(self.build_dir) + try: + os.mkdir(self._build_dir) + except FileExistsError as e: + pass + + try: + os.chdir(self._build_dir) + cmd_str = self.get_cmd1_cmake() + print(f'call("{cmd_str})"') + retcode = call( + cmd_str, + shell=True, + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + if retcode != 0: + raise RuntimeError(f'CMake command "{cmd_str}" was terminated by signal {retcode}') + cmd_str = self.get_cmd2_build() + print(f'call("{cmd_str}")') + retcode = call( + cmd_str, + shell=True, + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + if retcode != 0: + raise RuntimeError(f'Build command "{cmd_str}" was terminated by signal {retcode}') + cmd_str = self.get_cmd3_install() + print(f'call("{cmd_str}")') + retcode = call( + cmd_str, + shell=True, + stdout=None if verbose else DEVNULL, + stderr=None if verbose else STDOUT + ) + if retcode != 0: + raise RuntimeError(f'Install command "{cmd_str}" was terminated by signal {retcode}') + except OSError as e: + print("Execution failed:", e, file=sys.stderr) + except Exception as e: + print("Execution failed:", e, file=sys.stderr) + exit(1) diff --git a/third_party/acados/acados_template/c_templates_tera/CMakeLists.in.txt b/third_party/acados/acados_template/c_templates_tera/CMakeLists.in.txt new file mode 100644 index 0000000000..99bc26f750 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/CMakeLists.in.txt @@ -0,0 +1,397 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +{%- if solver_options.qp_solver %} + {%- set qp_solver = solver_options.qp_solver %} +{%- else %} + {%- set qp_solver = "FULL_CONDENSING_HPIPM" %} +{%- endif %} + +{%- if solver_options.hessian_approx %} + {%- set hessian_approx = solver_options.hessian_approx %} +{%- elif solver_options.sens_hess %} + {%- set hessian_approx = "EXACT" %} +{%- else %} + {%- set hessian_approx = "GAUSS_NEWTON" %} +{%- endif %} + +{%- if constraints.constr_type %} + {%- set constr_type = constraints.constr_type %} +{%- else %} + {%- set constr_type = "NONE" %} +{%- endif %} + +{%- if constraints.constr_type_e %} + {%- set constr_type_e = constraints.constr_type_e %} +{%- else %} + {%- set constr_type_e = "NONE" %} +{%- endif %} + +{%- if cost.cost_type %} + {%- set cost_type = cost.cost_type %} +{%- else %} + {%- set cost_type = "NONE" %} +{%- endif %} + +{%- if cost.cost_type_e %} + {%- set cost_type_e = cost.cost_type_e %} +{%- else %} + {%- set cost_type_e = "NONE" %} +{%- endif %} + +{%- if cost.cost_type_0 %} + {%- set cost_type_0 = cost.cost_type_0 %} +{%- else %} + {%- set cost_type_0 = "NONE" %} +{%- endif %} + +{%- if dims.nh %} + {%- set dims_nh = dims.nh %} +{%- else %} + {%- set dims_nh = 0 %} +{%- endif %} + +{%- if dims.nphi %} + {%- set dims_nphi = dims.nphi %} +{%- else %} + {%- set dims_nphi = 0 %} +{%- endif %} + +{%- if dims.nh_e %} + {%- set dims_nh_e = dims.nh_e %} +{%- else %} + {%- set dims_nh_e = 0 %} +{%- endif %} + +{%- if dims.nphi_e %} + {%- set dims_nphi_e = dims.nphi_e %} +{%- else %} + {%- set dims_nphi_e = 0 %} +{%- endif %} + +{%- if solver_options.model_external_shared_lib_dir %} + {%- set model_external_shared_lib_dir = solver_options.model_external_shared_lib_dir %} +{%- endif %} + +{%- if solver_options.model_external_shared_lib_name %} + {%- set model_external_shared_lib_name = solver_options.model_external_shared_lib_name %} +{%- endif %} + +{#- control operator #} +{%- if os and os == "pc" %} + {%- set control = "&" %} +{%- else %} + {%- set control = ";" %} +{%- endif %} + +{%- if acados_link_libs and os and os == "pc" %}{# acados linking libraries and flags #} + {%- set link_libs = acados_link_libs.qpoases ~ " " ~ acados_link_libs.hpmpc ~ " " ~ acados_link_libs.osqp -%} + {%- set openmp_flag = acados_link_libs.openmp %} +{%- else %} + {%- set openmp_flag = " " %} + {%- if qp_solver == "FULL_CONDENSING_QPOASES" %} + {%- set link_libs = "-lqpOASES_e" %} + {%- elif qp_solver == "FULL_CONDENSING_DAQP" %} + {%- set link_libs = "-ldaqp" %} + {%- else %} + {%- set link_libs = "" %} + {%- endif %} +{%- endif %} + +cmake_minimum_required(VERSION 3.13) + +project({{ model.name }}) + +# build options. +option(BUILD_ACADOS_SOLVER_LIB "Should the solver library acados_solver_{{ model.name }} be build?" OFF) +option(BUILD_ACADOS_OCP_SOLVER_LIB "Should the OCP solver library acados_ocp_solver_{{ model.name }} be build?" OFF) +option(BUILD_EXAMPLE "Should the example main_{{ model.name }} be build?" OFF) +{%- if solver_options.integrator_type != "DISCRETE" %} +option(BUILD_SIM_EXAMPLE "Should the simulation example main_sim_{{ model.name }} be build?" OFF) +option(BUILD_ACADOS_SIM_SOLVER_LIB "Should the simulation solver library acados_sim_solver_{{ model.name }} be build?" OFF) +{%- endif %} + + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_SYSTEM_NAME MATCHES "Windows") + # MinGW, change to .lib such that mex recognizes it + set(CMAKE_SHARED_LIBRARY_SUFFIX ".lib") + set(CMAKE_SHARED_LIBRARY_PREFIX "") +endif() + + +# object target names +set(MODEL_OBJ model_{{ model.name }}) +set(OCP_OBJ ocp_{{ model.name }}) +set(SIM_OBJ sim_{{ model.name }}) + +# model +set(MODEL_SRC + {%- if model.dyn_ext_fun_type == "casadi" %} +{%- if solver_options.integrator_type == "ERK" %} + {{ model.name }}_model/{{ model.name }}_expl_ode_fun.c + {{ model.name }}_model/{{ model.name }}_expl_vde_forw.c + {{ model.name }}_model/{{ model.name }}_expl_vde_adj.c + {%- if hessian_approx == "EXACT" %} + {{ model.name }}_model/{{ model.name }}_expl_ode_hess.c + {%- endif %} +{%- elif solver_options.integrator_type == "IRK" %} + {{ model.name }}_model/{{ model.name }}_impl_dae_fun.c + {{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.c + {{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.c + {%- if hessian_approx == "EXACT" %} + {{ model.name }}_model/{{ model.name }}_impl_dae_hess.c + {%- endif %} +{%- elif solver_options.integrator_type == "LIFTED_IRK" %} + {{ model.name }}_model/{{ model.name }}_impl_dae_fun.c + {{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_u.c + {%- if hessian_approx == "EXACT" %} + {{ model.name }}_model/{{ model.name }}_impl_dae_hess.c + {%- endif %} +{%- elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + {{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.c + {{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.c + {{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.c + {% if model.gnsf.nontrivial_f_LO == 1 %} + {{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c + {%- endif %} + {%- endif %} + {{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.c +{%- elif solver_options.integrator_type == "DISCRETE" %} + {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun.c + {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac.c + {%- if hessian_approx == "EXACT" %} + {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac_hess.c + {%- endif %} +{%- endif -%} + {%- else %} + {{ model.name }}_model/{{ model.dyn_generic_source }} + {%- endif %} +) +add_library(${MODEL_OBJ} OBJECT ${MODEL_SRC} ) + +# optimal control problem - mostly CasADi exports +if(${BUILD_ACADOS_SOLVER_LIB} OR ${BUILD_ACADOS_OCP_SOLVER_LIB} OR ${BUILD_EXAMPLE}) + set(OCP_SRC +{%- if constr_type == "BGP" and dims_nphi > 0 %} + {{ model.name }}_constraints/{{ model.name }}_phi_constraint.c +{%- endif %} +{%- if constr_type_e == "BGP" and dims_nphi_e > 0 %} + {{ model.name }}_constraints/{{ model.name }}_phi_e_constraint.c +{%- endif %} + +{%- if constr_type == "BGH" and dims_nh > 0 %} + {{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt.c + {{ model.name }}_constraints/{{ model.name }}_constr_h_fun.c + {%- if hessian_approx == "EXACT" %} + {{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt_hess.c + {%- endif %} +{%- endif %} + +{%- if constr_type_e == "BGH" and dims_nh_e > 0 %} + {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt.c + {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun.c + {%- if hessian_approx == "EXACT" %} + {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess.c + {%- endif %} +{%- endif %} + +{%- if cost_type_0 == "NONLINEAR_LS" %} + {{ model.name }}_cost/{{ model.name }}_cost_y_0_fun.c + {{ model.name }}_cost/{{ model.name }}_cost_y_0_fun_jac_ut_xt.c + {{ model.name }}_cost/{{ model.name }}_cost_y_0_hess.c +{%- elif cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + {{ model.name }}_cost/{{ model.name }}_conl_cost_0_fun.c + {{ model.name }}_cost/{{ model.name }}_conl_cost_0_fun_jac_hess.c +{%- elif cost_type_0 == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type_0 == "casadi" %} + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun.c + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac.c + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac_hess.c + {%- else %} + {{ model.name }}_cost/{{ cost.cost_source_ext_cost_0 }} + {%- endif %} +{%- endif %} +{%- if cost_type == "NONLINEAR_LS" %} + {{ model.name }}_cost/{{ model.name }}_cost_y_fun.c + {{ model.name }}_cost/{{ model.name }}_cost_y_fun_jac_ut_xt.c + {{ model.name }}_cost/{{ model.name }}_cost_y_hess.c +{%- elif cost_type == "CONVEX_OVER_NONLINEAR" %} + {{ model.name }}_cost/{{ model.name }}_conl_cost_fun.c + {{ model.name }}_cost/{{ model.name }}_conl_cost_fun_jac_hess.c +{%- elif cost_type == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type == "casadi" %} + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun.c + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac.c + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac_hess.c + {%- elif cost.cost_source_ext_cost != cost.cost_source_ext_cost_0 %} + {{ model.name }}_cost/{{ cost.cost_source_ext_cost }} + {%- endif %} +{%- endif %} +{%- if cost_type_e == "NONLINEAR_LS" %} + {{ model.name }}_cost/{{ model.name }}_cost_y_e_fun.c + {{ model.name }}_cost/{{ model.name }}_cost_y_e_fun_jac_ut_xt.c + {{ model.name }}_cost/{{ model.name }}_cost_y_e_hess.c +{%- elif cost_type_e == "CONVEX_OVER_NONLINEAR" %} + {{ model.name }}_cost/{{ model.name }}_conl_cost_e_fun.c + {{ model.name }}_cost/{{ model.name }}_conl_cost_e_fun_jac_hess.c +{%- elif cost_type_e == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type_e == "casadi" %} + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun.c + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac.c + {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac_hess.c + {%- elif cost.cost_source_ext_cost_e != cost.cost_source_ext_cost_0 %} + {{ model.name }}_cost/{{ cost.cost_source_ext_cost_e }} + {%- endif %} +{%- endif %} + acados_solver_{{ model.name }}.c) + add_library(${OCP_OBJ} OBJECT ${OCP_SRC}) +endif() + +{%- if solver_options.integrator_type != "DISCRETE" %} +# for sim solver +if(${BUILD_ACADOS_SOLVER_LIB} OR ${BUILD_EXAMPLE} + {%- if solver_options.integrator_type != "DISCRETE" %} + OR ${BUILD_SIM_EXAMPLE} OR ${BUILD_ACADOS_SIM_SOLVER_LIB} + {%- endif -%} + ) + set(SIM_SRC acados_sim_solver_{{ model.name }}.c) + add_library(${SIM_OBJ} OBJECT ${SIM_SRC}) +endif() +{%- endif %} + +# for target example +set(EX_SRC main_{{ model.name }}.c) +set(EX_EXE main_{{ model.name }}) + +{%- if model_external_shared_lib_dir and model_external_shared_lib_name %} +set(EXTERNAL_DIR {{ model_external_shared_lib_dir | replace(from="\", to="/") }}) +set(EXTERNAL_LIB {{ model_external_shared_lib_name }}) +{%- else %} +set(EXTERNAL_DIR) +set(EXTERNAL_LIB) +{%- endif %} + +# set some search paths for preprocessor and linker +set(ACADOS_INCLUDE_PATH {{ acados_include_path | replace(from="\", to="/") }} CACHE PATH "Define the path which contains the include directory for acados.") +set(ACADOS_LIB_PATH {{ acados_lib_path | replace(from="\", to="/") }} CACHE PATH "Define the path which contains the lib directory for acados.") + +# c-compiler flags for debugging +set(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb") + +set(CMAKE_C_FLAGS "-fPIC -std=c99 {{ openmp_flag }} +{%- if qp_solver == "FULL_CONDENSING_QPOASES" -%} + -DACADOS_WITH_QPOASES +{%- endif -%} +{%- if qp_solver == "FULL_CONDENSING_DAQP" -%} + -DACADOS_WITH_DAQP +{%- endif -%} +{%- if qp_solver == "PARTIAL_CONDENSING_OSQP" -%} + -DACADOS_WITH_OSQP +{%- endif -%} +{%- if qp_solver == "PARTIAL_CONDENSING_QPDUNES" -%} + -DACADOS_WITH_QPDUNES +{%- endif -%} +") +#-fno-diagnostics-show-line-numbers -g + +include_directories( + ${ACADOS_INCLUDE_PATH} + ${ACADOS_INCLUDE_PATH}/acados + ${ACADOS_INCLUDE_PATH}/blasfeo/include + ${ACADOS_INCLUDE_PATH}/hpipm/include +{%- if qp_solver == "FULL_CONDENSING_QPOASES" %} + ${ACADOS_INCLUDE_PATH}/qpOASES_e/ +{%- endif %} +{%- if qp_solver == "FULL_CONDENSING_DAQP" %} + ${ACADOS_INCLUDE_PATH}/daqp/include +{%- endif %} +) + +# linker flags +link_directories(${ACADOS_LIB_PATH}) + +# link to libraries +if(UNIX) + link_libraries(acados hpipm blasfeo m {{ link_libs }}) +else() + link_libraries(acados hpipm blasfeo {{ link_libs }}) +endif() + +# the targets + +# bundled_shared_lib +if(${BUILD_ACADOS_SOLVER_LIB}) + set(LIB_ACADOS_SOLVER acados_solver_{{ model.name }}) + add_library(${LIB_ACADOS_SOLVER} SHARED $ $ + {%- if solver_options.integrator_type != "DISCRETE" %} + $ + {%- endif -%} + ) + install(TARGETS ${LIB_ACADOS_SOLVER} DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif(${BUILD_ACADOS_SOLVER_LIB}) + +# ocp_shared_lib +if(${BUILD_ACADOS_OCP_SOLVER_LIB}) + set(LIB_ACADOS_OCP_SOLVER acados_ocp_solver_{{ model.name }}) + add_library(${LIB_ACADOS_OCP_SOLVER} SHARED $ $) + # Specify libraries or flags to use when linking a given target and/or its dependents. + target_link_libraries(${LIB_ACADOS_OCP_SOLVER} PRIVATE ${EXTERNAL_LIB}) + target_link_directories(${LIB_ACADOS_OCP_SOLVER} PRIVATE ${EXTERNAL_DIR}) + install(TARGETS ${LIB_ACADOS_OCP_SOLVER} DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif(${BUILD_ACADOS_OCP_SOLVER_LIB}) + +# example +if(${BUILD_EXAMPLE}) + add_executable(${EX_EXE} ${EX_SRC} $ $ + {%- if solver_options.integrator_type != "DISCRETE" %} + $ + {%- endif -%} + ) + install(TARGETS ${EX_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif(${BUILD_EXAMPLE}) + +{% if solver_options.integrator_type != "DISCRETE" -%} +# example_sim +if(${BUILD_SIM_EXAMPLE}) + set(EX_SIM_SRC main_sim_{{ model.name }}.c) + set(EX_SIM_EXE main_sim_{{ model.name }}) + add_executable(${EX_SIM_EXE} ${EX_SIM_SRC} $ $) + install(TARGETS ${EX_SIM_EXE} DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif(${BUILD_SIM_EXAMPLE}) + +# sim_shared_lib +if(${BUILD_ACADOS_SIM_SOLVER_LIB}) + set(LIB_ACADOS_SIM_SOLVER acados_sim_solver_{{ model.name }}) + add_library(${LIB_ACADOS_SIM_SOLVER} SHARED $ $) + install(TARGETS ${LIB_ACADOS_SIM_SOLVER} DESTINATION ${CMAKE_INSTALL_PREFIX}) +endif(${BUILD_ACADOS_SIM_SOLVER_LIB}) +{%- endif %} + diff --git a/third_party/acados/acados_template/c_templates_tera/Makefile.in b/third_party/acados/acados_template/c_templates_tera/Makefile.in new file mode 100644 index 0000000000..fbefc08e38 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/Makefile.in @@ -0,0 +1,468 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +{%- if solver_options.qp_solver %} + {%- set qp_solver = solver_options.qp_solver %} +{%- else %} + {%- set qp_solver = "FULL_CONDENSING_HPIPM" %} +{%- endif %} + +{%- if solver_options.hessian_approx %} + {%- set hessian_approx = solver_options.hessian_approx %} +{%- elif solver_options.sens_hess %} + {%- set hessian_approx = "EXACT" %} +{%- else %} + {%- set hessian_approx = "GAUSS_NEWTON" %} +{%- endif %} + +{%- if constraints.constr_type %} + {%- set constr_type = constraints.constr_type %} +{%- else %} + {%- set constr_type = "NONE" %} +{%- endif %} + +{%- if constraints.constr_type_e %} + {%- set constr_type_e = constraints.constr_type_e %} +{%- else %} + {%- set constr_type_e = "NONE" %} +{%- endif %} + +{%- if cost.cost_type %} + {%- set cost_type = cost.cost_type %} +{%- else %} + {%- set cost_type = "NONE" %} +{%- endif %} + +{%- if cost.cost_type_e %} + {%- set cost_type_e = cost.cost_type_e %} +{%- else %} + {%- set cost_type_e = "NONE" %} +{%- endif %} + +{%- if cost.cost_type_0 %} + {%- set cost_type_0 = cost.cost_type_0 %} +{%- else %} + {%- set cost_type_0 = "NONE" %} +{%- endif %} + +{%- if dims.nh %} + {%- set dims_nh = dims.nh %} +{%- else %} + {%- set dims_nh = 0 %} +{%- endif %} + +{%- if dims.nphi %} + {%- set dims_nphi = dims.nphi %} +{%- else %} + {%- set dims_nphi = 0 %} +{%- endif %} + +{%- if dims.nh_e %} + {%- set dims_nh_e = dims.nh_e %} +{%- else %} + {%- set dims_nh_e = 0 %} +{%- endif %} + +{%- if dims.nphi_e %} + {%- set dims_nphi_e = dims.nphi_e %} +{%- else %} + {%- set dims_nphi_e = 0 %} +{%- endif %} +{%- if solver_options.model_external_shared_lib_dir %} + {%- set model_external_shared_lib_dir = solver_options.model_external_shared_lib_dir %} +{%- endif %} +{%- if solver_options.model_external_shared_lib_name %} + {%- set model_external_shared_lib_name = solver_options.model_external_shared_lib_name %} +{%- endif %} + +{# control operator #} +{%- if os and os == "pc" %} + {%- set control = "&" %} +{%- else %} + {%- set control = ";" %} +{%- endif %} + +{# acados linking libraries and flags #} +{%- if acados_link_libs and os and os == "pc" %} + {%- set link_libs = acados_link_libs.qpoases ~ " " ~ acados_link_libs.hpmpc ~ " " ~ acados_link_libs.osqp -%} + {%- set openmp_flag = acados_link_libs.openmp %} +{%- else %} + {%- set openmp_flag = " " %} + {%- if qp_solver == "FULL_CONDENSING_QPOASES" %} + {%- set link_libs = "-lqpOASES_e" %} + {%- elif qp_solver == "FULL_CONDENSING_DAQP" %} + {%- set link_libs = "-ldaqp" %} + {%- else %} + {%- set link_libs = "" %} + {%- endif %} +{%- endif %} + +# define sources and use make's implicit rules to generate object files (*.o) + +# model +MODEL_SRC= + {%- if model.dyn_ext_fun_type == "casadi" %} +{%- if solver_options.integrator_type == "ERK" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_expl_ode_fun.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_expl_vde_forw.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_expl_vde_adj.c + {%- if hessian_approx == "EXACT" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_expl_ode_hess.c + {%- endif %} +{%- elif solver_options.integrator_type == "IRK" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.c + {%- if hessian_approx == "EXACT" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_hess.c + {%- endif %} +{%- elif solver_options.integrator_type == "LIFTED_IRK" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_u.c + {%- if hessian_approx == "EXACT" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_impl_dae_hess.c + {%- endif %} +{%- elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.c + {% if model.gnsf.nontrivial_f_LO == 1 %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c + {%- endif %} + {%- endif %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.c +{%- elif solver_options.integrator_type == "DISCRETE" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun.c +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac.c + {%- if hessian_approx == "EXACT" %} +MODEL_SRC+= {{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac_hess.c + {%- endif %} +{%- endif %} + {%- else %} +MODEL_SRC+= {{ model.name }}_model/{{ model.dyn_generic_source }} + {%- endif %} +MODEL_OBJ := $(MODEL_SRC:.c=.o) + +# optimal control problem - mostly CasADi exports +OCP_SRC= +{%- if constr_type == "BGP" and dims_nphi > 0 %} +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_phi_constraint.c +{%- endif %} +{%- if constr_type_e == "BGP" and dims_nphi_e > 0 %} +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_phi_e_constraint.c +{%- endif %} + +{%- if constr_type == "BGH" and dims_nh > 0 %} +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt.c +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_constr_h_fun.c + {%- if hessian_approx == "EXACT" %} +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt_hess.c + {%- endif %} +{%- endif %} + +{%- if constr_type_e == "BGH" and dims_nh_e > 0 %} +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt.c +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun.c + {%- if hessian_approx == "EXACT" %} +OCP_SRC+= {{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess.c + {%- endif %} +{%- endif %} + +{%- if cost_type_0 == "NONLINEAR_LS" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_0_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_0_fun_jac_ut_xt.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_0_hess.c +{%- elif cost_type_0 == "CONVEX_OVER_NONLINEAR" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_conl_cost_0_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_conl_cost_0_fun_jac_hess.c +{%- elif cost_type_0 == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type_0 == "casadi" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac_hess.c + {%- else %} +OCP_SRC+= {{ model.name }}_cost/{{ cost.cost_source_ext_cost_0 }} + {%- endif %} +{%- endif %} +{%- if cost_type == "NONLINEAR_LS" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_fun_jac_ut_xt.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_hess.c +{%- elif cost_type == "CONVEX_OVER_NONLINEAR" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_conl_cost_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_conl_cost_fun_jac_hess.c +{%- elif cost_type == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type == "casadi" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac_hess.c + {%- elif cost.cost_source_ext_cost != cost.cost_source_ext_cost_0 %} +OCP_SRC+= {{ model.name }}_cost/{{ cost.cost_source_ext_cost }} + {%- endif %} +{%- endif %} +{%- if cost_type_e == "NONLINEAR_LS" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_e_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_e_fun_jac_ut_xt.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_y_e_hess.c +{%- elif cost_type_e == "CONVEX_OVER_NONLINEAR" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_conl_cost_e_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_conl_cost_e_fun_jac_hess.c +{%- elif cost_type_e == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type_e == "casadi" %} +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac.c +OCP_SRC+= {{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac_hess.c + {%- elif cost.cost_source_ext_cost_e != cost.cost_source_ext_cost_0 %} +OCP_SRC+= {{ model.name }}_cost/{{ cost.cost_source_ext_cost_e }} + {%- endif %} +{%- endif %} +{%- if solver_options.custom_update_filename %} + {%- if solver_options.custom_update_filename != "" %} +OCP_SRC+= {{ solver_options.custom_update_filename }} + {%- endif %} +{%- endif %} + +OCP_SRC+= acados_solver_{{ model.name }}.c +OCP_OBJ := $(OCP_SRC:.c=.o) + +# for sim solver +SIM_SRC= acados_sim_solver_{{ model.name }}.c +SIM_OBJ := $(SIM_SRC:.c=.o) + +# for target example +EX_SRC= main_{{ model.name }}.c +EX_OBJ := $(EX_SRC:.c=.o) +EX_EXE := $(EX_SRC:.c=) + +# for target example_sim +EX_SIM_SRC= main_sim_{{ model.name }}.c +EX_SIM_OBJ := $(EX_SIM_SRC:.c=.o) +EX_SIM_EXE := $(EX_SIM_SRC:.c=) + +# combine model, sim and ocp object files +OBJ= +OBJ+= $(MODEL_OBJ) +{%- if solver_options.integrator_type != "DISCRETE" %} +OBJ+= $(SIM_OBJ) +{%- endif %} +OBJ+= $(OCP_OBJ) + +EXTERNAL_DIR= +EXTERNAL_LIB= + +{%- if model_external_shared_lib_dir and model_external_shared_lib_name %} +EXTERNAL_DIR+= {{ model_external_shared_lib_dir }} +EXTERNAL_LIB+= {{ model_external_shared_lib_name }} +{%- endif %} + +INCLUDE_PATH = {{ acados_include_path }} +LIB_PATH = {{ acados_lib_path }} + +# preprocessor flags for make's implicit rules +{%- if qp_solver == "FULL_CONDENSING_QPOASES" %} +CPPFLAGS += -DACADOS_WITH_QPOASES +{%- endif %} +{%- if qp_solver == "FULL_CONDENSING_DAQP" %} +CPPFLAGS += -DACADOS_WITH_DAQP +{%- endif %} +{%- if qp_solver == "PARTIAL_CONDENSING_OSQP" %} +CPPFLAGS += -DACADOS_WITH_OSQP +{%- endif %} +{%- if qp_solver == "PARTIAL_CONDENSING_QPDUNES" %} +CPPFLAGS += -DACADOS_WITH_QPDUNES +{%- endif %} +CPPFLAGS+= -I$(INCLUDE_PATH) +CPPFLAGS+= -I$(INCLUDE_PATH)/acados +CPPFLAGS+= -I$(INCLUDE_PATH)/blasfeo/include +CPPFLAGS+= -I$(INCLUDE_PATH)/hpipm/include + {%- if qp_solver == "FULL_CONDENSING_QPOASES" %} +CPPFLAGS+= -I $(INCLUDE_PATH)/qpOASES_e/ + {%- endif %} + {%- if qp_solver == "FULL_CONDENSING_DAQP" %} +CPPFLAGS+= -I $(INCLUDE_PATH)/daqp/include + {%- endif %} + +{# c-compiler flags #} +# define the c-compiler flags for make's implicit rules +CFLAGS = -fPIC -std=c99 {{ openmp_flag }} {{ solver_options.ext_fun_compile_flags }}#-fno-diagnostics-show-line-numbers -g +# # Debugging +# CFLAGS += -g3 + +# linker flags +LDFLAGS+= -L$(LIB_PATH) + +# link to libraries +LDLIBS+= -lacados +LDLIBS+= -lhpipm +LDLIBS+= -lblasfeo +LDLIBS+= -lm +LDLIBS+= {{ link_libs }} + +# libraries +LIBACADOS_SOLVER=libacados_solver_{{ model.name }}{{ shared_lib_ext }} +LIBACADOS_OCP_SOLVER=libacados_ocp_solver_{{ model.name }}{{ shared_lib_ext }} +LIBACADOS_SIM_SOLVER=lib$(SIM_SRC:.c={{ shared_lib_ext }}) + +# virtual targets +.PHONY : all clean + +#all: clean example_sim example shared_lib +{% if solver_options.integrator_type == "DISCRETE" -%} +all: clean example +shared_lib: ocp_shared_lib +{%- else %} +all: clean example_sim example +shared_lib: bundled_shared_lib ocp_shared_lib sim_shared_lib +{%- endif %} + +# some linker targets +example: $(EX_OBJ) $(OBJ) + $(CC) $^ -o $(EX_EXE) $(LDFLAGS) $(LDLIBS) + +example_sim: $(EX_SIM_OBJ) $(MODEL_OBJ) $(SIM_OBJ) + $(CC) $^ -o $(EX_SIM_EXE) $(LDFLAGS) $(LDLIBS) + +{% if solver_options.integrator_type != "DISCRETE" -%} +bundled_shared_lib: $(OBJ) + $(CC) -shared $^ -o $(LIBACADOS_SOLVER) $(LDFLAGS) $(LDLIBS) +{%- endif %} + +ocp_shared_lib: $(OCP_OBJ) $(MODEL_OBJ) + $(CC) -shared $^ -o $(LIBACADOS_OCP_SOLVER) $(LDFLAGS) $(LDLIBS) \ + -L$(EXTERNAL_DIR) -l$(EXTERNAL_LIB) + +sim_shared_lib: $(SIM_OBJ) $(MODEL_OBJ) + $(CC) -shared $^ -o $(LIBACADOS_SIM_SOLVER) $(LDFLAGS) $(LDLIBS) + + +# Cython targets +ocp_cython_c: ocp_shared_lib + cython \ + -o acados_ocp_solver_pyx.c \ + -I $(INCLUDE_PATH)/../interfaces/acados_template/acados_template \ + $(INCLUDE_PATH)/../interfaces/acados_template/acados_template/acados_ocp_solver_pyx.pyx \ + -I {{ code_export_directory }} \ + +ocp_cython_o: ocp_cython_c + $(CC) $(ACADOS_FLAGS) -c -O2 \ + -fPIC \ + -o acados_ocp_solver_pyx.o \ + -I $(INCLUDE_PATH)/blasfeo/include/ \ + -I $(INCLUDE_PATH)/hpipm/include/ \ + -I $(INCLUDE_PATH) \ + {%- for path in cython_include_dirs %} + -I {{ path }} \ + {%- endfor %} + acados_ocp_solver_pyx.c \ + +ocp_cython: ocp_cython_o + $(CC) $(ACADOS_FLAGS) -shared \ + -o acados_ocp_solver_pyx{{ shared_lib_ext }} \ + -Wl,-rpath=$(LIB_PATH) \ + acados_ocp_solver_pyx.o \ + $(abspath .)/libacados_ocp_solver_{{ model.name }}{{ shared_lib_ext }} \ + $(LDFLAGS) $(LDLIBS) + +# Sim Cython targets +sim_cython_c: sim_shared_lib + cython \ + -o acados_sim_solver_pyx.c \ + -I $(INCLUDE_PATH)/../interfaces/acados_template/acados_template \ + $(INCLUDE_PATH)/../interfaces/acados_template/acados_template/acados_sim_solver_pyx.pyx \ + -I {{ code_export_directory }} \ + +sim_cython_o: sim_cython_c + $(CC) $(ACADOS_FLAGS) -c -O2 \ + -fPIC \ + -o acados_sim_solver_pyx.o \ + -I $(INCLUDE_PATH)/blasfeo/include/ \ + -I $(INCLUDE_PATH)/hpipm/include/ \ + -I $(INCLUDE_PATH) \ + {%- for path in cython_include_dirs %} + -I {{ path }} \ + {%- endfor %} + acados_sim_solver_pyx.c \ + +sim_cython: sim_cython_o + $(CC) $(ACADOS_FLAGS) -shared \ + -o acados_sim_solver_pyx{{ shared_lib_ext }} \ + -Wl,-rpath=$(LIB_PATH) \ + acados_sim_solver_pyx.o \ + $(abspath .)/libacados_sim_solver_{{ model.name }}{{ shared_lib_ext }} \ + $(LDFLAGS) $(LDLIBS) + +{%- if os and os == "pc" %} + +clean: + del \Q *.o 2>nul + del \Q *{{ shared_lib_ext }} 2>nul + del \Q main_{{ model.name }} 2>nul + +clean_ocp_shared_lib: + del \Q libacados_ocp_solver_{{ model.name }}{{ shared_lib_ext }} 2>nul + del \Q acados_solver_{{ model.name }}.o 2>nul + +clean_ocp_cython: + del \Q libacados_ocp_solver_{{ model.name }}{{ shared_lib_ext }} 2>nul + del \Q acados_solver_{{ model.name }}.o 2>nul + del \Q acados_ocp_solver_pyx{{ shared_lib_ext }} 2>nul + del \Q acados_ocp_solver_pyx.o 2>nul + +clean_sim_cython: + del \Q libacados_sim_solver_{{ model.name }}{{ shared_lib_ext }} 2>nul + del \Q acados_sim_solver_{{ model.name }}.o 2>nul + del \Q acados_sim_solver_pyx{{ shared_lib_ext }} 2>nul + del \Q acados_sim_solver_pyx.o 2>nul + +{%- else %} + +clean: + $(RM) $(OBJ) $(EX_OBJ) $(EX_SIM_OBJ) + $(RM) $(LIBACADOS_SOLVER) $(LIBACADOS_OCP_SOLVER) $(LIBACADOS_SIM_SOLVER) + $(RM) $(EX_EXE) $(EX_SIM_EXE) + +clean_ocp_shared_lib: + $(RM) $(LIBACADOS_OCP_SOLVER) + $(RM) $(OCP_OBJ) + +clean_ocp_cython: + $(RM) libacados_ocp_solver_{{ model.name }}{{ shared_lib_ext }} + $(RM) acados_solver_{{ model.name }}.o + $(RM) acados_ocp_solver_pyx{{ shared_lib_ext }} + $(RM) acados_ocp_solver_pyx.o + +clean_sim_cython: + $(RM) libacados_sim_solver_{{ model.name }}{{ shared_lib_ext }} + $(RM) acados_sim_solver_{{ model.name }}.o + $(RM) acados_sim_solver_pyx{{ shared_lib_ext }} + $(RM) acados_sim_solver_pyx.o + +{%- endif %} diff --git a/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.c b/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.c new file mode 100644 index 0000000000..0cd098273c --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +{%- if solver_options.hessian_approx %} + {%- set hessian_approx = solver_options.hessian_approx %} +{%- elif solver_options.sens_hess %} + {%- set hessian_approx = "EXACT" %} +{%- else %} + {%- set hessian_approx = "GAUSS_NEWTON" %} +{%- endif %} +// standard +#include +#include + +// acados +#include "acados_c/external_function_interface.h" +#include "acados_c/sim_interface.h" +#include "acados_c/external_function_interface.h" + +#include "acados/sim/sim_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/print.h" + + +// example specific +#include "{{ model.name }}_model/{{ model.name }}_model.h" +#include "acados_sim_solver_{{ model.name }}.h" + + +// ** solver data ** + +sim_solver_capsule * {{ model.name }}_acados_sim_solver_create_capsule() +{ + void* capsule_mem = malloc(sizeof(sim_solver_capsule)); + sim_solver_capsule *capsule = (sim_solver_capsule *) capsule_mem; + + return capsule; +} + + +int {{ model.name }}_acados_sim_solver_free_capsule(sim_solver_capsule * capsule) +{ + free(capsule); + return 0; +} + + +int {{ model.name }}_acados_sim_create(sim_solver_capsule * capsule) +{ + // initialize + const int nx = {{ model.name | upper }}_NX; + const int nu = {{ model.name | upper }}_NU; + const int nz = {{ model.name | upper }}_NZ; + const int np = {{ model.name | upper }}_NP; + bool tmp_bool; + + {#// double Tsim = {{ solver_options.tf / dims.N }};#} + double Tsim = {{ solver_options.Tsim }}; + + {% if solver_options.integrator_type == "IRK" %} + capsule->sim_impl_dae_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + capsule->sim_impl_dae_fun_jac_x_xdot_z = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + capsule->sim_impl_dae_jac_x_xdot_u_z = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + + {%- if model.dyn_ext_fun_type == "casadi" %} + // external functions (implicit model) + capsule->sim_impl_dae_fun->casadi_fun = &{{ model.name }}_impl_dae_fun; + capsule->sim_impl_dae_fun->casadi_work = &{{ model.name }}_impl_dae_fun_work; + capsule->sim_impl_dae_fun->casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_sparsity_in; + capsule->sim_impl_dae_fun->casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_sparsity_out; + capsule->sim_impl_dae_fun->casadi_n_in = &{{ model.name }}_impl_dae_fun_n_in; + capsule->sim_impl_dae_fun->casadi_n_out = &{{ model.name }}_impl_dae_fun_n_out; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_impl_dae_fun, np); + + capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_fun = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z; + capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_work = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_work; + capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_sparsity_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_in; + capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_sparsity_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_out; + capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_n_in = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_in; + capsule->sim_impl_dae_fun_jac_x_xdot_z->casadi_n_out = &{{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_out; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_impl_dae_fun_jac_x_xdot_z, np); + + // external_function_param_{{ model.dyn_ext_fun_type }} impl_dae_jac_x_xdot_u_z; + capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_fun = &{{ model.name }}_impl_dae_jac_x_xdot_u_z; + capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_work = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_work; + capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_sparsity_in = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_in; + capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_sparsity_out = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_out; + capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_n_in = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_n_in; + capsule->sim_impl_dae_jac_x_xdot_u_z->casadi_n_out = &{{ model.name }}_impl_dae_jac_x_xdot_u_z_n_out; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_impl_dae_jac_x_xdot_u_z, np); + {%- else %} + capsule->sim_impl_dae_fun->fun = &{{ model.dyn_impl_dae_fun }}; + capsule->sim_impl_dae_fun_jac_x_xdot_z->fun = &{{ model.dyn_impl_dae_fun_jac }}; + capsule->sim_impl_dae_jac_x_xdot_u_z->fun = &{{ model.dyn_impl_dae_jac }}; + {%- endif %} + +{%- if hessian_approx == "EXACT" %} + capsule->sim_impl_dae_hess = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + // external_function_param_{{ model.dyn_ext_fun_type }} impl_dae_jac_x_xdot_u_z; + capsule->sim_impl_dae_hess->casadi_fun = &{{ model.name }}_impl_dae_hess; + capsule->sim_impl_dae_hess->casadi_work = &{{ model.name }}_impl_dae_hess_work; + capsule->sim_impl_dae_hess->casadi_sparsity_in = &{{ model.name }}_impl_dae_hess_sparsity_in; + capsule->sim_impl_dae_hess->casadi_sparsity_out = &{{ model.name }}_impl_dae_hess_sparsity_out; + capsule->sim_impl_dae_hess->casadi_n_in = &{{ model.name }}_impl_dae_hess_n_in; + capsule->sim_impl_dae_hess->casadi_n_out = &{{ model.name }}_impl_dae_hess_n_out; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_impl_dae_hess, np); +{%- endif %} + + {% elif solver_options.integrator_type == "ERK" %} + // explicit ode + capsule->sim_forw_vde_casadi = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + capsule->sim_vde_adj_casadi = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + capsule->sim_expl_ode_fun_casadi = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + + capsule->sim_forw_vde_casadi->casadi_fun = &{{ model.name }}_expl_vde_forw; + capsule->sim_forw_vde_casadi->casadi_n_in = &{{ model.name }}_expl_vde_forw_n_in; + capsule->sim_forw_vde_casadi->casadi_n_out = &{{ model.name }}_expl_vde_forw_n_out; + capsule->sim_forw_vde_casadi->casadi_sparsity_in = &{{ model.name }}_expl_vde_forw_sparsity_in; + capsule->sim_forw_vde_casadi->casadi_sparsity_out = &{{ model.name }}_expl_vde_forw_sparsity_out; + capsule->sim_forw_vde_casadi->casadi_work = &{{ model.name }}_expl_vde_forw_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_forw_vde_casadi, np); + + capsule->sim_vde_adj_casadi->casadi_fun = &{{ model.name }}_expl_vde_adj; + capsule->sim_vde_adj_casadi->casadi_n_in = &{{ model.name }}_expl_vde_adj_n_in; + capsule->sim_vde_adj_casadi->casadi_n_out = &{{ model.name }}_expl_vde_adj_n_out; + capsule->sim_vde_adj_casadi->casadi_sparsity_in = &{{ model.name }}_expl_vde_adj_sparsity_in; + capsule->sim_vde_adj_casadi->casadi_sparsity_out = &{{ model.name }}_expl_vde_adj_sparsity_out; + capsule->sim_vde_adj_casadi->casadi_work = &{{ model.name }}_expl_vde_adj_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_vde_adj_casadi, np); + + capsule->sim_expl_ode_fun_casadi->casadi_fun = &{{ model.name }}_expl_ode_fun; + capsule->sim_expl_ode_fun_casadi->casadi_n_in = &{{ model.name }}_expl_ode_fun_n_in; + capsule->sim_expl_ode_fun_casadi->casadi_n_out = &{{ model.name }}_expl_ode_fun_n_out; + capsule->sim_expl_ode_fun_casadi->casadi_sparsity_in = &{{ model.name }}_expl_ode_fun_sparsity_in; + capsule->sim_expl_ode_fun_casadi->casadi_sparsity_out = &{{ model.name }}_expl_ode_fun_sparsity_out; + capsule->sim_expl_ode_fun_casadi->casadi_work = &{{ model.name }}_expl_ode_fun_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_expl_ode_fun_casadi, np); + +{%- if hessian_approx == "EXACT" %} + capsule->sim_expl_ode_hess = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + // external_function_param_{{ model.dyn_ext_fun_type }} impl_dae_jac_x_xdot_u_z; + capsule->sim_expl_ode_hess->casadi_fun = &{{ model.name }}_expl_ode_hess; + capsule->sim_expl_ode_hess->casadi_work = &{{ model.name }}_expl_ode_hess_work; + capsule->sim_expl_ode_hess->casadi_sparsity_in = &{{ model.name }}_expl_ode_hess_sparsity_in; + capsule->sim_expl_ode_hess->casadi_sparsity_out = &{{ model.name }}_expl_ode_hess_sparsity_out; + capsule->sim_expl_ode_hess->casadi_n_in = &{{ model.name }}_expl_ode_hess_n_in; + capsule->sim_expl_ode_hess->casadi_n_out = &{{ model.name }}_expl_ode_hess_n_out; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_expl_ode_hess, np); +{%- endif %} + + {% elif solver_options.integrator_type == "GNSF" -%} + {% if model.gnsf.purely_linear != 1 %} + capsule->sim_gnsf_phi_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + capsule->sim_gnsf_phi_fun_jac_y = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + capsule->sim_gnsf_phi_jac_y_uhat = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + {% if model.gnsf.nontrivial_f_LO == 1 %} + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + {%- endif %} + {%- endif %} + capsule->sim_gnsf_get_matrices_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})); + + {% if model.gnsf.purely_linear != 1 %} + capsule->sim_gnsf_phi_fun->casadi_fun = &{{ model.name }}_gnsf_phi_fun; + capsule->sim_gnsf_phi_fun->casadi_n_in = &{{ model.name }}_gnsf_phi_fun_n_in; + capsule->sim_gnsf_phi_fun->casadi_n_out = &{{ model.name }}_gnsf_phi_fun_n_out; + capsule->sim_gnsf_phi_fun->casadi_sparsity_in = &{{ model.name }}_gnsf_phi_fun_sparsity_in; + capsule->sim_gnsf_phi_fun->casadi_sparsity_out = &{{ model.name }}_gnsf_phi_fun_sparsity_out; + capsule->sim_gnsf_phi_fun->casadi_work = &{{ model.name }}_gnsf_phi_fun_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_gnsf_phi_fun, np); + + capsule->sim_gnsf_phi_fun_jac_y->casadi_fun = &{{ model.name }}_gnsf_phi_fun_jac_y; + capsule->sim_gnsf_phi_fun_jac_y->casadi_n_in = &{{ model.name }}_gnsf_phi_fun_jac_y_n_in; + capsule->sim_gnsf_phi_fun_jac_y->casadi_n_out = &{{ model.name }}_gnsf_phi_fun_jac_y_n_out; + capsule->sim_gnsf_phi_fun_jac_y->casadi_sparsity_in = &{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_in; + capsule->sim_gnsf_phi_fun_jac_y->casadi_sparsity_out = &{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_out; + capsule->sim_gnsf_phi_fun_jac_y->casadi_work = &{{ model.name }}_gnsf_phi_fun_jac_y_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_gnsf_phi_fun_jac_y, np); + + capsule->sim_gnsf_phi_jac_y_uhat->casadi_fun = &{{ model.name }}_gnsf_phi_jac_y_uhat; + capsule->sim_gnsf_phi_jac_y_uhat->casadi_n_in = &{{ model.name }}_gnsf_phi_jac_y_uhat_n_in; + capsule->sim_gnsf_phi_jac_y_uhat->casadi_n_out = &{{ model.name }}_gnsf_phi_jac_y_uhat_n_out; + capsule->sim_gnsf_phi_jac_y_uhat->casadi_sparsity_in = &{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_in; + capsule->sim_gnsf_phi_jac_y_uhat->casadi_sparsity_out = &{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_out; + capsule->sim_gnsf_phi_jac_y_uhat->casadi_work = &{{ model.name }}_gnsf_phi_jac_y_uhat_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_gnsf_phi_jac_y_uhat, np); + + {% if model.gnsf.nontrivial_f_LO == 1 %} + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_fun = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz; + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_n_in = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_in; + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_n_out = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_out; + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_sparsity_in = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_in; + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_sparsity_out = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_out; + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z->casadi_work = &{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z, np); + {%- endif %} + {%- endif %} + + capsule->sim_gnsf_get_matrices_fun->casadi_fun = &{{ model.name }}_gnsf_get_matrices_fun; + capsule->sim_gnsf_get_matrices_fun->casadi_n_in = &{{ model.name }}_gnsf_get_matrices_fun_n_in; + capsule->sim_gnsf_get_matrices_fun->casadi_n_out = &{{ model.name }}_gnsf_get_matrices_fun_n_out; + capsule->sim_gnsf_get_matrices_fun->casadi_sparsity_in = &{{ model.name }}_gnsf_get_matrices_fun_sparsity_in; + capsule->sim_gnsf_get_matrices_fun->casadi_sparsity_out = &{{ model.name }}_gnsf_get_matrices_fun_sparsity_out; + capsule->sim_gnsf_get_matrices_fun->casadi_work = &{{ model.name }}_gnsf_get_matrices_fun_work; + external_function_param_{{ model.dyn_ext_fun_type }}_create(capsule->sim_gnsf_get_matrices_fun, np); + {% endif %} + + // sim plan & config + sim_solver_plan_t plan; + plan.sim_solver = {{ solver_options.integrator_type }}; + + // create correct config based on plan + sim_config * {{ model.name }}_sim_config = sim_config_create(plan); + capsule->acados_sim_config = {{ model.name }}_sim_config; + + // sim dims + void *{{ model.name }}_sim_dims = sim_dims_create({{ model.name }}_sim_config); + capsule->acados_sim_dims = {{ model.name }}_sim_dims; + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nx", &nx); + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nu", &nu); + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nz", &nz); +{% if solver_options.integrator_type == "GNSF" %} + int gnsf_nx1 = {{ dims.gnsf_nx1 }}; + int gnsf_nz1 = {{ dims.gnsf_nz1 }}; + int gnsf_nout = {{ dims.gnsf_nout }}; + int gnsf_ny = {{ dims.gnsf_ny }}; + int gnsf_nuhat = {{ dims.gnsf_nuhat }}; + + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nx1", &gnsf_nx1); + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nz1", &gnsf_nz1); + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nout", &gnsf_nout); + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "ny", &gnsf_ny); + sim_dims_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, "nuhat", &gnsf_nuhat); +{% endif %} + + // sim opts + sim_opts *{{ model.name }}_sim_opts = sim_opts_create({{ model.name }}_sim_config, {{ model.name }}_sim_dims); + capsule->acados_sim_opts = {{ model.name }}_sim_opts; + int tmp_int = {{ solver_options.sim_method_newton_iter }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "newton_iter", &tmp_int); + double tmp_double = {{ solver_options.sim_method_newton_tol }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "newton_tol", &tmp_double); + sim_collocation_type collocation_type = {{ solver_options.collocation_type }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "collocation_type", &collocation_type); + +{% if problem_class == "SIM" %} + tmp_int = {{ solver_options.sim_method_num_stages }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_stages", &tmp_int); + tmp_int = {{ solver_options.sim_method_num_steps }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_steps", &tmp_int); + + // options that are not available to AcadosOcpSolver + // (in OCP they will be determined by other options, like exact_hessian) + tmp_bool = {{ solver_options.sens_forw }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_forw", &tmp_bool); + tmp_bool = {{ solver_options.sens_adj }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_adj", &tmp_bool); + tmp_bool = {{ solver_options.sens_algebraic }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_algebraic", &tmp_bool); + tmp_bool = {{ solver_options.sens_hess }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "sens_hess", &tmp_bool); + tmp_bool = {{ solver_options.output_z }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "output_z", &tmp_bool); + +{% else %} {# num_stages and num_steps of first shooting interval are used #} + tmp_int = {{ solver_options.sim_method_num_stages[0] }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_stages", &tmp_int); + tmp_int = {{ solver_options.sim_method_num_steps[0] }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "num_steps", &tmp_int); + tmp_bool = {{ solver_options.sim_method_jac_reuse[0] }}; + sim_opts_set({{ model.name }}_sim_config, {{ model.name }}_sim_opts, "jac_reuse", &tmp_bool); +{% endif %} + + // sim in / out + sim_in *{{ model.name }}_sim_in = sim_in_create({{ model.name }}_sim_config, {{ model.name }}_sim_dims); + capsule->acados_sim_in = {{ model.name }}_sim_in; + sim_out *{{ model.name }}_sim_out = sim_out_create({{ model.name }}_sim_config, {{ model.name }}_sim_dims); + capsule->acados_sim_out = {{ model.name }}_sim_out; + + sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, + {{ model.name }}_sim_in, "T", &Tsim); + + // model functions +{%- if solver_options.integrator_type == "IRK" %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "impl_ode_fun", capsule->sim_impl_dae_fun); + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "impl_ode_fun_jac_x_xdot", capsule->sim_impl_dae_fun_jac_x_xdot_z); + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "impl_ode_jac_x_xdot_u", capsule->sim_impl_dae_jac_x_xdot_u_z); +{%- if hessian_approx == "EXACT" %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "impl_dae_hess", capsule->sim_impl_dae_hess); +{%- endif %} + +{%- elif solver_options.integrator_type == "ERK" %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "expl_vde_forw", capsule->sim_forw_vde_casadi); + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "expl_vde_adj", capsule->sim_vde_adj_casadi); + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "expl_ode_fun", capsule->sim_expl_ode_fun_casadi); +{%- if hessian_approx == "EXACT" %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "expl_ode_hess", capsule->sim_expl_ode_hess); +{%- endif %} +{%- elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "phi_fun", capsule->sim_gnsf_phi_fun); + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "phi_fun_jac_y", capsule->sim_gnsf_phi_fun_jac_y); + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "phi_jac_y_uhat", capsule->sim_gnsf_phi_jac_y_uhat); + {% if model.gnsf.nontrivial_f_LO == 1 %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "f_lo_jac_x1_x1dot_u_z", capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z); + {%- endif %} + {%- endif %} + {{ model.name }}_sim_config->model_set({{ model.name }}_sim_in->model, + "gnsf_get_matrices_fun", capsule->sim_gnsf_get_matrices_fun); +{%- endif %} + + // sim solver + sim_solver *{{ model.name }}_sim_solver = sim_solver_create({{ model.name }}_sim_config, + {{ model.name }}_sim_dims, {{ model.name }}_sim_opts); + capsule->acados_sim_solver = {{ model.name }}_sim_solver; + +{% if dims.np > 0 %} + /* initialize parameter values */ + double* p = calloc(np, sizeof(double)); + {% for item in parameter_values %} + {%- if item != 0 %} + p[{{ loop.index0 }}] = {{ item }}; + {%- endif %} + {%- endfor %} + + {{ model.name }}_acados_sim_update_params(capsule, p, np); + free(p); +{% endif %}{# if dims.np #} + + /* initialize input */ + // x + double x0[{{ dims.nx }}]; + for (int ii = 0; ii < {{ dims.nx }}; ii++) + x0[ii] = 0.0; + + sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, + {{ model.name }}_sim_in, "x", x0); + + + // u + double u0[{{ dims.nu }}]; + for (int ii = 0; ii < {{ dims.nu }}; ii++) + u0[ii] = 0.0; + + sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, + {{ model.name }}_sim_in, "u", u0); + + // S_forw + double S_forw[{{ dims.nx * (dims.nx + dims.nu) }}]; + for (int ii = 0; ii < {{ dims.nx * (dims.nx + dims.nu) }}; ii++) + S_forw[ii] = 0.0; + for (int ii = 0; ii < {{ dims.nx }}; ii++) + S_forw[ii + ii * {{ dims.nx }} ] = 1.0; + + + sim_in_set({{ model.name }}_sim_config, {{ model.name }}_sim_dims, + {{ model.name }}_sim_in, "S_forw", S_forw); + + int status = sim_precompute({{ model.name }}_sim_solver, {{ model.name }}_sim_in, {{ model.name }}_sim_out); + + return status; +} + + +int {{ model.name }}_acados_sim_solve(sim_solver_capsule *capsule) +{ + // integrate dynamics using acados sim_solver + int status = sim_solve(capsule->acados_sim_solver, + capsule->acados_sim_in, capsule->acados_sim_out); + if (status != 0) + printf("error in {{ model.name }}_acados_sim_solve()! Exiting.\n"); + + return status; +} + + +int {{ model.name }}_acados_sim_free(sim_solver_capsule *capsule) +{ + // free memory + sim_solver_destroy(capsule->acados_sim_solver); + sim_in_destroy(capsule->acados_sim_in); + sim_out_destroy(capsule->acados_sim_out); + sim_opts_destroy(capsule->acados_sim_opts); + sim_dims_destroy(capsule->acados_sim_dims); + sim_config_destroy(capsule->acados_sim_config); + + // free external function +{%- if solver_options.integrator_type == "IRK" %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_impl_dae_fun); + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_impl_dae_fun_jac_x_xdot_z); + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_impl_dae_jac_x_xdot_u_z); +{%- if hessian_approx == "EXACT" %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_impl_dae_hess); +{%- endif %} +{%- elif solver_options.integrator_type == "ERK" %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_forw_vde_casadi); + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_vde_adj_casadi); + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_expl_ode_fun_casadi); +{%- if hessian_approx == "EXACT" %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_expl_ode_hess); +{%- endif %} +{%- elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_gnsf_phi_fun); + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_gnsf_phi_fun_jac_y); + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_gnsf_phi_jac_y_uhat); + {% if model.gnsf.nontrivial_f_LO == 1 %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z); + {%- endif %} + {%- endif %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(capsule->sim_gnsf_get_matrices_fun); +{% endif %} + + return 0; +} + + +int {{ model.name }}_acados_sim_update_params(sim_solver_capsule *capsule, double *p, int np) +{ + int status = 0; + int casadi_np = {{ model.name | upper }}_NP; + + if (casadi_np != np) { + printf("{{ model.name }}_acados_sim_update_params: trying to set %i parameters for external functions." + " External function has %i parameters. Exiting.\n", np, casadi_np); + exit(1); + } + +{%- if solver_options.integrator_type == "ERK" %} + capsule->sim_forw_vde_casadi[0].set_param(capsule->sim_forw_vde_casadi, p); + capsule->sim_vde_adj_casadi[0].set_param(capsule->sim_vde_adj_casadi, p); + capsule->sim_expl_ode_fun_casadi[0].set_param(capsule->sim_expl_ode_fun_casadi, p); +{%- if hessian_approx == "EXACT" %} + capsule->sim_expl_ode_hess[0].set_param(capsule->sim_expl_ode_hess, p); +{%- endif %} +{%- elif solver_options.integrator_type == "IRK" %} + capsule->sim_impl_dae_fun[0].set_param(capsule->sim_impl_dae_fun, p); + capsule->sim_impl_dae_fun_jac_x_xdot_z[0].set_param(capsule->sim_impl_dae_fun_jac_x_xdot_z, p); + capsule->sim_impl_dae_jac_x_xdot_u_z[0].set_param(capsule->sim_impl_dae_jac_x_xdot_u_z, p); +{%- if hessian_approx == "EXACT" %} + capsule->sim_impl_dae_hess[0].set_param(capsule->sim_impl_dae_hess, p); +{%- endif %} +{%- elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + capsule->sim_gnsf_phi_fun[0].set_param(capsule->sim_gnsf_phi_fun, p); + capsule->sim_gnsf_phi_fun_jac_y[0].set_param(capsule->sim_gnsf_phi_fun_jac_y, p); + capsule->sim_gnsf_phi_jac_y_uhat[0].set_param(capsule->sim_gnsf_phi_jac_y_uhat, p); + {% if model.gnsf.nontrivial_f_LO == 1 %} + capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z[0].set_param(capsule->sim_gnsf_f_lo_jac_x1_x1dot_u_z, p); + {%- endif %} + {%- endif %} + capsule->sim_gnsf_get_matrices_fun[0].set_param(capsule->sim_gnsf_get_matrices_fun, p); +{% endif %} + + return status; +} + +/* getters pointers to C objects*/ +sim_config * {{ model.name }}_acados_get_sim_config(sim_solver_capsule *capsule) +{ + return capsule->acados_sim_config; +}; + +sim_in * {{ model.name }}_acados_get_sim_in(sim_solver_capsule *capsule) +{ + return capsule->acados_sim_in; +}; + +sim_out * {{ model.name }}_acados_get_sim_out(sim_solver_capsule *capsule) +{ + return capsule->acados_sim_out; +}; + +void * {{ model.name }}_acados_get_sim_dims(sim_solver_capsule *capsule) +{ + return capsule->acados_sim_dims; +}; + +sim_opts * {{ model.name }}_acados_get_sim_opts(sim_solver_capsule *capsule) +{ + return capsule->acados_sim_opts; +}; + +sim_solver * {{ model.name }}_acados_get_sim_solver(sim_solver_capsule *capsule) +{ + return capsule->acados_sim_solver; +}; + diff --git a/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.h b/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.h new file mode 100644 index 0000000000..59aee62f49 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#ifndef ACADOS_SIM_{{ model.name }}_H_ +#define ACADOS_SIM_{{ model.name }}_H_ + +#include "acados_c/sim_interface.h" +#include "acados_c/external_function_interface.h" + +#define {{ model.name | upper }}_NX {{ dims.nx }} +#define {{ model.name | upper }}_NZ {{ dims.nz }} +#define {{ model.name | upper }}_NU {{ dims.nu }} +#define {{ model.name | upper }}_NP {{ dims.np }} + +#ifdef __cplusplus +extern "C" { +#endif + + +// ** capsule for solver data ** +typedef struct sim_solver_capsule +{ + // acados objects + sim_in *acados_sim_in; + sim_out *acados_sim_out; + sim_solver *acados_sim_solver; + sim_opts *acados_sim_opts; + sim_config *acados_sim_config; + void *acados_sim_dims; + + /* external functions */ + // ERK + external_function_param_{{ model.dyn_ext_fun_type }} * sim_forw_vde_casadi; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_vde_adj_casadi; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_expl_ode_fun_casadi; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_expl_ode_hess; + + // IRK + external_function_param_{{ model.dyn_ext_fun_type }} * sim_impl_dae_fun; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_impl_dae_fun_jac_x_xdot_z; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_impl_dae_jac_x_xdot_u_z; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_impl_dae_hess; + + // GNSF + external_function_param_{{ model.dyn_ext_fun_type }} * sim_gnsf_phi_fun; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_gnsf_phi_fun_jac_y; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_gnsf_phi_jac_y_uhat; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_gnsf_f_lo_jac_x1_x1dot_u_z; + external_function_param_{{ model.dyn_ext_fun_type }} * sim_gnsf_get_matrices_fun; + +} sim_solver_capsule; + + +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_sim_create(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_sim_solve(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_sim_free(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_sim_update_params(sim_solver_capsule *capsule, double *value, int np); + +ACADOS_SYMBOL_EXPORT sim_config * {{ model.name }}_acados_get_sim_config(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT sim_in * {{ model.name }}_acados_get_sim_in(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT sim_out * {{ model.name }}_acados_get_sim_out(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT void * {{ model.name }}_acados_get_sim_dims(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT sim_opts * {{ model.name }}_acados_get_sim_opts(sim_solver_capsule *capsule); +ACADOS_SYMBOL_EXPORT sim_solver * {{ model.name }}_acados_get_sim_solver(sim_solver_capsule *capsule); + + +ACADOS_SYMBOL_EXPORT sim_solver_capsule * {{ model.name }}_acados_sim_solver_create_capsule(void); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_sim_solver_free_capsule(sim_solver_capsule *capsule); + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_SIM_{{ model.name }}_H_ diff --git a/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.pxd b/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.pxd new file mode 100644 index 0000000000..153f98d13a --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/acados_sim_solver.in.pxd @@ -0,0 +1,51 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +cimport acados_sim_solver_common + +cdef extern from "acados_sim_solver_{{ model.name }}.h": + ctypedef struct sim_solver_capsule "sim_solver_capsule": + pass + + sim_solver_capsule * acados_sim_solver_create_capsule "{{ model.name }}_acados_sim_solver_create_capsule"() + int acados_sim_solver_free_capsule "{{ model.name }}_acados_sim_solver_free_capsule"(sim_solver_capsule *capsule) + + int acados_sim_create "{{ model.name }}_acados_sim_create"(sim_solver_capsule * capsule) + int acados_sim_solve "{{ model.name }}_acados_sim_solve"(sim_solver_capsule * capsule) + int acados_sim_free "{{ model.name }}_acados_sim_free"(sim_solver_capsule * capsule) + int acados_sim_update_params "{{ model.name }}_acados_sim_update_params"(sim_solver_capsule * capsule, double *value, int np_) + # int acados_sim_update_params_sparse "{{ model.name }}_acados_sim_update_params_sparse"(sim_solver_capsule * capsule, int stage, int *idx, double *p, int n_update) + + acados_sim_solver_common.sim_in *acados_get_sim_in "{{ model.name }}_acados_get_sim_in"(sim_solver_capsule * capsule) + acados_sim_solver_common.sim_out *acados_get_sim_out "{{ model.name }}_acados_get_sim_out"(sim_solver_capsule * capsule) + acados_sim_solver_common.sim_solver *acados_get_sim_solver "{{ model.name }}_acados_get_sim_solver"(sim_solver_capsule * capsule) + acados_sim_solver_common.sim_config *acados_get_sim_config "{{ model.name }}_acados_get_sim_config"(sim_solver_capsule * capsule) + acados_sim_solver_common.sim_opts *acados_get_sim_opts "{{ model.name }}_acados_get_sim_opts"(sim_solver_capsule * capsule) + void *acados_get_sim_dims "{{ model.name }}_acados_get_sim_dims"(sim_solver_capsule * capsule) diff --git a/third_party/acados/acados_template/c_templates_tera/acados_solver.in.c b/third_party/acados/acados_template/c_templates_tera/acados_solver.in.c new file mode 100644 index 0000000000..5e36a53d10 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/acados_solver.in.c @@ -0,0 +1,2741 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +// standard +#include +#include +#include +// acados +// #include "acados/utils/print.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados_c/external_function_interface.h" + +// example specific +#include "{{ model.name }}_model/{{ model.name }}_model.h" +#include "{{ model.name }}_constraints/{{ model.name }}_constraints.h" + +{%- if cost.cost_type != "LINEAR_LS" or cost.cost_type_e != "LINEAR_LS" or cost.cost_type_0 != "LINEAR_LS" %} +#include "{{ model.name }}_cost/{{ model.name }}_cost.h" +{%- endif %} + +{%- if not solver_options.custom_update_filename %} + {%- set custom_update_filename = "" %} +{% else %} + {%- set custom_update_filename = solver_options.custom_update_filename %} +{%- endif %} +{%- if not solver_options.custom_update_header_filename %} + {%- set custom_update_header_filename = "" %} +{% else %} + {%- set custom_update_header_filename = solver_options.custom_update_header_filename %} +{%- endif %} +{%- if custom_update_header_filename != "" %} +#include "{{ custom_update_header_filename }}" +{%- endif %} + + +#include "acados_solver_{{ model.name }}.h" + +#define NX {{ model.name | upper }}_NX +#define NZ {{ model.name | upper }}_NZ +#define NU {{ model.name | upper }}_NU +#define NP {{ model.name | upper }}_NP +#define NBX {{ model.name | upper }}_NBX +#define NBX0 {{ model.name | upper }}_NBX0 +#define NBU {{ model.name | upper }}_NBU +#define NSBX {{ model.name | upper }}_NSBX +#define NSBU {{ model.name | upper }}_NSBU +#define NSH {{ model.name | upper }}_NSH +#define NSG {{ model.name | upper }}_NSG +#define NSPHI {{ model.name | upper }}_NSPHI +#define NSHN {{ model.name | upper }}_NSHN +#define NSGN {{ model.name | upper }}_NSGN +#define NSPHIN {{ model.name | upper }}_NSPHIN +#define NSBXN {{ model.name | upper }}_NSBXN +#define NS {{ model.name | upper }}_NS +#define NSN {{ model.name | upper }}_NSN +#define NG {{ model.name | upper }}_NG +#define NBXN {{ model.name | upper }}_NBXN +#define NGN {{ model.name | upper }}_NGN +#define NY0 {{ model.name | upper }}_NY0 +#define NY {{ model.name | upper }}_NY +#define NYN {{ model.name | upper }}_NYN +// #define N {{ model.name | upper }}_N +#define NH {{ model.name | upper }}_NH +#define NPHI {{ model.name | upper }}_NPHI +#define NHN {{ model.name | upper }}_NHN +#define NPHIN {{ model.name | upper }}_NPHIN +#define NR {{ model.name | upper }}_NR + + +// ** solver data ** + +{{ model.name }}_solver_capsule * {{ model.name }}_acados_create_capsule(void) +{ + void* capsule_mem = malloc(sizeof({{ model.name }}_solver_capsule)); + {{ model.name }}_solver_capsule *capsule = ({{ model.name }}_solver_capsule *) capsule_mem; + + return capsule; +} + + +int {{ model.name }}_acados_free_capsule({{ model.name }}_solver_capsule *capsule) +{ + free(capsule); + return 0; +} + + +int {{ model.name }}_acados_create({{ model.name }}_solver_capsule* capsule) +{ + int N_shooting_intervals = {{ model.name | upper }}_N; + double* new_time_steps = NULL; // NULL -> don't alter the code generated time-steps + return {{ model.name }}_acados_create_with_discretization(capsule, N_shooting_intervals, new_time_steps); +} + + +int {{ model.name }}_acados_update_time_steps({{ model.name }}_solver_capsule* capsule, int N, double* new_time_steps) +{ + if (N != capsule->nlp_solver_plan->N) { + fprintf(stderr, "{{ model.name }}_acados_update_time_steps: given number of time steps (= %d) " \ + "differs from the currently allocated number of " \ + "time steps (= %d)!\n" \ + "Please recreate with new discretization and provide a new vector of time_stamps!\n", + N, capsule->nlp_solver_plan->N); + return 1; + } + + ocp_nlp_config * nlp_config = capsule->nlp_config; + ocp_nlp_dims * nlp_dims = capsule->nlp_dims; + ocp_nlp_in * nlp_in = capsule->nlp_in; + + for (int i = 0; i < N; i++) + { + ocp_nlp_in_set(nlp_config, nlp_dims, nlp_in, i, "Ts", &new_time_steps[i]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "scaling", &new_time_steps[i]); + } + return 0; +} + +/** + * Internal function for {{ model.name }}_acados_create: step 1 + */ +void {{ model.name }}_acados_create_1_set_plan(ocp_nlp_plan_t* nlp_solver_plan, const int N) +{ + assert(N == nlp_solver_plan->N); + + /************************************************ + * plan + ************************************************/ + + {%- if solver_options.nlp_solver_type == "SQP" %} + nlp_solver_plan->nlp_solver = SQP; + {%- else %} + nlp_solver_plan->nlp_solver = SQP_RTI; + {%- endif %} + + nlp_solver_plan->ocp_qp_solver_plan.qp_solver = {{ solver_options.qp_solver }}; + + nlp_solver_plan->nlp_cost[0] = {{ cost.cost_type_0 }}; + for (int i = 1; i < N; i++) + nlp_solver_plan->nlp_cost[i] = {{ cost.cost_type }}; + + nlp_solver_plan->nlp_cost[N] = {{ cost.cost_type_e }}; + + for (int i = 0; i < N; i++) + { + {%- if solver_options.integrator_type == "DISCRETE" %} + nlp_solver_plan->nlp_dynamics[i] = DISCRETE_MODEL; + // discrete dynamics does not need sim solver option, this field is ignored + nlp_solver_plan->sim_solver_plan[i].sim_solver = INVALID_SIM_SOLVER; + {%- else %} + nlp_solver_plan->nlp_dynamics[i] = CONTINUOUS_MODEL; + nlp_solver_plan->sim_solver_plan[i].sim_solver = {{ solver_options.integrator_type }}; + {%- endif %} + } + + for (int i = 0; i < N; i++) + { + {%- if constraints.constr_type == "BGP" %} + nlp_solver_plan->nlp_constraints[i] = BGP; + {%- else -%} + nlp_solver_plan->nlp_constraints[i] = BGH; + {%- endif %} + } + + {%- if constraints.constr_type_e == "BGP" %} + nlp_solver_plan->nlp_constraints[N] = BGP; + {%- else %} + nlp_solver_plan->nlp_constraints[N] = BGH; + {%- endif %} + + {%- if solver_options.regularize_method == "NO_REGULARIZE" %} + nlp_solver_plan->regularization = NO_REGULARIZE; + {%- elif solver_options.regularize_method == "MIRROR" %} + nlp_solver_plan->regularization = MIRROR; + {%- elif solver_options.regularize_method == "PROJECT" %} + nlp_solver_plan->regularization = PROJECT; + {%- elif solver_options.regularize_method == "PROJECT_REDUC_HESS" %} + nlp_solver_plan->regularization = PROJECT_REDUC_HESS; + {%- elif solver_options.regularize_method == "CONVEXIFY" %} + nlp_solver_plan->regularization = CONVEXIFY; + {%- endif %} +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 2 + */ +ocp_nlp_dims* {{ model.name }}_acados_create_2_create_and_set_dimensions({{ model.name }}_solver_capsule* capsule) +{ + ocp_nlp_plan_t* nlp_solver_plan = capsule->nlp_solver_plan; + const int N = nlp_solver_plan->N; + ocp_nlp_config* nlp_config = capsule->nlp_config; + + /************************************************ + * dimensions + ************************************************/ + #define NINTNP1MEMS 17 + int* intNp1mem = (int*)malloc( (N+1)*sizeof(int)*NINTNP1MEMS ); + + int* nx = intNp1mem + (N+1)*0; + int* nu = intNp1mem + (N+1)*1; + int* nbx = intNp1mem + (N+1)*2; + int* nbu = intNp1mem + (N+1)*3; + int* nsbx = intNp1mem + (N+1)*4; + int* nsbu = intNp1mem + (N+1)*5; + int* nsg = intNp1mem + (N+1)*6; + int* nsh = intNp1mem + (N+1)*7; + int* nsphi = intNp1mem + (N+1)*8; + int* ns = intNp1mem + (N+1)*9; + int* ng = intNp1mem + (N+1)*10; + int* nh = intNp1mem + (N+1)*11; + int* nphi = intNp1mem + (N+1)*12; + int* nz = intNp1mem + (N+1)*13; + int* ny = intNp1mem + (N+1)*14; + int* nr = intNp1mem + (N+1)*15; + int* nbxe = intNp1mem + (N+1)*16; + + for (int i = 0; i < N+1; i++) + { + // common + nx[i] = NX; + nu[i] = NU; + nz[i] = NZ; + ns[i] = NS; + // cost + ny[i] = NY; + // constraints + nbx[i] = NBX; + nbu[i] = NBU; + nsbx[i] = NSBX; + nsbu[i] = NSBU; + nsg[i] = NSG; + nsh[i] = NSH; + nsphi[i] = NSPHI; + ng[i] = NG; + nh[i] = NH; + nphi[i] = NPHI; + nr[i] = NR; + nbxe[i] = 0; + } + + // for initial state + nbx[0] = NBX0; + nsbx[0] = 0; + ns[0] = NS - NSBX; + nbxe[0] = {{ dims.nbxe_0 }}; + ny[0] = NY0; + + // terminal - common + nu[N] = 0; + nz[N] = 0; + ns[N] = NSN; + // cost + ny[N] = NYN; + // constraint + nbx[N] = NBXN; + nbu[N] = 0; + ng[N] = NGN; + nh[N] = NHN; + nphi[N] = NPHIN; + nr[N] = {{ dims.nr_e }}; + + nsbx[N] = NSBXN; + nsbu[N] = 0; + nsg[N] = NSGN; + nsh[N] = NSHN; + nsphi[N] = NSPHIN; + + /* create and set ocp_nlp_dims */ + ocp_nlp_dims * nlp_dims = ocp_nlp_dims_create(nlp_config); + + ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "nx", nx); + ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "nu", nu); + ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "nz", nz); + ocp_nlp_dims_set_opt_vars(nlp_config, nlp_dims, "ns", ns); + + for (int i = 0; i <= N; i++) + { + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nbx", &nbx[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nbu", &nbu[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsbx", &nsbx[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsbu", &nsbu[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "ng", &ng[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsg", &nsg[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nbxe", &nbxe[i]); + } + +{%- if cost.cost_type_0 == "NONLINEAR_LS" or cost.cost_type_0 == "LINEAR_LS" or cost.cost_type_0 == "CONVEX_OVER_NONLINEAR"%} + ocp_nlp_dims_set_cost(nlp_config, nlp_dims, 0, "ny", &ny[0]); +{%- endif %} + +{%- if cost.cost_type == "NONLINEAR_LS" or cost.cost_type == "LINEAR_LS" or cost.cost_type == "CONVEX_OVER_NONLINEAR"%} + for (int i = 1; i < N; i++) + ocp_nlp_dims_set_cost(nlp_config, nlp_dims, i, "ny", &ny[i]); +{%- endif %} + + for (int i = 0; i < N; i++) + { + {%- if constraints.constr_type == "BGH" and dims.nh > 0 %} + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nh", &nh[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsh", &nsh[i]); + {%- elif constraints.constr_type == "BGP" and dims.nphi > 0 %} + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nr", &nr[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nphi", &nphi[i]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, i, "nsphi", &nsphi[i]); + {%- endif %} + } + +{%- if constraints.constr_type_e == "BGH" %} + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nh", &nh[N]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nsh", &nsh[N]); +{%- elif constraints.constr_type_e == "BGP" %} + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nr", &nr[N]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nphi", &nphi[N]); + ocp_nlp_dims_set_constraints(nlp_config, nlp_dims, N, "nsphi", &nsphi[N]); +{%- endif %} +{%- if cost.cost_type_e == "NONLINEAR_LS" or cost.cost_type_e == "LINEAR_LS" or cost.cost_type_e == "CONVEX_OVER_NONLINEAR"%} + ocp_nlp_dims_set_cost(nlp_config, nlp_dims, N, "ny", &ny[N]); +{%- endif %} + free(intNp1mem); + +{%- if solver_options.integrator_type == "GNSF" -%} + // GNSF specific dimensions + int gnsf_nx1 = {{ dims.gnsf_nx1 }}; + int gnsf_nz1 = {{ dims.gnsf_nz1 }}; + int gnsf_nout = {{ dims.gnsf_nout }}; + int gnsf_ny = {{ dims.gnsf_ny }}; + int gnsf_nuhat = {{ dims.gnsf_nuhat }}; + + for (int i = 0; i < N; i++) + { + if (nlp_solver_plan->sim_solver_plan[i].sim_solver == GNSF) + { + ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nx1", &gnsf_nx1); + ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nz1", &gnsf_nz1); + ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nout", &gnsf_nout); + ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_ny", &gnsf_ny); + ocp_nlp_dims_set_dynamics(nlp_config, nlp_dims, i, "gnsf_nuhat", &gnsf_nuhat); + } + } +{%- endif %} +return nlp_dims; +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 3 + */ +void {{ model.name }}_acados_create_3_create_and_set_functions({{ model.name }}_solver_capsule* capsule) +{ + const int N = capsule->nlp_solver_plan->N; + + /************************************************ + * external functions + ************************************************/ + +#define MAP_CASADI_FNC(__CAPSULE_FNC__, __MODEL_BASE_FNC__) do{ \ + capsule->__CAPSULE_FNC__.casadi_fun = & __MODEL_BASE_FNC__ ;\ + capsule->__CAPSULE_FNC__.casadi_n_in = & __MODEL_BASE_FNC__ ## _n_in; \ + capsule->__CAPSULE_FNC__.casadi_n_out = & __MODEL_BASE_FNC__ ## _n_out; \ + capsule->__CAPSULE_FNC__.casadi_sparsity_in = & __MODEL_BASE_FNC__ ## _sparsity_in; \ + capsule->__CAPSULE_FNC__.casadi_sparsity_out = & __MODEL_BASE_FNC__ ## _sparsity_out; \ + capsule->__CAPSULE_FNC__.casadi_work = & __MODEL_BASE_FNC__ ## _work; \ + external_function_param_casadi_create(&capsule->__CAPSULE_FNC__ , {{ dims.np }}); \ + }while(false) + +{% if constraints.constr_type == "BGP" %} + // constraints.constr_type == "BGP" + capsule->phi_constraint = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) + { + // nonlinear part of convex-composite constraint + MAP_CASADI_FNC(phi_constraint[i], {{ model.name }}_phi_constraint); + } +{%- endif %} + +{%- if constraints.constr_type_e == "BGP" %} + // constraints.constr_type_e == "BGP" + // nonlinear part of convex-composite constraint + MAP_CASADI_FNC(phi_e_constraint, {{ model.name }}_phi_e_constraint); +{%- endif %} + +{%- if constraints.constr_type == "BGH" and dims.nh > 0 %} + // constraints.constr_type == "BGH" and dims.nh > 0 + capsule->nl_constr_h_fun_jac = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(nl_constr_h_fun_jac[i], {{ model.name }}_constr_h_fun_jac_uxt_zt); + } + capsule->nl_constr_h_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(nl_constr_h_fun[i], {{ model.name }}_constr_h_fun); + } + {% if solver_options.hessian_approx == "EXACT" %} + capsule->nl_constr_h_fun_jac_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(nl_constr_h_fun_jac_hess[i], {{ model.name }}_constr_h_fun_jac_uxt_zt_hess); + } + {% endif %} +{% endif %} + +{%- if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + MAP_CASADI_FNC(nl_constr_h_e_fun_jac, {{ model.name }}_constr_h_e_fun_jac_uxt_zt); + MAP_CASADI_FNC(nl_constr_h_e_fun, {{ model.name }}_constr_h_e_fun); + + {%- if solver_options.hessian_approx == "EXACT" %} + MAP_CASADI_FNC(nl_constr_h_e_fun_jac_hess, {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess); + {% endif %} +{%- endif %} + +{% if solver_options.integrator_type == "ERK" %} + // explicit ode + capsule->forw_vde_casadi = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(forw_vde_casadi[i], {{ model.name }}_expl_vde_forw); + } + + capsule->expl_ode_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(expl_ode_fun[i], {{ model.name }}_expl_ode_fun); + } + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->hess_vde_casadi = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(hess_vde_casadi[i], {{ model.name }}_expl_ode_hess); + } + {%- endif %} + +{% elif solver_options.integrator_type == "IRK" %} + // implicit dae + capsule->impl_dae_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) { + {%- if model.dyn_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(impl_dae_fun[i], {{ model.name }}_impl_dae_fun); + {%- else %} + capsule->impl_dae_fun[i].fun = &{{ model.dyn_impl_dae_fun }}; + external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->impl_dae_fun[i], {{ dims.np }}); + {%- endif %} + } + + capsule->impl_dae_fun_jac_x_xdot_z = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) { + {%- if model.dyn_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(impl_dae_fun_jac_x_xdot_z[i], {{ model.name }}_impl_dae_fun_jac_x_xdot_z); + {%- else %} + capsule->impl_dae_fun_jac_x_xdot_z[i].fun = &{{ model.dyn_impl_dae_fun_jac }}; + external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->impl_dae_fun_jac_x_xdot_z[i], {{ dims.np }}); + {%- endif %} + } + + capsule->impl_dae_jac_x_xdot_u_z = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) { + {%- if model.dyn_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(impl_dae_jac_x_xdot_u_z[i], {{ model.name }}_impl_dae_jac_x_xdot_u_z); + {%- else %} + capsule->impl_dae_jac_x_xdot_u_z[i].fun = &{{ model.dyn_impl_dae_jac }}; + external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->impl_dae_jac_x_xdot_u_z[i], {{ dims.np }}); + {%- endif %} + } + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->impl_dae_hess = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(impl_dae_hess[i], {{ model.name }}_impl_dae_hess); + } + {%- endif %} +{% elif solver_options.integrator_type == "LIFTED_IRK" %} + // external functions (implicit model) + capsule->impl_dae_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(impl_dae_fun[i], {{ model.name }}_impl_dae_fun); + } + + capsule->impl_dae_fun_jac_x_xdot_u = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(impl_dae_fun_jac_x_xdot_u[i], {{ model.name }}_impl_dae_fun_jac_x_xdot_u); + } + +{% elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + capsule->gnsf_phi_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(gnsf_phi_fun[i], {{ model.name }}_gnsf_phi_fun); + } + + capsule->gnsf_phi_fun_jac_y = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(gnsf_phi_fun_jac_y[i], {{ model.name }}_gnsf_phi_fun_jac_y); + } + + capsule->gnsf_phi_jac_y_uhat = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(gnsf_phi_jac_y_uhat[i], {{ model.name }}_gnsf_phi_jac_y_uhat); + } + + {% if model.gnsf.nontrivial_f_LO == 1 %} + capsule->gnsf_f_lo_jac_x1_x1dot_u_z = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(gnsf_f_lo_jac_x1_x1dot_u_z[i], {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz); + } + {%- endif %} + {%- endif %} + capsule->gnsf_get_matrices_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N; i++) { + MAP_CASADI_FNC(gnsf_get_matrices_fun[i], {{ model.name }}_gnsf_get_matrices_fun); + } +{% elif solver_options.integrator_type == "DISCRETE" %} + // discrete dynamics + capsule->discr_dyn_phi_fun = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) + { + {%- if model.dyn_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(discr_dyn_phi_fun[i], {{ model.name }}_dyn_disc_phi_fun); + {%- else %} + capsule->discr_dyn_phi_fun[i].fun = &{{ model.dyn_disc_fun }}; + external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->discr_dyn_phi_fun[i], {{ dims.np }}); + {%- endif %} + } + + capsule->discr_dyn_phi_fun_jac_ut_xt = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) + { + {%- if model.dyn_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(discr_dyn_phi_fun_jac_ut_xt[i], {{ model.name }}_dyn_disc_phi_fun_jac); + {%- else %} + capsule->discr_dyn_phi_fun_jac_ut_xt[i].fun = &{{ model.dyn_disc_fun_jac }}; + external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->discr_dyn_phi_fun_jac_ut_xt[i], {{ dims.np }}); + {%- endif %} + } + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->discr_dyn_phi_fun_jac_ut_xt_hess = (external_function_param_{{ model.dyn_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ model.dyn_ext_fun_type }})*N); + for (int i = 0; i < N; i++) + { + {%- if model.dyn_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(discr_dyn_phi_fun_jac_ut_xt_hess[i], {{ model.name }}_dyn_disc_phi_fun_jac_hess); + {%- else %} + capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i].fun = &{{ model.dyn_disc_fun_jac_hess }}; + external_function_param_{{ model.dyn_ext_fun_type }}_create(&capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i], {{ dims.np }}); + {%- endif %} + } + {%- endif %} +{%- endif %} + + +{%- if cost.cost_type_0 == "NONLINEAR_LS" %} + // nonlinear least squares function + MAP_CASADI_FNC(cost_y_0_fun, {{ model.name }}_cost_y_0_fun); + MAP_CASADI_FNC(cost_y_0_fun_jac_ut_xt, {{ model.name }}_cost_y_0_fun_jac_ut_xt); + MAP_CASADI_FNC(cost_y_0_hess, {{ model.name }}_cost_y_0_hess); + +{%- elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + // convex-over-nonlinear cost + MAP_CASADI_FNC(conl_cost_0_fun, {{ model.name }}_conl_cost_0_fun); + MAP_CASADI_FNC(conl_cost_0_fun_jac_hess, {{ model.name }}_conl_cost_0_fun_jac_hess); + +{%- elif cost.cost_type_0 == "EXTERNAL" %} + // external cost + {%- if cost.cost_ext_fun_type_0 == "casadi" %} + MAP_CASADI_FNC(ext_cost_0_fun, {{ model.name }}_cost_ext_cost_0_fun); + {%- else %} + capsule->ext_cost_0_fun.fun = &{{ cost.cost_function_ext_cost_0 }}; + external_function_param_{{ cost.cost_ext_fun_type_0 }}_create(&capsule->ext_cost_0_fun, {{ dims.np }}); + {%- endif %} + + // external cost + {%- if cost.cost_ext_fun_type_0 == "casadi" %} + MAP_CASADI_FNC(ext_cost_0_fun_jac, {{ model.name }}_cost_ext_cost_0_fun_jac); + {%- else %} + capsule->ext_cost_0_fun_jac.fun = &{{ cost.cost_function_ext_cost_0 }}; + external_function_param_{{ cost.cost_ext_fun_type_0 }}_create(&capsule->ext_cost_0_fun_jac, {{ dims.np }}); + {%- endif %} + + // external cost + {%- if cost.cost_ext_fun_type_0 == "casadi" %} + MAP_CASADI_FNC(ext_cost_0_fun_jac_hess, {{ model.name }}_cost_ext_cost_0_fun_jac_hess); + {%- else %} + capsule->ext_cost_0_fun_jac_hess.fun = &{{ cost.cost_function_ext_cost_0 }}; + external_function_param_{{ cost.cost_ext_fun_type_0 }}_create(&capsule->ext_cost_0_fun_jac_hess, {{ dims.np }}); + {%- endif %} +{%- endif %} + +{%- if cost.cost_type == "NONLINEAR_LS" %} + // nonlinear least squares cost + capsule->cost_y_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N-1; i++) + { + MAP_CASADI_FNC(cost_y_fun[i], {{ model.name }}_cost_y_fun); + } + + capsule->cost_y_fun_jac_ut_xt = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N-1; i++) + { + MAP_CASADI_FNC(cost_y_fun_jac_ut_xt[i], {{ model.name }}_cost_y_fun_jac_ut_xt); + } + + capsule->cost_y_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N-1; i++) + { + MAP_CASADI_FNC(cost_y_hess[i], {{ model.name }}_cost_y_hess); + } + +{%- elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + // convex-over-nonlinear cost + capsule->conl_cost_fun = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N-1; i++) + { + MAP_CASADI_FNC(conl_cost_fun[i], {{ model.name }}_conl_cost_fun); + } + capsule->conl_cost_fun_jac_hess = (external_function_param_casadi *) malloc(sizeof(external_function_param_casadi)*N); + for (int i = 0; i < N-1; i++) + { + MAP_CASADI_FNC(conl_cost_fun_jac_hess[i], {{ model.name }}_conl_cost_fun_jac_hess); + } + +{%- elif cost.cost_type == "EXTERNAL" %} + // external cost + capsule->ext_cost_fun = (external_function_param_{{ cost.cost_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ cost.cost_ext_fun_type }})*N); + for (int i = 0; i < N-1; i++) + { + {%- if cost.cost_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(ext_cost_fun[i], {{ model.name }}_cost_ext_cost_fun); + {%- else %} + capsule->ext_cost_fun[i].fun = &{{ cost.cost_function_ext_cost }}; + external_function_param_{{ cost.cost_ext_fun_type }}_create(&capsule->ext_cost_fun[i], {{ dims.np }}); + {%- endif %} + } + + capsule->ext_cost_fun_jac = (external_function_param_{{ cost.cost_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ cost.cost_ext_fun_type }})*N); + for (int i = 0; i < N-1; i++) + { + {%- if cost.cost_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(ext_cost_fun_jac[i], {{ model.name }}_cost_ext_cost_fun_jac); + {%- else %} + capsule->ext_cost_fun_jac[i].fun = &{{ cost.cost_function_ext_cost }}; + external_function_param_{{ cost.cost_ext_fun_type }}_create(&capsule->ext_cost_fun_jac[i], {{ dims.np }}); + {%- endif %} + } + + capsule->ext_cost_fun_jac_hess = (external_function_param_{{ cost.cost_ext_fun_type }} *) malloc(sizeof(external_function_param_{{ cost.cost_ext_fun_type }})*N); + for (int i = 0; i < N-1; i++) + { + {%- if cost.cost_ext_fun_type == "casadi" %} + MAP_CASADI_FNC(ext_cost_fun_jac_hess[i], {{ model.name }}_cost_ext_cost_fun_jac_hess); + {%- else %} + capsule->ext_cost_fun_jac_hess[i].fun = &{{ cost.cost_function_ext_cost }}; + external_function_param_{{ cost.cost_ext_fun_type }}_create(&capsule->ext_cost_fun_jac_hess[i], {{ dims.np }}); + {%- endif %} + } +{%- endif %} + +{%- if cost.cost_type_e == "NONLINEAR_LS" %} + // nonlinear least square function + MAP_CASADI_FNC(cost_y_e_fun, {{ model.name }}_cost_y_e_fun); + MAP_CASADI_FNC(cost_y_e_fun_jac_ut_xt, {{ model.name }}_cost_y_e_fun_jac_ut_xt); + MAP_CASADI_FNC(cost_y_e_hess, {{ model.name }}_cost_y_e_hess); + +{%- elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + // convex-over-nonlinear cost + MAP_CASADI_FNC(conl_cost_e_fun, {{ model.name }}_conl_cost_e_fun); + MAP_CASADI_FNC(conl_cost_e_fun_jac_hess, {{ model.name }}_conl_cost_e_fun_jac_hess); + +{%- elif cost.cost_type_e == "EXTERNAL" %} + // external cost - function + {%- if cost.cost_ext_fun_type_e == "casadi" %} + MAP_CASADI_FNC(ext_cost_e_fun, {{ model.name }}_cost_ext_cost_e_fun); + {% else %} + capsule->ext_cost_e_fun.fun = &{{ cost.cost_function_ext_cost_e }}; + external_function_param_{{ cost.cost_ext_fun_type_e }}_create(&capsule->ext_cost_e_fun, {{ dims.np }}); + {%- endif %} + + // external cost - jacobian + {%- if cost.cost_ext_fun_type_e == "casadi" %} + MAP_CASADI_FNC(ext_cost_e_fun_jac, {{ model.name }}_cost_ext_cost_e_fun_jac); + {%- else %} + capsule->ext_cost_e_fun_jac.fun = &{{ cost.cost_function_ext_cost_e }}; + external_function_param_{{ cost.cost_ext_fun_type_e }}_create(&capsule->ext_cost_e_fun_jac, {{ dims.np }}); + {%- endif %} + + // external cost - hessian + {%- if cost.cost_ext_fun_type_e == "casadi" %} + MAP_CASADI_FNC(ext_cost_e_fun_jac_hess, {{ model.name }}_cost_ext_cost_e_fun_jac_hess); + {%- else %} + capsule->ext_cost_e_fun_jac_hess.fun = &{{ cost.cost_function_ext_cost_e }}; + external_function_param_{{ cost.cost_ext_fun_type_e }}_create(&capsule->ext_cost_e_fun_jac_hess, {{ dims.np }}); + {%- endif %} +{%- endif %} + +#undef MAP_CASADI_FNC +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 4 + */ +void {{ model.name }}_acados_create_4_set_default_parameters({{ model.name }}_solver_capsule* capsule) { +{%- if dims.np > 0 %} + const int N = capsule->nlp_solver_plan->N; + // initialize parameters to nominal value + double* p = calloc(NP, sizeof(double)); + {%- for item in parameter_values %} + {%- if item != 0 %} + p[{{ loop.index0 }}] = {{ item }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i <= N; i++) { + {{ model.name }}_acados_update_params(capsule, i, p, NP); + } + free(p); +{%- else %} + // no parameters defined +{%- endif %}{# if dims.np #} +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 5 + */ +void {{ model.name }}_acados_create_5_set_nlp_in({{ model.name }}_solver_capsule* capsule, const int N, double* new_time_steps) +{ + assert(N == capsule->nlp_solver_plan->N); + ocp_nlp_config* nlp_config = capsule->nlp_config; + ocp_nlp_dims* nlp_dims = capsule->nlp_dims; + + /************************************************ + * nlp_in + ************************************************/ +// ocp_nlp_in * nlp_in = ocp_nlp_in_create(nlp_config, nlp_dims); +// capsule->nlp_in = nlp_in; + ocp_nlp_in * nlp_in = capsule->nlp_in; + + // set up time_steps + {% set all_equal = true -%} + {%- set val = solver_options.time_steps[0] %} + {%- for j in range(start=1, end=dims.N) %} + {%- if val != solver_options.time_steps[j] %} + {%- set_global all_equal = false %} + {%- break %} + {%- endif %} + {%- endfor %} + + if (new_time_steps) { + {{ model.name }}_acados_update_time_steps(capsule, N, new_time_steps); + } else { + {%- if all_equal == true -%} + // all time_steps are identical + double time_step = {{ solver_options.time_steps[0] }}; + for (int i = 0; i < N; i++) + { + ocp_nlp_in_set(nlp_config, nlp_dims, nlp_in, i, "Ts", &time_step); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "scaling", &time_step); + } + {%- else -%} + // time_steps are different + double* time_steps = malloc(N*sizeof(double)); + {%- for j in range(end=dims.N) %} + time_steps[{{ j }}] = {{ solver_options.time_steps[j] }}; + {%- endfor %} + {{ model.name }}_acados_update_time_steps(capsule, N, time_steps); + free(time_steps); + {%- endif %} + } + + /**** Dynamics ****/ + for (int i = 0; i < N; i++) + { + {%- if solver_options.integrator_type == "ERK" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "expl_vde_forw", &capsule->forw_vde_casadi[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "expl_ode_fun", &capsule->expl_ode_fun[i]); + {%- if solver_options.hessian_approx == "EXACT" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "expl_ode_hess", &capsule->hess_vde_casadi[i]); + {%- endif %} + {% elif solver_options.integrator_type == "IRK" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "impl_dae_fun", &capsule->impl_dae_fun[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, + "impl_dae_fun_jac_x_xdot_z", &capsule->impl_dae_fun_jac_x_xdot_z[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, + "impl_dae_jac_x_xdot_u", &capsule->impl_dae_jac_x_xdot_u_z[i]); + {%- if solver_options.hessian_approx == "EXACT" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "impl_dae_hess", &capsule->impl_dae_hess[i]); + {%- endif %} + {% elif solver_options.integrator_type == "LIFTED_IRK" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "impl_dae_fun", &capsule->impl_dae_fun[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, + "impl_dae_fun_jac_x_xdot_u", &capsule->impl_dae_fun_jac_x_xdot_u[i]); + {% elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "phi_fun", &capsule->gnsf_phi_fun[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "phi_fun_jac_y", &capsule->gnsf_phi_fun_jac_y[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "phi_jac_y_uhat", &capsule->gnsf_phi_jac_y_uhat[i]); + {% if model.gnsf.nontrivial_f_LO == 1 %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "f_lo_jac_x1_x1dot_u_z", + &capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i]); + {%- endif %} + {%- endif %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "gnsf_get_matrices_fun", + &capsule->gnsf_get_matrices_fun[i]); + {% elif solver_options.integrator_type == "DISCRETE" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "disc_dyn_fun", &capsule->discr_dyn_phi_fun[i]); + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "disc_dyn_fun_jac", + &capsule->discr_dyn_phi_fun_jac_ut_xt[i]); + {%- if solver_options.hessian_approx == "EXACT" %} + ocp_nlp_dynamics_model_set(nlp_config, nlp_dims, nlp_in, i, "disc_dyn_fun_jac_hess", + &capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i]); + {%- endif %} + {%- endif %} + } + + /**** Cost ****/ + +{%- if dims.ny_0 == 0 %} +{%- elif cost.cost_type_0 == "NONLINEAR_LS" or cost.cost_type_0 == "LINEAR_LS" or cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + double* yref_0 = calloc(NY0, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny_0) %} + {%- if cost.yref_0[j] != 0 %} + yref_0[{{ j }}] = {{ cost.yref_0[j] }}; + {%- endif %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "yref", yref_0); + free(yref_0); +{%- endif %} + + +{%- if dims.ny == 0 %} +{%- elif cost.cost_type == "NONLINEAR_LS" or cost.cost_type == "LINEAR_LS" or cost.cost_type == "CONVEX_OVER_NONLINEAR" %} + double* yref = calloc(NY, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny) %} + {%- if cost.yref[j] != 0 %} + yref[{{ j }}] = {{ cost.yref[j] }}; + {%- endif %} + {%- endfor %} + + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "yref", yref); + } + free(yref); +{%- endif %} + + +{%- if dims.ny_e == 0 %} +{%- elif cost.cost_type_e == "NONLINEAR_LS" or cost.cost_type_e == "LINEAR_LS" or cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + double* yref_e = calloc(NYN, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny_e) %} + {%- if cost.yref_e[j] != 0 %} + yref_e[{{ j }}] = {{ cost.yref_e[j] }}; + {%- endif %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "yref", yref_e); + free(yref_e); +{%- endif %} + +{%- if dims.ny_0 == 0 %} +{%- elif cost.cost_type_0 == "NONLINEAR_LS" or cost.cost_type_0 == "LINEAR_LS" %} + double* W_0 = calloc(NY0*NY0, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny_0) %} + {%- for k in range(end=dims.ny_0) %} + {%- if cost.W_0[j][k] != 0 %} + W_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.W_0[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "W", W_0); + free(W_0); +{%- endif %} + +{%- if dims.ny == 0 %} +{%- elif cost.cost_type == "NONLINEAR_LS" or cost.cost_type == "LINEAR_LS" %} + double* W = calloc(NY*NY, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny) %} + {%- for k in range(end=dims.ny) %} + {%- if cost.W[j][k] != 0 %} + W[{{ j }}+(NY) * {{ k }}] = {{ cost.W[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "W", W); + } + free(W); +{%- endif %} + +{%- if dims.ny_e == 0 %} +{%- elif cost.cost_type_e == "NONLINEAR_LS" or cost.cost_type_e == "LINEAR_LS" %} + double* W_e = calloc(NYN*NYN, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny_e) %} + {%- for k in range(end=dims.ny_e) %} + {%- if cost.W_e[j][k] != 0 %} + W_e[{{ j }}+(NYN) * {{ k }}] = {{ cost.W_e[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "W", W_e); + free(W_e); +{%- endif %} + +{%- if dims.ny_0 == 0 %} +{%- elif cost.cost_type_0 == "LINEAR_LS" %} + double* Vx_0 = calloc(NY0*NX, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny_0) %} + {%- for k in range(end=dims.nx) %} + {%- if cost.Vx_0[j][k] != 0 %} + Vx_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.Vx_0[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "Vx", Vx_0); + free(Vx_0); + + {%- if dims.nu > 0 %} + double* Vu_0 = calloc(NY0*NU, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny_0) %} + {%- for k in range(end=dims.nu) %} + {%- if cost.Vu_0[j][k] != 0 %} + Vu_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.Vu_0[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "Vu", Vu_0); + free(Vu_0); + {%- endif %} + + {%- if dims.nz > 0 %} + double* Vz_0 = calloc(NY0*NZ, sizeof(double)); + // change only the non-zero elements: + {% for j in range(end=dims.ny_0) %} + {%- for k in range(end=dims.nz) %} + {%- if cost.Vz_0[j][k] != 0 %} + Vz_0[{{ j }}+(NY0) * {{ k }}] = {{ cost.Vz_0[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "Vz", Vz_0); + free(Vz_0); + {%- endif %} +{%- endif %} + +{%- if dims.ny == 0 %} +{%- elif cost.cost_type == "LINEAR_LS" %} + double* Vx = calloc(NY*NX, sizeof(double)); + // change only the non-zero elements: + {%- for j in range(end=dims.ny) %} + {%- for k in range(end=dims.nx) %} + {%- if cost.Vx[j][k] != 0 %} + Vx[{{ j }}+(NY) * {{ k }}] = {{ cost.Vx[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Vx", Vx); + } + free(Vx); + + {% if dims.nu > 0 %} + double* Vu = calloc(NY*NU, sizeof(double)); + // change only the non-zero elements: + {% for j in range(end=dims.ny) %} + {%- for k in range(end=dims.nu) %} + {%- if cost.Vu[j][k] != 0 %} + Vu[{{ j }}+(NY) * {{ k }}] = {{ cost.Vu[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Vu", Vu); + } + free(Vu); + {%- endif %} + + {%- if dims.nz > 0 %} + double* Vz = calloc(NY*NZ, sizeof(double)); + // change only the non-zero elements: + {% for j in range(end=dims.ny) %} + {%- for k in range(end=dims.nz) %} + {%- if cost.Vz[j][k] != 0 %} + Vz[{{ j }}+(NY) * {{ k }}] = {{ cost.Vz[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Vz", Vz); + } + free(Vz); + {%- endif %} +{%- endif %}{# LINEAR LS #} + +{%- if dims.ny_e == 0 %} +{%- elif cost.cost_type_e == "LINEAR_LS" %} + double* Vx_e = calloc(NYN*NX, sizeof(double)); + // change only the non-zero elements: + {% for j in range(end=dims.ny_e) %} + {%- for k in range(end=dims.nx) %} + {%- if cost.Vx_e[j][k] != 0 %} + Vx_e[{{ j }}+(NYN) * {{ k }}] = {{ cost.Vx_e[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "Vx", Vx_e); + free(Vx_e); +{%- endif %} + +{%- if cost.cost_type_0 == "NONLINEAR_LS" %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "nls_y_fun", &capsule->cost_y_0_fun); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "nls_y_fun_jac", &capsule->cost_y_0_fun_jac_ut_xt); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "nls_y_hess", &capsule->cost_y_0_hess); +{%- elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "conl_cost_fun", &capsule->conl_cost_0_fun); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "conl_cost_fun_jac_hess", &capsule->conl_cost_0_fun_jac_hess); +{%- elif cost.cost_type_0 == "EXTERNAL" %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "ext_cost_fun", &capsule->ext_cost_0_fun); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "ext_cost_fun_jac", &capsule->ext_cost_0_fun_jac); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "ext_cost_fun_jac_hess", &capsule->ext_cost_0_fun_jac_hess); +{%- endif %} + +{%- if cost.cost_type == "NONLINEAR_LS" %} + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "nls_y_fun", &capsule->cost_y_fun[i-1]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "nls_y_fun_jac", &capsule->cost_y_fun_jac_ut_xt[i-1]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "nls_y_hess", &capsule->cost_y_hess[i-1]); + } +{%- elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "conl_cost_fun", &capsule->conl_cost_fun[i-1]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "conl_cost_fun_jac_hess", &capsule->conl_cost_fun_jac_hess[i-1]); + } +{%- elif cost.cost_type == "EXTERNAL" %} + for (int i = 1; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "ext_cost_fun", &capsule->ext_cost_fun[i-1]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "ext_cost_fun_jac", &capsule->ext_cost_fun_jac[i-1]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "ext_cost_fun_jac_hess", &capsule->ext_cost_fun_jac_hess[i-1]); + } +{%- endif %} + +{%- if cost.cost_type_e == "NONLINEAR_LS" %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "nls_y_fun", &capsule->cost_y_e_fun); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "nls_y_fun_jac", &capsule->cost_y_e_fun_jac_ut_xt); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "nls_y_hess", &capsule->cost_y_e_hess); + +{%- elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "conl_cost_fun", &capsule->conl_cost_e_fun); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "conl_cost_fun_jac_hess", &capsule->conl_cost_e_fun_jac_hess); + +{%- elif cost.cost_type_e == "EXTERNAL" %} + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "ext_cost_fun", &capsule->ext_cost_e_fun); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "ext_cost_fun_jac", &capsule->ext_cost_e_fun_jac); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "ext_cost_fun_jac_hess", &capsule->ext_cost_e_fun_jac_hess); +{%- endif %} + + +{%- if dims.ns > 0 %} + // slacks + double* zlumem = calloc(4*NS, sizeof(double)); + double* Zl = zlumem+NS*0; + double* Zu = zlumem+NS*1; + double* zl = zlumem+NS*2; + double* zu = zlumem+NS*3; + // change only the non-zero elements: + {%- for j in range(end=dims.ns) %} + {%- if cost.Zl[j] != 0 %} + Zl[{{ j }}] = {{ cost.Zl[j] }}; + {%- endif %} + {%- endfor %} + + {%- for j in range(end=dims.ns) %} + {%- if cost.Zu[j] != 0 %} + Zu[{{ j }}] = {{ cost.Zu[j] }}; + {%- endif %} + {%- endfor %} + + {%- for j in range(end=dims.ns) %} + {%- if cost.zl[j] != 0 %} + zl[{{ j }}] = {{ cost.zl[j] }}; + {%- endif %} + {%- endfor %} + + {%- for j in range(end=dims.ns) %} + {%- if cost.zu[j] != 0 %} + zu[{{ j }}] = {{ cost.zu[j] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Zl", Zl); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "Zu", Zu); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "zl", zl); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, i, "zu", zu); + } + free(zlumem); +{%- endif %} + +{% if dims.ns_e > 0 %} + // slacks terminal + double* zluemem = calloc(4*NSN, sizeof(double)); + double* Zl_e = zluemem+NSN*0; + double* Zu_e = zluemem+NSN*1; + double* zl_e = zluemem+NSN*2; + double* zu_e = zluemem+NSN*3; + + // change only the non-zero elements: + {% for j in range(end=dims.ns_e) %} + {%- if cost.Zl_e[j] != 0 %} + Zl_e[{{ j }}] = {{ cost.Zl_e[j] }}; + {%- endif %} + {%- endfor %} + + {% for j in range(end=dims.ns_e) %} + {%- if cost.Zu_e[j] != 0 %} + Zu_e[{{ j }}] = {{ cost.Zu_e[j] }}; + {%- endif %} + {%- endfor %} + + {% for j in range(end=dims.ns_e) %} + {%- if cost.zl_e[j] != 0 %} + zl_e[{{ j }}] = {{ cost.zl_e[j] }}; + {%- endif %} + {%- endfor %} + + {% for j in range(end=dims.ns_e) %} + {%- if cost.zu_e[j] != 0 %} + zu_e[{{ j }}] = {{ cost.zu_e[j] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "Zl", Zl_e); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "Zu", Zu_e); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "zl", zl_e); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "zu", zu_e); + free(zluemem); +{%- endif %} + + /**** Constraints ****/ + + // bounds for initial stage +{%- if dims.nbx_0 > 0 %} + // x0 + int* idxbx0 = malloc(NBX0 * sizeof(int)); + {%- for i in range(end=dims.nbx_0) %} + idxbx0[{{ i }}] = {{ constraints.idxbx_0[i] }}; + {%- endfor %} + + double* lubx0 = calloc(2*NBX0, sizeof(double)); + double* lbx0 = lubx0; + double* ubx0 = lubx0 + NBX0; + // change only the non-zero elements: + {%- for i in range(end=dims.nbx_0) %} + {%- if constraints.lbx_0[i] != 0 %} + lbx0[{{ i }}] = {{ constraints.lbx_0[i] }}; + {%- endif %} + {%- if constraints.ubx_0[i] != 0 %} + ubx0[{{ i }}] = {{ constraints.ubx_0[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxbx", idxbx0); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbx", lbx0); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubx", ubx0); + free(idxbx0); + free(lubx0); +{%- endif %} + +{%- if dims.nbxe_0 > 0 %} + // idxbxe_0 + int* idxbxe_0 = malloc({{ dims.nbxe_0 }} * sizeof(int)); + {% for i in range(end=dims.nbxe_0) %} + idxbxe_0[{{ i }}] = {{ constraints.idxbxe_0[i] }}; + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxbxe", idxbxe_0); + free(idxbxe_0); +{%- endif %} + + /* constraints that are the same for initial and intermediate */ +{%- if dims.nsbx > 0 %} +{# TODO: introduce nsbx0 & move this block down!! #} + // ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxsbx", idxsbx); + // ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lsbx", lsbx); + // ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "usbx", usbx); + + // soft bounds on x + int* idxsbx = malloc(NSBX * sizeof(int)); + {%- for i in range(end=dims.nsbx) %} + idxsbx[{{ i }}] = {{ constraints.idxsbx[i] }}; + {%- endfor %} + + double* lusbx = calloc(2*NSBX, sizeof(double)); + double* lsbx = lusbx; + double* usbx = lusbx + NSBX; + {%- for i in range(end=dims.nsbx) %} + {%- if constraints.lsbx[i] != 0 %} + lsbx[{{ i }}] = {{ constraints.lsbx[i] }}; + {%- endif %} + {%- if constraints.usbx[i] != 0 %} + usbx[{{ i }}] = {{ constraints.usbx[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 1; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsbx", idxsbx); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsbx", lsbx); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usbx", usbx); + } + free(idxsbx); + free(lusbx); +{%- endif %} + + +{%- if dims.nbu > 0 %} + // u + int* idxbu = malloc(NBU * sizeof(int)); + {% for i in range(end=dims.nbu) %} + idxbu[{{ i }}] = {{ constraints.idxbu[i] }}; + {%- endfor %} + double* lubu = calloc(2*NBU, sizeof(double)); + double* lbu = lubu; + double* ubu = lubu + NBU; + {% for i in range(end=dims.nbu) %} + {%- if constraints.lbu[i] != 0 %} + lbu[{{ i }}] = {{ constraints.lbu[i] }}; + {%- endif %} + {%- if constraints.ubu[i] != 0 %} + ubu[{{ i }}] = {{ constraints.ubu[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxbu", idxbu); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lbu", lbu); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ubu", ubu); + } + free(idxbu); + free(lubu); +{%- endif %} + +{%- if dims.nsbu > 0 %} + // set up soft bounds for u + int* idxsbu = malloc(NSBU * sizeof(int)); + {% for i in range(end=dims.nsbu) %} + idxsbu[{{ i }}] = {{ constraints.idxsbu[i] }}; + {%- endfor %} + double* lusbu = calloc(2*NSBU, sizeof(double)); + double* lsbu = lusbu; + double* usbu = lusbu + NSBU; + {% for i in range(end=dims.nsbu) %} + {%- if constraints.lsbu[i] != 0 %} + lsbu[{{ i }}] = {{ constraints.lsbu[i] }}; + {%- endif %} + {%- if constraints.usbu[i] != 0 %} + usbu[{{ i }}] = {{ constraints.usbu[i] }}; + {%- endif %} + {%- endfor %} + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsbu", idxsbu); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsbu", lsbu); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usbu", usbu); + } + free(idxsbu); + free(lusbu); +{%- endif %} + +{% if dims.nsg > 0 %} + // set up soft bounds for general linear constraints + int* idxsg = malloc(NSG * sizeof(int)); + {% for i in range(end=dims.nsg) %} + idxsg[{{ i }}] = {{ constraints.idxsg[i] }}; + {%- endfor %} + double* lusg = calloc(2*NSG, sizeof(double)); + double* lsg = lusg; + double* usg = lusg + NSG; + {% for i in range(end=dims.nsg) %} + {%- if constraints.lsg[i] != 0 %} + lsg[{{ i }}] = {{ constraints.lsg[i] }}; + {%- endif %} + {%- if constraints.usg[i] != 0 %} + usg[{{ i }}] = {{ constraints.usg[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsg", idxsg); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsg", lsg); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usg", usg); + } + free(idxsg); + free(lusg); +{%- endif %} + +{% if dims.nsh > 0 %} + // set up soft bounds for nonlinear constraints + int* idxsh = malloc(NSH * sizeof(int)); + {% for i in range(end=dims.nsh) %} + idxsh[{{ i }}] = {{ constraints.idxsh[i] }}; + {%- endfor %} + double* lush = calloc(2*NSH, sizeof(double)); + double* lsh = lush; + double* ush = lush + NSH; + {% for i in range(end=dims.nsh) %} + {%- if constraints.lsh[i] != 0 %} + lsh[{{ i }}] = {{ constraints.lsh[i] }}; + {%- endif %} + {%- if constraints.ush[i] != 0 %} + ush[{{ i }}] = {{ constraints.ush[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsh", idxsh); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsh", lsh); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ush", ush); + } + free(idxsh); + free(lush); +{%- endif %} + +{% if dims.nsphi > 0 %} + // set up soft bounds for convex-over-nonlinear constraints + int* idxsphi = malloc(NSPHI * sizeof(int)); + {% for i in range(end=dims.nsphi) %} + idxsphi[{{ i }}] = {{ constraints.idxsphi[i] }}; + {%- endfor %} + double* lusphi = calloc(2*NSPHI, sizeof(double)); + double* lsphi = lusphi; + double* usphi = lusphi + NSPHI; + {% for i in range(end=dims.nsphi) %} + {%- if constraints.lsphi[i] != 0 %} + lsphi[{{ i }}] = {{ constraints.lsphi[i] }}; + {%- endif %} + {%- if constraints.usphi[i] != 0 %} + usphi[{{ i }}] = {{ constraints.usphi[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxsphi", idxsphi); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lsphi", lsphi); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "usphi", usphi); + } + free(idxsphi); + free(lusphi); +{%- endif %} + +{% if dims.nbx > 0 %} + // x + int* idxbx = malloc(NBX * sizeof(int)); + {% for i in range(end=dims.nbx) %} + idxbx[{{ i }}] = {{ constraints.idxbx[i] }}; + {%- endfor %} + double* lubx = calloc(2*NBX, sizeof(double)); + double* lbx = lubx; + double* ubx = lubx + NBX; + {% for i in range(end=dims.nbx) %} + {%- if constraints.lbx[i] != 0 %} + lbx[{{ i }}] = {{ constraints.lbx[i] }}; + {%- endif %} + {%- if constraints.ubx[i] != 0 %} + ubx[{{ i }}] = {{ constraints.ubx[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 1; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "idxbx", idxbx); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lbx", lbx); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ubx", ubx); + } + free(idxbx); + free(lubx); +{%- endif %} + +{% if dims.ng > 0 %} + // set up general constraints for stage 0 to N-1 + double* D = calloc(NG*NU, sizeof(double)); + double* C = calloc(NG*NX, sizeof(double)); + double* lug = calloc(2*NG, sizeof(double)); + double* lg = lug; + double* ug = lug + NG; + + {% for j in range(end=dims.ng) -%} + {% for k in range(end=dims.nu) %} + {%- if constraints.D[j][k] != 0 %} + D[{{ j }}+NG * {{ k }}] = {{ constraints.D[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + + {% for j in range(end=dims.ng) -%} + {% for k in range(end=dims.nx) %} + {%- if constraints.C[j][k] != 0 %} + C[{{ j }}+NG * {{ k }}] = {{ constraints.C[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + + {% for i in range(end=dims.ng) %} + {%- if constraints.lg[i] != 0 %} + lg[{{ i }}] = {{ constraints.lg[i] }}; + {%- endif %} + {%- endfor %} + + {% for i in range(end=dims.ng) %} + {%- if constraints.ug[i] != 0 %} + ug[{{ i }}] = {{ constraints.ug[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "D", D); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "C", C); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lg", lg); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "ug", ug); + } + free(D); + free(C); + free(lug); +{%- endif %} + +{% if dims.nh > 0 %} + // set up nonlinear constraints for stage 0 to N-1 + double* luh = calloc(2*NH, sizeof(double)); + double* lh = luh; + double* uh = luh + NH; + + {% for i in range(end=dims.nh) %} + {%- if constraints.lh[i] != 0 %} + lh[{{ i }}] = {{ constraints.lh[i] }}; + {%- endif %} + {%- endfor %} + + {% for i in range(end=dims.nh) %} + {%- if constraints.uh[i] != 0 %} + uh[{{ i }}] = {{ constraints.uh[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + // nonlinear constraints for stages 0 to N-1 + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "nl_constr_h_fun_jac", + &capsule->nl_constr_h_fun_jac[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "nl_constr_h_fun", + &capsule->nl_constr_h_fun[i]); + {% if solver_options.hessian_approx == "EXACT" %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, + "nl_constr_h_fun_jac_hess", &capsule->nl_constr_h_fun_jac_hess[i]); + {% endif %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lh", lh); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "uh", uh); + } + free(luh); +{%- endif %} + +{% if dims.nphi > 0 and constraints.constr_type == "BGP" %} + // set up convex-over-nonlinear constraints for stage 0 to N-1 + double* luphi = calloc(2*NPHI, sizeof(double)); + double* lphi = luphi; + double* uphi = luphi + NPHI; + {% for i in range(end=dims.nphi) %} + {%- if constraints.lphi[i] != 0 %} + lphi[{{ i }}] = {{ constraints.lphi[i] }}; + {%- endif %} + {%- endfor %} + + {% for i in range(end=dims.nphi) %} + {%- if constraints.uphi[i] != 0 %} + uphi[{{ i }}] = {{ constraints.uphi[i] }}; + {%- endif %} + {%- endfor %} + + for (int i = 0; i < N; i++) + { + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, + "nl_constr_phi_o_r_fun_phi_jac_ux_z_phi_hess_r_jac_ux", &capsule->phi_constraint[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "lphi", lphi); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, i, "uphi", uphi); + } + free(luphi); +{%- endif %} + + /* terminal constraints */ +{% if dims.nbx_e > 0 %} + // set up bounds for last stage + // x + int* idxbx_e = malloc(NBXN * sizeof(int)); + {% for i in range(end=dims.nbx_e) %} + idxbx_e[{{ i }}] = {{ constraints.idxbx_e[i] }}; + {%- endfor %} + double* lubx_e = calloc(2*NBXN, sizeof(double)); + double* lbx_e = lubx_e; + double* ubx_e = lubx_e + NBXN; + {% for i in range(end=dims.nbx_e) %} + {%- if constraints.lbx_e[i] != 0 %} + lbx_e[{{ i }}] = {{ constraints.lbx_e[i] }}; + {%- endif %} + {%- if constraints.ubx_e[i] != 0 %} + ubx_e[{{ i }}] = {{ constraints.ubx_e[i] }}; + {%- endif %} + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxbx", idxbx_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lbx", lbx_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ubx", ubx_e); + free(idxbx_e); + free(lubx_e); +{%- endif %} + +{% if dims.nsg_e > 0 %} + // set up soft bounds for general linear constraints + int* idxsg_e = calloc(NSGN, sizeof(int)); + {% for i in range(end=dims.nsg_e) %} + idxsg_e[{{ i }}] = {{ constraints.idxsg_e[i] }}; + {%- endfor %} + double* lusg_e = calloc(2*NSGN, sizeof(double)); + double* lsg_e = lusg_e; + double* usg_e = lusg_e + NSGN; + {% for i in range(end=dims.nsg_e) %} + {%- if constraints.lsg_e[i] != 0 %} + lsg_e[{{ i }}] = {{ constraints.lsg_e[i] }}; + {%- endif %} + {%- if constraints.usg_e[i] != 0 %} + usg_e[{{ i }}] = {{ constraints.usg_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsg", idxsg_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsg", lsg_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "usg", usg_e); + free(idxsg_e); + free(lusg_e); +{%- endif %} + +{% if dims.nsh_e > 0 %} + // set up soft bounds for nonlinear constraints + int* idxsh_e = malloc(NSHN * sizeof(int)); + {% for i in range(end=dims.nsh_e) %} + idxsh_e[{{ i }}] = {{ constraints.idxsh_e[i] }}; + {%- endfor %} + double* lush_e = calloc(2*NSHN, sizeof(double)); + double* lsh_e = lush_e; + double* ush_e = lush_e + NSHN; + {% for i in range(end=dims.nsh_e) %} + {%- if constraints.lsh_e[i] != 0 %} + lsh_e[{{ i }}] = {{ constraints.lsh_e[i] }}; + {%- endif %} + {%- if constraints.ush_e[i] != 0 %} + ush_e[{{ i }}] = {{ constraints.ush_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsh", idxsh_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsh", lsh_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ush", ush_e); + free(idxsh_e); + free(lush_e); +{%- endif %} + +{% if dims.nsphi_e > 0 %} + // set up soft bounds for convex-over-nonlinear constraints + int* idxsphi_e = malloc(NSPHIN * sizeof(int)); + {% for i in range(end=dims.nsphi_e) %} + idxsphi_e[{{ i }}] = {{ constraints.idxsphi_e[i] }}; + {%- endfor %} + double* lusphi_e = calloc(2*NSPHIN, sizeof(double)); + double* lsphi_e = lusphi_e; + double* usphi_e = lusphi_e + NSPHIN; + {% for i in range(end=dims.nsphi_e) %} + {%- if constraints.lsphi_e[i] != 0 %} + lsphi_e[{{ i }}] = {{ constraints.lsphi_e[i] }}; + {%- endif %} + {%- if constraints.usphi_e[i] != 0 %} + usphi_e[{{ i }}] = {{ constraints.usphi_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsphi", idxsphi_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsphi", lsphi_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "usphi", usphi_e); + free(idxsphi_e); + free(lusphi_e); +{%- endif %} + +{% if dims.nsbx_e > 0 %} + // soft bounds on x + int* idxsbx_e = malloc(NSBXN * sizeof(int)); + {% for i in range(end=dims.nsbx_e) %} + idxsbx_e[{{ i }}] = {{ constraints.idxsbx_e[i] }}; + {%- endfor %} + double* lusbx_e = calloc(2*NSBXN, sizeof(double)); + double* lsbx_e = lusbx_e; + double* usbx_e = lusbx_e + NSBXN; + {% for i in range(end=dims.nsbx_e) %} + {%- if constraints.lsbx_e[i] != 0 %} + lsbx_e[{{ i }}] = {{ constraints.lsbx_e[i] }}; + {%- endif %} + {%- if constraints.usbx_e[i] != 0 %} + usbx_e[{{ i }}] = {{ constraints.usbx_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "idxsbx", idxsbx_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lsbx", lsbx_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "usbx", usbx_e); + free(idxsbx_e); + free(lusbx_e); +{% endif %} + +{% if dims.ng_e > 0 %} + // set up general constraints for last stage + double* C_e = calloc(NGN*NX, sizeof(double)); + double* lug_e = calloc(2*NGN, sizeof(double)); + double* lg_e = lug_e; + double* ug_e = lug_e + NGN; + + {% for j in range(end=dims.ng_e) %} + {%- for k in range(end=dims.nx) %} + {%- if constraints.C_e[j][k] != 0 %} + C_e[{{ j }}+NGN * {{ k }}] = {{ constraints.C_e[j][k] }}; + {%- endif %} + {%- endfor %} + {%- endfor %} + + {% for i in range(end=dims.ng_e) %} + {%- if constraints.lg_e[i] != 0 %} + lg_e[{{ i }}] = {{ constraints.lg_e[i] }}; + {%- endif %} + {%- if constraints.ug_e[i] != 0 %} + ug_e[{{ i }}] = {{ constraints.ug_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "C", C_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lg", lg_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ug", ug_e); + free(C_e); + free(lug_e); +{%- endif %} + +{% if dims.nh_e > 0 %} + // set up nonlinear constraints for last stage + double* luh_e = calloc(2*NHN, sizeof(double)); + double* lh_e = luh_e; + double* uh_e = luh_e + NHN; + {% for i in range(end=dims.nh_e) %} + {%- if constraints.lh_e[i] != 0 %} + lh_e[{{ i }}] = {{ constraints.lh_e[i] }}; + {%- endif %} + {%- endfor %} + + {% for i in range(end=dims.nh_e) %} + {%- if constraints.uh_e[i] != 0 %} + uh_e[{{ i }}] = {{ constraints.uh_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "nl_constr_h_fun_jac", &capsule->nl_constr_h_e_fun_jac); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "nl_constr_h_fun", &capsule->nl_constr_h_e_fun); + {% if solver_options.hessian_approx == "EXACT" %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "nl_constr_h_fun_jac_hess", + &capsule->nl_constr_h_e_fun_jac_hess); + {% endif %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lh", lh_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uh", uh_e); + free(luh_e); +{%- endif %} + +{% if dims.nphi_e > 0 and constraints.constr_type_e == "BGP" %} + // set up convex-over-nonlinear constraints for last stage + double* luphi_e = calloc(2*NPHIN, sizeof(double)); + double* lphi_e = luphi_e; + double* uphi_e = luphi_e + NPHIN; + {% for i in range(end=dims.nphi_e) %} + {%- if constraints.lphi_e[i] != 0 %} + lphi_e[{{ i }}] = {{ constraints.lphi_e[i] }}; + {%- endif %} + {%- if constraints.uphi_e[i] != 0 %} + uphi_e[{{ i }}] = {{ constraints.uphi_e[i] }}; + {%- endif %} + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lphi", lphi_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uphi", uphi_e); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, + "nl_constr_phi_o_r_fun_phi_jac_ux_z_phi_hess_r_jac_ux", &capsule->phi_e_constraint); + free(luphi_e); +{% endif %} +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 6 + */ +void {{ model.name }}_acados_create_6_set_opts({{ model.name }}_solver_capsule* capsule) +{ + const int N = capsule->nlp_solver_plan->N; + ocp_nlp_config* nlp_config = capsule->nlp_config; + void *nlp_opts = capsule->nlp_opts; + + /************************************************ + * opts + ************************************************/ + +{% if solver_options.hessian_approx == "EXACT" %} + int nlp_solver_exact_hessian = 1; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "exact_hess", &nlp_solver_exact_hessian); + + int exact_hess_dyn = {{ solver_options.exact_hess_dyn }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "exact_hess_dyn", &exact_hess_dyn); + + int exact_hess_cost = {{ solver_options.exact_hess_cost }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "exact_hess_cost", &exact_hess_cost); + + int exact_hess_constr = {{ solver_options.exact_hess_constr }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "exact_hess_constr", &exact_hess_constr); +{%- endif -%} + +{%- if solver_options.globalization == "FIXED_STEP" %} + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "globalization", "fixed_step"); +{%- elif solver_options.globalization == "MERIT_BACKTRACKING" %} + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "globalization", "merit_backtracking"); + + double alpha_min = {{ solver_options.alpha_min }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "alpha_min", &alpha_min); + + double alpha_reduction = {{ solver_options.alpha_reduction }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "alpha_reduction", &alpha_reduction); + + int line_search_use_sufficient_descent = {{ solver_options.line_search_use_sufficient_descent }}; + ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "line_search_use_sufficient_descent", &line_search_use_sufficient_descent); + + int globalization_use_SOC = {{ solver_options.globalization_use_SOC }}; + ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "globalization_use_SOC", &globalization_use_SOC); + + double eps_sufficient_descent = {{ solver_options.eps_sufficient_descent }}; + ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "eps_sufficient_descent", &eps_sufficient_descent); +{%- endif -%} + int full_step_dual = {{ solver_options.full_step_dual }}; + ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "full_step_dual", &full_step_dual); + +{%- if dims.nz > 0 %} + // TODO: these options are lower level -> should be encapsulated! maybe through hessian approx option. + bool output_z_val = true; + bool sens_algebraic_val = true; + + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_output_z", &output_z_val); + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_sens_algebraic", &sens_algebraic_val); +{%- endif %} + +{%- if solver_options.integrator_type != "DISCRETE" %} + + // set collocation type (relevant for implicit integrators) + sim_collocation_type collocation_type = {{ solver_options.collocation_type }}; + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_collocation_type", &collocation_type); + + // set up sim_method_num_steps + {%- set all_equal = true %} + {%- set val = solver_options.sim_method_num_steps[0] %} + {%- for j in range(start=1, end=dims.N) %} + {%- if val != solver_options.sim_method_num_steps[j] %} + {%- set_global all_equal = false %} + {%- break %} + {%- endif %} + {%- endfor %} + + {%- if all_equal == true %} + // all sim_method_num_steps are identical + int sim_method_num_steps = {{ solver_options.sim_method_num_steps[0] }}; + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_num_steps", &sim_method_num_steps); + {%- else %} + // sim_method_num_steps are different + int* sim_method_num_steps = malloc(N*sizeof(int)); + {%- for j in range(end=dims.N) %} + sim_method_num_steps[{{ j }}] = {{ solver_options.sim_method_num_steps[j] }}; + {%- endfor %} + + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_num_steps", &sim_method_num_steps[i]); + free(sim_method_num_steps); + {%- endif %} + + // set up sim_method_num_stages + {%- set all_equal = true %} + {%- set val = solver_options.sim_method_num_stages[0] %} + {%- for j in range(start=1, end=dims.N) %} + {%- if val != solver_options.sim_method_num_stages[j] %} + {%- set_global all_equal = false %} + {%- break %} + {%- endif %} + {%- endfor %} + + {%- if all_equal == true %} + // all sim_method_num_stages are identical + int sim_method_num_stages = {{ solver_options.sim_method_num_stages[0] }}; + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_num_stages", &sim_method_num_stages); + {%- else %} + int* sim_method_num_stages = malloc(N*sizeof(int)); + {%- for j in range(end=dims.N) %} + sim_method_num_stages[{{ j }}] = {{ solver_options.sim_method_num_stages[j] }}; + {%- endfor %} + + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_num_stages", &sim_method_num_stages[i]); + free(sim_method_num_stages); + {%- endif %} + + int newton_iter_val = {{ solver_options.sim_method_newton_iter }}; + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_newton_iter", &newton_iter_val); + + + // set up sim_method_jac_reuse + {%- set all_equal = true %} + {%- set val = solver_options.sim_method_jac_reuse[0] %} + {%- for j in range(start=1, end=dims.N) %} + {%- if val != solver_options.sim_method_jac_reuse[j] %} + {%- set_global all_equal = false %} + {%- break %} + {%- endif %} + {%- endfor %} + {%- if all_equal == true %} + bool tmp_bool = (bool) {{ solver_options.sim_method_jac_reuse[0] }}; + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_jac_reuse", &tmp_bool); + {%- else %} + bool* sim_method_jac_reuse = malloc(N*sizeof(bool)); + {%- for j in range(end=dims.N) %} + sim_method_jac_reuse[{{ j }}] = (bool){{ solver_options.sim_method_jac_reuse[j] }}; + {%- endfor %} + + for (int i = 0; i < N; i++) + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "dynamics_jac_reuse", &sim_method_jac_reuse[i]); + free(sim_method_jac_reuse); + {%- endif %} + +{%- endif %} + + double nlp_solver_step_length = {{ solver_options.nlp_solver_step_length }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "step_length", &nlp_solver_step_length); + + {%- if solver_options.nlp_solver_warm_start_first_qp %} + int nlp_solver_warm_start_first_qp = {{ solver_options.nlp_solver_warm_start_first_qp }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "warm_start_first_qp", &nlp_solver_warm_start_first_qp); + {%- endif %} + + double levenberg_marquardt = {{ solver_options.levenberg_marquardt }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "levenberg_marquardt", &levenberg_marquardt); + + /* options QP solver */ +{%- if solver_options.qp_solver is starting_with("PARTIAL_CONDENSING") %} + int qp_solver_cond_N; + + {% if solver_options.qp_solver_cond_N -%} + const int qp_solver_cond_N_ori = {{ solver_options.qp_solver_cond_N }}; + qp_solver_cond_N = N < qp_solver_cond_N_ori ? N : qp_solver_cond_N_ori; // use the minimum value here + {%- else %} + // NOTE: there is no condensing happening here! + qp_solver_cond_N = N; + {%- endif %} + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_cond_N", &qp_solver_cond_N); +{%- endif %} + + int nlp_solver_ext_qp_res = {{ solver_options.nlp_solver_ext_qp_res }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "ext_qp_res", &nlp_solver_ext_qp_res); + +{%- if solver_options.qp_solver is containing("HPIPM") %} + // set HPIPM mode: should be done before setting other QP solver options + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_hpipm_mode", "{{ solver_options.hpipm_mode }}"); +{%- endif %} + +{% if solver_options.nlp_solver_type == "SQP" %} + // set SQP specific options + double nlp_solver_tol_stat = {{ solver_options.nlp_solver_tol_stat }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "tol_stat", &nlp_solver_tol_stat); + + double nlp_solver_tol_eq = {{ solver_options.nlp_solver_tol_eq }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "tol_eq", &nlp_solver_tol_eq); + + double nlp_solver_tol_ineq = {{ solver_options.nlp_solver_tol_ineq }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "tol_ineq", &nlp_solver_tol_ineq); + + double nlp_solver_tol_comp = {{ solver_options.nlp_solver_tol_comp }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "tol_comp", &nlp_solver_tol_comp); + + int nlp_solver_max_iter = {{ solver_options.nlp_solver_max_iter }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "max_iter", &nlp_solver_max_iter); + + int initialize_t_slacks = {{ solver_options.initialize_t_slacks }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "initialize_t_slacks", &initialize_t_slacks); +{%- endif %} + + int qp_solver_iter_max = {{ solver_options.qp_solver_iter_max }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_iter_max", &qp_solver_iter_max); + +{# NOTE: qp_solver tolerances must be set after NLP ones, since the setter for NLP tolerances sets the QP tolerances to the sam values. #} + {%- if solver_options.qp_solver_tol_stat %} + double qp_solver_tol_stat = {{ solver_options.qp_solver_tol_stat }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_tol_stat", &qp_solver_tol_stat); + {%- endif -%} + + {%- if solver_options.qp_solver_tol_eq %} + double qp_solver_tol_eq = {{ solver_options.qp_solver_tol_eq }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_tol_eq", &qp_solver_tol_eq); + {%- endif -%} + + {%- if solver_options.qp_solver_tol_ineq %} + double qp_solver_tol_ineq = {{ solver_options.qp_solver_tol_ineq }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_tol_ineq", &qp_solver_tol_ineq); + {%- endif -%} + + {%- if solver_options.qp_solver_tol_comp %} + double qp_solver_tol_comp = {{ solver_options.qp_solver_tol_comp }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_tol_comp", &qp_solver_tol_comp); + {%- endif -%} + + {%- if solver_options.qp_solver_warm_start %} + int qp_solver_warm_start = {{ solver_options.qp_solver_warm_start }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_warm_start", &qp_solver_warm_start); + {%- endif -%} + + int print_level = {{ solver_options.print_level }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "print_level", &print_level); + +{%- if solver_options.qp_solver is containing('PARTIAL_CONDENSING') %} + int qp_solver_cond_ric_alg = {{ solver_options.qp_solver_cond_ric_alg }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_cond_ric_alg", &qp_solver_cond_ric_alg); +{% endif %} + +{%- if solver_options.qp_solver == 'PARTIAL_CONDENSING_HPIPM' %} + int qp_solver_ric_alg = {{ solver_options.qp_solver_ric_alg }}; + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "qp_ric_alg", &qp_solver_ric_alg); +{% endif %} + + int ext_cost_num_hess = {{ solver_options.ext_cost_num_hess }}; +{%- if cost.cost_type == "EXTERNAL" %} + for (int i = 0; i < N; i++) + { + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, i, "cost_numerical_hessian", &ext_cost_num_hess); + } +{%- endif %} +{%- if cost.cost_type_e == "EXTERNAL" %} + ocp_nlp_solver_opts_set_at_stage(nlp_config, nlp_opts, N, "cost_numerical_hessian", &ext_cost_num_hess); +{%- endif %} +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 7 + */ +void {{ model.name }}_acados_create_7_set_nlp_out({{ model.name }}_solver_capsule* capsule) +{ + const int N = capsule->nlp_solver_plan->N; + ocp_nlp_config* nlp_config = capsule->nlp_config; + ocp_nlp_dims* nlp_dims = capsule->nlp_dims; + ocp_nlp_out* nlp_out = capsule->nlp_out; + + // initialize primal solution + double* xu0 = calloc(NX+NU, sizeof(double)); + double* x0 = xu0; +{% if dims.nbx_0 == dims.nx %} + // initialize with x0 + {% for item in constraints.lbx_0 %} + {%- if item != 0 %} + x0[{{ loop.index0 }}] = {{ item }}; + {%- endif %} + {%- endfor %} +{% else %} + // initialize with zeros +{%- endif %} + + double* u0 = xu0 + NX; + + for (int i = 0; i < N; i++) + { + // x0 + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "x", x0); + // u0 + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "u", u0); + } + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, N, "x", x0); + free(xu0); +} + + +/** + * Internal function for {{ model.name }}_acados_create: step 8 + */ +//void {{ model.name }}_acados_create_8_create_solver({{ model.name }}_solver_capsule* capsule) +//{ +// capsule->nlp_solver = ocp_nlp_solver_create(capsule->nlp_config, capsule->nlp_dims, capsule->nlp_opts); +//} + +/** + * Internal function for {{ model.name }}_acados_create: step 9 + */ +int {{ model.name }}_acados_create_9_precompute({{ model.name }}_solver_capsule* capsule) { + int status = ocp_nlp_precompute(capsule->nlp_solver, capsule->nlp_in, capsule->nlp_out); + + if (status != ACADOS_SUCCESS) { + printf("\nocp_nlp_precompute failed!\n\n"); + exit(1); + } + + return status; +} + + +int {{ model.name }}_acados_create_with_discretization({{ model.name }}_solver_capsule* capsule, int N, double* new_time_steps) +{ + // If N does not match the number of shooting intervals used for code generation, new_time_steps must be given. + if (N != {{ model.name | upper }}_N && !new_time_steps) { + fprintf(stderr, "{{ model.name }}_acados_create_with_discretization: new_time_steps is NULL " \ + "but the number of shooting intervals (= %d) differs from the number of " \ + "shooting intervals (= %d) during code generation! Please provide a new vector of time_stamps!\n", \ + N, {{ model.name | upper }}_N); + return 1; + } + + // number of expected runtime parameters + capsule->nlp_np = NP; + + // 1) create and set nlp_solver_plan; create nlp_config + capsule->nlp_solver_plan = ocp_nlp_plan_create(N); + {{ model.name }}_acados_create_1_set_plan(capsule->nlp_solver_plan, N); + capsule->nlp_config = ocp_nlp_config_create(*capsule->nlp_solver_plan); + + // 3) create and set dimensions + capsule->nlp_dims = {{ model.name }}_acados_create_2_create_and_set_dimensions(capsule); + {{ model.name }}_acados_create_3_create_and_set_functions(capsule); + + // 4) set default parameters in functions + {{ model.name }}_acados_create_4_set_default_parameters(capsule); + + // 5) create and set nlp_in + capsule->nlp_in = ocp_nlp_in_create(capsule->nlp_config, capsule->nlp_dims); + {{ model.name }}_acados_create_5_set_nlp_in(capsule, N, new_time_steps); + + // 6) create and set nlp_opts + capsule->nlp_opts = ocp_nlp_solver_opts_create(capsule->nlp_config, capsule->nlp_dims); + {{ model.name }}_acados_create_6_set_opts(capsule); + + // 7) create and set nlp_out + // 7.1) nlp_out + capsule->nlp_out = ocp_nlp_out_create(capsule->nlp_config, capsule->nlp_dims); + // 7.2) sens_out + capsule->sens_out = ocp_nlp_out_create(capsule->nlp_config, capsule->nlp_dims); + {{ model.name }}_acados_create_7_set_nlp_out(capsule); + + // 8) create solver + capsule->nlp_solver = ocp_nlp_solver_create(capsule->nlp_config, capsule->nlp_dims, capsule->nlp_opts); + //{{ model.name }}_acados_create_8_create_solver(capsule); + + // 9) do precomputations + int status = {{ model.name }}_acados_create_9_precompute(capsule); + + {%- if custom_update_filename != "" %} + // Initialize custom update function + custom_update_init_function(capsule); + {%- endif %} + + return status; +} + +/** + * This function is for updating an already initialized solver with a different number of qp_cond_N. It is useful for code reuse after code export. + */ +int {{ model.name }}_acados_update_qp_solver_cond_N({{ model.name }}_solver_capsule* capsule, int qp_solver_cond_N) +{ +{%- if solver_options.qp_solver is starting_with("PARTIAL_CONDENSING") %} + // 1) destroy solver + ocp_nlp_solver_destroy(capsule->nlp_solver); + + // 2) set new value for "qp_cond_N" + const int N = capsule->nlp_solver_plan->N; + if(qp_solver_cond_N > N) + printf("Warning: qp_solver_cond_N = %d > N = %d\n", qp_solver_cond_N, N); + ocp_nlp_solver_opts_set(capsule->nlp_config, capsule->nlp_opts, "qp_cond_N", &qp_solver_cond_N); + + // 3) continue with the remaining steps from {{ model.name }}_acados_create_with_discretization(...): + // -> 8) create solver + capsule->nlp_solver = ocp_nlp_solver_create(capsule->nlp_config, capsule->nlp_dims, capsule->nlp_opts); + + // -> 9) do precomputations + int status = {{ model.name }}_acados_create_9_precompute(capsule); + return status; +{%- else %} + printf("\nacados_update_qp_solver_cond_N() failed, since no partial condensing solver is used!\n\n"); + // Todo: what is an adequate behavior here? + exit(1); + return -1; +{%- endif %} +} + + +int {{ model.name }}_acados_reset({{ model.name }}_solver_capsule* capsule, int reset_qp_solver_mem) +{ + + // set initialization to all zeros +{# TODO: use guess values / initial state value from json instead?! #} + const int N = capsule->nlp_solver_plan->N; + ocp_nlp_config* nlp_config = capsule->nlp_config; + ocp_nlp_dims* nlp_dims = capsule->nlp_dims; + ocp_nlp_out* nlp_out = capsule->nlp_out; + ocp_nlp_in* nlp_in = capsule->nlp_in; + ocp_nlp_solver* nlp_solver = capsule->nlp_solver; + + double* buffer = calloc(NX+NU+NZ+2*NS+2*NSN+NBX+NBU+NG+NH+NPHI+NBX0+NBXN+NHN+NPHIN+NGN, sizeof(double)); + + for(int i=0; i reset memory + int qp_status; + ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "qp_status", &qp_status); + if (reset_qp_solver_mem || (qp_status == 3)) + { + // printf("\nin reset qp_status %d -> resetting QP memory\n", qp_status); + ocp_nlp_solver_reset_qp_memory(nlp_solver, nlp_in, nlp_out); + } +{%- endif %} + + free(buffer); + return 0; +} + + + + +int {{ model.name }}_acados_update_params({{ model.name }}_solver_capsule* capsule, int stage, double *p, int np) +{ + int solver_status = 0; + + int casadi_np = {{ dims.np }}; + if (casadi_np != np) { + printf("acados_update_params: trying to set %i parameters for external functions." + " External function has %i parameters. Exiting.\n", np, casadi_np); + exit(1); + } + + const int N = capsule->nlp_solver_plan->N; + if (stage < N && stage >= 0) + { + {%- if solver_options.integrator_type == "IRK" %} + capsule->impl_dae_fun[stage].set_param(capsule->impl_dae_fun+stage, p); + capsule->impl_dae_fun_jac_x_xdot_z[stage].set_param(capsule->impl_dae_fun_jac_x_xdot_z+stage, p); + capsule->impl_dae_jac_x_xdot_u_z[stage].set_param(capsule->impl_dae_jac_x_xdot_u_z+stage, p); + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->impl_dae_hess[stage].set_param(capsule->impl_dae_hess+stage, p); + {%- endif %} + {% elif solver_options.integrator_type == "LIFTED_IRK" %} + capsule->impl_dae_fun[stage].set_param(capsule->impl_dae_fun+stage, p); + capsule->impl_dae_fun_jac_x_xdot_u[stage].set_param(capsule->impl_dae_fun_jac_x_xdot_u+stage, p); + {% elif solver_options.integrator_type == "ERK" %} + capsule->forw_vde_casadi[stage].set_param(capsule->forw_vde_casadi+stage, p); + capsule->expl_ode_fun[stage].set_param(capsule->expl_ode_fun+stage, p); + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->hess_vde_casadi[stage].set_param(capsule->hess_vde_casadi+stage, p); + {%- endif %} + {% elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + capsule->gnsf_phi_fun[stage].set_param(capsule->gnsf_phi_fun+stage, p); + capsule->gnsf_phi_fun_jac_y[stage].set_param(capsule->gnsf_phi_fun_jac_y+stage, p); + capsule->gnsf_phi_jac_y_uhat[stage].set_param(capsule->gnsf_phi_jac_y_uhat+stage, p); + {% if model.gnsf.nontrivial_f_LO == 1 %} + capsule->gnsf_f_lo_jac_x1_x1dot_u_z[stage].set_param(capsule->gnsf_f_lo_jac_x1_x1dot_u_z+stage, p); + {%- endif %} + {%- endif %} + {% elif solver_options.integrator_type == "DISCRETE" %} + capsule->discr_dyn_phi_fun[stage].set_param(capsule->discr_dyn_phi_fun+stage, p); + capsule->discr_dyn_phi_fun_jac_ut_xt[stage].set_param(capsule->discr_dyn_phi_fun_jac_ut_xt+stage, p); + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->discr_dyn_phi_fun_jac_ut_xt_hess[stage].set_param(capsule->discr_dyn_phi_fun_jac_ut_xt_hess+stage, p); + {% endif %} + {%- endif %}{# integrator_type #} + + // constraints + {% if constraints.constr_type == "BGP" %} + capsule->phi_constraint[stage].set_param(capsule->phi_constraint+stage, p); + {% elif constraints.constr_type == "BGH" and dims.nh > 0 %} + capsule->nl_constr_h_fun_jac[stage].set_param(capsule->nl_constr_h_fun_jac+stage, p); + capsule->nl_constr_h_fun[stage].set_param(capsule->nl_constr_h_fun+stage, p); + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->nl_constr_h_fun_jac_hess[stage].set_param(capsule->nl_constr_h_fun_jac_hess+stage, p); + {%- endif %} + {%- endif %} + + // cost + if (stage == 0) + { + {%- if cost.cost_type_0 == "NONLINEAR_LS" %} + capsule->cost_y_0_fun.set_param(&capsule->cost_y_0_fun, p); + capsule->cost_y_0_fun_jac_ut_xt.set_param(&capsule->cost_y_0_fun_jac_ut_xt, p); + capsule->cost_y_0_hess.set_param(&capsule->cost_y_0_hess, p); + {%- elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + capsule->conl_cost_0_fun.set_param(&capsule->conl_cost_0_fun, p); + capsule->conl_cost_0_fun_jac_hess.set_param(&capsule->conl_cost_0_fun_jac_hess, p); + {%- elif cost.cost_type_0 == "EXTERNAL" %} + capsule->ext_cost_0_fun.set_param(&capsule->ext_cost_0_fun, p); + capsule->ext_cost_0_fun_jac.set_param(&capsule->ext_cost_0_fun_jac, p); + capsule->ext_cost_0_fun_jac_hess.set_param(&capsule->ext_cost_0_fun_jac_hess, p); + {% endif %} + } + else // 0 < stage < N + { + {%- if cost.cost_type == "NONLINEAR_LS" %} + capsule->cost_y_fun[stage-1].set_param(capsule->cost_y_fun+stage-1, p); + capsule->cost_y_fun_jac_ut_xt[stage-1].set_param(capsule->cost_y_fun_jac_ut_xt+stage-1, p); + capsule->cost_y_hess[stage-1].set_param(capsule->cost_y_hess+stage-1, p); + {%- elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} + capsule->conl_cost_fun[stage-1].set_param(capsule->conl_cost_fun+stage-1, p); + capsule->conl_cost_fun_jac_hess[stage-1].set_param(capsule->conl_cost_fun_jac_hess+stage-1, p); + {%- elif cost.cost_type == "EXTERNAL" %} + capsule->ext_cost_fun[stage-1].set_param(capsule->ext_cost_fun+stage-1, p); + capsule->ext_cost_fun_jac[stage-1].set_param(capsule->ext_cost_fun_jac+stage-1, p); + capsule->ext_cost_fun_jac_hess[stage-1].set_param(capsule->ext_cost_fun_jac_hess+stage-1, p); + {%- endif %} + } + } + + else // stage == N + { + // terminal shooting node has no dynamics + // cost + {%- if cost.cost_type_e == "NONLINEAR_LS" %} + capsule->cost_y_e_fun.set_param(&capsule->cost_y_e_fun, p); + capsule->cost_y_e_fun_jac_ut_xt.set_param(&capsule->cost_y_e_fun_jac_ut_xt, p); + capsule->cost_y_e_hess.set_param(&capsule->cost_y_e_hess, p); + {%- elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + capsule->conl_cost_e_fun.set_param(&capsule->conl_cost_e_fun, p); + capsule->conl_cost_e_fun_jac_hess.set_param(&capsule->conl_cost_e_fun_jac_hess, p); + {%- elif cost.cost_type_e == "EXTERNAL" %} + capsule->ext_cost_e_fun.set_param(&capsule->ext_cost_e_fun, p); + capsule->ext_cost_e_fun_jac.set_param(&capsule->ext_cost_e_fun_jac, p); + capsule->ext_cost_e_fun_jac_hess.set_param(&capsule->ext_cost_e_fun_jac_hess, p); + {% endif %} + // constraints + {% if constraints.constr_type_e == "BGP" %} + capsule->phi_e_constraint.set_param(&capsule->phi_e_constraint, p); + {% elif constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + capsule->nl_constr_h_e_fun_jac.set_param(&capsule->nl_constr_h_e_fun_jac, p); + capsule->nl_constr_h_e_fun.set_param(&capsule->nl_constr_h_e_fun, p); + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->nl_constr_h_e_fun_jac_hess.set_param(&capsule->nl_constr_h_e_fun_jac_hess, p); + {%- endif %} + {% endif %} + } + + return solver_status; +} + + +int {{ model.name }}_acados_update_params_sparse({{ model.name }}_solver_capsule * capsule, int stage, int *idx, double *p, int n_update) +{ + int solver_status = 0; + + int casadi_np = {{ dims.np }}; + if (casadi_np < n_update) { + printf("{{ model.name }}_acados_update_params_sparse: trying to set %d parameters for external functions." + " External function has %d parameters. Exiting.\n", n_update, casadi_np); + exit(1); + } + // for (int i = 0; i < n_update; i++) + // { + // if (idx[i] > casadi_np) { + // printf("{{ model.name }}_acados_update_params_sparse: attempt to set parameters with index %d, while" + // " external functions only has %d parameters. Exiting.\n", idx[i], casadi_np); + // exit(1); + // } + // printf("param %d value %e\n", idx[i], p[i]); + // } + +{%- if dims.np > 0 %} + const int N = capsule->nlp_solver_plan->N; + if (stage < N && stage >= 0) + { + {%- if solver_options.integrator_type == "IRK" %} + capsule->impl_dae_fun[stage].set_param_sparse(capsule->impl_dae_fun+stage, n_update, idx, p); + capsule->impl_dae_fun_jac_x_xdot_z[stage].set_param_sparse(capsule->impl_dae_fun_jac_x_xdot_z+stage, n_update, idx, p); + capsule->impl_dae_jac_x_xdot_u_z[stage].set_param_sparse(capsule->impl_dae_jac_x_xdot_u_z+stage, n_update, idx, p); + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->impl_dae_hess[stage].set_param_sparse(capsule->impl_dae_hess+stage, n_update, idx, p); + {%- endif %} + {% elif solver_options.integrator_type == "LIFTED_IRK" %} + capsule->impl_dae_fun[stage].set_param_sparse(capsule->impl_dae_fun+stage, n_update, idx, p); + capsule->impl_dae_fun_jac_x_xdot_u[stage].set_param_sparse(capsule->impl_dae_fun_jac_x_xdot_u+stage, n_update, idx, p); + {% elif solver_options.integrator_type == "ERK" %} + capsule->forw_vde_casadi[stage].set_param_sparse(capsule->forw_vde_casadi+stage, n_update, idx, p); + capsule->expl_ode_fun[stage].set_param_sparse(capsule->expl_ode_fun+stage, n_update, idx, p); + + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->hess_vde_casadi[stage].set_param_sparse(capsule->hess_vde_casadi+stage, n_update, idx, p); + {%- endif %} + {% elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + capsule->gnsf_phi_fun[stage].set_param_sparse(capsule->gnsf_phi_fun+stage, n_update, idx, p); + capsule->gnsf_phi_fun_jac_y[stage].set_param_sparse(capsule->gnsf_phi_fun_jac_y+stage, n_update, idx, p); + capsule->gnsf_phi_jac_y_uhat[stage].set_param_sparse(capsule->gnsf_phi_jac_y_uhat+stage, n_update, idx, p); + {% if model.gnsf.nontrivial_f_LO == 1 %} + capsule->gnsf_f_lo_jac_x1_x1dot_u_z[stage].set_param_sparse(capsule->gnsf_f_lo_jac_x1_x1dot_u_z+stage, n_update, idx, p); + {%- endif %} + {%- endif %} + {% elif solver_options.integrator_type == "DISCRETE" %} + capsule->discr_dyn_phi_fun[stage].set_param_sparse(capsule->discr_dyn_phi_fun+stage, n_update, idx, p); + capsule->discr_dyn_phi_fun_jac_ut_xt[stage].set_param_sparse(capsule->discr_dyn_phi_fun_jac_ut_xt+stage, n_update, idx, p); + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->discr_dyn_phi_fun_jac_ut_xt_hess[stage].set_param_sparse(capsule->discr_dyn_phi_fun_jac_ut_xt_hess+stage, n_update, idx, p); + {% endif %} + {%- endif %}{# integrator_type #} + + // constraints + {% if constraints.constr_type == "BGP" %} + capsule->phi_constraint[stage].set_param_sparse(capsule->phi_constraint+stage, n_update, idx, p); + {% elif constraints.constr_type == "BGH" and dims.nh > 0 %} + capsule->nl_constr_h_fun_jac[stage].set_param_sparse(capsule->nl_constr_h_fun_jac+stage, n_update, idx, p); + capsule->nl_constr_h_fun[stage].set_param_sparse(capsule->nl_constr_h_fun+stage, n_update, idx, p); + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->nl_constr_h_fun_jac_hess[stage].set_param_sparse(capsule->nl_constr_h_fun_jac_hess+stage, n_update, idx, p); + {%- endif %} + {%- endif %} + + // cost + if (stage == 0) + { + {%- if cost.cost_type_0 == "NONLINEAR_LS" %} + capsule->cost_y_0_fun.set_param_sparse(&capsule->cost_y_0_fun, n_update, idx, p); + capsule->cost_y_0_fun_jac_ut_xt.set_param_sparse(&capsule->cost_y_0_fun_jac_ut_xt, n_update, idx, p); + capsule->cost_y_0_hess.set_param_sparse(&capsule->cost_y_0_hess, n_update, idx, p); + {%- elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + capsule->conl_cost_0_fun.set_param_sparse(&capsule->conl_cost_0_fun, n_update, idx, p); + capsule->conl_cost_0_fun_jac_hess.set_param_sparse(&capsule->conl_cost_0_fun_jac_hess, n_update, idx, p); + {%- elif cost.cost_type_0 == "EXTERNAL" %} + capsule->ext_cost_0_fun.set_param_sparse(&capsule->ext_cost_0_fun, n_update, idx, p); + capsule->ext_cost_0_fun_jac.set_param_sparse(&capsule->ext_cost_0_fun_jac, n_update, idx, p); + capsule->ext_cost_0_fun_jac_hess.set_param_sparse(&capsule->ext_cost_0_fun_jac_hess, n_update, idx, p); + {% endif %} + } + else // 0 < stage < N + { + {%- if cost.cost_type == "NONLINEAR_LS" %} + capsule->cost_y_fun[stage-1].set_param_sparse(capsule->cost_y_fun+stage-1, n_update, idx, p); + capsule->cost_y_fun_jac_ut_xt[stage-1].set_param_sparse(capsule->cost_y_fun_jac_ut_xt+stage-1, n_update, idx, p); + capsule->cost_y_hess[stage-1].set_param_sparse(capsule->cost_y_hess+stage-1, n_update, idx, p); + {%- elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} + capsule->conl_cost_fun[stage-1].set_param_sparse(capsule->conl_cost_fun+stage-1, n_update, idx, p); + capsule->conl_cost_fun_jac_hess[stage-1].set_param_sparse(capsule->conl_cost_fun_jac_hess+stage-1, n_update, idx, p); + {%- elif cost.cost_type == "EXTERNAL" %} + capsule->ext_cost_fun[stage-1].set_param_sparse(capsule->ext_cost_fun+stage-1, n_update, idx, p); + capsule->ext_cost_fun_jac[stage-1].set_param_sparse(capsule->ext_cost_fun_jac+stage-1, n_update, idx, p); + capsule->ext_cost_fun_jac_hess[stage-1].set_param_sparse(capsule->ext_cost_fun_jac_hess+stage-1, n_update, idx, p); + {%- endif %} + } + } + + else // stage == N + { + // terminal shooting node has no dynamics + // cost + {%- if cost.cost_type_e == "NONLINEAR_LS" %} + capsule->cost_y_e_fun.set_param_sparse(&capsule->cost_y_e_fun, n_update, idx, p); + capsule->cost_y_e_fun_jac_ut_xt.set_param_sparse(&capsule->cost_y_e_fun_jac_ut_xt, n_update, idx, p); + capsule->cost_y_e_hess.set_param_sparse(&capsule->cost_y_e_hess, n_update, idx, p); + {%- elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + capsule->conl_cost_e_fun.set_param_sparse(&capsule->conl_cost_e_fun, n_update, idx, p); + capsule->conl_cost_e_fun_jac_hess.set_param_sparse(&capsule->conl_cost_e_fun_jac_hess, n_update, idx, p); + {%- elif cost.cost_type_e == "EXTERNAL" %} + capsule->ext_cost_e_fun.set_param_sparse(&capsule->ext_cost_e_fun, n_update, idx, p); + capsule->ext_cost_e_fun_jac.set_param_sparse(&capsule->ext_cost_e_fun_jac, n_update, idx, p); + capsule->ext_cost_e_fun_jac_hess.set_param_sparse(&capsule->ext_cost_e_fun_jac_hess, n_update, idx, p); + {% endif %} + // constraints + {% if constraints.constr_type_e == "BGP" %} + capsule->phi_e_constraint.set_param_sparse(&capsule->phi_e_constraint, n_update, idx, p); + {% elif constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + capsule->nl_constr_h_e_fun_jac.set_param_sparse(&capsule->nl_constr_h_e_fun_jac, n_update, idx, p); + capsule->nl_constr_h_e_fun.set_param_sparse(&capsule->nl_constr_h_e_fun, n_update, idx, p); + {%- if solver_options.hessian_approx == "EXACT" %} + capsule->nl_constr_h_e_fun_jac_hess.set_param_sparse(&capsule->nl_constr_h_e_fun_jac_hess, n_update, idx, p); + {%- endif %} + {% endif %} + } +{% endif %}{# if dims.np #} + + return solver_status; +} + +int {{ model.name }}_acados_solve({{ model.name }}_solver_capsule* capsule) +{ + // solve NLP + int solver_status = ocp_nlp_solve(capsule->nlp_solver, capsule->nlp_in, capsule->nlp_out); + + return solver_status; +} + + +int {{ model.name }}_acados_free({{ model.name }}_solver_capsule* capsule) +{ + // before destroying, keep some info + const int N = capsule->nlp_solver_plan->N; + {%- if custom_update_filename != "" %} + custom_update_terminate_function(capsule); + {%- endif %} + // free memory + ocp_nlp_solver_opts_destroy(capsule->nlp_opts); + ocp_nlp_in_destroy(capsule->nlp_in); + ocp_nlp_out_destroy(capsule->nlp_out); + ocp_nlp_out_destroy(capsule->sens_out); + ocp_nlp_solver_destroy(capsule->nlp_solver); + ocp_nlp_dims_destroy(capsule->nlp_dims); + ocp_nlp_config_destroy(capsule->nlp_config); + ocp_nlp_plan_destroy(capsule->nlp_solver_plan); + + /* free external function */ + // dynamics +{%- if solver_options.integrator_type == "IRK" %} + for (int i = 0; i < N; i++) + { + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->impl_dae_fun[i]); + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->impl_dae_fun_jac_x_xdot_z[i]); + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->impl_dae_jac_x_xdot_u_z[i]); + {%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->impl_dae_hess[i]); + {%- endif %} + } + free(capsule->impl_dae_fun); + free(capsule->impl_dae_fun_jac_x_xdot_z); + free(capsule->impl_dae_jac_x_xdot_u_z); + {%- if solver_options.hessian_approx == "EXACT" %} + free(capsule->impl_dae_hess); + {%- endif %} + +{%- elif solver_options.integrator_type == "LIFTED_IRK" %} + for (int i = 0; i < N; i++) + { + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->impl_dae_fun[i]); + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->impl_dae_fun_jac_x_xdot_u[i]); + } + free(capsule->impl_dae_fun); + free(capsule->impl_dae_fun_jac_x_xdot_u); + +{%- elif solver_options.integrator_type == "ERK" %} + for (int i = 0; i < N; i++) + { + external_function_param_casadi_free(&capsule->forw_vde_casadi[i]); + external_function_param_casadi_free(&capsule->expl_ode_fun[i]); + {%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_casadi_free(&capsule->hess_vde_casadi[i]); + {%- endif %} + } + free(capsule->forw_vde_casadi); + free(capsule->expl_ode_fun); + {%- if solver_options.hessian_approx == "EXACT" %} + free(capsule->hess_vde_casadi); + {%- endif %} + +{%- elif solver_options.integrator_type == "GNSF" %} + for (int i = 0; i < N; i++) + { + {% if model.gnsf.purely_linear != 1 %} + external_function_param_casadi_free(&capsule->gnsf_phi_fun[i]); + external_function_param_casadi_free(&capsule->gnsf_phi_fun_jac_y[i]); + external_function_param_casadi_free(&capsule->gnsf_phi_jac_y_uhat[i]); + {% if model.gnsf.nontrivial_f_LO == 1 %} + external_function_param_casadi_free(&capsule->gnsf_f_lo_jac_x1_x1dot_u_z[i]); + {%- endif %} + {%- endif %} + external_function_param_casadi_free(&capsule->gnsf_get_matrices_fun[i]); + } + {% if model.gnsf.purely_linear != 1 %} + free(capsule->gnsf_phi_fun); + free(capsule->gnsf_phi_fun_jac_y); + free(capsule->gnsf_phi_jac_y_uhat); + {% if model.gnsf.nontrivial_f_LO == 1 %} + free(capsule->gnsf_f_lo_jac_x1_x1dot_u_z); + {%- endif %} + {%- endif %} + free(capsule->gnsf_get_matrices_fun); +{%- elif solver_options.integrator_type == "DISCRETE" %} + for (int i = 0; i < N; i++) + { + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->discr_dyn_phi_fun[i]); + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->discr_dyn_phi_fun_jac_ut_xt[i]); + {%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_{{ model.dyn_ext_fun_type }}_free(&capsule->discr_dyn_phi_fun_jac_ut_xt_hess[i]); + {%- endif %} + } + free(capsule->discr_dyn_phi_fun); + free(capsule->discr_dyn_phi_fun_jac_ut_xt); + {%- if solver_options.hessian_approx == "EXACT" %} + free(capsule->discr_dyn_phi_fun_jac_ut_xt_hess); + {%- endif %} + +{%- endif %} + + // cost +{%- if cost.cost_type_0 == "NONLINEAR_LS" %} + external_function_param_casadi_free(&capsule->cost_y_0_fun); + external_function_param_casadi_free(&capsule->cost_y_0_fun_jac_ut_xt); + external_function_param_casadi_free(&capsule->cost_y_0_hess); +{%- elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + external_function_param_casadi_free(&capsule->conl_cost_0_fun); + external_function_param_casadi_free(&capsule->conl_cost_0_fun_jac_hess); +{%- elif cost.cost_type_0 == "EXTERNAL" %} + external_function_param_{{ cost.cost_ext_fun_type_0 }}_free(&capsule->ext_cost_0_fun); + external_function_param_{{ cost.cost_ext_fun_type_0 }}_free(&capsule->ext_cost_0_fun_jac); + external_function_param_{{ cost.cost_ext_fun_type_0 }}_free(&capsule->ext_cost_0_fun_jac_hess); +{%- endif %} +{%- if cost.cost_type == "NONLINEAR_LS" %} + for (int i = 0; i < N - 1; i++) + { + external_function_param_casadi_free(&capsule->cost_y_fun[i]); + external_function_param_casadi_free(&capsule->cost_y_fun_jac_ut_xt[i]); + external_function_param_casadi_free(&capsule->cost_y_hess[i]); + } + free(capsule->cost_y_fun); + free(capsule->cost_y_fun_jac_ut_xt); + free(capsule->cost_y_hess); +{%- elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} + for (int i = 0; i < N - 1; i++) + { + external_function_param_casadi_free(&capsule->conl_cost_fun[i]); + external_function_param_casadi_free(&capsule->conl_cost_fun_jac_hess[i]); + } + free(capsule->conl_cost_fun); + free(capsule->conl_cost_fun_jac_hess); +{%- elif cost.cost_type == "EXTERNAL" %} + for (int i = 0; i < N - 1; i++) + { + external_function_param_{{ cost.cost_ext_fun_type }}_free(&capsule->ext_cost_fun[i]); + external_function_param_{{ cost.cost_ext_fun_type }}_free(&capsule->ext_cost_fun_jac[i]); + external_function_param_{{ cost.cost_ext_fun_type }}_free(&capsule->ext_cost_fun_jac_hess[i]); + } + free(capsule->ext_cost_fun); + free(capsule->ext_cost_fun_jac); + free(capsule->ext_cost_fun_jac_hess); +{%- endif %} +{%- if cost.cost_type_e == "NONLINEAR_LS" %} + external_function_param_casadi_free(&capsule->cost_y_e_fun); + external_function_param_casadi_free(&capsule->cost_y_e_fun_jac_ut_xt); + external_function_param_casadi_free(&capsule->cost_y_e_hess); +{%- elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + external_function_param_casadi_free(&capsule->conl_cost_e_fun); + external_function_param_casadi_free(&capsule->conl_cost_e_fun_jac_hess); +{%- elif cost.cost_type_e == "EXTERNAL" %} + external_function_param_{{ cost.cost_ext_fun_type_e }}_free(&capsule->ext_cost_e_fun); + external_function_param_{{ cost.cost_ext_fun_type_e }}_free(&capsule->ext_cost_e_fun_jac); + external_function_param_{{ cost.cost_ext_fun_type_e }}_free(&capsule->ext_cost_e_fun_jac_hess); +{%- endif %} + + // constraints +{%- if constraints.constr_type == "BGH" and dims.nh > 0 %} + for (int i = 0; i < N; i++) + { + external_function_param_casadi_free(&capsule->nl_constr_h_fun_jac[i]); + external_function_param_casadi_free(&capsule->nl_constr_h_fun[i]); + } + {%- if solver_options.hessian_approx == "EXACT" %} + for (int i = 0; i < N; i++) + { + external_function_param_casadi_free(&capsule->nl_constr_h_fun_jac_hess[i]); + } + {%- endif %} + free(capsule->nl_constr_h_fun_jac); + free(capsule->nl_constr_h_fun); + {%- if solver_options.hessian_approx == "EXACT" %} + free(capsule->nl_constr_h_fun_jac_hess); + {%- endif %} + +{%- elif constraints.constr_type == "BGP" and dims.nphi > 0 %} + for (int i = 0; i < N; i++) + { + external_function_param_casadi_free(&capsule->phi_constraint[i]); + } + free(capsule->phi_constraint); +{%- endif %} + +{%- if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + external_function_param_casadi_free(&capsule->nl_constr_h_e_fun_jac); + external_function_param_casadi_free(&capsule->nl_constr_h_e_fun); +{%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_casadi_free(&capsule->nl_constr_h_e_fun_jac_hess); +{%- endif %} +{%- elif constraints.constr_type_e == "BGP" and dims.nphi_e > 0 %} + external_function_param_casadi_free(&capsule->phi_e_constraint); +{%- endif %} + + return 0; +} + + +void {{ model.name }}_acados_print_stats({{ model.name }}_solver_capsule* capsule) +{ + int sqp_iter, stat_m, stat_n, tmp_int; + ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "sqp_iter", &sqp_iter); + ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "stat_n", &stat_n); + ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "stat_m", &stat_m); + + {% set stat_n_max = 12 %} + double stat[{{ solver_options.nlp_solver_max_iter * stat_n_max }}]; + ocp_nlp_get(capsule->nlp_config, capsule->nlp_solver, "statistics", stat); + + int nrow = sqp_iter+1 < stat_m ? sqp_iter+1 : stat_m; + + printf("iter\tres_stat\tres_eq\t\tres_ineq\tres_comp\tqp_stat\tqp_iter\talpha"); + if (stat_n > 8) + printf("\t\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp"); + printf("\n"); + +{%- if solver_options.nlp_solver_type == "SQP" %} + + for (int i = 0; i < nrow; i++) + { + for (int j = 0; j < stat_n + 1; j++) + { + if (j == 0 || j == 5 || j == 6) + { + tmp_int = (int) stat[i + j * nrow]; + printf("%d\t", tmp_int); + } + else + { + printf("%e\t", stat[i + j * nrow]); + } + } + printf("\n"); + } +{% else %} + printf("iter\tqp_stat\tqp_iter\n"); + for (int i = 0; i < nrow; i++) + { + for (int j = 0; j < stat_n + 1; j++) + { + tmp_int = (int) stat[i + j * nrow]; + printf("%d\t", tmp_int); + } + printf("\n"); + } +{%- endif %} +} + +int {{ model.name }}_acados_custom_update({{ model.name }}_solver_capsule* capsule, double* data, int data_len) +{ +{%- if custom_update_filename == "" %} + (void)capsule; + (void)data; + (void)data_len; + printf("\ndummy function that can be called in between solver calls to update parameters or numerical data efficiently in C.\n"); + printf("nothing set yet..\n"); + return 1; +{% else %} + custom_update_function(capsule, data, data_len); +{%- endif %} +} + + + +ocp_nlp_in *{{ model.name }}_acados_get_nlp_in({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_in; } +ocp_nlp_out *{{ model.name }}_acados_get_nlp_out({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_out; } +ocp_nlp_out *{{ model.name }}_acados_get_sens_out({{ model.name }}_solver_capsule* capsule) { return capsule->sens_out; } +ocp_nlp_solver *{{ model.name }}_acados_get_nlp_solver({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_solver; } +ocp_nlp_config *{{ model.name }}_acados_get_nlp_config({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_config; } +void *{{ model.name }}_acados_get_nlp_opts({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_opts; } +ocp_nlp_dims *{{ model.name }}_acados_get_nlp_dims({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_dims; } +ocp_nlp_plan_t *{{ model.name }}_acados_get_nlp_plan({{ model.name }}_solver_capsule* capsule) { return capsule->nlp_solver_plan; } diff --git a/third_party/acados/acados_template/c_templates_tera/acados_solver.in.h b/third_party/acados/acados_template/c_templates_tera/acados_solver.in.h new file mode 100644 index 0000000000..5cf38aa8c8 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/acados_solver.in.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#ifndef ACADOS_SOLVER_{{ model.name }}_H_ +#define ACADOS_SOLVER_{{ model.name }}_H_ + +#include "acados/utils/types.h" + +#include "acados_c/ocp_nlp_interface.h" +#include "acados_c/external_function_interface.h" + +#define {{ model.name | upper }}_NX {{ dims.nx }} +#define {{ model.name | upper }}_NZ {{ dims.nz }} +#define {{ model.name | upper }}_NU {{ dims.nu }} +#define {{ model.name | upper }}_NP {{ dims.np }} +#define {{ model.name | upper }}_NBX {{ dims.nbx }} +#define {{ model.name | upper }}_NBX0 {{ dims.nbx_0 }} +#define {{ model.name | upper }}_NBU {{ dims.nbu }} +#define {{ model.name | upper }}_NSBX {{ dims.nsbx }} +#define {{ model.name | upper }}_NSBU {{ dims.nsbu }} +#define {{ model.name | upper }}_NSH {{ dims.nsh }} +#define {{ model.name | upper }}_NSG {{ dims.nsg }} +#define {{ model.name | upper }}_NSPHI {{ dims.nsphi }} +#define {{ model.name | upper }}_NSHN {{ dims.nsh_e }} +#define {{ model.name | upper }}_NSGN {{ dims.nsg_e }} +#define {{ model.name | upper }}_NSPHIN {{ dims.nsphi_e }} +#define {{ model.name | upper }}_NSBXN {{ dims.nsbx_e }} +#define {{ model.name | upper }}_NS {{ dims.ns }} +#define {{ model.name | upper }}_NSN {{ dims.ns_e }} +#define {{ model.name | upper }}_NG {{ dims.ng }} +#define {{ model.name | upper }}_NBXN {{ dims.nbx_e }} +#define {{ model.name | upper }}_NGN {{ dims.ng_e }} +#define {{ model.name | upper }}_NY0 {{ dims.ny_0 }} +#define {{ model.name | upper }}_NY {{ dims.ny }} +#define {{ model.name | upper }}_NYN {{ dims.ny_e }} +#define {{ model.name | upper }}_N {{ dims.N }} +#define {{ model.name | upper }}_NH {{ dims.nh }} +#define {{ model.name | upper }}_NPHI {{ dims.nphi }} +#define {{ model.name | upper }}_NHN {{ dims.nh_e }} +#define {{ model.name | upper }}_NPHIN {{ dims.nphi_e }} +#define {{ model.name | upper }}_NR {{ dims.nr }} + +#ifdef __cplusplus +extern "C" { +#endif + +{%- if not solver_options.custom_update_filename %} + {%- set custom_update_filename = "" %} +{% else %} + {%- set custom_update_filename = solver_options.custom_update_filename %} +{%- endif %} + +// ** capsule for solver data ** +typedef struct {{ model.name }}_solver_capsule +{ + // acados objects + ocp_nlp_in *nlp_in; + ocp_nlp_out *nlp_out; + ocp_nlp_out *sens_out; + ocp_nlp_solver *nlp_solver; + void *nlp_opts; + ocp_nlp_plan_t *nlp_solver_plan; + ocp_nlp_config *nlp_config; + ocp_nlp_dims *nlp_dims; + + // number of expected runtime parameters + unsigned int nlp_np; + + /* external functions */ + // dynamics +{% if solver_options.integrator_type == "ERK" %} + external_function_param_casadi *forw_vde_casadi; + external_function_param_casadi *expl_ode_fun; +{% if solver_options.hessian_approx == "EXACT" %} + external_function_param_casadi *hess_vde_casadi; +{%- endif %} +{% elif solver_options.integrator_type == "IRK" %} + external_function_param_{{ model.dyn_ext_fun_type }} *impl_dae_fun; + external_function_param_{{ model.dyn_ext_fun_type }} *impl_dae_fun_jac_x_xdot_z; + external_function_param_{{ model.dyn_ext_fun_type }} *impl_dae_jac_x_xdot_u_z; +{% if solver_options.hessian_approx == "EXACT" %} + external_function_param_{{ model.dyn_ext_fun_type }} *impl_dae_hess; +{%- endif %} +{% elif solver_options.integrator_type == "LIFTED_IRK" %} + external_function_param_{{ model.dyn_ext_fun_type }} *impl_dae_fun; + external_function_param_{{ model.dyn_ext_fun_type }} *impl_dae_fun_jac_x_xdot_u; +{% elif solver_options.integrator_type == "GNSF" %} + external_function_param_casadi *gnsf_phi_fun; + external_function_param_casadi *gnsf_phi_fun_jac_y; + external_function_param_casadi *gnsf_phi_jac_y_uhat; + external_function_param_casadi *gnsf_f_lo_jac_x1_x1dot_u_z; + external_function_param_casadi *gnsf_get_matrices_fun; +{% elif solver_options.integrator_type == "DISCRETE" %} + external_function_param_{{ model.dyn_ext_fun_type }} *discr_dyn_phi_fun; + external_function_param_{{ model.dyn_ext_fun_type }} *discr_dyn_phi_fun_jac_ut_xt; +{%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_{{ model.dyn_ext_fun_type }} *discr_dyn_phi_fun_jac_ut_xt_hess; +{%- endif %} +{%- endif %} + + + // cost +{% if cost.cost_type == "NONLINEAR_LS" %} + external_function_param_casadi *cost_y_fun; + external_function_param_casadi *cost_y_fun_jac_ut_xt; + external_function_param_casadi *cost_y_hess; +{% elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} + external_function_param_casadi *conl_cost_fun; + external_function_param_casadi *conl_cost_fun_jac_hess; +{%- elif cost.cost_type == "EXTERNAL" %} + external_function_param_{{ cost.cost_ext_fun_type }} *ext_cost_fun; + external_function_param_{{ cost.cost_ext_fun_type }} *ext_cost_fun_jac; + external_function_param_{{ cost.cost_ext_fun_type }} *ext_cost_fun_jac_hess; +{% endif %} + +{% if cost.cost_type_0 == "NONLINEAR_LS" %} + external_function_param_casadi cost_y_0_fun; + external_function_param_casadi cost_y_0_fun_jac_ut_xt; + external_function_param_casadi cost_y_0_hess; +{% elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + external_function_param_casadi conl_cost_0_fun; + external_function_param_casadi conl_cost_0_fun_jac_hess; +{% elif cost.cost_type_0 == "EXTERNAL" %} + external_function_param_{{ cost.cost_ext_fun_type_0 }} ext_cost_0_fun; + external_function_param_{{ cost.cost_ext_fun_type_0 }} ext_cost_0_fun_jac; + external_function_param_{{ cost.cost_ext_fun_type_0 }} ext_cost_0_fun_jac_hess; +{%- endif %} + +{% if cost.cost_type_e == "NONLINEAR_LS" %} + external_function_param_casadi cost_y_e_fun; + external_function_param_casadi cost_y_e_fun_jac_ut_xt; + external_function_param_casadi cost_y_e_hess; +{% elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} + external_function_param_casadi conl_cost_e_fun; + external_function_param_casadi conl_cost_e_fun_jac_hess; +{% elif cost.cost_type_e == "EXTERNAL" %} + external_function_param_{{ cost.cost_ext_fun_type_e }} ext_cost_e_fun; + external_function_param_{{ cost.cost_ext_fun_type_e }} ext_cost_e_fun_jac; + external_function_param_{{ cost.cost_ext_fun_type_e }} ext_cost_e_fun_jac_hess; +{%- endif %} + + // constraints +{%- if constraints.constr_type == "BGP" %} + external_function_param_casadi *phi_constraint; +{% elif constraints.constr_type == "BGH" and dims.nh > 0 %} + external_function_param_casadi *nl_constr_h_fun_jac; + external_function_param_casadi *nl_constr_h_fun; +{%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_casadi *nl_constr_h_fun_jac_hess; +{%- endif %} +{%- endif %} + + +{% if constraints.constr_type_e == "BGP" %} + external_function_param_casadi phi_e_constraint; +{% elif constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + external_function_param_casadi nl_constr_h_e_fun_jac; + external_function_param_casadi nl_constr_h_e_fun; +{%- if solver_options.hessian_approx == "EXACT" %} + external_function_param_casadi nl_constr_h_e_fun_jac_hess; +{%- endif %} +{%- endif %} + +{%- if custom_update_filename != "" %} + void * custom_update_memory; +{%- endif %} + +} {{ model.name }}_solver_capsule; + +ACADOS_SYMBOL_EXPORT {{ model.name }}_solver_capsule * {{ model.name }}_acados_create_capsule(void); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_free_capsule({{ model.name }}_solver_capsule *capsule); + +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_create({{ model.name }}_solver_capsule * capsule); + +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_reset({{ model.name }}_solver_capsule* capsule, int reset_qp_solver_mem); + +/** + * Generic version of {{ model.name }}_acados_create which allows to use a different number of shooting intervals than + * the number used for code generation. If new_time_steps=NULL and n_time_steps matches the number used for code + * generation, the time-steps from code generation is used. + */ +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_create_with_discretization({{ model.name }}_solver_capsule * capsule, int n_time_steps, double* new_time_steps); +/** + * Update the time step vector. Number N must be identical to the currently set number of shooting nodes in the + * nlp_solver_plan. Returns 0 if no error occurred and a otherwise a value other than 0. + */ +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_update_time_steps({{ model.name }}_solver_capsule * capsule, int N, double* new_time_steps); +/** + * This function is used for updating an already initialized solver with a different number of qp_cond_N. + */ +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_update_qp_solver_cond_N({{ model.name }}_solver_capsule * capsule, int qp_solver_cond_N); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_update_params({{ model.name }}_solver_capsule * capsule, int stage, double *value, int np); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_update_params_sparse({{ model.name }}_solver_capsule * capsule, int stage, int *idx, double *p, int n_update); + +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_solve({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_free({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT void {{ model.name }}_acados_print_stats({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT int {{ model.name }}_acados_custom_update({{ model.name }}_solver_capsule* capsule, double* data, int data_len); + + +ACADOS_SYMBOL_EXPORT ocp_nlp_in *{{ model.name }}_acados_get_nlp_in({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT ocp_nlp_out *{{ model.name }}_acados_get_nlp_out({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT ocp_nlp_out *{{ model.name }}_acados_get_sens_out({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT ocp_nlp_solver *{{ model.name }}_acados_get_nlp_solver({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT ocp_nlp_config *{{ model.name }}_acados_get_nlp_config({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT void *{{ model.name }}_acados_get_nlp_opts({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT ocp_nlp_dims *{{ model.name }}_acados_get_nlp_dims({{ model.name }}_solver_capsule * capsule); +ACADOS_SYMBOL_EXPORT ocp_nlp_plan_t *{{ model.name }}_acados_get_nlp_plan({{ model.name }}_solver_capsule * capsule); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_SOLVER_{{ model.name }}_H_ diff --git a/third_party/acados/acados_template/c_templates_tera/acados_solver.in.pxd b/third_party/acados/acados_template/c_templates_tera/acados_solver.in.pxd new file mode 100644 index 0000000000..233e3f79da --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/acados_solver.in.pxd @@ -0,0 +1,62 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +cimport acados_solver_common + +cdef extern from "acados_solver_{{ model.name }}.h": + ctypedef struct nlp_solver_capsule "{{ model.name }}_solver_capsule": + pass + + nlp_solver_capsule * acados_create_capsule "{{ model.name }}_acados_create_capsule"() + int acados_free_capsule "{{ model.name }}_acados_free_capsule"(nlp_solver_capsule *capsule) + + int acados_create "{{ model.name }}_acados_create"(nlp_solver_capsule * capsule) + + int acados_create_with_discretization "{{ model.name }}_acados_create_with_discretization"(nlp_solver_capsule * capsule, int n_time_steps, double* new_time_steps) + int acados_update_time_steps "{{ model.name }}_acados_update_time_steps"(nlp_solver_capsule * capsule, int N, double* new_time_steps) + int acados_update_qp_solver_cond_N "{{ model.name }}_acados_update_qp_solver_cond_N"(nlp_solver_capsule * capsule, int qp_solver_cond_N) + + int acados_update_params "{{ model.name }}_acados_update_params"(nlp_solver_capsule * capsule, int stage, double *value, int np_) + int acados_update_params_sparse "{{ model.name }}_acados_update_params_sparse"(nlp_solver_capsule * capsule, int stage, int *idx, double *p, int n_update) + int acados_solve "{{ model.name }}_acados_solve"(nlp_solver_capsule * capsule) + int acados_reset "{{ model.name }}_acados_reset"(nlp_solver_capsule * capsule, int reset_qp_solver_mem) + int acados_free "{{ model.name }}_acados_free"(nlp_solver_capsule * capsule) + void acados_print_stats "{{ model.name }}_acados_print_stats"(nlp_solver_capsule * capsule) + + int acados_custom_update "{{ model.name }}_acados_custom_update"(nlp_solver_capsule* capsule, double * data, int data_len) + + acados_solver_common.ocp_nlp_in *acados_get_nlp_in "{{ model.name }}_acados_get_nlp_in"(nlp_solver_capsule * capsule) + acados_solver_common.ocp_nlp_out *acados_get_nlp_out "{{ model.name }}_acados_get_nlp_out"(nlp_solver_capsule * capsule) + acados_solver_common.ocp_nlp_out *acados_get_sens_out "{{ model.name }}_acados_get_sens_out"(nlp_solver_capsule * capsule) + acados_solver_common.ocp_nlp_solver *acados_get_nlp_solver "{{ model.name }}_acados_get_nlp_solver"(nlp_solver_capsule * capsule) + acados_solver_common.ocp_nlp_config *acados_get_nlp_config "{{ model.name }}_acados_get_nlp_config"(nlp_solver_capsule * capsule) + void *acados_get_nlp_opts "{{ model.name }}_acados_get_nlp_opts"(nlp_solver_capsule * capsule) + acados_solver_common.ocp_nlp_dims *acados_get_nlp_dims "{{ model.name }}_acados_get_nlp_dims"(nlp_solver_capsule * capsule) + acados_solver_common.ocp_nlp_plan *acados_get_nlp_plan "{{ model.name }}_acados_get_nlp_plan"(nlp_solver_capsule * capsule) diff --git a/third_party/acados/acados_template/c_templates_tera/constraints.in.h b/third_party/acados/acados_template/c_templates_tera/constraints.in.h new file mode 100644 index 0000000000..d71ce5cc22 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/constraints.in.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#ifndef {{ model.name }}_CONSTRAINTS +#define {{ model.name }}_CONSTRAINTS + +#ifdef __cplusplus +extern "C" { +#endif + +{% if dims.nphi > 0 %} +int {{ model.name }}_phi_constraint(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_phi_constraint_work(int *, int *, int *, int *); +const int *{{ model.name }}_phi_constraint_sparsity_in(int); +const int *{{ model.name }}_phi_constraint_sparsity_out(int); +int {{ model.name }}_phi_constraint_n_in(void); +int {{ model.name }}_phi_constraint_n_out(void); +{% endif %} + +{% if dims.nphi_e > 0 %} +int {{ model.name }}_phi_e_constraint(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_phi_e_constraint_work(int *, int *, int *, int *); +const int *{{ model.name }}_phi_e_constraint_sparsity_in(int); +const int *{{ model.name }}_phi_e_constraint_sparsity_out(int); +int {{ model.name }}_phi_e_constraint_n_in(void); +int {{ model.name }}_phi_e_constraint_n_out(void); +{% endif %} + +{% if dims.nh > 0 %} +int {{ model.name }}_constr_h_fun_jac_uxt_zt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_constr_h_fun_jac_uxt_zt_work(int *, int *, int *, int *); +const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_in(int); +const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_sparsity_out(int); +int {{ model.name }}_constr_h_fun_jac_uxt_zt_n_in(void); +int {{ model.name }}_constr_h_fun_jac_uxt_zt_n_out(void); + +int {{ model.name }}_constr_h_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_constr_h_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_constr_h_fun_sparsity_in(int); +const int *{{ model.name }}_constr_h_fun_sparsity_out(int); +int {{ model.name }}_constr_h_fun_n_in(void); +int {{ model.name }}_constr_h_fun_n_out(void); + +{% if solver_options.hessian_approx == "EXACT" -%} +int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_in(int); +const int *{{ model.name }}_constr_h_fun_jac_uxt_zt_hess_sparsity_out(int); +int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_in(void); +int {{ model.name }}_constr_h_fun_jac_uxt_zt_hess_n_out(void); +{% endif %} +{% endif %} + +{% if dims.nh_e > 0 %} +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_work(int *, int *, int *, int *); +const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_sparsity_in(int); +const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_sparsity_out(int); +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_n_in(void); +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_n_out(void); + +int {{ model.name }}_constr_h_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_constr_h_e_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_constr_h_e_fun_sparsity_in(int); +const int *{{ model.name }}_constr_h_e_fun_sparsity_out(int); +int {{ model.name }}_constr_h_e_fun_n_in(void); +int {{ model.name }}_constr_h_e_fun_n_out(void); + +{% if solver_options.hessian_approx == "EXACT" -%} +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_sparsity_in(int); +const int *{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_sparsity_out(int); +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_n_in(void); +int {{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess_n_out(void); +{% endif %} +{% endif %} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // {{ model.name }}_CONSTRAINTS diff --git a/third_party/acados/acados_template/c_templates_tera/cost.in.h b/third_party/acados/acados_template/c_templates_tera/cost.in.h new file mode 100644 index 0000000000..45eb09c12e --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/cost.in.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef {{ model.name }}_COST +#define {{ model.name }}_COST + +#ifdef __cplusplus +extern "C" { +#endif + + +// Cost at initial shooting node +{% if cost.cost_type_0 == "NONLINEAR_LS" %} +int {{ model.name }}_cost_y_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_0_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_0_fun_sparsity_in(int); +const int *{{ model.name }}_cost_y_0_fun_sparsity_out(int); +int {{ model.name }}_cost_y_0_fun_n_in(void); +int {{ model.name }}_cost_y_0_fun_n_out(void); + +int {{ model.name }}_cost_y_0_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_0_fun_jac_ut_xt_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_in(int); +const int *{{ model.name }}_cost_y_0_fun_jac_ut_xt_sparsity_out(int); +int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_in(void); +int {{ model.name }}_cost_y_0_fun_jac_ut_xt_n_out(void); + +int {{ model.name }}_cost_y_0_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_0_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_0_hess_sparsity_in(int); +const int *{{ model.name }}_cost_y_0_hess_sparsity_out(int); +int {{ model.name }}_cost_y_0_hess_n_in(void); +int {{ model.name }}_cost_y_0_hess_n_out(void); +{% elif cost.cost_type_0 == "CONVEX_OVER_NONLINEAR" %} + +int {{ model.name }}_conl_cost_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_conl_cost_0_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_conl_cost_0_fun_sparsity_in(int); +const int *{{ model.name }}_conl_cost_0_fun_sparsity_out(int); +int {{ model.name }}_conl_cost_0_fun_n_in(void); +int {{ model.name }}_conl_cost_0_fun_n_out(void); + +int {{ model.name }}_conl_cost_0_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_conl_cost_0_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_conl_cost_0_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_conl_cost_0_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_conl_cost_0_fun_jac_hess_n_in(void); +int {{ model.name }}_conl_cost_0_fun_jac_hess_n_out(void); + +{% elif cost.cost_type_0 == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type_0 == "casadi" %} +int {{ model.name }}_cost_ext_cost_0_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_0_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_0_fun_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_0_fun_n_in(void); +int {{ model.name }}_cost_ext_cost_0_fun_n_out(void); + +int {{ model.name }}_cost_ext_cost_0_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_0_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_in(void); +int {{ model.name }}_cost_ext_cost_0_fun_jac_hess_n_out(void); + +int {{ model.name }}_cost_ext_cost_0_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_0_fun_jac_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_0_fun_jac_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_0_fun_jac_n_in(void); +int {{ model.name }}_cost_ext_cost_0_fun_jac_n_out(void); + {%- else %} +int {{ cost.cost_function_ext_cost_0 }}(void **, void **, void *); + {%- endif %} +{% endif %} + + +// Cost at path shooting node +{% if cost.cost_type == "NONLINEAR_LS" %} +int {{ model.name }}_cost_y_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_fun_sparsity_in(int); +const int *{{ model.name }}_cost_y_fun_sparsity_out(int); +int {{ model.name }}_cost_y_fun_n_in(void); +int {{ model.name }}_cost_y_fun_n_out(void); + +int {{ model.name }}_cost_y_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_fun_jac_ut_xt_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_in(int); +const int *{{ model.name }}_cost_y_fun_jac_ut_xt_sparsity_out(int); +int {{ model.name }}_cost_y_fun_jac_ut_xt_n_in(void); +int {{ model.name }}_cost_y_fun_jac_ut_xt_n_out(void); + +int {{ model.name }}_cost_y_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_hess_sparsity_in(int); +const int *{{ model.name }}_cost_y_hess_sparsity_out(int); +int {{ model.name }}_cost_y_hess_n_in(void); +int {{ model.name }}_cost_y_hess_n_out(void); + +{% elif cost.cost_type == "CONVEX_OVER_NONLINEAR" %} +int {{ model.name }}_conl_cost_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_conl_cost_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_conl_cost_fun_sparsity_in(int); +const int *{{ model.name }}_conl_cost_fun_sparsity_out(int); +int {{ model.name }}_conl_cost_fun_n_in(void); +int {{ model.name }}_conl_cost_fun_n_out(void); + +int {{ model.name }}_conl_cost_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_conl_cost_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_conl_cost_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_conl_cost_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_conl_cost_fun_jac_hess_n_in(void); +int {{ model.name }}_conl_cost_fun_jac_hess_n_out(void); +{% elif cost.cost_type == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type == "casadi" %} +int {{ model.name }}_cost_ext_cost_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_fun_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_fun_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_fun_n_in(void); +int {{ model.name }}_cost_ext_cost_fun_n_out(void); + +int {{ model.name }}_cost_ext_cost_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_in(void); +int {{ model.name }}_cost_ext_cost_fun_jac_hess_n_out(void); + +int {{ model.name }}_cost_ext_cost_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_fun_jac_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_fun_jac_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_fun_jac_n_in(void); +int {{ model.name }}_cost_ext_cost_fun_jac_n_out(void); + {%- else %} +int {{ cost.cost_function_ext_cost }}(void **, void **, void *); + {%- endif %} +{% endif %} + +// Cost at terminal shooting node +{% if cost.cost_type_e == "NONLINEAR_LS" %} +int {{ model.name }}_cost_y_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_e_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_e_fun_sparsity_in(int); +const int *{{ model.name }}_cost_y_e_fun_sparsity_out(int); +int {{ model.name }}_cost_y_e_fun_n_in(void); +int {{ model.name }}_cost_y_e_fun_n_out(void); + +int {{ model.name }}_cost_y_e_fun_jac_ut_xt(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_e_fun_jac_ut_xt_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_in(int); +const int *{{ model.name }}_cost_y_e_fun_jac_ut_xt_sparsity_out(int); +int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_in(void); +int {{ model.name }}_cost_y_e_fun_jac_ut_xt_n_out(void); + +int {{ model.name }}_cost_y_e_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_y_e_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_y_e_hess_sparsity_in(int); +const int *{{ model.name }}_cost_y_e_hess_sparsity_out(int); +int {{ model.name }}_cost_y_e_hess_n_in(void); +int {{ model.name }}_cost_y_e_hess_n_out(void); +{% elif cost.cost_type_e == "CONVEX_OVER_NONLINEAR" %} +int {{ model.name }}_conl_cost_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_conl_cost_e_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_conl_cost_e_fun_sparsity_in(int); +const int *{{ model.name }}_conl_cost_e_fun_sparsity_out(int); +int {{ model.name }}_conl_cost_e_fun_n_in(void); +int {{ model.name }}_conl_cost_e_fun_n_out(void); + +int {{ model.name }}_conl_cost_e_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_conl_cost_e_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_conl_cost_e_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_conl_cost_e_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_conl_cost_e_fun_jac_hess_n_in(void); +int {{ model.name }}_conl_cost_e_fun_jac_hess_n_out(void); +{% elif cost.cost_type_e == "EXTERNAL" %} + {%- if cost.cost_ext_fun_type_e == "casadi" %} +int {{ model.name }}_cost_ext_cost_e_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_e_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_e_fun_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_e_fun_n_in(void); +int {{ model.name }}_cost_ext_cost_e_fun_n_out(void); + +int {{ model.name }}_cost_ext_cost_e_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_e_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_in(void); +int {{ model.name }}_cost_ext_cost_e_fun_jac_hess_n_out(void); + +int {{ model.name }}_cost_ext_cost_e_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_cost_ext_cost_e_fun_jac_work(int *, int *, int *, int *); +const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_in(int); +const int *{{ model.name }}_cost_ext_cost_e_fun_jac_sparsity_out(int); +int {{ model.name }}_cost_ext_cost_e_fun_jac_n_in(void); +int {{ model.name }}_cost_ext_cost_e_fun_jac_n_out(void); + {%- else %} +int {{ cost.cost_function_ext_cost_e }}(void **, void **, void *); + {%- endif %} +{% endif %} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // {{ model.name }}_COST diff --git a/third_party/acados/acados_template/c_templates_tera/main.in.c b/third_party/acados/acados_template/c_templates_tera/main.in.c new file mode 100644 index 0000000000..92a8b33eac --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/main.in.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +{%- if not solver_options.custom_update_filename %} + {%- set custom_update_filename = "" %} +{% else %} + {%- set custom_update_filename = solver_options.custom_update_filename %} +{%- endif %} + +// standard +#include +#include +// acados +#include "acados/utils/print.h" +#include "acados/utils/math.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados_c/external_function_interface.h" +#include "acados_solver_{{ model.name }}.h" + +// blasfeo +#include "blasfeo/include/blasfeo_d_aux_ext_dep.h" + +#define NX {{ model.name | upper }}_NX +#define NZ {{ model.name | upper }}_NZ +#define NU {{ model.name | upper }}_NU +#define NP {{ model.name | upper }}_NP +#define NBX {{ model.name | upper }}_NBX +#define NBX0 {{ model.name | upper }}_NBX0 +#define NBU {{ model.name | upper }}_NBU +#define NSBX {{ model.name | upper }}_NSBX +#define NSBU {{ model.name | upper }}_NSBU +#define NSH {{ model.name | upper }}_NSH +#define NSG {{ model.name | upper }}_NSG +#define NSPHI {{ model.name | upper }}_NSPHI +#define NSHN {{ model.name | upper }}_NSHN +#define NSGN {{ model.name | upper }}_NSGN +#define NSPHIN {{ model.name | upper }}_NSPHIN +#define NSBXN {{ model.name | upper }}_NSBXN +#define NS {{ model.name | upper }}_NS +#define NSN {{ model.name | upper }}_NSN +#define NG {{ model.name | upper }}_NG +#define NBXN {{ model.name | upper }}_NBXN +#define NGN {{ model.name | upper }}_NGN +#define NY0 {{ model.name | upper }}_NY0 +#define NY {{ model.name | upper }}_NY +#define NYN {{ model.name | upper }}_NYN +#define NH {{ model.name | upper }}_NH +#define NPHI {{ model.name | upper }}_NPHI +#define NHN {{ model.name | upper }}_NHN +#define NPHIN {{ model.name | upper }}_NPHIN +#define NR {{ model.name | upper }}_NR + + +int main() +{ + + {{ model.name }}_solver_capsule *acados_ocp_capsule = {{ model.name }}_acados_create_capsule(); + // there is an opportunity to change the number of shooting intervals in C without new code generation + int N = {{ model.name | upper }}_N; + // allocate the array and fill it accordingly + double* new_time_steps = NULL; + int status = {{ model.name }}_acados_create_with_discretization(acados_ocp_capsule, N, new_time_steps); + + if (status) + { + printf("{{ model.name }}_acados_create() returned status %d. Exiting.\n", status); + exit(1); + } + + ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(acados_ocp_capsule); + ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(acados_ocp_capsule); + ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(acados_ocp_capsule); + ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(acados_ocp_capsule); + ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(acados_ocp_capsule); + void *nlp_opts = {{ model.name }}_acados_get_nlp_opts(acados_ocp_capsule); + + // initial condition + int idxbx0[NBX0]; + {%- for i in range(end=dims.nbx_0) %} + idxbx0[{{ i }}] = {{ constraints.idxbx_0[i] }}; + {%- endfor %} + + double lbx0[NBX0]; + double ubx0[NBX0]; + {%- for i in range(end=dims.nbx_0) %} + lbx0[{{ i }}] = {{ constraints.lbx_0[i] }}; + ubx0[{{ i }}] = {{ constraints.ubx_0[i] }}; + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "idxbx", idxbx0); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbx", lbx0); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubx", ubx0); + + // initialization for state values + double x_init[NX]; + {%- for i in range(end=dims.nx) %} + x_init[{{ i }}] = 0.0; + {%- endfor %} + + // initial value for control input + double u0[NU]; + {%- for i in range(end=dims.nu) %} + u0[{{ i }}] = 0.0; + {%- endfor %} + + + {%- if dims.np > 0 %} + // set parameters + double p[NP]; + {%- for item in parameter_values %} + p[{{ loop.index0 }}] = {{ item }}; + {%- endfor %} + + for (int ii = 0; ii <= N; ii++) + { + {{ model.name }}_acados_update_params(acados_ocp_capsule, ii, p, NP); + } + {% endif %}{# if np > 0 #} + + // prepare evaluation + int NTIMINGS = 1; + double min_time = 1e12; + double kkt_norm_inf; + double elapsed_time; + int sqp_iter; + + double xtraj[NX * (N+1)]; + double utraj[NU * N]; + + + // solve ocp in loop + int rti_phase = 0; + + for (int ii = 0; ii < NTIMINGS; ii++) + { + // initialize solution + for (int i = 0; i < N; i++) + { + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "x", x_init); + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "u", u0); + } + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, N, "x", x_init); + ocp_nlp_solver_opts_set(nlp_config, nlp_opts, "rti_phase", &rti_phase); + status = {{ model.name }}_acados_solve(acados_ocp_capsule); + ocp_nlp_get(nlp_config, nlp_solver, "time_tot", &elapsed_time); + min_time = MIN(elapsed_time, min_time); + } + + /* print solution and statistics */ + for (int ii = 0; ii <= nlp_dims->N; ii++) + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "x", &xtraj[ii*NX]); + for (int ii = 0; ii < nlp_dims->N; ii++) + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "u", &utraj[ii*NU]); + + printf("\n--- xtraj ---\n"); + d_print_exp_tran_mat( NX, N+1, xtraj, NX); + printf("\n--- utraj ---\n"); + d_print_exp_tran_mat( NU, N, utraj, NU ); + // ocp_nlp_out_print(nlp_solver->dims, nlp_out); + + printf("\nsolved ocp %d times, solution printed above\n\n", NTIMINGS); + + if (status == ACADOS_SUCCESS) + { + printf("{{ model.name }}_acados_solve(): SUCCESS!\n"); + } + else + { + printf("{{ model.name }}_acados_solve() failed with status %d.\n", status); + } + + +{%- if custom_update_filename != "" %} + {{ model.name }}_acados_custom_update(acados_ocp_capsule, xtraj, NX*(N+1)); +{%- endif %} + + // get solution + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 0, "kkt_norm_inf", &kkt_norm_inf); + ocp_nlp_get(nlp_config, nlp_solver, "sqp_iter", &sqp_iter); + + {{ model.name }}_acados_print_stats(acados_ocp_capsule); + + printf("\nSolver info:\n"); + printf(" SQP iterations %2d\n minimum time for %d solve %f [ms]\n KKT %e\n", + sqp_iter, NTIMINGS, min_time*1000, kkt_norm_inf); + + // free solver + status = {{ model.name }}_acados_free(acados_ocp_capsule); + if (status) { + printf("{{ model.name }}_acados_free() returned status %d. \n", status); + } + // free solver capsule + status = {{ model.name }}_acados_free_capsule(acados_ocp_capsule); + if (status) { + printf("{{ model.name }}_acados_free_capsule() returned status %d. \n", status); + } + + return status; +} diff --git a/third_party/acados/acados_template/c_templates_tera/main_sim.in.c b/third_party/acados/acados_template/c_templates_tera/main_sim.in.c new file mode 100644 index 0000000000..8960aa0035 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/main_sim.in.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +// standard +#include +#include +// acados +#include "acados/utils/print.h" +#include "acados/utils/math.h" +#include "acados_c/sim_interface.h" +#include "acados_sim_solver_{{ model.name }}.h" + +#define NX {{ model.name | upper }}_NX +#define NZ {{ model.name | upper }}_NZ +#define NU {{ model.name | upper }}_NU +#define NP {{ model.name | upper }}_NP + + +int main() +{ + int status = 0; + sim_solver_capsule *capsule = {{ model.name }}_acados_sim_solver_create_capsule(); + status = {{ model.name }}_acados_sim_create(capsule); + + if (status) + { + printf("acados_create() returned status %d. Exiting.\n", status); + exit(1); + } + + sim_config *acados_sim_config = {{ model.name }}_acados_get_sim_config(capsule); + sim_in *acados_sim_in = {{ model.name }}_acados_get_sim_in(capsule); + sim_out *acados_sim_out = {{ model.name }}_acados_get_sim_out(capsule); + void *acados_sim_dims = {{ model.name }}_acados_get_sim_dims(capsule); + + // initial condition + double x_current[NX]; + {%- for i in range(end=dims.nx) %} + x_current[{{ i }}] = 0.0; + {%- endfor %} + + {% if constraints.lbx_0 %} + {%- for i in range(end=dims.nbx_0) %} + x_current[{{ constraints.idxbx_0[i] }}] = {{ constraints.lbx_0[i] }}; + {%- endfor %} + {% if dims.nbx_0 != dims.nx %} + printf("main_sim: NOTE: initial state not fully defined via lbx_0, using 0.0 for indices that are not in idxbx_0."); + {%- endif %} + {% else %} + printf("main_sim: initial state not defined, should be in lbx_0, using zero vector."); + {%- endif %} + + + // initial value for control input + double u0[NU]; + {%- for i in range(end=dims.nu) %} + u0[{{ i }}] = 0.0; + {%- endfor %} + + {%- if dims.np > 0 %} + // set parameters + double p[NP]; + {%- for item in parameter_values %} + p[{{ loop.index0 }}] = {{ item }}; + {%- endfor %} + + {{ model.name }}_acados_sim_update_params(capsule, p, NP); + {% endif %}{# if np > 0 #} + + int n_sim_steps = 3; + // solve ocp in loop + for (int ii = 0; ii < n_sim_steps; ii++) + { + sim_in_set(acados_sim_config, acados_sim_dims, + acados_sim_in, "x", x_current); + status = {{ model.name }}_acados_sim_solve(capsule); + + if (status != ACADOS_SUCCESS) + { + printf("acados_solve() failed with status %d.\n", status); + } + + sim_out_get(acados_sim_config, acados_sim_dims, + acados_sim_out, "x", x_current); + + printf("\nx_current, %d\n", ii); + for (int jj = 0; jj < NX; jj++) + { + printf("%e\n", x_current[jj]); + } + } + + printf("\nPerformed %d simulation steps with acados integrator successfully.\n\n", n_sim_steps); + + // free solver + status = {{ model.name }}_acados_sim_free(capsule); + if (status) { + printf("{{ model.name }}_acados_sim_free() returned status %d. \n", status); + } + + {{ model.name }}_acados_sim_solver_free_capsule(capsule); + + return status; +} diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_create.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_create.in.c new file mode 100644 index 0000000000..24ae94ac2c --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_create.in.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +// standard +#include +#include +#include + +// acados +#include "acados/utils/print.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados_solver_{{ model.name }}.h" + +// mex +#include "mex.h" + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + long long *l_ptr; + int status = 0; + + // create solver + {{ model.name }}_solver_capsule *acados_ocp_capsule = {{ model.name }}_acados_create_capsule(); + + status = {{ model.name }}_acados_create(acados_ocp_capsule); + + if (status) + { + mexPrintf("{{ model.name }}_acados_create() returned status %d.\n", status); + } + mexPrintf("{{ model.name }}_acados_create() -> success!\n"); + + // get pointers to nlp solver related objects + ocp_nlp_plan_t *nlp_plan = {{ model.name }}_acados_get_nlp_plan(acados_ocp_capsule); + ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(acados_ocp_capsule); + ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(acados_ocp_capsule); + ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(acados_ocp_capsule); + ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(acados_ocp_capsule); + ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(acados_ocp_capsule); + void *nlp_opts = {{ model.name }}_acados_get_nlp_opts(acados_ocp_capsule); + + // mexPrintf("acados: got pointer to objectes!\n"); + + // field names of output struct + #define FIELDS_OCP 9 + #define FIELDS_EXT_FUN 25 + #define MAX_FIELDS 25 + char *fieldnames[MAX_FIELDS]; + + for (int i = 0; i < MAX_FIELDS; i++) + { + fieldnames[i] = (char*) mxMalloc(50); + } + + memcpy(fieldnames[0],"config",sizeof("config")); + memcpy(fieldnames[1],"dims",sizeof("dims")); + memcpy(fieldnames[2],"opts",sizeof("opts")); + memcpy(fieldnames[3],"in",sizeof("in")); + memcpy(fieldnames[4],"out",sizeof("out")); + memcpy(fieldnames[5],"solver",sizeof("solver")); + memcpy(fieldnames[6],"sens_out",sizeof("sens_out")); + memcpy(fieldnames[7],"plan",sizeof("plan")); + memcpy(fieldnames[8],"capsule",sizeof("capsule")); + + // create output struct - C_ocp + plhs[0] = mxCreateStructMatrix(1, 1, 9, (const char **) fieldnames); + + // MEX: config, dims, opts, in, out, solver, sens_out, plan + // plan + mxArray *plan_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(plan_mat); + l_ptr[0] = (long long) nlp_plan; + mxSetField(plhs[0], 0, "plan", plan_mat); + + // config + mxArray *config_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(config_mat); + l_ptr[0] = (long long) nlp_config; + mxSetField(plhs[0], 0, "config", config_mat); + + // dims + mxArray *dims_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(dims_mat); + l_ptr[0] = (long long) nlp_dims; + mxSetField(plhs[0], 0, "dims", dims_mat); + + // opts + mxArray *opts_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(opts_mat); + l_ptr[0] = (long long) nlp_opts; + mxSetField(plhs[0], 0, "opts", opts_mat); + + // in + mxArray *in_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(in_mat); + l_ptr[0] = (long long) nlp_in; + mxSetField(plhs[0], 0, "in", in_mat); + + // out + mxArray *out_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(out_mat); + l_ptr[0] = (long long) nlp_out; + mxSetField(plhs[0], 0, "out", out_mat); + + // solver + mxArray *solver_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(solver_mat); + l_ptr[0] = (long long) nlp_solver; + mxSetField(plhs[0], 0, "solver", solver_mat); + + // TODO: sens_out not actually implemented in templates.. + // sens_out + mxArray *sens_out_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(sens_out_mat); + l_ptr[0] = (long long) 1; + mxSetField(plhs[0], 0, "sens_out", sens_out_mat); + + // capsule + mxArray *capsule_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(capsule_mat); + l_ptr[0] = (long long) acados_ocp_capsule; + mxSetField(plhs[0], 0, "capsule", capsule_mat); + + /* store external function pointers */ + // dyn + memcpy(fieldnames[0],"expl_ode_fun",sizeof("expl_ode_fun")); + memcpy(fieldnames[1],"forw_vde",sizeof("forw_vde")); + memcpy(fieldnames[2],"hess_vde",sizeof("hess_vde")); + memcpy(fieldnames[3],"impl_dae_fun",sizeof("impl_dae_fun")); + memcpy(fieldnames[4],"impl_dae_fun_jac_x_xdot_z",sizeof("impl_dae_fun_jac_x_xdot_z")); + memcpy(fieldnames[5],"impl_dae_jac_x_xdot_u_z",sizeof("impl_dae_jac_x_xdot_u_z")); + memcpy(fieldnames[6],"impl_dae_hess",sizeof("impl_dae_hess")); + + memcpy(fieldnames[7],"gnsf_phi_fun",sizeof("gnsf_phi_fun")); + memcpy(fieldnames[8],"gnsf_phi_fun_jac_y",sizeof("gnsf_phi_fun_jac_y")); + memcpy(fieldnames[9],"gnsf_phi_jac_y_uhat",sizeof("gnsf_phi_jac_y_uhat")); + memcpy(fieldnames[10],"gnsf_f_lo_jac_x1_x1dot_u_z",sizeof("gnsf_f_lo_jac_x1_x1dot_u_z")); + memcpy(fieldnames[11],"gnsf_get_matrices_fun",sizeof("gnsf_get_matrices_fun")); + + memcpy(fieldnames[12],"disc_phi_fun",sizeof("disc_phi_fun")); + memcpy(fieldnames[13],"disc_phi_fun_jac",sizeof("disc_phi_fun_jac")); + memcpy(fieldnames[14],"disc_phi_fun_jac_hess",sizeof("disc_phi_fun_jac_hess")); + + // cost + memcpy(fieldnames[15],"cost_y_fun",sizeof("cost_y_fun")); + memcpy(fieldnames[16],"cost_y_fun_jac_ut_xt",sizeof("cost_y_fun_jac_ut_xt")); + memcpy(fieldnames[17],"cost_y_hess",sizeof("cost_y_hess")); + memcpy(fieldnames[18],"ext_cost_fun",sizeof("ext_cost_fun")); + memcpy(fieldnames[19],"ext_cost_fun_jac",sizeof("ext_cost_fun_jac")); + memcpy(fieldnames[20],"ext_cost_fun_jac_hess",sizeof("ext_cost_fun_jac_hess")); + + // constraints + memcpy(fieldnames[21],"phi_constraint",sizeof("phi_constraint")); + memcpy(fieldnames[22],"nl_constr_h_fun_jac",sizeof("nl_constr_h_fun_jac")); + memcpy(fieldnames[23],"nl_constr_h_fun",sizeof("nl_constr_h_fun")); + memcpy(fieldnames[24],"nl_constr_h_fun_jac_hess",sizeof("nl_constr_h_fun_jac_hess")); + + + // create output struct - C_ocp_ext_fun + plhs[1] = mxCreateStructMatrix(1, 1, FIELDS_EXT_FUN, (const char **) fieldnames); + + + for (int i = 0; i < FIELDS_EXT_FUN; i++) + { + mxFree( fieldnames[i] ); + } + +/* dynamics */ + mxArray *expl_ode_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *forw_vde_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *hess_vde_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *impl_dae_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *impl_dae_fun_jac_x_xdot_z_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *impl_dae_jac_x_xdot_u_z_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *impl_dae_hess_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + + mxArray *gnsf_phi_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *gnsf_phi_fun_jac_y_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *gnsf_phi_jac_y_uhat_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *gnsf_f_lo_jac_x1_x1dot_u_z_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *gnsf_get_matrices_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + + mxArray *disc_phi_fun_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *disc_phi_fun_jac_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + mxArray *disc_phi_fun_jac_hess_mat = mxCreateNumericMatrix(1, 1, mxINT64_CLASS, mxREAL); + +{% if solver_options.integrator_type == "ERK" %} + {# TODO: remove _casadi from these names.. #} + l_ptr = mxGetData(forw_vde_mat); + l_ptr[0] = (long long) acados_ocp_capsule->forw_vde_casadi; + l_ptr = mxGetData(expl_ode_fun_mat); + l_ptr[0] = (long long) acados_ocp_capsule->expl_ode_fun; +{% if solver_options.hessian_approx == "EXACT" %} + l_ptr = mxGetData(hess_vde_mat); + l_ptr[0] = (long long) acados_ocp_capsule->hess_vde_casadi; +{%- endif %} +{% elif solver_options.integrator_type == "IRK" %} + l_ptr = mxGetData(impl_dae_fun_mat); + l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_fun; + l_ptr = mxGetData(impl_dae_fun_jac_x_xdot_z_mat); + l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_fun_jac_x_xdot_z; + l_ptr = mxGetData(impl_dae_jac_x_xdot_u_z_mat); + l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_jac_x_xdot_u_z; +{% if solver_options.hessian_approx == "EXACT" %} + l_ptr = mxGetData(impl_dae_hess_mat); + l_ptr[0] = (long long) acados_ocp_capsule->impl_dae_hess; +{%- endif %} +{% elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + l_ptr = mxGetData(gnsf_phi_fun_mat); + l_ptr[0] = (long long) acados_ocp_capsule->gnsf_phi_fun; + l_ptr = mxGetData(gnsf_phi_fun_jac_y_mat); + l_ptr[0] = (long long) acados_ocp_capsule->gnsf_phi_fun_jac_y; + l_ptr = mxGetData(gnsf_phi_jac_y_uhat_mat); + l_ptr[0] = (long long) acados_ocp_capsule->gnsf_phi_jac_y_uhat; + {% if model.gnsf.nontrivial_f_LO == 1 %} + l_ptr = mxGetData(gnsf_f_lo_jac_x1_x1dot_u_z_mat); + l_ptr[0] = (long long) acados_ocp_capsule->gnsf_f_lo_jac_x1_x1dot_u_z; + {%- endif %} + {%- endif %} + l_ptr = mxGetData(gnsf_get_matrices_fun_mat); + l_ptr[0] = (long long) acados_ocp_capsule->gnsf_get_matrices_fun; +{% elif solver_options.integrator_type == "DISCRETE" %} + l_ptr = mxGetData(disc_phi_fun_mat); + l_ptr[0] = (long long) acados_ocp_capsule->discr_dyn_phi_fun; + l_ptr = mxGetData(disc_phi_fun_jac_mat); + l_ptr[0] = (long long) acados_ocp_capsule->discr_dyn_phi_fun_jac_ut_xt; +{% if solver_options.hessian_approx == "EXACT" %} + l_ptr = mxGetData(disc_phi_fun_jac_hess_mat); + l_ptr[0] = (long long) acados_ocp_capsule->discr_dyn_phi_fun_jac_ut_xt_hess; +{%- endif %} +{%- endif %} + mxSetField(plhs[1], 0, "expl_ode_fun", expl_ode_fun_mat); + mxSetField(plhs[1], 0, "forw_vde", forw_vde_mat); + mxSetField(plhs[1], 0, "hess_vde", hess_vde_mat); + + mxSetField(plhs[1], 0, "gnsf_phi_fun", gnsf_phi_fun_mat); + mxSetField(plhs[1], 0, "gnsf_phi_fun_jac_y", gnsf_phi_fun_jac_y_mat); + mxSetField(plhs[1], 0, "gnsf_phi_jac_y_uhat", gnsf_phi_jac_y_uhat_mat); + mxSetField(plhs[1], 0, "gnsf_f_lo_jac_x1_x1dot_u_z", gnsf_f_lo_jac_x1_x1dot_u_z_mat); + mxSetField(plhs[1], 0, "gnsf_get_matrices_fun", gnsf_get_matrices_fun_mat); + + mxSetField(plhs[1], 0, "impl_dae_fun", impl_dae_fun_mat); + mxSetField(plhs[1], 0, "impl_dae_fun_jac_x_xdot_z", impl_dae_fun_jac_x_xdot_z_mat); + mxSetField(plhs[1], 0, "impl_dae_jac_x_xdot_u_z", impl_dae_jac_x_xdot_u_z_mat); + mxSetField(plhs[1], 0, "impl_dae_hess", impl_dae_hess_mat); + + mxSetField(plhs[1], 0, "disc_phi_fun", disc_phi_fun_mat); + mxSetField(plhs[1], 0, "disc_phi_fun_jac", disc_phi_fun_jac_mat); + mxSetField(plhs[1], 0, "disc_phi_fun_jac_hess", disc_phi_fun_jac_hess_mat); +/* constaints */ + mxArray *phi_constraint_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(phi_constraint_mat); +{%- if constraints.constr_type == "BGP" %} + l_ptr[0] = (long long) acados_ocp_capsule->phi_constraint; +{% endif %} +{% if constraints.constr_type_e == "BGP" %} + l_ptr[1] = (long long) &acados_ocp_capsule->phi_e_constraint; +{% endif %} + mxSetField(plhs[1], 0, "phi_constraint", phi_constraint_mat); + + mxArray *nl_constr_h_fun_jac_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(nl_constr_h_fun_jac_mat); +{% if constraints.constr_type == "BGH" and dims.nh > 0 %} + l_ptr[0] = (long long) acados_ocp_capsule->nl_constr_h_fun_jac; +{% endif %} +{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + l_ptr[1] = (long long) &acados_ocp_capsule->nl_constr_h_e_fun_jac; +{%- endif %} + mxSetField(plhs[1], 0, "nl_constr_h_fun_jac", nl_constr_h_fun_jac_mat); + + mxArray *nl_constr_h_fun_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(nl_constr_h_fun_mat); +{% if constraints.constr_type == "BGH" and dims.nh > 0 %} + l_ptr[0] = (long long) acados_ocp_capsule->nl_constr_h_fun; +{% endif %} +{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + l_ptr[1] = (long long) &acados_ocp_capsule->nl_constr_h_e_fun; +{%- endif %} + mxSetField(plhs[1], 0, "nl_constr_h_fun", nl_constr_h_fun_mat); + + mxArray *nl_constr_h_fun_jac_hess_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(nl_constr_h_fun_jac_hess_mat); +{% if constraints.constr_type == "BGH" and dims.nh > 0 and solver_options.hessian_approx == "EXACT" %} + l_ptr[0] = (long long) acados_ocp_capsule->nl_constr_h_fun_jac_hess; +{% endif %} +{% if constraints.constr_type_e == "BGH" and dims.nh_e > 0 and solver_options.hessian_approx == "EXACT" %} + l_ptr[1] = (long long) &acados_ocp_capsule->nl_constr_h_e_fun_jac_hess; +{%- endif %} + mxSetField(plhs[1], 0, "nl_constr_h_fun_jac_hess", nl_constr_h_fun_jac_hess_mat); + +/* cost */ + mxArray *cost_y_fun_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(cost_y_fun_mat); +{% if cost.cost_type == "NONLINEAR_LS" %} + l_ptr[0] = (long long) acados_ocp_capsule->cost_y_fun; +{% endif %} +{% if cost.cost_type_e == "NONLINEAR_LS" %} + l_ptr[1] = (long long) &acados_ocp_capsule->cost_y_e_fun; +{%- endif %} + mxSetField(plhs[1], 0, "cost_y_fun", cost_y_fun_mat); + + mxArray *cost_y_fun_jac_ut_xt_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(cost_y_fun_jac_ut_xt_mat); +{% if cost.cost_type == "NONLINEAR_LS" %} + l_ptr[0] = (long long) acados_ocp_capsule->cost_y_fun_jac_ut_xt; +{% endif %} +{% if cost.cost_type_e == "NONLINEAR_LS" %} + l_ptr[1] = (long long) &acados_ocp_capsule->cost_y_e_fun_jac_ut_xt; +{%- endif %} + mxSetField(plhs[1], 0, "cost_y_fun_jac_ut_xt", cost_y_fun_jac_ut_xt_mat); + + mxArray *cost_y_hess_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(cost_y_hess_mat); +{% if cost.cost_type == "NONLINEAR_LS" %} + l_ptr[0] = (long long) acados_ocp_capsule->cost_y_hess; +{% endif %} +{% if cost.cost_type_e == "NONLINEAR_LS" %} + l_ptr[1] = (long long) &acados_ocp_capsule->cost_y_e_hess; +{%- endif %} + mxSetField(plhs[1], 0, "cost_y_hess", cost_y_hess_mat); + + mxArray *ext_cost_fun_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(ext_cost_fun_mat); +{% if cost.cost_type == "EXTERNAL" %} + l_ptr[0] = (long long) acados_ocp_capsule->ext_cost_fun; +{% endif -%} +{% if cost.cost_type_e == "EXTERNAL" %} + l_ptr[1] = (long long) &acados_ocp_capsule->ext_cost_e_fun; +{%- endif %} + mxSetField(plhs[1], 0, "ext_cost_fun", ext_cost_fun_mat); + + mxArray *ext_cost_fun_jac_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(ext_cost_fun_jac_mat); +{% if cost.cost_type == "EXTERNAL" %} + l_ptr[0] = (long long) acados_ocp_capsule->ext_cost_fun_jac; +{% endif -%} +{% if cost.cost_type_e == "EXTERNAL" %} + l_ptr[1] = (long long) &acados_ocp_capsule->ext_cost_e_fun_jac; +{%- endif %} + mxSetField(plhs[1], 0, "ext_cost_fun_jac", ext_cost_fun_jac_mat); + + mxArray *ext_cost_fun_jac_hess_mat = mxCreateNumericMatrix(1, 2, mxINT64_CLASS, mxREAL); + l_ptr = mxGetData(ext_cost_fun_jac_hess_mat); +{% if cost.cost_type == "EXTERNAL" %} + l_ptr[0] = (long long) acados_ocp_capsule->ext_cost_fun_jac_hess; +{% endif -%} +{% if cost.cost_type_e == "EXTERNAL" %} + l_ptr[1] = (long long) &acados_ocp_capsule->ext_cost_e_fun_jac_hess; +{%- endif %} + mxSetField(plhs[1], 0, "ext_cost_fun_jac_hess", ext_cost_fun_jac_hess_mat); + + + return; +} diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_free.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_free.in.c new file mode 100644 index 0000000000..bd457969b2 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_free.in.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +// system +#include +#include +#include +// acados +#include "acados_solver_{{ model.name }}.h" + +// mex +#include "mex.h" + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + int status = 0; + long long *ptr; + + // mexPrintf("\nin mex_acados_free\n"); + const mxArray *C_ocp = prhs[0]; + // capsule + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "capsule" ) ); + {{ model.name }}_solver_capsule *capsule = ({{ model.name }}_solver_capsule *) ptr[0]; + + status = {{ model.name }}_acados_free(capsule); + if (status) + { + mexPrintf("{{ model.name }}_acados_free() returned status %d.\n", status); + } + + status = {{ model.name }}_acados_free_capsule(capsule); + if (status) + { + mexPrintf("{{ model.name }}_acados_free_capsule() returned status %d.\n", status); + } + + return; +} + diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_set.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_set.in.c new file mode 100644 index 0000000000..78a308df49 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_set.in.c @@ -0,0 +1,632 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +// standard +#include +#include +#include + +// acados +#include "acados/utils/print.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados_solver_{{ model.name }}.h" + +// mex +#include "mex.h" +#include "mex_macros.h" + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + + long long *ptr; + int acados_size; + mxArray *mex_field; + char fun_name[20] = "ocp_set"; + char buffer [500]; // for error messages + + /* RHS */ + int min_nrhs = 6; + + // C ocp + const mxArray *C_ocp = prhs[2]; + // capsule + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "capsule" ) ); + {{ model.name }}_solver_capsule *capsule = ({{ model.name }}_solver_capsule *) ptr[0]; + // plan + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "plan" ) ); + ocp_nlp_plan_t *plan = (ocp_nlp_plan_t *) ptr[0]; + // config + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "config" ) ); + ocp_nlp_config *config = (ocp_nlp_config *) ptr[0]; + // dims + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "dims" ) ); + ocp_nlp_dims *dims = (ocp_nlp_dims *) ptr[0]; + // opts + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "opts" ) ); + void *opts = (void *) ptr[0]; + // in + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "in" ) ); + ocp_nlp_in *in = (ocp_nlp_in *) ptr[0]; + // out + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "out" ) ); + ocp_nlp_out *out = (ocp_nlp_out *) ptr[0]; + // solver + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "solver" ) ); + ocp_nlp_solver *solver = (ocp_nlp_solver *) ptr[0]; + + const mxArray *C_ext_fun_pointers = prhs[3]; + // field + char *field = mxArrayToString( prhs[4] ); + // value + double *value = mxGetPr( prhs[5] ); + + // for checks + int matlab_size = (int) mxGetNumberOfElements( prhs[5] ); + int nrow = (int) mxGetM( prhs[5] ); + int ncol = (int) mxGetN( prhs[5] ); + + int N = dims->N; + int nu = dims->nu[0]; + int nx = dims->nx[0]; + + // stage + int s0, se; + if (nrhs==min_nrhs) + { + s0 = 0; + se = N; + } + else if (nrhs==min_nrhs+1) + { + s0 = mxGetScalar( prhs[6] ); + if (s0 > N) + { + sprintf(buffer, "ocp_set: N < specified stage = %d\n", s0); + mexErrMsgTxt(buffer); + } + se = s0 + 1; + } + else + { + sprintf(buffer, "ocp_set: wrong nrhs: %d\n", nrhs); + mexErrMsgTxt(buffer); + } + + /* Set value */ + // constraints + if (!strcmp(field, "constr_x0")) + { + acados_size = nx; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + ocp_nlp_constraints_model_set(config, dims, in, 0, "lbx", value); + ocp_nlp_constraints_model_set(config, dims, in, 0, "ubx", value); + } + else if (!strcmp(field, "constr_C")) + { + for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS)) + { + acados_size = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "y_ref"); + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + ocp_nlp_cost_model_set(config, dims, in, ii, "y_ref", value); + } + else + { + MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii); + } + } + } + else if (!strcmp(field, "cost_y_ref_e")) + { + acados_size = ocp_nlp_dims_get_from_attr(config, dims, out, N, "y_ref"); + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + ocp_nlp_cost_model_set(config, dims, in, N, "y_ref", value); + } + else if (!strcmp(field, "cost_Vu")) + { + for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS)) + { + int ny = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "y_ref"); + int nu = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "u"); + acados_size = ny * nu; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + ocp_nlp_cost_model_set(config, dims, in, ii, "Vu", value); + } + else + { + MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii); + } + } + } + else if (!strcmp(field, "cost_Vx")) + { + for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS)) + { + int ny = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "y_ref"); + int nx = ocp_nlp_dims_get_from_attr(config, dims, out, ii, "x"); + acados_size = ny * nx; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + ocp_nlp_cost_model_set(config, dims, in, ii, "Vx", value); + } + else + { + MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii); + } + } + } + else if (!strcmp(field, "cost_W")) + { + for (int ii=s0; iinlp_cost[ii] == LINEAR_LS) || (plan->nlp_cost[ii] == NONLINEAR_LS)) + { + int ny = ocp_nlp_dims_get_from_attr(config, dims, out, s0, "y_ref"); + acados_size = ny * ny; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + ocp_nlp_cost_model_set(config, dims, in, ii, "W", value); + } + else + { + MEX_FIELD_NOT_SUPPORTED_FOR_COST_STAGE(fun_name, field, plan->nlp_cost[ii], ii); + } + } + } + else if (!strcmp(field, "cost_Z")) + { + acados_size = ocp_nlp_dims_get_from_attr(config, dims, out, s0, "cost_Z"); + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + for (int ii=s0; iisim_solver_plan[0]; + sim_solver_t type = sim_plan.sim_solver; + if (type == IRK) + { + int nz = ocp_nlp_dims_get_from_attr(config, dims, out, 0, "z"); + if (nrhs==min_nrhs) + { + acados_size = N*nz; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + for (int ii=0; iisim_solver_plan[0]; + sim_solver_t type = sim_plan.sim_solver; + if (type == IRK) + { + int nx = ocp_nlp_dims_get_from_attr(config, dims, out, 0, "x"); + if (nrhs==min_nrhs) + { + acados_size = N*nx; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + for (int ii=0; iisim_solver_plan[0]; + sim_solver_t type = sim_plan.sim_solver; + if (type == GNSF) + { + int nout = ocp_nlp_dims_get_from_attr(config, dims, out, 0, "init_gnsf_phi"); + + if (nrhs==min_nrhs) + { + acados_size = N*nout; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + for (int ii=0; iinlp_solver == SQP && rti_phase != 0) + { + MEX_FIELD_ONLY_SUPPORTED_FOR_SOLVER(fun_name, field, "sqp_rti") + } + ocp_nlp_solver_opts_set(config, opts, "rti_phase", &rti_phase); + } + else if (!strcmp(field, "qp_warm_start")) + { + acados_size = 1; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + int qp_warm_start = (int) value[0]; + ocp_nlp_solver_opts_set(config, opts, "qp_warm_start", &qp_warm_start); + } + else if (!strcmp(field, "warm_start_first_qp")) + { + acados_size = 1; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + int warm_start_first_qp = (int) value[0]; + ocp_nlp_solver_opts_set(config, opts, "warm_start_first_qp", &warm_start_first_qp); + } + else if (!strcmp(field, "print_level")) + { + acados_size = 1; + MEX_DIM_CHECK_VEC(fun_name, field, matlab_size, acados_size); + int print_level = (int) value[0]; + ocp_nlp_solver_opts_set(config, opts, "print_level", &print_level); + } + else + { + MEX_FIELD_NOT_SUPPORTED_SUGGEST(fun_name, field, "p, constr_x0,\ + constr_lbx, constr_ubx, constr_C, constr_D, constr_lg, constr_ug, constr_lh, constr_uh,\ + constr_lbu, constr_ubu, cost_y_ref[_e], sl, su, x, xdot, u, pi, lam, z, \ + cost_Vu, cost_Vx, cost_Vz, cost_W, cost_Z, cost_Zl, cost_Zu, cost_z,\ + cost_zl, cost_zu, init_x, init_u, init_z, init_xdot, init_gnsf_phi,\ + init_pi, nlp_solver_max_iter, qp_warm_start, warm_start_first_qp, print_level"); + } + + return; +} + diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_solve.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_solve.in.c new file mode 100644 index 0000000000..300a440cc9 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_mex_solve.in.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +// system +#include +#include +#include +// acados +#include "acados_solver_{{ model.name }}.h" + +// mex +#include "mex.h" + + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + // C_ocp + long long *ptr; + const mxArray *C_ocp = prhs[0]; + + // capsule + ptr = (long long *) mxGetData( mxGetField( C_ocp, 0, "capsule" ) ); + {{ model.name }}_solver_capsule *capsule = ({{ model.name }}_solver_capsule *) ptr[0]; + + // solve + {{ model.name }}_acados_solve(capsule); + +} diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_sim_solver_sfun.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_sim_solver_sfun.in.c new file mode 100644 index 0000000000..bd73ff69a4 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_sim_solver_sfun.in.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#define S_FUNCTION_NAME acados_sim_solver_sfunction_{{ model.name }} +#define S_FUNCTION_LEVEL 2 + +#define MDL_START + +// acados +// #include "acados/utils/print.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados_c/external_function_interface.h" + +// example specific +#include "{{ model.name }}_model/{{ model.name }}_model.h" +#include "acados_sim_solver_{{ model.name }}.h" + +#include "simstruc.h" + +#define SAMPLINGTIME {{ solver_options.Tsim }} + + +static void mdlInitializeSizes (SimStruct *S) +{ + // specify the number of continuous and discrete states + ssSetNumContStates(S, 0); + ssSetNumDiscStates(S, 0); + + {# compute number of input ports #} + {%- set n_inputs = 1 %} {# x0 #} + {%- if dims.nu > 0 %} {# u0 -#} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif %} + {%- if dims.np > 0 %} {# parameters #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif %} + + // specify the number of input ports + if ( !ssSetNumInputPorts(S, {{ n_inputs }}) ) + return; + + // specify the number of output ports + if ( !ssSetNumOutputPorts(S, 1) ) + return; + + // specify dimension information for the input ports + {%- set i_input = 0 %} + // x0 + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nx }}); + + {%- if dims.nu > 0 %} + {%- set i_input = i_input + 1 %} + // u0 + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nu }}); + {%- endif %} + + {%- if dims.np > 0 %} + {%- set i_input = i_input + 1 %} + // parameters + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.np }}); + {%- endif %} + + // specify dimension information for the output ports + ssSetOutputPortVectorDimension(S, 0, {{ dims.nx }} ); // xnext + + // specify the direct feedthrough status + // should be set to 1 for all inputs used in mdlOutputs + {%- for i in range(end=n_inputs) %} + ssSetInputPortDirectFeedThrough(S, {{ i }}, 1); + {%- endfor %} + + // one sample time + ssSetNumSampleTimes(S, 1); +} + + +#if defined(MATLAB_MEX_FILE) + +#define MDL_SET_INPUT_PORT_DIMENSION_INFO +#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO + +static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +#endif /* MATLAB_MEX_FILE */ + + +static void mdlInitializeSampleTimes(SimStruct *S) +{ + ssSetSampleTime(S, 0, SAMPLINGTIME); + ssSetOffsetTime(S, 0, 0.0); +} + + +static void mdlStart(SimStruct *S) +{ + sim_solver_capsule *capsule = {{ model.name }}_acados_sim_solver_create_capsule(); + {{ model.name }}_acados_sim_create(capsule); + + ssSetUserData(S, (void*)capsule); +} + +static void mdlOutputs(SimStruct *S, int_T tid) +{ + sim_solver_capsule *capsule = ssGetUserData(S); + + sim_config *acados_sim_config = {{ model.name }}_acados_get_sim_config(capsule); + sim_in *acados_sim_in = {{ model.name }}_acados_get_sim_in(capsule); + sim_out *acados_sim_out = {{ model.name }}_acados_get_sim_out(capsule); + void *acados_sim_dims = {{ model.name }}_acados_get_sim_dims(capsule); + // sim_opts * {{ model.name }}_acados_get_sim_opts(capsule); + // sim_solver * {{ model.name }}_acados_get_sim_solver(capsule); + + InputRealPtrsType in_sign; + {% set input_sizes = [dims.nx, dims.nu, dims.np] %} + + // local buffer + {%- set buffer_size = input_sizes | sort | last %} + real_t buffer[{{ buffer_size }}]; + + + /* go through inputs */ + {%- set i_input = 0 %} + // initial condition + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.nx }}; i++) + buffer[i] = (double)(*in_sign[i]); + + sim_in_set(acados_sim_config, acados_sim_dims, + acados_sim_in, "x", buffer); + + + // ssPrintf("\nin acados sim:\n"); + // for (int i = 0; i < {{ dims.nx }}; i++) ssPrintf("x0[%d] = %f\n", i, buffer[i]); + // ssPrintf("\n"); + +{% if dims.nu > 0 %} + // control input - u + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int i = 0; i < {{ dims.nu }}; i++) + buffer[i] = (double)(*in_sign[i]); + + sim_in_set(acados_sim_config, acados_sim_dims, + acados_sim_in, "u", buffer); +{%- endif %} + + +{% if dims.np > 0 %} + // parameters + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int i = 0; i < {{ dims.np }}; i++) + buffer[i] = (double)(*in_sign[i]); + + // update value of parameters + {{ model.name }}_acados_sim_update_params(capsule, buffer, {{ dims.np }}); +{%- endif %} + + + /* call solver */ + int acados_status = {{ model.name }}_acados_sim_solve(capsule); + + + /* set outputs */ + real_t *out_x = ssGetOutputPortRealSignal(S, 0); + + // get simulated state + sim_out_get(acados_sim_config, acados_sim_dims, acados_sim_out, + "xn", (void *) out_x); + + // ssPrintf("\nacados sim solve: returned %d\n", acados_status); + // for (int i = 0; i < {{ dims.nx }}; i++) ssPrintf("x_sim[%d] = %f\n", i, out_x[i]); + // ssPrintf("\n"); + +} + + +static void mdlTerminate(SimStruct *S) +{ + sim_solver_capsule *capsule = ssGetUserData(S); + + {{ model.name }}_acados_sim_free(capsule); + {{ model.name }}_acados_sim_solver_free_capsule(capsule); +} + + +#ifdef MATLAB_MEX_FILE +#include "simulink.c" +#else +#include "cg_sfun.h" +#endif diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_solver_sfun.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_solver_sfun.in.c new file mode 100644 index 0000000000..3dd248037a --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/acados_solver_sfun.in.c @@ -0,0 +1,853 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#define S_FUNCTION_NAME acados_solver_sfunction_{{ model.name }} +#define S_FUNCTION_LEVEL 2 + +#define MDL_START + +// acados +// #include "acados/utils/print.h" +#include "acados_c/sim_interface.h" +#include "acados_c/external_function_interface.h" + +// example specific +#include "{{ model.name }}_model/{{ model.name }}_model.h" +#include "acados_solver_{{ model.name }}.h" + +#include "simstruc.h" + +{% if simulink_opts.samplingtime == "t0" -%} +#define SAMPLINGTIME {{ solver_options.time_steps[0] }} +{%- elif simulink_opts.samplingtime == "-1" -%} +#define SAMPLINGTIME -1 +{%- else -%} + {{ throw(message = "simulink_opts.samplingtime must be '-1' or 't0', got val") }} +{%- endif %} + +static void mdlInitializeSizes (SimStruct *S) +{ + // specify the number of continuous and discrete states + ssSetNumContStates(S, 0); + ssSetNumDiscStates(S, 0); + + int N = {{ model.name | upper }}_N; + + {%- for key, val in simulink_opts.inputs -%} + {%- if val != 0 and val != 1 -%} + {{ throw(message = "simulink_opts.inputs must be 0 or 1, got val") }} + {%- endif -%} + {%- endfor -%} + + {#- compute number of input ports #} + {%- set n_inputs = 0 -%} + {%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 -%} {#- y_ref_0 -#} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref -%} {#- y_ref -#} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e -%} {#- y_ref_e #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nh_e > 0 and simulink_opts.inputs.lh_e -%} {#- lh_e #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + {%- if dims.nh_e > 0 and simulink_opts.inputs.uh_e -%} {#- uh_e #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + + {%- for key, val in simulink_opts.inputs -%} + {%- if val != 0 and val != 1 -%} + {{ throw(message = "simulink_opts.inputs must be 0 or 1, got val") }} + {%- endif -%} + {%- endfor -%} + {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #} + {%- set n_inputs = n_inputs + 1 %} + {%- endif -%} + {%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #} + {%- set n_inputs = n_inputs + 1 %} + {%- endif -%} + {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + + {%- if simulink_opts.inputs.reset_solver -%} {#- reset_solver #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + + {%- if simulink_opts.inputs.x_init -%} {#- x_init #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + + {%- if simulink_opts.inputs.u_init -%} {#- u_init #} + {%- set n_inputs = n_inputs + 1 -%} + {%- endif -%} + + // specify the number of input ports + if ( !ssSetNumInputPorts(S, {{ n_inputs }}) ) + return; + + // specify the number of output ports + {%- set_global n_outputs = 0 %} + {%- for key, val in simulink_opts.outputs %} + {%- if val == 1 %} + {%- set_global n_outputs = n_outputs + val %} + {%- elif val != 0 %} + {{ throw(message = "simulink_opts.outputs must be 0 or 1, got val") }} + {%- endif %} + {%- endfor %} + if ( !ssSetNumOutputPorts(S, {{ n_outputs }}) ) + return; + + // specify dimension information for the input ports + {%- set i_input = -1 %}{# note here i_input is 0-based #} + {%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #} + {%- set i_input = i_input + 1 %} + // lbx_0 + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_0 }}); + {%- endif %} + {%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #} + {%- set i_input = i_input + 1 %} + // ubx_0 + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_0 }}); + {%- endif %} + + {%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #} + {%- set i_input = i_input + 1 %} + // parameters + ssSetInputPortVectorDimension(S, {{ i_input }}, (N+1) * {{ dims.np }}); + {%- endif %} + + {%- if dims.ny > 0 and simulink_opts.inputs.y_ref_0 %} + {%- set i_input = i_input + 1 %} + // y_ref_0 + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_0 }}); + {%- endif %} + + {%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %} + {%- set i_input = i_input + 1 %} + // y_ref + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ (dims.N-1) * dims.ny }}); + {%- endif %} + + {%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %} + {%- set i_input = i_input + 1 %} + // y_ref_e + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_e }}); + {%- endif %} + + {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #} + {%- set i_input = i_input + 1 %} + // lbx + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ (dims.N-1) * dims.nbx }}); + {%- endif %} + {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #} + {%- set i_input = i_input + 1 %} + // ubx + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ (dims.N-1) * dims.nbx }}); + {%- endif %} + + {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #} + {%- set i_input = i_input + 1 %} + // lbx_e + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_e }}); + {%- endif %} + {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #} + {%- set i_input = i_input + 1 %} + // ubx_e + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nbx_e }}); + {%- endif %} + + {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #} + {%- set i_input = i_input + 1 %} + // lbu + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.nbu }}); + {%- endif -%} + {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #} + {%- set i_input = i_input + 1 %} + // ubu + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.nbu }}); + {%- endif -%} + + + {%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #} + {%- set i_input = i_input + 1 %} + // lg + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.ng }}); + {%- endif -%} + {%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #} + {%- set i_input = i_input + 1 %} + // ug + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.ng }}); + {%- endif -%} + + {%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #} + {%- set i_input = i_input + 1 %} + // lh + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.nh }}); + {%- endif -%} + {%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #} + {%- set i_input = i_input + 1 %} + // uh + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.N*dims.nh }}); + {%- endif -%} + + {%- if dims.nh_e > 0 and simulink_opts.inputs.lh_e -%} {#- lh_e #} + {%- set i_input = i_input + 1 %} + // lh_e + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nh_e }}); + {%- endif -%} + {%- if dims.nh_e > 0 and simulink_opts.inputs.uh_e -%} {#- uh_e #} + {%- set i_input = i_input + 1 %} + // uh_e + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nh_e }}); + {%- endif -%} + + {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #} + {%- set i_input = i_input + 1 %} + // cost_W_0 + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_0 * dims.ny_0 }}); + {%- endif %} + + {%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #} + {%- set i_input = i_input + 1 %} + // cost_W + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny * dims.ny }}); + {%- endif %} + + {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #} + {%- set i_input = i_input + 1 %} + // cost_W_e + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.ny_e * dims.ny_e }}); + {%- endif %} + + {%- if simulink_opts.inputs.reset_solver -%} {#- reset_solver #} + {%- set i_input = i_input + 1 %} + // reset_solver + ssSetInputPortVectorDimension(S, {{ i_input }}, 1); + {%- endif -%} + + {%- if simulink_opts.inputs.x_init -%} {#- x_init #} + {%- set i_input = i_input + 1 %} + // x_init + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nx * (dims.N+1) }}); + {%- endif -%} + + {%- if simulink_opts.inputs.u_init -%} {#- u_init #} + {%- set i_input = i_input + 1 %} + // u_init + ssSetInputPortVectorDimension(S, {{ i_input }}, {{ dims.nu * (dims.N) }}); + {%- endif -%} + + /* specify dimension information for the OUTPUT ports */ + {%- set i_output = -1 %}{# note here i_output is 0-based #} + {%- if dims.nu > 0 and simulink_opts.outputs.u0 == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nu }} ); + {%- endif %} + + {%- if simulink_opts.outputs.utraj == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nu * dims.N }} ); + {%- endif %} + + {%- if simulink_opts.outputs.xtraj == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nx * (dims.N+1) }} ); + {%- endif %} + + {%- if simulink_opts.outputs.solver_status == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 ); + {%- endif %} + + {%- if simulink_opts.outputs.cost_value == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 ); + {%- endif %} + + {%- if simulink_opts.outputs.KKT_residual == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 ); + {%- endif %} + + {%- if simulink_opts.outputs.KKT_residuals == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 4 ); + {%- endif %} + + {%- if dims.N > 0 and simulink_opts.outputs.x1 == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, {{ dims.nx }} ); // state at shooting node 1 + {%- endif %} + + {%- if simulink_opts.outputs.CPU_time == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1); + {%- endif %} + + {%- if simulink_opts.outputs.CPU_time_sim == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1); + {%- endif %} + + {%- if simulink_opts.outputs.CPU_time_qp == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1); + {%- endif %} + + {%- if simulink_opts.outputs.CPU_time_lin == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1); + {%- endif %} + + {%- if simulink_opts.outputs.sqp_iter == 1 %} + {%- set i_output = i_output + 1 %} + ssSetOutputPortVectorDimension(S, {{ i_output }}, 1 ); + {%- endif %} + + // specify the direct feedthrough status + // should be set to 1 for all inputs used in mdlOutputs + {%- for i in range(end=n_inputs) %} + ssSetInputPortDirectFeedThrough(S, {{ i }}, 1); + {%- endfor %} + + // one sample time + ssSetNumSampleTimes(S, 1); +} + + +#if defined(MATLAB_MEX_FILE) + +#define MDL_SET_INPUT_PORT_DIMENSION_INFO +#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO + +static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo) +{ + if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) ) + return; +} + +#endif /* MATLAB_MEX_FILE */ + + +static void mdlInitializeSampleTimes(SimStruct *S) +{ + ssSetSampleTime(S, 0, SAMPLINGTIME); + ssSetOffsetTime(S, 0, 0.0); +} + + +static void mdlStart(SimStruct *S) +{ + {{ model.name }}_solver_capsule *capsule = {{ model.name }}_acados_create_capsule(); + {{ model.name }}_acados_create(capsule); + + ssSetUserData(S, (void*)capsule); +} + + +static void mdlOutputs(SimStruct *S, int_T tid) +{ + {{ model.name }}_solver_capsule *capsule = ssGetUserData(S); + ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(capsule); + ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); + ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(capsule); + ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(capsule); + + InputRealPtrsType in_sign; + + int N = {{ model.name | upper }}_N; + + {%- set buffer_sizes = [dims.nbx_0, dims.np, dims.nbx, dims.nbx_e, dims.nbu, dims.ng, dims.nh, dims.ng_e, dims.nh_e] -%} + + {%- if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 %} {# y_ref_0 #} + {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_0)) %} + {%- endif %} + {%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %} {# y_ref #} + {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny)) %} + {%- endif %} + {%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %} {# y_ref_e #} + {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_e)) %} + {%- endif %} + + {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #} + {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_0 * dims.ny_0)) %} + {%- endif %} + {%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #} + {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny * dims.ny)) %} + {%- endif %} + {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #} + {%- set buffer_sizes = buffer_sizes | concat(with=(dims.ny_e * dims.ny_e)) %} + {%- endif %} + + // local buffer + {%- set buffer_size = buffer_sizes | sort | last %} + real_t buffer[{{ buffer_size }}]; + + /* go through inputs */ + {%- set i_input = -1 %} + {%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #} + // lbx_0 + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.nbx_0 }}; i++) + buffer[i] = (double)(*in_sign[i]); + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbx", buffer); + {%- endif %} + + {%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #} + // ubx_0 + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.nbx_0 }}; i++) + buffer[i] = (double)(*in_sign[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubx", buffer); + {%- endif %} + + {%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #} + // parameters - stage-variant !!! + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + // update value of parameters + for (int ii = 0; ii <= N; ii++) + { + for (int jj = 0; jj < {{ dims.np }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{dims.np}}+jj]); + {{ model.name }}_acados_update_params(capsule, ii, buffer, {{ dims.np }}); + } + {%- endif %} + + {% if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 %} + // y_ref_0 + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int i = 0; i < {{ dims.ny_0 }}; i++) + buffer[i] = (double)(*in_sign[i]); + + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "yref", (void *) buffer); + {%- endif %} + + {% if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %} + // y_ref - for stages 1 to N-1 + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int ii = 1; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.ny }}; jj++) + buffer[jj] = (double)(*in_sign[(ii-1)*{{ dims.ny }}+jj]); + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, ii, "yref", (void *) buffer); + } + {%- endif %} + + {% if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %} + // y_ref_e + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int i = 0; i < {{ dims.ny_e }}; i++) + buffer[i] = (double)(*in_sign[i]); + + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "yref", (void *) buffer); + {%- endif %} + + {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #} + // lbx + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int ii = 1; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nbx }}; jj++) + buffer[jj] = (double)(*in_sign[(ii-1)*{{ dims.nbx }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lbx", (void *) buffer); + } + {%- endif %} + {%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #} + // ubx + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int ii = 1; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nbx }}; jj++) + buffer[jj] = (double)(*in_sign[(ii-1)*{{ dims.nbx }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "ubx", (void *) buffer); + } + {%- endif %} + + + {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #} + // lbx_e + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int i = 0; i < {{ dims.nbx_e }}; i++) + buffer[i] = (double)(*in_sign[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lbx", buffer); + {%- endif %} + {%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #} + // ubx_e + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int i = 0; i < {{ dims.nbx_e }}; i++) + buffer[i] = (double)(*in_sign[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ubx", buffer); + {%- endif %} + + + {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #} + // lbu + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nbu }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{ dims.nbu }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lbu", (void *) buffer); + } + {%- endif -%} + {%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #} + // ubu + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nbu }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{ dims.nbu }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "ubu", (void *) buffer); + } + {%- endif -%} + + {%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #} + // lg + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.ng }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{ dims.ng }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lg", (void *) buffer); + } + {%- endif -%} + {%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #} + // ug + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.ng }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{ dims.ng }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "ug", (void *) buffer); + } + {%- endif -%} + + {%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #} + // lh + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nh }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{ dims.nh }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "lh", (void *) buffer); + } + {%- endif -%} + {%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #} + // uh + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nh }}; jj++) + buffer[jj] = (double)(*in_sign[ii*{{ dims.nh }}+jj]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii, "uh", (void *) buffer); + } + {%- endif -%} + + + {%- if dims.nh_e > 0 and simulink_opts.inputs.lh_e -%} {#- lh_e #} + // lh_e + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.nh_e }}; i++) + buffer[i] = (double)(*in_sign[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lh", buffer); + {%- endif -%} + {%- if dims.nh_e > 0 and simulink_opts.inputs.uh_e -%} {#- uh_e #} + // uh_e + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.nh_e }}; i++) + buffer[i] = (double)(*in_sign[i]); + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uh", buffer); + {%- endif -%} + + {%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #} + // cost_W_0 + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.ny_0 * dims.ny_0 }}; i++) + buffer[i] = (double)(*in_sign[i]); + + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, 0, "W", buffer); + {%- endif %} + + {%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #} + // cost_W + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.ny * dims.ny }}; i++) + buffer[i] = (double)(*in_sign[i]); + + for (int ii = 1; ii < N; ii++) + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, ii, "W", buffer); + {%- endif %} + + {%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #} + // cost_W_e + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int i = 0; i < {{ dims.ny_e * dims.ny_e }}; i++) + buffer[i] = (double)(*in_sign[i]); + + ocp_nlp_cost_model_set(nlp_config, nlp_dims, nlp_in, N, "W", buffer); + {%- endif %} + + {%- if simulink_opts.inputs.reset_solver %} {#- reset_solver #} + // reset_solver + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + double reset = (double)(*in_sign[0]); + if (reset) + { + {{ model.name }}_acados_reset(capsule, 1); + } + {%- endif %} + + {%- if simulink_opts.inputs.x_init %} {#- x_init #} + // x_init + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int ii = 0; ii < {{ dims.N + 1 }}; ii++) + { + for (int jj = 0; jj < {{ dims.nx }}; jj++) + buffer[jj] = (double)(*in_sign[(ii)*{{ dims.nx }}+jj]); + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, ii, "x", (void *) buffer); + } + {%- endif %} + + {%- if simulink_opts.inputs.u_init %} {#- u_init #} + // u_init + {%- set i_input = i_input + 1 %} + in_sign = ssGetInputPortRealSignalPtrs(S, {{ i_input }}); + for (int ii = 0; ii < N; ii++) + { + for (int jj = 0; jj < {{ dims.nu }}; jj++) + buffer[jj] = (double)(*in_sign[(ii)*{{ dims.nu }}+jj]); + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, ii, "u", (void *) buffer); + } + {%- endif %} + + /* call solver */ + int rti_phase = 0; + ocp_nlp_solver_opts_set(nlp_config, capsule->nlp_opts, "rti_phase", &rti_phase); + int acados_status = {{ model.name }}_acados_solve(capsule); + + + /* set outputs */ + // assign pointers to output signals + real_t *out_u0, *out_utraj, *out_xtraj, *out_status, *out_sqp_iter, *out_KKT_res, *out_KKT_residuals, *out_x1, *out_cpu_time, *out_cpu_time_sim, *out_cpu_time_qp, *out_cpu_time_lin, *out_cost_value; + int tmp_int; + + {%- set i_output = -1 -%}{# note here i_output is 0-based #} + {%- if dims.nu > 0 and simulink_opts.outputs.u0 == 1 %} + {%- set i_output = i_output + 1 %} + out_u0 = ssGetOutputPortRealSignal(S, {{ i_output }}); + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 0, "u", (void *) out_u0); + {%- endif %} + + {%- if simulink_opts.outputs.utraj == 1 %} + {%- set i_output = i_output + 1 %} + out_utraj = ssGetOutputPortRealSignal(S, {{ i_output }}); + for (int ii = 0; ii < N; ii++) + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, + "u", (void *) (out_utraj + ii * {{ dims.nu }})); + {%- endif %} + + {% if simulink_opts.outputs.xtraj == 1 %} + {%- set i_output = i_output + 1 %} + + out_xtraj = ssGetOutputPortRealSignal(S, {{ i_output }}); + for (int ii = 0; ii < {{ dims.N + 1 }}; ii++) + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, + "x", (void *) (out_xtraj + ii * {{ dims.nx }})); + {%- endif %} + + {%- if simulink_opts.outputs.solver_status == 1 %} + {%- set i_output = i_output + 1 %} + out_status = ssGetOutputPortRealSignal(S, {{ i_output }}); + *out_status = (real_t) acados_status; + {%- endif %} + + {%- if simulink_opts.outputs.cost_value == 1 %} + {%- set i_output = i_output + 1 %} + out_cost_value = ssGetOutputPortRealSignal(S, {{ i_output }}); + ocp_nlp_eval_cost(capsule->nlp_solver, nlp_in, nlp_out); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "cost_value", (void *) out_cost_value); + {%- endif %} + + {%- if simulink_opts.outputs.KKT_residual == 1 %} + {%- set i_output = i_output + 1 %} + out_KKT_res = ssGetOutputPortRealSignal(S, {{ i_output }}); + *out_KKT_res = (real_t) nlp_out->inf_norm_res; + {%- endif %} + + {%- if simulink_opts.outputs.KKT_residuals == 1 %} + {%- set i_output = i_output + 1 %} + out_KKT_residuals = ssGetOutputPortRealSignal(S, {{ i_output }}); + + {%- if solver_options.nlp_solver_type == "SQP_RTI" %} + ocp_nlp_eval_residuals(capsule->nlp_solver, nlp_in, nlp_out); + {%- endif %} + ocp_nlp_get(nlp_config, capsule->nlp_solver, "res_stat", (void *) &out_KKT_residuals[0]); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "res_eq", (void *) &out_KKT_residuals[1]); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "res_ineq", (void *) &out_KKT_residuals[2]); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "res_comp", (void *) &out_KKT_residuals[3]); + {%- endif %} + + {%- if dims.N > 0 and simulink_opts.outputs.x1 == 1 %} + {%- set i_output = i_output + 1 %} + out_x1 = ssGetOutputPortRealSignal(S, {{ i_output }}); + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 1, "x", (void *) out_x1); + {%- endif %} + + {%- if simulink_opts.outputs.CPU_time == 1 %} + {%- set i_output = i_output + 1 %} + out_cpu_time = ssGetOutputPortRealSignal(S, {{ i_output }}); + // get solution time + ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_tot", (void *) out_cpu_time); + {%- endif -%} + + {%- if simulink_opts.outputs.CPU_time_sim == 1 %} + {%- set i_output = i_output + 1 %} + out_cpu_time_sim = ssGetOutputPortRealSignal(S, {{ i_output }}); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_sim", (void *) out_cpu_time_sim); + {%- endif -%} + + {%- if simulink_opts.outputs.CPU_time_qp == 1 %} + {%- set i_output = i_output + 1 %} + out_cpu_time_qp = ssGetOutputPortRealSignal(S, {{ i_output }}); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_qp", (void *) out_cpu_time_qp); + {%- endif -%} + + {%- if simulink_opts.outputs.CPU_time_lin == 1 %} + {%- set i_output = i_output + 1 %} + out_cpu_time_lin = ssGetOutputPortRealSignal(S, {{ i_output }}); + ocp_nlp_get(nlp_config, capsule->nlp_solver, "time_lin", (void *) out_cpu_time_lin); + {%- endif -%} + + {%- if simulink_opts.outputs.sqp_iter == 1 %} + {%- set i_output = i_output + 1 %} + out_sqp_iter = ssGetOutputPortRealSignal(S, {{ i_output }}); + // get sqp iter + ocp_nlp_get(nlp_config, capsule->nlp_solver, "sqp_iter", (void *) &tmp_int); + *out_sqp_iter = (real_t) tmp_int; + {%- endif %} + +} + +static void mdlTerminate(SimStruct *S) +{ + {{ model.name }}_solver_capsule *capsule = ssGetUserData(S); + + {{ model.name }}_acados_free(capsule); + {{ model.name }}_acados_free_capsule(capsule); +} + + +#ifdef MATLAB_MEX_FILE +#include "simulink.c" +#else +#include "cg_sfun.h" +#endif diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/main_mex.in.c b/third_party/acados/acados_template/c_templates_tera/matlab_templates/main_mex.in.c new file mode 100644 index 0000000000..851a3cc04f --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/main_mex.in.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +// standard +#include +#include +// acados +#include "acados/utils/print.h" +#include "acados/utils/math.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados_solver_{{ model.name }}.h" +// mex +#include "mex.h" + +/* auxilary mex */ +// prints a matrix in column-major format (exponential notation) +void MEX_print_exp_mat(int m, int n, double *A, int lda) +{ + for (int i=0; iN; i++) + { + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "x", x_init); + ocp_nlp_out_set(nlp_config, nlp_dims, nlp_out, i, "u", u0); + } + status = {{ model.name }}_acados_solve(); + ocp_nlp_get(nlp_config, nlp_solver, "time_tot", &elapsed_time); + min_time = MIN(elapsed_time, min_time); + } + + /* print solution and statistics */ + for (int ii = 0; ii <= nlp_dims->N; ii++) + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "x", &xtraj[ii*{{ dims.nx }}]); + for (int ii = 0; ii < nlp_dims->N; ii++) + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, ii, "u", &utraj[ii*{{ dims.nu }}]); + + mexPrintf("\n--- xtraj ---\n"); + MEX_print_exp_tran_mat( {{ dims.nx }}, {{ dims.N }}+1, xtraj, {{ dims.nx }} ); + mexPrintf("\n--- utraj ---\n"); + MEX_print_exp_tran_mat( {{ dims.nu }}, {{ dims.N }}, utraj, {{ dims.nu }} ); + + mexPrintf("\nsolved ocp %d times, solution printed above\n\n", NTIMINGS); + + if (status == ACADOS_SUCCESS) + mexPrintf("{{ model.name }}_acados_solve(): SUCCESS!\n"); + else + mexPrintf("{{ model.name }}_acados_solve() failed with status %d.\n", status); + + // get solution + ocp_nlp_out_get(nlp_config, nlp_dims, nlp_out, 0, "kkt_norm_inf", &kkt_norm_inf); + ocp_nlp_get(nlp_config, nlp_solver, "sqp_iter", &sqp_iter); + + mexPrintf("\nSolver info:\n"); + mexPrintf(" SQP iterations %2d\n minimum time for 1 solve %f [ms]\n KKT %e\n", + sqp_iter, min_time*1000, kkt_norm_inf); + + // free solver + status = {{ model.name }}_acados_free(); + if (status) + { + mexPrintf("{{ model.name }}_acados_free() returned status %d.\n", status); + } + + return; +} diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_main_mex.in.m b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_main_mex.in.m new file mode 100644 index 0000000000..d217948456 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_main_mex.in.m @@ -0,0 +1,103 @@ +% +% Copyright (c) The acados authors. +% +% This file is part of acados. +% +% The 2-Clause BSD License +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% +% 1. Redistributions of source code must retain the above copyright notice, +% this list of conditions and the following disclaimer. +% +% 2. Redistributions in binary form must reproduce the above copyright notice, +% this list of conditions and the following disclaimer in the documentation +% and/or other materials provided with the distribution. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE.; + +% + +function make_main_mex_{{ model.name }}() + + opts.output_dir = pwd; + + % get acados folder + acados_folder = getenv('ACADOS_INSTALL_DIR'); + + % set paths + acados_include = ['-I' fullfile(acados_folder, 'include')]; + template_lib_include = ['-l' 'acados_solver_{{ model.name }}']; + template_lib_path = ['-L' fullfile(pwd)]; + + acados_lib_path = ['-L' fullfile(acados_folder, 'lib')]; + external_include = ['-I', fullfile(acados_folder, 'external')]; + blasfeo_include = ['-I', fullfile(acados_folder, 'external', 'blasfeo', 'include')]; + hpipm_include = ['-I', fullfile(acados_folder, 'external', 'hpipm', 'include')]; + + mex_names = { ... + 'main_mex_{{ model.name }}' ... + }; + + mex_files = cell(length(mex_names), 1); + for k=1:length(mex_names) + mex_files{k} = fullfile([mex_names{k}, '.c']); + end + + %% octave C flags + if is_octave() + if ~exist(fullfile(opts.output_dir, 'cflags_octave.txt'), 'file') + diary(fullfile(opts.output_dir, 'cflags_octave.txt')); + diary on + mkoctfile -p CFLAGS + diary off + input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r'); + cflags_tmp = fscanf(input_file, '%[^\n]s'); + fclose(input_file); + if ~ismac() + cflags_tmp = [cflags_tmp, ' -std=c99 -fopenmp']; + else + cflags_tmp = [cflags_tmp, ' -std=c99']; + end + input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'w'); + fprintf(input_file, '%s', cflags_tmp); + fclose(input_file); + end + % read cflags from file + input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r'); + cflags_tmp = fscanf(input_file, '%[^\n]s'); + fclose(input_file); + setenv('CFLAGS', cflags_tmp); + end + + %% compile mex + for ii=1:length(mex_files) + disp(['compiling ', mex_files{ii}]) + if is_octave() + % mkoctfile -p CFLAGS + mex(acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,... + acados_lib_path, template_lib_path, '-lacados', '-lhpipm', '-lblasfeo', mex_files{ii}) + else + if ismac() + FLAGS = 'CFLAGS=$CFLAGS -std=c99'; + else + FLAGS = 'CFLAGS=$CFLAGS -std=c99 -fopenmp'; + end + mex(FLAGS, acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,... + acados_lib_path, template_lib_path, '-lacados', '-lhpipm', '-lblasfeo', mex_files{ii}) + end + end + + +end \ No newline at end of file diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_mex.in.m b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_mex.in.m new file mode 100644 index 0000000000..5e35827137 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_mex.in.m @@ -0,0 +1,127 @@ +% +% Copyright (c) The acados authors. +% +% This file is part of acados. +% +% The 2-Clause BSD License +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% +% 1. Redistributions of source code must retain the above copyright notice, +% this list of conditions and the following disclaimer. +% +% 2. Redistributions in binary form must reproduce the above copyright notice, +% this list of conditions and the following disclaimer in the documentation +% and/or other materials provided with the distribution. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE.; + +% + +function make_mex_{{ model.name }}() + + opts.output_dir = pwd; + + % get acados folder + acados_folder = getenv('ACADOS_INSTALL_DIR'); + + % set paths + acados_include = ['-I' fullfile(acados_folder, 'include')]; + template_lib_include = ['-l' 'acados_ocp_solver_{{ model.name }}']; + template_lib_path = ['-L' fullfile(pwd)]; + + acados_lib_path = ['-L' fullfile(acados_folder, 'lib')]; + external_include = ['-I', fullfile(acados_folder, 'external')]; + blasfeo_include = ['-I', fullfile(acados_folder, 'external', 'blasfeo', 'include')]; + hpipm_include = ['-I', fullfile(acados_folder, 'external', 'hpipm', 'include')]; + + % load linking information of compiled acados + link_libs_core_filename = fullfile(acados_folder, 'lib', 'link_libs.json'); + addpath(fullfile(acados_folder, 'external', 'jsonlab')); + link_libs = loadjson(link_libs_core_filename); + + % add necessary link instructs + acados_lib_extra = {}; + lib_names = fieldnames(link_libs); + for idx = 1 : numel(lib_names) + lib_name = lib_names{idx}; + link_arg = link_libs.(lib_name); + if ~isempty(link_arg) + acados_lib_extra = [acados_lib_extra, link_arg]; + end + end + + + mex_include = ['-I', fullfile(acados_folder, 'interfaces', 'acados_matlab_octave')]; + + mex_names = { ... + 'acados_mex_create_{{ model.name }}' ... + 'acados_mex_free_{{ model.name }}' ... + 'acados_mex_solve_{{ model.name }}' ... + 'acados_mex_set_{{ model.name }}' ... + }; + + mex_files = cell(length(mex_names), 1); + for k=1:length(mex_names) + mex_files{k} = fullfile([mex_names{k}, '.c']); + end + + %% octave C flags + if is_octave() + if ~exist(fullfile(opts.output_dir, 'cflags_octave.txt'), 'file') + diary(fullfile(opts.output_dir, 'cflags_octave.txt')); + diary on + mkoctfile -p CFLAGS + diary off + input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r'); + cflags_tmp = fscanf(input_file, '%[^\n]s'); + fclose(input_file); + if ~ismac() + cflags_tmp = [cflags_tmp, ' -std=c99 -fopenmp']; + else + cflags_tmp = [cflags_tmp, ' -std=c99']; + end + input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'w'); + fprintf(input_file, '%s', cflags_tmp); + fclose(input_file); + end + % read cflags from file + input_file = fopen(fullfile(opts.output_dir, 'cflags_octave.txt'), 'r'); + cflags_tmp = fscanf(input_file, '%[^\n]s'); + fclose(input_file); + setenv('CFLAGS', cflags_tmp); + end + + %% compile mex + for ii=1:length(mex_files) + disp(['compiling ', mex_files{ii}]) + if is_octave() + % mkoctfile -p CFLAGS + mex(acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,... + template_lib_path, mex_include, acados_lib_path, '-lacados', '-lhpipm', '-lblasfeo',... + acados_lib_extra{:}, mex_files{ii}) + else + if ismac() + FLAGS = 'CFLAGS=$CFLAGS -std=c99'; + else + FLAGS = 'CFLAGS=$CFLAGS -std=c99 -fopenmp'; + end + mex(FLAGS, acados_include, template_lib_include, external_include, blasfeo_include, hpipm_include,... + template_lib_path, mex_include, acados_lib_path, '-lacados', '-lhpipm', '-lblasfeo',... + acados_lib_extra{:}, mex_files{ii}) + end + end + + +end \ No newline at end of file diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_sfun.in.m b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_sfun.in.m new file mode 100644 index 0000000000..5d74c523f8 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_sfun.in.m @@ -0,0 +1,432 @@ +% +% Copyright (c) The acados authors. +% +% This file is part of acados. +% +% The 2-Clause BSD License +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% +% 1. Redistributions of source code must retain the above copyright notice, +% this list of conditions and the following disclaimer. +% +% 2. Redistributions in binary form must reproduce the above copyright notice, +% this list of conditions and the following disclaimer in the documentation +% and/or other materials provided with the distribution. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE.; + +% + +SOURCES = { ... + {%- if solver_options.integrator_type == 'ERK' %} + '{{ model.name }}_model/{{ model.name }}_expl_ode_fun.c', ... + '{{ model.name }}_model/{{ model.name }}_expl_vde_forw.c',... + {%- if solver_options.hessian_approx == 'EXACT' %} + '{{ model.name }}_model/{{ model.name }}_expl_ode_hess.c',... + {%- endif %} + {%- elif solver_options.integrator_type == "IRK" %} + '{{ model.name }}_model/{{ model.name }}_impl_dae_fun.c', ... + '{{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.c', ... + '{{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.c', ... + {%- if solver_options.hessian_approx == 'EXACT' %} + '{{ model.name }}_model/{{ model.name }}_impl_dae_hess.c',... + {%- endif %} + {%- elif solver_options.integrator_type == "GNSF" %} + {% if model.gnsf.purely_linear != 1 %} + '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.c',... + '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.c',... + '{{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.c',... + {% if model.gnsf.nontrivial_f_LO == 1 %} + '{{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c',... + {%- endif %} + {%- endif %} + '{{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.c',... + {%- elif solver_options.integrator_type == "DISCRETE" %} + '{{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun.c',... + '{{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac.c',... + {%- if solver_options.hessian_approx == "EXACT" %} + '{{ model.name }}_model/{{ model.name }}_dyn_disc_phi_fun_jac_hess.c',... + {%- endif %} + {%- endif %} + {%- if cost.cost_type_0 == "NONLINEAR_LS" %} + '{{ model.name }}_cost/{{ model.name }}_cost_y_0_fun.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_y_0_fun_jac_ut_xt.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_y_0_hess.c',... + {%- elif cost.cost_type_0 == "EXTERNAL" %} + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_0_fun_jac_hess.c',... + {%- endif %} + + {%- if cost.cost_type == "NONLINEAR_LS" %} + '{{ model.name }}_cost/{{ model.name }}_cost_y_fun.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_y_fun_jac_ut_xt.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_y_hess.c',... + {%- elif cost.cost_type == "EXTERNAL" %} + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_fun_jac_hess.c',... + {%- endif %} + {%- if cost.cost_type_e == "NONLINEAR_LS" %} + '{{ model.name }}_cost/{{ model.name }}_cost_y_e_fun.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_y_e_fun_jac_ut_xt.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_y_e_hess.c',... + {%- elif cost.cost_type_e == "EXTERNAL" %} + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac.c',... + '{{ model.name }}_cost/{{ model.name }}_cost_ext_cost_e_fun_jac_hess.c',... + {%- endif %} + {%- if constraints.constr_type == "BGH" and dims.nh > 0 %} + '{{ model.name }}_constraints/{{ model.name }}_constr_h_fun.c', ... + '{{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt_hess.c', ... + '{{ model.name }}_constraints/{{ model.name }}_constr_h_fun_jac_uxt_zt.c', ... + {%- elif constraints.constr_type == "BGP" and dims.nphi > 0 %} + '{{ model.name }}_constraints/{{ model.name }}_phi_constraint.c', ... + {%- endif %} + {%- if constraints.constr_type_e == "BGH" and dims.nh_e > 0 %} + '{{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun.c', ... + '{{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt_hess.c', ... + '{{ model.name }}_constraints/{{ model.name }}_constr_h_e_fun_jac_uxt_zt.c', ... + {%- elif constraints.constr_type_e == "BGP" and dims.nphi_e > 0 %} + '{{ model.name }}_constraints/{{ model.name }}_phi_e_constraint.c', ... + {%- endif %} + 'acados_solver_sfunction_{{ model.name }}.c', ... + 'acados_solver_{{ model.name }}.c' + }; + +INC_PATH = '{{ acados_include_path }}'; + +INCS = {['-I', fullfile(INC_PATH, 'blasfeo', 'include')], ... + ['-I', fullfile(INC_PATH, 'hpipm', 'include')], ... + ['-I', fullfile(INC_PATH, 'acados')], ... + ['-I', fullfile(INC_PATH)]}; + +{% if solver_options.qp_solver is containing("QPOASES") %} +INCS{end+1} = ['-I', fullfile(INC_PATH, 'qpOASES_e')]; +{% endif %} + +CFLAGS = 'CFLAGS=$CFLAGS'; +LDFLAGS = 'LDFLAGS=$LDFLAGS'; +COMPFLAGS = 'COMPFLAGS=$COMPFLAGS'; +COMPDEFINES = 'COMPDEFINES=$COMPDEFINES'; + +{% if solver_options.qp_solver is containing("QPOASES") %} +CFLAGS = [ CFLAGS, ' -DACADOS_WITH_QPOASES ' ]; +COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_QPOASES ' ]; +{%- elif solver_options.qp_solver is containing("OSQP") %} +CFLAGS = [ CFLAGS, ' -DACADOS_WITH_OSQP ' ]; +COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_OSQP ' ]; +{%- elif solver_options.qp_solver is containing("QPDUNES") %} +CFLAGS = [ CFLAGS, ' -DACADOS_WITH_QPDUNES ' ]; +COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_QPDUNES ' ]; +{%- elif solver_options.qp_solver is containing("DAQP") %} +CFLAGS = [ CFLAGS, ' -DACADOS_WITH_DAQP' ]; +COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_DAQP' ]; +{%- elif solver_options.qp_solver is containing("HPMPC") %} +CFLAGS = [ CFLAGS, ' -DACADOS_WITH_HPMPC ' ]; +COMPDEFINES = [ COMPDEFINES, ' -DACADOS_WITH_HPMPC ' ]; +{% endif %} + +LIB_PATH = ['-L', fullfile('{{ acados_lib_path }}')]; + +LIBS = {'-lacados', '-lhpipm', '-lblasfeo'}; + +% acados linking libraries and flags +{%- if acados_link_libs and os and os == "pc" %} +LDFLAGS = [LDFLAGS ' {{ acados_link_libs.openmp }}']; +COMPFLAGS = [COMPFLAGS ' {{ acados_link_libs.openmp }}']; +LIBS{end+1} = '{{ acados_link_libs.qpoases }}'; +LIBS{end+1} = '{{ acados_link_libs.hpmpc }}'; +LIBS{end+1} = '{{ acados_link_libs.osqp }}'; +{%- else %} + {% if solver_options.qp_solver is containing("QPOASES") %} +LIBS{end+1} = '-lqpOASES_e'; + {% endif %} + {% if solver_options.qp_solver is containing("DAQP") %} +LIBS{end+1} = '-ldaqp'; + {% endif %} +{%- endif %} + + +try + % mex('-v', '-O', CFLAGS, LDFLAGS, COMPFLAGS, COMPDEFINES, INCS{:}, ... + mex('-O', CFLAGS, LDFLAGS, COMPFLAGS, COMPDEFINES, INCS{:}, ... + LIB_PATH, LIBS{:}, SOURCES{:}, ... + '-output', 'acados_solver_sfunction_{{ model.name }}' ); +catch exception + disp('make_sfun failed with the following exception:') + disp(exception); + disp('Try adding -v to the mex command above to get more information.') + keyboard +end + +fprintf( [ '\n\nSuccessfully created sfunction:\nacados_solver_sfunction_{{ model.name }}', '.', ... + eval('mexext')] ); + + +%% print note on usage of s-function, and create I/O port names vectors +fprintf('\n\nNote: Usage of Sfunction is as follows:\n') +input_note = 'Inputs are:\n'; +i_in = 1; + +global sfun_input_names +sfun_input_names = {}; + +{%- if dims.nbx_0 > 0 and simulink_opts.inputs.lbx_0 -%} {#- lbx_0 #} +input_note = strcat(input_note, num2str(i_in), ') lbx_0 - lower bound on x for stage 0,',... + ' size [{{ dims.nbx_0 }}]\n '); +sfun_input_names = [sfun_input_names; 'lbx_0 [{{ dims.nbx_0 }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.nbx_0 > 0 and simulink_opts.inputs.ubx_0 -%} {#- ubx_0 #} +input_note = strcat(input_note, num2str(i_in), ') ubx_0 - upper bound on x for stage 0,',... + ' size [{{ dims.nbx_0 }}]\n '); +sfun_input_names = [sfun_input_names; 'ubx_0 [{{ dims.nbx_0 }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.np > 0 and simulink_opts.inputs.parameter_traj -%} {#- parameter_traj #} +input_note = strcat(input_note, num2str(i_in), ') parameters - concatenated for all shooting nodes 0 to N,',... + ' size [{{ (dims.N+1)*dims.np }}]\n '); +sfun_input_names = [sfun_input_names; 'parameter_traj [{{ (dims.N+1)*dims.np }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.ny_0 > 0 and simulink_opts.inputs.y_ref_0 %} +input_note = strcat(input_note, num2str(i_in), ') y_ref_0, size [{{ dims.ny_0 }}]\n '); +sfun_input_names = [sfun_input_names; 'y_ref_0 [{{ dims.ny_0 }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.ny > 0 and dims.N > 1 and simulink_opts.inputs.y_ref %} +input_note = strcat(input_note, num2str(i_in), ') y_ref - concatenated for shooting nodes 1 to N-1,',... + ' size [{{ (dims.N-1) * dims.ny }}]\n '); +sfun_input_names = [sfun_input_names; 'y_ref [{{ (dims.N-1) * dims.ny }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.ny_e > 0 and dims.N > 0 and simulink_opts.inputs.y_ref_e %} +input_note = strcat(input_note, num2str(i_in), ') y_ref_e, size [{{ dims.ny_e }}]\n '); +sfun_input_names = [sfun_input_names; 'y_ref_e [{{ dims.ny_e }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.lbx -%} {#- lbx #} +input_note = strcat(input_note, num2str(i_in), ') lbx for shooting nodes 1 to N-1, size [{{ (dims.N-1) * dims.nbx }}]\n '); +sfun_input_names = [sfun_input_names; 'lbx [{{ (dims.N-1) * dims.nbx }}]']; +i_in = i_in + 1; +{%- endif %} +{%- if dims.nbx > 0 and dims.N > 1 and simulink_opts.inputs.ubx -%} {#- ubx #} +input_note = strcat(input_note, num2str(i_in), ') ubx for shooting nodes 1 to N-1, size [{{ (dims.N-1) * dims.nbx }}]\n '); +sfun_input_names = [sfun_input_names; 'ubx [{{ (dims.N-1) * dims.nbx }}]']; +i_in = i_in + 1; +{%- endif %} + + +{%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.lbx_e -%} {#- lbx_e #} +input_note = strcat(input_note, num2str(i_in), ') lbx_e (lbx at shooting node N), size [{{ dims.nbx_e }}]\n '); +sfun_input_names = [sfun_input_names; 'lbx_e [{{ dims.nbx_e }}]']; +i_in = i_in + 1; +{%- endif %} +{%- if dims.nbx_e > 0 and dims.N > 0 and simulink_opts.inputs.ubx_e -%} {#- ubx_e #} +input_note = strcat(input_note, num2str(i_in), ') ubx_e (ubx at shooting node N), size [{{ dims.nbx_e }}]\n '); +sfun_input_names = [sfun_input_names; 'ubx_e [{{ dims.nbx_e }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.lbu -%} {#- lbu #} +input_note = strcat(input_note, num2str(i_in), ') lbu for shooting nodes 0 to N-1, size [{{ dims.N*dims.nbu }}]\n '); +sfun_input_names = [sfun_input_names; 'lbu [{{ dims.N*dims.nbu }}]']; +i_in = i_in + 1; +{%- endif -%} +{%- if dims.nbu > 0 and dims.N > 0 and simulink_opts.inputs.ubu -%} {#- ubu #} +input_note = strcat(input_note, num2str(i_in), ') ubu for shooting nodes 0 to N-1, size [{{ dims.N*dims.nbu }}]\n '); +sfun_input_names = [sfun_input_names; 'ubu [{{ dims.N*dims.nbu }}]']; +i_in = i_in + 1; +{%- endif -%} + +{%- if dims.ng > 0 and simulink_opts.inputs.lg -%} {#- lg #} +input_note = strcat(input_note, num2str(i_in), ') lg for shooting nodes 0 to N-1, size [{{ dims.N*dims.ng }}]\n '); +sfun_input_names = [sfun_input_names; 'lg [{{ dims.N*dims.ng }}]']; +i_in = i_in + 1; +{%- endif %} +{%- if dims.ng > 0 and simulink_opts.inputs.ug -%} {#- ug #} +input_note = strcat(input_note, num2str(i_in), ') ug for shooting nodes 0 to N-1, size [{{ dims.N*dims.ng }}]\n '); +sfun_input_names = [sfun_input_names; 'ug [{{ dims.N*dims.ng }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.nh > 0 and simulink_opts.inputs.lh -%} {#- lh #} +input_note = strcat(input_note, num2str(i_in), ') lh for shooting nodes 0 to N-1, size [{{ dims.N*dims.nh }}]\n '); +sfun_input_names = [sfun_input_names; 'lh [{{ dims.N*dims.nh }}]']; +i_in = i_in + 1; +{%- endif %} +{%- if dims.nh > 0 and simulink_opts.inputs.uh -%} {#- uh #} +input_note = strcat(input_note, num2str(i_in), ') uh for shooting nodes 0 to N-1, size [{{ dims.N*dims.nh }}]\n '); +sfun_input_names = [sfun_input_names; 'uh [{{ dims.N*dims.nh }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.nh_e > 0 and simulink_opts.inputs.lh_e -%} {#- lh_e #} +input_note = strcat(input_note, num2str(i_in), ') lh_e, size [{{ dims.nh_e }}]\n '); +sfun_input_names = [sfun_input_names; 'lh_e [{{ dims.nh_e }}]']; +i_in = i_in + 1; +{%- endif %} +{%- if dims.nh_e > 0 and simulink_opts.inputs.uh_e -%} {#- uh_e #} +input_note = strcat(input_note, num2str(i_in), ') uh_e, size [{{ dims.nh_e }}]\n '); +sfun_input_names = [sfun_input_names; 'uh_e [{{ dims.nh_e }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.ny_0 > 0 and simulink_opts.inputs.cost_W_0 %} {#- cost_W_0 #} +input_note = strcat(input_note, num2str(i_in), ') cost_W_0 in column-major format, size [{{ dims.ny_0 * dims.ny_0 }}]\n '); +sfun_input_names = [sfun_input_names; 'cost_W_0 [{{ dims.ny_0 * dims.ny_0 }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.ny > 0 and simulink_opts.inputs.cost_W %} {#- cost_W #} +input_note = strcat(input_note, num2str(i_in), ') cost_W in column-major format, that is set for all intermediate shooting nodes: 1 to N-1, size [{{ dims.ny * dims.ny }}]\n '); +sfun_input_names = [sfun_input_names; 'cost_W [{{ dims.ny * dims.ny }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if dims.ny_e > 0 and simulink_opts.inputs.cost_W_e %} {#- cost_W_e #} +input_note = strcat(input_note, num2str(i_in), ') cost_W_e in column-major format, size [{{ dims.ny_e * dims.ny_e }}]\n '); +sfun_input_names = [sfun_input_names; 'cost_W_e [{{ dims.ny_e * dims.ny_e }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if simulink_opts.inputs.reset_solver %} {#- reset_solver #} +input_note = strcat(input_note, num2str(i_in), ') reset_solver determines if iterate is set to all zeros before other initializations (x_init, u_init) are set and before solver is called, size [1]\n '); +sfun_input_names = [sfun_input_names; 'reset_solver [1]']; +i_in = i_in + 1; +{%- endif %} + +{%- if simulink_opts.inputs.x_init %} {#- x_init #} +input_note = strcat(input_note, num2str(i_in), ') initialization of x for all shooting nodes, size [{{ dims.nx * (dims.N+1) }}]\n '); +sfun_input_names = [sfun_input_names; 'x_init [{{ dims.nx * (dims.N+1) }}]']; +i_in = i_in + 1; +{%- endif %} + +{%- if simulink_opts.inputs.u_init %} {#- u_init #} +input_note = strcat(input_note, num2str(i_in), ') initialization of u for shooting nodes 0 to N-1, size [{{ dims.nu * (dims.N) }}]\n '); +sfun_input_names = [sfun_input_names; 'u_init [{{ dims.nu * (dims.N) }}]']; +i_in = i_in + 1; +{%- endif %} + +fprintf(input_note) + +disp(' ') + +output_note = 'Outputs are:\n'; +i_out = 0; + +global sfun_output_names +sfun_output_names = {}; + +{%- if dims.nu > 0 and simulink_opts.outputs.u0 == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') u0, control input at node 0, size [{{ dims.nu }}]\n '); +sfun_output_names = [sfun_output_names; 'u0 [{{ dims.nu }}]']; +{%- endif %} + +{%- if simulink_opts.outputs.utraj == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') utraj, control input concatenated for nodes 0 to N-1, size [{{ dims.nu * dims.N }}]\n '); +sfun_output_names = [sfun_output_names; 'utraj [{{ dims.nu * dims.N }}]']; +{%- endif %} + +{%- if simulink_opts.outputs.xtraj == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') xtraj, state concatenated for nodes 0 to N, size [{{ dims.nx * (dims.N + 1) }}]\n '); +sfun_output_names = [sfun_output_names; 'xtraj [{{ dims.nx * (dims.N + 1) }}]']; +{%- endif %} + +{%- if simulink_opts.outputs.solver_status == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') acados solver status (0 = SUCCESS)\n '); +sfun_output_names = [sfun_output_names; 'solver_status']; +{%- endif %} + +{%- if simulink_opts.outputs.cost_value == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') cost function value\n '); +sfun_output_names = [sfun_output_names; 'cost_value']; +{%- endif %} + + +{%- if simulink_opts.outputs.KKT_residual == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') KKT residual\n '); +sfun_output_names = [sfun_output_names; 'KKT_residual']; +{%- endif %} + +{%- if simulink_opts.outputs.KKT_residuals == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') KKT residuals, size [4] (stat, eq, ineq, comp)\n '); +sfun_output_names = [sfun_output_names; 'KKT_residuals [4]']; +{%- endif %} + +{%- if dims.N > 0 and simulink_opts.outputs.x1 == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') x1, state at node 1\n '); +sfun_output_names = [sfun_output_names; 'x1']; +{%- endif %} + +{%- if simulink_opts.outputs.CPU_time == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') CPU time\n '); +sfun_output_names = [sfun_output_names; 'CPU_time']; +{%- endif %} + +{%- if simulink_opts.outputs.CPU_time_sim == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') CPU time integrator\n '); +sfun_output_names = [sfun_output_names; 'CPU_time_sim']; +{%- endif %} + +{%- if simulink_opts.outputs.CPU_time_qp == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') CPU time QP solution\n '); +sfun_output_names = [sfun_output_names; 'CPU_time_qp']; +{%- endif %} + +{%- if simulink_opts.outputs.CPU_time_lin == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') CPU time linearization (including integrator)\n '); +sfun_output_names = [sfun_output_names; 'CPU_time_lin']; +{%- endif %} + +{%- if simulink_opts.outputs.sqp_iter == 1 %} +i_out = i_out + 1; +output_note = strcat(output_note, num2str(i_out), ') SQP iterations\n '); +sfun_output_names = [sfun_output_names; 'sqp_iter']; +{%- endif %} + +fprintf(output_note) + +% The mask drawing command is: +% --- +% global sfun_input_names sfun_output_names +% for i = 1:length(sfun_input_names) +% port_label('input', i, sfun_input_names{i}) +% end +% for i = 1:length(sfun_output_names) +% port_label('output', i, sfun_output_names{i}) +% end +% --- +% It can be used by copying it in sfunction/Mask/Edit mask/Icon drawing commands +% (you can access it wirth ctrl+M on the s-function) \ No newline at end of file diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_sfun_sim.in.m b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_sfun_sim.in.m new file mode 100644 index 0000000000..e4c32a8c19 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/make_sfun_sim.in.m @@ -0,0 +1,137 @@ +% +% Copyright (c) The acados authors. +% +% This file is part of acados. +% +% The 2-Clause BSD License +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% +% 1. Redistributions of source code must retain the above copyright notice, +% this list of conditions and the following disclaimer. +% +% 2. Redistributions in binary form must reproduce the above copyright notice, +% this list of conditions and the following disclaimer in the documentation +% and/or other materials provided with the distribution. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE.; + +% + +SOURCES = [ 'acados_sim_solver_sfunction_{{ model.name }}.c ', ... + 'acados_sim_solver_{{ model.name }}.c ', ... + {%- if solver_options.integrator_type == 'ERK' %} + '{{ model.name }}_model/{{ model.name }}_expl_ode_fun.c ',... + '{{ model.name }}_model/{{ model.name }}_expl_vde_forw.c ',... + '{{ model.name }}_model/{{ model.name }}_expl_vde_adj.c ',... + {%- if solver_options.hessian_approx == 'EXACT' %} + '{{ model.name }}_model/{{ model.name }}_expl_ode_hess.c ',... + {%- endif %} + {%- elif solver_options.integrator_type == "IRK" %} + '{{ model.name }}_model/{{ model.name }}_impl_dae_fun.c ', ... + '{{ model.name }}_model/{{ model.name }}_impl_dae_fun_jac_x_xdot_z.c ', ... + '{{ model.name }}_model/{{ model.name }}_impl_dae_jac_x_xdot_u_z.c ', ... + {%- if solver_options.hessian_approx == 'EXACT' %} + '{{ model.name }}_model/{{ model.name }}_impl_dae_hess.c ',... + {%- endif %} + {%- elif solver_options.integrator_type == "GNSF" %} + {%- if model.gnsf.purely_linear != 1 %} + '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun.c ',... + '{{ model.name }}_model/{{ model.name }}_gnsf_phi_fun_jac_y.c ',... + '{{ model.name }}_model/{{ model.name }}_gnsf_phi_jac_y_uhat.c ',... + {%- if model.gnsf.nontrivial_f_LO == 1 %} + '{{ model.name }}_model/{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz.c ',... + {%- endif %} + {%- endif %} + '{{ model.name }}_model/{{ model.name }}_gnsf_get_matrices_fun.c ',... + {%- endif %} + ]; + +INC_PATH = '{{ acados_include_path }}'; + +INCS = [ ' -I', fullfile(INC_PATH, 'blasfeo', 'include'), ... + ' -I', fullfile(INC_PATH, 'hpipm', 'include'), ... + ' -I', INC_PATH, ' -I', fullfile(INC_PATH, 'acados'), ' ']; + +CFLAGS = ' -O'; + +LIB_PATH = '{{ acados_lib_path }}'; + +LIBS = '-lacados -lblasfeo -lhpipm'; + +try + % eval( [ 'mex -v -output acados_sim_solver_sfunction_{{ model.name }} ', ... + eval( [ 'mex -output acados_sim_solver_sfunction_{{ model.name }} ', ... + CFLAGS, INCS, ' ', SOURCES, ' -L', LIB_PATH, ' ', LIBS ]); + +catch exception + disp('make_sfun failed with the following exception:') + disp(exception); + disp('Try adding -v to the mex command above to get more information.') + keyboard +end + + +fprintf( [ '\n\nSuccessfully created sfunction:\nacados_sim_solver_sfunction_{{ model.name }}', '.', ... + eval('mexext')] ); + + +global sfun_sim_input_names +sfun_sim_input_names = {}; + +%% print note on usage of s-function +fprintf('\n\nNote: Usage of Sfunction is as follows:\n') +input_note = 'Inputs are:\n1) x0, initial state, size [{{ dims.nx }}]\n '; +i_in = 2; +sfun_sim_input_names = [sfun_sim_input_names; 'x0 [{{ dims.nx }}]']; + +{%- if dims.nu > 0 %} +input_note = strcat(input_note, num2str(i_in), ') u, size [{{ dims.nu }}]\n '); +i_in = i_in + 1; +sfun_sim_input_names = [sfun_sim_input_names; 'u [{{ dims.nu }}]']; +{%- endif %} + +{%- if dims.np > 0 %} +input_note = strcat(input_note, num2str(i_in), ') parameters, size [{{ dims.np }}]\n '); +i_in = i_in + 1; +sfun_sim_input_names = [sfun_sim_input_names; 'p [{{ dims.np }}]']; +{%- endif %} + + +fprintf(input_note) + +disp(' ') + +global sfun_sim_output_names +sfun_sim_output_names = {}; + +output_note = strcat('Outputs are:\n', ... + '1) x1 - simulated state, size [{{ dims.nx }}]\n'); +sfun_sim_output_names = [sfun_sim_output_names; 'x1 [{{ dims.nx }}]']; + +fprintf(output_note) + + +% The mask drawing command is: +% --- +% global sfun_sim_input_names sfun_sim_output_names +% for i = 1:length(sfun_sim_input_names) +% port_label('input', i, sfun_sim_input_names{i}) +% end +% for i = 1:length(sfun_sim_output_names) +% port_label('output', i, sfun_sim_output_names{i}) +% end +% --- +% It can be used by copying it in sfunction/Mask/Edit mask/Icon drawing commands +% (you can access it wirth ctrl+M on the s-function) \ No newline at end of file diff --git a/third_party/acados/acados_template/c_templates_tera/matlab_templates/mex_solver.in.m b/third_party/acados/acados_template/c_templates_tera/matlab_templates/mex_solver.in.m new file mode 100644 index 0000000000..3743212830 --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/matlab_templates/mex_solver.in.m @@ -0,0 +1,270 @@ +% +% Copyright (c) The acados authors. +% +% This file is part of acados. +% +% The 2-Clause BSD License +% +% Redistribution and use in source and binary forms, with or without +% modification, are permitted provided that the following conditions are met: +% +% 1. Redistributions of source code must retain the above copyright notice, +% this list of conditions and the following disclaimer. +% +% 2. Redistributions in binary form must reproduce the above copyright notice, +% this list of conditions and the following disclaimer in the documentation +% and/or other materials provided with the distribution. +% +% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +% POSSIBILITY OF SUCH DAMAGE.; + +% + +classdef {{ model.name }}_mex_solver < handle + + properties + C_ocp + C_ocp_ext_fun + cost_ext_fun_type + cost_ext_fun_type_e + N + name + code_gen_dir + end % properties + + + + methods + + % constructor + function obj = {{ model.name }}_mex_solver() + make_mex_{{ model.name }}(); + [obj.C_ocp, obj.C_ocp_ext_fun] = acados_mex_create_{{ model.name }}(); + % to have path to destructor when changing directory + addpath('.') + obj.cost_ext_fun_type = '{{ cost.cost_ext_fun_type }}'; + obj.cost_ext_fun_type_e = '{{ cost.cost_ext_fun_type_e }}'; + obj.N = {{ dims.N }}; + obj.name = '{{ model.name }}'; + obj.code_gen_dir = pwd(); + end + + % destructor + function delete(obj) + disp("delete template..."); + return_dir = pwd(); + cd(obj.code_gen_dir); + if ~isempty(obj.C_ocp) + acados_mex_free_{{ model.name }}(obj.C_ocp); + end + cd(return_dir); + disp("done."); + end + + % solve + function solve(obj) + acados_mex_solve_{{ model.name }}(obj.C_ocp); + end + + % set -- borrowed from MEX interface + function set(varargin) + obj = varargin{1}; + field = varargin{2}; + value = varargin{3}; + if ~isa(field, 'char') + error('field must be a char vector, use '' '''); + end + if nargin==3 + acados_mex_set_{{ model.name }}(obj.cost_ext_fun_type, obj.cost_ext_fun_type_e, obj.C_ocp, obj.C_ocp_ext_fun, field, value); + elseif nargin==4 + stage = varargin{4}; + acados_mex_set_{{ model.name }}(obj.cost_ext_fun_type, obj.cost_ext_fun_type_e, obj.C_ocp, obj.C_ocp_ext_fun, field, value, stage); + else + disp('acados_ocp.set: wrong number of input arguments (2 or 3 allowed)'); + end + end + + function value = get_cost(obj) + value = ocp_get_cost(obj.C_ocp); + end + + % get -- borrowed from MEX interface + function value = get(varargin) + % usage: + % obj.get(field, value, [stage]) + obj = varargin{1}; + field = varargin{2}; + if any(strfind('sens', field)) + error('field sens* (sensitivities of optimal solution) not yet supported for templated MEX.') + end + if ~isa(field, 'char') + error('field must be a char vector, use '' '''); + end + + if nargin==2 + value = ocp_get(obj.C_ocp, field); + elseif nargin==3 + stage = varargin{3}; + value = ocp_get(obj.C_ocp, field, stage); + else + disp('acados_ocp.get: wrong number of input arguments (1 or 2 allowed)'); + end + end + + + function [] = store_iterate(varargin) + %%% Stores the current iterate of the ocp solver in a json file. + %%% param1: filename: if not set, use model_name + timestamp + '.json' + %%% param2: overwrite: if false and filename exists add timestamp to filename + + obj = varargin{1}; + filename = ''; + overwrite = false; + + if nargin>=2 + filename = varargin{2}; + if ~isa(filename, 'char') + error('filename must be a char vector, use '' '''); + end + end + + if nargin==3 + overwrite = varargin{3}; + end + + if nargin > 3 + disp('acados_ocp.get: wrong number of input arguments (1 or 2 allowed)'); + end + + if strcmp(filename,'') + filename = [obj.name '_iterate.json']; + end + if ~overwrite + % append timestamp + if exist(filename, 'file') + filename = filename(1:end-5); + filename = [filename '_' datestr(now,'yyyy-mm-dd-HH:MM:SS') '.json']; + end + end + filename = fullfile(pwd, filename); + + % get iterate: + solution = struct(); + for i=0:obj.N + solution.(['x_' num2str(i)]) = obj.get('x', i); + solution.(['lam_' num2str(i)]) = obj.get('lam', i); + solution.(['t_' num2str(i)]) = obj.get('t', i); + solution.(['sl_' num2str(i)]) = obj.get('sl', i); + solution.(['su_' num2str(i)]) = obj.get('su', i); + end + for i=0:obj.N-1 + solution.(['z_' num2str(i)]) = obj.get('z', i); + solution.(['u_' num2str(i)]) = obj.get('u', i); + solution.(['pi_' num2str(i)]) = obj.get('pi', i); + end + + acados_folder = getenv('ACADOS_INSTALL_DIR'); + addpath(fullfile(acados_folder, 'external', 'jsonlab')); + savejson('', solution, filename); + + json_string = savejson('', solution, 'ForceRootName', 0); + + fid = fopen(filename, 'w'); + if fid == -1, error('store_iterate: Cannot create JSON file'); end + fwrite(fid, json_string, 'char'); + fclose(fid); + + disp(['stored current iterate in ' filename]); + end + + + function [] = load_iterate(obj, filename) + %%% Loads the iterate stored in json file with filename into the ocp solver. + acados_folder = getenv('ACADOS_INSTALL_DIR'); + addpath(fullfile(acados_folder, 'external', 'jsonlab')); + filename = fullfile(pwd, filename); + + if ~exist(filename, 'file') + error(['load_iterate: failed, file does not exist: ' filename]) + end + + solution = loadjson(filename); + keys = fieldnames(solution); + + for k = 1:numel(keys) + key = keys{k}; + key_parts = strsplit(key, '_'); + field = key_parts{1}; + stage = key_parts{2}; + + val = solution.(key); + + % check if array is empty (can happen for z) + if numel(val) > 0 + obj.set(field, val, str2num(stage)) + end + end + end + + + % print + function print(varargin) + if nargin < 2 + field = 'stat'; + else + field = varargin{2}; + end + + obj = varargin{1}; + + if strcmp(field, 'stat') + stat = obj.get('stat'); + {%- if solver_options.nlp_solver_type == "SQP" %} + fprintf('\niter\tres_stat\tres_eq\t\tres_ineq\tres_comp\tqp_stat\tqp_iter\talpha'); + if size(stat,2)>8 + fprintf('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp'); + end + fprintf('\n'); + for jj=1:size(stat,1) + fprintf('%d\t%e\t%e\t%e\t%e\t%d\t%d\t%e', stat(jj,1), stat(jj,2), stat(jj,3), stat(jj,4), stat(jj,5), stat(jj,6), stat(jj,7), stat(jj, 8)); + if size(stat,2)>8 + fprintf('\t%e\t%e\t%e\t%e', stat(jj,9), stat(jj,10), stat(jj,11), stat(jj,12)); + end + fprintf('\n'); + end + fprintf('\n'); + {%- else %} + fprintf('\niter\tqp_status\tqp_iter'); + if size(stat,2)>3 + fprintf('\tqp_res_stat\tqp_res_eq\tqp_res_ineq\tqp_res_comp'); + end + fprintf('\n'); + for jj=1:size(stat,1) + fprintf('%d\t%d\t\t%d', stat(jj,1), stat(jj,2), stat(jj,3)); + if size(stat,2)>3 + fprintf('\t%e\t%e\t%e\t%e', stat(jj,4), stat(jj,5), stat(jj,6), stat(jj,7)); + end + fprintf('\n'); + end + {% endif %} + + else + fprintf('unsupported field in function print of acados_ocp.print, got %s', field); + keyboard + end + + end + + end % methods + +end % class + diff --git a/third_party/acados/acados_template/c_templates_tera/model.in.h b/third_party/acados/acados_template/c_templates_tera/model.in.h new file mode 100644 index 0000000000..e5059df9ff --- /dev/null +++ b/third_party/acados/acados_template/c_templates_tera/model.in.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#ifndef {{ model.name }}_MODEL +#define {{ model.name }}_MODEL + +#ifdef __cplusplus +extern "C" { +#endif + +{%- if solver_options.hessian_approx %} + {%- set hessian_approx = solver_options.hessian_approx %} +{%- elif solver_options.sens_hess %} + {%- set hessian_approx = "EXACT" %} +{%- else %} + {%- set hessian_approx = "GAUSS_NEWTON" %} +{%- endif %} + +{% if solver_options.integrator_type == "IRK" or solver_options.integrator_type == "LIFTED_IRK" %} + {% if model.dyn_ext_fun_type == "casadi" %} +// implicit ODE: function +int {{ model.name }}_impl_dae_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_impl_dae_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_impl_dae_fun_sparsity_in(int); +const int *{{ model.name }}_impl_dae_fun_sparsity_out(int); +int {{ model.name }}_impl_dae_fun_n_in(void); +int {{ model.name }}_impl_dae_fun_n_out(void); + +// implicit ODE: function + jacobians +int {{ model.name }}_impl_dae_fun_jac_x_xdot_z(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_impl_dae_fun_jac_x_xdot_z_work(int *, int *, int *, int *); +const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_in(int); +const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_z_sparsity_out(int); +int {{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_in(void); +int {{ model.name }}_impl_dae_fun_jac_x_xdot_z_n_out(void); + +// implicit ODE: jacobians only +int {{ model.name }}_impl_dae_jac_x_xdot_u_z(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_impl_dae_jac_x_xdot_u_z_work(int *, int *, int *, int *); +const int *{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_in(int); +const int *{{ model.name }}_impl_dae_jac_x_xdot_u_z_sparsity_out(int); +int {{ model.name }}_impl_dae_jac_x_xdot_u_z_n_in(void); +int {{ model.name }}_impl_dae_jac_x_xdot_u_z_n_out(void); + +// implicit ODE - for lifted_irk +int {{ model.name }}_impl_dae_fun_jac_x_xdot_u(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_impl_dae_fun_jac_x_xdot_u_work(int *, int *, int *, int *); +const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_u_sparsity_in(int); +const int *{{ model.name }}_impl_dae_fun_jac_x_xdot_u_sparsity_out(int); +int {{ model.name }}_impl_dae_fun_jac_x_xdot_u_n_in(void); +int {{ model.name }}_impl_dae_fun_jac_x_xdot_u_n_out(void); + + {%- if hessian_approx == "EXACT" %} +// implicit ODE - hessian +int {{ model.name }}_impl_dae_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_impl_dae_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_impl_dae_hess_sparsity_in(int); +const int *{{ model.name }}_impl_dae_hess_sparsity_out(int); +int {{ model.name }}_impl_dae_hess_n_in(void); +int {{ model.name }}_impl_dae_hess_n_out(void); + {% endif %} + {% else %}{# ext_fun_type #} + {%- if hessian_approx == "EXACT" %} +int {{ model.dyn_impl_dae_hess }}(void **, void **, void *); + {% endif %} +int {{ model.dyn_impl_dae_fun_jac }}(void **, void **, void *); +int {{ model.dyn_impl_dae_jac }}(void **, void **, void *); +int {{ model.dyn_impl_dae_fun }}(void **, void **, void *); + {% endif %}{# ext_fun_type #} + +{% elif solver_options.integrator_type == "GNSF" %} +/* GNSF Functions */ + {% if model.gnsf.purely_linear != 1 %} +// phi_fun +int {{ model.name }}_gnsf_phi_fun(const double** arg, double** res, int* iw, double* w, void *mem); +int {{ model.name }}_gnsf_phi_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_gnsf_phi_fun_sparsity_in(int); +const int *{{ model.name }}_gnsf_phi_fun_sparsity_out(int); +int {{ model.name }}_gnsf_phi_fun_n_in(void); +int {{ model.name }}_gnsf_phi_fun_n_out(void); + +// phi_fun_jac_y +int {{ model.name }}_gnsf_phi_fun_jac_y(const double** arg, double** res, int* iw, double* w, void *mem); +int {{ model.name }}_gnsf_phi_fun_jac_y_work(int *, int *, int *, int *); +const int *{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_in(int); +const int *{{ model.name }}_gnsf_phi_fun_jac_y_sparsity_out(int); +int {{ model.name }}_gnsf_phi_fun_jac_y_n_in(void); +int {{ model.name }}_gnsf_phi_fun_jac_y_n_out(void); + +// phi_jac_y_uhat +int {{ model.name }}_gnsf_phi_jac_y_uhat(const double** arg, double** res, int* iw, double* w, void *mem); +int {{ model.name }}_gnsf_phi_jac_y_uhat_work(int *, int *, int *, int *); +const int *{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_in(int); +const int *{{ model.name }}_gnsf_phi_jac_y_uhat_sparsity_out(int); +int {{ model.name }}_gnsf_phi_jac_y_uhat_n_in(void); +int {{ model.name }}_gnsf_phi_jac_y_uhat_n_out(void); + {% if model.gnsf.nontrivial_f_LO == 1 %} +// f_lo_fun_jac_x1k1uz +int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz(const double** arg, double** res, int* iw, double* w, void *mem); +int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_work(int *, int *, int *, int *); +const int *{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_in(int); +const int *{{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_sparsity_out(int); +int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_in(void); +int {{ model.name }}_gnsf_f_lo_fun_jac_x1k1uz_n_out(void); + {%- endif %} + {%- endif %} +// used to import model matrices +int {{ model.name }}_gnsf_get_matrices_fun(const double** arg, double** res, int* iw, double* w, void *mem); +int {{ model.name }}_gnsf_get_matrices_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_gnsf_get_matrices_fun_sparsity_in(int); +const int *{{ model.name }}_gnsf_get_matrices_fun_sparsity_out(int); +int {{ model.name }}_gnsf_get_matrices_fun_n_in(void); +int {{ model.name }}_gnsf_get_matrices_fun_n_out(void); + +{% elif solver_options.integrator_type == "ERK" %} +/* explicit ODE */ + +// explicit ODE +int {{ model.name }}_expl_ode_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_expl_ode_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_expl_ode_fun_sparsity_in(int); +const int *{{ model.name }}_expl_ode_fun_sparsity_out(int); +int {{ model.name }}_expl_ode_fun_n_in(void); +int {{ model.name }}_expl_ode_fun_n_out(void); + +// explicit forward VDE +int {{ model.name }}_expl_vde_forw(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_expl_vde_forw_work(int *, int *, int *, int *); +const int *{{ model.name }}_expl_vde_forw_sparsity_in(int); +const int *{{ model.name }}_expl_vde_forw_sparsity_out(int); +int {{ model.name }}_expl_vde_forw_n_in(void); +int {{ model.name }}_expl_vde_forw_n_out(void); + +// explicit adjoint VDE +int {{ model.name }}_expl_vde_adj(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_expl_vde_adj_work(int *, int *, int *, int *); +const int *{{ model.name }}_expl_vde_adj_sparsity_in(int); +const int *{{ model.name }}_expl_vde_adj_sparsity_out(int); +int {{ model.name }}_expl_vde_adj_n_in(void); +int {{ model.name }}_expl_vde_adj_n_out(void); + +{%- if hessian_approx == "EXACT" %} +int {{ model.name }}_expl_ode_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_expl_ode_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_expl_ode_hess_sparsity_in(int); +const int *{{ model.name }}_expl_ode_hess_sparsity_out(int); +int {{ model.name }}_expl_ode_hess_n_in(void); +int {{ model.name }}_expl_ode_hess_n_out(void); +{%- endif %} + +{% elif solver_options.integrator_type == "DISCRETE" %} + +{% if model.dyn_ext_fun_type == "casadi" %} +int {{ model.name }}_dyn_disc_phi_fun(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_dyn_disc_phi_fun_work(int *, int *, int *, int *); +const int *{{ model.name }}_dyn_disc_phi_fun_sparsity_in(int); +const int *{{ model.name }}_dyn_disc_phi_fun_sparsity_out(int); +int {{ model.name }}_dyn_disc_phi_fun_n_in(void); +int {{ model.name }}_dyn_disc_phi_fun_n_out(void); + +int {{ model.name }}_dyn_disc_phi_fun_jac(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_dyn_disc_phi_fun_jac_work(int *, int *, int *, int *); +const int *{{ model.name }}_dyn_disc_phi_fun_jac_sparsity_in(int); +const int *{{ model.name }}_dyn_disc_phi_fun_jac_sparsity_out(int); +int {{ model.name }}_dyn_disc_phi_fun_jac_n_in(void); +int {{ model.name }}_dyn_disc_phi_fun_jac_n_out(void); + +{%- if hessian_approx == "EXACT" %} +int {{ model.name }}_dyn_disc_phi_fun_jac_hess(const real_t** arg, real_t** res, int* iw, real_t* w, void *mem); +int {{ model.name }}_dyn_disc_phi_fun_jac_hess_work(int *, int *, int *, int *); +const int *{{ model.name }}_dyn_disc_phi_fun_jac_hess_sparsity_in(int); +const int *{{ model.name }}_dyn_disc_phi_fun_jac_hess_sparsity_out(int); +int {{ model.name }}_dyn_disc_phi_fun_jac_hess_n_in(void); +int {{ model.name }}_dyn_disc_phi_fun_jac_hess_n_out(void); +{%- endif %} +{% else %} + {%- if hessian_approx == "EXACT" %} +int {{ model.dyn_disc_fun_jac_hess }}(void **, void **, void *); + {% endif %} +int {{ model.dyn_disc_fun_jac }}(void **, void **, void *); +int {{ model.dyn_disc_fun }}(void **, void **, void *); +{% endif %} + + +{% endif %} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // {{ model.name }}_MODEL diff --git a/third_party/acados/acados_template/casadi_function_generation.py b/third_party/acados/acados_template/casadi_function_generation.py new file mode 100644 index 0000000000..6373a2809d --- /dev/null +++ b/third_party/acados/acados_template/casadi_function_generation.py @@ -0,0 +1,708 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import os +import casadi as ca +from .utils import is_empty, casadi_length + + +def get_casadi_symbol(x): + if isinstance(x, ca.MX): + return ca.MX.sym + elif isinstance(x, ca.SX): + return ca.SX.sym + else: + raise TypeError("Expected casadi SX or MX.") + +################ +# Dynamics +################ + + +def generate_c_code_discrete_dynamics( model, opts ): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + # load model + x = model.x + u = model.u + p = model.p + phi = model.disc_dyn_expr + model_name = model.name + nx = casadi_length(x) + + symbol = get_casadi_symbol(x) + # assume nx1 = nx !!! + lam = symbol('lam', nx, 1) + + # generate jacobians + ux = ca.vertcat(u,x) + jac_ux = ca.jacobian(phi, ux) + # generate adjoint + adj_ux = ca.jtimes(phi, ux, lam, True) + # generate hessian + hess_ux = ca.jacobian(adj_ux, ux) + + # change directory + cwd = os.getcwd() + model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) + if not os.path.exists(model_dir): + os.makedirs(model_dir) + os.chdir(model_dir) + + # set up & generate ca.Functions + fun_name = model_name + '_dyn_disc_phi_fun' + phi_fun = ca.Function(fun_name, [x, u, p], [phi]) + phi_fun.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_dyn_disc_phi_fun_jac' + phi_fun_jac_ut_xt = ca.Function(fun_name, [x, u, p], [phi, jac_ux.T]) + phi_fun_jac_ut_xt.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_dyn_disc_phi_fun_jac_hess' + phi_fun_jac_ut_xt_hess = ca.Function(fun_name, [x, u, lam, p], [phi, jac_ux.T, hess_ux]) + phi_fun_jac_ut_xt_hess.generate(fun_name, casadi_codegen_opts) + + os.chdir(cwd) + return + + + +def generate_c_code_explicit_ode( model, opts ): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + generate_hess = opts["generate_hess"] + + # load model + x = model.x + u = model.u + p = model.p + f_expl = model.f_expl_expr + model_name = model.name + + ## get model dimensions + nx = x.size()[0] + nu = u.size()[0] + + symbol = get_casadi_symbol(x) + + ## set up functions to be exported + Sx = symbol('Sx', nx, nx) + Sp = symbol('Sp', nx, nu) + lambdaX = symbol('lambdaX', nx, 1) + + fun_name = model_name + '_expl_ode_fun' + + ## Set up functions + expl_ode_fun = ca.Function(fun_name, [x, u, p], [f_expl]) + + vdeX = ca.jtimes(f_expl,x,Sx) + vdeP = ca.jacobian(f_expl,u) + ca.jtimes(f_expl,x,Sp) + + fun_name = model_name + '_expl_vde_forw' + + expl_vde_forw = ca.Function(fun_name, [x, Sx, Sp, u, p], [f_expl, vdeX, vdeP]) + + adj = ca.jtimes(f_expl, ca.vertcat(x, u), lambdaX, True) + + fun_name = model_name + '_expl_vde_adj' + expl_vde_adj = ca.Function(fun_name, [x, lambdaX, u, p], [adj]) + + if generate_hess: + S_forw = ca.vertcat(ca.horzcat(Sx, Sp), ca.horzcat(ca.DM.zeros(nu,nx), ca.DM.eye(nu))) + hess = ca.mtimes(ca.transpose(S_forw),ca.jtimes(adj, ca.vertcat(x,u), S_forw)) + hess2 = [] + for j in range(nx+nu): + for i in range(j,nx+nu): + hess2 = ca.vertcat(hess2, hess[i,j]) + + fun_name = model_name + '_expl_ode_hess' + expl_ode_hess = ca.Function(fun_name, [x, Sx, Sp, lambdaX, u, p], [adj, hess2]) + + # change directory + cwd = os.getcwd() + model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) + if not os.path.exists(model_dir): + os.makedirs(model_dir) + os.chdir(model_dir) + + # generate C code + fun_name = model_name + '_expl_ode_fun' + expl_ode_fun.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_expl_vde_forw' + expl_vde_forw.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_expl_vde_adj' + expl_vde_adj.generate(fun_name, casadi_codegen_opts) + + if generate_hess: + fun_name = model_name + '_expl_ode_hess' + expl_ode_hess.generate(fun_name, casadi_codegen_opts) + os.chdir(cwd) + + return + + +def generate_c_code_implicit_ode( model, opts ): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + # load model + x = model.x + xdot = model.xdot + u = model.u + z = model.z + p = model.p + f_impl = model.f_impl_expr + model_name = model.name + + # get model dimensions + nx = casadi_length(x) + nz = casadi_length(z) + + # generate jacobians + jac_x = ca.jacobian(f_impl, x) + jac_xdot = ca.jacobian(f_impl, xdot) + jac_u = ca.jacobian(f_impl, u) + jac_z = ca.jacobian(f_impl, z) + + # Set up functions + p = model.p + fun_name = model_name + '_impl_dae_fun' + impl_dae_fun = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl]) + + fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' + impl_dae_fun_jac_x_xdot_z = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_z]) + + fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z' + impl_dae_fun_jac_x_xdot_u_z = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u, jac_z]) + + fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u' + impl_dae_fun_jac_x_xdot_u = ca.Function(fun_name, [x, xdot, u, z, p], [f_impl, jac_x, jac_xdot, jac_u]) + + fun_name = model_name + '_impl_dae_jac_x_xdot_u_z' + impl_dae_jac_x_xdot_u_z = ca.Function(fun_name, [x, xdot, u, z, p], [jac_x, jac_xdot, jac_u, jac_z]) + + if opts["generate_hess"]: + x_xdot_z_u = ca.vertcat(x, xdot, z, u) + symbol = get_casadi_symbol(x) + multiplier = symbol('multiplier', nx + nz) + ADJ = ca.jtimes(f_impl, x_xdot_z_u, multiplier, True) + HESS = ca.jacobian(ADJ, x_xdot_z_u) + fun_name = model_name + '_impl_dae_hess' + impl_dae_hess = ca.Function(fun_name, [x, xdot, u, z, multiplier, p], [HESS]) + + # change directory + cwd = os.getcwd() + model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) + if not os.path.exists(model_dir): + os.makedirs(model_dir) + os.chdir(model_dir) + + # generate C code + fun_name = model_name + '_impl_dae_fun' + impl_dae_fun.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_impl_dae_fun_jac_x_xdot_z' + impl_dae_fun_jac_x_xdot_z.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_impl_dae_jac_x_xdot_u_z' + impl_dae_jac_x_xdot_u_z.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u_z' + impl_dae_fun_jac_x_xdot_u_z.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_impl_dae_fun_jac_x_xdot_u' + impl_dae_fun_jac_x_xdot_u.generate(fun_name, casadi_codegen_opts) + + if opts["generate_hess"]: + fun_name = model_name + '_impl_dae_hess' + impl_dae_hess.generate(fun_name, casadi_codegen_opts) + + os.chdir(cwd) + return + + +def generate_c_code_gnsf( model, opts ): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + model_name = model.name + + # set up directory + cwd = os.getcwd() + model_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model_name}_model')) + if not os.path.exists(model_dir): + os.makedirs(model_dir) + os.chdir(model_dir) + + # obtain gnsf dimensions + get_matrices_fun = model.get_matrices_fun + phi_fun = model.phi_fun + + size_gnsf_A = get_matrices_fun.size_out(0) + gnsf_nx1 = size_gnsf_A[1] + gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1] + gnsf_nuhat = max(phi_fun.size_in(1)) + gnsf_ny = max(phi_fun.size_in(0)) + gnsf_nout = max(phi_fun.size_out(0)) + + # set up expressions + # if the model uses ca.MX because of cost/constraints + # the DAE can be exported as ca.SX -> detect GNSF in Matlab + # -> evaluated ca.SX GNSF functions with ca.MX. + u = model.u + symbol = get_casadi_symbol(u) + + y = symbol("y", gnsf_ny, 1) + uhat = symbol("uhat", gnsf_nuhat, 1) + p = model.p + x1 = symbol("gnsf_x1", gnsf_nx1, 1) + x1dot = symbol("gnsf_x1dot", gnsf_nx1, 1) + z1 = symbol("gnsf_z1", gnsf_nz1, 1) + dummy = symbol("gnsf_dummy", 1, 1) + empty_var = symbol("gnsf_empty_var", 0, 0) + + ## generate C code + fun_name = model_name + '_gnsf_phi_fun' + phi_fun_ = ca.Function(fun_name, [y, uhat, p], [phi_fun(y, uhat, p)]) + phi_fun_.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_gnsf_phi_fun_jac_y' + phi_fun_jac_y = model.phi_fun_jac_y + phi_fun_jac_y_ = ca.Function(fun_name, [y, uhat, p], phi_fun_jac_y(y, uhat, p)) + phi_fun_jac_y_.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_gnsf_phi_jac_y_uhat' + phi_jac_y_uhat = model.phi_jac_y_uhat + phi_jac_y_uhat_ = ca.Function(fun_name, [y, uhat, p], phi_jac_y_uhat(y, uhat, p)) + phi_jac_y_uhat_.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_gnsf_f_lo_fun_jac_x1k1uz' + f_lo_fun_jac_x1k1uz = model.f_lo_fun_jac_x1k1uz + f_lo_fun_jac_x1k1uz_eval = f_lo_fun_jac_x1k1uz(x1, x1dot, z1, u, p) + + # avoid codegeneration issue + if not isinstance(f_lo_fun_jac_x1k1uz_eval, tuple) and is_empty(f_lo_fun_jac_x1k1uz_eval): + f_lo_fun_jac_x1k1uz_eval = [empty_var] + + f_lo_fun_jac_x1k1uz_ = ca.Function(fun_name, [x1, x1dot, z1, u, p], + f_lo_fun_jac_x1k1uz_eval) + f_lo_fun_jac_x1k1uz_.generate(fun_name, casadi_codegen_opts) + + fun_name = model_name + '_gnsf_get_matrices_fun' + get_matrices_fun_ = ca.Function(fun_name, [dummy], get_matrices_fun(1)) + get_matrices_fun_.generate(fun_name, casadi_codegen_opts) + + # remove fields for json dump + del model.phi_fun + del model.phi_fun_jac_y + del model.phi_jac_y_uhat + del model.f_lo_fun_jac_x1k1uz + del model.get_matrices_fun + + os.chdir(cwd) + + return + + +################ +# Cost +################ + +def generate_c_code_external_cost(model, stage_type, opts): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + x = model.x + p = model.p + u = model.u + z = model.z + symbol = get_casadi_symbol(x) + + if stage_type == 'terminal': + suffix_name = "_cost_ext_cost_e_fun" + suffix_name_hess = "_cost_ext_cost_e_fun_jac_hess" + suffix_name_jac = "_cost_ext_cost_e_fun_jac" + ext_cost = model.cost_expr_ext_cost_e + custom_hess = model.cost_expr_ext_cost_custom_hess_e + # Last stage cannot depend on u and z + u = symbol("u", 0, 0) + z = symbol("z", 0, 0) + + elif stage_type == 'path': + suffix_name = "_cost_ext_cost_fun" + suffix_name_hess = "_cost_ext_cost_fun_jac_hess" + suffix_name_jac = "_cost_ext_cost_fun_jac" + ext_cost = model.cost_expr_ext_cost + custom_hess = model.cost_expr_ext_cost_custom_hess + + elif stage_type == 'initial': + suffix_name = "_cost_ext_cost_0_fun" + suffix_name_hess = "_cost_ext_cost_0_fun_jac_hess" + suffix_name_jac = "_cost_ext_cost_0_fun_jac" + ext_cost = model.cost_expr_ext_cost_0 + custom_hess = model.cost_expr_ext_cost_custom_hess_0 + + nunx = x.shape[0] + u.shape[0] + + # set up functions to be exported + fun_name = model.name + suffix_name + fun_name_hess = model.name + suffix_name_hess + fun_name_jac = model.name + suffix_name_jac + + # generate expression for full gradient and Hessian + hess_uxz, grad_uxz = ca.hessian(ext_cost, ca.vertcat(u, x, z)) + + hess_ux = hess_uxz[:nunx, :nunx] + hess_z = hess_uxz[nunx:, nunx:] + hess_z_ux = hess_uxz[nunx:, :nunx] + + if custom_hess is not None: + hess_ux = custom_hess + + ext_cost_fun = ca.Function(fun_name, [x, u, z, p], [ext_cost]) + + ext_cost_fun_jac_hess = ca.Function( + fun_name_hess, [x, u, z, p], [ext_cost, grad_uxz, hess_ux, hess_z, hess_z_ux] + ) + ext_cost_fun_jac = ca.Function( + fun_name_jac, [x, u, z, p], [ext_cost, grad_uxz] + ) + + # change directory + cwd = os.getcwd() + cost_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_cost')) + if not os.path.exists(cost_dir): + os.makedirs(cost_dir) + os.chdir(cost_dir) + + ext_cost_fun.generate(fun_name, casadi_codegen_opts) + ext_cost_fun_jac_hess.generate(fun_name_hess, casadi_codegen_opts) + ext_cost_fun_jac.generate(fun_name_jac, casadi_codegen_opts) + + os.chdir(cwd) + return + + +def generate_c_code_nls_cost( model, cost_name, stage_type, opts ): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + x = model.x + z = model.z + p = model.p + u = model.u + + symbol = get_casadi_symbol(x) + + if stage_type == 'terminal': + middle_name = '_cost_y_e' + u = symbol('u', 0, 0) + y_expr = model.cost_y_expr_e + + elif stage_type == 'initial': + middle_name = '_cost_y_0' + y_expr = model.cost_y_expr_0 + + elif stage_type == 'path': + middle_name = '_cost_y' + y_expr = model.cost_y_expr + + # change directory + cwd = os.getcwd() + cost_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_cost')) + if not os.path.exists(cost_dir): + os.makedirs(cost_dir) + os.chdir(cost_dir) + + # set up expressions + cost_jac_expr = ca.transpose(ca.jacobian(y_expr, ca.vertcat(u, x))) + dy_dz = ca.jacobian(y_expr, z) + ny = casadi_length(y_expr) + + y = symbol('y', ny, 1) + + y_adj = ca.jtimes(y_expr, ca.vertcat(u, x), y, True) + y_hess = ca.jacobian(y_adj, ca.vertcat(u, x)) + + ## generate C code + suffix_name = '_fun' + fun_name = cost_name + middle_name + suffix_name + y_fun = ca.Function( fun_name, [x, u, z, p], [ y_expr ]) + y_fun.generate( fun_name, casadi_codegen_opts ) + + suffix_name = '_fun_jac_ut_xt' + fun_name = cost_name + middle_name + suffix_name + y_fun_jac_ut_xt = ca.Function(fun_name, [x, u, z, p], [ y_expr, cost_jac_expr, dy_dz ]) + y_fun_jac_ut_xt.generate( fun_name, casadi_codegen_opts ) + + suffix_name = '_hess' + fun_name = cost_name + middle_name + suffix_name + y_hess = ca.Function(fun_name, [x, u, z, y, p], [ y_hess ]) + y_hess.generate( fun_name, casadi_codegen_opts ) + + os.chdir(cwd) + + return + + + +def generate_c_code_conl_cost(model, cost_name, stage_type, opts): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + x = model.x + z = model.z + p = model.p + + symbol = get_casadi_symbol(x) + + if stage_type == 'terminal': + u = symbol('u', 0, 0) + + yref = model.cost_r_in_psi_expr_e + inner_expr = model.cost_y_expr_e - yref + outer_expr = model.cost_psi_expr_e + res_expr = model.cost_r_in_psi_expr_e + + suffix_name_fun = '_conl_cost_e_fun' + suffix_name_fun_jac_hess = '_conl_cost_e_fun_jac_hess' + + custom_hess = model.cost_conl_custom_outer_hess_e + + elif stage_type == 'initial': + u = model.u + + yref = model.cost_r_in_psi_expr_0 + inner_expr = model.cost_y_expr_0 - yref + outer_expr = model.cost_psi_expr_0 + res_expr = model.cost_r_in_psi_expr_0 + + suffix_name_fun = '_conl_cost_0_fun' + suffix_name_fun_jac_hess = '_conl_cost_0_fun_jac_hess' + + custom_hess = model.cost_conl_custom_outer_hess_0 + + elif stage_type == 'path': + u = model.u + + yref = model.cost_r_in_psi_expr + inner_expr = model.cost_y_expr - yref + outer_expr = model.cost_psi_expr + res_expr = model.cost_r_in_psi_expr + + suffix_name_fun = '_conl_cost_fun' + suffix_name_fun_jac_hess = '_conl_cost_fun_jac_hess' + + custom_hess = model.cost_conl_custom_outer_hess + + # set up function names + fun_name_cost_fun = model.name + suffix_name_fun + fun_name_cost_fun_jac_hess = model.name + suffix_name_fun_jac_hess + + # set up functions to be exported + outer_loss_fun = ca.Function('psi', [res_expr, p], [outer_expr]) + cost_expr = outer_loss_fun(inner_expr, p) + + outer_loss_grad_fun = ca.Function('outer_loss_grad', [res_expr, p], [ca.jacobian(outer_expr, res_expr).T]) + + if custom_hess is None: + outer_hess_fun = ca.Function('inner_hess', [res_expr, p], [ca.hessian(outer_loss_fun(res_expr, p), res_expr)[0]]) + else: + outer_hess_fun = ca.Function('inner_hess', [res_expr, p], [custom_hess]) + + Jt_ux_expr = ca.jacobian(inner_expr, ca.vertcat(u, x)).T + Jt_z_expr = ca.jacobian(inner_expr, z).T + + cost_fun = ca.Function( + fun_name_cost_fun, + [x, u, z, yref, p], + [cost_expr]) + + cost_fun_jac_hess = ca.Function( + fun_name_cost_fun_jac_hess, + [x, u, z, yref, p], + [cost_expr, outer_loss_grad_fun(inner_expr, p), Jt_ux_expr, Jt_z_expr, outer_hess_fun(inner_expr, p)] + ) + # change directory + cwd = os.getcwd() + cost_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_cost')) + if not os.path.exists(cost_dir): + os.makedirs(cost_dir) + os.chdir(cost_dir) + + # generate C code + cost_fun.generate(fun_name_cost_fun, casadi_codegen_opts) + cost_fun_jac_hess.generate(fun_name_cost_fun_jac_hess, casadi_codegen_opts) + + os.chdir(cwd) + + return + + +################ +# Constraints +################ +def generate_c_code_constraint( model, con_name, is_terminal, opts ): + + casadi_codegen_opts = dict(mex=False, casadi_int='int', casadi_real='double') + + # load constraint variables and expression + x = model.x + p = model.p + + symbol = get_casadi_symbol(x) + + if is_terminal: + con_h_expr = model.con_h_expr_e + con_phi_expr = model.con_phi_expr_e + # create dummy u, z + u = symbol('u', 0, 0) + z = symbol('z', 0, 0) + else: + con_h_expr = model.con_h_expr + con_phi_expr = model.con_phi_expr + u = model.u + z = model.z + + if (not is_empty(con_h_expr)) and (not is_empty(con_phi_expr)): + raise Exception("acados: you can either have constraint_h, or constraint_phi, not both.") + + if (is_empty(con_h_expr) and is_empty(con_phi_expr)): + # both empty -> nothing to generate + return + + if is_empty(con_h_expr): + constr_type = 'BGP' + else: + constr_type = 'BGH' + + if is_empty(p): + p = symbol('p', 0, 0) + + if is_empty(z): + z = symbol('z', 0, 0) + + if not (is_empty(con_h_expr)) and opts['generate_hess']: + # multipliers for hessian + nh = casadi_length(con_h_expr) + lam_h = symbol('lam_h', nh, 1) + + # set up & change directory + cwd = os.getcwd() + constraints_dir = os.path.abspath(os.path.join(opts["code_export_directory"], f'{model.name}_constraints')) + if not os.path.exists(constraints_dir): + os.makedirs(constraints_dir) + os.chdir(constraints_dir) + + # export casadi functions + if constr_type == 'BGH': + if is_terminal: + fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt' + else: + fun_name = con_name + '_constr_h_fun_jac_uxt_zt' + + jac_ux_t = ca.transpose(ca.jacobian(con_h_expr, ca.vertcat(u,x))) + jac_z_t = ca.jacobian(con_h_expr, z) + constraint_fun_jac_tran = ca.Function(fun_name, [x, u, z, p], \ + [con_h_expr, jac_ux_t, jac_z_t]) + + constraint_fun_jac_tran.generate(fun_name, casadi_codegen_opts) + if opts['generate_hess']: + + if is_terminal: + fun_name = con_name + '_constr_h_e_fun_jac_uxt_zt_hess' + else: + fun_name = con_name + '_constr_h_fun_jac_uxt_zt_hess' + + # adjoint + adj_ux = ca.jtimes(con_h_expr, ca.vertcat(u, x), lam_h, True) + # hessian + hess_ux = ca.jacobian(adj_ux, ca.vertcat(u, x)) + + adj_z = ca.jtimes(con_h_expr, z, lam_h, True) + hess_z = ca.jacobian(adj_z, z) + + # set up functions + constraint_fun_jac_tran_hess = \ + ca.Function(fun_name, [x, u, lam_h, z, p], \ + [con_h_expr, jac_ux_t, hess_ux, jac_z_t, hess_z]) + + # generate C code + constraint_fun_jac_tran_hess.generate(fun_name, casadi_codegen_opts) + + if is_terminal: + fun_name = con_name + '_constr_h_e_fun' + else: + fun_name = con_name + '_constr_h_fun' + h_fun = ca.Function(fun_name, [x, u, z, p], [con_h_expr]) + h_fun.generate(fun_name, casadi_codegen_opts) + + else: # BGP constraint + if is_terminal: + fun_name = con_name + '_phi_e_constraint' + r = model.con_r_in_phi_e + con_r_expr = model.con_r_expr_e + else: + fun_name = con_name + '_phi_constraint' + r = model.con_r_in_phi + con_r_expr = model.con_r_expr + + nphi = casadi_length(con_phi_expr) + con_phi_expr_x_u_z = ca.substitute(con_phi_expr, r, con_r_expr) + phi_jac_u = ca.jacobian(con_phi_expr_x_u_z, u) + phi_jac_x = ca.jacobian(con_phi_expr_x_u_z, x) + phi_jac_z = ca.jacobian(con_phi_expr_x_u_z, z) + + hess = ca.hessian(con_phi_expr[0], r)[0] + for i in range(1, nphi): + hess = ca.vertcat(hess, ca.hessian(con_phi_expr[i], r)[0]) + + r_jac_u = ca.jacobian(con_r_expr, u) + r_jac_x = ca.jacobian(con_r_expr, x) + + constraint_phi = \ + ca.Function(fun_name, [x, u, z, p], \ + [con_phi_expr_x_u_z, \ + ca.vertcat(ca.transpose(phi_jac_u), ca.transpose(phi_jac_x)), \ + ca.transpose(phi_jac_z), \ + hess, + ca.vertcat(ca.transpose(r_jac_u), ca.transpose(r_jac_x))]) + + constraint_phi.generate(fun_name, casadi_codegen_opts) + + # change directory back + os.chdir(cwd) + + return + diff --git a/third_party/acados/acados_template/custom_update_templates/custom_update_function_zoro_template.in.c b/third_party/acados/acados_template/custom_update_templates/custom_update_function_zoro_template.in.c new file mode 100644 index 0000000000..b39ff2e23b --- /dev/null +++ b/third_party/acados/acados_template/custom_update_templates/custom_update_function_zoro_template.in.c @@ -0,0 +1,819 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +// This is a template based custom_update function +#include +#include +#include +#include + +#include "custom_update_function.h" +#include "acados_solver_{{ model.name }}.h" +#include "acados_c/ocp_nlp_interface.h" +#include "acados/utils/mem.h" + +#include "blasfeo/include/blasfeo_d_aux_ext_dep.h" +#include "blasfeo/include/blasfeo_d_blasfeo_api.h" + + +typedef struct custom_memory +{ + // covariance matrics + struct blasfeo_dmat *uncertainty_matrix_buffer; // shape = (N+1, nx, nx) + // covariance matrix of the additive disturbance + struct blasfeo_dmat W_mat; // shape = (nw, nw) + struct blasfeo_dmat unc_jac_G_mat; // shape = (nx, nw) + struct blasfeo_dmat temp_GW_mat; // shape = (nx, nw) + struct blasfeo_dmat GWG_mat; // shape = (nx, nx) + // sensitivity matrices + struct blasfeo_dmat A_mat; // shape = (nx, nx) + struct blasfeo_dmat B_mat; // shape = (nx, nu) + // matrix in linear constraints + struct blasfeo_dmat Cg_mat; // shape = (ng, nx) + struct blasfeo_dmat Dg_mat; // shape = (ng, nu) + struct blasfeo_dmat Cg_e_mat; // shape = (ng_e, nx) + struct blasfeo_dmat dummy_Dgh_e_mat; // shape = (ngh_e_max, nu) + // matrix in nonlinear constraints + struct blasfeo_dmat Ch_mat; // shape = (nh, nx) + struct blasfeo_dmat Dh_mat; // shape = (nh, nu) + struct blasfeo_dmat Ch_e_mat; // shape = (nh_e, nx) + // feedback gain matrix + struct blasfeo_dmat K_mat; // shape = (nu, nx) + // AK = A - B@K + struct blasfeo_dmat AK_mat; // shape = (nx, nx) + // A@P_k + struct blasfeo_dmat temp_AP_mat; // shape = (nx, nx) + // K@P_k, K@P_k@K^T + struct blasfeo_dmat temp_KP_mat; // shape = (nu, nx) + struct blasfeo_dmat temp_KPK_mat; // shape = (nu, nu) + // C + D @ K, (C + D @ K) @ P_k + struct blasfeo_dmat temp_CaDK_mat; // shape = (ngh_me_max, nx) + struct blasfeo_dmat temp_CaDKmP_mat; // shape = (ngh_me_max, nx) + struct blasfeo_dmat temp_beta_mat; // shape = (ngh_me_max, ngh_me_max) + + double *d_A_mat; // shape = (nx, nx) + double *d_B_mat; // shape = (nx, nu) + double *d_Cg_mat; // shape = (ng, nx) + double *d_Dg_mat; // shape = (ng, nu) + double *d_Cg_e_mat; // shape = (ng_e, nx) + double *d_Cgh_mat; // shape = (ng+nh, nx) + double *d_Dgh_mat; // shape = (ng+nh, nu) + double *d_Cgh_e_mat; // shape = (ng_e+nh_e, nx) + double *d_state_vec; + // upper and lower bounds on state variables + double *d_lbx; // shape = (nbx,) + double *d_ubx; // shape = (nbx,) + double *d_lbx_e; // shape = (nbx_e,) + double *d_ubx_e; // shape = (nbx_e,) + // tightened upper and lower bounds on state variables + double *d_lbx_tightened; // shape = (nbx,) + double *d_ubx_tightened; // shape = (nbx,) + double *d_lbx_e_tightened; // shape = (nbx_e,) + double *d_ubx_e_tightened; // shape = (nbx_e,) + // upper and lower bounds on control inputs + double *d_lbu; // shape = (nbu,) + double *d_ubu; // shape = (nbu,) + // tightened upper and lower bounds on control inputs + double *d_lbu_tightened; // shape = (nbu,) + double *d_ubu_tightened; // shape = (nbu,) + // upper and lower bounds on polytopic constraints + double *d_lg; // shape = (ng,) + double *d_ug; // shape = (ng,) + double *d_lg_e; // shape = (ng_e,) + double *d_ug_e; // shape = (ng_e,) + // tightened lower bounds on polytopic constraints + double *d_lg_tightened; // shape = (ng,) + double *d_ug_tightened; // shape = (ng,) + double *d_lg_e_tightened; // shape = (ng_e,) + double *d_ug_e_tightened; // shape = (ng_e,) + // upper and lower bounds on nonlinear constraints + double *d_lh; // shape = (nh,) + double *d_uh; // shape = (nh,) + double *d_lh_e; // shape = (nh_e,) + double *d_uh_e; // shape = (nh_e,) + // tightened upper and lower bounds on nonlinear constraints + double *d_lh_tightened; // shape = (nh,) + double *d_uh_tightened; // shape = (nh,) + double *d_lh_e_tightened; // shape = (nh_e,) + double *d_uh_e_tightened; // shape = (nh_e,) + + int *idxbx; // shape = (nbx,) + int *idxbu; // shape = (nbu,) + int *idxbx_e; // shape = (nbx_e,) + + void *raw_memory; // Pointer to allocated memory, to be used for freeing +} custom_memory; + +static int int_max(int num1, int num2) +{ + return (num1 > num2 ) ? num1 : num2; +} + + +static int custom_memory_calculate_size(ocp_nlp_config *nlp_config, ocp_nlp_dims *nlp_dims) +{ + int N = nlp_dims->N; + int nx = {{ dims.nx }}; + int nu = {{ dims.nu }}; + int nw = {{ zoro_description.nw }}; + + int ng = {{ dims.ng }}; + int nh = {{ dims.nh }}; + int nbx = {{ dims.nbx }}; + int nbu = {{ dims.nbu }}; + + int ng_e = {{ dims.ng_e }}; + int nh_e = {{ dims.nh_e }}; + int ngh_e_max = int_max(ng_e, nh_e); + int ngh_me_max = int_max(ngh_e_max, int_max(ng, nh)); + int nbx_e = {{ dims.nbx_e }}; + + assert({{zoro_description.nlbx_t}} <= nbx); + assert({{zoro_description.nubx_t}} <= nbx); + assert({{zoro_description.nlbu_t}} <= nbu); + assert({{zoro_description.nubu_t}} <= nbu); + assert({{zoro_description.nlg_t}} <= ng); + assert({{zoro_description.nug_t}} <= ng); + assert({{zoro_description.nlh_t}} <= nh); + assert({{zoro_description.nuh_t}} <= nh); + assert({{zoro_description.nlbx_e_t}} <= nbx_e); + assert({{zoro_description.nubx_e_t}} <= nbx_e); + assert({{zoro_description.nlg_e_t}} <= ng_e); + assert({{zoro_description.nug_e_t}} <= ng_e); + assert({{zoro_description.nlh_e_t}} <= nh_e); + assert({{zoro_description.nuh_e_t}} <= nh_e); + + acados_size_t size = sizeof(custom_memory); + size += nbx * sizeof(int); + /* blasfeo structs */ + size += (N + 1) * sizeof(struct blasfeo_dmat); + /* blasfeo mem: mat */ + size += (N + 1) * blasfeo_memsize_dmat(nx, nx); // uncertainty_matrix_buffer + size += blasfeo_memsize_dmat(nw, nw); // W_mat + size += 2 * blasfeo_memsize_dmat(nx, nw); // unc_jac_G_mat, temp_GW_mat + size += 4 * blasfeo_memsize_dmat(nx, nx); // GWG_mat, A_mat, AK_mat, temp_AP_mat + size += blasfeo_memsize_dmat(nx, nu); // B_mat + size += 2 * blasfeo_memsize_dmat(nu, nx); // K_mat, temp_KP_mat + size += blasfeo_memsize_dmat(nu, nu); // temp_KPK_mat + size += blasfeo_memsize_dmat(ng, nx); // Cg_mat + size += blasfeo_memsize_dmat(ng, nu); // Dg_mat + size += blasfeo_memsize_dmat(ng_e, nx); // Cg_e_mat + size += blasfeo_memsize_dmat(ngh_e_max, nu); // dummy_Dgh_e_mat + size += blasfeo_memsize_dmat(nh, nx); // Ch_mat + size += blasfeo_memsize_dmat(nh, nu); // Dh_mat + size += blasfeo_memsize_dmat(nh_e, nx); // Ch_e_mat + size += 2 * blasfeo_memsize_dmat(ngh_me_max, nx); // temp_CaDK_mat, temp_CaDKmP_mat + size += blasfeo_memsize_dmat(ngh_me_max, ngh_me_max); // temp_beta_mat + /* blasfeo mem: vec */ + /* Arrays */ + size += nx*nx *sizeof(double); // d_A_mat + size += nx*nu *sizeof(double); // d_B_mat + size += (ng + ng_e) * nx * sizeof(double); // d_Cg_mat, d_Cg_e_mat + size += (ng) * nu * sizeof(double); // d_Dg_mat + size += (nh + nh_e + ng + ng_e) * nx * sizeof(double); // d_Cgh_mat, d_Cgh_e_mat + size += (nh + ng) * nu * sizeof(double); // d_Dgh_mat + // d_state_vec + size += nx *sizeof(double); + // constraints and tightened constraints + size += 4 * (nbx + nbu + ng + nh)*sizeof(double); + size += 4 * (nbx_e + ng_e + nh_e)*sizeof(double); + size += (nbx + nbu + nbx_e)*sizeof(int); // idxbx, idxbu, idxbx_e + + size += 1 * 8; // initial alignment + make_int_multiple_of(64, &size); + size += 1 * 64; + + return size; +} + + +static custom_memory *custom_memory_assign(ocp_nlp_config *nlp_config, ocp_nlp_dims *nlp_dims, void *raw_memory) +{ + int N = nlp_dims->N; + int nx = {{ dims.nx }}; + int nu = {{ dims.nu }}; + int nw = {{ zoro_description.nw }}; + + int ng = {{ dims.ng }}; + int nh = {{ dims.nh }}; + int nbx = {{ dims.nbx }}; + int nbu = {{ dims.nbu }}; + + int ng_e = {{ dims.ng_e }}; + int nh_e = {{ dims.nh_e }}; + int ngh_e_max = int_max(ng_e, nh_e); + int ngh_me_max = int_max(ngh_e_max, int_max(ng, nh)); + int nbx_e = {{ dims.nbx_e }}; + + char *c_ptr = (char *) raw_memory; + custom_memory *mem = (custom_memory *) c_ptr; + c_ptr += sizeof(custom_memory); + + align_char_to(8, &c_ptr); + assign_and_advance_blasfeo_dmat_structs(N+1, &mem->uncertainty_matrix_buffer, &c_ptr); + + align_char_to(64, &c_ptr); + + for (int ii = 0; ii <= N; ii++) + { + assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->uncertainty_matrix_buffer[ii], &c_ptr); + } + // Disturbance Dynamics + assign_and_advance_blasfeo_dmat_mem(nw, nw, &mem->W_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nx, nw, &mem->unc_jac_G_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nx, nw, &mem->temp_GW_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->GWG_mat, &c_ptr); + // System Dynamics + assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->A_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nx, nu, &mem->B_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ng, nx, &mem->Cg_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ng, nu, &mem->Dg_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ng_e, nx, &mem->Cg_e_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ngh_e_max, nu, &mem->dummy_Dgh_e_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nh, nx, &mem->Ch_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nh, nu, &mem->Dh_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nh_e, nx, &mem->Ch_e_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nu, nx, &mem->K_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->AK_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nx, nx, &mem->temp_AP_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nu, nx, &mem->temp_KP_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(nu, nu, &mem->temp_KPK_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ngh_me_max, nx, &mem->temp_CaDK_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ngh_me_max, nx, &mem->temp_CaDKmP_mat, &c_ptr); + assign_and_advance_blasfeo_dmat_mem(ngh_me_max, ngh_me_max, &mem->temp_beta_mat, &c_ptr); + + assign_and_advance_double(nx*nx, &mem->d_A_mat, &c_ptr); + assign_and_advance_double(nx*nu, &mem->d_B_mat, &c_ptr); + assign_and_advance_double(ng*nx, &mem->d_Cg_mat, &c_ptr); + assign_and_advance_double(ng*nu, &mem->d_Dg_mat, &c_ptr); + assign_and_advance_double(ng_e*nx, &mem->d_Cg_e_mat, &c_ptr); + assign_and_advance_double((ng + nh)*nx, &mem->d_Cgh_mat, &c_ptr); + assign_and_advance_double((ng + nh)*nu, &mem->d_Dgh_mat, &c_ptr); + assign_and_advance_double((ng_e + nh_e)*nx, &mem->d_Cgh_e_mat, &c_ptr); + assign_and_advance_double(nx, &mem->d_state_vec, &c_ptr); + assign_and_advance_double(nbx, &mem->d_lbx, &c_ptr); + assign_and_advance_double(nbx, &mem->d_ubx, &c_ptr); + assign_and_advance_double(nbx_e, &mem->d_lbx_e, &c_ptr); + assign_and_advance_double(nbx_e, &mem->d_ubx_e, &c_ptr); + assign_and_advance_double(nbx, &mem->d_lbx_tightened, &c_ptr); + assign_and_advance_double(nbx, &mem->d_ubx_tightened, &c_ptr); + assign_and_advance_double(nbx_e, &mem->d_lbx_e_tightened, &c_ptr); + assign_and_advance_double(nbx_e, &mem->d_ubx_e_tightened, &c_ptr); + assign_and_advance_double(nbu, &mem->d_lbu, &c_ptr); + assign_and_advance_double(nbu, &mem->d_ubu, &c_ptr); + assign_and_advance_double(nbu, &mem->d_lbu_tightened, &c_ptr); + assign_and_advance_double(nbu, &mem->d_ubu_tightened, &c_ptr); + assign_and_advance_double(ng, &mem->d_lg, &c_ptr); + assign_and_advance_double(ng, &mem->d_ug, &c_ptr); + assign_and_advance_double(ng_e, &mem->d_lg_e, &c_ptr); + assign_and_advance_double(ng_e, &mem->d_ug_e, &c_ptr); + assign_and_advance_double(ng, &mem->d_lg_tightened, &c_ptr); + assign_and_advance_double(ng, &mem->d_ug_tightened, &c_ptr); + assign_and_advance_double(ng_e, &mem->d_lg_e_tightened, &c_ptr); + assign_and_advance_double(ng_e, &mem->d_ug_e_tightened, &c_ptr); + assign_and_advance_double(nh, &mem->d_lh, &c_ptr); + assign_and_advance_double(nh, &mem->d_uh, &c_ptr); + assign_and_advance_double(nh_e, &mem->d_lh_e, &c_ptr); + assign_and_advance_double(nh_e, &mem->d_uh_e, &c_ptr); + assign_and_advance_double(nh, &mem->d_lh_tightened, &c_ptr); + assign_and_advance_double(nh, &mem->d_uh_tightened, &c_ptr); + assign_and_advance_double(nh_e, &mem->d_lh_e_tightened, &c_ptr); + assign_and_advance_double(nh_e, &mem->d_uh_e_tightened, &c_ptr); + + assign_and_advance_int(nbx, &mem->idxbx, &c_ptr); + assign_and_advance_int(nbu, &mem->idxbu, &c_ptr); + assign_and_advance_int(nbx_e, &mem->idxbx_e, &c_ptr); + + assert((char *) raw_memory + custom_memory_calculate_size(nlp_config, nlp_dims) >= c_ptr); + mem->raw_memory = raw_memory; + + return mem; +} + + + +static void *custom_memory_create({{ model.name }}_solver_capsule* capsule) +{ + printf("\nin custom_memory_create_function\n"); + + ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); + ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(capsule); + acados_size_t bytes = custom_memory_calculate_size(nlp_config, nlp_dims); + + void *ptr = acados_calloc(1, bytes); + + custom_memory *custom_mem = custom_memory_assign(nlp_config, nlp_dims, ptr); + custom_mem->raw_memory = ptr; + + return custom_mem; +} + + +static void custom_val_init_function(ocp_nlp_dims *nlp_dims, ocp_nlp_in *nlp_in, ocp_nlp_solver *nlp_solver, custom_memory *custom_mem) +{ + int N = nlp_dims->N; + int nx = {{ dims.nx }}; + int nu = {{ dims.nu }}; + int nw = {{ zoro_description.nw }}; + + int ng = {{ dims.ng }}; + int nh = {{ dims.nh }}; + int nbx = {{ dims.nbx }}; + int nbu = {{ dims.nbu }}; + + int ng_e = {{ dims.ng_e }}; + int nh_e = {{ dims.nh_e }}; + int ngh_e_max = int_max(ng_e, nh_e); + int nbx_e = {{ dims.nbx_e }}; + + /* Get the state constraint bounds */ + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "idxbx", custom_mem->idxbx); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "idxbx", custom_mem->idxbx_e); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbx", custom_mem->d_lbx); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubx", custom_mem->d_ubx); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lbx", custom_mem->d_lbx_e); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ubx", custom_mem->d_ubx_e); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "idxbu", custom_mem->idxbu); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbu", custom_mem->d_lbu); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubu", custom_mem->d_ubu); + // Get the Jacobians and the bounds of the linear constraints + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lg", custom_mem->d_lg); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ug", custom_mem->d_ug); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lg", custom_mem->d_lg_e); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ug", custom_mem->d_ug_e); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "C", custom_mem->d_Cg_mat); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "D", custom_mem->d_Dg_mat); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "C", custom_mem->d_Cg_e_mat); + blasfeo_pack_dmat(ng, nx, custom_mem->d_Cg_mat, ng, &custom_mem->Cg_mat, 0, 0); + blasfeo_pack_dmat(ng, nu, custom_mem->d_Dg_mat, ng, &custom_mem->Dg_mat, 0, 0); + blasfeo_pack_dmat(ng_e, nx, custom_mem->d_Cg_e_mat, ng_e, &custom_mem->Cg_e_mat, 0, 0); + blasfeo_dgese(ngh_e_max, nu, 0., &custom_mem->dummy_Dgh_e_mat, 0, 0); //fill with zeros + // NOTE: fixed lower and upper bounds of nonlinear constraints + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lh", custom_mem->d_lh); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "uh", custom_mem->d_uh); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lh", custom_mem->d_lh_e); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "uh", custom_mem->d_uh_e); + + /* Initilize tightened constraints*/ + // NOTE: tightened constraints are only initialized once + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbx", custom_mem->d_lbx_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubx", custom_mem->d_ubx_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lbx", custom_mem->d_lbx_e_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ubx", custom_mem->d_ubx_e_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lbu", custom_mem->d_lbu_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ubu", custom_mem->d_ubu_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lg", custom_mem->d_lg_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "ug", custom_mem->d_ug_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lg", custom_mem->d_lg_e_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "ug", custom_mem->d_ug_e_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "lh", custom_mem->d_lh_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, 1, "uh", custom_mem->d_uh_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "lh", custom_mem->d_lh_e_tightened); + ocp_nlp_constraints_model_get(nlp_solver->config, nlp_dims, nlp_in, N, "uh", custom_mem->d_uh_e_tightened); + + /* Initialize the W matrix */ + // blasfeo_dgese(nw, nw, 0., &custom_mem->W_mat, 0, 0); +{%- for ir in range(end=zoro_description.nw) %} + {%- for ic in range(end=zoro_description.nw) %} + blasfeo_dgein1({{zoro_description.W_mat[ir][ic]}}, &custom_mem->W_mat, {{ir}}, {{ic}}); + {%- endfor %} +{%- endfor %} + +{%- for ir in range(end=dims.nx) %} + {%- for ic in range(end=zoro_description.nw) %} + blasfeo_dgein1({{zoro_description.unc_jac_G_mat[ir][ic]}}, &custom_mem->unc_jac_G_mat, {{ir}}, {{ic}}); + {%- endfor %} +{%- endfor %} + + // NOTE: if G is changing this is not in init! + // temp_GW_mat = unc_jac_G_mat * W_mat + blasfeo_dgemm_nn(nx, nw, nw, 1.0, &custom_mem->unc_jac_G_mat, 0, 0, + &custom_mem->W_mat, 0, 0, 0.0, + &custom_mem->temp_GW_mat, 0, 0, &custom_mem->temp_GW_mat, 0, 0); + // GWG_mat = temp_GW_mat * unc_jac_G_mat^T + blasfeo_dgemm_nt(nx, nx, nw, 1.0, &custom_mem->temp_GW_mat, 0, 0, + &custom_mem->unc_jac_G_mat, 0, 0, 0.0, + &custom_mem->GWG_mat, 0, 0, &custom_mem->GWG_mat, 0, 0); + + /* Initialize the uncertainty_matrix_buffer[0] */ +{%- for ir in range(end=dims.nx) %} + {%- for ic in range(end=dims.nx) %} + blasfeo_dgein1({{zoro_description.P0_mat[ir][ic]}}, &custom_mem->uncertainty_matrix_buffer[0], {{ir}}, {{ic}}); + {%- endfor %} +{%- endfor %} + + /* Initialize the feedback gain matrix */ +{%- for ir in range(end=dims.nu) %} + {%- for ic in range(end=dims.nx) %} + blasfeo_dgein1({{zoro_description.fdbk_K_mat[ir][ic]}}, &custom_mem->K_mat, {{ir}}, {{ic}}); + {%- endfor %} +{%- endfor %} +} + + +int custom_update_init_function({{ model.name }}_solver_capsule* capsule) +{ + capsule->custom_update_memory = custom_memory_create(capsule); + ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(capsule); + + ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); + ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(capsule); + custom_val_init_function(nlp_dims, nlp_in, nlp_solver, capsule->custom_update_memory); + return 1; +} + +static void compute_gh_beta(struct blasfeo_dmat* K_mat, struct blasfeo_dmat* C_mat, + struct blasfeo_dmat* D_mat, struct blasfeo_dmat* CaDK_mat, + struct blasfeo_dmat* CaDKmP_mat, struct blasfeo_dmat* beta_mat, + struct blasfeo_dmat* P_mat, + int n_cstr, int nx, int nu) +{ + // (C+DK)@P@(C^T+K^TD^T) + // CaDK_mat = C_mat + D_mat @ K_mat + blasfeo_dgemm_nn(n_cstr, nx, nu, 1.0, D_mat, 0, 0, + K_mat, 0, 0, 1.0, + C_mat, 0, 0, CaDK_mat, 0, 0); + // CaDKmP_mat = CaDK_mat @ P_mat + blasfeo_dgemm_nn(n_cstr, nx, nx, 1.0, CaDK_mat, 0, 0, + P_mat, 0, 0, 0.0, + CaDKmP_mat, 0, 0, CaDKmP_mat, 0, 0); + // beta_mat = CaDKmP_mat @ CaDK_mat^T + blasfeo_dgemm_nt(n_cstr, n_cstr, nx, 1.0, CaDKmP_mat, 0, 0, + CaDK_mat, 0, 0, 0.0, + beta_mat, 0, 0, beta_mat, 0, 0); +} + +static void compute_KPK(struct blasfeo_dmat* K_mat, struct blasfeo_dmat* temp_KP_mat, + struct blasfeo_dmat* temp_KPK_mat, struct blasfeo_dmat* P_mat, + int nx, int nu) +{ + // K @ P_k @ K^T + // temp_KP_mat = K_mat @ P_mat + blasfeo_dgemm_nn(nu, nx, nx, 1.0, K_mat, 0, 0, + P_mat, 0, 0, 0.0, + temp_KP_mat, 0, 0, temp_KP_mat, 0, 0); + // temp_KPK_mat = temp_KP_mat @ K_mat^T + blasfeo_dgemm_nt(nu, nu, nx, 1.0, temp_KP_mat, 0, 0, + K_mat, 0, 0, 0.0, + temp_KPK_mat, 0, 0, temp_KPK_mat, 0, 0); +} + +static void compute_next_P_matrix(struct blasfeo_dmat* P_mat, struct blasfeo_dmat* P_next_mat, + struct blasfeo_dmat* A_mat, struct blasfeo_dmat* B_mat, + struct blasfeo_dmat* K_mat, struct blasfeo_dmat* W_mat, + struct blasfeo_dmat* AK_mat, struct blasfeo_dmat* temp_AP_mat, int nx, int nu) +{ + // AK_mat = -B@K + A + blasfeo_dgemm_nn(nx, nx, nu, -1.0, B_mat, 0, 0, K_mat, 0, 0, + 1.0, A_mat, 0, 0, AK_mat, 0, 0); + // temp_AP_mat = AK_mat @ P_k + blasfeo_dgemm_nn(nx, nx, nx, 1.0, AK_mat, 0, 0, + P_mat, 0, 0, 0.0, + temp_AP_mat, 0, 0, temp_AP_mat, 0, 0); + // P_{k+1} = temp_AP_mat @ AK_mat^T + GWG_mat + blasfeo_dgemm_nt(nx, nx, nx, 1.0, temp_AP_mat, 0, 0, + AK_mat, 0, 0, 1.0, + W_mat, 0, 0, P_next_mat, 0, 0); +} + +static void reset_P0_matrix(ocp_nlp_dims *nlp_dims, struct blasfeo_dmat* P_mat, double* data) +{ + int nx = nlp_dims->nx[0]; + blasfeo_pack_dmat(nx, nx, data, nx, P_mat, 0, 0); +} + +static void uncertainty_propagate_and_update(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out, custom_memory *custom_mem) +{ + ocp_nlp_config *nlp_config = solver->config; + ocp_nlp_dims *nlp_dims = solver->dims; + + int N = nlp_dims->N; + int nx = nlp_dims->nx[0]; + int nu = nlp_dims->nu[0]; + int nx_sqr = nx*nx; + int nbx = {{ dims.nbx }}; + int nbu = {{ dims.nbu }}; + int ng = {{ dims.ng }}; + int nh = {{ dims.nh }}; + int ng_e = {{ dims.ng_e }}; + int nh_e = {{ dims.nh_e }}; + int nbx_e = {{ dims.nbx_e }}; + double backoff_scaling_gamma = {{ zoro_description.backoff_scaling_gamma }}; + + // First Stage + // NOTE: lbx_0 and ubx_0 should not be tightened. + // NOTE: lg_0 and ug_0 are not tightened. + // NOTE: lh_0 and uh_0 are not tightened. +{%- if zoro_description.nlbu_t + zoro_description.nubu_t > 0 %} + compute_KPK(&custom_mem->K_mat, &custom_mem->temp_KP_mat, + &custom_mem->temp_KPK_mat, &(custom_mem->uncertainty_matrix_buffer[0]), nx, nu); + +{%- if zoro_description.nlbu_t > 0 %} + // backoff lbu + {%- for it in zoro_description.idx_lbu_t %} + custom_mem->d_lbu_tightened[{{it}}] + = custom_mem->d_lbu[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, + custom_mem->idxbu[{{it}}],custom_mem->idxbu[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "lbu", custom_mem->d_lbu_tightened); +{%- endif %} +{%- if zoro_description.nubu_t > 0 %} + // backoff ubu + {%- for it in zoro_description.idx_ubu_t %} + custom_mem->d_ubu_tightened[{{it}}] + = custom_mem->d_ubu[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, + custom_mem->idxbu[{{it}}],custom_mem->idxbu[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, 0, "ubu", custom_mem->d_ubu_tightened); +{%- endif %} +{%- endif %} + // Middle Stages + // constraint tightening: for next stage based on dynamics of ii stage + // P[ii+1] = (A-B@K) @ P[ii] @ (A-B@K).T + G@W@G.T + for (int ii = 0; ii < N-1; ii++) + { + // get and pack: A, B + ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, ii, "A", custom_mem->d_A_mat); + blasfeo_pack_dmat(nx, nx, custom_mem->d_A_mat, nx, &custom_mem->A_mat, 0, 0); + ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, ii, "B", custom_mem->d_B_mat); + blasfeo_pack_dmat(nx, nu, custom_mem->d_B_mat, nx, &custom_mem->B_mat, 0, 0); + + compute_next_P_matrix(&(custom_mem->uncertainty_matrix_buffer[ii]), + &(custom_mem->uncertainty_matrix_buffer[ii+1]), + &custom_mem->A_mat, &custom_mem->B_mat, + &custom_mem->K_mat, &custom_mem->GWG_mat, + &custom_mem->AK_mat, &custom_mem->temp_AP_mat, nx, nu); + + // state constraints +{%- if zoro_description.nlbx_t + zoro_description.nubx_t> 0 %} + {%- if zoro_description.nlbx_t > 0 %} + // lbx + {%- for it in zoro_description.idx_lbx_t %} + custom_mem->d_lbx_tightened[{{it}}] + = custom_mem->d_lbx[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[ii+1], + custom_mem->idxbx[{{it}}],custom_mem->idxbx[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lbx", custom_mem->d_lbx_tightened); + {%- endif %} + {% if zoro_description.nubx_t > 0 %} + // ubx + {%- for it in zoro_description.idx_ubx_t %} + custom_mem->d_ubx_tightened[{{it}}] = custom_mem->d_ubx[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[ii+1], + custom_mem->idxbx[{{it}}],custom_mem->idxbx[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "ubx", custom_mem->d_ubx_tightened); + {%- endif %} +{%- endif %} + +{%- if zoro_description.nlbu_t + zoro_description.nubu_t > 0 %} + // input constraints + compute_KPK(&custom_mem->K_mat, &custom_mem->temp_KP_mat, + &custom_mem->temp_KPK_mat, &(custom_mem->uncertainty_matrix_buffer[ii+1]), nx, nu); + + {%- if zoro_description.nlbu_t > 0 %} + {%- for it in zoro_description.idx_lbu_t %} + custom_mem->d_lbu_tightened[{{it}}] = custom_mem->d_lbu[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, + custom_mem->idxbu[{{it}}], custom_mem->idxbu[{{it}}])); + {%- endfor %} + + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lbu", custom_mem->d_lbu_tightened); + {%- endif %} + {%- if zoro_description.nubu_t > 0 %} + {%- for it in zoro_description.idx_ubu_t %} + custom_mem->d_ubu_tightened[{{it}}] = custom_mem->d_ubu[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_KPK_mat, + custom_mem->idxbu[{{it}}], custom_mem->idxbu[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "ubu", custom_mem->d_ubu_tightened); + {%- endif %} +{%- endif %} + +{%- if zoro_description.nlg_t + zoro_description.nug_t > 0 %} + // Linear constraints: g + compute_gh_beta(&custom_mem->K_mat, &custom_mem->Cg_mat, + &custom_mem->Dg_mat, &custom_mem->temp_CaDK_mat, + &custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, + &custom_mem->uncertainty_matrix_buffer[ii+1], ng, nx, nu); + + {%- if zoro_description.nlg_t > 0 %} + {%- for it in zoro_description.idx_lg_t %} + custom_mem->d_lg_tightened[{{it}}] + = custom_mem->d_lg[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lg", custom_mem->d_lg_tightened); + {%- endif %} + {%- if zoro_description.nug_t > 0 %} + {%- for it in zoro_description.idx_ug_t %} + custom_mem->d_ug_tightened[{{it}}] + = custom_mem->d_ug[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "ug", custom_mem->d_ug_tightened); + {%- endif %} +{%- endif %} + + +{%- if zoro_description.nlh_t + zoro_description.nuh_t > 0 %} + // nonlinear constraints: h + // Get C_{k+1} and D_{k+1} + ocp_nlp_get_at_stage(solver->config, nlp_dims, solver, ii+1, "C", custom_mem->d_Cgh_mat); + ocp_nlp_get_at_stage(solver->config, nlp_dims, solver, ii+1, "D", custom_mem->d_Dgh_mat); + // NOTE: the d_Cgh_mat is column-major, the first ng rows are the Jacobians of the linear constraints + blasfeo_pack_dmat(nh, nx, custom_mem->d_Cgh_mat+ng, ng+nh, &custom_mem->Ch_mat, 0, 0); + blasfeo_pack_dmat(nh, nu, custom_mem->d_Dgh_mat+ng, ng+nh, &custom_mem->Dh_mat, 0, 0); + + compute_gh_beta(&custom_mem->K_mat, &custom_mem->Ch_mat, + &custom_mem->Dh_mat, &custom_mem->temp_CaDK_mat, + &custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, + &custom_mem->uncertainty_matrix_buffer[ii+1], nh, nx, nu); + + {%- if zoro_description.nlh_t > 0 %} + {%- for it in zoro_description.idx_lh_t %} + custom_mem->d_lh_tightened[{{it}}] + = custom_mem->d_lh[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "lh", custom_mem->d_lh_tightened); + {%- endif %} + {%- if zoro_description.nuh_t > 0 %} + {%- for it in zoro_description.idx_uh_t %} + custom_mem->d_uh_tightened[{{it}}] = custom_mem->d_uh[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, ii+1, "uh", custom_mem->d_uh_tightened); + {%- endif %} +{%- endif %} + } + + // Last stage + // get and pack: A, B + ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, N-1, "A", custom_mem->d_A_mat); + blasfeo_pack_dmat(nx, nx, custom_mem->d_A_mat, nx, &custom_mem->A_mat, 0, 0); + ocp_nlp_get_at_stage(nlp_config, nlp_dims, solver, N-1, "B", custom_mem->d_B_mat); + blasfeo_pack_dmat(nx, nu, custom_mem->d_B_mat, nx, &custom_mem->B_mat, 0, 0); + // AK_mat = -B*K + A + compute_next_P_matrix(&(custom_mem->uncertainty_matrix_buffer[N-1]), + &(custom_mem->uncertainty_matrix_buffer[N]), + &custom_mem->A_mat, &custom_mem->B_mat, + &custom_mem->K_mat, &custom_mem->GWG_mat, + &custom_mem->AK_mat, &custom_mem->temp_AP_mat, nx, nu); + + // state constraints nlbx_e_t +{%- if zoro_description.nlbx_e_t + zoro_description.nubx_e_t> 0 %} +{%- if zoro_description.nlbx_e_t > 0 %} + // lbx_e + {%- for it in zoro_description.idx_lbx_e_t %} + custom_mem->d_lbx_e_tightened[{{it}}] + = custom_mem->d_lbx_e[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[N], + custom_mem->idxbx_e[{{it}}],custom_mem->idxbx_e[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lbx", custom_mem->d_lbx_e_tightened); +{%- endif %} +{% if zoro_description.nubx_e_t > 0 %} + // ubx_e + {%- for it in zoro_description.idx_ubx_e_t %} + custom_mem->d_ubx_e_tightened[{{it}}] = custom_mem->d_ubx_e[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->uncertainty_matrix_buffer[N], + custom_mem->idxbx_e[{{it}}],custom_mem->idxbx_e[{{it}}])); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ubx", custom_mem->d_ubx_e_tightened); +{%- endif %} +{%- endif %} + +{%- if zoro_description.nlg_e_t + zoro_description.nug_e_t > 0 %} + // Linear constraints: g + compute_gh_beta(&custom_mem->K_mat, &custom_mem->Cg_mat, + &custom_mem->dummy_Dgh_e_mat, &custom_mem->temp_CaDK_mat, + &custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, + &custom_mem->uncertainty_matrix_buffer[N], ng, nx, nu); + +{%- if zoro_description.nlg_e_t > 0 %} + {%- for it in zoro_description.idx_lg_e_t %} + custom_mem->d_lg_e_tightened[{{it}}] + = custom_mem->d_lg_e[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lg", custom_mem->d_lg_e_tightened); +{%- endif %} +{%- if zoro_description.nug_e_t > 0 %} + {%- for it in zoro_description.idx_ug_e_t %} + custom_mem->d_ug_e_tightened[{{it}}] + = custom_mem->d_ug_e[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "ug", custom_mem->d_ug_e_tightened); +{%- endif %} +{%- endif %} + + +{%- if zoro_description.nlh_e_t + zoro_description.nuh_e_t > 0 %} + // nonlinear constraints: h + // Get C_{k+1} and D_{k+1} + ocp_nlp_get_at_stage(solver->config, nlp_dims, solver, N, "C", custom_mem->d_Cgh_mat); + // NOTE: the d_Cgh_mat is column-major, the first ng rows are the Jacobians of the linear constraints + blasfeo_pack_dmat(nh, nx, custom_mem->d_Cgh_mat+ng, ng+nh, &custom_mem->Ch_mat, 0, 0); + + compute_gh_beta(&custom_mem->K_mat, &custom_mem->Ch_mat, + &custom_mem->dummy_Dgh_e_mat, &custom_mem->temp_CaDK_mat, + &custom_mem->temp_CaDKmP_mat, &custom_mem->temp_beta_mat, + &custom_mem->uncertainty_matrix_buffer[N], nh, nx, nu); + + {%- if zoro_description.nlh_e_t > 0 %} + {%- for it in zoro_description.idx_lh_e_t %} + custom_mem->d_lh_e_tightened[{{it}}] + = custom_mem->d_lh_e[{{it}}] + + backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "lh", custom_mem->d_lh_e_tightened); + {%- endif %} + {%- if zoro_description.nuh_e_t > 0 %} + {%- for it in zoro_description.idx_uh_e_t %} + custom_mem->d_uh_e_tightened[{{it}}] = custom_mem->d_uh_e[{{it}}] + - backoff_scaling_gamma * sqrt(blasfeo_dgeex1(&custom_mem->temp_beta_mat, {{it}}, {{it}})); + {%- endfor %} + ocp_nlp_constraints_model_set(nlp_config, nlp_dims, nlp_in, N, "uh", custom_mem->d_uh_e_tightened); + {%- endif %} +{%- endif %} + +} + + +int custom_update_function({{ model.name }}_solver_capsule* capsule, double* data, int data_len) +{ + custom_memory *custom_mem = (custom_memory *) capsule->custom_update_memory; + ocp_nlp_config *nlp_config = {{ model.name }}_acados_get_nlp_config(capsule); + ocp_nlp_dims *nlp_dims = {{ model.name }}_acados_get_nlp_dims(capsule); + ocp_nlp_in *nlp_in = {{ model.name }}_acados_get_nlp_in(capsule); + ocp_nlp_out *nlp_out = {{ model.name }}_acados_get_nlp_out(capsule); + ocp_nlp_solver *nlp_solver = {{ model.name }}_acados_get_nlp_solver(capsule); + void *nlp_opts = {{ model.name }}_acados_get_nlp_opts(capsule); + + if (data_len > 0) + { + reset_P0_matrix(nlp_dims, &custom_mem->uncertainty_matrix_buffer[0], data); + } + uncertainty_propagate_and_update(nlp_solver, nlp_in, nlp_out, custom_mem); + + return 1; +} + + +int custom_update_terminate_function({{ model.name }}_solver_capsule* capsule) +{ + custom_memory *mem = capsule->custom_update_memory; + + free(mem->raw_memory); + return 1; +} + +// useful prints for debugging + +/* +printf("A_mat:\n"); +blasfeo_print_exp_dmat(nx, nx, &custom_mem->A_mat, 0, 0); +printf("B_mat:\n"); +blasfeo_print_exp_dmat(nx, nu, &custom_mem->B_mat, 0, 0); +printf("K_mat:\n"); +blasfeo_print_exp_dmat(nu, nx, &custom_mem->K_mat, 0, 0); +printf("AK_mat:\n"); +blasfeo_print_exp_dmat(nx, nx, &custom_mem->AK_mat, 0, 0); +printf("temp_AP_mat:\n"); +blasfeo_print_exp_dmat(nx, nx, &custom_mem->temp_AP_mat, 0, 0); +printf("W_mat:\n"); +blasfeo_print_exp_dmat(nx, nx, &custom_mem->W_mat, 0, 0); +printf("P_k+1:\n"); +blasfeo_print_exp_dmat(nx, nx, &(custom_mem->uncertainty_matrix_buffer[ii+1]), 0, 0);*/ \ No newline at end of file diff --git a/third_party/acados/acados_template/custom_update_templates/custom_update_function_zoro_template.in.h b/third_party/acados/acados_template/custom_update_templates/custom_update_function_zoro_template.in.h new file mode 100644 index 0000000000..9611ea210c --- /dev/null +++ b/third_party/acados/acados_template/custom_update_templates/custom_update_function_zoro_template.in.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#include "acados_solver_{{ model.name }}.h" + +// Called at the end of solver creation. +// This is allowed to allocate memory and store the pointer to it into capsule->custom_update_memory. +int custom_update_init_function({{ model.name }}_solver_capsule* capsule); + + +// Custom update function that can be called between solver calls +int custom_update_function({{ model.name }}_solver_capsule* capsule, double* data, int data_len); + + +// Called just before destroying the solver. +// Responsible to free allocated memory, stored at capsule->custom_update_memory. +int custom_update_terminate_function({{ model.name }}_solver_capsule* capsule); diff --git a/third_party/acados/acados_template/gnsf/__init__.py b/third_party/acados/acados_template/gnsf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/third_party/acados/acados_template/gnsf/check_reformulation.py b/third_party/acados/acados_template/gnsf/check_reformulation.py new file mode 100644 index 0000000000..2bdfbbc336 --- /dev/null +++ b/third_party/acados/acados_template/gnsf/check_reformulation.py @@ -0,0 +1,216 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +from acados_template.utils import casadi_length +from casadi import * +import numpy as np + + +def check_reformulation(model, gnsf, print_info): + + ## Description: + # this function takes the implicit ODE/ index-1 DAE and a gnsf structure + # to evaluate both models at num_eval random points x0, x0dot, z0, u0 + # if for all points the relative error is <= TOL, the function will return:: + # 1, otherwise it will give an error. + + TOL = 1e-14 + num_eval = 10 + + # get dimensions + nx = gnsf["nx"] + nu = gnsf["nu"] + nz = gnsf["nz"] + nx1 = gnsf["nx1"] + nx2 = gnsf["nx2"] + nz1 = gnsf["nz1"] + nz2 = gnsf["nz2"] + n_out = gnsf["n_out"] + + # get model matrices + A = gnsf["A"] + B = gnsf["B"] + C = gnsf["C"] + E = gnsf["E"] + c = gnsf["c"] + + L_x = gnsf["L_x"] + L_xdot = gnsf["L_xdot"] + L_z = gnsf["L_z"] + L_u = gnsf["L_u"] + + A_LO = gnsf["A_LO"] + E_LO = gnsf["E_LO"] + B_LO = gnsf["B_LO"] + c_LO = gnsf["c_LO"] + + I_x1 = range(nx1) + I_x2 = range(nx1, nx) + + I_z1 = range(nz1) + I_z2 = range(nz1, nz) + + idx_perm_f = gnsf["idx_perm_f"] + + # get casadi variables + x = gnsf["x"] + xdot = gnsf["xdot"] + z = gnsf["z"] + u = gnsf["u"] + y = gnsf["y"] + uhat = gnsf["uhat"] + p = gnsf["p"] + + # create functions + impl_dae_fun = Function("impl_dae_fun", [x, xdot, u, z, p], [model.f_impl_expr]) + phi_fun = Function("phi_fun", [y, uhat, p], [gnsf["phi_expr"]]) + f_lo_fun = Function( + "f_lo_fun", [x[range(nx1)], xdot[range(nx1)], z, u, p], [gnsf["f_lo_expr"]] + ) + + # print(gnsf) + # print(gnsf["n_out"]) + + for i_check in range(num_eval): + # generate random values + x0 = np.random.rand(nx, 1) + x0dot = np.random.rand(nx, 1) + z0 = np.random.rand(nz, 1) + u0 = np.random.rand(nu, 1) + + if gnsf["ny"] > 0: + y0 = L_x @ x0[I_x1] + L_xdot @ x0dot[I_x1] + L_z @ z0[I_z1] + else: + y0 = [] + if gnsf["nuhat"] > 0: + uhat0 = L_u @ u0 + else: + uhat0 = [] + + # eval functions + p0 = np.random.rand(gnsf["np"], 1) + f_impl_val = impl_dae_fun(x0, x0dot, u0, z0, p0).full() + phi_val = phi_fun(y0, uhat0, p0) + f_lo_val = f_lo_fun(x0[I_x1], x0dot[I_x1], z0[I_z1], u0, p0) + + f_impl_val = f_impl_val[idx_perm_f] + # eval gnsf + if n_out > 0: + C_phi = C @ phi_val + else: + C_phi = np.zeros((nx1 + nz1, 1)) + try: + gnsf_val1 = ( + A @ x0[I_x1] + B @ u0 + C_phi + c - E @ vertcat(x0dot[I_x1], z0[I_z1]) + ) + # gnsf_1 = (A @ x[I_x1] + B @ u + C_phi + c - E @ vertcat(xdot[I_x1], z[I_z1])) + except: + import pdb + + pdb.set_trace() + + if nx2 > 0: # eval LOS: + gnsf_val2 = ( + A_LO @ x0[I_x2] + + B_LO @ u0 + + c_LO + + f_lo_val + - E_LO @ vertcat(x0dot[I_x2], z0[I_z2]) + ) + gnsf_val = vertcat(gnsf_val1, gnsf_val2).full() + else: + gnsf_val = gnsf_val1.full() + # compute error and check + rel_error = np.linalg.norm(f_impl_val - gnsf_val) / np.linalg.norm(f_impl_val) + + if rel_error > TOL: + print("transcription failed rel_error > TOL") + print("you are in debug mode now: import pdb; pdb.set_trace()") + abs_error = gnsf_val - f_impl_val + # T = table(f_impl_val, gnsf_val, abs_error) + # print(T) + print("abs_error:", abs_error) + # error('transcription failed rel_error > TOL') + # check = 0 + import pdb + + pdb.set_trace() + if print_info: + print(" ") + print("model reformulation checked: relative error <= TOL = ", str(TOL)) + print(" ") + check = 1 + ## helpful for debugging: + # # use in calling function and compare + # # compare f_impl(i) with gnsf_val1(i) + # + + # nx = gnsf['nx'] + # nu = gnsf['nu'] + # nz = gnsf['nz'] + # nx1 = gnsf['nx1'] + # nx2 = gnsf['nx2'] + # + # A = gnsf['A'] + # B = gnsf['B'] + # C = gnsf['C'] + # E = gnsf['E'] + # c = gnsf['c'] + # + # L_x = gnsf['L_x'] + # L_z = gnsf['L_z'] + # L_xdot = gnsf['L_xdot'] + # L_u = gnsf['L_u'] + # + # A_LO = gnsf['A_LO'] + # + # x0 = rand(nx, 1) + # x0dot = rand(nx, 1) + # z0 = rand(nz, 1) + # u0 = rand(nu, 1) + # I_x1 = range(nx1) + # I_x2 = nx1+range(nx) + # + # y0 = L_x @ x0[I_x1] + L_xdot @ x0dot[I_x1] + L_z @ z0 + # uhat0 = L_u @ u0 + # + # gnsf_val1 = (A @ x[I_x1] + B @ u + # C @ phi_current + c) - E @ [xdot[I_x1] z] + # gnsf_val1 = gnsf_val1.simplify() + # + # # gnsf_val2 = A_LO @ x[I_x2] + gnsf['f_lo_fun'](x[I_x1], xdot[I_x1], z, u) - xdot[I_x2] + # gnsf_val2 = A_LO @ x[I_x2] + gnsf['f_lo_fun'](x[I_x1], xdot[I_x1], z, u) - xdot[I_x2] + # + # + # gnsf_val = [gnsf_val1 gnsf_val2] + # gnsf_val = gnsf_val.simplify() + # dyn_expr_f = dyn_expr_f.simplify() + # import pdb; pdb.set_trace() + + return check diff --git a/third_party/acados/acados_template/gnsf/detect_affine_terms_reduce_nonlinearity.py b/third_party/acados/acados_template/gnsf/detect_affine_terms_reduce_nonlinearity.py new file mode 100644 index 0000000000..ebf1f373a4 --- /dev/null +++ b/third_party/acados/acados_template/gnsf/detect_affine_terms_reduce_nonlinearity.py @@ -0,0 +1,278 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +from casadi import * +from .check_reformulation import check_reformulation +from .determine_input_nonlinearity_function import determine_input_nonlinearity_function +from ..utils import casadi_length, print_casadi_expression + + +def detect_affine_terms_reduce_nonlinearity(gnsf, acados_ocp, print_info): + + ## Description + # this function takes a gnsf structure with trivial model matrices (A, B, + # E, c are zeros, and C is eye). + # It detects all affine linear terms and sets up an equivalent model in the + # GNSF structure, where all affine linear terms are modeled through the + # matrices A, B, E, c and the linear output system (LOS) is empty. + # NOTE: model is just taken as an argument to check equivalence of the + # models within the function. + + model = acados_ocp.model + if print_info: + print(" ") + print("====================================================================") + print(" ") + print("============ Detect affine-linear dependencies ==================") + print(" ") + print("====================================================================") + print(" ") + # symbolics + x = gnsf["x"] + xdot = gnsf["xdot"] + u = gnsf["u"] + z = gnsf["z"] + + # dimensions + nx = gnsf["nx"] + nu = gnsf["nu"] + nz = gnsf["nz"] + + ny_old = gnsf["ny"] + nuhat_old = gnsf["nuhat"] + + ## Represent all affine dependencies through the model matrices A, B, E, c + ## determine A + n_nodes_current = n_nodes(gnsf["phi_expr"]) + + for ii in range(casadi_length(gnsf["phi_expr"])): + fii = gnsf["phi_expr"][ii] + for ix in range(nx): + var = x[ix] + varname = var.name + # symbolic jacobian of fii w.r.t. xi + jac_fii_xi = jacobian(fii, var) + if jac_fii_xi.is_constant(): + # jacobian value + jac_fii_xi_fun = Function("jac_fii_xi_fun", [x[1]], [jac_fii_xi]) + # x[1] as input just to have a scalar input and call the function as follows: + gnsf["A"][ii, ix] = jac_fii_xi_fun(0).full() + else: + gnsf["A"][ii, ix] = 0 + if print_info: + print( + "phi(", + str(ii), + ") is nonlinear in x(", + str(ix), + ") = ", + varname, + ) + print(fii) + print("-----------------------------------------------------") + f_next = gnsf["phi_expr"] - gnsf["A"] @ x + f_next = simplify(f_next) + n_nodes_next = n_nodes(f_next) + + if print_info: + print("\n") + print(f"determined matrix A:") + print(gnsf["A"]) + print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") + # assert(n_nodes_current >= n_nodes_next,'n_nodes_current >= n_nodes_next FAILED') + gnsf["phi_expr"] = f_next + + check_reformulation(model, gnsf, print_info) + + ## determine B + n_nodes_current = n_nodes(gnsf["phi_expr"]) + + for ii in range(casadi_length(gnsf["phi_expr"])): + fii = gnsf["phi_expr"][ii] + for iu in range(nu): + var = u[iu] + varname = var.name + # symbolic jacobian of fii w.r.t. ui + jac_fii_ui = jacobian(fii, var) + if jac_fii_ui.is_constant(): # i.e. hessian is structural zero: + # jacobian value + jac_fii_ui_fun = Function("jac_fii_ui_fun", [x[1]], [jac_fii_ui]) + gnsf["B"][ii, iu] = jac_fii_ui_fun(0).full() + else: + gnsf["B"][ii, iu] = 0 + if print_info: + print(f"phi({ii}) is nonlinear in u(", str(iu), ") = ", varname) + print(fii) + print("-----------------------------------------------------") + f_next = gnsf["phi_expr"] - gnsf["B"] @ u + f_next = simplify(f_next) + n_nodes_next = n_nodes(f_next) + + if print_info: + print("\n") + print(f"determined matrix B:") + print(gnsf["B"]) + print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") + + gnsf["phi_expr"] = f_next + + check_reformulation(model, gnsf, print_info) + + ## determine E + n_nodes_current = n_nodes(gnsf["phi_expr"]) + k = vertcat(xdot, z) + + for ii in range(casadi_length(gnsf["phi_expr"])): + fii = gnsf["phi_expr"][ii] + for ik in range(casadi_length(k)): + # symbolic jacobian of fii w.r.t. ui + var = k[ik] + varname = var.name + jac_fii_ki = jacobian(fii, var) + if jac_fii_ki.is_constant(): + # jacobian value + jac_fii_ki_fun = Function("jac_fii_ki_fun", [x[1]], [jac_fii_ki]) + gnsf["E"][ii, ik] = -jac_fii_ki_fun(0).full() + else: + gnsf["E"][ii, ik] = 0 + if print_info: + print(f"phi( {ii}) is nonlinear in xdot_z({ik}) = ", varname) + print(fii) + print("-----------------------------------------------------") + f_next = gnsf["phi_expr"] + gnsf["E"] @ k + f_next = simplify(f_next) + n_nodes_next = n_nodes(f_next) + + if print_info: + print("\n") + print(f"determined matrix E:") + print(gnsf["E"]) + print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") + + gnsf["phi_expr"] = f_next + check_reformulation(model, gnsf, print_info) + + ## determine constant term c + + n_nodes_current = n_nodes(gnsf["phi_expr"]) + for ii in range(casadi_length(gnsf["phi_expr"])): + fii = gnsf["phi_expr"][ii] + if fii.is_constant(): + # function value goes into c + fii_fun = Function("fii_fun", [x[1]], [fii]) + gnsf["c"][ii] = fii_fun(0).full() + else: + gnsf["c"][ii] = 0 + if print_info: + print(f"phi(", str(ii), ") is NOT constant") + print(fii) + print("-----------------------------------------------------") + gnsf["phi_expr"] = gnsf["phi_expr"] - gnsf["c"] + gnsf["phi_expr"] = simplify(gnsf["phi_expr"]) + n_nodes_next = n_nodes(gnsf["phi_expr"]) + + if print_info: + print("\n") + print(f"determined vector c:") + print(gnsf["c"]) + print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") + + check_reformulation(model, gnsf, print_info) + + ## determine nonlinearity & corresponding matrix C + ## Reduce dimension of phi + n_nodes_current = n_nodes(gnsf["phi_expr"]) + ind_non_zero = [] + for ii in range(casadi_length(gnsf["phi_expr"])): + fii = gnsf["phi_expr"][ii] + fii = simplify(fii) + if not fii.is_zero(): + ind_non_zero = list(set.union(set(ind_non_zero), set([ii]))) + gnsf["phi_expr"] = gnsf["phi_expr"][ind_non_zero] + + # C + gnsf["C"] = np.zeros((nx + nz, len(ind_non_zero))) + for ii in range(len(ind_non_zero)): + gnsf["C"][ind_non_zero[ii], ii] = 1 + gnsf = determine_input_nonlinearity_function(gnsf) + n_nodes_next = n_nodes(gnsf["phi_expr"]) + + if print_info: + print(" ") + print("determined matrix C:") + print(gnsf["C"]) + print( + "---------------------------------------------------------------------------------" + ) + print( + "------------- Success: Affine linear terms detected -----------------------------" + ) + print( + "---------------------------------------------------------------------------------" + ) + print( + f'reduced nonlinearity dimension n_out from {nx+nz} to {gnsf["n_out"]}' + ) + print(f"reduced nonlinearity from {n_nodes_current} to {n_nodes_next} nodes") + print(" ") + print("phi now reads as:") + print_casadi_expression(gnsf["phi_expr"]) + + ## determine input of nonlinearity function + check_reformulation(model, gnsf, print_info) + + gnsf["ny"] = casadi_length(gnsf["y"]) + gnsf["nuhat"] = casadi_length(gnsf["uhat"]) + + if print_info: + print( + "-----------------------------------------------------------------------------------" + ) + print(" ") + print( + f"reduced input ny of phi from ", + str(ny_old), + " to ", + str(gnsf["ny"]), + ) + print( + f"reduced input nuhat of phi from ", + str(nuhat_old), + " to ", + str(gnsf["nuhat"]), + ) + print( + "-----------------------------------------------------------------------------------" + ) + + # if print_info: + # print(f"gnsf: {gnsf}") + + return gnsf diff --git a/third_party/acados/acados_template/gnsf/detect_gnsf_structure.py b/third_party/acados/acados_template/gnsf/detect_gnsf_structure.py new file mode 100644 index 0000000000..24ffe643b8 --- /dev/null +++ b/third_party/acados/acados_template/gnsf/detect_gnsf_structure.py @@ -0,0 +1,240 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com + +from casadi import Function, jacobian, SX, vertcat, horzcat + +from .determine_trivial_gnsf_transcription import determine_trivial_gnsf_transcription +from .detect_affine_terms_reduce_nonlinearity import ( + detect_affine_terms_reduce_nonlinearity, +) +from .reformulate_with_LOS import reformulate_with_LOS +from .reformulate_with_invertible_E_mat import reformulate_with_invertible_E_mat +from .structure_detection_print_summary import structure_detection_print_summary +from .check_reformulation import check_reformulation + + +def detect_gnsf_structure(acados_ocp, transcribe_opts=None): + + ## Description + # This function takes a CasADi implicit ODE or index-1 DAE model "model" + # consisting of a CasADi expression f_impl in the symbolic CasADi + # variables x, xdot, u, z, (and possibly parameters p), which are also part + # of the model, as well as a model name. + # It will create a struct "gnsf" containing all information needed to use + # it with the gnsf integrator in acados. + # Additionally it will create the struct "reordered_model" which contains + # the permuted state vector and permuted f_impl, in which additionally some + # functions, which were made part of the linear output system of the gnsf, + # have changed signs. + + # Options: transcribe_opts is a Matlab struct consisting of booleans: + # print_info: if extensive information on how the model is processed + # is printed to the console. + # generate_gnsf_model: if the neccessary C functions to simulate the gnsf + # model with the acados implementation of the GNSF exploiting + # integrator should be generated. + # generate_gnsf_model: if the neccessary C functions to simulate the + # reordered model with the acados implementation of the IRK + # integrator should be generated. + # check_E_invertibility: if the transcription method should check if the + # assumption that the main blocks of the matrix gnsf.E are invertible + # holds. If not, the method will try to reformulate the gnsf model + # with a different model, such that the assumption holds. + + # acados_root_dir = getenv('ACADOS_INSTALL_DIR') + + ## load transcribe_opts + if transcribe_opts is None: + print("WARNING: GNSF structure detection called without transcribe_opts") + print(" using default settings") + print("") + transcribe_opts = dict() + + if "print_info" in transcribe_opts: + print_info = transcribe_opts["print_info"] + else: + print_info = 1 + print("print_info option was not set - default is true") + + if "detect_LOS" in transcribe_opts: + detect_LOS = transcribe_opts["detect_LOS"] + else: + detect_LOS = 1 + if print_info: + print("detect_LOS option was not set - default is true") + + if "check_E_invertibility" in transcribe_opts: + check_E_invertibility = transcribe_opts["check_E_invertibility"] + else: + check_E_invertibility = 1 + if print_info: + print("check_E_invertibility option was not set - default is true") + + ## Reformulate implicit index-1 DAE into GNSF form + # (Generalized nonlinear static feedback) + gnsf = determine_trivial_gnsf_transcription(acados_ocp, print_info) + gnsf = detect_affine_terms_reduce_nonlinearity(gnsf, acados_ocp, print_info) + + if detect_LOS: + gnsf = reformulate_with_LOS(acados_ocp, gnsf, print_info) + + if check_E_invertibility: + gnsf = reformulate_with_invertible_E_mat(gnsf, acados_ocp, print_info) + + # detect purely linear model + if gnsf["nx1"] == 0 and gnsf["nz1"] == 0 and gnsf["nontrivial_f_LO"] == 0: + gnsf["purely_linear"] = 1 + else: + gnsf["purely_linear"] = 0 + + structure_detection_print_summary(gnsf, acados_ocp) + check_reformulation(acados_ocp.model, gnsf, print_info) + + ## copy relevant fields from gnsf to model + acados_ocp.model.get_matrices_fun = Function() + dummy = acados_ocp.model.x[0] + model_name = acados_ocp.model.name + + get_matrices_fun = Function( + f"{model_name}_gnsf_get_matrices_fun", + [dummy], + [ + gnsf["A"], + gnsf["B"], + gnsf["C"], + gnsf["E"], + gnsf["L_x"], + gnsf["L_xdot"], + gnsf["L_z"], + gnsf["L_u"], + gnsf["A_LO"], + gnsf["c"], + gnsf["E_LO"], + gnsf["B_LO"], + gnsf["nontrivial_f_LO"], + gnsf["purely_linear"], + gnsf["ipiv_x"] + 1, + gnsf["ipiv_z"] + 1, + gnsf["c_LO"], + ], + ) + + phi = gnsf["phi_expr"] + y = gnsf["y"] + uhat = gnsf["uhat"] + p = gnsf["p"] + + jac_phi_y = jacobian(phi, y) + jac_phi_uhat = jacobian(phi, uhat) + + phi_fun = Function(f"{model_name}_gnsf_phi_fun", [y, uhat, p], [phi]) + acados_ocp.model.phi_fun = phi_fun + acados_ocp.model.phi_fun_jac_y = Function( + f"{model_name}_gnsf_phi_fun_jac_y", [y, uhat, p], [phi, jac_phi_y] + ) + acados_ocp.model.phi_jac_y_uhat = Function( + f"{model_name}_gnsf_phi_jac_y_uhat", [y, uhat, p], [jac_phi_y, jac_phi_uhat] + ) + + x1 = acados_ocp.model.x[gnsf["idx_perm_x"][: gnsf["nx1"]]] + x1dot = acados_ocp.model.xdot[gnsf["idx_perm_x"][: gnsf["nx1"]]] + if gnsf["nz1"] > 0: + z1 = acados_ocp.model.z[gnsf["idx_perm_z"][: gnsf["nz1"]]] + else: + z1 = SX.sym("z1", 0, 0) + f_lo = gnsf["f_lo_expr"] + u = acados_ocp.model.u + acados_ocp.model.f_lo_fun_jac_x1k1uz = Function( + f"{model_name}_gnsf_f_lo_fun_jac_x1k1uz", + [x1, x1dot, z1, u, p], + [ + f_lo, + horzcat( + jacobian(f_lo, x1), + jacobian(f_lo, x1dot), + jacobian(f_lo, u), + jacobian(f_lo, z1), + ), + ], + ) + + acados_ocp.model.get_matrices_fun = get_matrices_fun + + size_gnsf_A = gnsf["A"].shape + acados_ocp.dims.gnsf_nx1 = size_gnsf_A[1] + acados_ocp.dims.gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1] + acados_ocp.dims.gnsf_nuhat = max(phi_fun.size_in(1)) + acados_ocp.dims.gnsf_ny = max(phi_fun.size_in(0)) + acados_ocp.dims.gnsf_nout = max(phi_fun.size_out(0)) + + # # dim + # model['dim_gnsf_nx1'] = gnsf['nx1'] + # model['dim_gnsf_nx2'] = gnsf['nx2'] + # model['dim_gnsf_nz1'] = gnsf['nz1'] + # model['dim_gnsf_nz2'] = gnsf['nz2'] + # model['dim_gnsf_nuhat'] = gnsf['nuhat'] + # model['dim_gnsf_ny'] = gnsf['ny'] + # model['dim_gnsf_nout'] = gnsf['n_out'] + + # # sym + # model['sym_gnsf_y'] = gnsf['y'] + # model['sym_gnsf_uhat'] = gnsf['uhat'] + + # # data + # model['dyn_gnsf_A'] = gnsf['A'] + # model['dyn_gnsf_A_LO'] = gnsf['A_LO'] + # model['dyn_gnsf_B'] = gnsf['B'] + # model['dyn_gnsf_B_LO'] = gnsf['B_LO'] + # model['dyn_gnsf_E'] = gnsf['E'] + # model['dyn_gnsf_E_LO'] = gnsf['E_LO'] + # model['dyn_gnsf_C'] = gnsf['C'] + # model['dyn_gnsf_c'] = gnsf['c'] + # model['dyn_gnsf_c_LO'] = gnsf['c_LO'] + # model['dyn_gnsf_L_x'] = gnsf['L_x'] + # model['dyn_gnsf_L_xdot'] = gnsf['L_xdot'] + # model['dyn_gnsf_L_z'] = gnsf['L_z'] + # model['dyn_gnsf_L_u'] = gnsf['L_u'] + # model['dyn_gnsf_idx_perm_x'] = gnsf['idx_perm_x'] + # model['dyn_gnsf_ipiv_x'] = gnsf['ipiv_x'] + # model['dyn_gnsf_idx_perm_z'] = gnsf['idx_perm_z'] + # model['dyn_gnsf_ipiv_z'] = gnsf['ipiv_z'] + # model['dyn_gnsf_idx_perm_f'] = gnsf['idx_perm_f'] + # model['dyn_gnsf_ipiv_f'] = gnsf['ipiv_f'] + + # # flags + # model['dyn_gnsf_nontrivial_f_LO'] = gnsf['nontrivial_f_LO'] + # model['dyn_gnsf_purely_linear'] = gnsf['purely_linear'] + + # # casadi expr + # model['dyn_gnsf_expr_phi'] = gnsf['phi_expr'] + # model['dyn_gnsf_expr_f_lo'] = gnsf['f_lo_expr'] + + return acados_ocp diff --git a/third_party/acados/acados_template/gnsf/determine_input_nonlinearity_function.py b/third_party/acados/acados_template/gnsf/determine_input_nonlinearity_function.py new file mode 100644 index 0000000000..94aa001c79 --- /dev/null +++ b/third_party/acados/acados_template/gnsf/determine_input_nonlinearity_function.py @@ -0,0 +1,110 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com + +from casadi import * +from ..utils import casadi_length, is_empty + + +def determine_input_nonlinearity_function(gnsf): + + ## Description + # this function takes a structure gnsf and updates the matrices L_x, + # L_xdot, L_z, L_u and CasADi vectors y, uhat of this structure as follows: + + # given a CasADi expression phi_expr, which may depend on the variables + # (x1, x1dot, z, u), this function determines a vector y (uhat) consisting + # of all components of (x1, x1dot, z) (respectively u) that enter phi_expr. + # Additionally matrices L_x, L_xdot, L_z, L_u are determined such that + # y = L_x * x + L_xdot * xdot + L_z * z + # uhat = L_u * u + # Furthermore the dimensions ny, nuhat, n_out are updated + + ## y + y = SX.sym('y', 0, 0) + # components of x1 + for ii in range(gnsf["nx1"]): + if which_depends(gnsf["phi_expr"], gnsf["x"][ii])[0]: + y = vertcat(y, gnsf["x"][ii]) + # else: + # x[ii] is not part of y + # components of x1dot + for ii in range(gnsf["nx1"]): + if which_depends(gnsf["phi_expr"], gnsf["xdot"][ii])[0]: + print(gnsf["phi_expr"], "depends on", gnsf["xdot"][ii]) + y = vertcat(y, gnsf["xdot"][ii]) + # else: + # xdot[ii] is not part of y + # components of z + for ii in range(gnsf["nz1"]): + if which_depends(gnsf["phi_expr"], gnsf["z"][ii])[0]: + y = vertcat(y, gnsf["z"][ii]) + # else: + # z[ii] is not part of y + ## uhat + uhat = SX.sym('uhat', 0, 0) + # components of u + for ii in range(gnsf["nu"]): + if which_depends(gnsf["phi_expr"], gnsf["u"][ii])[0]: + uhat = vertcat(uhat, gnsf["u"][ii]) + # else: + # u[ii] is not part of uhat + ## generate gnsf['phi_expr_fun'] + # linear input matrices + if is_empty(y): + gnsf["L_x"] = [] + gnsf["L_xdot"] = [] + gnsf["L_u"] = [] + gnsf["L_z"] = [] + else: + dummy = SX.sym("dummy_input", 0) + L_x_fun = Function( + "L_x_fun", [dummy], [jacobian(y, gnsf["x"][range(gnsf["nx1"])])] + ) + L_xdot_fun = Function( + "L_xdot_fun", [dummy], [jacobian(y, gnsf["xdot"][range(gnsf["nx1"])])] + ) + L_z_fun = Function( + "L_z_fun", [dummy], [jacobian(y, gnsf["z"][range(gnsf["nz1"])])] + ) + L_u_fun = Function("L_u_fun", [dummy], [jacobian(uhat, gnsf["u"])]) + + gnsf["L_x"] = L_x_fun(0).full() + gnsf["L_xdot"] = L_xdot_fun(0).full() + gnsf["L_u"] = L_u_fun(0).full() + gnsf["L_z"] = L_z_fun(0).full() + gnsf["y"] = y + gnsf["uhat"] = uhat + + gnsf["ny"] = casadi_length(y) + gnsf["nuhat"] = casadi_length(uhat) + gnsf["n_out"] = casadi_length(gnsf["phi_expr"]) + + return gnsf diff --git a/third_party/acados/acados_template/gnsf/determine_trivial_gnsf_transcription.py b/third_party/acados/acados_template/gnsf/determine_trivial_gnsf_transcription.py new file mode 100644 index 0000000000..23c2440537 --- /dev/null +++ b/third_party/acados/acados_template/gnsf/determine_trivial_gnsf_transcription.py @@ -0,0 +1,155 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +from casadi import * +import numpy as np +from ..utils import casadi_length, idx_perm_to_ipiv +from .determine_input_nonlinearity_function import determine_input_nonlinearity_function +from .check_reformulation import check_reformulation + + +def determine_trivial_gnsf_transcription(acados_ocp, print_info): + ## Description + # this function takes a model of an implicit ODE/ index-1 DAE and sets up + # an equivalent model in the GNSF structure, with empty linear output + # system and trivial model matrices, i.e. A, B, E, c are zeros, and C is + # eye. - no structure is exploited + + model = acados_ocp.model + # initial print + print("*****************************************************************") + print(" ") + print(f"****** Restructuring {model.name} model ***********") + print(" ") + print("*****************************************************************") + + # load model + f_impl_expr = model.f_impl_expr + + model_name_prefix = model.name + + # x + x = model.x + nx = acados_ocp.dims.nx + # check type + if isinstance(x[0], SX): + isSX = True + else: + print("GNSF detection only works for SX CasADi type!!!") + import pdb + + pdb.set_trace() + # xdot + xdot = model.xdot + # u + nu = acados_ocp.dims.nu + if nu == 0: + u = SX.sym("u", 0, 0) + else: + u = model.u + + nz = acados_ocp.dims.nz + if nz == 0: + z = SX.sym("z", 0, 0) + else: + z = model.z + + p = model.p + nparam = acados_ocp.dims.np + + # avoid SX of size 0x1 + if casadi_length(u) == 0: + u = SX.sym("u", 0, 0) + nu = 0 + ## initialize gnsf struct + # dimensions + gnsf = {"nx": nx, "nu": nu, "nz": nz, "np": nparam} + gnsf["nx1"] = nx + gnsf["nx2"] = 0 + gnsf["nz1"] = nz + gnsf["nz2"] = 0 + gnsf["nuhat"] = nu + gnsf["ny"] = 2 * nx + nz + + gnsf["phi_expr"] = f_impl_expr + gnsf["A"] = np.zeros((nx + nz, nx)) + gnsf["B"] = np.zeros((nx + nz, nu)) + gnsf["E"] = np.zeros((nx + nz, nx + nz)) + gnsf["c"] = np.zeros((nx + nz, 1)) + gnsf["C"] = np.eye(nx + nz) + gnsf["name"] = model_name_prefix + + gnsf["x"] = x + gnsf["xdot"] = xdot + gnsf["z"] = z + gnsf["u"] = u + gnsf["p"] = p + + gnsf = determine_input_nonlinearity_function(gnsf) + + gnsf["A_LO"] = [] + gnsf["E_LO"] = [] + gnsf["B_LO"] = [] + gnsf["c_LO"] = [] + gnsf["f_lo_expr"] = [] + + # permutation + gnsf["idx_perm_x"] = range(nx) # matlab-style) + gnsf["ipiv_x"] = idx_perm_to_ipiv(gnsf["idx_perm_x"]) # blasfeo-style + gnsf["idx_perm_z"] = range(nz) + gnsf["ipiv_z"] = idx_perm_to_ipiv(gnsf["idx_perm_z"]) + gnsf["idx_perm_f"] = range((nx + nz)) + gnsf["ipiv_f"] = idx_perm_to_ipiv(gnsf["idx_perm_f"]) + + gnsf["nontrivial_f_LO"] = 0 + + check_reformulation(model, gnsf, print_info) + if print_info: + print(f"Success: Set up equivalent GNSF model with trivial matrices") + print(" ") + if print_info: + print( + "-----------------------------------------------------------------------------------" + ) + print(" ") + print( + "reduced input ny of phi from ", + str(2 * nx + nz), + " to ", + str(gnsf["ny"]), + ) + print( + "reduced input nuhat of phi from ", str(nu), " to ", str(gnsf["nuhat"]) + ) + print(" ") + print( + "-----------------------------------------------------------------------------------" + ) + return gnsf diff --git a/third_party/acados/acados_template/gnsf/reformulate_with_LOS.py b/third_party/acados/acados_template/gnsf/reformulate_with_LOS.py new file mode 100644 index 0000000000..297a56556c --- /dev/null +++ b/third_party/acados/acados_template/gnsf/reformulate_with_LOS.py @@ -0,0 +1,394 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com + +from .determine_input_nonlinearity_function import determine_input_nonlinearity_function +from .check_reformulation import check_reformulation +from casadi import * +from ..utils import casadi_length, idx_perm_to_ipiv, is_empty + + +def reformulate_with_LOS(acados_ocp, gnsf, print_info): + + ## Description: + # This function takes an intitial transcription of the implicit ODE model + # "model" into "gnsf" and reformulates "gnsf" with a linear output system + # (LOS), containing as many states of the model as possible. + # Therefore it might be that the state vector and the implicit function + # vector have to be reordered. This reordered model is part of the output, + # namely reordered_model. + + ## import CasADi and load models + model = acados_ocp.model + + # symbolics + x = gnsf["x"] + xdot = gnsf["xdot"] + u = gnsf["u"] + z = gnsf["z"] + + # dimensions + nx = gnsf["nx"] + nz = gnsf["nz"] + + # get model matrices + A = gnsf["A"] + B = gnsf["B"] + C = gnsf["C"] + E = gnsf["E"] + c = gnsf["c"] + + A_LO = gnsf["A_LO"] + + y = gnsf["y"] + + phi_old = gnsf["phi_expr"] + + if print_info: + print(" ") + print("=================================================================") + print(" ") + print("================ Detect Linear Output System ===============") + print(" ") + print("=================================================================") + print(" ") + ## build initial I_x1 and I_x2_candidates + # I_xrange( all components of x for which either xii or xdot_ii enters y): + # I_LOS_candidates: the remaining components + + I_nsf_components = set() + I_LOS_candidates = set() + + if gnsf["ny"] > 0: + for ii in range(nx): + if which_depends(y, x[ii])[0] or which_depends(y, xdot[ii])[0]: + # i.e. xii or xiidot are part of y, and enter phi_expr + if print_info: + print(f"x_{ii} is part of x1") + I_nsf_components = set.union(I_nsf_components, set([ii])) + else: + # i.e. neither xii nor xiidot are part of y, i.e. enter phi_expr + I_LOS_candidates = set.union(I_LOS_candidates, set([ii])) + if print_info: + print(" ") + for ii in range(nz): + if which_depends(y, z[ii])[0]: + # i.e. xii or xiidot are part of y, and enter phi_expr + if print_info: + print(f"z_{ii} is part of x1") + I_nsf_components = set.union(I_nsf_components, set([ii + nx])) + else: + # i.e. neither xii nor xiidot are part of y, i.e. enter phi_expr + I_LOS_candidates = set.union(I_LOS_candidates, set([ii + nx])) + else: + I_LOS_candidates = set(range((nx + nz))) + if print_info: + print(" ") + print(f"I_LOS_candidates {I_LOS_candidates}") + new_nsf_components = I_nsf_components + I_nsf_eq = set([]) + unsorted_dyn = set(range(nx + nz)) + xdot_z = vertcat(xdot, z) + + ## determine components of Linear Output System + # determine maximal index set I_x2 + # such that the components x(I_x2) can be written as a LOS + Eq_map = [] + while True: + ## find equations corresponding to new_nsf_components + for ii in new_nsf_components: + current_var = xdot_z[ii] + var_name = current_var.name + + # print( unsorted_dyn) + # print("np.nonzero(E[:,ii])[0]",np.nonzero(E[:,ii])[0]) + I_eq = set.intersection(set(np.nonzero(E[:, ii])[0]), unsorted_dyn) + if len(I_eq) == 1: + i_eq = I_eq.pop() + if print_info: + print(f"component {i_eq} is associated with state {ii}") + elif len(I_eq) > 1: # x_ii_dot occurs in more than 1 eq linearly + # find the equation with least linear dependencies on + # I_LOS_cancidates + number_of_eq = 0 + candidate_dependencies = np.zeros(len(I_eq), 1) + I_x2_candidates = set.intersection(I_LOS_candidates, set(range(nx))) + for eq in I_eq: + depending_candidates = set.union( + np.nonzero(E[eq, I_LOS_candidates])[0], + np.nonzero(A[eq, I_x2_candidates])[0], + ) + candidate_dependencies[number_of_eq] = +len(depending_candidates) + number_of_eq += 1 + number_of_eq = np.argmin(candidate_dependencies) + i_eq = I_eq[number_of_eq] + else: ## x_ii_dot does not occur linearly in any of the unsorted dynamics + for j in unsorted_dyn: + phi_eq_j = gnsf["phi_expr"][np.nonzero(C[j, :])[0]] + if which_depends(phi_eq_j, xdot_z(ii))[0]: + I_eq = set.union(I_eq, j) + if is_empty(I_eq): + I_eq = unsorted_dyn + # find the equation with least linear dependencies on I_LOS_cancidates + number_of_eq = 0 + candidate_dependencies = np.zeros(len(I_eq), 1) + I_x2_candidates = set.intersection(I_LOS_candidates, set(range(nx))) + for eq in I_eq: + depending_candidates = set.union( + np.nonzero(E[eq, I_LOS_candidates])[0], + np.nonzero(A[eq, I_x2_candidates])[0], + ) + candidate_dependencies[number_of_eq] = +len(depending_candidates) + number_of_eq += 1 + number_of_eq = np.argmin(candidate_dependencies) + i_eq = I_eq[number_of_eq] + ## add 1 * [xdot,z](ii) to both sides of i_eq + if print_info: + print( + "adding 1 * ", + var_name, + " to both sides of equation ", + i_eq, + ".", + ) + gnsf["E"][i_eq, ii] = 1 + i_phi = np.nonzero(gnsf["C"][i_eq, :]) + if is_empty(i_phi): + i_phi = len(gnsf["phi_expr"]) + 1 + gnsf["C"][i_eq, i_phi] = 1 # add column to C with 1 entry + gnsf["phi_expr"] = vertcat(gnsf["phi_expr"], 0) + gnsf["phi_expr"][i_phi] = ( + gnsf["phi_expr"](i_phi) + + gnsf["E"][i_eq, ii] / gnsf["C"][i_eq, i_phi] * xdot_z[ii] + ) + if print_info: + print( + "detected equation ", + i_eq, + " to correspond to variable ", + var_name, + ) + I_nsf_eq = set.union(I_nsf_eq, {i_eq}) + # remove i_eq from unsorted_dyn + unsorted_dyn.remove(i_eq) + Eq_map.append([ii, i_eq]) + + ## add components to I_x1 + for eq in I_nsf_eq: + I_linear_dependence = set.union( + set(np.nonzero(A[eq, :])[0]), set(np.nonzero(E[eq, :])[0]) + ) + I_nsf_components = set.union(I_linear_dependence, I_nsf_components) + # I_nsf_components = I_nsf_components[:] + + new_nsf_components = set.intersection(I_LOS_candidates, I_nsf_components) + if is_empty(new_nsf_components): + if print_info: + print("new_nsf_components is empty") + break + # remove new_nsf_components from candidates + I_LOS_candidates = set.difference(I_LOS_candidates, new_nsf_components) + if not is_empty(Eq_map): + # [~, new_eq_order] = sort(Eq_map(1,:)) + # I_nsf_eq = Eq_map(2, new_eq_order ) + for count, m in enumerate(Eq_map): + m.append(count) + sorted(Eq_map, key=lambda x: x[1]) + new_eq_order = [m[2] for m in Eq_map] + Eq_map = [Eq_map[i] for i in new_eq_order] + I_nsf_eq = [m[1] for m in Eq_map] + + else: + I_nsf_eq = [] + + I_LOS_components = I_LOS_candidates + I_LOS_eq = sorted(set.difference(set(range(nx + nz)), I_nsf_eq)) + I_nsf_eq = sorted(I_nsf_eq) + + I_x1 = set.intersection(I_nsf_components, set(range(nx))) + I_z1 = set.intersection(I_nsf_components, set(range(nx, nx + nz))) + I_z1 = set([i - nx for i in I_z1]) + + I_x2 = set.intersection(I_LOS_components, set(range(nx))) + I_z2 = set.intersection(I_LOS_components, set(range(nx, nx + nz))) + I_z2 = set([i - nx for i in I_z2]) + + if print_info: + print(f"I_x1 {I_x1}, I_x2 {I_x2}") + + ## permute x, xdot + if is_empty(I_x1): + x1 = [] + x1dot = [] + else: + x1 = x[list(I_x1)] + x1dot = xdot[list(I_x1)] + if is_empty(I_x2): + x2 = [] + x2dot = [] + else: + x2 = x[list(I_x2)] + x2dot = xdot[list(I_x2)] + if is_empty(I_z1): + z1 = [] + else: + z1 = z(I_z1) + if is_empty(I_z2): + z2 = [] + else: + z2 = z[list(I_z2)] + + I_x1 = sorted(I_x1) + I_x2 = sorted(I_x2) + I_z1 = sorted(I_z1) + I_z2 = sorted(I_z2) + gnsf["xdot"] = vertcat(x1dot, x2dot) + gnsf["x"] = vertcat(x1, x2) + gnsf["z"] = vertcat(z1, z2) + gnsf["nx1"] = len(I_x1) + gnsf["nx2"] = len(I_x2) + gnsf["nz1"] = len(I_z1) + gnsf["nz2"] = len(I_z2) + + # store permutations + gnsf["idx_perm_x"] = I_x1 + I_x2 + gnsf["ipiv_x"] = idx_perm_to_ipiv(gnsf["idx_perm_x"]) + gnsf["idx_perm_z"] = I_z1 + I_z2 + gnsf["ipiv_z"] = idx_perm_to_ipiv(gnsf["idx_perm_z"]) + gnsf["idx_perm_f"] = I_nsf_eq + I_LOS_eq + gnsf["ipiv_f"] = idx_perm_to_ipiv(gnsf["idx_perm_f"]) + + f_LO = SX.sym("f_LO", 0, 0) + + ## rewrite I_LOS_eq as LOS + if gnsf["n_out"] == 0: + C_phi = np.zeros(gnsf["nx"] + gnsf["nz"], 1) + else: + C_phi = C @ phi_old + if gnsf["nx1"] == 0: + Ax1 = np.zeros(gnsf["nx"] + gnsf["nz"], 1) + else: + Ax1 = A[:, sorted(I_x1)] @ x1 + if gnsf["nx1"] + gnsf["nz1"] == 0: + lhs_nsf = np.zeros(gnsf["nx"] + gnsf["nz"], 1) + else: + lhs_nsf = E[:, sorted(I_nsf_components)] @ vertcat(x1, z1) + n_LO = len(I_LOS_eq) + B_LO = np.zeros((n_LO, gnsf["nu"])) + A_LO = np.zeros((gnsf["nx2"] + gnsf["nz2"], gnsf["nx2"])) + E_LO = np.zeros((n_LO, n_LO)) + c_LO = np.zeros((n_LO, 1)) + + I_LOS_eq = list(I_LOS_eq) + for eq in I_LOS_eq: + i_LO = I_LOS_eq.index(eq) + f_LO = vertcat(f_LO, Ax1[eq] + C_phi[eq] - lhs_nsf[eq]) + print(f"eq {eq} I_LOS_components {I_LOS_components}, i_LO {i_LO}, f_LO {f_LO}") + E_LO[i_LO, :] = E[eq, sorted(I_LOS_components)] + A_LO[i_LO, :] = A[eq, I_x2] + c_LO[i_LO, :] = c[eq] + B_LO[i_LO, :] = B[eq, :] + if casadi_length(f_LO) == 0: + f_LO = SX.zeros((gnsf["nx2"] + gnsf["nz2"], 1)) + f_LO = simplify(f_LO) + gnsf["A_LO"] = A_LO + gnsf["E_LO"] = E_LO + gnsf["B_LO"] = B_LO + gnsf["c_LO"] = c_LO + gnsf["f_lo_expr"] = f_LO + + ## remove I_LOS_eq from NSF type system + gnsf["A"] = gnsf["A"][np.ix_(sorted(I_nsf_eq), sorted(I_x1))] + gnsf["B"] = gnsf["B"][sorted(I_nsf_eq), :] + gnsf["C"] = gnsf["C"][sorted(I_nsf_eq), :] + gnsf["E"] = gnsf["E"][np.ix_(sorted(I_nsf_eq), sorted(I_nsf_components))] + gnsf["c"] = gnsf["c"][sorted(I_nsf_eq), :] + + ## reduce phi, C + I_nonzero = [] + for ii in range(gnsf["C"].shape[1]): # n_colums of C: + print(f"ii {ii}") + if not all(gnsf["C"][:, ii] == 0): # if column ~= 0 + I_nonzero.append(ii) + gnsf["C"] = gnsf["C"][:, I_nonzero] + gnsf["phi_expr"] = gnsf["phi_expr"][I_nonzero] + + gnsf = determine_input_nonlinearity_function(gnsf) + + check_reformulation(model, gnsf, print_info) + + gnsf["nontrivial_f_LO"] = 0 + if not is_empty(gnsf["f_lo_expr"]): + for ii in range(casadi_length(gnsf["f_lo_expr"])): + fii = gnsf["f_lo_expr"][ii] + if not fii.is_zero(): + gnsf["nontrivial_f_LO"] = 1 + if not gnsf["nontrivial_f_LO"] and print_info: + print("f_LO is fully trivial (== 0)") + check_reformulation(model, gnsf, print_info) + + if print_info: + print("") + print( + "---------------------------------------------------------------------------------" + ) + print( + "------------- Success: Linear Output System (LOS) detected ----------------------" + ) + print( + "---------------------------------------------------------------------------------" + ) + print("") + print( + "==>> moved ", + gnsf["nx2"], + "differential states and ", + gnsf["nz2"], + " algebraic variables to the Linear Output System", + ) + print( + "==>> recuced output dimension of phi from ", + casadi_length(phi_old), + " to ", + casadi_length(gnsf["phi_expr"]), + ) + print(" ") + print("Matrices defining the LOS read as") + print(" ") + print("E_LO =") + print(gnsf["E_LO"]) + print("A_LO =") + print(gnsf["A_LO"]) + print("B_LO =") + print(gnsf["B_LO"]) + print("c_LO =") + print(gnsf["c_LO"]) + + return gnsf diff --git a/third_party/acados/acados_template/gnsf/reformulate_with_invertible_E_mat.py b/third_party/acados/acados_template/gnsf/reformulate_with_invertible_E_mat.py new file mode 100644 index 0000000000..21ab8ebfd5 --- /dev/null +++ b/third_party/acados/acados_template/gnsf/reformulate_with_invertible_E_mat.py @@ -0,0 +1,167 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com + +from casadi import * +from .determine_input_nonlinearity_function import determine_input_nonlinearity_function +from .check_reformulation import check_reformulation + + +def reformulate_with_invertible_E_mat(gnsf, model, print_info): + ## Description + # this function checks that the necessary condition to apply the gnsf + # structure exploiting integrator to a model, namely that the matrices E11, + # E22 are invertible holds. + # if this is not the case, it will make these matrices invertible and add: + # corresponding terms, to the term C * phi, such that the obtained model is + # still equivalent + + # check invertibility of E11, E22 and reformulate if needed: + ind_11 = range(gnsf["nx1"]) + ind_22 = range(gnsf["nx1"], gnsf["nx1"] + gnsf["nz1"]) + + if print_info: + print(" ") + print("----------------------------------------------------") + print("checking rank of E11 and E22") + print("----------------------------------------------------") + ## check if E11, E22 are invertible: + z_check = False + if gnsf["nz1"] > 0: + z_check = ( + np.linalg.matrix_rank(gnsf["E"][np.ix_(ind_22, ind_22)]) != gnsf["nz1"] + ) + + if ( + np.linalg.matrix_rank(gnsf["E"][np.ix_(ind_11, ind_11)]) != gnsf["nx1"] + or z_check + ): + # print warning (always) + print(f"the rank of E11 or E22 is not full after the reformulation") + print("") + print( + f"the script will try to reformulate the model with an invertible matrix instead" + ) + print( + f"NOTE: this feature is based on a heuristic, it should be used with care!!!" + ) + + ## load models + xdot = gnsf["xdot"] + z = gnsf["z"] + + # # GNSF + # get dimensions + nx1 = gnsf["nx1"] + x1dot = xdot[range(nx1)] + + k = vertcat(x1dot, z) + for i in [1, 2]: + if i == 1: + ind = range(gnsf["nx1"]) + else: + ind = range(gnsf["nx1"], gnsf["nx1"] + gnsf["nz1"]) + mat = gnsf["E"][np.ix_(ind, ind)] + import pdb + + pdb.set_trace() + while np.linalg.matrix_rank(mat) < len(ind): + # import pdb; pdb.set_trace() + if print_info: + print(" ") + print(f"the rank of E", str(i), str(i), " is not full") + print( + f"the algorithm will try to reformulate the model with an invertible matrix instead" + ) + print( + f"NOTE: this feature is not super stable and might need more testing!!!!!!" + ) + for sub_max in ind: + sub_ind = range(min(ind), sub_max) + # regard the submatrix mat(sub_ind, sub_ind) + sub_mat = gnsf["E"][sub_ind, sub_ind] + if np.linalg.matrix_rank(sub_mat) < len(sub_ind): + # reformulate the model by adding a 1 to last diagonal + # element and changing rhs respectively. + gnsf["E"][sub_max, sub_max] = gnsf["E"][sub_max, sub_max] + 1 + # this means adding the term 1 * k(sub_max) to the sub_max + # row of the l.h.s + if len(np.nonzero(gnsf["C"][sub_max, :])[0]) == 0: + # if isempty(find(gnsf['C'](sub_max,:), 1)): + # add new nonlinearity entry + gnsf["C"][sub_max, gnsf["n_out"] + 1] = 1 + gnsf["phi_expr"] = vertcat(gnsf["phi_expr"], k[sub_max]) + else: + ind_f = np.nonzero(gnsf["C"][sub_max, :])[0] + if len(ind_f) != 1: + raise Exception("C is assumed to be a selection matrix") + else: + ind_f = ind_f[0] + # add term to corresponding nonlinearity entry + # note: herbey we assume that C is a selection matrix, + # i.e. gnsf['phi_expr'](ind_f) is only entering one equation + + gnsf["phi_expr"][ind_f] = ( + gnsf["phi_expr"][ind_f] + + k[sub_max] / gnsf["C"][sub_max, ind_f] + ) + gnsf = determine_input_nonlinearity_function(gnsf) + check_reformulation(model, gnsf, print_info) + print("successfully reformulated the model with invertible matrices E11, E22") + else: + if print_info: + print(" ") + print( + "the rank of both E11 and E22 is naturally full after the reformulation " + ) + print("==> model reformulation finished") + print(" ") + if (gnsf['nx2'] > 0 or gnsf['nz2'] > 0) and det(gnsf["E_LO"]) == 0: + print( + "_______________________________________________________________________________________________________" + ) + print(" ") + print("TAKE CARE ") + print("E_LO matrix is NOT regular after automatic transcription!") + print("->> this means the model CANNOT be used with the gnsf integrator") + print( + "->> it probably means that one entry (of xdot or z) that was moved to the linear output type system" + ) + print(" does not appear in the model at all (zero column in E_LO)") + print(" OR: the columns of E_LO are linearly dependent ") + print(" ") + print( + " SOLUTIONs: a) go through your model & check equations the method wanted to move to LOS" + ) + print(" b) deactivate the detect_LOS option") + print( + "_______________________________________________________________________________________________________" + ) + return gnsf diff --git a/third_party/acados/acados_template/gnsf/structure_detection_print_summary.py b/third_party/acados/acados_template/gnsf/structure_detection_print_summary.py new file mode 100644 index 0000000000..db2d18758e --- /dev/null +++ b/third_party/acados/acados_template/gnsf/structure_detection_print_summary.py @@ -0,0 +1,174 @@ +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# +# Author: Jonathan Frey: jonathanpaulfrey(at)gmail.com + +from casadi import n_nodes +import numpy as np + + +def structure_detection_print_summary(gnsf, acados_ocp): + + ## Description + # this function prints the most important info after determining a GNSF + # reformulation of the implicit model "initial_model" into "gnsf", which is + # equivalent to the "reordered_model". + model = acados_ocp.model + # # GNSF + # get dimensions + nx = gnsf["nx"] + nu = gnsf["nu"] + nz = gnsf["nz"] + + nx1 = gnsf["nx1"] + nx2 = gnsf["nx2"] + + nz1 = gnsf["nz1"] + nz2 = gnsf["nz2"] + + # np = gnsf['np'] + n_out = gnsf["n_out"] + ny = gnsf["ny"] + nuhat = gnsf["nuhat"] + + # + f_impl_expr = model.f_impl_expr + n_nodes_initial = n_nodes(model.f_impl_expr) + # x_old = model.x + # f_impl_old = model.f_impl_expr + + x = gnsf["x"] + z = gnsf["z"] + + phi_current = gnsf["phi_expr"] + + ## PRINT SUMMARY -- STRUCHTRE DETECTION + print(" ") + print( + "*********************************************************************************************" + ) + print(" ") + print( + "****************** SUCCESS: GNSF STRUCTURE DETECTION COMPLETE !!! ***************" + ) + print(" ") + print( + "*********************************************************************************************" + ) + print(" ") + print( + f"========================= STRUCTURE DETECTION SUMMARY ====================================" + ) + print(" ") + print("-------- Nonlinear Static Feedback type system --------") + print(" ") + print(" successfully transcribed dynamic system model into GNSF structure ") + print(" ") + print( + "reduced dimension of nonlinearity phi from ", + str(nx + nz), + " to ", + str(gnsf["n_out"]), + ) + print(" ") + print( + "reduced input dimension of nonlinearity phi from ", + 2 * nx + nz + nu, + " to ", + gnsf["ny"] + gnsf["nuhat"], + ) + print(" ") + print(f"reduced number of nodes in CasADi expression of nonlinearity phi from {n_nodes_initial} to {n_nodes(phi_current)}\n") + print("----------- Linear Output System (LOS) ---------------") + if nx2 + nz2 > 0: + print(" ") + print(f"introduced Linear Output System of size ", str(nx2 + nz2)) + print(" ") + if nx2 > 0: + print("consisting of the states:") + print(" ") + print(x[range(nx1, nx)]) + print(" ") + if nz2 > 0: + print("and algebraic variables:") + print(" ") + print(z[range(nz1, nz)]) + print(" ") + if gnsf["purely_linear"] == 1: + print(" ") + print("Model is fully linear!") + print(" ") + if not all(gnsf["idx_perm_x"] == np.array(range(nx))): + print(" ") + print( + "--------------------------------------------------------------------------------------------------" + ) + print( + "NOTE: permuted differential state vector x, such that x_gnsf = x(idx_perm_x) with idx_perm_x =" + ) + print(" ") + print(gnsf["idx_perm_x"]) + if nz != 0 and not all(gnsf["idx_perm_z"] == np.array(range(nz))): + print(" ") + print( + "--------------------------------------------------------------------------------------------------" + ) + print( + "NOTE: permuted algebraic state vector z, such that z_gnsf = z(idx_perm_z) with idx_perm_z =" + ) + print(" ") + print(gnsf["idx_perm_z"]) + if not all(gnsf["idx_perm_f"] == np.array(range(nx + nz))): + print(" ") + print( + "--------------------------------------------------------------------------------------------------" + ) + print( + "NOTE: permuted rhs expression vector f, such that f_gnsf = f(idx_perm_f) with idx_perm_f =" + ) + print(" ") + print(gnsf["idx_perm_f"]) + ## print GNSF dimensions + print( + "--------------------------------------------------------------------------------------------------------" + ) + print(" ") + print("The dimensions of the GNSF reformulated model read as:") + print(" ") + # T_dim = table(nx, nu, nz, np, nx1, nz1, n_out, ny, nuhat) + # print( T_dim ) + print(f"nx ", {nx}) + print(f"nu ", {nu}) + print(f"nz ", {nz}) + # print(f"np ", {np}) + print(f"nx1 ", {nx1}) + print(f"nz1 ", {nz1}) + print(f"n_out ", {n_out}) + print(f"ny ", {ny}) + print(f"nuhat ", {nuhat}) diff --git a/third_party/acados/acados_template/simulink_default_opts.json b/third_party/acados/acados_template/simulink_default_opts.json new file mode 100644 index 0000000000..5d178fef85 --- /dev/null +++ b/third_party/acados/acados_template/simulink_default_opts.json @@ -0,0 +1,44 @@ +{ + "outputs": { + "u0": 1, + "utraj": 0, + "xtraj": 0, + "solver_status": 1, + "cost_value": 0, + "KKT_residual": 1, + "KKT_residuals": 0, + "x1": 1, + "CPU_time": 1, + "CPU_time_sim": 0, + "CPU_time_qp": 0, + "CPU_time_lin": 0, + "sqp_iter": 1 + }, + "inputs": { + "lbx_0": 1, + "ubx_0": 1, + "parameter_traj": 1, + "y_ref_0": 1, + "y_ref": 1, + "y_ref_e": 1, + "lbx": 1, + "ubx": 1, + "lbx_e": 1, + "ubx_e": 1, + "lbu": 1, + "ubu": 1, + "lg": 1, + "ug": 1, + "lh": 1, + "uh": 1, + "lh_e": 1, + "uh_e": 1, + "cost_W_0": 0, + "cost_W": 0, + "cost_W_e": 0, + "reset_solver": 0, + "x_init": 0, + "u_init": 0 + }, + "samplingtime": "t0" +} diff --git a/third_party/acados/acados_template/utils.py b/third_party/acados/acados_template/utils.py new file mode 100644 index 0000000000..d6f6c02f84 --- /dev/null +++ b/third_party/acados/acados_template/utils.py @@ -0,0 +1,435 @@ +# -*- coding: future_fstrings -*- +# +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; +# + +import os, sys, json +import urllib.request +import shutil +import numpy as np +from casadi import SX, MX, DM, Function, CasadiMeta + +ALLOWED_CASADI_VERSIONS = ('3.5.6', '3.5.5', '3.5.4', '3.5.3', '3.5.2', '3.5.1', '3.4.5', '3.4.0') + +TERA_VERSION = "0.0.34" + +PLATFORM2TERA = { + "linux": "linux", + "darwin": "osx", + "win32": "windows" +} + + +def get_acados_path(): + ACADOS_PATH = os.environ.get('ACADOS_SOURCE_DIR') + if not ACADOS_PATH: + acados_template_path = os.path.dirname(os.path.abspath(__file__)) + acados_path = os.path.join(acados_template_path, '..','..','..') + ACADOS_PATH = os.path.realpath(acados_path) + msg = 'Warning: Did not find environment variable ACADOS_SOURCE_DIR, ' + msg += 'guessed ACADOS_PATH to be {}.\n'.format(ACADOS_PATH) + msg += 'Please export ACADOS_SOURCE_DIR to avoid this warning.' + print(msg) + return ACADOS_PATH + + +def get_python_interface_path(): + ACADOS_PYTHON_INTERFACE_PATH = os.environ.get('ACADOS_PYTHON_INTERFACE_PATH') + if not ACADOS_PYTHON_INTERFACE_PATH: + acados_path = get_acados_path() + ACADOS_PYTHON_INTERFACE_PATH = os.path.join(acados_path, 'interfaces', 'acados_template', 'acados_template') + return ACADOS_PYTHON_INTERFACE_PATH + + +def get_tera_exec_path(): + TERA_PATH = os.environ.get('TERA_PATH') + if not TERA_PATH: + TERA_PATH = os.path.join(get_acados_path(), 'bin', 't_renderer') + if os.name == 'nt': + TERA_PATH += '.exe' + return TERA_PATH + + +def check_casadi_version(): + casadi_version = CasadiMeta.version() + if casadi_version in ALLOWED_CASADI_VERSIONS: + return + else: + msg = 'Warning: Please note that the following versions of CasADi are ' + msg += 'officially supported: {}.\n '.format(" or ".join(ALLOWED_CASADI_VERSIONS)) + msg += 'If there is an incompatibility with the CasADi generated code, ' + msg += 'please consider changing your CasADi version.\n' + msg += 'Version {} currently in use.'.format(casadi_version) + print(msg) + + +def is_column(x): + if isinstance(x, np.ndarray): + if x.ndim == 1: + return True + elif x.ndim == 2 and x.shape[1] == 1: + return True + else: + return False + elif isinstance(x, (MX, SX, DM)): + if x.shape[1] == 1: + return True + elif x.shape[0] == 0 and x.shape[1] == 0: + return True + else: + return False + elif x == None or x == []: + return False + else: + raise Exception("is_column expects one of the following types: np.ndarray, casadi.MX, casadi.SX." + + " Got: " + str(type(x))) + + +def is_empty(x): + if isinstance(x, (MX, SX, DM)): + return x.is_empty() + elif isinstance(x, np.ndarray): + if np.prod(x.shape) == 0: + return True + else: + return False + elif x == None: + return True + elif isinstance(x, (set, list)): + if len(x)==0: + return True + else: + return False + else: + raise Exception("is_empty expects one of the following types: casadi.MX, casadi.SX, " + + "None, numpy array empty list, set. Got: " + str(type(x))) + + +def casadi_length(x): + if isinstance(x, (MX, SX, DM)): + return int(np.prod(x.shape)) + else: + raise Exception("casadi_length expects one of the following types: casadi.MX, casadi.SX." + + " Got: " + str(type(x))) + + +def make_model_consistent(model): + x = model.x + xdot = model.xdot + u = model.u + z = model.z + p = model.p + + if isinstance(x, MX): + symbol = MX.sym + elif isinstance(x, SX): + symbol = SX.sym + else: + raise Exception("model.x must be casadi.SX or casadi.MX, got {}".format(type(x))) + + if is_empty(p): + model.p = symbol('p', 0, 0) + + if is_empty(z): + model.z = symbol('z', 0, 0) + + return model + +def get_lib_ext(): + lib_ext = '.so' + if sys.platform == 'darwin': + lib_ext = '.dylib' + elif os.name == 'nt': + lib_ext = '' + + return lib_ext + +def get_tera(): + tera_path = get_tera_exec_path() + acados_path = get_acados_path() + + if os.path.exists(tera_path) and os.access(tera_path, os.X_OK): + return tera_path + + repo_url = "https://github.com/acados/tera_renderer/releases" + url = "{}/download/v{}/t_renderer-v{}-{}".format( + repo_url, TERA_VERSION, TERA_VERSION, PLATFORM2TERA[sys.platform]) + + manual_install = 'For manual installation follow these instructions:\n' + manual_install += '1 Download binaries from {}\n'.format(url) + manual_install += '2 Copy them in {}/bin\n'.format(acados_path) + manual_install += '3 Strip the version and platform from the binaries: ' + manual_install += 'as t_renderer-v0.0.34-X -> t_renderer)\n' + manual_install += '4 Enable execution privilege on the file "t_renderer" with:\n' + manual_install += '"chmod +x {}"\n\n'.format(tera_path) + + msg = "\n" + msg += 'Tera template render executable not found, ' + msg += 'while looking in path:\n{}\n'.format(tera_path) + msg += 'In order to be able to render the templates, ' + msg += 'you need to download the tera renderer binaries from:\n' + msg += '{}\n\n'.format(repo_url) + msg += 'Do you wish to set up Tera renderer automatically?\n' + msg += 'y/N? (press y to download tera or any key for manual installation)\n' + + if input(msg) == 'y': + print("Dowloading {}".format(url)) + with urllib.request.urlopen(url) as response, open(tera_path, 'wb') as out_file: + shutil.copyfileobj(response, out_file) + print("Successfully downloaded t_renderer.") + os.chmod(tera_path, 0o755) + return tera_path + + msg_cancel = "\nYou cancelled automatic download.\n\n" + msg_cancel += manual_install + msg_cancel += "Once installed re-run your script.\n\n" + print(msg_cancel) + + sys.exit(1) + + +def render_template(in_file, out_file, output_dir, json_path, template_glob=None): + + acados_path = os.path.dirname(os.path.abspath(__file__)) + if template_glob is None: + template_glob = os.path.join(acados_path, 'c_templates_tera', '**', '*') + cwd = os.getcwd() + + if not os.path.exists(output_dir): + os.makedirs(output_dir) + os.chdir(output_dir) + + tera_path = get_tera() + + # call tera as system cmd + os_cmd = f"{tera_path} '{template_glob}' '{in_file}' '{json_path}' '{out_file}'" + # Windows cmd.exe can not cope with '...', so use "..." instead: + if os.name == 'nt': + os_cmd = os_cmd.replace('\'', '\"') + + status = os.system(os_cmd) + if (status != 0): + raise Exception(f'Rendering of {in_file} failed!\n\nAttempted to execute OS command:\n{os_cmd}\n\n') + + os.chdir(cwd) + + +## Conversion functions +def make_object_json_dumpable(input): + if isinstance(input, (np.ndarray)): + return input.tolist() + elif isinstance(input, (SX)): + return input.serialize() + elif isinstance(input, (MX)): + # NOTE: MX expressions can not be serialized, only Functions. + return input.__str__() + elif isinstance(input, (DM)): + return input.full() + else: + raise TypeError(f"Cannot make input of type {type(input)} dumpable.") + + +def format_class_dict(d): + """ + removes the __ artifact from class to dict conversion + """ + out = {} + for k, v in d.items(): + if isinstance(v, dict): + v = format_class_dict(v) + + out_key = k.split('__', 1)[-1] + out[k.replace(k, out_key)] = v + return out + + +def get_ocp_nlp_layout() -> dict: + python_interface_path = get_python_interface_path() + abs_path = os.path.join(python_interface_path, 'acados_layout.json') + with open(abs_path, 'r') as f: + ocp_nlp_layout = json.load(f) + return ocp_nlp_layout + + +def get_default_simulink_opts() -> dict: + python_interface_path = get_python_interface_path() + abs_path = os.path.join(python_interface_path, 'simulink_default_opts.json') + with open(abs_path, 'r') as f: + simulink_opts = json.load(f) + return simulink_opts + + +def J_to_idx(J): + nrows = J.shape[0] + idx = np.zeros((nrows, )) + for i in range(nrows): + this_idx = np.nonzero(J[i,:])[0] + if len(this_idx) != 1: + raise Exception('Invalid J matrix structure detected, ' \ + 'must contain one nonzero element per row.') + if this_idx.size > 0 and J[i,this_idx[0]] != 1: + raise Exception('J matrices can only contain 1s.') + idx[i] = this_idx[0] + return idx + + +def J_to_idx_slack(J): + nrows = J.shape[0] + ncol = J.shape[1] + idx = np.zeros((ncol, )) + i_idx = 0 + for i in range(nrows): + this_idx = np.nonzero(J[i,:])[0] + if len(this_idx) == 1: + idx[i_idx] = i + i_idx = i_idx + 1 + elif len(this_idx) > 1: + raise Exception('J_to_idx_slack: Invalid J matrix. ' \ + 'Found more than one nonzero in row ' + str(i)) + if this_idx.size > 0 and J[i,this_idx[0]] != 1: + raise Exception('J_to_idx_slack: J matrices can only contain 1s, ' \ + 'got J(' + str(i) + ', ' + str(this_idx[0]) + ') = ' + str(J[i,this_idx[0]]) ) + if not i_idx == ncol: + raise Exception('J_to_idx_slack: J must contain a 1 in every column!') + return idx + + +def acados_dae_model_json_dump(model): + + # load model + x = model.x + xdot = model.xdot + u = model.u + z = model.z + p = model.p + + f_impl = model.f_impl_expr + model_name = model.name + + # create struct with impl_dae_fun, casadi_version + fun_name = model_name + '_impl_dae_fun' + impl_dae_fun = Function(fun_name, [x, xdot, u, z, p], [f_impl]) + + casadi_version = CasadiMeta.version() + str_impl_dae_fun = impl_dae_fun.serialize() + + dae_dict = {"str_impl_dae_fun": str_impl_dae_fun, "casadi_version": casadi_version} + + # dump + json_file = model_name + '_acados_dae.json' + with open(json_file, 'w') as f: + json.dump(dae_dict, f, default=make_object_json_dumpable, indent=4, sort_keys=True) + print("dumped ", model_name, " dae to file:", json_file, "\n") + + +def set_up_imported_gnsf_model(acados_ocp): + + gnsf = acados_ocp.gnsf_model + + # check CasADi version + # dump_casadi_version = gnsf['casadi_version'] + # casadi_version = CasadiMeta.version() + + # if not casadi_version == dump_casadi_version: + # print("WARNING: GNSF model was dumped with another CasADi version.\n" + # + "This might yield errors. Please use the same version for compatibility, serialize version: " + # + dump_casadi_version + " current Python CasADi verison: " + casadi_version) + # input("Press any key to attempt to continue...") + + # load model + phi_fun = Function.deserialize(gnsf['phi_fun']) + phi_fun_jac_y = Function.deserialize(gnsf['phi_fun_jac_y']) + phi_jac_y_uhat = Function.deserialize(gnsf['phi_jac_y_uhat']) + get_matrices_fun = Function.deserialize(gnsf['get_matrices_fun']) + + # obtain gnsf dimensions + size_gnsf_A = get_matrices_fun.size_out(0) + acados_ocp.dims.gnsf_nx1 = size_gnsf_A[1] + acados_ocp.dims.gnsf_nz1 = size_gnsf_A[0] - size_gnsf_A[1] + acados_ocp.dims.gnsf_nuhat = max(phi_fun.size_in(1)) + acados_ocp.dims.gnsf_ny = max(phi_fun.size_in(0)) + acados_ocp.dims.gnsf_nout = max(phi_fun.size_out(0)) + + # save gnsf functions in model + acados_ocp.model.phi_fun = phi_fun + acados_ocp.model.phi_fun_jac_y = phi_fun_jac_y + acados_ocp.model.phi_jac_y_uhat = phi_jac_y_uhat + acados_ocp.model.get_matrices_fun = get_matrices_fun + + # get_matrices_fun = Function([model_name,'_gnsf_get_matrices_fun'], {dummy},... + # {A, B, C, E, L_x, L_xdot, L_z, L_u, A_LO, c, E_LO, B_LO,... + # nontrivial_f_LO, purely_linear, ipiv_x, ipiv_z, c_LO}); + get_matrices_out = get_matrices_fun(0) + acados_ocp.model.gnsf['nontrivial_f_LO'] = int(get_matrices_out[12]) + acados_ocp.model.gnsf['purely_linear'] = int(get_matrices_out[13]) + + if "f_lo_fun_jac_x1k1uz" in gnsf: + f_lo_fun_jac_x1k1uz = Function.deserialize(gnsf['f_lo_fun_jac_x1k1uz']) + acados_ocp.model.f_lo_fun_jac_x1k1uz = f_lo_fun_jac_x1k1uz + else: + dummy_var_x1 = SX.sym('dummy_var_x1', acados_ocp.dims.gnsf_nx1) + dummy_var_x1dot = SX.sym('dummy_var_x1dot', acados_ocp.dims.gnsf_nx1) + dummy_var_z1 = SX.sym('dummy_var_z1', acados_ocp.dims.gnsf_nz1) + dummy_var_u = SX.sym('dummy_var_z1', acados_ocp.dims.nu) + dummy_var_p = SX.sym('dummy_var_z1', acados_ocp.dims.np) + empty_var = SX.sym('empty_var', 0, 0) + + empty_fun = Function('empty_fun', \ + [dummy_var_x1, dummy_var_x1dot, dummy_var_z1, dummy_var_u, dummy_var_p], + [empty_var]) + acados_ocp.model.f_lo_fun_jac_x1k1uz = empty_fun + + del acados_ocp.gnsf_model + + +def idx_perm_to_ipiv(idx_perm): + n = len(idx_perm) + vec = list(range(n)) + ipiv = np.zeros(n) + + print(n, idx_perm) + # import pdb; pdb.set_trace() + for ii in range(n): + idx0 = idx_perm[ii] + for jj in range(ii,n): + if vec[jj]==idx0: + idx1 = jj + break + tmp = vec[ii] + vec[ii] = vec[idx1] + vec[idx1] = tmp + ipiv[ii] = idx1 + + ipiv = ipiv-1 # C 0-based indexing + return ipiv + + +def print_casadi_expression(f): + for ii in range(casadi_length(f)): + print(f[ii,:]) diff --git a/third_party/acados/acados_template/zoro_description.py b/third_party/acados/acados_template/zoro_description.py new file mode 100644 index 0000000000..4d795c1502 --- /dev/null +++ b/third_party/acados/acados_template/zoro_description.py @@ -0,0 +1,78 @@ +# Copyright (c) The acados authors. +# +# This file is part of acados. +# +# The 2-Clause BSD License +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE.; + +from dataclasses import dataclass, field +import numpy as np + + +@dataclass +class ZoroDescription: + """ + Zero-Order Robust Optimization scheme. + + For advanced users. + """ + backoff_scaling_gamma: float = 1.0 + fdbk_K_mat: np.ndarray = None + unc_jac_G_mat: np.ndarray = None # default: an identity matrix + P0_mat: np.ndarray = None + W_mat: np.ndarray = None + idx_lbx_t: list = field(default_factory=list) + idx_ubx_t: list = field(default_factory=list) + idx_lbx_e_t: list = field(default_factory=list) + idx_ubx_e_t: list = field(default_factory=list) + idx_lbu_t: list = field(default_factory=list) + idx_ubu_t: list = field(default_factory=list) + idx_lg_t: list = field(default_factory=list) + idx_ug_t: list = field(default_factory=list) + idx_lg_e_t: list = field(default_factory=list) + idx_ug_e_t: list = field(default_factory=list) + idx_lh_t: list = field(default_factory=list) + idx_uh_t: list = field(default_factory=list) + idx_lh_e_t: list = field(default_factory=list) + idx_uh_e_t: list = field(default_factory=list) + +def process_zoro_description(zoro_description: ZoroDescription): + zoro_description.nw, _ = zoro_description.W_mat.shape + if zoro_description.unc_jac_G_mat is None: + zoro_description.unc_jac_G_mat = np.eye(zoro_description.nw) + zoro_description.nlbx_t = len(zoro_description.idx_lbx_t) + zoro_description.nubx_t = len(zoro_description.idx_ubx_t) + zoro_description.nlbx_e_t = len(zoro_description.idx_lbx_e_t) + zoro_description.nubx_e_t = len(zoro_description.idx_ubx_e_t) + zoro_description.nlbu_t = len(zoro_description.idx_lbu_t) + zoro_description.nubu_t = len(zoro_description.idx_ubu_t) + zoro_description.nlg_t = len(zoro_description.idx_lg_t) + zoro_description.nug_t = len(zoro_description.idx_ug_t) + zoro_description.nlg_e_t = len(zoro_description.idx_lg_e_t) + zoro_description.nug_e_t = len(zoro_description.idx_ug_e_t) + zoro_description.nlh_t = len(zoro_description.idx_lh_t) + zoro_description.nuh_t = len(zoro_description.idx_uh_t) + zoro_description.nlh_e_t = len(zoro_description.idx_lh_e_t) + zoro_description.nuh_e_t = len(zoro_description.idx_uh_e_t) + return zoro_description.__dict__ diff --git a/third_party/acados/build.sh b/third_party/acados/build.sh new file mode 100755 index 0000000000..b45c167b16 --- /dev/null +++ b/third_party/acados/build.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -e + +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" + +ARCHNAME="x86_64" +BLAS_TARGET="X64_AUTOMATIC" +if [ -f /TICI ]; then + ARCHNAME="larch64" + BLAS_TARGET="ARMV8A_ARM_CORTEX_A57" +fi + +ACADOS_FLAGS="-DACADOS_WITH_QPOASES=ON -UBLASFEO_TARGET -DBLASFEO_TARGET=$BLAS_TARGET" + +if [[ "$OSTYPE" == "darwin"* ]]; then + ACADOS_FLAGS="$ACADOS_FLAGS -DCMAKE_OSX_ARCHITECTURES=arm64;x86_64 -DCMAKE_MACOSX_RPATH=1" + ARCHNAME="Darwin" +fi + +if [ ! -d acados_repo/ ]; then + git clone https://github.com/acados/acados.git $DIR/acados_repo + # git clone https://github.com/commaai/acados.git $DIR/acados_repo +fi +cd acados_repo +git fetch --all +git checkout 8af9b0ad180940ef611884574a0b27a43504311d # v0.2.2 +git submodule update --depth=1 --recursive --init + +# build +mkdir -p build +cd build +cmake $ACADOS_FLAGS .. +make -j20 install + +INSTALL_DIR="$DIR/$ARCHNAME" +rm -rf $INSTALL_DIR +mkdir -p $INSTALL_DIR + +rm $DIR/acados_repo/lib/*.json + +rm -rf $DIR/include $DIR/acados_template +cp -r $DIR/acados_repo/include $DIR +cp -r $DIR/acados_repo/lib $INSTALL_DIR +cp -r $DIR/acados_repo/interfaces/acados_template/acados_template $DIR/ +#pip3 install -e $DIR/acados/interfaces/acados_template + +# build tera +cd $DIR/acados_repo/interfaces/acados_template/tera_renderer/ +if [[ "$OSTYPE" == "darwin"* ]]; then + cargo build --verbose --release --target aarch64-apple-darwin + cargo build --verbose --release --target x86_64-apple-darwin + lipo -create -output target/release/t_renderer target/x86_64-apple-darwin/release/t_renderer target/aarch64-apple-darwin/release/t_renderer +else + cargo build --verbose --release +fi +cp target/release/t_renderer $INSTALL_DIR/ diff --git a/third_party/acados/include/acados/dense_qp/dense_qp_common.h b/third_party/acados/include/acados/dense_qp/dense_qp_common.h new file mode 100644 index 0000000000..2a9a974f99 --- /dev/null +++ b/third_party/acados/include/acados/dense_qp/dense_qp_common.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_DENSE_QP_DENSE_QP_COMMON_H_ +#define ACADOS_DENSE_QP_DENSE_QP_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// hpipm +#include "hpipm/include/hpipm_d_dense_qp.h" +#include "hpipm/include/hpipm_d_dense_qp_res.h" +#include "hpipm/include/hpipm_d_dense_qp_sol.h" +// acados +#include "acados/utils/types.h" + +typedef struct d_dense_qp_dim dense_qp_dims; +typedef struct d_dense_qp dense_qp_in; +typedef struct d_dense_qp_sol dense_qp_out; +typedef struct d_dense_qp_res dense_qp_res; +typedef struct d_dense_qp_res_ws dense_qp_res_ws; + + + +#ifndef QP_SOLVER_CONFIG_ +#define QP_SOLVER_CONFIG_ +typedef struct +{ + void (*dims_set)(void *config_, void *dims_, const char *field, const int* value); + acados_size_t (*opts_calculate_size)(void *config, void *dims); + void *(*opts_assign)(void *config, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, void *dims, void *args); + void (*opts_update)(void *config, void *dims, void *args); + void (*opts_set)(void *config_, void *opts_, const char *field, void* value); + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *args); + void *(*memory_assign)(void *config, void *dims, void *args, void *raw_memory); + void (*memory_get)(void *config_, void *mem_, const char *field, void* value); + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *args); + int (*evaluate)(void *config, void *qp_in, void *qp_out, void *args, void *mem, void *work); + void (*eval_sens)(void *config, void *qp_in, void *qp_out, void *opts, void *mem, void *work); +} qp_solver_config; +#endif + + + +#ifndef QP_INFO_ +#define QP_INFO_ +typedef struct +{ + double solve_QP_time; + double condensing_time; + double interface_time; + double total_time; + int num_iter; + int t_computed; +} qp_info; +#endif + + + +/* config */ +// +acados_size_t dense_qp_solver_config_calculate_size(); +// +qp_solver_config *dense_qp_solver_config_assign(void *raw_memory); + +/* dims */ +// +acados_size_t dense_qp_dims_calculate_size(); +// +dense_qp_dims *dense_qp_dims_assign(void *raw_memory); +// +void dense_qp_dims_set(void *config_, void *dims_, const char *field, const int* value); +// + +/* in */ +// +acados_size_t dense_qp_in_calculate_size(dense_qp_dims *dims); +// +dense_qp_in *dense_qp_in_assign(dense_qp_dims *dims, void *raw_memory); + +/* out */ +// +acados_size_t dense_qp_out_calculate_size(dense_qp_dims *dims); +// +dense_qp_out *dense_qp_out_assign(dense_qp_dims *dims, void *raw_memory); +// +void dense_qp_out_get(dense_qp_out *out, const char *field, void *value); + +/* res */ +// +acados_size_t dense_qp_res_calculate_size(dense_qp_dims *dims); +// +dense_qp_res *dense_qp_res_assign(dense_qp_dims *dims, void *raw_memory); +// +acados_size_t dense_qp_res_workspace_calculate_size(dense_qp_dims *dims); +// +dense_qp_res_ws *dense_qp_res_workspace_assign(dense_qp_dims *dims, void *raw_memory); +// +void dense_qp_compute_t(dense_qp_in *qp_in, dense_qp_out *qp_out); +// +void dense_qp_res_compute(dense_qp_in *qp_in, dense_qp_out *qp_out, dense_qp_res *qp_res, dense_qp_res_ws *res_ws); +// +void dense_qp_res_compute_nrm_inf(dense_qp_res *qp_res, double res[4]); + +/* misc */ +// +void dense_qp_stack_slacks_dims(dense_qp_dims *in, dense_qp_dims *out); +// +void dense_qp_stack_slacks(dense_qp_in *in, dense_qp_in *out); +// +void dense_qp_unstack_slacks(dense_qp_out *in, dense_qp_in *qp_out, dense_qp_out *out); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_DENSE_QP_DENSE_QP_COMMON_H_ diff --git a/third_party/acados/include/acados/dense_qp/dense_qp_daqp.h b/third_party/acados/include/acados/dense_qp/dense_qp_daqp.h new file mode 100644 index 0000000000..b262089b4f --- /dev/null +++ b/third_party/acados/include/acados/dense_qp/dense_qp_daqp.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_DENSE_QP_DENSE_QP_DAQP_H_ +#define ACADOS_DENSE_QP_DENSE_QP_DAQP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// daqp +#include "daqp/include/types.h" + +// acados +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/utils/types.h" + + +typedef struct dense_qp_daqp_opts_ +{ + DAQPSettings* daqp_opts; + int warm_start; +} dense_qp_daqp_opts; + + +typedef struct dense_qp_daqp_memory_ +{ + double* lb_tmp; + double* ub_tmp; + int* idxb; + int* idxv_to_idxb; + int* idxs; + int* idxdaqp_to_idxs; + + double* Zl; + double* Zu; + double* zl; + double* zu; + double* d_ls; + double* d_us; + + double time_qp_solver_call; + int iter; + DAQPWorkspace * daqp_work; + +} dense_qp_daqp_memory; + +// opts +acados_size_t dense_qp_daqp_opts_calculate_size(void *config, dense_qp_dims *dims); +// +void *dense_qp_daqp_opts_assign(void *config, dense_qp_dims *dims, void *raw_memory); +// +void dense_qp_daqp_opts_initialize_default(void *config, dense_qp_dims *dims, void *opts_); +// +void dense_qp_daqp_opts_update(void *config, dense_qp_dims *dims, void *opts_); +// +// memory +acados_size_t dense_qp_daqp_workspace_calculate_size(void *config, dense_qp_dims *dims, void *opts_); +// +void *dense_qp_daqp_workspace_assign(void *config, dense_qp_dims *dims, void *raw_memory); +// +acados_size_t dense_qp_daqp_memory_calculate_size(void *config, dense_qp_dims *dims, void *opts_); +// +void *dense_qp_daqp_memory_assign(void *config, dense_qp_dims *dims, void *opts_, void *raw_memory); +// +// functions +int dense_qp_daqp(void *config, dense_qp_in *qp_in, dense_qp_out *qp_out, void *opts_, void *memory_, void *work_); +// +void dense_qp_daqp_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_daqp_memory_reset(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_daqp_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_DENSE_QP_DENSE_QP_DAQP_H_ diff --git a/third_party/acados/include/acados/dense_qp/dense_qp_hpipm.h b/third_party/acados/include/acados/dense_qp/dense_qp_hpipm.h new file mode 100644 index 0000000000..136279d666 --- /dev/null +++ b/third_party/acados/include/acados/dense_qp/dense_qp_hpipm.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_DENSE_QP_DENSE_QP_HPIPM_H_ +#define ACADOS_DENSE_QP_DENSE_QP_HPIPM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// hpipm +#include "hpipm/include/hpipm_d_dense_qp.h" +#include "hpipm/include/hpipm_d_dense_qp_ipm.h" +#include "hpipm/include/hpipm_d_dense_qp_sol.h" +// acados +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/utils/types.h" + + + +typedef struct dense_qp_hpipm_opts_ +{ + struct d_dense_qp_ipm_arg *hpipm_opts; +} dense_qp_hpipm_opts; + + + +typedef struct dense_qp_hpipm_memory_ +{ + struct d_dense_qp_ipm_ws *hpipm_workspace; + double time_qp_solver_call; + int iter; + +} dense_qp_hpipm_memory; + + + +// +acados_size_t dense_qp_hpipm_opts_calculate_size(void *config, void *dims); +// +void *dense_qp_hpipm_opts_assign(void *config, void *dims, void *raw_memory); +// +void dense_qp_hpipm_opts_initialize_default(void *config, void *dims, void *opts_); +// +void dense_qp_hpipm_opts_update(void *config, void *dims, void *opts_); +// +acados_size_t dense_qp_hpipm_calculate_memory_size(void *dims, void *opts_); +// +void *dense_qp_hpipm_assign_memory(void *dims, void *opts_, void *raw_memory); +// +acados_size_t dense_qp_hpipm_calculate_workspace_size(void *dims, void *opts_); +// +int dense_qp_hpipm(void *config, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_hpipm_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_hpipm_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_DENSE_QP_DENSE_QP_HPIPM_H_ diff --git a/third_party/acados/include/acados/dense_qp/dense_qp_ooqp.h b/third_party/acados/include/acados/dense_qp/dense_qp_ooqp.h new file mode 100644 index 0000000000..d051cb15f7 --- /dev/null +++ b/third_party/acados/include/acados/dense_qp/dense_qp_ooqp.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_DENSE_QP_DENSE_QP_OOQP_H_ +#define ACADOS_DENSE_QP_DENSE_QP_OOQP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/utils/types.h" + +enum dense_qp_ooqp_termination_code +{ + DENSE_SUCCESSFUL_TERMINATION = 0, + DENSE_NOT_FINISHED, + DENSE_MAX_ITS_EXCEEDED, + DENSE_INFEASIBLE, + DENSE_UNKNOWN +}; + +typedef struct dense_qp_ooqp_opts_ +{ + int printLevel; + int useDiagonalWeights; // TODO(dimitris): implement option + int fixHessian; + int fixDynamics; + int fixInequalities; +} dense_qp_ooqp_opts; + +typedef struct dense_qp_ooqp_workspace_ +{ + double *x; + double *gamma; + double *phi; + double *y; + double *z; + double *lambda; + double *pi; + double objectiveValue; +} dense_qp_ooqp_workspace; + +typedef struct dense_qp_ooqp_memory_ +{ + int firstRun; + int nx; + int my; + int mz; + double *c; + double *dQ; + double *xlow; + char *ixlow; + double *xupp; + char *ixupp; + double *dA; + double *bA; + double *dC; + double *clow; + char *iclow; + double *cupp; + char *icupp; + double time_qp_solver_call; + int iter; + +} dense_qp_ooqp_memory; + +// +acados_size_t dense_qp_ooqp_opts_calculate_size(void *config_, dense_qp_dims *dims); +// +void *dense_qp_ooqp_opts_assign(void *config_, dense_qp_dims *dims, void *raw_memory); +// +void dense_qp_ooqp_opts_initialize_default(void *config_, dense_qp_dims *dims, void *opts_); +// +void dense_qp_ooqp_opts_update(void *config_, dense_qp_dims *dims, void *opts_); +// +acados_size_t dense_qp_ooqp_memory_calculate_size(void *config_, dense_qp_dims *dims, void *opts_); +// +void *dense_qp_ooqp_memory_assign(void *config_, dense_qp_dims *dims, void *opts_, + void *raw_memory); +// +acados_size_t dense_qp_ooqp_workspace_calculate_size(void *config_, dense_qp_dims *dims, void *opts_); +// +int dense_qp_ooqp(void *config_, dense_qp_in *qp_in, dense_qp_out *qp_out, void *opts_, + void *memory_, void *work_); +// +void dense_qp_ooqp_destroy(void *mem_, void *work); +// +void dense_qp_ooqp_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_ooqp_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_DENSE_QP_DENSE_QP_OOQP_H_ diff --git a/third_party/acados/include/acados/dense_qp/dense_qp_qore.h b/third_party/acados/include/acados/dense_qp/dense_qp_qore.h new file mode 100644 index 0000000000..392e472918 --- /dev/null +++ b/third_party/acados/include/acados/dense_qp/dense_qp_qore.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_DENSE_QP_DENSE_QP_QORE_H_ +#define ACADOS_DENSE_QP_DENSE_QP_QORE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// qore +#include "qore/QPSOLVER_DENSE/include/qpsolver_dense.h" +// acados +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/utils/types.h" + +typedef struct dense_qp_qore_opts_ +{ + int nsmax; // maximum size of Schur complement + int print_freq; // print frequency, + // prtfreq < 0: disable printing; + // prtfreq == 0: print on each call and include working set changes; + // prtfreq > 0: print on every prtfreq seconds, but do not include working set + // changes; + int warm_start; // warm start with updated matrices H and C + int warm_strategy; // 0: ramp-up from zero homotopy; 1: setup homotopy from the previous + // solution + int hot_start; // hot start with unchanged matrices H and C + int max_iter; // maximum number of iterations + int compute_t; // compute t in qp_out (to have correct residuals in NLP) +} dense_qp_qore_opts; + +typedef struct dense_qp_qore_memory_ +{ + double *H; + double *HH; + double *g; + double *gg; + double *Zl; + double *Zu; + double *zl; + double *zu; + double *A; + double *b; + double *C; + double *CC; + double *Ct; + double *CCt; + double *d_lb0; + double *d_ub0; + double *d_lb; + double *d_ub; + double *d_lg; + double *d_ug; + double *d_ls; + double *d_us; + double *lb; + double *ub; + int *idxb; + int *idxb_stacked; + int *idxs; + double *prim_sol; + double *dual_sol; + QoreProblemDense *QP; + int num_iter; + dense_qp_in *qp_stacked; + double time_qp_solver_call; + int iter; + +} dense_qp_qore_memory; + +acados_size_t dense_qp_qore_opts_calculate_size(void *config, dense_qp_dims *dims); +// +void *dense_qp_qore_opts_assign(void *config, dense_qp_dims *dims, void *raw_memory); +// +void dense_qp_qore_opts_initialize_default(void *config, dense_qp_dims *dims, void *opts_); +// +void dense_qp_qore_opts_update(void *config, dense_qp_dims *dims, void *opts_); +// +acados_size_t dense_qp_qore_memory_calculate_size(void *config, dense_qp_dims *dims, void *opts_); +// +void *dense_qp_qore_memory_assign(void *config, dense_qp_dims *dims, void *opts_, void *raw_memory); +// +acados_size_t dense_qp_qore_workspace_calculate_size(void *config, dense_qp_dims *dims, void *opts_); +// +int dense_qp_qore(void *config, dense_qp_in *qp_in, dense_qp_out *qp_out, void *opts_, void *memory_, void *work_); +// +void dense_qp_qore_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_qore_config_initialize_default(void *config); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_DENSE_QP_DENSE_QP_QORE_H_ diff --git a/third_party/acados/include/acados/dense_qp/dense_qp_qpoases.h b/third_party/acados/include/acados/dense_qp/dense_qp_qpoases.h new file mode 100644 index 0000000000..0e13d3ef64 --- /dev/null +++ b/third_party/acados/include/acados/dense_qp/dense_qp_qpoases.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_DENSE_QP_DENSE_QP_QPOASES_H_ +#define ACADOS_DENSE_QP_DENSE_QP_QPOASES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/utils/types.h" + +typedef struct dense_qp_qpoases_opts_ +{ + double max_cputime; // maximum cpu time in seconds + int max_nwsr; // maximum number of working set recalculations + int warm_start; // warm start with dual_sol in memory + int use_precomputed_cholesky; + int hotstart; // this option requires constant data matrices! (eg linear MPC, inexact schemes + // with frozen sensitivities) + int set_acado_opts; // use same options as in acado code generation + int compute_t; // compute t in qp_out (to have correct residuals in NLP) + double tolerance; // terminationTolerance +} dense_qp_qpoases_opts; + +typedef struct dense_qp_qpoases_memory_ +{ + double *H; + double *HH; + double *R; + double *g; + double *gg; + double *Zl; + double *Zu; + double *zl; + double *zu; + double *A; + double *b; + double *d_lb0; + double *d_ub0; + double *d_lb; + double *d_ub; + double *C; + double *CC; + double *d_lg0; + double *d_ug0; + double *d_lg; + double *d_ug; + double *d_ls; + double *d_us; + int *idxb; + int *idxb_stacked; + int *idxs; + double *prim_sol; + double *dual_sol; + void *QPB; // NOTE(giaf): cast to QProblemB to use + void *QP; // NOTE(giaf): cast to QProblem to use + double cputime; // cputime of qpoases + int nwsr; // performed number of working set recalculations + int first_it; // to be used with hotstart + dense_qp_in *qp_stacked; + double time_qp_solver_call; // equal to cputime + int iter; + +} dense_qp_qpoases_memory; + +acados_size_t dense_qp_qpoases_opts_calculate_size(void *config, dense_qp_dims *dims); +// +void *dense_qp_qpoases_opts_assign(void *config, dense_qp_dims *dims, void *raw_memory); +// +void dense_qp_qpoases_opts_initialize_default(void *config, dense_qp_dims *dims, void *opts_); +// +void dense_qp_qpoases_opts_update(void *config, dense_qp_dims *dims, void *opts_); +// +acados_size_t dense_qp_qpoases__memorycalculate_size(void *config, dense_qp_dims *dims, void *opts_); +// +void *dense_qp_qpoases_memory_assign(void *config, dense_qp_dims *dims, void *opts_, void *raw_memory); +// +acados_size_t dense_qp_qpoases_workspace_calculate_size(void *config, dense_qp_dims *dims, void *opts_); +// +int dense_qp_qpoases(void *config, dense_qp_in *qp_in, dense_qp_out *qp_out, void *opts_, void *memory_, void *work_); +// +void dense_qp_qpoases_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_qpoases_memory_reset(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void dense_qp_qpoases_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_DENSE_QP_DENSE_QP_QPOASES_H_ diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_common.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_common.h new file mode 100644 index 0000000000..ba97db9768 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_common.h @@ -0,0 +1,446 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + + +/// \defgroup ocp_nlp ocp_nlp +/// @{ +/// @} + +/// \defgroup ocp_nlp_solver ocp_nlp_solver +/// @{ +/// @} + +/// \ingroup ocp_nlp +/// @{ + +/// \ingroup ocp_nlp_solver +/// @{ + +/// \defgroup ocp_nlp_common ocp_nlp_common +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_COMMON_H_ +#define ACADOS_OCP_NLP_OCP_NLP_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_nlp/ocp_nlp_constraints_common.h" +#include "acados/ocp_nlp/ocp_nlp_cost_common.h" +#include "acados/ocp_nlp/ocp_nlp_dynamics_common.h" +#include "acados/ocp_nlp/ocp_nlp_reg_common.h" +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/ocp_qp/ocp_qp_xcond_solver.h" +#include "acados/sim/sim_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * config + ************************************************/ + +typedef struct ocp_nlp_config +{ + int N; // number of stages + + // solver-specific implementations of memory management functions + acados_size_t (*opts_calculate_size)(void *config, void *dims); + void *(*opts_assign)(void *config, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, void *dims, void *opts_); + void (*opts_update)(void *config, void *dims, void *opts_); + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *opts_); + void *(*memory_assign)(void *config, void *dims, void *opts_, void *raw_memory); + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *opts_); + void (*opts_set)(void *config_, void *opts_, const char *field, void* value); + void (*opts_set_at_stage)(void *config_, void *opts_, size_t stage, const char *field, void* value); + // evaluate solver // TODO rename into solve + int (*evaluate)(void *config, void *dims, void *nlp_in, void *nlp_out, void *opts_, void *mem, void *work); + void (*eval_param_sens)(void *config, void *dims, void *opts_, void *mem, void *work, + char *field, int stage, int index, void *sens_nlp_out); + // prepare memory + int (*precompute)(void *config, void *dims, void *nlp_in, void *nlp_out, void *opts_, void *mem, void *work); + void (*memory_reset_qp_solver)(void *config, void *dims, void *nlp_in, void *nlp_out, void *opts_, void *mem, void *work); + // initalize this struct with default values + void (*config_initialize_default)(void *config); + // general getter + void (*get)(void *config_, void *dims, void *mem_, const char *field, void *return_value_); + void (*opts_get)(void *config_, void *dims, void *opts_, const char *field, void *return_value_); + void (*work_get)(void *config_, void *dims, void *work_, const char *field, void *return_value_); + // config structs of submodules + ocp_qp_xcond_solver_config *qp_solver; // TODO rename xcond_solver + ocp_nlp_dynamics_config **dynamics; + ocp_nlp_cost_config **cost; + ocp_nlp_constraints_config **constraints; + ocp_nlp_reg_config *regularize; + +} ocp_nlp_config; + +// +acados_size_t ocp_nlp_config_calculate_size(int N); +// +ocp_nlp_config *ocp_nlp_config_assign(int N, void *raw_memory); + + + +/************************************************ + * dims + ************************************************/ + +/// Structure to store dimensions/number of variables. +typedef struct ocp_nlp_dims +{ + void **cost; + void **dynamics; + void **constraints; + ocp_qp_xcond_solver_dims *qp_solver; // xcond solver instead ?? + ocp_nlp_reg_dims *regularize; + + int *nv; // number of primal variables (states+controls+slacks) + int *nx; // number of differential states + int *nu; // number of inputs + int *ni; // number of two-sided inequality constraints: nb+ng+nh+ns + int *nz; // number of algebraic variables + int *ns; // number of slack variables + int N; // number of shooting nodes + + void *raw_memory; // Pointer to allocated memory, to be used for freeing +} ocp_nlp_dims; + +// +acados_size_t ocp_nlp_dims_calculate_size(void *config); +// +ocp_nlp_dims *ocp_nlp_dims_assign(void *config, void *raw_memory); + +/// Sets the dimension of optimization variables +/// (states, constrols, algebraic variables, slack variables). +/// +/// \param config_ The configuration struct. +/// \param dims_ The dimension struct. +/// \param field The type of optimization variables, either nx, nu, nz, or ns. +/// \param value_array Number of variables for each stage. +void ocp_nlp_dims_set_opt_vars(void *config_, void *dims_, + const char *field, const void* value_array); + +/// Sets the dimensions of constraints functions for a stage +/// (bounds on states, bounds on controls, equality constraints, +/// inequality constraints). +/// +/// \param config_ The configuration struct. +/// \param dims_ The dimension struct. +/// \param stage Stage number. +/// \param field The type of constraint/bound, either nbx, nbu, ng, or nh. +/// \param value_field Number of constraints/bounds for the given stage. +void ocp_nlp_dims_set_constraints(void *config_, void *dims_, int stage, + const char *field, const void* value_field); + +/// Sets the dimensions of the cost terms for a stage. +/// +/// \param config_ The configuration struct. +/// \param dims_ The dimension struct. +/// \param stage Stage number. +/// \param field Type of cost term, can be eiter ny. +/// \param value_field Number of cost terms/residuals for the given stage. +void ocp_nlp_dims_set_cost(void *config_, void *dims_, int stage, const char *field, + const void* value_field); + +/// Sets the dimensions of the dynamics for a stage. +/// +/// \param config_ The configuration struct. +/// \param dims_ The dimension struct. +/// \param stage Stage number. +/// \param field TBD +/// \param value TBD +void ocp_nlp_dims_set_dynamics(void *config_, void *dims_, int stage, const char *field, + const void* value); + +/************************************************ + * Inputs + ************************************************/ + +/// Struct for storing the inputs of an OCP NLP solver +typedef struct ocp_nlp_in +{ + /// Length of sampling intervals/timesteps. + double *Ts; + + /// Pointers to cost functions (TBC). + void **cost; + + /// Pointers to dynamics functions (TBC). + void **dynamics; + + /// Pointers to constraints functions (TBC). + void **constraints; + + /// Pointer to allocated memory, to be used for freeing. + void *raw_memory; + +} ocp_nlp_in; + +// +acados_size_t ocp_nlp_in_calculate_size_self(int N); +// +acados_size_t ocp_nlp_in_calculate_size(ocp_nlp_config *config, ocp_nlp_dims *dims); +// +ocp_nlp_in *ocp_nlp_in_assign_self(int N, void *raw_memory); +// +ocp_nlp_in *ocp_nlp_in_assign(ocp_nlp_config *config, ocp_nlp_dims *dims, void *raw_memory); + + +/************************************************ + * out + ************************************************/ + +typedef struct ocp_nlp_out +{ + struct blasfeo_dvec *ux; // NOTE: this contains [u; x; s_l; s_u]! - rename to uxs? + struct blasfeo_dvec *z; // algebraic vairables + struct blasfeo_dvec *pi; // multipliers for dynamics + struct blasfeo_dvec *lam; // inequality mulitpliers + struct blasfeo_dvec *t; // slack variables corresponding to evaluation of all inequalities (at the solution) + + // NOTE: the inequalities are internally organized in the following order: + // [ lbu lbx lg lh lphi ubu ubx ug uh uphi; lsbu lsbx lsg lsh lsphi usbu usbx usg ush usphi] + double inf_norm_res; + + void *raw_memory; // Pointer to allocated memory, to be used for freeing + +} ocp_nlp_out; + +// +acados_size_t ocp_nlp_out_calculate_size(ocp_nlp_config *config, ocp_nlp_dims *dims); +// +ocp_nlp_out *ocp_nlp_out_assign(ocp_nlp_config *config, ocp_nlp_dims *dims, + void *raw_memory); + + + +/************************************************ + * options + ************************************************/ + +/// Globalization types +typedef enum +{ + FIXED_STEP, + MERIT_BACKTRACKING, +} ocp_nlp_globalization_t; + +typedef struct ocp_nlp_opts +{ + ocp_qp_xcond_solver_opts *qp_solver_opts; // xcond solver opts instead ??? + void *regularize; + void **dynamics; // dynamics_opts + void **cost; // cost_opts + void **constraints; // constraints_opts + double step_length; // step length in case of FIXED_STEP + double levenberg_marquardt; // LM factor to be added to the hessian before regularization + int reuse_workspace; + int num_threads; + int print_level; + + // TODO: move to separate struct? + ocp_nlp_globalization_t globalization; + int full_step_dual; + int line_search_use_sufficient_descent; + int globalization_use_SOC; + double alpha_min; + double alpha_reduction; + double eps_sufficient_descent; +} ocp_nlp_opts; + +// +acados_size_t ocp_nlp_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_opts_set(void *config_, void *opts_, const char *field, void* value); +// +void ocp_nlp_opts_set_at_stage(void *config, void *opts, int stage, const char *field, void *value); + + +/************************************************ + * residuals + ************************************************/ + +typedef struct ocp_nlp_res +{ + struct blasfeo_dvec *res_stat; // stationarity + struct blasfeo_dvec *res_eq; // dynamics + struct blasfeo_dvec *res_ineq; // inequality constraints + struct blasfeo_dvec *res_comp; // complementarity + struct blasfeo_dvec tmp; // tmp + double inf_norm_res_stat; + double inf_norm_res_eq; + double inf_norm_res_ineq; + double inf_norm_res_comp; + acados_size_t memsize; +} ocp_nlp_res; + +// +acados_size_t ocp_nlp_res_calculate_size(ocp_nlp_dims *dims); +// +ocp_nlp_res *ocp_nlp_res_assign(ocp_nlp_dims *dims, void *raw_memory); +// +void ocp_nlp_res_get_inf_norm(ocp_nlp_res *res, double *out); + +/************************************************ + * memory + ************************************************/ + +typedef struct ocp_nlp_memory +{ +// void *qp_solver_mem; // xcond solver mem instead ??? + ocp_qp_xcond_solver_memory *qp_solver_mem; // xcond solver mem instead ??? + void *regularize_mem; + void **dynamics; // dynamics memory + void **cost; // cost memory + void **constraints; // constraints memory + + // residuals + ocp_nlp_res *nlp_res; + + // qp in & out + ocp_qp_in *qp_in; + ocp_qp_out *qp_out; + // QP stuff not entering the qp_in struct + struct blasfeo_dmat *dzduxt; // dzdux transposed + struct blasfeo_dvec *z_alg; // z_alg, output algebraic variables + + struct blasfeo_dvec *cost_grad; + struct blasfeo_dvec *ineq_fun; + struct blasfeo_dvec *ineq_adj; + struct blasfeo_dvec *dyn_fun; + struct blasfeo_dvec *dyn_adj; + + double cost_value; + + bool *set_sim_guess; // indicate if there is new explicitly provided guess for integration variables + struct blasfeo_dvec *sim_guess; + + int *sqp_iter; // pointer to iteration number + +} ocp_nlp_memory; + +// +acados_size_t ocp_nlp_memory_calculate_size(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_opts *opts); +// +ocp_nlp_memory *ocp_nlp_memory_assign(ocp_nlp_config *config, ocp_nlp_dims *dims, + ocp_nlp_opts *opts, void *raw_memory); + + + +/************************************************ + * workspace + ************************************************/ + +typedef struct ocp_nlp_workspace +{ + + void *qp_work; + void **dynamics; // dynamics_workspace + void **cost; // cost_workspace + void **constraints; // constraints_workspace + + // for globalization: -> move to module?! + ocp_nlp_out *tmp_nlp_out; + ocp_nlp_out *weight_merit_fun; + struct blasfeo_dvec tmp_nxu; + struct blasfeo_dvec tmp_ni; + struct blasfeo_dvec dxnext_dy; + +} ocp_nlp_workspace; + +// +acados_size_t ocp_nlp_workspace_calculate_size(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_opts *opts); +// +ocp_nlp_workspace *ocp_nlp_workspace_assign(ocp_nlp_config *config, ocp_nlp_dims *dims, + ocp_nlp_opts *opts, ocp_nlp_memory *mem, void *raw_memory); + + + +/************************************************ + * function + ************************************************/ + +void ocp_nlp_alias_memory_to_submodules(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_initialize_submodules(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_approximate_qp_matrices(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_approximate_qp_vectors_sqp(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_embed_initial_value(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_update_variables_sqp(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work, double alpha); +// +int ocp_nlp_precompute_common(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +double ocp_nlp_line_search(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work, + int check_early_termination); +// +double ocp_nlp_evaluate_merit_fun(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_initialize_t_slacks(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); +// +void ocp_nlp_res_compute(ocp_nlp_dims *dims, ocp_nlp_in *in, ocp_nlp_out *out, + ocp_nlp_res *res, ocp_nlp_memory *mem); +// +void ocp_nlp_cost_compute(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + ocp_nlp_out *out, ocp_nlp_opts *opts, ocp_nlp_memory *mem, ocp_nlp_workspace *work); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_COMMON_H_ +/// @} +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_bgh.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_bgh.h new file mode 100644 index 0000000000..9dbf16f6dc --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_bgh.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_constraints +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_BGH_H_ +#define ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_BGH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/ocp_nlp/ocp_nlp_constraints_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * dims + ************************************************/ + +typedef struct +{ + int nx; + int nu; + int nz; + int nb; // nbx + nbu + int nbu; // number of input box constraints + int nbx; // number of state box constraints + int ng; // number of general linear constraints + int nh; // number of nonlinear path constraints + int ns; // nsbu + nsbx + nsg + nsh + int nsbu; // number of softened input bounds + int nsbx; // number of softened state bounds + int nsg; // number of softened general linear constraints + int nsh; // number of softened nonlinear constraints + int nbue; // number of input box constraints which are equality + int nbxe; // number of state box constraints which are equality + int nge; // number of general linear constraints which are equality + int nhe; // number of nonlinear path constraints which are equality +} ocp_nlp_constraints_bgh_dims; + +// +acados_size_t ocp_nlp_constraints_bgh_dims_calculate_size(void *config); +// +void *ocp_nlp_constraints_bgh_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_constraints_bgh_dims_get(void *config_, void *dims_, const char *field, int* value); +// +void ocp_nlp_constraints_bgh_dims_set(void *config_, void *dims_, + const char *field, const int* value); + + +/************************************************ + * model + ************************************************/ + +typedef struct +{ + int *idxb; + int *idxs; + int *idxe; + struct blasfeo_dvec d; // gathers bounds + struct blasfeo_dmat DCt; // general linear constraint matrix + // lg <= [D, C] * [u; x] <= ug + external_function_generic *nl_constr_h_fun; // nonlinear: lh <= h(x,u) <= uh + external_function_generic *nl_constr_h_fun_jac; // nonlinear: lh <= h(x,u) <= uh + external_function_generic *nl_constr_h_fun_jac_hess; // nonlinear: lh <= h(x,u) <= uh +} ocp_nlp_constraints_bgh_model; + +// +acados_size_t ocp_nlp_constraints_bgh_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_constraints_bgh_model_assign(void *config, void *dims, void *raw_memory); +// +int ocp_nlp_constraints_bgh_model_set(void *config_, void *dims_, + void *model_, const char *field, void *value); + +// +void ocp_nlp_constraints_bgh_model_get(void *config_, void *dims_, + void *model_, const char *field, void *value); + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + int compute_adj; + int compute_hess; +} ocp_nlp_constraints_bgh_opts; + +// +acados_size_t ocp_nlp_constraints_bgh_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_constraints_bgh_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_constraints_bgh_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_constraints_bgh_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_constraints_bgh_opts_set(void *config, void *opts, char *field, void *value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + struct blasfeo_dvec fun; + struct blasfeo_dvec adj; + struct blasfeo_dvec *ux; // pointer to ux in nlp_out + struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out + struct blasfeo_dvec *lam; // pointer to lam in nlp_out + struct blasfeo_dvec *tmp_lam;// pointer to lam in tmp_nlp_out + struct blasfeo_dvec *z_alg; // pointer to z_alg in ocp_nlp memory + struct blasfeo_dmat *DCt; // pointer to DCt in qp_in + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dmat *dzduxt; // pointer to dzduxt in ocp_nlp memory + int *idxb; // pointer to idxb[ii] in qp_in + int *idxs_rev; // pointer to idxs_rev[ii] in qp_in + int *idxe; // pointer to idxe[ii] in qp_in +} ocp_nlp_constraints_bgh_memory; + +// +acados_size_t ocp_nlp_constraints_bgh_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_constraints_bgh_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +struct blasfeo_dvec *ocp_nlp_constraints_bgh_memory_get_fun_ptr(void *memory_); +// +struct blasfeo_dvec *ocp_nlp_constraints_bgh_memory_get_adj_ptr(void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_lam_ptr(struct blasfeo_dvec *lam, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_tmp_lam_ptr(struct blasfeo_dvec *tmp_lam, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_DCt_ptr(struct blasfeo_dmat *DCt, void *memory); +// +void ocp_nlp_constraints_bgh_memory_set_RSQrq_ptr(struct blasfeo_dmat *RSQrq, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_dzduxt_ptr(struct blasfeo_dmat *dzduxt, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_idxb_ptr(int *idxb, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_idxs_rev_ptr(int *idxs_rev, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_idxe_ptr(int *idxe, void *memory_); + + + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat tmp_nv_nv; + struct blasfeo_dmat tmp_nz_nh; + struct blasfeo_dmat tmp_nv_nh; + struct blasfeo_dmat tmp_nz_nv; + struct blasfeo_dmat hess_z; + struct blasfeo_dvec tmp_ni; + struct blasfeo_dvec tmp_nh; +} ocp_nlp_constraints_bgh_workspace; + +// +acados_size_t ocp_nlp_constraints_bgh_workspace_calculate_size(void *config, void *dims, void *opts); + +/* functions */ + +// +void ocp_nlp_constraints_bgh_config_initialize_default(void *config); +// +void ocp_nlp_constraints_bgh_initialize(void *config, void *dims, void *model, void *opts, + void *mem, void *work); +// +void ocp_nlp_constraints_bgh_update_qp_matrices(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); + +// +void ocp_nlp_constraints_bgh_compute_fun(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); +// +void ocp_nlp_constraints_bgh_bounds_update(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_BGH_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_bgp.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_bgp.h new file mode 100644 index 0000000000..eb05edf7a6 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_bgp.h @@ -0,0 +1,218 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_constraints +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_BGP_H_ +#define ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_BGP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/ocp_nlp/ocp_nlp_constraints_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/* dims */ + +typedef struct +{ + int nx; + int nu; + int nz; + int nb; // nbx + nbu + int nbu; + int nbx; + int ng; // number of general linear constraints + int nphi; // dimension of convex outer part + int ns; // nsbu + nsbx + nsg + nsphi + int nsbu; // number of softened input bounds + int nsbx; // number of softened state bounds + int nsg; // number of softened general linear constraints + int nsphi; // number of softened nonlinear constraints + int nr; // dimension of nonlinear function in convex_over_nonlinear constraint + int nbue; // number of input box constraints which are equality + int nbxe; // number of state box constraints which are equality + int nge; // number of general linear constraints which are equality + int nphie; // number of nonlinear path constraints which are equality +} ocp_nlp_constraints_bgp_dims; + +// +acados_size_t ocp_nlp_constraints_bgp_dims_calculate_size(void *config); +// +void *ocp_nlp_constraints_bgp_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_constraints_bgp_dims_get(void *config_, void *dims_, const char *field, int* value); + + +/* model */ + +typedef struct +{ + // ocp_nlp_constraints_bgp_dims *dims; + int *idxb; + int *idxs; + int *idxe; + struct blasfeo_dvec d; + struct blasfeo_dmat DCt; + external_function_generic *nl_constr_phi_o_r_fun_phi_jac_ux_z_phi_hess_r_jac_ux; + external_function_generic *nl_constr_phi_o_r_fun; + external_function_generic *nl_constr_r_fun_jac; +} ocp_nlp_constraints_bgp_model; + +// +acados_size_t ocp_nlp_constraints_bgp_calculate_size(void *config, void *dims); +// +void *ocp_nlp_constraints_bgp_assign(void *config, void *dims, void *raw_memory); +// +int ocp_nlp_constraints_bgp_model_set(void *config_, void *dims_, + void *model_, const char *field, void *value); +// +void ocp_nlp_constraints_bgp_model_get(void *config_, void *dims_, + void *model_, const char *field, void *value); + +/* options */ + +typedef struct +{ + int compute_adj; + int compute_hess; +} ocp_nlp_constraints_bgp_opts; + +// +acados_size_t ocp_nlp_constraints_bgp_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_constraints_bgp_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_constraints_bgp_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_constraints_bgp_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_constraints_bgp_opts_set(void *config, void *opts, char *field, void *value); + +/* memory */ + +typedef struct +{ + struct blasfeo_dvec fun; + struct blasfeo_dvec adj; + struct blasfeo_dvec *ux; // pointer to ux in nlp_out + struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out + struct blasfeo_dvec *lam; // pointer to lam in nlp_out + struct blasfeo_dvec *tmp_lam;// pointer to lam in tmp_nlp_out + struct blasfeo_dvec *z_alg; // pointer to z_alg in ocp_nlp memory + struct blasfeo_dmat *DCt; // pointer to DCt in qp_in + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dmat *dzduxt; // pointer to dzduxt in ocp_nlp memory + int *idxb; // pointer to idxb[ii] in qp_in + int *idxs_rev; // pointer to idxs_rev[ii] in qp_in + int *idxe; // pointer to idxe[ii] in qp_in +} ocp_nlp_constraints_bgp_memory; + +// +acados_size_t ocp_nlp_constraints_bgp_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_constraints_bgp_memory_assign(void *config, void *dims, void *opts, + void *raw_memory); +// +struct blasfeo_dvec *ocp_nlp_constraints_bgp_memory_get_fun_ptr(void *memory_); +// +struct blasfeo_dvec *ocp_nlp_constraints_bgp_memory_get_adj_ptr(void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_lam_ptr(struct blasfeo_dvec *lam, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_tmp_lam_ptr(struct blasfeo_dvec *tmp_lam, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_DCt_ptr(struct blasfeo_dmat *DCt, void *memory); +// +void ocp_nlp_constraints_bgp_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_dzduxt_ptr(struct blasfeo_dmat *dzduxt, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_idxb_ptr(int *idxb, void *memory_); +// +void ocp_nlp_constraints_bgp_memory_set_idxs_rev_ptr(int *idxs_rev, void *memory_); +// +void ocp_nlp_constraints_bgh_memory_set_idxe_ptr(int *idxe, void *memory_); + +/* workspace */ + +typedef struct +{ + struct blasfeo_dvec tmp_ni; + struct blasfeo_dmat jac_r_ux_tran; + struct blasfeo_dmat tmp_nr_nphi_nr; + struct blasfeo_dmat tmp_nv_nr; + struct blasfeo_dmat tmp_nv_nphi; + struct blasfeo_dmat tmp_nz_nphi; +} ocp_nlp_constraints_bgp_workspace; + +// +acados_size_t ocp_nlp_constraints_bgp_workspace_calculate_size(void *config, void *dims, void *opts); + +/* functions */ + +// +void ocp_nlp_constraints_bgp_config_initialize_default(void *config); +// +void ocp_nlp_constraints_bgp_initialize(void *config, void *dims, void *model, + void *opts, void *mem, void *work); +// +void ocp_nlp_constraints_bgp_update_qp_matrices(void *config_, void *dims, + void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_constraints_bgp_compute_fun(void *config_, void *dims, + void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_constraints_bgp_bounds_update(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_BGP_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_common.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_common.h new file mode 100644 index 0000000000..bb73c468de --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_constraints_common.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \ingroup ocp_nlp +/// @{ + +/// \defgroup ocp_nlp_constraints ocp_nlp_constraints +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_COMMON_H_ +#define ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * config + ************************************************/ + +typedef struct +{ + acados_size_t (*dims_calculate_size)(void *config); + void *(*dims_assign)(void *config, void *raw_memory); + acados_size_t (*model_calculate_size)(void *config, void *dims); + void *(*model_assign)(void *config, void *dims, void *raw_memory); + int (*model_set)(void *config_, void *dims_, void *model_, const char *field, void *value); + void (*model_get)(void *config_, void *dims_, void *model_, const char *field, void *value); + acados_size_t (*opts_calculate_size)(void *config, void *dims); + void *(*opts_assign)(void *config, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, void *dims, void *opts); + void (*opts_update)(void *config, void *dims, void *opts); + void (*opts_set)(void *config, void *opts, char *field, void *value); + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *opts); + struct blasfeo_dvec *(*memory_get_fun_ptr)(void *memory); + struct blasfeo_dvec *(*memory_get_adj_ptr)(void *memory); + void (*memory_set_ux_ptr)(struct blasfeo_dvec *ux, void *memory); + void (*memory_set_tmp_ux_ptr)(struct blasfeo_dvec *tmp_ux, void *memory); + void (*memory_set_lam_ptr)(struct blasfeo_dvec *lam, void *memory); + void (*memory_set_tmp_lam_ptr)(struct blasfeo_dvec *tmp_lam, void *memory); + void (*memory_set_DCt_ptr)(struct blasfeo_dmat *DCt, void *memory); + void (*memory_set_RSQrq_ptr)(struct blasfeo_dmat *RSQrq, void *memory); + void (*memory_set_z_alg_ptr)(struct blasfeo_dvec *z_alg, void *memory); + void (*memory_set_dzdux_tran_ptr)(struct blasfeo_dmat *dzduxt, void *memory); + void (*memory_set_idxb_ptr)(int *idxb, void *memory); + void (*memory_set_idxs_rev_ptr)(int *idxs_rev, void *memory); + void (*memory_set_idxe_ptr)(int *idxe, void *memory); + void *(*memory_assign)(void *config, void *dims, void *opts, void *raw_memory); + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *opts); + void (*initialize)(void *config, void *dims, void *model, void *opts, void *mem, void *work); + void (*update_qp_matrices)(void *config, void *dims, void *model, void *opts, void *mem, void *work); + void (*compute_fun)(void *config, void *dims, void *model, void *opts, void *mem, void *work); + void (*bounds_update)(void *config, void *dims, void *model, void *opts, void *mem, void *work); + void (*config_initialize_default)(void *config); + // dimension setters + void (*dims_set)(void *config_, void *dims_, const char *field, const int *value); + void (*dims_get)(void *config_, void *dims_, const char *field, int* value); +} ocp_nlp_constraints_config; + +// +acados_size_t ocp_nlp_constraints_config_calculate_size(); +// +ocp_nlp_constraints_config *ocp_nlp_constraints_config_assign(void *raw_memory); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_CONSTRAINTS_COMMON_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_common.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_common.h new file mode 100644 index 0000000000..eb40564036 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_common.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// +/// \defgroup ocp_nlp_cost ocp_nlp_cost +/// + +/// \addtogroup ocp_nlp_cost ocp_nlp_cost +/// @{ +/// \addtogroup ocp_nlp_cost_common ocp_nlp_cost_common +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_COST_COMMON_H_ +#define ACADOS_OCP_NLP_OCP_NLP_COST_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * config + ************************************************/ + +typedef struct +{ + acados_size_t (*dims_calculate_size)(void *config); + void *(*dims_assign)(void *config, void *raw_memory); + void (*dims_set)(void *config_, void *dims_, const char *field, int *value); + void (*dims_get)(void *config_, void *dims_, const char *field, int *value); + acados_size_t (*model_calculate_size)(void *config, void *dims); + void *(*model_assign)(void *config, void *dims, void *raw_memory); + int (*model_set)(void *config_, void *dims_, void *model_, const char *field, void *value_); + acados_size_t (*opts_calculate_size)(void *config, void *dims); + void *(*opts_assign)(void *config, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, void *dims, void *opts); + void (*opts_update)(void *config, void *dims, void *opts); + void (*opts_set)(void *config, void *opts, const char *field, void *value); + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *opts); + double *(*memory_get_fun_ptr)(void *memory); + struct blasfeo_dvec *(*memory_get_grad_ptr)(void *memory); + void (*memory_set_ux_ptr)(struct blasfeo_dvec *ux, void *memory); + void (*memory_set_tmp_ux_ptr)(struct blasfeo_dvec *tmp_ux, void *memory); + void (*memory_set_z_alg_ptr)(struct blasfeo_dvec *z_alg, void *memory); + void (*memory_set_dzdux_tran_ptr)(struct blasfeo_dmat *dzdux, void *memory); + void (*memory_set_RSQrq_ptr)(struct blasfeo_dmat *RSQrq, void *memory); + void (*memory_set_Z_ptr)(struct blasfeo_dvec *Z, void *memory); + void *(*memory_assign)(void *config, void *dims, void *opts, void *raw_memory); + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *opts); + void (*initialize)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + + // computes the function value, gradient and hessian (approximation) of the cost function + void (*update_qp_matrices)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + // computes the cost function value (intended for globalization) + void (*compute_fun)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + void (*config_initialize_default)(void *config); + void (*precompute)(void *config_, void *dims_, void *model_, void *opts_, void *memory_, void *work_); + +} ocp_nlp_cost_config; + +// +acados_size_t ocp_nlp_cost_config_calculate_size(); +// +ocp_nlp_cost_config *ocp_nlp_cost_config_assign(void *raw_memory); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_COST_COMMON_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_conl.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_conl.h new file mode 100644 index 0000000000..2eb3f5d127 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_conl.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_cost ocp_nlp_cost +/// @{ +/// \addtogroup ocp_nlp_cost_conl ocp_nlp_cost_conl +/// \brief This module implements convex-over-nonlinear costs of the form +/// \f$\min_{x,u,z} \psi(y(x,u,z,p) - y_{\text{ref}}, p)\f$, + + +#ifndef ACADOS_OCP_NLP_OCP_NLP_COST_CONL_H_ +#define ACADOS_OCP_NLP_OCP_NLP_COST_CONL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_cost_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * dims + ************************************************/ + +typedef struct +{ + int nx; // number of states + int nz; // number of algebraic variables + int nu; // number of inputs + int ny; // number of outputs + int ns; // number of slacks +} ocp_nlp_cost_conl_dims; + +// +acados_size_t ocp_nlp_cost_conl_dims_calculate_size(void *config); +// +void *ocp_nlp_cost_conl_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_cost_conl_dims_initialize(void *config, void *dims, int nx, int nu, int ny, int ns, int nz); +// +void ocp_nlp_cost_conl_dims_set(void *config_, void *dims_, const char *field, int* value); +// +void ocp_nlp_cost_conl_dims_get(void *config_, void *dims_, const char *field, int* value); + + + +/************************************************ + * model + ************************************************/ + +typedef struct +{ + // slack penalty has the form z^T * s + .5 * s^T * Z * s + external_function_generic *conl_cost_fun; + external_function_generic *conl_cost_fun_jac_hess; + struct blasfeo_dvec y_ref; + struct blasfeo_dvec Z; // diagonal Hessian of slacks as vector + struct blasfeo_dvec z; // gradient of slacks as vector + double scaling; +} ocp_nlp_cost_conl_model; + +// +acados_size_t ocp_nlp_cost_conl_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_conl_model_assign(void *config, void *dims, void *raw_memory); +// +int ocp_nlp_cost_conl_model_set(void *config_, void *dims_, void *model_, const char *field, void *value_); + + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + bool gauss_newton_hess; // dummy options, we always use a gauss-newton hessian +} ocp_nlp_cost_conl_opts; + +// +acados_size_t ocp_nlp_cost_conl_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_conl_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_cost_conl_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_conl_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_conl_opts_set(void *config, void *opts, const char *field, void *value); + + + +/************************************************ + * memory + ************************************************/ +typedef struct +{ + struct blasfeo_dvec grad; // gradient of cost function + struct blasfeo_dvec *ux; // pointer to ux in nlp_out + struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dvec *Z; // pointer to Z in qp_in + struct blasfeo_dvec *z_alg; ///< pointer to z in sim_out + struct blasfeo_dmat *dzdux_tran; ///< pointer to sensitivity of a wrt ux in sim_out + double fun; ///< value of the cost function +} ocp_nlp_cost_conl_memory; + +// +acados_size_t ocp_nlp_cost_conl_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_cost_conl_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +double *ocp_nlp_cost_conl_memory_get_fun_ptr(void *memory_); +// +struct blasfeo_dvec *ocp_nlp_cost_conl_memory_get_grad_ptr(void *memory_); +// +void ocp_nlp_cost_conl_memory_set_RSQrq_ptr(struct blasfeo_dmat *RSQrq, void *memory); +// +void ocp_nlp_cost_conl_memory_set_Z_ptr(struct blasfeo_dvec *Z, void *memory); +// +void ocp_nlp_cost_conl_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); +// +void ocp_nlp_cost_conl_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); +// +void ocp_nlp_cost_conl_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); +// +void ocp_nlp_cost_conl_memory_set_dzdux_tran_ptr(struct blasfeo_dmat *dzdux_tran, void *memory_); + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat W; // hessian of outer loss function + struct blasfeo_dmat W_chol; // cholesky factor of hessian of outer loss function + struct blasfeo_dmat Jt_ux; // jacobian of inner residual function + struct blasfeo_dmat Jt_ux_tilde; // jacobian of inner residual function plus gradient contribution of algebraic variables + struct blasfeo_dmat Jt_z; // jacobian of inner residual function wrt algebraic variables + struct blasfeo_dmat tmp_nv_ny; + struct blasfeo_dvec tmp_ny; + struct blasfeo_dvec tmp_2ns; +} ocp_nlp_cost_conl_workspace; + +// +acados_size_t ocp_nlp_cost_conl_workspace_calculate_size(void *config, void *dims, void *opts); + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_cost_conl_precompute(void *config_, void *dims_, void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_conl_config_initialize_default(void *config); +// +void ocp_nlp_cost_conl_initialize(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); +// +void ocp_nlp_cost_conl_update_qp_matrices(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_conl_compute_fun(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_COST_CONL_H_ +/// @} +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_external.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_external.h new file mode 100644 index 0000000000..78958270de --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_external.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_NLP_OCP_NLP_COST_EXTERNAL_H_ +#define ACADOS_OCP_NLP_OCP_NLP_COST_EXTERNAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_cost_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + +/************************************************ + * dims + ************************************************/ + +typedef struct +{ + int nx; // number of states + int nz; // number of algebraic variables + int nu; // number of inputs + int ns; // number of slacks +} ocp_nlp_cost_external_dims; + +// +acados_size_t ocp_nlp_cost_external_dims_calculate_size(void *config); +// +void *ocp_nlp_cost_external_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_cost_external_dims_set(void *config_, void *dims_, const char *field, int* value); +// +void ocp_nlp_cost_external_dims_get(void *config_, void *dims_, const char *field, int* value); + +/************************************************ + * model + ************************************************/ + +typedef struct +{ + external_function_generic *ext_cost_fun; // function + external_function_generic *ext_cost_fun_jac_hess; // function, gradient and hessian + external_function_generic *ext_cost_fun_jac; // function, gradient + struct blasfeo_dvec Z; + struct blasfeo_dvec z; + struct blasfeo_dmat numerical_hessian; // custom hessian approximation + double scaling; +} ocp_nlp_cost_external_model; + +// +acados_size_t ocp_nlp_cost_external_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_external_model_assign(void *config, void *dims, void *raw_memory); + + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + int use_numerical_hessian; // > 0 indicating custom hessian is used instead of CasADi evaluation +} ocp_nlp_cost_external_opts; + +// +acados_size_t ocp_nlp_cost_external_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_external_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_cost_external_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_external_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_external_opts_set(void *config, void *opts, const char *field, void *value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + struct blasfeo_dvec grad; // gradient of cost function + struct blasfeo_dvec *ux; // pointer to ux in nlp_out + struct blasfeo_dvec *tmp_ux; // pointer to tmp_ux in nlp_out + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dvec *Z; // pointer to Z in qp_in + struct blasfeo_dvec *z_alg; ///< pointer to z in sim_out + struct blasfeo_dmat *dzdux_tran; ///< pointer to sensitivity of a wrt ux in sim_out + double fun; ///< value of the cost function +} ocp_nlp_cost_external_memory; + +// +acados_size_t ocp_nlp_cost_external_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_cost_external_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +double *ocp_nlp_cost_external_memory_get_fun_ptr(void *memory_); +// +struct blasfeo_dvec *ocp_nlp_cost_external_memory_get_grad_ptr(void *memory_); +// +void ocp_nlp_cost_external_memory_set_RSQrq_ptr(struct blasfeo_dmat *RSQrq, void *memory); +// +void ocp_nlp_cost_ls_memory_set_Z_ptr(struct blasfeo_dvec *Z, void *memory); +// +void ocp_nlp_cost_external_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); +// +void ocp_nlp_cost_external_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); +// +void ocp_nlp_cost_external_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); +// +void ocp_nlp_cost_external_memory_set_dzdux_tran_ptr(struct blasfeo_dmat *dzdux_tran, void *memory_); + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat tmp_nunx_nunx; + struct blasfeo_dmat tmp_nz_nz; + struct blasfeo_dmat tmp_nz_nunx; + struct blasfeo_dvec tmp_nunxnz; + struct blasfeo_dvec tmp_2ns; // temporary vector of dimension 2*ns +} ocp_nlp_cost_external_workspace; + +// +acados_size_t ocp_nlp_cost_external_workspace_calculate_size(void *config, void *dims, void *opts); + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_cost_external_precompute(void *config_, void *dims_, void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_external_config_initialize_default(void *config); +// +void ocp_nlp_cost_external_initialize(void *config_, void *dims, void *model_, + void *opts_, void *mem_, void *work_); +// +void ocp_nlp_cost_external_update_qp_matrices(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_external_compute_fun(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_COST_EXTERNAL_H_ diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_ls.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_ls.h new file mode 100644 index 0000000000..801e9a5b87 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_ls.h @@ -0,0 +1,243 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_cost ocp_nlp_cost +/// @{ +/// \addtogroup ocp_nlp_cost_ls ocp_nlp_cost_ls +/// \brief This module implements linear-least squares costs of the form +/// \f$\min_{x,u,z} \| V_x x + V_u u + V_z z - y_{\text{ref}}\|_W^2\f$. +/// @{ + + + +#ifndef ACADOS_OCP_NLP_OCP_NLP_COST_LS_H_ +#define ACADOS_OCP_NLP_OCP_NLP_COST_LS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_cost_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + +//////////////////////////////////////////////////////////////////////////////// +// dims // +//////////////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int nx; // number of states + int nz; // number of algebraic variables + int nu; // number of inputs + int ny; // number of outputs + int ns; // number of slacks +} ocp_nlp_cost_ls_dims; + + +/// Calculate the size of the ocp_nlp_cost_ls_dims struct +/// +/// \param[in] config_ structure containing configuration of ocp_nlp_cost +/// module +/// \param[out] [] +/// \return \c size of ocp_nlp_dims struct +acados_size_t ocp_nlp_cost_ls_dims_calculate_size(void *config); + + +/// Assign memory pointed to by raw_memory to ocp_nlp-cost_ls dims struct +/// +/// \param[in] config structure containing configuration of ocp_nlp_cost +/// module +/// \param[in] raw_memory pointer to memory location +/// \param[out] [] +/// \return dims +void *ocp_nlp_cost_ls_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_cost_ls_dims_set(void *config_, void *dims_, const char *field, int* value); +// +void ocp_nlp_cost_ls_dims_get(void *config_, void *dims_, const char *field, int* value); + + +//////////////////////////////////////////////////////////////////////////////// +// model // +//////////////////////////////////////////////////////////////////////////////// + + +/// structure containing the data describing the linear least-square cost +typedef struct +{ + // slack penalty has the form z^T * s + .5 * s^T * Z * s + struct blasfeo_dmat Cyt; ///< output matrix: Cy * [u,x] = y; in transposed form + struct blasfeo_dmat Vz; ///< Vz in ls cost Vx*x + Vu*u + Vz*z + struct blasfeo_dmat W; ///< ls norm corresponding to this matrix + struct blasfeo_dvec y_ref; ///< yref + struct blasfeo_dvec Z; ///< diagonal Hessian of slacks as vector (lower and upper) + struct blasfeo_dvec z; ///< gradient of slacks as vector (lower and upper) + double scaling; + int W_changed; ///< flag indicating whether W has changed and needs to be refactorized + int Cyt_or_scaling_changed; ///< flag indicating whether Cyt or scaling has changed and Hessian needs to be recomputed +} ocp_nlp_cost_ls_model; + +// +acados_size_t ocp_nlp_cost_ls_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_ls_model_assign(void *config, void *dims, void *raw_memory); +// +int ocp_nlp_cost_ls_model_set(void *config_, void *dims_, void *model_, + const char *field, void *value_); + + + +//////////////////////////////////////////////////////////////////////////////// +// options // +//////////////////////////////////////////////////////////////////////////////// + + + +typedef struct +{ + int dummy; // struct can't be void +} ocp_nlp_cost_ls_opts; + +// +acados_size_t ocp_nlp_cost_ls_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_ls_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_cost_ls_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_ls_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_ls_opts_set(void *config, void *opts, const char *field, void *value); + + + +//////////////////////////////////////////////////////////////////////////////// +// memory // +//////////////////////////////////////////////////////////////////////////////// + + + +/// structure containing the memory associated with cost_ls component +/// of the ocp_nlp module +typedef struct +{ + struct blasfeo_dmat hess; ///< hessian of cost function + struct blasfeo_dmat W_chol; ///< cholesky factor of weight matrix + struct blasfeo_dvec res; ///< ls residual r(x) + struct blasfeo_dvec grad; ///< gradient of cost function + struct blasfeo_dvec *ux; ///< pointer to ux in nlp_out + struct blasfeo_dvec *tmp_ux; ///< pointer to ux in tmp_nlp_out + struct blasfeo_dvec *z_alg; ///< pointer to z in sim_out + struct blasfeo_dmat *dzdux_tran; ///< pointer to sensitivity of a wrt ux in sim_out + struct blasfeo_dmat *RSQrq; ///< pointer to RSQrq in qp_in + struct blasfeo_dvec *Z; ///< pointer to Z in qp_in + double fun; ///< value of the cost function +} ocp_nlp_cost_ls_memory; + +// +acados_size_t ocp_nlp_cost_ls_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_cost_ls_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +double *ocp_nlp_cost_ls_memory_get_fun_ptr(void *memory_); +// +struct blasfeo_dvec *ocp_nlp_cost_ls_memory_get_grad_ptr(void *memory_); +// +void ocp_nlp_cost_ls_memory_set_RSQrq_ptr(struct blasfeo_dmat *RSQrq, void *memory); +// +void ocp_nlp_cost_ls_memory_set_Z_ptr(struct blasfeo_dvec *Z, void *memory); +// +void ocp_nlp_cost_ls_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); +// +void ocp_nlp_cost_ls_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); +// +void ocp_nlp_cost_ls_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); +// +void ocp_nlp_cost_ls_memory_set_dzdux_tran_ptr(struct blasfeo_dmat *dzdux_tran, void *memory_); + + + +//////////////////////////////////////////////////////////////////////////////// +// workspace // +//////////////////////////////////////////////////////////////////////////////// + + + +typedef struct +{ + struct blasfeo_dmat tmp_nv_ny; // temporary matrix of dimensions nv, ny + struct blasfeo_dmat Cyt_tilde; // updated Cyt (after z elimination) + struct blasfeo_dmat dzdux_tran; // derivatives of z wrt u and x (tran) + struct blasfeo_dvec tmp_ny; // temporary vector of dimension ny + struct blasfeo_dvec tmp_2ns; // temporary vector of dimension ny + struct blasfeo_dvec tmp_nz; // temporary vector of dimension nz + struct blasfeo_dvec y_ref_tilde; // updated y_ref (after z elimination) +} ocp_nlp_cost_ls_workspace; + +// +acados_size_t ocp_nlp_cost_ls_workspace_calculate_size(void *config, void *dims, void *opts); + + + +//////////////////////////////////////////////////////////////////////////////// +// functions // +//////////////////////////////////////////////////////////////////////////////// + + +// computations that are done once when solver is created +void ocp_nlp_cost_ls_precompute(void *config_, void *dims_, void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_ls_config_initialize_default(void *config); +// +void ocp_nlp_cost_ls_initialize(void *config_, void *dims, void *model_, void *opts_, + void *mem_, void *work_); +// +void ocp_nlp_cost_ls_update_qp_matrices(void *config_, void *dims, void *model_, + void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_ls_compute_fun(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_COST_LS_H_ +/// @} +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_nls.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_nls.h new file mode 100644 index 0000000000..5ec68cf580 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_cost_nls.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_cost ocp_nlp_cost +/// @{ +/// \addtogroup ocp_nlp_cost_nls ocp_nlp_cost_nls +/// \brief This module implements nonlinear-least squares costs of the form +/// \f$\min_{x,u,z} \| y(x,u,z,p) - y_{\text{ref}} \|_W^2\f$, + +#ifndef ACADOS_OCP_NLP_OCP_NLP_COST_NLS_H_ +#define ACADOS_OCP_NLP_OCP_NLP_COST_NLS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_cost_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * dims + ************************************************/ + +typedef struct +{ + int nx; // number of states + int nz; // number of algebraic variables + int nu; // number of inputs + int ny; // number of outputs + int ns; // number of slacks +} ocp_nlp_cost_nls_dims; + +// +acados_size_t ocp_nlp_cost_nls_dims_calculate_size(void *config); +// +void *ocp_nlp_cost_nls_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_cost_nls_dims_set(void *config_, void *dims_, const char *field, int* value); +// +void ocp_nlp_cost_nls_dims_get(void *config_, void *dims_, const char *field, int* value); + + + +/************************************************ + * model + ************************************************/ + +typedef struct +{ + // nonliner function nls_y(x,u) replaces Cy * [x,u] in ls_cost + // slack penalty has the form z^T * s + .5 * s^T * Z * s + external_function_generic *nls_y_fun; // evaluation of nls function + external_function_generic *nls_y_fun_jac; // evaluation nls function and jacobian + external_function_generic *nls_y_hess; // hessian*seeds of nls residuals + struct blasfeo_dmat W; // + struct blasfeo_dvec y_ref; + struct blasfeo_dvec Z; // diagonal Hessian of slacks as vector + struct blasfeo_dvec z; // gradient of slacks as vector + double scaling; + int W_changed; ///< flag indicating whether W has changed and needs to be refactorized +} ocp_nlp_cost_nls_model; + +// +acados_size_t ocp_nlp_cost_nls_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_nls_model_assign(void *config, void *dims, void *raw_memory); +// +int ocp_nlp_cost_nls_model_set(void *config_, void *dims_, void *model_, const char *field, void *value_); + + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + bool gauss_newton_hess; // gauss-newton hessian approximation +} ocp_nlp_cost_nls_opts; + +// +acados_size_t ocp_nlp_cost_nls_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_cost_nls_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_cost_nls_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_nls_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_cost_nls_opts_set(void *config, void *opts, const char *field, void *value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat W_chol; // cholesky factor of weight matrix + struct blasfeo_dmat Jt; // jacobian of nls fun + struct blasfeo_dvec res; // nls residual r(x) + struct blasfeo_dvec grad; // gradient of cost function + struct blasfeo_dvec *ux; // pointer to ux in nlp_out + struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dvec *Z; // pointer to Z in qp_in + struct blasfeo_dvec *z_alg; ///< pointer to z in sim_out + struct blasfeo_dmat *dzdux_tran; ///< pointer to sensitivity of a wrt ux in sim_out + double fun; ///< value of the cost function +} ocp_nlp_cost_nls_memory; + +// +acados_size_t ocp_nlp_cost_nls_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_cost_nls_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +double *ocp_nlp_cost_nls_memory_get_fun_ptr(void *memory_); +// +struct blasfeo_dvec *ocp_nlp_cost_nls_memory_get_grad_ptr(void *memory_); +// +void ocp_nlp_cost_nls_memory_set_RSQrq_ptr(struct blasfeo_dmat *RSQrq, void *memory); +// +void ocp_nlp_cost_nls_memory_set_Z_ptr(struct blasfeo_dvec *Z, void *memory); +// +void ocp_nlp_cost_nls_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory_); +// +void ocp_nlp_cost_nls_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory_); +// +void ocp_nlp_cost_nls_memory_set_z_alg_ptr(struct blasfeo_dvec *z_alg, void *memory_); +// +void ocp_nlp_cost_nls_memory_set_dzdux_tran_ptr(struct blasfeo_dmat *dzdux_tran, void *memory_); + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat tmp_nv_ny; + struct blasfeo_dmat tmp_nv_nv; + struct blasfeo_dmat Vz; + struct blasfeo_dmat Cyt_tilde; + struct blasfeo_dvec tmp_ny; + struct blasfeo_dvec tmp_2ns; + struct blasfeo_dvec tmp_nz; +} ocp_nlp_cost_nls_workspace; + +// +acados_size_t ocp_nlp_cost_nls_workspace_calculate_size(void *config, void *dims, void *opts); + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_cost_nls_precompute(void *config_, void *dims_, void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_nls_config_initialize_default(void *config); +// +void ocp_nlp_cost_nls_initialize(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); +// +void ocp_nlp_cost_nls_update_qp_matrices(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); +// +void ocp_nlp_cost_nls_compute_fun(void *config_, void *dims, void *model_, void *opts_, void *memory_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_COST_NLS_H_ +/// @} +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_common.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_common.h new file mode 100644 index 0000000000..43fe71b12f --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_common.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \ingroup ocp_nlp +/// @{ + +/// \defgroup ocp_nlp_dynamics ocp_nlp_dynamics +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_COMMON_H_ +#define ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/sim/sim_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + + + +/************************************************ + * config + ************************************************/ + +typedef struct +{ + void (*config_initialize_default)(void *config); + sim_config *sim_solver; + /* dims */ + acados_size_t (*dims_calculate_size)(void *config); + void *(*dims_assign)(void *config, void *raw_memory); + void (*dims_set)(void *config_, void *dims_, const char *field, int *value); + void (*dims_get)(void *config_, void *dims_, const char *field, int* value); + /* model */ + acados_size_t (*model_calculate_size)(void *config, void *dims); + void *(*model_assign)(void *config, void *dims, void *raw_memory); + void (*model_set)(void *config_, void *dims_, void *model_, const char *field, void *value_); + /* opts */ + acados_size_t (*opts_calculate_size)(void *config, void *dims); + void *(*opts_assign)(void *config, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, void *dims, void *opts); + void (*opts_set)(void *config_, void *opts_, const char *field, void *value); + void (*opts_update)(void *config, void *dims, void *opts); + /* memory */ + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *opts); + void *(*memory_assign)(void *config, void *dims, void *opts, void *raw_memory); + // get shooting node gap x_next(x_n, u_n) - x_{n+1} + struct blasfeo_dvec *(*memory_get_fun_ptr)(void *memory_); + struct blasfeo_dvec *(*memory_get_adj_ptr)(void *memory_); + void (*memory_set_ux_ptr)(struct blasfeo_dvec *ux, void *memory_); + void (*memory_set_tmp_ux_ptr)(struct blasfeo_dvec *tmp_ux, void *memory_); + void (*memory_set_ux1_ptr)(struct blasfeo_dvec *ux1, void *memory_); + void (*memory_set_tmp_ux1_ptr)(struct blasfeo_dvec *tmp_ux1, void *memory_); + void (*memory_set_pi_ptr)(struct blasfeo_dvec *pi, void *memory_); + void (*memory_set_tmp_pi_ptr)(struct blasfeo_dvec *tmp_pi, void *memory_); + void (*memory_set_BAbt_ptr)(struct blasfeo_dmat *BAbt, void *memory_); + void (*memory_set_RSQrq_ptr)(struct blasfeo_dmat *RSQrq, void *memory_); + void (*memory_set_dzduxt_ptr)(struct blasfeo_dmat *mat, void *memory_); + void (*memory_set_sim_guess_ptr)(struct blasfeo_dvec *vec, bool *bool_ptr, void *memory_); + void (*memory_set_z_alg_ptr)(struct blasfeo_dvec *vec, void *memory_); + void (*memory_get)(void *config, void *dims, void *mem, const char *field, void* value); + /* workspace */ + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *opts); + void (*initialize)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + void (*update_qp_matrices)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + void (*compute_fun)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + int (*precompute)(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); +} ocp_nlp_dynamics_config; + +// +acados_size_t ocp_nlp_dynamics_config_calculate_size(); +// +ocp_nlp_dynamics_config *ocp_nlp_dynamics_config_assign(void *raw_memory); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_COMMON_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_cont.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_cont.h new file mode 100644 index 0000000000..3afdc9f4ed --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_cont.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_dynamics +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_CONT_H_ +#define ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_CONT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_dynamics_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" +#include "acados_c/sim_interface.h" + + + +/************************************************ + * dims + ************************************************/ + +typedef struct +{ + void *sim; + int nx; // number of states at the current stage + int nz; // number of algebraic states at the current stage + int nu; // number of inputs at the current stage + int nx1; // number of states at the next stage + int nu1; // number of inputes at the next stage +} ocp_nlp_dynamics_cont_dims; + +// +acados_size_t ocp_nlp_dynamics_cont_dims_calculate_size(void *config); +// +void *ocp_nlp_dynamics_cont_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_dynamics_cont_dims_set(void *config_, void *dims_, const char *field, int* value); + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + void *sim_solver; + int compute_adj; + int compute_hess; +} ocp_nlp_dynamics_cont_opts; + +// +acados_size_t ocp_nlp_dynamics_cont_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_dynamics_cont_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_dynamics_cont_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_dynamics_cont_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_dynamics_cont_opts_set(void *config, void *opts, const char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + struct blasfeo_dvec fun; + struct blasfeo_dvec adj; + struct blasfeo_dvec *ux; // pointer to ux in nlp_out at current stage + struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out at current stage + struct blasfeo_dvec *ux1; // pointer to ux in nlp_out at next stage + struct blasfeo_dvec *tmp_ux1; // pointer to ux in tmp_nlp_out at next stage + struct blasfeo_dvec *pi; // pointer to pi in nlp_out at current stage + struct blasfeo_dvec *tmp_pi; // pointer to pi in tmp_nlp_out at current stage + struct blasfeo_dmat *BAbt; // pointer to BAbt in qp_in + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dvec *z_alg; // pointer to output z at t = 0 + bool *set_sim_guess; // indicate if initialization for integrator is set from outside + struct blasfeo_dvec *sim_guess; // initializations for integrator + // struct blasfeo_dvec *z; // pointer to (input) z in nlp_out at current stage + struct blasfeo_dmat *dzduxt; // pointer to dzdux transposed + void *sim_solver; // sim solver memory +} ocp_nlp_dynamics_cont_memory; + +// +acados_size_t ocp_nlp_dynamics_cont_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_dynamics_cont_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +struct blasfeo_dvec *ocp_nlp_dynamics_cont_memory_get_fun_ptr(void *memory); +// +struct blasfeo_dvec *ocp_nlp_dynamics_cont_memory_get_adj_ptr(void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_ux1_ptr(struct blasfeo_dvec *ux1, void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_tmp_ux1_ptr(struct blasfeo_dvec *tmp_ux1, void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_pi_ptr(struct blasfeo_dvec *pi, void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_tmp_pi_ptr(struct blasfeo_dvec *tmp_pi, void *memory); +// +void ocp_nlp_dynamics_cont_memory_set_BAbt_ptr(struct blasfeo_dmat *BAbt, void *memory); + + + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat hess; + sim_in *sim_in; + sim_out *sim_out; + void *sim_solver; // sim solver workspace +} ocp_nlp_dynamics_cont_workspace; + +acados_size_t ocp_nlp_dynamics_cont_workspace_calculate_size(void *config, void *dims, void *opts); + + + +/************************************************ + * model + ************************************************/ + +typedef struct +{ + void *sim_model; + // double *state_transition; // TODO + double T; // simulation time +} ocp_nlp_dynamics_cont_model; + +// +acados_size_t ocp_nlp_dynamics_cont_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_dynamics_cont_model_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_dynamics_cont_model_set(void *config_, void *dims_, void *model_, const char *field, void *value); + + + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_dynamics_cont_config_initialize_default(void *config); +// +void ocp_nlp_dynamics_cont_initialize(void *config_, void *dims, void *model_, void *opts, void *mem, void *work_); +// +void ocp_nlp_dynamics_cont_update_qp_matrices(void *config_, void *dims, void *model_, void *opts, void *mem, void *work_); +// +void ocp_nlp_dynamics_cont_compute_fun(void *config_, void *dims, void *model_, void *opts, void *mem, void *work_); +// +int ocp_nlp_dynamics_cont_precompute(void *config_, void *dims, void *model_, void *opts_, void *mem_, void *work_); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_CONT_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_disc.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_disc.h new file mode 100644 index 0000000000..6ea26a7010 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_dynamics_disc.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_dynamics +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_DISC_H_ +#define ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_DISC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_dynamics_common.h" +#include "acados/utils/external_function_generic.h" +#include "acados/utils/types.h" + +/************************************************ + * dims + ************************************************/ + +typedef struct +{ + int nx; // number of states at the current stage + int nu; // number of inputs at the current stage + int nx1; // number of states at the next stage + int nu1; // number of inputes at the next stage +} ocp_nlp_dynamics_disc_dims; + +// +acados_size_t ocp_nlp_dynamics_disc_dims_calculate_size(void *config); +// +void *ocp_nlp_dynamics_disc_dims_assign(void *config, void *raw_memory); +// +void ocp_nlp_dynamics_disc_dims_set(void *config_, void *dims_, const char *dim, int* value); + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + int compute_adj; + int compute_hess; +} ocp_nlp_dynamics_disc_opts; + +// +acados_size_t ocp_nlp_dynamics_disc_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_dynamics_disc_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_dynamics_disc_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_dynamics_disc_opts_update(void *config, void *dims, void *opts); +// +int ocp_nlp_dynamics_disc_precompute(void *config_, void *dims, void *model_, void *opts_, + void *mem_, void *work_); + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + struct blasfeo_dvec fun; + struct blasfeo_dvec adj; + struct blasfeo_dvec *ux; // pointer to ux in nlp_out at current stage + struct blasfeo_dvec *tmp_ux; // pointer to ux in tmp_nlp_out at current stage + struct blasfeo_dvec *ux1; // pointer to ux in nlp_out at next stage + struct blasfeo_dvec *tmp_ux1;// pointer to ux in tmp_nlp_out at next stage + struct blasfeo_dvec *pi; // pointer to pi in nlp_out at current stage + struct blasfeo_dvec *tmp_pi; // pointer to pi in tmp_nlp_out at current stage + struct blasfeo_dmat *BAbt; // pointer to BAbt in qp_in + struct blasfeo_dmat *RSQrq; // pointer to RSQrq in qp_in +} ocp_nlp_dynamics_disc_memory; + +// +acados_size_t ocp_nlp_dynamics_disc_memory_calculate_size(void *config, void *dims, void *opts); +// +void *ocp_nlp_dynamics_disc_memory_assign(void *config, void *dims, void *opts, void *raw_memory); +// +struct blasfeo_dvec *ocp_nlp_dynamics_disc_memory_get_fun_ptr(void *memory); +// +struct blasfeo_dvec *ocp_nlp_dynamics_disc_memory_get_adj_ptr(void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_ux_ptr(struct blasfeo_dvec *ux, void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_tmp_ux_ptr(struct blasfeo_dvec *tmp_ux, void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_ux1_ptr(struct blasfeo_dvec *ux1, void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_tmp_ux1_ptr(struct blasfeo_dvec *tmp_ux1, void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_pi_ptr(struct blasfeo_dvec *pi, void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_tmp_pi_ptr(struct blasfeo_dvec *tmp_pi, void *memory); +// +void ocp_nlp_dynamics_disc_memory_set_BAbt_ptr(struct blasfeo_dmat *BAbt, void *memory); + + + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + struct blasfeo_dmat tmp_nv_nv; +} ocp_nlp_dynamics_disc_workspace; + +acados_size_t ocp_nlp_dynamics_disc_workspace_calculate_size(void *config, void *dims, void *opts); + + + +/************************************************ + * model + ************************************************/ + +typedef struct +{ + external_function_generic *disc_dyn_fun; + external_function_generic *disc_dyn_fun_jac; + external_function_generic *disc_dyn_fun_jac_hess; +} ocp_nlp_dynamics_disc_model; + +// +acados_size_t ocp_nlp_dynamics_disc_model_calculate_size(void *config, void *dims); +// +void *ocp_nlp_dynamics_disc_model_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_dynamics_disc_model_set(void *config_, void *dims_, void *model_, const char *field, void *value); + + + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_dynamics_disc_config_initialize_default(void *config); +// +void ocp_nlp_dynamics_disc_initialize(void *config_, void *dims, void *model_, void *opts, void *mem, void *work_); +// +void ocp_nlp_dynamics_disc_update_qp_matrices(void *config_, void *dims, void *model_, void *opts, void *mem, void *work_); +// +void ocp_nlp_dynamics_disc_compute_fun(void *config_, void *dims, void *model_, void *opts, void *mem, void *work_); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_DYNAMICS_DISC_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_common.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_common.h new file mode 100644 index 0000000000..9388f3fd24 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_common.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \ingroup ocp_nlp +/// @{ + +/// \defgroup ocp_nlp_reg ocp_nlp_reg +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_REG_COMMON_H_ +#define ACADOS_OCP_NLP_OCP_NLP_REG_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_qp/ocp_qp_common.h" + + + +/* dims */ + +//typedef ocp_qp_dims ocp_nlp_reg_dims; +typedef struct +{ + int *nx; + int *nu; + int *nbu; + int *nbx; + int *ng; + int N; +} ocp_nlp_reg_dims; + +// +acados_size_t ocp_nlp_reg_dims_calculate_size(int N); +// +ocp_nlp_reg_dims *ocp_nlp_reg_dims_assign(int N, void *raw_memory); +// +void ocp_nlp_reg_dims_set(void *config_, ocp_nlp_reg_dims *dims, int stage, char *field, int* value); + + + +/* config */ + +typedef struct +{ + /* dims */ + acados_size_t (*dims_calculate_size)(int N); + ocp_nlp_reg_dims *(*dims_assign)(int N, void *raw_memory); + void (*dims_set)(void *config, ocp_nlp_reg_dims *dims, int stage, char *field, int *value); + /* opts */ + acados_size_t (*opts_calculate_size)(void); + void *(*opts_assign)(void *raw_memory); + void (*opts_initialize_default)(void *config, ocp_nlp_reg_dims *dims, void *opts); + void (*opts_set)(void *config, ocp_nlp_reg_dims *dims, void *opts, char *field, void* value); + /* memory */ + acados_size_t (*memory_calculate_size)(void *config, ocp_nlp_reg_dims *dims, void *opts); + void *(*memory_assign)(void *config, ocp_nlp_reg_dims *dims, void *opts, void *raw_memory); + void (*memory_set)(void *config, ocp_nlp_reg_dims *dims, void *memory, char *field, void* value); + void (*memory_set_RSQrq_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dmat *mat, void *memory); + void (*memory_set_rq_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dvec *vec, void *memory); + void (*memory_set_BAbt_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dmat *mat, void *memory); + void (*memory_set_b_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dvec *vec, void *memory); + void (*memory_set_idxb_ptr)(ocp_nlp_reg_dims *dims, int **idxb, void *memory); + void (*memory_set_DCt_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dmat *mat, void *memory); + void (*memory_set_ux_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dvec *vec, void *memory); + void (*memory_set_pi_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dvec *vec, void *memory); + void (*memory_set_lam_ptr)(ocp_nlp_reg_dims *dims, struct blasfeo_dvec *vec, void *memory); + /* functions */ + void (*regularize_hessian)(void *config, ocp_nlp_reg_dims *dims, void *opts, void *memory); + void (*correct_dual_sol)(void *config, ocp_nlp_reg_dims *dims, void *opts, void *memory); +} ocp_nlp_reg_config; + +// +acados_size_t ocp_nlp_reg_config_calculate_size(void); +// +void *ocp_nlp_reg_config_assign(void *raw_memory); + + + +/* regularization help functions */ +void acados_reconstruct_A(int dim, double *A, double *V, double *d); +void acados_mirror(int dim, double *A, double *V, double *d, double *e, double epsilon); +void acados_project(int dim, double *A, double *V, double *d, double *e, double epsilon); + + + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_REG_COMMON_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_convexify.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_convexify.h new file mode 100644 index 0000000000..cb523525e1 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_convexify.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_reg +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_REG_CONVEXIFY_H_ +#define ACADOS_OCP_NLP_OCP_NLP_REG_CONVEXIFY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_reg_common.h" + + + +/************************************************ + * dims + ************************************************/ + +// use the functions in ocp_nlp_reg_common + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + double delta; + double epsilon; +// double gamma; // 0.0 +} ocp_nlp_reg_convexify_opts; + +// +acados_size_t ocp_nlp_reg_convexify_opts_calculate_size(void); +// +void *ocp_nlp_reg_convexify_opts_assign(void *raw_memory); +// +void ocp_nlp_reg_convexify_opts_initialize_default(void *config_, ocp_nlp_reg_dims *dims, void *opts_); +// +void ocp_nlp_reg_convexify_opts_set(void *config_, ocp_nlp_reg_dims *dims, void *opts_, char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct { + double *R; + double *V; // TODO move to workspace + double *d; // TODO move to workspace + double *e; // TODO move to workspace + double *reg_hess; // TODO move to workspace + + struct blasfeo_dmat Q_tilde; + struct blasfeo_dmat Q_bar; + struct blasfeo_dmat BAQ; + struct blasfeo_dmat L; + struct blasfeo_dmat delta_eye; + struct blasfeo_dmat St_copy; + + struct blasfeo_dmat *original_RSQrq; + struct blasfeo_dmat tmp_RSQ; + + struct blasfeo_dvec tmp_nuxM; + struct blasfeo_dvec tmp_nbgM; + +// struct blasfeo_dvec grad; +// struct blasfeo_dvec b2; + + // giaf's + struct blasfeo_dmat **RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dvec **rq; // pointer to rq in qp_in + struct blasfeo_dmat **BAbt; // pointer to BAbt in qp_in + struct blasfeo_dvec **b; // pointer to b in qp_in + struct blasfeo_dmat **DCt; // pointer to DCt in qp_in + struct blasfeo_dvec **ux; // pointer to ux in qp_out + struct blasfeo_dvec **pi; // pointer to pi in qp_out + struct blasfeo_dvec **lam; // pointer to lam in qp_out + int **idxb; // pointer to idxb in qp_in + +} ocp_nlp_reg_convexify_memory; + +// +acados_size_t ocp_nlp_reg_convexify_calculate_memory_size(void *config, ocp_nlp_reg_dims *dims, void *opts); +// +void *ocp_nlp_reg_convexify_assign_memory(void *config, ocp_nlp_reg_dims *dims, void *opts, void *raw_memory); + +/************************************************ + * workspace + ************************************************/ + + // TODO + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_reg_convexify_config_initialize_default(ocp_nlp_reg_config *config); + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_REG_CONVEXIFY_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_mirror.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_mirror.h new file mode 100644 index 0000000000..84a023cb69 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_mirror.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_reg +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_REG_MIRROR_H_ +#define ACADOS_OCP_NLP_OCP_NLP_REG_MIRROR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_reg_common.h" + + + +/************************************************ + * dims + ************************************************/ + +// use the functions in ocp_nlp_reg_common + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + double epsilon; +} ocp_nlp_reg_mirror_opts; + +// +acados_size_t ocp_nlp_reg_mirror_opts_calculate_size(void); +// +void *ocp_nlp_reg_mirror_opts_assign(void *raw_memory); +// +void ocp_nlp_reg_mirror_opts_initialize_default(void *config_, ocp_nlp_reg_dims *dims, void *opts_); +// +void ocp_nlp_reg_mirror_opts_set(void *config_, ocp_nlp_reg_dims *dims, void *opts_, char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + double *reg_hess; // TODO move to workspace + double *V; // TODO move to workspace + double *d; // TODO move to workspace + double *e; // TODO move to workspace + + // giaf's + struct blasfeo_dmat **RSQrq; // pointer to RSQrq in qp_in +} ocp_nlp_reg_mirror_memory; + +// +acados_size_t ocp_nlp_reg_mirror_memory_calculate_size(void *config, ocp_nlp_reg_dims *dims, void *opts); +// +void *ocp_nlp_reg_mirror_memory_assign(void *config, ocp_nlp_reg_dims *dims, void *opts, void *raw_memory); + +/************************************************ + * workspace + ************************************************/ + + // TODO + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_reg_mirror_config_initialize_default(ocp_nlp_reg_config *config); + + + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_REG_MIRROR_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_noreg.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_noreg.h new file mode 100644 index 0000000000..b571f3bac1 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_noreg.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_reg +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_REG_NOREG_H_ +#define ACADOS_OCP_NLP_OCP_NLP_REG_NOREG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_reg_common.h" + + + +/************************************************ + * dims + ************************************************/ + +// use the functions in ocp_nlp_reg_common + + +/************************************************ + * options + ************************************************/ + +// +acados_size_t ocp_nlp_reg_noreg_opts_calculate_size(void); +// +void *ocp_nlp_reg_noreg_opts_assign(void *raw_memory); +// +void ocp_nlp_reg_noreg_opts_initialize_default(void *config_, ocp_nlp_reg_dims *dims, void *opts_); +// +void ocp_nlp_reg_noreg_opts_set(void *config_, ocp_nlp_reg_dims *dims, void *opts_, char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ +// +acados_size_t ocp_nlp_reg_noreg_memory_calculate_size(void *config, ocp_nlp_reg_dims *dims, void *opts); +// +void *ocp_nlp_reg_noreg_memory_assign(void *config, ocp_nlp_reg_dims *dims, void *opts, void *raw_memory); + +/************************************************ + * workspace + ************************************************/ + +// not needed + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_reg_noreg_config_initialize_default(ocp_nlp_reg_config *config); + + + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_REG_NOREG_H_ + +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_project.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_project.h new file mode 100644 index 0000000000..682ea206dc --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_project.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_reg +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_REG_PROJECT_H_ +#define ACADOS_OCP_NLP_OCP_NLP_REG_PROJECT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_reg_common.h" + + + +/************************************************ + * dims + ************************************************/ + +// use the functions in ocp_nlp_reg_common + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + double epsilon; +} ocp_nlp_reg_project_opts; + +// +acados_size_t ocp_nlp_reg_project_opts_calculate_size(void); +// +void *ocp_nlp_reg_project_opts_assign(void *raw_memory); +// +void ocp_nlp_reg_project_opts_initialize_default(void *config_, ocp_nlp_reg_dims *dims, void *opts_); +// +void ocp_nlp_reg_project_opts_set(void *config_, ocp_nlp_reg_dims *dims, void *opts_, char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + double *reg_hess; // TODO move to workspace + double *V; // TODO move to workspace + double *d; // TODO move to workspace + double *e; // TODO move to workspace + + // giaf's + struct blasfeo_dmat **RSQrq; // pointer to RSQrq in qp_in +} ocp_nlp_reg_project_memory; + +// +acados_size_t ocp_nlp_reg_project_memory_calculate_size(void *config, ocp_nlp_reg_dims *dims, void *opts); +// +void *ocp_nlp_reg_project_memory_assign(void *config, ocp_nlp_reg_dims *dims, void *opts, void *raw_memory); + +/************************************************ + * workspace + ************************************************/ + + // TODO + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_reg_project_config_initialize_default(ocp_nlp_reg_config *config); + + + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_REG_PROJECT_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_project_reduc_hess.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_project_reduc_hess.h new file mode 100644 index 0000000000..7e12952c15 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_reg_project_reduc_hess.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_reg +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_REG_PROJECT_REDUC_HESS_H_ +#define ACADOS_OCP_NLP_OCP_NLP_REG_PROJECT_REDUC_HESS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// blasfeo +#include "blasfeo/include/blasfeo_common.h" + +// acados +#include "acados/ocp_nlp/ocp_nlp_reg_common.h" + + + +/************************************************ + * dims + ************************************************/ + +// use the functions in ocp_nlp_reg_common + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + double thr_eig; + double min_eig; + double min_pivot; + int pivoting; +} ocp_nlp_reg_project_reduc_hess_opts; + +// +acados_size_t ocp_nlp_reg_project_reduc_hess_opts_calculate_size(void); +// +void *ocp_nlp_reg_project_reduc_hess_opts_assign(void *raw_memory); +// +void ocp_nlp_reg_project_reduc_hess_opts_initialize_default(void *config_, ocp_nlp_reg_dims *dims, void *opts_); +// +void ocp_nlp_reg_project_reduc_hess_opts_set(void *config_, ocp_nlp_reg_dims *dims, void *opts_, char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + double *reg_hess; // TODO move to workspace + double *V; // TODO move to workspace + double *d; // TODO move to workspace + double *e; // TODO move to workspace + + // giaf's + struct blasfeo_dmat L; // TODO move to workspace + struct blasfeo_dmat L2; // TODO move to workspace + struct blasfeo_dmat L3; // TODO move to workspace + struct blasfeo_dmat Ls; // TODO move to workspace + struct blasfeo_dmat P; // TODO move to workspace + struct blasfeo_dmat AL; // TODO move to workspace + + struct blasfeo_dmat **RSQrq; // pointer to RSQrq in qp_in + struct blasfeo_dmat **BAbt; // pointer to RSQrq in qp_in +} ocp_nlp_reg_project_reduc_hess_memory; + +// +acados_size_t ocp_nlp_reg_project_reduc_hess_memory_calculate_size(void *config, ocp_nlp_reg_dims *dims, void *opts); +// +void *ocp_nlp_reg_project_reduc_hess_memory_assign(void *config, ocp_nlp_reg_dims *dims, void *opts, void *raw_memory); + +/************************************************ + * workspace + ************************************************/ + + // TODO + +/************************************************ + * functions + ************************************************/ + +// +void ocp_nlp_reg_project_reduc_hess_config_initialize_default(ocp_nlp_reg_config *config); + + + +#ifdef __cplusplus +} +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_REG_PROJECT_REDUC_HESS_H_ +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_sqp.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_sqp.h new file mode 100644 index 0000000000..fdb96417f9 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_sqp.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_solver +/// @{ +/// \addtogroup ocp_nlp_sqp ocp_nlp_sqp +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_SQP_H_ +#define ACADOS_OCP_NLP_OCP_NLP_SQP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_nlp/ocp_nlp_common.h" +#include "acados/utils/types.h" + + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + ocp_nlp_opts *nlp_opts; + double tol_stat; // exit tolerance on stationarity condition + double tol_eq; // exit tolerance on equality constraints + double tol_ineq; // exit tolerance on inequality constraints + double tol_comp; // exit tolerance on complementarity condition + int max_iter; + int ext_qp_res; // compute external QP residuals (i.e. at SQP level) at each SQP iteration (for debugging) + int qp_warm_start; // qp_warm_start in all but the first sqp iterations + bool warm_start_first_qp; // to set qp_warm_start in first iteration + int rti_phase; // only phase 0 at the moment + int initialize_t_slacks; // 0-false or 1-true + +} ocp_nlp_sqp_opts; + +// +acados_size_t ocp_nlp_sqp_opts_calculate_size(void *config, void *dims); +// +void *ocp_nlp_sqp_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_nlp_sqp_opts_initialize_default(void *config, void *dims, void *opts); +// +void ocp_nlp_sqp_opts_update(void *config, void *dims, void *opts); +// +void ocp_nlp_sqp_opts_set(void *config_, void *opts_, const char *field, void* value); +// +void ocp_nlp_sqp_opts_set_at_stage(void *config_, void *opts_, size_t stage, const char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + // nlp memory + ocp_nlp_memory *nlp_mem; + + double time_qp_sol; + double time_qp_solver_call; + double time_qp_xcond; + double time_lin; + double time_reg; + double time_tot; + double time_glob; + double time_sim; + double time_sim_la; + double time_sim_ad; + double time_solution_sensitivities; + + // statistics + double *stat; + int stat_m; + int stat_n; + + int status; + int sqp_iter; + +} ocp_nlp_sqp_memory; + +// +acados_size_t ocp_nlp_sqp_memory_calculate_size(void *config, void *dims, void *opts_); +// +void *ocp_nlp_sqp_memory_assign(void *config, void *dims, void *opts_, void *raw_memory); +// +void ocp_nlp_sqp_memory_reset_qp_solver(void *config_, void *dims_, void *nlp_in_, void *nlp_out_, + void *opts_, void *mem_, void *work_); + + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + ocp_nlp_workspace *nlp_work; + + // temp QP in & out (to be used as workspace in param sens) + ocp_qp_in *tmp_qp_in; + ocp_qp_out *tmp_qp_out; + + // qp residuals + ocp_qp_res *qp_res; + ocp_qp_res_ws *qp_res_ws; + +} ocp_nlp_sqp_workspace; + +// +acados_size_t ocp_nlp_sqp_workspace_calculate_size(void *config, void *dims, void *opts_); + + + +/************************************************ + * functions + ************************************************/ + +// +int ocp_nlp_sqp(void *config, void *dims, void *nlp_in, void *nlp_out, + void *args, void *mem, void *work_); +// +void ocp_nlp_sqp_config_initialize_default(void *config_); +// +int ocp_nlp_sqp_precompute(void *config_, void *dims_, void *nlp_in_, void *nlp_out_, + void *opts_, void *mem_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_SQP_H_ +/// @} +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_nlp/ocp_nlp_sqp_rti.h b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_sqp_rti.h new file mode 100644 index 0000000000..364d0f4717 --- /dev/null +++ b/third_party/acados/include/acados/ocp_nlp/ocp_nlp_sqp_rti.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +/// \addtogroup ocp_nlp +/// @{ +/// \addtogroup ocp_nlp_solver +/// @{ +/// \addtogroup ocp_nlp_sqp_rti ocp_nlp_sqp_rti +/// @{ + +#ifndef ACADOS_OCP_NLP_OCP_NLP_SQP_RTI_H_ +#define ACADOS_OCP_NLP_OCP_NLP_SQP_RTI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_nlp/ocp_nlp_common.h" +#include "acados/utils/types.h" + + + +/************************************************ + * options + ************************************************/ + +typedef struct +{ + ocp_nlp_opts *nlp_opts; + int compute_dual_sol; + int ext_qp_res; // compute external QP residuals (i.e. at SQP level) at each SQP iteration (for debugging) + int qp_warm_start; // NOTE: this is not actually setting the warm_start! Just for compatibility with sqp. + bool warm_start_first_qp; // to set qp_warm_start in first iteration + int rti_phase; // phase of RTI. Possible values 1 (preparation), 2 (feedback) 0 (both) + +} ocp_nlp_sqp_rti_opts; + +// +acados_size_t ocp_nlp_sqp_rti_opts_calculate_size(void *config_, void *dims_); +// +void *ocp_nlp_sqp_rti_opts_assign(void *config_, void *dims_, void *raw_memory); +// +void ocp_nlp_sqp_rti_opts_initialize_default(void *config_, void *dims_, void *opts_); +// +void ocp_nlp_sqp_rti_opts_update(void *config_, void *dims_, void *opts_); +// +void ocp_nlp_sqp_rti_opts_set(void *config_, void *opts_, const char *field, void* value); +// +void ocp_nlp_sqp_rti_opts_set_at_stage(void *config_, void *opts_, size_t stage, + const char *field, void* value); + + + +/************************************************ + * memory + ************************************************/ + +typedef struct +{ + // nlp memory + ocp_nlp_memory *nlp_mem; + + double time_qp_sol; + double time_qp_solver_call; + double time_qp_xcond; + double time_lin; + double time_reg; + double time_tot; + double time_glob; + double time_solution_sensitivities; + + // statistics + double *stat; + int stat_m; + int stat_n; + + int status; + +} ocp_nlp_sqp_rti_memory; + +// +acados_size_t ocp_nlp_sqp_rti_memory_calculate_size(void *config_, void *dims_, void *opts_); +// +void *ocp_nlp_sqp_rti_memory_assign(void *config_, void *dims_, void *opts_, + void *raw_memory); + + + +/************************************************ + * workspace + ************************************************/ + +typedef struct +{ + ocp_nlp_workspace *nlp_work; + + // temp QP in & out (to be used as workspace in param sens) + ocp_qp_in *tmp_qp_in; + ocp_qp_out *tmp_qp_out; + + // qp residuals + ocp_qp_res *qp_res; + ocp_qp_res_ws *qp_res_ws; + + +} ocp_nlp_sqp_rti_workspace; + +// +acados_size_t ocp_nlp_sqp_rti_workspace_calculate_size(void *config_, void *dims_, void *opts_); + + + +/************************************************ + * functions + ************************************************/ +// +int ocp_nlp_sqp_rti(void *config_, void *dims_, void *nlp_in_, void *nlp_out_, + void *opts_, void *mem_, void *work_); +// +void ocp_nlp_sqp_rti_config_initialize_default(void *config_); +// +int ocp_nlp_sqp_rti_precompute(void *config_, void *dims_, + void *nlp_in_, void *nlp_out_, void *opts_, void *mem_, void *work_); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_NLP_OCP_NLP_SQP_RTI_H_ +/// @} +/// @} +/// @} diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_common.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_common.h new file mode 100644 index 0000000000..d1a45635e4 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_common.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_COMMON_H_ +#define ACADOS_OCP_QP_OCP_QP_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// hpipm +#include "hpipm/include/hpipm_d_ocp_qp.h" +#include "hpipm/include/hpipm_d_ocp_qp_dim.h" +#include "hpipm/include/hpipm_d_ocp_qp_res.h" +#include "hpipm/include/hpipm_d_ocp_qp_sol.h" +// acados +#include "acados/utils/types.h" + + + +typedef struct d_ocp_qp_dim ocp_qp_dims; +typedef struct d_ocp_qp ocp_qp_in; +typedef struct d_ocp_qp_sol ocp_qp_out; +typedef struct d_ocp_qp_res ocp_qp_res; +typedef struct d_ocp_qp_res_ws ocp_qp_res_ws; + + + +#ifndef QP_SOLVER_CONFIG_ +#define QP_SOLVER_CONFIG_ +typedef struct +{ + void (*dims_set)(void *config_, void *dims_, int stage, const char *field, int* value); + acados_size_t (*opts_calculate_size)(void *config, void *dims); + void *(*opts_assign)(void *config, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, void *dims, void *opts); + void (*opts_update)(void *config, void *dims, void *opts); + void (*opts_set)(void *config_, void *opts_, const char *field, void* value); + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *opts); + void *(*memory_assign)(void *config, void *dims, void *opts, void *raw_memory); + void (*memory_get)(void *config_, void *mem_, const char *field, void* value); + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *opts); + int (*evaluate)(void *config, void *qp_in, void *qp_out, void *opts, void *mem, void *work); + void (*memory_reset)(void *config, void *qp_in, void *qp_out, void *opts, void *mem, void *work); + void (*eval_sens)(void *config, void *qp_in, void *qp_out, void *opts, void *mem, void *work); +} qp_solver_config; +#endif + + + +typedef struct +{ + acados_size_t (*dims_calculate_size)(void *config, int N); + void *(*dims_assign)(void *config, int N, void *raw_memory); + void (*dims_set)(void *config, void *dims_, int stage, const char *field, int* value); + void (*dims_get)(void *config, void *dims, const char *field, void* value); + // TODO add config everywhere !!!!! + acados_size_t (*opts_calculate_size)(void *dims); + void *(*opts_assign)(void *dims, void *raw_memory); + void (*opts_initialize_default)(void *dims, void *opts); + void (*opts_update)(void *dims, void *opts); + void (*opts_set)(void *opts_, const char *field, void* value); + acados_size_t (*memory_calculate_size)(void *dims, void *opts); + void *(*memory_assign)(void *dims, void *opts, void *raw_memory); + void (*memory_get)(void *config, void *mem, const char *field, void* value); + acados_size_t (*workspace_calculate_size)(void *dims, void *opts); + int (*condensing)(void *qp_in, void *qp_out, void *opts, void *mem, void *work); + int (*condensing_rhs)(void *qp_in, void *qp_out, void *opts, void *mem, void *work); + int (*expansion)(void *qp_in, void *qp_out, void *opts, void *mem, void *work); +} ocp_qp_xcond_config; + + + +/// Struct containing metrics of the qp solver. +#ifndef QP_INFO_ +#define QP_INFO_ +typedef struct +{ + double solve_QP_time; + double condensing_time; + double interface_time; + double total_time; + int num_iter; + int t_computed; +} qp_info; +#endif + + + +/* config */ +// +acados_size_t ocp_qp_solver_config_calculate_size(); +// +qp_solver_config *ocp_qp_solver_config_assign(void *raw_memory); +// +acados_size_t ocp_qp_condensing_config_calculate_size(); +// +ocp_qp_xcond_config *ocp_qp_condensing_config_assign(void *raw_memory); + + +/* dims */ +// +acados_size_t ocp_qp_dims_calculate_size(int N); +// +ocp_qp_dims *ocp_qp_dims_assign(int N, void *raw_memory); +// +void ocp_qp_dims_set(void *config_, void *dims, int stage, const char *field, int* value); +// +void ocp_qp_dims_get(void *config_, void *dims, int stage, const char *field, int* value); + + +/* in */ +// +acados_size_t ocp_qp_in_calculate_size(ocp_qp_dims *dims); +// +ocp_qp_in *ocp_qp_in_assign(ocp_qp_dims *dims, void *raw_memory); + + +/* out */ +// +acados_size_t ocp_qp_out_calculate_size(ocp_qp_dims *dims); +// +ocp_qp_out *ocp_qp_out_assign(ocp_qp_dims *dims, void *raw_memory); + +/* res */ +// +acados_size_t ocp_qp_res_calculate_size(ocp_qp_dims *dims); +// +ocp_qp_res *ocp_qp_res_assign(ocp_qp_dims *dims, void *raw_memory); +// +acados_size_t ocp_qp_res_workspace_calculate_size(ocp_qp_dims *dims); +// +ocp_qp_res_ws *ocp_qp_res_workspace_assign(ocp_qp_dims *dims, void *raw_memory); +// +void ocp_qp_res_compute(ocp_qp_in *qp_in, ocp_qp_out *qp_out, ocp_qp_res *qp_res, ocp_qp_res_ws *res_ws); +// +void ocp_qp_res_compute_nrm_inf(ocp_qp_res *qp_res, double res[4]); + + +/* misc */ +// +void ocp_qp_stack_slacks_dims(ocp_qp_dims *in, ocp_qp_dims *out); +// +void ocp_qp_stack_slacks(ocp_qp_in *in, ocp_qp_in *out); +// +void ocp_qp_compute_t(ocp_qp_in *qp_in, ocp_qp_out *qp_out); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_COMMON_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_common_frontend.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_common_frontend.h new file mode 100644 index 0000000000..f65f602c15 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_common_frontend.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_COMMON_FRONTEND_H_ +#define ACADOS_OCP_QP_OCP_QP_COMMON_FRONTEND_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_qp/ocp_qp_common.h" + +typedef struct +{ + int N; + int *nx; + int *nu; + int *nb; + int *nc; + double **A; + double **B; + double **b; + double **Q; + double **S; + double **R; + double **q; + double **r; + int **idxb; + double **lb; + double **ub; + double **Cx; + double **Cu; + double **lc; + double **uc; +} colmaj_ocp_qp_in; + +typedef struct +{ + double **x; + double **u; + double **pi; + double **lam; +} colmaj_ocp_qp_out; + +typedef struct +{ + double **res_r; + double **res_q; + double **res_ls; + double **res_us; + double **res_b; + double **res_d_lb; + double **res_d_ub; + double **res_d_lg; + double **res_d_ug; + double **res_d_ls; + double **res_d_us; + double **res_m_lb; + double **res_m_ub; + double **res_m_lg; + double **res_m_ug; + double **res_m_ls; + double **res_m_us; + double res_nrm_inf[4]; +} colmaj_ocp_qp_res; + +// +acados_size_t colmaj_ocp_qp_in_calculate_size(ocp_qp_dims *dims); +// +char *assign_colmaj_ocp_qp_in(ocp_qp_dims *dims, colmaj_ocp_qp_in **qp_in, void *ptr); +// +acados_size_t colmaj_ocp_qp_out_calculate_size(ocp_qp_dims *dims); +// +char *assign_colmaj_ocp_qp_out(ocp_qp_dims *dims, colmaj_ocp_qp_out **qp_out, void *ptr); +// +acados_size_t colmaj_ocp_qp_res_calculate_size(ocp_qp_dims *dims); +// +char *assign_colmaj_ocp_qp_res(ocp_qp_dims *dims, colmaj_ocp_qp_res **qp_res, void *ptr); +// +void convert_colmaj_to_ocp_qp_in(colmaj_ocp_qp_in *cm_qp_in, ocp_qp_in *qp_in); +// +void convert_ocp_qp_out_to_colmaj(ocp_qp_out *qp_out, colmaj_ocp_qp_out *cm_qp_out); +// +void convert_ocp_qp_res_to_colmaj(ocp_qp_res *qp_res, colmaj_ocp_qp_res *cm_qp_res); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_COMMON_FRONTEND_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_full_condensing.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_full_condensing.h new file mode 100644 index 0000000000..d23e658b48 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_full_condensing.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_FULL_CONDENSING_H_ +#define ACADOS_OCP_QP_OCP_QP_FULL_CONDENSING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// hpipm +#include "hpipm/include/hpipm_d_ocp_qp_red.h" +// acados +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + + + +typedef struct +{ + ocp_qp_dims *orig_dims; + ocp_qp_dims *red_dims; // dims of reduced qp + dense_qp_dims *fcond_dims; +} ocp_qp_full_condensing_dims; + + + +typedef struct ocp_qp_full_condensing_opts_ +{ + struct d_cond_qp_arg *hpipm_cond_opts; + struct d_ocp_qp_reduce_eq_dof_arg *hpipm_red_opts; +// dense_qp_dims *fcond_dims; // TODO(all): move to dims + int cond_hess; // 0 cond only rhs, 1 cond hess + rhs + int expand_dual_sol; // 0 primal sol only, 1 primal + dual sol + int ric_alg; + int mem_qp_in; // allocate qp_in in memory +} ocp_qp_full_condensing_opts; + + + +typedef struct ocp_qp_full_condensing_memory_ +{ + struct d_cond_qp_ws *hpipm_cond_work; + struct d_ocp_qp_reduce_eq_dof_ws *hpipm_red_work; + // in memory + dense_qp_in *fcond_qp_in; + dense_qp_out *fcond_qp_out; + ocp_qp_in *red_qp; // reduced qp + ocp_qp_out *red_sol; // reduced qp sol + // only pointer + ocp_qp_in *ptr_qp_in; + qp_info *qp_out_info; // info in fcond_qp_in + double time_qp_xcond; +} ocp_qp_full_condensing_memory; + + + +// +acados_size_t ocp_qp_full_condensing_opts_calculate_size(void *dims); +// +void *ocp_qp_full_condensing_opts_assign(void *dims, void *raw_memory); +// +void ocp_qp_full_condensing_opts_initialize_default(void *dims, void *opts_); +// +void ocp_qp_full_condensing_opts_update(void *dims, void *opts_); +// +void ocp_qp_full_condensing_opts_set(void *opts_, const char *field, void* value); +// +acados_size_t ocp_qp_full_condensing_memory_calculate_size(void *dims, void *opts_); +// +void *ocp_qp_full_condensing_memory_assign(void *dims, void *opts_, void *raw_memory); +// +acados_size_t ocp_qp_full_condensing_workspace_calculate_size(void *dims, void *opts_); +// +int ocp_qp_full_condensing(void *in, void *out, void *opts, void *mem, void *work); +// +int ocp_qp_full_expansion(void *in, void *out, void *opts, void *mem, void *work); +// +void ocp_qp_full_condensing_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_FULL_CONDENSING_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_hpipm.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_hpipm.h new file mode 100644 index 0000000000..261606b842 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_hpipm.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_HPIPM_H_ +#define ACADOS_OCP_QP_OCP_QP_HPIPM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// hpipm +#include "hpipm/include/hpipm_d_ocp_qp_ipm.h" +// acados +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + + + +// struct of arguments to the solver +// TODO(roversch): why not make this a typedef of the underlying struct? +typedef struct ocp_qp_hpipm_opts_ +{ + struct d_ocp_qp_ipm_arg *hpipm_opts; +} ocp_qp_hpipm_opts; + + + +// TODO(roversch): why not make this a typedef of the underlying struct? +// struct of the solver memory +typedef struct ocp_qp_hpipm_memory_ +{ + struct d_ocp_qp_ipm_ws *hpipm_workspace; + double time_qp_solver_call; + int iter; + int status; + +} ocp_qp_hpipm_memory; + + + +// +acados_size_t ocp_qp_hpipm_opts_calculate_size(void *config, void *dims); +// +void *ocp_qp_hpipm_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_qp_hpipm_opts_initialize_default(void *config, void *dims, void *opts_); +// +void ocp_qp_hpipm_opts_update(void *config, void *dims, void *opts_); +// +void ocp_qp_hpipm_opts_set(void *config_, void *opts_, const char *field, void *value); +// +acados_size_t ocp_qp_hpipm_memory_calculate_size(void *config, void *dims, void *opts_); +// +void *ocp_qp_hpipm_memory_assign(void *config, void *dims, void *opts_, void *raw_memory); +// +acados_size_t ocp_qp_hpipm_workspace_calculate_size(void *config, void *dims, void *opts_); +// +int ocp_qp_hpipm(void *config, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_hpipm_memory_reset(void *config_, void *qp_in_, void *qp_out_, void *opts_, void *mem_, void *work_); +// +void ocp_qp_hpipm_eval_sens(void *config, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_hpipm_config_initialize_default(void *config); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_HPIPM_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_hpmpc.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_hpmpc.h new file mode 100644 index 0000000000..8db53a279d --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_hpmpc.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_HPMPC_H_ +#define ACADOS_OCP_QP_OCP_QP_HPMPC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + +typedef enum hpmpc_options_t_ { HPMPC_DEFAULT_ARGUMENTS } hpmpc_options_t; + +typedef struct ocp_qp_hpmpc_opts_ +{ + double tol; + int max_iter; + double mu0; + double alpha_min; + int warm_start; + int N2; // horizion length of the partially condensed problem + + // partial tightening + double sigma_mu; + int N; + int M; +} ocp_qp_hpmpc_opts; + +// struct of the solver memory +typedef struct ocp_qp_hpmpc_memory_ +{ + struct blasfeo_dvec *hpi; + double *stats; + + // workspace + void *hpmpc_work; // raw workspace + + // partial tightening-specific (init of extra variables) + struct blasfeo_dvec *lam0; + struct blasfeo_dvec *ux0; + struct blasfeo_dvec *pi0; + struct blasfeo_dvec *t0; + + // 2. workspace + struct blasfeo_dmat *hsL; + struct blasfeo_dmat *hsric_work_mat; + struct blasfeo_dmat sLxM; + struct blasfeo_dmat sPpM; + + struct blasfeo_dvec *hsQx; + struct blasfeo_dvec *hsqx; + struct blasfeo_dvec *hstinv; + struct blasfeo_dvec *hsrq; + struct blasfeo_dvec *hsdux; + + struct blasfeo_dvec *hsdlam; + struct blasfeo_dvec *hsdt; + struct blasfeo_dvec *hsdpi; + struct blasfeo_dvec *hslamt; + + struct blasfeo_dvec *hsPb; + + void *work_ric; + + int out_iter; + + double time_qp_solver_call; + int iter; + int status; + +} ocp_qp_hpmpc_memory; + +acados_size_t ocp_qp_hpmpc_opts_calculate_size(void *config_, ocp_qp_dims *dims); +// +void *ocp_qp_hpmpc_opts_assign(void *config_, ocp_qp_dims *dims, void *raw_memory); +// +void ocp_qp_hpmpc_opts_initialize_default(void *config_, ocp_qp_dims *dims, void *opts_); +// +void ocp_qp_hpmpc_opts_update(void *config_, ocp_qp_dims *dims, void *opts_); +// +acados_size_t ocp_qp_hpmpc_memory_calculate_size(void *config_, ocp_qp_dims *dims, void *opts_); +// +void *ocp_qp_hpmpc_memory_assign(void *config_, ocp_qp_dims *dims, void *opts_, void *raw_memory); +// +acados_size_t ocp_qp_hpmpc_workspace_calculate_size(void *config_, ocp_qp_dims *dims, void *opts_); +// +int ocp_qp_hpmpc(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_hpmpc_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_hpmpc_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_HPMPC_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_ooqp.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_ooqp.h new file mode 100644 index 0000000000..a535503f21 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_ooqp.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_OOQP_H_ +#define ACADOS_OCP_QP_OCP_QP_OOQP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + +enum ocp_qp_ooqp_termination_code +{ + SPARSE_SUCCESSFUL_TERMINATION = 0, + SPARSE_NOT_FINISHED, + SPARSE_MAX_ITS_EXCEEDED, + SPARSE_INFEASIBLE, + SPARSE_UNKNOWN +}; + +typedef struct ocp_qp_ooqp_opts_ +{ + int printLevel; + int useDiagonalWeights; // TODO(dimitris): implement option + int fixHessian; + int fixHessianSparsity; + int fixDynamics; + int fixDynamicsSparsity; + int fixInequalities; + int fixInequalitiesSparsity; +} ocp_qp_ooqp_opts; + +typedef struct ocp_qp_ooqp_workspace_ +{ + double *x; + double *gamma; + double *phi; + double *y; + double *z; + double *lambda; + double *pi; + double objectiveValue; + int *tmpInt; // temporary vector to sort indicies sparse matrices + double *tmpReal; // temporary vector to sort data of sparse matrices + // int ierr; +} ocp_qp_ooqp_workspace; + +typedef struct ocp_qp_ooqp_memory_ +{ + int firstRun; + double *c; + int nx; + int *irowQ; + int nnzQ; + int *jcolQ; + int *orderQ; + double *dQ; + double *xlow; + char *ixlow; + double *xupp; + char *ixupp; + int *irowA; + int nnzA; + int *jcolA; + int *orderA; + double *dA; + double *bA; + int my; + int *irowC; + int nnzC; + int *jcolC; + int *orderC; + double *dC; + double *clow; + int mz; + char *iclow; + double *cupp; + char *icupp; + int nnz; // max(nnzQ, nnzA, nnzC) + double time_qp_solver_call; + int iter; + int status; + +} ocp_qp_ooqp_memory; + +// +acados_size_t ocp_qp_ooqp_opts_calculate_size(void *config_, ocp_qp_dims *dims); +// +void *ocp_qp_ooqp_opts_assign(void *config_, ocp_qp_dims *dims, void *raw_memory); +// +void ocp_qp_ooqp_opts_initialize_default(void *config_, ocp_qp_dims *dims, void *opts_); +// +void ocp_qp_ooqp_opts_update(void *config_, ocp_qp_dims *dims, void *opts_); +// +acados_size_t ocp_qp_ooqp_memory_calculate_size(void *config_, ocp_qp_dims *dims, void *opts_); +// +void *ocp_qp_ooqp_memory_assign(void *config_, ocp_qp_dims *dims, void *opts_, void *raw_memory); +// +acados_size_t ocp_qp_ooqp_workspace_calculate_size(void *config_, ocp_qp_dims *dims, void *opts_); +// +int ocp_qp_ooqp(void *config_, ocp_qp_in *qp_in, ocp_qp_out *qp_out, void *opts_, void *memory_, + void *work_); +// +void ocp_qp_ooqp_destroy(void *mem_, void *work); +// +void ocp_qp_ooqp_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_ooqp_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_OOQP_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_osqp.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_osqp.h new file mode 100644 index 0000000000..51df1b1cd6 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_osqp.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_OSQP_H_ +#define ACADOS_OCP_QP_OCP_QP_OSQP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// osqp +#include "osqp/include/types.h" + +// acados +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + +typedef struct ocp_qp_osqp_opts_ +{ + OSQPSettings *osqp_opts; +} ocp_qp_osqp_opts; + + +typedef struct ocp_qp_osqp_memory_ +{ + c_int first_run; + + c_float *q; + c_float *l; + c_float *u; + + c_int P_nnzmax; + c_int *P_i; + c_int *P_p; + c_float *P_x; + + c_int A_nnzmax; + c_int *A_i; + c_int *A_p; + c_float *A_x; + + OSQPData *osqp_data; + OSQPWorkspace *osqp_work; + + double time_qp_solver_call; + int iter; + int status; + +} ocp_qp_osqp_memory; + +acados_size_t ocp_qp_osqp_opts_calculate_size(void *config, void *dims); +// +void *ocp_qp_osqp_opts_assign(void *config, void *dims, void *raw_memory); +// +void ocp_qp_osqp_opts_initialize_default(void *config, void *dims, void *opts_); +// +void ocp_qp_osqp_opts_update(void *config, void *dims, void *opts_); +// +acados_size_t ocp_qp_osqp_memory_calculate_size(void *config, void *dims, void *opts_); +// +void *ocp_qp_osqp_memory_assign(void *config, void *dims, void *opts_, void *raw_memory); +// +acados_size_t ocp_qp_osqp_workspace_calculate_size(void *config, void *dims, void *opts_); +// +int ocp_qp_osqp(void *config, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_osqp_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_osqp_config_initialize_default(void *config); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_OSQP_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_partial_condensing.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_partial_condensing.h new file mode 100644 index 0000000000..844f6048fe --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_partial_condensing.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_PARTIAL_CONDENSING_H_ +#define ACADOS_OCP_QP_OCP_QP_PARTIAL_CONDENSING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// hpipm +#include "hpipm/include/hpipm_d_ocp_qp_red.h" +// acados +#include "acados/ocp_qp/ocp_qp_common.h" + + + +typedef struct +{ + ocp_qp_dims *orig_dims; + ocp_qp_dims *red_dims; // dims of reduced qp + ocp_qp_dims *pcond_dims; + int *block_size; + int N2; + int N2_bkp; +} ocp_qp_partial_condensing_dims; + + + +typedef struct ocp_qp_partial_condensing_opts_ +{ + struct d_part_cond_qp_arg *hpipm_pcond_opts; + struct d_ocp_qp_reduce_eq_dof_arg *hpipm_red_opts; +// ocp_qp_dims *pcond_dims; // TODO(all): move to dims +// int *block_size; + int N2; + int N2_bkp; +// int expand_dual_sol; // 0 primal sol only, 1 primal + dual sol + int ric_alg; + int mem_qp_in; // allocate qp_in in memory +} ocp_qp_partial_condensing_opts; + + + +typedef struct ocp_qp_partial_condensing_memory_ +{ + struct d_part_cond_qp_ws *hpipm_pcond_work; + struct d_ocp_qp_reduce_eq_dof_ws *hpipm_red_work; + // in memory + ocp_qp_in *pcond_qp_in; + ocp_qp_out *pcond_qp_out; + ocp_qp_in *red_qp; // reduced qp + ocp_qp_out *red_sol; // reduced qp sol + // only pointer + ocp_qp_in *ptr_qp_in; + ocp_qp_in *ptr_pcond_qp_in; + qp_info *qp_out_info; // info in pcond_qp_in + double time_qp_xcond; +} ocp_qp_partial_condensing_memory; + + + +// +acados_size_t ocp_qp_partial_condensing_opts_calculate_size(void *dims); +// +void *ocp_qp_partial_condensing_opts_assign(void *dims, void *raw_memory); +// +void ocp_qp_partial_condensing_opts_initialize_default(void *dims, void *opts_); +// +void ocp_qp_partial_condensing_opts_update(void *dims, void *opts_); +// +void ocp_qp_partial_condensing_opts_set(void *opts_, const char *field, void* value); +// +acados_size_t ocp_qp_partial_condensing_memory_calculate_size(void *dims, void *opts_); +// +void *ocp_qp_partial_condensing_memory_assign(void *dims, void *opts, void *raw_memory); +// +acados_size_t ocp_qp_partial_condensing_workspace_calculate_size(void *dims, void *opts_); +// +int ocp_qp_partial_condensing(void *in, void *out, void *opts, void *mem, void *work); +// +int ocp_qp_partial_expansion(void *in, void *out, void *opts, void *mem, void *work); +// +void ocp_qp_partial_condensing_config_initialize_default(void *config_); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_PARTIAL_CONDENSING_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_qpdunes.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_qpdunes.h new file mode 100644 index 0000000000..3b875caeb5 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_qpdunes.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_QPDUNES_H_ +#define ACADOS_OCP_QP_OCP_QP_QPDUNES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "qpDUNES.h" + +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + +typedef enum qpdunes_options_t_ { + QPDUNES_DEFAULT_ARGUMENTS, + QPDUNES_LINEAR_MPC, // TODO(dimitris): partly implemented + QPDUNES_NONLINEAR_MPC, // TODO(dimitris): not implemented yet + QPDUNES_ACADO_SETTINGS +} qpdunes_options_t; + +typedef enum { QPDUNES_WITH_QPOASES, QPDUNES_WITH_CLIPPING } qpdunes_stage_qp_solver_t; + +typedef struct ocp_qp_qpdunes_opts_ +{ + qpOptions_t options; + qpdunes_stage_qp_solver_t stageQpSolver; + int warmstart; // warmstart = 0: all multipliers set to zero, warmstart = 1: use previous mult. + bool isLinearMPC; +} ocp_qp_qpdunes_opts; + +typedef struct ocp_qp_qpdunes_memory_ +{ + int firstRun; + int nx; + int nu; + int nz; + int nDmax; // max(dims->ng) + qpData_t qpData; + double time_qp_solver_call; + int iter; + int status; + +} ocp_qp_qpdunes_memory; + +typedef struct ocp_qp_qpdunes_workspace_ +{ + double *H; + double *Q; + double *R; + double *S; + double *g; + double *ABt; + double *b; + double *Ct; + double *lc; + double *uc; + double *zLow; + double *zUpp; +} ocp_qp_qpdunes_workspace; + +// +acados_size_t ocp_qp_qpdunes_opts_calculate_size(void *config_, ocp_qp_dims *dims); +// +void *ocp_qp_qpdunes_opts_assign(void *config_, ocp_qp_dims *dims, void *raw_memory); +// +void ocp_qp_qpdunes_opts_initialize_default(void *config_, ocp_qp_dims *dims, void *opts_); +// +void ocp_qp_qpdunes_opts_update(void *config_, ocp_qp_dims *dims, void *opts_); +// +acados_size_t ocp_qp_qpdunes_memory_calculate_size(void *config_, ocp_qp_dims *dims, void *opts_); +// +void *ocp_qp_qpdunes_memory_assign(void *config_, ocp_qp_dims *dims, void *opts_, void *raw_memory); +// +acados_size_t ocp_qp_qpdunes_workspace_calculate_size(void *config_, ocp_qp_dims *dims, void *opts_); +// +int ocp_qp_qpdunes(void *config_, ocp_qp_in *qp_in, ocp_qp_out *qp_out, void *opts_, void *memory_, + void *work_); +// +void ocp_qp_qpdunes_free_memory(void *mem_); +// +void ocp_qp_qpdunes_eval_sens(void *config_, void *qp_in, void *qp_out, void *opts_, void *mem_, void *work_); +// +void ocp_qp_qpdunes_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_QPDUNES_H_ diff --git a/third_party/acados/include/acados/ocp_qp/ocp_qp_xcond_solver.h b/third_party/acados/include/acados/ocp_qp/ocp_qp_xcond_solver.h new file mode 100644 index 0000000000..a78bc65bb9 --- /dev/null +++ b/third_party/acados/include/acados/ocp_qp/ocp_qp_xcond_solver.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_OCP_QP_OCP_QP_PARTIAL_CONDENSING_SOLVER_H_ +#define ACADOS_OCP_QP_OCP_QP_PARTIAL_CONDENSING_SOLVER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/utils/types.h" + + + +typedef struct +{ + ocp_qp_dims *orig_dims; + void *xcond_dims; +} ocp_qp_xcond_solver_dims; + + + +typedef struct ocp_qp_xcond_solver_opts_ +{ + void *xcond_opts; + void *qp_solver_opts; +} ocp_qp_xcond_solver_opts; + + + +typedef struct ocp_qp_xcond_solver_memory_ +{ + void *xcond_memory; + void *solver_memory; + void *xcond_qp_in; + void *xcond_qp_out; +} ocp_qp_xcond_solver_memory; + + + +typedef struct ocp_qp_xcond_solver_workspace_ +{ + void *xcond_work; + void *qp_solver_work; +} ocp_qp_xcond_solver_workspace; + + + +typedef struct +{ + acados_size_t (*dims_calculate_size)(void *config, int N); + ocp_qp_xcond_solver_dims *(*dims_assign)(void *config, int N, void *raw_memory); + void (*dims_set)(void *config_, ocp_qp_xcond_solver_dims *dims, int stage, const char *field, int* value); + void (*dims_get)(void *config_, ocp_qp_xcond_solver_dims *dims, int stage, const char *field, int* value); + acados_size_t (*opts_calculate_size)(void *config, ocp_qp_xcond_solver_dims *dims); + void *(*opts_assign)(void *config, ocp_qp_xcond_solver_dims *dims, void *raw_memory); + void (*opts_initialize_default)(void *config, ocp_qp_xcond_solver_dims *dims, void *opts); + void (*opts_update)(void *config, ocp_qp_xcond_solver_dims *dims, void *opts); + void (*opts_set)(void *config_, void *opts_, const char *field, void* value); + acados_size_t (*memory_calculate_size)(void *config, ocp_qp_xcond_solver_dims *dims, void *opts); + void *(*memory_assign)(void *config, ocp_qp_xcond_solver_dims *dims, void *opts, void *raw_memory); + void (*memory_get)(void *config_, void *mem_, const char *field, void* value); + void (*memory_reset)(void *config, ocp_qp_xcond_solver_dims *dims, ocp_qp_in *qp_in, ocp_qp_out *qp_out, void *opts, void *mem, void *work); + acados_size_t (*workspace_calculate_size)(void *config, ocp_qp_xcond_solver_dims *dims, void *opts); + int (*evaluate)(void *config, ocp_qp_xcond_solver_dims *dims, ocp_qp_in *qp_in, ocp_qp_out *qp_out, void *opts, void *mem, void *work); + void (*eval_sens)(void *config, ocp_qp_xcond_solver_dims *dims, ocp_qp_in *param_qp_in, ocp_qp_out *sens_qp_out, void *opts, void *mem, void *work); + qp_solver_config *qp_solver; // either ocp_qp_solver or dense_solver + ocp_qp_xcond_config *xcond; +} ocp_qp_xcond_solver_config; // pcond - partial condensing or fcond - full condensing + + + +/* config */ +// +acados_size_t ocp_qp_xcond_solver_config_calculate_size(); +// +ocp_qp_xcond_solver_config *ocp_qp_xcond_solver_config_assign(void *raw_memory); + +/* dims */ +// +acados_size_t ocp_qp_xcond_solver_dims_calculate_size(void *config, int N); +// +ocp_qp_xcond_solver_dims *ocp_qp_xcond_solver_dims_assign(void *config, int N, void *raw_memory); +// +void ocp_qp_xcond_solver_dims_set_(void *config, ocp_qp_xcond_solver_dims *dims, int stage, const char *field, int* value); + +/* opts */ +// +acados_size_t ocp_qp_xcond_solver_opts_calculate_size(void *config, ocp_qp_xcond_solver_dims *dims); +// +void *ocp_qp_xcond_solver_opts_assign(void *config, ocp_qp_xcond_solver_dims *dims, void *raw_memory); +// +void ocp_qp_xcond_solver_opts_initialize_default(void *config, ocp_qp_xcond_solver_dims *dims, void *opts_); +// +void ocp_qp_xcond_solver_opts_update(void *config, ocp_qp_xcond_solver_dims *dims, void *opts_); +// +void ocp_qp_xcond_solver_opts_set_(void *config_, void *opts_, const char *field, void* value); + +/* memory */ +// +acados_size_t ocp_qp_xcond_solver_memory_calculate_size(void *config, ocp_qp_xcond_solver_dims *dims, void *opts_); +// +void *ocp_qp_xcond_solver_memory_assign(void *config, ocp_qp_xcond_solver_dims *dims, void *opts_, void *raw_memory); + +/* workspace */ +// +acados_size_t ocp_qp_xcond_solver_workspace_calculate_size(void *config, ocp_qp_xcond_solver_dims *dims, void *opts_); + +/* config */ +// +int ocp_qp_xcond_solver(void *config, ocp_qp_xcond_solver_dims *dims, ocp_qp_in *qp_in, ocp_qp_out *qp_out, void *opts_, void *mem_, void *work_); + +// +void ocp_qp_xcond_solver_config_initialize_default(void *config_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_OCP_QP_OCP_QP_PARTIAL_CONDENSING_SOLVER_H_ diff --git a/third_party/acados/include/acados/sim/sim_collocation_utils.h b/third_party/acados/include/acados/sim/sim_collocation_utils.h new file mode 100644 index 0000000000..045d165cbc --- /dev/null +++ b/third_party/acados/include/acados/sim/sim_collocation_utils.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_SIM_SIM_COLLOCATION_UTILS_H_ +#define ACADOS_SIM_SIM_COLLOCATION_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/utils/types.h" + + + +// enum Newton_type_collocation +// { +// exact = 0, +// simplified_in, +// simplified_inis +// }; + + + +// typedef struct +// { +// enum Newton_type_collocation type; +// double *eig; +// double *low_tria; +// bool single; +// bool freeze; + +// double *transf1; +// double *transf2; + +// double *transf1_T; +// double *transf2_T; +// } Newton_scheme; + + +typedef enum +{ + GAUSS_LEGENDRE, + GAUSS_RADAU_IIA, +} sim_collocation_type; + + +// +// acados_size_t gauss_legendre_nodes_work_calculate_size(int ns); +// +// void gauss_legendre_nodes(int ns, double *nodes, void *raw_memory); +// +// acados_size_t gauss_simplified_work_calculate_size(int ns); +// // +// void gauss_simplified(int ns, Newton_scheme *scheme, void *work); +// +acados_size_t butcher_tableau_work_calculate_size(int ns); +// +// void calculate_butcher_tableau_from_nodes(int ns, double *nodes, double *b, double *A, void *work); +// +void calculate_butcher_tableau(int ns, sim_collocation_type collocation_type, double *c_vec, + double *b_vec, double *A_mat, void *work); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_SIM_SIM_COLLOCATION_UTILS_H_ diff --git a/third_party/acados/include/acados/sim/sim_common.h b/third_party/acados/include/acados/sim/sim_common.h new file mode 100644 index 0000000000..c4bbd6ed2b --- /dev/null +++ b/third_party/acados/include/acados/sim/sim_common.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_SIM_SIM_COMMON_H_ +#define ACADOS_SIM_SIM_COMMON_H_ + +#include + +#include "acados/sim/sim_collocation_utils.h" +#include "acados/utils/timing.h" +#include "acados/utils/types.h" + +#include "acados/utils/external_function_generic.h" + +// maximum number of integration stages +#define NS_MAX 15 + + + +typedef enum +{ + // ERK and LIFTED_ERK + EXPL_ODE_FUN, + EXPL_ODE_HES, // wrt x and u ??? + EXPL_VDE_FOR, + EXPL_VDE_ADJ, + // IRK + IMPL_ODE_FUN, + IMPL_ODE_FUN_JAC_X_XDOT, + IMPL_ODE_JAC_X_XDOT_U, + IMPL_ODE_FUN_JAC_X_XDOT_U, + IMPL_ODE_HESS, + // gnsf + PHI_FUN, + PHI_FUN_JAC_Y, + PHI_JAC_Y_UHAT, + LO_FUN, + GET_GNSF_MATRICES +} sim_function_t; + + + +typedef struct +{ + void *dims; + + double *x; // x[NX] - initial state value for simulation + double *u; // u[NU] - control - constant over simulation time + + double *S_forw; // forward seed [Sx, Su] + double *S_adj; // backward seed + + bool identity_seed; // indicating if S_forw = [eye(nx), zeros(nx x nu)] + + void *model; + + double T; // simulation time + +} sim_in; + + + +typedef struct +{ + double CPUtime; // in seconds + double LAtime; // in seconds + double ADtime; // in seconds + +} sim_info; + + + +typedef struct +{ + double *xn; // xn[NX] + double *S_forw; // S_forw[NX*(NX+NU)] + double *S_adj; // + double *S_hess; // + + double *zn; // z - algebraic variables - reported at start of simulation interval + double *S_algebraic; // sensitivities of reported value of algebraic variables w.r.t. + // initial stat & control (x_n,u) + + double *grad; // gradient correction + + sim_info *info; + +} sim_out; + + + +typedef struct +{ + int ns; // number of integration stages + + int num_steps; + int num_forw_sens; + + int tableau_size; // check that is consistent with ns + // only update when butcher tableau is changed + // kind of private -> no setter! + double *A_mat; + double *c_vec; + double *b_vec; + + bool sens_forw; + bool sens_adj; + bool sens_hess; + + bool output_z; // 1 -- if zn should be computed + bool sens_algebraic; // 1 -- if S_algebraic should be computed + bool exact_z_output; // 1 -- if z, S_algebraic should be computed exactly, extra Newton iterations + sim_collocation_type collocation_type; + + // for explicit integrators: newton_iter == 0 && scheme == NULL + // && jac_reuse=false + int newton_iter; + bool jac_reuse; + // Newton_scheme *scheme; + + double newton_tol; // optinally used in implicit integrators + + // workspace + void *work; + +} sim_opts; + + + +typedef struct +{ + int (*evaluate)(void *config_, sim_in *in, sim_out *out, void *opts, void *mem, void *work); + int (*precompute)(void *config_, sim_in *in, sim_out *out, void *opts, void *mem, void *work); + // opts + acados_size_t (*opts_calculate_size)(void *config_, void *dims); + void *(*opts_assign)(void *config_, void *dims, void *raw_memory); + void (*opts_initialize_default)(void *config_, void *dims, void *opts); + void (*opts_update)(void *config_, void *dims, void *opts); + void (*opts_set)(void *config_, void *opts_, const char *field, void *value); + void (*opts_get)(void *config_, void *opts_, const char *field, void *value); + // mem + acados_size_t (*memory_calculate_size)(void *config, void *dims, void *opts); + void *(*memory_assign)(void *config, void *dims, void *opts, void *raw_memory); + int (*memory_set)(void *config, void *dims, void *mem, const char *field, void *value); + int (*memory_set_to_zero)(void *config, void *dims, void *opts, void *mem, const char *field); + void (*memory_get)(void *config, void *dims, void *mem, const char *field, void *value); + // work + acados_size_t (*workspace_calculate_size)(void *config, void *dims, void *opts); + // model + acados_size_t (*model_calculate_size)(void *config, void *dims); + void *(*model_assign)(void *config, void *dims, void *raw_memory); + int (*model_set)(void *model, const char *field, void *value); + // config + void (*config_initialize_default)(void *config); + // dims + acados_size_t (*dims_calculate_size)(); + void *(*dims_assign)(void *config, void *raw_memory); + void (*dims_set)(void *config, void *dims, const char *field, const int *value); + void (*dims_get)(void *config, void *dims, const char *field, int *value); + +} sim_config; + + + +/* config */ +// +acados_size_t sim_config_calculate_size(); +// +sim_config *sim_config_assign(void *raw_memory); + +/* in */ +// +acados_size_t sim_in_calculate_size(void *config, void *dims); +// +sim_in *sim_in_assign(void *config, void *dims, void *raw_memory); +// +int sim_in_set_(void *config_, void *dims_, sim_in *in, const char *field, void *value); + +/* out */ +// +acados_size_t sim_out_calculate_size(void *config, void *dims); +// +sim_out *sim_out_assign(void *config, void *dims, void *raw_memory); +// +int sim_out_get_(void *config, void *dims, sim_out *out, const char *field, void *value); + +/* opts */ +// +void sim_opts_set_(sim_opts *opts, const char *field, void *value); +// +void sim_opts_get_(sim_config *config, sim_opts *opts, const char *field, void *value); + +#endif // ACADOS_SIM_SIM_COMMON_H_ diff --git a/third_party/acados/include/acados/sim/sim_erk_integrator.h b/third_party/acados/include/acados/sim/sim_erk_integrator.h new file mode 100644 index 0000000000..fd46cb4d99 --- /dev/null +++ b/third_party/acados/include/acados/sim/sim_erk_integrator.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_SIM_SIM_ERK_INTEGRATOR_H_ +#define ACADOS_SIM_SIM_ERK_INTEGRATOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/sim/sim_common.h" +#include "acados/utils/types.h" + + + +typedef struct +{ + int nx; + int nu; + int nz; +} sim_erk_dims; + + + +typedef struct +{ + /* external functions */ + // explicit ode + external_function_generic *expl_ode_fun; + // hessian explicit ode + external_function_generic *expl_ode_hes; + // forward explicit vde + external_function_generic *expl_vde_for; + // adjoint explicit vde + external_function_generic *expl_vde_adj; + +} erk_model; + + + +typedef struct +{ + // memory + double time_sim; + double time_ad; + double time_la; + + // workspace structs +} sim_erk_memory; + + + +typedef struct +{ + // workspace mem + double *rhs_forw_in; // x + S + p + + double *K_traj; // (stages*nX) or (steps*stages*nX) for adj + double *out_forw_traj; // S or (steps+1)*nX for adj + + double *rhs_adj_in; + double *out_adj_tmp; + double *adj_traj; + +} sim_erk_workspace; + + + +// dims +acados_size_t sim_erk_dims_calculate_size(); +void *sim_erk_dims_assign(void *config_, void *raw_memory); +void sim_erk_dims_set(void *config_, void *dims_, const char *field, const int* value); +void sim_erk_dims_get(void *config_, void *dims_, const char *field, int* value); + +// model +acados_size_t sim_erk_model_calculate_size(void *config, void *dims); +void *sim_erk_model_assign(void *config, void *dims, void *raw_memory); +int sim_erk_model_set(void *model, const char *field, void *value); + +// opts +acados_size_t sim_erk_opts_calculate_size(void *config, void *dims); +// +void sim_erk_opts_update(void *config_, void *dims, void *opts_); +// +void *sim_erk_opts_assign(void *config, void *dims, void *raw_memory); +// +void sim_erk_opts_initialize_default(void *config, void *dims, void *opts_); +// +void sim_erk_opts_set(void *config_, void *opts_, const char *field, void *value); + + +// memory +acados_size_t sim_erk_memory_calculate_size(void *config, void *dims, void *opts_); +// +void *sim_erk_memory_assign(void *config, void *dims, void *opts_, void *raw_memory); +// +int sim_erk_memory_set(void *config_, void *dims_, void *mem_, const char *field, void *value); + + +// workspace +acados_size_t sim_erk_workspace_calculate_size(void *config, void *dims, void *opts_); + +// +int sim_erk(void *config, sim_in *in, sim_out *out, void *opts_, void *mem_, void *work_); +// +void sim_erk_config_initialize_default(void *config); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_SIM_SIM_ERK_INTEGRATOR_H_ diff --git a/third_party/acados/include/acados/sim/sim_gnsf.h b/third_party/acados/include/acados/sim/sim_gnsf.h new file mode 100644 index 0000000000..404532a732 --- /dev/null +++ b/third_party/acados/include/acados/sim/sim_gnsf.h @@ -0,0 +1,364 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_SIM_SIM_GNSF_H_ +#define ACADOS_SIM_SIM_GNSF_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "acados/utils/timing.h" +#include "acados/utils/types.h" +#include "acados/sim/sim_common.h" + +#include "blasfeo/include/blasfeo_common.h" +// #include "blasfeo/include/blasfeo_d_aux.h" +// #include "blasfeo/include/blasfeo_d_aux_ext_dep.h" +// #include "blasfeo/include/blasfeo_d_blas.h" +// #include "blasfeo/include/blasfeo_d_kernel.h" +// #include "blasfeo/include/blasfeo_i_aux_ext_dep.h" +// #include "blasfeo/include/blasfeo_target.h" + +/* +GNSF - Generalized Nonlinear Static Feedback Model +has the following form +https://github.com/acados/acados/files/3359595/gnsf_structure_blo.pdf + +Details on the algorithm can be found in master thesis of Jonathan Frey, +which presents a slightly different format without the terms B_LO, c_LO. +https://github.com/acados/acados/files/2318322/gnsf_structure.pdf +https://cdn.syscop.de/publications/Frey2018.pdf +https://cdn.syscop.de/publications/Frey2019.pdf +*/ + +typedef struct +{ + int nx; // total number of differential states + int nu; // total number of inputs + int nz; // total number of algebraic states + int nx1; // number of differential states in NSF part + int nz1; // number of algebraic states in NSF part + int n_out; // output dimension of phi + int ny; // dimension of first input of phi + int nuhat; // dimension of second input of phi + +} sim_gnsf_dims; + + + +typedef struct +{ + /* external functions */ + // phi: nonlinearity function + external_function_generic *phi_fun; + external_function_generic *phi_fun_jac_y; + external_function_generic *phi_jac_y_uhat; + + // f_lo: linear output function + external_function_generic *f_lo_fun_jac_x1_x1dot_u_z; + + // to import model matrices + external_function_generic *get_gnsf_matrices; + + // flag indicating, if model defining matrices are imported via external (casadi) function, + // [default]: true -> auto; + bool auto_import_gnsf; + + // booleans from structure detection + bool nontrivial_f_LO; // indicates if f_LO is constant zero function + bool fully_linear; // indicates if model is fully linear LOS + + /* model defining matrices */ + // TODO: add setters to set manually + double *A; + double *B; + double *C; + double *E; + + double *L_x; + double *L_xdot; + double *L_z; + double *L_u; + + double *A_LO; + double *B_LO; + double *E_LO; + + /* constant vector */ + double *c; + double *c_LO; + + // permutation vector - to have GNSF order of x, z within sim_gnsf only + int *ipiv_x; + int *ipiv_z; + + double *ipiv_x_double; + double *ipiv_z_double; + +} gnsf_model; + + + +// pre_workspace - workspace used in the precomputation phase +typedef struct +{ + struct blasfeo_dmat E11; + struct blasfeo_dmat E12; + struct blasfeo_dmat E21; + struct blasfeo_dmat E22; + + struct blasfeo_dmat A1; + struct blasfeo_dmat A2; + struct blasfeo_dmat B1; + struct blasfeo_dmat B2; + struct blasfeo_dmat C1; + struct blasfeo_dmat C2; + + struct blasfeo_dmat AA1; + struct blasfeo_dmat AA2; + struct blasfeo_dmat BB1; + struct blasfeo_dmat BB2; + struct blasfeo_dmat CC1; + struct blasfeo_dmat CC2; + struct blasfeo_dmat DD1; + struct blasfeo_dmat DD2; + struct blasfeo_dmat EE1; + struct blasfeo_dmat EE2; + + struct blasfeo_dmat QQ1; + + struct blasfeo_dmat LLZ; + struct blasfeo_dmat LLx; + struct blasfeo_dmat LLK; + + int *ipivEE1; // index of pivot vector + int *ipivEE2; + int *ipivQQ1; + + // for algebraic sensitivity propagation + struct blasfeo_dmat Q1; + + // for constant term in NSF + struct blasfeo_dvec cc1; + struct blasfeo_dvec cc2; + +} gnsf_pre_workspace; + + + +// workspace +typedef struct +{ + double *Z_work; // used to perform computations to get out->zn + + int *ipiv; // index of pivot vector + + struct blasfeo_dvec *vv_traj; + struct blasfeo_dvec *yy_traj; + struct blasfeo_dmat *f_LO_jac_traj; + + struct blasfeo_dvec K2_val; + struct blasfeo_dvec x0_traj; + struct blasfeo_dvec res_val; + struct blasfeo_dvec u0; + struct blasfeo_dvec lambda; + struct blasfeo_dvec lambda_old; + + struct blasfeo_dvec yyu; + struct blasfeo_dvec yyss; + + struct blasfeo_dvec K1_val; + struct blasfeo_dvec f_LO_val; + struct blasfeo_dvec x1_stage_val; + struct blasfeo_dvec Z1_val; + + struct blasfeo_dvec K1u; + struct blasfeo_dvec Zu; + struct blasfeo_dvec ALOtimesx02; + struct blasfeo_dvec BLOtimesu0; + + struct blasfeo_dvec uhat; + + struct blasfeo_dmat J_r_vv; + struct blasfeo_dmat J_r_x1u; + + struct blasfeo_dmat dK1_dx1; + struct blasfeo_dmat dK1_du; + struct blasfeo_dmat dZ_dx1; + struct blasfeo_dmat dZ_du; + struct blasfeo_dmat J_G2_K1; + + struct blasfeo_dmat dK2_dx1; + struct blasfeo_dmat dK2_dvv; + struct blasfeo_dmat dxf_dwn; + struct blasfeo_dmat S_forw_new; + struct blasfeo_dmat S_algebraic_aux; + + struct blasfeo_dmat dPsi_dvv; + struct blasfeo_dmat dPsi_dx; + struct blasfeo_dmat dPsi_du; + + struct blasfeo_dmat dPHI_dyuhat; + struct blasfeo_dvec z0; + + // memory only available if (opts->sens_algebraic) + // struct blasfeo_dvec y_one_stage; + // struct blasfeo_dvec x0dot_1; + // struct blasfeo_dmat dz10_dx1u; // (nz1) * (nx1+nu); + // struct blasfeo_dmat dr0_dvv0; // (n_out * n_out) + // struct blasfeo_dmat f_LO_jac0; // (nx2+nz2) * (2*nx1 + nz1 + nu) + // struct blasfeo_dmat sens_z2_rhs; // (nx2 + nz2) * (nx1 + nu) + // int *ipiv_vv0; + +} gnsf_workspace; + + + +// memory +typedef struct +{ + bool first_call; + + // simulation time for one step + double dt; + + // (scaled) butcher table + double *A_dt; + double *b_dt; + double *c_butcher; + + // value used to initialize integration variables - corresponding to value of phi + double *phi_guess; // n_out + + struct blasfeo_dmat S_forw; + struct blasfeo_dmat S_algebraic; + + // precomputed matrices + struct blasfeo_dmat KKv; + struct blasfeo_dmat KKx; + struct blasfeo_dmat KKu; + + struct blasfeo_dmat YYv; + struct blasfeo_dmat YYx; + struct blasfeo_dmat YYu; + + struct blasfeo_dmat ZZv; + struct blasfeo_dmat ZZx; + struct blasfeo_dmat ZZu; + + struct blasfeo_dmat ALO; + struct blasfeo_dmat BLO; + struct blasfeo_dmat M2_LU; + int *ipivM2; + + struct blasfeo_dmat dK2_dx2; + struct blasfeo_dmat dK2_du; + struct blasfeo_dmat dx2f_dx2u; + + struct blasfeo_dmat Lu; + + // precomputed vectors for constant term in NSF + struct blasfeo_dvec KK0; + struct blasfeo_dvec YY0; + struct blasfeo_dvec ZZ0; + + // for algebraic sensitivities only; + // struct blasfeo_dmat *Z0x; + // struct blasfeo_dmat *Z0u; + // struct blasfeo_dmat *Z0v; + + // struct blasfeo_dmat *Y0x; + // struct blasfeo_dmat *Y0u; + // struct blasfeo_dmat *Y0v; + + // struct blasfeo_dmat *K0x; + // struct blasfeo_dmat *K0u; + // struct blasfeo_dmat *K0v; + + // struct blasfeo_dmat *ELO_LU; + // int *ipiv_ELO; + // struct blasfeo_dmat *ELO_inv_ALO; + + // struct blasfeo_dmat *Lx; + // struct blasfeo_dmat *Lxdot; + // struct blasfeo_dmat *Lz; + + double time_sim; + double time_ad; + double time_la; + +} sim_gnsf_memory; + + + +// gnsf dims +acados_size_t sim_gnsf_dims_calculate_size(); +void *sim_gnsf_dims_assign(void *config_, void *raw_memory); + +// get & set functions +void sim_gnsf_dims_set(void *config_, void *dims_, const char *field, const int *value); +void sim_gnsf_dims_get(void *config_, void *dims_, const char *field, int* value); + +// opts +acados_size_t sim_gnsf_opts_calculate_size(void *config, void *dims); +void *sim_gnsf_opts_assign(void *config, void *dims, void *raw_memory); +void sim_gnsf_opts_initialize_default(void *config, void *dims, void *opts_); +void sim_gnsf_opts_update(void *config_, void *dims, void *opts_); +void sim_gnsf_opts_set(void *config_, void *opts_, const char *field, void *value); + +// model +acados_size_t sim_gnsf_model_calculate_size(void *config, void *dims_); +void *sim_gnsf_model_assign(void *config, void *dims_, void *raw_memory); +int sim_gnsf_model_set(void *model_, const char *field, void *value); + +// precomputation +int sim_gnsf_precompute(void *config_, sim_in *in, sim_out *out, void *opts_, void *mem_, + void *work_); + +// workspace & memory +acados_size_t sim_gnsf_workspace_calculate_size(void *config, void *dims_, void *args); +acados_size_t sim_gnsf_memory_calculate_size(void *config, void *dims_, void *opts_); +void *sim_gnsf_memory_assign(void *config, void *dims_, void *opts_, void *raw_memory); + +// interface +void sim_gnsf_config_initialize_default(void *config_); + +// integrator +int sim_gnsf(void *config, sim_in *in, sim_out *out, void *opts, void *mem_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_SIM_SIM_GNSF_H_ diff --git a/third_party/acados/include/acados/sim/sim_irk_integrator.h b/third_party/acados/include/acados/sim/sim_irk_integrator.h new file mode 100644 index 0000000000..5090aa0bb5 --- /dev/null +++ b/third_party/acados/include/acados/sim/sim_irk_integrator.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_SIM_SIM_IRK_INTEGRATOR_H_ +#define ACADOS_SIM_SIM_IRK_INTEGRATOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/sim/sim_common.h" +#include "acados/utils/types.h" + +#include "blasfeo/include/blasfeo_common.h" + +typedef struct +{ + int nx; + int nu; + int nz; + +} sim_irk_dims; + + + +typedef struct +{ + /* external functions */ + // implicit fun - can either be fully implicit ode or dae + // - i.e. dae has z as additional last argument & nz > 0 + external_function_generic *impl_ode_fun; + // implicit ode & jac_x & jax_xdot & jac_z + external_function_generic *impl_ode_fun_jac_x_xdot_z; + // jax_x & jac_xdot & jac_u & jac_z of implicit ode + external_function_generic *impl_ode_jac_x_xdot_u_z; + // hessian of implicit ode: + external_function_generic *impl_ode_hess; +} irk_model; + + + +typedef struct +{ + struct blasfeo_dvec *rG; // residuals of G (nx*ns) + struct blasfeo_dvec *K; // internal K variables ((nx+nz)*ns) + struct blasfeo_dvec *xt; // temporary x + struct blasfeo_dvec *xn; // x at each integration step + struct blasfeo_dvec xtdot; // temporary xdot + + struct blasfeo_dvec *lambda; // adjoint sensitivities (nx + nu) + struct blasfeo_dvec *lambdaK; // auxiliary variable ((nx+nz)*ns) for adjoint propagation + + struct blasfeo_dmat df_dx; // temporary Jacobian of ode w.r.t x (nx+nz, nx) + struct blasfeo_dmat df_dxdot; // temporary Jacobian of ode w.r.t xdot (nx+nz, nx) + struct blasfeo_dmat df_du; // temporary Jacobian of ode w.r.t u (nx+nz, nu) + struct blasfeo_dmat df_dz; // temporary Jacobian of ode w.r.t z (nx+nz, nu) + + /* NOTE: the memory allocation corresponding to the following fields is CONDITIONAL */ + + // only allocated if (opts->sens_algebraic || opts->output_z) + int *ipiv_one_stage; // index of pivot vector (nx + nz) + double *Z_work; // used to perform computations to get out->zn (ns) + + // df_dxdotz, dk0_dxu, only allocated if (opts->sens_algebraic && opts->exact_z_output) + // used for algebraic sensitivity generation + struct blasfeo_dmat df_dxdotz; // temporary Jacobian of ode w.r.t. xdot,z (nx+nz, nx+nz); + struct blasfeo_dmat dk0_dxu; // intermediate result, (nx+nz, nx+nu) + + // dK_dxu: if (!opts->sens_hess) - single blasfeo_dmat that is reused + // if ( opts->sens_hess) - array of (num_steps) blasfeo_dmat + // to store intermediate results + struct blasfeo_dmat *dK_dxu; // jacobian of (K,Z) over x and u ((nx+nz)*ns, nx+nu); + + // S_forw: if (!opts->sens_hess) - single blasfeo_dmat that is reused + // if ( opts->sens_hess) - array of (num_steps + 1) blasfeo_dmat + // to store intermediate results + struct blasfeo_dmat *S_forw; // forward sensitivities (nx, nx+nu) + + // dG_dxu: if (!opts->sens_hess) - single blasfeo_dmat that is reused + // if ( opts->sens_hess) - array of blasfeo_dmat to store intermediate results + struct blasfeo_dmat *dG_dxu; // jacobian of G over x and u ((nx+nz)*ns, nx+nu) + + // dG_dK: if (!opts->sens_hess) - single blasfeo_dmat that is reused + // if ( opts->sens_hess) - array of blasfeo_dmat to store intermediate results + struct blasfeo_dmat *dG_dK; // jacobian of G over K ((nx+nz)*ns, (nx+nz)*ns) + + // ipiv: index of pivot vector + // if (!opts->sens_hess) - array (ns * (nx + nz)) that is reused + // if ( opts->sens_hess) - array (ns * (nx + nz)) * num_steps, to store all + // pivot vectors for dG_dxu + int *ipiv; // index of pivot vector + + // xn_traj, K_traj only available if( opts->sens_adj || opts->sens_hess ) + struct blasfeo_dvec *xn_traj; // xn trajectory + struct blasfeo_dvec *K_traj; // K trajectory + + /* the following variables are only available if (opts->sens_hess) */ + // For Hessian propagation + struct blasfeo_dmat Hess; // temporary Hessian (nx + nu, nx + nu) + // output of impl_ode_hess + struct blasfeo_dmat f_hess; // size: (nx + nu, nx + nu) + struct blasfeo_dmat dxkzu_dw0; // size (2*nx + nu + nz) x (nx + nu) + struct blasfeo_dmat tmp_dxkzu_dw0; // size (2*nx + nu + nz) x (nx + nu) + +} sim_irk_workspace; + + +typedef struct +{ + double *xdot; // xdot[NX] - initialization for state derivatives k within the integrator + double *z; // z[NZ] - initialization for algebraic variables z + + double time_sim; + double time_ad; + double time_la; +} sim_irk_memory; + + +// get & set functions +void sim_irk_dims_set(void *config_, void *dims_, const char *field, const int *value); +void sim_irk_dims_get(void *config_, void *dims_, const char *field, int* value); + +// dims +acados_size_t sim_irk_dims_calculate_size(); +void *sim_irk_dims_assign(void *config_, void *raw_memory); + +// model +acados_size_t sim_irk_model_calculate_size(void *config, void *dims); +void *sim_irk_model_assign(void *config, void *dims, void *raw_memory); +int sim_irk_model_set(void *model, const char *field, void *value); + +// opts +acados_size_t sim_irk_opts_calculate_size(void *config, void *dims); +void *sim_irk_opts_assign(void *config, void *dims, void *raw_memory); +void sim_irk_opts_initialize_default(void *config, void *dims, void *opts_); +void sim_irk_opts_update(void *config_, void *dims, void *opts_); +void sim_irk_opts_set(void *config_, void *opts_, const char *field, void *value); + +// memory +acados_size_t sim_irk_memory_calculate_size(void *config, void *dims, void *opts_); +void *sim_irk_memory_assign(void *config, void *dims, void *opts_, void *raw_memory); +int sim_irk_memory_set(void *config_, void *dims_, void *mem_, const char *field, void *value); + +// workspace +acados_size_t sim_irk_workspace_calculate_size(void *config, void *dims, void *opts_); +void sim_irk_config_initialize_default(void *config); + +// main +int sim_irk(void *config, sim_in *in, sim_out *out, void *opts_, void *mem_, void *work_); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_SIM_SIM_IRK_INTEGRATOR_H_ diff --git a/third_party/acados/include/acados/sim/sim_lifted_irk_integrator.h b/third_party/acados/include/acados/sim/sim_lifted_irk_integrator.h new file mode 100644 index 0000000000..e60bb80ebf --- /dev/null +++ b/third_party/acados/include/acados/sim/sim_lifted_irk_integrator.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_SIM_SIM_LIFTED_IRK_INTEGRATOR_H_ +#define ACADOS_SIM_SIM_LIFTED_IRK_INTEGRATOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/sim/sim_common.h" +#include "acados/utils/types.h" + +typedef struct +{ + int nx; + int nu; + int nz; +} sim_lifted_irk_dims; + + + +typedef struct +{ + /* external functions */ + // implicit ode + external_function_generic *impl_ode_fun; + // implicit ode & jax_x & jac_xdot & jac_u implicit ode + external_function_generic *impl_ode_fun_jac_x_xdot_u; + +} lifted_irk_model; + + + +typedef struct +{ + + struct blasfeo_dmat *J_temp_x; // temporary Jacobian of ode w.r.t x (nx, nx) + struct blasfeo_dmat *J_temp_xdot; // temporary Jacobian of ode w.r.t xdot (nx, nx) + struct blasfeo_dmat *J_temp_u; // temporary Jacobian of ode w.r.t u (nx, nu) + + struct blasfeo_dvec *rG; // residuals of G (nx*ns) + struct blasfeo_dvec *xt; // temporary x + struct blasfeo_dvec *xn; // x at each integration step (for evaluations) + struct blasfeo_dvec *xn_out; // x at each integration step (output) + struct blasfeo_dvec *dxn; // dx at each integration step + struct blasfeo_dvec *w; // stacked x and u + + int *ipiv; // index of pivot vector + +} sim_lifted_irk_workspace; + + + +typedef struct +{ + // memory for lifted integrators + struct blasfeo_dmat *S_forw; // forward sensitivities + struct blasfeo_dmat *JGK; // jacobian of G over K (nx*ns, nx*ns) + struct blasfeo_dmat *JGf; // jacobian of G over x and u (nx*ns, nx+nu); + struct blasfeo_dmat *JKf; // jacobian of K over x and u (nx*ns, nx+nu); + + struct blasfeo_dvec *K; // internal variables (nx*ns) + struct blasfeo_dvec *x; // states (nx) -- for expansion step + struct blasfeo_dvec *u; // controls (nu) -- for expansion step + + int update_sens; + // int init_K; + + double time_sim; + double time_ad; + double time_la; + +} sim_lifted_irk_memory; + + + +/* dims */ +void sim_lifted_irk_dims_set(void *config_, void *dims_, const char *field, const int *value); +void sim_lifted_irk_dims_get(void *config_, void *dims_, const char *field, int* value); + +acados_size_t sim_lifted_irk_dims_calculate_size(); +// +void *sim_lifted_irk_dims_assign(void* config_, void *raw_memory); + +/* model */ +// +acados_size_t sim_lifted_irk_model_calculate_size(void *config, void *dims); +// +void *sim_lifted_irk_model_assign(void *config, void *dims, void *raw_memory); +// +int sim_lifted_irk_model_set(void *model_, const char *field, void *value); + +/* opts */ +// +acados_size_t sim_lifted_irk_opts_calculate_size(void *config, void *dims); +// +void *sim_lifted_irk_opts_assign(void *config, void *dims, void *raw_memory); +// +void sim_lifted_irk_opts_initialize_default(void *config, void *dims, void *opts_); +// +void sim_lifted_irk_opts_update(void *config_, void *dims, void *opts_); +// +void sim_lifted_irk_opts_set(void *config_, void *opts_, const char *field, void *value); + +/* memory */ +// +acados_size_t sim_lifted_irk_memory_calculate_size(void *config, void *dims, void *opts_); +// +void *sim_lifted_irk_memory_assign(void *config, void *dims, void *opts_, void *raw_memory); + +/* workspace */ +// +acados_size_t sim_lifted_irk_workspace_calculate_size(void *config, void *dims, void *opts_); +// +void sim_lifted_irk_config_initialize_default(void *config); + +/* solver */ +// +int sim_lifted_irk(void *config, sim_in *in, sim_out *out, void *opts_, + void *mem_, void *work_); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_SIM_SIM_LIFTED_IRK_INTEGRATOR_H_ diff --git a/third_party/acados/include/acados/utils/external_function_generic.h b/third_party/acados/include/acados/utils/external_function_generic.h new file mode 100644 index 0000000000..1e68dc155d --- /dev/null +++ b/third_party/acados/include/acados/utils/external_function_generic.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_UTILS_EXTERNAL_FUNCTION_GENERIC_H_ +#define ACADOS_UTILS_EXTERNAL_FUNCTION_GENERIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/utils/types.h" + +/************************************************ + * generic external function + ************************************************/ + +// type of arguments +typedef enum { + COLMAJ, + BLASFEO_DMAT, + BLASFEO_DVEC, + COLMAJ_ARGS, + BLASFEO_DMAT_ARGS, + BLASFEO_DVEC_ARGS, + IGNORE_ARGUMENT +} ext_fun_arg_t; + +struct colmaj_args +{ + double *A; + int lda; +}; + +struct blasfeo_dmat_args +{ + struct blasfeo_dmat *A; + int ai; + int aj; +}; + +struct blasfeo_dvec_args +{ + struct blasfeo_dvec *x; + int xi; +}; + +// prototype of an external function +typedef struct +{ + // public members (have to be before private ones) + void (*evaluate)(void *, ext_fun_arg_t *, void **, ext_fun_arg_t *, void **); + // private members + // ..... +} external_function_generic; + + + +/************************************************ + * generic external parametric function + ************************************************/ + +// prototype of a parametric external function +typedef struct +{ + // public members for core (have to be before private ones) + void (*evaluate)(void *, ext_fun_arg_t *, void **, ext_fun_arg_t *, void **); + // public members for interfaces + void (*get_nparam)(void *, int *); + void (*set_param)(void *, double *); + void (*set_param_sparse)(void *, int n_update, int *idx, double *); + // private members + void *ptr_ext_mem; // pointer to external memory + int (*fun)(void **, void **, void *); + double *p; // parameters + int np; // number of parameters + // ..... +} external_function_param_generic; + +// +acados_size_t external_function_param_generic_struct_size(); +// +void external_function_param_generic_set_fun(external_function_param_generic *fun, void *value); +// +acados_size_t external_function_param_generic_calculate_size(external_function_param_generic *fun, int np); +// +void external_function_param_generic_assign(external_function_param_generic *fun, void *mem); +// +void external_function_param_generic_wrapper(void *self, ext_fun_arg_t *type_in, void **in, ext_fun_arg_t *type_out, void **out); +// +void external_function_param_generic_get_nparam(void *self, int *np); +// +void external_function_param_generic_set_param(void *self, double *p); + + +/************************************************ + * casadi external function + ************************************************/ + +typedef struct +{ + // public members (have to be the same as in the prototype, and before the private ones) + void (*evaluate)(void *, ext_fun_arg_t *, void **, ext_fun_arg_t *, void **); + // private members + void *ptr_ext_mem; // pointer to external memory + int (*casadi_fun)(const double **, double **, int *, double *, void *); + int (*casadi_work)(int *, int *, int *, int *); + const int *(*casadi_sparsity_in)(int); + const int *(*casadi_sparsity_out)(int); + int (*casadi_n_in)(void); + int (*casadi_n_out)(void); + double **args; + double **res; + double *w; + int *iw; + int *args_size; // size of args[i] + int *res_size; // size of res[i] + int args_num; // number of args arrays + int args_size_tot; // total size of args arrays + int res_num; // number of res arrays + int res_size_tot; // total size of res arrays + int in_num; // number of input arrays + int out_num; // number of output arrays + int iw_size; // number of ints for worksapce + int w_size; // number of doubles for workspace +} external_function_casadi; + +// +acados_size_t external_function_casadi_struct_size(); +// +void external_function_casadi_set_fun(external_function_casadi *fun, void *value); +// +void external_function_casadi_set_work(external_function_casadi *fun, void *value); +// +void external_function_casadi_set_sparsity_in(external_function_casadi *fun, void *value); +// +void external_function_casadi_set_sparsity_out(external_function_casadi *fun, void *value); +// +void external_function_casadi_set_n_in(external_function_casadi *fun, void *value); +// +void external_function_casadi_set_n_out(external_function_casadi *fun, void *value); +// +acados_size_t external_function_casadi_calculate_size(external_function_casadi *fun); +// +void external_function_casadi_assign(external_function_casadi *fun, void *mem); +// +void external_function_casadi_wrapper(void *self, ext_fun_arg_t *type_in, void **in, + ext_fun_arg_t *type_out, void **out); + +/************************************************ + * casadi external parametric function + ************************************************/ + +typedef struct +{ + // public members for core (have to be the same as in the prototype, and before the private ones) + void (*evaluate)(void *, ext_fun_arg_t *, void **, ext_fun_arg_t *, void **); + // public members for interfaces + void (*get_nparam)(void *, int *); + void (*set_param)(void *, double *); + void (*set_param_sparse)(void *, int n_update, int *idx, double *); + // private members + void *ptr_ext_mem; // pointer to external memory + int (*casadi_fun)(const double **, double **, int *, double *, void *); + int (*casadi_work)(int *, int *, int *, int *); + const int *(*casadi_sparsity_in)(int); + const int *(*casadi_sparsity_out)(int); + int (*casadi_n_in)(void); + int (*casadi_n_out)(void); + double **args; + double **res; + double *w; + int *iw; + int *args_size; // size of args[i] + int *res_size; // size of res[i] + int args_num; // number of args arrays + int args_size_tot; // total size of args arrays + int res_num; // number of res arrays + int res_size_tot; // total size of res arrays + int in_num; // number of input arrays + int out_num; // number of output arrays + int iw_size; // number of ints for worksapce + int w_size; // number of doubles for workspace + int np; // number of parameters +} external_function_param_casadi; + +// +acados_size_t external_function_param_casadi_struct_size(); +// +void external_function_param_casadi_set_fun(external_function_param_casadi *fun, void *value); +// +void external_function_param_casadi_set_work(external_function_param_casadi *fun, void *value); +// +void external_function_param_casadi_set_sparsity_in(external_function_param_casadi *fun, void *value); +// +void external_function_param_casadi_set_sparsity_out(external_function_param_casadi *fun, void *value); +// +void external_function_param_casadi_set_n_in(external_function_param_casadi *fun, void *value); +// +void external_function_param_casadi_set_n_out(external_function_param_casadi *fun, void *value); +// +acados_size_t external_function_param_casadi_calculate_size(external_function_param_casadi *fun, int np); +// +void external_function_param_casadi_assign(external_function_param_casadi *fun, void *mem); +// +void external_function_param_casadi_wrapper(void *self, ext_fun_arg_t *type_in, void **in, + ext_fun_arg_t *type_out, void **out); +// +void external_function_param_casadi_get_nparam(void *self, int *np); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_UTILS_EXTERNAL_FUNCTION_GENERIC_H_ diff --git a/third_party/acados/include/acados/utils/math.h b/third_party/acados/include/acados/utils/math.h new file mode 100644 index 0000000000..7156a82084 --- /dev/null +++ b/third_party/acados/include/acados/utils/math.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + +#ifndef ACADOS_UTILS_MATH_H_ +#define ACADOS_UTILS_MATH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/utils/types.h" + +#if defined(__MABX2__) +double fmax(double a, double b); +int isnan(double x); +#endif + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +void dgemm_nn_3l(int m, int n, int k, double *A, int lda, double *B, int ldb, double *C, int ldc); +// void dgemv_n_3l(int m, int n, double *A, int lda, double *x, double *y); +// void dgemv_t_3l(int m, int n, double *A, int lda, double *x, double *y); +// void dcopy_3l(int n, double *x, int incx, double *y, int incy); +void daxpy_3l(int n, double da, double *dx, double *dy); +void dscal_3l(int n, double da, double *dx); +double twonormv(int n, double *ptrv); + +/* copies a matrix into another matrix */ +void dmcopy(int row, int col, double *ptrA, int lda, double *ptrB, int ldb); + +/* solution of a system of linear equations */ +void dgesv_3l(int n, int nrhs, double *A, int lda, int *ipiv, double *B, int ldb, int *info); + +/* matrix exponential */ +void expm(int row, double *A); + +int idamax_3l(int n, double *x); + +void dswap_3l(int n, double *x, int incx, double *y, int incy); + +void dger_3l(int m, int n, double alpha, double *x, int incx, double *y, int incy, double *A, + int lda); + +void dgetf2_3l(int m, int n, double *A, int lda, int *ipiv, int *info); + +void dlaswp_3l(int n, double *A, int lda, int k1, int k2, int *ipiv); + +void dtrsm_l_l_n_u_3l(int m, int n, double *A, int lda, double *B, int ldb); + +void dgetrs_3l(int n, int nrhs, double *A, int lda, int *ipiv, double *B, int ldb); + +void dgesv_3l(int n, int nrhs, double *A, int lda, int *ipiv, double *B, int ldb, int *info); + +double onenorm(int row, int col, double *ptrA); + +// double twonormv(int n, double *ptrv); + +void padeapprox(int m, int row, double *A); + +void expm(int row, double *A); + +// void d_compute_qp_size_ocp2dense_rev(int N, int *nx, int *nu, int *nb, int **hidxb, int *ng, +// int *nvd, int *ned, int *nbd, int *ngd); + +void acados_eigen_decomposition(int dim, double *A, double *V, double *d, double *e); + +double minimum_of_doubles(double *x, int n); + +void neville_algorithm(double xx, int n, double *x, double *Q, double *out); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_UTILS_MATH_H_ diff --git a/third_party/acados/include/acados/utils/mem.h b/third_party/acados/include/acados/utils/mem.h new file mode 100644 index 0000000000..681a371e36 --- /dev/null +++ b/third_party/acados/include/acados/utils/mem.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_UTILS_MEM_H_ +#define ACADOS_UTILS_MEM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include "types.h" + +// blasfeo +#include "blasfeo/include/blasfeo_d_aux.h" +#include "blasfeo/include/blasfeo_d_aux_ext_dep.h" + +// TODO(dimitris): probably does not belong here +typedef struct +{ + int (*fun)(void *); + acados_size_t (*calculate_args_size)(void *); + void *(*assign_args)(void *); + void (*initialize_default_args)(void *); + acados_size_t (*calculate_memory_size)(void *); + void *(*assign_memory)(void *); + acados_size_t (*calculate_workspace_size)(void *); +} module_solver; + +// make int counter of memory multiple of a number (typically 8 or 64) +void make_int_multiple_of(acados_size_t num, acados_size_t *size); + +// align char pointer to number (typically 8 for pointers and doubles, +// 64 for blasfeo structs) and return offset +int align_char_to(int num, char **c_ptr); + +// switch between malloc and calloc (for valgrinding) +void *acados_malloc(size_t nitems, acados_size_t size); + +// uses always calloc +void *acados_calloc(size_t nitems, acados_size_t size); + +// allocate vector of pointers to vectors of doubles and advance pointer +void assign_and_advance_double_ptrs(int n, double ***v, char **ptr); + +// allocate vector of pointers to vectors of ints and advance pointer +void assign_and_advance_int_ptrs(int n, int ***v, char **ptr); + +// allocate vector of pointers to strvecs and advance pointer +void assign_and_advance_blasfeo_dvec_structs(int n, struct blasfeo_dvec **sv, char **ptr); + +// allocate vector of pointers to strmats and advance pointer +void assign_and_advance_blasfeo_dmat_structs(int n, struct blasfeo_dmat **sm, char **ptr); + +// allocate vector of pointers to vector of pointers to strmats and advance pointer +void assign_and_advance_blasfeo_dmat_ptrs(int n, struct blasfeo_dmat ***sm, char **ptr); + +// allocate vector of chars and advance pointer +void assign_and_advance_char(int n, char **v, char **ptr); + +// allocate vector of ints and advance pointer +void assign_and_advance_int(int n, int **v, char **ptr); + +// allocate vector of bools and advance pointer +void assign_and_advance_bool(int n, bool **v, char **ptr); + +// allocate vector of doubles and advance pointer +void assign_and_advance_double(int n, double **v, char **ptr); + +// allocate strvec and advance pointer +void assign_and_advance_blasfeo_dvec_mem(int n, struct blasfeo_dvec *sv, char **ptr); + +// allocate strmat and advance pointer +void assign_and_advance_blasfeo_dmat_mem(int m, int n, struct blasfeo_dmat *sA, char **ptr); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_UTILS_MEM_H_ diff --git a/third_party/acados/include/acados/utils/print.h b/third_party/acados/include/acados/utils/print.h new file mode 100644 index 0000000000..824d3cee22 --- /dev/null +++ b/third_party/acados/include/acados/utils/print.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_UTILS_PRINT_H_ +#define ACADOS_UTILS_PRINT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/dense_qp/dense_qp_common.h" +#include "acados/ocp_nlp/ocp_nlp_common.h" +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/ocp_qp/ocp_qp_common_frontend.h" +#include "acados/utils/types.h" + +// void print_matrix(char *file_name, const real_t *matrix, const int_t nrows, const int_t ncols); + +// void print_matrix_name(char *file_name, char *name, const real_t *matrix, const int_t nrows, +// const int_t ncols); + +// void print_int_matrix(char *file_name, const int_t *matrix, const int_t nrows, const int_t ncols); + +// void print_array(char *file_name, real_t *array, int_t size); + +// void print_int_array(char *file_name, const int_t *array, int_t size); + +void read_matrix(const char *file_name, real_t *array, const int_t nrows, const int_t ncols); + +void write_double_vector_to_txt(real_t *vec, int_t n, const char *fname); + +// ocp nlp +// TODO(andrea): inconsistent naming +void ocp_nlp_dims_print(ocp_nlp_dims *dims); +// TODO(andrea): inconsistent naming +void ocp_nlp_out_print(ocp_nlp_dims *dims, ocp_nlp_out *nlp_out); +// TODO(andrea): inconsistent naming +void ocp_nlp_res_print(ocp_nlp_dims *dims, ocp_nlp_res *nlp_res); + +// ocp qp +// TODO: move printing routines below that print qp structures to HPIPM! +void print_ocp_qp_dims(ocp_qp_dims *dims); + +// void print_dense_qp_dims(dense_qp_dims *dims); + +void print_ocp_qp_in(ocp_qp_in *qp_in); + +void print_ocp_qp_in_to_file(FILE *file, ocp_qp_in *qp_in); + +void print_ocp_qp_out(ocp_qp_out *qp_out); + +void print_ocp_qp_out_to_file(FILE *file, ocp_qp_out *qp_out); + +void print_ocp_qp_res(ocp_qp_res *qp_res); + +void print_dense_qp_in(dense_qp_in *qp_in); +// void print_ocp_qp_in_to_string(char string_out[], ocp_qp_in *qp_in); + +// void print_ocp_qp_out_to_string(char string_out[], ocp_qp_out *qp_out); + +// void print_colmaj_ocp_qp_in(colmaj_ocp_qp_in *qp); + +// void print_colmaj_ocp_qp_in_to_file(colmaj_ocp_qp_in *qp); + +// void print_colmaj_ocp_qp_out(char *filename, colmaj_ocp_qp_in *qp, colmaj_ocp_qp_out *out); + +void print_qp_info(qp_info *info); + +// void acados_warning(char warning_string[]); + +// void acados_error(char error_string[]); + +// void acados_not_implemented(char feature_string[]); + +// blasfeo +// void print_blasfeo_target(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_UTILS_PRINT_H_ diff --git a/third_party/acados/include/acados/utils/strsep.h b/third_party/acados/include/acados/utils/strsep.h new file mode 100644 index 0000000000..62bdfb4891 --- /dev/null +++ b/third_party/acados/include/acados/utils/strsep.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_UTILS_STRSEP_H_ +#define ACADOS_UTILS_STRSEP_H_ + +#ifdef __cplusplus +#include +#define STD(x) std::x +namespace std +{ +#else +#include +#define STD(x) x +#endif + +char* strsep_acados(char** stringp, const char* delim) +{ + char* result; + + if ((stringp == NULL) || (*stringp == NULL)) return NULL; + + result = *stringp; + + while (**stringp && !STD(strchr)(delim, **stringp)) ++*stringp; + + if (**stringp) + *(*stringp)++ = '\0'; + else + *stringp = NULL; + + return result; +} + +#ifdef __cplusplus +} // namespace std +#endif + +#undef STD + +#endif // ACADOS_UTILS_STRSEP_H_ diff --git a/third_party/acados/include/acados/utils/timing.h b/third_party/acados/include/acados/utils/timing.h new file mode 100644 index 0000000000..b0955932da --- /dev/null +++ b/third_party/acados/include/acados/utils/timing.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_UTILS_TIMING_H_ +#define ACADOS_UTILS_TIMING_H_ + +#include "acados/utils/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef MEASURE_TIMINGS +#if (defined _WIN32 || defined _WIN64) && !(defined __MINGW32__ || defined __MINGW64__) + +/* Use Windows QueryPerformanceCounter for timing. */ +#include + +/** A structure for keeping internal timer data. */ +typedef struct acados_timer_ +{ + LARGE_INTEGER tic; + LARGE_INTEGER toc; + LARGE_INTEGER freq; +} acados_timer; + +#elif defined(__APPLE__) + +#include + +/** A structure for keeping internal timer data. */ +typedef struct acados_timer_ +{ + uint64_t tic; + uint64_t toc; + mach_timebase_info_data_t tinfo; +} acados_timer; + +#elif defined(__MABX2__) + +#include + +typedef struct acados_timer_ +{ + double time; +} acados_timer; + +#else + +/* Use POSIX clock_gettime() for timing on non-Windows machines. */ +#include + +#if (__STDC_VERSION__ >= 199901L) && !(defined __MINGW32__ || defined __MINGW64__) // C99 Mode + +#include +#include + +typedef struct acados_timer_ +{ + struct timeval tic; + struct timeval toc; +} acados_timer; + +#else // ANSI C Mode + +/** A structure for keeping internal timer data. */ +typedef struct acados_timer_ +{ + struct timespec tic; + struct timespec toc; +} acados_timer; + +#endif // __STDC_VERSION__ >= 199901L + +#endif // (defined _WIN32 || defined _WIN64) + +#else + +// Dummy type when timings are off +typedef real_t acados_timer; + +#endif // MEASURE_TIMINGS + +/** A function for measurement of the current time. */ +void acados_tic(acados_timer* t); + +/** A function which returns the elapsed time. */ +real_t acados_toc(acados_timer* t); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_UTILS_TIMING_H_ diff --git a/third_party/acados/include/acados/utils/types.h b/third_party/acados/include/acados/utils/types.h new file mode 100644 index 0000000000..a27ef9e552 --- /dev/null +++ b/third_party/acados/include/acados/utils/types.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef ACADOS_UTILS_TYPES_H_ +#define ACADOS_UTILS_TYPES_H_ + +/* Symbol visibility in DLLs */ +#ifndef ACADOS_SYMBOL_EXPORT + #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) + #if defined(STATIC_LINKED) + #define ACADOS_SYMBOL_EXPORT + #else + #define ACADOS_SYMBOL_EXPORT __declspec(dllexport) + #endif + #elif defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) + #define ACADOS_SYMBOL_EXPORT __attribute__ ((visibility ("default"))) + #else + #define ACADOS_SYMBOL_EXPORT + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define MAX_STR_LEN 256 +#define ACADOS_EPS 1e-12 +#define ACADOS_NEG_INFTY -1.0e9 +#define ACADOS_POS_INFTY +1.0e9 +#define UNUSED(x) ((void)(x)) + + + +typedef double real_t; +typedef int int_t; +typedef size_t acados_size_t; + + +typedef int (*casadi_function_t)(const double** arg, double** res, int* iw, double* w, void* mem); + + + +// enum of return values +enum return_values +{ + ACADOS_SUCCESS, + ACADOS_NAN_DETECTED, + ACADOS_MAXITER, + ACADOS_MINSTEP, + ACADOS_QP_FAILURE, + ACADOS_READY, +}; + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ACADOS_UTILS_TYPES_H_ diff --git a/third_party/acados/include/acados_c/condensing_interface.h b/third_party/acados/include/acados_c/condensing_interface.h new file mode 100644 index 0000000000..b4302078d6 --- /dev/null +++ b/third_party/acados/include/acados_c/condensing_interface.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef INTERFACES_ACADOS_C_CONDENSING_INTERFACE_H_ +#define INTERFACES_ACADOS_C_CONDENSING_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_qp/ocp_qp_full_condensing.h" +#include "acados/ocp_qp/ocp_qp_partial_condensing.h" + +typedef enum { + PARTIAL_CONDENSING, + FULL_CONDENSING, +} condensing_t; + +typedef struct +{ + condensing_t condensing_type; +} condensing_plan; + +typedef struct +{ + ocp_qp_xcond_config *config; + void *dims; + void *opts; + void *mem; + void *work; +} condensing_module; + +ocp_qp_xcond_config *ocp_qp_condensing_config_create(condensing_plan *plan); +// +void *ocp_qp_condensing_opts_create(ocp_qp_xcond_config *config, void *dims_); +// +acados_size_t ocp_qp_condensing_calculate_size(ocp_qp_xcond_config *config, void *dims_, void *opts_); +// +condensing_module *ocp_qp_condensing_assign(ocp_qp_xcond_config *config, void *dims_, + void *opts_, void *raw_memory); +// +condensing_module *ocp_qp_condensing_create(ocp_qp_xcond_config *config, void *dims_, + void *opts_); +// +int ocp_qp_condense(condensing_module *module, void *qp_in, void *qp_out); +// +int ocp_qp_expand(condensing_module *module, void *qp_in, void *qp_out); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // INTERFACES_ACADOS_C_CONDENSING_INTERFACE_H_ diff --git a/third_party/acados/include/acados_c/dense_qp_interface.h b/third_party/acados/include/acados_c/dense_qp_interface.h new file mode 100644 index 0000000000..b3af4bf682 --- /dev/null +++ b/third_party/acados/include/acados_c/dense_qp_interface.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef INTERFACES_ACADOS_C_DENSE_QP_INTERFACE_H_ +#define INTERFACES_ACADOS_C_DENSE_QP_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/dense_qp/dense_qp_common.h" + +typedef enum { DENSE_QP_HPIPM, DENSE_QP_QORE, DENSE_QP_QPOASES, DENSE_QP_OOQP, DENSE_QP_DAQP } dense_qp_solver_t; + +typedef struct +{ + dense_qp_solver_t qp_solver; +} dense_qp_solver_plan; + +typedef struct +{ + qp_solver_config *config; + void *dims; + void *opts; + void *mem; + void *work; +} dense_qp_solver; + +qp_solver_config *dense_qp_config_create(dense_qp_solver_plan *plan); +// +dense_qp_dims *dense_qp_dims_create(); +// +dense_qp_in *dense_qp_in_create(qp_solver_config *config, dense_qp_dims *dims); +// +dense_qp_out *dense_qp_out_create(qp_solver_config *config, dense_qp_dims *dims); +// +void *dense_qp_opts_create(qp_solver_config *config, dense_qp_dims *dims); +// +acados_size_t dense_qp_calculate_size(qp_solver_config *config, dense_qp_dims *dims, void *opts_); +// +dense_qp_solver *dense_qp_assign(qp_solver_config *config, dense_qp_dims *dims, void *opts_, + void *raw_memory); +// +dense_qp_solver *dense_qp_create(qp_solver_config *config, dense_qp_dims *dims, void *opts_); +// +int dense_qp_solve(dense_qp_solver *solver, dense_qp_in *qp_in, dense_qp_out *qp_out); +// +void dense_qp_inf_norm_residuals(dense_qp_dims *dims, dense_qp_in *qp_in, dense_qp_out *qp_out, + double *res); +// +bool dense_qp_set_field_double_array(const char *field, double *arr, dense_qp_in *qp_in); +// +bool dense_qp_set_field_int_array(const char *field, int *arr, dense_qp_in *qp_in); +// +bool dense_qp_get_field_double_array(const char *field, dense_qp_in *qp_in, double *arr); +// +bool dense_qp_get_field_int_array(const char *field, dense_qp_in *qp_in, int *arr); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // INTERFACES_ACADOS_C_DENSE_QP_INTERFACE_H_ diff --git a/third_party/acados/include/acados_c/external_function_interface.h b/third_party/acados/include/acados_c/external_function_interface.h new file mode 100644 index 0000000000..d4f52db850 --- /dev/null +++ b/third_party/acados/include/acados_c/external_function_interface.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef INTERFACES_ACADOS_C_EXTERNAL_FUNCTION_INTERFACE_H_ +#define INTERFACES_ACADOS_C_EXTERNAL_FUNCTION_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/utils/external_function_generic.h" + + + +/************************************************ + * generic external parametric function + ************************************************/ + +// +void external_function_param_generic_create(external_function_param_generic *fun, int np); +// +void external_function_param_generic_free(external_function_param_generic *fun); + + + +/************************************************ + * casadi external function + ************************************************/ + +// +void external_function_casadi_create(external_function_casadi *fun); +// +void external_function_casadi_free(external_function_casadi *fun); +// +void external_function_casadi_create_array(int size, external_function_casadi *funs); +// +void external_function_casadi_free_array(int size, external_function_casadi *funs); + + + +/************************************************ + * casadi external parametric function + ************************************************/ + +// +void external_function_param_casadi_create(external_function_param_casadi *fun, int np); +// +void external_function_param_casadi_free(external_function_param_casadi *fun); +// +void external_function_param_casadi_create_array(int size, external_function_param_casadi *funs, + int np); +// +void external_function_param_casadi_free_array(int size, external_function_param_casadi *funs); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // INTERFACES_ACADOS_C_EXTERNAL_FUNCTION_INTERFACE_H_ diff --git a/third_party/acados/include/acados_c/ocp_nlp_interface.h b/third_party/acados/include/acados_c/ocp_nlp_interface.h new file mode 100644 index 0000000000..dd3e596f8b --- /dev/null +++ b/third_party/acados/include/acados_c/ocp_nlp_interface.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef INTERFACES_ACADOS_C_OCP_NLP_INTERFACE_H_ +#define INTERFACES_ACADOS_C_OCP_NLP_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// acados +#include "acados/ocp_nlp/ocp_nlp_common.h" +#include "acados/ocp_nlp/ocp_nlp_constraints_bgh.h" +#include "acados/sim/sim_erk_integrator.h" +#include "acados/sim/sim_irk_integrator.h" +#include "acados/sim/sim_lifted_irk_integrator.h" +#include "acados/sim/sim_gnsf.h" +#include "acados/utils/types.h" +// acados_c +#include "acados_c/ocp_qp_interface.h" +#include "acados_c/sim_interface.h" + + +/// Solution methods for optimal control problems. +typedef enum +{ + SQP, + SQP_RTI, + INVALID_NLP_SOLVER, +} ocp_nlp_solver_t; + + +/// Types of the cost function. +typedef enum +{ + LINEAR_LS, + NONLINEAR_LS, + CONVEX_OVER_NONLINEAR, + EXTERNAL, + INVALID_COST, +} ocp_nlp_cost_t; + + +/// Types of the system dynamics, discrete or continuous time. +typedef enum +{ + CONTINUOUS_MODEL, + DISCRETE_MODEL, + INVALID_DYNAMICS, +} ocp_nlp_dynamics_t; + + +/// Constraint types +typedef enum +{ + /// Comprises simple bounds, polytopic constraints, + /// general non-linear constraints. + BGH, + + /// Comprises simple bounds, polytopic constraints, + /// general non-linear constraints, and positive definite constraints. + BGP, + + INVALID_CONSTRAINT, +} ocp_nlp_constraints_t; + + +/// Regularization types +typedef enum +{ + NO_REGULARIZE, + MIRROR, + PROJECT, + PROJECT_REDUC_HESS, + CONVEXIFY, + INVALID_REGULARIZE, +} ocp_nlp_reg_t; + + +/// Structure to store the configuration of a non-linear program +typedef struct ocp_nlp_plan_t +{ + /// QP solver configuration. + ocp_qp_solver_plan_t ocp_qp_solver_plan; + + /// Simulation solver configuration for each stage. + sim_solver_plan_t *sim_solver_plan; + + /// Nlp solver type. + ocp_nlp_solver_t nlp_solver; + + /// Regularization type, defaults to no regularization. + ocp_nlp_reg_t regularization; + + /// Cost type for each stage. + ocp_nlp_cost_t *nlp_cost; + + /// Dynamics type for each stage. + ocp_nlp_dynamics_t *nlp_dynamics; + + /// Constraints type for each stage. + ocp_nlp_constraints_t *nlp_constraints; + + /// Horizon length. + int N; + +} ocp_nlp_plan_t; + + +/// Structure to store the state/configuration for the non-linear programming solver +typedef struct ocp_nlp_solver +{ + ocp_nlp_config *config; + void *dims; + void *opts; + void *mem; + void *work; +} ocp_nlp_solver; + + +/// Constructs an empty plan struct (user nlp configuration), all fields are set to a +/// default/invalid state. +/// +/// \param N Horizon length +ACADOS_SYMBOL_EXPORT ocp_nlp_plan_t *ocp_nlp_plan_create(int N); + +/// Destructor for plan struct, frees memory. +/// +/// \param plan_ The plan struct to destroy. +ACADOS_SYMBOL_EXPORT void ocp_nlp_plan_destroy(void* plan_); + + +/// Constructs an nlp configuration struct from a plan. +/// +/// \param plan The plan (user nlp configuration). +ACADOS_SYMBOL_EXPORT ocp_nlp_config *ocp_nlp_config_create(ocp_nlp_plan_t plan); + +/// Desctructor of the nlp configuration. +/// +/// \param config_ The configuration struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_config_destroy(void *config_); + + +/// Constructs an struct that contains the dimensions of the variables. +/// +/// \param config_ The configuration struct. +ACADOS_SYMBOL_EXPORT ocp_nlp_dims *ocp_nlp_dims_create(void *config_); + +/// Destructor of The dimension struct. +/// +/// \param dims_ The dimension struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_dims_destroy(void *dims_); + + +/// Constructs an input struct for a non-linear programs. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +ACADOS_SYMBOL_EXPORT ocp_nlp_in *ocp_nlp_in_create(ocp_nlp_config *config, ocp_nlp_dims *dims); + +/// Destructor of the inputs struct. +/// +/// \param in The inputs struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_in_destroy(void *in); + + +/// Sets the sampling times for the given stage. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param in The inputs struct. +/// \param stage Stage number. +/// \param field Has to be "Ts" (TBC other options). +/// \param value The sampling times (floating point). +ACADOS_SYMBOL_EXPORT void ocp_nlp_in_set(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, int stage, + const char *field, void *value); + +/// +// void ocp_nlp_in_get(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, int stage, +// const char *field, void *value); + +/// Sets the function pointers to the dynamics functions for the given stage. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param in The inputs struct. +/// \param stage Stage number. +/// \param fun_type The name of the function type, either impl_ode_fun, +/// impl_ode_fun_jac_x_xdot, impl_ode_jac_x_xdot_u (TBC) +/// \param fun_ptr Function pointer to the dynamics function. +ACADOS_SYMBOL_EXPORT int ocp_nlp_dynamics_model_set(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + int stage, const char *fun_type, void *fun_ptr); + + +/// Sets the function pointers to the cost functions for the given stage. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param in The inputs struct. +/// \param stage Stage number. +/// \param field The name of the field, either nls_res_jac, +/// y_ref, W (others TBC) +/// \param value Cost values. +ACADOS_SYMBOL_EXPORT int ocp_nlp_cost_model_set(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_in *in, + int stage, const char *field, void *value); + + +/// Sets the function pointers to the constraints functions for the given stage. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param in The inputs struct. +/// \param stage Stage number. +/// \param field The name of the field, either lb, ub (others TBC) +/// \param value Constraints function or values. +ACADOS_SYMBOL_EXPORT int ocp_nlp_constraints_model_set(ocp_nlp_config *config, ocp_nlp_dims *dims, + ocp_nlp_in *in, int stage, const char *field, void *value); + +/// +ACADOS_SYMBOL_EXPORT void ocp_nlp_constraints_model_get(ocp_nlp_config *config, ocp_nlp_dims *dims, + ocp_nlp_in *in, int stage, const char *field, void *value); + +/* out */ + +/// Constructs an output struct for the non-linear program. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +ACADOS_SYMBOL_EXPORT ocp_nlp_out *ocp_nlp_out_create(ocp_nlp_config *config, ocp_nlp_dims *dims); + +/// Destructor of the output struct. +/// +/// \param out The output struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_out_destroy(void *out); + + +/// Sets fields in the output struct of an nlp solver, used to initialize the solver. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param out The output struct. +/// \param stage Stage number. +/// \param field The name of the field, either x, u, pi. +/// \param value Initialization values. +ACADOS_SYMBOL_EXPORT void ocp_nlp_out_set(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, void *value); + + +/// Gets values of fields in the output struct of an nlp solver. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param out The output struct. +/// \param stage Stage number. +/// \param field The name of the field, either x, u, z, pi. +/// \param value Pointer to the output memory. +ACADOS_SYMBOL_EXPORT void ocp_nlp_out_get(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, void *value); + +// +ACADOS_SYMBOL_EXPORT void ocp_nlp_get_at_stage(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_solver *solver, + int stage, const char *field, void *value); + +// TODO(andrea): remove this once/if the MATLAB interface uses the new setters below? +ACADOS_SYMBOL_EXPORT int ocp_nlp_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field); + +ACADOS_SYMBOL_EXPORT void ocp_nlp_constraint_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, int *dims_out); + +ACADOS_SYMBOL_EXPORT void ocp_nlp_cost_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, int *dims_out); + +ACADOS_SYMBOL_EXPORT void ocp_nlp_qp_dims_get_from_attr(ocp_nlp_config *config, ocp_nlp_dims *dims, ocp_nlp_out *out, + int stage, const char *field, int *dims_out); + +/* opts */ + +/// Creates an options struct for the non-linear program. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +ACADOS_SYMBOL_EXPORT void *ocp_nlp_solver_opts_create(ocp_nlp_config *config, ocp_nlp_dims *dims); + +/// Destructor of the options. +/// +/// \param opts The options struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_opts_destroy(void *opts); + +/// Sets an option. +/// +/// \param config The configuration struct. +/// \param opts_ The options struct. +/// \param field Name of the option. +/// \param value Value of the option. +ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_opts_set(ocp_nlp_config *config, void *opts_, const char *field, void* value); + + +// ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_opts_get(ocp_nlp_config *config, void *opts_, const char *field, void* value); + + +ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_opts_set_at_stage(ocp_nlp_config *config, void *opts_, int stage, const char *field, void* value); + + +/// TBC +/// Updates the options. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param opts_ The options struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_opts_update(ocp_nlp_config *config, ocp_nlp_dims *dims, void *opts_); + + +/* solver */ + +/// Creates an ocp solver. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param opts_ The options struct. +/// \return The solver. +ACADOS_SYMBOL_EXPORT ocp_nlp_solver *ocp_nlp_solver_create(ocp_nlp_config *config, ocp_nlp_dims *dims, void *opts_); + +/// Destructor of the solver. +/// +/// \param solver The solver struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_destroy(void *solver); + +/// Solves the optimal control problem. Call ocp_nlp_precompute before +/// calling this functions (TBC). +/// +/// \param solver The solver struct. +/// \param nlp_in The inputs struct. +/// \param nlp_out The output struct. +ACADOS_SYMBOL_EXPORT int ocp_nlp_solve(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out); + + + +/// Resets the memory of the QP solver +/// +/// \param solver The solver struct. +/// \param nlp_in The inputs struct. +/// \param nlp_out The output struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_solver_reset_qp_memory(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out); + + +/// Performs precomputations for the solver. Needs to be called before +/// ocl_nlp_solve (TBC). +/// +/// \param solver The solver struct. +/// \param nlp_in The inputs struct. +/// \param nlp_out The output struct. +ACADOS_SYMBOL_EXPORT int ocp_nlp_precompute(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out); + + +/// Computes cost function value. +/// +/// \param solver The solver struct. +/// \param nlp_in The inputs struct. +/// \param nlp_out The output struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_eval_cost(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out); + + +/// Computes the residuals. +/// +/// \param solver The solver struct. +/// \param nlp_in The inputs struct. +/// \param nlp_out The output struct. +ACADOS_SYMBOL_EXPORT void ocp_nlp_eval_residuals(ocp_nlp_solver *solver, ocp_nlp_in *nlp_in, ocp_nlp_out *nlp_out); + + +// +ACADOS_SYMBOL_EXPORT void ocp_nlp_eval_param_sens(ocp_nlp_solver *solver, char *field, int stage, int index, ocp_nlp_out *sens_nlp_out); + +/* get */ +/// \param config The configuration struct. +/// \param solver The solver struct. +/// \param field Supports "sqp_iter", "status", "nlp_res", "time_tot", ... +/// \param return_value_ Pointer to the output memory. +ACADOS_SYMBOL_EXPORT void ocp_nlp_get(ocp_nlp_config *config, ocp_nlp_solver *solver, + const char *field, void *return_value_); + +/* set */ +/// Sets the initial guesses for the integrator for the given stage. +/// +/// \param config The configuration struct. +/// \param solver The ocp_nlp_solver struct. +/// \param stage Stage number. +/// \param field Supports "z_guess", "xdot_guess" (IRK), "phi_guess" (GNSF-IRK) +/// \param value The initial guess for the algebraic variables in the integrator (if continuous model is used). +ACADOS_SYMBOL_EXPORT void ocp_nlp_set(ocp_nlp_config *config, ocp_nlp_solver *solver, + int stage, const char *field, void *value); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // INTERFACES_ACADOS_C_OCP_NLP_INTERFACE_H_ diff --git a/third_party/acados/include/acados_c/ocp_qp_interface.h b/third_party/acados/include/acados_c/ocp_qp_interface.h new file mode 100644 index 0000000000..3dc3f1a532 --- /dev/null +++ b/third_party/acados/include/acados_c/ocp_qp_interface.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef INTERFACES_ACADOS_C_OCP_QP_INTERFACE_H_ +#define INTERFACES_ACADOS_C_OCP_QP_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/ocp_qp/ocp_qp_common.h" +#include "acados/ocp_qp/ocp_qp_xcond_solver.h" + + +/// QP solver types (Enumeration). +/// +/// Full list of fields: +/// PARTIAL_CONDENSING_HPIPM +/// PARTIAL_CONDENSING_HPMPC +/// PARTIAL_CONDENSING_OOQP +/// PARTIAL_CONDENSING_OSQP +/// PARTIAL_CONDENSING_QPDUNES +/// FULL_CONDENSING_HPIPM +/// FULL_CONDENSING_QPOASES +/// FULL_CONDENSING_QORE +/// FULL_CONDENSING_OOQP +/// INVALID_QP_SOLVER +/// +/// Note: In this enumeration the partial condensing solvers have to be +/// specified before the full condensing solvers. +typedef enum { + PARTIAL_CONDENSING_HPIPM, +#ifdef ACADOS_WITH_HPMPC + PARTIAL_CONDENSING_HPMPC, +#else + PARTIAL_CONDENSING_HPMPC_NOT_AVAILABLE, +#endif +#ifdef ACADOS_WITH_OOQP + PARTIAL_CONDENSING_OOQP, +#else + PARTIAL_CONDENSING_OOQP_NOT_AVAILABLE, +#endif +#ifdef ACADOS_WITH_OSQP + PARTIAL_CONDENSING_OSQP, +#else + PARTIAL_CONDENSING_OSQP_NOT_AVAILABLE, +#endif +#ifdef ACADOS_WITH_QPDUNES + PARTIAL_CONDENSING_QPDUNES, +#else + PARTIAL_CONDENSING_QPDUNES_NOT_AVAILABLE, +#endif + FULL_CONDENSING_HPIPM, +#ifdef ACADOS_WITH_QPOASES + FULL_CONDENSING_QPOASES, +#else + FULL_CONDENSING_QPOASES_NOT_AVAILABLE, +#endif +#ifdef ACADOS_WITH_DAQP + FULL_CONDENSING_DAQP, +#else + FULL_CONDENSING_DAQP_NOT_AVAILABLE, +#endif +#ifdef ACADOS_WITH_QORE + FULL_CONDENSING_QORE, +#else + FULL_CONDENSING_QORE_NOT_AVAILABLE, +#endif +#ifdef ACADOS_WITH_OOQP + FULL_CONDENSING_OOQP, +#else + FULL_CONDENSING_OOQP_NOT_AVAILABLE, +#endif + INVALID_QP_SOLVER, +} ocp_qp_solver_t; + + +/// Struct containing qp solver +typedef struct +{ + ocp_qp_solver_t qp_solver; +} ocp_qp_solver_plan_t; + + +/// Linear ocp configuration. +typedef struct +{ + ocp_qp_xcond_solver_config *config; + ocp_qp_xcond_solver_dims *dims; + void *opts; + void *mem; + void *work; +} ocp_qp_solver; + + +/// Initializes the qp solver configuration. +/// TBC should this be private/static - no, used in ocp_nlp +void ocp_qp_xcond_solver_config_initialize_from_plan( + ocp_qp_solver_t solver_name, ocp_qp_xcond_solver_config *solver_config); + +/// Constructs a qp solver config and Initializes with default values. +/// +/// \param plan The qp solver plan struct. +ocp_qp_xcond_solver_config *ocp_qp_xcond_solver_config_create(ocp_qp_solver_plan_t plan); + +/// Destructor for config struct, frees memory. +/// +/// \param config The config object to destroy. +void ocp_qp_xcond_solver_config_free(ocp_qp_xcond_solver_config *config); + + +/// Constructs a struct that contains the dimensions for the variables of the qp. +/// +/// \param N The number of variables. +ocp_qp_dims *ocp_qp_dims_create(int N); + +/// Destructor of The dimension struct. +/// +/// \param dims The dimension struct. +void ocp_qp_dims_free(void *dims); + +// +ocp_qp_xcond_solver_dims *ocp_qp_xcond_solver_dims_create(ocp_qp_xcond_solver_config *config, int N); +// +ocp_qp_xcond_solver_dims *ocp_qp_xcond_solver_dims_create_from_ocp_qp_dims( + ocp_qp_xcond_solver_config *config, ocp_qp_dims *dims); +// +void ocp_qp_xcond_solver_dims_free(ocp_qp_xcond_solver_dims *dims_); + +void ocp_qp_xcond_solver_dims_set(void *config_, ocp_qp_xcond_solver_dims *dims, + int stage, const char *field, int* value); + + +/// Constructs an input object for the qp. +/// +/// \param dims The dimension struct. +ocp_qp_in *ocp_qp_in_create(ocp_qp_dims *dims); + + +void ocp_qp_in_set(ocp_qp_xcond_solver_config *config, ocp_qp_in *in, + int stage, char *field, void *value); + +/// Destructor of the inputs struct. +/// +/// \param in_ The inputs struct. +void ocp_qp_in_free(void *in_); + + +/// Constructs an outputs object for the qp. +/// +/// \param dims The dimension struct. +ocp_qp_out *ocp_qp_out_create(ocp_qp_dims *dims); + +/// Destructor of the output struct. +/// +/// \param out_ The output struct. +void ocp_qp_out_free(void *out_); + + +/// Getter of output struct +void ocp_qp_out_get(ocp_qp_out *out, const char *field, void *value); + + +/// Constructs an options object for the qp. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +void *ocp_qp_xcond_solver_opts_create(ocp_qp_xcond_solver_config *config, + ocp_qp_xcond_solver_dims *dims); + +/// Destructor of the options struct. +/// +/// \param opts The options struct to destroy. +void ocp_qp_xcond_solver_opts_free(ocp_qp_xcond_solver_opts *opts); + + +/// Setter of the options struct. +/// +/// \param opts The options struct. +void ocp_qp_xcond_solver_opts_set(ocp_qp_xcond_solver_config *config, + ocp_qp_xcond_solver_opts *opts, const char *field, void* value); + +/// TBC Should be private/static? +acados_size_t ocp_qp_calculate_size(ocp_qp_xcond_solver_config *config, ocp_qp_xcond_solver_dims *dims, void *opts_); + + +/// TBC Reserves memory? TBC Should this be private? +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param opts_ The options struct. +/// \param raw_memory Pointer to raw memory to assign to qp solver. +ocp_qp_solver *ocp_qp_assign(ocp_qp_xcond_solver_config *config, ocp_qp_xcond_solver_dims *dims, + void *opts_, void *raw_memory); + +/// Creates a qp solver. Reserves memory. +/// +/// \param config The configuration struct. +/// \param dims The dimension struct. +/// \param opts_ The options struct. +ocp_qp_solver *ocp_qp_create(ocp_qp_xcond_solver_config *config, + ocp_qp_xcond_solver_dims *dims, void *opts_); + + +/// Destroys a qp solver. Frees memory. +/// +/// \param solver The qp solver +void ocp_qp_solver_destroy(ocp_qp_solver *solver); + +void ocp_qp_x_cond_solver_free(ocp_qp_xcond_solver_config *config, + ocp_qp_xcond_solver_dims *dims, void *opts_); + + +/// Solves the qp. +/// +/// \param solver The solver. +/// \param qp_in The inputs struct. +/// \param qp_out The output struct. +int ocp_qp_solve(ocp_qp_solver *solver, ocp_qp_in *qp_in, ocp_qp_out *qp_out); + + +/// Calculates the infinity norm of the residuals. +/// +/// \param dims The dimension struct. +/// \param qp_in The inputs struct. +/// \param qp_out The output struct. +/// \param res Output array for the residuals. +void ocp_qp_inf_norm_residuals(ocp_qp_dims *dims, ocp_qp_in *qp_in, ocp_qp_out *qp_out, + double *res); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // INTERFACES_ACADOS_C_OCP_QP_INTERFACE_H_ diff --git a/third_party/acados/include/acados_c/sim_interface.h b/third_party/acados/include/acados_c/sim_interface.h new file mode 100644 index 0000000000..09a05d6995 --- /dev/null +++ b/third_party/acados/include/acados_c/sim_interface.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) The acados authors. + * + * This file is part of acados. + * + * The 2-Clause BSD License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.; + */ + + +#ifndef INTERFACES_ACADOS_C_SIM_INTERFACE_H_ +#define INTERFACES_ACADOS_C_SIM_INTERFACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acados/sim/sim_common.h" + + + +typedef enum +{ + ERK, + IRK, + GNSF, + LIFTED_IRK, + INVALID_SIM_SOLVER, +} sim_solver_t; + + + +typedef struct +{ + sim_solver_t sim_solver; +} sim_solver_plan_t; + + + +typedef struct +{ + sim_config *config; + void *dims; + void *opts; + void *mem; + void *work; +} sim_solver; + + + +/* config */ +// +ACADOS_SYMBOL_EXPORT sim_config *sim_config_create(sim_solver_plan_t plan); +// +ACADOS_SYMBOL_EXPORT void sim_config_destroy(void *config); + +/* dims */ +// +ACADOS_SYMBOL_EXPORT void *sim_dims_create(void *config_); +// +ACADOS_SYMBOL_EXPORT void sim_dims_destroy(void *dims); +// +ACADOS_SYMBOL_EXPORT void sim_dims_set(sim_config *config, void *dims, const char *field, const int* value); +// +ACADOS_SYMBOL_EXPORT void sim_dims_get(sim_config *config, void *dims, const char *field, int* value); +// +ACADOS_SYMBOL_EXPORT void sim_dims_get_from_attr(sim_config *config, void *dims, const char *field, int *dims_out); + +/* in */ +// +ACADOS_SYMBOL_EXPORT sim_in *sim_in_create(sim_config *config, void *dims); +// +ACADOS_SYMBOL_EXPORT void sim_in_destroy(void *out); +// +ACADOS_SYMBOL_EXPORT int sim_in_set(void *config_, void *dims_, sim_in *in, const char *field, void *value); + + +/* out */ +// +ACADOS_SYMBOL_EXPORT sim_out *sim_out_create(sim_config *config, void *dims); +// +ACADOS_SYMBOL_EXPORT void sim_out_destroy(void *out); +// +ACADOS_SYMBOL_EXPORT int sim_out_get(void *config, void *dims, sim_out *out, const char *field, void *value); + +/* opts */ +// +ACADOS_SYMBOL_EXPORT void *sim_opts_create(sim_config *config, void *dims); +// +ACADOS_SYMBOL_EXPORT void sim_opts_destroy(void *opts); +// +ACADOS_SYMBOL_EXPORT void sim_opts_set(sim_config *config, void *opts, const char *field, void *value); +// +ACADOS_SYMBOL_EXPORT void sim_opts_get(sim_config *config, void *opts, const char *field, void *value); + +/* solver */ +// +ACADOS_SYMBOL_EXPORT acados_size_t sim_calculate_size(sim_config *config, void *dims, void *opts_); +// +ACADOS_SYMBOL_EXPORT sim_solver *sim_assign(sim_config *config, void *dims, void *opts_, void *raw_memory); +// +ACADOS_SYMBOL_EXPORT sim_solver *sim_solver_create(sim_config *config, void *dims, void *opts_); +// +ACADOS_SYMBOL_EXPORT void sim_solver_destroy(void *solver); +// +ACADOS_SYMBOL_EXPORT int sim_solve(sim_solver *solver, sim_in *in, sim_out *out); +// +ACADOS_SYMBOL_EXPORT int sim_precompute(sim_solver *solver, sim_in *in, sim_out *out); +// +ACADOS_SYMBOL_EXPORT int sim_solver_set(sim_solver *solver, const char *field, void *value); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // INTERFACES_ACADOS_C_SIM_INTERFACE_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo.h b/third_party/acados/include/blasfeo/include/blasfeo.h new file mode 100644 index 0000000000..c854918193 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo.h @@ -0,0 +1,52 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#include "blasfeo_processor_features.h" +#include "blasfeo_target.h" +#include "blasfeo_block_size.h" +#include "blasfeo_stdlib.h" +#include "blasfeo_common.h" +#include "blasfeo_d_aux.h" +#include "blasfeo_d_aux_ext_dep.h" +#include "blasfeo_d_kernel.h" +#include "blasfeo_d_blas.h" +#include "blasfeo_s_aux.h" +#include "blasfeo_s_aux_ext_dep.h" +#include "blasfeo_s_kernel.h" +#include "blasfeo_s_blas.h" +#include "blasfeo_i_aux_ext_dep.h" +#include "blasfeo_v_aux_ext_dep.h" +#include "blasfeo_timing.h" +#include "blasfeo_memory.h" diff --git a/third_party/acados/include/blasfeo/include/blasfeo_block_size.h b/third_party/acados/include/blasfeo/include/blasfeo_block_size.h new file mode 100644 index 0000000000..5d0907a61c --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_block_size.h @@ -0,0 +1,447 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_BLOCK_SIZE_H_ +#define BLASFEO_BLOCK_SIZE_H_ + + + +#define D_EL_SIZE 8 // double precision +#define S_EL_SIZE 4 // single precision + + + +#if defined( TARGET_X64_INTEL_SKYLAKE_X ) +// common +#define CACHE_LINE_SIZE 64 // data cache size: 64 bytes +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB, 8-way +#define L2_CACHE_SIZE (256*1024) //(1024*1024) // L2 data cache size: 1 MB ; DTLB1 64*4 kB = 256 kB +#define LLC_CACHE_SIZE (6*1024*1024) //(8*1024*1024) // LLC cache size: 8 MB ; TLB 1536*4 kB = 6 MB +// double +#define D_PS 8 // panel size +#define D_PLD 8 // 4 // GCD of panel length +#define D_M_KERNEL 24 // max kernel size +#define D_N_KERNEL 8 // max kernel size +#define D_KC 128 //256 // 192 +#define D_NC 144 //72 //96 //72 // 120 // 512 +#define D_MC 2400 // 6000 +// single +#define S_PS 16 // panel size +#define S_PLD 4 // GCD of panel length TODO probably 16 when writing assebly +#define S_M_KERNEL 32 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 128 //256 +#define S_NC 128 //144 +#define S_MC 3000 + +#elif defined( TARGET_X64_INTEL_HASWELL ) +// common +#define CACHE_LINE_SIZE 64 // data cache size: 64 bytes +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB, 8-way +#define L2_CACHE_SIZE (256*1024) // L2 data cache size: 256 kB ; DTLB1 64*4 kB = 256 kB +#define LLC_CACHE_SIZE (6*1024*1024) // LLC cache size: 6 MB ; TLB 1024*4 kB = 4 MB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 12 // max kernel size +#define D_N_KERNEL 8 // max kernel size +#define D_KC 256 // 192 +#define D_NC 64 //96 //72 // 120 // 512 +#define D_MC 1500 +// single +#define S_PS 8 // panel size +#define S_PLD 4 // 2 // GCD of panel length +#define S_M_KERNEL 24 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 256 +#define S_NC 144 +#define S_MC 3000 + +#elif defined( TARGET_X64_INTEL_SANDY_BRIDGE ) +// common +#define CACHE_LINE_SIZE 64 // data cache size: 64 bytes +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB, 8-way +#define L2_CACHE_SIZE (256*1024) // L2 data cache size: 256 kB ; DTLB1 64*4 kB = 256 kB +#define LLC_CACHE_SIZE (4*1024*1024) // LLC cache size: 4 MB ; TLB 1024*4 kB = 4 MB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 8 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 //320 //256 //320 +#define D_NC 72 //64 //72 //60 // 120 +#define D_MC 1000 // 800 +// single +#define S_PS 8 // panel size +#define S_PLD 4 // 2 // GCD of panel length +#define S_M_KERNEL 16 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 256 +#define S_NC 144 +#define S_MC 2000 + +#elif defined( TARGET_X64_INTEL_CORE ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + +#elif defined( TARGET_X64_AMD_BULLDOZER ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined( TARGET_X86_AMD_JAGUAR ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined( TARGET_X86_AMD_BARCELONA ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined(TARGET_ARMV8A_APPLE_M1) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (128*1024) // L1 data cache size (big cores): 64 kB, ?-way ; DTLB1 ? +#define LLC_CACHE_SIZE (12*1024*1024) // LLC (L2) cache size (big cores): 12 MB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 8 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 512 //256 +#define D_NC 128 //256 +#define D_MC 6000 +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 8 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 512 +#define S_NC 256 +#define S_MC 6000 + + +#elif defined(TARGET_ARMV8A_ARM_CORTEX_A76) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (64*1024) // L1 data cache size: 64 kB, 4-way ; DTLB1 48*4 kB = 192 kB +#define LLC_CACHE_SIZE (1*1024*1024) // LLC cache size: 1 MB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 8 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 512 //256 +#define D_NC 128 //256 +#define D_MC 6000 +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 8 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 512 +#define S_NC 256 +#define S_MC 6000 + + +#elif defined(TARGET_ARMV8A_ARM_CORTEX_A73) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 (64?) kB, 4-way, seen as 8-(16-)way ; DTLB1 48*4 kB = 192 kB +#define LLC_CACHE_SIZE (1*1024*1024) // LLC cache size: 1 MB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 8 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 320 +#define D_NC 256 +#define D_MC 6000 +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 8 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined(TARGET_ARMV8A_ARM_CORTEX_A57) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB, 2-way ; DTLB1 32*4 kB = 128 kB +#define LLC_CACHE_SIZE (1*1024*1024) // LLC cache size: 1 MB // 2 MB ??? +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 8 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 128 //224 //256 //192 +#define D_NC 72 //40 //36 //48 +#define D_MC (4*192) //512 //488 //600 +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 8 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined(TARGET_ARMV8A_ARM_CORTEX_A55) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB, 4-way ; DTLB1 16*4 kB = 64 kB +#define LLC_CACHE_SIZE (512*1024) // LLC cache size: 512 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 12 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 224 +#define D_NC 160 +#define D_MC 6000 +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 8 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined(TARGET_ARMV8A_ARM_CORTEX_A53) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB, 4-way ??? ; DTLB1 10*4 kB = 40 kB +#define LLC_CACHE_SIZE (256*1024) // LLC cache size: 256 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 12 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 160 +#define D_NC 128 +#define D_MC 6000 +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 8 // max kernel size +#define S_N_KERNEL 8 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined( TARGET_ARMV7A_ARM_CORTEX_A15 ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined( TARGET_ARMV7A_ARM_CORTEX_A7 ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined( TARGET_ARMV7A_ARM_CORTEX_A9 ) +// common +#define CACHE_LINE_SIZE 32 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#elif defined( TARGET_GENERIC ) +// common +#define CACHE_LINE_SIZE 64 +#define L1_CACHE_SIZE (32*1024) // L1 data cache size: 32 kB +// double +#define D_PS 4 // panel size +#define D_PLD 4 // 2 // GCD of panel length +#define D_M_KERNEL 4 // max kernel size +#define D_N_KERNEL 4 // max kernel size +#define D_KC 256 +#define D_NC 128 // TODO these are just dummy +#define D_MC 3000 // TODO these are just dummy + +// single +#define S_PS 4 +#define S_PLD 4 //2 +#define S_M_KERNEL 4 // max kernel size +#define S_N_KERNEL 4 // max kernel size +#define S_KC 256 +#define S_NC 128 // TODO these are just dummy +#define S_MC 3000 // TODO these are just dummy + + +#else +#error "Unknown architecture" +#endif + + + +#define D_CACHE_LINE_EL (CACHE_LINE_SIZE/D_EL_SIZE) +#define D_L1_CACHE_EL (L1_CACHE_SIZE/D_EL_SIZE) +#define D_L2_CACHE_EL (L2_CACHE_SIZE/D_EL_SIZE) +#define D_LLC_CACHE_EL (LLC_CACHE_SIZE/D_EL_SIZE) + +#define S_CACHE_LINE_EL (CACHE_LINE_SIZE/S_EL_SIZE) +#define S_L1_CACHE_EL (L1_CACHE_SIZE/S_EL_SIZE) +#define S_L2_CACHE_EL (L2_CACHE_SIZE/S_EL_SIZE) +#define S_LLC_CACHE_EL (LLC_CACHE_SIZE/S_EL_SIZE) + + + +#endif // BLASFEO_BLOCK_SIZE_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_common.h b/third_party/acados/include/blasfeo/include/blasfeo_common.h new file mode 100644 index 0000000000..03b6c36d84 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_common.h @@ -0,0 +1,274 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_COMMON_H_ +#define BLASFEO_COMMON_H_ + + + +#include "blasfeo_target.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__INTEL_LLVM_COMPILER) +#define ALIGNED(VEC, BYTES) VEC __attribute__ ((aligned ( BYTES ))) +#elif defined (_MSC_VER) +#define ALIGNED(VEC, BYTES) __declspec(align( BYTES )) VEC +#else +#define ALIGNED(VEC, BYTES) VEC +#endif + + + + +#if ( defined(LA_HIGH_PERFORMANCE) & defined(MF_PANELMAJ) ) | ( defined(LA_REFERENCE) & defined(MF_PANELMAJ) ) + +#include "blasfeo_block_size.h" + +// matrix structure +struct blasfeo_dmat + { + double *mem; // pointer to passed chunk of memory + double *pA; // pointer to a pm*pn array of doubles, the first is aligned to cache line size + double *dA; // pointer to a min(m,n) (or max???) array of doubles + int m; // rows + int n; // cols + int pm; // packed number or rows + int cn; // packed number or cols + int use_dA; // flag to tell if dA can be used + int memsize; // size of needed memory + }; + +struct blasfeo_smat + { + float *mem; // pointer to passed chunk of memory + float *pA; // pointer to a pm*pn array of floats, the first is aligned to cache line size + float *dA; // pointer to a min(m,n) (or max???) array of floats + int m; // rows + int n; // cols + int pm; // packed number or rows + int cn; // packed number or cols + int use_dA; // flag to tell if dA can be used + int memsize; // size of needed memory + }; + +// vector structure +struct blasfeo_dvec + { + double *mem; // pointer to passed chunk of memory + double *pa; // pointer to a pm array of doubles, the first is aligned to cache line size + int m; // size + int pm; // packed size + int memsize; // size of needed memory + }; + +struct blasfeo_svec + { + float *mem; // pointer to passed chunk of memory + float *pa; // pointer to a pm array of floats, the first is aligned to cache line size + int m; // size + int pm; // packed size + int memsize; // size of needed memory + }; + +#define BLASFEO_DMATEL(sA,ai,aj) ((sA)->pA[((ai)-((ai)&(D_PS-1)))*(sA)->cn+(aj)*D_PS+((ai)&(D_PS-1))]) +#define BLASFEO_SMATEL(sA,ai,aj) ((sA)->pA[((ai)-((ai)&(S_PS-1)))*(sA)->cn+(aj)*S_PS+((ai)&(S_PS-1))]) +#define BLASFEO_DVECEL(sa,ai) ((sa)->pa[ai]) +#define BLASFEO_SVECEL(sa,ai) ((sa)->pa[ai]) + +#elif ( defined(LA_HIGH_PERFORMANCE) & defined(MF_COLMAJ) ) | ( defined(LA_REFERENCE) & defined(MF_COLMAJ) ) | defined(LA_EXTERNAL_BLAS_WRAPPER) + +// matrix structure +struct blasfeo_dmat + { + double *mem; // pointer to passed chunk of memory + double *pA; // pointer to a m*n array of doubles + double *dA; // pointer to a min(m,n) (or max???) array of doubles + int m; // rows + int n; // cols + int use_dA; // flag to tell if dA can be used + int memsize; // size of needed memory + }; + +struct blasfeo_smat + { + float *mem; // pointer to passed chunk of memory + float *pA; // pointer to a m*n array of floats + float *dA; // pointer to a min(m,n) (or max???) array of floats + int m; // rows + int n; // cols + int use_dA; // flag to tell if dA can be used + int memsize; // size of needed memory + }; + +// vector structure +struct blasfeo_dvec + { + double *mem; // pointer to passed chunk of memory + double *pa; // pointer to a m array of doubles, the first is aligned to cache line size + int m; // size + int memsize; // size of needed memory + }; + +struct blasfeo_svec + { + float *mem; // pointer to passed chunk of memory + float *pa; // pointer to a m array of floats, the first is aligned to cache line size + int m; // size + int memsize; // size of needed memory + }; + +#define BLASFEO_DMATEL(sA,ai,aj) ((sA)->pA[(ai)+(aj)*(sA)->m]) +#define BLASFEO_SMATEL(sA,ai,aj) ((sA)->pA[(ai)+(aj)*(sA)->m]) +#define BLASFEO_DVECEL(sa,ai) ((sa)->pa[ai]) +#define BLASFEO_SVECEL(sa,ai) ((sa)->pa[ai]) + +#else + +#error : wrong LA or MF choice + +#endif + + + +// Explicitly panel-major matrix structure +struct blasfeo_pm_dmat + { + double *mem; // pointer to passed chunk of memory + double *pA; // pointer to a pm*pn array of doubles, the first is aligned to cache line size + double *dA; // pointer to a min(m,n) (or max???) array of doubles + int m; // rows + int n; // cols + int pm; // packed number or rows + int cn; // packed number or cols + int use_dA; // flag to tell if dA can be used + int ps; // panel size + int memsize; // size of needed memory + }; + +struct blasfeo_pm_smat + { + float *mem; // pointer to passed chunk of memory + float *pA; // pointer to a pm*pn array of floats, the first is aligned to cache line size + float *dA; // pointer to a min(m,n) (or max???) array of floats + int m; // rows + int n; // cols + int pm; // packed number or rows + int cn; // packed number or cols + int use_dA; // flag to tell if dA can be used + int ps; // panel size + int memsize; // size of needed memory + }; + +struct blasfeo_pm_dvec + { + double *mem; // pointer to passed chunk of memory + double *pa; // pointer to a pm array of doubles, the first is aligned to cache line size + int m; // size + int pm; // packed size + int memsize; // size of needed memory + }; + +struct blasfeo_pm_svec + { + float *mem; // pointer to passed chunk of memory + float *pa; // pointer to a pm array of floats, the first is aligned to cache line size + int m; // size + int pm; // packed size + int memsize; // size of needed memory + }; + +// Explicitly column-major matrix structure +struct blasfeo_cm_dmat + { + double *mem; // pointer to passed chunk of memory + double *pA; // pointer to a m*n array of doubles + double *dA; // pointer to a min(m,n) (or max???) array of doubles + int m; // rows + int n; // cols + int use_dA; // flag to tell if dA can be used + int memsize; // size of needed memory + }; + +struct blasfeo_cm_smat + { + float *mem; // pointer to passed chunk of memory + float *pA; // pointer to a m*n array of floats + float *dA; // pointer to a min(m,n) (or max???) array of floats + int m; // rows + int n; // cols + int use_dA; // flag to tell if dA can be used + int memsize; // size of needed memory + }; + +struct blasfeo_cm_dvec + { + double *mem; // pointer to passed chunk of memory + double *pa; // pointer to a m array of doubles, the first is aligned to cache line size + int m; // size + int memsize; // size of needed memory + }; + +struct blasfeo_cm_svec + { + float *mem; // pointer to passed chunk of memory + float *pa; // pointer to a m array of floats, the first is aligned to cache line size + int m; // size + int memsize; // size of needed memory + }; + + +#define BLASFEO_PM_DMATEL(sA,ai,aj) ((sA)->pA[((ai)-((ai)&((sA)->ps-1)))*(sA)->cn+(aj)*((sA)->ps)+((ai)&((sA)->ps-1))]) +#define BLASFEO_PM_SMATEL(sA,ai,aj) ((sA)->pA[((ai)-((ai)&((sA)->ps-1)))*(sA)->cn+(aj)*((sA)->ps)+((ai)&((sA)->ps-1))]) +#define BLASFEO_PM_DVECEL(sa,ai) ((sa)->pa[ai]) +#define BLASFEO_PM_SVECEL(sa,ai) ((sa)->pa[ai]) +#define BLASFEO_CM_DMATEL(sA,ai,aj) ((sA)->pA[(ai)+(aj)*(sA)->m]) +#define BLASFEO_CM_SMATEL(sA,ai,aj) ((sA)->pA[(ai)+(aj)*(sA)->m]) +#define BLASFEO_CM_DVECEL(sa,ai) ((sa)->pa[ai]) +#define BLASFEO_CM_SVECEL(sa,ai) ((sa)->pa[ai]) + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_COMMON_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_aux.h b/third_party/acados/include/blasfeo/include/blasfeo_d_aux.h new file mode 100644 index 0000000000..a6d6119c6c --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_aux.h @@ -0,0 +1,255 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +/* + * auxiliary algebra operations header + * + * include/blasfeo_aux_lib*.h + * + */ + +#ifndef BLASFEO_D_AUX_H_ +#define BLASFEO_D_AUX_H_ + + + +#include + +#include "blasfeo_common.h" +#include "blasfeo_d_aux_old.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + +// --- memory size calculations +// +// returns the memory size (in bytes) needed for a dmat +size_t blasfeo_memsize_dmat(int m, int n); +// returns the memory size (in bytes) needed for the diagonal of a dmat +size_t blasfeo_memsize_diag_dmat(int m, int n); +// returns the memory size (in bytes) needed for a dvec +size_t blasfeo_memsize_dvec(int m); + +// --- creation +// +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_create_dmat(int m, int n, struct blasfeo_dmat *sA, void *memory); +// create a strvec for a vector of size m by using memory passed by a pointer (pointer is not updated) +void blasfeo_create_dvec(int m, struct blasfeo_dvec *sA, void *memory); + +// --- packing +// pack the column-major matrix A into the matrix struct B +void blasfeo_pack_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// pack the lower-triangular column-major matrix A into the matrix struct B +void blasfeo_pack_l_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// pack the upper-triangular column-major matrix A into the matrix struct B +void blasfeo_pack_u_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// transpose and pack the column-major matrix A into the matrix struct B +void blasfeo_pack_tran_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// pack the vector x into the vector structure y +void blasfeo_pack_dvec(int m, double *x, int xi, struct blasfeo_dvec *sy, int yi); +// unpack the matrix structure A into the column-major matrix B +void blasfeo_unpack_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, double *B, int ldb); +// transpose and unpack the matrix structure A into the column-major matrix B +void blasfeo_unpack_tran_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, double *B, int ldb); +// pack the vector structure x into the vector y +void blasfeo_unpack_dvec(int m, struct blasfeo_dvec *sx, int xi, double *y, int yi); + +// --- cast +// +//void d_cast_mat2strmat(double *A, struct blasfeo_dmat *sA); // TODO +//void d_cast_diag_mat2strmat(double *dA, struct blasfeo_dmat *sA); // TODO +//void d_cast_vec2vecmat(double *a, struct blasfeo_dvec *sx); // TODO + + +// ge +// --- insert/extract +// +// sA[ai, aj] <= a +void blasfeo_dgein1(double a, struct blasfeo_dmat *sA, int ai, int aj); +// <= sA[ai, aj] +double blasfeo_dgeex1(struct blasfeo_dmat *sA, int ai, int aj); + +// --- set +// A <= alpha +void blasfeo_dgese(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj); + +// --- copy / scale +// B <= A +void blasfeo_dgecp(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// A <= alpha*A +void blasfeo_dgesc(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +// B <= alpha*A +void blasfeo_dgecpsc(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// B <= A, A lower triangular +void blasfeo_dtrcp_l(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +void blasfeo_dtrcpsc_l(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +void blasfeo_dtrsc_l(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj); + +// --- sum +// B <= B + alpha*A +void blasfeo_dgead(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// y <= y + alpha*x +void blasfeo_dvecad(int m, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); + +// --- traspositions +// B <= A' +void blasfeo_dgetr(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// B <= A', A lower triangular +void blasfeo_dtrtr_l(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// B <= A', A upper triangular +void blasfeo_dtrtr_u(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); + +// dia +// diag(A) += alpha +void blasfeo_ddiare(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +// diag(A) <= alpha*x +void blasfeo_ddiain(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// diag(A)[idx] <= alpha*x +void blasfeo_ddiain_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// x <= diag(A) +void blasfeo_ddiaex(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +// x <= diag(A)[idx] +void blasfeo_ddiaex_sp(int kmax, double alpha, int *idx, struct blasfeo_dmat *sD, int di, int dj, struct blasfeo_dvec *sx, int xi); +// diag(A) += alpha*x +void blasfeo_ddiaad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// diag(A)[idx] += alpha*x +void blasfeo_ddiaad_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// diag(A)[idx] = y + alpha*x +void blasfeo_ddiaadin_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, int *idx, struct blasfeo_dmat *sD, int di, int dj); + +// row +void blasfeo_drowin(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_drowex(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +void blasfeo_drowad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_drowad_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_drowsw(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +void blasfeo_drowpe(int kmax, int *ipiv, struct blasfeo_dmat *sA); +void blasfeo_drowpei(int kmax, int *ipiv, struct blasfeo_dmat *sA); + +// col +void blasfeo_dcolex(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +void blasfeo_dcolin(int kmax, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_dcolad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_dcolsc(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_dcolsw(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +void blasfeo_dcolpe(int kmax, int *ipiv, struct blasfeo_dmat *sA); +void blasfeo_dcolpei(int kmax, int *ipiv, struct blasfeo_dmat *sA); + +// vec +// a <= alpha +void blasfeo_dvecse(int m, double alpha, struct blasfeo_dvec *sx, int xi); +// sx[xi] <= a +void blasfeo_dvecin1(double a, struct blasfeo_dvec *sx, int xi); +// <= sx[xi] +double blasfeo_dvecex1(struct blasfeo_dvec *sx, int xi); +// y <= x +void blasfeo_dveccp(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); +// x <= alpha*x +void blasfeo_dvecsc(int m, double alpha, struct blasfeo_dvec *sx, int xi); +// y <= alpha*x +void blasfeo_dveccpsc(int m, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); +// z[idx] += alpha * x +void blasfeo_dvecad_sp(int m, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dvec *sz, int zi); +// z[idx] <= alpha * x +void blasfeo_dvecin_sp(int m, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dvec *sz, int zi); +// z <= alpha * x[idx] +void blasfeo_dvecex_sp(int m, double alpha, int *idx, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z += alpha * x[idx] +void blasfeo_dvecexad_sp(int m, double alpha, int *idx, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); + +void blasfeo_dveccl(int m, + struct blasfeo_dvec *sxm, int xim, struct blasfeo_dvec *sx, int xi, + struct blasfeo_dvec *sxp, int xip, struct blasfeo_dvec *sz, int zi); + +void blasfeo_dveccl_mask(int m, + struct blasfeo_dvec *sxm, int xim, struct blasfeo_dvec *sx, int xi, + struct blasfeo_dvec *sxp, int xip, struct blasfeo_dvec *sz, int zi, + struct blasfeo_dvec *sm, int mi); + +void blasfeo_dvecze(int m, struct blasfeo_dvec *sm, int mi, struct blasfeo_dvec *sv, int vi, struct blasfeo_dvec *se, int ei); +void blasfeo_dvecnrm_inf(int m, struct blasfeo_dvec *sx, int xi, double *ptr_norm); +void blasfeo_dvecnrm_2(int m, struct blasfeo_dvec *sx, int xi, double *ptr_norm); +void blasfeo_dvecpe(int kmax, int *ipiv, struct blasfeo_dvec *sx, int xi); +void blasfeo_dvecpei(int kmax, int *ipiv, struct blasfeo_dvec *sx, int xi); + + + + + +/* +* Explicitly panel-major matrix format +*/ + +// returns the memory size (in bytes) needed for a dmat +size_t blasfeo_pm_memsize_dmat(int ps, int m, int n); +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_pm_create_dmat(int ps, int m, int n, struct blasfeo_pm_dmat *sA, void *memory); +// print +void blasfeo_pm_print_dmat(int m, int n, struct blasfeo_pm_dmat *sA, int ai, int aj); + + + +/* +* Explicitly panel-major matrix format +*/ + +// returns the memory size (in bytes) needed for a dmat +size_t blasfeo_cm_memsize_dmat(int m, int n); +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_cm_create_dmat(int m, int n, struct blasfeo_pm_dmat *sA, void *memory); + + + +// +// BLAS API helper functions +// + +#if ( defined(BLAS_API) & defined(MF_PANELMAJ) ) +// aux +void blasfeo_cm_dgetr(int m, int n, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj); +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_AUX_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ext_dep.h b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ext_dep.h new file mode 100644 index 0000000000..bee9e986f1 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ext_dep.h @@ -0,0 +1,145 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +/* + * auxiliary algebra operation external dependancies header + * + * include/blasfeo_d_aux_ext_dep.h + * + * - dynamic memory allocation + * - print + * + */ + +#ifndef BLASFEO_D_AUX_EXT_DEP_H_ +#define BLASFEO_D_AUX_EXT_DEP_H_ + + + +#include + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef EXT_DEP + +/* column-major matrices */ + +// dynamically allocate row*col doubles of memory and set accordingly a pointer to double; set allocated memory to zero +void d_zeros(double **pA, int row, int col); +// dynamically allocate row*col doubles of memory aligned to 64-byte boundaries and set accordingly a pointer to double; set allocated memory to zero +void d_zeros_align(double **pA, int row, int col); +// dynamically allocate size bytes of memory aligned to 64-byte boundaries and set accordingly a pointer to double; set allocated memory to zero +void d_zeros_align_bytes(double **pA, int size); +// free the memory allocated by d_zeros +void d_free(double *pA); +// free the memory allocated by d_zeros_align or d_zeros_align_bytes +void d_free_align(double *pA); +// print a column-major matrix +void d_print_mat(int m, int n, double *A, int lda); +// print the transposed of a column-major matrix +void d_print_tran_mat(int row, int col, double *A, int lda); +// print to file a column-major matrix +void d_print_to_file_mat(FILE *file, int row, int col, double *A, int lda); +// print to file a column-major matrix in exponential format +void d_print_to_file_exp_mat(FILE *file, int row, int col, double *A, int lda); +// print to string a column-major matrix +void d_print_to_string_mat(char **buf_out, int row, int col, double *A, int lda); +// print to file the transposed of a column-major matrix +void d_print_tran_to_file_mat(FILE *file, int row, int col, double *A, int lda); +// print to file the transposed of a column-major matrix in exponential format +void d_print_tran_to_file_exp_mat(FILE *file, int row, int col, double *A, int lda); +// print in exponential notation a column-major matrix +void d_print_exp_mat(int m, int n, double *A, int lda); +// print in exponential notation the transposed of a column-major matrix +void d_print_exp_tran_mat(int row, int col, double *A, int lda); + +/* strmat and strvec */ + +// create a strmat for a matrix of size m*n by dynamically allocating memory +void blasfeo_allocate_dmat(int m, int n, struct blasfeo_dmat *sA); +// create a strvec for a vector of size m by dynamically allocating memory +void blasfeo_allocate_dvec(int m, struct blasfeo_dvec *sa); +// free the memory allocated by blasfeo_allocate_dmat +void blasfeo_free_dmat(struct blasfeo_dmat *sA); +// free the memory allocated by blasfeo_allocate_dvec +void blasfeo_free_dvec(struct blasfeo_dvec *sa); +// print a strmat +void blasfeo_print_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +// print in exponential notation a strmat +void blasfeo_print_exp_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +// print to file a strmat +void blasfeo_print_to_file_dmat(FILE *file, int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +// print to file a strmat in exponential format +void blasfeo_print_to_file_exp_dmat(FILE *file, int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +// print to string a strmat +void blasfeo_print_to_string_dmat(char **buf_out, int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +// print the transposed of a strmat +void blasfeo_print_tran_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +// print a strvec +void blasfeo_print_dvec(int m, struct blasfeo_dvec *sa, int ai); +// print in exponential notation a strvec +void blasfeo_print_exp_dvec(int m, struct blasfeo_dvec *sa, int ai); +// print to file a strvec +void blasfeo_print_to_file_dvec(FILE *file, int m, struct blasfeo_dvec *sa, int ai); +// print to string a strvec +void blasfeo_print_to_string_dvec(char **buf_out, int m, struct blasfeo_dvec *sa, int ai); +// print the transposed of a strvec +void blasfeo_print_tran_dvec(int m, struct blasfeo_dvec *sa, int ai); +// print in exponential notation the transposed of a strvec +void blasfeo_print_exp_tran_dvec(int m, struct blasfeo_dvec *sa, int ai); +// print to file the transposed of a strvec +void blasfeo_print_to_file_tran_dvec(FILE *file, int m, struct blasfeo_dvec *sa, int ai); +// print to string the transposed of a strvec +void blasfeo_print_to_string_tran_dvec(char **buf_out, int m, struct blasfeo_dvec *sa, int ai); + +#endif // EXT_DEP + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_AUX_EXT_DEP_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ext_dep_ref.h b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ext_dep_ref.h new file mode 100644 index 0000000000..81b811f032 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ext_dep_ref.h @@ -0,0 +1,84 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +/* + * auxiliary algebra operation external dependancies header + * + * include/blasfeo_d_aux_ext_dep.h + * + * - dynamic memory allocation + * - print + * + */ + +#ifndef BLASFEO_D_AUX_EXT_DEP_REF_H_ +#define BLASFEO_D_AUX_EXT_DEP_REF_H_ + + +#include + +#include "blasfeo_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// expose reference BLASFEO for testing +// see blasfeo_d_aux_exp_dep.h for help + +void blasfeo_print_dmat_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj); +void blasfeo_allocate_dmat_ref(int m, int n, struct blasfeo_dmat_ref *sA); +void blasfeo_allocate_dvec_ref(int m, struct blasfeo_dvec_ref *sa); +void blasfeo_free_dmat_ref(struct blasfeo_dmat_ref *sA); +void blasfeo_free_dvec_ref(struct blasfeo_dvec_ref *sa); +void blasfeo_print_dmat_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj); +void blasfeo_print_exp_dmat_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj); +void blasfeo_print_to_file_dmat_ref(FILE *file, int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj); +void blasfeo_print_to_file_exp_dmat_ref(FILE *file, int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj); +void blasfeo_print_to_string_dmat_ref(char **buf_out, int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj); +void blasfeo_print_dvec(int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_exp_dvec(int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_to_file_dvec(FILE *file, int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_to_string_dvec(char **buf_out, int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_tran_dvec(int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_exp_tran_dvec(int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_to_file_tran_dvec(FILE *file, int m, struct blasfeo_dvec *sa, int ai); +void blasfeo_print_to_string_tran_dvec(char **buf_out, int m, struct blasfeo_dvec *sa, int ai); + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_AUX_EXT_DEP_REF_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_aux_old.h b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_old.h new file mode 100644 index 0000000000..3a1847a6a0 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_old.h @@ -0,0 +1,75 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +/* + * ----------- TOMOVE + * + * expecting column major matrices + * + */ + +#include "blasfeo_common.h" + + +void dtrcp_l_lib(int m, double alpha, int offsetA, double *A, int sda, int offsetB, double *B, int sdb); +void dgead_lib(int m, int n, double alpha, int offsetA, double *A, int sda, int offsetB, double *B, int sdb); +// TODO remove ??? +void ddiain_sqrt_lib(int kmax, double *x, int offset, double *pD, int sdd); +// TODO ddiaad1 +void ddiareg_lib(int kmax, double reg, int offset, double *pD, int sdd); + + +void dgetr_lib(int m, int n, double alpha, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +void dtrtr_l_lib(int m, double alpha, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +void dtrtr_u_lib(int m, double alpha, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +void ddiaex_lib(int kmax, double alpha, int offset, double *pD, int sdd, double *x); +void ddiaad_lib(int kmax, double alpha, double *x, int offset, double *pD, int sdd); +void ddiain_libsp(int kmax, int *idx, double alpha, double *x, double *pD, int sdd); +void ddiaex_libsp(int kmax, int *idx, double alpha, double *pD, int sdd, double *x); +void ddiaad_libsp(int kmax, int *idx, double alpha, double *x, double *pD, int sdd); +void ddiaadin_libsp(int kmax, int *idx, double alpha, double *x, double *y, double *pD, int sdd); +void drowin_lib(int kmax, double alpha, double *x, double *pD); +void drowex_lib(int kmax, double alpha, double *pD, double *x); +void drowad_lib(int kmax, double alpha, double *x, double *pD); +void drowin_libsp(int kmax, double alpha, int *idx, double *x, double *pD); +void drowad_libsp(int kmax, int *idx, double alpha, double *x, double *pD); +void drowadin_libsp(int kmax, int *idx, double alpha, double *x, double *y, double *pD); +void dcolin_lib(int kmax, double *x, int offset, double *pD, int sdd); +void dcolad_lib(int kmax, double alpha, double *x, int offset, double *pD, int sdd); +void dcolin_libsp(int kmax, int *idx, double *x, double *pD, int sdd); +void dcolad_libsp(int kmax, double alpha, int *idx, double *x, double *pD, int sdd); +void dcolsw_lib(int kmax, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +void dvecin_libsp(int kmax, int *idx, double *x, double *y); +void dvecad_libsp(int kmax, int *idx, double alpha, double *x, double *y); diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ref.h b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ref.h new file mode 100644 index 0000000000..1e007fa89e --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_ref.h @@ -0,0 +1,208 @@ + +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_AUX_REF_H_ +#define BLASFEO_D_AUX_REF_H_ + + + +#include + +#include "blasfeo_common.h" +#include "blasfeo_d_aux_old.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + +// --- memory calculations +// +// returns the memory size (in bytes) needed for a dmat +size_t blasfeo_ref_memsize_dmat(int m, int n); +// returns the memory size (in bytes) needed for the diagonal of a dmat +size_t blasfeo_ref_memsize_diag_dmat(int m, int n); +// returns the memory size (in bytes) needed for a dvec +size_t blasfeo_ref_memsize_dvec(int m); + +// --- creation +// +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_ref_create_dmat(int m, int n, struct blasfeo_dmat *sA, void *memory); +// create a strvec for a vector of size m by using memory passed by a pointer (pointer is not updated) +void blasfeo_ref_create_dvec(int m, struct blasfeo_dvec *sA, void *memory); + +// --- packing +// pack the column-major matrix A into the matrix struct B +void blasfeo_ref_pack_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// pack the lower-triangular column-major matrix A into the matrix struct B +void blasfeo_ref_pack_l_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// pack the upper-triangular column-major matrix A into the matrix struct B +void blasfeo_ref_pack_u_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// transpose and pack the column-major matrix A into the matrix struct B +void blasfeo_ref_pack_tran_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sB, int bi, int bj); +// pack the vector x into the vector structure y +void blasfeo_ref_pack_dvec(int m, double *x, int xi, struct blasfeo_dvec *sy, int yi); +// unpack the matrix structure A into the column-major matrix B +void blasfeo_ref_unpack_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, double *B, int ldb); +// transpose and unpack the matrix structure A into the column-major matrix B +void blasfeo_ref_unpack_tran_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, double *B, int ldb); +// pack the vector structure x into the vector y +void blasfeo_ref_unpack_dvec(int m, struct blasfeo_dvec *sx, int xi, double *y, int yi); + +// --- cast +// +void ref_d_cast_mat2strmat(double *A, struct blasfeo_dmat *sA); // TODO +void ref_d_cast_diag_mat2strmat(double *dA, struct blasfeo_dmat *sA); // TODO +void ref_d_cast_vec2vecmat(double *a, struct blasfeo_dvec *sx); // TODO + + +// ge +// --- insert/extract +// +// sA[ai, aj] <= a +void blasfeo_ref_dgein1(double a, struct blasfeo_dmat *sA, int ai, int aj); +// <= sA[ai, aj] +double blasfeo_ref_dgeex1(struct blasfeo_dmat *sA, int ai, int aj); + +// --- set +// A <= alpha +void blasfeo_ref_dgese(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj); + +// --- copy / scale +// B <= A +void blasfeo_ref_dgecp(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// A <= alpha*A +void blasfeo_ref_dgesc(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +// B <= alpha*A +void blasfeo_ref_dgecpsc(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// B <= A, A lower triangular +void blasfeo_ref_dtrcp_l(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +void blasfeo_ref_dtrcpsc_l(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +void blasfeo_ref_dtrsc_l(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj); + +// --- sum +// B <= B + alpha*A +void blasfeo_ref_dgead(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int yi, int cj); +// y <= y + alpha*x +void blasfeo_ref_dvecad(int m, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); + +// --- traspositions +// B <= A' +void blasfeo_ref_dgetr(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// B <= A', A lower triangular +void blasfeo_ref_dtrtr_l(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); +// B <= A', A upper triangular +void blasfeo_ref_dtrtr_u(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj); + +// dia +// diag(A) += alpha +void blasfeo_ref_ddiare(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +// diag(A) <= alpha*x +void blasfeo_ref_ddiain(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// diag(A)[idx] <= alpha*x +void blasfeo_ref_ddiain_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// x <= diag(A) +void blasfeo_ref_ddiaex(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +// x <= diag(A)[idx] +void blasfeo_ref_ddiaex_sp(int kmax, double alpha, int *idx, struct blasfeo_dmat *sD, int di, int dj, struct blasfeo_dvec *sx, int xi); +// diag(A) += alpha*x +void blasfeo_ref_ddiaad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// diag(A)[idx] += alpha*x +void blasfeo_ref_ddiaad_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// diag(A)[idx] = y + alpha*x +void blasfeo_ref_ddiaadin_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, int *idx, struct blasfeo_dmat *sD, int di, int dj); + +// row +void blasfeo_ref_drowin(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_ref_drowex(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +void blasfeo_ref_drowad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_ref_drowad_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_ref_drowsw(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +void blasfeo_ref_drowpe(int kmax, int *ipiv, struct blasfeo_dmat *sA); +void blasfeo_ref_drowpei(int kmax, int *ipiv, struct blasfeo_dmat *sA); + +// col +void blasfeo_ref_dcolex(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +void blasfeo_ref_dcolin(int kmax, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_ref_dcolad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_ref_dcolsc(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +void blasfeo_ref_dcolsw(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +void blasfeo_ref_dcolpe(int kmax, int *ipiv, struct blasfeo_dmat *sA); +void blasfeo_ref_dcolpei(int kmax, int *ipiv, struct blasfeo_dmat *sA); + +// vec +// a <= alpha +void blasfeo_ref_dvecse(int m, double alpha, struct blasfeo_dvec *sx, int xi); +// sx[xi] <= a +void blasfeo_ref_dvecin1(double a, struct blasfeo_dvec *sx, int xi); +// <= sx[xi] +double blasfeo_ref_dvecex1(struct blasfeo_dvec *sx, int xi); +// y <= x +void blasfeo_ref_dveccp(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); +// x <= alpha*x +void blasfeo_ref_dvecsc(int m, double alpha, struct blasfeo_dvec *sx, int xi); +// y <= alpha*x +void blasfeo_ref_dveccpsc(int m, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); +void blasfeo_ref_dvecad_sp(int m, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dvec *sz, int zi); +void blasfeo_ref_dvecin_sp(int m, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dvec *sz, int zi); +void blasfeo_ref_dvecex_sp(int m, double alpha, int *idx, struct blasfeo_dvec *sx, int x, struct blasfeo_dvec *sz, int zi); +// z += alpha * x[idx] +void blasfeo_ref_dvecexad_sp(int m, double alpha, int *idx, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); + +void blasfeo_ref_dveccl(int m, + struct blasfeo_dvec *sxm, int xim, struct blasfeo_dvec *sx, int xi, + struct blasfeo_dvec *sxp, int xip, struct blasfeo_dvec *sz, int zi); + +void blasfeo_ref_dveccl_mask(int m, + struct blasfeo_dvec *sxm, int xim, struct blasfeo_dvec *sx, int xi, + struct blasfeo_dvec *sxp, int xip, struct blasfeo_dvec *sz, int zi, + struct blasfeo_dvec *sm, int mi); + +void blasfeo_ref_dvecze(int m, struct blasfeo_dvec *sm, int mi, struct blasfeo_dvec *sv, int vi, struct blasfeo_dvec *se, int ei); +void blasfeo_ref_dvecnrm_inf(int m, struct blasfeo_dvec *sx, int xi, double *ptr_norm); +void blasfeo_ref_dvecpe(int kmax, int *ipiv, struct blasfeo_dvec *sx, int xi); +void blasfeo_ref_dvecpei(int kmax, int *ipiv, struct blasfeo_dvec *sx, int xi); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_AUX_REF_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_aux_test.h b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_test.h new file mode 100644 index 0000000000..1c61635f3f --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_aux_test.h @@ -0,0 +1,226 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +/* + * auxiliary algebra operations header + * + * include/blasfeo_aux_lib*.h + * + */ + +#ifndef BLASFEO_D_AUX_TEST_H_ +#define BLASFEO_D_AUX_TEST_H_ + +#include "blasfeo_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +// --- memory calculations +int test_blasfeo_memsize_dmat(int m, int n); +int test_blasfeo_memsize_diag_dmat(int m, int n); +int test_blasfeo_memsize_dvec(int m); + +// --- creation +void test_blasfeo_create_dmat(int m, int n, struct blasfeo_dmat *sA, void *memory); +void test_blasfeo_create_dvec(int m, struct blasfeo_dvec *sA, void *memory); + +// --- conversion +void test_blasfeo_pack_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sA, int ai, int aj); +void test_blasfeo_pack_dvec(int m, double *x, int xi, struct blasfeo_dvec *sa, int ai); +void test_blasfeo_pack_tran_dmat(int m, int n, double *A, int lda, struct blasfeo_dmat *sA, int ai, int aj); +void test_blasfeo_unpack_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, double *A, int lda); +void test_blasfeo_unpack_dvec(int m, struct blasfeo_dvec *sa, int ai, double *x, int xi); +void test_blasfeo_unpack_tran_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, double *A, int lda); + +// --- cast +void test_d_cast_mat2strmat(double *A, struct blasfeo_dmat *sA); +void test_d_cast_diag_mat2strmat(double *dA, struct blasfeo_dmat *sA); +void test_d_cast_vec2vecmat(double *a, struct blasfeo_dvec *sa); + +// ------ copy / scale + +// B <= A +void test_blasfeo_dgecp(int m, int n, + struct blasfeo_dmat *sA, int ai, int aj, + struct blasfeo_dmat *sB, int bi, int bj); + +// A <= alpha*A +void test_blasfeo_dgesc(int m, int n, + double alpha, + struct blasfeo_dmat *sA, int ai, int aj); + +// B <= alpha*A +void test_blasfeo_dgecpsc(int m, int n, + double alpha, + struct blasfeo_dmat *sA, int ai, int aj, + struct blasfeo_dmat *sB, int bi, int bj); + +// // --- insert/extract +// // +// // <= sA[ai, aj] +// void test_blasfeo_dgein1(double a, struct blasfeo_dmat *sA, int ai, int aj); +// // <= sA[ai, aj] +// double blasfeo_dgeex1(struct blasfeo_dmat *sA, int ai, int aj); +// // sx[xi] <= a +// void test_blasfeo_dvecin1(double a, struct blasfeo_dvec *sx, int xi); +// // <= sx[xi] +// double blasfeo_dvecex1(struct blasfeo_dvec *sx, int xi); +// // A <= alpha + +// // --- set +// void test_blasfeo_dgese(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +// // a <= alpha +// void test_blasfeo_dvecse(int m, double alpha, struct blasfeo_dvec *sx, int xi); +// // B <= A + + +// // --- vector +// // y <= x +// void test_blasfeo_dveccp(int m, struct blasfeo_dvec *sa, int ai, struct blasfeo_dvec *sc, int ci); +// // x <= alpha*x +// void test_blasfeo_dvecsc(int m, double alpha, struct blasfeo_dvec *sa, int ai); +// // TODO +// // x <= alpha*x +// void test_blasfeo_dveccpsc(int m, double alpha, struct blasfeo_dvec *sa, int ai, struct blasfeo_dvec *sc, int ci); + + +// // B <= A, A lower triangular +// void test_blasfeo_dtrcp_l(int m, +// struct blasfeo_dmat *sA, int ai, int aj, +// struct blasfeo_dmat *sB, int bi, int bj); + +// void test_blasfeo_dtrcpsc_l(int m, double alpha, +// struct blasfeo_dmat *sA, int ai, int aj, +// struct blasfeo_dmat *sB, int bi, int bj); + +// void test_blasfeo_dtrsc_l(int m, double alpha, +// struct blasfeo_dmat *sA, int ai, int aj); + + +// // B <= B + alpha*A +// void test_blasfeo_dgead(int m, int n, double alpha, +// struct blasfeo_dmat *sA, int ai, int aj, +// struct blasfeo_dmat *sC, int ci, int cj); + +// // y <= y + alpha*x +// void test_blasfeo_dvecad(int m, double alpha, +// struct blasfeo_dvec *sa, int ai, +// struct blasfeo_dvec *sc, int ci); + +// // --- traspositions +// void test_dgetr_lib(int m, int n, double alpha, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +// void test_blasfeo_dgetr(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +// void test_dtrtr_l_lib(int m, double alpha, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +// void test_blasfeo_dtrtr_l(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +// void test_dtrtr_u_lib(int m, double alpha, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +// void test_blasfeo_dtrtr_u(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +// void test_blasfeo_ddiare(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj); +// void test_blasfeo_ddiain(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// void test_ddiaex_lib(int kmax, double alpha, int offset, double *pD, int sdd, double *x); +// void test_ddiaad_lib(int kmax, double alpha, double *x, int offset, double *pD, int sdd); +// void test_ddiain_libsp(int kmax, int *idx, double alpha, double *x, double *pD, int sdd); +// void test_blasfeo_ddiain_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// void test_ddiaex_libsp(int kmax, int *idx, double alpha, double *pD, int sdd, double *x); +// void test_blasfeo_ddiaex(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +// void test_blasfeo_ddiaex_sp(int kmax, double alpha, int *idx, struct blasfeo_dmat *sD, int di, int dj, struct blasfeo_dvec *sx, int xi); +// void test_blasfeo_ddiaad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// void test_ddiaad_libsp(int kmax, int *idx, double alpha, double *x, double *pD, int sdd); +// void test_blasfeo_ddiaad_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// void test_ddiaadin_libsp(int kmax, int *idx, double alpha, double *x, double *y, double *pD, int sdd); +// void test_blasfeo_ddiaadin_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// void test_drowin_lib(int kmax, double alpha, double *x, double *pD); +// void test_blasfeo_drowin(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// void test_drowex_lib(int kmax, double alpha, double *pD, double *x); +// void test_blasfeo_drowex(int kmax, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +// void test_drowad_lib(int kmax, double alpha, double *x, double *pD); +// void test_blasfeo_drowad(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// void test_drowin_libsp(int kmax, double alpha, int *idx, double *x, double *pD); +// void test_drowad_libsp(int kmax, int *idx, double alpha, double *x, double *pD); +// void test_blasfeo_drowad_sp(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dmat *sD, int di, int dj); +// void test_drowadin_libsp(int kmax, int *idx, double alpha, double *x, double *y, double *pD); +// void test_drowsw_lib(int kmax, double *pA, double *pC); +// void test_blasfeo_drowsw(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +// void test_blasfeo_drowpe(int kmax, int *ipiv, struct blasfeo_dmat *sA); +// void test_blasfeo_dcolex(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi); +// void test_dcolin_lib(int kmax, double *x, int offset, double *pD, int sdd); +// void test_blasfeo_dcolin(int kmax, struct blasfeo_dvec *sx, int xi, struct blasfeo_dmat *sA, int ai, int aj); +// void test_dcolad_lib(int kmax, double alpha, double *x, int offset, double *pD, int sdd); +// void test_dcolin_libsp(int kmax, int *idx, double *x, double *pD, int sdd); +// void test_dcolad_libsp(int kmax, double alpha, int *idx, double *x, double *pD, int sdd); +// void test_dcolsw_lib(int kmax, int offsetA, double *pA, int sda, int offsetC, double *pC, int sdc); +// void test_blasfeo_dcolsw(int kmax, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sC, int ci, int cj); +// void test_blasfeo_dcolpe(int kmax, int *ipiv, struct blasfeo_dmat *sA); +// void test_dvecin_libsp(int kmax, int *idx, double *x, double *y); +// void test_dvecad_libsp(int kmax, int *idx, double alpha, double *x, double *y); +// void test_blasfeo_dvecad_sp(int m, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dvec *sz, int zi); +// void test_blasfeo_dvecin_sp(int m, double alpha, struct blasfeo_dvec *sx, int xi, int *idx, struct blasfeo_dvec *sz, int zi); +// void test_blasfeo_dvecex_sp(int m, double alpha, int *idx, struct blasfeo_dvec *sx, int x, struct blasfeo_dvec *sz, int zi); +// void test_blasfeo_dveccl(int m, struct blasfeo_dvec *sxm, int xim, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sxp, int xip, struct blasfeo_dvec *sz, int zi); +// void test_blasfeo_dveccl_mask(int m, struct blasfeo_dvec *sxm, int xim, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sxp, int xip, struct blasfeo_dvec *sz, int zi, struct blasfeo_dvec *sm, int mi); +// void test_blasfeo_dvecze(int m, struct blasfeo_dvec *sm, int mi, struct blasfeo_dvec *sv, int vi, struct blasfeo_dvec *se, int ei); +// void test_blasfeo_dvecnrm_inf(int m, struct blasfeo_dvec *sx, int xi, double *ptr_norm); +// void test_blasfeo_dvecpe(int kmax, int *ipiv, struct blasfeo_dvec *sx, int xi); +// void test_blasfeo_dvecpei(int kmax, int *ipiv, struct blasfeo_dvec *sx, int xi); + +// ext_dep + +void test_blasfeo_allocate_dmat(int m, int n, struct blasfeo_dmat *sA); +void test_blasfeo_allocate_dvec(int m, struct blasfeo_dvec *sa); + +void test_blasfeo_free_dmat(struct blasfeo_dmat *sA); +void test_blasfeo_free_dvec(struct blasfeo_dvec *sa); + +void test_blasfeo_print_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +void test_blasfeo_print_dvec(int m, struct blasfeo_dvec *sa, int ai); +void test_blasfeo_print_tran_dvec(int m, struct blasfeo_dvec *sa, int ai); + +void test_blasfeo_print_to_file_dmat(FILE *file, int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +void test_blasfeo_print_to_file_dvec(FILE *file, int m, struct blasfeo_dvec *sa, int ai); +void test_blasfeo_print_to_file_tran_dvec(FILE *file, int m, struct blasfeo_dvec *sa, int ai); + +void test_blasfeo_print_exp_dmat(int m, int n, struct blasfeo_dmat *sA, int ai, int aj); +void test_blasfeo_print_exp_dvec(int m, struct blasfeo_dvec *sa, int ai); +void test_blasfeo_print_exp_tran_dvec(int m, struct blasfeo_dvec *sa, int ai); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_AUX_TEST_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_blas.h b/third_party/acados/include/blasfeo/include/blasfeo_d_blas.h new file mode 100644 index 0000000000..ea8d006731 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_blas.h @@ -0,0 +1,46 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_BLAS_H_ +#define BLASFEO_D_BLAS_H_ + + + +#include "blasfeo_d_blasfeo_api.h" +#include "blasfeo_d_blas_api.h" + + + +#endif // BLASFEO_D_BLAS_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_blas_api.h b/third_party/acados/include/blasfeo/include/blasfeo_d_blas_api.h new file mode 100644 index 0000000000..2eab1e4094 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_blas_api.h @@ -0,0 +1,281 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef BLASFEO_D_BLAS_API_H_ +#define BLASFEO_D_BLAS_API_H_ + + + +#include "blasfeo_target.h" + + + +#ifdef BLAS_API +#ifdef CBLAS_API +#ifndef BLASFEO_CBLAS_ENUM +#define BLASFEO_CBLAS_ENUM +#ifdef FORTRAN_BLAS_API +#ifndef CBLAS_H +enum CBLAS_LAYOUT {CblasRowMajor=101, CblasColMajor=102}; +enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; +enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; +enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; +enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; +#define CBLAS_ORDER CBLAS_LAYOUT /* this for backward compatibility with CBLAS_ORDER */ +#endif // CBLAS_H +#else // FORTRAN_BLAS_API +enum BLASFEO_CBLAS_LAYOUT {BlasfeoCblasRowMajor=101, BlasfeoCblasColMajor=102}; +enum BLASFEO_CBLAS_TRANSPOSE {BlasfeoCblasNoTrans=111, BlasfeoCblasTrans=112, BlasfeoCblasConjTrans=113}; +enum BLASFEO_CBLAS_UPLO {BlasfeoCblasUpper=121, BlasfeoCblasLower=122}; +enum BLASFEO_CBLAS_DIAG {BlasfeoCblasNonUnit=131, BlasfeoCblasUnit=132}; +enum BLASFEO_CBLAS_SIDE {BlasfeoCblasLeft=141, BlasfeoCblasRight=142}; +#define BLASFEO_CBLAS_ORDER BLASFEO_CBLAS_LAYOUT /* this for backward compatibility with BLASFEO_CBLAS_ORDER */ +#endif // FORTRAN_BLAS_API +#endif // BLASFEO_CBLAS_ENUM +#endif // CBLAS_API +#endif // BLAS_API + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef BLAS_API + + + +#ifdef FORTRAN_BLAS_API + + + +// BLAS 1 +// +void daxpy_(int *n, double *alpha, double *x, int *incx, double *y, int *incy); +// +void dcopy_(int *n, double *x, int *incx, double *y, int *incy); +// +double ddot_(int *n, double *x, int *incx, double *y, int *incy); + +// BLAS 2 +// +void dgemv_(char *tran, int *m, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); +// +void dsymv_(char *uplo, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); +// +void dger_(int *m, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *A, int *lda); + +// BLAS 3 +// +void dgemm_(char *ta, char *tb, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc); +// +void dsyrk_(char *uplo, char *ta, int *m, int *k, double *alpha, double *A, int *lda, double *beta, double *C, int *ldc); +// +void dtrmm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *A, int *lda, double *B, int *ldb); +// +void dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *A, int *lda, double *B, int *ldb); +// +void dsyr2k_(char *uplo, char *ta, int *m, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc); + + + +// LAPACK +// +void dgesv_(int *m, int *n, double *A, int *lda, int *ipiv, double *B, int *ldb, int *info); +// +void dgetrf_(int *m, int *n, double *A, int *lda, int *ipiv, int *info); +// +void dgetrf_np_(int *m, int *n, double *A, int *lda, int *info); +// +void dgetrs_(char *trans, int *m, int *n, double *A, int *lda, int *ipiv, double *B, int *ldb, int *info); +// +void dlaswp_(int *n, double *A, int *lda, int *k1, int *k2, int *ipiv, int *incx); +// +void dposv_(char *uplo, int *m, int *n, double *A, int *lda, double *B, int *ldb, int *info); +// +void dpotrf_(char *uplo, int *m, double *A, int *lda, int *info); +// +void dpotrs_(char *uplo, int *m, int *n, double *A, int *lda, double *B, int *ldb, int *info); +// +void dtrtrs_(char *uplo, char *trans, char *diag, int *m, int *n, double *A, int *lda, double *B, int *ldb, int *info); + + + +// aux +void dgetr_(int *m, int *n, double *A, int *lda, double *B, int *ldb); + + + +#ifdef CBLAS_API + + + +// CBLAS 1 +// +void cblas_daxpy(const int N, const double alpha, const double *X, const int incX, double *Y, const int incY); +// +void cblas_dswap(const int N, double *X, const int incX, double *Y, const int incY); +// +void cblas_dcopy(const int N, const double *X, const int incX, double *Y, const int incY); + +// CBLAS 2 +// +void cblas_dgemv(const enum CBLAS_LAYOUT layout, const enum CBLAS_TRANSPOSE TransA, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *X, const int incX, const double beta, double *Y, const int incY); + +// CBLAS 3 +// +void cblas_dgemm(const enum CBLAS_LAYOUT layout, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc); +// +void cblas_dsyrk(const enum CBLAS_LAYOUT layout, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE Trans, const int N, const int K, const double alpha, const double *A, const int lda, const double beta, double *C, const int ldc); +// +void cblas_dtrmm(const enum CBLAS_LAYOUT layout, const enum CBLAS_SIDE Side, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int M, const int N, const double alpha, const double *A, const int lda, double *B, const int ldb); +// +void cblas_dtrsm(const enum CBLAS_LAYOUT layout, const enum CBLAS_SIDE Side, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int M, const int N, const double alpha, const double *A, const int lda, double *B, const int ldb); + + + +#endif // CBLAS_API + + + +#else // BLASFEO_API + + + +// BLAS 1 +// +void blasfeo_blas_daxpy(int *n, double *alpha, double *x, int *incx, double *y, int *incy); +// +double blasfeo_blas_ddot(int *n, double *x, int *incx, double *y, int *incy); +// +void blasfeo_blas_dcopy(int *n, double *x, int *incx, double *y, int *incy); + +// BLAS 2 +// +void blasfeo_blas_dgemv(char *trans, int *m, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); +// +void blasfeo_blas_dsymv(char *uplo, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); +// +void blasfeo_blas_dger(int *m, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *A, int *lda); + +// BLAS 3 +// +void blasfeo_blas_dgemm(char *ta, char *tb, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc); +// +void blasfeo_blas_dsyrk(char *uplo, char *ta, int *m, int *k, double *alpha, double *A, int *lda, double *beta, double *C, int *ldc); +// +void blasfeo_blas_dtrmm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *A, int *lda, double *B, int *ldb); +// +void blasfeo_blas_dtrsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, double *alpha, double *A, int *lda, double *B, int *ldb); +// +void blasfeo_blas_dsyr2k(char *uplo, char *ta, int *m, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc); + + + +// LAPACK +// +void blasfeo_lapack_dgesv(int *m, int *n, double *A, int *lda, int *ipiv, double *B, int *ldb, int *info); +// +void blasfeo_lapack_dgetrf(int *m, int *n, double *A, int *lda, int *ipiv, int *info); +// +void blasfeo_lapack_dgetrf_np(int *m, int *n, double *A, int *lda, int *info); +// +void blasfeo_lapack_dgetrs(char *trans, int *m, int *n, double *A, int *lda, int *ipiv, double *B, int *ldb, int *info); +// +void blasfeo_lapack_dlaswp(int *n, double *A, int *lda, int *k1, int *k2, int *ipiv, int *incx); +// +void blasfeo_lapack_dposv(char *uplo, int *m, int *n, double *A, int *lda, double *B, int *ldb, int *info); +// +void blasfeo_lapack_dpotrf(char *uplo, int *m, double *A, int *lda, int *info); +// +void blasfeo_lapack_dpotrs(char *uplo, int *m, int *n, double *A, int *lda, double *B, int *ldb, int *info); +// +void blasfeo_lapack_dtrtrs(char *uplo, char *trans, char *diag, int *m, int *n, double *A, int *lda, double *B, int *ldb, int *info); + + + +// aux +void blasfeo_blas_dgetr(int *m, int *n, double *A, int *lda, double *B, int *ldb); + + + +#ifdef CBLAS_API + + + +// CBLAS 1 +// +void blasfeo_cblas_daxpy(const int N, const double alpha, const double *X, const int incX, double *Y, const int incY); +// +void blasfeo_cblas_dswap(const int N, double *X, const int incX, double *Y, const int incY); +// +void blasfeo_cblas_dcopy(const int N, const double *X, const int incX, double *Y, const int incY); + +// CBLAS 2 +// +void blasfeo_cblas_dgemv(const enum BLASFEO_CBLAS_LAYOUT layout, const enum BLASFEO_CBLAS_TRANSPOSE TransA, const int M, const int N, const double alpha, const double *A, const int lda, const double *X, const int incX, const double beta, double *Y, const int incY); + +// CBLAS 3 +// +void blasfeo_cblas_dgemm(const enum BLASFEO_CBLAS_LAYOUT layout, const enum BLASFEO_CBLAS_TRANSPOSE TransA, const enum BLASFEO_CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc); +// +void blasfeo_cblas_dsyrk(const enum BLASFEO_CBLAS_LAYOUT layout, const enum BLASFEO_CBLAS_UPLO Uplo, const enum BLASFEO_CBLAS_TRANSPOSE Trans, const int N, const int K, const double alpha, const double *A, const int lda, const double beta, double *C, const int ldc); +// +void blasfeo_cblas_dtrmm(const enum BLASFEO_CBLAS_LAYOUT layout, const enum BLASFEO_CBLAS_SIDE Side, const enum BLASFEO_CBLAS_UPLO Uplo, const enum BLASFEO_CBLAS_TRANSPOSE TransA, const enum BLASFEO_CBLAS_DIAG Diag, const int M, const int N, const double alpha, const double *A, const int lda, double *B, const int ldb); +// +void blasfeo_cblas_dtrsm(const enum BLASFEO_CBLAS_LAYOUT layout, const enum BLASFEO_CBLAS_SIDE Side, const enum BLASFEO_CBLAS_UPLO Uplo, const enum BLASFEO_CBLAS_TRANSPOSE TransA, const enum BLASFEO_CBLAS_DIAG Diag, const int M, const int N, const double alpha, const double *A, const int lda, double *B, const int ldb); + + + +#endif // CBLAS_API + + + +#endif // BLASFEO_API + + + +#endif // BLAS_API + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_BLAS_API_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_api.h b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_api.h new file mode 100644 index 0000000000..88bb3fce22 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_api.h @@ -0,0 +1,364 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_BLASFEO_API_H_ +#define BLASFEO_D_BLASFEO_API_H_ + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +// level 1 BLAS +// + +// z = y + alpha*x +// z[zi:zi+n] = alpha*x[xi:xi+n] + y[yi:yi+n] +// NB: Different arguments semantic compare to equivalent standard BLAS routine +void blasfeo_daxpy(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z = beta*y + alpha*x +void blasfeo_daxpby(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z = x .* y +void blasfeo_dvecmul(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z += x .* y +void blasfeo_dvecmulacc(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z = x .* y, return sum(z) = x^T * y +double blasfeo_dvecmuldot(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// return x^T * y +double blasfeo_ddot(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); +// construct givens plane rotation +void blasfeo_drotg(double a, double b, double *c, double *s); +// apply plane rotation [a b] [c -s; s; c] to the aj0 and aj1 columns of A at row index ai +void blasfeo_dcolrot(int m, struct blasfeo_dmat *sA, int ai, int aj0, int aj1, double c, double s); +// apply plane rotation [c s; -s c] [a; b] to the ai0 and ai1 rows of A at column index aj +void blasfeo_drowrot(int m, struct blasfeo_dmat *sA, int ai0, int ai1, int aj, double c, double s); + + + +// +// level 2 BLAS +// + +// dense + +// z <= beta * y + alpha * A * x +void blasfeo_dgemv_n(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z <= beta * y + alpha * A^T * x +void blasfeo_dgemv_t(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A ) * x, A (m)x(n) +void blasfeo_dtrsv_lnn_mn(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A^T ) * x, A (m)x(n) +void blasfeo_dtrsv_ltn_mn(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, not_unit +void blasfeo_dtrsv_lnn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, unit +void blasfeo_dtrsv_lnu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A^T ) * x, A (m)x(m) lower, transposed, not_unit +void blasfeo_dtrsv_ltn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A^T ) * x, A (m)x(m) lower, transposed, unit +void blasfeo_dtrsv_ltu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A^T ) * x, A (m)x(m) upper, not_transposed, not_unit +void blasfeo_dtrsv_unn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A^T ) * x, A (m)x(m) upper, transposed, not_unit +void blasfeo_dtrsv_utn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A * x ; A lower triangular +void blasfeo_dtrmv_lnn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A * x ; A lower triangular, unit diagonal +void blasfeo_dtrmv_lnu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A^T * x ; A lower triangular +void blasfeo_dtrmv_ltn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A^T * x ; A lower triangular, unit diagonal +void blasfeo_dtrmv_ltu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= beta * y + alpha * A * x ; A upper triangular +void blasfeo_dtrmv_unn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A^T * x ; A upper triangular +void blasfeo_dtrmv_utn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z_n <= beta_n * y_n + alpha_n * A * x_n +// z_t <= beta_t * y_t + alpha_t * A^T * x_t +void blasfeo_dgemv_nt(int m, int n, double alpha_n, double alpha_t, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx_n, int xi_n, struct blasfeo_dvec *sx_t, int xi_t, double beta_n, double beta_t, struct blasfeo_dvec *sy_n, int yi_n, struct blasfeo_dvec *sy_t, int yi_t, struct blasfeo_dvec *sz_n, int zi_n, struct blasfeo_dvec *sz_t, int zi_t); +// z <= beta * y + alpha * A * x, where A is symmetric and only the lower triangular patr of A is accessed +void blasfeo_dsymv_l(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +void blasfeo_dsymv_l_mn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z <= beta * y + alpha * A * x, where A is symmetric and only the upper triangular patr of A is accessed +void blasfeo_dsymv_u(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// D = C + alpha * x * y^T +void blasfeo_dger(int m, int n, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); + +// diagonal + +// z <= beta * y + alpha * A * x, A diagonal +void blasfeo_dgemv_d(int m, double alpha, struct blasfeo_dvec *sA, int ai, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); + + + +// +// level 3 BLAS +// + +// dense + +// D <= beta * C + alpha * A * B +void blasfeo_dgemm_nn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T +void blasfeo_dgemm_nt(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B +void blasfeo_dgemm_tn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B^T +void blasfeo_dgemm_tt(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D lower triangular +void blasfeo_dsyrk_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_dsyrk_ln_mn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#if ( defined(LA_HIGH_PERFORMANCE) & defined(MF_COLMAJ) ) +void blasfeo_dsyrk3_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#endif +// D <= beta * C + alpha * A^T * B ; C, D lower triangular +void blasfeo_dsyrk_lt(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#if ( defined(LA_HIGH_PERFORMANCE) & defined(MF_COLMAJ) ) +void blasfeo_dsyrk3_lt(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#endif +// D <= beta * C + alpha * A * B^T ; C, D upper triangular +void blasfeo_dsyrk_un(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#if ( defined(LA_HIGH_PERFORMANCE) & defined(MF_COLMAJ) ) +void blasfeo_dsyrk3_un(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#endif +// D <= beta * C + alpha * A^T * B ; C, D upper triangular +void blasfeo_dsyrk_ut(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#if ( defined(LA_HIGH_PERFORMANCE) & defined(MF_COLMAJ) ) +void blasfeo_dsyrk3_ut(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +#endif +// D <= alpha * A * B ; A lower triangular +void blasfeo_dtrmm_llnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A lower triangular +void blasfeo_dtrmm_llnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A lower triangular +void blasfeo_dtrmm_lltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A lower triangular +void blasfeo_dtrmm_lltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A upper triangular +void blasfeo_dtrmm_lunn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A upper triangular +void blasfeo_dtrmm_lunu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A upper triangular +void blasfeo_dtrmm_lutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A upper triangular +void blasfeo_dtrmm_lutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A lower triangular +void blasfeo_dtrmm_rlnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A lower triangular +void blasfeo_dtrmm_rlnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A lower triangular +void blasfeo_dtrmm_rltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A lower triangular +void blasfeo_dtrmm_rltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A upper triangular +void blasfeo_dtrmm_runn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A upper triangular +void blasfeo_dtrmm_runu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A upper triangular +void blasfeo_dtrmm_rutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A upper triangular +void blasfeo_dtrmm_rutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular employint explicit inverse of diagonal +// D <= alpha * A^{-1} * B , with A lower triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_llnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular with unit diagonal +void blasfeo_dtrsm_llnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_lltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular with unit diagonal +void blasfeo_dtrsm_lltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_lunn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular with unit diagonal +void blasfeo_dtrsm_lunu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_lutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular with unit diagonal +void blasfeo_dtrsm_lutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_rlnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular with unit diagonal +void blasfeo_dtrsm_rlnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_rltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular with unit diagonal +void blasfeo_dtrsm_rltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_runn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular with unit diagonal +void blasfeo_dtrsm_runu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_dtrsm_rutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular with unit diagonal +void blasfeo_dtrsm_rutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T; C, D lower triangular +void blasfeo_dsyr2k_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A; C, D lower triangular +void blasfeo_dsyr2k_lt(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T; C, D upper triangular +void blasfeo_dsyr2k_un(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A; C, D upper triangular +void blasfeo_dsyr2k_ut(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); + +// diagonal + +// D <= alpha * A * B + beta * C, with A diagonal (stored as strvec) +void dgemm_diag_left_lib(int m, int n, double alpha, double *dA, double *pB, int sdb, double beta, double *pC, int sdc, double *pD, int sdd); +void blasfeo_dgemm_dn(int m, int n, double alpha, struct blasfeo_dvec *sA, int ai, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B + beta * C, with B diagonal (stored as strvec) +void blasfeo_dgemm_nd(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sB, int bi, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); + + + +// +// LAPACK +// + +// D <= chol( C ) ; C, D lower triangular +void blasfeo_dpotrf_l(int m, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_dpotrf_l_mn(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= chol( C ) ; C, D upper triangular +void blasfeo_dpotrf_u(int m, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= chol( C + A * B' ) ; C, D lower triangular +// D <= chol( C + A * B^T ) ; C, D lower triangular +void blasfeo_dsyrk_dpotrf_ln(int m, int k, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_dsyrk_dpotrf_ln_mn(int m, int n, int k, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= lu( C ) ; no pivoting +void blasfeo_dgetrf_np(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= lu( C ) ; row pivoting +void blasfeo_dgetrf_rp(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, int *ipiv); +// D <= qr( C ) +int blasfeo_dgeqrf_worksize(int m, int n); // in bytes +void blasfeo_dgeqrf(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +// D <= Q factor, where C is the output of the LQ factorization +int blasfeo_dorglq_worksize(int m, int n, int k); // in bytes +void blasfeo_dorglq(int m, int n, int k, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +// D <= lq( C ) +void blasfeo_dgelqf(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +int blasfeo_dgelqf_worksize(int m, int n); // in bytes +// D <= lq( C ), positive diagonal elements +void blasfeo_dgelqf_pd(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +// [L, A] <= lq( [L, A] ), positive diagonal elements, array of matrices, with +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_dgelqf_pd_la(int m, int n1, struct blasfeo_dmat *sL, int li, int lj, struct blasfeo_dmat *sA, int ai, int aj, void *work); +// [L, L, A] <= lq( [L, L, A] ), positive diagonal elements, array of matrices, with: +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_dgelqf_pd_lla(int m, int n1, struct blasfeo_dmat *sL0, int l0i, int l0j, struct blasfeo_dmat *sL1, int l1i, int l1j, struct blasfeo_dmat *sA, int ai, int aj, void *work); + + + +// +// BLAS API helper functions +// + +#if ( defined(BLAS_API) & defined(MF_PANELMAJ) ) +// BLAS 3 +void blasfeo_cm_dgemm_nn(int m, int n, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dgemm_nt(int m, int n, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dgemm_tn(int m, int n, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dgemm_tt(int m, int n, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk_ln(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk_lt(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk_un(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk_ut(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk3_ln(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk3_lt(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk3_un(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyrk3_ut(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_llnn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_llnu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_lltn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_lltu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_lunn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_lunu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_lutn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_lutu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_rlnn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_rlnu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_rltn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_rltu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_runn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_runu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_rutn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrsm_rutu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_llnn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_llnu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_lltn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_lltu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_lunn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_lunu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_lutn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_lutu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_rlnn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_rlnu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_rltn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_rltu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_runn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_runu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_rutn(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dtrmm_rutu(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyr2k_ln(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyr2k_lt(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyr2k_un(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dsyr2k_ut(int m, int k, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dmat *sB, int bi, int bj, double beta, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +// BLAS 2 +void blasfeo_cm_dgemv_n(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dvec *sx, int xi, double beta, struct blasfeo_cm_dvec *sy, int yi, struct blasfeo_cm_dvec *sz, int zi); +void blasfeo_cm_dgemv_t(int m, int n, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dvec *sx, int xi, double beta, struct blasfeo_cm_dvec *sy, int yi, struct blasfeo_cm_dvec *sz, int zi); +void blasfeo_cm_dsymv_l(int m, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dvec *sx, int xi, double beta, struct blasfeo_cm_dvec *sy, int yi, struct blasfeo_cm_dvec *sz, int zi); +void blasfeo_cm_dsymv_u(int m, double alpha, struct blasfeo_cm_dmat *sA, int ai, int aj, struct blasfeo_cm_dvec *sx, int xi, double beta, struct blasfeo_cm_dvec *sy, int yi, struct blasfeo_cm_dvec *sz, int zi); +void blasfeo_cm_dger(int m, int n, double alpha, struct blasfeo_cm_dvec *sx, int xi, struct blasfeo_cm_dvec *sy, int yi, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +// LAPACK +void blasfeo_cm_dpotrf_l(int m, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dpotrf_u(int m, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj); +void blasfeo_cm_dgetrf_rp(int m, int n, struct blasfeo_cm_dmat *sC, int ci, int cj, struct blasfeo_cm_dmat *sD, int di, int dj, int *ipiv); +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_BLASFEO_API_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_api_ref.h b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_api_ref.h new file mode 100644 index 0000000000..141a1f0f06 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_api_ref.h @@ -0,0 +1,147 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_BLASFEO_API_REF_H_ +#define BLASFEO_D_BLASFEO_API_REF_H_ + +#include "blasfeo_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +// expose reference BLASFEO for testing + +// --- level 1 + +void blasfeo_daxpy_ref(int kmax, double alpha, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_daxpby_ref(int kmax, double alpha, struct blasfeo_dvec_ref *sx, int xi, double beta, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dvecmul_ref(int m, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dvecmulacc_ref(int m, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +double blasfeo_dvecmuldot_ref(int m, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +double blasfeo_ddot_ref(int m, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sy, int yi); +void blasfeo_drotg_ref(double a, double b, double *c, double *s); +void blasfeo_dcolrot_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj0, int aj1, double c, double s); +void blasfeo_drowrot_ref(int m, struct blasfeo_dmat_ref *sA, int ai0, int ai1, int aj, double c, double s); + + +// --- level 2 + +// dense +void blasfeo_dgemv_n_ref(int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, double beta, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dgemv_t_ref(int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, double beta, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_lnn_mn_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_ltn_mn_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_lnn_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_lnu_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_ltn_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_ltu_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_unn_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrsv_utn_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrmv_unn_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrmv_utn_ref(int m, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrmv_lnn_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrmv_ltn_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrmv_lnu_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dtrmv_ltu_ref(int m, int n, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, struct blasfeo_dvec_ref *sz, int zi); +void blasfeo_dgemv_nt_ref(int m, int n, double alpha_n, double alpha_t, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx_n, int xi_n, struct blasfeo_dvec_ref *sx_t, int xi_t, double beta_n, double beta_t, struct blasfeo_dvec_ref *sy_n, int yi_n, struct blasfeo_dvec_ref *sy_t, int yi_t, struct blasfeo_dvec_ref *sz_n, int zi_n, struct blasfeo_dvec_ref *sz_t, int zi_t); +void blasfeo_dsymv_l_ref(int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sx, int xi, double beta, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); + +// diagonal +void blasfeo_dgemv_d_ref(int m, double alpha, struct blasfeo_dvec_ref *sA, int ai, struct blasfeo_dvec_ref *sx, int xi, double beta, struct blasfeo_dvec_ref *sy, int yi, struct blasfeo_dvec_ref *sz, int zi); + + +// --- level 3 + +// dense +void blasfeo_dgemm_nn_ref( int m, int n, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgemm_nt_ref( int m, int n, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgemm_tn_ref(int m, int n, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgemm_tt_ref(int m, int n, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); + +void blasfeo_dsyrk_ln_mn_ref( int m, int n, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dsyrk_ln_ref( int m, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dsyrk_lt_ref( int m, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dsyrk_un_ref( int m, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dsyrk_ut_ref( int m, int k, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); + +void blasfeo_dtrmm_rutn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrmm_rlnn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); + +void blasfeo_dtrsm_lunu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_lunn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_lutu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_lutn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_llnu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_llnn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_lltu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_lltn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_runu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_runn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_rutu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_rutn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_rlnu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_rlnn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_rltu_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dtrsm_rltn_ref( int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sD, int di, int dj); + +// diagonal +void dgemm_diag_left_lib_ref(int m, int n, double alpha, double *dA, double *pB, int sdb, double beta, double *pC, int sdc, double *pD, int sdd); +void blasfeo_dgemm_dn_ref(int m, int n, double alpha, struct blasfeo_dvec_ref *sA, int ai, struct blasfeo_dmat_ref *sB, int bi, int bj, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgemm_nd_ref(int m, int n, double alpha, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dvec_ref *sB, int bi, double beta, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); + +// --- lapack + +void blasfeo_dgetrf_nopivot_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgetrf_rowpivot_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj, int *ipiv); +void blasfeo_dpotrf_l_ref(int m, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dpotrf_l_mn_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dsyrk_dpotrf_ln_ref(int m, int k, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dsyrk_dpotrf_ln_mn_ref(int m, int n, int k, struct blasfeo_dmat_ref *sA, int ai, int aj, struct blasfeo_dmat_ref *sB, int bi, int bj, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgetrf_nopivot_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj); +void blasfeo_dgetrf_rowpivot_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj, int *ipiv); +void blasfeo_dgeqrf_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj, void *work); +void blasfeo_dgelqf_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj, void *work); +void blasfeo_dgelqf_pd_ref(int m, int n, struct blasfeo_dmat_ref *sC, int ci, int cj, struct blasfeo_dmat_ref *sD, int di, int dj, void *work); +void blasfeo_dgelqf_pd_la_ref(int m, int n1, struct blasfeo_dmat_ref *sL, int li, int lj, struct blasfeo_dmat_ref *sA, int ai, int aj, void *work); +void blasfeo_dgelqf_pd_lla_ref(int m, int n1, struct blasfeo_dmat_ref *sL0, int l0i, int l0j, struct blasfeo_dmat_ref *sL1, int l1i, int l1j, struct blasfeo_dmat_ref *sA, int ai, int aj, void *work); + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_BLASFEO_API_REF_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_hp_api.h b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_hp_api.h new file mode 100644 index 0000000000..405733f13e --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_hp_api.h @@ -0,0 +1,84 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_BLASFEO_HP_API_H_ +#define BLASFEO_D_BLASFEO_HP_API_H_ + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +// level 3 BLAS +// + +// dense + + +// D <= beta * C + alpha * A^T * B +void blasfeo_hp_dgemm_tn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T; C, D lower triangular +void blasfeo_hp_dsyrk_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * A^T ; C, D lower triangular +void blasfeo_hp_dsyrk3_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular +void blasfeo_hp_dtrsm_rltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); + + +// +// level 2 BLAS +// + +// dense + +// z <= beta * y + alpha * A * x +void blasfeo_hp_dgemv_n(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_BLASFEO_HP_API_H_ + diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_ref_api.h b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_ref_api.h new file mode 100644 index 0000000000..1a8b22c67e --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_blasfeo_ref_api.h @@ -0,0 +1,283 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_BLASFEO_REF_API_H_ +#define BLASFEO_D_BLASFEO_REF_API_H_ + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +// level 1 BLAS +// + +// z = y + alpha*x +// z[zi:zi+n] = alpha*x[xi:xi+n] + y[yi:yi+n] +// NB: Different arguments semantic compare to equivalent standard BLAS routine +void blasfeo_ref_daxpy(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z = beta*y + alpha*x +void blasfeo_ref_daxpby(int kmax, double alpha, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z = x .* y +void blasfeo_ref_dvecmul(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z += x .* y +void blasfeo_ref_dvecmulacc(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z = x .* y, return sum(z) = x^T * y +double blasfeo_ref_dvecmuldot(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// return x^T * y +double blasfeo_ref_ddot(int m, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi); +// construct givens plane rotation +void blasfeo_ref_drotg(double a, double b, double *c, double *s); +// apply plane rotation [a b] [c -s; s; c] to the aj0 and aj1 columns of A at row index ai +void blasfeo_ref_dcolrot(int m, struct blasfeo_dmat *sA, int ai, int aj0, int aj1, double c, double s); +// apply plane rotation [c s; -s c] [a; b] to the ai0 and ai1 rows of A at column index aj +void blasfeo_ref_drowrot(int m, struct blasfeo_dmat *sA, int ai0, int ai1, int aj, double c, double s); + + + +// +// level 2 BLAS +// + +// dense + +// z <= beta * y + alpha * A * x +void blasfeo_ref_dgemv_n(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z <= beta * y + alpha * A' * x +void blasfeo_ref_dgemv_t(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A ) * x, A (m)x(n) +void blasfeo_ref_dtrsv_lnn_mn(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(n) +void blasfeo_ref_dtrsv_ltn_mn(int m, int n, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, not_unit +void blasfeo_ref_dtrsv_lnn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, unit +void blasfeo_ref_dtrsv_lnu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) lower, transposed, not_unit +void blasfeo_ref_dtrsv_ltn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) lower, transposed, unit +void blasfeo_ref_dtrsv_ltu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) upper, not_transposed, not_unit +void blasfeo_ref_dtrsv_unn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) upper, transposed, not_unit +void blasfeo_ref_dtrsv_utn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A * x ; A lower triangular +void blasfeo_ref_dtrmv_lnn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A * x ; A lower triangular, unit diagonal +void blasfeo_ref_dtrmv_lnu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A' * x ; A lower triangular +void blasfeo_ref_dtrmv_ltn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A' * x ; A lower triangular, unit diagonal +void blasfeo_ref_dtrmv_ltu(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= beta * y + alpha * A * x ; A upper triangular +void blasfeo_ref_dtrmv_unn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z <= A' * x ; A upper triangular +void blasfeo_ref_dtrmv_utn(int m, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sz, int zi); +// z_n <= beta_n * y_n + alpha_n * A * x_n +// z_t <= beta_t * y_t + alpha_t * A' * x_t +void blasfeo_ref_dgemv_nt(int m, int n, double alpha_n, double alpha_t, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx_n, int xi_n, struct blasfeo_dvec *sx_t, int xi_t, double beta_n, double beta_t, struct blasfeo_dvec *sy_n, int yi_n, struct blasfeo_dvec *sy_t, int yi_t, struct blasfeo_dvec *sz_n, int zi_n, struct blasfeo_dvec *sz_t, int zi_t); +// z <= beta * y + alpha * A * x, where A is symmetric and only the lower triangular patr of A is accessed +void blasfeo_ref_dsymv_l(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +void blasfeo_ref_dsymv_l_mn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// z <= beta * y + alpha * A * x, where A is symmetric and only the upper triangular patr of A is accessed +void blasfeo_ref_dsymv_u(int m, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); +// D = C + alpha * x * y^T +void blasfeo_ref_dger(int m, int n, double alpha, struct blasfeo_dvec *sx, int xi, struct blasfeo_dvec *sy, int yi, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); + +// diagonal + +// z <= beta * y + alpha * A * x, A diagonal +void blasfeo_ref_dgemv_d(int m, double alpha, struct blasfeo_dvec *sA, int ai, struct blasfeo_dvec *sx, int xi, double beta, struct blasfeo_dvec *sy, int yi, struct blasfeo_dvec *sz, int zi); + + + +// +// level 3 BLAS +// + +// dense + +// D <= beta * C + alpha * A * B +void blasfeo_ref_dgemm_nn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T +void blasfeo_ref_dgemm_nt(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B +void blasfeo_ref_dgemm_tn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B^T +void blasfeo_ref_dgemm_tt(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D lower triangular +void blasfeo_ref_dsyrk_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_ref_dsyrk_ln_mn(int m, int n, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B ; C, D lower triangular +void blasfeo_ref_dsyrk_lt(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D upper triangular +void blasfeo_ref_dsyrk_un(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B ; C, D upper triangular +void blasfeo_ref_dsyrk_ut(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A lower triangular +void blasfeo_ref_dtrmm_llnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A lower triangular +void blasfeo_ref_dtrmm_llnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A lower triangular +void blasfeo_ref_dtrmm_lltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A lower triangular +void blasfeo_ref_dtrmm_lltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A upper triangular +void blasfeo_ref_dtrmm_lunn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B ; A upper triangular +void blasfeo_ref_dtrmm_lunu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A upper triangular +void blasfeo_ref_dtrmm_lutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^T * B ; A upper triangular +void blasfeo_ref_dtrmm_lutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A lower triangular +void blasfeo_ref_dtrmm_rlnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A lower triangular +void blasfeo_ref_dtrmm_rlnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A lower triangular +void blasfeo_ref_dtrmm_rltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A lower triangular +void blasfeo_ref_dtrmm_rltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A upper triangular +void blasfeo_ref_dtrmm_runn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A ; A upper triangular +void blasfeo_ref_dtrmm_runu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A upper triangular +void blasfeo_ref_dtrmm_rutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^T ; A upper triangular +void blasfeo_ref_dtrmm_rutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular employint explicit inverse of diagonal +void blasfeo_ref_dtrsm_llnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular with unit diagonal +void blasfeo_ref_dtrsm_llnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular employint explicit inverse of diagonal +void blasfeo_ref_dtrsm_lltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular with unit diagonal +void blasfeo_ref_dtrsm_lltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_dtrsm_lunn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular withunit diagonal +void blasfeo_ref_dtrsm_lunu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_dtrsm_lutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular withunit diagonal +void blasfeo_ref_dtrsm_lutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_ref_dtrsm_rlnn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular with unit diagonal +void blasfeo_ref_dtrsm_rlnu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_ref_dtrsm_rltn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular with unit diagonal +void blasfeo_ref_dtrsm_rltu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_dtrsm_runn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular with unit diagonal +void blasfeo_ref_dtrsm_runu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_dtrsm_rutn(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular with unit diagonal +void blasfeo_ref_dtrsm_rutu(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T ; C, D lower triangular +void blasfeo_ref_dsyr2k_ln(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A ; C, D lower triangular +void blasfeo_ref_dsyr2k_lt(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T ; C, D upper triangular +void blasfeo_ref_dsyr2k_un(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A ; C, D upper triangular +void blasfeo_ref_dsyr2k_ut(int m, int k, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); + +// diagonal + +// D <= alpha * A * B + beta * C, with A diagonal (stored as strvec) +void dgemm_diag_left_lib(int m, int n, double alpha, double *dA, double *pB, int sdb, double beta, double *pC, int sdc, double *pD, int sdd); +void blasfeo_ref_dgemm_dn(int m, int n, double alpha, struct blasfeo_dvec *sA, int ai, struct blasfeo_dmat *sB, int bi, int bj, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= alpha * A * B + beta * C, with B diagonal (stored as strvec) +void blasfeo_ref_dgemm_nd(int m, int n, double alpha, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dvec *sB, int bi, double beta, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); + + + +// +// LAPACK +// + +// D <= chol( C ) ; C, D lower triangular +void blasfeo_ref_dpotrf_l(int m, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_ref_dpotrf_l_mn(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= chol( C ) ; C, D upper triangular +void blasfeo_ref_dpotrf_u(int m, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= chol( C + A * B' ) ; C, D lower triangular +void blasfeo_ref_dsyrk_dpotrf_ln(int m, int k, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +void blasfeo_ref_dsyrk_dpotrf_ln_mn(int m, int n, int k, struct blasfeo_dmat *sA, int ai, int aj, struct blasfeo_dmat *sB, int bi, int bj, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= lu( C ) ; no pivoting +void blasfeo_ref_dgetrf_np(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj); +// D <= lu( C ) ; row pivoting +void blasfeo_ref_dgetrf_rp(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, int *ipiv); +// D <= qr( C ) +int blasfeo_ref_dgeqrf_worksize(int m, int n); // in bytes +void blasfeo_ref_dgeqrf(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +// D <= Q factor, where C is the output of the LQ factorization +int blasfeo_ref_dorglq_worksize(int m, int n, int k); // in bytes +void blasfeo_ref_dorglq(int m, int n, int k, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +// D <= lq( C ) +void blasfeo_ref_dgelqf(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +int blasfeo_ref_dgelqf_worksize(int m, int n); // in bytes +// D <= lq( C ), positive diagonal elements +void blasfeo_ref_dgelqf_pd(int m, int n, struct blasfeo_dmat *sC, int ci, int cj, struct blasfeo_dmat *sD, int di, int dj, void *work); +// [L, A] <= lq( [L, A] ), positive diagonal elements, array of matrices, with +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_ref_dgelqf_pd_la(int m, int n1, struct blasfeo_dmat *sL, int li, int lj, struct blasfeo_dmat *sA, int ai, int aj, void *work); +// [L, L, A] <= lq( [L, L, A] ), positive diagonal elements, array of matrices, with: +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_ref_dgelqf_pd_lla(int m, int n1, struct blasfeo_dmat *sL0, int l0i, int l0j, struct blasfeo_dmat *sL1, int l1i, int l1j, struct blasfeo_dmat *sA, int ai, int aj, void *work); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_BLASFEO_REF_API_H_ + diff --git a/third_party/acados/include/blasfeo/include/blasfeo_d_kernel.h b/third_party/acados/include/blasfeo/include/blasfeo_d_kernel.h new file mode 100644 index 0000000000..d20ac38bbd --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_d_kernel.h @@ -0,0 +1,1321 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_D_KERNEL_H_ +#define BLASFEO_D_KERNEL_H_ + + + +#include "blasfeo_target.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// utils +void blasfeo_align_2MB(void *ptr, void **ptr_align); +void blasfeo_align_4096_byte(void *ptr, void **ptr_align); +void blasfeo_align_64_byte(void *ptr, void **ptr_align); + + +// +// lib8 +// + +// 24x8 +void kernel_dgemm_nt_24x8_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nt_24x8_vs_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dtrsm_nt_rl_inv_24x8_lib8(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); // +void kernel_dpotrf_nt_l_24x8_lib8(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dpotrf_nt_l_24x8_vs_lib8(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_24x8_vs_lib8(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int m1, int n1); // +void kernel_dgemm_dtrsm_nt_rl_inv_24x8_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_24x8_vs_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int m1, int n1); +void kernel_dsyrk_dpotrf_nt_l_24x8_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_24x8_vs_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int m1, int n1); +void kernel_dlarfb8_rn_24_lib8(int kmax, double *pV, double *pT, double *pD, int sdd); +// 16x8 +void kernel_dgemm_nt_16x8_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nt_16x8_vs_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nt_16x8_gen_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_nn_16x8_lib8(int k, double *alpha, double *A, int sda, int offB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_16x8_vs_lib8(int k, double *alpha, double *A, int sda, int offB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_16x8_gen_lib8(int k, double *alpha, double *A, int sda, int offB, double *B, int sdb, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dsyrk_nt_l_16x8_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dsyrk_nt_l_16x8_vs_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dsyrk_nt_l_16x8_gen_lib8(int k, double *alpha, double *A, int sda, double *B, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dtrmm_nn_rl_16x8_lib8(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *D, int sdd); +void kernel_dtrmm_nn_rl_16x8_vs_lib8(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *D, int sdd, int m1, int n1); +void kernel_dtrmm_nn_rl_16x8_gen_lib8(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dtrsm_nt_rl_inv_16x8_lib8(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); // +void kernel_dtrsm_nt_rl_inv_16x8_vs_lib8(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int m1, int n1); // +void kernel_dpotrf_nt_l_16x8_lib8(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dpotrf_nt_l_16x8_vs_lib8(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int m1, int n1); +void kernel_dgemm_dtrsm_nt_rl_inv_16x8_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_16x8_vs_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int m1, int n1); +void kernel_dsyrk_dpotrf_nt_l_16x8_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_16x8_vs_lib8(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int m1, int n1); +void kernel_dlarfb8_rn_16_lib8(int kmax, double *pV, double *pT, double *pD, int sdd); +void kernel_dlarfb8_rn_la_16_lib8(int n1, double *pVA, double *pT, double *pD, int sdd, double *pA, int sda); +void kernel_dlarfb8_rn_lla_16_lib8(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, int sdd, double *pL, int sdl, double *pA, int sda); +// 8x16 +void kernel_dgemm_tt_8x16_lib8(int k, double *alpha, int offA, double *A, int sda, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_tt_8x16_vs_lib8(int k, double *alpha, int offA, double *A, int sda, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_8x16_gen_lib8(int k, double *alpha, int offA, double *A, int sda, double *B, int sdb, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_nt_8x16_lib8(int k, double *alpha, double *A, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nt_8x16_vs_lib8(int k, double *alpha, double *A, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +// 8x8 +void kernel_dgemm_nt_8x8_lib8(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dgemm_nt_8x8_vs_lib8(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_nt_8x8_gen_lib8(int k, double *alpha, double *A, double *B, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_nn_8x8_lib8(int k, double *alpha, double *A, int offB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_8x8_vs_lib8(int k, double *alpha, double *A, int offB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_nn_8x8_gen_lib8(int k, double *alpha, double *A, int offB, double *B, int sdb, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_tt_8x8_lib8(int k, double *alpha, int offA, double *A, int sda, double *B, double *beta, double *C, double *D); // +void kernel_dgemm_tt_8x8_vs_lib8(int k, double *alpha, int offA, double *A, int sda, double *B, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_8x8_gen_lib8(int k, double *alpha, int offA, double *A, int sda, double *B, double *beta, int offc, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dsyrk_nt_l_8x8_lib8(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dsyrk_nt_l_8x8_vs_lib8(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dsyrk_nt_l_8x8_gen_lib8(int k, double *alpha, double *A, double *B, double *beta, int offC, double *C, int sdc, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dtrmm_nn_rl_8x8_lib8(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *D); +void kernel_dtrmm_nn_rl_8x8_vs_lib8(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *D, int m1, int n1); +void kernel_dtrmm_nn_rl_8x8_gen_lib8(int k, double *alpha, double *A, int offsetB, double *B, int sdb, int offD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dtrsm_nt_rl_inv_8x8_lib8(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_8x8_vs_lib8(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E, int m1, int n1); +void kernel_dpotrf_nt_l_8x8_lib8(int k, double *A, double *B, double *C, double *D, double *inv_diag_D); +void kernel_dpotrf_nt_l_8x8_vs_lib8(int k, double *A, double *B, double *C, double *D, double *inv_diag_D, int m1, int n1); +void kernel_dgemm_dtrsm_nt_rl_inv_8x8_lib8(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_8x8_vs_lib8(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *E, double *inv_diag_E, int m1, int n1); +void kernel_dsyrk_dpotrf_nt_l_8x8_lib8(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_8x8_vs_lib8(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D, int m1, int n1); +void kernel_dgelqf_vs_lib8(int m, int n, int k, int offD, double *pD, int sdd, double *dD); +void kernel_dgelqf_pd_vs_lib8(int m, int n, int k, int offD, double *pD, int sdd, double *dD); +void kernel_dgelqf_8_lib8(int kmax, double *pD, double *dD); +void kernel_dgelqf_pd_8_lib8(int kmax, double *pD, double *dD); +void kernel_dlarft_8_lib8(int kmax, double *pD, double *dD, double *pT); +void kernel_dlarfb8_rn_8_lib8(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb8_rn_8_vs_lib8(int kmax, double *pV, double *pT, double *pD, int m1); +void kernel_dlarfb8_rn_1_lib8(int kmax, double *pV, double *pT, double *pD); +void kernel_dgelqf_dlarft8_8_lib8(int kmax, double *pD, double *dD, double *pT); +void kernel_dgelqf_pd_dlarft8_8_lib8(int kmax, double *pD, double *dD, double *pT); +void kernel_dgelqf_pd_la_vs_lib8(int m, int n1, int k, int offD, double *pD, int sdd, double *dD, int offA, double *pA, int sda); +void kernel_dgelqf_pd_la_dlarft8_8_lib8(int kmax, double *pD, double *dD, double *pA, double *pT); +void kernel_dlarft_la_8_lib8(int n1, double *dD, double *pA, double *pT); +void kernel_dlarfb8_rn_la_8_lib8(int n1, double *pVA, double *pT, double *pD, double *pA); +void kernel_dlarfb8_rn_la_8_vs_lib8(int n1, double *pVA, double *pT, double *pD, double *pA, int m1); +void kernel_dlarfb8_rn_la_1_lib8(int n1, double *pVA, double *pT, double *pD, double *pA); +void kernel_dgelqf_pd_lla_vs_lib8(int m, int n0, int n1, int k, int offD, double *pD, int sdd, double *dD, int offL, double *pL, int sdl, int offA, double *pA, int sda); +void kernel_dgelqf_pd_lla_dlarft8_8_lib8(int n0, int n1, double *pD, double *dD, double *pL, double *pA, double *pT); +void kernel_dlarft_lla_8_lib8(int n0, int n1, double *dD, double *pL, double *pA, double *pT); +void kernel_dlarfb8_rn_lla_8_lib8(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, double *pL, double *pA); +void kernel_dlarfb8_rn_lla_8_vs_lib8(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, double *pL, double *pA, int m1); +void kernel_dlarfb8_rn_lla_1_lib8(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, double *pL, double *pA); + +// panel copy / pack +// 24 +void kernel_dpack_nn_24_lib8(int kmax, double *A, int lda, double *C, int sdc); +void kernel_dpack_nn_24_vs_lib8(int kmax, double *A, int lda, double *C, int sdc, int m1); +// 16 +void kernel_dpacp_nn_16_lib8(int kmax, int offsetA, double *A, int sda, double *B, int sdb); +void kernel_dpacp_nn_16_vs_lib8(int kmax, int offsetA, double *A, int sda, double *B, int sdb, int m1); +void kernel_dpack_nn_16_lib8(int kmax, double *A, int lda, double *C, int sdc); +void kernel_dpack_nn_16_vs_lib8(int kmax, double *A, int lda, double *C, int sdc, int m1); +// 8 +void kernel_dpacp_nn_8_lib8(int kmax, int offsetA, double *A, int sda, double *B); +void kernel_dpacp_nn_8_vs_lib8(int kmax, int offsetA, double *A, int sda, double *B, int m1); +void kernel_dpacp_tn_8_lib8(int kmax, int offsetA, double *A, int sda, double *B); +void kernel_dpacp_tn_8_vs_lib8(int kmax, int offsetA, double *A, int sda, double *B, int m1); +void kernel_dpacp_l_nn_8_lib8(int kmax, int offsetA, double *A, int sda, double *B); +void kernel_dpacp_l_nn_8_vs_lib8(int kmax, int offsetA, double *A, int sda, double *B, int m1); +void kernel_dpacp_l_tn_8_lib8(int kmax, int offsetA, double *A, int sda, double *B); +void kernel_dpacp_l_tn_8_vs_lib8(int kmax, int offsetA, double *A, int sda, double *B, int m1); +void kernel_dpaad_nn_8_lib8(int kmax, double *alpha, int offsetA, double *A, int sda, double *B); +void kernel_dpaad_nn_8_vs_lib8(int kmax, double *alpha, int offsetA, double *A, int sda, double *B, int m1); +void kernel_dpack_nn_8_lib8(int kmax, double *A, int lda, double *C); +void kernel_dpack_nn_8_vs_lib8(int kmax, double *A, int lda, double *C, int m1); +void kernel_dpack_tn_8_lib8(int kmax, double *A, int lda, double *C); +void kernel_dpack_tn_8_vs_lib8(int kmax, double *A, int lda, double *C, int m1); +// 4 +void kernel_dpack_tt_4_lib8(int kmax, double *A, int lda, double *C, int sdc); // TODO offsetC +void kernel_dpack_tt_4_vs_lib8(int kmax, double *A, int lda, double *C, int sdc, int m1); // TODO offsetC + +// level 2 BLAS +// 16 +void kernel_dgemv_n_16_lib8(int k, double *alpha, double *A, int sda, double *x, double *beta, double *y, double *z); +// 8 +void kernel_dgemv_n_8_lib8(int k, double *alpha, double *A, double *x, double *beta, double *y, double *z); +void kernel_dgemv_n_8_vs_lib8(int k, double *alpha, double *A, double *x, double *beta, double *y, double *z, int m1); +//void kernel_dgemv_n_8_gen_lib8(int k, double *alpha, double *A, double *x, double *beta, double *y, double *z, int m0, int m1); +void kernel_dgemv_n_8_gen_lib8(int k, double *alpha, int offsetA, double *A, double *x, double *beta, double *y, double *z, int m1); +void kernel_dgemv_t_8_lib8(int k, double *alpha, int offsetA, double *A, int sda, double *x, double *beta, double *y, double *z); +void kernel_dgemv_t_8_vs_lib8(int k, double *alpha, int offsetA, double *A, int sda, double *x, double *beta, double *y, double *z, int n1); +void kernel_dgemv_nt_8_lib8(int kmax, double *alpha_n, double *alpha_t, int offsetA, double *A, int sda, double *x_n, double *x_t, double *beta_t, double *y_t, double *z_n, double *z_t); +void kernel_dgemv_nt_8_vs_lib8(int kmax, double *alpha_n, double *alpha_t, int offsetA, double *A, int sda, double *x_n, double *x_t, double *beta_t, double *y_t, double *z_n, double *z_t, int n1); +void kernel_dsymv_l_8_lib8(int kmax, double *alpha, double *A, int sda, double *x, double *z); +void kernel_dsymv_l_8_vs_lib8(int kmax, double *alpha, double *A, int sda, double *x, double *z, int n1); +void kernel_dsymv_l_8_gen_lib8(int kmax, double *alpha, int offsetA, double *A, int sda, double *x, double *z, int n1); +void kernel_dtrmv_n_ln_8_lib8(int k, double *A, double *x, double *z); +void kernel_dtrmv_n_ln_8_vs_lib8(int k, double *A, double *x, double *z, int m1); +void kernel_dtrmv_n_ln_8_gen_lib8(int k, int offsetA, double *A, double *x, double *z, int m1); +void kernel_dtrmv_t_ln_8_lib8(int k, double *A, int sda, double *x, double *z); +void kernel_dtrmv_t_ln_8_vs_lib8(int k, double *A, int sda, double *x, double *z, int n1); +void kernel_dtrmv_t_ln_8_gen_lib8(int k, int offsetA, double *A, int sda, double *x, double *z, int n1); +void kernel_dtrsv_n_l_inv_8_lib8(int k, double *A, double *inv_diag_A, double *x, double *z); +void kernel_dtrsv_n_l_inv_8_vs_lib8(int k, double *A, double *inv_diag_A, double *x, double *z, int m1, int n1); +void kernel_dtrsv_t_l_inv_8_lib8(int k, double *A, int sda, double *inv_diag_A, double *x, double *z); +void kernel_dtrsv_t_l_inv_8_vs_lib8(int k, double *A, int sda, double *inv_diag_A, double *x, double *z, int m1, int n1); + + + +// +// lib4 +// + +// level 2 BLAS +// 12 +void kernel_dgemv_n_12_lib4(int k, double *alpha, double *A, int sda, double *x, double *beta, double *y, double *z); +void kernel_dgemv_t_12_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *x, double *beta, double *y, double *z); +// 8 +void kernel_dgemv_n_8_lib4(int k, double *alpha, double *A, int sda, double *x, double *beta, double *y, double *z); +void kernel_dgemv_t_8_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *x, double *beta, double *y, double *z); +void kernel_dtrmv_un_8_lib4(int k, double *A, int sda, double *x, double *z); +// 4 +void kernel_dgemv_n_4_lib4(int k, double *alpha, double *A, double *x, double *beta, double *y, double *z); +void kernel_dgemv_n_4_vs_lib4(int k, double *alpha, double *A, double *x, double *beta, double *y, double *z, int k1); +void kernel_dgemv_n_4_gen_lib4(int kmax, double *alpha, double *A, double *x, double *beta, double *y, double *z, int k0, int k1); +void kernel_dgemv_t_4_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *x, double *beta, double *y, double *z); +void kernel_dgemv_t_4_vs_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *x, double *beta, double *y, double *z, int k1); +void kernel_dtrsv_ln_inv_4_lib4(int k, double *A, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_ln_inv_4_vs_lib4(int k, double *A, double *inv_diag_A, double *x, double *y, double *z, int km, int kn); +void kernel_dtrsv_lt_inv_4_lib4(int k, double *A, int sda, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_lt_inv_3_lib4(int k, double *A, int sda, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_lt_inv_2_lib4(int k, double *A, int sda, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_lt_inv_1_lib4(int k, double *A, int sda, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_lt_one_4_lib4(int k, double *A, int sda, double *x, double *y, double *z); +void kernel_dtrsv_lt_one_3_lib4(int k, double *A, int sda, double *x, double *y, double *z); +void kernel_dtrsv_lt_one_2_lib4(int k, double *A, int sda, double *x, double *y, double *z); +void kernel_dtrsv_lt_one_1_lib4(int k, double *A, int sda, double *x, double *y, double *z); +void kernel_dtrsv_ln_one_4_vs_lib4(int kmax, double *A, double *x, double *y, double *z, int km, int kn); +void kernel_dtrsv_ln_one_4_lib4(int kmax, double *A, double *x, double *y, double *z); +void kernel_dtrsv_un_inv_4_lib4(int kmax, double *A, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_ut_inv_4_lib4(int kmax, double *A, int sda, double *inv_diag_A, double *x, double *y, double *z); +void kernel_dtrsv_ut_inv_4_vs_lib4(int kmax, double *A, int sda, double *inv_diag_A, double *x, double *y, double *z, int m1, int n1); +void kernel_dtrmv_un_4_lib4(int k, double *A, double *x, double *z); +void kernel_dtrmv_ut_4_lib4(int k, double *A, int sda, double *x, double *z); +void kernel_dtrmv_ut_4_vs_lib4(int k, double *A, int sda, double *x, double *z, int km); +void kernel_dgemv_nt_6_lib4(int kmax, double *alpha_n, double *alpha_t, double *A, int sda, double *x_n, double *x_t, double *beta_t, double *y_t, double *z_n, double *z_t); +void kernel_dgemv_nt_4_lib4(int kmax, double *alpha_n, double *alpha_t, double *A, int sda, double *x_n, double *x_t, double *beta_t, double *y_t, double *z_n, double *z_t); +void kernel_dgemv_nt_4_vs_lib4(int kmax, double *alpha_n, double *alpha_t, double *A, int sda, double *x_n, double *x_t, double *beta_t, double *y_t, double *z_n, double *z_t, int km); +void kernel_dsymv_l_4_lib4(int kmax, double *alpha, double *A, int sda, double *x, double *z); +void kernel_dsymv_l_4_gen_lib4(int kmax, double *alpha, int offA, double *A, int sda, double *x, double *z, int km); + + + +// level 3 BLAS +// 12x4 +void kernel_dgemm_nt_12x4_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nt_12x4_vs_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // +void kernel_dgemm_nt_12x4_gen_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int k0, int k1); +void kernel_dgemm_nn_12x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_12x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // +void kernel_dgemm_nn_12x4_gen_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_tt_12x4_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_tt_12x4_vs_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dsyrk_nn_u_12x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dsyrk_nn_u_12x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dsyrk_nt_l_12x4_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dsyrk_nt_l_12x4_vs_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // +void kernel_dtrmm_nt_ru_12x4_lib4(int k, double *alpha, double *A, int sda, double *B, double *D, int sdd); // +void kernel_dtrmm_nt_ru_12x4_vs_lib4(int k, double *alpha, double *A, int sda, double *B, double *D, int sdd, int km, int kn); // +void kernel_dtrmm_nn_rl_12x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *D, int sdd); +void kernel_dtrmm_nn_rl_12x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *D, int sdd, int km, int kn); +void kernel_dtrsm_nt_rl_inv_12x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_12x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_one_12x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E); +void kernel_dtrsm_nt_rl_one_12x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, int km, int kn); +void kernel_dtrsm_nt_ru_inv_12x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_ru_inv_12x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_ru_one_12x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E); +void kernel_dtrsm_nt_ru_one_12x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, int km, int kn); +void kernel_dtrsm_nn_ru_inv_12x4_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dtrsm_nn_ru_inv_12x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_inv_12x4_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nn_ll_inv_12x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_one_12x4_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde); +void kernel_dtrsm_nn_ll_one_12x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde, int km, int kn); +void kernel_dtrsm_nn_lu_inv_12x4_lib4(int kmax, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nn_lu_inv_12x4_vs_lib4(int kmax, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E, int km, int kn); +// 4x12 +void kernel_dgemm_nt_4x12_lib4(int k, double *alpha, double *A, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nt_4x12_vs_lib4(int k, double *alpha, double *A, double *B, int sdb, double *beta, double *C, double *D, int km, int kn); // +void kernel_dgemm_nn_4x12_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_4x12_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_4x12_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_tt_4x12_vs_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_4x12_gen_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, int sdb, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dtrsm_nt_rl_inv_4x12_lib4(int k, double *A, double *B, int sdb, double *C, double *D, double *E, int sed, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_4x12_vs_lib4(int k, double *A, double *B, int sdb, double *C, double *D, double *E, int sed, double *inv_diag_E, int km, int kn); +// 8x8 +void kernel_dgemm_nt_8x8l_lib4(int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // computes [A00 *; A10 A11] +void kernel_dgemm_nt_8x8u_lib4(int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // computes [A00 *; A10 A11] +void kernel_dgemm_nt_8x8l_vs_lib4(int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // computes [A00 *; A10 A11] +void kernel_dgemm_nt_8x8u_vs_lib4(int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // computes [A00 *; A10 A11] +void kernel_dsyrk_nn_u_8x8_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dsyrk_nn_u_8x8_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dsyrk_nt_l_8x8_lib4(int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // computes [L00 *; A10 L11] +void kernel_dsyrk_nt_l_8x8_vs_lib4(int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // computes [L00 *; A10 L11] +void kernel_dtrsm_nt_rl_inv_8x8l_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sed, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_8x8l_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sed, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_inv_8x8u_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sed, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_8x8u_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sed, double *inv_diag_E, int km, int kn); +// 8x4 +void kernel_dgemm_nt_8x4_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nt_8x4_vs_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // +void kernel_dgemm_nt_8x4_gen_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int k0, int k1); +void kernel_dgemm_nn_8x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_8x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_8x4_gen_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_tt_8x4_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_tt_8x4_vs_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dsyrk_nn_u_8x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dsyrk_nn_u_8x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dsyrk_nt_l_8x4_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dsyrk_nt_l_8x4_vs_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, int km, int kn); // +void kernel_dsyrk_nt_l_8x4_gen_lib4(int k, double *alpha, double *A, int sda, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int k0, int k1); +void kernel_dtrmm_nt_ru_8x4_lib4(int k, double *alpha, double *A, int sda, double *B, double *D, int sdd); // +void kernel_dtrmm_nt_ru_8x4_vs_lib4(int k, double *alpha, double *A, int sda, double *B, double *D, int sdd, int km, int kn); // +void kernel_dtrmm_nn_rl_8x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *D, int sdd); +void kernel_dtrmm_nn_rl_8x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *D, int sdd, int km, int kn); +void kernel_dtrmm_nn_rl_8x4_gen_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dtrsm_nt_rl_inv_8x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_inv_8x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_rl_one_8x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E); +void kernel_dtrsm_nt_rl_one_8x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, int km, int kn); +void kernel_dtrsm_nt_ru_inv_8x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_ru_inv_8x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_ru_one_8x4_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E); +void kernel_dtrsm_nt_ru_one_8x4_vs_lib4(int k, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd, double *E, int km, int kn); +void kernel_dtrsm_nn_ru_inv_8x4_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dtrsm_nn_ru_inv_8x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_inv_8x4_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nn_ll_inv_8x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_one_8x4_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde); +void kernel_dtrsm_nn_ll_one_8x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int sde, int km, int kn); +void kernel_dtrsm_nn_lu_inv_8x4_lib4(int kmax, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nn_lu_inv_8x4_vs_lib4(int kmax, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E, int km, int kn); +// 4x8 +void kernel_dgemm_nt_4x8_lib4(int k, double *alpha, double *A, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nt_4x8_vs_lib4(int k, double *alpha, double *A, double *B, int sdb, double *beta, double *C, double *D, int km, int kn); // +void kernel_dgemm_nn_4x8_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_4x8_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_4x8_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_tt_4x8_vs_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_4x8_gen_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, int sdb, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dtrsm_nt_rl_inv_4x8_lib4(int k, double *A, double *B, int sdb, double *C, double *D, double *E, int sed, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_4x8_vs_lib4(int k, double *A, double *B, int sdb, double *C, double *D, double *E, int sed, double *inv_diag_E, int km, int kn); +// 8x2 +void kernel_dgemm_nn_8x2_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_8x2_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +// 2x8 +void kernel_dgemm_nn_2x8_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_2x8_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +// 10xX +void kernel_dgemm_nn_10x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_10x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_10x2_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_10x2_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +// 6xX +void kernel_dgemm_nn_8x6_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_8x6_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_6x8_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_6x8_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_6x6_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_6x6_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_6x4_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_6x4_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +void kernel_dgemm_nn_6x2_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd); // +void kernel_dgemm_nn_6x2_vs_lib4(int k, double *alpha, double *A, int sda, int offsetB, double *B, int sdb, double *beta, double *C, int sdc, double *D, int sdd, int m1, int n1); // +// 4x4 +void kernel_dgemm_nt_4x4_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dgemm_nt_4x4_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int km, int kn); // +void kernel_dgemm_nt_4x4_gen_lib4(int k, double *alpha, double *A, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dgemm_nn_4x4_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_4x4_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_nn_4x4_gen_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dgemm_tt_4x4_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, double *C, double *D); // +void kernel_dgemm_tt_4x4_vs_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_tt_4x4_gen_lib4(int k, double *alpha, int offsetA, double *A, int sda, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_dsyrk_nn_u_4x4_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dsyrk_nn_u_4x4_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dsyrk_nt_l_4x4_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dsyrk_nt_l_4x4_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int km, int kn); // +void kernel_dsyrk_nt_l_4x4_gen_lib4(int k, double *alpha, double *A, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dsyrk_nt_u_4x4_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dsyrk_nt_u_4x4_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int km, int kn); // +void kernel_dsyrk_nt_u_4x4_gen_lib4(int k, double *alpha, double *A, double *B, double *beta, int offsetC, double *C, int sdc, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dtrmm_nt_ru_4x4_lib4(int k, double *alpha, double *A, double *B, double *D); // +void kernel_dtrmm_nt_ru_4x4_vs_lib4(int k, double *alpha, double *A, double *B, double *D, int km, int kn); // +void kernel_dtrmm_nn_rl_4x4_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *D); +void kernel_dtrmm_nn_rl_4x4_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *D, int m1, int n1); +void kernel_dtrmm_nn_rl_4x4_gen_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, int offsetD, double *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_dtrsm_nt_rl_inv_4x4_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_4x4_vs_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_one_4x4_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E); +void kernel_dtrsm_nt_rl_one_4x4_vs_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, int km, int kn); +void kernel_dtrsm_nt_ru_inv_4x4_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_ru_inv_4x4_vs_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_ru_one_4x4_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E); +void kernel_dtrsm_nt_ru_one_4x4_vs_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, int km, int kn); +void kernel_dtrsm_nn_ru_inv_4x4_lib4(int k, double *A, double *B, int sdb, double *beta, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nn_ru_inv_4x4_vs_lib4(int k, double *A, double *B, int sdb, double *beta, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_inv_4x4_lib4(int k, double *A, double *B, int sdb, double *beta, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nn_ll_inv_4x4_vs_lib4(int k, double *A, double *B, int sdb, double *beta, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_one_4x4_lib4(int k, double *A, double *B, int sdb, double *beta, double *C, double *D, double *E); +void kernel_dtrsm_nn_ll_one_4x4_vs_lib4(int k, double *A, double *B, int sdb, double *beta, double *C, double *D, double *E, int km, int kn); +void kernel_dtrsm_nn_lu_inv_4x4_lib4(int kmax, double *A, double *B, int sdb, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nn_lu_inv_4x4_vs_lib4(int kmax, double *A, double *B, int sdb, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_lu_one_4x4_lib4(int kmax, double *A, double *B, int sdb, double *C, double *D, double *E); +void kernel_dtrsm_nn_lu_one_4x4_vs_lib4(int kmax, double *A, double *B, int sdb, double *C, double *D, double *E, int km, int kn); +// 4x2 +void kernel_dgemm_nn_4x2_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_4x2_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +void kernel_dgemm_nt_4x2_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); +void kernel_dgemm_nt_4x2_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int m1, int n1); +void kernel_dsyrk_nt_l_4x2_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dsyrk_nt_l_4x2_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int km, int kn); // +void kernel_dtrmm_nn_rl_4x2_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *D); +void kernel_dtrmm_nn_rl_4x2_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *D, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_4x2_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_rl_inv_4x2_vs_lib4(int k, double *A, double *B, double *beta, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +// 2x4 +void kernel_dgemm_nn_2x4_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dgemm_nn_2x4_vs_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D, int m1, int n1); // +// 2x2 +void kernel_dgemm_nn_2x2_lib4(int k, double *alpha, double *A, int offsetB, double *B, int sdb, double *beta, double *C, double *D); // +void kernel_dsyrk_nt_l_2x2_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dsyrk_nt_l_2x2_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int km, int kn); // +// diag +void kernel_dgemm_diag_right_4_a0_lib4(int kmax, double *alpha, double *A, int sda, double *B, double *D, int sdd); +void kernel_dgemm_diag_right_4_lib4(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); +void kernel_dgemm_diag_right_3_lib4(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); +void kernel_dgemm_diag_right_2_lib4(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); +void kernel_dgemm_diag_right_1_lib4(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int sdd); +void kernel_dgemm_diag_left_4_a0_lib4(int kmax, double *alpha, double *A, double *B, double *D); +void kernel_dgemm_diag_left_4_lib4(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D); +void kernel_dgemm_diag_left_3_lib4(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D); +void kernel_dgemm_diag_left_2_lib4(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D); +void kernel_dgemm_diag_left_1_lib4(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D); +// low rank update +void kernel_dger4_sub_12r_lib4(int k, double *A, int sda, double *B, double *C, int sdc); +void kernel_dger4_sub_12r_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, int km); +void kernel_dger4_sub_8r_lib4(int k, double *A, int sda, double *B, double *C, int sdc); +void kernel_dger4_sub_8r_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, int km); +void kernel_dger4_sub_4r_lib4(int n, double *A, double *B, double *C); +void kernel_dger4_sub_4r_vs_lib4(int n, double *A, double *B, double *C, int km); + + + +// LAPACK +// 12x4 +void kernel_dpotrf_nt_l_12x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dpotrf_nt_l_12x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nn_l_12x4_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nn_l_12x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nn_m_12x4_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nn_m_12x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nn_r_12x4_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nn_r_12x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nt_l_12x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nt_l_12x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nt_m_12x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nt_m_12x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nt_r_12x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nt_r_12x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +// 8x8 +void kernel_dpotrf_nt_l_8x8_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dpotrf_nt_l_8x8_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +// 8x4 +void kernel_dpotrf_nt_l_8x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dpotrf_nt_l_8x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nn_l_8x4_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nn_l_8x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nn_r_8x4_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nn_r_8x4_vs_lib4(int k, double *A, int sda, double *B, int sdb, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nt_l_8x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nt_l_8x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nt_r_8x4_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dgetrf_nt_r_8x4_vs_lib4(int k, double *A, int sda, double *B, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +// 4x4 +void kernel_dpotrf_nt_l_4x4_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D); +void kernel_dpotrf_nt_l_4x4_vs_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D, int km, int kn); +#if defined(TARGET_X64_INTEL_SANDY_BRIDGE) +void kernel_dlauum_nt_4x4_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D); // +void kernel_dlauum_nt_4x4_vs_lib4(int k, double *alpha, double *A, double *B, double *beta, double *C, double *D, int km, int kn); // +#endif +void kernel_dgetrf_nn_4x4_lib4(int k, double *A, double *B, int sdb, double *C, double *D, double *inv_diag_D); +void kernel_dgetrf_nn_4x4_vs_lib4(int k, double *A, double *B, int sdb, double *C, double *D, double *inv_diag_D, int km, int kn); +void kernel_dgetrf_nt_4x4_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D); +void kernel_dgetrf_nt_4x4_vs_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D, int km, int kn); +void kernel_dgeqrf_4_lib4(int m, double *pD, int sdd, double *dD); +void kernel_dgeqrf_vs_lib4(int m, int n, int k, int offD, double *pD, int sdd, double *dD); +void kernel_dlarf_4_lib4(int m, int n, double *pV, int sdv, double *tau, double *pC, int sdc); // rank-4 reflector +void kernel_dlarf_t_4_lib4(int m, int n, double *pD, int sdd, double *pVt, double *dD, double *pC0, int sdc, double *pW); +void kernel_dgelqf_4_lib4(int n, double *pD, double *dD); +void kernel_dgelqf_vs_lib4(int m, int n, int k, int offD, double *pD, int sdd, double *dD); +void kernel_dlarft_4_lib4(int kmax, double *pD, double *dD, double *pT); +void kernel_dlarft_3_lib4(int kmax, double *pD, double *dD, double *pT); +void kernel_dlarft_2_lib4(int kmax, double *pD, double *dD, double *pT); +void kernel_dlarft_1_lib4(int kmax, double *pD, double *dD, double *pT); +void kernel_dgelqf_dlarft12_12_lib4(int n, double *pD, int sdd, double *dD, double *pT); +void kernel_dgelqf_dlarft4_12_lib4(int n, double *pD, int sdd, double *dD, double *pT); +void kernel_dgelqf_dlarft4_8_lib4(int n, double *pD, int sdd, double *dD, double *pT); +void kernel_dgelqf_dlarft4_4_lib4(int n, double *pD, double *dD, double *pT); +void kernel_dlarfb12_rn_12_lib4(int kmax, double *pV, int sdd, double *pT, double *pD, double *pK); +void kernel_dlarfb12_rn_4_lib4(int kmax, double *pV, int sdd, double *pT, double *pD, double *pK, int km); +void kernel_dlarfb4_rn_12_lib4(int kmax, double *pV, double *pT, double *pD, int sdd); +void kernel_dlarfb4_rn_8_lib4(int kmax, double *pV, double *pT, double *pD, int sdd); +void kernel_dlarfb4_rn_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb3_rn_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb2_rn_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb1_rn_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb4_rn_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb3_rn_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb2_rn_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb1_rn_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb4_rt_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb3_rt_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb2_rt_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb1_rt_4_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb4_rt_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb3_rt_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb2_rt_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dlarfb1_rt_1_lib4(int kmax, double *pV, double *pT, double *pD); +void kernel_dgelqf_pd_dlarft12_12_lib4(int n, double *pD, int sdd, double *dD, double *pT); +void kernel_dgelqf_pd_dlarft4_8_lib4(int n, double *pD, int sdd, double *dD, double *pT); +void kernel_dgelqf_pd_dlarft4_4_lib4(int n, double *pD, double *dD, double *pT); +void kernel_dgelqf_pd_4_lib4(int n, double *pD, double *dD); +void kernel_dgelqf_pd_vs_lib4(int m, int n, int k, int offD, double *pD, int sdd, double *dD); +void kernel_dgelqf_pd_la_vs_lib4(int m, int n1, int k, int offD, double *pD, int sdd, double *dD, int offA, double *pA, int sda); +void kernel_dlarft_4_la_lib4(int n1, double *dD, double *pA, double *pT); +void kernel_dlarfb4_rn_12_la_lib4(int n1, double *pVA, double *pT, double *pD, int sdd, double *pA, int sda); +void kernel_dlarfb4_rn_8_la_lib4(int n1, double *pVA, double *pT, double *pD, int sdd, double *pA, int sda); +void kernel_dlarfb4_rn_4_la_lib4(int n1, double *pVA, double *pT, double *pD, double *pA); +void kernel_dlarfb4_rn_1_la_lib4(int n1, double *pVA, double *pT, double *pD, double *pA); +void kernel_dgelqf_pd_lla_vs_lib4(int m, int n0, int n1, int k, int offD, double *pD, int sdd, double *dD, int offL, double *pL, int sdl, int offA, double *pA, int sda); +void kernel_dlarft_4_lla_lib4(int n0, int n1, double *dD, double *pL, double *pA, double *pT); +void kernel_dlarfb4_rn_12_lla_lib4(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, int sdd, double *pL, int sdl, double *pA, int sda); +void kernel_dlarfb4_rn_8_lla_lib4(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, int sdd, double *pL, int sdl, double *pA, int sda); +void kernel_dlarfb4_rn_4_lla_lib4(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, double *pL, double *pA); +void kernel_dlarfb4_rn_1_lla_lib4(int n0, int n1, double *pVL, double *pVA, double *pT, double *pD, double *pL, double *pA); +// 4x2 +void kernel_dpotrf_nt_l_4x2_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D); +void kernel_dpotrf_nt_l_4x2_vs_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D, int km, int kn); +// 2x2 +void kernel_dpotrf_nt_l_2x2_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D); +void kernel_dpotrf_nt_l_2x2_vs_lib4(int k, double *A, double *B, double *C, double *D, double *inv_diag_D, int km, int kn); +// 12 +void kernel_dgetrf_pivot_12_lib4(int m, double *pA, int sda, double *inv_diag_A, int* ipiv); +void kernel_dgetrf_pivot_12_vs_lib4(int m, double *pA, int sda, double *inv_diag_A, int* ipiv, int n); +// 8 +void kernel_dgetrf_pivot_8_lib4(int m, double *pA, int sda, double *inv_diag_A, int* ipiv); +void kernel_dgetrf_pivot_8_vs_lib4(int m, double *pA, int sda, double *inv_diag_A, int* ipiv, int n); +// 4 +void kernel_dgetrf_pivot_4_lib4(int m, double *pA, int sda, double *inv_diag_A, int* ipiv); +void kernel_dgetrf_pivot_4_vs_lib4(int m, double *pA, int sda, double *inv_diag_A, int* ipiv, int n1); +// vector +void kernel_drowsw_lib4(int kmax, double *pA, double *pC); + + + +// merged routines +// 12x4 +void kernel_dgemm_dtrsm_nt_rl_inv_12x4_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_12x4_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dsyrk_dpotrf_nt_l_12x4_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_12x4_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +// 4x12 +void kernel_dgemm_dtrsm_nt_rl_inv_4x12_vs_lib4(int kp, double *Ap, double *Bp, int sdbp, int km_, double *Am, double *Bm, int sdbm, double *C, double *D, double *E, int sde, double *inv_diag_E, int km, int kn); +// 8x8 +void kernel_dsyrk_dpotrf_nt_l_8x8_lib4(int kp, double *Ap, int sdap, double *Bp, int sdbp, int km_, double *Am, int sdam, double *Bm, int sdbm, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_8x8_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int sdbp, int km_, double *Am, int sdam, double *Bm, int sdbm, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +void kernel_dgemm_dtrsm_nt_rl_inv_8x8l_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int sdb, int km_, double *Am, int sdam, double *Bm, int sdbm, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dgemm_dtrsm_nt_rl_inv_8x8u_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int sdb, int km_, double *Am, int sdam, double *Bm, int sdbm, double *C, int sdc, double *D, int sdd, double *E, int sde, double *inv_diag_E, int km, int kn); +// 8x4 +void kernel_dgemm_dtrsm_nt_rl_inv_8x4_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_8x4_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dsyrk_dpotrf_nt_l_8x4_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_8x4_vs_lib4(int kp, double *Ap, int sdap, double *Bp, int km_, double *Am, int sdam, double *Bm, double *C, int sdc, double *D, int sdd, double *inv_diag_D, int km, int kn); +// 4x8 +void kernel_dgemm_dtrsm_nt_rl_inv_4x8_vs_lib4(int kp, double *Ap, double *Bp, int sdbp, int km_, double *Am, double *Bm, int sdbm, double *C, double *D, double *E, int sde, double *inv_diag_E, int km, int kn); +// 4x4 +void kernel_dgemm_dtrsm_nt_rl_inv_4x4_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_4x4_vs_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dsyrk_dpotrf_nt_l_4x4_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_4x4_vs_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D, int km, int kn); +// 4x2 +void kernel_dgemm_dtrsm_nt_rl_inv_4x2_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *E, double *inv_diag_E); +void kernel_dgemm_dtrsm_nt_rl_inv_4x2_vs_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *E, double *inv_diag_E, int km, int kn); +void kernel_dsyrk_dpotrf_nt_l_4x2_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_4x2_vs_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D, int km, int kn); +// 2x2 +void kernel_dsyrk_dpotrf_nt_l_2x2_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D); +void kernel_dsyrk_dpotrf_nt_l_2x2_vs_lib4(int kp, double *Ap, double *Bp, int km_, double *Am, double *Bm, double *C, double *D, double *inv_diag_D, int km, int kn); + +/* + * + * Auxiliary routines + * + * cpsc copy and scale, scale + * cp copy + * add + * set and scale + * transpose and scale + * set and scale + * + */ + +// copy and scale +void kernel_dgecpsc_8_0_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgecpsc_8_1_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgecpsc_8_2_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgecpsc_8_3_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B, int sdb); + +void kernel_dgecpsc_4_0_lib4(int tri, int kmax, double alpha, double *A, double *B); +void kernel_dgecpsc_4_1_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgecpsc_4_2_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgecpsc_4_3_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B); + +void kernel_dgecpsc_3_0_lib4(int tri, int kmax, double alpha, double *A, double *B); +void kernel_dgecpsc_3_2_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgecpsc_3_3_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B); + +void kernel_dgecpsc_2_0_lib4(int tri, int kmax, double alpha, double *A, double *B); +void kernel_dgecpsc_2_3_lib4(int tri, int kmax, double alpha, double *A0, int sda, double *B); + +void kernel_dgecpsc_1_0_lib4(int tri, int kmax, double alpha, double *A, double *B); + +// copy only +void kernel_dgecp_8_0_lib4(int tri, int kmax, double *A, int sda, double *B, int sdb); + +void kernel_dgecp_4_0_lib4(int tri, int kmax, double *A, double *B); + +// add +void kernel_dgead_8_0_lib4(int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgead_8_1_lib4(int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgead_8_2_lib4(int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgead_8_3_lib4(int kmax, double alpha, double *A0, int sda, double *B, int sdb); +void kernel_dgead_4_0_lib4(int kmax, double alpha, double *A, double *B); +void kernel_dgead_4_1_lib4(int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgead_4_2_lib4(int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgead_4_3_lib4(int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgead_3_0_lib4(int kmax, double alpha, double *A, double *B); +void kernel_dgead_3_2_lib4(int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgead_3_3_lib4(int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgead_2_0_lib4(int kmax, double alpha, double *A, double *B); +void kernel_dgead_2_3_lib4(int kmax, double alpha, double *A0, int sda, double *B); +void kernel_dgead_1_0_lib4(int kmax, double alpha, double *A, double *B); + +// set +void kernel_dgeset_4_lib4(int kmax, double alpha, double *A); +void kernel_dtrset_4_lib4(int kmax, double alpha, double *A); + +// traspose +void kernel_dgetr_8_lib4(int tri, int kmax, int kna, double alpha, double *A, int sda, double *C, int sdc); +void kernel_dgetr_4_lib4(int tri, int kmax, int kna, double alpha, double *A, double *C, int sdc); +void kernel_dgetr_3_lib4(int tri, int kmax, int kna, double alpha, double *A, double *C, int sdc); +void kernel_dgetr_2_lib4(int tri, int kmax, int kna, double alpha, double *A, double *C, int sdc); +void kernel_dgetr_1_lib4(int tri, int kmax, int kna, double alpha, double *A, double *C, int sdc); +void kernel_dgetr_4_0_lib4(int m, double *A, int sda, double *B); + + + +// pack +// 12 +void kernel_dpack_nn_12_lib4(int kmax, double *A, int lda, double *B, int sdb); +void kernel_dpack_nn_12_vs_lib4(int kmax, double *A, int lda, double *B, int sdb, int m1); +void kernel_dpack_tt_12_lib4(int kmax, double *A, int lda, double *B, int sdb); +// 8 +void kernel_dpack_nn_8_lib4(int kmax, double *A, int lda, double *B, int sdb); +void kernel_dpack_nn_8_vs_lib4(int kmax, double *A, int lda, double *B, int sdb, int m1); +void kernel_dpack_tt_8_lib4(int kmax, double *A, int lda, double *B, int sdb); +// 4 +void kernel_dpack_nn_4_lib4(int kmax, double *A, int lda, double *B); +void kernel_dpack_nn_4_vs_lib4(int kmax, double *A, int lda, double *B, int m1); +void kernel_dpack_tn_4_p0_lib4(int kmax, double *A, int lda, double *B); +void kernel_dpack_tn_4_lib4(int kmax, double *A, int lda, double *B); +void kernel_dpack_tn_4_vs_lib4(int kmax, double *A, int lda, double *B, int m1); +void kernel_dpack_tt_4_lib4(int kmax, double *A, int lda, double *B, int sdb); +void kernel_dpack_tt_4_vs_lib4(int kmax, double *A, int lda, double *B, int sdb, int m1); +// unpack +// 12 +void kernel_dunpack_nn_12_lib4(int kmax, double *A, int sda, double *B, int ldb); +void kernel_dunpack_nn_12_vs_lib4(int kmax, double *A, int sda, double *B, int ldb, int m1); +void kernel_dunpack_tt_12_lib4(int kmax, double *A, int sda, double *B, int ldb); +// 8 +void kernel_dunpack_nn_8_lib4(int kmax, double *A, int sda, double *B, int ldb); +void kernel_dunpack_nn_8_vs_lib4(int kmax, double *A, int sda, double *B, int ldb, int m1); +void kernel_dunpack_tt_8_lib4(int kmax, double *A, int sda, double *B, int ldb); +// 4 +void kernel_dunpack_nn_4_lib4(int kmax, double *A, double *B, int ldb); +void kernel_dunpack_nn_4_vs_lib4(int kmax, double *A, double *B, int ldb, int m1); +void kernel_dunpack_nt_4_lib4(int kmax, double *A, double *B, int ldb); +void kernel_dunpack_nt_4_vs_lib4(int kmax, double *A, double *B, int ldb, int m1); +void kernel_dunpack_tt_4_lib4(int kmax, double *A, int sda, double *B, int ldb); + +// panel copy +// 12 +void kernel_dpacp_nn_12_lib4(int kmax, int offsetA, double *A, int sda, double *B, int sdb); +void kernel_dpacp_nn_12_vs_lib4(int kmax, int offsetA, double *A, int sda, double *B, int sdb, int m1); +// 8 +void kernel_dpacp_nn_8_lib4(int kmax, int offsetA, double *A, int sda, double *B, int sdb); +void kernel_dpacp_nn_8_vs_lib4(int kmax, int offsetA, double *A, int sda, double *B, int sdb, int m1); +// 4 +void kernel_dpacp_nt_4_lib4(int kmax, double *A, int offsetB, double *B, int sdb); +void kernel_dpacp_tn_4_lib4(int kmax, int offsetA, double *A, int sda, double *B); +void kernel_dpacp_nn_4_lib4(int kmax, int offsetA, double *A, int sda, double *B); +void kernel_dpacp_nn_4_vs_lib4(int kmax, int offsetA, double *A, int sda, double *B, int m1); + + + +/************************************************ +* BLAS API kernels +************************************************/ + +//#if defined(BLAS_API) + +// A, B panel-major bs=4; C, D column-major +// 12x4 +void kernel_dgemm_nt_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_12x4_p0_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *A_p, double *B_p); +void kernel_dsyrk_nt_l_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_u_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_u_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_12x4_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_12x4_vs_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyr2k_nt_l_12x4_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyr2k_nt_l_12x4_vs_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_12x4_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_12x4_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_12x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_12x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrsm_nt_ll_inv_12x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nt_ll_inv_12x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_inv_12x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE); +void kernel_dtrsm_nt_rl_inv_12x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_12x4_lib44ccc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_12x4_vs_lib44ccc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_12x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E); +void kernel_dtrsm_nt_rl_one_12x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_12x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE); +void kernel_dtrsm_nt_ru_inv_12x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_12x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E); +void kernel_dtrsm_nt_ru_one_12x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int m1, int n1); +void kernel_dpotrf_nt_l_12x4_lib44cc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *dD); +void kernel_dpotrf_nt_l_12x4_vs_lib44cc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *dD, int m1, int n1); +// 4x12 +void kernel_dgemm_nt_4x12_lib44cc(int kmax, double *alpha, double *A, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x12_vs_lib44cc(int kmax, double *alpha, double *A, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x12_p0_vs_lib44cc(int kmax, double *alpha, double *A, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1, double *A_p, double *B_p); +void kernel_dtrmm_nt_rl_4x12_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x12_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x12_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x12_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x12_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x12_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x12_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x12_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +// 8x8 +void kernel_dsyrk_nt_l_8x8_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_8x8_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_u_8x8_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_u_8x8_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_8x8_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, int sdb0, double *A1, int sda1, double *B1, int sdb1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_8x8_vs_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, int sdb0, double *A1, int sda1, double *B1, int sdb1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyr2k_nt_l_8x8_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, int sdb0, double *A1, int sda1, double *B1, int sdb1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyr2k_nt_l_8x8_vs_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, int sdb0, double *A1, int sda1, double *B1, int sdb1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dpotrf_nt_l_8x8_lib44cc(int kmax, double *A, int sda, double *B, int sdb, double *C, int ldc, double *D, int ldd, double *dD); +void kernel_dpotrf_nt_l_8x8_vs_lib44cc(int kmax, double *A, int sda, double *B, int sdb, double *C, int ldc, double *D, int ldd, double *dD, int m1, int n1); +// 8x4 +void kernel_dgemm_nt_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_8x4_p0_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *A_p, double *B_p); +void kernel_dgemm_nt_8x4_p_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *A_p); +void kernel_dsyrk_nt_l_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_u_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_u_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_8x4_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_8x4_vs_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyr2k_nt_l_8x4_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyr2k_nt_l_8x4_vs_lib44cc(int kmax, double *alpha, double *A0, int sda0, double *B0, double *A1, int sda1, double *B1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_8x4_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_8x4_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_8x4_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_8x4_vs_lib44cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrsm_nt_ll_inv_8x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nt_ll_inv_8x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_inv_8x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE); +void kernel_dtrsm_nt_rl_inv_8x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_8x4_lib44ccc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_8x4_vs_lib44ccc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_8x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E); +void kernel_dtrsm_nt_rl_one_8x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_8x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE); +void kernel_dtrsm_nt_ru_inv_8x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_8x4_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E); +void kernel_dtrsm_nt_ru_one_8x4_vs_lib44cc4(int kmax, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int m1, int n1); +void kernel_dpotrf_nt_l_8x4_lib44cc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *dD); +void kernel_dpotrf_nt_l_8x4_vs_lib44cc(int kmax, double *A, int sda, double *B, double *C, int ldc, double *D, int ldd, double *dD, int m1, int n1); +// 4x8 +void kernel_dgemm_nt_4x8_lib44cc(int kmax, double *alpha, double *A, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x8_vs_lib44cc(int kmax, double *alpha, double *A, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x8_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x8_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x8_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x8_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x8_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x8_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x8_tran_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x8_tran_vs_lib444c(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +// 4x4 +void kernel_dgemm_nt_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_l_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_u_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_u_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_4x4_lib44cc(int kmax, double *alpha, double *A0, double *B0, double *A1, double *B1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_4x4_vs_lib44cc(int kmax, double *alpha, double *A0, double *B0, double *A1, double *B1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyr2k_nt_l_4x4_lib44cc(int kmax, double *alpha, double *A0, double *B0, double *A1, double *B1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyr2k_nt_l_4x4_vs_lib44cc(int kmax, double *alpha, double *A0, double *B0, double *A1, double *B1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x4_tran_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x4_tran_vs_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x4_tran_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x4_tran_vs_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x4_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x4_vs_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x4_tran_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x4_tran_vs_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x4_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x4_vs_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x4_tran_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x4_tran_vs_lib444c(int kmax, double *alpha, double *A, double *B, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrsm_nt_ll_inv_4x4_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *inv_diag_E); +void kernel_dtrsm_nt_ll_inv_4x4_vs_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nt_rl_inv_4x4_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE); +void kernel_dtrsm_nt_rl_inv_4x4_vs_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_4x4_lib44ccc(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_4x4_vs_lib44ccc(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_4x4_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E); +void kernel_dtrsm_nt_rl_one_4x4_vs_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_4x4_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE); +void kernel_dtrsm_nt_ru_inv_4x4_vs_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_4x4_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E); +void kernel_dtrsm_nt_ru_one_4x4_vs_lib44cc4(int kmax, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, double *E, int m1, int n1); +void kernel_dpotrf_nt_l_4x4_lib44cc(int kmax, double *A, double *B, double *C, int ldc, double *D, int ldd, double *dD); +void kernel_dpotrf_nt_l_4x4_vs_lib44cc(int kmax, double *A, double *B, double *C, int ldc, double *D, int ldd, double *dD, int m1, int n1); +// 4x2 +void kernel_dgemm_nt_4x2_lib44cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); + +// A panel-major bs=4; B, C, D column-major +// 12x4 +void kernel_dgemm_nn_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_l_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_12x4_lib4ccc(int kmax, double *alpha, double *A0, int sda0, double *B0, int ldb0, double *A1, int sda1, double *B1, int ldb1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_12x4_vs_lib4ccc(int kmax, double *alpha, double *A0, int sda0, double *B0, int ldb0, double *A1, int sda1, double *B1, int ldb1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_rl_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_one_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_rl_one_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_ru_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_one_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_ru_one_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_12x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_12x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrsm_nn_ll_inv_12x4_lib4ccc4(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nn_ll_inv_12x4_vs_lib4ccc4(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_one_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_ll_one_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_rl_inv_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_rl_inv_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_rl_one_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_rl_one_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nt_rl_one_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_ru_inv_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_ru_inv_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_ru_one_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_ru_one_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_ru_inv_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_12x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nt_ru_one_12x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dgetrf_nn_l_12x4_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag); +void kernel_dgetrf_nn_l_12x4_vs_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag, int m1, int n1); +void kernel_dgetrf_nn_m_12x4_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag); +void kernel_dgetrf_nn_m_12x4_vs_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag, int m1, int n1); +void kernel_dgetrf_nn_r_12x4_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag); +void kernel_dgetrf_nn_r_12x4_vs_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag, int m1, int n1); +// 4x12 +void kernel_dgemm_nn_4x12_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_4x12_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x12_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x12_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_rl_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_one_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_rl_one_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_ru_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_one_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_ru_one_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x12_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x12_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +// 8x4 +void kernel_dgemm_nn_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_l_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_8x4_lib4ccc(int kmax, double *alpha, double *A0, int sda0, double *B0, int ldb0, double *A1, int sda1, double *B1, int ldb1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_8x4_vs_lib4ccc(int kmax, double *alpha, double *A0, int sda0, double *B0, int ldb0, double *A1, int sda1, double *B1, int ldb1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_rl_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_one_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_rl_one_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_ru_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_one_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_ru_one_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_8x4_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_8x4_vs_lib4ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrsm_nn_ll_inv_8x4_lib4ccc4(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E); +void kernel_dtrsm_nn_ll_inv_8x4_vs_lib4ccc4(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int sde, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_one_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_ll_one_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_rl_inv_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_rl_inv_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_rl_one_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_rl_one_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nt_rl_one_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_ru_inv_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_ru_inv_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_ru_one_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_ru_one_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_ru_inv_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_8x4_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nt_ru_one_8x4_vs_lib4cccc(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dgetrf_nn_l_8x4_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag); +void kernel_dgetrf_nn_l_8x4_vs_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag, int m1, int n1); +void kernel_dgetrf_nn_r_8x4_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag); +void kernel_dgetrf_nn_r_8x4_vs_lib4ccc(int kmax, double *A, int sda, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag, int m1, int n1); +// 4x8 +void kernel_dgemm_nn_4x8_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_4x8_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x8_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x8_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_rl_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_one_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_rl_one_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_ru_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_one_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nn_ru_one_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x8_tran_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x8_tran_vs_lib4c4c(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int ldd, int m1, int n1); +// 4x4 +void kernel_dgemm_nn_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dsyrk_nt_l_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dsyrk_nt_l_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dger2k_nt_4x4_lib4ccc(int kmax, double *alpha, double *A0, double *B0, int ldb0, double *A1, double *B1, int ldb1, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dger2k_nt_4x4_vs_lib4ccc(int kmax, double *alpha, double *A0, double *B0, int ldb0, double *A1, double *B1, int ldb1, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_rl_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nn_rl_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_one_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_rl_one_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_rl_one_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nn_rl_one_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_ru_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nn_ru_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_one_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nn_ru_one_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nn_ru_one_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nn_ru_one_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_rl_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_rl_one_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_rl_one_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_ru_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x4_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x4_vs_lib4ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dtrmm_nt_ru_one_4x4_tran_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd); +void kernel_dtrmm_nt_ru_one_4x4_tran_vs_lib4c4c(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, double *D, int ldd, int m1, int n1); +void kernel_dtrsm_nn_ll_inv_4x4_lib4ccc4(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *inv_diag_E); +void kernel_dtrsm_nn_ll_inv_4x4_vs_lib4ccc4(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, double *inv_diag_E, int km, int kn); +void kernel_dtrsm_nn_ll_one_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_ll_one_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_rl_inv_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_rl_inv_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_rl_one_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_rl_one_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nt_rl_one_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_ru_inv_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_ru_inv_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_ru_one_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nn_ru_one_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_ru_inv_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_4x4_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde); +void kernel_dtrsm_nt_ru_one_4x4_vs_lib4cccc(int kmax, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, double *E, int lde, int m1, int n1); +void kernel_dgetrf_nn_4x4_lib4ccc(int kmax, double *A, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag); +void kernel_dgetrf_nn_4x4_vs_lib4ccc(int kmax, double *A, double *B, int ldb, double *C, int ldc, double *D, int ldd, double *diag, int m1, int n1); + +// B panel-major bs=4; A, C, D column-major +// 12x4 +void kernel_dgemm_nt_12x4_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_12x4_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_12x4_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_12x4_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 4x12 +void kernel_dgemm_nt_4x12_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x12_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_4x12_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_4x12_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 8x4 +void kernel_dgemm_nt_8x4_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x4_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_8x4_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_8x4_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 4x8 +void kernel_dgemm_nt_4x8_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x8_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_4x8_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_4x8_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 4x4 +void kernel_dgemm_nt_4x4_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x4_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_4x4_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_4x4_vs_libc4cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); + +// A, C, D panel-major; B, E column-major +// TODO merge with above +// 12x4 +void kernel_dtrsm_nn_rl_inv_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_rl_inv_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_rl_one_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nn_rl_one_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_ru_inv_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_ru_inv_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_ru_one_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nn_ru_one_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nt_rl_one_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_ru_inv_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_12x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nt_ru_one_12x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +// 8x4 +void kernel_dtrsm_nn_rl_inv_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_rl_inv_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_rl_one_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nn_rl_one_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_ru_inv_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nn_ru_inv_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_ru_one_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nn_ru_one_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nt_rl_one_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE); +void kernel_dtrsm_nt_ru_inv_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_8x4_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde); +void kernel_dtrsm_nt_ru_one_8x4_vs_lib4c44c(int kmax, double *A, int sda, double *B, int ldb, double *beta, double *C, int sdc, double *D, int sdd, double *E, int lde, int m1, int n1); +// 4x4 +void kernel_dtrsm_nn_rl_inv_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE); +void kernel_dtrsm_nn_rl_inv_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_rl_one_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde); +void kernel_dtrsm_nn_rl_one_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nn_ru_inv_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE); +void kernel_dtrsm_nn_ru_inv_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nn_ru_one_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde); +void kernel_dtrsm_nn_ru_one_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_rl_inv_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE); +void kernel_dtrsm_nt_rl_inv_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_rl_one_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde); +void kernel_dtrsm_nt_rl_one_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, int m1, int n1); +void kernel_dtrsm_nt_ru_inv_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE); +void kernel_dtrsm_nt_ru_inv_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, double *dE, int m1, int n1); +void kernel_dtrsm_nt_ru_one_4x4_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde); +void kernel_dtrsm_nt_ru_one_4x4_vs_lib4c44c(int kmax, double *A, double *B, int ldb, double *beta, double *C, double *D, double *E, int lde, int m1, int n1); + +// A, B, C, D column-major +// 12x4 +void kernel_dgemm_nn_12x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_12x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_12x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_12x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_12x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_12x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 4x12 +void kernel_dgemm_nn_4x12_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_4x12_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x12_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x12_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_4x12_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_4x12_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 8x4 +void kernel_dgemm_nn_8x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_8x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_8x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_8x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_8x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 4x8 +void kernel_dgemm_nn_4x8_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_4x8_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x8_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x8_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_4x8_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_4x8_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 4x4 +void kernel_dgemm_nn_4x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_4x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nt_4x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_4x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_4x4_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_4x4_vs_libcccc(int kmax, double *alpha, double *A, int lda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); + +// A column-major +// 12 +void kernel_dgetrf_pivot_12_lib(int m, double *pA, int lda, double *inv_diag_A, int* ipiv); +void kernel_dgetrf_pivot_12_vs_lib(int m, double *pA, int lda, double *inv_diag_A, int* ipiv, int n); +// 8 +void kernel_dgetrf_pivot_8_lib(int m, double *pA, int lda, double *inv_diag_A, int* ipiv); +void kernel_dgetrf_pivot_8_vs_lib(int m, double *pA, int lda, double *inv_diag_A, int* ipiv, int n); +// 4 +void kernel_dgetrf_pivot_4_lib(int m, double *pA, int lda, double *inv_diag_A, int* ipiv); +void kernel_dgetrf_pivot_4_vs_lib(int m, double *pA, int lda, double *inv_diag_A, int* ipiv, int n); + +// vector +void kernel_ddot_11_lib(int n, double *x, double *y, double *res); +void kernel_daxpy_11_lib(int n, double *alpha, double *x, double *y); +void kernel_drowsw_lib(int kmax, double *pA, int lda, double *pC, int ldc); + +//#endif // BLAS_API + + + +// larger kernels +// 12 +void kernel_dgemm_nt_12xn_p0_lib44cc(int n, int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, double *A_p, double *B_p); +void kernel_dgemm_nt_12xn_pl_lib44cc(int n, int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, double *A_p, double *B_p); +void kernel_dgemm_nt_mx12_p0_lib44cc(int m, int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, double *A_p, double *B_p); +// 8 +void kernel_dgemm_nt_8xn_p0_lib44cc(int n, int k, double *alpha, double *A, int sda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, double *A_p, double *B_p); + + + +// A, B panel-major bs=8; C, D column-major +// 24x8 +void kernel_dgemm_nt_24x8_lib88cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_24x8_vs_lib88cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 16x8 +void kernel_dgemm_nt_16x8_lib88cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_16x8_vs_lib88cc(int kmax, double *alpha, double *A, int sda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 8x8 +void kernel_dgemm_nt_8x8_lib88cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x8_vs_lib88cc(int kmax, double *alpha, double *A, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); + +// A, panel-major bs=8; B, C, D column-major +// 24x8 +void kernel_dgemm_nt_24x8_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_24x8_vs_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nn_24x8_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_24x8_vs_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 16x8 +void kernel_dgemm_nt_16x8_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_16x8_vs_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nn_16x8_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_16x8_vs_lib8ccc(int kmax, double *alpha, double *A, int sda, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 8x8 +void kernel_dgemm_nt_8x8_lib8ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x8_vs_lib8ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_nn_8x8_lib8ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nn_8x8_vs_lib8ccc(int kmax, double *alpha, double *A, double *B, int ldb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); + +// B, panel-major bs=8; A, C, D column-major +// 8x24 +void kernel_dgemm_nt_8x24_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x24_vs_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_8x24_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_8x24_vs_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 8x16 +void kernel_dgemm_nt_8x16_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x16_vs_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_8x16_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_8x16_vs_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, int sdb, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +// 8x8 +void kernel_dgemm_nt_8x8_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_nt_8x8_vs_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); +void kernel_dgemm_tt_8x8_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd); +void kernel_dgemm_tt_8x8_vs_libc8cc(int kmax, double *alpha, double *A, int lda, double *B, double *beta, double *C, int ldc, double *D, int ldd, int m1, int n1); + + +// level 2 BLAS +void kernel_dgemv_n_4_libc(int kmax, double *alpha, double *A, int lda, double *x, double *z); +void kernel_dgemv_n_4_vs_libc(int kmax, double *alpha, double *A, int lda, double *x, double *z, int km); +void kernel_dgemv_t_4_libc(int kmax, double *alpha, double *A, int lda, double *x, double *beta, double *y, double *z); +void kernel_dgemv_t_4_vs_libc(int kmax, double *alpha, double *A, int lda, double *x, double *beta, double *y, double *z, int km); +void kernel_dsymv_l_4_libc(int kmax, double *alpha, double *A, int lda, double *x, double *z); +void kernel_dsymv_l_4_vs_libc(int kmax, double *alpha, double *A, int lda, double *x, double *z, int km); +void kernel_dsymv_u_4_libc(int kmax, double *alpha, double *A, int lda, double *x, double *z); +void kernel_dsymv_u_4_vs_libc(int kmax, double *alpha, double *A, int lda, double *x, double *z, int km); +void kernel_dger_4_libc(int kmax, double *alpha, double *x, double *y, double *C, int ldc, double *D, int ldd); +void kernel_dger_4_vs_libc(int kmax, double *alpha, double *x, double *y, double *C, int ldc, double *D, int ldd, int km); + + + +// aux +void kernel_dvecld_inc1(int kmax, double *x); +void kernel_dveccp_inc1(int kmax, double *x, double *y); + +//void kernel_dgetr_nt_8_p0_lib(int kmax, double *A, int lda, double *C, int ldc, double *Ap, double *Bp); +//void kernel_dgetr_nt_8_lib(int kmax, double *A, int lda, double *C, int ldc); +//void kernel_dgetr_nt_4_lib(int kmax, double *A, int lda, double *C, int ldc); +void kernel_dgetr_tn_8_p0_lib(int kmax, double *A, int lda, double *C, int ldc, double *Ap, double *Bp); +void kernel_dgetr_tn_8_lib(int kmax, double *A, int lda, double *C, int ldc); +void kernel_dgetr_tn_4_lib(int kmax, double *A, int lda, double *C, int ldc); +void kernel_dgetr_tn_4_vs_lib(int kmax, double *A, int lda, double *C, int ldc, int m1); + + +// building blocks for blocked algorithms +// +void blasfeo_hp_dgemm_nt_m2(int m, int n, int k, double alpha, double *pA, int sda, double *pB, int sdb, double beta, double *C, int ldc, double *D, int ldd); +void blasfeo_hp_dgemm_nt_n2(int m, int n, int k, double alpha, double *pA, int sda, double *pB, int sdb, double beta, double *C, int ldc, double *D, int ldd); +// +void kernel_dpack_buffer_fn(int m, int n, double *A, int lda, double *pA, int sda); +void kernel_dpack_buffer_ft(int m, int n, double *A, int lda, double *pA, int sda); +void kernel_dpack_buffer_ln(int m, double *A, int lda, double *pA, int sda); +void kernel_dpack_buffer_lt(int m, double *A, int lda, double *pA, int sda); +void kernel_dpack_buffer_ut(int m, double *A, int lda, double *pA, int sda); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_D_KERNEL_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_i_aux_ext_dep.h b/third_party/acados/include/blasfeo/include/blasfeo_i_aux_ext_dep.h new file mode 100644 index 0000000000..74c3fb5c0a --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_i_aux_ext_dep.h @@ -0,0 +1,69 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_I_AUX_EXT_DEP_H_ +#define BLASFEO_I_AUX_EXT_DEP_H_ + + + +#include "blasfeo_target.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef EXT_DEP + +// i_aux_extern_depend_lib +void int_zeros(int **pA, int row, int col); +void int_zeros_align(int **pA, int row, int col); +void int_free(int *pA); +void int_free_align(int *pA); +void int_print_mat(int row, int col, int *A, int lda); +int int_print_to_string_mat(char **buf_out, int row, int col, int *A, int lda); + +#endif // EXT_DEP + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_I_AUX_EXT_DEP_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_m_aux.h b/third_party/acados/include/blasfeo/include/blasfeo_m_aux.h new file mode 100644 index 0000000000..6248853e29 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_m_aux.h @@ -0,0 +1,57 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_M_AUX_H_ +#define BLASFEO_M_AUX_H_ + +#include "blasfeo_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +void blasfeo_cvt_d2s_vec(int m, struct blasfeo_dvec *vd, int vdi, struct blasfeo_svec *vs, int vsi); +void blasfeo_cvt_s2d_vec(int m, struct blasfeo_svec *vs, int vsi, struct blasfeo_dvec *vd, int vdi); +void blasfeo_cvt_d2s_mat(int m, int n, struct blasfeo_dmat *Md, int mid, int nid, struct blasfeo_smat *Ms, int mis, int nis); +void blasfeo_cvt_s2d_mat(int m, int n, struct blasfeo_smat *Ms, int mis, int nis, struct blasfeo_dmat *Md, int mid, int nid); + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_M_AUX_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_memory.h b/third_party/acados/include/blasfeo/include/blasfeo_memory.h new file mode 100644 index 0000000000..da4e7fa090 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_memory.h @@ -0,0 +1,62 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2020 by Gianluca Frison. * +* All rights reserved. * +* * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + +#ifndef BLASFEO_MEMORY_H_ +#define BLASFEO_MEMORY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +int blasfeo_is_init(); +// +void blasfeo_init(); +// +void blasfeo_quit(); +// +void *blasfeo_get_buffer(); + + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_MEMORY_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_naming.h b/third_party/acados/include/blasfeo/include/blasfeo_naming.h new file mode 100644 index 0000000000..c289443b17 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_naming.h @@ -0,0 +1,77 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + +/* + * ----------- Naming conventions + * + * (precision)(data) + * + * 1) d(double) + * s(single) + * + * 2) ge(general) + * tr(triangular) + * vec(vector) + * row(row) + * col(column) + * dia(diagonal) + * + * 3) se(set) + * cp(copy) + * sc(scale) + * ad(add) + * tr(transpose) + * in(insert) + * ex(extract) + * pe(premute) + * sw(swap) + * + * f(factorization) + * + * lqf(LQ factorization) + * qrf (factorization) + * trf (LU factorization using partial pivoting with row interchanges.) + * + * 4) _l(lower) / _u(upper) + * _lib8 (hp implementation, 8 rows kernel) + * _lib4 (hp implementation, 4 rows kernel) + * _lib0 (hp interface with reference implentation) + * _lib (reference implementation) + * _libref (reference implementation with dedicated namespace) + * + * 5) _sp(sparse) + * _exp(exponential format) + */ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_processor_features.h b/third_party/acados/include/blasfeo/include/blasfeo_processor_features.h new file mode 100644 index 0000000000..67a0a4da04 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_processor_features.h @@ -0,0 +1,88 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Ian McInerney * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_PROCESSOR_FEATURES_H_ +#define BLASFEO_PROCESSOR_FEATURES_H_ + +/** + * Flags to indicate the different processor features + */ +//enum +//{ +// // x86-64 CPU features +// BLASFEO_PROCESSOR_FEATURE_AVX = 0x0001, /// AVX instruction set +// BLASFEO_PROCESSOR_FEATURE_AVX2 = 0x0002, /// AVX2 instruction set +// BLASFEO_PROCESSOR_FEATURE_FMA = 0x0004, /// FMA instruction set +// BLASFEO_PROCESSOR_FEATURE_SSE3 = 0x0008, /// SSE3 instruction set +// +// // ARM CPU features +// BLASFEO_PROCESSOR_FEATURE_VFPv3 = 0x0100, /// VFPv3 instruction set +// BLASFEO_PROCESSOR_FEATURE_NEON = 0x0100, /// NEON instruction set +// BLASFEO_PROCESSOR_FEATURE_VFPv4 = 0x0100, /// VFPv4 instruction set +// BLASFEO_PROCESSOR_FEATURE_NEONv2 = 0x0100, /// NEONv2 instruction set +//} BLASFEO_PROCESSOR_FEATURES; + +/** + * Test the features that this processor provides against what the library was compiled with. + * + * @param features - Pointer to an integer to store the supported feature set (using the flags in the BLASFEO_PROCESSOR_FEATURES enum) + * @return 0 if current processor doesn't support all features required for this library, 1 otherwise + */ +int blasfeo_processor_cpu_features( int* features ); + +/** + * Test the features that this processor provides against what the library was compiled with. + * + * @param features - Pointer to an integer to store the supported feature set (using the flags in the BLASFEO_PROCESSOR_FEATURES enum) + * @return 0 if current processor doesn't support all features required for this library, 1 otherwise + */ +void blasfeo_processor_library_features( int* features ); + +/** + * Create a string listing the features the current processor supports. + * + * @param features - Flags from the BLASFEO_PROCESSOR_FEATURES enum indicating the features supported + * @param featureString - Character array to store the feature string in + */ +void blasfeo_processor_feature_string( int features, char* featureString ); + +/** + * Get a string listing the processor features that this library version needs to run. + * + * @param featureString - Character array to store the feature string in + */ +void blasfeo_processor_library_string( char* featureString ); + +#endif // BLASFEO_PROCESSOR_FEATURES_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_aux.h b/third_party/acados/include/blasfeo/include/blasfeo_s_aux.h new file mode 100644 index 0000000000..f43f5e83ce --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_aux.h @@ -0,0 +1,168 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_AUX_H_ +#define BLASFEO_S_AUX_H_ + + + +#include + +#include "blasfeo_s_aux_old.h" +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************ +* d_aux_lib.c +************************************************/ + +// returns the memory size (in bytes) needed for a smat +size_t blasfeo_memsize_smat(int m, int n); +size_t blasfeo_memsize_smat_ps(int ps, int m, int n); +// returns the memory size (in bytes) needed for the diagonal of a smat +size_t blasfeo_memsize_diag_smat(int m, int n); +// returns the memory size (in bytes) needed for a svec +size_t blasfeo_memsize_svec(int m); +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_create_smat(int m, int n, struct blasfeo_smat *sA, void *memory); +void blasfeo_create_smat_ps(int ps, int m, int n, struct blasfeo_smat *sA, void *memory); +// create a strvec for a vector of size m by using memory passed by a pointer (pointer is not updated) +void blasfeo_create_svec(int m, struct blasfeo_svec *sA, void *memory); +void blasfeo_pack_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_pack_l_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_pack_u_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_pack_tran_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_pack_svec(int m, float *x, int xi, struct blasfeo_svec *sa, int ai); +void blasfeo_unpack_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj, float *A, int lda); +void blasfeo_unpack_tran_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj, float *A, int lda); +void blasfeo_unpack_svec(int m, struct blasfeo_svec *sa, int ai, float *x, int xi); +//void s_cast_mat2strmat(float *A, struct blasfeo_smat *sA); +//void s_cast_diag_mat2strmat(float *dA, struct blasfeo_smat *sA); +//void s_cast_vec2vecmat(float *a, struct blasfeo_svec *sa); + +// ge +void blasfeo_sgese(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_sgecpsc(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_sgecp(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_sgesc(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_sgein1(float a, struct blasfeo_smat *sA, int ai, int aj); +float blasfeo_sgeex1(struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_sgead(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_sgetr(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// tr +void blasfeo_strcp_l(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_strtr_l(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_strtr_u(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// dia +void blasfeo_sdiare(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_sdiaex(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +void blasfeo_sdiain(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_sdiain_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_sdiaex_sp(int kmax, float alpha, int *idx, struct blasfeo_smat *sD, int di, int dj, struct blasfeo_svec *sx, int xi); +void blasfeo_sdiaad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_sdiaad_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_sdiaadin_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, int *idx, struct blasfeo_smat *sD, int di, int dj); +// row +void blasfeo_srowin(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_srowex(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +void blasfeo_srowad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_srowad_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_srowsw(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_srowpe(int kmax, int *ipiv, struct blasfeo_smat *sA); +void blasfeo_srowpei(int kmax, int *ipiv, struct blasfeo_smat *sA); +// col +void blasfeo_scolex(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +void blasfeo_scolin(int kmax, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_scolad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_scolsc(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_scolsw(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_scolpe(int kmax, int *ipiv, struct blasfeo_smat *sA); +void blasfeo_scolpei(int kmax, int *ipiv, struct blasfeo_smat *sA); +// vec +void blasfeo_svecse(int m, float alpha, struct blasfeo_svec *sx, int xi); +void blasfeo_sveccp(int m, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +void blasfeo_svecsc(int m, float alpha, struct blasfeo_svec *sa, int ai); +void blasfeo_sveccpsc(int m, float alpha, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +void blasfeo_svecad(int m, float alpha, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +void blasfeo_svecin1(float a, struct blasfeo_svec *sx, int xi); +float blasfeo_svecex1(struct blasfeo_svec *sx, int xi); +void blasfeo_svecad_sp(int m, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_svec *sz, int zi); +void blasfeo_svecin_sp(int m, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_svec *sz, int zi); +void blasfeo_svecex_sp(int m, float alpha, int *idx, struct blasfeo_svec *sx, int x, struct blasfeo_svec *sz, int zi); +// z += alpha * x[idx] +void blasfeo_svecexad_sp(int m, double alpha, int *idx, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +void blasfeo_sveccl(int m, struct blasfeo_svec *sxm, int xim, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sxp, int xip, struct blasfeo_svec *sz, int zi); +void blasfeo_sveccl_mask(int m, struct blasfeo_svec *sxm, int xim, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sxp, int xip, struct blasfeo_svec *sz, int zi, struct blasfeo_svec *sm, int mi); +void blasfeo_svecze(int m, struct blasfeo_svec *sm, int mi, struct blasfeo_svec *sv, int vi, struct blasfeo_svec *se, int ei); +void blasfeo_svecnrm_inf(int m, struct blasfeo_svec *sx, int xi, float *ptr_norm); +void blasfeo_svecnrm_2(int m, struct blasfeo_svec *sx, int xi, float *ptr_norm); +void blasfeo_svecpe(int kmax, int *ipiv, struct blasfeo_svec *sx, int xi); +void blasfeo_svecpei(int kmax, int *ipiv, struct blasfeo_svec *sx, int xi); + + + +/* +* Explicitly panel-major matrix format +*/ + +// returns the memory size (in bytes) needed for a dmat +size_t blasfeo_pm_memsize_smat(int ps, int m, int n); +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_pm_create_smat(int ps, int m, int n, struct blasfeo_pm_smat *sA, void *memory); + + + +/* +* Explicitly column-major matrix format +*/ + +// returns the memory size (in bytes) needed for a dmat +size_t blasfeo_cm_memsize_smat(int m, int n); +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_cm_create_smat(int m, int n, struct blasfeo_pm_smat *sA, void *memory); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_AUX_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ext_dep.h b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ext_dep.h new file mode 100644 index 0000000000..5209d20d37 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ext_dep.h @@ -0,0 +1,141 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_AUX_EXT_DEP_H_ +#define BLASFEO_S_AUX_EXT_DEP_H_ + + + +#include + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef EXT_DEP + +/************************************************ +* s_aux_extern_depend_lib.c +************************************************/ + +/* column-major matrices */ + +// dynamically allocate row*col floats of memory and set accordingly a pointer to float; set allocated memory to zero +void s_zeros(float **pA, int row, int col); +// dynamically allocate row*col floats of memory aligned to 64-byte boundaries and set accordingly a pointer to float; set allocated memory to zero +void s_zeros_align(float **pA, int row, int col); +// dynamically allocate size bytes of memory aligned to 64-byte boundaries and set accordingly a pointer to float; set allocated memory to zero +void s_zeros_align_bytes(float **pA, int size); +// free the memory allocated by d_zeros +void s_free(float *pA); +// free the memory allocated by d_zeros_align or d_zeros_align_bytes +void s_free_align(float *pA); +// print a column-major matrix +void s_print_mat(int m, int n, float *A, int lda); +// print the transposed of a column-major matrix +void s_print_tran_mat(int row, int col, float *A, int lda); +// print to file a column-major matrix +void s_print_to_file_mat(FILE *file, int row, int col, float *A, int lda); +// print to file a column-major matrix in exponential format +void s_print_to_file_exp_mat(FILE *file, int row, int col, float *A, int lda); +// print to string a column-major matrix +void s_print_to_string_mat(char **buf_out, int row, int col, float *A, int lda); +// print to file the transposed of a column-major matrix +void s_print_tran_to_file_mat(FILE *file, int row, int col, float *A, int lda); +// print to file the transposed of a column-major matrix in exponential format +void s_print_tran_to_file_exp_mat(FILE *file, int row, int col, float *A, int lda); +// print in exponential notation a column-major matrix +void s_print_exp_mat(int m, int n, float *A, int lda); +// print in exponential notation the transposed of a column-major matrix +void s_print_exp_tran_mat(int row, int col, float *A, int lda); + +/* strmat and strvec */ + +// create a strmat for a matrix of size m*n by dynamically allocating memory +void blasfeo_allocate_smat(int m, int n, struct blasfeo_smat *sA); +// create a strvec for a vector of size m by dynamically allocating memory +void blasfeo_allocate_svec(int m, struct blasfeo_svec *sa); +// free the memory allocated by blasfeo_allocate_dmat +void blasfeo_free_smat(struct blasfeo_smat *sA); +// free the memory allocated by blasfeo_allocate_dvec +void blasfeo_free_svec(struct blasfeo_svec *sa); +// print a strmat +void blasfeo_print_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj); +// print in exponential notation a strmat +void blasfeo_print_exp_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj); +// print to file a strmat +void blasfeo_print_to_file_smat(FILE *file, int m, int n, struct blasfeo_smat *sA, int ai, int aj); +// print to file a strmat in exponential format +void blasfeo_print_to_file_exp_smat(FILE *file, int m, int n, struct blasfeo_smat *sA, int ai, int aj); +// print to string a strmat +void blasfeo_print_to_string_smat(char **buf_out, int m, int n, struct blasfeo_smat *sA, int ai, int aj); +// print the transpose of a strmat +void blasfeo_print_tran_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj); +// print a strvec +void blasfeo_print_svec(int m, struct blasfeo_svec *sa, int ai); +// print in exponential notation a strvec +void blasfeo_print_exp_svec(int m, struct blasfeo_svec *sa, int ai); +// print to file a strvec +void blasfeo_print_to_file_svec(FILE *file, int m, struct blasfeo_svec *sa, int ai); +// print to string a strvec +void blasfeo_print_to_string_svec(char **buf_out, int m, struct blasfeo_svec *sa, int ai); +// print the transposed of a strvec +void blasfeo_print_tran_svec(int m, struct blasfeo_svec *sa, int ai); +// print in exponential notation the transposed of a strvec +void blasfeo_print_exp_tran_svec(int m, struct blasfeo_svec *sa, int ai); +// print to file the transposed of a strvec +void blasfeo_print_to_file_tran_svec(FILE *file, int m, struct blasfeo_svec *sa, int ai); +// print to string the transposed of a strvec +void blasfeo_print_to_string_tran_svec(char **buf_out, int m, struct blasfeo_svec *sa, int ai); + +#endif // EXT_DEP + + + +#ifdef __cplusplus +} +#endif + + + +#endif // BLASFEO_S_AUX_EXT_DEP_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ext_dep_ref.h b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ext_dep_ref.h new file mode 100644 index 0000000000..6640e20a40 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ext_dep_ref.h @@ -0,0 +1,82 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_AUX_EXT_DEP_REF_H_ +#define BLASFEO_S_AUX_EXT_DEP_REF_H_ + +#if defined(EXT_DEP) + + + +#include + +#include "blasfeo_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// expose reference BLASFEO for testing +// see blasfeo_s_aux_exp_dep.h for help + +void blasfeo_print_smat_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj); +void blasfeo_allocate_smat_ref(int m, int n, struct blasfeo_smat_ref *sA); +void blasfeo_allocate_svec_ref(int m, struct blasfeo_svec_ref *sa); +void blasfeo_free_smat_ref(struct blasfeo_smat_ref *sA); +void blasfeo_free_svec_ref(struct blasfeo_svec_ref *sa); +void blasfeo_print_smat_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj); +void blasfeo_print_exp_smat_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj); +void blasfeo_print_to_file_smat_ref(FILE *file, int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj); +void blasfeo_print_to_file_exp_smat_ref(FILE *file, int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj); +void blasfeo_print_to_string_smat_ref(char **buf_out, int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj); +void blasfeo_print_svec(int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_exp_svec(int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_to_file_svec(FILE *file, int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_to_string_svec(char **buf_out, int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_tran_svec(int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_exp_tran_svec(int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_to_file_tran_svec(FILE *file, int m, struct blasfeo_svec *sa, int ai); +void blasfeo_print_to_string_tran_svec(char **buf_out, int m, struct blasfeo_svec *sa, int ai); + + +#ifdef __cplusplus +} +#endif + + + +#endif // EXT_DEP + +#endif // BLASFEO_S_AUX_EXT_DEP_REF_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_aux_old.h b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_old.h new file mode 100644 index 0000000000..5c6db37bab --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_old.h @@ -0,0 +1,64 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +// TODO remove +// +void strcp_l_lib(int m, float alpha, int offsetA, float *A, int sda, int offsetB, float *B, int sdb); +void sgead_lib(int m, int n, float alpha, int offsetA, float *A, int sda, int offsetB, float *B, int sdb); +void sgetr_lib(int m, int n, float alpha, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +void strtr_l_lib(int m, float alpha, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +void strtr_u_lib(int m, float alpha, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +void sdiareg_lib(int kmax, float reg, int offset, float *pD, int sdd); +void sdiain_sqrt_lib(int kmax, float *x, int offset, float *pD, int sdd); +void sdiaex_lib(int kmax, float alpha, int offset, float *pD, int sdd, float *x); +void sdiaad_lib(int kmax, float alpha, float *x, int offset, float *pD, int sdd); +void sdiain_libsp(int kmax, int *idx, float alpha, float *x, float *pD, int sdd); +void sdiaex_libsp(int kmax, int *idx, float alpha, float *pD, int sdd, float *x); +void sdiaad_libsp(int kmax, int *idx, float alpha, float *x, float *pD, int sdd); +void sdiaadin_libsp(int kmax, int *idx, float alpha, float *x, float *y, float *pD, int sdd); +void srowin_lib(int kmax, float alpha, float *x, float *pD); +void srowex_lib(int kmax, float alpha, float *pD, float *x); +void srowad_lib(int kmax, float alpha, float *x, float *pD); +void srowin_libsp(int kmax, float alpha, int *idx, float *x, float *pD); +void srowad_libsp(int kmax, int *idx, float alpha, float *x, float *pD); +void srowadin_libsp(int kmax, int *idx, float alpha, float *x, float *y, float *pD); +void srowsw_lib(int kmax, float *pA, float *pC); +void scolin_lib(int kmax, float *x, int offset, float *pD, int sdd); +void scolad_lib(int kmax, float alpha, float *x, int offset, float *pD, int sdd); +void scolin_libsp(int kmax, int *idx, float *x, float *pD, int sdd); +void scolad_libsp(int kmax, float alpha, int *idx, float *x, float *pD, int sdd); +void scolsw_lib(int kmax, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +void svecin_libsp(int kmax, int *idx, float *x, float *y); +void svecad_libsp(int kmax, int *idx, float alpha, float *x, float *y); diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ref.h b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ref.h new file mode 100644 index 0000000000..998e1d8999 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_ref.h @@ -0,0 +1,147 @@ + +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_AUX_REF_H_ +#define BLASFEO_S_AUX_REF_H_ + + + +#include + +#include "blasfeo_s_aux_old.h" +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************ +* d_aux_lib.c +************************************************/ + +// returns the memory size (in bytes) needed for a smat +size_t blasfeo_ref_memsize_smat(int m, int n); +size_t blasfeo_ref_memsize_smat_ps(int ps, int m, int n); +// returns the memory size (in bytes) needed for the diagonal of a smat +size_t blasfeo_ref_memsize_diag_smat(int m, int n); +// returns the memory size (in bytes) needed for a svec +size_t blasfeo_ref_memsize_svec(int m); +// create a strmat for a matrix of size m*n by using memory passed by a pointer (pointer is not updated) +void blasfeo_ref_create_smat(int m, int n, struct blasfeo_smat *sA, void *memory); +void blasfeo_ref_create_smat_ps(int ps, int m, int n, struct blasfeo_smat *sA, void *memory); +// create a strvec for a vector of size m by using memory passed by a pointer (pointer is not updated) +void blasfeo_ref_create_svec(int m, struct blasfeo_svec *sA, void *memory); +void blasfeo_ref_pack_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_pack_l_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sB, int bi, int bj); +void blasfeo_ref_pack_l_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sB, int bi, int bj); +void blasfeo_ref_pack_tran_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_pack_svec(int m, float *x, int xi, struct blasfeo_svec *sa, int ai); +void blasfeo_ref_unpack_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj, float *A, int lda); +void blasfeo_ref_unpack_tran_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj, float *A, int lda); +void blasfeo_ref_unpack_svec(int m, struct blasfeo_svec *sa, int ai, float *x, int xi); +void ref_s_cast_mat2strmat(float *A, struct blasfeo_smat *sA); +void ref_s_cast_diag_mat2strmat(float *dA, struct blasfeo_smat *sA); +void ref_s_cast_vec2vecmat(float *a, struct blasfeo_svec *sa); + +// ge +void blasfeo_ref_sgese(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_sgecpsc(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_sgecp(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_sgesc(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_sgein1(float a, struct blasfeo_smat *sA, int ai, int aj); +float blasfeo_ref_sgeex1(struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_sgead(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_sgetr(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// tr +void blasfeo_ref_strcp_l(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_strtr_l(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_strtr_u(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// dia +void blasfeo_ref_sdiare(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_sdiaex(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +void blasfeo_ref_sdiain(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_sdiain_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ref_sdiaex_sp(int kmax, float alpha, int *idx, struct blasfeo_smat *sD, int di, int dj, struct blasfeo_svec *sx, int xi); +void blasfeo_ref_sdiaad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_sdiaad_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ref_sdiaadin_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, int *idx, struct blasfeo_smat *sD, int di, int dj); +// row +void blasfeo_ref_srowin(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_srowex(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +void blasfeo_ref_srowad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_srowad_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ref_srowsw(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_srowpe(int kmax, int *ipiv, struct blasfeo_smat *sA); +void blasfeo_ref_srowpei(int kmax, int *ipiv, struct blasfeo_smat *sA); +// col +void blasfeo_ref_scolex(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +void blasfeo_ref_scolin(int kmax, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_scolad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_scolsc(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj); +void blasfeo_ref_scolsw(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void blasfeo_ref_scolpe(int kmax, int *ipiv, struct blasfeo_smat *sA); +void blasfeo_ref_scolpei(int kmax, int *ipiv, struct blasfeo_smat *sA); +// vec +void blasfeo_ref_svecse(int m, float alpha, struct blasfeo_svec *sx, int xi); +void blasfeo_ref_sveccp(int m, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +void blasfeo_ref_svecsc(int m, float alpha, struct blasfeo_svec *sa, int ai); +void blasfeo_ref_sveccpsc(int m, float alpha, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +void blasfeo_ref_svecad(int m, float alpha, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +void blasfeo_ref_svecin1(float a, struct blasfeo_svec *sx, int xi); +float blasfeo_ref_svecex1(struct blasfeo_svec *sx, int xi); +void blasfeo_ref_svecad_sp(int m, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_svec *sz, int zi); +void blasfeo_ref_svecin_sp(int m, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_svec *sz, int zi); +void blasfeo_ref_svecex_sp(int m, float alpha, int *idx, struct blasfeo_svec *sx, int x, struct blasfeo_svec *sz, int zi); +// z += alpha * x[idx] +void blasfeo_ref_svecexad_sp(int m, double alpha, int *idx, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +void blasfeo_ref_sveccl(int m, struct blasfeo_svec *sxm, int xim, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sxp, int xip, struct blasfeo_svec *sz, int zi); +void blasfeo_ref_sveccl_mask(int m, struct blasfeo_svec *sxm, int xim, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sxp, int xip, struct blasfeo_svec *sz, int zi, struct blasfeo_svec *sm, int mi); +void blasfeo_ref_svecze(int m, struct blasfeo_svec *sm, int mi, struct blasfeo_svec *sv, int vi, struct blasfeo_svec *se, int ei); +void blasfeo_ref_svecnrm_inf(int m, struct blasfeo_svec *sx, int xi, float *ptr_norm); +void blasfeo_ref_svecpe(int kmax, int *ipiv, struct blasfeo_svec *sx, int xi); +void blasfeo_ref_svecpei(int kmax, int *ipiv, struct blasfeo_svec *sx, int xi); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_AUX_REF_H_ + diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_aux_test.h b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_test.h new file mode 100644 index 0000000000..08d9a14a6a --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_aux_test.h @@ -0,0 +1,177 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_AUX_TEST_H_ +#define BLASFEO_S_AUX_TEST_H_ + +#include + +#include "blasfeo_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/************************************************ +* d_aux_lib.c +************************************************/ + +int test_blasfeo_memsize_smat(int m, int n); +int test_blasfeo_memsize_diag_smat(int m, int n); +int test_blasfeo_memsize_svec(int m); + +void test_blasfeo_create_smat(int m, int n, struct blasfeo_smat *sA, void *memory); +void test_blasfeo_create_svec(int m, struct blasfeo_svec *sA, void *memory); + +void test_blasfeo_pack_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void test_blasfeo_pack_svec(int m, float *x, int xi, struct blasfeo_svec *sa, int ai); +void test_blasfeo_pack_tran_smat(int m, int n, float *A, int lda, struct blasfeo_smat *sA, int ai, int aj); +void test_blasfeo_unpack_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj, float *A, int lda); +void test_blasfeo_unpack_svec(int m, struct blasfeo_svec *sa, int ai, float *x, int xi); +void test_blasfeo_unpack_tran_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj, float *A, int lda); + +void test_s_cast_mat2strmat(float *A, struct blasfeo_smat *sA); +void test_s_cast_diag_mat2strmat(float *dA, struct blasfeo_smat *sA); +void test_s_cast_vec2vecmat(float *a, struct blasfeo_svec *sa); +// copy and scale +void test_blasfeo_sgecpsc(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void test_blasfeo_sgecp(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +void test_blasfeo_sgesc(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj); + +// void test_blasfeo_sgein1(float a, struct blasfeo_smat *sA, int ai, int aj); +// float test_blasfeo_sgeex1(struct blasfeo_smat *sA, int ai, int aj); +// void test_blasfeo_svecin1(float a, struct blasfeo_svec *sx, int xi); +// float test_blasfeo_svecex1(struct blasfeo_svec *sx, int xi); + +// // A <= alpha +// void test_blasfeo_sgese(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj); +// // a <= alpha +// void test_blasfeo_svecse(int m, float alpha, struct blasfeo_svec *sx, int xi); + + +// void test_blasfeo_sveccp(int m, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); +// void test_blasfeo_svecsc(int m, float alpha, struct blasfeo_svec *sa, int ai); + +// void test_strcp_l_lib(int m, float alpha, int offsetA, float *A, int sda, int offsetB, float *B, int sdb); +// void test_blasfeo_strcp_l(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); + +// void test_sgead_lib(int m, int n, float alpha, int offsetA, float *A, int sda, int offsetB, float *B, int sdb); +// void test_blasfeo_sgead(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// void test_blasfeo_svecad(int m, float alpha, struct blasfeo_svec *sa, int ai, struct blasfeo_svec *sc, int ci); + +// void test_sgetr_lib(int m, int n, float alpha, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +// void test_blasfeo_sgetr(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); + +// void test_strtr_l_lib(int m, float alpha, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +// void test_blasfeo_strtr_l(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// void test_strtr_u_lib(int m, float alpha, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +// void test_blasfeo_strtr_u(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); + +// void test_sdiareg_lib(int kmax, float reg, int offset, float *pD, int sdd); +// void test_blasfeo_sdiaex(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +// void test_blasfeo_sdiain(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +// void test_sdiain_sqrt_lib(int kmax, float *x, int offset, float *pD, int sdd); +// void test_sdiaex_lib(int kmax, float alpha, int offset, float *pD, int sdd, float *x); +// void test_sdiaad_lib(int kmax, float alpha, float *x, int offset, float *pD, int sdd); +// void test_sdiain_libsp(int kmax, int *idx, float alpha, float *x, float *pD, int sdd); +// void test_blasfeo_sdiain_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +// void test_sdiaex_libsp(int kmax, int *idx, float alpha, float *pD, int sdd, float *x); +// void test_blasfeo_sdiaex_sp(int kmax, float alpha, int *idx, struct blasfeo_smat *sD, int di, int dj, struct blasfeo_svec *sx, int xi); +// void test_blasfeo_sdiaad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +// void test_sdiaad_libsp(int kmax, int *idx, float alpha, float *x, float *pD, int sdd); +// void test_blasfeo_sdiaad_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +// void test_sdiaadin_libsp(int kmax, int *idx, float alpha, float *x, float *y, float *pD, int sdd); +// void test_blasfeo_sdiaadin_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, int *idx, struct blasfeo_smat *sD, int di, int dj); +// void test_srowin_lib(int kmax, float alpha, float *x, float *pD); +// void test_blasfeo_srowin(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +// void test_srowex_lib(int kmax, float alpha, float *pD, float *x); +// void test_blasfeo_srowex(int kmax, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi); +// void test_srowad_lib(int kmax, float alpha, float *x, float *pD); +// void test_blasfeo_srowad(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +// void test_srowin_libsp(int kmax, float alpha, int *idx, float *x, float *pD); +// void test_srowad_libsp(int kmax, int *idx, float alpha, float *x, float *pD); +// void test_blasfeo_srowad_sp(int kmax, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_smat *sD, int di, int dj); +// void test_srowadin_libsp(int kmax, int *idx, float alpha, float *x, float *y, float *pD); +// void test_srowsw_lib(int kmax, float *pA, float *pC); +// void test_blasfeo_srowsw(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// void test_blasfeo_srowpe(int kmax, int *ipiv, struct blasfeo_smat *sA); +// void test_scolin_lib(int kmax, float *x, int offset, float *pD, int sdd); +// void test_blasfeo_scolin(int kmax, struct blasfeo_svec *sx, int xi, struct blasfeo_smat *sA, int ai, int aj); +// void test_scolad_lib(int kmax, float alpha, float *x, int offset, float *pD, int sdd); +// void test_scolin_libsp(int kmax, int *idx, float *x, float *pD, int sdd); +// void test_scolad_libsp(int kmax, float alpha, int *idx, float *x, float *pD, int sdd); +// void test_scolsw_lib(int kmax, int offsetA, float *pA, int sda, int offsetC, float *pC, int sdc); +// void test_blasfeo_scolsw(int kmax, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sC, int ci, int cj); +// void test_blasfeo_scolpe(int kmax, int *ipiv, struct blasfeo_smat *sA); +// void test_svecin_libsp(int kmax, int *idx, float *x, float *y); +// void test_svecad_libsp(int kmax, int *idx, float alpha, float *x, float *y); +// void test_blasfeo_svecad_sp(int m, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_svec *sz, int zi); +// void test_blasfeo_svecin_sp(int m, float alpha, struct blasfeo_svec *sx, int xi, int *idx, struct blasfeo_svec *sz, int zi); +// void test_blasfeo_svecex_sp(int m, float alpha, int *idx, struct blasfeo_svec *sx, int x, struct blasfeo_svec *sz, int zi); +// void test_blasfeo_sveccl(int m, struct blasfeo_svec *sxm, int xim, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sxp, int xip, struct blasfeo_svec *sz, int zi); +// void test_blasfeo_sveccl_mask(int m, struct blasfeo_svec *sxm, int xim, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sxp, int xip, struct blasfeo_svec *sz, int zi, struct blasfeo_svec *sm, int mi); +// void test_blasfeo_svecze(int m, struct blasfeo_svec *sm, int mi, struct blasfeo_svec *sv, int vi, struct blasfeo_svec *se, int ei); +// void test_blasfeo_svecnrm_inf(int m, struct blasfeo_svec *sx, int xi, float *ptr_norm); +// void test_blasfeo_svecpe(int kmax, int *ipiv, struct blasfeo_svec *sx, int xi); + + +// ext_dep + +void test_blasfeo_allocate_smat(int m, int n, struct blasfeo_smat *sA); +void test_blasfeo_allocate_svec(int m, struct blasfeo_svec *sa); + +void test_blasfeo_free_smat(struct blasfeo_smat *sA); +void test_blasfeo_free_svec(struct blasfeo_svec *sa); + +void test_blasfeo_print_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj); +void test_blasfeo_print_svec(int m, struct blasfeo_svec *sa, int ai); +void test_blasfeo_print_tran_svec(int m, struct blasfeo_svec *sa, int ai); + +void test_blasfeo_print_to_file_smat(FILE *file, int m, int n, struct blasfeo_smat *sA, int ai, int aj); +void test_blasfeo_print_to_file_svec(FILE *file, int m, struct blasfeo_svec *sa, int ai); +void test_blasfeo_print_to_file_tran_svec(FILE *file, int m, struct blasfeo_svec *sa, int ai); + +void test_blasfeo_print_exp_smat(int m, int n, struct blasfeo_smat *sA, int ai, int aj); +void test_blasfeo_print_exp_svec(int m, struct blasfeo_svec *sa, int ai); +void test_blasfeo_print_exp_tran_svec(int m, struct blasfeo_svec *sa, int ai); + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_AUX_TEST_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_blas.h b/third_party/acados/include/blasfeo/include/blasfeo_s_blas.h new file mode 100644 index 0000000000..200f1f51b1 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_blas.h @@ -0,0 +1,46 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_BLAS_H_ +#define BLASFEO_S_BLAS_H_ + + + +#include "blasfeo_s_blasfeo_api.h" +#include "blasfeo_s_blas_api.h" + + + +#endif // BLASFEO_S_BLAS_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_blas_api.h b/third_party/acados/include/blasfeo/include/blasfeo_s_blas_api.h new file mode 100644 index 0000000000..cf2b3e0a2d --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_blas_api.h @@ -0,0 +1,182 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef BLASFEO_S_BLAS_API_H_ +#define BLASFEO_S_BLAS_API_H_ + + + +#include "blasfeo_target.h" + + + +#ifdef BLAS_API +#ifdef CBLAS_API +#ifndef BLASFEO_CBLAS_ENUM +#define BLASFEO_CBLAS_ENUM +#ifdef FORTRAN_BLAS_API +#ifndef CBLAS_H +enum CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; +enum CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; +enum CBLAS_UPLO {CblasUpper=121, CblasLower=122}; +enum CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; +enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; +#endif // CBLAS_H +#else // FORTRAN_BLAS_API +enum BLASFEO_CBLAS_ORDER {CblasRowMajor=101, CblasColMajor=102}; +enum BLASFEO_CBLAS_TRANSPOSE {CblasNoTrans=111, CblasTrans=112, CblasConjTrans=113}; +enum BLASFEO_CBLAS_UPLO {CblasUpper=121, CblasLower=122}; +enum BLASFEO_CBLAS_DIAG {CblasNonUnit=131, CblasUnit=132}; +enum BLASFEO_CBLAS_SIDE {CblasLeft=141, CblasRight=142}; +#endif // FORTRAN_BLAS_API +#endif // BLASFEO_CBLAS_ENUM +#endif // CBLAS_API +#endif // BLAS_API + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#ifdef BLAS_API + + + +#ifdef FORTRAN_BLAS_API + + + +// BLAS 1 +// +void saxpy_(int *n, float *alpha, float *x, int *incx, float *y, int *incy); +// +float sdot_(int *n, float *x, int *incx, float *y, int *incy); + +// BLAS 3 +// +void sgemm_(char *ta, char *tb, int *m, int *n, int *k, float *alpha, float *A, int *lda, float *B, int *ldb, float *beta, float *C, int *ldc); +// +void strsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *A, int *lda, float *B, int *ldb); + + + +// LAPACK +// +void spotrf_(char *uplo, int *m, float *A, int *lda, int *info); + + + +#ifdef CBLAS_API + + + +// CBLAS 1 +// +void cblas_saxpy(const int N, const float alpha, const float *X, const int incX, float *Y, const int incY); + +// CBLAS 3 +// +void cblas_sgemm(const enum CBLAS_ORDER Order, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *C, const int ldc); +// +void cblas_strsm(const enum CBLAS_ORDER Order, const enum CBLAS_SIDE Side, const enum CBLAS_UPLO Uplo, const enum CBLAS_TRANSPOSE TransA, const enum CBLAS_DIAG Diag, const int M, const int N, const float alpha, const float *A, const int lda, float *B, const int ldb); + + + +#endif // CBLAS_API + + + +#else // BLASFEO_API + + + +// BLAS 1 +// +void blasfeo_blas_saxpy(int *n, float *alpha, float *x, int *incx, float *y, int *incy); +// +float blasfeo_blas_sdot(int *n, float *x, int *incx, float *y, int *incy); + +// BLAS 3 +// +void blasfeo_blas_sgemm(char *ta, char *tb, int *m, int *n, int *k, float *alpha, float *A, int *lda, float *B, int *ldb, float *beta, float *C, int *ldc); +// +void blasfeo_blas_strsm(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *A, int *lda, float *B, int *ldb); + + + +// LAPACK +// +void blasfeo_lapack_spotrf(char *uplo, int *m, float *A, int *lda, int *info); + + + +#ifdef CBLAS_API + + + +// CBLAS 1 +// +void blasfeo_cblas_saxpy(const int N, const float alpha, const float *X, const int incX, float *Y, const int incY); + +// CBLAS 3 +// +void blasfeo_cblas_sgemm(const enum BLASFEO_CBLAS_ORDER Order, const enum BLASFEO_CBLAS_TRANSPOSE TransA, const enum BLASFEO_CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float *A, const int lda, const float *B, const int ldb, const float beta, float *C, const int ldc); +// +void blasfeo_cblas_strsm(const enum BLASFEO_CBLAS_ORDER Order, const enum BLASFEO_CBLAS_SIDE Side, const enum BLASFEO_CBLAS_UPLO Uplo, const enum BLASFEO_CBLAS_TRANSPOSE TransA, const enum BLASFEO_CBLAS_DIAG Diag, const int M, const int N, const float alpha, const float *A, const int lda, float *B, const int ldb); + + + +#endif // CBLAS_API + + + +#endif // BLASFEO_API + + + +#endif // BLAS_API + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_BLAS_API_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_api.h b/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_api.h new file mode 100644 index 0000000000..8b98104735 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_api.h @@ -0,0 +1,284 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_BLASFEO_API_H_ +#define BLASFEO_S_BLASFEO_API_H_ + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +// +// level 1 BLAS +// + +// z = y + alpha*x +void blasfeo_saxpy(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z = beta*y + alpha*x +void blasfeo_saxpby(int kmax, float alpha, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z = x .* y +void blasfeo_svecmul(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z += x .* y +void blasfeo_svecmulacc(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z = x .* y, return sum(z) = x^T * y +float blasfeo_svecmuldot(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// return x^T * y +float blasfeo_sdot(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi); +// construct givens plane rotation +void blasfeo_srotg(float a, float b, float *c, float *s); +// apply plane rotation [a b] [c -s; s; c] to the aj0 and aj1 columns of A at row index ai +void blasfeo_scolrot(int m, struct blasfeo_smat *sA, int ai, int aj0, int aj1, float c, float s); +// apply plane rotation [c s; -s c] [a; b] to the ai0 and ai1 rows of A at column index aj +void blasfeo_srowrot(int m, struct blasfeo_smat *sA, int ai0, int ai1, int aj, float c, float s); + + + +// +// level 2 BLAS +// + +// dense + +// z <= beta * y + alpha * A * x +void blasfeo_sgemv_n(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z <= beta * y + alpha * A' * x +void blasfeo_sgemv_t(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z <= inv( A ) * x, A (m)x(n) +void blasfeo_strsv_lnn_mn(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(n) +void blasfeo_strsv_ltn_mn(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, not_unit +void blasfeo_strsv_lnn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, unit +void blasfeo_strsv_lnu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) lower, transposed, not_unit +void blasfeo_strsv_ltn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) lower, transposed, unit +void blasfeo_strsv_ltu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) upper, not_transposed, not_unit +void blasfeo_strsv_unn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) upper, transposed, not_unit +void blasfeo_strsv_utn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A * x ; A lower triangular +void blasfeo_strmv_lnn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A * x ; A lower triangular, unit diagonal +void blasfeo_strmv_lnu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A' * x ; A lower triangular +void blasfeo_strmv_ltn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A' * x ; A lower triangular, unit diagonal +void blasfeo_strmv_ltu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= beta * y + alpha * A * x ; A upper triangular +void blasfeo_strmv_unn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A' * x ; A upper triangular +void blasfeo_strmv_utn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z_n <= beta_n * y_n + alpha_n * A * x_n +// z_t <= beta_t * y_t + alpha_t * A' * x_t +void blasfeo_sgemv_nt(int m, int n, float alpha_n, float alpha_t, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx_n, int xi_n, struct blasfeo_svec *sx_t, int xi_t, float beta_n, float beta_t, struct blasfeo_svec *sy_n, int yi_n, struct blasfeo_svec *sy_t, int yi_t, struct blasfeo_svec *sz_n, int zi_n, struct blasfeo_svec *sz_t, int zi_t); +// z <= beta * y + alpha * A * x, where A is symmetric and only the lower triangular patr of A is accessed +void blasfeo_ssymv_l(int m, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +void blasfeo_ssymv_l_mn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z <= beta * y + alpha * A * x, where A is symmetric and only the upper triangular patr of A is accessed +void blasfeo_ssymv_u(int m, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// D = C + alpha * x * y^T +void blasfeo_sger(int m, int n, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); + +// diagonal + +// z <= beta * y + alpha * A * x, A diagonal +void blasfeo_sgemv_d(int m, float alpha, struct blasfeo_svec *sA, int ai, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); + + + +// +// level 3 BLAS +// + +// dense + +// D <= beta * C + alpha * A * B +void blasfeo_sgemm_nn(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T +void blasfeo_sgemm_nt(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B +void blasfeo_sgemm_tn(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B +void blasfeo_sgemm_tt(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D lower triangular +void blasfeo_ssyrk_ln(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ssyrk_ln_mn(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B ; C, D lower triangular +void blasfeo_ssyrk_lt(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D upper triangular +void blasfeo_ssyrk_un(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B ; C, D upper triangular +void blasfeo_ssyrk_ut(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^T ; B upper triangular +void blasfeo_strmm_rutn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A ; A lower triangular +void blasfeo_strmm_rlnn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular employint explicit inverse of diagonal +void blasfeo_strsm_llnn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular with unit diagonal +void blasfeo_strsm_llnu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular employint explicit inverse of diagonal +void blasfeo_strsm_lltn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular with unit diagonal +void blasfeo_strsm_lltu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_strsm_lunn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular withunit diagonal +void blasfeo_strsm_lunu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_strsm_lutn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular withunit diagonal +void blasfeo_strsm_lutu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_strsm_rlnn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular with unit diagonal +void blasfeo_strsm_rlnu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_strsm_rltn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular with unit diagonal +void blasfeo_strsm_rltu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_strsm_runn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular with unit diagonal +void blasfeo_strsm_runu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_strsm_rutn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular with unit diagonal +void blasfeo_strsm_rutu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T; C, D lower triangular +void blasfeo_ssyr2k_ln(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A; C, D lower triangular +void blasfeo_ssyr2k_lt(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T; C, D upper triangular +void blasfeo_ssyr2k_un(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A; C, D upper triangular +void blasfeo_ssyr2k_ut(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); + +// diagonal + +// D <= alpha * A * B + beta * C, with A diagonal (stored as strvec) +void sgemm_diag_left_ib(int m, int n, float alpha, float *dA, float *pB, int sdb, float beta, float *pC, int sdc, float *pD, int sdd); +void blasfeo_sgemm_dn(int m, int n, float alpha, struct blasfeo_svec *sA, int ai, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A * B + beta * C, with B diagonal (stored as strvec) +void blasfeo_sgemm_nd(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sB, int bi, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); + + + +// +// LAPACK +// + +// D <= chol( C ) ; C, D lower triangular +void blasfeo_spotrf_l(int m, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_spotrf_l_mn(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= chol( C ) ; C, D upper triangular +void blasfeo_spotrf_u(int m, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= chol( C + A * B' ) ; C, D lower triangular +void blasfeo_ssyrk_spotrf_ln(int m, int k, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ssyrk_spotrf_ln_mn(int m, int n, int k, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= lu( C ) ; no pivoting +void blasfeo_sgetrf_np(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= lu( C ) ; row pivoting +void blasfeo_sgetrf_rp(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, int *ipiv); +// D <= qr( C ) +void blasfeo_sgeqrf(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +int blasfeo_sgeqrf_worksize(int m, int n); // in bytes +// D <= Q factor, where C is the output of the LQ factorization +int blasfeo_sorglq_worksize(int m, int n, int k); // in bytes +void blasfeo_sorglq(int m, int n, int k, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +// D <= lq( C ) +void blasfeo_sgelqf(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +int blasfeo_sgelqf_worksize(int m, int n); // in bytes +// D <= lq( C ), positive diagonal elements +void blasfeo_sgelqf_pd(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +// [L, A] <= lq( [L, A] ), positive diagonal elements, array of matrices, with +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_sgelqf_pd_la(int m, int n1, struct blasfeo_smat *sL, int li, int lj, struct blasfeo_smat *sA, int ai, int aj, void *work); +// [L, L, A] <= lq( [L, L, A] ), positive diagonal elements, array of matrices, with: +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_sgelqf_pd_lla(int m, int n1, struct blasfeo_smat *sL0, int l0i, int l0j, struct blasfeo_smat *sL1, int l1i, int l1j, struct blasfeo_smat *sA, int ai, int aj, void *work); + + + + +// +// BLAS API helper functions +// + +#if ( defined(BLAS_API) & defined(MF_PANELMAJ) ) +// BLAS 3 +void blasfeo_cm_sgemm_nn(int m, int n, int k, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, float beta, struct blasfeo_cm_smat *sC, int ci, int cj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_sgemm_nt(int m, int n, int k, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, float beta, struct blasfeo_cm_smat *sC, int ci, int cj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_sgemm_tn(int m, int n, int k, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, float beta, struct blasfeo_cm_smat *sC, int ci, int cj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_sgemm_tt(int m, int n, int k, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, float beta, struct blasfeo_cm_smat *sC, int ci, int cj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_llnn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_llnu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_lltn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_lltu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_lunn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_lunu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_lutn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_lutu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_rlnn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_rlnu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_rltn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_rltu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_runn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_runu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_rutn(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_strsm_rutu(int m, int n, float alpha, struct blasfeo_cm_smat *sA, int ai, int aj, struct blasfeo_cm_smat *sB, int bi, int bj, struct blasfeo_cm_smat *sD, int di, int dj); +// LAPACK +void blasfeo_cm_spotrf_l(int m, struct blasfeo_cm_smat *sC, int ci, int cj, struct blasfeo_cm_smat *sD, int di, int dj); +void blasfeo_cm_spotrf_u(int m, struct blasfeo_cm_smat *sC, int ci, int cj, struct blasfeo_cm_smat *sD, int di, int dj); +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_BLASFEO_API_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_api_ref.h b/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_api_ref.h new file mode 100644 index 0000000000..f429a79dc3 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_api_ref.h @@ -0,0 +1,135 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_BLASFEO_API_REF_H_ +#define BLASFEO_S_BLASFEO_API_REF_H_ + +#include "blasfeo_common.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +// expose reference BLASFEO for testing + +// --- level 1 + +void blasfeo_saxpy_ref(int kmax, float alpha, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_saxpby_ref(int kmax, float alpha, struct blasfeo_svec_ref *sx, int xi, float beta, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_svecmul_ref(int m, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_svecmulacc_ref(int m, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +float blasfeo_svecmuldot_ref(int m, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +float blasfeo_sdot_ref(int m, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sy, int yi); +void blasfeo_srotg_ref(float a, float b, float *c, float *s); +void blasfeo_scolrot_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj0, int aj1, float c, float s); +void blasfeo_srowrot_ref(int m, struct blasfeo_smat_ref *sA, int ai0, int ai1, int aj, float c, float s); + + +// --- level 2 + +// dense +void blasfeo_sgemv_n_ref(int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, float beta, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_sgemv_t_ref(int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, float beta, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_lnn_mn_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_ltn_mn_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_lnn_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_lnu_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_ltn_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_ltu_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_unn_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strsv_utn_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strmv_unn_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strmv_utn_ref(int m, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strmv_lnn_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strmv_ltn_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strmv_lnu_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_strmv_ltu_ref(int m, int n, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, struct blasfeo_svec_ref *sz, int zi); +void blasfeo_sgemv_nt_ref(int m, int n, float alpha_n, float alpha_t, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx_n, int xi_n, struct blasfeo_svec_ref *sx_t, int xi_t, float beta_n, float beta_t, struct blasfeo_svec_ref *sy_n, int yi_n, struct blasfeo_svec_ref *sy_t, int yi_t, struct blasfeo_svec_ref *sz_n, int zi_n, struct blasfeo_svec_ref *sz_t, int zi_t); +void blasfeo_ssymv_l_ref(int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sx, int xi, float beta, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); + +// diagonal +void blasfeo_sgemv_d_ref(int m, float alpha, struct blasfeo_svec_ref *sA, int ai, struct blasfeo_svec_ref *sx, int xi, float beta, struct blasfeo_svec_ref *sy, int yi, struct blasfeo_svec_ref *sz, int zi); + + +// --- level 3 + +// dense +void blasfeo_sgemm_nn_ref( int m, int n, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgemm_nt_ref( int m, int n, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgemm_tn_ref(int m, int n, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgemm_tt_ref(int m, int n, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); + +void blasfeo_ssyrk_ln_mn_ref( int m, int n, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_ssyrk_ln_ref( int m, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_ssyrk_lt_ref( int m, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_ssyrk_un_ref( int m, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_ssyrk_ut_ref( int m, int k, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); + +void blasfeo_strmm_rutn_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_strmm_rlnn_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_strsm_rltn_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_strsm_rltu_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_strsm_rutn_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_strsm_llnu_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_strsm_lunn_ref( int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sD, int di, int dj); + +// diagonal +void dgemm_diag_left_lib_ref(int m, int n, float alpha, float *dA, float *pB, int sdb, float beta, float *pC, int sdc, float *pD, int sdd); +void blasfeo_sgemm_dn_ref(int m, int n, float alpha, struct blasfeo_svec_ref *sA, int ai, struct blasfeo_smat_ref *sB, int bi, int bj, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgemm_nd_ref(int m, int n, float alpha, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_svec_ref *sB, int bi, float beta, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); + +// --- lapack + +void blasfeo_sgetrf_nopivot_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgetrf_rowpivot_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj, int *ipiv); +void blasfeo_spotrf_l_ref(int m, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_spotrf_l_mn_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_ssyrk_dpotrf_ln_ref(int m, int k, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_ssyrk_dpotrf_ln_mn_ref(int m, int n, int k, struct blasfeo_smat_ref *sA, int ai, int aj, struct blasfeo_smat_ref *sB, int bi, int bj, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgetrf_nopivot_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj); +void blasfeo_sgetrf_rowpivot_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj, int *ipiv); +void blasfeo_sgeqrf_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj, void *work); +void blasfeo_sgelqf_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj, void *work); +void blasfeo_sgelqf_pd_ref(int m, int n, struct blasfeo_smat_ref *sC, int ci, int cj, struct blasfeo_smat_ref *sD, int di, int dj, void *work); +void blasfeo_sgelqf_pd_la_ref(int m, int n1, struct blasfeo_smat_ref *sL, int li, int lj, struct blasfeo_smat_ref *sA, int ai, int aj, void *work); +void blasfeo_sgelqf_pd_lla_ref(int m, int n1, struct blasfeo_smat_ref *sL0, int l0i, int l0j, struct blasfeo_smat_ref *sL1, int l1i, int l1j, struct blasfeo_smat_ref *sA, int ai, int aj, void *work); + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_BLASFEO_API_REF_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_ref_api.h b/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_ref_api.h new file mode 100644 index 0000000000..17cb179695 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_blasfeo_ref_api.h @@ -0,0 +1,252 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_BLASFEO_REF_API_H_ +#define BLASFEO_S_BLASFEO_REF_API_H_ + + + +#include "blasfeo_common.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +// +// level 1 BLAS +// + +// z = y + alpha*x +void blasfeo_ref_saxpy(int kmax, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z = beta*y + alpha*x +void blasfeo_ref_saxpby(int kmax, float alpha, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z = x .* y +void blasfeo_ref_svecmul(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z += x .* y +void blasfeo_ref_svecmulacc(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z = x .* y, return sum(z) = x^T * y +float blasfeo_ref_svecmuldot(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// return x^T * y +float blasfeo_ref_sdot(int m, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi); +// construct givens plane rotation +void blasfeo_ref_srotg(float a, float b, float *c, float *s); +// apply plane rotation [a b] [c -s; s; c] to the aj0 and aj1 columns of A at row index ai +void blasfeo_ref_scolrot(int m, struct blasfeo_smat *sA, int ai, int aj0, int aj1, float c, float s); +// apply plane rotation [c s; -s c] [a; b] to the ai0 and ai1 rows of A at column index aj +void blasfeo_ref_srowrot(int m, struct blasfeo_smat *sA, int ai0, int ai1, int aj, float c, float s); + + + +// +// level 2 BLAS +// + +// dense + +// z <= beta * y + alpha * A * x +void blasfeo_ref_sgemv_n(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z <= beta * y + alpha * A' * x +void blasfeo_ref_sgemv_t(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z <= inv( A ) * x, A (m)x(n) +void blasfeo_ref_strsv_lnn_mn(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(n) +void blasfeo_ref_strsv_ltn_mn(int m, int n, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, not_unit +void blasfeo_ref_strsv_lnn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A ) * x, A (m)x(m) lower, not_transposed, unit +void blasfeo_ref_strsv_lnu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) lower, transposed, not_unit +void blasfeo_ref_strsv_ltn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) lower, transposed, unit +void blasfeo_ref_strsv_ltu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) upper, not_transposed, not_unit +void blasfeo_ref_strsv_unn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= inv( A' ) * x, A (m)x(m) upper, transposed, not_unit +void blasfeo_ref_strsv_utn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A * x ; A lower triangular +void blasfeo_ref_strmv_lnn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A * x ; A lower triangular, unit diagonal +void blasfeo_ref_strmv_lnu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A' * x ; A lower triangular +void blasfeo_ref_strmv_ltn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A' * x ; A lower triangular, unit diagonal +void blasfeo_ref_strmv_ltu(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= beta * y + alpha * A * x ; A upper triangular +void blasfeo_ref_strmv_unn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z <= A' * x ; A upper triangular +void blasfeo_ref_strmv_utn(int m, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sz, int zi); +// z_n <= beta_n * y_n + alpha_n * A * x_n +// z_t <= beta_t * y_t + alpha_t * A' * x_t +void blasfeo_ref_sgemv_nt(int m, int n, float alpha_n, float alpha_t, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx_n, int xi_n, struct blasfeo_svec *sx_t, int xi_t, float beta_n, float beta_t, struct blasfeo_svec *sy_n, int yi_n, struct blasfeo_svec *sy_t, int yi_t, struct blasfeo_svec *sz_n, int zi_n, struct blasfeo_svec *sz_t, int zi_t); +// z <= beta * y + alpha * A * x, where A is symmetric and only the lower triangular patr of A is accessed +void blasfeo_ref_ssymv_l(int m, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +void blasfeo_ref_ssymv_l_mn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// z <= beta * y + alpha * A * x, where A is symmetric and only the upper triangular patr of A is accessed +void blasfeo_ref_ssymv_u(int m, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); +// D = C + alpha * x * y^T +void blasfeo_ref_sger(int m, int n, float alpha, struct blasfeo_svec *sx, int xi, struct blasfeo_svec *sy, int yi, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); + +// diagonal + +// z <= beta * y + alpha * A * x, A diagonal +void blasfeo_ref_sgemv_d(int m, float alpha, struct blasfeo_svec *sA, int ai, struct blasfeo_svec *sx, int xi, float beta, struct blasfeo_svec *sy, int yi, struct blasfeo_svec *sz, int zi); + + + +// +// level 3 BLAS +// + +// dense + +// D <= beta * C + alpha * A * B +void blasfeo_ref_sgemm_nn(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T +void blasfeo_ref_sgemm_nt(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B +void blasfeo_ref_sgemm_tn(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B +void blasfeo_ref_sgemm_tt(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D lower triangular +void blasfeo_ref_ssyrk_ln(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ref_ssyrk_ln_mn(int m, int n, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B ; C, D lower triangular +void blasfeo_ref_ssyrk_lt(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T ; C, D upper triangular +void blasfeo_ref_ssyrk_un(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B ; C, D upper triangular +void blasfeo_ref_ssyrk_ut(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^T ; B upper triangular +void blasfeo_ref_strmm_rutn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A ; A lower triangular +void blasfeo_ref_strmm_rlnn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular employint explicit inverse of diagonal +void blasfeo_ref_strsm_llnn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A lower triangular with unit diagonal +void blasfeo_ref_strsm_llnu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular employint explicit inverse of diagonal +void blasfeo_ref_strsm_lltn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A lower triangular with unit diagonal +void blasfeo_ref_strsm_lltu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_strsm_lunn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-1} * B , with A upper triangular withunit diagonal +void blasfeo_ref_strsm_lunu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_strsm_lutn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A^{-T} * B , with A upper triangular withunit diagonal +void blasfeo_ref_strsm_lutu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_ref_strsm_rlnn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A lower triangular with unit diagonal +void blasfeo_ref_strsm_rlnu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular employing explicit inverse of diagonal +void blasfeo_ref_strsm_rltn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A lower triangular with unit diagonal +void blasfeo_ref_strsm_rltu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_strsm_runn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-1} , with A upper triangular with unit diagonal +void blasfeo_ref_strsm_runu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular employing explicit inverse of diagonal +void blasfeo_ref_strsm_rutn(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * B * A^{-T} , with A upper triangular with unit diagonal +void blasfeo_ref_strsm_rutu(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T ; C, D lower triangular +void blasfeo_ref_ssyr2k_ln(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A ; C, D lower triangular +void blasfeo_ref_ssyr2k_lt(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A * B^T + alpha * B * A^T ; C, D upper triangular +void blasfeo_ref_ssyr2k_un(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= beta * C + alpha * A^T * B + alpha * B^T * A ; C, D upper triangular +void blasfeo_ref_ssyr2k_ut(int m, int k, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); + +// diagonal + +// D <= alpha * A * B + beta * C, with A diagonal (stored as strvec) +void sgemm_diag_left_ib(int m, int n, float alpha, float *dA, float *pB, int sdb, float beta, float *pC, int sdc, float *pD, int sdd); +void blasfeo_ref_sgemm_dn(int m, int n, float alpha, struct blasfeo_svec *sA, int ai, struct blasfeo_smat *sB, int bi, int bj, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= alpha * A * B + beta * C, with B diagonal (stored as strvec) +void blasfeo_ref_sgemm_nd(int m, int n, float alpha, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_svec *sB, int bi, float beta, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); + + + +// +// LAPACK +// + +// D <= chol( C ) ; C, D lower triangular +void blasfeo_ref_spotrf_l(int m, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ref_spotrf_l_mn(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= chol( C ) ; C, D upper triangular +void blasfeo_ref_spotrf_u(int m, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= chol( C + A * B' ) ; C, D lower triangular +void blasfeo_ref_ssyrk_spotrf_ln(int m, int k, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +void blasfeo_ref_ssyrk_spotrf_ln_mn(int m, int n, int k, struct blasfeo_smat *sA, int ai, int aj, struct blasfeo_smat *sB, int bi, int bj, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= lu( C ) ; no pivoting +void blasfeo_ref_sgetrf_np(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj); +// D <= lu( C ) ; row pivoting +void blasfeo_ref_sgetrf_rp(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, int *ipiv); +// D <= qr( C ) +void blasfeo_ref_sgeqrf(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +int blasfeo_ref_sgeqrf_worksize(int m, int n); // in bytes +// D <= Q factor, where C is the output of the LQ factorization +int blasfeo_ref_sorglq_worksize(int m, int n, int k); // in bytes +void blasfeo_ref_sorglq(int m, int n, int k, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +// D <= lq( C ) +void blasfeo_ref_sgelqf(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +int blasfeo_ref_sgelqf_worksize(int m, int n); // in bytes +// D <= lq( C ), positive diagonal elements +void blasfeo_ref_sgelqf_pd(int m, int n, struct blasfeo_smat *sC, int ci, int cj, struct blasfeo_smat *sD, int di, int dj, void *work); +// [L, A] <= lq( [L, A] ), positive diagonal elements, array of matrices, with +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_ref_sgelqf_pd_la(int m, int n1, struct blasfeo_smat *sL, int li, int lj, struct blasfeo_smat *sA, int ai, int aj, void *work); +// [L, L, A] <= lq( [L, L, A] ), positive diagonal elements, array of matrices, with: +// L lower triangular, of size (m)x(m) +// A full, of size (m)x(n1) +void blasfeo_ref_sgelqf_pd_lla(int m, int n1, struct blasfeo_smat *sL0, int l0i, int l0j, struct blasfeo_smat *sL1, int l1i, int l1j, struct blasfeo_smat *sA, int ai, int aj, void *work); + + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_BLASFEO_REF_API_H_ + diff --git a/third_party/acados/include/blasfeo/include/blasfeo_s_kernel.h b/third_party/acados/include/blasfeo/include/blasfeo_s_kernel.h new file mode 100644 index 0000000000..99d2b28c82 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_s_kernel.h @@ -0,0 +1,692 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_S_KERNEL_H_ +#define BLASFEO_S_KERNEL_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// utils +void blasfeo_align_2MB(void *ptr, void **ptr_align); +void blasfeo_align_4096_byte(void *ptr, void **ptr_align); +void blasfeo_align_64_byte(void *ptr, void **ptr_align); + + + +// +// lib8 +// + +// 24x4 +void kernel_sgemm_nt_24x4_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_nt_24x4_vs_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_sgemm_nt_24x4_gen_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_sgemm_nn_24x4_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_nn_24x4_vs_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_sgemm_nn_24x4_gen_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_ssyrk_nt_l_24x4_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_ssyrk_nt_l_24x4_vs_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_ssyrk_nt_l_20x4_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_ssyrk_nt_l_20x4_vs_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_spotrf_nt_l_24x4_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_24x4_vs_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_spotrf_nt_l_20x4_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_20x4_vs_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_strsm_nt_rl_inv_24x4_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_24x4_vs_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int km, int kn); +void kernel_sgemm_strsm_nt_rl_inv_24x4_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_sgemm_strsm_nt_rl_inv_24x4_vs_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_20x4_vs_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_20x4_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_ssyrk_spotrf_nt_l_24x4_vs_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_24x4_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_strmm_nn_rl_24x4_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *D, int sdd); +void kernel_strmm_nn_rl_24x4_vs_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *D, int sdd, int km, int kn); + +// 16x8 +void kernel_sgemm_nt_16x8_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *spil); + +// 16x4 +void kernel_sgemm_nt_16x4_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_nt_16x4_vs_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_sgemm_nt_16x4_gen_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_sgemm_nn_16x4_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_nn_16x4_vs_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_sgemm_nn_16x4_gen_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_ssyrk_nt_l_16x4_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_ssyrk_nt_l_16x4_vs_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_ssyrk_nt_l_12x4_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_ssyrk_nt_l_12x4_vs_lib8(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); +void kernel_spotrf_nt_l_16x4_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_16x4_vs_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_spotrf_nt_l_12x4_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_12x4_vs_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_strsm_nt_rl_inv_16x4_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_16x4_vs_lib8(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int km, int kn); +void kernel_sgemm_strsm_nt_rl_inv_16x4_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_sgemm_strsm_nt_rl_inv_16x4_vs_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_12x4_vs_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_12x4_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_ssyrk_spotrf_nt_l_16x4_vs_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_16x4_lib8(int kp, float *Ap, int sdap, float *Bp, int km_, float *Am, int sdam, float *Bm, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_strmm_nn_rl_16x4_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *D, int sdd); +void kernel_strmm_nn_rl_16x4_vs_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *D, int sdd, int km, int kn); +void kernel_strmm_nn_rl_16x4_gen_lib8(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); + +// 8x8 +void kernel_sgemm_nt_8x8_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_sgemm_nt_8x8_vs_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); +void kernel_sgemm_nt_8x8_gen_lib8(int k, float *alpha, float *A, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_sgemm_nn_8x8_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, float *C, float *D); +void kernel_sgemm_nn_8x8_vs_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, float *C, float *D, int km, int kn); +void kernel_sgemm_nn_8x8_gen_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_ssyrk_nt_l_8x8_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_ssyrk_nt_l_8x8_vs_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); +void kernel_spotrf_nt_l_8x8_lib8(int k, float *A, float *B, float *C, float *D, float *inv_diag_D); +void kernel_spotrf_nt_l_8x8_vs_lib8(int k, float *A, float *B, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_strsm_nt_rl_inv_8x8_lib8(int k, float *A, float *B, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_8x8_vs_lib8(int k, float *A, float *B, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_sgemm_strsm_nt_rl_inv_8x8_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *E, float *inv_diag_E); +void kernel_sgemm_strsm_nt_rl_inv_8x8_vs_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_8x8_vs_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_8x8_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *inv_diag_D); + +// 8x4 +void kernel_sgemm_nt_8x4_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_sgemm_nt_8x4_vs_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); +void kernel_sgemm_nt_8x4_gen_lib8(int k, float *alpha, float *A, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_sgemm_nn_8x4_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, float *C, float *D); +void kernel_sgemm_nn_8x4_vs_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, float *C, float *D, int km, int kn); +void kernel_sgemm_nn_8x4_gen_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +//void kernel_ssyrk_nt_l_8x4_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_ssyrk_nt_l_8x4_vs_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); +void kernel_spotrf_nt_l_8x4_lib8(int k, float *A, float *B, float *C, float *D, float *inv_diag_D); +void kernel_spotrf_nt_l_8x4_vs_lib8(int k, float *A, float *B, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_strsm_nt_rl_inv_8x4_lib8(int k, float *A, float *B, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_8x4_vs_lib8(int k, float *A, float *B, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_sgemm_strsm_nt_rl_inv_8x4_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *E, float *inv_diag_E); +void kernel_sgemm_strsm_nt_rl_inv_8x4_vs_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_8x4_vs_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_8x4_lib8(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *inv_diag_D); +void kernel_strmm_nn_rl_8x4_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *D); +void kernel_strmm_nn_rl_8x4_vs_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *D, int km, int kn); +void kernel_strmm_nn_rl_8x4_gen_lib8(int k, float *alpha, float *A, int offsetB, float *B, int sdb, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_strmm_nt_ru_8x4_lib8(int k, float *alpha, float *A, float *B, float *D); +void kernel_strmm_nt_ru_8x4_vs_lib8(int k, float *alpha, float *A, float *B, float *D, int km, int kn); + +// 4x8 +void kernel_sgemm_nt_4x8_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_sgemm_nt_4x8_vs_lib8(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); +void kernel_sgemm_nt_4x8_gen_lib8(int k, float *alpha, float *A, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_strsm_nt_rl_inv_4x8_lib8(int k, float *A, float *B, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_4x8_vs_lib8(int k, float *A, float *B, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); + +// 8 +void kernel_sgemv_n_8_lib8(int k, float *alpha, float *A, float *x, float *beta, float *y, float *z); +void kernel_sgemv_n_8_vs_lib8(int k, float *alpha, float *A, float *x, float *beta, float *y, float *z, int k1); +void kernel_sgemv_n_8_gen_lib8(int kmax, float *alpha, float *A, float *x, float *beta, float *y, float *z, int k0, int k1); +void kernel_sgemv_t_8_lib8(int k, float *alpha, int offsetA, float *A, int sda, float *x, float *beta, float *y, float *z); +void kernel_sgemv_t_8_vs_lib8(int k, float *alpha, int offsetA, float *A, int sda, float *x, float *beta, float *y, float *z, int k1); +void kernel_sgemv_t_4_lib8(int k, float *alpha, int offsetA, float *A, int sda, float *x, float *beta, float *y, float *z); +void kernel_sgemv_t_4_vs_lib8(int k, float *alpha, int offsetA, float *A, int sda, float *x, float *beta, float *y, float *z, int k1); +void kernel_strsv_ln_inv_8_lib8(int k, float *A, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strsv_ln_inv_8_vs_lib8(int k, float *A, float *inv_diag_A, float *x, float *y, float *z, int km, int kn); +void kernel_strsv_lt_inv_8_lib8(int k, float *A, int sda, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strsv_lt_inv_8_vs_lib8(int k, float *A, int sda, float *inv_diag_A, float *x, float *y, float *z, int km, int kn); +void kernel_sgemv_nt_4_lib8(int kmax, float *alpha_n, float *alpha_t, float *A, int sda, float *x_n, float *x_t, float *beta_t, float *y_t, float *z_n, float *z_t); +void kernel_sgemv_nt_4_vs_lib8(int kmax, float *alpha_n, float *alpha_t, float *A, int sda, float *x_n, float *x_t, float *beta_t, float *y_t, float *z_n, float *z_t, int km); +void kernel_ssymv_l_4l_lib8(int kmax, float *alpha, float *A, int sda, float *x, float *z); +void kernel_ssymv_l_4r_lib8(int kmax, float *alpha, float *A, int sda, float *x, float *z); +void kernel_ssymv_l_4l_gen_lib8(int kmax, float *alpha, int offA, float *A, int sda, float *x, float *z, int km); +void kernel_ssymv_l_4r_gen_lib8(int kmax, float *alpha, int offA, float *A, int sda, float *x, float *z, int km); + +// -------- aux + +// ---- copy + +// lib4 +// +void kernel_sgecpsc_4_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgecp_4_0_lib4(int kmax, float *A, float *B); + +void kernel_sgecpsc_4_1_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgecp_4_1_lib4(int kmax, float *A0, int sda, float *B); +void kernel_sgecpsc_4_2_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgecp_4_2_lib4(int kmax, float *A0, int sda, float *B); +void kernel_sgecpsc_4_3_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgecp_4_3_lib4(int kmax, float *A0, int sda, float *B); + +void kernel_sgecpsc_3_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgecp_3_0_lib4(int kmax, float *A, float *B); +void kernel_sgecpsc_3_2_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgecp_3_2_lib4(int kmax, float *A0, int sda, float *B); +void kernel_sgecpsc_3_3_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgecp_3_3_lib4(int kmax, float *A0, int sda, float *B); + +void kernel_sgecpsc_2_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgecp_2_0_lib4(int kmax, float *A, float *B); +void kernel_sgecpsc_2_3_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgecp_2_3_lib4(int kmax, float *A0, int sda, float *B); + +void kernel_sgecpsc_1_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgecp_1_0_lib4(int kmax, float *A, float *B); + +// lib8 +// +void kernel_sgecp_8_0_lib8(int m, float *A, float *B); +void kernel_sgecp_8_0_gen_lib8(int m, float *A, float *B, int m1); +void kernel_sgecp_8_0_gen_u_lib8(int m, float *A, float *B, int m1); + +void kernel_sgesc_8_0_lib8(int m, float *alpha, float *A); +void kernel_sgesc_8_0_gen_lib8(int m, float *alpha, float *A, int m1); +void kernel_sgesc_8_0_gen_u_lib8(int m, float *alpha, float *A, int m1); + +void kernel_sgecpsc_8_0_lib8(int m, float *alpha, float *A, float *B); +void kernel_sgecpsc_8_0_gen_lib8(int m, float *alpha, float *A, float *B, int m1); +void kernel_sgecpsc_8_0_gen_u_lib8(int m, float *alpha, float *A, float *B, int m1); + +void kernel_sgecp_8_1_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_1_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_1_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_1_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +void kernel_sgecp_8_2_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_2_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_2_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_2_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +void kernel_sgecp_8_3_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_3_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_3_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_3_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +void kernel_sgecp_8_4_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_4_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_4_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_4_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +void kernel_sgecp_8_5_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_5_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_5_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_5_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +void kernel_sgecp_8_6_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_6_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_6_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_6_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +void kernel_sgecp_8_7_lib8(int m, float *A, int sda, float *B); +void kernel_sgecp_8_7_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgecpsc_8_7_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgecpsc_8_7_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + +// transpose +// +void kernel_sgetr_8_0_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_0_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_1_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_1_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_2_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_2_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_3_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_3_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_4_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_4_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_5_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_5_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_6_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_6_gen_lib8(int m, float *A, int sda, float *B, int m1); +void kernel_sgetr_8_7_lib8(int m, float *A, int sda, float *B); +void kernel_sgetr_8_7_gen_lib8(int m, float *A, int sda, float *B, int m1); + +// add +// +void kernel_sgead_8_0_lib8(int m, float *alpha, float *A, float *B); +void kernel_sgead_8_0_gen_lib8(int m, float *alpha, float *A, float *B, int m1); +void kernel_sgead_8_1_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_1_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); +void kernel_sgead_8_2_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_2_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); +void kernel_sgead_8_3_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_3_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); +void kernel_sgead_8_4_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_4_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); +void kernel_sgead_8_5_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_5_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); +void kernel_sgead_8_6_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_6_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); +void kernel_sgead_8_7_lib8(int m, float *alpha, float *A, int sda, float *B); +void kernel_sgead_8_7_gen_lib8(int m, float *alpha, float *A, int sda, float *B, int m1); + + +// +// lib4 +// + + + +// level 2 BLAS +// 4 +void kernel_sgemv_n_4_lib4(int k, float *alpha, float *A, float *x, float *beta, float *y, float *z); +void kernel_sgemv_n_4_vs_lib4(int k, float *alpha, float *A, float *x, float *beta, float *y, float *z, int k1); +void kernel_sgemv_n_4_gen_lib4(int kmax, float *alpha, float *A, float *x, float *beta, float *y, float *z, int k0, int k1); +void kernel_sgemv_t_4_lib4(int k, float *alpha, int offsetA, float *A, int sda, float *x, float *beta, float *y, float *z); +void kernel_sgemv_t_4_vs_lib4(int k, float *alpha, int offsetA, float *A, int sda, float *x, float *beta, float *y, float *z, int k1); +void kernel_strsv_ln_inv_4_lib4(int k, float *A, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strsv_ln_inv_4_vs_lib4(int k, float *A, float *inv_diag_A, float *x, float *y, float *z, int km, int kn); +void kernel_strsv_lt_inv_4_lib4(int k, float *A, int sda, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strsv_lt_inv_3_lib4(int k, float *A, int sda, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strsv_lt_inv_2_lib4(int k, float *A, int sda, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strsv_lt_inv_1_lib4(int k, float *A, int sda, float *inv_diag_A, float *x, float *y, float *z); +void kernel_strmv_un_4_lib4(int k, float *A, float *x, float *z); +void kernel_strmv_ut_4_lib4(int k, float *A, int sda, float *x, float *z); +void kernel_strmv_ut_4_vs_lib4(int k, float *A, int sda, float *x, float *z, int km); +void kernel_sgemv_nt_6_lib4(int kmax, float *alpha_n, float *alpha_t, float *A, int sda, float *x_n, float *x_t, float *beta_t, float *y_t, float *z_n, float *z_t); +void kernel_sgemv_nt_4_lib4(int kmax, float *alpha_n, float *alpha_t, float *A, int sda, float *x_n, float *x_t, float *beta_t, float *y_t, float *z_n, float *z_t); +void kernel_sgemv_nt_4_vs_lib4(int kmax, float *alpha_n, float *alpha_t, float *A, int sda, float *x_n, float *x_t, float *beta_t, float *y_t, float *z_n, float *z_t, int km); +void kernel_ssymv_l_4_lib4(int kmax, float *alpha, float *A, int sda, float *x_n, float *z_n); +void kernel_ssymv_l_4_gen_lib4(int kmax, float *alpha, int offA, float *A, int sda, float *x_n, float *z_n, int km); + + + +// level 3 BLAS +// 12x4 +void kernel_sgemm_nt_16x4_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_sgemm_nt_16x4_vs_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int m1, int n1); // +void kernel_strsm_nt_rl_inv_16x4_lib4(int k, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_16x4_vs_lib4(int k, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int m1, int n1); +// 12x4 +void kernel_sgemm_nt_12x4_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_sgemm_nt_12x4_vs_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int m1, int n1); // +void kernel_strsm_nt_rl_inv_12x4_lib4(int k, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_12x4_vs_lib4(int k, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int m1, int n1); +// 8x8 +void kernel_sgemm_nt_8x8_lib4(int k, float *alpha, float *A, int sda, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_sgemm_nt_8x8_vs_lib4(int k, float *alpha, float *A, int sda, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd, int m1, int n1); // +void kernel_sgemm_nn_8x8_lib4(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_sgemm_nn_8x8_vs_lib4(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd, int m1, int n1); // +// 8x4 +void kernel_sgemm_nt_8x4_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_sgemm_nt_8x4_vs_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int m1, int n1); // +void kernel_sgemm_nn_8x4_lib4(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_sgemm_nn_8x4_vs_lib4(int k, float *alpha, float *A, int sda, int offsetB, float *B, int sdb, float *beta, float *C, int sdc, float *D, int sdd, int m1, int n1); // +void kernel_ssyrk_nt_l_8x4_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); // +void kernel_ssyrk_nt_l_8x4_vs_lib4(int k, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, int km, int kn); // +void kernel_strsm_nt_rl_inv_8x4_lib4(int k, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_8x4_vs_lib4(int k, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd, float *E, float *inv_diag_E, int m1, int n1); +// 4x4 +void kernel_sgemm_nt_4x4_lib4(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); // +void kernel_sgemm_nt_4x4_vs_lib4(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); // +void kernel_sgemm_nt_4x4_gen_lib4(int k, float *alpha, float *A, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int k0, int k1); +void kernel_sgemm_nn_4x4_lib4(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, float *C, float *D); // +void kernel_sgemm_nn_4x4_vs_lib4(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, float *C, float *D, int km, int kn); // +void kernel_sgemm_nn_4x4_gen_lib4(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); // +void kernel_ssyrk_nt_l_4x4_lib4(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D); // +void kernel_ssyrk_nt_l_4x4_vs_lib4(int k, float *alpha, float *A, float *B, float *beta, float *C, float *D, int km, int kn); // +void kernel_ssyrk_nt_l_4x4_gen_lib4(int k, float *alpha, float *A, float *B, float *beta, int offsetC, float *C, int sdc, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_strmm_nt_ru_4x4_lib4(int k, float *alpha, float *A, float *B, float *D); // +void kernel_strmm_nt_ru_4x4_vs_lib4(int k, float *alpha, float *A, float *B, float *D, int km, int kn); // +void kernel_strmm_nn_rl_4x4_lib4(int k, float *alpha, float *A, int offsetB, float *B, int sdb, float *D); +void kernel_strmm_nn_rl_4x4_gen_lib4(int k, float *alpha, float *A, int offsetB, float *B, int sdb, int offsetD, float *D, int sdd, int m0, int m1, int n0, int n1); +void kernel_strsm_nt_rl_inv_4x4_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nt_rl_inv_4x4_vs_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_strsm_nt_rl_one_4x4_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E); +void kernel_strsm_nt_rl_one_4x4_vs_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E, int km, int kn); +void kernel_strsm_nt_ru_inv_4x4_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nt_ru_inv_4x4_vs_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_strsm_nt_ru_one_4x4_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E); +void kernel_strsm_nt_ru_one_4x4_vs_lib4(int k, float *A, float *B, float *beta, float *C, float *D, float *E, int km, int kn); +void kernel_strsm_nn_ru_inv_4x4_lib4(int k, float *A, float *B, int sdb, float *beta, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nn_ru_inv_4x4_vs_lib4(int k, float *A, float *B, int sdb, float *beta, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_strsm_nn_ll_one_4x4_lib4(int k, float *A, float *B, int sdb, float *C, float *D, float *E); +void kernel_strsm_nn_ll_one_4x4_vs_lib4(int k, float *A, float *B, int sdb, float *C, float *D, float *E, int km, int kn); +void kernel_strsm_nn_lu_inv_4x4_lib4(int kmax, float *A, float *B, int sdb, float *C, float *D, float *E, float *inv_diag_E); +void kernel_strsm_nn_lu_inv_4x4_vs_lib4(int kmax, float *A, float *B, int sdb, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +// diag +void kernel_sgemm_diag_right_4_a0_lib4(int kmax, float *alpha, float *A, int sda, float *B, float *D, int sdd); +void kernel_sgemm_diag_right_4_lib4(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_diag_right_3_lib4(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_diag_right_2_lib4(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_diag_right_1_lib4(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int sdc, float *D, int sdd); +void kernel_sgemm_diag_left_4_a0_lib4(int kmax, float *alpha, float *A, float *B, float *D); +void kernel_sgemm_diag_left_4_lib4(int kmax, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_sgemm_diag_left_3_lib4(int kmax, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_sgemm_diag_left_2_lib4(int kmax, float *alpha, float *A, float *B, float *beta, float *C, float *D); +void kernel_sgemm_diag_left_1_lib4(int kmax, float *alpha, float *A, float *B, float *beta, float *C, float *D); + + + +// LAPACK +// 16x4 +void kernel_spotrf_nt_l_16x4_lib4(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_16x4_vs_lib4(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int m1, int n1); +// 12x4 +void kernel_spotrf_nt_l_12x4_lib4(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_12x4_vs_lib4(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int m1, int n1); +// 8x4 +void kernel_spotrf_nt_l_8x4_lib4(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D); +void kernel_spotrf_nt_l_8x4_vs_lib4(int k, float *A, int sda, float *B, float *C, int sdc, float *D, int sdd, float *inv_diag_D, int m1, int n1); +// 4x4 +void kernel_spotrf_nt_l_4x4_lib4(int k, float *A, float *B, float *C, float *D, float *inv_diag_D); +void kernel_spotrf_nt_l_4x4_vs_lib4(int k, float *A, float *B, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_sgetrf_nn_4x4_lib4(int k, float *A, float *B, int sdb, float *C, float *D, float *inv_diag_D); +void kernel_sgetrf_nn_4x4_vs_lib4(int k, float *A, float *B, int sdb, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_sgetrf_pivot_4_lib4(int m, float *pA, int sda, float *inv_diag_A, int* ipiv); +void kernel_sgetrf_pivot_4_vs_lib4(int m, int n, float *pA, int sda, float *inv_diag_A, int* ipiv); + + + +// merged routines +// 4x4 +void kernel_sgemm_strsm_nt_rl_inv_4x4_lib4(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *E, float *inv_diag_E); +void kernel_sgemm_strsm_nt_rl_inv_4x4_vs_lib4(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *E, float *inv_diag_E, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_4x4_vs_lib4(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *inv_diag_D, int km, int kn); +void kernel_ssyrk_spotrf_nt_l_4x4_lib4(int kp, float *Ap, float *Bp, int km_, float *Am, float *Bm, float *C, float *D, float *inv_diag_D); + + + +// auxiliary routines +void kernel_strcp_l_4_0_lib4(int kmax, float *A, float *B); +void kernel_strcp_l_4_1_lib4(int kmax, float *A0, int sda, float *B); +void kernel_strcp_l_4_2_lib4(int kmax, float *A0, int sda, float *B); +void kernel_strcp_l_4_3_lib4(int kmax, float *A0, int sda, float *B); +void kernel_strcp_l_3_0_lib4(int kmax, float *A, float *B); +void kernel_strcp_l_3_2_lib4(int kmax, float *A0, int sda, float *B); +void kernel_strcp_l_3_3_lib4(int kmax, float *A0, int sda, float *B); +void kernel_strcp_l_2_0_lib4(int kmax, float *A, float *B); +void kernel_strcp_l_2_3_lib4(int kmax, float *A0, int sda, float *B); +void kernel_strcp_l_1_0_lib4(int kmax, float *A, float *B); +void kernel_sgead_4_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgead_4_1_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgead_4_2_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgead_4_3_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgead_3_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgead_3_2_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgead_3_3_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgead_2_0_lib4(int kmax, float *alpha, float *A, float *B); +void kernel_sgead_2_3_lib4(int kmax, float *alpha, float *A0, int sda, float *B); +void kernel_sgead_1_0_lib4(int kmax, float *alpha, float *A, float *B); +// TODO +void kernel_sgeset_4_lib4(int kmax, float alpha, float *A); +void kernel_strset_4_lib4(int kmax, float alpha, float *A); +void kernel_sgetr_4_lib4(int tri, int kmax, int kna, float alpha, float *A, float *C, int sdc); +void kernel_sgetr_3_lib4(int tri, int kmax, int kna, float alpha, float *A, float *C, int sdc); +void kernel_sgetr_2_lib4(int tri, int kmax, int kna, float alpha, float *A, float *C, int sdc); +void kernel_sgetr_1_lib4(int tri, int kmax, int kna, float alpha, float *A, float *C, int sdc); + + + +// pack +// 24 lib 8 +void kernel_spack_nn_24_lib8(int kmax, float *A, int lda, float *B, int sdb); +void kernel_spack_nn_24_vs_lib8(int kmax, float *A, int lda, float *B, int sdb, int m1); +// 16 lib 8 +void kernel_spack_nn_16_lib8(int kmax, float *A, int lda, float *B, int sdb); +void kernel_spack_nn_16_vs_lib8(int kmax, float *A, int lda, float *B, int sdb, int m1); +// 8 lib 8 +void kernel_spack_nn_8_lib8(int kmax, float *A, int lda, float *B); +void kernel_spack_nn_8_vs_lib8(int kmax, float *A, int lda, float *B, int m1); +void kernel_spack_tn_8_lib8(int kmax, float *A, int lda, float *B); +void kernel_spack_tn_8_vs_lib8(int kmax, float *A, int lda, float *B, int m1); +void kernel_spack_tt_8_lib8(int kmax, float *A, int lda, float *B, int sdb); +void kernel_spack_tt_8_vs_lib8(int kmax, float *A, int lda, float *B, int sdb, int m1); +// 8 lib 4 +void kernel_spack_nn_8_lib4(int kmax, float *A, int lda, float *B, int sdb); +void kernel_spack_nn_8_vs_lib4(int kmax, float *A, int lda, float *B, int sdb, int m1); +//void kernel_spack_tt_8_lib4(int kmax, float *A, int lda, float *B, int sdb); +// 4 +void kernel_spack_nn_4_lib4(int kmax, float *A, int lda, float *B); +void kernel_spack_nn_4_vs_lib4(int kmax, float *A, int lda, float *B, int m1); +void kernel_spack_tn_4_lib4(int kmax, float *A, int lda, float *B); +void kernel_spack_tn_4_vs_lib4(int kmax, float *A, int lda, float *B, int m1); +void kernel_spack_tt_4_lib4(int kmax, float *A, int lda, float *B, int sdb); +void kernel_spack_tt_4_vs_lib4(int kmax, float *A, int lda, float *B, int sdb, int m1); +// unpack +// 8 +void kernel_sunpack_nn_8_lib4(int kmax, float *A, int sda, float *B, int ldb); +void kernel_sunpack_nn_8_vs_lib4(int kmax, float *A, int sda, float *B, int ldb, int m1); +//void kernel_sunpack_tt_8_lib4(int kmax, float *A, int sda, float *B, int ldb); +// 4 +void kernel_sunpack_nn_4_lib4(int kmax, float *A, float *B, int ldb); +void kernel_sunpack_nn_4_vs_lib4(int kmax, float *A, float *B, int ldb, int m1); +void kernel_sunpack_nt_4_lib4(int kmax, float *A, float *B, int ldb); +void kernel_sunpack_nt_4_vs_lib4(int kmax, float *A, float *B, int ldb, int m1); +void kernel_sunpack_tt_4_lib4(int kmax, float *A, int sda, float *B, int ldb); + +// panel copy +// 4 +void kernel_spacp_nt_4_lib4(int kmax, float *A, int offsetB, float *B, int sdb); +void kernel_spacp_tn_4_lib4(int kmax, int offsetA, float *A, int sda, float *B); +void kernel_spacp_nn_4_lib4(int kmax, int offsetA, float *A, int sda, float *B); +void kernel_spacp_nn_4_vs_lib4(int kmax, int offsetA, float *A, int sda, float *B, int m1); + + + +/************************************************ +* BLAS API kernels +************************************************/ + +//#if defined(BLAS_API) + +// A, B panel-major bs=8; C, D column-major +// 24x4 +void kernel_sgemm_nt_24x4_lib88cc(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_24x4_vs_lib88cc(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 16x4 +void kernel_sgemm_nt_16x4_lib88cc(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_16x4_vs_lib88cc(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 8x8 +void kernel_sgemm_nt_8x8_lib88cc(int kmax, float *alpha, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x8_vs_lib88cc(int kmax, float *alpha, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_spotrf_nt_l_8x8_lib88cc(int kmax, float *A, float *B, float *C, int ldc, float *D, int ldd, float *dD); +void kernel_spotrf_nt_l_8x8_vs_lib88cc(int kmax, float *A, float *B, float *C, int ldc, float *D, int ldd, float *dD, int m1, int n1); +void kernel_strsm_nt_rl_inv_8x8_lib88ccc(int kmax, float *A, float *B, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nt_rl_inv_8x8_vs_lib88ccc(int kmax, float *A, float *B, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +// 8x4 +void kernel_sgemm_nt_8x4_lib88cc(int kmax, float *alpha, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x4_vs_lib88cc(int kmax, float *alpha, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); + +// A, B panel-major bs=4; C, D column-major +// 8x8 +void kernel_sgemm_nt_8x8_lib44cc(int kmax, float *alpha, float *A, int sda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +// 8x4 +void kernel_sgemm_nt_8x4_lib44cc(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x4_vs_lib44cc(int kmax, float *alpha, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_spotrf_nt_l_8x4_lib44cc(int kmax, float *A, int sda, float *B, float *C, int ldc, float *D, int ldd, float *dD); +void kernel_strsm_nt_rl_inv_8x4_lib44ccc(int kmax, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nt_rl_inv_8x4_vs_lib44ccc(int kmax, float *A, int sda, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +// 4x4 +void kernel_sgemm_nt_4x4_lib44cc(int kmax, float *alpha, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x4_vs_lib44cc(int kmax, float *alpha, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_strsm_nt_rl_inv_4x4_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, float *dE); +void kernel_strsm_nt_rl_inv_4x4_vs_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, float *dE, int m1, int n1); +void kernel_strsm_nt_rl_inv_4x4_lib44ccc(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nt_rl_inv_4x4_vs_lib44ccc(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nt_rl_one_4x4_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E); +void kernel_strsm_nt_rl_one_4x4_vs_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, int m1, int n1); +void kernel_strsm_nt_ru_inv_4x4_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, float *dE); +void kernel_strsm_nt_ru_inv_4x4_vs_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, float *dE, int m1, int n1); +void kernel_strsm_nt_ru_one_4x4_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E); +void kernel_strsm_nt_ru_one_4x4_vs_lib44cc4(int kmax, float *A, float *B, float *beta, float *C, int ldc, float *D, int ldd, float *E, int m1, int n1); +void kernel_spotrf_nt_l_4x4_lib44cc(int kmax, float *A, float *B, float *C, int ldc, float *D, int ldd, float *dD); +void kernel_spotrf_nt_l_4x4_vs_lib44cc(int kmax, float *A, float *B, float *C, int ldc, float *D, int ldd, float *dD, int m1, int n1); + +// B panel-major bs=8; A, C, D column-major +// 4x24 +void kernel_sgemm_nt_4x24_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x24_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_4x24_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_4x24_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 4x16 +void kernel_sgemm_nt_4x16_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x16_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_4x16_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_4x16_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 8x8 +void kernel_sgemm_nt_8x8_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x8_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_8x8_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_8x8_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 4x8 +void kernel_sgemm_nt_4x8_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x8_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_4x8_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_4x8_vs_libc8cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); + +// B panel-major bs=4; A, C, D column-major +// 8x8 +void kernel_sgemm_nt_8x8_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x8_vs_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_8x8_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_8x8_vs_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 4x8 +void kernel_sgemm_nt_4x8_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x8_vs_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_4x8_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_4x8_vs_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 4x4 +void kernel_sgemm_nt_4x4_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x4_vs_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_4x4_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_4x4_vs_libc4cc(int kmax, float *alpha, float *A, int lda, float *B, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); + +// A panel-major bs=8; B, C, D column-major +// 24x4 +void kernel_sgemm_nn_24x4_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_24x4_vs_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_24x4_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_24x4_vs_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 16x4 +void kernel_sgemm_nn_16x4_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_16x4_vs_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_16x4_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_16x4_vs_lib8ccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 8x8 +void kernel_sgemm_nn_8x8_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_8x8_vs_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_8x8_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x8_vs_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 8x4 +void kernel_sgemm_nn_8x4_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_8x4_vs_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_8x4_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x4_vs_lib8ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); + +// A panel-major bs=4; B, C, D column-major +// 8x8 +void kernel_sgemm_nn_8x8_lib4ccc(int kmax, float *alpha, float *A, int sda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x8_lib4ccc(int kmax, float *alpha, float *A, int sda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +// 8x4 +void kernel_sgemm_nn_8x4_lib4ccc(int kmax, float *alpha, float *A, int sda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_8x4_vs_lib4ccc(int kmax, float *alpha, float *A, int sda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_8x4_lib4ccc(int kmax, float *alpha, float *A, int sda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_8x4_vs_lib4ccc(int kmax, float *alpha, float *A, int sda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +// 4x4 +void kernel_sgemm_nn_4x4_lib4ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_4x4_vs_lib4ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_4x4_lib4ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x4_vs_lib4ccc(int kmax, float *alpha, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_strsm_nn_rl_inv_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nn_rl_inv_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nn_rl_one_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde); +void kernel_strsm_nn_rl_one_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, int m1, int n1); +void kernel_strsm_nt_rl_inv_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nt_rl_inv_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nt_rl_one_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde); +void kernel_strsm_nt_rl_one_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, int m1, int n1); +void kernel_strsm_nn_ru_inv_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nn_ru_inv_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nn_ru_one_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde); +void kernel_strsm_nn_ru_one_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, int m1, int n1); +void kernel_strsm_nt_ru_inv_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE); +void kernel_strsm_nt_ru_inv_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nt_ru_one_4x4_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde); +void kernel_strsm_nt_ru_one_4x4_vs_lib4cccc(int kmax, float *A, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, float *E, int lde, int m1, int n1); + +// A, C, D panel-major; B, E column-major +// TODO merge with above +// 4x4 +void kernel_strsm_nn_rl_inv_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE); +void kernel_strsm_nn_rl_inv_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nn_rl_one_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde); +void kernel_strsm_nn_rl_one_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, int m1, int n1); +void kernel_strsm_nn_ru_inv_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE); +void kernel_strsm_nn_ru_inv_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nn_ru_one_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde); +void kernel_strsm_nn_ru_one_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, int m1, int n1); +void kernel_strsm_nt_rl_inv_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE); +void kernel_strsm_nt_rl_inv_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nt_rl_one_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde); +void kernel_strsm_nt_rl_one_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, int m1, int n1); +void kernel_strsm_nt_ru_inv_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE); +void kernel_strsm_nt_ru_inv_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, float *dE, int m1, int n1); +void kernel_strsm_nt_ru_one_4x4_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde); +void kernel_strsm_nt_ru_one_4x4_vs_lib4c44c(int kmax, float *A, float *B, int ldb, float *beta, float *C, float *D, float *E, int lde, int m1, int n1); + +// A, B, C, D column-major +void kernel_sgemm_nn_4x4_libcccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nn_4x4_vs_libcccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_nt_4x4_libcccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_nt_4x4_vs_libcccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); +void kernel_sgemm_tt_4x4_libcccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd); +void kernel_sgemm_tt_4x4_vs_libcccc(int kmax, float *alpha, float *A, int lda, float *B, int ldb, float *beta, float *C, int ldc, float *D, int ldd, int m1, int n1); + +// vector +void kernel_sdot_11_lib(int n, float *x, float *y, float *res); +void kernel_saxpy_11_lib(int n, float *alpha, float *x, float *y); + + +//#endif // BLAS_API + + + +// larger kernels +// 24 +void kernel_sgemm_nt_24xn_p0_lib88cc(int n, int k, float *alpha, float *A, int sda, float *B, int sdb, float *beta, float *C, int ldc, float *D, int ldd, float *A_p, float *B_p); + + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_S_KERNEL_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_stdlib.h b/third_party/acados/include/blasfeo/include/blasfeo_stdlib.h new file mode 100644 index 0000000000..9bd248b1d4 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_stdlib.h @@ -0,0 +1,62 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_STDLIB_H_ +#define BLASFEO_STDLIB_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +#include + +// +void blasfeo_malloc(void **ptr, size_t size); +// +void blasfeo_malloc_align(void **ptr, size_t size); +// +void blasfeo_free(void *ptr); +// +void blasfeo_free_align(void *ptr); + + + +#ifdef __cplusplus +} +#endif + +#endif // BLASFEO_STDLIB_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_target.h b/third_party/acados/include/blasfeo/include/blasfeo_target.h new file mode 100644 index 0000000000..51f617a649 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_target.h @@ -0,0 +1,73 @@ +#ifndef TARGET_X64_INTEL_HASWELL +#define TARGET_X64_INTEL_HASWELL +#endif + +#ifndef TARGET_NEED_FEATURE_AVX2 +#define TARGET_NEED_FEATURE_AVX2 1 +#endif + +#ifndef TARGET_NEED_FEATURE_FMA +#define TARGET_NEED_FEATURE_FMA 1 +#endif + +#ifndef TARGET_NEED_FEATURE_SSE3 +/* #undef TARGET_NEED_FEATURE_SSE3 */ +#endif + +#ifndef TARGET_NEED_FEATURE_AVX +/* #undef TARGET_NEED_FEATURE_AVX */ +#endif + +#ifndef TARGET_NEED_FEATURE_VFPv3 +/* #undef TARGET_NEED_FEATURE_VFPv3 */ +#endif + +#ifndef TARGET_NEED_FEATURE_NEON +/* #undef TARGET_NEED_FEATURE_NEON */ +#endif + +#ifndef TARGET_NEED_FEATURE_VFPv4 +/* #undef TARGET_NEED_FEATURE_VFPv4 */ +#endif + +#ifndef TARGET_NEED_FEATURE_NEONv2 +/* #undef TARGET_NEED_FEATURE_NEONv2 */ +#endif + +#ifndef LA_HIGH_PERFORMANCE +#define LA_HIGH_PERFORMANCE +#endif + +#ifndef MF_PANELMAJ +#define MF_PANELMAJ +#endif + +#ifndef EXT_DEP +#define ON 1 +#define OFF 0 +#if ON==ON +#define EXT_DEP +#endif +#undef ON +#undef OFF +#endif + +#ifndef BLAS_API +#define ON 1 +#define OFF 0 +#if OFF==ON +#define BLAS_API +#endif +#undef ON +#undef OFF +#endif + +#ifndef FORTRAN_BLAS_API +#define ON 1 +#define OFF 0 +#if OFF==ON +#define FORTRAN_BLAS_API +#endif +#undef ON +#undef OFF +#endif diff --git a/third_party/acados/include/blasfeo/include/blasfeo_timing.h b/third_party/acados/include/blasfeo/include/blasfeo_timing.h new file mode 100644 index 0000000000..5671b888fe --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_timing.h @@ -0,0 +1,114 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_TIMING_H_ +#define BLASFEO_TIMING_H_ + +//#include + +#if (defined _WIN32 || defined _WIN64) && !(defined __MINGW32__ || defined __MINGW64__) + + /* Use Windows QueryPerformanceCounter for timing. */ + #include + + /** A structure for keeping internal timer data. */ + typedef struct blasfeo_timer_ { + LARGE_INTEGER tic; + LARGE_INTEGER toc; + LARGE_INTEGER freq; + } blasfeo_timer; + +#elif(defined __APPLE__) + + #include + + /** A structure for keeping internal timer data. */ + typedef struct blasfeo_timer_ { + uint64_t tic; + uint64_t toc; + mach_timebase_info_data_t tinfo; + } blasfeo_timer; + +#elif(defined __DSPACE__) + + #include + + typedef struct blasfeo_timer_ { + double time; + } blasfeo_timer; + +#elif(defined __XILINX_NONE_ELF__ || defined __XILINX_ULTRASCALE_NONE_ELF_JAILHOUSE__) + + #include "xtime_l.h" + + typedef struct blasfeo_timer_ { + uint64_t tic; + uint64_t toc; + } blasfeo_timer; + +#else + + /* Use POSIX clock_gettime() for timing on non-Windows machines. */ + #include + + #if __STDC_VERSION__ >= 199901L // C99 Mode + + #include + #include + + typedef struct blasfeo_timer_ { + struct timeval tic; + struct timeval toc; + } blasfeo_timer; + + #else // ANSI C Mode + + /** A structure for keeping internal timer data. */ + typedef struct blasfeo_timer_ { + struct timespec tic; + struct timespec toc; + } blasfeo_timer; + + #endif // __STDC_VERSION__ >= 199901L + +#endif // (defined _WIN32 || defined _WIN64) + +/** A function for measurement of the current time. */ +void blasfeo_tic(blasfeo_timer* t); + +/** A function which returns the elapsed time. */ +double blasfeo_toc(blasfeo_timer* t); + +#endif // BLASFEO_TIMING_H_ diff --git a/third_party/acados/include/blasfeo/include/blasfeo_v_aux_ext_dep.h b/third_party/acados/include/blasfeo/include/blasfeo_v_aux_ext_dep.h new file mode 100644 index 0000000000..1598551185 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/blasfeo_v_aux_ext_dep.h @@ -0,0 +1,83 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef BLASFEO_V_AUX_EXT_DEP_H_ +#define BLASFEO_V_AUX_EXT_DEP_H_ + + + +#include "blasfeo_target.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +/************************************************ +* d_aux_extern_depend_lib.c +************************************************/ + +#ifdef EXT_DEP + +void v_zeros(void **ptrA, int size); +// dynamically allocate size bytes of memory aligned to 64-byte boundaries and set accordingly a pointer to void; set allocated memory to zero +void v_zeros_align(void **ptrA, int size); +// free the memory allocated by v_zeros +void v_free(void *ptrA); +// free the memory allocated by v_zeros_aligned +void v_free_align(void *ptrA); +// dynamically allocate size bytes of memory and set accordingly a pointer to char; set allocated memory to zero +void c_zeros(char **ptrA, int size); +// dynamically allocate size bytes of memory aligned to 64-byte boundaries and set accordingly a pointer to char; set allocated memory to zero +void c_zeros_align(char **ptrA, int size); +// free the memory allocated by c_zeros +void c_free(char *ptrA); +// free the memory allocated by c_zeros_aligned +void c_free_align(char *ptrA); + +#endif // EXT_DEP + + + +#ifdef __cplusplus +} +#endif + + + +#endif // BLASFEO_V_AUX_EXT_DEP_H_ diff --git a/third_party/acados/include/blasfeo/include/d_blas.h b/third_party/acados/include/blasfeo/include/d_blas.h new file mode 100644 index 0000000000..ffd2578da3 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/d_blas.h @@ -0,0 +1,78 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// headers to reference BLAS and LAPACK routines employed in BLASFEO WR + +// level 1 +double ddot_(int *m, double *x, int *incx, double *y, int *incy); +void dcopy_(int *m, double *x, int *incx, double *y, int *incy); +void daxpy_(int *m, double *alpha, double *x, int *incx, double *y, int *incy); +void dscal_(int *m, double *alpha, double *x, int *incx); +void drot_(int *m, double *x, int *incx, double *y, int *incy, double *c, double *s); +void drotg_(double *a, double *b, double *c, double *s); + +// level 2 +void dgemv_(char *ta, int *m, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); +void dsymv_(char *uplo, int *m, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); +void dtrmv_(char *uplo, char *trans, char *diag, int *n, double *A, int *lda, double *x, int *incx); +void dtrsv_(char *uplo, char *trans, char *diag, int *n, double *A, int *lda, double *x, int *incx); +void dger_(int *m, int *n, double *alpha, double *x, int *incx, double *y, int *incy, double *A, int *lda); + +// level 3 +void dgemm_(char *ta, char *tb, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc); +void dsyrk_(char *uplo, char *trans, int *n, int *k, double *alpha, double *A, int *lda, double *beta, double *C, int *ldc); +void dtrmm_(char *side, char *uplo, char *trans, char *diag, int *m, int *n, double *alpha, double *A, int *lda, double *B, int *ldb); +void dtrsm_(char *side, char *uplo, char *trans, char *diag, int *m, int *n, double *alpha, double *A, int *lda, double *B, int *ldb); +void dsyr2k_(char *uplo, char *trans, int *n, int *k, double *alpha, double *A, int *lda, double *B, int *ldb, double *beta, double *C, int *ldc); + +// lapack +void dpotrf_(char *uplo, int *m, double *A, int *lda, int *info); +void dgetrf_(int *m, int *n, double *A, int *lda, int *ipiv, int *info); +void dgeqrf_(int *m, int *n, double *A, int *lda, double *tau, double *work, int *lwork, int *info); +void dgeqr2_(int *m, int *n, double *A, int *lda, double *tau, double *work, int *info); +void dgelqf_(int *m, int *n, double *A, int *lda, double *tau, double *work, int *lwork, int *info); +void dorglq_(int *m, int *n, int *k, double *A, int *lda, double *tau, double *work, int *lwork, int *info); + + + +#ifdef __cplusplus +} +#endif diff --git a/third_party/acados/include/blasfeo/include/d_blas_64.h b/third_party/acados/include/blasfeo/include/d_blas_64.h new file mode 100644 index 0000000000..4f40d00dfb --- /dev/null +++ b/third_party/acados/include/blasfeo/include/d_blas_64.h @@ -0,0 +1,73 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// headers to reference BLAS and LAPACK routines employed in BLASFEO WR + +// level 1 +double ddot_(long long *m, double *x, long long *incx, double *y, long long *incy); +void dcopy_(long long *m, double *x, long long *incx, double *y, long long *incy); +void daxpy_(long long *m, double *alpha, double *x, long long *incx, double *y, long long *incy); +void dscal_(long long *m, double *alpha, double *x, long long *incx); + +// level 2 +void dgemv_(char *ta, long long *m, long long *n, double *alpha, double *A, long long *lda, double *x, long long *incx, double *beta, double *y, long long *incy); +void dsymv_(char *uplo, long long *m, double *alpha, double *A, long long *lda, double *x, long long *incx, double *beta, double *y, long long *incy); +void dtrmv_(char *uplo, char *trans, char *diag, long long *n, double *A, long long *lda, double *x, long long *incx); +void dtrsv_(char *uplo, char *trans, char *diag, long long *n, double *A, long long *lda, double *x, long long *incx); +void dger_(long long *m, long long *n, double *alpha, double *x, long long *incx, double *y, long long *incy, double *A, long long *lda); + +// level 3 +void dgemm_(char *ta, char *tb, long long *m, long long *n, long long *k, double *alpha, double *A, long long *lda, double *B, long long *ldb, double *beta, double *C, long long *ldc); +void dsyrk_(char *uplo, char *trans, long long *n, long long *k, double *alpha, double *A, long long *lda, double *beta, double *C, long long *ldc); +void dtrmm_(char *side, char *uplo, char *trans, char *diag, long long *m, long long *n, double *alpha, double *A, long long *lda, double *B, long long *ldb); +void dtrsm_(char *side, char *uplo, char *trans, char *diag, long long *m, long long *n, double *alpha, double *A, long long *lda, double *B, long long *ldb); + +// lapack +void dpotrf_(char *uplo, long long *m, double *A, long long *lda, long long *info); +void dgetrf_(long long *m, long long *n, double *A, long long *lda, long long *ipiv, long long *info); +void dgeqrf_(long long *m, long long *n, double *A, long long *lda, double *tau, double *work, long long *lwork, long long *info); +void dgeqr2_(long long *m, long long *n, double *A, long long *lda, double *tau, double *work, long long *info); + + + +#ifdef __cplusplus +} +#endif diff --git a/third_party/acados/include/blasfeo/include/s_blas.h b/third_party/acados/include/blasfeo/include/s_blas.h new file mode 100644 index 0000000000..3b299ce64c --- /dev/null +++ b/third_party/acados/include/blasfeo/include/s_blas.h @@ -0,0 +1,78 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// headers to reference BLAS and LAPACK routines employed in BLASFEO WR + +// level 1 +float sdot_(int *m, float *x, int *incx, float *y, int *incy); +void scopy_(int *m, float *x, int *incx, float *y, int *incy); +void saxpy_(int *m, float *alpha, float *x, int *incx, float *y, int *incy); +void sscal_(int *m, float *alpha, float *x, int *incx); +void srot_(int *m, float *x, int *incx, float *y, int *incy, float *c, float *s); +void srotg_(float *a, float *b, float *c, float *s); + +// level 2 +void sgemv_(char *ta, int *m, int *n, float *alpha, float *A, int *lda, float *x, int *incx, float *beta, float *y, int *incy); +void ssymv_(char *uplo, int *m, float *alpha, float *A, int *lda, float *x, int *incx, float *beta, float *y, int *incy); +void strmv_(char *uplo, char *trans, char *diag, int *n, float *A, int *lda, float *x, int *incx); +void strsv_(char *uplo, char *trans, char *diag, int *n, float *A, int *lda, float *x, int *incx); +void sger_(int *m, int *n, float *alpha, float *x, int *incx, float *y, int *incy, float *A, int *lda); + +// level 3 +void sgemm_(char *ta, char *tb, int *m, int *n, int *k, float *alpha, float *A, int *lda, float *B, int *ldb, float *beta, float *C, int *ldc); +void ssyrk_(char *uplo, char *trans, int *n, int *k, float *alpha, float *A, int *lda, float *beta, float *C, int *ldc); +void strmm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *A, int *lda, float *B, int *ldb); +void strsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n, float *alpha, float *A, int *lda, float *B, int *ldb); +void ssyr2k_(char *uplo, char *trans, int *n, int *k, float *alpha, float *A, int *lda, float *B, int *ldb, float *beta, float *C, int *ldc); + +// lapack +void spotrf_(char *uplo, int *m, float *A, int *lda, int *info); +void sgetrf_(int *m, int *n, float *A, int *lda, int *ipiv, int *info); +void sgeqrf_(int *m, int *n, float *A, int *lda, float *tau, float *work, int *lwork, int *info); +void sgeqr2_(int *m, int *n, float *A, int *lda, float *tau, float *work, int *info); +void sgelqf_(int *m, int *n, float *A, int *lda, float *tau, float *work, int *lwork, int *info); +void sorglq_(int *m, int *n, int *k, float *A, int *lda, float *tau, float *work, int *lwork, int *info); + + + +#ifdef __cplusplus +} +#endif diff --git a/third_party/acados/include/blasfeo/include/s_blas_64.h b/third_party/acados/include/blasfeo/include/s_blas_64.h new file mode 100644 index 0000000000..b9efab6c23 --- /dev/null +++ b/third_party/acados/include/blasfeo/include/s_blas_64.h @@ -0,0 +1,73 @@ +/************************************************************************************************** +* * +* This file is part of BLASFEO. * +* * +* BLASFEO -- BLAS For Embedded Optimization. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + + +// headers to reference BLAS and LAPACK routines employed in BLASFEO WR + +// level 1 +float sdot_(long long *m, float *x, long long *incx, float *y, long long *incy); +void scopy_(long long *m, float *x, long long *incx, float *y, long long *incy); +void saxpy_(long long *m, float *alpha, float *x, long long *incx, float *y, long long *incy); +void sscal_(long long *m, float *alpha, float *x, long long *incx); + +// level 2 +void sgemv_(char *ta, long long *m, long long *n, float *alpha, float *A, long long *lda, float *x, long long *incx, float *beta, float *y, long long *incy); +void ssymv_(char *uplo, long long *m, float *alpha, float *A, long long *lda, float *x, long long *incx, float *beta, float *y, long long *incy); +void strmv_(char *uplo, char *trans, char *diag, long long *n, float *A, long long *lda, float *x, long long *incx); +void strsv_(char *uplo, char *trans, char *diag, long long *n, float *A, long long *lda, float *x, long long *incx); +void sger_(long long *m, long long *n, float *alpha, float *x, long long *incx, float *y, long long *incy, float *A, long long *lda); + +// level 3 +void sgemm_(char *ta, char *tb, long long *m, long long *n, long long *k, float *alpha, float *A, long long *lda, float *B, long long *ldb, float *beta, float *C, long long *ldc); +void ssyrk_(char *uplo, char *trans, long long *n, long long *k, float *alpha, float *A, long long *lda, float *beta, float *C, long long *ldc); +void strmm_(char *side, char *uplo, char *transa, char *diag, long long *m, long long *n, float *alpha, float *A, long long *lda, float *B, long long *ldb); +void strsm_(char *side, char *uplo, char *transa, char *diag, long long *m, long long *n, float *alpha, float *A, long long *lda, float *B, long long *ldb); + +// lapack +void spotrf_(char *uplo, long long *m, float *A, long long *lda, long long *info); +void sgetrf_(long long *m, long long *n, float *A, long long *lda, long long *ipiv, long long *info); +void sgeqrf_(long long *m, long long *n, float *A, long long *lda, float *tau, float *work, long long *lwork, long long *info); +void sgeqr2_(long long *m, long long *n, float *A, long long *lda, float *tau, float *work, long long *info); + + + +#ifdef __cplusplus +} +#endif diff --git a/third_party/acados/include/hpipm/include/hpipm_aux_mem.h b/third_party/acados/include/hpipm/include/hpipm_aux_mem.h new file mode 100644 index 0000000000..7bd3d7e8bc --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_aux_mem.h @@ -0,0 +1,52 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_AUX_MEM_H_ +#define HPIPM_AUX_MEM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void hpipm_zero_memset(hpipm_size_t memsize, void *mem); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_AUX_MEM_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_aux_string.h b/third_party/acados/include/hpipm/include/hpipm_aux_string.h new file mode 100644 index 0000000000..804cba5dc1 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_aux_string.h @@ -0,0 +1,50 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_AUX_STRING_H_ +#define HPIPM_AUX_STRING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_STR_LEN 5 +int hpipm_strcmp(char *str1, char *str2); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_AUX_STRING_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_common.h b/third_party/acados/include/hpipm/include/hpipm_common.h new file mode 100644 index 0000000000..0cc96a7b50 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_common.h @@ -0,0 +1,76 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_COMMON_H_ +#define HPIPM_COMMON_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef size_t hpipm_size_t; + +enum hpipm_mode + { + SPEED_ABS, // focus on speed, absolute IPM formulation + SPEED, // focus on speed, relative IPM formulation + BALANCE, // balanced mode, relative IPM formulation + ROBUST, // focus on robustness, relative IPM formulation + }; + +enum hpipm_status + { + SUCCESS, // found solution satisfying accuracy tolerance + MAX_ITER, // maximum iteration number reached + MIN_STEP, // minimum step length reached + NAN_SOL, // NaN in solution detected + INCONS_EQ, // unconsistent equality constraints + }; + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_COMMON_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_cast_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_d_cast_qcqp.h new file mode 100644 index 0000000000..0e4c41f221 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_cast_qcqp.h @@ -0,0 +1,71 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_CAST_QCQP_H_ +#define HPIPM_D_CAST_QCQP_H_ + + + +#include +#include + +#include "hpipm_d_dense_qcqp.h" +#include "hpipm_d_dense_qcqp_sol.h" +#include "hpipm_d_ocp_qcqp.h" +#include "hpipm_d_ocp_qcqp_dim.h" +#include "hpipm_d_ocp_qcqp_sol.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_cast_qcqp_compute_dim(struct d_ocp_qcqp_dim *ocp_dim, struct d_dense_qcqp_dim *dense_dim); +// +void d_cast_qcqp_cond(struct d_ocp_qcqp *ocp_qp, struct d_dense_qcqp *dense_qp); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_CAST_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_cond.h b/third_party/acados/include/hpipm/include/hpipm_d_cond.h new file mode 100644 index 0000000000..5900a2ab10 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_cond.h @@ -0,0 +1,135 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_COND_H_ +#define HPIPM_D_COND_H_ + + + +#include +#include + +#include "hpipm_d_dense_qp.h" +#include "hpipm_d_dense_qp_sol.h" +#include "hpipm_d_ocp_qp.h" +#include "hpipm_d_ocp_qp_dim.h" +#include "hpipm_d_ocp_qp_sol.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_cond_qp_arg + { + int cond_last_stage; // condense last stage + int cond_alg; // condensing algorithm: 0 N2-nx3, 1 N3-nx2 + int comp_prim_sol; // primal solution (v) + int comp_dual_sol_eq; // dual solution equality constr (pi) + int comp_dual_sol_ineq; // dual solution inequality constr (lam t) + int square_root_alg; // square root algorithm (faster but requires RSQ>0) + hpipm_size_t memsize; + }; + + + +struct d_cond_qp_ws + { + struct blasfeo_dmat *Gamma; + struct blasfeo_dmat *GammaQ; + struct blasfeo_dmat *L; + struct blasfeo_dmat *Lx; + struct blasfeo_dmat *AL; + struct blasfeo_dvec *Gammab; + struct blasfeo_dvec *l; + struct blasfeo_dvec *tmp_nbgM; + struct blasfeo_dvec *tmp_nuxM; + int bs; // block size + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_cond_qp_arg_memsize(); +// +void d_cond_qp_arg_create(struct d_cond_qp_arg *cond_arg, void *mem); +// +void d_cond_qp_arg_set_default(struct d_cond_qp_arg *cond_arg); +// condensing algorithm: 0 N2-nx3, 1 N3-nx2 +void d_cond_qp_arg_set_cond_alg(int cond_alg, struct d_cond_qp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 square-root +void d_cond_qp_arg_set_ric_alg(int ric_alg, struct d_cond_qp_arg *cond_arg); +// condense last stage: 0 last stage disregarded, 1 last stage condensed too +void d_cond_qp_arg_set_cond_last_stage(int cond_last_stage, struct d_cond_qp_arg *cond_arg); +// +void d_cond_qp_arg_set_comp_prim_sol(int value, struct d_cond_qp_arg *cond_arg); +// +void d_cond_qp_arg_set_comp_dual_sol_eq(int value, struct d_cond_qp_arg *cond_arg); +// +void d_cond_qp_arg_set_comp_dual_sol_ineq(int value, struct d_cond_qp_arg *cond_arg); + +// +void d_cond_qp_compute_dim(struct d_ocp_qp_dim *ocp_dim, struct d_dense_qp_dim *dense_dim); +// +hpipm_size_t d_cond_qp_ws_memsize(struct d_ocp_qp_dim *ocp_dim, struct d_cond_qp_arg *cond_arg); +// +void d_cond_qp_ws_create(struct d_ocp_qp_dim *ocp_dim, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws, void *mem); +// +void d_cond_qp_cond(struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_qp_cond_lhs(struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_qp_cond_rhs(struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_qp_expand_sol(struct d_ocp_qp *ocp_qp, struct d_dense_qp_sol *dense_qp_sol, struct d_ocp_qp_sol *ocp_qp_sol, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// TODO remove +void d_cond_qp_expand_primal_sol(struct d_ocp_qp *ocp_qp, struct d_dense_qp_sol *dense_qp_sol, struct d_ocp_qp_sol *ocp_qp_sol, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); + +// +void d_cond_qp_update(int *idxc, struct d_ocp_qp *ocp_qp, struct d_dense_qp *dense_qp, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_COND_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_cond_aux.h b/third_party/acados/include/hpipm/include/hpipm_d_cond_aux.h new file mode 100644 index 0000000000..73afba3c7e --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_cond_aux.h @@ -0,0 +1,92 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_COND_AUX_H_ +#define HPIPM_D_COND_AUX_H_ + + + +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_cond_BAbt(struct d_ocp_qp *ocp_qp, struct blasfeo_dmat *BAbt2, struct blasfeo_dvec *b, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_BAt(struct d_ocp_qp *ocp_qp, struct blasfeo_dmat *BAbt2, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_b(struct d_ocp_qp *ocp_qp, struct blasfeo_dvec *b, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_RSQrq(struct d_ocp_qp *ocp_qp, struct blasfeo_dmat *RSQrq2, struct blasfeo_dvec *rq, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_RSQ(struct d_ocp_qp *ocp_qp, struct blasfeo_dmat *RSQrq2, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_rq(struct d_ocp_qp *ocp_qp, struct blasfeo_dvec *rq, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_DCtd(struct d_ocp_qp *ocp_qp, int *idxb2, struct blasfeo_dmat *DCt2, struct blasfeo_dvec *d2, struct blasfeo_dvec *d_mask2, int *idxs_rev2, struct blasfeo_dvec *Z2, struct blasfeo_dvec *z, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_DCt(struct d_ocp_qp *ocp_qp, int *idxb2, struct blasfeo_dmat *DCt2, int *idxs_rev2, struct blasfeo_dvec *Z2, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_cond_d(struct d_ocp_qp *ocp_qp, struct blasfeo_dvec *d2, struct blasfeo_dvec *d_mask2, struct blasfeo_dvec *z, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_expand_sol(struct d_ocp_qp *ocp_qp, struct d_dense_qp_sol *dense_qp_sol, struct d_ocp_qp_sol *ocp_qp_so, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_expand_primal_sol(struct d_ocp_qp *ocp_qp, struct d_dense_qp_sol *dense_qp_sol, struct d_ocp_qp_sol *ocp_qp_so, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); + +// +void d_update_cond_BAbt(int *idxc, struct d_ocp_qp *ocp_qp, struct blasfeo_dmat *BAbt2, struct blasfeo_dvec *b, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_update_cond_RSQrq_N2nx3(int *idxc, struct d_ocp_qp *ocp_qp, struct blasfeo_dmat *RSQrq2, struct blasfeo_dvec *rq, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); +// +void d_update_cond_DCtd(int *idxc, struct d_ocp_qp *ocp_qp, int *idxb2, struct blasfeo_dmat *DCt2, struct blasfeo_dvec *d2, int *idxs2, struct blasfeo_dvec *Z2, struct blasfeo_dvec *z, struct d_cond_qp_arg *cond_arg, struct d_cond_qp_ws *cond_ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_COND_AUX_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_cond_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_d_cond_qcqp.h new file mode 100644 index 0000000000..266567bb8d --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_cond_qcqp.h @@ -0,0 +1,129 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_COND_QCQP_H_ +#define HPIPM_D_COND_QCQP_H_ + + + +#include +#include + +#include "hpipm_d_dense_qcqp.h" +#include "hpipm_d_dense_qcqp_sol.h" +#include "hpipm_d_ocp_qcqp.h" +#include "hpipm_d_ocp_qcqp_dim.h" +#include "hpipm_d_ocp_qcqp_sol.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_cond_qcqp_arg + { + struct d_cond_qp_arg *qp_arg; + int cond_last_stage; // condense last stage +// int cond_variant; // TODO + int comp_prim_sol; // primal solution (v) + int comp_dual_sol_eq; // dual solution equality constr (pi) + int comp_dual_sol_ineq; // dual solution equality constr (lam t) + int square_root_alg; // square root algorithm (faster but requires RSQ>0) + hpipm_size_t memsize; + }; + + + +struct d_cond_qcqp_ws + { + struct d_cond_qp_ws *qp_ws; + struct blasfeo_dmat *hess_array; // TODO remove + struct blasfeo_dmat *zero_hess; // TODO remove + struct blasfeo_dvec *grad_array; // TODO remove + struct blasfeo_dvec *zero_grad; // TODO remove + struct blasfeo_dvec *tmp_nvc; + struct blasfeo_dvec *tmp_nuxM; + struct blasfeo_dmat *GammaQ; + struct blasfeo_dmat *tmp_DCt; + struct blasfeo_dmat *tmp_nuM_nxM; +// struct blasfeo_dvec *d_qp; +// struct blasfeo_dvec *d_mask_qp; + hpipm_size_t memsize; + }; + + +// +hpipm_size_t d_cond_qcqp_arg_memsize(); +// +void d_cond_qcqp_arg_create(struct d_cond_qcqp_arg *cond_arg, void *mem); +// +void d_cond_qcqp_arg_set_default(struct d_cond_qcqp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 square-root +void d_cond_qcqp_arg_set_ric_alg(int ric_alg, struct d_cond_qcqp_arg *cond_arg); +// condense last stage: 0 last stage disregarded, 1 last stage condensed too +void d_cond_qcqp_arg_set_cond_last_stage(int cond_last_stage, struct d_cond_qcqp_arg *cond_arg); + +// +void d_cond_qcqp_compute_dim(struct d_ocp_qcqp_dim *ocp_dim, struct d_dense_qcqp_dim *dense_dim); +// +hpipm_size_t d_cond_qcqp_ws_memsize(struct d_ocp_qcqp_dim *ocp_dim, struct d_cond_qcqp_arg *cond_arg); +// +void d_cond_qcqp_ws_create(struct d_ocp_qcqp_dim *ocp_dim, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws, void *mem); +// +void d_cond_qcqp_qc(struct d_ocp_qcqp *ocp_qp, struct blasfeo_dmat *Hq2, int *Hq_nzero2, struct blasfeo_dmat *Ct2, struct blasfeo_dvec *d2, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); +// +void d_cond_qcqp_qc_lhs(struct d_ocp_qcqp *ocp_qp, struct blasfeo_dmat *Hq2, int *Hq_nzero2, struct blasfeo_dmat *Ct2, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); +// +void d_cond_qcqp_qc_rhs(struct d_ocp_qcqp *ocp_qp, struct blasfeo_dvec *d2, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); +// +void d_cond_qcqp_cond(struct d_ocp_qcqp *ocp_qp, struct d_dense_qcqp *dense_qp, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); +// +void d_cond_qcqp_cond_rhs(struct d_ocp_qcqp *ocp_qp, struct d_dense_qcqp *dense_qp, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); +// +void d_cond_qcqp_cond_lhs(struct d_ocp_qcqp *ocp_qp, struct d_dense_qcqp *dense_qp, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); +// +void d_cond_qcqp_expand_sol(struct d_ocp_qcqp *ocp_qp, struct d_dense_qcqp_sol *dense_qp_sol, struct d_ocp_qcqp_sol *ocp_qp_sol, struct d_cond_qcqp_arg *cond_arg, struct d_cond_qcqp_ws *cond_ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_COND_QCQP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_core_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_core_qp_ipm.h new file mode 100644 index 0000000000..f39d9a9b50 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_core_qp_ipm.h @@ -0,0 +1,101 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_CORE_QP_IPM_ +#define HPIPM_D_CORE_QP_IPM_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct d_core_qp_ipm_workspace + { + double *v; // primal variables + double *pi; // equality constraints multipliers + double *lam; // inequality constraints multipliers + double *t; // inequality constraints slacks + double *t_inv; // inverse of t + double *v_bkp; // backup of primal variables + double *pi_bkp; // backup of equality constraints multipliers + double *lam_bkp; // backup of inequality constraints multipliers + double *t_bkp; // backup of inequality constraints slacks + double *dv; // step in v + double *dpi; // step in pi + double *dlam; // step in lam + double *dt; // step in t + double *res_g; // q-residuals + double *res_b; // b-residuals + double *res_d; // d-residuals + double *res_m; // m-residuals + double *res_m_bkp; // m-residuals + double *Gamma; // Hessian update + double *gamma; // gradient update + double alpha; // step length + double alpha_prim; // step length + double alpha_dual; // step length + double sigma; // centering XXX + double mu; // duality measuere + double mu_aff; // affine duality measuere + double nc_inv; // 1.0/nc, where nc is the total number of inequality constraints + double nc_mask_inv; // 1.0/nc_mask + double lam_min; // min value in lam vector + double t_min; // min value in t vector + double t_min_inv; // inverse of min value in t vector + double tau_min; // min value of barrier parameter + int nv; // number of primal variables + int ne; // number of equality constraints + int nc; // (twice the) number of (two-sided) inequality constraints + int nc_mask; // total number of ineq constr after masking + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam also in solution, or only in Gamma computation + hpipm_size_t memsize; // memory size (in bytes) of workspace + }; + + + +// +hpipm_size_t d_memsize_core_qp_ipm(int nv, int ne, int nc); +// +void d_create_core_qp_ipm(int nv, int ne, int nc, struct d_core_qp_ipm_workspace *workspace, void *mem); +// +void d_core_qp_ipm(struct d_core_qp_ipm_workspace *workspace); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_D_CORE_QP_IPM_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_core_qp_ipm_aux.h b/third_party/acados/include/hpipm/include/hpipm_d_core_qp_ipm_aux.h new file mode 100644 index 0000000000..30cc824bad --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_core_qp_ipm_aux.h @@ -0,0 +1,68 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_CORE_QP_IPM_AUX_ +#define HPIPM_S_CORE_QP_IPM_AUX_ + +#ifdef __cplusplus +extern "C" { +#endif + +// +void d_compute_Gamma_gamma_qp(double *res_d, double *res_m, struct d_core_qp_ipm_workspace *rws); +// +void d_compute_gamma_qp(double *res_d, double *res_m, struct d_core_qp_ipm_workspace *rws); +// +void d_compute_lam_t_qp(double *res_d, double *res_m, double *dlam, double *dt, struct d_core_qp_ipm_workspace *rws); +// +void d_compute_alpha_qp(struct d_core_qp_ipm_workspace *rws); +// +void d_update_var_qp(struct d_core_qp_ipm_workspace *rws); +// +void d_compute_mu_aff_qp(struct d_core_qp_ipm_workspace *rws); +// +void d_backup_res_m(struct d_core_qp_ipm_workspace *rws); +// +void d_compute_centering_correction_qp(struct d_core_qp_ipm_workspace *rws); +// +void d_compute_centering_qp(struct d_core_qp_ipm_workspace *rws); +// +void d_compute_tau_min_qp(struct d_core_qp_ipm_workspace *rws); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_S_CORE_QP_IPM_AUX_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp.h new file mode 100644 index 0000000000..3da5716493 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp.h @@ -0,0 +1,199 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QCQP_H_ +#define HPIPM_D_DENSE_QCQP_H_ + + + +#include +#include + +#include "hpipm_d_dense_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qcqp + { + struct d_dense_qcqp_dim *dim; + struct blasfeo_dmat *Hv; // hessian of cost & vector work space + struct blasfeo_dmat *A; // equality constraint matrix + struct blasfeo_dmat *Ct; // inequality constraints matrix + struct blasfeo_dmat *Hq; // hessians of quadratic constraints + struct blasfeo_dvec *gz; // gradient of cost & gradient of slacks + struct blasfeo_dvec *b; // equality constraint vector + struct blasfeo_dvec *d; // inequality constraints vector + struct blasfeo_dvec *d_mask; // inequality constraints mask vector + struct blasfeo_dvec *m; // rhs of complementarity condition + struct blasfeo_dvec *Z; // (diagonal) hessian of slacks + int *idxb; // indices of box constrained variables within [u; x] + int *idxs_rev; // index of soft constraints (reverse storage) + int *Hq_nzero; // for each int, the last 3 bits ...abc, {a,b,c}=0 => {R,S,Q}=0 + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_dense_qcqp_memsize(struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_create(struct d_dense_qcqp_dim *dim, struct d_dense_qcqp *qp, void *memory); + +// +void d_dense_qcqp_set(char *field, void *value, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_H(double *H, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_g(double *g, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_A(double *A, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_b(double *b, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_idxb(int *idxb, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_lb(double *lb, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_lb_mask(double *lb, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_ub(double *ub, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_ub_mask(double *ub, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_C(double *C, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_lg(double *lg, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_lg_mask(double *lg, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_ug(double *ug, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_ug_mask(double *ug, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_Hq(double *Hq, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_gq(double *gq, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_uq(double *uq, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_uq_mask(double *uq, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_idxs(int *idxs, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_idxs_rev(int *idxs_rev, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_Zl(double *Zl, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_Zu(double *Zu, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_zl(double *zl, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_zu(double *zu, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_ls(double *ls, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_ls_mask(double *ls, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_us(double *us, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_set_us_mask(double *us, struct d_dense_qcqp *qp); + +// getters (COLMAJ) + +void d_dense_qcqp_get_H(struct d_dense_qcqp *qp, double *H); +// +void d_dense_qcqp_get_g(struct d_dense_qcqp *qp, double *g); +// +void d_dense_qcqp_get_A(struct d_dense_qcqp *qp, double *A); +// +void d_dense_qcqp_get_b(struct d_dense_qcqp *qp, double *b); +// +void d_dense_qcqp_get_idxb(struct d_dense_qcqp *qp, int *idxb); +// +void d_dense_qcqp_get_lb(struct d_dense_qcqp *qp, double *lb); +// +void d_dense_qcqp_get_lb_mask(struct d_dense_qcqp *qp, double *lb); +// +void d_dense_qcqp_get_ub(struct d_dense_qcqp *qp, double *ub); +// +void d_dense_qcqp_get_ub_mask(struct d_dense_qcqp *qp, double *ub); +// +void d_dense_qcqp_get_C(struct d_dense_qcqp *qp, double *C); +// +void d_dense_qcqp_get_lg(struct d_dense_qcqp *qp, double *lg); +// +void d_dense_qcqp_get_lg_mask(struct d_dense_qcqp *qp, double *lg); +// +void d_dense_qcqp_get_ug(struct d_dense_qcqp *qp, double *ug); +// +void d_dense_qcqp_get_ug_mask(struct d_dense_qcqp *qp, double *ug); +// +void d_dense_qcqp_get_idxs(struct d_dense_qcqp *qp, int *idxs); +// +void d_dense_qcqp_get_idxs_rev(struct d_dense_qcqp *qp, int *idxs_rev); +// +void d_dense_qcqp_get_Zl(struct d_dense_qcqp *qp, double *Zl); +// +void d_dense_qcqp_get_Zu(struct d_dense_qcqp *qp, double *Zu); +// +void d_dense_qcqp_get_zl(struct d_dense_qcqp *qp, double *zl); +// +void d_dense_qcqp_get_zu(struct d_dense_qcqp *qp, double *zu); +// +void d_dense_qcqp_get_ls(struct d_dense_qcqp *qp, double *ls); +// +void d_dense_qcqp_get_ls_mask(struct d_dense_qcqp *qp, double *ls); +// +void d_dense_qcqp_get_us(struct d_dense_qcqp *qp, double *us); +// +void d_dense_qcqp_get_us_mask(struct d_dense_qcqp *qp, double *us); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_dim.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_dim.h new file mode 100644 index 0000000000..fa8c574a1e --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_dim.h @@ -0,0 +1,98 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_DENSE_QCQP_DIM_H_ +#define HPIPM_D_DENSE_QCQP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qcqp_dim + { + struct d_dense_qp_dim *qp_dim; // dim of qp approximation + int nv; // number of variables + int ne; // number of equality constraints + int nb; // number of box constraints + int ng; // number of general constraints + int nq; // number of quadratic constraints + int nsb; // number of softened box constraints + int nsg; // number of softened general constraints + int nsq; // number of softened quadratic constraints + int ns; // number of softened constraints (nsb+nsg+nsq) TODO number of slacks + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_dense_qcqp_dim_memsize(); +// +void d_dense_qcqp_dim_create(struct d_dense_qcqp_dim *dim, void *memory); +// +void d_dense_qcqp_dim_set(char *field_name, int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_nv(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_ne(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_nb(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_ng(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_nq(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_nsb(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_nsg(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_nsq(int value, struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_dim_set_ns(int value, struct d_dense_qcqp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_DENSE_QCQP_DIM_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_ipm.h new file mode 100644 index 0000000000..fa3f98fa79 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_ipm.h @@ -0,0 +1,193 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QCQP_IPM_H_ +#define HPIPM_D_DENSE_QCQP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qcqp_ipm_arg + { + struct d_dense_qp_ipm_arg *qp_arg; + double mu0; // initial value for duality measure + double alpha_min; // exit cond on step length + double res_g_max; // exit cond on inf norm of residuals + double res_b_max; // exit cond on inf norm of residuals + double res_d_max; // exit cond on inf norm of residuals + double res_m_max; // exit cond on inf norm of residuals + double reg_prim; // reg of primal hessian + double reg_dual; // reg of dual hessian + double lam_min; // min value in lam vector + double t_min; // min value in t vector + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int scale; // scale hessian + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq + int abs_form; // absolute IPM formulation + int comp_res_exit; // compute residuals on exit (only for abs_form==1) + int comp_res_pred; // compute residuals of prediction + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct d_dense_qcqp_ipm_ws + { + struct d_dense_qp_ipm_ws *qp_ws; + struct d_dense_qp *qp; + struct d_dense_qp_sol *qp_sol; + struct d_dense_qcqp_res_ws *qcqp_res_ws; + struct d_dense_qcqp_res *qcqp_res; + struct blasfeo_dvec *tmp_nv; + int iter; // iteration number + int status; + hpipm_size_t memsize; // memory size (in bytes) of workspace + }; + + + +// +hpipm_size_t d_dense_qcqp_ipm_arg_memsize(struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_ipm_arg_create(struct d_dense_qcqp_dim *dim, struct d_dense_qcqp_ipm_arg *arg, void *mem); +// +void d_dense_qcqp_ipm_arg_set_default(enum hpipm_mode mode, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set(char *field, void *value, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_iter_max(int *iter_max, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_alpha_min(double *alpha_min, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_mu0(double *mu0, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_tol_stat(double *tol_stat, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_tol_eq(double *tol_eq, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_tol_ineq(double *tol_ineq, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_tol_comp(double *tol_comp, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_reg_prim(double *reg, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_reg_dual(double *reg, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_warm_start(int *warm_start, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_pred_corr(int *pred_corr, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_cond_pred_corr(int *cond_pred_corr, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_comp_res_pred(int *comp_res_pred, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_comp_res_exit(int *comp_res_exit, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_lam_min(double *value, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_t_min(double *value, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_split_step(int *value, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_arg_set_t_lam_min(int *value, struct d_dense_qcqp_ipm_arg *arg); + +// +hpipm_size_t d_dense_qcqp_ipm_ws_memsize(struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_ipm_ws_create(struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp_ipm_arg *arg, struct d_dense_qcqp_ipm_ws *ws, void *mem); +// +void d_dense_qcqp_ipm_get(char *field, struct d_dense_qcqp_ipm_ws *ws, void *value); +// +void d_dense_qcqp_ipm_get_status(struct d_dense_qcqp_ipm_ws *ws, int *status); +// +void d_dense_qcqp_ipm_get_iter(struct d_dense_qcqp_ipm_ws *ws, int *iter); +// +void d_dense_qcqp_ipm_get_max_res_stat(struct d_dense_qcqp_ipm_ws *ws, double *res_stat); +// +void d_dense_qcqp_ipm_get_max_res_eq(struct d_dense_qcqp_ipm_ws *ws, double *res_eq); +// +void d_dense_qcqp_ipm_get_max_res_ineq(struct d_dense_qcqp_ipm_ws *ws, double *res_ineq); +// +void d_dense_qcqp_ipm_get_max_res_comp(struct d_dense_qcqp_ipm_ws *ws, double *res_comp); +// +void d_dense_qcqp_ipm_get_stat(struct d_dense_qcqp_ipm_ws *ws, double **stat); +// +void d_dense_qcqp_ipm_get_stat_m(struct d_dense_qcqp_ipm_ws *ws, int *stat_m); +// +void d_dense_qcqp_init_var(struct d_dense_qcqp *qp, struct d_dense_qcqp_sol *qp_sol, struct d_dense_qcqp_ipm_arg *arg, struct d_dense_qcqp_ipm_ws *ws); +// +void d_dense_qcqp_ipm_solve(struct d_dense_qcqp *qp, struct d_dense_qcqp_sol *qp_sol, struct d_dense_qcqp_ipm_arg *arg, struct d_dense_qcqp_ipm_ws *ws); +#if 0 +// +void d_dense_qcqp_ipm_predict(struct d_dense_qcqp *qp, struct d_dense_qcqp_sol *qp_sol, struct d_dense_qcqp_ipm_arg *arg, struct d_dense_qcqp_ipm_ws *ws); +// +void d_dense_qcqp_ipm_sens(struct d_dense_qcqp *qp, struct d_dense_qcqp_sol *qp_sol, struct d_dense_qcqp_ipm_arg *arg, struct d_dense_qcqp_ipm_ws *ws); +#endif + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QCQP_IPM_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_res.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_res.h new file mode 100644 index 0000000000..a76f16215e --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_res.h @@ -0,0 +1,107 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_DENSE_QCQP_RES_H_ +#define HPIPM_D_DENSE_QCQP_RES_H_ + + + +#include +#include + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qcqp_res + { + struct d_dense_qcqp_dim *dim; + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + double res_max[4]; // infinity norm of residuals + double res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct d_dense_qcqp_res_ws + { + struct blasfeo_dvec *tmp_nv; // work space of size nv + struct blasfeo_dvec *tmp_nbgq; // work space of size nbM+ngM+nqM + struct blasfeo_dvec *tmp_ns; // work space of size nsM + struct blasfeo_dvec *q_fun; // value for evaluation of quadr constr + struct blasfeo_dvec *q_adj; // value for adjoint of quadr constr + int use_q_fun; // reuse cached value for evaluation of quadr constr + int use_q_adj; // reuse cached value for adjoint of quadr constr + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_dense_qcqp_res_memsize(struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_res_create(struct d_dense_qcqp_dim *dim, struct d_dense_qcqp_res *res, void *mem); +// +hpipm_size_t d_dense_qcqp_res_ws_memsize(struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_res_ws_create(struct d_dense_qcqp_dim *dim, struct d_dense_qcqp_res_ws *workspace, void *mem); +// +void d_dense_qcqp_res_compute(struct d_dense_qcqp *qp, struct d_dense_qcqp_sol *qp_sol, struct d_dense_qcqp_res *res, struct d_dense_qcqp_res_ws *ws); +// +void d_dense_qcqp_res_compute_inf_norm(struct d_dense_qcqp_res *res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_DENSE_QCQP_RES_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_sol.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_sol.h new file mode 100644 index 0000000000..6c697a8e69 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_sol.h @@ -0,0 +1,85 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QCQP_SOL_H_ +#define HPIPM_D_DENSE_QCQP_SOL_H_ + + + +#include +#include + +#include "hpipm_d_dense_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qcqp_sol + { + struct d_dense_qcqp_dim *dim; + struct blasfeo_dvec *v; + struct blasfeo_dvec *pi; + struct blasfeo_dvec *lam; + struct blasfeo_dvec *t; + void *misc; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_dense_qcqp_sol_memsize(struct d_dense_qcqp_dim *dim); +// +void d_dense_qcqp_sol_create(struct d_dense_qcqp_dim *dim, struct d_dense_qcqp_sol *qp_sol, void *memory); +// +void d_dense_qcqp_sol_get_v(struct d_dense_qcqp_sol *qp_sol, double *v); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QCQP_SOL_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_utils.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_utils.h new file mode 100644 index 0000000000..a34218bae4 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qcqp_utils.h @@ -0,0 +1,82 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_DENSE_QCQP_UTILS_H_ +#define HPIPM_D_DENSE_QCQP_UTILS_H_ + + + +#include +#include + +#include "hpipm_d_dense_qcqp_dim.h" +#include "hpipm_d_dense_qcqp.h" +#include "hpipm_d_dense_qcqp_sol.h" +//#include "hpipm_d_dense_qcqp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_dense_qcqp_dim_print(struct d_dense_qcqp_dim *qp_dim); +// +//void d_dense_qcqp_dim_codegen(char *file_name, char *mode, struct d_dense_qcqp_dim *qp_dim); +// +void d_dense_qcqp_print(struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp *qp); +// +//void d_dense_qcqp_codegen(char *file_name, char *mode, struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp *qp); +// +void d_dense_qcqp_sol_print(struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp_sol *dense_qcqp_sol); +// +//void d_dense_qcqp_ipm_arg_codegen(char *file_name, char *mode, struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp_ipm_arg *arg); +// +void d_dense_qcqp_res_print(struct d_dense_qcqp_dim *qp_dim, struct d_dense_qcqp_res *dense_qcqp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_DENSE_QCQP_UTILS_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp.h new file mode 100644 index 0000000000..02fba5a922 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp.h @@ -0,0 +1,207 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QP_H_ +#define HPIPM_D_DENSE_QP_H_ + + + +#include +#include + +#include "hpipm_d_dense_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qp + { + struct d_dense_qp_dim *dim; + struct blasfeo_dmat *Hv; // hessian of cost & vector work space + struct blasfeo_dmat *A; // equality constraint matrix + struct blasfeo_dmat *Ct; // inequality constraints matrix + struct blasfeo_dvec *gz; // gradient of cost & gradient of slacks + struct blasfeo_dvec *b; // equality constraint vector + struct blasfeo_dvec *d; // inequality constraints vector + struct blasfeo_dvec *d_mask; // inequality constraints mask vector + struct blasfeo_dvec *m; // rhs of complementarity condition + struct blasfeo_dvec *Z; // (diagonal) hessian of slacks + int *idxb; // indices of box constrained variables within [u; x] + int *idxs_rev; // index of soft constraints (reverse storage) + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_dense_qp_memsize(struct d_dense_qp_dim *dim); +// +void d_dense_qp_create(struct d_dense_qp_dim *dim, struct d_dense_qp *qp, void *memory); + +// setters - colmaj +// +void d_dense_qp_set_all(double *H, double *g, double *A, double *b, int *idxb, double *d_lb, double *d_ub, double *C, double *d_lg, double *d_ug, double *Zl, double *Zu, double *zl, double *zu, int *idxs, double *d_ls, double *d_us, struct d_dense_qp *qp); +// +void d_dense_qp_get_all(struct d_dense_qp *qp, double *H, double *g, double *A, double *b, int *idxb, double *d_lb, double *d_ub, double *C, double *d_lg, double *d_ug, double *Zl, double *Zu, double *zl, double *zu, int *idxs, double *d_ls, double *d_us); +// +void d_dense_qp_set(char *field, void *value, struct d_dense_qp *qp); +// +void d_dense_qp_set_H(double *H, struct d_dense_qp *qp); +// +void d_dense_qp_set_g(double *g, struct d_dense_qp *qp); +// +void d_dense_qp_set_A(double *A, struct d_dense_qp *qp); +// +void d_dense_qp_set_b(double *b, struct d_dense_qp *qp); +// +void d_dense_qp_set_idxb(int *idxb, struct d_dense_qp *qp); +// +void d_dense_qp_set_Jb(double *Jb, struct d_dense_qp *qp); +// +void d_dense_qp_set_lb(double *lb, struct d_dense_qp *qp); +// +void d_dense_qp_set_lb_mask(double *lb, struct d_dense_qp *qp); +// +void d_dense_qp_set_ub(double *ub, struct d_dense_qp *qp); +// +void d_dense_qp_set_ub_mask(double *ub, struct d_dense_qp *qp); +// +void d_dense_qp_set_C(double *C, struct d_dense_qp *qp); +// +void d_dense_qp_set_lg(double *lg, struct d_dense_qp *qp); +// +void d_dense_qp_set_lg_mask(double *lg, struct d_dense_qp *qp); +// +void d_dense_qp_set_ug(double *ug, struct d_dense_qp *qp); +// +void d_dense_qp_set_ug_mask(double *ug, struct d_dense_qp *qp); +// +void d_dense_qp_set_idxs(int *idxs, struct d_dense_qp *qp); +// +void d_dense_qp_set_idxs_rev(int *idxs_rev, struct d_dense_qp *qp); +// +void d_dense_qp_set_Jsb(double *Jsb, struct d_dense_qp *qp); +// +void d_dense_qp_set_Jsg(double *Jsg, struct d_dense_qp *qp); +// +void d_dense_qp_set_Zl(double *Zl, struct d_dense_qp *qp); +// +void d_dense_qp_set_Zu(double *Zu, struct d_dense_qp *qp); +// +void d_dense_qp_set_zl(double *zl, struct d_dense_qp *qp); +// +void d_dense_qp_set_zu(double *zu, struct d_dense_qp *qp); +// +void d_dense_qp_set_ls(double *ls, struct d_dense_qp *qp); +// +void d_dense_qp_set_ls_mask(double *ls, struct d_dense_qp *qp); +// +void d_dense_qp_set_us(double *us, struct d_dense_qp *qp); +// +void d_dense_qp_set_us_mask(double *us, struct d_dense_qp *qp); + +// getters - colmaj +// +void d_dense_qp_get_H(struct d_dense_qp *qp, double *H); +// +void d_dense_qp_get_g(struct d_dense_qp *qp, double *g); +// +void d_dense_qp_get_A(struct d_dense_qp *qp, double *A); +// +void d_dense_qp_get_b(struct d_dense_qp *qp, double *b); +// +void d_dense_qp_get_idxb(struct d_dense_qp *qp, int *idxb); +// +void d_dense_qp_get_lb(struct d_dense_qp *qp, double *lb); +// +void d_dense_qp_get_lb_mask(struct d_dense_qp *qp, double *lb); +// +void d_dense_qp_get_ub(struct d_dense_qp *qp, double *ub); +// +void d_dense_qp_get_ub_mask(struct d_dense_qp *qp, double *ub); +// +void d_dense_qp_get_C(struct d_dense_qp *qp, double *C); +// +void d_dense_qp_get_lg(struct d_dense_qp *qp, double *lg); +// +void d_dense_qp_get_lg_mask(struct d_dense_qp *qp, double *lg); +// +void d_dense_qp_get_ug(struct d_dense_qp *qp, double *ug); +// +void d_dense_qp_get_ug_mask(struct d_dense_qp *qp, double *ug); +// +void d_dense_qp_get_idxs(struct d_dense_qp *qp, int *idxs); +// +void d_dense_qp_get_idxs_rev(struct d_dense_qp *qp, int *idxs_rev); +// +void d_dense_qp_get_Zl(struct d_dense_qp *qp, double *Zl); +// +void d_dense_qp_get_Zu(struct d_dense_qp *qp, double *Zu); +// +void d_dense_qp_get_zl(struct d_dense_qp *qp, double *zl); +// +void d_dense_qp_get_zu(struct d_dense_qp *qp, double *zu); +// +void d_dense_qp_get_ls(struct d_dense_qp *qp, double *ls); +// +void d_dense_qp_get_ls_mask(struct d_dense_qp *qp, double *ls); +// +void d_dense_qp_get_us(struct d_dense_qp *qp, double *us); +// +void d_dense_qp_get_us_mask(struct d_dense_qp *qp, double *us); + +// setters - rowmaj +// +void d_dense_qp_set_all_rowmaj(double *H, double *g, double *A, double *b, int *idxb, double *d_lb, double *d_ub, double *C, double *d_lg, double *d_ug, double *Zl, double *Zu, double *zl, double *zu, int *idxs, double *d_ls, double *d_us, struct d_dense_qp *qp); + +// getters - rowmaj +// +void d_dense_qp_get_all_rowmaj(struct d_dense_qp *qp, double *H, double *g, double *A, double *b, int *idxb, double *d_lb, double *d_ub, double *C, double *d_lg, double *d_ug, double *Zl, double *Zu, double *zl, double *zu, int *idxs, double *d_ls, double *d_us); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_dim.h new file mode 100644 index 0000000000..98a551f312 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_dim.h @@ -0,0 +1,92 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_DENSE_QP_DIM_H_ +#define HPIPM_D_DENSE_QP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qp_dim + { + int nv; // number of variables + int ne; // number of equality constraints + int nb; // number of box constraints + int ng; // number of general constraints + int nsb; // number of softened box constraints + int nsg; // number of softened general constraints + int ns; // number of softened constraints (nsb+nsg) + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_dense_qp_dim_memsize(); +// +void d_dense_qp_dim_create(struct d_dense_qp_dim *qp_dim, void *memory); +// +void d_dense_qp_dim_set_all(int nv, int ne, int nb, int ng, int nsb, int nsg, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set(char *field_name, int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_nv(int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_ne(int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_nb(int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_ng(int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_nsb(int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_nsg(int value, struct d_dense_qp_dim *dim); +// +void d_dense_qp_dim_set_ns(int value, struct d_dense_qp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_DENSE_QP_DIM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_ipm.h new file mode 100644 index 0000000000..e6e5d5d9b5 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_ipm.h @@ -0,0 +1,260 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QP_IPM_H_ +#define HPIPM_D_DENSE_QP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qp_ipm_arg + { + double mu0; // initial value for duality measure + double alpha_min; // exit cond on step length + double res_g_max; // exit cond on inf norm of residuals + double res_b_max; // exit cond on inf norm of residuals + double res_d_max; // exit cond on inf norm of residuals + double res_m_max; // exit cond on inf norm of residuals + double reg_prim; // reg of primal hessian + double reg_dual; // reg of dual hessian + double lam_min; // min value in lam vector + double t_min; // min value in t vector + double tau_min; // min value of barrier parameter + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int scale; // scale hessian + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq + int abs_form; // absolute IPM formulation + int comp_res_exit; // compute residuals on exit (only for abs_form==1) + int comp_res_pred; // compute residuals of prediction + int kkt_fact_alg; // 0 null-space, 1 schur-complement + int remove_lin_dep_eq; // 0 do not, 1 do check and remove linearly dependent equality constraints + int compute_obj; // compute obj on exit + int split_step; // use different steps for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct d_dense_qp_ipm_ws + { + struct d_core_qp_ipm_workspace *core_workspace; + struct d_dense_qp_res_ws *res_ws; + struct d_dense_qp_sol *sol_step; + struct d_dense_qp_sol *sol_itref; + struct d_dense_qp *qp_step; + struct d_dense_qp *qp_itref; + struct d_dense_qp_res *res; + struct d_dense_qp_res *res_itref; + struct d_dense_qp_res *res_step; + struct blasfeo_dvec *Gamma; // + struct blasfeo_dvec *gamma; // + struct blasfeo_dvec *Zs_inv; // + struct blasfeo_dmat *Lv; // + struct blasfeo_dmat *AL; // + struct blasfeo_dmat *Le; // + struct blasfeo_dmat *Ctx; // + struct blasfeo_dvec *lv; // + struct blasfeo_dvec *sv; // scale for Lv + struct blasfeo_dvec *se; // scale for Le + struct blasfeo_dvec *tmp_nbg; // work space of size nb+ng + struct blasfeo_dvec *tmp_ns; // work space of size ns + struct blasfeo_dmat *lq0; + struct blasfeo_dmat *lq1; + struct blasfeo_dvec *tmp_m; + struct blasfeo_dmat *A_LQ; + struct blasfeo_dmat *A_Q; + struct blasfeo_dmat *Zt; + struct blasfeo_dmat *ZtH; + struct blasfeo_dmat *ZtHZ; + struct blasfeo_dvec *xy; + struct blasfeo_dvec *Yxy; + struct blasfeo_dvec *xz; + struct blasfeo_dvec *tmp_nv; + struct blasfeo_dvec *tmp_2ns; + struct blasfeo_dvec *tmp_nv2ns; + struct blasfeo_dmat *A_li; // A of linearly independent equality constraints + struct blasfeo_dvec *b_li; // b of linearly independent equality constraints + struct blasfeo_dmat *A_bkp; // pointer to backup A + struct blasfeo_dvec *b_bkp; // pointer to backup b + struct blasfeo_dmat *Ab_LU; + double *stat; // convergence statistics + int *ipiv_v; + int *ipiv_e; + int *ipiv_e1; + void *lq_work0; + void *lq_work1; + void *lq_work_null; + void *orglq_work_null; + int iter; // iteration number + int stat_max; // iterations saved in stat + int stat_m; // numer of recorded stat per ipm iter + int scale; + int use_hess_fact; + int use_A_fact; + int status; + int lq_fact; // cache from arg + int mask_constr; // use constr mask + int ne_li; // number of linearly independent equality constraints + int ne_bkp; // ne backup + hpipm_size_t memsize; // memory size (in bytes) of workspace + }; + + + +// +hpipm_size_t d_dense_qp_ipm_arg_memsize(struct d_dense_qp_dim *dim); +// +void d_dense_qp_ipm_arg_create(struct d_dense_qp_dim *dim, struct d_dense_qp_ipm_arg *arg, void *mem); +// +void d_dense_qp_ipm_arg_set_default(enum hpipm_mode mode, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set(char *field, void *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_iter_max(int *iter_max, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_alpha_min(double *alpha_min, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_mu0(double *mu0, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_tol_stat(double *tol_stat, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_tol_eq(double *tol_eq, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_tol_ineq(double *tol_ineq, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_tol_comp(double *tol_comp, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_reg_prim(double *reg, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_reg_dual(double *reg, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_warm_start(int *warm_start, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_pred_corr(int *pred_corr, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_cond_pred_corr(int *cond_pred_corr, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_comp_res_pred(int *comp_res_pred, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_comp_res_exit(int *comp_res_exit, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_lam_min(double *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_t_min(double *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_tau_min(double *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_kkt_fact_alg(int *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_remove_lin_dep_eq(int *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_compute_obj(int *value, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_arg_set_t_lam_min(int *value, struct d_dense_qp_ipm_arg *arg); + +// +void d_dense_qp_ipm_arg_set_split_step(int *value, struct d_dense_qp_ipm_arg *arg); + +// +hpipm_size_t d_dense_qp_ipm_ws_memsize(struct d_dense_qp_dim *qp_dim, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_ipm_ws_create(struct d_dense_qp_dim *qp_dim, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws, void *mem); +// +void d_dense_qp_ipm_get(char *field, struct d_dense_qp_ipm_ws *ws, void *value); +// +void d_dense_qp_ipm_get_status(struct d_dense_qp_ipm_ws *ws, int *status); +// +void d_dense_qp_ipm_get_iter(struct d_dense_qp_ipm_ws *ws, int *iter); +// +void d_dense_qp_ipm_get_max_res_stat(struct d_dense_qp_ipm_ws *ws, double *res_stat); +// +void d_dense_qp_ipm_get_max_res_eq(struct d_dense_qp_ipm_ws *ws, double *res_eq); +// +void d_dense_qp_ipm_get_max_res_ineq(struct d_dense_qp_ipm_ws *ws, double *res_ineq); +// +void d_dense_qp_ipm_get_max_res_comp(struct d_dense_qp_ipm_ws *ws, double *res_comp); +// +void d_dense_qp_ipm_get_stat(struct d_dense_qp_ipm_ws *ws, double **stat); +// +void d_dense_qp_ipm_get_stat_m(struct d_dense_qp_ipm_ws *ws, int *stat_m); +// +void d_dense_qp_init_var(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_ipm_abs_step(int kk, struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_ipm_delta_step(int kk, struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_ipm_solve(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_ipm_predict(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_ipm_sens(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_compute_step_length(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QP_IPM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_kkt.h new file mode 100644 index 0000000000..6d05779f4b --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_kkt.h @@ -0,0 +1,72 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QP_KKT_H_ +#define HPIPM_D_DENSE_QP_KKT_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_fact_solve_kkt_unconstr_dense_qp(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_fact_solve_kkt_step_dense_qp(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_fact_lq_solve_kkt_step_dense_qp(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_solve_kkt_step_dense_qp(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_remove_lin_dep_eq(struct d_dense_qp *qp, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_restore_lin_dep_eq(struct d_dense_qp *qp, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); +// +void d_dense_qp_compute_obj(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_ipm_arg *arg, struct d_dense_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QP_KKT_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_res.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_res.h new file mode 100644 index 0000000000..7c2023257a --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_res.h @@ -0,0 +1,105 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_DENSE_QP_RES_H_ +#define HPIPM_D_DENSE_QP_RES_H_ + + + +#include +#include + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qp_res + { + struct d_dense_qp_dim *dim; + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + double res_max[4]; // max of residuals + double res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct d_dense_qp_res_ws + { + struct blasfeo_dvec *tmp_nbg; // work space of size nbM+ngM + struct blasfeo_dvec *tmp_ns; // work space of size nsM + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_dense_qp_res_memsize(struct d_dense_qp_dim *dim); +// +void d_dense_qp_res_create(struct d_dense_qp_dim *dim, struct d_dense_qp_res *res, void *mem); +// +hpipm_size_t d_dense_qp_res_ws_memsize(struct d_dense_qp_dim *dim); +// +void d_dense_qp_res_ws_create(struct d_dense_qp_dim *dim, struct d_dense_qp_res_ws *workspace, void *mem); +// +void d_dense_qp_res_compute(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_res *res, struct d_dense_qp_res_ws *ws); +// +void d_dense_qp_res_compute_lin(struct d_dense_qp *qp, struct d_dense_qp_sol *qp_sol, struct d_dense_qp_sol *qp_step, struct d_dense_qp_res *res, struct d_dense_qp_res_ws *ws); +// +void d_dense_qp_res_compute_inf_norm(struct d_dense_qp_res *res); +// +void d_dense_qp_res_get_all(struct d_dense_qp_res *res, double *res_g, double *res_ls, double *res_us, double *res_b, double *res_d_lb, double *res_d_ub, double *res_d_lg, double *res_d_ug, double *res_d_ls, double *res_d_us, double *res_m_lb, double *res_m_ub, double *res_m_lg, double *res_m_ug, double *res_m_ls, double *res_m_us); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_DENSE_QP_RES_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_sol.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_sol.h new file mode 100644 index 0000000000..aaa3fdb0e4 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_sol.h @@ -0,0 +1,94 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_DENSE_QP_SOL_H_ +#define HPIPM_D_DENSE_QP_SOL_H_ + + + +#include +#include + +#include "hpipm_d_dense_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_dense_qp_sol + { + struct d_dense_qp_dim *dim; + struct blasfeo_dvec *v; + struct blasfeo_dvec *pi; + struct blasfeo_dvec *lam; + struct blasfeo_dvec *t; + void *misc; + double obj; + int valid_obj; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_dense_qp_sol_memsize(struct d_dense_qp_dim *dim); +// +void d_dense_qp_sol_create(struct d_dense_qp_dim *dim, struct d_dense_qp_sol *qp_sol, void *memory); +// +void d_dense_qp_sol_get_all(struct d_dense_qp_sol *qp_sol, double *v, double *ls, double *us, double *pi, double *lam_lb, double *lam_ub, double *lam_lg, double *lam_ug, double *lam_ls, double *lam_us); +// +void d_dense_qp_sol_get(char *field, struct d_dense_qp_sol *sol, void *value); +// +void d_dense_qp_sol_get_v(struct d_dense_qp_sol *sol, double *v); +// +void d_dense_qp_sol_get_valid_obj(struct d_dense_qp_sol *sol, int *valid_obj); +// +void d_dense_qp_sol_get_obj(struct d_dense_qp_sol *sol, double *obj); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_DENSE_QP_SOL_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_utils.h b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_utils.h new file mode 100644 index 0000000000..ccb77aaca3 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_dense_qp_utils.h @@ -0,0 +1,83 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_DENSE_QP_UTILS_H_ +#define HPIPM_D_DENSE_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_d_dense_qp_dim.h" +#include "hpipm_d_dense_qp.h" +#include "hpipm_d_dense_qp_sol.h" +#include "hpipm_d_dense_qp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_dense_qp_dim_print(struct d_dense_qp_dim *qp_dim); +// +//void d_dense_qp_dim_codegen(char *file_name, char *mode, struct d_dense_qp_dim *qp_dim); +// +void d_dense_qp_print(struct d_dense_qp_dim *qp_dim, struct d_dense_qp *qp); +// +//void d_dense_qp_codegen(char *file_name, char *mode, struct d_dense_qp_dim *qp_dim, struct d_dense_qp *qp); +// +void d_dense_qp_sol_print(struct d_dense_qp_dim *qp_dim, struct d_dense_qp_sol *dense_qp_sol); +// +//void d_dense_qp_ipm_arg_codegen(char *file_name, char *mode, struct d_dense_qp_dim *qp_dim, struct d_dense_qp_ipm_arg *arg); +// +void d_dense_qp_res_print(struct d_dense_qp_dim *qp_dim, struct d_dense_qp_res *dense_qp_res); +// +void d_dense_qp_arg_print(struct d_dense_qp_dim *qp_dim, struct d_dense_qp_ipm_arg *qp_ipm_arg); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_DENSE_QP_UTILS_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp.h new file mode 100644 index 0000000000..240c9b04be --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp.h @@ -0,0 +1,303 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QCQP_H_ +#define HPIPM_D_OCP_QCQP_H_ + + + +#include +#include + +#include "hpipm_d_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qcqp + { + struct d_ocp_qcqp_dim *dim; + struct blasfeo_dmat *BAbt; // dynamics matrix & vector work space + struct blasfeo_dmat *RSQrq; // hessian of cost & vector work space + struct blasfeo_dmat *DCt; // inequality constraints matrix + struct blasfeo_dmat **Hq; // hessians of quadratic constraints + struct blasfeo_dvec *b; // dynamics vector + struct blasfeo_dvec *rqz; // gradient of cost & gradient of slacks + struct blasfeo_dvec *d; // inequality constraints vector + struct blasfeo_dvec *d_mask; // inequality constraints mask vector + struct blasfeo_dvec *m; // rhs of complementarity condition + struct blasfeo_dvec *Z; // (diagonal) hessian of slacks + int **idxb; // indices of box constrained variables within [u; x] + int **idxs_rev; // index of soft constraints (reverse storage) + int **Hq_nzero; // for each int, the last 3 bits ...abc, {a,b,c}=0 => {R,S,Q}=0 + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_ocp_qcqp_strsize(); +// +hpipm_size_t d_ocp_qcqp_memsize(struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_create(struct d_ocp_qcqp_dim *dim, struct d_ocp_qcqp *qp, void *memory); +// +void d_ocp_qcqp_copy_all(struct d_ocp_qcqp *qp_orig, struct d_ocp_qcqp *qp_dest); + +// setters +// +void d_ocp_qcqp_set_all_zero(struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_rhs_zero(struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set(char *field_name, int stage, void *value, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_el(char *field_name, int stage, int index, void *value, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_A(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_B(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_b(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Q(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_S(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_R(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_q(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_r(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lb(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lb_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ub(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ub_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lbx(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lbx_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_el_lbx(int stage, int index, double *elem, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ubx(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ubx_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_el_ubx(int stage, int index, double *elem, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lbu(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lbu_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ubu(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ubu_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_idxb(int stage, int *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_idxbx(int stage, int *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Jbx(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_idxbu(int stage, int *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Jbu(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_C(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_D(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lg(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lg_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ug(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_ug_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Qq(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Sq(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Rq(int stage, double *mat, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_qq(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_rq(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_uq(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_uq_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Zl(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Zu(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_zl(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_zu(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lls(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lls_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lus(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_lus_mask(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_idxs(int stage, int *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_idxs_rev(int stage, int *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Jsbu(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Jsbx(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Jsg(int stage, double *vec, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_set_Jsq(int stage, double *vec, struct d_ocp_qcqp *qp); + +// getters +// +void d_ocp_qcqp_get(char *field, int stage, struct d_ocp_qcqp *qp, void *value); +// +void d_ocp_qcqp_get_A(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_B(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_b(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_Q(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_S(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_R(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_q(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_r(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ub(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ub_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lb(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lb_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lbx(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lbx_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ubx(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ubx_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lbu(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lbu_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ubu(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ubu_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_idxb(int stage, struct d_ocp_qcqp *qp, int *vec); +// +//void d_ocp_qcqp_get_idxbx(int stage, struct d_ocp_qcqp *qp, int *vec); +// +//void d_ocp_qcqp_get_Jbx(int stage, struct d_ocp_qcqp *qp, double *vec); +// +//void d_ocp_qcqp_get_idxbu(int stage, struct d_ocp_qcqp *qp, int *vec); +// +//void d_ocp_qcqp_get_Jbu(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_C(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_D(int stage, struct d_ocp_qcqp *qp, double *mat); +// +void d_ocp_qcqp_get_lg(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lg_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ug(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_ug_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_Zl(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_Zu(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_zl(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_zu(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lls(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lls_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lus(int stage, struct d_ocp_qcqp *qp, double *vec); +// +void d_ocp_qcqp_get_lus_mask(int stage, struct d_ocp_qcqp *qp, double *vec); +// XXX only valid if there is one slack per softed constraint !!! +void d_ocp_qcqp_get_idxs(int stage, struct d_ocp_qcqp *qp, int *vec); +// +void d_ocp_qcqp_get_idxs_rev(int stage, struct d_ocp_qcqp *qp, int *vec); +// +//void d_ocp_qcqp_get_Jsbu(int stage, struct d_ocp_qcqp *qp, float *vec); +// +//void d_ocp_qcqp_get_Jsbx(int stage, struct d_ocp_qcqp *qp, float *vec); +// +//void d_ocp_qcqp_get_Jsg(int stage, struct d_ocp_qcqp *qp, float *vec); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_dim.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_dim.h new file mode 100644 index 0000000000..268628a2b2 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_dim.h @@ -0,0 +1,118 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QCQP_DIM_H_ +#define HPIPM_D_OCP_QCQP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qcqp_dim + { + struct d_ocp_qp_dim *qp_dim; // dim of qp approximation + int *nx; // number of states + int *nu; // number of inputs + int *nb; // number of box constraints + int *nbx; // number of (two-sided) state box constraints + int *nbu; // number of (two-sided) input box constraints + int *ng; // number of (two-sided) general constraints + int *nq; // number of (upper) quadratic constraints + int *ns; // number of soft constraints + int *nsbx; // number of (two-sided) soft state box constraints + int *nsbu; // number of (two-sided) soft input box constraints + int *nsg; // number of (two-sided) soft general constraints + int *nsq; // number of (upper) soft quadratic constraints + int N; // horizon length + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_ocp_qcqp_dim_strsize(); +// +hpipm_size_t d_ocp_qcqp_dim_memsize(int N); +// +void d_ocp_qcqp_dim_create(int N, struct d_ocp_qcqp_dim *qp_dim, void *memory); +// +void d_ocp_qcqp_dim_copy_all(struct d_ocp_qcqp_dim *dim_orig, struct d_ocp_qcqp_dim *dim_dest); +// +void d_ocp_qcqp_dim_set(char *field, int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nx(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nu(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nbx(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nbu(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_ng(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nq(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_ns(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nsbx(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nsbu(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nsg(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_set_nsq(int stage, int value, struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_dim_get(struct d_ocp_qcqp_dim *dim, char *field, int stage, int *value); +// +void d_ocp_qcqp_dim_get_N(struct d_ocp_qcqp_dim *dim, int *value); +// +void d_ocp_qcqp_dim_get_nx(struct d_ocp_qcqp_dim *dim, int stage, int *value); +// +void d_ocp_qcqp_dim_get_nu(struct d_ocp_qcqp_dim *dim, int stage, int *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QCQP_DIM_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_ipm.h new file mode 100644 index 0000000000..99f2329dcc --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_ipm.h @@ -0,0 +1,190 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QCQP_IPM_H_ +#define HPIPM_D_OCP_QCQP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qcqp_ipm_arg + { + struct d_ocp_qp_ipm_arg *qp_arg; + double mu0; // initial value for complementarity slackness + double alpha_min; // exit cond on step length + double res_g_max; // exit cond on inf norm of residuals + double res_b_max; // exit cond on inf norm of residuals + double res_d_max; // exit cond on inf norm of residuals + double res_m_max; // exit cond on inf norm of residuals + double reg_prim; // reg of primal hessian + double lam_min; // min value in lam vector + double t_min; // min value in t vector + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int square_root_alg; // 0 classical Riccati, 1 square-root Riccati + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq (for square_root_alg==1) + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution of equality constrains (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol_eq==1) + int comp_res_pred; // compute residuals of prediction + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct d_ocp_qcqp_ipm_ws + { + struct d_ocp_qp_ipm_ws *qp_ws; + struct d_ocp_qp *qp; + struct d_ocp_qp_sol *qp_sol; + struct d_ocp_qcqp_res_ws *qcqp_res_ws; + struct d_ocp_qcqp_res *qcqp_res; + struct blasfeo_dvec *tmp_nuxM; + int iter; // iteration number + int status; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_ocp_qcqp_ipm_arg_strsize(); +// +hpipm_size_t d_ocp_qcqp_ipm_arg_memsize(struct d_ocp_qcqp_dim *ocp_dim); +// +void d_ocp_qcqp_ipm_arg_create(struct d_ocp_qcqp_dim *ocp_dim, struct d_ocp_qcqp_ipm_arg *arg, void *mem); +// +void d_ocp_qcqp_ipm_arg_set_default(enum hpipm_mode mode, struct d_ocp_qcqp_ipm_arg *arg); +// +void d_ocp_qcqp_ipm_arg_set(char *field, void *value, struct d_ocp_qcqp_ipm_arg *arg); +// set maximum number of iterations +void d_ocp_qcqp_ipm_arg_set_iter_max(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// set minimum step lenght +void d_ocp_qcqp_ipm_arg_set_alpha_min(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set initial value of barrier parameter +void d_ocp_qcqp_ipm_arg_set_mu0(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on stationarity condition +void d_ocp_qcqp_ipm_arg_set_tol_stat(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on equality constr +void d_ocp_qcqp_ipm_arg_set_tol_eq(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on inequality constr +void d_ocp_qcqp_ipm_arg_set_tol_ineq(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on complementarity condition +void d_ocp_qcqp_ipm_arg_set_tol_comp(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set regularization of primal variables +void d_ocp_qcqp_ipm_arg_set_reg_prim(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// set warm start: 0 no warm start, 1 primal var +void d_ocp_qcqp_ipm_arg_set_warm_start(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// Mehrotra's predictor-corrector IPM algorithm: 0 no predictor-corrector, 1 use predictor-corrector +void d_ocp_qcqp_ipm_arg_set_pred_corr(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// conditional predictor-corrector: 0 no conditinal predictor-corrector, 1 conditional predictor-corrector +void d_ocp_qcqp_ipm_arg_set_cond_pred_corr(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// set riccati algorithm: 0 classic, 1 square-root +void d_ocp_qcqp_ipm_arg_set_ric_alg(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// compute residuals after solution +void d_ocp_qcqp_ipm_arg_set_comp_res_exit(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// compute residuals of prediction +void d_ocp_qcqp_ipm_arg_set_comp_res_pred(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// min value of lam in the solution +void d_ocp_qcqp_ipm_arg_set_lam_min(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// min value of t in the solution +void d_ocp_qcqp_ipm_arg_set_t_min(double *value, struct d_ocp_qcqp_ipm_arg *arg); +// use different step for primal and dual variables +void d_ocp_qcqp_ipm_arg_set_split_step(int *value, struct d_ocp_qcqp_ipm_arg *arg); +// clip t and lam: 0 no, 1 in Gamma computation, 2 in solution +void d_ocp_qcqp_ipm_arg_set_t_lam_min(int *value, struct d_ocp_qcqp_ipm_arg *arg); + +// +hpipm_size_t d_ocp_qcqp_ipm_ws_strsize(); +// +hpipm_size_t d_ocp_qcqp_ipm_ws_memsize(struct d_ocp_qcqp_dim *ocp_dim, struct d_ocp_qcqp_ipm_arg *arg); +// +void d_ocp_qcqp_ipm_ws_create(struct d_ocp_qcqp_dim *ocp_dim, struct d_ocp_qcqp_ipm_arg *arg, struct d_ocp_qcqp_ipm_ws *ws, void *mem); +// +void d_ocp_qcqp_ipm_get(char *field, struct d_ocp_qcqp_ipm_ws *ws, void *value); +// +void d_ocp_qcqp_ipm_get_status(struct d_ocp_qcqp_ipm_ws *ws, int *status); +// +void d_ocp_qcqp_ipm_get_iter(struct d_ocp_qcqp_ipm_ws *ws, int *iter); +// +void d_ocp_qcqp_ipm_get_max_res_stat(struct d_ocp_qcqp_ipm_ws *ws, double *res_stat); +// +void d_ocp_qcqp_ipm_get_max_res_eq(struct d_ocp_qcqp_ipm_ws *ws, double *res_eq); +// +void d_ocp_qcqp_ipm_get_max_res_ineq(struct d_ocp_qcqp_ipm_ws *ws, double *res_ineq); +// +void d_ocp_qcqp_ipm_get_max_res_comp(struct d_ocp_qcqp_ipm_ws *ws, double *res_comp); +// +void d_ocp_qcqp_ipm_get_stat(struct d_ocp_qcqp_ipm_ws *ws, double **stat); +// +void d_ocp_qcqp_ipm_get_stat_m(struct d_ocp_qcqp_ipm_ws *ws, int *stat_m); +// +void d_ocp_qcqp_init_var(struct d_ocp_qcqp *qp, struct d_ocp_qcqp_sol *qp_sol, struct d_ocp_qcqp_ipm_arg *arg, struct d_ocp_qcqp_ipm_ws *ws); +// +void d_ocp_qcqp_ipm_solve(struct d_ocp_qcqp *qp, struct d_ocp_qcqp_sol *qp_sol, struct d_ocp_qcqp_ipm_arg *arg, struct d_ocp_qcqp_ipm_ws *ws); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_OCP_QCQP_IPM_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_res.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_res.h new file mode 100644 index 0000000000..077f134677 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_res.h @@ -0,0 +1,114 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QCQP_RES_H_ +#define HPIPM_D_OCP_QCQP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qcqp_res + { + struct d_ocp_qcqp_dim *dim; + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + double res_max[4]; // max of residuals + double res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct d_ocp_qcqp_res_ws + { + struct blasfeo_dvec *tmp_nuxM; // work space of size nuM+nxM + struct blasfeo_dvec *tmp_nbgqM; // work space of size nbM+ngM+nqM + struct blasfeo_dvec *tmp_nsM; // work space of size nsM + struct blasfeo_dvec *q_fun; // value for evaluation of quadr constr + struct blasfeo_dvec *q_adj; // value for adjoint of quadr constr + int use_q_fun; // reuse cached value for evaluation of quadr constr + int use_q_adj; // reuse cached value for adjoint of quadr constr + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_ocp_qcqp_res_memsize(struct d_ocp_qcqp_dim *ocp_dim); +// +void d_ocp_qcqp_res_create(struct d_ocp_qcqp_dim *ocp_dim, struct d_ocp_qcqp_res *res, void *mem); +// +hpipm_size_t d_ocp_qcqp_res_ws_memsize(struct d_ocp_qcqp_dim *ocp_dim); +// +void d_ocp_qcqp_res_ws_create(struct d_ocp_qcqp_dim *ocp_dim, struct d_ocp_qcqp_res_ws *workspace, void *mem); +// +void d_ocp_qcqp_res_compute(struct d_ocp_qcqp *qp, struct d_ocp_qcqp_sol *qp_sol, struct d_ocp_qcqp_res *res, struct d_ocp_qcqp_res_ws *ws); +// +void d_ocp_qcqp_res_compute_inf_norm(struct d_ocp_qcqp_res *res); +// +void d_ocp_qcqp_res_get_max_res_stat(struct d_ocp_qcqp_res *res, double *value); +// +void d_ocp_qcqp_res_get_max_res_eq(struct d_ocp_qcqp_res *res, double *value); +// +void d_ocp_qcqp_res_get_max_res_ineq(struct d_ocp_qcqp_res *res, double *value); +// +void d_ocp_qcqp_res_get_max_res_comp(struct d_ocp_qcqp_res *res, double *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_OCP_QCQP_RES_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_sol.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_sol.h new file mode 100644 index 0000000000..68adbfce2d --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_sol.h @@ -0,0 +1,114 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QCQP_SOL_H_ +#define HPIPM_D_OCP_QCQP_SOL_H_ + + + +#include +#include + +#include "hpipm_d_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qcqp_sol + { + struct d_ocp_qcqp_dim *dim; + struct blasfeo_dvec *ux; + struct blasfeo_dvec *pi; + struct blasfeo_dvec *lam; + struct blasfeo_dvec *t; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_ocp_qcqp_sol_strsize(); +// +hpipm_size_t d_ocp_qcqp_sol_memsize(struct d_ocp_qcqp_dim *dim); +// +void d_ocp_qcqp_sol_create(struct d_ocp_qcqp_dim *dim, struct d_ocp_qcqp_sol *qp_sol, void *memory); +// +void d_ocp_qcqp_sol_copy_all(struct d_ocp_qcqp_sol *qp_sol_orig, struct d_ocp_qcqp_sol *qp_sol_dest); +// +void d_ocp_qcqp_sol_get(char *field, int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_u(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_x(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_sl(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_su(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_pi(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_lam_lb(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_lam_ub(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_lam_lg(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_get_lam_ug(int stage, struct d_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_ocp_qcqp_sol_set(char *field, int stage, double *vec, struct d_ocp_qcqp_sol *qp_sol); +// +void d_ocp_qcqp_sol_set_u(int stage, double *vec, struct d_ocp_qcqp_sol *qp_sol); +// +void d_ocp_qcqp_sol_set_x(int stage, double *vec, struct d_ocp_qcqp_sol *qp_sol); +// +void d_ocp_qcqp_sol_set_sl(int stage, double *vec, struct d_ocp_qcqp_sol *qp_sol); +// +void d_ocp_qcqp_sol_set_su(int stage, double *vec, struct d_ocp_qcqp_sol *qp_sol); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QCQP_SOL_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_utils.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_utils.h new file mode 100644 index 0000000000..00248f1dbe --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qcqp_utils.h @@ -0,0 +1,81 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QCQP_UTILS_H_ +#define HPIPM_D_OCP_QCQP_UTILS_H_ + + + +#include +#include + +#include "hpipm_d_ocp_qcqp_dim.h" +#include "hpipm_d_ocp_qp.h" +#include "hpipm_d_ocp_qcqp_sol.h" +#include "hpipm_d_ocp_qcqp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_ocp_qcqp_dim_print(struct d_ocp_qcqp_dim *qcqp_dim); +// +void d_ocp_qcqp_dim_codegen(char *file_name, char *mode, struct d_ocp_qcqp_dim *qcqp_dim); +// +void d_ocp_qcqp_print(struct d_ocp_qcqp_dim *qcqp_dim, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_codegen(char *file_name, char *mode, struct d_ocp_qcqp_dim *qcqp_dim, struct d_ocp_qcqp *qp); +// +void d_ocp_qcqp_sol_print(struct d_ocp_qcqp_dim *qcqp_dim, struct d_ocp_qcqp_sol *ocp_qcqp_sol); +// +void d_ocp_qcqp_ipm_arg_codegen(char *file_name, char *mode, struct d_ocp_qcqp_dim *qcqp_dim, struct d_ocp_qcqp_ipm_arg *arg); +// +void d_ocp_qcqp_res_print(struct d_ocp_qcqp_dim *qcqp_dim, struct d_ocp_qcqp_res *ocp_qcqp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QCQP_UTILS_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp.h new file mode 100644 index 0000000000..ca26cdba34 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp.h @@ -0,0 +1,306 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_H_ +#define HPIPM_D_OCP_QP_H_ + + + +#include +#include + +#include "hpipm_d_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qp + { + struct d_ocp_qp_dim *dim; + struct blasfeo_dmat *BAbt; // dynamics matrix & vector work space + struct blasfeo_dmat *RSQrq; // hessian of cost & vector work space + struct blasfeo_dmat *DCt; // inequality constraints matrix + struct blasfeo_dvec *b; // dynamics vector + struct blasfeo_dvec *rqz; // gradient of cost & gradient of slacks + struct blasfeo_dvec *d; // inequality constraints vector + struct blasfeo_dvec *d_mask; // inequality constraints mask vector + struct blasfeo_dvec *m; // rhs of complementarity condition + struct blasfeo_dvec *Z; // (diagonal) hessian of slacks + int **idxb; // indices of box constrained variables within [u; x] + int **idxs_rev; // index of soft constraints (reverse storage) + int **idxe; // indices of constraints within [bu, bx, g] that are equalities, subset of [0, ..., nbu+nbx+ng-1] + int *diag_H_flag; // flag the fact that Hessian is diagonal + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_ocp_qp_strsize(); +// +hpipm_size_t d_ocp_qp_memsize(struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_create(struct d_ocp_qp_dim *dim, struct d_ocp_qp *qp, void *memory); +// +void d_ocp_qp_copy_all(struct d_ocp_qp *qp_orig, struct d_ocp_qp *qp_dest); + +// setters +// +void d_ocp_qp_set_all_zero(struct d_ocp_qp *qp); +// +void d_ocp_qp_set_rhs_zero(struct d_ocp_qp *qp); +// +void d_ocp_qp_set_all(double **A, double **B, double **b, double **Q, double **S, double **R, double **q, double **r, int **idxbx, double **lbx, double **ubx, int **idxbu, double **lbu, double **ubu, double **C, double **D, double **lg, double **ug, double **Zl, double **Zu, double **zl, double **zu, int **idxs, double **ls, double **us, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_all_rowmaj(double **A, double **B, double **b, double **Q, double **S, double **R, double **q, double **r, int **idxbx, double **lbx, double **ubx, int **idxbu, double **lbu, double **ubu, double **C, double **D, double **lg, double **ug, double **Zl, double **Zu, double **zl, double **zu, int **idxs, double **ls, double **us, struct d_ocp_qp *qp); +// +void d_ocp_qp_set(char *field_name, int stage, void *value, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_el(char *field_name, int stage, int index, void *value, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_A(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_B(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_b(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Q(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_S(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_R(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_q(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_r(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lb(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lb_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ub(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ub_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lbx(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lbx_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_el_lbx(int stage, int index, double *elem, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ubx(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ubx_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_el_ubx(int stage, int index, double *elem, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lbu(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lbu_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ubu(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ubu_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxb(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxbx(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jbx(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxbu(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jbu(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_C(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_D(int stage, double *mat, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lg(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lg_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ug(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_ug_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Zl(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Zu(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_zl(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_zu(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lls(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lls_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lus(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_lus_mask(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxs(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxs_rev(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jsbu(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jsbx(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jsg(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxe(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxbxe(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxbue(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_idxge(int stage, int *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jbxe(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jbue(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_Jge(int stage, double *vec, struct d_ocp_qp *qp); +// +void d_ocp_qp_set_diag_H_flag(int stage, int *value, struct d_ocp_qp *qp); + +// getters +// +void d_ocp_qp_get(char *field, int stage, struct d_ocp_qp *qp, void *value); +// +void d_ocp_qp_get_A(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_B(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_b(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_Q(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_S(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_R(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_q(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_r(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ub(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ub_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lb(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lb_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lbx(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lbx_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ubx(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ubx_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lbu(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lbu_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ubu(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ubu_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_idxb(int stage, struct d_ocp_qp *qp, int *vec); +// +//void d_ocp_qp_get_idxbx(int stage, struct d_ocp_qp *qp, int *vec); +// +//void d_ocp_qp_get_Jbx(int stage, struct d_ocp_qp *qp, double *vec); +// +//void d_ocp_qp_get_idxbu(int stage, struct d_ocp_qp *qp, int *vec); +// +//void d_ocp_qp_get_Jbu(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_C(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_D(int stage, struct d_ocp_qp *qp, double *mat); +// +void d_ocp_qp_get_lg(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lg_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ug(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_ug_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_Zl(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_Zu(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_zl(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_zu(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lls(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lls_mask(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lus(int stage, struct d_ocp_qp *qp, double *vec); +// +void d_ocp_qp_get_lus_mask(int stage, struct d_ocp_qp *qp, double *vec); +// XXX only valid if there is one slack per softed constraint !!! +void d_ocp_qp_get_idxs(int stage, struct d_ocp_qp *qp, int *vec); +// +void d_ocp_qp_get_idxs_rev(int stage, struct d_ocp_qp *qp, int *vec); +// +//void d_ocp_qp_get_Jsbu(int stage, struct d_ocp_qp *qp, float *vec); +// +//void d_ocp_qp_get_Jsbx(int stage, struct d_ocp_qp *qp, float *vec); +// +//void d_ocp_qp_get_Jsg(int stage, struct d_ocp_qp *qp, float *vec); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_dim.h new file mode 100644 index 0000000000..dcfb801d31 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_dim.h @@ -0,0 +1,142 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_DIM_H_ +#define HPIPM_D_OCP_QP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qp_dim + { + int *nx; // number of states + int *nu; // number of inputs + int *nb; // number of box constraints + int *nbx; // number of state box constraints + int *nbu; // number of input box constraints + int *ng; // number of general constraints + int *ns; // number of soft constraints + int *nsbx; // number of soft state box constraints + int *nsbu; // number of soft input box constraints + int *nsg; // number of soft general constraints + int *nbxe; // number of state box constraints which are equality + int *nbue; // number of input box constraints which are equality + int *nge; // number of general constraints which are equality + int N; // horizon length + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_ocp_qp_dim_strsize(); +// +hpipm_size_t d_ocp_qp_dim_memsize(int N); +// +void d_ocp_qp_dim_create(int N, struct d_ocp_qp_dim *qp_dim, void *memory); +// +void d_ocp_qp_dim_copy_all(struct d_ocp_qp_dim *dim_orig, struct d_ocp_qp_dim *dim_dest); +// +void d_ocp_qp_dim_set_all(int *nx, int *nu, int *nbx, int *nbu, int *ng, int *nsbx, int *nsbu, int *nsg, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set(char *field, int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nx(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nu(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nbx(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nbu(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_ng(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_ns(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nsbx(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nsbu(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nsg(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nbxe(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nbue(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_set_nge(int stage, int value, struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_dim_get(struct d_ocp_qp_dim *dim, char *field, int stage, int *value); +// +void d_ocp_qp_dim_get_N(struct d_ocp_qp_dim *dim, int *value); +// +void d_ocp_qp_dim_get_nx(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nu(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nbx(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nbu(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_ng(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_ns(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nsbx(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nsbu(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nsg(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nbxe(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nbue(struct d_ocp_qp_dim *dim, int stage, int *value); +// +void d_ocp_qp_dim_get_nge(struct d_ocp_qp_dim *dim, int stage, int *value); + + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QP_DIM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_ipm.h new file mode 100644 index 0000000000..d2a2833f22 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_ipm.h @@ -0,0 +1,250 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_IPM_H_ +#define HPIPM_D_OCP_QP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qp_ipm_arg + { + double mu0; // initial value for complementarity slackness + double alpha_min; // exit cond on step length + double res_g_max; // exit cond on inf norm of residuals + double res_b_max; // exit cond on inf norm of residuals + double res_d_max; // exit cond on inf norm of residuals + double res_m_max; // exit cond on inf norm of residuals + double reg_prim; // reg of primal hessian + double lam_min; // min value in lam vector + double t_min; // min value in t vector + double tau_min; // min value of barrier parameter + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int square_root_alg; // 0 classical Riccati, 1 square-root Riccati + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq (for square_root_alg==1) + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution of equality constraints (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol_eq==1) + int comp_res_pred; // compute residuals of prediction + int split_step; // use different steps for primal and dual variables + int var_init_scheme; // variables initialization scheme + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct d_ocp_qp_ipm_ws + { + double qp_res[4]; // infinity norm of residuals + struct d_core_qp_ipm_workspace *core_workspace; + struct d_ocp_qp_dim *dim; // cache dim + struct d_ocp_qp_res_ws *res_workspace; + struct d_ocp_qp_sol *sol_step; + struct d_ocp_qp_sol *sol_itref; + struct d_ocp_qp *qp_step; + struct d_ocp_qp *qp_itref; + struct d_ocp_qp_res *res_itref; + struct d_ocp_qp_res *res; + struct blasfeo_dvec *Gamma; // hessian update + struct blasfeo_dvec *gamma; // hessian update + struct blasfeo_dvec *tmp_nuxM; // work space of size nxM + struct blasfeo_dvec *tmp_nbgM; // work space of size nbM+ngM + struct blasfeo_dvec *tmp_nsM; // work space of size nsM + struct blasfeo_dvec *Pb; // Pb + struct blasfeo_dvec *Zs_inv; + struct blasfeo_dvec *tmp_m; + struct blasfeo_dvec *l; // cache linear part for _get_ric_xxx + struct blasfeo_dmat *L; + struct blasfeo_dmat *Ls; + struct blasfeo_dmat *P; + struct blasfeo_dmat *Lh; + struct blasfeo_dmat *AL; + struct blasfeo_dmat *lq0; + struct blasfeo_dmat *tmp_nxM_nxM; + double *stat; // convergence statistics + int *use_hess_fact; + void *lq_work0; + int iter; // iteration number + int stat_max; // iterations saved in stat + int stat_m; // number of recorded stat per IPM iter + int use_Pb; + int status; // solver status + int square_root_alg; // cache from arg + int lq_fact; // cache from arg + int mask_constr; // use constr mask + int valid_ric_vec; // meaningful riccati vectors + int valid_ric_p; // form of riccati p: 0 p*inv(L), 1 p + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_ocp_qp_ipm_arg_strsize(); +// +hpipm_size_t d_ocp_qp_ipm_arg_memsize(struct d_ocp_qp_dim *ocp_dim); +// +void d_ocp_qp_ipm_arg_create(struct d_ocp_qp_dim *ocp_dim, struct d_ocp_qp_ipm_arg *arg, void *mem); +// +void d_ocp_qp_ipm_arg_set_default(enum hpipm_mode mode, struct d_ocp_qp_ipm_arg *arg); +// +void d_ocp_qp_ipm_arg_set(char *field, void *value, struct d_ocp_qp_ipm_arg *arg); +// set maximum number of iterations +void d_ocp_qp_ipm_arg_set_iter_max(int *iter_max, struct d_ocp_qp_ipm_arg *arg); +// set minimum step lenght +void d_ocp_qp_ipm_arg_set_alpha_min(double *alpha_min, struct d_ocp_qp_ipm_arg *arg); +// set initial value of barrier parameter +void d_ocp_qp_ipm_arg_set_mu0(double *mu0, struct d_ocp_qp_ipm_arg *arg); +// set exit tolerance on stationarity condition +void d_ocp_qp_ipm_arg_set_tol_stat(double *tol_stat, struct d_ocp_qp_ipm_arg *arg); +// set exit tolerance on equality constr +void d_ocp_qp_ipm_arg_set_tol_eq(double *tol_eq, struct d_ocp_qp_ipm_arg *arg); +// set exit tolerance on inequality constr +void d_ocp_qp_ipm_arg_set_tol_ineq(double *tol_ineq, struct d_ocp_qp_ipm_arg *arg); +// set exit tolerance on complementarity condition +void d_ocp_qp_ipm_arg_set_tol_comp(double *tol_comp, struct d_ocp_qp_ipm_arg *arg); +// set regularization of primal variables +void d_ocp_qp_ipm_arg_set_reg_prim(double *tol_comp, struct d_ocp_qp_ipm_arg *arg); +// set warm start: 0 no warm start, 1 primal var +void d_ocp_qp_ipm_arg_set_warm_start(int *warm_start, struct d_ocp_qp_ipm_arg *arg); +// Mehrotra's predictor-corrector IPM algorithm: 0 no predictor-corrector, 1 use predictor-corrector +void d_ocp_qp_ipm_arg_set_pred_corr(int *pred_corr, struct d_ocp_qp_ipm_arg *arg); +// conditional predictor-corrector: 0 no conditinal predictor-corrector, 1 conditional predictor-corrector +void d_ocp_qp_ipm_arg_set_cond_pred_corr(int *value, struct d_ocp_qp_ipm_arg *arg); +// set riccati algorithm: 0 classic, 1 square-root +void d_ocp_qp_ipm_arg_set_ric_alg(int *value, struct d_ocp_qp_ipm_arg *arg); +// dual solution of equality constraints (only for abs_form==1) +void d_ocp_qp_ipm_arg_set_comp_dual_sol_eq(int *value, struct d_ocp_qp_ipm_arg *arg); +// compute residuals after solution +void d_ocp_qp_ipm_arg_set_comp_res_exit(int *value, struct d_ocp_qp_ipm_arg *arg); +// compute residuals of prediction +void d_ocp_qp_ipm_arg_set_comp_res_pred(int *value, struct d_ocp_qp_ipm_arg *arg); +// min value of lam in the solution +void d_ocp_qp_ipm_arg_set_lam_min(double *value, struct d_ocp_qp_ipm_arg *arg); +// min value of t in the solution +void d_ocp_qp_ipm_arg_set_t_min(double *value, struct d_ocp_qp_ipm_arg *arg); +// min value of tau in the solution +void d_ocp_qp_ipm_arg_set_tau_min(double *value, struct d_ocp_qp_ipm_arg *arg); +// set split step: 0 same step, 1 different step for primal and dual variables +void d_ocp_qp_ipm_arg_set_split_step(int *value, struct d_ocp_qp_ipm_arg *arg); +// variables initialization scheme +void d_ocp_qp_ipm_arg_set_var_init_scheme(int *value, struct d_ocp_qp_ipm_arg *arg); +// clip t and lam: 0 no, 1 in Gamma computation, 2 in solution +void d_ocp_qp_ipm_arg_set_t_lam_min(int *value, struct d_ocp_qp_ipm_arg *arg); + +// +hpipm_size_t d_ocp_qp_ipm_ws_strsize(); +// +hpipm_size_t d_ocp_qp_ipm_ws_memsize(struct d_ocp_qp_dim *ocp_dim, struct d_ocp_qp_ipm_arg *arg); +// +void d_ocp_qp_ipm_ws_create(struct d_ocp_qp_dim *ocp_dim, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, void *mem); +// +void d_ocp_qp_ipm_get(char *field, struct d_ocp_qp_ipm_ws *ws, void *value); +// +void d_ocp_qp_ipm_get_status(struct d_ocp_qp_ipm_ws *ws, int *status); +// +void d_ocp_qp_ipm_get_iter(struct d_ocp_qp_ipm_ws *ws, int *iter); +// +void d_ocp_qp_ipm_get_max_res_stat(struct d_ocp_qp_ipm_ws *ws, double *res_stat); +// +void d_ocp_qp_ipm_get_max_res_eq(struct d_ocp_qp_ipm_ws *ws, double *res_eq); +// +void d_ocp_qp_ipm_get_max_res_ineq(struct d_ocp_qp_ipm_ws *ws, double *res_ineq); +// +void d_ocp_qp_ipm_get_max_res_comp(struct d_ocp_qp_ipm_ws *ws, double *res_comp); +// +void d_ocp_qp_ipm_get_stat(struct d_ocp_qp_ipm_ws *ws, double **stat); +// +void d_ocp_qp_ipm_get_stat_m(struct d_ocp_qp_ipm_ws *ws, int *stat_m); +// +void d_ocp_qp_ipm_get_ric_Lr(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *Lr); +// +void d_ocp_qp_ipm_get_ric_Ls(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *Ls); +// +void d_ocp_qp_ipm_get_ric_P(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *P); +// +void d_ocp_qp_ipm_get_ric_lr(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *lr); +// +void d_ocp_qp_ipm_get_ric_p(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *p); +// feedback control gain in the form u = K x + k +void d_ocp_qp_ipm_get_ric_K(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *K); +// feedback control gain in the form u = K x + k +void d_ocp_qp_ipm_get_ric_k(struct d_ocp_qp *qp, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws, int stage, double *k); +// +void d_ocp_qp_init_var(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_ipm_abs_step(int kk, struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_ipm_delta_step(int kk, struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_ipm_solve(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_ipm_predict(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_ipm_sens(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); + + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_OCP_QP_IPM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_kkt.h new file mode 100644 index 0000000000..19dcec32ca --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_kkt.h @@ -0,0 +1,66 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_KKT_H_ +#define HPIPM_D_OCP_QP_KKT_H_ + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + +// +void d_ocp_qp_fact_solve_kkt_unconstr(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_fact_solve_kkt_step(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_fact_lq_solve_kkt_step(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); +// +void d_ocp_qp_solve_kkt_step(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_ipm_arg *arg, struct d_ocp_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // HPIPM_D_OCP_QP_KKT_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_red.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_red.h new file mode 100644 index 0000000000..f0482b0444 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_red.h @@ -0,0 +1,117 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_RED_H_ +#define HPIPM_D_OCP_QP_RED_H_ + + + +#include +#include + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qp_reduce_eq_dof_arg + { + double lam_min; + double t_min; + int alias_unchanged; // do not keep copy unchanged stage + int comp_prim_sol; // primal solution (v) + int comp_dual_sol_eq; // dual solution equality constr (pi) + int comp_dual_sol_ineq; // dual solution inequality constr (lam t) + hpipm_size_t memsize; // memory size in bytes + }; + + + +struct d_ocp_qp_reduce_eq_dof_ws + { + struct blasfeo_dvec *tmp_nuxM; + struct blasfeo_dvec *tmp_nbgM; + int *e_imask_ux; + int *e_imask_d; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +void d_ocp_qp_dim_reduce_eq_dof(struct d_ocp_qp_dim *dim, struct d_ocp_qp_dim *dim_red); +// +hpipm_size_t d_ocp_qp_reduce_eq_dof_arg_memsize(); +// +void d_ocp_qp_reduce_eq_dof_arg_create(struct d_ocp_qp_reduce_eq_dof_arg *arg, void *mem); +// +void d_ocp_qp_reduce_eq_dof_arg_set_default(struct d_ocp_qp_reduce_eq_dof_arg *arg); +// +void d_ocp_qp_reduce_eq_dof_arg_set_alias_unchanged(struct d_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +void d_ocp_qp_reduce_eq_dof_arg_set_comp_prim_sol(struct d_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +void d_ocp_qp_reduce_eq_dof_arg_set_comp_dual_sol_eq(struct d_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +void d_ocp_qp_reduce_eq_dof_arg_set_comp_dual_sol_ineq(struct d_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +hpipm_size_t d_ocp_qp_reduce_eq_dof_ws_memsize(struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_reduce_eq_dof_ws_create(struct d_ocp_qp_dim *dim, struct d_ocp_qp_reduce_eq_dof_ws *work, void *mem); +// +void d_ocp_qp_reduce_eq_dof(struct d_ocp_qp *qp, struct d_ocp_qp *qp_red, struct d_ocp_qp_reduce_eq_dof_arg *arg, struct d_ocp_qp_reduce_eq_dof_ws *work); +// +void d_ocp_qp_reduce_eq_dof_lhs(struct d_ocp_qp *qp, struct d_ocp_qp *qp_red, struct d_ocp_qp_reduce_eq_dof_arg *arg, struct d_ocp_qp_reduce_eq_dof_ws *work); +// +void d_ocp_qp_reduce_eq_dof_rhs(struct d_ocp_qp *qp, struct d_ocp_qp *qp_red, struct d_ocp_qp_reduce_eq_dof_arg *arg, struct d_ocp_qp_reduce_eq_dof_ws *work); +// +void d_ocp_qp_restore_eq_dof(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol_red, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_reduce_eq_dof_arg *arg, struct d_ocp_qp_reduce_eq_dof_ws *work); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QP_RED_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_res.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_res.h new file mode 100644 index 0000000000..061c5729cd --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_res.h @@ -0,0 +1,112 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_RES_H_ +#define HPIPM_D_OCP_QP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qp_res + { + struct d_ocp_qp_dim *dim; + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + double res_max[4]; // max of residuals + double res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct d_ocp_qp_res_ws + { + struct blasfeo_dvec *tmp_nbgM; // work space of size nbM+ngM + struct blasfeo_dvec *tmp_nsM; // work space of size nsM + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_ocp_qp_res_memsize(struct d_ocp_qp_dim *ocp_dim); +// +void d_ocp_qp_res_create(struct d_ocp_qp_dim *ocp_dim, struct d_ocp_qp_res *res, void *mem); +// +hpipm_size_t d_ocp_qp_res_ws_memsize(struct d_ocp_qp_dim *ocp_dim); +// +void d_ocp_qp_res_ws_create(struct d_ocp_qp_dim *ocp_dim, struct d_ocp_qp_res_ws *workspace, void *mem); +// +void d_ocp_qp_res_compute(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_res *res, struct d_ocp_qp_res_ws *ws); +// +void d_ocp_qp_res_compute_lin(struct d_ocp_qp *qp, struct d_ocp_qp_sol *qp_sol, struct d_ocp_qp_sol *qp_step, struct d_ocp_qp_res *res, struct d_ocp_qp_res_ws *ws); +// +void d_ocp_qp_res_compute_inf_norm(struct d_ocp_qp_res *res); +// +void d_ocp_qp_res_get_all(struct d_ocp_qp_res *res, double **res_r, double **res_q, double **res_ls, double **res_us, double **res_b, double **res_d_lb, double **res_d_ub, double **res_d_lg, double **res_d_ug, double **res_d_ls, double **res_d_us, double **res_m_lb, double **res_m_ub, double **res_m_lg, double **res_m_ug, double **res_m_ls, double **res_m_us); +// +void d_ocp_qp_res_get_max_res_stat(struct d_ocp_qp_res *res, double *value); +// +void d_ocp_qp_res_get_max_res_eq(struct d_ocp_qp_res *res, double *value); +// +void d_ocp_qp_res_get_max_res_ineq(struct d_ocp_qp_res *res, double *value); +// +void d_ocp_qp_res_get_max_res_comp(struct d_ocp_qp_res *res, double *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_OCP_QP_RES_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_sol.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_sol.h new file mode 100644 index 0000000000..eb91f3a7b1 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_sol.h @@ -0,0 +1,128 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_SOL_H_ +#define HPIPM_D_OCP_QP_SOL_H_ + + + +#include +#include + +#include "hpipm_d_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_ocp_qp_sol + { + struct d_ocp_qp_dim *dim; + struct blasfeo_dvec *ux; + struct blasfeo_dvec *pi; + struct blasfeo_dvec *lam; + struct blasfeo_dvec *t; + void *misc; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_ocp_qp_sol_strsize(); +// +hpipm_size_t d_ocp_qp_sol_memsize(struct d_ocp_qp_dim *dim); +// +void d_ocp_qp_sol_create(struct d_ocp_qp_dim *dim, struct d_ocp_qp_sol *qp_sol, void *memory); +// +void d_ocp_qp_sol_copy_all(struct d_ocp_qp_sol *qp_sol_orig, struct d_ocp_qp_sol *qp_sol_dest); +// +void d_ocp_qp_sol_get_all(struct d_ocp_qp_sol *qp_sol, double **u, double **x, double **ls, double **us, double **pi, double **lam_lb, double **lam_ub, double **lam_lg, double **lam_ug, double **lam_ls, double **lam_us); +// +void d_ocp_qp_sol_get_all_rowmaj(struct d_ocp_qp_sol *qp_sol, double **u, double **x, double **ls, double **us, double **pi, double **lam_lb, double **lam_ub, double **lam_lg, double **lam_ug, double **lam_ls, double **lam_us); +// +void d_ocp_qp_sol_set_all(double **u, double **x, double **ls, double **us, double **pi, double **lam_lb, double **lam_ub, double **lam_lg, double **lam_ug, double **lam_ls, double **lam_us, struct d_ocp_qp_sol *qp_sol); +// +void d_ocp_qp_sol_get(char *field, int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_u(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_x(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_sl(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_su(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_pi(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_lb(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_lbu(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_lbx(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_ub(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_ubu(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_ubx(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_lg(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_get_lam_ug(int stage, struct d_ocp_qp_sol *qp_sol, double *vec); +// +void d_ocp_qp_sol_set(char *field, int stage, double *vec, struct d_ocp_qp_sol *qp_sol); +// +void d_ocp_qp_sol_set_u(int stage, double *vec, struct d_ocp_qp_sol *qp_sol); +// +void d_ocp_qp_sol_set_x(int stage, double *vec, struct d_ocp_qp_sol *qp_sol); +// +void d_ocp_qp_sol_set_sl(int stage, double *vec, struct d_ocp_qp_sol *qp_sol); +// +void d_ocp_qp_sol_set_su(int stage, double *vec, struct d_ocp_qp_sol *qp_sol); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QP_SOL_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_utils.h b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_utils.h new file mode 100644 index 0000000000..217e9d94ae --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_ocp_qp_utils.h @@ -0,0 +1,82 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_OCP_QP_UTILS_H_ +#define HPIPM_D_OCP_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_d_ocp_qp_dim.h" +#include "hpipm_d_ocp_qp.h" +#include "hpipm_d_ocp_qp_sol.h" +#include "hpipm_d_ocp_qp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_ocp_qp_dim_print(struct d_ocp_qp_dim *qp_dim); +// +void d_ocp_qp_dim_codegen(char *file_name, char *mode, struct d_ocp_qp_dim *qp_dim); +// +void d_ocp_qp_print(struct d_ocp_qp_dim *qp_dim, struct d_ocp_qp *qp); +// +void d_ocp_qp_codegen(char *file_name, char *mode, struct d_ocp_qp_dim *qp_dim, struct d_ocp_qp *qp); +// +void d_ocp_qp_sol_print(struct d_ocp_qp_dim *qp_dim, struct d_ocp_qp_sol *ocp_qp_sol); +// +void d_ocp_qp_ipm_arg_print(struct d_ocp_qp_dim *qp_dim, struct d_ocp_qp_ipm_arg *arg); +// +void d_ocp_qp_ipm_arg_codegen(char *file_name, char *mode, struct d_ocp_qp_dim *qp_dim, struct d_ocp_qp_ipm_arg *arg); +// +void d_ocp_qp_res_print(struct d_ocp_qp_dim *qp_dim, struct d_ocp_qp_res *ocp_qp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QP_UTILS_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_part_cond.h b/third_party/acados/include/hpipm/include/hpipm_d_part_cond.h new file mode 100644 index 0000000000..1c5f785035 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_part_cond.h @@ -0,0 +1,115 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_PART_COND_H_ +#define HPIPM_D_PART_COND_H_ + + + +#include +#include + +#include "hpipm_common.h" +#include "hpipm_d_cond.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_part_cond_qp_arg + { + struct d_cond_qp_arg *cond_arg; + int N2; + hpipm_size_t memsize; + }; + + + +struct d_part_cond_qp_ws + { + struct d_cond_qp_ws *cond_workspace; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_part_cond_qp_arg_memsize(int N2); +// +void d_part_cond_qp_arg_create(int N2, struct d_part_cond_qp_arg *cond_arg, void *mem); +// +void d_part_cond_qp_arg_set_default(struct d_part_cond_qp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 squre-root +void d_part_cond_qp_arg_set_ric_alg(int ric_alg, struct d_part_cond_qp_arg *cond_arg); +// +void d_part_cond_qp_arg_set_comp_prim_sol(int value, struct d_part_cond_qp_arg *cond_arg); +// +void d_part_cond_qp_arg_set_comp_dual_sol_eq(int value, struct d_part_cond_qp_arg *cond_arg); +// +void d_part_cond_qp_arg_set_comp_dual_sol_ineq(int value, struct d_part_cond_qp_arg *cond_arg); + +// +void d_part_cond_qp_compute_block_size(int N, int N2, int *block_size); +// +void d_part_cond_qp_compute_dim(struct d_ocp_qp_dim *ocp_dim, int *block_size, struct d_ocp_qp_dim *part_dense_dim); +// +hpipm_size_t d_part_cond_qp_ws_memsize(struct d_ocp_qp_dim *ocp_dim, int *block_size, struct d_ocp_qp_dim *part_dense_dim, struct d_part_cond_qp_arg *cond_arg); +// +void d_part_cond_qp_ws_create(struct d_ocp_qp_dim *ocp_dim, int *block_size, struct d_ocp_qp_dim *part_dense_dim, struct d_part_cond_qp_arg *cond_arg, struct d_part_cond_qp_ws *cond_ws, void *mem); +// +void d_part_cond_qp_cond(struct d_ocp_qp *ocp_qp, struct d_ocp_qp *part_dense_qp, struct d_part_cond_qp_arg *cond_arg, struct d_part_cond_qp_ws *cond_ws); +// +void d_part_cond_qp_cond_lhs(struct d_ocp_qp *ocp_qp, struct d_ocp_qp *part_dense_qp, struct d_part_cond_qp_arg *cond_arg, struct d_part_cond_qp_ws *cond_ws); +// +void d_part_cond_qp_cond_rhs(struct d_ocp_qp *ocp_qp, struct d_ocp_qp *part_dense_qp, struct d_part_cond_qp_arg *cond_arg, struct d_part_cond_qp_ws *cond_ws); +// +void d_part_cond_qp_expand_sol(struct d_ocp_qp *ocp_qp, struct d_ocp_qp *part_dense_qp, struct d_ocp_qp_sol *part_dense_qp_sol, struct d_ocp_qp_sol *ocp_qp_sol, struct d_part_cond_qp_arg *cond_arg, struct d_part_cond_qp_ws *cond_ws); + +// +void d_part_cond_qp_update(int *idxc, struct d_ocp_qp *ocp_qp, struct d_ocp_qp *part_dense_qp, struct d_part_cond_qp_arg *cond_arg, struct d_part_cond_qp_ws *cond_ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_PART_COND_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_part_cond_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_d_part_cond_qcqp.h new file mode 100644 index 0000000000..2d6624e5bb --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_part_cond_qcqp.h @@ -0,0 +1,106 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_PART_COND_QCQP_H_ +#define HPIPM_D_PART_COND_QCQP_H_ + + + +#include +#include + +#include "hpipm_d_cond_qcqp.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_part_cond_qcqp_arg + { + struct d_cond_qcqp_arg *cond_arg; + int N2; + hpipm_size_t memsize; + }; + + + +struct d_part_cond_qcqp_ws + { + struct d_cond_qcqp_ws *cond_ws; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_part_cond_qcqp_arg_memsize(int N2); +// +void d_part_cond_qcqp_arg_create(int N2, struct d_part_cond_qcqp_arg *cond_arg, void *mem); +// +void d_part_cond_qcqp_arg_set_default(struct d_part_cond_qcqp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 squre-root +void d_part_cond_qcqp_arg_set_ric_alg(int ric_alg, struct d_part_cond_qcqp_arg *cond_arg); + +// +void d_part_cond_qcqp_compute_block_size(int N, int N2, int *block_size); +// +void d_part_cond_qcqp_compute_dim(struct d_ocp_qcqp_dim *ocp_dim, int *block_size, struct d_ocp_qcqp_dim *part_dense_dim); +// +hpipm_size_t d_part_cond_qcqp_ws_memsize(struct d_ocp_qcqp_dim *ocp_dim, int *block_size, struct d_ocp_qcqp_dim *part_dense_dim, struct d_part_cond_qcqp_arg *cond_arg); +// +void d_part_cond_qcqp_ws_create(struct d_ocp_qcqp_dim *ocp_dim, int *block_size, struct d_ocp_qcqp_dim *part_dense_dim, struct d_part_cond_qcqp_arg *cond_arg, struct d_part_cond_qcqp_ws *cond_ws, void *mem); +// +void d_part_cond_qcqp_cond(struct d_ocp_qcqp *ocp_qp, struct d_ocp_qcqp *part_dense_qp, struct d_part_cond_qcqp_arg *cond_arg, struct d_part_cond_qcqp_ws *cond_ws); +// +void d_part_cond_qcqp_cond_lhs(struct d_ocp_qcqp *ocp_qp, struct d_ocp_qcqp *part_dense_qp, struct d_part_cond_qcqp_arg *cond_arg, struct d_part_cond_qcqp_ws *cond_ws); +// +void d_part_cond_qcqp_cond_rhs(struct d_ocp_qcqp *ocp_qp, struct d_ocp_qcqp *part_dense_qp, struct d_part_cond_qcqp_arg *cond_arg, struct d_part_cond_qcqp_ws *cond_ws); +// +void d_part_cond_qcqp_expand_sol(struct d_ocp_qcqp *ocp_qp, struct d_ocp_qcqp *part_dense_qp, struct d_ocp_qcqp_sol *part_dense_qp_sol, struct d_ocp_qcqp_sol *ocp_qp_sol, struct d_part_cond_qcqp_arg *cond_arg, struct d_part_cond_qcqp_ws *cond_ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_PART_COND_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_sim_erk.h b/third_party/acados/include/hpipm/include/hpipm_d_sim_erk.h new file mode 100644 index 0000000000..320b66bb28 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_sim_erk.h @@ -0,0 +1,122 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_SIM_ERK_H_ +#define HPIPM_D_SIM_ERK_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct d_sim_erk_arg + { + struct d_sim_rk_data *rk_data; // integrator data + double h; // step size + int steps; // number of steps +// int for_sens; // compute adjoint sensitivities +// int adj_sens; // compute adjoint sensitivities + hpipm_size_t memsize; + }; + + + +struct d_sim_erk_ws + { + void (*ode)(int t, double *x, double *p, void *ode_args, double *xdot); // function pointer to ode + void (*vde_for)(int t, double *x, double *p, void *ode_args, double *xdot); // function pointer to forward vde + void (*vde_adj)(int t, double *adj_in, void *ode_args, double *adj_out); // function pointer to adjoint vde + void *ode_args; // pointer to ode args + struct d_sim_erk_arg *erk_arg; // erk arg + double *K; // internal variables + double *x_for; // states and forward sensitivities + double *x_traj; // states at all steps + double *l; // adjoint sensitivities + double *p; // parameter + double *x_tmp; // temporary states and forward sensitivities + double *adj_in; + double *adj_tmp; + int nx; // number of states + int np; // number of parameters + int nf; // number of forward sensitivities + int na; // number of adjoint sensitivities + int nf_max; // max number of forward sensitivities + int na_max; // max number of adjoint sensitivities + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_sim_erk_arg_memsize(); +// +void d_sim_erk_arg_create(struct d_sim_erk_arg *erk_arg, void *mem); +// +void d_sim_erk_arg_set_all(struct d_sim_rk_data *rk_data, double h, int steps, struct d_sim_erk_arg *erk_arg); + +// +hpipm_size_t d_sim_erk_ws_memsize(struct d_sim_erk_arg *erk_arg, int nx, int np, int nf_max, int na_max); +// +void d_sim_erk_ws_create(struct d_sim_erk_arg *erk_arg, int nx, int np, int nf_max, int na_max, struct d_sim_erk_ws *work, void *memory); +// +void d_sim_erk_ws_set_all(int nf, int na, double *x, double *fs, double *bs, double *p, void (*ode)(int t, double *x, double *p, void *ode_args, double *xdot), void (*vde_for)(int t, double *x, double *p, void *ode_args, double *xdot), void (*vde_adj)(int t, double *adj_in, void *ode_args, double *adj_out), void *ode_args, struct d_sim_erk_ws *work); +// number of directions for forward sensitivities +void d_sim_erk_ws_set_nf(int *nf, struct d_sim_erk_ws *work); +// parameters (e.g. inputs) +void d_sim_erk_ws_set_p(double *p, struct d_sim_erk_ws *work); +// state +void d_sim_erk_ws_set_x(double *x, struct d_sim_erk_ws *work); +// forward sensitivities +void d_sim_erk_ws_set_fs(double *fs, struct d_sim_erk_ws *work); +// ode funtion +void d_sim_erk_ws_set_ode(void (*ode)(int t, double *x, double *p, void *ode_args, double *xdot), struct d_sim_erk_ws *work); +// forward vde function +void d_sim_erk_ws_set_vde_for(void (*ode)(int t, double *x, double *p, void *ode_args, double *xdot), struct d_sim_erk_ws *work); +// ode_args, passed straight to the ode/vde_for/vde_adj functions +void d_sim_erk_ws_set_ode_args(void *ode_args, struct d_sim_erk_ws *work); +// state +void d_sim_erk_ws_get_x(struct d_sim_erk_ws *work, double *x); +// forward sensitivities +void d_sim_erk_ws_get_fs(struct d_sim_erk_ws *work, double *fs); +// +void d_sim_erk_solve(struct d_sim_erk_arg *arg, struct d_sim_erk_ws *work); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_D_SIM_ERK_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_sim_rk.h b/third_party/acados/include/hpipm/include/hpipm_d_sim_rk.h new file mode 100644 index 0000000000..a50dcbb491 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_sim_rk.h @@ -0,0 +1,71 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_SIM_RK_H_ +#define HPIPM_D_SIM_RK_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct d_sim_rk_data + { + double *A_rk; // A in butcher tableau + double *B_rk; // b in butcher tableau + double *C_rk; // c in butcher tableau + int expl; // erk vs irk + int ns; // number of stages + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_sim_rk_data_memsize(int ns); +// +void d_sim_rk_data_create(int ns, struct d_sim_rk_data *rk_data, void *memory); +// +void d_sim_rk_data_init_default(char *field, struct d_sim_rk_data *rk_data); +// +void d_sim_rk_data_set_all(int expl, double *A_rk, double *B_rk, double *C_rk, struct d_sim_rk_data *rk_data); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_D_SIM_RK_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp.h new file mode 100644 index 0000000000..f36b51a064 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp.h @@ -0,0 +1,213 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QCQP_H_ +#define HPIPM_D_TREE_OCP_QCQP_H_ + + + +#include +#include + +#include "hpipm_common.h" +#include "hpipm_d_tree_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qcqp + { + struct d_tree_ocp_qcqp_dim *dim; + struct blasfeo_dmat *BAbt; // Nn-1 + struct blasfeo_dmat *RSQrq; // Nn + struct blasfeo_dmat *DCt; // Nn + struct blasfeo_dmat **Hq; // Nn + struct blasfeo_dvec *b; // Nn-1 + struct blasfeo_dvec *rqz; // Nn + struct blasfeo_dvec *d; // Nn + struct blasfeo_dvec *d_mask; // Nn + struct blasfeo_dvec *m; // Nn + struct blasfeo_dvec *Z; // Nn + int **idxb; // indices of box constrained variables within [u; x] // Nn + int **idxs_rev; // index of soft constraints + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_tree_ocp_qcqp_memsize(struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_create(struct d_tree_ocp_qcqp_dim *dim, struct d_tree_ocp_qcqp *qp, void *memory); +// +void d_tree_ocp_qcqp_set_all(double **A, double **B, double **b, double **Q, double **S, double **R, double **q, double **r, int **idxb, double **d_lb, double **d_ub, double **C, double **D, double **d_lg, double **d_ug, double **Zl, double **Zu, double **zl, double **zu, int **idxs, double **d_ls, double **d_us, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set(char *field_name, int node_edge, void *value, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_A(int edge, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_B(int edge, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_b(int edge, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Q(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_S(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_R(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_q(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_r(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lb(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lb_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ub(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ub_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lbx(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lbx_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ubx(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ubx_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lbu(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lbu_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ubu(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ubu_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_idxb(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_idxbx(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Jbx(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_idxbu(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Jbu(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_C(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_D(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lg(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lg_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ug(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_ug_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Qq(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Sq(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Rq(int node, double *mat, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_qq(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_rq(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_uq(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_uq_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Zl(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Zu(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_zl(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_zu(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lls(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lls_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lus(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_lus_mask(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_idxs(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_idxs_rev(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Jsbu(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Jsbx(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Jsg(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_set_Jsq(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_idxe(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_idxbxe(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_idxbue(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_idxge(int node, int *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_Jbxe(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_Jbue(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_Jge(int node, double *vec, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_set_diag_H_flag(int node, int *value, struct d_tree_ocp_qcqp *qp); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_TREE_OCP_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_dim.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_dim.h new file mode 100644 index 0000000000..257b82b252 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_dim.h @@ -0,0 +1,117 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QCQP_DIM_H_ +#define HPIPM_D_TREE_OCP_QCQP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qcqp_dim + { + struct d_tree_ocp_qp_dim *qp_dim; // dim of qp approximation + struct tree *ttree; // tree describing node conndection + int *nx; // number of states // Nn + int *nu; // number of inputs // Nn + int *nb; // number of box constraints // Nn + int *nbx; // number of state box constraints // Nn + int *nbu; // number of input box constraints // Nn + int *ng; // number of general constraints // Nn + int *nq; // number of (upper) quadratic constraints + int *ns; // number of soft constraints // Nn + int *nsbx; // number of soft state box constraints + int *nsbu; // number of soft input box constraints + int *nsg; // number of soft general constraints + int *nsq; // number of (upper) soft quadratic constraints + int Nn; // number of nodes + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_tree_ocp_qcqp_dim_strsize(); +// +hpipm_size_t d_tree_ocp_qcqp_dim_memsize(int Nn); +// +void d_tree_ocp_qcqp_dim_create(int Nn, struct d_tree_ocp_qcqp_dim *qp_dim, void *memory); +// +void d_tree_ocp_qcqp_dim_set_tree(struct tree *ttree, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set(char *field, int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nx(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nu(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nbx(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nbu(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_ng(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nq(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_ns(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nsbx(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nsbu(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nsg(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_dim_set_nsq(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +//void d_tree_ocp_qcqp_dim_set_nbxe(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +//void d_tree_ocp_qcqp_dim_set_nbue(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); +// +//void d_tree_ocp_qcqp_dim_set_nge(int stage, int value, struct d_tree_ocp_qcqp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_TREE_OCP_QCQP_DIM_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_ipm.h new file mode 100644 index 0000000000..4a0fed1067 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_ipm.h @@ -0,0 +1,191 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QCQP_IPM_H_ +#define HPIPM_D_TREE_OCP_QCQP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qcqp_ipm_arg + { + struct d_tree_ocp_qp_ipm_arg *qp_arg; + double mu0; // initial value for complementarity slackness + double alpha_min; // exit cond on step length + double res_g_max; // exit cond on inf norm of residuals + double res_b_max; // exit cond on inf norm of residuals + double res_d_max; // exit cond on inf norm of residuals + double res_m_max; // exit cond on inf norm of residuals + double reg_prim; // reg of primal hessian + double lam_min; // min value in lam vector + double t_min; // min value in t vector + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol +// int square_root_alg; // 0 classical Riccati, 1 square-root Riccati + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq (for square_root_alg==1) + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution of equality constrains (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol_eq==1) +// int comp_res_pred; // compute residuals of prediction + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct d_tree_ocp_qcqp_ipm_ws + { + struct d_tree_ocp_qp_ipm_ws *qp_ws; + struct d_tree_ocp_qp *qp; + struct d_tree_ocp_qp_sol *qp_sol; + struct d_tree_ocp_qcqp_res_ws *qcqp_res_ws; + struct d_tree_ocp_qcqp_res *qcqp_res; + struct blasfeo_dvec *tmp_nuxM; + int iter; // iteration number + int status; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_tree_ocp_qcqp_ipm_arg_strsize(); +// +hpipm_size_t d_tree_ocp_qcqp_ipm_arg_memsize(struct d_tree_ocp_qcqp_dim *ocp_dim); +// +void d_tree_ocp_qcqp_ipm_arg_create(struct d_tree_ocp_qcqp_dim *ocp_dim, struct d_tree_ocp_qcqp_ipm_arg *arg, void *mem); +// +void d_tree_ocp_qcqp_ipm_arg_set_default(enum hpipm_mode mode, struct d_tree_ocp_qcqp_ipm_arg *arg); +// +void d_tree_ocp_qcqp_ipm_arg_set(char *field, void *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set maximum number of iterations +void d_tree_ocp_qcqp_ipm_arg_set_iter_max(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set minimum step lenght +void d_tree_ocp_qcqp_ipm_arg_set_alpha_min(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set initial value of barrier parameter +void d_tree_ocp_qcqp_ipm_arg_set_mu0(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on stationarity condition +void d_tree_ocp_qcqp_ipm_arg_set_tol_stat(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on equality constr +void d_tree_ocp_qcqp_ipm_arg_set_tol_eq(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on inequality constr +void d_tree_ocp_qcqp_ipm_arg_set_tol_ineq(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on complementarity condition +void d_tree_ocp_qcqp_ipm_arg_set_tol_comp(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set regularization of primal variables +void d_tree_ocp_qcqp_ipm_arg_set_reg_prim(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set warm start: 0 no warm start, 1 primal var +void d_tree_ocp_qcqp_ipm_arg_set_warm_start(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// Mehrotra's predictor-corrector IPM algorithm: 0 no predictor-corrector, 1 use predictor-corrector +void d_tree_ocp_qcqp_ipm_arg_set_pred_corr(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// conditional predictor-corrector: 0 no conditinal predictor-corrector, 1 conditional predictor-corrector +void d_tree_ocp_qcqp_ipm_arg_set_cond_pred_corr(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// set riccati algorithm: 0 classic, 1 square-root +//void d_tree_ocp_qcqp_ipm_arg_set_ric_alg(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// compute residuals after solution +void d_tree_ocp_qcqp_ipm_arg_set_comp_res_exit(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// compute residuals of prediction +//void d_tree_ocp_qcqp_ipm_arg_set_comp_res_pred(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// min value of lam in the solution +void d_tree_ocp_qcqp_ipm_arg_set_lam_min(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// min value of t in the solution +void d_tree_ocp_qcqp_ipm_arg_set_t_min(double *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// use different step for primal and dual variables +void d_tree_ocp_qcqp_ipm_arg_set_split_step(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); +// clip t and lam: 0 no, 1 in Gamma computation, 2 in solution +void d_tree_ocp_qcqp_ipm_arg_set_t_lam_min(int *value, struct d_tree_ocp_qcqp_ipm_arg *arg); + +// +hpipm_size_t d_tree_ocp_qcqp_ipm_ws_strsize(); +// +hpipm_size_t d_tree_ocp_qcqp_ipm_ws_memsize(struct d_tree_ocp_qcqp_dim *ocp_dim, struct d_tree_ocp_qcqp_ipm_arg *arg); +// +void d_tree_ocp_qcqp_ipm_ws_create(struct d_tree_ocp_qcqp_dim *ocp_dim, struct d_tree_ocp_qcqp_ipm_arg *arg, struct d_tree_ocp_qcqp_ipm_ws *ws, void *mem); +// +void d_tree_ocp_qcqp_ipm_get(char *field, struct d_tree_ocp_qcqp_ipm_ws *ws, void *value); +// +void d_tree_ocp_qcqp_ipm_get_status(struct d_tree_ocp_qcqp_ipm_ws *ws, int *status); +// +void d_tree_ocp_qcqp_ipm_get_iter(struct d_tree_ocp_qcqp_ipm_ws *ws, int *iter); +// +void d_tree_ocp_qcqp_ipm_get_max_res_stat(struct d_tree_ocp_qcqp_ipm_ws *ws, double *res_stat); +// +void d_tree_ocp_qcqp_ipm_get_max_res_eq(struct d_tree_ocp_qcqp_ipm_ws *ws, double *res_eq); +// +void d_tree_ocp_qcqp_ipm_get_max_res_ineq(struct d_tree_ocp_qcqp_ipm_ws *ws, double *res_ineq); +// +void d_tree_ocp_qcqp_ipm_get_max_res_comp(struct d_tree_ocp_qcqp_ipm_ws *ws, double *res_comp); +// +void d_tree_ocp_qcqp_ipm_get_stat(struct d_tree_ocp_qcqp_ipm_ws *ws, double **stat); +// +void d_tree_ocp_qcqp_ipm_get_stat_m(struct d_tree_ocp_qcqp_ipm_ws *ws, int *stat_m); +// +void d_tree_ocp_qcqp_init_var(struct d_tree_ocp_qcqp *qp, struct d_tree_ocp_qcqp_sol *qp_sol, struct d_tree_ocp_qcqp_ipm_arg *arg, struct d_tree_ocp_qcqp_ipm_ws *ws); +// +void d_tree_ocp_qcqp_ipm_solve(struct d_tree_ocp_qcqp *qp, struct d_tree_ocp_qcqp_sol *qp_sol, struct d_tree_ocp_qcqp_ipm_arg *arg, struct d_tree_ocp_qcqp_ipm_ws *ws); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_TREE_OCP_QCQP_IPM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_res.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_res.h new file mode 100644 index 0000000000..69eebb1ba4 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_res.h @@ -0,0 +1,108 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QCQP_RES_H_ +#define HPIPM_D_TREE_OCP_QCQP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qcqp_res + { + struct d_tree_ocp_qcqp_dim *dim; + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + double res_max[4]; // max of residuals + double res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct d_tree_ocp_qcqp_res_ws + { + struct blasfeo_dvec *tmp_nuxM; // work space of size nuM+nxM + struct blasfeo_dvec *tmp_nbgqM; // work space of size nbM+ngM+nqM + struct blasfeo_dvec *tmp_nsM; // work space of size nsM + struct blasfeo_dvec *q_fun; // value for evaluation of quadr constr + struct blasfeo_dvec *q_adj; // value for adjoint of quadr constr + int use_q_fun; // reuse cached value for evaluation of quadr constr + int use_q_adj; // reuse cached value for adjoint of quadr constr + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_tree_ocp_qcqp_res_memsize(struct d_tree_ocp_qcqp_dim *ocp_dim); +// +void d_tree_ocp_qcqp_res_create(struct d_tree_ocp_qcqp_dim *ocp_dim, struct d_tree_ocp_qcqp_res *res, void *mem); +// +hpipm_size_t d_tree_ocp_qcqp_res_ws_memsize(struct d_tree_ocp_qcqp_dim *ocp_dim); +// +void d_tree_ocp_qcqp_res_ws_create(struct d_tree_ocp_qcqp_dim *ocp_dim, struct d_tree_ocp_qcqp_res_ws *ws, void *mem); +// +void d_tree_ocp_qcqp_res_compute(struct d_tree_ocp_qcqp *qp, struct d_tree_ocp_qcqp_sol *qp_sol, struct d_tree_ocp_qcqp_res *res, struct d_tree_ocp_qcqp_res_ws *ws); +// +void d_tree_ocp_qcqp_res_compute_inf_norm(struct d_tree_ocp_qcqp_res *res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_TREE_OCP_QCQP_RES_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_sol.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_sol.h new file mode 100644 index 0000000000..cde8de5c51 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_sol.h @@ -0,0 +1,99 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QCQP_SOL_H_ +#define HPIPM_D_TREE_OCP_QCQP_SOL_H_ + + + +#include +#include + +#include "hpipm_d_tree_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct d_tree_ocp_qcqp_sol + { + struct d_tree_ocp_qcqp_dim *dim; + struct blasfeo_dvec *ux; + struct blasfeo_dvec *pi; + struct blasfeo_dvec *lam; + struct blasfeo_dvec *t; + void *misc; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_tree_ocp_qcqp_sol_memsize(struct d_tree_ocp_qcqp_dim *dim); +// +void d_tree_ocp_qcqp_sol_create(struct d_tree_ocp_qcqp_dim *dim, struct d_tree_ocp_qcqp_sol *qp_sol, void *memory); +// +void d_tree_ocp_qcqp_sol_get(char *field, int node_edge, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_u(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_x(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_sl(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_su(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_pi(int edge, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_lam_lb(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_lam_ub(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_lam_lg(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qcqp_sol_get_lam_ug(int node, struct d_tree_ocp_qcqp_sol *qp_sol, double *vec); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_TREE_OCP_QCQP_SOL_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_utils.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_utils.h new file mode 100644 index 0000000000..5ef04fcf66 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qcqp_utils.h @@ -0,0 +1,84 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QP_UTILS_H_ +#define HPIPM_D_TREE_OCP_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_d_tree_ocp_qcqp_dim.h" +#include "hpipm_d_tree_ocp_qcqp.h" +#include "hpipm_d_tree_ocp_qcqp_sol.h" +#include "hpipm_d_tree_ocp_qcqp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_tree_ocp_qcqp_dim_print(struct d_tree_ocp_qcqp_dim *qp_dim); +// +//void d_tree_ocp_qcqp_dim_codegen(char *file_name, char *mode, struct d_tree_ocp_qcqp_dim *qp_dim); +// +void d_tree_ocp_qcqp_print(struct d_tree_ocp_qcqp_dim *qp_dim, struct d_tree_ocp_qcqp *qp); +// +//void d_tree_ocp_qcqp_codegen(char *file_name, char *mode, struct d_tree_ocp_qcqp_dim *qp_dim, struct d_tree_ocp_qcqp *qp); +// +void d_tree_ocp_qcqp_sol_print(struct d_tree_ocp_qcqp_dim *qp_dim, struct d_tree_ocp_qcqp_sol *ocp_qcqp_sol); +// +void d_tree_ocp_qcqp_ipm_arg_print(struct d_tree_ocp_qcqp_dim *qp_dim, struct d_tree_ocp_qcqp_ipm_arg *arg); +// +//void d_tree_ocp_qcqp_ipm_arg_codegen(char *file_name, char *mode, struct d_tree_ocp_qcqp_dim *qp_dim, struct d_tree_ocp_qcqp_ipm_arg *arg); +// +void d_tree_ocp_qcqp_res_print(struct d_tree_ocp_qcqp_dim *qp_dim, struct d_tree_ocp_qcqp_res *ocp_qcqp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_TREE_OCP_QP_UTILS_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp.h new file mode 100644 index 0000000000..1666ad7c71 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp.h @@ -0,0 +1,195 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QP_H_ +#define HPIPM_D_TREE_OCP_QP_H_ + + + +#include +#include + +#include "hpipm_d_tree_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qp + { + struct d_tree_ocp_qp_dim *dim; + struct blasfeo_dmat *BAbt; // Nn-1 + struct blasfeo_dmat *RSQrq; // Nn + struct blasfeo_dmat *DCt; // Nn + struct blasfeo_dvec *b; // Nn-1 + struct blasfeo_dvec *rqz; // Nn + struct blasfeo_dvec *d; // Nn + struct blasfeo_dvec *d_mask; // Nn + struct blasfeo_dvec *m; // Nn + struct blasfeo_dvec *Z; // Nn + int **idxb; // indices of box constrained variables within [u; x] // Nn +// int **idxs; // index of soft constraints + int **idxs_rev; // index of soft constraints + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_tree_ocp_qp_memsize(struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_create(struct d_tree_ocp_qp_dim *dim, struct d_tree_ocp_qp *qp, void *memory); +// +void d_tree_ocp_qp_set_all(double **A, double **B, double **b, double **Q, double **S, double **R, double **q, double **r, int **idxb, double **d_lb, double **d_ub, double **C, double **D, double **d_lg, double **d_ug, double **Zl, double **Zu, double **zl, double **zu, int **idxs, double **d_ls, double **d_us, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set(char *field_name, int node_edge, void *value, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_A(int edge, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_B(int edge, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_b(int edge, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Q(int node, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_S(int node, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_R(int node, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_q(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_r(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lb(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lb_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ub(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ub_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lbx(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lbx_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ubx(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ubx_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lbu(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lbu_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ubu(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ubu_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_idxb(int node, int *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_idxbx(int node, int *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Jbx(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_idxbu(int node, int *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Jbu(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_C(int node, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_D(int node, double *mat, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lg(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lg_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ug(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_ug_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Zl(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Zu(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_zl(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_zu(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lls(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lls_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lus(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_lus_mask(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_idxs(int node, int *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_idxs_rev(int node, int *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Jsbu(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Jsbx(int node, double *vec, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_set_Jsg(int node, double *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_idxe(int node, int *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_idxbxe(int node, int *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_idxbue(int node, int *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_idxge(int node, int *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_Jbxe(int node, double *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_Jbue(int node, double *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_Jge(int node, double *vec, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_set_diag_H_flag(int node, int *value, struct d_tree_ocp_qp *qp); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_TREE_OCP_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_dim.h new file mode 100644 index 0000000000..659b664594 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_dim.h @@ -0,0 +1,111 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QP_DIM_H_ +#define HPIPM_D_TREE_OCP_QP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qp_dim + { + struct tree *ttree; // tree describing node conndection + int *nx; // number of states // Nn + int *nu; // number of inputs // Nn + int *nb; // number of box constraints // Nn + int *nbx; // number of state box constraints // Nn + int *nbu; // number of input box constraints // Nn + int *ng; // number of general constraints // Nn + int *ns; // number of soft constraints // Nn + int *nsbx; // number of soft state box constraints + int *nsbu; // number of soft input box constraints + int *nsg; // number of soft general constraints + int Nn; // number of nodes + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_tree_ocp_qp_dim_strsize(); +// +hpipm_size_t d_tree_ocp_qp_dim_memsize(int Nn); +// +void d_tree_ocp_qp_dim_create(int Nn, struct d_tree_ocp_qp_dim *qp_dim, void *memory); +// +void d_tree_ocp_qp_dim_set_all(struct tree *ttree, int *nx, int *nu, int *nbx, int *nbu, int *ng, int *nsbx, int *nsbu, int *nsg, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_tree(struct tree *ttree, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set(char *field, int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nx(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nu(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nbx(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nbu(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_ng(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_ns(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nsbx(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nsbu(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nsg(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nbxe(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nbue(int stage, int value, struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_dim_set_nge(int stage, int value, struct d_tree_ocp_qp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_TREE_OCP_QP_DIM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_ipm.h new file mode 100644 index 0000000000..fb634208ce --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_ipm.h @@ -0,0 +1,209 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_D_TREE_OCP_QP_IPM_H_ +#define HPIPM_D_TREE_OCP_QP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qp_ipm_arg + { + double mu0; // initial value for duality measure + double alpha_min; // exit cond on step length + double res_g_max; // exit cond on inf norm of residuals + double res_b_max; // exit cond on inf norm of residuals + double res_d_max; // exit cond on inf norm of residuals + double res_m_max; // exit cond on inf norm of residuals + double reg_prim; // reg of primal hessian + double lam_min; // min value in lam vector + double t_min; // min value in t vector + double tau_min; // min value of barrier parameter + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol==1) + int split_step; // use different steps for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct d_tree_ocp_qp_ipm_ws + { + struct d_core_qp_ipm_workspace *core_workspace; + struct d_tree_ocp_qp_res_ws *res_workspace; + struct d_tree_ocp_qp_sol *sol_step; + struct d_tree_ocp_qp_sol *sol_itref; + struct d_tree_ocp_qp *qp_step; + struct d_tree_ocp_qp *qp_itref; + struct d_tree_ocp_qp_res *res_itref; + struct d_tree_ocp_qp_res *res; + struct blasfeo_dvec *Gamma; // hessian update + struct blasfeo_dvec *gamma; // hessian update + struct blasfeo_dvec *tmp_nxM; // work space of size nxM + struct blasfeo_dvec *tmp_nbgM; // work space of size nbgM + struct blasfeo_dvec *tmp_nsM; // work space of size nsM + struct blasfeo_dvec *Pb; // Pb + struct blasfeo_dvec *Zs_inv; + struct blasfeo_dmat *L; + struct blasfeo_dmat *Lh; + struct blasfeo_dmat *AL; + struct blasfeo_dmat *lq0; + struct blasfeo_dvec *tmp_m; + double *stat; // convergence statistics + int *use_hess_fact; + void *lq_work0; + double qp_res[4]; // infinity norm of residuals + int iter; // iteration number + int stat_max; // iterations saved in stat + int stat_m; // number of recorded stat per IPM iter + int use_Pb; + int status; // solver status + int lq_fact; // cache from arg + int mask_constr; // use constr mask + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_tree_ocp_qp_ipm_arg_memsize(struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_ipm_arg_create(struct d_tree_ocp_qp_dim *dim, struct d_tree_ocp_qp_ipm_arg *arg, void *mem); +// +void d_tree_ocp_qp_ipm_arg_set_default(enum hpipm_mode mode, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_iter_max(int *iter_max, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_alpha_min(double *alpha_min, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_mu0(double *mu0, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_tol_stat(double *tol_stat, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_tol_eq(double *tol_eq, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_tol_ineq(double *tol_ineq, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_tol_comp(double *tol_comp, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_reg_prim(double *reg, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_warm_start(int *warm_start, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_pred_corr(int *pred_corr, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_cond_pred_corr(int *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_comp_dual_sol_eq(int *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_comp_res_exit(int *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_lam_min(double *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_t_min(double *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_tau_min(double *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_split_step(int *value, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_arg_set_t_lam_min(int *value, struct d_tree_ocp_qp_ipm_arg *arg); + +// +hpipm_size_t d_tree_ocp_qp_ipm_ws_memsize(struct d_tree_ocp_qp_dim *dim, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_ipm_ws_create(struct d_tree_ocp_qp_dim *dim, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws, void *mem); +// +void d_tree_ocp_qp_ipm_get_status(struct d_tree_ocp_qp_ipm_ws *ws, int *status); +// +void d_tree_ocp_qp_ipm_get_iter(struct d_tree_ocp_qp_ipm_ws *ws, int *iter); +// +void d_tree_ocp_qp_ipm_get_max_res_stat(struct d_tree_ocp_qp_ipm_ws *ws, double *res_stat); +// +void d_tree_ocp_qp_ipm_get_max_res_eq(struct d_tree_ocp_qp_ipm_ws *ws, double *res_eq); +// +void d_tree_ocp_qp_ipm_get_max_res_ineq(struct d_tree_ocp_qp_ipm_ws *ws, double *res_ineq); +// +void d_tree_ocp_qp_ipm_get_max_res_comp(struct d_tree_ocp_qp_ipm_ws *ws, double *res_comp); +// +void d_tree_ocp_qp_ipm_get_stat(struct d_tree_ocp_qp_ipm_ws *ws, double **stat); +// +void d_tree_ocp_qp_ipm_get_stat_m(struct d_tree_ocp_qp_ipm_ws *ws, int *stat_m); +// +void d_tree_ocp_qp_init_var(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); +// +void d_tree_ocp_qp_ipm_abs_step(int kk, struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); +// +void d_tree_ocp_qp_ipm_delta_step(int kk, struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); +// +void d_tree_ocp_qp_ipm_solve(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_TREE_OCP_QP_IPM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_kkt.h new file mode 100644 index 0000000000..4afd52fe4b --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_kkt.h @@ -0,0 +1,52 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + +// +void d_tree_ocp_qp_fact_solve_kkt_unconstr(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); +// +void d_tree_ocp_qp_fact_solve_kkt_step(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); +// +void d_tree_ocp_qp_fact_lq_solve_kkt_step(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); +// +void d_tree_ocp_qp_solve_kkt_step(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_ipm_arg *arg, struct d_tree_ocp_qp_ipm_ws *ws); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_res.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_res.h new file mode 100644 index 0000000000..fe499080ea --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_res.h @@ -0,0 +1,106 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QP_RES_H_ +#define HPIPM_D_TREE_OCP_QP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct d_tree_ocp_qp_res + { + struct d_tree_ocp_qp_dim *dim; + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + double res_max[4]; // max of residuals + double res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct d_tree_ocp_qp_res_ws + { + struct blasfeo_dvec *tmp_nbgM; // work space of size nbM+ngM + struct blasfeo_dvec *tmp_nsM; // work space of size nsM + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t d_tree_ocp_qp_res_memsize(struct d_tree_ocp_qp_dim *ocp_dim); +// +void d_tree_ocp_qp_res_create(struct d_tree_ocp_qp_dim *ocp_dim, struct d_tree_ocp_qp_res *res, void *mem); +// +hpipm_size_t d_tree_ocp_qp_res_ws_memsize(struct d_tree_ocp_qp_dim *ocp_dim); +// +void d_tree_ocp_qp_res_ws_create(struct d_tree_ocp_qp_dim *ocp_dim, struct d_tree_ocp_qp_res_ws *ws, void *mem); +// +void d_tree_ocp_qp_res_get_all(struct d_tree_ocp_qp_res *res, double **res_r, double **res_q, double **res_ls, double **res_us, double **res_b, double **res_d_lb, double **res_d_ub, double **res_d_lg, double **res_d_ug, double **res_d_ls, double **res_d_us, double **res_m_lb, double **res_m_ub, double **res_m_lg, double **res_m_ug, double **res_m_ls, double **res_m_us); +// +void d_tree_ocp_qp_res_compute(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_res *res, struct d_tree_ocp_qp_res_ws *ws); +// +void d_tree_ocp_qp_res_compute_lin(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, struct d_tree_ocp_qp_sol *qp_step, struct d_tree_ocp_qp_res *res, struct d_tree_ocp_qp_res_ws *ws); +// +void d_tree_ocp_qp_res_compute_inf_norm(struct d_tree_ocp_qp_res *res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_TREE_OCP_QP_RES_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_sol.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_sol.h new file mode 100644 index 0000000000..343d5e8ca6 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_sol.h @@ -0,0 +1,100 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QP_SOL_H_ +#define HPIPM_D_TREE_OCP_QP_SOL_H_ + + + +#include +#include + +#include "hpipm_d_tree_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct d_tree_ocp_qp_sol + { + struct d_tree_ocp_qp_dim *dim; + struct blasfeo_dvec *ux; + struct blasfeo_dvec *pi; + struct blasfeo_dvec *lam; + struct blasfeo_dvec *t; + void *misc; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t d_tree_ocp_qp_sol_memsize(struct d_tree_ocp_qp_dim *dim); +// +void d_tree_ocp_qp_sol_create(struct d_tree_ocp_qp_dim *dim, struct d_tree_ocp_qp_sol *qp_sol, void *memory); +// +void d_tree_ocp_qp_sol_get_all(struct d_tree_ocp_qp *qp, struct d_tree_ocp_qp_sol *qp_sol, double **u, double **x, double **ls, double **us, double **pi, double **lam_lb, double **lam_ub, double **lam_lg, double **lam_ug, double **lam_ls, double **lam_us); +// +void d_tree_ocp_qp_sol_get(char *field, int node_edge, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_u(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_x(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_sl(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_su(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_pi(int edge, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_lam_lb(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_lam_ub(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_lam_lg(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); +// +void d_tree_ocp_qp_sol_get_lam_ug(int node, struct d_tree_ocp_qp_sol *qp_sol, double *vec); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_TREE_OCP_QP_SOL_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_utils.h b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_utils.h new file mode 100644 index 0000000000..b689fdc0fa --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_d_tree_ocp_qp_utils.h @@ -0,0 +1,83 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_D_TREE_OCP_QP_UTILS_H_ +#define HPIPM_D_TREE_OCP_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_d_tree_ocp_qp_dim.h" +#include "hpipm_d_tree_ocp_qp.h" +#include "hpipm_d_tree_ocp_qp_sol.h" +#include "hpipm_d_tree_ocp_qp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void d_tree_ocp_qp_dim_print(struct d_tree_ocp_qp_dim *qp_dim); +// +//void d_tree_ocp_qp_dim_codegen(char *file_name, char *mode, struct d_tree_ocp_qp_dim *qp_dim); +// +void d_tree_ocp_qp_print(struct d_tree_ocp_qp_dim *qp_dim, struct d_tree_ocp_qp *qp); +// +//void d_tree_ocp_qp_codegen(char *file_name, char *mode, struct d_tree_ocp_qp_dim *qp_dim, struct d_tree_ocp_qp *qp); +// +void d_tree_ocp_qp_sol_print(struct d_tree_ocp_qp_dim *qp_dim, struct d_tree_ocp_qp_sol *ocp_qp_sol); +// +void d_tree_ocp_qp_ipm_arg_print(struct d_tree_ocp_qp_dim *qp_dim, struct d_tree_ocp_qp_ipm_arg *arg); +// +//void d_tree_ocp_qp_ipm_arg_codegen(char *file_name, char *mode, struct d_tree_ocp_qp_dim *qp_dim, struct d_tree_ocp_qp_ipm_arg *arg); +// +void d_tree_ocp_qp_res_print(struct d_tree_ocp_qp_dim *qp_dim, struct d_tree_ocp_qp_res *ocp_qp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_TREE_OCP_QP_UTILS_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_m_dense_qp.h b/third_party/acados/include/hpipm/include/hpipm_m_dense_qp.h new file mode 100644 index 0000000000..8bc101003e --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_m_dense_qp.h @@ -0,0 +1,68 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + + +#ifndef HPIPM_M_DENSE_QP_H_ +#define HPIPM_M_DENSE_QP_H_ + + + +#include +#include + +#include "hpipm_d_dense_qp.h" +#include "hpipm_s_dense_qp.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +void cvt_d2s_dense_qp(struct d_dense_qp *qpd, struct s_dense_qp *qps); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_M_DENSE_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_m_dense_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_m_dense_qp_dim.h new file mode 100644 index 0000000000..4610321b97 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_m_dense_qp_dim.h @@ -0,0 +1,68 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + + +#ifndef HPIPM_M_DENSE_QP_DIM_H_ +#define HPIPM_M_DENSE_QP_DIM_H_ + + + +#include +#include + +#include "hpipm_d_dense_qp_dim.h" +#include "hpipm_s_dense_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +void cvt_d2s_dense_qp_dim(struct d_dense_qp_dim *qpd, struct s_dense_qp_dim *qps); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_M_DENSE_QP_DIM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp.h b/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp.h new file mode 100644 index 0000000000..95c3dad1aa --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp.h @@ -0,0 +1,49 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void m_cvt_d_ocp_qp_to_s_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp_ipm_hard.h b/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp_ipm_hard.h new file mode 100644 index 0000000000..1c44acee2e --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp_ipm_hard.h @@ -0,0 +1,115 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +struct m_ipm_hard_ocp_qp_workspace + { + struct d_ipm_hard_core_qp_workspace *core_workspace; + struct blasfeo_dvec *dux; + struct blasfeo_dvec *dpi; + struct blasfeo_dvec *dt_lb; + struct blasfeo_dvec *dt_lg; + struct blasfeo_svec *sdux; // XXX + struct blasfeo_svec *sdpi; // XXX + struct blasfeo_dvec *res_g; // q-residuals + struct blasfeo_dvec *res_b; // b-residuals + struct blasfeo_dvec *res_d; // d-residuals XXX remove ??? + struct blasfeo_dvec *res_d_lb; // d-residuals + struct blasfeo_dvec *res_d_ub; // d-residuals + struct blasfeo_dvec *res_d_lg; // d-residuals + struct blasfeo_dvec *res_d_ug; // d-residuals + struct blasfeo_dvec *res_m; // m-residuals + struct blasfeo_dvec *res_m_lb; // m-residuals + struct blasfeo_dvec *res_m_ub; // m-residuals + struct blasfeo_dvec *res_m_lg; // m-residuals + struct blasfeo_dvec *res_m_ug; // m-residuals + struct blasfeo_svec *sres_g; // q-residuals // XXX + struct blasfeo_svec *sres_b; // b-residuals // XXX + struct blasfeo_dvec *Qx_lb; // hessian update + struct blasfeo_dvec *Qx_lg; // hessian update + struct blasfeo_dvec *qx_lb; // gradient update + struct blasfeo_dvec *qx_lg; // gradient update + struct blasfeo_svec *sQx_lb; // hessian update // XXX + struct blasfeo_svec *sQx_lg; // hessian update // XXX + struct blasfeo_svec *sqx_lb; // gradient update // XXX + struct blasfeo_svec *sqx_lg; // gradient update // XXX + struct blasfeo_dvec *tmp_nbM; // work space of size nbM + struct blasfeo_svec *tmp_nxM; // work space of size nxM // XXX + struct blasfeo_dvec *tmp_ngM; // work space of size ngM + struct blasfeo_svec *Pb; // Pb // XXX + struct blasfeo_smat *L; // XXX + struct blasfeo_smat *AL; // XXX + struct blasfeo_svec *sSx; // scaling + struct blasfeo_svec *sSi; // scaling inverted + double *stat; // convergence statistics + double res_mu; // mu-residual + int iter; // iteration number + int compute_Pb; + int scale; + }; + + + +struct m_ipm_hard_ocp_qp_arg + { + double alpha_min; // exit cond on step length + double mu_max; // exit cond on duality measure + double mu0; // initial value for duality measure + int iter_max; // exit cond in iter number + }; + + + +// +hpipm_size_t m_memsize_ipm_hard_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp, struct m_ipm_hard_ocp_qp_arg *arg); +// +void m_create_ipm_hard_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp, struct m_ipm_hard_ocp_qp_arg *arg, struct m_ipm_hard_ocp_qp_workspace *ws, void *mem); +// +void m_solve_ipm_hard_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp, struct d_ocp_qp_sol *qp_sol, struct m_ipm_hard_ocp_qp_workspace *ws); +// +void m_solve_ipm2_hard_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp, struct d_ocp_qp_sol *qp_sol, struct m_ipm_hard_ocp_qp_workspace *ws); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp_kkt.h new file mode 100644 index 0000000000..032fe95b1f --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_m_ocp_qp_kkt.h @@ -0,0 +1,45 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +void m_fact_solve_kkt_step_hard_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp, struct m_ipm_hard_ocp_qp_workspace *ws); +void m_solve_kkt_step_hard_ocp_qp(struct d_ocp_qp *d_qp, struct s_ocp_qp *s_qp, struct m_ipm_hard_ocp_qp_workspace *ws); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/third_party/acados/include/hpipm/include/hpipm_s_cast_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_s_cast_qcqp.h new file mode 100644 index 0000000000..ba01ecb3bd --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_cast_qcqp.h @@ -0,0 +1,72 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_CAST_QCQP_H_ +#define HPIPM_S_CAST_QCQP_H_ + + + +#include +#include + +#include "hpipm_s_dense_qcqp.h" +#include "hpipm_s_dense_qcqp_sol.h" +#include "hpipm_s_ocp_qcqp.h" +#include "hpipm_s_ocp_qcqp_dim.h" +#include "hpipm_s_ocp_qcqp_sol.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_cast_qcqp_compute_dim(struct s_ocp_qcqp_dim *ocp_dim, struct s_dense_qcqp_dim *dense_dim); +// +void s_cast_qcqp_cond(struct s_ocp_qcqp *ocp_qp, struct s_dense_qcqp *dense_qp); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_CAST_QCQP_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_cond.h b/third_party/acados/include/hpipm/include/hpipm_s_cond.h new file mode 100644 index 0000000000..30116798b7 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_cond.h @@ -0,0 +1,137 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_COND_H_ +#define HPIPM_S_COND_H_ + + + +#include +#include + +#include "hpipm_s_dense_qp.h" +#include "hpipm_s_dense_qp_sol.h" +#include "hpipm_s_ocp_qp.h" +#include "hpipm_s_ocp_qp_dim.h" +#include "hpipm_s_ocp_qp_sol.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_cond_qp_arg + { + int cond_last_stage; // condense last stage + int cond_alg; // condensing algorithm: 0 N2-nx3, 1 N3-nx2 + int comp_prim_sol; // primal solution (v) + int comp_dual_sol_eq; // dual solution equality constr (pi) + int comp_dual_sol_ineq; // dual solution inequality constr (lam t) + int square_root_alg; // square root algorithm (faster but requires RSQ>0) + hpipm_size_t memsize; + }; + + + +struct s_cond_qp_ws + { + struct blasfeo_smat *Gamma; + struct blasfeo_smat *GammaQ; + struct blasfeo_smat *L; + struct blasfeo_smat *Lx; + struct blasfeo_smat *AL; + struct blasfeo_svec *Gammab; + struct blasfeo_svec *l; + struct blasfeo_svec *tmp_nbgM; + struct blasfeo_svec *tmp_nuxM; + int bs; // block size + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_cond_qp_arg_memsize(); +// +void s_cond_qp_arg_create(struct s_cond_qp_arg *cond_arg, void *mem); +// +void s_cond_qp_arg_set_default(struct s_cond_qp_arg *cond_arg); +// condensing algorithm: 0 N2-nx3, 1 N3-nx2 +void s_cond_qp_arg_set_cond_alg(int cond_alg, struct s_cond_qp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 square-root +void s_cond_qp_arg_set_ric_alg(int ric_alg, struct s_cond_qp_arg *cond_arg); +// condense last stage: 0 last stage disregarded, 1 last stage condensed too +void s_cond_qp_arg_set_cond_last_stage(int cond_last_stage, struct s_cond_qp_arg *cond_arg); +// +void s_cond_qp_arg_set_comp_prim_sol(int value, struct s_cond_qp_arg *cond_arg); +// +void s_cond_qp_arg_set_comp_dual_sol_eq(int value, struct s_cond_qp_arg *cond_arg); +// +void s_cond_qp_arg_set_comp_dual_sol_ineq(int value, struct s_cond_qp_arg *cond_arg); + +// +void s_cond_qp_compute_dim(struct s_ocp_qp_dim *ocp_dim, struct s_dense_qp_dim *dense_dim); +// +hpipm_size_t s_cond_qp_ws_memsize(struct s_ocp_qp_dim *ocp_dim, struct s_cond_qp_arg *cond_arg); +// +void s_cond_qp_ws_create(struct s_ocp_qp_dim *ocp_dim, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws, void *mem); +// +void s_cond_qp_cond(struct s_ocp_qp *ocp_qp, struct s_dense_qp *dense_qp, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_qp_cond_lhs(struct s_ocp_qp *ocp_qp, struct s_dense_qp *dense_qp, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_qp_cond_rhs(struct s_ocp_qp *ocp_qp, struct s_dense_qp *dense_qp, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_qp_expand_sol(struct s_ocp_qp *ocp_qp, struct s_dense_qp_sol *dense_qp_sol, struct s_ocp_qp_sol *ocp_qp_sol, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// TODO remove +void s_cond_qp_expand_primal_sol(struct s_ocp_qp *ocp_qp, struct s_dense_qp_sol *dense_qp_sol, struct s_ocp_qp_sol *ocp_qp_sol, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); + +// +void s_cond_qp_update(int *idxc, struct s_ocp_qp *ocp_qp, struct s_dense_qp *dense_qp, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_COND_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_cond_aux.h b/third_party/acados/include/hpipm/include/hpipm_s_cond_aux.h new file mode 100644 index 0000000000..003472ab9f --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_cond_aux.h @@ -0,0 +1,92 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_COND_AUX_H_ +#define HPIPM_S_COND_AUX_H_ + + + +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_cond_BAbt(struct s_ocp_qp *ocp_qp, struct blasfeo_smat *BAbt2, struct blasfeo_svec *b2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_BAt(struct s_ocp_qp *ocp_qp, struct blasfeo_smat *BAbt2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_b(struct s_ocp_qp *ocp_qp, struct blasfeo_svec *b2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_RSQrq(struct s_ocp_qp *ocp_qp, struct blasfeo_smat *RSQrq2, struct blasfeo_svec *rq2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_RSQ(struct s_ocp_qp *ocp_qp, struct blasfeo_smat *RSQrq2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_rq(struct s_ocp_qp *ocp_qp, struct blasfeo_svec *rq2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_DCtd(struct s_ocp_qp *ocp_qp, int *idxb2, struct blasfeo_smat *DCt2, struct blasfeo_svec *d2, struct blasfeo_svec *d_mask2, int *idxs_rev2, struct blasfeo_svec *Z2, struct blasfeo_svec *z2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_DCt(struct s_ocp_qp *ocp_qp, int *idxb2, struct blasfeo_smat *DCt2, int *idxs_rev2, struct blasfeo_svec *Z2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_cond_d(struct s_ocp_qp *ocp_qp, struct blasfeo_svec *d2, struct blasfeo_svec *d_mask2, struct blasfeo_svec *z2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_expand_sol(struct s_ocp_qp *ocp_qp, struct s_dense_qp_sol *dense_qp_sol, struct s_ocp_qp_sol *ocp_qp_sol, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_expand_primal_sol(struct s_ocp_qp *ocp_qp, struct s_dense_qp_sol *dense_qp_sol, struct s_ocp_qp_sol *ocp_qp_sol, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); + +// +void s_update_cond_BAbt(int *idxc, struct s_ocp_qp *ocp_qp, struct blasfeo_smat *BAbt2, struct blasfeo_svec *b2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_update_cond_RSQrq_N2nx3(int *idxc, struct s_ocp_qp *ocp_qp, struct blasfeo_smat *RSQrq2, struct blasfeo_svec *rq2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); +// +void s_update_cond_DCtd(int *idxc, struct s_ocp_qp *ocp_qp, int *idxb2, struct blasfeo_smat *DCt2, struct blasfeo_svec *d2, int *idxs2, struct blasfeo_svec *Z2, struct blasfeo_svec *z2, struct s_cond_qp_arg *cond_arg, struct s_cond_qp_ws *cond_ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_COND_AUX_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_cond_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_s_cond_qcqp.h new file mode 100644 index 0000000000..c36678abd5 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_cond_qcqp.h @@ -0,0 +1,130 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_COND_QCQP_H_ +#define HPIPM_S_COND_QCQP_H_ + + + +#include +#include + +#include "hpipm_s_dense_qcqp.h" +#include "hpipm_s_dense_qcqp_sol.h" +#include "hpipm_s_ocp_qcqp.h" +#include "hpipm_s_ocp_qcqp_dim.h" +#include "hpipm_s_ocp_qcqp_sol.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_cond_qcqp_arg + { + struct s_cond_qp_arg *qp_arg; + int cond_last_stage; // condense last stage +// int cond_variant; // TODO + int comp_prim_sol; // primal solution (v) + int comp_dual_sol_eq; // dual solution equality constr (pi) + int comp_dual_sol_ineq; // dual solution equality constr (lam t) + int square_root_alg; // square root algorithm (faster but requires RSQ>0) + hpipm_size_t memsize; + }; + + + +struct s_cond_qcqp_ws + { + struct s_cond_qp_ws *qp_ws; + struct blasfeo_smat *hess_array; // TODO remove + struct blasfeo_smat *zero_hess; // TODO remove + struct blasfeo_svec *zero_grad; // TODO remove + struct blasfeo_svec *grad_array; // TODO remove + struct blasfeo_svec *tmp_nvc; + struct blasfeo_svec *tmp_nuxM; + struct blasfeo_smat *GammaQ; + struct blasfeo_smat *tmp_DCt; + struct blasfeo_smat *tmp_nuM_nxM; +// struct blasfeo_svec *d_qp; +// struct blasfeo_svec *d_mask_qp; + hpipm_size_t memsize; + }; + + +// +hpipm_size_t s_cond_qcqp_arg_memsize(); +// +void s_cond_qcqp_arg_create(struct s_cond_qcqp_arg *cond_arg, void *mem); +// +void s_cond_qcqp_arg_set_default(struct s_cond_qcqp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 square-root +void s_cond_qcqp_arg_set_ric_alg(int ric_alg, struct s_cond_qcqp_arg *cond_arg); +// condense last stage: 0 last stage disregarded, 1 last stage condensed too +void s_cond_qcqp_arg_set_cond_last_stage(int cond_last_stage, struct s_cond_qcqp_arg *cond_arg); + +// +void s_cond_qcqp_compute_dim(struct s_ocp_qcqp_dim *ocp_dim, struct s_dense_qcqp_dim *dense_dim); +// +hpipm_size_t s_cond_qcqp_ws_memsize(struct s_ocp_qcqp_dim *ocp_dim, struct s_cond_qcqp_arg *cond_arg); +// +void s_cond_qcqp_ws_create(struct s_ocp_qcqp_dim *ocp_dim, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws, void *mem); +// +void s_cond_qcqp_qc(struct s_ocp_qcqp *ocp_qp, struct blasfeo_smat *Hq2, int *Hq_nzero2, struct blasfeo_smat *Ct2, struct blasfeo_svec *d2, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); +// +void s_cond_qcqp_qc_lhs(struct s_ocp_qcqp *ocp_qp, struct blasfeo_smat *Hq2, int *Hq_nzero2, struct blasfeo_smat *Ct2, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); +// +void s_cond_qcqp_qc_rhs(struct s_ocp_qcqp *ocp_qp, struct blasfeo_svec *d2, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); +// +void s_cond_qcqp_cond(struct s_ocp_qcqp *ocp_qp, struct s_dense_qcqp *dense_qp, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); +// +void s_cond_qcqp_cond_rhs(struct s_ocp_qcqp *ocp_qp, struct s_dense_qcqp *dense_qp, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); +// +void s_cond_qcqp_cond_lhs(struct s_ocp_qcqp *ocp_qp, struct s_dense_qcqp *dense_qp, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); +// +void s_cond_qcqp_expand_sol(struct s_ocp_qcqp *ocp_qp, struct s_dense_qcqp_sol *dense_qp_sol, struct s_ocp_qcqp_sol *ocp_qp_sol, struct s_cond_qcqp_arg *cond_arg, struct s_cond_qcqp_ws *cond_ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_COND_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_core_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_core_qp_ipm.h new file mode 100644 index 0000000000..480392c7d9 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_core_qp_ipm.h @@ -0,0 +1,101 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_CORE_QP_IPM_ +#define HPIPM_S_CORE_QP_IPM_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct s_core_qp_ipm_workspace + { + float *v; // primal variables + float *pi; // equality constraints multipliers + float *lam; // inequality constraints multipliers + float *t; // inequality constraints slacks + float *t_inv; // inverse of t + float *v_bkp; // backup of primal variables + float *pi_bkp; // backup of equality constraints multipliers + float *lam_bkp; // backup of inequality constraints multipliers + float *t_bkp; // backup of inequality constraints slacks + float *dv; // step in v + float *dpi; // step in pi + float *dlam; // step in lam + float *dt; // step in t + float *res_g; // q-residuals + float *res_b; // b-residuals + float *res_d; // d-residuals + float *res_m; // m-residuals + float *res_m_bkp; // m-residuals + float *Gamma; // Hessian update + float *gamma; // gradient update + float alpha_prim; // step length + float alpha_dual; // step length + float alpha; // step length + float sigma; // centering XXX + float mu; // duality measuere + float mu_aff; // affine duality measuere + float nc_inv; // 1.0/nc, where nc is the total number of constraints + float nc_mask_inv; // 1.0/nc_mask + float lam_min; // min value in lam vector + float t_min; // min value in t vector + float t_min_inv; // inverse of min value in t vector + float tau_min; // min value of barrier parameter + int nv; // number of primal variables + int ne; // number of equality constraints + int nc; // (twice the) number of (two-sided) inequality constraints + int nc_mask; // total number of ineq constr after masking + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam also in solution, or only in Gamma computation + hpipm_size_t memsize; // memory size (in bytes) of workspace + }; + + + +// +hpipm_size_t s_memsize_core_qp_ipm(int nv, int ne, int nc); +// +void s_create_core_qp_ipm(int nv, int ne, int nc, struct s_core_qp_ipm_workspace *workspace, void *mem); +// +void s_core_qp_ipm(struct s_core_qp_ipm_workspace *workspace); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_S_CORE_QP_IPM_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_core_qp_ipm_aux.h b/third_party/acados/include/hpipm/include/hpipm_s_core_qp_ipm_aux.h new file mode 100644 index 0000000000..1ac3d7ede9 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_core_qp_ipm_aux.h @@ -0,0 +1,68 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_CORE_QP_IPM_AUX_ +#define HPIPM_S_CORE_QP_IPM_AUX_ + +#ifdef __cplusplus +extern "C" { +#endif + +// +void s_compute_Gamma_gamma_qp(float *res_d, float *res_m, struct s_core_qp_ipm_workspace *rws); +// +void s_compute_gamma_qp(float *res_d, float *res_m, struct s_core_qp_ipm_workspace *rws); +// +void s_compute_lam_t_qp(float *res_d, float *res_m, float *dlam, float *dt, struct s_core_qp_ipm_workspace *rws); +// +void s_compute_alpha_qp(struct s_core_qp_ipm_workspace *rws); +// +void s_update_var_qp(struct s_core_qp_ipm_workspace *rws); +// +void s_compute_mu_aff_qp(struct s_core_qp_ipm_workspace *rws); +// +void s_backup_res_m(struct s_core_qp_ipm_workspace *rws); +// +void s_compute_centering_correction_qp(struct s_core_qp_ipm_workspace *rws); +// +void s_compute_centering_qp(struct s_core_qp_ipm_workspace *rws); +// +void s_compute_tau_min_qp(struct s_core_qp_ipm_workspace *rws); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_S_CORE_QP_IPM_AUX_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp.h new file mode 100644 index 0000000000..d03c065375 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp.h @@ -0,0 +1,200 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QCQP_H_ +#define HPIPM_S_DENSE_QCQP_H_ + + + +#include +#include + +#include "hpipm_s_dense_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qcqp + { + struct s_dense_qcqp_dim *dim; + struct blasfeo_smat *Hv; // hessian of cost & vector work space + struct blasfeo_smat *A; // equality constraint matrix + struct blasfeo_smat *Ct; // inequality constraints matrix + struct blasfeo_smat *Hq; // hessians of quadratic constraints + struct blasfeo_svec *gz; // gradient of cost & gradient of slacks + struct blasfeo_svec *b; // equality constraint vector + struct blasfeo_svec *d; // inequality constraints vector + struct blasfeo_svec *d_mask; // inequality constraints mask vector + struct blasfeo_svec *m; // rhs of complementarity condition + struct blasfeo_svec *Z; // (diagonal) hessian of slacks + int *idxb; // indices of box constrained variables within [u; x] + int *idxs_rev; // index of soft constraints (reverse storage) + int *Hq_nzero; // for each int, the last 3 bits ...abc, {a,b,c}=0 => {R,S,Q}=0 + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_dense_qcqp_memsize(struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_create(struct s_dense_qcqp_dim *dim, struct s_dense_qcqp *qp, void *memory); + +// +void s_dense_qcqp_set(char *field, void *value, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_H(float *H, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_g(float *g, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_A(float *A, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_b(float *b, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_idxb(int *idxb, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_lb(float *lb, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_lb_mask(float *lb, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_ub(float *ub, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_ub_mask(float *ub, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_C(float *C, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_lg(float *lg, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_lg_mask(float *lg, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_ug(float *ug, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_ug_mask(float *ug, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_Hq(float *Hq, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_gq(float *gq, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_uq(float *uq, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_uq_mask(float *uq, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_idxs(int *idxs, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_idxs_rev(int *idxs_rev, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_Zl(float *Zl, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_Zu(float *Zu, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_zl(float *zl, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_zu(float *zu, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_ls(float *ls, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_ls_mask(float *ls, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_us(float *us, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_set_us_mask(float *us, struct s_dense_qcqp *qp); + +// getters (COLMAJ) + +void s_dense_qcqp_get_H(struct s_dense_qcqp *qp, float *H); +// +void s_dense_qcqp_get_g(struct s_dense_qcqp *qp, float *g); +// +void s_dense_qcqp_get_A(struct s_dense_qcqp *qp, float *A); +// +void s_dense_qcqp_get_b(struct s_dense_qcqp *qp, float *b); +// +void s_dense_qcqp_get_idxb(struct s_dense_qcqp *qp, int *idxb); +// +void s_dense_qcqp_get_lb(struct s_dense_qcqp *qp, float *lb); +// +void s_dense_qcqp_get_lb_mask(struct s_dense_qcqp *qp, float *lb); +// +void s_dense_qcqp_get_ub(struct s_dense_qcqp *qp, float *ub); +// +void s_dense_qcqp_get_ub_mask(struct s_dense_qcqp *qp, float *ub); +// +void s_dense_qcqp_get_C(struct s_dense_qcqp *qp, float *C); +// +void s_dense_qcqp_get_lg(struct s_dense_qcqp *qp, float *lg); +// +void s_dense_qcqp_get_lg_mask(struct s_dense_qcqp *qp, float *lg); +// +void s_dense_qcqp_get_ug(struct s_dense_qcqp *qp, float *ug); +// +void s_dense_qcqp_get_ug_mask(struct s_dense_qcqp *qp, float *ug); +// +void s_dense_qcqp_get_idxs(struct s_dense_qcqp *qp, int *idxs); +// +void s_dense_qcqp_get_idxs_rev(struct s_dense_qcqp *qp, int *idxs_rev); +// +void s_dense_qcqp_get_Zl(struct s_dense_qcqp *qp, float *Zl); +// +void s_dense_qcqp_get_Zu(struct s_dense_qcqp *qp, float *Zu); +// +void s_dense_qcqp_get_zl(struct s_dense_qcqp *qp, float *zl); +// +void s_dense_qcqp_get_zu(struct s_dense_qcqp *qp, float *zu); +// +void s_dense_qcqp_get_ls(struct s_dense_qcqp *qp, float *ls); +// +void s_dense_qcqp_get_ls_mask(struct s_dense_qcqp *qp, float *ls); +// +void s_dense_qcqp_get_us(struct s_dense_qcqp *qp, float *us); +// +void s_dense_qcqp_get_us_mask(struct s_dense_qcqp *qp, float *us); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QCQP_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_dim.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_dim.h new file mode 100644 index 0000000000..04908c2c3a --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_dim.h @@ -0,0 +1,99 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_DENSE_QCQP_DIM_H_ +#define HPIPM_S_DENSE_QCQP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qcqp_dim + { + struct s_dense_qp_dim *qp_dim; // dim of qp approximation + int nv; // number of variables + int ne; // number of equality constraints + int nb; // number of box constraints + int ng; // number of general constraints + int nq; // number of quadratic constraints + int nsb; // number of softened box constraints + int nsg; // number of softened general constraints + int nsq; // number of softened quadratic constraints + int ns; // number of softened constraints (nsb+nsg+nsq) TODO number of slacks + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_dense_qcqp_dim_memsize(); +// +void s_dense_qcqp_dim_create(struct s_dense_qcqp_dim *dim, void *memory); +// +void s_dense_qcqp_dim_set(char *fiels_name, int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_nv(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_ne(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_nb(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_ng(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_nq(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_nsb(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_nsg(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_nsq(int value, struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_dim_set_ns(int value, struct s_dense_qcqp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_DENSE_QCQP_DIM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_ipm.h new file mode 100644 index 0000000000..8f85768ee3 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_ipm.h @@ -0,0 +1,204 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QCQP_IPM_H_ +#define HPIPM_S_DENSE_QCQP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qcqp_ipm_arg + { + struct s_dense_qp_ipm_arg *qp_arg; + float mu0; // initial value for duality measure + float alpha_min; // exit cond on step length + float res_g_max; // exit cond on inf norm of residuals + float res_b_max; // exit cond on inf norm of residuals + float res_d_max; // exit cond on inf norm of residuals + float res_m_max; // exit cond on inf norm of residuals + float reg_prim; // reg of primal hessian + float reg_dual; // reg of dual hessian + float lam_min; // min value in lam vector + float t_min; // min value in t vector + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int scale; // scale hessian + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq + int abs_form; // absolute IPM formulation + int comp_res_exit; // compute residuals on exit (only for abs_form==1) + int comp_res_pred; // compute residuals of prediction + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct s_dense_qcqp_ipm_ws + { +// float qp_res[4]; // infinity norm of residuals + struct s_dense_qp_ipm_ws *qp_ws; + struct s_dense_qp *qp; + struct s_dense_qp_sol *qp_sol; + struct s_dense_qcqp_res_ws *qcqp_res_ws; + struct s_dense_qcqp_res *qcqp_res; + struct blasfeo_svec *tmp_nv; +// float *stat; // convergence statistics +// void *lq_work0; +// void *lq_work1; + int iter; // iteration number +// int stat_max; // iterations saved in stat +// int stat_m; // numer of recorded stat per ipm iter +// int scale; +// int use_hess_fact; + int status; + hpipm_size_t memsize; // memory size (in bytes) of workspace + }; + + + +// +hpipm_size_t s_dense_qcqp_ipm_arg_memsize(struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_ipm_arg_create(struct s_dense_qcqp_dim *dim, struct s_dense_qcqp_ipm_arg *arg, void *mem); +// +void s_dense_qcqp_ipm_arg_set_default(enum hpipm_mode mode, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set(char *field, void *value, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_iter_max(int *iter_max, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_alpha_min(float *alpha_min, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_mu0(float *mu0, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_tol_stat(float *tol_stat, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_tol_eq(float *tol_eq, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_tol_ineq(float *tol_ineq, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_tol_comp(float *tol_comp, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_reg_prim(float *reg, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_reg_dual(float *reg, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_warm_start(int *warm_start, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_pred_corr(int *pred_corr, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_cond_pred_corr(int *cond_pred_corr, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_comp_res_pred(int *comp_res_pred, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_comp_res_exit(int *comp_res_exit, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_lam_min(float *value, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_t_min(float *value, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_split_step(int *value, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_arg_set_t_lam_min(int *value, struct s_dense_qcqp_ipm_arg *arg); + +// +hpipm_size_t s_dense_qcqp_ipm_ws_memsize(struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_ipm_ws_create(struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp_ipm_arg *arg, struct s_dense_qcqp_ipm_ws *ws, void *mem); +// +void s_dense_qcqp_ipm_get(char *field, struct s_dense_qcqp_ipm_ws *ws, void *value); +// +void s_dense_qcqp_ipm_get_status(struct s_dense_qcqp_ipm_ws *ws, int *status); +// +void s_dense_qcqp_ipm_get_iter(struct s_dense_qcqp_ipm_ws *ws, int *iter); +// +void s_dense_qcqp_ipm_get_max_res_stat(struct s_dense_qcqp_ipm_ws *ws, float *res_stat); +// +void s_dense_qcqp_ipm_get_max_res_eq(struct s_dense_qcqp_ipm_ws *ws, float *res_eq); +// +void s_dense_qcqp_ipm_get_max_res_ineq(struct s_dense_qcqp_ipm_ws *ws, float *res_ineq); +// +void s_dense_qcqp_ipm_get_max_res_comp(struct s_dense_qcqp_ipm_ws *ws, float *res_comp); +// +void s_dense_qcqp_ipm_get_stat(struct s_dense_qcqp_ipm_ws *ws, float **stat); +// +void s_dense_qcqp_ipm_get_stat_m(struct s_dense_qcqp_ipm_ws *ws, int *stat_m); +#if 0 +// +void s_dense_qcqp_init_var(struct s_dense_qcqp *qp, struct s_dense_qcqp_sol *qp_sol, struct s_dense_qcqp_ipm_arg *arg, struct s_dense_qcqp_ipm_ws *ws); +#endif +// +void s_dense_qcqp_ipm_solve(struct s_dense_qcqp *qp, struct s_dense_qcqp_sol *qp_sol, struct s_dense_qcqp_ipm_arg *arg, struct s_dense_qcqp_ipm_ws *ws); +#if 0 +// +void s_dense_qcqp_ipm_predict(struct s_dense_qcqp *qp, struct s_dense_qcqp_sol *qp_sol, struct s_dense_qcqp_ipm_arg *arg, struct s_dense_qcqp_ipm_ws *ws); +// +void s_dense_qcqp_ipm_sens(struct s_dense_qcqp *qp, struct s_dense_qcqp_sol *qp_sol, struct s_dense_qcqp_ipm_arg *arg, struct s_dense_qcqp_ipm_ws *ws); +#endif + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QCQP_IPM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_res.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_res.h new file mode 100644 index 0000000000..779658cc8f --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_res.h @@ -0,0 +1,108 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_DENSE_QCQP_RES_H_ +#define HPIPM_S_DENSE_QCQP_RES_H_ + + + +#include +#include + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qcqp_res + { + struct s_dense_qcqp_dim *dim; + struct blasfeo_svec *res_g; // q-residuals + struct blasfeo_svec *res_b; // b-residuals + struct blasfeo_svec *res_d; // d-residuals + struct blasfeo_svec *res_m; // m-residuals + float res_max[4]; // infinity norm of residuals + float res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct s_dense_qcqp_res_ws + { + struct blasfeo_svec *tmp_nv; // work space of size nv + struct blasfeo_svec *tmp_nbgq; // work space of size nbM+ngM+nqM + struct blasfeo_svec *tmp_ns; // work space of size nsM + struct blasfeo_svec *q_fun; // value for evaluation of quadr constr + struct blasfeo_svec *q_adj; // value for adjoint of quadr constr + int use_q_fun; // reuse cached value for evaluation of quadr constr + int use_q_adj; // reuse cached value for adjoint of quadr constr + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_dense_qcqp_res_memsize(struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_res_create(struct s_dense_qcqp_dim *dim, struct s_dense_qcqp_res *res, void *mem); +// +hpipm_size_t s_dense_qcqp_res_ws_memsize(struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_res_ws_create(struct s_dense_qcqp_dim *dim, struct s_dense_qcqp_res_ws *workspace, void *mem); +// +void s_dense_qcqp_res_compute(struct s_dense_qcqp *qp, struct s_dense_qcqp_sol *qp_sol, struct s_dense_qcqp_res *res, struct s_dense_qcqp_res_ws *ws); +// +void s_dense_qcqp_res_compute_inf_norm(struct s_dense_qcqp_res *res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_DENSE_QCQP_RES_H_ + + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_sol.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_sol.h new file mode 100644 index 0000000000..197a690e52 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_sol.h @@ -0,0 +1,86 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QCQP_SOL_H_ +#define HPIPM_S_DENSE_QCQP_SOL_H_ + + + +#include +#include + +#include "hpipm_s_dense_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qcqp_sol + { + struct s_dense_qcqp_dim *dim; + struct blasfeo_svec *v; + struct blasfeo_svec *pi; + struct blasfeo_svec *lam; + struct blasfeo_svec *t; + void *misc; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_dense_qcqp_sol_memsize(struct s_dense_qcqp_dim *dim); +// +void s_dense_qcqp_sol_create(struct s_dense_qcqp_dim *dim, struct s_dense_qcqp_sol *qp_sol, void *memory); +// +void s_dense_qcqp_sol_get_v(struct s_dense_qcqp_sol *qp_sol, float *v); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QCQP_SOL_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_utils.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_utils.h new file mode 100644 index 0000000000..4f5aae26eb --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qcqp_utils.h @@ -0,0 +1,83 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_DENSE_QCQP_UTILS_H_ +#define HPIPM_S_DENSE_QCQP_UTILS_H_ + + + +#include +#include + +#include "hpipm_s_dense_qcqp_dim.h" +#include "hpipm_s_dense_qcqp.h" +#include "hpipm_s_dense_qcqp_sol.h" +//#include "hpipm_s_dense_qcqp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_dense_qcqp_dim_print(struct s_dense_qcqp_dim *qp_dim); +// +//void s_dense_qcqp_dim_codegen(char *file_name, char *mode, struct s_dense_qcqp_dim *qp_dim); +// +void s_dense_qcqp_print(struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp *qp); +// +//void s_dense_qcqp_codegen(char *file_name, char *mode, struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp *qp); +// +void s_dense_qcqp_sol_print(struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp_sol *dense_qcqp_sol); +// +//void s_dense_qcqp_ipm_arg_codegen(char *file_name, char *mode, struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp_ipm_arg *arg); +// +void s_dense_qcqp_res_print(struct s_dense_qcqp_dim *qp_dim, struct s_dense_qcqp_res *dense_qcqp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_DENSE_QCQP_UTILS_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp.h new file mode 100644 index 0000000000..3c2517fe1b --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp.h @@ -0,0 +1,207 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QP_H_ +#define HPIPM_S_DENSE_QP_H_ + + + +#include +#include + +#include "hpipm_s_dense_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qp + { + struct s_dense_qp_dim *dim; + struct blasfeo_smat *Hv; // hessian & gradient + struct blasfeo_smat *A; // dynamics matrix + struct blasfeo_smat *Ct; // constraints matrix + struct blasfeo_svec *gz; // gradient & gradient of slacks + struct blasfeo_svec *b; // dynamics vector + struct blasfeo_svec *d; // constraints vector + struct blasfeo_svec *d_mask; // inequality constraints mask vector + struct blasfeo_svec *m; // rhs of complementarity condition + struct blasfeo_svec *Z; // (diagonal) hessian of slacks + int *idxb; // indices of box constrained variables within [u; x] + int *idxs_rev; // index of soft constraints (reverse storage) + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_dense_qp_memsize(struct s_dense_qp_dim *dim); +// +void s_dense_qp_create(struct s_dense_qp_dim *dim, struct s_dense_qp *qp, void *memory); + +// setters - colmaj +// +void s_dense_qp_set_all(float *H, float *g, float *A, float *b, int *idxb, float *d_lb, float *d_ub, float *C, float *d_lg, float *d_ug, float *Zl, float *Zu, float *zl, float *zu, int *idxs, float *d_ls, float *d_us, struct s_dense_qp *qp); +// +void s_dense_qp_get_all(struct s_dense_qp *qp, float *H, float *g, float *A, float *b, int *idxb, float *d_lb, float *d_ub, float *C, float *d_lg, float *d_ug, float *Zl, float *Zu, float *zl, float *zu, int *idxs, float *d_ls, float *d_us); +// +void s_dense_qp_set(char *field, void *value, struct s_dense_qp *qp); +// +void s_dense_qp_set_H(float *H, struct s_dense_qp *qp); +// +void s_dense_qp_set_g(float *g, struct s_dense_qp *qp); +// +void s_dense_qp_set_A(float *A, struct s_dense_qp *qp); +// +void s_dense_qp_set_b(float *b, struct s_dense_qp *qp); +// +void s_dense_qp_set_idxb(int *idxb, struct s_dense_qp *qp); +// +void s_dense_qp_set_Jb(float *Jb, struct s_dense_qp *qp); +// +void s_dense_qp_set_lb(float *lb, struct s_dense_qp *qp); +// +void s_dense_qp_set_lb_mask(float *lb, struct s_dense_qp *qp); +// +void s_dense_qp_set_ub(float *ub, struct s_dense_qp *qp); +// +void s_dense_qp_set_ub_mask(float *ub, struct s_dense_qp *qp); +// +void s_dense_qp_set_C(float *C, struct s_dense_qp *qp); +// +void s_dense_qp_set_lg(float *lg, struct s_dense_qp *qp); +// +void s_dense_qp_set_lg_mask(float *lg, struct s_dense_qp *qp); +// +void s_dense_qp_set_ug(float *ug, struct s_dense_qp *qp); +// +void s_dense_qp_set_ug_mask(float *ug, struct s_dense_qp *qp); +// +void s_dense_qp_set_idxs(int *idxs, struct s_dense_qp *qp); +// +void s_dense_qp_set_idxs_rev(int *idxs_rev, struct s_dense_qp *qp); +// +void s_dense_qp_set_Jsb(float *Jsb, struct s_dense_qp *qp); +// +void s_dense_qp_set_Jsg(float *Jsg, struct s_dense_qp *qp); +// +void s_dense_qp_set_Zl(float *Zl, struct s_dense_qp *qp); +// +void s_dense_qp_set_Zu(float *Zu, struct s_dense_qp *qp); +// +void s_dense_qp_set_zl(float *zl, struct s_dense_qp *qp); +// +void s_dense_qp_set_zu(float *zu, struct s_dense_qp *qp); +// +void s_dense_qp_set_ls(float *ls, struct s_dense_qp *qp); +// +void s_dense_qp_set_ls_mask(float *ls, struct s_dense_qp *qp); +// +void s_dense_qp_set_us(float *us, struct s_dense_qp *qp); +// +void s_dense_qp_set_us_mask(float *us, struct s_dense_qp *qp); + +// getters - colmaj +// +void s_dense_qp_get_H(struct s_dense_qp *qp, float *H); +// +void s_dense_qp_get_g(struct s_dense_qp *qp, float *g); +// +void s_dense_qp_get_A(struct s_dense_qp *qp, float *A); +// +void s_dense_qp_get_b(struct s_dense_qp *qp, float *b); +// +void s_dense_qp_get_idxb(struct s_dense_qp *qp, int *idxb); +// +void s_dense_qp_get_lb(struct s_dense_qp *qp, float *lb); +// +void s_dense_qp_get_lb_mask(struct s_dense_qp *qp, float *lb); +// +void s_dense_qp_get_ub(struct s_dense_qp *qp, float *ub); +// +void s_dense_qp_get_ub_mask(struct s_dense_qp *qp, float *ub); +// +void s_dense_qp_get_C(struct s_dense_qp *qp, float *C); +// +void s_dense_qp_get_lg(struct s_dense_qp *qp, float *lg); +// +void s_dense_qp_get_lg_mask(struct s_dense_qp *qp, float *lg); +// +void s_dense_qp_get_ug(struct s_dense_qp *qp, float *ug); +// +void s_dense_qp_get_ug_mask(struct s_dense_qp *qp, float *ug); +// +void s_dense_qp_get_idxs(struct s_dense_qp *qp, int *idxs); +// +void s_dense_qp_get_idxs_rev(struct s_dense_qp *qp, int *idxs_rev); +// +void s_dense_qp_get_Zl(struct s_dense_qp *qp, float *Zl); +// +void s_dense_qp_get_Zu(struct s_dense_qp *qp, float *Zu); +// +void s_dense_qp_get_zl(struct s_dense_qp *qp, float *zl); +// +void s_dense_qp_get_zu(struct s_dense_qp *qp, float *zu); +// +void s_dense_qp_get_ls(struct s_dense_qp *qp, float *ls); +// +void s_dense_qp_get_ls_mask(struct s_dense_qp *qp, float *ls); +// +void s_dense_qp_get_us(struct s_dense_qp *qp, float *us); +// +void s_dense_qp_get_us_mask(struct s_dense_qp *qp, float *us); + +// setters - rowmaj +// +void s_dense_qp_set_all_rowmaj(float *H, float *g, float *A, float *b, int *idxb, float *d_lb, float *d_ub, float *C, float *d_lg, float *d_ug, float *Zl, float *Zu, float *zl, float *zu, int *idxs, float *d_ls, float *d_us, struct s_dense_qp *qp); + +// getters - rowmaj +// +void s_dense_qp_get_all_rowmaj(struct s_dense_qp *qp, float *H, float *g, float *A, float *b, int *idxb, float *d_lb, float *d_ub, float *C, float *d_lg, float *d_ug, float *Zl, float *Zu, float *zl, float *zu, int *idxs, float *d_ls, float *d_us); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_dim.h new file mode 100644 index 0000000000..b979d24432 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_dim.h @@ -0,0 +1,94 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_DENSE_QP_DIM_H_ +#define HPIPM_S_DENSE_QP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qp_dim + { + int nv; // number of variables + int ne; // number of equality constraints + int nb; // number of box constraints + int ng; // number of general constraints + int nsb; // number of softened box constraints + int nsg; // number of softened general constraints + int ns; // number of softened constraints (nsb+nsg) + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_dense_qp_dim_memsize(); +// +void s_dense_qp_dim_create(struct s_dense_qp_dim *qp_dim, void *memory); +// +void s_dense_qp_dim_set_all(int nv, int ne, int nb, int ng, int nsb, int nsg, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set(char *fiels_name, int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_nv(int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_ne(int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_nb(int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_ng(int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_nsb(int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_nsg(int value, struct s_dense_qp_dim *dim); +// +void s_dense_qp_dim_set_ns(int value, struct s_dense_qp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_DENSE_QP_DIM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_ipm.h new file mode 100644 index 0000000000..f2d56d4529 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_ipm.h @@ -0,0 +1,260 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QP_IPM_H_ +#define HPIPM_S_DENSE_QP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qp_ipm_arg + { + float mu0; // initial value for duality measure + float alpha_min; // exit cond on step length + float res_g_max; // exit cond on inf norm of residuals + float res_b_max; // exit cond on inf norm of residuals + float res_d_max; // exit cond on inf norm of residuals + float res_m_max; // exit cond on inf norm of residuals + float reg_prim; // reg of primal hessian + float reg_dual; // reg of dual hessian + float lam_min; // min value in lam vector + float t_min; // min value in t vector + float tau_min; // min value of barrier parameter + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int scale; // scale hessian + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq + int abs_form; // absolute IPM formulation + int comp_res_exit; // compute residuals on exit (only for abs_form==1) + int comp_res_pred; // compute residuals of prediction + int kkt_fact_alg; // 0 null-space, 1 schur-complement + int remove_lin_dep_eq; // 0 do not, 1 do check and remove linearly dependent equality constraints + int compute_obj; // compute obj on exit + int split_step; // use different steps for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct s_dense_qp_ipm_ws + { + struct s_core_qp_ipm_workspace *core_workspace; + struct s_dense_qp_res_ws *res_ws; + struct s_dense_qp_sol *sol_step; + struct s_dense_qp_sol *sol_itref; + struct s_dense_qp *qp_step; + struct s_dense_qp *qp_itref; + struct s_dense_qp_res *res; + struct s_dense_qp_res *res_itref; + struct s_dense_qp_res *res_step; + struct blasfeo_svec *Gamma; // + struct blasfeo_svec *gamma; // + struct blasfeo_svec *Zs_inv; // + struct blasfeo_smat *Lv; // + struct blasfeo_smat *AL; // + struct blasfeo_smat *Le; // + struct blasfeo_smat *Ctx; // + struct blasfeo_svec *lv; // + struct blasfeo_svec *sv; // scale for Lv + struct blasfeo_svec *se; // scale for Le + struct blasfeo_svec *tmp_nbg; // work space of size nb+ng + struct blasfeo_svec *tmp_ns; // work space of size ns + struct blasfeo_smat *lq0; + struct blasfeo_smat *lq1; + struct blasfeo_svec *tmp_m; + struct blasfeo_smat *A_LQ; + struct blasfeo_smat *A_Q; + struct blasfeo_smat *Zt; + struct blasfeo_smat *ZtH; + struct blasfeo_smat *ZtHZ; + struct blasfeo_svec *xy; + struct blasfeo_svec *Yxy; + struct blasfeo_svec *xz; + struct blasfeo_svec *tmp_nv; + struct blasfeo_svec *tmp_2ns; + struct blasfeo_svec *tmp_nv2ns; + struct blasfeo_smat *A_li; // A of linearly independent equality constraints + struct blasfeo_svec *b_li; // b of linearly independent equality constraints + struct blasfeo_smat *A_bkp; // pointer to backup A + struct blasfeo_svec *b_bkp; // pointer to backup b + struct blasfeo_smat *Ab_LU; + float *stat; // convergence statistics + int *ipiv_v; + int *ipiv_e; + int *ipiv_e1; + void *lq_work0; + void *lq_work1; + void *lq_work_null; + void *orglq_work_null; + int iter; // iteration number + int stat_max; // iterations saved in stat + int stat_m; // numer of recorded stat per ipm iter + int scale; + int use_hess_fact; + int use_A_fact; + int status; + int lq_fact; // cache from arg + int mask_constr; // use constr mask + int ne_li; // number of linearly independent equality constraints + int ne_bkp; // ne backup + hpipm_size_t memsize; // memory size (in bytes) of workspace + }; + + + +// +hpipm_size_t s_dense_qp_ipm_arg_memsize(struct s_dense_qp_dim *qp_dim); +// +void s_dense_qp_ipm_arg_create(struct s_dense_qp_dim *qp_dim, struct s_dense_qp_ipm_arg *arg, void *mem); +// +void s_dense_qp_ipm_arg_set_default(enum hpipm_mode mode, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set(char *field, void *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_iter_max(int *iter_max, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_alpha_min(float *alpha_min, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_mu0(float *mu0, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_tol_stat(float *tol_stat, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_tol_eq(float *tol_eq, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_tol_ineq(float *tol_ineq, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_tol_comp(float *tol_comp, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_reg_prim(float *reg, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_reg_dual(float *reg, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_warm_start(int *warm_start, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_pred_corr(int *pred_corr, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_cond_pred_corr(int *cond_pred_corr, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_comp_res_pred(int *comp_res_pred, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_comp_res_exit(int *comp_res_exit, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_lam_min(float *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_t_min(float *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_tau_min(float *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_kkt_fact_alg(int *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_remove_lin_dep_eq(int *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_compute_obj(int *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_split_step(int *value, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_arg_set_t_lam_min(int *value, struct s_dense_qp_ipm_arg *arg); + +// +hpipm_size_t s_dense_qp_ipm_ws_memsize(struct s_dense_qp_dim *qp_dim, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_ipm_ws_create(struct s_dense_qp_dim *qp_dim, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws, void *mem); +// +void s_dense_qp_ipm_get(char *field, struct s_dense_qp_ipm_ws *ws, void *value); +// +void s_dense_qp_ipm_get_status(struct s_dense_qp_ipm_ws *ws, int *status); +// +void s_dense_qp_ipm_get_iter(struct s_dense_qp_ipm_ws *ws, int *iter); +// +void s_dense_qp_ipm_get_max_res_stat(struct s_dense_qp_ipm_ws *ws, float *res_stat); +// +void s_dense_qp_ipm_get_max_res_eq(struct s_dense_qp_ipm_ws *ws, float *res_eq); +// +void s_dense_qp_ipm_get_max_res_ineq(struct s_dense_qp_ipm_ws *ws, float *res_ineq); +// +void s_dense_qp_ipm_get_max_res_comp(struct s_dense_qp_ipm_ws *ws, float *res_comp); +// +void s_dense_qp_ipm_get_stat(struct s_dense_qp_ipm_ws *ws, float **stat); +// +void s_dense_qp_ipm_get_stat_m(struct s_dense_qp_ipm_ws *ws, int *stat_m); +// +void s_dense_qp_init_var(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_ipm_abs_step(int kk, struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_ipm_delta_step(int kk, struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_ipm_solve(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_ipm_predict(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_ipm_sens(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_compute_step_length(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QP_IPM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_kkt.h new file mode 100644 index 0000000000..260dc0ab21 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_kkt.h @@ -0,0 +1,72 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QP_KKT_H_ +#define HPIPM_S_DENSE_QP_KKT_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_fact_solve_kkt_unconstr_dense_qp(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_fact_solve_kkt_step_dense_qp(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_fact_lq_solve_kkt_step_dense_qp(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_solve_kkt_step_dense_qp(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_remove_lin_dep_eq(struct s_dense_qp *qp, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_restore_lin_dep_eq(struct s_dense_qp *qp, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); +// +void s_dense_qp_compute_obj(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_ipm_arg *arg, struct s_dense_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QP_KKT_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_res.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_res.h new file mode 100644 index 0000000000..06b609c537 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_res.h @@ -0,0 +1,106 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_DENSE_QP_RES_H_ +#define HPIPM_S_DENSE_QP_RES_H_ + + + +#include +#include + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qp_res + { + struct s_dense_qp_dim *dim; + struct blasfeo_svec *res_g; // q-residuals + struct blasfeo_svec *res_b; // b-residuals + struct blasfeo_svec *res_d; // d-residuals + struct blasfeo_svec *res_m; // m-residuals + float res_max[4]; // max of residuals + float res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct s_dense_qp_res_ws + { + struct blasfeo_svec *tmp_nbg; // work space of size nbM+ngM + struct blasfeo_svec *tmp_ns; // work space of size nsM + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_dense_qp_res_memsize(struct s_dense_qp_dim *dim); +// +void s_dense_qp_res_create(struct s_dense_qp_dim *dim, struct s_dense_qp_res *res, void *mem); +// +hpipm_size_t s_dense_qp_res_ws_memsize(struct s_dense_qp_dim *dim); +// +void s_dense_qp_res_ws_create(struct s_dense_qp_dim *dim, struct s_dense_qp_res_ws *workspace, void *mem); +// +void s_dense_qp_res_compute(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_res *res, struct s_dense_qp_res_ws *ws); +// +void s_dense_qp_res_compute_lin(struct s_dense_qp *qp, struct s_dense_qp_sol *qp_sol, struct s_dense_qp_sol *qp_step, struct s_dense_qp_res *res, struct s_dense_qp_res_ws *ws); +// +void s_dense_qp_res_compute_inf_norm(struct s_dense_qp_res *res); +// +void s_dense_qp_res_get_all(struct s_dense_qp_res *res, float *res_g, float *res_ls, float *res_us, float *res_b, float *res_d_lb, float *res_d_ub, float *res_d_lg, float *res_d_ug, float *res_d_ls, float *res_d_us, float *res_m_lb, float *res_m_ub, float *res_m_lg, float *res_m_ug, float *res_m_ls, float *res_m_us); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_D_DENSE_QP_RES_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_sol.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_sol.h new file mode 100644 index 0000000000..1f40076378 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_sol.h @@ -0,0 +1,94 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_DENSE_QP_SOL_H_ +#define HPIPM_S_DENSE_QP_SOL_H_ + + + +#include +#include + +#include "hpipm_s_dense_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_dense_qp_sol + { + struct s_dense_qp_dim *dim; + struct blasfeo_svec *v; + struct blasfeo_svec *pi; + struct blasfeo_svec *lam; + struct blasfeo_svec *t; + void *misc; + float obj; + int valid_obj; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_dense_qp_sol_memsize(struct s_dense_qp_dim *dim); +// +void s_dense_qp_sol_create(struct s_dense_qp_dim *dim, struct s_dense_qp_sol *qp_sol, void *memory); +// +void s_dense_qp_sol_get_all(struct s_dense_qp_sol *qp_sol, float *v, float *ls, float *us, float *pi, float *lam_lb, float *lam_ub, float *lam_lg, float *lam_ug, float *lam_ls, float *lam_us); +// +void s_dense_qp_sol_get(char *field, struct s_dense_qp_sol *sol, void *value); +// +void s_dense_qp_sol_get_v(struct s_dense_qp_sol *sol, float *v); +// +void s_dense_qp_sol_get_valid_obj(struct s_dense_qp_sol *sol, int *valid_obj); +// +void s_dense_qp_sol_get_obj(struct s_dense_qp_sol *sol, float *obj); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_DENSE_QP_SOL_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_utils.h b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_utils.h new file mode 100644 index 0000000000..3dd93259a5 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_dense_qp_utils.h @@ -0,0 +1,84 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_DENSE_QP_UTILS_H_ +#define HPIPM_S_DENSE_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_s_dense_qp_dim.h" +#include "hpipm_s_dense_qp.h" +#include "hpipm_s_dense_qp_sol.h" +#include "hpipm_s_dense_qp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_dense_qp_dim_print(struct s_dense_qp_dim *qp_dim); +// +//void s_dense_qp_dim_codegen(char *file_name, char *mode, struct s_dense_qp_dim *qp_dim); +// +void s_dense_qp_print(struct s_dense_qp_dim *qp_dim, struct s_dense_qp *qp); +// +//void s_dense_qp_codegen(char *file_name, char *mode, struct s_dense_qp_dim *qp_dim, struct s_dense_qp *qp); +// +void s_dense_qp_sol_print(struct s_dense_qp_dim *qp_dim, struct s_dense_qp_sol *dense_qp_sol); +// +//void s_dense_qp_ipm_arg_codegen(char *file_name, char *mode, struct s_dense_qp_dim *qp_dim, struct s_dense_qp_ipm_arg *arg); +// +void s_dense_qp_res_print(struct s_dense_qp_dim *qp_dim, struct s_dense_qp_res *dense_qp_res); +// +void s_dense_qp_arg_print(struct s_dense_qp_dim *qp_dim, struct s_dense_qp_ipm_arg *qp_ipm_arg); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_DENSE_QP_UTILS_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp.h new file mode 100644 index 0000000000..b90b2ac633 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp.h @@ -0,0 +1,303 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QCQP_H_ +#define HPIPM_S_OCP_QCQP_H_ + + + +#include +#include + +#include "hpipm_s_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qcqp + { + struct s_ocp_qcqp_dim *dim; + struct blasfeo_smat *BAbt; // dynamics matrix & vector work space + struct blasfeo_smat *RSQrq; // hessian of cost & vector work space + struct blasfeo_smat *DCt; // inequality constraints matrix + struct blasfeo_smat **Hq; // hessians of quadratic constraints + struct blasfeo_svec *b; // dynamics vector + struct blasfeo_svec *rqz; // gradient of cost & gradient of slacks + struct blasfeo_svec *d; // inequality constraints vector + struct blasfeo_svec *d_mask; // inequality constraints mask vector + struct blasfeo_svec *m; // rhs of complementarity condition + struct blasfeo_svec *Z; // (diagonal) hessian of slacks + int **idxb; // indices of box constrained variables within [u; x] + int **idxs_rev; // index of soft constraints (reverse storage) + int **Hq_nzero; // for each int, the last 3 bits ...abc, {a,b,c}=0 => {R,S,Q}=0 + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_ocp_qcqp_strsize(); +// +hpipm_size_t s_ocp_qcqp_memsize(struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_create(struct s_ocp_qcqp_dim *dim, struct s_ocp_qcqp *qp, void *memory); +// +void s_ocp_qcqp_copy_all(struct s_ocp_qcqp *qp_orig, struct s_ocp_qcqp *qp_dest); + +// setters +// +void s_ocp_qcqp_set_all_zero(struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_rhs_zero(struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set(char *fiels_name, int stage, void *value, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_el(char *fiels_name, int stage, int index, void *value, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_A(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_B(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_b(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Q(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_S(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_R(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_q(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_r(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lb(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lb_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ub(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ub_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lbx(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lbx_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_el_lbx(int stage, int index, float *elem, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ubx(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ubx_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_el_ubx(int stage, int index, float *elem, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lbu(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lbu_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ubu(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ubu_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_idxb(int stage, int *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_idxbx(int stage, int *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Jbx(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_idxbu(int stage, int *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Jbu(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_C(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_D(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lg(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lg_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ug(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_ug_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Qq(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Sq(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Rq(int stage, float *mat, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_qq(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_rq(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_uq(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_uq_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Zl(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Zu(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_zl(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_zu(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lls(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lls_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lus(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_lus_mask(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_idxs(int stage, int *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_idxs_rev(int stage, int *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Jsbu(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Jsbx(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Jsg(int stage, float *vec, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_set_Jsq(int stage, float *vec, struct s_ocp_qcqp *qp); + +// getters +// +void s_ocp_qcqp_get(char *field, int stage, struct s_ocp_qcqp *qp, void *value); +// +void s_ocp_qcqp_get_A(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_B(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_b(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_Q(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_S(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_R(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_q(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_r(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ub(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ub_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lb(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lb_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lbx(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lbx_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ubx(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ubx_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lbu(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lbu_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ubu(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ubu_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_idxb(int stage, struct s_ocp_qcqp *qp, int *vec); +// +//void s_ocp_qcqp_get_idxbx(int stage, struct s_ocp_qcqp *qp, int *vec); +// +//void s_ocp_qcqp_get_Jbx(int stage, struct s_ocp_qcqp *qp, float *vec); +// +//void s_ocp_qcqp_get_idxbu(int stage, struct s_ocp_qcqp *qp, int *vec); +// +//void s_ocp_qcqp_get_Jbu(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_C(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_D(int stage, struct s_ocp_qcqp *qp, float *mat); +// +void s_ocp_qcqp_get_lg(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lg_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ug(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_ug_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_Zl(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_Zu(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_zl(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_zu(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lls(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lls_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lus(int stage, struct s_ocp_qcqp *qp, float *vec); +// +void s_ocp_qcqp_get_lus_mask(int stage, struct s_ocp_qcqp *qp, float *vec); +// XXX only valid if there is one slack per softed constraint !!! +void s_ocp_qcqp_get_idxs(int stage, struct s_ocp_qcqp *qp, int *vec); +// +void s_ocp_qcqp_get_idxs_rev(int stage, struct s_ocp_qcqp *qp, int *vec); +// +//void s_ocp_qcqp_get_Jsbu(int stage, struct s_ocp_qcqp *qp, float *vec); +// +//void s_ocp_qcqp_get_Jsbx(int stage, struct s_ocp_qcqp *qp, float *vec); +// +//void s_ocp_qcqp_get_Jsg(int stage, struct s_ocp_qcqp *qp, float *vec); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_OCP_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_dim.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_dim.h new file mode 100644 index 0000000000..c09903f074 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_dim.h @@ -0,0 +1,119 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QCQP_DIM_H_ +#define HPIPM_S_OCP_QCQP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qcqp_dim + { + struct s_ocp_qp_dim *qp_dim; // dim of qp approximation + int *nx; // number of states + int *nu; // number of inputs + int *nb; // number of box constraints + int *nbx; // number of (two-sided) state box constraints + int *nbu; // number of (two-sided) input box constraints + int *ng; // number of (two-sided) general constraints + int *nq; // number of (upper) quadratic constraints + int *ns; // number of soft constraints + int *nsbx; // number of (two-sided) soft state box constraints + int *nsbu; // number of (two-sided) soft input box constraints + int *nsg; // number of (two-sided) soft general constraints + int *nsq; // number of (upper) soft quadratic constraints + int N; // horizon length + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_ocp_qcqp_dim_strsize(); +// +hpipm_size_t s_ocp_qcqp_dim_memsize(int N); +// +void s_ocp_qcqp_dim_create(int N, struct s_ocp_qcqp_dim *qp_dim, void *memory); +// +void s_ocp_qcqp_dim_copy_all(struct s_ocp_qcqp_dim *dim_orig, struct s_ocp_qcqp_dim *dim_dest); +// +void s_ocp_qcqp_dim_set(char *field, int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nx(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nu(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nbx(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nbu(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_ng(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nq(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_ns(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nsbx(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nsbu(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nsg(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_set_nsq(int stage, int value, struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_dim_get(struct s_ocp_qcqp_dim *dim, char *field, int stage, int *value); +// +void s_ocp_qcqp_dim_get_N(struct s_ocp_qcqp_dim *dim, int *value); +// +void s_ocp_qcqp_dim_get_nx(struct s_ocp_qcqp_dim *dim, int stage, int *value); +// +void s_ocp_qcqp_dim_get_nu(struct s_ocp_qcqp_dim *dim, int stage, int *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_OCP_QCQP_DIM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_ipm.h new file mode 100644 index 0000000000..c14fc1c9fd --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_ipm.h @@ -0,0 +1,191 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QCQP_IPM_H_ +#define HPIPM_S_OCP_QCQP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qcqp_ipm_arg + { + struct s_ocp_qp_ipm_arg *qp_arg; + float mu0; // initial value for complementarity slackness + float alpha_min; // exit cond on step length + float res_g_max; // exit cond on inf norm of residuals + float res_b_max; // exit cond on inf norm of residuals + float res_d_max; // exit cond on inf norm of residuals + float res_m_max; // exit cond on inf norm of residuals + float reg_prim; // reg of primal hessian + float lam_min; // min value in lam vector + float t_min; // min value in t vector + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int square_root_alg; // 0 classical Riccati, 1 square-root Riccati + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq (for square_root_alg==1) + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution of equality constraints (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol_eq==1) + int comp_res_pred; // compute residuals of prediction + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct s_ocp_qcqp_ipm_ws + { + struct s_ocp_qp_ipm_ws *qp_ws; + struct s_ocp_qp *qp; + struct s_ocp_qp_sol *qp_sol; + struct s_ocp_qcqp_res_ws *qcqp_res_ws; + struct s_ocp_qcqp_res *qcqp_res; + struct blasfeo_svec *tmp_nuxM; + int iter; // iteration number + int status; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_ocp_qcqp_ipm_arg_strsize(); +// +hpipm_size_t s_ocp_qcqp_ipm_arg_memsize(struct s_ocp_qcqp_dim *ocp_dim); +// +void s_ocp_qcqp_ipm_arg_create(struct s_ocp_qcqp_dim *ocp_dim, struct s_ocp_qcqp_ipm_arg *arg, void *mem); +// +void s_ocp_qcqp_ipm_arg_set_default(enum hpipm_mode mode, struct s_ocp_qcqp_ipm_arg *arg); +// +void s_ocp_qcqp_ipm_arg_set(char *field, void *value, struct s_ocp_qcqp_ipm_arg *arg); +// set maximum number of iterations +void s_ocp_qcqp_ipm_arg_set_iter_max(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// set minimum step lenght +void s_ocp_qcqp_ipm_arg_set_alpha_min(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set initial value of barrier parameter +void s_ocp_qcqp_ipm_arg_set_mu0(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on stationarity condition +void s_ocp_qcqp_ipm_arg_set_tol_stat(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on equality constr +void s_ocp_qcqp_ipm_arg_set_tol_eq(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on inequality constr +void s_ocp_qcqp_ipm_arg_set_tol_ineq(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on complementarity condition +void s_ocp_qcqp_ipm_arg_set_tol_comp(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set regularization of primal variables +void s_ocp_qcqp_ipm_arg_set_reg_prim(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// set warm start: 0 no warm start, 1 primal var +void s_ocp_qcqp_ipm_arg_set_warm_start(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// Mehrotra's predictor-corrector IPM algorithm: 0 no predictor-corrector, 1 use predictor-corrector +void s_ocp_qcqp_ipm_arg_set_pred_corr(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// conditional predictor-corrector: 0 no conditinal predictor-corrector, 1 conditional predictor-corrector +void s_ocp_qcqp_ipm_arg_set_cond_pred_corr(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// set riccati algorithm: 0 classic, 1 square-root +void s_ocp_qcqp_ipm_arg_set_ric_alg(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// compute residuals after solution +void s_ocp_qcqp_ipm_arg_set_comp_res_exit(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// compute residuals of prediction +void s_ocp_qcqp_ipm_arg_set_comp_res_pred(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// min value of lam in the solution +void s_ocp_qcqp_ipm_arg_set_lam_min(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// min value of t in the solution +void s_ocp_qcqp_ipm_arg_set_t_min(float *value, struct s_ocp_qcqp_ipm_arg *arg); +// use different step for primal and dual variables +void s_ocp_qcqp_ipm_arg_set_split_step(int *value, struct s_ocp_qcqp_ipm_arg *arg); +// clip t and lam: 0 no, 1 in Gamma computation, 2 in solution +void s_ocp_qcqp_ipm_arg_set_t_lam_min(int *value, struct s_ocp_qcqp_ipm_arg *arg); + +// +hpipm_size_t s_ocp_qcqp_ipm_ws_strsize(); +// +hpipm_size_t s_ocp_qcqp_ipm_ws_memsize(struct s_ocp_qcqp_dim *ocp_dim, struct s_ocp_qcqp_ipm_arg *arg); +// +void s_ocp_qcqp_ipm_ws_create(struct s_ocp_qcqp_dim *ocp_dim, struct s_ocp_qcqp_ipm_arg *arg, struct s_ocp_qcqp_ipm_ws *ws, void *mem); +// +void s_ocp_qcqp_ipm_get(char *field, struct s_ocp_qcqp_ipm_ws *ws, void *value); +// +void s_ocp_qcqp_ipm_get_status(struct s_ocp_qcqp_ipm_ws *ws, int *status); +// +void s_ocp_qcqp_ipm_get_iter(struct s_ocp_qcqp_ipm_ws *ws, int *iter); +// +void s_ocp_qcqp_ipm_get_max_res_stat(struct s_ocp_qcqp_ipm_ws *ws, float *res_stat); +// +void s_ocp_qcqp_ipm_get_max_res_eq(struct s_ocp_qcqp_ipm_ws *ws, float *res_eq); +// +void s_ocp_qcqp_ipm_get_max_res_ineq(struct s_ocp_qcqp_ipm_ws *ws, float *res_ineq); +// +void s_ocp_qcqp_ipm_get_max_res_comp(struct s_ocp_qcqp_ipm_ws *ws, float *res_comp); +// +void s_ocp_qcqp_ipm_get_stat(struct s_ocp_qcqp_ipm_ws *ws, float **stat); +// +void s_ocp_qcqp_ipm_get_stat_m(struct s_ocp_qcqp_ipm_ws *ws, int *stat_m); +// +void s_ocp_qcqp_init_var(struct s_ocp_qcqp *qp, struct s_ocp_qcqp_sol *qp_sol, struct s_ocp_qcqp_ipm_arg *arg, struct s_ocp_qcqp_ipm_ws *ws); +// +void s_ocp_qcqp_ipm_solve(struct s_ocp_qcqp *qp, struct s_ocp_qcqp_sol *qp_sol, struct s_ocp_qcqp_ipm_arg *arg, struct s_ocp_qcqp_ipm_ws *ws); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_OCP_QCQP_IPM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_res.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_res.h new file mode 100644 index 0000000000..1ceeec93b7 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_res.h @@ -0,0 +1,115 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QCQP_RES_H_ +#define HPIPM_S_OCP_QCQP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qcqp_res + { + struct s_ocp_qcqp_dim *dim; + struct blasfeo_svec *res_g; // q-residuals + struct blasfeo_svec *res_b; // b-residuals + struct blasfeo_svec *res_d; // d-residuals + struct blasfeo_svec *res_m; // m-residuals + float res_max[4]; // max of residuals + float res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct s_ocp_qcqp_res_ws + { + struct blasfeo_svec *tmp_nuxM; // work space of size nuM+nxM + struct blasfeo_svec *tmp_nbgqM; // work space of size nbM+ngM+nqM + struct blasfeo_svec *tmp_nsM; // work space of size nsM + struct blasfeo_svec *q_fun; // value for evaluation of quadr constr + struct blasfeo_svec *q_adj; // value for adjoint of quadr constr + int use_q_fun; // reuse cached value for evaluation of quadr constr + int use_q_adj; // reuse cached value for adjoint of quadr constr + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_ocp_qcqp_res_memsize(struct s_ocp_qcqp_dim *ocp_dim); +// +void s_ocp_qcqp_res_create(struct s_ocp_qcqp_dim *ocp_dim, struct s_ocp_qcqp_res *res, void *mem); +// +hpipm_size_t s_ocp_qcqp_res_ws_memsize(struct s_ocp_qcqp_dim *ocp_dim); +// +void s_ocp_qcqp_res_ws_create(struct s_ocp_qcqp_dim *ocp_dim, struct s_ocp_qcqp_res_ws *workspace, void *mem); +// +void s_ocp_qcqp_res_compute(struct s_ocp_qcqp *qp, struct s_ocp_qcqp_sol *qp_sol, struct s_ocp_qcqp_res *res, struct s_ocp_qcqp_res_ws *ws); +// +void s_ocp_qcqp_res_compute_inf_norm(struct s_ocp_qcqp_res *res); +// +void s_ocp_qcqp_res_get_max_res_stat(struct s_ocp_qcqp_res *res, float *value); +// +void s_ocp_qcqp_res_get_max_res_eq(struct s_ocp_qcqp_res *res, float *value); +// +void s_ocp_qcqp_res_get_max_res_ineq(struct s_ocp_qcqp_res *res, float *value); +// +void s_ocp_qcqp_res_get_max_res_comp(struct s_ocp_qcqp_res *res, float *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_OCP_QCQP_RES_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_sol.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_sol.h new file mode 100644 index 0000000000..3d58022cc9 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_sol.h @@ -0,0 +1,115 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QCQP_SOL_H_ +#define HPIPM_S_OCP_QCQP_SOL_H_ + + + +#include +#include + +#include "hpipm_s_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qcqp_sol + { + struct s_ocp_qcqp_dim *dim; + struct blasfeo_svec *ux; + struct blasfeo_svec *pi; + struct blasfeo_svec *lam; + struct blasfeo_svec *t; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_ocp_qcqp_sol_strsize(); +// +hpipm_size_t s_ocp_qcqp_sol_memsize(struct s_ocp_qcqp_dim *dim); +// +void s_ocp_qcqp_sol_create(struct s_ocp_qcqp_dim *dim, struct s_ocp_qcqp_sol *qp_sol, void *memory); +// +void s_ocp_qcqp_sol_copy_all(struct s_ocp_qcqp_sol *qp_sol_orig, struct s_ocp_qcqp_sol *qp_sol_dest); +// +void s_ocp_qcqp_sol_get(char *field, int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_u(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_x(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_sl(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_su(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_pi(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_lam_lb(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_lam_ub(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_lam_lg(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_get_lam_ug(int stage, struct s_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_ocp_qcqp_sol_set(char *field, int stage, float *vec, struct s_ocp_qcqp_sol *qp_sol); +// +void s_ocp_qcqp_sol_set_u(int stage, float *vec, struct s_ocp_qcqp_sol *qp_sol); +// +void s_ocp_qcqp_sol_set_x(int stage, float *vec, struct s_ocp_qcqp_sol *qp_sol); +// +void s_ocp_qcqp_sol_set_sl(int stage, float *vec, struct s_ocp_qcqp_sol *qp_sol); +// +void s_ocp_qcqp_sol_set_su(int stage, float *vec, struct s_ocp_qcqp_sol *qp_sol); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_OCP_QCQP_SOL_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_utils.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_utils.h new file mode 100644 index 0000000000..d64e3aabe7 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qcqp_utils.h @@ -0,0 +1,82 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QCQP_UTILS_H_ +#define HPIPM_S_OCP_QCQP_UTILS_H_ + + + +#include +#include + +#include "hpipm_s_ocp_qcqp_dim.h" +#include "hpipm_s_ocp_qp.h" +#include "hpipm_s_ocp_qcqp_sol.h" +#include "hpipm_s_ocp_qcqp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_ocp_qcqp_dim_print(struct s_ocp_qcqp_dim *qcqp_dim); +// +void s_ocp_qcqp_dim_codegen(char *file_name, char *mode, struct s_ocp_qcqp_dim *qcqp_dim); +// +void s_ocp_qcqp_print(struct s_ocp_qcqp_dim *qcqp_dim, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_codegen(char *file_name, char *mode, struct s_ocp_qcqp_dim *qcqp_dim, struct s_ocp_qcqp *qp); +// +void s_ocp_qcqp_sol_print(struct s_ocp_qcqp_dim *qcqp_dim, struct s_ocp_qcqp_sol *ocp_qcqp_sol); +// +void s_ocp_qcqp_ipm_arg_codegen(char *file_name, char *mode, struct s_ocp_qcqp_dim *qcqp_dim, struct s_ocp_qcqp_ipm_arg *arg); +// +void s_ocp_qcqp_res_print(struct s_ocp_qcqp_dim *qcqp_dim, struct s_ocp_qcqp_res *ocp_qcqp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_OCP_QCQP_UTILS_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp.h new file mode 100644 index 0000000000..b49191f192 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp.h @@ -0,0 +1,306 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_H_ +#define HPIPM_S_OCP_QP_H_ + + + +#include +#include + +#include "hpipm_s_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qp + { + struct s_ocp_qp_dim *dim; + struct blasfeo_smat *BAbt; // dynamics matrix & vector work space + struct blasfeo_smat *RSQrq; // hessian of cost & vector work space + struct blasfeo_smat *DCt; // inequality constraints matrix + struct blasfeo_svec *b; // dynamics vector + struct blasfeo_svec *rqz; // gradient of cost & gradient of slacks + struct blasfeo_svec *d; // inequality constraints vector + struct blasfeo_svec *d_mask; // inequality constraints mask vector + struct blasfeo_svec *m; // rhs of complementarity condition + struct blasfeo_svec *Z; // (diagonal) hessian of slacks + int **idxb; // indices of box constrained variables within [u; x] + int **idxs_rev; // index of soft constraints (reverse storage) + int **idxe; // indices of constraints within [bu, bx, g] that are equalities, subset of [0, ..., nbu+nbx+ng-1] + int *diag_H_flag; // flag the fact that Hessian is diagonal + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_ocp_qp_strsize(); +// +hpipm_size_t s_ocp_qp_memsize(struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_create(struct s_ocp_qp_dim *dim, struct s_ocp_qp *qp, void *memory); +// +void s_ocp_qp_copy_all(struct s_ocp_qp *qp_orig, struct s_ocp_qp *qp_dest); + +// setters +// +void s_ocp_qp_set_all_zero(struct s_ocp_qp *qp); +// +void s_ocp_qp_set_rhs_zero(struct s_ocp_qp *qp); +// +void s_ocp_qp_set_all(float **A, float **B, float **b, float **Q, float **S, float **R, float **q, float **r, int **idxbx, float **lbx, float **ubx, int **idxbu, float **lbu, float **ubu, float **C, float **D, float **lg, float **ug, float **Zl, float **Zu, float **zl, float **zu, int **idxs, float **ls, float **us, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_all_rowmaj(float **A, float **B, float **b, float **Q, float **S, float **R, float **q, float **r, int **idxbx, float **lbx, float **ubx, int **idxbu, float **lbu, float **ubu, float **C, float **D, float **lg, float **ug, float **Zl, float **Zu, float **zl, float **zu, int **idxs, float **ls, float **us, struct s_ocp_qp *qp); +// +void s_ocp_qp_set(char *fiels_name, int stage, void *value, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_el(char *fiels_name, int stage, int index, void *value, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_A(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_B(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_b(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Q(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_S(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_R(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_q(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_r(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lb(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lb_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ub(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ub_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lbx(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lbx_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_el_lbx(int stage, int index, float *elem, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ubx(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ubx_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_el_ubx(int stage, int index, float *elem, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lbu(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lbu_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ubu(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ubu_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxb(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxbx(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jbx(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxbu(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jbu(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_C(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_D(int stage, float *mat, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lg(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lg_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ug(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_ug_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Zl(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Zu(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_zl(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_zu(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lls(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lls_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lus(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_lus_mask(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxs(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxs_rev(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jsbu(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jsbx(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jsg(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxe(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxbxe(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxbue(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_idxge(int stage, int *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jbxe(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jbue(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_Jge(int stage, float *vec, struct s_ocp_qp *qp); +// +void s_ocp_qp_set_diag_H_flag(int stage, int *value, struct s_ocp_qp *qp); + +// getters +// +void s_ocp_qp_get(char *field, int stage, struct s_ocp_qp *qp, void *value); +// +void s_ocp_qp_get_A(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_B(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_b(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_Q(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_S(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_R(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_q(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_r(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ub(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ub_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lb(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lb_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lbx(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lbx_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ubx(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ubx_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lbu(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lbu_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ubu(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ubu_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_idxb(int stage, struct s_ocp_qp *qp, int *vec); +// +//void s_ocp_qp_get_idxbx(int stage, struct s_ocp_qp *qp, int *vec); +// +//void s_ocp_qp_get_Jbx(int stage, struct s_ocp_qp *qp, float *vec); +// +//void s_ocp_qp_get_idxbu(int stage, struct s_ocp_qp *qp, int *vec); +// +//void s_ocp_qp_get_Jbu(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_C(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_D(int stage, struct s_ocp_qp *qp, float *mat); +// +void s_ocp_qp_get_lg(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lg_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ug(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_ug_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_Zl(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_Zu(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_zl(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_zu(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lls(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lls_mask(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lus(int stage, struct s_ocp_qp *qp, float *vec); +// +void s_ocp_qp_get_lus_mask(int stage, struct s_ocp_qp *qp, float *vec); +// XXX only valid if there is one slack per softed constraint !!! +void s_ocp_qp_get_idxs(int stage, struct s_ocp_qp *qp, int *vec); +// +void s_ocp_qp_get_idxs_rev(int stage, struct s_ocp_qp *qp, int *vec); +// +//void s_ocp_qp_get_Jsbu(int stage, struct s_ocp_qp *qp, float *vec); +// +//void s_ocp_qp_get_Jsbx(int stage, struct s_ocp_qp *qp, float *vec); +// +//void s_ocp_qp_get_Jsg(int stage, struct s_ocp_qp *qp, float *vec); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_OCP_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_dim.h new file mode 100644 index 0000000000..bce80243b3 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_dim.h @@ -0,0 +1,141 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_DIM_H_ +#define HPIPM_S_OCP_QP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qp_dim + { + int *nx; // number of states + int *nu; // number of inputs + int *nb; // number of box constraints + int *nbx; // number of state box constraints + int *nbu; // number of input box constraints + int *ng; // number of general constraints + int *ns; // number of soft constraints + int *nsbx; // number of soft state box constraints + int *nsbu; // number of soft input box constraints + int *nsg; // number of soft general constraints + int *nbxe; // number of state box constraints which are equality + int *nbue; // number of input box constraints which are equality + int *nge; // number of general constraints which are equality + int N; // horizon length + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_ocp_qp_dim_strsize(); +// +hpipm_size_t s_ocp_qp_dim_memsize(int N); +// +void s_ocp_qp_dim_create(int N, struct s_ocp_qp_dim *qp_dim, void *memory); +// +void s_ocp_qp_dim_copy_all(struct s_ocp_qp_dim *dim_orig, struct s_ocp_qp_dim *dim_dest); +// +void s_ocp_qp_dim_set_all(int *nx, int *nu, int *nbx, int *nbu, int *ng, int *nsbx, int *nsbu, int *nsg, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set(char *field, int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nx(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nu(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nbx(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nbu(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_ng(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_ns(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nsbx(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nsbu(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nsg(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nbxe(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nbue(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_set_nge(int stage, int value, struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_dim_get(struct s_ocp_qp_dim *dim, char *field, int stage, int *value); +// +void s_ocp_qp_dim_get_N(struct s_ocp_qp_dim *dim, int *value); +// +void s_ocp_qp_dim_get_nx(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nu(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nbx(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nbu(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_ng(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_ns(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nsbx(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nsbu(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nsg(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nbxe(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nbue(struct s_ocp_qp_dim *dim, int stage, int *value); +// +void s_ocp_qp_dim_get_nge(struct s_ocp_qp_dim *dim, int stage, int *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_OCP_QP_DIM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_ipm.h new file mode 100644 index 0000000000..11f3c47be6 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_ipm.h @@ -0,0 +1,250 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_IPM_H_ +#define HPIPM_S_OCP_QP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qp_ipm_arg + { + float mu0; // initial value for complementarity slackness + float alpha_min; // exit cond on step length + float res_g_max; // exit cond on inf norm of residuals + float res_b_max; // exit cond on inf norm of residuals + float res_d_max; // exit cond on inf norm of residuals + float res_m_max; // exit cond on inf norm of residuals + float reg_prim; // reg of primal hessian + float lam_min; // min value in lam vector + float t_min; // min value in t vector + float tau_min; // min value of barrier parameter + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int square_root_alg; // 0 classical Riccati, 1 square-root Riccati + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq (for square_root_alg==1) + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution of equality constraints (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol_eq==1) + int comp_res_pred; // compute residuals of prediction + int split_step; // use different steps for primal and dual variables + int var_init_scheme; // variables initialization scheme + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct s_ocp_qp_ipm_ws + { + struct s_core_qp_ipm_workspace *core_workspace; + struct s_ocp_qp_res_ws *res_workspace; + struct s_ocp_qp_dim *dim; // cache dim + struct s_ocp_qp_sol *sol_step; + struct s_ocp_qp_sol *sol_itref; + struct s_ocp_qp *qp_step; + struct s_ocp_qp *qp_itref; + struct s_ocp_qp_res *res; + struct s_ocp_qp_res *res_itref; + struct blasfeo_svec *Gamma; // hessian update + struct blasfeo_svec *gamma; // hessian update + struct blasfeo_svec *tmp_nuxM; // work space of size nxM + struct blasfeo_svec *tmp_nbgM; // work space of size nbM+ngM + struct blasfeo_svec *tmp_nsM; // work space of size nsM + struct blasfeo_svec *Pb; // Pb + struct blasfeo_svec *Zs_inv; + struct blasfeo_svec *tmp_m; + struct blasfeo_svec *l; // cache linear part for _get_ric_xxx + struct blasfeo_smat *L; + struct blasfeo_smat *Ls; + struct blasfeo_smat *P; + struct blasfeo_smat *Lh; + struct blasfeo_smat *AL; + struct blasfeo_smat *lq0; + struct blasfeo_smat *tmp_nxM_nxM; + float *stat; // convergence statistics + int *use_hess_fact; + void *lq_work0; + float qp_res[4]; // infinity norm of residuals + int iter; // iteration number + int stat_max; // iterations saved in stat + int stat_m; // number of recorded stat per IPM iter + int use_Pb; + int status; // solver status + int square_root_alg; // cache from arg + int lq_fact; // cache from arg + int mask_constr; // use constr mask + int valid_ric_vec; // meaningful riccati vectors + int valid_ric_p; // form of riccati p: 0 p*inv(L), 1 p + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_ocp_qp_ipm_arg_strsize(); +// +hpipm_size_t s_ocp_qp_ipm_arg_memsize(struct s_ocp_qp_dim *ocp_dim); +// +void s_ocp_qp_ipm_arg_create(struct s_ocp_qp_dim *ocp_dim, struct s_ocp_qp_ipm_arg *arg, void *mem); +// +void s_ocp_qp_ipm_arg_set_default(enum hpipm_mode mode, struct s_ocp_qp_ipm_arg *arg); +// +void s_ocp_qp_ipm_arg_set(char *field, void *value, struct s_ocp_qp_ipm_arg *arg); +// set maximum number of iterations +void s_ocp_qp_ipm_arg_set_iter_max(int *iter_max, struct s_ocp_qp_ipm_arg *arg); +// set minimum step lenght +void s_ocp_qp_ipm_arg_set_alpha_min(float *alpha_min, struct s_ocp_qp_ipm_arg *arg); +// set initial value of barrier parameter +void s_ocp_qp_ipm_arg_set_mu0(float *mu0, struct s_ocp_qp_ipm_arg *arg); +// set exit tolerance on stationarity condition +void s_ocp_qp_ipm_arg_set_tol_stat(float *tol_stat, struct s_ocp_qp_ipm_arg *arg); +// set exit tolerance on equality constr +void s_ocp_qp_ipm_arg_set_tol_eq(float *tol_eq, struct s_ocp_qp_ipm_arg *arg); +// set exit tolerance on inequality constr +void s_ocp_qp_ipm_arg_set_tol_ineq(float *tol_ineq, struct s_ocp_qp_ipm_arg *arg); +// set exit tolerance on complementarity condition +void s_ocp_qp_ipm_arg_set_tol_comp(float *tol_comp, struct s_ocp_qp_ipm_arg *arg); +// set regularization of primal variables +void s_ocp_qp_ipm_arg_set_reg_prim(float *tol_comp, struct s_ocp_qp_ipm_arg *arg); +// set warm start: 0 no warm start, 1 primal var +void s_ocp_qp_ipm_arg_set_warm_start(int *warm_start, struct s_ocp_qp_ipm_arg *arg); +// Mehrotra's predictor-corrector IPM algorithm: 0 no predictor-corrector, 1 use predictor-corrector +void s_ocp_qp_ipm_arg_set_pred_corr(int *pred_corr, struct s_ocp_qp_ipm_arg *arg); +// conditional predictor-corrector: 0 no conditinal predictor-corrector, 1 conditional predictor-corrector +void s_ocp_qp_ipm_arg_set_cond_pred_corr(int *value, struct s_ocp_qp_ipm_arg *arg); +// set riccati algorithm: 0 classic, 1 square-root +void s_ocp_qp_ipm_arg_set_ric_alg(int *alg, struct s_ocp_qp_ipm_arg *arg); +// dual solution of equality constraints (only for abs_form==1) +void s_ocp_qp_ipm_arg_set_comp_dual_sol_eq(int *value, struct s_ocp_qp_ipm_arg *arg); +// compute residuals after solution +void s_ocp_qp_ipm_arg_set_comp_res_exit(int *value, struct s_ocp_qp_ipm_arg *arg); +// compute residuals of prediction +void s_ocp_qp_ipm_arg_set_comp_res_pred(int *alg, struct s_ocp_qp_ipm_arg *arg); +// min value of lam in the solution +void s_ocp_qp_ipm_arg_set_lam_min(float *value, struct s_ocp_qp_ipm_arg *arg); +// min value of t in the solution +void s_ocp_qp_ipm_arg_set_t_min(float *value, struct s_ocp_qp_ipm_arg *arg); +// min value of tau in the solution +void s_ocp_qp_ipm_arg_set_tau_min(float *value, struct s_ocp_qp_ipm_arg *arg); +// set split step: 0 same step, 1 different step for primal and dual variables +void s_ocp_qp_ipm_arg_set_split_step(int *value, struct s_ocp_qp_ipm_arg *arg); +// variables initialization scheme +void s_ocp_qp_ipm_arg_set_var_init_scheme(int *value, struct s_ocp_qp_ipm_arg *arg); +// clip t and lam: 0 no, 1 in Gamma computation, 2 in solution +void s_ocp_qp_ipm_arg_set_t_lam_min(int *value, struct s_ocp_qp_ipm_arg *arg); + +// +hpipm_size_t s_ocp_qp_ipm_ws_strsize(); +// +hpipm_size_t s_ocp_qp_ipm_ws_memsize(struct s_ocp_qp_dim *ocp_dim, struct s_ocp_qp_ipm_arg *arg); +// +void s_ocp_qp_ipm_ws_create(struct s_ocp_qp_dim *ocp_dim, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, void *mem); +// +void s_ocp_qp_ipm_get(char *field, struct s_ocp_qp_ipm_ws *ws, void *value); +// +void s_ocp_qp_ipm_get_status(struct s_ocp_qp_ipm_ws *ws, int *status); +// +void s_ocp_qp_ipm_get_iter(struct s_ocp_qp_ipm_ws *ws, int *iter); +// +void s_ocp_qp_ipm_get_max_res_stat(struct s_ocp_qp_ipm_ws *ws, float *res_stat); +// +void s_ocp_qp_ipm_get_max_res_eq(struct s_ocp_qp_ipm_ws *ws, float *res_eq); +// +void s_ocp_qp_ipm_get_max_res_ineq(struct s_ocp_qp_ipm_ws *ws, float *res_ineq); +// +void s_ocp_qp_ipm_get_max_res_comp(struct s_ocp_qp_ipm_ws *ws, float *res_comp); +// +void s_ocp_qp_ipm_get_stat(struct s_ocp_qp_ipm_ws *ws, float **stat); +// +void s_ocp_qp_ipm_get_stat_m(struct s_ocp_qp_ipm_ws *ws, int *stat_m); +// +void s_ocp_qp_ipm_get_ric_Lr(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *Lr); +// +void s_ocp_qp_ipm_get_ric_Ls(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *Ls); +// +void s_ocp_qp_ipm_get_ric_P(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *P); +// +void s_ocp_qp_ipm_get_ric_lr(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *lr); +// +void s_ocp_qp_ipm_get_ric_p(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *p); +// feedback control gain in the form u = K x + k +void s_ocp_qp_ipm_get_ric_K(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *K); +// feedback control gain in the form u = K x + k +void s_ocp_qp_ipm_get_ric_k(struct s_ocp_qp *qp, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws, int stage, float *k); +// +void s_ocp_qp_init_var(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_ipm_abs_step(int kk, struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_ipm_delta_step(int kk, struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_ipm_solve(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_ipm_predict(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_ipm_sens(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_OCP_QP_IPM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_kkt.h new file mode 100644 index 0000000000..3eb1f4aae8 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_kkt.h @@ -0,0 +1,66 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + +#ifndef HPIPM_S_OCP_QP_KKT_H_ +#define HPIPM_S_OCP_QP_KKT_H_ + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + +// +void s_ocp_qp_fact_solve_kkt_unconstr(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_fact_solve_kkt_step(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_fact_lq_solve_kkt_step(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); +// +void s_ocp_qp_solve_kkt_step(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_ipm_arg *arg, struct s_ocp_qp_ipm_ws *ws); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif // HPIPM_S_OCP_QP_KKT_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_red.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_red.h new file mode 100644 index 0000000000..5a7b3b0703 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_red.h @@ -0,0 +1,118 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_RED_H_ +#define HPIPM_S_OCP_QP_RED_H_ + + + +#include +#include + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qp_reduce_eq_dof_arg + { + float lam_min; + float t_min; + int alias_unchanged; // do not keep copy unchanged stage + int comp_prim_sol; // primal solution (v) + int comp_dual_sol_eq; // dual solution equality constr (pi) + int comp_dual_sol_ineq; // dual solution inequality constr (lam t) + hpipm_size_t memsize; // memory size in bytes + }; + + + +struct s_ocp_qp_reduce_eq_dof_ws + { + struct blasfeo_svec *tmp_nuxM; + struct blasfeo_svec *tmp_nbgM; + int *e_imask_ux; + int *e_imask_d; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +void s_ocp_qp_dim_reduce_eq_dof(struct s_ocp_qp_dim *dim, struct s_ocp_qp_dim *dim_red); +// +hpipm_size_t s_ocp_qp_reduce_eq_dof_arg_memsize(); +// +void s_ocp_qp_reduce_eq_dof_arg_create(struct s_ocp_qp_reduce_eq_dof_arg *arg, void *mem); +// +void s_ocp_qp_reduce_eq_dof_arg_set_default(struct s_ocp_qp_reduce_eq_dof_arg *arg); +// +void s_ocp_qp_reduce_eq_dof_arg_set_alias_unchanged(struct s_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +void s_ocp_qp_reduce_eq_dof_arg_set_comp_prim_sol(struct s_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +void s_ocp_qp_reduce_eq_dof_arg_set_comp_dual_sol_eq(struct s_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +void s_ocp_qp_reduce_eq_dof_arg_set_comp_dual_sol_ineq(struct s_ocp_qp_reduce_eq_dof_arg *arg, int value); +// +hpipm_size_t s_ocp_qp_reduce_eq_dof_ws_memsize(struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_reduce_eq_dof_ws_create(struct s_ocp_qp_dim *dim, struct s_ocp_qp_reduce_eq_dof_ws *work, void *mem); +// +void s_ocp_qp_reduce_eq_dof(struct s_ocp_qp *qp, struct s_ocp_qp *qp_red, struct s_ocp_qp_reduce_eq_dof_arg *arg, struct s_ocp_qp_reduce_eq_dof_ws *work); +// +void s_ocp_qp_reduce_eq_dof_lhs(struct s_ocp_qp *qp, struct s_ocp_qp *qp_red, struct s_ocp_qp_reduce_eq_dof_arg *arg, struct s_ocp_qp_reduce_eq_dof_ws *work); +// +void s_ocp_qp_reduce_eq_dof_rhs(struct s_ocp_qp *qp, struct s_ocp_qp *qp_red, struct s_ocp_qp_reduce_eq_dof_arg *arg, struct s_ocp_qp_reduce_eq_dof_ws *work); +// +void s_ocp_qp_restore_eq_dof(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol_red, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_reduce_eq_dof_arg *arg, struct s_ocp_qp_reduce_eq_dof_ws *work); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_OCP_QP_RED_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_res.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_res.h new file mode 100644 index 0000000000..821585da65 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_res.h @@ -0,0 +1,114 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_RES_H_ +#define HPIPM_S_OCP_QP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qp_res + { + struct s_ocp_qp_dim *dim; + struct blasfeo_svec *res_g; // q-residuals + struct blasfeo_svec *res_b; // b-residuals + struct blasfeo_svec *res_d; // d-residuals + struct blasfeo_svec *res_m; // m-residuals + float res_max[4]; // max of residuals + float res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct s_ocp_qp_res_ws + { + struct blasfeo_svec *tmp_nbgM; // work space of size nbM+ngM + struct blasfeo_svec *tmp_nsM; // work space of size nsM + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_ocp_qp_res_memsize(struct s_ocp_qp_dim *ocp_dim); +// +void s_ocp_qp_res_create(struct s_ocp_qp_dim *ocp_dim, struct s_ocp_qp_res *res, void *mem); +// +hpipm_size_t s_ocp_qp_res_ws_memsize(struct s_ocp_qp_dim *ocp_dim); +// +void s_ocp_qp_res_ws_create(struct s_ocp_qp_dim *ocp_dim, struct s_ocp_qp_res_ws *workspace, void *mem); +// +void s_ocp_qp_res_compute(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_res *res, struct s_ocp_qp_res_ws *ws); +// +void s_ocp_qp_res_compute_lin(struct s_ocp_qp *qp, struct s_ocp_qp_sol *qp_sol, struct s_ocp_qp_sol *qp_step, struct s_ocp_qp_res *res, struct s_ocp_qp_res_ws *ws); +// +void s_ocp_qp_res_compute_inf_norm(struct s_ocp_qp_res *res); +// +void s_ocp_qp_res_get_all(struct s_ocp_qp_res *res, float **res_r, float **res_q, float **res_ls, float **res_us, float **res_b, float **res_d_lb, float **res_d_ub, float **res_d_lg, float **res_d_ug, float **res_d_ls, float **res_d_us, float **res_m_lb, float **res_m_ub, float **res_m_lg, float **res_m_ug, float **res_m_ls, float **res_m_us); +// +void s_ocp_qp_res_get_max_res_stat(struct s_ocp_qp_res *res, float *value); +// +void s_ocp_qp_res_get_max_res_eq(struct s_ocp_qp_res *res, float *value); +// +void s_ocp_qp_res_get_max_res_ineq(struct s_ocp_qp_res *res, float *value); +// +void s_ocp_qp_res_get_max_res_comp(struct s_ocp_qp_res *res, float *value); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_OCP_QP_RES_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_sol.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_sol.h new file mode 100644 index 0000000000..94dfa0d003 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_sol.h @@ -0,0 +1,128 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_SOL_H_ +#define HPIPM_S_OCP_QP_SOL_H_ + + + +#include +#include + +#include "hpipm_s_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_ocp_qp_sol + { + struct s_ocp_qp_dim *dim; + struct blasfeo_svec *ux; + struct blasfeo_svec *pi; + struct blasfeo_svec *lam; + struct blasfeo_svec *t; + void *misc; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_ocp_qp_sol_strsize(); +// +hpipm_size_t s_ocp_qp_sol_memsize(struct s_ocp_qp_dim *dim); +// +void s_ocp_qp_sol_create(struct s_ocp_qp_dim *dim, struct s_ocp_qp_sol *qp_sol, void *memory); +// +void s_ocp_qp_sol_copy_all(struct s_ocp_qp_sol *qp_sol_orig, struct s_ocp_qp_sol *qp_sol_dest); +// +void s_qp_sol_get_all(struct s_ocp_qp_sol *qp_sol, float **u, float **x, float **ls, float **us, float **pi, float **lam_lb, float **lam_ub, float **lam_lg, float **lam_ug, float **lam_ls, float **lam_us); +// +void s_qp_sol_get_all_rowmaj(struct s_ocp_qp_sol *qp_sol, float **u, float **x, float **ls, float **us, float **pi, float **lam_lb, float **lam_ub, float **lam_lg, float **lam_ug, float **lam_ls, float **lam_us); +// +void s_ocp_qp_sol_set_all(float **u, float **x, float **ls, float **us, float **pi, float **lam_lb, float **lam_ub, float **lam_lg, float **lam_ug, float **lam_ls, float **lam_us, struct s_ocp_qp_sol *qp_sol); +// +void s_ocp_qp_sol_get(char *field, int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_u(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_x(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_sl(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_su(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_pi(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_lb(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_lbu(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_lbx(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_ub(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_ubu(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_ubx(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_lg(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_get_lam_ug(int stage, struct s_ocp_qp_sol *qp_sol, float *vec); +// +void s_ocp_qp_sol_set(char *field, int stage, float *vec, struct s_ocp_qp_sol *qp_sol); +// +void s_ocp_qp_sol_set_u(int stage, float *vec, struct s_ocp_qp_sol *qp_sol); +// +void s_ocp_qp_sol_set_x(int stage, float *vec, struct s_ocp_qp_sol *qp_sol); +// +void s_ocp_qp_sol_set_sl(int stage, float *vec, struct s_ocp_qp_sol *qp_sol); +// +void s_ocp_qp_sol_set_su(int stage, float *vec, struct s_ocp_qp_sol *qp_sol); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_OCP_QP_SOL_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_utils.h b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_utils.h new file mode 100644 index 0000000000..a4f832a5ea --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_ocp_qp_utils.h @@ -0,0 +1,83 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_OCP_QP_UTILS_H_ +#define HPIPM_S_OCP_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_s_ocp_qp_dim.h" +#include "hpipm_s_ocp_qp.h" +#include "hpipm_s_ocp_qp_sol.h" +#include "hpipm_s_ocp_qp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_ocp_qp_dim_print(struct s_ocp_qp_dim *qp_dim); +// +void s_ocp_qp_dim_codegen(char *file_name, char *mode, struct s_ocp_qp_dim *qp_dim); +// +void s_ocp_qp_print(struct s_ocp_qp_dim *qp_dim, struct s_ocp_qp *qp); +// +void s_ocp_qp_codegen(char *file_name, char *mode, struct s_ocp_qp_dim *qp_dim, struct s_ocp_qp *qp); +// +void s_ocp_qp_sol_print(struct s_ocp_qp_dim *qp_dim, struct s_ocp_qp_sol *ocp_qp_sol); +// +void s_ocp_qp_ipm_arg_print(struct s_ocp_qp_dim *qp_dim, struct s_ocp_qp_ipm_arg *arg); +// +void s_ocp_qp_ipm_arg_codegen(char *file_name, char *mode, struct s_ocp_qp_dim *qp_dim, struct s_ocp_qp_ipm_arg *arg); +// +void s_ocp_qp_res_print(struct s_ocp_qp_dim *qp_dim, struct s_ocp_qp_res *ocp_qp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_D_OCP_QP_UTILS_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_part_cond.h b/third_party/acados/include/hpipm/include/hpipm_s_part_cond.h new file mode 100644 index 0000000000..e40511e69f --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_part_cond.h @@ -0,0 +1,115 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_PART_COND_H_ +#define HPIPM_S_PART_COND_H_ + + + +#include +#include + +#include "hpipm_s_cond.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_part_cond_qp_arg + { + struct s_cond_qp_arg *cond_arg; + int N2; + hpipm_size_t memsize; + }; + + + +struct s_part_cond_qp_ws + { + struct s_cond_qp_ws *cond_workspace; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_part_cond_qp_arg_memsize(int N2); +// +void s_part_cond_qp_arg_create(int N2, struct s_part_cond_qp_arg *cond_arg, void *mem); +// +void s_part_cond_qp_arg_set_default(struct s_part_cond_qp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 squre-root +void s_part_cond_qp_arg_set_ric_alg(int ric_alg, struct s_part_cond_qp_arg *cond_arg); +// +void s_part_cond_qp_arg_set_comp_prim_sol(int value, struct s_part_cond_qp_arg *cond_arg); +// +void s_part_cond_qp_arg_set_comp_dual_sol_eq(int value, struct s_part_cond_qp_arg *cond_arg); +// +void s_part_cond_qp_arg_set_comp_dual_sol_ineq(int value, struct s_part_cond_qp_arg *cond_arg); + +// +void s_part_cond_qp_compute_block_size(int N, int N2, int *block_size); +// +void s_part_cond_qp_compute_dim(struct s_ocp_qp_dim *ocp_dim, int *block_size, struct s_ocp_qp_dim *part_dense_dim); +// +hpipm_size_t s_part_cond_qp_ws_memsize(struct s_ocp_qp_dim *ocp_dim, int *block_size, struct s_ocp_qp_dim *part_dense_dim, struct s_part_cond_qp_arg *cond_arg); +// +void s_part_cond_qp_ws_create(struct s_ocp_qp_dim *ocp_dim, int *block_size, struct s_ocp_qp_dim *part_dense_dim, struct s_part_cond_qp_arg *cond_arg, struct s_part_cond_qp_ws *cond_ws, void *mem); +// +void s_part_cond_qp_cond(struct s_ocp_qp *ocp_qp, struct s_ocp_qp *part_dense_qp, struct s_part_cond_qp_arg *cond_arg, struct s_part_cond_qp_ws *cond_ws); +// +void s_part_cond_qp_cond_lhs(struct s_ocp_qp *ocp_qp, struct s_ocp_qp *part_dense_qp, struct s_part_cond_qp_arg *cond_arg, struct s_part_cond_qp_ws *cond_ws); +// +void s_part_cond_qp_cond_rhs(struct s_ocp_qp *ocp_qp, struct s_ocp_qp *part_dense_qp, struct s_part_cond_qp_arg *cond_arg, struct s_part_cond_qp_ws *cond_ws); +// +void s_part_cond_qp_expand_sol(struct s_ocp_qp *ocp_qp, struct s_ocp_qp *part_dense_qp, struct s_ocp_qp_sol *part_dense_qp_sol, struct s_ocp_qp_sol *ocp_qp_sol, struct s_part_cond_qp_arg *cond_arg, struct s_part_cond_qp_ws *cond_ws); + +// +void s_part_cond_qp_update(int *idxc, struct s_ocp_qp *ocp_qp, struct s_ocp_qp *part_dense_qp, struct s_part_cond_qp_arg *cond_arg, struct s_part_cond_qp_ws *cond_ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_PART_COND_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_part_cond_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_s_part_cond_qcqp.h new file mode 100644 index 0000000000..311f7000bf --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_part_cond_qcqp.h @@ -0,0 +1,107 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_PART_COND_QCQP_H_ +#define HPIPM_S_PART_COND_QCQP_H_ + + + +#include +#include + +#include "hpipm_s_cond_qcqp.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_part_cond_qcqp_arg + { + struct s_cond_qcqp_arg *cond_arg; + int N2; + hpipm_size_t memsize; + }; + + + +struct s_part_cond_qcqp_ws + { + struct s_cond_qcqp_ws *cond_ws; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_part_cond_qcqp_arg_memsize(int N2); +// +void s_part_cond_qcqp_arg_create(int N2, struct s_part_cond_qcqp_arg *cond_arg, void *mem); +// +void s_part_cond_qcqp_arg_set_default(struct s_part_cond_qcqp_arg *cond_arg); +// set riccati-like algorithm: 0 classical, 1 squre-root +void s_part_cond_qcqp_arg_set_ric_alg(int ric_alg, struct s_part_cond_qcqp_arg *cond_arg); + +// +void s_part_cond_qcqp_compute_block_size(int N, int N2, int *block_size); +// +void s_part_cond_qcqp_compute_dim(struct s_ocp_qcqp_dim *ocp_dim, int *block_size, struct s_ocp_qcqp_dim *part_dense_dim); +// +hpipm_size_t s_part_cond_qcqp_ws_memsize(struct s_ocp_qcqp_dim *ocp_dim, int *block_size, struct s_ocp_qcqp_dim *part_dense_dim, struct s_part_cond_qcqp_arg *cond_arg); +// +void s_part_cond_qcqp_ws_create(struct s_ocp_qcqp_dim *ocp_dim, int *block_size, struct s_ocp_qcqp_dim *part_dense_dim, struct s_part_cond_qcqp_arg *cond_arg, struct s_part_cond_qcqp_ws *cond_ws, void *mem); +// +void s_part_cond_qcqp_cond(struct s_ocp_qcqp *ocp_qp, struct s_ocp_qcqp *part_dense_qp, struct s_part_cond_qcqp_arg *cond_arg, struct s_part_cond_qcqp_ws *cond_ws); +// +void s_part_cond_qcqp_cond_lhs(struct s_ocp_qcqp *ocp_qp, struct s_ocp_qcqp *part_dense_qp, struct s_part_cond_qcqp_arg *cond_arg, struct s_part_cond_qcqp_ws *cond_ws); +// +void s_part_cond_qcqp_cond_rhs(struct s_ocp_qcqp *ocp_qp, struct s_ocp_qcqp *part_dense_qp, struct s_part_cond_qcqp_arg *cond_arg, struct s_part_cond_qcqp_ws *cond_ws); +// +void s_part_cond_qcqp_expand_sol(struct s_ocp_qcqp *ocp_qp, struct s_ocp_qcqp *part_dense_qp, struct s_ocp_qcqp_sol *part_dense_qp_sol, struct s_ocp_qcqp_sol *ocp_qp_sol, struct s_part_cond_qcqp_arg *cond_arg, struct s_part_cond_qcqp_ws *cond_ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_D_PART_COND_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_sim_erk.h b/third_party/acados/include/hpipm/include/hpipm_s_sim_erk.h new file mode 100644 index 0000000000..1a05ad1a28 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_sim_erk.h @@ -0,0 +1,121 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_SIM_ERK_H_ +#define HPIPM_S_SIM_ERK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct s_sim_erk_arg + { + struct s_sim_rk_data *rk_data; // integrator data + float h; // step size + int steps; // number of steps +// int for_sens; // compute adjoint sensitivities +// int adj_sens; // compute adjoint sensitivities + hpipm_size_t memsize; + }; + + + +struct s_sim_erk_ws + { + void (*ode)(int t, float *x, float *p, void *ode_args, float *xdot); // function pointer to ode + void (*vde_for)(int t, float *x, float *p, void *ode_args, float *xdot); // function pointer to forward vde + void (*vde_adj)(int t, float *adj_in, void *ode_args, float *adj_out); // function pointer to adjoint vde + void *ode_args; // pointer to ode args + struct s_sim_erk_arg *erk_arg; // erk arg + float *K; // internal variables + float *x_for; // states and forward sensitivities + float *x_traj; // states at all steps + float *l; // adjoint sensitivities + float *p; // parameter + float *x_tmp; // temporary states and forward sensitivities + float *adj_in; + float *adj_tmp; + int nx; // number of states + int np; // number of parameters + int nf; // number of forward sensitivities + int na; // number of adjoint sensitivities + int nf_max; // max number of forward sensitivities + int na_max; // max number of adjoint sensitivities + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_sim_erk_arg_memsize(); +// +void s_sim_erk_arg_create(struct s_sim_erk_arg *erk_arg, void *mem); +// +void s_sim_erk_arg_set_all(struct s_sim_rk_data *rk_data, float h, int steps, struct s_sim_erk_arg *erk_arg); + +// +hpipm_size_t s_sim_erk_ws_memsize(struct s_sim_erk_arg *erk_arg, int nx, int np, int nf_max, int na_max); +// +void s_sim_erk_ws_create(struct s_sim_erk_arg *erk_arg, int nx, int np, int nf_max, int na_max, struct s_sim_erk_ws *work, void *memory); +// +void s_sim_erk_ws_set_all(int nf, int na, float *x, float *fs, float *bs, float *p, void (*ode)(int t, float *x, float *p, void *ode_args, float *xdot), void (*vde_for)(int t, float *x, float *p, void *ode_args, float *xdot), void (*vde_adj)(int t, float *adj_in, void *ode_args, float *adj_out), void *ode_args, struct s_sim_erk_ws *work); +// number of directions for forward sensitivities +void s_sim_erk_ws_set_nf(int *nf, struct s_sim_erk_ws *work); +// parameters (e.g. inputs) +void s_sim_erk_ws_set_p(float *p, struct s_sim_erk_ws *work); +// state +void s_sim_erk_ws_set_x(float *x, struct s_sim_erk_ws *work); +// forward sensitivities +void s_sim_erk_ws_set_fs(float *fs, struct s_sim_erk_ws *work); +// ode funtion +void s_sim_erk_ws_set_ode(void (*ode)(int t, float *x, float *p, void *ode_args, float *xdot), struct s_sim_erk_ws *work); +// forward vde function +void s_sim_erk_ws_set_vde_for(void (*ode)(int t, float *x, float *p, void *ode_args, float *xdot), struct s_sim_erk_ws *work); +// ode_args, passed straight to the ode/vde_for/vde_adj functions +void s_sim_erk_ws_set_ode_args(void *ode_args, struct s_sim_erk_ws *work); +// state +void s_sim_erk_ws_get_x(struct s_sim_erk_ws *work, float *x); +// forward sensitivities +void s_sim_erk_ws_get_fs(struct s_sim_erk_ws *work, float *fs); +// +void s_sim_erk_solve(struct s_sim_erk_arg *arg, struct s_sim_erk_ws *work); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_D_SIM_ERK_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_sim_rk.h b/third_party/acados/include/hpipm/include/hpipm_s_sim_rk.h new file mode 100644 index 0000000000..53acd71498 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_sim_rk.h @@ -0,0 +1,72 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_SIM_RK_H_ +#define HPIPM_S_SIM_RK_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct s_sim_rk_data + { + float *A_rk; // A in butcher tableau + float *B_rk; // b in butcher tableau + float *C_rk; // c in butcher tableau + int expl; // erk vs irk + int ns; // number of stages + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_sim_rk_data_memsize(int ns); +// +void s_sim_rk_data_create(int ns, struct s_sim_rk_data *rk_data, void *memory); +// +void s_sim_rk_data_init_default(char *field, struct s_sim_rk_data *rk_data); +// +void s_sim_rk_data_set_all(int expl, float *A_rk, float *B_rk, float *C_rk, struct s_sim_rk_data *rk_data); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_S_SIM_RK_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp.h new file mode 100644 index 0000000000..450e992624 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp.h @@ -0,0 +1,213 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QCQP_H_ +#define HPIPM_S_TREE_OCP_QCQP_H_ + + + +#include +#include + +#include "hpipm_s_tree_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qcqp + { + struct s_tree_ocp_qcqp_dim *dim; + struct blasfeo_smat *BAbt; // Nn-1 + struct blasfeo_smat *RSQrq; // Nn + struct blasfeo_smat *DCt; // Nn + struct blasfeo_smat **Hq; // Nn + struct blasfeo_svec *b; // Nn-1 + struct blasfeo_svec *rqz; // Nn + struct blasfeo_svec *d; // Nn + struct blasfeo_svec *d_mask; // Nn + struct blasfeo_svec *m; // Nn + struct blasfeo_svec *Z; // Nn + int **idxb; // indices of box constrained variables within [u; x] // Nn + int **idxs_rev; // index of soft constraints + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_tree_ocp_qcqp_memsize(struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_create(struct s_tree_ocp_qcqp_dim *dim, struct s_tree_ocp_qcqp *qp, void *memory); +// +void s_tree_ocp_qcqp_set_all(float **A, float **B, float **b, float **Q, float **S, float **R, float **q, float **r, int **idxb, float **d_lb, float **d_ub, float **C, float **D, float **d_lg, float **d_ug, float **Zl, float **Zu, float **zl, float **zu, int **idxs, float **d_ls, float **d_us, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set(char *field_name, int node_edge, void *value, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_A(int edge, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_B(int edge, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_b(int edge, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Q(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_S(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_R(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_q(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_r(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lb(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lb_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ub(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ub_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lbx(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lbx_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ubx(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ubx_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lbu(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lbu_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ubu(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ubu_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_idxb(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_idxbx(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Jbx(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_idxbu(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Jbu(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_C(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_D(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lg(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lg_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ug(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_ug_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Qq(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Sq(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Rq(int node, float *mat, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_qq(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_rq(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_uq(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_uq_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Zl(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Zu(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_zl(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_zu(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lls(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lls_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lus(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_lus_mask(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_idxs(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_idxs_rev(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Jsbu(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Jsbx(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Jsg(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_set_Jsq(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_idxe(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_idxbxe(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_idxbue(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_idxge(int node, int *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_Jbxe(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_Jbue(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_Jge(int node, float *vec, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_set_diag_H_flag(int node, int *value, struct s_tree_ocp_qcqp *qp); + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_TREE_OCP_QCQP_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_dim.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_dim.h new file mode 100644 index 0000000000..7a49d51995 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_dim.h @@ -0,0 +1,118 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QCQP_DIM_H_ +#define HPIPM_S_TREE_OCP_QCQP_DIM_H_ + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qcqp_dim + { + struct s_tree_ocp_qp_dim *qp_dim; // dim of qp approximation + struct tree *ttree; // tree describing node conndection + int *nx; // number of states // Nn + int *nu; // number of inputs // Nn + int *nb; // number of box constraints // Nn + int *nbx; // number of state box constraints // Nn + int *nbu; // number of input box constraints // Nn + int *ng; // number of general constraints // Nn + int *nq; // number of (upper) quadratic constraints + int *ns; // number of soft constraints // Nn + int *nsbx; // number of soft state box constraints + int *nsbu; // number of soft input box constraints + int *nsg; // number of soft general constraints + int *nsq; // number of (upper) soft quadratic constraints + int Nn; // number of nodes + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_tree_ocp_qcqp_dim_strsize(); +// +hpipm_size_t s_tree_ocp_qcqp_dim_memsize(int Nn); +// +void s_tree_ocp_qcqp_dim_create(int Nn, struct s_tree_ocp_qcqp_dim *qp_dim, void *memory); +// +void s_tree_ocp_qcqp_dim_set_tree(struct tree *ttree, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set(char *field, int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nx(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nu(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nbx(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nbu(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_ng(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nq(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_ns(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nsbx(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nsbu(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nsg(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_dim_set_nsq(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +//void s_tree_ocp_qcqp_dim_set_nbxe(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +//void s_tree_ocp_qcqp_dim_set_nbue(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); +// +//void s_tree_ocp_qcqp_dim_set_nge(int stage, int value, struct s_tree_ocp_qcqp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_TREE_OCP_QCQP_DIM_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_ipm.h new file mode 100644 index 0000000000..69d65914c5 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_ipm.h @@ -0,0 +1,192 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QCQP_IPM_H_ +#define HPIPM_S_TREE_OCP_QCQP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qcqp_ipm_arg + { + struct s_tree_ocp_qp_ipm_arg *qp_arg; + float mu0; // initial value for complementarity slackness + float alpha_min; // exit cond on step length + float res_g_max; // exit cond on inf norm of residuals + float res_b_max; // exit cond on inf norm of residuals + float res_d_max; // exit cond on inf norm of residuals + float res_m_max; // exit cond on inf norm of residuals + float reg_prim; // reg of primal hessian + float lam_min; // min value in lam vector + float t_min; // min value in t vector + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol +// int square_root_alg; // 0 classical Riccati, 1 square-root Riccati + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq (for square_root_alg==1) + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution of equality constraints (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol_eq==1) +// int comp_res_pred; // compute residuals of prediction + int split_step; // use different step for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct s_tree_ocp_qcqp_ipm_ws + { + struct s_tree_ocp_qp_ipm_ws *qp_ws; + struct s_tree_ocp_qp *qp; + struct s_tree_ocp_qp_sol *qp_sol; + struct s_tree_ocp_qcqp_res_ws *qcqp_res_ws; + struct s_tree_ocp_qcqp_res *qcqp_res; + struct blasfeo_svec *tmp_nuxM; + int iter; // iteration number + int status; + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_tree_ocp_qcqp_ipm_arg_strsize(); +// +hpipm_size_t s_tree_ocp_qcqp_ipm_arg_memsize(struct s_tree_ocp_qcqp_dim *ocp_dim); +// +void s_tree_ocp_qcqp_ipm_arg_create(struct s_tree_ocp_qcqp_dim *ocp_dim, struct s_tree_ocp_qcqp_ipm_arg *arg, void *mem); +// +void s_tree_ocp_qcqp_ipm_arg_set_default(enum hpipm_mode mode, struct s_tree_ocp_qcqp_ipm_arg *arg); +// +void s_tree_ocp_qcqp_ipm_arg_set(char *field, void *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set maximum number of iterations +void s_tree_ocp_qcqp_ipm_arg_set_iter_max(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set minimum step lenght +void s_tree_ocp_qcqp_ipm_arg_set_alpha_min(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set initial value of barrier parameter +void s_tree_ocp_qcqp_ipm_arg_set_mu0(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on stationarity condition +void s_tree_ocp_qcqp_ipm_arg_set_tol_stat(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on equality constr +void s_tree_ocp_qcqp_ipm_arg_set_tol_eq(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on inequality constr +void s_tree_ocp_qcqp_ipm_arg_set_tol_ineq(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set exit tolerance on complementarity condition +void s_tree_ocp_qcqp_ipm_arg_set_tol_comp(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set regularization of primal variables +void s_tree_ocp_qcqp_ipm_arg_set_reg_prim(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set warm start: 0 no warm start, 1 primal var +void s_tree_ocp_qcqp_ipm_arg_set_warm_start(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// Mehrotra's predictor-corrector IPM algorithm: 0 no predictor-corrector, 1 use predictor-corrector +void s_tree_ocp_qcqp_ipm_arg_set_pred_corr(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// conditional predictor-corrector: 0 no conditinal predictor-corrector, 1 conditional predictor-corrector +void s_tree_ocp_qcqp_ipm_arg_set_cond_pred_corr(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// set riccati algorithm: 0 classic, 1 square-root +//void s_tree_ocp_qcqp_ipm_arg_set_ric_alg(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// compute residuals after solution +void s_tree_ocp_qcqp_ipm_arg_set_comp_res_exit(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// compute residuals of prediction +//void s_tree_ocp_qcqp_ipm_arg_set_comp_res_pred(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// min value of lam in the solution +void s_tree_ocp_qcqp_ipm_arg_set_lam_min(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// min value of t in the solution +void s_tree_ocp_qcqp_ipm_arg_set_t_min(float *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// use different step for primal and dual variables +void s_tree_ocp_qcqp_ipm_arg_set_split_step(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); +// clip t and lam: 0 no, 1 in Gamma computation, 2 in solution +void s_tree_ocp_qcqp_ipm_arg_set_t_lam_min(int *value, struct s_tree_ocp_qcqp_ipm_arg *arg); + +// +hpipm_size_t s_tree_ocp_qcqp_ipm_ws_strsize(); +// +hpipm_size_t s_tree_ocp_qcqp_ipm_ws_memsize(struct s_tree_ocp_qcqp_dim *ocp_dim, struct s_tree_ocp_qcqp_ipm_arg *arg); +// +void s_tree_ocp_qcqp_ipm_ws_create(struct s_tree_ocp_qcqp_dim *ocp_dim, struct s_tree_ocp_qcqp_ipm_arg *arg, struct s_tree_ocp_qcqp_ipm_ws *ws, void *mem); +// +void s_tree_ocp_qcqp_ipm_get(char *field, struct s_tree_ocp_qcqp_ipm_ws *ws, void *value); +// +void s_tree_ocp_qcqp_ipm_get_status(struct s_tree_ocp_qcqp_ipm_ws *ws, int *status); +// +void s_tree_ocp_qcqp_ipm_get_iter(struct s_tree_ocp_qcqp_ipm_ws *ws, int *iter); +// +void s_tree_ocp_qcqp_ipm_get_max_res_stat(struct s_tree_ocp_qcqp_ipm_ws *ws, float *res_stat); +// +void s_tree_ocp_qcqp_ipm_get_max_res_eq(struct s_tree_ocp_qcqp_ipm_ws *ws, float *res_eq); +// +void s_tree_ocp_qcqp_ipm_get_max_res_ineq(struct s_tree_ocp_qcqp_ipm_ws *ws, float *res_ineq); +// +void s_tree_ocp_qcqp_ipm_get_max_res_comp(struct s_tree_ocp_qcqp_ipm_ws *ws, float *res_comp); +// +void s_tree_ocp_qcqp_ipm_get_stat(struct s_tree_ocp_qcqp_ipm_ws *ws, float **stat); +// +void s_tree_ocp_qcqp_ipm_get_stat_m(struct s_tree_ocp_qcqp_ipm_ws *ws, int *stat_m); +// +void s_tree_ocp_qcqp_init_var(struct s_tree_ocp_qcqp *qp, struct s_tree_ocp_qcqp_sol *qp_sol, struct s_tree_ocp_qcqp_ipm_arg *arg, struct s_tree_ocp_qcqp_ipm_ws *ws); +// +void s_tree_ocp_qcqp_ipm_solve(struct s_tree_ocp_qcqp *qp, struct s_tree_ocp_qcqp_sol *qp_sol, struct s_tree_ocp_qcqp_ipm_arg *arg, struct s_tree_ocp_qcqp_ipm_ws *ws); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_TREE_OCP_QCQP_IPM_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_res.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_res.h new file mode 100644 index 0000000000..d0d84a6f23 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_res.h @@ -0,0 +1,109 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QCQP_RES_H_ +#define HPIPM_S_TREE_OCP_QCQP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qcqp_res + { + struct s_tree_ocp_qcqp_dim *dim; + struct blasfeo_svec *res_g; // q-residuals + struct blasfeo_svec *res_b; // b-residuals + struct blasfeo_svec *res_d; // d-residuals + struct blasfeo_svec *res_m; // m-residuals + float res_max[4]; // max of residuals + float res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct s_tree_ocp_qcqp_res_ws + { + struct blasfeo_svec *tmp_nuxM; // work space of size nuM+nxM + struct blasfeo_svec *tmp_nbgqM; // work space of size nbM+ngM+nqM + struct blasfeo_svec *tmp_nsM; // work space of size nsM + struct blasfeo_svec *q_fun; // value for evaluation of quadr constr + struct blasfeo_svec *q_adj; // value for adjoint of quadr constr + int use_q_fun; // reuse cached value for evaluation of quadr constr + int use_q_adj; // reuse cached value for adjoint of quadr constr + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_tree_ocp_qcqp_res_memsize(struct s_tree_ocp_qcqp_dim *ocp_dim); +// +void s_tree_ocp_qcqp_res_create(struct s_tree_ocp_qcqp_dim *ocp_dim, struct s_tree_ocp_qcqp_res *res, void *mem); +// +hpipm_size_t s_tree_ocp_qcqp_res_ws_memsize(struct s_tree_ocp_qcqp_dim *ocp_dim); +// +void s_tree_ocp_qcqp_res_ws_create(struct s_tree_ocp_qcqp_dim *ocp_dim, struct s_tree_ocp_qcqp_res_ws *ws, void *mem); +// +void s_tree_ocp_qcqp_res_compute(struct s_tree_ocp_qcqp *qp, struct s_tree_ocp_qcqp_sol *qp_sol, struct s_tree_ocp_qcqp_res *res, struct s_tree_ocp_qcqp_res_ws *ws); +// +void s_tree_ocp_qcqp_res_compute_inf_norm(struct s_tree_ocp_qcqp_res *res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_TREE_OCP_QCQP_RES_H_ + + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_sol.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_sol.h new file mode 100644 index 0000000000..47f038c6b3 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_sol.h @@ -0,0 +1,97 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QCQP_SOL_H_ +#define HPIPM_S_TREE_OCP_QCQP_SOL_H_ + + + +#include +#include + +#include "hpipm_s_tree_ocp_qcqp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct s_tree_ocp_qcqp_sol + { + struct s_tree_ocp_qcqp_dim *dim; + struct blasfeo_svec *ux; + struct blasfeo_svec *pi; + struct blasfeo_svec *lam; + struct blasfeo_svec *t; + void *misc; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_tree_ocp_qcqp_sol_memsize(struct s_tree_ocp_qcqp_dim *dim); +// +void s_tree_ocp_qcqp_sol_create(struct s_tree_ocp_qcqp_dim *dim, struct s_tree_ocp_qcqp_sol *qp_sol, void *memory); +// +void s_tree_ocp_qcqp_sol_get_u(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_x(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_sl(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_su(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_pi(int edge, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_lam_lb(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_lam_ub(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_lam_lg(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qcqp_sol_get_lam_ug(int node, struct s_tree_ocp_qcqp_sol *qp_sol, float *vec); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_TREE_OCP_QCQP_SOL_H_ + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_utils.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_utils.h new file mode 100644 index 0000000000..79528de1ce --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qcqp_utils.h @@ -0,0 +1,85 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QCQP_UTILS_H_ +#define HPIPM_S_TREE_OCP_QCQP_UTILS_H_ + + + +#include +#include + +#include "hpipm_s_tree_ocp_qcqp_dim.h" +#include "hpipm_s_tree_ocp_qcqp.h" +#include "hpipm_s_tree_ocp_qcqp_sol.h" +#include "hpipm_s_tree_ocp_qcqp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_tree_ocp_qcqp_dim_print(struct s_tree_ocp_qcqp_dim *qp_dim); +// +//void s_tree_ocp_qcqp_dim_codegen(char *file_name, char *mode, struct s_tree_ocp_qcqp_dim *qp_dim); +// +void s_tree_ocp_qcqp_print(struct s_tree_ocp_qcqp_dim *qp_dim, struct s_tree_ocp_qcqp *qp); +// +//void s_tree_ocp_qcqp_codegen(char *file_name, char *mode, struct s_tree_ocp_qcqp_dim *qp_dim, struct s_tree_ocp_qcqp *qp); +// +void s_tree_ocp_qcqp_sol_print(struct s_tree_ocp_qcqp_dim *qp_dim, struct s_tree_ocp_qcqp_sol *ocp_qcqp_sol); +// +void s_tree_ocp_qcqp_ipm_arg_print(struct s_tree_ocp_qcqp_dim *qp_dim, struct s_tree_ocp_qcqp_ipm_arg *arg); +// +//void s_tree_ocp_qcqp_ipm_arg_codegen(char *file_name, char *mode, struct s_tree_ocp_qcqp_dim *qp_dim, struct s_tree_ocp_qcqp_ipm_arg *arg); +// +void s_tree_ocp_qcqp_res_print(struct s_tree_ocp_qcqp_dim *qp_dim, struct s_tree_ocp_qcqp_res *ocp_qcqp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_TREE_OCP_QCQP_UTILS_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp.h new file mode 100644 index 0000000000..722b930b9a --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp.h @@ -0,0 +1,196 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QP_H_ +#define HPIPM_S_TREE_OCP_QP_H_ + + + +#include +#include + +#include "hpipm_s_tree_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qp + { + struct s_tree_ocp_qp_dim *dim; + struct blasfeo_smat *BAbt; // Nn-1 + struct blasfeo_smat *RSQrq; // Nn + struct blasfeo_smat *DCt; // Nn + struct blasfeo_svec *b; // Nn-1 + struct blasfeo_svec *rqz; // Nn + struct blasfeo_svec *d; // Nn + struct blasfeo_svec *d_mask; // Nn + struct blasfeo_svec *m; // Nn + struct blasfeo_svec *Z; // Nn + int **idxb; // indices of box constrained variables within [u; x] // Nn +// int **idxs; // index of soft constraints + int **idxs_rev; // index of soft constraints + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_tree_ocp_qp_memsize(struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_create(struct s_tree_ocp_qp_dim *dim, struct s_tree_ocp_qp *qp, void *memory); +// +void s_tree_ocp_qp_set_all(float **A, float **B, float **b, float **Q, float **S, float **R, float **q, float **r, int **idxb, float **d_lb, float **d_ub, float **C, float **D, float **d_lg, float **d_ug, float **Zl, float **Zu, float **zl, float **zu, int **idxs, float **d_ls, float **d_us, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set(char *field_name, int node_edge, void *value, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_A(int edge, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_B(int edge, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_b(int edge, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Q(int node, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_S(int node, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_R(int node, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_q(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_r(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lb(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lb_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ub(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ub_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lbx(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lbx_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ubx(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ubx_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lbu(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lbu_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ubu(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ubu_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_idxb(int node, int *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_idxbx(int node, int *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Jbx(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_idxbu(int node, int *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Jbu(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_C(int node, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_D(int node, float *mat, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lg(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lg_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ug(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_ug_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Zl(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Zu(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_zl(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_zu(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lls(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lls_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lus(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_lus_mask(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_idxs(int node, int *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_idxs_rev(int node, int *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Jsbu(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Jsbx(int node, float *vec, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_set_Jsg(int node, float *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_idxe(int node, int *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_idxbxe(int node, int *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_idxbue(int node, int *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_idxge(int node, int *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_Jbxe(int node, float *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_Jbue(int node, float *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_Jge(int node, float *vec, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_set_diag_H_flag(int node, int *value, struct s_tree_ocp_qp *qp); + + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_TREE_OCP_QP_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_dim.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_dim.h new file mode 100644 index 0000000000..90df57182b --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_dim.h @@ -0,0 +1,111 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QP_DIM_H_ +#define HPIPM_S_TREE_OCP_QP_DIM_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qp_dim + { + struct tree *ttree; // tree describing node conndection + int *nx; // number of states // Nn + int *nu; // number of inputs // Nn + int *nb; // number of box constraints // Nn + int *nbx; // number of state box constraints // Nn + int *nbu; // number of input box constraints // Nn + int *ng; // number of general constraints // Nn + int *ns; // number of soft constraints // Nn + int *nsbx; // number of soft state box constraints + int *nsbu; // number of soft input box constraints + int *nsg; // number of soft general constraints + int Nn; // number of nodes + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_tree_ocp_qp_dim_strsize(); +// +hpipm_size_t s_tree_ocp_qp_dim_memsize(int Nn); +// +void s_tree_ocp_qp_dim_create(int Nn, struct s_tree_ocp_qp_dim *qp_dim, void *memory); +// +void s_tree_ocp_qp_dim_set_all(struct tree *ttree, int *nx, int *nu, int *nbx, int *nbu, int *ng, int *nsbx, int *nsbu, int *nsg, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_tree(struct tree *ttree, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set(char *field, int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nx(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nu(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nbx(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nbu(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_ng(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_ns(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nsbx(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nsbu(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nsg(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nbxe(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nbue(int stage, int value, struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_dim_set_nge(int stage, int value, struct s_tree_ocp_qp_dim *dim); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_TREE_OCP_QP_DIM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_ipm.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_ipm.h new file mode 100644 index 0000000000..f8c26d3173 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_ipm.h @@ -0,0 +1,208 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + + +#ifndef HPIPM_S_TREE_OCP_QP_IPM_H_ +#define HPIPM_S_TREE_OCP_QP_IPM_H_ + + + +#include +#include + +#include +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qp_ipm_arg + { + float mu0; // initial value for duality measure + float alpha_min; // exit cond on step length + float res_g_max; // exit cond on inf norm of residuals + float res_b_max; // exit cond on inf norm of residuals + float res_d_max; // exit cond on inf norm of residuals + float res_m_max; // exit cond on inf norm of residuals + float reg_prim; // reg of primal hessian + float lam_min; // min value in lam vector + float t_min; // min value in t vector + float tau_min; // min value of barrier parameter + int iter_max; // exit cond in iter number + int stat_max; // iterations saved in stat + int stat_m; // number of recorded stat per IPM iter + int pred_corr; // use Mehrotra's predictor-corrector IPM algirthm + int cond_pred_corr; // conditional Mehrotra's predictor-corrector + int itref_pred_max; // max number of iterative refinement steps for predictor step + int itref_corr_max; // max number of iterative refinement steps for corrector step + int warm_start; // 0 no warm start, 1 warm start primal sol, 2 warm start primal and dual sol + int lq_fact; // 0 syrk+potrf, 1 mix, 2 lq + int abs_form; // absolute IPM formulation + int comp_dual_sol_eq; // dual solution (only for abs_form==1) + int comp_res_exit; // compute residuals on exit (only for abs_form==1 and comp_dual_sol==1) + int split_step; // use different steps for primal and dual variables + int t_lam_min; // clip t and lam: 0 no, 1 in Gamma computation, 2 in solution + int mode; + hpipm_size_t memsize; + }; + + + +struct s_tree_ocp_qp_ipm_ws + { + struct s_core_qp_ipm_workspace *core_workspace; + struct s_tree_ocp_qp_res_ws *res_workspace; + struct s_tree_ocp_qp_sol *sol_step; + struct s_tree_ocp_qp_sol *sol_itref; + struct s_tree_ocp_qp *qp_step; + struct s_tree_ocp_qp *qp_itref; + struct s_tree_ocp_qp_res *res_itref; + struct s_tree_ocp_qp_res *res; + struct blasfeo_svec *Gamma; // hessian update + struct blasfeo_svec *gamma; // hessian update + struct blasfeo_svec *tmp_nxM; // work space of size nxM + struct blasfeo_svec *tmp_nbgM; // work space of size nbgM + struct blasfeo_svec *tmp_nsM; // work space of size nsM + struct blasfeo_svec *Pb; // Pb + struct blasfeo_svec *Zs_inv; + struct blasfeo_smat *L; + struct blasfeo_smat *Lh; + struct blasfeo_smat *AL; + struct blasfeo_smat *lq0; + struct blasfeo_svec *tmp_m; + float *stat; // convergence statistics + int *use_hess_fact; + void *lq_work0; + float qp_res[4]; // infinity norm of residuals + int iter; // iteration number + int stat_max; // iterations saved in stat + int stat_m; // number of recorded stat per IPM iter + int use_Pb; + int status; // solver status + int lq_fact; // cache from arg + int mask_constr; // use constr mask + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_tree_ocp_qp_ipm_arg_memsize(struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_ipm_arg_create(struct s_tree_ocp_qp_dim *dim, struct s_tree_ocp_qp_ipm_arg *arg, void *mem); +// +void s_tree_ocp_qp_ipm_arg_set_default(enum hpipm_mode mode, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_iter_max(int *iter_max, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_alpha_min(float *alpha_min, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_mu0(float *mu0, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_tol_stat(float *tol_stat, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_tol_eq(float *tol_eq, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_tol_ineq(float *tol_ineq, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_tol_comp(float *tol_comp, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_reg_prim(float *reg, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_warm_start(int *warm_start, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_pred_corr(int *pred_corr, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_cond_pred_corr(int *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_comp_dual_sol_eq(int *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_comp_res_exit(int *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_lam_min(float *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_t_min(float *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_tau_min(float *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_split_step(int *value, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_arg_set_t_lam_min(int *value, struct s_tree_ocp_qp_ipm_arg *arg); + +// +hpipm_size_t s_tree_ocp_qp_ipm_ws_memsize(struct s_tree_ocp_qp_dim *dim, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_ipm_ws_create(struct s_tree_ocp_qp_dim *dim, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws, void *mem); +// +void s_tree_ocp_qp_ipm_get_status(struct s_tree_ocp_qp_ipm_ws *ws, int *status); +// +void s_tree_ocp_qp_ipm_get_iter(struct s_tree_ocp_qp_ipm_ws *ws, int *iter); +// +void s_tree_ocp_qp_ipm_get_max_res_stat(struct s_tree_ocp_qp_ipm_ws *ws, float *res_stat); +// +void s_tree_ocp_qp_ipm_get_max_res_eq(struct s_tree_ocp_qp_ipm_ws *ws, float *res_eq); +// +void s_tree_ocp_qp_ipm_get_max_res_ineq(struct s_tree_ocp_qp_ipm_ws *ws, float *res_ineq); +// +void s_tree_ocp_qp_ipm_get_max_res_comp(struct s_tree_ocp_qp_ipm_ws *ws, float *res_comp); +// +void s_tree_ocp_qp_ipm_get_stat(struct s_tree_ocp_qp_ipm_ws *ws, float **stat); +// +void s_tree_ocp_qp_ipm_get_stat_m(struct s_tree_ocp_qp_ipm_ws *ws, int *stat_m); +// +void s_tree_ocp_qp_init_var(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); +// +void s_tree_ocp_qp_ipm_abs_step(int kk, struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); +// +void s_tree_ocp_qp_ipm_delta_step(int kk, struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); +// +void s_tree_ocp_qp_ipm_solve(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_TREE_OCP_QP_IPM_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_kkt.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_kkt.h new file mode 100644 index 0000000000..bcf7354783 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_kkt.h @@ -0,0 +1,54 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +// +void s_tree_ocp_qp_fact_solve_kkt_unconstr(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); +// +void s_tree_ocp_qp_fact_solve_kkt_step(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); +// +void s_tree_ocp_qp_fact_lq_solve_kkt_step(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); +// +void s_tree_ocp_qp_solve_kkt_step(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_ipm_arg *arg, struct s_tree_ocp_qp_ipm_ws *ws); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_res.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_res.h new file mode 100644 index 0000000000..5c6797204f --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_res.h @@ -0,0 +1,107 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QP_RES_H_ +#define HPIPM_S_TREE_OCP_QP_RES_H_ + + + +#include +#include + +#include +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct s_tree_ocp_qp_res + { + struct s_tree_ocp_qp_dim *dim; + struct blasfeo_svec *res_g; // q-residuals + struct blasfeo_svec *res_b; // b-residuals + struct blasfeo_svec *res_d; // d-residuals + struct blasfeo_svec *res_m; // m-residuals + float res_max[4]; // max of residuals + float res_mu; // mu-residual + hpipm_size_t memsize; + }; + + + +struct s_tree_ocp_qp_res_ws + { + struct blasfeo_svec *tmp_nbgM; // work space of size nbM+ngM + struct blasfeo_svec *tmp_nsM; // work space of size nsM + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t s_tree_ocp_qp_res_memsize(struct s_tree_ocp_qp_dim *ocp_dim); +// +void s_tree_ocp_qp_res_create(struct s_tree_ocp_qp_dim *ocp_dim, struct s_tree_ocp_qp_res *res, void *mem); +// +hpipm_size_t s_tree_ocp_qp_res_ws_memsize(struct s_tree_ocp_qp_dim *ocp_dim); +// +void s_tree_ocp_qp_res_ws_create(struct s_tree_ocp_qp_dim *ocp_dim, struct s_tree_ocp_qp_res_ws *ws, void *mem); +// +void s_tree_ocp_qp_res_get_all(struct s_tree_ocp_qp_res *res, float **res_r, float **res_q, float **res_ls, float **res_us, float **res_b, float **res_d_lb, float **res_d_ub, float **res_d_lg, float **res_d_ug, float **res_d_ls, float **res_d_us, float **res_m_lb, float **res_m_ub, float **res_m_lg, float **res_m_ug, float **res_m_ls, float **res_m_us); +// +void s_tree_ocp_qp_res_compute(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_res *res, struct s_tree_ocp_qp_res_ws *ws); +// +void s_tree_ocp_qp_res_compute_lin(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, struct s_tree_ocp_qp_sol *qp_step, struct s_tree_ocp_qp_res *res, struct s_tree_ocp_qp_res_ws *ws); +// +void s_tree_ocp_qp_res_compute_inf_norm(struct s_tree_ocp_qp_res *res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_S_TREE_OCP_QP_RES_H_ + + + diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_sol.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_sol.h new file mode 100644 index 0000000000..71e887675b --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_sol.h @@ -0,0 +1,98 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QP_SOL_H_ +#define HPIPM_S_TREE_OCP_QP_SOL_H_ + + + +#include +#include + +#include "hpipm_s_tree_ocp_qp_dim.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +struct s_tree_ocp_qp_sol + { + struct s_tree_ocp_qp_dim *dim; + struct blasfeo_svec *ux; + struct blasfeo_svec *pi; + struct blasfeo_svec *lam; + struct blasfeo_svec *t; + void *misc; + hpipm_size_t memsize; // memory size in bytes + }; + + + +// +hpipm_size_t s_tree_ocp_qp_sol_memsize(struct s_tree_ocp_qp_dim *dim); +// +void s_tree_ocp_qp_sol_create(struct s_tree_ocp_qp_dim *dim, struct s_tree_ocp_qp_sol *qp_sol, void *memory); +// +void s_tree_ocp_qp_sol_get_all(struct s_tree_ocp_qp *qp, struct s_tree_ocp_qp_sol *qp_sol, float **u, float **x, float **ls, float **us, float **pi, float **lam_lb, float **lam_ub, float **lam_lg, float **lam_ug, float **lam_ls, float **lam_us); +// +void s_tree_ocp_qp_sol_get_u(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_x(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_sl(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_su(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_pi(int edge, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_lam_lb(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_lam_ub(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_lam_lg(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); +// +void s_tree_ocp_qp_sol_get_lam_ug(int node, struct s_tree_ocp_qp_sol *qp_sol, float *vec); + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // HPIPM_S_TREE_OCP_QP_SOL_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_utils.h b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_utils.h new file mode 100644 index 0000000000..ec1747568f --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_s_tree_ocp_qp_utils.h @@ -0,0 +1,84 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_S_TREE_OCP_QP_UTILS_H_ +#define HPIPM_S_TREE_OCP_QP_UTILS_H_ + + + +#include +#include + +#include "hpipm_s_tree_ocp_qp_dim.h" +#include "hpipm_s_tree_ocp_qp.h" +#include "hpipm_s_tree_ocp_qp_sol.h" +#include "hpipm_s_tree_ocp_qp_ipm.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +void s_tree_ocp_qp_dim_print(struct s_tree_ocp_qp_dim *qp_dim); +// +//void s_tree_ocp_qp_dim_codegen(char *file_name, char *mode, struct s_tree_ocp_qp_dim *qp_dim); +// +void s_tree_ocp_qp_print(struct s_tree_ocp_qp_dim *qp_dim, struct s_tree_ocp_qp *qp); +// +//void s_tree_ocp_qp_codegen(char *file_name, char *mode, struct s_tree_ocp_qp_dim *qp_dim, struct s_tree_ocp_qp *qp); +// +void s_tree_ocp_qp_sol_print(struct s_tree_ocp_qp_dim *qp_dim, struct s_tree_ocp_qp_sol *ocp_qp_sol); +// +void s_tree_ocp_qp_ipm_arg_print(struct s_tree_ocp_qp_dim *qp_dim, struct s_tree_ocp_qp_ipm_arg *arg); +// +//void s_tree_ocp_qp_ipm_arg_codegen(char *file_name, char *mode, struct s_tree_ocp_qp_dim *qp_dim, struct s_tree_ocp_qp_ipm_arg *arg); +// +void s_tree_ocp_qp_res_print(struct s_tree_ocp_qp_dim *qp_dim, struct s_tree_ocp_qp_res *ocp_qp_res); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + + +#endif // HPIPM_S_TREE_OCP_QP_UTILS_H_ + + diff --git a/third_party/acados/include/hpipm/include/hpipm_scenario_tree.h b/third_party/acados/include/hpipm/include/hpipm_scenario_tree.h new file mode 100644 index 0000000000..a3c77a670a --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_scenario_tree.h @@ -0,0 +1,70 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_SCENARIO_TREE_H_ +#define HPIPM_SCENARIO_TREE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct sctree + { + struct node *root; // pointer to root + int *kids; // pointer to array of kids + int Nn; // numer of nodes + int md; // number of realizations + int Nr; // robust horizion + int Nh; // control horizion + hpipm_size_t memsize; + }; + + + +// +hpipm_size_t sctree_memsize(int md, int Nr, int Nh); +// +void sctree_create(int md, int Nr, int Nh, struct sctree *st, void *memory); +// +void sctree_cast_to_tree(struct sctree *st, struct tree *tt); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_SCENARIO_TREE_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_timing.h b/third_party/acados/include/hpipm/include/hpipm_timing.h new file mode 100644 index 0000000000..bd0f2dbcb3 --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_timing.h @@ -0,0 +1,67 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + +#ifndef HPIPM_TIMING_H_ +#define HPIPM_TIMING_H_ + + + +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef blasfeo_timer hpipm_timer; + + + +// +void hpipm_tic(hpipm_timer *t); +// +double hpipm_toc(hpipm_timer *t); + + + +#ifdef __cplusplus +} // #extern "C" +#endif + + +#endif // HPIPM_TIMING_H_ diff --git a/third_party/acados/include/hpipm/include/hpipm_tree.h b/third_party/acados/include/hpipm/include/hpipm_tree.h new file mode 100644 index 0000000000..f9d69ecddd --- /dev/null +++ b/third_party/acados/include/hpipm/include/hpipm_tree.h @@ -0,0 +1,76 @@ +/************************************************************************************************** +* * +* This file is part of HPIPM. * +* * +* HPIPM -- High-Performance Interior Point Method. * +* Copyright (C) 2019 by Gianluca Frison. * +* Developed at IMTEK (University of Freiburg) under the supervision of Moritz Diehl. * +* All rights reserved. * +* * +* The 2-Clause BSD License * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, this * +* list of conditions and the following disclaimer. * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +* Author: Gianluca Frison, gianluca.frison (at) imtek.uni-freiburg.de * +* * +**************************************************************************************************/ + + +#ifndef HPIPM_TREE_H_ +#define HPIPM_TREE_H_ + +#include "hpipm_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +struct node + { + int *kids; // 64 bits + int idx; // 32 bits + int dad; // 32 bits + int nkids; // 32 bits + int stage; // 32 bits + int real; // 32 bits + int idxkid; // 32 bits // XXX needed ??? + // total 256 bits + }; + + + +struct tree + { + struct node *root; // pointer to root + int *kids; // pointer to array of kids + int Nn; // numer of nodes + hpipm_size_t memsize; + }; + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // HPIPM_TREE_H_ diff --git a/third_party/acados/include/qpOASES_e/Bounds.h b/third_party/acados/include/qpOASES_e/Bounds.h new file mode 100644 index 0000000000..4e41c1d163 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Bounds.h @@ -0,0 +1,543 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Bounds.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the Bounds class designed to manage working sets of + * bounds within a QProblem. + */ + + +#ifndef QPOASES_BOUNDS_H +#define QPOASES_BOUNDS_H + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Manages working sets of bounds (= box constraints). + * + * This class manages working sets of bounds (= box constraints) + * by storing index sets and other status information. + * + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + Indexlist *freee; /**< Index list of free variables. */ + Indexlist *fixed; /**< Index list of fixed variables. */ + + Indexlist *shiftedFreee; /**< Memory for shifting free variables. */ + Indexlist *shiftedFixed; /**< Memory for shifting fixed variables. */ + + Indexlist *rotatedFreee; /**< Memory for rotating free variables. */ + Indexlist *rotatedFixed; /**< Memory for rotating fixed variables. */ + + SubjectToType *type; /**< Type of bounds. */ + SubjectToStatus *status; /**< Status of bounds. */ + + SubjectToType *typeTmp; /**< Temp memory for type of bounds. */ + SubjectToStatus *statusTmp; /**< Temp memory for status of bounds. */ + + BooleanType noLower; /**< This flag indicates if there is no lower bound on any variable. */ + BooleanType noUpper; /**< This flag indicates if there is no upper bound on any variable. */ + + int n; /**< Total number of bounds. */ +} Bounds; + +int Bounds_calculateMemorySize( int n); + +char *Bounds_assignMemory(int n, Bounds **mem, void *raw_memory); + +Bounds *Bounds_createMemory( int n ); + +/** Constructor which takes the number of bounds. */ +void BoundsCON( Bounds* _THIS, + int _n /**< Number of bounds. */ + ); + +/** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ +void BoundsCPY( Bounds* FROM, + Bounds* TO + ); + + +/** Initialises object with given number of bounds. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ +returnValue Bounds_init( Bounds* _THIS, + int _n /**< Number of bounds. */ + ); + + +/** Initially adds number of a new (i.e. not yet in the list) bound to + * given index set. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS */ +returnValue Bounds_setupBound( Bounds* _THIS, + int number, /**< Number of new bound. */ + SubjectToStatus _status /**< Status of new bound. */ + ); + +/** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set of free bounds; the order depends on the SujectToType + * of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ +returnValue Bounds_setupAllFree( Bounds* _THIS + ); + +/** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set of fixed bounds (on their lower bounds); + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ +returnValue Bounds_setupAllLower( Bounds* _THIS + ); + +/** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set of fixed bounds (on their upper bounds); + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ +returnValue Bounds_setupAllUpper( Bounds* _THIS + ); + + +/** Moves index of a bound from index list of fixed to that of free bounds. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ +returnValue Bounds_moveFixedToFree( Bounds* _THIS, + int number /**< Number of bound to be freed. */ + ); + +/** Moves index of a bound from index list of free to that of fixed bounds. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ +returnValue Bounds_moveFreeToFixed( Bounds* _THIS, + int number, /**< Number of bound to be fixed. */ + SubjectToStatus _status /**< Status of bound to be fixed. */ + ); + +/** Flip fixed bound. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_BOUND_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ +returnValue Bounds_flipFixed( Bounds* _THIS, + int number + ); + +/** Swaps the indices of two free bounds within the index set. + * \return SUCCESSFUL_RETURN \n + RET_SWAPINDEX_FAILED */ +returnValue Bounds_swapFree( Bounds* _THIS, + int number1, /**< Number of first bound. */ + int number2 /**< Number of second bound. */ + ); + + +/** Returns number of variables. + * \return Number of variables. */ +static inline int Bounds_getNV( Bounds* _THIS + ); + +/** Returns number of implicitly fixed variables. + * \return Number of implicitly fixed variables. */ +static inline int Bounds_getNFV( Bounds* _THIS + ); + +/** Returns number of bounded (but possibly free) variables. + * \return Number of bounded (but possibly free) variables. */ +static inline int Bounds_getNBV( Bounds* _THIS + ); + +/** Returns number of unbounded variables. + * \return Number of unbounded variables. */ +static inline int Bounds_getNUV( Bounds* _THIS + ); + +/** Returns number of free variables. + * \return Number of free variables. */ +static inline int Bounds_getNFR( Bounds* _THIS + ); + +/** Returns number of fixed variables. + * \return Number of fixed variables. */ +static inline int Bounds_getNFX( Bounds* _THIS + ); + + +/** Returns a pointer to free variables index list. + * \return Pointer to free variables index list. */ +static inline Indexlist* Bounds_getFree( Bounds* _THIS + ); + +/** Returns a pointer to fixed variables index list. + * \return Pointer to fixed variables index list. */ +static inline Indexlist* Bounds_getFixed( Bounds* _THIS + ); + + +/** Returns number of bounds with given SubjectTo type. + * \return Number of bounds with given type. */ +static inline int Bounds_getNumberOfType( Bounds* _THIS, + SubjectToType _type /**< Type of bound. */ + ); + + +/** Returns type of bound. + * \return Type of bound \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline SubjectToType Bounds_getType( Bounds* _THIS, + int i /**< Number of bound. */ + ); + +/** Returns status of bound. + * \return Status of bound \n + ST_UNDEFINED */ +static inline SubjectToStatus Bounds_getStatus( Bounds* _THIS, + int i /**< Number of bound. */ + ); + + +/** Sets type of bound. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue Bounds_setType( Bounds* _THIS, + int i, /**< Number of bound. */ + SubjectToType value /**< Type of bound. */ + ); + +/** Sets status of bound. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue Bounds_setStatus( Bounds* _THIS, + int i, /**< Number of bound. */ + SubjectToStatus value /**< Status of bound. */ + ); + + +/** Sets status of lower bounds. */ +static inline void Bounds_setNoLower( Bounds* _THIS, + BooleanType _status /**< Status of lower bounds. */ + ); + +/** Sets status of upper bounds. */ +static inline void Bounds_setNoUpper( Bounds* _THIS, + BooleanType _status /**< Status of upper bounds. */ + ); + + +/** Returns status of lower bounds. + * \return BT_TRUE if there is no lower bound on any variable. */ +static inline BooleanType Bounds_hasNoLower( Bounds* _THIS + ); + +/** Returns status of upper bounds. + * \return BT_TRUE if there is no upper bound on any variable. */ +static inline BooleanType Bounds_hasNoUpper( Bounds* _THIS + ); + + +/** Shifts forward type and status of all bounds by a given + * offset. This offset has to lie within the range [0,n/2] and has to + * be an integer divisor of the total number of bounds n. + * Type and status of the first \ bounds is thrown away, + * type and status of the last \ bounds is doubled, + * e.g. for offset = 2: \n + * shift( {b1,b2,b3,b4,b5,b6} ) = {b3,b4,b5,b6,b5,b6} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS \n + RET_SHIFTING_FAILED */ +returnValue Bounds_shift( Bounds* _THIS, + int offset /**< Shift offset within the range [0,n/2] and integer divisor of n. */ + ); + +/** Rotates forward type and status of all bounds by a given + * offset. This offset has to lie within the range [0,n]. + * Example for offset = 2: \n + * rotate( {b1,b2,b3,b4,b5,b6} ) = {b3,b4,b5,b6,b1,b2} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_ROTATING_FAILED */ +returnValue Bounds_rotate( Bounds* _THIS, + int offset /**< Rotation offset within the range [0,n]. */ + ); + + +/** Prints information on bounds object + * (in particular, lists of free and fixed bounds. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ +returnValue Bounds_print( Bounds* _THIS + ); + + +/** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set corresponding to the desired status; + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_BOUND_FAILED */ +returnValue Bounds_setupAll( Bounds* _THIS, + SubjectToStatus _status /**< Desired initial status for all bounds. */ + ); + + +/** Adds the index of a new bound to index set. + * \return SUCCESSFUL_RETURN \n + RET_ADDINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue Bounds_addIndex( Bounds* _THIS, + Indexlist* const indexlist, /**< Index list to which the new index shall be added. */ + int newnumber, /**< Number of new bound. */ + SubjectToStatus newstatus /**< Status of new bound. */ + ); + +/** Removes the index of a bound from index set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVEINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue Bounds_removeIndex( Bounds* _THIS, + Indexlist* const indexlist, /**< Index list from which the new index shall be removed. */ + int removenumber /**< Number of bound to be removed. */ + ); + +/** Swaps the indices of two constraints or bounds within the index set. + * \return SUCCESSFUL_RETURN \n + RET_SWAPINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue Bounds_swapIndex( Bounds* _THIS, + Indexlist* const indexlist, /**< Index list in which the indices shold be swapped. */ + int number1, /**< Number of first bound. */ + int number2 /**< Number of second bound. */ + ); + + + +/* + * g e t N u m b e r O f T y p e + */ +static inline int Bounds_getNumberOfType( Bounds* _THIS, SubjectToType _type ) +{ + int i; + int numberOfType = 0; + + if ( _THIS->type != 0 ) + { + for( i=0; i<_THIS->n; ++i ) + if ( _THIS->type[i] == _type ) + ++numberOfType; + } + + return numberOfType; +} + + +/* + * g e t T y p e + */ +static inline SubjectToType Bounds_getType( Bounds* _THIS, int i ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + return _THIS->type[i]; + + return ST_UNKNOWN; +} + + +/* + * g e t S t a t u s + */ +static inline SubjectToStatus Bounds_getStatus( Bounds* _THIS, int i ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + return _THIS->status[i]; + + return ST_UNDEFINED; +} + + +/* + * s e t T y p e + */ +static inline returnValue Bounds_setType( Bounds* _THIS, int i, SubjectToType value ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + { + _THIS->type[i] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t S t a t u s + */ +static inline returnValue Bounds_setStatus( Bounds* _THIS, int i, SubjectToStatus value ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + { + _THIS->status[i] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t N o L o w e r + */ +static inline void Bounds_setNoLower( Bounds* _THIS, BooleanType _status ) +{ + _THIS->noLower = _status; +} + + +/* + * s e t N o U p p e r + */ +static inline void Bounds_setNoUpper( Bounds* _THIS, BooleanType _status ) +{ + _THIS->noUpper = _status; +} + + +/* + * h a s N o L o w e r + */ +static inline BooleanType Bounds_hasNoLower( Bounds* _THIS ) +{ + return _THIS->noLower; +} + + +/* + * h a s N o U p p p e r + */ +static inline BooleanType Bounds_hasNoUpper( Bounds* _THIS ) +{ + return _THIS->noUpper; +} + + + +/* + * g e t N V + */ +static inline int Bounds_getNV( Bounds* _THIS ) +{ + return _THIS->n; +} + + +/* + * g e t N F V + */ +static inline int Bounds_getNFV( Bounds* _THIS ) +{ + return Bounds_getNumberOfType( _THIS,ST_EQUALITY ); +} + + +/* + * g e t N B V + */ +static inline int Bounds_getNBV( Bounds* _THIS ) +{ + return Bounds_getNumberOfType( _THIS,ST_BOUNDED ); +} + + +/* + * g e t N U V + */ +static inline int Bounds_getNUV( Bounds* _THIS ) +{ + return Bounds_getNumberOfType( _THIS,ST_UNBOUNDED ); +} + + +/* + * g e t N F R + */ +static inline int Bounds_getNFR( Bounds* _THIS ) +{ + return Indexlist_getLength( _THIS->freee ); +} + + +/* + * g e t N F X + */ +static inline int Bounds_getNFX( Bounds* _THIS ) +{ + return Indexlist_getLength( _THIS->fixed ); +} + + +/* + * g e t F r e e + */ +static inline Indexlist* Bounds_getFree( Bounds* _THIS ) +{ + return _THIS->freee; +} + + +/* + * g e t F i x e d + */ +static inline Indexlist* Bounds_getFixed( Bounds* _THIS ) +{ + return _THIS->fixed; +} + + +END_NAMESPACE_QPOASES + +#endif /* QPOASES_BOUNDS_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Constants.h b/third_party/acados/include/qpOASES_e/Constants.h new file mode 100644 index 0000000000..13c777d75b --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Constants.h @@ -0,0 +1,134 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Constants.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Definition of all global constants. + */ + + +#ifndef QPOASES_CONSTANTS_H +#define QPOASES_CONSTANTS_H + + +#include + +#ifdef __CODE_GENERATION__ + + #define CONVERTTOSTRINGAUX(x) #x + #define CONVERTTOSTRING(x) CONVERTTOSTRINGAUX(x) + + #ifndef QPOASES_CUSTOM_INTERFACE + #include "acado_qpoases3_interface.h" + #else + #include CONVERTTOSTRING(QPOASES_CUSTOM_INTERFACE) + #endif + +#endif + + +BEGIN_NAMESPACE_QPOASES + + +#ifndef __EXTERNAL_DIMENSIONS__ + + /*#define QPOASES_NVMAX 50 + #define QPOASES_NCMAX 100*/ + #define QPOASES_NVMAX 287 + #define QPOASES_NCMAX 709 + +#endif /* __EXTERNAL_DIMENSIONS__ */ + + +/** Maximum number of variables within a QP formulation. + * Note: this value has to be positive! */ +#define NVMAX QPOASES_NVMAX + +/** Maximum number of constraints within a QP formulation. + * Note: this value has to be positive! */ +#define NCMAX QPOASES_NCMAX + +#if ( QPOASES_NVMAX > QPOASES_NCMAX ) +#define NVCMAX QPOASES_NVMAX +#else +#define NVCMAX QPOASES_NCMAX +#endif + +#if ( QPOASES_NVMAX > QPOASES_NCMAX ) +#define NVCMIN QPOASES_NCMAX +#else +#define NVCMIN QPOASES_NVMAX +#endif + + +/** Maximum number of QPs in a sequence solved by means of the OQP interface. + * Note: this value has to be positive! */ +#define NQPMAX 1000 + + +/** Numerical value of machine precision (min eps, s.t. 1+eps > 1). + * Note: this value has to be positive! */ +#ifndef __CODE_GENERATION__ + + #ifdef __USE_SINGLE_PRECISION__ + static const real_t QPOASES_EPS = 1.193e-07; + #else + static const real_t QPOASES_EPS = 2.221e-16; + #endif /* __USE_SINGLE_PRECISION__ */ + +#endif /* __CODE_GENERATION__ */ + + +/** Numerical value of zero (for situations in which it would be + * unreasonable to compare with 0.0). + * Note: this value has to be positive! */ +static const real_t QPOASES_ZERO = 1.0e-25; + +/** Numerical value of infinity (e.g. for non-existing bounds). + * Note: this value has to be positive! */ +static const real_t QPOASES_INFTY = 1.0e20; + +/** Tolerance to used for isEqual, isZero etc. + * Note: this value has to be positive! */ +static const real_t QPOASES_TOL = 1.0e-25; + + +/** Maximum number of characters within a string. + * Note: this value should be at least 41! */ +#define QPOASES_MAX_STRING_LENGTH 160 + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_CONSTANTS_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/ConstraintProduct.h b/third_party/acados/include/qpOASES_e/ConstraintProduct.h new file mode 100644 index 0000000000..eb5400c6cb --- /dev/null +++ b/third_party/acados/include/qpOASES_e/ConstraintProduct.h @@ -0,0 +1,62 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/ConstraintProduct.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches (thanks to D. Kwame Minde Kufoalor) + * \version 3.1embedded + * \date 2009-2015 + * + * Declaration of the ConstraintProduct interface which allows to specify a + * user-defined function for evaluating the constraint product at the + * current iterate to speed-up QP solution in case of a specially structured + * constraint matrix. + */ + + + +#ifndef QPOASES_CONSTRAINT_PRODUCT_H +#define QPOASES_CONSTRAINT_PRODUCT_H + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Interface for specifying user-defined evaluations of constraint products. + * + * An interface which allows to specify a user-defined function for evaluating the + * constraint product at the current iterate to speed-up QP solution in case + * of a specially structured constraint matrix. + * + * \author Hans Joachim Ferreau (thanks to Kwame Minde Kufoalor) + * \version 3.1embedded + * \date 2009-2015 + */ +typedef int(*ConstraintProduct)( int, const real_t* const, real_t* const ); + + +END_NAMESPACE_QPOASES + +#endif /* QPOASES_CONSTRAINT_PRODUCT_H */ diff --git a/third_party/acados/include/qpOASES_e/Constraints.h b/third_party/acados/include/qpOASES_e/Constraints.h new file mode 100644 index 0000000000..8aca10d5d9 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Constraints.h @@ -0,0 +1,535 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Constraints.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the Constraints class designed to manage working sets of + * constraints within a QProblem. + */ + + +#ifndef QPOASES_CONSTRAINTS_H +#define QPOASES_CONSTRAINTS_H + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Manages working sets of constraints. + * + * This class manages working sets of constraints by storing + * index sets and other status information. + * + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + Indexlist *active; /**< Index list of active constraints. */ + Indexlist *inactive; /**< Index list of inactive constraints. */ + + Indexlist *shiftedActive; /**< Memory for shifting active constraints. */ + Indexlist *shiftedInactive; /**< Memory for shifting inactive constraints. */ + + Indexlist *rotatedActive; /**< Memory for rotating active constraints. */ + Indexlist *rotatedInactive; /**< Memory for rotating inactive constraints. */ + + SubjectToType *type; /**< Type of constraints. */ + SubjectToStatus *status; /**< Status of constraints. */ + + SubjectToType *typeTmp; /**< Temp memory for type of constraints. */ + SubjectToStatus *statusTmp; /**< Temp memory for status of constraints. */ + + BooleanType noLower; /**< This flag indicates if there is no lower bound on any variable. */ + BooleanType noUpper; /**< This flag indicates if there is no upper bound on any variable. */ + + int n; /**< Total number of constraints. */ +} Constraints; + +int Constraints_calculateMemorySize( int n); + +char *Constraints_assignMemory(int n, Constraints **mem, void *raw_memory); + +Constraints *Constraints_createMemory( int n ); + +/** Constructor which takes the number of constraints. */ +void ConstraintsCON( Constraints* _THIS, + int _n /**< Number of constraints. */ + ); + +/** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ +void ConstraintsCPY( Constraints* FROM, + Constraints* TO + ); + + +/** Initialises object with given number of constraints. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ +returnValue Constraints_init( Constraints* _THIS, + int _n /**< Number of constraints. */ + ); + + +/** Initially adds number of a new (i.e. not yet in the list) constraint to + * a given index set. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS */ +returnValue Constraints_setupConstraint( Constraints* _THIS, + int number, /**< Number of new constraint. */ + SubjectToStatus _status /**< Status of new constraint. */ + ); + +/** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to + * to the index set of inactive constraints; the order depends on the SujectToType + * of each index. Only disabled constraints are added to index set of disabled constraints! + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ +returnValue Constraints_setupAllInactive( Constraints* _THIS + ); + +/** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to + * to the index set of active constraints (on their lower bounds); the order depends on the SujectToType + * of each index. Only disabled constraints are added to index set of disabled constraints! + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ +returnValue Constraints_setupAllLower( Constraints* _THIS + ); + +/** Initially adds all enabled numbers of new (i.e. not yet in the list) constraints to + * to the index set of active constraints (on their upper bounds); the order depends on the SujectToType + * of each index. Only disabled constraints are added to index set of disabled constraints! + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ +returnValue Constraints_setupAllUpper( Constraints* _THIS + ); + + +/** Moves index of a constraint from index list of active to that of inactive constraints. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_CONSTRAINT_FAILED */ +returnValue Constraints_moveActiveToInactive( Constraints* _THIS, + int number /**< Number of constraint to become inactive. */ + ); + +/** Moves index of a constraint from index list of inactive to that of active constraints. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_CONSTRAINT_FAILED */ +returnValue Constraints_moveInactiveToActive( Constraints* _THIS, + int number, /**< Number of constraint to become active. */ + SubjectToStatus _status /**< Status of constraint to become active. */ + ); + +/** Flip fixed constraint. + * \return SUCCESSFUL_RETURN \n + RET_MOVING_CONSTRAINT_FAILED \n + RET_INDEX_OUT_OF_BOUNDS */ +returnValue Constraints_flipFixed( Constraints* _THIS, + int number + ); + + +/** Returns the number of constraints. + * \return Number of constraints. */ +static inline int Constraints_getNC( Constraints* _THIS + ); + +/** Returns the number of implicit equality constraints. + * \return Number of implicit equality constraints. */ +static inline int Constraints_getNEC( Constraints* _THIS + ); + +/** Returns the number of "real" inequality constraints. + * \return Number of "real" inequality constraints. */ +static inline int Constraints_getNIC( Constraints* _THIS + ); + +/** Returns the number of unbounded constraints (i.e. without any bounds). + * \return Number of unbounded constraints (i.e. without any bounds). */ +static inline int Constraints_getNUC( Constraints* _THIS + ); + +/** Returns the number of active constraints. + * \return Number of active constraints. */ +static inline int Constraints_getNAC( Constraints* _THIS + ); + +/** Returns the number of inactive constraints. + * \return Number of inactive constraints. */ +static inline int Constraints_getNIAC( Constraints* _THIS + ); + + +/** Returns a pointer to active constraints index list. + * \return Pointer to active constraints index list. */ +static inline Indexlist* Constraints_getActive( Constraints* _THIS + ); + +/** Returns a pointer to inactive constraints index list. + * \return Pointer to inactive constraints index list. */ +static inline Indexlist* Constraints_getInactive( Constraints* _THIS + ); + + +/** Returns number of constraints with given SubjectTo type. + * \return Number of constraints with given type. */ +static inline int Constraints_getNumberOfType( Constraints* _THIS, + SubjectToType _type /**< Type of constraints' bound. */ + ); + + +/** Returns type of constraints' bound. + * \return Type of constraints' bound \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline SubjectToType Constraints_getType( Constraints* _THIS, + int i /**< Number of constraints' bound. */ + ); + +/** Returns status of constraints' bound. + * \return Status of constraints' bound \n + ST_UNDEFINED */ +static inline SubjectToStatus Constraints_getStatus( Constraints* _THIS, + int i /**< Number of constraints' bound. */ + ); + + +/** Sets type of constraints' bound. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue Constraints_setType( Constraints* _THIS, + int i, /**< Number of constraints' bound. */ + SubjectToType value /**< Type of constraints' bound. */ + ); + +/** Sets status of constraints' bound. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue Constraints_setStatus( Constraints* _THIS, + int i, /**< Number of constraints' bound. */ + SubjectToStatus value /**< Status of constraints' bound. */ + ); + + +/** Sets status of lower constraints' bounds. */ +static inline void Constraints_setNoLower( Constraints* _THIS, + BooleanType _status /**< Status of lower constraints' bounds. */ + ); + +/** Sets status of upper constraints' bounds. */ +static inline void Constraints_setNoUpper( Constraints* _THIS, + BooleanType _status /**< Status of upper constraints' bounds. */ + ); + + +/** Returns status of lower constraints' bounds. + * \return BT_TRUE if there is no lower constraints' bound on any variable. */ +static inline BooleanType Constraints_hasNoLower( Constraints* _THIS + ); + +/** Returns status of upper bounds. + * \return BT_TRUE if there is no upper constraints' bound on any variable. */ +static inline BooleanType Constraints_hasNoUpper( Constraints* _THIS + ); + + +/** Shifts forward type and status of all constraints by a given + * offset. This offset has to lie within the range [0,n/2] and has to + * be an integer divisor of the total number of constraints n. + * Type and status of the first \ constraints is thrown away, + * type and status of the last \ constraints is doubled, + * e.g. for offset = 2: \n + * shift( {c/b1,c/b2,c/b3,c/b4,c/b5,c/b6} ) = {c/b3,c/b4,c/b5,c/b6,c/b5,c/b6} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_INVALID_ARGUMENTS \n + RET_SHIFTING_FAILED */ +returnValue Constraints_shift( Constraints* _THIS, + int offset /**< Shift offset within the range [0,n/2] and integer divisor of n. */ + ); + +/** Rotates forward type and status of all constraints by a given + * offset. This offset has to lie within the range [0,n]. + * Example for offset = 2: \n + * rotate( {c1,c2,c3,c4,c5,c6} ) = {c3,c4,c5,c6,c1,c2} + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS \n + RET_ROTATING_FAILED */ +returnValue Constraints_rotate( Constraints* _THIS, + int offset /**< Rotation offset within the range [0,n]. */ + ); + + +/** Prints information on constraints object + * (in particular, lists of inactive and active constraints. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ +returnValue Constraints_print( Constraints* _THIS + ); + + +/** Initially adds all numbers of new (i.e. not yet in the list) bounds to + * to the index set corresponding to the desired status; + * the order depends on the SujectToType of each index. + * \return SUCCESSFUL_RETURN \n + RET_SETUP_CONSTRAINT_FAILED */ +returnValue Constraints_setupAll( Constraints* _THIS, + SubjectToStatus _status /**< Desired initial status for all bounds. */ + ); + + +/** Adds the index of a new constraint to index set. + * \return SUCCESSFUL_RETURN \n + RET_ADDINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue Constraints_addIndex( Constraints* _THIS, + Indexlist* const indexlist, /**< Index list to which the new index shall be added. */ + int newnumber, /**< Number of new constraint. */ + SubjectToStatus newstatus /**< Status of new constraint. */ + ); + +/** Removes the index of a constraint from index set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVEINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue Constraints_removeIndex( Constraints* _THIS, + Indexlist* const indexlist, /**< Index list from which the new index shall be removed. */ + int removenumber /**< Number of constraint to be removed. */ + ); + +/** Swaps the indices of two constraints or bounds within the index set. + * \return SUCCESSFUL_RETURN \n + RET_SWAPINDEX_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue Constraints_swapIndex( Constraints* _THIS, + Indexlist* const indexlist, /**< Index list in which the indices shold be swapped. */ + int number1, /**< Number of first constraint. */ + int number2 /**< Number of second constraint. */ + ); + + + +/* + * g e t N u m b e r O f T y p e + */ +static inline int Constraints_getNumberOfType( Constraints* _THIS, SubjectToType _type ) +{ + int i; + int numberOfType = 0; + + if ( _THIS->type != 0 ) + { + for( i=0; i<_THIS->n; ++i ) + if ( _THIS->type[i] == _type ) + ++numberOfType; + } + + return numberOfType; +} + + +/* + * g e t T y p e + */ +static inline SubjectToType Constraints_getType( Constraints* _THIS, int i ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + return _THIS->type[i]; + + return ST_UNKNOWN; +} + + +/* + * g e t S t a t u s + */ +static inline SubjectToStatus Constraints_getStatus( Constraints* _THIS, int i ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + return _THIS->status[i]; + + return ST_UNDEFINED; +} + + +/* + * s e t T y p e + */ +static inline returnValue Constraints_setType( Constraints* _THIS, int i, SubjectToType value ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + { + _THIS->type[i] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t S t a t u s + */ +static inline returnValue Constraints_setStatus( Constraints* _THIS, int i, SubjectToStatus value ) +{ + if ( ( i >= 0 ) && ( i < _THIS->n ) ) + { + _THIS->status[i] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t N o L o w e r + */ +static inline void Constraints_setNoLower( Constraints* _THIS, BooleanType _status ) +{ + _THIS->noLower = _status; +} + + +/* + * s e t N o U p p e r + */ +static inline void Constraints_setNoUpper( Constraints* _THIS, BooleanType _status ) +{ + _THIS->noUpper = _status; +} + + +/* + * h a s N o L o w e r + */ +static inline BooleanType Constraints_hasNoLower( Constraints* _THIS ) +{ + return _THIS->noLower; +} + + +/* + * h a s N o U p p p e r + */ +static inline BooleanType Constraints_hasNoUpper( Constraints* _THIS ) +{ + return _THIS->noUpper; +} + + + +/* + * g e t N C + */ +static inline int Constraints_getNC( Constraints* _THIS ) +{ + return _THIS->n; +} + + +/* + * g e t N E C + */ +static inline int Constraints_getNEC( Constraints* _THIS ) +{ + return Constraints_getNumberOfType( _THIS,ST_EQUALITY ); +} + + +/* + * g e t N I C + */ +static inline int Constraints_getNIC( Constraints* _THIS ) +{ + return Constraints_getNumberOfType( _THIS,ST_BOUNDED ); +} + + +/* + * g e t N U C + */ +static inline int Constraints_getNUC( Constraints* _THIS ) +{ + return Constraints_getNumberOfType( _THIS,ST_UNBOUNDED ); +} + + +/* + * g e t N A C + */ +static inline int Constraints_getNAC( Constraints* _THIS ) +{ + return Indexlist_getLength( _THIS->active ); +} + + +/* + * g e t N I A C + */ +static inline int Constraints_getNIAC( Constraints* _THIS ) +{ + return Indexlist_getLength( _THIS->inactive ); +} + + + +/* + * g e t A c t i v e + */ +static inline Indexlist* Constraints_getActive( Constraints* _THIS ) +{ + return _THIS->active; +} + + +/* + * g e t I n a c t i v e + */ +static inline Indexlist* Constraints_getInactive( Constraints* _THIS ) +{ + return _THIS->inactive; +} + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_CONSTRAINTS_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Flipper.h b/third_party/acados/include/qpOASES_e/Flipper.h new file mode 100644 index 0000000000..63526a30f3 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Flipper.h @@ -0,0 +1,129 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Flipper.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the Options class designed to manage user-specified + * options for solving a QProblem. + */ + + +#ifndef QPOASES_FLIPPER_H +#define QPOASES_FLIPPER_H + + +#include +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Auxiliary class for storing a copy of the current matrix factorisations. + * + * This auxiliary class stores a copy of the current matrix factorisations. It + * is used by the classe QProblemB and QProblem in case flipping bounds are enabled. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + Bounds *bounds; /**< Data structure for problem's bounds. */ + Constraints *constraints; /**< Data structure for problem's constraints. */ + + real_t *R; /**< Cholesky factor of H (i.e. H = R^T*R). */ + real_t *Q; /**< Orthonormal quadratic matrix, A = [0 T]*Q'. */ + real_t *T; /**< Reverse triangular matrix, A = [0 T]*Q'. */ + + unsigned int nV; /**< Number of variables. */ + unsigned int nC; /**< Number of constraints. */ +} Flipper; + +int Flipper_calculateMemorySize( unsigned int nV, unsigned int nC ); + +char *Flipper_assignMemory( unsigned int nV, unsigned int nC, Flipper **mem, void *raw_memory ); + +Flipper *Flipper_createMemory( unsigned int nV, unsigned int nC ); + +/** Constructor which takes the number of bounds and constraints. */ +void FlipperCON( Flipper* _THIS, + unsigned int _nV, /**< Number of bounds. */ + unsigned int _nC /**< Number of constraints. */ + ); + +/** Copy constructor (deep copy). */ +void FlipperCPY( Flipper* FROM, + Flipper* TO + ); + +/** Initialises object with given number of bounds and constraints. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ +returnValue Flipper_init( Flipper* _THIS, + unsigned int _nV, /**< Number of bounds. */ + unsigned int _nC /**< Number of constraints. */ + ); + + +/** Copies current values to non-null arguments (assumed to be allocated with consistent size). + * \return SUCCESSFUL_RETURN */ +returnValue Flipper_get( Flipper* _THIS, + Bounds* const _bounds, /**< Pointer to new bounds. */ + real_t* const R, /**< New matrix R. */ + Constraints* const _constraints, /**< Pointer to new constraints. */ + real_t* const _Q, /**< New matrix Q. */ + real_t* const _T /**< New matrix T. */ + ); + +/** Assigns new values to non-null arguments. + * \return SUCCESSFUL_RETURN */ +returnValue Flipper_set( Flipper* _THIS, + const Bounds* const _bounds, /**< Pointer to new bounds. */ + const real_t* const _R, /**< New matrix R. */ + const Constraints* const _constraints, /**< Pointer to new constraints. */ + const real_t* const _Q, /**< New matrix Q. */ + const real_t* const _T /**< New matrix T. */ + ); + +/** Returns dimension of matrix T. + * \return Dimension of matrix T. */ +unsigned int Flipper_getDimT( Flipper* _THIS ); + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_FLIPPER_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Indexlist.h b/third_party/acados/include/qpOASES_e/Indexlist.h new file mode 100644 index 0000000000..02d259d63d --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Indexlist.h @@ -0,0 +1,221 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Indexlist.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the Indexlist class designed to manage index lists of + * constraints and bounds within a SubjectTo object. + */ + + +#ifndef QPOASES_INDEXLIST_H +#define QPOASES_INDEXLIST_H + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Stores and manages index lists. + * + * This class manages index lists of active/inactive bounds/constraints. + * + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + int *number; /**< Array to store numbers of constraints or bounds. */ + int *iSort; /**< Index list to sort vector \a number */ + + int length; /**< Length of index list. */ + int first; /**< Physical index of first element. */ + int last; /**< Physical index of last element. */ + int lastusedindex; /**< Physical index of last entry in index list. */ + int physicallength; /**< Physical length of index list. */ +} Indexlist; + +int Indexlist_calculateMemorySize( int n); + +char *Indexlist_assignMemory(int n, Indexlist **mem, void *raw_memory); + +Indexlist *Indexlist_createMemory( int n ); + +/** Constructor which takes the desired physical length of the index list. */ +void IndexlistCON( Indexlist* _THIS, + int n /**< Physical length of index list. */ + ); + +/** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ +void IndexlistCPY( Indexlist* FROM, + Indexlist* TO + ); + +/** Initialises index list of desired physical length. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ +returnValue Indexlist_init( Indexlist* _THIS, + int n /**< Physical length of index list. */ + ); + +/** Creates an array of all numbers within the index set in correct order. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ +returnValue Indexlist_getNumberArray( Indexlist* _THIS, + int** const numberarray /**< Output: Array of numbers (NULL on error). */ + ); + +/** Creates an array of all numbers within the index set in correct order. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ +returnValue Indexlist_getISortArray( Indexlist* _THIS, + int** const iSortArray /**< Output: iSort Array. */ + ); + + +/** Determines the index within the index list at which a given number is stored. + * \return >= 0: Index of given number. \n + -1: Number not found. */ +int Indexlist_getIndex( Indexlist* _THIS, + int givennumber /**< Number whose index shall be determined. */ + ); + +/** Returns the number stored at a given physical index. + * \return >= 0: Number stored at given physical index. \n + -RET_INDEXLIST_OUTOFBOUNDS */ +static inline int Indexlist_getNumber( Indexlist* _THIS, + int physicalindex /**< Physical index of the number to be returned. */ + ); + + +/** Returns the current length of the index list. + * \return Current length of the index list. */ +static inline int Indexlist_getLength( Indexlist* _THIS + ); + +/** Returns last number within the index list. + * \return Last number within the index list. */ +static inline int Indexlist_getLastNumber( Indexlist* _THIS + ); + + +/** Adds number to index list. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_MUST_BE_REORDERD \n + RET_INDEXLIST_EXCEEDS_MAX_LENGTH */ +returnValue Indexlist_addNumber( Indexlist* _THIS, + int addnumber /**< Number to be added. */ + ); + +/** Removes number from index list. + * \return SUCCESSFUL_RETURN */ +returnValue Indexlist_removeNumber( Indexlist* _THIS, + int removenumber /**< Number to be removed. */ + ); + +/** Swaps two numbers within index list. + * \return SUCCESSFUL_RETURN */ +returnValue Indexlist_swapNumbers( Indexlist* _THIS, + int number1, /**< First number for swapping. */ + int number2 /**< Second number for swapping. */ + ); + +/** Determines if a given number is contained in the index set. + * \return BT_TRUE iff number is contain in the index set */ +static inline BooleanType Indexlist_isMember( Indexlist* _THIS, + int _number /**< Number to be tested for membership. */ + ); + + +/** Find first index j between -1 and length in sorted list of indices + * iSort such that numbers[iSort[j]] <= i < numbers[iSort[j+1]]. Uses + * bisection. + * \return j. */ +int Indexlist_findInsert( Indexlist* _THIS, + int i + ); + + + +/* + * g e t N u m b e r + */ +static inline int Indexlist_getNumber( Indexlist* _THIS, int physicalindex ) +{ + /* consistency check */ + if ( ( physicalindex < 0 ) || ( physicalindex > _THIS->length ) ) + return -RET_INDEXLIST_OUTOFBOUNDS; + + return _THIS->number[physicalindex]; +} + + +/* + * g e t L e n g t h + */ +static inline int Indexlist_getLength( Indexlist* _THIS ) +{ + return _THIS->length; +} + + +/* + * g e t L a s t N u m b e r + */ +static inline int Indexlist_getLastNumber( Indexlist* _THIS ) +{ + return _THIS->number[_THIS->length-1]; +} + + +/* + * g e t L a s t N u m b e r + */ +static inline BooleanType Indexlist_isMember( Indexlist* _THIS, int _number ) +{ + if ( Indexlist_getIndex( _THIS,_number ) >= 0 ) + return BT_TRUE; + else + return BT_FALSE; +} + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_INDEXLIST_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Matrices.h b/third_party/acados/include/qpOASES_e/Matrices.h new file mode 100644 index 0000000000..e2a46b3a9d --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Matrices.h @@ -0,0 +1,287 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Matrices.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2009-2015 + * + * Various matrix classes: Abstract base matrix class, dense and sparse matrices, + * including symmetry exploiting specializations. + */ + + + +#ifndef QPOASES_MATRICES_H +#define QPOASES_MATRICES_H + +#ifdef __USE_SINGLE_PRECISION__ + + // single precision + #define GEMM sgemm_ + #define GEMV sgemv_ +// #define SYR ssyr_ +// #define SYR2 ssyr2_ + #define POTRF spotrf_ + +#else + + // double precision + #define GEMM dgemm_ + #define GEMV dgemv_ +// #define SYR dsyr_ +// #define SYR2 dsyr2_ + #define POTRF dpotrf_ + +#endif /* __USE_SINGLE_PRECISION__ */ + + +#ifdef EXTERNAL_BLAS + // double precision + void dgemm_(char *ta, char *tb, int *m, int *n, int *k, double *alpha, double *A, int *lda, double *B, int ldb, double *beta, double *C, int *ldc); + void dgemv_(char *ta, int *m, int *n, double *alpha, double *A, int *lda, double *x, int *incx, double *beta, double *y, int *incy); + void dpotrf_(char *uplo, int *m, double *A, int *lda, int *info); + // single precision + void sgemm_(char *ta, char *tb, int *m, int *n, int *k, float *alpha, float *A, int *lda, float *B, int ldb, float *beta, float *C, int *ldc); + void sgemv_(char *ta, int *m, int *n, float *alpha, float *A, int *lda, float *x, int *incx, float *beta, float *y, int *incy); + void spotrf_(char *uplo, int *m, float *A, int *lda, int *info); +#else + /** Performs one of the matrix-matrix operation in double precision. */ + void dgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*, + const double*, const double*, const unsigned long*, const double*, const unsigned long*, + const double*, double*, const unsigned long* ); + /** Performs one of the matrix-matrix operation in single precision. */ + void sgemm_ ( const char*, const char*, const unsigned long*, const unsigned long*, const unsigned long*, + const float*, const float*, const unsigned long*, const float*, const unsigned long*, + const float*, float*, const unsigned long* ); + + /** Calculates the Cholesky factorization of a real symmetric positive definite matrix in double precision. */ + void dpotrf_ ( const char *, const unsigned long *, double *, const unsigned long *, long * ); + /** Calculates the Cholesky factorization of a real symmetric positive definite matrix in single precision. */ + void spotrf_ ( const char *, const unsigned long *, float *, const unsigned long *, long * ); + +#endif + + /** Performs a symmetric rank 1 operation in double precision. */ +// void dsyr_ ( const char *, const unsigned long *, const double *, const double *, +// const unsigned long *, double *, const unsigned long *); + /** Performs a symmetric rank 1 operation in single precision. */ +// void ssyr_ ( const char *, const unsigned long *, const float *, const float *, +// const unsigned long *, float *, const unsigned long *); + + /** Performs a symmetric rank 2 operation in double precision. */ +// void dsyr2_ ( const char *, const unsigned long *, const double *, const double *, +// const unsigned long *, const double *, const unsigned long *, double *, const unsigned long *); + /** Performs a symmetric rank 2 operation in single precision. */ +// void ssyr2_ ( const char *, const unsigned long *, const float *, const float *, +// const unsigned long *, const float *, const unsigned long *, float *, const unsigned long *); + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Interfaces matrix-vector operations tailored to general dense matrices. + * + * Dense matrix class (row major format). + * + * \author Andreas Potschka, Christian Kirches, Hans Joachim Ferreau + * \version 3.1embedded + * \date 2011-2015 + */ +typedef struct +{ + real_t *val; /**< Vector of entries. */ + int nRows; /**< Number of rows. */ + int nCols; /**< Number of columns. */ + int leaDim; /**< Leading dimension. */ +} DenseMatrix; + +int DenseMatrix_calculateMemorySize( int m, int n ); + +char *DenseMatrix_assignMemory( int m, int n, DenseMatrix **mem, void *raw_memory ); + +DenseMatrix *DenseMatrix_createMemory( int m, int n ); + +/** Constructor from vector of values. + * Caution: Data pointer must be valid throughout lifetime + */ +void DenseMatrixCON( DenseMatrix* _THIS, + int m, /**< Number of rows. */ + int n, /**< Number of columns. */ + int lD, /**< Leading dimension. */ + real_t *v /**< Values. */ + ); + +void DenseMatrixCPY( DenseMatrix* FROM, + DenseMatrix* TO + ); + + +/** Frees all internal memory. */ +void DenseMatrix_free( DenseMatrix* _THIS ); + +/** Constructor from vector of values. + * Caution: Data pointer must be valid throughout lifetime + */ +returnValue DenseMatrix_init( DenseMatrix* _THIS, + int m, /**< Number of rows. */ + int n, /**< Number of columns. */ + int lD, /**< Leading dimension. */ + real_t *v /**< Values. */ + ); + + +/** Returns i-th diagonal entry. + * \return i-th diagonal entry */ +real_t DenseMatrix_diag( DenseMatrix* _THIS, + int i /**< Index. */ + ); + +/** Checks whether matrix is square and diagonal. + * \return BT_TRUE iff matrix is square and diagonal; \n + * BT_FALSE otherwise. */ +BooleanType DenseMatrix_isDiag( DenseMatrix* _THIS ); + +/** Get the N-norm of the matrix + * \return N-norm of the matrix + */ +real_t DenseMatrix_getNorm( DenseMatrix* _THIS, + int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ); + +/** Get the N-norm of a row + * \return N-norm of row \a rNum + */ +real_t DenseMatrix_getRowNorm( DenseMatrix* _THIS, + int rNum, /**< Row number. */ + int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ); + +/** Retrieve indexed entries of matrix row multiplied by alpha. + * \return SUCCESSFUL_RETURN */ +returnValue DenseMatrix_getRow( DenseMatrix* _THIS, + int rNum, /**< Row number. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + real_t alpha, /**< Scalar factor. */ + real_t *row /**< Output row vector. */ + ); + +/** Retrieve indexed entries of matrix column multiplied by alpha. + * \return SUCCESSFUL_RETURN */ + returnValue DenseMatrix_getCol( DenseMatrix* _THIS, + int cNum, /**< Column number. */ + const Indexlist* const irows, /**< Index list specifying rows. */ + real_t alpha, /**< Scalar factor. */ + real_t *col /**< Output column vector. */ + ); + +/** Evaluate Y=alpha*A*X + beta*Y. + * \return SUCCESSFUL_RETURN. */ +returnValue DenseMatrix_times( DenseMatrix* _THIS, + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ); + +/** Evaluate Y=alpha*A'*X + beta*Y. + * \return SUCCESSFUL_RETURN. */ +returnValue DenseMatrix_transTimes( DenseMatrix* _THIS, + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ); + +/** Evaluate matrix vector product with submatrix given by Indexlist. + * \return SUCCESSFUL_RETURN */ + returnValue DenseMatrix_subTimes( DenseMatrix* _THIS, + const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD, /**< Leading dimension of output y. */ + BooleanType yCompr /**< Compressed storage for y. */ + ); + +/** Evaluate matrix transpose vector product. + * \return SUCCESSFUL_RETURN */ +returnValue DenseMatrix_subTransTimes( DenseMatrix* _THIS, + const Indexlist* const irows, /**< Index list specifying rows. */ + const Indexlist* const icols, /**< Index list specifying columns. */ + int xN, /**< Number of vectors to multiply. */ + real_t alpha, /**< Scalar factor for matrix vector product. */ + const real_t *x, /**< Input vector to be multiplied. */ + int xLD, /**< Leading dimension of input x. */ + real_t beta, /**< Scalar factor for y. */ + real_t *y, /**< Output vector of results. */ + int yLD /**< Leading dimension of output y. */ + ); + +/** Adds given offset to diagonal of matrix. + * \return SUCCESSFUL_RETURN \n + RET_NO_DIAGONAL_AVAILABLE */ +returnValue DenseMatrix_addToDiag( DenseMatrix* _THIS, + real_t alpha /**< Diagonal offset. */ + ); + +/** Prints matrix to screen. + * \return SUCCESSFUL_RETURN */ +returnValue DenseMatrix_print( DenseMatrix* _THIS + ); + +static inline real_t* DenseMatrix_getVal( DenseMatrix* _THIS ) { return _THIS->val; } + +/** Compute bilinear form y = x'*H*x using submatrix given by index list. + * \return SUCCESSFUL_RETURN */ +returnValue DenseMatrix_bilinear( DenseMatrix* _THIS, + const Indexlist* const icols, /**< Index list specifying columns of x. */ + int xN, /**< Number of vectors to multiply. */ + const real_t *x, /**< Input vector to be multiplied (uncompressed). */ + int xLD, /**< Leading dimension of input x. */ + real_t *y, /**< Output vector of results (compressed). */ + int yLD /**< Leading dimension of output y. */ + ); + + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_MATRICES_H */ diff --git a/third_party/acados/include/qpOASES_e/MessageHandling.h b/third_party/acados/include/qpOASES_e/MessageHandling.h new file mode 100644 index 0000000000..fe5524948a --- /dev/null +++ b/third_party/acados/include/qpOASES_e/MessageHandling.h @@ -0,0 +1,544 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/MessageHandling.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches (thanks to Leonard Wirsching) + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the MessageHandling class including global return values. + */ + + +#ifndef QPOASES_MESSAGEHANDLING_H +#define QPOASES_MESSAGEHANDLING_H + + +#include +#include +#include +#include + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** Default file to display messages. */ +#define stdFile stderr + + +/** + * \brief Defines all symbols for global return values. + * + * The enumeration returnValueType defines all symbols for global return values. + * Important: All return values are assumed to be nonnegative! + * + * \author Hans Joachim Ferreau + */ +typedef enum +{ +TERMINAL_LIST_ELEMENT = -1, /**< Terminal list element, internal usage only! */ +/* miscellaneous */ +SUCCESSFUL_RETURN = 0, /**< Successful return. */ +RET_DIV_BY_ZERO, /**< Division by zero. */ +RET_INDEX_OUT_OF_BOUNDS, /**< Index out of bounds. */ +RET_INVALID_ARGUMENTS, /**< At least one of the arguments is invalid. */ +RET_ERROR_UNDEFINED, /**< Error number undefined. */ +RET_WARNING_UNDEFINED, /**< Warning number undefined. */ +RET_INFO_UNDEFINED, /**< Info number undefined. */ +RET_EWI_UNDEFINED, /**< Error/warning/info number undefined. */ +RET_AVAILABLE_WITH_LINUX_ONLY, /**< This function is available under Linux only. */ +RET_UNKNOWN_BUG, /**< The error occurred is not yet known. */ +RET_PRINTLEVEL_CHANGED, /**< Print level changed. (10) */ +RET_NOT_YET_IMPLEMENTED, /**< Requested function is not yet implemented in this version of qpOASES. */ +/* Indexlist */ +RET_INDEXLIST_MUST_BE_REORDERD, /**< Index list has to be reordered. */ +RET_INDEXLIST_EXCEEDS_MAX_LENGTH, /**< Index list exceeds its maximal physical length. */ +RET_INDEXLIST_CORRUPTED, /**< Index list corrupted. */ +RET_INDEXLIST_OUTOFBOUNDS, /**< Physical index is out of bounds. */ +RET_INDEXLIST_ADD_FAILED, /**< Adding indices from another index set failed. */ +RET_INDEXLIST_INTERSECT_FAILED, /**< Intersection with another index set failed. */ +/* SubjectTo / Bounds / Constraints */ +RET_INDEX_ALREADY_OF_DESIRED_STATUS, /**< Index is already of desired status. (18) */ +RET_ADDINDEX_FAILED, /**< Adding index to index set failed. */ +RET_REMOVEINDEX_FAILED, /**< Removing index from index set failed. (20) */ +RET_SWAPINDEX_FAILED, /**< Cannot swap between different indexsets. */ +RET_NOTHING_TO_DO, /**< Nothing to do. */ +RET_SETUP_BOUND_FAILED, /**< Setting up bound index failed. */ +RET_SETUP_CONSTRAINT_FAILED, /**< Setting up constraint index failed. */ +RET_MOVING_BOUND_FAILED, /**< Moving bound between index sets failed. */ +RET_MOVING_CONSTRAINT_FAILED, /**< Moving constraint between index sets failed. */ +RET_SHIFTING_FAILED, /**< Shifting of bounds/constraints failed. */ +RET_ROTATING_FAILED, /**< Rotating of bounds/constraints failed. */ +/* QProblem */ +RET_QPOBJECT_NOT_SETUP, /**< The QP object has not been setup correctly, use another constructor. */ +RET_QP_ALREADY_INITIALISED, /**< QProblem has already been initialised. (30) */ +RET_NO_INIT_WITH_STANDARD_SOLVER, /**< Initialisation via extern QP solver is not yet implemented. */ +RET_RESET_FAILED, /**< Reset failed. */ +RET_INIT_FAILED, /**< Initialisation failed. */ +RET_INIT_FAILED_TQ, /**< Initialisation failed due to TQ factorisation. */ +RET_INIT_FAILED_CHOLESKY, /**< Initialisation failed due to Cholesky decomposition. */ +RET_INIT_FAILED_HOTSTART, /**< Initialisation failed! QP could not be solved! */ +RET_INIT_FAILED_INFEASIBILITY, /**< Initial QP could not be solved due to infeasibility! */ +RET_INIT_FAILED_UNBOUNDEDNESS, /**< Initial QP could not be solved due to unboundedness! */ +RET_INIT_FAILED_REGULARISATION, /**< Initialisation failed as Hessian matrix could not be regularised. */ +RET_INIT_SUCCESSFUL, /**< Initialisation done. (40) */ +RET_OBTAINING_WORKINGSET_FAILED, /**< Failed to obtain working set for auxiliary QP. */ +RET_SETUP_WORKINGSET_FAILED, /**< Failed to setup working set for auxiliary QP. */ +RET_SETUP_AUXILIARYQP_FAILED, /**< Failed to setup auxiliary QP for initialised homotopy. */ +RET_NO_CHOLESKY_WITH_INITIAL_GUESS, /**< Externally computed Cholesky factor cannot be combined with an initial guess. */ +RET_NO_EXTERN_SOLVER, /**< No extern QP solver available. */ +RET_QP_UNBOUNDED, /**< QP is unbounded. */ +RET_QP_INFEASIBLE, /**< QP is infeasible. */ +RET_QP_NOT_SOLVED, /**< Problems occurred while solving QP with standard solver. */ +RET_QP_SOLVED, /**< QP successfully solved. */ +RET_UNABLE_TO_SOLVE_QP, /**< Problems occurred while solving QP. (50) */ +RET_INITIALISATION_STARTED, /**< Starting problem initialisation... */ +RET_HOTSTART_FAILED, /**< Unable to perform homotopy due to internal error. */ +RET_HOTSTART_FAILED_TO_INIT, /**< Unable to initialise problem. */ +RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED, /**< Unable to perform homotopy as previous QP is not solved. */ +RET_ITERATION_STARTED, /**< Iteration... */ +RET_SHIFT_DETERMINATION_FAILED, /**< Determination of shift of the QP data failed. */ +RET_STEPDIRECTION_DETERMINATION_FAILED, /**< Determination of step direction failed. */ +RET_STEPLENGTH_DETERMINATION_FAILED, /**< Determination of step direction failed. */ +RET_OPTIMAL_SOLUTION_FOUND, /**< Optimal solution of neighbouring QP found. */ +RET_HOMOTOPY_STEP_FAILED, /**< Unable to perform homotopy step. (60) */ +RET_HOTSTART_STOPPED_INFEASIBILITY, /**< Premature homotopy termination because QP is infeasible. */ +RET_HOTSTART_STOPPED_UNBOUNDEDNESS, /**< Premature homotopy termination because QP is unbounded. */ +RET_WORKINGSET_UPDATE_FAILED, /**< Unable to update working sets according to initial guesses. */ +RET_MAX_NWSR_REACHED, /**< Maximum number of working set recalculations performed. */ +RET_CONSTRAINTS_NOT_SPECIFIED, /**< Problem does comprise constraints! You also have to specify new constraints' bounds. */ +RET_INVALID_FACTORISATION_FLAG, /**< Invalid factorisation flag. */ +RET_UNABLE_TO_SAVE_QPDATA, /**< Unable to save QP data. */ +RET_STEPDIRECTION_FAILED_TQ, /**< Abnormal termination due to TQ factorisation. */ +RET_STEPDIRECTION_FAILED_CHOLESKY, /**< Abnormal termination due to Cholesky factorisation. */ +RET_CYCLING_DETECTED, /**< Cycling detected. (70) */ +RET_CYCLING_NOT_RESOLVED, /**< Cycling cannot be resolved, QP probably infeasible. */ +RET_CYCLING_RESOLVED, /**< Cycling probably resolved. */ +RET_STEPSIZE, /**< For displaying performed stepsize. */ +RET_STEPSIZE_NONPOSITIVE, /**< For displaying non-positive stepsize. */ +RET_SETUPSUBJECTTOTYPE_FAILED, /**< Setup of SubjectToTypes failed. */ +RET_ADDCONSTRAINT_FAILED, /**< Addition of constraint to working set failed. */ +RET_ADDCONSTRAINT_FAILED_INFEASIBILITY, /**< Addition of constraint to working set failed (due to QP infeasibility). */ +RET_ADDBOUND_FAILED, /**< Addition of bound to working set failed. */ +RET_ADDBOUND_FAILED_INFEASIBILITY, /**< Addition of bound to working set failed (due to QP infeasibility). */ +RET_REMOVECONSTRAINT_FAILED, /**< Removal of constraint from working set failed. (80) */ +RET_REMOVEBOUND_FAILED, /**< Removal of bound from working set failed. */ +RET_REMOVE_FROM_ACTIVESET, /**< Removing from active set... */ +RET_ADD_TO_ACTIVESET, /**< Adding to active set... */ +RET_REMOVE_FROM_ACTIVESET_FAILED, /**< Removing from active set failed. */ +RET_ADD_TO_ACTIVESET_FAILED, /**< Adding to active set failed. */ +RET_CONSTRAINT_ALREADY_ACTIVE, /**< Constraint is already active. */ +RET_ALL_CONSTRAINTS_ACTIVE, /**< All constraints are active, no further constraint can be added. */ +RET_LINEARLY_DEPENDENT, /**< New bound/constraint is linearly dependent. */ +RET_LINEARLY_INDEPENDENT, /**< New bound/constraint is linearly independent. */ +RET_LI_RESOLVED, /**< Linear independence of active constraint matrix successfully resolved. (90) */ +RET_ENSURELI_FAILED, /**< Failed to ensure linear independence of active constraint matrix. */ +RET_ENSURELI_FAILED_TQ, /**< Abnormal termination due to TQ factorisation. */ +RET_ENSURELI_FAILED_NOINDEX, /**< QP is infeasible. */ +RET_ENSURELI_FAILED_CYCLING, /**< QP is infeasible. */ +RET_BOUND_ALREADY_ACTIVE, /**< Bound is already active. */ +RET_ALL_BOUNDS_ACTIVE, /**< All bounds are active, no further bound can be added. */ +RET_CONSTRAINT_NOT_ACTIVE, /**< Constraint is not active. */ +RET_BOUND_NOT_ACTIVE, /**< Bound is not active. */ +RET_HESSIAN_NOT_SPD, /**< Projected Hessian matrix not positive definite. */ +RET_HESSIAN_INDEFINITE, /**< Hessian matrix is indefinite. (100) */ +RET_MATRIX_SHIFT_FAILED, /**< Unable to update matrices or to transform vectors. */ +RET_MATRIX_FACTORISATION_FAILED, /**< Unable to calculate new matrix factorisations. */ +RET_PRINT_ITERATION_FAILED, /**< Unable to print information on current iteration. */ +RET_NO_GLOBAL_MESSAGE_OUTPUTFILE, /**< No global message output file initialised. */ +RET_DISABLECONSTRAINTS_FAILED, /**< Unable to disbable constraints. */ +RET_ENABLECONSTRAINTS_FAILED, /**< Unable to enbable constraints. */ +RET_ALREADY_ENABLED, /**< Bound or constraint is already enabled. */ +RET_ALREADY_DISABLED, /**< Bound or constraint is already disabled. */ +RET_NO_HESSIAN_SPECIFIED, /**< No Hessian matrix has been specified. */ +RET_USING_REGULARISATION, /**< Using regularisation as Hessian matrix is not positive definite. (110) */ +RET_EPS_MUST_BE_POSITVE, /**< Eps for regularisation must be sufficiently positive. */ +RET_REGSTEPS_MUST_BE_POSITVE, /**< Maximum number of regularisation steps must be non-negative. */ +RET_HESSIAN_ALREADY_REGULARISED, /**< Hessian has been already regularised. */ +RET_CANNOT_REGULARISE_IDENTITY, /**< Identity Hessian matrix cannot be regularised. */ +RET_CANNOT_REGULARISE_SPARSE, /**< Sparse matrix cannot be regularised as diagonal entry is missing. */ +RET_NO_REGSTEP_NWSR, /**< No additional regularisation step could be performed due to limits. */ +RET_FEWER_REGSTEPS_NWSR, /**< Fewer additional regularisation steps have been performed due to limits. */ +RET_CHOLESKY_OF_ZERO_HESSIAN, /**< Cholesky decomposition of (unregularised) zero Hessian matrix. */ +RET_ZERO_HESSIAN_ASSUMED, /**< Zero Hessian matrix assumed as null pointer passed without specifying hessianType. */ +RET_CONSTRAINTS_ARE_NOT_SCALED, /**< (no longer in use) (120) */ +RET_INITIAL_BOUNDS_STATUS_NYI, /**< (no longer in use) */ +RET_ERROR_IN_CONSTRAINTPRODUCT, /**< Error in user-defined constraint product function. */ +RET_FIX_BOUNDS_FOR_LP, /**< All initial bounds must be fixed when solving an (unregularised) LP. */ +RET_USE_REGULARISATION_FOR_LP, /**< Set options.enableRegularisation=BT_TRUE for solving LPs. */ +/* SQProblem */ +RET_UPDATEMATRICES_FAILED, /**< Unable to update QP matrices. */ +RET_UPDATEMATRICES_FAILED_AS_QP_NOT_SOLVED, /**< Unable to update matrices as previous QP is not solved. */ +/* Utils */ +RET_UNABLE_TO_OPEN_FILE, /**< Unable to open file. */ +RET_UNABLE_TO_WRITE_FILE, /**< Unable to write into file. */ +RET_UNABLE_TO_READ_FILE, /**< Unable to read from file. */ +RET_FILEDATA_INCONSISTENT, /**< File contains inconsistent data. (130) */ +/* Options */ +RET_OPTIONS_ADJUSTED, /**< Options needed to be adjusted for consistency reasons. */ +/* SolutionAnalysis */ +RET_UNABLE_TO_ANALYSE_QPROBLEM, /**< Unable to analyse (S)QProblem(B) object. */ +/* Benchmark */ +RET_NWSR_SET_TO_ONE, /**< Maximum number of working set changes was set to 1. */ +RET_UNABLE_TO_READ_BENCHMARK, /**< Unable to read benchmark data. */ +RET_BENCHMARK_ABORTED, /**< Benchmark aborted. */ +RET_INITIAL_QP_SOLVED, /**< Initial QP solved. */ +RET_QP_SOLUTION_STARTED, /**< Solving QP... */ +RET_BENCHMARK_SUCCESSFUL, /**< Benchmark terminated successfully. */ +/* Sparse matrices */ +RET_NO_DIAGONAL_AVAILABLE, /**< Sparse matrix does not have entries on full diagonal. */ +RET_DIAGONAL_NOT_INITIALISED, /**< Diagonal data of sparse matrix has not been initialised. (140) */ +/* Dropping of infeasible constraints */ +RET_ENSURELI_DROPPED, /**< Linear independence resolved by dropping blocking constraint. */ +/* Simple exitflags */ +RET_SIMPLE_STATUS_P1, /**< QP problem could not be solved within given number of iterations. */ +RET_SIMPLE_STATUS_P0, /**< QP problem solved. */ +RET_SIMPLE_STATUS_M1, /**< QP problem could not be solved due to an internal error. */ +RET_SIMPLE_STATUS_M2, /**< QP problem is infeasible (and thus could not be solved). */ +RET_SIMPLE_STATUS_M3 /**< QP problem is unbounded (and thus could not be solved). (146) */ +} returnValue; + + +/** + * \brief Data structure for entries in global message list. + * + * Data structure for entries in global message list. + * + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + returnValue key; /**< Global return value. */ + const char* data; /**< Corresponding message. */ + VisibilityStatus globalVisibilityStatus; /**< Determines if message can be printed. + * If this value is set to VS_HIDDEN, no message is printed! */ +} ReturnValueList; + + + +/** + * \brief Handles all kind of error messages, warnings and other information. + * + * This class handles all kinds of messages (errors, warnings, infos) initiated + * by qpOASES modules and stores the corresponding global preferences. + * + * \author Hans Joachim Ferreau (thanks to Leonard Wirsching) + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + VisibilityStatus errorVisibility; /**< Error messages visible? */ + VisibilityStatus warningVisibility; /**< Warning messages visible? */ + VisibilityStatus infoVisibility; /**< Info messages visible? */ + + FILE* outputFile; /**< Output file for messages. */ + + int errorCount; /**< Counts number of errors (for nicer output only). */ +} MessageHandling; + + + +/** Constructor which takes the desired output file and desired visibility states. */ +void MessageHandlingCON( MessageHandling* _THIS, + FILE* _outputFile, /**< Output file. */ + VisibilityStatus _errorVisibility, /**< Visibility status for error messages. */ + VisibilityStatus _warningVisibility,/**< Visibility status for warning messages. */ + VisibilityStatus _infoVisibility /**< Visibility status for info messages. */ + ); + +void MessageHandlingCPY( MessageHandling* FROM, + MessageHandling* TO + ); + + +/** Prints an error message(a simplified macro THROWERROR is also provided). \n + * Errors are definied as abnormal events which cause an immediate termination of the current (sub) function. + * Errors of a sub function should be commented by the calling function by means of a warning message + * (if this error does not cause an error of the calling function, either)! + * \return Error number returned by sub function call + */ +returnValue MessageHandling_throwError( MessageHandling* _THIS, + returnValue Enumber, /**< Error number returned by sub function call. */ + const char* additionaltext, /**< Additional error text (0, if none). */ + const char* functionname, /**< Name of function which caused the error. */ + const char* filename, /**< Name of file which caused the error. */ + const unsigned long linenumber, /**< Number of line which caused the error.incompatible binary file */ + VisibilityStatus localVisibilityStatus /**< Determines (locally) if error message can be printed to stderr. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + ); + +/** Prints a warning message (a simplified macro THROWWARNING is also provided). + * Warnings are definied as abnormal events which does NOT cause an immediate termination of the current (sub) function. + * \return Warning number returned by sub function call + */ +returnValue MessageHandling_throwWarning( MessageHandling* _THIS, + returnValue Wnumber, /**< Warning number returned by sub function call. */ + const char* additionaltext, /**< Additional warning text (0, if none). */ + const char* functionname, /**< Name of function which caused the warning. */ + const char* filename, /**< Name of file which caused the warning. */ + const unsigned long linenumber, /**< Number of line which caused the warning. */ + VisibilityStatus localVisibilityStatus /**< Determines (locally) if warning message can be printed to stderr. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + ); + +/** Prints a info message (a simplified macro THROWINFO is also provided). + * \return Info number returned by sub function call + */ +returnValue MessageHandling_throwInfo( MessageHandling* _THIS, + returnValue Inumber, /**< Info number returned by sub function call. */ + const char* additionaltext, /**< Additional warning text (0, if none). */ + const char* functionname, /**< Name of function which submitted the info. */ + const char* filename, /**< Name of file which submitted the info. */ + const unsigned long linenumber, /**< Number of line which submitted the info. */ + VisibilityStatus localVisibilityStatus /**< Determines (locally) if info message can be printed to stderr. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + ); + + +/** Resets all preferences to default values. + * \return SUCCESSFUL_RETURN */ +returnValue MessageHandling_reset( MessageHandling* _THIS ); + + +/** Prints a complete list of all messages to output file. + * \return SUCCESSFUL_RETURN */ +returnValue MessageHandling_listAllMessages( MessageHandling* _THIS ); + + +/** Returns visibility status for error messages. + * \return Visibility status for error messages. */ +static inline VisibilityStatus MessageHandling_getErrorVisibilityStatus( MessageHandling* _THIS ); + +/** Returns visibility status for warning messages. + * \return Visibility status for warning messages. */ +static inline VisibilityStatus MessageHandling_getWarningVisibilityStatus( MessageHandling* _THIS ); + +/** Returns visibility status for info messages. + * \return Visibility status for info messages. */ +static inline VisibilityStatus MessageHandling_getInfoVisibilityStatus( MessageHandling* _THIS ); + +/** Returns pointer to output file. + * \return Pointer to output file. */ +static inline FILE* MessageHandling_getOutputFile( MessageHandling* _THIS ); + +/** Returns error count value. + * \return Error count value. */ +static inline int MessageHandling_getErrorCount( MessageHandling* _THIS ); + + +/** Changes visibility status for error messages. */ +static inline void MessageHandling_setErrorVisibilityStatus( MessageHandling* _THIS, + VisibilityStatus _errorVisibility /**< New visibility status for error messages. */ + ); + +/** Changes visibility status for warning messages. */ +static inline void MessageHandling_setWarningVisibilityStatus( MessageHandling* _THIS, + VisibilityStatus _warningVisibility /**< New visibility status for warning messages. */ + ); + +/** Changes visibility status for info messages. */ +static inline void MessageHandling_setInfoVisibilityStatus( MessageHandling* _THIS, + VisibilityStatus _infoVisibility /**< New visibility status for info messages. */ + ); + +/** Changes output file for messages. */ +static inline void MessageHandling_setOutputFile( MessageHandling* _THIS, + FILE* _outputFile /**< New output file for messages. */ + ); + +/** Changes error count. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENT */ +static inline returnValue MessageHandling_setErrorCount( MessageHandling* _THIS, + int _errorCount /**< New error count value. */ + ); + +/** Provides message text corresponding to given \a returnValue. + * \return String containing message text. */ +const char* MessageHandling_getErrorCodeMessage( MessageHandling* _THIS, + const returnValue _returnValue + ); + + +returnValue MessageHandling_throwMessage( MessageHandling* _THIS, + returnValue RETnumber, /**< Error/warning/info number returned by sub function call. */ + const char* additionaltext, /**< Additional warning text (0, if none). */ + const char* functionname, /**< Name of function which caused the error/warning/info. */ + const char* filename, /**< Name of file which caused the error/warning/info. */ + const unsigned long linenumber, /**< Number of line which caused the error/warning/info. */ + VisibilityStatus localVisibilityStatus, /**< Determines (locally) if info message can be printed to stderr. + * If GLOBAL visibility status of the message is set to VS_HIDDEN, + * no message is printed, anyway! */ + const char* RETstring /**< Leading string of error/warning/info message. */ + ); + + +#ifndef __FILE__ + /** Ensures that __FILE__ macro is defined. */ + #define __FILE__ 0 +#endif + +#ifndef __LINE__ + /** Ensures that __LINE__ macro is defined. */ + #define __LINE__ 0 +#endif + +/** Define __FUNC__ macro providing current function for debugging. */ +/*#define __FUNC__ 0*/ +#define __FUNC__ ("(no function name provided)") +/*#define __FUNC__ __func__*/ +/*#define __FUNC__ __FUNCTION__*/ + + +/** Short version of throwError with default values, only returnValue is needed */ +#define THROWERROR(retval) ( MessageHandling_throwError( qpOASES_getGlobalMessageHandler(),(retval),0,__FUNC__,__FILE__,__LINE__,VS_VISIBLE) ) + +/** Short version of throwWarning with default values, only returnValue is needed */ +#define THROWWARNING(retval) ( MessageHandling_throwWarning( qpOASES_getGlobalMessageHandler(),(retval),0,__FUNC__,__FILE__,__LINE__,VS_VISIBLE) ) + +/** Short version of throwInfo with default values, only returnValue is needed */ +#define THROWINFO(retval) ( MessageHandling_throwInfo( qpOASES_getGlobalMessageHandler(),(retval),0,__FUNC__,__FILE__,__LINE__,VS_VISIBLE) ) + + +/** Returns a pointer to global message handler. + * \return Pointer to global message handler. + */ +MessageHandling* qpOASES_getGlobalMessageHandler( ); + + +/* + * g e t E r r o r V i s i b i l i t y S t a t u s + */ +static inline VisibilityStatus MessageHandling_getErrorVisibilityStatus( MessageHandling* _THIS ) +{ + return _THIS->errorVisibility; +} + + +/* + * g e t W a r n i n g V i s i b i l i t y S t a t u s + */ +static inline VisibilityStatus MessageHandling_getWarningVisibilityStatus( MessageHandling* _THIS ) +{ + return _THIS->warningVisibility; +} + + +/* + * g e t I n f o V i s i b i l i t y S t a t u s + */ +static inline VisibilityStatus MessageHandling_getInfoVisibilityStatus( MessageHandling* _THIS ) +{ + return _THIS->infoVisibility; +} + + +/* + * g e t O u t p u t F i l e + */ +static inline FILE* MessageHandling_getOutputFile( MessageHandling* _THIS ) +{ + return _THIS->outputFile; +} + + +/* + * g e t E r r o r C o u n t + */ +static inline int MessageHandling_getErrorCount( MessageHandling* _THIS ) +{ + return _THIS->errorCount; +} + + +/* + * s e t E r r o r V i s i b i l i t y S t a t u s + */ +static inline void MessageHandling_setErrorVisibilityStatus( MessageHandling* _THIS, VisibilityStatus _errorVisibility ) +{ + _THIS->errorVisibility = _errorVisibility; +} + + +/* + * s e t W a r n i n g V i s i b i l i t y S t a t u s + */ +static inline void MessageHandling_setWarningVisibilityStatus( MessageHandling* _THIS, VisibilityStatus _warningVisibility ) +{ + _THIS->warningVisibility = _warningVisibility; +} + + +/* + * s e t I n f o V i s i b i l i t y S t a t u s + */ +static inline void MessageHandling_setInfoVisibilityStatus( MessageHandling* _THIS, VisibilityStatus _infoVisibility ) +{ + _THIS->infoVisibility = _infoVisibility; +} + + +/* + * s e t O u t p u t F i l e + */ +static inline void MessageHandling_setOutputFile( MessageHandling* _THIS, FILE* _outputFile ) +{ + _THIS->outputFile = _outputFile; +} + + +/* + * s e t E r r o r C o u n t + */ +static inline returnValue MessageHandling_setErrorCount( MessageHandling* _THIS, int _errorCount ) +{ + if ( _errorCount >= 0 ) + { + _THIS->errorCount = _errorCount; + return SUCCESSFUL_RETURN; + } + else + return RET_INVALID_ARGUMENTS; +} + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_MESSAGEHANDLING_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Options.h b/third_party/acados/include/qpOASES_e/Options.h new file mode 100644 index 0000000000..ca8086d2cc --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Options.h @@ -0,0 +1,153 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Options.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the Options class designed to manage user-specified + * options for solving a QProblem. + */ + + +#ifndef QPOASES_OPTIONS_H +#define QPOASES_OPTIONS_H + + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** + * \brief Manages all user-specified options for solving QPs. + * + * This class manages all user-specified options used for solving + * quadratic programs. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + PrintLevel printLevel; /**< Print level. */ + + BooleanType enableRamping; /**< Specifies whether ramping shall be enabled or not. */ + BooleanType enableFarBounds; /**< Specifies whether far bounds shall be used or not. */ + BooleanType enableFlippingBounds; /**< Specifies whether flipping bounds shall be used or not. */ + BooleanType enableRegularisation; /**< Specifies whether Hessian matrix shall be regularised in case semi-definiteness is detected. */ + BooleanType enableFullLITests; /**< Specifies whether condition-hardened LI test shall be used or not. */ + BooleanType enableNZCTests; /**< Specifies whether nonzero curvature tests shall be used. */ + int enableDriftCorrection; /**< Specifies the frequency of drift corrections (0 = off). */ + int enableCholeskyRefactorisation; /**< Specifies the frequency of full refactorisation of proj. Hessian (otherwise updates). */ + BooleanType enableEqualities; /**< Specifies whether equalities shall be always treated as active constraints. */ + + real_t terminationTolerance; /**< Termination tolerance. */ + real_t boundTolerance; /**< Lower/upper (constraints') bound tolerance (an inequality constraint whose lower and upper bounds differ by less is regarded to be an equality constraint). */ + real_t boundRelaxation; /**< Offset for relaxing (constraints') bounds at beginning of an initial homotopy. It is also as initial value for far bounds. */ + real_t epsNum; /**< Numerator tolerance for ratio tests. */ + real_t epsDen; /**< Denominator tolerance for ratio tests. */ + real_t maxPrimalJump; /**< Maximum allowed jump in primal variables in nonzero curvature tests. */ + real_t maxDualJump; /**< Maximum allowed jump in dual variables in linear independence tests. */ + + real_t initialRamping; /**< Start value for Ramping Strategy. */ + real_t finalRamping; /**< Final value for Ramping Strategy. */ + real_t initialFarBounds; /**< Initial size of Far Bounds. */ + real_t growFarBounds; /**< Factor to grow Far Bounds. */ + SubjectToStatus initialStatusBounds; /**< Initial status of bounds at first iteration. */ + real_t epsFlipping; /**< Tolerance of squared Cholesky diagonal factor which triggers flipping bound. */ + int numRegularisationSteps; /**< Maximum number of successive regularisation steps. */ + real_t epsRegularisation; /**< Scaling factor of identity matrix used for Hessian regularisation. */ + int numRefinementSteps; /**< Maximum number of iterative refinement steps. */ + real_t epsIterRef; /**< Early termination tolerance for iterative refinement. */ + real_t epsLITests; /**< Tolerance for linear independence tests. */ + real_t epsNZCTests; /**< Tolerance for nonzero curvature tests. */ + + BooleanType enableDropInfeasibles; /**< ... */ + int dropBoundPriority; /**< ... */ + int dropEqConPriority; /**< ... */ + int dropIneqConPriority; /**< ... */ +} Options; + + +void OptionsCON( Options* _THIS + ); + +/** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ +void OptionsCPY( Options* FROM, + Options* TO + ); + + +/** Sets all options to default values. + * \return SUCCESSFUL_RETURN */ +returnValue Options_setToDefault( Options* _THIS + ); + +/** Sets all options to values resulting in maximum reliabilty. + * \return SUCCESSFUL_RETURN */ +returnValue Options_setToReliable( Options* _THIS + ); + +/** Sets all options to values resulting in minimum solution time. + * \return SUCCESSFUL_RETURN */ +returnValue Options_setToMPC( Options* _THIS + ); + +/** Same as setToMPC( ), for ensuring backwards compatibility. + * \return SUCCESSFUL_RETURN */ +returnValue Options_setToFast( Options* _THIS + ); + + +/** Ensures that all options have consistent values by automatically + * adjusting inconsistent ones. + * Note: This routine cannot (and does not try to) ensure that values + * are set to reasonable values that make the QP solution work! + * \return SUCCESSFUL_RETURN \n + * RET_OPTIONS_ADJUSTED */ +returnValue Options_ensureConsistency( Options* _THIS + ); + + +/** Prints values of all options. + * \return SUCCESSFUL_RETURN */ +returnValue Options_print( Options* _THIS + ); + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_OPTIONS_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/QProblem.h b/third_party/acados/include/qpOASES_e/QProblem.h new file mode 100644 index 0000000000..91a4a6f396 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/QProblem.h @@ -0,0 +1,2369 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/QProblem.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the QProblem class which is able to use the newly + * developed online active set strategy for parametric quadratic programming. + */ + + + +#ifndef QPOASES_QPROBLEM_H +#define QPOASES_QPROBLEM_H + + +#include +#include +#include +#include +#include +#include + + +BEGIN_NAMESPACE_QPOASES + +typedef struct { + Bounds *auxiliaryBounds; + Constraints *auxiliaryConstraints; + + real_t *ub_new_far; + real_t *lb_new_far; + real_t *ubA_new_far; + real_t *lbA_new_far; + + real_t *g_new; + real_t *lb_new; + real_t *ub_new; + real_t *lbA_new; + real_t *ubA_new; + + real_t *g_new2; + real_t *lb_new2; + real_t *ub_new2; + real_t *lbA_new2; + real_t *ubA_new2; + + real_t *delta_xFX5; + real_t *delta_xFR5; + real_t *delta_yAC5; + real_t *delta_yFX5; + + real_t *Hx; + + real_t *_H; + + real_t *g_original; + real_t *lb_original; + real_t *ub_original; + real_t *lbA_original; + real_t *ubA_original; + + real_t *delta_xFR; + real_t *delta_xFX; + real_t *delta_yAC; + real_t *delta_yFX; + real_t *delta_g; + real_t *delta_lb; + real_t *delta_ub; + real_t *delta_lbA; + real_t *delta_ubA; + + real_t *gMod; + + real_t *aFR; + real_t *wZ; + + real_t *delta_g2; + real_t *delta_xFX2; + real_t *delta_xFR2; + real_t *delta_yAC2; + real_t *delta_yFX2; + real_t *nul; + real_t *Arow; + + real_t *xiC; + real_t *xiC_TMP; + real_t *xiB; + real_t *Arow2; + real_t *num; + + real_t *w; + real_t *tmp; + + real_t *delta_g3; + real_t *delta_xFX3; + real_t *delta_xFR3; + real_t *delta_yAC3; + real_t *delta_yFX3; + real_t *nul2; + + real_t *xiC2; + real_t *xiC_TMP2; + real_t *xiB2; + real_t *num2; + + real_t *Hz; + real_t *z; + real_t *ZHz; + real_t *r; + + real_t *tmp2; + real_t *Hz2; + real_t *z2; + real_t *r2; + real_t *rhs; + + real_t *delta_xFX4; + real_t *delta_xFR4; + real_t *delta_yAC4; + real_t *delta_yFX4; + real_t *nul3; + real_t *ek; + real_t *x_W; + real_t *As; + real_t *Ax_W; + + real_t *num3; + real_t *den; + real_t *delta_Ax_l; + real_t *delta_Ax_u; + real_t *delta_Ax; + real_t *delta_x; + + real_t *_A; + + real_t *grad; + real_t *AX; +} QProblem_ws; + +int QProblem_ws_calculateMemorySize( unsigned int nV, unsigned int nC ); + +char *QProblem_ws_assignMemory( unsigned int nV, unsigned int nC, QProblem_ws **mem, void *raw_memory ); + +QProblem_ws *QProblem_ws_createMemory( unsigned int nV, unsigned int nC ); + +/** + * \brief Implements the online active set strategy for QPs with general constraints. + * + * A class for setting up and solving quadratic programs. The main feature is + * the possibily to use the newly developed online active set strategy for + * parametric quadratic programming. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + QProblem_ws *ws; /**< Workspace */ + Bounds *bounds; /**< Data structure for problem's bounds. */ + Constraints *constraints; /**< Data structure for problem's constraints. */ + Flipper *flipper; /**< Struct for making a temporary copy of the matrix factorisations. */ + + DenseMatrix* H; /**< Hessian matrix pointer. */ + DenseMatrix* A; /**< Constraint matrix pointer. */ + + Options options; /**< Struct containing all user-defined options for solving QPs. */ + TabularOutput tabularOutput; /**< Struct storing information for tabular output (printLevel == PL_TABULAR). */ + + real_t *g; /**< Gradient. */ + + real_t *lb; /**< Lower bound vector (on variables). */ + real_t *ub; /**< Upper bound vector (on variables). */ + real_t *lbA; /**< Lower constraints' bound vector. */ + real_t *ubA; /**< Upper constraints' bound vector. */ + + real_t *R; /**< Cholesky factor of H (i.e. H = R^T*R). */ + + real_t *T; /**< Reverse triangular matrix, A = [0 T]*Q'. */ + real_t *Q; /**< Orthonormal quadratic matrix, A = [0 T]*Q'. */ + + real_t *Ax; /**< Stores the current A*x \n + * (for increased efficiency only). */ + real_t *Ax_l; /**< Stores the current distance to lower constraints' bounds A*x-lbA \n + * (for increased efficiency only). */ + real_t *Ax_u; /**< Stores the current distance to lower constraints' bounds ubA-A*x \n + * (for increased efficiency only). */ + + real_t *x; /**< Primal solution vector. */ + real_t *y; /**< Dual solution vector. */ + + real_t *delta_xFR_TMP; /**< Temporary for determineStepDirection */ + real_t *tempA; /**< Temporary for determineStepDirection. */ + real_t *tempB; /**< Temporary for determineStepDirection. */ + real_t *ZFR_delta_xFRz; /**< Temporary for determineStepDirection. */ + real_t *delta_xFRy; /**< Temporary for determineStepDirection. */ + real_t *delta_xFRz; /**< Temporary for determineStepDirection. */ + real_t *delta_yAC_TMP; /**< Temporary for determineStepDirection. */ + + ConstraintProduct constraintProduct; /**< Pointer to user-defined constraint product function. */ + + real_t tau; /**< Last homotopy step length. */ + real_t regVal; /**< Holds the offset used to regularise Hessian matrix (zero by default). */ + + real_t ramp0; /**< Start value for Ramping Strategy. */ + real_t ramp1; /**< Final value for Ramping Strategy. */ + + QProblemStatus status; /**< Current status of the solution process. */ + HessianType hessianType; /**< Type of Hessian matrix. */ + + BooleanType haveCholesky; /**< Flag indicating whether Cholesky decomposition has already been setup. */ + BooleanType infeasible; /**< QP infeasible? */ + BooleanType unbounded; /**< QP unbounded? */ + + int rampOffset; /**< Offset index for Ramping. */ + unsigned int count; /**< Counts the number of hotstart function calls (internal usage only!). */ + + int sizeT; /**< Matrix T is stored in a (sizeT x sizeT) array. */ +} QProblem; + +int QProblem_calculateMemorySize( unsigned int nV, unsigned int nC ); + +char *QProblem_assignMemory( unsigned int nV, unsigned int nC, QProblem **mem, void *raw_memory ); + +QProblem *QProblem_createMemory( unsigned int nV, unsigned int nC ); + + +/** Constructor which takes the QP dimension and Hessian type + * information. If the Hessian is the zero (i.e. HST_ZERO) or the + * identity matrix (i.e. HST_IDENTITY), respectively, no memory + * is allocated for it and a NULL pointer can be passed for it + * to the init() functions. */ +void QProblemCON( QProblem* _THIS, + int _nV, /**< Number of variables. */ + int _nC, /**< Number of constraints. */ + HessianType _hessianType /**< Type of Hessian matrix. */ + ); + +/** Copies all members from given rhs object. + * \return SUCCESSFUL_RETURN */ +void QProblemCPY( QProblem* FROM, + QProblem* TO + ); + + +/** Clears all data structures of QProblem except for QP data. + * \return SUCCESSFUL_RETURN \n + RET_RESET_FAILED */ +returnValue QProblem_reset( QProblem* _THIS ); + + +/** Initialises a QP problem with given QP data and tries to solve it + * using at most nWSR iterations. + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_initM( QProblem* _THIS, + DenseMatrix *_H, /**< Hessian matrix. */ + const real_t* const _g, /**< Gradient vector. */ + DenseMatrix *_A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation (if pointer passed). */ + ); + + +/** Initialises a QP problem with given QP data and tries to solve it + * using at most nWSR iterations. + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_init( QProblem* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + real_t* const _A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation (if pointer passed). */ + ); + +/** Initialises a QP problem with given QP data to be read from files and tries to solve it + * using at most nWSR iterations. + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ +returnValue QProblem_initF( QProblem* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const A_file, /**< Name of file where constraint matrix is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bound vector. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation (if pointer passed). */ + ); + +/** Initialises a QP problem with given QP data and tries to solve it + * using at most nWSR iterations. Depending on the parameter constellation it: \n + * 1. 0, 0, 0 : starts with xOpt = 0, yOpt = 0 and gB/gC empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : starts with xOpt, yOpt = 0 and obtain gB/gC by "clipping", \n + * 3. 0, yOpt, 0 : starts with xOpt = 0, yOpt and obtain gB/gC from yOpt != 0, \n + * 4. 0, 0, gB/gC: starts with xOpt = 0, yOpt = 0 and gB/gC, \n + * 5. xOpt, yOpt, 0 : starts with xOpt, yOpt and obtain gB/gC from yOpt != 0, \n + * 6. xOpt, 0, gB/gC: starts with xOpt, yOpt = 0 and gB/gC, \n + * 7. xOpt, yOpt, gB/gC: starts with xOpt, yOpt and gB/gC (assume them to be consistent!) + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_initMW( QProblem* _THIS, + DenseMatrix *_H, /**< Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + DenseMatrix *_A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + * Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. \n + (If a null pointer is passed, the old dual solution is kept!) */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + Constraints* const guessedConstraints, /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + const real_t* const _R /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. + The Cholesky factor must be stored in a real_t array of size nV*nV + in row-major format. Note: Only used if xOpt/yOpt and gB are NULL! \n + (If a null pointer is passed, Cholesky decomposition is computed internally!) */ + ); + +/** Initialises a QP problem with given QP data and tries to solve it + * using at most nWSR iterations. Depending on the parameter constellation it: \n + * 1. 0, 0, 0 : starts with xOpt = 0, yOpt = 0 and gB/gC empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : starts with xOpt, yOpt = 0 and obtain gB/gC by "clipping", \n + * 3. 0, yOpt, 0 : starts with xOpt = 0, yOpt and obtain gB/gC from yOpt != 0, \n + * 4. 0, 0, gB/gC: starts with xOpt = 0, yOpt = 0 and gB/gC, \n + * 5. xOpt, yOpt, 0 : starts with xOpt, yOpt and obtain gB/gC from yOpt != 0, \n + * 6. xOpt, 0, gB/gC: starts with xOpt, yOpt = 0 and gB/gC, \n + * 7. xOpt, yOpt, gB/gC: starts with xOpt, yOpt and gB/gC (assume them to be consistent!) + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_initW( QProblem* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + real_t* const _A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA, /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + * Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. \n + (If a null pointer is passed, the old dual solution is kept!) */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + Constraints* const guessedConstraints, /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + const real_t* const _R /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. + The Cholesky factor must be stored in a real_t array of size nV*nV + in row-major format. Note: Only used if xOpt/yOpt and gB are NULL! \n + (If a null pointer is passed, Cholesky decomposition is computed internally!) */ + ); + +/** Initialises a QP problem with given QP data to be ream from files and tries to solve it + * using at most nWSR iterations. Depending on the parameter constellation it: \n + * 1. 0, 0, 0 : starts with xOpt = 0, yOpt = 0 and gB/gC empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : starts with xOpt, yOpt = 0 and obtain gB/gC by "clipping", \n + * 3. 0, yOpt, 0 : starts with xOpt = 0, yOpt and obtain gB/gC from yOpt != 0, \n + * 4. 0, 0, gB/gC: starts with xOpt = 0, yOpt = 0 and gB/gC, \n + * 5. xOpt, yOpt, 0 : starts with xOpt, yOpt and obtain gB/gC from yOpt != 0, \n + * 6. xOpt, 0, gB/gC: starts with xOpt, yOpt = 0 and gB/gC, \n + * 7. xOpt, yOpt, gB/gC: starts with xOpt, yOpt and gB/gC (assume them to be consistent!) + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ +returnValue QProblem_initFW( QProblem* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const A_file, /**< Name of file where constraint matrix is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bound vector. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. \n + (If a null pointer is passed, the old dual solution is kept!) */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + Constraints* const guessedConstraints, /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + const char* const R_file /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. + The Cholesky factor must be stored in a real_t array of size nV*nV + in row-major format. Note: Only used if xOpt/yOpt and gB are NULL! \n + (If a null pointer is passed, Cholesky decomposition is computed internally!) */ + ); + +/** Solves an initialised QP sequence using the online active set strategy. + * QP solution is started from previous solution. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblem_hotstart( QProblem* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + ); + +/** Solves an initialised QP sequence using the online active set strategy, + * where QP data is read from files. QP solution is started from previous solution. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_hotstartF( QProblem* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + ); + +/** Solves an initialised QP sequence using the online active set strategy. + * By default, QP solution is started from previous solution. If a guess + * for the working set is provided, an initialised homotopy is performed. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED */ +returnValue QProblem_hotstartW( QProblem* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, the previous working set of bounds is kept!) */ + Constraints* const guessedConstraints /**< Optimal working set of constraints for solution (xOpt,yOpt). \n + (If a null pointer is passed, the previous working set of constraints is kept!) */ + ); + +/** Solves an initialised QP sequence using the online active set strategy, + * where QP data is read from files. + * By default, QP solution is started from previous solution. If a guess + * for the working set is provided, an initialised homotopy is performed. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_hotstartFW( QProblem* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, the previous working set of bounds is kept!) */ + Constraints* const guessedConstraints /**< Optimal working set of constraints for solution (xOpt,yOpt). \n + (If a null pointer is passed, the previous working set of constraints is kept!) */ + ); + + +/** Solves using the current working set + * \return SUCCESSFUL_RETURN \n + * RET_STEPDIRECTION_FAILED_TQ \n + * RET_STEPDIRECTION_FAILED_CHOLESKY \n + * RET_INVALID_ARGUMENTS */ +returnValue QProblem_solveCurrentEQP ( QProblem* _THIS, + const int n_rhs, /**< Number of consecutive right hand sides */ + const real_t* g_in, /**< Gradient of neighbouring QP to be solved. */ + const real_t* lb_in, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* ub_in, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* lbA_in, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* ubA_in, /**< Upper constraints' bounds of neighbouring QP to be solved. \n */ + real_t* x_out, /**< Output: Primal solution */ + real_t* y_out /**< Output: Dual solution */ + ); + + + +/** Returns current constraints object of the QP (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblem_getConstraints( QProblem* _THIS, + Constraints* _constraints /** Output: Constraints object. */ + ); + + +/** Returns the number of constraints. + * \return Number of constraints. */ +static inline int QProblem_getNC( QProblem* _THIS ); + +/** Returns the number of (implicitly defined) equality constraints. + * \return Number of (implicitly defined) equality constraints. */ +static inline int QProblem_getNEC( QProblem* _THIS ); + +/** Returns the number of active constraints. + * \return Number of active constraints. */ +static inline int QProblem_getNAC( QProblem* _THIS ); + +/** Returns the number of inactive constraints. + * \return Number of inactive constraints. */ +static inline int QProblem_getNIAC( QProblem* _THIS ); + +/** Returns the dimension of null space. + * \return Dimension of null space. */ +int QProblem_getNZ( QProblem* _THIS ); + + +/** Returns the dual solution vector (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ +returnValue QProblem_getDualSolution( QProblem* _THIS, + real_t* const yOpt /**< Output: Dual solution vector (if QP has been solved). */ + ); + + +/** Defines user-defined routine for calculating the constraint product A*x + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblem_setConstraintProduct( QProblem* _THIS, + ConstraintProduct _constraintProduct + ); + + +/** Prints concise list of properties of the current QP. + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblem_printProperties( QProblem* _THIS ); + + + +/** Writes a vector with the state of the working set +* \return SUCCESSFUL_RETURN */ +returnValue QProblem_getWorkingSet( QProblem* _THIS, + real_t* workingSet /** Output: array containing state of the working set. */ + ); + +/** Writes a vector with the state of the working set of bounds + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue QProblem_getWorkingSetBounds( QProblem* _THIS, + real_t* workingSetB /** Output: array containing state of the working set of bounds. */ + ); + +/** Writes a vector with the state of the working set of constraints + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue QProblem_getWorkingSetConstraints( QProblem* _THIS, + real_t* workingSetC /** Output: array containing state of the working set of constraints. */ + ); + + +/** Returns current bounds object of the QP (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblem_getBounds( QProblem* _THIS, + Bounds* _bounds /** Output: Bounds object. */ + ); + + +/** Returns the number of variables. + * \return Number of variables. */ +static inline int QProblem_getNV( QProblem* _THIS ); + +/** Returns the number of free variables. + * \return Number of free variables. */ +static inline int QProblem_getNFR( QProblem* _THIS ); + +/** Returns the number of fixed variables. + * \return Number of fixed variables. */ +static inline int QProblem_getNFX( QProblem* _THIS ); + +/** Returns the number of implicitly fixed variables. + * \return Number of implicitly fixed variables. */ +static inline int QProblem_getNFV( QProblem* _THIS ); + + +/** Returns the optimal objective function value. + * \return finite value: Optimal objective function value (QP was solved) \n + +infinity: QP was not yet solved */ +real_t QProblem_getObjVal( QProblem* _THIS ); + +/** Returns the objective function value at an arbitrary point x. + * \return Objective function value at point x */ +real_t QProblem_getObjValX( QProblem* _THIS, + const real_t* const _x /**< Point at which the objective function shall be evaluated. */ + ); + +/** Returns the primal solution vector. + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ +returnValue QProblem_getPrimalSolution( QProblem* _THIS, + real_t* const xOpt /**< Output: Primal solution vector (if QP has been solved). */ + ); + + +/** Returns status of the solution process. + * \return Status of solution process. */ +static inline QProblemStatus QProblem_getStatus( QProblem* _THIS ); + + +/** Returns if the QProblem object is initialised. + * \return BT_TRUE: QProblem initialised \n + BT_FALSE: QProblem not initialised */ +static inline BooleanType QProblem_isInitialised( QProblem* _THIS ); + +/** Returns if the QP has been solved. + * \return BT_TRUE: QProblem solved \n + BT_FALSE: QProblem not solved */ +static inline BooleanType QProblem_isSolved( QProblem* _THIS ); + +/** Returns if the QP is infeasible. + * \return BT_TRUE: QP infeasible \n + BT_FALSE: QP feasible (or not known to be infeasible!) */ +static inline BooleanType QProblem_isInfeasible( QProblem* _THIS ); + +/** Returns if the QP is unbounded. + * \return BT_TRUE: QP unbounded \n + BT_FALSE: QP unbounded (or not known to be unbounded!) */ +static inline BooleanType QProblem_isUnbounded( QProblem* _THIS ); + + +/** Returns Hessian type flag (type is not determined due to _THIS call!). + * \return Hessian type. */ +static inline HessianType QProblem_getHessianType( QProblem* _THIS ); + +/** Changes the print level. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblem_setHessianType( QProblem* _THIS, + HessianType _hessianType /**< New Hessian type. */ + ); + +/** Returns if the QP has been internally regularised. + * \return BT_TRUE: Hessian is internally regularised for QP solution \n + BT_FALSE: No internal Hessian regularisation is used for QP solution */ +static inline BooleanType QProblem_usingRegularisation( QProblem* _THIS ); + +/** Returns current options struct. + * \return Current options struct. */ +static inline Options QProblem_getOptions( QProblem* _THIS ); + +/** Overrides current options with given ones. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblem_setOptions( QProblem* _THIS, + Options _options /**< New options. */ + ); + +/** Returns the print level. + * \return Print level. */ +static inline PrintLevel QProblem_getPrintLevel( QProblem* _THIS ); + +/** Changes the print level. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_setPrintLevel( QProblem* _THIS, + PrintLevel _printlevel /**< New print level. */ + ); + + +/** Returns the current number of QP problems solved. + * \return Number of QP problems solved. */ +static inline unsigned int QProblem_getCount( QProblem* _THIS ); + +/** Resets QP problem counter (to zero). + * \return SUCCESSFUL_RETURN. */ +static inline returnValue QProblem_resetCounter( QProblem* _THIS ); + + +/** Prints a list of all options and their current values. + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblem_printOptions( QProblem* _THIS ); + + +/** Solves a QProblem whose QP data is assumed to be stored in the member variables. + * A guess for its primal/dual optimal solution vectors and the corresponding + * working sets of bounds and constraints can be provided. + * Note: This function is internally called by all init functions! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_TQ \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED */ +returnValue QProblem_solveInitialQP( QProblem* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector.*/ + const real_t* const yOpt, /**< Optimal dual solution vector. */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + Constraints* const guessedConstraints, /**< Optimal working set of constraints for solution (xOpt,yOpt). */ + const real_t* const _R, /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + * Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + * Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + ); + +/** Solves QProblem using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblem_solveQP( QProblem* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + int nWSRperformed, /**< Number of working set recalculations already performed to solve + this QP within previous solveQP() calls. This number is + always zero, except for successive calls from solveRegularisedQP() + or when using the far bound strategy. */ + BooleanType isFirstCall /**< Indicating whether this is the first call for current QP. */ + ); + + +/** Solves QProblem using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblem_solveRegularisedQP( QProblem* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const lbA_new, /**< Lower constraints' bounds of neighbouring QP to be solved. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const ubA_new, /**< Upper constraints' bounds of neighbouring QP to be solved. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + int nWSRperformed, /**< Number of working set recalculations already performed to solve + this QP within previous solveRegularisedQP() calls. This number is + always zero, except for successive calls when using the far bound strategy. */ + BooleanType isFirstCall /**< Indicating whether this is the first call for current QP. */ + ); + + +/** Determines type of existing constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ +returnValue QProblem_setupSubjectToType( QProblem* _THIS ); + +/** Determines type of new constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ +returnValue QProblem_setupSubjectToTypeNew( QProblem* _THIS, + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + const real_t* const lbA_new, /**< New lower constraints' bounds. */ + const real_t* const ubA_new /**< New upper constraints' bounds. */ + ); + +/** Computes the Cholesky decomposition of the projected Hessian (i.e. R^T*R = Z^T*H*Z). + * Note: If Hessian turns out not to be positive definite, the Hessian type + * is set to HST_SEMIDEF accordingly. + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ +returnValue QProblem_computeProjectedCholesky( QProblem* _THIS ); + +/** Computes initial Cholesky decomposition of the projected Hessian making + * use of the function setupCholeskyDecomposition() or setupCholeskyDecompositionProjected(). + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ +returnValue QProblem_setupInitialCholesky( QProblem* _THIS ); + +/** Initialises TQ factorisation of A (i.e. A*Q = [0 T]) if NO constraint is active. + * \return SUCCESSFUL_RETURN \n + RET_INDEXLIST_CORRUPTED */ +returnValue QProblem_setupTQfactorisation( QProblem* _THIS ); + + +/** Obtains the desired working set for the auxiliary initial QP in + * accordance with the user specifications + * (assumes that member AX has already been initialised!) + * \return SUCCESSFUL_RETURN \n + RET_OBTAINING_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_obtainAuxiliaryWorkingSet( QProblem* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + Bounds* const guessedBounds, /**< Guessed working set of bounds for solution (xOpt,yOpt). */ + Constraints* const guessedConstraints, /**< Guessed working set for solution (xOpt,yOpt). */ + Bounds* auxiliaryBounds, /**< Input: Allocated bound object. \n + * Ouput: Working set of constraints for auxiliary QP. */ + Constraints* auxiliaryConstraints /**< Input: Allocated bound object. \n + * Ouput: Working set for auxiliary QP. */ + ); + +/** Sets up bound and constraints data structures according to auxiliaryBounds/Constraints. + * (If the working set shall be setup afresh, make sure that + * bounds and constraints data structure have been resetted + * and the TQ factorisation has been initialised!) + * \return SUCCESSFUL_RETURN \n + RET_SETUP_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS \n + RET_UNKNOWN_BUG */ +returnValue QProblem_setupAuxiliaryWorkingSet( QProblem* _THIS, + Bounds* const auxiliaryBounds, /**< Working set of bounds for auxiliary QP. */ + Constraints* const auxiliaryConstraints, /**< Working set of constraints for auxiliary QP. */ + BooleanType setupAfresh /**< Flag indicating if given working set shall be + * setup afresh or by updating the current one. */ + ); + +/** Sets up the optimal primal/dual solution of the auxiliary initial QP. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_setupAuxiliaryQPsolution( QProblem* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + const real_t* const yOpt /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + ); + +/** Sets up gradient of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS, CONSTRAINTS have already been initialised!). + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_setupAuxiliaryQPgradient( QProblem* _THIS ); + +/** Sets up (constraints') bounds of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS, CONSTRAINTS have already been initialised!). + * \return SUCCESSFUL_RETURN \n + RET_UNKNOWN_BUG */ +returnValue QProblem_setupAuxiliaryQPbounds( QProblem* _THIS, + Bounds* const auxiliaryBounds, /**< Working set of bounds for auxiliary QP. */ + Constraints* const auxiliaryConstraints, /**< Working set of constraints for auxiliary QP. */ + BooleanType useRelaxation /**< Flag indicating if inactive (constraints') bounds shall be relaxed. */ + ); + + +/** Adds a constraint to active set. + * \return SUCCESSFUL_RETURN \n + RET_ADDCONSTRAINT_FAILED \n + RET_ADDCONSTRAINT_FAILED_INFEASIBILITY \n + RET_ENSURELI_FAILED */ +returnValue QProblem_addConstraint( QProblem* _THIS, + int number, /**< Number of constraint to be added to active set. */ + SubjectToStatus C_status, /**< Status of new active constraint. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType ensureLI /**< Ensure linear independence by exchange rules by default. */ + ); + +/** Checks if new active constraint to be added is linearly dependent from + * from row of the active constraints matrix. + * \return RET_LINEARLY_DEPENDENT \n + RET_LINEARLY_INDEPENDENT \n + RET_INDEXLIST_CORRUPTED */ +returnValue QProblem_addConstraint_checkLI( QProblem* _THIS, + int number /**< Number of constraint to be added to active set. */ + ); + +/** Ensures linear independence of constraint matrix when a new constraint is added. + * To _THIS end a bound or constraint is removed simultaneously if necessary. + * \return SUCCESSFUL_RETURN \n + RET_LI_RESOLVED \n + RET_ENSURELI_FAILED \n + RET_ENSURELI_FAILED_TQ \n + RET_ENSURELI_FAILED_NOINDEX \n + RET_REMOVE_FROM_ACTIVESET */ +returnValue QProblem_addConstraint_ensureLI( QProblem* _THIS, + int number, /**< Number of constraint to be added to active set. */ + SubjectToStatus C_status /**< Status of new active bound. */ + ); + +/** Adds a bound to active set. + * \return SUCCESSFUL_RETURN \n + RET_ADDBOUND_FAILED \n + RET_ADDBOUND_FAILED_INFEASIBILITY \n + RET_ENSURELI_FAILED */ +returnValue QProblem_addBound( QProblem* _THIS, + int number, /**< Number of bound to be added to active set. */ + SubjectToStatus B_status, /**< Status of new active bound. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType ensureLI /**< Ensure linear independence by exchange rules by default. */ + ); + +/** Checks if new active bound to be added is linearly dependent from + * from row of the active constraints matrix. + * \return RET_LINEARLY_DEPENDENT \n + RET_LINEARLY_INDEPENDENT */ +returnValue QProblem_addBound_checkLI( QProblem* _THIS, + int number /**< Number of bound to be added to active set. */ + ); + +/** Ensures linear independence of constraint matrix when a new bound is added. + * To _THIS end a bound or constraint is removed simultaneously if necessary. + * \return SUCCESSFUL_RETURN \n + RET_LI_RESOLVED \n + RET_ENSURELI_FAILED \n + RET_ENSURELI_FAILED_TQ \n + RET_ENSURELI_FAILED_NOINDEX \n + RET_REMOVE_FROM_ACTIVESET */ +returnValue QProblem_addBound_ensureLI( QProblem* _THIS, + int number, /**< Number of bound to be added to active set. */ + SubjectToStatus B_status /**< Status of new active bound. */ + ); + +/** Removes a constraint from active set. + * \return SUCCESSFUL_RETURN \n + RET_CONSTRAINT_NOT_ACTIVE \n + RET_REMOVECONSTRAINT_FAILED \n + RET_HESSIAN_NOT_SPD */ +returnValue QProblem_removeConstraint( QProblem* _THIS, + int number, /**< Number of constraint to be removed from active set. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType allowFlipping, /**< Flag indicating if flipping bounds are allowed. */ + BooleanType ensureNZC /**< Flag indicating if non-zero curvature is ensured by exchange rules. */ + ); + +/** Removes a bounds from active set. + * \return SUCCESSFUL_RETURN \n + RET_BOUND_NOT_ACTIVE \n + RET_HESSIAN_NOT_SPD \n + RET_REMOVEBOUND_FAILED */ +returnValue QProblem_removeBound( QProblem* _THIS, + int number, /**< Number of bound to be removed from active set. */ + BooleanType updateCholesky, /**< Flag indicating if Cholesky decomposition shall be updated. */ + BooleanType allowFlipping, /**< Flag indicating if flipping bounds are allowed. */ + BooleanType ensureNZC /**< Flag indicating if non-zero curvature is ensured by exchange rules. */ + ); + + +/** Performs robustified ratio test yield the maximum possible step length + * along the homotopy path. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_performPlainRatioTest( QProblem* _THIS, + int nIdx, /**< Number of ratios to be checked. */ + const int* const idxList, /**< Array containing the indices of all ratios to be checked. */ + const real_t* const num, /**< Array containing all numerators for performing the ratio test. */ + const real_t* const den, /**< Array containing all denominators for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t* t, /**< Output: Maximum possible step length along the homotopy path. */ + int* BC_idx /**< Output: Index of blocking constraint. */ + ); + + +/** Ensure non-zero curvature by primal jump. + * \return SUCCESSFUL_RETURN \n + * RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblem_ensureNonzeroCurvature( QProblem* _THIS, + BooleanType removeBoundNotConstraint, /**< SubjectTo to be removed is a bound. */ + int remIdx, /**< Index of bound/constraint to be removed. */ + BooleanType* exchangeHappened, /**< Output: Exchange was necessary to ensure. */ + BooleanType* addBoundNotConstraint, /**< SubjectTo to be added is a bound. */ + int* addIdx, /**< Index of bound/constraint to be added. */ + SubjectToStatus* addStatus /**< Status of bound/constraint to be added. */ + ); + + +/** Solves the system Ta = b or T^Ta = b where T is a reverse upper triangular matrix. + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ +returnValue QProblem_backsolveT( QProblem* _THIS, + const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + real_t* const a /**< Output: Solution vector */ + ); + + +/** Determines step direction of the shift of the QP data. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_determineDataShift( QProblem* _THIS, + const real_t* const g_new, /**< New gradient vector. */ + const real_t* const lbA_new, /**< New lower constraints' bounds. */ + const real_t* const ubA_new, /**< New upper constraints' bounds. */ + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + real_t* const delta_g, /**< Output: Step direction of gradient vector. */ + real_t* const delta_lbA, /**< Output: Step direction of lower constraints' bounds. */ + real_t* const delta_ubA, /**< Output: Step direction of upper constraints' bounds. */ + real_t* const delta_lb, /**< Output: Step direction of lower bounds. */ + real_t* const delta_ub, /**< Output: Step direction of upper bounds. */ + BooleanType* Delta_bC_isZero, /**< Output: Indicates if active constraints' bounds are to be shifted. */ + BooleanType* Delta_bB_isZero /**< Output: Indicates if active bounds are to be shifted. */ + ); + +/** Determines step direction of the homotopy path. + * \return SUCCESSFUL_RETURN \n + RET_STEPDIRECTION_FAILED_TQ \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ +returnValue QProblem_determineStepDirection( QProblem* _THIS, + const real_t* const delta_g, /**< Step direction of gradient vector. */ + const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */ + const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + BooleanType Delta_bC_isZero, /**< Indicates if active constraints' bounds are to be shifted. */ + BooleanType Delta_bB_isZero, /**< Indicates if active bounds are to be shifted. */ + real_t* const delta_xFX, /**< Output: Primal homotopy step direction of fixed variables. */ + real_t* const delta_xFR, /**< Output: Primal homotopy step direction of free variables. */ + real_t* const delta_yAC, /**< Output: Dual homotopy step direction of active constraints' multiplier. */ + real_t* const delta_yFX /**< Output: Dual homotopy step direction of fixed variables' multiplier. */ + ); + +/** Determines the maximum possible step length along the homotopy path + * and performs _THIS step (without changing working set). + * \return SUCCESSFUL_RETURN \n + * RET_ERROR_IN_CONSTRAINTPRODUCT \n + * RET_QP_INFEASIBLE */ +returnValue QProblem_performStep( QProblem* _THIS, + const real_t* const delta_g, /**< Step direction of gradient. */ + const real_t* const delta_lbA, /**< Step direction of lower constraints' bounds. */ + const real_t* const delta_ubA, /**< Step direction of upper constraints' bounds. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */ + const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */ + const real_t* const delta_yAC, /**< Dual homotopy step direction of active constraints' multiplier. */ + const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */ + int* BC_idx, /**< Output: Index of blocking constraint. */ + SubjectToStatus* BC_status, /**< Output: Status of blocking constraint. */ + BooleanType* BC_isBound /**< Output: Indicates if blocking constraint is a bound. */ + ); + +/** Updates the active set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVE_FROM_ACTIVESET_FAILED \n + RET_ADD_TO_ACTIVESET_FAILED */ +returnValue QProblem_changeActiveSet( QProblem* _THIS, + int BC_idx, /**< Index of blocking constraint. */ + SubjectToStatus BC_status, /**< Status of blocking constraint. */ + BooleanType BC_isBound /**< Indicates if blocking constraint is a bound. */ + ); + + +/** Compute relative length of homotopy in data space for termination + * criterion. + * \return Relative length in data space. */ +real_t QProblem_getRelativeHomotopyLength( QProblem* _THIS, + const real_t* const g_new, /**< Final gradient. */ + const real_t* const lb_new, /**< Final lower variable bounds. */ + const real_t* const ub_new, /**< Final upper variable bounds. */ + const real_t* const lbA_new, /**< Final lower constraint bounds. */ + const real_t* const ubA_new /**< Final upper constraint bounds. */ + ); + + +/** Ramping Strategy to avoid ties. Modifies homotopy start without + * changing current active set. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_performRamping( QProblem* _THIS ); + + +/** ... */ +returnValue QProblem_updateFarBounds( QProblem* _THIS, + real_t curFarBound, /**< ... */ + int nRamp, /**< ... */ + const real_t* const lb_new, /**< ... */ + real_t* const lb_new_far, /**< ... */ + const real_t* const ub_new, /**< ... */ + real_t* const ub_new_far, /**< ... */ + const real_t* const lbA_new, /**< ... */ + real_t* const lbA_new_far, /**< ... */ + const real_t* const ubA_new, /**< ... */ + real_t* const ubA_new_far /**< ... */ + ); + +/** ... */ +returnValue QProblemBCPY_updateFarBounds( QProblem* _THIS, + real_t curFarBound, /**< ... */ + int nRamp, /**< ... */ + const real_t* const lb_new, /**< ... */ + real_t* const lb_new_far, /**< ... */ + const real_t* const ub_new, /**< ... */ + real_t* const ub_new_far /**< ... */ + ); + + + +/** Performs robustified ratio test yield the maximum possible step length + * along the homotopy path. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_performRatioTestC( QProblem* _THIS, + int nIdx, /**< Number of ratios to be checked. */ + const int* const idxList, /**< Array containing the indices of all ratios to be checked. */ + Constraints* const subjectTo, /**< Constraint object corresponding to ratios to be checked. */ + const real_t* const num, /**< Array containing all numerators for performing the ratio test. */ + const real_t* const den, /**< Array containing all denominators for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t* t, /**< Output: Maximum possible step length along the homotopy path. */ + int* BC_idx /**< Output: Index of blocking constraint. */ + ); + + +/** Drift correction at end of each active set iteration + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_performDriftCorrection( QProblem* _THIS ); + + +/** Updates QP vectors, working sets and internal data structures in order to + start from an optimal solution corresponding to initial guesses of the working + set for bounds and constraints. + * \return SUCCESSFUL_RETURN \n + * RET_SETUP_AUXILIARYQP_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_setupAuxiliaryQP( QProblem* _THIS, + Bounds* const guessedBounds, /**< Initial guess for working set of bounds. */ + Constraints* const guessedConstraints /**< Initial guess for working set of constraints. */ + ); + +/** Determines if it is more efficient to refactorise the matrices when + * hotstarting or not (i.e. better to update the existing factorisations). + * \return BT_TRUE iff matrices shall be refactorised afresh + */ +BooleanType QProblem_shallRefactorise( QProblem* _THIS, + Bounds* const guessedBounds, /**< Guessed new working set of bounds. */ + Constraints* const guessedConstraints /**< Guessed new working set of constraints. */ + ); + +/** Setups internal QP data. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_UNKNONW_BUG */ +returnValue QProblem_setupQPdataM( QProblem* _THIS, + DenseMatrix *_H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + DenseMatrix *_A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + ); + + +/** Sets up dense internal QP data. If the current Hessian is trivial + * (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_UNKNONW_BUG */ +returnValue QProblem_setupQPdata( QProblem* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + real_t* const _A, /**< Constraint matrix. */ + const real_t* const _lb, /**< Lower bound vector (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bound vector (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + const real_t* const _lbA, /**< Lower constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const real_t* const _ubA /**< Upper constraints' bound vector. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + ); + +/** Sets up internal QP data by loading it from files. If the current Hessian + * is trivial (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_UNKNONW_BUG */ +returnValue QProblem_setupQPdataFromFile( QProblem* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix, of neighbouring QP to be solved, is stored. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const A_file, /**< Name of file where constraint matrix, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + ); + +/** Loads new QP vectors from files (internal members are not affected!). + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ +returnValue QProblem_loadQPvectorsFromFile( QProblem* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + const char* const lbA_file, /**< Name of file where lower constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no lower constraints' bounds exist, a NULL pointer can be passed. */ + const char* const ubA_file, /**< Name of file where upper constraints' bounds, of neighbouring QP to be solved, is stored. \n + If no upper constraints' bounds exist, a NULL pointer can be passed. */ + real_t* const g_new, /**< Output: Gradient of neighbouring QP to be solved. */ + real_t* const lb_new, /**< Output: Lower bounds of neighbouring QP to be solved */ + real_t* const ub_new, /**< Output: Upper bounds of neighbouring QP to be solved */ + real_t* const lbA_new, /**< Output: Lower constraints' bounds of neighbouring QP to be solved */ + real_t* const ubA_new /**< Output: Upper constraints' bounds of neighbouring QP to be solved */ + ); + + +/** Prints concise information on the current iteration. + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblem_printIteration( QProblem* _THIS, + int iter, /**< Number of current iteration. */ + int BC_idx, /**< Index of blocking constraint. */ + SubjectToStatus BC_status, /**< Status of blocking constraint. */ + BooleanType BC_isBound, /**< Indicates if blocking constraint is a bound. */ + real_t homotopyLength, /**< Current homotopy distance. */ + BooleanType isFirstCall /**< Indicating whether this is the first call for current QP. */ + ); + + +/** Sets constraint matrix of the QP. \n + Note: Also internal vector Ax is recomputed! + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +static inline returnValue QProblem_setAM( QProblem* _THIS, + DenseMatrix *A_new /**< New constraint matrix. */ + ); + +/** Sets dense constraint matrix of the QP. \n + Note: Also internal vector Ax is recomputed! + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +static inline returnValue QProblem_setA( QProblem* _THIS, + real_t* const A_new /**< New dense constraint matrix (with correct dimension!). */ + ); + + +/** Sets constraints' lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblem_setLBA( QProblem* _THIS, + const real_t* const lbA_new /**< New constraints' lower bound vector (with correct dimension!). */ + ); + +/** Changes single entry of lower constraints' bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue QProblem_setLBAn( QProblem* _THIS, + int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of lower constraints' bound vector (with correct dimension!). */ + ); + +/** Sets constraints' upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblem_setUBA( QProblem* _THIS, + const real_t* const ubA_new /**< New constraints' upper bound vector (with correct dimension!). */ + ); + +/** Changes single entry of upper constraints' bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue QProblem_setUBAn( QProblem* _THIS, + int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of upper constraints' bound vector (with correct dimension!). */ + ); + + +/** Decides if lower bounds are smaller than upper bounds + * + * \return SUCCESSFUL_RETURN \n + * RET_QP_INFEASIBLE */ +returnValue QProblem_areBoundsConsistent( QProblem* _THIS, + const real_t* const lb, /**< Vector of lower bounds*/ + const real_t* const ub, /**< Vector of upper bounds*/ + const real_t* const lbA, /**< Vector of lower constraints*/ + const real_t* const ubA /**< Vector of upper constraints*/ + ); + + +/** Drops the blocking bound/constraint that led to infeasibility, or finds another + * bound/constraint to drop according to drop priorities. + * \return SUCCESSFUL_RETURN \n + */ +returnValue QProblem_dropInfeasibles ( QProblem* _THIS, + int BC_number, /**< Number of the bound or constraint to be added */ + SubjectToStatus BC_status, /**< New status of the bound or constraint to be added */ + BooleanType BC_isBound, /**< Whether a bound or a constraint is to be added */ + real_t *xiB, + real_t *xiC + ); + + +/** If Hessian type has been set by the user, nothing is done. + * Otherwise the Hessian type is set to HST_IDENTITY, HST_ZERO, or + * HST_POSDEF (default), respectively. + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_INDEFINITE */ +returnValue QProblem_determineHessianType( QProblem* _THIS ); + +/** Computes the Cholesky decomposition of the (simply projected) Hessian + * (i.e. R^T*R = Z^T*H*Z). It only works in the case where Z is a simple + * projection matrix! + * Note: If Hessian turns out not to be positive definite, the Hessian type + * is set to HST_SEMIDEF accordingly. + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ +returnValue QProblemBCPY_computeCholesky( QProblem* _THIS ); + +/** Obtains the desired working set for the auxiliary initial QP in + * accordance with the user specifications + * \return SUCCESSFUL_RETURN \n + RET_OBTAINING_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemBCPY_obtainAuxiliaryWorkingSet( QProblem* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + Bounds* const guessedBounds, /**< Guessed working set for solution (xOpt,yOpt). */ + Bounds* auxiliaryBounds /**< Input: Allocated bound object. \n + * Output: Working set for auxiliary QP. */ + ); + + +/** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ +returnValue QProblem_backsolveR( QProblem* _THIS, + const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + real_t* const a /**< Output: Solution vector */ + ); + +/** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. \n + * Special variant for the case that _THIS function is called from within "removeBound()". + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ +returnValue QProblem_backsolveRrem( QProblem* _THIS, + const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + BooleanType removingBound, /**< Indicates if function is called from "removeBound()". */ + real_t* const a /**< Output: Solution vector */ + ); + + +/** Determines step direction of the shift of the QP data. + * \return SUCCESSFUL_RETURN */ +returnValue QProblemBCPY_determineDataShift( QProblem* _THIS, + const real_t* const g_new, /**< New gradient vector. */ + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + real_t* const delta_g, /**< Output: Step direction of gradient vector. */ + real_t* const delta_lb, /**< Output: Step direction of lower bounds. */ + real_t* const delta_ub, /**< Output: Step direction of upper bounds. */ + BooleanType* Delta_bB_isZero /**< Output: Indicates if active bounds are to be shifted. */ + ); + + +/** Sets up internal QP data. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemBCPY_setupQPdataM( QProblem* _THIS, + DenseMatrix *_H, /**< Hessian matrix.*/ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + +/** Sets up internal QP data. If the current Hessian is trivial + * (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_NO_HESSIAN_SPECIFIED */ +returnValue QProblemBCPY_setupQPdata( QProblem* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + +/** Sets up internal QP data by loading it from files. If the current Hessian + * is trivial (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_NO_HESSIAN_SPECIFIED */ +returnValue QProblemBCPY_setupQPdataFromFile( QProblem* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix, of neighbouring QP to be solved, is stored. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + +/** Loads new QP vectors from files (internal members are not affected!). + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemBCPY_loadQPvectorsFromFile( QProblem* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + real_t* const g_new, /**< Output: Gradient of neighbouring QP to be solved. */ + real_t* const lb_new, /**< Output: Lower bounds of neighbouring QP to be solved */ + real_t* const ub_new /**< Output: Upper bounds of neighbouring QP to be solved */ + ); + + +/** Sets internal infeasibility flag and throws given error in case the far bound + * strategy is not enabled (as QP might actually not be infeasible in _THIS case). + * \return RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_ENSURELI_FAILED_CYCLING \n + RET_ENSURELI_FAILED_NOINDEX */ +returnValue QProblem_setInfeasibilityFlag( QProblem* _THIS, + returnValue returnvalue, /**< Returnvalue to be tunneled. */ + BooleanType doThrowError /**< Flag forcing to throw an error. */ + ); + + +/** Determines if next QP iteration can be performed within given CPU time limit. + * \return BT_TRUE: CPU time limit is exceeded, stop QP solution. \n + BT_FALSE: Sufficient CPU time for next QP iteration. */ +BooleanType QProblem_isCPUtimeLimitExceeded( QProblem* _THIS, + const real_t* const cputime, /**< Maximum CPU time allowed for QP solution. */ + real_t starttime, /**< Start time of current QP solution. */ + int nWSR /**< Number of working set recalculations performed so far. */ + ); + + +/** Regularise Hessian matrix by adding a scaled identity matrix to it. + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_ALREADY_REGULARISED */ +returnValue QProblem_regulariseHessian( QProblem* _THIS ); + + +/** Sets Hessian matrix of the QP. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblem_setHM( QProblem* _THIS, + DenseMatrix* H_new /**< New Hessian matrix. */ + ); + +/** Sets dense Hessian matrix of the QP. + * If a null pointer is passed and + * a) hessianType is HST_IDENTITY, nothing is done, + * b) hessianType is not HST_IDENTITY, Hessian matrix is set to zero. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblem_setH( QProblem* _THIS, + real_t* const H_new /**< New dense Hessian matrix (with correct dimension!). */ + ); + +/** Changes gradient vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +static inline returnValue QProblem_setG( QProblem* _THIS, + const real_t* const g_new /**< New gradient vector (with correct dimension!). */ + ); + +/** Changes lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +static inline returnValue QProblem_setLB( QProblem* _THIS, + const real_t* const lb_new /**< New lower bound vector (with correct dimension!). */ + ); + +/** Changes single entry of lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue QProblem_setLBn( QProblem* _THIS, + int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of lower bound vector. */ + ); + +/** Changes upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +static inline returnValue QProblem_setUB( QProblem* _THIS, + const real_t* const ub_new /**< New upper bound vector (with correct dimension!). */ + ); + +/** Changes single entry of upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue QProblem_setUBn( QProblem* _THIS, + int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of upper bound vector. */ + ); + + + +/** Compute relative length of homotopy in data space for termination + * criterion. + * \return Relative length in data space. */ +real_t QProblemBCPY_getRelativeHomotopyLength( QProblem* _THIS, + const real_t* const g_new, /**< Final gradient. */ + const real_t* const lb_new, /**< Final lower variable bounds. */ + const real_t* const ub_new /**< Final upper variable bounds. */ + ); + + + +/** Performs robustified ratio test yield the maximum possible step length + * along the homotopy path. + * \return SUCCESSFUL_RETURN */ +returnValue QProblem_performRatioTestB( QProblem* _THIS, + int nIdx, /**< Number of ratios to be checked. */ + const int* const idxList, /**< Array containing the indices of all ratios to be checked. */ + Bounds* const subjectTo, /**< Bound object corresponding to ratios to be checked. */ + const real_t* const num, /**< Array containing all numerators for performing the ratio test. */ + const real_t* const den, /**< Array containing all denominators for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t* t, /**< Output: Maximum possible step length along the homotopy path. */ + int* BC_idx /**< Output: Index of blocking constraint. */ + ); + +/** Checks whether given ratio is blocking, i.e. limits the maximum step length + * along the homotopy path to a value lower than given one. + * \return SUCCESSFUL_RETURN */ +static inline BooleanType QProblem_isBlocking( QProblem* _THIS, + real_t num, /**< Numerator for performing the ratio test. */ + real_t den, /**< Denominator for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t* t /**< Input: Current maximum step length along the homotopy path, + * Output: Updated maximum possible step length along the homotopy path. */ + ); + + +/** ... + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue QProblem_writeQpDataIntoMatFile( QProblem* _THIS, + const char* const filename /**< Mat file name. */ + ); + +/** ... +* \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue QProblem_writeQpWorkspaceIntoMatFile( QProblem* _THIS, + const char* const filename /**< Mat file name. */ + ); + + +/* + * g e t B o u n d s + */ +static inline returnValue QProblem_getBounds( QProblem* _THIS, Bounds* _bounds ) +{ + int nV = QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + _bounds = _THIS->bounds; + + return SUCCESSFUL_RETURN; +} + + +/* + * g e t N V + */ +static inline int QProblem_getNV( QProblem* _THIS ) +{ + return Bounds_getNV( _THIS->bounds ); +} + + +/* + * g e t N F R + */ +static inline int QProblem_getNFR( QProblem* _THIS ) +{ + return Bounds_getNFR( _THIS->bounds ); +} + + +/* + * g e t N F X + */ +static inline int QProblem_getNFX( QProblem* _THIS ) +{ + return Bounds_getNFX( _THIS->bounds ); +} + + +/* + * g e t N F V + */ +static inline int QProblem_getNFV( QProblem* _THIS ) +{ + return Bounds_getNFV( _THIS->bounds ); +} + + +/* + * g e t S t a t u s + */ +static inline QProblemStatus QProblem_getStatus( QProblem* _THIS ) +{ + return _THIS->status; +} + + +/* + * i s I n i t i a l i s e d + */ +static inline BooleanType QProblem_isInitialised( QProblem* _THIS ) +{ + if ( _THIS->status == QPS_NOTINITIALISED ) + return BT_FALSE; + else + return BT_TRUE; +} + + +/* + * i s S o l v e d + */ +static inline BooleanType QProblem_isSolved( QProblem* _THIS ) +{ + if ( _THIS->status == QPS_SOLVED ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * i s I n f e a s i b l e + */ +static inline BooleanType QProblem_isInfeasible( QProblem* _THIS ) +{ + return _THIS->infeasible; +} + + +/* + * i s U n b o u n d e d + */ +static inline BooleanType QProblem_isUnbounded( QProblem* _THIS ) +{ + return _THIS->unbounded; +} + + +/* + * g e t H e s s i a n T y p e + */ +static inline HessianType QProblem_getHessianType( QProblem* _THIS ) +{ + return _THIS->hessianType; +} + + +/* + * s e t H e s s i a n T y p e + */ +static inline returnValue QProblem_setHessianType( QProblem* _THIS, HessianType _hessianType ) +{ + _THIS->hessianType = _hessianType; + return SUCCESSFUL_RETURN; +} + + +/* + * u s i n g R e g u l a r i s a t i o n + */ +static inline BooleanType QProblem_usingRegularisation( QProblem* _THIS ) +{ + if ( _THIS->regVal > QPOASES_ZERO ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * g e t O p t i o n s + */ +static inline Options QProblem_getOptions( QProblem* _THIS ) +{ + return _THIS->options; +} + + +/* + * s e t O p t i o n s + */ +static inline returnValue QProblem_setOptions( QProblem* _THIS, + Options _options + ) +{ + OptionsCPY( &_options,&(_THIS->options) ); + Options_ensureConsistency( &(_THIS->options) ); + + QProblem_setPrintLevel( _THIS,_THIS->options.printLevel ); + + return SUCCESSFUL_RETURN; +} + + +/* + * g e t P r i n t L e v e l + */ +static inline PrintLevel QProblem_getPrintLevel( QProblem* _THIS ) +{ + return _THIS->options.printLevel; +} + + +/* + * g e t C o u n t + */ +static inline unsigned int QProblem_getCount( QProblem* _THIS ) +{ + return _THIS->count; +} + + +/* + * r e s e t C o u n t e r + */ +static inline returnValue QProblem_resetCounter( QProblem* _THIS ) +{ + _THIS->count = 0; + return SUCCESSFUL_RETURN; +} + + + +/***************************************************************************** + * P R O T E C T E D * + *****************************************************************************/ + + +/* + * s e t H + */ +static inline returnValue QProblem_setHM( QProblem* _THIS, DenseMatrix* H_new ) +{ + if ( H_new == 0 ) + return QProblem_setH( _THIS,(real_t*)0 ); + else + return QProblem_setH( _THIS,DenseMatrix_getVal(H_new) ); +} + + +/* + * s e t H + */ +static inline returnValue QProblem_setH( QProblem* _THIS, real_t* const H_new ) +{ + /* if null pointer is passed, Hessian is set to zero matrix + * (or stays identity matrix) */ + if ( H_new == 0 ) + { + if ( _THIS->hessianType == HST_IDENTITY ) + return SUCCESSFUL_RETURN; + + _THIS->hessianType = HST_ZERO; + + _THIS->H = 0; + } + else + { + DenseMatrixCON( _THIS->H,QProblem_getNV( _THIS ),QProblem_getNV( _THIS ),QProblem_getNV( _THIS ),H_new ); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t G + */ +static inline returnValue QProblem_setG( QProblem* _THIS, const real_t* const g_new ) +{ + unsigned int nV = (unsigned int)QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( g_new == 0 ) + return THROWERROR( RET_INVALID_ARGUMENTS ); + + memcpy( _THIS->g,g_new,nV*sizeof(real_t) ); + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B + */ +static inline returnValue QProblem_setLB( QProblem* _THIS, const real_t* const lb_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( lb_new != 0 ) + { + memcpy( _THIS->lb,lb_new,nV*sizeof(real_t) ); + } + else + { + /* if no lower bounds are specified, set them to -infinity */ + for( i=0; ilb[i] = -QPOASES_INFTY; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B + */ +static inline returnValue QProblem_setLBn( QProblem* _THIS, int number, real_t value ) +{ + int nV = QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ( number >= 0 ) && ( number < nV ) ) + { + _THIS->lb[number] = value; + return SUCCESSFUL_RETURN; + } + else + { + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); + } +} + + +/* + * s e t U B + */ +static inline returnValue QProblem_setUB( QProblem* _THIS, const real_t* const ub_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ub_new != 0 ) + { + memcpy( _THIS->ub,ub_new,nV*sizeof(real_t) ); + } + else + { + /* if no upper bounds are specified, set them to infinity */ + for( i=0; iub[i] = QPOASES_INFTY; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t U B + */ +static inline returnValue QProblem_setUBn( QProblem* _THIS, int number, real_t value ) +{ + int nV = QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ( number >= 0 ) && ( number < nV ) ) + { + _THIS->ub[number] = value; + + return SUCCESSFUL_RETURN; + } + else + { + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); + } +} + + + +/* + * i s B l o c k i n g + */ +static inline BooleanType QProblem_isBlocking( QProblem* _THIS, + real_t num, + real_t den, + real_t epsNum, + real_t epsDen, + real_t* t + ) +{ + if ( ( den >= epsDen ) && ( num >= epsNum ) ) + { + if ( num < (*t)*den ) + return BT_TRUE; + } + + return BT_FALSE; +} + + + +/* + * g e t C o n s t r a i n t s + */ +static inline returnValue QProblem_getConstraints( QProblem* _THIS, Constraints* _constraints ) +{ + int nV = QProblem_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + ConstraintsCPY( _THIS->constraints,_constraints ); + + return SUCCESSFUL_RETURN; +} + + + +/* + * g e t N C + */ +static inline int QProblem_getNC( QProblem* _THIS ) +{ + return Constraints_getNC( _THIS->constraints ); +} + + +/* + * g e t N E C + */ +static inline int QProblem_getNEC( QProblem* _THIS ) +{ + return Constraints_getNEC( _THIS->constraints ); +} + + +/* + * g e t N A C + */ +static inline int QProblem_getNAC( QProblem* _THIS ) +{ + return Constraints_getNAC( _THIS->constraints ); +} + + +/* + * g e t N I A C + */ +static inline int QProblem_getNIAC( QProblem* _THIS ) +{ + return Constraints_getNIAC( _THIS->constraints ); +} + + + +/***************************************************************************** + * P R O T E C T E D * + *****************************************************************************/ + + +/* + * s e t A + */ +static inline returnValue QProblem_setAM( QProblem* _THIS, DenseMatrix *A_new ) +{ + if ( A_new == 0 ) + return QProblem_setA( _THIS,(real_t*)0 ); + else + return QProblem_setA( _THIS,DenseMatrix_getVal(A_new) ); +} + + +/* + * s e t A + */ +static inline returnValue QProblem_setA( QProblem* _THIS, real_t* const A_new ) +{ + int j; + int nV = QProblem_getNV( _THIS ); + int nC = QProblem_getNC( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( A_new == 0 ) + return THROWERROR( RET_INVALID_ARGUMENTS ); + + DenseMatrixCON( _THIS->A,QProblem_getNC( _THIS ),QProblem_getNV( _THIS ),QProblem_getNV( _THIS ),A_new ); + + DenseMatrix_times( _THIS->A,1, 1.0, _THIS->x, nV, 0.0, _THIS->Ax, nC); + + for( j=0; jAx_u[j] = _THIS->ubA[j] - _THIS->Ax[j]; + _THIS->Ax_l[j] = _THIS->Ax[j] - _THIS->lbA[j]; + + /* (ckirches) disable constraints with empty rows */ + if ( qpOASES_isZero( DenseMatrix_getRowNorm( _THIS->A,j,2 ),QPOASES_ZERO ) == BT_TRUE ) + Constraints_setType( _THIS->constraints,j,ST_DISABLED ); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B A + */ +static inline returnValue QProblem_setLBA( QProblem* _THIS, const real_t* const lbA_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)QProblem_getNV( _THIS ); + unsigned int nC = (unsigned int)QProblem_getNC( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( lbA_new != 0 ) + { + memcpy( _THIS->lbA,lbA_new,nC*sizeof(real_t) ); + } + else + { + /* if no lower constraints' bounds are specified, set them to -infinity */ + for( i=0; ilbA[i] = -QPOASES_INFTY; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B A + */ +static inline returnValue QProblem_setLBAn( QProblem* _THIS, int number, real_t value ) +{ + int nV = QProblem_getNV( _THIS ); + int nC = QProblem_getNC( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ( number >= 0 ) && ( number < nC ) ) + { + _THIS->lbA[number] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +/* + * s e t U B A + */ +static inline returnValue QProblem_setUBA( QProblem* _THIS, const real_t* const ubA_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)QProblem_getNV( _THIS ); + unsigned int nC = (unsigned int)QProblem_getNC( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ubA_new != 0 ) + { + memcpy( _THIS->ubA,ubA_new,nC*sizeof(real_t) ); + } + else + { + /* if no upper constraints' bounds are specified, set them to infinity */ + for( i=0; iubA[i] = QPOASES_INFTY; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t U B A + */ +static inline returnValue QProblem_setUBAn( QProblem* _THIS, int number, real_t value ) +{ + int nV = QProblem_getNV( _THIS ); + int nC = QProblem_getNC( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ( number >= 0 ) && ( number < nC ) ) + { + _THIS->ubA[number] = value; + return SUCCESSFUL_RETURN; + } + else + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); +} + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_QPROBLEM_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/QProblemB.h b/third_party/acados/include/qpOASES_e/QProblemB.h new file mode 100644 index 0000000000..ee5157dda7 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/QProblemB.h @@ -0,0 +1,1641 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/QProblemB.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of the QProblemB class which is able to use the newly + * developed online active set strategy for parametric quadratic programming + * for problems with (simple) bounds only. + */ + + + +#ifndef QPOASES_QPROBLEMB_H +#define QPOASES_QPROBLEMB_H + + +#include +#include +#include +#include + + +BEGIN_NAMESPACE_QPOASES + +typedef struct { + Bounds *emptyBounds; + Bounds *auxiliaryBounds; + + real_t *ub_new_far; + real_t *lb_new_far; + + real_t *g_new; + real_t *lb_new; + real_t *ub_new; + + real_t *g_new2; + real_t *lb_new2; + real_t *ub_new2; + + real_t *Hx; + + real_t *_H; + + real_t *g_original; + real_t *lb_original; + real_t *ub_original; + + real_t *delta_xFR; + real_t *delta_xFX; + real_t *delta_yFX; + real_t *delta_g; + real_t *delta_lb; + real_t *delta_ub; + + real_t *gMod; + + real_t *num; + real_t *den; + + real_t *rhs; + real_t *r; +} QProblemB_ws; + +int QProblemB_ws_calculateMemorySize( unsigned int nV ); + +char *QProblemB_ws_assignMemory( unsigned int nV, QProblemB_ws **mem, void *raw_memory ); + +QProblemB_ws *QProblemB_ws_createMemory( unsigned int nV ); + + +/** + * \brief Implements the online active set strategy for box-constrained QPs. + * + * Class for setting up and solving quadratic programs with bounds (= box constraints) only. + * The main feature is the possibility to use the newly developed online active set strategy + * for parametric quadratic programming. + * + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + */ +typedef struct +{ + QProblemB_ws *ws; + Bounds *bounds; /**< Data structure for problem's bounds. */ + Flipper *flipper; /**< Struct for making a temporary copy of the matrix factorisations. */ + + DenseMatrix* H; /**< Hessian matrix pointer. */ + + Options options; /**< Struct containing all user-defined options for solving QPs. */ + TabularOutput tabularOutput; /**< Struct storing information for tabular output (printLevel == PL_TABULAR). */ + + real_t *g; /**< Gradient. */ + real_t *lb; /**< Lower bound vector (on variables). */ + real_t *ub; /**< Upper bound vector (on variables). */ + + real_t *R; /**< Cholesky factor of H (i.e. H = R^T*R). */ + + real_t *x; /**< Primal solution vector. */ + real_t *y; /**< Dual solution vector. */ + + real_t *delta_xFR_TMP; /**< Temporary for determineStepDirection */ + + real_t tau; /**< Last homotopy step length. */ + real_t regVal; /**< Holds the offset used to regularise Hessian matrix (zero by default). */ + + real_t ramp0; /**< Start value for Ramping Strategy. */ + real_t ramp1; /**< Final value for Ramping Strategy. */ + + QProblemStatus status; /**< Current status of the solution process. */ + HessianType hessianType; /**< Type of Hessian matrix. */ + + BooleanType haveCholesky; /**< Flag indicating whether Cholesky decomposition has already been setup. */ + BooleanType infeasible; /**< QP infeasible? */ + BooleanType unbounded; /**< QP unbounded? */ + + int rampOffset; /**< Offset index for Ramping. */ + unsigned int count; /**< Counts the number of hotstart function calls (internal usage only!). */ +} QProblemB; + +int QProblemB_calculateMemorySize( unsigned int nV ); + +char *QProblemB_assignMemory( unsigned int nV, QProblemB **mem, void *raw_memory ); + +QProblemB *QProblemB_createMemory( unsigned int nV ); + + +/** Constructor which takes the QP dimension and Hessian type + * information. If the Hessian is the zero (i.e. HST_ZERO) or the + * identity matrix (i.e. HST_IDENTITY), respectively, no memory + * is allocated for it and a NULL pointer can be passed for it + * to the init() functions. */ +void QProblemBCON( QProblemB* _THIS, + int _nV, /**< Number of variables. */ + HessianType _hessianType /**< Type of Hessian matrix. */ + ); + +void QProblemBCPY( QProblemB* FROM, + QProblemB* TO + ); + + +/** Clears all data structures of QProblemB except for QP data. + * \return SUCCESSFUL_RETURN \n + RET_RESET_FAILED */ +returnValue QProblemB_reset( QProblemB* _THIS ); + + +/** Initialises a simply bounded QP problem with given QP data and tries to solve it + * using at most nWSR iterations. + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_initM( QProblemB* _THIS, + DenseMatrix *_H, /**< Hessian matrix. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation (if pointer passed). */ + ); + +/** Initialises a simply bounded QP problem with given QP data and tries to solve it + * using at most nWSR iterations. + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_init( QProblemB* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation (if pointer passed). */ + ); + +/** Initialises a simply bounded QP problem with given QP data to be read from files and solves it + * using at most nWSR iterations. + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ +returnValue QProblemB_initF( QProblemB* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation (if pointer passed). */ + ); + +/** Initialises a simply bounded QP problem with given QP data and tries to solve it + * using at most nWSR iterations. Depending on the parameter constellation it: \n + * 1. 0, 0, 0 : starts with xOpt = 0, yOpt = 0 and gB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : starts with xOpt, yOpt = 0 and obtain gB by "clipping", \n + * 3. 0, yOpt, 0 : starts with xOpt = 0, yOpt and obtain gB from yOpt != 0, \n + * 4. 0, 0, gB: starts with xOpt = 0, yOpt = 0 and gB, \n + * 5. xOpt, yOpt, 0 : starts with xOpt, yOpt and obtain gB from yOpt != 0, \n + * 6. xOpt, 0, gB: starts with xOpt, yOpt = 0 and gB, \n + * 7. xOpt, yOpt, gB: starts with xOpt, yOpt and gB (assume them to be consistent!) + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_initMW( QProblemB* _THIS, + DenseMatrix *_H, /**< Hessian matrix. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. A NULL pointer can be passed. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. A NULL pointer can be passed. \n + (If a null pointer is passed, the old dual solution is kept!) */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, all bounds are assumed inactive!) */ + const real_t* const _R /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. + The Cholesky factor must be stored in a real_t array of size nV*nV + in row-major format. Note: Only used if xOpt/yOpt and gB are NULL! \n + (If a null pointer is passed, Cholesky decomposition is computed internally!) */ + ); + +/** Initialises a simply bounded QP problem with given QP data and tries to solve it + * using at most nWSR iterations. Depending on the parameter constellation it: \n + * 1. 0, 0, 0 : starts with xOpt = 0, yOpt = 0 and gB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : starts with xOpt, yOpt = 0 and obtain gB by "clipping", \n + * 3. 0, yOpt, 0 : starts with xOpt = 0, yOpt and obtain gB from yOpt != 0, \n + * 4. 0, 0, gB: starts with xOpt = 0, yOpt = 0 and gB, \n + * 5. xOpt, yOpt, 0 : starts with xOpt, yOpt and obtain gB from yOpt != 0, \n + * 6. xOpt, 0, gB: starts with xOpt, yOpt = 0 and gB, \n + * 7. xOpt, yOpt, gB: starts with xOpt, yOpt and gB (assume them to be consistent!) + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_initW( QProblemB* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub, /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. A NULL pointer can be passed. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. A NULL pointer can be passed. \n + (If a null pointer is passed, the old dual solution is kept!) */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, all bounds are assumed inactive!) */ + const real_t* const _R /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. + The Cholesky factor must be stored in a real_t array of size nV*nV + in row-major format. Note: Only used if xOpt/yOpt and gB are NULL! \n + (If a null pointer is passed, Cholesky decomposition is computed internally!) */ + ); + +/** Initialises a simply bounded QP problem with given QP data to be read from files and solves it + * using at most nWSR iterations. Depending on the parameter constellation it: \n + * 1. 0, 0, 0 : starts with xOpt = 0, yOpt = 0 and gB empty (or all implicit equality bounds), \n + * 2. xOpt, 0, 0 : starts with xOpt, yOpt = 0 and obtain gB by "clipping", \n + * 3. 0, yOpt, 0 : starts with xOpt = 0, yOpt and obtain gB from yOpt != 0, \n + * 4. 0, 0, gB: starts with xOpt = 0, yOpt = 0 and gB, \n + * 5. xOpt, yOpt, 0 : starts with xOpt, yOpt and obtain gB from yOpt != 0, \n + * 6. xOpt, 0, gB: starts with xOpt, yOpt = 0 and gB, \n + * 7. xOpt, yOpt, gB: starts with xOpt, yOpt and gB (assume them to be consistent!) + * + * Note: This function internally calls solveInitialQP for initialisation! + * + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED \n + RET_UNABLE_TO_READ_FILE */ +returnValue QProblemB_initFW( QProblemB* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix is stored. \n + If Hessian matrix is trivial, a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient vector is stored. */ + const char* const lb_file, /**< Name of file where lower bound vector. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bound vector. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations when using initial homotopy. \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP initialisation. \n + Output: CPU time spent for QP initialisation. */ + const real_t* const xOpt, /**< Optimal primal solution vector. A NULL pointer can be passed. \n + (If a null pointer is passed, the old primal solution is kept!) */ + const real_t* const yOpt, /**< Optimal dual solution vector. A NULL pointer can be passed. \n + (If a null pointer is passed, the old dual solution is kept!) */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, all bounds are assumed inactive!) */ + const char* const R_file /**< Name of the file where a pre-computed (upper triangular) Cholesky factor + of the Hessian matrix is stored. \n + (If a null pointer is passed, Cholesky decomposition is computed internally!) */ + ); + + +/** Solves an initialised QP sequence using the online active set strategy. + * By default, QP solution is started from previous solution. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblemB_hotstart( QProblemB* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + ); + +/** Solves an initialised QP sequence using the online active set strategy, + * where QP data is read from files. QP solution is started from previous solution. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_hotstartF( QProblemB* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + ); + +/** Solves an initialised QP sequence using the online active set strategy. + * By default, QP solution is started from previous solution. If a guess + * for the working set is provided, an initialised homotopy is performed. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_SETUP_AUXILIARYQP_FAILED */ +returnValue QProblemB_hotstartW( QProblemB* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + Bounds* const guessedBounds /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, the previous working set is kept!) */ + ); + +/** Solves an initialised QP sequence using the online active set strategy, + * where QP data is read from files. + * By default, QP solution is started from previous solution. If a guess + * for the working set is provided, an initialised homotopy is performed. + * + * Note: This function internally calls solveQP/solveRegularisedQP + * for solving an initialised QP! + * + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_SETUP_AUXILIARYQP_FAILED */ +returnValue QProblemB_hotstartFW( QProblemB* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + Bounds* const guessedBounds /**< Optimal working set of bounds for solution (xOpt,yOpt). \n + (If a null pointer is passed, the previous working set is kept!) */ + ); + + +/** Writes a vector with the state of the working set + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue QProblemB_getWorkingSet( QProblemB* _THIS, + real_t* workingSet /** Output: array containing state of the working set. */ + ); + +/** Writes a vector with the state of the working set of bounds + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue QProblemB_getWorkingSetBounds( QProblemB* _THIS, + real_t* workingSetB /** Output: array containing state of the working set of bounds. */ + ); + +/** Writes a vector with the state of the working set of constraints + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue QProblemB_getWorkingSetConstraints( QProblemB* _THIS, + real_t* workingSetC /** Output: array containing state of the working set of constraints. */ + ); + + +/** Returns current bounds object of the QP (deep copy). + * \return SUCCESSFUL_RETURN \n + RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblemB_getBounds( QProblemB* _THIS, + Bounds* _bounds /** Output: Bounds object. */ + ); + + +/** Returns the number of variables. + * \return Number of variables. */ +static inline int QProblemB_getNV( QProblemB* _THIS ); + +/** Returns the number of free variables. + * \return Number of free variables. */ +static inline int QProblemB_getNFR( QProblemB* _THIS ); + +/** Returns the number of fixed variables. + * \return Number of fixed variables. */ +static inline int QProblemB_getNFX( QProblemB* _THIS ); + +/** Returns the number of implicitly fixed variables. + * \return Number of implicitly fixed variables. */ +static inline int QProblemB_getNFV( QProblemB* _THIS ); + +/** Returns the dimension of null space. + * \return Dimension of null space. */ +int QProblemB_getNZ( QProblemB* _THIS ); + + +/** Returns the optimal objective function value. + * \return finite value: Optimal objective function value (QP was solved) \n + +infinity: QP was not yet solved */ +real_t QProblemB_getObjVal( QProblemB* _THIS ); + +/** Returns the objective function value at an arbitrary point x. + * \return Objective function value at point x */ +real_t QProblemB_getObjValX( QProblemB* _THIS, + const real_t* const _x /**< Point at which the objective function shall be evaluated. */ + ); + +/** Returns the primal solution vector. + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ +returnValue QProblemB_getPrimalSolution( QProblemB* _THIS, + real_t* const xOpt /**< Output: Primal solution vector (if QP has been solved). */ + ); + +/** Returns the dual solution vector. + * \return SUCCESSFUL_RETURN \n + RET_QP_NOT_SOLVED */ +returnValue QProblemB_getDualSolution( QProblemB* _THIS, + real_t* const yOpt /**< Output: Dual solution vector (if QP has been solved). */ + ); + + +/** Returns status of the solution process. + * \return Status of solution process. */ +static inline QProblemStatus QProblemB_getStatus( QProblemB* _THIS ); + + +/** Returns if the QProblem object is initialised. + * \return BT_TRUE: QProblemB initialised \n + BT_FALSE: QProblemB not initialised */ +static inline BooleanType QProblemB_isInitialised( QProblemB* _THIS ); + +/** Returns if the QP has been solved. + * \return BT_TRUE: QProblemB solved \n + BT_FALSE: QProblemB not solved */ +static inline BooleanType QProblemB_isSolved( QProblemB* _THIS ); + +/** Returns if the QP is infeasible. + * \return BT_TRUE: QP infeasible \n + BT_FALSE: QP feasible (or not known to be infeasible!) */ +static inline BooleanType QProblemB_isInfeasible( QProblemB* _THIS ); + +/** Returns if the QP is unbounded. + * \return BT_TRUE: QP unbounded \n + BT_FALSE: QP unbounded (or not known to be unbounded!) */ +static inline BooleanType QProblemB_isUnbounded( QProblemB* _THIS ); + + +/** Returns Hessian type flag (type is not determined due to _THIS call!). + * \return Hessian type. */ +static inline HessianType QProblemB_getHessianType( QProblemB* _THIS ); + +/** Changes the print level. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblemB_setHessianType( QProblemB* _THIS, + HessianType _hessianType /**< New Hessian type. */ + ); + +/** Returns if the QP has been internally regularised. + * \return BT_TRUE: Hessian is internally regularised for QP solution \n + BT_FALSE: No internal Hessian regularisation is used for QP solution */ +static inline BooleanType QProblemB_usingRegularisation( QProblemB* _THIS ); + +/** Returns current options struct. + * \return Current options struct. */ +static inline Options QProblemB_getOptions( QProblemB* _THIS ); + +/** Overrides current options with given ones. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblemB_setOptions( QProblemB* _THIS, + Options _options /**< New options. */ + ); + +/** Returns the print level. + * \return Print level. */ +static inline PrintLevel QProblemB_getPrintLevel( QProblemB* _THIS ); + +/** Changes the print level. + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_setPrintLevel( QProblemB* _THIS, + PrintLevel _printlevel /**< New print level. */ + ); + +/** Returns the current number of QP problems solved. + * \return Number of QP problems solved. */ +static inline unsigned int QProblemB_getCount( QProblemB* _THIS ); + +/** Resets QP problem counter (to zero). + * \return SUCCESSFUL_RETURN. */ +static inline returnValue QProblemB_resetCounter( QProblemB* _THIS ); + + +/** Prints concise list of properties of the current QP. + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblemB_printProperties( QProblemB* _THIS ); + +/** Prints a list of all options and their current values. + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblemB_printOptions( QProblemB* _THIS ); + + +/** If Hessian type has been set by the user, nothing is done. + * Otherwise the Hessian type is set to HST_IDENTITY, HST_ZERO, or + * HST_POSDEF (default), respectively. + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_INDEFINITE */ +returnValue QProblemB_determineHessianType( QProblemB* _THIS ); + +/** Determines type of existing constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ +returnValue QProblemB_setupSubjectToType( QProblemB* _THIS ); + +/** Determines type of new constraints and bounds (i.e. implicitly fixed, unbounded etc.). + * \return SUCCESSFUL_RETURN \n + RET_SETUPSUBJECTTOTYPE_FAILED */ +returnValue QProblemB_setupSubjectToTypeNew( QProblemB* _THIS, + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new /**< New upper bounds. */ + ); + +/** Computes the Cholesky decomposition of the (simply projected) Hessian + * (i.e. R^T*R = Z^T*H*Z). It only works in the case where Z is a simple + * projection matrix! + * Note: If Hessian turns out not to be positive definite, the Hessian type + * is set to HST_SEMIDEF accordingly. + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ +returnValue QProblemB_computeCholesky( QProblemB* _THIS ); + +/** Computes initial Cholesky decomposition of the projected Hessian making + * use of the function setupCholeskyDecomposition() or setupCholeskyDecompositionProjected(). + * \return SUCCESSFUL_RETURN \n + * RET_HESSIAN_NOT_SPD \n + * RET_INDEXLIST_CORRUPTED */ +returnValue QProblemB_setupInitialCholesky( QProblemB* _THIS ); + + +/** Obtains the desired working set for the auxiliary initial QP in + * accordance with the user specifications + * \return SUCCESSFUL_RETURN \n + RET_OBTAINING_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_obtainAuxiliaryWorkingSet( QProblemB* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + const real_t* const yOpt, /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are assumed to be zero. */ + Bounds* const guessedBounds, /**< Guessed working set for solution (xOpt,yOpt). */ + Bounds* auxiliaryBounds /**< Input: Allocated bound object. \n + * Ouput: Working set for auxiliary QP. */ + ); + +/** Decides if lower bounds are smaller than upper bounds + * + * \return SUCCESSFUL_RETURN \n + * RET_QP_INFEASIBLE */ +returnValue QProblemB_areBoundsConsistent( QProblemB* _THIS, + const real_t* const lb, /**< Vector of lower bounds*/ + const real_t* const ub /**< Vector of upper bounds*/ + ); + +/** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ +returnValue QProblemB_backsolveR( QProblemB* _THIS, + const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + real_t* const a /**< Output: Solution vector */ + ); + +/** Solves the system Ra = b or R^Ta = b where R is an upper triangular matrix. \n + * Special variant for the case that _THIS function is called from within "removeBound()". + * \return SUCCESSFUL_RETURN \n + RET_DIV_BY_ZERO */ +returnValue QProblemB_backsolveRrem( QProblemB* _THIS, + const real_t* const b, /**< Right hand side vector. */ + BooleanType transposed, /**< Indicates if the transposed system shall be solved. */ + BooleanType removingBound, /**< Indicates if function is called from "removeBound()". */ + real_t* const a /**< Output: Solution vector */ + ); + + +/** Determines step direction of the shift of the QP data. + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_determineDataShift( QProblemB* _THIS, + const real_t* const g_new, /**< New gradient vector. */ + const real_t* const lb_new, /**< New lower bounds. */ + const real_t* const ub_new, /**< New upper bounds. */ + real_t* const delta_g, /**< Output: Step direction of gradient vector. */ + real_t* const delta_lb, /**< Output: Step direction of lower bounds. */ + real_t* const delta_ub, /**< Output: Step direction of upper bounds. */ + BooleanType* Delta_bB_isZero/**< Output: Indicates if active bounds are to be shifted. */ + ); + + +/** Sets up internal QP data. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_setupQPdataM( QProblemB* _THIS, + DenseMatrix *_H, /**< Hessian matrix.*/ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + +/** Sets up internal QP data. If the current Hessian is trivial + * (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_NO_HESSIAN_SPECIFIED */ +returnValue QProblemB_setupQPdata( QProblemB* _THIS, + real_t* const _H, /**< Hessian matrix. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const real_t* const _g, /**< Gradient vector. */ + const real_t* const _lb, /**< Lower bounds (on variables). \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const _ub /**< Upper bounds (on variables). \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + +/** Sets up internal QP data by loading it from files. If the current Hessian + * is trivial (i.e. HST_ZERO or HST_IDENTITY) but a non-trivial one is given, + * memory for Hessian is allocated and it is set to the given one. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS \n + RET_NO_HESSIAN_SPECIFIED */ +returnValue QProblemB_setupQPdataFromFile( QProblemB* _THIS, + const char* const H_file, /**< Name of file where Hessian matrix, of neighbouring QP to be solved, is stored. \n + If Hessian matrix is trivial,a NULL pointer can be passed. */ + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + ); + +/** Loads new QP vectors from files (internal members are not affected!). + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE \n + RET_INVALID_ARGUMENTS */ +returnValue QProblemB_loadQPvectorsFromFile( QProblemB* _THIS, + const char* const g_file, /**< Name of file where gradient, of neighbouring QP to be solved, is stored. */ + const char* const lb_file, /**< Name of file where lower bounds, of neighbouring QP to be solved, is stored. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const char* const ub_file, /**< Name of file where upper bounds, of neighbouring QP to be solved, is stored. \n + If no upper bounds exist, a NULL pointer can be passed. */ + real_t* const g_new, /**< Output: Gradient of neighbouring QP to be solved. */ + real_t* const lb_new, /**< Output: Lower bounds of neighbouring QP to be solved */ + real_t* const ub_new /**< Output: Upper bounds of neighbouring QP to be solved */ + ); + + +/** Sets internal infeasibility flag and throws given error in case the far bound + * strategy is not enabled (as QP might actually not be infeasible in _THIS case). + * \return RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_ENSURELI_FAILED_CYCLING \n + RET_ENSURELI_FAILED_NOINDEX */ +returnValue QProblemB_setInfeasibilityFlag( QProblemB* _THIS, + returnValue returnvalue, /**< Returnvalue to be tunneled. */ + BooleanType doThrowError /**< Flag forcing to throw an error. */ + ); + + +/** Determines if next QP iteration can be performed within given CPU time limit. + * \return BT_TRUE: CPU time limit is exceeded, stop QP solution. \n + BT_FALSE: Sufficient CPU time for next QP iteration. */ +BooleanType QProblemB_isCPUtimeLimitExceeded( QProblemB* _THIS, + const real_t* const cputime, /**< Maximum CPU time allowed for QP solution. */ + real_t starttime, /**< Start time of current QP solution. */ + int nWSR /**< Number of working set recalculations performed so far. */ + ); + + +/** Regularise Hessian matrix by adding a scaled identity matrix to it. + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_ALREADY_REGULARISED */ +returnValue QProblemB_regulariseHessian( QProblemB* _THIS ); + + +/** Sets Hessian matrix of the QP. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblemB_setHM( QProblemB* _THIS, + DenseMatrix* H_new /**< New Hessian matrix. */ + ); + +/** Sets dense Hessian matrix of the QP. + * If a null pointer is passed and + * a) hessianType is HST_IDENTITY, nothing is done, + * b) hessianType is not HST_IDENTITY, Hessian matrix is set to zero. + * \return SUCCESSFUL_RETURN */ +static inline returnValue QProblemB_setH( QProblemB* _THIS, + real_t* const H_new /**< New dense Hessian matrix (with correct dimension!). */ + ); + +/** Changes gradient vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +static inline returnValue QProblemB_setG( QProblemB* _THIS, + const real_t* const g_new /**< New gradient vector (with correct dimension!). */ + ); + +/** Changes lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblemB_setLB( QProblemB* _THIS, + const real_t* const lb_new /**< New lower bound vector (with correct dimension!). */ + ); + +/** Changes single entry of lower bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue QProblemB_setLBn( QProblemB* _THIS, + int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of lower bound vector. */ + ); + +/** Changes upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP */ +static inline returnValue QProblemB_setUB( QProblemB* _THIS, + const real_t* const ub_new /**< New upper bound vector (with correct dimension!). */ + ); + +/** Changes single entry of upper bound vector of the QP. + * \return SUCCESSFUL_RETURN \n + * RET_QPOBJECT_NOT_SETUP \n + * RET_INDEX_OUT_OF_BOUNDS */ +static inline returnValue QProblemB_setUBn( QProblemB* _THIS, + int number, /**< Number of entry to be changed. */ + real_t value /**< New value for entry of upper bound vector. */ + ); + + +/** Computes parameters for the Givens matrix G for which [x,y]*G = [z,0] + * \return SUCCESSFUL_RETURN */ +static inline void QProblemB_computeGivens( real_t xold, /**< Matrix entry to be normalised. */ + real_t yold, /**< Matrix entry to be annihilated. */ + real_t* xnew, /**< Output: Normalised matrix entry. */ + real_t* ynew, /**< Output: Annihilated matrix entry. */ + real_t* c, /**< Output: Cosine entry of Givens matrix. */ + real_t* s /**< Output: Sine entry of Givens matrix. */ + ); + +/** Applies Givens matrix determined by c and s (cf. computeGivens). + * \return SUCCESSFUL_RETURN */ +static inline void QProblemB_applyGivens( real_t c, /**< Cosine entry of Givens matrix. */ + real_t s, /**< Sine entry of Givens matrix. */ + real_t nu, /**< Further factor: s/(1+c). */ + real_t xold, /**< Matrix entry to be transformed corresponding to + * the normalised entry of the original matrix. */ + real_t yold, /**< Matrix entry to be transformed corresponding to + * the annihilated entry of the original matrix. */ + real_t* xnew, /**< Output: Transformed matrix entry corresponding to + * the normalised entry of the original matrix. */ + real_t* ynew /**< Output: Transformed matrix entry corresponding to + * the annihilated entry of the original matrix. */ + ); + + + +/** Compute relative length of homotopy in data space for termination + * criterion. + * \return Relative length in data space. */ +real_t QProblemB_getRelativeHomotopyLength( QProblemB* _THIS, + const real_t* const g_new, /**< Final gradient. */ + const real_t* const lb_new, /**< Final lower variable bounds. */ + const real_t* const ub_new /**< Final upper variable bounds. */ + ); + +/** Ramping Strategy to avoid ties. Modifies homotopy start without + * changing current active set. + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_performRamping( QProblemB* _THIS ); + + +/** ... */ +returnValue QProblemB_updateFarBounds( QProblemB* _THIS, + real_t curFarBound, /**< ... */ + int nRamp, /**< ... */ + const real_t* const lb_new, /**< ... */ + real_t* const lb_new_far, /**< ... */ + const real_t* const ub_new, /**< ... */ + real_t* const ub_new_far /**< ... */ + ); + + + +/** Performs robustified ratio test yield the maximum possible step length + * along the homotopy path. + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_performRatioTestB( QProblemB* _THIS, + int nIdx, /**< Number of ratios to be checked. */ + const int* const idxList, /**< Array containing the indices of all ratios to be checked. */ + Bounds* const subjectTo, /**< Bound object corresponding to ratios to be checked. */ + const real_t* const num, /**< Array containing all numerators for performing the ratio test. */ + const real_t* const den, /**< Array containing all denominators for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t* t, /**< Output: Maximum possible step length along the homotopy path. */ + int* BC_idx /**< Output: Index of blocking constraint. */ + ); + +/** Checks whether given ratio is blocking, i.e. limits the maximum step length + * along the homotopy path to a value lower than given one. + * \return SUCCESSFUL_RETURN */ +static inline BooleanType QProblemB_isBlocking( QProblemB* _THIS, + real_t num, /**< Numerator for performing the ratio test. */ + real_t den, /**< Denominator for performing the ratio test. */ + real_t epsNum, /**< Numerator tolerance. */ + real_t epsDen, /**< Denominator tolerance. */ + real_t* t /**< Input: Current maximum step length along the homotopy path, + * Output: Updated maximum possible step length along the homotopy path. */ + ); + + +/** Solves a QProblemB whose QP data is assumed to be stored in the member variables. + * A guess for its primal/dual optimal solution vectors and the corresponding + * optimal working set can be provided. + * Note: This function is internally called by all init functions! + * \return SUCCESSFUL_RETURN \n + RET_INIT_FAILED \n + RET_INIT_FAILED_CHOLESKY \n + RET_INIT_FAILED_HOTSTART \n + RET_INIT_FAILED_INFEASIBILITY \n + RET_INIT_FAILED_UNBOUNDEDNESS \n + RET_MAX_NWSR_REACHED */ +returnValue QProblemB_solveInitialQP( QProblemB* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector.*/ + const real_t* const yOpt, /**< Optimal dual solution vector. */ + Bounds* const guessedBounds, /**< Optimal working set of bounds for solution (xOpt,yOpt). */ + const real_t* const _R, /**< Pre-computed (upper triangular) Cholesky factor of Hessian matrix. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + * Output: Number of performed working set recalculations. */ + real_t* const cputime /**< Input: Maximum CPU time allowed for QP solution. \n + * Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + ); + +/** Solves an initialised QProblemB using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblemB_solveQP( QProblemB* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + int nWSRperformed, /**< Number of working set recalculations already performed to solve + this QP within previous solveQP() calls. This number is + always zero, except for successive calls from solveRegularisedQP() + or when using the far bound strategy. */ + BooleanType isFirstCall /**< Indicating whether this is the first call for current QP. */ + ); + + +/** Solves an initialised QProblemB using online active set strategy. + * Note: This function is internally called by all hotstart functions! + * \return SUCCESSFUL_RETURN \n + RET_MAX_NWSR_REACHED \n + RET_HOTSTART_FAILED_AS_QP_NOT_INITIALISED \n + RET_HOTSTART_FAILED \n + RET_SHIFT_DETERMINATION_FAILED \n + RET_STEPDIRECTION_DETERMINATION_FAILED \n + RET_STEPLENGTH_DETERMINATION_FAILED \n + RET_HOMOTOPY_STEP_FAILED \n + RET_HOTSTART_STOPPED_INFEASIBILITY \n + RET_HOTSTART_STOPPED_UNBOUNDEDNESS */ +returnValue QProblemB_solveRegularisedQP( QProblemB* _THIS, + const real_t* const g_new, /**< Gradient of neighbouring QP to be solved. */ + const real_t* const lb_new, /**< Lower bounds of neighbouring QP to be solved. \n + If no lower bounds exist, a NULL pointer can be passed. */ + const real_t* const ub_new, /**< Upper bounds of neighbouring QP to be solved. \n + If no upper bounds exist, a NULL pointer can be passed. */ + int* nWSR, /**< Input: Maximum number of working set recalculations; \n + Output: Number of performed working set recalculations. */ + real_t* const cputime, /**< Input: Maximum CPU time allowed for QP solution. \n + Output: CPU time spent for QP solution (or to perform nWSR iterations). */ + int nWSRperformed, /**< Number of working set recalculations already performed to solve + this QP within previous solveRegularisedQP() calls. This number is + always zero, except for successive calls when using the far bound strategy. */ + BooleanType isFirstCall /**< Indicating whether this is the first call for current QP. */ + ); + + +/** Sets up bound data structure according to auxiliaryBounds. + * (If the working set shall be setup afresh, make sure that + * bounds data structure has been resetted!) + * \return SUCCESSFUL_RETURN \n + RET_SETUP_WORKINGSET_FAILED \n + RET_INVALID_ARGUMENTS \n + RET_UNKNOWN_BUG */ +returnValue QProblemB_setupAuxiliaryWorkingSet( QProblemB* _THIS, + Bounds* const auxiliaryBounds, /**< Working set for auxiliary QP. */ + BooleanType setupAfresh /**< Flag indicating if given working set shall be + * setup afresh or by updating the current one. */ + ); + +/** Sets up the optimal primal/dual solution of the auxiliary initial QP. + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_setupAuxiliaryQPsolution( QProblemB* _THIS, + const real_t* const xOpt, /**< Optimal primal solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + const real_t* const yOpt /**< Optimal dual solution vector. + * If a NULL pointer is passed, all entries are set to zero. */ + ); + +/** Sets up gradient of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS have already been (ialised!). + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_setupAuxiliaryQPgradient( QProblemB* _THIS ); + +/** Sets up bounds of the auxiliary initial QP for given + * optimal primal/dual solution and given initial working set + * (assumes that members X, Y and BOUNDS have already been initialised!). + * \return SUCCESSFUL_RETURN \n + RET_UNKNOWN_BUG */ +returnValue QProblemB_setupAuxiliaryQPbounds( QProblemB* _THIS, + BooleanType useRelaxation /**< Flag indicating if inactive bounds shall be relaxed. */ + ); + + +/** Updates QP vectors, working sets and internal data structures in order to + start from an optimal solution corresponding to initial guesses of the working + set for bounds + * \return SUCCESSFUL_RETURN \n + * RET_SETUP_AUXILIARYQP_FAILED */ +returnValue QProblemB_setupAuxiliaryQP( QProblemB* _THIS, + Bounds* const guessedBounds /**< Initial guess for working set of bounds. */ + ); + +/** Determines step direction of the homotopy path. + * \return SUCCESSFUL_RETURN \n + RET_STEPDIRECTION_FAILED_CHOLESKY */ +returnValue QProblemB_determineStepDirection( QProblemB* _THIS, + const real_t* const delta_g, /**< Step direction of gradient vector. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + BooleanType Delta_bB_isZero, /**< Indicates if active bounds are to be shifted. */ + real_t* const delta_xFX, /**< Output: Primal homotopy step direction of fixed variables. */ + real_t* const delta_xFR, /**< Output: Primal homotopy step direction of free variables. */ + real_t* const delta_yFX /**< Output: Dual homotopy step direction of fixed variables' multiplier. */ + ); + +/** Determines the maximum possible step length along the homotopy path + * and performs _THIS step (without changing working set). + * \return SUCCESSFUL_RETURN \n + * RET_QP_INFEASIBLE \n + */ +returnValue QProblemB_performStep( QProblemB* _THIS, + const real_t* const delta_g, /**< Step direction of gradient. */ + const real_t* const delta_lb, /**< Step direction of lower bounds. */ + const real_t* const delta_ub, /**< Step direction of upper bounds. */ + const real_t* const delta_xFX, /**< Primal homotopy step direction of fixed variables. */ + const real_t* const delta_xFR, /**< Primal homotopy step direction of free variables. */ + const real_t* const delta_yFX, /**< Dual homotopy step direction of fixed variables' multiplier. */ + int* BC_idx, /**< Output: Index of blocking constraint. */ + SubjectToStatus* BC_status /**< Output: Status of blocking constraint. */ + ); + +/** Updates active set. + * \return SUCCESSFUL_RETURN \n + RET_REMOVE_FROM_ACTIVESET_FAILED \n + RET_ADD_TO_ACTIVESET_FAILED */ +returnValue QProblemB_changeActiveSet( QProblemB* _THIS, + int BC_idx, /**< Index of blocking constraint. */ + SubjectToStatus BC_status /**< Status of blocking constraint. */ + ); + +/** Drift correction at end of each active set iteration + * \return SUCCESSFUL_RETURN */ +returnValue QProblemB_performDriftCorrection( QProblemB* _THIS ); + +/** Determines if it is more efficient to refactorise the matrices when + * hotstarting or not (i.e. better to update the existing factorisations). + * \return BT_TRUE iff matrices shall be refactorised afresh + */ +BooleanType QProblemB_shallRefactorise( QProblemB* _THIS, + Bounds* const guessedBounds /**< Guessed new working set. */ + ); + + +/** Adds a bound to active set (specialised version for the case where no constraints exist). + * \return SUCCESSFUL_RETURN \n + RET_ADDBOUND_FAILED */ +returnValue QProblemB_addBound( QProblemB* _THIS, + int number, /**< Number of bound to be added to active set. */ + SubjectToStatus B_status, /**< Status of new active bound. */ + BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */ + ); + +/** Removes a bounds from active set (specialised version for the case where no constraints exist). + * \return SUCCESSFUL_RETURN \n + RET_HESSIAN_NOT_SPD \n + RET_REMOVEBOUND_FAILED */ +returnValue QProblemB_removeBound( QProblemB* _THIS, + int number, /**< Number of bound to be removed from active set. */ + BooleanType updateCholesky /**< Flag indicating if Cholesky decomposition shall be updated. */ + ); + + +/** Prints concise information on the current iteration. + * \return SUCCESSFUL_RETURN \n */ +returnValue QProblemB_printIteration( QProblemB* _THIS, + int iter, /**< Number of current iteration. */ + int BC_idx, /**< Index of blocking bound. */ + SubjectToStatus BC_status, /**< Status of blocking bound. */ + real_t homotopyLength, /**< Current homotopy distance. */ + BooleanType isFirstCall /**< Indicating whether this is the first call for current QP. */ + ); + + + +/* + * g e t B o u n d s + */ +static inline returnValue QProblemB_getBounds( QProblemB* _THIS, Bounds* _bounds ) +{ + int nV = QProblemB_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + _bounds = _THIS->bounds; + + return SUCCESSFUL_RETURN; +} + + +/* + * g e t N V + */ +static inline int QProblemB_getNV( QProblemB* _THIS ) +{ + return Bounds_getNV( _THIS->bounds ); +} + + +/* + * g e t N F R + */ +static inline int QProblemB_getNFR( QProblemB* _THIS ) +{ + return Bounds_getNFR( _THIS->bounds ); +} + + +/* + * g e t N F X + */ +static inline int QProblemB_getNFX( QProblemB* _THIS ) +{ + return Bounds_getNFX( _THIS->bounds ); +} + + +/* + * g e t N F V + */ +static inline int QProblemB_getNFV( QProblemB* _THIS ) +{ + return Bounds_getNFV( _THIS->bounds ); +} + + +/* + * g e t S t a t u s + */ +static inline QProblemStatus QProblemB_getStatus( QProblemB* _THIS ) +{ + return _THIS->status; +} + + +/* + * i s I n i t i a l i s e d + */ +static inline BooleanType QProblemB_isInitialised( QProblemB* _THIS ) +{ + if ( _THIS->status == QPS_NOTINITIALISED ) + return BT_FALSE; + else + return BT_TRUE; +} + + +/* + * i s S o l v e d + */ +static inline BooleanType QProblemB_isSolved( QProblemB* _THIS ) +{ + if ( _THIS->status == QPS_SOLVED ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * i s I n f e a s i b l e + */ +static inline BooleanType QProblemB_isInfeasible( QProblemB* _THIS ) +{ + return _THIS->infeasible; +} + + +/* + * i s U n b o u n d e d + */ +static inline BooleanType QProblemB_isUnbounded( QProblemB* _THIS ) +{ + return _THIS->unbounded; +} + + +/* + * g e t H e s s i a n T y p e + */ +static inline HessianType QProblemB_getHessianType( QProblemB* _THIS ) +{ + return _THIS->hessianType; +} + + +/* + * s e t H e s s i a n T y p e + */ +static inline returnValue QProblemB_setHessianType( QProblemB* _THIS, HessianType _hessianType ) +{ + _THIS->hessianType = _hessianType; + return SUCCESSFUL_RETURN; +} + + +/* + * u s i n g R e g u l a r i s a t i o n + */ +static inline BooleanType QProblemB_usingRegularisation( QProblemB* _THIS ) +{ + if ( _THIS->regVal > QPOASES_ZERO ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * g e t O p t i o n s + */ +static inline Options QProblemB_getOptions( QProblemB* _THIS ) +{ + return _THIS->options; +} + + +/* + * s e t O p t i o n s + */ +static inline returnValue QProblemB_setOptions( QProblemB* _THIS, + Options _options + ) +{ + OptionsCPY( &_options,&(_THIS->options) ); + Options_ensureConsistency( &(_THIS->options) ); + + QProblemB_setPrintLevel( _THIS,_THIS->options.printLevel ); + + return SUCCESSFUL_RETURN; +} + + +/* + * g e t P r i n t L e v e l + */ +static inline PrintLevel QProblemB_getPrintLevel( QProblemB* _THIS ) +{ + return _THIS->options.printLevel; +} + + + +/* + * g e t C o u n t + */ +static inline unsigned int QProblemB_getCount( QProblemB* _THIS ) +{ + return _THIS->count; +} + + +/* + * r e s e t C o u n t e r + */ +static inline returnValue QProblemB_resetCounter( QProblemB* _THIS ) +{ + _THIS->count = 0; + return SUCCESSFUL_RETURN; +} + + + +/***************************************************************************** + * P R O T E C T E D * + *****************************************************************************/ + + +/* + * s e t H + */ +static inline returnValue QProblemB_setHM( QProblemB* _THIS, DenseMatrix* H_new ) +{ + if ( H_new == 0 ) + return QProblemB_setH( _THIS,(real_t*)0 ); + else + return QProblemB_setH( _THIS,DenseMatrix_getVal(H_new) ); +} + + +/* + * s e t H + */ +static inline returnValue QProblemB_setH( QProblemB* _THIS, real_t* const H_new ) +{ + /* if null pointer is passed, Hessian is set to zero matrix + * (or stays identity matrix) */ + if ( H_new == 0 ) + { + if ( _THIS->hessianType == HST_IDENTITY ) + return SUCCESSFUL_RETURN; + + _THIS->hessianType = HST_ZERO; + + _THIS->H = 0; + } + else + { + DenseMatrixCON( _THIS->H,QProblemB_getNV( _THIS ),QProblemB_getNV( _THIS ),QProblemB_getNV( _THIS ),H_new ); + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t G + */ +static inline returnValue QProblemB_setG( QProblemB* _THIS, const real_t* const g_new ) +{ + unsigned int nV = (unsigned int)QProblemB_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( g_new == 0 ) + return THROWERROR( RET_INVALID_ARGUMENTS ); + + memcpy( _THIS->g,g_new,nV*sizeof(real_t) ); + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B + */ +static inline returnValue QProblemB_setLB( QProblemB* _THIS, const real_t* const lb_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)QProblemB_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( lb_new != 0 ) + { + memcpy( _THIS->lb,lb_new,nV*sizeof(real_t) ); + } + else + { + /* if no lower bounds are specified, set them to -infinity */ + for( i=0; ilb[i] = -QPOASES_INFTY; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t L B + */ +static inline returnValue QProblemB_setLBn( QProblemB* _THIS, int number, real_t value ) +{ + int nV = QProblemB_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ( number >= 0 ) && ( number < nV ) ) + { + _THIS->lb[number] = value; + return SUCCESSFUL_RETURN; + } + else + { + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); + } +} + + +/* + * s e t U B + */ +static inline returnValue QProblemB_setUB( QProblemB* _THIS, const real_t* const ub_new ) +{ + unsigned int i; + unsigned int nV = (unsigned int)QProblemB_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ub_new != 0 ) + { + memcpy( _THIS->ub,ub_new,nV*sizeof(real_t) ); + } + else + { + /* if no upper bounds are specified, set them to infinity */ + for( i=0; iub[i] = QPOASES_INFTY; + } + + return SUCCESSFUL_RETURN; +} + + +/* + * s e t U B + */ +static inline returnValue QProblemB_setUBn( QProblemB* _THIS, int number, real_t value ) +{ + int nV = QProblemB_getNV( _THIS ); + + if ( nV == 0 ) + return THROWERROR( RET_QPOBJECT_NOT_SETUP ); + + if ( ( number >= 0 ) && ( number < nV ) ) + { + _THIS->ub[number] = value; + + return SUCCESSFUL_RETURN; + } + else + { + return THROWERROR( RET_INDEX_OUT_OF_BOUNDS ); + } +} + + +/* + * c o m p u t e G i v e n s + */ +static inline void QProblemB_computeGivens( real_t xold, real_t yold, + real_t* xnew, real_t* ynew, real_t* c, real_t* s + ) +{ + real_t t, mu; + + if ( fabs( yold ) <= QPOASES_ZERO ) + { + *c = 1.0; + *s = 0.0; + + *xnew = xold; + *ynew = yold; + } + else + { + mu = fabs( xold ); + if ( fabs( yold ) > mu ) + mu = fabs( yold ); + + t = mu * sqrt( (xold/mu)*(xold/mu) + (yold/mu)*(yold/mu) ); + + if ( xold < 0.0 ) + t = -t; + + *c = xold/t; + *s = yold/t; + *xnew = t; + *ynew = 0.0; + } + + return; +} + + +/* + * a p p l y G i v e n s + */ +static inline void QProblemB_applyGivens( real_t c, real_t s, real_t nu, real_t xold, real_t yold, + real_t* xnew, real_t* ynew + ) +{ + #ifdef __USE_THREE_MULTS_GIVENS__ + + /* Givens plane rotation requiring only three multiplications, + * cf. Hammarling, S.: A note on modifications to the givens plane rotation. + * J. Inst. Maths Applics, 13:215-218, 1974. */ + *xnew = xold*c + yold*s; + *ynew = (*xnew+xold)*nu - yold; + + #else + + /* Usual Givens plane rotation requiring four multiplications. */ + *xnew = c*xold + s*yold; + *ynew = -s*xold + c*yold; + + #endif + + return; +} + + +/* + * i s B l o c k i n g + */ +static inline BooleanType QProblemB_isBlocking( QProblemB* _THIS, + real_t num, + real_t den, + real_t epsNum, + real_t epsDen, + real_t* t + ) +{ + if ( ( den >= epsDen ) && ( num >= epsNum ) ) + { + if ( num < (*t)*den ) + return BT_TRUE; + } + + return BT_FALSE; +} + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_QPROBLEMB_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Types.h b/third_party/acados/include/qpOASES_e/Types.h new file mode 100644 index 0000000000..fc042aed82 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Types.h @@ -0,0 +1,310 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Types.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of all non-built-in types (except for classes). + */ + + +#ifndef QPOASES_TYPES_H +#define QPOASES_TYPES_H + +#ifdef USE_ACADOS_TYPES +#include "acados/utils/types.h" +#endif + +/* If your compiler does not support the snprintf() function, + * uncomment the following line and try to compile again. */ +/* #define __NO_SNPRINTF__ */ + + +/* Uncomment the following line for setting the __DSPACE__ flag. */ +/* #define __DSPACE__ */ + +/* Uncomment the following line for setting the __XPCTARGET__ flag. */ +/* #define __XPCTARGET__ */ + + +/* Uncomment the following line for setting the __NO_FMATH__ flag. */ +/* #define __NO_FMATH__ */ + +/* Uncomment the following line to enable debug information. */ +/* #define __DEBUG__ */ + +/* Uncomment the following line to enable suppress any kind of console output. */ +/* #define __SUPPRESSANYOUTPUT__ */ + + +/** Forces to always include all implicitly fixed bounds and all equality constraints + * into the initial working set when setting up an auxiliary QP. */ +#define __ALWAYS_INITIALISE_WITH_ALL_EQUALITIES__ + +/* Uncomment the following line to activate the use of an alternative Givens + * plane rotation requiring only three multiplications. */ +/* #define __USE_THREE_MULTS_GIVENS__ */ + +/* Uncomment the following line to activate the use of single precision arithmetic. */ +/* #define __USE_SINGLE_PRECISION__ */ + +/* The inline keyword is skipped by default as it is not part of the C90 standard. + * However, by uncommenting the following line, use of the inline keyword can be enforced. */ +/* #define __USE_INLINE__ */ + + +/* Work-around for Borland BCC 5.5 compiler. */ +#ifdef __BORLANDC__ +#if __BORLANDC__ < 0x0561 + #define __STDC__ 1 +#endif +#endif + + +/* Work-around for Microsoft compilers. */ +#ifdef _MSC_VER + #define __NO_SNPRINTF__ + #pragma warning( disable : 4061 4100 4250 4514 4996 ) +#endif + + +/* Apply pre-processor settings when using qpOASES within auto-generated code. */ +#ifdef __CODE_GENERATION__ + #define __NO_COPYRIGHT__ + #define __EXTERNAL_DIMENSIONS__ +#endif /* __CODE_GENERATION__ */ + + +/* Avoid using static variables declaration within functions. */ +#ifdef __NO_STATIC__ + #define myStatic +#else + #define myStatic static +#endif /* __NO_STATIC__ */ + + +/* Skip inline keyword if not specified otherwise. */ +#ifndef __USE_INLINE__ + #define inline +#endif + + +/* Avoid any printing on embedded platforms. */ +#if defined(__DSPACE__) || defined(__XPCTARGET__) + #define __SUPPRESSANYOUTPUT__ + #define __NO_SNPRINTF__ +#endif + + +#ifdef __NO_SNPRINTF__ + #if (!defined(_MSC_VER)) || defined(__DSPACE__) || defined(__XPCTARGET__) + /* If snprintf is not available, provide an empty implementation... */ + int snprintf( char* s, size_t n, const char* format, ... ); + #else + /* ... or substitute snprintf by _snprintf for Microsoft compilers. */ + #define snprintf _snprintf + #endif +#endif /* __NO_SNPRINTF__ */ + + +/** Macro for switching on/off the beginning of the qpOASES namespace definition. */ +#define BEGIN_NAMESPACE_QPOASES + +/** Macro for switching on/off the end of the qpOASES namespace definition. */ +#define END_NAMESPACE_QPOASES + +/** Macro for switching on/off the use of the qpOASES namespace. */ +#define USING_NAMESPACE_QPOASES + +/** Macro for switching on/off references to the qpOASES namespace. */ +#define REFER_NAMESPACE_QPOASES /*::*/ + + +/** Macro for accessing the Cholesky factor R. */ +#define RR( I,J ) _THIS->R[(I)+nV*(J)] + +/** Macro for accessing the orthonormal matrix Q of the QT factorisation. */ +#define QQ( I,J ) _THIS->Q[(I)+nV*(J)] + +/** Macro for accessing the triangular matrix T of the QT factorisation. */ +#define TT( I,J ) _THIS->T[(I)*nVC_min+(J)] + + + +BEGIN_NAMESPACE_QPOASES + + +/** Defines real_t for facilitating switching between double and float. */ + +#ifndef USE_ACADOS_TYPES +#ifndef __CODE_GENERATION__ + + #ifdef __USE_SINGLE_PRECISION__ + typedef float real_t; + #else + typedef double real_t; + #endif /* __USE_SINGLE_PRECISION__ */ + +#endif /* __CODE_GENERATION__ */ +#endif /* USE_ACADOS_TYPES */ + +/** Summarises all possible logical values. */ +typedef enum +{ + BT_FALSE = 0, /**< Logical value for "false". */ + BT_TRUE /**< Logical value for "true". */ +} BooleanType; + + +/** Summarises all possible print levels. Print levels are used to describe + * the desired amount of output during runtime of qpOASES. */ +typedef enum +{ + PL_DEBUG_ITER = -2, /**< Full tabular debugging output. */ + PL_TABULAR, /**< Tabular output. */ + PL_NONE, /**< No output. */ + PL_LOW, /**< Print error messages only. */ + PL_MEDIUM, /**< Print error and warning messages as well as concise info messages. */ + PL_HIGH /**< Print all messages with full details. */ +} PrintLevel; + + +/** Defines visibility status of a message. */ +typedef enum +{ + VS_HIDDEN, /**< Message not visible. */ + VS_VISIBLE /**< Message visible. */ +} VisibilityStatus; + + +/** Summarises all possible states of the (S)QProblem(B) object during the +solution process of a QP sequence. */ +typedef enum +{ + QPS_NOTINITIALISED, /**< QProblem object is freshly instantiated or reset. */ + QPS_PREPARINGAUXILIARYQP, /**< An auxiliary problem is currently setup, either at the very beginning + * via an initial homotopy or after changing the QP matrices. */ + QPS_AUXILIARYQPSOLVED, /**< An auxilary problem was solved, either at the very beginning + * via an initial homotopy or after changing the QP matrices. */ + QPS_PERFORMINGHOMOTOPY, /**< A homotopy according to the main idea of the online active + * set strategy is performed. */ + QPS_HOMOTOPYQPSOLVED, /**< An intermediate QP along the homotopy path was solved. */ + QPS_SOLVED /**< The solution of the actual QP was found. */ +} QProblemStatus; + + +/** Summarises all possible types of the QP's Hessian matrix. */ +typedef enum +{ + HST_ZERO, /**< Hessian is zero matrix (i.e. LP formulation). */ + HST_IDENTITY, /**< Hessian is identity matrix. */ + HST_POSDEF, /**< Hessian is (strictly) positive definite. */ + HST_POSDEF_NULLSPACE, /**< Hessian is positive definite on null space of active bounds/constraints. */ + HST_SEMIDEF, /**< Hessian is positive semi-definite. */ + HST_INDEF, /**< Hessian is indefinite. */ + HST_UNKNOWN /**< Hessian type is unknown. */ +} HessianType; + + +/** Summarises all possible types of bounds and constraints. */ +typedef enum +{ + ST_UNBOUNDED, /**< Bound/constraint is unbounded. */ + ST_BOUNDED, /**< Bound/constraint is bounded but not fixed. */ + ST_EQUALITY, /**< Bound/constraint is fixed (implicit equality bound/constraint). */ + ST_DISABLED, /**< Bound/constraint is disabled (i.e. ignored when solving QP). */ + ST_UNKNOWN /**< Type of bound/constraint unknown. */ +} SubjectToType; + + +/** Summarises all possible states of bounds and constraints. */ +typedef enum +{ + ST_LOWER = -1, /**< Bound/constraint is at its lower bound. */ + ST_INACTIVE, /**< Bound/constraint is inactive. */ + ST_UPPER, /**< Bound/constraint is at its upper bound. */ + ST_INFEASIBLE_LOWER, /**< (to be documented) */ + ST_INFEASIBLE_UPPER, /**< (to be documented) */ + ST_UNDEFINED /**< Status of bound/constraint undefined. */ +} SubjectToStatus; + + +/** + * \brief Stores internal information for tabular (debugging) output. + * + * Struct storing internal information for tabular (debugging) output + * when using the (S)QProblem(B) objects. + * + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2013-2015 + */ +typedef struct +{ + int idxAddB; /**< Index of bound that has been added to working set. */ + int idxRemB; /**< Index of bound that has been removed from working set. */ + int idxAddC; /**< Index of constraint that has been added to working set. */ + int idxRemC; /**< Index of constraint that has been removed from working set. */ + int excAddB; /**< Flag indicating whether a bound has been added to working set to keep a regular projected Hessian. */ + int excRemB; /**< Flag indicating whether a bound has been removed from working set to keep a regular projected Hessian. */ + int excAddC; /**< Flag indicating whether a constraint has been added to working set to keep a regular projected Hessian. */ + int excRemC; /**< Flag indicating whether a constraint has been removed from working set to keep a regular projected Hessian. */ +} TabularOutput; + +/** + * \brief Struct containing the variable header for mat file. + * + * Struct storing the header of a variable to be stored in + * Matlab's binary format (using the outdated Level 4 variant + * for simplictiy). + * + * Note, this code snippet has been inspired from the document + * "Matlab(R) MAT-file Format, R2013b" by MathWorks + * + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2013-2015 + */ +typedef struct +{ + long numericFormat; /**< Flag indicating numerical format. */ + long nRows; /**< Number of rows. */ + long nCols; /**< Number of rows. */ + long imaginaryPart; /**< (to be documented) */ + long nCharName; /**< Number of character in name. */ +} MatMatrixHeader; + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_TYPES_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/UnitTesting.h b/third_party/acados/include/qpOASES_e/UnitTesting.h new file mode 100644 index 0000000000..dbff201039 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/UnitTesting.h @@ -0,0 +1,79 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/UnitTesting.h + * \author Hans Joachim Ferreau + * \version 3.1embedded + * \date 2014-2015 + * + * Definition of auxiliary functions/macros for unit testing. + */ + + +#ifndef QPOASES_UNIT_TESTING_H +#define QPOASES_UNIT_TESTING_H + + +#ifndef TEST_TOL_FACTOR +#define TEST_TOL_FACTOR 1 +#endif + + +/** Return value for tests that passed. */ +#define TEST_PASSED 0 + +/** Return value for tests that failed. */ +#define TEST_FAILED 1 + +/** Return value for tests that could not run due to missing external data. */ +#define TEST_DATA_NOT_FOUND 99 + + +/** Macro verifying that two numerical values are equal in order to pass unit test. */ +#define QPOASES_TEST_FOR_EQUAL( x,y ) if ( REFER_NAMESPACE_QPOASES isEqual( (x),(y) ) == BT_FALSE ) { return TEST_FAILED; } + +/** Macro verifying that two numerical values are close to each other in order to pass unit test. */ +#define QPOASES_TEST_FOR_NEAR( x,y ) if ( REFER_NAMESPACE_QPOASES getAbs((x)-(y)) / REFER_NAMESPACE_QPOASES getMax( 1.0,REFER_NAMESPACE_QPOASES getAbs(x) ) >= 1e-10 ) { return TEST_FAILED; } + +/** Macro verifying that first quantity is lower or equal than second one in order to pass unit test. */ +#define QPOASES_TEST_FOR_TOL( x,tol ) if ( (x) > (tol)*(TEST_TOL_FACTOR) ) { return TEST_FAILED; } + +/** Macro verifying that a logical expression holds in order to pass unit test. */ +#define QPOASES_TEST_FOR_TRUE( x ) if ( (x) == 0 ) { return TEST_FAILED; } + + + +BEGIN_NAMESPACE_QPOASES + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_UNIT_TESTING_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/Utils.h b/third_party/acados/include/qpOASES_e/Utils.h new file mode 100644 index 0000000000..75e45a56a0 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/Utils.h @@ -0,0 +1,500 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/Utils.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of some utilities for working with the different QProblem classes. + */ + + +#ifndef QPOASES_UTILS_H +#define QPOASES_UTILS_H + +#include + + +BEGIN_NAMESPACE_QPOASES + + +/** Prints a vector. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printV( const real_t* const v, /**< Vector to be printed. */ + int n /**< Length of vector. */ + ); + +/** Prints a permuted vector. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printPV( const real_t* const v, /**< Vector to be printed. */ + int n, /**< Length of vector. */ + const int* const V_idx /**< Pemutation vector. */ + ); + +/** Prints a named vector. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printNV( const real_t* const v, /**< Vector to be printed. */ + int n, /**< Length of vector. */ + const char* name /** Name of vector. */ + ); + +/** Prints a matrix. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printM( const real_t* const M, /**< Matrix to be printed. */ + int nrow, /**< Row number of matrix. */ + int ncol /**< Column number of matrix. */ + ); + +/** Prints a permuted matrix. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printPM( const real_t* const M, /**< Matrix to be printed. */ + int nrow, /**< Row number of matrix. */ + int ncol , /**< Column number of matrix. */ + const int* const ROW_idx, /**< Row pemutation vector. */ + const int* const COL_idx /**< Column pemutation vector. */ + ); + +/** Prints a named matrix. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printNM( const real_t* const M, /**< Matrix to be printed. */ + int nrow, /**< Row number of matrix. */ + int ncol, /**< Column number of matrix. */ + const char* name /** Name of matrix. */ + ); + +/** Prints an index array. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printI( const int* const _index, /**< Index array to be printed. */ + int n /**< Length of index array. */ + ); + +/** Prints a named index array. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printNI( const int* const _index, /**< Index array to be printed. */ + int n, /**< Length of index array. */ + const char* name /**< Name of index array. */ + ); + + +/** Prints a string to desired output target (useful also for MATLAB output!). + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_myPrintf( const char* s /**< String to be written. */ + ); + + +/** Prints qpOASES copyright notice. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_printCopyrightNotice( ); + + +/** Reads a real_t matrix from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE */ +returnValue qpOASES_readFromFileM( real_t* data, /**< Matrix to be read from file. */ + int nrow, /**< Row number of matrix. */ + int ncol, /**< Column number of matrix. */ + const char* datafilename /**< Data file name. */ + ); + +/** Reads a real_t vector from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE */ +returnValue qpOASES_readFromFileV( real_t* data, /**< Vector to be read from file. */ + int n, /**< Length of vector. */ + const char* datafilename /**< Data file name. */ + ); + +/** Reads an integer (column) vector from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE \n + RET_UNABLE_TO_READ_FILE */ +returnValue qpOASES_readFromFileI( int* data, /**< Vector to be read from file. */ + int n, /**< Length of vector. */ + const char* datafilename /**< Data file name. */ + ); + + +/** Writes a real_t matrix into a file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue qpOASES_writeIntoFileM( const real_t* const data, /**< Matrix to be written into file. */ + int nrow, /**< Row number of matrix. */ + int ncol, /**< Column number of matrix. */ + const char* datafilename, /**< Data file name. */ + BooleanType append /**< Indicates if data shall be appended if the file already exists (otherwise it is overwritten). */ + ); + +/** Writes a real_t vector into a file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue qpOASES_writeIntoFileV( const real_t* const data, /**< Vector to be written into file. */ + int n, /**< Length of vector. */ + const char* datafilename, /**< Data file name. */ + BooleanType append /**< Indicates if data shall be appended if the file already exists (otherwise it is overwritten). */ + ); + +/** Writes an integer (column) vector into a file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_OPEN_FILE */ +returnValue qpOASES_writeIntoFileI( const int* const integer, /**< Integer vector to be written into file. */ + int n, /**< Length of vector. */ + const char* datafilename, /**< Data file name. */ + BooleanType append /**< Indicates if integer shall be appended if the file already exists (otherwise it is overwritten). */ + ); + +/** Writes a real_t matrix/vector into a Matlab binary file. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS + RET_UNABLE_TO_WRITE_FILE */ +returnValue qpOASES_writeIntoMatFile( FILE* const matFile, /**< Pointer to Matlab binary file. */ + const real_t* const data, /**< Data to be written into file. */ + int nRows, /**< Row number of matrix. */ + int nCols, /**< Column number of matrix. */ + const char* name /**< Matlab name of matrix/vector to be stored. */ + ); + +/** Writes in integer matrix/vector into a Matlab binary file. + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS + RET_UNABLE_TO_WRITE_FILE */ +returnValue qpOASES_writeIntoMatFileI( FILE* const matFile, /**< Pointer to Matlab binary file. */ + const int* const data, /**< Data to be written into file. */ + int nRows, /**< Row number of matrix. */ + int nCols, /**< Column number of matrix. */ + const char* name /**< Matlab name of matrix/vector to be stored. */ + ); + + +/** Returns the current system time. + * \return current system time */ +real_t qpOASES_getCPUtime( ); + + +/** Returns the N-norm of a vector. + * \return >= 0.0: successful */ +real_t qpOASES_getNorm( const real_t* const v, /**< Vector. */ + int n, /**< Vector's dimension. */ + int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ); + +/** Tests whether two real-valued arguments are (numerically) equal. + * \return BT_TRUE: arguments differ not more than TOL \n + BT_FALSE: arguments differ more than TOL */ +static inline BooleanType qpOASES_isEqual( real_t x, /**< First real number. */ + real_t y, /**< Second real number. */ + real_t TOL /**< Tolerance for comparison. */ + ); + + +/** Tests whether a real-valued argument is (numerically) zero. + * \return BT_TRUE: argument differs from 0.0 not more than TOL \n + BT_FALSE: argument differs from 0.0 more than TOL */ +static inline BooleanType qpOASES_isZero( real_t x, /**< Real number. */ + real_t TOL /**< Tolerance for comparison. */ + ); + + +/** Returns sign of a real-valued argument. + * \return 1.0: argument is non-negative \n + -1.0: argument is negative */ +static inline real_t qpOASES_getSign( real_t arg /**< real-valued argument whose sign is to be determined. */ + ); + + +/** Returns maximum of two integers. + * \return Maximum of two integers */ +static inline int qpOASES_getMaxI( int x, /**< First integer. */ + int y /**< Second integer. */ + ); + + +/** Returns minimum of two integers. + * \return Minimum of two integers */ +static inline int qpOASES_getMinI( int x, /**< First integer. */ + int y /**< Second integer. */ + ); + + +/** Returns maximum of two reals. + * \return Maximum of two reals */ +static inline real_t qpOASES_getMax( real_t x, /**< First real number. */ + real_t y /**< Second real number. */ + ); + + +/** Returns minimum of two reals. + * \return Minimum of two reals */ +static inline real_t qpOASES_getMin( real_t x, /**< First real number. */ + real_t y /**< Second real number. */ + ); + + +/** Returns the absolute value of a real_t-valued argument. + * \return Absolute value of a real_t-valued argument */ +static inline real_t qpOASES_getAbs( real_t x /**< real_t-valued argument. */ + ); + +/** Returns the square-root of a real number. + * \return Square-root of a real number */ +static inline real_t qpOASES_getSqrt( real_t x /**< Non-negative real number. */ + ); + + +/** Computes the maximum violation of the KKT optimality conditions + * of given iterate for given QP data. */ +returnValue qpOASES_getKktViolation( int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + const real_t* const H, /**< Hessian matrix (may be NULL if Hessian is zero or identity matrix). */ + const real_t* const g, /**< Gradient vector. */ + const real_t* const A, /**< Constraint matrix. */ + const real_t* const lb, /**< Lower bound vector (on variables). */ + const real_t* const ub, /**< Upper bound vector (on variables). */ + const real_t* const lbA, /**< Lower constraints' bound vector. */ + const real_t* const ubA, /**< Upper constraints' bound vector. */ + const real_t* const x, /**< Primal trial vector. */ + const real_t* const y, /**< Dual trial vector. */ + real_t* const _stat, /**< Output: maximum value of stationarity condition residual. */ + real_t* const feas, /**< Output: maximum value of primal feasibility violation. */ + real_t* const cmpl /**< Output: maximum value of complementarity residual. */ + ); + +/** Computes the maximum violation of the KKT optimality conditions + * of given iterate for given QP data. */ +returnValue qpOASES_getKktViolationSB( int nV, /**< Number of variables. */ + const real_t* const H, /**< Hessian matrix (may be NULL if Hessian is zero or identity matrix). */ + const real_t* const g, /**< Gradient vector. */ + const real_t* const lb, /**< Lower bound vector (on variables). */ + const real_t* const ub, /**< Upper bound vector (on variables). */ + const real_t* const x, /**< Primal trial vector. */ + const real_t* const y, /**< Dual trial vector. */ + real_t* const _stat, /**< Output: maximum value of stationarity condition residual. */ + real_t* const feas, /**< Output: maximum value of primal feasibility violation. */ + real_t* const cmpl /**< Output: maximum value of complementarity residual. */ + ); + + +/** Writes a value of BooleanType into a string. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_convertBooleanTypeToString( BooleanType value, /**< Value to be written. */ + char* const string /**< Input: String of sufficient size, \n + Output: String containing value. */ + ); + +/** Writes a value of SubjectToStatus into a string. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_convertSubjectToStatusToString( SubjectToStatus value, /**< Value to be written. */ + char* const string /**< Input: String of sufficient size, \n + Output: String containing value. */ + ); + +/** Writes a value of PrintLevel into a string. + * \return SUCCESSFUL_RETURN */ +returnValue qpOASES_convertPrintLevelToString( PrintLevel value, /**< Value to be written. */ + char* const string /**< Input: String of sufficient size, \n + Output: String containing value. */ + ); + + +/** Converts a returnValue from an QProblem(B) object into a more + * simple status flag. + * + * \return 0: QP problem solved + * 1: QP could not be solved within given number of iterations + * -1: QP could not be solved due to an internal error + * -2: QP is infeasible (and thus could not be solved) + * -3: QP is unbounded (and thus could not be solved) + */ +int qpOASES_getSimpleStatus( returnValue returnvalue, /**< ReturnValue to be analysed. */ + BooleanType doPrintStatus /**< Flag indicating whether simple status shall be printed to screen. */ + ); + +/** Normalises QP constraints. + * \return SUCCESSFUL_RETURN \n + * RET_INVALID_ARGUMENTS */ +returnValue qpOASES_normaliseConstraints( int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + real_t* A, /**< Input: Constraint matrix, \n + Output: Normalised constraint matrix. */ + real_t* lbA, /**< Input: Constraints' lower bound vector, \n + Output: Normalised constraints' lower bound vector. */ + real_t* ubA, /**< Input: Constraints' upper bound vector, \n + Output: Normalised constraints' upper bound vector. */ + int type /**< Norm type, 1: one-norm, 2: Euclidean norm. */ + ); + + +#ifdef __DEBUG__ +/** Writes matrix with given dimension into specified file. */ +void gdb_printmat( const char *fname, /**< File name. */ + real_t *M, /**< Matrix to be written. */ + int n, /**< Number of rows. */ + int m, /**< Number of columns. */ + int ldim /**< Leading dimension. */ + ); +#endif /* __DEBUG__ */ + + +#if defined(__DSPACE__) || defined(__XPCTARGET__) +void __cxa_pure_virtual( void ); +#endif /* __DSPACE__ || __XPCTARGET__*/ + + + +/* + * i s E q u a l + */ +static inline BooleanType qpOASES_isEqual( real_t x, + real_t y, + real_t TOL + ) +{ + if ( qpOASES_getAbs(x-y) <= TOL ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * i s Z e r o + */ +static inline BooleanType qpOASES_isZero( real_t x, + real_t TOL + ) +{ + if ( qpOASES_getAbs(x) <= TOL ) + return BT_TRUE; + else + return BT_FALSE; +} + + +/* + * g e t S i g n + */ +static inline real_t qpOASES_getSign( real_t arg + ) +{ + if ( arg >= 0.0 ) + return 1.0; + else + return -1.0; +} + + + +/* + * g e t M a x + */ +static inline int qpOASES_getMaxI( int x, + int y + ) +{ + return (yx) ? x : y; +} + + +/* + * g e t M a x + */ +static inline real_t qpOASES_getMax( real_t x, + real_t y + ) +{ + #ifdef __NO_FMATH__ + return (yx) ? x : y; + #else + return (y>x) ? x : y; + /*return fmin(x,y); seems to be slower */ + #endif +} + + +/* + * g e t A b s + */ +static inline real_t qpOASES_getAbs( real_t x + ) +{ + #ifdef __NO_FMATH__ + return (x>=0.0) ? x : -x; + #else + return fabs(x); + #endif +} + +/* + * g e t S q r t + */ +static inline real_t qpOASES_getSqrt( real_t x + ) +{ + #ifdef __NO_FMATH__ + return sqrt(x); /* put your custom sqrt-replacement here */ + #else + return sqrt(x); + #endif +} + + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_UTILS_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/include/qpOASES_e/extras/OQPinterface.h b/third_party/acados/include/qpOASES_e/extras/OQPinterface.h new file mode 100644 index 0000000000..da59ea9db6 --- /dev/null +++ b/third_party/acados/include/qpOASES_e/extras/OQPinterface.h @@ -0,0 +1,227 @@ +/* + * This file is part of qpOASES. + * + * qpOASES -- An Implementation of the Online Active Set Strategy. + * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka, + * Christian Kirches et al. All rights reserved. + * + * qpOASES is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * qpOASES is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with qpOASES; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +/** + * \file include/qpOASES_e/extras/OQPinterface.h + * \author Hans Joachim Ferreau, Andreas Potschka, Christian Kirches + * \version 3.1embedded + * \date 2007-2015 + * + * Declaration of an interface comprising several utility functions + * for solving test problems from the Online QP Benchmark Collection + * (This collection is no longer maintained, see + * http://www.qpOASES.org/onlineQP for a backup). + */ + + +#ifndef QPOASES_OQPINTERFACE_H +#define QPOASES_OQPINTERFACE_H + + +#include +#include + +#include +#include + + +BEGIN_NAMESPACE_QPOASES + +typedef struct { + QProblem *qp; + + DenseMatrix *H; + DenseMatrix *A; + + real_t *x; + real_t *y; +} OQPbenchmark_ws; + +int OQPbenchmark_ws_calculateMemorySize( unsigned int nV, unsigned int nC ); + +char *OQPbenchmark_ws_assignMemory( unsigned int nV, unsigned int nC, OQPbenchmark_ws **mem, void *raw_memory ); + +OQPbenchmark_ws *OQPbenchmark_ws_createMemory( unsigned int nV, unsigned int nC ); + +typedef struct { + QProblemB *qp; + + DenseMatrix *H; + + real_t *x; + real_t *y; +} OQPbenchmarkB_ws; + +int OQPbenchmarkB_ws_calculateMemorySize( unsigned int nV ); + +char *OQPbenchmarkB_ws_assignMemory( unsigned int nV, OQPbenchmarkB_ws **mem, void *raw_memory ); + +OQPbenchmarkB_ws *OQPbenchmarkB_ws_createMemory( unsigned int nV ); + +typedef struct { + OQPbenchmark_ws *qp_ws; + OQPbenchmarkB_ws *qpB_ws; + + real_t *H; + real_t *g; + real_t *A; + real_t *lb; + real_t *ub; + real_t *lbA; + real_t *ubA; +} OQPinterface_ws; + +int OQPinterface_ws_calculateMemorySize( unsigned int nV, unsigned int nC, unsigned int nQP ); + +char *OQPinterface_ws_assignMemory( unsigned int nV, unsigned int nC, unsigned int nQP, OQPinterface_ws **mem, void *raw_memory ); + +OQPinterface_ws *OQPinterface_ws_createMemory( unsigned int nV, unsigned int nC, unsigned int nQP ); + +/** Reads dimensions of an Online QP Benchmark problem from file. + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_READ_FILE \n + RET_FILEDATA_INCONSISTENT */ +returnValue readOQPdimensions( const char* path, /**< Full path of the data files (without trailing slash!). */ + int* nQP, /**< Output: Number of QPs. */ + int* nV, /**< Output: Number of variables. */ + int* nC, /**< Output: Number of constraints. */ + int* nEC /**< Output: Number of equality constraints. */ + ); + +/** Reads data of an Online QP Benchmark problem from file. + * This function allocates the required memory for all data; after successfully calling it, + * you have to free this memory yourself! + * \return SUCCESSFUL_RETURN \n + RET_INVALID_ARGUMENTS \n + RET_UNABLE_TO_READ_FILE \n + RET_FILEDATA_INCONSISTENT */ +returnValue readOQPdata( const char* path, /**< Full path of the data files (without trailing slash!). */ + int* nQP, /**< Output: Number of QPs. */ + int* nV, /**< Output: Number of variables. */ + int* nC, /**< Output: Number of constraints. */ + int* nEC, /**< Output: Number of equality constraints. */ + real_t* H, /**< Output: Hessian matrix. */ + real_t* g, /**< Output: Sequence of gradient vectors. */ + real_t* A, /**< Output: Constraint matrix. */ + real_t* lb, /**< Output: Sequence of lower bound vectors (on variables). */ + real_t* ub, /**< Output: Sequence of upper bound vectors (on variables). */ + real_t* lbA, /**< Output: Sequence of lower constraints' bound vectors. */ + real_t* ubA, /**< Output: Sequence of upper constraints' bound vectors. */ + real_t* xOpt, /**< Output: Sequence of primal solution vectors + * (not read if a null pointer is passed). */ + real_t* yOpt, /**< Output: Sequence of dual solution vectors + * (not read if a null pointer is passed). */ + real_t* objOpt /**< Output: Sequence of optimal objective function values + * (not read if a null pointer is passed). */ + ); + + +/** Solves an Online QP Benchmark problem as specified by the arguments. + * The maximum deviations from the given optimal solution as well as the + * maximum CPU time to solve each QP are determined. + * \return SUCCESSFUL_RETURN \n + RET_BENCHMARK_ABORTED */ +returnValue solveOQPbenchmark( int nQP, /**< Number of QPs. */ + int nV, /**< Number of variables. */ + int nC, /**< Number of constraints. */ + int nEC, /**< Number of equality constraints. */ + real_t* _H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + real_t* _A, /**< Constraint matrix. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + const real_t* const lbA, /**< Sequence of lower constraints' bound vectors. */ + const real_t* const ubA, /**< Sequence of upper constraints' bound vectors. */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + BooleanType useHotstarts, /**< Shall QP solution be hotstarted? */ + const Options* options, /**< QP solver options to be used while solving benchmark problems. */ + int maxAllowedNWSR, /**< Maximum number of working set recalculations to be performed. */ + real_t* maxNWSR, /**< Output: Maximum number of performed working set recalculations. */ + real_t* avgNWSR, /**< Output: Average number of performed working set recalculations. */ + real_t* maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t* avgCPUtime, /**< Output: Average CPU time required for solving each QP. */ + real_t* maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t* maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t* maxComplementarity, /**< Output: Maximum residual of complementarity condition. */ + OQPbenchmark_ws *work /**< Workspace. */ + ); + +/** Solves an Online QP Benchmark problem (without constraints) as specified + * by the arguments. The maximum deviations from the given optimal solution + * as well as the maximum CPU time to solve each QP are determined. + * \return SUCCESSFUL_RETURN \n + RET_BENCHMARK_ABORTED */ +returnValue solveOQPbenchmarkB( int nQP, /**< Number of QPs. */ + int nV, /**< Number of variables. */ + real_t* _H, /**< Hessian matrix. */ + const real_t* const g, /**< Sequence of gradient vectors. */ + const real_t* const lb, /**< Sequence of lower bound vectors (on variables). */ + const real_t* const ub, /**< Sequence of upper bound vectors (on variables). */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + BooleanType useHotstarts, /**< Shall QP solution be hotstarted? */ + const Options* options, /**< QP solver options to be used while solving benchmark problems. */ + int maxAllowedNWSR, /**< Maximum number of working set recalculations to be performed. */ + real_t* maxNWSR, /**< Output: Maximum number of performed working set recalculations. */ + real_t* avgNWSR, /**< Output: Average number of performed working set recalculations. */ + real_t* maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t* avgCPUtime, /**< Output: Average CPU time required for solving each QP. */ + real_t* maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t* maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t* maxComplementarity, /**< Output: Maximum residual of complementarity condition. */ + OQPbenchmarkB_ws *work /**< Workspace. */ + ); + + +/** Runs an Online QP Benchmark problem and determines the maximum + * violation of the KKT optimality conditions as well as the + * maximum and average number of iterations and CPU time to solve + * each QP. + * + * \return SUCCESSFUL_RETURN \n + RET_UNABLE_TO_READ_BENCHMARK \n + RET_BENCHMARK_ABORTED */ +returnValue runOQPbenchmark( const char* path, /**< Full path of the benchmark files (without trailing slash!). */ + BooleanType isSparse, /**< Shall convert matrices to sparse format before solution? */ + BooleanType useHotstarts, /**< Shall QP solution be hotstarted? */ + const Options* options, /**< QP solver options to be used while solving benchmark problems. */ + int maxAllowedNWSR, /**< Maximum number of working set recalculations to be performed. */ + real_t* maxNWSR, /**< Output: Maximum number of performed working set recalculations. */ + real_t* avgNWSR, /**< Output: Average number of performed working set recalculations. */ + real_t* maxCPUtime, /**< Output: Maximum CPU time required for solving each QP. */ + real_t* avgCPUtime, /**< Output: Average CPU time required for solving each QP. */ + real_t* maxStationarity, /**< Output: Maximum residual of stationarity condition. */ + real_t* maxFeasibility, /**< Output: Maximum residual of primal feasibility condition. */ + real_t* maxComplementarity, /**< Output: Maximum residual of complementarity condition. */ + OQPinterface_ws* work /**< Workspace. */ + ); + +END_NAMESPACE_QPOASES + + +#endif /* QPOASES_OQPINTERFACE_H */ + + +/* + * end of file + */ diff --git a/third_party/acados/larch64/lib/libacados.so b/third_party/acados/larch64/lib/libacados.so new file mode 100644 index 0000000000..9a28b4c9d6 Binary files /dev/null and b/third_party/acados/larch64/lib/libacados.so differ diff --git a/third_party/acados/larch64/lib/libblasfeo.so b/third_party/acados/larch64/lib/libblasfeo.so new file mode 100644 index 0000000000..b97ed876e2 Binary files /dev/null and b/third_party/acados/larch64/lib/libblasfeo.so differ diff --git a/third_party/acados/larch64/lib/libhpipm.so b/third_party/acados/larch64/lib/libhpipm.so new file mode 100644 index 0000000000..cd4b1f1b5b Binary files /dev/null and b/third_party/acados/larch64/lib/libhpipm.so differ diff --git a/third_party/acados/larch64/lib/libqpOASES_e.so b/third_party/acados/larch64/lib/libqpOASES_e.so new file mode 120000 index 0000000000..14048625a1 --- /dev/null +++ b/third_party/acados/larch64/lib/libqpOASES_e.so @@ -0,0 +1 @@ +libqpOASES_e.so.3.1 \ No newline at end of file diff --git a/third_party/acados/larch64/lib/libqpOASES_e.so.3.1 b/third_party/acados/larch64/lib/libqpOASES_e.so.3.1 new file mode 100644 index 0000000000..19e7a69bd5 Binary files /dev/null and b/third_party/acados/larch64/lib/libqpOASES_e.so.3.1 differ diff --git a/third_party/acados/larch64/t_renderer b/third_party/acados/larch64/t_renderer new file mode 100755 index 0000000000..b6f70bde06 Binary files /dev/null and b/third_party/acados/larch64/t_renderer differ diff --git a/third_party/acados/x86_64/lib/libacados.so b/third_party/acados/x86_64/lib/libacados.so new file mode 100644 index 0000000000..ae5fc363f2 Binary files /dev/null and b/third_party/acados/x86_64/lib/libacados.so differ diff --git a/third_party/acados/x86_64/lib/libblasfeo.so b/third_party/acados/x86_64/lib/libblasfeo.so new file mode 100644 index 0000000000..676ff67e98 Binary files /dev/null and b/third_party/acados/x86_64/lib/libblasfeo.so differ diff --git a/third_party/acados/x86_64/lib/libhpipm.so b/third_party/acados/x86_64/lib/libhpipm.so new file mode 100644 index 0000000000..8d026b1185 Binary files /dev/null and b/third_party/acados/x86_64/lib/libhpipm.so differ diff --git a/third_party/acados/x86_64/lib/libqpOASES_e.so b/third_party/acados/x86_64/lib/libqpOASES_e.so new file mode 120000 index 0000000000..14048625a1 --- /dev/null +++ b/third_party/acados/x86_64/lib/libqpOASES_e.so @@ -0,0 +1 @@ +libqpOASES_e.so.3.1 \ No newline at end of file diff --git a/third_party/acados/x86_64/lib/libqpOASES_e.so.3.1 b/third_party/acados/x86_64/lib/libqpOASES_e.so.3.1 new file mode 100644 index 0000000000..c0c8b66650 Binary files /dev/null and b/third_party/acados/x86_64/lib/libqpOASES_e.so.3.1 differ diff --git a/third_party/acados/x86_64/t_renderer b/third_party/acados/x86_64/t_renderer new file mode 100755 index 0000000000..d84fc762c8 Binary files /dev/null and b/third_party/acados/x86_64/t_renderer differ diff --git a/third_party/bootstrap/.gitignore b/third_party/bootstrap/.gitignore new file mode 100644 index 0000000000..ac06c0cf85 --- /dev/null +++ b/third_party/bootstrap/.gitignore @@ -0,0 +1 @@ +/icons/ diff --git a/third_party/bootstrap/bootstrap-icons.svg b/third_party/bootstrap/bootstrap-icons.svg new file mode 100644 index 0000000000..61f2720db4 --- /dev/null +++ b/third_party/bootstrap/bootstrap-icons.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/third_party/bootstrap/pull.sh b/third_party/bootstrap/pull.sh new file mode 100755 index 0000000000..0b03b4db9e --- /dev/null +++ b/third_party/bootstrap/pull.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +cd $DIR + +if [ ! -d icons/ ]; then + git clone https://github.com/twbs/icons/ +fi + +cd icons +git fetch --all +git checkout d5aa187483a1b0b186f87adcfa8576350d970d98 +cp bootstrap-icons.svg ../ diff --git a/third_party/catch2/include/catch2/catch.hpp b/third_party/catch2/include/catch2/catch.hpp new file mode 100644 index 0000000000..d2a12427b2 --- /dev/null +++ b/third_party/catch2/include/catch2/catch.hpp @@ -0,0 +1,17970 @@ +/* + * Catch v2.13.9 + * Generated: 2022-04-12 22:37:23.260201 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 9 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html +#ifdef __APPLE__ +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +# endif + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +# if !defined(__clang__) // Handle Clang masquerading for msvc + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL + +// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop` +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) +# endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # include + # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0) + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template